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.ba...@linux.intel.com>
---
 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to