From 052ac01aeb84d8427ba8ac3d70991ac01b009b59 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 27 Oct 2006 10:33:11 -0400 Subject: USB: OHCI: disable RHSC inside interrupt handler This patch (as808b) moves the Root Hub Status Change interrupt-disable code in ohci-hcd back into the interrupt handler proper, to avoid the chance of adverse interactions with mediocre hardware implementations. It also deletes the root-hub status timer from within the interrupt-enable routine. There's no need to poll for status any more once interrupts are re-enabled. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hub.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'drivers/usb/host/ohci-hub.c') diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 99357b99d133..1e5ed3bb1a93 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -41,7 +41,11 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); - ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); + spin_lock_irq(&ohci->lock); + if (!ohci->autostop) + del_timer(&hcd->rh_timer); /* Prevent next poll */ + ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); + spin_unlock_irq(&ohci->lock); } #define OHCI_SCHED_ENABLES \ @@ -348,7 +352,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); int i, changed = 0, length = 1; - int any_connected = 0, rhsc_enabled = 1; + int any_connected = 0; unsigned long flags; spin_lock_irqsave (&ohci->lock, flags); @@ -389,19 +393,6 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) } } - /* NOTE: vendors didn't always make the same implementation - * choices for RHSC. Sometimes it triggers on an edge (like - * setting and maybe clearing a port status change bit); and - * it's level-triggered on other silicon, active until khubd - * clears all active port status change bits. If it's still - * set (level-triggered) we must disable it and rely on - * polling until khubd re-enables it. - */ - if (ohci_readl (ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC) { - ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable); - (void) ohci_readl (ohci, &ohci->regs->intrdisable); - rhsc_enabled = 0; - } hcd->poll_rh = 1; /* carry out appropriate state changes */ @@ -412,7 +403,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) * and RHSC is enabled */ if (!ohci->autostop) { if (any_connected) { - if (rhsc_enabled) + if (ohci_readl(ohci, &ohci->regs->intrenable) & + OHCI_INTR_RHSC) hcd->poll_rh = 0; } else { ohci->autostop = 1; -- cgit v1.2.1