LCOV - code coverage report
Current view: top level - sound/core - pcm_native.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 1808 0.0 %
Date: 2022-03-28 16:04:14 Functions: 0 127 0.0 %
Branches: 0 1109 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  *  Digital Audio (PCM) abstract layer
       4                 :            :  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
       5                 :            :  */
       6                 :            : 
       7                 :            : #include <linux/compat.h>
       8                 :            : #include <linux/mm.h>
       9                 :            : #include <linux/module.h>
      10                 :            : #include <linux/file.h>
      11                 :            : #include <linux/slab.h>
      12                 :            : #include <linux/sched/signal.h>
      13                 :            : #include <linux/time.h>
      14                 :            : #include <linux/pm_qos.h>
      15                 :            : #include <linux/io.h>
      16                 :            : #include <linux/dma-mapping.h>
      17                 :            : #include <linux/vmalloc.h>
      18                 :            : #include <sound/core.h>
      19                 :            : #include <sound/control.h>
      20                 :            : #include <sound/info.h>
      21                 :            : #include <sound/pcm.h>
      22                 :            : #include <sound/pcm_params.h>
      23                 :            : #include <sound/timer.h>
      24                 :            : #include <sound/minors.h>
      25                 :            : #include <linux/uio.h>
      26                 :            : #include <linux/delay.h>
      27                 :            : 
      28                 :            : #include "pcm_local.h"
      29                 :            : 
      30                 :            : #ifdef CONFIG_SND_DEBUG
      31                 :            : #define CREATE_TRACE_POINTS
      32                 :            : #include "pcm_param_trace.h"
      33                 :            : #else
      34                 :            : #define trace_hw_mask_param_enabled()           0
      35                 :            : #define trace_hw_interval_param_enabled()       0
      36                 :            : #define trace_hw_mask_param(substream, type, index, prev, curr)
      37                 :            : #define trace_hw_interval_param(substream, type, index, prev, curr)
      38                 :            : #endif
      39                 :            : 
      40                 :            : /*
      41                 :            :  *  Compatibility
      42                 :            :  */
      43                 :            : 
      44                 :            : struct snd_pcm_hw_params_old {
      45                 :            :         unsigned int flags;
      46                 :            :         unsigned int masks[SNDRV_PCM_HW_PARAM_SUBFORMAT -
      47                 :            :                            SNDRV_PCM_HW_PARAM_ACCESS + 1];
      48                 :            :         struct snd_interval intervals[SNDRV_PCM_HW_PARAM_TICK_TIME -
      49                 :            :                                         SNDRV_PCM_HW_PARAM_SAMPLE_BITS + 1];
      50                 :            :         unsigned int rmask;
      51                 :            :         unsigned int cmask;
      52                 :            :         unsigned int info;
      53                 :            :         unsigned int msbits;
      54                 :            :         unsigned int rate_num;
      55                 :            :         unsigned int rate_den;
      56                 :            :         snd_pcm_uframes_t fifo_size;
      57                 :            :         unsigned char reserved[64];
      58                 :            : };
      59                 :            : 
      60                 :            : #ifdef CONFIG_SND_SUPPORT_OLD_API
      61                 :            : #define SNDRV_PCM_IOCTL_HW_REFINE_OLD _IOWR('A', 0x10, struct snd_pcm_hw_params_old)
      62                 :            : #define SNDRV_PCM_IOCTL_HW_PARAMS_OLD _IOWR('A', 0x11, struct snd_pcm_hw_params_old)
      63                 :            : 
      64                 :            : static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
      65                 :            :                                       struct snd_pcm_hw_params_old __user * _oparams);
      66                 :            : static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
      67                 :            :                                       struct snd_pcm_hw_params_old __user * _oparams);
      68                 :            : #endif
      69                 :            : static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream);
      70                 :            : 
      71                 :            : /*
      72                 :            :  *
      73                 :            :  */
      74                 :            : 
      75                 :            : static DECLARE_RWSEM(snd_pcm_link_rwsem);
      76                 :            : 
      77                 :          0 : void snd_pcm_group_init(struct snd_pcm_group *group)
      78                 :            : {
      79                 :          0 :         spin_lock_init(&group->lock);
      80                 :          0 :         mutex_init(&group->mutex);
      81                 :          0 :         INIT_LIST_HEAD(&group->substreams);
      82                 :          0 :         refcount_set(&group->refs, 1);
      83                 :          0 : }
      84                 :            : 
      85                 :            : /* define group lock helpers */
      86                 :            : #define DEFINE_PCM_GROUP_LOCK(action, mutex_action) \
      87                 :            : static void snd_pcm_group_ ## action(struct snd_pcm_group *group, bool nonatomic) \
      88                 :            : { \
      89                 :            :         if (nonatomic) \
      90                 :            :                 mutex_ ## mutex_action(&group->mutex); \
      91                 :            :         else \
      92                 :            :                 spin_ ## action(&group->lock); \
      93                 :            : }
      94                 :            : 
      95                 :          0 : DEFINE_PCM_GROUP_LOCK(lock, lock);
      96                 :          0 : DEFINE_PCM_GROUP_LOCK(unlock, unlock);
      97                 :          0 : DEFINE_PCM_GROUP_LOCK(lock_irq, lock);
      98                 :          0 : DEFINE_PCM_GROUP_LOCK(unlock_irq, unlock);
      99                 :            : 
     100                 :            : /**
     101                 :            :  * snd_pcm_stream_lock - Lock the PCM stream
     102                 :            :  * @substream: PCM substream
     103                 :            :  *
     104                 :            :  * This locks the PCM stream's spinlock or mutex depending on the nonatomic
     105                 :            :  * flag of the given substream.  This also takes the global link rw lock
     106                 :            :  * (or rw sem), too, for avoiding the race with linked streams.
     107                 :            :  */
     108                 :          0 : void snd_pcm_stream_lock(struct snd_pcm_substream *substream)
     109                 :            : {
     110         [ #  # ]:          0 :         snd_pcm_group_lock(&substream->self_group, substream->pcm->nonatomic);
     111                 :          0 : }
     112                 :            : EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
     113                 :            : 
     114                 :            : /**
     115                 :            :  * snd_pcm_stream_lock - Unlock the PCM stream
     116                 :            :  * @substream: PCM substream
     117                 :            :  *
     118                 :            :  * This unlocks the PCM stream that has been locked via snd_pcm_stream_lock().
     119                 :            :  */
     120                 :          0 : void snd_pcm_stream_unlock(struct snd_pcm_substream *substream)
     121                 :            : {
     122         [ #  # ]:          0 :         snd_pcm_group_unlock(&substream->self_group, substream->pcm->nonatomic);
     123                 :          0 : }
     124                 :            : EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
     125                 :            : 
     126                 :            : /**
     127                 :            :  * snd_pcm_stream_lock_irq - Lock the PCM stream
     128                 :            :  * @substream: PCM substream
     129                 :            :  *
     130                 :            :  * This locks the PCM stream like snd_pcm_stream_lock() and disables the local
     131                 :            :  * IRQ (only when nonatomic is false).  In nonatomic case, this is identical
     132                 :            :  * as snd_pcm_stream_lock().
     133                 :            :  */
     134                 :          0 : void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream)
     135                 :            : {
     136                 :          0 :         snd_pcm_group_lock_irq(&substream->self_group,
     137         [ #  # ]:          0 :                                substream->pcm->nonatomic);
     138                 :          0 : }
     139                 :            : EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
     140                 :            : 
     141                 :            : /**
     142                 :            :  * snd_pcm_stream_unlock_irq - Unlock the PCM stream
     143                 :            :  * @substream: PCM substream
     144                 :            :  *
     145                 :            :  * This is a counter-part of snd_pcm_stream_lock_irq().
     146                 :            :  */
     147                 :          0 : void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream)
     148                 :            : {
     149                 :          0 :         snd_pcm_group_unlock_irq(&substream->self_group,
     150         [ #  # ]:          0 :                                  substream->pcm->nonatomic);
     151                 :          0 : }
     152                 :            : EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq);
     153                 :            : 
     154                 :          0 : unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream)
     155                 :            : {
     156                 :          0 :         unsigned long flags = 0;
     157         [ #  # ]:          0 :         if (substream->pcm->nonatomic)
     158                 :          0 :                 mutex_lock(&substream->self_group.mutex);
     159                 :            :         else
     160                 :          0 :                 spin_lock_irqsave(&substream->self_group.lock, flags);
     161                 :          0 :         return flags;
     162                 :            : }
     163                 :            : EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);
     164                 :            : 
     165                 :            : /**
     166                 :            :  * snd_pcm_stream_unlock_irqrestore - Unlock the PCM stream
     167                 :            :  * @substream: PCM substream
     168                 :            :  * @flags: irq flags
     169                 :            :  *
     170                 :            :  * This is a counter-part of snd_pcm_stream_lock_irqsave().
     171                 :            :  */
     172                 :          0 : void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
     173                 :            :                                       unsigned long flags)
     174                 :            : {
     175         [ #  # ]:          0 :         if (substream->pcm->nonatomic)
     176                 :          0 :                 mutex_unlock(&substream->self_group.mutex);
     177                 :            :         else
     178                 :          0 :                 spin_unlock_irqrestore(&substream->self_group.lock, flags);
     179                 :          0 : }
     180                 :            : EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);
     181                 :            : 
     182                 :            : /* Run PCM ioctl ops */
     183                 :          0 : static int snd_pcm_ops_ioctl(struct snd_pcm_substream *substream,
     184                 :            :                              unsigned cmd, void *arg)
     185                 :            : {
     186         [ #  # ]:          0 :         if (substream->ops->ioctl)
     187                 :          0 :                 return substream->ops->ioctl(substream, cmd, arg);
     188                 :            :         else
     189                 :          0 :                 return snd_pcm_lib_ioctl(substream, cmd, arg);
     190                 :            : }
     191                 :            : 
     192                 :          0 : int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
     193                 :            : {
     194                 :          0 :         struct snd_pcm *pcm = substream->pcm;
     195                 :          0 :         struct snd_pcm_str *pstr = substream->pstr;
     196                 :            : 
     197                 :          0 :         memset(info, 0, sizeof(*info));
     198                 :          0 :         info->card = pcm->card->number;
     199                 :          0 :         info->device = pcm->device;
     200                 :          0 :         info->stream = substream->stream;
     201                 :          0 :         info->subdevice = substream->number;
     202                 :          0 :         strlcpy(info->id, pcm->id, sizeof(info->id));
     203                 :          0 :         strlcpy(info->name, pcm->name, sizeof(info->name));
     204                 :          0 :         info->dev_class = pcm->dev_class;
     205                 :          0 :         info->dev_subclass = pcm->dev_subclass;
     206                 :          0 :         info->subdevices_count = pstr->substream_count;
     207                 :          0 :         info->subdevices_avail = pstr->substream_count - pstr->substream_opened;
     208                 :          0 :         strlcpy(info->subname, substream->name, sizeof(info->subname));
     209                 :            : 
     210                 :          0 :         return 0;
     211                 :            : }
     212                 :            : 
     213                 :          0 : int snd_pcm_info_user(struct snd_pcm_substream *substream,
     214                 :            :                       struct snd_pcm_info __user * _info)
     215                 :            : {
     216                 :          0 :         struct snd_pcm_info *info;
     217                 :          0 :         int err;
     218                 :            : 
     219                 :          0 :         info = kmalloc(sizeof(*info), GFP_KERNEL);
     220         [ #  # ]:          0 :         if (! info)
     221                 :            :                 return -ENOMEM;
     222                 :          0 :         err = snd_pcm_info(substream, info);
     223         [ #  # ]:          0 :         if (err >= 0) {
     224   [ #  #  #  # ]:          0 :                 if (copy_to_user(_info, info, sizeof(*info)))
     225                 :            :                         err = -EFAULT;
     226                 :            :         }
     227                 :          0 :         kfree(info);
     228                 :          0 :         return err;
     229                 :            : }
     230                 :            : 
     231                 :          0 : static bool hw_support_mmap(struct snd_pcm_substream *substream)
     232                 :            : {
     233         [ #  # ]:          0 :         if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP))
     234                 :            :                 return false;
     235                 :            : 
     236         [ #  # ]:          0 :         if (substream->ops->mmap ||
     237         [ #  # ]:          0 :             (substream->dma_buffer.dev.type != SNDRV_DMA_TYPE_DEV &&
     238                 :            :              substream->dma_buffer.dev.type != SNDRV_DMA_TYPE_DEV_UC))
     239                 :            :                 return true;
     240                 :            : 
     241                 :          0 :         return dma_can_mmap(substream->dma_buffer.dev.dev);
     242                 :            : }
     243                 :            : 
     244                 :            : static int constrain_mask_params(struct snd_pcm_substream *substream,
     245                 :            :                                  struct snd_pcm_hw_params *params)
     246                 :            : {
     247                 :            :         struct snd_pcm_hw_constraints *constrs =
     248                 :            :                                         &substream->runtime->hw_constraints;
     249                 :            :         struct snd_mask *m;
     250                 :            :         unsigned int k;
     251                 :            :         struct snd_mask old_mask;
     252                 :            :         int changed;
     253                 :            : 
     254                 :            :         for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) {
     255                 :            :                 m = hw_param_mask(params, k);
     256                 :            :                 if (snd_mask_empty(m))
     257                 :            :                         return -EINVAL;
     258                 :            : 
     259                 :            :                 /* This parameter is not requested to change by a caller. */
     260                 :            :                 if (!(params->rmask & (1 << k)))
     261                 :            :                         continue;
     262                 :            : 
     263                 :            :                 if (trace_hw_mask_param_enabled())
     264                 :            :                         old_mask = *m;
     265                 :            : 
     266                 :            :                 changed = snd_mask_refine(m, constrs_mask(constrs, k));
     267                 :            :                 if (changed < 0)
     268                 :            :                         return changed;
     269                 :            :                 if (changed == 0)
     270                 :            :                         continue;
     271                 :            : 
     272                 :            :                 /* Set corresponding flag so that the caller gets it. */
     273                 :            :                 trace_hw_mask_param(substream, k, 0, &old_mask, m);
     274                 :            :                 params->cmask |= 1 << k;
     275                 :            :         }
     276                 :            : 
     277                 :            :         return 0;
     278                 :            : }
     279                 :            : 
     280                 :            : static int constrain_interval_params(struct snd_pcm_substream *substream,
     281                 :            :                                      struct snd_pcm_hw_params *params)
     282                 :            : {
     283                 :            :         struct snd_pcm_hw_constraints *constrs =
     284                 :            :                                         &substream->runtime->hw_constraints;
     285                 :            :         struct snd_interval *i;
     286                 :            :         unsigned int k;
     287                 :            :         struct snd_interval old_interval;
     288                 :            :         int changed;
     289                 :            : 
     290                 :            :         for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) {
     291                 :            :                 i = hw_param_interval(params, k);
     292                 :            :                 if (snd_interval_empty(i))
     293                 :            :                         return -EINVAL;
     294                 :            : 
     295                 :            :                 /* This parameter is not requested to change by a caller. */
     296                 :            :                 if (!(params->rmask & (1 << k)))
     297                 :            :                         continue;
     298                 :            : 
     299                 :            :                 if (trace_hw_interval_param_enabled())
     300                 :            :                         old_interval = *i;
     301                 :            : 
     302                 :            :                 changed = snd_interval_refine(i, constrs_interval(constrs, k));
     303                 :            :                 if (changed < 0)
     304                 :            :                         return changed;
     305                 :            :                 if (changed == 0)
     306                 :            :                         continue;
     307                 :            : 
     308                 :            :                 /* Set corresponding flag so that the caller gets it. */
     309                 :            :                 trace_hw_interval_param(substream, k, 0, &old_interval, i);
     310                 :            :                 params->cmask |= 1 << k;
     311                 :            :         }
     312                 :            : 
     313                 :            :         return 0;
     314                 :            : }
     315                 :            : 
     316                 :            : static int constrain_params_by_rules(struct snd_pcm_substream *substream,
     317                 :            :                                      struct snd_pcm_hw_params *params)
     318                 :            : {
     319                 :            :         struct snd_pcm_hw_constraints *constrs =
     320                 :            :                                         &substream->runtime->hw_constraints;
     321                 :            :         unsigned int k;
     322                 :            :         unsigned int *rstamps;
     323                 :            :         unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
     324                 :            :         unsigned int stamp;
     325                 :            :         struct snd_pcm_hw_rule *r;
     326                 :            :         unsigned int d;
     327                 :            :         struct snd_mask old_mask;
     328                 :            :         struct snd_interval old_interval;
     329                 :            :         bool again;
     330                 :            :         int changed, err = 0;
     331                 :            : 
     332                 :            :         /*
     333                 :            :          * Each application of rule has own sequence number.
     334                 :            :          *
     335                 :            :          * Each member of 'rstamps' array represents the sequence number of
     336                 :            :          * recent application of corresponding rule.
     337                 :            :          */
     338                 :            :         rstamps = kcalloc(constrs->rules_num, sizeof(unsigned int), GFP_KERNEL);
     339                 :            :         if (!rstamps)
     340                 :            :                 return -ENOMEM;
     341                 :            : 
     342                 :            :         /*
     343                 :            :          * Each member of 'vstamps' array represents the sequence number of
     344                 :            :          * recent application of rule in which corresponding parameters were
     345                 :            :          * changed.
     346                 :            :          *
     347                 :            :          * In initial state, elements corresponding to parameters requested by
     348                 :            :          * a caller is 1. For unrequested parameters, corresponding members
     349                 :            :          * have 0 so that the parameters are never changed anymore.
     350                 :            :          */
     351                 :            :         for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
     352                 :            :                 vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
     353                 :            : 
     354                 :            :         /* Due to the above design, actual sequence number starts at 2. */
     355                 :            :         stamp = 2;
     356                 :            : retry:
     357                 :            :         /* Apply all rules in order. */
     358                 :            :         again = false;
     359                 :            :         for (k = 0; k < constrs->rules_num; k++) {
     360                 :            :                 r = &constrs->rules[k];
     361                 :            : 
     362                 :            :                 /*
     363                 :            :                  * Check condition bits of this rule. When the rule has
     364                 :            :                  * some condition bits, parameter without the bits is
     365                 :            :                  * never processed. SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP
     366                 :            :                  * is an example of the condition bits.
     367                 :            :                  */
     368                 :            :                 if (r->cond && !(r->cond & params->flags))
     369                 :            :                         continue;
     370                 :            : 
     371                 :            :                 /*
     372                 :            :                  * The 'deps' array includes maximum three dependencies
     373                 :            :                  * to SNDRV_PCM_HW_PARAM_XXXs for this rule. The fourth
     374                 :            :                  * member of this array is a sentinel and should be
     375                 :            :                  * negative value.
     376                 :            :                  *
     377                 :            :                  * This rule should be processed in this time when dependent
     378                 :            :                  * parameters were changed at former applications of the other
     379                 :            :                  * rules.
     380                 :            :                  */
     381                 :            :                 for (d = 0; r->deps[d] >= 0; d++) {
     382                 :            :                         if (vstamps[r->deps[d]] > rstamps[k])
     383                 :            :                                 break;
     384                 :            :                 }
     385                 :            :                 if (r->deps[d] < 0)
     386                 :            :                         continue;
     387                 :            : 
     388                 :            :                 if (trace_hw_mask_param_enabled()) {
     389                 :            :                         if (hw_is_mask(r->var))
     390                 :            :                                 old_mask = *hw_param_mask(params, r->var);
     391                 :            :                 }
     392                 :            :                 if (trace_hw_interval_param_enabled()) {
     393                 :            :                         if (hw_is_interval(r->var))
     394                 :            :                                 old_interval = *hw_param_interval(params, r->var);
     395                 :            :                 }
     396                 :            : 
     397                 :            :                 changed = r->func(params, r);
     398                 :            :                 if (changed < 0) {
     399                 :            :                         err = changed;
     400                 :            :                         goto out;
     401                 :            :                 }
     402                 :            : 
     403                 :            :                 /*
     404                 :            :                  * When the parameter is changed, notify it to the caller
     405                 :            :                  * by corresponding returned bit, then preparing for next
     406                 :            :                  * iteration.
     407                 :            :                  */
     408                 :            :                 if (changed && r->var >= 0) {
     409                 :            :                         if (hw_is_mask(r->var)) {
     410                 :            :                                 trace_hw_mask_param(substream, r->var,
     411                 :            :                                         k + 1, &old_mask,
     412                 :            :                                         hw_param_mask(params, r->var));
     413                 :            :                         }
     414                 :            :                         if (hw_is_interval(r->var)) {
     415                 :            :                                 trace_hw_interval_param(substream, r->var,
     416                 :            :                                         k + 1, &old_interval,
     417                 :            :                                         hw_param_interval(params, r->var));
     418                 :            :                         }
     419                 :            : 
     420                 :            :                         params->cmask |= (1 << r->var);
     421                 :            :                         vstamps[r->var] = stamp;
     422                 :            :                         again = true;
     423                 :            :                 }
     424                 :            : 
     425                 :            :                 rstamps[k] = stamp++;
     426                 :            :         }
     427                 :            : 
     428                 :            :         /* Iterate to evaluate all rules till no parameters are changed. */
     429                 :            :         if (again)
     430                 :            :                 goto retry;
     431                 :            : 
     432                 :            :  out:
     433                 :            :         kfree(rstamps);
     434                 :            :         return err;
     435                 :            : }
     436                 :            : 
     437                 :          0 : static int fixup_unreferenced_params(struct snd_pcm_substream *substream,
     438                 :            :                                      struct snd_pcm_hw_params *params)
     439                 :            : {
     440                 :          0 :         const struct snd_interval *i;
     441                 :          0 :         const struct snd_mask *m;
     442                 :          0 :         int err;
     443                 :            : 
     444         [ #  # ]:          0 :         if (!params->msbits) {
     445         [ #  # ]:          0 :                 i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
     446         [ #  # ]:          0 :                 if (snd_interval_single(i))
     447         [ #  # ]:          0 :                         params->msbits = snd_interval_value(i);
     448                 :            :         }
     449                 :            : 
     450         [ #  # ]:          0 :         if (!params->rate_den) {
     451         [ #  # ]:          0 :                 i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
     452         [ #  # ]:          0 :                 if (snd_interval_single(i)) {
     453         [ #  # ]:          0 :                         params->rate_num = snd_interval_value(i);
     454                 :          0 :                         params->rate_den = 1;
     455                 :            :                 }
     456                 :            :         }
     457                 :            : 
     458         [ #  # ]:          0 :         if (!params->fifo_size) {
     459                 :            :                 m = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
     460                 :            :                 i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
     461         [ #  # ]:          0 :                 if (snd_mask_single(m) && snd_interval_single(i)) {
     462                 :          0 :                         err = snd_pcm_ops_ioctl(substream,
     463                 :            :                                                 SNDRV_PCM_IOCTL1_FIFO_SIZE,
     464                 :            :                                                 params);
     465         [ #  # ]:          0 :                         if (err < 0)
     466                 :            :                                 return err;
     467                 :            :                 }
     468                 :            :         }
     469                 :            : 
     470         [ #  # ]:          0 :         if (!params->info) {
     471                 :          0 :                 params->info = substream->runtime->hw.info;
     472                 :          0 :                 params->info &= ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES |
     473                 :            :                                   SNDRV_PCM_INFO_DRAIN_TRIGGER);
     474         [ #  # ]:          0 :                 if (!hw_support_mmap(substream))
     475                 :          0 :                         params->info &= ~(SNDRV_PCM_INFO_MMAP |
     476                 :            :                                           SNDRV_PCM_INFO_MMAP_VALID);
     477                 :            :         }
     478                 :            : 
     479                 :            :         return 0;
     480                 :            : }
     481                 :            : 
     482                 :          0 : int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
     483                 :            :                       struct snd_pcm_hw_params *params)
     484                 :            : {
     485                 :          0 :         int err;
     486                 :            : 
     487                 :          0 :         params->info = 0;
     488                 :          0 :         params->fifo_size = 0;
     489         [ #  # ]:          0 :         if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS))
     490                 :          0 :                 params->msbits = 0;
     491         [ #  # ]:          0 :         if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) {
     492                 :          0 :                 params->rate_num = 0;
     493                 :          0 :                 params->rate_den = 0;
     494                 :            :         }
     495                 :            : 
     496                 :          0 :         err = constrain_mask_params(substream, params);
     497         [ #  # ]:          0 :         if (err < 0)
     498                 :            :                 return err;
     499                 :            : 
     500                 :          0 :         err = constrain_interval_params(substream, params);
     501         [ #  # ]:          0 :         if (err < 0)
     502                 :            :                 return err;
     503                 :            : 
     504                 :          0 :         err = constrain_params_by_rules(substream, params);
     505         [ #  # ]:          0 :         if (err < 0)
     506                 :            :                 return err;
     507                 :            : 
     508                 :          0 :         params->rmask = 0;
     509                 :            : 
     510                 :          0 :         return 0;
     511                 :            : }
     512                 :            : EXPORT_SYMBOL(snd_pcm_hw_refine);
     513                 :            : 
     514                 :          0 : static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
     515                 :            :                                   struct snd_pcm_hw_params __user * _params)
     516                 :            : {
     517                 :          0 :         struct snd_pcm_hw_params *params;
     518                 :          0 :         int err;
     519                 :            : 
     520                 :          0 :         params = memdup_user(_params, sizeof(*params));
     521         [ #  # ]:          0 :         if (IS_ERR(params))
     522                 :          0 :                 return PTR_ERR(params);
     523                 :            : 
     524                 :          0 :         err = snd_pcm_hw_refine(substream, params);
     525         [ #  # ]:          0 :         if (err < 0)
     526                 :          0 :                 goto end;
     527                 :            : 
     528                 :          0 :         err = fixup_unreferenced_params(substream, params);
     529         [ #  # ]:          0 :         if (err < 0)
     530                 :          0 :                 goto end;
     531                 :            : 
     532   [ #  #  #  # ]:          0 :         if (copy_to_user(_params, params, sizeof(*params)))
     533                 :            :                 err = -EFAULT;
     534                 :          0 : end:
     535                 :          0 :         kfree(params);
     536                 :          0 :         return err;
     537                 :            : }
     538                 :            : 
     539                 :          0 : static int period_to_usecs(struct snd_pcm_runtime *runtime)
     540                 :            : {
     541                 :          0 :         int usecs;
     542                 :            : 
     543                 :          0 :         if (! runtime->rate)
     544                 :            :                 return -1; /* invalid */
     545                 :            : 
     546                 :            :         /* take 75% of period time as the deadline */
     547                 :          0 :         usecs = (750000 / runtime->rate) * runtime->period_size;
     548                 :          0 :         usecs += ((750000 % runtime->rate) * runtime->period_size) /
     549                 :          0 :                 runtime->rate;
     550                 :            : 
     551                 :          0 :         return usecs;
     552                 :            : }
     553                 :            : 
     554                 :          0 : static void snd_pcm_set_state(struct snd_pcm_substream *substream,
     555                 :            :                               snd_pcm_state_t state)
     556                 :            : {
     557                 :          0 :         snd_pcm_stream_lock_irq(substream);
     558         [ #  # ]:          0 :         if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED)
     559                 :          0 :                 substream->runtime->status->state = state;
     560         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
     561                 :          0 : }
     562                 :            : 
     563                 :          0 : static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream,
     564                 :            :                                         int event)
     565                 :            : {
     566                 :            : #ifdef CONFIG_SND_PCM_TIMER
     567                 :          0 :         if (substream->timer)
     568                 :          0 :                 snd_timer_notify(substream->timer, event,
     569                 :            :                                         &substream->runtime->trigger_tstamp);
     570                 :            : #endif
     571                 :            : }
     572                 :            : 
     573                 :          0 : static void snd_pcm_sync_stop(struct snd_pcm_substream *substream)
     574                 :            : {
     575         [ #  # ]:          0 :         if (substream->runtime->stop_operating) {
     576                 :          0 :                 substream->runtime->stop_operating = false;
     577         [ #  # ]:          0 :                 if (substream->ops->sync_stop)
     578                 :          0 :                         substream->ops->sync_stop(substream);
     579         [ #  # ]:          0 :                 else if (substream->pcm->card->sync_irq > 0)
     580                 :          0 :                         synchronize_irq(substream->pcm->card->sync_irq);
     581                 :            :         }
     582                 :          0 : }
     583                 :            : 
     584                 :            : /**
     585                 :            :  * snd_pcm_hw_param_choose - choose a configuration defined by @params
     586                 :            :  * @pcm: PCM instance
     587                 :            :  * @params: the hw_params instance
     588                 :            :  *
     589                 :            :  * Choose one configuration from configuration space defined by @params.
     590                 :            :  * The configuration chosen is that obtained fixing in this order:
     591                 :            :  * first access, first format, first subformat, min channels,
     592                 :            :  * min rate, min period time, max buffer size, min tick time
     593                 :            :  *
     594                 :            :  * Return: Zero if successful, or a negative error code on failure.
     595                 :            :  */
     596                 :          0 : static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
     597                 :            :                                     struct snd_pcm_hw_params *params)
     598                 :            : {
     599                 :          0 :         static const int vars[] = {
     600                 :            :                 SNDRV_PCM_HW_PARAM_ACCESS,
     601                 :            :                 SNDRV_PCM_HW_PARAM_FORMAT,
     602                 :            :                 SNDRV_PCM_HW_PARAM_SUBFORMAT,
     603                 :            :                 SNDRV_PCM_HW_PARAM_CHANNELS,
     604                 :            :                 SNDRV_PCM_HW_PARAM_RATE,
     605                 :            :                 SNDRV_PCM_HW_PARAM_PERIOD_TIME,
     606                 :            :                 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
     607                 :            :                 SNDRV_PCM_HW_PARAM_TICK_TIME,
     608                 :            :                 -1
     609                 :            :         };
     610                 :          0 :         const int *v;
     611                 :          0 :         struct snd_mask old_mask;
     612                 :          0 :         struct snd_interval old_interval;
     613                 :          0 :         int changed;
     614                 :            : 
     615         [ #  # ]:          0 :         for (v = vars; *v != -1; v++) {
     616                 :            :                 /* Keep old parameter to trace. */
     617                 :          0 :                 if (trace_hw_mask_param_enabled()) {
     618                 :            :                         if (hw_is_mask(*v))
     619                 :            :                                 old_mask = *hw_param_mask(params, *v);
     620                 :            :                 }
     621                 :          0 :                 if (trace_hw_interval_param_enabled()) {
     622                 :            :                         if (hw_is_interval(*v))
     623                 :            :                                 old_interval = *hw_param_interval(params, *v);
     624                 :            :                 }
     625         [ #  # ]:          0 :                 if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE)
     626                 :          0 :                         changed = snd_pcm_hw_param_first(pcm, params, *v, NULL);
     627                 :            :                 else
     628                 :          0 :                         changed = snd_pcm_hw_param_last(pcm, params, *v, NULL);
     629         [ #  # ]:          0 :                 if (changed < 0)
     630                 :          0 :                         return changed;
     631                 :          0 :                 if (changed == 0)
     632                 :            :                         continue;
     633                 :            : 
     634                 :            :                 /* Trace the changed parameter. */
     635                 :          0 :                 if (hw_is_mask(*v)) {
     636                 :            :                         trace_hw_mask_param(pcm, *v, 0, &old_mask,
     637                 :          0 :                                             hw_param_mask(params, *v));
     638                 :            :                 }
     639                 :          0 :                 if (hw_is_interval(*v)) {
     640                 :            :                         trace_hw_interval_param(pcm, *v, 0, &old_interval,
     641                 :          0 :                                                 hw_param_interval(params, *v));
     642                 :            :                 }
     643                 :            :         }
     644                 :            : 
     645                 :            :         return 0;
     646                 :            : }
     647                 :            : 
     648                 :          0 : static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
     649                 :            :                              struct snd_pcm_hw_params *params)
     650                 :            : {
     651                 :          0 :         struct snd_pcm_runtime *runtime;
     652                 :          0 :         int err, usecs;
     653                 :          0 :         unsigned int bits;
     654                 :          0 :         snd_pcm_uframes_t frames;
     655                 :            : 
     656   [ #  #  #  #  :          0 :         if (PCM_RUNTIME_CHECK(substream))
                   #  # ]
     657                 :            :                 return -ENXIO;
     658                 :          0 :         runtime = substream->runtime;
     659                 :          0 :         snd_pcm_stream_lock_irq(substream);
     660         [ #  # ]:          0 :         switch (runtime->status->state) {
     661                 :            :         case SNDRV_PCM_STATE_OPEN:
     662                 :            :         case SNDRV_PCM_STATE_SETUP:
     663                 :            :         case SNDRV_PCM_STATE_PREPARED:
     664                 :          0 :                 break;
     665                 :            :         default:
     666         [ #  # ]:          0 :                 snd_pcm_stream_unlock_irq(substream);
     667                 :            :                 return -EBADFD;
     668                 :            :         }
     669         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
     670                 :            : #if IS_ENABLED(CONFIG_SND_PCM_OSS)
     671                 :            :         if (!substream->oss.oss)
     672                 :            : #endif
     673         [ #  # ]:          0 :                 if (atomic_read(&substream->mmap_count))
     674                 :            :                         return -EBADFD;
     675                 :            : 
     676                 :          0 :         snd_pcm_sync_stop(substream);
     677                 :            : 
     678                 :          0 :         params->rmask = ~0U;
     679                 :          0 :         err = snd_pcm_hw_refine(substream, params);
     680         [ #  # ]:          0 :         if (err < 0)
     681                 :          0 :                 goto _error;
     682                 :            : 
     683                 :          0 :         err = snd_pcm_hw_params_choose(substream, params);
     684         [ #  # ]:          0 :         if (err < 0)
     685                 :          0 :                 goto _error;
     686                 :            : 
     687                 :          0 :         err = fixup_unreferenced_params(substream, params);
     688         [ #  # ]:          0 :         if (err < 0)
     689                 :          0 :                 goto _error;
     690                 :            : 
     691         [ #  # ]:          0 :         if (substream->managed_buffer_alloc) {
     692                 :          0 :                 err = snd_pcm_lib_malloc_pages(substream,
     693                 :            :                                                params_buffer_bytes(params));
     694         [ #  # ]:          0 :                 if (err < 0)
     695                 :          0 :                         goto _error;
     696                 :          0 :                 runtime->buffer_changed = err > 0;
     697                 :            :         }
     698                 :            : 
     699         [ #  # ]:          0 :         if (substream->ops->hw_params != NULL) {
     700                 :          0 :                 err = substream->ops->hw_params(substream, params);
     701         [ #  # ]:          0 :                 if (err < 0)
     702                 :          0 :                         goto _error;
     703                 :            :         }
     704                 :            : 
     705                 :          0 :         runtime->access = params_access(params);
     706                 :          0 :         runtime->format = params_format(params);
     707                 :          0 :         runtime->subformat = params_subformat(params);
     708         [ #  # ]:          0 :         runtime->channels = params_channels(params);
     709         [ #  # ]:          0 :         runtime->rate = params_rate(params);
     710         [ #  # ]:          0 :         runtime->period_size = params_period_size(params);
     711         [ #  # ]:          0 :         runtime->periods = params_periods(params);
     712         [ #  # ]:          0 :         runtime->buffer_size = params_buffer_size(params);
     713                 :          0 :         runtime->info = params->info;
     714                 :          0 :         runtime->rate_num = params->rate_num;
     715                 :          0 :         runtime->rate_den = params->rate_den;
     716                 :          0 :         runtime->no_period_wakeup =
     717         [ #  # ]:          0 :                         (params->info & SNDRV_PCM_INFO_NO_PERIOD_WAKEUP) &&
     718         [ #  # ]:          0 :                         (params->flags & SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP);
     719                 :            : 
     720                 :          0 :         bits = snd_pcm_format_physical_width(runtime->format);
     721                 :          0 :         runtime->sample_bits = bits;
     722                 :          0 :         bits *= runtime->channels;
     723                 :          0 :         runtime->frame_bits = bits;
     724                 :          0 :         frames = 1;
     725         [ #  # ]:          0 :         while (bits % 8 != 0) {
     726                 :          0 :                 bits *= 2;
     727                 :          0 :                 frames *= 2;
     728                 :            :         }
     729                 :          0 :         runtime->byte_align = bits / 8;
     730                 :          0 :         runtime->min_align = frames;
     731                 :            : 
     732                 :            :         /* Default sw params */
     733                 :          0 :         runtime->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
     734                 :          0 :         runtime->period_step = 1;
     735                 :          0 :         runtime->control->avail_min = runtime->period_size;
     736                 :          0 :         runtime->start_threshold = 1;
     737                 :          0 :         runtime->stop_threshold = runtime->buffer_size;
     738                 :          0 :         runtime->silence_threshold = 0;
     739                 :          0 :         runtime->silence_size = 0;
     740                 :          0 :         runtime->boundary = runtime->buffer_size;
     741         [ #  # ]:          0 :         while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size)
     742                 :          0 :                 runtime->boundary *= 2;
     743                 :            : 
     744                 :            :         /* clear the buffer for avoiding possible kernel info leaks */
     745   [ #  #  #  # ]:          0 :         if (runtime->dma_area && !substream->ops->copy_user)
     746                 :          0 :                 memset(runtime->dma_area, 0, runtime->dma_bytes);
     747                 :            : 
     748                 :          0 :         snd_pcm_timer_resolution_change(substream);
     749                 :          0 :         snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);
     750                 :            : 
     751         [ #  # ]:          0 :         if (pm_qos_request_active(&substream->latency_pm_qos_req))
     752                 :          0 :                 pm_qos_remove_request(&substream->latency_pm_qos_req);
     753   [ #  #  #  # ]:          0 :         if ((usecs = period_to_usecs(runtime)) >= 0)
     754                 :          0 :                 pm_qos_add_request(&substream->latency_pm_qos_req,
     755                 :            :                                    PM_QOS_CPU_DMA_LATENCY, usecs);
     756                 :            :         return 0;
     757                 :          0 :  _error:
     758                 :            :         /* hardware might be unusable from this time,
     759                 :            :            so we force application to retry to set
     760                 :            :            the correct hardware parameter settings */
     761                 :          0 :         snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
     762         [ #  # ]:          0 :         if (substream->ops->hw_free != NULL)
     763                 :          0 :                 substream->ops->hw_free(substream);
     764         [ #  # ]:          0 :         if (substream->managed_buffer_alloc)
     765                 :          0 :                 snd_pcm_lib_free_pages(substream);
     766                 :            :         return err;
     767                 :            : }
     768                 :            : 
     769                 :          0 : static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
     770                 :            :                                   struct snd_pcm_hw_params __user * _params)
     771                 :            : {
     772                 :          0 :         struct snd_pcm_hw_params *params;
     773                 :          0 :         int err;
     774                 :            : 
     775                 :          0 :         params = memdup_user(_params, sizeof(*params));
     776         [ #  # ]:          0 :         if (IS_ERR(params))
     777                 :          0 :                 return PTR_ERR(params);
     778                 :            : 
     779                 :          0 :         err = snd_pcm_hw_params(substream, params);
     780         [ #  # ]:          0 :         if (err < 0)
     781                 :          0 :                 goto end;
     782                 :            : 
     783   [ #  #  #  # ]:          0 :         if (copy_to_user(_params, params, sizeof(*params)))
     784                 :            :                 err = -EFAULT;
     785                 :          0 : end:
     786                 :          0 :         kfree(params);
     787                 :          0 :         return err;
     788                 :            : }
     789                 :            : 
     790                 :          0 : static int do_hw_free(struct snd_pcm_substream *substream)
     791                 :            : {
     792                 :          0 :         int result = 0;
     793                 :            : 
     794                 :          0 :         snd_pcm_sync_stop(substream);
     795         [ #  # ]:          0 :         if (substream->ops->hw_free)
     796                 :          0 :                 result = substream->ops->hw_free(substream);
     797         [ #  # ]:          0 :         if (substream->managed_buffer_alloc)
     798                 :          0 :                 snd_pcm_lib_free_pages(substream);
     799                 :          0 :         return result;
     800                 :            : }
     801                 :            : 
     802                 :          0 : static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
     803                 :            : {
     804                 :          0 :         struct snd_pcm_runtime *runtime;
     805                 :          0 :         int result;
     806                 :            : 
     807   [ #  #  #  #  :          0 :         if (PCM_RUNTIME_CHECK(substream))
                   #  # ]
     808                 :            :                 return -ENXIO;
     809                 :          0 :         runtime = substream->runtime;
     810                 :          0 :         snd_pcm_stream_lock_irq(substream);
     811         [ #  # ]:          0 :         switch (runtime->status->state) {
     812                 :            :         case SNDRV_PCM_STATE_SETUP:
     813                 :            :         case SNDRV_PCM_STATE_PREPARED:
     814                 :          0 :                 break;
     815                 :            :         default:
     816         [ #  # ]:          0 :                 snd_pcm_stream_unlock_irq(substream);
     817                 :            :                 return -EBADFD;
     818                 :            :         }
     819         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
     820         [ #  # ]:          0 :         if (atomic_read(&substream->mmap_count))
     821                 :            :                 return -EBADFD;
     822                 :          0 :         result = do_hw_free(substream);
     823                 :          0 :         snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
     824                 :          0 :         pm_qos_remove_request(&substream->latency_pm_qos_req);
     825                 :          0 :         return result;
     826                 :            : }
     827                 :            : 
     828                 :          0 : static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
     829                 :            :                              struct snd_pcm_sw_params *params)
     830                 :            : {
     831                 :          0 :         struct snd_pcm_runtime *runtime;
     832                 :          0 :         int err;
     833                 :            : 
     834   [ #  #  #  #  :          0 :         if (PCM_RUNTIME_CHECK(substream))
                   #  # ]
     835                 :            :                 return -ENXIO;
     836                 :          0 :         runtime = substream->runtime;
     837                 :          0 :         snd_pcm_stream_lock_irq(substream);
     838         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
     839         [ #  # ]:          0 :                 snd_pcm_stream_unlock_irq(substream);
     840                 :          0 :                 return -EBADFD;
     841                 :            :         }
     842         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
     843                 :            : 
     844         [ #  # ]:          0 :         if (params->tstamp_mode < 0 ||
     845                 :            :             params->tstamp_mode > SNDRV_PCM_TSTAMP_LAST)
     846                 :            :                 return -EINVAL;
     847         [ #  # ]:          0 :         if (params->proto >= SNDRV_PROTOCOL_VERSION(2, 0, 12) &&
     848         [ #  # ]:          0 :             params->tstamp_type > SNDRV_PCM_TSTAMP_TYPE_LAST)
     849                 :            :                 return -EINVAL;
     850         [ #  # ]:          0 :         if (params->avail_min == 0)
     851                 :            :                 return -EINVAL;
     852         [ #  # ]:          0 :         if (params->silence_size >= runtime->boundary) {
     853         [ #  # ]:          0 :                 if (params->silence_threshold != 0)
     854                 :            :                         return -EINVAL;
     855                 :            :         } else {
     856         [ #  # ]:          0 :                 if (params->silence_size > params->silence_threshold)
     857                 :            :                         return -EINVAL;
     858         [ #  # ]:          0 :                 if (params->silence_threshold > runtime->buffer_size)
     859                 :            :                         return -EINVAL;
     860                 :            :         }
     861                 :          0 :         err = 0;
     862                 :          0 :         snd_pcm_stream_lock_irq(substream);
     863                 :          0 :         runtime->tstamp_mode = params->tstamp_mode;
     864         [ #  # ]:          0 :         if (params->proto >= SNDRV_PROTOCOL_VERSION(2, 0, 12))
     865                 :          0 :                 runtime->tstamp_type = params->tstamp_type;
     866                 :          0 :         runtime->period_step = params->period_step;
     867                 :          0 :         runtime->control->avail_min = params->avail_min;
     868                 :          0 :         runtime->start_threshold = params->start_threshold;
     869                 :          0 :         runtime->stop_threshold = params->stop_threshold;
     870                 :          0 :         runtime->silence_threshold = params->silence_threshold;
     871                 :          0 :         runtime->silence_size = params->silence_size;
     872                 :          0 :         params->boundary = runtime->boundary;
     873         [ #  # ]:          0 :         if (snd_pcm_running(substream)) {
     874         [ #  # ]:          0 :                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
     875         [ #  # ]:          0 :                     runtime->silence_size > 0)
     876                 :          0 :                         snd_pcm_playback_silence(substream, ULONG_MAX);
     877                 :          0 :                 err = snd_pcm_update_state(substream, runtime);
     878                 :            :         }
     879         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
     880                 :            :         return err;
     881                 :            : }
     882                 :            : 
     883                 :          0 : static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream,
     884                 :            :                                   struct snd_pcm_sw_params __user * _params)
     885                 :            : {
     886                 :          0 :         struct snd_pcm_sw_params params;
     887                 :          0 :         int err;
     888         [ #  # ]:          0 :         if (copy_from_user(&params, _params, sizeof(params)))
     889                 :            :                 return -EFAULT;
     890                 :          0 :         err = snd_pcm_sw_params(substream, &params);
     891         [ #  # ]:          0 :         if (copy_to_user(_params, &params, sizeof(params)))
     892                 :          0 :                 return -EFAULT;
     893                 :            :         return err;
     894                 :            : }
     895                 :            : 
     896                 :            : static inline snd_pcm_uframes_t
     897                 :            : snd_pcm_calc_delay(struct snd_pcm_substream *substream)
     898                 :            : {
     899                 :            :         snd_pcm_uframes_t delay;
     900                 :            : 
     901                 :            :         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
     902                 :            :                 delay = snd_pcm_playback_hw_avail(substream->runtime);
     903                 :            :         else
     904                 :            :                 delay = snd_pcm_capture_avail(substream->runtime);
     905                 :            :         return delay + substream->runtime->delay;
     906                 :            : }
     907                 :            : 
     908                 :          0 : int snd_pcm_status64(struct snd_pcm_substream *substream,
     909                 :            :                      struct snd_pcm_status64 *status)
     910                 :            : {
     911                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
     912                 :            : 
     913                 :          0 :         snd_pcm_stream_lock_irq(substream);
     914                 :            : 
     915         [ #  # ]:          0 :         snd_pcm_unpack_audio_tstamp_config(status->audio_tstamp_data,
     916                 :            :                                         &runtime->audio_tstamp_config);
     917                 :            : 
     918                 :            :         /* backwards compatible behavior */
     919         [ #  # ]:          0 :         if (runtime->audio_tstamp_config.type_requested ==
     920                 :            :                 SNDRV_PCM_AUDIO_TSTAMP_TYPE_COMPAT) {
     921         [ #  # ]:          0 :                 if (runtime->hw.info & SNDRV_PCM_INFO_HAS_WALL_CLOCK)
     922                 :          0 :                         runtime->audio_tstamp_config.type_requested =
     923                 :            :                                 SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK;
     924                 :            :                 else
     925                 :          0 :                         runtime->audio_tstamp_config.type_requested =
     926                 :            :                                 SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT;
     927                 :          0 :                 runtime->audio_tstamp_report.valid = 0;
     928                 :            :         } else
     929                 :          0 :                 runtime->audio_tstamp_report.valid = 1;
     930                 :            : 
     931                 :          0 :         status->state = runtime->status->state;
     932                 :          0 :         status->suspended_state = runtime->status->suspended_state;
     933         [ #  # ]:          0 :         if (status->state == SNDRV_PCM_STATE_OPEN)
     934                 :          0 :                 goto _end;
     935                 :          0 :         status->trigger_tstamp_sec = runtime->trigger_tstamp.tv_sec;
     936                 :          0 :         status->trigger_tstamp_nsec = runtime->trigger_tstamp.tv_nsec;
     937         [ #  # ]:          0 :         if (snd_pcm_running(substream)) {
     938                 :          0 :                 snd_pcm_update_hw_ptr(substream);
     939         [ #  # ]:          0 :                 if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
     940                 :          0 :                         status->tstamp_sec = runtime->status->tstamp.tv_sec;
     941                 :          0 :                         status->tstamp_nsec =
     942                 :          0 :                                 runtime->status->tstamp.tv_nsec;
     943                 :          0 :                         status->driver_tstamp_sec =
     944                 :          0 :                                 runtime->driver_tstamp.tv_sec;
     945                 :          0 :                         status->driver_tstamp_nsec =
     946                 :          0 :                                 runtime->driver_tstamp.tv_nsec;
     947                 :          0 :                         status->audio_tstamp_sec =
     948                 :          0 :                                 runtime->status->audio_tstamp.tv_sec;
     949                 :          0 :                         status->audio_tstamp_nsec =
     950                 :          0 :                                 runtime->status->audio_tstamp.tv_nsec;
     951         [ #  # ]:          0 :                         if (runtime->audio_tstamp_report.valid == 1)
     952                 :            :                                 /* backwards compatibility, no report provided in COMPAT mode */
     953                 :          0 :                                 snd_pcm_pack_audio_tstamp_report(&status->audio_tstamp_data,
     954                 :            :                                                                 &status->audio_tstamp_accuracy,
     955                 :            :                                                                 &runtime->audio_tstamp_report);
     956                 :            : 
     957                 :          0 :                         goto _tstamp_end;
     958                 :            :                 }
     959                 :            :         } else {
     960                 :            :                 /* get tstamp only in fallback mode and only if enabled */
     961         [ #  # ]:          0 :                 if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
     962                 :          0 :                         struct timespec64 tstamp;
     963                 :            : 
     964                 :          0 :                         snd_pcm_gettime(runtime, &tstamp);
     965                 :          0 :                         status->tstamp_sec = tstamp.tv_sec;
     966                 :          0 :                         status->tstamp_nsec = tstamp.tv_nsec;
     967                 :            :                 }
     968                 :            :         }
     969                 :          0 :  _tstamp_end:
     970                 :          0 :         status->appl_ptr = runtime->control->appl_ptr;
     971                 :          0 :         status->hw_ptr = runtime->status->hw_ptr;
     972                 :          0 :         status->avail = snd_pcm_avail(substream);
     973         [ #  # ]:          0 :         status->delay = snd_pcm_running(substream) ?
     974                 :          0 :                 snd_pcm_calc_delay(substream) : 0;
     975                 :          0 :         status->avail_max = runtime->avail_max;
     976                 :          0 :         status->overrange = runtime->overrange;
     977                 :          0 :         runtime->avail_max = 0;
     978                 :          0 :         runtime->overrange = 0;
     979                 :          0 :  _end:
     980         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
     981                 :          0 :         return 0;
     982                 :            : }
     983                 :            : 
     984                 :          0 : static int snd_pcm_status_user64(struct snd_pcm_substream *substream,
     985                 :            :                                  struct snd_pcm_status64 __user * _status,
     986                 :            :                                  bool ext)
     987                 :            : {
     988                 :          0 :         struct snd_pcm_status64 status;
     989                 :          0 :         int res;
     990                 :            : 
     991                 :          0 :         memset(&status, 0, sizeof(status));
     992                 :            :         /*
     993                 :            :          * with extension, parameters are read/write,
     994                 :            :          * get audio_tstamp_data from user,
     995                 :            :          * ignore rest of status structure
     996                 :            :          */
     997   [ #  #  #  # ]:          0 :         if (ext && get_user(status.audio_tstamp_data,
     998                 :            :                                 (u32 __user *)(&_status->audio_tstamp_data)))
     999                 :            :                 return -EFAULT;
    1000                 :          0 :         res = snd_pcm_status64(substream, &status);
    1001         [ #  # ]:          0 :         if (res < 0)
    1002                 :            :                 return res;
    1003         [ #  # ]:          0 :         if (copy_to_user(_status, &status, sizeof(status)))
    1004                 :          0 :                 return -EFAULT;
    1005                 :            :         return 0;
    1006                 :            : }
    1007                 :            : 
    1008                 :          0 : static int snd_pcm_status_user32(struct snd_pcm_substream *substream,
    1009                 :            :                                  struct snd_pcm_status32 __user * _status,
    1010                 :            :                                  bool ext)
    1011                 :            : {
    1012                 :          0 :         struct snd_pcm_status64 status64;
    1013                 :          0 :         struct snd_pcm_status32 status32;
    1014                 :          0 :         int res;
    1015                 :            : 
    1016                 :          0 :         memset(&status64, 0, sizeof(status64));
    1017                 :          0 :         memset(&status32, 0, sizeof(status32));
    1018                 :            :         /*
    1019                 :            :          * with extension, parameters are read/write,
    1020                 :            :          * get audio_tstamp_data from user,
    1021                 :            :          * ignore rest of status structure
    1022                 :            :          */
    1023   [ #  #  #  # ]:          0 :         if (ext && get_user(status64.audio_tstamp_data,
    1024                 :            :                             (u32 __user *)(&_status->audio_tstamp_data)))
    1025                 :            :                 return -EFAULT;
    1026                 :          0 :         res = snd_pcm_status64(substream, &status64);
    1027         [ #  # ]:          0 :         if (res < 0)
    1028                 :            :                 return res;
    1029                 :            : 
    1030                 :          0 :         status32 = (struct snd_pcm_status32) {
    1031                 :          0 :                 .state = status64.state,
    1032                 :          0 :                 .trigger_tstamp_sec = status64.trigger_tstamp_sec,
    1033                 :          0 :                 .trigger_tstamp_nsec = status64.trigger_tstamp_nsec,
    1034                 :          0 :                 .tstamp_sec = status64.tstamp_sec,
    1035                 :          0 :                 .tstamp_nsec = status64.tstamp_nsec,
    1036                 :          0 :                 .appl_ptr = status64.appl_ptr,
    1037                 :          0 :                 .hw_ptr = status64.hw_ptr,
    1038                 :          0 :                 .delay = status64.delay,
    1039                 :          0 :                 .avail = status64.avail,
    1040                 :          0 :                 .avail_max = status64.avail_max,
    1041                 :          0 :                 .overrange = status64.overrange,
    1042                 :          0 :                 .suspended_state = status64.suspended_state,
    1043                 :          0 :                 .audio_tstamp_data = status64.audio_tstamp_data,
    1044                 :          0 :                 .audio_tstamp_sec = status64.audio_tstamp_sec,
    1045                 :          0 :                 .audio_tstamp_nsec = status64.audio_tstamp_nsec,
    1046                 :            :                 .driver_tstamp_sec = status64.audio_tstamp_sec,
    1047                 :            :                 .driver_tstamp_nsec = status64.audio_tstamp_nsec,
    1048                 :          0 :                 .audio_tstamp_accuracy = status64.audio_tstamp_accuracy,
    1049                 :            :         };
    1050                 :            : 
    1051         [ #  # ]:          0 :         if (copy_to_user(_status, &status32, sizeof(status32)))
    1052                 :          0 :                 return -EFAULT;
    1053                 :            : 
    1054                 :            :         return 0;
    1055                 :            : }
    1056                 :            : 
    1057                 :          0 : static int snd_pcm_channel_info(struct snd_pcm_substream *substream,
    1058                 :            :                                 struct snd_pcm_channel_info * info)
    1059                 :            : {
    1060                 :          0 :         struct snd_pcm_runtime *runtime;
    1061                 :          0 :         unsigned int channel;
    1062                 :            :         
    1063                 :          0 :         channel = info->channel;
    1064                 :          0 :         runtime = substream->runtime;
    1065                 :          0 :         snd_pcm_stream_lock_irq(substream);
    1066         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
    1067         [ #  # ]:          0 :                 snd_pcm_stream_unlock_irq(substream);
    1068                 :          0 :                 return -EBADFD;
    1069                 :            :         }
    1070         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
    1071         [ #  # ]:          0 :         if (channel >= runtime->channels)
    1072                 :            :                 return -EINVAL;
    1073                 :          0 :         memset(info, 0, sizeof(*info));
    1074                 :          0 :         info->channel = channel;
    1075                 :          0 :         return snd_pcm_ops_ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, info);
    1076                 :            : }
    1077                 :            : 
    1078                 :          0 : static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream,
    1079                 :            :                                      struct snd_pcm_channel_info __user * _info)
    1080                 :            : {
    1081                 :          0 :         struct snd_pcm_channel_info info;
    1082                 :          0 :         int res;
    1083                 :            :         
    1084         [ #  # ]:          0 :         if (copy_from_user(&info, _info, sizeof(info)))
    1085                 :            :                 return -EFAULT;
    1086                 :          0 :         res = snd_pcm_channel_info(substream, &info);
    1087         [ #  # ]:          0 :         if (res < 0)
    1088                 :            :                 return res;
    1089         [ #  # ]:          0 :         if (copy_to_user(_info, &info, sizeof(info)))
    1090                 :          0 :                 return -EFAULT;
    1091                 :            :         return 0;
    1092                 :            : }
    1093                 :            : 
    1094                 :          0 : static void snd_pcm_trigger_tstamp(struct snd_pcm_substream *substream)
    1095                 :            : {
    1096                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1097         [ #  # ]:          0 :         if (runtime->trigger_master == NULL)
    1098                 :            :                 return;
    1099         [ #  # ]:          0 :         if (runtime->trigger_master == substream) {
    1100         [ #  # ]:          0 :                 if (!runtime->trigger_tstamp_latched)
    1101                 :          0 :                         snd_pcm_gettime(runtime, &runtime->trigger_tstamp);
    1102                 :            :         } else {
    1103                 :          0 :                 snd_pcm_trigger_tstamp(runtime->trigger_master);
    1104                 :          0 :                 runtime->trigger_tstamp = runtime->trigger_master->runtime->trigger_tstamp;
    1105                 :            :         }
    1106                 :          0 :         runtime->trigger_master = NULL;
    1107                 :            : }
    1108                 :            : 
    1109                 :            : #define ACTION_ARG_IGNORE       (__force snd_pcm_state_t)0
    1110                 :            : 
    1111                 :            : struct action_ops {
    1112                 :            :         int (*pre_action)(struct snd_pcm_substream *substream,
    1113                 :            :                           snd_pcm_state_t state);
    1114                 :            :         int (*do_action)(struct snd_pcm_substream *substream,
    1115                 :            :                          snd_pcm_state_t state);
    1116                 :            :         void (*undo_action)(struct snd_pcm_substream *substream,
    1117                 :            :                             snd_pcm_state_t state);
    1118                 :            :         void (*post_action)(struct snd_pcm_substream *substream,
    1119                 :            :                             snd_pcm_state_t state);
    1120                 :            : };
    1121                 :            : 
    1122                 :            : /*
    1123                 :            :  *  this functions is core for handling of linked stream
    1124                 :            :  *  Note: the stream state might be changed also on failure
    1125                 :            :  *  Note2: call with calling stream lock + link lock
    1126                 :            :  */
    1127                 :          0 : static int snd_pcm_action_group(const struct action_ops *ops,
    1128                 :            :                                 struct snd_pcm_substream *substream,
    1129                 :            :                                 snd_pcm_state_t state,
    1130                 :            :                                 bool do_lock)
    1131                 :            : {
    1132                 :          0 :         struct snd_pcm_substream *s = NULL;
    1133                 :          0 :         struct snd_pcm_substream *s1;
    1134                 :          0 :         int res = 0, depth = 1;
    1135                 :            : 
    1136         [ #  # ]:          0 :         snd_pcm_group_for_each_entry(s, substream) {
    1137         [ #  # ]:          0 :                 if (do_lock && s != substream) {
    1138         [ #  # ]:          0 :                         if (s->pcm->nonatomic)
    1139                 :          0 :                                 mutex_lock_nested(&s->self_group.mutex, depth);
    1140                 :            :                         else
    1141                 :          0 :                                 spin_lock_nested(&s->self_group.lock, depth);
    1142                 :          0 :                         depth++;
    1143                 :            :                 }
    1144                 :          0 :                 res = ops->pre_action(s, state);
    1145         [ #  # ]:          0 :                 if (res < 0)
    1146                 :          0 :                         goto _unlock;
    1147                 :            :         }
    1148         [ #  # ]:          0 :         snd_pcm_group_for_each_entry(s, substream) {
    1149                 :          0 :                 res = ops->do_action(s, state);
    1150         [ #  # ]:          0 :                 if (res < 0) {
    1151         [ #  # ]:          0 :                         if (ops->undo_action) {
    1152         [ #  # ]:          0 :                                 snd_pcm_group_for_each_entry(s1, substream) {
    1153         [ #  # ]:          0 :                                         if (s1 == s) /* failed stream */
    1154                 :            :                                                 break;
    1155                 :          0 :                                         ops->undo_action(s1, state);
    1156                 :            :                                 }
    1157                 :            :                         }
    1158                 :          0 :                         s = NULL; /* unlock all */
    1159                 :          0 :                         goto _unlock;
    1160                 :            :                 }
    1161                 :            :         }
    1162         [ #  # ]:          0 :         snd_pcm_group_for_each_entry(s, substream) {
    1163                 :          0 :                 ops->post_action(s, state);
    1164                 :            :         }
    1165                 :          0 :  _unlock:
    1166         [ #  # ]:          0 :         if (do_lock) {
    1167                 :            :                 /* unlock streams */
    1168         [ #  # ]:          0 :                 snd_pcm_group_for_each_entry(s1, substream) {
    1169         [ #  # ]:          0 :                         if (s1 != substream) {
    1170         [ #  # ]:          0 :                                 if (s1->pcm->nonatomic)
    1171                 :          0 :                                         mutex_unlock(&s1->self_group.mutex);
    1172                 :            :                                 else
    1173                 :          0 :                                         spin_unlock(&s1->self_group.lock);
    1174                 :            :                         }
    1175         [ #  # ]:          0 :                         if (s1 == s)    /* end */
    1176                 :            :                                 break;
    1177                 :            :                 }
    1178                 :            :         }
    1179                 :          0 :         return res;
    1180                 :            : }
    1181                 :            : 
    1182                 :            : /*
    1183                 :            :  *  Note: call with stream lock
    1184                 :            :  */
    1185                 :          0 : static int snd_pcm_action_single(const struct action_ops *ops,
    1186                 :            :                                  struct snd_pcm_substream *substream,
    1187                 :            :                                  snd_pcm_state_t state)
    1188                 :            : {
    1189                 :          0 :         int res;
    1190                 :            :         
    1191                 :          0 :         res = ops->pre_action(substream, state);
    1192         [ #  # ]:          0 :         if (res < 0)
    1193                 :            :                 return res;
    1194                 :          0 :         res = ops->do_action(substream, state);
    1195         [ #  # ]:          0 :         if (res == 0)
    1196                 :          0 :                 ops->post_action(substream, state);
    1197         [ #  # ]:          0 :         else if (ops->undo_action)
    1198                 :          0 :                 ops->undo_action(substream, state);
    1199                 :            :         return res;
    1200                 :            : }
    1201                 :            : 
    1202                 :          0 : static void snd_pcm_group_assign(struct snd_pcm_substream *substream,
    1203                 :            :                                  struct snd_pcm_group *new_group)
    1204                 :            : {
    1205                 :          0 :         substream->group = new_group;
    1206                 :          0 :         list_move(&substream->link_list, &new_group->substreams);
    1207                 :            : }
    1208                 :            : 
    1209                 :            : /*
    1210                 :            :  * Unref and unlock the group, but keep the stream lock;
    1211                 :            :  * when the group becomes empty and no longer referred, destroy itself
    1212                 :            :  */
    1213                 :            : static void snd_pcm_group_unref(struct snd_pcm_group *group,
    1214                 :            :                                 struct snd_pcm_substream *substream)
    1215                 :            : {
    1216                 :            :         bool do_free;
    1217                 :            : 
    1218                 :            :         if (!group)
    1219                 :            :                 return;
    1220                 :            :         do_free = refcount_dec_and_test(&group->refs);
    1221                 :            :         snd_pcm_group_unlock(group, substream->pcm->nonatomic);
    1222                 :            :         if (do_free)
    1223                 :            :                 kfree(group);
    1224                 :            : }
    1225                 :            : 
    1226                 :            : /*
    1227                 :            :  * Lock the group inside a stream lock and reference it;
    1228                 :            :  * return the locked group object, or NULL if not linked
    1229                 :            :  */
    1230                 :            : static struct snd_pcm_group *
    1231                 :          0 : snd_pcm_stream_group_ref(struct snd_pcm_substream *substream)
    1232                 :            : {
    1233                 :          0 :         bool nonatomic = substream->pcm->nonatomic;
    1234                 :          0 :         struct snd_pcm_group *group;
    1235                 :          0 :         bool trylock;
    1236                 :            : 
    1237                 :          0 :         for (;;) {
    1238         [ #  # ]:          0 :                 if (!snd_pcm_stream_linked(substream))
    1239                 :            :                         return NULL;
    1240                 :          0 :                 group = substream->group;
    1241                 :            :                 /* block freeing the group object */
    1242                 :          0 :                 refcount_inc(&group->refs);
    1243                 :            : 
    1244         [ #  # ]:          0 :                 trylock = nonatomic ? mutex_trylock(&group->mutex) :
    1245                 :            :                         spin_trylock(&group->lock);
    1246         [ #  # ]:          0 :                 if (trylock)
    1247                 :            :                         break; /* OK */
    1248                 :            : 
    1249                 :            :                 /* re-lock for avoiding ABBA deadlock */
    1250         [ #  # ]:          0 :                 snd_pcm_stream_unlock(substream);
    1251         [ #  # ]:          0 :                 snd_pcm_group_lock(group, nonatomic);
    1252                 :          0 :                 snd_pcm_stream_lock(substream);
    1253                 :            : 
    1254                 :            :                 /* check the group again; the above opens a small race window */
    1255         [ #  # ]:          0 :                 if (substream->group == group)
    1256                 :            :                         break; /* OK */
    1257                 :            :                 /* group changed, try again */
    1258                 :          0 :                 snd_pcm_group_unref(group, substream);
    1259                 :            :         }
    1260                 :            :         return group;
    1261                 :            : }
    1262                 :            : 
    1263                 :            : /*
    1264                 :            :  *  Note: call with stream lock
    1265                 :            :  */
    1266                 :          0 : static int snd_pcm_action(const struct action_ops *ops,
    1267                 :            :                           struct snd_pcm_substream *substream,
    1268                 :            :                           snd_pcm_state_t state)
    1269                 :            : {
    1270                 :          0 :         struct snd_pcm_group *group;
    1271                 :          0 :         int res;
    1272                 :            : 
    1273                 :          0 :         group = snd_pcm_stream_group_ref(substream);
    1274         [ #  # ]:          0 :         if (group)
    1275                 :          0 :                 res = snd_pcm_action_group(ops, substream, state, true);
    1276                 :            :         else
    1277                 :          0 :                 res = snd_pcm_action_single(ops, substream, state);
    1278                 :          0 :         snd_pcm_group_unref(group, substream);
    1279                 :          0 :         return res;
    1280                 :            : }
    1281                 :            : 
    1282                 :            : /*
    1283                 :            :  *  Note: don't use any locks before
    1284                 :            :  */
    1285                 :          0 : static int snd_pcm_action_lock_irq(const struct action_ops *ops,
    1286                 :            :                                    struct snd_pcm_substream *substream,
    1287                 :            :                                    snd_pcm_state_t state)
    1288                 :            : {
    1289                 :          0 :         int res;
    1290                 :            : 
    1291                 :          0 :         snd_pcm_stream_lock_irq(substream);
    1292                 :          0 :         res = snd_pcm_action(ops, substream, state);
    1293         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
    1294                 :          0 :         return res;
    1295                 :            : }
    1296                 :            : 
    1297                 :            : /*
    1298                 :            :  */
    1299                 :          0 : static int snd_pcm_action_nonatomic(const struct action_ops *ops,
    1300                 :            :                                     struct snd_pcm_substream *substream,
    1301                 :            :                                     snd_pcm_state_t state)
    1302                 :            : {
    1303                 :          0 :         int res;
    1304                 :            : 
    1305                 :            :         /* Guarantee the group members won't change during non-atomic action */
    1306                 :          0 :         down_read(&snd_pcm_link_rwsem);
    1307         [ #  # ]:          0 :         if (snd_pcm_stream_linked(substream))
    1308                 :          0 :                 res = snd_pcm_action_group(ops, substream, state, false);
    1309                 :            :         else
    1310                 :          0 :                 res = snd_pcm_action_single(ops, substream, state);
    1311                 :          0 :         up_read(&snd_pcm_link_rwsem);
    1312                 :          0 :         return res;
    1313                 :            : }
    1314                 :            : 
    1315                 :            : /*
    1316                 :            :  * start callbacks
    1317                 :            :  */
    1318                 :          0 : static int snd_pcm_pre_start(struct snd_pcm_substream *substream,
    1319                 :            :                              snd_pcm_state_t state)
    1320                 :            : {
    1321                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1322         [ #  # ]:          0 :         if (runtime->status->state != SNDRV_PCM_STATE_PREPARED)
    1323                 :            :                 return -EBADFD;
    1324   [ #  #  #  # ]:          0 :         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
    1325                 :            :             !snd_pcm_playback_data(substream))
    1326                 :            :                 return -EPIPE;
    1327                 :          0 :         runtime->trigger_tstamp_latched = false;
    1328                 :          0 :         runtime->trigger_master = substream;
    1329                 :          0 :         return 0;
    1330                 :            : }
    1331                 :            : 
    1332                 :          0 : static int snd_pcm_do_start(struct snd_pcm_substream *substream,
    1333                 :            :                             snd_pcm_state_t state)
    1334                 :            : {
    1335         [ #  # ]:          0 :         if (substream->runtime->trigger_master != substream)
    1336                 :            :                 return 0;
    1337                 :          0 :         return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
    1338                 :            : }
    1339                 :            : 
    1340                 :          0 : static void snd_pcm_undo_start(struct snd_pcm_substream *substream,
    1341                 :            :                                snd_pcm_state_t state)
    1342                 :            : {
    1343         [ #  # ]:          0 :         if (substream->runtime->trigger_master == substream)
    1344                 :          0 :                 substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
    1345                 :          0 : }
    1346                 :            : 
    1347                 :          0 : static void snd_pcm_post_start(struct snd_pcm_substream *substream,
    1348                 :            :                                snd_pcm_state_t state)
    1349                 :            : {
    1350                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1351                 :          0 :         snd_pcm_trigger_tstamp(substream);
    1352                 :          0 :         runtime->hw_ptr_jiffies = jiffies;
    1353                 :          0 :         runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) / 
    1354                 :          0 :                                                             runtime->rate;
    1355                 :          0 :         runtime->status->state = state;
    1356         [ #  # ]:          0 :         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
    1357         [ #  # ]:          0 :             runtime->silence_size > 0)
    1358                 :          0 :                 snd_pcm_playback_silence(substream, ULONG_MAX);
    1359         [ #  # ]:          0 :         snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTART);
    1360                 :          0 : }
    1361                 :            : 
    1362                 :            : static const struct action_ops snd_pcm_action_start = {
    1363                 :            :         .pre_action = snd_pcm_pre_start,
    1364                 :            :         .do_action = snd_pcm_do_start,
    1365                 :            :         .undo_action = snd_pcm_undo_start,
    1366                 :            :         .post_action = snd_pcm_post_start
    1367                 :            : };
    1368                 :            : 
    1369                 :            : /**
    1370                 :            :  * snd_pcm_start - start all linked streams
    1371                 :            :  * @substream: the PCM substream instance
    1372                 :            :  *
    1373                 :            :  * Return: Zero if successful, or a negative error code.
    1374                 :            :  * The stream lock must be acquired before calling this function.
    1375                 :            :  */
    1376                 :          0 : int snd_pcm_start(struct snd_pcm_substream *substream)
    1377                 :            : {
    1378                 :          0 :         return snd_pcm_action(&snd_pcm_action_start, substream,
    1379                 :            :                               SNDRV_PCM_STATE_RUNNING);
    1380                 :            : }
    1381                 :            : 
    1382                 :            : /* take the stream lock and start the streams */
    1383                 :          0 : static int snd_pcm_start_lock_irq(struct snd_pcm_substream *substream)
    1384                 :            : {
    1385                 :          0 :         return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream,
    1386                 :            :                                        SNDRV_PCM_STATE_RUNNING);
    1387                 :            : }
    1388                 :            : 
    1389                 :            : /*
    1390                 :            :  * stop callbacks
    1391                 :            :  */
    1392                 :          0 : static int snd_pcm_pre_stop(struct snd_pcm_substream *substream,
    1393                 :            :                             snd_pcm_state_t state)
    1394                 :            : {
    1395                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1396         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    1397                 :            :                 return -EBADFD;
    1398                 :          0 :         runtime->trigger_master = substream;
    1399                 :          0 :         return 0;
    1400                 :            : }
    1401                 :            : 
    1402                 :          0 : static int snd_pcm_do_stop(struct snd_pcm_substream *substream,
    1403                 :            :                            snd_pcm_state_t state)
    1404                 :            : {
    1405         [ #  # ]:          0 :         if (substream->runtime->trigger_master == substream &&
    1406         [ #  # ]:          0 :             snd_pcm_running(substream))
    1407                 :          0 :                 substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
    1408                 :          0 :         return 0; /* unconditonally stop all substreams */
    1409                 :            : }
    1410                 :            : 
    1411                 :          0 : static void snd_pcm_post_stop(struct snd_pcm_substream *substream,
    1412                 :            :                               snd_pcm_state_t state)
    1413                 :            : {
    1414                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1415         [ #  # ]:          0 :         if (runtime->status->state != state) {
    1416                 :          0 :                 snd_pcm_trigger_tstamp(substream);
    1417                 :          0 :                 runtime->status->state = state;
    1418         [ #  # ]:          0 :                 snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTOP);
    1419                 :            :         }
    1420                 :          0 :         runtime->stop_operating = true;
    1421                 :          0 :         wake_up(&runtime->sleep);
    1422                 :          0 :         wake_up(&runtime->tsleep);
    1423                 :          0 : }
    1424                 :            : 
    1425                 :            : static const struct action_ops snd_pcm_action_stop = {
    1426                 :            :         .pre_action = snd_pcm_pre_stop,
    1427                 :            :         .do_action = snd_pcm_do_stop,
    1428                 :            :         .post_action = snd_pcm_post_stop
    1429                 :            : };
    1430                 :            : 
    1431                 :            : /**
    1432                 :            :  * snd_pcm_stop - try to stop all running streams in the substream group
    1433                 :            :  * @substream: the PCM substream instance
    1434                 :            :  * @state: PCM state after stopping the stream
    1435                 :            :  *
    1436                 :            :  * The state of each stream is then changed to the given state unconditionally.
    1437                 :            :  *
    1438                 :            :  * Return: Zero if successful, or a negative error code.
    1439                 :            :  */
    1440                 :          0 : int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state)
    1441                 :            : {
    1442                 :          0 :         return snd_pcm_action(&snd_pcm_action_stop, substream, state);
    1443                 :            : }
    1444                 :            : EXPORT_SYMBOL(snd_pcm_stop);
    1445                 :            : 
    1446                 :            : /**
    1447                 :            :  * snd_pcm_drain_done - stop the DMA only when the given stream is playback
    1448                 :            :  * @substream: the PCM substream
    1449                 :            :  *
    1450                 :            :  * After stopping, the state is changed to SETUP.
    1451                 :            :  * Unlike snd_pcm_stop(), this affects only the given stream.
    1452                 :            :  *
    1453                 :            :  * Return: Zero if succesful, or a negative error code.
    1454                 :            :  */
    1455                 :          0 : int snd_pcm_drain_done(struct snd_pcm_substream *substream)
    1456                 :            : {
    1457                 :          0 :         return snd_pcm_action_single(&snd_pcm_action_stop, substream,
    1458                 :            :                                      SNDRV_PCM_STATE_SETUP);
    1459                 :            : }
    1460                 :            : 
    1461                 :            : /**
    1462                 :            :  * snd_pcm_stop_xrun - stop the running streams as XRUN
    1463                 :            :  * @substream: the PCM substream instance
    1464                 :            :  *
    1465                 :            :  * This stops the given running substream (and all linked substreams) as XRUN.
    1466                 :            :  * Unlike snd_pcm_stop(), this function takes the substream lock by itself.
    1467                 :            :  *
    1468                 :            :  * Return: Zero if successful, or a negative error code.
    1469                 :            :  */
    1470                 :          0 : int snd_pcm_stop_xrun(struct snd_pcm_substream *substream)
    1471                 :            : {
    1472                 :          0 :         unsigned long flags;
    1473                 :            : 
    1474                 :          0 :         snd_pcm_stream_lock_irqsave(substream, flags);
    1475   [ #  #  #  # ]:          0 :         if (substream->runtime && snd_pcm_running(substream))
    1476                 :          0 :                 __snd_pcm_xrun(substream);
    1477                 :          0 :         snd_pcm_stream_unlock_irqrestore(substream, flags);
    1478                 :          0 :         return 0;
    1479                 :            : }
    1480                 :            : EXPORT_SYMBOL_GPL(snd_pcm_stop_xrun);
    1481                 :            : 
    1482                 :            : /*
    1483                 :            :  * pause callbacks: pass boolean (to start pause or resume) as state argument
    1484                 :            :  */
    1485                 :            : #define pause_pushed(state)     (__force bool)(state)
    1486                 :            : 
    1487                 :          0 : static int snd_pcm_pre_pause(struct snd_pcm_substream *substream,
    1488                 :            :                              snd_pcm_state_t state)
    1489                 :            : {
    1490                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1491         [ #  # ]:          0 :         if (!(runtime->info & SNDRV_PCM_INFO_PAUSE))
    1492                 :            :                 return -ENOSYS;
    1493         [ #  # ]:          0 :         if (pause_pushed(state)) {
    1494         [ #  # ]:          0 :                 if (runtime->status->state != SNDRV_PCM_STATE_RUNNING)
    1495                 :            :                         return -EBADFD;
    1496         [ #  # ]:          0 :         } else if (runtime->status->state != SNDRV_PCM_STATE_PAUSED)
    1497                 :            :                 return -EBADFD;
    1498                 :          0 :         runtime->trigger_master = substream;
    1499                 :          0 :         return 0;
    1500                 :            : }
    1501                 :            : 
    1502                 :          0 : static int snd_pcm_do_pause(struct snd_pcm_substream *substream,
    1503                 :            :                             snd_pcm_state_t state)
    1504                 :            : {
    1505         [ #  # ]:          0 :         if (substream->runtime->trigger_master != substream)
    1506                 :            :                 return 0;
    1507                 :            :         /* some drivers might use hw_ptr to recover from the pause -
    1508                 :            :            update the hw_ptr now */
    1509         [ #  # ]:          0 :         if (pause_pushed(state))
    1510                 :          0 :                 snd_pcm_update_hw_ptr(substream);
    1511                 :            :         /* The jiffies check in snd_pcm_update_hw_ptr*() is done by
    1512                 :            :          * a delta between the current jiffies, this gives a large enough
    1513                 :            :          * delta, effectively to skip the check once.
    1514                 :            :          */
    1515                 :          0 :         substream->runtime->hw_ptr_jiffies = jiffies - HZ * 1000;
    1516         [ #  # ]:          0 :         return substream->ops->trigger(substream,
    1517                 :            :                                        pause_pushed(state) ?
    1518                 :            :                                        SNDRV_PCM_TRIGGER_PAUSE_PUSH :
    1519                 :            :                                        SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
    1520                 :            : }
    1521                 :            : 
    1522                 :          0 : static void snd_pcm_undo_pause(struct snd_pcm_substream *substream,
    1523                 :            :                                snd_pcm_state_t state)
    1524                 :            : {
    1525         [ #  # ]:          0 :         if (substream->runtime->trigger_master == substream)
    1526         [ #  # ]:          0 :                 substream->ops->trigger(substream,
    1527                 :            :                                         pause_pushed(state) ?
    1528                 :            :                                         SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
    1529                 :            :                                         SNDRV_PCM_TRIGGER_PAUSE_PUSH);
    1530                 :          0 : }
    1531                 :            : 
    1532                 :          0 : static void snd_pcm_post_pause(struct snd_pcm_substream *substream,
    1533                 :            :                                snd_pcm_state_t state)
    1534                 :            : {
    1535                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1536                 :          0 :         snd_pcm_trigger_tstamp(substream);
    1537         [ #  # ]:          0 :         if (pause_pushed(state)) {
    1538                 :          0 :                 runtime->status->state = SNDRV_PCM_STATE_PAUSED;
    1539         [ #  # ]:          0 :                 snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MPAUSE);
    1540                 :          0 :                 wake_up(&runtime->sleep);
    1541                 :          0 :                 wake_up(&runtime->tsleep);
    1542                 :            :         } else {
    1543                 :          0 :                 runtime->status->state = SNDRV_PCM_STATE_RUNNING;
    1544         [ #  # ]:          0 :                 snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MCONTINUE);
    1545                 :            :         }
    1546                 :          0 : }
    1547                 :            : 
    1548                 :            : static const struct action_ops snd_pcm_action_pause = {
    1549                 :            :         .pre_action = snd_pcm_pre_pause,
    1550                 :            :         .do_action = snd_pcm_do_pause,
    1551                 :            :         .undo_action = snd_pcm_undo_pause,
    1552                 :            :         .post_action = snd_pcm_post_pause
    1553                 :            : };
    1554                 :            : 
    1555                 :            : /*
    1556                 :            :  * Push/release the pause for all linked streams.
    1557                 :            :  */
    1558                 :          0 : static int snd_pcm_pause(struct snd_pcm_substream *substream, bool push)
    1559                 :            : {
    1560                 :          0 :         return snd_pcm_action(&snd_pcm_action_pause, substream,
    1561                 :            :                               (__force snd_pcm_state_t)push);
    1562                 :            : }
    1563                 :            : 
    1564                 :          0 : static int snd_pcm_pause_lock_irq(struct snd_pcm_substream *substream,
    1565                 :            :                                   bool push)
    1566                 :            : {
    1567                 :          0 :         return snd_pcm_action_lock_irq(&snd_pcm_action_pause, substream,
    1568                 :            :                                        (__force snd_pcm_state_t)push);
    1569                 :            : }
    1570                 :            : 
    1571                 :            : #ifdef CONFIG_PM
    1572                 :            : /* suspend callback: state argument ignored */
    1573                 :            : 
    1574                 :          0 : static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream,
    1575                 :            :                                snd_pcm_state_t state)
    1576                 :            : {
    1577                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1578         [ #  # ]:          0 :         switch (runtime->status->state) {
    1579                 :            :         case SNDRV_PCM_STATE_SUSPENDED:
    1580                 :            :                 return -EBUSY;
    1581                 :            :         /* unresumable PCM state; return -EBUSY for skipping suspend */
    1582                 :            :         case SNDRV_PCM_STATE_OPEN:
    1583                 :            :         case SNDRV_PCM_STATE_SETUP:
    1584                 :            :         case SNDRV_PCM_STATE_DISCONNECTED:
    1585                 :            :                 return -EBUSY;
    1586                 :            :         }
    1587                 :          0 :         runtime->trigger_master = substream;
    1588                 :          0 :         return 0;
    1589                 :            : }
    1590                 :            : 
    1591                 :          0 : static int snd_pcm_do_suspend(struct snd_pcm_substream *substream,
    1592                 :            :                               snd_pcm_state_t state)
    1593                 :            : {
    1594                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1595         [ #  # ]:          0 :         if (runtime->trigger_master != substream)
    1596                 :            :                 return 0;
    1597         [ #  # ]:          0 :         if (! snd_pcm_running(substream))
    1598                 :            :                 return 0;
    1599                 :          0 :         substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
    1600                 :          0 :         return 0; /* suspend unconditionally */
    1601                 :            : }
    1602                 :            : 
    1603                 :          0 : static void snd_pcm_post_suspend(struct snd_pcm_substream *substream,
    1604                 :            :                                  snd_pcm_state_t state)
    1605                 :            : {
    1606                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1607                 :          0 :         snd_pcm_trigger_tstamp(substream);
    1608                 :          0 :         runtime->status->suspended_state = runtime->status->state;
    1609                 :          0 :         runtime->status->state = SNDRV_PCM_STATE_SUSPENDED;
    1610         [ #  # ]:          0 :         snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSUSPEND);
    1611                 :          0 :         wake_up(&runtime->sleep);
    1612                 :          0 :         wake_up(&runtime->tsleep);
    1613                 :          0 : }
    1614                 :            : 
    1615                 :            : static const struct action_ops snd_pcm_action_suspend = {
    1616                 :            :         .pre_action = snd_pcm_pre_suspend,
    1617                 :            :         .do_action = snd_pcm_do_suspend,
    1618                 :            :         .post_action = snd_pcm_post_suspend
    1619                 :            : };
    1620                 :            : 
    1621                 :            : /*
    1622                 :            :  * snd_pcm_suspend - trigger SUSPEND to all linked streams
    1623                 :            :  * @substream: the PCM substream
    1624                 :            :  *
    1625                 :            :  * After this call, all streams are changed to SUSPENDED state.
    1626                 :            :  *
    1627                 :            :  * Return: Zero if successful, or a negative error code.
    1628                 :            :  */
    1629                 :          0 : static int snd_pcm_suspend(struct snd_pcm_substream *substream)
    1630                 :            : {
    1631                 :          0 :         int err;
    1632                 :          0 :         unsigned long flags;
    1633                 :            : 
    1634                 :          0 :         snd_pcm_stream_lock_irqsave(substream, flags);
    1635                 :          0 :         err = snd_pcm_action(&snd_pcm_action_suspend, substream,
    1636                 :            :                              ACTION_ARG_IGNORE);
    1637                 :          0 :         snd_pcm_stream_unlock_irqrestore(substream, flags);
    1638                 :          0 :         return err;
    1639                 :            : }
    1640                 :            : 
    1641                 :            : /**
    1642                 :            :  * snd_pcm_suspend_all - trigger SUSPEND to all substreams in the given pcm
    1643                 :            :  * @pcm: the PCM instance
    1644                 :            :  *
    1645                 :            :  * After this call, all streams are changed to SUSPENDED state.
    1646                 :            :  *
    1647                 :            :  * Return: Zero if successful (or @pcm is %NULL), or a negative error code.
    1648                 :            :  */
    1649                 :          0 : int snd_pcm_suspend_all(struct snd_pcm *pcm)
    1650                 :            : {
    1651                 :          0 :         struct snd_pcm_substream *substream;
    1652                 :          0 :         int stream, err = 0;
    1653                 :            : 
    1654         [ #  # ]:          0 :         if (! pcm)
    1655                 :            :                 return 0;
    1656                 :            : 
    1657         [ #  # ]:          0 :         for (stream = 0; stream < 2; stream++) {
    1658                 :          0 :                 for (substream = pcm->streams[stream].substream;
    1659         [ #  # ]:          0 :                      substream; substream = substream->next) {
    1660                 :            :                         /* FIXME: the open/close code should lock this as well */
    1661         [ #  # ]:          0 :                         if (substream->runtime == NULL)
    1662                 :          0 :                                 continue;
    1663                 :            : 
    1664                 :            :                         /*
    1665                 :            :                          * Skip BE dai link PCM's that are internal and may
    1666                 :            :                          * not have their substream ops set.
    1667                 :            :                          */
    1668         [ #  # ]:          0 :                         if (!substream->ops)
    1669                 :          0 :                                 continue;
    1670                 :            : 
    1671                 :          0 :                         err = snd_pcm_suspend(substream);
    1672         [ #  # ]:          0 :                         if (err < 0 && err != -EBUSY)
    1673                 :          0 :                                 return err;
    1674                 :            :                 }
    1675                 :            :         }
    1676                 :            :         return 0;
    1677                 :            : }
    1678                 :            : EXPORT_SYMBOL(snd_pcm_suspend_all);
    1679                 :            : 
    1680                 :            : /* resume callbacks: state argument ignored */
    1681                 :            : 
    1682                 :          0 : static int snd_pcm_pre_resume(struct snd_pcm_substream *substream,
    1683                 :            :                               snd_pcm_state_t state)
    1684                 :            : {
    1685                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1686         [ #  # ]:          0 :         if (!(runtime->info & SNDRV_PCM_INFO_RESUME))
    1687                 :            :                 return -ENOSYS;
    1688                 :          0 :         runtime->trigger_master = substream;
    1689                 :          0 :         return 0;
    1690                 :            : }
    1691                 :            : 
    1692                 :          0 : static int snd_pcm_do_resume(struct snd_pcm_substream *substream,
    1693                 :            :                              snd_pcm_state_t state)
    1694                 :            : {
    1695                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1696         [ #  # ]:          0 :         if (runtime->trigger_master != substream)
    1697                 :            :                 return 0;
    1698                 :            :         /* DMA not running previously? */
    1699   [ #  #  #  # ]:          0 :         if (runtime->status->suspended_state != SNDRV_PCM_STATE_RUNNING &&
    1700                 :          0 :             (runtime->status->suspended_state != SNDRV_PCM_STATE_DRAINING ||
    1701         [ #  # ]:          0 :              substream->stream != SNDRV_PCM_STREAM_PLAYBACK))
    1702                 :            :                 return 0;
    1703                 :          0 :         return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_RESUME);
    1704                 :            : }
    1705                 :            : 
    1706                 :          0 : static void snd_pcm_undo_resume(struct snd_pcm_substream *substream,
    1707                 :            :                                 snd_pcm_state_t state)
    1708                 :            : {
    1709         [ #  # ]:          0 :         if (substream->runtime->trigger_master == substream &&
    1710         [ #  # ]:          0 :             snd_pcm_running(substream))
    1711                 :          0 :                 substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
    1712                 :          0 : }
    1713                 :            : 
    1714                 :          0 : static void snd_pcm_post_resume(struct snd_pcm_substream *substream,
    1715                 :            :                                 snd_pcm_state_t state)
    1716                 :            : {
    1717                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1718                 :          0 :         snd_pcm_trigger_tstamp(substream);
    1719                 :          0 :         runtime->status->state = runtime->status->suspended_state;
    1720         [ #  # ]:          0 :         snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MRESUME);
    1721                 :          0 :         snd_pcm_sync_stop(substream);
    1722                 :          0 : }
    1723                 :            : 
    1724                 :            : static const struct action_ops snd_pcm_action_resume = {
    1725                 :            :         .pre_action = snd_pcm_pre_resume,
    1726                 :            :         .do_action = snd_pcm_do_resume,
    1727                 :            :         .undo_action = snd_pcm_undo_resume,
    1728                 :            :         .post_action = snd_pcm_post_resume
    1729                 :            : };
    1730                 :            : 
    1731                 :          0 : static int snd_pcm_resume(struct snd_pcm_substream *substream)
    1732                 :            : {
    1733                 :          0 :         return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream,
    1734                 :            :                                        ACTION_ARG_IGNORE);
    1735                 :            : }
    1736                 :            : 
    1737                 :            : #else
    1738                 :            : 
    1739                 :            : static int snd_pcm_resume(struct snd_pcm_substream *substream)
    1740                 :            : {
    1741                 :            :         return -ENOSYS;
    1742                 :            : }
    1743                 :            : 
    1744                 :            : #endif /* CONFIG_PM */
    1745                 :            : 
    1746                 :            : /*
    1747                 :            :  * xrun ioctl
    1748                 :            :  *
    1749                 :            :  * Change the RUNNING stream(s) to XRUN state.
    1750                 :            :  */
    1751                 :          0 : static int snd_pcm_xrun(struct snd_pcm_substream *substream)
    1752                 :            : {
    1753                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1754                 :          0 :         int result;
    1755                 :            : 
    1756                 :          0 :         snd_pcm_stream_lock_irq(substream);
    1757      [ #  #  # ]:          0 :         switch (runtime->status->state) {
    1758                 :            :         case SNDRV_PCM_STATE_XRUN:
    1759                 :            :                 result = 0;     /* already there */
    1760                 :            :                 break;
    1761                 :          0 :         case SNDRV_PCM_STATE_RUNNING:
    1762                 :          0 :                 __snd_pcm_xrun(substream);
    1763                 :          0 :                 result = 0;
    1764                 :          0 :                 break;
    1765                 :          0 :         default:
    1766                 :          0 :                 result = -EBADFD;
    1767                 :            :         }
    1768         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
    1769                 :          0 :         return result;
    1770                 :            : }
    1771                 :            : 
    1772                 :            : /*
    1773                 :            :  * reset ioctl
    1774                 :            :  */
    1775                 :            : /* reset callbacks:  state argument ignored */
    1776                 :          0 : static int snd_pcm_pre_reset(struct snd_pcm_substream *substream,
    1777                 :            :                              snd_pcm_state_t state)
    1778                 :            : {
    1779                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1780         [ #  # ]:          0 :         switch (runtime->status->state) {
    1781                 :            :         case SNDRV_PCM_STATE_RUNNING:
    1782                 :            :         case SNDRV_PCM_STATE_PREPARED:
    1783                 :            :         case SNDRV_PCM_STATE_PAUSED:
    1784                 :            :         case SNDRV_PCM_STATE_SUSPENDED:
    1785                 :            :                 return 0;
    1786                 :          0 :         default:
    1787                 :          0 :                 return -EBADFD;
    1788                 :            :         }
    1789                 :            : }
    1790                 :            : 
    1791                 :          0 : static int snd_pcm_do_reset(struct snd_pcm_substream *substream,
    1792                 :            :                             snd_pcm_state_t state)
    1793                 :            : {
    1794                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1795                 :          0 :         int err = snd_pcm_ops_ioctl(substream, SNDRV_PCM_IOCTL1_RESET, NULL);
    1796         [ #  # ]:          0 :         if (err < 0)
    1797                 :            :                 return err;
    1798                 :          0 :         runtime->hw_ptr_base = 0;
    1799                 :          0 :         runtime->hw_ptr_interrupt = runtime->status->hw_ptr -
    1800                 :          0 :                 runtime->status->hw_ptr % runtime->period_size;
    1801                 :          0 :         runtime->silence_start = runtime->status->hw_ptr;
    1802                 :          0 :         runtime->silence_filled = 0;
    1803                 :          0 :         return 0;
    1804                 :            : }
    1805                 :            : 
    1806                 :          0 : static void snd_pcm_post_reset(struct snd_pcm_substream *substream,
    1807                 :            :                                snd_pcm_state_t state)
    1808                 :            : {
    1809                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1810                 :          0 :         runtime->control->appl_ptr = runtime->status->hw_ptr;
    1811         [ #  # ]:          0 :         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
    1812         [ #  # ]:          0 :             runtime->silence_size > 0)
    1813                 :          0 :                 snd_pcm_playback_silence(substream, ULONG_MAX);
    1814                 :          0 : }
    1815                 :            : 
    1816                 :            : static const struct action_ops snd_pcm_action_reset = {
    1817                 :            :         .pre_action = snd_pcm_pre_reset,
    1818                 :            :         .do_action = snd_pcm_do_reset,
    1819                 :            :         .post_action = snd_pcm_post_reset
    1820                 :            : };
    1821                 :            : 
    1822                 :          0 : static int snd_pcm_reset(struct snd_pcm_substream *substream)
    1823                 :            : {
    1824                 :          0 :         return snd_pcm_action_nonatomic(&snd_pcm_action_reset, substream,
    1825                 :            :                                         ACTION_ARG_IGNORE);
    1826                 :            : }
    1827                 :            : 
    1828                 :            : /*
    1829                 :            :  * prepare ioctl
    1830                 :            :  */
    1831                 :            : /* pass f_flags as state argument */
    1832                 :          0 : static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
    1833                 :            :                                snd_pcm_state_t state)
    1834                 :            : {
    1835                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1836                 :          0 :         int f_flags = (__force int)state;
    1837                 :            : 
    1838         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
    1839                 :            :             runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
    1840                 :            :                 return -EBADFD;
    1841         [ #  # ]:          0 :         if (snd_pcm_running(substream))
    1842                 :            :                 return -EBUSY;
    1843                 :          0 :         substream->f_flags = f_flags;
    1844                 :          0 :         return 0;
    1845                 :            : }
    1846                 :            : 
    1847                 :          0 : static int snd_pcm_do_prepare(struct snd_pcm_substream *substream,
    1848                 :            :                               snd_pcm_state_t state)
    1849                 :            : {
    1850                 :          0 :         int err;
    1851                 :          0 :         snd_pcm_sync_stop(substream);
    1852                 :          0 :         err = substream->ops->prepare(substream);
    1853         [ #  # ]:          0 :         if (err < 0)
    1854                 :            :                 return err;
    1855                 :          0 :         return snd_pcm_do_reset(substream, state);
    1856                 :            : }
    1857                 :            : 
    1858                 :          0 : static void snd_pcm_post_prepare(struct snd_pcm_substream *substream,
    1859                 :            :                                  snd_pcm_state_t state)
    1860                 :            : {
    1861                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1862                 :          0 :         runtime->control->appl_ptr = runtime->status->hw_ptr;
    1863                 :          0 :         snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED);
    1864                 :          0 : }
    1865                 :            : 
    1866                 :            : static const struct action_ops snd_pcm_action_prepare = {
    1867                 :            :         .pre_action = snd_pcm_pre_prepare,
    1868                 :            :         .do_action = snd_pcm_do_prepare,
    1869                 :            :         .post_action = snd_pcm_post_prepare
    1870                 :            : };
    1871                 :            : 
    1872                 :            : /**
    1873                 :            :  * snd_pcm_prepare - prepare the PCM substream to be triggerable
    1874                 :            :  * @substream: the PCM substream instance
    1875                 :            :  * @file: file to refer f_flags
    1876                 :            :  *
    1877                 :            :  * Return: Zero if successful, or a negative error code.
    1878                 :            :  */
    1879                 :          0 : static int snd_pcm_prepare(struct snd_pcm_substream *substream,
    1880                 :            :                            struct file *file)
    1881                 :            : {
    1882                 :          0 :         int f_flags;
    1883                 :            : 
    1884         [ #  # ]:          0 :         if (file)
    1885                 :          0 :                 f_flags = file->f_flags;
    1886                 :            :         else
    1887                 :          0 :                 f_flags = substream->f_flags;
    1888                 :            : 
    1889                 :          0 :         snd_pcm_stream_lock_irq(substream);
    1890      [ #  #  # ]:          0 :         switch (substream->runtime->status->state) {
    1891                 :            :         case SNDRV_PCM_STATE_PAUSED:
    1892                 :          0 :                 snd_pcm_pause(substream, false);
    1893                 :            :                 /* fallthru */
    1894                 :          0 :         case SNDRV_PCM_STATE_SUSPENDED:
    1895                 :          0 :                 snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
    1896                 :            :                 break;
    1897                 :            :         }
    1898         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
    1899                 :            : 
    1900                 :          0 :         return snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
    1901                 :            :                                         substream,
    1902                 :            :                                         (__force snd_pcm_state_t)f_flags);
    1903                 :            : }
    1904                 :            : 
    1905                 :            : /*
    1906                 :            :  * drain ioctl
    1907                 :            :  */
    1908                 :            : 
    1909                 :            : /* drain init callbacks: state argument ignored */
    1910                 :          0 : static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream,
    1911                 :            :                                   snd_pcm_state_t state)
    1912                 :            : {
    1913                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1914         [ #  # ]:          0 :         switch (runtime->status->state) {
    1915                 :            :         case SNDRV_PCM_STATE_OPEN:
    1916                 :            :         case SNDRV_PCM_STATE_DISCONNECTED:
    1917                 :            :         case SNDRV_PCM_STATE_SUSPENDED:
    1918                 :            :                 return -EBADFD;
    1919                 :            :         }
    1920                 :          0 :         runtime->trigger_master = substream;
    1921                 :          0 :         return 0;
    1922                 :            : }
    1923                 :            : 
    1924                 :          0 : static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream,
    1925                 :            :                                  snd_pcm_state_t state)
    1926                 :            : {
    1927                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1928         [ #  # ]:          0 :         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    1929   [ #  #  #  # ]:          0 :                 switch (runtime->status->state) {
    1930                 :          0 :                 case SNDRV_PCM_STATE_PREPARED:
    1931                 :            :                         /* start playback stream if possible */
    1932   [ #  #  #  # ]:          0 :                         if (! snd_pcm_playback_empty(substream)) {
    1933         [ #  # ]:          0 :                                 snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING);
    1934                 :          0 :                                 snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING);
    1935                 :            :                         } else {
    1936                 :          0 :                                 runtime->status->state = SNDRV_PCM_STATE_SETUP;
    1937                 :            :                         }
    1938                 :            :                         break;
    1939                 :          0 :                 case SNDRV_PCM_STATE_RUNNING:
    1940                 :          0 :                         runtime->status->state = SNDRV_PCM_STATE_DRAINING;
    1941                 :          0 :                         break;
    1942                 :          0 :                 case SNDRV_PCM_STATE_XRUN:
    1943                 :          0 :                         runtime->status->state = SNDRV_PCM_STATE_SETUP;
    1944                 :          0 :                         break;
    1945                 :            :                 default:
    1946                 :            :                         break;
    1947                 :            :                 }
    1948                 :            :         } else {
    1949                 :            :                 /* stop running stream */
    1950         [ #  # ]:          0 :                 if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) {
    1951                 :          0 :                         snd_pcm_state_t new_state;
    1952                 :            : 
    1953         [ #  # ]:          0 :                         new_state = snd_pcm_capture_avail(runtime) > 0 ?
    1954         [ #  # ]:          0 :                                 SNDRV_PCM_STATE_DRAINING : SNDRV_PCM_STATE_SETUP;
    1955                 :          0 :                         snd_pcm_do_stop(substream, new_state);
    1956                 :          0 :                         snd_pcm_post_stop(substream, new_state);
    1957                 :            :                 }
    1958                 :            :         }
    1959                 :            : 
    1960         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_DRAINING &&
    1961         [ #  # ]:          0 :             runtime->trigger_master == substream &&
    1962         [ #  # ]:          0 :             (runtime->hw.info & SNDRV_PCM_INFO_DRAIN_TRIGGER))
    1963                 :          0 :                 return substream->ops->trigger(substream,
    1964                 :            :                                                SNDRV_PCM_TRIGGER_DRAIN);
    1965                 :            : 
    1966                 :            :         return 0;
    1967                 :            : }
    1968                 :            : 
    1969                 :          0 : static void snd_pcm_post_drain_init(struct snd_pcm_substream *substream,
    1970                 :            :                                     snd_pcm_state_t state)
    1971                 :            : {
    1972                 :          0 : }
    1973                 :            : 
    1974                 :            : static const struct action_ops snd_pcm_action_drain_init = {
    1975                 :            :         .pre_action = snd_pcm_pre_drain_init,
    1976                 :            :         .do_action = snd_pcm_do_drain_init,
    1977                 :            :         .post_action = snd_pcm_post_drain_init
    1978                 :            : };
    1979                 :            : 
    1980                 :            : /*
    1981                 :            :  * Drain the stream(s).
    1982                 :            :  * When the substream is linked, sync until the draining of all playback streams
    1983                 :            :  * is finished.
    1984                 :            :  * After this call, all streams are supposed to be either SETUP or DRAINING
    1985                 :            :  * (capture only) state.
    1986                 :            :  */
    1987                 :          0 : static int snd_pcm_drain(struct snd_pcm_substream *substream,
    1988                 :            :                          struct file *file)
    1989                 :            : {
    1990                 :          0 :         struct snd_card *card;
    1991                 :          0 :         struct snd_pcm_runtime *runtime;
    1992                 :          0 :         struct snd_pcm_substream *s;
    1993                 :          0 :         struct snd_pcm_group *group;
    1994                 :          0 :         wait_queue_entry_t wait;
    1995                 :          0 :         int result = 0;
    1996                 :          0 :         int nonblock = 0;
    1997                 :            : 
    1998                 :          0 :         card = substream->pcm->card;
    1999                 :          0 :         runtime = substream->runtime;
    2000                 :            : 
    2001         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    2002                 :            :                 return -EBADFD;
    2003                 :            : 
    2004         [ #  # ]:          0 :         if (file) {
    2005         [ #  # ]:          0 :                 if (file->f_flags & O_NONBLOCK)
    2006                 :          0 :                         nonblock = 1;
    2007         [ #  # ]:          0 :         } else if (substream->f_flags & O_NONBLOCK)
    2008                 :          0 :                 nonblock = 1;
    2009                 :            : 
    2010                 :          0 :         snd_pcm_stream_lock_irq(substream);
    2011                 :            :         /* resume pause */
    2012         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
    2013                 :          0 :                 snd_pcm_pause(substream, false);
    2014                 :            : 
    2015                 :            :         /* pre-start/stop - all running streams are changed to DRAINING state */
    2016                 :          0 :         result = snd_pcm_action(&snd_pcm_action_drain_init, substream,
    2017                 :            :                                 ACTION_ARG_IGNORE);
    2018         [ #  # ]:          0 :         if (result < 0)
    2019                 :          0 :                 goto unlock;
    2020                 :            :         /* in non-blocking, we don't wait in ioctl but let caller poll */
    2021         [ #  # ]:          0 :         if (nonblock) {
    2022                 :          0 :                 result = -EAGAIN;
    2023                 :          0 :                 goto unlock;
    2024                 :            :         }
    2025                 :            : 
    2026                 :          0 :         for (;;) {
    2027                 :          0 :                 long tout;
    2028                 :          0 :                 struct snd_pcm_runtime *to_check;
    2029         [ #  # ]:          0 :                 if (signal_pending(current)) {
    2030                 :            :                         result = -ERESTARTSYS;
    2031                 :            :                         break;
    2032                 :            :                 }
    2033                 :            :                 /* find a substream to drain */
    2034                 :          0 :                 to_check = NULL;
    2035                 :          0 :                 group = snd_pcm_stream_group_ref(substream);
    2036         [ #  # ]:          0 :                 snd_pcm_group_for_each_entry(s, substream) {
    2037         [ #  # ]:          0 :                         if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
    2038                 :          0 :                                 continue;
    2039                 :          0 :                         runtime = s->runtime;
    2040         [ #  # ]:          0 :                         if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
    2041                 :            :                                 to_check = runtime;
    2042                 :            :                                 break;
    2043                 :            :                         }
    2044                 :            :                 }
    2045                 :          0 :                 snd_pcm_group_unref(group, substream);
    2046         [ #  # ]:          0 :                 if (!to_check)
    2047                 :            :                         break; /* all drained */
    2048                 :          0 :                 init_waitqueue_entry(&wait, current);
    2049                 :          0 :                 set_current_state(TASK_INTERRUPTIBLE);
    2050                 :          0 :                 add_wait_queue(&to_check->sleep, &wait);
    2051         [ #  # ]:          0 :                 snd_pcm_stream_unlock_irq(substream);
    2052         [ #  # ]:          0 :                 if (runtime->no_period_wakeup)
    2053                 :            :                         tout = MAX_SCHEDULE_TIMEOUT;
    2054                 :            :                 else {
    2055                 :          0 :                         tout = 10;
    2056         [ #  # ]:          0 :                         if (runtime->rate) {
    2057                 :          0 :                                 long t = runtime->period_size * 2 / runtime->rate;
    2058                 :          0 :                                 tout = max(t, tout);
    2059                 :            :                         }
    2060         [ #  # ]:          0 :                         tout = msecs_to_jiffies(tout * 1000);
    2061                 :            :                 }
    2062                 :          0 :                 tout = schedule_timeout(tout);
    2063                 :            : 
    2064                 :          0 :                 snd_pcm_stream_lock_irq(substream);
    2065                 :          0 :                 group = snd_pcm_stream_group_ref(substream);
    2066         [ #  # ]:          0 :                 snd_pcm_group_for_each_entry(s, substream) {
    2067         [ #  # ]:          0 :                         if (s->runtime == to_check) {
    2068                 :          0 :                                 remove_wait_queue(&to_check->sleep, &wait);
    2069                 :          0 :                                 break;
    2070                 :            :                         }
    2071                 :            :                 }
    2072                 :          0 :                 snd_pcm_group_unref(group, substream);
    2073                 :            : 
    2074         [ #  # ]:          0 :                 if (card->shutdown) {
    2075                 :            :                         result = -ENODEV;
    2076                 :            :                         break;
    2077                 :            :                 }
    2078         [ #  # ]:          0 :                 if (tout == 0) {
    2079         [ #  # ]:          0 :                         if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
    2080                 :            :                                 result = -ESTRPIPE;
    2081                 :            :                         else {
    2082                 :          0 :                                 dev_dbg(substream->pcm->card->dev,
    2083                 :            :                                         "playback drain error (DMA or IRQ trouble?)\n");
    2084                 :          0 :                                 snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
    2085                 :          0 :                                 result = -EIO;
    2086                 :            :                         }
    2087                 :            :                         break;
    2088                 :            :                 }
    2089                 :            :         }
    2090                 :            : 
    2091                 :          0 :  unlock:
    2092         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
    2093                 :            : 
    2094                 :            :         return result;
    2095                 :            : }
    2096                 :            : 
    2097                 :            : /*
    2098                 :            :  * drop ioctl
    2099                 :            :  *
    2100                 :            :  * Immediately put all linked substreams into SETUP state.
    2101                 :            :  */
    2102                 :          0 : static int snd_pcm_drop(struct snd_pcm_substream *substream)
    2103                 :            : {
    2104                 :          0 :         struct snd_pcm_runtime *runtime;
    2105                 :          0 :         int result = 0;
    2106                 :            :         
    2107   [ #  #  #  #  :          0 :         if (PCM_RUNTIME_CHECK(substream))
                   #  # ]
    2108                 :            :                 return -ENXIO;
    2109                 :          0 :         runtime = substream->runtime;
    2110                 :            : 
    2111         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
    2112                 :            :             runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
    2113                 :            :                 return -EBADFD;
    2114                 :            : 
    2115                 :          0 :         snd_pcm_stream_lock_irq(substream);
    2116                 :            :         /* resume pause */
    2117         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
    2118                 :          0 :                 snd_pcm_pause(substream, false);
    2119                 :            : 
    2120                 :          0 :         snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
    2121                 :            :         /* runtime->control->appl_ptr = runtime->status->hw_ptr; */
    2122         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
    2123                 :            : 
    2124                 :            :         return result;
    2125                 :            : }
    2126                 :            : 
    2127                 :            : 
    2128                 :          0 : static bool is_pcm_file(struct file *file)
    2129                 :            : {
    2130         [ #  # ]:          0 :         struct inode *inode = file_inode(file);
    2131                 :          0 :         struct snd_pcm *pcm;
    2132                 :          0 :         unsigned int minor;
    2133                 :            : 
    2134   [ #  #  #  # ]:          0 :         if (!S_ISCHR(inode->i_mode) || imajor(inode) != snd_major)
    2135                 :            :                 return false;
    2136                 :          0 :         minor = iminor(inode);
    2137                 :          0 :         pcm = snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
    2138         [ #  # ]:          0 :         if (!pcm)
    2139                 :          0 :                 pcm = snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE);
    2140         [ #  # ]:          0 :         if (!pcm)
    2141                 :            :                 return false;
    2142                 :          0 :         snd_card_unref(pcm->card);
    2143                 :          0 :         return true;
    2144                 :            : }
    2145                 :            : 
    2146                 :            : /*
    2147                 :            :  * PCM link handling
    2148                 :            :  */
    2149                 :          0 : static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
    2150                 :            : {
    2151                 :          0 :         int res = 0;
    2152                 :          0 :         struct snd_pcm_file *pcm_file;
    2153                 :          0 :         struct snd_pcm_substream *substream1;
    2154                 :          0 :         struct snd_pcm_group *group, *target_group;
    2155                 :          0 :         bool nonatomic = substream->pcm->nonatomic;
    2156                 :          0 :         struct fd f = fdget(fd);
    2157                 :            : 
    2158         [ #  # ]:          0 :         if (!f.file)
    2159                 :            :                 return -EBADFD;
    2160         [ #  # ]:          0 :         if (!is_pcm_file(f.file)) {
    2161                 :          0 :                 res = -EBADFD;
    2162                 :          0 :                 goto _badf;
    2163                 :            :         }
    2164                 :          0 :         pcm_file = f.file->private_data;
    2165                 :          0 :         substream1 = pcm_file->substream;
    2166                 :          0 :         group = kzalloc(sizeof(*group), GFP_KERNEL);
    2167         [ #  # ]:          0 :         if (!group) {
    2168                 :          0 :                 res = -ENOMEM;
    2169                 :          0 :                 goto _nolock;
    2170                 :            :         }
    2171                 :          0 :         snd_pcm_group_init(group);
    2172                 :            : 
    2173                 :          0 :         down_write(&snd_pcm_link_rwsem);
    2174         [ #  # ]:          0 :         if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
    2175         [ #  # ]:          0 :             substream->runtime->status->state != substream1->runtime->status->state ||
    2176         [ #  # ]:          0 :             substream->pcm->nonatomic != substream1->pcm->nonatomic) {
    2177                 :          0 :                 res = -EBADFD;
    2178                 :          0 :                 goto _end;
    2179                 :            :         }
    2180         [ #  # ]:          0 :         if (snd_pcm_stream_linked(substream1)) {
    2181                 :          0 :                 res = -EALREADY;
    2182                 :          0 :                 goto _end;
    2183                 :            :         }
    2184                 :            : 
    2185                 :          0 :         snd_pcm_stream_lock_irq(substream);
    2186         [ #  # ]:          0 :         if (!snd_pcm_stream_linked(substream)) {
    2187                 :          0 :                 snd_pcm_group_assign(substream, group);
    2188                 :          0 :                 group = NULL; /* assigned, don't free this one below */
    2189                 :            :         }
    2190                 :          0 :         target_group = substream->group;
    2191         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
    2192                 :            : 
    2193         [ #  # ]:          0 :         snd_pcm_group_lock_irq(target_group, nonatomic);
    2194                 :          0 :         snd_pcm_stream_lock(substream1);
    2195                 :          0 :         snd_pcm_group_assign(substream1, target_group);
    2196                 :          0 :         refcount_inc(&target_group->refs);
    2197         [ #  # ]:          0 :         snd_pcm_stream_unlock(substream1);
    2198         [ #  # ]:          0 :         snd_pcm_group_unlock_irq(target_group, nonatomic);
    2199                 :          0 :  _end:
    2200                 :          0 :         up_write(&snd_pcm_link_rwsem);
    2201                 :          0 :  _nolock:
    2202                 :          0 :         kfree(group);
    2203                 :          0 :  _badf:
    2204         [ #  # ]:          0 :         fdput(f);
    2205                 :            :         return res;
    2206                 :            : }
    2207                 :            : 
    2208                 :          0 : static void relink_to_local(struct snd_pcm_substream *substream)
    2209                 :            : {
    2210                 :          0 :         snd_pcm_stream_lock(substream);
    2211         [ #  # ]:          0 :         snd_pcm_group_assign(substream, &substream->self_group);
    2212         [ #  # ]:          0 :         snd_pcm_stream_unlock(substream);
    2213                 :          0 : }
    2214                 :            : 
    2215                 :          0 : static int snd_pcm_unlink(struct snd_pcm_substream *substream)
    2216                 :            : {
    2217                 :          0 :         struct snd_pcm_group *group;
    2218                 :          0 :         bool nonatomic = substream->pcm->nonatomic;
    2219                 :          0 :         bool do_free = false;
    2220                 :          0 :         int res = 0;
    2221                 :            : 
    2222                 :          0 :         down_write(&snd_pcm_link_rwsem);
    2223                 :            : 
    2224         [ #  # ]:          0 :         if (!snd_pcm_stream_linked(substream)) {
    2225                 :          0 :                 res = -EALREADY;
    2226                 :          0 :                 goto _end;
    2227                 :            :         }
    2228                 :            : 
    2229                 :          0 :         group = substream->group;
    2230         [ #  # ]:          0 :         snd_pcm_group_lock_irq(group, nonatomic);
    2231                 :            : 
    2232                 :          0 :         relink_to_local(substream);
    2233                 :          0 :         refcount_dec(&group->refs);
    2234                 :            : 
    2235                 :            :         /* detach the last stream, too */
    2236         [ #  # ]:          0 :         if (list_is_singular(&group->substreams)) {
    2237                 :          0 :                 relink_to_local(list_first_entry(&group->substreams,
    2238                 :            :                                                  struct snd_pcm_substream,
    2239                 :            :                                                  link_list));
    2240                 :          0 :                 do_free = refcount_dec_and_test(&group->refs);
    2241                 :            :         }
    2242                 :            : 
    2243         [ #  # ]:          0 :         snd_pcm_group_unlock_irq(group, nonatomic);
    2244         [ #  # ]:          0 :         if (do_free)
    2245                 :          0 :                 kfree(group);
    2246                 :            : 
    2247                 :          0 :        _end:
    2248                 :          0 :         up_write(&snd_pcm_link_rwsem);
    2249                 :          0 :         return res;
    2250                 :            : }
    2251                 :            : 
    2252                 :            : /*
    2253                 :            :  * hw configurator
    2254                 :            :  */
    2255                 :          0 : static int snd_pcm_hw_rule_mul(struct snd_pcm_hw_params *params,
    2256                 :            :                                struct snd_pcm_hw_rule *rule)
    2257                 :            : {
    2258                 :          0 :         struct snd_interval t;
    2259                 :          0 :         snd_interval_mul(hw_param_interval_c(params, rule->deps[0]),
    2260                 :            :                      hw_param_interval_c(params, rule->deps[1]), &t);
    2261                 :          0 :         return snd_interval_refine(hw_param_interval(params, rule->var), &t);
    2262                 :            : }
    2263                 :            : 
    2264                 :          0 : static int snd_pcm_hw_rule_div(struct snd_pcm_hw_params *params,
    2265                 :            :                                struct snd_pcm_hw_rule *rule)
    2266                 :            : {
    2267                 :          0 :         struct snd_interval t;
    2268                 :          0 :         snd_interval_div(hw_param_interval_c(params, rule->deps[0]),
    2269                 :            :                      hw_param_interval_c(params, rule->deps[1]), &t);
    2270                 :          0 :         return snd_interval_refine(hw_param_interval(params, rule->var), &t);
    2271                 :            : }
    2272                 :            : 
    2273                 :          0 : static int snd_pcm_hw_rule_muldivk(struct snd_pcm_hw_params *params,
    2274                 :            :                                    struct snd_pcm_hw_rule *rule)
    2275                 :            : {
    2276                 :          0 :         struct snd_interval t;
    2277                 :          0 :         snd_interval_muldivk(hw_param_interval_c(params, rule->deps[0]),
    2278                 :            :                          hw_param_interval_c(params, rule->deps[1]),
    2279                 :          0 :                          (unsigned long) rule->private, &t);
    2280                 :          0 :         return snd_interval_refine(hw_param_interval(params, rule->var), &t);
    2281                 :            : }
    2282                 :            : 
    2283                 :          0 : static int snd_pcm_hw_rule_mulkdiv(struct snd_pcm_hw_params *params,
    2284                 :            :                                    struct snd_pcm_hw_rule *rule)
    2285                 :            : {
    2286                 :          0 :         struct snd_interval t;
    2287                 :          0 :         snd_interval_mulkdiv(hw_param_interval_c(params, rule->deps[0]),
    2288                 :          0 :                          (unsigned long) rule->private,
    2289                 :            :                          hw_param_interval_c(params, rule->deps[1]), &t);
    2290                 :          0 :         return snd_interval_refine(hw_param_interval(params, rule->var), &t);
    2291                 :            : }
    2292                 :            : 
    2293                 :          0 : static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params,
    2294                 :            :                                   struct snd_pcm_hw_rule *rule)
    2295                 :            : {
    2296                 :          0 :         unsigned int k;
    2297                 :          0 :         const struct snd_interval *i =
    2298                 :          0 :                                 hw_param_interval_c(params, rule->deps[0]);
    2299                 :          0 :         struct snd_mask m;
    2300                 :          0 :         struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
    2301                 :          0 :         snd_mask_any(&m);
    2302         [ #  # ]:          0 :         for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) {
    2303                 :          0 :                 int bits;
    2304         [ #  # ]:          0 :                 if (! snd_mask_test(mask, k))
    2305                 :          0 :                         continue;
    2306                 :          0 :                 bits = snd_pcm_format_physical_width(k);
    2307         [ #  # ]:          0 :                 if (bits <= 0)
    2308                 :          0 :                         continue; /* ignore invalid formats */
    2309   [ #  #  #  # ]:          0 :                 if ((unsigned)bits < i->min || (unsigned)bits > i->max)
    2310                 :          0 :                         snd_mask_reset(&m, k);
    2311                 :            :         }
    2312                 :          0 :         return snd_mask_refine(mask, &m);
    2313                 :            : }
    2314                 :            : 
    2315                 :          0 : static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params,
    2316                 :            :                                        struct snd_pcm_hw_rule *rule)
    2317                 :            : {
    2318                 :          0 :         struct snd_interval t;
    2319                 :          0 :         unsigned int k;
    2320                 :          0 :         t.min = UINT_MAX;
    2321                 :          0 :         t.max = 0;
    2322                 :          0 :         t.openmin = 0;
    2323                 :          0 :         t.openmax = 0;
    2324         [ #  # ]:          0 :         for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) {
    2325                 :          0 :                 int bits;
    2326         [ #  # ]:          0 :                 if (! snd_mask_test(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), k))
    2327                 :          0 :                         continue;
    2328                 :          0 :                 bits = snd_pcm_format_physical_width(k);
    2329         [ #  # ]:          0 :                 if (bits <= 0)
    2330                 :          0 :                         continue; /* ignore invalid formats */
    2331         [ #  # ]:          0 :                 if (t.min > (unsigned)bits)
    2332                 :          0 :                         t.min = bits;
    2333         [ #  # ]:          0 :                 if (t.max < (unsigned)bits)
    2334                 :          0 :                         t.max = bits;
    2335                 :            :         }
    2336                 :          0 :         t.integer = 1;
    2337                 :          0 :         return snd_interval_refine(hw_param_interval(params, rule->var), &t);
    2338                 :            : }
    2339                 :            : 
    2340                 :            : #if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12
    2341                 :            : #error "Change this table"
    2342                 :            : #endif
    2343                 :            : 
    2344                 :            : static const unsigned int rates[] = {
    2345                 :            :         5512, 8000, 11025, 16000, 22050, 32000, 44100,
    2346                 :            :         48000, 64000, 88200, 96000, 176400, 192000, 352800, 384000
    2347                 :            : };
    2348                 :            : 
    2349                 :            : const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = {
    2350                 :            :         .count = ARRAY_SIZE(rates),
    2351                 :            :         .list = rates,
    2352                 :            : };
    2353                 :            : 
    2354                 :          0 : static int snd_pcm_hw_rule_rate(struct snd_pcm_hw_params *params,
    2355                 :            :                                 struct snd_pcm_hw_rule *rule)
    2356                 :            : {
    2357                 :          0 :         struct snd_pcm_hardware *hw = rule->private;
    2358                 :          0 :         return snd_interval_list(hw_param_interval(params, rule->var),
    2359                 :            :                                  snd_pcm_known_rates.count,
    2360                 :            :                                  snd_pcm_known_rates.list, hw->rates);
    2361                 :            : }               
    2362                 :            : 
    2363                 :          0 : static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params,
    2364                 :            :                                             struct snd_pcm_hw_rule *rule)
    2365                 :            : {
    2366                 :          0 :         struct snd_interval t;
    2367                 :          0 :         struct snd_pcm_substream *substream = rule->private;
    2368                 :          0 :         t.min = 0;
    2369                 :          0 :         t.max = substream->buffer_bytes_max;
    2370                 :          0 :         t.openmin = 0;
    2371                 :          0 :         t.openmax = 0;
    2372                 :          0 :         t.integer = 1;
    2373                 :          0 :         return snd_interval_refine(hw_param_interval(params, rule->var), &t);
    2374                 :            : }               
    2375                 :            : 
    2376                 :            : static int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream)
    2377                 :            : {
    2378                 :            :         struct snd_pcm_runtime *runtime = substream->runtime;
    2379                 :            :         struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
    2380                 :            :         int k, err;
    2381                 :            : 
    2382                 :            :         for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) {
    2383                 :            :                 snd_mask_any(constrs_mask(constrs, k));
    2384                 :            :         }
    2385                 :            : 
    2386                 :            :         for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) {
    2387                 :            :                 snd_interval_any(constrs_interval(constrs, k));
    2388                 :            :         }
    2389                 :            : 
    2390                 :            :         snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_CHANNELS));
    2391                 :            :         snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_BUFFER_SIZE));
    2392                 :            :         snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_BUFFER_BYTES));
    2393                 :            :         snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_SAMPLE_BITS));
    2394                 :            :         snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_FRAME_BITS));
    2395                 :            : 
    2396                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
    2397                 :            :                                    snd_pcm_hw_rule_format, NULL,
    2398                 :            :                                    SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
    2399                 :            :         if (err < 0)
    2400                 :            :                 return err;
    2401                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 
    2402                 :            :                                   snd_pcm_hw_rule_sample_bits, NULL,
    2403                 :            :                                   SNDRV_PCM_HW_PARAM_FORMAT, 
    2404                 :            :                                   SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
    2405                 :            :         if (err < 0)
    2406                 :            :                 return err;
    2407                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 
    2408                 :            :                                   snd_pcm_hw_rule_div, NULL,
    2409                 :            :                                   SNDRV_PCM_HW_PARAM_FRAME_BITS, SNDRV_PCM_HW_PARAM_CHANNELS, -1);
    2410                 :            :         if (err < 0)
    2411                 :            :                 return err;
    2412                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS, 
    2413                 :            :                                   snd_pcm_hw_rule_mul, NULL,
    2414                 :            :                                   SNDRV_PCM_HW_PARAM_SAMPLE_BITS, SNDRV_PCM_HW_PARAM_CHANNELS, -1);
    2415                 :            :         if (err < 0)
    2416                 :            :                 return err;
    2417                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS, 
    2418                 :            :                                   snd_pcm_hw_rule_mulkdiv, (void*) 8,
    2419                 :            :                                   SNDRV_PCM_HW_PARAM_PERIOD_BYTES, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1);
    2420                 :            :         if (err < 0)
    2421                 :            :                 return err;
    2422                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS, 
    2423                 :            :                                   snd_pcm_hw_rule_mulkdiv, (void*) 8,
    2424                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_BYTES, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1);
    2425                 :            :         if (err < 0)
    2426                 :            :                 return err;
    2427                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 
    2428                 :            :                                   snd_pcm_hw_rule_div, NULL,
    2429                 :            :                                   SNDRV_PCM_HW_PARAM_FRAME_BITS, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
    2430                 :            :         if (err < 0)
    2431                 :            :                 return err;
    2432                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 
    2433                 :            :                                   snd_pcm_hw_rule_mulkdiv, (void*) 1000000,
    2434                 :            :                                   SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_PERIOD_TIME, -1);
    2435                 :            :         if (err < 0)
    2436                 :            :                 return err;
    2437                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 
    2438                 :            :                                   snd_pcm_hw_rule_mulkdiv, (void*) 1000000,
    2439                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_BUFFER_TIME, -1);
    2440                 :            :         if (err < 0)
    2441                 :            :                 return err;
    2442                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS, 
    2443                 :            :                                   snd_pcm_hw_rule_div, NULL,
    2444                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1);
    2445                 :            :         if (err < 0)
    2446                 :            :                 return err;
    2447                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 
    2448                 :            :                                   snd_pcm_hw_rule_div, NULL,
    2449                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_PERIODS, -1);
    2450                 :            :         if (err < 0)
    2451                 :            :                 return err;
    2452                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 
    2453                 :            :                                   snd_pcm_hw_rule_mulkdiv, (void*) 8,
    2454                 :            :                                   SNDRV_PCM_HW_PARAM_PERIOD_BYTES, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);
    2455                 :            :         if (err < 0)
    2456                 :            :                 return err;
    2457                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 
    2458                 :            :                                   snd_pcm_hw_rule_muldivk, (void*) 1000000,
    2459                 :            :                                   SNDRV_PCM_HW_PARAM_PERIOD_TIME, SNDRV_PCM_HW_PARAM_RATE, -1);
    2460                 :            :         if (err < 0)
    2461                 :            :                 return err;
    2462                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 
    2463                 :            :                                   snd_pcm_hw_rule_mul, NULL,
    2464                 :            :                                   SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_PERIODS, -1);
    2465                 :            :         if (err < 0)
    2466                 :            :                 return err;
    2467                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 
    2468                 :            :                                   snd_pcm_hw_rule_mulkdiv, (void*) 8,
    2469                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_BYTES, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);
    2470                 :            :         if (err < 0)
    2471                 :            :                 return err;
    2472                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 
    2473                 :            :                                   snd_pcm_hw_rule_muldivk, (void*) 1000000,
    2474                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_TIME, SNDRV_PCM_HW_PARAM_RATE, -1);
    2475                 :            :         if (err < 0)
    2476                 :            :                 return err;
    2477                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 
    2478                 :            :                                   snd_pcm_hw_rule_muldivk, (void*) 8,
    2479                 :            :                                   SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);
    2480                 :            :         if (err < 0)
    2481                 :            :                 return err;
    2482                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 
    2483                 :            :                                   snd_pcm_hw_rule_muldivk, (void*) 8,
    2484                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);
    2485                 :            :         if (err < 0)
    2486                 :            :                 return err;
    2487                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 
    2488                 :            :                                   snd_pcm_hw_rule_mulkdiv, (void*) 1000000,
    2489                 :            :                                   SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_RATE, -1);
    2490                 :            :         if (err < 0)
    2491                 :            :                 return err;
    2492                 :            :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_TIME, 
    2493                 :            :                                   snd_pcm_hw_rule_mulkdiv, (void*) 1000000,
    2494                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_RATE, -1);
    2495                 :            :         if (err < 0)
    2496                 :            :                 return err;
    2497                 :            :         return 0;
    2498                 :            : }
    2499                 :            : 
    2500                 :          0 : static int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
    2501                 :            : {
    2502                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    2503                 :          0 :         struct snd_pcm_hardware *hw = &runtime->hw;
    2504                 :          0 :         int err;
    2505                 :          0 :         unsigned int mask = 0;
    2506                 :            : 
    2507         [ #  # ]:          0 :         if (hw->info & SNDRV_PCM_INFO_INTERLEAVED)
    2508                 :          0 :                 mask |= 1 << SNDRV_PCM_ACCESS_RW_INTERLEAVED;
    2509         [ #  # ]:          0 :         if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED)
    2510                 :          0 :                 mask |= 1 << SNDRV_PCM_ACCESS_RW_NONINTERLEAVED;
    2511         [ #  # ]:          0 :         if (hw_support_mmap(substream)) {
    2512         [ #  # ]:          0 :                 if (hw->info & SNDRV_PCM_INFO_INTERLEAVED)
    2513                 :          0 :                         mask |= 1 << SNDRV_PCM_ACCESS_MMAP_INTERLEAVED;
    2514         [ #  # ]:          0 :                 if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED)
    2515                 :          0 :                         mask |= 1 << SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED;
    2516         [ #  # ]:          0 :                 if (hw->info & SNDRV_PCM_INFO_COMPLEX)
    2517                 :          0 :                         mask |= 1 << SNDRV_PCM_ACCESS_MMAP_COMPLEX;
    2518                 :            :         }
    2519                 :          0 :         err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_ACCESS, mask);
    2520         [ #  # ]:          0 :         if (err < 0)
    2521                 :            :                 return err;
    2522                 :            : 
    2523                 :          0 :         err = snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT, hw->formats);
    2524         [ #  # ]:          0 :         if (err < 0)
    2525                 :            :                 return err;
    2526                 :            : 
    2527                 :          0 :         err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1 << SNDRV_PCM_SUBFORMAT_STD);
    2528         [ #  # ]:          0 :         if (err < 0)
    2529                 :            :                 return err;
    2530                 :            : 
    2531                 :          0 :         err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS,
    2532                 :            :                                            hw->channels_min, hw->channels_max);
    2533         [ #  # ]:          0 :         if (err < 0)
    2534                 :            :                 return err;
    2535                 :            : 
    2536                 :          0 :         err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,
    2537                 :            :                                            hw->rate_min, hw->rate_max);
    2538         [ #  # ]:          0 :         if (err < 0)
    2539                 :            :                 return err;
    2540                 :            : 
    2541                 :          0 :         err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
    2542                 :          0 :                                            hw->period_bytes_min, hw->period_bytes_max);
    2543         [ #  # ]:          0 :         if (err < 0)
    2544                 :            :                 return err;
    2545                 :            : 
    2546                 :          0 :         err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS,
    2547                 :            :                                            hw->periods_min, hw->periods_max);
    2548         [ #  # ]:          0 :         if (err < 0)
    2549                 :            :                 return err;
    2550                 :            : 
    2551                 :          0 :         err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
    2552                 :          0 :                                            hw->period_bytes_min, hw->buffer_bytes_max);
    2553         [ #  # ]:          0 :         if (err < 0)
    2554                 :            :                 return err;
    2555                 :            : 
    2556                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 
    2557                 :            :                                   snd_pcm_hw_rule_buffer_bytes_max, substream,
    2558                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -1);
    2559         [ #  # ]:          0 :         if (err < 0)
    2560                 :            :                 return err;
    2561                 :            : 
    2562                 :            :         /* FIXME: remove */
    2563         [ #  # ]:          0 :         if (runtime->dma_bytes) {
    2564                 :          0 :                 err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 0, runtime->dma_bytes);
    2565         [ #  # ]:          0 :                 if (err < 0)
    2566                 :            :                         return err;
    2567                 :            :         }
    2568                 :            : 
    2569         [ #  # ]:          0 :         if (!(hw->rates & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))) {
    2570                 :          0 :                 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 
    2571                 :            :                                           snd_pcm_hw_rule_rate, hw,
    2572                 :            :                                           SNDRV_PCM_HW_PARAM_RATE, -1);
    2573         [ #  # ]:          0 :                 if (err < 0)
    2574                 :            :                         return err;
    2575                 :            :         }
    2576                 :            : 
    2577                 :            :         /* FIXME: this belong to lowlevel */
    2578                 :          0 :         snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
    2579                 :            : 
    2580                 :          0 :         return 0;
    2581                 :            : }
    2582                 :            : 
    2583                 :          0 : static void pcm_release_private(struct snd_pcm_substream *substream)
    2584                 :            : {
    2585         [ #  # ]:          0 :         if (snd_pcm_stream_linked(substream))
    2586                 :          0 :                 snd_pcm_unlink(substream);
    2587                 :          0 : }
    2588                 :            : 
    2589                 :          0 : void snd_pcm_release_substream(struct snd_pcm_substream *substream)
    2590                 :            : {
    2591                 :          0 :         substream->ref_count--;
    2592         [ #  # ]:          0 :         if (substream->ref_count > 0)
    2593                 :            :                 return;
    2594                 :            : 
    2595                 :          0 :         snd_pcm_drop(substream);
    2596         [ #  # ]:          0 :         if (substream->hw_opened) {
    2597         [ #  # ]:          0 :                 if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
    2598                 :          0 :                         do_hw_free(substream);
    2599                 :          0 :                 substream->ops->close(substream);
    2600                 :          0 :                 substream->hw_opened = 0;
    2601                 :            :         }
    2602         [ #  # ]:          0 :         if (pm_qos_request_active(&substream->latency_pm_qos_req))
    2603                 :          0 :                 pm_qos_remove_request(&substream->latency_pm_qos_req);
    2604         [ #  # ]:          0 :         if (substream->pcm_release) {
    2605                 :          0 :                 substream->pcm_release(substream);
    2606                 :          0 :                 substream->pcm_release = NULL;
    2607                 :            :         }
    2608                 :          0 :         snd_pcm_detach_substream(substream);
    2609                 :            : }
    2610                 :            : EXPORT_SYMBOL(snd_pcm_release_substream);
    2611                 :            : 
    2612                 :          0 : int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
    2613                 :            :                            struct file *file,
    2614                 :            :                            struct snd_pcm_substream **rsubstream)
    2615                 :            : {
    2616                 :          0 :         struct snd_pcm_substream *substream;
    2617                 :          0 :         int err;
    2618                 :            : 
    2619                 :          0 :         err = snd_pcm_attach_substream(pcm, stream, file, &substream);
    2620         [ #  # ]:          0 :         if (err < 0)
    2621                 :            :                 return err;
    2622         [ #  # ]:          0 :         if (substream->ref_count > 1) {
    2623                 :          0 :                 *rsubstream = substream;
    2624                 :          0 :                 return 0;
    2625                 :            :         }
    2626                 :            : 
    2627                 :          0 :         err = snd_pcm_hw_constraints_init(substream);
    2628         [ #  # ]:          0 :         if (err < 0) {
    2629                 :          0 :                 pcm_dbg(pcm, "snd_pcm_hw_constraints_init failed\n");
    2630                 :          0 :                 goto error;
    2631                 :            :         }
    2632                 :            : 
    2633         [ #  # ]:          0 :         if ((err = substream->ops->open(substream)) < 0)
    2634                 :          0 :                 goto error;
    2635                 :            : 
    2636                 :          0 :         substream->hw_opened = 1;
    2637                 :            : 
    2638                 :          0 :         err = snd_pcm_hw_constraints_complete(substream);
    2639         [ #  # ]:          0 :         if (err < 0) {
    2640                 :          0 :                 pcm_dbg(pcm, "snd_pcm_hw_constraints_complete failed\n");
    2641                 :          0 :                 goto error;
    2642                 :            :         }
    2643                 :            : 
    2644                 :          0 :         *rsubstream = substream;
    2645                 :          0 :         return 0;
    2646                 :            : 
    2647                 :          0 :  error:
    2648                 :          0 :         snd_pcm_release_substream(substream);
    2649                 :          0 :         return err;
    2650                 :            : }
    2651                 :            : EXPORT_SYMBOL(snd_pcm_open_substream);
    2652                 :            : 
    2653                 :          0 : static int snd_pcm_open_file(struct file *file,
    2654                 :            :                              struct snd_pcm *pcm,
    2655                 :            :                              int stream)
    2656                 :            : {
    2657                 :          0 :         struct snd_pcm_file *pcm_file;
    2658                 :          0 :         struct snd_pcm_substream *substream;
    2659                 :          0 :         int err;
    2660                 :            : 
    2661                 :          0 :         err = snd_pcm_open_substream(pcm, stream, file, &substream);
    2662         [ #  # ]:          0 :         if (err < 0)
    2663                 :            :                 return err;
    2664                 :            : 
    2665                 :          0 :         pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
    2666         [ #  # ]:          0 :         if (pcm_file == NULL) {
    2667                 :          0 :                 snd_pcm_release_substream(substream);
    2668                 :          0 :                 return -ENOMEM;
    2669                 :            :         }
    2670                 :          0 :         pcm_file->substream = substream;
    2671         [ #  # ]:          0 :         if (substream->ref_count == 1)
    2672                 :          0 :                 substream->pcm_release = pcm_release_private;
    2673                 :          0 :         file->private_data = pcm_file;
    2674                 :            : 
    2675                 :          0 :         return 0;
    2676                 :            : }
    2677                 :            : 
    2678                 :          0 : static int snd_pcm_playback_open(struct inode *inode, struct file *file)
    2679                 :            : {
    2680                 :          0 :         struct snd_pcm *pcm;
    2681                 :          0 :         int err = nonseekable_open(inode, file);
    2682         [ #  # ]:          0 :         if (err < 0)
    2683                 :            :                 return err;
    2684                 :          0 :         pcm = snd_lookup_minor_data(iminor(inode),
    2685                 :            :                                     SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
    2686                 :          0 :         err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
    2687         [ #  # ]:          0 :         if (pcm)
    2688                 :          0 :                 snd_card_unref(pcm->card);
    2689                 :            :         return err;
    2690                 :            : }
    2691                 :            : 
    2692                 :          0 : static int snd_pcm_capture_open(struct inode *inode, struct file *file)
    2693                 :            : {
    2694                 :          0 :         struct snd_pcm *pcm;
    2695                 :          0 :         int err = nonseekable_open(inode, file);
    2696         [ #  # ]:          0 :         if (err < 0)
    2697                 :            :                 return err;
    2698                 :          0 :         pcm = snd_lookup_minor_data(iminor(inode),
    2699                 :            :                                     SNDRV_DEVICE_TYPE_PCM_CAPTURE);
    2700                 :          0 :         err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
    2701         [ #  # ]:          0 :         if (pcm)
    2702                 :          0 :                 snd_card_unref(pcm->card);
    2703                 :            :         return err;
    2704                 :            : }
    2705                 :            : 
    2706                 :          0 : static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
    2707                 :            : {
    2708                 :          0 :         int err;
    2709                 :          0 :         wait_queue_entry_t wait;
    2710                 :            : 
    2711         [ #  # ]:          0 :         if (pcm == NULL) {
    2712                 :          0 :                 err = -ENODEV;
    2713                 :          0 :                 goto __error1;
    2714                 :            :         }
    2715                 :          0 :         err = snd_card_file_add(pcm->card, file);
    2716         [ #  # ]:          0 :         if (err < 0)
    2717                 :          0 :                 goto __error1;
    2718         [ #  # ]:          0 :         if (!try_module_get(pcm->card->module)) {
    2719                 :          0 :                 err = -EFAULT;
    2720                 :          0 :                 goto __error2;
    2721                 :            :         }
    2722                 :          0 :         init_waitqueue_entry(&wait, current);
    2723                 :          0 :         add_wait_queue(&pcm->open_wait, &wait);
    2724                 :          0 :         mutex_lock(&pcm->open_mutex);
    2725                 :          0 :         while (1) {
    2726                 :          0 :                 err = snd_pcm_open_file(file, pcm, stream);
    2727         [ #  # ]:          0 :                 if (err >= 0)
    2728                 :            :                         break;
    2729         [ #  # ]:          0 :                 if (err == -EAGAIN) {
    2730         [ #  # ]:          0 :                         if (file->f_flags & O_NONBLOCK) {
    2731                 :            :                                 err = -EBUSY;
    2732                 :            :                                 break;
    2733                 :            :                         }
    2734                 :            :                 } else
    2735                 :            :                         break;
    2736                 :          0 :                 set_current_state(TASK_INTERRUPTIBLE);
    2737                 :          0 :                 mutex_unlock(&pcm->open_mutex);
    2738                 :          0 :                 schedule();
    2739                 :          0 :                 mutex_lock(&pcm->open_mutex);
    2740         [ #  # ]:          0 :                 if (pcm->card->shutdown) {
    2741                 :            :                         err = -ENODEV;
    2742                 :            :                         break;
    2743                 :            :                 }
    2744         [ #  # ]:          0 :                 if (signal_pending(current)) {
    2745                 :            :                         err = -ERESTARTSYS;
    2746                 :            :                         break;
    2747                 :            :                 }
    2748                 :            :         }
    2749                 :          0 :         remove_wait_queue(&pcm->open_wait, &wait);
    2750                 :          0 :         mutex_unlock(&pcm->open_mutex);
    2751         [ #  # ]:          0 :         if (err < 0)
    2752                 :          0 :                 goto __error;
    2753                 :            :         return err;
    2754                 :            : 
    2755                 :            :       __error:
    2756                 :          0 :         module_put(pcm->card->module);
    2757                 :          0 :       __error2:
    2758                 :          0 :         snd_card_file_remove(pcm->card, file);
    2759                 :            :       __error1:
    2760                 :            :         return err;
    2761                 :            : }
    2762                 :            : 
    2763                 :          0 : static int snd_pcm_release(struct inode *inode, struct file *file)
    2764                 :            : {
    2765                 :          0 :         struct snd_pcm *pcm;
    2766                 :          0 :         struct snd_pcm_substream *substream;
    2767                 :          0 :         struct snd_pcm_file *pcm_file;
    2768                 :            : 
    2769                 :          0 :         pcm_file = file->private_data;
    2770                 :          0 :         substream = pcm_file->substream;
    2771         [ #  # ]:          0 :         if (snd_BUG_ON(!substream))
    2772                 :            :                 return -ENXIO;
    2773                 :          0 :         pcm = substream->pcm;
    2774                 :          0 :         mutex_lock(&pcm->open_mutex);
    2775                 :          0 :         snd_pcm_release_substream(substream);
    2776                 :          0 :         kfree(pcm_file);
    2777                 :          0 :         mutex_unlock(&pcm->open_mutex);
    2778                 :          0 :         wake_up(&pcm->open_wait);
    2779                 :          0 :         module_put(pcm->card->module);
    2780                 :          0 :         snd_card_file_remove(pcm->card, file);
    2781                 :          0 :         return 0;
    2782                 :            : }
    2783                 :            : 
    2784                 :            : /* check and update PCM state; return 0 or a negative error
    2785                 :            :  * call this inside PCM lock
    2786                 :            :  */
    2787                 :          0 : static int do_pcm_hwsync(struct snd_pcm_substream *substream)
    2788                 :            : {
    2789   [ #  #  #  #  :          0 :         switch (substream->runtime->status->state) {
                   #  # ]
    2790                 :          0 :         case SNDRV_PCM_STATE_DRAINING:
    2791         [ #  # ]:          0 :                 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
    2792                 :            :                         return -EBADFD;
    2793                 :            :                 /* Fall through */
    2794                 :            :         case SNDRV_PCM_STATE_RUNNING:
    2795                 :          0 :                 return snd_pcm_update_hw_ptr(substream);
    2796                 :            :         case SNDRV_PCM_STATE_PREPARED:
    2797                 :            :         case SNDRV_PCM_STATE_PAUSED:
    2798                 :            :                 return 0;
    2799                 :          0 :         case SNDRV_PCM_STATE_SUSPENDED:
    2800                 :          0 :                 return -ESTRPIPE;
    2801                 :          0 :         case SNDRV_PCM_STATE_XRUN:
    2802                 :          0 :                 return -EPIPE;
    2803                 :          0 :         default:
    2804                 :          0 :                 return -EBADFD;
    2805                 :            :         }
    2806                 :            : }
    2807                 :            : 
    2808                 :            : /* increase the appl_ptr; returns the processed frames or a negative error */
    2809                 :          0 : static snd_pcm_sframes_t forward_appl_ptr(struct snd_pcm_substream *substream,
    2810                 :            :                                           snd_pcm_uframes_t frames,
    2811                 :            :                                            snd_pcm_sframes_t avail)
    2812                 :            : {
    2813                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    2814                 :          0 :         snd_pcm_sframes_t appl_ptr;
    2815                 :          0 :         int ret;
    2816                 :            : 
    2817         [ #  # ]:          0 :         if (avail <= 0)
    2818                 :            :                 return 0;
    2819                 :          0 :         if (frames > (snd_pcm_uframes_t)avail)
    2820                 :            :                 frames = avail;
    2821                 :          0 :         appl_ptr = runtime->control->appl_ptr + frames;
    2822         [ #  # ]:          0 :         if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
    2823                 :          0 :                 appl_ptr -= runtime->boundary;
    2824                 :          0 :         ret = pcm_lib_apply_appl_ptr(substream, appl_ptr);
    2825         [ #  # ]:          0 :         return ret < 0 ? ret : frames;
    2826                 :            : }
    2827                 :            : 
    2828                 :            : /* decrease the appl_ptr; returns the processed frames or zero for error */
    2829                 :          0 : static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream,
    2830                 :            :                                          snd_pcm_uframes_t frames,
    2831                 :            :                                          snd_pcm_sframes_t avail)
    2832                 :            : {
    2833                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    2834                 :          0 :         snd_pcm_sframes_t appl_ptr;
    2835                 :          0 :         int ret;
    2836                 :            : 
    2837         [ #  # ]:          0 :         if (avail <= 0)
    2838                 :            :                 return 0;
    2839                 :          0 :         if (frames > (snd_pcm_uframes_t)avail)
    2840                 :            :                 frames = avail;
    2841                 :          0 :         appl_ptr = runtime->control->appl_ptr - frames;
    2842         [ #  # ]:          0 :         if (appl_ptr < 0)
    2843                 :          0 :                 appl_ptr += runtime->boundary;
    2844                 :          0 :         ret = pcm_lib_apply_appl_ptr(substream, appl_ptr);
    2845                 :            :         /* NOTE: we return zero for errors because PulseAudio gets depressed
    2846                 :            :          * upon receiving an error from rewind ioctl and stops processing
    2847                 :            :          * any longer.  Returning zero means that no rewind is done, so
    2848                 :            :          * it's not absolutely wrong to answer like that.
    2849                 :            :          */
    2850         [ #  # ]:          0 :         return ret < 0 ? 0 : frames;
    2851                 :            : }
    2852                 :            : 
    2853                 :          0 : static snd_pcm_sframes_t snd_pcm_rewind(struct snd_pcm_substream *substream,
    2854                 :            :                                         snd_pcm_uframes_t frames)
    2855                 :            : {
    2856                 :          0 :         snd_pcm_sframes_t ret;
    2857                 :            : 
    2858         [ #  # ]:          0 :         if (frames == 0)
    2859                 :            :                 return 0;
    2860                 :            : 
    2861                 :          0 :         snd_pcm_stream_lock_irq(substream);
    2862                 :          0 :         ret = do_pcm_hwsync(substream);
    2863         [ #  # ]:          0 :         if (!ret)
    2864                 :          0 :                 ret = rewind_appl_ptr(substream, frames,
    2865                 :          0 :                                       snd_pcm_hw_avail(substream));
    2866         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
    2867                 :            :         return ret;
    2868                 :            : }
    2869                 :            : 
    2870                 :          0 : static snd_pcm_sframes_t snd_pcm_forward(struct snd_pcm_substream *substream,
    2871                 :            :                                          snd_pcm_uframes_t frames)
    2872                 :            : {
    2873                 :          0 :         snd_pcm_sframes_t ret;
    2874                 :            : 
    2875         [ #  # ]:          0 :         if (frames == 0)
    2876                 :            :                 return 0;
    2877                 :            : 
    2878                 :          0 :         snd_pcm_stream_lock_irq(substream);
    2879                 :          0 :         ret = do_pcm_hwsync(substream);
    2880         [ #  # ]:          0 :         if (!ret)
    2881                 :          0 :                 ret = forward_appl_ptr(substream, frames,
    2882                 :          0 :                                        snd_pcm_avail(substream));
    2883         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
    2884                 :            :         return ret;
    2885                 :            : }
    2886                 :            : 
    2887                 :          0 : static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
    2888                 :            : {
    2889                 :          0 :         int err;
    2890                 :            : 
    2891                 :          0 :         snd_pcm_stream_lock_irq(substream);
    2892                 :          0 :         err = do_pcm_hwsync(substream);
    2893         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
    2894                 :          0 :         return err;
    2895                 :            : }
    2896                 :            :                 
    2897                 :          0 : static int snd_pcm_delay(struct snd_pcm_substream *substream,
    2898                 :            :                          snd_pcm_sframes_t *delay)
    2899                 :            : {
    2900                 :          0 :         int err;
    2901                 :          0 :         snd_pcm_sframes_t n = 0;
    2902                 :            : 
    2903                 :          0 :         snd_pcm_stream_lock_irq(substream);
    2904                 :          0 :         err = do_pcm_hwsync(substream);
    2905         [ #  # ]:          0 :         if (!err)
    2906                 :          0 :                 n = snd_pcm_calc_delay(substream);
    2907         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
    2908         [ #  # ]:          0 :         if (!err)
    2909                 :          0 :                 *delay = n;
    2910                 :          0 :         return err;
    2911                 :            : }
    2912                 :            :                 
    2913                 :          0 : static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
    2914                 :            :                             struct snd_pcm_sync_ptr __user *_sync_ptr)
    2915                 :            : {
    2916                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    2917                 :          0 :         struct snd_pcm_sync_ptr sync_ptr;
    2918                 :          0 :         volatile struct snd_pcm_mmap_status *status;
    2919                 :          0 :         volatile struct snd_pcm_mmap_control *control;
    2920                 :          0 :         int err;
    2921                 :            : 
    2922                 :          0 :         memset(&sync_ptr, 0, sizeof(sync_ptr));
    2923         [ #  # ]:          0 :         if (get_user(sync_ptr.flags, (unsigned __user *)&(_sync_ptr->flags)))
    2924                 :            :                 return -EFAULT;
    2925         [ #  # ]:          0 :         if (copy_from_user(&sync_ptr.c.control, &(_sync_ptr->c.control), sizeof(struct snd_pcm_mmap_control)))
    2926                 :            :                 return -EFAULT; 
    2927                 :          0 :         status = runtime->status;
    2928                 :          0 :         control = runtime->control;
    2929         [ #  # ]:          0 :         if (sync_ptr.flags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
    2930                 :          0 :                 err = snd_pcm_hwsync(substream);
    2931         [ #  # ]:          0 :                 if (err < 0)
    2932                 :            :                         return err;
    2933                 :            :         }
    2934                 :          0 :         snd_pcm_stream_lock_irq(substream);
    2935         [ #  # ]:          0 :         if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) {
    2936                 :          0 :                 err = pcm_lib_apply_appl_ptr(substream,
    2937                 :            :                                              sync_ptr.c.control.appl_ptr);
    2938         [ #  # ]:          0 :                 if (err < 0) {
    2939         [ #  # ]:          0 :                         snd_pcm_stream_unlock_irq(substream);
    2940                 :          0 :                         return err;
    2941                 :            :                 }
    2942                 :            :         } else {
    2943                 :          0 :                 sync_ptr.c.control.appl_ptr = control->appl_ptr;
    2944                 :            :         }
    2945         [ #  # ]:          0 :         if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
    2946                 :          0 :                 control->avail_min = sync_ptr.c.control.avail_min;
    2947                 :            :         else
    2948                 :          0 :                 sync_ptr.c.control.avail_min = control->avail_min;
    2949                 :          0 :         sync_ptr.s.status.state = status->state;
    2950                 :          0 :         sync_ptr.s.status.hw_ptr = status->hw_ptr;
    2951                 :          0 :         sync_ptr.s.status.tstamp = status->tstamp;
    2952                 :          0 :         sync_ptr.s.status.suspended_state = status->suspended_state;
    2953                 :          0 :         sync_ptr.s.status.audio_tstamp = status->audio_tstamp;
    2954         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
    2955         [ #  # ]:          0 :         if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr)))
    2956                 :          0 :                 return -EFAULT;
    2957                 :            :         return 0;
    2958                 :            : }
    2959                 :            : 
    2960                 :            : struct snd_pcm_mmap_status32 {
    2961                 :            :         snd_pcm_state_t state;
    2962                 :            :         s32 pad1;
    2963                 :            :         u32 hw_ptr;
    2964                 :            :         s32 tstamp_sec;
    2965                 :            :         s32 tstamp_nsec;
    2966                 :            :         snd_pcm_state_t suspended_state;
    2967                 :            :         s32 audio_tstamp_sec;
    2968                 :            :         s32 audio_tstamp_nsec;
    2969                 :            : } __attribute__((packed));
    2970                 :            : 
    2971                 :            : struct snd_pcm_mmap_control32 {
    2972                 :            :         u32 appl_ptr;
    2973                 :            :         u32 avail_min;
    2974                 :            : };
    2975                 :            : 
    2976                 :            : struct snd_pcm_sync_ptr32 {
    2977                 :            :         u32 flags;
    2978                 :            :         union {
    2979                 :            :                 struct snd_pcm_mmap_status32 status;
    2980                 :            :                 unsigned char reserved[64];
    2981                 :            :         } s;
    2982                 :            :         union {
    2983                 :            :                 struct snd_pcm_mmap_control32 control;
    2984                 :            :                 unsigned char reserved[64];
    2985                 :            :         } c;
    2986                 :            : } __attribute__((packed));
    2987                 :            : 
    2988                 :            : /* recalcuate the boundary within 32bit */
    2989                 :          0 : static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime)
    2990                 :            : {
    2991                 :          0 :         snd_pcm_uframes_t boundary;
    2992                 :            : 
    2993   [ #  #  #  # ]:          0 :         if (! runtime->buffer_size)
    2994                 :            :                 return 0;
    2995                 :            :         boundary = runtime->buffer_size;
    2996   [ #  #  #  #  :          0 :         while (boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
                   #  # ]
    2997                 :            :                 boundary *= 2;
    2998                 :            :         return boundary;
    2999                 :            : }
    3000                 :            : 
    3001                 :          0 : static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
    3002                 :            :                                          struct snd_pcm_sync_ptr32 __user *src)
    3003                 :            : {
    3004                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    3005                 :          0 :         volatile struct snd_pcm_mmap_status *status;
    3006                 :          0 :         volatile struct snd_pcm_mmap_control *control;
    3007                 :          0 :         u32 sflags;
    3008                 :          0 :         struct snd_pcm_mmap_control scontrol;
    3009                 :          0 :         struct snd_pcm_mmap_status sstatus;
    3010                 :          0 :         snd_pcm_uframes_t boundary;
    3011                 :          0 :         int err;
    3012                 :            : 
    3013         [ #  # ]:          0 :         if (snd_BUG_ON(!runtime))
    3014                 :            :                 return -EINVAL;
    3015                 :            : 
    3016         [ #  # ]:          0 :         if (get_user(sflags, &src->flags) ||
    3017         [ #  # ]:          0 :             get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
    3018         [ #  # ]:          0 :             get_user(scontrol.avail_min, &src->c.control.avail_min))
    3019                 :          0 :                 return -EFAULT;
    3020         [ #  # ]:          0 :         if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
    3021                 :          0 :                 err = snd_pcm_hwsync(substream);
    3022         [ #  # ]:          0 :                 if (err < 0)
    3023                 :            :                         return err;
    3024                 :            :         }
    3025                 :          0 :         status = runtime->status;
    3026                 :          0 :         control = runtime->control;
    3027         [ #  # ]:          0 :         boundary = recalculate_boundary(runtime);
    3028         [ #  # ]:          0 :         if (! boundary)
    3029                 :          0 :                 boundary = 0x7fffffff;
    3030                 :          0 :         snd_pcm_stream_lock_irq(substream);
    3031                 :            :         /* FIXME: we should consider the boundary for the sync from app */
    3032         [ #  # ]:          0 :         if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
    3033                 :          0 :                 control->appl_ptr = scontrol.appl_ptr;
    3034                 :            :         else
    3035                 :          0 :                 scontrol.appl_ptr = control->appl_ptr % boundary;
    3036         [ #  # ]:          0 :         if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
    3037                 :          0 :                 control->avail_min = scontrol.avail_min;
    3038                 :            :         else
    3039                 :          0 :                 scontrol.avail_min = control->avail_min;
    3040                 :          0 :         sstatus.state = status->state;
    3041                 :          0 :         sstatus.hw_ptr = status->hw_ptr % boundary;
    3042                 :          0 :         sstatus.tstamp = status->tstamp;
    3043                 :          0 :         sstatus.suspended_state = status->suspended_state;
    3044                 :          0 :         sstatus.audio_tstamp = status->audio_tstamp;
    3045         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
    3046         [ #  # ]:          0 :         if (put_user(sstatus.state, &src->s.status.state) ||
    3047         [ #  # ]:          0 :             put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) ||
    3048         [ #  # ]:          0 :             put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp_sec) ||
    3049         [ #  # ]:          0 :             put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp_nsec) ||
    3050         [ #  # ]:          0 :             put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
    3051         [ #  # ]:          0 :             put_user(sstatus.audio_tstamp.tv_sec, &src->s.status.audio_tstamp_sec) ||
    3052         [ #  # ]:          0 :             put_user(sstatus.audio_tstamp.tv_nsec, &src->s.status.audio_tstamp_nsec) ||
    3053         [ #  # ]:          0 :             put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
    3054         [ #  # ]:          0 :             put_user(scontrol.avail_min, &src->c.control.avail_min))
    3055                 :          0 :                 return -EFAULT;
    3056                 :            : 
    3057                 :            :         return 0;
    3058                 :            : }
    3059                 :            : #define __SNDRV_PCM_IOCTL_SYNC_PTR32 _IOWR('A', 0x23, struct snd_pcm_sync_ptr32)
    3060                 :            : 
    3061                 :          0 : static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
    3062                 :            : {
    3063                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    3064                 :          0 :         int arg;
    3065                 :            :         
    3066         [ #  # ]:          0 :         if (get_user(arg, _arg))
    3067                 :            :                 return -EFAULT;
    3068         [ #  # ]:          0 :         if (arg < 0 || arg > SNDRV_PCM_TSTAMP_TYPE_LAST)
    3069                 :            :                 return -EINVAL;
    3070                 :          0 :         runtime->tstamp_type = arg;
    3071                 :          0 :         return 0;
    3072                 :            : }
    3073                 :            : 
    3074                 :          0 : static int snd_pcm_xferi_frames_ioctl(struct snd_pcm_substream *substream,
    3075                 :            :                                       struct snd_xferi __user *_xferi)
    3076                 :            : {
    3077                 :          0 :         struct snd_xferi xferi;
    3078                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    3079                 :          0 :         snd_pcm_sframes_t result;
    3080                 :            : 
    3081         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    3082                 :            :                 return -EBADFD;
    3083         [ #  # ]:          0 :         if (put_user(0, &_xferi->result))
    3084                 :            :                 return -EFAULT;
    3085         [ #  # ]:          0 :         if (copy_from_user(&xferi, _xferi, sizeof(xferi)))
    3086                 :            :                 return -EFAULT;
    3087         [ #  # ]:          0 :         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    3088                 :          0 :                 result = snd_pcm_lib_write(substream, xferi.buf, xferi.frames);
    3089                 :            :         else
    3090                 :          0 :                 result = snd_pcm_lib_read(substream, xferi.buf, xferi.frames);
    3091         [ #  # ]:          0 :         __put_user(result, &_xferi->result);
    3092                 :          0 :         return result < 0 ? result : 0;
    3093                 :            : }
    3094                 :            : 
    3095                 :          0 : static int snd_pcm_xfern_frames_ioctl(struct snd_pcm_substream *substream,
    3096                 :            :                                       struct snd_xfern __user *_xfern)
    3097                 :            : {
    3098                 :          0 :         struct snd_xfern xfern;
    3099                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    3100                 :          0 :         void *bufs;
    3101                 :          0 :         snd_pcm_sframes_t result;
    3102                 :            : 
    3103         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    3104                 :            :                 return -EBADFD;
    3105         [ #  # ]:          0 :         if (runtime->channels > 128)
    3106                 :            :                 return -EINVAL;
    3107         [ #  # ]:          0 :         if (put_user(0, &_xfern->result))
    3108                 :            :                 return -EFAULT;
    3109         [ #  # ]:          0 :         if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
    3110                 :            :                 return -EFAULT;
    3111                 :            : 
    3112                 :          0 :         bufs = memdup_user(xfern.bufs, sizeof(void *) * runtime->channels);
    3113         [ #  # ]:          0 :         if (IS_ERR(bufs))
    3114                 :          0 :                 return PTR_ERR(bufs);
    3115         [ #  # ]:          0 :         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    3116                 :          0 :                 result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
    3117                 :            :         else
    3118                 :          0 :                 result = snd_pcm_lib_readv(substream, bufs, xfern.frames);
    3119                 :          0 :         kfree(bufs);
    3120         [ #  # ]:          0 :         __put_user(result, &_xfern->result);
    3121                 :          0 :         return result < 0 ? result : 0;
    3122                 :            : }
    3123                 :            : 
    3124                 :          0 : static int snd_pcm_rewind_ioctl(struct snd_pcm_substream *substream,
    3125                 :            :                                 snd_pcm_uframes_t __user *_frames)
    3126                 :            : {
    3127                 :          0 :         snd_pcm_uframes_t frames;
    3128                 :          0 :         snd_pcm_sframes_t result;
    3129                 :            : 
    3130         [ #  # ]:          0 :         if (get_user(frames, _frames))
    3131                 :            :                 return -EFAULT;
    3132         [ #  # ]:          0 :         if (put_user(0, _frames))
    3133                 :            :                 return -EFAULT;
    3134                 :          0 :         result = snd_pcm_rewind(substream, frames);
    3135         [ #  # ]:          0 :         __put_user(result, _frames);
    3136                 :          0 :         return result < 0 ? result : 0;
    3137                 :            : }
    3138                 :            : 
    3139                 :          0 : static int snd_pcm_forward_ioctl(struct snd_pcm_substream *substream,
    3140                 :            :                                  snd_pcm_uframes_t __user *_frames)
    3141                 :            : {
    3142                 :          0 :         snd_pcm_uframes_t frames;
    3143                 :          0 :         snd_pcm_sframes_t result;
    3144                 :            : 
    3145         [ #  # ]:          0 :         if (get_user(frames, _frames))
    3146                 :            :                 return -EFAULT;
    3147         [ #  # ]:          0 :         if (put_user(0, _frames))
    3148                 :            :                 return -EFAULT;
    3149                 :          0 :         result = snd_pcm_forward(substream, frames);
    3150         [ #  # ]:          0 :         __put_user(result, _frames);
    3151                 :          0 :         return result < 0 ? result : 0;
    3152                 :            : }
    3153                 :            : 
    3154                 :          0 : static int snd_pcm_common_ioctl(struct file *file,
    3155                 :            :                                  struct snd_pcm_substream *substream,
    3156                 :            :                                  unsigned int cmd, void __user *arg)
    3157                 :            : {
    3158                 :          0 :         struct snd_pcm_file *pcm_file = file->private_data;
    3159                 :          0 :         int res;
    3160                 :            : 
    3161   [ #  #  #  #  :          0 :         if (PCM_RUNTIME_CHECK(substream))
                   #  # ]
    3162                 :            :                 return -ENXIO;
    3163                 :            : 
    3164                 :          0 :         res = snd_power_wait(substream->pcm->card, SNDRV_CTL_POWER_D0);
    3165         [ #  # ]:          0 :         if (res < 0)
    3166                 :            :                 return res;
    3167                 :            : 
    3168   [ #  #  #  #  :          0 :         switch (cmd) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3169                 :            :         case SNDRV_PCM_IOCTL_PVERSION:
    3170         [ #  # ]:          0 :                 return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0;
    3171                 :          0 :         case SNDRV_PCM_IOCTL_INFO:
    3172                 :          0 :                 return snd_pcm_info_user(substream, arg);
    3173                 :            :         case SNDRV_PCM_IOCTL_TSTAMP:    /* just for compatibility */
    3174                 :            :                 return 0;
    3175                 :          0 :         case SNDRV_PCM_IOCTL_TTSTAMP:
    3176                 :          0 :                 return snd_pcm_tstamp(substream, arg);
    3177                 :            :         case SNDRV_PCM_IOCTL_USER_PVERSION:
    3178         [ #  # ]:          0 :                 if (get_user(pcm_file->user_pversion,
    3179                 :            :                              (unsigned int __user *)arg))
    3180                 :          0 :                         return -EFAULT;
    3181                 :            :                 return 0;
    3182                 :          0 :         case SNDRV_PCM_IOCTL_HW_REFINE:
    3183                 :          0 :                 return snd_pcm_hw_refine_user(substream, arg);
    3184                 :          0 :         case SNDRV_PCM_IOCTL_HW_PARAMS:
    3185                 :          0 :                 return snd_pcm_hw_params_user(substream, arg);
    3186                 :          0 :         case SNDRV_PCM_IOCTL_HW_FREE:
    3187                 :          0 :                 return snd_pcm_hw_free(substream);
    3188                 :          0 :         case SNDRV_PCM_IOCTL_SW_PARAMS:
    3189                 :          0 :                 return snd_pcm_sw_params_user(substream, arg);
    3190                 :          0 :         case SNDRV_PCM_IOCTL_STATUS32:
    3191                 :          0 :                 return snd_pcm_status_user32(substream, arg, false);
    3192                 :          0 :         case SNDRV_PCM_IOCTL_STATUS_EXT32:
    3193                 :          0 :                 return snd_pcm_status_user32(substream, arg, true);
    3194                 :          0 :         case SNDRV_PCM_IOCTL_STATUS64:
    3195                 :          0 :                 return snd_pcm_status_user64(substream, arg, false);
    3196                 :          0 :         case SNDRV_PCM_IOCTL_STATUS_EXT64:
    3197                 :          0 :                 return snd_pcm_status_user64(substream, arg, true);
    3198                 :          0 :         case SNDRV_PCM_IOCTL_CHANNEL_INFO:
    3199                 :          0 :                 return snd_pcm_channel_info_user(substream, arg);
    3200                 :          0 :         case SNDRV_PCM_IOCTL_PREPARE:
    3201                 :          0 :                 return snd_pcm_prepare(substream, file);
    3202                 :            :         case SNDRV_PCM_IOCTL_RESET:
    3203                 :          0 :                 return snd_pcm_reset(substream);
    3204                 :            :         case SNDRV_PCM_IOCTL_START:
    3205                 :          0 :                 return snd_pcm_start_lock_irq(substream);
    3206                 :          0 :         case SNDRV_PCM_IOCTL_LINK:
    3207                 :          0 :                 return snd_pcm_link(substream, (int)(unsigned long) arg);
    3208                 :          0 :         case SNDRV_PCM_IOCTL_UNLINK:
    3209                 :          0 :                 return snd_pcm_unlink(substream);
    3210                 :            :         case SNDRV_PCM_IOCTL_RESUME:
    3211                 :          0 :                 return snd_pcm_resume(substream);
    3212                 :          0 :         case SNDRV_PCM_IOCTL_XRUN:
    3213                 :          0 :                 return snd_pcm_xrun(substream);
    3214                 :          0 :         case SNDRV_PCM_IOCTL_HWSYNC:
    3215                 :          0 :                 return snd_pcm_hwsync(substream);
    3216                 :          0 :         case SNDRV_PCM_IOCTL_DELAY:
    3217                 :            :         {
    3218                 :          0 :                 snd_pcm_sframes_t delay;
    3219                 :          0 :                 snd_pcm_sframes_t __user *res = arg;
    3220                 :          0 :                 int err;
    3221                 :            : 
    3222                 :          0 :                 err = snd_pcm_delay(substream, &delay);
    3223         [ #  # ]:          0 :                 if (err)
    3224                 :            :                         return err;
    3225         [ #  # ]:          0 :                 if (put_user(delay, res))
    3226                 :          0 :                         return -EFAULT;
    3227                 :            :                 return 0;
    3228                 :            :         }
    3229                 :          0 :         case __SNDRV_PCM_IOCTL_SYNC_PTR32:
    3230                 :          0 :                 return snd_pcm_ioctl_sync_ptr_compat(substream, arg);
    3231                 :          0 :         case __SNDRV_PCM_IOCTL_SYNC_PTR64:
    3232                 :          0 :                 return snd_pcm_sync_ptr(substream, arg);
    3233                 :            : #ifdef CONFIG_SND_SUPPORT_OLD_API
    3234                 :          0 :         case SNDRV_PCM_IOCTL_HW_REFINE_OLD:
    3235                 :          0 :                 return snd_pcm_hw_refine_old_user(substream, arg);
    3236                 :          0 :         case SNDRV_PCM_IOCTL_HW_PARAMS_OLD:
    3237                 :          0 :                 return snd_pcm_hw_params_old_user(substream, arg);
    3238                 :            : #endif
    3239                 :          0 :         case SNDRV_PCM_IOCTL_DRAIN:
    3240                 :          0 :                 return snd_pcm_drain(substream, file);
    3241                 :          0 :         case SNDRV_PCM_IOCTL_DROP:
    3242                 :          0 :                 return snd_pcm_drop(substream);
    3243                 :          0 :         case SNDRV_PCM_IOCTL_PAUSE:
    3244                 :          0 :                 return snd_pcm_pause_lock_irq(substream, (unsigned long)arg);
    3245                 :          0 :         case SNDRV_PCM_IOCTL_WRITEI_FRAMES:
    3246                 :            :         case SNDRV_PCM_IOCTL_READI_FRAMES:
    3247                 :          0 :                 return snd_pcm_xferi_frames_ioctl(substream, arg);
    3248                 :          0 :         case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
    3249                 :            :         case SNDRV_PCM_IOCTL_READN_FRAMES:
    3250                 :          0 :                 return snd_pcm_xfern_frames_ioctl(substream, arg);
    3251                 :          0 :         case SNDRV_PCM_IOCTL_REWIND:
    3252                 :          0 :                 return snd_pcm_rewind_ioctl(substream, arg);
    3253                 :          0 :         case SNDRV_PCM_IOCTL_FORWARD:
    3254                 :          0 :                 return snd_pcm_forward_ioctl(substream, arg);
    3255                 :            :         }
    3256                 :          0 :         pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd);
    3257                 :          0 :         return -ENOTTY;
    3258                 :            : }
    3259                 :            : 
    3260                 :          0 : static long snd_pcm_ioctl(struct file *file, unsigned int cmd,
    3261                 :            :                           unsigned long arg)
    3262                 :            : {
    3263                 :          0 :         struct snd_pcm_file *pcm_file;
    3264                 :            : 
    3265                 :          0 :         pcm_file = file->private_data;
    3266                 :            : 
    3267         [ #  # ]:          0 :         if (((cmd >> 8) & 0xff) != 'A')
    3268                 :            :                 return -ENOTTY;
    3269                 :            : 
    3270                 :          0 :         return snd_pcm_common_ioctl(file, pcm_file->substream, cmd,
    3271                 :            :                                      (void __user *)arg);
    3272                 :            : }
    3273                 :            : 
    3274                 :            : /**
    3275                 :            :  * snd_pcm_kernel_ioctl - Execute PCM ioctl in the kernel-space
    3276                 :            :  * @substream: PCM substream
    3277                 :            :  * @cmd: IOCTL cmd
    3278                 :            :  * @arg: IOCTL argument
    3279                 :            :  *
    3280                 :            :  * The function is provided primarily for OSS layer and USB gadget drivers,
    3281                 :            :  * and it allows only the limited set of ioctls (hw_params, sw_params,
    3282                 :            :  * prepare, start, drain, drop, forward).
    3283                 :            :  */
    3284                 :          0 : int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
    3285                 :            :                          unsigned int cmd, void *arg)
    3286                 :            : {
    3287                 :          0 :         snd_pcm_uframes_t *frames = arg;
    3288                 :          0 :         snd_pcm_sframes_t result;
    3289                 :            :         
    3290   [ #  #  #  #  :          0 :         switch (cmd) {
             #  #  #  #  
                      # ]
    3291                 :          0 :         case SNDRV_PCM_IOCTL_FORWARD:
    3292                 :            :         {
    3293                 :            :                 /* provided only for OSS; capture-only and no value returned */
    3294         [ #  # ]:          0 :                 if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
    3295                 :            :                         return -EINVAL;
    3296                 :          0 :                 result = snd_pcm_forward(substream, *frames);
    3297                 :          0 :                 return result < 0 ? result : 0;
    3298                 :            :         }
    3299                 :          0 :         case SNDRV_PCM_IOCTL_HW_PARAMS:
    3300                 :          0 :                 return snd_pcm_hw_params(substream, arg);
    3301                 :          0 :         case SNDRV_PCM_IOCTL_SW_PARAMS:
    3302                 :          0 :                 return snd_pcm_sw_params(substream, arg);
    3303                 :          0 :         case SNDRV_PCM_IOCTL_PREPARE:
    3304                 :          0 :                 return snd_pcm_prepare(substream, NULL);
    3305                 :            :         case SNDRV_PCM_IOCTL_START:
    3306                 :          0 :                 return snd_pcm_start_lock_irq(substream);
    3307                 :          0 :         case SNDRV_PCM_IOCTL_DRAIN:
    3308                 :          0 :                 return snd_pcm_drain(substream, NULL);
    3309                 :          0 :         case SNDRV_PCM_IOCTL_DROP:
    3310                 :          0 :                 return snd_pcm_drop(substream);
    3311                 :          0 :         case SNDRV_PCM_IOCTL_DELAY:
    3312                 :          0 :                 return snd_pcm_delay(substream, frames);
    3313                 :            :         default:
    3314                 :            :                 return -EINVAL;
    3315                 :            :         }
    3316                 :            : }
    3317                 :            : EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
    3318                 :            : 
    3319                 :          0 : static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
    3320                 :            :                             loff_t * offset)
    3321                 :            : {
    3322                 :          0 :         struct snd_pcm_file *pcm_file;
    3323                 :          0 :         struct snd_pcm_substream *substream;
    3324                 :          0 :         struct snd_pcm_runtime *runtime;
    3325                 :          0 :         snd_pcm_sframes_t result;
    3326                 :            : 
    3327                 :          0 :         pcm_file = file->private_data;
    3328                 :          0 :         substream = pcm_file->substream;
    3329   [ #  #  #  #  :          0 :         if (PCM_RUNTIME_CHECK(substream))
                   #  # ]
    3330                 :            :                 return -ENXIO;
    3331                 :          0 :         runtime = substream->runtime;
    3332         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    3333                 :            :                 return -EBADFD;
    3334         [ #  # ]:          0 :         if (!frame_aligned(runtime, count))
    3335                 :            :                 return -EINVAL;
    3336                 :          0 :         count = bytes_to_frames(runtime, count);
    3337                 :          0 :         result = snd_pcm_lib_read(substream, buf, count);
    3338         [ #  # ]:          0 :         if (result > 0)
    3339                 :          0 :                 result = frames_to_bytes(runtime, result);
    3340                 :            :         return result;
    3341                 :            : }
    3342                 :            : 
    3343                 :          0 : static ssize_t snd_pcm_write(struct file *file, const char __user *buf,
    3344                 :            :                              size_t count, loff_t * offset)
    3345                 :            : {
    3346                 :          0 :         struct snd_pcm_file *pcm_file;
    3347                 :          0 :         struct snd_pcm_substream *substream;
    3348                 :          0 :         struct snd_pcm_runtime *runtime;
    3349                 :          0 :         snd_pcm_sframes_t result;
    3350                 :            : 
    3351                 :          0 :         pcm_file = file->private_data;
    3352                 :          0 :         substream = pcm_file->substream;
    3353   [ #  #  #  #  :          0 :         if (PCM_RUNTIME_CHECK(substream))
                   #  # ]
    3354                 :            :                 return -ENXIO;
    3355                 :          0 :         runtime = substream->runtime;
    3356         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    3357                 :            :                 return -EBADFD;
    3358         [ #  # ]:          0 :         if (!frame_aligned(runtime, count))
    3359                 :            :                 return -EINVAL;
    3360                 :          0 :         count = bytes_to_frames(runtime, count);
    3361                 :          0 :         result = snd_pcm_lib_write(substream, buf, count);
    3362         [ #  # ]:          0 :         if (result > 0)
    3363                 :          0 :                 result = frames_to_bytes(runtime, result);
    3364                 :            :         return result;
    3365                 :            : }
    3366                 :            : 
    3367                 :          0 : static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to)
    3368                 :            : {
    3369                 :          0 :         struct snd_pcm_file *pcm_file;
    3370                 :          0 :         struct snd_pcm_substream *substream;
    3371                 :          0 :         struct snd_pcm_runtime *runtime;
    3372                 :          0 :         snd_pcm_sframes_t result;
    3373                 :          0 :         unsigned long i;
    3374                 :          0 :         void __user **bufs;
    3375                 :          0 :         snd_pcm_uframes_t frames;
    3376                 :            : 
    3377                 :          0 :         pcm_file = iocb->ki_filp->private_data;
    3378                 :          0 :         substream = pcm_file->substream;
    3379   [ #  #  #  #  :          0 :         if (PCM_RUNTIME_CHECK(substream))
                   #  # ]
    3380                 :            :                 return -ENXIO;
    3381                 :          0 :         runtime = substream->runtime;
    3382         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    3383                 :            :                 return -EBADFD;
    3384         [ #  # ]:          0 :         if (!iter_is_iovec(to))
    3385                 :            :                 return -EINVAL;
    3386   [ #  #  #  # ]:          0 :         if (to->nr_segs > 1024 || to->nr_segs != runtime->channels)
    3387                 :            :                 return -EINVAL;
    3388         [ #  # ]:          0 :         if (!frame_aligned(runtime, to->iov->iov_len))
    3389                 :            :                 return -EINVAL;
    3390                 :          0 :         frames = bytes_to_samples(runtime, to->iov->iov_len);
    3391                 :          0 :         bufs = kmalloc_array(to->nr_segs, sizeof(void *), GFP_KERNEL);
    3392         [ #  # ]:          0 :         if (bufs == NULL)
    3393                 :            :                 return -ENOMEM;
    3394         [ #  # ]:          0 :         for (i = 0; i < to->nr_segs; ++i)
    3395                 :          0 :                 bufs[i] = to->iov[i].iov_base;
    3396                 :          0 :         result = snd_pcm_lib_readv(substream, bufs, frames);
    3397         [ #  # ]:          0 :         if (result > 0)
    3398                 :          0 :                 result = frames_to_bytes(runtime, result);
    3399                 :          0 :         kfree(bufs);
    3400                 :          0 :         return result;
    3401                 :            : }
    3402                 :            : 
    3403                 :          0 : static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
    3404                 :            : {
    3405                 :          0 :         struct snd_pcm_file *pcm_file;
    3406                 :          0 :         struct snd_pcm_substream *substream;
    3407                 :          0 :         struct snd_pcm_runtime *runtime;
    3408                 :          0 :         snd_pcm_sframes_t result;
    3409                 :          0 :         unsigned long i;
    3410                 :          0 :         void __user **bufs;
    3411                 :          0 :         snd_pcm_uframes_t frames;
    3412                 :            : 
    3413                 :          0 :         pcm_file = iocb->ki_filp->private_data;
    3414                 :          0 :         substream = pcm_file->substream;
    3415   [ #  #  #  #  :          0 :         if (PCM_RUNTIME_CHECK(substream))
                   #  # ]
    3416                 :            :                 return -ENXIO;
    3417                 :          0 :         runtime = substream->runtime;
    3418         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    3419                 :            :                 return -EBADFD;
    3420         [ #  # ]:          0 :         if (!iter_is_iovec(from))
    3421                 :            :                 return -EINVAL;
    3422   [ #  #  #  #  :          0 :         if (from->nr_segs > 128 || from->nr_segs != runtime->channels ||
                   #  # ]
    3423         [ #  # ]:          0 :             !frame_aligned(runtime, from->iov->iov_len))
    3424                 :            :                 return -EINVAL;
    3425                 :          0 :         frames = bytes_to_samples(runtime, from->iov->iov_len);
    3426                 :          0 :         bufs = kmalloc_array(from->nr_segs, sizeof(void *), GFP_KERNEL);
    3427         [ #  # ]:          0 :         if (bufs == NULL)
    3428                 :            :                 return -ENOMEM;
    3429         [ #  # ]:          0 :         for (i = 0; i < from->nr_segs; ++i)
    3430                 :          0 :                 bufs[i] = from->iov[i].iov_base;
    3431                 :          0 :         result = snd_pcm_lib_writev(substream, bufs, frames);
    3432         [ #  # ]:          0 :         if (result > 0)
    3433                 :          0 :                 result = frames_to_bytes(runtime, result);
    3434                 :          0 :         kfree(bufs);
    3435                 :          0 :         return result;
    3436                 :            : }
    3437                 :            : 
    3438                 :          0 : static __poll_t snd_pcm_poll(struct file *file, poll_table *wait)
    3439                 :            : {
    3440                 :          0 :         struct snd_pcm_file *pcm_file;
    3441                 :          0 :         struct snd_pcm_substream *substream;
    3442                 :          0 :         struct snd_pcm_runtime *runtime;
    3443                 :          0 :         __poll_t mask, ok;
    3444                 :          0 :         snd_pcm_uframes_t avail;
    3445                 :            : 
    3446                 :          0 :         pcm_file = file->private_data;
    3447                 :            : 
    3448                 :          0 :         substream = pcm_file->substream;
    3449         [ #  # ]:          0 :         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    3450                 :            :                 ok = EPOLLOUT | EPOLLWRNORM;
    3451                 :            :         else
    3452                 :          0 :                 ok = EPOLLIN | EPOLLRDNORM;
    3453   [ #  #  #  #  :          0 :         if (PCM_RUNTIME_CHECK(substream))
                   #  # ]
    3454                 :          0 :                 return ok | EPOLLERR;
    3455                 :            : 
    3456                 :          0 :         runtime = substream->runtime;
    3457         [ #  # ]:          0 :         poll_wait(file, &runtime->sleep, wait);
    3458                 :            : 
    3459                 :          0 :         mask = 0;
    3460                 :          0 :         snd_pcm_stream_lock_irq(substream);
    3461                 :          0 :         avail = snd_pcm_avail(substream);
    3462      [ #  #  # ]:          0 :         switch (runtime->status->state) {
    3463                 :          0 :         case SNDRV_PCM_STATE_RUNNING:
    3464                 :            :         case SNDRV_PCM_STATE_PREPARED:
    3465                 :            :         case SNDRV_PCM_STATE_PAUSED:
    3466         [ #  # ]:          0 :                 if (avail >= runtime->control->avail_min)
    3467                 :          0 :                         mask = ok;
    3468                 :            :                 break;
    3469                 :          0 :         case SNDRV_PCM_STATE_DRAINING:
    3470         [ #  # ]:          0 :                 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
    3471                 :          0 :                         mask = ok;
    3472         [ #  # ]:          0 :                         if (!avail)
    3473                 :          0 :                                 mask |= EPOLLERR;
    3474                 :            :                 }
    3475                 :            :                 break;
    3476                 :          0 :         default:
    3477                 :          0 :                 mask = ok | EPOLLERR;
    3478                 :          0 :                 break;
    3479                 :            :         }
    3480         [ #  # ]:          0 :         snd_pcm_stream_unlock_irq(substream);
    3481                 :            :         return mask;
    3482                 :            : }
    3483                 :            : 
    3484                 :            : /*
    3485                 :            :  * mmap support
    3486                 :            :  */
    3487                 :            : 
    3488                 :            : /*
    3489                 :            :  * Only on coherent architectures, we can mmap the status and the control records
    3490                 :            :  * for effcient data transfer.  On others, we have to use HWSYNC ioctl...
    3491                 :            :  */
    3492                 :            : #if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA)
    3493                 :            : /*
    3494                 :            :  * mmap status record
    3495                 :            :  */
    3496                 :          0 : static vm_fault_t snd_pcm_mmap_status_fault(struct vm_fault *vmf)
    3497                 :            : {
    3498                 :          0 :         struct snd_pcm_substream *substream = vmf->vma->vm_private_data;
    3499                 :          0 :         struct snd_pcm_runtime *runtime;
    3500                 :            :         
    3501         [ #  # ]:          0 :         if (substream == NULL)
    3502                 :            :                 return VM_FAULT_SIGBUS;
    3503                 :          0 :         runtime = substream->runtime;
    3504         [ #  # ]:          0 :         vmf->page = virt_to_page(runtime->status);
    3505         [ #  # ]:          0 :         get_page(vmf->page);
    3506                 :          0 :         return 0;
    3507                 :            : }
    3508                 :            : 
    3509                 :            : static const struct vm_operations_struct snd_pcm_vm_ops_status =
    3510                 :            : {
    3511                 :            :         .fault =        snd_pcm_mmap_status_fault,
    3512                 :            : };
    3513                 :            : 
    3514                 :          0 : static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
    3515                 :            :                                struct vm_area_struct *area)
    3516                 :            : {
    3517                 :          0 :         long size;
    3518                 :          0 :         if (!(area->vm_flags & VM_READ))
    3519                 :            :                 return -EINVAL;
    3520                 :          0 :         size = area->vm_end - area->vm_start;
    3521         [ #  # ]:          0 :         if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)))
    3522                 :            :                 return -EINVAL;
    3523                 :          0 :         area->vm_ops = &snd_pcm_vm_ops_status;
    3524                 :          0 :         area->vm_private_data = substream;
    3525                 :          0 :         area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
    3526                 :          0 :         return 0;
    3527                 :            : }
    3528                 :            : 
    3529                 :            : /*
    3530                 :            :  * mmap control record
    3531                 :            :  */
    3532                 :          0 : static vm_fault_t snd_pcm_mmap_control_fault(struct vm_fault *vmf)
    3533                 :            : {
    3534                 :          0 :         struct snd_pcm_substream *substream = vmf->vma->vm_private_data;
    3535                 :          0 :         struct snd_pcm_runtime *runtime;
    3536                 :            :         
    3537         [ #  # ]:          0 :         if (substream == NULL)
    3538                 :            :                 return VM_FAULT_SIGBUS;
    3539                 :          0 :         runtime = substream->runtime;
    3540         [ #  # ]:          0 :         vmf->page = virt_to_page(runtime->control);
    3541         [ #  # ]:          0 :         get_page(vmf->page);
    3542                 :          0 :         return 0;
    3543                 :            : }
    3544                 :            : 
    3545                 :            : static const struct vm_operations_struct snd_pcm_vm_ops_control =
    3546                 :            : {
    3547                 :            :         .fault =        snd_pcm_mmap_control_fault,
    3548                 :            : };
    3549                 :            : 
    3550                 :          0 : static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
    3551                 :            :                                 struct vm_area_struct *area)
    3552                 :            : {
    3553                 :          0 :         long size;
    3554                 :          0 :         if (!(area->vm_flags & VM_READ))
    3555                 :            :                 return -EINVAL;
    3556                 :          0 :         size = area->vm_end - area->vm_start;
    3557         [ #  # ]:          0 :         if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)))
    3558                 :            :                 return -EINVAL;
    3559                 :          0 :         area->vm_ops = &snd_pcm_vm_ops_control;
    3560                 :          0 :         area->vm_private_data = substream;
    3561                 :          0 :         area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
    3562                 :          0 :         return 0;
    3563                 :            : }
    3564                 :            : 
    3565                 :          0 : static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file)
    3566                 :            : {
    3567                 :            :         /* See pcm_control_mmap_allowed() below.
    3568                 :            :          * Since older alsa-lib requires both status and control mmaps to be
    3569                 :            :          * coupled, we have to disable the status mmap for old alsa-lib, too.
    3570                 :            :          */
    3571                 :          0 :         if (pcm_file->user_pversion < SNDRV_PROTOCOL_VERSION(2, 0, 14) &&
    3572         [ #  # ]:          0 :             (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR))
    3573                 :            :                 return false;
    3574                 :            :         return true;
    3575                 :            : }
    3576                 :            : 
    3577                 :          0 : static bool pcm_control_mmap_allowed(struct snd_pcm_file *pcm_file)
    3578                 :            : {
    3579                 :          0 :         if (pcm_file->no_compat_mmap)
    3580                 :            :                 return false;
    3581                 :            :         /* Disallow the control mmap when SYNC_APPLPTR flag is set;
    3582                 :            :          * it enforces the user-space to fall back to snd_pcm_sync_ptr(),
    3583                 :            :          * thus it effectively assures the manual update of appl_ptr.
    3584                 :            :          */
    3585         [ #  # ]:          0 :         if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR)
    3586                 :            :                 return false;
    3587                 :            :         return true;
    3588                 :            : }
    3589                 :            : 
    3590                 :            : #else /* ! coherent mmap */
    3591                 :            : /*
    3592                 :            :  * don't support mmap for status and control records.
    3593                 :            :  */
    3594                 :            : #define pcm_status_mmap_allowed(pcm_file)       false
    3595                 :            : #define pcm_control_mmap_allowed(pcm_file)      false
    3596                 :            : 
    3597                 :            : static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
    3598                 :            :                                struct vm_area_struct *area)
    3599                 :            : {
    3600                 :            :         return -ENXIO;
    3601                 :            : }
    3602                 :            : static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
    3603                 :            :                                 struct vm_area_struct *area)
    3604                 :            : {
    3605                 :            :         return -ENXIO;
    3606                 :            : }
    3607                 :            : #endif /* coherent mmap */
    3608                 :            : 
    3609                 :            : static inline struct page *
    3610                 :          0 : snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs)
    3611                 :            : {
    3612                 :          0 :         void *vaddr = substream->runtime->dma_area + ofs;
    3613                 :            : 
    3614      [ #  #  # ]:          0 :         switch (substream->dma_buffer.dev.type) {
    3615                 :            : #ifdef CONFIG_SND_DMA_SGBUF
    3616                 :          0 :         case SNDRV_DMA_TYPE_DEV_SG:
    3617                 :            :         case SNDRV_DMA_TYPE_DEV_UC_SG:
    3618                 :          0 :                 return snd_pcm_sgbuf_ops_page(substream, ofs);
    3619                 :            : #endif /* CONFIG_SND_DMA_SGBUF */
    3620                 :          0 :         case SNDRV_DMA_TYPE_VMALLOC:
    3621                 :          0 :                 return vmalloc_to_page(vaddr);
    3622                 :          0 :         default:
    3623         [ #  # ]:          0 :                 return virt_to_page(vaddr);
    3624                 :            :         }
    3625                 :            : }
    3626                 :            : 
    3627                 :            : /*
    3628                 :            :  * fault callback for mmapping a RAM page
    3629                 :            :  */
    3630                 :          0 : static vm_fault_t snd_pcm_mmap_data_fault(struct vm_fault *vmf)
    3631                 :            : {
    3632                 :          0 :         struct snd_pcm_substream *substream = vmf->vma->vm_private_data;
    3633                 :          0 :         struct snd_pcm_runtime *runtime;
    3634                 :          0 :         unsigned long offset;
    3635                 :          0 :         struct page * page;
    3636                 :          0 :         size_t dma_bytes;
    3637                 :            :         
    3638         [ #  # ]:          0 :         if (substream == NULL)
    3639                 :            :                 return VM_FAULT_SIGBUS;
    3640                 :          0 :         runtime = substream->runtime;
    3641                 :          0 :         offset = vmf->pgoff << PAGE_SHIFT;
    3642                 :          0 :         dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
    3643         [ #  # ]:          0 :         if (offset > dma_bytes - PAGE_SIZE)
    3644                 :            :                 return VM_FAULT_SIGBUS;
    3645         [ #  # ]:          0 :         if (substream->ops->page)
    3646                 :          0 :                 page = substream->ops->page(substream, offset);
    3647                 :            :         else
    3648                 :          0 :                 page = snd_pcm_default_page_ops(substream, offset);
    3649         [ #  # ]:          0 :         if (!page)
    3650                 :            :                 return VM_FAULT_SIGBUS;
    3651         [ #  # ]:          0 :         get_page(page);
    3652                 :          0 :         vmf->page = page;
    3653                 :          0 :         return 0;
    3654                 :            : }
    3655                 :            : 
    3656                 :            : static const struct vm_operations_struct snd_pcm_vm_ops_data = {
    3657                 :            :         .open =         snd_pcm_mmap_data_open,
    3658                 :            :         .close =        snd_pcm_mmap_data_close,
    3659                 :            : };
    3660                 :            : 
    3661                 :            : static const struct vm_operations_struct snd_pcm_vm_ops_data_fault = {
    3662                 :            :         .open =         snd_pcm_mmap_data_open,
    3663                 :            :         .close =        snd_pcm_mmap_data_close,
    3664                 :            :         .fault =        snd_pcm_mmap_data_fault,
    3665                 :            : };
    3666                 :            : 
    3667                 :            : /*
    3668                 :            :  * mmap the DMA buffer on RAM
    3669                 :            :  */
    3670                 :            : 
    3671                 :            : /**
    3672                 :            :  * snd_pcm_lib_default_mmap - Default PCM data mmap function
    3673                 :            :  * @substream: PCM substream
    3674                 :            :  * @area: VMA
    3675                 :            :  *
    3676                 :            :  * This is the default mmap handler for PCM data.  When mmap pcm_ops is NULL,
    3677                 :            :  * this function is invoked implicitly.
    3678                 :            :  */
    3679                 :          0 : int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream,
    3680                 :            :                              struct vm_area_struct *area)
    3681                 :            : {
    3682                 :          0 :         area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
    3683                 :            : #ifdef CONFIG_GENERIC_ALLOCATOR
    3684         [ #  # ]:          0 :         if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_IRAM) {
    3685                 :          0 :                 area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
    3686                 :          0 :                 return remap_pfn_range(area, area->vm_start,
    3687                 :          0 :                                 substream->dma_buffer.addr >> PAGE_SHIFT,
    3688                 :          0 :                                 area->vm_end - area->vm_start, area->vm_page_prot);
    3689                 :            :         }
    3690                 :            : #endif /* CONFIG_GENERIC_ALLOCATOR */
    3691                 :            : #ifndef CONFIG_X86 /* for avoiding warnings arch/x86/mm/pat.c */
    3692                 :            :         if (IS_ENABLED(CONFIG_HAS_DMA) && !substream->ops->page &&
    3693                 :            :             (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV ||
    3694                 :            :              substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_UC))
    3695                 :            :                 return dma_mmap_coherent(substream->dma_buffer.dev.dev,
    3696                 :            :                                          area,
    3697                 :            :                                          substream->runtime->dma_area,
    3698                 :            :                                          substream->runtime->dma_addr,
    3699                 :            :                                          substream->runtime->dma_bytes);
    3700                 :            : #endif /* CONFIG_X86 */
    3701                 :            :         /* mmap with fault handler */
    3702                 :          0 :         area->vm_ops = &snd_pcm_vm_ops_data_fault;
    3703                 :          0 :         return 0;
    3704                 :            : }
    3705                 :            : EXPORT_SYMBOL_GPL(snd_pcm_lib_default_mmap);
    3706                 :            : 
    3707                 :            : /*
    3708                 :            :  * mmap the DMA buffer on I/O memory area
    3709                 :            :  */
    3710                 :            : #if SNDRV_PCM_INFO_MMAP_IOMEM
    3711                 :            : /**
    3712                 :            :  * snd_pcm_lib_mmap_iomem - Default PCM data mmap function for I/O mem
    3713                 :            :  * @substream: PCM substream
    3714                 :            :  * @area: VMA
    3715                 :            :  *
    3716                 :            :  * When your hardware uses the iomapped pages as the hardware buffer and
    3717                 :            :  * wants to mmap it, pass this function as mmap pcm_ops.  Note that this
    3718                 :            :  * is supposed to work only on limited architectures.
    3719                 :            :  */
    3720                 :          0 : int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
    3721                 :            :                            struct vm_area_struct *area)
    3722                 :            : {
    3723                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    3724                 :            : 
    3725         [ #  # ]:          0 :         area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
    3726                 :          0 :         return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes);
    3727                 :            : }
    3728                 :            : EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
    3729                 :            : #endif /* SNDRV_PCM_INFO_MMAP */
    3730                 :            : 
    3731                 :            : /*
    3732                 :            :  * mmap DMA buffer
    3733                 :            :  */
    3734                 :          0 : int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
    3735                 :            :                       struct vm_area_struct *area)
    3736                 :            : {
    3737                 :          0 :         struct snd_pcm_runtime *runtime;
    3738                 :          0 :         long size;
    3739                 :          0 :         unsigned long offset;
    3740                 :          0 :         size_t dma_bytes;
    3741                 :          0 :         int err;
    3742                 :            : 
    3743         [ #  # ]:          0 :         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    3744         [ #  # ]:          0 :                 if (!(area->vm_flags & (VM_WRITE|VM_READ)))
    3745                 :            :                         return -EINVAL;
    3746                 :            :         } else {
    3747         [ #  # ]:          0 :                 if (!(area->vm_flags & VM_READ))
    3748                 :            :                         return -EINVAL;
    3749                 :            :         }
    3750                 :          0 :         runtime = substream->runtime;
    3751         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    3752                 :            :                 return -EBADFD;
    3753         [ #  # ]:          0 :         if (!(runtime->info & SNDRV_PCM_INFO_MMAP))
    3754                 :            :                 return -ENXIO;
    3755         [ #  # ]:          0 :         if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
    3756                 :            :             runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
    3757                 :            :                 return -EINVAL;
    3758                 :          0 :         size = area->vm_end - area->vm_start;
    3759                 :          0 :         offset = area->vm_pgoff << PAGE_SHIFT;
    3760                 :          0 :         dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
    3761         [ #  # ]:          0 :         if ((size_t)size > dma_bytes)
    3762                 :            :                 return -EINVAL;
    3763         [ #  # ]:          0 :         if (offset > dma_bytes - size)
    3764                 :            :                 return -EINVAL;
    3765                 :            : 
    3766                 :          0 :         area->vm_ops = &snd_pcm_vm_ops_data;
    3767                 :          0 :         area->vm_private_data = substream;
    3768         [ #  # ]:          0 :         if (substream->ops->mmap)
    3769                 :          0 :                 err = substream->ops->mmap(substream, area);
    3770                 :            :         else
    3771                 :          0 :                 err = snd_pcm_lib_default_mmap(substream, area);
    3772         [ #  # ]:          0 :         if (!err)
    3773                 :          0 :                 atomic_inc(&substream->mmap_count);
    3774                 :            :         return err;
    3775                 :            : }
    3776                 :            : EXPORT_SYMBOL(snd_pcm_mmap_data);
    3777                 :            : 
    3778                 :          0 : static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
    3779                 :            : {
    3780                 :          0 :         struct snd_pcm_file * pcm_file;
    3781                 :          0 :         struct snd_pcm_substream *substream;    
    3782                 :          0 :         unsigned long offset;
    3783                 :            :         
    3784                 :          0 :         pcm_file = file->private_data;
    3785                 :          0 :         substream = pcm_file->substream;
    3786   [ #  #  #  #  :          0 :         if (PCM_RUNTIME_CHECK(substream))
                   #  # ]
    3787                 :            :                 return -ENXIO;
    3788                 :            : 
    3789                 :          0 :         offset = area->vm_pgoff << PAGE_SHIFT;
    3790   [ #  #  #  #  :          0 :         switch (offset) {
                      # ]
    3791                 :          0 :         case SNDRV_PCM_MMAP_OFFSET_STATUS_OLD:
    3792         [ #  # ]:          0 :                 if (pcm_file->no_compat_mmap || !IS_ENABLED(CONFIG_64BIT))
    3793                 :            :                         return -ENXIO;
    3794                 :            :                 /* fallthrough */
    3795                 :            :         case SNDRV_PCM_MMAP_OFFSET_STATUS_NEW:
    3796         [ #  # ]:          0 :                 if (!pcm_status_mmap_allowed(pcm_file))
    3797                 :            :                         return -ENXIO;
    3798         [ #  # ]:          0 :                 return snd_pcm_mmap_status(substream, file, area);
    3799                 :          0 :         case SNDRV_PCM_MMAP_OFFSET_CONTROL_OLD:
    3800         [ #  # ]:          0 :                 if (pcm_file->no_compat_mmap || !IS_ENABLED(CONFIG_64BIT))
    3801                 :            :                         return -ENXIO;
    3802                 :            :                 /* fallthrough */
    3803                 :            :         case SNDRV_PCM_MMAP_OFFSET_CONTROL_NEW:
    3804         [ #  # ]:          0 :                 if (!pcm_control_mmap_allowed(pcm_file))
    3805                 :            :                         return -ENXIO;
    3806         [ #  # ]:          0 :                 return snd_pcm_mmap_control(substream, file, area);
    3807                 :          0 :         default:
    3808                 :          0 :                 return snd_pcm_mmap_data(substream, file, area);
    3809                 :            :         }
    3810                 :            :         return 0;
    3811                 :            : }
    3812                 :            : 
    3813                 :          0 : static int snd_pcm_fasync(int fd, struct file * file, int on)
    3814                 :            : {
    3815                 :          0 :         struct snd_pcm_file * pcm_file;
    3816                 :          0 :         struct snd_pcm_substream *substream;
    3817                 :          0 :         struct snd_pcm_runtime *runtime;
    3818                 :            : 
    3819                 :          0 :         pcm_file = file->private_data;
    3820                 :          0 :         substream = pcm_file->substream;
    3821   [ #  #  #  #  :          0 :         if (PCM_RUNTIME_CHECK(substream))
                   #  # ]
    3822                 :            :                 return -ENXIO;
    3823                 :          0 :         runtime = substream->runtime;
    3824                 :          0 :         return fasync_helper(fd, file, on, &runtime->fasync);
    3825                 :            : }
    3826                 :            : 
    3827                 :            : /*
    3828                 :            :  * ioctl32 compat
    3829                 :            :  */
    3830                 :            : #ifdef CONFIG_COMPAT
    3831                 :            : #include "pcm_compat.c"
    3832                 :            : #else
    3833                 :            : #define snd_pcm_ioctl_compat    NULL
    3834                 :            : #endif
    3835                 :            : 
    3836                 :            : /*
    3837                 :            :  *  To be removed helpers to keep binary compatibility
    3838                 :            :  */
    3839                 :            : 
    3840                 :            : #ifdef CONFIG_SND_SUPPORT_OLD_API
    3841                 :            : #define __OLD_TO_NEW_MASK(x) ((x&7)|((x&0x07fffff8)<<5))
    3842                 :            : #define __NEW_TO_OLD_MASK(x) ((x&7)|((x&0xffffff00)>>5))
    3843                 :            : 
    3844                 :          0 : static void snd_pcm_hw_convert_from_old_params(struct snd_pcm_hw_params *params,
    3845                 :            :                                                struct snd_pcm_hw_params_old *oparams)
    3846                 :            : {
    3847                 :          0 :         unsigned int i;
    3848                 :            : 
    3849                 :          0 :         memset(params, 0, sizeof(*params));
    3850                 :          0 :         params->flags = oparams->flags;
    3851         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
    3852                 :          0 :                 params->masks[i].bits[0] = oparams->masks[i];
    3853                 :          0 :         memcpy(params->intervals, oparams->intervals, sizeof(oparams->intervals));
    3854                 :          0 :         params->rmask = __OLD_TO_NEW_MASK(oparams->rmask);
    3855                 :          0 :         params->cmask = __OLD_TO_NEW_MASK(oparams->cmask);
    3856                 :          0 :         params->info = oparams->info;
    3857                 :          0 :         params->msbits = oparams->msbits;
    3858                 :          0 :         params->rate_num = oparams->rate_num;
    3859                 :          0 :         params->rate_den = oparams->rate_den;
    3860                 :          0 :         params->fifo_size = oparams->fifo_size;
    3861                 :          0 : }
    3862                 :            : 
    3863                 :          0 : static void snd_pcm_hw_convert_to_old_params(struct snd_pcm_hw_params_old *oparams,
    3864                 :            :                                              struct snd_pcm_hw_params *params)
    3865                 :            : {
    3866                 :          0 :         unsigned int i;
    3867                 :            : 
    3868                 :          0 :         memset(oparams, 0, sizeof(*oparams));
    3869                 :          0 :         oparams->flags = params->flags;
    3870         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
    3871                 :          0 :                 oparams->masks[i] = params->masks[i].bits[0];
    3872                 :          0 :         memcpy(oparams->intervals, params->intervals, sizeof(oparams->intervals));
    3873                 :          0 :         oparams->rmask = __NEW_TO_OLD_MASK(params->rmask);
    3874                 :          0 :         oparams->cmask = __NEW_TO_OLD_MASK(params->cmask);
    3875                 :          0 :         oparams->info = params->info;
    3876                 :          0 :         oparams->msbits = params->msbits;
    3877                 :          0 :         oparams->rate_num = params->rate_num;
    3878                 :          0 :         oparams->rate_den = params->rate_den;
    3879                 :          0 :         oparams->fifo_size = params->fifo_size;
    3880                 :          0 : }
    3881                 :            : 
    3882                 :          0 : static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
    3883                 :            :                                       struct snd_pcm_hw_params_old __user * _oparams)
    3884                 :            : {
    3885                 :          0 :         struct snd_pcm_hw_params *params;
    3886                 :          0 :         struct snd_pcm_hw_params_old *oparams = NULL;
    3887                 :          0 :         int err;
    3888                 :            : 
    3889                 :          0 :         params = kmalloc(sizeof(*params), GFP_KERNEL);
    3890         [ #  # ]:          0 :         if (!params)
    3891                 :            :                 return -ENOMEM;
    3892                 :            : 
    3893                 :          0 :         oparams = memdup_user(_oparams, sizeof(*oparams));
    3894         [ #  # ]:          0 :         if (IS_ERR(oparams)) {
    3895                 :          0 :                 err = PTR_ERR(oparams);
    3896                 :          0 :                 goto out;
    3897                 :            :         }
    3898                 :          0 :         snd_pcm_hw_convert_from_old_params(params, oparams);
    3899                 :          0 :         err = snd_pcm_hw_refine(substream, params);
    3900         [ #  # ]:          0 :         if (err < 0)
    3901                 :          0 :                 goto out_old;
    3902                 :            : 
    3903                 :          0 :         err = fixup_unreferenced_params(substream, params);
    3904         [ #  # ]:          0 :         if (err < 0)
    3905                 :          0 :                 goto out_old;
    3906                 :            : 
    3907                 :          0 :         snd_pcm_hw_convert_to_old_params(oparams, params);
    3908   [ #  #  #  # ]:          0 :         if (copy_to_user(_oparams, oparams, sizeof(*oparams)))
    3909                 :            :                 err = -EFAULT;
    3910                 :          0 : out_old:
    3911                 :          0 :         kfree(oparams);
    3912                 :          0 : out:
    3913                 :          0 :         kfree(params);
    3914                 :          0 :         return err;
    3915                 :            : }
    3916                 :            : 
    3917                 :          0 : static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
    3918                 :            :                                       struct snd_pcm_hw_params_old __user * _oparams)
    3919                 :            : {
    3920                 :          0 :         struct snd_pcm_hw_params *params;
    3921                 :          0 :         struct snd_pcm_hw_params_old *oparams = NULL;
    3922                 :          0 :         int err;
    3923                 :            : 
    3924                 :          0 :         params = kmalloc(sizeof(*params), GFP_KERNEL);
    3925         [ #  # ]:          0 :         if (!params)
    3926                 :            :                 return -ENOMEM;
    3927                 :            : 
    3928                 :          0 :         oparams = memdup_user(_oparams, sizeof(*oparams));
    3929         [ #  # ]:          0 :         if (IS_ERR(oparams)) {
    3930                 :          0 :                 err = PTR_ERR(oparams);
    3931                 :          0 :                 goto out;
    3932                 :            :         }
    3933                 :            : 
    3934                 :          0 :         snd_pcm_hw_convert_from_old_params(params, oparams);
    3935                 :          0 :         err = snd_pcm_hw_params(substream, params);
    3936         [ #  # ]:          0 :         if (err < 0)
    3937                 :          0 :                 goto out_old;
    3938                 :            : 
    3939                 :          0 :         snd_pcm_hw_convert_to_old_params(oparams, params);
    3940   [ #  #  #  # ]:          0 :         if (copy_to_user(_oparams, oparams, sizeof(*oparams)))
    3941                 :            :                 err = -EFAULT;
    3942                 :          0 : out_old:
    3943                 :          0 :         kfree(oparams);
    3944                 :          0 : out:
    3945                 :          0 :         kfree(params);
    3946                 :          0 :         return err;
    3947                 :            : }
    3948                 :            : #endif /* CONFIG_SND_SUPPORT_OLD_API */
    3949                 :            : 
    3950                 :            : #ifndef CONFIG_MMU
    3951                 :            : static unsigned long snd_pcm_get_unmapped_area(struct file *file,
    3952                 :            :                                                unsigned long addr,
    3953                 :            :                                                unsigned long len,
    3954                 :            :                                                unsigned long pgoff,
    3955                 :            :                                                unsigned long flags)
    3956                 :            : {
    3957                 :            :         struct snd_pcm_file *pcm_file = file->private_data;
    3958                 :            :         struct snd_pcm_substream *substream = pcm_file->substream;
    3959                 :            :         struct snd_pcm_runtime *runtime = substream->runtime;
    3960                 :            :         unsigned long offset = pgoff << PAGE_SHIFT;
    3961                 :            : 
    3962                 :            :         switch (offset) {
    3963                 :            :         case SNDRV_PCM_MMAP_OFFSET_STATUS_NEW:
    3964                 :            :                 return (unsigned long)runtime->status;
    3965                 :            :         case SNDRV_PCM_MMAP_OFFSET_CONTROL_NEW:
    3966                 :            :                 return (unsigned long)runtime->control;
    3967                 :            :         default:
    3968                 :            :                 return (unsigned long)runtime->dma_area + offset;
    3969                 :            :         }
    3970                 :            : }
    3971                 :            : #else
    3972                 :            : # define snd_pcm_get_unmapped_area NULL
    3973                 :            : #endif
    3974                 :            : 
    3975                 :            : /*
    3976                 :            :  *  Register section
    3977                 :            :  */
    3978                 :            : 
    3979                 :            : const struct file_operations snd_pcm_f_ops[2] = {
    3980                 :            :         {
    3981                 :            :                 .owner =                THIS_MODULE,
    3982                 :            :                 .write =                snd_pcm_write,
    3983                 :            :                 .write_iter =           snd_pcm_writev,
    3984                 :            :                 .open =                 snd_pcm_playback_open,
    3985                 :            :                 .release =              snd_pcm_release,
    3986                 :            :                 .llseek =               no_llseek,
    3987                 :            :                 .poll =                 snd_pcm_poll,
    3988                 :            :                 .unlocked_ioctl =       snd_pcm_ioctl,
    3989                 :            :                 .compat_ioctl =         snd_pcm_ioctl_compat,
    3990                 :            :                 .mmap =                 snd_pcm_mmap,
    3991                 :            :                 .fasync =               snd_pcm_fasync,
    3992                 :            :                 .get_unmapped_area =    snd_pcm_get_unmapped_area,
    3993                 :            :         },
    3994                 :            :         {
    3995                 :            :                 .owner =                THIS_MODULE,
    3996                 :            :                 .read =                 snd_pcm_read,
    3997                 :            :                 .read_iter =            snd_pcm_readv,
    3998                 :            :                 .open =                 snd_pcm_capture_open,
    3999                 :            :                 .release =              snd_pcm_release,
    4000                 :            :                 .llseek =               no_llseek,
    4001                 :            :                 .poll =                 snd_pcm_poll,
    4002                 :            :                 .unlocked_ioctl =       snd_pcm_ioctl,
    4003                 :            :                 .compat_ioctl =         snd_pcm_ioctl_compat,
    4004                 :            :                 .mmap =                 snd_pcm_mmap,
    4005                 :            :                 .fasync =               snd_pcm_fasync,
    4006                 :            :                 .get_unmapped_area =    snd_pcm_get_unmapped_area,
    4007                 :            :         }
    4008                 :            : };

Generated by: LCOV version 1.14