]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
staging: most: usb: clear functional stall on OUT endpoint
authorChristian Gromm <christian.gromm@microchip.com>
Tue, 21 Nov 2017 14:05:15 +0000 (15:05 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 27 Nov 2017 08:20:36 +0000 (09:20 +0100)
For the MOST packet channel there are two dedicated USB endpoints. But
internally the hardware has actually one channel for data forwarding from
and to MOST. To have the hardware clean up its state machine correctly in
case of an error, both USB pipes need to be reset.  This patch triggers the
host to also clear the OUT endpoint's halt condition in case an IN endpoint
has signaled to be stalled.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/most/usb/usb.c

index 87e7fec2af8af16e1cad32b240f2d6d4f2234fa3..1169635454f305876f61d4524a3c27e719c7ec48 100644 (file)
@@ -809,6 +809,21 @@ static void wq_clear_halt(struct work_struct *wq_obj)
        if (usb_clear_halt(mdev->usb_device, pipe))
                dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n");
 
+       /* If the functional Stall condition has been set on an
+        * asynchronous rx channel, we need to clear the tx channel
+        * too, since the hardware runs its clean-up sequence on both
+        * channels, as they are physically one on the network.
+        *
+        * The USB interface that exposes the asynchronous channels
+        * contains always two endpoints, and two only.
+        */
+       if (mdev->conf[channel].data_type == MOST_CH_ASYNC &&
+           mdev->conf[channel].direction == MOST_CH_RX) {
+               int peer = 1 - channel;
+               int snd_pipe = usb_sndbulkpipe(mdev->usb_device,
+                                              mdev->ep_address[peer]);
+               usb_clear_halt(mdev->usb_device, snd_pipe);
+       }
        mdev->is_channel_healthy[channel] = true;
        most_resume_enqueue(&mdev->iface, channel);
        mutex_unlock(&mdev->io_mutex);