aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@linux.intel.com>2018-11-28 16:32:11 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-12-06 16:00:43 +0100
commitc37d721c68ad88925ba0e72f6e14acb829a8c6bb (patch)
treeaec913e20edb678f7751bcc1a036d039fefd7fb7
parentdriver core: platform: Respect return code of platform_device_register_full() (diff)
downloadlinux-dev-c37d721c68ad88925ba0e72f6e14acb829a8c6bb.tar.xz
linux-dev-c37d721c68ad88925ba0e72f6e14acb829a8c6bb.zip
driver core: Move async_synchronize_full call
Move the async_synchronize_full call out of __device_release_driver and into driver_detach. The idea behind this is that the async_synchronize_full call will only guarantee that any existing async operations are flushed. This doesn't do anything to guarantee that a hotplug event that may occur while we are doing the release of the driver will not be asynchronously scheduled. By moving this into the driver_detach path we can avoid potential deadlocks as we aren't holding the device lock at this point and we should not have the driver we want to flush loaded so the flush will take care of any asynchronous events the driver we are detaching might have scheduled. Fixes: 765230b5f084 ("driver-core: add asynchronous probing support for drivers") Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Alexander Duyck <alexander.h.duyck@linux.intel.com> Reviewed-by: Luis Chamberlain <mcgrof@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/base/dd.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 689ac9dc6d81..88713f182086 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -931,9 +931,6 @@ static void __device_release_driver(struct device *dev, struct device *parent)
drv = dev->driver;
if (drv) {
- if (driver_allows_async_probing(drv))
- async_synchronize_full();
-
while (device_links_busy(dev)) {
device_unlock(dev);
if (parent)
@@ -1039,6 +1036,9 @@ void driver_detach(struct device_driver *drv)
struct device_private *dev_prv;
struct device *dev;
+ if (driver_allows_async_probing(drv))
+ async_synchronize_full();
+
for (;;) {
spin_lock(&drv->p->klist_devices.k_lock);
if (list_empty(&drv->p->klist_devices.k_list)) {