[PATCH 2/7] usb: core: hcd: let HCDs pass a threaded irq handler

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

 



in case an HCD wants to use threaded irqs to spend
less time in hardirq context, we need
this. Eventually we will remove IRQF_ONESHOT but
only after all HCDs are fixed.

Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxxxxxxxx>
---
 drivers/usb/core/hcd.c  | 43 ++++++++++++++++++++++++++++++++++++++++---
 include/linux/usb/hcd.h |  2 ++
 2 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 76a6cd0d3af9..66dc5a8dfca8 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2420,7 +2420,8 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);
  * If the controller isn't HALTed, calls the driver's irq handler.
  * Checks whether the controller is now dead.
  *
- * Return: %IRQ_HANDLED if the IRQ was handled. %IRQ_NONE otherwise.
+ * Return: %IRQ_HANDLED if the IRQ was handled or %IRQ_WAKE_THREAD if we need to
+ * wake our threaded handler. %IRQ_NONE otherwise.
  */
 irqreturn_t usb_hcd_irq (int irq, void *__hcd)
 {
@@ -2433,6 +2434,29 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
 }
 EXPORT_SYMBOL_GPL(usb_hcd_irq);
 
+/**
+ * usb_hcd_threaded_irq - hook threaded IRQs to HCD framework (bus glue)
+ * @irq the IRQ for which a thread is being woken
+ * @__hcd: pointer to the HCD whose IRQ is being signaled
+ * If the controller isn't HALTed, calls the driver's irq handler.
+ * Checks whether the controller is now dead.
+ *
+ * Return: %IRQ_HANDLED if the IRQ was handled. %IRQ_NONE otherwise.
+ */
+irqreturn_t usb_hcd_threaded_irq (int irq, void *__hcd)
+{
+	struct usb_hcd		*hcd = __hcd;
+
+	if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd)))
+		return IRQ_NONE;
+
+	if (hcd->driver->threaded_irq)
+		return hcd->driver->threaded_irq(hcd);
+
+	return IRQ_NONE;
+}
+EXPORT_SYMBOL_GPL(usb_hcd_threaded_irq);
+
 /*-------------------------------------------------------------------------*/
 
 /**
@@ -2646,8 +2670,21 @@ static int usb_hcd_request_irqs(struct usb_hcd *hcd,
 
 		snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
 				hcd->driver->description, hcd->self.busnum);
-		retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
-				hcd->irq_descr, hcd);
+
+		/*
+		 * NOTICE: we're assuming here that if an HCD implements
+		 * threaded_irq, it's because it wants to use it. For now, we're
+		 * leaving IRQF_ONESHOT in place, but soon enough we plan on
+		 * removing that after all HCDs are fixed.
+		 */
+		if (hcd->driver->threaded_irq)
+			retval = request_threaded_irq(irqnum, usb_hcd_irq,
+					usb_hcd_threaded_irq,
+					irqflags | IRQF_ONESHOT, hcd->irq_descr,
+					hcd);
+		else
+			retval = request_irq(irqnum, usb_hcd_irq, irqflags,
+					hcd->irq_descr, hcd);
 		if (retval != 0) {
 			dev_err(hcd->self.controller,
 					"request interrupt %d failed\n",
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index b98f831dcda3..75287dd91a52 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -242,6 +242,7 @@ struct hc_driver {
 
 	/* irq handler */
 	irqreturn_t	(*irq) (struct usb_hcd *hcd);
+	irqreturn_t	(*threaded_irq) (struct usb_hcd *hcd);
 
 	int	flags;
 #define	HCD_MEMORY	0x0001		/* HC regs use memory (else I/O) */
@@ -479,6 +480,7 @@ void hcd_buffer_free(struct usb_bus *bus, size_t size,
 
 /* generic bus glue, needed for host controllers that don't use PCI */
 extern irqreturn_t usb_hcd_irq(int irq, void *__hcd);
+extern irqreturn_t usb_hcd_threaded_irq(int irq, void *__hcd);
 
 extern void usb_hc_died(struct usb_hcd *hcd);
 extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);
-- 
2.8.0.rc2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



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

  Powered by Linux