static int mei_txe_pm_runtime_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct mei_device *dev; int ret; dev_dbg(&pdev->dev, "rpm: txe: runtime suspend\n"); dev = pci_get_drvdata(pdev); if (!dev) return -ENODEV; mutex_lock(&dev->device_lock); if (mei_write_is_idle(dev)) ret = mei_txe_aliveness_set_sync(dev, 0); else ret = -EAGAIN; /* * If everything is okay we're about to enter PCI low * power state therefor we need to save and disable * the interrupts towards host. * However if device is not wakeable we cannot do that */ if (!ret && pci_dev_run_wake(pdev)) mei_txe_intr_save(dev); dev_dbg(&pdev->dev, "rpm: txe: runtime suspend ret=%d\n", ret); mutex_unlock(&dev->device_lock); return ret; }
static void xhci_ush_pci_remove(struct pci_dev *dev) { struct xhci_hcd *xhci; xhci = hcd_to_xhci(pci_get_drvdata(dev)); if (xhci->shared_hcd) { usb_remove_hcd(xhci->shared_hcd); usb_put_hcd(xhci->shared_hcd); } if (!pci_dev_run_wake(dev)) pm_runtime_get_noresume(&dev->dev); pm_runtime_forbid(&dev->dev); usb_hcd_pci_remove(dev); /* Free the aux irq */ hsic_aux_irq_free(); hsic_wakeup_irq_free(); gpio_free(hsic.aux_gpio); gpio_free(hsic.wakeup_gpio); hsic.hsic_stopped = 1; hsic_enable = 0; kfree(xhci); }
static void xhci_ush_pci_remove(struct pci_dev *dev) { struct xhci_hcd *xhci; xhci = hcd_to_xhci(pci_get_drvdata(dev)); if (xhci->shared_hcd) { usb_remove_hcd(xhci->shared_hcd); usb_put_hcd(xhci->shared_hcd); } if (!pci_dev_run_wake(dev)) pm_runtime_get_noresume(&dev->dev); pm_runtime_forbid(&dev->dev); usb_hcd_pci_remove(dev); /* Free the aux irq */ hsic_aux_irq_free(); hsic_wakeup_irq_free(); gpio_free(hsic.aux_gpio); gpio_free(hsic.wakeup_gpio); hsic.port_disconnect = 1; hsic_enable = 0; wake_lock_destroy(&(hsic.resume_wake_lock)); wake_lock_destroy(&hsic.s3_wake_lock); usb_unregister_notify(&hsic.hsic_pm_nb); unregister_pm_notifier(&hsic.hsic_s3_entry_nb); kfree(xhci); }
/** * mei_txe_remove - Device Shutdown Routine * * @pdev: PCI device structure * * mei_txe_shutdown is called from the reboot notifier * it's a simplified version of remove so we go down * faster. */ static void mei_txe_shutdown(struct pci_dev *pdev) { struct mei_device *dev; dev = pci_get_drvdata(pdev); if (!dev) return; dev_dbg(&pdev->dev, "shutdown\n"); mei_stop(dev); if (!pci_dev_run_wake(pdev)) mei_txe_unset_pm_domain(dev); mei_disable_interrupts(dev); free_irq(pdev->irq, dev); }
/** * mei_remove - Device Removal Routine * * @pdev: PCI device structure * * mei_remove is called by the PCI subsystem to alert the driver * that it should release a PCI device. */ static void mei_txe_remove(struct pci_dev *pdev) { struct mei_device *dev; struct mei_txe_hw *hw; dev = pci_get_drvdata(pdev); if (!dev) { dev_err(&pdev->dev, "mei: dev =NULL\n"); return; } pm_runtime_get_noresume(&pdev->dev); hw = to_txe_hw(dev); mei_stop(dev); if (!pci_dev_run_wake(pdev)) mei_txe_unset_pm_domain(dev); /* disable interrupts */ mei_disable_interrupts(dev); free_irq(pdev->irq, dev); pci_disable_msi(pdev); mei_mm_deinit(hw->mdev); if (hw->pool_release) hw->pool_release(hw); pci_set_drvdata(pdev, NULL); mei_txe_pci_iounmap(pdev, hw); mei_deregister(dev); kfree(dev); pci_release_regions(pdev); pci_disable_device(pdev); }
/** * mei_me_remove - Device Removal Routine * * @pdev: PCI device structure * * mei_remove is called by the PCI subsystem to alert the driver * that it should release a PCI device. */ static void mei_me_remove(struct pci_dev *pdev) { struct mei_device *dev; struct mei_me_hw *hw; dev = pci_get_drvdata(pdev); if (!dev) return; if (mei_pg_is_enabled(dev)) pm_runtime_get_noresume(&pdev->dev); hw = to_me_hw(dev); dev_dbg(&pdev->dev, "stop\n"); mei_stop(dev); if (!pci_dev_run_wake(pdev)) mei_me_unset_pm_domain(dev); /* disable interrupts */ mei_disable_interrupts(dev); free_irq(pdev->irq, dev); pci_disable_msi(pdev); if (hw->mem_addr) pci_iounmap(pdev, hw->mem_addr); mei_deregister(dev); kfree(dev); pci_release_regions(pdev); pci_disable_device(pdev); }
/** * mei_txe_remove - Device Removal Routine * * @pdev: PCI device structure * * mei_remove is called by the PCI subsystem to alert the driver * that it should release a PCI device. */ static void mei_txe_remove(struct pci_dev *pdev) { struct mei_device *dev; dev = pci_get_drvdata(pdev); if (!dev) { dev_err(&pdev->dev, "mei: dev == NULL\n"); return; } pm_runtime_get_noresume(&pdev->dev); mei_stop(dev); if (!pci_dev_run_wake(pdev)) mei_txe_unset_pm_domain(dev); mei_disable_interrupts(dev); free_irq(pdev->irq, dev); mei_deregister(dev); }
static int mei_txe_pm_runtime_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct mei_device *dev; int ret; dev_dbg(&pdev->dev, "rpm: txe: runtime suspend\n"); dev = pci_get_drvdata(pdev); if (!dev) return -ENODEV; mutex_lock(&dev->device_lock); if (mei_write_is_idle(dev)) ret = mei_txe_aliveness_set_sync(dev, 0); else ret = -EAGAIN; /* * If everything is okay we're about to enter PCI low * power state (D3) therefor we need to disable the * interrupts towards host. * However if device is not wakeable we do not enter * D-low state and we need to keep the interrupt kicking */ if (!ret && pci_dev_run_wake(pdev)) mei_disable_interrupts(dev); dev_dbg(&pdev->dev, "rpm: txe: runtime suspend ret=%d\n", ret); mutex_unlock(&dev->device_lock); if (ret && ret != -EAGAIN) schedule_work(&dev->reset_work); return ret; }
static void ehci_hsic_remove(struct pci_dev *pdev) { struct usb_hcd *hcd = pci_get_drvdata(pdev); struct ehci_hcd *ehci = hcd_to_ehci(hcd); if (!hcd) return; hsic.hsic_stopped = 1; hsic_enable = 0; if (pci_dev_run_wake(pdev)) pm_runtime_get_noresume(&pdev->dev); if (!enabling_disabling) { if (!pci_dev_run_wake(pdev)) pm_runtime_get_noresume(&pdev->dev); pm_runtime_forbid(&pdev->dev); } /* Free the aux irq */ hsic_aux_irq_free(); hsic_wakeup_irq_free(); /* Fake an interrupt request in order to give the driver a chance * to test whether the controller hardware has been removed (e.g., * cardbus physical eject). */ local_irq_disable(); usb_hcd_irq(0, hcd); local_irq_enable(); usb_remove_hcd(hcd); #if 0 ehci_hsic_port_power(ehci, 0); #endif /* Set phy low power mode, disable phy clock */ ehci_hsic_phy_power(ehci, 1); if (hcd->driver->flags & HCD_MEMORY) { iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); } else { release_region(hcd->rsrc_start, hcd->rsrc_len); } usb_put_hcd(hcd); gpio_free(hsic.aux_gpio); gpio_free(hsic.wakeup_gpio); pci_disable_device(pdev); cancel_delayed_work_sync(&hsic.wakeup_work); destroy_workqueue(hsic.work_queue); wake_lock_destroy(&(hsic.resume_wake_lock)); wake_lock_destroy(&hsic.s3_wake_lock); usb_unregister_notify(&hsic.hsic_pm_nb); unregister_pm_notifier(&hsic.hsic_s3_entry_nb); hsic_debugfs_cleanup(); }
static int ehci_hsic_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct hc_driver *driver; struct usb_hcd *hcd; struct ehci_hcd *ehci; int irq, retval; pr_debug("initializing Intel EHCI HSIC Host Controller\n"); if (usb_disabled()) return -ENODEV; if (!id) return -EINVAL; pci_dev = pdev; if (pci_enable_device(pdev) < 0) return -ENODEV; pdev->current_state = PCI_D0; wake_lock_init(&hsic.resume_wake_lock, WAKE_LOCK_SUSPEND, "hsic_aux2_wlock"); wake_lock_init(&hsic.s3_wake_lock, WAKE_LOCK_SUSPEND, "hsic_s3_wlock"); hsic.hsic_pm_nb.notifier_call = hsic_pm_notify; usb_register_notify(&hsic.hsic_pm_nb); hsic.hsic_s3_entry_nb.notifier_call = hsic_s3_entry_notify; register_pm_notifier(&hsic.hsic_s3_entry_nb); /* we need not call pci_enable_dev since otg transceiver already take * the control of this device and this probe actaully gets called by * otg transceiver driver with HNP protocol. */ irq = pdev->irq; if (!pdev->irq) { dev_dbg(&pdev->dev, "No IRQ.\n"); retval = -ENODEV; goto disable_pci; } driver = (struct hc_driver *)id->driver_data; if (!driver) return -EINVAL; /* AUX GPIO init */ retval = hsic_aux_gpio_init(); if (retval < 0) { dev_err(&pdev->dev, "AUX GPIO init fail\n"); retval = -ENODEV; goto disable_pci; } /* AUX GPIO init */ retval = hsic_wakeup_gpio_init(); if (retval < 0) { dev_err(&pdev->dev, "Wakeup GPIO init fail\n"); retval = -ENODEV; goto disable_pci; } hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { retval = -ENOMEM; goto disable_pci; } ehci = hcd_to_ehci(hcd); hcd->rsrc_start = pci_resource_start(pdev, 0); hcd->rsrc_len = pci_resource_len(pdev, 0); if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, driver->description)) { dev_dbg(&pdev->dev, "controller already in use\n"); retval = -EBUSY; goto clear_companion; } hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); if (hcd->regs == NULL) { dev_dbg(&pdev->dev, "error mapping memory\n"); retval = -EFAULT; goto release_mem_region; } pci_set_master(pdev); if (hsic.hsic_enable_created == 0) { retval = create_device_files(); if (retval < 0) { dev_dbg(&pdev->dev, "error create device files\n"); goto release_mem_region; } hsic.hsic_enable_created = 1; } if (hsic.hsic_mutex_init == 0) { mutex_init(&hsic.hsic_mutex); mutex_init(&hsic.wlock_mutex); hsic.hsic_mutex_init = 1; } if (hsic.aux_wq_init == 0) { init_waitqueue_head(&hsic.aux_wq); hsic.aux_wq_init = 1; } hsic.work_queue = create_singlethread_workqueue("hsic"); INIT_DELAYED_WORK(&hsic.wakeup_work, wakeup_work); INIT_DELAYED_WORK(&(hsic.hsic_aux), hsic_aux_work); hcd->hsic_notify = hsic_notify; retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED | IRQF_NO_SUSPEND); if (retval != 0) goto unmap_registers; dev_set_drvdata(&pdev->dev, hcd); /* Clear phy low power mode, enable phy clock */ ehci_hsic_phy_power(ehci, 0); if (pci_dev_run_wake(pdev)) pm_runtime_put_noidle(&pdev->dev); if (!enabling_disabling) { /* Check here to avoid to call pm_runtime_put_noidle() twice */ if (!pci_dev_run_wake(pdev)) pm_runtime_put_noidle(&pdev->dev); pm_runtime_allow(&pdev->dev); } hsic.hsic_stopped = 0; hsic_enable = 1; hsic.s3_rt_state = RESUMED; s3_wake_lock(); hsic_debugfs_init(hcd); return retval; unmap_registers: destroy_workqueue(hsic.work_queue); if (driver->flags & HCD_MEMORY) { iounmap(hcd->regs); release_mem_region: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); } else release_region(hcd->rsrc_start, hcd->rsrc_len); clear_companion: dev_set_drvdata(&pdev->dev, NULL); usb_put_hcd(hcd); disable_pci: pci_disable_device(pdev); dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval); wake_lock_destroy(&(hsic.resume_wake_lock)); wake_lock_destroy(&hsic.s3_wake_lock); return retval; }
/* * We need to register our own PCI probe function (instead of the USB core's * function) in order to create a second roothub under xHCI. */ static int xhci_ush_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { int retval; struct xhci_hcd *xhci; struct hc_driver *driver; struct usb_hcd *hcd; driver = (struct hc_driver *)id->driver_data; pci_dev = dev; /* AUX GPIO init */ retval = hsic_aux_gpio_init(); if (retval < 0) { dev_err(&dev->dev, "AUX GPIO init fail\n"); retval = -ENODEV; } /* AUX GPIO init */ retval = hsic_wakeup_gpio_init(); if (retval < 0) { dev_err(&dev->dev, "Wakeup GPIO init fail\n"); retval = -ENODEV; } /* Register the USB 2.0 roothub. * FIXME: USB core must know to register the USB 2.0 roothub first. * This is sort of silly, because we could just set the HCD driver flags * to say USB 2.0, but I'm not sure what the implications would be in * the other parts of the HCD code. */ retval = usb_hcd_pci_probe(dev, id); if (retval) return retval; /* USB 2.0 roothub is stored in the PCI device now. */ hcd = dev_get_drvdata(&dev->dev); xhci = hcd_to_xhci(hcd); xhci->shared_hcd = usb_create_shared_hcd(driver, &dev->dev, pci_name(dev), hcd); if (!xhci->shared_hcd) { retval = -ENOMEM; goto dealloc_usb2_hcd; } /* Set the xHCI pointer before xhci_pci_setup() (aka hcd_driver.reset) * is called by usb_add_hcd(). */ *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci; if (hsic.hsic_enable_created == 0) { retval = create_device_files(); if (retval < 0) { dev_dbg(&dev->dev, "error create device files\n"); goto dealloc_usb2_hcd; } hsic.hsic_enable_created = 1; } if (hsic.hsic_mutex_init == 0) { mutex_init(&hsic.hsic_mutex); hsic.hsic_mutex_init = 1; } if (hsic.aux_wq_init == 0) { init_waitqueue_head(&hsic.aux_wq); hsic.aux_wq_init = 1; } hsic.work_queue = create_singlethread_workqueue("hsic"); INIT_WORK(&hsic.wakeup_work, wakeup_work); INIT_DELAYED_WORK(&(hsic.hsic_aux), hsic_aux_work); retval = usb_add_hcd(xhci->shared_hcd, dev->irq, IRQF_SHARED); if (retval) goto put_usb3_hcd; /* Roothub already marked as USB 3.0 speed */ /* Enable Controller wakeup capability */ device_set_wakeup_enable(&dev->dev, true); /* Enable runtime pm ability */ hcd->rpm_control = 1; hcd->rpm_resume = 0; pm_runtime_set_active(&dev->dev); /* Check here to avoid to call pm_runtime_put_noidle() twice */ if (!pci_dev_run_wake(dev)) pm_runtime_put_noidle(&dev->dev); pm_runtime_allow(&dev->dev); hsic.hsic_stopped = 0; hsic_enable = 1; return 0; put_usb3_hcd: usb_put_hcd(xhci->shared_hcd); dealloc_usb2_hcd: usb_hcd_pci_remove(dev); return retval; }
/** * mei_me_probe - Device Initialization Routine * * @pdev: PCI device structure * @ent: entry in kcs_pci_tbl * * Return: 0 on success, <0 on failure. */ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { const struct mei_cfg *cfg = (struct mei_cfg *)(ent->driver_data); struct mei_device *dev; struct mei_me_hw *hw; int err; if (!mei_me_quirk_probe(pdev, cfg)) return -ENODEV; /* enable pci dev */ err = pci_enable_device(pdev); if (err) { dev_err(&pdev->dev, "failed to enable pci device.\n"); goto end; } /* set PCI host mastering */ pci_set_master(pdev); /* pci request regions for mei driver */ err = pci_request_regions(pdev, KBUILD_MODNAME); if (err) { dev_err(&pdev->dev, "failed to get pci regions.\n"); goto disable_device; } if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) || dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64))) { err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (err) err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); } if (err) { dev_err(&pdev->dev, "No usable DMA configuration, aborting\n"); goto release_regions; } /* allocates and initializes the mei dev structure */ dev = mei_me_dev_init(pdev, cfg); if (!dev) { err = -ENOMEM; goto release_regions; } hw = to_me_hw(dev); /* mapping IO device memory */ hw->mem_addr = pci_iomap(pdev, 0, 0); if (!hw->mem_addr) { dev_err(&pdev->dev, "mapping I/O device memory failure.\n"); err = -ENOMEM; goto free_device; } pci_enable_msi(pdev); /* request and enable interrupt */ if (pci_dev_msi_enabled(pdev)) err = request_threaded_irq(pdev->irq, NULL, mei_me_irq_thread_handler, IRQF_ONESHOT, KBUILD_MODNAME, dev); else err = request_threaded_irq(pdev->irq, mei_me_irq_quick_handler, mei_me_irq_thread_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (err) { dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n", pdev->irq); goto disable_msi; } if (mei_start(dev)) { dev_err(&pdev->dev, "init hw failure.\n"); err = -ENODEV; goto release_irq; } pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_ME_RPM_TIMEOUT); pm_runtime_use_autosuspend(&pdev->dev); err = mei_register(dev, &pdev->dev); if (err) goto release_irq; pci_set_drvdata(pdev, dev); schedule_delayed_work(&dev->timer_work, HZ); /* * For not wake-able HW runtime pm framework * can't be used on pci device level. * Use domain runtime pm callbacks instead. */ if (!pci_dev_run_wake(pdev)) mei_me_set_pm_domain(dev); if (mei_pg_is_enabled(dev)) pm_runtime_put_noidle(&pdev->dev); dev_dbg(&pdev->dev, "initialization successful.\n"); return 0; release_irq: mei_cancel_work(dev); mei_disable_interrupts(dev); free_irq(pdev->irq, dev); disable_msi: pci_disable_msi(pdev); pci_iounmap(pdev, hw->mem_addr); free_device: kfree(dev); release_regions: pci_release_regions(pdev); disable_device: pci_disable_device(pdev); end: dev_err(&pdev->dev, "initialization failed.\n"); return err; }
/** * mei_txe_probe - Device Initialization Routine * * @pdev: PCI device structure * @ent: entry in mei_txe_pci_tbl * * Return: 0 on success, <0 on failure. */ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct mei_device *dev; struct mei_txe_hw *hw; int err; int i; /* enable pci dev */ err = pci_enable_device(pdev); if (err) { dev_err(&pdev->dev, "failed to enable pci device.\n"); goto end; } /* set PCI host mastering */ pci_set_master(pdev); /* pci request regions for mei driver */ err = pci_request_regions(pdev, KBUILD_MODNAME); if (err) { dev_err(&pdev->dev, "failed to get pci regions.\n"); goto disable_device; } err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); if (err) { err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (err) { dev_err(&pdev->dev, "No suitable DMA available.\n"); goto release_regions; } } /* allocates and initializes the mei dev structure */ dev = mei_txe_dev_init(pdev); if (!dev) { err = -ENOMEM; goto release_regions; } hw = to_txe_hw(dev); /* mapping IO device memory */ for (i = SEC_BAR; i < NUM_OF_MEM_BARS; i++) { hw->mem_addr[i] = pci_iomap(pdev, i, 0); if (!hw->mem_addr[i]) { dev_err(&pdev->dev, "mapping I/O device memory failure.\n"); err = -ENOMEM; goto free_device; } } pci_enable_msi(pdev); /* clear spurious interrupts */ mei_clear_interrupts(dev); /* request and enable interrupt */ if (pci_dev_msi_enabled(pdev)) err = request_threaded_irq(pdev->irq, NULL, mei_txe_irq_thread_handler, IRQF_ONESHOT, KBUILD_MODNAME, dev); else err = request_threaded_irq(pdev->irq, mei_txe_irq_quick_handler, mei_txe_irq_thread_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (err) { dev_err(&pdev->dev, "mei: request_threaded_irq failure. irq = %d\n", pdev->irq); goto free_device; } if (mei_start(dev)) { dev_err(&pdev->dev, "init hw failure.\n"); err = -ENODEV; goto release_irq; } pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_TXI_RPM_TIMEOUT); pm_runtime_use_autosuspend(&pdev->dev); err = mei_register(dev, &pdev->dev); if (err) goto stop; pci_set_drvdata(pdev, dev); /* * For not wake-able HW runtime pm framework * can't be used on pci device level. * Use domain runtime pm callbacks instead. */ if (!pci_dev_run_wake(pdev)) mei_txe_set_pm_domain(dev); pm_runtime_put_noidle(&pdev->dev); return 0; stop: mei_stop(dev); release_irq: mei_cancel_work(dev); /* disable interrupts */ mei_disable_interrupts(dev); free_irq(pdev->irq, dev); pci_disable_msi(pdev); free_device: mei_txe_pci_iounmap(pdev, hw); kfree(dev); release_regions: pci_release_regions(pdev); disable_device: pci_disable_device(pdev); end: dev_err(&pdev->dev, "initialization failed.\n"); return err; }