int usb_hcd_amba_remove (void *vid) { struct amba_device *dev = (struct amba_id *)vid; struct usb_hcd *hcd = (struct usb_hcd*)(&dev->dev); if (!hcd) { printk(KERN_ERR"usb_hcd_amba_remove: dev has no drvdata!\n"); return -ENODEV; } if (in_interrupt ()) BUG (); if (HCD_IS_RUNNING (hcd->state)) hcd->state = USB_STATE_QUIESCING; if (hcd->driver->stop) hcd->driver->stop(hcd); hcd->state = USB_STATE_HALT; free_irq(dev->irq[0], hcd); if (hcd->driver->flags & HCD_MEMORY) { iounmap (hcd->regs); } usb_set_vbus_off(); vbus_cleanup(); return 0; }
/** * usb_hcd_ppc_soc_remove - shutdown processing for On-Chip HCDs * @pdev: USB Host Controller being removed * Context: !in_interrupt() * * Reverses the effect of usb_hcd_ppc_soc_probe(). * It is always called from a thread * context, normally "rmmod", "apmd", or something similar. * */ static void usb_hcd_ppc_soc_remove(struct platform_device *pdev) { struct usb_hcd *hcd; struct resource *res; hcd = dev_get_drvdata(&pdev->dev); if (!hcd) return; if (in_interrupt()) BUG(); if (HCD_IS_RUNNING(hcd->state)) hcd->state = USB_STATE_QUIESCING; usb_disconnect(&hcd->self.root_hub); hcd->driver->stop(hcd); del_timer_sync(&hcd->rh_timer); hcd_buffer_destroy(hcd); hcd->state = USB_STATE_HALT; dev_set_drvdata(&pdev->dev, NULL); free_irq(hcd->irq, hcd); iounmap(hcd->regs); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res) { release_mem_region(res->start, res->end - res->start + 1); } usb_deregister_bus (&hcd->self); pr_debug("Removed PPC-SOC EHCI USB Controller\n"); }
static int __init_or_module arc_ehci_remove(struct device *dev) { struct ehci_hcd *ehci = dev_get_drvdata(dev); struct usb_hcd *hcd = ehci_to_hcd(ehci); struct arc_usb_config *config; config = (struct arc_usb_config *)dev->platform_data; dbg("%s dev=0x%p\n", __FUNCTION__, dev); if (HCD_IS_RUNNING(hcd->state)) hcd->state = USB_STATE_QUIESCING; usb_disconnect(&hcd->self.root_hub); hcd->driver->stop(hcd); hcd_buffer_destroy(hcd); usb_deregister_bus(&hcd->self); free_irq(hcd->irq, hcd); usb_put_hcd(hcd); /* * do platform specific un-initialization: * release iomux pins, etc. */ config->platform_uninit(); return 0; }
/** * usb_hcd_pci_remove - shutdown processing for PCI-based HCDs * @dev: USB Host Controller being removed * Context: !in_interrupt() * * Reverses the effect of usb_hcd_pci_probe(), first invoking * the HCD's stop() method. It is always called from a thread * context, normally "rmmod", "apmd", or something similar. * * Store this function in the HCD's struct pci_driver as remove(). */ void usb_hcd_pci_remove (struct pci_dev *dev) { struct usb_hcd *hcd; hcd = pci_get_drvdata(dev); if (!hcd) return; dev_info (hcd->self.controller, "remove, state %x\n", hcd->state); if (in_interrupt ()) BUG (); if (HCD_IS_RUNNING (hcd->state)) hcd->state = USB_STATE_QUIESCING; dev_dbg (hcd->self.controller, "roothub graceful disconnect\n"); usb_disconnect (&hcd->self.root_hub); hcd->driver->stop (hcd); hcd_buffer_destroy (hcd); hcd->state = USB_STATE_HALT; pci_set_drvdata(dev, NULL); free_irq (hcd->irq, hcd); if (hcd->driver->flags & HCD_MEMORY) { iounmap (hcd->regs); release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0)); } else { release_region (pci_resource_start (dev, hcd->region), pci_resource_len (dev, hcd->region)); } usb_deregister_bus (&hcd->self); }
/** * usb_hcd_pci_resume - power management resume of a PCI-based HCD * @dev: USB Host Controller being resumed * * Store this function in the HCD's struct pci_driver as resume(). */ int usb_hcd_pci_resume (struct pci_dev *dev) { struct usb_hcd *hcd; int retval; int has_pci_pm; hcd = pci_get_drvdata(dev); if (hcd->state != HCD_STATE_SUSPENDED) { dev_dbg (hcd->self.controller, "can't resume, not suspended!\n"); return 0; } has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM); /* D3cold resume isn't usually reported this way... */ dev_dbg(hcd->self.controller, "resume from PCI %s%s\n", pci_state(dev->current_state), has_pci_pm ? "" : " (legacy)"); hcd->state = USB_STATE_RESUMING; if (has_pci_pm) pci_set_power_state (dev, 0); dev->dev.power.power_state = 0; retval = request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ, hcd->description, hcd); if (retval < 0) { dev_err (hcd->self.controller, "can't restore IRQ after resume!\n"); return retval; } hcd->saw_irq = 0; pci_restore_state (dev); #ifdef CONFIG_USB_SUSPEND pci_enable_wake (dev, dev->current_state, 0); pci_enable_wake (dev, 4, 0); #endif retval = hcd->driver->resume (hcd); if (!HCD_IS_RUNNING (hcd->state)) { dev_dbg (hcd->self.controller, "resume fail, retval %d\n", retval); usb_hc_died (hcd); } return retval; }
/** * usb_hcd_pci_resume - power management resume of a PCI-based HCD * @dev: USB Host Controller being resumed * * Store this function in the HCD's struct pci_driver as resume(). */ int usb_hcd_pci_resume (struct pci_dev *dev) { struct usb_hcd *hcd; int retval; int has_pci_pm; hcd = pci_get_drvdata(dev); has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM); if (has_pci_pm) dev_dbg(hcd->self.controller, "resume from state D%d\n", dev->current_state); if (hcd->state != HCD_STATE_SUSPENDED) { dev_dbg (hcd->self.controller, "can't resume, not suspended!\n"); return -EL3HLT; } hcd->state = USB_STATE_RESUMING; if (has_pci_pm) pci_set_power_state (dev, 0); dev->dev.power.power_state = 0; retval = request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ, hcd->description, hcd); if (retval < 0) { dev_err (hcd->self.controller, "can't restore IRQ after resume!\n"); return retval; } pci_set_master (dev); pci_restore_state (dev, hcd->pci_state); #ifdef CONFIG_USB_SUSPEND pci_enable_wake (dev, dev->current_state, 0); pci_enable_wake (dev, 4, 0); #endif retval = hcd->driver->resume (hcd); if (!HCD_IS_RUNNING (hcd->state)) { dev_dbg (hcd->self.controller, "resume fail, retval %d\n", retval); usb_hc_died (hcd); } return retval; }
/** * usb_hcd_pci_resume - power management resume of a PCI-based HCD * @dev: USB Host Controller being resumed * * Store this function in the HCD's struct pci_driver as resume(). */ int usb_hcd_pci_resume (struct pci_dev *dev) { struct usb_hcd *hcd; int retval; hcd = pci_get_drvdata(dev); dev_info (hcd->controller, "resume\n"); /* guard against multiple resumes (APM bug?) */ atomic_inc (&hcd->resume_count); if (atomic_read (&hcd->resume_count) != 1) { dev_err (hcd->controller, "concurrent PCI resumes\n"); retval = 0; goto done; } retval = -EBUSY; if (hcd->state != USB_STATE_SUSPENDED) { dev_dbg (hcd->controller, "can't resume, not suspended!\n"); goto done; } hcd->state = USB_STATE_RESUMING; pci_set_power_state (dev, 0); pci_restore_state (dev, hcd->pci_state); retval = hcd->driver->resume (hcd); if (!HCD_IS_RUNNING (hcd->state)) { dev_dbg (hcd->controller, "resume fail, retval %d\n", retval); usb_hc_died (hcd); // FIXME: recover, reset etc. } else { // FIXME for all connected devices, root-to-leaf: // driver->resume (); // proposed "new 2.5 driver model" will automate that } done: atomic_dec (&hcd->resume_count); return retval; }
static int ohci_hub_status_data (struct usb_hcd *hcd, char *buf) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); int ports, i, changed = 0, length = 1; int can_suspend = hcd->can_wakeup; unsigned long flags; spin_lock_irqsave (&ohci->lock, flags); /* handle autosuspended root: finish resuming before * letting khubd or root hub timer see state changes. */ if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER || !HCD_IS_RUNNING(ohci->hcd.state)) { can_suspend = 0; goto done; } ports = roothub_a (ohci) & RH_A_NDP; if (ports > MAX_ROOT_PORTS) { ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports, ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP); /* retry later; "should not happen" */ goto done; } /* init status */ if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC)) buf [0] = changed = 1; else buf [0] = 0; if (ports > 7) { buf [1] = 0; length++; } /* look at each port */ for (i = 0; i < ports; i++) { u32 status = roothub_portstatus (ohci, i); if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC | RH_PS_PRSC)) { changed = 1; if (i < 7) buf [0] |= 1 << (i + 1); else buf [1] |= 1 << (i - 7); continue; } /* can suspend if no ports are enabled; or if all all * enabled ports are suspended AND remote wakeup is on. */ if (!(status & RH_PS_CCS)) continue; if ((status & RH_PS_PSS) && ohci->hcd.remote_wakeup) continue; can_suspend = 0; } done: spin_unlock_irqrestore (&ohci->lock, flags); #ifdef CONFIG_PM /* save power by suspending idle root hubs; * INTR_RD wakes us when there's work * NOTE: if we can do this, we don't need a root hub timer! */ if (can_suspend && !changed && !ohci->ed_rm_list && ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES) & ohci->hc_control) == OHCI_USB_OPER && time_after (jiffies, ohci->next_statechange) && usb_trylock_device (hcd->self.root_hub) ) { ohci_vdbg (ohci, "autosuspend\n"); (void) ohci_hub_suspend (&ohci->hcd); ohci->hcd.state = USB_STATE_RUNNING; usb_unlock_device (hcd->self.root_hub); } #endif return changed ? length : 0; }
static int ohci_hub_status_data (struct usb_hcd *hcd, char *buf) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); int ports, i, changed = 0, length = 1; int can_suspend = 1; ports = roothub_a (ohci) & RH_A_NDP; if (ports > MAX_ROOT_PORTS) { if (!HCD_IS_RUNNING(ohci->hcd.state)) return -ESHUTDOWN; ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports, ohci_readl (&ohci->regs->roothub.a) & RH_A_NDP); /* retry later; "should not happen" */ return 0; } /* init status */ if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC)) buf [0] = changed = 1; else buf [0] = 0; if (ports > 7) { buf [1] = 0; length++; } /* look at each port */ for (i = 0; i < ports; i++) { u32 status = roothub_portstatus (ohci, i); if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC | RH_PS_PRSC)) { changed = 1; if (i < 7) buf [0] |= 1 << (i + 1); else buf [1] |= 1 << (i - 7); continue; } /* can suspend if no ports are enabled; or if all all * enabled ports are suspended AND remote wakeup is on. */ if (!(status & RH_PS_CCS)) continue; if ((status & RH_PS_PSS) && ohci->hcd.remote_wakeup) continue; can_suspend = 0; } #ifdef CONFIG_PM /* save power by suspending idle root hubs; * INTR_RD wakes us when there's work */ if (can_suspend && !changed && !ohci->ed_rm_list && ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES) & ohci->hc_control) == OHCI_USB_OPER && down_trylock (&hcd->self.root_hub->serialize) == 0 ) { ohci_vdbg (ohci, "autosuspend\n"); (void) ohci_hub_suspend (&ohci->hcd); ohci->hcd.state = USB_STATE_RUNNING; up (&hcd->self.root_hub->serialize); } #endif return changed ? length : 0; }