From 5b275ce27077d6463ca28c9671dce7c2c1f622e2 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 11 Nov 2010 15:27:29 +0000 Subject: thermal: make ops constant And while touching that function definition do something about the disaster of formatting there. Signed-off-by: Alan Cox Acked-by: Zhang Rui Signed-off-by: Len Brown --- include/linux/thermal.h | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 1de8b9eb841..06626904daa 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -77,7 +77,7 @@ struct thermal_cooling_device { char type[THERMAL_NAME_LENGTH]; struct device device; void *devdata; - struct thermal_cooling_device_ops *ops; + const struct thermal_cooling_device_ops *ops; struct list_head node; }; @@ -114,7 +114,7 @@ struct thermal_zone_device { int last_temperature; bool passive; unsigned int forced_passive; - struct thermal_zone_device_ops *ops; + const struct thermal_zone_device_ops *ops; struct list_head cooling_devices; struct idr idr; struct mutex lock; /* protect cooling devices list */ @@ -129,11 +129,8 @@ struct thermal_zone_device { }; struct thermal_zone_device *thermal_zone_device_register(char *, int, void *, - struct - thermal_zone_device_ops - *, int tc1, int tc2, - int passive_freq, - int polling_freq); + const struct thermal_zone_device_ops *, int tc1, int tc2, + int passive_freq, int polling_freq); void thermal_zone_device_unregister(struct thermal_zone_device *); int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int, @@ -142,9 +139,7 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int, struct thermal_cooling_device *); void thermal_zone_device_update(struct thermal_zone_device *); struct thermal_cooling_device *thermal_cooling_device_register(char *, void *, - struct - thermal_cooling_device_ops - *); + const struct thermal_cooling_device_ops *); void thermal_cooling_device_unregister(struct thermal_cooling_device *); #endif /* __THERMAL_H__ */ -- cgit v1.2.3-70-g09d2 From c9aa308fd5c373faeda588cfb02b04f116904613 Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Tue, 7 Dec 2010 10:22:29 +0800 Subject: Add CPER PCIe error section structure and constants definition On some machine, PCIe error is reported via APEI (ACPI Platform Error Interface). The error data is passed from firmware to Linux via CPER PCIe error section structure. This patch adds CPER PCIe error section structure and constants definition. Signed-off-by: Huang Ying Signed-off-by: Len Brown --- include/linux/cper.h | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/cper.h b/include/linux/cper.h index bf972f81e2a..3104aaff5dd 100644 --- a/include/linux/cper.h +++ b/include/linux/cper.h @@ -39,10 +39,12 @@ * Severity difinition for error_severity in struct cper_record_header * and section_severity in struct cper_section_descriptor */ -#define CPER_SEV_RECOVERABLE 0x0 -#define CPER_SEV_FATAL 0x1 -#define CPER_SEV_CORRECTED 0x2 -#define CPER_SEV_INFORMATIONAL 0x3 +enum { + CPER_SEV_RECOVERABLE, + CPER_SEV_FATAL, + CPER_SEV_CORRECTED, + CPER_SEV_INFORMATIONAL, +}; /* * Validation bits difinition for validation_bits in struct @@ -201,6 +203,47 @@ UUID_LE(0x036F84E1, 0x7F37, 0x428c, 0xA7, 0x9E, 0x57, 0x5F, \ 0xDF, 0xAA, 0x84, 0xEC) +#define CPER_PROC_VALID_TYPE 0x0001 +#define CPER_PROC_VALID_ISA 0x0002 +#define CPER_PROC_VALID_ERROR_TYPE 0x0004 +#define CPER_PROC_VALID_OPERATION 0x0008 +#define CPER_PROC_VALID_FLAGS 0x0010 +#define CPER_PROC_VALID_LEVEL 0x0020 +#define CPER_PROC_VALID_VERSION 0x0040 +#define CPER_PROC_VALID_BRAND_INFO 0x0080 +#define CPER_PROC_VALID_ID 0x0100 +#define CPER_PROC_VALID_TARGET_ADDRESS 0x0200 +#define CPER_PROC_VALID_REQUESTOR_ID 0x0400 +#define CPER_PROC_VALID_RESPONDER_ID 0x0800 +#define CPER_PROC_VALID_IP 0x1000 + +#define CPER_MEM_VALID_ERROR_STATUS 0x0001 +#define CPER_MEM_VALID_PHYSICAL_ADDRESS 0x0002 +#define CPER_MEM_VALID_PHYSICAL_ADDRESS_MASK 0x0004 +#define CPER_MEM_VALID_NODE 0x0008 +#define CPER_MEM_VALID_CARD 0x0010 +#define CPER_MEM_VALID_MODULE 0x0020 +#define CPER_MEM_VALID_BANK 0x0040 +#define CPER_MEM_VALID_DEVICE 0x0080 +#define CPER_MEM_VALID_ROW 0x0100 +#define CPER_MEM_VALID_COLUMN 0x0200 +#define CPER_MEM_VALID_BIT_POSITION 0x0400 +#define CPER_MEM_VALID_REQUESTOR_ID 0x0800 +#define CPER_MEM_VALID_RESPONDER_ID 0x1000 +#define CPER_MEM_VALID_TARGET_ID 0x2000 +#define CPER_MEM_VALID_ERROR_TYPE 0x4000 + +#define CPER_PCIE_VALID_PORT_TYPE 0x0001 +#define CPER_PCIE_VALID_VERSION 0x0002 +#define CPER_PCIE_VALID_COMMAND_STATUS 0x0004 +#define CPER_PCIE_VALID_DEVICE_ID 0x0008 +#define CPER_PCIE_VALID_SERIAL_NUMBER 0x0010 +#define CPER_PCIE_VALID_BRIDGE_CONTROL_STATUS 0x0020 +#define CPER_PCIE_VALID_CAPABILITY 0x0040 +#define CPER_PCIE_VALID_AER_INFO 0x0080 + +#define CPER_PCIE_SLOT_SHIFT 3 + /* * All tables and structs must be byte-packed to match CPER * specification, since the tables are provided by the system BIOS @@ -306,6 +349,41 @@ struct cper_sec_mem_err { __u8 error_type; }; +struct cper_sec_pcie { + __u64 validation_bits; + __u32 port_type; + struct { + __u8 minor; + __u8 major; + __u8 reserved[2]; + } version; + __u16 command; + __u16 status; + __u32 reserved; + struct { + __u16 vendor_id; + __u16 device_id; + __u8 class_code[3]; + __u8 function; + __u8 device; + __u16 segment; + __u8 bus; + __u8 secondary_bus; + __u16 slot; + __u8 reserved; + } device_id; + struct { + __u32 lower; + __u32 upper; + } serial_number; + struct { + __u16 secondary_status; + __u16 control; + } bridge; + __u8 capability[60]; + __u8 aer_info[96]; +}; + /* Reset to default packing */ #pragma pack() -- cgit v1.2.3-70-g09d2 From 16f4232ce4d6855361b4eb56262f4a202295c978 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 8 Dec 2010 10:10:16 +0800 Subject: IPMI: Add one interface to get more info of low-level IPMI device The IPMI smi_watcher will be used to catch the IPMI interface as they come or go. In order to communicate with the correct IPMI device, it should be confirmed whether it is what we wanted especially on the system with multiple IPMI devices. But the new_smi callback function of smi_watcher provides very limited info(only the interface number and dev pointer) and there is no detailed info about the low level interface. For example: which mechansim registers the IPMI interface(ACPI, PCI, DMI and so on). This is to add one interface that can get more info of low-level IPMI device. For example: the ACPI device handle will be returned for the pnp_acpi IPMI device. Signed-off-by: Zhao Yakui Signed-off-by: Corey Minyard Signed-off-by: Len Brown --- drivers/char/ipmi/ipmi_msghandler.c | 27 ++++++++++++++++++++++++++ drivers/char/ipmi/ipmi_si_intf.c | 20 +++++++++++++++---- include/linux/ipmi.h | 38 +++++++++++++++++++++++++++++++++++++ include/linux/ipmi_smi.h | 8 ++++++++ 4 files changed, 89 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 2fe72f8edf4..38223e93aa9 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -970,6 +970,33 @@ out_kfree: } EXPORT_SYMBOL(ipmi_create_user); +int ipmi_get_smi_info(int if_num, struct ipmi_smi_info *data) +{ + int rv = 0; + ipmi_smi_t intf; + struct ipmi_smi_handlers *handlers; + + mutex_lock(&ipmi_interfaces_mutex); + list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { + if (intf->intf_num == if_num) + goto found; + } + /* Not found, return an error */ + rv = -EINVAL; + mutex_unlock(&ipmi_interfaces_mutex); + return rv; + +found: + handlers = intf->handlers; + rv = -ENOSYS; + if (handlers->get_smi_info) + rv = handlers->get_smi_info(intf->send_info, data); + mutex_unlock(&ipmi_interfaces_mutex); + + return rv; +} +EXPORT_SYMBOL(ipmi_get_smi_info); + static void free_user(struct kref *ref) { ipmi_user_t user = container_of(ref, struct ipmi_user, refcount); diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 035da9e64a1..945ae4d5d21 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include "ipmi_si_sm.h" @@ -107,10 +108,6 @@ enum si_type { }; static char *si_to_str[] = { "kcs", "smic", "bt" }; -enum ipmi_addr_src { - SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS, - SI_PCI, SI_DEVICETREE, SI_DEFAULT -}; static char *ipmi_addr_src_to_str[] = { NULL, "hotmod", "hardcoded", "SPMI", "ACPI", "SMBIOS", "PCI", "device-tree", "default" }; @@ -291,6 +288,7 @@ struct smi_info { struct task_struct *thread; struct list_head link; + union ipmi_smi_info_union addr_info; }; #define smi_inc_stat(smi, stat) \ @@ -1186,6 +1184,18 @@ static int smi_start_processing(void *send_info, return 0; } +static int get_smi_info(void *send_info, struct ipmi_smi_info *data) +{ + struct smi_info *smi = send_info; + + data->addr_src = smi->addr_source; + data->dev = smi->dev; + data->addr_info = smi->addr_info; + get_device(smi->dev); + + return 0; +} + static void set_maintenance_mode(void *send_info, int enable) { struct smi_info *smi_info = send_info; @@ -1197,6 +1207,7 @@ static void set_maintenance_mode(void *send_info, int enable) static struct ipmi_smi_handlers handlers = { .owner = THIS_MODULE, .start_processing = smi_start_processing, + .get_smi_info = get_smi_info, .sender = sender, .request_events = request_events, .set_maintenance_mode = set_maintenance_mode, @@ -2156,6 +2167,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, printk(KERN_INFO PFX "probing via ACPI\n"); handle = acpi_dev->handle; + info->addr_info.acpi_info.acpi_handle = handle; /* _IFT tells us the interface type: KCS, BT, etc */ status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp); diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h index 65aae34759d..045f2f275cd 100644 --- a/include/linux/ipmi.h +++ b/include/linux/ipmi.h @@ -454,6 +454,44 @@ unsigned int ipmi_addr_length(int addr_type); /* Validate that the given IPMI address is valid. */ int ipmi_validate_addr(struct ipmi_addr *addr, int len); +/* + * How did the IPMI driver find out about the device? + */ +enum ipmi_addr_src { + SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS, + SI_PCI, SI_DEVICETREE, SI_DEFAULT +}; + +union ipmi_smi_info_union { + /* + * the acpi_info element is defined for the SI_ACPI + * address type + */ + struct { + void *acpi_handle; + } acpi_info; +}; + +struct ipmi_smi_info { + enum ipmi_addr_src addr_src; + + /* + * Base device for the interface. Don't forget to put this when + * you are done. + */ + struct device *dev; + + /* + * The addr_info provides more detailed info for some IPMI + * devices, depending on the addr_src. Currently only SI_ACPI + * info is provided. + */ + union ipmi_smi_info_union addr_info; +}; + +/* This is to get the private info of ipmi_smi_t */ +extern int ipmi_get_smi_info(int if_num, struct ipmi_smi_info *data); + #endif /* __KERNEL__ */ diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h index 4b48318ac54..906590aa690 100644 --- a/include/linux/ipmi_smi.h +++ b/include/linux/ipmi_smi.h @@ -39,6 +39,7 @@ #include #include #include +#include /* This files describes the interface for IPMI system management interface drivers to bind into the IPMI message handler. */ @@ -86,6 +87,13 @@ struct ipmi_smi_handlers { int (*start_processing)(void *send_info, ipmi_smi_t new_intf); + /* + * Get the detailed private info of the low level interface and store + * it into the structure of ipmi_smi_data. For example: the + * ACPI device handle will be returned for the pnp_acpi IPMI device. + */ + int (*get_smi_info)(void *send_info, struct ipmi_smi_info *data); + /* Called to enqueue an SMI message to be sent. This operation is not allowed to fail. If an error occurs, it should report back the error in a received message. It may -- cgit v1.2.3-70-g09d2 From 26fcaf60fe3861409eb4c455c5c0d0f00f599b08 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 7 Jan 2011 01:42:31 +0100 Subject: PM: Fix oops in suspend/hibernate code related to failing ioremap() When ioremap() fails (which might happen for some reason), we nicely oops in suspend_nvs_save() due to NULL dereference by memcpy() in there. Fail gracefully instead. Signed-off-by: Jiri Slaby Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/sleep.c | 5 ++--- include/linux/suspend.h | 4 ++-- kernel/power/nvs.c | 8 +++++++- 3 files changed, 11 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index febb153b5a6..d8bca6c9071 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -124,8 +124,7 @@ static int acpi_pm_freeze(void) static int acpi_pm_pre_suspend(void) { acpi_pm_freeze(); - suspend_nvs_save(); - return 0; + return suspend_nvs_save(); } /** @@ -151,7 +150,7 @@ static int acpi_pm_prepare(void) { int error = __acpi_pm_prepare(); if (!error) - acpi_pm_pre_suspend(); + error = acpi_pm_pre_suspend(); return error; } diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 26697514c5e..acb7d911bb0 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -262,7 +262,7 @@ static inline bool system_entering_hibernation(void) { return false; } extern int suspend_nvs_register(unsigned long start, unsigned long size); extern int suspend_nvs_alloc(void); extern void suspend_nvs_free(void); -extern void suspend_nvs_save(void); +extern int suspend_nvs_save(void); extern void suspend_nvs_restore(void); #else /* CONFIG_SUSPEND_NVS */ static inline int suspend_nvs_register(unsigned long a, unsigned long b) @@ -271,7 +271,7 @@ static inline int suspend_nvs_register(unsigned long a, unsigned long b) } static inline int suspend_nvs_alloc(void) { return 0; } static inline void suspend_nvs_free(void) {} -static inline void suspend_nvs_save(void) {} +static inline int suspend_nvs_save(void) {} static inline void suspend_nvs_restore(void) {} #endif /* CONFIG_SUSPEND_NVS */ diff --git a/kernel/power/nvs.c b/kernel/power/nvs.c index 1836db60bbb..57c6fabbb6b 100644 --- a/kernel/power/nvs.c +++ b/kernel/power/nvs.c @@ -105,7 +105,7 @@ int suspend_nvs_alloc(void) /** * suspend_nvs_save - save NVS memory regions */ -void suspend_nvs_save(void) +int suspend_nvs_save(void) { struct nvs_page *entry; @@ -114,8 +114,14 @@ void suspend_nvs_save(void) list_for_each_entry(entry, &nvs_list, node) if (entry->data) { entry->kaddr = ioremap(entry->phys_start, entry->size); + if (!entry->kaddr) { + suspend_nvs_free(); + return -ENOMEM; + } memcpy(entry->data, entry->kaddr, entry->size); } + + return 0; } /** -- cgit v1.2.3-70-g09d2 From 976513dbfc1547c7b1822566923058655f0c32fd Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 7 Jan 2011 01:43:44 +0100 Subject: PM / ACPI: Move NVS saving and restoring code to drivers/acpi The saving of the ACPI NVS area during hibernation and suspend and restoring it during the subsequent resume is entirely specific to ACPI, so move it to drivers/acpi and drop the CONFIG_SUSPEND_NVS configuration option which is redundant. Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- arch/x86/kernel/e820.c | 1 + drivers/acpi/Makefile | 2 +- drivers/acpi/internal.h | 8 +++ drivers/acpi/nvs.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/acpi.h | 9 +++ include/linux/suspend.h | 17 ------ kernel/power/Kconfig | 5 -- kernel/power/Makefile | 1 - kernel/power/nvs.c | 142 ------------------------------------------------ 9 files changed, 161 insertions(+), 166 deletions(-) create mode 100644 drivers/acpi/nvs.c delete mode 100644 kernel/power/nvs.c (limited to 'include') diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 0c2b7ef7a34..294f26da0c0 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 3d031d02e54..9cc9f2c4da7 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -24,7 +24,7 @@ acpi-y += atomicio.o # sleep related files acpi-y += wakeup.o acpi-y += sleep.o -acpi-$(CONFIG_ACPI_SLEEP) += proc.o +acpi-$(CONFIG_ACPI_SLEEP) += proc.o nvs.o # diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index a212bfeddf8..7c23b76e8ec 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -82,8 +82,16 @@ extern int acpi_sleep_init(void); #ifdef CONFIG_ACPI_SLEEP int acpi_sleep_proc_init(void); +int suspend_nvs_alloc(void); +void suspend_nvs_free(void); +int suspend_nvs_save(void); +void suspend_nvs_restore(void); #else static inline int acpi_sleep_proc_init(void) { return 0; } +static inline int suspend_nvs_alloc(void) { return 0; } +static inline void suspend_nvs_free(void) {} +static inline int suspend_nvs_save(void) {} +static inline void suspend_nvs_restore(void) {} #endif #endif /* _ACPI_INTERNAL_H_ */ diff --git a/drivers/acpi/nvs.c b/drivers/acpi/nvs.c new file mode 100644 index 00000000000..57c6fabbb6b --- /dev/null +++ b/drivers/acpi/nvs.c @@ -0,0 +1,142 @@ +/* + * linux/kernel/power/hibernate_nvs.c - Routines for handling NVS memory + * + * Copyright (C) 2008,2009 Rafael J. Wysocki , Novell Inc. + * + * This file is released under the GPLv2. + */ + +#include +#include +#include +#include +#include +#include + +/* + * Platforms, like ACPI, may want us to save some memory used by them during + * suspend and to restore the contents of this memory during the subsequent + * resume. The code below implements a mechanism allowing us to do that. + */ + +struct nvs_page { + unsigned long phys_start; + unsigned int size; + void *kaddr; + void *data; + struct list_head node; +}; + +static LIST_HEAD(nvs_list); + +/** + * suspend_nvs_register - register platform NVS memory region to save + * @start - physical address of the region + * @size - size of the region + * + * The NVS region need not be page-aligned (both ends) and we arrange + * things so that the data from page-aligned addresses in this region will + * be copied into separate RAM pages. + */ +int suspend_nvs_register(unsigned long start, unsigned long size) +{ + struct nvs_page *entry, *next; + + while (size > 0) { + unsigned int nr_bytes; + + entry = kzalloc(sizeof(struct nvs_page), GFP_KERNEL); + if (!entry) + goto Error; + + list_add_tail(&entry->node, &nvs_list); + entry->phys_start = start; + nr_bytes = PAGE_SIZE - (start & ~PAGE_MASK); + entry->size = (size < nr_bytes) ? size : nr_bytes; + + start += entry->size; + size -= entry->size; + } + return 0; + + Error: + list_for_each_entry_safe(entry, next, &nvs_list, node) { + list_del(&entry->node); + kfree(entry); + } + return -ENOMEM; +} + +/** + * suspend_nvs_free - free data pages allocated for saving NVS regions + */ +void suspend_nvs_free(void) +{ + struct nvs_page *entry; + + list_for_each_entry(entry, &nvs_list, node) + if (entry->data) { + free_page((unsigned long)entry->data); + entry->data = NULL; + if (entry->kaddr) { + iounmap(entry->kaddr); + entry->kaddr = NULL; + } + } +} + +/** + * suspend_nvs_alloc - allocate memory necessary for saving NVS regions + */ +int suspend_nvs_alloc(void) +{ + struct nvs_page *entry; + + list_for_each_entry(entry, &nvs_list, node) { + entry->data = (void *)__get_free_page(GFP_KERNEL); + if (!entry->data) { + suspend_nvs_free(); + return -ENOMEM; + } + } + return 0; +} + +/** + * suspend_nvs_save - save NVS memory regions + */ +int suspend_nvs_save(void) +{ + struct nvs_page *entry; + + printk(KERN_INFO "PM: Saving platform NVS memory\n"); + + list_for_each_entry(entry, &nvs_list, node) + if (entry->data) { + entry->kaddr = ioremap(entry->phys_start, entry->size); + if (!entry->kaddr) { + suspend_nvs_free(); + return -ENOMEM; + } + memcpy(entry->data, entry->kaddr, entry->size); + } + + return 0; +} + +/** + * suspend_nvs_restore - restore NVS memory regions + * + * This function is going to be called with interrupts disabled, so it + * cannot iounmap the virtual addresses used to access the NVS region. + */ +void suspend_nvs_restore(void) +{ + struct nvs_page *entry; + + printk(KERN_INFO "PM: Restoring platform NVS memory\n"); + + list_for_each_entry(entry, &nvs_list, node) + if (entry->data) + memcpy(entry->kaddr, entry->data, entry->size); +} diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 67c91b4418b..fa7ed6a983d 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -254,6 +254,15 @@ void __init acpi_old_suspend_ordering(void); void __init acpi_nvs_nosave(void); #endif /* CONFIG_PM_SLEEP */ +#ifdef CONFIG_ACPI_SLEEP +int suspend_nvs_register(unsigned long start, unsigned long size); +#else +static inline int suspend_nvs_register(unsigned long a, unsigned long b) +{ + return 0; +} +#endif + struct acpi_osc_context { char *uuid_str; /* uuid string */ int rev; diff --git a/include/linux/suspend.h b/include/linux/suspend.h index acb7d911bb0..0e288e3c37b 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -258,23 +258,6 @@ static inline int hibernate(void) { return -ENOSYS; } static inline bool system_entering_hibernation(void) { return false; } #endif /* CONFIG_HIBERNATION */ -#ifdef CONFIG_SUSPEND_NVS -extern int suspend_nvs_register(unsigned long start, unsigned long size); -extern int suspend_nvs_alloc(void); -extern void suspend_nvs_free(void); -extern int suspend_nvs_save(void); -extern void suspend_nvs_restore(void); -#else /* CONFIG_SUSPEND_NVS */ -static inline int suspend_nvs_register(unsigned long a, unsigned long b) -{ - return 0; -} -static inline int suspend_nvs_alloc(void) { return 0; } -static inline void suspend_nvs_free(void) {} -static inline int suspend_nvs_save(void) {} -static inline void suspend_nvs_restore(void) {} -#endif /* CONFIG_SUSPEND_NVS */ - #ifdef CONFIG_PM_SLEEP void save_processor_state(void); void restore_processor_state(void); diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index a5aff3ebad3..265729966ec 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -100,13 +100,9 @@ config PM_SLEEP_ADVANCED_DEBUG depends on PM_ADVANCED_DEBUG default n -config SUSPEND_NVS - bool - config SUSPEND bool "Suspend to RAM and standby" depends on PM && ARCH_SUSPEND_POSSIBLE - select SUSPEND_NVS if HAS_IOMEM default y ---help--- Allow the system to enter sleep states in which main memory is @@ -140,7 +136,6 @@ config HIBERNATION depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE select LZO_COMPRESS select LZO_DECOMPRESS - select SUSPEND_NVS if HAS_IOMEM ---help--- Enable the suspend to disk (STD) functionality, which is usually called "hibernation" in user interfaces. STD checkpoints the diff --git a/kernel/power/Makefile b/kernel/power/Makefile index f9063c6b185..120a1582332 100644 --- a/kernel/power/Makefile +++ b/kernel/power/Makefile @@ -10,6 +10,5 @@ obj-$(CONFIG_SUSPEND) += suspend.o obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o \ block_io.o -obj-$(CONFIG_SUSPEND_NVS) += nvs.o obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o diff --git a/kernel/power/nvs.c b/kernel/power/nvs.c deleted file mode 100644 index 57c6fabbb6b..00000000000 --- a/kernel/power/nvs.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * linux/kernel/power/hibernate_nvs.c - Routines for handling NVS memory - * - * Copyright (C) 2008,2009 Rafael J. Wysocki , Novell Inc. - * - * This file is released under the GPLv2. - */ - -#include -#include -#include -#include -#include -#include - -/* - * Platforms, like ACPI, may want us to save some memory used by them during - * suspend and to restore the contents of this memory during the subsequent - * resume. The code below implements a mechanism allowing us to do that. - */ - -struct nvs_page { - unsigned long phys_start; - unsigned int size; - void *kaddr; - void *data; - struct list_head node; -}; - -static LIST_HEAD(nvs_list); - -/** - * suspend_nvs_register - register platform NVS memory region to save - * @start - physical address of the region - * @size - size of the region - * - * The NVS region need not be page-aligned (both ends) and we arrange - * things so that the data from page-aligned addresses in this region will - * be copied into separate RAM pages. - */ -int suspend_nvs_register(unsigned long start, unsigned long size) -{ - struct nvs_page *entry, *next; - - while (size > 0) { - unsigned int nr_bytes; - - entry = kzalloc(sizeof(struct nvs_page), GFP_KERNEL); - if (!entry) - goto Error; - - list_add_tail(&entry->node, &nvs_list); - entry->phys_start = start; - nr_bytes = PAGE_SIZE - (start & ~PAGE_MASK); - entry->size = (size < nr_bytes) ? size : nr_bytes; - - start += entry->size; - size -= entry->size; - } - return 0; - - Error: - list_for_each_entry_safe(entry, next, &nvs_list, node) { - list_del(&entry->node); - kfree(entry); - } - return -ENOMEM; -} - -/** - * suspend_nvs_free - free data pages allocated for saving NVS regions - */ -void suspend_nvs_free(void) -{ - struct nvs_page *entry; - - list_for_each_entry(entry, &nvs_list, node) - if (entry->data) { - free_page((unsigned long)entry->data); - entry->data = NULL; - if (entry->kaddr) { - iounmap(entry->kaddr); - entry->kaddr = NULL; - } - } -} - -/** - * suspend_nvs_alloc - allocate memory necessary for saving NVS regions - */ -int suspend_nvs_alloc(void) -{ - struct nvs_page *entry; - - list_for_each_entry(entry, &nvs_list, node) { - entry->data = (void *)__get_free_page(GFP_KERNEL); - if (!entry->data) { - suspend_nvs_free(); - return -ENOMEM; - } - } - return 0; -} - -/** - * suspend_nvs_save - save NVS memory regions - */ -int suspend_nvs_save(void) -{ - struct nvs_page *entry; - - printk(KERN_INFO "PM: Saving platform NVS memory\n"); - - list_for_each_entry(entry, &nvs_list, node) - if (entry->data) { - entry->kaddr = ioremap(entry->phys_start, entry->size); - if (!entry->kaddr) { - suspend_nvs_free(); - return -ENOMEM; - } - memcpy(entry->data, entry->kaddr, entry->size); - } - - return 0; -} - -/** - * suspend_nvs_restore - restore NVS memory regions - * - * This function is going to be called with interrupts disabled, so it - * cannot iounmap the virtual addresses used to access the NVS region. - */ -void suspend_nvs_restore(void) -{ - struct nvs_page *entry; - - printk(KERN_INFO "PM: Restoring platform NVS memory\n"); - - list_for_each_entry(entry, &nvs_list, node) - if (entry->data) - memcpy(entry->kaddr, entry->data, entry->size); -} -- cgit v1.2.3-70-g09d2 From 7fa69baf29de8c77a6b32c054df2abb8f11f8aa4 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 6 Jan 2011 23:35:10 +0100 Subject: ACPI / PM: Drop special ACPI wakeup flags Drop special ACPI wakeup flags, wakeup.state.enabled and wakeup.flags.always_enabled, that aren't necessary any more after we've started to use standard device wakeup flags for handling ACPI wakeup devices. Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/glue.c | 5 +---- include/acpi/acpi_bus.h | 6 ------ 2 files changed, 1 insertion(+), 10 deletions(-) (limited to 'include') diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 78b0164c35b..7c47ed55e52 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -167,11 +167,8 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) "firmware_node"); ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, "physical_node"); - if (acpi_dev->wakeup.flags.valid) { + if (acpi_dev->wakeup.flags.valid) device_set_wakeup_capable(dev, true); - device_set_wakeup_enable(dev, - acpi_dev->wakeup.state.enabled); - } } return 0; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 359ef11725a..f2499f57210 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -242,20 +242,14 @@ struct acpi_device_perf { struct acpi_device_wakeup_flags { u8 valid:1; /* Can successfully enable wakeup? */ u8 run_wake:1; /* Run-Wake GPE devices */ - u8 always_enabled:1; /* Run-wake devices that are always enabled */ u8 notifier_present:1; /* Wake-up notify handler has been installed */ }; -struct acpi_device_wakeup_state { - u8 enabled:1; -}; - struct acpi_device_wakeup { acpi_handle gpe_device; u64 gpe_number; u64 sleep_state; struct acpi_handle_list resources; - struct acpi_device_wakeup_state state; struct acpi_device_wakeup_flags flags; int prepare_count; int run_wake_count; -- cgit v1.2.3-70-g09d2 From 5a344a505093dd65f82f338ffdb7208321b3630e Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 10 Jan 2011 16:35:45 +0800 Subject: ACPI: Reevaluate whether the T-state is supported or not after cpu is online/offline After one CPU is offlined, it is unnecessary to switch T-state for it. So it will be better that the throttling is disabled after the cpu is offline. At the same time after one cpu is online, we should check whether the T-state is supported and then set the corresponding T-state flag. Signed-off-by: Zhao Yakui Signed-off-by: Len Brown --- drivers/acpi/processor_driver.c | 5 ++++ drivers/acpi/processor_throttling.c | 52 +++++++++++++++++++++++++++++++++++++ include/acpi/processor.h | 6 +++++ 3 files changed, 63 insertions(+) (limited to 'include') diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 85e48047d7b..c8a0ca2af83 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -478,8 +478,13 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb, if (action == CPU_ONLINE && pr) { acpi_processor_ppc_has_changed(pr, 0); acpi_processor_cst_has_changed(pr); + acpi_processor_reevaluate_tstate(pr, action); acpi_processor_tstate_has_changed(pr); } + if (action == CPU_DEAD && pr) { + /* invalidate the flag.throttling after one CPU is offline */ + acpi_processor_reevaluate_tstate(pr, action); + } return NOTIFY_OK; } diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index ffc859c6139..4305d560b06 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -369,6 +369,58 @@ int acpi_processor_tstate_has_changed(struct acpi_processor *pr) return acpi_processor_set_throttling(pr, target_state, false); } +/* + * This function is used to reevaluate whether the T-state is valid + * after one CPU is onlined/offlined. + * It is noted that it won't reevaluate the following properties for + * the T-state. + * 1. Control method. + * 2. the number of supported T-state + * 3. TSD domain + */ +void acpi_processor_reevaluate_tstate(struct acpi_processor *pr, + unsigned long action) +{ + int result = 0; + + if (action == CPU_DEAD) { + /* When one CPU is offline, the T-state throttling + * will be invalidated. + */ + pr->flags.throttling = 0; + return; + } + /* the following is to recheck whether the T-state is valid for + * the online CPU + */ + if (!pr->throttling.state_count) { + /* If the number of T-state is invalid, it is + * invalidated. + */ + pr->flags.throttling = 0; + return; + } + pr->flags.throttling = 1; + + /* Disable throttling (if enabled). We'll let subsequent + * policy (e.g.thermal) decide to lower performance if it + * so chooses, but for now we'll crank up the speed. + */ + + result = acpi_processor_get_throttling(pr); + if (result) + goto end; + + if (pr->throttling.state) { + result = acpi_processor_set_throttling(pr, 0, false); + if (result) + goto end; + } + +end: + if (result) + pr->flags.throttling = 0; +} /* * _PTC - Processor Throttling Control (and status) register location */ diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 1b62102fbb6..55192ac0ced 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -324,6 +324,12 @@ int acpi_processor_tstate_has_changed(struct acpi_processor *pr); int acpi_processor_get_throttling_info(struct acpi_processor *pr); extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state, bool force); +/* + * Reevaluate whether the T-state is invalid after one cpu is + * onlined/offlined. In such case the flags.throttling will be updated. + */ +extern void acpi_processor_reevaluate_tstate(struct acpi_processor *pr, + unsigned long action); extern const struct file_operations acpi_processor_throttling_fops; extern void acpi_processor_throttling_init(void); /* in processor_idle.c */ -- cgit v1.2.3-70-g09d2 From 4cb18728709683c91a5f6f8d5f337bfb498b089a Mon Sep 17 00:00:00 2001 From: "R.Durgadoss" Date: Wed, 27 Oct 2010 03:33:29 +0530 Subject: thermal: Add event notification to thermal framework This patch adds event notification support to the generic thermal sysfs framework in the kernel. The notification is in the form of a netlink event. Signed-off-by: R.Durgadoss Signed-off-by: Len Brown --- Documentation/ABI/stable/thermal-notification | 4 + Documentation/thermal/sysfs-api.txt | 12 +++ drivers/thermal/Kconfig | 1 + drivers/thermal/thermal_sys.c | 103 +++++++++++++++++++++++++- include/linux/thermal.h | 32 ++++++++ 5 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 Documentation/ABI/stable/thermal-notification (limited to 'include') diff --git a/Documentation/ABI/stable/thermal-notification b/Documentation/ABI/stable/thermal-notification new file mode 100644 index 00000000000..9723e8b7aeb --- /dev/null +++ b/Documentation/ABI/stable/thermal-notification @@ -0,0 +1,4 @@ +What: A notification mechanism for thermal related events +Description: + This interface enables notification for thermal related events. + The notification is in the form of a netlink event. diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt index cb3d15bc1ae..b61e46f449a 100644 --- a/Documentation/thermal/sysfs-api.txt +++ b/Documentation/thermal/sysfs-api.txt @@ -278,3 +278,15 @@ method, the sys I/F structure will be built like this: |---name: acpitz |---temp1_input: 37000 |---temp1_crit: 100000 + +4. Event Notification + +The framework includes a simple notification mechanism, in the form of a +netlink event. Netlink socket initialization is done during the _init_ +of the framework. Drivers which intend to use the notification mechanism +just need to call generate_netlink_event() with two arguments viz +(originator, event). Typically the originator will be an integer assigned +to a thermal_zone_device when it registers itself with the framework. The +event will be one of:{THERMAL_AUX0, THERMAL_AUX1, THERMAL_CRITICAL, +THERMAL_DEV_FAULT}. Notification can be sent when the current temperature +crosses any of the configured thresholds. diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index bf7c687519e..f7a5dba3ca2 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -4,6 +4,7 @@ menuconfig THERMAL tristate "Generic Thermal sysfs driver" + depends on NET help Generic Thermal Sysfs driver offers a generic mechanism for thermal management. Usually it's made up of one or more thermal diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 13c72c62932..760e045c93c 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include MODULE_AUTHOR("Zhang Rui"); MODULE_DESCRIPTION("Generic thermal management sysfs support"); @@ -58,6 +60,22 @@ static LIST_HEAD(thermal_tz_list); static LIST_HEAD(thermal_cdev_list); static DEFINE_MUTEX(thermal_list_lock); +static unsigned int thermal_event_seqnum; + +static struct genl_family thermal_event_genl_family = { + .id = GENL_ID_GENERATE, + .name = THERMAL_GENL_FAMILY_NAME, + .version = THERMAL_GENL_VERSION, + .maxattr = THERMAL_GENL_ATTR_MAX, +}; + +static struct genl_multicast_group thermal_event_mcgrp = { + .name = THERMAL_GENL_MCAST_GROUP_NAME, +}; + +static int genetlink_init(void); +static void genetlink_exit(void); + static int get_idr(struct idr *idr, struct mutex *lock, int *id) { int err; @@ -1214,6 +1232,82 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) EXPORT_SYMBOL(thermal_zone_device_unregister); +int generate_netlink_event(u32 orig, enum events event) +{ + struct sk_buff *skb; + struct nlattr *attr; + struct thermal_genl_event *thermal_event; + void *msg_header; + int size; + int result; + + /* allocate memory */ + size = nla_total_size(sizeof(struct thermal_genl_event)) + \ + nla_total_size(0); + + skb = genlmsg_new(size, GFP_ATOMIC); + if (!skb) + return -ENOMEM; + + /* add the genetlink message header */ + msg_header = genlmsg_put(skb, 0, thermal_event_seqnum++, + &thermal_event_genl_family, 0, + THERMAL_GENL_CMD_EVENT); + if (!msg_header) { + nlmsg_free(skb); + return -ENOMEM; + } + + /* fill the data */ + attr = nla_reserve(skb, THERMAL_GENL_ATTR_EVENT, \ + sizeof(struct thermal_genl_event)); + + if (!attr) { + nlmsg_free(skb); + return -EINVAL; + } + + thermal_event = nla_data(attr); + if (!thermal_event) { + nlmsg_free(skb); + return -EINVAL; + } + + memset(thermal_event, 0, sizeof(struct thermal_genl_event)); + + thermal_event->orig = orig; + thermal_event->event = event; + + /* send multicast genetlink message */ + result = genlmsg_end(skb, msg_header); + if (result < 0) { + nlmsg_free(skb); + return result; + } + + result = genlmsg_multicast(skb, 0, thermal_event_mcgrp.id, GFP_ATOMIC); + if (result) + printk(KERN_INFO "failed to send netlink event:%d", result); + + return result; +} +EXPORT_SYMBOL(generate_netlink_event); + +static int genetlink_init(void) +{ + int result; + + result = genl_register_family(&thermal_event_genl_family); + if (result) + return result; + + result = genl_register_mc_group(&thermal_event_genl_family, + &thermal_event_mcgrp); + if (result) + genl_unregister_family(&thermal_event_genl_family); + return result; +} + static int __init thermal_init(void) { int result = 0; @@ -1225,9 +1319,15 @@ static int __init thermal_init(void) mutex_destroy(&thermal_idr_lock); mutex_destroy(&thermal_list_lock); } + result = genetlink_init(); return result; } +static void genetlink_exit(void) +{ + genl_unregister_family(&thermal_event_genl_family); +} + static void __exit thermal_exit(void) { class_unregister(&thermal_class); @@ -1235,7 +1335,8 @@ static void __exit thermal_exit(void) idr_destroy(&thermal_cdev_idr); mutex_destroy(&thermal_idr_lock); mutex_destroy(&thermal_list_lock); + genetlink_exit(); } -subsys_initcall(thermal_init); +fs_initcall(thermal_init); module_exit(thermal_exit); diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 1de8b9eb841..78464496127 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -127,6 +127,37 @@ struct thermal_zone_device { struct thermal_hwmon_attr temp_crit; /* hwmon sys attr */ #endif }; +/* Adding event notification support elements */ +#define THERMAL_GENL_FAMILY_NAME "thermal_event" +#define THERMAL_GENL_VERSION 0x01 +#define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_group" + +enum events { + THERMAL_AUX0, + THERMAL_AUX1, + THERMAL_CRITICAL, + THERMAL_DEV_FAULT, +}; + +struct thermal_genl_event { + u32 orig; + enum events event; +}; +/* attributes of thermal_genl_family */ +enum { + THERMAL_GENL_ATTR_UNSPEC, + THERMAL_GENL_ATTR_EVENT, + __THERMAL_GENL_ATTR_MAX, +}; +#define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1) + +/* commands supported by the thermal_genl_family */ +enum { + THERMAL_GENL_CMD_UNSPEC, + THERMAL_GENL_CMD_EVENT, + __THERMAL_GENL_CMD_MAX, +}; +#define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1) struct thermal_zone_device *thermal_zone_device_register(char *, int, void *, struct @@ -146,5 +177,6 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *, void *, thermal_cooling_device_ops *); void thermal_cooling_device_unregister(struct thermal_cooling_device *); +extern int generate_netlink_event(u32 orig, enum events event); #endif /* __THERMAL_H__ */ -- cgit v1.2.3-70-g09d2 From 3a37898d507794cfc68a092303e02651d3f01308 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Mon, 13 Dec 2010 13:36:15 +0800 Subject: ACPICA: Rename some function and variable names Some function and variable names are renamed to be consistent with ACPICA code base. acpi_raw_enable_gpe -> acpi_ev_add_gpe_reference acpi_raw_disable_gpe -> acpi_ev_remove_gpe_reference acpi_gpe_can_wake -> acpi_setup_gpe_for_wake acpi_gpe_wakeup -> acpi_set_gpe_wake_mask acpi_update_gpes -> acpi_update_all_gpes acpi_all_gpes_initialized -> acpi_gbl_all_gpes_initialized acpi_handler_info -> acpi_gpe_handler_info ... Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/acevents.h | 6 ++--- drivers/acpi/acpica/acglobal.h | 2 +- drivers/acpi/acpica/aclocal.h | 8 +++---- drivers/acpi/acpica/evgpe.c | 14 +++++++---- drivers/acpi/acpica/evgpeblk.c | 4 ++-- drivers/acpi/acpica/evxface.c | 16 ++++++------- drivers/acpi/acpica/evxfgpe.c | 53 ++++++++++++++++++++++++++---------------- drivers/acpi/acpica/hwgpe.c | 2 +- drivers/acpi/acpica/utglobal.c | 2 +- drivers/acpi/dock.c | 2 +- drivers/acpi/scan.c | 6 ++--- drivers/acpi/wakeup.c | 4 ++-- include/acpi/acpixf.h | 6 ++--- include/acpi/actypes.h | 4 ++-- 14 files changed, 73 insertions(+), 56 deletions(-) (limited to 'include') diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 43f15c8cd2b..ce2af07f62b 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -82,9 +82,9 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info); acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info); -acpi_status acpi_raw_enable_gpe(struct acpi_gpe_event_info *gpe_event_info); +acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info); -acpi_status acpi_raw_disable_gpe(struct acpi_gpe_event_info *gpe_event_info); +acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info); struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, u32 gpe_number); @@ -107,7 +107,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, acpi_status acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, struct acpi_gpe_block_info *gpe_block, - void *ignored); + void *context); acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block); diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index ad88fcae4eb..fc694647699 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -370,7 +370,7 @@ ACPI_EXTERN struct acpi_fixed_event_handler ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; ACPI_EXTERN struct acpi_gpe_block_info *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; -ACPI_EXTERN u8 acpi_all_gpes_initialized; +ACPI_EXTERN u8 acpi_gbl_all_gpes_initialized; /***************************************************************************** * diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 2ceb0c05b2d..2f841d019a3 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -412,13 +412,13 @@ struct acpi_handler_info { acpi_event_handler address; /* Address of handler, if any */ void *context; /* Context to be passed to handler */ struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */ - u8 orig_flags; /* Original misc info about this GPE */ - u8 orig_enabled; /* Set if the GPE was originally enabled */ + u8 original_flags; /* Original (pre-handler) GPE info */ + u8 originally_enabled; /* True if GPE was originally enabled */ }; union acpi_gpe_dispatch_info { struct acpi_namespace_node *method_node; /* Method node for this GPE level */ - struct acpi_handler_info *handler; + struct acpi_handler_info *handler; /* Installed GPE handler */ }; /* @@ -458,7 +458,7 @@ struct acpi_gpe_block_info { u32 register_count; /* Number of register pairs in block */ u16 gpe_count; /* Number of individual GPEs in block */ u8 block_base_number; /* Base GPE number for this block */ - u8 initialized; /* If set, the GPE block has been initialized */ + u8 initialized; /* TRUE if this block is initialized */ }; /* Information about GPE interrupt handlers, one per each interrupt level used for GPEs */ diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index f226eac314d..005c170d244 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -137,7 +137,7 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) /******************************************************************************* * - * FUNCTION: acpi_raw_enable_gpe + * FUNCTION: acpi_ev_add_gpe_reference * * PARAMETERS: gpe_event_info - GPE to enable * @@ -148,10 +148,12 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) * ******************************************************************************/ -acpi_status acpi_raw_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) +acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info) { acpi_status status = AE_OK; + ACPI_FUNCTION_TRACE(ev_add_gpe_reference); + if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) { return_ACPI_STATUS(AE_LIMIT); } @@ -173,7 +175,7 @@ acpi_status acpi_raw_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) /******************************************************************************* * - * FUNCTION: acpi_raw_disable_gpe + * FUNCTION: acpi_ev_remove_gpe_reference * * PARAMETERS: gpe_event_info - GPE to disable * @@ -184,10 +186,12 @@ acpi_status acpi_raw_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) * ******************************************************************************/ -acpi_status acpi_raw_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) +acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info) { acpi_status status = AE_OK; + ACPI_FUNCTION_TRACE(ev_remove_gpe_reference); + if (!gpe_event_info->runtime_count) { return_ACPI_STATUS(AE_LIMIT); } @@ -529,7 +533,7 @@ static void acpi_ev_asynch_enable_gpe(void *context) * Enable this GPE, conditionally. This means that the GPE will only be * physically enabled if the enable_for_run bit is set in the event_info */ - (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_COND_ENABLE); + (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE); return_VOID; } diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index 020add3eee1..2a445dfcfdb 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -386,7 +386,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, return_ACPI_STATUS(status); } - acpi_all_gpes_initialized = FALSE; + acpi_gbl_all_gpes_initialized = FALSE; /* Find all GPE methods (_Lxx or_Exx) for this block */ @@ -479,7 +479,7 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, continue; } - status = acpi_raw_enable_gpe(gpe_event_info); + status = acpi_ev_add_gpe_reference(gpe_event_info); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not enable GPE 0x%02X", diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 36af222cac6..042a6d69f38 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -722,7 +722,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device, handler->address = address; handler->context = context; handler->method_node = gpe_event_info->dispatch.method_node; - handler->orig_flags = gpe_event_info->flags & + handler->original_flags = gpe_event_info->flags & (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* @@ -731,10 +731,10 @@ acpi_install_gpe_handler(acpi_handle gpe_device, * disabled now to avoid spurious execution of the handler. */ - if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD) + if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) && gpe_event_info->runtime_count) { - handler->orig_enabled = 1; - (void)acpi_raw_disable_gpe(gpe_event_info); + handler->originally_enabled = 1; + (void)acpi_ev_remove_gpe_reference(gpe_event_info); } /* Install the handler */ @@ -835,7 +835,7 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, gpe_event_info->dispatch.method_node = handler->method_node; gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); - gpe_event_info->flags |= handler->orig_flags; + gpe_event_info->flags |= handler->original_flags; /* * If the GPE was previously associated with a method and it was @@ -843,9 +843,9 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, * post-initialization configuration. */ - if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD) - && handler->orig_enabled) - (void)acpi_raw_enable_gpe(gpe_event_info); + if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) + && handler->originally_enabled) + (void)acpi_ev_add_gpe_reference(gpe_event_info); /* Now we can free the handler object */ diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index 8068065d90e..99f77ab2972 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -51,7 +51,7 @@ ACPI_MODULE_NAME("evxfgpe") /****************************************************************************** * - * FUNCTION: acpi_update_gpes + * FUNCTION: acpi_update_all_gpes * * PARAMETERS: None * @@ -65,30 +65,34 @@ ACPI_MODULE_NAME("evxfgpe") * ******************************************************************************/ -acpi_status acpi_update_gpes(void) +acpi_status acpi_update_all_gpes(void) { acpi_status status; - ACPI_FUNCTION_TRACE(acpi_update_gpes); + ACPI_FUNCTION_TRACE(acpi_update_all_gpes); status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); - } else if (acpi_all_gpes_initialized) { - goto unlock; + } + + if (acpi_gbl_all_gpes_initialized) { + goto unlock_and_exit; } status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL); if (ACPI_SUCCESS(status)) { - acpi_all_gpes_initialized = TRUE; + acpi_gbl_all_gpes_initialized = TRUE; } -unlock: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_update_all_gpes) + /******************************************************************************* * * FUNCTION: acpi_enable_gpe @@ -117,7 +121,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); if (gpe_event_info) { - status = acpi_raw_enable_gpe(gpe_event_info); + status = acpi_ev_add_gpe_reference(gpe_event_info); } acpi_os_release_lock(acpi_gbl_gpe_lock, flags); @@ -154,7 +158,7 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); if (gpe_event_info) { - status = acpi_raw_disable_gpe(gpe_event_info) ; + status = acpi_ev_remove_gpe_reference(gpe_event_info) ; } acpi_os_release_lock(acpi_gbl_gpe_lock, flags); @@ -164,7 +168,7 @@ ACPI_EXPORT_SYMBOL(acpi_disable_gpe) /******************************************************************************* * - * FUNCTION: acpi_gpe_can_wake + * FUNCTION: acpi_setup_gpe_for_wake * * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 * gpe_number - GPE level within the GPE block @@ -178,13 +182,13 @@ ACPI_EXPORT_SYMBOL(acpi_disable_gpe) * to be initially disabled). * ******************************************************************************/ -acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number) +acpi_status acpi_setup_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number) { acpi_status status = AE_OK; struct acpi_gpe_event_info *gpe_event_info; acpi_cpu_flags flags; - ACPI_FUNCTION_TRACE(acpi_gpe_can_wake); + ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake); flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); @@ -200,11 +204,11 @@ acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number) acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake) +ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake) /******************************************************************************* * - * FUNCTION: acpi_gpe_wakeup + * FUNCTION: acpi_set_gpe_wake_mask * * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 * gpe_number - GPE level within the GPE block @@ -216,7 +220,7 @@ ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake) * ******************************************************************************/ -acpi_status acpi_gpe_wakeup(acpi_handle gpe_device, u32 gpe_number, u8 action) +acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action) { acpi_status status = AE_OK; struct acpi_gpe_event_info *gpe_event_info; @@ -224,18 +228,23 @@ acpi_status acpi_gpe_wakeup(acpi_handle gpe_device, u32 gpe_number, u8 action) acpi_cpu_flags flags; u32 register_bit; - ACPI_FUNCTION_TRACE(acpi_gpe_wakeup); + ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask); 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); - if (!gpe_event_info || !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { + if (!gpe_event_info) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } + if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { + status = AE_TYPE; + goto unlock_and_exit; + } + gpe_register_info = gpe_event_info->register_info; if (!gpe_register_info) { status = AE_NOT_EXIST; @@ -269,7 +278,7 @@ unlock_and_exit: return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_gpe_wakeup) +ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask) /******************************************************************************* * @@ -387,6 +396,8 @@ acpi_status acpi_disable_all_gpes(void) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes) + /****************************************************************************** * * FUNCTION: acpi_enable_all_runtime_gpes @@ -416,6 +427,8 @@ acpi_status acpi_enable_all_runtime_gpes(void) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes) + /******************************************************************************* * * FUNCTION: acpi_install_gpe_block @@ -435,7 +448,7 @@ acpi_install_gpe_block(acpi_handle gpe_device, struct acpi_generic_address *gpe_block_address, u32 register_count, u32 interrupt_number) { - acpi_status status = AE_OK; + acpi_status status; union acpi_operand_object *obj_desc; struct acpi_namespace_node *node; struct acpi_gpe_block_info *gpe_block; @@ -603,7 +616,7 @@ acpi_get_gpe_device(u32 index, acpi_handle *gpe_device) return_ACPI_STATUS(status); } - *gpe_device = info.gpe_device; + *gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device); return_ACPI_STATUS(info.status); } diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index 14750db2a1b..7c6d4858bb4 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c @@ -118,7 +118,7 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action) register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info); switch (action) { - case ACPI_GPE_COND_ENABLE: + case ACPI_GPE_CONDITIONAL_ENABLE: if (!(register_bit & gpe_register_info->enable_for_run)) return (AE_BAD_PARAMETER); diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index e87bc6760be..a99c32aa48a 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -768,7 +768,7 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_gpe_fadt_blocks[0] = NULL; acpi_gbl_gpe_fadt_blocks[1] = NULL; acpi_current_gpe_count = 0; - acpi_all_gpes_initialized = FALSE; + acpi_gbl_all_gpes_initialized = FALSE; /* Global handlers */ diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 81514a4918c..1864ad3cf89 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -725,7 +725,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) complete_dock(ds); dock_event(ds, event, DOCK_EVENT); dock_lock(ds, 1); - acpi_update_gpes(); + acpi_update_all_gpes(); break; } if (dock_present(ds) || dock_in_progress(ds)) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 29ef505c487..70249b3d293 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -778,7 +778,7 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, wakeup->resources.handles[i] = element->reference.handle; } - acpi_gpe_can_wake(wakeup->gpe_device, wakeup->gpe_number); + acpi_setup_gpe_for_wake(wakeup->gpe_device, wakeup->gpe_number); out: kfree(buffer.pointer); @@ -1467,7 +1467,7 @@ int acpi_bus_start(struct acpi_device *device) result = acpi_bus_scan(device->handle, &ops, NULL); - acpi_update_gpes(); + acpi_update_all_gpes(); return result; } @@ -1584,7 +1584,7 @@ int __init acpi_scan_init(void) if (result) acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); else - acpi_update_gpes(); + acpi_update_all_gpes(); return result; } diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c index f62a50c3ed3..c6cb68e0a80 100644 --- a/drivers/acpi/wakeup.c +++ b/drivers/acpi/wakeup.c @@ -45,7 +45,7 @@ void acpi_enable_wakeup_devices(u8 sleep_state) acpi_enable_wakeup_device_power(dev, sleep_state); /* The wake-up power should have been enabled already. */ - acpi_gpe_wakeup(dev->wakeup.gpe_device, dev->wakeup.gpe_number, + acpi_set_gpe_wake_mask(dev->wakeup.gpe_device, dev->wakeup.gpe_number, ACPI_GPE_ENABLE); } } @@ -67,7 +67,7 @@ void acpi_disable_wakeup_devices(u8 sleep_state) || (sleep_state > (u32) dev->wakeup.sleep_state)) continue; - acpi_gpe_wakeup(dev->wakeup.gpe_device, dev->wakeup.gpe_number, + acpi_set_gpe_wake_mask(dev->wakeup.gpe_device, dev->wakeup.gpe_number, ACPI_GPE_DISABLE); if (dev->wakeup.state.enabled) diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 53b7cfd924a..5f8ccf1b5ae 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -292,11 +292,11 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number); acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number); -acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number); +acpi_status acpi_setup_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number); acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number); -acpi_status acpi_gpe_wakeup(acpi_handle gpe_device, u32 gpe_number, u8 action); +acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action); acpi_status acpi_get_gpe_status(acpi_handle gpe_device, @@ -315,7 +315,7 @@ acpi_install_gpe_block(acpi_handle gpe_device, acpi_status acpi_remove_gpe_block(acpi_handle gpe_device); -acpi_status acpi_update_gpes(void); +acpi_status acpi_update_all_gpes(void); /* * Resource interfaces diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 2b134b691e3..e73893994b5 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -656,11 +656,11 @@ typedef u32 acpi_event_status; #define ACPI_GPE_MAX 0xFF #define ACPI_NUM_GPE 256 -/* Actions for acpi_gpe_wakeup, acpi_hw_low_set_gpe */ +/* Actions for acpi_set_gpe_wake_mask, acpi_hw_low_set_gpe */ #define ACPI_GPE_ENABLE 0 #define ACPI_GPE_DISABLE 1 -#define ACPI_GPE_COND_ENABLE 2 +#define ACPI_GPE_CONDITIONAL_ENABLE 2 /* * GPE info flags - Per GPE -- cgit v1.2.3-70-g09d2 From 8b6cd8ad18def34bfc5045b2a0234329bf94cf78 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Mon, 13 Dec 2010 13:38:46 +0800 Subject: ACPICA: New GPE handler callback definition The new GPE handler callback has 2 additional parameters, gpe_device and gpe_number. typedef u32 (*acpi_gpe_handler) (acpi_handle gpe_device, u32 gpe_number, void *context); Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/acevents.h | 3 ++- drivers/acpi/acpica/aclocal.h | 6 +++--- drivers/acpi/acpica/evgpe.c | 14 ++++++++++---- drivers/acpi/acpica/evxface.c | 10 +++++----- drivers/acpi/ec.c | 3 ++- drivers/char/ipmi/ipmi_si_intf.c | 3 ++- include/acpi/acpixf.h | 4 ++-- include/acpi/actypes.h | 3 +++ 8 files changed, 29 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index ce2af07f62b..ebb467fe367 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -112,7 +112,8 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block); u32 -acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, +acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, + struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number); /* diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 2f841d019a3..6a71f8e673e 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -408,8 +408,8 @@ struct acpi_predefined_data { /* Dispatch info for each GPE -- either a method or handler, cannot be both */ -struct acpi_handler_info { - acpi_event_handler address; /* Address of handler, if any */ +struct acpi_gpe_handler_info { + acpi_gpe_handler address; /* Address of handler, if any */ void *context; /* Context to be passed to handler */ struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */ u8 original_flags; /* Original (pre-handler) GPE info */ @@ -418,7 +418,7 @@ struct acpi_handler_info { union acpi_gpe_dispatch_info { struct acpi_namespace_node *method_node; /* Method node for this GPE level */ - struct acpi_handler_info *handler; /* Installed GPE handler */ + struct acpi_gpe_handler_info *handler; /* Installed GPE handler */ }; /* diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 005c170d244..3fb621eec2f 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -409,7 +409,9 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) * or method. */ int_status |= - acpi_ev_gpe_dispatch(&gpe_block-> + acpi_ev_gpe_dispatch(gpe_block-> + node, + &gpe_block-> event_info[((acpi_size) i * ACPI_GPE_REGISTER_WIDTH) + j], j + gpe_register_info->base_gpe_number); } } @@ -542,7 +544,8 @@ static void acpi_ev_asynch_enable_gpe(void *context) * * FUNCTION: acpi_ev_gpe_dispatch * - * PARAMETERS: gpe_event_info - Info for this GPE + * PARAMETERS: gpe_device - Device node. NULL for GPE0/GPE1 + * gpe_event_info - Info for this GPE * gpe_number - Number relative to the parent GPE block * * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED @@ -555,7 +558,8 @@ static void acpi_ev_asynch_enable_gpe(void *context) ******************************************************************************/ u32 -acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) +acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, + struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) { acpi_status status; @@ -593,7 +597,9 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) * Ignore return status for now. * TBD: leave GPE disabled on error? */ - (void)gpe_event_info->dispatch.handler->address(gpe_event_info-> + (void)gpe_event_info->dispatch.handler->address(gpe_device, + gpe_number, + gpe_event_info-> dispatch. handler-> context); diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 042a6d69f38..d193b905dfa 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -671,10 +671,10 @@ ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler) acpi_status acpi_install_gpe_handler(acpi_handle gpe_device, u32 gpe_number, - u32 type, acpi_event_handler address, void *context) + u32 type, acpi_gpe_handler address, void *context) { struct acpi_gpe_event_info *gpe_event_info; - struct acpi_handler_info *handler; + struct acpi_gpe_handler_info *handler; acpi_status status; acpi_cpu_flags flags; @@ -693,7 +693,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device, /* Allocate memory for the handler object */ - handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_handler_info)); + handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info)); if (!handler) { status = AE_NO_MEMORY; goto unlock_and_exit; @@ -777,10 +777,10 @@ ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler) ******************************************************************************/ acpi_status acpi_remove_gpe_handler(acpi_handle gpe_device, - u32 gpe_number, acpi_event_handler address) + u32 gpe_number, acpi_gpe_handler address) { struct acpi_gpe_event_info *gpe_event_info; - struct acpi_handler_info *handler; + struct acpi_gpe_handler_info *handler; acpi_status status; acpi_cpu_flags flags; diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 302b31ed31f..81887724de8 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -606,7 +606,8 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state) return 0; } -static u32 acpi_ec_gpe_handler(void *data) +static u32 acpi_ec_gpe_handler(acpi_handle gpe_device, + u32 gpe_number, void *data) { struct acpi_ec *ec = data; diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 035da9e64a1..c4bacc6ec45 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -1928,7 +1928,8 @@ static void __devinit hardcode_find_bmc(void) static int acpi_failure; /* For GPE-type interrupts. */ -static u32 ipmi_acpi_gpe(void *context) +static u32 ipmi_acpi_gpe(acpi_handle gpe_device, + u32 gpe_number, void *context) { struct smi_info *smi_info = context; unsigned long flags; diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 5f8ccf1b5ae..b806e5611c9 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -258,11 +258,11 @@ acpi_remove_address_space_handler(acpi_handle device, acpi_status acpi_install_gpe_handler(acpi_handle gpe_device, u32 gpe_number, - u32 type, acpi_event_handler address, void *context); + u32 type, acpi_gpe_handler address, void *context); acpi_status acpi_remove_gpe_handler(acpi_handle gpe_device, - u32 gpe_number, acpi_event_handler address); + u32 gpe_number, acpi_gpe_handler address); #ifdef ACPI_FUTURE_USAGE acpi_status acpi_install_exception_handler(acpi_exception_handler handler); diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index e73893994b5..b9575ad9b74 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -896,6 +896,9 @@ typedef void */ typedef u32(*acpi_event_handler) (void *context); +typedef +u32 (*acpi_gpe_handler) (acpi_handle gpe_device, u32 gpe_number, void *context); + typedef void (*acpi_notify_handler) (acpi_handle device, u32 value, void *context); -- cgit v1.2.3-70-g09d2 From bba63a296ffab20e08d9e8252d2f0d99050ac859 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Mon, 13 Dec 2010 13:39:17 +0800 Subject: ACPICA: Implicit notify support This feature provides an automatic device notification for wake devices when a wakeup GPE occurs and there is no corresponding GPE method or handler. Rather than ignoring such a GPE, an implicit AML Notify operation is performed on the parent device object. This feature is not part of the ACPI specification and is provided for Windows compatibility only. Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/acevents.h | 2 + drivers/acpi/acpica/aclocal.h | 1 + drivers/acpi/acpica/evgpe.c | 172 +++++++++++++++++++++++----------------- drivers/acpi/acpica/evgpeblk.c | 11 ++- drivers/acpi/acpica/evgpeinit.c | 1 + drivers/acpi/acpica/evxfgpe.c | 58 +++++++++++--- drivers/acpi/ec.c | 2 +- drivers/acpi/scan.c | 2 +- include/acpi/acpixf.h | 6 +- include/acpi/actypes.h | 37 +++++---- 10 files changed, 186 insertions(+), 106 deletions(-) (limited to 'include') diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 04a83fe47d6..70e0b28801a 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -91,6 +91,8 @@ struct acpi_gpe_event_info *acpi_ev_low_get_gpe_info(u32 gpe_number, struct acpi_gpe_block_info *gpe_block); +acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info); + /* * evgpeblk - Upper-level GPE block support */ diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 6a71f8e673e..74000f5b7da 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -419,6 +419,7 @@ struct acpi_gpe_handler_info { union acpi_gpe_dispatch_info { struct acpi_namespace_node *method_node; /* Method node for this GPE level */ struct acpi_gpe_handler_info *handler; /* Installed GPE handler */ + struct acpi_namespace_node *device_node; /* Parent _PRW device for implicit notify */ }; /* diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index c25999546c8..2dbca95979c 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -115,12 +115,13 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) ACPI_FUNCTION_TRACE(ev_enable_gpe); /* - * We will only allow a GPE to be enabled if it has either an - * associated method (_Lxx/_Exx) or a handler. Otherwise, the - * GPE will be immediately disabled by acpi_ev_gpe_dispatch the - * first time it fires. + * We will only allow a GPE to be enabled if it has either an associated + * method (_Lxx/_Exx) or a handler, or is using the implicit notify + * feature. Otherwise, the GPE will be immediately disabled by + * acpi_ev_gpe_dispatch the first time it fires. */ - if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) { + if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_NONE) { return_ACPI_STATUS(AE_NO_HANDLER); } @@ -486,12 +487,26 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) return_VOID; } - /* - * Must check for control method type dispatch one more time to avoid a - * race with ev_gpe_install_handler - */ - if ((local_gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == - ACPI_GPE_DISPATCH_METHOD) { + /* Do the correct dispatch - normal method or implicit notify */ + + switch (local_gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) { + case ACPI_GPE_DISPATCH_NOTIFY: + + /* + * Implicit notify. + * Dispatch a DEVICE_WAKE notify to the appropriate handler. + * NOTE: the request is queued for execution after this method + * completes. The notify handlers are NOT invoked synchronously + * from this thread -- because handlers may in turn run other + * control methods. + */ + status = + acpi_ev_queue_notify_request(local_gpe_event_info->dispatch. + device_node, + ACPI_NOTIFY_DEVICE_WAKE); + break; + + case ACPI_GPE_DISPATCH_METHOD: /* Allocate the evaluation information block */ @@ -518,6 +533,11 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) (local_gpe_event_info->dispatch. method_node))); } + + break; + + default: + return_VOID; /* Should never happen */ } /* Defer enabling of GPE until all notify handlers are done */ @@ -531,6 +551,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) return_VOID; } + /******************************************************************************* * * FUNCTION: acpi_ev_asynch_enable_gpe @@ -541,38 +562,60 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) * RETURN: None * * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to - * complete. + * complete (i.e., finish execution of Notify) * ******************************************************************************/ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context) { struct acpi_gpe_event_info *gpe_event_info = context; + + (void)acpi_ev_finish_gpe(gpe_event_info); + + ACPI_FREE(gpe_event_info); + return; +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ev_finish_gpe + * + * PARAMETERS: gpe_event_info - Info for this GPE + * + * RETURN: Status + * + * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution + * of a GPE method or a synchronous or asynchronous GPE handler. + * + ******************************************************************************/ + +acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info) +{ acpi_status status; if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED) { /* - * GPE is level-triggered, we clear the GPE status bit after handling - * the event. + * GPE is level-triggered, we clear the GPE status bit after + * handling the event. */ status = acpi_hw_clear_gpe(gpe_event_info); if (ACPI_FAILURE(status)) { - goto exit; + return (status); } } /* - * Enable this GPE, conditionally. This means that the GPE will only be - * physically enabled if the enable_for_run bit is set in the event_info + * Enable this GPE, conditionally. This means that the GPE will + * only be physically enabled if the enable_for_run bit is set + * in the event_info. */ (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE); - -exit: - ACPI_FREE(gpe_event_info); - return; + return (AE_OK); } + /******************************************************************************* * * FUNCTION: acpi_ev_gpe_dispatch @@ -595,6 +638,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) { acpi_status status; + u32 return_value; ACPI_FUNCTION_TRACE(ev_gpe_dispatch); @@ -616,54 +660,49 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, } /* - * Dispatch the GPE to either an installed handler, or the control method - * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke - * it and do not attempt to run the method. If there is neither a handler - * nor a method, we disable this GPE to prevent further such pointless - * events from firing. + * Always disable the GPE so that it does not keep firing before + * any asynchronous activity completes (either from the execution + * of a GPE method or an asynchronous GPE handler.) + * + * If there is no handler or method to run, just disable the + * GPE and leave it disabled permanently to prevent further such + * pointless events from firing. + */ + status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Unable to disable GPE%02X", gpe_number)); + return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); + } + + /* + * Dispatch the GPE to either an installed handler or the control + * method associated with this GPE (_Lxx or _Exx). If a handler + * exists, we invoke it and do not attempt to run the method. + * If there is neither a handler nor a method, leave the GPE + * disabled. */ switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) { case ACPI_GPE_DISPATCH_HANDLER: - /* - * Invoke the installed handler (at interrupt level) - * Ignore return status for now. - * TBD: leave GPE disabled on error? - */ - (void)gpe_event_info->dispatch.handler->address(gpe_device, - gpe_number, - gpe_event_info-> - dispatch. - handler-> - context); - - /* It is now safe to clear level-triggered events. */ - - if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == - ACPI_GPE_LEVEL_TRIGGERED) { - status = acpi_hw_clear_gpe(gpe_event_info); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Unable to clear GPE[0x%2X]", - gpe_number)); - return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); - } + /* Invoke the installed handler (at interrupt level) */ + + return_value = + gpe_event_info->dispatch.handler->address(gpe_device, + gpe_number, + gpe_event_info-> + dispatch.handler-> + context); + + /* If requested, clear (if level-triggered) and reenable the GPE */ + + if (return_value & ACPI_REENABLE_GPE) { + (void)acpi_ev_finish_gpe(gpe_event_info); } break; case ACPI_GPE_DISPATCH_METHOD: - - /* - * Disable the GPE, so it doesn't keep firing before the method has a - * chance to run (it runs asynchronously with interrupts enabled). - */ - status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Unable to disable GPE[0x%2X]", - gpe_number)); - return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); - } + case ACPI_GPE_DISPATCH_NOTIFY: /* * Execute the method associated with the GPE @@ -690,17 +729,6 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, "No handler or method for GPE[0x%2X], disabling event", gpe_number)); - /* - * Disable the GPE. The GPE will remain disabled a handler - * is installed or ACPICA is restarted. - */ - status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Unable to disable GPE[0x%2X]", - gpe_number)); - return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); - } break; } diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index 2a445dfcfdb..e2e8164bb81 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -472,9 +472,14 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j; gpe_event_info = &gpe_block->event_info[gpe_index]; - /* Ignore GPEs that have no corresponding _Lxx/_Exx method */ - - if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) + /* + * Ignore GPEs that have no corresponding _Lxx/_Exx method + * and GPEs that are used to wake the system + */ + if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_NONE) + || ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) + == ACPI_GPE_DISPATCH_HANDLER) || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { continue; } diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c index 4c8dea513b6..734a494bd70 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c @@ -415,6 +415,7 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle, * Add the GPE information from above to the gpe_event_info block for * use during dispatch of this GPE. */ + gpe_event_info->flags &= ~(ACPI_GPE_DISPATCH_MASK); gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD); gpe_event_info->dispatch.method_node = method_node; diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index 99f77ab2972..fcf4a5cdc9a 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -166,39 +166,75 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) } ACPI_EXPORT_SYMBOL(acpi_disable_gpe) + /******************************************************************************* * * FUNCTION: acpi_setup_gpe_for_wake * - * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 - * gpe_number - GPE level within the GPE block + * PARAMETERS: wake_device - Device associated with the GPE (via _PRW) + * gpe_device - Parent GPE Device. NULL for GPE0/GPE1 + * gpe_number - GPE level within the GPE block * * RETURN: Status * - * DESCRIPTION: Set the ACPI_GPE_CAN_WAKE flag for the given GPE. If the GPE - * has a corresponding method and is currently enabled, disable it - * (GPEs with corresponding methods are enabled unconditionally - * during initialization, but GPEs that can wake up are expected - * to be initially disabled). + * DESCRIPTION: Mark a GPE as having the ability to wake the system. This + * interface is intended to be used as the host executes the + * _PRW methods (Power Resources for Wake) in the system tables. + * Each _PRW appears under a Device Object (The wake_device), and + * contains the info for the wake GPE associated with the + * wake_device. * ******************************************************************************/ -acpi_status acpi_setup_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number) +acpi_status +acpi_setup_gpe_for_wake(acpi_handle wake_device, + acpi_handle gpe_device, u32 gpe_number) { - acpi_status status = AE_OK; + acpi_status status = AE_BAD_PARAMETER; struct acpi_gpe_event_info *gpe_event_info; + struct acpi_namespace_node *device_node; acpi_cpu_flags flags; ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake); + /* Parameter Validation */ + + if (!wake_device) { + /* + * By forcing wake_device to be valid, we automatically enable the + * implicit notify feature on all hosts. + */ + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Validate wake_device is of type Device */ + + device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); + if (device_node->type != ACPI_TYPE_DEVICE) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + 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); if (gpe_event_info) { + /* + * If there is no method or handler for this GPE, then the + * wake_device will be notified whenever this GPE fires (aka + * "implicit notify") Note: The GPE is assumed to be + * level-triggered (for windows compatibility). + */ + if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_NONE) { + gpe_event_info->flags = + (ACPI_GPE_DISPATCH_NOTIFY | + ACPI_GPE_LEVEL_TRIGGERED); + gpe_event_info->dispatch.device_node = device_node; + } + gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; - } else { - status = AE_BAD_PARAMETER; + status = AE_OK; } acpi_os_release_lock(acpi_gbl_gpe_lock, flags); diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 81887724de8..fa848c4116a 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -619,7 +619,7 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device, wake_up(&ec->wait); ec_check_sci(ec, acpi_ec_read_status(ec)); } - return ACPI_INTERRUPT_HANDLED; + return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE; } /* -------------------------------------------------------------------------- diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 70249b3d293..ce6741ee196 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -778,7 +778,7 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, wakeup->resources.handles[i] = element->reference.handle; } - acpi_setup_gpe_for_wake(wakeup->gpe_device, wakeup->gpe_number); + acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number); out: kfree(buffer.pointer); diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index b806e5611c9..9de6a17cbd4 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -292,10 +292,12 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number); acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number); -acpi_status acpi_setup_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number); - acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number); +acpi_status +acpi_setup_gpe_for_wake(acpi_handle parent_device, + acpi_handle gpe_device, u32 gpe_number); + acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action); acpi_status diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index b9575ad9b74..d7274ee4474 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -664,25 +664,26 @@ typedef u32 acpi_event_status; /* * GPE info flags - Per GPE - * +-------+---+-+-+ - * | 7:4 |3:2|1|0| - * +-------+---+-+-+ - * | | | | - * | | | +--- Interrupt type: edge or level triggered - * | | +----- GPE can wake the system - * | +-------- Type of dispatch:to method, handler, or none - * +-------------- + * +-------+-+-+---+ + * | 7:4 |3|2|1:0| + * +-------+-+-+---+ + * | | | | + * | | | +-- Type of dispatch:to method, handler, notify, or none + * | | +----- Interrupt type: edge or level triggered + * | +------- Is a Wake GPE + * +------------ */ -#define ACPI_GPE_XRUPT_TYPE_MASK (u8) 0x01 -#define ACPI_GPE_LEVEL_TRIGGERED (u8) 0x01 -#define ACPI_GPE_EDGE_TRIGGERED (u8) 0x00 +#define ACPI_GPE_DISPATCH_NONE (u8) 0x00 +#define ACPI_GPE_DISPATCH_METHOD (u8) 0x01 +#define ACPI_GPE_DISPATCH_HANDLER (u8) 0x02 +#define ACPI_GPE_DISPATCH_NOTIFY (u8) 0x03 +#define ACPI_GPE_DISPATCH_MASK (u8) 0x03 -#define ACPI_GPE_CAN_WAKE (u8) 0x02 +#define ACPI_GPE_LEVEL_TRIGGERED (u8) 0x04 +#define ACPI_GPE_EDGE_TRIGGERED (u8) 0x00 +#define ACPI_GPE_XRUPT_TYPE_MASK (u8) 0x04 -#define ACPI_GPE_DISPATCH_MASK (u8) 0x0C -#define ACPI_GPE_DISPATCH_HANDLER (u8) 0x04 -#define ACPI_GPE_DISPATCH_METHOD (u8) 0x08 -#define ACPI_GPE_DISPATCH_NOT_USED (u8) 0x00 +#define ACPI_GPE_CAN_WAKE (u8) 0x08 /* * Flags for GPE and Lock interfaces @@ -954,6 +955,10 @@ u32 (*acpi_interface_handler) (acpi_string interface_name, u32 supported); #define ACPI_INTERRUPT_NOT_HANDLED 0x00 #define ACPI_INTERRUPT_HANDLED 0x01 +/* GPE handler return values */ + +#define ACPI_REENABLE_GPE 0x80 + /* Length of 32-bit EISAID values when converted back to a string */ #define ACPI_EISAID_STRING_SIZE 8 /* Includes null terminator */ -- cgit v1.2.3-70-g09d2 From a0fcdb237fcd4eaa7e5009b28ef5be07415f287d Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Mon, 13 Dec 2010 13:39:26 +0800 Subject: ACPICA: Global event handler The global event handler is called whenever a general purpose or fixed ACPI event occurs. Also update Linux OSL to collect events counter with global event handler. Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/acglobal.h | 5 +++++ drivers/acpi/acpica/evevent.c | 12 ++++++++-- drivers/acpi/acpica/evgpe.c | 9 +++++++- drivers/acpi/acpica/evxface.c | 51 ++++++++++++++++++++++++++++++++++++++++++ drivers/acpi/acpica/utglobal.c | 1 + drivers/acpi/sysfs.c | 19 ++++++++++++++-- include/acpi/acpixf.h | 4 ++++ include/acpi/actypes.h | 8 +++++++ 8 files changed, 104 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index fc694647699..9bb69c59bb1 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -146,6 +146,9 @@ u8 acpi_gbl_system_awake_and_running; extern u32 acpi_gbl_nesting_level; +ACPI_EXTERN u32 acpi_gpe_count; +ACPI_EXTERN u32 acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS]; + /* Support for dynamic control method tracing mechanism */ ACPI_EXTERN u32 acpi_gbl_original_dbg_level; @@ -371,6 +374,8 @@ ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; ACPI_EXTERN struct acpi_gpe_block_info *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; ACPI_EXTERN u8 acpi_gbl_all_gpes_initialized; +ACPI_EXTERN ACPI_GBL_EVENT_HANDLER acpi_gbl_global_event_handler; +ACPI_EXTERN void *acpi_gbl_global_event_handler_context; /***************************************************************************** * diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c index c61c3039c31..e5e313c663a 100644 --- a/drivers/acpi/acpica/evevent.c +++ b/drivers/acpi/acpica/evevent.c @@ -217,9 +217,17 @@ u32 acpi_ev_fixed_event_detect(void) status_bit_mask) && (fixed_enable & acpi_gbl_fixed_event_info[i]. enable_bit_mask)) { + /* + * Found an active (signalled) event. Invoke global event + * handler if present. + */ + acpi_fixed_event_count[i]++; + if (acpi_gbl_global_event_handler) { + acpi_gbl_global_event_handler + (ACPI_EVENT_TYPE_FIXED, NULL, i, + acpi_gbl_global_event_handler_context); + } - /* Found an active (signalled) event */ - acpi_os_fixed_event_count(i); int_status |= acpi_ev_fixed_event_dispatch(i); } } diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 2dbca95979c..3bcf5ef74c6 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -642,7 +642,14 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, ACPI_FUNCTION_TRACE(ev_gpe_dispatch); - acpi_os_gpe_count(gpe_number); + /* Invoke global event handler if present */ + + acpi_gpe_count++; + if (acpi_gbl_global_event_handler) { + acpi_gbl_global_event_handler(ACPI_EVENT_TYPE_GPE, gpe_device, + gpe_number, + acpi_gbl_global_event_handler_context); + } /* * If edge-triggered, clear the GPE status bit now. Note that diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index d193b905dfa..1226689bdb1 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -92,6 +92,57 @@ acpi_status acpi_install_exception_handler(acpi_exception_handler handler) ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) #endif /* ACPI_FUTURE_USAGE */ + +/******************************************************************************* + * + * FUNCTION: acpi_install_global_event_handler + * + * PARAMETERS: Handler - Pointer to the global event handler function + * Context - Value passed to the handler on each event + * + * RETURN: Status + * + * DESCRIPTION: Saves the pointer to the handler function. The global handler + * is invoked upon each incoming GPE and Fixed Event. It is + * invoked at interrupt level at the time of the event dispatch. + * Can be used to update event counters, etc. + * + ******************************************************************************/ +acpi_status +acpi_install_global_event_handler(ACPI_GBL_EVENT_HANDLER handler, void *context) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_install_global_event_handler); + + /* Parameter validation */ + + if (!handler) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Don't allow two handlers. */ + + if (acpi_gbl_global_event_handler) { + status = AE_ALREADY_EXISTS; + goto cleanup; + } + + acpi_gbl_global_event_handler = handler; + acpi_gbl_global_event_handler_context = context; + + cleanup: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler) + /******************************************************************************* * * FUNCTION: acpi_install_fixed_event_handler diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index a99c32aa48a..508537f884a 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -778,6 +778,7 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_init_handler = NULL; acpi_gbl_table_handler = NULL; acpi_gbl_interface_handler = NULL; + acpi_gbl_global_event_handler = NULL; /* Global Lock support */ diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index f8588f81048..61891e75583 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -438,7 +438,7 @@ static void delete_gpe_attr_array(void) return; } -void acpi_os_gpe_count(u32 gpe_number) +static void gpe_count(u32 gpe_number) { acpi_gpe_count++; @@ -454,7 +454,7 @@ void acpi_os_gpe_count(u32 gpe_number) return; } -void acpi_os_fixed_event_count(u32 event_number) +static void fixed_event_count(u32 event_number) { if (!all_counters) return; @@ -468,6 +468,16 @@ void acpi_os_fixed_event_count(u32 event_number) return; } +static void acpi_gbl_event_handler(u32 event_type, acpi_handle device, + u32 event_number, void *context) +{ + if (event_type == ACPI_EVENT_TYPE_GPE) + gpe_count(event_number); + + if (event_type == ACPI_EVENT_TYPE_FIXED) + fixed_event_count(event_number); +} + static int get_status(u32 index, acpi_event_status *status, acpi_handle *handle) { @@ -601,6 +611,7 @@ end: void acpi_irq_stats_init(void) { + acpi_status status; int i; if (all_counters) @@ -619,6 +630,10 @@ void acpi_irq_stats_init(void) if (all_counters == NULL) goto fail; + status = acpi_install_global_event_handler(acpi_gbl_event_handler, NULL); + if (ACPI_FAILURE(status)) + goto fail; + counter_attrs = kzalloc(sizeof(struct kobj_attribute) * (num_counters), GFP_KERNEL); if (counter_attrs == NULL) diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 9de6a17cbd4..e8142d5ebab 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -228,6 +228,10 @@ acpi_status acpi_get_parent(acpi_handle object, acpi_handle * out_handle); acpi_status acpi_install_initialization_handler(acpi_init_handler handler, u32 function); +acpi_status +acpi_install_global_event_handler(ACPI_GBL_EVENT_HANDLER handler, + void *context); + acpi_status acpi_install_fixed_event_handler(u32 acpi_event, acpi_event_handler handler, void *context); diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index d7274ee4474..939a431a6ab 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -895,6 +895,14 @@ typedef void /* * Various handlers and callback procedures */ +typedef +void (*ACPI_GBL_EVENT_HANDLER) (u32 event_type, + acpi_handle device, + u32 event_number, void *context); + +#define ACPI_EVENT_TYPE_GPE 0 +#define ACPI_EVENT_TYPE_FIXED 1 + typedef u32(*acpi_event_handler) (void *context); typedef -- cgit v1.2.3-70-g09d2 From 1ae5ec903f71c0ffa583ec54d17415892036ee18 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Mon, 27 Dec 2010 09:07:43 +0800 Subject: ACPICA: Update version to 20101209 Version 20101209. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- include/acpi/acpixf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index e8142d5ebab..241b8a04c83 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -47,7 +47,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20101013 +#define ACPI_CA_VERSION 0x20101209 #include "actypes.h" #include "actbl.h" -- cgit v1.2.3-70-g09d2 From 25eed40720fc9005c63a1f436e5f8a78836c26ff Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 25 Nov 2010 00:09:15 +0100 Subject: ACPI / PM: Add function for updating device power state consistently Add function acpi_bus_update_power() for reading the actual power state of an ACPI device and updating its device->power.state field in such a way that its power resources' reference counters will remain consistent with that field. For this purpose introduce __acpi_bus_set_power() setting the power state of an ACPI device without updating its device->power.state field and make acpi_bus_set_power() and acpi_bus_update_power() use it (acpi_bus_set_power() retains the current behavior for now). Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/bus.c | 90 +++++++++++++++++++++++++++++++++---------------- include/acpi/acpi_bus.h | 1 + 2 files changed, 62 insertions(+), 29 deletions(-) (limited to 'include') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 45345109050..19decee72e9 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -255,44 +255,17 @@ int acpi_bus_get_power(acpi_handle handle, int *state) EXPORT_SYMBOL(acpi_bus_get_power); -int acpi_bus_set_power(acpi_handle handle, int state) +static int __acpi_bus_set_power(struct acpi_device *device, int state) { int result = 0; acpi_status status = AE_OK; - struct acpi_device *device = NULL; char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' }; - - result = acpi_bus_get_device(handle, &device); - if (result) - return result; - - if ((state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) + if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) return -EINVAL; /* Make sure this is a valid target state */ - if (!device->flags.power_manageable) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n", - kobject_name(&device->dev.kobj))); - return -ENODEV; - } - /* - * Get device's current 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)); @@ -362,6 +335,42 @@ int acpi_bus_set_power(acpi_handle handle, int state) return result; } + +int acpi_bus_set_power(acpi_handle handle, int state) +{ + struct acpi_device *device; + int result; + + result = acpi_bus_get_device(handle, &device); + if (result) + return result; + + if (!device->flags.power_manageable) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Device [%s] is not power manageable\n", + dev_name(&device->dev))); + return -ENODEV; + } + + /* + * Get device's current 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, &device->power.state); + } + + return __acpi_bus_set_power(device, state); +} EXPORT_SYMBOL(acpi_bus_set_power); @@ -389,6 +398,29 @@ int acpi_bus_init_power(struct acpi_device *device) } +int acpi_bus_update_power(acpi_handle handle, int *state_p) +{ + struct acpi_device *device; + int state; + int result; + + result = acpi_bus_get_device(handle, &device); + if (result) + return result; + + result = __acpi_bus_get_power(device, &state); + if (result) + return result; + + result = __acpi_bus_set_power(device, state); + if (!result && state_p) + *state_p = state; + + return result; +} +EXPORT_SYMBOL_GPL(acpi_bus_update_power); + + bool acpi_bus_power_manageable(acpi_handle handle) { struct acpi_device *device; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 359ef11725a..5d2c4c54006 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -330,6 +330,7 @@ acpi_status acpi_bus_get_status_handle(acpi_handle handle, int acpi_bus_get_status(struct acpi_device *device); int acpi_bus_get_power(acpi_handle handle, int *state); int acpi_bus_set_power(acpi_handle handle, int state); +int acpi_bus_update_power(acpi_handle handle, int *state_p); bool acpi_bus_power_manageable(acpi_handle handle); bool acpi_bus_can_wakeup(acpi_handle handle); #ifdef CONFIG_ACPI_PROC_EVENT -- cgit v1.2.3-70-g09d2 From 488a76c52606199100adf09c8eb7cbedbd94e9d9 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 25 Nov 2010 00:11:24 +0100 Subject: ACPI / Fan: Rework the handling of power resources Use the new function acpi_bus_update_power() for manipulating power resources used by ACPI fan devices, which allows them to be put into the right state during initialization and resume. Consequently, remove the flags.force_power_state field from struct acpi_device, which is not necessary any more. Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/bus.c | 2 +- drivers/acpi/fan.c | 27 +++++++-------------------- drivers/acpi/thermal.c | 5 +++-- include/acpi/acpi_bus.h | 3 +-- 4 files changed, 12 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 47864013c0d..2ee83b5fff9 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -266,7 +266,7 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state) /* Make sure this is a valid target state */ - if ((state == device->power.state) && !device->flags.force_power_state) { + if (state == device->power.state) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", state)); return 0; diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 60049080c86..467479f07c1 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -86,7 +86,7 @@ static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long if (!device) return -EINVAL; - result = acpi_bus_get_power(device->handle, &acpi_state); + result = acpi_bus_update_power(device->handle, &acpi_state); if (result) return result; @@ -123,7 +123,6 @@ static struct thermal_cooling_device_ops fan_cooling_ops = { static int acpi_fan_add(struct acpi_device *device) { int result = 0; - int state = 0; struct thermal_cooling_device *cdev; if (!device) @@ -132,16 +131,12 @@ static int acpi_fan_add(struct acpi_device *device) strcpy(acpi_device_name(device), "Fan"); strcpy(acpi_device_class(device), ACPI_FAN_CLASS); - result = acpi_bus_get_power(device->handle, &state); + result = acpi_bus_update_power(device->handle, NULL); if (result) { - printk(KERN_ERR PREFIX "Reading power state\n"); + printk(KERN_ERR PREFIX "Setting initial power state\n"); goto end; } - device->flags.force_power_state = 1; - acpi_bus_set_power(device->handle, state); - device->flags.force_power_state = 0; - cdev = thermal_cooling_device_register("Fan", device, &fan_cooling_ops); if (IS_ERR(cdev)) { @@ -200,22 +195,14 @@ static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state) static int acpi_fan_resume(struct acpi_device *device) { - int result = 0; - int power_state = 0; + int result; if (!device) return -EINVAL; - result = acpi_bus_get_power(device->handle, &power_state); - if (result) { - printk(KERN_ERR PREFIX - "Error reading fan power state\n"); - return result; - } - - device->flags.force_power_state = 1; - acpi_bus_set_power(device->handle, power_state); - device->flags.force_power_state = 0; + result = acpi_bus_update_power(device->handle, NULL); + if (result) + printk(KERN_ERR PREFIX "Error updating fan power state\n"); return result; } diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 5a27b0a3131..2607e17b520 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -1059,8 +1059,9 @@ static int acpi_thermal_resume(struct acpi_device *device) break; tz->trips.active[i].flags.enabled = 1; for (j = 0; j < tz->trips.active[i].devices.count; j++) { - result = acpi_bus_get_power(tz->trips.active[i].devices. - handles[j], &power_state); + result = acpi_bus_update_power( + tz->trips.active[i].devices.handles[j], + &power_state); if (result || (power_state != ACPI_STATE_D0)) { tz->trips.active[i].flags.enabled = 0; break; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 5d2c4c54006..89125808fbd 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -149,8 +149,7 @@ struct acpi_device_flags { u32 power_manageable:1; u32 performance_manageable:1; u32 wake_capable:1; /* Wakeup(_PRW) supported? */ - u32 force_power_state:1; - u32 reserved:22; + u32 reserved:23; }; /* File System */ -- cgit v1.2.3-70-g09d2 From f6767dcf2a4f6e62960912d0affec1e15a246191 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 11 Dec 2010 23:44:39 +0100 Subject: ACPI / PM: Drop acpi_bus_get_power() There are no more users of acpi_bus_get_power(), so it can be dropped. Moreover, it should be dropped, because it modifies the device->power.state field of an ACPI device without updating the reference counters of the device's power resources, which is wrong. Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/bus.c | 19 ------------------- include/acpi/acpi_bus.h | 1 - 2 files changed, 20 deletions(-) (limited to 'include') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 2ee83b5fff9..0baa5f97734 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -236,25 +236,6 @@ static int __acpi_bus_get_power(struct acpi_device *device, int *state) } -int acpi_bus_get_power(acpi_handle handle, int *state) -{ - struct acpi_device *device; - int result; - - result = acpi_bus_get_device(handle, &device); - if (result) - return result; - - result = __acpi_bus_get_power(device, state); - if (result) - return result; - - device->power.state = *state; - return 0; -} -EXPORT_SYMBOL(acpi_bus_get_power); - - static int __acpi_bus_set_power(struct acpi_device *device, int state) { int result = 0; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 89125808fbd..673a3f4d1f0 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -327,7 +327,6 @@ void acpi_bus_data_handler(acpi_handle handle, void *context); acpi_status acpi_bus_get_status_handle(acpi_handle handle, unsigned long long *sta); int acpi_bus_get_status(struct acpi_device *device); -int acpi_bus_get_power(acpi_handle handle, int *state); int acpi_bus_set_power(acpi_handle handle, int state); int acpi_bus_update_power(acpi_handle handle, int *state_p); bool acpi_bus_power_manageable(acpi_handle handle); -- cgit v1.2.3-70-g09d2 From d57d09a480e1db38eeee7629c81289b00f338a15 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 6 Jan 2011 23:41:27 +0100 Subject: ACPI: Drop device flag wake_capable The wake_capable ACPI device flag is not necessary, because it is only used in scan.c for recording the information that _PRW is present for the given device. That information is only used by acpi_add_single_object() to decide whether or not to call acpi_bus_get_wakeup_device_flags(), so the flag may be dropped if the _PRW check is moved to acpi_bus_get_wakeup_device_flags(). Moreover, acpi_bus_get_wakeup_device_flags() always returns 0, so it really should be void. Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/scan.c | 26 +++++++++----------------- include/acpi/acpi_bus.h | 3 +-- 2 files changed, 10 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index b5e4dedb497..b99e6249460 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -815,16 +815,22 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) !!(event_status & ACPI_EVENT_FLAG_HANDLE); } -static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) +static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) { + acpi_handle temp; acpi_status status = 0; int psw_error; + /* Presence of _PRW indicates wake capable */ + status = acpi_get_handle(device->handle, "_PRW", &temp); + if (ACPI_FAILURE(status)) + return; + status = acpi_bus_extract_wakeup_device_power_package(device->handle, &device->wakeup); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package")); - goto end; + return; } device->wakeup.flags.valid = 1; @@ -840,11 +846,6 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) if (psw_error) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in _DSW or _PSW evaluation\n")); - -end: - if (ACPI_FAILURE(status)) - device->flags.wake_capable = 0; - return 0; } static void acpi_bus_add_power_resource(acpi_handle handle); @@ -950,11 +951,6 @@ static int acpi_bus_get_flags(struct acpi_device *device) if (ACPI_SUCCESS(status)) device->flags.power_manageable = 1; - /* Presence of _PRW indicates wake capable */ - status = acpi_get_handle(device->handle, "_PRW", &temp); - if (ACPI_SUCCESS(status)) - device->flags.wake_capable = 1; - /* TBD: Performance management */ return 0; @@ -1281,11 +1277,7 @@ static int acpi_add_single_object(struct acpi_device **child, * Wakeup device management *----------------------- */ - if (device->flags.wake_capable) { - result = acpi_bus_get_wakeup_device_flags(device); - if (result) - goto end; - } + acpi_bus_get_wakeup_device_flags(device); /* * Performance Management diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 20b05cd6866..78ca429929f 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -148,8 +148,7 @@ struct acpi_device_flags { u32 suprise_removal_ok:1; u32 power_manageable:1; u32 performance_manageable:1; - u32 wake_capable:1; /* Wakeup(_PRW) supported? */ - u32 reserved:23; + u32 reserved:24; }; /* File System */ -- cgit v1.2.3-70-g09d2 From 6fed05c9c9812b5882bc708f4da4fa8d5df2875c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 12 Jan 2011 22:03:20 +0100 Subject: ACPI / PM: Fix build problems for !CONFIG_ACPI related to NVS rework The recent rework of the NVS saving/restoring code introduced two build issues for !CONFIG_ACPI, a warning in drivers/acpi/internal.h and an error in arch/x86/kernel/e820.c. Fix them by providing suitable static inline definitions of the relevant functions. Signed-off-by: Rafael J. Wysocki Acked-by: Randy Dunlap Signed-off-by: Len Brown --- drivers/acpi/internal.h | 2 +- include/linux/acpi.h | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 7c23b76e8ec..6d69bbedf97 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -90,7 +90,7 @@ void suspend_nvs_restore(void); static inline int acpi_sleep_proc_init(void) { return 0; } static inline int suspend_nvs_alloc(void) { return 0; } static inline void suspend_nvs_free(void) {} -static inline int suspend_nvs_save(void) {} +static inline int suspend_nvs_save(void) { return 0; } static inline void suspend_nvs_restore(void) {} #endif diff --git a/include/linux/acpi.h b/include/linux/acpi.h index fa7ed6a983d..eb176bb1b15 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -254,15 +254,6 @@ void __init acpi_old_suspend_ordering(void); void __init acpi_nvs_nosave(void); #endif /* CONFIG_PM_SLEEP */ -#ifdef CONFIG_ACPI_SLEEP -int suspend_nvs_register(unsigned long start, unsigned long size); -#else -static inline int suspend_nvs_register(unsigned long a, unsigned long b) -{ - return 0; -} -#endif - struct acpi_osc_context { char *uuid_str; /* uuid string */ int rev; @@ -361,4 +352,14 @@ static inline int acpi_table_parse(char *id, return -1; } #endif /* !CONFIG_ACPI */ + +#ifdef CONFIG_ACPI_SLEEP +int suspend_nvs_register(unsigned long start, unsigned long size); +#else +static inline int suspend_nvs_register(unsigned long a, unsigned long b) +{ + return 0; +} +#endif + #endif /*_LINUX_ACPI_H*/ -- cgit v1.2.3-70-g09d2