ChangeSet 1.1500.8.11, 2004/02/02 13:43:56-08:00, shemminger@osdl.org

[PATCH] USB: fix usb hc and shared irq handling

Here is a revised version of the irqreturn_t propagation patch.
The only difference is now ohci-hcd returns IRQ_HANDLED in the remove case.


 drivers/usb/core/hcd.c      |    4 +++-
 drivers/usb/core/hcd.h      |    2 +-
 drivers/usb/host/ehci-hcd.c |    9 ++++++++-
 drivers/usb/host/ohci-hcd.c |    8 +++++---
 drivers/usb/host/uhci-hcd.c |    5 +++--
 5 files changed, 20 insertions(+), 8 deletions(-)


diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
--- a/drivers/usb/core/hcd.c	Mon Feb  9 14:41:01 2004
+++ b/drivers/usb/core/hcd.c	Mon Feb  9 14:41:01 2004
@@ -1516,7 +1516,9 @@
 		return IRQ_NONE;
 
 	hcd->saw_irq = 1;
-	hcd->driver->irq (hcd, r);
+	if (hcd->driver->irq (hcd, r) == IRQ_NONE)
+		return IRQ_NONE;
+
 	if (hcd->state != start && hcd->state == USB_STATE_HALT)
 		usb_hc_died (hcd);
 	return IRQ_HANDLED;
diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
--- a/drivers/usb/core/hcd.h	Mon Feb  9 14:41:01 2004
+++ b/drivers/usb/core/hcd.h	Mon Feb  9 14:41:01 2004
@@ -163,7 +163,7 @@
 	const char	*description;	/* "ehci-hcd" etc */
 
 	/* irq handler */
-	void	(*irq) (struct usb_hcd *hcd, struct pt_regs *regs);
+	irqreturn_t	(*irq) (struct usb_hcd *hcd, struct pt_regs *regs);
 
 	int	flags;
 #define	HCD_MEMORY	0x0001		/* HC regs use memory (else I/O) */
diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c	Mon Feb  9 14:41:01 2004
+++ b/drivers/usb/host/ehci-hcd.c	Mon Feb  9 14:41:01 2004
@@ -680,7 +680,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
+static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	u32			status;
@@ -690,6 +690,12 @@
 
 	status = readl (&ehci->regs->status);
 
+	/* shared irq */
+	if (status == 0) {
+		spin_unlock (&ehci->lock);
+		return IRQ_NONE;
+	}
+
 	/* e.g. cardbus physical eject */
 	if (status == ~(u32) 0) {
 		ehci_dbg (ehci, "device removed\n");
@@ -743,6 +749,7 @@
 		ehci_work (ehci, regs);
 done:
 	spin_unlock (&ehci->lock);
+	return IRQ_HANDLED;
 }
 
 /*-------------------------------------------------------------------------*/
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- a/drivers/usb/host/ohci-hcd.c	Mon Feb  9 14:41:01 2004
+++ b/drivers/usb/host/ohci-hcd.c	Mon Feb  9 14:41:01 2004
@@ -545,7 +545,7 @@
 
 /* an interrupt happens */
 
-static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
+static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 	struct ohci_regs	*regs = ohci->regs;
@@ -560,11 +560,11 @@
 	} else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
 		disable (ohci);
 		ohci_dbg (ohci, "device removed!\n");
-		return;
+		return IRQ_HANDLED;
 
 	/* interrupt for some other device? */
 	} else if ((ints &= readl (&regs->intrenable)) == 0) {
-		return;
+		return IRQ_NONE;
 	} 
 
 	if (ints & OHCI_INTR_UE) {
@@ -604,6 +604,8 @@
 		// flush those pci writes
 		(void) readl (&ohci->regs->control);
 	}
+
+	return IRQ_HANDLED;
 }
 
 /*-------------------------------------------------------------------------*/
diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c	Mon Feb  9 14:41:01 2004
+++ b/drivers/usb/host/uhci-hcd.c	Mon Feb  9 14:41:01 2004
@@ -1909,7 +1909,7 @@
 	spin_unlock_irqrestore(&uhci->urb_remove_list_lock, flags);
 }
 
-static void uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	unsigned int io_addr = uhci->io_addr;
@@ -1922,7 +1922,7 @@
 	 */
 	status = inw(io_addr + USBSTS);
 	if (!status)	/* shared interrupt, not mine */
-		return;
+		return IRQ_NONE;
 	outw(status, io_addr + USBSTS);		/* Clear it */
 
 	if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
@@ -1963,6 +1963,7 @@
 	spin_unlock(&uhci->urb_list_lock);
 
 	uhci_finish_completion(hcd, regs);
+	return IRQ_HANDLED;
 }
 
 static void reset_hc(struct uhci_hcd *uhci)
