===================================================================
@@ -15,6 +15,7 @@
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/pm_runtime.h>
#include "pci.h"
@@ -134,6 +135,9 @@ pci_bus_alloc_resource(struct pci_bus *b
int pci_bus_add_device(struct pci_dev *dev)
{
int retval;
+
+ pm_runtime_set_active(&dev->dev);
+ pm_runtime_enable(&dev->dev);
retval = device_add(&dev->dev);
if (retval)
return retval;
===================================================================
@@ -289,8 +289,23 @@ struct drv_dev_and_id {
static long local_pci_probe(void *_ddi)
{
struct drv_dev_and_id *ddi = _ddi;
-
- return ddi->drv->probe(ddi->dev, ddi->id);
+ struct device *dev = &ddi->dev->dev;
+ struct device_driver *driver = dev->driver;
+ int rc;
+
+ dev->driver = NULL;
+ rc = pm_runtime_get_sync(dev);
+ dev->driver = driver;
+ if (rc < 0)
+ return rc;
+
+ rc = ddi->drv->probe(ddi->dev, ddi->id);
+ if (rc) {
+ dev->driver = NULL;
+ pm_runtime_put_sync(dev);
+ dev->driver = driver;
+ }
+ return rc;
}
static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
@@ -365,15 +380,24 @@ static int pci_device_probe(struct devic
static int pci_device_remove(struct device * dev)
{
+ struct device_driver *driver = dev->driver;
struct pci_dev * pci_dev = to_pci_dev(dev);
struct pci_driver * drv = pci_dev->driver;
if (drv) {
- if (drv->remove)
+ if (drv->remove) {
+ pm_runtime_get_sync(dev);
drv->remove(pci_dev);
+ pm_runtime_put_noidle(dev);
+ }
pci_dev->driver = NULL;
}
+ /* Undo the pm_runtime_get_sync() in local_pci_probe() */
+ dev->driver = NULL;
+ pm_runtime_put_sync(dev);
+ dev->driver = driver;
+
/*
* If the device is still on, set the power state as "unknown",
* since it might change by the next time we load the driver.