diff options
author | François Romieu <romieu@nail.test.fr.zoreil.com> | 2006-08-15 20:10:57 +0200 |
---|---|---|
committer | Francois Romieu <romieu@fr.zoreil.com> | 2006-08-31 22:15:42 +0200 |
commit | 7668a4945ba0e17a61e535a6c67aa64a319a03b4 (patch) | |
tree | 08a883a950a69e1105d1eef59ae7f6e6ec318932 /drivers/net | |
parent | e68970e7543815133224f79a858e7c9e0c42f4de (diff) | |
download | op-kernel-dev-7668a4945ba0e17a61e535a6c67aa64a319a03b4.zip op-kernel-dev-7668a4945ba0e17a61e535a6c67aa64a319a03b4.tar.gz |
8139cp: pci_get_drvdata(pdev) can not be NULL in suspend handler
1) pci_set_drvdata() is used in cp_{init/remove}_one to initialize/reset
driver_data to the relevant value (resp. net_device * and NULL).
2) each of the 3 relevant functions is issued under (device *)->sem:
2.1) pci_unregister_driver
-> driver_unregister
-> bus_remove_driver
-> driver_detach (takes (device *)->sem)
-> __device_release_driver(dev)
-> dev->bus-remove(dev) (== pci_device_remove)
-> drv->remove(pdev) (== cp_remove_one)
[...]
pci_dev->driver = NULL;
2.2) pci_register_driver
-> __pci_register_driver
-> driver_register
-> bus_add_driver
-> driver_attach
-> __driver_attach (takes (device *)->sem)
-> driver_probe_device(drv, dev)
-> dev->bus->probe(dev) (== pci_device_probe)
-> _pci_device_probe(drv, pci_dev)
-> pci_call_probe(drv, pci_dev, id)
-> drv->probe(dev, id) (== cp_init_one)
[...]
pci_dev->driver = drv;
2.3) suspend_device (takes (device *)->sem)
-> dev->bus->suspend(dev) (== pci_device_suspend)
checking for drv = pci_dev->driver != NULL
[...]
-> drv->suspend(pci_dev, state) (== cp_suspend)
dev->sem and the state of pci_dev->driver provide the expected result.
St Mary's day was a bit rainy here.
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/8139cp.c | 10 |
1 files changed, 4 insertions, 6 deletions
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 94ab3c3..a123d28 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -2023,14 +2023,12 @@ static void cp_remove_one (struct pci_dev *pdev) #ifdef CONFIG_PM static int cp_suspend (struct pci_dev *pdev, pm_message_t state) { - struct net_device *dev; - struct cp_private *cp; + struct net_device *dev = pci_get_drvdata(pdev); + struct cp_private *cp = netdev_priv(dev); unsigned long flags; - dev = pci_get_drvdata (pdev); - cp = netdev_priv(dev); - - if (!dev || !netif_running (dev)) return 0; + if (!netif_running(dev)) + return 0; netif_device_detach (dev); netif_stop_queue (dev); |