From e1d3a90846b40ad3160bf4b648d36c6badad39ac Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Wed, 11 Jun 2008 16:35:17 +0200 Subject: pci, acpi: reroute PCI interrupt to legacy boot interrupt equivalent Some chipsets (e.g. intel 6700PXH) generate a legacy INTx when the IRQ entry in the chipset's IO-APIC is masked (as, e.g. the RT kernel does during interrupt handling). On chipsets where this INTx generation cannot be disabled, we reroute the valid interrupts to their legacy equivalent to get rid of spurious interrupts that might otherwise bring down (vital) interrupt lines through spurious interrupt detection in note_interrupt(). This patch benefited from discussions with Alexander Graf, Torsten Duwe, Ihno Krumreich, Daniel Gollub, Hannes Reinecke. The conclusions we drew and the patch itself are the authors' responsibility alone. Signed-off-by: Stefan Assmann Signed-off-by: Olaf Dabrunz Signed-off-by: Ingo Molnar --- drivers/acpi/pci_irq.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 89022a74faee..b37cb0a9826e 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -384,6 +384,27 @@ acpi_pci_free_irq(struct acpi_prt_entry *entry, return irq; } +#ifdef CONFIG_X86_IO_APIC +extern int noioapicquirk; + +static int bridge_has_boot_interrupt_variant(struct pci_bus *bus) +{ + struct pci_bus *bus_it; + + for (bus_it = bus ; bus_it ; bus_it = bus_it->parent) { + if (!bus_it->self) + return 0; + + printk(KERN_INFO "vendor=%04x device=%04x\n", bus_it->self->vendor, + bus_it->self->device); + + if (bus_it->self->irq_reroute_variant) + return bus_it->self->irq_reroute_variant; + } + return 0; +} +#endif /* CONFIG_X86_IO_APIC */ + /* * acpi_pci_irq_lookup * success: return IRQ >= 0 @@ -413,6 +434,41 @@ acpi_pci_irq_lookup(struct pci_bus *bus, } ret = func(entry, triggering, polarity, link); + +#ifdef CONFIG_X86_IO_APIC + /* + * Some chipsets (e.g. intel 6700PXH) generate a legacy INTx when the + * IRQ entry in the chipset's IO-APIC is masked (as, e.g. the RT kernel + * does during interrupt handling). When this INTx generation cannot be + * disabled, we reroute these interrupts to their legacy equivalent to + * get rid of spurious interrupts. + */ + if (!noioapicquirk) { + switch (bridge_has_boot_interrupt_variant(bus)) { + case 0: + /* no rerouting necessary */ + break; + + case INTEL_IRQ_REROUTE_VARIANT: + /* + * Remap according to INTx routing table in 6700PXH + * specs, intel order number 302628-002, section + * 2.15.2. Other chipsets (80332, ...) have the same + * mapping and are handled here as well. + */ + printk(KERN_INFO "pci irq %d -> rerouted to legacy " + "irq %d\n", ret, (ret % 4) + 16); + ret = (ret % 4) + 16; + break; + + default: + printk(KERN_INFO "not rerouting irq %d to legacy irq: " + "unknown mapping\n", ret); + break; + } + } +#endif /* CONFIG_X86_IO_APIC */ + return ret; } -- cgit v1.2.3 From 910dfae298f7b3dae0e9a52736182a3b0559ca35 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Mon, 1 Sep 2008 14:27:04 +0200 Subject: ACPI: cpufreq, processor: Detect old BIOS, not supporting CPU freq on a recent CPU. On Intel CPUs it is rather common and a good hint that BIOSes which do provide _PPC func, but not the frequencies itself in _PSS function, are old and need to be updated for CPU freq support. Tell the user/vendor he has a BIOS/firmware problem. Make use of FW_BUG interface to give vendors and users the ability to automatically check with (or let linuxfirmwarekit do that): dmesg |grep "Firmware Bug" Signed-off-by: Thomas Renninger Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/processor_perflib.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 80c251ec6d2a..242f8143008a 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -38,6 +38,7 @@ #include #endif +#include #include #include @@ -334,7 +335,6 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr) acpi_status status = AE_OK; acpi_handle handle = NULL; - if (!pr || !pr->performance || !pr->handle) return -EINVAL; @@ -347,13 +347,25 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr) result = acpi_processor_get_performance_control(pr); if (result) - return result; + goto update_bios; result = acpi_processor_get_performance_states(pr); if (result) - return result; + goto update_bios; return 0; + + /* + * Having _PPC but missing frequencies (_PSS, _PCT) is a very good hint that + * the BIOS is older than the CPU and does not know its frequencies + */ + update_bios: + if (ACPI_SUCCESS(acpi_get_handle(pr->handle, "_PPC", &handle))){ + if(boot_cpu_has(X86_FEATURE_EST)) + printk(KERN_WARNING FW_BUG "BIOS needs update for CPU " + "frequency support\n"); + } + return result; } int acpi_processor_notify_smm(struct module *calling_module) -- cgit v1.2.3 From 8b59560a3baf2e7c24e0fb92ea5d09eca92805db Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 28 Aug 2008 10:02:03 +0800 Subject: ACPI: dock: avoid check _STA method In some BIOSes, every _STA method call will send a notification again, this cause freeze. And in some BIOSes, it appears _STA should be called after _DCK. This tries to avoid calls _STA, and still keep the device present check. http://bugzilla.kernel.org/show_bug.cgi?id=10431 Signed-off-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/dock.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 7d2edf143f16..25d2161ae9d9 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -604,14 +604,17 @@ static int handle_eject_request(struct dock_station *ds, u32 event) static void dock_notify(acpi_handle handle, u32 event, void *data) { struct dock_station *ds = data; + struct acpi_device *tmp; switch (event) { case ACPI_NOTIFY_BUS_CHECK: - if (!dock_in_progress(ds) && dock_present(ds)) { + if (!dock_in_progress(ds) && acpi_bus_get_device(ds->handle, + &tmp)) { begin_dock(ds); dock(ds); if (!dock_present(ds)) { printk(KERN_ERR PREFIX "Unable to dock!\n"); + complete_dock(ds); break; } atomic_notifier_call_chain(&dock_notifier_list, -- cgit v1.2.3 From 82545394e0690aaef446cb262aa5dac0f9c7156e Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 28 Aug 2008 10:02:41 +0800 Subject: dock: fix eject request process (2.6.27-rc1 regression) commit 2a7feab28d3fc060d320eaba192e49dad1079b7e introduces a bug. My thinkpad actually will send an eject_request and we should follow the eject process to finish the eject, otherwise system still thinks the bay is present. Signed-off-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/dock.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 25d2161ae9d9..78d27cef573f 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -575,11 +575,6 @@ static int handle_eject_request(struct dock_station *ds, u32 event) */ dock_event(ds, event, UNDOCK_EVENT); - if (!dock_present(ds)) { - complete_undock(ds); - return -ENODEV; - } - hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST); undock(ds); eject_dock(ds); -- cgit v1.2.3 From 406f692d0803d73acd3984c1e11719d3a913fd5e Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 28 Aug 2008 10:03:26 +0800 Subject: dock: add _LCK support support _LCK method, which is a optional method for hotplug lenb: we have not seen _LCK used in the field yet Signed-off-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/dock.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 78d27cef573f..7bdf93b74690 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -452,6 +452,25 @@ static inline void complete_undock(struct dock_station *ds) ds->flags &= ~(DOCK_UNDOCKING); } +static void dock_lock(struct dock_station *ds, int lock) +{ + struct acpi_object_list arg_list; + union acpi_object arg; + acpi_status status; + + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = !!lock; + status = acpi_evaluate_object(ds->handle, "_LCK", &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + if (lock) + printk(KERN_WARNING PREFIX "Locking device failed\n"); + else + printk(KERN_WARNING PREFIX "Unlocking device failed\n"); + } +} + /** * dock_in_progress - see if we are in the middle of handling a dock event * @ds: the dock station @@ -577,6 +596,7 @@ static int handle_eject_request(struct dock_station *ds, u32 event) hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST); undock(ds); + dock_lock(ds, 0); eject_dock(ds); if (dock_present(ds)) { printk(KERN_ERR PREFIX "Unable to undock!\n"); @@ -617,6 +637,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) hotplug_dock_devices(ds, event); complete_dock(ds); dock_event(ds, event, DOCK_EVENT); + dock_lock(ds, 1); } break; case ACPI_NOTIFY_DEVICE_CHECK: -- cgit v1.2.3 From db350b084dc2cf816288643861ce07b0562dd723 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 28 Aug 2008 10:03:58 +0800 Subject: dock: add bay and battery hotplug support Make the dock driver support bay and battery hotplug. They are all regarded as dock, so handling can be unified. Signed-off-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/dock.c | 223 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 175 insertions(+), 48 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 7bdf93b74690..799a0fdbb62d 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -48,7 +48,6 @@ MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to " " before undocking"); static struct atomic_notifier_head dock_notifier_list; -static struct platform_device *dock_device; static char dock_device_name[] = "dock"; static const struct acpi_device_id dock_device_ids[] = { @@ -65,7 +64,12 @@ struct dock_station { struct mutex hp_lock; struct list_head dependent_devices; struct list_head hotplug_devices; + + struct list_head sibiling; + struct platform_device *dock_device; }; +static LIST_HEAD(dock_stations); +static int dock_station_count; struct dock_dependent_device { struct list_head list; @@ -77,11 +81,12 @@ struct dock_dependent_device { #define DOCK_DOCKING 0x00000001 #define DOCK_UNDOCKING 0x00000002 +#define DOCK_IS_DOCK 0x00000010 +#define DOCK_IS_ATA 0x00000020 +#define DOCK_IS_BAT 0x00000040 #define DOCK_EVENT 3 #define UNDOCK_EVENT 2 -static struct dock_station *dock_station; - /***************************************************************************** * Dock Dependent device functions * *****************************************************************************/ @@ -199,6 +204,60 @@ static int is_dock(acpi_handle handle) return 1; } +static int is_ejectable(acpi_handle handle) +{ + acpi_status status; + acpi_handle tmp; + + status = acpi_get_handle(handle, "_EJ0", &tmp); + if (ACPI_FAILURE(status)) + return 0; + return 1; +} + +static int is_ata(acpi_handle handle) +{ + acpi_handle tmp; + + if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) || + (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) || + (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) || + (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp)))) + return 1; + + return 0; +} + +static int is_battery(acpi_handle handle) +{ + struct acpi_device_info *info; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + int ret = 1; + + if (!ACPI_SUCCESS(acpi_get_object_info(handle, &buffer))) + return 0; + info = buffer.pointer; + if (!(info->valid & ACPI_VALID_HID)) + ret = 0; + else + ret = !strcmp("PNP0C0A", info->hardware_id.value); + + kfree(buffer.pointer); + return ret; +} + +static int is_ejectable_bay(acpi_handle handle) +{ + acpi_handle phandle; + if (!is_ejectable(handle)) + return 0; + if (is_battery(handle) || is_ata(handle)) + return 1; + if (!acpi_get_parent(handle, &phandle) && is_ata(phandle)) + return 1; + return 0; +} + /** * is_dock_device - see if a device is on a dock station * @handle: acpi handle of the device @@ -209,11 +268,17 @@ static int is_dock(acpi_handle handle) */ int is_dock_device(acpi_handle handle) { - if (!dock_station) + struct dock_station *dock_station; + + if (!dock_station_count) return 0; - if (is_dock(handle) || find_dock_dependent_device(dock_station, handle)) + if (is_dock(handle)) return 1; + list_for_each_entry(dock_station, &dock_stations, sibiling) { + if (find_dock_dependent_device(dock_station, handle)) + return 1; + } return 0; } @@ -341,7 +406,7 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) static void dock_event(struct dock_station *ds, u32 event, int num) { - struct device *dev = &dock_device->dev; + struct device *dev = &ds->dock_device->dev; char event_string[13]; char *envp[] = { event_string, NULL }; @@ -414,7 +479,7 @@ static void handle_dock(struct dock_station *ds, int dock) arg.type = ACPI_TYPE_INTEGER; arg.integer.value = dock; status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) printk(KERN_ERR PREFIX "%s - failed to execute _DCK\n", (char *)name_buffer.pointer); kfree(buffer.pointer); @@ -498,7 +563,7 @@ static int dock_in_progress(struct dock_station *ds) */ int register_dock_notifier(struct notifier_block *nb) { - if (!dock_station) + if (!dock_station_count) return -ENODEV; return atomic_notifier_chain_register(&dock_notifier_list, nb); @@ -512,7 +577,7 @@ EXPORT_SYMBOL_GPL(register_dock_notifier); */ void unregister_dock_notifier(struct notifier_block *nb) { - if (!dock_station) + if (!dock_station_count) return; atomic_notifier_chain_unregister(&dock_notifier_list, nb); @@ -535,20 +600,23 @@ register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler, void *context) { struct dock_dependent_device *dd; + struct dock_station *dock_station; - if (!dock_station) + if (!dock_station_count) return -ENODEV; /* * make sure this handle is for a device dependent on the dock, * this would include the dock station itself */ - dd = find_dock_dependent_device(dock_station, handle); - if (dd) { - dd->handler = handler; - dd->context = context; - dock_add_hotplug_device(dock_station, dd); - return 0; + list_for_each_entry(dock_station, &dock_stations, sibiling) { + dd = find_dock_dependent_device(dock_station, handle); + if (dd) { + dd->handler = handler; + dd->context = context; + dock_add_hotplug_device(dock_station, dd); + return 0; + } } return -EINVAL; @@ -563,13 +631,16 @@ EXPORT_SYMBOL_GPL(register_hotplug_dock_device); void unregister_hotplug_dock_device(acpi_handle handle) { struct dock_dependent_device *dd; + struct dock_station *dock_station; - if (!dock_station) + if (!dock_station_count) return; - dd = find_dock_dependent_device(dock_station, handle); - if (dd) - dock_del_hotplug_device(dock_station, dd); + list_for_each_entry(dock_station, &dock_stations, sibiling) { + dd = find_dock_dependent_device(dock_station, handle); + if (dd) + dock_del_hotplug_device(dock_station, dd); + } } EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); @@ -620,9 +691,28 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) { struct dock_station *ds = data; struct acpi_device *tmp; + int surprise_removal = 0; + /* + * According to acpi spec 3.0a, if a DEVICE_CHECK notification + * is sent and _DCK is present, it is assumed to mean an undock + * request. + */ + if ((ds->flags & DOCK_IS_DOCK) && event == ACPI_NOTIFY_DEVICE_CHECK) + event = ACPI_NOTIFY_EJECT_REQUEST; + + /* + * dock station: BUS_CHECK - docked or surprise removal + * DEVICE_CHECK - undocked + * other device: BUS_CHECK/DEVICE_CHECK - added or surprise removal + * + * To simplify event handling, dock dependent device handler always + * get ACPI_NOTIFY_BUS_CHECK/ACPI_NOTIFY_DEVICE_CHECK for add and + * ACPI_NOTIFY_EJECT_REQUEST for removal + */ switch (event) { case ACPI_NOTIFY_BUS_CHECK: + case ACPI_NOTIFY_DEVICE_CHECK: if (!dock_in_progress(ds) && acpi_bus_get_device(ds->handle, &tmp)) { begin_dock(ds); @@ -638,20 +728,17 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) complete_dock(ds); dock_event(ds, event, DOCK_EVENT); dock_lock(ds, 1); + break; } - break; - case ACPI_NOTIFY_DEVICE_CHECK: - /* - * According to acpi spec 3.0a, if a DEVICE_CHECK notification - * is sent and _DCK is present, it is assumed to mean an - * undock request. This notify routine will only be called - * for objects defining _DCK, so we will fall through to eject - * request here. However, we will pass an eject request through - * to the driver who wish to hotplug. - */ + if (dock_present(ds) || dock_in_progress(ds)) + break; + /* This is a surprise removal */ + surprise_removal = 1; + event = ACPI_NOTIFY_EJECT_REQUEST; + /* Fall back */ case ACPI_NOTIFY_EJECT_REQUEST: begin_undock(ds); - if (immediate_undock) + if (immediate_undock || surprise_removal) handle_eject_request(ds, event); else dock_event(ds, event, UNDOCK_EVENT); @@ -707,6 +794,8 @@ fdd_out: static ssize_t show_docked(struct device *dev, struct device_attribute *attr, char *buf) { + struct dock_station *dock_station = *((struct dock_station **) + dev->platform_data); return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station)); } @@ -718,6 +807,8 @@ static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); static ssize_t show_flags(struct device *dev, struct device_attribute *attr, char *buf) { + struct dock_station *dock_station = *((struct dock_station **) + dev->platform_data); return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags); } @@ -730,6 +821,8 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int ret; + struct dock_station *dock_station = *((struct dock_station **) + dev->platform_data); if (!count) return -EINVAL; @@ -747,6 +840,8 @@ static ssize_t show_dock_uid(struct device *dev, struct device_attribute *attr, char *buf) { unsigned long lbuf; + struct dock_station *dock_station = *((struct dock_station **) + dev->platform_data); acpi_status status = acpi_evaluate_integer(dock_station->handle, "_UID", NULL, &lbuf); if (ACPI_FAILURE(status)) @@ -768,6 +863,8 @@ static int dock_add(acpi_handle handle) int ret; acpi_status status; struct dock_dependent_device *dd; + struct dock_station *dock_station; + struct platform_device *dock_device; /* allocate & initialize the dock_station private data */ dock_station = kzalloc(sizeof(*dock_station), GFP_KERNEL); @@ -777,22 +874,34 @@ static int dock_add(acpi_handle handle) dock_station->last_dock_time = jiffies - HZ; INIT_LIST_HEAD(&dock_station->dependent_devices); INIT_LIST_HEAD(&dock_station->hotplug_devices); + INIT_LIST_HEAD(&dock_station->sibiling); spin_lock_init(&dock_station->dd_lock); mutex_init(&dock_station->hp_lock); ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); /* initialize platform device stuff */ - dock_device = - platform_device_register_simple(dock_device_name, 0, NULL, 0); + dock_station->dock_device = + platform_device_register_simple(dock_device_name, + dock_station_count, NULL, 0); + dock_device = dock_station->dock_device; if (IS_ERR(dock_device)) { kfree(dock_station); dock_station = NULL; return PTR_ERR(dock_device); } + platform_device_add_data(dock_device, &dock_station, + sizeof(struct dock_station *)); /* we want the dock device to send uevents */ dock_device->dev.uevent_suppress = 0; + if (is_dock(handle)) + dock_station->flags |= DOCK_IS_DOCK; + if (is_ata(handle)) + dock_station->flags |= DOCK_IS_ATA; + if (is_battery(handle)) + dock_station->flags |= DOCK_IS_BAT; + ret = device_create_file(&dock_device->dev, &dev_attr_docked); if (ret) { printk("Error %d adding sysfs file\n", ret); @@ -858,8 +967,8 @@ static int dock_add(acpi_handle handle) goto dock_add_err; } - printk(KERN_INFO PREFIX "%s\n", ACPI_DOCK_DRIVER_DESCRIPTION); - + dock_station_count++; + list_add(&dock_station->sibiling, &dock_stations); return 0; dock_add_err: @@ -878,12 +987,13 @@ dock_add_err_unregister: /** * dock_remove - free up resources related to the dock station */ -static int dock_remove(void) +static int dock_remove(struct dock_station *dock_station) { struct dock_dependent_device *dd, *tmp; acpi_status status; + struct platform_device *dock_device = dock_station->dock_device; - if (!dock_station) + if (!dock_station_count) return 0; /* remove dependent devices */ @@ -923,41 +1033,58 @@ static int dock_remove(void) static acpi_status find_dock(acpi_handle handle, u32 lvl, void *context, void **rv) { - int *count = context; acpi_status status = AE_OK; if (is_dock(handle)) { if (dock_add(handle) >= 0) { - (*count)++; status = AE_CTRL_TERMINATE; } } return status; } -static int __init dock_init(void) +static acpi_status +find_bay(acpi_handle handle, u32 lvl, void *context, void **rv) { - int num = 0; - - dock_station = NULL; + /* If bay is in a dock, it's already handled */ + if (is_ejectable_bay(handle) && !is_dock_device(handle)) + dock_add(handle); + return AE_OK; +} +static int __init dock_init(void) +{ if (acpi_disabled) return 0; /* look for a dock station */ acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, find_dock, &num, NULL); + ACPI_UINT32_MAX, find_dock, NULL, NULL); - if (!num) - printk(KERN_INFO "No dock devices found.\n"); + /* look for bay */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, find_bay, NULL, NULL); + if (!dock_station_count) { + printk(KERN_INFO PREFIX "No dock devices found.\n"); + return 0; + } + printk(KERN_INFO PREFIX "%s: %d docks/bays found\n", + ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count); return 0; } static void __exit dock_exit(void) { - dock_remove(); + struct dock_station *dock_station; + + list_for_each_entry(dock_station, &dock_stations, sibiling) + dock_remove(dock_station); } -postcore_initcall(dock_init); +/* + * Must be called before drivers of devices in dock, otherwise we can't know + * which devices are in a dock + */ +subsys_initcall(dock_init); module_exit(dock_exit); -- cgit v1.2.3 From 6bd00a61ab63d4ceb635ae0316353c11c900b8d8 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 28 Aug 2008 10:04:29 +0800 Subject: ACPI: introduce notifier change to avoid duplicates The battery driver already registers notification handler. To avoid registering notification handler again, introduce a notifier chain in global system notifier handler and use it in dock driver. Signed-off-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/bus.c | 15 +++++++++++++++ drivers/acpi/dock.c | 46 ++++++++++++++++++++++++---------------------- 2 files changed, 39 insertions(+), 22 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index ccae305ee55d..0dc44945725e 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -496,6 +496,19 @@ static int acpi_bus_check_scope(struct acpi_device *device) return 0; } +static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list); +int register_acpi_bus_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&acpi_bus_notify_list, nb); +} +EXPORT_SYMBOL_GPL(register_acpi_bus_notifier); + +void unregister_acpi_bus_notifier(struct notifier_block *nb) +{ + blocking_notifier_chain_unregister(&acpi_bus_notify_list, nb); +} +EXPORT_SYMBOL_GPL(unregister_acpi_bus_notifier); + /** * acpi_bus_notify * --------------- @@ -506,6 +519,8 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) int result = 0; struct acpi_device *device = NULL; + blocking_notifier_call_chain(&acpi_bus_notify_list, + type, (void *)handle); if (acpi_bus_get_device(handle, &device)) return; diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 799a0fdbb62d..2563bc62987d 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -748,6 +748,28 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) } } +static int acpi_dock_notifier_call(struct notifier_block *this, + unsigned long event, void *data) +{ + struct dock_station *dock_station; + acpi_handle handle = (acpi_handle)data; + + if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK + && event != ACPI_NOTIFY_EJECT_REQUEST) + return 0; + list_for_each_entry(dock_station, &dock_stations, sibiling) { + if (dock_station->handle == handle) { + dock_notify(handle, event, dock_station); + return 0 ; + } + } + return 0; +} + +static struct notifier_block dock_acpi_notifier = { + .notifier_call = acpi_dock_notifier_call, +}; + /** * find_dock_devices - find devices on the dock station * @handle: the handle of the device we are examining @@ -861,7 +883,6 @@ static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL); static int dock_add(acpi_handle handle) { int ret; - acpi_status status; struct dock_dependent_device *dd; struct dock_station *dock_station; struct platform_device *dock_device; @@ -956,23 +977,10 @@ static int dock_add(acpi_handle handle) } add_dock_dependent_device(dock_station, dd); - /* register for dock events */ - status = acpi_install_notify_handler(dock_station->handle, - ACPI_SYSTEM_NOTIFY, - dock_notify, dock_station); - - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Error installing notify handler\n"); - ret = -ENODEV; - goto dock_add_err; - } - dock_station_count++; list_add(&dock_station->sibiling, &dock_stations); return 0; -dock_add_err: - kfree(dd); dock_add_err_unregister: device_remove_file(&dock_device->dev, &dev_attr_docked); device_remove_file(&dock_device->dev, &dev_attr_undock); @@ -990,7 +998,6 @@ dock_add_err_unregister: static int dock_remove(struct dock_station *dock_station) { struct dock_dependent_device *dd, *tmp; - acpi_status status; struct platform_device *dock_device = dock_station->dock_device; if (!dock_station_count) @@ -1001,13 +1008,6 @@ static int dock_remove(struct dock_station *dock_station) list) kfree(dd); - /* remove dock notify handler */ - status = acpi_remove_notify_handler(dock_station->handle, - ACPI_SYSTEM_NOTIFY, - dock_notify); - if (ACPI_FAILURE(status)) - printk(KERN_ERR "Error removing notify handler\n"); - /* cleanup sysfs */ device_remove_file(&dock_device->dev, &dev_attr_docked); device_remove_file(&dock_device->dev, &dev_attr_undock); @@ -1069,6 +1069,7 @@ static int __init dock_init(void) return 0; } + register_acpi_bus_notifier(&dock_acpi_notifier); printk(KERN_INFO PREFIX "%s: %d docks/bays found\n", ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count); return 0; @@ -1078,6 +1079,7 @@ static void __exit dock_exit(void) { struct dock_station *dock_station; + unregister_acpi_bus_notifier(&dock_acpi_notifier); list_for_each_entry(dock_station, &dock_stations, sibiling) dock_remove(dock_station); } -- cgit v1.2.3 From 19cd847ab24fefe9e50101ec94479e0400a08650 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 28 Aug 2008 10:05:06 +0800 Subject: ACPI: fix hotplug race The hotplug notification handler and drivers' notification handler all run in one workqueue. Before hotplug removes an acpi device, the device driver's notification handler is already be recorded to run just after global notification handler. After hotplug notification handler runs, acpica will notice a NULL notification handler and crash. So now we run run hotplug in another workqueue and wait for all acpi notication handlers finish. This was found in battery hotplug, but actually all hotplug can be affected. Signed-off-by: Zhang Rui Signed-off-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/dock.c | 25 ++++++++++++++++++++++++- drivers/acpi/osl.c | 46 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 65 insertions(+), 6 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 2563bc62987d..4b395b1e61b2 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -748,6 +748,20 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) } } +struct dock_data { + acpi_handle handle; + unsigned long event; + struct dock_station *ds; +}; + +static void acpi_dock_deferred_cb(void *context) +{ + struct dock_data *data = (struct dock_data *)context; + + dock_notify(data->handle, data->event, data->ds); + kfree(data); +} + static int acpi_dock_notifier_call(struct notifier_block *this, unsigned long event, void *data) { @@ -759,7 +773,16 @@ static int acpi_dock_notifier_call(struct notifier_block *this, return 0; list_for_each_entry(dock_station, &dock_stations, sibiling) { if (dock_station->handle == handle) { - dock_notify(handle, event, dock_station); + struct dock_data *dock_data; + + dock_data = kmalloc(sizeof(*dock_data), GFP_KERNEL); + if (!dock_data) + return 0; + dock_data->handle = handle; + dock_data->event = event; + dock_data->ds = dock_station; + acpi_os_hotplug_execute(acpi_dock_deferred_cb, + dock_data); return 0 ; } } diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 235a1386888a..750e0df15604 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -682,6 +682,22 @@ static void acpi_os_execute_deferred(struct work_struct *work) return; } +static void acpi_os_execute_hp_deferred(struct work_struct *work) +{ + struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); + if (!dpc) { + printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); + return; + } + + acpi_os_wait_events_complete(NULL); + + dpc->function(dpc->context); + kfree(dpc); + + return; +} + /******************************************************************************* * * FUNCTION: acpi_os_execute @@ -697,12 +713,13 @@ static void acpi_os_execute_deferred(struct work_struct *work) * ******************************************************************************/ -acpi_status acpi_os_execute(acpi_execute_type type, - acpi_osd_exec_callback function, void *context) +static acpi_status __acpi_os_execute(acpi_execute_type type, + acpi_osd_exec_callback function, void *context, int hp) { acpi_status status = AE_OK; struct acpi_os_dpc *dpc; struct workqueue_struct *queue; + int ret; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); @@ -726,9 +743,17 @@ acpi_status acpi_os_execute(acpi_execute_type type, dpc->function = function; dpc->context = context; - INIT_WORK(&dpc->work, acpi_os_execute_deferred); - queue = (type == OSL_NOTIFY_HANDLER) ? kacpi_notify_wq : kacpid_wq; - if (!queue_work(queue, &dpc->work)) { + if (!hp) { + INIT_WORK(&dpc->work, acpi_os_execute_deferred); + queue = (type == OSL_NOTIFY_HANDLER) ? + kacpi_notify_wq : kacpid_wq; + ret = queue_work(queue, &dpc->work); + } else { + INIT_WORK(&dpc->work, acpi_os_execute_hp_deferred); + ret = schedule_work(&dpc->work); + } + + if (!ret) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Call to queue_work() failed.\n")); status = AE_ERROR; @@ -737,8 +762,19 @@ acpi_status acpi_os_execute(acpi_execute_type type, return_ACPI_STATUS(status); } +acpi_status acpi_os_execute(acpi_execute_type type, + acpi_osd_exec_callback function, void *context) +{ + return __acpi_os_execute(type, function, context, 0); +} EXPORT_SYMBOL(acpi_os_execute); +acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function, + void *context) +{ + return __acpi_os_execute(0, function, context, 1); +} + void acpi_os_wait_events_complete(void *context) { flush_workqueue(kacpid_wq); -- cgit v1.2.3 From f730ae1838635a02aa60834762c61566911d004c Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 28 Aug 2008 10:05:45 +0800 Subject: libata: remove functions now handed by ACPI dock driver dock driver can handle ata(bay) hotplug now. dock driver already handles _EJ0 and _STA, so remove them. Also libata doesn't need register notification handler anymore. Signed-off-by: Shaohua Li Acked-by: Tejun Heo Signed-off-by: Len Brown --- drivers/acpi/dock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 4b395b1e61b2..f19f643fb362 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -738,7 +738,8 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) /* Fall back */ case ACPI_NOTIFY_EJECT_REQUEST: begin_undock(ds); - if (immediate_undock || surprise_removal) + if ((immediate_undock && !(ds->flags & DOCK_IS_ATA)) + || surprise_removal) handle_eject_request(ds, event); else dock_event(ds, event, UNDOCK_EVENT); -- cgit v1.2.3 From 1253f7aabfebc51446dbec5c8895c5c8846dfe06 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 28 Aug 2008 10:06:16 +0800 Subject: dock: introduce .uevent for devices in dock, eg libata dock's uevent reported itself, not ata. It might be difficult to find an ata device just according to a dock. This patch introduces docking ops for each device in a dock. when docking, dock driver can send device specific uevent. This should help dock station too (not just bay) Signed-off-by: Shaohua Li Acked-by: Tejun Heo Signed-off-by: Len Brown --- drivers/acpi/dock.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index f19f643fb362..ac7dfefcb50b 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -75,7 +75,7 @@ struct dock_dependent_device { struct list_head list; struct list_head hotplug_list; acpi_handle handle; - acpi_notify_handler handler; + struct acpi_dock_ops *ops; void *context; }; @@ -385,8 +385,8 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) * First call driver specific hotplug functions */ list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) { - if (dd->handler) - dd->handler(dd->handle, event, dd->context); + if (dd->ops && dd->ops->handler) + dd->ops->handler(dd->handle, event, dd->context); } /* @@ -409,6 +409,7 @@ static void dock_event(struct dock_station *ds, u32 event, int num) struct device *dev = &ds->dock_device->dev; char event_string[13]; char *envp[] = { event_string, NULL }; + struct dock_dependent_device *dd; if (num == UNDOCK_EVENT) sprintf(event_string, "EVENT=undock"); @@ -419,7 +420,14 @@ static void dock_event(struct dock_station *ds, u32 event, int num) * Indicate that the status of the dock station has * changed. */ - kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); + if (num == DOCK_EVENT) + kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); + + list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) + if (dd->ops && dd->ops->uevent) + dd->ops->uevent(dd->handle, event, dd->context); + if (num != DOCK_EVENT) + kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); } /** @@ -588,7 +596,7 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier); /** * register_hotplug_dock_device - register a hotplug function * @handle: the handle of the device - * @handler: the acpi_notifier_handler to call after docking + * @ops: handlers to call after docking * @context: device specific data * * If a driver would like to perform a hotplug operation after a dock @@ -596,7 +604,7 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier); * the dock driver after _DCK is executed. */ int -register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler, +register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops, void *context) { struct dock_dependent_device *dd; @@ -612,7 +620,7 @@ register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler, list_for_each_entry(dock_station, &dock_stations, sibiling) { dd = find_dock_dependent_device(dock_station, handle); if (dd) { - dd->handler = handler; + dd->ops = ops; dd->context = context; dock_add_hotplug_device(dock_station, dd); return 0; -- cgit v1.2.3 From 4be9309d15e88e4a1e4a78deb52eb88c7da38c99 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 28 Aug 2008 10:06:44 +0800 Subject: bay: remove driver, all functions now handled by dock driver Signed-off-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 11 +- drivers/acpi/Makefile | 1 - drivers/acpi/bay.c | 411 -------------------------------------------------- 3 files changed, 2 insertions(+), 421 deletions(-) delete mode 100644 drivers/acpi/bay.c (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 735f5ea17473..3919d6dbe06f 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -160,15 +160,8 @@ config ACPI_DOCK tristate "Dock" depends on EXPERIMENTAL help - This driver adds support for ACPI controlled docking stations - -config ACPI_BAY - tristate "Removable Drive Bay (EXPERIMENTAL)" - depends on EXPERIMENTAL - depends on ACPI_DOCK - help - This driver adds support for ACPI controlled removable drive - bays such as the IBM ultrabay or the Dell Module Bay. + This driver adds support for ACPI controlled docking stations and removable + drive bays such as the IBM ultrabay or the Dell Module Bay. config ACPI_PROCESSOR tristate "Processor" diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 52a4cd4b81d0..ad4bfd558ff3 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -45,7 +45,6 @@ obj-$(CONFIG_ACPI_BATTERY) += battery.o obj-$(CONFIG_ACPI_BUTTON) += button.o obj-$(CONFIG_ACPI_FAN) += fan.o obj-$(CONFIG_ACPI_DOCK) += dock.o -obj-$(CONFIG_ACPI_BAY) += bay.o obj-$(CONFIG_ACPI_VIDEO) += video.o obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c deleted file mode 100644 index 61b6c5beb2d3..000000000000 --- a/drivers/acpi/bay.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * bay.c - ACPI removable drive bay driver - * - * Copyright (C) 2006 Kristen Carlson Accardi - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -ACPI_MODULE_NAME("bay"); -MODULE_AUTHOR("Kristen Carlson Accardi"); -MODULE_DESCRIPTION("ACPI Removable Drive Bay Driver"); -MODULE_LICENSE("GPL"); -#define ACPI_BAY_CLASS "bay" -#define ACPI_BAY_COMPONENT 0x10000000 -#define _COMPONENT ACPI_BAY_COMPONENT -#define bay_dprintk(h,s) {\ - char prefix[80] = {'\0'};\ - struct acpi_buffer buffer = {sizeof(prefix), prefix};\ - acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\ - printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); } -static void bay_notify(acpi_handle handle, u32 event, void *data); - -static const struct acpi_device_id bay_device_ids[] = { - {"LNXIOBAY", 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, bay_device_ids); - -struct bay { - acpi_handle handle; - char *name; - struct list_head list; - struct platform_device *pdev; -}; - -static LIST_HEAD(drive_bays); - - -/***************************************************************************** - * Drive Bay functions * - *****************************************************************************/ -/** - * is_ejectable - see if a device is ejectable - * @handle: acpi handle of the device - * - * If an acpi object has a _EJ0 method, then it is ejectable - */ -static int is_ejectable(acpi_handle handle) -{ - acpi_status status; - acpi_handle tmp; - - status = acpi_get_handle(handle, "_EJ0", &tmp); - if (ACPI_FAILURE(status)) - return 0; - return 1; -} - -/** - * bay_present - see if the bay device is present - * @bay: the drive bay - * - * execute the _STA method. - */ -static int bay_present(struct bay *bay) -{ - unsigned long sta; - acpi_status status; - - if (bay) { - status = acpi_evaluate_integer(bay->handle, "_STA", NULL, &sta); - if (ACPI_SUCCESS(status) && sta) - return 1; - } - return 0; -} - -/** - * eject_device - respond to an eject request - * @handle - the device to eject - * - * Call this devices _EJ0 method. - */ -static void eject_device(acpi_handle handle) -{ - struct acpi_object_list arg_list; - union acpi_object arg; - - bay_dprintk(handle, "Ejecting device"); - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = 1; - - if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0", - &arg_list, NULL))) - pr_debug("Failed to evaluate _EJ0!\n"); -} - -/* - * show_present - read method for "present" file in sysfs - */ -static ssize_t show_present(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct bay *bay = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%d\n", bay_present(bay)); - -} -static DEVICE_ATTR(present, S_IRUGO, show_present, NULL); - -/* - * write_eject - write method for "eject" file in sysfs - */ -static ssize_t write_eject(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct bay *bay = dev_get_drvdata(dev); - - if (!count) - return -EINVAL; - - eject_device(bay->handle); - return count; -} -static DEVICE_ATTR(eject, S_IWUSR, NULL, write_eject); - -/** - * is_ata - see if a device is an ata device - * @handle: acpi handle of the device - * - * If an acpi object has one of 4 ATA ACPI methods defined, - * then it is an ATA device - */ -static int is_ata(acpi_handle handle) -{ - acpi_handle tmp; - - if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp)))) - return 1; - - return 0; -} - -/** - * parent_is_ata(acpi_handle handle) - * - */ -static int parent_is_ata(acpi_handle handle) -{ - acpi_handle phandle; - - if (acpi_get_parent(handle, &phandle)) - return 0; - - return is_ata(phandle); -} - -/** - * is_ejectable_bay - see if a device is an ejectable drive bay - * @handle: acpi handle of the device - * - * If an acpi object is ejectable and has one of the ACPI ATA - * methods defined, then we can safely call it an ejectable - * drive bay - */ -static int is_ejectable_bay(acpi_handle handle) -{ - if ((is_ata(handle) || parent_is_ata(handle)) && is_ejectable(handle)) - return 1; - return 0; -} - -#if 0 -/** - * eject_removable_drive - try to eject this drive - * @dev : the device structure of the drive - * - * If a device is a removable drive that requires an _EJ0 method - * to be executed in order to safely remove from the system, do - * it. ATM - always returns success - */ -int eject_removable_drive(struct device *dev) -{ - acpi_handle handle = DEVICE_ACPI_HANDLE(dev); - - if (handle) { - bay_dprintk(handle, "Got device handle"); - if (is_ejectable_bay(handle)) - eject_device(handle); - } else { - printk("No acpi handle for device\n"); - } - - /* should I return an error code? */ - return 0; -} -EXPORT_SYMBOL_GPL(eject_removable_drive); -#endif /* 0 */ - -static int acpi_bay_add_fs(struct bay *bay) -{ - int ret; - struct device *dev = &bay->pdev->dev; - - ret = device_create_file(dev, &dev_attr_present); - if (ret) - goto add_fs_err; - ret = device_create_file(dev, &dev_attr_eject); - if (ret) { - device_remove_file(dev, &dev_attr_present); - goto add_fs_err; - } - return 0; - - add_fs_err: - bay_dprintk(bay->handle, "Error adding sysfs files\n"); - return ret; -} - -static void acpi_bay_remove_fs(struct bay *bay) -{ - struct device *dev = &bay->pdev->dev; - - /* cleanup sysfs */ - device_remove_file(dev, &dev_attr_present); - device_remove_file(dev, &dev_attr_eject); -} - -static int bay_is_dock_device(acpi_handle handle) -{ - acpi_handle parent; - - acpi_get_parent(handle, &parent); - - /* if the device or it's parent is dependent on the - * dock, then we are a dock device - */ - return (is_dock_device(handle) || is_dock_device(parent)); -} - -static int bay_add(acpi_handle handle, int id) -{ - acpi_status status; - struct bay *new_bay; - struct platform_device *pdev; - struct acpi_buffer nbuffer = {ACPI_ALLOCATE_BUFFER, NULL}; - acpi_get_name(handle, ACPI_FULL_PATHNAME, &nbuffer); - - bay_dprintk(handle, "Adding notify handler"); - - /* - * Initialize bay device structure - */ - new_bay = kzalloc(sizeof(*new_bay), GFP_ATOMIC); - INIT_LIST_HEAD(&new_bay->list); - new_bay->handle = handle; - new_bay->name = (char *)nbuffer.pointer; - - /* initialize platform device stuff */ - pdev = platform_device_register_simple(ACPI_BAY_CLASS, id, NULL, 0); - if (IS_ERR(pdev)) { - printk(KERN_ERR PREFIX "Error registering bay device\n"); - goto bay_add_err; - } - new_bay->pdev = pdev; - platform_set_drvdata(pdev, new_bay); - - /* - * we want the bay driver to be able to send uevents - */ - pdev->dev.uevent_suppress = 0; - - /* register for events on this device */ - status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, - bay_notify, new_bay); - if (ACPI_FAILURE(status)) { - printk(KERN_INFO PREFIX "Error installing bay notify handler\n"); - platform_device_unregister(new_bay->pdev); - goto bay_add_err; - } - - if (acpi_bay_add_fs(new_bay)) { - acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, - bay_notify); - platform_device_unregister(new_bay->pdev); - goto bay_add_err; - } - - /* if we are on a dock station, we should register for dock - * notifications. - */ - if (bay_is_dock_device(handle)) { - bay_dprintk(handle, "Is dependent on dock\n"); - register_hotplug_dock_device(handle, bay_notify, new_bay); - } - list_add(&new_bay->list, &drive_bays); - printk(KERN_INFO PREFIX "Bay [%s] Added\n", new_bay->name); - return 0; - -bay_add_err: - kfree(new_bay->name); - kfree(new_bay); - return -ENODEV; -} - -/** - * bay_notify - act upon an acpi bay notification - * @handle: the bay handle - * @event: the acpi event - * @data: our driver data struct - * - */ -static void bay_notify(acpi_handle handle, u32 event, void *data) -{ - struct bay *bay_dev = (struct bay *)data; - struct device *dev = &bay_dev->pdev->dev; - char event_string[12]; - char *envp[] = { event_string, NULL }; - - bay_dprintk(handle, "Bay event"); - sprintf(event_string, "BAY_EVENT=%d", event); - kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); -} - -static acpi_status -find_bay(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - int *count = (int *)context; - - /* - * there could be more than one ejectable bay. - * so, just return AE_OK always so that every object - * will be checked. - */ - if (is_ejectable_bay(handle)) { - bay_dprintk(handle, "found ejectable bay"); - if (!bay_add(handle, *count)) - (*count)++; - } - return AE_OK; -} - -static int __init bay_init(void) -{ - int bays = 0; - - INIT_LIST_HEAD(&drive_bays); - - if (acpi_disabled) - return -ENODEV; - - /* look for dockable drive bays */ - acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, find_bay, &bays, NULL); - - if (!bays) - return -ENODEV; - - return 0; -} - -static void __exit bay_exit(void) -{ - struct bay *bay, *tmp; - - list_for_each_entry_safe(bay, tmp, &drive_bays, list) { - if (is_dock_device(bay->handle)) - unregister_hotplug_dock_device(bay->handle); - acpi_bay_remove_fs(bay); - acpi_remove_notify_handler(bay->handle, ACPI_SYSTEM_NOTIFY, - bay_notify); - platform_device_unregister(bay->pdev); - kfree(bay->name); - kfree(bay); - } -} - -postcore_initcall(bay_init); -module_exit(bay_exit); - -- cgit v1.2.3 From 61b836958371c717d1e6d4fea1d2c512969ad20b Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 28 Aug 2008 10:07:14 +0800 Subject: dock: fix for ATA bay in a dock station an ATA bay can be in a dock and itself can be ejected separately. This patch handles such eject bay. Found by Holger. Signed-off-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/dock.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index ac7dfefcb50b..c877cc526002 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -609,6 +609,7 @@ register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops, { struct dock_dependent_device *dd; struct dock_station *dock_station; + int ret = -EINVAL; if (!dock_station_count) return -ENODEV; @@ -618,16 +619,21 @@ register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops, * this would include the dock station itself */ list_for_each_entry(dock_station, &dock_stations, sibiling) { + /* + * An ATA bay can be in a dock and itself can be ejected + * seperately, so there are two 'dock stations' which need the + * ops + */ dd = find_dock_dependent_device(dock_station, handle); if (dd) { dd->ops = ops; dd->context = context; dock_add_hotplug_device(dock_station, dd); - return 0; + ret = 0; } } - return -EINVAL; + return ret; } EXPORT_SYMBOL_GPL(register_hotplug_dock_device); @@ -1078,8 +1084,8 @@ find_dock(acpi_handle handle, u32 lvl, void *context, void **rv) static acpi_status find_bay(acpi_handle handle, u32 lvl, void *context, void **rv) { - /* If bay is in a dock, it's already handled */ - if (is_ejectable_bay(handle) && !is_dock_device(handle)) + /* If bay is a dock, it's already handled */ + if (is_ejectable_bay(handle) && !is_dock(handle)) dock_add(handle); return AE_OK; } -- cgit v1.2.3 From 8652b00fd6416773f113dab3dfa0d4509def825b Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 28 Aug 2008 10:07:45 +0800 Subject: dock: add 'type' sysfs file add a sysfs file to present dock type. Suggested by Holger. Signed-off-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/dock.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index c877cc526002..b7d15818215c 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -911,6 +911,26 @@ static ssize_t show_dock_uid(struct device *dev, } static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL); +static ssize_t show_dock_type(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct dock_station *dock_station = *((struct dock_station **) + dev->platform_data); + char *type; + + if (dock_station->flags & DOCK_IS_DOCK) + type = "dock_station"; + else if (dock_station->flags & DOCK_IS_ATA) + type = "ata_bay"; + else if (dock_station->flags & DOCK_IS_BAT) + type = "battery_bay"; + else + type = "unknown"; + + return snprintf(buf, PAGE_SIZE, "%s\n", type); +} +static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL); + /** * dock_add - add a new dock station * @handle: the dock station handle @@ -999,6 +1019,9 @@ static int dock_add(acpi_handle handle) dock_station = NULL; return ret; } + ret = device_create_file(&dock_device->dev, &dev_attr_type); + if (ret) + printk(KERN_ERR"Error %d adding sysfs file\n", ret); /* Find dependent devices */ acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, @@ -1020,6 +1043,7 @@ static int dock_add(acpi_handle handle) return 0; dock_add_err_unregister: + device_remove_file(&dock_device->dev, &dev_attr_type); device_remove_file(&dock_device->dev, &dev_attr_docked); device_remove_file(&dock_device->dev, &dev_attr_undock); device_remove_file(&dock_device->dev, &dev_attr_uid); @@ -1047,6 +1071,7 @@ static int dock_remove(struct dock_station *dock_station) kfree(dd); /* cleanup sysfs */ + device_remove_file(&dock_device->dev, &dev_attr_type); device_remove_file(&dock_device->dev, &dev_attr_docked); device_remove_file(&dock_device->dev, &dev_attr_undock); device_remove_file(&dock_device->dev, &dev_attr_uid); -- cgit v1.2.3 From 7c6db4e050601f359081fde418ca6dc4fc2d0011 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Thu, 25 Sep 2008 21:00:31 +0400 Subject: ACPI: EC: do transaction from interrupt context It is easier and faster to do transaction directly from interrupt context rather than waking control thread. Also, cleaner GPE storm avoidance is implemented. References: http://bugzilla.kernel.org/show_bug.cgi?id=9998 http://bugzilla.kernel.org/show_bug.cgi?id=10724 http://bugzilla.kernel.org/show_bug.cgi?id=10919 http://bugzilla.kernel.org/show_bug.cgi?id=11309 http://bugzilla.kernel.org/show_bug.cgi?id=11549 Signed-off-by: Alexey Starikovskiy Tested-by: Sitsofe Wheeler Signed-off-by: Len Brown --- drivers/acpi/ec.c | 309 ++++++++++++++++++++++++++---------------------------- 1 file changed, 149 insertions(+), 160 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 13593f9f2197..7f0d81c0ec99 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1,7 +1,7 @@ /* - * ec.c - ACPI Embedded Controller Driver (v2.0) + * ec.c - ACPI Embedded Controller Driver (v2.1) * - * Copyright (C) 2006, 2007 Alexey Starikovskiy + * Copyright (C) 2006-2008 Alexey Starikovskiy * Copyright (C) 2006 Denis Sadykov * Copyright (C) 2004 Luming Yu * Copyright (C) 2001, 2002 Andy Grover @@ -26,7 +26,7 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* Uncomment next line to get verbose print outs*/ +/* Uncomment next line to get verbose printout */ /* #define DEBUG */ #include @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -65,22 +66,21 @@ enum ec_command { ACPI_EC_COMMAND_QUERY = 0x84, }; -/* EC events */ -enum ec_event { - ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */ - ACPI_EC_EVENT_IBF_0, /* Input buffer empty */ -}; - #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ #define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */ +#define ACPI_EC_STORM_THRESHOLD 20 /* number of false interrupts + per one transaction */ + enum { - EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ EC_FLAGS_QUERY_PENDING, /* Query is pending */ - EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ + EC_FLAGS_GPE_MODE, /* Expect GPE to be sent + * for status change */ EC_FLAGS_NO_GPE, /* Don't use GPE mode */ - EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */ + EC_FLAGS_GPE_STORM, /* GPE storm detected */ + EC_FLAGS_HANDLERS_INSTALLED /* Handlers for GPE and + * OpReg are installed */ }; /* If we find an EC via the ECDT, we need to keep a ptr to its context */ @@ -95,6 +95,14 @@ struct acpi_ec_query_handler { u8 query_bit; }; +struct transaction_data { + const u8 *wdata; + u8 *rdata; + unsigned short irq_count; + u8 wlen; + u8 rlen; +}; + static struct acpi_ec { acpi_handle handle; unsigned long gpe; @@ -105,9 +113,8 @@ static struct acpi_ec { struct mutex lock; wait_queue_head_t wait; struct list_head list; - struct delayed_work work; - atomic_t irq_count; - u8 handlers_installed; + struct transaction_data *t; + spinlock_t t_lock; } *boot_ec, *first_ec; /* @@ -150,7 +157,7 @@ static inline u8 acpi_ec_read_data(struct acpi_ec *ec) { u8 x = inb(ec->data_addr); pr_debug(PREFIX "---> data = 0x%2.2x\n", x); - return inb(ec->data_addr); + return x; } static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) @@ -165,68 +172,79 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) outb(data, ec->data_addr); } -static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) +static int ec_transaction_done(struct acpi_ec *ec) { - if (test_bit(EC_FLAGS_WAIT_GPE, &ec->flags)) - return 0; - if (event == ACPI_EC_EVENT_OBF_1) { - if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_OBF) - return 1; - } else if (event == ACPI_EC_EVENT_IBF_0) { - if (!(acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF)) - return 1; - } - - return 0; + unsigned long flags; + int ret = 0; + spin_lock_irqsave(&ec->t_lock, flags); + if (!ec->t || (!ec->t->wlen && !ec->t->rlen)) + ret = 1; + spin_unlock_irqrestore(&ec->t_lock, flags); + return ret; } -static void ec_schedule_ec_poll(struct acpi_ec *ec) +static void gpe_transaction(struct acpi_ec *ec, u8 status) { - if (test_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags)) - schedule_delayed_work(&ec->work, - msecs_to_jiffies(ACPI_EC_DELAY)); + unsigned long flags; + spin_lock_irqsave(&ec->t_lock, flags); + if (!ec->t) + goto unlock; + if (ec->t->wlen > 0) { + if ((status & ACPI_EC_FLAG_IBF) == 0) { + acpi_ec_write_data(ec, *(ec->t->wdata++)); + --ec->t->wlen; + } else + /* false interrupt, state didn't change */ + ++ec->t->irq_count; + + } else if (ec->t->rlen > 0) { + if ((status & ACPI_EC_FLAG_OBF) == 1) { + *(ec->t->rdata++) = acpi_ec_read_data(ec); + --ec->t->rlen; + } else + /* false interrupt, state didn't change */ + ++ec->t->irq_count; + } +unlock: + spin_unlock_irqrestore(&ec->t_lock, flags); } -static void ec_switch_to_poll_mode(struct acpi_ec *ec) +static int acpi_ec_wait(struct acpi_ec *ec) { + if (wait_event_timeout(ec->wait, ec_transaction_done(ec), + msecs_to_jiffies(ACPI_EC_DELAY))) + return 0; + /* missing GPEs, switch back to poll mode */ + if (printk_ratelimit()) + pr_info(PREFIX "missing confirmations, " + "switch off interrupt mode.\n"); set_bit(EC_FLAGS_NO_GPE, &ec->flags); clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); - acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); - set_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); + return 1; } -static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) +static void acpi_ec_gpe_query(void *ec_cxt); + +static int ec_check_sci(struct acpi_ec *ec, u8 state) { - atomic_set(&ec->irq_count, 0); - if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && - likely(!force_poll)) { - if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), - msecs_to_jiffies(ACPI_EC_DELAY))) - return 0; - clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - if (acpi_ec_check_status(ec, event)) { - /* missing GPEs, switch back to poll mode */ - if (printk_ratelimit()) - pr_info(PREFIX "missing confirmations, " - "switch off interrupt mode.\n"); - ec_switch_to_poll_mode(ec); - ec_schedule_ec_poll(ec); - return 0; - } - } else { - unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); - clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - while (time_before(jiffies, delay)) { - if (acpi_ec_check_status(ec, event)) - return 0; - msleep(1); - } - if (acpi_ec_check_status(ec,event)) + if (state & ACPI_EC_FLAG_SCI) { + if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) + return acpi_os_execute(OSL_EC_BURST_HANDLER, + acpi_ec_gpe_query, ec); + } + return 0; +} + +static int ec_poll(struct acpi_ec *ec) +{ + unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); + msleep(1); + while (time_before(jiffies, delay)) { + gpe_transaction(ec, acpi_ec_read_status(ec)); + msleep(1); + if (ec_transaction_done(ec)) return 0; } - pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", - acpi_ec_read_status(ec), - (event == ACPI_EC_EVENT_OBF_1) ? "\"b0=1\"" : "\"b1=0\""); return -ETIME; } @@ -235,45 +253,51 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, u8 * rdata, unsigned rdata_len, int force_poll) { - int result = 0; - set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); + unsigned long tmp; + struct transaction_data t = {.wdata = wdata, .rdata = rdata, + .wlen = wdata_len, .rlen = rdata_len, + .irq_count = 0}; + int ret = 0; pr_debug(PREFIX "transaction start\n"); - acpi_ec_write_cmd(ec, command); - for (; wdata_len > 0; --wdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); - if (result) { - pr_err(PREFIX - "write_cmd timeout, command = %d\n", command); - goto end; - } - set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - acpi_ec_write_data(ec, *(wdata++)); + /* disable GPE during transaction if storm is detected */ + if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); + acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); } - - if (!rdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); - if (result) { - pr_err(PREFIX - "finish-write timeout, command = %d\n", command); - goto end; - } - } else if (command == ACPI_EC_COMMAND_QUERY) + /* start transaction */ + spin_lock_irqsave(&ec->t_lock, tmp); + /* following two actions should be kept atomic */ + ec->t = &t; + acpi_ec_write_cmd(ec, command); + if (command == ACPI_EC_COMMAND_QUERY) clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); - - for (; rdata_len > 0; --rdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll); - if (result) { - pr_err(PREFIX "read timeout, command = %d\n", command); - goto end; - } - /* Don't expect GPE after last read */ - if (rdata_len > 1) - set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - *(rdata++) = acpi_ec_read_data(ec); - } - end: + spin_unlock_irqrestore(&ec->t_lock, tmp); + /* if we selected poll mode or failed in GPE-mode do a poll loop */ + if (force_poll || + !test_bit(EC_FLAGS_GPE_MODE, &ec->flags) || + acpi_ec_wait(ec)) + ret = ec_poll(ec); pr_debug(PREFIX "transaction end\n"); - return result; + spin_lock_irqsave(&ec->t_lock, tmp); + ec->t = NULL; + spin_unlock_irqrestore(&ec->t_lock, tmp); + if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + /* check if we received SCI during transaction */ + ec_check_sci(ec, acpi_ec_read_status(ec)); + /* it is safe to enable GPE outside of transaction */ + acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && + t.irq_count > ACPI_EC_STORM_THRESHOLD) { + pr_debug(PREFIX "GPE storm detected\n"); + set_bit(EC_FLAGS_GPE_STORM, &ec->flags); + } + return ret; +} + +static int ec_check_ibf0(struct acpi_ec *ec) +{ + u8 status = acpi_ec_read_status(ec); + return (status & ACPI_EC_FLAG_IBF) == 0; } static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, @@ -283,40 +307,34 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, { int status; u32 glk; - if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata)) return -EINVAL; - if (rdata) memset(rdata, 0, rdata_len); - mutex_lock(&ec->lock); if (ec->global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) { - mutex_unlock(&ec->lock); - return -ENODEV; + status = -ENODEV; + goto unlock; } } - - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0); - if (status) { + if (!wait_event_timeout(ec->wait, ec_check_ibf0(ec), + msecs_to_jiffies(ACPI_EC_DELAY))) { pr_err(PREFIX "input buffer is not empty, " "aborting transaction\n"); + status = -ETIME; goto end; } - status = acpi_ec_transaction_unlocked(ec, command, wdata, wdata_len, rdata, rdata_len, force_poll); - - end: - +end: if (ec->global_lock) acpi_release_global_lock(glk); +unlock: mutex_unlock(&ec->lock); - return status; } @@ -332,7 +350,9 @@ int acpi_ec_burst_enable(struct acpi_ec *ec) int acpi_ec_burst_disable(struct acpi_ec *ec) { - return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0, 0); + return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ? + acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, + NULL, 0, NULL, 0, 0) : 0; } static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) @@ -513,46 +533,26 @@ static void acpi_ec_gpe_query(void *ec_cxt) static u32 acpi_ec_gpe_handler(void *data) { - acpi_status status = AE_OK; struct acpi_ec *ec = data; - u8 state = acpi_ec_read_status(ec); + u8 status; pr_debug(PREFIX "~~~> interrupt\n"); - atomic_inc(&ec->irq_count); - if (atomic_read(&ec->irq_count) > 5) { - pr_err(PREFIX "GPE storm detected, disabling EC GPE\n"); - ec_switch_to_poll_mode(ec); - goto end; - } - clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) + status = acpi_ec_read_status(ec); + + gpe_transaction(ec, status); + if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) wake_up(&ec->wait); - if (state & ACPI_EC_FLAG_SCI) { - if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) - status = acpi_os_execute(OSL_EC_BURST_HANDLER, - acpi_ec_gpe_query, ec); - } else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && - !test_bit(EC_FLAGS_NO_GPE, &ec->flags) && - in_interrupt()) { + ec_check_sci(ec, status); + if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && + !test_bit(EC_FLAGS_NO_GPE, &ec->flags)) { /* this is non-query, must be confirmation */ if (printk_ratelimit()) pr_info(PREFIX "non-query interrupt received," " switching to interrupt mode\n"); set_bit(EC_FLAGS_GPE_MODE, &ec->flags); - clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); } -end: - ec_schedule_ec_poll(ec); - return ACPI_SUCCESS(status) ? - ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; -} - -static void do_ec_poll(struct work_struct *work) -{ - struct acpi_ec *ec = container_of(work, struct acpi_ec, work.work); - atomic_set(&ec->irq_count, 0); - (void)acpi_ec_gpe_handler(ec); + return ACPI_INTERRUPT_HANDLED; } /* -------------------------------------------------------------------------- @@ -696,8 +696,7 @@ static struct acpi_ec *make_acpi_ec(void) mutex_init(&ec->lock); init_waitqueue_head(&ec->wait); INIT_LIST_HEAD(&ec->list); - INIT_DELAYED_WORK_DEFERRABLE(&ec->work, do_ec_poll); - atomic_set(&ec->irq_count, 0); + spin_lock_init(&ec->t_lock); return ec; } @@ -736,22 +735,15 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) return AE_CTRL_TERMINATE; } -static void ec_poll_stop(struct acpi_ec *ec) -{ - clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); - cancel_delayed_work(&ec->work); -} - static void ec_remove_handlers(struct acpi_ec *ec) { - ec_poll_stop(ec); if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) pr_err(PREFIX "failed to remove space handler\n"); if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler))) pr_err(PREFIX "failed to remove gpe handler\n"); - ec->handlers_installed = 0; + clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); } static int acpi_ec_add(struct acpi_device *device) @@ -846,17 +838,15 @@ ec_parse_io_ports(struct acpi_resource *resource, void *context) static int ec_install_handlers(struct acpi_ec *ec) { acpi_status status; - if (ec->handlers_installed) + if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags)) return 0; status = acpi_install_gpe_handler(NULL, ec->gpe, - ACPI_GPE_EDGE_TRIGGERED, - &acpi_ec_gpe_handler, ec); + ACPI_GPE_EDGE_TRIGGERED, + &acpi_ec_gpe_handler, ec); if (ACPI_FAILURE(status)) return -ENODEV; - acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); - status = acpi_install_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, @@ -866,7 +856,7 @@ static int ec_install_handlers(struct acpi_ec *ec) return -ENODEV; } - ec->handlers_installed = 1; + set_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); return 0; } @@ -887,7 +877,6 @@ static int acpi_ec_start(struct acpi_device *device) /* EC is fully operational, allow queries */ clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); - ec_schedule_ec_poll(ec); return ret; } @@ -906,7 +895,7 @@ static int acpi_ec_stop(struct acpi_device *device, int type) int __init acpi_boot_ec_enable(void) { - if (!boot_ec || boot_ec->handlers_installed) + if (!boot_ec || test_bit(EC_FLAGS_HANDLERS_INSTALLED, &boot_ec->flags)) return 0; if (!ec_install_handlers(boot_ec)) { first_ec = boot_ec; -- cgit v1.2.3 From 8463200a00fe2aea938b40173198a0983f2929ef Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Fri, 26 Sep 2008 00:54:28 +0400 Subject: ACPI: EC: Rename some variables No functional changes. Signed-off-by: Alexey Starikovskiy Acked-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/ec.c | 118 +++++++++++++++++++++++++++++------------------------- 1 file changed, 63 insertions(+), 55 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 7f0d81c0ec99..453ba1e534ef 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -95,10 +95,11 @@ struct acpi_ec_query_handler { u8 query_bit; }; -struct transaction_data { +struct transaction { const u8 *wdata; u8 *rdata; unsigned short irq_count; + u8 command; u8 wlen; u8 rlen; }; @@ -113,8 +114,8 @@ static struct acpi_ec { struct mutex lock; wait_queue_head_t wait; struct list_head list; - struct transaction_data *t; - spinlock_t t_lock; + struct transaction *curr; + spinlock_t curr_lock; } *boot_ec, *first_ec; /* @@ -176,37 +177,37 @@ static int ec_transaction_done(struct acpi_ec *ec) { unsigned long flags; int ret = 0; - spin_lock_irqsave(&ec->t_lock, flags); - if (!ec->t || (!ec->t->wlen && !ec->t->rlen)) + spin_lock_irqsave(&ec->curr_lock, flags); + if (!ec->curr || (!ec->curr->wlen && !ec->curr->rlen)) ret = 1; - spin_unlock_irqrestore(&ec->t_lock, flags); + spin_unlock_irqrestore(&ec->curr_lock, flags); return ret; } static void gpe_transaction(struct acpi_ec *ec, u8 status) { unsigned long flags; - spin_lock_irqsave(&ec->t_lock, flags); - if (!ec->t) + spin_lock_irqsave(&ec->curr_lock, flags); + if (!ec->curr) goto unlock; - if (ec->t->wlen > 0) { + if (ec->curr->wlen > 0) { if ((status & ACPI_EC_FLAG_IBF) == 0) { - acpi_ec_write_data(ec, *(ec->t->wdata++)); - --ec->t->wlen; + acpi_ec_write_data(ec, *(ec->curr->wdata++)); + --ec->curr->wlen; } else /* false interrupt, state didn't change */ - ++ec->t->irq_count; + ++ec->curr->irq_count; - } else if (ec->t->rlen > 0) { + } else if (ec->curr->rlen > 0) { if ((status & ACPI_EC_FLAG_OBF) == 1) { - *(ec->t->rdata++) = acpi_ec_read_data(ec); - --ec->t->rlen; + *(ec->curr->rdata++) = acpi_ec_read_data(ec); + --ec->curr->rlen; } else /* false interrupt, state didn't change */ - ++ec->t->irq_count; + ++ec->curr->irq_count; } unlock: - spin_unlock_irqrestore(&ec->t_lock, flags); + spin_unlock_irqrestore(&ec->curr_lock, flags); } static int acpi_ec_wait(struct acpi_ec *ec) @@ -248,15 +249,11 @@ static int ec_poll(struct acpi_ec *ec) return -ETIME; } -static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, - const u8 * wdata, unsigned wdata_len, - u8 * rdata, unsigned rdata_len, +static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, + struct transaction *t, int force_poll) { unsigned long tmp; - struct transaction_data t = {.wdata = wdata, .rdata = rdata, - .wlen = wdata_len, .rlen = rdata_len, - .irq_count = 0}; int ret = 0; pr_debug(PREFIX "transaction start\n"); /* disable GPE during transaction if storm is detected */ @@ -265,29 +262,30 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); } /* start transaction */ - spin_lock_irqsave(&ec->t_lock, tmp); + spin_lock_irqsave(&ec->curr_lock, tmp); /* following two actions should be kept atomic */ - ec->t = &t; - acpi_ec_write_cmd(ec, command); - if (command == ACPI_EC_COMMAND_QUERY) + t->irq_count = 0; + ec->curr = t; + acpi_ec_write_cmd(ec, ec->curr->command); + if (ec->curr->command == ACPI_EC_COMMAND_QUERY) clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); - spin_unlock_irqrestore(&ec->t_lock, tmp); + spin_unlock_irqrestore(&ec->curr_lock, tmp); /* if we selected poll mode or failed in GPE-mode do a poll loop */ if (force_poll || !test_bit(EC_FLAGS_GPE_MODE, &ec->flags) || acpi_ec_wait(ec)) ret = ec_poll(ec); pr_debug(PREFIX "transaction end\n"); - spin_lock_irqsave(&ec->t_lock, tmp); - ec->t = NULL; - spin_unlock_irqrestore(&ec->t_lock, tmp); + spin_lock_irqsave(&ec->curr_lock, tmp); + ec->curr = NULL; + spin_unlock_irqrestore(&ec->curr_lock, tmp); if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { /* check if we received SCI during transaction */ ec_check_sci(ec, acpi_ec_read_status(ec)); /* it is safe to enable GPE outside of transaction */ acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && - t.irq_count > ACPI_EC_STORM_THRESHOLD) { + t->irq_count > ACPI_EC_STORM_THRESHOLD) { pr_debug(PREFIX "GPE storm detected\n"); set_bit(EC_FLAGS_GPE_STORM, &ec->flags); } @@ -300,17 +298,15 @@ static int ec_check_ibf0(struct acpi_ec *ec) return (status & ACPI_EC_FLAG_IBF) == 0; } -static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, - const u8 * wdata, unsigned wdata_len, - u8 * rdata, unsigned rdata_len, +static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t, int force_poll) { int status; u32 glk; - if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata)) + if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata)) return -EINVAL; - if (rdata) - memset(rdata, 0, rdata_len); + if (t->rdata) + memset(t->rdata, 0, t->rlen); mutex_lock(&ec->lock); if (ec->global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); @@ -326,10 +322,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, status = -ETIME; goto end; } - status = acpi_ec_transaction_unlocked(ec, command, - wdata, wdata_len, - rdata, rdata_len, - force_poll); + status = acpi_ec_transaction_unlocked(ec, t, force_poll); end: if (ec->global_lock) acpi_release_global_lock(glk); @@ -345,23 +338,32 @@ unlock: int acpi_ec_burst_enable(struct acpi_ec *ec) { u8 d; - return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1, 0); + struct transaction t = {.command = ACPI_EC_BURST_ENABLE, + .wdata = NULL, .rdata = &d, + .wlen = 0, .rlen = 1}; + + return acpi_ec_transaction(ec, &t, 0); } int acpi_ec_burst_disable(struct acpi_ec *ec) { + struct transaction t = {.command = ACPI_EC_BURST_DISABLE, + .wdata = NULL, .rdata = NULL, + .wlen = 0, .rlen = 0}; + return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ? - acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, - NULL, 0, NULL, 0, 0) : 0; + acpi_ec_transaction(ec, &t, 0) : 0; } static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) { int result; u8 d; + struct transaction t = {.command = ACPI_EC_COMMAND_READ, + .wdata = &address, .rdata = &d, + .wlen = 1, .rlen = 1}; - result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ, - &address, 1, &d, 1, 0); + result = acpi_ec_transaction(ec, &t, 0); *data = d; return result; } @@ -369,8 +371,11 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) { u8 wdata[2] = { address, data }; - return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE, - wdata, 2, NULL, 0, 0); + struct transaction t = {.command = ACPI_EC_COMMAND_WRITE, + .wdata = wdata, .rdata = NULL, + .wlen = 2, .rlen = 0}; + + return acpi_ec_transaction(ec, &t, 0); } /* @@ -432,12 +437,13 @@ int ec_transaction(u8 command, u8 * rdata, unsigned rdata_len, int force_poll) { + struct transaction t = {.command = command, + .wdata = wdata, .rdata = rdata, + .wlen = wdata_len, .rlen = rdata_len}; if (!first_ec) return -ENODEV; - return acpi_ec_transaction(first_ec, command, wdata, - wdata_len, rdata, rdata_len, - force_poll); + return acpi_ec_transaction(first_ec, &t, force_poll); } EXPORT_SYMBOL(ec_transaction); @@ -446,7 +452,9 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) { int result; u8 d; - + struct transaction t = {.command = ACPI_EC_COMMAND_QUERY, + .wdata = NULL, .rdata = &d, + .wlen = 0, .rlen = 1}; if (!ec || !data) return -EINVAL; @@ -456,7 +464,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) * bit to be cleared (and thus clearing the interrupt source). */ - result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1, 0); + result = acpi_ec_transaction(ec, &t, 0); if (result) return result; @@ -696,7 +704,7 @@ static struct acpi_ec *make_acpi_ec(void) mutex_init(&ec->lock); init_waitqueue_head(&ec->wait); INIT_LIST_HEAD(&ec->list); - spin_lock_init(&ec->t_lock); + spin_lock_init(&ec->curr_lock); return ec; } -- cgit v1.2.3 From faee816b1502385dc9bc5abf2960d1cc645844d1 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 12 Sep 2008 11:12:25 +0800 Subject: ACPI: don't enable control method power button as wakeup device when Fixed Power button is used don't enable control method power button as wakeup device when Fixed Power button is used. http://bugzilla.kernel.org/show_bug.cgi?id=10503 Tested-by: walken@zoy.org Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/scan.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f6f52c1a2aba..5ce14aee5e3f 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -744,6 +744,16 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) if (!acpi_match_device_ids(device, button_device_ids)) device->wakeup.flags.run_wake = 1; + /* + * Don't set Power button GPE as run_wake + * if Fixed Power button is used + */ + if (!strcmp(device->pnp.hardware_id, "PNP0C0C") && + !(acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON)) { + device->wakeup.flags.run_wake = 0; + device->wakeup.flags.valid = 0; + } + end: if (ACPI_FAILURE(status)) device->flags.wake_capable = 0; -- cgit v1.2.3 From a66bfa7a4726e9cbdc985133af728a4bd9925d96 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 8 Oct 2008 21:40:32 +0100 Subject: ACPI: WMI: Enable event methods when registering notifiers According to the ACPI-WMI spec, event blocks may provide a function call for enabling/disabling them. This patch adds support for making these calls when registering or removing notifications. Without this, my Dell firmware provides no data in the event notification. Signed-off-by: Matthew Garrett Signed-off-by: Carlos Corbacho Signed-off-by: Len Brown --- drivers/acpi/wmi.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/wmi.c b/drivers/acpi/wmi.c index cfe2c833474d..5464cfcf8297 100644 --- a/drivers/acpi/wmi.c +++ b/drivers/acpi/wmi.c @@ -217,6 +217,35 @@ static bool find_guid(const char *guid_string, struct wmi_block **out) return 0; } +static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable) +{ + struct guid_block *block = NULL; + char method[5]; + struct acpi_object_list input; + union acpi_object params[1]; + acpi_status status; + acpi_handle handle; + + block = &wblock->gblock; + handle = wblock->handle; + + if (!block) + return AE_NOT_EXIST; + + input.count = 1; + input.pointer = params; + params[0].type = ACPI_TYPE_INTEGER; + params[0].integer.value = enable; + + snprintf(method, 5, "WE%02X", block->notify_id); + status = acpi_evaluate_object(handle, method, &input, NULL); + + if (status != AE_OK && status != AE_NOT_FOUND) + return status; + else + return AE_OK; +} + /* * Exported WMI functions */ @@ -427,6 +456,7 @@ acpi_status wmi_install_notify_handler(const char *guid, wmi_notify_handler handler, void *data) { struct wmi_block *block; + acpi_status status; if (!guid || !handler) return AE_BAD_PARAMETER; @@ -441,7 +471,9 @@ wmi_notify_handler handler, void *data) block->handler = handler; block->handler_data = data; - return AE_OK; + status = wmi_method_enable(block, 1); + + return status; } EXPORT_SYMBOL_GPL(wmi_install_notify_handler); @@ -453,6 +485,7 @@ EXPORT_SYMBOL_GPL(wmi_install_notify_handler); acpi_status wmi_remove_notify_handler(const char *guid) { struct wmi_block *block; + acpi_status status; if (!guid) return AE_BAD_PARAMETER; @@ -464,10 +497,12 @@ acpi_status wmi_remove_notify_handler(const char *guid) if (!block->handler) return AE_NULL_ENTRY; + status = wmi_method_enable(block, 0); + block->handler = NULL; block->handler_data = NULL; - return AE_OK; + return status; } EXPORT_SYMBOL_GPL(wmi_remove_notify_handler); -- cgit v1.2.3 From fcea94ba0773a4bf78d109f2acd72d003f0621f6 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 19 Sep 2008 15:50:32 -0700 Subject: ACPI: fix FADT parsing The (1.0 inherited) separate length fields in the FADT are byte granular. Further, PM1a/b may have distinct lengths (if using the v2 fields was okay) and may live in distinct address spaces. acpi_tb_convert_fadt() should account for all of these conditions. Apart from these changes I'm puzzled by the fact that, not just for acpi_gbl_xpm1{a,b}_enable, acpi_hw_low_level_{read,write}() get an explicit size passed rather than using the size found in the passed GAS. What happens on a platform that defines PM1{a,b} wider than 16 bits? Of course, acpi_hw_low_level_{read,write}() at present are entirely un-prepared to deal with sizes other than 8, 16, or 32, not to speak of a non-zero bit_offset or access_width... Signed-off-by: Jan Beulich Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/tables/tbfadt.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c index a4a41ba2484b..2c7885e7ffba 100644 --- a/drivers/acpi/tables/tbfadt.c +++ b/drivers/acpi/tables/tbfadt.c @@ -50,7 +50,7 @@ ACPI_MODULE_NAME("tbfadt") /* Local prototypes */ static void inline acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, - u8 bit_width, u64 address); + u8 byte_width, u64 address); static void acpi_tb_convert_fadt(void); @@ -111,7 +111,7 @@ static struct acpi_fadt_info fadt_info_table[] = { * FUNCTION: acpi_tb_init_generic_address * * PARAMETERS: generic_address - GAS struct to be initialized - * bit_width - Width of this register + * byte_width - Width of this register * Address - Address of the register * * RETURN: None @@ -124,7 +124,7 @@ static struct acpi_fadt_info fadt_info_table[] = { static void inline acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, - u8 bit_width, u64 address) + u8 byte_width, u64 address) { /* @@ -136,7 +136,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, /* All other fields are byte-wide */ generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO; - generic_address->bit_width = bit_width; + generic_address->bit_width = byte_width << 3; generic_address->bit_offset = 0; generic_address->access_width = 0; } @@ -342,9 +342,20 @@ static void acpi_tb_convert_fadt(void) * useful to calculate them once, here. * * The PM event blocks are split into two register blocks, first is the - * PM Status Register block, followed immediately by the PM Enable Register - * block. Each is of length (pm1_event_length/2) + * PM Status Register block, followed immediately by the PM Enable + * Register block. Each is of length (xpm1x_event_block.bit_width/2). + * + * On various systems the v2 fields (and particularly the bit widths) + * cannot be relied upon, though. Hence resort to using the v1 length + * here (and warn about the inconsistency). */ + if (acpi_gbl_FADT.xpm1a_event_block.bit_width + != acpi_gbl_FADT.pm1_event_length * 8) + printk(KERN_WARNING "FADT: " + "X_PM1a_EVT_BLK.bit_width (%u) does not match" + " PM1_EVT_LEN (%u)\n", + acpi_gbl_FADT.xpm1a_event_block.bit_width, + acpi_gbl_FADT.pm1_event_length); pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length); /* The PM1A register block is required */ @@ -360,13 +371,20 @@ static void acpi_tb_convert_fadt(void) /* The PM1B register block is optional, ignore if not present */ if (acpi_gbl_FADT.xpm1b_event_block.address) { + if (acpi_gbl_FADT.xpm1b_event_block.bit_width + != acpi_gbl_FADT.pm1_event_length * 8) + printk(KERN_WARNING "FADT: " + "X_PM1b_EVT_BLK.bit_width (%u) does not match" + " PM1_EVT_LEN (%u)\n", + acpi_gbl_FADT.xpm1b_event_block.bit_width, + acpi_gbl_FADT.pm1_event_length); acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, pm1_register_length, (acpi_gbl_FADT.xpm1b_event_block. address + pm1_register_length)); /* Don't forget to copy space_id of the GAS */ acpi_gbl_xpm1b_enable.space_id = - acpi_gbl_FADT.xpm1a_event_block.space_id; + acpi_gbl_FADT.xpm1b_event_block.space_id; } } -- cgit v1.2.3 From 4b5fcb353ba46adfa2f98546e3d34e7dc65221cb Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 10 Sep 2008 14:33:43 +0400 Subject: ACPI: acpi_driver_data could only be applied to acpi_device Signed-off-by: Alexey Starikovskiy CC: Hannes Reinecke Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f6f52c1a2aba..e7b8853c310b 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -384,7 +384,7 @@ static int acpi_device_remove(struct device * dev) acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type); } acpi_dev->driver = NULL; - acpi_driver_data(dev) = NULL; + acpi_driver_data(acpi_dev) = NULL; put_device(dev); return 0; -- cgit v1.2.3 From 9e113e0014204bfb44a2baa29b2a141ede41b074 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Mon, 22 Sep 2008 14:37:29 -0700 Subject: ACPI: toshiba_acpi.c fix sparse signedness mismatch warnings set_bit expects unsigned int, and we start with a u32 anyway. drivers/acpi/toshiba_acpi.c:397:14: warning: incorrect type in argument 1 (different signedness) drivers/acpi/toshiba_acpi.c:397:14: expected unsigned int [usertype] *word drivers/acpi/toshiba_acpi.c:397:14: got int * drivers/acpi/toshiba_acpi.c:399:14: warning: incorrect type in argument 1 (different signedness) drivers/acpi/toshiba_acpi.c:399:14: expected unsigned int [usertype] *word drivers/acpi/toshiba_acpi.c:399:14: got int * drivers/acpi/toshiba_acpi.c:401:14: warning: incorrect type in argument 1 (different signedness) drivers/acpi/toshiba_acpi.c:401:14: expected unsigned int [usertype] *word drivers/acpi/toshiba_acpi.c:401:14: got int * Signed-off-by: Harvey Harrison Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/toshiba_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c index 0a43c8e0eff3..4172d290f275 100644 --- a/drivers/acpi/toshiba_acpi.c +++ b/drivers/acpi/toshiba_acpi.c @@ -392,7 +392,7 @@ static unsigned long write_video(const char *buffer, unsigned long count) hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result); if (hci_result == HCI_SUCCESS) { - int new_video_out = video_out; + unsigned int new_video_out = video_out; if (lcd_out != -1) _set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out); if (crt_out != -1) -- cgit v1.2.3 From db89b4f0dbab837d0f3de2c3e9427a8d5393afa3 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 22 Sep 2008 14:37:34 -0700 Subject: ACPI: catch calls of acpi_driver_data on pointer of wrong type Catch attempts to use of acpi_driver_data on pointers of wrong type. akpm: rewritten to use proper C typechecking and remove the "function"-used-as-lvalue thing. Signed-off-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/ac.c | 2 +- drivers/acpi/acpi_memhotplug.c | 2 +- drivers/acpi/asus_acpi.c | 2 +- drivers/acpi/battery.c | 2 +- drivers/acpi/button.c | 2 +- drivers/acpi/container.c | 2 +- drivers/acpi/ec.c | 4 ++-- drivers/acpi/fan.c | 2 +- drivers/acpi/pci_link.c | 2 +- drivers/acpi/pci_root.c | 2 +- drivers/acpi/power.c | 4 ++-- drivers/acpi/processor_core.c | 2 +- drivers/acpi/sbs.c | 2 +- drivers/acpi/sbshc.c | 4 ++-- drivers/acpi/scan.c | 4 ++-- drivers/acpi/thermal.c | 2 +- drivers/acpi/video.c | 6 +++--- 17 files changed, 23 insertions(+), 23 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 831883b7d6c9..8b6a84a43b15 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -269,7 +269,7 @@ static int acpi_ac_add(struct acpi_device *device) ac->device = device; strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_AC_CLASS); - acpi_driver_data(device) = ac; + device->driver_data = ac; result = acpi_ac_get_state(ac); if (result) diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 5f1127ad5a95..afd955fc0dc2 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -403,7 +403,7 @@ static int acpi_memory_device_add(struct acpi_device *device) mem_device->device = device; sprintf(acpi_device_name(device), "%s", ACPI_MEMORY_DEVICE_NAME); sprintf(acpi_device_class(device), "%s", ACPI_MEMORY_DEVICE_CLASS); - acpi_driver_data(device) = mem_device; + device->driver_data = mem_device; /* Get the range from the _CRS */ result = acpi_memory_get_device_resources(mem_device); diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index d3d0886d637f..91571fc0f17d 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -1321,7 +1321,7 @@ static int asus_hotk_add(struct acpi_device *device) hotk->handle = device->handle; strcpy(acpi_device_name(device), ACPI_HOTK_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_HOTK_CLASS); - acpi_driver_data(device) = hotk; + device->driver_data = hotk; hotk->device = device; result = asus_hotk_check(); diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index b1c723f9f58d..de8046933bce 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -804,7 +804,7 @@ static int acpi_battery_add(struct acpi_device *device) battery->device = device; strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); - acpi_driver_data(device) = battery; + device->driver_data = battery; mutex_init(&battery->lock); acpi_battery_update(battery); #ifdef CONFIG_ACPI_PROCFS_POWER diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 1dfec413588c..e22033ea2614 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -384,7 +384,7 @@ static int acpi_button_add(struct acpi_device *device) return -ENOMEM; button->device = device; - acpi_driver_data(device) = button; + device->driver_data = button; button->input = input = input_allocate_device(); if (!input) { diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 3c25ec7a1871..03ea8478e393 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -108,7 +108,7 @@ static int acpi_container_add(struct acpi_device *device) container->handle = device->handle; strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS); - acpi_driver_data(device) = container; + device->driver_data = container; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n", acpi_device_name(device), acpi_device_bid(device))); diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 13593f9f2197..5741d99d6034 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -788,7 +788,7 @@ static int acpi_ec_add(struct acpi_device *device) if (!first_ec) first_ec = ec; - acpi_driver_data(device) = ec; + device->driver_data = ec; acpi_ec_add_fs(device); pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", ec->gpe, ec->command_addr, ec->data_addr); @@ -813,7 +813,7 @@ static int acpi_ec_remove(struct acpi_device *device, int type) } mutex_unlock(&ec->lock); acpi_ec_remove_fs(device); - acpi_driver_data(device) = NULL; + device->driver_data = NULL; if (ec == first_ec) first_ec = NULL; kfree(ec); diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 2655bc1b4eeb..e603e4070702 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -265,7 +265,7 @@ static int acpi_fan_add(struct acpi_device *device) dev_info(&device->dev, "registered as cooling_device%d\n", cdev->id); - acpi_driver_data(device) = cdev; + device->driver_data = cdev; result = sysfs_create_link(&device->dev.kobj, &cdev->device.kobj, "thermal_cooling"); diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index cf47805a7448..54cd77a0a78e 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -737,7 +737,7 @@ static int acpi_pci_link_add(struct acpi_device *device) link->device = device; strcpy(acpi_device_name(device), ACPI_PCI_LINK_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS); - acpi_driver_data(device) = link; + device->driver_data = link; mutex_lock(&acpi_link_lock); result = acpi_pci_link_get_possible(link); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index c3fed31166b5..add1a19bbbfe 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -206,7 +206,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) root->device = device; strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); - acpi_driver_data(device) = root; + device->driver_data = root; device->ops.bind = acpi_pci_bind; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 4ab21cb1c8c7..1bef9429189b 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -657,7 +657,7 @@ static int acpi_power_add(struct acpi_device *device) strcpy(resource->name, device->pnp.bus_id); strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_POWER_CLASS); - acpi_driver_data(device) = resource; + device->driver_data = resource; /* Evalute the object to get the system level and resource order. */ status = acpi_evaluate_object(device->handle, NULL, NULL, &buffer); @@ -733,7 +733,7 @@ static int acpi_power_resume(struct acpi_device *device) if (!device || !acpi_driver_data(device)) return -EINVAL; - resource = (struct acpi_power_resource *)acpi_driver_data(device); + resource = acpi_driver_data(device); result = acpi_power_get_state(resource, &state); if (result) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index ee68ac54c0d4..289461649196 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -818,7 +818,7 @@ static int acpi_processor_add(struct acpi_device *device) pr->handle = device->handle; strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS); - acpi_driver_data(device) = pr; + device->driver_data = pr; return 0; } diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 10a36512647c..d0033250b5a9 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -931,7 +931,7 @@ static int acpi_sbs_add(struct acpi_device *device) sbs->device = device; strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_SBS_CLASS); - acpi_driver_data(device) = sbs; + device->driver_data = sbs; result = acpi_charger_add(sbs); if (result) diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index a4e3767b8c64..001d9143a2cb 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -282,7 +282,7 @@ static int acpi_smbus_hc_add(struct acpi_device *device) hc->ec = acpi_driver_data(device->parent); hc->offset = (val >> 8) & 0xff; hc->query_bit = val & 0xff; - acpi_driver_data(device) = hc; + device->driver_data = hc; acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc); printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n", @@ -303,7 +303,7 @@ static int acpi_smbus_hc_remove(struct acpi_device *device, int type) hc = acpi_driver_data(device); acpi_ec_remove_query_handler(hc->ec, hc->query_bit); kfree(hc); - acpi_driver_data(device) = NULL; + device->driver_data = NULL; return 0; } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index e7b8853c310b..b88536ab040a 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -384,7 +384,7 @@ static int acpi_device_remove(struct device * dev) acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type); } acpi_dev->driver = NULL; - acpi_driver_data(acpi_dev) = NULL; + acpi_dev->driver_data = NULL; put_device(dev); return 0; @@ -537,7 +537,7 @@ acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver) result = driver->ops.add(device); if (result) { device->driver = NULL; - acpi_driver_data(device) = NULL; + device->driver_data = NULL; return result; } diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 912703691d36..e052a75c29ce 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -1647,7 +1647,7 @@ static int acpi_thermal_add(struct acpi_device *device) strcpy(tz->name, device->pnp.bus_id); strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS); - acpi_driver_data(device) = tz; + device->driver_data = tz; mutex_init(&tz->lock); diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index e8a51a1700f7..85c6554bcb4c 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1491,7 +1491,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device, strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); - acpi_driver_data(device) = data; + device->driver_data = data; data->device_id = device_id; data->video = video; @@ -1982,7 +1982,7 @@ static int acpi_video_bus_add(struct acpi_device *device) video->device = device; strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME); strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); - acpi_driver_data(device) = video; + device->driver_data = video; acpi_video_bus_find_cap(video); error = acpi_video_bus_check(video); @@ -2058,7 +2058,7 @@ static int acpi_video_bus_add(struct acpi_device *device) acpi_video_bus_remove_fs(device); err_free_video: kfree(video); - acpi_driver_data(device) = NULL; + device->driver_data = NULL; return error; } -- cgit v1.2.3 From b3cef8f6eba47a10b80aa3e7a99e27110e34f3df Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 19 Sep 2008 14:06:59 -0700 Subject: toshiba_acpi: depends on INPUT CONFIG_ACPI_TOSHIBA can =y when CONFIG_INPUT=m, so prevent that combination and its subsequent build errors: toshiba_acpi.c:(.text+0x3e877): undefined reference to `input_event' toshiba_acpi.c:(.text+0x3e98a): undefined reference to `input_unregister_polled_device' toshiba_acpi.c:(.text+0x3e994): undefined reference to `input_free_polled_device' toshiba_acpi.c:(.init.text+0x21b4): undefined reference to `input_allocate_polled_device' toshiba_acpi.c:(.init.text+0x2263): undefined reference to `input_register_polled_device' make[1]: *** [.tmp_vmlinux1] Error 1 Signed-off-by: Randy Dunlap Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 735f5ea17473..79540db29808 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -259,7 +259,7 @@ config ACPI_ASUS config ACPI_TOSHIBA tristate "Toshiba Laptop Extras" - depends on X86 + depends on X86 && INPUT select BACKLIGHT_CLASS_DEVICE ---help--- This driver adds support for access to certain system settings -- cgit v1.2.3 From 0a918a9432cc30aede10f904253b66ea6ab485ac Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Sat, 11 Oct 2008 00:15:04 -0400 Subject: Subject: ACPI dock: Use ACPI_EXCEPTION instead of printk(KERN_ERR lenb: stripped patch down to what still applied to new dock.c Signed-off-by: Thomas Renninger Signed-off-by: Len Brown --- drivers/acpi/dock.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index b7d15818215c..913bb1e89dd6 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -488,8 +488,9 @@ static void handle_dock(struct dock_station *ds, int dock) arg.integer.value = dock; status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) - printk(KERN_ERR PREFIX "%s - failed to execute _DCK\n", - (char *)name_buffer.pointer); + ACPI_EXCEPTION((AE_INFO, status, "%s - failed to execute" + " _DCK\n", (char *)name_buffer.pointer)); + kfree(buffer.pointer); kfree(name_buffer.pointer); } -- cgit v1.2.3 From 455c8793d2c49eaecad038c8de83dade9fc3759f Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 6 Oct 2008 10:31:36 +0800 Subject: ACPI: Enable EC device immediately after ACPI full initialization when there is no ECDT table and no _INI object for EC device, it will be enabled before scanning ACPI device. But it is too late after the following the commit is merged. >commit 7752d5cfe3d11ca0bb9c673ec38bd78ba6578f8e > Author: Robert Hancock > Date: Fri Feb 15 01:27:20 2008 -0800 >x86: validate against acpi motherboard resources After the above commit is merged, OS will check whether MCFG area is reserved in ACPI motherboard resources by calling the function of acpi_get_devices when there exists MCFG table. In the acpi_get_devices the _STA object will be evaluated to check the status of the ACPI device. On some broken BIOS the MYEC object of EC device is initialized as one, which indicates that EC operation region is already accessible before enabling EC device.So on these broken BIOS the EC operation region will be accessed in course of evaluating the _STA object before enabling EC device, which causes that OS will print the following warning messages: >ACPI Error (evregion-0315): No handler for Region [EC__] (ffff88007f8145e8) [EmbeddedControl] [20080609] >ACPI Error (exfldio-0290): Region EmbeddedControl(3) has no handler [20080321] >ACPI Error (psparse-0530): Method parse/execution failed [\_SB_.PCI0.SBRG. EC__.BAT1._STA] (Node ffff81013fc17a00), AE_NOT_EXIST >ACPI Error (uteval-0233): Method execution failed [\_SB_.PCI0.SBRG.EC__.BAT1. _STA] (Node ffff81013fc17a00), AE_NOT_EXIST Although the above warning message is harmless, it looks confusing. So it is necessary to enable EC device as early as possible.Maybe it is appropriate to enable it immediately after ACPI full initialization. http://bugzilla.kernel.org/show_bug.cgi?id=11255 http://bugzilla.kernel.org/show_bug.cgi?id=11374 http://bugzilla.kernel.org/show_bug.cgi?id=11660 Signed-off-by: Zhao Yakui Acked-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/bus.c | 6 ++++++ drivers/acpi/scan.c | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index ccae305ee55d..0e0bbc6209e5 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -749,6 +749,12 @@ static int __init acpi_bus_init(void) goto error1; } + /* + * Maybe EC region is required at bus_scan/acpi_get_devices. So it + * is necessary to enable it as early as possible. + */ + acpi_boot_ec_enable(); + printk(KERN_INFO PREFIX "Interpreter enabled\n"); /* Initialize sleep structures */ diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f6f52c1a2aba..2ae218f5ea59 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1545,7 +1545,6 @@ static int acpi_bus_scan_fixed(struct acpi_device *root) return result; } -int __init acpi_boot_ec_enable(void); static int __init acpi_scan_init(void) { @@ -1579,9 +1578,6 @@ static int __init acpi_scan_init(void) */ result = acpi_bus_scan_fixed(acpi_root); - /* EC region might be needed at bus_scan, so enable it now */ - acpi_boot_ec_enable(); - if (!result) result = acpi_bus_scan(acpi_root, &ops); -- cgit v1.2.3 From 27663c5855b10af9ec67bc7dfba001426ba21222 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 10 Oct 2008 02:22:59 -0400 Subject: ACPI: Change acpi_evaluate_integer to support 64-bit on 32-bit kernels As of version 2.0, ACPI can return 64-bit integers. The current acpi_evaluate_integer only supports 64-bit integers on 64-bit platforms. Change the argument to take a pointer to an acpi_integer so we support 64-bit integers on all platforms. lenb: replaced use of "acpi_integer" with "unsigned long long" lenb: fixed bug in acpi_thermal_trips_update() Signed-off-by: Matthew Wilcox Signed-off-by: Len Brown --- drivers/acpi/ac.c | 2 +- drivers/acpi/acpi_memhotplug.c | 5 ++--- drivers/acpi/asus_acpi.c | 2 +- drivers/acpi/bay.c | 2 +- drivers/acpi/bus.c | 4 ++-- drivers/acpi/button.c | 4 ++-- drivers/acpi/container.c | 2 +- drivers/acpi/dock.c | 6 +++--- drivers/acpi/ec.c | 7 ++++-- drivers/acpi/numa.c | 2 +- drivers/acpi/osl.c | 5 ++--- drivers/acpi/pci_root.c | 2 +- drivers/acpi/pci_slot.c | 10 ++++----- drivers/acpi/power.c | 2 +- drivers/acpi/processor_core.c | 4 ++-- drivers/acpi/processor_perflib.c | 2 +- drivers/acpi/processor_throttling.c | 2 +- drivers/acpi/sbshc.c | 2 +- drivers/acpi/sleep/main.c | 2 +- drivers/acpi/thermal.c | 43 +++++++++++++++++++++++-------------- drivers/acpi/utils.c | 4 ++-- drivers/acpi/video.c | 42 ++++++++++++++++++------------------ 22 files changed, 84 insertions(+), 72 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 831883b7d6c9..5e57a80c6cf1 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -85,7 +85,7 @@ struct acpi_ac { struct power_supply charger; #endif struct acpi_device * device; - unsigned long state; + unsigned long long state; }; #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger); diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 5f1127ad5a95..2b773160e9c2 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -194,8 +194,7 @@ acpi_memory_get_device(acpi_handle handle, static int acpi_memory_check_device(struct acpi_memory_device *mem_device) { - unsigned long current_status; - + unsigned long long current_status; /* Get device present/absent information from the _STA */ if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle, "_STA", @@ -264,7 +263,7 @@ static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device) acpi_status status; struct acpi_object_list arg_list; union acpi_object arg; - unsigned long current_status; + unsigned long long current_status; /* Issue the _EJ0 command */ diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index d3d0886d637f..4434209e453e 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -753,7 +753,7 @@ static int get_lcd_state(void) /* That's what the AML code does */ lcd = out_obj.integer.value >> 8; } else if (hotk->model == F3Sa) { - unsigned long tmp; + unsigned long long tmp; union acpi_object param; struct acpi_object_list input; acpi_status status; diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c index 61b6c5beb2d3..23a51e4779f7 100644 --- a/drivers/acpi/bay.c +++ b/drivers/acpi/bay.c @@ -90,7 +90,7 @@ static int is_ejectable(acpi_handle handle) */ static int bay_present(struct bay *bay) { - unsigned long sta; + unsigned long long sta; acpi_status status; if (bay) { diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index ccae305ee55d..0885fc796fa0 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -77,7 +77,7 @@ EXPORT_SYMBOL(acpi_bus_get_device); int acpi_bus_get_status(struct acpi_device *device) { acpi_status status = AE_OK; - unsigned long sta = 0; + unsigned long long sta = 0; if (!device) @@ -155,7 +155,7 @@ int acpi_bus_get_power(acpi_handle handle, int *state) int result = 0; acpi_status status = 0; struct acpi_device *device = NULL; - unsigned long psc = 0; + unsigned long long psc = 0; result = acpi_bus_get_device(handle, &device); diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 1dfec413588c..baeb661ca953 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -145,7 +145,7 @@ static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) { struct acpi_button *button = seq->private; acpi_status status; - unsigned long state; + unsigned long long state; if (!button || !button->device) return 0; @@ -253,7 +253,7 @@ static int acpi_button_remove_fs(struct acpi_device *device) -------------------------------------------------------------------------- */ static int acpi_lid_send_state(struct acpi_button *button) { - unsigned long state; + unsigned long long state; acpi_status status; status = acpi_evaluate_integer(button->device->handle, "_LID", NULL, diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 3c25ec7a1871..cfa5fd68168a 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -76,7 +76,7 @@ static int is_device_present(acpi_handle handle) { acpi_handle temp; acpi_status status; - unsigned long sta; + unsigned long long sta; status = acpi_get_handle(handle, "_STA", &temp); diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 7d2edf143f16..94857112b64d 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -229,7 +229,7 @@ EXPORT_SYMBOL_GPL(is_dock_device); */ static int dock_present(struct dock_station *ds) { - unsigned long sta; + unsigned long long sta; acpi_status status; if (ds) { @@ -727,13 +727,13 @@ static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock); static ssize_t show_dock_uid(struct device *dev, struct device_attribute *attr, char *buf) { - unsigned long lbuf; + unsigned long long lbuf; acpi_status status = acpi_evaluate_integer(dock_station->handle, "_UID", NULL, &lbuf); if (ACPI_FAILURE(status)) return 0; - return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf); + return snprintf(buf, PAGE_SIZE, "%llx\n", lbuf); } static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL); diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 13593f9f2197..638a68679a42 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -718,6 +718,7 @@ static acpi_status ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) { acpi_status status; + unsigned long long tmp; struct acpi_ec *ec = context; status = acpi_walk_resources(handle, METHOD_NAME__CRS, @@ -727,11 +728,13 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) /* Get GPE bit assignment (EC events). */ /* TODO: Add support for _GPE returning a package */ - status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe); + status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp); if (ACPI_FAILURE(status)) return status; + ec->gpe = tmp; /* Use the global lock for all EC transactions? */ - acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock); + acpi_evaluate_integer(handle, "_GLK", NULL, &tmp); + ec->global_lock = tmp; ec->handle = handle; return AE_CTRL_TERMINATE; } diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index cb9864e39bae..25ceae9191ef 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -258,7 +258,7 @@ int __init acpi_numa_init(void) int acpi_get_pxm(acpi_handle h) { - unsigned long pxm; + unsigned long long pxm; acpi_status status; acpi_handle handle; acpi_handle phandle = h; diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 235a1386888a..f58fcbbc810d 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -608,7 +608,7 @@ static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */ acpi_handle handle; struct acpi_pci_id *pci_id = *id; acpi_status status; - unsigned long temp; + unsigned long long temp; acpi_object_type type; acpi_get_parent(chandle, &handle); @@ -620,8 +620,7 @@ static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */ if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE)) return; - status = - acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, + status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &temp); if (ACPI_SUCCESS(status)) { u32 val; diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index c3fed31166b5..18ff4e5c8d81 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -190,7 +190,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) struct acpi_pci_root *root = NULL; struct acpi_pci_root *tmp; acpi_status status = AE_OK; - unsigned long value = 0; + unsigned long long value = 0; acpi_handle handle = NULL; struct acpi_device *child; diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c index d5b4ef898879..9bb84d4596be 100644 --- a/drivers/acpi/pci_slot.c +++ b/drivers/acpi/pci_slot.c @@ -76,10 +76,10 @@ static struct acpi_pci_driver acpi_pci_slot_driver = { }; static int -check_slot(acpi_handle handle, unsigned long *sun) +check_slot(acpi_handle handle, unsigned long long *sun) { int device = -1; - unsigned long adr, sta; + unsigned long long adr, sta; acpi_status status; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -132,7 +132,7 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) { int device; - unsigned long sun; + unsigned long long sun; char name[SLOT_NAME_SIZE]; struct acpi_pci_slot *slot; struct pci_slot *pci_slot; @@ -182,7 +182,7 @@ static acpi_status walk_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) { int device, function; - unsigned long adr; + unsigned long long adr; acpi_status status; acpi_handle dummy_handle; acpi_walk_callback user_function; @@ -239,7 +239,7 @@ static int walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function) { int seg, bus; - unsigned long tmp; + unsigned long long tmp; acpi_status status; acpi_handle dummy_handle; struct pci_bus *pci_bus; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 4ab21cb1c8c7..89e5d2a8c33a 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -131,7 +131,7 @@ acpi_power_get_context(acpi_handle handle, static int acpi_power_get_state(struct acpi_power_resource *resource, int *state) { acpi_status status = AE_OK; - unsigned long sta = 0; + unsigned long long sta = 0; if (!resource || !state) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index ee68ac54c0d4..8a2787141f80 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -563,7 +563,7 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) /* Check if it is a Device with HID and UID */ if (has_uid) { - unsigned long value; + unsigned long long value; status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, NULL, &value); if (ACPI_FAILURE(status)) { @@ -875,7 +875,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type) static int is_processor_present(acpi_handle handle) { acpi_status status; - unsigned long sta = 0; + unsigned long long sta = 0; status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 80c251ec6d2a..f8129c7277f1 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -126,7 +126,7 @@ static struct notifier_block acpi_ppc_notifier_block = { static int acpi_processor_get_platform_limit(struct acpi_processor *pr) { acpi_status status = 0; - unsigned long ppc = 0; + unsigned long long ppc = 0; if (!pr) diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index a56fc6c4394b..3097b752003d 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -274,7 +274,7 @@ static int acpi_processor_throttling_notifier(unsigned long event, void *data) static int acpi_processor_get_platform_limit(struct acpi_processor *pr) { acpi_status status = 0; - unsigned long tpc = 0; + unsigned long long tpc = 0; if (!pr) return -EINVAL; diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index a4e3767b8c64..81d23d38ec91 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -258,7 +258,7 @@ extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, static int acpi_smbus_hc_add(struct acpi_device *device) { int status; - unsigned long val; + unsigned long long val; struct acpi_smb_hc *hc; if (!device) diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index d13194a031bf..b32ba565e69e 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -444,7 +444,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) acpi_handle handle = DEVICE_ACPI_HANDLE(dev); struct acpi_device *adev; char acpi_method[] = "_SxD"; - unsigned long d_min, d_max; + unsigned long long d_min, d_max; if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { printk(KERN_DEBUG "ACPI handle has no context!\n"); diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 912703691d36..47abb94bdfb9 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -246,18 +246,18 @@ static const struct file_operations acpi_thermal_polling_fops = { static int acpi_thermal_get_temperature(struct acpi_thermal *tz) { acpi_status status = AE_OK; - + unsigned long long tmp; if (!tz) return -EINVAL; tz->last_temperature = tz->temperature; - status = - acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tz->temperature); + status = acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tmp); if (ACPI_FAILURE(status)) return -ENODEV; + tz->temperature = tmp; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n", tz->temperature)); @@ -267,17 +267,16 @@ static int acpi_thermal_get_temperature(struct acpi_thermal *tz) static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz) { acpi_status status = AE_OK; - + unsigned long long tmp; if (!tz) return -EINVAL; - status = - acpi_evaluate_integer(tz->device->handle, "_TZP", NULL, - &tz->polling_frequency); + status = acpi_evaluate_integer(tz->device->handle, "_TZP", NULL, &tmp); if (ACPI_FAILURE(status)) return -ENODEV; + tz->polling_frequency = tmp; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n", tz->polling_frequency)); @@ -356,6 +355,7 @@ do { \ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) { acpi_status status = AE_OK; + unsigned long long tmp; struct acpi_handle_list devices; int valid = 0; int i; @@ -363,7 +363,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) /* Critical Shutdown (required) */ if (flag & ACPI_TRIPS_CRITICAL) { status = acpi_evaluate_integer(tz->device->handle, - "_CRT", NULL, &tz->trips.critical.temperature); + "_CRT", NULL, &tmp); + tz->trips.critical.temperature = tmp; /* * Treat freezing temperatures as invalid as well; some * BIOSes return really low values and cause reboots at startup. @@ -399,12 +400,13 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) /* Critical Sleep (optional) */ if (flag & ACPI_TRIPS_HOT) { status = acpi_evaluate_integer(tz->device->handle, - "_HOT", NULL, &tz->trips.hot.temperature); + "_HOT", NULL, &tmp); if (ACPI_FAILURE(status)) { tz->trips.hot.flags.valid = 0; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No hot threshold\n")); } else { + tz->trips.hot.temperature = tmp; tz->trips.hot.flags.valid = 1; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n", @@ -418,33 +420,40 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) if (psv == -1) { status = AE_SUPPORT; } else if (psv > 0) { - tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv); + tmp = CELSIUS_TO_KELVIN(psv); status = AE_OK; } else { status = acpi_evaluate_integer(tz->device->handle, - "_PSV", NULL, &tz->trips.passive.temperature); + "_PSV", NULL, &tmp); } if (ACPI_FAILURE(status)) tz->trips.passive.flags.valid = 0; else { + tz->trips.passive.temperature = tmp; tz->trips.passive.flags.valid = 1; if (flag == ACPI_TRIPS_INIT) { status = acpi_evaluate_integer( tz->device->handle, "_TC1", - NULL, &tz->trips.passive.tc1); + NULL, &tmp); if (ACPI_FAILURE(status)) tz->trips.passive.flags.valid = 0; + else + tz->trips.passive.tc1 = tmp; status = acpi_evaluate_integer( tz->device->handle, "_TC2", - NULL, &tz->trips.passive.tc2); + NULL, &tmp); if (ACPI_FAILURE(status)) tz->trips.passive.flags.valid = 0; + else + tz->trips.passive.tc2 = tmp; status = acpi_evaluate_integer( tz->device->handle, "_TSP", - NULL, &tz->trips.passive.tsp); + NULL, &tmp); if (ACPI_FAILURE(status)) tz->trips.passive.flags.valid = 0; + else + tz->trips.passive.tsp = tmp; } } } @@ -479,7 +488,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) if (flag & ACPI_TRIPS_ACTIVE) { status = acpi_evaluate_integer(tz->device->handle, - name, NULL, &tz->trips.active[i].temperature); + name, NULL, &tmp); if (ACPI_FAILURE(status)) { tz->trips.active[i].flags.valid = 0; if (i == 0) @@ -500,8 +509,10 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) tz->trips.active[i - 2].temperature : CELSIUS_TO_KELVIN(act)); break; - } else + } else { + tz->trips.active[i].temperature = tmp; tz->trips.active[i].flags.valid = 1; + } } name[2] = 'L'; diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 100926143818..e827be36ee8d 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -256,7 +256,7 @@ EXPORT_SYMBOL(acpi_extract_package); acpi_status acpi_evaluate_integer(acpi_handle handle, acpi_string pathname, - struct acpi_object_list *arguments, unsigned long *data) + struct acpi_object_list *arguments, unsigned long long *data) { acpi_status status = AE_OK; union acpi_object *element; @@ -288,7 +288,7 @@ acpi_evaluate_integer(acpi_handle handle, *data = element->integer.value; kfree(element); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%lu]\n", *data)); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data)); return AE_OK; } diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index e8a51a1700f7..79409c9d2ad6 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -291,20 +291,20 @@ static int acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level); static int acpi_video_device_lcd_get_level_current( struct acpi_video_device *device, - unsigned long *level); + unsigned long long *level); static int acpi_video_get_next_level(struct acpi_video_device *device, u32 level_current, u32 event); static void acpi_video_switch_brightness(struct acpi_video_device *device, int event); static int acpi_video_device_get_state(struct acpi_video_device *device, - unsigned long *state); + unsigned long long *state); static int acpi_video_output_get(struct output_device *od); static int acpi_video_device_set_state(struct acpi_video_device *device, int state); /*backlight device sysfs support*/ static int acpi_video_get_brightness(struct backlight_device *bd) { - unsigned long cur_level; + unsigned long long cur_level; int i; struct acpi_video_device *vd = (struct acpi_video_device *)bl_get_data(bd); @@ -336,7 +336,7 @@ static struct backlight_ops acpi_backlight_ops = { /*video output device sysfs support*/ static int acpi_video_output_get(struct output_device *od) { - unsigned long state; + unsigned long long state; struct acpi_video_device *vd = (struct acpi_video_device *)dev_get_drvdata(&od->dev); acpi_video_device_get_state(vd, &state); @@ -370,7 +370,7 @@ static int video_get_cur_state(struct thermal_cooling_device *cdev, char *buf) { struct acpi_device *device = cdev->devdata; struct acpi_video_device *video = acpi_driver_data(device); - unsigned long level; + unsigned long long level; int state; acpi_video_device_lcd_get_level_current(video, &level); @@ -410,7 +410,7 @@ static struct thermal_cooling_device_ops video_cooling_ops = { /* device */ static int -acpi_video_device_query(struct acpi_video_device *device, unsigned long *state) +acpi_video_device_query(struct acpi_video_device *device, unsigned long long *state) { int status; @@ -421,7 +421,7 @@ acpi_video_device_query(struct acpi_video_device *device, unsigned long *state) static int acpi_video_device_get_state(struct acpi_video_device *device, - unsigned long *state) + unsigned long long *state) { int status; @@ -436,7 +436,7 @@ acpi_video_device_set_state(struct acpi_video_device *device, int state) int status; union acpi_object arg0 = { ACPI_TYPE_INTEGER }; struct acpi_object_list args = { 1, &arg0 }; - unsigned long ret; + unsigned long long ret; arg0.integer.value = state; @@ -495,7 +495,7 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level) static int acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, - unsigned long *level) + unsigned long long *level) { if (device->cap._BQC) return acpi_evaluate_integer(device->dev->handle, "_BQC", NULL, @@ -549,7 +549,7 @@ static int acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option) { int status; - unsigned long tmp; + unsigned long long tmp; union acpi_object arg0 = { ACPI_TYPE_INTEGER }; struct acpi_object_list args = { 1, &arg0 }; @@ -564,7 +564,7 @@ acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option) } static int -acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id) +acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long long *id) { int status; @@ -575,7 +575,7 @@ acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id) static int acpi_video_bus_POST_options(struct acpi_video_bus *video, - unsigned long *options) + unsigned long long *options) { int status; @@ -918,7 +918,7 @@ static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset) { int status; struct acpi_video_device *dev = seq->private; - unsigned long state; + unsigned long long state; if (!dev) @@ -927,14 +927,14 @@ static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset) status = acpi_video_device_get_state(dev, &state); seq_printf(seq, "state: "); if (ACPI_SUCCESS(status)) - seq_printf(seq, "0x%02lx\n", state); + seq_printf(seq, "0x%02llx\n", state); else seq_printf(seq, "\n"); status = acpi_video_device_query(dev, &state); seq_printf(seq, "query: "); if (ACPI_SUCCESS(status)) - seq_printf(seq, "0x%02lx\n", state); + seq_printf(seq, "0x%02llx\n", state); else seq_printf(seq, "\n"); @@ -1217,7 +1217,7 @@ static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file) static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset) { struct acpi_video_bus *video = seq->private; - unsigned long options; + unsigned long long options; int status; @@ -1232,7 +1232,7 @@ static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset) printk(KERN_WARNING PREFIX "This indicates a BIOS bug. Please contact the manufacturer.\n"); } - printk("%lx\n", options); + printk("%llx\n", options); seq_printf(seq, "can POST: "); if (options & 2) seq_printf(seq, " "); @@ -1256,7 +1256,7 @@ static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset) { struct acpi_video_bus *video = seq->private; int status; - unsigned long id; + unsigned long long id; if (!video) @@ -1303,7 +1303,7 @@ acpi_video_bus_write_POST(struct file *file, struct seq_file *m = file->private_data; struct acpi_video_bus *video = m->private; char str[12] = { 0 }; - unsigned long opt, options; + unsigned long long opt, options; if (!video || count + 1 > sizeof str) @@ -1473,7 +1473,7 @@ static int acpi_video_bus_get_one_device(struct acpi_device *device, struct acpi_video_bus *video) { - unsigned long device_id; + unsigned long long device_id; int status; struct acpi_video_device *data; struct acpi_video_device_attrib* attribute; @@ -1724,7 +1724,7 @@ acpi_video_get_next_level(struct acpi_video_device *device, static void acpi_video_switch_brightness(struct acpi_video_device *device, int event) { - unsigned long level_current, level_next; + unsigned long long level_current, level_next; if (!device->brightness) return; acpi_video_device_lcd_get_level_current(device, &level_current); -- cgit v1.2.3 From a68823ee5285e65b51ceb96f8b13a5b4f99a6888 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 6 Aug 2008 19:12:04 +0100 Subject: ACPI: Clear WAK_STS on resume The leading other brand OS appears to clear the WAK_STS flag on resume. When rebooted, certain BIOSes assume that the system is actually resuming if it's still set and so fail to reboot correctly. Make sure that it's cleared at resume time. Comment clarified as suggested by Bob Moore http://bugzilla.kernel.org/show_bug.cgi?id=11634 Signed-off-by: Matthew Garrett Signed-off-by: Andi Kleen Tested-by: Christian Borntraeger Tested-by: Romano Giannetti Signed-off-by: Len Brown --- drivers/acpi/hardware/hwsleep.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index dba3cfbe8cba..130a44b79687 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -627,6 +627,13 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) } /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */ + /* + * Some BIOSes assume that WAK_STS will be cleared on resume and use + * it to determine whether the system is rebooting or resuming. Clear + * it for compatibility. + */ + acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); + acpi_gbl_system_awake_and_running = TRUE; /* Enable power button */ -- cgit v1.2.3 From addbad46ed0906cd584784423b9d0babc7476446 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Mon, 29 Sep 2008 15:24:28 -0700 Subject: cpuidle: update the last_state acpi cpuidle reflecting actual state entered reflect the actual state entered in dev->last_state, when actaul state entered is different from intended one. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index cf5b1b7b684f..81b40ed5379e 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -1587,6 +1587,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, if (acpi_idle_bm_check()) { if (dev->safe_state) { + dev->last_state = dev->safe_state; return dev->safe_state->enter(dev, dev->safe_state); } else { local_irq_disable(); -- cgit v1.2.3 From c0ff17720ec5f42205b3d2ca03a18da0a8272976 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Thu, 16 Oct 2008 02:02:33 +0400 Subject: ACPI: EC: Check for IBF=0 periodically if not in GPE mode Signed-off-by: Alexey Starikovskiy Tested-by: Alan Jenkins Signed-off-by: Len Brown --- drivers/acpi/ec.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 453ba1e534ef..444cd9ed12c7 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -298,6 +298,18 @@ static int ec_check_ibf0(struct acpi_ec *ec) return (status & ACPI_EC_FLAG_IBF) == 0; } +static int ec_wait_ibf0(struct acpi_ec *ec) +{ + unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); + /* interrupt wait manually if GPE mode is not active */ + unsigned long timeout = test_bit(EC_FLAGS_GPE_MODE, &ec->flags) ? + msecs_to_jiffies(ACPI_EC_DELAY) : msecs_to_jiffies(1); + while (time_before(jiffies, delay)) + if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), timeout)) + return 0; + return -ETIME; +} + static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t, int force_poll) { @@ -315,8 +327,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t, goto unlock; } } - if (!wait_event_timeout(ec->wait, ec_check_ibf0(ec), - msecs_to_jiffies(ACPI_EC_DELAY))) { + if (ec_wait_ibf0(ec)) { pr_err(PREFIX "input buffer is not empty, " "aborting transaction\n"); status = -ETIME; -- cgit v1.2.3 From e49f711cc8f3bf8d719a9f5c86e79ecc0a72bf70 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Tue, 12 Aug 2008 10:20:22 +0800 Subject: ACPI: Add the support for _TTS object The _TTS object is defined in the section 7.3 of acpi 3.0b spec. The _TTS control method is executed by the OSPM at the beginning of the sleep transition process for S1,S2, S3, S4, and orderly S5 shutdown. OS will invoke _TTS before it has notified any native mode device drivers of the sleep state transition. The target sleeping state value is passed to the _TTS control method. The _TTS control method is also executed by the OSPM at the end of any sleep transition process when the system transitions to S0 from S1, S2, S3, or S4. The _TTS object should be evaluated after it has notified any native mode device drivers of the end of the sleep state transition. The working state value (0) is passed to the _TTS control method. So it is necessary to add the support for _TTS object. The _TTS object will be evaluated if it exists. At the same time a block notifier is added to the reboot notifier list so that the _TTS object will also be evaluated when the system shutdown. lenb: note that as of Sep 2008, I've not yet seen _TTS in any shipping BIOS. So this patch is to future-proof Linux, rather than fix the installed base. http://bugzilla.kernel.org/show_bug.cgi?id=11132 Signed-off-by: Zhao Yakui Signed-off-by: Li Shaohua Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/sleep/main.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index d13194a031bf..c7f0c9cd8701 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -24,6 +25,36 @@ u8 sleep_states[ACPI_S_STATE_COUNT]; +static void acpi_sleep_tts_switch(u32 acpi_state) +{ + union acpi_object in_arg = { ACPI_TYPE_INTEGER }; + struct acpi_object_list arg_list = { 1, &in_arg }; + acpi_status status = AE_OK; + + in_arg.integer.value = acpi_state; + status = acpi_evaluate_object(NULL, "\\_TTS", &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + /* + * OS can't evaluate the _TTS object correctly. Some warning + * message will be printed. But it won't break anything. + */ + printk(KERN_NOTICE "Failure in evaluating _TTS object\n"); + } +} + +static int tts_notify_reboot(struct notifier_block *this, + unsigned long code, void *x) +{ + acpi_sleep_tts_switch(ACPI_STATE_S5); + return NOTIFY_DONE; +} + +static struct notifier_block tts_notifier = { + .notifier_call = tts_notify_reboot, + .next = NULL, + .priority = 0, +}; + static int acpi_sleep_prepare(u32 acpi_state) { #ifdef CONFIG_ACPI_SLEEP @@ -131,6 +162,7 @@ static void acpi_pm_end(void) * failing transition to a sleep state. */ acpi_target_sleep_state = ACPI_STATE_S0; + acpi_sleep_tts_switch(acpi_target_sleep_state); } #endif /* CONFIG_PM_SLEEP */ @@ -155,6 +187,7 @@ static int acpi_suspend_begin(suspend_state_t pm_state) if (sleep_states[acpi_state]) { acpi_target_sleep_state = acpi_state; + acpi_sleep_tts_switch(acpi_target_sleep_state); } else { printk(KERN_ERR "ACPI does not support this state: %d\n", pm_state); @@ -313,6 +346,7 @@ void __init acpi_no_s4_hw_signature(void) static int acpi_hibernation_begin(void) { acpi_target_sleep_state = ACPI_STATE_S4; + acpi_sleep_tts_switch(acpi_target_sleep_state); return 0; } @@ -376,7 +410,15 @@ static struct platform_hibernation_ops acpi_hibernation_ops = { */ static int acpi_hibernation_begin_old(void) { - int error = acpi_sleep_prepare(ACPI_STATE_S4); + int error; + /* + * The _TTS object should always be evaluated before the _PTS object. + * When the old_suspended_ordering is true, the _PTS object is + * evaluated in the acpi_sleep_prepare. + */ + acpi_sleep_tts_switch(ACPI_STATE_S4); + + error = acpi_sleep_prepare(ACPI_STATE_S4); if (!error) acpi_target_sleep_state = ACPI_STATE_S4; @@ -596,5 +638,10 @@ int __init acpi_sleep_init(void) pm_power_off = acpi_power_off; } printk(")\n"); + /* + * Register the tts_notifier to reboot notifier list so that the _TTS + * object can also be evaluated when the system enters S5. + */ + register_reboot_notifier(&tts_notifier); return 0; } -- cgit v1.2.3 From a6629105dd03d370fcb31e97bddf223fa4bb651e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 6 Sep 2008 13:13:01 +0200 Subject: ACPI suspend: Always use the 32-bit waking vector According to the ACPI specification 2.0c and later, the 64-bit waking vector should be cleared and the 32-bit waking vector should be used, unless we want the wake-up code to be called by the BIOS in Protected Mode. Moreover, some systems (for example HP dv5-1004nr) are known to fail to resume if the 64-bit waking vector is used. Therefore, modify the code to clear the 64-bit waking vector, for FACS version 1 or greater, and set the 32-bit one before suspend. http://bugzilla.kernel.org/show_bug.cgi?id=11368 Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/hardware/hwsleep.c | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 130a44b79687..25dccdf179b9 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -78,19 +78,17 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address) return_ACPI_STATUS(status); } - /* Set the vector */ + /* + * According to the ACPI specification 2.0c and later, the 64-bit + * waking vector should be cleared and the 32-bit waking vector should + * be used, unless we want the wake-up code to be called by the BIOS in + * Protected Mode. Some systems (for example HP dv5-1004nr) are known + * to fail to resume if the 64-bit vector is used. + */ + if (facs->version >= 1) + facs->xfirmware_waking_vector = 0; - if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) { - /* - * ACPI 1.0 FACS or short table or optional X_ field is zero - */ - facs->firmware_waking_vector = (u32) physical_address; - } else { - /* - * ACPI 2.0 FACS with valid X_ field - */ - facs->xfirmware_waking_vector = physical_address; - } + facs->firmware_waking_vector = (u32)physical_address; return_ACPI_STATUS(AE_OK); } @@ -134,20 +132,7 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) } /* Get the vector */ - - if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) { - /* - * ACPI 1.0 FACS or short table or optional X_ field is zero - */ - *physical_address = - (acpi_physical_address) facs->firmware_waking_vector; - } else { - /* - * ACPI 2.0 FACS with valid X_ field - */ - *physical_address = - (acpi_physical_address) facs->xfirmware_waking_vector; - } + *physical_address = (acpi_physical_address)facs->firmware_waking_vector; return_ACPI_STATUS(AE_OK); } -- cgit v1.2.3 From d0c71fe7ebc180f1b7bc7da1d39a07fc19eec768 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 4 Oct 2008 00:05:05 +0200 Subject: ACPI Suspend: Enable ACPI during resume if SCI_EN is not set On some machines, like for example MSI Wind U100, the BIOS doesn't enable ACPI before returning control to the OS, which sometimes causes resume to fail. This is against the ACPI specification, which clearly states that "When the platform is waking from an S1, S2 or S3 state, OSPM assumes the hardware is already in the ACPI mode and will not issue an ACPI_ENABLE", but it won't hurt to check the SCI_EN bit and enable ACPI during resume from S3 if this bit is not set. Fortunately, we already have acpi_enable() for that, so use it in the resume code path, before executing _BFS, in analogy with the resume-from-hibernation code path. NOTE: We aren't supposed to set SCI_EN directly, because it's owned by the hardware. Signed-off-by: Rafael J. Wysocki Pavel Machek Signed-off-by: Len Brown --- drivers/acpi/sleep/main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index c7f0c9cd8701..5419938ef297 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -233,6 +233,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state) break; } + /* If ACPI is not enabled by the BIOS, we need to enable it here. */ + acpi_enable(); /* Reprogram control registers and execute _BFS */ acpi_leave_sleep_state_prep(acpi_state); -- cgit v1.2.3 From 4fb507b6b764195bb7821cf2baa988f6eb677d30 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 14 Oct 2008 22:54:06 +0200 Subject: ACPI suspend: Blacklist HP xw4600 Workstation for old code ordering HP xw4600 Workstation is known to require the "old" (ie. compatible with ACPI 1.0) suspend code ordering, so blacklist it for this purpose. Signed-off-by: Rafael J. Wysocki Tested-by: John Brown Signed-off-by: Len Brown --- drivers/acpi/sleep/main.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 5419938ef297..2a312702225f 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -331,6 +331,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"), }, }, + { + .callback = init_old_suspend_ordering, + .ident = "HP xw4600 Workstation", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"), + }, + }, {}, }; #endif /* CONFIG_SUSPEND */ -- cgit v1.2.3 From 7745384080ef70f7710530afa3e45477b126e056 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 17 Oct 2008 01:42:41 -0400 Subject: don't load asus-acpi if model is not supported asus_hotk_get_info should return -ENODEV if the model is not supported. http://bugzilla.kernel.org/show_bug.cgi?id=10389 Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/asus_acpi.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index 91571fc0f17d..428e47b1ca6b 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -1244,6 +1244,8 @@ static int asus_hotk_get_info(void) "default values\n", string); printk(KERN_NOTICE " send /proc/acpi/dsdt to the developers\n"); + kfree(model); + return -ENODEV; } hotk->methods = &model_conf[hotk->model]; return AE_OK; -- cgit v1.2.3 From 20edd74fcf9ad02c19efba0c13670a7b6b045099 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 17 Oct 2008 02:02:44 -0400 Subject: ACPI: Ignore AE_NOT_FOUND error of EC _REG method and continue to initialize EC On some broken BIOS the ACPI object in EC _REG method can't be found in ACPI namespace, which causes that the status code of AE_NOT_FOUND is returned by the EC _REG object. In such case the EC device can't be initialized correctly, which causes that battery/AC adapter can't work normally. As the EC address space handler is not removed and the memory pointed by its input argument is already free, sometimes the kernel will also be panic when EC internal register is still accessed. But the windows can work well on such broken BIOS. Maybe it will be reasonable that OS ignores the AE_NOT_FOUND error returned by the EC _REG object and continues to initialize EC device on some broken BIOS. For example: the ACPI object in EC _REG method can't be found and status error code is AE_NOT_FOUND. http://bugzilla.kernel.org/show_bug.cgi?id=8953 http://bugzilla.kernel.org/show_bug.cgi?id=10237 lenb: we may find a more general solution to this in the future. Signed-off-by: Zhao Yakui Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/ec.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 13593f9f2197..4c004286b3d9 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -862,8 +862,19 @@ static int ec_install_handlers(struct acpi_ec *ec) &acpi_ec_space_handler, NULL, ec); if (ACPI_FAILURE(status)) { - acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler); - return -ENODEV; + if (status == AE_NOT_FOUND) { + /* + * Maybe OS fails in evaluating the _REG object. + * The AE_NOT_FOUND error will be ignored and OS + * continue to initialize EC. + */ + printk(KERN_ERR "Fail in evaluating the _REG object" + " of EC device. Broken bios is suspected.\n"); + } else { + acpi_remove_gpe_handler(NULL, ec->gpe, + &acpi_ec_gpe_handler); + return -ENODEV; + } } ec->handlers_installed = 1; -- cgit v1.2.3 From 22a94d79a34bf010d11996d30eed8ee3fc1a4fbf Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 17 Oct 2008 02:41:20 -0400 Subject: ACPI: Allow overriding to higher critical trip point. http://bugzilla.kernel.org/show_bug.cgi?id=9129 lenb: Note that overriding a critical trip point may simply fool the user into thinking that they have control that they do not actually have. For it is EC firmware that decides when the EC sends Linux temperature change events, and the EC may or may not decide to send Linux these events anywhere in the neighborhood of the fake override trip points. Beware. note also that thermal.nocrt is already available to disable crtical trip point actios, and thermal.crt=-1 is already available to disabled critical trip points entirely. Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/thermal.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index e052a75c29ce..e9e17dfc5dc2 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -388,10 +388,12 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) } else if (crt > 0) { unsigned long crt_k = CELSIUS_TO_KELVIN(crt); /* - * Allow override to lower critical threshold + * Allow override critical threshold */ - if (crt_k < tz->trips.critical.temperature) - tz->trips.critical.temperature = crt_k; + if (crt_k > tz->trips.critical.temperature) + printk(KERN_WARNING PREFIX + "Critical threshold %d C\n", crt); + tz->trips.critical.temperature = crt_k; } } } -- cgit v1.2.3 From c6c38bac2608b0f439b9ede72394780fe7fe1951 Mon Sep 17 00:00:00 2001 From: Mike Dahlgren Date: Fri, 17 Oct 2008 14:35:14 -0400 Subject: asus_acpi: whitespace and comment cleanup Signed-off-by: Mike Dahlgren Signed-off-by: Len Brown --- drivers/acpi/asus_acpi.c | 221 +++++++++++++++++++++++------------------------ 1 file changed, 110 insertions(+), 111 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index d3d0886d637f..3f7adf683d4e 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -42,7 +42,7 @@ #define ASUS_ACPI_VERSION "0.30" -#define PROC_ASUS "asus" //the directory +#define PROC_ASUS "asus" /* The directory */ #define PROC_MLED "mled" #define PROC_WLED "wled" #define PROC_TLED "tled" @@ -66,10 +66,10 @@ /* * Flags for hotk status */ -#define MLED_ON 0x01 //mail LED -#define WLED_ON 0x02 //wireless LED -#define TLED_ON 0x04 //touchpad LED -#define BT_ON 0x08 //internal Bluetooth +#define MLED_ON 0x01 /* Mail LED */ +#define WLED_ON 0x02 /* Wireless LED */ +#define TLED_ON 0x04 /* Touchpad LED */ +#define BT_ON 0x08 /* Internal Bluetooth */ MODULE_AUTHOR("Julien Lerouge, Karol Kozimor"); MODULE_DESCRIPTION(ACPI_HOTK_NAME); @@ -82,28 +82,28 @@ MODULE_PARM_DESC(asus_uid, "UID for entries in /proc/acpi/asus"); module_param(asus_gid, uint, 0); MODULE_PARM_DESC(asus_gid, "GID for entries in /proc/acpi/asus"); -/* For each model, all features implemented, +/* For each model, all features implemented, * those marked with R are relative to HOTK, A for absolute */ struct model_data { - char *name; //name of the laptop________________A - char *mt_mled; //method to handle mled_____________R - char *mled_status; //node to handle mled reading_______A - char *mt_wled; //method to handle wled_____________R - char *wled_status; //node to handle wled reading_______A - char *mt_tled; //method to handle tled_____________R - char *tled_status; //node to handle tled reading_______A - char *mt_ledd; //method to handle LED display______R - char *mt_bt_switch; //method to switch Bluetooth on/off_R - char *bt_status; //no model currently supports this__? - char *mt_lcd_switch; //method to turn LCD on/off_________A - char *lcd_status; //node to read LCD panel state______A - char *brightness_up; //method to set brightness up_______A - char *brightness_down; //guess what ?______________________A - char *brightness_set; //method to set absolute brightness_R - char *brightness_get; //method to get absolute brightness_R - char *brightness_status; //node to get brightness____________A - char *display_set; //method to set video output________R - char *display_get; //method to get video output________R + char *name; /* name of the laptop________________A */ + char *mt_mled; /* method to handle mled_____________R */ + char *mled_status; /* node to handle mled reading_______A */ + char *mt_wled; /* method to handle wled_____________R */ + char *wled_status; /* node to handle wled reading_______A */ + char *mt_tled; /* method to handle tled_____________R */ + char *tled_status; /* node to handle tled reading_______A */ + char *mt_ledd; /* method to handle LED display______R */ + char *mt_bt_switch; /* method to switch Bluetooth on/off_R */ + char *bt_status; /* no model currently supports this__? */ + char *mt_lcd_switch; /* method to turn LCD on/off_________A */ + char *lcd_status; /* node to read LCD panel state______A */ + char *brightness_up; /* method to set brightness up_______A */ + char *brightness_down; /* method to set brightness down ____A */ + char *brightness_set; /* method to set absolute brightness_R */ + char *brightness_get; /* method to get absolute brightness_R */ + char *brightness_status;/* node to get brightness____________A */ + char *display_set; /* method to set video output________R */ + char *display_get; /* method to get video output________R */ }; /* @@ -111,41 +111,41 @@ struct model_data { * about the hotk device */ struct asus_hotk { - struct acpi_device *device; //the device we are in - acpi_handle handle; //the handle of the hotk device - char status; //status of the hotk, for LEDs, ... - u32 ledd_status; //status of the LED display - struct model_data *methods; //methods available on the laptop - u8 brightness; //brightness level + struct acpi_device *device; /* the device we are in */ + acpi_handle handle; /* the handle of the hotk device */ + char status; /* status of the hotk, for LEDs */ + u32 ledd_status; /* status of the LED display */ + struct model_data *methods; /* methods available on the laptop */ + u8 brightness; /* brightness level */ enum { - A1x = 0, //A1340D, A1300F - A2x, //A2500H - A4G, //A4700G - D1x, //D1 - L2D, //L2000D - L3C, //L3800C - L3D, //L3400D - L3H, //L3H, L2000E, L5D - L4R, //L4500R - L5x, //L5800C - L8L, //L8400L - M1A, //M1300A - M2E, //M2400E, L4400L - M6N, //M6800N, W3400N - M6R, //M6700R, A3000G - P30, //Samsung P30 - S1x, //S1300A, but also L1400B and M2400A (L84F) - S2x, //S200 (J1 reported), Victor MP-XP7210 - W1N, //W1000N - W5A, //W5A - W3V, //W3030V - xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N - A4S, //Z81sp - //(Centrino) - F3Sa, + A1x = 0, /* A1340D, A1300F */ + A2x, /* A2500H */ + A4G, /* A4700G */ + D1x, /* D1 */ + L2D, /* L2000D */ + L3C, /* L3800C */ + L3D, /* L3400D */ + L3H, /* L3H, L2000E, L5D */ + L4R, /* L4500R */ + L5x, /* L5800C */ + L8L, /* L8400L */ + M1A, /* M1300A */ + M2E, /* M2400E, L4400L */ + M6N, /* M6800N, W3400N */ + M6R, /* M6700R, A3000G */ + P30, /* Samsung P30 */ + S1x, /* S1300A, but also L1400B and M2400A (L84F) */ + S2x, /* S200 (J1 reported), Victor MP-XP7210 */ + W1N, /* W1000N */ + W5A, /* W5A */ + W3V, /* W3030V */ + xxN, /* M2400N, M3700N, M5200N, M6800N, + S1300N, S5200N*/ + A4S, /* Z81sp */ + F3Sa, /* (Centrino) */ END_MODEL - } model; //Models currently supported - u16 event_count[128]; //count for each event TODO make this better + } model; /* Models currently supported */ + u16 event_count[128]; /* Count for each event TODO make this better */ }; /* Here we go */ @@ -459,18 +459,18 @@ static struct acpi_driver asus_hotk_driver = { }, }; -/* +/* * This function evaluates an ACPI method, given an int as parameter, the * method is searched within the scope of the handle, can be NULL. The output * of the method is written is output, which can also be NULL * - * returns 1 if write is successful, 0 else. + * returns 1 if write is successful, 0 else. */ static int write_acpi_int(acpi_handle handle, const char *method, int val, struct acpi_buffer *output) { - struct acpi_object_list params; //list of input parameters (an int here) - union acpi_object in_obj; //the only param we use + struct acpi_object_list params; /* list of input parameters (int) */ + union acpi_object in_obj; /* the only param we use */ acpi_status status; params.count = 1; @@ -507,18 +507,18 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof, { int len = 0; int temp; - char buf[16]; //enough for all info + char buf[16]; /* enough for all info */ /* - * We use the easy way, we don't care of off and count, so we don't set eof - * to 1 + * We use the easy way, we don't care of off and count, + * so we don't set eof to 1 */ len += sprintf(page, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n"); len += sprintf(page + len, "Model reference : %s\n", hotk->methods->name); - /* - * The SFUN method probably allows the original driver to get the list - * of features supported by a given model. For now, 0x0100 or 0x0800 + /* + * The SFUN method probably allows the original driver to get the list + * of features supported by a given model. For now, 0x0100 or 0x0800 * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card. * The significance of others is yet to be found. */ @@ -528,7 +528,7 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof, /* * Another value for userspace: the ASYM method returns 0x02 for * battery low and 0x04 for battery critical, its readings tend to be - * more accurate than those provided by _BST. + * more accurate than those provided by _BST. * Note: since not all the laptops provide this method, errors are * silently ignored. */ @@ -579,7 +579,7 @@ static int read_led(const char *ledname, int ledmask) return (hotk->status & ledmask) ? 1 : 0; } -static int parse_arg(const char __user * buf, unsigned long count, int *val) +static int parse_arg(const char __user *buf, unsigned long count, int *val) { char s[32]; if (!count) @@ -596,7 +596,7 @@ static int parse_arg(const char __user * buf, unsigned long count, int *val) /* FIXME: kill extraneous args so it can be called independently */ static int -write_led(const char __user * buffer, unsigned long count, +write_led(const char __user *buffer, unsigned long count, char *ledname, int ledmask, int invert) { int rv, value; @@ -631,7 +631,7 @@ proc_read_mled(char *page, char **start, off_t off, int count, int *eof, } static int -proc_write_mled(struct file *file, const char __user * buffer, +proc_write_mled(struct file *file, const char __user *buffer, unsigned long count, void *data) { return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1); @@ -648,7 +648,7 @@ proc_read_ledd(char *page, char **start, off_t off, int count, int *eof, } static int -proc_write_ledd(struct file *file, const char __user * buffer, +proc_write_ledd(struct file *file, const char __user *buffer, unsigned long count, void *data) { int rv, value; @@ -677,7 +677,7 @@ proc_read_wled(char *page, char **start, off_t off, int count, int *eof, } static int -proc_write_wled(struct file *file, const char __user * buffer, +proc_write_wled(struct file *file, const char __user *buffer, unsigned long count, void *data) { return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0); @@ -694,10 +694,10 @@ proc_read_bluetooth(char *page, char **start, off_t off, int count, int *eof, } static int -proc_write_bluetooth(struct file *file, const char __user * buffer, +proc_write_bluetooth(struct file *file, const char __user *buffer, unsigned long count, void *data) { - /* Note: mt_bt_switch controls both internal Bluetooth adapter's + /* Note: mt_bt_switch controls both internal Bluetooth adapter's presence and its LED */ return write_led(buffer, count, hotk->methods->mt_bt_switch, BT_ON, 0); } @@ -714,7 +714,7 @@ proc_read_tled(char *page, char **start, off_t off, int count, int *eof, } static int -proc_write_tled(struct file *file, const char __user * buffer, +proc_write_tled(struct file *file, const char __user *buffer, unsigned long count, void *data) { return write_led(buffer, count, hotk->methods->mt_tled, TLED_ON, 0); @@ -734,7 +734,7 @@ static int get_lcd_state(void) input.count = 2; input.pointer = mt_params; - /* Note: the following values are partly guessed up, but + /* Note: the following values are partly guessed up, but otherwise they seem to work */ mt_params[0].type = ACPI_TYPE_INTEGER; mt_params[0].integer.value = 0x02; @@ -796,12 +796,13 @@ static int set_lcd_state(int value) acpi_evaluate_object(NULL, hotk->methods->mt_lcd_switch, NULL, NULL); - } else { /* L3H and the like have to be handled differently */ + } else { + /* L3H and the like must be handled differently */ if (!write_acpi_int (hotk->handle, hotk->methods->mt_lcd_switch, 0x07, NULL)) status = AE_ERROR; - /* L3H's AML executes EHK (0x07) upon Fn+F7 keypress, + /* L3H's AML executes EHK (0x07) upon Fn+F7 keypress, the exact behaviour is simulated here */ } if (ACPI_FAILURE(status)) @@ -819,7 +820,7 @@ proc_read_lcd(char *page, char **start, off_t off, int count, int *eof, } static int -proc_write_lcd(struct file *file, const char __user * buffer, +proc_write_lcd(struct file *file, const char __user *buffer, unsigned long count, void *data) { int rv, value; @@ -897,7 +898,7 @@ proc_read_brn(char *page, char **start, off_t off, int count, int *eof, } static int -proc_write_brn(struct file *file, const char __user * buffer, +proc_write_brn(struct file *file, const char __user *buffer, unsigned long count, void *data) { int rv, value; @@ -921,7 +922,7 @@ static void set_display(int value) } /* - * Now, *this* one could be more user-friendly, but so far, no-one has + * Now, *this* one could be more user-friendly, but so far, no-one has * complained. The significance of bits is the same as in proc_write_disp() */ static int @@ -933,18 +934,18 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof, if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value)) printk(KERN_WARNING "Asus ACPI: Error reading display status\n"); - value &= 0x07; /* needed for some models, shouldn't hurt others */ + value &= 0x07; /* needed for some models, shouldn't hurt others */ return sprintf(page, "%d\n", value); } /* - * Experimental support for display switching. As of now: 1 should activate - * the LCD output, 2 should do for CRT, and 4 for TV-Out. Any combination - * (bitwise) of these will suffice. I never actually tested 3 displays hooked up - * simultaneously, so be warned. See the acpi4asus README for more info. + * Experimental support for display switching. As of now: 1 should activate + * the LCD output, 2 should do for CRT, and 4 for TV-Out. Any combination + * (bitwise) of these will suffice. I never actually tested 3 displays hooked + * up simultaneously, so be warned. See the acpi4asus README for more info. */ static int -proc_write_disp(struct file *file, const char __user * buffer, +proc_write_disp(struct file *file, const char __user *buffer, unsigned long count, void *data) { int rv, value; @@ -957,12 +958,12 @@ proc_write_disp(struct file *file, const char __user * buffer, typedef int (proc_readfunc) (char *page, char **start, off_t off, int count, int *eof, void *data); -typedef int (proc_writefunc) (struct file * file, const char __user * buffer, +typedef int (proc_writefunc) (struct file *file, const char __user *buffer, unsigned long count, void *data); static int -asus_proc_add(char *name, proc_writefunc * writefunc, - proc_readfunc * readfunc, mode_t mode, +asus_proc_add(char *name, proc_writefunc *writefunc, + proc_readfunc *readfunc, mode_t mode, struct acpi_device *device) { struct proc_dir_entry *proc = @@ -1040,9 +1041,9 @@ static int asus_hotk_add_fs(struct acpi_device *device) &proc_read_bluetooth, mode, device); } - /* - * We need both read node and write method as LCD switch is also accessible - * from keyboard + /* + * We need both read node and write method as LCD switch is also + * accessible from the keyboard */ if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) { asus_proc_add(PROC_LCD, &proc_write_lcd, &proc_read_lcd, mode, @@ -1096,11 +1097,10 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) if (!hotk) return; - if ((event & ~((u32) BR_UP)) < 16) { + if ((event & ~((u32) BR_UP)) < 16) hotk->brightness = (event & ~((u32) BR_UP)); - } else if ((event & ~((u32) BR_DOWN)) < 16) { + else if ((event & ~((u32) BR_DOWN)) < 16) hotk->brightness = (event & ~((u32) BR_DOWN)); - } acpi_bus_generate_proc_event(hotk->device, event, hotk->event_count[event % 128]++); @@ -1186,8 +1186,8 @@ static int asus_hotk_get_info(void) acpi_status status; /* - * Get DSDT headers early enough to allow for differentiating between - * models, but late enough to allow acpi_bus_register_driver() to fail + * Get DSDT headers early enough to allow for differentiating between + * models, but late enough to allow acpi_bus_register_driver() to fail * before doing anything ACPI-specific. Should we encounter a machine, * which needs special handling (i.e. its hotkey device has a different * HID), this bit will be moved. A global variable asus_info contains @@ -1212,8 +1212,8 @@ static int asus_hotk_get_info(void) /* * Try to match the object returned by INIT to the specific model. - * Handle every possible object (or the lack of thereof) the DSDT - * writers might throw at us. When in trouble, we pass NULL to + * Handle every possible object (or the lack of thereof) the DSDT + * writers might throw at us. When in trouble, we pass NULL to * asus_model_match() and try something completely different. */ if (buffer.pointer) { @@ -1254,7 +1254,7 @@ static int asus_hotk_get_info(void) /* Sort of per-model blacklist */ if (strncmp(string, "L2B", 3) == 0) hotk->methods->lcd_status = NULL; - /* L2B is similar enough to L3C to use its settings, with this only + /* L2B is similar enough to L3C to use its settings, with this only exception */ else if (strncmp(string, "A3G", 3) == 0) hotk->methods->lcd_status = "\\BLFG"; @@ -1366,10 +1366,9 @@ static int asus_hotk_add(struct acpi_device *device) /* LED display is off by default */ hotk->ledd_status = 0xFFF; - end: - if (result) { +end: + if (result) kfree(hotk); - } return result; } @@ -1394,8 +1393,8 @@ static int asus_hotk_remove(struct acpi_device *device, int type) } static struct backlight_ops asus_backlight_data = { - .get_brightness = read_brightness, - .update_status = set_brightness_status, + .get_brightness = read_brightness, + .update_status = set_brightness_status, }; static void asus_acpi_exit(void) @@ -1442,15 +1441,15 @@ static int __init asus_acpi_init(void) return -ENODEV; } - asus_backlight_device = backlight_device_register("asus",NULL,NULL, + asus_backlight_device = backlight_device_register("asus", NULL, NULL, &asus_backlight_data); - if (IS_ERR(asus_backlight_device)) { + if (IS_ERR(asus_backlight_device)) { printk(KERN_ERR "Could not register asus backlight device\n"); asus_backlight_device = NULL; asus_acpi_exit(); return -ENODEV; } - asus_backlight_device->props.max_brightness = 15; + asus_backlight_device->props.max_brightness = 15; return 0; } -- cgit v1.2.3 From 8fd145917fb62368a9b80db59562c20576238f5a Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 17 Oct 2008 14:22:27 -0400 Subject: ACPI: Ingore the RESET_REG_SUP bit when using ACPI reset mechanism According to ACPI 3.0, FADT.flags.RESET_REG_SUP indicates whether the ACPI reboot mechanism is supported. However, some boxes have this bit clear, have a valid ACPI_RESET_REG & RESET_VALUE, and ACPI reboot is the only mechanism that works for them after S3. This suggests that other operating systems may not be checking the RESET_REG_SUP bit, and are using other means to decide whether to use the ACPI reboot mechanism or not. Here we stop checking RESET_REG_SUP. Instead, When acpi reboot is requested, only the reset_register is checked. If the following conditions are met, it indicates that the reset register is supported. a. reset_register is not zero b. the access width is eight c. the bit_offset is zero http://bugzilla.kernel.org/show_bug.cgi?id=7299 http://bugzilla.kernel.org/show_bug.cgi?id=1148 Signed-off-by: Zhao Yakui Signed-off-by: Len Brown --- drivers/acpi/reboot.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c index a6b662c00b67..755baf2ca70a 100644 --- a/drivers/acpi/reboot.c +++ b/drivers/acpi/reboot.c @@ -15,9 +15,28 @@ void acpi_reboot(void) rr = &acpi_gbl_FADT.reset_register; - /* Is the reset register supported? */ - if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) || - rr->bit_width != 8 || rr->bit_offset != 0) + /* + * Is the ACPI reset register supported? + * + * According to ACPI 3.0, FADT.flags.RESET_REG_SUP indicates + * whether the ACPI reset mechanism is supported. + * + * However, some boxes have this bit clear, yet a valid + * ACPI_RESET_REG & RESET_VALUE, and ACPI reboot is the only + * mechanism that works for them after S3. + * + * This suggests that other operating systems may not be checking + * the RESET_REG_SUP bit, and are using other means to decide + * whether to use the ACPI reboot mechanism or not. + * + * So when acpi reboot is requested, + * only the reset_register is checked. If the following + * conditions are met, it indicates that the reset register is supported. + * a. reset_register is not zero + * b. the access width is eight + * c. the bit_offset is zero + */ + if (!(rr->address) || rr->bit_width != 8 || rr->bit_offset != 0) return; reset_value = acpi_gbl_FADT.reset_value; -- cgit v1.2.3 From ab527d75787c16114bcf2bc1b98bef18c67bb57c Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 18 Oct 2008 20:28:39 -0700 Subject: acpi: use bcd2bin/bin2bcd Change ACPI to use the new bcd2bin/bin2bcd functions instead of the obsolete BCD_TO_BIN/BIN_TO_BCD macros. Signed-off-by: Adrian Bunk Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/sleep/proc.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index bf5b04de02d1..631ee2ee2ca0 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c @@ -120,13 +120,13 @@ static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset) spin_unlock_irqrestore(&rtc_lock, flags); if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hr); - BCD_TO_BIN(day); - BCD_TO_BIN(mo); - BCD_TO_BIN(yr); - BCD_TO_BIN(cent); + sec = bcd2bin(sec); + min = bcd2bin(min); + hr = bcd2bin(hr); + day = bcd2bin(day); + mo = bcd2bin(mo); + yr = bcd2bin(yr); + cent = bcd2bin(cent); } /* we're trusting the FADT (see above) */ @@ -204,7 +204,7 @@ static u32 cmos_bcd_read(int offset, int rtc_control) { u32 val = CMOS_READ(offset); if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - BCD_TO_BIN(val); + val = bcd2bin(val); return val; } @@ -212,7 +212,7 @@ static u32 cmos_bcd_read(int offset, int rtc_control) static void cmos_bcd_write(u32 val, int offset, int rtc_control) { if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - BIN_TO_BCD(val); + val = bin2bcd(val); CMOS_WRITE(val, offset); } -- cgit v1.2.3 From 01e8ef11bc1a74e65678ed55795f59266d4add01 Mon Sep 17 00:00:00 2001 From: Parag Warudkar Date: Sat, 18 Oct 2008 20:28:50 -0700 Subject: x86: sysfs: kill owner field from attribute Tejun's commit 7b595756ec1f49e0049a9e01a1298d53a7faaa15 made sysfs attribute->owner unnecessary. But the field was left in the structure to ease the merge. It's been over a year since that change and it is now time to start killing attribute->owner along with its users - one arch at a time! This patch is attempt #1 to get rid of attribute->owner only for CONFIG_X86_64 or CONFIG_X86_32 . We will deal with other arches later on as and when possible - avr32 will be the next since that is something I can test. Compile (make allyesconfig / make allmodconfig / custom config) and boot tested. akpm: the idea is that we put the declaration of sttribute.owner inside `#ifndef CONFIG_X86'. But that proved to be too ambitious for now because new usages kept on turning up in subsystem trees. [akpm: remove the ifdef for now] Signed-off-by: Parag Warudkar Cc: Greg KH Cc: Ingo Molnar Cc: Tejun Heo Cc: Len Brown Cc: Jens Axboe Cc: Jean Delvare Cc: Roland Dreier Cc: David Brownell Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/battery.c | 2 +- drivers/acpi/sbs.c | 2 +- drivers/acpi/system.c | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index b1c723f9f58d..70f7f60929ca 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -431,7 +431,7 @@ static ssize_t acpi_battery_alarm_store(struct device *dev, } static struct device_attribute alarm_attr = { - .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE}, + .attr = {.name = "alarm", .mode = 0644}, .show = acpi_battery_alarm_show, .store = acpi_battery_alarm_store, }; diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 10a36512647c..7b011e7e29fe 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -463,7 +463,7 @@ static ssize_t acpi_battery_alarm_store(struct device *dev, } static struct device_attribute alarm_attr = { - .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE}, + .attr = {.name = "alarm", .mode = 0644}, .show = acpi_battery_alarm_show, .store = acpi_battery_alarm_store, }; diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 91dec448b3ed..24e80fd927e2 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -115,7 +115,6 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr, table_attr->attr.read = acpi_table_show; table_attr->attr.attr.name = table_attr->name; table_attr->attr.attr.mode = 0444; - table_attr->attr.attr.owner = THIS_MODULE; return; } -- cgit v1.2.3 From 5d1e072b6b9cffebefa681faca1c6d608310d4b2 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 22 Oct 2008 14:58:43 -0400 Subject: ACPI suspend: Fix CONFIG_ACPI_SLEEP dependence and some compilation warnings Initially CONFIG_PM_SLEEP was defined as CONFIG_SUSPEND || CONFIG_HIBERNATION and some ACPI code, most importantly the code in drivers/acpi/main.c, was written with this assumption. Currently, however, CONFIG_PM_SLEEP is also set when CONFIG_XEN_SAVE_RESTORE is set. This causes some compilation warnings to appear in drivers/acpi/main.c if both CONFIG_SUSPEND and CONFIG_HIBERNATION are unset and CONFIG_PM_SLEEP is set (this was impossible before). To fix this problem, redefine CONFIG_ACPI_SLEEP do depend directly on CONFIG_SUSPEND || CONFIG_HIBERNATION, as originally intended, and use it instead of CONFIG_PM_SLEEP in drivers/acpi/main.c, wherever appropriate. Additionally, move the acpi_target_sleep_state definition from under the #ifdef to prevent compilation from failing in some cases. Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 2 +- drivers/acpi/sleep/main.c | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 79540db29808..325b4b5fa7df 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -42,7 +42,7 @@ if ACPI config ACPI_SLEEP bool - depends on PM_SLEEP + depends on SUSPEND || HIBERNATION default y config ACPI_PROCFS diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index d13194a031bf..4c21480b5820 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -23,6 +23,7 @@ #include "sleep.h" u8 sleep_states[ACPI_S_STATE_COUNT]; +static u32 acpi_target_sleep_state = ACPI_STATE_S0; static int acpi_sleep_prepare(u32 acpi_state) { @@ -45,9 +46,7 @@ static int acpi_sleep_prepare(u32 acpi_state) return 0; } -#ifdef CONFIG_PM_SLEEP -static u32 acpi_target_sleep_state = ACPI_STATE_S0; - +#ifdef CONFIG_ACPI_SLEEP /* * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the * user to request that behavior by using the 'acpi_old_suspend_ordering' @@ -132,7 +131,7 @@ static void acpi_pm_end(void) */ acpi_target_sleep_state = ACPI_STATE_S0; } -#endif /* CONFIG_PM_SLEEP */ +#endif /* CONFIG_ACPI_SLEEP */ #ifdef CONFIG_SUSPEND extern void do_suspend_lowlevel(void); -- cgit v1.2.3 From 08237974af22a97da59869979ef1a515524d5cc3 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Fri, 8 Aug 2008 11:57:11 +0800 Subject: ACPI: replace AE_BAD_ADDRESS exception code with AE_ERROR The AE_BAD_ADDRESS exception code is now unused in ACPICA. For linux, it's only used at wmi.c and acer-wmi.c. I checked both wmi.c and acer-wmi.c, the AE_BAD_ADDRESS exception code has no special meaning. The parent functions just call AE_SUCCESS() or AE_FAILURE() to check the return status. So it's safe to replace AE_BAD_ADDRESS with AE_ERROR. Signed-off-by Lin Ming Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/wmi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/wmi.c b/drivers/acpi/wmi.c index cfe2c833474d..5b94be38861f 100644 --- a/drivers/acpi/wmi.c +++ b/drivers/acpi/wmi.c @@ -242,7 +242,7 @@ u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out) char method[4] = "WM"; if (!find_guid(guid_string, &wblock)) - return AE_BAD_ADDRESS; + return AE_ERROR; block = &wblock->gblock; handle = wblock->handle; @@ -304,7 +304,7 @@ struct acpi_buffer *out) return AE_BAD_PARAMETER; if (!find_guid(guid_string, &wblock)) - return AE_BAD_ADDRESS; + return AE_ERROR; block = &wblock->gblock; handle = wblock->handle; @@ -314,7 +314,7 @@ struct acpi_buffer *out) /* Check GUID is a data block */ if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD)) - return AE_BAD_ADDRESS; + return AE_ERROR; input.count = 1; input.pointer = wq_params; @@ -385,7 +385,7 @@ const struct acpi_buffer *in) return AE_BAD_DATA; if (!find_guid(guid_string, &wblock)) - return AE_BAD_ADDRESS; + return AE_ERROR; block = &wblock->gblock; handle = wblock->handle; @@ -395,7 +395,7 @@ const struct acpi_buffer *in) /* Check GUID is a data block */ if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD)) - return AE_BAD_ADDRESS; + return AE_ERROR; input.count = 2; input.pointer = params; -- cgit v1.2.3 From a51e145f379ae48003129610922595893e8efde0 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 11 Aug 2008 14:55:05 +0800 Subject: ACPI: Get the device power state in the course of scanning device Get the device power state in the course of scanning device if the device power flag is power_managable. i.e. The device has the _PSx/_PRx object. At the same time before the drivers/acpi/power module is loaded, there is no relation between acpi_power_resource and acpi device. So the first parameter of acpi_power_get_state is changed to acpi_handle. http://bugzilla.kernel.org/show_bug.cgi?id=8049 http://bugzilla.kernel.org/show_bug.cgi?id=11000 Signed-off-by: Zhao Yakui Signed-off-by: Li Shaohua Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/power.c | 30 ++++++++++++++++-------------- drivers/acpi/scan.c | 1 + 2 files changed, 17 insertions(+), 14 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 4ab21cb1c8c7..e7bab75075a9 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -128,16 +128,16 @@ acpi_power_get_context(acpi_handle handle, return 0; } -static int acpi_power_get_state(struct acpi_power_resource *resource, int *state) +static int acpi_power_get_state(acpi_handle handle, int *state) { acpi_status status = AE_OK; unsigned long sta = 0; - if (!resource || !state) + if (!handle || !state) return -EINVAL; - status = acpi_evaluate_integer(resource->device->handle, "_STA", NULL, &sta); + status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); if (ACPI_FAILURE(status)) return -ENODEV; @@ -145,7 +145,7 @@ static int acpi_power_get_state(struct acpi_power_resource *resource, int *state ACPI_POWER_RESOURCE_STATE_OFF; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", - resource->name, state ? "on" : "off")); + acpi_ut_get_node_name(handle), state ? "on" : "off")); return 0; } @@ -153,7 +153,6 @@ static int acpi_power_get_state(struct acpi_power_resource *resource, int *state static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) { int result = 0, state1; - struct acpi_power_resource *resource = NULL; u32 i = 0; @@ -161,12 +160,15 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) return -EINVAL; /* The state of the list is 'on' IFF all resources are 'on'. */ + /* */ for (i = 0; i < list->count; i++) { - result = acpi_power_get_context(list->handles[i], &resource); - if (result) - return result; - result = acpi_power_get_state(resource, &state1); + /* + * The state of the power resource can be obtained by + * using the ACPI handle. In such case it is unnecessary to + * get the Power resource first and then get its state again. + */ + result = acpi_power_get_state(list->handles[i], &state1); if (result) return result; @@ -226,7 +228,7 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) if (ACPI_FAILURE(status)) return -ENODEV; - result = acpi_power_get_state(resource, &state); + result = acpi_power_get_state(resource->device->handle, &state); if (result) return result; if (state != ACPI_POWER_RESOURCE_STATE_ON) @@ -277,7 +279,7 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) if (ACPI_FAILURE(status)) return -ENODEV; - result = acpi_power_get_state(resource, &state); + result = acpi_power_get_state(handle, &state); if (result) return result; if (state != ACPI_POWER_RESOURCE_STATE_OFF) @@ -555,7 +557,7 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset) if (!resource) goto end; - result = acpi_power_get_state(resource, &state); + result = acpi_power_get_state(resource->device->handle, &state); if (result) goto end; @@ -668,7 +670,7 @@ static int acpi_power_add(struct acpi_device *device) resource->system_level = acpi_object.power_resource.system_level; resource->order = acpi_object.power_resource.resource_order; - result = acpi_power_get_state(resource, &state); + result = acpi_power_get_state(device->handle, &state); if (result) goto end; @@ -735,7 +737,7 @@ static int acpi_power_resume(struct acpi_device *device) resource = (struct acpi_power_resource *)acpi_driver_data(device); - result = acpi_power_get_state(resource, &state); + result = acpi_power_get_state(device->handle, &state); if (result) return result; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f6f52c1a2aba..308ddb1c207c 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -807,6 +807,7 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) /* TBD: System wake support and resource requirements. */ device->power.state = ACPI_STATE_UNKNOWN; + acpi_bus_get_power(device->handle, &(device->power.state)); return 0; } -- cgit v1.2.3 From eab4b645769fa2f8703f5a3cb0cc4ac090d347af Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 11 Aug 2008 14:54:16 +0800 Subject: ACPI: Attach the ACPI device to the ACPI handle as early as possible Attach the ACPI device to the ACPI handle as early as possible so that OS can get the corresponding ACPI device by the acpi handle in the course of getting the power/wakeup/performance flags. http://bugzilla.kernel.org/show_bug.cgi?id=8049 http://bugzilla.kernel.org/show_bug.cgi?id=11000 Signed-off-by: Zhao Yakui Signed-off-by: Zhang Rui Signed-off-by: Andi Kleen 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 308ddb1c207c..ad0679843bd5 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1252,6 +1252,16 @@ acpi_add_single_object(struct acpi_device **child, */ acpi_device_set_id(device, parent, handle, type); + /* + * The ACPI device is attached to acpi handle before getting + * the power/wakeup/peformance flags. Otherwise OS can't get + * the corresponding ACPI device by the acpi handle in the course + * of getting the power/wakeup/performance flags. + */ + result = acpi_device_set_context(device, type); + if (result) + goto end; + /* * Power Management * ---------------- @@ -1282,8 +1292,6 @@ acpi_add_single_object(struct acpi_device **child, goto end; } - if ((result = acpi_device_set_context(device, type))) - goto end; result = acpi_device_register(device, parent); -- cgit v1.2.3 From f5adfaa372c76423b6e8e4727a9701330374f364 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 11 Aug 2008 14:57:50 +0800 Subject: ACPI: Add "acpi.power_nocheck=1" to disable power state check in power transition Maybe the incorrect power state is returned on the bogus bios, which is different with the real power state. For example: the bios returns D0 state and the real power state is D3. OS expects to set the device to D0 state. In such case if OS uses the power state returned by the BIOS and checks the device power state very strictly in power transition, the device can't be transited to the correct power state. So the boot option of "acpi.power_nocheck=1" is added to avoid checking the device power in the course of device power transition. http://bugzilla.kernel.org/show_bug.cgi?id=8049 http://bugzilla.kernel.org/show_bug.cgi?id=11000 Signed-off-by: Zhao Yakui Signed-off-by: Zhang Rui Signed-off-by: Li Shaohua Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/bus.c | 14 +++++++++++++- drivers/acpi/power.c | 42 +++++++++++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 12 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index ccae305ee55d..91bdeb3b081e 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -223,7 +223,19 @@ int acpi_bus_set_power(acpi_handle handle, int state) /* * Get device's current power state */ - acpi_bus_get_power(device->handle, &device->power.state); + if (!acpi_power_nocheck) { + /* + * Maybe the incorrect power state is returned on the bogus + * bios, which is different with the real power state. + * For example: the bios returns D0 state and the real power + * state is D3. OS expects to set the device to D0 state. In + * such case if OS uses the power state returned by the BIOS, + * the device can't be transisted to the correct power state. + * So if the acpi_power_nocheck is set, it is unnecessary to + * get the power state by calling acpi_bus_get_power. + */ + acpi_bus_get_power(device->handle, &device->power.state); + } if ((state == device->power.state) && !device->flags.force_power_state) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", state)); diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index e7bab75075a9..7ff7349c0c52 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -54,6 +54,14 @@ ACPI_MODULE_NAME("power"); #define ACPI_POWER_RESOURCE_STATE_OFF 0x00 #define ACPI_POWER_RESOURCE_STATE_ON 0x01 #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF + +#ifdef MODULE_PARAM_PREFIX +#undef MODULE_PARAM_PREFIX +#endif +#define MODULE_PARAM_PREFIX "acpi." +int acpi_power_nocheck; +module_param_named(power_nocheck, acpi_power_nocheck, bool, 000); + static int acpi_power_add(struct acpi_device *device); static int acpi_power_remove(struct acpi_device *device, int type); static int acpi_power_resume(struct acpi_device *device); @@ -228,12 +236,18 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) if (ACPI_FAILURE(status)) return -ENODEV; - result = acpi_power_get_state(resource->device->handle, &state); - if (result) - return result; - if (state != ACPI_POWER_RESOURCE_STATE_ON) - return -ENOEXEC; - + if (!acpi_power_nocheck) { + /* + * If acpi_power_nocheck is set, it is unnecessary to check + * the power state after power transition. + */ + result = acpi_power_get_state(resource->device->handle, + &state); + if (result) + return result; + if (state != ACPI_POWER_RESOURCE_STATE_ON) + return -ENOEXEC; + } /* Update the power resource's _device_ power state */ resource->device->power.state = ACPI_STATE_D0; @@ -279,11 +293,17 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) if (ACPI_FAILURE(status)) return -ENODEV; - result = acpi_power_get_state(handle, &state); - if (result) - return result; - if (state != ACPI_POWER_RESOURCE_STATE_OFF) - return -ENOEXEC; + if (!acpi_power_nocheck) { + /* + * If acpi_power_nocheck is set, it is unnecessary to check + * the power state after power transition. + */ + result = acpi_power_get_state(handle, &state); + if (result) + return result; + if (state != ACPI_POWER_RESOURCE_STATE_OFF) + return -ENOEXEC; + } /* Update the power resource's _device_ power state */ resource->device->power.state = ACPI_STATE_D3; -- cgit v1.2.3 From 6415e12ba0f92a54f02d9c4ecaa3c82f35f3d335 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 11 Aug 2008 14:59:59 +0800 Subject: ACPI: Add DMI check to disable power state check in power transition Add the DMI check to disable power check in the course of device power transistion. http://bugzilla.kernel.org/show_bug.cgi?id=11000 Signed-off-by: Zhao Yakui Signed-off-by: Li Shaohua Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/bus.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 91bdeb3b081e..945cd2f2807d 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -48,6 +48,23 @@ EXPORT_SYMBOL(acpi_root_dir); #define STRUCT_TO_INT(s) (*((int*)&s)) +static int set_power_nocheck(const struct dmi_system_id *id) +{ + printk(KERN_NOTICE PREFIX "%s detected - " + "disable power check in power transistion\n", id->ident); + acpi_power_nocheck = 1; + return 0; +} +static struct dmi_system_id __cpuinitdata power_nocheck_dmi_table[] = { + { + set_power_nocheck, "HP Pavilion 05", { + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), + DMI_MATCH(DMI_SYS_VENDOR, "HP Pavilion 05"), + DMI_MATCH(DMI_PRODUCT_VERSION, "2001211RE101GLEND") }, NULL}, + {}, +}; + + /* -------------------------------------------------------------------------- Device Management -------------------------------------------------------------------------- */ @@ -830,7 +847,11 @@ static int __init acpi_init(void) } } else disable_acpi(); - + /* + * If the laptop falls into the DMI check table, the power state check + * will be disabled in the course of device power transistion. + */ + dmi_check_system(power_nocheck_dmi_table); return result; } -- cgit v1.2.3 From 39a0ad871000d2a016a4fa113a6e53d22aabf25d Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 11 Aug 2008 13:40:22 +0800 Subject: ACPI : Load device driver according to the status of acpi device According to ACPI spec when the status of some device is not present but functional, the device is valid and the children of this device should be enumerated. It means that the device should be added to linux acpi device tree. But the device driver for this device should not be loaded. The detailed info can be found in the section 6.3.7 of ACPI 3.0b spec. _STA may return bit 0 clear (not present) with bit 3 set (device is functional). This case is used to indicate a valid device for which no device driver should be loaded (for example, a bridge device.). Children of this device may be present and valid. OS should continue enumeration below a device whose _STA returns this bit combination http://bugzilla.kernel.org/show_bug.cgi?id=3358 Signed-off-by: Zhao Yakui Signed-off-by: Li Shaohua Signed-off-by: Zhang Rui Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/bus.c | 16 ++++++++-------- drivers/acpi/scan.c | 35 +++++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 18 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 945cd2f2807d..e9b116d2b56d 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -112,21 +112,21 @@ int acpi_bus_get_status(struct acpi_device *device) } /* - * Otherwise we assume the status of our parent (unless we don't - * have one, in which case status is implied). + * According to ACPI spec some device can be present and functional + * even if the parent is not present but functional. + * In such conditions the child device should not inherit the status + * from the parent. */ - else if (device->parent) - device->status = device->parent->status; else STRUCT_TO_INT(device->status) = ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING; if (device->status.functional && !device->status.present) { - printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: " - "functional but not present; setting present\n", - device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status)); - device->status.present = 1; + 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))); } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n", diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index ad0679843bd5..89c112ef9e14 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -276,6 +276,13 @@ int acpi_match_device_ids(struct acpi_device *device, { const struct acpi_device_id *id; + /* + * If the device is not present, it is unnecessary to load device + * driver for it. + */ + if (!device->status.present) + return -ENODEV; + if (device->flags.hardware_id) { for (id = ids; id->id[0]; id++) { if (!strcmp((char*)id->id, device->pnp.hardware_id)) @@ -1222,15 +1229,18 @@ acpi_add_single_object(struct acpi_device **child, result = -ENODEV; goto end; } - if (!device->status.present) { - /* Bay and dock should be handled even if absent */ - if (!ACPI_SUCCESS( - acpi_is_child_device(device, acpi_bay_match)) && - !ACPI_SUCCESS( - acpi_is_child_device(device, acpi_dock_match))) { - result = -ENODEV; - goto end; - } + /* + * When the device is neither present nor functional, the + * device should not be added to Linux ACPI device tree. + * When the status of the device is not present but functinal, + * it should be added to Linux ACPI tree. For example : bay + * device , dock device. + * In such conditions it is unncessary to check whether it is + * bay device or dock device. + */ + if (!device->status.present && !device->status.functional) { + result = -ENODEV; + goto end; } break; default: @@ -1411,7 +1421,12 @@ static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops) * TBD: Need notifications and other detection mechanisms * in place before we can fully implement this. */ - if (child->status.present) { + /* + * When the device is not present but functional, it is also + * necessary to scan the children of this device. + */ + if (child->status.present || (!child->status.present && + child->status.functional)) { status = acpi_get_next_object(ACPI_TYPE_ANY, chandle, NULL, NULL); if (ACPI_SUCCESS(status)) { -- cgit v1.2.3 From ea5c8af9b1241a10dc4ba6cd2d2362c179884b74 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 11 Oct 2008 01:13:12 -0400 Subject: ACPI: remove unused acpi_is_child_device() Signed-off-by: Len Brown --- drivers/acpi/scan.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 89c112ef9e14..91fed422bae8 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1160,20 +1160,6 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) return 0; } -static int -acpi_is_child_device(struct acpi_device *device, - int (*matcher)(struct acpi_device *)) -{ - int result = -ENODEV; - - do { - if (ACPI_SUCCESS(matcher(device))) - return AE_OK; - } while ((device = device->parent)); - - return result; -} - static int acpi_add_single_object(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type, -- cgit v1.2.3 From 383d7a11c9989205db44c7f1be339e5097062f03 Mon Sep 17 00:00:00 2001 From: "donald.d.dugger@intel.com" Date: Fri, 17 Oct 2008 07:49:50 -0700 Subject: ACPI: Fix possible null ptr dereference Code in `pci_link.c' is calling the internal routine `acpi_ut_evaluate_object' which is dangerous given that it is passing a NULL pointer when it should be passing a pointer to a real object. The patch corrects the issue by having the code call the external routine `acpi_evaluate_object', which correctly handles a NULL pointer. Signed-off-by: Don Dugger Signed-off-by: Len Brown --- drivers/acpi/pci_link.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index cf47805a7448..65bf4fa59633 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -709,7 +709,7 @@ int acpi_pci_link_free_irq(acpi_handle handle) acpi_device_bid(link->device))); if (link->refcnt == 0) { - acpi_ut_evaluate_object(link->device->handle, "_DIS", 0, NULL); + acpi_evaluate_object(link->device->handle, "_DIS", NULL, NULL); } mutex_unlock(&acpi_link_lock); return (link->irq.active); @@ -773,7 +773,7 @@ static int acpi_pci_link_add(struct acpi_device *device) end: /* disable all links -- to be activated on use */ - acpi_ut_evaluate_object(device->handle, "_DIS", 0, NULL); + acpi_evaluate_object(device->handle, "_DIS", NULL, NULL); mutex_unlock(&acpi_link_lock); if (result) -- cgit v1.2.3 From 828f37683e6d3ab5912989df0d04201db7ad798e Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Mon, 20 Oct 2008 17:40:52 -0600 Subject: PCI: update pci_create_slot() to take a 'hotplug' param Slot detection drivers can co-exist with hotplug drivers. The names of the detected/claimed slots may be different depending on module load order. For legacy reasons, we need to allow hotplug drivers to override the slot name if a detection driver is loaded first (and they find the same slots). Creating and overriding slot names should be an atomic operation, otherwise you get a locking nightmare as various drivers race to call pci_create_slot(). pci_create_slot() is already serialized by grabbing the pci_bus_sem. We update the API and add a 'hotplug' param, which is: set if the caller is a hotplug driver NULL if the caller is a detection driver pci_create_slot() does not actually use the 'hotplug' parameter in this patch. A later patch will add the logic that uses it. Cc: kristen.c.accardi@intel.com Cc: matthew@wil.cx Acked-by: Kenji Kaneshige Signed-off-by: Alex Chiang Signed-off-by: Jesse Barnes --- drivers/acpi/pci_slot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c index d5b4ef898879..8d4a568be1cc 100644 --- a/drivers/acpi/pci_slot.c +++ b/drivers/acpi/pci_slot.c @@ -150,7 +150,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) } snprintf(name, sizeof(name), "%u", (u32)sun); - pci_slot = pci_create_slot(pci_bus, device, name); + pci_slot = pci_create_slot(pci_bus, device, name, NULL); if (IS_ERR(pci_slot)) { err("pci_create_slot returned %ld\n", PTR_ERR(pci_slot)); kfree(slot); -- cgit v1.2.3 From f0e0da8a6cca44396c7a711e308d58084e881617 Mon Sep 17 00:00:00 2001 From: Dennis Noordsij Date: Fri, 15 Aug 2008 09:37:58 +0800 Subject: ACPICA: Copy dynamically loaded tables to local buffer Previously, dynamically loaded tables were simply mapped, but on some machines this memory is corrupted after suspend. Now copy the table to a local buffer. For OpRegion case, added checksum verify. Use the table length from the table header, not the region length. For Buffer case, use the table length also. http://bugzilla.kernel.org/show_bug.cgi?id=10734 Signed-off-by: Dennis Noordsij Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/executer/exconfig.c | 113 ++++++++++++++++++++++++++++----------- 1 file changed, 82 insertions(+), 31 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 8892b9824fae..331a114f42c9 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -280,6 +280,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, struct acpi_walk_state *walk_state) { union acpi_operand_object *ddb_handle; + struct acpi_table_header *table; struct acpi_table_desc table_desc; u32 table_index; acpi_status status; @@ -294,9 +295,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_REGION: - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", - obj_desc, - acpi_ut_get_object_type_name(obj_desc))); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Load table from Region %p\n", obj_desc)); /* Region must be system_memory (from ACPI spec) */ @@ -316,61 +316,112 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, } /* - * We will simply map the memory region for the table. However, the - * memory region is technically not guaranteed to remain stable and - * we may eventually have to copy the table to a local buffer. + * Map the table header and get the actual table length. The region + * length is not guaranteed to be the same as the table length. + */ + table = acpi_os_map_memory(obj_desc->region.address, + sizeof(struct acpi_table_header)); + if (!table) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + length = table->length; + acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); + + /* Must have at least an ACPI table header */ + + if (length < sizeof(struct acpi_table_header)) { + return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); + } + + /* + * The memory region is not guaranteed to remain stable and we must + * copy the table to a local buffer. For example, the memory region + * is corrupted after suspend on some machines. Dynamically loaded + * tables are usually small, so this overhead is minimal. */ + + /* Allocate a buffer for the table */ + + table_desc.pointer = ACPI_ALLOCATE(length); + if (!table_desc.pointer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Map the entire table and copy it */ + + table = acpi_os_map_memory(obj_desc->region.address, length); + if (!table) { + ACPI_FREE(table_desc.pointer); + return_ACPI_STATUS(AE_NO_MEMORY); + } + + ACPI_MEMCPY(table_desc.pointer, table, length); + acpi_os_unmap_memory(table, length); + table_desc.address = obj_desc->region.address; - table_desc.length = obj_desc->region.length; - table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED; break; case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Load from Buffer or Field %p %s\n", obj_desc, - acpi_ut_get_object_type_name(obj_desc))); - - length = obj_desc->buffer.length; + "Load table from Buffer or Field %p\n", + obj_desc)); /* Must have at least an ACPI table header */ - if (length < sizeof(struct acpi_table_header)) { + if (obj_desc->buffer.length < sizeof(struct acpi_table_header)) { return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); } - /* Validate checksum here. It won't get validated in tb_add_table */ + /* Get the actual table length from the table header */ - status = - acpi_tb_verify_checksum(ACPI_CAST_PTR - (struct acpi_table_header, - obj_desc->buffer.pointer), length); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + table = + ACPI_CAST_PTR(struct acpi_table_header, + obj_desc->buffer.pointer); + length = table->length; + + /* Table cannot extend beyond the buffer */ + + if (length > obj_desc->buffer.length) { + return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); + } + if (length < sizeof(struct acpi_table_header)) { + return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); } /* - * We need to copy the buffer since the original buffer could be - * changed or deleted in the future + * Copy the table from the buffer because the buffer could be modified + * or even deleted in the future */ table_desc.pointer = ACPI_ALLOCATE(length); if (!table_desc.pointer) { return_ACPI_STATUS(AE_NO_MEMORY); } - ACPI_MEMCPY(table_desc.pointer, obj_desc->buffer.pointer, - length); - table_desc.length = length; - table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; + ACPI_MEMCPY(table_desc.pointer, table, length); + table_desc.address = ACPI_TO_INTEGER(table_desc.pointer); break; default: return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } - /* - * Install the new table into the local data structures - */ + /* Validate table checksum (will not get validated in tb_add_table) */ + + status = acpi_tb_verify_checksum(table_desc.pointer, length); + if (ACPI_FAILURE(status)) { + ACPI_FREE(table_desc.pointer); + return_ACPI_STATUS(status); + } + + /* Complete the table descriptor */ + + table_desc.length = length; + table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; + + /* Install the new table into the local data structures */ + status = acpi_tb_add_table(&table_desc, &table_index); if (ACPI_FAILURE(status)) { goto cleanup; @@ -379,7 +430,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* * Add the table to the namespace. * - * Note: We load the table objects relative to the root of the namespace. + * Note: Load the table objects relative to the root of the namespace. * This appears to go against the ACPI specification, but we do it for * compatibility with other ACPI implementations. */ @@ -415,7 +466,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, cleanup: if (ACPI_FAILURE(status)) { - /* Delete allocated buffer or mapping */ + /* Delete allocated table buffer */ acpi_tb_delete_table(&table_desc); } -- cgit v1.2.3 From 237a927682a63f02adb542dbdaafe8a81566451d Mon Sep 17 00:00:00 2001 From: Fiodor Suietov Date: Fri, 4 Jul 2008 10:18:34 +0800 Subject: ACPICA: Add check for invalid handle in acpi_get_object_info Return AE_BAD_PARAMETER if input handle is invalid. http://www.acpica.org/bugzilla/show_bug.cgi?id=474 Signed-off-by: Fiodor Suietov Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/namespace/nsxfname.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c index a287ed550f54..3cb910ded44a 100644 --- a/drivers/acpi/namespace/nsxfname.c +++ b/drivers/acpi/namespace/nsxfname.c @@ -253,6 +253,7 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) node = acpi_ns_map_handle_to_node(handle); if (!node) { (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + status = AE_BAD_PARAMETER; goto cleanup; } -- cgit v1.2.3 From e56f561736e340a4e923b0db65f65dabf5d94823 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 4 Jul 2008 10:48:43 +0800 Subject: ACPICA: Allow same ACPI table to be loaded/unloaded more than once Without this change, a table cannot be loaded again once it has been loaded/unloaded one time. The current mechanism does not unregister a table upon an unload. During a load, if the same table is found, this no longer returns an exception. http://www.acpica.org/bugzilla/show_bug.cgi?id=722 Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/tables/tbinstal.c | 49 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 7 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index b22185f55a16..905dc38ab23b 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -145,6 +145,8 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) } } + /* Check for a table match on the entire table length */ + length = ACPI_MIN(table_desc->length, acpi_gbl_root_table_list.tables[i].length); if (ACPI_MEMCMP(table_desc->pointer, @@ -153,17 +155,49 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) continue; } - /* Table is already registered */ - + /* + * Note: the current mechanism does not unregister a table if it is + * dynamically unloaded. The related namespace entries are deleted, + * but the table remains in the root table list. + * + * The assumption here is that the number of different tables that + * will be loaded is actually small, and there is minimal overhead + * in just keeping the table in case it is needed again. + * + * If this assumption changes in the future (perhaps on large + * machines with many table load/unload operations), tables will + * need to be unregistered when they are unloaded, and slots in the + * root table list should be reused when empty. + */ + + /* + * Table is already registered. + * We can delete the table that was passed as a parameter. + */ acpi_tb_delete_table(table_desc); *table_index = i; - status = AE_ALREADY_EXISTS; - goto release; + + if (acpi_gbl_root_table_list.tables[i]. + flags & ACPI_TABLE_IS_LOADED) { + + /* Table is still loaded, this is an error */ + + status = AE_ALREADY_EXISTS; + goto release; + } else { + /* Table was unloaded, allow it to be reloaded */ + + table_desc->pointer = + acpi_gbl_root_table_list.tables[i].pointer; + table_desc->address = + acpi_gbl_root_table_list.tables[i].address; + status = AE_OK; + goto print_header; + } } - /* - * Add the table to the global table list - */ + /* Add the table to the global root table list */ + status = acpi_tb_store_table(table_desc->address, table_desc->pointer, table_desc->length, table_desc->flags, table_index); @@ -171,6 +205,7 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) goto release; } + print_header: acpi_tb_print_table_header(table_desc->address, table_desc->pointer); release: -- cgit v1.2.3 From a6f30539f31a8129288b0e5640d3eb1174848c15 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 4 Jul 2008 10:57:51 +0800 Subject: ACPICA: Fix table compare code, length then data Split the ACPI table compare. First check that the lengths match exactly. Then compare the data. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/tables/tbinstal.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index 905dc38ab23b..18747ce8dd2f 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -110,7 +110,6 @@ acpi_status acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) { u32 i; - u32 length; acpi_status status = AE_OK; ACPI_FUNCTION_TRACE(tb_add_table); @@ -145,13 +144,18 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) } } - /* Check for a table match on the entire table length */ + /* + * Check for a table match on the entire table length, + * not just the header. + */ + if (table_desc->length != + acpi_gbl_root_table_list.tables[i].length) { + continue; + } - length = ACPI_MIN(table_desc->length, - acpi_gbl_root_table_list.tables[i].length); if (ACPI_MEMCMP(table_desc->pointer, acpi_gbl_root_table_list.tables[i].pointer, - length)) { + acpi_gbl_root_table_list.tables[i].length)) { continue; } -- cgit v1.2.3 From b417d40b9a850f12f69aa9d785d2af39c9463bb8 Mon Sep 17 00:00:00 2001 From: Yi Yang Date: Mon, 4 Aug 2008 10:30:09 +0800 Subject: ACPICA: Return status from global init function Return status from acpi_ut_init_globals. This is used by both the kernel subsystem and the utilities such as iASL compiler. The function could possibly fail when the caches are initialized. Yang Yi. Signed-off-by: Yi Yang Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/utilities/utglobal.c | 8 ++++---- drivers/acpi/utilities/utxface.c | 7 ++++++- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index a6e71b801d2d..248eefc369f8 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -677,14 +677,14 @@ u8 acpi_ut_valid_object_type(acpi_object_type type) * * PARAMETERS: None * - * RETURN: None + * RETURN: Status * * DESCRIPTION: Init library globals. All globals that require specific * initialization should be initialized here! * ******************************************************************************/ -void acpi_ut_init_globals(void) +acpi_status acpi_ut_init_globals(void) { acpi_status status; u32 i; @@ -695,7 +695,7 @@ void acpi_ut_init_globals(void) status = acpi_ut_create_caches(); if (ACPI_FAILURE(status)) { - return; + return_ACPI_STATUS(status); } /* Mutex locked flags */ @@ -772,7 +772,7 @@ void acpi_ut_init_globals(void) acpi_gbl_display_final_mem_stats = FALSE; #endif - return_VOID; + return_ACPI_STATUS(AE_OK); } ACPI_EXPORT_SYMBOL(acpi_dbg_level) diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c index f8bdadf3c32f..c198a4d40583 100644 --- a/drivers/acpi/utilities/utxface.c +++ b/drivers/acpi/utilities/utxface.c @@ -81,7 +81,12 @@ acpi_status __init acpi_initialize_subsystem(void) /* Initialize all globals used by the subsystem */ - acpi_ut_init_globals(); + status = acpi_ut_init_globals(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "During initialization of globals")); + return_ACPI_STATUS(status); + } /* Create the default mutex objects */ -- cgit v1.2.3 From bbc241340681557a16982f4d1840f00963bc05b4 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Mon, 4 Aug 2008 13:22:10 +0800 Subject: ACPICA: Add function to dereference returned reference objects Examines the return object from a call to acpi_evaluate_object. Any Index or RefOf references are automatically dereferenced in an attempt to return something useful (these reference types cannot be converted into an external ACPI_OBJECT.) Lin Ming, Bob Moore. http://bugzilla.kernel.org/show_bug.cgi?id=11105 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/namespace/nsxfeval.c | 79 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index 38be5865d95d..f3cc37624537 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -45,9 +45,14 @@ #include #include #include +#include #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsxfeval") + +/* Local prototypes */ +static void acpi_ns_resolve_references(struct acpi_evaluate_info *info); + #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -69,6 +74,7 @@ ACPI_MODULE_NAME("nsxfeval") * be valid (non-null) * ******************************************************************************/ + acpi_status acpi_evaluate_object_typed(acpi_handle handle, acpi_string pathname, @@ -283,6 +289,10 @@ acpi_evaluate_object(acpi_handle handle, if (ACPI_SUCCESS(status)) { + /* Dereference Index and ref_of references */ + + acpi_ns_resolve_references(info); + /* Get the size of the returned object */ status = @@ -350,6 +360,74 @@ acpi_evaluate_object(acpi_handle handle, ACPI_EXPORT_SYMBOL(acpi_evaluate_object) +/******************************************************************************* + * + * FUNCTION: acpi_ns_resolve_references + * + * PARAMETERS: Info - Evaluation info block + * + * RETURN: Info->return_object is replaced with the dereferenced object + * + * DESCRIPTION: Dereference certain reference objects. Called before an + * internal return object is converted to an external union acpi_object. + * + * Performs an automatic dereference of Index and ref_of reference objects. + * These reference objects are not supported by the union acpi_object, so this is a + * last resort effort to return something useful. Also, provides compatibility + * with other ACPI implementations. + * + * NOTE: does not handle references within returned package objects or nested + * references, but this support could be added later if found to be necessary. + * + ******************************************************************************/ +static void acpi_ns_resolve_references(struct acpi_evaluate_info *info) +{ + union acpi_operand_object *obj_desc = NULL; + struct acpi_namespace_node *node; + + /* We are interested in reference objects only */ + + if (ACPI_GET_OBJECT_TYPE(info->return_object) != + ACPI_TYPE_LOCAL_REFERENCE) { + return; + } + + /* + * Two types of references are supported - those created by Index and + * ref_of operators. A name reference (AML_NAMEPATH_OP) can be converted + * to an union acpi_object, so it is not dereferenced here. A ddb_handle + * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to + * an union acpi_object. + */ + switch (info->return_object->reference.opcode) { + case AML_INDEX_OP: + + obj_desc = *(info->return_object->reference.where); + break; + + case AML_REF_OF_OP: + + node = info->return_object->reference.object; + if (node) { + obj_desc = node->object; + } + break; + + default: + return; + } + + /* Replace the existing reference object */ + + if (obj_desc) { + acpi_ut_add_reference(obj_desc); + acpi_ut_remove_reference(info->return_object); + info->return_object = obj_desc; + } + + return; +} + /******************************************************************************* * * FUNCTION: acpi_walk_namespace @@ -379,6 +457,7 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object) * function, etc. * ******************************************************************************/ + acpi_status acpi_walk_namespace(acpi_object_type type, acpi_handle start_object, -- cgit v1.2.3 From b7906e324532c1616546f6d4a1306894ba7c0a3d Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 15 Aug 2008 04:32:59 +0200 Subject: ACPICA: Fix warning for 64-bit build Fixes warning from exconfig.c on 64-bit build. AK: This actually was fixed earlier in Linux, this just syncs with AK: the version of the fix that went into the ACPCA codebase Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/executer/exconfig.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 331a114f42c9..4c512c2990e5 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -96,8 +96,7 @@ acpi_ex_add_table(u32 table_index, /* Install the new table into the local data structures */ - obj_desc->reference.object = ACPI_CAST_PTR(void, - (unsigned long)table_index); + obj_desc->reference.object = ACPI_TO_POINTER(table_index); /* Add the table to the namespace */ -- cgit v1.2.3 From 0a1fbf2db0d275f0f8160bb9c3e51c4df5bafdc2 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 4 Jul 2008 10:53:58 +0800 Subject: ACPICA: Return method arg count from acpi_get_object_info Also update the debugger so that the correct number of arguments is passed to the method. Prevents a warning message from the debugger. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/namespace/nsxfname.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c index 3cb910ded44a..5efa4e7ddb0b 100644 --- a/drivers/acpi/namespace/nsxfname.c +++ b/drivers/acpi/namespace/nsxfname.c @@ -265,6 +265,10 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) info->name = node->name.integer; info->valid = 0; + if (node->type == ACPI_TYPE_METHOD) { + info->param_count = node->object->method.param_count; + } + status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { goto cleanup; -- cgit v1.2.3 From f02a99ac66748f8b62477c86f6df04d3ec6169fd Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 4 Aug 2008 10:40:09 +0800 Subject: ACPICA: Add function to decode reference obj types to strings Created for improved error messages. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/utilities/utglobal.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index 248eefc369f8..bcace577183b 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -45,6 +45,7 @@ #include #include +#include ACPI_EXPORT_SYMBOL(acpi_gbl_FADT) #define _COMPONENT ACPI_UTILITIES @@ -575,6 +576,41 @@ char *acpi_ut_get_descriptor_name(void *object) } +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_reference_name + * + * PARAMETERS: Object - An ACPI reference object + * + * RETURN: Pointer to a string + * + * DESCRIPTION: Decode a reference object sub-type to a string. + * + ******************************************************************************/ + +/* Printable names of reference object sub-types */ + +const char *acpi_ut_get_reference_name(union acpi_operand_object *object) +{ + + switch (object->reference.opcode) { + case AML_INT_NAMEPATH_OP: + return "Name"; + + case AML_LOAD_OP: + return "DDB-Handle"; + + case AML_REF_OF_OP: + return "RefOf"; + + case AML_INDEX_OP: + return "Index"; + + default: + return "Unknown"; + } +} + #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) /* * Strings and procedures used for debug only -- cgit v1.2.3 From c2de3a49454cdc9ca42bbd5d742913421d049f59 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 4 Aug 2008 10:41:29 +0800 Subject: ACPICA: Improve object conversion error messages Better error messages during object conversion from internal to the external ACPI_OBJECT. Used for external calls to acpi_evaluate_object. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/utilities/utobject.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index 916eff399eb3..924d05af94d2 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c @@ -503,7 +503,9 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, * required eventually. */ ACPI_ERROR((AE_INFO, - "Unsupported Reference opcode=%X in object %p", + "Cannot convert to external object - " + "unsupported Reference type [%s] %X in object %p", + acpi_ut_get_reference_name(internal_object), internal_object->reference.opcode, internal_object)); status = AE_TYPE; @@ -513,7 +515,9 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, default: - ACPI_ERROR((AE_INFO, "Unsupported type=%X in object %p", + ACPI_ERROR((AE_INFO, "Cannot convert to external object - " + "unsupported type [%s] %X in object %p", + acpi_ut_get_object_type_name(internal_object), ACPI_GET_OBJECT_TYPE(internal_object), internal_object)); status = AE_TYPE; -- cgit v1.2.3 From 8bd108d14604d9c95000751e6c6ecbd11ea6ed40 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Thu, 25 Sep 2008 21:40:30 +0400 Subject: ACPICA: add preemption point after each opcode parse Reference: http://marc.info/?l=linux-acpi&m=122236382701062&w=2 Signed-off-by: Alexey Starikovskiy Tested-by: Sitsofe Wheeler Signed-off-by: Len Brown --- drivers/acpi/parser/psloop.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c index c06238e55d98..4647039a0d8a 100644 --- a/drivers/acpi/parser/psloop.c +++ b/drivers/acpi/parser/psloop.c @@ -719,6 +719,8 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state, *op = NULL; } + ACPI_PREEMPTION_POINT(); + return_ACPI_STATUS(AE_OK); } -- cgit v1.2.3 From 55ac9a018f83e4f42f3c6ce98a8dbda73b985935 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Sun, 28 Sep 2008 14:51:56 +0800 Subject: ACPI: replace ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ...) with printk ACPI_DB_ERROR and ACPI_DB_WARN were removed from ACPICA core. So replace ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ...) with printk(KERN_ERR PREFIX ...) and ACPI_DEBUG_PRINT((ACPI_DB_WARN, ...) with printk(KERN_WARNING PREFIX ...) We do not use ACPI_ERROR/ACPI_WARNING since they're not exported, see ------------------------------------------------------------- commit 6468463abd7051fcc29f3ee7c931f9bbbb26f5a4 Author: Len Brown Date: Mon Jun 26 23:41:38 2006 -0400 ACPI: un-export ACPI_ERROR() -- use printk(KERN_ERR...) Signed-off-by: Len Brown ------------------------------------------------------------- Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpi_memhotplug.c | 4 ++-- drivers/acpi/cm_sbs.c | 8 ++++---- drivers/acpi/fan.c | 4 ++-- drivers/acpi/osl.c | 4 ++-- drivers/acpi/processor_perflib.c | 10 +++++----- drivers/acpi/processor_throttling.c | 10 +++++----- drivers/acpi/scan.c | 10 +++++----- drivers/acpi/system.c | 4 ++-- drivers/acpi/thermal.c | 4 ++-- drivers/acpi/video.c | 12 ++++++------ 10 files changed, 35 insertions(+), 35 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 5f1127ad5a95..bbad9b6c2c88 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -454,8 +454,8 @@ static int acpi_memory_device_start (struct acpi_device *device) /* call add_memory func */ result = acpi_memory_enable_device(mem_device); if (result) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error in acpi_memory_enable_device\n")); + printk(KERN_ERR PREFIX + "Error in acpi_memory_enable_device\n"); } return result; } diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c index f9db4f444bd0..4441e84b28a9 100644 --- a/drivers/acpi/cm_sbs.c +++ b/drivers/acpi/cm_sbs.c @@ -52,8 +52,8 @@ struct proc_dir_entry *acpi_lock_ac_dir(void) if (acpi_ac_dir) { lock_ac_dir_cnt++; } else { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Cannot create %s\n", ACPI_AC_CLASS)); + printk(KERN_ERR PREFIX + "Cannot create %s\n", ACPI_AC_CLASS); } mutex_unlock(&cm_sbs_mutex); return acpi_ac_dir; @@ -83,8 +83,8 @@ struct proc_dir_entry *acpi_lock_battery_dir(void) if (acpi_battery_dir) { lock_battery_dir_cnt++; } else { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Cannot create %s\n", ACPI_BATTERY_CLASS)); + printk(KERN_ERR PREFIX + "Cannot create %s\n", ACPI_BATTERY_CLASS); } mutex_unlock(&cm_sbs_mutex); return acpi_battery_dir; diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 2655bc1b4eeb..dfc0486ffaff 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -327,8 +327,8 @@ static int acpi_fan_resume(struct acpi_device *device) result = acpi_bus_get_power(device->handle, &power_state); if (result) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error reading fan power state\n")); + printk(KERN_ERR PREFIX + "Error reading fan power state\n"); return result; } diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 235a1386888a..1420a9f69e5d 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -729,8 +729,8 @@ acpi_status acpi_os_execute(acpi_execute_type type, INIT_WORK(&dpc->work, acpi_os_execute_deferred); queue = (type == OSL_NOTIFY_HANDLER) ? kacpi_notify_wq : kacpid_wq; if (!queue_work(queue, &dpc->work)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Call to queue_work() failed.\n")); + printk(KERN_ERR PREFIX + "Call to queue_work() failed.\n"); status = AE_ERROR; kfree(dpc); } diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 80c251ec6d2a..e5c457b45f2b 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -524,13 +524,13 @@ static int acpi_processor_get_psd(struct acpi_processor *pr) psd = buffer.pointer; if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); + printk(KERN_ERR PREFIX "Invalid _PSD data\n"); result = -EFAULT; goto end; } if (psd->package.count != 1) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); + printk(KERN_ERR PREFIX "Invalid _PSD data\n"); result = -EFAULT; goto end; } @@ -543,19 +543,19 @@ static int acpi_processor_get_psd(struct acpi_processor *pr) status = acpi_extract_package(&(psd->package.elements[0]), &format, &state); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); + printk(KERN_ERR PREFIX "Invalid _PSD data\n"); result = -EFAULT; goto end; } if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:num_entries\n")); + printk(KERN_ERR PREFIX "Unknown _PSD:num_entries\n"); result = -EFAULT; goto end; } if (pdomain->revision != ACPI_PSD_REV0_REVISION) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:revision\n")); + printk(KERN_ERR PREFIX "Unknown _PSD:revision\n"); result = -EFAULT; goto end; } diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index a56fc6c4394b..e89a25824f2a 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -528,13 +528,13 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr) tsd = buffer.pointer; if (!tsd || (tsd->type != ACPI_TYPE_PACKAGE)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n")); + printk(KERN_ERR PREFIX "Invalid _TSD data\n"); result = -EFAULT; goto end; } if (tsd->package.count != 1) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n")); + printk(KERN_ERR PREFIX "Invalid _TSD data\n"); result = -EFAULT; goto end; } @@ -547,19 +547,19 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr) status = acpi_extract_package(&(tsd->package.elements[0]), &format, &state); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n")); + printk(KERN_ERR PREFIX "Invalid _TSD data\n"); result = -EFAULT; goto end; } if (pdomain->num_entries != ACPI_TSD_REV0_ENTRIES) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:num_entries\n")); + printk(KERN_ERR PREFIX "Unknown _TSD:num_entries\n"); result = -EFAULT; goto end; } if (pdomain->revision != ACPI_TSD_REV0_REVISION) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:revision\n")); + printk(KERN_ERR PREFIX "Unknown _TSD:revision\n"); result = -EFAULT; goto end; } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f6f52c1a2aba..81d6095468f9 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -113,16 +113,16 @@ static int acpi_bus_hot_remove_device(void *context) if (acpi_bus_trim(device, 1)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Removing device failed\n")); + printk(KERN_ERR PREFIX + "Removing device failed\n"); return -1; } /* power off device */ status = acpi_evaluate_object(handle, "_PS3", NULL, NULL); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Power-off device failed\n")); + printk(KERN_WARNING PREFIX + "Power-off device failed\n"); if (device->flags.lockable) { arg_list.count = 1; @@ -477,7 +477,7 @@ static int acpi_device_register(struct acpi_device *device, result = acpi_device_setup_files(device); if(result) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error creating sysfs interface for device %s\n", device->dev.bus_id)); + printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", device->dev.bus_id); device->removal_type = ACPI_BUS_REMOVAL_NORMAL; return 0; diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 91dec448b3ed..3eefd6d029f9 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -387,8 +387,8 @@ static ssize_t counter_set(struct kobject *kobj, goto end; if (!(all_counters[index].flags & ACPI_EVENT_VALID)) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Can not change Invalid GPE/Fixed Event status\n")); + printk(KERN_WARNING PREFIX + "Can not change Invalid GPE/Fixed Event status\n"); return -EINVAL; } diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 912703691d36..263ec08a9011 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -1213,8 +1213,8 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) acpi_bus_private_data_handler, tz->thermal_zone); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error attaching device data\n")); + printk(KERN_ERR PREFIX + "Error attaching device data\n"); return -ENODEV; } diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index e8a51a1700f7..4ae39ee8cdef 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1530,8 +1530,8 @@ acpi_video_bus_get_one_device(struct acpi_device *device, acpi_video_device_notify, data); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error installing notify handler\n")); + printk(KERN_ERR PREFIX + "Error installing notify handler\n"); if(data->brightness) kfree(data->brightness->levels); kfree(data->brightness); @@ -1745,8 +1745,8 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, status = acpi_video_bus_get_one_device(dev, video); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Cant attach device")); + printk(KERN_WARNING PREFIX + "Cant attach device"); continue; } } @@ -2003,8 +2003,8 @@ static int acpi_video_bus_add(struct acpi_device *device) ACPI_DEVICE_NOTIFY, acpi_video_bus_notify, video); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error installing notify handler\n")); + printk(KERN_ERR PREFIX + "Error installing notify handler\n"); error = -ENODEV; goto err_stop_video; } -- cgit v1.2.3 From 23d3e055beb12db2a3b91dfeee474c4d5ecc13b9 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Sun, 28 Sep 2008 15:00:47 +0800 Subject: ACPICA: Remove obsolete debug levels (WARN and ERROR) Removed ACPI_DB_WARN and ACPI_DB_ERROR. These debug levels were made obsolete by the ACPI_WARNING and ACPI_ERROR/ACPI_EXCEPTION interfaces. Also added ACPI_DB_EVENTS to correspond with the existing ACPI_LV_EVENTS. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/debug.c | 2 -- drivers/acpi/executer/exstore.c | 2 +- drivers/acpi/namespace/nssearch.c | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index 6df564f4ca6e..abf36b4b1d1d 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c @@ -47,8 +47,6 @@ static const struct acpi_dlayer acpi_debug_layers[] = { }; static const struct acpi_dlevel acpi_debug_levels[] = { - ACPI_DEBUG_INIT(ACPI_LV_ERROR), - ACPI_DEBUG_INIT(ACPI_LV_WARN), ACPI_DEBUG_INIT(ACPI_LV_INIT), ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT), ACPI_DEBUG_INIT(ACPI_LV_INFO), diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index 38b55e352495..09e96846d155 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -403,7 +403,7 @@ acpi_ex_store(union acpi_operand_object *source_desc, ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X", ref_desc->reference.opcode)); - ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_ERROR); + ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_INFO); status = AE_AML_INTERNAL; break; diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c index 8399276cba1e..a9a80bf811b3 100644 --- a/drivers/acpi/namespace/nssearch.c +++ b/drivers/acpi/namespace/nssearch.c @@ -331,7 +331,7 @@ acpi_ns_search_and_enter(u32 target_name, "Found bad character(s) in name, repaired: [%4.4s]\n", ACPI_CAST_PTR(char, &target_name))); } else { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found bad character(s) in name, repaired: [%4.4s]\n", ACPI_CAST_PTR(char, &target_name))); } -- cgit v1.2.3 From b68bacf225e5e9758472e99505d76125ced3ea88 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Sat, 27 Sep 2008 10:29:31 +0800 Subject: ACPICA: Disallow evaluation of named object types with no value Return AE_TYPE for objects that have no value and therefore evaluation is undefined: Device, Event, Mutex, Region, Thermal, and Scope. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/namespace/nseval.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index d369164e00b0..0a1ae670a847 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c @@ -195,7 +195,28 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) } else { /* * 2) Object is not a method, return its current value + * + * Disallow certain object types. For these, "evaluation" is undefined. */ + switch (info->resolved_node->type) { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_REGION: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_LOCAL_SCOPE: + + ACPI_ERROR((AE_INFO, + "[%4.4s] Evaluation of object type [%s] is not supported", + info->resolved_node->name.ascii, + acpi_ut_get_type_name(info->resolved_node-> + type))); + + return_ACPI_STATUS(AE_TYPE); + + default: + break; + } /* * Objects require additional resolution steps (e.g., the Node may be -- cgit v1.2.3 From 93851b4d13de48753eaae76ed190eef7355e2c19 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Sat, 27 Sep 2008 10:38:07 +0800 Subject: ACPICA: Reduce error to warning for incorrect method arg count Previously aborted with error if too few arguments were passed to a control method via the external ACPICA interface. Now issue a warning instead and continue. Handles the case where the method inadvertently declares too many arguments, but does not actually use the extra ones. Applies mainly to the predefined methods. http://bugzilla.kernel.org/show_bug.cgi?id=11032 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/namespace/nseval.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index 0a1ae670a847..42dae12f2ef8 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c @@ -148,21 +148,22 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) info->param_count++; } - /* Error if too few arguments were passed in */ + /* + * Warning if too few or too many arguments have been passed by the + * caller. We don't want to abort here with an error because an + * incorrect number of arguments may not cause the method to fail. + * However, the method will fail if there are too few arguments passed + * and the method attempts to use one of the missing ones. + */ if (info->param_count < info->obj_desc->method.param_count) { - ACPI_ERROR((AE_INFO, + ACPI_WARNING((AE_INFO, "Insufficient arguments - " "method [%4.4s] needs %d, found %d", acpi_ut_get_node_name(info->resolved_node), info->obj_desc->method.param_count, info->param_count)); - return_ACPI_STATUS(AE_MISSING_ARGUMENTS); - } - - /* Just a warning if too many arguments */ - - else if (info->param_count > + } else if (info->param_count > info->obj_desc->method.param_count) { ACPI_WARNING((AE_INFO, "Excess arguments - " -- cgit v1.2.3 From 57e664cfd968ec8e4b0bfd80a5e8f903307e598b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Sat, 27 Sep 2008 10:40:39 +0800 Subject: ACPICA: Update for Reference ACPI_OPERAND_OBJECT 1) Add new field for use by DdbHandle (Value) 2) Use ACPI_CAST_INDIRECT_PTR to eliminate strict type warnings 3) Cleanup debug output Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsobject.c | 16 ++++++++++------ drivers/acpi/executer/exconfig.c | 6 +++--- drivers/acpi/executer/exdump.c | 29 ++++++++++++++--------------- drivers/acpi/executer/exstore.c | 4 ++-- 4 files changed, 29 insertions(+), 26 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 0f2805899210..09af39fff1a3 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -741,10 +741,12 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, obj_desc-> reference.offset, walk_state, + ACPI_CAST_INDIRECT_PTR (struct - acpi_namespace_node - **)&obj_desc-> - reference.object); + acpi_namespace_node, + &obj_desc-> + reference. + object)); #endif break; @@ -760,10 +762,12 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, obj_desc-> reference.offset, walk_state, + ACPI_CAST_INDIRECT_PTR (struct - acpi_namespace_node - **)&obj_desc-> - reference.object); + acpi_namespace_node, + &obj_desc-> + reference. + object)); #endif break; diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 4c512c2990e5..5f2b1ebf70a3 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -96,7 +96,7 @@ acpi_ex_add_table(u32 table_index, /* Install the new table into the local data structures */ - obj_desc->reference.object = ACPI_TO_POINTER(table_index); + obj_desc->reference.value = table_index; /* Add the table to the namespace */ @@ -505,9 +505,9 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Get the table index from the ddb_handle (acpi_size for 64-bit case) */ + /* Get the table index from the ddb_handle */ - table_index = (u32) (acpi_size) table_desc->reference.object; + table_index = table_desc->reference.value; /* Invoke table handler if present */ diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index 2be2e2bf95bf..7d4123256cf1 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -214,10 +214,11 @@ static struct acpi_exdump_info acpi_ex_dump_index_field[5] = { {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(index_field.data_obj), "Data Object"} }; -static struct acpi_exdump_info acpi_ex_dump_reference[7] = { +static struct acpi_exdump_info acpi_ex_dump_reference[8] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_reference), NULL}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.target_type), "Target Type"}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(reference.offset), "Offset"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(reference.value), "Value"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.object), "Object Desc"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.node), "Node"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.where), "Where"}, @@ -497,24 +498,24 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) switch (obj_desc->reference.opcode) { case AML_DEBUG_OP: - acpi_os_printf("Reference: Debug\n"); + acpi_os_printf("Reference: [Debug]\n"); break; case AML_INDEX_OP: - acpi_os_printf("Reference: Index %p\n", + acpi_os_printf("Reference: [Index] %p\n", obj_desc->reference.object); break; case AML_LOAD_OP: - acpi_os_printf("Reference: [DdbHandle] TableIndex %p\n", - obj_desc->reference.object); + acpi_os_printf("Reference: [DdbHandle] TableIndex %X\n", + obj_desc->reference.value); break; case AML_REF_OF_OP: - acpi_os_printf("Reference: (RefOf) %p [%s]\n", + acpi_os_printf("Reference: [RefOf] %p [%s]\n", obj_desc->reference.object, acpi_ut_get_type_name(((union acpi_operand_object @@ -526,7 +527,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) case AML_ARG_OP: - acpi_os_printf("Reference: Arg%d", + acpi_os_printf("Reference: [Arg%d]", obj_desc->reference.offset); if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { @@ -544,7 +545,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) case AML_LOCAL_OP: - acpi_os_printf("Reference: Local%d", + acpi_os_printf("Reference: [Local%d]", obj_desc->reference.offset); if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { @@ -562,7 +563,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) case AML_INT_NAMEPATH_OP: - acpi_os_printf("Reference: Namepath %X [%4.4s]\n", + acpi_os_printf("Reference: [Namepath] %X [%4.4s]\n", obj_desc->reference.node->name.integer, obj_desc->reference.node->name.ascii); break; @@ -883,13 +884,11 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) acpi_os_printf(" Target: %p", obj_desc->reference.object); if (obj_desc->reference.opcode == AML_LOAD_OP) { - /* - * For DDBHandle reference, - * obj_desc->Reference.Object is the table index - */ - acpi_os_printf(" [DDBHandle]\n"); + acpi_os_printf(" [DDBHandle] Table Index: %X\n", + obj_desc->reference.value); } else { - acpi_os_printf(" [%s]\n", + acpi_os_printf(" Target: %p [%s]\n", + obj_desc->reference.object, acpi_ut_get_type_name(((union acpi_operand_object *) diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index 09e96846d155..20b4893e06ed 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -193,8 +193,8 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, if (source_desc->reference.opcode == AML_LOAD_OP) { /* Load and load_table */ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - " Table OwnerId %p\n", - source_desc->reference.object)); + " Table Index %X\n", + source_desc->reference.value)); break; } -- cgit v1.2.3 From 2425a0967f29b196fad5d4f726c9502679284656 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Sat, 27 Sep 2008 10:42:02 +0800 Subject: ACPICA: Update comments - no functional changes Some formatting and spelling fixes. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/executer/exconvrt.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c index 261d97516d9b..890378e789a4 100644 --- a/drivers/acpi/executer/exconvrt.c +++ b/drivers/acpi/executer/exconvrt.c @@ -57,7 +57,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer, * * FUNCTION: acpi_ex_convert_to_integer * - * PARAMETERS: obj_desc - Object to be converted. Must be an + * PARAMETERS: obj_desc - Object to be converted. Must be an * Integer, Buffer, or String * result_desc - Where the new Integer object is returned * Flags - Used for string conversion @@ -103,7 +103,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, } /* - * Convert the buffer/string to an integer. Note that both buffers and + * Convert the buffer/string to an integer. Note that both buffers and * strings are treated as raw data - we don't convert ascii to hex for * strings. * @@ -120,7 +120,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, /* * Convert string to an integer - for most cases, the string must be - * hexadecimal as per the ACPI specification. The only exception (as + * hexadecimal as per the ACPI specification. The only exception (as * of ACPI 3.0) is that the to_integer() operator allows both decimal * and hexadecimal strings (hex prefixed with "0x"). */ @@ -159,6 +159,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, break; default: + /* No other types can get here */ break; } @@ -185,7 +186,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, * * FUNCTION: acpi_ex_convert_to_buffer * - * PARAMETERS: obj_desc - Object to be converted. Must be an + * PARAMETERS: obj_desc - Object to be converted. Must be an * Integer, Buffer, or String * result_desc - Where the new buffer object is returned * @@ -365,7 +366,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer, } /* - * Since leading zeros are supressed, we must check for the case where + * Since leading zeros are suppressed, we must check for the case where * the integer equals 0 * * Finally, null terminate the string and return the length @@ -383,7 +384,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer, * * FUNCTION: acpi_ex_convert_to_string * - * PARAMETERS: obj_desc - Object to be converted. Must be an + * PARAMETERS: obj_desc - Object to be converted. Must be an * Integer, Buffer, or String * result_desc - Where the string object is returned * Type - String flags (base and conversion type) @@ -472,7 +473,7 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, base = 10; /* - * Calculate the final string length. Individual string values + * Calculate the final string length. Individual string values * are variable length (include separator for each) */ for (i = 0; i < obj_desc->buffer.length; i++) { @@ -617,7 +618,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: /* - * These types require an Integer operand. We can convert + * These types require an Integer operand. We can convert * a Buffer or a String to an Integer if necessary. */ status = @@ -627,7 +628,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, case ACPI_TYPE_STRING: /* - * The operand must be a String. We can convert an + * The operand must be a String. We can convert an * Integer or Buffer if necessary */ status = @@ -637,7 +638,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, case ACPI_TYPE_BUFFER: /* - * The operand must be a Buffer. We can convert an + * The operand must be a Buffer. We can convert an * Integer or String if necessary */ status = -- cgit v1.2.3 From 1044f1f65b7df2aae979e397904c4985eeb99ba2 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Sat, 27 Sep 2008 11:08:41 +0800 Subject: ACPICA: Cleanup for internal Reference Object Fix some sloppiness in the Reference object. No longer use AML opcodes to differentiate the types, introduce new reference Class. Cleanup the debug output code. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsmthdat.c | 83 ++++++++++++++++++++------------------ drivers/acpi/dispatcher/dsobject.c | 56 +++++++++++++++---------- drivers/acpi/dispatcher/dsopcode.c | 2 +- drivers/acpi/dispatcher/dswexec.c | 8 ++-- drivers/acpi/executer/exconfig.c | 3 +- drivers/acpi/executer/exdump.c | 74 ++++++++++++++++----------------- drivers/acpi/executer/exmisc.c | 14 +++---- drivers/acpi/executer/exoparg1.c | 26 ++++++------ drivers/acpi/executer/exoparg2.c | 4 +- drivers/acpi/executer/exresnte.c | 16 +++----- drivers/acpi/executer/exresolv.c | 60 +++++++++++++-------------- drivers/acpi/executer/exresop.c | 50 ++++++++++------------- drivers/acpi/executer/exstore.c | 57 +++++++++++++------------- drivers/acpi/executer/exstoren.c | 3 +- drivers/acpi/namespace/nsdump.c | 5 +-- drivers/acpi/namespace/nsxfeval.c | 7 ++-- drivers/acpi/resources/rscalc.c | 5 +-- drivers/acpi/resources/rscreate.c | 10 ++--- drivers/acpi/utilities/utcopy.c | 29 +++++++------ drivers/acpi/utilities/utdelete.c | 5 +-- drivers/acpi/utilities/utglobal.c | 35 +++++++++------- drivers/acpi/utilities/utobject.c | 9 ++--- 22 files changed, 280 insertions(+), 281 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index 13c43eac35db..d03f81bd1bcb 100644 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ b/drivers/acpi/dispatcher/dsmthdat.c @@ -43,7 +43,6 @@ #include #include -#include #include #include @@ -52,11 +51,11 @@ ACPI_MODULE_NAME("dsmthdat") /* Local prototypes */ static void -acpi_ds_method_data_delete_value(u16 opcode, +acpi_ds_method_data_delete_value(u8 type, u32 index, struct acpi_walk_state *walk_state); static acpi_status -acpi_ds_method_data_set_value(u16 opcode, +acpi_ds_method_data_set_value(u8 type, u32 index, union acpi_operand_object *object, struct acpi_walk_state *walk_state); @@ -216,7 +215,7 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params, * Store the argument in the method/walk descriptor. * Do not copy the arg in order to implement call by reference */ - status = acpi_ds_method_data_set_value(AML_ARG_OP, index, + status = acpi_ds_method_data_set_value(ACPI_REFCLASS_ARG, index, params[index], walk_state); if (ACPI_FAILURE(status)) { @@ -234,7 +233,8 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params, * * FUNCTION: acpi_ds_method_data_get_node * - * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG * Index - Which Local or Arg whose type to get * walk_state - Current walk state object * Node - Where the node is returned. @@ -246,7 +246,7 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params, ******************************************************************************/ acpi_status -acpi_ds_method_data_get_node(u16 opcode, +acpi_ds_method_data_get_node(u8 type, u32 index, struct acpi_walk_state *walk_state, struct acpi_namespace_node **node) @@ -256,8 +256,8 @@ acpi_ds_method_data_get_node(u16 opcode, /* * Method Locals and Arguments are supported */ - switch (opcode) { - case AML_LOCAL_OP: + switch (type) { + case ACPI_REFCLASS_LOCAL: if (index > ACPI_METHOD_MAX_LOCAL) { ACPI_ERROR((AE_INFO, @@ -271,7 +271,7 @@ acpi_ds_method_data_get_node(u16 opcode, *node = &walk_state->local_variables[index]; break; - case AML_ARG_OP: + case ACPI_REFCLASS_ARG: if (index > ACPI_METHOD_MAX_ARG) { ACPI_ERROR((AE_INFO, @@ -286,8 +286,8 @@ acpi_ds_method_data_get_node(u16 opcode, break; default: - ACPI_ERROR((AE_INFO, "Opcode %d is invalid", opcode)); - return_ACPI_STATUS(AE_AML_BAD_OPCODE); + ACPI_ERROR((AE_INFO, "Type %d is invalid", type)); + return_ACPI_STATUS(AE_TYPE); } return_ACPI_STATUS(AE_OK); @@ -297,7 +297,8 @@ acpi_ds_method_data_get_node(u16 opcode, * * FUNCTION: acpi_ds_method_data_set_value * - * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG * Index - Which Local or Arg to get * Object - Object to be inserted into the stack entry * walk_state - Current walk state object @@ -310,7 +311,7 @@ acpi_ds_method_data_get_node(u16 opcode, ******************************************************************************/ static acpi_status -acpi_ds_method_data_set_value(u16 opcode, +acpi_ds_method_data_set_value(u8 type, u32 index, union acpi_operand_object *object, struct acpi_walk_state *walk_state) @@ -321,13 +322,13 @@ acpi_ds_method_data_set_value(u16 opcode, ACPI_FUNCTION_TRACE(ds_method_data_set_value); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "NewObj %p Opcode %X, Refs=%d [%s]\n", object, - opcode, object->common.reference_count, + "NewObj %p Type %2.2X, Refs=%d [%s]\n", object, + type, object->common.reference_count, acpi_ut_get_type_name(object->common.type))); /* Get the namespace node for the arg/local */ - status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node); + status = acpi_ds_method_data_get_node(type, index, walk_state, &node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -350,7 +351,8 @@ acpi_ds_method_data_set_value(u16 opcode, * * FUNCTION: acpi_ds_method_data_get_value * - * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG * Index - Which local_var or argument to get * walk_state - Current walk state object * dest_desc - Where Arg or Local value is returned @@ -363,7 +365,7 @@ acpi_ds_method_data_set_value(u16 opcode, ******************************************************************************/ acpi_status -acpi_ds_method_data_get_value(u16 opcode, +acpi_ds_method_data_get_value(u8 type, u32 index, struct acpi_walk_state *walk_state, union acpi_operand_object **dest_desc) @@ -383,7 +385,7 @@ acpi_ds_method_data_get_value(u16 opcode, /* Get the namespace node for the arg/local */ - status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node); + status = acpi_ds_method_data_get_node(type, index, walk_state, &node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -419,8 +421,8 @@ acpi_ds_method_data_get_value(u16 opcode, /* Otherwise, return the error */ else - switch (opcode) { - case AML_ARG_OP: + switch (type) { + case ACPI_REFCLASS_ARG: ACPI_ERROR((AE_INFO, "Uninitialized Arg[%d] at node %p", @@ -428,7 +430,7 @@ acpi_ds_method_data_get_value(u16 opcode, return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG); - case AML_LOCAL_OP: + case ACPI_REFCLASS_LOCAL: ACPI_ERROR((AE_INFO, "Uninitialized Local[%d] at node %p", @@ -437,9 +439,10 @@ acpi_ds_method_data_get_value(u16 opcode, return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL); default: + ACPI_ERROR((AE_INFO, "Not a Arg/Local opcode: %X", - opcode)); + type)); return_ACPI_STATUS(AE_AML_INTERNAL); } } @@ -458,7 +461,8 @@ acpi_ds_method_data_get_value(u16 opcode, * * FUNCTION: acpi_ds_method_data_delete_value * - * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG * Index - Which local_var or argument to delete * walk_state - Current walk state object * @@ -470,7 +474,7 @@ acpi_ds_method_data_get_value(u16 opcode, ******************************************************************************/ static void -acpi_ds_method_data_delete_value(u16 opcode, +acpi_ds_method_data_delete_value(u8 type, u32 index, struct acpi_walk_state *walk_state) { acpi_status status; @@ -481,7 +485,7 @@ acpi_ds_method_data_delete_value(u16 opcode, /* Get the namespace node for the arg/local */ - status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node); + status = acpi_ds_method_data_get_node(type, index, walk_state, &node); if (ACPI_FAILURE(status)) { return_VOID; } @@ -514,7 +518,8 @@ acpi_ds_method_data_delete_value(u16 opcode, * * FUNCTION: acpi_ds_store_object_to_local * - * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG * Index - Which Local or Arg to set * obj_desc - Value to be stored * walk_state - Current walk state @@ -528,7 +533,7 @@ acpi_ds_method_data_delete_value(u16 opcode, ******************************************************************************/ acpi_status -acpi_ds_store_object_to_local(u16 opcode, +acpi_ds_store_object_to_local(u8 type, u32 index, union acpi_operand_object *obj_desc, struct acpi_walk_state *walk_state) @@ -539,8 +544,8 @@ acpi_ds_store_object_to_local(u16 opcode, union acpi_operand_object *new_obj_desc; ACPI_FUNCTION_TRACE(ds_store_object_to_local); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Opcode=%X Index=%d Obj=%p\n", - opcode, index, obj_desc)); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Type=%2.2X Index=%d Obj=%p\n", + type, index, obj_desc)); /* Parameter validation */ @@ -550,7 +555,7 @@ acpi_ds_store_object_to_local(u16 opcode, /* Get the namespace node for the arg/local */ - status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node); + status = acpi_ds_method_data_get_node(type, index, walk_state, &node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -602,7 +607,7 @@ acpi_ds_store_object_to_local(u16 opcode, * * Weird, but true. */ - if (opcode == AML_ARG_OP) { + if (type == ACPI_REFCLASS_ARG) { /* * If we have a valid reference object that came from ref_of(), * do the indirect store @@ -611,8 +616,8 @@ acpi_ds_store_object_to_local(u16 opcode, ACPI_DESC_TYPE_OPERAND) && (current_obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) - && (current_obj_desc->reference.opcode == - AML_REF_OF_OP)) { + && (current_obj_desc->reference.class == + ACPI_REFCLASS_REFOF)) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Arg (%p) is an ObjRef(Node), storing in node %p\n", new_obj_desc, @@ -640,11 +645,9 @@ acpi_ds_store_object_to_local(u16 opcode, } } - /* - * Delete the existing object - * before storing the new one - */ - acpi_ds_method_data_delete_value(opcode, index, walk_state); + /* Delete the existing object before storing the new one */ + + acpi_ds_method_data_delete_value(type, index, walk_state); } /* @@ -653,7 +656,7 @@ acpi_ds_store_object_to_local(u16 opcode, * (increments the object reference count by one) */ status = - acpi_ds_method_data_set_value(opcode, index, new_obj_desc, + acpi_ds_method_data_set_value(type, index, new_obj_desc, walk_state); /* Remove local reference if we copied the object above */ diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 09af39fff1a3..4f08e599d07e 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -731,36 +731,35 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, switch (op_info->type) { case AML_TYPE_LOCAL_VARIABLE: - /* Split the opcode into a base opcode + offset */ + /* Local ID (0-7) is (AML opcode - base AML_LOCAL_OP) */ - obj_desc->reference.opcode = AML_LOCAL_OP; - obj_desc->reference.offset = opcode - AML_LOCAL_OP; + obj_desc->reference.value = opcode - AML_LOCAL_OP; + obj_desc->reference.class = ACPI_REFCLASS_LOCAL; #ifndef ACPI_NO_METHOD_EXECUTION - status = acpi_ds_method_data_get_node(AML_LOCAL_OP, - obj_desc-> - reference.offset, - walk_state, - ACPI_CAST_INDIRECT_PTR - (struct - acpi_namespace_node, - &obj_desc-> - reference. - object)); + status = + acpi_ds_method_data_get_node(ACPI_REFCLASS_LOCAL, + obj_desc->reference. + value, walk_state, + ACPI_CAST_INDIRECT_PTR + (struct + acpi_namespace_node, + &obj_desc->reference. + object)); #endif break; case AML_TYPE_METHOD_ARGUMENT: - /* Split the opcode into a base opcode + offset */ + /* Arg ID (0-6) is (AML opcode - base AML_ARG_OP) */ - obj_desc->reference.opcode = AML_ARG_OP; - obj_desc->reference.offset = opcode - AML_ARG_OP; + obj_desc->reference.value = opcode - AML_ARG_OP; + obj_desc->reference.class = ACPI_REFCLASS_ARG; #ifndef ACPI_NO_METHOD_EXECUTION - status = acpi_ds_method_data_get_node(AML_ARG_OP, + status = acpi_ds_method_data_get_node(ACPI_REFCLASS_ARG, obj_desc-> - reference.offset, + reference.value, walk_state, ACPI_CAST_INDIRECT_PTR (struct @@ -771,18 +770,31 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, #endif break; - default: /* Other literals, etc.. */ + default: /* Object name or Debug object */ - if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { + switch (op->common.aml_opcode) { + case AML_INT_NAMEPATH_OP: /* Node was saved in Op */ obj_desc->reference.node = op->common.node; obj_desc->reference.object = op->common.node->object; - } + obj_desc->reference.class = ACPI_REFCLASS_NAME; + break; + + case AML_DEBUG_OP: - obj_desc->reference.opcode = opcode; + obj_desc->reference.class = ACPI_REFCLASS_DEBUG; + break; + + default: + + ACPI_ERROR((AE_INFO, + "Unimplemented reference type for AML opcode: %4.4X", + opcode)); + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } break; } break; diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index 6a81c4400edf..69fae5905bb8 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c @@ -1330,7 +1330,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, (walk_state->results->results.obj_desc[0]) == ACPI_TYPE_LOCAL_REFERENCE) && ((walk_state->results->results.obj_desc[0])-> - reference.opcode != AML_INDEX_OP)) { + reference.class != ACPI_REFCLASS_INDEX)) { status = acpi_ex_resolve_to_value(&walk_state-> results->results. diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index b5072fa9c920..5b2419197b9b 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -429,10 +429,10 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) ACPI_TYPE_LOCAL_REFERENCE) && (walk_state->operands[1]->common.type == ACPI_TYPE_LOCAL_REFERENCE) - && (walk_state->operands[0]->reference.opcode == - walk_state->operands[1]->reference.opcode) - && (walk_state->operands[0]->reference.offset == - walk_state->operands[1]->reference.offset)) { + && (walk_state->operands[0]->reference.class == + walk_state->operands[1]->reference.class) + && (walk_state->operands[0]->reference.value == + walk_state->operands[1]->reference.value)) { status = AE_OK; } else { ACPI_EXCEPTION((AE_INFO, status, diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 5f2b1ebf70a3..74da6fa52ef1 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -43,7 +43,6 @@ #include #include -#include #include #include #include @@ -91,7 +90,7 @@ acpi_ex_add_table(u32 table_index, /* Init the table handle */ - obj_desc->reference.opcode = AML_LOAD_OP; + obj_desc->reference.class = ACPI_REFCLASS_TABLE; *ddb_handle = obj_desc; /* Install the new table into the local data structures */ diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index 7d4123256cf1..d087a7d28aa5 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -45,7 +45,6 @@ #include #include #include -#include #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exdump") @@ -216,8 +215,8 @@ static struct acpi_exdump_info acpi_ex_dump_index_field[5] = { static struct acpi_exdump_info acpi_ex_dump_reference[8] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_reference), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.class), "Class"}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.target_type), "Target Type"}, - {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(reference.offset), "Offset"}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(reference.value), "Value"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.object), "Object Desc"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.node), "Node"}, @@ -414,10 +413,10 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, case ACPI_EXD_REFERENCE: - acpi_ex_out_string("Opcode", - (acpi_ps_get_opcode_info - (obj_desc->reference.opcode))-> - name); + acpi_ex_out_string("Class Name", + (char *) + acpi_ut_get_reference_name + (obj_desc)); acpi_ex_dump_reference_obj(obj_desc); break; @@ -495,40 +494,41 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_LOCAL_REFERENCE: - switch (obj_desc->reference.opcode) { - case AML_DEBUG_OP: + acpi_os_printf("Reference: [%s] ", + acpi_ut_get_reference_name(obj_desc)); + + switch (obj_desc->reference.class) { + case ACPI_REFCLASS_DEBUG: - acpi_os_printf("Reference: [Debug]\n"); + acpi_os_printf("\n"); break; - case AML_INDEX_OP: + case ACPI_REFCLASS_INDEX: - acpi_os_printf("Reference: [Index] %p\n", - obj_desc->reference.object); + acpi_os_printf("%p\n", obj_desc->reference.object); break; - case AML_LOAD_OP: + case ACPI_REFCLASS_TABLE: - acpi_os_printf("Reference: [DdbHandle] TableIndex %X\n", + acpi_os_printf("Table Index %X\n", obj_desc->reference.value); break; - case AML_REF_OF_OP: + case ACPI_REFCLASS_REFOF: - acpi_os_printf("Reference: [RefOf] %p [%s]\n", - obj_desc->reference.object, + acpi_os_printf("%p [%s]\n", obj_desc->reference.object, acpi_ut_get_type_name(((union acpi_operand_object - *)obj_desc-> + *) + obj_desc-> reference. object)->common. type)); break; - case AML_ARG_OP: + case ACPI_REFCLASS_ARG: - acpi_os_printf("Reference: [Arg%d]", - obj_desc->reference.offset); + acpi_os_printf("%X", obj_desc->reference.value); if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { @@ -543,10 +543,9 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) acpi_os_printf("\n"); break; - case AML_LOCAL_OP: + case ACPI_REFCLASS_LOCAL: - acpi_os_printf("Reference: [Local%d]", - obj_desc->reference.offset); + acpi_os_printf("%X", obj_desc->reference.value); if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { @@ -561,21 +560,16 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) acpi_os_printf("\n"); break; - case AML_INT_NAMEPATH_OP: + case ACPI_REFCLASS_NAME: - acpi_os_printf("Reference: [Namepath] %X [%4.4s]\n", - obj_desc->reference.node->name.integer, + acpi_os_printf("- [%4.4s]\n", obj_desc->reference.node->name.ascii); break; - default: - - /* Unknown opcode */ + default: /* Unknown reference class */ - acpi_os_printf("Unknown Reference opcode=%X\n", - obj_desc->reference.opcode); + acpi_os_printf("%2.2X\n", obj_desc->reference.class); break; - } break; @@ -866,8 +860,8 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER; - if (obj_desc->reference.opcode == AML_INT_NAMEPATH_OP) { - acpi_os_printf(" Named Object %p ", obj_desc->reference.node); + if (obj_desc->reference.class == ACPI_REFCLASS_NAME) { + acpi_os_printf(" %p ", obj_desc->reference.node); status = acpi_ns_handle_to_pathname(obj_desc->reference.node, @@ -883,8 +877,8 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) ACPI_DESC_TYPE_OPERAND) { acpi_os_printf(" Target: %p", obj_desc->reference.object); - if (obj_desc->reference.opcode == AML_LOAD_OP) { - acpi_os_printf(" [DDBHandle] Table Index: %X\n", + if (obj_desc->reference.class == ACPI_REFCLASS_TABLE) { + acpi_os_printf(" Table Index: %X\n", obj_desc->reference.value); } else { acpi_os_printf(" Target: %p [%s]\n", @@ -987,9 +981,9 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, case ACPI_TYPE_LOCAL_REFERENCE: - acpi_os_printf("[Object Reference] %s", - (acpi_ps_get_opcode_info - (obj_desc->reference.opcode))->name); + acpi_os_printf("[Object Reference] Type [%s] %2.2X", + acpi_ut_get_reference_name(obj_desc), + obj_desc->reference.class); acpi_ex_dump_reference_obj(obj_desc); break; diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c index 731414a581a6..efb191340059 100644 --- a/drivers/acpi/executer/exmisc.c +++ b/drivers/acpi/executer/exmisc.c @@ -86,10 +86,10 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, /* * Must be a reference to a Local or Arg */ - switch (obj_desc->reference.opcode) { - case AML_LOCAL_OP: - case AML_ARG_OP: - case AML_DEBUG_OP: + switch (obj_desc->reference.class) { + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: + case ACPI_REFCLASS_DEBUG: /* The referenced object is the pseudo-node for the local/arg */ @@ -98,8 +98,8 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, default: - ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X", - obj_desc->reference.opcode)); + ACPI_ERROR((AE_INFO, "Unknown Reference Class %2.2X", + obj_desc->reference.class)); return_ACPI_STATUS(AE_AML_INTERNAL); } break; @@ -127,7 +127,7 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_NO_MEMORY); } - reference_obj->reference.opcode = AML_REF_OF_OP; + reference_obj->reference.class = ACPI_REFCLASS_REFOF; reference_obj->reference.object = referenced_obj; *return_desc = reference_obj; diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index 7c3bea575e02..f622f9eac8a1 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c @@ -825,16 +825,16 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) * * Must resolve/dereference the local/arg reference first */ - switch (operand[0]->reference.opcode) { - case AML_LOCAL_OP: - case AML_ARG_OP: + switch (operand[0]->reference.class) { + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: /* Set Operand[0] to the value of the local/arg */ status = acpi_ds_method_data_get_value - (operand[0]->reference.opcode, - operand[0]->reference.offset, + (operand[0]->reference.class, + operand[0]->reference.value, walk_state, &temp_desc); if (ACPI_FAILURE(status)) { goto cleanup; @@ -848,7 +848,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) operand[0] = temp_desc; break; - case AML_REF_OF_OP: + case ACPI_REFCLASS_REFOF: /* Get the object to which the reference refers */ @@ -928,8 +928,8 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) * This must be a reference object produced by either the * Index() or ref_of() operator */ - switch (operand[0]->reference.opcode) { - case AML_INDEX_OP: + switch (operand[0]->reference.class) { + case ACPI_REFCLASS_INDEX: /* * The target type for the Index operator must be @@ -965,7 +965,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) return_desc->integer.value = temp_desc->buffer. pointer[operand[0]->reference. - offset]; + value]; break; case ACPI_TYPE_PACKAGE: @@ -985,7 +985,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) default: ACPI_ERROR((AE_INFO, - "Unknown Index TargetType %X in obj %p", + "Unknown Index TargetType %X in reference object %p", operand[0]->reference. target_type, operand[0])); status = AE_AML_OPERAND_TYPE; @@ -993,7 +993,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) } break; - case AML_REF_OF_OP: + case ACPI_REFCLASS_REFOF: return_desc = operand[0]->reference.object; @@ -1013,9 +1013,9 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) default: ACPI_ERROR((AE_INFO, - "Unknown opcode in reference(%p) - %X", + "Unknown class in reference(%p) - %2.2X", operand[0], - operand[0]->reference.opcode)); + operand[0]->reference.class)); status = AE_TYPE; goto cleanup; diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c index 8e8bbb6ccebd..368def5dffce 100644 --- a/drivers/acpi/executer/exoparg2.c +++ b/drivers/acpi/executer/exoparg2.c @@ -391,8 +391,8 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) /* Initialize the Index reference object */ index = operand[1]->integer.value; - return_desc->reference.offset = (u32) index; - return_desc->reference.opcode = AML_INDEX_OP; + return_desc->reference.value = (u32) index; + return_desc->reference.class = ACPI_REFCLASS_INDEX; /* * At this point, the Source operand is a String, Buffer, or Package. diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c index 5596f42c9676..423ad3635f3d 100644 --- a/drivers/acpi/executer/exresnte.c +++ b/drivers/acpi/executer/exresnte.c @@ -46,8 +46,6 @@ #include #include #include -#include -#include #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exresnte") @@ -238,10 +236,10 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_LOCAL_REFERENCE: - switch (source_desc->reference.opcode) { - case AML_LOAD_OP: /* This is a ddb_handle */ - case AML_REF_OF_OP: - case AML_INDEX_OP: + switch (source_desc->reference.class) { + case ACPI_REFCLASS_TABLE: /* This is a ddb_handle */ + case ACPI_REFCLASS_REFOF: + case ACPI_REFCLASS_INDEX: /* Return an additional reference to the object */ @@ -253,10 +251,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, /* No named references are allowed here */ ACPI_ERROR((AE_INFO, - "Unsupported Reference opcode %X (%s)", - source_desc->reference.opcode, - acpi_ps_get_opcode_name(source_desc-> - reference.opcode))); + "Unsupported Reference type %X", + source_desc->reference.class)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index b35f7c817acf..89571b92a522 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c @@ -47,7 +47,6 @@ #include #include #include -#include #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exresolv") @@ -141,7 +140,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, acpi_status status = AE_OK; union acpi_operand_object *stack_desc; union acpi_operand_object *obj_desc = NULL; - u16 opcode; + u8 ref_type; ACPI_FUNCTION_TRACE(ex_resolve_object_to_value); @@ -152,19 +151,19 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, switch (ACPI_GET_OBJECT_TYPE(stack_desc)) { case ACPI_TYPE_LOCAL_REFERENCE: - opcode = stack_desc->reference.opcode; + ref_type = stack_desc->reference.class; - switch (opcode) { - case AML_LOCAL_OP: - case AML_ARG_OP: + switch (ref_type) { + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: /* * Get the local from the method's state info * Note: this increments the local's object reference count */ - status = acpi_ds_method_data_get_value(opcode, + status = acpi_ds_method_data_get_value(ref_type, stack_desc-> - reference.offset, + reference.value, walk_state, &obj_desc); if (ACPI_FAILURE(status)) { @@ -173,7 +172,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[Arg/Local %X] ValueObj is %p\n", - stack_desc->reference.offset, + stack_desc->reference.value, obj_desc)); /* @@ -184,7 +183,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, *stack_ptr = obj_desc; break; - case AML_INDEX_OP: + case ACPI_REFCLASS_INDEX: switch (stack_desc->reference.target_type) { case ACPI_TYPE_BUFFER_FIELD: @@ -239,15 +238,15 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, } break; - case AML_REF_OF_OP: - case AML_DEBUG_OP: - case AML_LOAD_OP: + case ACPI_REFCLASS_REFOF: + case ACPI_REFCLASS_DEBUG: + case ACPI_REFCLASS_TABLE: /* Just leave the object as-is, do not dereference */ break; - case AML_INT_NAMEPATH_OP: /* Reference to a named object */ + case ACPI_REFCLASS_NAME: /* Reference to a named object */ /* Dereference the name */ @@ -273,8 +272,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, default: ACPI_ERROR((AE_INFO, - "Unknown Reference opcode %X (%s) in %p", - opcode, acpi_ps_get_opcode_name(opcode), + "Unknown Reference type %X in %p", ref_type, stack_desc)); status = AE_AML_INTERNAL; break; @@ -388,13 +386,13 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, * traversing the list of possibly many nested references. */ while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) { - switch (obj_desc->reference.opcode) { - case AML_REF_OF_OP: - case AML_INT_NAMEPATH_OP: + switch (obj_desc->reference.class) { + case ACPI_REFCLASS_REFOF: + case ACPI_REFCLASS_NAME: /* Dereference the reference pointer */ - if (obj_desc->reference.opcode == AML_REF_OF_OP) { + if (obj_desc->reference.class == ACPI_REFCLASS_REFOF) { node = obj_desc->reference.object; } else { /* AML_INT_NAMEPATH_OP */ @@ -429,7 +427,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, } break; - case AML_INDEX_OP: + case ACPI_REFCLASS_INDEX: /* Get the type of this reference (index into another object) */ @@ -455,22 +453,22 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, } break; - case AML_LOAD_OP: + case ACPI_REFCLASS_TABLE: type = ACPI_TYPE_DDB_HANDLE; goto exit; - case AML_LOCAL_OP: - case AML_ARG_OP: + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: if (return_desc) { status = acpi_ds_method_data_get_value(obj_desc-> reference. - opcode, + class, obj_desc-> reference. - offset, + value, walk_state, &obj_desc); if (ACPI_FAILURE(status)) { @@ -481,10 +479,10 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, status = acpi_ds_method_data_get_node(obj_desc-> reference. - opcode, + class, obj_desc-> reference. - offset, + value, walk_state, &node); if (ACPI_FAILURE(status)) { @@ -499,7 +497,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, } break; - case AML_DEBUG_OP: + case ACPI_REFCLASS_DEBUG: /* The Debug Object is of type "DebugObject" */ @@ -509,8 +507,8 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, default: ACPI_ERROR((AE_INFO, - "Unknown Reference subtype %X", - obj_desc->reference.opcode)); + "Unknown Reference Class %2.2X", + obj_desc->reference.class)); return_ACPI_STATUS(AE_AML_INTERNAL); } } diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c index 54085f16ec28..0bb82593da72 100644 --- a/drivers/acpi/executer/exresop.c +++ b/drivers/acpi/executer/exresop.c @@ -225,41 +225,36 @@ acpi_ex_resolve_operands(u16 opcode, if (object_type == (u8) ACPI_TYPE_LOCAL_REFERENCE) { - /* Decode the Reference */ + /* Validate the Reference */ - op_info = acpi_ps_get_opcode_info(opcode); - if (op_info->class == AML_CLASS_UNKNOWN) { - return_ACPI_STATUS(AE_AML_BAD_OPCODE); - } + switch (obj_desc->reference.class) { + case ACPI_REFCLASS_DEBUG: - switch (obj_desc->reference.opcode) { - case AML_DEBUG_OP: target_op = AML_DEBUG_OP; /*lint -fallthrough */ - case AML_INDEX_OP: - case AML_REF_OF_OP: - case AML_ARG_OP: - case AML_LOCAL_OP: - case AML_LOAD_OP: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */ - case AML_INT_NAMEPATH_OP: /* Reference to a named object */ - - ACPI_DEBUG_ONLY_MEMBERS(ACPI_DEBUG_PRINT - ((ACPI_DB_EXEC, - "Operand is a Reference, RefOpcode [%s]\n", - (acpi_ps_get_opcode_info - (obj_desc-> - reference. - opcode))-> - name))); + case ACPI_REFCLASS_ARG: + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_INDEX: + case ACPI_REFCLASS_REFOF: + case ACPI_REFCLASS_TABLE: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */ + case ACPI_REFCLASS_NAME: /* Reference to a named object */ + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Operand is a Reference, Class [%s] %2.2X\n", + acpi_ut_get_reference_name + (obj_desc), + obj_desc->reference. + class)); break; default: + ACPI_ERROR((AE_INFO, - "Operand is a Reference, Unknown Reference Opcode: %X", - obj_desc->reference. - opcode)); + "Unknown Reference Class %2.2X in %p", + obj_desc->reference.class, + obj_desc)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -270,8 +265,7 @@ acpi_ex_resolve_operands(u16 opcode, /* Invalid descriptor */ - ACPI_ERROR((AE_INFO, - "Invalid descriptor %p [%s]", + ACPI_ERROR((AE_INFO, "Invalid descriptor %p [%s]", obj_desc, acpi_ut_get_descriptor_name(obj_desc))); @@ -343,7 +337,7 @@ acpi_ex_resolve_operands(u16 opcode, if ((opcode == AML_STORE_OP) && (ACPI_GET_OBJECT_TYPE(*stack_ptr) == ACPI_TYPE_LOCAL_REFERENCE) - && ((*stack_ptr)->reference.opcode == AML_INDEX_OP)) { + && ((*stack_ptr)->reference.class == ACPI_REFCLASS_INDEX)) { goto next_operand; } break; diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index 20b4893e06ed..3318df4cbd98 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -47,7 +47,6 @@ #include #include #include -#include #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exstore") @@ -179,23 +178,27 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, case ACPI_TYPE_LOCAL_REFERENCE: - if (source_desc->reference.opcode == AML_INDEX_OP) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - "[%s, 0x%X]\n", - acpi_ps_get_opcode_name - (source_desc->reference.opcode), - source_desc->reference.offset)); - } else { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]", - acpi_ps_get_opcode_name - (source_desc->reference.opcode))); - } + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s] ", + acpi_ut_get_reference_name(source_desc))); + + /* Decode the reference */ + + switch (source_desc->reference.class) { + case ACPI_REFCLASS_INDEX: + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%X\n", + source_desc->reference.value)); + break; + + case ACPI_REFCLASS_TABLE: - if (source_desc->reference.opcode == AML_LOAD_OP) { /* Load and load_table */ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - " Table Index %X\n", + "Table Index 0x%X\n", source_desc->reference.value)); break; + + default: + break; } ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, " ")); @@ -347,15 +350,15 @@ acpi_ex_store(union acpi_operand_object *source_desc, } /* - * Examine the Reference opcode. These cases are handled: + * Examine the Reference class. These cases are handled: * * 1) Store to Name (Change the object associated with a name) * 2) Store to an indexed area of a Buffer or Package * 3) Store to a Method Local or Arg * 4) Store to the debug object */ - switch (ref_desc->reference.opcode) { - case AML_REF_OF_OP: + switch (ref_desc->reference.class) { + case ACPI_REFCLASS_REFOF: /* Storing an object into a Name "container" */ @@ -365,7 +368,7 @@ acpi_ex_store(union acpi_operand_object *source_desc, ACPI_IMPLICIT_CONVERSION); break; - case AML_INDEX_OP: + case ACPI_REFCLASS_INDEX: /* Storing to an Index (pointer into a packager or buffer) */ @@ -374,18 +377,18 @@ acpi_ex_store(union acpi_operand_object *source_desc, walk_state); break; - case AML_LOCAL_OP: - case AML_ARG_OP: + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: /* Store to a method local/arg */ status = - acpi_ds_store_object_to_local(ref_desc->reference.opcode, - ref_desc->reference.offset, + acpi_ds_store_object_to_local(ref_desc->reference.class, + ref_desc->reference.value, source_desc, walk_state); break; - case AML_DEBUG_OP: + case ACPI_REFCLASS_DEBUG: /* * Storing to the Debug object causes the value stored to be @@ -401,8 +404,8 @@ acpi_ex_store(union acpi_operand_object *source_desc, default: - ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X", - ref_desc->reference.opcode)); + ACPI_ERROR((AE_INFO, "Unknown Reference Class %2.2X", + ref_desc->reference.class)); ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_INFO); status = AE_AML_INTERNAL; @@ -458,7 +461,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, if (ACPI_GET_OBJECT_TYPE(source_desc) == ACPI_TYPE_LOCAL_REFERENCE - && source_desc->reference.opcode == AML_LOAD_OP) { + && source_desc->reference.class == ACPI_REFCLASS_TABLE) { /* This is a DDBHandle, just add a reference to it */ @@ -553,7 +556,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, /* Store the source value into the target buffer byte */ - obj_desc->buffer.pointer[index_desc->reference.offset] = value; + obj_desc->buffer.pointer[index_desc->reference.value] = value; break; default: diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c index a6d2168b81f9..eef61a00803e 100644 --- a/drivers/acpi/executer/exstoren.c +++ b/drivers/acpi/executer/exstoren.c @@ -121,7 +121,8 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) && !((ACPI_GET_OBJECT_TYPE(source_desc) == ACPI_TYPE_LOCAL_REFERENCE) - && (source_desc->reference.opcode == AML_LOAD_OP))) { + && (source_desc->reference.class == + ACPI_REFCLASS_TABLE))) { /* Conversion successful but still not a valid type */ diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c index 0ab22004728a..cc0ae39440e4 100644 --- a/drivers/acpi/namespace/nsdump.c +++ b/drivers/acpi/namespace/nsdump.c @@ -43,7 +43,6 @@ #include #include -#include #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsdump") @@ -334,9 +333,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, case ACPI_TYPE_LOCAL_REFERENCE: acpi_os_printf("[%s]\n", - acpi_ps_get_opcode_name(obj_desc-> - reference. - opcode)); + acpi_ut_get_reference_name(obj_desc)); break; case ACPI_TYPE_BUFFER_FIELD: diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index f3cc37624537..a085cc39c055 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -45,7 +45,6 @@ #include #include #include -#include #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsxfeval") @@ -399,13 +398,13 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info) * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to * an union acpi_object. */ - switch (info->return_object->reference.opcode) { - case AML_INDEX_OP: + switch (info->return_object->reference.class) { + case ACPI_REFCLASS_INDEX: obj_desc = *(info->return_object->reference.where); break; - case AML_REF_OF_OP: + case ACPI_REFCLASS_REFOF: node = info->return_object->reference.object; if (node) { diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index d9063ea414e3..8eaaecf92009 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -43,7 +43,6 @@ #include #include -#include #include #define _COMPONENT ACPI_RESOURCES @@ -560,8 +559,8 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, ACPI_GET_OBJECT_TYPE(*sub_object_list)) || ((ACPI_TYPE_LOCAL_REFERENCE == ACPI_GET_OBJECT_TYPE(*sub_object_list)) && - ((*sub_object_list)->reference.opcode == - AML_INT_NAMEPATH_OP)))) { + ((*sub_object_list)->reference.class == + ACPI_REFCLASS_NAME)))) { name_found = TRUE; } else { /* Look at the next element */ diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c index 7804a8c40e7a..c0bbfa2c4193 100644 --- a/drivers/acpi/resources/rscreate.c +++ b/drivers/acpi/resources/rscreate.c @@ -43,7 +43,6 @@ #include #include -#include #include #define _COMPONENT ACPI_RESOURCES @@ -310,13 +309,12 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_LOCAL_REFERENCE: - if (obj_desc->reference.opcode != - AML_INT_NAMEPATH_OP) { + if (obj_desc->reference.class != + ACPI_REFCLASS_NAME) { ACPI_ERROR((AE_INFO, - "(PRT[%X].Source) Need name, found reference op %X", + "(PRT[%X].Source) Need name, found Reference Class %X", index, - obj_desc->reference. - opcode)); + obj_desc->reference.class)); return_ACPI_STATUS(AE_BAD_DATA); } diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index 53499ac90988..5b2f7c27b705 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c @@ -42,7 +42,6 @@ */ #include -#include #include @@ -176,20 +175,24 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, /* This is an object reference. */ - switch (internal_object->reference.opcode) { - case AML_INT_NAMEPATH_OP: - - /* For namepath, return the object handle ("reference") */ - - default: - - /* We are referring to the namespace node */ + switch (internal_object->reference.class) { + case ACPI_REFCLASS_NAME: + /* + * For namepath, return the object handle ("reference") + * We are referring to the namespace node + */ external_object->reference.handle = internal_object->reference.node; external_object->reference.actual_type = acpi_ns_get_type(internal_object->reference.node); break; + + default: + + /* All other reference types are unsupported */ + + return_ACPI_STATUS(AE_TYPE); } break; @@ -533,7 +536,7 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, /* TBD: should validate incoming handle */ - internal_object->reference.opcode = AML_INT_NAMEPATH_OP; + internal_object->reference.class = ACPI_REFCLASS_NAME; internal_object->reference.node = external_object->reference.handle; break; @@ -743,11 +746,11 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, * We copied the reference object, so we now must add a reference * to the object pointed to by the reference * - * DDBHandle reference (from Load/load_table is a special reference, - * it's Reference.Object is the table index, so does not need to + * DDBHandle reference (from Load/load_table) is a special reference, + * it does not have a Reference.Object, so does not need to * increase the reference count */ - if (source_desc->reference.opcode == AML_LOAD_OP) { + if (source_desc->reference.class == ACPI_REFCLASS_TABLE) { break; } diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index 42609d3a8aa9..5c219758c226 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -45,7 +45,6 @@ #include #include #include -#include #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utdelete") @@ -548,8 +547,8 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) * reference must track changes to the ref count of the index or * target object. */ - if ((object->reference.opcode == AML_INDEX_OP) || - (object->reference.opcode == AML_INT_NAMEPATH_OP)) { + if ((object->reference.class == ACPI_REFCLASS_INDEX) || + (object->reference.class == ACPI_REFCLASS_NAME)) { next_object = object->reference.object; } break; diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index bcace577183b..0b1e493a8374 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -45,7 +45,6 @@ #include #include -#include ACPI_EXPORT_SYMBOL(acpi_gbl_FADT) #define _COMPONENT ACPI_UTILITIES @@ -590,25 +589,31 @@ char *acpi_ut_get_descriptor_name(void *object) /* Printable names of reference object sub-types */ +static const char *acpi_gbl_ref_class_names[] = { + /* 00 */ "Local", + /* 01 */ "Argument", + /* 02 */ "RefOf", + /* 03 */ "Index", + /* 04 */ "DdbHandle", + /* 05 */ "Named Object", + /* 06 */ "Debug" +}; + const char *acpi_ut_get_reference_name(union acpi_operand_object *object) { + if (!object) + return "NULL Object"; - switch (object->reference.opcode) { - case AML_INT_NAMEPATH_OP: - return "Name"; + if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) + return "Not an Operand object"; - case AML_LOAD_OP: - return "DDB-Handle"; + if (object->common.type != ACPI_TYPE_LOCAL_REFERENCE) + return "Not a Reference object"; - case AML_REF_OF_OP: - return "RefOf"; + if (object->reference.class > ACPI_REFCLASS_MAX) + return "Unknown Reference class"; - case AML_INDEX_OP: - return "Index"; - - default: - return "Unknown"; - } + return acpi_gbl_ref_class_names[object->reference.class]; } #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) @@ -812,4 +817,4 @@ acpi_status acpi_ut_init_globals(void) } ACPI_EXPORT_SYMBOL(acpi_dbg_level) - ACPI_EXPORT_SYMBOL(acpi_dbg_layer) +ACPI_EXPORT_SYMBOL(acpi_dbg_layer) diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index 924d05af94d2..c354e7a42bcd 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c @@ -43,7 +43,6 @@ #include #include -#include #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utobject") @@ -478,8 +477,8 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, case ACPI_TYPE_LOCAL_REFERENCE: - switch (internal_object->reference.opcode) { - case AML_INT_NAMEPATH_OP: + switch (internal_object->reference.class) { + case ACPI_REFCLASS_NAME: /* * Get the actual length of the full pathname to this object. @@ -504,9 +503,9 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, */ ACPI_ERROR((AE_INFO, "Cannot convert to external object - " - "unsupported Reference type [%s] %X in object %p", + "unsupported Reference Class [%s] %X in object %p", acpi_ut_get_reference_name(internal_object), - internal_object->reference.opcode, + internal_object->reference.class, internal_object)); status = AE_TYPE; break; -- cgit v1.2.3 From 393a75d6b7bae59221b2122634eb4cb905e84208 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Sat, 27 Sep 2008 11:12:36 +0800 Subject: ACPICA: Fix possible memory leak in acpi_ns_get_external_pathname Fixes a memory leak in the error exit path. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/namespace/nsnames.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c index bd5773878009..9c587bdfe3f3 100644 --- a/drivers/acpi/namespace/nsnames.c +++ b/drivers/acpi/namespace/nsnames.c @@ -142,7 +142,7 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) size = acpi_ns_get_pathname_length(node); if (!size) { - return (NULL); + return_PTR(NULL); } /* Allocate a buffer to be returned to caller */ @@ -157,7 +157,8 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) status = acpi_ns_build_external_path(node, size, name_buffer); if (ACPI_FAILURE(status)) { - return (NULL); + ACPI_FREE(name_buffer); + return_PTR(NULL); } return_PTR(name_buffer); -- cgit v1.2.3 From bbbbeb8e31af97f11b84294b2e7e5607125829d2 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Sat, 27 Sep 2008 11:26:59 +0800 Subject: ACPICA: Remove unused ACPI register bit definition Removed the ACPI_BITREG_WAKE_ENABLE definition and entry in the global register table. This bit does not exist and is unused. http://www.acpica.org/bugzilla/show_bug.cgi?id=442 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/utilities/utglobal.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index 0b1e493a8374..670551b95e56 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -281,7 +281,6 @@ struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG] = { /* ACPI_BITREG_RT_CLOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_ENABLE}, - /* ACPI_BITREG_WAKE_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, 0, 0}, /* ACPI_BITREG_PCIEXP_WAKE_DISABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE, ACPI_BITMASK_PCIEXP_WAKE_DISABLE}, -- cgit v1.2.3 From c35def2118d3d7cceb0f69d6707f613a7473df15 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Sat, 27 Sep 2008 11:28:46 +0800 Subject: ACPICA: Fix fault after mem allocation failure in AML parser Fixes a crash if a memory allocation fails during the Op completion routine acpi_ps_complete_this_op(). http://www.acpica.org/bugzilla/show_bug.cgi?id=492 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/parser/psparse.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index 15e1702e48d6..52caaf6582e7 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -137,6 +137,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, union acpi_parse_object *next; const struct acpi_opcode_info *parent_info; union acpi_parse_object *replacement_op = NULL; + acpi_status status = AE_OK; ACPI_FUNCTION_TRACE_PTR(ps_complete_this_op, op); @@ -186,7 +187,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, replacement_op = acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); if (!replacement_op) { - goto allocate_error; + status = AE_NO_MEMORY; } break; @@ -211,7 +212,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, replacement_op = acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); if (!replacement_op) { - goto allocate_error; + status = AE_NO_MEMORY; } } else if ((op->common.parent->common.aml_opcode == @@ -226,13 +227,13 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, acpi_ps_alloc_op(op->common. aml_opcode); if (!replacement_op) { - goto allocate_error; + status = AE_NO_MEMORY; + } else { + replacement_op->named.data = + op->named.data; + replacement_op->named.length = + op->named.length; } - - replacement_op->named.data = - op->named.data; - replacement_op->named.length = - op->named.length; } } break; @@ -242,7 +243,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, replacement_op = acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); if (!replacement_op) { - goto allocate_error; + status = AE_NO_MEMORY; } } @@ -302,14 +303,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, /* Now we can actually delete the subtree rooted at Op */ acpi_ps_delete_parse_tree(op); - return_ACPI_STATUS(AE_OK); - - allocate_error: - - /* Always delete the subtree, even on error */ - - acpi_ps_delete_parse_tree(op); - return_ACPI_STATUS(AE_NO_MEMORY); + return_ACPI_STATUS(status); } /******************************************************************************* -- cgit v1.2.3 From cf058bd1c84df9921ecc517d8a8a413f4d6b5b45 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Sat, 27 Sep 2008 11:29:57 +0800 Subject: ACPICA: Fix possible memory leak, error exit path Fixed two possible memory leaks in the error exit paths of acpi_ut_update_objerct_reference() and acpi_ut_walk_package_tree() These functions are similar in that they use a stack of state objects in order to eliminate recursion. The stack must be fully deallocated if an error occurs. http://www.acpica.org/bugzilla/show_bug.cgi?id=383 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/utilities/utdelete.c | 7 +++++++ drivers/acpi/utilities/utmisc.c | 9 +++++++++ 2 files changed, 16 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index 5c219758c226..d197c6b29e17 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -585,6 +585,13 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) ACPI_EXCEPTION((AE_INFO, status, "Could not update object reference count")); + /* Free any stacked Update State objects */ + + while (state_list) { + state = acpi_ut_pop_generic_state(&state_list); + acpi_ut_delete_generic_state(state); + } + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index f34be6773556..9089a158a874 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -995,6 +995,15 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object, state->pkg. this_target_obj, 0); if (!state) { + + /* Free any stacked Update State objects */ + + while (state_list) { + state = + acpi_ut_pop_generic_state + (&state_list); + acpi_ut_delete_generic_state(state); + } return_ACPI_STATUS(AE_NO_MEMORY); } } -- cgit v1.2.3 From 68e125c40597802b9789bc696775bf0246e7667d Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Sat, 27 Sep 2008 11:34:48 +0800 Subject: ACPICA: Optimize buffer allocation procedure Eliminate duplicate code. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/utilities/utalloc.c | 53 +++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 25 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c index 7dcb67e0b215..241c535c1753 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c @@ -232,7 +232,7 @@ acpi_status acpi_ut_validate_buffer(struct acpi_buffer * buffer) * RETURN: Status * * DESCRIPTION: Validate that the buffer is of the required length or - * allocate a new buffer. Returned buffer is always zeroed. + * allocate a new buffer. Returned buffer is always zeroed. * ******************************************************************************/ @@ -240,7 +240,7 @@ acpi_status acpi_ut_initialize_buffer(struct acpi_buffer * buffer, acpi_size required_length) { - acpi_status status = AE_OK; + acpi_size input_buffer_length; /* Parameter validation */ @@ -248,55 +248,58 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer, return (AE_BAD_PARAMETER); } - switch (buffer->length) { + /* + * Buffer->Length is used as both an input and output parameter. Get the + * input actual length and set the output required buffer length. + */ + input_buffer_length = buffer->length; + buffer->length = required_length; + + /* + * The input buffer length contains the actual buffer length, or the type + * of buffer to be allocated by this routine. + */ + switch (input_buffer_length) { case ACPI_NO_BUFFER: - /* Set the exception and returned the required length */ + /* Return the exception (and the required buffer length) */ - status = AE_BUFFER_OVERFLOW; - break; + return (AE_BUFFER_OVERFLOW); case ACPI_ALLOCATE_BUFFER: /* Allocate a new buffer */ buffer->pointer = acpi_os_allocate(required_length); - if (!buffer->pointer) { - return (AE_NO_MEMORY); - } - - /* Clear the buffer */ - - ACPI_MEMSET(buffer->pointer, 0, required_length); break; case ACPI_ALLOCATE_LOCAL_BUFFER: /* Allocate a new buffer with local interface to allow tracking */ - buffer->pointer = ACPI_ALLOCATE_ZEROED(required_length); - if (!buffer->pointer) { - return (AE_NO_MEMORY); - } + buffer->pointer = ACPI_ALLOCATE(required_length); break; default: /* Existing buffer: Validate the size of the buffer */ - if (buffer->length < required_length) { - status = AE_BUFFER_OVERFLOW; - break; + if (input_buffer_length < required_length) { + return (AE_BUFFER_OVERFLOW); } + break; + } - /* Clear the buffer */ + /* Validate allocation from above or input buffer pointer */ - ACPI_MEMSET(buffer->pointer, 0, required_length); - break; + if (!buffer->pointer) { + return (AE_NO_MEMORY); } - buffer->length = required_length; - return (status); + /* Have a valid buffer, clear it */ + + ACPI_MEMSET(buffer->pointer, 0, required_length); + return (AE_OK); } #ifdef NOT_USED_BY_LINUX -- cgit v1.2.3 From d8a0ec914afa1a994d2f6184ac4c6668b5f8068f Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Sat, 27 Sep 2008 11:50:24 +0800 Subject: ACPICA: Fixed a couple memory leaks associated with "implicit return" Fixed a couple memory leaks associated with "implicit return" objects when the AML Interpreter slack mode is enabled. http://www.acpica.org/bugzilla/show_bug.cgi?id=349 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsmethod.c | 3 +++ drivers/acpi/parser/psparse.c | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 4613b9ca5792..279a5a60a0dd 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -103,6 +103,9 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state) NULL); acpi_ex_enter_interpreter(); } + + acpi_ds_clear_implicit_return(walk_state); + #ifdef ACPI_DISASSEMBLER if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index 52caaf6582e7..68e932f215ea 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -635,10 +635,12 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) ACPI_WALK_METHOD_RESTART; } } else { - /* On error, delete any return object */ + /* On error, delete any return object or implicit return */ acpi_ut_remove_reference(previous_walk_state-> return_desc); + acpi_ds_clear_implicit_return + (previous_walk_state); } } -- cgit v1.2.3 From b9d1312ad4246e467f333dfe2ac4dc7a79608d59 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Sat, 27 Sep 2008 12:01:12 +0800 Subject: ACPICA: Fix for implicit return compatibility Predicate can be used for an implicit return value. This change improves the implicit return mechanism to be more compatible with the MS interpreter. http://www.acpica.org/bugzilla/show_bug.cgi?id=349 Below AML code from http://bugzilla.kernel.org/show_bug.cgi?id=10686 Store(0x07D6, OSYS) Method (_CRT, 0, Serialized) { If (LLess (OSYS, 0x07D6)) { If (LEqual (\_SB.TJ85, Zero)) { Return (Add (0x0AAC, Multiply (TPC, 0x0A))) } Else { Return (Add (0x0AAC, Multiply (TP85, 0x0A))) } } } Previously _CRT returns 0x07D6, now it returns 0 (predicate value of LLess) Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dswexec.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index 5b2419197b9b..396fe12078cd 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -166,6 +166,10 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, status = AE_CTRL_FALSE; } + /* Predicate can be used for an implicit return value */ + + (void)acpi_ds_do_implicit_return(local_obj_desc, walk_state, TRUE); + cleanup: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n", -- cgit v1.2.3 From e8707b340fb5b6313cde784b944a568dfd770ddd Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Sun, 28 Sep 2008 15:26:17 +0800 Subject: ACPICA: New: Validation for predefined ACPI methods/objects Validates predefined ACPI objects that appear in the namespace, at the time they are evaluated. The argument count and the type of the returned object are validated. The purpose of this validation is to detect problems with the BIOS-exposed predefined ACPI objects before the results are returned to the ACPI-related drivers. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/namespace/Makefile | 2 +- drivers/acpi/namespace/nseval.c | 35 +- drivers/acpi/namespace/nsnames.c | 2 - drivers/acpi/namespace/nspredef.c | 900 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 933 insertions(+), 6 deletions(-) create mode 100644 drivers/acpi/namespace/nspredef.c (limited to 'drivers/acpi') diff --git a/drivers/acpi/namespace/Makefile b/drivers/acpi/namespace/Makefile index 3f63d3640696..371a2daf837f 100644 --- a/drivers/acpi/namespace/Makefile +++ b/drivers/acpi/namespace/Makefile @@ -5,7 +5,7 @@ obj-y := nsaccess.o nsload.o nssearch.o nsxfeval.o \ nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \ nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \ - nsparse.o + nsparse.o nspredef.o obj-$(ACPI_FUTURE_USAGE) += nsdumpdv.o diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index 42dae12f2ef8..4cdf03ac2b46 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c @@ -78,6 +78,7 @@ ACPI_MODULE_NAME("nseval") acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) { acpi_status status; + struct acpi_namespace_node *node; ACPI_FUNCTION_TRACE(ns_evaluate); @@ -117,6 +118,8 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) info->resolved_node, acpi_ns_get_attached_object(info->resolved_node))); + node = info->resolved_node; + /* * Two major cases here: * @@ -261,9 +264,35 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) } } - /* - * Check if there is a return value that must be dealt with - */ + /* Validation of return values for ACPI-predefined methods and objects */ + + if ((status == AE_OK) || (status == AE_CTRL_RETURN_VALUE)) { + /* + * If this is the first evaluation, check the return value. This + * ensures that any warnings will only be emitted during the very + * first evaluation of the object. + */ + if (!(node->flags & ANOBJ_EVALUATED)) { + /* + * Check for a predefined ACPI name. If found, validate the + * returned object. + * + * Note: Ignore return status for now, emit warnings if there are + * problems with the returned object. May change later to abort + * the method on invalid return object. + */ + (void)acpi_ns_check_predefined_names(node, + info-> + return_object); + } + + /* Mark the node as having been evaluated */ + + node->flags |= ANOBJ_EVALUATED; + } + + /* Check if there is a return value that must be dealt with */ + if (status == AE_CTRL_RETURN_VALUE) { /* If caller does not want the return value, delete it */ diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c index 9c587bdfe3f3..42a39a7c96e9 100644 --- a/drivers/acpi/namespace/nsnames.c +++ b/drivers/acpi/namespace/nsnames.c @@ -115,7 +115,6 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node, return (AE_OK); } -#ifdef ACPI_DEBUG_OUTPUT /******************************************************************************* * * FUNCTION: acpi_ns_get_external_pathname @@ -163,7 +162,6 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) return_PTR(name_buffer); } -#endif /******************************************************************************* * diff --git a/drivers/acpi/namespace/nspredef.c b/drivers/acpi/namespace/nspredef.c new file mode 100644 index 000000000000..0f17cf0898c9 --- /dev/null +++ b/drivers/acpi/namespace/nspredef.c @@ -0,0 +1,900 @@ +/****************************************************************************** + * + * Module Name: nspredef - Validation of ACPI predefined methods and objects + * $Revision: 1.1 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nspredef") + +/******************************************************************************* + * + * This module validates predefined ACPI objects that appear in the namespace, + * at the time they are evaluated (via acpi_evaluate_object). The purpose of this + * validation is to detect problems with BIOS-exposed predefined ACPI objects + * before the results are returned to the ACPI-related drivers. + * + * There are several areas that are validated: + * + * 1) The number of input arguments as defined by the method/object in the + * ASL is validated against the ACPI specification. + * 2) The type of the return object (if any) is validated against the ACPI + * specification. + * 3) For returned package objects, the count of package elements is + * validated, as well as the type of each package element. Nested + * packages are supported. + * + * For any problems found, a warning message is issued. + * + ******************************************************************************/ +/* Local prototypes */ +static acpi_status +acpi_ns_check_package(char *pathname, + union acpi_operand_object *return_object, + const union acpi_predefined_info *predefined); + +static acpi_status +acpi_ns_check_package_elements(char *pathname, + union acpi_operand_object **elements, + u8 type1, u32 count1, u8 type2, u32 count2); + +static acpi_status +acpi_ns_check_object_type(char *pathname, + union acpi_operand_object *return_object, + u32 expected_btypes, u32 package_index); + +static acpi_status +acpi_ns_check_reference(char *pathname, + union acpi_operand_object *return_object); + +/* + * Names for the types that can be returned by the predefined objects. + * Used for warning messages. Must be in the same order as the ACPI_RTYPEs + */ +static const char *acpi_rtype_names[] = { + "/Integer", + "/String", + "/Buffer", + "/Package", + "/Reference", +}; + +#define ACPI_NOT_PACKAGE ACPI_UINT32_MAX + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_predefined_names + * + * PARAMETERS: Node - Namespace node for the method/object + * return_object - Object returned from the evaluation of this + * method/object + * + * RETURN: Status + * + * DESCRIPTION: Check an ACPI name for a match in the predefined name list. + * + ******************************************************************************/ + +acpi_status +acpi_ns_check_predefined_names(struct acpi_namespace_node *node, + union acpi_operand_object *return_object) +{ + acpi_status status = AE_OK; + const union acpi_predefined_info *predefined; + char *pathname; + + /* Match the name for this method/object against the predefined list */ + + predefined = acpi_ns_check_for_predefined_name(node); + if (!predefined) { + + /* Name was not one of the predefined names */ + + return (AE_OK); + } + + /* Get the full pathname to the object, for use in error messages */ + + pathname = acpi_ns_get_external_pathname(node); + if (!pathname) { + pathname = ACPI_CAST_PTR(char, predefined->info.name); + } + + /* + * Check that the parameter count for this method is in accordance + * with the ACPI specification. + */ + acpi_ns_check_parameter_count(pathname, node, predefined); + + /* + * If there is no return value, check if we require a return value for + * this predefined name. Either one return value is expected, or none, + * for both methods and other objects. + * + * Exit now if there is no return object. Warning if one was expected. + */ + if (!return_object) { + if ((predefined->info.expected_btypes) && + (!(predefined->info.expected_btypes & ACPI_RTYPE_NONE))) { + ACPI_ERROR((AE_INFO, + "%s: Missing expected return value", + pathname)); + + status = AE_AML_NO_RETURN_VALUE; + } + goto exit; + } + + /* + * We have a return value, but if one wasn't expected, just exit, this is + * not a problem + * + * For example, if "Implicit return value" is enabled, methods will + * always return a value + */ + if (!predefined->info.expected_btypes) { + goto exit; + } + + /* + * Check that the type of the return object is what is expected for + * this predefined name + */ + status = acpi_ns_check_object_type(pathname, return_object, + predefined->info.expected_btypes, + ACPI_NOT_PACKAGE); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* For returned Package objects, check the type of all sub-objects */ + + if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_PACKAGE) { + status = + acpi_ns_check_package(pathname, return_object, predefined); + } + + exit: + if (pathname) { + ACPI_FREE(pathname); + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_parameter_count + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * Node - Namespace node for the method/object + * Predefined - Pointer to entry in predefined name table + * + * RETURN: None + * + * DESCRIPTION: Check that the declared (in ASL/AML) parameter count for a + * predefined name is what is expected (i.e., what is defined in + * the ACPI specification for this predefined name.) + * + ******************************************************************************/ + +void +acpi_ns_check_parameter_count(char *pathname, + struct acpi_namespace_node *node, + const union acpi_predefined_info *predefined) +{ + u32 param_count; + u32 required_params_current; + u32 required_params_old; + + /* + * Check that the ASL-defined parameter count is what is expected for + * this predefined name. + * + * Methods have 0-7 parameters. All other types have zero. + */ + param_count = 0; + if (node->type == ACPI_TYPE_METHOD) { + param_count = node->object->method.param_count; + } + + /* Validate parameter count - allow two different legal counts (_SCP) */ + + required_params_current = predefined->info.param_count & 0x0F; + required_params_old = predefined->info.param_count >> 4; + + if ((param_count != required_params_current) && + (param_count != required_params_old)) { + ACPI_WARNING((AE_INFO, + "%s: Parameter count mismatch - ASL declared %d, expected %d", + pathname, param_count, required_params_current)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_for_predefined_name + * + * PARAMETERS: Node - Namespace node for the method/object + * + * RETURN: Pointer to entry in predefined table. NULL indicates not found. + * + * DESCRIPTION: Check an object name against the predefined object list. + * + ******************************************************************************/ + +const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct + acpi_namespace_node + *node) +{ + const union acpi_predefined_info *this_name; + + /* Quick check for a predefined name, first character must be underscore */ + + if (node->name.ascii[0] != '_') { + return (NULL); + } + + /* Search info table for a predefined method/object name */ + + this_name = predefined_names; + while (this_name->info.name[0]) { + if (ACPI_COMPARE_NAME(node->name.ascii, this_name->info.name)) { + + /* Return pointer to this table entry */ + + return (this_name); + } + + /* + * Skip next entry in the table if this name returns a Package + * (next entry contains the package info) + */ + if (this_name->info.expected_btypes & ACPI_RTYPE_PACKAGE) { + this_name++; + } + + this_name++; + } + + return (NULL); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_package + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * return_object - Object returned from the evaluation of a + * method or object + * Predefined - Pointer to entry in predefined name table + * + * RETURN: Status + * + * DESCRIPTION: Check a returned package object for the correct count and + * correct type of all sub-objects. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_package(char *pathname, + union acpi_operand_object *return_object, + const union acpi_predefined_info *predefined) +{ + const union acpi_predefined_info *package; + union acpi_operand_object *sub_package; + union acpi_operand_object **elements; + union acpi_operand_object **sub_elements; + acpi_status status; + u32 expected_count; + u32 count; + u32 i; + u32 j; + + ACPI_FUNCTION_NAME(ns_check_package); + + /* The package info for this name is in the next table entry */ + + package = predefined + 1; + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "%s Validating return Package of Type %X, Count %X\n", + pathname, package->ret_info.type, + return_object->package.count)); + + /* Extract package count and elements array */ + + elements = return_object->package.elements; + count = return_object->package.count; + + /* The package must have at least one element, else invalid */ + + if (!count) { + ACPI_WARNING((AE_INFO, + "%s: Return Package has no elements (empty)", + pathname)); + + return (AE_AML_OPERAND_VALUE); + } + + /* + * Decode the type of the expected package contents + * + * PTYPE1 packages contain no subpackages + * PTYPE2 packages contain sub-packages + */ + switch (package->ret_info.type) { + case ACPI_PTYPE1_FIXED: + + /* + * The package count is fixed and there are no sub-packages + * + * If package is too small, exit. + * If package is larger than expected, issue warning but continue + */ + expected_count = + package->ret_info.count1 + package->ret_info.count2; + if (count < expected_count) { + goto package_too_small; + } else if (count > expected_count) { + ACPI_WARNING((AE_INFO, + "%s: Return Package is larger than needed - " + "found %u, expected %u", pathname, count, + expected_count)); + } + + /* Validate all elements of the returned package */ + + status = acpi_ns_check_package_elements(pathname, elements, + package->ret_info. + object_type1, + package->ret_info. + count1, + package->ret_info. + object_type2, + package->ret_info. + count2); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE1_VAR: + + /* + * The package count is variable, there are no sub-packages, and all + * elements must be of the same type + */ + for (i = 0; i < count; i++) { + status = acpi_ns_check_object_type(pathname, *elements, + package->ret_info. + object_type1, i); + if (ACPI_FAILURE(status)) { + return (status); + } + elements++; + } + break; + + case ACPI_PTYPE1_OPTION: + + /* + * The package count is variable, there are no sub-packages. There are + * a fixed number of required elements, and a variable number of + * optional elements. + * + * Check if package is at least as large as the minimum required + */ + expected_count = package->ret_info3.count; + if (count < expected_count) { + goto package_too_small; + } + + /* Variable number of sub-objects */ + + for (i = 0; i < count; i++) { + if (i < package->ret_info3.count) { + + /* These are the required package elements (0, 1, or 2) */ + + status = + acpi_ns_check_object_type(pathname, + *elements, + package-> + ret_info3. + object_type[i], + i); + if (ACPI_FAILURE(status)) { + return (status); + } + } else { + /* These are the optional package elements */ + + status = + acpi_ns_check_object_type(pathname, + *elements, + package-> + ret_info3. + tail_object_type, + i); + if (ACPI_FAILURE(status)) { + return (status); + } + } + elements++; + } + break; + + case ACPI_PTYPE2_PKG_COUNT: + + /* First element is the (Integer) count of sub-packages to follow */ + + status = acpi_ns_check_object_type(pathname, *elements, + ACPI_RTYPE_INTEGER, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* + * Count cannot be larger than the parent package length, but allow it + * to be smaller. The >= accounts for the Integer above. + */ + expected_count = (u32) (*elements)->integer.value; + if (expected_count >= count) { + goto package_too_small; + } + + count = expected_count; + elements++; + + /* Now we can walk the sub-packages */ + + /*lint -fallthrough */ + + case ACPI_PTYPE2: + case ACPI_PTYPE2_FIXED: + case ACPI_PTYPE2_MIN: + case ACPI_PTYPE2_COUNT: + + /* + * These types all return a single package that consists of a variable + * number of sub-packages + */ + for (i = 0; i < count; i++) { + sub_package = *elements; + sub_elements = sub_package->package.elements; + + /* Each sub-object must be of type Package */ + + status = + acpi_ns_check_object_type(pathname, sub_package, + ACPI_RTYPE_PACKAGE, i); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Examine the different types of sub-packages */ + + switch (package->ret_info.type) { + case ACPI_PTYPE2: + case ACPI_PTYPE2_PKG_COUNT: + + /* Each subpackage has a fixed number of elements */ + + expected_count = + package->ret_info.count1 + + package->ret_info.count2; + if (sub_package->package.count != + expected_count) { + count = sub_package->package.count; + goto package_too_small; + } + + status = + acpi_ns_check_package_elements(pathname, + sub_elements, + package-> + ret_info. + object_type1, + package-> + ret_info. + count1, + package-> + ret_info. + object_type2, + package-> + ret_info. + count2); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE2_FIXED: + + /* Each sub-package has a fixed length */ + + expected_count = package->ret_info2.count; + if (sub_package->package.count < expected_count) { + count = sub_package->package.count; + goto package_too_small; + } + + /* Check the type of each sub-package element */ + + for (j = 0; j < expected_count; j++) { + status = + acpi_ns_check_object_type(pathname, + sub_elements + [j], + package-> + ret_info2. + object_type + [j], j); + if (ACPI_FAILURE(status)) { + return (status); + } + } + break; + + case ACPI_PTYPE2_MIN: + + /* Each sub-package has a variable but minimum length */ + + expected_count = package->ret_info.count1; + if (sub_package->package.count < expected_count) { + count = sub_package->package.count; + goto package_too_small; + } + + /* Check the type of each sub-package element */ + + status = + acpi_ns_check_package_elements(pathname, + sub_elements, + package-> + ret_info. + object_type1, + sub_package-> + package. + count, 0, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE2_COUNT: + + /* First element is the (Integer) count of elements to follow */ + + status = + acpi_ns_check_object_type(pathname, + *sub_elements, + ACPI_RTYPE_INTEGER, + 0); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Make sure package is large enough for the Count */ + + expected_count = + (u32) (*sub_elements)->integer.value; + if (sub_package->package.count < expected_count) { + count = sub_package->package.count; + goto package_too_small; + } + + /* Check the type of each sub-package element */ + + status = + acpi_ns_check_package_elements(pathname, + (sub_elements + + 1), + package-> + ret_info. + object_type1, + (expected_count + - 1), 0, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + default: + break; + } + + elements++; + } + break; + + default: + + /* Should not get here if predefined info table is correct */ + + ACPI_WARNING((AE_INFO, + "%s: Invalid internal return type in table entry: %X", + pathname, package->ret_info.type)); + + return (AE_AML_INTERNAL); + } + + return (AE_OK); + + package_too_small: + + /* Error exit for the case with an incorrect package count */ + + ACPI_WARNING((AE_INFO, "%s: Return Package is too small - " + "found %u, expected %u", pathname, count, + expected_count)); + + return (AE_AML_OPERAND_VALUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_package_elements + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * Elements - Pointer to the package elements array + * Type1 - Object type for first group + * Count1 - Count for first group + * Type2 - Object type for second group + * Count2 - Count for second group + * + * RETURN: Status + * + * DESCRIPTION: Check that all elements of a package are of the correct object + * type. Supports up to two groups of different object types. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_package_elements(char *pathname, + union acpi_operand_object **elements, + u8 type1, u32 count1, u8 type2, u32 count2) +{ + union acpi_operand_object **this_element = elements; + acpi_status status; + u32 i; + + /* + * Up to two groups of package elements are supported by the data + * structure. All elements in each group must be of the same type. + * The second group can have a count of zero. + */ + for (i = 0; i < count1; i++) { + status = acpi_ns_check_object_type(pathname, *this_element, + type1, i); + if (ACPI_FAILURE(status)) { + return (status); + } + this_element++; + } + + for (i = 0; i < count2; i++) { + status = acpi_ns_check_object_type(pathname, *this_element, + type2, (i + count1)); + if (ACPI_FAILURE(status)) { + return (status); + } + this_element++; + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_object_type + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * return_object - Object return from the execution of this + * method/object + * expected_btypes - Bitmap of expected return type(s) + * package_index - Index of object within parent package (if + * applicable - ACPI_NOT_PACKAGE otherwise) + * + * RETURN: Status + * + * DESCRIPTION: Check the type of the return object against the expected object + * type(s). Use of Btype allows multiple expected object types. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_object_type(char *pathname, + union acpi_operand_object *return_object, + u32 expected_btypes, u32 package_index) +{ + acpi_status status = AE_OK; + u32 return_btype; + char type_buffer[48]; /* Room for 5 types */ + u32 this_rtype; + u32 i; + u32 j; + + /* + * If we get a NULL return_object here, it is a NULL package element, + * and this is always an error. + */ + if (!return_object) { + goto type_error_exit; + } + + /* A Namespace node should not get here, but make sure */ + + if (ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) { + ACPI_WARNING((AE_INFO, + "%s: Invalid return type - Found a Namespace node [%4.4s] type %s", + pathname, return_object->node.name.ascii, + acpi_ut_get_type_name(return_object->node.type))); + return (AE_AML_OPERAND_TYPE); + } + + /* + * Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type. + * The bitmapped type allows multiple possible return types. + * + * Note, the cases below must handle all of the possible types returned + * from all of the predefined names (including elements of returned + * packages) + */ + switch (ACPI_GET_OBJECT_TYPE(return_object)) { + case ACPI_TYPE_INTEGER: + return_btype = ACPI_RTYPE_INTEGER; + break; + + case ACPI_TYPE_BUFFER: + return_btype = ACPI_RTYPE_BUFFER; + break; + + case ACPI_TYPE_STRING: + return_btype = ACPI_RTYPE_STRING; + break; + + case ACPI_TYPE_PACKAGE: + return_btype = ACPI_RTYPE_PACKAGE; + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + return_btype = ACPI_RTYPE_REFERENCE; + break; + + default: + /* Not one of the supported objects, must be incorrect */ + + goto type_error_exit; + } + + /* Is the object one of the expected types? */ + + if (!(return_btype & expected_btypes)) { + goto type_error_exit; + } + + /* For reference objects, check that the reference type is correct */ + + if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_LOCAL_REFERENCE) { + status = acpi_ns_check_reference(pathname, return_object); + } + + return (status); + + type_error_exit: + + /* Create a string with all expected types for this predefined object */ + + j = 1; + type_buffer[0] = 0; + this_rtype = ACPI_RTYPE_INTEGER; + + for (i = 0; i < ACPI_NUM_RTYPES; i++) { + + /* If one of the expected types, concatenate the name of this type */ + + if (expected_btypes & this_rtype) { + ACPI_STRCAT(type_buffer, &acpi_rtype_names[i][j]); + j = 0; /* Use name separator from now on */ + } + this_rtype <<= 1; /* Next Rtype */ + } + + if (package_index == ACPI_NOT_PACKAGE) { + ACPI_WARNING((AE_INFO, + "%s: Return type mismatch - found %s, expected %s", + pathname, + acpi_ut_get_object_type_name(return_object), + type_buffer)); + } else { + ACPI_WARNING((AE_INFO, + "%s: Return Package type mismatch at index %u - " + "found %s, expected %s", pathname, package_index, + acpi_ut_get_object_type_name(return_object), + type_buffer)); + } + + return (AE_AML_OPERAND_TYPE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_reference + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * return_object - Object returned from the evaluation of a + * method or object + * + * RETURN: Status + * + * DESCRIPTION: Check a returned reference object for the correct reference + * type. The only reference type that can be returned from a + * predefined method is a named reference. All others are invalid. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_reference(char *pathname, + union acpi_operand_object *return_object) +{ + + /* + * Check the reference object for the correct reference type (opcode). + * The only type of reference that can be converted to an union acpi_object is + * a reference to a named object (reference class: NAME) + */ + if (return_object->reference.class == ACPI_REFCLASS_NAME) { + return (AE_OK); + } + + ACPI_WARNING((AE_INFO, + "%s: Return type mismatch - unexpected reference object type [%s] %2.2X", + pathname, acpi_ut_get_reference_name(return_object), + return_object->reference.class)); + + return (AE_AML_OPERAND_TYPE); +} -- cgit v1.2.3 From 4ca846e9270f305ad19e61f6654664f31459f332 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Sat, 27 Sep 2008 13:27:51 +0800 Subject: ACPICA: Add support for zero-length buffer-to-string conversions Allow zero length strings during interpreter buffer-to-string conversions. For example, during the ToDecimalString and ToHexString operaters, as well as implicit conversions. Fiodor Suietov. ACPICA BZ 585. http://www.acpica.org/bugzilla/show_bug.cgi?id=585 Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/executer/exconvrt.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c index 890378e789a4..1d1f35adddde 100644 --- a/drivers/acpi/executer/exconvrt.c +++ b/drivers/acpi/executer/exconvrt.c @@ -512,9 +512,14 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, /* * Create a new string object and string buffer * (-1 because of extra separator included in string_length from above) + * Allow creation of zero-length strings from zero-length buffers. */ + if (string_length) { + string_length--; + } + return_desc = acpi_ut_create_string_object((acpi_size) - (string_length - 1)); + string_length); if (!return_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -537,7 +542,9 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, * Null terminate the string * (overwrites final comma/space from above) */ - new_buf--; + if (obj_desc->buffer.length) { + new_buf--; + } *new_buf = 0; break; -- cgit v1.2.3 From b849075c0e08ea43400c1341c78eeca76ab08d8a Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 23 Oct 2008 00:45:18 -0400 Subject: ACPI suspend: fix build warning when CONFIG_ACPI_SLEEP=n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/acpi/sleep/main.c:27: warning: â€acpi_target_sleep_state’ defined but not used Signed-off-by: Len Brown --- drivers/acpi/sleep/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 76037883cd13..26571bafb158 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -24,7 +24,6 @@ #include "sleep.h" u8 sleep_states[ACPI_S_STATE_COUNT]; -static u32 acpi_target_sleep_state = ACPI_STATE_S0; static void acpi_sleep_tts_switch(u32 acpi_state) { @@ -78,6 +77,7 @@ static int acpi_sleep_prepare(u32 acpi_state) } #ifdef CONFIG_ACPI_SLEEP +static u32 acpi_target_sleep_state = ACPI_STATE_S0; /* * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the * user to request that behavior by using the 'acpi_old_suspend_ordering' -- cgit v1.2.3 From 5eaff72218b9c2cb7ca7aa284cf0271870c7a7b1 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 17 Oct 2008 16:33:57 +0800 Subject: ACPI: hack around sysfs warning with link order There exists the following warning message will appear after the following commit is merged. >commit f2e969acd6d5981e6b1272810002558650d0736e >Author: Zhao Yakui >Date: Mon Aug 11 14:57:50 2008 +0800 >ACPI: Add "acpi.power_nocheck=1" to disable power state check in power transition: >WARNING: at linux-2.6/fs/sysfs/dir.c:463 sysfs_add_one+0x33/0x39() >sysfs: duplicate filename 'acpi' can not be created >kobject_add_internal failed for acpi with -EEXIST, don't try to register things with the same name in the same directory In the above commit the "acpi.power_nocheck" module parameter is defined in drivers/acpi/power.c file. As several module parameters using the same ACPI prefix are defined in the different files(for example: power_nocheck is defined in drivers/acpi/power.c,debug_layer/debug_level are defined in drivers/acpi/debug.c) and there exists another module between them, the warning message will be printed when using the current generic param code. (In the function of param_sysfs_init). In fact when ACPI is selected, the drivers/acpi/power will also be compiled as built-in kernel.So this issue can be fixed by the following approach. workaround it by adjusting the module link order in drivers/acpi/Makefile. In such case the module parameter using the same prefix(ACPI) are put together in the param data section. Of course the better solution is to fix it in generic param code related with sysfs. Signed-off-by: Zhao Yakui Signed-off-by: Len Brown --- drivers/acpi/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index ad4bfd558ff3..d91c027ece8f 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -48,10 +48,10 @@ obj-$(CONFIG_ACPI_DOCK) += dock.o obj-$(CONFIG_ACPI_VIDEO) += video.o obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o -obj-$(CONFIG_ACPI_POWER) += power.o obj-$(CONFIG_ACPI_PROCESSOR) += processor.o obj-$(CONFIG_ACPI_CONTAINER) += container.o obj-$(CONFIG_ACPI_THERMAL) += thermal.o +obj-$(CONFIG_ACPI_POWER) += power.o obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o obj-$(CONFIG_ACPI_DEBUG) += debug.o obj-$(CONFIG_ACPI_NUMA) += numa.o -- cgit v1.2.3 From 898b054f3eec5921320ae8614b5bdd7b07ea5b43 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Sat, 27 Sep 2008 11:10:28 +0800 Subject: dock: make dock driver not a module To avoid dock driver is loaded after other drivers like libata, let's make dock driver not a module. Signed-off-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index dc1de7224426..f4f632917509 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -157,7 +157,7 @@ config ACPI_FAN applications to perform basic fan control (on, off, status). config ACPI_DOCK - tristate "Dock" + bool "Dock" depends on EXPERIMENTAL help This driver adds support for ACPI controlled docking stations and removable -- cgit v1.2.3 From 16be87ea170ae6cfaa9f47f79d14f7577d8cb420 Mon Sep 17 00:00:00 2001 From: Miao Xie Date: Fri, 24 Oct 2008 17:22:04 +0800 Subject: ACPI: cpufreq, processor: fix compile error in drivers/acpi/processor_perflib.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When trying to build 2.6.28-rc1 on ia64, make aborts with: CC drivers/acpi/processor_perflib.o drivers/acpi/processor_perflib.c:41:28: error: asm/cpufeature.h: No such file or directory drivers/acpi/processor_perflib.c: In function â€acpi_processor_get_performance_info’: drivers/acpi/processor_perflib.c:364: error: implicit declaration of function â€boot_cpu_has’ drivers/acpi/processor_perflib.c:364: error: â€X86_FEATURE_EST’ undeclared (first use in this function) drivers/acpi/processor_perflib.c:364: error: (Each undeclared identifier is reported only once drivers/acpi/processor_perflib.c:364: error: for each function it appears in.) make[2]: *** [drivers/acpi/processor_perflib.o] Error 1 make[1]: *** [drivers/acpi] Error 2 make: *** [drivers] Error 2 this patch fix it. Signed-off-by: Miao Xie Acked-by: Thomas Renninger Signed-off-by: Len Brown --- drivers/acpi/processor_perflib.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index dc98f7a6f2c4..dbcf260ea93f 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -38,7 +38,10 @@ #include #endif + +#ifdef CONFIG_X86 #include +#endif #include #include @@ -360,11 +363,13 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr) * the BIOS is older than the CPU and does not know its frequencies */ update_bios: +#ifdef CONFIG_X86 if (ACPI_SUCCESS(acpi_get_handle(pr->handle, "_PPC", &handle))){ if(boot_cpu_has(X86_FEATURE_EST)) printk(KERN_WARNING FW_BUG "BIOS needs update for CPU " "frequency support\n"); } +#endif return result; } -- cgit v1.2.3 From df316e939100e789b3c5d4d102619ccf5834bd00 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Fri, 24 Oct 2008 00:28:33 +0300 Subject: ACPI: Always report a sync event after a lid state change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently not always an EV_SYN event is reported to userland after the EV_SW SW_LID event has been sent. This is easy to verify by using “input-events” from input-utils and just closing and opening the lid. Signed-off-by: Guillem Jover Signed-off-by: Len Brown --- drivers/acpi/button.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 9d568d417eaa..cb046c3fc3f2 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -262,6 +262,7 @@ static int acpi_lid_send_state(struct acpi_button *button) return -ENODEV; /* input layer checks if event is redundant */ input_report_switch(button->input, SW_LID, !state); + input_sync(button->input); return 0; } @@ -285,8 +286,8 @@ static void acpi_button_notify(acpi_handle handle, u32 event, void *data) input_report_key(input, keycode, 1); input_sync(input); input_report_key(input, keycode, 0); + input_sync(input); } - input_sync(input); acpi_bus_generate_proc_event(button->device, event, ++button->pushed); -- cgit v1.2.3 From cab08969188e2da09923fe9c4a99ec9b934b0708 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 24 Oct 2008 15:39:47 -0400 Subject: toshiba_acpi: always call input_sync() after input_report_switch() Signed-off-by: Len Brown --- drivers/acpi/toshiba_acpi.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c index 2a632f8b7a05..66aac06f2ac5 100644 --- a/drivers/acpi/toshiba_acpi.c +++ b/drivers/acpi/toshiba_acpi.c @@ -371,6 +371,7 @@ static void bt_poll_rfkill(struct input_polled_dev *poll_dev) RFKILL_STATE_HARD_BLOCKED); input_report_switch(poll_dev->input, SW_RFKILL_ALL, new_rfk_state); + input_sync(poll_dev->input); } } @@ -842,6 +843,7 @@ static int __init toshiba_acpi_init(void) set_bit(EV_SW, toshiba_acpi.poll_dev->input->evbit); set_bit(SW_RFKILL_ALL, toshiba_acpi.poll_dev->input->swbit); input_report_switch(toshiba_acpi.poll_dev->input, SW_RFKILL_ALL, TRUE); + input_sync(toshiba_acpi.poll_dev->input); ret = input_register_polled_device(toshiba_acpi.poll_dev); if (ret) { -- cgit v1.2.3 From 92daa7b53b76984565dfdfda5d9c679884121fb2 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 23 Oct 2008 21:46:43 +0200 Subject: ACPI suspend: build fix for ACPI_SLEEP=n && XEN_SAVE_RESTORE=y. Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/sleep/main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 26571bafb158..80c0868d0480 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -163,6 +163,8 @@ static void acpi_pm_end(void) acpi_target_sleep_state = ACPI_STATE_S0; acpi_sleep_tts_switch(acpi_target_sleep_state); } +#else /* !CONFIG_ACPI_SLEEP */ +#define acpi_target_sleep_state ACPI_STATE_S0 #endif /* CONFIG_ACPI_SLEEP */ #ifdef CONFIG_SUSPEND -- cgit v1.2.3 From b1b57fbe9bb10d94682a975456de7a727d1dbc84 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 27 Oct 2008 16:04:53 +0800 Subject: ACPI: fix de-reference bug in power resource driver change state to *state in the function of acpi_power_get_state() Signed-off-by: yakui.zhao@intel.com Signed-off-by: Len Brown --- drivers/acpi/power.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index a1718e56103b..30d4a5282a2d 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -153,7 +153,8 @@ static int acpi_power_get_state(acpi_handle handle, int *state) ACPI_POWER_RESOURCE_STATE_OFF; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", - acpi_ut_get_node_name(handle), state ? "on" : "off")); + acpi_ut_get_node_name(handle), + *state ? "on" : "off")); return 0; } -- cgit v1.2.3 From 676962dac6e267ce7c13f73962208f9124a084bb Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 27 Oct 2008 16:05:39 +0800 Subject: ACPI: fan: Delete the strict check in power transition On some laptops the Fan device is turned on/off by controlling the corresponding power resource. For example: If the power resource defined in _PR0 object is turned off, it indicates that the FAN device is in off state(the ACPI state is in D3 state). Maybe the device is already in D3 state and expected to be transited to D3 state. As there is no _PR3 object, the power transition can't be finished and it will be switched to the Unknown state. Maybe it is more reasonable that the strick check in power transistion is deleted. http://bugzilla.kernel.org/show_bug.cgi?id=9485 Signed-off-by: yakui.zhao@intel.com Signed-off-by: Len Brown --- drivers/acpi/power.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 30d4a5282a2d..89111cd28ed8 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -517,11 +517,6 @@ int acpi_power_transition(struct acpi_device *device, int state) cl = &device->power.states[device->power.state].resources; tl = &device->power.states[state].resources; - if (!cl->count && !tl->count) { - result = -ENODEV; - goto end; - } - /* TBD: Resources must be ordered. */ /* -- cgit v1.2.3 From ed206fac87d65917280b6c3edd3f01125d4095c9 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 27 Oct 2008 14:01:02 -0700 Subject: ACPI: bugfix reporting of event handler status Introduce a new flag showing whether the event has an event handler/method. For all the GPEs and Fixed Events, 1. ACPI_EVENT_FLAG_HANDLE is cleared, it's an "invalid" ACPI event. 2. Both ACPI_EVENT_FLAG_HANDLE and ACPI_EVENT_FLAG_DISABLE are set, it's "disabled". 3. Both ACPI_EVENT_FLAG_HANDLE and ACPI_EVENT_FLAG_ENABLE are set, it's "enabled". 4. Both ACPI_EVENT_FLAG_HANDLE and ACPI_EVENT_FLAG_WAKE_ENABLE are set, it's "wake_enabled". Among other things, this prevents incorrect reporting of ACPI events as being "invalid" when it's really just (temporarily) "disabled". Signed-off-by: Zhang Rui Signed-off-by: David Brownell Signed-off-by: Len Brown --- drivers/acpi/events/evxfevnt.c | 6 ++++++ drivers/acpi/system.c | 19 +++++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c index 73bfd6bf962f..211e93a90e95 100644 --- a/drivers/acpi/events/evxfevnt.c +++ b/drivers/acpi/events/evxfevnt.c @@ -521,6 +521,9 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) if (value) *event_status |= ACPI_EVENT_FLAG_SET; + if (acpi_gbl_fixed_event_handlers[event].handler) + *event_status |= ACPI_EVENT_FLAG_HANDLE; + return_ACPI_STATUS(status); } @@ -571,6 +574,9 @@ acpi_get_gpe_status(acpi_handle gpe_device, status = acpi_hw_get_gpe_status(gpe_event_info, event_status); + if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) + *event_status |= ACPI_EVENT_FLAG_HANDLE; + unlock_and_exit: if (flags & ACPI_NOT_ISR) { (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 1d74171b7940..6d348dce0810 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -167,7 +167,6 @@ static int acpi_system_sysfs_init(void) #define COUNT_ERROR 2 /* other */ #define NUM_COUNTERS_EXTRA 3 -#define ACPI_EVENT_VALID 0x01 struct event_counter { u32 count; u32 flags; @@ -312,12 +311,6 @@ static int get_status(u32 index, acpi_event_status *status, acpi_handle *handle) } else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS)) result = acpi_get_event_status(index - num_gpes, status); - /* - * sleep/power button GPE/Fixed Event is enabled after acpi_system_init, - * check the status at runtime and mark it as valid once it's enabled - */ - if (!result && (*status & ACPI_EVENT_FLAG_ENABLED)) - all_counters[index].flags |= ACPI_EVENT_VALID; end: return result; } @@ -346,12 +339,14 @@ static ssize_t counter_show(struct kobject *kobj, if (result) goto end; - if (!(all_counters[index].flags & ACPI_EVENT_VALID)) - size += sprintf(buf + size, " invalid"); + if (!(status & ACPI_EVENT_FLAG_HANDLE)) + size += sprintf(buf + size, " invalid"); else if (status & ACPI_EVENT_FLAG_ENABLED) - size += sprintf(buf + size, " enable"); + size += sprintf(buf + size, " enabled"); + else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED) + size += sprintf(buf + size, " wake_enabled"); else - size += sprintf(buf + size, " disable"); + size += sprintf(buf + size, " disabled"); end: size += sprintf(buf + size, "\n"); @@ -385,7 +380,7 @@ static ssize_t counter_set(struct kobject *kobj, if (result) goto end; - if (!(all_counters[index].flags & ACPI_EVENT_VALID)) { + if (!(status & ACPI_EVENT_FLAG_HANDLE)) { printk(KERN_WARNING PREFIX "Can not change Invalid GPE/Fixed Event status\n"); return -EINVAL; -- cgit v1.2.3 From 5704d626e7c770ef4a984a697bac7eff07420a39 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 5 Nov 2008 16:17:42 -0700 Subject: ACPI: remove comments about debug layer/level to use I don't think there's any point in cluttering the code with these. Better to improve the documentation so *anybody* can figure out what layer & level to use. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_root.c | 6 ------ drivers/acpi/video.c | 6 ------ 2 files changed, 12 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 1b8f67d21d53..642554b1b60c 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -376,15 +376,9 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) static int __init acpi_pci_root_init(void) { - if (acpi_pci_disabled) return 0; - /* DEBUG: - acpi_dbg_layer = ACPI_PCI_COMPONENT; - acpi_dbg_level = 0xFFFFFFFF; - */ - if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) return -ENODEV; diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index a29b0ccac65a..bf0c26a7368d 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -2094,12 +2094,6 @@ static int __init acpi_video_init(void) { int result = 0; - - /* - acpi_dbg_level = 0xFFFFFFFF; - acpi_dbg_layer = 0x08000000; - */ - acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); if (!acpi_video_dir) return -ENODEV; -- cgit v1.2.3 From 5b881479af4352791e5004b74e3639f1416c5fe4 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 5 Nov 2008 16:17:47 -0700 Subject: ACPI: SBS: remove useless acpi_cm_sbs_init() initcall acpi_cm_sbs_init() doesn't do anything, so we can just remove it. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/cm_sbs.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c index 4441e84b28a9..80d5c88e68c3 100644 --- a/drivers/acpi/cm_sbs.c +++ b/drivers/acpi/cm_sbs.c @@ -105,9 +105,3 @@ void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param) return; } EXPORT_SYMBOL(acpi_unlock_battery_dir); - -static int __init acpi_cm_sbs_init(void) -{ - return 0; -} -subsys_initcall(acpi_cm_sbs_init); -- cgit v1.2.3 From fefe5ab3d67b0ade6200fec5ed6f2812cbcbb658 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 5 Nov 2008 16:17:58 -0700 Subject: ACPI: remove CONFIG_ACPI_POWER Remove CONFIG_ACPI_POWER. It was always set the same as CONFIG_ACPI, and it had no menu label, so there was no way to set it to anything other than "y". The interfaces under CONFIG_ACPI_POWER (acpi_device_sleep_wake(), acpi_power_transition(), etc) are called unconditionally from the ACPI core, so we already depend on it always being present. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 4 ---- drivers/acpi/Makefile | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index f4f632917509..4fa7866a9a5e 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -341,10 +341,6 @@ config ACPI_PCI_SLOT help you correlate PCI bus addresses with the physical geography of your slots. If you are unsure, say N. -config ACPI_POWER - bool - default y - config ACPI_SYSTEM bool default y diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index d91c027ece8f..8017f63920c4 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -51,7 +51,7 @@ obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o obj-$(CONFIG_ACPI_PROCESSOR) += processor.o obj-$(CONFIG_ACPI_CONTAINER) += container.o obj-$(CONFIG_ACPI_THERMAL) += thermal.o -obj-$(CONFIG_ACPI_POWER) += power.o +obj-y += power.o obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o obj-$(CONFIG_ACPI_DEBUG) += debug.o obj-$(CONFIG_ACPI_NUMA) += numa.o -- cgit v1.2.3 From 8950d89acaa8c353869e681772479d7955ae6f7a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 5 Nov 2008 16:18:03 -0700 Subject: ACPI: remove CONFIG_ACPI_EC Remove CONFIG_ACPI_EC. It was always set the same as CONFIG_ACPI, and it had no menu label, so there was no way to set it to anything other than "y". Per section 6.5.4 of the ACPI 3.0b specification, OSPM must make Embedded Controller operation regions, accessed via the Embedded Controllers described in ECDT, available before executing any control method. The ECDT table is optional, but if it is present, the above text means that the EC it describes is a required part of the ACPI subsystem, so CONFIG_ACPI_EC=n wouldn't make sense. Signed-off-by: Bjorn Helgaas Acked-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 8 -------- drivers/acpi/Makefile | 2 +- drivers/acpi/bus.c | 3 +-- 3 files changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 4fa7866a9a5e..90cb2a823b56 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -324,14 +324,6 @@ config ACPI_DEBUG_FUNC_TRACE ACPI Debug Statements slow down ACPI processing. Function trace is about half of the penalty and is rarely useful. -config ACPI_EC - bool - default y - help - This driver is required on some systems for the proper operation of - the battery and thermal drivers. If you are compiling for a - mobile system, say Y. - config ACPI_PCI_SLOT tristate "PCI slot detection driver" default n diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 8017f63920c4..fc622316a7d8 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -39,7 +39,7 @@ obj-y += sleep/ obj-y += bus.o glue.o obj-y += scan.o # Keep EC driver first. Initialization of others depend on it. -obj-$(CONFIG_ACPI_EC) += ec.o +obj-y += ec.o obj-$(CONFIG_ACPI_AC) += ac.o obj-$(CONFIG_ACPI_BATTERY) += battery.o obj-$(CONFIG_ACPI_BUTTON) += button.o diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index c797c6473f31..765fd1c56cd6 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -774,7 +774,7 @@ static int __init acpi_bus_init(void) "Unable to initialize ACPI OS objects\n"); goto error1; } -#ifdef CONFIG_ACPI_EC + /* * ACPI 2.0 requires the EC driver to be loaded and work before * the EC device is found in the namespace (i.e. before acpi_initialize_objects() @@ -785,7 +785,6 @@ static int __init acpi_bus_init(void) */ status = acpi_ec_ecdt_probe(); /* Ignore result. Not having an ECDT is not fatal. */ -#endif status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); if (ACPI_FAILURE(status)) { -- cgit v1.2.3 From ad93a765c1834db031b5bf1c2baf2a50d0462ca4 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Tue, 4 Nov 2008 14:52:55 -0700 Subject: ACPI: Disambiguate processor declaration type Declaring processors in ACPI namespace can be done using either a "Processor" definition or a "Device" definition (see section 8.4 - Declaring Processors; "Advanced Configuration and Power Interface Specification", Revision 3.0b). Currently the two processor declaration types are conflated. This patch disambiguates the processor declaration's definition type enabling subsequent code to behave uniquely based explicitly on the declaration's type. Signed-off-by: Myron Stowe Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 1 + drivers/acpi/scan.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 24a362f8034c..0c670dd297d7 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -89,6 +89,7 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr); static const struct acpi_device_id processor_device_ids[] = { + {ACPI_PROCESSOR_OBJECT_HID, 0}, {ACPI_PROCESSOR_HID, 0}, {"", 0}, }; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a9dda8e0f9f9..3fb6e2db585a 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1043,7 +1043,7 @@ static void acpi_device_set_id(struct acpi_device *device, hid = ACPI_POWER_HID; break; case ACPI_BUS_TYPE_PROCESSOR: - hid = ACPI_PROCESSOR_HID; + hid = ACPI_PROCESSOR_OBJECT_HID; break; case ACPI_BUS_TYPE_SYSTEM: hid = ACPI_SYSTEM_HID; -- cgit v1.2.3 From b26e9286fb438eb78bcdb68b67a3dbb8bc539125 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Tue, 4 Nov 2008 14:53:00 -0700 Subject: ACPI: Behave uniquely based on processor declaration definition type Associating a Local SAPIC with a processor object is dependent upon the processor object's definition type. CPUs declared as "Processor" should use the Local SAPIC's 'processor_id', and CPUs declared as "Device" should use the 'uid'. Note that for "Processor" declarations, even if a '_UID' child object exists, it has no bearing with respect to mapping Local SAPICs (see section 5.2.11.13 - Local SAPIC Structure; "Advanced Configuration and Power Interface Specification", Revision 3.0b). This patch changes the lsapic mapping logic to rely on the distinction of how the processor object was declared - the mapping can't just try both types of matches regardless of declaration type and rely on one failing as is currently being done. Signed-off-by: Myron Stowe Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 78 ++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 34 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 0c670dd297d7..bc332fc28d7f 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -410,7 +410,7 @@ static int acpi_processor_remove_fs(struct acpi_device *device) /* Use the acpiid in MADT to map cpus in case of SMP */ #ifndef CONFIG_SMP -static int get_cpu_id(acpi_handle handle, u32 acpi_id) {return -1;} +static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id) { return -1; } #else static struct acpi_table_madt *madt; @@ -429,27 +429,35 @@ static int map_lapic_id(struct acpi_subtable_header *entry, } static int map_lsapic_id(struct acpi_subtable_header *entry, - u32 acpi_id, int *apic_id) + int device_declaration, u32 acpi_id, int *apic_id) { struct acpi_madt_local_sapic *lsapic = (struct acpi_madt_local_sapic *)entry; + u32 tmp = (lsapic->id << 8) | lsapic->eid; + /* Only check enabled APICs*/ - if (lsapic->lapic_flags & ACPI_MADT_ENABLED) { - /* First check against id */ - if (lsapic->processor_id == acpi_id) { - *apic_id = (lsapic->id << 8) | lsapic->eid; - return 1; - /* Check against optional uid */ - } else if (entry->length >= 16 && - lsapic->uid == acpi_id) { - *apic_id = lsapic->uid; - return 1; - } - } + if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED)) + return 0; + + /* Device statement declaration type */ + if (device_declaration) { + if (entry->length < 16) + printk(KERN_ERR PREFIX + "Invalid LSAPIC with Device type processor (SAPIC ID %#x)\n", + tmp); + else if (lsapic->uid == acpi_id) + goto found; + /* Processor statement declaration type */ + } else if (lsapic->processor_id == acpi_id) + goto found; + return 0; +found: + *apic_id = tmp; + return 1; } -static int map_madt_entry(u32 acpi_id) +static int map_madt_entry(int type, u32 acpi_id) { unsigned long madt_end, entry; int apic_id = -1; @@ -470,7 +478,7 @@ static int map_madt_entry(u32 acpi_id) if (map_lapic_id(header, acpi_id, &apic_id)) break; } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { - if (map_lsapic_id(header, acpi_id, &apic_id)) + if (map_lsapic_id(header, type, acpi_id, &apic_id)) break; } entry += header->length; @@ -478,7 +486,7 @@ static int map_madt_entry(u32 acpi_id) return apic_id; } -static int map_mat_entry(acpi_handle handle, u32 acpi_id) +static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; @@ -501,7 +509,7 @@ static int map_mat_entry(acpi_handle handle, u32 acpi_id) if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { map_lapic_id(header, acpi_id, &apic_id); } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { - map_lsapic_id(header, acpi_id, &apic_id); + map_lsapic_id(header, type, acpi_id, &apic_id); } exit: @@ -510,14 +518,14 @@ exit: return apic_id; } -static int get_cpu_id(acpi_handle handle, u32 acpi_id) +static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id) { int i; int apic_id = -1; - apic_id = map_mat_entry(handle, acpi_id); + apic_id = map_mat_entry(handle, type, acpi_id); if (apic_id == -1) - apic_id = map_madt_entry(acpi_id); + apic_id = map_madt_entry(type, acpi_id); if (apic_id == -1) return apic_id; @@ -533,15 +541,16 @@ static int get_cpu_id(acpi_handle handle, u32 acpi_id) Driver Interface -------------------------------------------------------------------------- */ -static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) +static int acpi_processor_get_info(struct acpi_device *device) { acpi_status status = 0; union acpi_object object = { 0 }; struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; - int cpu_index; + struct acpi_processor *pr; + int cpu_index, device_declaration = 0; static int cpu0_initialized; - + pr = acpi_driver_data(device); if (!pr) return -EINVAL; @@ -562,22 +571,23 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No bus mastering arbitration control\n")); - /* Check if it is a Device with HID and UID */ - if (has_uid) { + if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_HID)) { + /* + * Declared with "Device" statement; match _UID. + * Note that we don't handle string _UIDs yet. + */ unsigned long long value; status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, NULL, &value); if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Evaluating processor _UID\n"); + printk(KERN_ERR PREFIX + "Evaluating processor _UID [%#x]\n", status); return -ENODEV; } + device_declaration = 1; pr->acpi_id = value; } else { - /* - * Evalute the processor object. Note that it is common on SMP to - * have the first (boot) processor with a valid PBLK address while - * all others have a NULL address. - */ + /* Declared with "Processor" statement; match ProcessorID */ status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Evaluating processor object\n"); @@ -590,7 +600,7 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) */ pr->acpi_id = object.processor.proc_id; } - cpu_index = get_cpu_id(pr->handle, pr->acpi_id); + cpu_index = get_cpu_id(pr->handle, device_declaration, pr->acpi_id); /* Handle UP system running SMP kernel, with no LAPIC in MADT */ if (!cpu0_initialized && (cpu_index == -1) && @@ -662,7 +672,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) pr = acpi_driver_data(device); - result = acpi_processor_get_info(pr, device->flags.unique_id); + result = acpi_processor_get_info(device); if (result) { /* Processor is physically not present */ return 0; -- cgit v1.2.3 From 5b53ed69158eeff115004f246193d07a083445f6 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Tue, 4 Nov 2008 14:53:05 -0700 Subject: ACPI: 80 column adherence and spelling fix (no functional change) Signed-off-by: Myron Stowe Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index bc332fc28d7f..b57b1f05cb38 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -595,9 +595,10 @@ static int acpi_processor_get_info(struct acpi_device *device) } /* - * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. - * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c - */ + * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. + * >>> 'acpi_get_processor_id(acpi_id, &id)' in + * arch/xxx/acpi.c + */ pr->acpi_id = object.processor.proc_id; } cpu_index = get_cpu_id(pr->handle, device_declaration, pr->acpi_id); -- cgit v1.2.3 From d17cb18a07c587b8f9ff174a1bf6d03413eabe64 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 6 Nov 2008 20:51:59 -0500 Subject: Revert "ACPI: Ingore the RESET_REG_SUP bit when using ACPI reset mechanism" This reverts commit 8fd145917fb62368a9b80db59562c20576238f5a. http://bugzilla.kernel.org/show_bug.cgi?id=11942 Signed-off-by: Len Brown --- drivers/acpi/reboot.c | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c index 755baf2ca70a..a6b662c00b67 100644 --- a/drivers/acpi/reboot.c +++ b/drivers/acpi/reboot.c @@ -15,28 +15,9 @@ void acpi_reboot(void) rr = &acpi_gbl_FADT.reset_register; - /* - * Is the ACPI reset register supported? - * - * According to ACPI 3.0, FADT.flags.RESET_REG_SUP indicates - * whether the ACPI reset mechanism is supported. - * - * However, some boxes have this bit clear, yet a valid - * ACPI_RESET_REG & RESET_VALUE, and ACPI reboot is the only - * mechanism that works for them after S3. - * - * This suggests that other operating systems may not be checking - * the RESET_REG_SUP bit, and are using other means to decide - * whether to use the ACPI reboot mechanism or not. - * - * So when acpi reboot is requested, - * only the reset_register is checked. If the following - * conditions are met, it indicates that the reset register is supported. - * a. reset_register is not zero - * b. the access width is eight - * c. the bit_offset is zero - */ - if (!(rr->address) || rr->bit_width != 8 || rr->bit_offset != 0) + /* Is the reset register supported? */ + if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) || + rr->bit_width != 8 || rr->bit_offset != 0) return; reset_value = acpi_gbl_FADT.reset_value; -- cgit v1.2.3 From 0794469da3f7b2093575cbdfc1108308dd3641ce Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 30 Oct 2008 01:18:59 +0100 Subject: ACPI: struct device - replace bus_id with dev_name(), dev_set_name() This patch is part of a larger patch series which will remove the "char bus_id[20]" name string from struct device. The device name is managed in the kobject anyway, and without any size limitation, and just needlessly copied into "struct device". To set and read the device name dev_name(dev) and dev_set_name(dev) must be used. If your code uses static kobjects, which it shouldn't do, "const char *init_name" can be used to statically provide the name the registered device should have. At registration time, the init_name field is cleared, to enforce the use of dev_name(dev) to access the device name at a later time. We need to get rid of all occurrences of bus_id in the entire tree to be able to enable the new interface. Please apply this patch, and possibly convert any remaining remaining occurrences of bus_id. We want to submit a patch to -next, which will remove bus_id from "struct device", to find the remaining pieces to convert, and finally switch over to the new api, which will remove the 20 bytes array and does no longer have a size limitation. Acked-by: Greg Kroah-Hartman Signed-Off-By: Kay Sievers Signed-off-by: Len Brown --- drivers/acpi/ac.c | 2 +- drivers/acpi/battery.c | 2 +- drivers/acpi/processor_core.c | 6 +++--- drivers/acpi/scan.c | 8 ++++---- drivers/acpi/sleep/proc.c | 4 ++-- drivers/acpi/thermal.c | 8 ++++---- drivers/acpi/wmi.c | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index d72a1b6c8a94..2d467326d9e0 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -242,7 +242,7 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data) acpi_ac_get_state(ac); acpi_bus_generate_proc_event(device, event, (u32) ac->state); acpi_bus_generate_netlink_event(device->pnp.device_class, - device->dev.bus_id, event, + dev_name(&device->dev), event, (u32) ac->state); #ifdef CONFIG_ACPI_SYSFS_POWER kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index b2133e89ad9a..e68f2187ed64 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -782,7 +782,7 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) acpi_bus_generate_proc_event(device, event, acpi_battery_present(battery)); acpi_bus_generate_netlink_event(device->pnp.device_class, - device->dev.bus_id, event, + dev_name(&device->dev), event, acpi_battery_present(battery)); #ifdef CONFIG_ACPI_SYSFS_POWER /* acpi_batter_update could remove power_supply object */ diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 24a362f8034c..cf7e8856a4cd 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -761,20 +761,20 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) acpi_bus_generate_proc_event(device, event, pr->performance_platform_limit); acpi_bus_generate_netlink_event(device->pnp.device_class, - device->dev.bus_id, event, + dev_name(&device->dev), event, pr->performance_platform_limit); break; case ACPI_PROCESSOR_NOTIFY_POWER: acpi_processor_cst_has_changed(pr); acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, - device->dev.bus_id, event, 0); + dev_name(&device->dev), event, 0); break; case ACPI_PROCESSOR_NOTIFY_THROTTLING: acpi_processor_tstate_has_changed(pr); acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, - device->dev.bus_id, event, 0); + dev_name(&device->dev), event, 0); default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a9dda8e0f9f9..4dd1f31930b8 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -109,8 +109,7 @@ static int acpi_bus_hot_remove_device(void *context) return 0; ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Hot-removing device %s...\n", device->dev.bus_id)); - + "Hot-removing device %s...\n", dev_name(&device->dev))); if (acpi_bus_trim(device, 1)) { printk(KERN_ERR PREFIX @@ -460,7 +459,7 @@ static int acpi_device_register(struct acpi_device *device, acpi_device_bus_id->instance_no = 0; list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list); } - sprintf(device->dev.bus_id, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no); + 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); @@ -484,7 +483,8 @@ static int acpi_device_register(struct acpi_device *device, result = acpi_device_setup_files(device); if(result) - printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", device->dev.bus_id); + printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", + dev_name(&device->dev)); device->removal_type = ACPI_BUS_REMOVAL_NORMAL; return 0; diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 631ee2ee2ca0..64e591ba86f2 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c @@ -366,8 +366,8 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) dev->wakeup.state.enabled ? "enabled" : "disabled"); if (ldev) seq_printf(seq, "%s:%s", - ldev->bus ? ldev->bus->name : "no-bus", - ldev->bus_id); + dev_name(ldev) ? ldev->bus->name : "no-bus", + dev_name(ldev)); seq_printf(seq, "\n"); put_device(ldev); diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index ad6cae938f0b..462b16878851 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -576,7 +576,7 @@ static int acpi_thermal_critical(struct acpi_thermal *tz) acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL, tz->trips.critical.flags.enabled); acpi_bus_generate_netlink_event(tz->device->pnp.device_class, - tz->device->dev.bus_id, + dev_name(&tz->device->dev), ACPI_THERMAL_NOTIFY_CRITICAL, tz->trips.critical.flags.enabled); @@ -605,7 +605,7 @@ static int acpi_thermal_hot(struct acpi_thermal *tz) acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_HOT, tz->trips.hot.flags.enabled); acpi_bus_generate_netlink_event(tz->device->pnp.device_class, - tz->device->dev.bus_id, + dev_name(&tz->device->dev), ACPI_THERMAL_NOTIFY_HOT, tz->trips.hot.flags.enabled); @@ -1592,14 +1592,14 @@ static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data) acpi_thermal_check(tz); acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, - device->dev.bus_id, event, 0); + dev_name(&device->dev), event, 0); break; case ACPI_THERMAL_NOTIFY_DEVICES: acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES); acpi_thermal_check(tz); acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, - device->dev.bus_id, event, 0); + dev_name(&device->dev), event, 0); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, diff --git a/drivers/acpi/wmi.c b/drivers/acpi/wmi.c index 47cd7baf9b1b..8a8b377712c9 100644 --- a/drivers/acpi/wmi.c +++ b/drivers/acpi/wmi.c @@ -660,7 +660,7 @@ static void acpi_wmi_notify(acpi_handle handle, u32 event, void *data) wblock->handler(event, wblock->handler_data); acpi_bus_generate_netlink_event( - device->pnp.device_class, device->dev.bus_id, + device->pnp.device_class, dev_name(&device->dev), event, 0); break; } -- cgit v1.2.3 From 14a63ba821ac2a0f5166789b31241c0b7eb147d9 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Wed, 29 Oct 2008 14:13:22 -0700 Subject: ACPI: use macro to replace hard number Impact: cleanup Use MACRO for rev 3 fadt id instead of 3 directly. Signed-off-by: Yinghai Lu Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/tables/tbfadt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c index 2c7885e7ffba..2817158fb6a1 100644 --- a/drivers/acpi/tables/tbfadt.c +++ b/drivers/acpi/tables/tbfadt.c @@ -304,7 +304,7 @@ static void acpi_tb_convert_fadt(void) * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at * offset 45, 55, 95, and the word located at offset 109, 110. */ - if (acpi_gbl_FADT.header.revision < 3) { + if (acpi_gbl_FADT.header.revision < FADT2_REVISION_ID) { acpi_gbl_FADT.preferred_profile = 0; acpi_gbl_FADT.pstate_control = 0; acpi_gbl_FADT.cst_control = 0; -- cgit v1.2.3 From 4feba70a2c1a1a0c96909f657f48b2e11e682370 Mon Sep 17 00:00:00 2001 From: Peter Gruber Date: Mon, 27 Oct 2008 23:59:36 -0400 Subject: ACPI: avoid empty file name in sysfs Since commit bc45b1d39a925b56796bebf8a397a0491489d85c acpi tables are allowed to have an empty signature and /sys/firmware/acpi/tables uses the signature as filename. Applications using naive recursion through /sys loop forever. A possible solution would be: (replacing the zero length filename with the string "NULL") http://bugzilla.kernel.org/show_bug.cgi?id=11539 Acked-by: Zhang Rui Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/system.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 1d74171b7940..62ec75e79120 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -78,9 +78,15 @@ static ssize_t acpi_table_show(struct kobject *kobj, container_of(bin_attr, struct acpi_table_attr, attr); struct acpi_table_header *table_header = NULL; acpi_status status; + char name[ACPI_NAME_SIZE]; + + if (strncmp(table_attr->name, "NULL", 4)) + memcpy(name, table_attr->name, ACPI_NAME_SIZE); + else + memcpy(name, "\0\0\0\0", 4); status = - acpi_get_table(table_attr->name, table_attr->instance, + acpi_get_table(name, table_attr->instance, &table_header); if (ACPI_FAILURE(status)) return -ENODEV; @@ -95,21 +101,24 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr, struct acpi_table_header *header = NULL; struct acpi_table_attr *attr = NULL; - memcpy(table_attr->name, table_header->signature, ACPI_NAME_SIZE); + if (table_header->signature[0] != '\0') + memcpy(table_attr->name, table_header->signature, + ACPI_NAME_SIZE); + else + memcpy(table_attr->name, "NULL", 4); list_for_each_entry(attr, &acpi_table_attr_list, node) { - if (!memcmp(table_header->signature, attr->name, - ACPI_NAME_SIZE)) + if (!memcmp(table_attr->name, attr->name, ACPI_NAME_SIZE)) if (table_attr->instance < attr->instance) table_attr->instance = attr->instance; } table_attr->instance++; if (table_attr->instance > 1 || (table_attr->instance == 1 && - !acpi_get_table(table_header-> - signature, 2, - &header))) - sprintf(table_attr->name + 4, "%d", table_attr->instance); + !acpi_get_table + (table_header->signature, 2, &header))) + sprintf(table_attr->name + ACPI_NAME_SIZE, "%d", + table_attr->instance); table_attr->attr.size = 0; table_attr->attr.read = acpi_table_show; -- cgit v1.2.3 From d21cf3c16b1191f3154a51e0b20c82bf851cc553 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Mon, 3 Nov 2008 14:26:40 -0500 Subject: ACPI EC: Fix regression due to use of uninitialized variable breakage introduced by following patch commit 27663c5855b10af9ec67bc7dfba001426ba21222 Author: Matthew Wilcox Date: Fri Oct 10 02:22:59 2008 -0400 acpi_evaluate_integer() does not clear passed variable if there is an error at evaluation. So if we ignore error, we must supply initialized variable. http://bugzilla.kernel.org/show_bug.cgi?id=11917 Signed-off-by: Alexey Starikovskiy Tested-by: Alan Jenkins Signed-off-by: Len Brown --- drivers/acpi/ec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index ef42316f89f5..523ac5b229a5 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -736,7 +736,7 @@ static acpi_status ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) { acpi_status status; - unsigned long long tmp; + unsigned long long tmp = 0; struct acpi_ec *ec = context; status = acpi_walk_resources(handle, METHOD_NAME__CRS, @@ -751,6 +751,7 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) return status; ec->gpe = tmp; /* Use the global lock for all EC transactions? */ + tmp = 0; acpi_evaluate_integer(handle, "_GLK", NULL, &tmp); ec->global_lock = tmp; ec->handle = handle; -- cgit v1.2.3 From 89595b8f2850a080d290bf778ec933ea1d99f78e Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 7 Nov 2008 16:57:45 -0700 Subject: ACPI: consolidate ACPI_*_COMPONENT definitions in acpi_drivers.h Move all the component definitions for drivers to a single shared place, include/acpi/acpi_drivers.h. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/ac.c | 1 - drivers/acpi/acpi_memhotplug.c | 1 - drivers/acpi/battery.c | 1 - drivers/acpi/button.c | 1 - drivers/acpi/cm_sbs.c | 1 - drivers/acpi/container.c | 1 - drivers/acpi/fan.c | 1 - drivers/acpi/power.c | 3 +-- drivers/acpi/processor_core.c | 1 - drivers/acpi/processor_idle.c | 1 - drivers/acpi/processor_perflib.c | 2 +- drivers/acpi/processor_thermal.c | 1 - drivers/acpi/processor_throttling.c | 2 +- drivers/acpi/thermal.c | 1 - drivers/acpi/video.c | 1 - 15 files changed, 3 insertions(+), 16 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index d72a1b6c8a94..5cdd713a0eaf 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -37,7 +37,6 @@ #include #include -#define ACPI_AC_COMPONENT 0x00020000 #define ACPI_AC_CLASS "ac_adapter" #define ACPI_AC_DEVICE_NAME "AC Adapter" #define ACPI_AC_FILE_STATE "state" diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 71d21c51c45f..63a17b55b39b 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -32,7 +32,6 @@ #include #include -#define ACPI_MEMORY_DEVICE_COMPONENT 0x08000000UL #define ACPI_MEMORY_DEVICE_CLASS "memory" #define ACPI_MEMORY_DEVICE_HID "PNP0C80" #define ACPI_MEMORY_DEVICE_NAME "Hotplug Mem Device" diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index b2133e89ad9a..47f6e38fa6c8 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -46,7 +46,6 @@ #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF -#define ACPI_BATTERY_COMPONENT 0x00040000 #define ACPI_BATTERY_CLASS "battery" #define ACPI_BATTERY_DEVICE_NAME "Battery" #define ACPI_BATTERY_NOTIFY_STATUS 0x80 diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index cb046c3fc3f2..fd7ca289cb02 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -33,7 +33,6 @@ #include #include -#define ACPI_BUTTON_COMPONENT 0x00080000 #define ACPI_BUTTON_CLASS "button" #define ACPI_BUTTON_FILE_INFO "info" #define ACPI_BUTTON_FILE_STATE "state" diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c index 80d5c88e68c3..307963bd1043 100644 --- a/drivers/acpi/cm_sbs.c +++ b/drivers/acpi/cm_sbs.c @@ -34,7 +34,6 @@ ACPI_MODULE_NAME("cm_sbs"); #define ACPI_AC_CLASS "ac_adapter" #define ACPI_BATTERY_CLASS "battery" -#define ACPI_SBS_COMPONENT 0x00080000 #define _COMPONENT ACPI_SBS_COMPONENT static struct proc_dir_entry *acpi_ac_dir; static struct proc_dir_entry *acpi_battery_dir; diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 134818b265a9..17020c12623c 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -41,7 +41,6 @@ #define INSTALL_NOTIFY_HANDLER 1 #define UNINSTALL_NOTIFY_HANDLER 2 -#define ACPI_CONTAINER_COMPONENT 0x01000000 #define _COMPONENT ACPI_CONTAINER_COMPONENT ACPI_MODULE_NAME("container"); diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 60d54d1f6b19..eaaee1660bdf 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -34,7 +34,6 @@ #include #include -#define ACPI_FAN_COMPONENT 0x00200000 #define ACPI_FAN_CLASS "fan" #define ACPI_FAN_FILE_STATE "state" diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index a1718e56103b..81f583f8098b 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -44,9 +44,8 @@ #include #include -#define _COMPONENT ACPI_POWER_COMPONENT +#define _COMPONENT ACPI_POWER_COMPONENT ACPI_MODULE_NAME("power"); -#define ACPI_POWER_COMPONENT 0x00800000 #define ACPI_POWER_CLASS "power_resource" #define ACPI_POWER_DEVICE_NAME "Power Resource" #define ACPI_POWER_FILE_INFO "info" diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 24a362f8034c..105e0ff83848 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -59,7 +59,6 @@ #include #include -#define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" #define ACPI_PROCESSOR_DEVICE_NAME "Processor" #define ACPI_PROCESSOR_FILE_INFO "info" diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 81b40ed5379e..5f8d746a9b81 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -59,7 +59,6 @@ #include #include -#define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_idle"); diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index dbcf260ea93f..0d7b772bef50 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -44,9 +44,9 @@ #endif #include +#include #include -#define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" #define ACPI_PROCESSOR_FILE_PERFORMANCE "performance" #define _COMPONENT ACPI_PROCESSOR_COMPONENT diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index ef34b18f95ca..b1eb376fae45 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -40,7 +40,6 @@ #include #include -#define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_thermal"); diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 3da2df93d924..a0c38c94a8a0 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -38,9 +38,9 @@ #include #include +#include #include -#define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_throttling"); diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index ad6cae938f0b..a6da1d9918c7 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -47,7 +47,6 @@ #include #include -#define ACPI_THERMAL_COMPONENT 0x04000000 #define ACPI_THERMAL_CLASS "thermal_zone" #define ACPI_THERMAL_DEVICE_NAME "Thermal Zone" #define ACPI_THERMAL_FILE_STATE "state" diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bf0c26a7368d..a3aad30d39f6 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -41,7 +41,6 @@ #include #include -#define ACPI_VIDEO_COMPONENT 0x08000000 #define ACPI_VIDEO_CLASS "video" #define ACPI_VIDEO_BUS_NAME "Video Bus" #define ACPI_VIDEO_DEVICE_NAME "Video Device" -- cgit v1.2.3 From bdd7279919f682da8752fb47784a1ee302f8b7ea Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 7 Nov 2008 16:57:55 -0700 Subject: ACPI: add driver component definitions to sysfs debug_layers /sys/module/acpi/parameters/debug_layers used to contain only the debug layers defined by the ACPI CA. This patch adds the additional layer definitions for ACPI drivers. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/debug.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index abf36b4b1d1d..c48396892008 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c @@ -44,6 +44,21 @@ static const struct acpi_dlayer acpi_debug_layers[] = { ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER), ACPI_DEBUG_INIT(ACPI_COMPILER), ACPI_DEBUG_INIT(ACPI_TOOLS), + + ACPI_DEBUG_INIT(ACPI_BUS_COMPONENT), + ACPI_DEBUG_INIT(ACPI_AC_COMPONENT), + ACPI_DEBUG_INIT(ACPI_BATTERY_COMPONENT), + ACPI_DEBUG_INIT(ACPI_BUTTON_COMPONENT), + ACPI_DEBUG_INIT(ACPI_SBS_COMPONENT), + ACPI_DEBUG_INIT(ACPI_FAN_COMPONENT), + ACPI_DEBUG_INIT(ACPI_PCI_COMPONENT), + ACPI_DEBUG_INIT(ACPI_POWER_COMPONENT), + ACPI_DEBUG_INIT(ACPI_CONTAINER_COMPONENT), + ACPI_DEBUG_INIT(ACPI_SYSTEM_COMPONENT), + ACPI_DEBUG_INIT(ACPI_THERMAL_COMPONENT), + ACPI_DEBUG_INIT(ACPI_MEMORY_DEVICE_COMPONENT), + ACPI_DEBUG_INIT(ACPI_VIDEO_COMPONENT), + ACPI_DEBUG_INIT(ACPI_PROCESSOR_COMPONENT), }; static const struct acpi_dlevel acpi_debug_levels[] = { -- cgit v1.2.3 From 87b586088ef953c602680e5aff8ab83a2e299498 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 7 Nov 2008 16:58:00 -0700 Subject: ACPI: turn off all debug output by default When CONFIG_ACPI_DEBUG=y, the default acpi_dbg_layer and acpi_dbg_level values built into the ACPI CA have some debug output enabled. We'd rather be quiet unless the user actually specified the acpi.debug_level argument. This enables distros to ship with CONFIG_ACPI_DEBUG=y without inundating users with debug output. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/bus.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 765fd1c56cd6..7edf6d913c13 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -688,6 +688,14 @@ void __init acpi_early_init(void) if (acpi_disabled) return; + /* + * ACPI CA initializes acpi_dbg_level to non-zero, which means + * we get debug output merely by turning on CONFIG_ACPI_DEBUG. + * Turn it off so we don't get output unless the user specifies + * acpi.debug_level. + */ + acpi_dbg_level = 0; + printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION); /* enable workarounds, unless strict ACPI spec. compliance */ -- cgit v1.2.3 From a0d84a92df43b7206b9c1330a2cccf109cf0a41a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 7 Nov 2008 16:58:05 -0700 Subject: ACPI: update debug parameter documentation Reformat acpi.debug_layer and acpi.debug_level documentation so it's more readable, add some clues about how to figure out the mask bits that enable a specific ACPI_DEBUG_PRINT statement, and include some useful examples. Move the list of masks to Documentation/acpi/debug.txt (these are copies of the authoritative values in acoutput.h and acpi_drivers.h). Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 90cb2a823b56..b0243fd55ac0 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -312,9 +312,13 @@ config ACPI_DEBUG bool "Debug Statements" default n help - The ACPI driver can optionally report errors with a great deal - of verbosity. Saying Y enables these statements. This will increase - your kernel size by around 50K. + The ACPI subsystem can produce debug output. Saying Y enables this + output and increases the kernel size by around 50K. + + Use the acpi.debug_layer and acpi.debug_level kernel command-line + parameters documented in Documentation/acpi/debug.txt and + Documentation/kernel-parameters.txt to control the type and + amount of debug output. config ACPI_DEBUG_FUNC_TRACE bool "Additionally enable ACPI function tracing" -- cgit v1.2.3 From a1a8d334f9e8c89a15bba8f34e443a37c29079c3 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 31 Jul 2008 23:02:28 +0200 Subject: Delete an unwanted return statement at evgpe.c Len's tree branch release-2.6.27, found an unwanted return statement at evgpe.c. (git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6 release-2.6.27) Signed-of-by Lin Ming Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/events/evgpe.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index c5e53aae86f7..f45c74fe745e 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c @@ -289,8 +289,6 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) */ status = acpi_hw_low_disable_gpe(gpe_event_info); return_ACPI_STATUS(status); - - return_ACPI_STATUS(AE_OK); } /******************************************************************************* -- cgit v1.2.3 From 22c13f9d8179f4c9caecfcb60a95214562b9addc Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 1 Aug 2008 17:37:54 +0200 Subject: ACPI: video: Ignore devices that aren't present in hardware This is a reimplemention of commit 0119509c4fbc9adcef1472817fda295334612976 from Matthew Garrett This patch got removed because of a regression: ThinkPads with a Intel graphics card and an Integrated Graphics Device BIOS implementation stopped working. In fact, they only worked because the ACPI device of the discrete, the wrong one, got used (via int10). So ACPI functions were poking on the wrong hardware used which is a sever bug. The next patch provides support for above ThinkPads to be able to switch brightness via the legacy thinkpad_acpi driver and automatically detect when to use it. Original commit message from Matthew Garrett: Vendors often ship machines with a choice of integrated or discrete graphics, and use the same DSDT for both. As a result, the ACPI video module will locate devices that may not exist on this specific platform. Attempt to determine whether the device exists or not, and abort the device creation if it doesn't. http://bugzilla.kernel.org/show_bug.cgi?id=9614 Signed-off-by: Thomas Renninger Acked-by: Zhang Rui Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/glue.c | 40 ++++++++++++++++++++++++++++++++++++++++ drivers/acpi/video.c | 7 ++++++- 2 files changed, 46 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 24649ada08df..adec3d15810a 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -140,6 +140,46 @@ struct device *acpi_get_physical_device(acpi_handle handle) EXPORT_SYMBOL(acpi_get_physical_device); +/* ToDo: When a PCI bridge is found, return the PCI device behind the bridge + * This should work in general, but did not on a Lenovo T61 for the + * graphics card. But this must be fixed when the PCI device is + * bound and the kernel device struct is attached to the acpi device + * Note: A success call will increase reference count by one + * Do call put_device(dev) on the returned device then + */ +struct device *acpi_get_physical_pci_device(acpi_handle handle) +{ + struct device *dev; + long long device_id; + acpi_status status; + + status = + acpi_evaluate_integer(handle, "_ADR", NULL, &device_id); + + if (ACPI_FAILURE(status)) + return NULL; + + /* We need to attempt to determine whether the _ADR refers to a + PCI device or not. There's no terribly good way to do this, + so the best we can hope for is to assume that there'll never + be a device in the host bridge */ + if (device_id >= 0x10000) { + /* It looks like a PCI device. Does it exist? */ + dev = acpi_get_physical_device(handle); + } else { + /* It doesn't look like a PCI device. Does its parent + exist? */ + acpi_handle phandle; + if (acpi_get_parent(handle, &phandle)) + return NULL; + dev = acpi_get_physical_device(phandle); + } + if (!dev) + return NULL; + return dev; +} +EXPORT_SYMBOL(acpi_get_physical_pci_device); + static int acpi_bind_one(struct device *dev, acpi_handle handle) { struct acpi_device *acpi_dev; diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index a29b0ccac65a..6597c2a37c36 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -842,11 +842,16 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video) static int acpi_video_bus_check(struct acpi_video_bus *video) { acpi_status status = -ENOENT; - + struct device *dev; if (!video) return -EINVAL; + dev = acpi_get_physical_pci_device(video->device->handle); + if (!dev) + return -ENODEV; + put_device(dev); + /* Since there is no HID, CID and so on for VGA driver, we have * to check well known required nodes. */ -- cgit v1.2.3 From c3d6de698c84efdbdd3781b7058bcc339ab43da8 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 1 Aug 2008 17:37:55 +0200 Subject: ACPI video: if no ACPI backlight support, use vendor drivers If an ACPI graphics device supports backlight brightness functions (cmp. with latest ACPI spec Appendix B), let the ACPI video driver control backlight and switch backlight control off in vendor specific ACPI drivers (asus_acpi, thinkpad_acpi, eeepc, fujitsu_laptop, msi_laptop, sony_laptop, acer-wmi). Currently it is possible to load above drivers and let both poke on the brightness HW registers, the video and vendor specific ACPI drivers -> bad. This patch provides the basic support to check for BIOS capabilities before driver loading time. Driver specific modifications are in separate follow up patches. "acpi_backlight=vendor" Prever vendor driver over ACPI driver for backlight. "acpi_backlight=video" (default) Prever ACPI driver over vendor driver for backlight. Signed-off-by: Thomas Renninger Acked-by: Zhang Rui Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/Makefile | 4 + drivers/acpi/scan.c | 32 +----- drivers/acpi/video.c | 28 +++-- drivers/acpi/video_detect.c | 268 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 289 insertions(+), 43 deletions(-) create mode 100644 drivers/acpi/video_detect.c (limited to 'drivers/acpi') diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index d91c027ece8f..c03810aa19c0 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -46,6 +46,10 @@ obj-$(CONFIG_ACPI_BUTTON) += button.o obj-$(CONFIG_ACPI_FAN) += fan.o obj-$(CONFIG_ACPI_DOCK) += dock.o obj-$(CONFIG_ACPI_VIDEO) += video.o +ifdef CONFIG_ACPI_VIDEO +obj-y += video_detect.o +endif + obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o obj-$(CONFIG_ACPI_PROCESSOR) += processor.o diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a9dda8e0f9f9..556b182001ca 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -919,36 +919,6 @@ static void acpi_device_get_busid(struct acpi_device *device, } } -static int -acpi_video_bus_match(struct acpi_device *device) -{ - acpi_handle h_dummy; - - if (!device) - return -EINVAL; - - /* Since there is no HID, CID for ACPI Video drivers, we have - * to check well known required nodes for each feature we support. - */ - - /* Does this device able to support video switching ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy))) - return 0; - - /* Does this device able to retrieve a video ROM ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy))) - return 0; - - /* Does this device able to configure which video head to be POSTed ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy))) - return 0; - - return -ENODEV; -} - /* * acpi_bay_match - see if a device is an ejectable driver bay * @@ -1031,7 +1001,7 @@ static void acpi_device_set_id(struct acpi_device *device, will get autoloaded and the device might still match against another driver. */ - if (ACPI_SUCCESS(acpi_video_bus_match(device))) + if (acpi_is_video_device(device)) cid_add = ACPI_VIDEO_HID; else if (ACPI_SUCCESS(acpi_bay_match(device))) cid_add = ACPI_BAY_HID; diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 6597c2a37c36..2097c399dd06 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -739,7 +739,8 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) device->cap._DSS = 1; } - max_level = acpi_video_init_brightness(device); + if (acpi_video_backlight_support()) + max_level = acpi_video_init_brightness(device); if (device->cap._BCL && device->cap._BCM && max_level > 0) { int result; @@ -785,18 +786,21 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) printk(KERN_ERR PREFIX "Create sysfs link\n"); } - if (device->cap._DCS && device->cap._DSS){ - static int count = 0; - char *name; - name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); - if (!name) - return; - sprintf(name, "acpi_video%d", count++); - device->output_dev = video_output_register(name, - NULL, device, &acpi_output_properties); - kfree(name); + + if (acpi_video_display_switch_support()) { + + if (device->cap._DCS && device->cap._DSS) { + static int count; + char *name; + name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); + if (!name) + return; + sprintf(name, "acpi_video%d", count++); + device->output_dev = video_output_register(name, + NULL, device, &acpi_output_properties); + kfree(name); + } } - return; } /* diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c new file mode 100644 index 000000000000..70b1e91ae2ab --- /dev/null +++ b/drivers/acpi/video_detect.c @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2008 SuSE Linux Products GmbH + * Thomas Renninger + * + * May be copied or modified under the terms of the GNU General Public License + * + * video_detect.c: + * Provides acpi_is_video_device() for early scanning of ACPI devices in scan.c + * There a Linux specific (Spec does not provide a HID for video devices) is + * assinged + * + * After PCI devices are glued with ACPI devices + * acpi_get_physical_pci_device() can be called to identify ACPI graphics + * devices for which a real graphics card is plugged in + * + * Now acpi_video_get_capabilities() can be called to check which + * capabilities the graphics cards plugged in support. The check for general + * video capabilities will be triggered by the first caller of + * acpi_video_get_capabilities(NULL); which will happen when the first + * backlight (or display output) switching supporting driver calls: + * acpi_video_backlight_support(); + * + * Depending on whether ACPI graphics extensions (cmp. ACPI spec Appendix B) + * are available, video.ko should be used to handle the device. + * + * Otherwise vendor specific drivers like thinkpad_acpi, asus_acpi, + * sony_acpi,... can take care about backlight brightness and display output + * switching. + * + * If CONFIG_ACPI_VIDEO is neither set as "compiled in" (y) nor as a module (m) + * this file will not be compiled, acpi_video_get_capabilities() and + * acpi_video_backlight_support() will always return 0 and vendor specific + * drivers always can handle backlight. + * + */ + +#include +#include + +ACPI_MODULE_NAME("video"); +#define ACPI_VIDEO_COMPONENT 0x08000000 +#define _COMPONENT ACPI_VIDEO_COMPONENT + +static long acpi_video_support; +static bool acpi_video_caps_checked; + +static acpi_status +acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context, + void **retyurn_value) +{ + long *cap = context; + acpi_handle h_dummy; + + if (ACPI_SUCCESS(acpi_get_handle(handle, "_BCM", &h_dummy)) && + ACPI_SUCCESS(acpi_get_handle(handle, "_BCL", &h_dummy))) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight " + "support\n")); + *cap |= ACPI_VIDEO_BACKLIGHT; + /* We have backlight support, no need to scan further */ + return AE_CTRL_TERMINATE; + } + return 0; +} + +/* Returns true if the device is a video device which can be handled by + * video.ko. + * The device will get a Linux specific CID added in scan.c to + * identify the device as an ACPI graphics device + * Be aware that the graphics device may not be physically present + * Use acpi_video_get_capabilities() to detect general ACPI video + * capabilities of present cards + */ +long acpi_is_video_device(struct acpi_device *device) +{ + acpi_handle h_dummy; + long video_caps = 0; + + if (!device) + return 0; + + /* Does this device able to support video switching ? */ + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy))) + video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING; + + /* Does this device able to retrieve a video ROM ? */ + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy))) + video_caps |= ACPI_VIDEO_ROM_AVAILABLE; + + /* Does this device able to configure which video head to be POSTed ? */ + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy))) + video_caps |= ACPI_VIDEO_DEVICE_POSTING; + + /* Only check for backlight functionality if one of the above hit. */ + if (video_caps) + acpi_walk_namespace(ACPI_TYPE_DEVICE, device->handle, + ACPI_UINT32_MAX, acpi_backlight_cap_match, + &video_caps, NULL); + + return video_caps; +} +EXPORT_SYMBOL(acpi_is_video_device); + +static acpi_status +find_video(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + long *cap = context; + struct device *dev; + struct acpi_device *acpi_dev; + + const struct acpi_device_id video_ids[] = { + {ACPI_VIDEO_HID, 0}, + {"", 0}, + }; + if (acpi_bus_get_device(handle, &acpi_dev)) + return AE_OK; + + if (!acpi_match_device_ids(acpi_dev, video_ids)) { + dev = acpi_get_physical_pci_device(handle); + if (!dev) + return AE_OK; + put_device(dev); + *cap |= acpi_is_video_device(acpi_dev); + } + return AE_OK; +} + +/* + * Returns the video capabilities of a specific ACPI graphics device + * + * if NULL is passed as argument all ACPI devices are enumerated and + * all graphics capabilities of physically present devices are + * summerized and returned. This is cached and done only once. + */ +long acpi_video_get_capabilities(acpi_handle graphics_handle) +{ + long caps = 0; + struct acpi_device *tmp_dev; + acpi_status status; + + if (acpi_video_caps_checked && graphics_handle == NULL) + return acpi_video_support; + + if (!graphics_handle) { + /* Only do the global walk through all graphics devices once */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, find_video, + &caps, NULL); + /* There might be boot param flags set already... */ + acpi_video_support |= caps; + acpi_video_caps_checked = 1; + /* Add blacklists here. Be careful to use the right *DMI* bits + * to still be able to override logic via boot params, e.g.: + * + * if (dmi_name_in_vendors("XY")) { + * acpi_video_support |= + * ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR; + * acpi_video_support |= + * ACPI_VIDEO_BACKLIGHT_DMI_VENDOR; + *} + */ + } else { + status = acpi_bus_get_device(graphics_handle, &tmp_dev); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Invalid device")); + return 0; + } + acpi_walk_namespace(ACPI_TYPE_DEVICE, graphics_handle, + ACPI_UINT32_MAX, find_video, + &caps, NULL); + } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "We have 0x%lX video support %s %s\n", + graphics_handle ? caps : acpi_video_support, + graphics_handle ? "on device " : "in general", + graphics_handle ? acpi_device_bid(tmp_dev) : "")); + return caps; +} +EXPORT_SYMBOL(acpi_video_get_capabilities); + +/* Returns true if video.ko can do backlight switching */ +int acpi_video_backlight_support(void) +{ + /* + * We must check whether the ACPI graphics device is physically plugged + * in. Therefore this must be called after binding PCI and ACPI devices + */ + if (!acpi_video_caps_checked) + acpi_video_get_capabilities(NULL); + + /* First check for boot param -> highest prio */ + if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR) + return 0; + else if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO) + return 1; + + /* Then check for DMI blacklist -> second highest prio */ + if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_DMI_VENDOR) + return 0; + else if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_DMI_VIDEO) + return 1; + + /* Then go the default way */ + return acpi_video_support & ACPI_VIDEO_BACKLIGHT; +} +EXPORT_SYMBOL(acpi_video_backlight_support); + +/* + * Returns true if video.ko can do display output switching. + * This does not work well/at all with binary graphics drivers + * which disable system io ranges and do it on their own. + */ +int acpi_video_display_switch_support(void) +{ + if (!acpi_video_caps_checked) + acpi_video_get_capabilities(NULL); + + if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR) + return 0; + else if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO) + return 1; + + if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR) + return 0; + else if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO) + return 1; + + return acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING; +} +EXPORT_SYMBOL(acpi_video_display_switch_support); + +/* + * Use acpi_display_output=vendor/video or acpi_backlight=vendor/video + * To force that backlight or display output switching is processed by vendor + * specific acpi drivers or video.ko driver. + */ +int __init acpi_backlight(char *str) +{ + if (str == NULL || *str == '\0') + return 1; + else { + if (!strcmp("vendor", str)) + acpi_video_support |= + ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR; + if (!strcmp("video", str)) + acpi_video_support |= + ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO; + } + return 1; +} +__setup("acpi_backlight=", acpi_backlight); + +int __init acpi_display_output(char *str) +{ + if (str == NULL || *str == '\0') + return 1; + else { + if (!strcmp("vendor", str)) + acpi_video_support |= + ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR; + if (!strcmp("video", str)) + acpi_video_support |= + ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO; + } + return 1; +} +__setup("acpi_display_output=", acpi_display_output); -- cgit v1.2.3 From 1cfe62c8010ac56e1bd3827e30386a87cc2f3594 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Tue, 28 Oct 2008 00:35:30 +0300 Subject: ACPI: EC: revert msleep patch With the better solution for EC interrupt storm issue, there is no need to use msleep over udelay. References: http://bugzilla.kernel.org/show_bug.cgi?id=11810 http://bugzilla.kernel.org/show_bug.cgi?id=10724 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index ef42316f89f5..3ef5b796a685 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -239,10 +239,10 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state) static int ec_poll(struct acpi_ec *ec) { unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); - msleep(1); + udelay(ACPI_EC_UDELAY); while (time_before(jiffies, delay)) { gpe_transaction(ec, acpi_ec_read_status(ec)); - msleep(1); + udelay(ACPI_EC_UDELAY); if (ec_transaction_done(ec)) return 0; } -- cgit v1.2.3 From f8248434e6a11d7cd314281be3b39bbcf82fc243 Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Sat, 1 Nov 2008 11:05:26 +0000 Subject: ACPI: EC: make kernel messages more useful when GPE storm is detected Make sure we can tell if the GPE storm workaround gets activated, and avoid flooding the logs afterwards. http://bugzilla.kernel.org/show_bug.cgi?id=11841 "plenty of line "ACPI: EC: non-query interrupt received, switching to interrupt mode" in dmesg" Signed-off-by: Alan Jenkins Acked-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 3ef5b796a685..b340e08cf1d9 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -286,7 +286,8 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && t->irq_count > ACPI_EC_STORM_THRESHOLD) { - pr_debug(PREFIX "GPE storm detected\n"); + pr_info(PREFIX "GPE storm detected, " + "transactions will use polling mode\n"); set_bit(EC_FLAGS_GPE_STORM, &ec->flags); } return ret; @@ -566,9 +567,15 @@ static u32 acpi_ec_gpe_handler(void *data) if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && !test_bit(EC_FLAGS_NO_GPE, &ec->flags)) { /* this is non-query, must be confirmation */ - if (printk_ratelimit()) - pr_info(PREFIX "non-query interrupt received," + if (!test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + if (printk_ratelimit()) + pr_info(PREFIX "non-query interrupt received," + " switching to interrupt mode\n"); + } else { + /* hush, STORM switches the mode every transaction */ + pr_debug(PREFIX "non-query interrupt received," " switching to interrupt mode\n"); + } set_bit(EC_FLAGS_GPE_MODE, &ec->flags); } return ACPI_INTERRUPT_HANDLED; -- cgit v1.2.3 From dd15f8c42af09031e27da5b4d697ce925511f2e1 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Sat, 8 Nov 2008 21:42:30 +0300 Subject: ACPI: EC: wait for last write gpe There is a possibility that EC might break if next command is issued within 1 us after write or burst-disable command. Suggestd-by: Zhao Yakui Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index b340e08cf1d9..cebd65d2e2a9 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -102,6 +102,7 @@ struct transaction { u8 command; u8 wlen; u8 rlen; + bool done; }; static struct acpi_ec { @@ -178,7 +179,7 @@ static int ec_transaction_done(struct acpi_ec *ec) unsigned long flags; int ret = 0; spin_lock_irqsave(&ec->curr_lock, flags); - if (!ec->curr || (!ec->curr->wlen && !ec->curr->rlen)) + if (!ec->curr || ec->curr->done) ret = 1; spin_unlock_irqrestore(&ec->curr_lock, flags); return ret; @@ -195,17 +196,20 @@ static void gpe_transaction(struct acpi_ec *ec, u8 status) acpi_ec_write_data(ec, *(ec->curr->wdata++)); --ec->curr->wlen; } else - /* false interrupt, state didn't change */ - ++ec->curr->irq_count; - + goto err; } else if (ec->curr->rlen > 0) { if ((status & ACPI_EC_FLAG_OBF) == 1) { *(ec->curr->rdata++) = acpi_ec_read_data(ec); - --ec->curr->rlen; + if (--ec->curr->rlen == 0) + ec->curr->done = true; } else - /* false interrupt, state didn't change */ - ++ec->curr->irq_count; - } + goto err; + } else if (ec->curr->wlen == 0 && (status & ACPI_EC_FLAG_IBF) == 0) + ec->curr->done = true; + goto unlock; +err: + /* false interrupt, state didn't change */ + ++ec->curr->irq_count; unlock: spin_unlock_irqrestore(&ec->curr_lock, flags); } @@ -265,6 +269,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, spin_lock_irqsave(&ec->curr_lock, tmp); /* following two actions should be kept atomic */ t->irq_count = 0; + t->done = false; ec->curr = t; acpi_ec_write_cmd(ec, ec->curr->command); if (ec->curr->command == ACPI_EC_COMMAND_QUERY) -- cgit v1.2.3 From a2f93aeadf97e870ff385030633a73e21146815d Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 12 Nov 2008 01:40:19 +0300 Subject: ACPI: EC: restart failed command Restart current transaction if we recieved unexpected GPEs instead of needed ones. http://bugzilla.kernel.org/show_bug.cgi?id=11896 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index cebd65d2e2a9..34c67ca3bebe 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -100,6 +100,8 @@ struct transaction { u8 *rdata; unsigned short irq_count; u8 command; + u8 wi; + u8 ri; u8 wlen; u8 rlen; bool done; @@ -185,26 +187,34 @@ static int ec_transaction_done(struct acpi_ec *ec) return ret; } +static void start_transaction(struct acpi_ec *ec) +{ + ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0; + ec->curr->done = false; + acpi_ec_write_cmd(ec, ec->curr->command); +} + static void gpe_transaction(struct acpi_ec *ec, u8 status) { unsigned long flags; spin_lock_irqsave(&ec->curr_lock, flags); if (!ec->curr) goto unlock; - if (ec->curr->wlen > 0) { - if ((status & ACPI_EC_FLAG_IBF) == 0) { - acpi_ec_write_data(ec, *(ec->curr->wdata++)); - --ec->curr->wlen; - } else + if (ec->curr->wlen > ec->curr->wi) { + if ((status & ACPI_EC_FLAG_IBF) == 0) + acpi_ec_write_data(ec, + ec->curr->wdata[ec->curr->wi++]); + else goto err; - } else if (ec->curr->rlen > 0) { + } else if (ec->curr->rlen > ec->curr->ri) { if ((status & ACPI_EC_FLAG_OBF) == 1) { - *(ec->curr->rdata++) = acpi_ec_read_data(ec); - if (--ec->curr->rlen == 0) + ec->curr->rdata[ec->curr->ri++] = acpi_ec_read_data(ec); + if (ec->curr->rlen == ec->curr->ri) ec->curr->done = true; } else goto err; - } else if (ec->curr->wlen == 0 && (status & ACPI_EC_FLAG_IBF) == 0) + } else if (ec->curr->wlen == ec->curr->wi && + (status & ACPI_EC_FLAG_IBF) == 0) ec->curr->done = true; goto unlock; err: @@ -219,6 +229,15 @@ static int acpi_ec_wait(struct acpi_ec *ec) if (wait_event_timeout(ec->wait, ec_transaction_done(ec), msecs_to_jiffies(ACPI_EC_DELAY))) return 0; + /* try restart command if we get any false interrupts */ + if (ec->curr->irq_count && + (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { + pr_debug(PREFIX "controller reset, restart transaction\n"); + start_transaction(ec); + if (wait_event_timeout(ec->wait, ec_transaction_done(ec), + msecs_to_jiffies(ACPI_EC_DELAY))) + return 0; + } /* missing GPEs, switch back to poll mode */ if (printk_ratelimit()) pr_info(PREFIX "missing confirmations, " @@ -268,10 +287,8 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, /* start transaction */ spin_lock_irqsave(&ec->curr_lock, tmp); /* following two actions should be kept atomic */ - t->irq_count = 0; - t->done = false; ec->curr = t; - acpi_ec_write_cmd(ec, ec->curr->command); + start_transaction(ec); if (ec->curr->command == ACPI_EC_COMMAND_QUERY) clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); spin_unlock_irqrestore(&ec->curr_lock, tmp); -- cgit v1.2.3 From 0b7084ac67fb84f0cf2f8bc02d7e0dea8521dd2d Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Sat, 25 Oct 2008 21:48:46 +0400 Subject: ACPICA: Use spinlock for acpi_{en|dis}able_gpe Disabling gpe might interfere with gpe detection/handling, thus producing "interrupt not handled" errors. Ironically, disabling of GPE from interrupt context is already under spinlock, so only userspace needs to start using it. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/button.c | 2 +- drivers/acpi/ec.c | 10 +++++----- drivers/acpi/events/evxfevnt.c | 35 +++++++++-------------------------- drivers/acpi/sleep/wakeup.c | 8 ++++---- drivers/acpi/system.c | 4 ++-- 5 files changed, 21 insertions(+), 38 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index cb046c3fc3f2..eb6bf3025f97 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -479,7 +479,7 @@ static int acpi_button_add(struct acpi_device *device) device->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN); acpi_enable_gpe(device->wakeup.gpe_device, - device->wakeup.gpe_number, ACPI_NOT_ISR); + device->wakeup.gpe_number); device->wakeup.state.enabled = 1; } diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 34c67ca3bebe..89d6d2868e8c 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -282,7 +282,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, /* disable GPE during transaction if storm is detected */ if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); - acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + acpi_disable_gpe(NULL, ec->gpe); } /* start transaction */ spin_lock_irqsave(&ec->curr_lock, tmp); @@ -305,7 +305,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, /* check if we received SCI during transaction */ ec_check_sci(ec, acpi_ec_read_status(ec)); /* it is safe to enable GPE outside of transaction */ - acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->gpe); } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && t->irq_count > ACPI_EC_STORM_THRESHOLD) { pr_info(PREFIX "GPE storm detected, " @@ -897,7 +897,7 @@ static int ec_install_handlers(struct acpi_ec *ec) if (ACPI_FAILURE(status)) return -ENODEV; acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); - acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->gpe); status = acpi_install_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, @@ -1036,7 +1036,7 @@ static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state) /* Stop using GPE */ set_bit(EC_FLAGS_NO_GPE, &ec->flags); clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); - acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + acpi_disable_gpe(NULL, ec->gpe); return 0; } @@ -1045,7 +1045,7 @@ static int acpi_ec_resume(struct acpi_device *device) struct acpi_ec *ec = acpi_driver_data(device); /* Enable use of GPE back */ clear_bit(EC_FLAGS_NO_GPE, &ec->flags); - acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->gpe); return 0; } diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c index 73bfd6bf962f..39db00874a22 100644 --- a/drivers/acpi/events/evxfevnt.c +++ b/drivers/acpi/events/evxfevnt.c @@ -248,21 +248,15 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe_type) * DESCRIPTION: Enable an ACPI event (general purpose) * ******************************************************************************/ -acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) +acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) { acpi_status status = AE_OK; + acpi_cpu_flags flags; struct acpi_gpe_event_info *gpe_event_info; ACPI_FUNCTION_TRACE(acpi_enable_gpe); - /* Use semaphore lock if not executing at interrupt level */ - - if (flags & ACPI_NOT_ISR) { - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); /* Ensure that we have a valid GPE number */ @@ -277,9 +271,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) status = acpi_ev_enable_gpe(gpe_event_info, TRUE); unlock_and_exit: - if (flags & ACPI_NOT_ISR) { - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - } + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } @@ -299,22 +291,15 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe) * DESCRIPTION: Disable an ACPI event (general purpose) * ******************************************************************************/ -acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) +acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) { acpi_status status = AE_OK; + acpi_cpu_flags flags; struct acpi_gpe_event_info *gpe_event_info; ACPI_FUNCTION_TRACE(acpi_disable_gpe); - /* Use semaphore lock if not executing at interrupt level */ - - if (flags & ACPI_NOT_ISR) { - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); /* Ensure that we have a valid GPE number */ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); @@ -325,10 +310,8 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) status = acpi_ev_disable_gpe(gpe_event_info); - unlock_and_exit: - if (flags & ACPI_NOT_ISR) { - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - } +unlock_and_exit: + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c index 38655eb132dc..dea4c23df764 100644 --- a/drivers/acpi/sleep/wakeup.c +++ b/drivers/acpi/sleep/wakeup.c @@ -88,7 +88,7 @@ void acpi_enable_wakeup_device(u8 sleep_state) spin_unlock(&acpi_device_lock); if (!dev->wakeup.flags.run_wake) acpi_enable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, ACPI_ISR); + dev->wakeup.gpe_number); spin_lock(&acpi_device_lock); } spin_unlock(&acpi_device_lock); @@ -122,7 +122,7 @@ void acpi_disable_wakeup_device(u8 sleep_state) ACPI_GPE_TYPE_WAKE_RUN); /* Re-enable it, since set_gpe_type will disable it */ acpi_enable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, ACPI_NOT_ISR); + dev->wakeup.gpe_number); spin_lock(&acpi_device_lock); } continue; @@ -133,7 +133,7 @@ void acpi_disable_wakeup_device(u8 sleep_state) /* Never disable run-wake GPE */ if (!dev->wakeup.flags.run_wake) { acpi_disable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, ACPI_NOT_ISR); + dev->wakeup.gpe_number); acpi_clear_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, ACPI_NOT_ISR); } @@ -162,7 +162,7 @@ static int __init acpi_wakeup_device_init(void) dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN); acpi_enable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, ACPI_NOT_ISR); + dev->wakeup.gpe_number); dev->wakeup.state.enabled = 1; spin_lock(&acpi_device_lock); } diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 1d74171b7940..11995b612ad7 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -394,10 +394,10 @@ static ssize_t counter_set(struct kobject *kobj, if (index < num_gpes) { if (!strcmp(buf, "disable\n") && (status & ACPI_EVENT_FLAG_ENABLED)) - result = acpi_disable_gpe(handle, index, ACPI_NOT_ISR); + result = acpi_disable_gpe(handle, index); else if (!strcmp(buf, "enable\n") && !(status & ACPI_EVENT_FLAG_ENABLED)) - result = acpi_enable_gpe(handle, index, ACPI_NOT_ISR); + result = acpi_enable_gpe(handle, index); else if (!strcmp(buf, "clear\n") && (status & ACPI_EVENT_FLAG_SET)) result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR); -- cgit v1.2.3 From 06cf7d3c7af902939cd1754abcafb2464060cba8 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Sun, 9 Nov 2008 19:01:06 +0300 Subject: ACPI: EC: lower interrupt storm treshold http://bugzilla.kernel.org/show_bug.cgi?id=11892 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 89d6d2868e8c..ab84f99f1369 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -70,7 +70,7 @@ enum ec_command { #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ #define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */ -#define ACPI_EC_STORM_THRESHOLD 20 /* number of false interrupts +#define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts per one transaction */ enum { -- cgit v1.2.3 From 8517934ef6aaa28d6e055b98df65b31cedbd1372 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Tue, 11 Nov 2008 12:54:11 +0300 Subject: ACPI: EC: Don't do transaction from GPE handler in poll mode. Referencies: http://bugzilla.kernel.org/show_bug.cgi?id=12004 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index ab84f99f1369..bd1af3e9e4ce 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -581,9 +581,12 @@ static u32 acpi_ec_gpe_handler(void *data) pr_debug(PREFIX "~~~> interrupt\n"); status = acpi_ec_read_status(ec); - gpe_transaction(ec, status); - if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) - wake_up(&ec->wait); + if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) { + gpe_transaction(ec, status); + if (ec_transaction_done(ec) && + (status & ACPI_EC_FLAG_IBF) == 0) + wake_up(&ec->wait); + } ec_check_sci(ec, status); if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && -- cgit v1.2.3 From 32836259ff25ce97010569706cd33ba94de81d62 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 5 Nov 2008 16:17:52 -0700 Subject: ACPI: pci_link: remove acpi_irq_balance_set() interface This removes the acpi_irq_balance_set() interface from the PCI interrupt link driver. x86 used acpi_irq_balance_set() to tell the PCI interrupt link driver to configure links to minimize IRQ sharing. But the link driver can easily figure out whether to turn on IRQ balancing based on the IRQ model (PIC/IOAPIC/etc), so we can get rid of that external interface. It's better for the driver to figure this out at init-time. If we set it externally via the x86 code, the interface reduces modularity, and we depend on the fact that acpi_process_madt() happens before we process the kernel command line. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_link.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index fcfdef7b4fdd..e52ad91ce2dc 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -531,7 +531,7 @@ int __init acpi_irq_penalty_init(void) return 0; } -static int acpi_irq_balance; /* 0: static, 1: balance */ +static int acpi_irq_balance = -1; /* 0: static, 1: balance */ static int acpi_pci_link_allocate(struct acpi_pci_link *link) { @@ -950,10 +950,17 @@ device_initcall(irqrouter_init_sysfs); static int __init acpi_pci_link_init(void) { - if (acpi_noirq) return 0; + if (acpi_irq_balance == -1) { + /* no command line switch: enable balancing in IOAPIC mode */ + if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) + acpi_irq_balance = 1; + else + acpi_irq_balance = 0; + } + acpi_link.count = 0; INIT_LIST_HEAD(&acpi_link.entries); -- cgit v1.2.3 From 77fb61a04a0483ad274ce5c51b02c46c12db3693 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 16 Nov 2008 10:09:34 -0800 Subject: acpi: fix oops in acpi_system_wakeup_device_seq_show MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 0794469da3f7b2093575cbdfc1108308dd3641ce: ("ACPI: struct device - replace bus_id with dev_name(), dev_set_name()") introduced a bug by testing 'dev_name(ldev)' instead of 'ldev->bus' for NULL when printing out the bus information. So if ldev->bus was NULL, we'd oops. Reported-and-tested-by: Bruno Prémont Cc: Kay Sievers Cc: Len Brown Cc: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/acpi/sleep/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 64e591ba86f2..4dbc2271acf5 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c @@ -366,7 +366,7 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) dev->wakeup.state.enabled ? "enabled" : "disabled"); if (ldev) seq_printf(seq, "%s:%s", - dev_name(ldev) ? ldev->bus->name : "no-bus", + ldev->bus ? ldev->bus->name : "no-bus", dev_name(ldev)); seq_printf(seq, "\n"); put_device(ldev); -- cgit v1.2.3 From 7b4d469228a92a00e412675817cedd60133de38a Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Thu, 13 Nov 2008 12:00:03 +0300 Subject: ACPI: EC: count interrupts only if called from interrupt handler. fix 2.6.28 EC interrupt storm regression Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index cf41f9fc24a7..30f3ef236ecb 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -219,7 +219,8 @@ static void gpe_transaction(struct acpi_ec *ec, u8 status) goto unlock; err: /* false interrupt, state didn't change */ - ++ec->curr->irq_count; + if (in_interrupt()) + ++ec->curr->irq_count; unlock: spin_unlock_irqrestore(&ec->curr_lock, flags); } -- cgit v1.2.3 From 558073dd56707864f09d563b64e7c37c021e89d2 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Fri, 21 Nov 2008 22:41:01 +0800 Subject: ACPI: battery: Convert discharge energy rate to current properly ACPI battery interface reports its state either in mW or in mA, and discharge rate in your case is reported in mW. power_supply interface does not have such a parameter, so current_now parameter is used for all cases. But in case of mW, reported discharge should be converted into mA. Signed-off-by: Alexey Starikovskiy Tested-by: Ferenc Wagner Signed-off-by: Len Brown --- drivers/acpi/battery.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 1423b0c0cd2e..a0a178dd189c 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -174,6 +174,15 @@ static int acpi_battery_get_property(struct power_supply *psy, break; case POWER_SUPPLY_PROP_CURRENT_NOW: val->intval = battery->current_now * 1000; + /* if power units are mW, convert to mA by + dividing by current voltage (mV/1000) */ + if (!battery->power_unit) { + if (battery->voltage_now) { + val->intval /= battery->voltage_now; + val->intval *= 1000; + } else + val->intval = -1; + } break; case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: -- cgit v1.2.3 From 40599072dca3ec7d4c9ff8271978be169f974638 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 25 Nov 2008 12:05:08 +0100 Subject: ACPI: scheduling in atomic via acpi_evaluate_integer () Now I know why I had strange "scheduling in atomic" problems: acpi_evaluate_integer() does malloc(..., irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL)... which is (of course) broken. There's no way to reliably tell if we need GFP_ATOMIC or not from code, this one for example fails to detect spinlocks held. Fortunately, allocation seems small enough to be done on stack. Signed-off-by: Pavel Machek Acked-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/utils.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index e827be36ee8d..f844941089bb 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -259,34 +259,26 @@ acpi_evaluate_integer(acpi_handle handle, struct acpi_object_list *arguments, unsigned long long *data) { acpi_status status = AE_OK; - union acpi_object *element; + union acpi_object element; struct acpi_buffer buffer = { 0, NULL }; - if (!data) return AE_BAD_PARAMETER; - element = kzalloc(sizeof(union acpi_object), irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL); - if (!element) - return AE_NO_MEMORY; - buffer.length = sizeof(union acpi_object); - buffer.pointer = element; + buffer.pointer = &element; status = acpi_evaluate_object(handle, pathname, arguments, &buffer); if (ACPI_FAILURE(status)) { acpi_util_eval_error(handle, pathname, status); - kfree(element); return status; } - if (element->type != ACPI_TYPE_INTEGER) { + if (element.type != ACPI_TYPE_INTEGER) { acpi_util_eval_error(handle, pathname, AE_BAD_DATA); - kfree(element); return AE_BAD_DATA; } - *data = element->integer.value; - kfree(element); + *data = element.integer.value; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data)); -- cgit v1.2.3 From 65df78473ffbf3bff5e2034df1638acc4f3ddd50 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 26 Nov 2008 17:53:13 -0500 Subject: ACPI suspend: Blacklist boxes that require us to set SCI_EN directly on resume Some Apple boxes evidently require us to set SCI_EN on resume directly, because if we don't do that, they hung somewhere in the resume code path. Moreover, on these boxes it is not sufficient to use acpi_enable() to turn ACPI on during resume. All of this is against the ACPI specification which states that (1) the BIOS is supposed to return from the S3 sleep state with ACPI enabled (SCI_EN set) and (2) the SCI_EN bit is owned by the hardware and we are not supposed to change it. For this reason, blacklist the affected systems so that the SCI_EN bit is set during resume on them. [NOTE: Unconditional setting SCI_EN for all system on resume doesn't work, because it makes some other systems crash (that's to be expected). Also, it is not entirely clear right now if all of the Apple boxes require this workaround.] This patch fixes the recent regression tracked as http://bugzilla.kernel.org/show_bug.cgi?id=12038 Signed-off-by: Rafael J. Wysocki Tested-by: Tino Keitel Tested-by: Bob Copeland Signed-off-by: Len Brown --- drivers/acpi/sleep/main.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 80c0868d0480..28a691cc625e 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -90,6 +90,18 @@ void __init acpi_old_suspend_ordering(void) old_suspend_ordering = true; } +/* + * According to the ACPI specification the BIOS should make sure that ACPI is + * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, + * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI + * on such systems during resume. Unfortunately that doesn't help in + * particularly pathological cases in which SCI_EN has to be set directly on + * resume, although the specification states very clearly that this flag is + * owned by the hardware. The set_sci_en_on_resume variable will be set in such + * cases. + */ +static bool set_sci_en_on_resume; + /** * acpi_pm_disable_gpes - Disable the GPEs. */ @@ -235,7 +247,11 @@ static int acpi_suspend_enter(suspend_state_t pm_state) } /* If ACPI is not enabled by the BIOS, we need to enable it here. */ - acpi_enable(); + if (set_sci_en_on_resume) + acpi_set_register(ACPI_BITREG_SCI_ENABLE, 1); + else + acpi_enable(); + /* Reprogram control registers and execute _BFS */ acpi_leave_sleep_state_prep(acpi_state); @@ -323,6 +339,12 @@ static int __init init_old_suspend_ordering(const struct dmi_system_id *d) return 0; } +static int __init init_set_sci_en_on_resume(const struct dmi_system_id *d) +{ + set_sci_en_on_resume = true; + return 0; +} + static struct dmi_system_id __initdata acpisleep_dmi_table[] = { { .callback = init_old_suspend_ordering, @@ -340,6 +362,22 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"), }, }, + { + .callback = init_set_sci_en_on_resume, + .ident = "Apple MacBook 1,1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), + }, + }, + { + .callback = init_set_sci_en_on_resume, + .ident = "Apple MacMini 1,1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), + }, + }, {}, }; #endif /* CONFIG_SUSPEND */ -- cgit v1.2.3 From 3bdca1b863c1ebcb2244fc0cb683876d7330e62b Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 26 Nov 2008 17:55:15 -0500 Subject: Revert "ACPI: don't enable control method power button as wakeup device when Fixed Power button is used" This reverts commit faee816b1502385dc9bc5abf2960d1cc645844d1. http://bugzilla.kernel.org/show_bug.cgi?id=12091 Signed-off-by: Len Brown --- drivers/acpi/scan.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index bd5253ee5c85..39b7233c3485 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -751,16 +751,6 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) if (!acpi_match_device_ids(device, button_device_ids)) device->wakeup.flags.run_wake = 1; - /* - * Don't set Power button GPE as run_wake - * if Fixed Power button is used - */ - if (!strcmp(device->pnp.hardware_id, "PNP0C0C") && - !(acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON)) { - device->wakeup.flags.run_wake = 0; - device->wakeup.flags.valid = 0; - } - end: if (ACPI_FAILURE(status)) device->flags.wake_capable = 0; -- cgit v1.2.3 From a6e0887f21bbab337ee32d9c0a84d7c0b6e9141b Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 8 Nov 2008 01:21:10 -0500 Subject: ACPI: delete OSI(Linux) DMI dmesg spam Linux will continue to ignore OSI(Linux), except for a white-list containing a few systems. So delete the black-list, and stop soliciting user-feedback on the console. Signed-off-by: Len Brown --- drivers/acpi/blacklist.c | 401 +---------------------------------------------- drivers/acpi/osl.c | 104 +++--------- 2 files changed, 30 insertions(+), 475 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index ea92bac42c53..09c69806c1fc 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -176,16 +176,6 @@ static int __init dmi_enable_osi_linux(const struct dmi_system_id *d) acpi_dmi_osi_linux(1, d); /* enable */ return 0; } -static int __init dmi_disable_osi_linux(const struct dmi_system_id *d) -{ - acpi_dmi_osi_linux(0, d); /* disable */ - return 0; -} -static int __init dmi_unknown_osi_linux(const struct dmi_system_id *d) -{ - acpi_dmi_osi_linux(-1, d); /* unknown */ - return 0; -} static int __init dmi_disable_osi_vista(const struct dmi_system_id *d) { printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); @@ -193,295 +183,21 @@ static int __init dmi_disable_osi_vista(const struct dmi_system_id *d) return 0; } -/* - * Most BIOS that invoke OSI(Linux) do nothing with it. - * But some cause Linux to break. - * Only a couple use it to make Linux run better. - * - * Thus, Linux should continue to disable OSI(Linux) by default, - * should continue to discourage BIOS writers from using it, and - * should whitelist the few existing systems that require it. - * - * If it appears clear a vendor isn't using OSI(Linux) - * for anything constructive, blacklist them by name to disable - * unnecessary dmesg warnings on all of their products. - */ - static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { - /* - * Disable OSI(Linux) warnings on all "Acer, inc." - * - * _OSI(Linux) disables the latest Windows BIOS code: - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3100"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5050"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5580"), - * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 3010"), - * _OSI(Linux) effect unknown: - * DMI_MATCH(DMI_PRODUCT_NAME, "Ferrari 5000"), - */ - /* - * note that dmi_check_system() uses strstr() - * to match sub-strings rather than !strcmp(), - * so "Acer" below matches "Acer, inc." above. - */ - /* - * Disable OSI(Linux) warnings on all "Acer" - * - * _OSI(Linux) effect unknown: - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720Z"), - * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5520"), - * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 6460"), - * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 7510"), - * - * _OSI(Linux) is a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5220"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "Acer", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - }, - }, - /* - * Disable OSI(Linux) warnings on all "Apple Computer, Inc." - * Disable OSI(Linux) warnings on all "Apple Inc." - * - * _OSI(Linux) confirmed to be a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), - * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"), - * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"), - * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"), - * _OSI(Linux) effect unknown: - * DMI_MATCH(DMI_PRODUCT_NAME, "MacPro2,1"), - * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "Apple", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple"), - }, - }, - /* - * Disable OSI(Linux) warnings on all "BenQ" - * - * _OSI(Linux) confirmed to be a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "Joybook S31"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "BenQ", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "BenQ"), - }, - }, - /* - * Disable OSI(Linux) warnings on all "Clevo Co." - * - * _OSI(Linux) confirmed to be a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "M570RU"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "Clevo", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Clevo Co."), - }, - }, - /* - * Disable OSI(Linux) warnings on all "COMPAL" - * - * _OSI(Linux) confirmed to be a NOP: - * DMI_MATCH(DMI_BOARD_NAME, "HEL8X"), - * _OSI(Linux) unknown effect: - * DMI_MATCH(DMI_BOARD_NAME, "IFL91"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "Compal", - .matches = { - DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"), - }, - }, - { /* OSI(Linux) touches USB, unknown side-effect */ - .callback = dmi_disable_osi_linux, - .ident = "Dell Dimension 5150", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM051"), - }, - }, - { /* OSI(Linux) is a NOP */ - .callback = dmi_disable_osi_linux, - .ident = "Dell i1501", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1501"), - }, - }, - { /* OSI(Linux) effect unknown */ - .callback = dmi_unknown_osi_linux, - .ident = "Dell Latitude D830", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D830"), - }, - }, - { /* OSI(Linux) effect unknown */ - .callback = dmi_unknown_osi_linux, - .ident = "Dell OptiPlex GX620", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX620"), - }, - }, - { /* OSI(Linux) causes some USB initialization to not run */ - .callback = dmi_unknown_osi_linux, - .ident = "Dell OptiPlex 755", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 755"), - }, - }, - { /* OSI(Linux) effect unknown */ - .callback = dmi_unknown_osi_linux, - .ident = "Dell PE 1900", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1900"), - }, - }, - { /* OSI(Linux) is a NOP */ - .callback = dmi_unknown_osi_linux, - .ident = "Dell PE 1950", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"), - }, - }, - { /* OSI(Linux) is a NOP */ - .callback = dmi_disable_osi_linux, - .ident = "Dell PE R200", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R200"), - }, - }, - { /* OSI(Linux) touches USB */ - .callback = dmi_disable_osi_linux, - .ident = "Dell PR 390", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 390"), - }, - }, - { /* OSI(Linux) touches USB */ - .callback = dmi_unknown_osi_linux, - .ident = "Dell PR 390", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 690"), - }, - }, - { /* OSI(Linux) unknown - ASL looks benign, but may effect dock/SMM */ - .callback = dmi_unknown_osi_linux, - .ident = "Dell PR M4300", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Precision M4300"), - }, - }, - { /* OSI(Linux) is a NOP */ - .callback = dmi_disable_osi_linux, - .ident = "Dell Vostro 1000", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1000"), - }, - }, - { /* OSI(Linux) effect unknown */ - .callback = dmi_unknown_osi_linux, - .ident = "Dell PE SC440", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge SC440"), - }, - }, - { /* OSI(Linux) effect unknown */ - .callback = dmi_unknown_osi_linux, - .ident = "Dialogue Flybook V5", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dialogue Technology Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "Flybook V5"), - }, - }, - /* - * Disable OSI(Linux) warnings on all "FUJITSU SIEMENS" - * - * _OSI(Linux) disables latest Windows BIOS code: - * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2510"), - * _OSI(Linux) confirmed to be a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 1536"), - * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 1556"), - * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 1546"), - * DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), - * _OSI(Linux) unknown effect: - * DMI_MATCH(DMI_PRODUCT_NAME, "Amilo M1425"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Amilo Si 1520"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "Fujitsu Siemens", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), - }, - }, { .callback = dmi_disable_osi_vista, .ident = "Fujitsu Siemens", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), - DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), + DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), }, }, + /* - * Disable OSI(Linux) warnings on all "Hewlett-Packard" - * - * _OSI(Linux) confirmed to be a NOP: - * .ident = "HP Pavilion tx 1000" - * DMI_MATCH(DMI_BOARD_NAME, "30BF"), - * .ident = "HP Pavilion dv2000" - * DMI_MATCH(DMI_BOARD_NAME, "30B5"), - * .ident = "HP Pavilion dv5000", - * DMI_MATCH(DMI_BOARD_NAME, "30A7"), - * .ident = "HP Pavilion dv6300 30BC", - * DMI_MATCH(DMI_BOARD_NAME, "30BC"), - * .ident = "HP Pavilion dv6000", - * DMI_MATCH(DMI_BOARD_NAME, "30B7"), - * DMI_MATCH(DMI_BOARD_NAME, "30B8"), - * .ident = "HP Pavilion dv9000", - * DMI_MATCH(DMI_BOARD_NAME, "30B9"), - * .ident = "HP Pavilion dv9500", - * DMI_MATCH(DMI_BOARD_NAME, "30CB"), - * .ident = "HP/Compaq Presario C500", - * DMI_MATCH(DMI_BOARD_NAME, "30C6"), - * .ident = "HP/Compaq Presario F500", - * DMI_MATCH(DMI_BOARD_NAME, "30D3"), - * _OSI(Linux) unknown effect: - * .ident = "HP Pavilion dv6500", - * DMI_MATCH(DMI_BOARD_NAME, "30D0"), + * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. + * Linux ignores it, except for the machines enumerated below. */ - { - .callback = dmi_disable_osi_linux, - .ident = "Hewlett-Packard", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - }, - }, + /* * Lenovo has a mix of systems OSI(Linux) situations * and thus we can not wildcard the vendor. @@ -519,113 +235,6 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X61"), }, }, - { - .callback = dmi_disable_osi_linux, - .ident = "Lenovo 3000 V100", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "LENOVO3000 V100"), - }, - }, - { - .callback = dmi_disable_osi_linux, - .ident = "Lenovo 3000 N100", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"), - }, - }, - /* - * Disable OSI(Linux) warnings on all "LG Electronics" - * - * _OSI(Linux) confirmed to be a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "P1-J150B"), - * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"), - * - * unknown: - * DMI_MATCH(DMI_PRODUCT_NAME, "S1-MDGDG"), - * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "LG", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), - }, - }, - /* NEC - OSI(Linux) effect unknown */ - { - .callback = dmi_unknown_osi_linux, - .ident = "NEC VERSA M360", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "NEC Computers SAS"), - DMI_MATCH(DMI_PRODUCT_NAME, "NEC VERSA M360"), - }, - }, - /* Panasonic */ - { - .callback = dmi_unknown_osi_linux, - .ident = "Panasonic", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), - /* Toughbook CF-52 */ - DMI_MATCH(DMI_PRODUCT_NAME, "CF-52CCABVBG"), - }, - }, - /* - * Disable OSI(Linux) warnings on all "Samsung Electronics" - * - * OSI(Linux) disables PNP0C32 and other BIOS code for Windows: - * DMI_MATCH(DMI_PRODUCT_NAME, "R40P/R41P"), - * DMI_MATCH(DMI_PRODUCT_NAME, "R59P/R60P/R61P"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "Samsung", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), - }, - }, - /* - * Disable OSI(Linux) warnings on all "Sony Corporation" - * - * _OSI(Linux) is a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NR11S_S"), - * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SZ38GP_C"), - * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SZ650N"), - * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-TZ21MN_N"), - * _OSI(Linux) unknown effect: - * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ11M"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "Sony", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - }, - }, - /* - * Disable OSI(Linux) warnings on all "TOSHIBA" - * - * _OSI(Linux) breaks sound (bugzilla 7787): - * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P100"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P105"), - * _OSI(Linux) is a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A100"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A210"), - * _OSI(Linux) unknown effect: - * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A135"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A200"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P205"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite U305"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "Toshiba", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - }, - }, {} }; diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 4be252145cb4..c8111424dcb8 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -97,54 +96,44 @@ static DEFINE_SPINLOCK(acpi_res_lock); static char osi_additional_string[OSI_STRING_LENGTH_MAX]; /* - * "Ode to _OSI(Linux)" + * The story of _OSI(Linux) * - * osi_linux -- Control response to BIOS _OSI(Linux) query. + * From pre-history through Linux-2.6.22, + * Linux responded TRUE upon a BIOS OSI(Linux) query. * - * As Linux evolves, the features that it supports change. - * So an OSI string such as "Linux" is not specific enough - * to be useful across multiple versions of Linux. It - * doesn't identify any particular feature, interface, - * or even any particular version of Linux... + * Unfortunately, reference BIOS writers got wind of this + * and put OSI(Linux) in their example code, quickly exposing + * this string as ill-conceived and opening the door to + * an un-bounded number of BIOS incompatibilities. * - * Unfortunately, Linux-2.6.22 and earlier responded "yes" - * to a BIOS _OSI(Linux) query. When - * a reference mobile BIOS started using it, its use - * started to spread to many vendor platforms. - * As it is not supportable, we need to halt that spread. + * For example, OSI(Linux) was used on resume to re-POST a + * video card on one system, because Linux at that time + * could not do a speedy restore in its native driver. + * But then upon gaining quick native restore capability, + * Linux has no way to tell the BIOS to skip the time-consuming + * POST -- putting Linux at a permanent performance disadvantage. + * On another system, the BIOS writer used OSI(Linux) + * to infer native OS support for IPMI! On other systems, + * OSI(Linux) simply got in the way of Linux claiming to + * be compatible with other operating systems, exposing + * BIOS issues such as skipped device initialization. * - * Today, most BIOS references to _OSI(Linux) are noise -- - * they have no functional effect and are just dead code - * carried over from the reference BIOS. - * - * The next most common case is that _OSI(Linux) harms Linux, - * usually by causing the BIOS to follow paths that are - * not tested during Windows validation. - * - * Finally, there is a short list of platforms - * where OSI(Linux) benefits Linux. - * - * In Linux-2.6.23, OSI(Linux) is first disabled by default. - * DMI is used to disable the dmesg warning about OSI(Linux) - * on platforms where it is known to have no effect. - * But a dmesg warning remains for systems where - * we do not know if OSI(Linux) is good or bad for the system. - * DMI is also used to enable OSI(Linux) for the machines - * that are known to need it. + * So "Linux" turned out to be a really poor chose of + * OSI string, and from Linux-2.6.23 onward we respond FALSE. * * BIOS writers should NOT query _OSI(Linux) on future systems. - * It will be ignored by default, and to get Linux to - * not ignore it will require a kernel source update to - * add a DMI entry, or a boot-time "acpi_osi=Linux" invocation. + * Linux will complain on the console when it sees it, and return FALSE. + * To get Linux to return TRUE for your system will require + * a kernel source update to add a DMI entry, + * or boot with "acpi_osi=Linux" */ -#define OSI_LINUX_ENABLE 0 static struct osi_linux { unsigned int enable:1; unsigned int dmi:1; unsigned int cmdline:1; unsigned int known:1; -} osi_linux = { OSI_LINUX_ENABLE, 0, 0, 0}; +} osi_linux = { 0, 0, 0, 0}; static void __init acpi_request_region (struct acpi_generic_address *addr, unsigned int length, char *desc) @@ -1296,34 +1285,6 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object) return (AE_OK); } -/** - * acpi_dmi_dump - dump DMI slots needed for blacklist entry - * - * Returns 0 on success - */ -static int acpi_dmi_dump(void) -{ - - if (!dmi_available) - return -1; - - printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n", - dmi_get_system_info(DMI_SYS_VENDOR)); - printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n", - dmi_get_system_info(DMI_PRODUCT_NAME)); - printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n", - dmi_get_system_info(DMI_PRODUCT_VERSION)); - printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n", - dmi_get_system_info(DMI_BOARD_NAME)); - printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n", - dmi_get_system_info(DMI_BIOS_VENDOR)); - printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n", - dmi_get_system_info(DMI_BIOS_DATE)); - - return 0; -} - - /****************************************************************************** * * FUNCTION: acpi_os_validate_interface @@ -1350,21 +1311,6 @@ acpi_os_validate_interface (char *interface) osi_linux.cmdline ? " via cmdline" : osi_linux.dmi ? " via DMI" : ""); - if (!osi_linux.dmi) { - if (acpi_dmi_dump()) - printk(KERN_NOTICE PREFIX - "[please extract dmidecode output]\n"); - printk(KERN_NOTICE PREFIX - "Please send DMI info above to " - "linux-acpi@vger.kernel.org\n"); - } - if (!osi_linux.known && !osi_linux.cmdline) { - printk(KERN_NOTICE PREFIX - "If \"acpi_osi=%sLinux\" works better, " - "please notify linux-acpi@vger.kernel.org\n", - osi_linux.enable ? "!" : ""); - } - if (osi_linux.enable) return AE_OK; } -- cgit v1.2.3 From 23d0a65cf229acd273b6f5a325c34d758a90d592 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Fri, 28 Nov 2008 08:19:09 -0800 Subject: toshiba_acpi: close race in toshiba_acpi driver the toshiba ACPI driver will, in a failure case, free the rfkill state before stopping the polling timer that would use this state. More interesting, in the same failure case handling, it calls the exit function, which also frees the rfkill state, but after stopping the polling. If the race happens, a NULL pointer is passed to rfkill_force_state() which then causes a nice dereference. Fix the race by just not doing the too-early freeing of the rfkill state. This appears to be the cause of a hot issue on kerneloops.org; while I have no solid evidence of that this patch will fix the issue, the race appears rather real. Signed-off-by: Arjan van de Ven Signed-off-by: Len Brown --- drivers/acpi/toshiba_acpi.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c index 66aac06f2ac5..25f531d892de 100644 --- a/drivers/acpi/toshiba_acpi.c +++ b/drivers/acpi/toshiba_acpi.c @@ -848,8 +848,6 @@ static int __init toshiba_acpi_init(void) ret = input_register_polled_device(toshiba_acpi.poll_dev); if (ret) { printk(MY_ERR "unable to register kill-switch input device\n"); - rfkill_free(toshiba_acpi.rfk_dev); - toshiba_acpi.rfk_dev = NULL; toshiba_acpi_exit(); return ret; } -- cgit v1.2.3 From aaad077638be1a25871bcae5e43952d6b63abfca Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 5 Dec 2008 01:07:51 +0100 Subject: ACPI: Fix ACPI battery regression introduced by commit 558073 Commit 558073dd56707864f09d563b64e7c37c021e89d2 ("ACPI: battery: Convert discharge energy rate to current properly") caused the battery subsystem to report wrong values of the remaining time on battery power and the time until fully charged on Toshiba Portege R500 (and presumably on other boxes too). Fix the issue by correcting the conversion from mW to mA. Signed-off-by: Rafael J. Wysocki Signed-off-by: Linus Torvalds --- drivers/acpi/battery.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index a0a178dd189c..4fb3c12ac1d8 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -173,14 +173,17 @@ static int acpi_battery_get_property(struct power_supply *psy, val->intval = battery->voltage_now * 1000; break; case POWER_SUPPLY_PROP_CURRENT_NOW: - val->intval = battery->current_now * 1000; - /* if power units are mW, convert to mA by - dividing by current voltage (mV/1000) */ - if (!battery->power_unit) { - if (battery->voltage_now) { + val->intval = battery->current_now; + if (battery->power_unit) { + val->intval *= 1000; + } else { + /* + * If power units are mW, convert to mA by dividing by + * current voltage. + */ + if (battery->voltage_now) val->intval /= battery->voltage_now; - val->intval *= 1000; - } else + else val->intval = -1; } break; -- cgit v1.2.3 From f10a3a32ae2edbe94920ce6827f4c2550eb6ed48 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 5 Dec 2008 13:30:03 -0800 Subject: Revert "ACPI: battery: Convert discharge energy rate to current properly" This reverts commit 558073dd56707864f09d563b64e7c37c021e89d2, along with the failed try to fix the regression it caused ("ACPI: Fix ACPI battery regression introduced by commit 558073"), which just made things worse. Commit aaad077638be1a25871bcae5e43952d6b63abfca (that failed "Fix ACPI battery regression") got the voltage conversion confused, and fixed the problem with Rafael's battery monitor apparently just by mistake. So revert them both, getting us back to the 2.6.27 state in this, and let's revisit it when people understand what's going on. Noted-by: Paul Martin Requested-by: Rafael J. Wysocki Cc: Len Brown Cc: Alexey Starikovskiy Signed-off-by: Linus Torvalds --- drivers/acpi/battery.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 4fb3c12ac1d8..1423b0c0cd2e 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -173,19 +173,7 @@ static int acpi_battery_get_property(struct power_supply *psy, val->intval = battery->voltage_now * 1000; break; case POWER_SUPPLY_PROP_CURRENT_NOW: - val->intval = battery->current_now; - if (battery->power_unit) { - val->intval *= 1000; - } else { - /* - * If power units are mW, convert to mA by dividing by - * current voltage. - */ - if (battery->voltage_now) - val->intval /= battery->voltage_now; - else - val->intval = -1; - } + val->intval = battery->current_now * 1000; break; case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: -- cgit v1.2.3 From 38aefbc585c5d86df101e7644bff2c47112783d4 Mon Sep 17 00:00:00 2001 From: Frederik Deweerdt Date: Mon, 15 Dec 2008 13:54:19 -0800 Subject: ACPI toshiba: only register rfkill if bt is enabled Part of the rfkill initialization was done whenever BT was on or not. The following patch checks for BT presence before registering the rfkill to the input layer. Some minor cleanups (> 80 char lines) were also added in the process. On Tue, Oct 28, 2008 at 10:10:37PM +0300, Andrey Borzenkov wrote: [...] > [ 66.633036] toshiba_acpi: Toshiba Laptop ACPI Extras version 0.19 > [ 66.633054] toshiba_acpi: HCI method: \_SB_.VALD.GHCI > [ 66.637764] input: Toshiba RFKill Switch as /devices/virtual/input/input3 [...] > [ 113.920753] ------------[ cut here ]------------ > [ 113.920828] kernel BUG at /home/bor/src/linux-git/net/rfkill/rfkill.c:347! > [ 113.920845] invalid opcode: 0000 [#1] > [ 113.920877] last sysfs file: /sys/devices/pci0000:00/0000:00:04.0/host0/target0:0:0/0:0:0:0/block/sda/size > [ 113.920900] Dumping ftrace buffer: > [ 113.920919] (ftrace buffer empty) > [ 113.920933] Modules linked in: af_packet irnet ppp_generic slhc ircomm_tty ircomm binfmt_misc loop dm_mirror dm_region_hash dm_log dm_round_robin dm_multipath dm_mod alim15x3 ide_core nvram toshiba cryptomgr aead crypto_blkcipher michael_mic crypto_algapi orinoco_cs orinoco hermes_dld hermes pcmcia firmware_class snd_ali5451 snd_ac97_codec ac97_bus snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device smsc_ircc2 snd_pcm_oss snd_pcm rtc_cmos irda snd_timer snd_mixer_oss rtc_core snd crc_ccitt yenta_socket rtc_lib rsrc_nonstatic i2c_ali1535 pcmcia_core pcspkr psmouse soundcore i2c_core evdev sr_mod snd_page_alloc alim1535_wdt cdrom fan sg video output toshiba_acpi rfkill thermal backlight ali_agp processor ac button input_polldev battery agpgart ohci_hcd usbcore reiserfs pata_ali libata sd_mod scsi_mod [last unloaded: scsi_wait_scan] > [ 113.921765] > [ 113.921785] Pid: 3272, comm: ipolldevd Not tainted (2.6.28-rc2-1avb #3) PORTEGE 4000 > [ 113.921801] EIP: 0060:[] EFLAGS: 00010246 CPU: 0 > [ 113.921854] EIP is at rfkill_force_state+0x53/0x90 [rfkill] > [ 113.921870] EAX: 00000000 EBX: 00000000 ECX: 00000003 EDX: 00000000 > [ 113.921885] ESI: 00000000 EDI: ddd50300 EBP: d8d7af40 ESP: d8d7af24 > [ 113.921900] DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068 > [ 113.921918] Process ipolldevd (pid: 3272, ti=d8d7a000 task=d8d93c90 task.ti=d8d7a000) > [ 113.921933] Stack: > [ 113.921945] d8d7af38 00000246 dfb029d8 dfb029c0 dfb029d8 dfb029c0 ddd50300 d8d7af5c > [ 113.922014] dfb018e2 01000246 01000000 ddd50300 ddd50314 ddabb8a0 d8d7af68 dfb381c1 > [ 113.922098] 00000000 d8d7afa4 c012ec0a 00000000 00000002 00000000 c012eba8 ddabb8c0 > [ 113.922240] Call Trace: > [ 113.922240] [] ? bt_poll_rfkill+0x5c/0x82 [toshiba_acpi] > [ 113.922240] [] ? input_polled_device_work+0x11/0x40 [input_polldev] > [ 113.922240] [] ? run_workqueue+0xea/0x1f0 > [ 113.922240] [] ? run_workqueue+0x88/0x1f0 > [ 113.922240] [] ? input_polled_device_work+0x0/0x40 [input_polldev] > [ 113.922240] [] ? worker_thread+0x87/0xf0 > [ 113.922240] [] ? autoremove_wake_function+0x0/0x50 > [ 113.922240] [] ? worker_thread+0x0/0xf0 > [ 113.922240] [] ? kthread+0x3f/0x80 > [ 113.922240] [] ? kthread+0x0/0x80 > [ 113.922240] [] ? kernel_thread_helper+0x7/0x10 > [ 113.922240] Code: 43 54 89 73 54 39 c6 74 11 89 d9 ba 01 00 00 00 b8 40 68 aa df e8 3e 35 69 e0 89 f8 e8 77 fd 85 e0 31 c0 83 c4 10 5b 5e 5f 5d c3 <0f> 0b eb fe 89 f6 8d bc 27 00 00 00 00 be f4 4d aa df bb 5f 01 > [ 113.922240] EIP: [] rfkill_force_state+0x53/0x90 [rfkill] SS:ESP 0068:d8d7af24 > [ 113.924700] ---[ end trace 0e404eb40cadd5f0 ]--- Signed-off-by: Frederik Deweerdt Tested-by: Andrey Borzenkov Acked-by: Len Brown Cc: Richard Purdie Acked-by: Philip Langdale Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/toshiba_acpi.c | 54 ++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 25 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c index 25f531d892de..40e60fc2e596 100644 --- a/drivers/acpi/toshiba_acpi.c +++ b/drivers/acpi/toshiba_acpi.c @@ -824,32 +824,36 @@ static int __init toshiba_acpi_init(void) toshiba_acpi_exit(); return -ENOMEM; } - } - /* Register input device for kill switch */ - toshiba_acpi.poll_dev = input_allocate_polled_device(); - if (!toshiba_acpi.poll_dev) { - printk(MY_ERR "unable to allocate kill-switch input device\n"); - toshiba_acpi_exit(); - return -ENOMEM; - } - toshiba_acpi.poll_dev->private = &toshiba_acpi; - toshiba_acpi.poll_dev->poll = bt_poll_rfkill; - toshiba_acpi.poll_dev->poll_interval = 1000; /* msecs */ - - toshiba_acpi.poll_dev->input->name = toshiba_acpi.rfk_name; - toshiba_acpi.poll_dev->input->id.bustype = BUS_HOST; - toshiba_acpi.poll_dev->input->id.vendor = 0x0930; /* Toshiba USB ID */ - set_bit(EV_SW, toshiba_acpi.poll_dev->input->evbit); - set_bit(SW_RFKILL_ALL, toshiba_acpi.poll_dev->input->swbit); - input_report_switch(toshiba_acpi.poll_dev->input, SW_RFKILL_ALL, TRUE); - input_sync(toshiba_acpi.poll_dev->input); - - ret = input_register_polled_device(toshiba_acpi.poll_dev); - if (ret) { - printk(MY_ERR "unable to register kill-switch input device\n"); - toshiba_acpi_exit(); - return ret; + /* Register input device for kill switch */ + toshiba_acpi.poll_dev = input_allocate_polled_device(); + if (!toshiba_acpi.poll_dev) { + printk(MY_ERR + "unable to allocate kill-switch input device\n"); + toshiba_acpi_exit(); + return -ENOMEM; + } + toshiba_acpi.poll_dev->private = &toshiba_acpi; + toshiba_acpi.poll_dev->poll = bt_poll_rfkill; + toshiba_acpi.poll_dev->poll_interval = 1000; /* msecs */ + + toshiba_acpi.poll_dev->input->name = toshiba_acpi.rfk_name; + toshiba_acpi.poll_dev->input->id.bustype = BUS_HOST; + /* Toshiba USB ID */ + toshiba_acpi.poll_dev->input->id.vendor = 0x0930; + set_bit(EV_SW, toshiba_acpi.poll_dev->input->evbit); + set_bit(SW_RFKILL_ALL, toshiba_acpi.poll_dev->input->swbit); + input_report_switch(toshiba_acpi.poll_dev->input, + SW_RFKILL_ALL, TRUE); + input_sync(toshiba_acpi.poll_dev->input); + + ret = input_register_polled_device(toshiba_acpi.poll_dev); + if (ret) { + printk(MY_ERR + "unable to register kill-switch input device\n"); + toshiba_acpi_exit(); + return ret; + } } return 0; -- cgit v1.2.3 From 40fb17152c50a69dc304dd632131c2f41281ce44 Mon Sep 17 00:00:00 2001 From: Venki Pallipadi Date: Mon, 17 Nov 2008 16:11:37 -0800 Subject: x86: support always running TSC on Intel CPUs Impact: reward non-stop TSCs with good TSC-based clocksources, etc. Add support for CPUID_0x80000007_Bit8 on Intel CPUs as well. This bit means that the TSC is invariant with C/P/T states and always runs at constant frequency. With Intel CPUs, we have 3 classes * CPUs where TSC runs at constant rate and does not stop n C-states * CPUs where TSC runs at constant rate, but will stop in deep C-states * CPUs where TSC rate will vary based on P/T-states and TSC will stop in deep C-states. To cover these 3, one feature bit (CONSTANT_TSC) is not enough. So, add a second bit (NONSTOP_TSC). CONSTANT_TSC indicates that the TSC runs at constant frequency irrespective of P/T-states, and NONSTOP_TSC indicates that TSC does not stop in deep C-states. CPUID_0x8000000_Bit8 indicates both these feature bit can be set. We still have CONSTANT_TSC _set_ and NONSTOP_TSC _not_set_ on some older Intel CPUs, based on model checks. We can use TSC on such CPUs for time, as long as those CPUs do not support/enter deep C-states. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Ingo Molnar --- drivers/acpi/processor_idle.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 5f8d746a9b81..38aca048e951 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -374,15 +374,15 @@ static int tsc_halts_in_c(int state) { switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_AMD: + case X86_VENDOR_INTEL: /* * AMD Fam10h TSC will tick in all * C/P/S0/S1 states when this bit is set. */ - if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) + if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) return 0; + /*FALL THROUGH*/ - case X86_VENDOR_INTEL: - /* Several cases known where TSC halts in C2 too */ default: return state > ACPI_STATE_C1; } -- cgit v1.2.3 From e76f42761197dd6e9405e2eeb35932acfede115a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 13 Nov 2008 17:30:13 -0600 Subject: ACPI: fix 2.6.28 acpi.debug_level regression acpi_early_init() was changed to over-write the cmdline param, making it really inconvenient to set debug flags at boot-time. Also, This sets the default level to "info", which is what all the ACPI drivers use. So to enable messages from drivers, you only have to supply the "layer" (a.k.a. "component"). For non-"info" ACPI core and ACPI interpreter messages, you have to supply both level and layer masks, as before. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/bus.c | 8 -------- drivers/acpi/utilities/utglobal.c | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 7edf6d913c13..765fd1c56cd6 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -688,14 +688,6 @@ void __init acpi_early_init(void) if (acpi_disabled) return; - /* - * ACPI CA initializes acpi_dbg_level to non-zero, which means - * we get debug output merely by turning on CONFIG_ACPI_DEBUG. - * Turn it off so we don't get output unless the user specifies - * acpi.debug_level. - */ - acpi_dbg_level = 0; - printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION); /* enable workarounds, unless strict ACPI spec. compliance */ diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index 670551b95e56..17ed5ac840f7 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -64,7 +64,7 @@ u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT; /* Debug switch - layer (component) mask */ -u32 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS; +u32 acpi_dbg_layer = 0; u32 acpi_gbl_nesting_level = 0; /* Debugger globals */ -- cgit v1.2.3