rk: revert to v3.10
[firefly-linux-kernel-4.4.55.git] / sound / usb / usx2y / usbusx2yaudio.c
index cd69a80b5ca9d1506683694c87f02ec511ab4aec..b37653247ef4e035b096153253b69ca0fd1e9a8b 100644 (file)
@@ -273,11 +273,7 @@ static void usX2Y_clients_stop(struct usX2Ydev *usX2Y)
                struct snd_usX2Y_substream *subs = usX2Y->subs[s];
                if (subs) {
                        if (atomic_read(&subs->state) >= state_PRERUNNING) {
-                               unsigned long flags;
-
-                               snd_pcm_stream_lock_irqsave(subs->pcm_substream, flags);
                                snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN);
-                               snd_pcm_stream_unlock_irqrestore(subs->pcm_substream, flags);
                        }
                        for (u = 0; u < NRURBS; u++) {
                                struct urb *urb = subs->urb[u];
@@ -299,6 +295,19 @@ static void usX2Y_error_urb_status(struct usX2Ydev *usX2Y,
        usX2Y_clients_stop(usX2Y);
 }
 
+static void usX2Y_error_sequence(struct usX2Ydev *usX2Y,
+                                struct snd_usX2Y_substream *subs, struct urb *urb)
+{
+       snd_printk(KERN_ERR
+"Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n"
+"Most probably some urb of usb-frame %i is still missing.\n"
+"Cause could be too long delays in usb-hcd interrupt handling.\n",
+                  usb_get_current_frame_number(usX2Y->dev),
+                  subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
+                  usX2Y->wait_iso_frame, urb->start_frame, usX2Y->wait_iso_frame);
+       usX2Y_clients_stop(usX2Y);
+}
+
 static void i_usX2Y_urb_complete(struct urb *urb)
 {
        struct snd_usX2Y_substream *subs = urb->context;
@@ -315,9 +324,12 @@ static void i_usX2Y_urb_complete(struct urb *urb)
                usX2Y_error_urb_status(usX2Y, subs, urb);
                return;
        }
-
-       subs->completed_urb = urb;
-
+       if (likely((urb->start_frame & 0xFFFF) == (usX2Y->wait_iso_frame & 0xFFFF)))
+               subs->completed_urb = urb;
+       else {
+               usX2Y_error_sequence(usX2Y, subs, urb);
+               return;
+       }
        {
                struct snd_usX2Y_substream *capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE],
                        *playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];