diff options
Diffstat (limited to 'drivers/acpi/glue.c')
| -rw-r--r-- | drivers/acpi/glue.c | 50 |
1 files changed, 35 insertions, 15 deletions
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 01551840d236..ac00b882e75d 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
| @@ -63,6 +63,9 @@ static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type) | |||
| 63 | { | 63 | { |
| 64 | struct acpi_bus_type *tmp, *ret = NULL; | 64 | struct acpi_bus_type *tmp, *ret = NULL; |
| 65 | 65 | ||
| 66 | if (!type) | ||
| 67 | return NULL; | ||
| 68 | |||
| 66 | down_read(&bus_type_sem); | 69 | down_read(&bus_type_sem); |
| 67 | list_for_each_entry(tmp, &bus_type_list, list) { | 70 | list_for_each_entry(tmp, &bus_type_list, list) { |
| 68 | if (tmp->bus == type) { | 71 | if (tmp->bus == type) { |
| @@ -264,28 +267,39 @@ static int acpi_platform_notify(struct device *dev) | |||
| 264 | { | 267 | { |
| 265 | struct acpi_bus_type *type; | 268 | struct acpi_bus_type *type; |
| 266 | acpi_handle handle; | 269 | acpi_handle handle; |
| 267 | int ret = -EINVAL; | 270 | int ret; |
| 268 | 271 | ||
| 269 | ret = acpi_bind_one(dev, NULL); | 272 | ret = acpi_bind_one(dev, NULL); |
| 270 | if (!ret) | 273 | if (ret && (!dev->bus || !dev->parent)) { |
| 271 | goto out; | ||
| 272 | |||
| 273 | if (!dev->bus || !dev->parent) { | ||
| 274 | /* bridge devices genernally haven't bus or parent */ | 274 | /* bridge devices genernally haven't bus or parent */ |
| 275 | ret = acpi_find_bridge_device(dev, &handle); | 275 | ret = acpi_find_bridge_device(dev, &handle); |
| 276 | goto end; | 276 | if (!ret) { |
| 277 | ret = acpi_bind_one(dev, handle); | ||
| 278 | if (ret) | ||
| 279 | goto out; | ||
| 280 | } | ||
| 277 | } | 281 | } |
| 282 | |||
| 278 | type = acpi_get_bus_type(dev->bus); | 283 | type = acpi_get_bus_type(dev->bus); |
| 279 | if (!type) { | 284 | if (ret) { |
| 280 | DBG("No ACPI bus support for %s\n", dev_name(dev)); | 285 | if (!type || !type->find_device) { |
| 281 | ret = -EINVAL; | 286 | DBG("No ACPI bus support for %s\n", dev_name(dev)); |
| 282 | goto end; | 287 | ret = -EINVAL; |
| 288 | goto out; | ||
| 289 | } | ||
| 290 | |||
| 291 | ret = type->find_device(dev, &handle); | ||
| 292 | if (ret) { | ||
| 293 | DBG("Unable to get handle for %s\n", dev_name(dev)); | ||
| 294 | goto out; | ||
| 295 | } | ||
| 296 | ret = acpi_bind_one(dev, handle); | ||
| 297 | if (ret) | ||
| 298 | goto out; | ||
| 283 | } | 299 | } |
| 284 | if ((ret = type->find_device(dev, &handle)) != 0) | 300 | |
| 285 | DBG("Can't get handler for %s\n", dev_name(dev)); | 301 | if (type && type->setup) |
| 286 | end: | 302 | type->setup(dev); |
| 287 | if (!ret) | ||
| 288 | acpi_bind_one(dev, handle); | ||
| 289 | 303 | ||
| 290 | out: | 304 | out: |
| 291 | #if ACPI_GLUE_DEBUG | 305 | #if ACPI_GLUE_DEBUG |
| @@ -304,6 +318,12 @@ static int acpi_platform_notify(struct device *dev) | |||
| 304 | 318 | ||
| 305 | static int acpi_platform_notify_remove(struct device *dev) | 319 | static int acpi_platform_notify_remove(struct device *dev) |
| 306 | { | 320 | { |
| 321 | struct acpi_bus_type *type; | ||
| 322 | |||
| 323 | type = acpi_get_bus_type(dev->bus); | ||
| 324 | if (type && type->cleanup) | ||
| 325 | type->cleanup(dev); | ||
| 326 | |||
| 307 | acpi_unbind_one(dev); | 327 | acpi_unbind_one(dev); |
| 308 | return 0; | 328 | return 0; |
| 309 | } | 329 | } |
