ACPI patches queued for Linux-2.6.38
Subsystems (11)
Len Brown
reviewerThese patches are in acpi-test (and linux-next), queued for 2.6.38. Please let me know if you have troubles with any of them.
thanks,
Len Brown, Intel Open Source Technology Center
Len Brown
reviewerPATCH 1/33 PNP: Compile all pnp built-in stuff in one module namespace
From: Thomas Renninger <[email protected]>
This is cleanup mostly, nothing urgent.
I came up with it when looking at dynamic debug which can enable pr_debug messages at runtime or boot param for a specific module.
Advantages:
- Any pnp code can make use of the moduleparam.h interface, the modules will show up as pnp.param.
- Passing pnp.ddebug as kernel boot param will enable all pnp debug messages with my previous patch and CONFIG_DYNAMIC_DEBUG enabled.
--- drivers/pnp/Makefile | 6 ++++-- drivers/pnp/isapnp/Makefile | 6 +++--- drivers/pnp/pnpacpi/Makefile | 3 ++- drivers/pnp/pnpbios/Makefile | 5 +++-- 4 files changed, 12 insertions(+), 8 deletions(-)
drivers/pnp/Makefile +4 -2
@@ -2,11 +2,13 @@ # Makefile for the Linux Plug-and-Play Support. # -obj-y := core.o card.o driver.o resource.o manager.o support.o interface.o quirks.o +obj-y := pnp.o + +pnp-y := core.o card.o driver.o resource.o manager.o support.o interface.o quirks.o obj-$(CONFIG_PNPACPI) += pnpacpi/ obj-$(CONFIG_PNPBIOS) += pnpbios/ obj-$(CONFIG_ISAPNP) += isapnp/ # pnp_system_init goes after pnpacpi/pnpbios init -obj-y += system.o +pnp-y += system.o
drivers/pnp/isapnp/Makefile +3 -3
@@ -1,7 +1,7 @@ # # Makefile for the kernel ISAPNP driver. # +obj-y += pnp.o +pnp-y := core.o compat.o -isapnp-proc-$(CONFIG_PROC_FS) = proc.o - -obj-y := core.o compat.o $(isapnp-proc-y) +pnp-$(CONFIG_PROC_FS) += proc.o
drivers/pnp/pnpacpi/Makefile +2 -1
@@ -1,5 +1,6 @@ # # Makefile for the kernel PNPACPI driver. # +obj-y += pnp.o -obj-y := core.o rsparser.o +pnp-y := core.o rsparser.o
drivers/pnp/pnpbios/Makefile +3 -2
@@ -1,7 +1,8 @@ # # Makefile for the kernel PNPBIOS driver. # +obj-y := pnp.o -pnpbios-proc-$(CONFIG_PNPBIOS_PROC_FS) = proc.o +pnp-y := core.o bioscalls.o rsparser.o -obj-y := core.o bioscalls.o rsparser.o $(pnpbios-proc-y) +pnp-$(CONFIG_PNPBIOS_PROC_FS) += proc.o
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 2/33 PNP: Set up pnp_debug via module and not via boot param.
In reply to Len BrownFrom: Thomas Renninger <[email protected]>
Cleanup only, no functional change (pnp.debug can be enabled and disabled at runtime, but that's not a real enhancement).
This one depends on another PNP cleanup patch:
PNP: Compile all pnp built-in stuff in one module namespace
--- drivers/pnp/core.c | 7 +------ 1 files changed, 1 insertions(+), 6 deletions(-)
drivers/pnp/core.c +1 -6
@@ -218,10 +218,5 @@ subsys_initcall(pnp_init);int pnp_debug;#if defined(CONFIG_PNP_DEBUG_MESSAGES ) -static int __init pnp_debug_setup (char *__unused) -{ - pnp_debug =1 ; -return 1 ; -} -__setup ("pnp.debug" , pnp_debug_setup); +module_param_named (debug, pnp_debug, int,0644 );#endif
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 3/33 thermal: make ops constant
In reply to Len BrownFrom: Alan Cox <[email protected]>
And while touching that function definition do something about the disaster of formatting there.
--- drivers/thermal/thermal_sys.c | 17 +++++------------ include/linux/thermal.h | 15 +++++---------- 2 files changed, 10 insertions(+), 22 deletions(-)
drivers/thermal/thermal_sys.c +5 -12
@@ -823,11 +823,8 @@ static struct class thermal_class = {* @devdata: device private data. * @ops: standard thermal cooling devices callbacks. */ -struct thermal_cooling_device *thermal_cooling_device_register (char *type, -void *devdata, -struct -thermal_cooling_device_ops - *ops) +struct thermal_cooling_device *thermal_cooling_device_register ( +char *type,void *devdata,const struct thermal_cooling_device_ops *ops) {struct thermal_cooling_device *cdev;struct thermal_zone_device *pos;
@@ -1048,13 +1045,9 @@ EXPORT_SYMBOL(thermal_zone_device_update);* section 11.1.5.1 of the ACPI specification 3.0. */ struct thermal_zone_device *thermal_zone_device_register (char *type, -int trips, -void *devdata,struct -thermal_zone_device_ops - *ops,int tc1,int - tc2, -int passive_delay, -int polling_delay) +int trips,void *devdata, +const struct thermal_zone_device_ops *ops, +int tc1,int tc2,int passive_delay,int polling_delay) {struct thermal_zone_device *tz;struct thermal_cooling_device *pos;
include/linux/thermal.h +5 -10
@@ -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__ */
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 4/33 ACPI / PM: Prevent acpi_power_get_inferred_state() from making changes
In reply to Len BrownFrom: Rafael J. Wysocki <[email protected]>
acpi_power_get_inferred_state() should not update device->power.state behind the back of its caller, so make it return the state via a pointer instead.
--- drivers/acpi/bus.c | 3 ++- drivers/acpi/internal.h | 2 +- drivers/acpi/power.c | 12 ++++-------- 3 files changed, 7 insertions(+), 10 deletions(-)
drivers/acpi/bus.c +2 -1
@@ -222,7 +222,8 @@ int acpi_bus_get_power(acpi_handle handle, int *state)* indirectly (via power resources). */ if (device->power.flags.power_resources) { - result =acpi_power_get_inferred_state (device); + result =acpi_power_get_inferred_state (device, + &device->power.state);if (result)return result; }else if (device->power.flags.explicit_get) {
drivers/acpi/internal.h +1 -1
@@ -41,7 +41,7 @@ static inline int acpi_debugfs_init(void) { return 0; }int acpi_power_init (void );int acpi_device_sleep_wake (struct acpi_device *dev,int enable,int sleep_state,int dev_state); -int acpi_power_get_inferred_state (struct acpi_device *device); +int acpi_power_get_inferred_state (struct acpi_device *device,int *state);int acpi_power_transition (struct acpi_device *device,int state);extern int acpi_power_nocheck;
drivers/acpi/power.c +4 -8
@@ -423,19 +423,16 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)Device Power Management -------------------------------------------------------------------------- */ -int acpi_power_get_inferred_state (struct acpi_device *device) +int acpi_power_get_inferred_state (struct acpi_device *device,int *state) {int result =0 ;struct acpi_handle_list *list =NULL ;int list_state =0 ;int i =0 ; - -if (!device) +if (!device || !state)return -EINVAL ; - device->power.state =ACPI_STATE_UNKNOWN ; -/* * We know a device's inferred power state when all the resources * required for a given D-state are 'on'.
@@ -450,13 +447,12 @@ int acpi_power_get_inferred_state(struct acpi_device *device)return result;if (list_state ==ACPI_POWER_RESOURCE_STATE_ON ) { - device->power.state = i; + *state = i;return 0 ; } } - device->power.state =ACPI_STATE_D3 ; - + *state =ACPI_STATE_D3 ;return 0 ; }
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 5/33 ACPI / PM: Add functions for manipulating lists of power resources
In reply to Len BrownFrom: Rafael J. Wysocki <[email protected]>
ACPI device power resources should be reference counted during device initialization, so that their reference counters are always up to date. It is convenient to do that with the help of a function that will reference count and possibly turn on power resources in a given list, so introduce that function, acpi_power_on_list(). For symmetry, introduce acpi_power_off_list() for performing the reverse operation and use the both of them to simplify acpi_power_transition().
--- drivers/acpi/power.c | 67 ++++++++++++++++++++++++++++--------------------- 1 files changed, 38 insertions(+), 29 deletions(-)
drivers/acpi/power.c +38 -29
@@ -266,6 +266,35 @@ static int acpi_power_off_device(acpi_handle handle)return result; } +static void __acpi_power_off_list (struct acpi_handle_list *list,int num_res) +{ +int i; + +for (i = num_res -1 ; i >=0 ; i--) +acpi_power_off_device (list->handles[i]); +} + +static void acpi_power_off_list (struct acpi_handle_list *list) +{ +__acpi_power_off_list (list, list->count); +} + +static int acpi_power_on_list (struct acpi_handle_list *list) +{ +int result =0 ; +int i; + +for (i =0 ; i < list->count; i++) { + result =acpi_power_on (list->handles[i]); +if (result) { +__acpi_power_off_list (list, i); +break ; + } + } + +return result; +} +/** * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in * ACPI 3.0) _PSW (Power State Wake)
@@ -458,10 +487,7 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state)int acpi_power_transition (struct acpi_device *device,int state) { -int result =0 ; -struct acpi_handle_list *cl =NULL ;/* Current Resources */ -struct acpi_handle_list *tl =NULL ;/* Target Resources */ -int i =0 ; +int result;if (!device || (state <ACPI_STATE_D0 ) || (state >ACPI_STATE_D3 ))return -EINVAL ;
@@ -473,37 +499,20 @@ int acpi_power_transition(struct acpi_device *device, int state) || (device->power.state > ACPI_STATE_D3))return -ENODEV ; - cl = &device->power.states[device->power.state].resources; - tl = &device->power.states[state].resources; -/* TBD: Resources must be ordered. */ /* * First we reference all power resources required in the target list -* (e.g. so the device doesn't lose power while transitioning). +* (e.g. so the device doesn't lose power while transitioning). Then, +* we dereference all power resources used in the current list. */ -for (i =0 ; i < tl->count; i++) { - result =acpi_power_on (tl->handles[i]); -if (result) - goto end; - } + result =acpi_power_on_list (&device->power.states[state].resources); +if (!result) +acpi_power_off_list ( + &device->power.states[device->power.state].resources); -/* -* Then we dereference all power resources used in the current list. -*/ -for (i =0 ; i < cl->count; i++) { - result =acpi_power_off_device (cl->handles[i]); -if (result) - goto end; - } - - end: -if (result) - device->power.state =ACPI_STATE_UNKNOWN ; -else { -/* We shouldn't change the state till all above operations succeed */ - device->power.state = state; - } +/* We shouldn't change the state unless the above operations succeed. */ + device->power.state = result ?ACPI_STATE_UNKNOWN : state;return result; }
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 6/33 ACPI / PM: Introduce function for refcounting device power resources
In reply to Len BrownFrom: Rafael J. Wysocki <[email protected]>
Introduce function acpi_power_on_resources() that reference counts and possibly turns on ACPI power resources for a given device and a given power state of it.
This function will be used for reference counting device power resources during initialization.
--- drivers/acpi/internal.h | 1 + drivers/acpi/power.c | 8 ++++++++ 2 files changed, 9 insertions(+), 0 deletions(-)
drivers/acpi/internal.h +1 -0
@@ -42,6 +42,7 @@ int acpi_power_init(void);int acpi_device_sleep_wake (struct acpi_device *dev,int enable,int sleep_state,int dev_state);int acpi_power_get_inferred_state (struct acpi_device *device,int *state); +int acpi_power_on_resources (struct acpi_device *device,int state);int acpi_power_transition (struct acpi_device *device,int state);extern int acpi_power_nocheck;
drivers/acpi/power.c +8 -0
@@ -485,6 +485,14 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state)return 0 ; } +int acpi_power_on_resources (struct acpi_device *device,int state) +{ +if (!device || state <ACPI_STATE_D0 || state >ACPI_STATE_D3 ) +return -EINVAL ; + +return acpi_power_on_list (&device->power.states[state].resources); +} +int acpi_power_transition (struct acpi_device *device,int state) {int result;
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 7/33 ACPI / PM: Introduce __acpi_bus_get_power()
In reply to Len BrownFrom: Rafael J. Wysocki <[email protected]>
It sometimes is necessary to get the power state of an ACPI device without updating its device->power.state field, for example to avoid inconsistencies between device->power.state and the reference counters of the device's power resources. For this purpose introduce __acpi_bus_get_power() that will return the given device's power state via a pointer (instead of modifying device->power.state) and make acpi_bus_get_power() use it.
--- drivers/acpi/bus.c | 48 +++++++++++++++++++++++++++++------------------- 1 files changed, 29 insertions(+), 19 deletions(-)
drivers/acpi/bus.c +29 -19
@@ -196,34 +196,24 @@ EXPORT_SYMBOL(acpi_bus_get_private_data);Power Management -------------------------------------------------------------------------- */ -int acpi_bus_get_power (acpi_handle handle,int *state) +static int __acpi_bus_get_power (struct acpi_device *device,int *state) {int result =0 ;acpi_status status =0 ; -struct acpi_device *device =NULL ;unsigned long long psc =0 ; - - result =acpi_bus_get_device (handle, &device); -if (result) -return result; +if (!device || !state) +return -EINVAL ; *state =ACPI_STATE_UNKNOWN ; -if (!device->flags.power_manageable) { -/* TBD: Non-recursive algorithm for walking up hierarchy */ -if (device->parent) - *state = device->parent->power.state; -else - *state =ACPI_STATE_D0 ; - }else { +if (device->flags.power_manageable) {/* * Get the device's power state either directly (via _PSC) or * indirectly (via power resources). */ if (device->power.flags.power_resources) { - result =acpi_power_get_inferred_state (device, - &device->power.state); + result =acpi_power_get_inferred_state (device, state);if (result)return result; }else if (device->power.flags.explicit_get) {
@@ -231,20 +221,40 @@ int acpi_bus_get_power(acpi_handle handle, int *state) NULL, &psc);if (ACPI_FAILURE (status))return -ENODEV ; - device->power.state = (int )psc; + *state = (int )psc; } - - *state = device->power.state; + }else { +/* TBD: Non-recursive algorithm for walking up hierarchy. */ + *state = device->parent ? + device->parent->power.state :ACPI_STATE_D0 ; }ACPI_DEBUG_PRINT ((ACPI_DB_INFO ,"Device [%s] power state is D%d\n" , - device->pnp.bus_id, device->power.state)); + device->pnp.bus_id, *state));return 0 ; } + +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); +int acpi_bus_set_power (acpi_handle handle,int state) {int result =0 ;
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 8/33 ACPI / PM: Add function for device power state initialization
In reply to Len BrownFrom: Rafael J. Wysocki <[email protected]>
Add function acpi_bus_init_power() for getting the initial power state of an ACPI device and reference counting its power resources as appropriate.
Make acpi_bus_get_power_flags() use the new function instead of acpi_bus_get_power() that updates device->power.state without reference counting the device's power resources.
--- drivers/acpi/bus.c | 25 +++++++++++++++++++++++++ drivers/acpi/internal.h | 1 + drivers/acpi/scan.c | 5 +---- 3 files changed, 27 insertions(+), 4 deletions(-)
drivers/acpi/bus.c +25 -0
@@ -364,6 +364,31 @@ int acpi_bus_set_power(acpi_handle handle, int state)EXPORT_SYMBOL (acpi_bus_set_power); + +int acpi_bus_init_power (struct acpi_device *device) +{ +int state; +int result; + +if (!device) +return -EINVAL ; + + device->power.state =ACPI_STATE_UNKNOWN ; + + result =__acpi_bus_get_power (device, &state); +if (result) +return result; + +if (device->power.flags.power_resources) + result =acpi_power_on_resources (device, state); + +if (!result) + device->power.state = state; + +return result; +} + +bool acpi_bus_power_manageable (acpi_handle handle) {struct acpi_device *device;
drivers/acpi/internal.h +1 -0
@@ -44,6 +44,7 @@ int acpi_device_sleep_wake(struct acpi_device *dev,int acpi_power_get_inferred_state (struct acpi_device *device,int *state);int acpi_power_on_resources (struct acpi_device *device,int state);int acpi_power_transition (struct acpi_device *device,int state); +int acpi_bus_init_power (struct acpi_device *device);extern int acpi_power_nocheck;int acpi_wakeup_device_init (void );
drivers/acpi/scan.c +1 -4
@@ -881,10 +881,7 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) device->power.states[ACPI_STATE_D3 ].flags.valid =1 ; device->power.states[ACPI_STATE_D3 ].power =0 ; -/* TBD: System wake support and resource requirements. */ - - device->power.state =ACPI_STATE_UNKNOWN ; -acpi_bus_get_power (device->handle, &(device->power.state)); +acpi_bus_init_power (device);return 0 ; }
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 9/33 ACPI / PM: Add function for updating device power state consistently
In reply to Len BrownFrom: Rafael J. Wysocki <[email protected]>
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).
--- drivers/acpi/bus.c | 90 ++++++++++++++++++++++++++++++++--------------- include/acpi/acpi_bus.h | 1 + 2 files changed, 62 insertions(+), 29 deletions(-)
drivers/acpi/bus.c +61 -29
@@ -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;
include/acpi/acpi_bus.h +1 -0
@@ -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
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 10/33 ACPI / PM: Register acpi_power_driver early
In reply to Len BrownFrom: Rafael J. Wysocki <[email protected]>
The ACPI device driver used for handling power resources, acpi_power_driver, creates a struct acpi_power_resource object for each ACPI device representing a power resource. These objects are then used when setting and reading the power states of devices using the corresponding power resources. Unfortunately, acpi_power_driver is registered after acpi_scan_init() that may add devices using the power resources before acpi_power_driver has a chance to create struct acpi_power_resource objects for them (specifically, the power resources may be referred to during the scanning process through acpi_bus_get_power() before they have been initialized).
As the first step towards fixing this issue, move the registration of acpi_power_driver into acpi_scan_init() so that power resource devices can be initialized by it as soon as they have been found in the namespace.
--- drivers/acpi/bus.c | 1 - drivers/acpi/scan.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletions(-)
drivers/acpi/bus.c +0 -1
@@ -1099,7 +1099,6 @@ static int __init acpi_init(void)acpi_scan_init ();acpi_ec_init (); -acpi_power_init ();acpi_debugfs_init ();acpi_sleep_proc_init ();acpi_wakeup_device_init ();
drivers/acpi/scan.c +2 -0
@@ -1547,6 +1547,8 @@ int __init acpi_scan_init(void) printk(KERN_ERR PREFIX "Could not register bus type\n"); } +acpi_power_init (); +/* * Enumerate devices in the ACPI namespace. */
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 11/33 ACPI / PM: Register power resource devices as soon as they are needed
In reply to Len BrownFrom: Rafael J. Wysocki <[email protected]>
Depending on the organization of the ACPI namespace, power resource device objects may generally be scanned after the "regular" device objects that they are referred from through _PRn. This, in turn, may cause acpi_bus_get_power_flags() to attempt to access them through acpi_bus_init_power() before they are registered (and initialized by acpi_power_driver). [This is not a theoretical issue, it actually happens for one PnP device on my testbed HP nx6325.]
To fix this problem, make acpi_bus_get_power_flags() attempt to register power resource devices as soon as they have been found in the _PRn output for any other devices.
--- drivers/acpi/scan.c | 20 ++++++++++++++++++++ 1 files changed, 20 insertions(+), 0 deletions(-)
drivers/acpi/scan.c +20 -0
@@ -827,6 +827,8 @@ end:return 0 ; } +static void acpi_bus_add_power_resource (acpi_handle handle); +static int acpi_bus_get_power_flags (struct acpi_device *device) {acpi_status status =0 ;
@@ -855,8 +857,12 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)acpi_evaluate_reference (device->handle, object_name,NULL , &ps->resources);if (ps->resources.count) { +int j; + device->power.flags.power_resources =1 ; ps->flags.valid =1 ; +for (j =0 ; j < ps->resources.count; j++) +acpi_bus_add_power_resource (ps->resources.handles[j]); }/* Evaluate "_PSx" to see if we can do explicit sets */
@@ -1303,6 +1309,20 @@ end:#define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \ ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING) +static void acpi_bus_add_power_resource (acpi_handle handle) +{ +struct acpi_bus_ops ops = { + .acpi_op_add =1 , + .acpi_op_start =1 , + }; +struct acpi_device *device =NULL ; + +acpi_bus_get_device (handle, &device); +if (!device) +acpi_add_single_object (&device, handle,ACPI_BUS_TYPE_POWER , +ACPI_STA_DEFAULT , &ops); +} +static int acpi_bus_type_and_status (acpi_handle handle,int *type,unsigned long long *sta) {
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 12/33 ACPI / Fan: Rework the handling of power resources
In reply to Len BrownFrom: Rafael J. Wysocki <[email protected]>
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.
--- 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(-)
drivers/acpi/bus.c +1 -1
@@ -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 ;
drivers/acpi/fan.c +7 -20
@@ -86,7 +86,7 @@ static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned longif (!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; }
drivers/acpi/thermal.c +3 -2
@@ -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 ;
include/acpi/acpi_bus.h +1 -2
@@ -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 */
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 13/33 thermal: Add event notification to thermal framework
In reply to Len BrownFrom: R.Durgadoss <[email protected]>
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.
--- Documentation/ABI/stable/thermal-notification | 4 + Documentation/thermal/sysfs-api.txt | 12 +++ drivers/thermal/thermal_sys.c | 103 ++++++++++++++++++++++++- include/linux/thermal.h | 32 ++++++++ 4 files changed, 150 insertions(+), 1 deletions(-) create mode 100644 Documentation/ABI/stable/thermal-notification
Documentation/ABI/stable/thermal-notification new file +4 -0
@@ -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.
Documentation/thermal/sysfs-api.txt +12 -0
@@ -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.
drivers/thermal/thermal_sys.c +102 -1
136 lines not on this page · raw message
include/linux/thermal.h +32 -0
@@ -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__ */
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 14/33 Platform / x86: Make fujitsu_laptop use acpi_bus_update_power()
In reply to Len BrownFrom: Rafael J. Wysocki <[email protected]>
Use the new function acpi_bus_update_power(), which is safer than acpi_bus_get_power(), for getting device power state in acpi_fujitsu_add() and acpi_fujitsu_hotkey_add().
--- drivers/platform/x86/fujitsu-laptop.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/platform/x86/fujitsu-laptop.c +2 -2
@@ -689,7 +689,7 @@ static int acpi_fujitsu_add(struct acpi_device *device)if (error) goto err_free_input_dev; - result =acpi_bus_get_power (fujitsu->acpi_handle, &state); + result =acpi_bus_update_power (fujitsu->acpi_handle, &state);if (result) {printk (KERN_ERR "Error reading power state\n" ); goto err_unregister_input_dev;
@@ -857,7 +857,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)if (error) goto err_free_input_dev; - result =acpi_bus_get_power (fujitsu_hotkey->acpi_handle, &state); + result =acpi_bus_update_power (fujitsu_hotkey->acpi_handle, &state);if (result) {printk (KERN_ERR "Error reading power state\n" ); goto err_unregister_input_dev;
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 15/33 ACPI / PM: Drop acpi_bus_get_power()
In reply to Len BrownFrom: Rafael J. Wysocki <[email protected]>
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.
--- drivers/acpi/bus.c | 19 ------------------- include/acpi/acpi_bus.h | 1 - 2 files changed, 0 insertions(+), 20 deletions(-)
drivers/acpi/bus.c +0 -19
@@ -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 ;
include/acpi/acpi_bus.h +0 -1
@@ -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);
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 16/33 ACPI / PM: Drop acpi_power_nocheck
In reply to Len BrownFrom: Rafael J. Wysocki <[email protected]>
Since acpi_bus_set_power() should not use __acpi_bus_get_power() to update the device's device->power.state field before changing its power state (this may cause device->power.state to be inconsistent with the device power resources' reference counters), remove this call from it. In consequence, the acpi_power_nocheck variable is not necessary any more, so it can be dropped along with the DMI table used for setting that variable for HP Pavilion 05.
--- drivers/acpi/bus.c | 39 --------------------------------------- drivers/acpi/internal.h | 1 - drivers/acpi/power.c | 3 --- 3 files changed, 0 insertions(+), 43 deletions(-)
drivers/acpi/bus.c +0 -39
@@ -52,22 +52,6 @@ EXPORT_SYMBOL(acpi_root_dir);#define STRUCT_TO_INT (s) (*((int*)&s)) -static int set_power_nocheck (const struct dmi_system_id *id) -{ - printk(KERN_NOTICE PREFIX "%s detected - " - "disable power check in power transition\n", id->ident); - acpi_power_nocheck =1 ; -return 0 ; -} -static struct dmi_system_id __cpuinitdata power_nocheck_dmi_table[] = { - { - set_power_nocheck,"HP Pavilion 05" , { -DMI_MATCH (DMI_BIOS_VENDOR ,"Phoenix Technologies LTD" ), -DMI_MATCH (DMI_SYS_VENDOR ,"HP Pavilion 05" ), -DMI_MATCH (DMI_PRODUCT_VERSION ,"2001211RE101GLEND" ) },NULL }, - {}, -}; -#ifdef CONFIG_X86 static int set_copy_dsdt (const struct dmi_system_id *id)
@@ -333,23 +317,6 @@ int acpi_bus_set_power(acpi_handle handle, int state)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);
@@ -1072,12 +1039,6 @@ static int __init acpi_init(void)if (acpi_disabled)return result; -/* -* If the laptop falls into the DMI check table, the power state check -* will be disabled in the course of device power transition. -*/ -dmi_check_system (power_nocheck_dmi_table); -acpi_scan_init ();acpi_ec_init ();acpi_debugfs_init ();
drivers/acpi/internal.h +0 -1
@@ -45,7 +45,6 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state);int acpi_power_on_resources (struct acpi_device *device,int state);int acpi_power_transition (struct acpi_device *device,int state);int acpi_bus_init_power (struct acpi_device *device); -extern int acpi_power_nocheck;int acpi_wakeup_device_init (void );void acpi_early_processor_set_pdc (void );
drivers/acpi/power.c +0 -3
@@ -56,9 +56,6 @@ ACPI_MODULE_NAME("power");#define ACPI_POWER_RESOURCE_STATE_ON 0x01#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF -int acpi_power_nocheck; -module_param_named (power_nocheck, acpi_power_nocheck, bool,000 ); -static int acpi_power_add (struct acpi_device *device);static int acpi_power_remove (struct acpi_device *device,int type);static int acpi_power_resume (struct acpi_device *device);
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 17/33 ACPICA: Move GPE functions to new file evxfgpe.c
In reply to Len BrownFrom: Lin Ming <[email protected]>
Create a new file evxfgpe.c and move GPE specific functions to it.
--- drivers/acpi/acpica/Makefile | 2 +- drivers/acpi/acpica/acevents.h | 4 + drivers/acpi/acpica/evgpeutil.c | 39 +++ drivers/acpi/acpica/evxfevnt.c | 600 -------------------------------------- drivers/acpi/acpica/evxfgpe.c | 610 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 654 insertions(+), 601 deletions(-) create mode 100644 drivers/acpi/acpica/evxfgpe.c
drivers/acpi/acpica/Makefile +1 -1
@@ -14,7 +14,7 @@ acpi-y := dsfield.o dsmthdat.o dsopcode.o dswexec.o dswscope.o \ acpi-y += evevent.o evregion.o evsci.o evxfevnt.o \ evmisc.o evrgnini.o evxface.o evxfregn.o \ - evgpe.o evgpeblk.o evgpeinit.o evgpeutil.o + evgpe.o evgpeblk.o evgpeinit.o evgpeutil.o evxfgpe.o acpi-y += exconfig.o exfield.o exnames.o exoparg6.o exresolv.o exstorob.o\ exconvrt.o exfldio.o exoparg1.o exprep.o exresop.o exsystem.o\
drivers/acpi/acpica/acevents.h +4 -0
@@ -138,6 +138,10 @@ acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback, void *context);u8 acpi_ev_valid_gpe_event (struct acpi_gpe_event_info *gpe_event_info); +acpi_status +acpi_ev_get_gpe_device (struct acpi_gpe_xrupt_info *gpe_xrupt_info, +struct acpi_gpe_block_info *gpe_block,void *context); +struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block (u32 interrupt_number);acpi_status acpi_ev_delete_gpe_xrupt (struct acpi_gpe_xrupt_info *gpe_xrupt);
drivers/acpi/acpica/evgpeutil.c +39 -0
@@ -154,6 +154,45 @@ u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info)/******************************************************************************* * +* FUNCTION: acpi_ev_get_gpe_device +* +* PARAMETERS: GPE_WALK_CALLBACK +* +* RETURN: Status +* +* DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE +* block device. NULL if the GPE is one of the FADT-defined GPEs. +* +******************************************************************************/ + +acpi_status +acpi_ev_get_gpe_device (struct acpi_gpe_xrupt_info *gpe_xrupt_info, +struct acpi_gpe_block_info *gpe_block,void *context) +{ +struct acpi_gpe_device_info *info = context; + +/* Increment Index by the number of GPEs in this block */ + + info->next_block_base_index += gpe_block->gpe_count; + +if (info->index < info->next_block_base_index) { +/* +* The GPE index is within this block, get the node. Leave the node +* NULL for the FADT-defined GPEs +*/ +if ((gpe_block->node)->type ==ACPI_TYPE_DEVICE ) { + info->gpe_device = gpe_block->node; + } + + info->status =AE_OK ; +return (AE_CTRL_END ); + } + +return (AE_OK ); +} + +/******************************************************************************* +* * FUNCTION: acpi_ev_get_gpe_xrupt_block * * PARAMETERS: interrupt_number - Interrupt for a GPE block
drivers/acpi/acpica/evxfevnt.c +0 -600
626 lines not on this page · raw message
drivers/acpi/acpica/evxfgpe.c new file +610 -0
610 lines not on this page · raw message
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 18/33 ACPICA: Rename some function and variable names
In reply to Len BrownFrom: Lin Ming <[email protected]>
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
...
--- 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(-)
drivers/acpi/acpica/acevents.h +3 -3
@@ -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);
drivers/acpi/acpica/acglobal.h +1 -1
@@ -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;/***************************************************************************** *
drivers/acpi/acpica/aclocal.h +4 -4
@@ -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 */
drivers/acpi/acpica/evgpe.c +9 -5
@@ -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; }
drivers/acpi/acpica/evgpeblk.c +2 -2
@@ -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",
drivers/acpi/acpica/evxface.c +8 -8
@@ -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 */
drivers/acpi/acpica/evxfgpe.c +33 -20
173 lines not on this page · raw message
drivers/acpi/acpica/hwgpe.c +1 -1
@@ -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 );
drivers/acpi/acpica/utglobal.c +1 -1
@@ -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 */
drivers/acpi/dock.c +1 -1
@@ -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))
drivers/acpi/scan.c +3 -3
@@ -750,7 +750,7 @@ acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device, device->wakeup.resources.handles[i] = element->reference.handle; } -acpi_gpe_can_wake (device->wakeup.gpe_device, device->wakeup.gpe_number); +acpi_setup_gpe_for_wake (device->wakeup.gpe_device, device->wakeup.gpe_number);return AE_OK ; }
@@ -1444,7 +1444,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; }
@@ -1561,7 +1561,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; }
drivers/acpi/wakeup.c +2 -2
@@ -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)
include/acpi/acpixf.h +3 -3
@@ -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
include/acpi/actypes.h +2 -2
@@ -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
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 19/33 ACPICA: New GPE handler callback definition
In reply to Len BrownFrom: Lin Ming <[email protected]>
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);
--- 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(-)
drivers/acpi/acpica/acevents.h +2 -1
@@ -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);/*
drivers/acpi/acpica/aclocal.h +3 -3
@@ -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 */ };/*
drivers/acpi/acpica/evgpe.c +10 -4
@@ -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);
drivers/acpi/acpica/evxface.c +5 -5
@@ -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;
drivers/acpi/ec.c +2 -1
@@ -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;
drivers/char/ipmi/ipmi_si_intf.c +2 -1
@@ -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;
include/acpi/acpixf.h +2 -2
@@ -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);
include/acpi/actypes.h +3 -0
@@ -897,6 +897,9 @@ typedef voidtypedef 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); typedef
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 20/33 ACPICA: Remove unused function declarations
In reply to Len BrownFrom: Lin Ming <[email protected]>
--- drivers/acpi/acpica/acevents.h | 6 ------ 1 files changed, 0 insertions(+), 6 deletions(-)
drivers/acpi/acpica/acevents.h +0 -6
@@ -51,8 +51,6 @@ acpi_status acpi_ev_initialize_events(void);acpi_status acpi_ev_install_xrupt_handlers (void ); -acpi_status acpi_ev_install_fadt_gpes (void ); -u32 acpi_ev_fixed_event_detect (void );/*
@@ -127,10 +125,6 @@ acpi_status acpi_ev_match_gpe_method(acpi_handle obj_handle, u32 level, void *context, void **return_value); -acpi_status -acpi_ev_match_prw_and_gpe (acpi_handle obj_handle, -u32 level,void *context,void **return_value); -/* * evgpeutil - GPE utilities */
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 21/33 ACPICA: Fix local variable mess in acpi_ev_asynch_execute_gpe_method
In reply to Len BrownFrom: Lin Ming <[email protected]>
Change the local variable in acpi_ev_asynch_execute_gpe_method() back into a pointer as ACPICA code base does.
--- drivers/acpi/acpica/evgpe.c | 57 ++++++++++++++++++++++++++++++++++--------- 1 files changed, 45 insertions(+), 12 deletions(-)
drivers/acpi/acpica/evgpe.c +45 -12
@@ -52,6 +52,8 @@ ACPI_MODULE_NAME("evgpe")/* Local prototypes */ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context); +static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context); +/******************************************************************************* * * FUNCTION: acpi_ev_update_gpe_enable_mask
@@ -441,17 +443,25 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)* an interrupt handler. * ******************************************************************************/ -static void acpi_ev_asynch_enable_gpe (void *context); static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) { -struct acpi_gpe_event_info *gpe_event_info = (void *)context; +struct acpi_gpe_event_info *gpe_event_info = context;acpi_status status; -struct acpi_gpe_event_info local_gpe_event_info; +struct acpi_gpe_event_info *local_gpe_event_info;struct acpi_evaluate_info *info;ACPI_FUNCTION_TRACE (ev_asynch_execute_gpe_method); +/* Allocate a local GPE block */ + + local_gpe_event_info = +ACPI_ALLOCATE_ZEROED (sizeof (struct acpi_gpe_event_info )); +if (!local_gpe_event_info) { +ACPI_EXCEPTION ((AE_INFO ,AE_NO_MEMORY ,"while handling a GPE" )); + return_VOID; + } + status =acpi_ut_acquire_mutex (ACPI_MTX_EVENTS );if (ACPI_FAILURE (status)) { return_VOID;
@@ -468,7 +478,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)* Take a snapshot of the GPE info for this level - we copy the info to * prevent a race condition with remove_handler/remove_block. */ -ACPI_MEMCPY (&local_gpe_event_info, gpe_event_info, +ACPI_MEMCPY (local_gpe_event_info, gpe_event_info,sizeof (struct acpi_gpe_event_info )); status =acpi_ut_release_mutex (ACPI_MTX_EVENTS );
@@ -480,7 +490,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)* 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 ) == +if ((local_gpe_event_info->flags &ACPI_GPE_DISPATCH_MASK ) ==ACPI_GPE_DISPATCH_METHOD ) {/* Allocate the evaluation information block */
@@ -494,7 +504,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)* control method that corresponds to this GPE */ info->prefix_node = - local_gpe_event_info.dispatch.method_node; + local_gpe_event_info->dispatch.method_node; info->flags =ACPI_IGNORE_RETURN_VALUE ; status =acpi_ns_evaluate (info);
@@ -505,20 +515,41 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)ACPI_EXCEPTION ((AE_INFO , status,"while evaluating GPE method [%4.4s]" ,acpi_ut_get_node_name - (local_gpe_event_info.dispatch. + (local_gpe_event_info->dispatch. method_node))); } } +/* Defer enabling of GPE until all notify handlers are done */ -acpi_os_execute (OSL_NOTIFY_HANDLER , acpi_ev_asynch_enable_gpe, - gpe_event_info); + + status =acpi_os_execute (OSL_NOTIFY_HANDLER , + acpi_ev_asynch_enable_gpe, + local_gpe_event_info); +if (ACPI_FAILURE (status)) { +ACPI_FREE (local_gpe_event_info); + } return_VOID; } -static void acpi_ev_asynch_enable_gpe (void *context) +/******************************************************************************* +* +* FUNCTION: acpi_ev_asynch_enable_gpe +* +* PARAMETERS: Context (gpe_event_info) - Info for this GPE +* Callback from acpi_os_execute +* +* RETURN: None +* +* DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to +* complete. +* +******************************************************************************/ + +static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context) {struct acpi_gpe_event_info *gpe_event_info = context;acpi_status status; +if ((gpe_event_info->flags &ACPI_GPE_XRUPT_TYPE_MASK ) ==ACPI_GPE_LEVEL_TRIGGERED ) {/*
@@ -527,7 +558,7 @@ static void acpi_ev_asynch_enable_gpe(void *context)*/ status =acpi_hw_clear_gpe (gpe_event_info);if (ACPI_FAILURE (status)) { - return_VOID; + goto exit; } }
@@ -537,7 +568,9 @@ static void acpi_ev_asynch_enable_gpe(void *context)*/ (void )acpi_hw_low_set_gpe (gpe_event_info,ACPI_GPE_CONDITIONAL_ENABLE ); - return_VOID; +exit: +ACPI_FREE (gpe_event_info); +return ; }/*******************************************************************************
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 22/33 ACPICA: Implicit notify support
In reply to Len BrownFrom: Lin Ming <[email protected]>
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.
--- 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/scan.c | 3 +- include/acpi/acpixf.h | 6 +- include/acpi/actypes.h | 39 +++++---- 9 files changed, 187 insertions(+), 106 deletions(-)
drivers/acpi/acpica/acevents.h +2 -0
@@ -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 */
drivers/acpi/acpica/aclocal.h +1 -0
@@ -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 */ };/*
drivers/acpi/acpica/evgpe.c +100 -72
251 lines not on this page · raw message
drivers/acpi/acpica/evgpeblk.c +8 -3
@@ -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 ; }
drivers/acpi/acpica/evgpeinit.c +1 -0
@@ -412,6 +412,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;
drivers/acpi/acpica/evxfgpe.c +47 -11
86 lines not on this page · raw message
drivers/acpi/scan.c +2 -1
@@ -750,7 +750,8 @@ acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device, device->wakeup.resources.handles[i] = element->reference.handle; } -acpi_setup_gpe_for_wake (device->wakeup.gpe_device, device->wakeup.gpe_number); +acpi_setup_gpe_for_wake (device->wakeup.gpe_device,NULL , + device->wakeup.gpe_number);return AE_OK ; }
include/acpi/acpixf.h +4 -2
@@ -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
include/acpi/actypes.h +21 -16
@@ -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 -* +-------------- <Reserved> +* +-------+-+-+---+ +* | 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 +* +------------ <Reserved> */ -#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 */
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 23/33 ACPICA: Global event handler
In reply to Len BrownFrom: Lin Ming <[email protected]>
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.
--- 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(-)
drivers/acpi/acpica/acglobal.h +5 -0
@@ -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;/***************************************************************************** *
drivers/acpi/acpica/evevent.c +10 -2
@@ -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); } }
drivers/acpi/acpica/evgpe.c +8 -1
@@ -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
drivers/acpi/acpica/evxface.c +51 -0
57 lines not on this page · raw message
drivers/acpi/acpica/utglobal.c +1 -0
@@ -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 */
drivers/acpi/sysfs.c +17 -2
@@ -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 )
include/acpi/acpixf.h +4 -0
@@ -229,6 +229,10 @@ 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);
include/acpi/actypes.h +8 -0
@@ -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
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 24/33 ACPICA: Misc comments to minimize code divergence
In reply to Len BrownFrom: Lin Ming <[email protected]>
Modify/add some comments to minimize ACPICA/linux GPE code divergence.
--- drivers/acpi/acpica/achware.h | 2 +- drivers/acpi/acpica/evgpe.c | 21 +++++++++++++-------- drivers/acpi/acpica/evgpeblk.c | 18 ++++++++---------- drivers/acpi/acpica/evgpeinit.c | 24 ++++++++++++++++++++---- drivers/acpi/acpica/evxfgpe.c | 32 +++++++++++++++++++++----------- drivers/acpi/acpica/hwgpe.c | 30 ++++++++++++++++++------------ 6 files changed, 81 insertions(+), 46 deletions(-)
drivers/acpi/acpica/achware.h +1 -1
@@ -94,7 +94,7 @@ u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info, struct acpi_gpe_register_info *gpe_register_info);acpi_status -acpi_hw_low_set_gpe (struct acpi_gpe_event_info *gpe_event_info,u8 action); +acpi_hw_low_set_gpe (struct acpi_gpe_event_info *gpe_event_info,u32 action); acpi_status acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
drivers/acpi/acpica/evgpe.c +13 -8
@@ -104,7 +104,7 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info)* * RETURN: Status * -* DESCRIPTION: Clear the given GPE from stale events and enable it. +* DESCRIPTION: Clear a GPE of stale events and enable it. * ******************************************************************************/ acpi_status
@@ -142,7 +142,7 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)* * FUNCTION: acpi_ev_add_gpe_reference * -* PARAMETERS: gpe_event_info - GPE to enable +* PARAMETERS: gpe_event_info - Add a reference to this GPE * * RETURN: Status *
@@ -163,6 +163,9 @@ acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info gpe_event_info->runtime_count++;if (gpe_event_info->runtime_count ==1 ) { + +/* Enable on first reference */ + status =acpi_ev_update_gpe_enable_mask (gpe_event_info);if (ACPI_SUCCESS (status)) { status =acpi_ev_enable_gpe (gpe_event_info);
@@ -180,7 +183,7 @@ acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info* * FUNCTION: acpi_ev_remove_gpe_reference * -* PARAMETERS: gpe_event_info - GPE to disable +* PARAMETERS: gpe_event_info - Remove a reference to this GPE * * RETURN: Status *
@@ -201,6 +204,9 @@ acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_i gpe_event_info->runtime_count--;if (!gpe_event_info->runtime_count) { + +/* Disable on last reference */ + status =acpi_ev_update_gpe_enable_mask (gpe_event_info);if (ACPI_SUCCESS (status)) { status = acpi_hw_low_set_gpe(gpe_event_info,
@@ -386,7 +392,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) }ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS , -"Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n" , +"Read GPE Register at GPE%02X: Status=%02X, Enable=%02X\n" , gpe_register_info->base_gpe_number, status_reg, enable_reg));
@@ -660,8 +666,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, 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)); +"Unable to clear GPE%02X" , gpe_number));return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED ); } }
@@ -720,7 +725,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, gpe_event_info);if (ACPI_FAILURE (status)) {ACPI_EXCEPTION ((AE_INFO , status, -"Unable to queue handler for GPE[0x%2X] - event disabled" , +"Unable to queue handler for GPE%2X - event disabled" , gpe_number)); }break ;
@@ -733,7 +738,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,* a GPE to be enabled if it has no handler or method. */ ACPI_ERROR ((AE_INFO , -"No handler or method for GPE[0x%2X], disabling event" , +"No handler or method for GPE%02X, disabling event" , gpe_number));break ;
drivers/acpi/acpica/evgpeblk.c +8 -10
@@ -361,9 +361,9 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, gpe_block->node = gpe_device; gpe_block->gpe_count = (u16)(register_count *ACPI_GPE_REGISTER_WIDTH ); + gpe_block->initialized = FALSE; gpe_block->register_count = register_count; gpe_block->block_base_number = gpe_block_base_number; - gpe_block->initialized = FALSE;ACPI_MEMCPY (&gpe_block->block_address, gpe_block_address,sizeof (struct acpi_generic_address ));
@@ -423,14 +423,12 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,* * FUNCTION: acpi_ev_initialize_gpe_block * -* PARAMETERS: gpe_device - Handle to the parent GPE block -* gpe_block - Gpe Block info +* PARAMETERS: acpi_gpe_callback * * RETURN: Status * -* DESCRIPTION: Initialize and enable a GPE block. First find and run any -* _PRT methods associated with the block, then enable the -* appropriate GPEs. +* DESCRIPTION: Initialize and enable a GPE block. Enable GPEs that have +* associated methods. * Note: Assumes namespace is locked. * ******************************************************************************/
@@ -450,8 +448,8 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,ACPI_FUNCTION_TRACE (ev_initialize_gpe_block);/* -* Ignore a null GPE block (e.g., if no GPE block 1 exists) and -* GPE blocks that have been initialized already. +* Ignore a null GPE block (e.g., if no GPE block 1 exists), and +* any GPE blocks that have been initialized already. */ if (!gpe_block || gpe_block->initialized) {return_ACPI_STATUS (AE_OK );
@@ -459,8 +457,8 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,/* * Enable all GPEs that have a corresponding method and have the -* ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block must -* be enabled via the acpi_enable_gpe() interface. +* ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block +* must be enabled via the acpi_enable_gpe() interface. */ gpe_enabled_count =0 ;
drivers/acpi/acpica/evgpeinit.c +20 -4
@@ -45,11 +45,27 @@#include "accommon.h" #include "acevents.h" #include "acnamesp.h" -#include "acinterp.h" #define _COMPONENT ACPI_EVENTSACPI_MODULE_NAME ("evgpeinit" ) +/* +* Note: History of _PRW support in ACPICA +* +* Originally (2000 - 2010), the GPE initialization code performed a walk of +* the entire namespace to execute the _PRW methods and detect all GPEs +* capable of waking the system. +* +* As of 10/2010, the _PRW method execution has been removed since it is +* actually unnecessary. The host OS must in fact execute all _PRW methods +* in order to identify the device/power-resource dependencies. We now put +* the onus on the host OS to identify the wake GPEs as part of this process +* and to inform ACPICA of these GPEs via the acpi_setup_gpe_for_wake interface. This +* not only reduces the complexity of the ACPICA initialization code, but in +* some cases (on systems with very large namespaces) it should reduce the +* kernel boot time as well. +*/ +/******************************************************************************* * * FUNCTION: acpi_ev_gpe_initialize
@@ -222,7 +238,7 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)acpi_status status =AE_OK ;/* -* 2) Find any _Lxx/_Exx GPE methods that have just been loaded. +* Find any _Lxx/_Exx GPE methods that have just been loaded. * * Any GPEs that correspond to new _Lxx/_Exx methods are immediately * enabled.
@@ -235,9 +251,9 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)return ; } + walk_info.count =0 ; walk_info.owner_id = table_owner_id; walk_info.execute_by_owner_id = TRUE; - walk_info.count =0 ;/* Walk the interrupt level descriptor list */
@@ -298,7 +314,7 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)* xx - is the GPE number [in HEX] * * If walk_info->execute_by_owner_id is TRUE, we only execute examine GPE methods -* with that owner. +* with that owner. * ******************************************************************************/
drivers/acpi/acpica/evxfgpe.c +21 -11
@@ -55,13 +55,19 @@ ACPI_MODULE_NAME("evxfgpe")* * PARAMETERS: None * -* RETURN: None +* RETURN: Status +* +* DESCRIPTION: Complete GPE initialization and enable all GPEs that have +* associated _Lxx or _Exx methods and are not pointed to by any +* device _PRW methods (this indicates that these GPEs are +* generally intended for system or device wakeup. Such GPEs +* have to be enabled directly when the devices whose _PRW +* methods point to them are set up for wakeup signaling.) * -* DESCRIPTION: Enable all GPEs that have associated _Lxx or _Exx methods and -* are not pointed to by any device _PRW methods indicating that -* these GPEs are generally intended for system or device wakeup -* (such GPEs have to be enabled directly when the devices whose -* _PRW methods point to them are set up for wakeup signaling). +* NOTE: Should be called after any GPEs are added to the system. Primarily, +* after the system _PRW methods have been run, but also after a GPE Block +* Device has been added or if any new GPE methods have been added via a +* dynamic table load. * ******************************************************************************/
@@ -252,7 +258,8 @@ ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)* * RETURN: Status * -* DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. +* DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must +* already be marked as a WAKE GPE. * ******************************************************************************/
@@ -268,8 +275,10 @@ acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 ac flags =acpi_os_acquire_lock (acpi_gbl_gpe_lock); -/* Ensure that we have a valid GPE number */ - +/* +* Ensure that we have a valid GPE number and that this GPE is in +* fact a wake GPE +*/ gpe_event_info =acpi_ev_get_gpe_event_info (gpe_device, gpe_number);if (!gpe_event_info) { status =AE_BAD_PARAMETER ;
@@ -366,7 +375,7 @@ ACPI_EXPORT_SYMBOL(acpi_clear_gpe)* * RETURN: Status * -* DESCRIPTION: Get status of an event (general purpose) +* DESCRIPTION: Get the current status of a GPE (signalled/not_signalled) * ******************************************************************************/ acpi_status
@@ -476,7 +485,8 @@ ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes)* * RETURN: Status * -* DESCRIPTION: Create and Install a block of GPE registers +* DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not +* enabled here. * ******************************************************************************/ acpi_status
drivers/acpi/acpica/hwgpe.c +18 -12
@@ -62,10 +62,10 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,* PARAMETERS: gpe_event_info - Info block for the GPE * gpe_register_info - Info block for the GPE register * -* RETURN: Status +* RETURN: Register mask with a one in the GPE bit position * -* DESCRIPTION: Compute GPE enable mask with one bit corresponding to the given -* GPE set. +* DESCRIPTION: Compute the register mask for this GPE. One bit is set in the +* correct position for the input GPE. * ******************************************************************************/
@@ -85,12 +85,12 @@ u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info,* * RETURN: Status * -* DESCRIPTION: Enable or disable a single GPE in its enable register. +* DESCRIPTION: Enable or disable a single GPE in the parent enable register. * ******************************************************************************/ acpi_status -acpi_hw_low_set_gpe (struct acpi_gpe_event_info *gpe_event_info,u8 action) +acpi_hw_low_set_gpe (struct acpi_gpe_event_info *gpe_event_info,u32 action) {struct acpi_gpe_register_info *gpe_register_info;acpi_status status;
@@ -113,14 +113,20 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action)return (status); } -/* Set ot clear just the bit that corresponds to this GPE */ +/* Set or clear just the bit that corresponds to this GPE */ register_bit =acpi_hw_get_gpe_register_bit (gpe_event_info, gpe_register_info);switch (action) {case ACPI_GPE_CONDITIONAL_ENABLE : -if (!(register_bit & gpe_register_info->enable_for_run)) + +/* Only enable if the enable_for_run bit is set */ + +if (!(register_bit & gpe_register_info->enable_for_run)) {return (AE_BAD_PARAMETER ); + } + +/*lint -fallthrough */ case ACPI_GPE_ENABLE :ACPI_SET_BIT (enable_mask, register_bit);
@@ -131,7 +137,7 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action)break ;default : -ACPI_ERROR ((AE_INFO ,"Invalid action\n" )); +ACPI_ERROR ((AE_INFO ,"Invalid GPE Action, %u\n" , action));return (AE_BAD_PARAMETER ); }
@@ -168,13 +174,13 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)return (AE_NOT_EXIST ); } - register_bit =acpi_hw_get_gpe_register_bit (gpe_event_info, - gpe_register_info); -/* * Write a one to the appropriate bit in the status register to * clear this GPE. */ + register_bit = +acpi_hw_get_gpe_register_bit (gpe_event_info, gpe_register_info); + status =acpi_hw_write (register_bit, &gpe_register_info->status_address);
@@ -201,8 +207,8 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,u32 in_byte;u32 register_bit;struct acpi_gpe_register_info *gpe_register_info; -acpi_status status;acpi_event_status local_event_status =0 ; +acpi_status status;ACPI_FUNCTION_ENTRY ();
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 25/33 Add CPER PCIe error section structure and constants definition
In reply to Len BrownFrom: Huang Ying <[email protected]>
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.
--- include/linux/cper.h | 86 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 82 insertions(+), 4 deletions(-)
include/linux/cper.h +82 -4
@@ -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()
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 26/33 ACPI, APEI, Add APEI generic error status printing support
In reply to Len BrownFrom: Huang Ying <[email protected]>
In APEI, Hardware error information reported by firmware to Linux kernel is in the data structure of APEI generic error status (struct acpi_hes_generic_status). While now printk is used by Linux kernel to report hardware error information to user space.
So, this patch adds printing support for the data structure, so that the corresponding hardware error information can be reported to user space via printk.
PCIe AER information printing is not implemented yet. Will refactor the original PCIe AER information printing code to avoid code duplicating.
The output format is as follow:
<error record> :=
APEI generic hardware error status
severity: <integer>, <severity string>
section: <integer>, severity: <integer>, <severity string>
flags: <integer>
<section flags strings>fru_id: <uuid string>fru_text: <string>section_type: <section type string>
<section data>
<severity string>* := recoverable | fatal | corrected | info
<section flags strings># :=
[primary][, containment warning][, reset][, threshold exceeded]\
[, resource not accessible][, latent error]
<section type string> := generic processor error | memory error | \
PCIe error | unknown, <uuid string>
<section data> :=
<generic processor section data> | <memory section data> | \
<pcie section data> | <null>
<generic processor section data> :=
[processor_type: <integer>, <proc type string>]
[processor_isa: <integer>, <proc isa string>]
[error_type: <integer>
<proc error type strings>]
[operation: <integer>, <proc operation string>]
[flags: <integer>
<proc flags strings>]
[level: <integer>]
[version_info: <integer>]
[processor_id: <integer>]
[target_address: <integer>]
[requestor_id: <integer>]
[responder_id: <integer>]
[IP: <integer>]
<proc type string>* := IA32/X64 | IA64
<proc isa string>* := IA32 | IA64 | X64
<processor error type strings># :=
[cache error][, TLB error][, bus error][, micro-architectural error]
<proc operation string>* := unknown or generic | data read | data write | \
instruction execution
<proc flags strings># :=
[restartable][, precise IP][, overflow][, corrected]
<memory section data> :=
[error_status: <integer>]
[physical_address: <integer>]
[physical_address_mask: <integer>]
[node: <integer>]
[card: <integer>]
[module: <integer>]
[bank: <integer>]
[device: <integer>]
[row: <integer>]
[column: <integer>]
[bit_position: <integer>]
[requestor_id: <integer>]
[responder_id: <integer>]
[target_id: <integer>]
[error_type: <integer>, <mem error type string>]
<mem error type string>* :=
unknown | no error | single-bit ECC | multi-bit ECC | \
single-symbol chipkill ECC | multi-symbol chipkill ECC | master abort | \
target abort | parity error | watchdog timeout | invalid address | \
mirror Broken | memory sparing | scrub corrected error | \
scrub uncorrected error
<pcie section data> :=
[port_type: <integer>, <pcie port type string>] [version: <integer>.<integer>]
[command: <integer>, status: <integer>] [device_id: <integer>:<integer>:<integer>.<integer>
slot: <integer>secondary_bus: <integer>vendor_id: <integer>, device_id: <integer>class_code: <integer>]
[serial number: <integer>, <integer>]
[bridge: secondary_status: <integer>, control: <integer>]
<pcie port type string>* := PCIe end point | legacy PCI end point | \
unknown | unknown | root port | upstream switch port | \
downstream switch port | PCIe to PCI/PCI-X bridge | \
PCI/PCI-X to PCIe bridge | root complex integrated endpoint device | \
root complex event collector
Where, [] designate corresponding content is optional
All <field string> description with * has the following format:
field: <integer>, <field string>
Where value of <integer> should be the position of "string" in <field string> description. Otherwise, <field string> will be "unknown".
All <field strings> description with # has the following format:
field: <integer>
<field strings>
Where each string in <fields strings> corresponding to one set bit of <integer>. The bit position is the position of "string" in <field strings> description.
For more detailed explanation of every field, please refer to UEFI specification version 2.3 or later, section Appendix N: Common Platform Error Record.
--- Documentation/acpi/apei/output_format.txt | 122 +++++++++++ drivers/acpi/apei/apei-internal.h | 2 + drivers/acpi/apei/cper.c | 311 +++++++++++++++++++++++++++++ 3 files changed, 435 insertions(+), 0 deletions(-) create mode 100644 Documentation/acpi/apei/output_format.txt
Documentation/acpi/apei/output_format.txt new file +122 -0
@@ -0,0 +1,122 @@ + APEI output format + ~~~~~~~~~~~~~~~~~~ + +APEI uses printk as hardware error reporting interface, the output +format is as follow. + +<error record> := +APEI generic hardware error status +severity: <integer>, <severity string> +section: <integer>, severity: <integer>, <severity string> +flags: <integer> +<section flags strings> +fru_id: <uuid string> +fru_text: <string> +section_type: <section type string> +<section data> + +<severity string>* := recoverable | fatal | corrected | info + +<section flags strings># := +[primary][, containment warning][, reset][, threshold exceeded]\ +[, resource not accessible][, latent error] + +<section type string> := generic processor error | memory error | \ +PCIe error | unknown, <uuid string> + +<section data> := +<generic processor section data> | <memory section data> | \ +<pcie section data> | <null> + +<generic processor section data> := +[processor_type: <integer>, <proc type string>] +[processor_isa: <integer>, <proc isa string>] +[error_type: <integer> +<proc error type strings>] +[operation: <integer>, <proc operation string>] +[flags: <integer> +<proc flags strings>] +[level: <integer>] +[version_info: <integer>] +[processor_id: <integer>] +[target_address: <integer>] +[requestor_id: <integer>] +[responder_id: <integer>] +[IP: <integer>] + +<proc type string>* := IA32/X64 | IA64 + +<proc isa string>* := IA32 | IA64 | X64 + +<processor error type strings># := +[cache error][, TLB error][, bus error][, micro-architectural error] + +<proc operation string>* := unknown or generic | data read | data write | \ +instruction execution + +<proc flags strings># := +[restartable][, precise IP][, overflow][, corrected] + +<memory section data> := +[error_status: <integer>] +[physical_address: <integer>] +[physical_address_mask: <integer>] +[node: <integer>] +[card: <integer>] +[module: <integer>] +[bank: <integer>] +[device: <integer>] +[row: <integer>] +[column: <integer>] +[bit_position: <integer>] +[requestor_id: <integer>] +[responder_id: <integer>] +[target_id: <integer>] +[error_type: <integer>, <mem error type string>] + +<mem error type string>* := +unknown | no error | single-bit ECC | multi-bit ECC | \ +single-symbol chipkill ECC | multi-symbol chipkill ECC | master abort | \ +target abort | parity error | watchdog timeout | invalid address | \ +mirror Broken | memory sparing | scrub corrected error | \ +scrub uncorrected error + +<pcie section data> := +[port_type: <integer>, <pcie port type string>] +[version: <integer>.<integer>] +[command: <integer>, status: <integer>] +[device_id: <integer>:<integer>:<integer>.<integer> +slot: <integer> +secondary_bus: <integer> +vendor_id: <integer>, device_id: <integer> +class_code: <integer>] +[serial number: <integer>, <integer>] +[bridge: secondary_status: <integer>, control: <integer>] + +<pcie port type string>* := PCIe end point | legacy PCI end point | \ +unknown | unknown | root port | upstream switch port | \ +downstream switch port | PCIe to PCI/PCI-X bridge | \ +PCI/PCI-X to PCIe bridge | root complex integrated endpoint device | \ +root complex event collector + +Where, [] designate corresponding content is optional + +All <field string> description with * has the following format: + +field: <integer>, <field string> + +Where value of <integer> should be the position of "string" in <field +string> description. Otherwise, <field string> will be "unknown". + +All <field strings> description with # has the following format: + +field: <integer> +<field strings> + +Where each string in <fields strings> corresponding to one set bit of +<integer>. The bit position is the position of "string" in <field +strings> description. + +For more detailed explanation of every field, please refer to UEFI +specification version 2.3 or later, section Appendix N: Common +Platform Error Record.
drivers/acpi/apei/apei-internal.h +2 -0
@@ -109,6 +109,8 @@ static inline u32 apei_estatus_len(struct acpi_hest_generic_status *estatus) return sizeof(*estatus) + estatus->data_length; } +void apei_estatus_print (const char *pfx, +const struct acpi_hest_generic_status *estatus);int apei_estatus_check_header (const struct acpi_hest_generic_status *estatus);int apei_estatus_check (const struct acpi_hest_generic_status *estatus);#endif
drivers/acpi/apei/cper.c +311 -0
317 lines not on this page · raw message
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 27/33 ACPI, APEI, Report GHES error information via printk
In reply to Len BrownFrom: Huang Ying <[email protected]>
printk is one of the methods to report hardware errors to user space. This patch implements hardware error reporting for GHES via printk.
--- drivers/acpi/apei/ghes.c | 25 +++++++++++++++++++++---- 1 files changed, 21 insertions(+), 4 deletions(-)
drivers/acpi/apei/ghes.c +21 -4
@@ -43,6 +43,7 @@#include <linux/kdebug.h> #include <linux/platform_device.h> #include <linux/mutex.h> +#include <linux/ratelimit.h> #include <acpi/apei.h> #include <acpi/atomicio.h> #include <acpi/hed.h>
@@ -255,11 +256,26 @@ static void ghes_do_proc(struct ghes *ghes) }#endif } +} -if (!processed &&printk_ratelimit ()) -pr_warning (GHES_PFX -"Unknown error record from generic hardware error source: %d\n" , - ghes->generic->header.source_id); +static void ghes_print_estatus (const char *pfx,struct ghes *ghes) +{ +/* Not more than 2 messages every 5 seconds */ + static DEFINE_RATELIMIT_STATE(ratelimit, 5*HZ, 2); + +if (pfx ==NULL ) { +if (ghes_severity (ghes->estatus->error_severity) <= +GHES_SEV_CORRECTED ) + pfx = KERN_WARNING HW_ERR; +else + pfx = KERN_ERR HW_ERR; + } +if (__ratelimit (&ratelimit)) { +printk ( +"%s""Hardware error from APEI Generic Hardware Error Source: %d\n" , + pfx, ghes->generic->header.source_id); +apei_estatus_print (pfx, ghes->estatus); + } }static int ghes_proc (struct ghes *ghes)
@@ -269,6 +285,7 @@ static int ghes_proc(struct ghes *ghes) rc =ghes_read_estatus (ghes,0 );if (rc) goto out; +ghes_print_estatus (NULL , ghes);ghes_do_proc (ghes); out:
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 28/33 IPMI: Add one interface to get more info of low-level IPMI device
In reply to Len BrownFrom: Zhao Yakui <[email protected]>
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.
--- 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(-)
drivers/char/ipmi/ipmi_msghandler.c +27 -0
@@ -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);
drivers/char/ipmi/ipmi_si_intf.c +16 -4
@@ -57,6 +57,7 @@#include <asm/irq.h> #include <linux/interrupt.h> #include <linux/rcupdate.h> +#include <linux/ipmi.h> #include <linux/ipmi_smi.h> #include <asm/io.h> #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);
include/linux/ipmi.h +38 -0
@@ -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__ */
include/linux/ipmi_smi.h +8 -0
@@ -39,6 +39,7 @@#include <linux/module.h> #include <linux/device.h> #include <linux/platform_device.h> +#include <linux/ipmi.h> /* 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
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 29/33 IPMI: Add the document description of ipmi_get_smi_info
In reply to Len BrownFrom: Zhao Yakui <[email protected]>
Add the document description about how to use ipmi_get_smi_info.
--- Documentation/IPMI.txt | 27 +++++++++++++++++++++++++++ 1 files changed, 27 insertions(+), 0 deletions(-)
Documentation/IPMI.txt +27 -0
@@ -533,6 +533,33 @@ completion during sending a panic event. Other Pieces ------------ +Get the detailed info related with the IPMI device +-------------------------------------------------- + +Some users need more detailed information about a device, like where +the address came from or the raw base device for the IPMI interface. +You can use the IPMI smi_watcher to catch the IPMI interfaces as they +come or go, and to grab the information, you can use the function +ipmi_get_smi_info(), which returns the following structure: + +struct ipmi_smi_info { + enum ipmi_addr_src addr_src; + struct device *dev; + union { + struct { + void *acpi_handle; + } acpi_info; + } addr_info; +}; + +Currently special info for only for SI_ACPI address sources is +returned. Others may be added as necessary. + +Note that the dev pointer is included in the above structure, and +assuming ipmi_smi_get_info returns success, you must call put_device +on the dev pointer. + + Watchdog --------
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 30/33 IPMI/ACPI: Add the IPMI opregion driver to enable ACPI to access BMC controller
In reply to Len BrownFrom: Zhao Yakui <[email protected]>
ACPI 4.0 spec adds the ACPI IPMI opregion, which means that the ACPI AML code can also communicate with the BMC controller. This is to install the ACPI IPMI opregion and enable the ACPI to access the BMC controller through the IPMI message.
It will create IPMI user interface for every IPMI device detected
in ACPI namespace and install the corresponding IPMI opregion space handler. Then it can enable ACPI to access the BMC controller through the IPMI message.
The following describes how to process the IPMI request in IPMI space handler:
1. format the IPMI message based on the request in AML code. IPMI system address. Now the address type is SYSTEM_INTERFACE_ADDR_TYPE IPMI net function & command
IPMI message payload
2. send the IPMI message by using the function of ipmi_request_settime
3. wait for the completion of IPMI message. It can be done in different
routes: One is in handled in IPMI user recv callback function. Another is handled in timeout function.
4. format the IPMI response and return it to ACPI AML code.
At the same time it also addes the module dependency. The ACPI IPMI opregion will depend on the IPMI subsystem.
--- drivers/acpi/Kconfig | 11 + drivers/acpi/Makefile | 1 + drivers/acpi/acpi_ipmi.c | 525 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 537 insertions(+), 0 deletions(-) create mode 100644 drivers/acpi/acpi_ipmi.c
drivers/acpi/Kconfig +11 -0
@@ -209,6 +209,17 @@ config ACPI_PROCESSOR To compile this driver as a module, choose M here: the module will be called processor. +config ACPI_IPMI + tristate "IPMI" + depends on EXPERIMENTAL && IPMI_SI && IPMI_HANDLER + default n + help + This driver enables the ACPI to access the BMC controller. And it + uses the IPMI request/response message to communicate with BMC + controller, which can be found on on the server. + + To compile this driver as a module, choose M here: + the module will be called as acpi_ipmi. config ACPI_HOTPLUG_CPU bool
drivers/acpi/Makefile +1 -0
@@ -69,5 +69,6 @@ processor-y += processor_idle.o processor_thermal.o processor-$(CONFIG_CPU_FREQ) += processor_perflib.o obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o +obj-$(CONFIG_ACPI_IPMI) += acpi_ipmi.o obj-$(CONFIG_ACPI_APEI) += apei/
drivers/acpi/acpi_ipmi.c new file +525 -0
525 lines not on this page · raw message
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 31/33 ACPI: use ioremap_cache()
In reply to Len BrownFrom: Len Brown <[email protected]>
Although the temporary boot-time ACPI table mappings were set up with CPU caching enabled, the permanent table mappings and AML run-time region memory accesses were set up with ioremap(), which on x86 is a synonym for ioremap_nocache().
Changing this to ioremap_cache() improves performance as seen when accessing the tables via acpidump,
or /sys/firmware/acpi/tables. It should also improve AML run-time performance.
No change on ia64.
--- arch/ia64/include/asm/io.h | 5 +++++ drivers/acpi/osl.c | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-)
arch/ia64/include/asm/io.h +5 -0
@@ -426,6 +426,11 @@ extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size)extern void iounmap (volatile void __iomem *addr);extern void __iomem *early_ioremap (unsigned long phys_addr,unsigned long size);extern void early_iounmap (volatile void __iomem *addr,unsigned long size); +static inline void __iomem *ioremap_cache (unsigned long phys_addr,unsigned long size) +{ + return ioremap(unsigned long phys_addr, unsigned long size); +} +/* * String version of IO memory access ops:
drivers/acpi/osl.c +3 -3
@@ -324,7 +324,7 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) pg_off =round_down (phys,PAGE_SIZE ); pg_sz =round_up (phys + size,PAGE_SIZE ) - pg_off; - virt =ioremap (pg_off, pg_sz); + virt =ioremap_cache (pg_off, pg_sz);if (!virt) {kfree (map);return NULL ;
@@ -646,7 +646,7 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width) virt_addr =acpi_map_vaddr_lookup (phys_addr, size);rcu_read_unlock ();if (!virt_addr) { - virt_addr =ioremap (phys_addr, size); + virt_addr =ioremap_cache (phys_addr, size); unmap =1 ; }if (!value)
@@ -682,7 +682,7 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width) virt_addr =acpi_map_vaddr_lookup (phys_addr, size);rcu_read_unlock ();if (!virt_addr) { - virt_addr =ioremap (phys_addr, size); + virt_addr =ioremap_cache (phys_addr, size); unmap =1 ; }
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 32/33 ACPI throttling: Use this_cpu_has and simplify code
In reply to Len BrownFrom: Christoph Lameter <[email protected]>
With the this_cpu_xx we no longer need to pass an acpi structure to the msr management code. Simplifies code and improves performance.
--- drivers/acpi/processor_throttling.c | 32 ++++++++++---------------------- 1 files changed, 10 insertions(+), 22 deletions(-)
drivers/acpi/processor_throttling.c +10 -22
@@ -662,20 +662,14 @@ static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr) }#ifdef CONFIG_X86 -static int acpi_throttling_rdmsr (struct acpi_processor *pr, -u64 *value) +static int acpi_throttling_rdmsr (u64 *value) { -struct cpuinfo_x86 *c;u64 msr_high, msr_low; -unsigned int cpu;u64 msr =0 ;int ret =-1 ; - cpu = pr->id; - c = &cpu_data (cpu); - -if ((c->x86_vendor !=X86_VENDOR_INTEL ) || - !cpu_has (c,X86_FEATURE_ACPI )) { +if ((this_cpu_read (cpu_info.x86_vendor) !=X86_VENDOR_INTEL ) || + !this_cpu_has (X86_FEATURE_ACPI )) { printk(KERN_ERR PREFIX "HARDWARE addr space,NOT supported yet\n"); }else {
@@ -690,18 +684,13 @@ static int acpi_throttling_rdmsr(struct acpi_processor *pr,return ret; } -static int acpi_throttling_wrmsr (struct acpi_processor *pr,u64 value) +static int acpi_throttling_wrmsr (u64 value) { -struct cpuinfo_x86 *c; -unsigned int cpu;int ret =-1 ;u64 msr; - cpu = pr->id; - c = &cpu_data (cpu); - -if ((c->x86_vendor !=X86_VENDOR_INTEL ) || - !cpu_has (c,X86_FEATURE_ACPI )) { +if ((this_cpu_read (cpu_info.x86_vendor) !=X86_VENDOR_INTEL ) || + !this_cpu_has (X86_FEATURE_ACPI )) { printk(KERN_ERR PREFIX "HARDWARE addr space,NOT supported yet\n"); }else {
@@ -713,15 +702,14 @@ static int acpi_throttling_wrmsr(struct acpi_processor *pr, u64 value)return ret; }#else -static int acpi_throttling_rdmsr (struct acpi_processor *pr, -u64 *value) +static int acpi_throttling_rdmsr (u64 *value) { printk(KERN_ERR PREFIX "HARDWARE addr space,NOT supported yet\n");return -1 ; } -static int acpi_throttling_wrmsr (struct acpi_processor *pr,u64 value) +static int acpi_throttling_wrmsr (u64 value) { printk(KERN_ERR PREFIX "HARDWARE addr space,NOT supported yet\n");
@@ -753,7 +741,7 @@ static int acpi_read_throttling_status(struct acpi_processor *pr, ret =0 ;break ;case ACPI_ADR_SPACE_FIXED_HARDWARE : - ret =acpi_throttling_rdmsr (pr, value); + ret =acpi_throttling_rdmsr (value);break ;default : printk(KERN_ERR PREFIX "Unknown addr space %d\n",
@@ -786,7 +774,7 @@ static int acpi_write_throttling_state(struct acpi_processor *pr, ret =0 ;break ;case ACPI_ADR_SPACE_FIXED_HARDWARE : - ret =acpi_throttling_wrmsr (pr, value); + ret =acpi_throttling_wrmsr (value);break ;default : printk(KERN_ERR PREFIX "Unknown addr space %d\n",
Signature · 1 line
1.7.3.3.557.gb5c17
Len Brown
reviewerPATCH 33/33 Revert "ACPI throttling: Use this_cpu_has and simplify code"
In reply to Len BrownFrom: Len Brown <[email protected]>
This reverts commit 630c6a2603a844b3771f007224e22db8cc16a038.
b/c the build isn't ready for it yet:
drivers/acpi/processor_throttling.c: In function ‘acpi_throttling_rdmsr’:drivers/acpi/processor_throttling.c:672: error: implicit declaration of function ‘this_cpu_has’
--- drivers/acpi/processor_throttling.c | 32 ++++++++++++++++++++++---------- 1 files changed, 22 insertions(+), 10 deletions(-)
drivers/acpi/processor_throttling.c +22 -10
@@ -662,14 +662,20 @@ static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr) }#ifdef CONFIG_X86 -static int acpi_throttling_rdmsr (u64 *value) +static int acpi_throttling_rdmsr (struct acpi_processor *pr, +u64 *value) { +struct cpuinfo_x86 *c;u64 msr_high, msr_low; +unsigned int cpu;u64 msr =0 ;int ret =-1 ; -if ((this_cpu_read (cpu_info.x86_vendor) !=X86_VENDOR_INTEL ) || - !this_cpu_has (X86_FEATURE_ACPI )) { + cpu = pr->id; + c = &cpu_data (cpu); + +if ((c->x86_vendor !=X86_VENDOR_INTEL ) || + !cpu_has (c,X86_FEATURE_ACPI )) { printk(KERN_ERR PREFIX "HARDWARE addr space,NOT supported yet\n"); }else {
@@ -684,13 +690,18 @@ static int acpi_throttling_rdmsr(u64 *value)return ret; } -static int acpi_throttling_wrmsr (u64 value) +static int acpi_throttling_wrmsr (struct acpi_processor *pr,u64 value) { +struct cpuinfo_x86 *c; +unsigned int cpu;int ret =-1 ;u64 msr; -if ((this_cpu_read (cpu_info.x86_vendor) !=X86_VENDOR_INTEL ) || - !this_cpu_has (X86_FEATURE_ACPI )) { + cpu = pr->id; + c = &cpu_data (cpu); + +if ((c->x86_vendor !=X86_VENDOR_INTEL ) || + !cpu_has (c,X86_FEATURE_ACPI )) { printk(KERN_ERR PREFIX "HARDWARE addr space,NOT supported yet\n"); }else {
@@ -702,14 +713,15 @@ static int acpi_throttling_wrmsr(u64 value)return ret; }#else -static int acpi_throttling_rdmsr (u64 *value) +static int acpi_throttling_rdmsr (struct acpi_processor *pr, +u64 *value) { printk(KERN_ERR PREFIX "HARDWARE addr space,NOT supported yet\n");return -1 ; } -static int acpi_throttling_wrmsr (u64 value) +static int acpi_throttling_wrmsr (struct acpi_processor *pr,u64 value) { printk(KERN_ERR PREFIX "HARDWARE addr space,NOT supported yet\n");
@@ -741,7 +753,7 @@ static int acpi_read_throttling_status(struct acpi_processor *pr, ret =0 ;break ;case ACPI_ADR_SPACE_FIXED_HARDWARE : - ret =acpi_throttling_rdmsr (value); + ret =acpi_throttling_rdmsr (pr, value);break ;default : printk(KERN_ERR PREFIX "Unknown addr space %d\n",
@@ -774,7 +786,7 @@ static int acpi_write_throttling_state(struct acpi_processor *pr, ret =0 ;break ;case ACPI_ADR_SPACE_FIXED_HARDWARE : - ret =acpi_throttling_wrmsr (value); + ret =acpi_throttling_wrmsr (pr, value);break ;default : printk(KERN_ERR PREFIX "Unknown addr space %d\n",
Signature · 6 lines
1.7.3.3.557.gb5c17 -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html