Messages in this thread Patch in this message |  | | From | Haojian Zhuang <> | Subject | [PATCH] driver core: add wait event for deferred probe | Date | Sun, 10 Feb 2013 00:57:57 +0800 |
| |
do_initcalls() could call all driver initialization code in kernel_init thread. It means that probe() function will be also called from that time. After this, kernel could access console & release __init section in the same thread.
But if device probe fails and moves into deferred probe list, a new thread is created to reinvoke probe. If the device is serial console, kernel has to open console failure & release __init section before reinvoking failure. Because there's no synchronization mechanism. Now add wait event to synchronize after do_initcalls().
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org> --- drivers/base/dd.c | 8 +++++--- init/main.c | 1 + 2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 65631015..23db672 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -53,6 +53,9 @@ static LIST_HEAD(deferred_probe_pending_list); static LIST_HEAD(deferred_probe_active_list); static struct workqueue_struct *deferred_wq; +static atomic_t probe_count = ATOMIC_INIT(0); +static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); + /** * deferred_probe_work_func() - Retry probing devices in the active list. */ @@ -77,6 +80,7 @@ static void deferred_probe_work_func(struct work_struct *work) private = list_first_entry(&deferred_probe_active_list, typeof(*dev->p), deferred_probe); dev = private->device; + atomic_dec(&probe_count); list_del_init(&private->deferred_probe); get_device(dev); @@ -257,9 +261,6 @@ int device_bind_driver(struct device *dev) } EXPORT_SYMBOL_GPL(device_bind_driver); -static atomic_t probe_count = ATOMIC_INIT(0); -static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); - static int really_probe(struct device *dev, struct device_driver *drv) { int ret = 0; @@ -308,6 +309,7 @@ probe_failed: /* Driver requested deferred probing */ dev_info(dev, "Driver %s requests probe deferral\n", drv->name); driver_deferred_probe_add(dev); + atomic_inc(&probe_count); } else if (ret != -ENODEV && ret != -ENXIO) { /* driver matched but the probe failed */ printk(KERN_WARNING diff --git a/init/main.c b/init/main.c index 63534a1..033bf5f 100644 --- a/init/main.c +++ b/init/main.c @@ -786,6 +786,7 @@ static void __init do_basic_setup(void) do_ctors(); usermodehelper_enable(); do_initcalls(); + wait_for_device_probe(); } static void __init do_pre_smp_initcalls(void) -- 1.7.10.4
|  |