aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/dd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/dd.c')
-rw-r--r--drivers/base/dd.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index b5f43c3e44fa..c5d6bb4290ad 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -18,6 +18,7 @@
18#include <linux/device.h> 18#include <linux/device.h>
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/kthread.h> 20#include <linux/kthread.h>
21#include <linux/wait.h>
21 22
22#include "base.h" 23#include "base.h"
23#include "power/power.h" 24#include "power/power.h"
@@ -70,6 +71,8 @@ struct stupid_thread_structure {
70}; 71};
71 72
72static atomic_t probe_count = ATOMIC_INIT(0); 73static atomic_t probe_count = ATOMIC_INIT(0);
74static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);
75
73static int really_probe(void *void_data) 76static int really_probe(void *void_data)
74{ 77{
75 struct stupid_thread_structure *data = void_data; 78 struct stupid_thread_structure *data = void_data;
@@ -121,6 +124,7 @@ probe_failed:
121done: 124done:
122 kfree(data); 125 kfree(data);
123 atomic_dec(&probe_count); 126 atomic_dec(&probe_count);
127 wake_up(&probe_waitqueue);
124 return ret; 128 return ret;
125} 129}
126 130
@@ -171,6 +175,8 @@ int driver_probe_device(struct device_driver * drv, struct device * dev)
171 drv->bus->name, dev->bus_id, drv->name); 175 drv->bus->name, dev->bus_id, drv->name);
172 176
173 data = kmalloc(sizeof(*data), GFP_KERNEL); 177 data = kmalloc(sizeof(*data), GFP_KERNEL);
178 if (!data)
179 return -ENOMEM;
174 data->drv = drv; 180 data->drv = drv;
175 data->dev = dev; 181 data->dev = dev;
176 182
@@ -178,7 +184,7 @@ int driver_probe_device(struct device_driver * drv, struct device * dev)
178 probe_task = kthread_run(really_probe, data, 184 probe_task = kthread_run(really_probe, data,
179 "probe-%s", dev->bus_id); 185 "probe-%s", dev->bus_id);
180 if (IS_ERR(probe_task)) 186 if (IS_ERR(probe_task))
181 ret = PTR_ERR(probe_task); 187 ret = really_probe(data);
182 } else 188 } else
183 ret = really_probe(data); 189 ret = really_probe(data);
184 190
@@ -335,6 +341,32 @@ void driver_detach(struct device_driver * drv)
335 } 341 }
336} 342}
337 343
344#ifdef CONFIG_PCI_MULTITHREAD_PROBE
345static int __init wait_for_probes(void)
346{
347 DEFINE_WAIT(wait);
348
349 printk(KERN_INFO "%s: waiting for %d threads\n", __FUNCTION__,
350 atomic_read(&probe_count));
351 if (!atomic_read(&probe_count))
352 return 0;
353 while (atomic_read(&probe_count)) {
354 prepare_to_wait(&probe_waitqueue, &wait, TASK_UNINTERRUPTIBLE);
355 if (atomic_read(&probe_count))
356 schedule();
357 }
358 finish_wait(&probe_waitqueue, &wait);
359 return 0;
360}
361
362core_initcall_sync(wait_for_probes);
363postcore_initcall_sync(wait_for_probes);
364arch_initcall_sync(wait_for_probes);
365subsys_initcall_sync(wait_for_probes);
366fs_initcall_sync(wait_for_probes);
367device_initcall_sync(wait_for_probes);
368late_initcall_sync(wait_for_probes);
369#endif
338 370
339EXPORT_SYMBOL_GPL(device_bind_driver); 371EXPORT_SYMBOL_GPL(device_bind_driver);
340EXPORT_SYMBOL_GPL(device_release_driver); 372EXPORT_SYMBOL_GPL(device_release_driver);