This patch adds a new field to the ehci-hcd private structure, for holding the value of the EHCI Interrupt Enable register, together with an inline routine for setting this value. The ehci->intr-enable field will used in a following patch, when a tasklet's bottom-half handler needs to restore the correct interrupt mask. Not-yet-signed-off-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> --- drivers/usb/host/ehci-hcd.c | 21 ++++++++++++++------- drivers/usb/host/ehci-hub.c | 6 +++--- drivers/usb/host/ehci-timer.c | 2 +- drivers/usb/host/ehci.h | 1 + 4 files changed, 19 insertions(+), 11 deletions(-) Index: usb-3.11/drivers/usb/host/ehci-hcd.c =================================================================== --- usb-3.11.orig/drivers/usb/host/ehci-hcd.c +++ usb-3.11/drivers/usb/host/ehci-hcd.c @@ -134,6 +134,12 @@ static inline unsigned ehci_read_frame_i return ehci_readl(ehci, &ehci->regs->frame_index); } +static inline void ehci_set_intr_enable(struct ehci_hcd *ehci, u32 mask) +{ + ehci->intr_mask = mask; + ehci_writel(ehci, mask, &ehci->regs->intr_enable); +} + #include "ehci-dbg.c" /*-------------------------------------------------------------------------*/ @@ -194,7 +200,7 @@ static int ehci_halt (struct ehci_hcd *e spin_lock_irq(&ehci->lock); /* disable any irqs left enabled by previous code */ - ehci_writel(ehci, 0, &ehci->regs->intr_enable); + ehci_set_intr_enable(ehci, 0); if (ehci_is_TDI(ehci) && !tdi_in_host_mode(ehci)) { spin_unlock_irq(&ehci->lock); @@ -639,8 +645,9 @@ static int ehci_run (struct usb_hcd *hcd temp >> 8, temp & 0xff, ignore_oc ? ", overcurrent ignored" : ""); - ehci_writel(ehci, INTR_MASK, - &ehci->regs->intr_enable); /* Turn On Interrupts */ + spin_lock_irq(&ehci->lock); + ehci_set_intr_enable(ehci, INTR_MASK); /* Turn on interrupts */ + spin_unlock_irq(&ehci->lock); /* GRR this is run-once init(), being done every time the HC starts. * So long as they're part of class devices, we can't do it init() @@ -817,7 +824,7 @@ dead: ehci->rh_state = EHCI_RH_STOPPING; ehci->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE); ehci_writel(ehci, ehci->command, &ehci->regs->command); - ehci_writel(ehci, 0, &ehci->regs->intr_enable); + ehci_set_intr_enable(ehci, 0); ehci_handle_controller_death(ehci); /* Handle completions when the controller stops */ @@ -1080,7 +1087,7 @@ int ehci_suspend(struct usb_hcd *hcd, bo ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup); spin_lock_irq(&ehci->lock); - ehci_writel(ehci, 0, &ehci->regs->intr_enable); + ehci_set_intr_enable(ehci, 0); (void) ehci_readl(ehci, &ehci->regs->intr_enable); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); @@ -1111,7 +1118,7 @@ int ehci_resume(struct usb_hcd *hcd, boo */ if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF && !hibernated) { - int mask = INTR_MASK; + u32 mask = INTR_MASK; ehci_prepare_ports_for_controller_resume(ehci); @@ -1121,7 +1128,7 @@ int ehci_resume(struct usb_hcd *hcd, boo if (!hcd->self.root_hub->do_remote_wakeup) mask &= ~STS_PCD; - ehci_writel(ehci, mask, &ehci->regs->intr_enable); + ehci_set_intr_enable(ehci, mask); ehci_readl(ehci, &ehci->regs->intr_enable); skip: spin_unlock_irq(&ehci->lock); Index: usb-3.11/drivers/usb/host/ehci-hub.c =================================================================== --- usb-3.11.orig/drivers/usb/host/ehci-hub.c +++ usb-3.11/drivers/usb/host/ehci-hub.c @@ -352,7 +352,7 @@ static int ehci_bus_suspend (struct usb_ mask = INTR_MASK; if (!hcd->self.root_hub->do_remote_wakeup) mask &= ~STS_PCD; - ehci_writel(ehci, mask, &ehci->regs->intr_enable); + ehci_set_intr_enable(ehci, mask); ehci_readl(ehci, &ehci->regs->intr_enable); done: @@ -401,7 +401,7 @@ static int ehci_bus_resume (struct usb_h /* at least some APM implementations will try to deliver * IRQs right away, so delay them until we're ready. */ - ehci_writel(ehci, 0, &ehci->regs->intr_enable); + ehci_set_intr_enable(ehci, 0); /* re-init operational registers */ ehci_writel(ehci, 0, &ehci->regs->segment); @@ -495,7 +495,7 @@ static int ehci_bus_resume (struct usb_h spin_lock_irq(&ehci->lock); if (ehci->shutdown) goto shutdown; - ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); + ehci_set_intr_enable(ehci, INTR_MASK); (void) ehci_readl(ehci, &ehci->regs->intr_enable); spin_unlock_irq(&ehci->lock); Index: usb-3.11/drivers/usb/host/ehci.h =================================================================== --- usb-3.11.orig/drivers/usb/host/ehci.h +++ usb-3.11/drivers/usb/host/ehci.h @@ -186,6 +186,7 @@ struct ehci_hcd { /* one per controlle unsigned long next_statechange; ktime_t last_periodic_enable; u32 command; + u32 intr_mask; /* SILICON QUIRKS */ unsigned no_selective_suspend:1; Index: usb-3.11/drivers/usb/host/ehci-timer.c =================================================================== --- usb-3.11.orig/drivers/usb/host/ehci-timer.c +++ usb-3.11/drivers/usb/host/ehci-timer.c @@ -208,7 +208,7 @@ static void ehci_handle_controller_death /* Clean up the mess */ ehci->rh_state = EHCI_RH_HALTED; ehci_writel(ehci, 0, &ehci->regs->configured_flag); - ehci_writel(ehci, 0, &ehci->regs->intr_enable); + ehci_set_intr_enable(ehci, 0); ehci_work(ehci); end_unlink_async(ehci); -- 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