diff options
| -rw-r--r-- | drivers/base/base.h | 2 | ||||
| -rw-r--r-- | drivers/base/dd.c | 48 | ||||
| -rw-r--r-- | drivers/base/power/main.c | 17 |
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, | |||
| 131 | extern char *make_class_name(const char *name, struct kobject *kobj); | 131 | extern char *make_class_name(const char *name, struct kobject *kobj); |
| 132 | 132 | ||
| 133 | extern int devres_release_all(struct device *dev); | 133 | extern int devres_release_all(struct device *dev); |
| 134 | extern void device_block_probing(void); | ||
| 135 | extern void device_unblock_probing(void); | ||
| 134 | 136 | ||
| 135 | /* /sys/devices directory */ | 137 | /* /sys/devices directory */ |
| 136 | extern struct kset *devices_kset; | 138 | extern 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; | |||
| 55 | static atomic_t deferred_trigger_count = ATOMIC_INIT(0); | 55 | static 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 | */ | ||
| 62 | static 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 | */ |
| 60 | static void deferred_probe_work_func(struct work_struct *work) | 67 | static 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 | */ | ||
| 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 | |||
| 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 | ||
| 278 | static int really_probe(struct device *dev, struct device_driver *drv) | 309 | static 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 | */ |
| 394 | void wait_for_device_probe(void) | 436 | void 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); |
