From d568df84f987a9321c1f5826a6c8678ef2bb2b70 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 12 Jul 2006 01:47:00 -0400 Subject: ACPI: handle firmware_register init errors Signed-off-by: Randy Dunlap Signed-off-by: Len Brown --- drivers/acpi/bus.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index b2977695e120..7b77ee146a80 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -738,7 +739,10 @@ static int __init acpi_init(void) return -ENODEV; } - firmware_register(&acpi_subsys); + result = firmware_register(&acpi_subsys); + if (result < 0) + printk(KERN_WARNING "%s: firmware_register error: %d\n", + __FUNCTION__, result); result = acpi_bus_init(); -- cgit v1.2.2 From 9b6d97b64eff08b368375efcf9c1d01eba582ea2 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 12 Jul 2006 02:08:00 -0400 Subject: ACPI: scan: handle kset/kobject errors Check and handle kset_register() and kobject_register() init errors. Signed-off-by: Randy Dunlap Signed-off-by: Len Brown --- drivers/acpi/scan.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5fcb50c7b778..698a1540e303 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -113,6 +114,8 @@ static struct kset acpi_namespace_kset = { static void acpi_device_register(struct acpi_device *device, struct acpi_device *parent) { + int err; + /* * Linkage * ------- @@ -138,7 +141,10 @@ static void acpi_device_register(struct acpi_device *device, device->kobj.parent = &parent->kobj; device->kobj.ktype = &ktype_acpi_ns; device->kobj.kset = &acpi_namespace_kset; - kobject_register(&device->kobj); + err = kobject_register(&device->kobj); + if (err < 0) + printk(KERN_WARNING "%s: kobject_register error: %d\n", + __FUNCTION__, err); create_sysfs_device_files(device); } @@ -1450,7 +1456,9 @@ static int __init acpi_scan_init(void) if (acpi_disabled) return 0; - kset_register(&acpi_namespace_kset); + result = kset_register(&acpi_namespace_kset); + if (result < 0) + printk(KERN_ERR PREFIX "kset_register error: %d\n", result); result = bus_register(&acpi_bus_type); if (result) { -- cgit v1.2.2 From 9805cb76f7bcd3108e012270d9ef2fd8ea3bea55 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 25 Jul 2006 13:30:57 -0400 Subject: ACPI: restore some dmesg to DEBUG-only, ala 2.6.17 The ACPI_EXCEPTION() patch enabled a bunch of messages to print even in the non-DEBUG kernel. Need to change a couple back, and note that ACPI_EXCEPTION takes no \n, but ACPI_DEBUG_PRINT does. No context for object [%p]\n Device `[%s]' is not power manageable\n Signed-off-by: Len Brown --- drivers/acpi/bus.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 7b77ee146a80..279c4bac92e5 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -69,7 +69,8 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device); if (ACPI_FAILURE(status) || !*device) { - ACPI_EXCEPTION((AE_INFO, status, "No context for object [%p]", handle)); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", + handle)); return -ENODEV; } @@ -193,7 +194,7 @@ int acpi_bus_set_power(acpi_handle handle, int state) /* Make sure this is a valid target state */ if (!device->flags.power_manageable) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n", device->kobj.name)); return -ENODEV; } -- cgit v1.2.2 From 5669021e40964303994a20633548732c6bb26636 Mon Sep 17 00:00:00 2001 From: Kristen Carlson Accardi Date: Tue, 1 Aug 2006 14:59:19 -0700 Subject: PCI: docking station: remove dock uevents Remove uevent dock notifications. There are no consumers of these events at present, and uevents are likely not the correct way to send this type of event anyway. Until I get some kind of idea if anyone in userspace cares about dock events, I will just not send any. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/dock.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 1c0a39d8b04e..578b99b71d9c 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -58,8 +58,8 @@ struct dock_dependent_device { }; #define DOCK_DOCKING 0x00000001 -#define DOCK_EVENT KOBJ_DOCK -#define UNDOCK_EVENT KOBJ_UNDOCK +#define DOCK_EVENT 3 +#define UNDOCK_EVENT 2 static struct dock_station *dock_station; @@ -322,11 +322,10 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) static void dock_event(struct dock_station *ds, u32 event, int num) { - struct acpi_device *device; - - device = dock_create_acpi_device(ds->handle); - if (device) - kobject_uevent(&device->kobj, num); + /* + * we don't do events until someone tells me that + * they would like to have them. + */ } /** -- cgit v1.2.2 From fa25d8d6d3fa0fecd00cd4b909011291eae9257d Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Sat, 5 Aug 2006 12:15:02 -0700 Subject: [PATCH] memory hotadd fixes: avoid check in acpi add_memory() does all necessary check to avoid collision. then, acpi layer doesn't have to check region by itself. (*) pfn_valid() just returns page struct is valid or not. It returns 0 if a section has been already added even is ioresource is not added. ioresource collision check in mm/memory_hotplug.c can do more precise collistion check. added enabled bit check just for sanity check.. Signed-off-by: KAMEZAWA Hiroyuki Cc: Keith Mannthey Cc: Yasunori Goto Cc: Dave Hansen Cc: "Brown, Len" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/acpi_memhotplug.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 81e970adeab3..e9175eaeb1df 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -230,17 +230,10 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) * (i.e. memory-hot-remove function) */ list_for_each_entry(info, &mem_device->res_list, list) { - u64 start_pfn, end_pfn; - - start_pfn = info->start_addr >> PAGE_SHIFT; - end_pfn = (info->start_addr + info->length - 1) >> PAGE_SHIFT; - - if (pfn_valid(start_pfn) || pfn_valid(end_pfn)) { - /* already enabled. try next area */ + if (info->enabled) { /* just sanity check...*/ num_enabled++; continue; } - result = add_memory(node, info->start_addr, info->length); if (result) continue; -- cgit v1.2.2 From 5d2870faaa1fdcec795a6bf4dbbfc3e5d57fd7ab Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Sat, 5 Aug 2006 12:15:04 -0700 Subject: [PATCH] memory hotadd fixes: avoid registering res twice both of acpi_memory_enable_device() and acpi_memory_add_device() may evaluate _CRS method. We should avoid evaluate device's resource twice if we could get it successfully in past. Signed-off-by: KAMEZWA Hiroyuki Cc: Keith Mannthey Cc: Yasunori Goto Cc: Dave Hansen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/acpi_memhotplug.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index e9175eaeb1df..b0d4b147b19e 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -129,11 +129,15 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device) struct acpi_memory_info *info, *n; + if (!list_empty(&mem_device->res_list)) + return 0; + status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS, acpi_memory_get_resource, mem_device); if (ACPI_FAILURE(status)) { list_for_each_entry_safe(info, n, &mem_device->res_list, list) kfree(info); + INIT_LIST_HEAD(&mem_device->res_list); return -EINVAL; } -- cgit v1.2.2 From 0ee6a17389ceef65f1a86c38872fa98f08489022 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 11 Aug 2006 08:30:31 +0200 Subject: ACPI: fix kfree in i2c_ec error path Signed-off-by: Jean Delvare Signed-off-by: Len Brown --- drivers/acpi/i2c_ec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/i2c_ec.c b/drivers/acpi/i2c_ec.c index 84239d51dc0c..6809c283ec58 100644 --- a/drivers/acpi/i2c_ec.c +++ b/drivers/acpi/i2c_ec.c @@ -330,7 +330,7 @@ static int acpi_ec_hc_add(struct acpi_device *device) status = acpi_evaluate_integer(ec_hc->handle, "_EC", NULL, &val); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error obtaining _EC\n")); - kfree(ec_hc->smbus); + kfree(ec_hc); kfree(smbus); return -EIO; } -- cgit v1.2.2 From 4d8316d5ea4dcf0bf15d8a06d539ed7c99e9cfbe Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 14 Aug 2006 22:37:22 -0700 Subject: ACPI: fix boot with acpi=off Fix acpi_ac/battery boot with acpi=off Signed-off-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/ac.c | 2 ++ drivers/acpi/battery.c | 3 +++ 2 files changed, 5 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 96309b9660da..11abc7bf777e 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -285,6 +285,8 @@ static int __init acpi_ac_init(void) { int result; + if (acpi_disabled) + return -ENODEV; acpi_ac_dir = acpi_lock_ac_dir(); if (!acpi_ac_dir) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 6e5221707d97..9810e2a55d0a 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -757,6 +757,9 @@ static int __init acpi_battery_init(void) { int result; + if (acpi_disabled) + return -ENODEV; + acpi_battery_dir = acpi_lock_battery_dir(); if (!acpi_battery_dir) return -ENODEV; -- cgit v1.2.2 From b20d2aeb0ad322cbe7fd9120acae6118231b17a3 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 15 Aug 2006 23:21:37 -0400 Subject: ACPI: skip smart battery init when acpi=off Signed-off-by: Len Brown --- drivers/acpi/sbs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index db7b350a5035..62bef0b3b614 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -1714,6 +1714,9 @@ static int __init acpi_sbs_init(void) { int result = 0; + if (acpi_disabled) + return -ENODEV; + init_MUTEX(&sbs_sem); if (capacity_mode != DEF_CAPACITY_UNIT -- cgit v1.2.2 From 7daef60721e03809c7e5f8aa8491df4190f6b56f Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 14 Aug 2006 22:37:24 -0700 Subject: ACPI: add message if firmware_register() init fails Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/bus.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index b2977695e120..7b77ee146a80 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -738,7 +739,10 @@ static int __init acpi_init(void) return -ENODEV; } - firmware_register(&acpi_subsys); + result = firmware_register(&acpi_subsys); + if (result < 0) + printk(KERN_WARNING "%s: firmware_register error: %d\n", + __FUNCTION__, result); result = acpi_bus_init(); -- cgit v1.2.2 From e9a315bcae3b9e0c54fb68ef90d0095956314480 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 14 Aug 2006 22:37:24 -0700 Subject: ACPI: verbose on kset/kobject_register errors Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/scan.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5fcb50c7b778..698a1540e303 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -113,6 +114,8 @@ static struct kset acpi_namespace_kset = { static void acpi_device_register(struct acpi_device *device, struct acpi_device *parent) { + int err; + /* * Linkage * ------- @@ -138,7 +141,10 @@ static void acpi_device_register(struct acpi_device *device, device->kobj.parent = &parent->kobj; device->kobj.ktype = &ktype_acpi_ns; device->kobj.kset = &acpi_namespace_kset; - kobject_register(&device->kobj); + err = kobject_register(&device->kobj); + if (err < 0) + printk(KERN_WARNING "%s: kobject_register error: %d\n", + __FUNCTION__, err); create_sysfs_device_files(device); } @@ -1450,7 +1456,9 @@ static int __init acpi_scan_init(void) if (acpi_disabled) return 0; - kset_register(&acpi_namespace_kset); + result = kset_register(&acpi_namespace_kset); + if (result < 0) + printk(KERN_ERR PREFIX "kset_register error: %d\n", result); result = bus_register(&acpi_bus_type); if (result) { -- cgit v1.2.2 From 07dd4855e7fffeb50565826e5e736509ee8f6129 Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Mon, 14 Aug 2006 22:37:32 -0700 Subject: ACPI: memory hotplug: remove useless message at boot time This is to remove noisy useless message at boot. The message is a ton of "ACPI Exception (acpi_memory-0492): AE_ERROR, handle is no memory device" In my emulation, number of memory devices are not so many (only 6), but, this messages are displayed 114 times. It is showed by acpi_memory_register_notify_handler() which is called by acpi_walk_namespace(). acpi_walk_namespace() parses all of ACPI's namespace and execute acpi_memory_register_notify_handler(). So, it is called for all of the device which is defined in namespace. If the parsing device is not memory, acpi_memhotplug ignores it due to "no match" and will parse next device. This is normal route, not an exception. Signed-off-by: Yasunori Goto Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/acpi_memhotplug.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index b0d4b147b19e..1dda370f402b 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -484,10 +484,8 @@ acpi_memory_register_notify_handler(acpi_handle handle, status = is_memory_device(handle); - if (ACPI_FAILURE(status)){ - ACPI_EXCEPTION((AE_INFO, status, "handle is no memory device")); + if (ACPI_FAILURE(status)) return AE_OK; /* continue */ - } status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, acpi_memory_device_notify, NULL); @@ -503,10 +501,8 @@ acpi_memory_deregister_notify_handler(acpi_handle handle, status = is_memory_device(handle); - if (ACPI_FAILURE(status)){ - ACPI_EXCEPTION((AE_INFO, status, "handle is no memory device")); + if (ACPI_FAILURE(status)) return AE_OK; /* continue */ - } status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, -- cgit v1.2.2 From 5672bde6355f2d12c49df1eec083d25afe489063 Mon Sep 17 00:00:00 2001 From: Handle X Date: Mon, 14 Aug 2006 22:37:27 -0700 Subject: ACPI: hotkey.c fixes, fix for potential crash of hotkey.c While going through the code, I found out some memory leaks and potential crashes in drivers/acpi/hotkey.c Please find the patch to fix them. This patch does the following, 1. Fixes memory leaks in error paths of hotkey_write_config 2. Fixes freeing unallocated pointers in the error paths of hotkey_write_config 3. Uses a loop instead of linear searching for parsing the userspace input in get_params 4. Uses array of char * instead of passing 4 pointer parameters explicitly into the init_{poll_}hotkey_* static functions Signed-off-by: Andrew Morton Acked-by: Luming Yu Signed-off-by: Len Brown --- drivers/acpi/hotkey.c | 281 +++++++++++++++++++++----------------------------- 1 file changed, 119 insertions(+), 162 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c index 32c9d88fd196..1ba2db671865 100644 --- a/drivers/acpi/hotkey.c +++ b/drivers/acpi/hotkey.c @@ -91,6 +91,14 @@ enum { HK_EVENT_ENTERRING_S5, }; +enum conf_entry_enum { + bus_handle = 0, + bus_method = 1, + action_handle = 2, + method = 3, + LAST_CONF_ENTRY +}; + /* procdir we use */ static struct proc_dir_entry *hotkey_proc_dir; static struct proc_dir_entry *hotkey_config; @@ -244,19 +252,15 @@ static int hotkey_info_open_fs(struct inode *inode, struct file *file) static char *format_result(union acpi_object *object) { - char *buf = NULL; - - buf = (char *)kmalloc(RESULT_STR_LEN, GFP_KERNEL); - if (buf) - memset(buf, 0, RESULT_STR_LEN); - else - goto do_fail; + char *buf; + buf = kzalloc(RESULT_STR_LEN, GFP_KERNEL); + if (!buf) + return NULL; /* Now, just support integer type */ if (object->type == ACPI_TYPE_INTEGER) sprintf(buf, "%d\n", (u32) object->integer.value); - do_fail: - return (buf); + return buf; } static int hotkey_polling_seq_show(struct seq_file *seq, void *offset) @@ -486,98 +490,102 @@ static void free_hotkey_device(union acpi_hotkey *key) static void free_hotkey_buffer(union acpi_hotkey *key) { + /* key would never be null, action method could be */ kfree(key->event_hotkey.action_method); } static void free_poll_hotkey_buffer(union acpi_hotkey *key) { + /* key would never be null, others could be*/ kfree(key->poll_hotkey.action_method); kfree(key->poll_hotkey.poll_method); kfree(key->poll_hotkey.poll_result); } static int -init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str, - char *method, int std_num, int external_num) +init_hotkey_device(union acpi_hotkey *key, char **config_entry, + int std_num, int external_num) { acpi_handle tmp_handle; acpi_status status = AE_OK; - if (std_num < 0 || IS_POLL(std_num) || !key) goto do_fail; - if (!bus_str || !action_str || !method) + if (!config_entry[bus_handle] || !config_entry[action_handle] + || !config_entry[method]) goto do_fail; key->link.hotkey_type = ACPI_HOTKEY_EVENT; key->link.hotkey_standard_num = std_num; key->event_hotkey.flag = 0; - key->event_hotkey.action_method = method; + key->event_hotkey.action_method = config_entry[method]; - status = - acpi_get_handle(NULL, bus_str, &(key->event_hotkey.bus_handle)); + status = acpi_get_handle(NULL, config_entry[bus_handle], + &(key->event_hotkey.bus_handle)); if (ACPI_FAILURE(status)) - goto do_fail; + goto do_fail_zero; key->event_hotkey.external_hotkey_num = external_num; - status = - acpi_get_handle(NULL, action_str, + status = acpi_get_handle(NULL, config_entry[action_handle], &(key->event_hotkey.action_handle)); if (ACPI_FAILURE(status)) - goto do_fail; + goto do_fail_zero; status = acpi_get_handle(key->event_hotkey.action_handle, - method, &tmp_handle); + config_entry[method], &tmp_handle); if (ACPI_FAILURE(status)) - goto do_fail; + goto do_fail_zero; return AE_OK; - do_fail: +do_fail_zero: + key->event_hotkey.action_method = NULL; +do_fail: return -ENODEV; } static int -init_poll_hotkey_device(union acpi_hotkey *key, - char *poll_str, - char *poll_method, - char *action_str, char *action_method, int std_num) +init_poll_hotkey_device(union acpi_hotkey *key, char **config_entry, + int std_num) { acpi_status status = AE_OK; acpi_handle tmp_handle; - if (std_num < 0 || IS_EVENT(std_num) || !key) goto do_fail; - - if (!poll_str || !poll_method || !action_str || !action_method) + if (!config_entry[bus_handle] ||!config_entry[bus_method] || + !config_entry[action_handle] || !config_entry[method]) goto do_fail; key->link.hotkey_type = ACPI_HOTKEY_POLLING; key->link.hotkey_standard_num = std_num; key->poll_hotkey.flag = 0; - key->poll_hotkey.poll_method = poll_method; - key->poll_hotkey.action_method = action_method; + key->poll_hotkey.poll_method = config_entry[bus_method]; + key->poll_hotkey.action_method = config_entry[method]; - status = - acpi_get_handle(NULL, poll_str, &(key->poll_hotkey.poll_handle)); + status = acpi_get_handle(NULL, config_entry[bus_handle], + &(key->poll_hotkey.poll_handle)); if (ACPI_FAILURE(status)) - goto do_fail; + goto do_fail_zero; status = acpi_get_handle(key->poll_hotkey.poll_handle, - poll_method, &tmp_handle); + config_entry[bus_method], &tmp_handle); if (ACPI_FAILURE(status)) - goto do_fail; + goto do_fail_zero; status = - acpi_get_handle(NULL, action_str, + acpi_get_handle(NULL, config_entry[action_handle], &(key->poll_hotkey.action_handle)); if (ACPI_FAILURE(status)) - goto do_fail; + goto do_fail_zero; status = acpi_get_handle(key->poll_hotkey.action_handle, - action_method, &tmp_handle); + config_entry[method], &tmp_handle); if (ACPI_FAILURE(status)) - goto do_fail; + goto do_fail_zero; key->poll_hotkey.poll_result = (union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL); if (!key->poll_hotkey.poll_result) - goto do_fail; + goto do_fail_zero; return AE_OK; - do_fail: + +do_fail_zero: + key->poll_hotkey.poll_method = NULL; + key->poll_hotkey.action_method = NULL; +do_fail: return -ENODEV; } @@ -652,17 +660,18 @@ static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset) } static int -get_parms(char *config_record, - int *cmd, - char **bus_handle, - char **bus_method, - char **action_handle, - char **method, int *internal_event_num, int *external_event_num) +get_parms(char *config_record, int *cmd, char **config_entry, + int *internal_event_num, int *external_event_num) { +/* the format of *config_record = + * "1:\d+:*" : "cmd:internal_event_num" + * "\d+:\w+:\w+:\w+:\w+:\d+:\d+" : + * "cmd:bus_handle:bus_method:action_handle:method:internal_event_num:external_event_num" + */ char *tmp, *tmp1, count; + int i; sscanf(config_record, "%d", cmd); - if (*cmd == 1) { if (sscanf(config_record, "%d:%d", cmd, internal_event_num) != 2) @@ -674,59 +683,27 @@ get_parms(char *config_record, if (!tmp) goto do_fail; tmp++; - tmp1 = strchr(tmp, ':'); - if (!tmp1) - goto do_fail; - - count = tmp1 - tmp; - *bus_handle = (char *)kmalloc(count + 1, GFP_KERNEL); - if (!*bus_handle) - goto do_fail; - strncpy(*bus_handle, tmp, count); - *(*bus_handle + count) = 0; - - tmp = tmp1; - tmp++; - tmp1 = strchr(tmp, ':'); - if (!tmp1) - goto do_fail; - count = tmp1 - tmp; - *bus_method = (char *)kmalloc(count + 1, GFP_KERNEL); - if (!*bus_method) - goto do_fail; - strncpy(*bus_method, tmp, count); - *(*bus_method + count) = 0; - - tmp = tmp1; - tmp++; - tmp1 = strchr(tmp, ':'); - if (!tmp1) - goto do_fail; - count = tmp1 - tmp; - *action_handle = (char *)kmalloc(count + 1, GFP_KERNEL); - if (!*action_handle) - goto do_fail; - strncpy(*action_handle, tmp, count); - *(*action_handle + count) = 0; - - tmp = tmp1; - tmp++; - tmp1 = strchr(tmp, ':'); - if (!tmp1) - goto do_fail; - count = tmp1 - tmp; - *method = (char *)kmalloc(count + 1, GFP_KERNEL); - if (!*method) - goto do_fail; - strncpy(*method, tmp, count); - *(*method + count) = 0; - - if (sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num) <= - 0) - goto do_fail; - - return 6; - do_fail: + for (i = 0; i < LAST_CONF_ENTRY; i++) { + tmp1 = strchr(tmp, ':'); + if (!tmp1) { + goto do_fail; + } + count = tmp1 - tmp; + config_entry[i] = kzalloc(count + 1, GFP_KERNEL); + if (!config_entry[i]) + goto handle_failure; + strncpy(config_entry[i], tmp, count); + tmp = tmp1 + 1; + } + if (sscanf(tmp, "%d:%d", internal_event_num, external_event_num) <= 0) + goto handle_failure; + if (!IS_OTHERS(*internal_event_num)) { + return 6; + } +handle_failure: + while (i-- > 0) + kfree(config_entry[i]); +do_fail: return -1; } @@ -736,50 +713,34 @@ static ssize_t hotkey_write_config(struct file *file, size_t count, loff_t * data) { char *config_record = NULL; - char *bus_handle = NULL; - char *bus_method = NULL; - char *action_handle = NULL; - char *method = NULL; + char *config_entry[LAST_CONF_ENTRY]; int cmd, internal_event_num, external_event_num; int ret = 0; - union acpi_hotkey *key = NULL; + union acpi_hotkey *key = kzalloc(sizeof(union acpi_hotkey), GFP_KERNEL); + if (!key) + return -ENOMEM; - config_record = (char *)kmalloc(count + 1, GFP_KERNEL); - if (!config_record) + config_record = kzalloc(count + 1, GFP_KERNEL); + if (!config_record) { + kfree(key); return -ENOMEM; + } if (copy_from_user(config_record, buffer, count)) { kfree(config_record); + kfree(key); printk(KERN_ERR PREFIX "Invalid data\n"); return -EINVAL; } - config_record[count] = 0; - - ret = get_parms(config_record, - &cmd, - &bus_handle, - &bus_method, - &action_handle, - &method, &internal_event_num, &external_event_num); - + ret = get_parms(config_record, &cmd, config_entry, + &internal_event_num, &external_event_num); kfree(config_record); - if (IS_OTHERS(internal_event_num)) - goto do_fail; if (ret != 6) { - do_fail: - kfree(bus_handle); - kfree(bus_method); - kfree(action_handle); - kfree(method); printk(KERN_ERR PREFIX "Invalid data format ret=%d\n", ret); return -EINVAL; } - key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL); - if (!key) - goto do_fail; - memset(key, 0, sizeof(union acpi_hotkey)); if (cmd == 1) { union acpi_hotkey *tmp = NULL; tmp = get_hotkey_by_event(&global_hotkey_list, @@ -791,34 +752,19 @@ static ssize_t hotkey_write_config(struct file *file, goto cont_cmd; } if (IS_EVENT(internal_event_num)) { - kfree(bus_method); - ret = init_hotkey_device(key, bus_handle, action_handle, method, - internal_event_num, - external_event_num); - } else - ret = init_poll_hotkey_device(key, bus_handle, bus_method, - action_handle, method, - internal_event_num); - if (ret) { - kfree(bus_handle); - kfree(action_handle); - if (IS_EVENT(internal_event_num)) - free_hotkey_buffer(key); - else - free_poll_hotkey_buffer(key); - kfree(key); - printk(KERN_ERR PREFIX "Invalid hotkey\n"); - return -EINVAL; + if (init_hotkey_device(key, config_entry, + internal_event_num, external_event_num)) + goto init_hotkey_fail; + } else { + if (init_poll_hotkey_device(key, config_entry, + internal_event_num)) + goto init_poll_hotkey_fail; } - - cont_cmd: - kfree(bus_handle); - kfree(action_handle); - +cont_cmd: switch (cmd) { case 0: - if (get_hotkey_by_event - (&global_hotkey_list, key->link.hotkey_standard_num)) + if (get_hotkey_by_event(&global_hotkey_list, + key->link.hotkey_standard_num)) goto fail_out; else hotkey_add(key); @@ -827,6 +773,7 @@ static ssize_t hotkey_write_config(struct file *file, hotkey_remove(key); break; case 2: + /* key is kfree()ed if matched*/ if (hotkey_update(key)) goto fail_out; break; @@ -835,11 +782,22 @@ static ssize_t hotkey_write_config(struct file *file, break; } return count; - fail_out: - if (IS_EVENT(internal_event_num)) - free_hotkey_buffer(key); - else - free_poll_hotkey_buffer(key); + +init_poll_hotkey_fail: /* failed init_poll_hotkey_device */ + kfree(config_entry[bus_method]); + config_entry[bus_method] = NULL; +init_hotkey_fail: /* failed init_hotkey_device */ + kfree(config_entry[method]); +fail_out: + kfree(config_entry[bus_handle]); + kfree(config_entry[action_handle]); + /* No double free since elements =NULL for error cases */ + if (IS_EVENT(internal_event_num)) { + if (config_entry[bus_method]) + kfree(config_entry[bus_method]); + free_hotkey_buffer(key); /* frees [method] */ + } else + free_poll_hotkey_buffer(key); /* frees [bus_method]+[method] */ kfree(key); printk(KERN_ERR PREFIX "invalid key\n"); return -EINVAL; @@ -923,10 +881,9 @@ static ssize_t hotkey_execute_aml_method(struct file *file, union acpi_hotkey *key; - arg = (char *)kmalloc(count + 1, GFP_KERNEL); + arg = kzalloc(count + 1, GFP_KERNEL); if (!arg) return -ENOMEM; - arg[count] = 0; if (copy_from_user(arg, buffer, count)) { kfree(arg); -- cgit v1.2.2 From d68909f4c3eee09c13d4e5c86512c6c075553dbd Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 16 Aug 2006 19:16:58 -0400 Subject: ACPI: avoid irqrouter_resume might_sleep oops on resume from S4 __might_sleep+0x8e/0x93 acpi_os_wait_semaphore+0x50/0xa3 acpi_ut_acquire_mutex+0x28/0x6a acpi_ns_get_node+0x46/0x88 acpi_ns_evaluate+0x2d/0xfc acpi_rs_set_srs_method_data+0xc5/0xe1 acpi_set_current_resources+0x31/0x3f acpi_pci_link_set+0xfc/0x1a5 irqrouter_resume+0x48/0x5f and __might_sleep+0x8e/0x93 kmem_cache_alloc+0x2a/0x8f acpi_evaluate_integer+0x32/0x96 acpi_bus_get_status+0x30/0x84 acpi_pci_link_set+0x12a/0x1a5 irqrouter_resume+0x48/0x5f http://bugzilla.kernel.org/show_bug.cgi?id=6810 Signed-off-by: Len Brown --- drivers/acpi/osl.c | 10 ++++++++++ drivers/acpi/utils.c | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index b7d1514cd199..507f051d1cef 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -746,6 +746,16 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout)); + /* + * This can be called during resume with interrupts off. + * Like boot-time, we should be single threaded and will + * always get the lock if we try -- timeout or not. + * If this doesn't succeed, then we will oops courtesy of + * might_sleep() in down(). + */ + if (!down_trylock(sem)) + return AE_OK; + switch (timeout) { /* * No Wait: diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index f48227f4c8c9..d0d84c43a9d4 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -262,7 +262,7 @@ acpi_evaluate_integer(acpi_handle handle, if (!data) return AE_BAD_PARAMETER; - element = kmalloc(sizeof(union acpi_object), GFP_KERNEL); + element = kmalloc(sizeof(union acpi_object), irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL); if (!element) return AE_NO_MEMORY; -- cgit v1.2.2