diff options
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 257 |
1 files changed, 162 insertions, 95 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index c4358716aadc..daee7497efd3 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -29,30 +29,10 @@ extern struct acpi_device *acpi_root; | |||
29 | 29 | ||
30 | static const char *dummy_hid = "device"; | 30 | static const char *dummy_hid = "device"; |
31 | 31 | ||
32 | /* | ||
33 | * The following ACPI IDs are known to be suitable for representing as | ||
34 | * platform devices. | ||
35 | */ | ||
36 | static const struct acpi_device_id acpi_platform_device_ids[] = { | ||
37 | |||
38 | { "PNP0D40" }, | ||
39 | |||
40 | /* Haswell LPSS devices */ | ||
41 | { "INT33C0", ACPI_PLATFORM_CLK }, | ||
42 | { "INT33C1", ACPI_PLATFORM_CLK }, | ||
43 | { "INT33C2", ACPI_PLATFORM_CLK }, | ||
44 | { "INT33C3", ACPI_PLATFORM_CLK }, | ||
45 | { "INT33C4", ACPI_PLATFORM_CLK }, | ||
46 | { "INT33C5", ACPI_PLATFORM_CLK }, | ||
47 | { "INT33C6", ACPI_PLATFORM_CLK }, | ||
48 | { "INT33C7", ACPI_PLATFORM_CLK }, | ||
49 | |||
50 | { } | ||
51 | }; | ||
52 | |||
53 | static LIST_HEAD(acpi_device_list); | 32 | static LIST_HEAD(acpi_device_list); |
54 | static LIST_HEAD(acpi_bus_id_list); | 33 | static LIST_HEAD(acpi_bus_id_list); |
55 | static DEFINE_MUTEX(acpi_scan_lock); | 34 | static DEFINE_MUTEX(acpi_scan_lock); |
35 | static LIST_HEAD(acpi_scan_handlers_list); | ||
56 | DEFINE_MUTEX(acpi_device_lock); | 36 | DEFINE_MUTEX(acpi_device_lock); |
57 | LIST_HEAD(acpi_wakeup_device_list); | 37 | LIST_HEAD(acpi_wakeup_device_list); |
58 | 38 | ||
@@ -62,6 +42,27 @@ struct acpi_device_bus_id{ | |||
62 | struct list_head node; | 42 | struct list_head node; |
63 | }; | 43 | }; |
64 | 44 | ||
45 | void acpi_scan_lock_acquire(void) | ||
46 | { | ||
47 | mutex_lock(&acpi_scan_lock); | ||
48 | } | ||
49 | EXPORT_SYMBOL_GPL(acpi_scan_lock_acquire); | ||
50 | |||
51 | void acpi_scan_lock_release(void) | ||
52 | { | ||
53 | mutex_unlock(&acpi_scan_lock); | ||
54 | } | ||
55 | EXPORT_SYMBOL_GPL(acpi_scan_lock_release); | ||
56 | |||
57 | int acpi_scan_add_handler(struct acpi_scan_handler *handler) | ||
58 | { | ||
59 | if (!handler || !handler->attach) | ||
60 | return -EINVAL; | ||
61 | |||
62 | list_add_tail(&handler->list_node, &acpi_scan_handlers_list); | ||
63 | return 0; | ||
64 | } | ||
65 | |||
65 | /* | 66 | /* |
66 | * Creates hid/cid(s) string needed for modalias and uevent | 67 | * Creates hid/cid(s) string needed for modalias and uevent |
67 | * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: | 68 | * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: |
@@ -116,7 +117,7 @@ static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); | |||
116 | */ | 117 | */ |
117 | void acpi_bus_hot_remove_device(void *context) | 118 | void acpi_bus_hot_remove_device(void *context) |
118 | { | 119 | { |
119 | struct acpi_eject_event *ej_event = (struct acpi_eject_event *) context; | 120 | struct acpi_eject_event *ej_event = context; |
120 | struct acpi_device *device = ej_event->device; | 121 | struct acpi_device *device = ej_event->device; |
121 | acpi_handle handle = device->handle; | 122 | acpi_handle handle = device->handle; |
122 | acpi_handle temp; | 123 | acpi_handle temp; |
@@ -125,19 +126,23 @@ void acpi_bus_hot_remove_device(void *context) | |||
125 | acpi_status status = AE_OK; | 126 | acpi_status status = AE_OK; |
126 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ | 127 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ |
127 | 128 | ||
129 | mutex_lock(&acpi_scan_lock); | ||
130 | |||
131 | /* If there is no handle, the device node has been unregistered. */ | ||
132 | if (!device->handle) { | ||
133 | dev_dbg(&device->dev, "ACPI handle missing\n"); | ||
134 | put_device(&device->dev); | ||
135 | goto out; | ||
136 | } | ||
137 | |||
128 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 138 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
129 | "Hot-removing device %s...\n", dev_name(&device->dev))); | 139 | "Hot-removing device %s...\n", dev_name(&device->dev))); |
130 | 140 | ||
131 | acpi_bus_trim(device); | 141 | acpi_bus_trim(device); |
132 | /* Device node has been released. */ | 142 | /* Device node has been unregistered. */ |
143 | put_device(&device->dev); | ||
133 | device = NULL; | 144 | device = NULL; |
134 | 145 | ||
135 | /* power off device */ | ||
136 | status = acpi_evaluate_object(handle, "_PS3", NULL, NULL); | ||
137 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) | ||
138 | printk(KERN_WARNING PREFIX | ||
139 | "Power-off device failed\n"); | ||
140 | |||
141 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) { | 146 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) { |
142 | arg_list.count = 1; | 147 | arg_list.count = 1; |
143 | arg_list.pointer = &arg; | 148 | arg_list.pointer = &arg; |
@@ -157,18 +162,15 @@ void acpi_bus_hot_remove_device(void *context) | |||
157 | status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); | 162 | status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); |
158 | if (ACPI_FAILURE(status)) { | 163 | if (ACPI_FAILURE(status)) { |
159 | if (status != AE_NOT_FOUND) | 164 | if (status != AE_NOT_FOUND) |
160 | printk(KERN_WARNING PREFIX | 165 | acpi_handle_warn(handle, "Eject failed\n"); |
161 | "Eject device failed\n"); | ||
162 | goto err_out; | ||
163 | } | ||
164 | 166 | ||
165 | kfree(context); | 167 | /* Tell the firmware the hot-remove operation has failed. */ |
166 | return; | 168 | acpi_evaluate_hotplug_ost(handle, ej_event->event, |
169 | ost_code, NULL); | ||
170 | } | ||
167 | 171 | ||
168 | err_out: | 172 | out: |
169 | /* Inform firmware the hot-remove operation has completed w/ error */ | 173 | mutex_unlock(&acpi_scan_lock); |
170 | (void) acpi_evaluate_hotplug_ost(handle, | ||
171 | ej_event->event, ost_code, NULL); | ||
172 | kfree(context); | 174 | kfree(context); |
173 | return; | 175 | return; |
174 | } | 176 | } |
@@ -213,12 +215,10 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
213 | if ((!count) || (buf[0] != '1')) { | 215 | if ((!count) || (buf[0] != '1')) { |
214 | return -EINVAL; | 216 | return -EINVAL; |
215 | } | 217 | } |
216 | #ifndef FORCE_EJECT | 218 | if (!acpi_device->driver && !acpi_device->handler) { |
217 | if (acpi_device->driver == NULL) { | ||
218 | ret = -ENODEV; | 219 | ret = -ENODEV; |
219 | goto err; | 220 | goto err; |
220 | } | 221 | } |
221 | #endif | ||
222 | status = acpi_get_type(acpi_device->handle, &type); | 222 | status = acpi_get_type(acpi_device->handle, &type); |
223 | if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) { | 223 | if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) { |
224 | ret = -ENODEV; | 224 | ret = -ENODEV; |
@@ -231,6 +231,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
231 | goto err; | 231 | goto err; |
232 | } | 232 | } |
233 | 233 | ||
234 | get_device(&acpi_device->dev); | ||
234 | ej_event->device = acpi_device; | 235 | ej_event->device = acpi_device; |
235 | if (acpi_device->flags.eject_pending) { | 236 | if (acpi_device->flags.eject_pending) { |
236 | /* event originated from ACPI eject notification */ | 237 | /* event originated from ACPI eject notification */ |
@@ -243,7 +244,11 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
243 | ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | 244 | ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); |
244 | } | 245 | } |
245 | 246 | ||
246 | acpi_os_hotplug_execute(acpi_bus_hot_remove_device, (void *)ej_event); | 247 | status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); |
248 | if (ACPI_FAILURE(status)) { | ||
249 | put_device(&acpi_device->dev); | ||
250 | kfree(ej_event); | ||
251 | } | ||
247 | err: | 252 | err: |
248 | return ret; | 253 | return ret; |
249 | } | 254 | } |
@@ -637,8 +642,9 @@ static int acpi_device_probe(struct device * dev) | |||
637 | ret = acpi_device_install_notify_handler(acpi_dev); | 642 | ret = acpi_device_install_notify_handler(acpi_dev); |
638 | if (ret) { | 643 | if (ret) { |
639 | if (acpi_drv->ops.remove) | 644 | if (acpi_drv->ops.remove) |
640 | acpi_drv->ops.remove(acpi_dev, | 645 | acpi_drv->ops.remove(acpi_dev); |
641 | acpi_dev->removal_type); | 646 | acpi_dev->driver = NULL; |
647 | acpi_dev->driver_data = NULL; | ||
642 | return ret; | 648 | return ret; |
643 | } | 649 | } |
644 | } | 650 | } |
@@ -660,7 +666,7 @@ static int acpi_device_remove(struct device * dev) | |||
660 | if (acpi_drv->ops.notify) | 666 | if (acpi_drv->ops.notify) |
661 | acpi_device_remove_notify_handler(acpi_dev); | 667 | acpi_device_remove_notify_handler(acpi_dev); |
662 | if (acpi_drv->ops.remove) | 668 | if (acpi_drv->ops.remove) |
663 | acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type); | 669 | acpi_drv->ops.remove(acpi_dev); |
664 | } | 670 | } |
665 | acpi_dev->driver = NULL; | 671 | acpi_dev->driver = NULL; |
666 | acpi_dev->driver_data = NULL; | 672 | acpi_dev->driver_data = NULL; |
@@ -792,10 +798,12 @@ static void acpi_device_unregister(struct acpi_device *device) | |||
792 | 798 | ||
793 | device_del(&device->dev); | 799 | device_del(&device->dev); |
794 | /* | 800 | /* |
795 | * Drop the reference counts of all power resources the device depends | 801 | * Transition the device to D3cold to drop the reference counts of all |
796 | * on and turn off the ones that have no more references. | 802 | * power resources the device depends on and turn off the ones that have |
803 | * no more references. | ||
797 | */ | 804 | */ |
798 | acpi_power_transition(device, ACPI_STATE_D3_COLD); | 805 | acpi_device_set_power(device, ACPI_STATE_D3_COLD); |
806 | device->handle = NULL; | ||
799 | put_device(&device->dev); | 807 | put_device(&device->dev); |
800 | } | 808 | } |
801 | 809 | ||
@@ -883,29 +891,23 @@ EXPORT_SYMBOL(acpi_bus_unregister_driver); | |||
883 | -------------------------------------------------------------------------- */ | 891 | -------------------------------------------------------------------------- */ |
884 | static struct acpi_device *acpi_bus_get_parent(acpi_handle handle) | 892 | static struct acpi_device *acpi_bus_get_parent(acpi_handle handle) |
885 | { | 893 | { |
894 | struct acpi_device *device = NULL; | ||
886 | acpi_status status; | 895 | acpi_status status; |
887 | int ret; | ||
888 | struct acpi_device *device; | ||
889 | 896 | ||
890 | /* | 897 | /* |
891 | * Fixed hardware devices do not appear in the namespace and do not | 898 | * Fixed hardware devices do not appear in the namespace and do not |
892 | * have handles, but we fabricate acpi_devices for them, so we have | 899 | * have handles, but we fabricate acpi_devices for them, so we have |
893 | * to deal with them specially. | 900 | * to deal with them specially. |
894 | */ | 901 | */ |
895 | if (handle == NULL) | 902 | if (!handle) |
896 | return acpi_root; | 903 | return acpi_root; |
897 | 904 | ||
898 | do { | 905 | do { |
899 | status = acpi_get_parent(handle, &handle); | 906 | status = acpi_get_parent(handle, &handle); |
900 | if (status == AE_NULL_ENTRY) | ||
901 | return NULL; | ||
902 | if (ACPI_FAILURE(status)) | 907 | if (ACPI_FAILURE(status)) |
903 | return acpi_root; | 908 | return status == AE_NULL_ENTRY ? NULL : acpi_root; |
904 | 909 | } while (acpi_bus_get_device(handle, &device)); | |
905 | ret = acpi_bus_get_device(handle, &device); | 910 | return device; |
906 | if (ret == 0) | ||
907 | return device; | ||
908 | } while (1); | ||
909 | } | 911 | } |
910 | 912 | ||
911 | acpi_status | 913 | acpi_status |
@@ -1441,19 +1443,21 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, | |||
1441 | acpi_device_get_busid(device); | 1443 | acpi_device_get_busid(device); |
1442 | acpi_device_set_id(device); | 1444 | acpi_device_set_id(device); |
1443 | acpi_bus_get_flags(device); | 1445 | acpi_bus_get_flags(device); |
1446 | device->flags.match_driver = false; | ||
1444 | device_initialize(&device->dev); | 1447 | device_initialize(&device->dev); |
1445 | dev_set_uevent_suppress(&device->dev, true); | 1448 | dev_set_uevent_suppress(&device->dev, true); |
1446 | } | 1449 | } |
1447 | 1450 | ||
1448 | void acpi_device_add_finalize(struct acpi_device *device) | 1451 | void acpi_device_add_finalize(struct acpi_device *device) |
1449 | { | 1452 | { |
1453 | device->flags.match_driver = true; | ||
1450 | dev_set_uevent_suppress(&device->dev, false); | 1454 | dev_set_uevent_suppress(&device->dev, false); |
1451 | kobject_uevent(&device->dev.kobj, KOBJ_ADD); | 1455 | kobject_uevent(&device->dev.kobj, KOBJ_ADD); |
1452 | } | 1456 | } |
1453 | 1457 | ||
1454 | static int acpi_add_single_object(struct acpi_device **child, | 1458 | static int acpi_add_single_object(struct acpi_device **child, |
1455 | acpi_handle handle, int type, | 1459 | acpi_handle handle, int type, |
1456 | unsigned long long sta, bool match_driver) | 1460 | unsigned long long sta) |
1457 | { | 1461 | { |
1458 | int result; | 1462 | int result; |
1459 | struct acpi_device *device; | 1463 | struct acpi_device *device; |
@@ -1469,7 +1473,6 @@ static int acpi_add_single_object(struct acpi_device **child, | |||
1469 | acpi_bus_get_power_flags(device); | 1473 | acpi_bus_get_power_flags(device); |
1470 | acpi_bus_get_wakeup_device_flags(device); | 1474 | acpi_bus_get_wakeup_device_flags(device); |
1471 | 1475 | ||
1472 | device->flags.match_driver = match_driver; | ||
1473 | result = acpi_device_add(device, acpi_device_release); | 1476 | result = acpi_device_add(device, acpi_device_release); |
1474 | if (result) { | 1477 | if (result) { |
1475 | acpi_device_release(&device->dev); | 1478 | acpi_device_release(&device->dev); |
@@ -1562,12 +1565,10 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, | |||
1562 | return AE_CTRL_DEPTH; | 1565 | return AE_CTRL_DEPTH; |
1563 | } | 1566 | } |
1564 | 1567 | ||
1565 | acpi_add_single_object(&device, handle, type, sta, false); | 1568 | acpi_add_single_object(&device, handle, type, sta); |
1566 | if (!device) | 1569 | if (!device) |
1567 | return AE_CTRL_DEPTH; | 1570 | return AE_CTRL_DEPTH; |
1568 | 1571 | ||
1569 | device->flags.match_driver = true; | ||
1570 | |||
1571 | out: | 1572 | out: |
1572 | if (!*return_value) | 1573 | if (!*return_value) |
1573 | *return_value = device; | 1574 | *return_value = device; |
@@ -1575,33 +1576,68 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, | |||
1575 | return AE_OK; | 1576 | return AE_OK; |
1576 | } | 1577 | } |
1577 | 1578 | ||
1579 | static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id) | ||
1580 | { | ||
1581 | struct acpi_scan_handler *handler; | ||
1582 | |||
1583 | list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) { | ||
1584 | const struct acpi_device_id *devid; | ||
1585 | |||
1586 | for (devid = handler->ids; devid->id[0]; devid++) { | ||
1587 | int ret; | ||
1588 | |||
1589 | if (strcmp((char *)devid->id, id)) | ||
1590 | continue; | ||
1591 | |||
1592 | ret = handler->attach(device, devid); | ||
1593 | if (ret > 0) { | ||
1594 | device->handler = handler; | ||
1595 | return ret; | ||
1596 | } else if (ret < 0) { | ||
1597 | return ret; | ||
1598 | } | ||
1599 | } | ||
1600 | } | ||
1601 | return 0; | ||
1602 | } | ||
1603 | |||
1604 | static int acpi_scan_attach_handler(struct acpi_device *device) | ||
1605 | { | ||
1606 | struct acpi_hardware_id *hwid; | ||
1607 | int ret = 0; | ||
1608 | |||
1609 | list_for_each_entry(hwid, &device->pnp.ids, list) { | ||
1610 | ret = acpi_scan_do_attach_handler(device, hwid->id); | ||
1611 | if (ret) | ||
1612 | break; | ||
1613 | |||
1614 | } | ||
1615 | return ret; | ||
1616 | } | ||
1617 | |||
1578 | static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, | 1618 | static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, |
1579 | void *not_used, void **ret_not_used) | 1619 | void *not_used, void **ret_not_used) |
1580 | { | 1620 | { |
1581 | const struct acpi_device_id *id; | ||
1582 | acpi_status status = AE_OK; | ||
1583 | struct acpi_device *device; | 1621 | struct acpi_device *device; |
1584 | unsigned long long sta_not_used; | 1622 | unsigned long long sta_not_used; |
1585 | int type_not_used; | 1623 | int ret; |
1586 | 1624 | ||
1587 | /* | 1625 | /* |
1588 | * Ignore errors ignored by acpi_bus_check_add() to avoid terminating | 1626 | * Ignore errors ignored by acpi_bus_check_add() to avoid terminating |
1589 | * namespace walks prematurely. | 1627 | * namespace walks prematurely. |
1590 | */ | 1628 | */ |
1591 | if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) | 1629 | if (acpi_bus_type_and_status(handle, &ret, &sta_not_used)) |
1592 | return AE_OK; | 1630 | return AE_OK; |
1593 | 1631 | ||
1594 | if (acpi_bus_get_device(handle, &device)) | 1632 | if (acpi_bus_get_device(handle, &device)) |
1595 | return AE_CTRL_DEPTH; | 1633 | return AE_CTRL_DEPTH; |
1596 | 1634 | ||
1597 | id = __acpi_match_device(device, acpi_platform_device_ids); | 1635 | ret = acpi_scan_attach_handler(device); |
1598 | if (id) { | 1636 | if (ret) |
1599 | /* This is a known good platform device. */ | 1637 | return ret > 0 ? AE_OK : AE_CTRL_DEPTH; |
1600 | acpi_create_platform_device(device, id->driver_data); | 1638 | |
1601 | } else if (device_attach(&device->dev) < 0) { | 1639 | ret = device_attach(&device->dev); |
1602 | status = AE_CTRL_DEPTH; | 1640 | return ret >= 0 ? AE_OK : AE_CTRL_DEPTH; |
1603 | } | ||
1604 | return status; | ||
1605 | } | 1641 | } |
1606 | 1642 | ||
1607 | /** | 1643 | /** |
@@ -1615,14 +1651,14 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, | |||
1615 | * there has been a real error. There just have been no suitable ACPI objects | 1651 | * there has been a real error. There just have been no suitable ACPI objects |
1616 | * in the table trunk from which the kernel could create a device and add an | 1652 | * in the table trunk from which the kernel could create a device and add an |
1617 | * appropriate driver. | 1653 | * appropriate driver. |
1654 | * | ||
1655 | * Must be called under acpi_scan_lock. | ||
1618 | */ | 1656 | */ |
1619 | int acpi_bus_scan(acpi_handle handle) | 1657 | int acpi_bus_scan(acpi_handle handle) |
1620 | { | 1658 | { |
1621 | void *device = NULL; | 1659 | void *device = NULL; |
1622 | int error = 0; | 1660 | int error = 0; |
1623 | 1661 | ||
1624 | mutex_lock(&acpi_scan_lock); | ||
1625 | |||
1626 | if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) | 1662 | if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) |
1627 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 1663 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
1628 | acpi_bus_check_add, NULL, NULL, &device); | 1664 | acpi_bus_check_add, NULL, NULL, &device); |
@@ -1633,7 +1669,6 @@ int acpi_bus_scan(acpi_handle handle) | |||
1633 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 1669 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
1634 | acpi_bus_device_attach, NULL, NULL, NULL); | 1670 | acpi_bus_device_attach, NULL, NULL, NULL); |
1635 | 1671 | ||
1636 | mutex_unlock(&acpi_scan_lock); | ||
1637 | return error; | 1672 | return error; |
1638 | } | 1673 | } |
1639 | EXPORT_SYMBOL(acpi_bus_scan); | 1674 | EXPORT_SYMBOL(acpi_bus_scan); |
@@ -1644,8 +1679,17 @@ static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used, | |||
1644 | struct acpi_device *device = NULL; | 1679 | struct acpi_device *device = NULL; |
1645 | 1680 | ||
1646 | if (!acpi_bus_get_device(handle, &device)) { | 1681 | if (!acpi_bus_get_device(handle, &device)) { |
1682 | struct acpi_scan_handler *dev_handler = device->handler; | ||
1683 | |||
1647 | device->removal_type = ACPI_BUS_REMOVAL_EJECT; | 1684 | device->removal_type = ACPI_BUS_REMOVAL_EJECT; |
1648 | device_release_driver(&device->dev); | 1685 | if (dev_handler) { |
1686 | if (dev_handler->detach) | ||
1687 | dev_handler->detach(device); | ||
1688 | |||
1689 | device->handler = NULL; | ||
1690 | } else { | ||
1691 | device_release_driver(&device->dev); | ||
1692 | } | ||
1649 | } | 1693 | } |
1650 | return AE_OK; | 1694 | return AE_OK; |
1651 | } | 1695 | } |
@@ -1661,10 +1705,14 @@ static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used, | |||
1661 | return AE_OK; | 1705 | return AE_OK; |
1662 | } | 1706 | } |
1663 | 1707 | ||
1708 | /** | ||
1709 | * acpi_bus_trim - Remove ACPI device node and all of its descendants | ||
1710 | * @start: Root of the ACPI device nodes subtree to remove. | ||
1711 | * | ||
1712 | * Must be called under acpi_scan_lock. | ||
1713 | */ | ||
1664 | void acpi_bus_trim(struct acpi_device *start) | 1714 | void acpi_bus_trim(struct acpi_device *start) |
1665 | { | 1715 | { |
1666 | mutex_lock(&acpi_scan_lock); | ||
1667 | |||
1668 | /* | 1716 | /* |
1669 | * Execute acpi_bus_device_detach() as a post-order callback to detach | 1717 | * Execute acpi_bus_device_detach() as a post-order callback to detach |
1670 | * all ACPI drivers from the device nodes being removed. | 1718 | * all ACPI drivers from the device nodes being removed. |
@@ -1679,33 +1727,45 @@ void acpi_bus_trim(struct acpi_device *start) | |||
1679 | acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, | 1727 | acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, |
1680 | acpi_bus_remove, NULL, NULL); | 1728 | acpi_bus_remove, NULL, NULL); |
1681 | acpi_bus_remove(start->handle, 0, NULL, NULL); | 1729 | acpi_bus_remove(start->handle, 0, NULL, NULL); |
1682 | |||
1683 | mutex_unlock(&acpi_scan_lock); | ||
1684 | } | 1730 | } |
1685 | EXPORT_SYMBOL_GPL(acpi_bus_trim); | 1731 | EXPORT_SYMBOL_GPL(acpi_bus_trim); |
1686 | 1732 | ||
1687 | static int acpi_bus_scan_fixed(void) | 1733 | static int acpi_bus_scan_fixed(void) |
1688 | { | 1734 | { |
1689 | int result = 0; | 1735 | int result = 0; |
1690 | struct acpi_device *device = NULL; | ||
1691 | 1736 | ||
1692 | /* | 1737 | /* |
1693 | * Enumerate all fixed-feature devices. | 1738 | * Enumerate all fixed-feature devices. |
1694 | */ | 1739 | */ |
1695 | if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) { | 1740 | if (!(acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON)) { |
1741 | struct acpi_device *device = NULL; | ||
1742 | |||
1696 | result = acpi_add_single_object(&device, NULL, | 1743 | result = acpi_add_single_object(&device, NULL, |
1697 | ACPI_BUS_TYPE_POWER_BUTTON, | 1744 | ACPI_BUS_TYPE_POWER_BUTTON, |
1698 | ACPI_STA_DEFAULT, true); | 1745 | ACPI_STA_DEFAULT); |
1746 | if (result) | ||
1747 | return result; | ||
1748 | |||
1749 | result = device_attach(&device->dev); | ||
1750 | if (result < 0) | ||
1751 | return result; | ||
1752 | |||
1699 | device_init_wakeup(&device->dev, true); | 1753 | device_init_wakeup(&device->dev, true); |
1700 | } | 1754 | } |
1701 | 1755 | ||
1702 | if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) { | 1756 | if (!(acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON)) { |
1757 | struct acpi_device *device = NULL; | ||
1758 | |||
1703 | result = acpi_add_single_object(&device, NULL, | 1759 | result = acpi_add_single_object(&device, NULL, |
1704 | ACPI_BUS_TYPE_SLEEP_BUTTON, | 1760 | ACPI_BUS_TYPE_SLEEP_BUTTON, |
1705 | ACPI_STA_DEFAULT, true); | 1761 | ACPI_STA_DEFAULT); |
1762 | if (result) | ||
1763 | return result; | ||
1764 | |||
1765 | result = device_attach(&device->dev); | ||
1706 | } | 1766 | } |
1707 | 1767 | ||
1708 | return result; | 1768 | return result < 0 ? result : 0; |
1709 | } | 1769 | } |
1710 | 1770 | ||
1711 | int __init acpi_scan_init(void) | 1771 | int __init acpi_scan_init(void) |
@@ -1719,25 +1779,32 @@ int __init acpi_scan_init(void) | |||
1719 | } | 1779 | } |
1720 | 1780 | ||
1721 | acpi_pci_root_init(); | 1781 | acpi_pci_root_init(); |
1782 | acpi_pci_link_init(); | ||
1783 | acpi_platform_init(); | ||
1722 | acpi_csrt_init(); | 1784 | acpi_csrt_init(); |
1785 | acpi_container_init(); | ||
1723 | 1786 | ||
1787 | mutex_lock(&acpi_scan_lock); | ||
1724 | /* | 1788 | /* |
1725 | * Enumerate devices in the ACPI namespace. | 1789 | * Enumerate devices in the ACPI namespace. |
1726 | */ | 1790 | */ |
1727 | result = acpi_bus_scan(ACPI_ROOT_OBJECT); | 1791 | result = acpi_bus_scan(ACPI_ROOT_OBJECT); |
1728 | if (result) | 1792 | if (result) |
1729 | return result; | 1793 | goto out; |
1730 | 1794 | ||
1731 | result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root); | 1795 | result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root); |
1732 | if (result) | 1796 | if (result) |
1733 | return result; | 1797 | goto out; |
1734 | 1798 | ||
1735 | result = acpi_bus_scan_fixed(); | 1799 | result = acpi_bus_scan_fixed(); |
1736 | if (result) { | 1800 | if (result) { |
1737 | acpi_device_unregister(acpi_root); | 1801 | acpi_device_unregister(acpi_root); |
1738 | return result; | 1802 | goto out; |
1739 | } | 1803 | } |
1740 | 1804 | ||
1741 | acpi_update_all_gpes(); | 1805 | acpi_update_all_gpes(); |
1742 | return 0; | 1806 | |
1807 | out: | ||
1808 | mutex_unlock(&acpi_scan_lock); | ||
1809 | return result; | ||
1743 | } | 1810 | } |