]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - sound/usb/usx2y/us122l.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / 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;
 }