aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/dd.c62
-rw-r--r--drivers/pci/pci-driver.c6
-rw-r--r--include/linux/device.h3
-rw-r--r--include/linux/pci.h2
4 files changed, 33 insertions, 40 deletions
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 6a48824e43ff..616b4bbacf1b 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -94,19 +94,11 @@ int device_bind_driver(struct device *dev)
94 return ret; 94 return ret;
95} 95}
96 96
97struct stupid_thread_structure {
98 struct device_driver *drv;
99 struct device *dev;
100};
101
102static atomic_t probe_count = ATOMIC_INIT(0); 97static atomic_t probe_count = ATOMIC_INIT(0);
103static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); 98static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);
104 99
105static int really_probe(void *void_data) 100static int really_probe(struct device *dev, struct device_driver *drv)
106{ 101{
107 struct stupid_thread_structure *data = void_data;
108 struct device_driver *drv = data->drv;
109 struct device *dev = data->dev;
110 int ret = 0; 102 int ret = 0;
111 103
112 atomic_inc(&probe_count); 104 atomic_inc(&probe_count);
@@ -154,7 +146,6 @@ probe_failed:
154 */ 146 */
155 ret = 0; 147 ret = 0;
156done: 148done:
157 kfree(data);
158 atomic_dec(&probe_count); 149 atomic_dec(&probe_count);
159 wake_up(&probe_waitqueue); 150 wake_up(&probe_waitqueue);
160 return ret; 151 return ret;
@@ -186,16 +177,14 @@ int driver_probe_done(void)
186 * format of the ID structures, nor what is to be considered a match and 177 * format of the ID structures, nor what is to be considered a match and
187 * what is not. 178 * what is not.
188 * 179 *
189 * This function returns 1 if a match is found, an error if one occurs 180 * This function returns 1 if a match is found, -ENODEV if the device is
190 * (that is not -ENODEV or -ENXIO), and 0 otherwise. 181 * not registered, and 0 otherwise.
191 * 182 *
192 * This function must be called with @dev->sem held. When called for a 183 * This function must be called with @dev->sem held. When called for a
193 * USB interface, @dev->parent->sem must be held as well. 184 * USB interface, @dev->parent->sem must be held as well.
194 */ 185 */
195int driver_probe_device(struct device_driver * drv, struct device * dev) 186int driver_probe_device(struct device_driver * drv, struct device * dev)
196{ 187{
197 struct stupid_thread_structure *data;
198 struct task_struct *probe_task;
199 int ret = 0; 188 int ret = 0;
200 189
201 if (!device_is_registered(dev)) 190 if (!device_is_registered(dev))
@@ -206,19 +195,7 @@ int driver_probe_device(struct device_driver * drv, struct device * dev)
206 pr_debug("%s: Matched Device %s with Driver %s\n", 195 pr_debug("%s: Matched Device %s with Driver %s\n",
207 drv->bus->name, dev->bus_id, drv->name); 196 drv->bus->name, dev->bus_id, drv->name);
208 197
209 data = kmalloc(sizeof(*data), GFP_KERNEL); 198 ret = really_probe(dev, drv);
210 if (!data)
211 return -ENOMEM;
212 data->drv = drv;
213 data->dev = dev;
214
215 if (drv->multithread_probe) {
216 probe_task = kthread_run(really_probe, data,
217 "probe-%s", dev->bus_id);
218 if (IS_ERR(probe_task))
219 ret = really_probe(data);
220 } else
221 ret = really_probe(data);
222 199
223done: 200done:
224 return ret; 201 return ret;
@@ -230,30 +207,53 @@ static int __device_attach(struct device_driver * drv, void * data)
230 return driver_probe_device(drv, dev); 207 return driver_probe_device(drv, dev);
231} 208}
232 209
210static int device_probe_drivers(void *data)
211{
212 struct device *dev = data;
213 int ret = 0;
214
215 if (dev->bus) {
216 down(&dev->sem);
217 ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
218 up(&dev->sem);
219 }
220 return ret;
221}
222
233/** 223/**
234 * device_attach - try to attach device to a driver. 224 * device_attach - try to attach device to a driver.
235 * @dev: device. 225 * @dev: device.
236 * 226 *
237 * Walk the list of drivers that the bus has and call 227 * Walk the list of drivers that the bus has and call
238 * driver_probe_device() for each pair. If a compatible 228 * driver_probe_device() for each pair. If a compatible
239 * pair is found, break out and return. 229 * pair is found, break out and return. If the bus specifies
230 * multithreaded probing, walking the list of drivers is done
231 * on a probing thread.
240 * 232 *
241 * Returns 1 if the device was bound to a driver; 233 * Returns 1 if the device was bound to a driver;
242 * 0 if no matching device was found; error code otherwise. 234 * 0 if no matching device was found or multithreaded probing is done;
235 * error code otherwise.
243 * 236 *
244 * When called for a USB interface, @dev->parent->sem must be held. 237 * When called for a USB interface, @dev->parent->sem must be held.
245 */ 238 */
246int device_attach(struct device * dev) 239int device_attach(struct device * dev)
247{ 240{
248 int ret = 0; 241 int ret = 0;
242 struct task_struct *probe_task = ERR_PTR(-ENOMEM);
249 243
250 down(&dev->sem); 244 down(&dev->sem);
251 if (dev->driver) { 245 if (dev->driver) {
252 ret = device_bind_driver(dev); 246 ret = device_bind_driver(dev);
253 if (ret == 0) 247 if (ret == 0)
254 ret = 1; 248 ret = 1;
255 } else 249 } else {
256 ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); 250 if (dev->bus->multithread_probe)
251 probe_task = kthread_run(device_probe_drivers, dev,
252 "probe-%s", dev->bus_id);
253 if(IS_ERR(probe_task))
254 ret = bus_for_each_drv(dev->bus, NULL, dev,
255 __device_attach);
256 }
257 up(&dev->sem); 257 up(&dev->sem);
258 return ret; 258 return ret;
259} 259}
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index a3c1755b2f28..39e80fcef4b3 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -434,11 +434,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner,
434 drv->driver.mod_name = mod_name; 434 drv->driver.mod_name = mod_name;
435 drv->driver.kobj.ktype = &pci_driver_kobj_type; 435 drv->driver.kobj.ktype = &pci_driver_kobj_type;
436 436
437 if (pci_multithread_probe)
438 drv->driver.multithread_probe = pci_multithread_probe;
439 else
440 drv->driver.multithread_probe = drv->multithread_probe;
441
442 spin_lock_init(&drv->dynids.lock); 437 spin_lock_init(&drv->dynids.lock);
443 INIT_LIST_HEAD(&drv->dynids.list); 438 INIT_LIST_HEAD(&drv->dynids.list);
444 439
@@ -574,6 +569,7 @@ struct bus_type pci_bus_type = {
574 569
575static int __init pci_driver_init(void) 570static int __init pci_driver_init(void)
576{ 571{
572 pci_bus_type.multithread_probe = pci_multithread_probe;
577 return bus_register(&pci_bus_type); 573 return bus_register(&pci_bus_type);
578} 574}
579 575
diff --git a/include/linux/device.h b/include/linux/device.h
index 7f63d4de5c4d..eb1fff0b1d2a 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -80,6 +80,7 @@ struct bus_type {
80 int (*resume)(struct device * dev); 80 int (*resume)(struct device * dev);
81 81
82 unsigned int drivers_autoprobe:1; 82 unsigned int drivers_autoprobe:1;
83 unsigned int multithread_probe:1;
83}; 84};
84 85
85extern int __must_check bus_register(struct bus_type * bus); 86extern int __must_check bus_register(struct bus_type * bus);
@@ -139,8 +140,6 @@ struct device_driver {
139 void (*shutdown) (struct device * dev); 140 void (*shutdown) (struct device * dev);
140 int (*suspend) (struct device * dev, pm_message_t state); 141 int (*suspend) (struct device * dev, pm_message_t state);
141 int (*resume) (struct device * dev); 142 int (*resume) (struct device * dev);
142
143 unsigned int multithread_probe:1;
144}; 143};
145 144
146 145
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 481ea0663f19..a3ad76221c6f 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -361,8 +361,6 @@ struct pci_driver {
361 struct pci_error_handlers *err_handler; 361 struct pci_error_handlers *err_handler;
362 struct device_driver driver; 362 struct device_driver driver;
363 struct pci_dynids dynids; 363 struct pci_dynids dynids;
364
365 int multithread_probe;
366}; 364};
367 365
368#define to_pci_driver(drv) container_of(drv,struct pci_driver, driver) 366#define to_pci_driver(drv) container_of(drv,struct pci_driver, driver)