Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney...
[firefly-linux-kernel-4.4.55.git] / sound / usb / endpoint.c
index 34de6f2faf6120b492eb65208b9c9805aafe44e3..21049b882ee6445d47714074fddbcb550cf5eef8 100644 (file)
@@ -485,15 +485,10 @@ __exit_unlock:
 static int wait_clear_urbs(struct snd_usb_endpoint *ep)
 {
        unsigned long end_time = jiffies + msecs_to_jiffies(1000);
-       unsigned int i;
        int alive;
 
        do {
-               alive = 0;
-               for (i = 0; i < ep->nurbs; i++)
-                       if (test_bit(i, &ep->active_mask))
-                               alive++;
-
+               alive = bitmap_weight(&ep->active_mask, ep->nurbs);
                if (!alive)
                        break;
 
@@ -520,33 +515,24 @@ void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep)
 /*
  * unlink active urbs.
  */
-static int deactivate_urbs(struct snd_usb_endpoint *ep, int force, int can_sleep)
+static int deactivate_urbs(struct snd_usb_endpoint *ep, bool force)
 {
        unsigned int i;
-       int async;
 
        if (!force && ep->chip->shutdown) /* to be sure... */
                return -EBADFD;
 
-       async = !can_sleep && ep->chip->async_unlink;
-
        clear_bit(EP_FLAG_RUNNING, &ep->flags);
 
        INIT_LIST_HEAD(&ep->ready_playback_urbs);
        ep->next_packet_read_pos = 0;
        ep->next_packet_write_pos = 0;
 
-       if (!async && in_interrupt())
-               return 0;
-
        for (i = 0; i < ep->nurbs; i++) {
                if (test_bit(i, &ep->active_mask)) {
                        if (!test_and_set_bit(i, &ep->unlink_mask)) {
                                struct urb *u = ep->urb[i].urb;
-                               if (async)
-                                       usb_unlink_urb(u);
-                               else
-                                       usb_kill_urb(u);
+                               usb_unlink_urb(u);
                        }
                }
        }
@@ -566,7 +552,7 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force)
        ep->prepare_data_urb = NULL;
 
        /* stop urbs */
-       deactivate_urbs(ep, force, 1);
+       deactivate_urbs(ep, force);
        wait_clear_urbs(ep);
 
        for (i = 0; i < ep->nurbs; i++)
@@ -829,7 +815,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
  *
  * Returns an error if the URB submission failed, 0 in all other cases.
  */
-int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep)
+int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep)
 {
        int err;
        unsigned int i;
@@ -842,7 +828,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep)
                return 0;
 
        /* just to be sure */
-       deactivate_urbs(ep, 0, can_sleep);
+       deactivate_urbs(ep, false);
        if (can_sleep)
                wait_clear_urbs(ep);
 
@@ -896,7 +882,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep)
 __error:
        clear_bit(EP_FLAG_RUNNING, &ep->flags);
        ep->use_count--;
-       deactivate_urbs(ep, 0, 0);
+       deactivate_urbs(ep, false);
        return -EPIPE;
 }
 
@@ -910,9 +896,11 @@ __error:
  * actually be deactivated.
  *
  * Must be balanced to calls of snd_usb_endpoint_start().
+ *
+ * The caller needs to synchronize the pending stop operation via
+ * snd_usb_endpoint_sync_pending_stop().
  */
-void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
-                          int force, int can_sleep, int wait)
+void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep)
 {
        if (!ep)
                return;
@@ -921,16 +909,12 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
                return;
 
        if (--ep->use_count == 0) {
-               deactivate_urbs(ep, force, can_sleep);
+               deactivate_urbs(ep, false);
                ep->data_subs = NULL;
                ep->sync_slave = NULL;
                ep->retire_data_urb = NULL;
                ep->prepare_data_urb = NULL;
-
-               if (wait)
-                       wait_clear_urbs(ep);
-               else
-                       set_bit(EP_FLAG_STOPPING, &ep->flags);
+               set_bit(EP_FLAG_STOPPING, &ep->flags);
        }
 }
 
@@ -952,7 +936,7 @@ int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep)
        if (!ep)
                return -EINVAL;
 
-       deactivate_urbs(ep, 1, 1);
+       deactivate_urbs(ep, true);
        wait_clear_urbs(ep);
 
        if (ep->use_count != 0)
@@ -1034,15 +1018,18 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
                /*
                 * Iterate through the inbound packet and prepare the lengths
                 * for the output packet. The OUT packet we are about to send
-                * will have the same amount of payload bytes than the IN
-                * packet we just received.
+                * will have the same amount of payload bytes per stride as the
+                * IN packet we just received. Since the actual size is scaled
+                * by the stride, use the sender stride to calculate the length
+                * in case the number of channels differ between the implicitly
+                * fed-back endpoint and the synchronizing endpoint.
                 */
 
                out_packet->packets = in_ctx->packets;
                for (i = 0; i < in_ctx->packets; i++) {
                        if (urb->iso_frame_desc[i].status == 0)
                                out_packet->packet_size[i] =
-                                       urb->iso_frame_desc[i].actual_length / ep->stride;
+                                       urb->iso_frame_desc[i].actual_length / sender->stride;
                        else
                                out_packet->packet_size[i] = 0;
                }