X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=drivers%2Fbase%2Fdd.c;h=92428e55b0c210a8c00cf8e656a934fa9e21f2d3;hb=7dfe50b3aac2b3500139ab10a6e228d34fed9a49;hp=510e7884975f9f4a4571dd5038ef4b7dbb090f80;hpb=9cdf083f981b8d37b3212400a359368661385099;p=powerpc.git diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 510e788497..92428e55b0 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -86,28 +86,25 @@ static void driver_sysfs_remove(struct device *dev) */ int device_bind_driver(struct device *dev) { - driver_bound(dev); - return driver_sysfs_add(dev); -} + int ret; -struct stupid_thread_structure { - struct device_driver *drv; - struct device *dev; -}; + ret = driver_sysfs_add(dev); + if (!ret) + driver_bound(dev); + return ret; +} static atomic_t probe_count = ATOMIC_INIT(0); static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); -static int really_probe(void *void_data) +static int really_probe(struct device *dev, struct device_driver *drv) { - struct stupid_thread_structure *data = void_data; - struct device_driver *drv = data->drv; - struct device *dev = data->dev; int ret = 0; atomic_inc(&probe_count); pr_debug("%s: Probing driver %s with device %s\n", drv->bus->name, drv->name, dev->bus_id); + WARN_ON(!list_empty(&dev->devres_head)); dev->driver = drv; if (driver_sysfs_add(dev)) { @@ -133,23 +130,22 @@ static int really_probe(void *void_data) goto done; probe_failed: + devres_release_all(dev); driver_sysfs_remove(dev); dev->driver = NULL; - if (ret == -ENODEV || ret == -ENXIO) { - /* Driver matched, but didn't support device - * or device not found. - * Not an error; keep going. - */ - ret = 0; - } else { + if (ret != -ENODEV && ret != -ENXIO) { /* driver matched but the probe failed */ printk(KERN_WARNING "%s: probe of %s failed with error %d\n", drv->name, dev->bus_id, ret); } + /* + * Ignore errors returned by ->probe so that the next driver can try + * its luck. + */ + ret = 0; done: - kfree(data); atomic_dec(&probe_count); wake_up(&probe_waitqueue); return ret; @@ -181,16 +177,14 @@ int driver_probe_done(void) * format of the ID structures, nor what is to be considered a match and * what is not. * - * This function returns 1 if a match is found, an error if one occurs - * (that is not -ENODEV or -ENXIO), and 0 otherwise. + * This function returns 1 if a match is found, -ENODEV if the device is + * not registered, and 0 otherwise. * * This function must be called with @dev->sem held. When called for a * USB interface, @dev->parent->sem must be held as well. */ int driver_probe_device(struct device_driver * drv, struct device * dev) { - struct stupid_thread_structure *data; - struct task_struct *probe_task; int ret = 0; if (!device_is_registered(dev)) @@ -201,19 +195,7 @@ int driver_probe_device(struct device_driver * drv, struct device * dev) pr_debug("%s: Matched Device %s with Driver %s\n", drv->bus->name, dev->bus_id, drv->name); - data = kmalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - data->drv = drv; - data->dev = dev; - - if (drv->multithread_probe) { - probe_task = kthread_run(really_probe, data, - "probe-%s", dev->bus_id); - if (IS_ERR(probe_task)) - ret = really_probe(data); - } else - ret = really_probe(data); + ret = really_probe(dev, drv); done: return ret; @@ -225,6 +207,19 @@ static int __device_attach(struct device_driver * drv, void * data) return driver_probe_device(drv, dev); } +static int device_probe_drivers(void *data) +{ + struct device *dev = data; + int ret = 0; + + if (dev->bus) { + down(&dev->sem); + ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); + up(&dev->sem); + } + return ret; +} + /** * device_attach - try to attach device to a driver. * @dev: device. @@ -234,7 +229,8 @@ static int __device_attach(struct device_driver * drv, void * data) * pair is found, break out and return. * * Returns 1 if the device was bound to a driver; - * 0 if no matching device was found; error code otherwise. + * 0 if no matching device was found; + * -ENODEV if the device is not registered. * * When called for a USB interface, @dev->parent->sem must be held. */ @@ -247,8 +243,13 @@ int device_attach(struct device * dev) ret = device_bind_driver(dev); if (ret == 0) ret = 1; - } else + else { + dev->driver = NULL; + ret = 0; + } + } else { ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); + } up(&dev->sem); return ret; } @@ -324,6 +325,7 @@ static void __device_release_driver(struct device * dev) dev->bus->remove(dev); else if (drv->remove) drv->remove(dev); + devres_release_all(dev); dev->driver = NULL; put_driver(drv); } @@ -373,33 +375,6 @@ void driver_detach(struct device_driver * drv) } } -#ifdef CONFIG_PCI_MULTITHREAD_PROBE -static int __init wait_for_probes(void) -{ - DEFINE_WAIT(wait); - - printk(KERN_INFO "%s: waiting for %d threads\n", __FUNCTION__, - atomic_read(&probe_count)); - if (!atomic_read(&probe_count)) - return 0; - while (atomic_read(&probe_count)) { - prepare_to_wait(&probe_waitqueue, &wait, TASK_UNINTERRUPTIBLE); - if (atomic_read(&probe_count)) - schedule(); - } - finish_wait(&probe_waitqueue, &wait); - return 0; -} - -core_initcall_sync(wait_for_probes); -postcore_initcall_sync(wait_for_probes); -arch_initcall_sync(wait_for_probes); -subsys_initcall_sync(wait_for_probes); -fs_initcall_sync(wait_for_probes); -device_initcall_sync(wait_for_probes); -late_initcall_sync(wait_for_probes); -#endif - EXPORT_SYMBOL_GPL(device_bind_driver); EXPORT_SYMBOL_GPL(device_release_driver); EXPORT_SYMBOL_GPL(device_attach);