This patch (as1500) removes all uses of the objectionable hcd->state variable from the ohci-hcd family of drivers. It is replaced by a private ohci->rh_state field, just as in uhci-hcd and ehci-hcd. Signed-off-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> --- drivers/usb/host/ohci-au1xxx.c | 5 +---- drivers/usb/host/ohci-dbg.c | 18 ++++++++++++++++-- drivers/usb/host/ohci-ep93xx.c | 2 -- drivers/usb/host/ohci-hcd.c | 26 +++++++++++++------------- drivers/usb/host/ohci-hub.c | 7 +++---- drivers/usb/host/ohci-omap.c | 1 - drivers/usb/host/ohci-pci.c | 5 +---- drivers/usb/host/ohci-pxa27x.c | 2 -- drivers/usb/host/ohci-q.c | 8 +++----- drivers/usb/host/ohci-sh.c | 1 - drivers/usb/host/ohci-sm501.c | 1 - drivers/usb/host/ohci-spear.c | 1 - drivers/usb/host/ohci-tmio.c | 3 --- drivers/usb/host/ohci.h | 14 ++++++++------ 14 files changed, 45 insertions(+), 49 deletions(-) Index: usb-3.2/drivers/usb/host/ohci.h =================================================================== --- usb-3.2.orig/drivers/usb/host/ohci.h +++ usb-3.2/drivers/usb/host/ohci.h @@ -344,6 +344,12 @@ typedef struct urb_priv { * a subset of what the full implementation needs. (Linus) */ +enum ohci_rh_state { + OHCI_RH_HALTED, + OHCI_RH_SUSPENDED, + OHCI_RH_RUNNING +}; + struct ohci_hcd { spinlock_t lock; @@ -384,6 +390,7 @@ struct ohci_hcd { /* * driver state */ + enum ohci_rh_state rh_state; int num_ports; int load [NUM_INTS]; u32 hc_control; /* copy of hc control reg */ @@ -679,11 +686,6 @@ static inline u16 ohci_hwPSW(const struc /*-------------------------------------------------------------------------*/ -static inline void disable (struct ohci_hcd *ohci) -{ - ohci_to_hcd(ohci)->state = HC_STATE_HALT; -} - #define FI 0x2edf /* 12000 bits per frame (-1) */ #define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7)) #define FIT (1 << 31) @@ -707,7 +709,7 @@ static inline void periodic_reinit (stru #define read_roothub(hc, register, mask) ({ \ u32 temp = ohci_readl (hc, &hc->regs->roothub.register); \ if (temp == -1) \ - disable (hc); \ + hc->rh_state = OHCI_RH_HALTED; \ else if (hc->flags & OHCI_QUIRK_AMD756) \ while (temp & mask) \ temp = ohci_readl (hc, &hc->regs->roothub.register); \ Index: usb-3.2/drivers/usb/host/ohci-hcd.c =================================================================== --- usb-3.2.orig/drivers/usb/host/ohci-hcd.c +++ usb-3.2/drivers/usb/host/ohci-hcd.c @@ -209,7 +209,7 @@ static int ohci_urb_enqueue ( retval = -ENODEV; goto fail; } - if (!HC_IS_RUNNING(hcd->state)) { + if (ohci->rh_state != OHCI_RH_RUNNING) { retval = -ENODEV; goto fail; } @@ -274,7 +274,7 @@ static int ohci_urb_dequeue(struct usb_h rc = usb_hcd_check_unlink_urb(hcd, urb, status); if (rc) { ; /* Do nothing */ - } else if (HC_IS_RUNNING(hcd->state)) { + } else if (ohci->rh_state == OHCI_RH_RUNNING) { urb_priv_t *urb_priv; /* Unless an IRQ completed the unlink while it was being @@ -321,7 +321,7 @@ ohci_endpoint_disable (struct usb_hcd *h rescan: spin_lock_irqsave (&ohci->lock, flags); - if (!HC_IS_RUNNING (hcd->state)) { + if (ohci->rh_state != OHCI_RH_RUNNING) { sanitize: ed->state = ED_IDLE; if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT) @@ -377,6 +377,7 @@ static void ohci_usb_reset (struct ohci_ ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); ohci->hc_control &= OHCI_CTRL_RWC; ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); + ohci->rh_state = OHCI_RH_HALTED; } /* ohci_shutdown forcibly disables IRQs and DMA, helping kexec and @@ -500,7 +501,7 @@ static int ohci_init (struct ohci_hcd *o if (distrust_firmware) ohci->flags |= OHCI_QUIRK_HUB_POWER; - disable (ohci); + ohci->rh_state = OHCI_RH_HALTED; ohci->regs = hcd->regs; /* REVISIT this BIOS handshake is now moved into PCI "quirks", and @@ -575,7 +576,7 @@ static int ohci_run (struct ohci_hcd *oh int first = ohci->fminterval == 0; struct usb_hcd *hcd = ohci_to_hcd(ohci); - disable (ohci); + ohci->rh_state = OHCI_RH_HALTED; /* boot firmware should have set this up (5.1.1.3.1) */ if (first) { @@ -688,7 +689,7 @@ retry: ohci->hc_control &= OHCI_CTRL_RWC; ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER; ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); - hcd->state = HC_STATE_RUNNING; + ohci->rh_state = OHCI_RH_RUNNING; /* wake on ConnectStatusChange, matching external hubs */ ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status); @@ -725,7 +726,6 @@ retry: // POTPGT delay is bits 24-31, in 2 ms units. mdelay ((val >> 23) & 0x1fe); - hcd->state = HC_STATE_RUNNING; if (quirk_zfmicro(ohci)) { /* Create timer to watch for bad queue state on ZF Micro */ @@ -761,7 +761,7 @@ static irqreturn_t ohci_irq (struct usb_ * of dead, unclocked, or unplugged (CardBus...) devices */ if (ints == ~(u32)0) { - disable (ohci); + ohci->rh_state = OHCI_RH_HALTED; ohci_dbg (ohci, "device removed!\n"); usb_hc_died(hcd); return IRQ_HANDLED; @@ -771,7 +771,7 @@ static irqreturn_t ohci_irq (struct usb_ ints &= ohci_readl(ohci, ®s->intrenable); /* interrupt for some other device? */ - if (ints == 0 || unlikely(hcd->state == HC_STATE_HALT)) + if (ints == 0 || unlikely(ohci->rh_state == OHCI_RH_HALTED)) return IRQ_NOTMINE; if (ints & OHCI_INTR_UE) { @@ -786,8 +786,8 @@ static irqreturn_t ohci_irq (struct usb_ schedule_work (&ohci->nec_work); } else { - disable (ohci); ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n"); + ohci->rh_state = OHCI_RH_HALTED; usb_hc_died(hcd); } @@ -871,11 +871,11 @@ static irqreturn_t ohci_irq (struct usb_ if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list && !ohci->ed_to_check - && HC_IS_RUNNING(hcd->state)) + && ohci->rh_state == OHCI_RH_RUNNING) ohci_writel (ohci, OHCI_INTR_SF, ®s->intrdisable); spin_unlock (&ohci->lock); - if (HC_IS_RUNNING(hcd->state)) { + if (ohci->rh_state == OHCI_RH_RUNNING) { ohci_writel (ohci, ints, ®s->intrstatus); ohci_writel (ohci, OHCI_INTR_MIE, ®s->intrenable); // flush those writes @@ -929,7 +929,7 @@ static int ohci_restart (struct ohci_hcd struct urb_priv *priv; spin_lock_irq(&ohci->lock); - disable (ohci); + ohci->rh_state = OHCI_RH_HALTED; /* Recycle any "live" eds/tds (and urbs). */ if (!list_empty (&ohci->pending)) Index: usb-3.2/drivers/usb/host/ohci-hub.c =================================================================== --- usb-3.2.orig/drivers/usb/host/ohci-hub.c +++ usb-3.2/drivers/usb/host/ohci-hub.c @@ -111,6 +111,7 @@ __acquires(ohci->lock) if (!autostop) { ohci->next_statechange = jiffies + msecs_to_jiffies (5); ohci->autostop = 0; + ohci->rh_state = OHCI_RH_SUSPENDED; } done: @@ -140,7 +141,7 @@ __acquires(ohci->lock) if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { /* this can happen after resuming a swsusp snapshot */ - if (hcd->state == HC_STATE_RESUMING) { + if (ohci->rh_state != OHCI_RH_RUNNING) { ohci_dbg (ohci, "BIOS/SMM active, control %03x\n", ohci->hc_control); status = -EBUSY; @@ -274,6 +275,7 @@ skip_resume: (void) ohci_readl (ohci, &ohci->regs->control); } + ohci->rh_state = OHCI_RH_RUNNING; return 0; } @@ -336,11 +338,8 @@ static void ohci_finish_controller_resum /* If needed, reinitialize and suspend the root hub */ if (need_reinit) { spin_lock_irq(&ohci->lock); - hcd->state = HC_STATE_RESUMING; ohci_rh_resume(ohci); - hcd->state = HC_STATE_QUIESCING; ohci_rh_suspend(ohci, 0); - hcd->state = HC_STATE_SUSPENDED; spin_unlock_irq(&ohci->lock); } Index: usb-3.2/drivers/usb/host/ohci-q.c =================================================================== --- usb-3.2.orig/drivers/usb/host/ohci-q.c +++ usb-3.2/drivers/usb/host/ohci-q.c @@ -912,7 +912,7 @@ rescan_all: /* only take off EDs that the HC isn't using, accounting for * frame counter wraps and EDs with partially retired TDs */ - if (likely (HC_IS_RUNNING(ohci_to_hcd(ohci)->state))) { + if (likely(ohci->rh_state == OHCI_RH_RUNNING)) { if (tick_before (tick, ed->tick)) { skip_ed: last = &ed->ed_next; @@ -1012,7 +1012,7 @@ rescan_this: /* but if there's work queued, reschedule */ if (!list_empty (&ed->td_list)) { - if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state)) + if (ohci->rh_state == OHCI_RH_RUNNING) ed_schedule (ohci, ed); } @@ -1021,9 +1021,7 @@ rescan_this: } /* maybe reenable control and bulk lists */ - if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state) - && ohci_to_hcd(ohci)->state != HC_STATE_QUIESCING - && !ohci->ed_rm_list) { + if (ohci->rh_state == OHCI_RH_RUNNING && !ohci->ed_rm_list) { u32 command = 0, control = 0; if (ohci->ed_controltail) { Index: usb-3.2/drivers/usb/host/ohci-dbg.c =================================================================== --- usb-3.2.orig/drivers/usb/host/ohci-dbg.c +++ usb-3.2/drivers/usb/host/ohci-dbg.c @@ -127,6 +127,19 @@ static char *hcfs2string (int state) return "?"; } +static const char *rh_state_string(struct ohci_hcd *ohci) +{ + switch (ohci->rh_state) { + case OHCI_RH_HALTED: + return "halted"; + case OHCI_RH_SUSPENDED: + return "suspended"; + case OHCI_RH_RUNNING: + return "running"; + } + return "?"; +} + // dump control and status registers static void ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size) @@ -136,9 +149,10 @@ ohci_dump_status (struct ohci_hcd *contr temp = ohci_readl (controller, ®s->revision) & 0xff; ohci_dbg_sw (controller, next, size, - "OHCI %d.%d, %s legacy support registers\n", + "OHCI %d.%d, %s legacy support registers, rh state %s\n", 0x03 & (temp >> 4), (temp & 0x0f), - (temp & 0x0100) ? "with" : "NO"); + (temp & 0x0100) ? "with" : "NO", + rh_state_string(controller)); temp = ohci_readl (controller, ®s->control); ohci_dbg_sw (controller, next, size, Index: usb-3.2/drivers/usb/host/ohci-au1xxx.c =================================================================== --- usb-3.2.orig/drivers/usb/host/ohci-au1xxx.c +++ usb-3.2/drivers/usb/host/ohci-au1xxx.c @@ -173,12 +173,9 @@ static int ohci_hcd_au1xxx_drv_suspend(s * mark HW unaccessible, bail out if RH has been resumed. Use * the spinlock to properly synchronize with possible pending * RH suspend or resume activity. - * - * This is still racy as hcd->state is manipulated outside of - * any locks =P But that will be a different fix. */ spin_lock_irqsave(&ohci->lock, flags); - if (hcd->state != HC_STATE_SUSPENDED) { + if (ohci->rh_state != OHCI_RH_SUSPENDED) { rc = -EINVAL; goto bail; } Index: usb-3.2/drivers/usb/host/ohci-ep93xx.c =================================================================== --- usb-3.2.orig/drivers/usb/host/ohci-ep93xx.c +++ usb-3.2/drivers/usb/host/ohci-ep93xx.c @@ -179,8 +179,6 @@ static int ohci_hcd_ep93xx_drv_suspend(s ohci->next_statechange = jiffies; ep93xx_stop_hc(&pdev->dev); - hcd->state = HC_STATE_SUSPENDED; - return 0; } Index: usb-3.2/drivers/usb/host/ohci-omap.c =================================================================== --- usb-3.2.orig/drivers/usb/host/ohci-omap.c +++ usb-3.2/drivers/usb/host/ohci-omap.c @@ -516,7 +516,6 @@ static int ohci_omap_suspend(struct plat ohci->next_statechange = jiffies; omap_ohci_clock_power(0); - ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED; return 0; } Index: usb-3.2/drivers/usb/host/ohci-pci.c =================================================================== --- usb-3.2.orig/drivers/usb/host/ohci-pci.c +++ usb-3.2/drivers/usb/host/ohci-pci.c @@ -308,12 +308,9 @@ static int ohci_pci_suspend(struct usb_h * mark HW unaccessible, bail out if RH has been resumed. Use * the spinlock to properly synchronize with possible pending * RH suspend or resume activity. - * - * This is still racy as hcd->state is manipulated outside of - * any locks =P But that will be a different fix. */ spin_lock_irqsave (&ohci->lock, flags); - if (hcd->state != HC_STATE_SUSPENDED) { + if (ohci->rh_state != OHCI_RH_SUSPENDED) { rc = -EINVAL; goto bail; } Index: usb-3.2/drivers/usb/host/ohci-pxa27x.c =================================================================== --- usb-3.2.orig/drivers/usb/host/ohci-pxa27x.c +++ usb-3.2/drivers/usb/host/ohci-pxa27x.c @@ -502,8 +502,6 @@ static int ohci_hcd_pxa27x_drv_suspend(s ohci->ohci.next_statechange = jiffies; pxa27x_stop_hc(ohci, dev); - hcd->state = HC_STATE_SUSPENDED; - return 0; } Index: usb-3.2/drivers/usb/host/ohci-sh.c =================================================================== --- usb-3.2.orig/drivers/usb/host/ohci-sh.c +++ usb-3.2/drivers/usb/host/ohci-sh.c @@ -29,7 +29,6 @@ static int ohci_sh_start(struct usb_hcd ohci_hcd_init(ohci); ohci_init(ohci); ohci_run(ohci); - hcd->state = HC_STATE_RUNNING; return 0; } Index: usb-3.2/drivers/usb/host/ohci-sm501.c =================================================================== --- usb-3.2.orig/drivers/usb/host/ohci-sm501.c +++ usb-3.2/drivers/usb/host/ohci-sm501.c @@ -224,7 +224,6 @@ static int ohci_sm501_suspend(struct pla ohci->next_statechange = jiffies; sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 0); - ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED; return 0; } Index: usb-3.2/drivers/usb/host/ohci-spear.c =================================================================== --- usb-3.2.orig/drivers/usb/host/ohci-spear.c +++ usb-3.2/drivers/usb/host/ohci-spear.c @@ -203,7 +203,6 @@ static int spear_ohci_hcd_drv_suspend(st ohci->next_statechange = jiffies; spear_stop_ohci(ohci_p); - ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED; return 0; } Index: usb-3.2/drivers/usb/host/ohci-tmio.c =================================================================== --- usb-3.2.orig/drivers/usb/host/ohci-tmio.c +++ usb-3.2/drivers/usb/host/ohci-tmio.c @@ -318,9 +318,6 @@ static int ohci_hcd_tmio_drv_suspend(str if (ret) return ret; } - - hcd->state = HC_STATE_SUSPENDED; - return 0; } -- 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