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 03204bfd17af..fa601b085eba 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -133,7 +133,7 @@ static struct kobj_type ktype_bus = { | |||
133 | decl_subsys(bus, &ktype_bus, NULL); | 133 | decl_subsys(bus, &ktype_bus, NULL); |
134 | 134 | ||
135 | 135 | ||
136 | /* Manually detach a device from it's associated driver. */ | 136 | /* Manually detach a device from its associated driver. */ |
137 | static int driver_helper(struct device *dev, void *data) | 137 | static int driver_helper(struct device *dev, void *data) |
138 | { | 138 | { |
139 | const char *name = data; | 139 | const char *name = data; |
@@ -151,14 +151,13 @@ static ssize_t driver_unbind(struct device_driver *drv, | |||
151 | int err = -ENODEV; | 151 | int err = -ENODEV; |
152 | 152 | ||
153 | dev = bus_find_device(bus, NULL, (void *)buf, driver_helper); | 153 | dev = bus_find_device(bus, NULL, (void *)buf, driver_helper); |
154 | if ((dev) && | 154 | if (dev && dev->driver == drv) { |
155 | (dev->driver == drv)) { | ||
156 | device_release_driver(dev); | 155 | device_release_driver(dev); |
157 | err = count; | 156 | err = count; |
158 | } | 157 | } |
159 | if (err) | 158 | put_device(dev); |
160 | return err; | 159 | put_bus(bus); |
161 | return count; | 160 | return err; |
162 | } | 161 | } |
163 | static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind); | 162 | static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind); |
164 | 163 | ||
@@ -175,16 +174,14 @@ static ssize_t driver_bind(struct device_driver *drv, | |||
175 | int err = -ENODEV; | 174 | int err = -ENODEV; |
176 | 175 | ||
177 | dev = bus_find_device(bus, NULL, (void *)buf, driver_helper); | 176 | dev = bus_find_device(bus, NULL, (void *)buf, driver_helper); |
178 | if ((dev) && | 177 | if (dev && dev->driver == NULL) { |
179 | (dev->driver == NULL)) { | ||
180 | down(&dev->sem); | 178 | down(&dev->sem); |
181 | err = driver_probe_device(drv, dev); | 179 | err = driver_probe_device(drv, dev); |
182 | up(&dev->sem); | 180 | up(&dev->sem); |
183 | put_device(dev); | ||
184 | } | 181 | } |
185 | if (err) | 182 | put_device(dev); |
186 | return err; | 183 | put_bus(bus); |
187 | return count; | 184 | return err; |
188 | } | 185 | } |
189 | static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); | 186 | static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); |
190 | 187 | ||
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 3565e9795301..3b419c9a1e7e 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
@@ -62,7 +62,6 @@ void device_bind_driver(struct device * dev) | |||
62 | * because we don't know the format of the ID structures, nor what | 62 | * because we don't know the format of the ID structures, nor what |
63 | * is to be considered a match and what is not. | 63 | * is to be considered a match and what is not. |
64 | * | 64 | * |
65 | * | ||
66 | * This function returns 1 if a match is found, an error if one | 65 | * This function returns 1 if a match is found, an error if one |
67 | * occurs (that is not -ENODEV or -ENXIO), and 0 otherwise. | 66 | * occurs (that is not -ENODEV or -ENXIO), and 0 otherwise. |
68 | * | 67 | * |
@@ -158,7 +157,6 @@ static int __driver_attach(struct device * dev, void * data) | |||
158 | driver_probe_device(drv, dev); | 157 | driver_probe_device(drv, dev); |
159 | up(&dev->sem); | 158 | up(&dev->sem); |
160 | 159 | ||
161 | |||
162 | return 0; | 160 | return 0; |
163 | } | 161 | } |
164 | 162 | ||
@@ -225,15 +223,15 @@ void driver_detach(struct device_driver * drv) | |||
225 | struct device * dev; | 223 | struct device * dev; |
226 | 224 | ||
227 | for (;;) { | 225 | for (;;) { |
228 | spin_lock_irq(&drv->klist_devices.k_lock); | 226 | spin_lock(&drv->klist_devices.k_lock); |
229 | if (list_empty(&drv->klist_devices.k_list)) { | 227 | if (list_empty(&drv->klist_devices.k_list)) { |
230 | spin_unlock_irq(&drv->klist_devices.k_lock); | 228 | spin_unlock(&drv->klist_devices.k_lock); |
231 | break; | 229 | break; |
232 | } | 230 | } |
233 | dev = list_entry(drv->klist_devices.k_list.prev, | 231 | dev = list_entry(drv->klist_devices.k_list.prev, |
234 | struct device, knode_driver.n_node); | 232 | struct device, knode_driver.n_node); |
235 | get_device(dev); | 233 | get_device(dev); |
236 | spin_unlock_irq(&drv->klist_devices.k_lock); | 234 | spin_unlock(&drv->klist_devices.k_lock); |
237 | 235 | ||
238 | down(&dev->sem); | 236 | down(&dev->sem); |
239 | if (dev->driver == drv) | 237 | if (dev->driver == drv) |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 98f6c02d6790..59dacb6552c0 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -526,18 +526,23 @@ request_firmware_work_func(void *arg) | |||
526 | { | 526 | { |
527 | struct firmware_work *fw_work = arg; | 527 | struct firmware_work *fw_work = arg; |
528 | const struct firmware *fw; | 528 | const struct firmware *fw; |
529 | int ret; | ||
529 | if (!arg) { | 530 | if (!arg) { |
530 | WARN_ON(1); | 531 | WARN_ON(1); |
531 | return 0; | 532 | return 0; |
532 | } | 533 | } |
533 | daemonize("%s/%s", "firmware", fw_work->name); | 534 | daemonize("%s/%s", "firmware", fw_work->name); |
534 | _request_firmware(&fw, fw_work->name, fw_work->device, | 535 | ret = _request_firmware(&fw, fw_work->name, fw_work->device, |
535 | fw_work->hotplug); | 536 | fw_work->hotplug); |
536 | fw_work->cont(fw, fw_work->context); | 537 | if (ret < 0) |
537 | release_firmware(fw); | 538 | fw_work->cont(NULL, fw_work->context); |
539 | else { | ||
540 | fw_work->cont(fw, fw_work->context); | ||
541 | release_firmware(fw); | ||
542 | } | ||
538 | module_put(fw_work->module); | 543 | module_put(fw_work->module); |
539 | kfree(fw_work); | 544 | kfree(fw_work); |
540 | return 0; | 545 | return ret; |
541 | } | 546 | } |
542 | 547 | ||
543 | /** | 548 | /** |
@@ -586,6 +591,8 @@ request_firmware_nowait( | |||
586 | 591 | ||
587 | if (ret < 0) { | 592 | if (ret < 0) { |
588 | fw_work->cont(NULL, fw_work->context); | 593 | fw_work->cont(NULL, fw_work->context); |
594 | module_put(fw_work->module); | ||
595 | kfree(fw_work); | ||
589 | return ret; | 596 | return ret; |
590 | } | 597 | } |
591 | return 0; | 598 | return 0; |
diff --git a/drivers/base/memory.c b/drivers/base/memory.c index b7ddd651d664..bc3ca6a656b2 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c | |||
@@ -28,7 +28,6 @@ | |||
28 | static struct sysdev_class memory_sysdev_class = { | 28 | static struct sysdev_class memory_sysdev_class = { |
29 | set_kset_name(MEMORY_CLASS_NAME), | 29 | set_kset_name(MEMORY_CLASS_NAME), |
30 | }; | 30 | }; |
31 | EXPORT_SYMBOL(memory_sysdev_class); | ||
32 | 31 | ||
33 | static char *memory_hotplug_name(struct kset *kset, struct kobject *kobj) | 32 | static char *memory_hotplug_name(struct kset *kset, struct kobject *kobj) |
34 | { | 33 | { |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 6d4736e89f1a..8827dafba945 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -20,6 +20,8 @@ | |||
20 | 20 | ||
21 | #include "base.h" | 21 | #include "base.h" |
22 | 22 | ||
23 | #define to_platform_driver(drv) (container_of((drv), struct platform_driver, driver)) | ||
24 | |||
23 | struct device platform_bus = { | 25 | struct device platform_bus = { |
24 | .bus_id = "platform", | 26 | .bus_id = "platform", |
25 | }; | 27 | }; |
@@ -354,6 +356,77 @@ error: | |||
354 | return ERR_PTR(retval); | 356 | return ERR_PTR(retval); |
355 | } | 357 | } |
356 | 358 | ||
359 | static int platform_drv_probe(struct device *_dev) | ||
360 | { | ||
361 | struct platform_driver *drv = to_platform_driver(_dev->driver); | ||
362 | struct platform_device *dev = to_platform_device(_dev); | ||
363 | |||
364 | return drv->probe(dev); | ||
365 | } | ||
366 | |||
367 | static int platform_drv_remove(struct device *_dev) | ||
368 | { | ||
369 | struct platform_driver *drv = to_platform_driver(_dev->driver); | ||
370 | struct platform_device *dev = to_platform_device(_dev); | ||
371 | |||
372 | return drv->remove(dev); | ||
373 | } | ||
374 | |||
375 | static void platform_drv_shutdown(struct device *_dev) | ||
376 | { | ||
377 | struct platform_driver *drv = to_platform_driver(_dev->driver); | ||
378 | struct platform_device *dev = to_platform_device(_dev); | ||
379 | |||
380 | drv->shutdown(dev); | ||
381 | } | ||
382 | |||
383 | static int platform_drv_suspend(struct device *_dev, pm_message_t state) | ||
384 | { | ||
385 | struct platform_driver *drv = to_platform_driver(_dev->driver); | ||
386 | struct platform_device *dev = to_platform_device(_dev); | ||
387 | |||
388 | return drv->suspend(dev, state); | ||
389 | } | ||
390 | |||
391 | static int platform_drv_resume(struct device *_dev) | ||
392 | { | ||
393 | struct platform_driver *drv = to_platform_driver(_dev->driver); | ||
394 | struct platform_device *dev = to_platform_device(_dev); | ||
395 | |||
396 | return drv->resume(dev); | ||
397 | } | ||
398 | |||
399 | /** | ||
400 | * platform_driver_register | ||
401 | * @drv: platform driver structure | ||
402 | */ | ||
403 | int platform_driver_register(struct platform_driver *drv) | ||
404 | { | ||
405 | drv->driver.bus = &platform_bus_type; | ||
406 | if (drv->probe) | ||
407 | drv->driver.probe = platform_drv_probe; | ||
408 | if (drv->remove) | ||
409 | drv->driver.remove = platform_drv_remove; | ||
410 | if (drv->shutdown) | ||
411 | drv->driver.shutdown = platform_drv_shutdown; | ||
412 | if (drv->suspend) | ||
413 | drv->driver.suspend = platform_drv_suspend; | ||
414 | if (drv->resume) | ||
415 | drv->driver.resume = platform_drv_resume; | ||
416 | return driver_register(&drv->driver); | ||
417 | } | ||
418 | EXPORT_SYMBOL_GPL(platform_driver_register); | ||
419 | |||
420 | /** | ||
421 | * platform_driver_unregister | ||
422 | * @drv: platform driver structure | ||
423 | */ | ||
424 | void platform_driver_unregister(struct platform_driver *drv) | ||
425 | { | ||
426 | driver_unregister(&drv->driver); | ||
427 | } | ||
428 | EXPORT_SYMBOL_GPL(platform_driver_unregister); | ||
429 | |||
357 | 430 | ||
358 | /** | 431 | /** |
359 | * platform_match - bind platform device to platform driver. | 432 | * platform_match - bind platform device to platform driver. |