diff options
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 221 |
1 files changed, 110 insertions, 111 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a184529d8fa4..a22778e880c2 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -479,9 +479,8 @@ static void acpi_device_del(struct acpi_device *device) list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) if (!strcmp(acpi_device_bus_id->bus_id, acpi_device_hid(device))) { - if (acpi_device_bus_id->instance_no > 0) - acpi_device_bus_id->instance_no--; - else { + ida_simple_remove(&acpi_device_bus_id->instance_ida, device->pnp.instance_no); + if (ida_is_empty(&acpi_device_bus_id->instance_ida)) { list_del(&acpi_device_bus_id->node); kfree_const(acpi_device_bus_id->bus_id); kfree(acpi_device_bus_id); @@ -531,7 +530,7 @@ static void acpi_device_del_work_fn(struct work_struct *work_not_used) * used by the device. */ acpi_power_transition(adev, ACPI_STATE_D3_COLD); - put_device(&adev->dev); + acpi_dev_put(adev); } } @@ -561,7 +560,7 @@ static void acpi_scan_drop_device(acpi_handle handle, void *context) * prevents attempts to register device objects identical to those being * deleted from happening concurrently (such attempts result from * hotplug events handled via the ACPI hotplug workqueue). It also will - * run after all of the work items submitted previosuly, which helps + * run after all of the work items submitted previously, which helps * those work items to ensure that they are not accessing stale device * objects. */ @@ -605,8 +604,7 @@ EXPORT_SYMBOL(acpi_bus_get_device); static void get_acpi_device(void *dev) { - if (dev) - get_device(&((struct acpi_device *)dev)->dev); + acpi_dev_get(dev); } struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle) @@ -616,7 +614,7 @@ struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle) void acpi_bus_put_acpi_device(struct acpi_device *adev) { - put_device(&adev->dev); + acpi_dev_put(adev); } static struct acpi_device_bus_id *acpi_device_bus_id_match(const char *dev_id) @@ -631,6 +629,21 @@ static struct acpi_device_bus_id *acpi_device_bus_id_match(const char *dev_id) return NULL; } +static int acpi_device_set_name(struct acpi_device *device, + struct acpi_device_bus_id *acpi_device_bus_id) +{ + struct ida *instance_ida = &acpi_device_bus_id->instance_ida; + int result; + + result = ida_simple_get(instance_ida, 0, ACPI_MAX_DEVICE_INSTANCES, GFP_KERNEL); + if (result < 0) + return result; + + device->pnp.instance_no = result; + dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, result); + return 0; +} + int acpi_device_add(struct acpi_device *device, void (*release)(struct device *)) { @@ -665,7 +678,9 @@ int acpi_device_add(struct acpi_device *device, acpi_device_bus_id = acpi_device_bus_id_match(acpi_device_hid(device)); if (acpi_device_bus_id) { - acpi_device_bus_id->instance_no++; + result = acpi_device_set_name(device, acpi_device_bus_id); + if (result) + goto err_unlock; } else { acpi_device_bus_id = kzalloc(sizeof(*acpi_device_bus_id), GFP_KERNEL); @@ -681,9 +696,16 @@ int acpi_device_add(struct acpi_device *device, goto err_unlock; } + ida_init(&acpi_device_bus_id->instance_ida); + + result = acpi_device_set_name(device, acpi_device_bus_id); + if (result) { + kfree(acpi_device_bus_id); + goto err_unlock; + } + list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list); } - dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no); if (device->parent) list_add_tail(&device->node, &device->parent->children); @@ -734,27 +756,25 @@ static bool acpi_info_matches_ids(struct acpi_device_info *info, const char * const ids[]) { struct acpi_pnp_device_id_list *cid_list = NULL; - int i; + int i, index; if (!(info->valid & ACPI_VALID_HID)) return false; + index = match_string(ids, -1, info->hardware_id.string); + if (index >= 0) + return true; + if (info->valid & ACPI_VALID_CID) cid_list = &info->compatible_id_list; - for (i = 0; ids[i]; i++) { - int j; + if (!cid_list) + return false; - if (!strcmp(info->hardware_id.string, ids[i])) + for (i = 0; i < cid_list->count; i++) { + index = match_string(ids, -1, cid_list->ids[i].string); + if (index >= 0) return true; - - if (!cid_list) - continue; - - for (j = 0; j < cid_list->count; j++) { - if (!strcmp(cid_list->ids[j].string, ids[i])) - return true; - } } return false; @@ -1284,8 +1304,9 @@ static bool acpi_object_is_system_bus(acpi_handle handle) } static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, - int device_type, struct acpi_device_info *info) + int device_type) { + struct acpi_device_info *info = NULL; struct acpi_pnp_device_id_list *cid_list; int i; @@ -1296,6 +1317,7 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, break; } + acpi_get_object_info(handle, &info); if (!info) { pr_err(PREFIX "%s: Error reading device info\n", __func__); @@ -1321,6 +1343,8 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, if (info->valid & ACPI_VALID_CLS) acpi_add_id(pnp, info->class_code.string); + kfree(info); + /* * Some devices don't reliably have _HIDs & _CIDs, so add * synthetic HIDs to make sure drivers can find them. @@ -1626,17 +1650,16 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device) } void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, - int type, unsigned long long sta, - struct acpi_device_info *info) + int type) { INIT_LIST_HEAD(&device->pnp.ids); device->device_type = type; device->handle = handle; device->parent = acpi_bus_get_parent(handle); fwnode_init(&device->fwnode, &acpi_device_fwnode_ops); - acpi_set_device_status(device, sta); + acpi_set_device_status(device, ACPI_STA_DEFAULT); acpi_device_get_busid(device); - acpi_set_pnp_ids(handle, &device->pnp, type, info); + acpi_set_pnp_ids(handle, &device->pnp, type); acpi_init_properties(device); acpi_bus_get_flags(device); device->flags.match_driver = false; @@ -1647,6 +1670,8 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, device_initialize(&device->dev); dev_set_uevent_suppress(&device->dev, true); acpi_init_coherency(device); + /* Assume there are unmet deps to start with. */ + device->dep_unmet = 1; } void acpi_device_add_finalize(struct acpi_device *device) @@ -1655,33 +1680,30 @@ void acpi_device_add_finalize(struct acpi_device *device) kobject_uevent(&device->dev.kobj, KOBJ_ADD); } +static void acpi_scan_init_status(struct acpi_device *adev) +{ + if (acpi_bus_get_status(adev)) + acpi_set_device_status(adev, 0); +} + static int acpi_add_single_object(struct acpi_device **child, - acpi_handle handle, int type, - unsigned long long sta) + acpi_handle handle, int type) { - struct acpi_device_info *info = NULL; struct acpi_device *device; int result; - if (handle != ACPI_ROOT_OBJECT && type == ACPI_BUS_TYPE_DEVICE) - acpi_get_object_info(handle, &info); - device = kzalloc(sizeof(struct acpi_device), GFP_KERNEL); - if (!device) { - kfree(info); + if (!device) return -ENOMEM; - } - acpi_init_device_object(device, handle, type, sta, info); - kfree(info); + acpi_init_device_object(device, handle, type); /* - * For ACPI_BUS_TYPE_DEVICE getting the status is delayed till here so - * that we can call acpi_bus_get_status() and use its quirk handling. - * Note this must be done before the get power-/wakeup_dev-flags calls. + * Getting the status is delayed till here so that we can call + * acpi_bus_get_status() and use its quirk handling. Note that + * this must be done before the get power-/wakeup_dev-flags calls. */ - if (type == ACPI_BUS_TYPE_DEVICE) - if (acpi_bus_get_status(device) < 0) - acpi_set_device_status(device, 0); + if (type == ACPI_BUS_TYPE_DEVICE || type == ACPI_BUS_TYPE_PROCESSOR) + acpi_scan_init_status(device); acpi_bus_get_power_flags(device); acpi_bus_get_wakeup_device_flags(device); @@ -1738,50 +1760,6 @@ static bool acpi_device_should_be_hidden(acpi_handle handle) return true; } -static int acpi_bus_type_and_status(acpi_handle handle, int *type, - unsigned long long *sta) -{ - acpi_status status; - acpi_object_type acpi_type; - - status = acpi_get_type(handle, &acpi_type); - if (ACPI_FAILURE(status)) - return -ENODEV; - - switch (acpi_type) { - case ACPI_TYPE_ANY: /* for ACPI_ROOT_OBJECT */ - case ACPI_TYPE_DEVICE: - if (acpi_device_should_be_hidden(handle)) - return -ENODEV; - - *type = ACPI_BUS_TYPE_DEVICE; - /* - * acpi_add_single_object updates this once we've an acpi_device - * so that acpi_bus_get_status' quirk handling can be used. - */ - *sta = ACPI_STA_DEFAULT; - break; - case ACPI_TYPE_PROCESSOR: - *type = ACPI_BUS_TYPE_PROCESSOR; - status = acpi_bus_get_status_handle(handle, sta); - if (ACPI_FAILURE(status)) - return -ENODEV; - break; - case ACPI_TYPE_THERMAL: - *type = ACPI_BUS_TYPE_THERMAL; - *sta = ACPI_STA_DEFAULT; - break; - case ACPI_TYPE_POWER: - *type = ACPI_BUS_TYPE_POWER; - *sta = ACPI_STA_DEFAULT; - break; - default: - return -ENODEV; - } - - return 0; -} - bool acpi_device_is_present(const struct acpi_device *adev) { return adev->status.present || adev->status.functional; @@ -1850,7 +1828,7 @@ static void acpi_scan_init_hotplug(struct acpi_device *adev) } } -static u32 acpi_scan_check_dep(acpi_handle handle) +static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep) { struct acpi_handle_list dep_devices; acpi_status status; @@ -1863,7 +1841,8 @@ static u32 acpi_scan_check_dep(acpi_handle handle) * 2. ACPI nodes describing USB ports. * Still, checking for _HID catches more then just these cases ... */ - if (!acpi_has_method(handle, "_DEP") || !acpi_has_method(handle, "_HID")) + if (!check_dep || !acpi_has_method(handle, "_DEP") || + !acpi_has_method(handle, "_HID")) return 0; status = acpi_evaluate_reference(handle, "_DEP", NULL, &dep_devices); @@ -1910,6 +1889,8 @@ static void acpi_scan_dep_init(struct acpi_device *adev) { struct acpi_dep_data *dep; + adev->dep_unmet = 0; + mutex_lock(&acpi_dep_list_lock); list_for_each_entry(dep, &acpi_dep_list, node) { @@ -1926,38 +1907,59 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep, struct acpi_device **adev_p) { struct acpi_device *device = NULL; - unsigned long long sta; + acpi_object_type acpi_type; int type; - int result; acpi_bus_get_device(handle, &device); if (device) goto out; - result = acpi_bus_type_and_status(handle, &type, &sta); - if (result) + if (ACPI_FAILURE(acpi_get_type(handle, &acpi_type))) return AE_OK; - if (type == ACPI_BUS_TYPE_POWER) { - acpi_add_power_resource(handle); - return AE_OK; - } + switch (acpi_type) { + case ACPI_TYPE_DEVICE: + if (acpi_device_should_be_hidden(handle)) + return AE_OK; - if (type == ACPI_BUS_TYPE_DEVICE && check_dep) { - u32 count = acpi_scan_check_dep(handle); - /* Bail out if the number of recorded dependencies is not 0. */ - if (count > 0) { + /* Bail out if there are dependencies. */ + if (acpi_scan_check_dep(handle, check_dep) > 0) { acpi_bus_scan_second_pass = true; return AE_CTRL_DEPTH; } + + fallthrough; + case ACPI_TYPE_ANY: /* for ACPI_ROOT_OBJECT */ + type = ACPI_BUS_TYPE_DEVICE; + break; + + case ACPI_TYPE_PROCESSOR: + type = ACPI_BUS_TYPE_PROCESSOR; + break; + + case ACPI_TYPE_THERMAL: + type = ACPI_BUS_TYPE_THERMAL; + break; + + case ACPI_TYPE_POWER: + acpi_add_power_resource(handle); + fallthrough; + default: + return AE_OK; } - acpi_add_single_object(&device, handle, type, sta); + acpi_add_single_object(&device, handle, type); if (!device) return AE_CTRL_DEPTH; acpi_scan_init_hotplug(device); - if (!check_dep) + /* + * If check_dep is true at this point, the device has no dependencies, + * or the creation of the device object would have been postponed above. + */ + if (check_dep) + device->dep_unmet = 0; + else acpi_scan_dep_init(device); out: @@ -2220,8 +2222,7 @@ int acpi_bus_register_early_device(int type) struct acpi_device *device = NULL; int result; - result = acpi_add_single_object(&device, NULL, - type, ACPI_STA_DEFAULT); + result = acpi_add_single_object(&device, NULL, type); if (result) return result; @@ -2241,8 +2242,7 @@ static int acpi_bus_scan_fixed(void) struct acpi_device *device = NULL; result = acpi_add_single_object(&device, NULL, - ACPI_BUS_TYPE_POWER_BUTTON, - ACPI_STA_DEFAULT); + ACPI_BUS_TYPE_POWER_BUTTON); if (result) return result; @@ -2258,8 +2258,7 @@ static int acpi_bus_scan_fixed(void) struct acpi_device *device = NULL; result = acpi_add_single_object(&device, NULL, - ACPI_BUS_TYPE_SLEEP_BUTTON, - ACPI_STA_DEFAULT); + ACPI_BUS_TYPE_SLEEP_BUTTON); if (result) return result; @@ -2355,7 +2354,7 @@ int __init acpi_scan_init(void) acpi_detach_data(acpi_root->handle, acpi_scan_drop_device); acpi_device_del(acpi_root); - put_device(&acpi_root->dev); + acpi_bus_put_acpi_device(acpi_root); goto out; } } |