ALSA: snd-usb-us122l: Fix missing NULL checks
authorKarsten Wiese <fzu@wemgehoertderstaat.de>
Tue, 4 Jan 2011 00:20:37 +0000 (01:20 +0100)
committerTakashi Iwai <tiwai@suse.de>
Tue, 11 Jan 2011 18:50:28 +0000 (19:50 +0100)
Fix missing NULL checks in usb_stream_hwdep_poll() and usb_stream_hwdep_ioctl().
Wake up poll waiters before returning from usb_stream_hwdep_ioctl().

Signed-off-by: Karsten Wiese <fzu@wemgehoertderstaat.de>
Cc: stable@kernel.org
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/usb/usx2y/us122l.c

index 6ef68e42138e4a3e0f2b05975c7b7013d8fa3b7f..084e6fc8d5bf1e6f74f6e3f377bd34b517586d85 100644 (file)
@@ -273,29 +273,26 @@ static unsigned int usb_stream_hwdep_poll(struct snd_hwdep *hw,
                                          struct file *file, poll_table *wait)
 {
        struct us122l   *us122l = hw->private_data;
-       struct usb_stream *s = us122l->sk.s;
        unsigned        *polled;
        unsigned int    mask;
 
        poll_wait(file, &us122l->sk.sleep, wait);
 
-       switch (s->state) {
-       case usb_stream_ready:
-               if (us122l->first == file)
-                       polled = &s->periods_polled;
-               else
-                       polled = &us122l->second_periods_polled;
-               if (*polled != s->periods_done) {
-                       *polled = s->periods_done;
-                       mask = POLLIN | POLLOUT | POLLWRNORM;
-                       break;
+       mask = POLLIN | POLLOUT | POLLWRNORM | POLLERR;
+       if (mutex_trylock(&us122l->mutex)) {
+               struct usb_stream *s = us122l->sk.s;
+               if (s && s->state == usb_stream_ready) {
+                       if (us122l->first == file)
+                               polled = &s->periods_polled;
+                       else
+                               polled = &us122l->second_periods_polled;
+                       if (*polled != s->periods_done) {
+                               *polled = s->periods_done;
+                               mask = POLLIN | POLLOUT | POLLWRNORM;
+                       } else
+                               mask = 0;
                }
-               /* Fall through */
-               mask = 0;
-               break;
-       default:
-               mask = POLLIN | POLLOUT | POLLWRNORM | POLLERR;
-               break;
+               mutex_unlock(&us122l->mutex);
        }
        return mask;
 }
@@ -381,6 +378,7 @@ static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
 {
        struct usb_stream_config *cfg;
        struct us122l *us122l = hw->private_data;
+       struct usb_stream *s;
        unsigned min_period_frames;
        int err = 0;
        bool high_speed;
@@ -426,18 +424,18 @@ static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
        snd_power_wait(hw->card, SNDRV_CTL_POWER_D0);
 
        mutex_lock(&us122l->mutex);
+       s = us122l->sk.s;
        if (!us122l->master)
                us122l->master = file;
        else if (us122l->master != file) {
-               if (memcmp(cfg, &us122l->sk.s->cfg, sizeof(*cfg))) {
+               if (!s || memcmp(cfg, &s->cfg, sizeof(*cfg))) {
                        err = -EIO;
                        goto unlock;
                }
                us122l->slave = file;
        }
-       if (!us122l->sk.s ||
-           memcmp(cfg, &us122l->sk.s->cfg, sizeof(*cfg)) ||
-           us122l->sk.s->state == usb_stream_xrun) {
+       if (!s || memcmp(cfg, &s->cfg, sizeof(*cfg)) ||
+           s->state == usb_stream_xrun) {
                us122l_stop(us122l);
                if (!us122l_start(us122l, cfg->sample_rate, cfg->period_frames))
                        err = -EIO;
@@ -448,6 +446,7 @@ unlock:
        mutex_unlock(&us122l->mutex);
 free:
        kfree(cfg);
+       wake_up_all(&us122l->sk.sleep);
        return err;
 }