From 805d410fb0dbd65e1a57a810858fa2491e75822d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 21 Dec 2012 00:36:39 +0100 Subject: ACPI: Separate adding ACPI device objects from probing ACPI drivers Split the ACPI namespace scanning for devices into two passes, such that struct acpi_device objects are registerd in the first pass without probing ACPI drivers and the drivers are probed against them directly in the second pass. There are two main reasons for doing that. First, the ACPI PCI root bridge driver's .add() routine, acpi_pci_root_add(), causes struct pci_dev objects to be created for all PCI devices under the given root bridge. Usually, there are corresponding ACPI device nodes in the ACPI namespace for some of those devices and therefore there should be "companion" struct acpi_device objects to attach those struct pci_dev objects to. These struct acpi_device objects should exist when the corresponding struct pci_dev objects are created, but that is only guaranteed during boot and not during hotplug. This leads to a number of functional differences between the boot and the hotplug cases which are not strictly necessary and make the code more complicated. For example, this forces the ACPI PCI root bridge driver to defer the registration of the just created struct pci_dev objects and to use a special .start() callback routine, acpi_pci_root_start(), to make sure that all of the "companion" struct acpi_device objects will be present at PCI devices registration time during hotplug. If those differences can be eliminated, we will be able to consolidate the boot and hotplug code paths for the enumeration and registration of PCI devices and to reduce the complexity of that code quite a bit. The second reason is that, in general, it should be possible to resolve conflicts of resources assigned by the BIOS to different devices represented by ACPI namespace nodes before any drivers bind to them and before they are attached to "companion" objects representing physical devices (such as struct pci_dev). However, for this purpose we first need to enumerate all ACPI device nodes in the given namespace scope. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani --- drivers/acpi/scan.c | 103 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 31 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 53502d1bbf26..726f0d1ace4b 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv) struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(drv); - return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); + return acpi_dev->bus_ops.acpi_op_match + && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) return 0; } +/* + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add. + * @device: ACPI device node to bind. + */ +static void acpi_hot_add_bind(struct acpi_device *device) +{ + if (device->flags.bus_address + && device->parent && device->parent->ops.bind) + device->parent->ops.bind(device); +} + static int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, unsigned long long sta, @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct acpi_device **child, result = acpi_device_register(device); - /* - * Bind _ADR-Based Devices when hot add - */ - if (device->flags.bus_address) { - if (device->parent && device->parent->ops.bind) - device->parent->ops.bind(device); - } + if (device->bus_ops.acpi_op_match) + acpi_hot_add_bind(device); end: if (!result) { @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource(acpi_handle handle) struct acpi_bus_ops ops = { .acpi_op_add = 1, .acpi_op_start = 1, + .acpi_op_match = 1, }; struct acpi_device *device = NULL; @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, void *context, void **return_value) { struct acpi_bus_ops *ops = context; + struct acpi_device *device = NULL; int type; unsigned long long sta; - struct acpi_device *device; acpi_status status; int result; @@ -1596,52 +1604,84 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, return AE_CTRL_DEPTH; } - /* - * We may already have an acpi_device from a previous enumeration. If - * so, we needn't add it again, but we may still have to start it. - */ - device = NULL; acpi_bus_get_device(handle, &device); if (ops->acpi_op_add && !device) { - acpi_add_single_object(&device, handle, type, sta, ops); - /* Is the device a known good platform device? */ - if (device - && !acpi_match_device_ids(device, acpi_platform_device_ids)) - acpi_create_platform_device(device); - } + struct acpi_bus_ops add_ops = *ops; - if (!device) - return AE_CTRL_DEPTH; - - if (ops->acpi_op_start && !(ops->acpi_op_add)) { - status = acpi_start_single_object(device); - if (ACPI_FAILURE(status)) + add_ops.acpi_op_match = 0; + acpi_add_single_object(&device, handle, type, sta, &add_ops); + if (!device) return AE_CTRL_DEPTH; + + device->bus_ops.acpi_op_match = 1; + acpi_hot_add_bind(device); } if (!*return_value) *return_value = device; + return AE_OK; } +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, + void *context, void **not_used) +{ + struct acpi_bus_ops *ops = context; + acpi_status status = AE_OK; + struct acpi_device *device; + unsigned long long sta_not_used; + int type_not_used; + + /* + * Ignore errors ignored by acpi_bus_check_add() to avoid terminating + * namespace walks prematurely. + */ + if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) + return AE_OK; + + if (acpi_bus_get_device(handle, &device)) + return AE_CTRL_DEPTH; + + if (ops->acpi_op_add) { + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { + /* This is a known good platform device. */ + acpi_create_platform_device(device); + } else if (device_attach(&device->dev)) { + status = AE_CTRL_DEPTH; + } + } else if (ops->acpi_op_start) { + if (ACPI_FAILURE(acpi_start_single_object(device))) + status = AE_CTRL_DEPTH; + } + return status; +} + static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, struct acpi_device **child) { - acpi_status status; void *device = NULL; + acpi_status status; + int ret = -ENODEV; status = acpi_bus_check_add(handle, 0, ops, &device); if (ACPI_SUCCESS(status)) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, acpi_bus_check_add, NULL, ops, &device); + if (!device) + goto out; + + ret = 0; + status = acpi_bus_probe_start(handle, 0, ops, NULL); + if (ACPI_SUCCESS(status)) + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + acpi_bus_probe_start, NULL, ops, NULL); + + out: if (child) *child = device; - if (device) - return 0; - else - return -ENODEV; + return ret; } /* @@ -1752,6 +1792,7 @@ static int acpi_bus_scan_fixed(void) memset(&ops, 0, sizeof(ops)); ops.acpi_op_add = 1; ops.acpi_op_start = 1; + ops.acpi_op_match = 1; /* * Enumerate all fixed-feature devices. -- cgit v1.2.2 From 92ef2a25c763338905dce8344a0584606f842920 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 21 Dec 2012 00:36:40 +0100 Subject: ACPI: Change the ordering of PCI root bridge driver registrarion Instead of running acpi_pci_root_init() from a separate subsys initcall, call it directly from acpi_scan_init() before scanning the ACPI namespace for the first time, so that the PCI root bridge driver's .add() routine, acpi_pci_root_start(), is always run before binding ACPI drivers or attaching "companion" device objects to struct acpi_device objects below the root bridge's device node in the ACPI namespace. The first, simpler reason for doing this is that it makes the situation during boot more similar to the situation during hotplug, in which the ACPI PCI root bridge driver is always present. The second reason is that acpi_pci_root_init() causes struct pci_dev objects to be created for all PCI devices below the bridge and these objects may be necessary for whatever is done with the other ACPI device nodes in that namespace scope. For example, devices created by acpi_create_platform_device() sometimes may need to be added to the device hierarchy as children of PCI bridges. For this purpose, however, the struct pci_dev objects representing those bridges need to exist before the platform devices in question are registered. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani --- drivers/acpi/internal.h | 1 + drivers/acpi/pci_root.c | 4 +--- drivers/acpi/scan.c | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 3c407cdc1ec1..e050254ae143 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -67,6 +67,7 @@ struct acpi_ec { extern struct acpi_ec *first_ec; +int acpi_pci_root_init(void); int acpi_ec_init(void); int acpi_ec_ecdt_probe(void); int acpi_boot_ec_enable(void); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 7928d4dc7056..a233fe93dfac 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -699,7 +699,7 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) return 0; } -static int __init acpi_pci_root_init(void) +int __init acpi_pci_root_init(void) { acpi_hest_init(); @@ -712,5 +712,3 @@ static int __init acpi_pci_root_init(void) return 0; } - -subsys_initcall(acpi_pci_root_init); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 726f0d1ace4b..a7e81ac2cd0c 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1831,6 +1831,7 @@ int __init acpi_scan_init(void) } acpi_power_init(); + acpi_pci_root_init(); /* * Enumerate devices in the ACPI namespace. -- cgit v1.2.2 From 0fc300b0537c6a6a7f2b261b6c339dc498cd1702 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 21 Dec 2012 00:36:41 +0100 Subject: ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different The current ACPI namespace scanning code suggests that acpi_bus_add() and acpi_bus_start() share some code. In fact, however, they are completely different code paths (except for the initial checks), so refactor the code to make that distinction visibly clear. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani --- drivers/acpi/scan.c | 63 +++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 28 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a7e81ac2cd0c..f3bcaf6c6bd4 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1623,10 +1623,9 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, return AE_OK; } -static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, - void *context, void **not_used) +static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, + void *not_used, void **ret_not_used) { - struct acpi_bus_ops *ops = context; acpi_status status = AE_OK; struct acpi_device *device; unsigned long long sta_not_used; @@ -1642,16 +1641,11 @@ static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, if (acpi_bus_get_device(handle, &device)) return AE_CTRL_DEPTH; - if (ops->acpi_op_add) { - if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { - /* This is a known good platform device. */ - acpi_create_platform_device(device); - } else if (device_attach(&device->dev)) { - status = AE_CTRL_DEPTH; - } - } else if (ops->acpi_op_start) { - if (ACPI_FAILURE(acpi_start_single_object(device))) - status = AE_CTRL_DEPTH; + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { + /* This is a known good platform device. */ + acpi_create_platform_device(device); + } else if (device_attach(&device->dev)) { + status = AE_CTRL_DEPTH; } return status; } @@ -1672,10 +1666,10 @@ static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, goto out; ret = 0; - status = acpi_bus_probe_start(handle, 0, ops, NULL); + status = acpi_bus_device_attach(handle, 0, NULL, NULL); if (ACPI_SUCCESS(status)) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_probe_start, NULL, ops, NULL); + acpi_bus_device_attach, NULL, NULL, NULL); out: if (child) @@ -1700,31 +1694,44 @@ int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type) { - struct acpi_bus_ops ops; - - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; + struct acpi_bus_ops ops = { .acpi_op_add = 1, }; return acpi_bus_scan(handle, &ops, child); } EXPORT_SYMBOL(acpi_bus_add); -int acpi_bus_start(struct acpi_device *device) +static acpi_status acpi_bus_start_device(acpi_handle handle, u32 lvl, + void *not_used, void **ret_not_used) { - struct acpi_bus_ops ops; - int result; + struct acpi_device *device; + unsigned long long sta_not_used; + int type_not_used; + + /* + * Ignore errors ignored by acpi_bus_check_add() to avoid terminating + * namespace walks prematurely. + */ + if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) + return AE_OK; + + if (acpi_bus_get_device(handle, &device)) + return AE_CTRL_DEPTH; + + return acpi_start_single_object(device); +} +int acpi_bus_start(struct acpi_device *device) +{ if (!device) return -EINVAL; - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_start = 1; - - result = acpi_bus_scan(device->handle, &ops, NULL); + if (ACPI_SUCCESS(acpi_start_single_object(device))) + acpi_walk_namespace(ACPI_TYPE_ANY, device->handle, + ACPI_UINT32_MAX, acpi_bus_start_device, + NULL, NULL, NULL); acpi_update_all_gpes(); - - return result; + return 0; } EXPORT_SYMBOL(acpi_bus_start); -- cgit v1.2.2 From ca7b3c4f3d85bf7ec225eebb43b6af0a25499c6c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 21 Dec 2012 00:36:42 +0100 Subject: ACPI: Reduce the usage of struct acpi_bus_ops Objects of type struct acpi_bus_ops are currently used to pass information between different parts of the ACPI namespace scanning code, sometimes in quite convoluted ways. It turns out that that is not necessary in some cases, so simplify the code by reducing the utilization of struct acpi_bus_ops objects where clearly possible. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani --- drivers/acpi/scan.c | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f3bcaf6c6bd4..8dde0e7f68d8 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1527,7 +1527,6 @@ end: static void acpi_bus_add_power_resource(acpi_handle handle) { struct acpi_bus_ops ops = { - .acpi_op_add = 1, .acpi_op_start = 1, .acpi_op_match = 1, }; @@ -1581,7 +1580,6 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type, static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, void *context, void **return_value) { - struct acpi_bus_ops *ops = context; struct acpi_device *device = NULL; int type; unsigned long long sta; @@ -1605,11 +1603,13 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, } acpi_bus_get_device(handle, &device); - if (ops->acpi_op_add && !device) { - struct acpi_bus_ops add_ops = *ops; + if (!device) { + struct acpi_bus_ops ops = { + .acpi_op_start = !!context, + .acpi_op_match = 0, + }; - add_ops.acpi_op_match = 0; - acpi_add_single_object(&device, handle, type, sta, &add_ops); + acpi_add_single_object(&device, handle, type, sta, &ops); if (!device) return AE_CTRL_DEPTH; @@ -1650,17 +1650,18 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, return status; } -static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, +static int acpi_bus_scan(acpi_handle handle, bool start, struct acpi_device **child) { void *device = NULL; acpi_status status; int ret = -ENODEV; - status = acpi_bus_check_add(handle, 0, ops, &device); + status = acpi_bus_check_add(handle, 0, (void *)start, &device); if (ACPI_SUCCESS(status)) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_check_add, NULL, ops, &device); + acpi_bus_check_add, NULL, (void *)start, + &device); if (!device) goto out; @@ -1694,9 +1695,7 @@ int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type) { - struct acpi_bus_ops ops = { .acpi_op_add = 1, }; - - return acpi_bus_scan(handle, &ops, child); + return acpi_bus_scan(handle, false, child); } EXPORT_SYMBOL(acpi_bus_add); @@ -1794,12 +1793,10 @@ static int acpi_bus_scan_fixed(void) { int result = 0; struct acpi_device *device = NULL; - struct acpi_bus_ops ops; - - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; - ops.acpi_op_start = 1; - ops.acpi_op_match = 1; + struct acpi_bus_ops ops = { + .acpi_op_start = 1, + .acpi_op_match = 1, + }; /* * Enumerate all fixed-feature devices. @@ -1825,11 +1822,6 @@ static int acpi_bus_scan_fixed(void) int __init acpi_scan_init(void) { int result; - struct acpi_bus_ops ops; - - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; - ops.acpi_op_start = 1; result = bus_register(&acpi_bus_type); if (result) { @@ -1843,7 +1835,7 @@ int __init acpi_scan_init(void) /* * Enumerate devices in the ACPI namespace. */ - result = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root); + result = acpi_bus_scan(ACPI_ROOT_OBJECT, true, &acpi_root); if (!result) result = acpi_bus_scan_fixed(); -- cgit v1.2.2 From a2d06a1a0851fb3d7e775b9d878cdffb9e0300ee Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 21 Dec 2012 00:36:43 +0100 Subject: ACPI: Replace struct acpi_bus_ops with enum type Notice that one member of struct acpi_bus_ops, acpi_op_add, is not used anywhere any more and the relationship between its remaining members, acpi_op_match and acpi_op_start, is such that it doesn't make sense to set the latter without setting the former at the same time. Therefore, replace struct acpi_bus_ops with new a enum type, enum acpi_bus_add_type, with three values, ACPI_BUS_ADD_BASIC, ACPI_BUS_ADD_MATCH, ACPI_BUS_ADD_START, corresponding to both acpi_op_match and acpi_op_start unset, acpi_op_match set and acpi_op_start unset, and both acpi_op_match and acpi_op_start set, respectively. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani --- drivers/acpi/scan.c | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 8dde0e7f68d8..7082d11ce5d2 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -494,7 +494,7 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv) struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(drv); - return acpi_dev->bus_ops.acpi_op_match + return acpi_dev->add_type >= ACPI_BUS_ADD_MATCH && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } @@ -580,7 +580,7 @@ static int acpi_device_probe(struct device * dev) ret = acpi_bus_driver_init(acpi_dev, acpi_drv); if (!ret) { - if (acpi_dev->bus_ops.acpi_op_start) + if (acpi_dev->add_type == ACPI_BUS_ADD_START) acpi_start_single_object(acpi_dev); if (acpi_drv->ops.notify) { @@ -1433,7 +1433,7 @@ static void acpi_hot_add_bind(struct acpi_device *device) static int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, unsigned long long sta, - struct acpi_bus_ops *ops) + enum acpi_bus_add_type add_type) { int result; struct acpi_device *device; @@ -1449,7 +1449,7 @@ static int acpi_add_single_object(struct acpi_device **child, device->device_type = type; device->handle = handle; device->parent = acpi_bus_get_parent(handle); - device->bus_ops = *ops; /* workround for not call .start */ + device->add_type = add_type; STRUCT_TO_INT(device->status) = sta; acpi_device_get_busid(device); @@ -1502,7 +1502,7 @@ static int acpi_add_single_object(struct acpi_device **child, result = acpi_device_register(device); - if (device->bus_ops.acpi_op_match) + if (device->add_type >= ACPI_BUS_ADD_MATCH) acpi_hot_add_bind(device); end: @@ -1526,16 +1526,12 @@ end: static void acpi_bus_add_power_resource(acpi_handle handle) { - struct acpi_bus_ops ops = { - .acpi_op_start = 1, - .acpi_op_match = 1, - }; struct acpi_device *device = NULL; acpi_bus_get_device(handle, &device); if (!device) acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER, - ACPI_STA_DEFAULT, &ops); + ACPI_STA_DEFAULT, ACPI_BUS_ADD_START); } static int acpi_bus_type_and_status(acpi_handle handle, int *type, @@ -1604,16 +1600,13 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, acpi_bus_get_device(handle, &device); if (!device) { - struct acpi_bus_ops ops = { - .acpi_op_start = !!context, - .acpi_op_match = 0, - }; - - acpi_add_single_object(&device, handle, type, sta, &ops); + acpi_add_single_object(&device, handle, type, sta, + ACPI_BUS_ADD_BASIC); if (!device) return AE_CTRL_DEPTH; - device->bus_ops.acpi_op_match = 1; + device->add_type = context ? + ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; acpi_hot_add_bind(device); } @@ -1793,10 +1786,6 @@ static int acpi_bus_scan_fixed(void) { int result = 0; struct acpi_device *device = NULL; - struct acpi_bus_ops ops = { - .acpi_op_start = 1, - .acpi_op_match = 1, - }; /* * Enumerate all fixed-feature devices. @@ -1805,7 +1794,7 @@ static int acpi_bus_scan_fixed(void) result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_POWER_BUTTON, ACPI_STA_DEFAULT, - &ops); + ACPI_BUS_ADD_START); device_init_wakeup(&device->dev, true); } @@ -1813,7 +1802,7 @@ static int acpi_bus_scan_fixed(void) result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_SLEEP_BUTTON, ACPI_STA_DEFAULT, - &ops); + ACPI_BUS_ADD_START); } return result; -- cgit v1.2.2 From 4002bf384cc567a843a7d16c95db54a7d77b16c6 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 21 Dec 2012 00:36:44 +0100 Subject: ACPI: Change the ordering of acpi_bus_check_add() If acpi_bus_check_add() is called for a handle already having an existing struct acpi_device object attached, it is not necessary to check the type and status of the device correspondig to it, so change the ordering of acpi_bus_check_add() to avoid that. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani --- drivers/acpi/scan.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 7082d11ce5d2..eb7ecb1f2032 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1582,6 +1582,10 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, acpi_status status; int result; + acpi_bus_get_device(handle, &device); + if (device) + goto out; + result = acpi_bus_type_and_status(handle, &type, &sta); if (result) return AE_OK; @@ -1598,18 +1602,14 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, return AE_CTRL_DEPTH; } - acpi_bus_get_device(handle, &device); - if (!device) { - acpi_add_single_object(&device, handle, type, sta, - ACPI_BUS_ADD_BASIC); - if (!device) - return AE_CTRL_DEPTH; + acpi_add_single_object(&device, handle, type, sta, ACPI_BUS_ADD_BASIC); + if (!device) + return AE_CTRL_DEPTH; - device->add_type = context ? - ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; - acpi_hot_add_bind(device); - } + device->add_type = context ? ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; + acpi_hot_add_bind(device); + out: if (!*return_value) *return_value = device; -- cgit v1.2.2 From 47525cda88f5cc4dbe24de1cc05617c08e2d7c4a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 21 Dec 2012 00:36:45 +0100 Subject: ACPI / PCI: Fold acpi_pci_root_start() into acpi_pci_root_add() Move the code from the ACPI PCI root bridge's .start() callback routine, acpi_pci_root_start(), directly into acpi_pci_root_add() and drop acpi_pci_root_start(). It is safe to do that, because it is now always guaranteed that when struct pci_dev objects are created, their companion struct acpi_device objects are already present, so it is not necessary to wait for them to be created before calling pci_bus_add_devices(). This change was previously proposed in a different form by Yinghai Lu. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani --- drivers/acpi/pci_root.c | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index a233fe93dfac..0e593a203ff8 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -47,7 +47,6 @@ ACPI_MODULE_NAME("pci_root"); #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" static int acpi_pci_root_add(struct acpi_device *device); static int acpi_pci_root_remove(struct acpi_device *device, int type); -static int acpi_pci_root_start(struct acpi_device *device); #define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \ | OSC_ACTIVE_STATE_PWR_SUPPORT \ @@ -67,7 +66,6 @@ static struct acpi_driver acpi_pci_root_driver = { .ops = { .add = acpi_pci_root_add, .remove = acpi_pci_root_remove, - .start = acpi_pci_root_start, }, }; @@ -453,6 +451,7 @@ static int acpi_pci_root_add(struct acpi_device *device) struct acpi_pci_root *root; acpi_handle handle; struct acpi_device *child; + struct acpi_pci_driver *driver; u32 flags, base_flags; bool is_osc_granted = false; @@ -632,24 +631,6 @@ static int acpi_pci_root_add(struct acpi_device *device) if (device->wakeup.flags.run_wake) device_set_run_wake(root->bus->bridge, true); - return 0; - -out_del_root: - mutex_lock(&acpi_pci_root_lock); - list_del(&root->node); - mutex_unlock(&acpi_pci_root_lock); - - acpi_pci_irq_del_prt(root->segment, root->secondary.start); -end: - kfree(root); - return result; -} - -static int acpi_pci_root_start(struct acpi_device *device) -{ - struct acpi_pci_root *root = acpi_driver_data(device); - struct acpi_pci_driver *driver; - if (system_state != SYSTEM_BOOTING) pci_assign_unassigned_bus_resources(root->bus); @@ -664,8 +645,17 @@ static int acpi_pci_root_start(struct acpi_device *device) pci_enable_bridges(root->bus); pci_bus_add_devices(root->bus); - return 0; + +out_del_root: + mutex_lock(&acpi_pci_root_lock); + list_del(&root->node); + mutex_unlock(&acpi_pci_root_lock); + + acpi_pci_irq_del_prt(root->segment, root->secondary.start); +end: + kfree(root); + return result; } static int acpi_pci_root_remove(struct acpi_device *device, int type) -- cgit v1.2.2 From 02f57c67a8677ae55dcdd256a2a7abaf41e4cc1f Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 21 Dec 2012 00:36:46 +0100 Subject: ACPI: Remove acpi_start_single_object() and acpi_bus_start() The ACPI PCI root bridge driver was the only ACPI driver implementing the .start() callback, which isn't used by any ACPI drivers any more now. For this reason, acpi_start_single_object() has no purpose any more, so remove it and all references to it. Also remove acpi_bus_start_device(), whose only purpose was to call acpi_start_single_object(). Moreover, since after the removal of acpi_bus_start_device() the only purpose of acpi_bus_start() remains to call acpi_update_all_gpes(), move that into acpi_bus_add() and drop acpi_bus_start() too, remove its header from acpi_bus.h and update all of its former users accordingly. This change was previously proposed in a different from by Yinghai Lu. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani --- drivers/acpi/container.c | 16 +++--------- drivers/acpi/scan.c | 66 ++++++------------------------------------------ 2 files changed, 11 insertions(+), 71 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 811910b50b75..98b85e3e4781 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -139,24 +139,14 @@ static int container_device_add(struct acpi_device **device, acpi_handle handle) { acpi_handle phandle; struct acpi_device *pdev; - int result; - - - if (acpi_get_parent(handle, &phandle)) { - return -ENODEV; - } - if (acpi_bus_get_device(phandle, &pdev)) { + if (acpi_get_parent(handle, &phandle)) return -ENODEV; - } - if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE)) { + if (acpi_bus_get_device(phandle, &pdev)) return -ENODEV; - } - - result = acpi_bus_start(*device); - return result; + return acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE); } static void container_notify_cb(acpi_handle handle, u32 type, void *context) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index eb7ecb1f2032..6321cab4e5ff 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -571,7 +571,6 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device) } static int acpi_bus_driver_init(struct acpi_device *, struct acpi_driver *); -static int acpi_start_single_object(struct acpi_device *); static int acpi_device_probe(struct device * dev) { struct acpi_device *acpi_dev = to_acpi_device(dev); @@ -580,9 +579,6 @@ static int acpi_device_probe(struct device * dev) ret = acpi_bus_driver_init(acpi_dev, acpi_drv); if (!ret) { - if (acpi_dev->add_type == ACPI_BUS_ADD_START) - acpi_start_single_object(acpi_dev); - if (acpi_drv->ops.notify) { ret = acpi_device_install_notify_handler(acpi_dev); if (ret) { @@ -761,24 +757,6 @@ acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver) return 0; } -static int acpi_start_single_object(struct acpi_device *device) -{ - int result = 0; - struct acpi_driver *driver; - - - if (!(driver = device->driver)) - return 0; - - if (driver->ops.start) { - result = driver->ops.start(device); - if (result && driver->ops.remove) - driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); - } - - return result; -} - /** * acpi_bus_register_driver - register a driver with the ACPI bus * @driver: driver being registered @@ -1673,59 +1651,31 @@ static int acpi_bus_scan(acpi_handle handle, bool start, } /* - * acpi_bus_add and acpi_bus_start + * acpi_bus_add * * scan a given ACPI tree and (probably recently hot-plugged) - * create and add or starts found devices. + * create and add found devices. * * If no devices were found -ENODEV is returned which does not * mean that this is a real error, there just have been no suitable * ACPI objects in the table trunk from which the kernel could create - * a device and add/start an appropriate driver. + * a device and add an appropriate driver. */ int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type) { - return acpi_bus_scan(handle, false, child); -} -EXPORT_SYMBOL(acpi_bus_add); - -static acpi_status acpi_bus_start_device(acpi_handle handle, u32 lvl, - void *not_used, void **ret_not_used) -{ - struct acpi_device *device; - unsigned long long sta_not_used; - int type_not_used; - - /* - * Ignore errors ignored by acpi_bus_check_add() to avoid terminating - * namespace walks prematurely. - */ - if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) - return AE_OK; - - if (acpi_bus_get_device(handle, &device)) - return AE_CTRL_DEPTH; - - return acpi_start_single_object(device); -} - -int acpi_bus_start(struct acpi_device *device) -{ - if (!device) - return -EINVAL; + int err; - if (ACPI_SUCCESS(acpi_start_single_object(device))) - acpi_walk_namespace(ACPI_TYPE_ANY, device->handle, - ACPI_UINT32_MAX, acpi_bus_start_device, - NULL, NULL, NULL); + err = acpi_bus_scan(handle, false, child); + if (err) + return err; acpi_update_all_gpes(); return 0; } -EXPORT_SYMBOL(acpi_bus_start); +EXPORT_SYMBOL(acpi_bus_add); int acpi_bus_trim(struct acpi_device *start, int rmdevice) { -- cgit v1.2.2 From 636458de36f1fb4cdd318387d2f45604e451b17a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 21 Dec 2012 00:36:47 +0100 Subject: ACPI: Remove the arguments of acpi_bus_add() that are not used Notice that acpi_bus_add() uses only 2 of its 4 arguments and redefine its header to match the body. Update all of its callers as necessary and observe that this leads to quite a number of removed lines of code (Linus will like that). Add a kerneldoc comment documenting acpi_bus_add() and wonder how its callers make wrong assumptions about the second argument (make note to self to take care of that later). Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani --- drivers/acpi/acpi_memhotplug.c | 19 +------------------ drivers/acpi/container.c | 16 +--------------- drivers/acpi/dock.c | 13 ++----------- drivers/acpi/processor_driver.c | 24 +----------------------- drivers/acpi/scan.c | 34 +++++++++++++++++++++------------- 5 files changed, 26 insertions(+), 80 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index eb30e5ab4cab..d0a7da704d49 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -157,34 +157,17 @@ static int acpi_memory_get_device(acpi_handle handle, struct acpi_memory_device **mem_device) { - acpi_status status; - acpi_handle phandle; struct acpi_device *device = NULL; - struct acpi_device *pdevice = NULL; int result; - if (!acpi_bus_get_device(handle, &device) && device) goto end; - status = acpi_get_parent(handle, &phandle); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Cannot find acpi parent")); - return -EINVAL; - } - - /* Get the parent device */ - result = acpi_bus_get_device(phandle, &pdevice); - if (result) { - acpi_handle_warn(phandle, "Cannot get acpi bus device\n"); - return -EINVAL; - } - /* * Now add the notified device. This creates the acpi_device * and invokes .add function */ - result = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE); + result = acpi_bus_add(handle, &device); if (result) { acpi_handle_warn(handle, "Cannot add acpi bus\n"); return -EINVAL; diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 98b85e3e4781..0688f83bc436 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -135,20 +135,6 @@ static int acpi_container_remove(struct acpi_device *device, int type) return status; } -static int container_device_add(struct acpi_device **device, acpi_handle handle) -{ - acpi_handle phandle; - struct acpi_device *pdev; - - if (acpi_get_parent(handle, &phandle)) - return -ENODEV; - - if (acpi_bus_get_device(phandle, &pdev)) - return -ENODEV; - - return acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE); -} - static void container_notify_cb(acpi_handle handle, u32 type, void *context) { struct acpi_device *device = NULL; @@ -180,7 +166,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) if (!ACPI_FAILURE(status) || device) break; - result = container_device_add(&device, handle); + result = acpi_bus_add(handle, &device); if (result) { acpi_handle_warn(handle, "Failed to add container\n"); break; diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index f32bd47b35e0..ff30582d2e1d 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -310,8 +310,6 @@ static int dock_present(struct dock_station *ds) static struct acpi_device * dock_create_acpi_device(acpi_handle handle) { struct acpi_device *device; - struct acpi_device *parent_device; - acpi_handle parent; int ret; if (acpi_bus_get_device(handle, &device)) { @@ -319,16 +317,9 @@ static struct acpi_device * dock_create_acpi_device(acpi_handle handle) * no device created for this object, * so we should create one. */ - acpi_get_parent(handle, &parent); - if (acpi_bus_get_device(parent, &parent_device)) - parent_device = NULL; - - ret = acpi_bus_add(&device, parent_device, handle, - ACPI_BUS_TYPE_DEVICE); - if (ret) { + ret = acpi_bus_add(handle, &device); + if (ret) pr_debug("error adding bus, %x\n", -ret); - return NULL; - } } return device; } diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index e83311bf1ebd..18b292e12b38 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -677,28 +677,6 @@ static int is_processor_present(acpi_handle handle) return 0; } -static -int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) -{ - acpi_handle phandle; - struct acpi_device *pdev; - - - if (acpi_get_parent(handle, &phandle)) { - return -ENODEV; - } - - if (acpi_bus_get_device(phandle, &pdev)) { - return -ENODEV; - } - - if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) { - return -ENODEV; - } - - return 0; -} - static void acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) { @@ -721,7 +699,7 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, if (!acpi_bus_get_device(handle, &device)) break; - result = acpi_processor_device_add(handle, &device); + result = acpi_bus_add(handle, &device); if (result) { acpi_handle_err(handle, "Unable to add the device\n"); break; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 6321cab4e5ff..25095bf57bba 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1650,25 +1650,33 @@ static int acpi_bus_scan(acpi_handle handle, bool start, return ret; } -/* - * acpi_bus_add +/** + * acpi_bus_add - Add ACPI device node objects in a given namespace scope. + * @handle: Root of the namespace scope to scan. + * @ret: Location to store a return struct acpi_device pointer. + * + * Scan a given ACPI tree (probably recently hot-plugged) and create and add + * found devices. * - * scan a given ACPI tree and (probably recently hot-plugged) - * create and add found devices. + * If no devices were found, -ENODEV is returned, but it does not mean that + * there has been a real error. There just have been no suitable ACPI objects + * in the table trunk from which the kernel could create a device and add an + * appropriate driver. * - * If no devices were found -ENODEV is returned which does not - * mean that this is a real error, there just have been no suitable - * ACPI objects in the table trunk from which the kernel could create - * a device and add an appropriate driver. + * If 0 is returned, the memory location pointed to by @ret will be populated + * with a pointer to a struct acpi_device created while scanning the namespace. + * If @handle corresponds to a device node, that will be a pointer to the struct + * acpi_device object corresponding to @handle. Otherwise, it will be a pointer + * to a struct acpi_device corresponding to one of its descendants. + * + * If an error code is returned, NULL will be stored in the memory location + * pointed to by @ret. */ - -int -acpi_bus_add(struct acpi_device **child, - struct acpi_device *parent, acpi_handle handle, int type) +int acpi_bus_add(acpi_handle handle, struct acpi_device **ret) { int err; - err = acpi_bus_scan(handle, false, child); + err = acpi_bus_scan(handle, false, ret); if (err) return err; -- cgit v1.2.2 From e3863094c6f9b2f980d6e7a5cad6b4d03a4dd579 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 21 Dec 2012 00:36:47 +0100 Subject: ACPI: Drop the second argument of acpi_bus_scan() After the removal of acpi_start_single_object() and acpi_bus_start() the second argument of acpi_bus_scan() is not necessary any more, so drop it and update acpi_bus_check_add() accordingly. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani --- drivers/acpi/scan.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 25095bf57bba..eb54f98bb728 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1551,8 +1551,8 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type, return 0; } -static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, - void *context, void **return_value) +static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, + void *not_used, void **return_value) { struct acpi_device *device = NULL; int type; @@ -1584,7 +1584,7 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, if (!device) return AE_CTRL_DEPTH; - device->add_type = context ? ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; + device->add_type = ACPI_BUS_ADD_START; acpi_hot_add_bind(device); out: @@ -1621,18 +1621,16 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, return status; } -static int acpi_bus_scan(acpi_handle handle, bool start, - struct acpi_device **child) +static int acpi_bus_scan(acpi_handle handle, struct acpi_device **child) { void *device = NULL; acpi_status status; int ret = -ENODEV; - status = acpi_bus_check_add(handle, 0, (void *)start, &device); + status = acpi_bus_check_add(handle, 0, NULL, &device); if (ACPI_SUCCESS(status)) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_check_add, NULL, (void *)start, - &device); + acpi_bus_check_add, NULL, NULL, &device); if (!device) goto out; @@ -1676,7 +1674,7 @@ int acpi_bus_add(acpi_handle handle, struct acpi_device **ret) { int err; - err = acpi_bus_scan(handle, false, ret); + err = acpi_bus_scan(handle, ret); if (err) return err; @@ -1782,7 +1780,7 @@ int __init acpi_scan_init(void) /* * Enumerate devices in the ACPI namespace. */ - result = acpi_bus_scan(ACPI_ROOT_OBJECT, true, &acpi_root); + result = acpi_bus_scan(ACPI_ROOT_OBJECT, &acpi_root); if (!result) result = acpi_bus_scan_fixed(); -- cgit v1.2.2 From 209d3b1743c8187c67cc75dbe9fefbcd3121fba0 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 21 Dec 2012 00:36:48 +0100 Subject: ACPI: Replace ACPI device add_type field with a match_driver flag After the removal of the second argument of acpi_bus_scan() there is no difference between the ACPI_BUS_ADD_MATCH and ACPI_BUS_ADD_START add types, so the add_type field in struct acpi_device may be replaced with a single flag. Do that calling the flag match_driver. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani --- drivers/acpi/scan.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index eb54f98bb728..e3aed481aed2 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -494,7 +494,7 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv) struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(drv); - return acpi_dev->add_type >= ACPI_BUS_ADD_MATCH + return acpi_dev->flags.match_driver && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } @@ -1410,8 +1410,7 @@ static void acpi_hot_add_bind(struct acpi_device *device) static int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, - unsigned long long sta, - enum acpi_bus_add_type add_type) + unsigned long long sta, bool match_driver) { int result; struct acpi_device *device; @@ -1427,7 +1426,6 @@ static int acpi_add_single_object(struct acpi_device **child, device->device_type = type; device->handle = handle; device->parent = acpi_bus_get_parent(handle); - device->add_type = add_type; STRUCT_TO_INT(device->status) = sta; acpi_device_get_busid(device); @@ -1478,9 +1476,10 @@ static int acpi_add_single_object(struct acpi_device **child, if ((result = acpi_device_set_context(device))) goto end; + device->flags.match_driver = match_driver; result = acpi_device_register(device); - if (device->add_type >= ACPI_BUS_ADD_MATCH) + if (device->flags.match_driver) acpi_hot_add_bind(device); end: @@ -1509,7 +1508,7 @@ static void acpi_bus_add_power_resource(acpi_handle handle) acpi_bus_get_device(handle, &device); if (!device) acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER, - ACPI_STA_DEFAULT, ACPI_BUS_ADD_START); + ACPI_STA_DEFAULT, true); } static int acpi_bus_type_and_status(acpi_handle handle, int *type, @@ -1580,11 +1579,11 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, return AE_CTRL_DEPTH; } - acpi_add_single_object(&device, handle, type, sta, ACPI_BUS_ADD_BASIC); + acpi_add_single_object(&device, handle, type, sta, false); if (!device) return AE_CTRL_DEPTH; - device->add_type = ACPI_BUS_ADD_START; + device->flags.match_driver = true; acpi_hot_add_bind(device); out: @@ -1749,16 +1748,14 @@ static int acpi_bus_scan_fixed(void) if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) { result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_POWER_BUTTON, - ACPI_STA_DEFAULT, - ACPI_BUS_ADD_START); + ACPI_STA_DEFAULT, true); device_init_wakeup(&device->dev, true); } if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) { result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_SLEEP_BUTTON, - ACPI_STA_DEFAULT, - ACPI_BUS_ADD_START); + ACPI_STA_DEFAULT, true); } return result; -- cgit v1.2.2 From 0cd6ac52b333f66ee64e50ed216ec99231092dcd Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 21 Dec 2012 00:36:49 +0100 Subject: ACPI: Make acpi_bus_scan() and acpi_bus_add() take only one argument The callers of acpi_bus_add() usually assume that if it has succeeded, then a struct acpi_device object has been attached to the handle passed as the first argument. Unfortunately, however, this assumption is wrong, because acpi_bus_scan(), and acpi_bus_add() too as a result, may return a pointer to a different struct acpi_device object on success (it may be an object corresponding to one of the descendant ACPI nodes in the namespace scope below that handle). For this reason, the callers of acpi_bus_add() who care about whether or not a struct acpi_device object has been created for its first argument need to check that using acpi_bus_get_device() anyway, so the second argument of acpi_bus_add() is not really useful for them. The same observation applies to acpi_bus_scan() executed directly from acpi_scan_init(). Therefore modify the relevant callers of acpi_bus_add() to check the existence of the struct acpi_device in question with the help of acpi_bus_get_device() and drop the no longer necessary second argument of acpi_bus_add(). Accordingly, modify acpi_scan_init() to use acpi_bus_get_device() to get acpi_root and drop the no longer needed second argument of acpi_bus_scan(). Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani --- drivers/acpi/acpi_memhotplug.c | 7 ++++++- drivers/acpi/container.c | 7 ++++++- drivers/acpi/dock.c | 4 +++- drivers/acpi/processor_driver.c | 8 ++++++-- drivers/acpi/scan.c | 38 +++++++++++--------------------------- 5 files changed, 32 insertions(+), 32 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index d0a7da704d49..327ab4459558 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -167,11 +167,16 @@ acpi_memory_get_device(acpi_handle handle, * Now add the notified device. This creates the acpi_device * and invokes .add function */ - result = acpi_bus_add(handle, &device); + result = acpi_bus_add(handle); if (result) { acpi_handle_warn(handle, "Cannot add acpi bus\n"); return -EINVAL; } + result = acpi_bus_get_device(handle, &device); + if (result) { + acpi_handle_warn(handle, "Missing device object\n"); + return -EINVAL; + } end: *mem_device = acpi_driver_data(device); diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 0688f83bc436..f8fb2281f34a 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -166,11 +166,16 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) if (!ACPI_FAILURE(status) || device) break; - result = acpi_bus_add(handle, &device); + result = acpi_bus_add(handle); if (result) { acpi_handle_warn(handle, "Failed to add container\n"); break; } + result = acpi_bus_get_device(handle, &device); + if (result) { + acpi_handle_warn(handle, "Missing device object\n"); + break; + } kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); ost_code = ACPI_OST_SC_SUCCESS; diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index ff30582d2e1d..9e31b2bd93d3 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -317,9 +317,11 @@ static struct acpi_device * dock_create_acpi_device(acpi_handle handle) * no device created for this object, * so we should create one. */ - ret = acpi_bus_add(handle, &device); + ret = acpi_bus_add(handle); if (ret) pr_debug("error adding bus, %x\n", -ret); + + acpi_bus_get_device(handle, &device); } return device; } diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 18b292e12b38..0777663f443e 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -699,12 +699,16 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, if (!acpi_bus_get_device(handle, &device)) break; - result = acpi_bus_add(handle, &device); + result = acpi_bus_add(handle); if (result) { acpi_handle_err(handle, "Unable to add the device\n"); break; } - + result = acpi_bus_get_device(handle, &device); + if (result) { + acpi_handle_err(handle, "Missing device object\n"); + break; + } ost_code = ACPI_OST_SC_SUCCESS; break; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index e3aed481aed2..3d44c705a3a2 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1620,37 +1620,27 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, return status; } -static int acpi_bus_scan(acpi_handle handle, struct acpi_device **child) +static int acpi_bus_scan(acpi_handle handle) { void *device = NULL; - acpi_status status; - int ret = -ENODEV; - status = acpi_bus_check_add(handle, 0, NULL, &device); - if (ACPI_SUCCESS(status)) + if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, acpi_bus_check_add, NULL, NULL, &device); if (!device) - goto out; + return -ENODEV; - ret = 0; - status = acpi_bus_device_attach(handle, 0, NULL, NULL); - if (ACPI_SUCCESS(status)) + if (ACPI_SUCCESS(acpi_bus_device_attach(handle, 0, NULL, NULL))) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, acpi_bus_device_attach, NULL, NULL, NULL); - out: - if (child) - *child = device; - - return ret; + return 0; } /** * acpi_bus_add - Add ACPI device node objects in a given namespace scope. * @handle: Root of the namespace scope to scan. - * @ret: Location to store a return struct acpi_device pointer. * * Scan a given ACPI tree (probably recently hot-plugged) and create and add * found devices. @@ -1659,21 +1649,12 @@ static int acpi_bus_scan(acpi_handle handle, struct acpi_device **child) * there has been a real error. There just have been no suitable ACPI objects * in the table trunk from which the kernel could create a device and add an * appropriate driver. - * - * If 0 is returned, the memory location pointed to by @ret will be populated - * with a pointer to a struct acpi_device created while scanning the namespace. - * If @handle corresponds to a device node, that will be a pointer to the struct - * acpi_device object corresponding to @handle. Otherwise, it will be a pointer - * to a struct acpi_device corresponding to one of its descendants. - * - * If an error code is returned, NULL will be stored in the memory location - * pointed to by @ret. */ -int acpi_bus_add(acpi_handle handle, struct acpi_device **ret) +int acpi_bus_add(acpi_handle handle) { int err; - err = acpi_bus_scan(handle, ret); + err = acpi_bus_scan(handle); if (err) return err; @@ -1777,8 +1758,11 @@ int __init acpi_scan_init(void) /* * Enumerate devices in the ACPI namespace. */ - result = acpi_bus_scan(ACPI_ROOT_OBJECT, &acpi_root); + result = acpi_bus_scan(ACPI_ROOT_OBJECT); + if (result) + return result; + result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root); if (!result) result = acpi_bus_scan_fixed(); -- cgit v1.2.2 From 11909ca1cf614f9396b17d366f9e3cfcba7b4a99 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 23 Dec 2012 00:02:13 +0100 Subject: ACPI: Add .setup() and .cleanup() callbacks to struct acpi_bus_type Add two new callbacks,.setup() and .cleanup(), struct acpi_bus_type and modify acpi_platform_notify() to call .setup() after executing acpi_bind_one() successfully and acpi_platform_notify_remove() to call .cleanup() before running acpi_unbind_one(). This will allow the users of struct acpi_bus_type, PCI in particular, to specify operations to be executed right after the given device has been associated with a companion struct acpi_device and right before it's going to be detached from that companion, respectively. The main motivation is to be able to get rid of acpi_pci_bind() and acpi_pci_unbind(), which are horrible horrible stuff. [In short, there are three problems with them: The way they populate the .bind() and .unbind() callbacks of ACPI devices is rather less than straightforward, they require special hotplug-specific paths to be present in the ACPI namespace scanning code and by the time acpi_pci_unbind() is called the PCI device object in question may not exist any more.] Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani --- drivers/acpi/glue.c | 50 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 15 deletions(-) (limited to 'drivers/acpi') 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) { struct acpi_bus_type *tmp, *ret = NULL; + if (!type) + return NULL; + down_read(&bus_type_sem); list_for_each_entry(tmp, &bus_type_list, list) { if (tmp->bus == type) { @@ -264,28 +267,39 @@ static int acpi_platform_notify(struct device *dev) { struct acpi_bus_type *type; acpi_handle handle; - int ret = -EINVAL; + int ret; ret = acpi_bind_one(dev, NULL); - if (!ret) - goto out; - - if (!dev->bus || !dev->parent) { + if (ret && (!dev->bus || !dev->parent)) { /* bridge devices genernally haven't bus or parent */ ret = acpi_find_bridge_device(dev, &handle); - goto end; + if (!ret) { + ret = acpi_bind_one(dev, handle); + if (ret) + goto out; + } } + type = acpi_get_bus_type(dev->bus); - if (!type) { - DBG("No ACPI bus support for %s\n", dev_name(dev)); - ret = -EINVAL; - goto end; + if (ret) { + if (!type || !type->find_device) { + DBG("No ACPI bus support for %s\n", dev_name(dev)); + ret = -EINVAL; + goto out; + } + + ret = type->find_device(dev, &handle); + if (ret) { + DBG("Unable to get handle for %s\n", dev_name(dev)); + goto out; + } + ret = acpi_bind_one(dev, handle); + if (ret) + goto out; } - if ((ret = type->find_device(dev, &handle)) != 0) - DBG("Can't get handler for %s\n", dev_name(dev)); - end: - if (!ret) - acpi_bind_one(dev, handle); + + if (type && type->setup) + type->setup(dev); out: #if ACPI_GLUE_DEBUG @@ -304,6 +318,12 @@ static int acpi_platform_notify(struct device *dev) static int acpi_platform_notify_remove(struct device *dev) { + struct acpi_bus_type *type; + + type = acpi_get_bus_type(dev->bus); + if (type && type->cleanup) + type->cleanup(dev); + acpi_unbind_one(dev); return 0; } -- cgit v1.2.2 From d2e5f0c16ad60a7208fd371233e63b73c990ece2 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 23 Dec 2012 00:02:44 +0100 Subject: ACPI / PCI: Rework the setup and cleanup of device wakeup Currently, the ACPI wakeup capability of PCI devices is set up in two different places, partially in acpi_pci_bind() where runtime wakeup is initialized and partially in platform_pci_wakeup_init(), where system wakeup is initialized. The cleanup is only done in acpi_pci_unbind() and it only covers runtime wakeup. Use the new .setup() and .cleanup() callbacks in struct acpi_bus_type to consolidate that code and do the setup and the cleanup each in one place. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani --- drivers/acpi/device_pm.c | 2 +- drivers/acpi/pci_bind.c | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index f09dc987cf17..e4f6ac95595c 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -353,7 +353,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable) * acpi_dev_pm_get_node - Get ACPI device node for the given physical device. * @dev: Device to get the ACPI node for. */ -static struct acpi_device *acpi_dev_pm_get_node(struct device *dev) +struct acpi_device *acpi_dev_pm_get_node(struct device *dev) { acpi_handle handle = DEVICE_ACPI_HANDLE(dev); struct acpi_device *adev; diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index a1dee29beed3..bbddcc9c894f 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c @@ -43,8 +43,6 @@ static int acpi_pci_unbind(struct acpi_device *device) if (!dev) goto out; - device_set_run_wake(&dev->dev, false); - pci_acpi_remove_pm_notifier(device); acpi_power_resource_unregister_device(&dev->dev, device->handle); if (!dev->subordinate) @@ -71,10 +69,7 @@ static int acpi_pci_bind(struct acpi_device *device) if (!dev) return 0; - pci_acpi_add_pm_notifier(device, dev); acpi_power_resource_register_device(&dev->dev, device->handle); - if (device->wakeup.flags.run_wake) - device_set_run_wake(&dev->dev, true); /* * Install the 'bind' function to facilitate callbacks for -- cgit v1.2.2 From 38a9a67a281eeebcd7cccf87f0e371f58ae625e3 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 23 Dec 2012 00:02:54 +0100 Subject: ACPI / PCI: Move the _PRT setup and cleanup code to pci-acpi.c Move the code related to _PRT setup and removal and to power resources from acpi_pci_bind() and acpi_pci_unbind() to the .setup() and .cleanup() callbacks in acpi_pci_bus and remove acpi_pci_bind() and acpi_pci_unbind() that have no purpose any more. Accordingly, remove the code related to device .bind() and .unbind() operations from the ACPI PCI root bridge driver. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani --- drivers/acpi/Makefile | 2 +- drivers/acpi/pci_bind.c | 117 ------------------------------------------------ drivers/acpi/pci_root.c | 31 ------------- 3 files changed, 1 insertion(+), 149 deletions(-) delete mode 100644 drivers/acpi/pci_bind.c (limited to 'drivers/acpi') diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 2a4502becd13..4ee2e753306a 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -37,7 +37,7 @@ acpi-y += resource.o acpi-y += processor_core.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o -acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o +acpi-y += pci_root.o pci_link.o pci_irq.o acpi-y += acpi_platform.o acpi-y += power.o acpi-y += event.o diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c deleted file mode 100644 index bbddcc9c894f..000000000000 --- a/drivers/acpi/pci_bind.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * pci_bind.c - ACPI PCI Device Binding ($Revision: 2 $) - * - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_PCI_COMPONENT -ACPI_MODULE_NAME("pci_bind"); - -static int acpi_pci_unbind(struct acpi_device *device) -{ - struct pci_dev *dev; - - dev = acpi_get_pci_dev(device->handle); - if (!dev) - goto out; - - acpi_power_resource_unregister_device(&dev->dev, device->handle); - - if (!dev->subordinate) - goto out; - - acpi_pci_irq_del_prt(pci_domain_nr(dev->bus), dev->subordinate->number); - - device->ops.bind = NULL; - device->ops.unbind = NULL; - -out: - pci_dev_put(dev); - return 0; -} - -static int acpi_pci_bind(struct acpi_device *device) -{ - acpi_status status; - acpi_handle handle; - unsigned char bus; - struct pci_dev *dev; - - dev = acpi_get_pci_dev(device->handle); - if (!dev) - return 0; - - acpi_power_resource_register_device(&dev->dev, device->handle); - - /* - * Install the 'bind' function to facilitate callbacks for - * children of the P2P bridge. - */ - if (dev->subordinate) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Device %04x:%02x:%02x.%d is a PCI bridge\n", - pci_domain_nr(dev->bus), dev->bus->number, - PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn))); - device->ops.bind = acpi_pci_bind; - device->ops.unbind = acpi_pci_unbind; - } - - /* - * Evaluate and parse _PRT, if exists. This code allows parsing of - * _PRT objects within the scope of non-bridge devices. Note that - * _PRTs within the scope of a PCI bridge assume the bridge's - * subordinate bus number. - * - * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? - */ - status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); - if (ACPI_FAILURE(status)) - goto out; - - if (dev->subordinate) - bus = dev->subordinate->number; - else - bus = dev->bus->number; - - acpi_pci_irq_add_prt(device->handle, pci_domain_nr(dev->bus), bus); - -out: - pci_dev_put(dev); - return 0; -} - -int acpi_pci_bind_root(struct acpi_device *device) -{ - device->ops.bind = acpi_pci_bind; - device->ops.unbind = acpi_pci_unbind; - - return 0; -} diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 0e593a203ff8..22a8458b4ec9 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -186,21 +186,6 @@ static acpi_status try_get_root_bridge_busnr(acpi_handle handle, return AE_OK; } -static void acpi_pci_bridge_scan(struct acpi_device *device) -{ - int status; - struct acpi_device *child = NULL; - - if (device->flags.bus_address) - if (device->parent && device->parent->ops.bind) { - status = device->parent->ops.bind(device); - if (!status) { - list_for_each_entry(child, &device->children, node) - acpi_pci_bridge_scan(child); - } - } -} - static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766"; static acpi_status acpi_pci_run_osc(acpi_handle handle, @@ -450,7 +435,6 @@ static int acpi_pci_root_add(struct acpi_device *device) int result; struct acpi_pci_root *root; acpi_handle handle; - struct acpi_device *child; struct acpi_pci_driver *driver; u32 flags, base_flags; bool is_osc_granted = false; @@ -602,21 +586,6 @@ static int acpi_pci_root_add(struct acpi_device *device) goto out_del_root; } - /* - * Attach ACPI-PCI Context - * ----------------------- - * Thus binding the ACPI and PCI devices. - */ - result = acpi_pci_bind_root(device); - if (result) - goto out_del_root; - - /* - * Scan and bind all _ADR-Based Devices - */ - list_for_each_entry(child, &device->children, node) - acpi_pci_bridge_scan(child); - /* ASPM setting */ if (is_osc_granted) { if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) -- cgit v1.2.2 From 3eec5f7a1955ead549020ec2f60235ea6a4a2252 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 23 Dec 2012 00:03:03 +0100 Subject: ACPI: Drop ACPI device .bind() and .unbind() callbacks Drop the .bind() and .unbind() that have no more users from struct acpi_device_ops and remove all of the code referring to them from drivers/acpi/scan.c. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani --- drivers/acpi/scan.c | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 3d44c705a3a2..f8a0d0f7d197 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1385,29 +1385,11 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) if (!rmdevice) return 0; - /* - * unbind _ADR-Based Devices when hot removal - */ - if (dev->flags.bus_address) { - if ((dev->parent) && (dev->parent->ops.unbind)) - dev->parent->ops.unbind(dev); - } acpi_device_unregister(dev, ACPI_BUS_REMOVAL_EJECT); return 0; } -/* - * acpi_hot_add_bind - Bind _ADR-based devices on hot-add. - * @device: ACPI device node to bind. - */ -static void acpi_hot_add_bind(struct acpi_device *device) -{ - if (device->flags.bus_address - && device->parent && device->parent->ops.bind) - device->parent->ops.bind(device); -} - static int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, unsigned long long sta, bool match_driver) @@ -1479,9 +1461,6 @@ static int acpi_add_single_object(struct acpi_device **child, device->flags.match_driver = match_driver; result = acpi_device_register(device); - if (device->flags.match_driver) - acpi_hot_add_bind(device); - end: if (!result) { acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); @@ -1584,7 +1563,6 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, return AE_CTRL_DEPTH; device->flags.match_driver = true; - acpi_hot_add_bind(device); out: if (!*return_value) -- cgit v1.2.2 From f95988de06ea62ef5bd861f06e9ef56cea405ed1 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 7 Jan 2013 21:17:02 +0100 Subject: ACPI / scan: Treat power resources in a special way Commit 805d410 (ACPI: Separate adding ACPI device objects from probing ACPI drivers) introduced an ACPI power resources management regression, because it didn't ensure that the power resources driver bind to the struct acpi_device objects corresponding to power resources as soon as they were created. As a result, ACPI power management routines may attempt to access power resource objects before they are ready to use. To fix this problem, tell the acpi_add_single_object() in acpi_bus_check_add() to probe the driver for objects of type ACPI_BUS_TYPE_POWER. This fix has been verified to work on HP nx6325 where the problem was first observed. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani --- drivers/acpi/scan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f8a0d0f7d197..e380345b643a 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1558,7 +1558,8 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, return AE_CTRL_DEPTH; } - acpi_add_single_object(&device, handle, type, sta, false); + acpi_add_single_object(&device, handle, type, sta, + type == ACPI_BUS_TYPE_POWER); if (!device) return AE_CTRL_DEPTH; -- cgit v1.2.2