diff options
Diffstat (limited to 'drivers/base/dd.c')
-rw-r--r-- | drivers/base/dd.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index dcb8a6e48692..e3bbed8a617c 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
@@ -85,8 +85,20 @@ static void deferred_probe_work_func(struct work_struct *work) | |||
85 | * manipulate the deferred list | 85 | * manipulate the deferred list |
86 | */ | 86 | */ |
87 | mutex_unlock(&deferred_probe_mutex); | 87 | mutex_unlock(&deferred_probe_mutex); |
88 | |||
89 | /* | ||
90 | * Force the device to the end of the dpm_list since | ||
91 | * the PM code assumes that the order we add things to | ||
92 | * the list is a good order for suspend but deferred | ||
93 | * probe makes that very unsafe. | ||
94 | */ | ||
95 | device_pm_lock(); | ||
96 | device_pm_move_last(dev); | ||
97 | device_pm_unlock(); | ||
98 | |||
88 | dev_dbg(dev, "Retrying from deferred list\n"); | 99 | dev_dbg(dev, "Retrying from deferred list\n"); |
89 | bus_probe_device(dev); | 100 | bus_probe_device(dev); |
101 | |||
90 | mutex_lock(&deferred_probe_mutex); | 102 | mutex_lock(&deferred_probe_mutex); |
91 | 103 | ||
92 | put_device(dev); | 104 | put_device(dev); |
@@ -283,6 +295,7 @@ probe_failed: | |||
283 | devres_release_all(dev); | 295 | devres_release_all(dev); |
284 | driver_sysfs_remove(dev); | 296 | driver_sysfs_remove(dev); |
285 | dev->driver = NULL; | 297 | dev->driver = NULL; |
298 | dev_set_drvdata(dev, NULL); | ||
286 | 299 | ||
287 | if (ret == -EPROBE_DEFER) { | 300 | if (ret == -EPROBE_DEFER) { |
288 | /* Driver requested deferred probing */ | 301 | /* Driver requested deferred probing */ |
@@ -356,10 +369,9 @@ int driver_probe_device(struct device_driver *drv, struct device *dev) | |||
356 | pr_debug("bus: '%s': %s: matched device %s with driver %s\n", | 369 | pr_debug("bus: '%s': %s: matched device %s with driver %s\n", |
357 | drv->bus->name, __func__, dev_name(dev), drv->name); | 370 | drv->bus->name, __func__, dev_name(dev), drv->name); |
358 | 371 | ||
359 | pm_runtime_get_noresume(dev); | ||
360 | pm_runtime_barrier(dev); | 372 | pm_runtime_barrier(dev); |
361 | ret = really_probe(dev, drv); | 373 | ret = really_probe(dev, drv); |
362 | pm_runtime_put_sync(dev); | 374 | pm_runtime_idle(dev); |
363 | 375 | ||
364 | return ret; | 376 | return ret; |
365 | } | 377 | } |
@@ -406,9 +418,8 @@ int device_attach(struct device *dev) | |||
406 | ret = 0; | 418 | ret = 0; |
407 | } | 419 | } |
408 | } else { | 420 | } else { |
409 | pm_runtime_get_noresume(dev); | ||
410 | ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); | 421 | ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); |
411 | pm_runtime_put_sync(dev); | 422 | pm_runtime_idle(dev); |
412 | } | 423 | } |
413 | out_unlock: | 424 | out_unlock: |
414 | device_unlock(dev); | 425 | device_unlock(dev); |
@@ -487,6 +498,7 @@ static void __device_release_driver(struct device *dev) | |||
487 | drv->remove(dev); | 498 | drv->remove(dev); |
488 | devres_release_all(dev); | 499 | devres_release_all(dev); |
489 | dev->driver = NULL; | 500 | dev->driver = NULL; |
501 | dev_set_drvdata(dev, NULL); | ||
490 | klist_remove(&dev->p->knode_driver); | 502 | klist_remove(&dev->p->knode_driver); |
491 | if (dev->bus) | 503 | if (dev->bus) |
492 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, | 504 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, |