From: Rafael J. Wysocki Date: Wed, 29 Jan 2014 10:47:18 +0000 (+0100) Subject: Merge branches 'acpi-processor', 'acpi-hotplug', 'acpi-init', 'acpi-pm' and 'acpica' X-Git-Url: http://pileus.org/git/?p=~andy%2Flinux;a=commitdiff_plain;h=82e180598b54873553fb1d285fb0c90fc54f8f23;hp=-c Merge branches 'acpi-processor', 'acpi-hotplug', 'acpi-init', 'acpi-pm' and 'acpica' * acpi-processor: ACPI / scan: reduce log level of "ACPI: \_PR_.CPU4: failed to get CPU APIC ID" ACPI / processor: Return specific error value when mapping lapic id * acpi-hotplug: ACPI / scan: Clear match_driver flag in acpi_bus_trim() * acpi-init: ACPI / init: Flag use of ACPI and ACPI idioms for power supplies to regulator API * acpi-pm: ACPI / PM: Use ACPI_COMPANION() to get ACPI companions of devices * acpica: ACPICA: Remove bool usage from ACPICA. --- 82e180598b54873553fb1d285fb0c90fc54f8f23 diff --combined drivers/acpi/acpi_processor.c index c9311be29a6,21c0856daad,d58a2aba093,3c1d6b0c09a,3c1d6b0c09a,3c1d6b0c09a..c29c2c3ec0a --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@@@@@@ -212,7 -212,7 -212,7 -212,7 -212,7 -212,7 +212,7 @@@@@@@ static int acpi_processor_get_info(stru union acpi_object object = { 0 }; struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; struct acpi_processor *pr = acpi_driver_data(device); ---- int cpu_index, device_declaration = 0; ++++ int apic_id, cpu_index, device_declaration = 0; acpi_status status = AE_OK; static int cpu0_initialized; unsigned long long value; @@@@@@@ -258,21 -258,21 -258,18 -258,18 -258,18 -258,18 +258,21 @@@@@@@ device_declaration = 1; pr->acpi_id = value; } ---- pr->apic_id = acpi_get_apicid(pr->handle, device_declaration, ---- pr->acpi_id); ---- cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id); ---- /* Handle UP system running SMP kernel, with no LAPIC in MADT */ ---- if (!cpu0_initialized && (cpu_index == -1) && ---- (num_online_cpus() == 1)) { ---- cpu_index = 0; ++++ apic_id = acpi_get_apicid(pr->handle, device_declaration, pr->acpi_id); ++++ if (apic_id < 0) { - acpi_handle_err(pr->handle, "failed to get CPU APIC ID.\n"); + ++++ acpi_handle_debug(pr->handle, "failed to get CPU APIC ID.\n"); ++++ return -ENODEV; } ++++ pr->apic_id = apic_id; ---- cpu0_initialized = 1; ---- ++++ cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id); ++++ if (!cpu0_initialized) { ++++ cpu0_initialized = 1; ++++ /* Handle UP system running SMP kernel, with no LAPIC in MADT */ ++++ if ((cpu_index == -1) && (num_online_cpus() == 1)) ++++ cpu_index = 0; ++++ } pr->id = cpu_index; /* @@@@@@@ -285,7 -285,7 -282,6 -282,6 -282,6 -282,6 +285,7 @@@@@@@ if (ret) return ret; } ++++ /* * On some boxes several processors use the same processor bus id. * But they are located in different scope. For example: @@@@@@@ -399,7 -399,7 -395,7 -395,7 -395,7 -395,7 +399,7 @@@@@@@ static int acpi_processor_add(struct ac goto err; } - --- result = acpi_bind_one(dev, pr->handle); + +++ result = acpi_bind_one(dev, device); if (result) goto err; diff --combined drivers/acpi/bus.c index 384da5ab595,0710004055c,384da5ab595,296bec89f4a,0710004055c,0710004055c..fcb59c21c68 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@@@@@@ -33,10 -33,12 -33,10 -33,13 -33,12 -33,12 +33,11 @@@@@@@ #include #include #include +++ ++#include #ifdef CONFIG_X86 #include #endif #include - ---#include - ---#include #include #include #include @@@@@@@ -50,6 -52,9 -50,6 -53,9 -52,9 -52,9 +51,6 @@@@@@@ struct acpi_device *acpi_root struct proc_dir_entry *acpi_root_dir; EXPORT_SYMBOL(acpi_root_dir); - ---#define STRUCT_TO_INT(s) (*((int*)&s)) - --- - --- #ifdef CONFIG_X86 static int set_copy_dsdt(const struct dmi_system_id *id) { @@@@@@@ -110,16 -115,18 -110,16 -116,18 -115,18 -115,18 +111,16 @@@@@@@ int acpi_bus_get_status(struct acpi_dev if (ACPI_FAILURE(status)) return -ENODEV; - --- STRUCT_TO_INT(device->status) = (int) sta; + +++ acpi_set_device_status(device, sta); if (device->status.functional && !device->status.present) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]: " "functional but not present;\n", - --- device->pnp.bus_id, - --- (u32) STRUCT_TO_INT(device->status))); + +++ device->pnp.bus_id, (u32)sta)); } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n", - --- device->pnp.bus_id, - --- (u32) STRUCT_TO_INT(device->status))); + +++ device->pnp.bus_id, (u32)sta)); return 0; } EXPORT_SYMBOL(acpi_bus_get_status); @@@@@@@ -332,6 -339,58 -332,6 -340,58 -339,58 -339,58 +333,6 @@@@@@@ static void acpi_bus_osc_support(void Notification Handling -------------------------------------------------------------------------- */ - ---static void acpi_bus_check_device(acpi_handle handle) - ---{ - --- struct acpi_device *device; - --- acpi_status status; - --- struct acpi_device_status old_status; - --- - --- if (acpi_bus_get_device(handle, &device)) - --- return; - --- if (!device) - --- return; - --- - --- old_status = device->status; - --- - --- /* - --- * Make sure this device's parent is present before we go about - --- * messing with the device. - --- */ - --- if (device->parent && !device->parent->status.present) { - --- device->status = device->parent->status; - --- return; - --- } - --- - --- status = acpi_bus_get_status(device); - --- if (ACPI_FAILURE(status)) - --- return; - --- - --- if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status)) - --- return; - --- - --- /* - --- * Device Insertion/Removal - --- */ - --- if ((device->status.present) && !(old_status.present)) { - --- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n")); - --- /* TBD: Handle device insertion */ - --- } else if (!(device->status.present) && (old_status.present)) { - --- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n")); - --- /* TBD: Handle device removal */ - --- } - ---} - --- - ---static void acpi_bus_check_scope(acpi_handle handle) - ---{ - --- /* Status Change? */ - --- acpi_bus_check_device(handle); - --- - --- /* - --- * TBD: Enumerate child devices within this device's scope and - --- * run acpi_bus_check_device()'s on them. - --- */ - ---} - --- /** * acpi_bus_notify * --------------- @@@@@@@ -348,11 -407,19 -348,11 -408,19 -407,19 -407,19 +349,11 @@@@@@@ static void acpi_bus_notify(acpi_handl switch (type) { case ACPI_NOTIFY_BUS_CHECK: - --- acpi_bus_check_scope(handle); - --- /* - --- * TBD: We'll need to outsource certain events to non-ACPI - --- * drivers via the device manager (device.c). - --- */ + +++ /* TBD */ break; case ACPI_NOTIFY_DEVICE_CHECK: - --- acpi_bus_check_device(handle); - --- /* - --- * TBD: We'll need to outsource certain events to non-ACPI - --- * drivers via the device manager (device.c). - --- */ + +++ /* TBD */ break; case ACPI_NOTIFY_DEVICE_WAKE: @@@@@@@ -509,6 -576,6 -509,6 -577,14 -576,6 -576,6 +510,14 @@@@@@@ void __init acpi_early_init(void goto error0; } +++ ++ /* +++ ++ * If the system is using ACPI then we can be reasonably +++ ++ * confident that any regulators are managed by the firmware +++ ++ * so tell the regulator core it has everything it needs to +++ ++ * know. +++ ++ */ +++ ++ regulator_has_full_constraints(); +++ ++ return; error0: diff --combined drivers/acpi/device_pm.c index d49f1e46470,b3480cf7db1,d49f1e46470,b3480cf7db1,c14aa9a8a1b,b3480cf7db1..c14a00d3dca --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@@@@@@ -256,8 -256,6 -256,8 -256,6 -256,6 -256,6 +256,8 @@@@@@@ int acpi_bus_init_power(struct acpi_dev return -EINVAL; device->power.state = ACPI_STATE_UNKNOWN; + +++ if (!acpi_device_is_present(device)) + +++ return 0; result = acpi_device_get_power(device, &state); if (result) @@@@@@@ -304,18 -302,15 -304,18 -302,15 -302,15 -302,15 +304,18 @@@@@@@ int acpi_device_fix_up_power(struct acp return ret; } - ---int acpi_bus_update_power(acpi_handle handle, int *state_p) + +++int acpi_device_update_power(struct acpi_device *device, int *state_p) { - --- struct acpi_device *device; int state; int result; - --- result = acpi_bus_get_device(handle, &device); - --- if (result) + +++ if (device->power.state == ACPI_STATE_UNKNOWN) { + +++ result = acpi_bus_init_power(device); + +++ if (!result && state_p) + +++ *state_p = device->power.state; + +++ return result; + +++ } result = acpi_device_get_power(device, &state); if (result) @@@@@@@ -343,15 -338,6 -343,15 -338,6 -338,6 -338,6 +343,15 @@@@@@@ return 0; } + +++ + +++int acpi_bus_update_power(acpi_handle handle, int *state_p) + +++{ + +++ struct acpi_device *device; + +++ int result; + +++ + +++ result = acpi_bus_get_device(handle, &device); + +++ return result ? result : acpi_device_update_power(device, state_p); + +++} EXPORT_SYMBOL_GPL(acpi_bus_update_power); bool acpi_bus_power_manageable(acpi_handle handle) @@@@@@@ -726,18 -712,18 -726,18 -712,18 -712,6 -712,18 +726,6 @@@@@@@ int acpi_pm_device_sleep_wake(struct de } #endif /* CONFIG_PM_SLEEP */ ---- -/** ---- - * acpi_dev_pm_get_node - Get ACPI device node for the given physical device. ---- - * @dev: Device to get the ACPI node for. ---- - */ ---- -struct acpi_device *acpi_dev_pm_get_node(struct device *dev) ---- -{ ---- - acpi_handle handle = ACPI_HANDLE(dev); ---- - struct acpi_device *adev; ---- - ---- - return handle && !acpi_bus_get_device(handle, &adev) ? adev : NULL; ---- -} ---- - /** * acpi_dev_pm_low_power - Put ACPI device into a low-power state. * @dev: Device to put into a low-power state. @@@@@@@ -778,7 -764,7 -778,7 -764,7 -752,7 -764,7 +766,7 @@@@@@@ static int acpi_dev_pm_full_power(struc */ int acpi_dev_runtime_suspend(struct device *dev) { ---- - struct acpi_device *adev = acpi_dev_pm_get_node(dev); ++++ + struct acpi_device *adev = ACPI_COMPANION(dev); bool remote_wakeup; int error; @@@@@@@ -809,7 -795,7 -809,7 -795,7 -783,7 -795,7 +797,7 @@@@@@@ EXPORT_SYMBOL_GPL(acpi_dev_runtime_susp */ int acpi_dev_runtime_resume(struct device *dev) { ---- - struct acpi_device *adev = acpi_dev_pm_get_node(dev); ++++ + struct acpi_device *adev = ACPI_COMPANION(dev); int error; if (!adev) @@@@@@@ -862,7 -848,7 -862,7 -848,7 -836,7 -848,7 +850,7 @@@@@@@ EXPORT_SYMBOL_GPL(acpi_subsys_runtime_r */ int acpi_dev_suspend_late(struct device *dev) { ---- - struct acpi_device *adev = acpi_dev_pm_get_node(dev); ++++ + struct acpi_device *adev = ACPI_COMPANION(dev); u32 target_state; bool wakeup; int error; @@@@@@@ -894,7 -880,7 -894,7 -880,7 -868,7 -880,7 +882,7 @@@@@@@ EXPORT_SYMBOL_GPL(acpi_dev_suspend_late */ int acpi_dev_resume_early(struct device *dev) { ---- - struct acpi_device *adev = acpi_dev_pm_get_node(dev); ++++ + struct acpi_device *adev = ACPI_COMPANION(dev); int error; if (!adev) @@@@@@@ -985,7 -971,7 -985,7 -971,7 -959,7 -971,7 +973,7 @@@@@@@ static struct dev_pm_domain acpi_genera */ int acpi_dev_pm_attach(struct device *dev, bool power_on) { ---- - struct acpi_device *adev = acpi_dev_pm_get_node(dev); ++++ + struct acpi_device *adev = ACPI_COMPANION(dev); if (!adev) return -ENODEV; @@@@@@@ -1017,7 -1003,7 -1017,7 -1003,7 -991,7 -1003,7 +1005,7 @@@@@@@ EXPORT_SYMBOL_GPL(acpi_dev_pm_attach) */ void acpi_dev_pm_detach(struct device *dev, bool power_off) { ---- - struct acpi_device *adev = acpi_dev_pm_get_node(dev); ++++ + struct acpi_device *adev = ACPI_COMPANION(dev); if (adev && dev->pm_domain == &acpi_general_pm_domain) { dev->pm_domain = NULL; diff --combined drivers/acpi/processor_core.c index 34e7b3c6a08,24c87efbc1c,34e7b3c6a08,b3171f30b31,b3171f30b31,b3171f30b31..a4eea9a508d --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@@@@@@ -10,7 -10,8 -10,7 -10,8 -10,8 -10,8 +10,7 @@@@@@@ #include #include #include - --- - ---#include + +++#include #include #include "internal.h" @@@@@@@ -44,13 -45,13 -44,13 -45,13 -45,13 -45,13 +44,13 @@@@@@@ static int map_lapic_id(struct acpi_sub (struct acpi_madt_local_apic *)entry; if (!(lapic->lapic_flags & ACPI_MADT_ENABLED)) - ---- return 0; + ++++ return -ENODEV; if (lapic->processor_id != acpi_id) - ---- return 0; + ++++ return -EINVAL; *apic_id = lapic->id; - ---- return 1; + ++++ return 0; } static int map_x2apic_id(struct acpi_subtable_header *entry, @@@@@@@ -60,14 -61,14 -60,14 -61,14 -61,14 -61,14 +60,14 @@@@@@@ (struct acpi_madt_local_x2apic *)entry; if (!(apic->lapic_flags & ACPI_MADT_ENABLED)) - ---- return 0; + ++++ return -ENODEV; if (device_declaration && (apic->uid == acpi_id)) { *apic_id = apic->local_apic_id; - ---- return 1; + ++++ return 0; } - ---- return 0; + ++++ return -EINVAL; } static int map_lsapic_id(struct acpi_subtable_header *entry, @@@@@@@ -77,16 -78,16 -77,16 -78,16 -78,16 -78,16 +77,16 @@@@@@@ (struct acpi_madt_local_sapic *)entry; if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED)) - ---- return 0; + ++++ return -ENODEV; if (device_declaration) { if ((entry->length < 16) || (lsapic->uid != acpi_id)) - ---- return 0; + ++++ return -EINVAL; } else if (lsapic->processor_id != acpi_id) - ---- return 0; + ++++ return -EINVAL; *apic_id = (lsapic->id << 8) | lsapic->eid; - ---- return 1; + ++++ return 0; } static int map_madt_entry(int type, u32 acpi_id) @@@@@@@ -116,13 -117,13 -116,13 -117,13 -117,13 -117,13 +116,13 @@@@@@@ struct acpi_subtable_header *header = (struct acpi_subtable_header *)entry; if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { - ---- if (map_lapic_id(header, acpi_id, &apic_id)) + ++++ if (!map_lapic_id(header, acpi_id, &apic_id)) break; } else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) { - ---- if (map_x2apic_id(header, type, acpi_id, &apic_id)) + ++++ if (!map_x2apic_id(header, type, acpi_id, &apic_id)) break; } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { - ---- if (map_lsapic_id(header, type, acpi_id, &apic_id)) + ++++ if (!map_lsapic_id(header, type, acpi_id, &apic_id)) break; } entry += header->length; diff --combined drivers/acpi/scan.c index e00365ccb89,fd39459926b,089dc403c43,fd39459926b,fd39459926b,fd39459926b..7384158c7f8 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@@@@@@ -12,12 -12,13 -12,12 -12,13 -12,13 -12,13 +12,12 @@@@@@@ #include #include - ---#include + +++#include #include "internal.h" #define _COMPONENT ACPI_BUS_COMPONENT ACPI_MODULE_NAME("scan"); - ---#define STRUCT_TO_INT(s) (*((int*)&s)) extern struct acpi_device *acpi_root; #define ACPI_BUS_CLASS "system_bus" @@@@@@@ -26,8 -27,6 -26,8 -27,6 -27,6 -27,6 +26,8 @@@@@@@ #define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent) + +++#define INVALID_ACPI_HANDLE ((acpi_handle)empty_zero_page) + +++ /* * If set, devices will be hot-removed even if they cannot be put offline * gracefully (from the kernel's standpoint). @@@@@@@ -86,9 -85,6 -86,6 -85,6 -85,6 -85,6 +86,9 @@@@@@@ int acpi_scan_add_handler_with_hotplug( * Creates hid/cid(s) string needed for modalias and uevent * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: * char *modalias: "acpi:IBM0001:ACPI0001" +++++ * Return: 0: no _HID and no _CID +++++ * -EINVAL: output error +++++ * -ENOMEM: output is truncated */ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, int size) @@@@@@@ -105,10 -101,8 -102,8 -101,8 -101,8 -101,8 +105,10 @@@@@@@ list_for_each_entry(id, &acpi_dev->pnp.ids, list) { count = snprintf(&modalias[len], size, "%s:", id->id); ----- if (count < 0 || count >= size) ----- return -EINVAL; +++++ if (count < 0) +++++ return EINVAL; +++++ if (count >= size) +++++ return -ENOMEM; len += count; size -= count; } @@@@@@@ -117,96 -111,20 -112,40 -111,20 -111,20 -111,20 +117,96 @@@@@@@ return len; } +++++/* +++++ * Creates uevent modalias field for ACPI enumerated devices. +++++ * Because the other buses does not support ACPI HIDs & CIDs. +++++ * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: +++++ * "acpi:IBM0001:ACPI0001" +++++ */ +++++int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) +++++{ +++++ struct acpi_device *acpi_dev; +++++ int len; +++++ +++++ acpi_dev = ACPI_COMPANION(dev); +++++ if (!acpi_dev) +++++ return -ENODEV; +++++ +++++ /* Fall back to bus specific way of modalias exporting */ +++++ if (list_empty(&acpi_dev->pnp.ids)) +++++ return -ENODEV; +++++ +++++ if (add_uevent_var(env, "MODALIAS=")) +++++ return -ENOMEM; +++++ len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], +++++ sizeof(env->buf) - env->buflen); +++++ if (len <= 0) +++++ return len; +++++ env->buflen += len; +++++ return 0; +++++} +++++EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias); +++++ +++++/* +++++ * Creates modalias sysfs attribute for ACPI enumerated devices. +++++ * Because the other buses does not support ACPI HIDs & CIDs. +++++ * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: +++++ * "acpi:IBM0001:ACPI0001" +++++ */ +++++int acpi_device_modalias(struct device *dev, char *buf, int size) +++++{ +++++ struct acpi_device *acpi_dev; +++++ int len; +++++ +++++ acpi_dev = ACPI_COMPANION(dev); +++++ if (!acpi_dev) +++++ return -ENODEV; +++++ +++++ /* Fall back to bus specific way of modalias exporting */ +++++ if (list_empty(&acpi_dev->pnp.ids)) +++++ return -ENODEV; +++++ +++++ len = create_modalias(acpi_dev, buf, size -1); +++++ if (len <= 0) +++++ return len; +++++ buf[len++] = '\n'; +++++ return len; +++++} +++++EXPORT_SYMBOL_GPL(acpi_device_modalias); +++++ static ssize_t acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { struct acpi_device *acpi_dev = to_acpi_device(dev); int len; ----- /* Device has no HID and no CID or string is >1024 */ len = create_modalias(acpi_dev, buf, 1024); if (len <= 0) ----- return 0; +++++ return len; buf[len++] = '\n'; return len; } static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); + +++bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent) + +++{ + +++ struct acpi_device_physical_node *pn; + +++ bool offline = true; + +++ + +++ mutex_lock(&adev->physical_node_lock); + +++ + +++ list_for_each_entry(pn, &adev->physical_node_list, node) + +++ if (device_supports_offline(pn->dev) && !pn->dev->offline) { + +++ if (uevent) + +++ kobject_uevent(&pn->dev->kobj, KOBJ_CHANGE); + +++ + +++ offline = false; + +++ break; + +++ } + +++ + +++ mutex_unlock(&adev->physical_node_lock); + +++ return offline; + +++} + +++ static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data, void **ret_p) { @@@@@@@ -277,11 -195,19 -216,11 -195,19 -195,19 -195,19 +277,11 @@@@@@@ static acpi_status acpi_bus_online(acpi return AE_OK; } - ---static int acpi_scan_hot_remove(struct acpi_device *device) + +++static int acpi_scan_try_to_offline(struct acpi_device *device) { acpi_handle handle = device->handle; - --- struct device *errdev; + +++ struct device *errdev = NULL; acpi_status status; - --- unsigned long long sta; - --- - --- /* If there is no handle, the device node has been unregistered. */ - --- if (!handle) { - --- dev_dbg(&device->dev, "ACPI handle missing\n"); - --- put_device(&device->dev); - --- return -EINVAL; - --- } /* * Carry out two passes here and ignore errors in the first pass, @@@@@@@ -292,6 -218,7 -231,6 -218,7 -218,7 -218,7 +292,6 @@@@@@@ * * If the first pass is successful, the second one isn't needed, though. */ - --- errdev = NULL; status = acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, NULL, acpi_bus_offline, (void *)false, (void **)&errdev); @@@@@@@ -299,6 -226,7 -238,6 -226,7 -226,7 -226,7 +299,6 @@@@@@@ dev_warn(errdev, "Offline disabled.\n"); acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, acpi_bus_online, NULL, NULL, NULL); - --- put_device(&device->dev); return -EPERM; } acpi_bus_offline(handle, 0, (void *)false, (void **)&errdev); @@@@@@@ -317,32 -245,20 -256,32 -245,20 -245,20 -245,20 +317,32 @@@@@@@ acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, acpi_bus_online, NULL, NULL, NULL); - --- put_device(&device->dev); return -EBUSY; } } + +++ return 0; + +++} + +++ + +++static int acpi_scan_hot_remove(struct acpi_device *device) + +++{ + +++ acpi_handle handle = device->handle; + +++ unsigned long long sta; + +++ acpi_status status; + +++ + +++ if (device->handler->hotplug.demand_offline && !acpi_force_hot_remove) { + +++ if (!acpi_scan_is_offline(device, true)) + +++ return -EBUSY; + +++ } else { + +++ int error = acpi_scan_try_to_offline(device); + +++ if (error) + +++ return error; + +++ } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Hot-removing device %s...\n", dev_name(&device->dev))); acpi_bus_trim(device); - --- /* Device node has been unregistered. */ - --- put_device(&device->dev); - --- device = NULL; - --- acpi_evaluate_lck(handle, 0); /* * TBD: _EJD support. @@@@@@@ -369,127 -285,115 -308,127 -285,115 -285,115 -285,115 +369,127 @@@@@@@ return 0; } - ---void acpi_bus_device_eject(void *data, u32 ost_src) + +++static int acpi_scan_device_not_present(struct acpi_device *adev) { - --- struct acpi_device *device = data; - --- acpi_handle handle = device->handle; - --- u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; - --- int error; + +++ if (!acpi_device_enumerated(adev)) { + +++ dev_warn(&adev->dev, "Still not present\n"); + +++ return -EALREADY; + +++ } + +++ acpi_bus_trim(adev); + +++ return 0; + +++} - --- lock_device_hotplug(); - --- mutex_lock(&acpi_scan_lock); + +++static int acpi_scan_device_check(struct acpi_device *adev) + +++{ + +++ int error; - --- if (ost_src == ACPI_NOTIFY_EJECT_REQUEST) - --- acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, - --- ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); + +++ acpi_bus_get_status(adev); + +++ if (adev->status.present || adev->status.functional) { + +++ /* + +++ * This function is only called for device objects for which + +++ * matching scan handlers exist. The only situation in which + +++ * the scan handler is not attached to this device object yet + +++ * is when the device has just appeared (either it wasn't + +++ * present at all before or it was removed and then added + +++ * again). + +++ */ + +++ if (adev->handler) { + +++ dev_warn(&adev->dev, "Already enumerated\n"); + +++ return -EALREADY; + +++ } + +++ error = acpi_bus_scan(adev->handle); + +++ if (error) { + +++ dev_warn(&adev->dev, "Namespace scan failure\n"); + +++ return error; + +++ } + +++ if (!adev->handler) { + +++ dev_warn(&adev->dev, "Enumeration failure\n"); + +++ error = -ENODEV; + +++ } + +++ } else { + +++ error = acpi_scan_device_not_present(adev); + +++ } + +++ return error; + +++} - --- if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER) - --- kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); + +++static int acpi_scan_bus_check(struct acpi_device *adev) + +++{ + +++ struct acpi_scan_handler *handler = adev->handler; + +++ struct acpi_device *child; + +++ int error; - --- error = acpi_scan_hot_remove(device); - --- if (error == -EPERM) { - --- goto err_support; - --- } else if (error) { - --- goto err_out; + +++ acpi_bus_get_status(adev); + +++ if (!(adev->status.present || adev->status.functional)) { + +++ acpi_scan_device_not_present(adev); + +++ return 0; } + +++ if (handler && handler->hotplug.scan_dependent) + +++ return handler->hotplug.scan_dependent(adev); - --- out: - --- mutex_unlock(&acpi_scan_lock); - --- unlock_device_hotplug(); - --- return; - --- - --- err_support: - --- ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; - --- err_out: - --- acpi_evaluate_hotplug_ost(handle, ost_src, ost_code, NULL); - --- goto out; + +++ error = acpi_bus_scan(adev->handle); + +++ if (error) { + +++ dev_warn(&adev->dev, "Namespace scan failure\n"); + +++ return error; + +++ } + +++ list_for_each_entry(child, &adev->children, node) { + +++ error = acpi_scan_bus_check(child); + +++ if (error) + +++ return error; + +++ } + +++ return 0; } - ---static void acpi_scan_bus_device_check(void *data, u32 ost_source) + +++static void acpi_device_hotplug(void *data, u32 src) { - --- acpi_handle handle = data; - --- struct acpi_device *device = NULL; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; + +++ struct acpi_device *adev = data; int error; lock_device_hotplug(); mutex_lock(&acpi_scan_lock); - --- if (ost_source != ACPI_NOTIFY_BUS_CHECK) { - --- acpi_bus_get_device(handle, &device); - --- if (device) { - --- dev_warn(&device->dev, "Attempt to re-insert\n"); - --- goto out; - --- } - --- } - --- error = acpi_bus_scan(handle); - --- if (error) { - --- acpi_handle_warn(handle, "Namespace scan failure\n"); - --- goto out; - --- } - --- error = acpi_bus_get_device(handle, &device); - --- if (error) { - --- acpi_handle_warn(handle, "Missing device node object\n"); + +++ /* + +++ * The device object's ACPI handle cannot become invalid as long as we + +++ * are holding acpi_scan_lock, but it may have become invalid before + +++ * that lock was acquired. + +++ */ + +++ if (adev->handle == INVALID_ACPI_HANDLE) goto out; - --- } - --- ost_code = ACPI_OST_SC_SUCCESS; - --- if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER) - --- kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); - --- out: - --- acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL); - --- mutex_unlock(&acpi_scan_lock); - --- unlock_device_hotplug(); - ---} - --- - ---static void acpi_hotplug_unsupported(acpi_handle handle, u32 type) - ---{ - --- u32 ost_status; - --- - --- switch (type) { + +++ switch (src) { case ACPI_NOTIFY_BUS_CHECK: - --- acpi_handle_debug(handle, - --- "ACPI_NOTIFY_BUS_CHECK event: unsupported\n"); - --- ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED; + +++ error = acpi_scan_bus_check(adev); break; case ACPI_NOTIFY_DEVICE_CHECK: - --- acpi_handle_debug(handle, - --- "ACPI_NOTIFY_DEVICE_CHECK event: unsupported\n"); - --- ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED; + +++ error = acpi_scan_device_check(adev); break; case ACPI_NOTIFY_EJECT_REQUEST: - --- acpi_handle_debug(handle, - --- "ACPI_NOTIFY_EJECT_REQUEST event: unsupported\n"); - --- ost_status = ACPI_OST_SC_EJECT_NOT_SUPPORTED; + +++ case ACPI_OST_EC_OSPM_EJECT: + +++ error = acpi_scan_hot_remove(adev); break; default: - --- /* non-hotplug event; possibly handled by other handler */ - --- return; + +++ error = -EINVAL; + +++ break; } + +++ if (!error) + +++ ost_code = ACPI_OST_SC_SUCCESS; - --- acpi_evaluate_hotplug_ost(handle, type, ost_status, NULL); + +++ out: + +++ acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL); + +++ put_device(&adev->dev); + +++ mutex_unlock(&acpi_scan_lock); + +++ unlock_device_hotplug(); } static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) { + +++ u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; struct acpi_scan_handler *handler = data; struct acpi_device *adev; acpi_status status; - --- if (!handler->hotplug.enabled) - --- return acpi_hotplug_unsupported(handle, type); + +++ if (acpi_bus_get_device(handle, &adev)) + +++ goto err_out; switch (type) { case ACPI_NOTIFY_BUS_CHECK: @@@@@@@ -500,27 -404,27 -439,27 -404,27 -404,27 -404,27 +500,27 @@@@@@@ break; case ACPI_NOTIFY_EJECT_REQUEST: acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); - --- if (acpi_bus_get_device(handle, &adev)) + +++ if (!handler->hotplug.enabled) { + +++ acpi_handle_err(handle, "Eject disabled\n"); + +++ ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; goto err_out; - --- - --- get_device(&adev->dev); - --- status = acpi_hotplug_execute(acpi_bus_device_eject, adev, type); - --- if (ACPI_SUCCESS(status)) - --- return; - --- - --- put_device(&adev->dev); - --- goto err_out; + +++ } + +++ acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, + +++ ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); + +++ break; default: /* non-hotplug event; possibly handled by other handler */ return; } - --- status = acpi_hotplug_execute(acpi_scan_bus_device_check, handle, type); + +++ get_device(&adev->dev); + +++ status = acpi_hotplug_execute(acpi_device_hotplug, adev, type); if (ACPI_SUCCESS(status)) return; + +++ put_device(&adev->dev); + +++ err_out: - --- acpi_evaluate_hotplug_ost(handle, type, - --- ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); + +++ acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); } static ssize_t real_power_state_show(struct device *dev, @@@@@@@ -571,7 -475,7 -510,7 -475,7 -475,7 -475,7 +571,7 @@@@@@@ acpi_eject_store(struct device *d, stru acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); get_device(&acpi_device->dev); - --- status = acpi_hotplug_execute(acpi_bus_device_eject, acpi_device, + +++ status = acpi_hotplug_execute(acpi_device_hotplug, acpi_device, ACPI_OST_EC_OSPM_EJECT); if (ACPI_SUCCESS(status)) return count; @@@@@@@ -663,20 -567,6 -602,20 -567,6 -567,6 -567,6 +663,20 @@@@@@@ acpi_device_sun_show(struct device *dev } static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL); + +++static ssize_t status_show(struct device *dev, struct device_attribute *attr, + +++ char *buf) { + +++ struct acpi_device *acpi_dev = to_acpi_device(dev); + +++ acpi_status status; + +++ unsigned long long sta; + +++ + +++ status = acpi_evaluate_integer(acpi_dev->handle, "_STA", NULL, &sta); + +++ if (ACPI_FAILURE(status)) + +++ return -ENODEV; + +++ + +++ return sprintf(buf, "%llu\n", sta); + +++} + +++static DEVICE_ATTR_RO(status); + +++ static int acpi_device_setup_files(struct acpi_device *dev) { struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; @@@@@@@ -732,12 -622,6 -671,12 -622,6 -622,6 -622,6 +732,12 @@@@@@@ dev->pnp.sun = (unsigned long)-1; } + +++ if (acpi_has_method(dev->handle, "_STA")) { + +++ result = device_create_file(&dev->dev, &dev_attr_status); + +++ if (result) + +++ goto end; + +++ } + +++ /* * If device has _EJ0, 'eject' file is created that is used to trigger * hot-removal function from userland. @@@@@@@ -793,8 -677,6 -732,8 -677,6 -677,6 -677,6 +793,8 @@@@@@@ static void acpi_device_remove_files(st device_remove_file(&dev->dev, &dev_attr_adr); device_remove_file(&dev->dev, &dev_attr_modalias); device_remove_file(&dev->dev, &dev_attr_hid); + +++ if (acpi_has_method(dev->handle, "_STA")) + +++ device_remove_file(&dev->dev, &dev_attr_status); if (dev->handle) device_remove_file(&dev->dev, &dev_attr_path); } @@@@@@@ -900,8 -782,8 -839,8 -782,8 -782,8 -782,8 +900,8 @@@@@@@ static int acpi_device_uevent(struct de return -ENOMEM; len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], sizeof(env->buf) - env->buflen); ----- if (len >= (sizeof(env->buf) - env->buflen)) ----- return -ENOMEM; +++++ if (len <= 0) +++++ return len; env->buflen += len; return 0; } @@@@@@@ -1025,91 -907,9 -964,91 -907,9 -907,9 -907,9 +1025,91 @@@@@@@ struct bus_type acpi_bus_type = .uevent = acpi_device_uevent, }; - ---static void acpi_bus_data_handler(acpi_handle handle, void *context) + +++static void acpi_device_del(struct acpi_device *device) + +++{ + +++ mutex_lock(&acpi_device_lock); + +++ if (device->parent) + +++ list_del(&device->node); + +++ + +++ list_del(&device->wakeup_list); + +++ mutex_unlock(&acpi_device_lock); + +++ + +++ acpi_power_add_remove_device(device, false); + +++ acpi_device_remove_files(device); + +++ if (device->remove) + +++ device->remove(device); + +++ + +++ device_del(&device->dev); + +++} + +++ + +++static LIST_HEAD(acpi_device_del_list); + +++static DEFINE_MUTEX(acpi_device_del_lock); + +++ + +++static void acpi_device_del_work_fn(struct work_struct *work_not_used) + +++{ + +++ for (;;) { + +++ struct acpi_device *adev; + +++ + +++ mutex_lock(&acpi_device_del_lock); + +++ + +++ if (list_empty(&acpi_device_del_list)) { + +++ mutex_unlock(&acpi_device_del_lock); + +++ break; + +++ } + +++ adev = list_first_entry(&acpi_device_del_list, + +++ struct acpi_device, del_list); + +++ list_del(&adev->del_list); + +++ + +++ mutex_unlock(&acpi_device_del_lock); + +++ + +++ acpi_device_del(adev); + +++ /* + +++ * Drop references to all power resources that might have been + +++ * used by the device. + +++ */ + +++ acpi_power_transition(adev, ACPI_STATE_D3_COLD); + +++ put_device(&adev->dev); + +++ } + +++} + +++ + +++/** + +++ * acpi_scan_drop_device - Drop an ACPI device object. + +++ * @handle: Handle of an ACPI namespace node, not used. + +++ * @context: Address of the ACPI device object to drop. + +++ * + +++ * This is invoked by acpi_ns_delete_node() during the removal of the ACPI + +++ * namespace node the device object pointed to by @context is attached to. + +++ * + +++ * The unregistration is carried out asynchronously to avoid running + +++ * acpi_device_del() under the ACPICA's namespace mutex and the list is used to + +++ * ensure the correct ordering (the device objects must be unregistered in the + +++ * same order in which the corresponding namespace nodes are deleted). + +++ */ + +++static void acpi_scan_drop_device(acpi_handle handle, void *context) { - --- /* Intentionally empty. */ + +++ static DECLARE_WORK(work, acpi_device_del_work_fn); + +++ struct acpi_device *adev = context; + +++ + +++ mutex_lock(&acpi_device_del_lock); + +++ + +++ /* + +++ * Use the ACPI hotplug workqueue which is ordered, so this work item + +++ * won't run after any hotplug work items submitted subsequently. That + +++ * 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 + +++ * those work items to ensure that they are not accessing stale device + +++ * objects. + +++ */ + +++ if (list_empty(&acpi_device_del_list)) + +++ acpi_queue_hotplug_work(&work); + +++ + +++ list_add_tail(&adev->del_list, &acpi_device_del_list); + +++ /* Make acpi_ns_validate_handle() return NULL for this handle. */ + +++ adev->handle = INVALID_ACPI_HANDLE; + +++ + +++ mutex_unlock(&acpi_device_del_lock); } int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) @@@@@@@ -1119,7 -919,7 -1058,7 -919,7 -919,7 -919,7 +1119,7 @@@@@@@ if (!device) return -EINVAL; - --- status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device); + +++ status = acpi_get_data(handle, acpi_scan_drop_device, (void **)device); if (ACPI_FAILURE(status) || !*device) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", handle)); @@@@@@@ -1139,7 -939,7 -1078,7 -939,7 -939,7 -939,7 +1139,7 @@@@@@@ int acpi_device_add(struct acpi_device if (device->handle) { acpi_status status; - --- status = acpi_attach_data(device->handle, acpi_bus_data_handler, + +++ status = acpi_attach_data(device->handle, acpi_scan_drop_device, device); if (ACPI_FAILURE(status)) { acpi_handle_err(device->handle, @@@@@@@ -1157,7 -957,6 -1096,7 -957,6 -957,6 -957,6 +1157,7 @@@@@@@ INIT_LIST_HEAD(&device->node); INIT_LIST_HEAD(&device->wakeup_list); INIT_LIST_HEAD(&device->physical_node_list); + +++ INIT_LIST_HEAD(&device->del_list); mutex_init(&device->physical_node_lock); new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); @@@@@@@ -1221,10 -1020,37 -1160,10 -1020,37 -1020,37 -1020,37 +1221,10 @@@@@@@ mutex_unlock(&acpi_device_lock); err_detach: - --- acpi_detach_data(device->handle, acpi_bus_data_handler); + +++ acpi_detach_data(device->handle, acpi_scan_drop_device); return result; } - ---static void acpi_device_unregister(struct acpi_device *device) - ---{ - --- mutex_lock(&acpi_device_lock); - --- if (device->parent) - --- list_del(&device->node); - --- - --- list_del(&device->wakeup_list); - --- mutex_unlock(&acpi_device_lock); - --- - --- acpi_detach_data(device->handle, acpi_bus_data_handler); - --- - --- acpi_power_add_remove_device(device, false); - --- acpi_device_remove_files(device); - --- if (device->remove) - --- device->remove(device); - --- - --- device_del(&device->dev); - --- /* - --- * Transition the device to D3cold to drop the reference counts of all - --- * power resources the device depends on and turn off the ones that have - --- * no more references. - --- */ - --- acpi_device_set_power(device, ACPI_STATE_D3_COLD); - --- device->handle = NULL; - --- put_device(&device->dev); - ---} - --- /* -------------------------------------------------------------------------- Driver Management -------------------------------------------------------------------------- */ @@@@@@@ -1798,13 -1624,11 -1737,13 -1624,11 -1624,11 -1624,11 +1798,13 @@@@@@@ void acpi_init_device_object(struct acp device->device_type = type; device->handle = handle; device->parent = acpi_bus_get_parent(handle); - --- STRUCT_TO_INT(device->status) = sta; + +++ acpi_set_device_status(device, sta); acpi_device_get_busid(device); acpi_set_pnp_ids(handle, &device->pnp, type); acpi_bus_get_flags(device); device->flags.match_driver = false; + +++ device->flags.initialized = true; + +++ device->flags.visited = false; device_initialize(&device->dev); dev_set_uevent_suppress(&device->dev, true); } @@@@@@@ -1889,15 -1713,6 -1828,15 -1713,6 -1713,6 -1713,6 +1889,15 @@@@@@@ static int acpi_bus_type_and_status(acp return 0; } + +++bool acpi_device_is_present(struct acpi_device *adev) + +++{ + +++ if (adev->status.present || adev->status.functional) + +++ return true; + +++ + +++ adev->flags.initialized = false; + +++ return false; + +++} + +++ static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler, char *idstr, const struct acpi_device_id **matchid) @@@@@@@ -1957,7 -1772,7 -1896,7 -1772,7 -1772,7 -1772,7 +1957,7 @@@@@@@ static void acpi_scan_init_hotplug(acpi */ list_for_each_entry(hwid, &pnp.ids, list) { handler = acpi_scan_match_handler(hwid->id, NULL); - --- if (handler && !handler->hotplug.ignore) { + +++ if (handler) { acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, acpi_hotplug_notify_cb, handler); break; @@@@@@@ -1991,6 -1806,18 -1930,6 -1806,18 -1806,18 -1806,18 +1991,6 @@@@@@@ static acpi_status acpi_bus_check_add(a acpi_scan_init_hotplug(handle, type); - --- if (!(sta & ACPI_STA_DEVICE_PRESENT) && - --- !(sta & ACPI_STA_DEVICE_FUNCTIONING)) { - --- struct acpi_device_wakeup wakeup; - --- - --- if (acpi_has_method(handle, "_PRW")) { - --- acpi_bus_extract_wakeup_device_power_package(handle, - --- &wakeup); - --- acpi_power_resources_list_free(&wakeup.resources); - --- } - --- return AE_CTRL_DEPTH; - --- } - --- acpi_add_single_object(&device, handle, type, sta); if (!device) return AE_CTRL_DEPTH; @@@@@@@ -2025,40 -1852,36 -1964,40 -1852,36 -1852,36 -1852,36 +2025,40 @@@@@@@ static int acpi_scan_attach_handler(str return ret; } - ---static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, - --- void *not_used, void **ret_not_used) + +++static void acpi_bus_attach(struct acpi_device *device) { - --- struct acpi_device *device; - --- unsigned long long sta_not_used; + +++ struct acpi_device *child; int ret; - --- /* - --- * Ignore errors ignored by acpi_bus_check_add() to avoid terminating - --- * namespace walks prematurely. - --- */ - --- if (acpi_bus_type_and_status(handle, &ret, &sta_not_used)) - --- return AE_OK; - --- - --- if (acpi_bus_get_device(handle, &device)) - --- return AE_CTRL_DEPTH; - --- + +++ acpi_bus_get_status(device); + +++ /* Skip devices that are not present. */ + +++ if (!acpi_device_is_present(device)) { + +++ device->flags.visited = false; + +++ return; + +++ } if (device->handler) - --- return AE_OK; + +++ goto ok; + +++ if (!device->flags.initialized) { + +++ acpi_bus_update_power(device, NULL); + +++ device->flags.initialized = true; + +++ } + +++ device->flags.visited = false; ret = acpi_scan_attach_handler(device); if (ret < 0) - --- return AE_CTRL_DEPTH; + +++ return; device->flags.match_driver = true; - --- if (ret > 0) - --- return AE_OK; + +++ if (!ret) { + +++ ret = device_attach(&device->dev); + +++ if (ret < 0) + +++ return; + +++ } + +++ device->flags.visited = true; - --- ret = device_attach(&device->dev); - --- return ret >= 0 ? AE_OK : AE_CTRL_DEPTH; + +++ ok: + +++ list_for_each_entry(child, &device->children, node) + +++ acpi_bus_attach(child); } /** @@@@@@@ -2078,48 -1901,75 -2017,49 -1901,75 -1901,75 -1901,75 +2078,49 @@@@@@@ int acpi_bus_scan(acpi_handle handle) { void *device = NULL; - --- int error = 0; 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) - --- error = -ENODEV; - --- else 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); - --- - --- return error; - ---} - ---EXPORT_SYMBOL(acpi_bus_scan); - --- - ---static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used, - --- void *not_used, void **ret_not_used) - ---{ - --- struct acpi_device *device = NULL; - --- - --- if (!acpi_bus_get_device(handle, &device)) { - --- struct acpi_scan_handler *dev_handler = device->handler; - --- - --- if (dev_handler) { - --- if (dev_handler->detach) - --- dev_handler->detach(device); - --- - --- device->handler = NULL; - --- } else { - --- device_release_driver(&device->dev); - --- } + +++ if (device) { + +++ acpi_bus_attach(device); + +++ return 0; } - --- return AE_OK; - ---} - --- - ---static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used, - --- void *not_used, void **ret_not_used) - ---{ - --- struct acpi_device *device = NULL; - --- - --- if (!acpi_bus_get_device(handle, &device)) - --- acpi_device_unregister(device); - --- - --- return AE_OK; + +++ return -ENODEV; } + +++EXPORT_SYMBOL(acpi_bus_scan); /** - --- * acpi_bus_trim - Remove ACPI device node and all of its descendants - --- * @start: Root of the ACPI device nodes subtree to remove. + +++ * acpi_bus_trim - Detach scan handlers and drivers from ACPI device objects. + +++ * @adev: Root of the ACPI namespace scope to walk. * * Must be called under acpi_scan_lock. */ - ---void acpi_bus_trim(struct acpi_device *start) + +++void acpi_bus_trim(struct acpi_device *adev) { + +++ struct acpi_scan_handler *handler = adev->handler; + +++ struct acpi_device *child; + +++ + +++ list_for_each_entry_reverse(child, &adev->children, node) + +++ acpi_bus_trim(child); + +++ ++ +++ adev->flags.match_driver = false; + +++ if (handler) { + +++ if (handler->detach) + +++ handler->detach(adev); + +++ + +++ adev->handler = NULL; + +++ } else { + +++ device_release_driver(&adev->dev); + +++ } /* - --- * Execute acpi_bus_device_detach() as a post-order callback to detach - --- * all ACPI drivers from the device nodes being removed. - --- */ - --- acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, - --- acpi_bus_device_detach, NULL, NULL); - --- acpi_bus_device_detach(start->handle, 0, NULL, NULL); - --- /* - --- * Execute acpi_bus_remove() as a post-order callback to remove device - --- * nodes in the given namespace scope. + +++ * Most likely, the device is going away, so put it into D3cold before + +++ * that. */ - --- acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, - --- acpi_bus_remove, NULL, NULL); - --- acpi_bus_remove(start->handle, 0, NULL, NULL); + +++ acpi_device_set_power(adev, ACPI_STATE_D3_COLD); + +++ adev->flags.initialized = false; + +++ adev->flags.visited = false; } EXPORT_SYMBOL_GPL(acpi_bus_trim); @@@@@@@ -2197,14 -2047,14 -2137,14 -2047,14 -2047,14 -2047,14 +2198,14 @@@@@@@ int __init acpi_scan_init(void result = acpi_bus_scan_fixed(); if (result) { - --- acpi_device_unregister(acpi_root); + +++ acpi_detach_data(acpi_root->handle, acpi_scan_drop_device); + +++ acpi_device_del(acpi_root); + +++ put_device(&acpi_root->dev); goto out; } acpi_update_all_gpes(); - --- acpi_pci_root_hp_init(); - --- out: mutex_unlock(&acpi_scan_lock); return result; diff --combined drivers/acpi/sysfs.c index 443dc936605,6dbc3ca4522,ba07d9a927a,6dbc3ca4522,6dbc3ca4522,3e0b54fb075..91a32cefb11 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@@@@@@ -5,7 -5,7 -5,7 -5,7 -5,7 -5,7 +5,7 @@@@@@@ #include #include #include - ---#include + +++#include #include "internal.h" @@@@@@@ -226,7 -226,7 -226,7 -226,7 -226,7 -226,7 +226,7 @@@@@@@ module_param_call(trace_state, param_se /* /sys/modules/acpi/parameters/aml_debug_output */ module_param_named(aml_debug_output, acpi_gbl_enable_aml_debug_object, ----- bool, 0644); +++++ byte, 0644); MODULE_PARM_DESC(aml_debug_output, "To enable/disable the ACPI Debug Object output."); @@@@@@@ -309,7 -309,7 -309,7 -309,7 -309,7 -309,7 +309,7 @@@@@@@ static void acpi_table_attr_init(struc sprintf(table_attr->name + ACPI_NAME_SIZE, "%d", table_attr->instance); - table_attr->attr.size = 0; + table_attr->attr.size = table_header->length; table_attr->attr.read = acpi_table_show; table_attr->attr.attr.name = table_attr->name; table_attr->attr.attr.mode = 0400; @@@@@@@ -354,9 -354,9 -354,8 -354,9 -354,9 -354,9 +354,9 @@@@@@@ static int acpi_tables_sysfs_init(void { struct acpi_table_attr *table_attr; struct acpi_table_header *table_header = NULL; - int table_index = 0; - int result; + int table_index; + acpi_status status; + int ret; tables_kobj = kobject_create_and_add("tables", acpi_kobj); if (!tables_kobj) @@@@@@@ -366,34 -366,34 -365,33 -366,34 -366,34 -366,34 +366,34 @@@@@@@ if (!dynamic_tables_kobj) goto err_dynamic_tables; - do { - result = acpi_get_table_by_index(table_index, &table_header); - if (!result) { - table_index++; - table_attr = NULL; - table_attr = - kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL); - if (!table_attr) - return -ENOMEM; - - acpi_table_attr_init(table_attr, table_header); - result = - sysfs_create_bin_file(tables_kobj, - &table_attr->attr); - if (result) { - kfree(table_attr); - return result; - } else - list_add_tail(&table_attr->node, - &acpi_table_attr_list); + for (table_index = 0;; table_index++) { + status = acpi_get_table_by_index(table_index, &table_header); + + if (status == AE_BAD_PARAMETER) + break; + + if (ACPI_FAILURE(status)) + continue; + + table_attr = NULL; + table_attr = kzalloc(sizeof(*table_attr), GFP_KERNEL); + if (!table_attr) + return -ENOMEM; + + acpi_table_attr_init(table_attr, table_header); + ret = sysfs_create_bin_file(tables_kobj, &table_attr->attr); + if (ret) { + kfree(table_attr); + return ret; } - } while (!result); + list_add_tail(&table_attr->node, &acpi_table_attr_list); + } + kobject_uevent(tables_kobj, KOBJ_ADD); kobject_uevent(dynamic_tables_kobj, KOBJ_ADD); - result = acpi_install_table_handler(acpi_sysfs_table_handler, NULL); + status = acpi_install_table_handler(acpi_sysfs_table_handler, NULL); - return result == AE_OK ? 0 : -EINVAL; + return ACPI_FAILURE(status) ? -EINVAL : 0; err_dynamic_tables: kobject_put(tables_kobj); err: