From bbadbc67de278123e28dd6f9ee7e88b6ada56ce4 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 21 Mar 2014 16:42:12 +0800 Subject: [PATCH] ACPI: temporary dep solution for battery support This is a dep workaround for battery support on Asus T100TA and the formal dep solution is under developing. This patch is just for test and will not be upstreamed. --- drivers/acpi/scan.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++--- drivers/i2c/i2c-acpi.c | 1 + include/linux/acpi.h | 1 + 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 7efe546..254afb7 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -36,6 +36,7 @@ bool acpi_force_hot_remove; static const char *dummy_hid = "device"; +static LIST_HEAD(acpi_bus_dep_device_list); static LIST_HEAD(acpi_bus_id_list); static DEFINE_MUTEX(acpi_scan_lock); static LIST_HEAD(acpi_scan_handlers_list); @@ -43,6 +44,12 @@ DEFINE_MUTEX(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); static DEFINE_MUTEX(acpi_hp_context_lock); + +struct acpi_dep_handle { + struct list_head node; + acpi_handle handle; +}; + struct acpi_device_bus_id{ char bus_id[15]; unsigned int instance_no; @@ -2027,10 +2034,22 @@ static void acpi_scan_init_hotplug(struct acpi_device *adev) } } + +static int acpi_dep_device_check(acpi_handle handle) +{ + struct acpi_dep_handle *dep; + + list_for_each_entry(dep, &acpi_bus_dep_device_list, node) + if (dep->handle == handle) + return -EEXIST; + return 0; +} + 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; + struct acpi_dep_handle *dep = NULL; int type; unsigned long long sta; int result; @@ -2048,9 +2067,24 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, return AE_OK; } - acpi_add_single_object(&device, handle, type, sta); - if (!device) - return AE_CTRL_DEPTH; + if (!acpi_dep_device_check(handle) + && acpi_has_method(handle, "_BIX") + && acpi_has_method(handle, "_DEP")) { + dep = kmalloc(sizeof(struct acpi_dep_handle), GFP_KERNEL); + if (!dep) + return AE_CTRL_DEPTH; + dep->handle = handle; + list_add_tail(&dep->node , &acpi_bus_dep_device_list); + + acpi_handle_info(dep->handle, + "is added to dep device list.\n"); + + return AE_OK; + } else { + acpi_add_single_object(&device, handle, type, sta); + if (!device) + return AE_CTRL_DEPTH; + } acpi_scan_init_hotplug(device); @@ -2061,6 +2095,30 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, return AE_OK; } +int acpi_walk_dep_device_list(void) +{ + struct acpi_dep_handle *dep, *tmp; + acpi_status status; + unsigned long long sta; + + list_for_each_entry_safe(dep, tmp, &acpi_bus_dep_device_list, node) { + status = acpi_evaluate_integer(dep->handle, "_STA", NULL, &sta); + + if (ACPI_FAILURE(status)) { + acpi_handle_warn(dep->handle, + "Status check failed (0x%x)\n", status); + } else if (sta & ACPI_STA_DEVICE_ENABLED) { + acpi_bus_scan(dep->handle); + acpi_handle_info(dep->handle, + "Device is readly\n"); + list_del(&dep->node); + kfree(dep); + } + } + return 0; +} +EXPORT_SYMBOL_GPL(acpi_walk_dep_device_list); + static int acpi_scan_attach_handler(struct acpi_device *device) { struct acpi_hardware_id *hwid; diff --git a/drivers/i2c/i2c-acpi.c b/drivers/i2c/i2c-acpi.c index a0ae867..471490a 100644 --- a/drivers/i2c/i2c-acpi.c +++ b/drivers/i2c/i2c-acpi.c @@ -349,6 +349,7 @@ int acpi_i2c_install_space_handler(struct i2c_adapter *adapter) return -ENOMEM; } + acpi_walk_dep_device_list(); return 0; } diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 667204c..66ad0dd 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -115,6 +115,7 @@ int acpi_boot_init (void); void acpi_boot_table_init (void); int acpi_mps_check (void); int acpi_numa_init (void); +int acpi_walk_dep_device_list(void); int acpi_table_init (void); int acpi_table_parse(char *id, acpi_tbl_table_handler handler); -- 1.8.3.1