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 | } |