ALSA: timer: Code cleanup
[pandora-kernel.git] / sound / core / timer.c
index bc83a96..ffecc44 100644 (file)
@@ -290,8 +290,19 @@ int snd_timer_open(struct snd_timer_instance **ti,
        }
        timeri->slave_class = tid->dev_sclass;
        timeri->slave_id = slave_id;
-       if (list_empty(&timer->open_list_head) && timer->hw.open)
-               timer->hw.open(timer);
+
+       if (list_empty(&timer->open_list_head) && timer->hw.open) {
+               int err = timer->hw.open(timer);
+               if (err) {
+                       kfree(timeri->owner);
+                       kfree(timeri);
+
+                       module_put(timer->module);
+                       mutex_unlock(&register_mutex);
+                       return err;
+               }
+       }
+
        list_add_tail(&timeri->open_list, &timer->open_list_head);
        snd_timer_check_master(timeri);
        mutex_unlock(&register_mutex);
@@ -299,8 +310,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
        return 0;
 }
 
-static int _snd_timer_stop(struct snd_timer_instance *timeri,
-                          int keep_flag, int event);
+static int _snd_timer_stop(struct snd_timer_instance *timeri, int event);
 
 /*
  * close a timer instance
@@ -342,7 +352,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
                spin_unlock_irq(&timer->lock);
                mutex_lock(&register_mutex);
                list_del(&timeri->open_list);
-               if (timer && list_empty(&timer->open_list_head) &&
+               if (list_empty(&timer->open_list_head) &&
                    timer->hw.close)
                        timer->hw.close(timer);
                /* remove slave links */
@@ -494,8 +504,7 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
        return result;
 }
 
-static int _snd_timer_stop(struct snd_timer_instance * timeri,
-                          int keep_flag, int event)
+static int _snd_timer_stop(struct snd_timer_instance *timeri, int event)
 {
        struct snd_timer *timer;
        unsigned long flags;
@@ -504,21 +513,19 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri,
                return -ENXIO;
 
        if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
-               if (!keep_flag) {
-                       spin_lock_irqsave(&slave_active_lock, flags);
-                       if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) {
-                               spin_unlock_irqrestore(&slave_active_lock, flags);
-                               return -EBUSY;
-                       }
-                       if (timeri->timer)
-                               spin_lock(&timeri->timer->lock);
-                       timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
-                       list_del_init(&timeri->ack_list);
-                       list_del_init(&timeri->active_list);
-                       if (timeri->timer)
-                               spin_unlock(&timeri->timer->lock);
+               spin_lock_irqsave(&slave_active_lock, flags);
+               if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) {
                        spin_unlock_irqrestore(&slave_active_lock, flags);
+                       return -EBUSY;
                }
+               if (timeri->timer)
+                       spin_lock(&timeri->timer->lock);
+               timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
+               list_del_init(&timeri->ack_list);
+               list_del_init(&timeri->active_list);
+               if (timeri->timer)
+                       spin_unlock(&timeri->timer->lock);
+               spin_unlock_irqrestore(&slave_active_lock, flags);
                goto __end;
        }
        timer = timeri->timer;
@@ -544,9 +551,7 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri,
                        }
                }
        }
-       if (!keep_flag)
-               timeri->flags &=
-                       ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START);
+       timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START);
        spin_unlock_irqrestore(&timer->lock, flags);
       __end:
        if (event != SNDRV_TIMER_EVENT_RESOLUTION)
@@ -565,7 +570,7 @@ int snd_timer_stop(struct snd_timer_instance *timeri)
        unsigned long flags;
        int err;
 
-       err = _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_STOP);
+       err = _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_STOP);
        if (err < 0)
                return err;
        timer = timeri->timer;
@@ -614,7 +619,7 @@ int snd_timer_continue(struct snd_timer_instance *timeri)
  */
 int snd_timer_pause(struct snd_timer_instance * timeri)
 {
-       return _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_PAUSE);
+       return _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_PAUSE);
 }
 
 /*
@@ -822,6 +827,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
        timer->tmr_subdevice = tid->subdevice;
        if (id)
                strlcpy(timer->id, id, sizeof(timer->id));
+       timer->sticks = 1;
        INIT_LIST_HEAD(&timer->device_list);
        INIT_LIST_HEAD(&timer->open_list_head);
        INIT_LIST_HEAD(&timer->active_list_head);
@@ -1213,6 +1219,7 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri,
                tu->tstamp = *tstamp;
        if ((tu->filter & (1 << event)) == 0 || !tu->tread)
                return;
+       memset(&r1, 0, sizeof(r1));
        r1.event = event;
        r1.tstamp = *tstamp;
        r1.val = resolution;
@@ -1247,6 +1254,7 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
        }
        if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) &&
            tu->last_resolution != resolution) {
+               memset(&r1, 0, sizeof(r1));
                r1.event = SNDRV_TIMER_EVENT_RESOLUTION;
                r1.tstamp = tstamp;
                r1.val = resolution;
@@ -1712,6 +1720,7 @@ static int snd_timer_user_params(struct file *file,
        if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) {
                if (tu->tread) {
                        struct snd_timer_tread tread;
+                       memset(&tread, 0, sizeof(tread));
                        tread.event = SNDRV_TIMER_EVENT_EARLY;
                        tread.tstamp.tv_sec = 0;
                        tread.tstamp.tv_nsec = 0;
@@ -1923,8 +1932,10 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
 
                qhead = tu->qhead++;
                tu->qhead %= tu->queue_size;
+               tu->qused--;
                spin_unlock_irq(&tu->qlock);
 
+               mutex_lock(&tu->ioctl_lock);
                if (tu->tread) {
                        if (copy_to_user(buffer, &tu->tqueue[qhead],
                                         sizeof(struct snd_timer_tread)))
@@ -1934,9 +1945,9 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
                                         sizeof(struct snd_timer_read)))
                                err = -EFAULT;
                }
+               mutex_unlock(&tu->ioctl_lock);
 
                spin_lock_irq(&tu->qlock);
-               tu->qused--;
                if (err < 0)
                        goto _error;
                result += unit;