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/

Reply via email to