[PATCH] usb: xhci: Support running urb giveback in tasklet context

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Patch "USB: HCD: support giveback of URB in tasklet context"
introduced giveback of urb in tasklet context. [1] This patch was
applied to ehci but not xhci. [2] It significantly reduces the hard
irq time of xhci. Especially for the uvc driver, the hard irq including
the uvc complete function runs quite long (about 300-350us in my
Thinkpad s440 laptop with webcam) but applying this patch reduces
the hard irq time of xhci to about 18-30us.

As mentioned in the patch [1], when the urb complete function is
executed in the tasklet, urb resubmission may be delayed and a time
sensitive interrupt/isochronous pipe may be affected. However, as
mentioned in [1], an interrupt pipe is mainly used for event report.
So some delays are fine.

In the case of isochronous pipe, executing the urb complete function
in tasklet can cause late urb resubmissions due to tasklet schduling
delay. Then the td can not match the endpoint service time interval
resulting in an empty isochronous transfer ring and ring overrun/
underrun event. But this is not a problem.

xhci spec 4.10.3.1 describes the xhc behavior when an empty isochronous
transfer ring situation occurs due to the software's late resubmission
of urb. And ehci also operates as the xhci specification. [3]

If the driver can not match the endpoint service time interval, the
isochronous transfer ring is empty and an overrun/underrun event
occurs. Then the isochronous td that missed the frame is dropped and
xhc shcedule the next td in appropriate frame. Or the xhc immediately
schedules the missing td to the next frame as soon as possible if the
driver sets the URB_ISO_ASAP flag in the urb->transfer_flags.
Therefore, there is no scheduling issue for the late submitted
isochronous td.

And drivers using isochronous pipe usually submit multiple urbs. For
example, uvc driver uses up to 5 urbs. Therefore, the time interval
at which the isochronous transfer ring is empty is quite long.[4]
Therefore, executing the urb complete function in the tasklet does
not affect the isochronous transfer ring overrun/underrun.

[1], https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=94dfd7edfd5c9b605caf7b562de7a813d216e011
[2], https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=428aac8a81058e2303677a8fbf26670229e51d3a
[3], https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=46c73d1d3ebc38feed1d97c6980252a0a01f6a5b
[4], https://marc.info/?l=linux-usb&m=137268420600615&w=2

Signed-off-by: Suwan Kim <suwan.kim027@xxxxxxxxx>
---
 drivers/usb/host/xhci-ring.c | 2 --
 drivers/usb/host/xhci.c      | 2 +-
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 40fa25c4d041..0ede5265e6e2 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -644,10 +644,8 @@ static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci,
 	}
 	xhci_urb_free_priv(urb_priv);
 	usb_hcd_unlink_urb_from_ep(hcd, urb);
-	spin_unlock(&xhci->lock);
 	trace_xhci_urb_giveback(urb);
 	usb_hcd_giveback_urb(hcd, urb, status);
-	spin_lock(&xhci->lock);
 }
 
 static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 005e65922608..b4610f70d660 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -5142,7 +5142,7 @@ static const struct hc_driver xhci_hc_driver = {
 	 * generic hardware linkage
 	 */
 	.irq =			xhci_irq,
-	.flags =		HCD_MEMORY | HCD_USB3 | HCD_SHARED,
+	.flags =		HCD_MEMORY | HCD_USB3 | HCD_SHARED | HCD_BH,
 
 	/*
 	 * basic lifecycle operations
-- 
2.20.1




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux