On Fri, Mar 25, 2005 at 04:03:09PM -0800, Greg KH wrote: > > Oh, looks like pci express now has problems too, I'll go hit that one > next...
Here's a fix for pci express. For some reason I don't think they are using the driver model properly here, but I could be wrong... thanks, greg k-h [pcie] use device_for_each_child() to properly access child devices. Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]> diff -Nru a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c --- a/drivers/pci/pcie/portdrv_core.c 2005-03-25 20:44:04 -08:00 +++ b/drivers/pci/pcie/portdrv_core.c 2005-03-25 20:44:04 -08:00 @@ -232,9 +232,6 @@ /* Initialize generic device interface */ device = &dev->device; memset(device, 0, sizeof(struct device)); - INIT_LIST_HEAD(&device->node); - INIT_LIST_HEAD(&device->children); - INIT_LIST_HEAD(&device->bus_list); device->bus = &pcie_port_bus_type; device->driver = NULL; device->driver_data = NULL; @@ -317,84 +314,71 @@ } #ifdef CONFIG_PM -int pcie_port_device_suspend(struct pci_dev *dev, u32 state) + +static int suspend_iter(struct device *dev, void *data) { - struct list_head *head, *tmp; - struct device *parent, *child; - struct device_driver *driver; struct pcie_port_service_driver *service_driver; + u32 state = (u32)data; - parent = &dev->dev; - head = &parent->children; - tmp = head->next; - while (head != tmp) { - child = container_of(tmp, struct device, node); - tmp = tmp->next; - if (child->bus != &pcie_port_bus_type) - continue; - driver = child->driver; - if (!driver) - continue; - service_driver = to_service_driver(driver); - if (service_driver->suspend) - service_driver->suspend(to_pcie_device(child), state); + 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), state); } + return 0; +} + +int pcie_port_device_suspend(struct pci_dev *dev, u32 state) +{ + device_for_each_child(&dev->dev, (void *)state, suspend_iter); return 0; } -int pcie_port_device_resume(struct pci_dev *dev) -{ - struct list_head *head, *tmp; - struct device *parent, *child; - struct device_driver *driver; +static int resume_iter(struct device *dev, void *data) +{ struct pcie_port_service_driver *service_driver; - parent = &dev->dev; - head = &parent->children; - tmp = head->next; - while (head != tmp) { - child = container_of(tmp, struct device, node); - tmp = tmp->next; - if (child->bus != &pcie_port_bus_type) - continue; - driver = child->driver; - if (!driver) - continue; - service_driver = to_service_driver(driver); - if (service_driver->resume) - service_driver->resume(to_pcie_device(child)); + 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; + return 0; +} +int pcie_port_device_resume(struct pci_dev *dev) +{ + device_for_each_child(&dev->dev, NULL, resume_iter); + return 0; } #endif -void pcie_port_device_remove(struct pci_dev *dev) +static int remove_iter(struct device *dev, void *data) { - struct list_head *head, *tmp; - struct device *parent, *child; - struct device_driver *driver; struct pcie_port_service_driver *service_driver; - int interrupt_mode = PCIE_PORT_INTx_MODE; + int *interrupt_mode = data; - parent = &dev->dev; - head = &parent->children; - tmp = head->next; - while (head != tmp) { - child = container_of(tmp, struct device, node); - tmp = tmp->next; - if (child->bus != &pcie_port_bus_type) - continue; - driver = child->driver; - if (driver) { - service_driver = to_service_driver(driver); + if (dev->bus == &pcie_port_bus_type) { + if (dev->driver) { + service_driver = to_service_driver(dev->driver); if (service_driver->remove) - service_driver->remove(to_pcie_device(child)); + service_driver->remove(to_pcie_device(dev)); } - interrupt_mode = (to_pcie_device(child))->interrupt_mode; - put_device(child); - device_unregister(child); + *interrupt_mode = (to_pcie_device(dev))->interrupt_mode; + put_device(dev); + device_unregister(dev); } + return 0; +} + +void pcie_port_device_remove(struct pci_dev *dev) +{ + int interrupt_mode = PCIE_PORT_INTx_MODE; + + device_for_each_child(&dev->dev, &interrupt_mode, remove_iter); + /* Switch to INTx by default if MSI enabled */ if (interrupt_mode == PCIE_PORT_MSIX_MODE) pci_disable_msix(dev); - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/