diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/bus.c | 21 | ||||
-rw-r--r-- | drivers/base/dd.c | 8 | ||||
-rw-r--r-- | drivers/base/firmware_class.c | 15 | ||||
-rw-r--r-- | drivers/base/memory.c | 1 | ||||
-rw-r--r-- | drivers/base/platform.c | 73 |
5 files changed, 96 insertions, 22 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 03204bfd17a..fa601b085eb 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -133,7 +133,7 @@ static struct kobj_type ktype_bus = { decl_subsys(bus, &ktype_bus, NULL); -/* Manually detach a device from it's associated driver. */ +/* Manually detach a device from its associated driver. */ static int driver_helper(struct device *dev, void *data) { const char *name = data; @@ -151,14 +151,13 @@ static ssize_t driver_unbind(struct device_driver *drv, int err = -ENODEV; dev = bus_find_device(bus, NULL, (void *)buf, driver_helper); - if ((dev) && - (dev->driver == drv)) { + if (dev && dev->driver == drv) { device_release_driver(dev); err = count; } - if (err) - return err; - return count; + put_device(dev); + put_bus(bus); + return err; } static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind); @@ -175,16 +174,14 @@ static ssize_t driver_bind(struct device_driver *drv, int err = -ENODEV; dev = bus_find_device(bus, NULL, (void *)buf, driver_helper); - if ((dev) && - (dev->driver == NULL)) { + if (dev && dev->driver == NULL) { down(&dev->sem); err = driver_probe_device(drv, dev); up(&dev->sem); - put_device(dev); } - if (err) - return err; - return count; + put_device(dev); + put_bus(bus); + return err; } static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 3565e979530..3b419c9a1e7 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -62,7 +62,6 @@ void device_bind_driver(struct device * dev) * because we don't know the 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. * @@ -158,7 +157,6 @@ static int __driver_attach(struct device * dev, void * data) driver_probe_device(drv, dev); up(&dev->sem); - return 0; } @@ -225,15 +223,15 @@ void driver_detach(struct device_driver * drv) struct device * dev; for (;;) { - spin_lock_irq(&drv->klist_devices.k_lock); + spin_lock(&drv->klist_devices.k_lock); if (list_empty(&drv->klist_devices.k_list)) { - spin_unlock_irq(&drv->klist_devices.k_lock); + spin_unlock(&drv->klist_devices.k_lock); break; } dev = list_entry(drv->klist_devices.k_list.prev, struct device, knode_driver.n_node); get_device(dev); - spin_unlock_irq(&drv->klist_devices.k_lock); + spin_unlock(&drv->klist_devices.k_lock); down(&dev->sem); if (dev->driver == drv) diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 98f6c02d679..59dacb6552c 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -526,18 +526,23 @@ request_firmware_work_func(void *arg) { struct firmware_work *fw_work = arg; const struct firmware *fw; + int ret; if (!arg) { WARN_ON(1); return 0; } daemonize("%s/%s", "firmware", fw_work->name); - _request_firmware(&fw, fw_work->name, fw_work->device, + ret = _request_firmware(&fw, fw_work->name, fw_work->device, fw_work->hotplug); - fw_work->cont(fw, fw_work->context); - release_firmware(fw); + if (ret < 0) + fw_work->cont(NULL, fw_work->context); + else { + fw_work->cont(fw, fw_work->context); + release_firmware(fw); + } module_put(fw_work->module); kfree(fw_work); - return 0; + return ret; } /** @@ -586,6 +591,8 @@ request_firmware_nowait( if (ret < 0) { fw_work->cont(NULL, fw_work->context); + module_put(fw_work->module); + kfree(fw_work); return ret; } return 0; diff --git a/drivers/base/memory.c b/drivers/base/memory.c index b7ddd651d66..bc3ca6a656b 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -28,7 +28,6 @@ static struct sysdev_class memory_sysdev_class = { set_kset_name(MEMORY_CLASS_NAME), }; -EXPORT_SYMBOL(memory_sysdev_class); static char *memory_hotplug_name(struct kset *kset, struct kobject *kobj) { diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 6d4736e89f1..8827dafba94 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -20,6 +20,8 @@ #include "base.h" +#define to_platform_driver(drv) (container_of((drv), struct platform_driver, driver)) + struct device platform_bus = { .bus_id = "platform", }; @@ -354,6 +356,77 @@ error: return ERR_PTR(retval); } +static int platform_drv_probe(struct device *_dev) +{ + struct platform_driver *drv = to_platform_driver(_dev->driver); + struct platform_device *dev = to_platform_device(_dev); + + return drv->probe(dev); +} + +static int platform_drv_remove(struct device *_dev) +{ + struct platform_driver *drv = to_platform_driver(_dev->driver); + struct platform_device *dev = to_platform_device(_dev); + + return drv->remove(dev); +} + +static void platform_drv_shutdown(struct device *_dev) +{ + struct platform_driver *drv = to_platform_driver(_dev->driver); + struct platform_device *dev = to_platform_device(_dev); + + drv->shutdown(dev); +} + +static int platform_drv_suspend(struct device *_dev, pm_message_t state) +{ + struct platform_driver *drv = to_platform_driver(_dev->driver); + struct platform_device *dev = to_platform_device(_dev); + + return drv->suspend(dev, state); +} + +static int platform_drv_resume(struct device *_dev) +{ + struct platform_driver *drv = to_platform_driver(_dev->driver); + struct platform_device *dev = to_platform_device(_dev); + + return drv->resume(dev); +} + +/** + * platform_driver_register + * @drv: platform driver structure + */ +int platform_driver_register(struct platform_driver *drv) +{ + drv->driver.bus = &platform_bus_type; + if (drv->probe) + drv->driver.probe = platform_drv_probe; + if (drv->remove) + drv->driver.remove = platform_drv_remove; + if (drv->shutdown) + drv->driver.shutdown = platform_drv_shutdown; + if (drv->suspend) + drv->driver.suspend = platform_drv_suspend; + if (drv->resume) + drv->driver.resume = platform_drv_resume; + return driver_register(&drv->driver); +} +EXPORT_SYMBOL_GPL(platform_driver_register); + +/** + * platform_driver_unregister + * @drv: platform driver structure + */ +void platform_driver_unregister(struct platform_driver *drv) +{ + driver_unregister(&drv->driver); +} +EXPORT_SYMBOL_GPL(platform_driver_unregister); + /** * platform_match - bind platform device to platform driver. |