diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2018-08-15 14:58:52 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2018-08-15 14:58:52 -0500 |
commit | c0638a455382e01e42bf66d8d41e4b703f1550a5 (patch) | |
tree | 87e95b7eec0ea23bb23fc385d3b83333532fcd3d /drivers/pci/pcie | |
parent | a8bcb5e5966ccbd99a6d06cf69ada7f95416aabc (diff) | |
parent | 4e6a13356f1c1dc27ff48ff35576a478d73f8713 (diff) | |
download | linux-c0638a455382e01e42bf66d8d41e4b703f1550a5.tar.bz2 |
Merge branch 'pci/hotplug'
- Simplify SHPC existence/permission checks (Bjorn Helgaas)
- Remove hotplug sample skeleton driver (Lukas Wunner)
- Convert pciehp to threaded IRQ handling (Lukas Wunner)
- Improve pciehp tolerance of missed events and initially unstable links
(Lukas Wunner)
- Clear spurious pciehp events on resume (Lukas Wunner)
- Add pciehp runtime PM support, including for Thunderbolt controllers
(Lukas Wunner)
- Support interrupts from pciehp bridges in D3hot (Lukas Wunner)
* pci/hotplug:
PCI: pciehp: Deduplicate presence check on probe & resume
PCI: pciehp: Avoid implicit fallthroughs in switch statements
PCI: Whitelist Thunderbolt ports for runtime D3
PCI: Whitelist native hotplug ports for runtime D3
PCI: sysfs: Resume to D0 on function reset
PCI: pciehp: Resume parent to D0 on config space access
PCI: pciehp: Resume to D0 on enable/disable
PCI: pciehp: Support interrupts sent from D3hot
PCI: pciehp: Obey compulsory command delay after resume
PCI: pciehp: Clear spurious events earlier on resume
PCI: portdrv: Deduplicate PM callback iterator
PCI: pciehp: Avoid slot access during reset
PCI: pciehp: Always enable occupied slot on probe
PCI: pciehp: Become resilient to missed events
PCI: pciehp: Tolerate initially unstable link
PCI: pciehp: Declare pciehp_enable/disable_slot() static
PCI: pciehp: Drop enable/disable lock
PCI: pciehp: Enable/disable exclusively from IRQ thread
PCI: pciehp: Track enable/disable status
PCI: pciehp: Publish to user space last on probe
PCI: hotplug: Demidlayer registration with the core
PCI: pciehp: Drop slot workqueue
PCI: pciehp: Handle events synchronously
PCI: pciehp: Stop blinking on slot enable failure
PCI: pciehp: Convert to threaded polling
PCI: pciehp: Convert to threaded IRQ
PCI: pciehp: Document struct slot and struct controller
PCI: pciehp: Declare pciehp_unconfigure_device() void
PCI: pciehp: Drop unnecessary NULL pointer check
PCI: pciehp: Fix unprotected list iteration in IRQ handler
PCI: pciehp: Fix use-after-free on unplug
PCI: hotplug: Don't leak pci_slot on registration failure
PCI: hotplug: Delete skeleton driver
PCI: shpchp: Separate existence of SHPC and permission to use it
Diffstat (limited to 'drivers/pci/pcie')
-rw-r--r-- | drivers/pci/pcie/portdrv.h | 2 | ||||
-rw-r--r-- | drivers/pci/pcie/portdrv_core.c | 30 | ||||
-rw-r--r-- | drivers/pci/pcie/portdrv_pci.c | 2 |
3 files changed, 19 insertions, 15 deletions
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index 6ffc797a0dc1..d59afa42fc14 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h @@ -50,6 +50,7 @@ struct pcie_port_service_driver { int (*probe) (struct pcie_device *dev); void (*remove) (struct pcie_device *dev); int (*suspend) (struct pcie_device *dev); + int (*resume_noirq) (struct pcie_device *dev); int (*resume) (struct pcie_device *dev); /* Device driver may resume normal operations */ @@ -82,6 +83,7 @@ extern struct bus_type pcie_port_bus_type; int pcie_port_device_register(struct pci_dev *dev); #ifdef CONFIG_PM int pcie_port_device_suspend(struct device *dev); +int pcie_port_device_resume_noirq(struct device *dev); int pcie_port_device_resume(struct device *dev); #endif void pcie_port_device_remove(struct pci_dev *dev); diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index e0261ad4bcdd..7c37d815229e 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -353,14 +353,19 @@ error_disable: } #ifdef CONFIG_PM -static int suspend_iter(struct device *dev, void *data) +typedef int (*pcie_pm_callback_t)(struct pcie_device *); + +static int pm_iter(struct device *dev, void *data) { struct pcie_port_service_driver *service_driver; + size_t offset = *(size_t *)data; + pcie_pm_callback_t cb; if ((dev->bus == &pcie_port_bus_type) && dev->driver) { service_driver = to_service_driver(dev->driver); - if (service_driver->suspend) - service_driver->suspend(to_pcie_device(dev)); + cb = *(pcie_pm_callback_t *)((void *)service_driver + offset); + if (cb) + return cb(to_pcie_device(dev)); } return 0; } @@ -371,20 +376,14 @@ static int suspend_iter(struct device *dev, void *data) */ int pcie_port_device_suspend(struct device *dev) { - return device_for_each_child(dev, NULL, suspend_iter); + size_t off = offsetof(struct pcie_port_service_driver, suspend); + return device_for_each_child(dev, &off, pm_iter); } -static int resume_iter(struct device *dev, void *data) +int pcie_port_device_resume_noirq(struct device *dev) { - struct pcie_port_service_driver *service_driver; - - if ((dev->bus == &pcie_port_bus_type) && - (dev->driver)) { - service_driver = to_service_driver(dev->driver); - if (service_driver->resume) - service_driver->resume(to_pcie_device(dev)); - } - return 0; + size_t off = offsetof(struct pcie_port_service_driver, resume_noirq); + return device_for_each_child(dev, &off, pm_iter); } /** @@ -393,7 +392,8 @@ static int resume_iter(struct device *dev, void *data) */ int pcie_port_device_resume(struct device *dev) { - return device_for_each_child(dev, NULL, resume_iter); + size_t off = offsetof(struct pcie_port_service_driver, resume); + return device_for_each_child(dev, &off, pm_iter); } #endif /* PM */ diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index b78840f54a9b..eef22dc29140 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -65,10 +65,12 @@ static int pcie_port_runtime_idle(struct device *dev) static const struct dev_pm_ops pcie_portdrv_pm_ops = { .suspend = pcie_port_device_suspend, + .resume_noirq = pcie_port_device_resume_noirq, .resume = pcie_port_device_resume, .freeze = pcie_port_device_suspend, .thaw = pcie_port_device_resume, .poweroff = pcie_port_device_suspend, + .restore_noirq = pcie_port_device_resume_noirq, .restore = pcie_port_device_resume, .runtime_suspend = pcie_port_runtime_suspend, .runtime_resume = pcie_port_runtime_resume, |