From d6d8b1103c0a9ec1c8d328e4ef6515c0efe2f2aa Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 1 Feb 2004 21:43:56 -0800 Subject: [PATCH] [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 --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 0df71f26cf428..8ee641df6b9cd 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1516,7 +1516,9 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r) 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 --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 15cda7f94f24a..1d0ea74d01483 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -163,7 +163,7 @@ struct hc_driver { 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 --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index d15c470784c5b..5c58a16c7693f 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -680,7 +680,7 @@ static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs) /*-------------------------------------------------------------------------*/ -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 @@ static void ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs) 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 @@ dead: ehci_work (ehci, regs); done: spin_unlock (&ehci->lock); + return IRQ_HANDLED; } /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 168c9e9edcc4a..1c3c8e509964e 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -545,7 +545,7 @@ static int hc_start (struct ohci_hcd *ohci) /* 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 @@ static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) } else if ((ints = readl (®s->intrstatus)) == ~(u32)0) { disable (ohci); ohci_dbg (ohci, "device removed!\n"); - return; + return IRQ_HANDLED; /* interrupt for some other device? */ } else if ((ints &= readl (®s->intrenable)) == 0) { - return; + return IRQ_NONE; } if (ints & OHCI_INTR_UE) { @@ -604,6 +604,8 @@ static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) // flush those pci writes (void) readl (&ohci->regs->control); } + + return IRQ_HANDLED; } /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index c567166757c62..f166ad77f2ccf 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -1909,7 +1909,7 @@ static void uhci_remove_pending_qhs(struct uhci_hcd *uhci) 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 @@ static void uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) */ 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 @@ static void uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) spin_unlock(&uhci->urb_list_lock); uhci_finish_completion(hcd, regs); + return IRQ_HANDLED; } static void reset_hc(struct uhci_hcd *uhci) -- 2.53.0