Skip to content

Commit 013c074

Browse files
grygoriySrafaeljw
authored andcommitted
PM / sleep: prohibit devices probing during suspend/hibernation
It is unsafe [1] if probing of devices will happen during suspend or hibernation and system behavior will be unpredictable in this case. So, let's prohibit device's probing in dpm_prepare() and defer their probing instead. The normal behavior will be restored in dpm_complete(). This patch introduces new DD core APIs: device_block_probing() It will disable probing of devices and defer their probes instead. device_unblock_probing() It will restore normal behavior and trigger re-probing of deferred devices. [1] https://lkml.org/lkml/2015/9/11/554 Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com> Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 31ade3b commit 013c074

File tree

3 files changed

+66
-1
lines changed

3 files changed

+66
-1
lines changed

drivers/base/base.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ extern void device_remove_groups(struct device *dev,
131131
extern char *make_class_name(const char *name, struct kobject *kobj);
132132

133133
extern int devres_release_all(struct device *dev);
134+
extern void device_block_probing(void);
135+
extern void device_unblock_probing(void);
134136

135137
/* /sys/devices directory */
136138
extern struct kset *devices_kset;

drivers/base/dd.c

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ static LIST_HEAD(deferred_probe_active_list);
5454
static struct workqueue_struct *deferred_wq;
5555
static atomic_t deferred_trigger_count = ATOMIC_INIT(0);
5656

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+
*/
62+
static bool defer_all_probes;
63+
5764
/*
5865
* deferred_probe_work_func() - Retry probing devices in the active list.
5966
*/
@@ -171,6 +178,30 @@ static void driver_deferred_probe_trigger(void)
171178
queue_work(deferred_wq, &deferred_probe_work);
172179
}
173180

181+
/**
182+
* device_block_probing() - Block/defere device's probes
183+
*
184+
* It will disable probing of devices and defer their probes instead.
185+
*/
186+
void 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+
*/
199+
void device_unblock_probing(void)
200+
{
201+
defer_all_probes = false;
202+
driver_deferred_probe_trigger();
203+
}
204+
174205
/**
175206
* deferred_probe_initcall() - Enable probing of deferred devices
176207
*
@@ -277,9 +308,20 @@ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);
277308

278309
static int really_probe(struct device *dev, struct device_driver *drv)
279310
{
280-
int ret = 0;
311+
int ret = -EPROBE_DEFER;
281312
int local_trigger_count = atomic_read(&deferred_trigger_count);
282313

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+
283325
atomic_inc(&probe_count);
284326
pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
285327
drv->bus->name, __func__, drv->name, dev_name(dev));
@@ -393,6 +435,10 @@ int driver_probe_done(void)
393435
*/
394436
void wait_for_device_probe(void)
395437
{
438+
/* wait for the deferred probe workqueue to finish */
439+
if (driver_deferred_probe_enable)
440+
flush_workqueue(deferred_wq);
441+
396442
/* wait for the known devices to complete their probing */
397443
wait_event(probe_waitqueue, atomic_read(&probe_count) == 0);
398444
async_synchronize_full();

drivers/base/power/main.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,9 @@ void dpm_complete(pm_message_t state)
963963
}
964964
list_splice(&list, &dpm_list);
965965
mutex_unlock(&dpm_list_mtx);
966+
967+
/* Allow device probing and trigger re-probing of deferred devices */
968+
device_unblock_probing();
966969
trace_suspend_resume(TPS("dpm_complete"), state.event, false);
967970
}
968971

@@ -1624,6 +1627,20 @@ int dpm_prepare(pm_message_t state)
16241627
trace_suspend_resume(TPS("dpm_prepare"), state.event, true);
16251628
might_sleep();
16261629

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+
16271644
mutex_lock(&dpm_list_mtx);
16281645
while (!list_empty(&dpm_list)) {
16291646
struct device *dev = to_device(dpm_list.next);

0 commit comments

Comments
 (0)