Re: [0/12] More Driver Model Locking Changes

From: Greg KH (gregkh_at_suse.de)
Date: 03/26/05

  • Next message: Lee Revell: "Re: [patch] Real-Time Preemption, -RT-2.6.12-rc1-V0.7.41-10"
    Date:	Fri, 25 Mar 2005 20:47:21 -0800
    To: Patrick Mochel <mochel@digitalimplant.org>, linux-kernel@vger.kernel.org, tom.l.nguyen@intel.com
    
    

    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 <gregkh@suse.de>

    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 majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/


  • Next message: Lee Revell: "Re: [patch] Real-Time Preemption, -RT-2.6.12-rc1-V0.7.41-10"

    Relevant Pages