LCOV - code coverage report
Current view: top level - sound/core - timer.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 16 875 1.8 %
Date: 2014-02-18 Functions: 1 59 1.7 %
Branches: 9 623 1.4 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  *  Timers abstract layer
       3                 :            :  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
       4                 :            :  *
       5                 :            :  *
       6                 :            :  *   This program is free software; you can redistribute it and/or modify
       7                 :            :  *   it under the terms of the GNU General Public License as published by
       8                 :            :  *   the Free Software Foundation; either version 2 of the License, or
       9                 :            :  *   (at your option) any later version.
      10                 :            :  *
      11                 :            :  *   This program is distributed in the hope that it will be useful,
      12                 :            :  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14                 :            :  *   GNU General Public License for more details.
      15                 :            :  *
      16                 :            :  *   You should have received a copy of the GNU General Public License
      17                 :            :  *   along with this program; if not, write to the Free Software
      18                 :            :  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
      19                 :            :  *
      20                 :            :  */
      21                 :            : 
      22                 :            : #include <linux/delay.h>
      23                 :            : #include <linux/init.h>
      24                 :            : #include <linux/slab.h>
      25                 :            : #include <linux/time.h>
      26                 :            : #include <linux/mutex.h>
      27                 :            : #include <linux/device.h>
      28                 :            : #include <linux/module.h>
      29                 :            : #include <linux/string.h>
      30                 :            : #include <sound/core.h>
      31                 :            : #include <sound/timer.h>
      32                 :            : #include <sound/control.h>
      33                 :            : #include <sound/info.h>
      34                 :            : #include <sound/minors.h>
      35                 :            : #include <sound/initval.h>
      36                 :            : #include <linux/kmod.h>
      37                 :            : 
      38                 :            : #if defined(CONFIG_SND_HRTIMER) || defined(CONFIG_SND_HRTIMER_MODULE)
      39                 :            : #define DEFAULT_TIMER_LIMIT 4
      40                 :            : #elif defined(CONFIG_SND_RTCTIMER) || defined(CONFIG_SND_RTCTIMER_MODULE)
      41                 :            : #define DEFAULT_TIMER_LIMIT 2
      42                 :            : #else
      43                 :            : #define DEFAULT_TIMER_LIMIT 1
      44                 :            : #endif
      45                 :            : 
      46                 :            : static int timer_limit = DEFAULT_TIMER_LIMIT;
      47                 :            : static int timer_tstamp_monotonic = 1;
      48                 :            : MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>");
      49                 :            : MODULE_DESCRIPTION("ALSA timer interface");
      50                 :            : MODULE_LICENSE("GPL");
      51                 :            : module_param(timer_limit, int, 0444);
      52                 :            : MODULE_PARM_DESC(timer_limit, "Maximum global timers in system.");
      53                 :            : module_param(timer_tstamp_monotonic, int, 0444);
      54                 :            : MODULE_PARM_DESC(timer_tstamp_monotonic, "Use posix monotonic clock source for timestamps (default).");
      55                 :            : 
      56                 :            : MODULE_ALIAS_CHARDEV(CONFIG_SND_MAJOR, SNDRV_MINOR_TIMER);
      57                 :            : MODULE_ALIAS("devname:snd/timer");
      58                 :            : 
      59                 :            : struct snd_timer_user {
      60                 :            :         struct snd_timer_instance *timeri;
      61                 :            :         int tread;              /* enhanced read with timestamps and events */
      62                 :            :         unsigned long ticks;
      63                 :            :         unsigned long overrun;
      64                 :            :         int qhead;
      65                 :            :         int qtail;
      66                 :            :         int qused;
      67                 :            :         int queue_size;
      68                 :            :         struct snd_timer_read *queue;
      69                 :            :         struct snd_timer_tread *tqueue;
      70                 :            :         spinlock_t qlock;
      71                 :            :         unsigned long last_resolution;
      72                 :            :         unsigned int filter;
      73                 :            :         struct timespec tstamp;         /* trigger tstamp */
      74                 :            :         wait_queue_head_t qchange_sleep;
      75                 :            :         struct fasync_struct *fasync;
      76                 :            :         struct mutex tread_sem;
      77                 :            : };
      78                 :            : 
      79                 :            : /* list of timers */
      80                 :            : static LIST_HEAD(snd_timer_list);
      81                 :            : 
      82                 :            : /* list of slave instances */
      83                 :            : static LIST_HEAD(snd_timer_slave_list);
      84                 :            : 
      85                 :            : /* lock for slave active lists */
      86                 :            : static DEFINE_SPINLOCK(slave_active_lock);
      87                 :            : 
      88                 :            : static DEFINE_MUTEX(register_mutex);
      89                 :            : 
      90                 :            : static int snd_timer_free(struct snd_timer *timer);
      91                 :            : static int snd_timer_dev_free(struct snd_device *device);
      92                 :            : static int snd_timer_dev_register(struct snd_device *device);
      93                 :            : static int snd_timer_dev_disconnect(struct snd_device *device);
      94                 :            : 
      95                 :            : static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_left);
      96                 :            : 
      97                 :            : /*
      98                 :            :  * create a timer instance with the given owner string.
      99                 :            :  * when timer is not NULL, increments the module counter
     100                 :            :  */
     101                 :          0 : static struct snd_timer_instance *snd_timer_instance_new(char *owner,
     102                 :            :                                                          struct snd_timer *timer)
     103                 :            : {
     104                 :            :         struct snd_timer_instance *timeri;
     105                 :            :         timeri = kzalloc(sizeof(*timeri), GFP_KERNEL);
     106         [ #  # ]:          0 :         if (timeri == NULL)
     107                 :            :                 return NULL;
     108                 :          0 :         timeri->owner = kstrdup(owner, GFP_KERNEL);
     109         [ #  # ]:          0 :         if (! timeri->owner) {
     110                 :          0 :                 kfree(timeri);
     111                 :          0 :                 return NULL;
     112                 :            :         }
     113                 :          0 :         INIT_LIST_HEAD(&timeri->open_list);
     114                 :          0 :         INIT_LIST_HEAD(&timeri->active_list);
     115                 :          0 :         INIT_LIST_HEAD(&timeri->ack_list);
     116                 :          0 :         INIT_LIST_HEAD(&timeri->slave_list_head);
     117                 :          0 :         INIT_LIST_HEAD(&timeri->slave_active_head);
     118                 :            : 
     119                 :          0 :         timeri->timer = timer;
     120 [ #  # ][ #  # ]:          0 :         if (timer && !try_module_get(timer->module)) {
     121                 :          0 :                 kfree(timeri->owner);
     122                 :          0 :                 kfree(timeri);
     123                 :          0 :                 return NULL;
     124                 :            :         }
     125                 :            : 
     126                 :          0 :         return timeri;
     127                 :            : }
     128                 :            : 
     129                 :            : /*
     130                 :            :  * find a timer instance from the given timer id
     131                 :            :  */
     132                 :          0 : static struct snd_timer *snd_timer_find(struct snd_timer_id *tid)
     133                 :            : {
     134                 :            :         struct snd_timer *timer = NULL;
     135                 :            : 
     136         [ #  # ]:          0 :         list_for_each_entry(timer, &snd_timer_list, device_list) {
     137         [ #  # ]:          0 :                 if (timer->tmr_class != tid->dev_class)
     138                 :          0 :                         continue;
     139         [ #  # ]:          0 :                 if ((timer->tmr_class == SNDRV_TIMER_CLASS_CARD ||
     140         [ #  # ]:          0 :                      timer->tmr_class == SNDRV_TIMER_CLASS_PCM) &&
     141         [ #  # ]:          0 :                     (timer->card == NULL ||
     142                 :          0 :                      timer->card->number != tid->card))
     143                 :          0 :                         continue;
     144         [ #  # ]:          0 :                 if (timer->tmr_device != tid->device)
     145                 :          0 :                         continue;
     146         [ #  # ]:          0 :                 if (timer->tmr_subdevice != tid->subdevice)
     147                 :          0 :                         continue;
     148                 :            :                 return timer;
     149                 :            :         }
     150                 :            :         return NULL;
     151                 :            : }
     152                 :            : 
     153                 :            : #ifdef CONFIG_MODULES
     154                 :            : 
     155                 :          0 : static void snd_timer_request(struct snd_timer_id *tid)
     156                 :            : {
     157      [ #  #  # ]:          0 :         switch (tid->dev_class) {
     158                 :            :         case SNDRV_TIMER_CLASS_GLOBAL:
     159         [ #  # ]:          0 :                 if (tid->device < timer_limit)
     160                 :          0 :                         request_module("snd-timer-%i", tid->device);
     161                 :            :                 break;
     162                 :            :         case SNDRV_TIMER_CLASS_CARD:
     163                 :            :         case SNDRV_TIMER_CLASS_PCM:
     164         [ #  # ]:          0 :                 if (tid->card < snd_ecards_limit)
     165                 :          0 :                         request_module("snd-card-%i", tid->card);
     166                 :            :                 break;
     167                 :            :         default:
     168                 :            :                 break;
     169                 :            :         }
     170                 :          0 : }
     171                 :            : 
     172                 :            : #endif
     173                 :            : 
     174                 :            : /*
     175                 :            :  * look for a master instance matching with the slave id of the given slave.
     176                 :            :  * when found, relink the open_link of the slave.
     177                 :            :  *
     178                 :            :  * call this with register_mutex down.
     179                 :            :  */
     180                 :          0 : static void snd_timer_check_slave(struct snd_timer_instance *slave)
     181                 :            : {
     182                 :            :         struct snd_timer *timer;
     183                 :            :         struct snd_timer_instance *master;
     184                 :            : 
     185                 :            :         /* FIXME: it's really dumb to look up all entries.. */
     186         [ #  # ]:          0 :         list_for_each_entry(timer, &snd_timer_list, device_list) {
     187         [ #  # ]:          0 :                 list_for_each_entry(master, &timer->open_list_head, open_list) {
     188 [ #  # ][ #  # ]:          0 :                         if (slave->slave_class == master->slave_class &&
     189                 :          0 :                             slave->slave_id == master->slave_id) {
     190                 :          0 :                                 list_move_tail(&slave->open_list,
     191                 :            :                                                &master->slave_list_head);
     192                 :            :                                 spin_lock_irq(&slave_active_lock);
     193                 :          0 :                                 slave->master = master;
     194                 :          0 :                                 slave->timer = master->timer;
     195                 :            :                                 spin_unlock_irq(&slave_active_lock);
     196                 :          0 :                                 return;
     197                 :            :                         }
     198                 :            :                 }
     199                 :            :         }
     200                 :            : }
     201                 :            : 
     202                 :            : /*
     203                 :            :  * look for slave instances matching with the slave id of the given master.
     204                 :            :  * when found, relink the open_link of slaves.
     205                 :            :  *
     206                 :            :  * call this with register_mutex down.
     207                 :            :  */
     208                 :          0 : static void snd_timer_check_master(struct snd_timer_instance *master)
     209                 :            : {
     210                 :            :         struct snd_timer_instance *slave, *tmp;
     211                 :            : 
     212                 :            :         /* check all pending slaves */
     213         [ #  # ]:          0 :         list_for_each_entry_safe(slave, tmp, &snd_timer_slave_list, open_list) {
     214 [ #  # ][ #  # ]:          0 :                 if (slave->slave_class == master->slave_class &&
     215                 :          0 :                     slave->slave_id == master->slave_id) {
     216                 :          0 :                         list_move_tail(&slave->open_list, &master->slave_list_head);
     217                 :            :                         spin_lock_irq(&slave_active_lock);
     218                 :          0 :                         slave->master = master;
     219                 :          0 :                         slave->timer = master->timer;
     220         [ #  # ]:          0 :                         if (slave->flags & SNDRV_TIMER_IFLG_RUNNING)
     221                 :          0 :                                 list_add_tail(&slave->active_list,
     222                 :            :                                               &master->slave_active_head);
     223                 :            :                         spin_unlock_irq(&slave_active_lock);
     224                 :            :                 }
     225                 :            :         }
     226                 :          0 : }
     227                 :            : 
     228                 :            : /*
     229                 :            :  * open a timer instance
     230                 :            :  * when opening a master, the slave id must be here given.
     231                 :            :  */
     232                 :          0 : int snd_timer_open(struct snd_timer_instance **ti,
     233                 :            :                    char *owner, struct snd_timer_id *tid,
     234                 :            :                    unsigned int slave_id)
     235                 :            : {
     236                 :            :         struct snd_timer *timer;
     237                 :            :         struct snd_timer_instance *timeri = NULL;
     238                 :            : 
     239         [ #  # ]:          0 :         if (tid->dev_class == SNDRV_TIMER_CLASS_SLAVE) {
     240                 :            :                 /* open a slave instance */
     241         [ #  # ]:          0 :                 if (tid->dev_sclass <= SNDRV_TIMER_SCLASS_NONE ||
     242                 :            :                     tid->dev_sclass > SNDRV_TIMER_SCLASS_OSS_SEQUENCER) {
     243                 :            :                         snd_printd("invalid slave class %i\n", tid->dev_sclass);
     244                 :            :                         return -EINVAL;
     245                 :            :                 }
     246                 :          0 :                 mutex_lock(&register_mutex);
     247                 :          0 :                 timeri = snd_timer_instance_new(owner, NULL);
     248         [ #  # ]:          0 :                 if (!timeri) {
     249                 :          0 :                         mutex_unlock(&register_mutex);
     250                 :          0 :                         return -ENOMEM;
     251                 :            :                 }
     252                 :          0 :                 timeri->slave_class = tid->dev_sclass;
     253                 :          0 :                 timeri->slave_id = tid->device;
     254                 :          0 :                 timeri->flags |= SNDRV_TIMER_IFLG_SLAVE;
     255                 :          0 :                 list_add_tail(&timeri->open_list, &snd_timer_slave_list);
     256                 :          0 :                 snd_timer_check_slave(timeri);
     257                 :          0 :                 mutex_unlock(&register_mutex);
     258                 :          0 :                 *ti = timeri;
     259                 :          0 :                 return 0;
     260                 :            :         }
     261                 :            : 
     262                 :            :         /* open a master instance */
     263                 :          0 :         mutex_lock(&register_mutex);
     264                 :          0 :         timer = snd_timer_find(tid);
     265                 :            : #ifdef CONFIG_MODULES
     266         [ #  # ]:          0 :         if (!timer) {
     267                 :          0 :                 mutex_unlock(&register_mutex);
     268                 :          0 :                 snd_timer_request(tid);
     269                 :          0 :                 mutex_lock(&register_mutex);
     270                 :          0 :                 timer = snd_timer_find(tid);
     271                 :            :         }
     272                 :            : #endif
     273         [ #  # ]:          0 :         if (!timer) {
     274                 :          0 :                 mutex_unlock(&register_mutex);
     275                 :          0 :                 return -ENODEV;
     276                 :            :         }
     277         [ #  # ]:          0 :         if (!list_empty(&timer->open_list_head)) {
     278                 :            :                 timeri = list_entry(timer->open_list_head.next,
     279                 :            :                                     struct snd_timer_instance, open_list);
     280         [ #  # ]:          0 :                 if (timeri->flags & SNDRV_TIMER_IFLG_EXCLUSIVE) {
     281                 :          0 :                         mutex_unlock(&register_mutex);
     282                 :          0 :                         return -EBUSY;
     283                 :            :                 }
     284                 :            :         }
     285                 :          0 :         timeri = snd_timer_instance_new(owner, timer);
     286         [ #  # ]:          0 :         if (!timeri) {
     287                 :          0 :                 mutex_unlock(&register_mutex);
     288                 :          0 :                 return -ENOMEM;
     289                 :            :         }
     290                 :          0 :         timeri->slave_class = tid->dev_sclass;
     291                 :          0 :         timeri->slave_id = slave_id;
     292 [ #  # ][ #  # ]:          0 :         if (list_empty(&timer->open_list_head) && timer->hw.open)
     293                 :          0 :                 timer->hw.open(timer);
     294                 :          0 :         list_add_tail(&timeri->open_list, &timer->open_list_head);
     295                 :          0 :         snd_timer_check_master(timeri);
     296                 :          0 :         mutex_unlock(&register_mutex);
     297                 :          0 :         *ti = timeri;
     298                 :          0 :         return 0;
     299                 :            : }
     300                 :            : 
     301                 :            : static int _snd_timer_stop(struct snd_timer_instance *timeri,
     302                 :            :                            int keep_flag, int event);
     303                 :            : 
     304                 :            : /*
     305                 :            :  * close a timer instance
     306                 :            :  */
     307                 :          0 : int snd_timer_close(struct snd_timer_instance *timeri)
     308                 :            : {
     309                 :            :         struct snd_timer *timer = NULL;
     310                 :            :         struct snd_timer_instance *slave, *tmp;
     311                 :            : 
     312         [ #  # ]:          0 :         if (snd_BUG_ON(!timeri))
     313                 :            :                 return -ENXIO;
     314                 :            : 
     315                 :            :         /* force to stop the timer */
     316                 :          0 :         snd_timer_stop(timeri);
     317                 :            : 
     318         [ #  # ]:          0 :         if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
     319                 :            :                 /* wait, until the active callback is finished */
     320                 :            :                 spin_lock_irq(&slave_active_lock);
     321         [ #  # ]:          0 :                 while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
     322                 :            :                         spin_unlock_irq(&slave_active_lock);
     323                 :          0 :                         udelay(10);
     324                 :            :                         spin_lock_irq(&slave_active_lock);
     325                 :            :                 }
     326                 :            :                 spin_unlock_irq(&slave_active_lock);
     327                 :          0 :                 mutex_lock(&register_mutex);
     328                 :            :                 list_del(&timeri->open_list);
     329                 :          0 :                 mutex_unlock(&register_mutex);
     330                 :            :         } else {
     331                 :          0 :                 timer = timeri->timer;
     332         [ #  # ]:          0 :                 if (snd_BUG_ON(!timer))
     333                 :            :                         goto out;
     334                 :            :                 /* wait, until the active callback is finished */
     335                 :            :                 spin_lock_irq(&timer->lock);
     336         [ #  # ]:          0 :                 while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
     337                 :            :                         spin_unlock_irq(&timer->lock);
     338                 :          0 :                         udelay(10);
     339                 :            :                         spin_lock_irq(&timer->lock);
     340                 :            :                 }
     341                 :            :                 spin_unlock_irq(&timer->lock);
     342                 :          0 :                 mutex_lock(&register_mutex);
     343                 :            :                 list_del(&timeri->open_list);
     344 [ #  # ][ #  # ]:          0 :                 if (timer && list_empty(&timer->open_list_head) &&
                 [ #  # ]
     345                 :          0 :                     timer->hw.close)
     346                 :          0 :                         timer->hw.close(timer);
     347                 :            :                 /* remove slave links */
     348         [ #  # ]:          0 :                 list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head,
     349                 :            :                                          open_list) {
     350                 :            :                         spin_lock_irq(&slave_active_lock);
     351                 :          0 :                         _snd_timer_stop(slave, 1, SNDRV_TIMER_EVENT_RESOLUTION);
     352                 :            :                         list_move_tail(&slave->open_list, &snd_timer_slave_list);
     353                 :          0 :                         slave->master = NULL;
     354                 :          0 :                         slave->timer = NULL;
     355                 :            :                         spin_unlock_irq(&slave_active_lock);
     356                 :            :                 }
     357                 :          0 :                 mutex_unlock(&register_mutex);
     358                 :            :         }
     359                 :            :  out:
     360         [ #  # ]:          0 :         if (timeri->private_free)
     361                 :          0 :                 timeri->private_free(timeri);
     362                 :          0 :         kfree(timeri->owner);
     363                 :          0 :         kfree(timeri);
     364         [ #  # ]:          0 :         if (timer)
     365                 :          0 :                 module_put(timer->module);
     366                 :            :         return 0;
     367                 :            : }
     368                 :            : 
     369                 :          0 : unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
     370                 :            : {
     371                 :            :         struct snd_timer * timer;
     372                 :            : 
     373 [ #  # ][ #  # ]:          0 :         if (timeri == NULL)
                 [ #  # ]
     374                 :            :                 return 0;
     375 [ #  # ][ #  # ]:          0 :         if ((timer = timeri->timer) != NULL) {
                 [ #  # ]
     376 [ #  # ][ #  # ]:          0 :                 if (timer->hw.c_resolution)
                 [ #  # ]
     377                 :          0 :                         return timer->hw.c_resolution(timer);
     378                 :          0 :                 return timer->hw.resolution;
     379                 :            :         }
     380                 :            :         return 0;
     381                 :            : }
     382                 :            : 
     383                 :          0 : static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
     384                 :            : {
     385                 :            :         struct snd_timer *timer;
     386                 :            :         unsigned long flags;
     387                 :            :         unsigned long resolution = 0;
     388                 :            :         struct snd_timer_instance *ts;
     389                 :            :         struct timespec tstamp;
     390                 :            : 
     391         [ #  # ]:          0 :         if (timer_tstamp_monotonic)
     392                 :          0 :                 do_posix_clock_monotonic_gettime(&tstamp);
     393                 :            :         else
     394                 :          0 :                 getnstimeofday(&tstamp);
     395         [ #  # ]:          0 :         if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START ||
     396                 :            :                        event > SNDRV_TIMER_EVENT_PAUSE))
     397                 :          0 :                 return;
     398         [ #  # ]:          0 :         if (event == SNDRV_TIMER_EVENT_START ||
     399                 :          0 :             event == SNDRV_TIMER_EVENT_CONTINUE)
     400                 :            :                 resolution = snd_timer_resolution(ti);
     401         [ #  # ]:          0 :         if (ti->ccallback)
     402                 :          0 :                 ti->ccallback(ti, event, &tstamp, resolution);
     403         [ #  # ]:          0 :         if (ti->flags & SNDRV_TIMER_IFLG_SLAVE)
     404                 :            :                 return;
     405                 :          0 :         timer = ti->timer;
     406         [ #  # ]:          0 :         if (timer == NULL)
     407                 :            :                 return;
     408         [ #  # ]:          0 :         if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
     409                 :            :                 return;
     410                 :          0 :         spin_lock_irqsave(&timer->lock, flags);
     411         [ #  # ]:          0 :         list_for_each_entry(ts, &ti->slave_active_head, active_list)
     412         [ #  # ]:          0 :                 if (ts->ccallback)
     413                 :          0 :                         ts->ccallback(ti, event + 100, &tstamp, resolution);
     414                 :            :         spin_unlock_irqrestore(&timer->lock, flags);
     415                 :            : }
     416                 :            : 
     417                 :          0 : static int snd_timer_start1(struct snd_timer *timer, struct snd_timer_instance *timeri,
     418                 :            :                             unsigned long sticks)
     419                 :            : {
     420                 :          0 :         list_move_tail(&timeri->active_list, &timer->active_list_head);
     421         [ #  # ]:          0 :         if (timer->running) {
     422         [ #  # ]:          0 :                 if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
     423                 :            :                         goto __start_now;
     424                 :          0 :                 timer->flags |= SNDRV_TIMER_FLG_RESCHED;
     425                 :          0 :                 timeri->flags |= SNDRV_TIMER_IFLG_START;
     426                 :          0 :                 return 1;       /* delayed start */
     427                 :            :         } else {
     428                 :          0 :                 timer->sticks = sticks;
     429                 :          0 :                 timer->hw.start(timer);
     430                 :            :               __start_now:
     431                 :          0 :                 timer->running++;
     432                 :          0 :                 timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
     433                 :          0 :                 return 0;
     434                 :            :         }
     435                 :            : }
     436                 :            : 
     437                 :          0 : static int snd_timer_start_slave(struct snd_timer_instance *timeri)
     438                 :            : {
     439                 :            :         unsigned long flags;
     440                 :            : 
     441                 :          0 :         spin_lock_irqsave(&slave_active_lock, flags);
     442                 :          0 :         timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
     443         [ #  # ]:          0 :         if (timeri->master)
     444                 :          0 :                 list_add_tail(&timeri->active_list,
     445                 :            :                               &timeri->master->slave_active_head);
     446                 :            :         spin_unlock_irqrestore(&slave_active_lock, flags);
     447                 :          0 :         return 1; /* delayed start */
     448                 :            : }
     449                 :            : 
     450                 :            : /*
     451                 :            :  *  start the timer instance
     452                 :            :  */
     453                 :          0 : int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
     454                 :            : {
     455                 :            :         struct snd_timer *timer;
     456                 :            :         int result = -EINVAL;
     457                 :            :         unsigned long flags;
     458                 :            : 
     459         [ #  # ]:          0 :         if (timeri == NULL || ticks < 1)
     460                 :            :                 return -EINVAL;
     461         [ #  # ]:          0 :         if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
     462                 :          0 :                 result = snd_timer_start_slave(timeri);
     463                 :          0 :                 snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
     464                 :          0 :                 return result;
     465                 :            :         }
     466                 :          0 :         timer = timeri->timer;
     467         [ #  # ]:          0 :         if (timer == NULL)
     468                 :            :                 return -EINVAL;
     469                 :          0 :         spin_lock_irqsave(&timer->lock, flags);
     470                 :          0 :         timeri->ticks = timeri->cticks = ticks;
     471                 :          0 :         timeri->pticks = 0;
     472                 :          0 :         result = snd_timer_start1(timer, timeri, ticks);
     473                 :            :         spin_unlock_irqrestore(&timer->lock, flags);
     474                 :          0 :         snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
     475                 :          0 :         return result;
     476                 :            : }
     477                 :            : 
     478                 :          0 : static int _snd_timer_stop(struct snd_timer_instance * timeri,
     479                 :            :                            int keep_flag, int event)
     480                 :            : {
     481                 :            :         struct snd_timer *timer;
     482                 :            :         unsigned long flags;
     483                 :            : 
     484         [ #  # ]:          0 :         if (snd_BUG_ON(!timeri))
     485                 :            :                 return -ENXIO;
     486                 :            : 
     487         [ #  # ]:          0 :         if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
     488         [ #  # ]:          0 :                 if (!keep_flag) {
     489                 :          0 :                         spin_lock_irqsave(&slave_active_lock, flags);
     490                 :          0 :                         timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
     491                 :            :                         spin_unlock_irqrestore(&slave_active_lock, flags);
     492                 :            :                 }
     493                 :            :                 goto __end;
     494                 :            :         }
     495                 :          0 :         timer = timeri->timer;
     496         [ #  # ]:          0 :         if (!timer)
     497                 :            :                 return -EINVAL;
     498                 :          0 :         spin_lock_irqsave(&timer->lock, flags);
     499                 :          0 :         list_del_init(&timeri->ack_list);
     500                 :          0 :         list_del_init(&timeri->active_list);
     501 [ #  # ][ #  # ]:          0 :         if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) &&
     502                 :          0 :             !(--timer->running)) {
     503                 :          0 :                 timer->hw.stop(timer);
     504         [ #  # ]:          0 :                 if (timer->flags & SNDRV_TIMER_FLG_RESCHED) {
     505                 :          0 :                         timer->flags &= ~SNDRV_TIMER_FLG_RESCHED;
     506                 :          0 :                         snd_timer_reschedule(timer, 0);
     507         [ #  # ]:          0 :                         if (timer->flags & SNDRV_TIMER_FLG_CHANGE) {
     508                 :          0 :                                 timer->flags &= ~SNDRV_TIMER_FLG_CHANGE;
     509                 :          0 :                                 timer->hw.start(timer);
     510                 :            :                         }
     511                 :            :                 }
     512                 :            :         }
     513         [ #  # ]:          0 :         if (!keep_flag)
     514                 :          0 :                 timeri->flags &=
     515                 :            :                         ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START);
     516                 :            :         spin_unlock_irqrestore(&timer->lock, flags);
     517                 :            :       __end:
     518         [ #  # ]:          0 :         if (event != SNDRV_TIMER_EVENT_RESOLUTION)
     519                 :          0 :                 snd_timer_notify1(timeri, event);
     520                 :            :         return 0;
     521                 :            : }
     522                 :            : 
     523                 :            : /*
     524                 :            :  * stop the timer instance.
     525                 :            :  *
     526                 :            :  * do not call this from the timer callback!
     527                 :            :  */
     528                 :          0 : int snd_timer_stop(struct snd_timer_instance *timeri)
     529                 :            : {
     530                 :            :         struct snd_timer *timer;
     531                 :            :         unsigned long flags;
     532                 :            :         int err;
     533                 :            : 
     534                 :          0 :         err = _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_STOP);
     535         [ #  # ]:          0 :         if (err < 0)
     536                 :            :                 return err;
     537                 :          0 :         timer = timeri->timer;
     538         [ #  # ]:          0 :         if (!timer)
     539                 :            :                 return -EINVAL;
     540                 :          0 :         spin_lock_irqsave(&timer->lock, flags);
     541                 :          0 :         timeri->cticks = timeri->ticks;
     542                 :          0 :         timeri->pticks = 0;
     543                 :            :         spin_unlock_irqrestore(&timer->lock, flags);
     544                 :          0 :         return 0;
     545                 :            : }
     546                 :            : 
     547                 :            : /*
     548                 :            :  * start again..  the tick is kept.
     549                 :            :  */
     550                 :          0 : int snd_timer_continue(struct snd_timer_instance *timeri)
     551                 :            : {
     552                 :            :         struct snd_timer *timer;
     553                 :            :         int result = -EINVAL;
     554                 :            :         unsigned long flags;
     555                 :            : 
     556         [ #  # ]:          0 :         if (timeri == NULL)
     557                 :            :                 return result;
     558         [ #  # ]:          0 :         if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE)
     559                 :          0 :                 return snd_timer_start_slave(timeri);
     560                 :          0 :         timer = timeri->timer;
     561         [ #  # ]:          0 :         if (! timer)
     562                 :            :                 return -EINVAL;
     563                 :          0 :         spin_lock_irqsave(&timer->lock, flags);
     564         [ #  # ]:          0 :         if (!timeri->cticks)
     565                 :          0 :                 timeri->cticks = 1;
     566                 :          0 :         timeri->pticks = 0;
     567                 :          0 :         result = snd_timer_start1(timer, timeri, timer->sticks);
     568                 :            :         spin_unlock_irqrestore(&timer->lock, flags);
     569                 :          0 :         snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_CONTINUE);
     570                 :          0 :         return result;
     571                 :            : }
     572                 :            : 
     573                 :            : /*
     574                 :            :  * pause.. remember the ticks left
     575                 :            :  */
     576                 :          0 : int snd_timer_pause(struct snd_timer_instance * timeri)
     577                 :            : {
     578                 :          0 :         return _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_PAUSE);
     579                 :            : }
     580                 :            : 
     581                 :            : /*
     582                 :            :  * reschedule the timer
     583                 :            :  *
     584                 :            :  * start pending instances and check the scheduling ticks.
     585                 :            :  * when the scheduling ticks is changed set CHANGE flag to reprogram the timer.
     586                 :            :  */
     587                 :          0 : static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_left)
     588                 :            : {
     589                 :            :         struct snd_timer_instance *ti;
     590                 :            :         unsigned long ticks = ~0UL;
     591                 :            : 
     592         [ #  # ]:          0 :         list_for_each_entry(ti, &timer->active_list_head, active_list) {
     593         [ #  # ]:          0 :                 if (ti->flags & SNDRV_TIMER_IFLG_START) {
     594                 :          0 :                         ti->flags &= ~SNDRV_TIMER_IFLG_START;
     595                 :          0 :                         ti->flags |= SNDRV_TIMER_IFLG_RUNNING;
     596                 :          0 :                         timer->running++;
     597                 :            :                 }
     598         [ #  # ]:          0 :                 if (ti->flags & SNDRV_TIMER_IFLG_RUNNING) {
     599         [ #  # ]:          0 :                         if (ticks > ti->cticks)
     600                 :            :                                 ticks = ti->cticks;
     601                 :            :                 }
     602                 :            :         }
     603         [ #  # ]:          0 :         if (ticks == ~0UL) {
     604                 :          0 :                 timer->flags &= ~SNDRV_TIMER_FLG_RESCHED;
     605                 :          0 :                 return;
     606                 :            :         }
     607         [ #  # ]:          0 :         if (ticks > timer->hw.ticks)
     608                 :            :                 ticks = timer->hw.ticks;
     609         [ #  # ]:          0 :         if (ticks_left != ticks)
     610                 :          0 :                 timer->flags |= SNDRV_TIMER_FLG_CHANGE;
     611                 :          0 :         timer->sticks = ticks;
     612                 :            : }
     613                 :            : 
     614                 :            : /*
     615                 :            :  * timer tasklet
     616                 :            :  *
     617                 :            :  */
     618                 :          0 : static void snd_timer_tasklet(unsigned long arg)
     619                 :            : {
     620                 :          0 :         struct snd_timer *timer = (struct snd_timer *) arg;
     621                 :            :         struct snd_timer_instance *ti;
     622                 :            :         struct list_head *p;
     623                 :            :         unsigned long resolution, ticks;
     624                 :            :         unsigned long flags;
     625                 :            : 
     626                 :          0 :         spin_lock_irqsave(&timer->lock, flags);
     627                 :            :         /* now process all callbacks */
     628         [ #  # ]:          0 :         while (!list_empty(&timer->sack_list_head)) {
     629                 :            :                 p = timer->sack_list_head.next;              /* get first item */
     630                 :          0 :                 ti = list_entry(p, struct snd_timer_instance, ack_list);
     631                 :            : 
     632                 :            :                 /* remove from ack_list and make empty */
     633                 :            :                 list_del_init(p);
     634                 :            : 
     635                 :          0 :                 ticks = ti->pticks;
     636                 :          0 :                 ti->pticks = 0;
     637                 :          0 :                 resolution = ti->resolution;
     638                 :            : 
     639                 :          0 :                 ti->flags |= SNDRV_TIMER_IFLG_CALLBACK;
     640                 :            :                 spin_unlock(&timer->lock);
     641         [ #  # ]:          0 :                 if (ti->callback)
     642                 :          0 :                         ti->callback(ti, resolution, ticks);
     643                 :            :                 spin_lock(&timer->lock);
     644                 :          0 :                 ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK;
     645                 :            :         }
     646                 :            :         spin_unlock_irqrestore(&timer->lock, flags);
     647                 :          0 : }
     648                 :            : 
     649                 :            : /*
     650                 :            :  * timer interrupt
     651                 :            :  *
     652                 :            :  * ticks_left is usually equal to timer->sticks.
     653                 :            :  *
     654                 :            :  */
     655                 :          0 : void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
     656                 :            : {
     657                 :            :         struct snd_timer_instance *ti, *ts, *tmp;
     658                 :            :         unsigned long resolution, ticks;
     659                 :            :         struct list_head *p, *ack_list_head;
     660                 :            :         unsigned long flags;
     661                 :            :         int use_tasklet = 0;
     662                 :            : 
     663         [ #  # ]:          0 :         if (timer == NULL)
     664                 :          0 :                 return;
     665                 :            : 
     666                 :          0 :         spin_lock_irqsave(&timer->lock, flags);
     667                 :            : 
     668                 :            :         /* remember the current resolution */
     669         [ #  # ]:          0 :         if (timer->hw.c_resolution)
     670                 :          0 :                 resolution = timer->hw.c_resolution(timer);
     671                 :            :         else
     672                 :          0 :                 resolution = timer->hw.resolution;
     673                 :            : 
     674                 :            :         /* loop for all active instances
     675                 :            :          * Here we cannot use list_for_each_entry because the active_list of a
     676                 :            :          * processed instance is relinked to done_list_head before the callback
     677                 :            :          * is called.
     678                 :            :          */
     679         [ #  # ]:          0 :         list_for_each_entry_safe(ti, tmp, &timer->active_list_head,
     680                 :            :                                  active_list) {
     681         [ #  # ]:          0 :                 if (!(ti->flags & SNDRV_TIMER_IFLG_RUNNING))
     682                 :          0 :                         continue;
     683                 :          0 :                 ti->pticks += ticks_left;
     684                 :          0 :                 ti->resolution = resolution;
     685         [ #  # ]:          0 :                 if (ti->cticks < ticks_left)
     686                 :          0 :                         ti->cticks = 0;
     687                 :            :                 else
     688                 :          0 :                         ti->cticks -= ticks_left;
     689         [ #  # ]:          0 :                 if (ti->cticks) /* not expired */
     690                 :          0 :                         continue;
     691         [ #  # ]:          0 :                 if (ti->flags & SNDRV_TIMER_IFLG_AUTO) {
     692                 :          0 :                         ti->cticks = ti->ticks;
     693                 :            :                 } else {
     694                 :          0 :                         ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
     695         [ #  # ]:          0 :                         if (--timer->running)
     696                 :            :                                 list_del(&ti->active_list);
     697                 :            :                 }
     698 [ #  # ][ #  # ]:          0 :                 if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
     699                 :          0 :                     (ti->flags & SNDRV_TIMER_IFLG_FAST))
     700                 :          0 :                         ack_list_head = &timer->ack_list_head;
     701                 :            :                 else
     702                 :          0 :                         ack_list_head = &timer->sack_list_head;
     703         [ #  # ]:          0 :                 if (list_empty(&ti->ack_list))
     704                 :            :                         list_add_tail(&ti->ack_list, ack_list_head);
     705         [ #  # ]:          0 :                 list_for_each_entry(ts, &ti->slave_active_head, active_list) {
     706                 :          0 :                         ts->pticks = ti->pticks;
     707                 :          0 :                         ts->resolution = resolution;
     708         [ #  # ]:          0 :                         if (list_empty(&ts->ack_list))
     709                 :            :                                 list_add_tail(&ts->ack_list, ack_list_head);
     710                 :            :                 }
     711                 :            :         }
     712         [ #  # ]:          0 :         if (timer->flags & SNDRV_TIMER_FLG_RESCHED)
     713                 :          0 :                 snd_timer_reschedule(timer, timer->sticks);
     714         [ #  # ]:          0 :         if (timer->running) {
     715         [ #  # ]:          0 :                 if (timer->hw.flags & SNDRV_TIMER_HW_STOP) {
     716                 :          0 :                         timer->hw.stop(timer);
     717                 :          0 :                         timer->flags |= SNDRV_TIMER_FLG_CHANGE;
     718                 :            :                 }
     719 [ #  # ][ #  # ]:          0 :                 if (!(timer->hw.flags & SNDRV_TIMER_HW_AUTO) ||
     720                 :          0 :                     (timer->flags & SNDRV_TIMER_FLG_CHANGE)) {
     721                 :            :                         /* restart timer */
     722                 :          0 :                         timer->flags &= ~SNDRV_TIMER_FLG_CHANGE;
     723                 :          0 :                         timer->hw.start(timer);
     724                 :            :                 }
     725                 :            :         } else {
     726                 :          0 :                 timer->hw.stop(timer);
     727                 :            :         }
     728                 :            : 
     729                 :            :         /* now process all fast callbacks */
     730         [ #  # ]:          0 :         while (!list_empty(&timer->ack_list_head)) {
     731                 :            :                 p = timer->ack_list_head.next;               /* get first item */
     732                 :          0 :                 ti = list_entry(p, struct snd_timer_instance, ack_list);
     733                 :            : 
     734                 :            :                 /* remove from ack_list and make empty */
     735                 :            :                 list_del_init(p);
     736                 :            : 
     737                 :          0 :                 ticks = ti->pticks;
     738                 :          0 :                 ti->pticks = 0;
     739                 :            : 
     740                 :          0 :                 ti->flags |= SNDRV_TIMER_IFLG_CALLBACK;
     741                 :            :                 spin_unlock(&timer->lock);
     742         [ #  # ]:          0 :                 if (ti->callback)
     743                 :          0 :                         ti->callback(ti, resolution, ticks);
     744                 :            :                 spin_lock(&timer->lock);
     745                 :          0 :                 ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK;
     746                 :            :         }
     747                 :            : 
     748                 :            :         /* do we have any slow callbacks? */
     749                 :          0 :         use_tasklet = !list_empty(&timer->sack_list_head);
     750                 :            :         spin_unlock_irqrestore(&timer->lock, flags);
     751                 :            : 
     752         [ #  # ]:          0 :         if (use_tasklet)
     753                 :          0 :                 tasklet_schedule(&timer->task_queue);
     754                 :            : }
     755                 :            : 
     756                 :            : /*
     757                 :            : 
     758                 :            :  */
     759                 :            : 
     760                 :          0 : int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
     761                 :            :                   struct snd_timer **rtimer)
     762                 :            : {
     763                 :            :         struct snd_timer *timer;
     764                 :            :         int err;
     765                 :            :         static struct snd_device_ops ops = {
     766                 :            :                 .dev_free = snd_timer_dev_free,
     767                 :            :                 .dev_register = snd_timer_dev_register,
     768                 :            :                 .dev_disconnect = snd_timer_dev_disconnect,
     769                 :            :         };
     770                 :            : 
     771         [ #  # ]:          0 :         if (snd_BUG_ON(!tid))
     772                 :            :                 return -EINVAL;
     773         [ #  # ]:          0 :         if (rtimer)
     774                 :          0 :                 *rtimer = NULL;
     775                 :            :         timer = kzalloc(sizeof(*timer), GFP_KERNEL);
     776         [ #  # ]:          0 :         if (timer == NULL) {
     777                 :          0 :                 snd_printk(KERN_ERR "timer: cannot allocate\n");
     778                 :          0 :                 return -ENOMEM;
     779                 :            :         }
     780                 :          0 :         timer->tmr_class = tid->dev_class;
     781                 :          0 :         timer->card = card;
     782                 :          0 :         timer->tmr_device = tid->device;
     783                 :          0 :         timer->tmr_subdevice = tid->subdevice;
     784         [ #  # ]:          0 :         if (id)
     785                 :          0 :                 strlcpy(timer->id, id, sizeof(timer->id));
     786                 :          0 :         INIT_LIST_HEAD(&timer->device_list);
     787                 :          0 :         INIT_LIST_HEAD(&timer->open_list_head);
     788                 :          0 :         INIT_LIST_HEAD(&timer->active_list_head);
     789                 :          0 :         INIT_LIST_HEAD(&timer->ack_list_head);
     790                 :          0 :         INIT_LIST_HEAD(&timer->sack_list_head);
     791                 :          0 :         spin_lock_init(&timer->lock);
     792                 :          0 :         tasklet_init(&timer->task_queue, snd_timer_tasklet,
     793                 :            :                      (unsigned long)timer);
     794         [ #  # ]:          0 :         if (card != NULL) {
     795                 :          0 :                 timer->module = card->module;
     796                 :          0 :                 err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops);
     797         [ #  # ]:          0 :                 if (err < 0) {
     798                 :          0 :                         snd_timer_free(timer);
     799                 :          0 :                         return err;
     800                 :            :                 }
     801                 :            :         }
     802         [ #  # ]:          0 :         if (rtimer)
     803                 :          0 :                 *rtimer = timer;
     804                 :            :         return 0;
     805                 :            : }
     806                 :            : 
     807                 :          0 : static int snd_timer_free(struct snd_timer *timer)
     808                 :            : {
     809         [ #  # ]:          0 :         if (!timer)
     810                 :            :                 return 0;
     811                 :            : 
     812                 :          0 :         mutex_lock(&register_mutex);
     813         [ #  # ]:          0 :         if (! list_empty(&timer->open_list_head)) {
     814                 :            :                 struct list_head *p, *n;
     815                 :            :                 struct snd_timer_instance *ti;
     816                 :          0 :                 snd_printk(KERN_WARNING "timer %p is busy?\n", timer);
     817         [ #  # ]:          0 :                 list_for_each_safe(p, n, &timer->open_list_head) {
     818                 :            :                         list_del_init(p);
     819                 :            :                         ti = list_entry(p, struct snd_timer_instance, open_list);
     820                 :          0 :                         ti->timer = NULL;
     821                 :            :                 }
     822                 :            :         }
     823                 :            :         list_del(&timer->device_list);
     824                 :          0 :         mutex_unlock(&register_mutex);
     825                 :            : 
     826         [ #  # ]:          0 :         if (timer->private_free)
     827                 :          0 :                 timer->private_free(timer);
     828                 :          0 :         kfree(timer);
     829                 :          0 :         return 0;
     830                 :            : }
     831                 :            : 
     832                 :          0 : static int snd_timer_dev_free(struct snd_device *device)
     833                 :            : {
     834                 :          0 :         struct snd_timer *timer = device->device_data;
     835                 :          0 :         return snd_timer_free(timer);
     836                 :            : }
     837                 :            : 
     838                 :          0 : static int snd_timer_dev_register(struct snd_device *dev)
     839                 :            : {
     840                 :          0 :         struct snd_timer *timer = dev->device_data;
     841                 :            :         struct snd_timer *timer1;
     842                 :            : 
     843 [ #  # ][ #  # ]:          0 :         if (snd_BUG_ON(!timer || !timer->hw.start || !timer->hw.stop))
         [ #  # ][ #  # ]
     844                 :            :                 return -ENXIO;
     845 [ #  # ][ #  # ]:          0 :         if (!(timer->hw.flags & SNDRV_TIMER_HW_SLAVE) &&
     846         [ #  # ]:          0 :             !timer->hw.resolution && timer->hw.c_resolution == NULL)
     847                 :            :                 return -EINVAL;
     848                 :            : 
     849                 :          0 :         mutex_lock(&register_mutex);
     850         [ #  # ]:          0 :         list_for_each_entry(timer1, &snd_timer_list, device_list) {
     851         [ #  # ]:          0 :                 if (timer1->tmr_class > timer->tmr_class)
     852                 :            :                         break;
     853         [ #  # ]:          0 :                 if (timer1->tmr_class < timer->tmr_class)
     854                 :          0 :                         continue;
     855 [ #  # ][ #  # ]:          0 :                 if (timer1->card && timer->card) {
     856         [ #  # ]:          0 :                         if (timer1->card->number > timer->card->number)
     857                 :            :                                 break;
     858         [ #  # ]:          0 :                         if (timer1->card->number < timer->card->number)
     859                 :          0 :                                 continue;
     860                 :            :                 }
     861         [ #  # ]:          0 :                 if (timer1->tmr_device > timer->tmr_device)
     862                 :            :                         break;
     863         [ #  # ]:          0 :                 if (timer1->tmr_device < timer->tmr_device)
     864                 :          0 :                         continue;
     865         [ #  # ]:          0 :                 if (timer1->tmr_subdevice > timer->tmr_subdevice)
     866                 :            :                         break;
     867         [ #  # ]:          0 :                 if (timer1->tmr_subdevice < timer->tmr_subdevice)
     868                 :          0 :                         continue;
     869                 :            :                 /* conflicts.. */
     870                 :          0 :                 mutex_unlock(&register_mutex);
     871                 :          0 :                 return -EBUSY;
     872                 :            :         }
     873                 :          0 :         list_add_tail(&timer->device_list, &timer1->device_list);
     874                 :          0 :         mutex_unlock(&register_mutex);
     875                 :          0 :         return 0;
     876                 :            : }
     877                 :            : 
     878                 :          0 : static int snd_timer_dev_disconnect(struct snd_device *device)
     879                 :            : {
     880                 :          0 :         struct snd_timer *timer = device->device_data;
     881                 :          0 :         mutex_lock(&register_mutex);
     882                 :          0 :         list_del_init(&timer->device_list);
     883                 :          0 :         mutex_unlock(&register_mutex);
     884                 :          0 :         return 0;
     885                 :            : }
     886                 :            : 
     887                 :          0 : void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstamp)
     888                 :            : {
     889                 :            :         unsigned long flags;
     890                 :            :         unsigned long resolution = 0;
     891                 :            :         struct snd_timer_instance *ti, *ts;
     892                 :            : 
     893         [ #  # ]:          0 :         if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE))
     894                 :            :                 return;
     895         [ #  # ]:          0 :         if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_MSTART ||
     896                 :            :                        event > SNDRV_TIMER_EVENT_MRESUME))
     897                 :            :                 return;
     898                 :          0 :         spin_lock_irqsave(&timer->lock, flags);
     899         [ #  # ]:          0 :         if (event == SNDRV_TIMER_EVENT_MSTART ||
     900         [ #  # ]:          0 :             event == SNDRV_TIMER_EVENT_MCONTINUE ||
     901                 :            :             event == SNDRV_TIMER_EVENT_MRESUME) {
     902         [ #  # ]:          0 :                 if (timer->hw.c_resolution)
     903                 :          0 :                         resolution = timer->hw.c_resolution(timer);
     904                 :            :                 else
     905                 :          0 :                         resolution = timer->hw.resolution;
     906                 :            :         }
     907         [ #  # ]:          0 :         list_for_each_entry(ti, &timer->active_list_head, active_list) {
     908         [ #  # ]:          0 :                 if (ti->ccallback)
     909                 :          0 :                         ti->ccallback(ti, event, tstamp, resolution);
     910         [ #  # ]:          0 :                 list_for_each_entry(ts, &ti->slave_active_head, active_list)
     911         [ #  # ]:          0 :                         if (ts->ccallback)
     912                 :          0 :                                 ts->ccallback(ts, event, tstamp, resolution);
     913                 :            :         }
     914                 :            :         spin_unlock_irqrestore(&timer->lock, flags);
     915                 :            : }
     916                 :            : 
     917                 :            : /*
     918                 :            :  * exported functions for global timers
     919                 :            :  */
     920                 :          0 : int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer)
     921                 :            : {
     922                 :            :         struct snd_timer_id tid;
     923                 :            : 
     924                 :          0 :         tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL;
     925                 :          0 :         tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
     926                 :          0 :         tid.card = -1;
     927                 :          0 :         tid.device = device;
     928                 :          0 :         tid.subdevice = 0;
     929                 :          0 :         return snd_timer_new(NULL, id, &tid, rtimer);
     930                 :            : }
     931                 :            : 
     932                 :          0 : int snd_timer_global_free(struct snd_timer *timer)
     933                 :            : {
     934                 :          0 :         return snd_timer_free(timer);
     935                 :            : }
     936                 :            : 
     937                 :          0 : int snd_timer_global_register(struct snd_timer *timer)
     938                 :            : {
     939                 :            :         struct snd_device dev;
     940                 :            : 
     941                 :          0 :         memset(&dev, 0, sizeof(dev));
     942                 :          0 :         dev.device_data = timer;
     943                 :          0 :         return snd_timer_dev_register(&dev);
     944                 :            : }
     945                 :            : 
     946                 :            : /*
     947                 :            :  *  System timer
     948                 :            :  */
     949                 :            : 
     950                 :            : struct snd_timer_system_private {
     951                 :            :         struct timer_list tlist;
     952                 :            :         unsigned long last_expires;
     953                 :            :         unsigned long last_jiffies;
     954                 :            :         unsigned long correction;
     955                 :            : };
     956                 :            : 
     957                 :          0 : static void snd_timer_s_function(unsigned long data)
     958                 :            : {
     959                 :          0 :         struct snd_timer *timer = (struct snd_timer *)data;
     960                 :          0 :         struct snd_timer_system_private *priv = timer->private_data;
     961                 :          0 :         unsigned long jiff = jiffies;
     962         [ #  # ]:          0 :         if (time_after(jiff, priv->last_expires))
     963                 :          0 :                 priv->correction += (long)jiff - (long)priv->last_expires;
     964                 :          0 :         snd_timer_interrupt(timer, (long)jiff - (long)priv->last_jiffies);
     965                 :          0 : }
     966                 :            : 
     967                 :          0 : static int snd_timer_s_start(struct snd_timer * timer)
     968                 :            : {
     969                 :            :         struct snd_timer_system_private *priv;
     970                 :            :         unsigned long njiff;
     971                 :            : 
     972                 :          0 :         priv = (struct snd_timer_system_private *) timer->private_data;
     973                 :          0 :         njiff = (priv->last_jiffies = jiffies);
     974         [ #  # ]:          0 :         if (priv->correction > timer->sticks - 1) {
     975                 :          0 :                 priv->correction -= timer->sticks - 1;
     976                 :          0 :                 njiff++;
     977                 :            :         } else {
     978                 :          0 :                 njiff += timer->sticks - priv->correction;
     979                 :          0 :                 priv->correction = 0;
     980                 :            :         }
     981                 :          0 :         priv->last_expires = priv->tlist.expires = njiff;
     982                 :          0 :         add_timer(&priv->tlist);
     983                 :          0 :         return 0;
     984                 :            : }
     985                 :            : 
     986                 :          0 : static int snd_timer_s_stop(struct snd_timer * timer)
     987                 :            : {
     988                 :            :         struct snd_timer_system_private *priv;
     989                 :            :         unsigned long jiff;
     990                 :            : 
     991                 :          0 :         priv = (struct snd_timer_system_private *) timer->private_data;
     992                 :          0 :         del_timer(&priv->tlist);
     993                 :          0 :         jiff = jiffies;
     994         [ #  # ]:          0 :         if (time_before(jiff, priv->last_expires))
     995                 :          0 :                 timer->sticks = priv->last_expires - jiff;
     996                 :            :         else
     997                 :          0 :                 timer->sticks = 1;
     998                 :          0 :         priv->correction = 0;
     999                 :          0 :         return 0;
    1000                 :            : }
    1001                 :            : 
    1002                 :            : static struct snd_timer_hardware snd_timer_system =
    1003                 :            : {
    1004                 :            :         .flags =        SNDRV_TIMER_HW_FIRST | SNDRV_TIMER_HW_TASKLET,
    1005                 :            :         .resolution =   1000000000L / HZ,
    1006                 :            :         .ticks =        10000000L,
    1007                 :            :         .start =        snd_timer_s_start,
    1008                 :            :         .stop =         snd_timer_s_stop
    1009                 :            : };
    1010                 :            : 
    1011                 :          0 : static void snd_timer_free_system(struct snd_timer *timer)
    1012                 :            : {
    1013                 :          0 :         kfree(timer->private_data);
    1014                 :          0 : }
    1015                 :            : 
    1016                 :          0 : static int snd_timer_register_system(void)
    1017                 :            : {
    1018                 :            :         struct snd_timer *timer;
    1019                 :            :         struct snd_timer_system_private *priv;
    1020                 :            :         int err;
    1021                 :            : 
    1022                 :          0 :         err = snd_timer_global_new("system", SNDRV_TIMER_GLOBAL_SYSTEM, &timer);
    1023         [ #  # ]:          0 :         if (err < 0)
    1024                 :            :                 return err;
    1025                 :          0 :         strcpy(timer->name, "system timer");
    1026                 :          0 :         timer->hw = snd_timer_system;
    1027                 :            :         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
    1028         [ #  # ]:          0 :         if (priv == NULL) {
    1029                 :          0 :                 snd_timer_free(timer);
    1030                 :          0 :                 return -ENOMEM;
    1031                 :            :         }
    1032                 :          0 :         init_timer(&priv->tlist);
    1033                 :          0 :         priv->tlist.function = snd_timer_s_function;
    1034                 :          0 :         priv->tlist.data = (unsigned long) timer;
    1035                 :          0 :         timer->private_data = priv;
    1036                 :          0 :         timer->private_free = snd_timer_free_system;
    1037                 :          0 :         return snd_timer_global_register(timer);
    1038                 :            : }
    1039                 :            : 
    1040                 :            : #ifdef CONFIG_PROC_FS
    1041                 :            : /*
    1042                 :            :  *  Info interface
    1043                 :            :  */
    1044                 :            : 
    1045                 :          0 : static void snd_timer_proc_read(struct snd_info_entry *entry,
    1046                 :            :                                 struct snd_info_buffer *buffer)
    1047                 :            : {
    1048                 :            :         struct snd_timer *timer;
    1049                 :            :         struct snd_timer_instance *ti;
    1050                 :            : 
    1051                 :          1 :         mutex_lock(&register_mutex);
    1052         [ +  + ]:          4 :         list_for_each_entry(timer, &snd_timer_list, device_list) {
    1053   [ +  -  +  - ]:          3 :                 switch (timer->tmr_class) {
    1054                 :            :                 case SNDRV_TIMER_CLASS_GLOBAL:
    1055                 :          1 :                         snd_iprintf(buffer, "G%i: ", timer->tmr_device);
    1056                 :          1 :                         break;
    1057                 :            :                 case SNDRV_TIMER_CLASS_CARD:
    1058                 :          0 :                         snd_iprintf(buffer, "C%i-%i: ",
    1059                 :          0 :                                     timer->card->number, timer->tmr_device);
    1060                 :          0 :                         break;
    1061                 :            :                 case SNDRV_TIMER_CLASS_PCM:
    1062                 :          2 :                         snd_iprintf(buffer, "P%i-%i-%i: ", timer->card->number,
    1063                 :            :                                     timer->tmr_device, timer->tmr_subdevice);
    1064                 :          2 :                         break;
    1065                 :            :                 default:
    1066         [ #  # ]:          0 :                         snd_iprintf(buffer, "?%i-%i-%i-%i: ", timer->tmr_class,
    1067                 :          0 :                                     timer->card ? timer->card->number : -1,
    1068                 :            :                                     timer->tmr_device, timer->tmr_subdevice);
    1069                 :            :                 }
    1070                 :          3 :                 snd_iprintf(buffer, "%s :", timer->name);
    1071         [ +  + ]:          3 :                 if (timer->hw.resolution)
    1072                 :          1 :                         snd_iprintf(buffer, " %lu.%03luus (%lu ticks)",
    1073                 :            :                                     timer->hw.resolution / 1000,
    1074                 :            :                                     timer->hw.resolution % 1000,
    1075                 :            :                                     timer->hw.ticks);
    1076         [ +  + ]:          3 :                 if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
    1077                 :          2 :                         snd_iprintf(buffer, " SLAVE");
    1078                 :          3 :                 snd_iprintf(buffer, "\n");
    1079         [ -  + ]:          4 :                 list_for_each_entry(ti, &timer->open_list_head, open_list)
    1080 [ #  # ][ #  # ]:          0 :                         snd_iprintf(buffer, "  Client %s : %s\n",
    1081                 :          0 :                                     ti->owner ? ti->owner : "unknown",
    1082                 :          0 :                                     ti->flags & (SNDRV_TIMER_IFLG_START |
    1083                 :            :                                                  SNDRV_TIMER_IFLG_RUNNING)
    1084                 :            :                                     ? "running" : "stopped");
    1085                 :            :         }
    1086                 :          1 :         mutex_unlock(&register_mutex);
    1087                 :          1 : }
    1088                 :            : 
    1089                 :            : static struct snd_info_entry *snd_timer_proc_entry;
    1090                 :            : 
    1091                 :          0 : static void __init snd_timer_proc_init(void)
    1092                 :            : {
    1093                 :            :         struct snd_info_entry *entry;
    1094                 :            : 
    1095                 :          0 :         entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL);
    1096         [ #  # ]:          0 :         if (entry != NULL) {
    1097                 :          0 :                 entry->c.text.read = snd_timer_proc_read;
    1098         [ #  # ]:          0 :                 if (snd_info_register(entry) < 0) {
    1099                 :          0 :                         snd_info_free_entry(entry);
    1100                 :            :                         entry = NULL;
    1101                 :            :                 }
    1102                 :            :         }
    1103                 :          0 :         snd_timer_proc_entry = entry;
    1104                 :          0 : }
    1105                 :            : 
    1106                 :          0 : static void __exit snd_timer_proc_done(void)
    1107                 :            : {
    1108                 :          0 :         snd_info_free_entry(snd_timer_proc_entry);
    1109                 :          0 : }
    1110                 :            : #else /* !CONFIG_PROC_FS */
    1111                 :            : #define snd_timer_proc_init()
    1112                 :            : #define snd_timer_proc_done()
    1113                 :            : #endif
    1114                 :            : 
    1115                 :            : /*
    1116                 :            :  *  USER SPACE interface
    1117                 :            :  */
    1118                 :            : 
    1119                 :          0 : static void snd_timer_user_interrupt(struct snd_timer_instance *timeri,
    1120                 :            :                                      unsigned long resolution,
    1121                 :            :                                      unsigned long ticks)
    1122                 :            : {
    1123                 :          0 :         struct snd_timer_user *tu = timeri->callback_data;
    1124                 :            :         struct snd_timer_read *r;
    1125                 :            :         int prev;
    1126                 :            : 
    1127                 :            :         spin_lock(&tu->qlock);
    1128         [ #  # ]:          0 :         if (tu->qused > 0) {
    1129         [ #  # ]:          0 :                 prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1;
    1130                 :          0 :                 r = &tu->queue[prev];
    1131         [ #  # ]:          0 :                 if (r->resolution == resolution) {
    1132                 :          0 :                         r->ticks += ticks;
    1133                 :          0 :                         goto __wake;
    1134                 :            :                 }
    1135                 :            :         }
    1136         [ #  # ]:          0 :         if (tu->qused >= tu->queue_size) {
    1137                 :          0 :                 tu->overrun++;
    1138                 :            :         } else {
    1139                 :          0 :                 r = &tu->queue[tu->qtail++];
    1140                 :          0 :                 tu->qtail %= tu->queue_size;
    1141                 :          0 :                 r->resolution = resolution;
    1142                 :          0 :                 r->ticks = ticks;
    1143                 :          0 :                 tu->qused++;
    1144                 :            :         }
    1145                 :            :       __wake:
    1146                 :            :         spin_unlock(&tu->qlock);
    1147                 :          0 :         kill_fasync(&tu->fasync, SIGIO, POLL_IN);
    1148                 :          0 :         wake_up(&tu->qchange_sleep);
    1149                 :          0 : }
    1150                 :            : 
    1151                 :          0 : static void snd_timer_user_append_to_tqueue(struct snd_timer_user *tu,
    1152                 :            :                                             struct snd_timer_tread *tread)
    1153                 :            : {
    1154         [ #  # ]:          0 :         if (tu->qused >= tu->queue_size) {
    1155                 :          0 :                 tu->overrun++;
    1156                 :            :         } else {
    1157                 :          0 :                 memcpy(&tu->tqueue[tu->qtail++], tread, sizeof(*tread));
    1158                 :          0 :                 tu->qtail %= tu->queue_size;
    1159                 :          0 :                 tu->qused++;
    1160                 :            :         }
    1161                 :          0 : }
    1162                 :            : 
    1163                 :          0 : static void snd_timer_user_ccallback(struct snd_timer_instance *timeri,
    1164                 :            :                                      int event,
    1165                 :            :                                      struct timespec *tstamp,
    1166                 :            :                                      unsigned long resolution)
    1167                 :            : {
    1168                 :          0 :         struct snd_timer_user *tu = timeri->callback_data;
    1169                 :            :         struct snd_timer_tread r1;
    1170                 :            :         unsigned long flags;
    1171                 :            : 
    1172         [ #  # ]:          0 :         if (event >= SNDRV_TIMER_EVENT_START &&
    1173                 :            :             event <= SNDRV_TIMER_EVENT_PAUSE)
    1174                 :          0 :                 tu->tstamp = *tstamp;
    1175 [ #  # ][ #  # ]:          0 :         if ((tu->filter & (1 << event)) == 0 || !tu->tread)
    1176                 :          0 :                 return;
    1177                 :          0 :         r1.event = event;
    1178                 :          0 :         r1.tstamp = *tstamp;
    1179                 :          0 :         r1.val = resolution;
    1180                 :          0 :         spin_lock_irqsave(&tu->qlock, flags);
    1181                 :          0 :         snd_timer_user_append_to_tqueue(tu, &r1);
    1182                 :            :         spin_unlock_irqrestore(&tu->qlock, flags);
    1183                 :          0 :         kill_fasync(&tu->fasync, SIGIO, POLL_IN);
    1184                 :          0 :         wake_up(&tu->qchange_sleep);
    1185                 :            : }
    1186                 :            : 
    1187                 :          0 : static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
    1188                 :            :                                       unsigned long resolution,
    1189                 :            :                                       unsigned long ticks)
    1190                 :            : {
    1191                 :          0 :         struct snd_timer_user *tu = timeri->callback_data;
    1192                 :            :         struct snd_timer_tread *r, r1;
    1193                 :            :         struct timespec tstamp;
    1194                 :            :         int prev, append = 0;
    1195                 :            : 
    1196                 :          0 :         memset(&tstamp, 0, sizeof(tstamp));
    1197                 :            :         spin_lock(&tu->qlock);
    1198         [ #  # ]:          0 :         if ((tu->filter & ((1 << SNDRV_TIMER_EVENT_RESOLUTION) |
    1199                 :            :                            (1 << SNDRV_TIMER_EVENT_TICK))) == 0) {
    1200                 :            :                 spin_unlock(&tu->qlock);
    1201                 :          0 :                 return;
    1202                 :            :         }
    1203 [ #  # ][ #  # ]:          0 :         if (tu->last_resolution != resolution || ticks > 0) {
    1204         [ #  # ]:          0 :                 if (timer_tstamp_monotonic)
    1205                 :          0 :                         do_posix_clock_monotonic_gettime(&tstamp);
    1206                 :            :                 else
    1207                 :          0 :                         getnstimeofday(&tstamp);
    1208                 :            :         }
    1209 [ #  # ][ #  # ]:          0 :         if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) &&
    1210                 :          0 :             tu->last_resolution != resolution) {
    1211                 :          0 :                 r1.event = SNDRV_TIMER_EVENT_RESOLUTION;
    1212                 :          0 :                 r1.tstamp = tstamp;
    1213                 :          0 :                 r1.val = resolution;
    1214                 :          0 :                 snd_timer_user_append_to_tqueue(tu, &r1);
    1215                 :          0 :                 tu->last_resolution = resolution;
    1216                 :            :                 append++;
    1217                 :            :         }
    1218         [ #  # ]:          0 :         if ((tu->filter & (1 << SNDRV_TIMER_EVENT_TICK)) == 0)
    1219                 :            :                 goto __wake;
    1220         [ #  # ]:          0 :         if (ticks == 0)
    1221                 :            :                 goto __wake;
    1222         [ #  # ]:          0 :         if (tu->qused > 0) {
    1223         [ #  # ]:          0 :                 prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1;
    1224                 :          0 :                 r = &tu->tqueue[prev];
    1225         [ #  # ]:          0 :                 if (r->event == SNDRV_TIMER_EVENT_TICK) {
    1226                 :          0 :                         r->tstamp = tstamp;
    1227                 :          0 :                         r->val += ticks;
    1228                 :          0 :                         append++;
    1229                 :          0 :                         goto __wake;
    1230                 :            :                 }
    1231                 :            :         }
    1232                 :          0 :         r1.event = SNDRV_TIMER_EVENT_TICK;
    1233                 :          0 :         r1.tstamp = tstamp;
    1234                 :          0 :         r1.val = ticks;
    1235                 :          0 :         snd_timer_user_append_to_tqueue(tu, &r1);
    1236                 :          0 :         append++;
    1237                 :            :       __wake:
    1238                 :            :         spin_unlock(&tu->qlock);
    1239         [ #  # ]:          0 :         if (append == 0)
    1240                 :            :                 return;
    1241                 :          0 :         kill_fasync(&tu->fasync, SIGIO, POLL_IN);
    1242                 :          0 :         wake_up(&tu->qchange_sleep);
    1243                 :            : }
    1244                 :            : 
    1245                 :          0 : static int snd_timer_user_open(struct inode *inode, struct file *file)
    1246                 :            : {
    1247                 :            :         struct snd_timer_user *tu;
    1248                 :            :         int err;
    1249                 :            : 
    1250                 :          0 :         err = nonseekable_open(inode, file);
    1251         [ #  # ]:          0 :         if (err < 0)
    1252                 :            :                 return err;
    1253                 :            : 
    1254                 :            :         tu = kzalloc(sizeof(*tu), GFP_KERNEL);
    1255         [ #  # ]:          0 :         if (tu == NULL)
    1256                 :            :                 return -ENOMEM;
    1257                 :          0 :         spin_lock_init(&tu->qlock);
    1258                 :          0 :         init_waitqueue_head(&tu->qchange_sleep);
    1259                 :          0 :         mutex_init(&tu->tread_sem);
    1260                 :          0 :         tu->ticks = 1;
    1261                 :          0 :         tu->queue_size = 128;
    1262                 :          0 :         tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
    1263                 :            :                             GFP_KERNEL);
    1264         [ #  # ]:          0 :         if (tu->queue == NULL) {
    1265                 :          0 :                 kfree(tu);
    1266                 :          0 :                 return -ENOMEM;
    1267                 :            :         }
    1268                 :          0 :         file->private_data = tu;
    1269                 :          0 :         return 0;
    1270                 :            : }
    1271                 :            : 
    1272                 :          0 : static int snd_timer_user_release(struct inode *inode, struct file *file)
    1273                 :            : {
    1274                 :            :         struct snd_timer_user *tu;
    1275                 :            : 
    1276         [ #  # ]:          0 :         if (file->private_data) {
    1277                 :            :                 tu = file->private_data;
    1278                 :          0 :                 file->private_data = NULL;
    1279         [ #  # ]:          0 :                 if (tu->timeri)
    1280                 :          0 :                         snd_timer_close(tu->timeri);
    1281                 :          0 :                 kfree(tu->queue);
    1282                 :          0 :                 kfree(tu->tqueue);
    1283                 :          0 :                 kfree(tu);
    1284                 :            :         }
    1285                 :          0 :         return 0;
    1286                 :            : }
    1287                 :            : 
    1288                 :            : static void snd_timer_user_zero_id(struct snd_timer_id *id)
    1289                 :            : {
    1290                 :          0 :         id->dev_class = SNDRV_TIMER_CLASS_NONE;
    1291                 :          0 :         id->dev_sclass = SNDRV_TIMER_SCLASS_NONE;
    1292                 :          0 :         id->card = -1;
    1293                 :          0 :         id->device = -1;
    1294                 :          0 :         id->subdevice = -1;
    1295                 :            : }
    1296                 :            : 
    1297                 :            : static void snd_timer_user_copy_id(struct snd_timer_id *id, struct snd_timer *timer)
    1298                 :            : {
    1299                 :          0 :         id->dev_class = timer->tmr_class;
    1300                 :          0 :         id->dev_sclass = SNDRV_TIMER_SCLASS_NONE;
    1301 [ #  # ][ #  # ]:          0 :         id->card = timer->card ? timer->card->number : -1;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1302                 :          0 :         id->device = timer->tmr_device;
    1303                 :          0 :         id->subdevice = timer->tmr_subdevice;
    1304                 :            : }
    1305                 :            : 
    1306                 :          0 : static int snd_timer_user_next_device(struct snd_timer_id __user *_tid)
    1307                 :            : {
    1308                 :            :         struct snd_timer_id id;
    1309                 :            :         struct snd_timer *timer;
    1310                 :            :         struct list_head *p;
    1311                 :            : 
    1312         [ #  # ]:          0 :         if (copy_from_user(&id, _tid, sizeof(id)))
    1313                 :            :                 return -EFAULT;
    1314                 :          0 :         mutex_lock(&register_mutex);
    1315         [ #  # ]:          0 :         if (id.dev_class < 0) {              /* first item */
    1316         [ #  # ]:          0 :                 if (list_empty(&snd_timer_list))
    1317                 :            :                         snd_timer_user_zero_id(&id);
    1318                 :            :                 else {
    1319                 :            :                         timer = list_entry(snd_timer_list.next,
    1320                 :            :                                            struct snd_timer, device_list);
    1321                 :            :                         snd_timer_user_copy_id(&id, timer);
    1322                 :            :                 }
    1323                 :            :         } else {
    1324      [ #  #  # ]:          0 :                 switch (id.dev_class) {
    1325                 :            :                 case SNDRV_TIMER_CLASS_GLOBAL:
    1326         [ #  # ]:          0 :                         id.device = id.device < 0 ? 0 : id.device + 1;
    1327         [ #  # ]:          0 :                         list_for_each(p, &snd_timer_list) {
    1328                 :            :                                 timer = list_entry(p, struct snd_timer, device_list);
    1329         [ #  # ]:          0 :                                 if (timer->tmr_class > SNDRV_TIMER_CLASS_GLOBAL) {
    1330                 :            :                                         snd_timer_user_copy_id(&id, timer);
    1331                 :            :                                         break;
    1332                 :            :                                 }
    1333         [ #  # ]:          0 :                                 if (timer->tmr_device >= id.device) {
    1334                 :            :                                         snd_timer_user_copy_id(&id, timer);
    1335                 :            :                                         break;
    1336                 :            :                                 }
    1337                 :            :                         }
    1338         [ #  # ]:          0 :                         if (p == &snd_timer_list)
    1339                 :            :                                 snd_timer_user_zero_id(&id);
    1340                 :            :                         break;
    1341                 :            :                 case SNDRV_TIMER_CLASS_CARD:
    1342                 :            :                 case SNDRV_TIMER_CLASS_PCM:
    1343         [ #  # ]:          0 :                         if (id.card < 0) {
    1344                 :          0 :                                 id.card = 0;
    1345                 :            :                         } else {
    1346         [ #  # ]:          0 :                                 if (id.card < 0) {
    1347                 :          0 :                                         id.card = 0;
    1348                 :            :                                 } else {
    1349         [ #  # ]:          0 :                                         if (id.device < 0) {
    1350                 :          0 :                                                 id.device = 0;
    1351                 :            :                                         } else {
    1352         [ #  # ]:          0 :                                                 if (id.subdevice < 0) {
    1353                 :          0 :                                                         id.subdevice = 0;
    1354                 :            :                                                 } else {
    1355                 :          0 :                                                         id.subdevice++;
    1356                 :            :                                                 }
    1357                 :            :                                         }
    1358                 :            :                                 }
    1359                 :            :                         }
    1360         [ #  # ]:          0 :                         list_for_each(p, &snd_timer_list) {
    1361                 :            :                                 timer = list_entry(p, struct snd_timer, device_list);
    1362         [ #  # ]:          0 :                                 if (timer->tmr_class > id.dev_class) {
    1363                 :            :                                         snd_timer_user_copy_id(&id, timer);
    1364                 :            :                                         break;
    1365                 :            :                                 }
    1366         [ #  # ]:          0 :                                 if (timer->tmr_class < id.dev_class)
    1367                 :          0 :                                         continue;
    1368         [ #  # ]:          0 :                                 if (timer->card->number > id.card) {
    1369                 :            :                                         snd_timer_user_copy_id(&id, timer);
    1370                 :            :                                         break;
    1371                 :            :                                 }
    1372         [ #  # ]:          0 :                                 if (timer->card->number < id.card)
    1373                 :          0 :                                         continue;
    1374         [ #  # ]:          0 :                                 if (timer->tmr_device > id.device) {
    1375                 :            :                                         snd_timer_user_copy_id(&id, timer);
    1376                 :            :                                         break;
    1377                 :            :                                 }
    1378         [ #  # ]:          0 :                                 if (timer->tmr_device < id.device)
    1379                 :          0 :                                         continue;
    1380         [ #  # ]:          0 :                                 if (timer->tmr_subdevice > id.subdevice) {
    1381                 :            :                                         snd_timer_user_copy_id(&id, timer);
    1382                 :            :                                         break;
    1383                 :            :                                 }
    1384         [ #  # ]:          0 :                                 if (timer->tmr_subdevice < id.subdevice)
    1385                 :          0 :                                         continue;
    1386                 :            :                                 snd_timer_user_copy_id(&id, timer);
    1387                 :            :                                 break;
    1388                 :            :                         }
    1389         [ #  # ]:          0 :                         if (p == &snd_timer_list)
    1390                 :            :                                 snd_timer_user_zero_id(&id);
    1391                 :            :                         break;
    1392                 :            :                 default:
    1393                 :            :                         snd_timer_user_zero_id(&id);
    1394                 :            :                 }
    1395                 :            :         }
    1396                 :          0 :         mutex_unlock(&register_mutex);
    1397         [ #  # ]:          0 :         if (copy_to_user(_tid, &id, sizeof(*_tid)))
    1398                 :            :                 return -EFAULT;
    1399                 :          0 :         return 0;
    1400                 :            : }
    1401                 :            : 
    1402                 :          0 : static int snd_timer_user_ginfo(struct file *file,
    1403                 :            :                                 struct snd_timer_ginfo __user *_ginfo)
    1404                 :            : {
    1405                 :            :         struct snd_timer_ginfo *ginfo;
    1406                 :            :         struct snd_timer_id tid;
    1407                 :            :         struct snd_timer *t;
    1408                 :            :         struct list_head *p;
    1409                 :            :         int err = 0;
    1410                 :            : 
    1411                 :          0 :         ginfo = memdup_user(_ginfo, sizeof(*ginfo));
    1412         [ #  # ]:          0 :         if (IS_ERR(ginfo))
    1413                 :            :                 return PTR_ERR(ginfo);
    1414                 :            : 
    1415                 :          0 :         tid = ginfo->tid;
    1416                 :          0 :         memset(ginfo, 0, sizeof(*ginfo));
    1417                 :          0 :         ginfo->tid = tid;
    1418                 :          0 :         mutex_lock(&register_mutex);
    1419                 :          0 :         t = snd_timer_find(&tid);
    1420         [ #  # ]:          0 :         if (t != NULL) {
    1421         [ #  # ]:          0 :                 ginfo->card = t->card ? t->card->number : -1;
    1422         [ #  # ]:          0 :                 if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
    1423                 :          0 :                         ginfo->flags |= SNDRV_TIMER_FLG_SLAVE;
    1424                 :          0 :                 strlcpy(ginfo->id, t->id, sizeof(ginfo->id));
    1425                 :          0 :                 strlcpy(ginfo->name, t->name, sizeof(ginfo->name));
    1426                 :          0 :                 ginfo->resolution = t->hw.resolution;
    1427         [ #  # ]:          0 :                 if (t->hw.resolution_min > 0) {
    1428                 :          0 :                         ginfo->resolution_min = t->hw.resolution_min;
    1429                 :          0 :                         ginfo->resolution_max = t->hw.resolution_max;
    1430                 :            :                 }
    1431         [ #  # ]:          0 :                 list_for_each(p, &t->open_list_head) {
    1432                 :          0 :                         ginfo->clients++;
    1433                 :            :                 }
    1434                 :            :         } else {
    1435                 :            :                 err = -ENODEV;
    1436                 :            :         }
    1437                 :          0 :         mutex_unlock(&register_mutex);
    1438 [ #  # ][ #  # ]:          0 :         if (err >= 0 && copy_to_user(_ginfo, ginfo, sizeof(*ginfo)))
    1439                 :            :                 err = -EFAULT;
    1440                 :          0 :         kfree(ginfo);
    1441                 :            :         return err;
    1442                 :            : }
    1443                 :            : 
    1444                 :          0 : static int snd_timer_user_gparams(struct file *file,
    1445                 :            :                                   struct snd_timer_gparams __user *_gparams)
    1446                 :            : {
    1447                 :            :         struct snd_timer_gparams gparams;
    1448                 :            :         struct snd_timer *t;
    1449                 :            :         int err;
    1450                 :            : 
    1451         [ #  # ]:          0 :         if (copy_from_user(&gparams, _gparams, sizeof(gparams)))
    1452                 :            :                 return -EFAULT;
    1453                 :          0 :         mutex_lock(&register_mutex);
    1454                 :          0 :         t = snd_timer_find(&gparams.tid);
    1455         [ #  # ]:          0 :         if (!t) {
    1456                 :            :                 err = -ENODEV;
    1457                 :            :                 goto _error;
    1458                 :            :         }
    1459         [ #  # ]:          0 :         if (!list_empty(&t->open_list_head)) {
    1460                 :            :                 err = -EBUSY;
    1461                 :            :                 goto _error;
    1462                 :            :         }
    1463         [ #  # ]:          0 :         if (!t->hw.set_period) {
    1464                 :            :                 err = -ENOSYS;
    1465                 :            :                 goto _error;
    1466                 :            :         }
    1467                 :          0 :         err = t->hw.set_period(t, gparams.period_num, gparams.period_den);
    1468                 :            : _error:
    1469                 :          0 :         mutex_unlock(&register_mutex);
    1470                 :            :         return err;
    1471                 :            : }
    1472                 :            : 
    1473                 :          0 : static int snd_timer_user_gstatus(struct file *file,
    1474                 :            :                                   struct snd_timer_gstatus __user *_gstatus)
    1475                 :            : {
    1476                 :            :         struct snd_timer_gstatus gstatus;
    1477                 :            :         struct snd_timer_id tid;
    1478                 :            :         struct snd_timer *t;
    1479                 :            :         int err = 0;
    1480                 :            : 
    1481         [ #  # ]:          0 :         if (copy_from_user(&gstatus, _gstatus, sizeof(gstatus)))
    1482                 :            :                 return -EFAULT;
    1483                 :          0 :         tid = gstatus.tid;
    1484                 :          0 :         memset(&gstatus, 0, sizeof(gstatus));
    1485                 :          0 :         gstatus.tid = tid;
    1486                 :          0 :         mutex_lock(&register_mutex);
    1487                 :          0 :         t = snd_timer_find(&tid);
    1488         [ #  # ]:          0 :         if (t != NULL) {
    1489         [ #  # ]:          0 :                 if (t->hw.c_resolution)
    1490                 :          0 :                         gstatus.resolution = t->hw.c_resolution(t);
    1491                 :            :                 else
    1492                 :          0 :                         gstatus.resolution = t->hw.resolution;
    1493         [ #  # ]:          0 :                 if (t->hw.precise_resolution) {
    1494                 :          0 :                         t->hw.precise_resolution(t, &gstatus.resolution_num,
    1495                 :            :                                                  &gstatus.resolution_den);
    1496                 :            :                 } else {
    1497                 :          0 :                         gstatus.resolution_num = gstatus.resolution;
    1498                 :          0 :                         gstatus.resolution_den = 1000000000uL;
    1499                 :            :                 }
    1500                 :            :         } else {
    1501                 :            :                 err = -ENODEV;
    1502                 :            :         }
    1503                 :          0 :         mutex_unlock(&register_mutex);
    1504 [ #  # ][ #  # ]:          0 :         if (err >= 0 && copy_to_user(_gstatus, &gstatus, sizeof(gstatus)))
    1505                 :            :                 err = -EFAULT;
    1506                 :            :         return err;
    1507                 :            : }
    1508                 :            : 
    1509                 :          0 : static int snd_timer_user_tselect(struct file *file,
    1510                 :            :                                   struct snd_timer_select __user *_tselect)
    1511                 :            : {
    1512                 :            :         struct snd_timer_user *tu;
    1513                 :            :         struct snd_timer_select tselect;
    1514                 :            :         char str[32];
    1515                 :            :         int err = 0;
    1516                 :            : 
    1517                 :          0 :         tu = file->private_data;
    1518                 :          0 :         mutex_lock(&tu->tread_sem);
    1519         [ #  # ]:          0 :         if (tu->timeri) {
    1520                 :          0 :                 snd_timer_close(tu->timeri);
    1521                 :          0 :                 tu->timeri = NULL;
    1522                 :            :         }
    1523         [ #  # ]:          0 :         if (copy_from_user(&tselect, _tselect, sizeof(tselect))) {
    1524                 :            :                 err = -EFAULT;
    1525                 :            :                 goto __err;
    1526                 :            :         }
    1527                 :          0 :         sprintf(str, "application %i", current->pid);
    1528         [ #  # ]:          0 :         if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE)
    1529                 :          0 :                 tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION;
    1530                 :          0 :         err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid);
    1531         [ #  # ]:          0 :         if (err < 0)
    1532                 :            :                 goto __err;
    1533                 :            : 
    1534                 :          0 :         kfree(tu->queue);
    1535                 :          0 :         tu->queue = NULL;
    1536                 :          0 :         kfree(tu->tqueue);
    1537                 :          0 :         tu->tqueue = NULL;
    1538         [ #  # ]:          0 :         if (tu->tread) {
    1539                 :          0 :                 tu->tqueue = kmalloc(tu->queue_size * sizeof(struct snd_timer_tread),
    1540                 :            :                                      GFP_KERNEL);
    1541         [ #  # ]:          0 :                 if (tu->tqueue == NULL)
    1542                 :            :                         err = -ENOMEM;
    1543                 :            :         } else {
    1544                 :          0 :                 tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
    1545                 :            :                                     GFP_KERNEL);
    1546         [ #  # ]:          0 :                 if (tu->queue == NULL)
    1547                 :            :                         err = -ENOMEM;
    1548                 :            :         }
    1549                 :            : 
    1550         [ #  # ]:          0 :         if (err < 0) {
    1551                 :          0 :                 snd_timer_close(tu->timeri);
    1552                 :          0 :                 tu->timeri = NULL;
    1553                 :            :         } else {
    1554                 :          0 :                 tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
    1555                 :          0 :                 tu->timeri->callback = tu->tread
    1556         [ #  # ]:          0 :                         ? snd_timer_user_tinterrupt : snd_timer_user_interrupt;
    1557                 :          0 :                 tu->timeri->ccallback = snd_timer_user_ccallback;
    1558                 :          0 :                 tu->timeri->callback_data = (void *)tu;
    1559                 :            :         }
    1560                 :            : 
    1561                 :            :       __err:
    1562                 :          0 :         mutex_unlock(&tu->tread_sem);
    1563                 :          0 :         return err;
    1564                 :            : }
    1565                 :            : 
    1566                 :          0 : static int snd_timer_user_info(struct file *file,
    1567                 :            :                                struct snd_timer_info __user *_info)
    1568                 :            : {
    1569                 :            :         struct snd_timer_user *tu;
    1570                 :            :         struct snd_timer_info *info;
    1571                 :            :         struct snd_timer *t;
    1572                 :            :         int err = 0;
    1573                 :            : 
    1574                 :          0 :         tu = file->private_data;
    1575         [ #  # ]:          0 :         if (!tu->timeri)
    1576                 :            :                 return -EBADFD;
    1577                 :          0 :         t = tu->timeri->timer;
    1578         [ #  # ]:          0 :         if (!t)
    1579                 :            :                 return -EBADFD;
    1580                 :            : 
    1581                 :            :         info = kzalloc(sizeof(*info), GFP_KERNEL);
    1582         [ #  # ]:          0 :         if (! info)
    1583                 :            :                 return -ENOMEM;
    1584         [ #  # ]:          0 :         info->card = t->card ? t->card->number : -1;
    1585         [ #  # ]:          0 :         if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
    1586                 :          0 :                 info->flags |= SNDRV_TIMER_FLG_SLAVE;
    1587                 :          0 :         strlcpy(info->id, t->id, sizeof(info->id));
    1588                 :          0 :         strlcpy(info->name, t->name, sizeof(info->name));
    1589                 :          0 :         info->resolution = t->hw.resolution;
    1590         [ #  # ]:          0 :         if (copy_to_user(_info, info, sizeof(*_info)))
    1591                 :            :                 err = -EFAULT;
    1592                 :          0 :         kfree(info);
    1593                 :            :         return err;
    1594                 :            : }
    1595                 :            : 
    1596                 :          0 : static int snd_timer_user_params(struct file *file,
    1597                 :            :                                  struct snd_timer_params __user *_params)
    1598                 :            : {
    1599                 :            :         struct snd_timer_user *tu;
    1600                 :            :         struct snd_timer_params params;
    1601                 :            :         struct snd_timer *t;
    1602                 :            :         struct snd_timer_read *tr;
    1603                 :            :         struct snd_timer_tread *ttr;
    1604                 :            :         int err;
    1605                 :            : 
    1606                 :          0 :         tu = file->private_data;
    1607         [ #  # ]:          0 :         if (!tu->timeri)
    1608                 :            :                 return -EBADFD;
    1609                 :          0 :         t = tu->timeri->timer;
    1610         [ #  # ]:          0 :         if (!t)
    1611                 :            :                 return -EBADFD;
    1612         [ #  # ]:          0 :         if (copy_from_user(&params, _params, sizeof(params)))
    1613                 :            :                 return -EFAULT;
    1614 [ #  # ][ #  # ]:          0 :         if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE) && params.ticks < 1) {
    1615                 :            :                 err = -EINVAL;
    1616                 :            :                 goto _end;
    1617                 :            :         }
    1618         [ #  # ]:          0 :         if (params.queue_size > 0 &&
    1619                 :            :             (params.queue_size < 32 || params.queue_size > 1024)) {
    1620                 :            :                 err = -EINVAL;
    1621                 :            :                 goto _end;
    1622                 :            :         }
    1623         [ #  # ]:          0 :         if (params.filter & ~((1<<SNDRV_TIMER_EVENT_RESOLUTION)|
    1624                 :            :                               (1<<SNDRV_TIMER_EVENT_TICK)|
    1625                 :            :                               (1<<SNDRV_TIMER_EVENT_START)|
    1626                 :            :                               (1<<SNDRV_TIMER_EVENT_STOP)|
    1627                 :            :                               (1<<SNDRV_TIMER_EVENT_CONTINUE)|
    1628                 :            :                               (1<<SNDRV_TIMER_EVENT_PAUSE)|
    1629                 :            :                               (1<<SNDRV_TIMER_EVENT_SUSPEND)|
    1630                 :            :                               (1<<SNDRV_TIMER_EVENT_RESUME)|
    1631                 :            :                               (1<<SNDRV_TIMER_EVENT_MSTART)|
    1632                 :            :                               (1<<SNDRV_TIMER_EVENT_MSTOP)|
    1633                 :            :                               (1<<SNDRV_TIMER_EVENT_MCONTINUE)|
    1634                 :            :                               (1<<SNDRV_TIMER_EVENT_MPAUSE)|
    1635                 :            :                               (1<<SNDRV_TIMER_EVENT_MSUSPEND)|
    1636                 :            :                               (1<<SNDRV_TIMER_EVENT_MRESUME))) {
    1637                 :            :                 err = -EINVAL;
    1638                 :            :                 goto _end;
    1639                 :            :         }
    1640                 :          0 :         snd_timer_stop(tu->timeri);
    1641                 :            :         spin_lock_irq(&t->lock);
    1642                 :          0 :         tu->timeri->flags &= ~(SNDRV_TIMER_IFLG_AUTO|
    1643                 :            :                                SNDRV_TIMER_IFLG_EXCLUSIVE|
    1644                 :            :                                SNDRV_TIMER_IFLG_EARLY_EVENT);
    1645         [ #  # ]:          0 :         if (params.flags & SNDRV_TIMER_PSFLG_AUTO)
    1646                 :          0 :                 tu->timeri->flags |= SNDRV_TIMER_IFLG_AUTO;
    1647         [ #  # ]:          0 :         if (params.flags & SNDRV_TIMER_PSFLG_EXCLUSIVE)
    1648                 :          0 :                 tu->timeri->flags |= SNDRV_TIMER_IFLG_EXCLUSIVE;
    1649         [ #  # ]:          0 :         if (params.flags & SNDRV_TIMER_PSFLG_EARLY_EVENT)
    1650                 :          0 :                 tu->timeri->flags |= SNDRV_TIMER_IFLG_EARLY_EVENT;
    1651                 :            :         spin_unlock_irq(&t->lock);
    1652 [ #  # ][ #  # ]:          0 :         if (params.queue_size > 0 &&
    1653                 :          0 :             (unsigned int)tu->queue_size != params.queue_size) {
    1654         [ #  # ]:          0 :                 if (tu->tread) {
    1655                 :          0 :                         ttr = kmalloc(params.queue_size * sizeof(*ttr),
    1656                 :            :                                       GFP_KERNEL);
    1657         [ #  # ]:          0 :                         if (ttr) {
    1658                 :          0 :                                 kfree(tu->tqueue);
    1659                 :          0 :                                 tu->queue_size = params.queue_size;
    1660                 :          0 :                                 tu->tqueue = ttr;
    1661                 :            :                         }
    1662                 :            :                 } else {
    1663                 :          0 :                         tr = kmalloc(params.queue_size * sizeof(*tr),
    1664                 :            :                                      GFP_KERNEL);
    1665         [ #  # ]:          0 :                         if (tr) {
    1666                 :          0 :                                 kfree(tu->queue);
    1667                 :          0 :                                 tu->queue_size = params.queue_size;
    1668                 :          0 :                                 tu->queue = tr;
    1669                 :            :                         }
    1670                 :            :                 }
    1671                 :            :         }
    1672                 :          0 :         tu->qhead = tu->qtail = tu->qused = 0;
    1673         [ #  # ]:          0 :         if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) {
    1674         [ #  # ]:          0 :                 if (tu->tread) {
    1675                 :            :                         struct snd_timer_tread tread;
    1676                 :          0 :                         tread.event = SNDRV_TIMER_EVENT_EARLY;
    1677                 :          0 :                         tread.tstamp.tv_sec = 0;
    1678                 :          0 :                         tread.tstamp.tv_nsec = 0;
    1679                 :          0 :                         tread.val = 0;
    1680                 :          0 :                         snd_timer_user_append_to_tqueue(tu, &tread);
    1681                 :            :                 } else {
    1682                 :          0 :                         struct snd_timer_read *r = &tu->queue[0];
    1683                 :          0 :                         r->resolution = 0;
    1684                 :          0 :                         r->ticks = 0;
    1685                 :          0 :                         tu->qused++;
    1686                 :          0 :                         tu->qtail++;
    1687                 :            :                 }
    1688                 :            :         }
    1689                 :          0 :         tu->filter = params.filter;
    1690                 :          0 :         tu->ticks = params.ticks;
    1691                 :            :         err = 0;
    1692                 :            :  _end:
    1693         [ #  # ]:          0 :         if (copy_to_user(_params, &params, sizeof(params)))
    1694                 :            :                 return -EFAULT;
    1695                 :            :         return err;
    1696                 :            : }
    1697                 :            : 
    1698                 :          0 : static int snd_timer_user_status(struct file *file,
    1699                 :            :                                  struct snd_timer_status __user *_status)
    1700                 :            : {
    1701                 :            :         struct snd_timer_user *tu;
    1702                 :            :         struct snd_timer_status status;
    1703                 :            : 
    1704                 :          0 :         tu = file->private_data;
    1705         [ #  # ]:          0 :         if (!tu->timeri)
    1706                 :            :                 return -EBADFD;
    1707                 :          0 :         memset(&status, 0, sizeof(status));
    1708                 :          0 :         status.tstamp = tu->tstamp;
    1709                 :          0 :         status.resolution = snd_timer_resolution(tu->timeri);
    1710                 :          0 :         status.lost = tu->timeri->lost;
    1711                 :          0 :         status.overrun = tu->overrun;
    1712                 :            :         spin_lock_irq(&tu->qlock);
    1713                 :          0 :         status.queue = tu->qused;
    1714                 :            :         spin_unlock_irq(&tu->qlock);
    1715         [ #  # ]:          0 :         if (copy_to_user(_status, &status, sizeof(status)))
    1716                 :            :                 return -EFAULT;
    1717                 :            :         return 0;
    1718                 :            : }
    1719                 :            : 
    1720                 :          0 : static int snd_timer_user_start(struct file *file)
    1721                 :            : {
    1722                 :            :         int err;
    1723                 :            :         struct snd_timer_user *tu;
    1724                 :            : 
    1725                 :          0 :         tu = file->private_data;
    1726         [ #  # ]:          0 :         if (!tu->timeri)
    1727                 :            :                 return -EBADFD;
    1728                 :          0 :         snd_timer_stop(tu->timeri);
    1729                 :          0 :         tu->timeri->lost = 0;
    1730                 :          0 :         tu->last_resolution = 0;
    1731         [ #  # ]:          0 :         return (err = snd_timer_start(tu->timeri, tu->ticks)) < 0 ? err : 0;
    1732                 :            : }
    1733                 :            : 
    1734                 :            : static int snd_timer_user_stop(struct file *file)
    1735                 :            : {
    1736                 :            :         int err;
    1737                 :            :         struct snd_timer_user *tu;
    1738                 :            : 
    1739                 :            :         tu = file->private_data;
    1740         [ #  # ]:          0 :         if (!tu->timeri)
    1741                 :            :                 return -EBADFD;
    1742         [ #  # ]:          0 :         return (err = snd_timer_stop(tu->timeri)) < 0 ? err : 0;
    1743                 :            : }
    1744                 :            : 
    1745                 :          0 : static int snd_timer_user_continue(struct file *file)
    1746                 :            : {
    1747                 :            :         int err;
    1748                 :            :         struct snd_timer_user *tu;
    1749                 :            : 
    1750                 :          0 :         tu = file->private_data;
    1751         [ #  # ]:          0 :         if (!tu->timeri)
    1752                 :            :                 return -EBADFD;
    1753                 :          0 :         tu->timeri->lost = 0;
    1754         [ #  # ]:          0 :         return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0;
    1755                 :            : }
    1756                 :            : 
    1757                 :          0 : static int snd_timer_user_pause(struct file *file)
    1758                 :            : {
    1759                 :            :         int err;
    1760                 :            :         struct snd_timer_user *tu;
    1761                 :            : 
    1762                 :          0 :         tu = file->private_data;
    1763         [ #  # ]:          0 :         if (!tu->timeri)
    1764                 :            :                 return -EBADFD;
    1765         [ #  # ]:          0 :         return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0;
    1766                 :            : }
    1767                 :            : 
    1768                 :            : enum {
    1769                 :            :         SNDRV_TIMER_IOCTL_START_OLD = _IO('T', 0x20),
    1770                 :            :         SNDRV_TIMER_IOCTL_STOP_OLD = _IO('T', 0x21),
    1771                 :            :         SNDRV_TIMER_IOCTL_CONTINUE_OLD = _IO('T', 0x22),
    1772                 :            :         SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
    1773                 :            : };
    1774                 :            : 
    1775                 :          0 : static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
    1776                 :            :                                  unsigned long arg)
    1777                 :            : {
    1778                 :            :         struct snd_timer_user *tu;
    1779                 :          0 :         void __user *argp = (void __user *)arg;
    1780                 :            :         int __user *p = argp;
    1781                 :            : 
    1782                 :          0 :         tu = file->private_data;
    1783   [ #  #  #  #  :          0 :         switch (cmd) {
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    1784                 :            :         case SNDRV_TIMER_IOCTL_PVERSION:
    1785         [ #  # ]:          0 :                 return put_user(SNDRV_TIMER_VERSION, p) ? -EFAULT : 0;
    1786                 :            :         case SNDRV_TIMER_IOCTL_NEXT_DEVICE:
    1787                 :          0 :                 return snd_timer_user_next_device(argp);
    1788                 :            :         case SNDRV_TIMER_IOCTL_TREAD:
    1789                 :            :         {
    1790                 :            :                 int xarg;
    1791                 :            : 
    1792                 :          0 :                 mutex_lock(&tu->tread_sem);
    1793         [ #  # ]:          0 :                 if (tu->timeri)      {       /* too late */
    1794                 :          0 :                         mutex_unlock(&tu->tread_sem);
    1795                 :          0 :                         return -EBUSY;
    1796                 :            :                 }
    1797         [ #  # ]:          0 :                 if (get_user(xarg, p)) {
    1798                 :          0 :                         mutex_unlock(&tu->tread_sem);
    1799                 :          0 :                         return -EFAULT;
    1800                 :            :                 }
    1801                 :          0 :                 tu->tread = xarg ? 1 : 0;
    1802                 :          0 :                 mutex_unlock(&tu->tread_sem);
    1803                 :          0 :                 return 0;
    1804                 :            :         }
    1805                 :            :         case SNDRV_TIMER_IOCTL_GINFO:
    1806                 :          0 :                 return snd_timer_user_ginfo(file, argp);
    1807                 :            :         case SNDRV_TIMER_IOCTL_GPARAMS:
    1808                 :          0 :                 return snd_timer_user_gparams(file, argp);
    1809                 :            :         case SNDRV_TIMER_IOCTL_GSTATUS:
    1810                 :          0 :                 return snd_timer_user_gstatus(file, argp);
    1811                 :            :         case SNDRV_TIMER_IOCTL_SELECT:
    1812                 :          0 :                 return snd_timer_user_tselect(file, argp);
    1813                 :            :         case SNDRV_TIMER_IOCTL_INFO:
    1814                 :          0 :                 return snd_timer_user_info(file, argp);
    1815                 :            :         case SNDRV_TIMER_IOCTL_PARAMS:
    1816                 :          0 :                 return snd_timer_user_params(file, argp);
    1817                 :            :         case SNDRV_TIMER_IOCTL_STATUS:
    1818                 :          0 :                 return snd_timer_user_status(file, argp);
    1819                 :            :         case SNDRV_TIMER_IOCTL_START:
    1820                 :            :         case SNDRV_TIMER_IOCTL_START_OLD:
    1821                 :          0 :                 return snd_timer_user_start(file);
    1822                 :            :         case SNDRV_TIMER_IOCTL_STOP:
    1823                 :            :         case SNDRV_TIMER_IOCTL_STOP_OLD:
    1824                 :          0 :                 return snd_timer_user_stop(file);
    1825                 :            :         case SNDRV_TIMER_IOCTL_CONTINUE:
    1826                 :            :         case SNDRV_TIMER_IOCTL_CONTINUE_OLD:
    1827                 :          0 :                 return snd_timer_user_continue(file);
    1828                 :            :         case SNDRV_TIMER_IOCTL_PAUSE:
    1829                 :            :         case SNDRV_TIMER_IOCTL_PAUSE_OLD:
    1830                 :          0 :                 return snd_timer_user_pause(file);
    1831                 :            :         }
    1832                 :            :         return -ENOTTY;
    1833                 :            : }
    1834                 :            : 
    1835                 :          0 : static int snd_timer_user_fasync(int fd, struct file * file, int on)
    1836                 :            : {
    1837                 :            :         struct snd_timer_user *tu;
    1838                 :            : 
    1839                 :          0 :         tu = file->private_data;
    1840                 :          0 :         return fasync_helper(fd, file, on, &tu->fasync);
    1841                 :            : }
    1842                 :            : 
    1843                 :          0 : static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
    1844                 :            :                                    size_t count, loff_t *offset)
    1845                 :            : {
    1846                 :            :         struct snd_timer_user *tu;
    1847                 :            :         long result = 0, unit;
    1848                 :            :         int err = 0;
    1849                 :            : 
    1850                 :          0 :         tu = file->private_data;
    1851         [ #  # ]:          0 :         unit = tu->tread ? sizeof(struct snd_timer_tread) : sizeof(struct snd_timer_read);
    1852                 :            :         spin_lock_irq(&tu->qlock);
    1853         [ #  # ]:          0 :         while ((long)count - result >= unit) {
    1854         [ #  # ]:          0 :                 while (!tu->qused) {
    1855                 :            :                         wait_queue_t wait;
    1856                 :            : 
    1857 [ #  # ][ #  # ]:          0 :                         if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
    1858                 :            :                                 err = -EAGAIN;
    1859                 :          0 :                                 break;
    1860                 :            :                         }
    1861                 :            : 
    1862                 :          0 :                         set_current_state(TASK_INTERRUPTIBLE);
    1863                 :          0 :                         init_waitqueue_entry(&wait, current);
    1864                 :          0 :                         add_wait_queue(&tu->qchange_sleep, &wait);
    1865                 :            : 
    1866                 :            :                         spin_unlock_irq(&tu->qlock);
    1867                 :          0 :                         schedule();
    1868                 :            :                         spin_lock_irq(&tu->qlock);
    1869                 :            : 
    1870                 :          0 :                         remove_wait_queue(&tu->qchange_sleep, &wait);
    1871                 :            : 
    1872         [ #  # ]:          0 :                         if (signal_pending(current)) {
    1873                 :            :                                 err = -ERESTARTSYS;
    1874                 :            :                                 break;
    1875                 :            :                         }
    1876                 :            :                 }
    1877                 :            : 
    1878                 :            :                 spin_unlock_irq(&tu->qlock);
    1879         [ #  # ]:          0 :                 if (err < 0)
    1880                 :            :                         goto _error;
    1881                 :            : 
    1882         [ #  # ]:          0 :                 if (tu->tread) {
    1883         [ #  # ]:          0 :                         if (copy_to_user(buffer, &tu->tqueue[tu->qhead++],
    1884                 :            :                                          sizeof(struct snd_timer_tread))) {
    1885                 :            :                                 err = -EFAULT;
    1886                 :            :                                 goto _error;
    1887                 :            :                         }
    1888                 :            :                 } else {
    1889         [ #  # ]:          0 :                         if (copy_to_user(buffer, &tu->queue[tu->qhead++],
    1890                 :            :                                          sizeof(struct snd_timer_read))) {
    1891                 :            :                                 err = -EFAULT;
    1892                 :            :                                 goto _error;
    1893                 :            :                         }
    1894                 :            :                 }
    1895                 :            : 
    1896                 :          0 :                 tu->qhead %= tu->queue_size;
    1897                 :            : 
    1898                 :          0 :                 result += unit;
    1899                 :          0 :                 buffer += unit;
    1900                 :            : 
    1901                 :            :                 spin_lock_irq(&tu->qlock);
    1902                 :          0 :                 tu->qused--;
    1903                 :            :         }
    1904                 :            :         spin_unlock_irq(&tu->qlock);
    1905                 :            :  _error:
    1906         [ #  # ]:          0 :         return result > 0 ? result : err;
    1907                 :            : }
    1908                 :            : 
    1909                 :          0 : static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait)
    1910                 :            : {
    1911                 :            :         unsigned int mask;
    1912                 :            :         struct snd_timer_user *tu;
    1913                 :            : 
    1914                 :          0 :         tu = file->private_data;
    1915                 :            : 
    1916                 :          0 :         poll_wait(file, &tu->qchange_sleep, wait);
    1917                 :            : 
    1918                 :            :         mask = 0;
    1919         [ #  # ]:          0 :         if (tu->qused)
    1920                 :            :                 mask |= POLLIN | POLLRDNORM;
    1921                 :            : 
    1922                 :          0 :         return mask;
    1923                 :            : }
    1924                 :            : 
    1925                 :            : #ifdef CONFIG_COMPAT
    1926                 :            : #include "timer_compat.c"
    1927                 :            : #else
    1928                 :            : #define snd_timer_user_ioctl_compat     NULL
    1929                 :            : #endif
    1930                 :            : 
    1931                 :            : static const struct file_operations snd_timer_f_ops =
    1932                 :            : {
    1933                 :            :         .owner =        THIS_MODULE,
    1934                 :            :         .read =         snd_timer_user_read,
    1935                 :            :         .open =         snd_timer_user_open,
    1936                 :            :         .release =      snd_timer_user_release,
    1937                 :            :         .llseek =       no_llseek,
    1938                 :            :         .poll =         snd_timer_user_poll,
    1939                 :            :         .unlocked_ioctl =       snd_timer_user_ioctl,
    1940                 :            :         .compat_ioctl = snd_timer_user_ioctl_compat,
    1941                 :            :         .fasync =       snd_timer_user_fasync,
    1942                 :            : };
    1943                 :            : 
    1944                 :            : /*
    1945                 :            :  *  ENTRY functions
    1946                 :            :  */
    1947                 :            : 
    1948                 :          0 : static int __init alsa_timer_init(void)
    1949                 :            : {
    1950                 :            :         int err;
    1951                 :            : 
    1952                 :            : #ifdef SNDRV_OSS_INFO_DEV_TIMERS
    1953                 :            :         snd_oss_info_register(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1,
    1954                 :            :                               "system timer");
    1955                 :            : #endif
    1956                 :            : 
    1957         [ #  # ]:          0 :         if ((err = snd_timer_register_system()) < 0)
    1958                 :          0 :                 snd_printk(KERN_ERR "unable to register system timer (%i)\n",
    1959                 :            :                            err);
    1960         [ #  # ]:          0 :         if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0,
    1961                 :            :                                        &snd_timer_f_ops, NULL, "timer")) < 0)
    1962                 :          0 :                 snd_printk(KERN_ERR "unable to register timer device (%i)\n",
    1963                 :            :                            err);
    1964                 :          0 :         snd_timer_proc_init();
    1965                 :          0 :         return 0;
    1966                 :            : }
    1967                 :            : 
    1968                 :          0 : static void __exit alsa_timer_exit(void)
    1969                 :            : {
    1970                 :            :         struct list_head *p, *n;
    1971                 :            : 
    1972                 :          0 :         snd_unregister_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0);
    1973                 :            :         /* unregister the system timer */
    1974         [ #  # ]:          0 :         list_for_each_safe(p, n, &snd_timer_list) {
    1975                 :          0 :                 struct snd_timer *timer = list_entry(p, struct snd_timer, device_list);
    1976                 :          0 :                 snd_timer_free(timer);
    1977                 :            :         }
    1978                 :          0 :         snd_timer_proc_done();
    1979                 :            : #ifdef SNDRV_OSS_INFO_DEV_TIMERS
    1980                 :            :         snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1);
    1981                 :            : #endif
    1982                 :          0 : }
    1983                 :            : 
    1984                 :            : module_init(alsa_timer_init)
    1985                 :            : module_exit(alsa_timer_exit)
    1986                 :            : 
    1987                 :            : EXPORT_SYMBOL(snd_timer_open);
    1988                 :            : EXPORT_SYMBOL(snd_timer_close);
    1989                 :            : EXPORT_SYMBOL(snd_timer_resolution);
    1990                 :            : EXPORT_SYMBOL(snd_timer_start);
    1991                 :            : EXPORT_SYMBOL(snd_timer_stop);
    1992                 :            : EXPORT_SYMBOL(snd_timer_continue);
    1993                 :            : EXPORT_SYMBOL(snd_timer_pause);
    1994                 :            : EXPORT_SYMBOL(snd_timer_new);
    1995                 :            : EXPORT_SYMBOL(snd_timer_notify);
    1996                 :            : EXPORT_SYMBOL(snd_timer_global_new);
    1997                 :            : EXPORT_SYMBOL(snd_timer_global_free);
    1998                 :            : EXPORT_SYMBOL(snd_timer_global_register);
    1999                 :            : EXPORT_SYMBOL(snd_timer_interrupt);

Generated by: LCOV version 1.9