From e7ae88486670f3904f187d0fff9dcf469bcdd8ba Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 1 Jan 2009 19:51:15 +0100 Subject: PCI: PCIe portdrv: Fix suspend and resume of PCI Express port services There is a problem with the suspend and resume of PCI Express port service devices that the ->suspend() and ->resume() routines of each service device are called twice in each suspend-resume cycle, which is obviously wrong. The scenario is that first, the PCI Express port driver calls suspend and resume routines of each port service driver from its pcie_portdrv_suspend() and pcie_portdrv_resume() callbacks, respectively (which is correct), and second, the pcie_port_bus_type driver calls them from its ->suspend() and ->resume() callbacks (which is not correct, because it doesn't happen at the right time). The solution is to remove the ->suspend() and ->resume() callbacks from pcie_port_bus_type and the associated functions. Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes --- drivers/pci/pcie/portdrv_bus.c | 34 ---------------------------------- 1 file changed, 34 deletions(-) (limited to 'drivers/pci/pcie/portdrv_bus.c') diff --git a/drivers/pci/pcie/portdrv_bus.c b/drivers/pci/pcie/portdrv_bus.c index 359fe5568df..3a03db4323a 100644 --- a/drivers/pci/pcie/portdrv_bus.c +++ b/drivers/pci/pcie/portdrv_bus.c @@ -16,14 +16,10 @@ #include "portdrv.h" static int pcie_port_bus_match(struct device *dev, struct device_driver *drv); -static int pcie_port_bus_suspend(struct device *dev, pm_message_t state); -static int pcie_port_bus_resume(struct device *dev); struct bus_type pcie_port_bus_type = { .name = "pci_express", .match = pcie_port_bus_match, - .suspend = pcie_port_bus_suspend, - .resume = pcie_port_bus_resume, }; EXPORT_SYMBOL_GPL(pcie_port_bus_type); @@ -48,33 +44,3 @@ static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) return 1; } - -static int pcie_port_bus_suspend(struct device *dev, pm_message_t state) -{ - struct pcie_device *pciedev; - struct pcie_port_service_driver *driver; - - if (!dev || !dev->driver) - return 0; - - pciedev = to_pcie_device(dev); - driver = to_service_driver(dev->driver); - if (driver && driver->suspend) - driver->suspend(pciedev, state); - return 0; -} - -static int pcie_port_bus_resume(struct device *dev) -{ - struct pcie_device *pciedev; - struct pcie_port_service_driver *driver; - - if (!dev || !dev->driver) - return 0; - - pciedev = to_pcie_device(dev); - driver = to_service_driver(dev->driver); - if (driver && driver->resume) - driver->resume(pciedev); - return 0; -} -- cgit v1.2.3-70-g09d2 From fa6c993736cb8cc18af86b8d17b608efa7882ab5 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 1 Jan 2009 19:52:12 +0100 Subject: PCI: PCIe portdrv: Rearrange code so that related things are together Rearrange code in drivers/pci/pcie/portdrv_bus.c and drivers/pci/pcie/portdrv_core.c so that related functions and data structures are closer together. Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes --- drivers/pci/pcie/portdrv_bus.c | 10 +++++ drivers/pci/pcie/portdrv_core.c | 90 ++++++++++++++++++----------------------- 2 files changed, 50 insertions(+), 50 deletions(-) (limited to 'drivers/pci/pcie/portdrv_bus.c') diff --git a/drivers/pci/pcie/portdrv_bus.c b/drivers/pci/pcie/portdrv_bus.c index 3a03db4323a..eec89b767f9 100644 --- a/drivers/pci/pcie/portdrv_bus.c +++ b/drivers/pci/pcie/portdrv_bus.c @@ -44,3 +44,13 @@ static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) return 1; } + +int pcie_port_bus_register(void) +{ + return bus_register(&pcie_port_bus_type); +} + +void pcie_port_bus_unregister(void) +{ + bus_unregister(&pcie_port_bus_type); +} diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 6ca5a40cc61..a0d51e3f34f 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -19,50 +19,6 @@ extern int pcie_mch_quirk; /* MSI-quirk Indicator */ -static int pcie_port_probe_service(struct device *dev) -{ - struct pcie_device *pciedev; - struct pcie_port_service_driver *driver; - int status; - - if (!dev || !dev->driver) - return -ENODEV; - - driver = to_service_driver(dev->driver); - if (!driver || !driver->probe) - return -ENODEV; - - pciedev = to_pcie_device(dev); - status = driver->probe(pciedev, driver->id_table); - if (!status) { - dev_printk(KERN_DEBUG, dev, "service driver %s loaded\n", - driver->name); - get_device(dev); - } - return status; -} - -static int pcie_port_remove_service(struct device *dev) -{ - struct pcie_device *pciedev; - struct pcie_port_service_driver *driver; - - if (!dev || !dev->driver) - return 0; - - pciedev = to_pcie_device(dev); - driver = to_service_driver(dev->driver); - if (driver && driver->remove) { - dev_printk(KERN_DEBUG, dev, "unloading service driver %s\n", - driver->name); - driver->remove(pciedev); - put_device(dev); - } - return 0; -} - -static void pcie_port_shutdown_service(struct device *dev) {} - /** * release_pcie_device - free PCI Express port service device structure * @dev: Port service device to release @@ -414,16 +370,50 @@ void pcie_port_device_remove(struct pci_dev *dev) pci_disable_msi(dev); } -int pcie_port_bus_register(void) +static int pcie_port_probe_service(struct device *dev) { - return bus_register(&pcie_port_bus_type); + struct pcie_device *pciedev; + struct pcie_port_service_driver *driver; + int status; + + if (!dev || !dev->driver) + return -ENODEV; + + driver = to_service_driver(dev->driver); + if (!driver || !driver->probe) + return -ENODEV; + + pciedev = to_pcie_device(dev); + status = driver->probe(pciedev, driver->id_table); + if (!status) { + dev_printk(KERN_DEBUG, dev, "service driver %s loaded\n", + driver->name); + get_device(dev); + } + return status; } -void pcie_port_bus_unregister(void) +static int pcie_port_remove_service(struct device *dev) { - bus_unregister(&pcie_port_bus_type); + struct pcie_device *pciedev; + struct pcie_port_service_driver *driver; + + if (!dev || !dev->driver) + return 0; + + pciedev = to_pcie_device(dev); + driver = to_service_driver(dev->driver); + if (driver && driver->remove) { + dev_printk(KERN_DEBUG, dev, "unloading service driver %s\n", + driver->name); + driver->remove(pciedev); + put_device(dev); + } + return 0; } +static void pcie_port_shutdown_service(struct device *dev) {} + int pcie_port_service_register(struct pcie_port_service_driver *new) { new->driver.name = (char *)new->name; @@ -435,9 +425,9 @@ int pcie_port_service_register(struct pcie_port_service_driver *new) return driver_register(&new->driver); } -void pcie_port_service_unregister(struct pcie_port_service_driver *new) +void pcie_port_service_unregister(struct pcie_port_service_driver *drv) { - driver_unregister(&new->driver); + driver_unregister(&drv->driver); } EXPORT_SYMBOL(pcie_port_service_register); -- cgit v1.2.3-70-g09d2