aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/base.h2
-rw-r--r--drivers/base/dd.c48
-rw-r--r--drivers/base/power/main.c17
3 files changed, 66 insertions, 1 deletions
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 1782f3aa386e..e05db388bd1c 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -131,6 +131,8 @@ extern void device_remove_groups(struct device *dev,
131extern char *make_class_name(const char *name, struct kobject *kobj); 131extern char *make_class_name(const char *name, struct kobject *kobj);
132 132
133extern int devres_release_all(struct device *dev); 133extern int devres_release_all(struct device *dev);
134extern void device_block_probing(void);
135extern void device_unblock_probing(void);
134 136
135/* /sys/devices directory */ 137/* /sys/devices directory */
136extern struct kset *devices_kset; 138extern struct kset *devices_kset;
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index a641cf3ccad6..b605f734b882 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -55,6 +55,13 @@ static struct workqueue_struct *deferred_wq;
55static atomic_t deferred_trigger_count = ATOMIC_INIT(0); 55static atomic_t deferred_trigger_count = ATOMIC_INIT(0);
56 56
57/* 57/*
58 * In some cases, like suspend to RAM or hibernation, It might be reasonable
59 * to prohibit probing of devices as it could be unsafe.
60 * Once defer_all_probes is true all drivers probes will be forcibly deferred.
61 */
62static bool defer_all_probes;
63
64/*
58 * deferred_probe_work_func() - Retry probing devices in the active list. 65 * deferred_probe_work_func() - Retry probing devices in the active list.
59 */ 66 */
60static void deferred_probe_work_func(struct work_struct *work) 67static void deferred_probe_work_func(struct work_struct *work)
@@ -172,6 +179,30 @@ static void driver_deferred_probe_trigger(void)
172} 179}
173 180
174/** 181/**
182 * device_block_probing() - Block/defere device's probes
183 *
184 * It will disable probing of devices and defer their probes instead.
185 */
186void device_block_probing(void)
187{
188 defer_all_probes = true;
189 /* sync with probes to avoid races. */
190 wait_for_device_probe();
191}
192
193/**
194 * device_unblock_probing() - Unblock/enable device's probes
195 *
196 * It will restore normal behavior and trigger re-probing of deferred
197 * devices.
198 */
199void device_unblock_probing(void)
200{
201 defer_all_probes = false;
202 driver_deferred_probe_trigger();
203}
204
205/**
175 * deferred_probe_initcall() - Enable probing of deferred devices 206 * deferred_probe_initcall() - Enable probing of deferred devices
176 * 207 *
177 * We don't want to get in the way when the bulk of drivers are getting probed. 208 * We don't want to get in the way when the bulk of drivers are getting probed.
@@ -277,9 +308,20 @@ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);
277 308
278static int really_probe(struct device *dev, struct device_driver *drv) 309static int really_probe(struct device *dev, struct device_driver *drv)
279{ 310{
280 int ret = 0; 311 int ret = -EPROBE_DEFER;
281 int local_trigger_count = atomic_read(&deferred_trigger_count); 312 int local_trigger_count = atomic_read(&deferred_trigger_count);
282 313
314 if (defer_all_probes) {
315 /*
316 * Value of defer_all_probes can be set only by
317 * device_defer_all_probes_enable() which, in turn, will call
318 * wait_for_device_probe() right after that to avoid any races.
319 */
320 dev_dbg(dev, "Driver %s force probe deferral\n", drv->name);
321 driver_deferred_probe_add(dev);
322 return ret;
323 }
324
283 atomic_inc(&probe_count); 325 atomic_inc(&probe_count);
284 pr_debug("bus: '%s': %s: probing driver %s with device %s\n", 326 pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
285 drv->bus->name, __func__, drv->name, dev_name(dev)); 327 drv->bus->name, __func__, drv->name, dev_name(dev));
@@ -393,6 +435,10 @@ int driver_probe_done(void)
393 */ 435 */
394void wait_for_device_probe(void) 436void wait_for_device_probe(void)
395{ 437{
438 /* wait for the deferred probe workqueue to finish */
439 if (driver_deferred_probe_enable)
440 flush_workqueue(deferred_wq);
441
396 /* wait for the known devices to complete their probing */ 442 /* wait for the known devices to complete their probing */
397 wait_event(probe_waitqueue, atomic_read(&probe_count) == 0); 443 wait_event(probe_waitqueue, atomic_read(&probe_count) == 0);
398 async_synchronize_full(); 444 async_synchronize_full();
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 1710c26ba097..9d626ac08d9c 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -963,6 +963,9 @@ void dpm_complete(pm_message_t state)
963 } 963 }
964 list_splice(&list, &dpm_list); 964 list_splice(&list, &dpm_list);
965 mutex_unlock(&dpm_list_mtx); 965 mutex_unlock(&dpm_list_mtx);
966
967 /* Allow device probing and trigger re-probing of deferred devices */
968 device_unblock_probing();
966 trace_suspend_resume(TPS("dpm_complete"), state.event, false); 969 trace_suspend_resume(TPS("dpm_complete"), state.event, false);
967} 970}
968 971
@@ -1624,6 +1627,20 @@ int dpm_prepare(pm_message_t state)
1624 trace_suspend_resume(TPS("dpm_prepare"), state.event, true); 1627 trace_suspend_resume(TPS("dpm_prepare"), state.event, true);
1625 might_sleep(); 1628 might_sleep();
1626 1629
1630 /*
1631 * Give a chance for the known devices to complete their probes, before
1632 * disable probing of devices. This sync point is important at least
1633 * at boot time + hibernation restore.
1634 */
1635 wait_for_device_probe();
1636 /*
1637 * It is unsafe if probing of devices will happen during suspend or
1638 * hibernation and system behavior will be unpredictable in this case.
1639 * So, let's prohibit device's probing here and defer their probes
1640 * instead. The normal behavior will be restored in dpm_complete().
1641 */
1642 device_block_probing();
1643
1627 mutex_lock(&dpm_list_mtx); 1644 mutex_lock(&dpm_list_mtx);
1628 while (!list_empty(&dpm_list)) { 1645 while (!list_empty(&dpm_list)) {
1629 struct device *dev = to_device(dpm_list.next); 1646 struct device *dev = to_device(dpm_list.next);