aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2010-06-08 15:23:51 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-07-30 12:29:09 -0400
commitf3ec4f87d607f40497afdb5ac03f11e2ea253d52 (patch)
treeb485337aee10cb1c0fcb1593d8947b5370aa73ff /drivers
parenta2dccdb2055abeb8a7ce8e45e5f83de9c980a00c (diff)
PCI: change device runtime PM settings for probe and remove
This patch (as1388) changes the way the PCI core handles runtime PM settings when probing or unbinding drivers. Now the core will make sure the device is enabled for runtime PM, with a usage count >= 1, when a driver is probed. It does the same when calling a driver's remove method. If the driver wants to use runtime PM, all it has to do is call pm_runtime_pu_noidle() near the end of its probe routine (to cancel the core's usage increment) and pm_runtime_get_noresume() near the start of its remove routine (to restore the usage count). It does not need to mess around with setting the runtime state to enabled, disabled, active, or suspended. The patch updates e1000e and r8169, the only PCI drivers that already use the existing runtime PM interface. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Acked-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/e1000e/netdev.c16
-rw-r--r--drivers/net/r8169.c16
-rw-r--r--drivers/pci/pci-driver.c32
3 files changed, 37 insertions, 27 deletions
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 57a7e41da69e..4afc8dd9b935 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -5721,11 +5721,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
5721 5721
5722 e1000_print_device_info(adapter); 5722 e1000_print_device_info(adapter);
5723 5723
5724 if (pci_dev_run_wake(pdev)) { 5724 if (pci_dev_run_wake(pdev))
5725 pm_runtime_set_active(&pdev->dev); 5725 pm_runtime_put_noidle(&pdev->dev);
5726 pm_runtime_enable(&pdev->dev);
5727 }
5728 pm_schedule_suspend(&pdev->dev, MSEC_PER_SEC);
5729 5726
5730 return 0; 5727 return 0;
5731 5728
@@ -5771,8 +5768,6 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
5771 struct e1000_adapter *adapter = netdev_priv(netdev); 5768 struct e1000_adapter *adapter = netdev_priv(netdev);
5772 bool down = test_bit(__E1000_DOWN, &adapter->state); 5769 bool down = test_bit(__E1000_DOWN, &adapter->state);
5773 5770
5774 pm_runtime_get_sync(&pdev->dev);
5775
5776 /* 5771 /*
5777 * flush_scheduled work may reschedule our watchdog task, so 5772 * flush_scheduled work may reschedule our watchdog task, so
5778 * explicitly disable watchdog tasks from being rescheduled 5773 * explicitly disable watchdog tasks from being rescheduled
@@ -5797,11 +5792,8 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
5797 clear_bit(__E1000_DOWN, &adapter->state); 5792 clear_bit(__E1000_DOWN, &adapter->state);
5798 unregister_netdev(netdev); 5793 unregister_netdev(netdev);
5799 5794
5800 if (pci_dev_run_wake(pdev)) { 5795 if (pci_dev_run_wake(pdev))
5801 pm_runtime_disable(&pdev->dev); 5796 pm_runtime_get_noresume(&pdev->dev);
5802 pm_runtime_set_suspended(&pdev->dev);
5803 }
5804 pm_runtime_put_noidle(&pdev->dev);
5805 5797
5806 /* 5798 /*
5807 * Release control of h/w to f/w. If f/w is AMT enabled, this 5799 * Release control of h/w to f/w. If f/w is AMT enabled, this
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index cdc6a5c2e70d..c982a4763bef 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -3219,11 +3219,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
3219 3219
3220 device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); 3220 device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
3221 3221
3222 if (pci_dev_run_wake(pdev)) { 3222 if (pci_dev_run_wake(pdev))
3223 pm_runtime_set_active(&pdev->dev); 3223 pm_runtime_put_noidle(&pdev->dev);
3224 pm_runtime_enable(&pdev->dev);
3225 }
3226 pm_runtime_idle(&pdev->dev);
3227 3224
3228out: 3225out:
3229 return rc; 3226 return rc;
@@ -3246,17 +3243,12 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
3246 struct net_device *dev = pci_get_drvdata(pdev); 3243 struct net_device *dev = pci_get_drvdata(pdev);
3247 struct rtl8169_private *tp = netdev_priv(dev); 3244 struct rtl8169_private *tp = netdev_priv(dev);
3248 3245
3249 pm_runtime_get_sync(&pdev->dev);
3250
3251 flush_scheduled_work(); 3246 flush_scheduled_work();
3252 3247
3253 unregister_netdev(dev); 3248 unregister_netdev(dev);
3254 3249
3255 if (pci_dev_run_wake(pdev)) { 3250 if (pci_dev_run_wake(pdev))
3256 pm_runtime_disable(&pdev->dev); 3251 pm_runtime_get_noresume(&pdev->dev);
3257 pm_runtime_set_suspended(&pdev->dev);
3258 }
3259 pm_runtime_put_noidle(&pdev->dev);
3260 3252
3261 /* restore original MAC address */ 3253 /* restore original MAC address */
3262 rtl_rar_set(tp, dev->perm_addr); 3254 rtl_rar_set(tp, dev->perm_addr);
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index f9a0aec3abcf..8a6f797de8e5 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -289,8 +289,26 @@ struct drv_dev_and_id {
289static long local_pci_probe(void *_ddi) 289static long local_pci_probe(void *_ddi)
290{ 290{
291 struct drv_dev_and_id *ddi = _ddi; 291 struct drv_dev_and_id *ddi = _ddi;
292 292 struct device *dev = &ddi->dev->dev;
293 return ddi->drv->probe(ddi->dev, ddi->id); 293 int rc;
294
295 /* Unbound PCI devices are always set to disabled and suspended.
296 * During probe, the device is set to enabled and active and the
297 * usage count is incremented. If the driver supports runtime PM,
298 * it should call pm_runtime_put_noidle() in its probe routine and
299 * pm_runtime_get_noresume() in its remove routine.
300 */
301 pm_runtime_get_noresume(dev);
302 pm_runtime_set_active(dev);
303 pm_runtime_enable(dev);
304
305 rc = ddi->drv->probe(ddi->dev, ddi->id);
306 if (rc) {
307 pm_runtime_disable(dev);
308 pm_runtime_set_suspended(dev);
309 pm_runtime_put_noidle(dev);
310 }
311 return rc;
294} 312}
295 313
296static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, 314static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
@@ -369,11 +387,19 @@ static int pci_device_remove(struct device * dev)
369 struct pci_driver * drv = pci_dev->driver; 387 struct pci_driver * drv = pci_dev->driver;
370 388
371 if (drv) { 389 if (drv) {
372 if (drv->remove) 390 if (drv->remove) {
391 pm_runtime_get_sync(dev);
373 drv->remove(pci_dev); 392 drv->remove(pci_dev);
393 pm_runtime_put_noidle(dev);
394 }
374 pci_dev->driver = NULL; 395 pci_dev->driver = NULL;
375 } 396 }
376 397
398 /* Undo the runtime PM settings in local_pci_probe() */
399 pm_runtime_disable(dev);
400 pm_runtime_set_suspended(dev);
401 pm_runtime_put_noidle(dev);
402
377 /* 403 /*
378 * If the device is still on, set the power state as "unknown", 404 * If the device is still on, set the power state as "unknown",
379 * since it might change by the next time we load the driver. 405 * since it might change by the next time we load the driver.