diff options
| author | Jeff Garzik <jgarzik@pobox.com> | 2005-09-08 05:37:58 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-08 05:37:58 -0400 |
| commit | 5a2cec83a9bb1b4295aa8ab728fcb8ca1811a33c (patch) | |
| tree | 2f83dc6949763e77cf6422e696dc6146684dcf4e /drivers/base | |
| parent | f2c853bca542f5ac0b036377637192a74f2091c2 (diff) | |
| parent | caf39e87cc1182f7dae84eefc43ca14d54c78ef9 (diff) | |
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'drivers/base')
| -rw-r--r-- | drivers/base/attribute_container.c | 86 | ||||
| -rw-r--r-- | drivers/base/bus.c | 34 | ||||
| -rw-r--r-- | drivers/base/core.c | 17 | ||||
| -rw-r--r-- | drivers/base/driver.c | 15 | ||||
| -rw-r--r-- | drivers/base/firmware_class.c | 79 | ||||
| -rw-r--r-- | drivers/base/transport_class.c | 19 |
6 files changed, 200 insertions, 50 deletions
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c index ec615d854be9..373e7b728fa7 100644 --- a/drivers/base/attribute_container.c +++ b/drivers/base/attribute_container.c | |||
| @@ -22,11 +22,26 @@ | |||
| 22 | /* This is a private structure used to tie the classdev and the | 22 | /* This is a private structure used to tie the classdev and the |
| 23 | * container .. it should never be visible outside this file */ | 23 | * container .. it should never be visible outside this file */ |
| 24 | struct internal_container { | 24 | struct internal_container { |
| 25 | struct list_head node; | 25 | struct klist_node node; |
| 26 | struct attribute_container *cont; | 26 | struct attribute_container *cont; |
| 27 | struct class_device classdev; | 27 | struct class_device classdev; |
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | static void internal_container_klist_get(struct klist_node *n) | ||
| 31 | { | ||
| 32 | struct internal_container *ic = | ||
| 33 | container_of(n, struct internal_container, node); | ||
| 34 | class_device_get(&ic->classdev); | ||
| 35 | } | ||
| 36 | |||
| 37 | static void internal_container_klist_put(struct klist_node *n) | ||
| 38 | { | ||
| 39 | struct internal_container *ic = | ||
| 40 | container_of(n, struct internal_container, node); | ||
| 41 | class_device_put(&ic->classdev); | ||
| 42 | } | ||
| 43 | |||
| 44 | |||
| 30 | /** | 45 | /** |
| 31 | * attribute_container_classdev_to_container - given a classdev, return the container | 46 | * attribute_container_classdev_to_container - given a classdev, return the container |
| 32 | * | 47 | * |
| @@ -57,7 +72,8 @@ int | |||
| 57 | attribute_container_register(struct attribute_container *cont) | 72 | attribute_container_register(struct attribute_container *cont) |
| 58 | { | 73 | { |
| 59 | INIT_LIST_HEAD(&cont->node); | 74 | INIT_LIST_HEAD(&cont->node); |
| 60 | INIT_LIST_HEAD(&cont->containers); | 75 | klist_init(&cont->containers,internal_container_klist_get, |
| 76 | internal_container_klist_put); | ||
| 61 | 77 | ||
| 62 | down(&attribute_container_mutex); | 78 | down(&attribute_container_mutex); |
| 63 | list_add_tail(&cont->node, &attribute_container_list); | 79 | list_add_tail(&cont->node, &attribute_container_list); |
| @@ -77,11 +93,13 @@ attribute_container_unregister(struct attribute_container *cont) | |||
| 77 | { | 93 | { |
| 78 | int retval = -EBUSY; | 94 | int retval = -EBUSY; |
| 79 | down(&attribute_container_mutex); | 95 | down(&attribute_container_mutex); |
| 80 | if (!list_empty(&cont->containers)) | 96 | spin_lock(&cont->containers.k_lock); |
| 97 | if (!list_empty(&cont->containers.k_list)) | ||
| 81 | goto out; | 98 | goto out; |
| 82 | retval = 0; | 99 | retval = 0; |
| 83 | list_del(&cont->node); | 100 | list_del(&cont->node); |
| 84 | out: | 101 | out: |
| 102 | spin_unlock(&cont->containers.k_lock); | ||
| 85 | up(&attribute_container_mutex); | 103 | up(&attribute_container_mutex); |
| 86 | return retval; | 104 | return retval; |
| 87 | 105 | ||
| @@ -140,7 +158,6 @@ attribute_container_add_device(struct device *dev, | |||
| 140 | continue; | 158 | continue; |
| 141 | } | 159 | } |
| 142 | memset(ic, 0, sizeof(struct internal_container)); | 160 | memset(ic, 0, sizeof(struct internal_container)); |
| 143 | INIT_LIST_HEAD(&ic->node); | ||
| 144 | ic->cont = cont; | 161 | ic->cont = cont; |
| 145 | class_device_initialize(&ic->classdev); | 162 | class_device_initialize(&ic->classdev); |
| 146 | ic->classdev.dev = get_device(dev); | 163 | ic->classdev.dev = get_device(dev); |
| @@ -151,11 +168,22 @@ attribute_container_add_device(struct device *dev, | |||
| 151 | fn(cont, dev, &ic->classdev); | 168 | fn(cont, dev, &ic->classdev); |
| 152 | else | 169 | else |
| 153 | attribute_container_add_class_device(&ic->classdev); | 170 | attribute_container_add_class_device(&ic->classdev); |
| 154 | list_add_tail(&ic->node, &cont->containers); | 171 | klist_add_tail(&ic->node, &cont->containers); |
| 155 | } | 172 | } |
| 156 | up(&attribute_container_mutex); | 173 | up(&attribute_container_mutex); |
| 157 | } | 174 | } |
| 158 | 175 | ||
| 176 | /* FIXME: can't break out of this unless klist_iter_exit is also | ||
| 177 | * called before doing the break | ||
| 178 | */ | ||
| 179 | #define klist_for_each_entry(pos, head, member, iter) \ | ||
| 180 | for (klist_iter_init(head, iter); (pos = ({ \ | ||
| 181 | struct klist_node *n = klist_next(iter); \ | ||
| 182 | n ? container_of(n, typeof(*pos), member) : \ | ||
| 183 | ({ klist_iter_exit(iter) ; NULL; }); \ | ||
| 184 | }) ) != NULL; ) | ||
| 185 | |||
| 186 | |||
| 159 | /** | 187 | /** |
| 160 | * attribute_container_remove_device - make device eligible for removal. | 188 | * attribute_container_remove_device - make device eligible for removal. |
| 161 | * | 189 | * |
| @@ -182,17 +210,19 @@ attribute_container_remove_device(struct device *dev, | |||
| 182 | 210 | ||
| 183 | down(&attribute_container_mutex); | 211 | down(&attribute_container_mutex); |
| 184 | list_for_each_entry(cont, &attribute_container_list, node) { | 212 | list_for_each_entry(cont, &attribute_container_list, node) { |
| 185 | struct internal_container *ic, *tmp; | 213 | struct internal_container *ic; |
| 214 | struct klist_iter iter; | ||
| 186 | 215 | ||
| 187 | if (attribute_container_no_classdevs(cont)) | 216 | if (attribute_container_no_classdevs(cont)) |
| 188 | continue; | 217 | continue; |
| 189 | 218 | ||
| 190 | if (!cont->match(cont, dev)) | 219 | if (!cont->match(cont, dev)) |
| 191 | continue; | 220 | continue; |
| 192 | list_for_each_entry_safe(ic, tmp, &cont->containers, node) { | 221 | |
| 222 | klist_for_each_entry(ic, &cont->containers, node, &iter) { | ||
| 193 | if (dev != ic->classdev.dev) | 223 | if (dev != ic->classdev.dev) |
| 194 | continue; | 224 | continue; |
| 195 | list_del(&ic->node); | 225 | klist_del(&ic->node); |
| 196 | if (fn) | 226 | if (fn) |
| 197 | fn(cont, dev, &ic->classdev); | 227 | fn(cont, dev, &ic->classdev); |
| 198 | else { | 228 | else { |
| @@ -225,12 +255,18 @@ attribute_container_device_trigger(struct device *dev, | |||
| 225 | 255 | ||
| 226 | down(&attribute_container_mutex); | 256 | down(&attribute_container_mutex); |
| 227 | list_for_each_entry(cont, &attribute_container_list, node) { | 257 | list_for_each_entry(cont, &attribute_container_list, node) { |
| 228 | struct internal_container *ic, *tmp; | 258 | struct internal_container *ic; |
| 259 | struct klist_iter iter; | ||
| 229 | 260 | ||
| 230 | if (!cont->match(cont, dev)) | 261 | if (!cont->match(cont, dev)) |
| 231 | continue; | 262 | continue; |
| 232 | 263 | ||
| 233 | list_for_each_entry_safe(ic, tmp, &cont->containers, node) { | 264 | if (attribute_container_no_classdevs(cont)) { |
| 265 | fn(cont, dev, NULL); | ||
| 266 | continue; | ||
| 267 | } | ||
| 268 | |||
| 269 | klist_for_each_entry(ic, &cont->containers, node, &iter) { | ||
| 234 | if (dev == ic->classdev.dev) | 270 | if (dev == ic->classdev.dev) |
| 235 | fn(cont, dev, &ic->classdev); | 271 | fn(cont, dev, &ic->classdev); |
| 236 | } | 272 | } |
| @@ -368,6 +404,36 @@ attribute_container_class_device_del(struct class_device *classdev) | |||
| 368 | } | 404 | } |
| 369 | EXPORT_SYMBOL_GPL(attribute_container_class_device_del); | 405 | EXPORT_SYMBOL_GPL(attribute_container_class_device_del); |
| 370 | 406 | ||
| 407 | /** | ||
| 408 | * attribute_container_find_class_device - find the corresponding class_device | ||
| 409 | * | ||
| 410 | * @cont: the container | ||
| 411 | * @dev: the generic device | ||
| 412 | * | ||
| 413 | * Looks up the device in the container's list of class devices and returns | ||
| 414 | * the corresponding class_device. | ||
| 415 | */ | ||
| 416 | struct class_device * | ||
| 417 | attribute_container_find_class_device(struct attribute_container *cont, | ||
| 418 | struct device *dev) | ||
| 419 | { | ||
| 420 | struct class_device *cdev = NULL; | ||
| 421 | struct internal_container *ic; | ||
| 422 | struct klist_iter iter; | ||
| 423 | |||
| 424 | klist_for_each_entry(ic, &cont->containers, node, &iter) { | ||
| 425 | if (ic->classdev.dev == dev) { | ||
| 426 | cdev = &ic->classdev; | ||
| 427 | /* FIXME: must exit iterator then break */ | ||
| 428 | klist_iter_exit(&iter); | ||
| 429 | break; | ||
| 430 | } | ||
| 431 | } | ||
| 432 | |||
| 433 | return cdev; | ||
| 434 | } | ||
| 435 | EXPORT_SYMBOL_GPL(attribute_container_find_class_device); | ||
| 436 | |||
| 371 | int __init | 437 | int __init |
| 372 | attribute_container_init(void) | 438 | attribute_container_init(void) |
| 373 | { | 439 | { |
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 17e96698410e..03204bfd17af 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
| @@ -568,6 +568,36 @@ static void bus_remove_attrs(struct bus_type * bus) | |||
| 568 | } | 568 | } |
| 569 | } | 569 | } |
| 570 | 570 | ||
| 571 | static void klist_devices_get(struct klist_node *n) | ||
| 572 | { | ||
| 573 | struct device *dev = container_of(n, struct device, knode_bus); | ||
| 574 | |||
| 575 | get_device(dev); | ||
| 576 | } | ||
| 577 | |||
| 578 | static void klist_devices_put(struct klist_node *n) | ||
| 579 | { | ||
| 580 | struct device *dev = container_of(n, struct device, knode_bus); | ||
| 581 | |||
| 582 | put_device(dev); | ||
| 583 | } | ||
| 584 | |||
| 585 | static void klist_drivers_get(struct klist_node *n) | ||
| 586 | { | ||
| 587 | struct device_driver *drv = container_of(n, struct device_driver, | ||
| 588 | knode_bus); | ||
| 589 | |||
| 590 | get_driver(drv); | ||
| 591 | } | ||
| 592 | |||
| 593 | static void klist_drivers_put(struct klist_node *n) | ||
| 594 | { | ||
| 595 | struct device_driver *drv = container_of(n, struct device_driver, | ||
| 596 | knode_bus); | ||
| 597 | |||
| 598 | put_driver(drv); | ||
| 599 | } | ||
| 600 | |||
| 571 | /** | 601 | /** |
| 572 | * bus_register - register a bus with the system. | 602 | * bus_register - register a bus with the system. |
| 573 | * @bus: bus. | 603 | * @bus: bus. |
| @@ -602,8 +632,8 @@ int bus_register(struct bus_type * bus) | |||
| 602 | if (retval) | 632 | if (retval) |
| 603 | goto bus_drivers_fail; | 633 | goto bus_drivers_fail; |
| 604 | 634 | ||
| 605 | klist_init(&bus->klist_devices); | 635 | klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put); |
| 606 | klist_init(&bus->klist_drivers); | 636 | klist_init(&bus->klist_drivers, klist_drivers_get, klist_drivers_put); |
| 607 | bus_add_attrs(bus); | 637 | bus_add_attrs(bus); |
| 608 | 638 | ||
| 609 | pr_debug("bus type '%s' registered\n", bus->name); | 639 | pr_debug("bus type '%s' registered\n", bus->name); |
diff --git a/drivers/base/core.c b/drivers/base/core.c index c8a33df00761..6ab73f5c799a 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
| @@ -191,6 +191,20 @@ void device_remove_file(struct device * dev, struct device_attribute * attr) | |||
| 191 | } | 191 | } |
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | static void klist_children_get(struct klist_node *n) | ||
| 195 | { | ||
| 196 | struct device *dev = container_of(n, struct device, knode_parent); | ||
| 197 | |||
| 198 | get_device(dev); | ||
| 199 | } | ||
| 200 | |||
| 201 | static void klist_children_put(struct klist_node *n) | ||
| 202 | { | ||
| 203 | struct device *dev = container_of(n, struct device, knode_parent); | ||
| 204 | |||
| 205 | put_device(dev); | ||
| 206 | } | ||
| 207 | |||
| 194 | 208 | ||
| 195 | /** | 209 | /** |
| 196 | * device_initialize - init device structure. | 210 | * device_initialize - init device structure. |
| @@ -207,7 +221,8 @@ void device_initialize(struct device *dev) | |||
| 207 | { | 221 | { |
| 208 | kobj_set_kset_s(dev, devices_subsys); | 222 | kobj_set_kset_s(dev, devices_subsys); |
| 209 | kobject_init(&dev->kobj); | 223 | kobject_init(&dev->kobj); |
| 210 | klist_init(&dev->klist_children); | 224 | klist_init(&dev->klist_children, klist_children_get, |
| 225 | klist_children_put); | ||
| 211 | INIT_LIST_HEAD(&dev->dma_pools); | 226 | INIT_LIST_HEAD(&dev->dma_pools); |
| 212 | init_MUTEX(&dev->sem); | 227 | init_MUTEX(&dev->sem); |
| 213 | } | 228 | } |
diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 291c5954a3af..ef3fe513e398 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c | |||
| @@ -142,6 +142,19 @@ void put_driver(struct device_driver * drv) | |||
| 142 | kobject_put(&drv->kobj); | 142 | kobject_put(&drv->kobj); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | static void klist_devices_get(struct klist_node *n) | ||
| 146 | { | ||
| 147 | struct device *dev = container_of(n, struct device, knode_driver); | ||
| 148 | |||
| 149 | get_device(dev); | ||
| 150 | } | ||
| 151 | |||
| 152 | static void klist_devices_put(struct klist_node *n) | ||
| 153 | { | ||
| 154 | struct device *dev = container_of(n, struct device, knode_driver); | ||
| 155 | |||
| 156 | put_device(dev); | ||
| 157 | } | ||
| 145 | 158 | ||
| 146 | /** | 159 | /** |
| 147 | * driver_register - register driver with bus | 160 | * driver_register - register driver with bus |
| @@ -157,7 +170,7 @@ void put_driver(struct device_driver * drv) | |||
| 157 | */ | 170 | */ |
| 158 | int driver_register(struct device_driver * drv) | 171 | int driver_register(struct device_driver * drv) |
| 159 | { | 172 | { |
| 160 | klist_init(&drv->klist_devices); | 173 | klist_init(&drv->klist_devices, klist_devices_get, klist_devices_put); |
| 161 | init_completion(&drv->unloaded); | 174 | init_completion(&drv->unloaded); |
| 162 | return bus_add_driver(drv); | 175 | return bus_add_driver(drv); |
| 163 | } | 176 | } |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 652281402c92..5bfa2e9a7c26 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
| @@ -28,6 +28,7 @@ enum { | |||
| 28 | FW_STATUS_DONE, | 28 | FW_STATUS_DONE, |
| 29 | FW_STATUS_ABORT, | 29 | FW_STATUS_ABORT, |
| 30 | FW_STATUS_READY, | 30 | FW_STATUS_READY, |
| 31 | FW_STATUS_READY_NOHOTPLUG, | ||
| 31 | }; | 32 | }; |
| 32 | 33 | ||
| 33 | static int loading_timeout = 10; /* In seconds */ | 34 | static int loading_timeout = 10; /* In seconds */ |
| @@ -344,7 +345,7 @@ error_kfree: | |||
| 344 | 345 | ||
| 345 | static int | 346 | static int |
| 346 | fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p, | 347 | fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p, |
| 347 | const char *fw_name, struct device *device) | 348 | const char *fw_name, struct device *device, int hotplug) |
| 348 | { | 349 | { |
| 349 | struct class_device *class_dev; | 350 | struct class_device *class_dev; |
| 350 | struct firmware_priv *fw_priv; | 351 | struct firmware_priv *fw_priv; |
| @@ -376,7 +377,10 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p, | |||
| 376 | goto error_unreg; | 377 | goto error_unreg; |
| 377 | } | 378 | } |
| 378 | 379 | ||
| 379 | set_bit(FW_STATUS_READY, &fw_priv->status); | 380 | if (hotplug) |
| 381 | set_bit(FW_STATUS_READY, &fw_priv->status); | ||
| 382 | else | ||
| 383 | set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status); | ||
| 380 | *class_dev_p = class_dev; | 384 | *class_dev_p = class_dev; |
| 381 | goto out; | 385 | goto out; |
| 382 | 386 | ||
| @@ -386,21 +390,9 @@ out: | |||
| 386 | return retval; | 390 | return retval; |
| 387 | } | 391 | } |
| 388 | 392 | ||
| 389 | /** | 393 | static int |
| 390 | * request_firmware: - request firmware to hotplug and wait for it | 394 | _request_firmware(const struct firmware **firmware_p, const char *name, |
| 391 | * Description: | 395 | struct device *device, int hotplug) |
| 392 | * @firmware will be used to return a firmware image by the name | ||
| 393 | * of @name for device @device. | ||
| 394 | * | ||
| 395 | * Should be called from user context where sleeping is allowed. | ||
| 396 | * | ||
| 397 | * @name will be use as $FIRMWARE in the hotplug environment and | ||
| 398 | * should be distinctive enough not to be confused with any other | ||
| 399 | * firmware image for this or any other device. | ||
| 400 | **/ | ||
| 401 | int | ||
| 402 | request_firmware(const struct firmware **firmware_p, const char *name, | ||
| 403 | struct device *device) | ||
| 404 | { | 396 | { |
| 405 | struct class_device *class_dev; | 397 | struct class_device *class_dev; |
| 406 | struct firmware_priv *fw_priv; | 398 | struct firmware_priv *fw_priv; |
| @@ -419,22 +411,25 @@ request_firmware(const struct firmware **firmware_p, const char *name, | |||
| 419 | } | 411 | } |
| 420 | memset(firmware, 0, sizeof (*firmware)); | 412 | memset(firmware, 0, sizeof (*firmware)); |
| 421 | 413 | ||
| 422 | retval = fw_setup_class_device(firmware, &class_dev, name, device); | 414 | retval = fw_setup_class_device(firmware, &class_dev, name, device, |
| 415 | hotplug); | ||
| 423 | if (retval) | 416 | if (retval) |
| 424 | goto error_kfree_fw; | 417 | goto error_kfree_fw; |
| 425 | 418 | ||
| 426 | fw_priv = class_get_devdata(class_dev); | 419 | fw_priv = class_get_devdata(class_dev); |
| 427 | 420 | ||
| 428 | if (loading_timeout > 0) { | 421 | if (hotplug) { |
| 429 | fw_priv->timeout.expires = jiffies + loading_timeout * HZ; | 422 | if (loading_timeout > 0) { |
| 430 | add_timer(&fw_priv->timeout); | 423 | fw_priv->timeout.expires = jiffies + loading_timeout * HZ; |
| 431 | } | 424 | add_timer(&fw_priv->timeout); |
| 432 | 425 | } | |
| 433 | kobject_hotplug(&class_dev->kobj, KOBJ_ADD); | ||
| 434 | wait_for_completion(&fw_priv->completion); | ||
| 435 | set_bit(FW_STATUS_DONE, &fw_priv->status); | ||
| 436 | 426 | ||
| 437 | del_timer_sync(&fw_priv->timeout); | 427 | kobject_hotplug(&class_dev->kobj, KOBJ_ADD); |
| 428 | wait_for_completion(&fw_priv->completion); | ||
| 429 | set_bit(FW_STATUS_DONE, &fw_priv->status); | ||
| 430 | del_timer_sync(&fw_priv->timeout); | ||
| 431 | } else | ||
| 432 | wait_for_completion(&fw_priv->completion); | ||
| 438 | 433 | ||
| 439 | down(&fw_lock); | 434 | down(&fw_lock); |
| 440 | if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) { | 435 | if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) { |
| @@ -455,6 +450,26 @@ out: | |||
| 455 | } | 450 | } |
| 456 | 451 | ||
| 457 | /** | 452 | /** |
| 453 | * request_firmware: - request firmware to hotplug and wait for it | ||
| 454 | * Description: | ||
| 455 | * @firmware will be used to return a firmware image by the name | ||
| 456 | * of @name for device @device. | ||
| 457 | * | ||
| 458 | * Should be called from user context where sleeping is allowed. | ||
| 459 | * | ||
| 460 | * @name will be use as $FIRMWARE in the hotplug environment and | ||
| 461 | * should be distinctive enough not to be confused with any other | ||
| 462 | * firmware image for this or any other device. | ||
| 463 | **/ | ||
| 464 | int | ||
| 465 | request_firmware(const struct firmware **firmware_p, const char *name, | ||
| 466 | struct device *device) | ||
| 467 | { | ||
| 468 | int hotplug = 1; | ||
| 469 | return _request_firmware(firmware_p, name, device, hotplug); | ||
| 470 | } | ||
| 471 | |||
| 472 | /** | ||
| 458 | * release_firmware: - release the resource associated with a firmware image | 473 | * release_firmware: - release the resource associated with a firmware image |
| 459 | **/ | 474 | **/ |
| 460 | void | 475 | void |
| @@ -491,6 +506,7 @@ struct firmware_work { | |||
| 491 | struct device *device; | 506 | struct device *device; |
| 492 | void *context; | 507 | void *context; |
| 493 | void (*cont)(const struct firmware *fw, void *context); | 508 | void (*cont)(const struct firmware *fw, void *context); |
| 509 | int hotplug; | ||
| 494 | }; | 510 | }; |
| 495 | 511 | ||
| 496 | static int | 512 | static int |
| @@ -503,7 +519,8 @@ request_firmware_work_func(void *arg) | |||
| 503 | return 0; | 519 | return 0; |
| 504 | } | 520 | } |
| 505 | daemonize("%s/%s", "firmware", fw_work->name); | 521 | daemonize("%s/%s", "firmware", fw_work->name); |
| 506 | request_firmware(&fw, fw_work->name, fw_work->device); | 522 | _request_firmware(&fw, fw_work->name, fw_work->device, |
| 523 | fw_work->hotplug); | ||
| 507 | fw_work->cont(fw, fw_work->context); | 524 | fw_work->cont(fw, fw_work->context); |
| 508 | release_firmware(fw); | 525 | release_firmware(fw); |
| 509 | module_put(fw_work->module); | 526 | module_put(fw_work->module); |
| @@ -518,6 +535,9 @@ request_firmware_work_func(void *arg) | |||
| 518 | * Asynchronous variant of request_firmware() for contexts where | 535 | * Asynchronous variant of request_firmware() for contexts where |
| 519 | * it is not possible to sleep. | 536 | * it is not possible to sleep. |
| 520 | * | 537 | * |
| 538 | * @hotplug invokes hotplug event to copy the firmware image if this flag | ||
| 539 | * is non-zero else the firmware copy must be done manually. | ||
| 540 | * | ||
| 521 | * @cont will be called asynchronously when the firmware request is over. | 541 | * @cont will be called asynchronously when the firmware request is over. |
| 522 | * | 542 | * |
| 523 | * @context will be passed over to @cont. | 543 | * @context will be passed over to @cont. |
| @@ -527,7 +547,7 @@ request_firmware_work_func(void *arg) | |||
| 527 | **/ | 547 | **/ |
| 528 | int | 548 | int |
| 529 | request_firmware_nowait( | 549 | request_firmware_nowait( |
| 530 | struct module *module, | 550 | struct module *module, int hotplug, |
| 531 | const char *name, struct device *device, void *context, | 551 | const char *name, struct device *device, void *context, |
| 532 | void (*cont)(const struct firmware *fw, void *context)) | 552 | void (*cont)(const struct firmware *fw, void *context)) |
| 533 | { | 553 | { |
| @@ -548,6 +568,7 @@ request_firmware_nowait( | |||
| 548 | .device = device, | 568 | .device = device, |
| 549 | .context = context, | 569 | .context = context, |
| 550 | .cont = cont, | 570 | .cont = cont, |
| 571 | .hotplug = hotplug, | ||
| 551 | }; | 572 | }; |
| 552 | 573 | ||
| 553 | ret = kernel_thread(request_firmware_work_func, fw_work, | 574 | ret = kernel_thread(request_firmware_work_func, fw_work, |
diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c index 6c2b447a3336..f25e7c6b2d27 100644 --- a/drivers/base/transport_class.c +++ b/drivers/base/transport_class.c | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | * This file is licensed under GPLv2 | 7 | * This file is licensed under GPLv2 |
| 8 | * | 8 | * |
| 9 | * The basic idea here is to allow any "device controller" (which | 9 | * The basic idea here is to allow any "device controller" (which |
| 10 | * would most often be a Host Bus Adapter" to use the services of one | 10 | * would most often be a Host Bus Adapter to use the services of one |
| 11 | * or more tranport classes for performing transport specific | 11 | * or more tranport classes for performing transport specific |
| 12 | * services. Transport specific services are things that the generic | 12 | * services. Transport specific services are things that the generic |
| 13 | * command layer doesn't want to know about (speed settings, line | 13 | * command layer doesn't want to know about (speed settings, line |
| @@ -64,7 +64,9 @@ void transport_class_unregister(struct transport_class *tclass) | |||
| 64 | } | 64 | } |
| 65 | EXPORT_SYMBOL_GPL(transport_class_unregister); | 65 | EXPORT_SYMBOL_GPL(transport_class_unregister); |
| 66 | 66 | ||
| 67 | static int anon_transport_dummy_function(struct device *dev) | 67 | static int anon_transport_dummy_function(struct transport_container *tc, |
| 68 | struct device *dev, | ||
| 69 | struct class_device *cdev) | ||
| 68 | { | 70 | { |
| 69 | /* do nothing */ | 71 | /* do nothing */ |
| 70 | return 0; | 72 | return 0; |
| @@ -115,9 +117,10 @@ static int transport_setup_classdev(struct attribute_container *cont, | |||
| 115 | struct class_device *classdev) | 117 | struct class_device *classdev) |
| 116 | { | 118 | { |
| 117 | struct transport_class *tclass = class_to_transport_class(cont->class); | 119 | struct transport_class *tclass = class_to_transport_class(cont->class); |
| 120 | struct transport_container *tcont = attribute_container_to_transport_container(cont); | ||
| 118 | 121 | ||
| 119 | if (tclass->setup) | 122 | if (tclass->setup) |
| 120 | tclass->setup(dev); | 123 | tclass->setup(tcont, dev, classdev); |
| 121 | 124 | ||
| 122 | return 0; | 125 | return 0; |
| 123 | } | 126 | } |
| @@ -178,12 +181,14 @@ void transport_add_device(struct device *dev) | |||
| 178 | EXPORT_SYMBOL_GPL(transport_add_device); | 181 | EXPORT_SYMBOL_GPL(transport_add_device); |
| 179 | 182 | ||
| 180 | static int transport_configure(struct attribute_container *cont, | 183 | static int transport_configure(struct attribute_container *cont, |
| 181 | struct device *dev) | 184 | struct device *dev, |
| 185 | struct class_device *cdev) | ||
| 182 | { | 186 | { |
| 183 | struct transport_class *tclass = class_to_transport_class(cont->class); | 187 | struct transport_class *tclass = class_to_transport_class(cont->class); |
| 188 | struct transport_container *tcont = attribute_container_to_transport_container(cont); | ||
| 184 | 189 | ||
| 185 | if (tclass->configure) | 190 | if (tclass->configure) |
| 186 | tclass->configure(dev); | 191 | tclass->configure(tcont, dev, cdev); |
| 187 | 192 | ||
| 188 | return 0; | 193 | return 0; |
| 189 | } | 194 | } |
| @@ -202,7 +207,7 @@ static int transport_configure(struct attribute_container *cont, | |||
| 202 | */ | 207 | */ |
| 203 | void transport_configure_device(struct device *dev) | 208 | void transport_configure_device(struct device *dev) |
| 204 | { | 209 | { |
| 205 | attribute_container_trigger(dev, transport_configure); | 210 | attribute_container_device_trigger(dev, transport_configure); |
| 206 | } | 211 | } |
| 207 | EXPORT_SYMBOL_GPL(transport_configure_device); | 212 | EXPORT_SYMBOL_GPL(transport_configure_device); |
| 208 | 213 | ||
| @@ -215,7 +220,7 @@ static int transport_remove_classdev(struct attribute_container *cont, | |||
| 215 | struct transport_class *tclass = class_to_transport_class(cont->class); | 220 | struct transport_class *tclass = class_to_transport_class(cont->class); |
| 216 | 221 | ||
| 217 | if (tclass->remove) | 222 | if (tclass->remove) |
| 218 | tclass->remove(dev); | 223 | tclass->remove(tcont, dev, classdev); |
| 219 | 224 | ||
| 220 | if (tclass->remove != anon_transport_dummy_function) { | 225 | if (tclass->remove != anon_transport_dummy_function) { |
| 221 | if (tcont->statistics) | 226 | if (tcont->statistics) |
