|
|
|
@ -54,6 +54,13 @@ static LIST_HEAD(deferred_probe_active_list); |
|
|
|
|
static struct workqueue_struct *deferred_wq; |
|
|
|
|
static atomic_t deferred_trigger_count = ATOMIC_INIT(0); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* In some cases, like suspend to RAM or hibernation, It might be reasonable |
|
|
|
|
* to prohibit probing of devices as it could be unsafe. |
|
|
|
|
* Once defer_all_probes is true all drivers probes will be forcibly deferred. |
|
|
|
|
*/ |
|
|
|
|
static bool defer_all_probes; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* deferred_probe_work_func() - Retry probing devices in the active list. |
|
|
|
|
*/ |
|
|
|
@ -171,6 +178,30 @@ static void driver_deferred_probe_trigger(void) |
|
|
|
|
queue_work(deferred_wq, &deferred_probe_work); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* device_block_probing() - Block/defere device's probes |
|
|
|
|
* |
|
|
|
|
* It will disable probing of devices and defer their probes instead. |
|
|
|
|
*/ |
|
|
|
|
void device_block_probing(void) |
|
|
|
|
{ |
|
|
|
|
defer_all_probes = true; |
|
|
|
|
/* sync with probes to avoid races. */ |
|
|
|
|
wait_for_device_probe(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* device_unblock_probing() - Unblock/enable device's probes |
|
|
|
|
* |
|
|
|
|
* It will restore normal behavior and trigger re-probing of deferred |
|
|
|
|
* devices. |
|
|
|
|
*/ |
|
|
|
|
void device_unblock_probing(void) |
|
|
|
|
{ |
|
|
|
|
defer_all_probes = false; |
|
|
|
|
driver_deferred_probe_trigger(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* deferred_probe_initcall() - Enable probing of deferred devices |
|
|
|
|
* |
|
|
|
@ -280,9 +311,20 @@ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); |
|
|
|
|
|
|
|
|
|
static int really_probe(struct device *dev, struct device_driver *drv) |
|
|
|
|
{ |
|
|
|
|
int ret = 0; |
|
|
|
|
int ret = -EPROBE_DEFER; |
|
|
|
|
int local_trigger_count = atomic_read(&deferred_trigger_count); |
|
|
|
|
|
|
|
|
|
if (defer_all_probes) { |
|
|
|
|
/*
|
|
|
|
|
* Value of defer_all_probes can be set only by |
|
|
|
|
* device_defer_all_probes_enable() which, in turn, will call |
|
|
|
|
* wait_for_device_probe() right after that to avoid any races. |
|
|
|
|
*/ |
|
|
|
|
dev_dbg(dev, "Driver %s force probe deferral\n", drv->name); |
|
|
|
|
driver_deferred_probe_add(dev); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
atomic_inc(&probe_count); |
|
|
|
|
pr_debug("bus: '%s': %s: probing driver %s with device %s\n", |
|
|
|
|
drv->bus->name, __func__, drv->name, dev_name(dev)); |
|
|
|
@ -347,6 +389,7 @@ pinctrl_bind_failed: |
|
|
|
|
dev_set_drvdata(dev, NULL); |
|
|
|
|
if (dev->pm_domain && dev->pm_domain->dismiss) |
|
|
|
|
dev->pm_domain->dismiss(dev); |
|
|
|
|
pm_runtime_reinit(dev); |
|
|
|
|
|
|
|
|
|
switch (ret) { |
|
|
|
|
case -EPROBE_DEFER: |
|
|
|
@ -400,6 +443,10 @@ int driver_probe_done(void) |
|
|
|
|
*/ |
|
|
|
|
void wait_for_device_probe(void) |
|
|
|
|
{ |
|
|
|
|
/* wait for the deferred probe workqueue to finish */ |
|
|
|
|
if (driver_deferred_probe_enable) |
|
|
|
|
flush_workqueue(deferred_wq); |
|
|
|
|
|
|
|
|
|
/* wait for the known devices to complete their probing */ |
|
|
|
|
wait_event(probe_waitqueue, atomic_read(&probe_count) == 0); |
|
|
|
|
async_synchronize_full(); |
|
|
|
@ -702,6 +749,7 @@ static void __device_release_driver(struct device *dev) |
|
|
|
|
dev_set_drvdata(dev, NULL); |
|
|
|
|
if (dev->pm_domain && dev->pm_domain->dismiss) |
|
|
|
|
dev->pm_domain->dismiss(dev); |
|
|
|
|
pm_runtime_reinit(dev); |
|
|
|
|
|
|
|
|
|
klist_remove(&dev->p->knode_driver); |
|
|
|
|
if (dev->bus) |
|
|
|
|