These patches are staged for 2.6.28,
please let me know if you see problems with them.
thanks,
-Len
From: Andi Kleen <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
---
Documentation/kernel-parameters.txt | 47 ++++++++++++++++++++++++----------
1 files changed, 33 insertions(+), 14 deletions(-)
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 1150444..44d1bd1 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -217,20 +217,39 @@ and is between 256 and 4096 characters. It is defined in the file
acpi.debug_level= [HW,ACPI]
Format: <int>
Each bit of the <int> indicates an ACPI debug level,
- 1: enable, 0: disable. It is useful for boot time
- debugging. After system has booted up, it can be set
- via /sys/module/acpi/parameters/debug_level.
- CONFIG_ACPI_DEBUG must be enabled for this to produce any output.
- Available bits (add the numbers together) to enable different
- debug output levels of the ACPI subsystem:
- 0x01 error 0x02 warn 0x04 init 0x08 debug object
- 0x10 info 0x20 init names 0x40 parse 0x80 load
- 0x100 dispatch 0x200 execute 0x400 names 0x800 operation region
- 0x1000 bfield 0x2000 tables 0x4000 values 0x8000 objects
- 0x10000 resources 0x20000 user requests 0x40000 package.
- The number can be in decimal or prefixed with 0x in hex.
- Warning: Many of these options can produce a lot of
- output and make your system unusable. Be very careful.
+ which corresponds to the level in an ACPI_DEBUG_PRINT
+ statement. After system has booted up, this mask
+ can be set via /sys/module/acpi/parameters/debug_level.
+
+ CONFIG_ACPI_DEBUG must be enabled for this to produce
+ any output. The number can be in decimal or prefixed
+ with 0x in hex. Some of these options produce so much
+ output that the system is unusable.
+
+ The following global components are defined by the
+ ACPI CA:
+ 0x01 error
+ 0x02 warn
+ 0x04 init
+ 0x08 debug object
+ 0x10 info
+ 0x20 init names
+ 0x40 parse
+ 0x80 load
+ 0x100 dispatch
+ 0x200 execute
+ 0x400 names
+ 0x800 operation region
+ 0x1000 bfield
+ 0x2000 tables
+ 0x4000 values
+ 0x8000 objects
+ 0x10000 resources
+ 0x20000 user requests
+ 0x40000 package
+ The number can be in decimal or prefixed with 0x in hex.
+ Warning: Many of these options can produce a lot of
+ output and make your system unusable. Be very careful.
acpi_pm_good [X86-32,X86-64]
Override the pmtimer bug detection: force the kernel
--
1.5.5.1
From: Zhao Yakui <[email protected]>
Maybe the incorrect power state is returned on the bogus bios, which
is different with the real power state. For example: the bios returns D0
state and the real power state is D3. OS expects to set the device to D0
state. In such case if OS uses the power state returned by the BIOS and
checks the device power state very strictly in power transition, the device
can't be transited to the correct power state.
So the boot option of "acpi.power_nocheck=1" is added to avoid checking
the device power in the course of device power transition.
http://bugzilla.kernel.org/show_bug.cgi?id=8049
http://bugzilla.kernel.org/show_bug.cgi?id=11000
Signed-off-by: Zhao Yakui <[email protected]>
Signed-off-by: Zhang Rui <[email protected]>
Signed-off-by: Li Shaohua <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
---
Documentation/kernel-parameters.txt | 8 ++++++
drivers/acpi/bus.c | 14 ++++++++++-
drivers/acpi/power.c | 42 +++++++++++++++++++++++++---------
include/acpi/acpi_drivers.h | 1 +
4 files changed, 53 insertions(+), 12 deletions(-)
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 44d1bd1..99cf83f 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -251,6 +251,14 @@ and is between 256 and 4096 characters. It is defined in the file
Warning: Many of these options can produce a lot of
output and make your system unusable. Be very careful.
+ acpi.power_nocheck= [HW,ACPI]
+ Format: 1/0 enable/disable the check of power state.
+ On some bogus BIOS the _PSC object/_STA object of
+ power resource can't return the correct device power
+ state. In such case it is unneccessary to check its
+ power state again in power transition.
+ 1 : disable the power state check
+
acpi_pm_good [X86-32,X86-64]
Override the pmtimer bug detection: force the kernel
to assume that this machine's pmtimer latches its value
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index ccae305..91bdeb3 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -223,7 +223,19 @@ int acpi_bus_set_power(acpi_handle handle, int state)
/*
* Get device's current power state
*/
- acpi_bus_get_power(device->handle, &device->power.state);
+ if (!acpi_power_nocheck) {
+ /*
+ * Maybe the incorrect power state is returned on the bogus
+ * bios, which is different with the real power state.
+ * For example: the bios returns D0 state and the real power
+ * state is D3. OS expects to set the device to D0 state. In
+ * such case if OS uses the power state returned by the BIOS,
+ * the device can't be transisted to the correct power state.
+ * So if the acpi_power_nocheck is set, it is unnecessary to
+ * get the power state by calling acpi_bus_get_power.
+ */
+ acpi_bus_get_power(device->handle, &device->power.state);
+ }
if ((state == device->power.state) && !device->flags.force_power_state) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
state));
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index e7bab75..7ff7349 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -54,6 +54,14 @@ ACPI_MODULE_NAME("power");
#define ACPI_POWER_RESOURCE_STATE_OFF 0x00
#define ACPI_POWER_RESOURCE_STATE_ON 0x01
#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
+
+#ifdef MODULE_PARAM_PREFIX
+#undef MODULE_PARAM_PREFIX
+#endif
+#define MODULE_PARAM_PREFIX "acpi."
+int acpi_power_nocheck;
+module_param_named(power_nocheck, acpi_power_nocheck, bool, 000);
+
static int acpi_power_add(struct acpi_device *device);
static int acpi_power_remove(struct acpi_device *device, int type);
static int acpi_power_resume(struct acpi_device *device);
@@ -228,12 +236,18 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
if (ACPI_FAILURE(status))
return -ENODEV;
- result = acpi_power_get_state(resource->device->handle, &state);
- if (result)
- return result;
- if (state != ACPI_POWER_RESOURCE_STATE_ON)
- return -ENOEXEC;
-
+ if (!acpi_power_nocheck) {
+ /*
+ * If acpi_power_nocheck is set, it is unnecessary to check
+ * the power state after power transition.
+ */
+ result = acpi_power_get_state(resource->device->handle,
+ &state);
+ if (result)
+ return result;
+ if (state != ACPI_POWER_RESOURCE_STATE_ON)
+ return -ENOEXEC;
+ }
/* Update the power resource's _device_ power state */
resource->device->power.state = ACPI_STATE_D0;
@@ -279,11 +293,17 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
if (ACPI_FAILURE(status))
return -ENODEV;
- result = acpi_power_get_state(handle, &state);
- if (result)
- return result;
- if (state != ACPI_POWER_RESOURCE_STATE_OFF)
- return -ENOEXEC;
+ if (!acpi_power_nocheck) {
+ /*
+ * If acpi_power_nocheck is set, it is unnecessary to check
+ * the power state after power transition.
+ */
+ result = acpi_power_get_state(handle, &state);
+ if (result)
+ return result;
+ if (state != ACPI_POWER_RESOURCE_STATE_OFF)
+ return -ENOEXEC;
+ }
/* Update the power resource's _device_ power state */
resource->device->power.state = ACPI_STATE_D3;
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index e5f38e5..efbaa27 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -93,6 +93,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state);
int acpi_disable_wakeup_device_power(struct acpi_device *dev);
int acpi_power_get_inferred_state(struct acpi_device *device);
int acpi_power_transition(struct acpi_device *device, int state);
+extern int acpi_power_nocheck;
#endif
/* --------------------------------------------------------------------------
--
1.5.5.1
From: Bob Moore <[email protected]>
The "minimal" descriptors such as EndTag are calculated as 12
bytes long, but the actual length in the internal descriptor is
16 because of the round-up to 8 on 64-bit build.
http://www.acpica.org/bugzilla/show_bug.cgi?id=728
Signed-off-by: Bob Moore <[email protected]>
Signed-off-by: Lin Ming <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
include/acpi/actypes.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 4ea4f40..73d6b1c 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -1225,8 +1225,8 @@ struct acpi_resource {
#pragma pack()
-#define ACPI_RS_SIZE_MIN 12
#define ACPI_RS_SIZE_NO_DATA 8 /* Id + Length fields */
+#define ACPI_RS_SIZE_MIN (u32) ACPI_ROUND_UP_TO_NATIVE_WORD (12)
#define ACPI_RS_SIZE(type) (u32) (ACPI_RS_SIZE_NO_DATA + sizeof (type))
#define ACPI_NEXT_RESOURCE(res) (struct acpi_resource *)((u8 *) res + res->length)
--
1.5.5.1
From: Lin Ming <[email protected]>
Examines the return object from a call to acpi_evaluate_object.
Any Index or RefOf references are automatically dereferenced in
an attempt to return something useful (these reference types
cannot be converted into an external ACPI_OBJECT.)
Lin Ming, Bob Moore.
http://bugzilla.kernel.org/show_bug.cgi?id=11105
Signed-off-by: Lin Ming <[email protected]>
Signed-off-by: Bob Moore <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/namespace/nsxfeval.c | 79 +++++++++++++++++++++++++++++++++++++
1 files changed, 79 insertions(+), 0 deletions(-)
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
index 38be586..f3cc376 100644
--- a/drivers/acpi/namespace/nsxfeval.c
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -45,9 +45,14 @@
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acinterp.h>
+#include <acpi/amlcode.h>
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsxfeval")
+
+/* Local prototypes */
+static void acpi_ns_resolve_references(struct acpi_evaluate_info *info);
+
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
@@ -69,6 +74,7 @@ ACPI_MODULE_NAME("nsxfeval")
* be valid (non-null)
*
******************************************************************************/
+
acpi_status
acpi_evaluate_object_typed(acpi_handle handle,
acpi_string pathname,
@@ -283,6 +289,10 @@ acpi_evaluate_object(acpi_handle handle,
if (ACPI_SUCCESS(status)) {
+ /* Dereference Index and ref_of references */
+
+ acpi_ns_resolve_references(info);
+
/* Get the size of the returned object */
status =
@@ -352,6 +362,74 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object)
/*******************************************************************************
*
+ * FUNCTION: acpi_ns_resolve_references
+ *
+ * PARAMETERS: Info - Evaluation info block
+ *
+ * RETURN: Info->return_object is replaced with the dereferenced object
+ *
+ * DESCRIPTION: Dereference certain reference objects. Called before an
+ * internal return object is converted to an external union acpi_object.
+ *
+ * Performs an automatic dereference of Index and ref_of reference objects.
+ * These reference objects are not supported by the union acpi_object, so this is a
+ * last resort effort to return something useful. Also, provides compatibility
+ * with other ACPI implementations.
+ *
+ * NOTE: does not handle references within returned package objects or nested
+ * references, but this support could be added later if found to be necessary.
+ *
+ ******************************************************************************/
+static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)
+{
+ union acpi_operand_object *obj_desc = NULL;
+ struct acpi_namespace_node *node;
+
+ /* We are interested in reference objects only */
+
+ if (ACPI_GET_OBJECT_TYPE(info->return_object) !=
+ ACPI_TYPE_LOCAL_REFERENCE) {
+ return;
+ }
+
+ /*
+ * Two types of references are supported - those created by Index and
+ * ref_of operators. A name reference (AML_NAMEPATH_OP) can be converted
+ * to an union acpi_object, so it is not dereferenced here. A ddb_handle
+ * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
+ * an union acpi_object.
+ */
+ switch (info->return_object->reference.opcode) {
+ case AML_INDEX_OP:
+
+ obj_desc = *(info->return_object->reference.where);
+ break;
+
+ case AML_REF_OF_OP:
+
+ node = info->return_object->reference.object;
+ if (node) {
+ obj_desc = node->object;
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ /* Replace the existing reference object */
+
+ if (obj_desc) {
+ acpi_ut_add_reference(obj_desc);
+ acpi_ut_remove_reference(info->return_object);
+ info->return_object = obj_desc;
+ }
+
+ return;
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_walk_namespace
*
* PARAMETERS: Type - acpi_object_type to search for
@@ -379,6 +457,7 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object)
* function, etc.
*
******************************************************************************/
+
acpi_status
acpi_walk_namespace(acpi_object_type type,
acpi_handle start_object,
--
1.5.5.1
From: Bob Moore <[email protected]>
Fixes warning from exconfig.c on 64-bit build.
AK: This actually was fixed earlier in Linux, this just syncs with
AK: the version of the fix that went into the ACPCA codebase
Signed-off-by: Bob Moore <[email protected]>
Signed-off-by: Lin Ming <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/executer/exconfig.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
index 331a114..4c512c2 100644
--- a/drivers/acpi/executer/exconfig.c
+++ b/drivers/acpi/executer/exconfig.c
@@ -96,8 +96,7 @@ acpi_ex_add_table(u32 table_index,
/* Install the new table into the local data structures */
- obj_desc->reference.object = ACPI_CAST_PTR(void,
- (unsigned long)table_index);
+ obj_desc->reference.object = ACPI_TO_POINTER(table_index);
/* Add the table to the namespace */
--
1.5.5.1
From: Bob Moore <[email protected]>
Better error messages during object conversion from internal
to the external ACPI_OBJECT. Used for external calls to
acpi_evaluate_object.
Signed-off-by: Bob Moore <[email protected]>
Signed-off-by: Lin Ming <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/utilities/utobject.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c
index 916eff3..924d05a 100644
--- a/drivers/acpi/utilities/utobject.c
+++ b/drivers/acpi/utilities/utobject.c
@@ -503,7 +503,9 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
* required eventually.
*/
ACPI_ERROR((AE_INFO,
- "Unsupported Reference opcode=%X in object %p",
+ "Cannot convert to external object - "
+ "unsupported Reference type [%s] %X in object %p",
+ acpi_ut_get_reference_name(internal_object),
internal_object->reference.opcode,
internal_object));
status = AE_TYPE;
@@ -513,7 +515,9 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
default:
- ACPI_ERROR((AE_INFO, "Unsupported type=%X in object %p",
+ ACPI_ERROR((AE_INFO, "Cannot convert to external object - "
+ "unsupported type [%s] %X in object %p",
+ acpi_ut_get_object_type_name(internal_object),
ACPI_GET_OBJECT_TYPE(internal_object),
internal_object));
status = AE_TYPE;
--
1.5.5.1
From: Matthew Garrett <[email protected]>
The leading other brand OS appears to clear the WAK_STS flag on resume.
When rebooted, certain BIOSes assume that the system is actually
resuming if it's still set and so fail to reboot correctly. Make sure
that it's cleared at resume time.
Comment clarified as suggested by Bob Moore
Signed-off-by: Matthew Garrett <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/hardware/hwsleep.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index dba3cfb..130a44b 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -627,6 +627,13 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
}
/* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
+ /*
+ * Some BIOSes assume that WAK_STS will be cleared on resume and use
+ * it to determine whether the system is rebooting or resuming. Clear
+ * it for compatibility.
+ */
+ acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1);
+
acpi_gbl_system_awake_and_running = TRUE;
/* Enable power button */
--
1.5.5.1
From: Matthew Garrett <[email protected]>
According to the ACPI-WMI spec, event blocks may provide a function call
for enabling/disabling them. This patch adds support for making these
calls when registering or removing notifications. Without this, my Dell
firmware provides no data in the event notification.
Signed-off-by: Matthew Garrett <[email protected]>
Signed-off-by: Carlos Corbacho <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/wmi.c | 39 +++++++++++++++++++++++++++++++++++++--
1 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/wmi.c b/drivers/acpi/wmi.c
index cfe2c83..5464cfc 100644
--- a/drivers/acpi/wmi.c
+++ b/drivers/acpi/wmi.c
@@ -217,6 +217,35 @@ static bool find_guid(const char *guid_string, struct wmi_block **out)
return 0;
}
+static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
+{
+ struct guid_block *block = NULL;
+ char method[5];
+ struct acpi_object_list input;
+ union acpi_object params[1];
+ acpi_status status;
+ acpi_handle handle;
+
+ block = &wblock->gblock;
+ handle = wblock->handle;
+
+ if (!block)
+ return AE_NOT_EXIST;
+
+ input.count = 1;
+ input.pointer = params;
+ params[0].type = ACPI_TYPE_INTEGER;
+ params[0].integer.value = enable;
+
+ snprintf(method, 5, "WE%02X", block->notify_id);
+ status = acpi_evaluate_object(handle, method, &input, NULL);
+
+ if (status != AE_OK && status != AE_NOT_FOUND)
+ return status;
+ else
+ return AE_OK;
+}
+
/*
* Exported WMI functions
*/
@@ -427,6 +456,7 @@ acpi_status wmi_install_notify_handler(const char *guid,
wmi_notify_handler handler, void *data)
{
struct wmi_block *block;
+ acpi_status status;
if (!guid || !handler)
return AE_BAD_PARAMETER;
@@ -441,7 +471,9 @@ wmi_notify_handler handler, void *data)
block->handler = handler;
block->handler_data = data;
- return AE_OK;
+ status = wmi_method_enable(block, 1);
+
+ return status;
}
EXPORT_SYMBOL_GPL(wmi_install_notify_handler);
@@ -453,6 +485,7 @@ EXPORT_SYMBOL_GPL(wmi_install_notify_handler);
acpi_status wmi_remove_notify_handler(const char *guid)
{
struct wmi_block *block;
+ acpi_status status;
if (!guid)
return AE_BAD_PARAMETER;
@@ -464,10 +497,12 @@ acpi_status wmi_remove_notify_handler(const char *guid)
if (!block->handler)
return AE_NULL_ENTRY;
+ status = wmi_method_enable(block, 0);
+
block->handler = NULL;
block->handler_data = NULL;
- return AE_OK;
+ return status;
}
EXPORT_SYMBOL_GPL(wmi_remove_notify_handler);
--
1.5.5.1
From: Bjorn Helgaas <[email protected]>
CONFIG_PNP_DEBUG is no longer used to turn on dev_dbg() in PNP,
since we have pnp_dbg() which can be enabled at boot-time, so
this patch removes the config option.
Note that pnp_dock_event() checks "#ifdef DEBUG". But there's
never been a clear path for enabling that via configgery. It
happened that CONFIG_PNP_DEBUG enabled it after 1bd17e63a068db6,
but that was accidental and only in 2.6.26.
Signed-off-by: Bjorn Helgaas <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/pnp/Kconfig | 6 ------
drivers/pnp/Makefile | 4 ----
drivers/pnp/isapnp/Makefile | 4 ----
drivers/pnp/pnpacpi/Makefile | 4 ----
drivers/pnp/pnpbios/Makefile | 4 ----
5 files changed, 0 insertions(+), 22 deletions(-)
diff --git a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig
index 8a3237f..2a37b3f 100644
--- a/drivers/pnp/Kconfig
+++ b/drivers/pnp/Kconfig
@@ -36,12 +36,6 @@ config PNP_DEBUG_MESSAGES
if PNP
-config PNP_DEBUG
- bool "PnP Debug Messages"
- help
- Say Y if you want the Plug and Play Layer to print debug messages.
- This is useful if you are developing a PnP driver or troubleshooting.
-
comment "Protocols"
source "drivers/pnp/isapnp/Kconfig"
diff --git a/drivers/pnp/Makefile b/drivers/pnp/Makefile
index 26f5abc..a381a92 100644
--- a/drivers/pnp/Makefile
+++ b/drivers/pnp/Makefile
@@ -7,7 +7,3 @@ obj-y := core.o card.o driver.o resource.o manager.o support.o interface.o quir
obj-$(CONFIG_PNPACPI) += pnpacpi/
obj-$(CONFIG_PNPBIOS) += pnpbios/
obj-$(CONFIG_ISAPNP) += isapnp/
-
-ifeq ($(CONFIG_PNP_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
diff --git a/drivers/pnp/isapnp/Makefile b/drivers/pnp/isapnp/Makefile
index 3e38f06..cac18bb 100644
--- a/drivers/pnp/isapnp/Makefile
+++ b/drivers/pnp/isapnp/Makefile
@@ -5,7 +5,3 @@
isapnp-proc-$(CONFIG_PROC_FS) = proc.o
obj-y := core.o compat.o $(isapnp-proc-y)
-
-ifeq ($(CONFIG_PNP_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
diff --git a/drivers/pnp/pnpacpi/Makefile b/drivers/pnp/pnpacpi/Makefile
index 2d7a1e6..905326f 100644
--- a/drivers/pnp/pnpacpi/Makefile
+++ b/drivers/pnp/pnpacpi/Makefile
@@ -3,7 +3,3 @@
#
obj-y := core.o rsparser.o
-
-ifeq ($(CONFIG_PNP_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
diff --git a/drivers/pnp/pnpbios/Makefile b/drivers/pnp/pnpbios/Makefile
index 310e2b3..3cd3ed7 100644
--- a/drivers/pnp/pnpbios/Makefile
+++ b/drivers/pnp/pnpbios/Makefile
@@ -5,7 +5,3 @@
pnpbios-proc-$(CONFIG_PNPBIOS_PROC_FS) = proc.o
obj-y := core.o bioscalls.o rsparser.o $(pnpbios-proc-y)
-
-ifeq ($(CONFIG_PNP_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
--
1.5.5.1
From: Carlos Corbacho <[email protected]>
As per Dmitry Torokhov's suggestion, acer-wmi doesn't need a private
workqueue, so remove it.
Signed-off-by: Carlos Corbacho <[email protected]>
Cc: Dmitry Torokhov <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/misc/acer-wmi.c | 18 ++----------------
1 files changed, 2 insertions(+), 16 deletions(-)
diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c
index 8708d31..cf4c39f 100644
--- a/drivers/misc/acer-wmi.c
+++ b/drivers/misc/acer-wmi.c
@@ -930,8 +930,6 @@ static void acer_backlight_exit(void)
/*
* Rfkill devices
*/
-static struct workqueue_struct *rfkill_workqueue;
-
static void acer_rfkill_update(struct work_struct *ignored);
static DECLARE_DELAYED_WORK(acer_rfkill_work, acer_rfkill_update);
static void acer_rfkill_update(struct work_struct *ignored)
@@ -952,8 +950,7 @@ static void acer_rfkill_update(struct work_struct *ignored)
RFKILL_STATE_SOFT_BLOCKED);
}
- queue_delayed_work(rfkill_workqueue, &acer_rfkill_work,
- round_jiffies_relative(HZ));
+ schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
}
static int acer_rfkill_set(void *data, enum rfkill_state state)
@@ -1018,17 +1015,7 @@ static int acer_rfkill_init(struct device *dev)
}
}
- rfkill_workqueue = create_singlethread_workqueue("rfkill_workqueue");
- if (!rfkill_workqueue) {
- if (has_cap(ACER_CAP_BLUETOOTH)) {
- kfree(bluetooth_rfkill->data);
- rfkill_unregister(bluetooth_rfkill);
- }
- kfree(wireless_rfkill->data);
- rfkill_unregister(wireless_rfkill);
- return -ENOMEM;
- }
- queue_delayed_work(rfkill_workqueue, &acer_rfkill_work, HZ);
+ schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
return 0;
}
@@ -1036,7 +1023,6 @@ static int acer_rfkill_init(struct device *dev)
static void acer_rfkill_exit(void)
{
cancel_delayed_work_sync(&acer_rfkill_work);
- destroy_workqueue(rfkill_workqueue);
kfree(wireless_rfkill->data);
rfkill_unregister(wireless_rfkill);
if (has_cap(ACER_CAP_BLUETOOTH)) {
--
1.5.5.1
From: Shaohua Li <[email protected]>
support _LCK method, which is a optional method for hotplug
lenb: we have not seen _LCK used in the field yet
Signed-off-by: Shaohua Li <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/dock.c | 21 +++++++++++++++++++++
1 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 78d27ce..7bdf93b 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -452,6 +452,25 @@ static inline void complete_undock(struct dock_station *ds)
ds->flags &= ~(DOCK_UNDOCKING);
}
+static void dock_lock(struct dock_station *ds, int lock)
+{
+ struct acpi_object_list arg_list;
+ union acpi_object arg;
+ acpi_status status;
+
+ arg_list.count = 1;
+ arg_list.pointer = &arg;
+ arg.type = ACPI_TYPE_INTEGER;
+ arg.integer.value = !!lock;
+ status = acpi_evaluate_object(ds->handle, "_LCK", &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ if (lock)
+ printk(KERN_WARNING PREFIX "Locking device failed\n");
+ else
+ printk(KERN_WARNING PREFIX "Unlocking device failed\n");
+ }
+}
+
/**
* dock_in_progress - see if we are in the middle of handling a dock event
* @ds: the dock station
@@ -577,6 +596,7 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
undock(ds);
+ dock_lock(ds, 0);
eject_dock(ds);
if (dock_present(ds)) {
printk(KERN_ERR PREFIX "Unable to undock!\n");
@@ -617,6 +637,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
hotplug_dock_devices(ds, event);
complete_dock(ds);
dock_event(ds, event, DOCK_EVENT);
+ dock_lock(ds, 1);
}
break;
case ACPI_NOTIFY_DEVICE_CHECK:
--
1.5.5.1
From: Bjorn Helgaas <[email protected]>
This patch just fixes indentation of a couple debug messages.
Signed-off-by: Bjorn Helgaas <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/pnp/resource.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index 4cfe3a1..e0206da 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -294,7 +294,7 @@ static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
u8 progif;
if (pci->irq == irq) {
- dev_dbg(&pnp->dev, "device %s using irq %d\n",
+ dev_dbg(&pnp->dev, " device %s using irq %d\n",
pci_name(pci), irq);
return 1;
}
@@ -316,7 +316,7 @@ static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
if ((progif & 0x5) != 0x5)
if (pci_get_legacy_ide_irq(pci, 0) == irq ||
pci_get_legacy_ide_irq(pci, 1) == irq) {
- dev_dbg(&pnp->dev, "legacy IDE device %s "
+ dev_dbg(&pnp->dev, " legacy IDE device %s "
"using irq %d\n", pci_name(pci), irq);
return 1;
}
--
1.5.5.1
From: Thomas Renninger <[email protected]>
Signed-off-by: Thomas Renninger <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/osl.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 235a138..e93e077 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -729,8 +729,7 @@ acpi_status acpi_os_execute(acpi_execute_type type,
INIT_WORK(&dpc->work, acpi_os_execute_deferred);
queue = (type == OSL_NOTIFY_HANDLER) ? kacpi_notify_wq : kacpid_wq;
if (!queue_work(queue, &dpc->work)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Call to queue_work() failed.\n"));
+ printk(KERN_ERR "Call to queue_work() failed.\n");
status = AE_ERROR;
kfree(dpc);
}
--
1.5.5.1
From: Bjorn Helgaas <[email protected]>
Use scnprintf() to build up a buffer of PNP IDs to print. This
makes the printk atomic and helps get rid of an #ifdef.
Also remove an "#ifdef DEBUG" from some debug functions. The
functions only produce debug output, so it's OK to run the
function and just have the output be dropped at the end.
Signed-off-by: Bjorn Helgaas <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/pnp/core.c | 18 ++++++++----------
drivers/pnp/support.c | 4 ----
2 files changed, 8 insertions(+), 14 deletions(-)
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index a411582..7cb1ffc 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -185,6 +185,9 @@ int __pnp_add_device(struct pnp_dev *dev)
int pnp_add_device(struct pnp_dev *dev)
{
int ret;
+ char buf[128];
+ int len = 0;
+ struct pnp_id *id;
if (dev->card)
return -EINVAL;
@@ -193,17 +196,12 @@ int pnp_add_device(struct pnp_dev *dev)
if (ret)
return ret;
-#ifdef CONFIG_PNP_DEBUG
- {
- struct pnp_id *id;
+ buf[0] = '\0';
+ for (id = dev->id; id; id = id->next)
+ len += scnprintf(buf + len, sizeof(buf) - len, " %s", id->id);
- dev_printk(KERN_DEBUG, &dev->dev, "%s device, IDs",
- dev->protocol->name);
- for (id = dev->id; id; id = id->next)
- printk(" %s", id->id);
- printk(" (%s)\n", dev->active ? "active" : "disabled");
- }
-#endif
+ dev_dbg(&dev->dev, "%s device, IDs%s (%s)\n",
+ dev->protocol->name, buf, dev->active ? "active" : "disabled");
return 0;
}
diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c
index b42df16..7149186 100644
--- a/drivers/pnp/support.c
+++ b/drivers/pnp/support.c
@@ -75,7 +75,6 @@ char *pnp_resource_type_name(struct resource *res)
void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
{
-#ifdef DEBUG
char buf[128];
int len;
struct pnp_resource *pnp_res;
@@ -118,7 +117,6 @@ void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
}
dev_dbg(&dev->dev, "%s\n", buf);
}
-#endif
}
char *pnp_option_priority_name(struct pnp_option *option)
@@ -136,7 +134,6 @@ char *pnp_option_priority_name(struct pnp_option *option)
void dbg_pnp_show_option(struct pnp_dev *dev, struct pnp_option *option)
{
-#ifdef DEBUG
char buf[128];
int len = 0, i;
struct pnp_port *port;
@@ -209,5 +206,4 @@ void dbg_pnp_show_option(struct pnp_dev *dev, struct pnp_option *option)
break;
}
dev_dbg(&dev->dev, "%s\n", buf);
-#endif
}
--
1.5.5.1
From: Zhao Yakui <[email protected]>
when there is no ECDT table and no _INI object for EC device, it will be
enabled before scanning ACPI device. But it is too late after the following
the commit is merged.
>commit 7752d5cfe3d11ca0bb9c673ec38bd78ba6578f8e
> Author: Robert Hancock <[email protected]>
> Date: Fri Feb 15 01:27:20 2008 -0800
>x86: validate against acpi motherboard resources
After the above commit is merged, OS will check whether MCFG area is
reserved in ACPI motherboard resources by calling the function of
acpi_get_devices when there exists MCFG table. In the acpi_get_devices the _STA
object will be evaluated to check the status of the ACPI device. On some broken
BIOS the MYEC object of EC device is initialized as one, which indicates that
EC operation region is already accessible before enabling EC device.So on these
broken BIOS the EC operation region will be accessed in course of evaluating
the _STA object before enabling EC device, which causes that OS will print the
following warning messages:
>ACPI Error (evregion-0315): No handler for Region [EC__] (ffff88007f8145e8)
[EmbeddedControl] [20080609]
>ACPI Error (exfldio-0290): Region EmbeddedControl(3) has no handler [20080321]
>ACPI Error (psparse-0530): Method parse/execution failed [\_SB_.PCI0.SBRG.
EC__.BAT1._STA] (Node ffff81013fc17a00), AE_NOT_EXIST
>ACPI Error (uteval-0233): Method execution failed [\_SB_.PCI0.SBRG.EC__.BAT1.
_STA] (Node ffff81013fc17a00), AE_NOT_EXIST
Although the above warning message is harmless, it looks confusing.
So it is necessary to enable EC device as early as possible.Maybe it is
appropriate to enable it immediately after ACPI full initialization.
http://bugzilla.kernel.org/show_bug.cgi?id=11255
http://bugzilla.kernel.org/show_bug.cgi?id=11374
http://bugzilla.kernel.org/show_bug.cgi?id=11660
Signed-off-by: Zhao Yakui <[email protected]>
Acked-by: Alexey Starikovskiy <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/bus.c | 6 ++++++
drivers/acpi/scan.c | 4 ----
include/acpi/acpi_drivers.h | 1 +
3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index ccae305..0e0bbc6 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -749,6 +749,12 @@ static int __init acpi_bus_init(void)
goto error1;
}
+ /*
+ * Maybe EC region is required at bus_scan/acpi_get_devices. So it
+ * is necessary to enable it as early as possible.
+ */
+ acpi_boot_ec_enable();
+
printk(KERN_INFO PREFIX "Interpreter enabled\n");
/* Initialize sleep structures */
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index f6f52c1..2ae218f 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1545,7 +1545,6 @@ static int acpi_bus_scan_fixed(struct acpi_device *root)
return result;
}
-int __init acpi_boot_ec_enable(void);
static int __init acpi_scan_init(void)
{
@@ -1579,9 +1578,6 @@ static int __init acpi_scan_init(void)
*/
result = acpi_bus_scan_fixed(acpi_root);
- /* EC region might be needed at bus_scan, so enable it now */
- acpi_boot_ec_enable();
-
if (!result)
result = acpi_bus_scan(acpi_root, &ops);
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index e5f38e5..ab926a7 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -100,6 +100,7 @@ int acpi_power_transition(struct acpi_device *device, int state);
-------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI_EC
int acpi_ec_ecdt_probe(void);
+int acpi_boot_ec_enable(void);
#endif
/* --------------------------------------------------------------------------
--
1.5.5.1
From: Bjorn Helgaas <[email protected]>
There are only a few remaining uses of pnp_info(), so I just
converted them to printk and removed the pnp_err(), pnp_info(),
pnp_warn(), and pnp_dbg() wrappers.
I also removed a couple debug messages that don't seem useful any
more ("driver registered", "driver unregistered", "driver attached").
Signed-off-by: Bjorn Helgaas <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/pnp/driver.c | 4 ----
drivers/pnp/pnpacpi/core.c | 6 +++---
include/linux/pnp.h | 10 ----------
3 files changed, 3 insertions(+), 17 deletions(-)
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index d3f869e..54673a4 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -114,7 +114,6 @@ static int pnp_device_probe(struct device *dev)
} else
goto fail;
- dev_dbg(dev, "driver attached\n");
return error;
fail:
@@ -210,8 +209,6 @@ struct bus_type pnp_bus_type = {
int pnp_register_driver(struct pnp_driver *drv)
{
- pnp_dbg("the driver '%s' has been registered", drv->name);
-
drv->driver.name = drv->name;
drv->driver.bus = &pnp_bus_type;
@@ -221,7 +218,6 @@ int pnp_register_driver(struct pnp_driver *drv)
void pnp_unregister_driver(struct pnp_driver *drv)
{
driver_unregister(&drv->driver);
- pnp_dbg("the driver '%s' has been unregistered", drv->name);
}
/**
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index c1b9ea3..67c651b 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -255,14 +255,14 @@ int pnpacpi_disabled __initdata;
static int __init pnpacpi_init(void)
{
if (acpi_disabled || pnpacpi_disabled) {
- pnp_info("PnP ACPI: disabled");
+ printk(KERN_INFO "pnp: PnP ACPI: disabled\n");
return 0;
}
- pnp_info("PnP ACPI init");
+ printk(KERN_INFO "pnp: PnP ACPI init\n");
pnp_register_protocol(&pnpacpi_protocol);
register_acpi_bus_type(&acpi_pnp_bus);
acpi_get_devices(NULL, pnpacpi_add_device_handler, NULL, NULL);
- pnp_info("PnP ACPI: found %d devices", num);
+ printk(KERN_INFO "pnp: PnP ACPI: found %d devices\n", num);
unregister_acpi_bus_type(&acpi_pnp_bus);
pnp_platform_devices = 1;
return 0;
diff --git a/include/linux/pnp.h b/include/linux/pnp.h
index be764e5..05daece 100644
--- a/include/linux/pnp.h
+++ b/include/linux/pnp.h
@@ -483,14 +483,4 @@ static inline void pnp_unregister_driver(struct pnp_driver *drv) { }
#endif /* CONFIG_PNP */
-#define pnp_err(format, arg...) printk(KERN_ERR "pnp: " format "\n" , ## arg)
-#define pnp_info(format, arg...) printk(KERN_INFO "pnp: " format "\n" , ## arg)
-#define pnp_warn(format, arg...) printk(KERN_WARNING "pnp: " format "\n" , ## arg)
-
-#ifdef CONFIG_PNP_DEBUG
-#define pnp_dbg(format, arg...) printk(KERN_DEBUG "pnp: " format "\n" , ## arg)
-#else
-#define pnp_dbg(format, arg...) do {} while (0)
-#endif
-
#endif /* _LINUX_PNP_H */
--
1.5.5.1
From: Thomas Renninger <[email protected]>
Signed-off-by: Thomas Renninger <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/system.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index 91dec44..58a1d89 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -387,8 +387,8 @@ static ssize_t counter_set(struct kobject *kobj,
goto end;
if (!(all_counters[index].flags & ACPI_EVENT_VALID)) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Can not change Invalid GPE/Fixed Event status\n"));
+ printk(KERN_WARNING
+ "Can not change Invalid GPE/Fixed Event status\n");
return -EINVAL;
}
--
1.5.5.1
From: Harvey Harrison <[email protected]>
set_bit expects unsigned int, and we start with a u32 anyway.
drivers/acpi/toshiba_acpi.c:397:14: warning: incorrect type in argument 1 (different signedness)
drivers/acpi/toshiba_acpi.c:397:14: expected unsigned int [usertype] *word
drivers/acpi/toshiba_acpi.c:397:14: got int *<noident>
drivers/acpi/toshiba_acpi.c:399:14: warning: incorrect type in argument 1 (different signedness)
drivers/acpi/toshiba_acpi.c:399:14: expected unsigned int [usertype] *word
drivers/acpi/toshiba_acpi.c:399:14: got int *<noident>
drivers/acpi/toshiba_acpi.c:401:14: warning: incorrect type in argument 1 (different signedness)
drivers/acpi/toshiba_acpi.c:401:14: expected unsigned int [usertype] *word
drivers/acpi/toshiba_acpi.c:401:14: got int *<noident>
Signed-off-by: Harvey Harrison <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/toshiba_acpi.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index 0a43c8e..4172d29 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -392,7 +392,7 @@ static unsigned long write_video(const char *buffer, unsigned long count)
hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result);
if (hci_result == HCI_SUCCESS) {
- int new_video_out = video_out;
+ unsigned int new_video_out = video_out;
if (lcd_out != -1)
_set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out);
if (crt_out != -1)
--
1.5.5.1
From: Shaohua Li <[email protected]>
dock driver can handle ata(bay) hotplug now. dock driver already handles
_EJ0 and _STA, so remove them. Also libata doesn't need register
notification handler anymore.
Signed-off-by: Shaohua Li <[email protected]>
Acked-by: Tejun Heo <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/dock.c | 3 +-
drivers/ata/libata-acpi.c | 107 ++++++---------------------------------------
2 files changed, 16 insertions(+), 94 deletions(-)
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 4b395b1..f19f643 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -738,7 +738,8 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
/* Fall back */
case ACPI_NOTIFY_EJECT_REQUEST:
begin_undock(ds);
- if (immediate_undock || surprise_removal)
+ if ((immediate_undock && !(ds->flags & DOCK_IS_ATA))
+ || surprise_removal)
handle_eject_request(ds, event);
else
dock_event(ds, event, UNDOCK_EVENT);
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 9330b79..97727be 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -120,21 +120,6 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap)
ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
}
-static void ata_acpi_eject_device(acpi_handle handle)
-{
- struct acpi_object_list arg_list;
- union acpi_object arg;
-
- arg_list.count = 1;
- arg_list.pointer = &arg;
- arg.type = ACPI_TYPE_INTEGER;
- arg.integer.value = 1;
-
- if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0",
- &arg_list, NULL)))
- printk(KERN_ERR "Failed to evaluate _EJ0!\n");
-}
-
/* @ap and @dev are the same as ata_acpi_handle_hotplug() */
static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
{
@@ -157,7 +142,6 @@ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
* @ap: ATA port ACPI event occurred
* @dev: ATA device ACPI event occurred (can be NULL)
* @event: ACPI event which occurred
- * @is_dock_event: boolean indicating whether the event was a dock one
*
* All ACPI bay / device realted events end up in this function. If
* the event is port-wide @dev is NULL. If the event is specific to a
@@ -171,115 +155,58 @@ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
* ACPI notify handler context. May sleep.
*/
static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
- u32 event, int is_dock_event)
+ u32 event)
{
- char event_string[12];
- char *envp[] = { event_string, NULL };
struct ata_eh_info *ehi = &ap->link.eh_info;
- struct kobject *kobj = NULL;
int wait = 0;
unsigned long flags;
- acpi_handle handle, tmphandle;
- unsigned long sta;
- acpi_status status;
+ acpi_handle handle;
- if (dev) {
- if (dev->sdev)
- kobj = &dev->sdev->sdev_gendev.kobj;
+ if (dev)
handle = dev->acpi_handle;
- } else {
- kobj = &ap->dev->kobj;
+ else
handle = ap->acpi_handle;
- }
-
- status = acpi_get_handle(handle, "_EJ0", &tmphandle);
- if (ACPI_FAILURE(status))
- /* This device does not support hotplug */
- return;
-
- if (event == ACPI_NOTIFY_BUS_CHECK ||
- event == ACPI_NOTIFY_DEVICE_CHECK)
- status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
spin_lock_irqsave(ap->lock, flags);
-
+ /*
+ * When dock driver calls into the routine, it will always use
+ * ACPI_NOTIFY_BUS_CHECK/ACPI_NOTIFY_DEVICE_CHECK for add and
+ * ACPI_NOTIFY_EJECT_REQUEST for remove
+ */
switch (event) {
case ACPI_NOTIFY_BUS_CHECK:
case ACPI_NOTIFY_DEVICE_CHECK:
ata_ehi_push_desc(ehi, "ACPI event");
- if (ACPI_FAILURE(status)) {
- ata_port_printk(ap, KERN_ERR,
- "acpi: failed to determine bay status (0x%x)\n",
- status);
- break;
- }
-
- if (sta) {
- ata_ehi_hotplugged(ehi);
- ata_port_freeze(ap);
- } else {
- /* The device has gone - unplug it */
- ata_acpi_detach_device(ap, dev);
- wait = 1;
- }
+ ata_ehi_hotplugged(ehi);
+ ata_port_freeze(ap);
break;
case ACPI_NOTIFY_EJECT_REQUEST:
ata_ehi_push_desc(ehi, "ACPI event");
- if (!is_dock_event)
- break;
-
- /* undock event - immediate unplug */
ata_acpi_detach_device(ap, dev);
wait = 1;
break;
}
- /* make sure kobj doesn't go away while ap->lock is released */
- kobject_get(kobj);
-
spin_unlock_irqrestore(ap->lock, flags);
- if (wait) {
+ if (wait)
ata_port_wait_eh(ap);
- ata_acpi_eject_device(handle);
- }
-
- if (kobj && !is_dock_event) {
- sprintf(event_string, "BAY_EVENT=%d", event);
- kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
- }
-
- kobject_put(kobj);
}
static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data)
{
struct ata_device *dev = data;
- ata_acpi_handle_hotplug(dev->link->ap, dev, event, 1);
+ ata_acpi_handle_hotplug(dev->link->ap, dev, event);
}
static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data)
{
struct ata_port *ap = data;
- ata_acpi_handle_hotplug(ap, NULL, event, 1);
-}
-
-static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data)
-{
- struct ata_device *dev = data;
-
- ata_acpi_handle_hotplug(dev->link->ap, dev, event, 0);
-}
-
-static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data)
-{
- struct ata_port *ap = data;
-
- ata_acpi_handle_hotplug(ap, NULL, event, 0);
+ ata_acpi_handle_hotplug(ap, NULL, event);
}
/**
@@ -315,9 +242,6 @@ void ata_acpi_associate(struct ata_host *host)
ata_acpi_associate_ide_port(ap);
if (ap->acpi_handle) {
- acpi_install_notify_handler(ap->acpi_handle,
- ACPI_SYSTEM_NOTIFY,
- ata_acpi_ap_notify, ap);
/* we might be on a docking station */
register_hotplug_dock_device(ap->acpi_handle,
ata_acpi_ap_notify_dock, ap);
@@ -327,9 +251,6 @@ void ata_acpi_associate(struct ata_host *host)
struct ata_device *dev = &ap->link.device[j];
if (dev->acpi_handle) {
- acpi_install_notify_handler(dev->acpi_handle,
- ACPI_SYSTEM_NOTIFY,
- ata_acpi_dev_notify, dev);
/* we might be on a docking station */
register_hotplug_dock_device(dev->acpi_handle,
ata_acpi_dev_notify_dock, dev);
--
1.5.5.1
From: Randy Dunlap <[email protected]>
CONFIG_ACPI_TOSHIBA can =y when CONFIG_INPUT=m, so prevent that
combination and its subsequent build errors:
toshiba_acpi.c:(.text+0x3e877): undefined reference to `input_event'
toshiba_acpi.c:(.text+0x3e98a): undefined reference to `input_unregister_polled_device'
toshiba_acpi.c:(.text+0x3e994): undefined reference to `input_free_polled_device'
toshiba_acpi.c:(.init.text+0x21b4): undefined reference to `input_allocate_polled_device'
toshiba_acpi.c:(.init.text+0x2263): undefined reference to `input_register_polled_device'
make[1]: *** [.tmp_vmlinux1] Error 1
Signed-off-by: Randy Dunlap <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/Kconfig | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 735f5ea..79540db 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -259,7 +259,7 @@ config ACPI_ASUS
config ACPI_TOSHIBA
tristate "Toshiba Laptop Extras"
- depends on X86
+ depends on X86 && INPUT
select BACKLIGHT_CLASS_DEVICE
---help---
This driver adds support for access to certain system settings
--
1.5.5.1
From: Thomas Renninger <[email protected]>
AK: Added missing printk prefix
Signed-off-by: Thomas Renninger <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/acpi_memhotplug.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 5f1127a..ce0763d 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -454,8 +454,8 @@ static int acpi_memory_device_start (struct acpi_device *device)
/* call add_memory func */
result = acpi_memory_enable_device(mem_device);
if (result)
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error in acpi_memory_enable_device\n"));
+ printk(KERN_ERR "Error in acpi_memory_enable_device [%d]\n",
+ result);
}
return result;
}
--
1.5.5.1
From: Bjorn Helgaas <[email protected]>
Use dev_printk() when possible for more informative error messages.
Signed-off-by: Bjorn Helgaas <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/pnp/pnpacpi/rsparser.c | 15 ++++++++-------
1 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 95015cb..0461d4b 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -132,7 +132,8 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
pnp_add_irq_resource(dev, irq, flags);
}
-static int dma_flags(int type, int bus_master, int transfer)
+static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
+ int transfer)
{
int flags = 0;
@@ -154,7 +155,7 @@ static int dma_flags(int type, int bus_master, int transfer)
default:
/* Set a default value ? */
flags |= IORESOURCE_DMA_COMPATIBLE;
- pnp_err("Invalid DMA type");
+ dev_err(&dev->dev, "invalid DMA type %d\n", type);
}
switch (transfer) {
case ACPI_TRANSFER_8:
@@ -169,7 +170,7 @@ static int dma_flags(int type, int bus_master, int transfer)
default:
/* Set a default value ? */
flags |= IORESOURCE_DMA_8AND16BIT;
- pnp_err("Invalid DMA transfer type");
+ dev_err(&dev->dev, "invalid DMA transfer type %d\n", transfer);
}
return flags;
@@ -336,7 +337,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
case ACPI_RESOURCE_TYPE_DMA:
dma = &res->data.dma;
if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)
- flags = dma_flags(dma->type, dma->bus_master,
+ flags = dma_flags(dev, dma->type, dma->bus_master,
dma->transfer);
else
flags = IORESOURCE_DISABLED;
@@ -477,7 +478,7 @@ static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
for (i = 0; i < p->channel_count; i++)
map |= 1 << p->channels[i];
- flags = dma_flags(p->type, p->bus_master, p->transfer);
+ flags = dma_flags(dev, p->type, p->bus_master, p->transfer);
pnp_register_dma_resource(dev, option_flags, map, flags);
}
@@ -608,8 +609,8 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
unsigned char flags = 0;
status = acpi_resource_to_address64(r, p);
- if (!ACPI_SUCCESS(status)) {
- pnp_warn("PnPACPI: failed to convert resource type %d",
+ if (ACPI_FAILURE(status)) {
+ dev_warn(&dev->dev, "can't convert resource type %d\n",
r->type);
return;
}
--
1.5.5.1
From: Harald Welte <[email protected]>
This is a driver for ACPI extras such as hotkeys and backlight
brightness control on various Panasonic "Let's Note" series laptop
computers.
It exports the backlight via the backlight class device API,
and the hotkeys as input event device. Some more esoteric
items like number of installed batteries are exported via sysfs
device attributes.
Hotkey events also generate old-style ACPI enents through
/proc/acpi/event to interoperate with current versions of acpid.
Signed-off-by: Harald Welte <[email protected]>
Acked-by: Henrique de Moraes Holschuh <[email protected]>
Acked-by: Matthew Garrett <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
MAINTAINERS | 5 +
drivers/misc/Kconfig | 11 +
drivers/misc/Makefile | 1 +
drivers/misc/panasonic-laptop.c | 767 +++++++++++++++++++++++++++++++++++++++
4 files changed, 784 insertions(+), 0 deletions(-)
create mode 100644 drivers/misc/panasonic-laptop.c
diff --git a/MAINTAINERS b/MAINTAINERS
index cad81a2..fa35793 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3148,6 +3148,11 @@ M: [email protected]
L: [email protected]
S: Maintained
+PANASONIC LAPTOP ACPI EXTRAS DRIVER
+P: Harald Welte
+M: [email protected]
+S: Maintained
+
PARALLEL PORT SUPPORT
L: [email protected] (subscribers-only)
S: Orphan
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index a726f3b..4ed8357 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -245,6 +245,17 @@ config MSI_LAPTOP
If you have an MSI S270 laptop, say Y or M here.
+config PANASONIC_LAPTOP
+ tristate "Panasonic Laptop Extras"
+ depends on X86 && INPUT
+ depends on BACKLIGHT_CLASS_DEVICE
+ ---help---
+ This driver adds support for access to backlight control and hotkeys
+ on Panasonic Let's Note laptops.
+
+ If you have a Panasonic Let's note laptop (such as the R1(N variant),
+ R2, R3, R5, T2, W2 and Y2 series), say Y.
+
config COMPAL_LAPTOP
tristate "Compal Laptop Extras"
depends on X86
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index c6c13f6..909e246 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_SGI_IOC4) += ioc4.o
obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
+obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o
obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
diff --git a/drivers/misc/panasonic-laptop.c b/drivers/misc/panasonic-laptop.c
new file mode 100644
index 0000000..9aecda5
--- /dev/null
+++ b/drivers/misc/panasonic-laptop.c
@@ -0,0 +1,767 @@
+/*
+ * Panasonic HotKey and LCD brightness control driver
+ * (C) 2004 Hiroshi Miura <[email protected]>
+ * (C) 2004 NTT DATA Intellilink Co. http://www.intellilink.co.jp/
+ * (C) YOKOTA Hiroshi <yokota (at) netlab. is. tsukuba. ac. jp>
+ * (C) 2004 David Bronaugh <dbronaugh>
+ * (C) 2006-2008 Harald Welte <[email protected]>
+ *
+ * derived from toshiba_acpi.c, Copyright (C) 2002-2004 John Belmonte
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publicshed by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *---------------------------------------------------------------------------
+ *
+ * ChangeLog:
+ * Sep.23, 2008 Harald Welte <[email protected]>
+ * -v0.95 rename driver from drivers/acpi/pcc_acpi.c to
+ * drivers/misc/panasonic-laptop.c
+ *
+ * Jul.04, 2008 Harald Welte <[email protected]>
+ * -v0.94 replace /proc interface with device attributes
+ * support {set,get}keycode on th input device
+ *
+ * Jun.27, 2008 Harald Welte <[email protected]>
+ * -v0.92 merge with 2.6.26-rc6 input API changes
+ * remove broken <= 2.6.15 kernel support
+ * resolve all compiler warnings
+ * various coding style fixes (checkpatch.pl)
+ * add support for backlight api
+ * major code restructuring
+ *
+ * Dac.28, 2007 Harald Welte <[email protected]>
+ * -v0.91 merge with 2.6.24-rc6 ACPI changes
+ *
+ * Nov.04, 2006 Hiroshi Miura <[email protected]>
+ * -v0.9 remove warning about section reference.
+ * remove acpi_os_free
+ * add /proc/acpi/pcc/brightness interface for HAL access
+ * merge dbronaugh's enhancement
+ * Aug.17, 2004 David Bronaugh (dbronaugh)
+ * - Added screen brightness setting interface
+ * Thanks to FreeBSD crew (acpi_panasonic.c)
+ * for the ideas I needed to accomplish it
+ *
+ * May.29, 2006 Hiroshi Miura <[email protected]>
+ * -v0.8.4 follow to change keyinput structure
+ * thanks Fabian Yamaguchi <[email protected]>,
+ * Jacob Bower <[email protected]> and
+ * Hiroshi Yokota for providing solutions.
+ *
+ * Oct.02, 2004 Hiroshi Miura <[email protected]>
+ * -v0.8.2 merge code of YOKOTA Hiroshi
+ * <[email protected]>.
+ * Add sticky key mode interface.
+ * Refactoring acpi_pcc_generate_keyinput().
+ *
+ * Sep.15, 2004 Hiroshi Miura <[email protected]>
+ * -v0.8 Generate key input event on input subsystem.
+ * This is based on yet another driver written by
+ * Ryuta Nakanishi.
+ *
+ * Sep.10, 2004 Hiroshi Miura <[email protected]>
+ * -v0.7 Change proc interface functions using seq_file
+ * facility as same as other ACPI drivers.
+ *
+ * Aug.28, 2004 Hiroshi Miura <[email protected]>
+ * -v0.6.4 Fix a silly error with status checking
+ *
+ * Aug.25, 2004 Hiroshi Miura <[email protected]>
+ * -v0.6.3 replace read_acpi_int by standard function
+ * acpi_evaluate_integer
+ * some clean up and make smart copyright notice.
+ * fix return value of pcc_acpi_get_key()
+ * fix checking return value of acpi_bus_register_driver()
+ *
+ * Aug.22, 2004 David Bronaugh <[email protected]>
+ * -v0.6.2 Add check on ACPI data (num_sifr)
+ * Coding style cleanups, better error messages/handling
+ * Fixed an off-by-one error in memory allocation
+ *
+ * Aug.21, 2004 David Bronaugh <[email protected]>
+ * -v0.6.1 Fix a silly error with status checking
+ *
+ * Aug.20, 2004 David Bronaugh <[email protected]>
+ * - v0.6 Correct brightness controls to reflect reality
+ * based on information gleaned by Hiroshi Miura
+ * and discussions with Hiroshi Miura
+ *
+ * Aug.10, 2004 Hiroshi Miura <[email protected]>
+ * - v0.5 support LCD brightness control
+ * based on the disclosed information by MEI.
+ *
+ * Jul.25, 2004 Hiroshi Miura <[email protected]>
+ * - v0.4 first post version
+ * add function to retrive SIFR
+ *
+ * Jul.24, 2004 Hiroshi Miura <[email protected]>
+ * - v0.3 get proper status of hotkey
+ *
+ * Jul.22, 2004 Hiroshi Miura <[email protected]>
+ * - v0.2 add HotKey handler
+ *
+ * Jul.17, 2004 Hiroshi Miura <[email protected]>
+ * - v0.1 start from toshiba_acpi driver written by John Belmonte
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/backlight.h>
+#include <linux/ctype.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+#include <linux/input.h>
+
+
+#ifndef ACPI_HOTKEY_COMPONENT
+#define ACPI_HOTKEY_COMPONENT 0x10000000
+#endif
+
+#define _COMPONENT ACPI_HOTKEY_COMPONENT
+
+MODULE_AUTHOR("Hiroshi Miura, David Bronaugh and Harald Welte");
+MODULE_DESCRIPTION("ACPI HotKey driver for Panasonic Let's Note laptops");
+MODULE_LICENSE("GPL");
+
+#define LOGPREFIX "pcc_acpi: "
+
+/* Define ACPI PATHs */
+/* Lets note hotkeys */
+#define METHOD_HKEY_QUERY "HINF"
+#define METHOD_HKEY_SQTY "SQTY"
+#define METHOD_HKEY_SINF "SINF"
+#define METHOD_HKEY_SSET "SSET"
+#define HKEY_NOTIFY 0x80
+
+#define ACPI_PCC_DRIVER_NAME "Panasonic Laptop Support"
+#define ACPI_PCC_DEVICE_NAME "Hotkey"
+#define ACPI_PCC_CLASS "pcc"
+
+#define ACPI_PCC_INPUT_PHYS "panasonic/hkey0"
+
+/* LCD_TYPEs: 0 = Normal, 1 = Semi-transparent
+ ENV_STATEs: Normal temp=0x01, High temp=0x81, N/A=0x00
+*/
+enum SINF_BITS { SINF_NUM_BATTERIES = 0,
+ SINF_LCD_TYPE,
+ SINF_AC_MAX_BRIGHT,
+ SINF_AC_MIN_BRIGHT,
+ SINF_AC_CUR_BRIGHT,
+ SINF_DC_MAX_BRIGHT,
+ SINF_DC_MIN_BRIGHT,
+ SINF_DC_CUR_BRIGHT,
+ SINF_MUTE,
+ SINF_RESERVED,
+ SINF_ENV_STATE,
+ SINF_STICKY_KEY = 0x80,
+ };
+/* R1 handles SINF_AC_CUR_BRIGHT as SINF_CUR_BRIGHT, doesn't know AC state */
+
+static int acpi_pcc_hotkey_add(struct acpi_device *device);
+static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type);
+static int acpi_pcc_hotkey_resume(struct acpi_device *device);
+
+static const struct acpi_device_id pcc_device_ids[] = {
+ { "MAT0012", 0},
+ { "MAT0013", 0},
+ { "MAT0018", 0},
+ { "MAT0019", 0},
+ { "", 0},
+};
+
+static struct acpi_driver acpi_pcc_driver = {
+ .name = ACPI_PCC_DRIVER_NAME,
+ .class = ACPI_PCC_CLASS,
+ .ids = pcc_device_ids,
+ .ops = {
+ .add = acpi_pcc_hotkey_add,
+ .remove = acpi_pcc_hotkey_remove,
+ .resume = acpi_pcc_hotkey_resume,
+ },
+};
+
+#define KEYMAP_SIZE 11
+static const int initial_keymap[KEYMAP_SIZE] = {
+ /* 0 */ KEY_RESERVED,
+ /* 1 */ KEY_BRIGHTNESSDOWN,
+ /* 2 */ KEY_BRIGHTNESSUP,
+ /* 3 */ KEY_DISPLAYTOGGLE,
+ /* 4 */ KEY_MUTE,
+ /* 5 */ KEY_VOLUMEDOWN,
+ /* 6 */ KEY_VOLUMEUP,
+ /* 7 */ KEY_SLEEP,
+ /* 8 */ KEY_PROG1, /* Change CPU boost */
+ /* 9 */ KEY_BATTERY,
+ /* 10 */ KEY_SUSPEND,
+};
+
+struct pcc_acpi {
+ acpi_handle handle;
+ unsigned long num_sifr;
+ int sticky_mode;
+ u32 *sinf;
+ struct acpi_device *device;
+ struct input_dev *input_dev;
+ struct backlight_device *backlight;
+ int keymap[KEYMAP_SIZE];
+};
+
+struct pcc_keyinput {
+ struct acpi_hotkey *hotkey;
+};
+
+/* method access functions */
+static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val)
+{
+ union acpi_object in_objs[] = {
+ { .integer.type = ACPI_TYPE_INTEGER,
+ .integer.value = func, },
+ { .integer.type = ACPI_TYPE_INTEGER,
+ .integer.value = val, },
+ };
+ struct acpi_object_list params = {
+ .count = ARRAY_SIZE(in_objs),
+ .pointer = in_objs,
+ };
+ acpi_status status = AE_OK;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_write_sset");
+
+ status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SSET,
+ ¶ms, NULL);
+
+ return status == AE_OK;
+}
+
+static inline int acpi_pcc_get_sqty(struct acpi_device *device)
+{
+ unsigned long s;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_get_sqty");
+
+ status = acpi_evaluate_integer(device->handle, METHOD_HKEY_SQTY,
+ NULL, &s);
+ if (ACPI_SUCCESS(status))
+ return s;
+ else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "evaluation error HKEY.SQTY\n"));
+ return -EINVAL;
+ }
+}
+
+static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf)
+{
+ acpi_status status;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ union acpi_object *hkey = NULL;
+ int i;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_retrieve_biosdata");
+
+ status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SINF, 0,
+ &buffer);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "evaluation error HKEY.SINF\n"));
+ return 0;
+ }
+
+ hkey = buffer.pointer;
+ if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF\n"));
+ goto end;
+ }
+
+ if (pcc->num_sifr < hkey->package.count) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "SQTY reports bad SINF length\n"));
+ status = AE_ERROR;
+ goto end;
+ }
+
+ for (i = 0; i < hkey->package.count; i++) {
+ union acpi_object *element = &(hkey->package.elements[i]);
+ if (likely(element->type == ACPI_TYPE_INTEGER)) {
+ sinf[i] = element->integer.value;
+ } else
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid HKEY.SINF data\n"));
+ }
+ sinf[hkey->package.count] = -1;
+
+end:
+ kfree(buffer.pointer);
+ return status == AE_OK;
+}
+
+/* backlight API interface functions */
+
+/* This driver currently treats AC and DC brightness identical,
+ * since we don't need to invent an interface to the core ACPI
+ * logic to receive events in case a power supply is plugged in
+ * or removed */
+
+static int bl_get(struct backlight_device *bd)
+{
+ struct pcc_acpi *pcc = bl_get_data(bd);
+
+ if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+ return -EIO;
+
+ return pcc->sinf[SINF_AC_CUR_BRIGHT];
+}
+
+static int bl_set_status(struct backlight_device *bd)
+{
+ struct pcc_acpi *pcc = bl_get_data(bd);
+ int bright = bd->props.brightness;
+ int rc;
+
+ if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+ return -EIO;
+
+ if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT])
+ bright = pcc->sinf[SINF_AC_MIN_BRIGHT];
+
+ if (bright < pcc->sinf[SINF_DC_MIN_BRIGHT])
+ bright = pcc->sinf[SINF_DC_MIN_BRIGHT];
+
+ if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT] ||
+ bright > pcc->sinf[SINF_AC_MAX_BRIGHT])
+ return -EINVAL;
+
+ rc = acpi_pcc_write_sset(pcc, SINF_AC_CUR_BRIGHT, bright);
+ if (rc < 0)
+ return rc;
+
+ return acpi_pcc_write_sset(pcc, SINF_DC_CUR_BRIGHT, bright);
+}
+
+static struct backlight_ops pcc_backlight_ops = {
+ .get_brightness = bl_get,
+ .update_status = bl_set_status,
+};
+
+
+/* sysfs user interface functions */
+
+static ssize_t show_numbatt(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct acpi_device *acpi = to_acpi_device(dev);
+ struct pcc_acpi *pcc = acpi_driver_data(acpi);
+
+ if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+ return -EIO;
+
+ return sprintf(buf, "%u\n", pcc->sinf[SINF_NUM_BATTERIES]);
+}
+
+static ssize_t show_lcdtype(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct acpi_device *acpi = to_acpi_device(dev);
+ struct pcc_acpi *pcc = acpi_driver_data(acpi);
+
+ if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+ return -EIO;
+
+ return sprintf(buf, "%u\n", pcc->sinf[SINF_LCD_TYPE]);
+}
+
+static ssize_t show_mute(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct acpi_device *acpi = to_acpi_device(dev);
+ struct pcc_acpi *pcc = acpi_driver_data(acpi);
+
+ if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+ return -EIO;
+
+ return sprintf(buf, "%u\n", pcc->sinf[SINF_MUTE]);
+}
+
+static ssize_t show_sticky(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct acpi_device *acpi = to_acpi_device(dev);
+ struct pcc_acpi *pcc = acpi_driver_data(acpi);
+
+ if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+ return -EIO;
+
+ return sprintf(buf, "%u\n", pcc->sinf[SINF_STICKY_KEY]);
+}
+
+static ssize_t set_sticky(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct acpi_device *acpi = to_acpi_device(dev);
+ struct pcc_acpi *pcc = acpi_driver_data(acpi);
+ int val;
+
+ if (count && sscanf(buf, "%i", &val) == 1 &&
+ (val == 0 || val == 1)) {
+ acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, val);
+ pcc->sticky_mode = val;
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(numbatt, S_IRUGO, show_numbatt, NULL);
+static DEVICE_ATTR(lcdtype, S_IRUGO, show_lcdtype, NULL);
+static DEVICE_ATTR(mute, S_IRUGO, show_mute, NULL);
+static DEVICE_ATTR(sticky_key, S_IRUGO | S_IWUSR, show_sticky, set_sticky);
+
+static struct attribute *pcc_sysfs_entries[] = {
+ &dev_attr_numbatt.attr,
+ &dev_attr_lcdtype.attr,
+ &dev_attr_mute.attr,
+ &dev_attr_sticky_key.attr,
+ NULL,
+};
+
+static struct attribute_group pcc_attr_group = {
+ .name = NULL, /* put in device directory */
+ .attrs = pcc_sysfs_entries,
+};
+
+
+/* hotkey input device driver */
+
+static int pcc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
+{
+ struct pcc_acpi *pcc = input_get_drvdata(dev);
+
+ if (scancode >= ARRAY_SIZE(pcc->keymap))
+ return -EINVAL;
+
+ *keycode = pcc->keymap[scancode];
+
+ return 0;
+}
+
+static int keymap_get_by_keycode(struct pcc_acpi *pcc, int keycode)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++) {
+ if (pcc->keymap[i] == keycode)
+ return i+1;
+ }
+
+ return 0;
+}
+
+static int pcc_setkeycode(struct input_dev *dev, int scancode, int keycode)
+{
+ struct pcc_acpi *pcc = input_get_drvdata(dev);
+ int oldkeycode;
+
+ if (scancode >= ARRAY_SIZE(pcc->keymap))
+ return -EINVAL;
+
+ if (keycode < 0 || keycode > KEY_MAX)
+ return -EINVAL;
+
+ oldkeycode = pcc->keymap[scancode];
+ pcc->keymap[scancode] = keycode;
+
+ set_bit(keycode, dev->keybit);
+
+ if (!keymap_get_by_keycode(pcc, oldkeycode))
+ clear_bit(oldkeycode, dev->keybit);
+
+ return 0;
+}
+
+static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
+{
+ struct input_dev *hotk_input_dev = pcc->input_dev;
+ int rc;
+ int key_code, hkey_num;
+ unsigned long result;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_generate_keyinput");
+
+ rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
+ NULL, &result);
+ if (!ACPI_SUCCESS(rc)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "error getting hotkey status\n"));
+ return;
+ }
+
+ acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result);
+
+ hkey_num = result & 0xf;
+
+ if (hkey_num < 0 || hkey_num > ARRAY_SIZE(pcc->keymap)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "hotkey number out of range: %d\n",
+ hkey_num));
+ return;
+ }
+
+ key_code = pcc->keymap[hkey_num];
+
+ if (key_code != KEY_RESERVED) {
+ int pushed = (result & 0x80) ? TRUE : FALSE;
+
+ input_report_key(hotk_input_dev, key_code, pushed);
+ input_sync(hotk_input_dev);
+ }
+
+ return;
+}
+
+static void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct pcc_acpi *pcc = (struct pcc_acpi *) data;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_notify");
+
+ switch (event) {
+ case HKEY_NOTIFY:
+ acpi_pcc_generate_keyinput(pcc);
+ break;
+ default:
+ /* nothing to do */
+ break;
+ }
+}
+
+static int acpi_pcc_init_input(struct pcc_acpi *pcc)
+{
+ int i, rc;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_init_input");
+
+ pcc->input_dev = input_allocate_device();
+ if (!pcc->input_dev) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Couldn't allocate input device for hotkey"));
+ return -ENOMEM;
+ }
+
+ pcc->input_dev->evbit[0] = BIT(EV_KEY);
+
+ pcc->input_dev->name = ACPI_PCC_DRIVER_NAME;
+ pcc->input_dev->phys = ACPI_PCC_INPUT_PHYS;
+ pcc->input_dev->id.bustype = BUS_HOST;
+ pcc->input_dev->id.vendor = 0x0001;
+ pcc->input_dev->id.product = 0x0001;
+ pcc->input_dev->id.version = 0x0100;
+ pcc->input_dev->getkeycode = pcc_getkeycode;
+ pcc->input_dev->setkeycode = pcc_setkeycode;
+
+ /* load initial keymap */
+ memcpy(pcc->keymap, initial_keymap, sizeof(pcc->keymap));
+
+ for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++)
+ __set_bit(pcc->keymap[i], pcc->input_dev->keybit);
+ __clear_bit(KEY_RESERVED, pcc->input_dev->keybit);
+
+ input_set_drvdata(pcc->input_dev, pcc);
+
+ rc = input_register_device(pcc->input_dev);
+ if (rc < 0)
+ input_free_device(pcc->input_dev);
+
+ return rc;
+}
+
+/* kernel module interface */
+
+static int acpi_pcc_hotkey_resume(struct acpi_device *device)
+{
+ struct pcc_acpi *pcc = acpi_driver_data(device);
+ acpi_status status = AE_OK;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_resume");
+
+ if (device == NULL || pcc == NULL)
+ return -EINVAL;
+
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Sticky mode restore: %d\n",
+ pcc->sticky_mode));
+
+ status = acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, pcc->sticky_mode);
+
+ return status == AE_OK ? 0 : -EINVAL;
+}
+
+static int acpi_pcc_hotkey_add(struct acpi_device *device)
+{
+ acpi_status status;
+ struct pcc_acpi *pcc;
+ int num_sifr, result;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_add");
+
+ if (!device)
+ return -EINVAL;
+
+ num_sifr = acpi_pcc_get_sqty(device);
+
+ if (num_sifr > 255) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "num_sifr too large"));
+ return -ENODEV;
+ }
+
+ pcc = kzalloc(sizeof(struct pcc_acpi), GFP_KERNEL);
+ if (!pcc) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Couldn't allocate mem for pcc"));
+ return -ENOMEM;
+ }
+
+ pcc->sinf = kzalloc(sizeof(u32) * (num_sifr + 1), GFP_KERNEL);
+ if (!pcc->sinf) {
+ result = -ENOMEM;
+ goto out_hotkey;
+ }
+
+ pcc->device = device;
+ pcc->handle = device->handle;
+ pcc->num_sifr = num_sifr;
+ acpi_driver_data(device) = pcc;
+ strcpy(acpi_device_name(device), ACPI_PCC_DEVICE_NAME);
+ strcpy(acpi_device_class(device), ACPI_PCC_CLASS);
+
+ result = acpi_pcc_init_input(pcc);
+ if (result) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error installing keyinput handler\n"));
+ goto out_sinf;
+ }
+
+ /* initialize hotkey input device */
+ status = acpi_install_notify_handler(pcc->handle, ACPI_DEVICE_NOTIFY,
+ acpi_pcc_hotkey_notify, pcc);
+
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error installing notify handler\n"));
+ result = -ENODEV;
+ goto out_input;
+ }
+
+ /* initialize backlight */
+ pcc->backlight = backlight_device_register("panasonic", NULL, pcc,
+ &pcc_backlight_ops);
+ if (IS_ERR(pcc->backlight))
+ goto out_notify;
+
+ if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Couldn't retrieve BIOS data\n"));
+ goto out_backlight;
+ }
+
+ /* read the initial brightness setting from the hardware */
+ pcc->backlight->props.max_brightness =
+ pcc->sinf[SINF_AC_MAX_BRIGHT];
+ pcc->backlight->props.brightness = pcc->sinf[SINF_AC_CUR_BRIGHT];
+
+ /* read the initial sticky key mode from the hardware */
+ pcc->sticky_mode = pcc->sinf[SINF_STICKY_KEY];
+
+ /* add sysfs attributes */
+ result = sysfs_create_group(&device->dev.kobj, &pcc_attr_group);
+ if (result)
+ goto out_backlight;
+
+ return 0;
+
+out_backlight:
+ backlight_device_unregister(pcc->backlight);
+out_notify:
+ acpi_remove_notify_handler(pcc->handle, ACPI_DEVICE_NOTIFY,
+ acpi_pcc_hotkey_notify);
+out_input:
+ input_unregister_device(pcc->input_dev);
+ /* no need to input_free_device() since core input API refcount and
+ * free()s the device */
+out_sinf:
+ kfree(pcc->sinf);
+out_hotkey:
+ kfree(pcc);
+
+ return result;
+}
+
+static int __init acpi_pcc_init(void)
+{
+ int result = 0;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_init");
+
+ if (acpi_disabled)
+ return -ENODEV;
+
+ result = acpi_bus_register_driver(&acpi_pcc_driver);
+ if (result < 0) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error registering hotkey driver\n"));
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
+{
+ struct pcc_acpi *pcc = acpi_driver_data(device);
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_remove");
+
+ if (!device || !pcc)
+ return -EINVAL;
+
+ sysfs_remove_group(&device->dev.kobj, &pcc_attr_group);
+
+ backlight_device_unregister(pcc->backlight);
+
+ acpi_remove_notify_handler(pcc->handle, ACPI_DEVICE_NOTIFY,
+ acpi_pcc_hotkey_notify);
+
+ input_unregister_device(pcc->input_dev);
+ /* no need to input_free_device() since core input API refcount and
+ * free()s the device */
+
+ kfree(pcc->sinf);
+ kfree(pcc);
+
+ return 0;
+}
+
+static void __exit acpi_pcc_exit(void)
+{
+ ACPI_FUNCTION_TRACE("acpi_pcc_exit");
+
+ acpi_bus_unregister_driver(&acpi_pcc_driver);
+}
+
+module_init(acpi_pcc_init);
+module_exit(acpi_pcc_exit);
--
1.5.5.1
From: Matt Mackall <[email protected]>
x86_64 SMP suspend to RAM uses a 10k temporary stack for saving the
kernel state, but only 4k of it is used. Shrink it to 4k.
Signed-off-by: Matt Mackall <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
arch/x86/kernel/acpi/sleep.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index 29cf340..55d10cb 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -21,7 +21,7 @@ unsigned long acpi_realmode_flags;
static unsigned long acpi_realmode;
#if defined(CONFIG_SMP) && defined(CONFIG_64BIT)
-static char temp_stack[10240];
+static char temp_stack[4096];
#endif
/**
--
1.5.5.1
From: Bjorn Helgaas <[email protected]>
pnp_dbg() is equivalent to dev_dbg() except that we can turn it
on at boot-time with the "pnp.debug" kernel parameter, so we don't
have to build a new kernel image.
Signed-off-by: Bjorn Helgaas <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/pnp/core.c | 2 +-
drivers/pnp/isapnp/core.c | 12 ++++++------
drivers/pnp/manager.c | 34 +++++++++++++++++-----------------
drivers/pnp/pnpacpi/core.c | 4 ++--
drivers/pnp/pnpacpi/rsparser.c | 28 ++++++++++++++--------------
drivers/pnp/pnpbios/core.c | 4 ++--
drivers/pnp/pnpbios/rsparser.c | 18 +++++++++---------
drivers/pnp/quirks.c | 2 +-
drivers/pnp/resource.c | 12 ++++++------
drivers/pnp/support.c | 10 +++++-----
10 files changed, 63 insertions(+), 63 deletions(-)
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index 61291b5..5215615 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -200,7 +200,7 @@ int pnp_add_device(struct pnp_dev *dev)
for (id = dev->id; id; id = id->next)
len += scnprintf(buf + len, sizeof(buf) - len, " %s", id->id);
- dev_dbg(&dev->dev, "%s device, IDs%s (%s)\n",
+ pnp_dbg(&dev->dev, "%s device, IDs%s (%s)\n",
dev->protocol->name, buf, dev->active ? "active" : "disabled");
return 0;
}
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index 101a835..bd213ff 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -901,7 +901,7 @@ static int isapnp_get_resources(struct pnp_dev *dev)
{
int i, ret;
- dev_dbg(&dev->dev, "get resources\n");
+ pnp_dbg(&dev->dev, "get resources\n");
pnp_init_resources(dev);
isapnp_cfg_begin(dev->card->number, dev->number);
dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE);
@@ -939,13 +939,13 @@ static int isapnp_set_resources(struct pnp_dev *dev)
struct resource *res;
int tmp;
- dev_dbg(&dev->dev, "set resources\n");
+ pnp_dbg(&dev->dev, "set resources\n");
isapnp_cfg_begin(dev->card->number, dev->number);
dev->active = 1;
for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) {
res = pnp_get_resource(dev, IORESOURCE_IO, tmp);
if (pnp_resource_enabled(res)) {
- dev_dbg(&dev->dev, " set io %d to %#llx\n",
+ pnp_dbg(&dev->dev, " set io %d to %#llx\n",
tmp, (unsigned long long) res->start);
isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1),
res->start);
@@ -957,14 +957,14 @@ static int isapnp_set_resources(struct pnp_dev *dev)
int irq = res->start;
if (irq == 2)
irq = 9;
- dev_dbg(&dev->dev, " set irq %d to %d\n", tmp, irq);
+ pnp_dbg(&dev->dev, " set irq %d to %d\n", tmp, irq);
isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq);
}
}
for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) {
res = pnp_get_resource(dev, IORESOURCE_DMA, tmp);
if (pnp_resource_enabled(res)) {
- dev_dbg(&dev->dev, " set dma %d to %lld\n",
+ pnp_dbg(&dev->dev, " set dma %d to %lld\n",
tmp, (unsigned long long) res->start);
isapnp_write_byte(ISAPNP_CFG_DMA + tmp, res->start);
}
@@ -972,7 +972,7 @@ static int isapnp_set_resources(struct pnp_dev *dev)
for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) {
res = pnp_get_resource(dev, IORESOURCE_MEM, tmp);
if (pnp_resource_enabled(res)) {
- dev_dbg(&dev->dev, " set mem %d to %#llx\n",
+ pnp_dbg(&dev->dev, " set mem %d to %#llx\n",
tmp, (unsigned long long) res->start);
isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3),
(res->start >> 8) & 0xffff);
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index b526eaa..00fd357 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -25,7 +25,7 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
res = pnp_get_resource(dev, IORESOURCE_IO, idx);
if (res) {
- dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx "
+ pnp_dbg(&dev->dev, " io %d already set to %#llx-%#llx "
"flags %#lx\n", idx, (unsigned long long) res->start,
(unsigned long long) res->end, res->flags);
return 0;
@@ -38,7 +38,7 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
if (!rule->size) {
res->flags |= IORESOURCE_DISABLED;
- dev_dbg(&dev->dev, " io %d disabled\n", idx);
+ pnp_dbg(&dev->dev, " io %d disabled\n", idx);
goto __add;
}
@@ -49,7 +49,7 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
res->start += rule->align;
res->end = res->start + rule->size - 1;
if (res->start > rule->max || !rule->align) {
- dev_dbg(&dev->dev, " couldn't assign io %d "
+ pnp_dbg(&dev->dev, " couldn't assign io %d "
"(min %#llx max %#llx)\n", idx,
(unsigned long long) rule->min,
(unsigned long long) rule->max);
@@ -68,7 +68,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
res = pnp_get_resource(dev, IORESOURCE_MEM, idx);
if (res) {
- dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx "
+ pnp_dbg(&dev->dev, " mem %d already set to %#llx-%#llx "
"flags %#lx\n", idx, (unsigned long long) res->start,
(unsigned long long) res->end, res->flags);
return 0;
@@ -90,7 +90,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
if (!rule->size) {
res->flags |= IORESOURCE_DISABLED;
- dev_dbg(&dev->dev, " mem %d disabled\n", idx);
+ pnp_dbg(&dev->dev, " mem %d disabled\n", idx);
goto __add;
}
@@ -101,7 +101,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
res->start += rule->align;
res->end = res->start + rule->size - 1;
if (res->start > rule->max || !rule->align) {
- dev_dbg(&dev->dev, " couldn't assign mem %d "
+ pnp_dbg(&dev->dev, " couldn't assign mem %d "
"(min %#llx max %#llx)\n", idx,
(unsigned long long) rule->min,
(unsigned long long) rule->max);
@@ -126,7 +126,7 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
res = pnp_get_resource(dev, IORESOURCE_IRQ, idx);
if (res) {
- dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n",
+ pnp_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n",
idx, (int) res->start, res->flags);
return 0;
}
@@ -138,7 +138,7 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
if (bitmap_empty(rule->map.bits, PNP_IRQ_NR)) {
res->flags |= IORESOURCE_DISABLED;
- dev_dbg(&dev->dev, " irq %d disabled\n", idx);
+ pnp_dbg(&dev->dev, " irq %d disabled\n", idx);
goto __add;
}
@@ -160,11 +160,11 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
res->start = -1;
res->end = -1;
res->flags |= IORESOURCE_DISABLED;
- dev_dbg(&dev->dev, " irq %d disabled (optional)\n", idx);
+ pnp_dbg(&dev->dev, " irq %d disabled (optional)\n", idx);
goto __add;
}
- dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx);
+ pnp_dbg(&dev->dev, " couldn't assign irq %d\n", idx);
return -EBUSY;
__add:
@@ -184,7 +184,7 @@ static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
res = pnp_get_resource(dev, IORESOURCE_DMA, idx);
if (res) {
- dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n",
+ pnp_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n",
idx, (int) res->start, res->flags);
return 0;
}
@@ -205,7 +205,7 @@ static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
res->start = res->end = MAX_DMA_CHANNELS;
#endif
res->flags |= IORESOURCE_DISABLED;
- dev_dbg(&dev->dev, " disable dma %d\n", idx);
+ pnp_dbg(&dev->dev, " disable dma %d\n", idx);
__add:
pnp_add_dma_resource(dev, res->start, res->flags);
@@ -238,7 +238,7 @@ static int pnp_assign_resources(struct pnp_dev *dev, int set)
int nport = 0, nmem = 0, nirq = 0, ndma = 0;
int ret = 0;
- dev_dbg(&dev->dev, "pnp_assign_resources, try dependent set %d\n", set);
+ pnp_dbg(&dev->dev, "pnp_assign_resources, try dependent set %d\n", set);
mutex_lock(&pnp_res_mutex);
pnp_clean_resource_table(dev);
@@ -270,7 +270,7 @@ static int pnp_assign_resources(struct pnp_dev *dev, int set)
mutex_unlock(&pnp_res_mutex);
if (ret < 0) {
- dev_dbg(&dev->dev, "pnp_assign_resources failed (%d)\n", ret);
+ pnp_dbg(&dev->dev, "pnp_assign_resources failed (%d)\n", ret);
pnp_clean_resource_table(dev);
} else
dbg_pnp_show_resources(dev, "pnp_assign_resources succeeded");
@@ -286,7 +286,7 @@ int pnp_auto_config_dev(struct pnp_dev *dev)
int i, ret;
if (!pnp_can_configure(dev)) {
- dev_dbg(&dev->dev, "configuration not supported\n");
+ pnp_dbg(&dev->dev, "configuration not supported\n");
return -ENODEV;
}
@@ -313,7 +313,7 @@ int pnp_auto_config_dev(struct pnp_dev *dev)
int pnp_start_dev(struct pnp_dev *dev)
{
if (!pnp_can_write(dev)) {
- dev_dbg(&dev->dev, "activation not supported\n");
+ pnp_dbg(&dev->dev, "activation not supported\n");
return -EINVAL;
}
@@ -336,7 +336,7 @@ int pnp_start_dev(struct pnp_dev *dev)
int pnp_stop_dev(struct pnp_dev *dev)
{
if (!pnp_can_disable(dev)) {
- dev_dbg(&dev->dev, "disabling not supported\n");
+ pnp_dbg(&dev->dev, "disabling not supported\n");
return -EINVAL;
}
if (dev->protocol->disable(dev) < 0) {
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 67c651b..b57d9d5 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -75,7 +75,7 @@ static int __init ispnpidacpi(char *id)
static int pnpacpi_get_resources(struct pnp_dev *dev)
{
- dev_dbg(&dev->dev, "get resources\n");
+ pnp_dbg(&dev->dev, "get resources\n");
return pnpacpi_parse_allocated_resource(dev);
}
@@ -86,7 +86,7 @@ static int pnpacpi_set_resources(struct pnp_dev *dev)
int ret;
acpi_status status;
- dev_dbg(&dev->dev, "set resources\n");
+ pnp_dbg(&dev->dev, "set resources\n");
ret = pnpacpi_build_resource_template(dev, &buffer);
if (ret)
return ret;
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 0461d4b..adf1785 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -450,7 +450,7 @@ int pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
acpi_handle handle = dev->data;
acpi_status status;
- dev_dbg(&dev->dev, "parse allocated resources\n");
+ pnp_dbg(&dev->dev, "parse allocated resources\n");
pnp_init_resources(dev);
@@ -736,7 +736,7 @@ int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
acpi_status status;
struct acpipnp_parse_option_s parse_data;
- dev_dbg(&dev->dev, "parse resource options\n");
+ pnp_dbg(&dev->dev, "parse resource options\n");
parse_data.dev = dev;
parse_data.option_flags = 0;
@@ -844,7 +844,7 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev,
if (!pnp_resource_enabled(p)) {
irq->interrupt_count = 0;
- dev_dbg(&dev->dev, " encode irq (%s)\n",
+ pnp_dbg(&dev->dev, " encode irq (%s)\n",
p ? "disabled" : "missing");
return;
}
@@ -856,7 +856,7 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev,
irq->interrupt_count = 1;
irq->interrupts[0] = p->start;
- dev_dbg(&dev->dev, " encode irq %d %s %s %s (%d-byte descriptor)\n",
+ pnp_dbg(&dev->dev, " encode irq %d %s %s %s (%d-byte descriptor)\n",
(int) p->start,
triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
polarity == ACPI_ACTIVE_LOW ? "low" : "high",
@@ -873,7 +873,7 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
if (!pnp_resource_enabled(p)) {
extended_irq->interrupt_count = 0;
- dev_dbg(&dev->dev, " encode extended irq (%s)\n",
+ pnp_dbg(&dev->dev, " encode extended irq (%s)\n",
p ? "disabled" : "missing");
return;
}
@@ -886,7 +886,7 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
extended_irq->interrupt_count = 1;
extended_irq->interrupts[0] = p->start;
- dev_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start,
+ pnp_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start,
triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
polarity == ACPI_ACTIVE_LOW ? "low" : "high",
extended_irq->sharable == ACPI_SHARED ? "shared" : "exclusive");
@@ -900,7 +900,7 @@ static void pnpacpi_encode_dma(struct pnp_dev *dev,
if (!pnp_resource_enabled(p)) {
dma->channel_count = 0;
- dev_dbg(&dev->dev, " encode dma (%s)\n",
+ pnp_dbg(&dev->dev, " encode dma (%s)\n",
p ? "disabled" : "missing");
return;
}
@@ -935,7 +935,7 @@ static void pnpacpi_encode_dma(struct pnp_dev *dev,
dma->channel_count = 1;
dma->channels[0] = p->start;
- dev_dbg(&dev->dev, " encode dma %d "
+ pnp_dbg(&dev->dev, " encode dma %d "
"type %#x transfer %#x master %d\n",
(int) p->start, dma->type, dma->transfer, dma->bus_master);
}
@@ -959,7 +959,7 @@ static void pnpacpi_encode_io(struct pnp_dev *dev,
io->address_length = 0;
}
- dev_dbg(&dev->dev, " encode io %#x-%#x decode %#x\n", io->minimum,
+ pnp_dbg(&dev->dev, " encode io %#x-%#x decode %#x\n", io->minimum,
io->minimum + io->address_length - 1, io->io_decode);
}
@@ -977,7 +977,7 @@ static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
fixed_io->address_length = 0;
}
- dev_dbg(&dev->dev, " encode fixed_io %#x-%#x\n", fixed_io->address,
+ pnp_dbg(&dev->dev, " encode fixed_io %#x-%#x\n", fixed_io->address,
fixed_io->address + fixed_io->address_length - 1);
}
@@ -1000,7 +1000,7 @@ static void pnpacpi_encode_mem24(struct pnp_dev *dev,
memory24->address_length = 0;
}
- dev_dbg(&dev->dev, " encode mem24 %#x-%#x write_protect %#x\n",
+ pnp_dbg(&dev->dev, " encode mem24 %#x-%#x write_protect %#x\n",
memory24->minimum,
memory24->minimum + memory24->address_length - 1,
memory24->write_protect);
@@ -1024,7 +1024,7 @@ static void pnpacpi_encode_mem32(struct pnp_dev *dev,
memory32->alignment = 0;
}
- dev_dbg(&dev->dev, " encode mem32 %#x-%#x write_protect %#x\n",
+ pnp_dbg(&dev->dev, " encode mem32 %#x-%#x write_protect %#x\n",
memory32->minimum,
memory32->minimum + memory32->address_length - 1,
memory32->write_protect);
@@ -1047,7 +1047,7 @@ static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
fixed_memory32->address_length = 0;
}
- dev_dbg(&dev->dev, " encode fixed_mem32 %#x-%#x write_protect %#x\n",
+ pnp_dbg(&dev->dev, " encode fixed_mem32 %#x-%#x write_protect %#x\n",
fixed_memory32->address,
fixed_memory32->address + fixed_memory32->address_length - 1,
fixed_memory32->write_protect);
@@ -1061,7 +1061,7 @@ int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer)
struct acpi_resource *resource = buffer->pointer;
int port = 0, irq = 0, dma = 0, mem = 0;
- dev_dbg(&dev->dev, "encode %d resources\n", res_cnt);
+ pnp_dbg(&dev->dev, "encode %d resources\n", res_cnt);
while (i < res_cnt) {
switch (resource->type) {
case ACPI_RESOURCE_TYPE_IRQ:
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 19a4be1..2f79eb2 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -211,7 +211,7 @@ static int pnpbios_get_resources(struct pnp_dev *dev)
if (!pnpbios_is_dynamic(dev))
return -EPERM;
- dev_dbg(&dev->dev, "get resources\n");
+ pnp_dbg(&dev->dev, "get resources\n");
node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node)
return -1;
@@ -234,7 +234,7 @@ static int pnpbios_set_resources(struct pnp_dev *dev)
if (!pnpbios_is_dynamic(dev))
return -EPERM;
- dev_dbg(&dev->dev, "set resources\n");
+ pnp_dbg(&dev->dev, "set resources\n");
node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node)
return -1;
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index ca56767..87b4f49 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -87,7 +87,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev,
if (!p)
return NULL;
- dev_dbg(&dev->dev, "parse allocated resources\n");
+ pnp_dbg(&dev->dev, "parse allocated resources\n");
pnp_init_resources(dev);
@@ -324,7 +324,7 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
if (!p)
return NULL;
- dev_dbg(&dev->dev, "parse resource options\n");
+ pnp_dbg(&dev->dev, "parse resource options\n");
option_flags = 0;
while ((char *)p < (char *)end) {
@@ -519,7 +519,7 @@ static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p,
p[10] = (len >> 8) & 0xff;
p[11] = ((len >> 8) >> 8) & 0xff;
- dev_dbg(&dev->dev, " encode mem %#lx-%#lx\n", base, base + len - 1);
+ pnp_dbg(&dev->dev, " encode mem %#lx-%#lx\n", base, base + len - 1);
}
static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
@@ -549,7 +549,7 @@ static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
p[18] = (len >> 16) & 0xff;
p[19] = (len >> 24) & 0xff;
- dev_dbg(&dev->dev, " encode mem32 %#lx-%#lx\n", base, base + len - 1);
+ pnp_dbg(&dev->dev, " encode mem32 %#lx-%#lx\n", base, base + len - 1);
}
static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
@@ -575,7 +575,7 @@ static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
p[10] = (len >> 16) & 0xff;
p[11] = (len >> 24) & 0xff;
- dev_dbg(&dev->dev, " encode fixed_mem32 %#lx-%#lx\n", base,
+ pnp_dbg(&dev->dev, " encode fixed_mem32 %#lx-%#lx\n", base,
base + len - 1);
}
@@ -592,7 +592,7 @@ static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p,
p[1] = map & 0xff;
p[2] = (map >> 8) & 0xff;
- dev_dbg(&dev->dev, " encode irq mask %#lx\n", map);
+ pnp_dbg(&dev->dev, " encode irq mask %#lx\n", map);
}
static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p,
@@ -607,7 +607,7 @@ static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p,
p[1] = map & 0xff;
- dev_dbg(&dev->dev, " encode dma mask %#lx\n", map);
+ pnp_dbg(&dev->dev, " encode dma mask %#lx\n", map);
}
static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
@@ -630,7 +630,7 @@ static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
p[5] = (base >> 8) & 0xff;
p[7] = len & 0xff;
- dev_dbg(&dev->dev, " encode io %#lx-%#lx\n", base, base + len - 1);
+ pnp_dbg(&dev->dev, " encode io %#lx-%#lx\n", base, base + len - 1);
}
static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p,
@@ -651,7 +651,7 @@ static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p,
p[2] = (base >> 8) & 0xff;
p[3] = len & 0xff;
- dev_dbg(&dev->dev, " encode fixed_io %#lx-%#lx\n", base,
+ pnp_dbg(&dev->dev, " encode fixed_io %#lx-%#lx\n", base,
base + len - 1);
}
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 414bb09..3d2e560 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -337,7 +337,7 @@ void pnp_fixup_device(struct pnp_dev *dev)
for (f = pnp_fixups; *f->id; f++) {
if (!compare_pnp_id(dev->id, f->id))
continue;
- dev_dbg(&dev->dev, "%s: calling %pF\n", f->id,
+ pnp_dbg(&dev->dev, "%s: calling %pF\n", f->id,
f->quirk_function);
f->quirk_function(dev);
}
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index e0206da..5ef463d 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -294,7 +294,7 @@ static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
u8 progif;
if (pci->irq == irq) {
- dev_dbg(&pnp->dev, " device %s using irq %d\n",
+ pnp_dbg(&pnp->dev, " device %s using irq %d\n",
pci_name(pci), irq);
return 1;
}
@@ -316,7 +316,7 @@ static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
if ((progif & 0x5) != 0x5)
if (pci_get_legacy_ide_irq(pci, 0) == irq ||
pci_get_legacy_ide_irq(pci, 1) == irq) {
- dev_dbg(&pnp->dev, " legacy IDE device %s "
+ pnp_dbg(&pnp->dev, " legacy IDE device %s "
"using irq %d\n", pci_name(pci), irq);
return 1;
}
@@ -517,7 +517,7 @@ struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
res->start = irq;
res->end = irq;
- dev_dbg(&dev->dev, " add irq %d flags %#x\n", irq, flags);
+ pnp_dbg(&dev->dev, " add irq %d flags %#x\n", irq, flags);
return pnp_res;
}
@@ -538,7 +538,7 @@ struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
res->start = dma;
res->end = dma;
- dev_dbg(&dev->dev, " add dma %d flags %#x\n", dma, flags);
+ pnp_dbg(&dev->dev, " add dma %d flags %#x\n", dma, flags);
return pnp_res;
}
@@ -562,7 +562,7 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
res->start = start;
res->end = end;
- dev_dbg(&dev->dev, " add io %#llx-%#llx flags %#x\n",
+ pnp_dbg(&dev->dev, " add io %#llx-%#llx flags %#x\n",
(unsigned long long) start, (unsigned long long) end, flags);
return pnp_res;
}
@@ -587,7 +587,7 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
res->start = start;
res->end = end;
- dev_dbg(&dev->dev, " add mem %#llx-%#llx flags %#x\n",
+ pnp_dbg(&dev->dev, " add mem %#llx-%#llx flags %#x\n",
(unsigned long long) start, (unsigned long long) end, flags);
return pnp_res;
}
diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c
index 7149186..63087d5 100644
--- a/drivers/pnp/support.c
+++ b/drivers/pnp/support.c
@@ -81,11 +81,11 @@ void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
struct resource *res;
if (list_empty(&dev->resources)) {
- dev_dbg(&dev->dev, "%s: no current resources\n", desc);
+ pnp_dbg(&dev->dev, "%s: no current resources\n", desc);
return;
}
- dev_dbg(&dev->dev, "%s: current resources:\n", desc);
+ pnp_dbg(&dev->dev, "%s: current resources:\n", desc);
list_for_each_entry(pnp_res, &dev->resources, list) {
res = &pnp_res->res;
len = 0;
@@ -94,7 +94,7 @@ void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
pnp_resource_type_name(res));
if (res->flags & IORESOURCE_DISABLED) {
- dev_dbg(&dev->dev, "%sdisabled\n", buf);
+ pnp_dbg(&dev->dev, "%sdisabled\n", buf);
continue;
}
@@ -115,7 +115,7 @@ void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
res->flags);
break;
}
- dev_dbg(&dev->dev, "%s\n", buf);
+ pnp_dbg(&dev->dev, "%s\n", buf);
}
}
@@ -205,5 +205,5 @@ void dbg_pnp_show_option(struct pnp_dev *dev, struct pnp_option *option)
"flags %#x", dma->map, dma->flags);
break;
}
- dev_dbg(&dev->dev, "%s\n", buf);
+ pnp_dbg(&dev->dev, "%s\n", buf);
}
--
1.5.5.1
From: Shaohua Li <[email protected]>
an ATA bay can be in a dock and itself can be ejected separately.
This patch handles such eject bay. Found by Holger.
Signed-off-by: Shaohua Li <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/dock.c | 14 ++++++++++----
1 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index ac7dfef..c877cc5 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -609,6 +609,7 @@ register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops,
{
struct dock_dependent_device *dd;
struct dock_station *dock_station;
+ int ret = -EINVAL;
if (!dock_station_count)
return -ENODEV;
@@ -618,16 +619,21 @@ register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops,
* this would include the dock station itself
*/
list_for_each_entry(dock_station, &dock_stations, sibiling) {
+ /*
+ * An ATA bay can be in a dock and itself can be ejected
+ * seperately, so there are two 'dock stations' which need the
+ * ops
+ */
dd = find_dock_dependent_device(dock_station, handle);
if (dd) {
dd->ops = ops;
dd->context = context;
dock_add_hotplug_device(dock_station, dd);
- return 0;
+ ret = 0;
}
}
- return -EINVAL;
+ return ret;
}
EXPORT_SYMBOL_GPL(register_hotplug_dock_device);
@@ -1078,8 +1084,8 @@ find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
static acpi_status
find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
{
- /* If bay is in a dock, it's already handled */
- if (is_ejectable_bay(handle) && !is_dock_device(handle))
+ /* If bay is a dock, it's already handled */
+ if (is_ejectable_bay(handle) && !is_dock(handle))
dock_add(handle);
return AE_OK;
}
--
1.5.5.1
From: Thomas Renninger <[email protected]>
lenb: stripped patch down to what still applied to new dock.c
Signed-off-by: Thomas Renninger <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/dock.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index b7d1581..913bb1e 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -488,8 +488,9 @@ static void handle_dock(struct dock_station *ds, int dock)
arg.integer.value = dock;
status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
- printk(KERN_ERR PREFIX "%s - failed to execute _DCK\n",
- (char *)name_buffer.pointer);
+ ACPI_EXCEPTION((AE_INFO, status, "%s - failed to execute"
+ " _DCK\n", (char *)name_buffer.pointer));
+
kfree(buffer.pointer);
kfree(name_buffer.pointer);
}
--
1.5.5.1
From: Thomas Renninger <[email protected]>
Signed-off-by: Thomas Renninger <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/video.c | 11 +++++------
1 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index e8a51a1..d758944 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -1530,8 +1530,8 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
acpi_video_device_notify,
data);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Error installing notify handler"));
if(data->brightness)
kfree(data->brightness->levels);
kfree(data->brightness);
@@ -1745,8 +1745,7 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video,
status = acpi_video_bus_get_one_device(dev, video);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Cant attach device"));
+ printk(KERN_ERR "Cant attach device [%d]\n", status);
continue;
}
}
@@ -2003,8 +2002,8 @@ static int acpi_video_bus_add(struct acpi_device *device)
ACPI_DEVICE_NOTIFY,
acpi_video_bus_notify, video);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Error installing notify handler"));
error = -ENODEV;
goto err_stop_video;
}
--
1.5.5.1
From: Len Brown <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/scan.c | 14 --------------
1 files changed, 0 insertions(+), 14 deletions(-)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 89c112e..91fed42 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1161,20 +1161,6 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
}
static int
-acpi_is_child_device(struct acpi_device *device,
- int (*matcher)(struct acpi_device *))
-{
- int result = -ENODEV;
-
- do {
- if (ACPI_SUCCESS(matcher(device)))
- return AE_OK;
- } while ((device = device->parent));
-
- return result;
-}
-
-static int
acpi_add_single_object(struct acpi_device **child,
struct acpi_device *parent, acpi_handle handle, int type,
struct acpi_bus_ops *ops)
--
1.5.5.1
From: Matthew Garrett <[email protected]>
eeepc-laptop currently only sends key events via ACPI and has
non-standard rfkill control. Add an input device and use the rfkill
infrastructure.
Signed-off-by: Matthew Garrett <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/misc/eeepc-laptop.c | 228 +++++++++++++++++++++++++++++++++++++++----
1 files changed, 209 insertions(+), 19 deletions(-)
diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c
index 1ee8501..5baa10b 100644
--- a/drivers/misc/eeepc-laptop.c
+++ b/drivers/misc/eeepc-laptop.c
@@ -28,6 +28,8 @@
#include <acpi/acpi_drivers.h>
#include <acpi/acpi_bus.h>
#include <linux/uaccess.h>
+#include <linux/input.h>
+#include <linux/rfkill.h>
#define EEEPC_LAPTOP_VERSION "0.1"
@@ -125,6 +127,10 @@ struct eeepc_hotk {
by this BIOS */
uint init_flag; /* Init flags */
u16 event_count[128]; /* count for each event */
+ struct input_dev *inputdev;
+ u16 *keycode_map;
+ struct rfkill *eeepc_wlan_rfkill;
+ struct rfkill *eeepc_bluetooth_rfkill;
};
/* The actual device the driver binds to */
@@ -140,6 +146,27 @@ static struct platform_driver platform_driver = {
static struct platform_device *platform_device;
+struct key_entry {
+ char type;
+ u8 code;
+ u16 keycode;
+};
+
+enum { KE_KEY, KE_END };
+
+static struct key_entry eeepc_keymap[] = {
+ /* Sleep already handled via generic ACPI code */
+ {KE_KEY, 0x10, KEY_WLAN },
+ {KE_KEY, 0x12, KEY_PROG1 },
+ {KE_KEY, 0x13, KEY_MUTE },
+ {KE_KEY, 0x14, KEY_VOLUMEDOWN },
+ {KE_KEY, 0x15, KEY_VOLUMEUP },
+ {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
+ {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
+ {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
+ {KE_END, 0},
+};
+
/*
* The hotkey driver declaration
*/
@@ -261,6 +288,44 @@ static int update_bl_status(struct backlight_device *bd)
}
/*
+ * Rfkill helpers
+ */
+
+static int eeepc_wlan_rfkill_set(void *data, enum rfkill_state state)
+{
+ if (state == RFKILL_STATE_SOFT_BLOCKED)
+ return set_acpi(CM_ASL_WLAN, 0);
+ else
+ return set_acpi(CM_ASL_WLAN, 1);
+}
+
+static int eeepc_wlan_rfkill_state(void *data, enum rfkill_state *state)
+{
+ if (get_acpi(CM_ASL_WLAN) == 1)
+ *state = RFKILL_STATE_UNBLOCKED;
+ else
+ *state = RFKILL_STATE_SOFT_BLOCKED;
+ return 0;
+}
+
+static int eeepc_bluetooth_rfkill_set(void *data, enum rfkill_state state)
+{
+ if (state == RFKILL_STATE_SOFT_BLOCKED)
+ return set_acpi(CM_ASL_BLUETOOTH, 0);
+ else
+ return set_acpi(CM_ASL_BLUETOOTH, 1);
+}
+
+static int eeepc_bluetooth_rfkill_state(void *data, enum rfkill_state *state)
+{
+ if (get_acpi(CM_ASL_BLUETOOTH) == 1)
+ *state = RFKILL_STATE_UNBLOCKED;
+ else
+ *state = RFKILL_STATE_SOFT_BLOCKED;
+ return 0;
+}
+
+/*
* Sys helpers
*/
static int parse_arg(const char *buf, unsigned long count, int *val)
@@ -311,13 +376,11 @@ static ssize_t show_sys_acpi(int cm, char *buf)
EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
-EEEPC_CREATE_DEVICE_ATTR(wlan, CM_ASL_WLAN);
static struct attribute *platform_attributes[] = {
&dev_attr_camera.attr,
&dev_attr_cardr.attr,
&dev_attr_disp.attr,
- &dev_attr_wlan.attr,
NULL
};
@@ -328,8 +391,64 @@ static struct attribute_group platform_attribute_group = {
/*
* Hotkey functions
*/
+static struct key_entry *eepc_get_entry_by_scancode(int code)
+{
+ struct key_entry *key;
+
+ for (key = eeepc_keymap; key->type != KE_END; key++)
+ if (code == key->code)
+ return key;
+
+ return NULL;
+}
+
+static struct key_entry *eepc_get_entry_by_keycode(int code)
+{
+ struct key_entry *key;
+
+ for (key = eeepc_keymap; key->type != KE_END; key++)
+ if (code == key->keycode && key->type == KE_KEY)
+ return key;
+
+ return NULL;
+}
+
+static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
+{
+ struct key_entry *key = eepc_get_entry_by_scancode(scancode);
+
+ if (key && key->type == KE_KEY) {
+ *keycode = key->keycode;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
+{
+ struct key_entry *key;
+ int old_keycode;
+
+ if (keycode < 0 || keycode > KEY_MAX)
+ return -EINVAL;
+
+ key = eepc_get_entry_by_scancode(scancode);
+ if (key && key->type == KE_KEY) {
+ old_keycode = key->keycode;
+ key->keycode = keycode;
+ set_bit(keycode, dev->keybit);
+ if (!eepc_get_entry_by_keycode(old_keycode))
+ clear_bit(old_keycode, dev->keybit);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
static int eeepc_hotk_check(void)
{
+ const struct key_entry *key;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
int result;
@@ -356,6 +475,31 @@ static int eeepc_hotk_check(void)
"Get control methods supported: 0x%x\n",
ehotk->cm_supported);
}
+ ehotk->inputdev = input_allocate_device();
+ if (!ehotk->inputdev) {
+ printk(EEEPC_INFO "Unable to allocate input device\n");
+ return 0;
+ }
+ ehotk->inputdev->name = "Asus EeePC extra buttons";
+ ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0";
+ ehotk->inputdev->id.bustype = BUS_HOST;
+ ehotk->inputdev->getkeycode = eeepc_getkeycode;
+ ehotk->inputdev->setkeycode = eeepc_setkeycode;
+
+ for (key = eeepc_keymap; key->type != KE_END; key++) {
+ switch (key->type) {
+ case KE_KEY:
+ set_bit(EV_KEY, ehotk->inputdev->evbit);
+ set_bit(key->keycode, ehotk->inputdev->keybit);
+ break;
+ }
+ }
+ result = input_register_device(ehotk->inputdev);
+ if (result) {
+ printk(EEEPC_INFO "Unable to register input device\n");
+ input_free_device(ehotk->inputdev);
+ return 0;
+ }
} else {
printk(EEEPC_ERR "Hotkey device not present, aborting\n");
return -EINVAL;
@@ -363,21 +507,6 @@ static int eeepc_hotk_check(void)
return 0;
}
-static void notify_wlan(u32 *event)
-{
- /* if DISABLE_ASL_WLAN is set, the notify code for fn+f2
- will always be 0x10 */
- if (ehotk->cm_supported & (0x1 << CM_ASL_WLAN)) {
- const char *method = cm_getv[CM_ASL_WLAN];
- int value;
- if (read_acpi_int(ehotk->handle, method, &value))
- printk(EEEPC_WARNING "Error reading %s\n",
- method);
- else if (value == 1)
- *event = 0x11;
- }
-}
-
static void notify_brn(void)
{
struct backlight_device *bd = eeepc_backlight_device;
@@ -386,14 +515,28 @@ static void notify_brn(void)
static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
{
+ static struct key_entry *key;
if (!ehotk)
return;
- if (event == NOTIFY_WLAN_ON && (DISABLE_ASL_WLAN & ehotk->init_flag))
- notify_wlan(&event);
if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
notify_brn();
acpi_bus_generate_proc_event(ehotk->device, event,
ehotk->event_count[event % 128]++);
+ if (ehotk->inputdev) {
+ key = eepc_get_entry_by_scancode(event);
+ if (key) {
+ switch (key->type) {
+ case KE_KEY:
+ input_report_key(ehotk->inputdev, key->keycode,
+ 1);
+ input_sync(ehotk->inputdev);
+ input_report_key(ehotk->inputdev, key->keycode,
+ 0);
+ input_sync(ehotk->inputdev);
+ break;
+ }
+ }
+ }
}
static int eeepc_hotk_add(struct acpi_device *device)
@@ -420,6 +563,47 @@ static int eeepc_hotk_add(struct acpi_device *device)
eeepc_hotk_notify, ehotk);
if (ACPI_FAILURE(status))
printk(EEEPC_ERR "Error installing notify handler\n");
+
+ if (get_acpi(CM_ASL_WLAN) != -1) {
+ ehotk->eeepc_wlan_rfkill = rfkill_allocate(&device->dev,
+ RFKILL_TYPE_WLAN);
+
+ if (!ehotk->eeepc_wlan_rfkill)
+ goto end;
+
+ ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan";
+ ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set;
+ ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state;
+ if (get_acpi(CM_ASL_WLAN) == 1)
+ ehotk->eeepc_wlan_rfkill->state =
+ RFKILL_STATE_UNBLOCKED;
+ else
+ ehotk->eeepc_wlan_rfkill->state =
+ RFKILL_STATE_SOFT_BLOCKED;
+ rfkill_register(ehotk->eeepc_wlan_rfkill);
+ }
+
+ if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
+ ehotk->eeepc_bluetooth_rfkill =
+ rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH);
+
+ if (!ehotk->eeepc_bluetooth_rfkill)
+ goto end;
+
+ ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth";
+ ehotk->eeepc_bluetooth_rfkill->toggle_radio =
+ eeepc_bluetooth_rfkill_set;
+ ehotk->eeepc_bluetooth_rfkill->get_state =
+ eeepc_bluetooth_rfkill_state;
+ if (get_acpi(CM_ASL_BLUETOOTH) == 1)
+ ehotk->eeepc_bluetooth_rfkill->state =
+ RFKILL_STATE_UNBLOCKED;
+ else
+ ehotk->eeepc_bluetooth_rfkill->state =
+ RFKILL_STATE_SOFT_BLOCKED;
+ rfkill_register(ehotk->eeepc_bluetooth_rfkill);
+ }
+
end:
if (result) {
kfree(ehotk);
@@ -553,6 +737,12 @@ static void eeepc_backlight_exit(void)
{
if (eeepc_backlight_device)
backlight_device_unregister(eeepc_backlight_device);
+ if (ehotk->inputdev)
+ input_unregister_device(ehotk->inputdev);
+ if (ehotk->eeepc_wlan_rfkill)
+ rfkill_unregister(ehotk->eeepc_wlan_rfkill);
+ if (ehotk->eeepc_bluetooth_rfkill)
+ rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
eeepc_backlight_device = NULL;
}
--
1.5.5.1
From: Alexey Starikovskiy <[email protected]>
It is easier and faster to do transaction directly from interrupt context
rather than waking control thread.
Also, cleaner GPE storm avoidance is implemented.
References: http://bugzilla.kernel.org/show_bug.cgi?id=9998
http://bugzilla.kernel.org/show_bug.cgi?id=10724
http://bugzilla.kernel.org/show_bug.cgi?id=10919
http://bugzilla.kernel.org/show_bug.cgi?id=11309
http://bugzilla.kernel.org/show_bug.cgi?id=11549
Signed-off-by: Alexey Starikovskiy <[email protected]>
Tested-by: Sitsofe Wheeler <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/ec.c | 309 +++++++++++++++++++++++++---------------------------
1 files changed, 149 insertions(+), 160 deletions(-)
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 13593f9..7f0d81c 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -1,7 +1,7 @@
/*
- * ec.c - ACPI Embedded Controller Driver (v2.0)
+ * ec.c - ACPI Embedded Controller Driver (v2.1)
*
- * Copyright (C) 2006, 2007 Alexey Starikovskiy <[email protected]>
+ * Copyright (C) 2006-2008 Alexey Starikovskiy <[email protected]>
* Copyright (C) 2006 Denis Sadykov <[email protected]>
* Copyright (C) 2004 Luming Yu <[email protected]>
* Copyright (C) 2001, 2002 Andy Grover <[email protected]>
@@ -26,7 +26,7 @@
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
-/* Uncomment next line to get verbose print outs*/
+/* Uncomment next line to get verbose printout */
/* #define DEBUG */
#include <linux/kernel.h>
@@ -38,6 +38,7 @@
#include <linux/seq_file.h>
#include <linux/interrupt.h>
#include <linux/list.h>
+#include <linux/spinlock.h>
#include <asm/io.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
@@ -65,22 +66,21 @@ enum ec_command {
ACPI_EC_COMMAND_QUERY = 0x84,
};
-/* EC events */
-enum ec_event {
- ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */
- ACPI_EC_EVENT_IBF_0, /* Input buffer empty */
-};
-
#define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */
#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
#define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */
+#define ACPI_EC_STORM_THRESHOLD 20 /* number of false interrupts
+ per one transaction */
+
enum {
- EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */
EC_FLAGS_QUERY_PENDING, /* Query is pending */
- EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */
+ EC_FLAGS_GPE_MODE, /* Expect GPE to be sent
+ * for status change */
EC_FLAGS_NO_GPE, /* Don't use GPE mode */
- EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */
+ EC_FLAGS_GPE_STORM, /* GPE storm detected */
+ EC_FLAGS_HANDLERS_INSTALLED /* Handlers for GPE and
+ * OpReg are installed */
};
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
@@ -95,6 +95,14 @@ struct acpi_ec_query_handler {
u8 query_bit;
};
+struct transaction_data {
+ const u8 *wdata;
+ u8 *rdata;
+ unsigned short irq_count;
+ u8 wlen;
+ u8 rlen;
+};
+
static struct acpi_ec {
acpi_handle handle;
unsigned long gpe;
@@ -105,9 +113,8 @@ static struct acpi_ec {
struct mutex lock;
wait_queue_head_t wait;
struct list_head list;
- struct delayed_work work;
- atomic_t irq_count;
- u8 handlers_installed;
+ struct transaction_data *t;
+ spinlock_t t_lock;
} *boot_ec, *first_ec;
/*
@@ -150,7 +157,7 @@ static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
{
u8 x = inb(ec->data_addr);
pr_debug(PREFIX "---> data = 0x%2.2x\n", x);
- return inb(ec->data_addr);
+ return x;
}
static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command)
@@ -165,68 +172,79 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
outb(data, ec->data_addr);
}
-static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
+static int ec_transaction_done(struct acpi_ec *ec)
{
- if (test_bit(EC_FLAGS_WAIT_GPE, &ec->flags))
- return 0;
- if (event == ACPI_EC_EVENT_OBF_1) {
- if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_OBF)
- return 1;
- } else if (event == ACPI_EC_EVENT_IBF_0) {
- if (!(acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF))
- return 1;
- }
-
- return 0;
+ unsigned long flags;
+ int ret = 0;
+ spin_lock_irqsave(&ec->t_lock, flags);
+ if (!ec->t || (!ec->t->wlen && !ec->t->rlen))
+ ret = 1;
+ spin_unlock_irqrestore(&ec->t_lock, flags);
+ return ret;
}
-static void ec_schedule_ec_poll(struct acpi_ec *ec)
+static void gpe_transaction(struct acpi_ec *ec, u8 status)
{
- if (test_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags))
- schedule_delayed_work(&ec->work,
- msecs_to_jiffies(ACPI_EC_DELAY));
+ unsigned long flags;
+ spin_lock_irqsave(&ec->t_lock, flags);
+ if (!ec->t)
+ goto unlock;
+ if (ec->t->wlen > 0) {
+ if ((status & ACPI_EC_FLAG_IBF) == 0) {
+ acpi_ec_write_data(ec, *(ec->t->wdata++));
+ --ec->t->wlen;
+ } else
+ /* false interrupt, state didn't change */
+ ++ec->t->irq_count;
+
+ } else if (ec->t->rlen > 0) {
+ if ((status & ACPI_EC_FLAG_OBF) == 1) {
+ *(ec->t->rdata++) = acpi_ec_read_data(ec);
+ --ec->t->rlen;
+ } else
+ /* false interrupt, state didn't change */
+ ++ec->t->irq_count;
+ }
+unlock:
+ spin_unlock_irqrestore(&ec->t_lock, flags);
}
-static void ec_switch_to_poll_mode(struct acpi_ec *ec)
+static int acpi_ec_wait(struct acpi_ec *ec)
{
+ if (wait_event_timeout(ec->wait, ec_transaction_done(ec),
+ msecs_to_jiffies(ACPI_EC_DELAY)))
+ return 0;
+ /* missing GPEs, switch back to poll mode */
+ if (printk_ratelimit())
+ pr_info(PREFIX "missing confirmations, "
+ "switch off interrupt mode.\n");
set_bit(EC_FLAGS_NO_GPE, &ec->flags);
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
- acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
- set_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags);
+ return 1;
}
-static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
+static void acpi_ec_gpe_query(void *ec_cxt);
+
+static int ec_check_sci(struct acpi_ec *ec, u8 state)
{
- atomic_set(&ec->irq_count, 0);
- if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) &&
- likely(!force_poll)) {
- if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event),
- msecs_to_jiffies(ACPI_EC_DELAY)))
- return 0;
- clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
- if (acpi_ec_check_status(ec, event)) {
- /* missing GPEs, switch back to poll mode */
- if (printk_ratelimit())
- pr_info(PREFIX "missing confirmations, "
- "switch off interrupt mode.\n");
- ec_switch_to_poll_mode(ec);
- ec_schedule_ec_poll(ec);
- return 0;
- }
- } else {
- unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
- clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
- while (time_before(jiffies, delay)) {
- if (acpi_ec_check_status(ec, event))
- return 0;
- msleep(1);
- }
- if (acpi_ec_check_status(ec,event))
+ if (state & ACPI_EC_FLAG_SCI) {
+ if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
+ return acpi_os_execute(OSL_EC_BURST_HANDLER,
+ acpi_ec_gpe_query, ec);
+ }
+ return 0;
+}
+
+static int ec_poll(struct acpi_ec *ec)
+{
+ unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
+ msleep(1);
+ while (time_before(jiffies, delay)) {
+ gpe_transaction(ec, acpi_ec_read_status(ec));
+ msleep(1);
+ if (ec_transaction_done(ec))
return 0;
}
- pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n",
- acpi_ec_read_status(ec),
- (event == ACPI_EC_EVENT_OBF_1) ? "\"b0=1\"" : "\"b1=0\"");
return -ETIME;
}
@@ -235,45 +253,51 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
u8 * rdata, unsigned rdata_len,
int force_poll)
{
- int result = 0;
- set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
+ unsigned long tmp;
+ struct transaction_data t = {.wdata = wdata, .rdata = rdata,
+ .wlen = wdata_len, .rlen = rdata_len,
+ .irq_count = 0};
+ int ret = 0;
pr_debug(PREFIX "transaction start\n");
- acpi_ec_write_cmd(ec, command);
- for (; wdata_len > 0; --wdata_len) {
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
- if (result) {
- pr_err(PREFIX
- "write_cmd timeout, command = %d\n", command);
- goto end;
- }
- set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
- acpi_ec_write_data(ec, *(wdata++));
+ /* disable GPE during transaction if storm is detected */
+ if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
+ clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
+ acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
}
-
- if (!rdata_len) {
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
- if (result) {
- pr_err(PREFIX
- "finish-write timeout, command = %d\n", command);
- goto end;
- }
- } else if (command == ACPI_EC_COMMAND_QUERY)
+ /* start transaction */
+ spin_lock_irqsave(&ec->t_lock, tmp);
+ /* following two actions should be kept atomic */
+ ec->t = &t;
+ acpi_ec_write_cmd(ec, command);
+ if (command == ACPI_EC_COMMAND_QUERY)
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
-
- for (; rdata_len > 0; --rdata_len) {
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll);
- if (result) {
- pr_err(PREFIX "read timeout, command = %d\n", command);
- goto end;
- }
- /* Don't expect GPE after last read */
- if (rdata_len > 1)
- set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
- *(rdata++) = acpi_ec_read_data(ec);
- }
- end:
+ spin_unlock_irqrestore(&ec->t_lock, tmp);
+ /* if we selected poll mode or failed in GPE-mode do a poll loop */
+ if (force_poll ||
+ !test_bit(EC_FLAGS_GPE_MODE, &ec->flags) ||
+ acpi_ec_wait(ec))
+ ret = ec_poll(ec);
pr_debug(PREFIX "transaction end\n");
- return result;
+ spin_lock_irqsave(&ec->t_lock, tmp);
+ ec->t = NULL;
+ spin_unlock_irqrestore(&ec->t_lock, tmp);
+ if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
+ /* check if we received SCI during transaction */
+ ec_check_sci(ec, acpi_ec_read_status(ec));
+ /* it is safe to enable GPE outside of transaction */
+ acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
+ } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
+ t.irq_count > ACPI_EC_STORM_THRESHOLD) {
+ pr_debug(PREFIX "GPE storm detected\n");
+ set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
+ }
+ return ret;
+}
+
+static int ec_check_ibf0(struct acpi_ec *ec)
+{
+ u8 status = acpi_ec_read_status(ec);
+ return (status & ACPI_EC_FLAG_IBF) == 0;
}
static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
@@ -283,40 +307,34 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
{
int status;
u32 glk;
-
if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata))
return -EINVAL;
-
if (rdata)
memset(rdata, 0, rdata_len);
-
mutex_lock(&ec->lock);
if (ec->global_lock) {
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
if (ACPI_FAILURE(status)) {
- mutex_unlock(&ec->lock);
- return -ENODEV;
+ status = -ENODEV;
+ goto unlock;
}
}
-
- status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0);
- if (status) {
+ if (!wait_event_timeout(ec->wait, ec_check_ibf0(ec),
+ msecs_to_jiffies(ACPI_EC_DELAY))) {
pr_err(PREFIX "input buffer is not empty, "
"aborting transaction\n");
+ status = -ETIME;
goto end;
}
-
status = acpi_ec_transaction_unlocked(ec, command,
wdata, wdata_len,
rdata, rdata_len,
force_poll);
-
- end:
-
+end:
if (ec->global_lock)
acpi_release_global_lock(glk);
+unlock:
mutex_unlock(&ec->lock);
-
return status;
}
@@ -332,7 +350,9 @@ int acpi_ec_burst_enable(struct acpi_ec *ec)
int acpi_ec_burst_disable(struct acpi_ec *ec)
{
- return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0, 0);
+ return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ?
+ acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE,
+ NULL, 0, NULL, 0, 0) : 0;
}
static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
@@ -513,46 +533,26 @@ static void acpi_ec_gpe_query(void *ec_cxt)
static u32 acpi_ec_gpe_handler(void *data)
{
- acpi_status status = AE_OK;
struct acpi_ec *ec = data;
- u8 state = acpi_ec_read_status(ec);
+ u8 status;
pr_debug(PREFIX "~~~> interrupt\n");
- atomic_inc(&ec->irq_count);
- if (atomic_read(&ec->irq_count) > 5) {
- pr_err(PREFIX "GPE storm detected, disabling EC GPE\n");
- ec_switch_to_poll_mode(ec);
- goto end;
- }
- clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
- if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))
+ status = acpi_ec_read_status(ec);
+
+ gpe_transaction(ec, status);
+ if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0)
wake_up(&ec->wait);
- if (state & ACPI_EC_FLAG_SCI) {
- if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
- status = acpi_os_execute(OSL_EC_BURST_HANDLER,
- acpi_ec_gpe_query, ec);
- } else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
- !test_bit(EC_FLAGS_NO_GPE, &ec->flags) &&
- in_interrupt()) {
+ ec_check_sci(ec, status);
+ if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
+ !test_bit(EC_FLAGS_NO_GPE, &ec->flags)) {
/* this is non-query, must be confirmation */
if (printk_ratelimit())
pr_info(PREFIX "non-query interrupt received,"
" switching to interrupt mode\n");
set_bit(EC_FLAGS_GPE_MODE, &ec->flags);
- clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags);
}
-end:
- ec_schedule_ec_poll(ec);
- return ACPI_SUCCESS(status) ?
- ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
-}
-
-static void do_ec_poll(struct work_struct *work)
-{
- struct acpi_ec *ec = container_of(work, struct acpi_ec, work.work);
- atomic_set(&ec->irq_count, 0);
- (void)acpi_ec_gpe_handler(ec);
+ return ACPI_INTERRUPT_HANDLED;
}
/* --------------------------------------------------------------------------
@@ -696,8 +696,7 @@ static struct acpi_ec *make_acpi_ec(void)
mutex_init(&ec->lock);
init_waitqueue_head(&ec->wait);
INIT_LIST_HEAD(&ec->list);
- INIT_DELAYED_WORK_DEFERRABLE(&ec->work, do_ec_poll);
- atomic_set(&ec->irq_count, 0);
+ spin_lock_init(&ec->t_lock);
return ec;
}
@@ -736,22 +735,15 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
return AE_CTRL_TERMINATE;
}
-static void ec_poll_stop(struct acpi_ec *ec)
-{
- clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags);
- cancel_delayed_work(&ec->work);
-}
-
static void ec_remove_handlers(struct acpi_ec *ec)
{
- ec_poll_stop(ec);
if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
pr_err(PREFIX "failed to remove space handler\n");
if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
&acpi_ec_gpe_handler)))
pr_err(PREFIX "failed to remove gpe handler\n");
- ec->handlers_installed = 0;
+ clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
}
static int acpi_ec_add(struct acpi_device *device)
@@ -846,17 +838,15 @@ ec_parse_io_ports(struct acpi_resource *resource, void *context)
static int ec_install_handlers(struct acpi_ec *ec)
{
acpi_status status;
- if (ec->handlers_installed)
+ if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags))
return 0;
status = acpi_install_gpe_handler(NULL, ec->gpe,
- ACPI_GPE_EDGE_TRIGGERED,
- &acpi_ec_gpe_handler, ec);
+ ACPI_GPE_EDGE_TRIGGERED,
+ &acpi_ec_gpe_handler, ec);
if (ACPI_FAILURE(status))
return -ENODEV;
-
acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
-
status = acpi_install_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC,
&acpi_ec_space_handler,
@@ -866,7 +856,7 @@ static int ec_install_handlers(struct acpi_ec *ec)
return -ENODEV;
}
- ec->handlers_installed = 1;
+ set_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
return 0;
}
@@ -887,7 +877,6 @@ static int acpi_ec_start(struct acpi_device *device)
/* EC is fully operational, allow queries */
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
- ec_schedule_ec_poll(ec);
return ret;
}
@@ -906,7 +895,7 @@ static int acpi_ec_stop(struct acpi_device *device, int type)
int __init acpi_boot_ec_enable(void)
{
- if (!boot_ec || boot_ec->handlers_installed)
+ if (!boot_ec || test_bit(EC_FLAGS_HANDLERS_INSTALLED, &boot_ec->flags))
return 0;
if (!ec_install_handlers(boot_ec)) {
first_ec = boot_ec;
--
1.5.5.1
From: Len Brown <[email protected]>
for some reason git didn't permit me to do this during the merge...
Signed-off-by: Len Brown <[email protected]>
---
0 files changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 drivers/acpi/bay.c
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c
deleted file mode 100644
index e69de29..0000000
--
1.5.5.1
From: Shaohua Li <[email protected]>
Signed-off-by: Shaohua Li <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/Kconfig | 11 +-
drivers/acpi/Makefile | 1 -
drivers/acpi/bay.c | 411 -------------------------------------------------
3 files changed, 2 insertions(+), 421 deletions(-)
delete mode 100644 drivers/acpi/bay.c
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 735f5ea..3919d6d 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -160,15 +160,8 @@ config ACPI_DOCK
tristate "Dock"
depends on EXPERIMENTAL
help
- This driver adds support for ACPI controlled docking stations
-
-config ACPI_BAY
- tristate "Removable Drive Bay (EXPERIMENTAL)"
- depends on EXPERIMENTAL
- depends on ACPI_DOCK
- help
- This driver adds support for ACPI controlled removable drive
- bays such as the IBM ultrabay or the Dell Module Bay.
+ This driver adds support for ACPI controlled docking stations and removable
+ drive bays such as the IBM ultrabay or the Dell Module Bay.
config ACPI_PROCESSOR
tristate "Processor"
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 52a4cd4..ad4bfd5 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -45,7 +45,6 @@ obj-$(CONFIG_ACPI_BATTERY) += battery.o
obj-$(CONFIG_ACPI_BUTTON) += button.o
obj-$(CONFIG_ACPI_FAN) += fan.o
obj-$(CONFIG_ACPI_DOCK) += dock.o
-obj-$(CONFIG_ACPI_BAY) += bay.o
obj-$(CONFIG_ACPI_VIDEO) += video.o
obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o
obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c
deleted file mode 100644
index 61b6c5b..0000000
--- a/drivers/acpi/bay.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * bay.c - ACPI removable drive bay driver
- *
- * Copyright (C) 2006 Kristen Carlson Accardi <[email protected]>
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/notifier.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-#include <linux/seq_file.h>
-#include <asm/uaccess.h>
-#include <linux/platform_device.h>
-
-ACPI_MODULE_NAME("bay");
-MODULE_AUTHOR("Kristen Carlson Accardi");
-MODULE_DESCRIPTION("ACPI Removable Drive Bay Driver");
-MODULE_LICENSE("GPL");
-#define ACPI_BAY_CLASS "bay"
-#define ACPI_BAY_COMPONENT 0x10000000
-#define _COMPONENT ACPI_BAY_COMPONENT
-#define bay_dprintk(h,s) {\
- char prefix[80] = {'\0'};\
- struct acpi_buffer buffer = {sizeof(prefix), prefix};\
- acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\
- printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); }
-static void bay_notify(acpi_handle handle, u32 event, void *data);
-
-static const struct acpi_device_id bay_device_ids[] = {
- {"LNXIOBAY", 0},
- {"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, bay_device_ids);
-
-struct bay {
- acpi_handle handle;
- char *name;
- struct list_head list;
- struct platform_device *pdev;
-};
-
-static LIST_HEAD(drive_bays);
-
-
-/*****************************************************************************
- * Drive Bay functions *
- *****************************************************************************/
-/**
- * is_ejectable - see if a device is ejectable
- * @handle: acpi handle of the device
- *
- * If an acpi object has a _EJ0 method, then it is ejectable
- */
-static int is_ejectable(acpi_handle handle)
-{
- acpi_status status;
- acpi_handle tmp;
-
- status = acpi_get_handle(handle, "_EJ0", &tmp);
- if (ACPI_FAILURE(status))
- return 0;
- return 1;
-}
-
-/**
- * bay_present - see if the bay device is present
- * @bay: the drive bay
- *
- * execute the _STA method.
- */
-static int bay_present(struct bay *bay)
-{
- unsigned long sta;
- acpi_status status;
-
- if (bay) {
- status = acpi_evaluate_integer(bay->handle, "_STA", NULL, &sta);
- if (ACPI_SUCCESS(status) && sta)
- return 1;
- }
- return 0;
-}
-
-/**
- * eject_device - respond to an eject request
- * @handle - the device to eject
- *
- * Call this devices _EJ0 method.
- */
-static void eject_device(acpi_handle handle)
-{
- struct acpi_object_list arg_list;
- union acpi_object arg;
-
- bay_dprintk(handle, "Ejecting device");
-
- arg_list.count = 1;
- arg_list.pointer = &arg;
- arg.type = ACPI_TYPE_INTEGER;
- arg.integer.value = 1;
-
- if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0",
- &arg_list, NULL)))
- pr_debug("Failed to evaluate _EJ0!\n");
-}
-
-/*
- * show_present - read method for "present" file in sysfs
- */
-static ssize_t show_present(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct bay *bay = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%d\n", bay_present(bay));
-
-}
-static DEVICE_ATTR(present, S_IRUGO, show_present, NULL);
-
-/*
- * write_eject - write method for "eject" file in sysfs
- */
-static ssize_t write_eject(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct bay *bay = dev_get_drvdata(dev);
-
- if (!count)
- return -EINVAL;
-
- eject_device(bay->handle);
- return count;
-}
-static DEVICE_ATTR(eject, S_IWUSR, NULL, write_eject);
-
-/**
- * is_ata - see if a device is an ata device
- * @handle: acpi handle of the device
- *
- * If an acpi object has one of 4 ATA ACPI methods defined,
- * then it is an ATA device
- */
-static int is_ata(acpi_handle handle)
-{
- acpi_handle tmp;
-
- if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||
- (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||
- (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||
- (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))
- return 1;
-
- return 0;
-}
-
-/**
- * parent_is_ata(acpi_handle handle)
- *
- */
-static int parent_is_ata(acpi_handle handle)
-{
- acpi_handle phandle;
-
- if (acpi_get_parent(handle, &phandle))
- return 0;
-
- return is_ata(phandle);
-}
-
-/**
- * is_ejectable_bay - see if a device is an ejectable drive bay
- * @handle: acpi handle of the device
- *
- * If an acpi object is ejectable and has one of the ACPI ATA
- * methods defined, then we can safely call it an ejectable
- * drive bay
- */
-static int is_ejectable_bay(acpi_handle handle)
-{
- if ((is_ata(handle) || parent_is_ata(handle)) && is_ejectable(handle))
- return 1;
- return 0;
-}
-
-#if 0
-/**
- * eject_removable_drive - try to eject this drive
- * @dev : the device structure of the drive
- *
- * If a device is a removable drive that requires an _EJ0 method
- * to be executed in order to safely remove from the system, do
- * it. ATM - always returns success
- */
-int eject_removable_drive(struct device *dev)
-{
- acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
-
- if (handle) {
- bay_dprintk(handle, "Got device handle");
- if (is_ejectable_bay(handle))
- eject_device(handle);
- } else {
- printk("No acpi handle for device\n");
- }
-
- /* should I return an error code? */
- return 0;
-}
-EXPORT_SYMBOL_GPL(eject_removable_drive);
-#endif /* 0 */
-
-static int acpi_bay_add_fs(struct bay *bay)
-{
- int ret;
- struct device *dev = &bay->pdev->dev;
-
- ret = device_create_file(dev, &dev_attr_present);
- if (ret)
- goto add_fs_err;
- ret = device_create_file(dev, &dev_attr_eject);
- if (ret) {
- device_remove_file(dev, &dev_attr_present);
- goto add_fs_err;
- }
- return 0;
-
- add_fs_err:
- bay_dprintk(bay->handle, "Error adding sysfs files\n");
- return ret;
-}
-
-static void acpi_bay_remove_fs(struct bay *bay)
-{
- struct device *dev = &bay->pdev->dev;
-
- /* cleanup sysfs */
- device_remove_file(dev, &dev_attr_present);
- device_remove_file(dev, &dev_attr_eject);
-}
-
-static int bay_is_dock_device(acpi_handle handle)
-{
- acpi_handle parent;
-
- acpi_get_parent(handle, &parent);
-
- /* if the device or it's parent is dependent on the
- * dock, then we are a dock device
- */
- return (is_dock_device(handle) || is_dock_device(parent));
-}
-
-static int bay_add(acpi_handle handle, int id)
-{
- acpi_status status;
- struct bay *new_bay;
- struct platform_device *pdev;
- struct acpi_buffer nbuffer = {ACPI_ALLOCATE_BUFFER, NULL};
- acpi_get_name(handle, ACPI_FULL_PATHNAME, &nbuffer);
-
- bay_dprintk(handle, "Adding notify handler");
-
- /*
- * Initialize bay device structure
- */
- new_bay = kzalloc(sizeof(*new_bay), GFP_ATOMIC);
- INIT_LIST_HEAD(&new_bay->list);
- new_bay->handle = handle;
- new_bay->name = (char *)nbuffer.pointer;
-
- /* initialize platform device stuff */
- pdev = platform_device_register_simple(ACPI_BAY_CLASS, id, NULL, 0);
- if (IS_ERR(pdev)) {
- printk(KERN_ERR PREFIX "Error registering bay device\n");
- goto bay_add_err;
- }
- new_bay->pdev = pdev;
- platform_set_drvdata(pdev, new_bay);
-
- /*
- * we want the bay driver to be able to send uevents
- */
- pdev->dev.uevent_suppress = 0;
-
- /* register for events on this device */
- status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
- bay_notify, new_bay);
- if (ACPI_FAILURE(status)) {
- printk(KERN_INFO PREFIX "Error installing bay notify handler\n");
- platform_device_unregister(new_bay->pdev);
- goto bay_add_err;
- }
-
- if (acpi_bay_add_fs(new_bay)) {
- acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
- bay_notify);
- platform_device_unregister(new_bay->pdev);
- goto bay_add_err;
- }
-
- /* if we are on a dock station, we should register for dock
- * notifications.
- */
- if (bay_is_dock_device(handle)) {
- bay_dprintk(handle, "Is dependent on dock\n");
- register_hotplug_dock_device(handle, bay_notify, new_bay);
- }
- list_add(&new_bay->list, &drive_bays);
- printk(KERN_INFO PREFIX "Bay [%s] Added\n", new_bay->name);
- return 0;
-
-bay_add_err:
- kfree(new_bay->name);
- kfree(new_bay);
- return -ENODEV;
-}
-
-/**
- * bay_notify - act upon an acpi bay notification
- * @handle: the bay handle
- * @event: the acpi event
- * @data: our driver data struct
- *
- */
-static void bay_notify(acpi_handle handle, u32 event, void *data)
-{
- struct bay *bay_dev = (struct bay *)data;
- struct device *dev = &bay_dev->pdev->dev;
- char event_string[12];
- char *envp[] = { event_string, NULL };
-
- bay_dprintk(handle, "Bay event");
- sprintf(event_string, "BAY_EVENT=%d", event);
- kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
-}
-
-static acpi_status
-find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
- int *count = (int *)context;
-
- /*
- * there could be more than one ejectable bay.
- * so, just return AE_OK always so that every object
- * will be checked.
- */
- if (is_ejectable_bay(handle)) {
- bay_dprintk(handle, "found ejectable bay");
- if (!bay_add(handle, *count))
- (*count)++;
- }
- return AE_OK;
-}
-
-static int __init bay_init(void)
-{
- int bays = 0;
-
- INIT_LIST_HEAD(&drive_bays);
-
- if (acpi_disabled)
- return -ENODEV;
-
- /* look for dockable drive bays */
- acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, find_bay, &bays, NULL);
-
- if (!bays)
- return -ENODEV;
-
- return 0;
-}
-
-static void __exit bay_exit(void)
-{
- struct bay *bay, *tmp;
-
- list_for_each_entry_safe(bay, tmp, &drive_bays, list) {
- if (is_dock_device(bay->handle))
- unregister_hotplug_dock_device(bay->handle);
- acpi_bay_remove_fs(bay);
- acpi_remove_notify_handler(bay->handle, ACPI_SYSTEM_NOTIFY,
- bay_notify);
- platform_device_unregister(bay->pdev);
- kfree(bay->name);
- kfree(bay);
- }
-}
-
-postcore_initcall(bay_init);
-module_exit(bay_exit);
-
--
1.5.5.1
From: Thomas Renninger <[email protected]>
Signed-off-by: Thomas Renninger <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/thermal.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 9127036..6f2c5e9 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -1213,8 +1213,8 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
acpi_bus_private_data_handler,
tz->thermal_zone);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error attaching device data\n"));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Error attaching device data"));
return -ENODEV;
}
--
1.5.5.1
From: Thomas Renninger <[email protected]>
Signed-off-by: Thomas Renninger <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/processor_perflib.c | 17 ++++++-----------
drivers/acpi/processor_throttling.c | 17 ++++++-----------
2 files changed, 12 insertions(+), 22 deletions(-)
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 80c251e..bf183e7 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -523,14 +523,9 @@ static int acpi_processor_get_psd(struct acpi_processor *pr)
}
psd = buffer.pointer;
- if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
- result = -EFAULT;
- goto end;
- }
-
- if (psd->package.count != 1) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
+ if (!psd || (psd->type != ACPI_TYPE_PACKAGE)
+ || psd->package.count != 1) {
+ printk(KERN_ERR "Invalid _PSD data\n");
result = -EFAULT;
goto end;
}
@@ -543,19 +538,19 @@ static int acpi_processor_get_psd(struct acpi_processor *pr)
status = acpi_extract_package(&(psd->package.elements[0]),
&format, &state);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
+ ACPI_EXCEPTION((AE_INFO, status, "Invalid _PSD data"));
result = -EFAULT;
goto end;
}
if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:num_entries\n"));
+ printk(KERN_ERR "Unknown _PSD:num_entries\n");
result = -EFAULT;
goto end;
}
if (pdomain->revision != ACPI_PSD_REV0_REVISION) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:revision\n"));
+ printk(KERN_ERR "Unknown _PSD:revision\n");
result = -EFAULT;
goto end;
}
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index a56fc6c..ce4540d 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -527,14 +527,9 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr)
}
tsd = buffer.pointer;
- if (!tsd || (tsd->type != ACPI_TYPE_PACKAGE)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
- result = -EFAULT;
- goto end;
- }
-
- if (tsd->package.count != 1) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
+ if (!tsd || (tsd->type != ACPI_TYPE_PACKAGE)
+ || tsd->package.count != 1) {
+ printk(KERN_INFO "Invalid _TSD data\n");
result = -EFAULT;
goto end;
}
@@ -547,19 +542,19 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr)
status = acpi_extract_package(&(tsd->package.elements[0]),
&format, &state);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
+ ACPI_EXCEPTION((AE_INFO, status, "Invalid _TSD data"));
result = -EFAULT;
goto end;
}
if (pdomain->num_entries != ACPI_TSD_REV0_ENTRIES) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:num_entries\n"));
+ printk(KERN_ERR "Unknown _TSD:num_entries\n");
result = -EFAULT;
goto end;
}
if (pdomain->revision != ACPI_TSD_REV0_REVISION) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:revision\n"));
+ printk(KERN_ERR "Unknown _TSD:revision\n");
result = -EFAULT;
goto end;
}
--
1.5.5.1
From: Jan Beulich <[email protected]>
The (1.0 inherited) separate length fields in the FADT are byte granular.
Further, PM1a/b may have distinct lengths (if using the v2 fields was
okay) and may live in distinct address spaces. acpi_tb_convert_fadt()
should account for all of these conditions.
Apart from these changes I'm puzzled by the fact that, not just for
acpi_gbl_xpm1{a,b}_enable, acpi_hw_low_level_{read,write}() get an
explicit size passed rather than using the size found in the passed GAS.
What happens on a platform that defines PM1{a,b} wider than 16 bits? Of
course, acpi_hw_low_level_{read,write}() at present are entirely
un-prepared to deal with sizes other than 8, 16, or 32, not to speak of a
non-zero bit_offset or access_width...
Signed-off-by: Jan Beulich <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/tables/tbfadt.c | 32 +++++++++++++++++++++++++-------
1 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c
index a4a41ba..2c7885e 100644
--- a/drivers/acpi/tables/tbfadt.c
+++ b/drivers/acpi/tables/tbfadt.c
@@ -50,7 +50,7 @@ ACPI_MODULE_NAME("tbfadt")
/* Local prototypes */
static void inline
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
- u8 bit_width, u64 address);
+ u8 byte_width, u64 address);
static void acpi_tb_convert_fadt(void);
@@ -111,7 +111,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
* FUNCTION: acpi_tb_init_generic_address
*
* PARAMETERS: generic_address - GAS struct to be initialized
- * bit_width - Width of this register
+ * byte_width - Width of this register
* Address - Address of the register
*
* RETURN: None
@@ -124,7 +124,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
static void inline
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
- u8 bit_width, u64 address)
+ u8 byte_width, u64 address)
{
/*
@@ -136,7 +136,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
/* All other fields are byte-wide */
generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO;
- generic_address->bit_width = bit_width;
+ generic_address->bit_width = byte_width << 3;
generic_address->bit_offset = 0;
generic_address->access_width = 0;
}
@@ -342,9 +342,20 @@ static void acpi_tb_convert_fadt(void)
* useful to calculate them once, here.
*
* The PM event blocks are split into two register blocks, first is the
- * PM Status Register block, followed immediately by the PM Enable Register
- * block. Each is of length (pm1_event_length/2)
+ * PM Status Register block, followed immediately by the PM Enable
+ * Register block. Each is of length (xpm1x_event_block.bit_width/2).
+ *
+ * On various systems the v2 fields (and particularly the bit widths)
+ * cannot be relied upon, though. Hence resort to using the v1 length
+ * here (and warn about the inconsistency).
*/
+ if (acpi_gbl_FADT.xpm1a_event_block.bit_width
+ != acpi_gbl_FADT.pm1_event_length * 8)
+ printk(KERN_WARNING "FADT: "
+ "X_PM1a_EVT_BLK.bit_width (%u) does not match"
+ " PM1_EVT_LEN (%u)\n",
+ acpi_gbl_FADT.xpm1a_event_block.bit_width,
+ acpi_gbl_FADT.pm1_event_length);
pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length);
/* The PM1A register block is required */
@@ -360,13 +371,20 @@ static void acpi_tb_convert_fadt(void)
/* The PM1B register block is optional, ignore if not present */
if (acpi_gbl_FADT.xpm1b_event_block.address) {
+ if (acpi_gbl_FADT.xpm1b_event_block.bit_width
+ != acpi_gbl_FADT.pm1_event_length * 8)
+ printk(KERN_WARNING "FADT: "
+ "X_PM1b_EVT_BLK.bit_width (%u) does not match"
+ " PM1_EVT_LEN (%u)\n",
+ acpi_gbl_FADT.xpm1b_event_block.bit_width,
+ acpi_gbl_FADT.pm1_event_length);
acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
pm1_register_length,
(acpi_gbl_FADT.xpm1b_event_block.
address + pm1_register_length));
/* Don't forget to copy space_id of the GAS */
acpi_gbl_xpm1b_enable.space_id =
- acpi_gbl_FADT.xpm1a_event_block.space_id;
+ acpi_gbl_FADT.xpm1b_event_block.space_id;
}
}
--
1.5.5.1
From: Thomas Renninger <[email protected]>
Signed-off-by: Thomas Renninger <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/cm_sbs.c | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c
index f9db4f4..58dc367 100644
--- a/drivers/acpi/cm_sbs.c
+++ b/drivers/acpi/cm_sbs.c
@@ -52,8 +52,7 @@ struct proc_dir_entry *acpi_lock_ac_dir(void)
if (acpi_ac_dir) {
lock_ac_dir_cnt++;
} else {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Cannot create %s\n", ACPI_AC_CLASS));
+ printk(KERN_ERR "Cannot create %s\n", ACPI_AC_CLASS);
}
mutex_unlock(&cm_sbs_mutex);
return acpi_ac_dir;
@@ -83,8 +82,7 @@ struct proc_dir_entry *acpi_lock_battery_dir(void)
if (acpi_battery_dir) {
lock_battery_dir_cnt++;
} else {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Cannot create %s\n", ACPI_BATTERY_CLASS));
+ printk(KERN_ERR "Cannot create %s\n", ACPI_BATTERY_CLASS);
}
mutex_unlock(&cm_sbs_mutex);
return acpi_battery_dir;
--
1.5.5.1
From: Venki Pallipadi <[email protected]>
The Intel 7300 Memory Controller supports dynamic throttling of memory which can
be used to save power when system is idle. This driver does the memory
throttling when all CPUs are idle on such a system.
Refer to "Intel 7300 Memory Controller Hub (MCH)" datasheet
for the config space description.
Signed-off-by: Andy Henroid <[email protected]>
Signed-off-by: Len Brown <[email protected]>
Signed-off-by: Venkatesh Pallipadi <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
MAINTAINERS | 6 ++++++
arch/x86/Kconfig | 2 ++
arch/x86/kernel/process_64.c | 7 +++++++
drivers/Makefile | 1 +
drivers/dma/ioat_dma.c | 3 +++
include/asm-x86/idle.h | 1 +
include/linux/pci_ids.h | 1 +
7 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 8dae455..43f71b0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2078,6 +2078,12 @@ L: [email protected]
L: [email protected]
S: Orphan
+IDLE-I7300
+P: Andy Henroid
+M: [email protected]
+L: [email protected]
+S: Supported
+
IEEE 1394 SUBSYSTEM (drivers/ieee1394)
P: Ben Collins
M: [email protected]
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ed92864..19cdfe1 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1536,6 +1536,8 @@ source "arch/x86/kernel/cpu/cpufreq/Kconfig"
source "drivers/cpuidle/Kconfig"
+source "drivers/idle/Kconfig"
+
endmenu
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index e12e0e4..3e3d503 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -62,6 +62,13 @@ void idle_notifier_register(struct notifier_block *n)
{
atomic_notifier_chain_register(&idle_notifier, n);
}
+EXPORT_SYMBOL_GPL(idle_notifier_register);
+
+void idle_notifier_unregister(struct notifier_block *n)
+{
+ atomic_notifier_chain_unregister(&idle_notifier, n);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_unregister);
void enter_idle(void)
{
diff --git a/drivers/Makefile b/drivers/Makefile
index 2735bde..f443a8a 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_EISA) += eisa/
obj-y += lguest/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_CPU_IDLE) += cpuidle/
+obj-y += idle/
obj-$(CONFIG_MMC) += mmc/
obj-$(CONFIG_MEMSTICK) += memstick/
obj-$(CONFIG_NEW_LEDS) += leds/
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
index bc8c6e3..f8396ca 100644
--- a/drivers/dma/ioat_dma.c
+++ b/drivers/dma/ioat_dma.c
@@ -171,6 +171,9 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET);
xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
+#if CONFIG_I7300_IDLE_IOAT_CHANNEL
+ device->common.chancnt--;
+#endif
for (i = 0; i < device->common.chancnt; i++) {
ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL);
if (!ioat_chan) {
diff --git a/include/asm-x86/idle.h b/include/asm-x86/idle.h
index cbb6491..54ce018 100644
--- a/include/asm-x86/idle.h
+++ b/include/asm-x86/idle.h
@@ -6,6 +6,7 @@
struct notifier_block;
void idle_notifier_register(struct notifier_block *n);
+void idle_notifier_unregister(struct notifier_block *n);
void enter_idle(void);
void exit_idle(void);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index f1624b3..efb786d 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2422,6 +2422,7 @@
#define PCI_DEVICE_ID_INTEL_MCH_PC1 0x359a
#define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e
#define PCI_DEVICE_ID_INTEL_IOAT_CNB 0x360b
+#define PCI_DEVICE_ID_INTEL_FBD_CNB 0x360c
#define PCI_DEVICE_ID_INTEL_ICH10_0 0x3a14
#define PCI_DEVICE_ID_INTEL_ICH10_1 0x3a16
#define PCI_DEVICE_ID_INTEL_ICH10_2 0x3a18
--
1.5.5.1
From: Shaohua Li <[email protected]>
commit 2a7feab28d3fc060d320eaba192e49dad1079b7e introduces a bug.
My thinkpad actually will send an eject_request and we should follow the
eject process to finish the eject, otherwise system still thinks the bay
is present.
Signed-off-by: Shaohua Li <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/dock.c | 5 -----
1 files changed, 0 insertions(+), 5 deletions(-)
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 25d2161..78d27ce 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -575,11 +575,6 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
*/
dock_event(ds, event, UNDOCK_EVENT);
- if (!dock_present(ds)) {
- complete_undock(ds);
- return -ENODEV;
- }
-
hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
undock(ds);
eject_dock(ds);
--
1.5.5.1
From: Thomas Renninger <[email protected]>
On Intel CPUs it is rather common and a good hint that BIOSes which do provide
_PPC func, but not the frequencies itself in _PSS function, are old and need
to be updated for CPU freq support.
Tell the user/vendor he has a BIOS/firmware problem.
Make use of FW_BUG interface to give vendors and users the ability to
automatically check with (or let linuxfirmwarekit do that):
dmesg |grep "Firmware Bug"
Signed-off-by: Thomas Renninger <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/processor_perflib.c | 18 +++++++++++++++---
1 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 80c251e..242f814 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -38,6 +38,7 @@
#include <asm/uaccess.h>
#endif
+#include <asm/cpufeature.h>
#include <acpi/acpi_bus.h>
#include <acpi/processor.h>
@@ -334,7 +335,6 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr)
acpi_status status = AE_OK;
acpi_handle handle = NULL;
-
if (!pr || !pr->performance || !pr->handle)
return -EINVAL;
@@ -347,13 +347,25 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr)
result = acpi_processor_get_performance_control(pr);
if (result)
- return result;
+ goto update_bios;
result = acpi_processor_get_performance_states(pr);
if (result)
- return result;
+ goto update_bios;
return 0;
+
+ /*
+ * Having _PPC but missing frequencies (_PSS, _PCT) is a very good hint that
+ * the BIOS is older than the CPU and does not know its frequencies
+ */
+ update_bios:
+ if (ACPI_SUCCESS(acpi_get_handle(pr->handle, "_PPC", &handle))){
+ if(boot_cpu_has(X86_FEATURE_EST))
+ printk(KERN_WARNING FW_BUG "BIOS needs update for CPU "
+ "frequency support\n");
+ }
+ return result;
}
int acpi_processor_notify_smm(struct module *calling_module)
--
1.5.5.1
From: Rafael J. Wysocki <[email protected]>
According to the ACPI specification 2.0c and later, the 64-bit waking vector
should be cleared and the 32-bit waking vector should be used, unless we want
the wake-up code to be called by the BIOS in Protected Mode. Moreover, some
systems (for example HP dv5-1004nr) are known to fail to resume if the 64-bit
waking vector is used. Therefore, modify the code to clear the 64-bit waking
vector, for FACS version 1 or greater, and set the 32-bit one before suspend.
Signed-off-by: Rafael J. Wysocki <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/hardware/hwsleep.c | 39 ++++++++++++---------------------------
1 files changed, 12 insertions(+), 27 deletions(-)
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index 130a44b..25dccdf 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -78,19 +78,17 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address)
return_ACPI_STATUS(status);
}
- /* Set the vector */
+ /*
+ * According to the ACPI specification 2.0c and later, the 64-bit
+ * waking vector should be cleared and the 32-bit waking vector should
+ * be used, unless we want the wake-up code to be called by the BIOS in
+ * Protected Mode. Some systems (for example HP dv5-1004nr) are known
+ * to fail to resume if the 64-bit vector is used.
+ */
+ if (facs->version >= 1)
+ facs->xfirmware_waking_vector = 0;
- if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) {
- /*
- * ACPI 1.0 FACS or short table or optional X_ field is zero
- */
- facs->firmware_waking_vector = (u32) physical_address;
- } else {
- /*
- * ACPI 2.0 FACS with valid X_ field
- */
- facs->xfirmware_waking_vector = physical_address;
- }
+ facs->firmware_waking_vector = (u32)physical_address;
return_ACPI_STATUS(AE_OK);
}
@@ -134,20 +132,7 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address)
}
/* Get the vector */
-
- if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) {
- /*
- * ACPI 1.0 FACS or short table or optional X_ field is zero
- */
- *physical_address =
- (acpi_physical_address) facs->firmware_waking_vector;
- } else {
- /*
- * ACPI 2.0 FACS with valid X_ field
- */
- *physical_address =
- (acpi_physical_address) facs->xfirmware_waking_vector;
- }
+ *physical_address = (acpi_physical_address)facs->firmware_waking_vector;
return_ACPI_STATUS(AE_OK);
}
--
1.5.5.1
From: Matt Mackall <[email protected]>
x86_64 SMP suspend to RAM uses a 10k temporary stack for saving the
kernel state, but only 4k of it is used. Shrink it to 4k.
Signed-off-by: Matt Mackall <[email protected]>
Acked-by: Pavel Machek <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
arch/x86/kernel/acpi/sleep.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index 426e5d9..29cf340 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -97,7 +97,7 @@ int acpi_save_state_mem(void)
#else /* CONFIG_64BIT */
header->trampoline_segment = setup_trampoline() >> 4;
#ifdef CONFIG_SMP
- stack_start.sp = temp_stack + 4096;
+ stack_start.sp = temp_stack + sizeof(temp_stack);
#endif
initial_code = (unsigned long)wakeup_long64;
saved_magic = 0x123456789abcdef0;
--
1.5.5.1
From: Alexey Starikovskiy <[email protected]>
Reference: http://marc.info/?l=linux-acpi&m=122236382701062&w=2
Signed-off-by: Alexey Starikovskiy <[email protected]>
Tested-by: Sitsofe Wheeler <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/parser/psloop.c | 2 ++
include/acpi/acmacros.h | 5 +++++
include/acpi/platform/aclinux.h | 6 ++++++
3 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c
index c06238e..4647039 100644
--- a/drivers/acpi/parser/psloop.c
+++ b/drivers/acpi/parser/psloop.c
@@ -719,6 +719,8 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state,
*op = NULL;
}
+ ACPI_PREEMPTION_POINT();
+
return_ACPI_STATUS(AE_OK);
}
diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h
index 57ab9e9..b402685 100644
--- a/include/acpi/acmacros.h
+++ b/include/acpi/acmacros.h
@@ -703,4 +703,9 @@ struct acpi_integer_overlay {
#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
+/* Preemption point */
+#ifndef ACPI_PREEMPTION_POINT
+#define ACPI_PREEMPTION_POINT() /* no preemption */
+#endif
+
#endif /* ACMACROS_H */
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
index 9af4645..029c8c0 100644
--- a/include/acpi/platform/aclinux.h
+++ b/include/acpi/platform/aclinux.h
@@ -53,6 +53,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/ctype.h>
+#include <linux/sched.h>
#include <asm/system.h>
#include <asm/atomic.h>
#include <asm/div64.h>
@@ -137,4 +138,9 @@ static inline void *acpi_os_acquire_object(acpi_cache_t * cache)
#define ACPI_ALLOCATE_ZEROED(a) acpi_os_allocate_zeroed(a)
#define ACPI_FREE(a) kfree(a)
+/*
+ * We need to show where it is safe to preempt execution of ACPICA
+ */
+#define ACPI_PREEMPTION_POINT() cond_resched()
+
#endif /* __ACLINUX_H__ */
--
1.5.5.1
From: Matthew Wilcox <[email protected]>
As of version 2.0, ACPI can return 64-bit integers. The current
acpi_evaluate_integer only supports 64-bit integers on 64-bit platforms.
Change the argument to take a pointer to an acpi_integer so we support
64-bit integers on all platforms.
lenb: replaced use of "acpi_integer" with "unsigned long long"
Signed-off-by: Matthew Wilcox <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
arch/ia64/sn/kernel/io_acpi_init.c | 8 +++---
drivers/acpi/ac.c | 2 +-
drivers/acpi/acpi_memhotplug.c | 5 +--
drivers/acpi/asus_acpi.c | 2 +-
drivers/acpi/bay.c | 2 +-
drivers/acpi/bus.c | 4 +-
drivers/acpi/button.c | 4 +-
drivers/acpi/container.c | 2 +-
drivers/acpi/dock.c | 6 ++--
drivers/acpi/ec.c | 7 ++++-
drivers/acpi/numa.c | 2 +-
drivers/acpi/osl.c | 5 +--
drivers/acpi/pci_root.c | 2 +-
drivers/acpi/pci_slot.c | 10 ++++----
drivers/acpi/power.c | 2 +-
drivers/acpi/processor_core.c | 4 +-
drivers/acpi/processor_perflib.c | 2 +-
drivers/acpi/processor_throttling.c | 2 +-
drivers/acpi/sbshc.c | 2 +-
drivers/acpi/sleep/main.c | 2 +-
drivers/acpi/thermal.c | 43 ++++++++++++++++++++++-------------
drivers/acpi/utils.c | 4 +-
drivers/acpi/video.c | 42 +++++++++++++++++-----------------
drivers/ata/libata-acpi.c | 2 +-
drivers/misc/asus-laptop.c | 12 +++++-----
drivers/misc/eeepc-laptop.c | 2 +-
drivers/misc/fujitsu-laptop.c | 8 +++---
drivers/misc/intel_menlow.c | 27 +++++++++++----------
drivers/pci/hotplug/acpiphp_glue.c | 14 +++++-----
drivers/pci/hotplug/acpiphp_ibm.c | 2 +-
drivers/pci/hotplug/sgi_hotplug.c | 4 +-
include/acpi/acpi_bus.h | 2 +-
32 files changed, 125 insertions(+), 112 deletions(-)
diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c
index 6568942..a15baac 100644
--- a/arch/ia64/sn/kernel/io_acpi_init.c
+++ b/arch/ia64/sn/kernel/io_acpi_init.c
@@ -232,7 +232,7 @@ exit:
static unsigned int
get_host_devfn(acpi_handle device_handle, acpi_handle rootbus_handle)
{
- unsigned long adr;
+ unsigned long long adr;
acpi_handle child;
unsigned int devfn;
int function;
@@ -292,8 +292,8 @@ get_host_devfn(acpi_handle device_handle, acpi_handle rootbus_handle)
static acpi_status
find_matching_device(acpi_handle handle, u32 lvl, void *context, void **rv)
{
- unsigned long bbn = -1;
- unsigned long adr;
+ unsigned long long bbn = -1;
+ unsigned long long adr;
acpi_handle parent = NULL;
acpi_status status;
unsigned int devfn;
@@ -348,7 +348,7 @@ sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info,
unsigned int host_devfn;
struct sn_pcidev_match pcidev_match;
acpi_handle rootbus_handle;
- unsigned long segment;
+ unsigned long long segment;
acpi_status status;
rootbus_handle = PCI_CONTROLLER(dev)->acpi_handle;
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 831883b..5e57a80 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -85,7 +85,7 @@ struct acpi_ac {
struct power_supply charger;
#endif
struct acpi_device * device;
- unsigned long state;
+ unsigned long long state;
};
#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger);
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 5f1127a..2b77316 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -194,8 +194,7 @@ acpi_memory_get_device(acpi_handle handle,
static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
{
- unsigned long current_status;
-
+ unsigned long long current_status;
/* Get device present/absent information from the _STA */
if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle, "_STA",
@@ -264,7 +263,7 @@ static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
acpi_status status;
struct acpi_object_list arg_list;
union acpi_object arg;
- unsigned long current_status;
+ unsigned long long current_status;
/* Issue the _EJ0 command */
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index d3d0886..4434209 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -753,7 +753,7 @@ static int get_lcd_state(void)
/* That's what the AML code does */
lcd = out_obj.integer.value >> 8;
} else if (hotk->model == F3Sa) {
- unsigned long tmp;
+ unsigned long long tmp;
union acpi_object param;
struct acpi_object_list input;
acpi_status status;
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c
index 61b6c5b..23a51e4 100644
--- a/drivers/acpi/bay.c
+++ b/drivers/acpi/bay.c
@@ -90,7 +90,7 @@ static int is_ejectable(acpi_handle handle)
*/
static int bay_present(struct bay *bay)
{
- unsigned long sta;
+ unsigned long long sta;
acpi_status status;
if (bay) {
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index ccae305..0885fc7 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -77,7 +77,7 @@ EXPORT_SYMBOL(acpi_bus_get_device);
int acpi_bus_get_status(struct acpi_device *device)
{
acpi_status status = AE_OK;
- unsigned long sta = 0;
+ unsigned long long sta = 0;
if (!device)
@@ -155,7 +155,7 @@ int acpi_bus_get_power(acpi_handle handle, int *state)
int result = 0;
acpi_status status = 0;
struct acpi_device *device = NULL;
- unsigned long psc = 0;
+ unsigned long long psc = 0;
result = acpi_bus_get_device(handle, &device);
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 1dfec41..baeb661 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -145,7 +145,7 @@ static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_button *button = seq->private;
acpi_status status;
- unsigned long state;
+ unsigned long long state;
if (!button || !button->device)
return 0;
@@ -253,7 +253,7 @@ static int acpi_button_remove_fs(struct acpi_device *device)
-------------------------------------------------------------------------- */
static int acpi_lid_send_state(struct acpi_button *button)
{
- unsigned long state;
+ unsigned long long state;
acpi_status status;
status = acpi_evaluate_integer(button->device->handle, "_LID", NULL,
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 3c25ec7..cfa5fd6 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -76,7 +76,7 @@ static int is_device_present(acpi_handle handle)
{
acpi_handle temp;
acpi_status status;
- unsigned long sta;
+ unsigned long long sta;
status = acpi_get_handle(handle, "_STA", &temp);
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 7d2edf1..9485711 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -229,7 +229,7 @@ EXPORT_SYMBOL_GPL(is_dock_device);
*/
static int dock_present(struct dock_station *ds)
{
- unsigned long sta;
+ unsigned long long sta;
acpi_status status;
if (ds) {
@@ -727,13 +727,13 @@ static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
static ssize_t show_dock_uid(struct device *dev,
struct device_attribute *attr, char *buf)
{
- unsigned long lbuf;
+ unsigned long long lbuf;
acpi_status status = acpi_evaluate_integer(dock_station->handle,
"_UID", NULL, &lbuf);
if (ACPI_FAILURE(status))
return 0;
- return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf);
+ return snprintf(buf, PAGE_SIZE, "%llx\n", lbuf);
}
static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 13593f9..638a686 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -718,6 +718,7 @@ static acpi_status
ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
{
acpi_status status;
+ unsigned long long tmp;
struct acpi_ec *ec = context;
status = acpi_walk_resources(handle, METHOD_NAME__CRS,
@@ -727,11 +728,13 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
/* Get GPE bit assignment (EC events). */
/* TODO: Add support for _GPE returning a package */
- status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe);
+ status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp);
if (ACPI_FAILURE(status))
return status;
+ ec->gpe = tmp;
/* Use the global lock for all EC transactions? */
- acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
+ acpi_evaluate_integer(handle, "_GLK", NULL, &tmp);
+ ec->global_lock = tmp;
ec->handle = handle;
return AE_CTRL_TERMINATE;
}
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index cb9864e..25ceae9 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -258,7 +258,7 @@ int __init acpi_numa_init(void)
int acpi_get_pxm(acpi_handle h)
{
- unsigned long pxm;
+ unsigned long long pxm;
acpi_status status;
acpi_handle handle;
acpi_handle phandle = h;
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 235a138..f58fcbb 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -608,7 +608,7 @@ static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */
acpi_handle handle;
struct acpi_pci_id *pci_id = *id;
acpi_status status;
- unsigned long temp;
+ unsigned long long temp;
acpi_object_type type;
acpi_get_parent(chandle, &handle);
@@ -620,8 +620,7 @@ static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */
if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE))
return;
- status =
- acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
+ status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
&temp);
if (ACPI_SUCCESS(status)) {
u32 val;
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index c3fed31..18ff4e5 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -190,7 +190,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
struct acpi_pci_root *root = NULL;
struct acpi_pci_root *tmp;
acpi_status status = AE_OK;
- unsigned long value = 0;
+ unsigned long long value = 0;
acpi_handle handle = NULL;
struct acpi_device *child;
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c
index d5b4ef8..9bb84d4 100644
--- a/drivers/acpi/pci_slot.c
+++ b/drivers/acpi/pci_slot.c
@@ -76,10 +76,10 @@ static struct acpi_pci_driver acpi_pci_slot_driver = {
};
static int
-check_slot(acpi_handle handle, unsigned long *sun)
+check_slot(acpi_handle handle, unsigned long long *sun)
{
int device = -1;
- unsigned long adr, sta;
+ unsigned long long adr, sta;
acpi_status status;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -132,7 +132,7 @@ static acpi_status
register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
{
int device;
- unsigned long sun;
+ unsigned long long sun;
char name[SLOT_NAME_SIZE];
struct acpi_pci_slot *slot;
struct pci_slot *pci_slot;
@@ -182,7 +182,7 @@ static acpi_status
walk_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
{
int device, function;
- unsigned long adr;
+ unsigned long long adr;
acpi_status status;
acpi_handle dummy_handle;
acpi_walk_callback user_function;
@@ -239,7 +239,7 @@ static int
walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function)
{
int seg, bus;
- unsigned long tmp;
+ unsigned long long tmp;
acpi_status status;
acpi_handle dummy_handle;
struct pci_bus *pci_bus;
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 4ab21cb..89e5d2a 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -131,7 +131,7 @@ acpi_power_get_context(acpi_handle handle,
static int acpi_power_get_state(struct acpi_power_resource *resource, int *state)
{
acpi_status status = AE_OK;
- unsigned long sta = 0;
+ unsigned long long sta = 0;
if (!resource || !state)
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index ee68ac5..8a27871 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -563,7 +563,7 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
/* Check if it is a Device with HID and UID */
if (has_uid) {
- unsigned long value;
+ unsigned long long value;
status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
NULL, &value);
if (ACPI_FAILURE(status)) {
@@ -875,7 +875,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
static int is_processor_present(acpi_handle handle)
{
acpi_status status;
- unsigned long sta = 0;
+ unsigned long long sta = 0;
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 80c251e..f8129c7 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -126,7 +126,7 @@ static struct notifier_block acpi_ppc_notifier_block = {
static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
{
acpi_status status = 0;
- unsigned long ppc = 0;
+ unsigned long long ppc = 0;
if (!pr)
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index a56fc6c..3097b75 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -274,7 +274,7 @@ static int acpi_processor_throttling_notifier(unsigned long event, void *data)
static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
{
acpi_status status = 0;
- unsigned long tpc = 0;
+ unsigned long long tpc = 0;
if (!pr)
return -EINVAL;
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index a4e3767..81d23d3 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -258,7 +258,7 @@ extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
static int acpi_smbus_hc_add(struct acpi_device *device)
{
int status;
- unsigned long val;
+ unsigned long long val;
struct acpi_smb_hc *hc;
if (!device)
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index d13194a..b32ba56 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -444,7 +444,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
struct acpi_device *adev;
char acpi_method[] = "_SxD";
- unsigned long d_min, d_max;
+ unsigned long long d_min, d_max;
if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
printk(KERN_DEBUG "ACPI handle has no context!\n");
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 9127036..6aeba58 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -246,18 +246,18 @@ static const struct file_operations acpi_thermal_polling_fops = {
static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
{
acpi_status status = AE_OK;
-
+ unsigned long long tmp;
if (!tz)
return -EINVAL;
tz->last_temperature = tz->temperature;
- status =
- acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tz->temperature);
+ status = acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tmp);
if (ACPI_FAILURE(status))
return -ENODEV;
+ tz->temperature = tmp;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n",
tz->temperature));
@@ -267,17 +267,16 @@ static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
{
acpi_status status = AE_OK;
-
+ unsigned long long tmp;
if (!tz)
return -EINVAL;
- status =
- acpi_evaluate_integer(tz->device->handle, "_TZP", NULL,
- &tz->polling_frequency);
+ status = acpi_evaluate_integer(tz->device->handle, "_TZP", NULL, &tmp);
if (ACPI_FAILURE(status))
return -ENODEV;
+ tz->polling_frequency = tmp;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n",
tz->polling_frequency));
@@ -356,6 +355,7 @@ do { \
static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
{
acpi_status status = AE_OK;
+ unsigned long long tmp;
struct acpi_handle_list devices;
int valid = 0;
int i;
@@ -363,7 +363,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
/* Critical Shutdown (required) */
if (flag & ACPI_TRIPS_CRITICAL) {
status = acpi_evaluate_integer(tz->device->handle,
- "_CRT", NULL, &tz->trips.critical.temperature);
+ "_CRT", NULL, &tmp);
/*
* Treat freezing temperatures as invalid as well; some
* BIOSes return really low values and cause reboots at startup.
@@ -377,6 +377,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
"No or invalid critical threshold"));
return -ENODEV;
} else {
+ tz->trips.critical.temperature = tmp;
tz->trips.critical.flags.valid = 1;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Found critical threshold [%lu]\n",
@@ -399,12 +400,13 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
/* Critical Sleep (optional) */
if (flag & ACPI_TRIPS_HOT) {
status = acpi_evaluate_integer(tz->device->handle,
- "_HOT", NULL, &tz->trips.hot.temperature);
+ "_HOT", NULL, &tmp);
if (ACPI_FAILURE(status)) {
tz->trips.hot.flags.valid = 0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"No hot threshold\n"));
} else {
+ tz->trips.hot.temperature = tmp;
tz->trips.hot.flags.valid = 1;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Found hot threshold [%lu]\n",
@@ -418,33 +420,40 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
if (psv == -1) {
status = AE_SUPPORT;
} else if (psv > 0) {
- tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv);
+ tmp = CELSIUS_TO_KELVIN(psv);
status = AE_OK;
} else {
status = acpi_evaluate_integer(tz->device->handle,
- "_PSV", NULL, &tz->trips.passive.temperature);
+ "_PSV", NULL, &tmp);
}
if (ACPI_FAILURE(status))
tz->trips.passive.flags.valid = 0;
else {
+ tz->trips.passive.temperature = tmp;
tz->trips.passive.flags.valid = 1;
if (flag == ACPI_TRIPS_INIT) {
status = acpi_evaluate_integer(
tz->device->handle, "_TC1",
- NULL, &tz->trips.passive.tc1);
+ NULL, &tmp);
if (ACPI_FAILURE(status))
tz->trips.passive.flags.valid = 0;
+ else
+ tz->trips.passive.tc1 = tmp;
status = acpi_evaluate_integer(
tz->device->handle, "_TC2",
- NULL, &tz->trips.passive.tc2);
+ NULL, &tmp);
if (ACPI_FAILURE(status))
tz->trips.passive.flags.valid = 0;
+ else
+ tz->trips.passive.tc2 = tmp;
status = acpi_evaluate_integer(
tz->device->handle, "_TSP",
- NULL, &tz->trips.passive.tsp);
+ NULL, &tmp);
if (ACPI_FAILURE(status))
tz->trips.passive.flags.valid = 0;
+ else
+ tz->trips.passive.tsp = tmp;
}
}
}
@@ -479,7 +488,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
if (flag & ACPI_TRIPS_ACTIVE) {
status = acpi_evaluate_integer(tz->device->handle,
- name, NULL, &tz->trips.active[i].temperature);
+ name, NULL, &tmp);
if (ACPI_FAILURE(status)) {
tz->trips.active[i].flags.valid = 0;
if (i == 0)
@@ -500,8 +509,10 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
tz->trips.active[i - 2].temperature :
CELSIUS_TO_KELVIN(act));
break;
- } else
+ } else {
+ tz->trips.active[i].temperature = tmp;
tz->trips.active[i].flags.valid = 1;
+ }
}
name[2] = 'L';
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 1009261..e827be3 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -256,7 +256,7 @@ EXPORT_SYMBOL(acpi_extract_package);
acpi_status
acpi_evaluate_integer(acpi_handle handle,
acpi_string pathname,
- struct acpi_object_list *arguments, unsigned long *data)
+ struct acpi_object_list *arguments, unsigned long long *data)
{
acpi_status status = AE_OK;
union acpi_object *element;
@@ -288,7 +288,7 @@ acpi_evaluate_integer(acpi_handle handle,
*data = element->integer.value;
kfree(element);
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%lu]\n", *data));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data));
return AE_OK;
}
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index e8a51a1..79409c9 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -291,20 +291,20 @@ static int acpi_video_device_lcd_set_level(struct acpi_video_device *device,
int level);
static int acpi_video_device_lcd_get_level_current(
struct acpi_video_device *device,
- unsigned long *level);
+ unsigned long long *level);
static int acpi_video_get_next_level(struct acpi_video_device *device,
u32 level_current, u32 event);
static void acpi_video_switch_brightness(struct acpi_video_device *device,
int event);
static int acpi_video_device_get_state(struct acpi_video_device *device,
- unsigned long *state);
+ unsigned long long *state);
static int acpi_video_output_get(struct output_device *od);
static int acpi_video_device_set_state(struct acpi_video_device *device, int state);
/*backlight device sysfs support*/
static int acpi_video_get_brightness(struct backlight_device *bd)
{
- unsigned long cur_level;
+ unsigned long long cur_level;
int i;
struct acpi_video_device *vd =
(struct acpi_video_device *)bl_get_data(bd);
@@ -336,7 +336,7 @@ static struct backlight_ops acpi_backlight_ops = {
/*video output device sysfs support*/
static int acpi_video_output_get(struct output_device *od)
{
- unsigned long state;
+ unsigned long long state;
struct acpi_video_device *vd =
(struct acpi_video_device *)dev_get_drvdata(&od->dev);
acpi_video_device_get_state(vd, &state);
@@ -370,7 +370,7 @@ static int video_get_cur_state(struct thermal_cooling_device *cdev, char *buf)
{
struct acpi_device *device = cdev->devdata;
struct acpi_video_device *video = acpi_driver_data(device);
- unsigned long level;
+ unsigned long long level;
int state;
acpi_video_device_lcd_get_level_current(video, &level);
@@ -410,7 +410,7 @@ static struct thermal_cooling_device_ops video_cooling_ops = {
/* device */
static int
-acpi_video_device_query(struct acpi_video_device *device, unsigned long *state)
+acpi_video_device_query(struct acpi_video_device *device, unsigned long long *state)
{
int status;
@@ -421,7 +421,7 @@ acpi_video_device_query(struct acpi_video_device *device, unsigned long *state)
static int
acpi_video_device_get_state(struct acpi_video_device *device,
- unsigned long *state)
+ unsigned long long *state)
{
int status;
@@ -436,7 +436,7 @@ acpi_video_device_set_state(struct acpi_video_device *device, int state)
int status;
union acpi_object arg0 = { ACPI_TYPE_INTEGER };
struct acpi_object_list args = { 1, &arg0 };
- unsigned long ret;
+ unsigned long long ret;
arg0.integer.value = state;
@@ -495,7 +495,7 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
static int
acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
- unsigned long *level)
+ unsigned long long *level)
{
if (device->cap._BQC)
return acpi_evaluate_integer(device->dev->handle, "_BQC", NULL,
@@ -549,7 +549,7 @@ static int
acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option)
{
int status;
- unsigned long tmp;
+ unsigned long long tmp;
union acpi_object arg0 = { ACPI_TYPE_INTEGER };
struct acpi_object_list args = { 1, &arg0 };
@@ -564,7 +564,7 @@ acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option)
}
static int
-acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id)
+acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long long *id)
{
int status;
@@ -575,7 +575,7 @@ acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id)
static int
acpi_video_bus_POST_options(struct acpi_video_bus *video,
- unsigned long *options)
+ unsigned long long *options)
{
int status;
@@ -918,7 +918,7 @@ static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
{
int status;
struct acpi_video_device *dev = seq->private;
- unsigned long state;
+ unsigned long long state;
if (!dev)
@@ -927,14 +927,14 @@ static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
status = acpi_video_device_get_state(dev, &state);
seq_printf(seq, "state: ");
if (ACPI_SUCCESS(status))
- seq_printf(seq, "0x%02lx\n", state);
+ seq_printf(seq, "0x%02llx\n", state);
else
seq_printf(seq, "<not supported>\n");
status = acpi_video_device_query(dev, &state);
seq_printf(seq, "query: ");
if (ACPI_SUCCESS(status))
- seq_printf(seq, "0x%02lx\n", state);
+ seq_printf(seq, "0x%02llx\n", state);
else
seq_printf(seq, "<not supported>\n");
@@ -1217,7 +1217,7 @@ static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file)
static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_video_bus *video = seq->private;
- unsigned long options;
+ unsigned long long options;
int status;
@@ -1232,7 +1232,7 @@ static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
printk(KERN_WARNING PREFIX
"This indicates a BIOS bug. Please contact the manufacturer.\n");
}
- printk("%lx\n", options);
+ printk("%llx\n", options);
seq_printf(seq, "can POST: <integrated video>");
if (options & 2)
seq_printf(seq, " <PCI video>");
@@ -1256,7 +1256,7 @@ static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_video_bus *video = seq->private;
int status;
- unsigned long id;
+ unsigned long long id;
if (!video)
@@ -1303,7 +1303,7 @@ acpi_video_bus_write_POST(struct file *file,
struct seq_file *m = file->private_data;
struct acpi_video_bus *video = m->private;
char str[12] = { 0 };
- unsigned long opt, options;
+ unsigned long long opt, options;
if (!video || count + 1 > sizeof str)
@@ -1473,7 +1473,7 @@ static int
acpi_video_bus_get_one_device(struct acpi_device *device,
struct acpi_video_bus *video)
{
- unsigned long device_id;
+ unsigned long long device_id;
int status;
struct acpi_video_device *data;
struct acpi_video_device_attrib* attribute;
@@ -1724,7 +1724,7 @@ acpi_video_get_next_level(struct acpi_video_device *device,
static void
acpi_video_switch_brightness(struct acpi_video_device *device, int event)
{
- unsigned long level_current, level_next;
+ unsigned long long level_current, level_next;
if (!device->brightness)
return;
acpi_video_device_lcd_get_level_current(device, &level_current);
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 9330b79..ae45187 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -180,7 +180,7 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
int wait = 0;
unsigned long flags;
acpi_handle handle, tmphandle;
- unsigned long sta;
+ unsigned long long sta;
acpi_status status;
if (dev) {
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c
index 7c6dfd0..967ecec 100644
--- a/drivers/misc/asus-laptop.c
+++ b/drivers/misc/asus-laptop.c
@@ -280,7 +280,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
static int read_wireless_status(int mask)
{
- ulong status;
+ unsigned long long status;
acpi_status rv = AE_OK;
if (!wireless_status_handle)
@@ -297,7 +297,7 @@ static int read_wireless_status(int mask)
static int read_gps_status(void)
{
- ulong status;
+ unsigned long long status;
acpi_status rv = AE_OK;
rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status);
@@ -404,7 +404,7 @@ static void lcd_blank(int blank)
static int read_brightness(struct backlight_device *bd)
{
- ulong value;
+ unsigned long long value;
acpi_status rv = AE_OK;
rv = acpi_evaluate_integer(brightness_get_handle, NULL, NULL, &value);
@@ -455,7 +455,7 @@ static ssize_t show_infos(struct device *dev,
struct device_attribute *attr, char *page)
{
int len = 0;
- ulong temp;
+ unsigned long long temp;
char buf[16]; //enough for all info
acpi_status rv = AE_OK;
@@ -603,7 +603,7 @@ static void set_display(int value)
static int read_display(void)
{
- ulong value = 0;
+ unsigned long long value = 0;
acpi_status rv = AE_OK;
/* In most of the case, we know how to set the display, but sometime
@@ -849,7 +849,7 @@ static int asus_hotk_get_info(void)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *model = NULL;
- ulong bsts_result, hwrs_result;
+ unsigned long long bsts_result, hwrs_result;
char *string = NULL;
acpi_status status;
diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c
index 1ee8501..616bcbd 100644
--- a/drivers/misc/eeepc-laptop.c
+++ b/drivers/misc/eeepc-laptop.c
@@ -204,7 +204,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
static int read_acpi_int(acpi_handle handle, const char *method, int *val)
{
acpi_status status;
- ulong result;
+ unsigned long long result;
status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
if (ACPI_FAILURE(status)) {
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c
index 3e56203..efd395a 100644
--- a/drivers/misc/fujitsu-laptop.c
+++ b/drivers/misc/fujitsu-laptop.c
@@ -224,7 +224,7 @@ static int set_lcd_level_alt(int level)
static int get_lcd_level(void)
{
- unsigned long state = 0;
+ unsigned long long state = 0;
acpi_status status = AE_OK;
vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLL\n");
@@ -246,7 +246,7 @@ static int get_lcd_level(void)
static int get_max_brightness(void)
{
- unsigned long state = 0;
+ unsigned long long state = 0;
acpi_status status = AE_OK;
vdbg_printk(FUJLAPTOP_DBG_TRACE, "get max lcd level via RBLL\n");
@@ -263,7 +263,7 @@ static int get_max_brightness(void)
static int get_lcd_level_alt(void)
{
- unsigned long state = 0;
+ unsigned long long state = 0;
acpi_status status = AE_OK;
vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLS\n");
@@ -384,7 +384,7 @@ static ssize_t store_lcd_level(struct device *dev,
static int get_irb(void)
{
- unsigned long state = 0;
+ unsigned long long state = 0;
acpi_status status = AE_OK;
vdbg_printk(FUJLAPTOP_DBG_TRACE, "Get irb\n");
diff --git a/drivers/misc/intel_menlow.c b/drivers/misc/intel_menlow.c
index 80a1363..bd372ea 100644
--- a/drivers/misc/intel_menlow.c
+++ b/drivers/misc/intel_menlow.c
@@ -57,7 +57,7 @@ static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev,
{
struct acpi_device *device = cdev->devdata;
acpi_handle handle = device->handle;
- unsigned long value;
+ unsigned long long value;
struct acpi_object_list arg_list;
union acpi_object arg;
acpi_status status = AE_OK;
@@ -90,7 +90,7 @@ static int memory_get_cur_bandwidth(struct thermal_cooling_device *cdev,
{
struct acpi_device *device = cdev->devdata;
acpi_handle handle = device->handle;
- unsigned long value;
+ unsigned long long value;
struct acpi_object_list arg_list;
union acpi_object arg;
acpi_status status = AE_OK;
@@ -115,7 +115,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
struct acpi_object_list arg_list;
union acpi_object arg;
acpi_status status;
- int temp;
+ unsigned long long temp;
unsigned long max_state;
if (memory_get_int_max_bandwidth(cdev, &max_state))
@@ -131,7 +131,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
status =
acpi_evaluate_integer(handle, MEMORY_SET_BANDWIDTH, &arg_list,
- (unsigned long *)&temp);
+ &temp);
printk(KERN_INFO
"Bandwidth value was %d: status is %d\n", state, status);
@@ -252,7 +252,8 @@ static DEFINE_MUTEX(intel_menlow_attr_lock);
* @auxtype : AUX0/AUX1
* @buf: syfs buffer
*/
-static int sensor_get_auxtrip(acpi_handle handle, int index, int *value)
+static int sensor_get_auxtrip(acpi_handle handle, int index,
+ unsigned long long *value)
{
acpi_status status;
@@ -260,7 +261,7 @@ static int sensor_get_auxtrip(acpi_handle handle, int index, int *value)
return -EINVAL;
status = acpi_evaluate_integer(handle, index ? GET_AUX1 : GET_AUX0,
- NULL, (unsigned long *)value);
+ NULL, value);
if (ACPI_FAILURE(status))
return -EIO;
@@ -282,13 +283,13 @@ static int sensor_set_auxtrip(acpi_handle handle, int index, int value)
struct acpi_object_list args = {
1, &arg
};
- int temp;
+ unsigned long long temp;
if (index != 0 && index != 1)
return -EINVAL;
status = acpi_evaluate_integer(handle, index ? GET_AUX0 : GET_AUX1,
- NULL, (unsigned long *)&temp);
+ NULL, &temp);
if (ACPI_FAILURE(status))
return -EIO;
if ((index && value < temp) || (!index && value > temp))
@@ -296,7 +297,7 @@ static int sensor_set_auxtrip(acpi_handle handle, int index, int value)
arg.integer.value = value;
status = acpi_evaluate_integer(handle, index ? SET_AUX1 : SET_AUX0,
- &args, (unsigned long *)&temp);
+ &args, &temp);
if (ACPI_FAILURE(status))
return -EIO;
@@ -312,7 +313,7 @@ static ssize_t aux0_show(struct device *dev,
struct device_attribute *dev_attr, char *buf)
{
struct intel_menlow_attribute *attr = to_intel_menlow_attr(dev_attr);
- int value;
+ unsigned long long value;
int result;
result = sensor_get_auxtrip(attr->handle, 0, &value);
@@ -324,7 +325,7 @@ static ssize_t aux1_show(struct device *dev,
struct device_attribute *dev_attr, char *buf)
{
struct intel_menlow_attribute *attr = to_intel_menlow_attr(dev_attr);
- int value;
+ unsigned long long value;
int result;
result = sensor_get_auxtrip(attr->handle, 1, &value);
@@ -376,7 +377,7 @@ static ssize_t bios_enabled_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
acpi_status status;
- unsigned long bios_enabled;
+ unsigned long long bios_enabled;
status = acpi_evaluate_integer(NULL, BIOS_ENABLED, NULL, &bios_enabled);
if (ACPI_FAILURE(status))
@@ -492,7 +493,7 @@ static int __init intel_menlow_module_init(void)
{
int result = -ENODEV;
acpi_status status;
- unsigned long enable;
+ unsigned long long enable;
if (acpi_disabled)
return result;
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index a3e4705..3baee56 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -180,7 +180,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
struct acpiphp_func *newfunc;
acpi_handle tmp;
acpi_status status = AE_OK;
- unsigned long adr, sun;
+ unsigned long long adr, sun;
int device, function, retval;
status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
@@ -528,7 +528,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
{
acpi_status status;
acpi_handle dummy_handle;
- unsigned long tmp;
+ unsigned long long tmp;
int device, function;
struct pci_dev *dev;
struct pci_bus *pci_bus = context;
@@ -573,7 +573,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
static int add_bridge(acpi_handle handle)
{
acpi_status status;
- unsigned long tmp;
+ unsigned long long tmp;
int seg, bus;
acpi_handle dummy_handle;
struct pci_bus *pci_bus;
@@ -767,7 +767,7 @@ static int get_gsi_base(acpi_handle handle, u32 *gsi_base)
{
acpi_status status;
int result = -1;
- unsigned long gsb;
+ unsigned long long gsb;
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
union acpi_object *obj;
void *table;
@@ -808,7 +808,7 @@ static acpi_status
ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv)
{
acpi_status status;
- unsigned long sta;
+ unsigned long long sta;
acpi_handle tmp;
struct pci_dev *pdev;
u32 gsi_base;
@@ -872,7 +872,7 @@ static acpi_status
ioapic_remove(acpi_handle handle, u32 lvl, void *context, void **rv)
{
acpi_status status;
- unsigned long sta;
+ unsigned long long sta;
acpi_handle tmp;
u32 gsi_base;
struct acpiphp_ioapic *pos, *n, *ioapic = NULL;
@@ -1264,7 +1264,7 @@ static int disable_device(struct acpiphp_slot *slot)
static unsigned int get_slot_status(struct acpiphp_slot *slot)
{
acpi_status status;
- unsigned long sta = 0;
+ unsigned long long sta = 0;
u32 dvid;
struct list_head *l;
struct acpiphp_func *func;
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index 2b7c45e..b291ee6 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -183,7 +183,7 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)
union acpi_object args[2];
struct acpi_object_list params = { .pointer = args, .count = 2 };
acpi_status stat;
- unsigned long rc;
+ unsigned long long rc;
union apci_descriptor *ibm_slot;
ibm_slot = ibm_slot_from_id(hpslot_to_sun(slot));
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
index 410fe03..59f4250 100644
--- a/drivers/pci/hotplug/sgi_hotplug.c
+++ b/drivers/pci/hotplug/sgi_hotplug.c
@@ -418,7 +418,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
/*
* Add the slot's devices to the ACPI infrastructure */
if (SN_ACPI_BASE_SUPPORT() && ssdt) {
- unsigned long adr;
+ unsigned long long adr;
struct acpi_device *pdevice;
struct acpi_device *device;
acpi_handle phandle;
@@ -510,7 +510,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
/* free the ACPI resources for the slot */
if (SN_ACPI_BASE_SUPPORT() &&
PCI_CONTROLLER(slot->pci_bus)->acpi_handle) {
- unsigned long adr;
+ unsigned long long adr;
struct acpi_device *device;
acpi_handle phandle;
acpi_handle chandle = NULL;
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index a5ac0bc..c52f10d 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -46,7 +46,7 @@ acpi_extract_package(union acpi_object *package,
acpi_status
acpi_evaluate_integer(acpi_handle handle,
acpi_string pathname,
- struct acpi_object_list *arguments, unsigned long *data);
+ struct acpi_object_list *arguments, unsigned long long *data);
acpi_status
acpi_evaluate_reference(acpi_handle handle,
acpi_string pathname,
--
1.5.5.1
From: Thomas Renninger <[email protected]>
The idea is to add this to printk after the severity:
printk(KERN_ERR FW_BUG "This is not our fault, BIOS developer: fix it by
simply add ...\n");
If a Firmware issue should be hidden, because it is
work-arounded, but you still want to see something popping up e.g.
for info only:
printk(KERN_INFO FW_INFO "This is done stupid, we can handle it,
but it should better be avoided in future\n");
or on the Linuxfirmwarekit to tell vendors that they did something
stupid or wrong without bothering the user:
printk(KERN_INFO FW_BUG "This is done stupid, we can handle it,
but it should better be avoided in future\n");
Some use cases:
- If a user sees a [Firmware Bug] message in the kernel
he should first update the BIOS before wasting time with
debugging and submiting on old firmware code to mailing
lists.
- The linuxfirmwarekit (http://www.linuxfirmwarekit.org)
tries to detect firmware bugs. It currently is doing that
in userspace which results in:
- Huge test scripts that could be a one liner in the kernel
- A lot of BIOS bugs are already absorbed by the kernel
What do we need such a stupid linuxfirmwarekit for?
- Vendors: Can test their BIOSes for Linux compatibility.
There will be the time when vendors realize that the test utils
on Linux are more strict and using them increases the qualitity
and stability of their products.
- Vendors: Can easily fix up their BIOSes and be more Linux
compatible by:
dmesg |grep "Firmware Bug"
and send the result to their BIOS developer colleagues who should
know what the messages are about and how to fix them, without
the need of studying kernel code.
- Distributions: can do a first automated HW/BIOS checks.
This can then be done without the need of asking kernel developers
who need to dig down the code and explain the details.
Certification can/will just be rejected until
dmesg |grep "Firmware Bug" is empty.
- Thus this can be used as an instrument to enforce cleaner BIOS
code. Currently every stupid Windows ACPI bug is
re-implemented in Linux which is a rather unfortunate situation.
We already have the power to avoid this in e.g. memory
or cpu hot-plug ACPI implementations, because Linux certification
is a must for most vendors in the server area.
Working towards being able to do that in the laptop area
(vendors are starting to look at Linux here also and will use this tool)
is the goal. At least provide them a tool to make it as easy
for this guys (e.g. not needing to browse kernel code) as possible.
- The ordinary Linux user: can go into the next shop, boots the
firmwarekit on his most preferred machines. He chooses one without
BIOS bugs. Unsupported HW is ok, he likes to try out latest projects
which might support them or likes to dig on it on his own, but he
hates to workaround broken BIOSes like hell.
I double checked with the firmwarekit.
There they have:
So the mapping generally is (also depending on how likely the BIOS is
to blame, this could sometimes be difficult):
FW_INFO = INFO
FW_WARN = WARN
FW_BUG = FAIL
For more info about the linuxfirmwarekit and why this is needed
can be found here:
http://www.linuxfirmwarekit.org
While severity matches with the firmwarekit, it might be tricky
to hide messages from the user.
E.g. we recently found out that on HP BIOSes negative temperatures
are returned, which seem to indicate that the thermal zone is
invalid.
We can work around that gracefully by ignoring the thermal zone
and we do not want to bother the ordinary user with a frightening
message: Firmware Bug: thermal management absolutely broken
but want to hide it from the user.
But in the linuxfirmwarekit this should be shown as a real
show stopper (the temperatures could really be wrong,
broken thermal management is one of the worst things
that can happen and the BIOS guys of the machine must
implement this properly).
It is intended to do that (hide it from the user with
KERN_INFO msg, but still print it as a BIOS bug) by:
printk(KERN_INFO FW_BUG "Negativ temperature values detected.
Try to workarounded, BIOS must get fixed\n");
Hope that works out..., no idea how to better hide it
as printk is the only way to easily provide this functionality.
Signed-off-by: Thomas Renninger <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
include/linux/kernel.h | 24 ++++++++++++++++++++++++
1 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 2651f80..0b19848 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -190,6 +190,30 @@ extern int kernel_text_address(unsigned long addr);
struct pid;
extern struct pid *session_of_pgrp(struct pid *pgrp);
+/*
+ * FW_BUG
+ * Add this to a message where you are sure the firmware is buggy or behaves
+ * really stupid or out of spec. Be aware that the responsible BIOS developer
+ * should be able to fix this issue or at least get a concrete idea of the
+ * problem by reading your message without the need of looking at the kernel
+ * code.
+ *
+ * Use it for definite and high priority BIOS bugs.
+ *
+ * FW_WARN
+ * Use it for not that clear (e.g. could the kernel messed up things already?)
+ * and medium priority BIOS bugs.
+ *
+ * FW_INFO
+ * Use this one if you want to tell the user or vendor about something
+ * suspicious, but generally harmless related to the firmware.
+ *
+ * Use it for information or very low priority BIOS bugs.
+ */
+#define FW_BUG "[Firmware Bug]: "
+#define FW_WARN "[Firmware Warn]: "
+#define FW_INFO "[Firmware Info]: "
+
#ifdef CONFIG_PRINTK
asmlinkage int vprintk(const char *fmt, va_list args)
__attribute__ ((format (printf, 1, 0)));
--
1.5.5.1
From: Jonathan Woithe <[email protected]>
This patch (mostly from Peter Gruber) improves the handling of the hotkeys
for P8010 laptops by passing more accurate input events back to userspace.
This is needed because the P8010 labels these buttons quite differently to
earlier laptops. As part of this, a P8010-specific DMI callback check has
been implemented. Finally there's some minor whitespace cleanups from
running the source through Lindent.
Signed-off-by: Peter Gruber <[email protected]>
Signed-off-by: Jonathan Woithe <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/misc/fujitsu-laptop.c | 123 +++++++++++++++++++++++-----------------
1 files changed, 71 insertions(+), 52 deletions(-)
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c
index 3e56203..f861db0 100644
--- a/drivers/misc/fujitsu-laptop.c
+++ b/drivers/misc/fujitsu-laptop.c
@@ -44,8 +44,9 @@
* Hotkeys present on certain Fujitsu laptops (eg: the S6xxx series) are
* also supported by this driver.
*
- * This driver has been tested on a Fujitsu Lifebook S6410 and S7020. It
- * should work on most P-series and S-series Lifebooks, but YMMV.
+ * This driver has been tested on a Fujitsu Lifebook S6410, S7020 and
+ * P8010. It should work on most P-series and S-series Lifebooks, but
+ * YMMV.
*
* The module parameter use_alt_lcd_levels switches between different ACPI
* brightness controls which are used by different Fujitsu laptops. In most
@@ -65,7 +66,7 @@
#include <linux/video_output.h>
#include <linux/platform_device.h>
-#define FUJITSU_DRIVER_VERSION "0.4.2"
+#define FUJITSU_DRIVER_VERSION "0.4.3"
#define FUJITSU_LCD_N_LEVELS 8
@@ -83,10 +84,10 @@
#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87
/* Hotkey details */
-#define LOCK_KEY 0x410 /* codes for the keys in the GIRB register */
-#define DISPLAY_KEY 0x411 /* keys are mapped to KEY_SCREENLOCK (the key with the key symbol) */
-#define ENERGY_KEY 0x412 /* KEY_MEDIA (the key with the laptop symbol, KEY_EMAIL (E key)) */
-#define REST_KEY 0x413 /* KEY_SUSPEND (R key) */
+#define KEY1_CODE 0x410 /* codes for the keys in the GIRB register */
+#define KEY2_CODE 0x411
+#define KEY3_CODE 0x412
+#define KEY4_CODE 0x413
#define MAX_HOTKEY_RINGBUFFER_SIZE 100
#define RINGBUFFERSIZE 40
@@ -123,6 +124,7 @@ struct fujitsu_t {
char phys[32];
struct backlight_device *bl_device;
struct platform_device *pf_device;
+ int keycode1, keycode2, keycode3, keycode4;
unsigned int max_brightness;
unsigned int brightness_changed;
@@ -430,7 +432,7 @@ static struct platform_driver fujitsupf_driver = {
}
};
-static int dmi_check_cb_s6410(const struct dmi_system_id *id)
+static void dmi_check_cb_common(const struct dmi_system_id *id)
{
acpi_handle handle;
int have_blnf;
@@ -452,24 +454,40 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id)
"auto-detecting disable_adjust\n");
disable_brightness_adjust = have_blnf ? 0 : 1;
}
+}
+
+static int dmi_check_cb_s6410(const struct dmi_system_id *id)
+{
+ dmi_check_cb_common(id);
+ fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */
+ fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */
+ return 0;
+}
+
+static int dmi_check_cb_p8010(const struct dmi_system_id *id)
+{
+ dmi_check_cb_common(id);
+ fujitsu->keycode1 = KEY_HELP; /* "Support" */
+ fujitsu->keycode3 = KEY_SWITCHVIDEOMODE; /* "Presentation" */
+ fujitsu->keycode4 = KEY_WWW; /* "Internet" */
return 0;
}
static struct dmi_system_id __initdata fujitsu_dmi_table[] = {
{
- .ident = "Fujitsu Siemens",
+ .ident = "Fujitsu Siemens S6410",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"),
},
.callback = dmi_check_cb_s6410},
{
- .ident = "FUJITSU LifeBook P8010",
+ .ident = "Fujitsu LifeBook P8010",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"),
- },
- .callback = dmi_check_cb_s6410},
+ },
+ .callback = dmi_check_cb_p8010},
{}
};
@@ -547,7 +565,6 @@ static int acpi_fujitsu_add(struct acpi_device *device)
}
/* do config (detect defaults) */
- dmi_check_system(fujitsu_dmi_table);
use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0;
disable_brightness_keys = disable_brightness_keys == 1 ? 1 : 0;
disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0;
@@ -623,17 +640,17 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
keycode = 0;
if (disable_brightness_keys != 1) {
if (oldb == 0) {
- acpi_bus_generate_proc_event(fujitsu->
- dev,
- ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS,
- 0);
+ acpi_bus_generate_proc_event
+ (fujitsu->dev,
+ ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS,
+ 0);
keycode = KEY_BRIGHTNESSDOWN;
} else if (oldb ==
(fujitsu->max_brightness) - 1) {
- acpi_bus_generate_proc_event(fujitsu->
- dev,
- ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS,
- 0);
+ acpi_bus_generate_proc_event
+ (fujitsu->dev,
+ ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS,
+ 0);
keycode = KEY_BRIGHTNESSUP;
}
}
@@ -646,8 +663,7 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
}
if (disable_brightness_keys != 1) {
acpi_bus_generate_proc_event(fujitsu->dev,
- ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS,
- 0);
+ ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, 0);
keycode = KEY_BRIGHTNESSUP;
}
} else if (oldb > newb) {
@@ -659,8 +675,7 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
}
if (disable_brightness_keys != 1) {
acpi_bus_generate_proc_event(fujitsu->dev,
- ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS,
- 0);
+ ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, 0);
keycode = KEY_BRIGHTNESSDOWN;
}
} else {
@@ -742,10 +757,10 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
input->id.product = 0x06;
input->dev.parent = &device->dev;
input->evbit[0] = BIT(EV_KEY);
- set_bit(KEY_SCREENLOCK, input->keybit);
- set_bit(KEY_MEDIA, input->keybit);
- set_bit(KEY_EMAIL, input->keybit);
- set_bit(KEY_SUSPEND, input->keybit);
+ set_bit(fujitsu->keycode1, input->keybit);
+ set_bit(fujitsu->keycode2, input->keybit);
+ set_bit(fujitsu->keycode3, input->keybit);
+ set_bit(fujitsu->keycode4, input->keybit);
set_bit(KEY_UNKNOWN, input->keybit);
error = input_register_device(input);
@@ -833,24 +848,24 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
irb);
switch (irb & 0x4ff) {
- case LOCK_KEY:
- keycode = KEY_SCREENLOCK;
+ case KEY1_CODE:
+ keycode = fujitsu->keycode1;
break;
- case DISPLAY_KEY:
- keycode = KEY_MEDIA;
+ case KEY2_CODE:
+ keycode = fujitsu->keycode2;
break;
- case ENERGY_KEY:
- keycode = KEY_EMAIL;
+ case KEY3_CODE:
+ keycode = fujitsu->keycode3;
break;
- case REST_KEY:
- keycode = KEY_SUSPEND;
+ case KEY4_CODE:
+ keycode = fujitsu->keycode4;
break;
case 0:
keycode = 0;
break;
default:
vdbg_printk(FUJLAPTOP_DBG_WARN,
- "Unknown GIRB result [%x]\n", irb);
+ "Unknown GIRB result [%x]\n", irb);
keycode = -1;
break;
}
@@ -859,12 +874,12 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
"Push keycode into ringbuffer [%d]\n",
keycode);
status = kfifo_put(fujitsu_hotkey->fifo,
- (unsigned char *)&keycode,
- sizeof(keycode));
+ (unsigned char *)&keycode,
+ sizeof(keycode));
if (status != sizeof(keycode)) {
vdbg_printk(FUJLAPTOP_DBG_WARN,
- "Could not push keycode [0x%x]\n",
- keycode);
+ "Could not push keycode [0x%x]\n",
+ keycode);
} else {
input_report_key(input, keycode, 1);
input_sync(input);
@@ -879,8 +894,8 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
input_report_key(input, keycode_r, 0);
input_sync(input);
vdbg_printk(FUJLAPTOP_DBG_TRACE,
- "Pop keycode from ringbuffer [%d]\n",
- keycode_r);
+ "Pop keycode from ringbuffer [%d]\n",
+ keycode_r);
}
}
}
@@ -943,6 +958,11 @@ static int __init fujitsu_init(void)
if (!fujitsu)
return -ENOMEM;
memset(fujitsu, 0, sizeof(struct fujitsu_t));
+ fujitsu->keycode1 = KEY_PROG1;
+ fujitsu->keycode2 = KEY_PROG2;
+ fujitsu->keycode3 = KEY_PROG3;
+ fujitsu->keycode4 = KEY_PROG4;
+ dmi_check_system(fujitsu_dmi_table);
result = acpi_bus_register_driver(&acpi_fujitsu_driver);
if (result < 0) {
@@ -1076,15 +1096,14 @@ MODULE_DESCRIPTION("Fujitsu laptop extras support");
MODULE_VERSION(FUJITSU_DRIVER_VERSION);
MODULE_LICENSE("GPL");
-MODULE_ALIAS
- ("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*");
-MODULE_ALIAS
- ("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
+MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*");
+MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
static struct pnp_device_id pnp_ids[] = {
- { .id = "FUJ02bf" },
- { .id = "FUJ02B1" },
- { .id = "FUJ02E3" },
- { .id = "" }
+ {.id = "FUJ02bf"},
+ {.id = "FUJ02B1"},
+ {.id = "FUJ02E3"},
+ {.id = ""}
};
+
MODULE_DEVICE_TABLE(pnp, pnp_ids);
--
1.5.5.1
From: Dennis Noordsij <[email protected]>
Previously, dynamically loaded tables were simply mapped, but on some machines
this memory is corrupted after suspend. Now copy the table to a local buffer.
For OpRegion case, added checksum verify. Use the table length from the table header,
not the region length. For Buffer case, use the table length also.
http://bugzilla.kernel.org/show_bug.cgi?id=10734
Signed-off-by: Dennis Noordsij <[email protected]>
Signed-off-by: Bob Moore <[email protected]>
Signed-off-by: Lin Ming <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/executer/exconfig.c | 113 +++++++++++++++++++++++++++----------
1 files changed, 82 insertions(+), 31 deletions(-)
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
index 8892b98..331a114 100644
--- a/drivers/acpi/executer/exconfig.c
+++ b/drivers/acpi/executer/exconfig.c
@@ -280,6 +280,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state)
{
union acpi_operand_object *ddb_handle;
+ struct acpi_table_header *table;
struct acpi_table_desc table_desc;
u32 table_index;
acpi_status status;
@@ -294,9 +295,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_REGION:
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n",
- obj_desc,
- acpi_ut_get_object_type_name(obj_desc)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Load table from Region %p\n", obj_desc));
/* Region must be system_memory (from ACPI spec) */
@@ -316,61 +316,112 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
}
/*
- * We will simply map the memory region for the table. However, the
- * memory region is technically not guaranteed to remain stable and
- * we may eventually have to copy the table to a local buffer.
+ * Map the table header and get the actual table length. The region
+ * length is not guaranteed to be the same as the table length.
+ */
+ table = acpi_os_map_memory(obj_desc->region.address,
+ sizeof(struct acpi_table_header));
+ if (!table) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ length = table->length;
+ acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
+
+ /* Must have at least an ACPI table header */
+
+ if (length < sizeof(struct acpi_table_header)) {
+ return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
+ }
+
+ /*
+ * The memory region is not guaranteed to remain stable and we must
+ * copy the table to a local buffer. For example, the memory region
+ * is corrupted after suspend on some machines. Dynamically loaded
+ * tables are usually small, so this overhead is minimal.
*/
+
+ /* Allocate a buffer for the table */
+
+ table_desc.pointer = ACPI_ALLOCATE(length);
+ if (!table_desc.pointer) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ /* Map the entire table and copy it */
+
+ table = acpi_os_map_memory(obj_desc->region.address, length);
+ if (!table) {
+ ACPI_FREE(table_desc.pointer);
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ ACPI_MEMCPY(table_desc.pointer, table, length);
+ acpi_os_unmap_memory(table, length);
+
table_desc.address = obj_desc->region.address;
- table_desc.length = obj_desc->region.length;
- table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED;
break;
case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Load from Buffer or Field %p %s\n", obj_desc,
- acpi_ut_get_object_type_name(obj_desc)));
-
- length = obj_desc->buffer.length;
+ "Load table from Buffer or Field %p\n",
+ obj_desc));
/* Must have at least an ACPI table header */
- if (length < sizeof(struct acpi_table_header)) {
+ if (obj_desc->buffer.length < sizeof(struct acpi_table_header)) {
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
}
- /* Validate checksum here. It won't get validated in tb_add_table */
+ /* Get the actual table length from the table header */
- status =
- acpi_tb_verify_checksum(ACPI_CAST_PTR
- (struct acpi_table_header,
- obj_desc->buffer.pointer), length);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
+ table =
+ ACPI_CAST_PTR(struct acpi_table_header,
+ obj_desc->buffer.pointer);
+ length = table->length;
+
+ /* Table cannot extend beyond the buffer */
+
+ if (length > obj_desc->buffer.length) {
+ return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
+ }
+ if (length < sizeof(struct acpi_table_header)) {
+ return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
}
/*
- * We need to copy the buffer since the original buffer could be
- * changed or deleted in the future
+ * Copy the table from the buffer because the buffer could be modified
+ * or even deleted in the future
*/
table_desc.pointer = ACPI_ALLOCATE(length);
if (!table_desc.pointer) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
- ACPI_MEMCPY(table_desc.pointer, obj_desc->buffer.pointer,
- length);
- table_desc.length = length;
- table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED;
+ ACPI_MEMCPY(table_desc.pointer, table, length);
+ table_desc.address = ACPI_TO_INTEGER(table_desc.pointer);
break;
default:
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
- /*
- * Install the new table into the local data structures
- */
+ /* Validate table checksum (will not get validated in tb_add_table) */
+
+ status = acpi_tb_verify_checksum(table_desc.pointer, length);
+ if (ACPI_FAILURE(status)) {
+ ACPI_FREE(table_desc.pointer);
+ return_ACPI_STATUS(status);
+ }
+
+ /* Complete the table descriptor */
+
+ table_desc.length = length;
+ table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED;
+
+ /* Install the new table into the local data structures */
+
status = acpi_tb_add_table(&table_desc, &table_index);
if (ACPI_FAILURE(status)) {
goto cleanup;
@@ -379,7 +430,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
/*
* Add the table to the namespace.
*
- * Note: We load the table objects relative to the root of the namespace.
+ * Note: Load the table objects relative to the root of the namespace.
* This appears to go against the ACPI specification, but we do it for
* compatibility with other ACPI implementations.
*/
@@ -415,7 +466,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
cleanup:
if (ACPI_FAILURE(status)) {
- /* Delete allocated buffer or mapping */
+ /* Delete allocated table buffer */
acpi_tb_delete_table(&table_desc);
}
--
1.5.5.1
From: Yi Yang <[email protected]>
Return status from acpi_ut_init_globals. This is used by both
the kernel subsystem and the utilities such as iASL compiler.
The function could possibly fail when the caches are initialized.
Yang Yi.
Signed-off-by: Yi Yang <[email protected]>
Signed-off-by: Bob Moore <[email protected]>
Signed-off-by: Lin Ming <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/utilities/utglobal.c | 8 ++++----
drivers/acpi/utilities/utxface.c | 7 ++++++-
include/acpi/acutils.h | 2 +-
3 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
index a6e71b8..248eefc 100644
--- a/drivers/acpi/utilities/utglobal.c
+++ b/drivers/acpi/utilities/utglobal.c
@@ -677,14 +677,14 @@ u8 acpi_ut_valid_object_type(acpi_object_type type)
*
* PARAMETERS: None
*
- * RETURN: None
+ * RETURN: Status
*
* DESCRIPTION: Init library globals. All globals that require specific
* initialization should be initialized here!
*
******************************************************************************/
-void acpi_ut_init_globals(void)
+acpi_status acpi_ut_init_globals(void)
{
acpi_status status;
u32 i;
@@ -695,7 +695,7 @@ void acpi_ut_init_globals(void)
status = acpi_ut_create_caches();
if (ACPI_FAILURE(status)) {
- return;
+ return_ACPI_STATUS(status);
}
/* Mutex locked flags */
@@ -772,7 +772,7 @@ void acpi_ut_init_globals(void)
acpi_gbl_display_final_mem_stats = FALSE;
#endif
- return_VOID;
+ return_ACPI_STATUS(AE_OK);
}
ACPI_EXPORT_SYMBOL(acpi_dbg_level)
diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c
index f8bdadf..c198a4d 100644
--- a/drivers/acpi/utilities/utxface.c
+++ b/drivers/acpi/utilities/utxface.c
@@ -81,7 +81,12 @@ acpi_status __init acpi_initialize_subsystem(void)
/* Initialize all globals used by the subsystem */
- acpi_ut_init_globals();
+ status = acpi_ut_init_globals();
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "During initialization of globals"));
+ return_ACPI_STATUS(status);
+ }
/* Create the default mutex objects */
diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h
index 69f8888..10ce814 100644
--- a/include/acpi/acutils.h
+++ b/include/acpi/acutils.h
@@ -110,7 +110,7 @@ struct acpi_pkg_info {
/*
* utglobal - Global data structures and procedures
*/
-void acpi_ut_init_globals(void);
+acpi_status acpi_ut_init_globals(void);
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
--
1.5.5.1
From: Zhang Rui <[email protected]>
don't enable control method power button as wakeup device
when Fixed Power button is used.
http://bugzilla.kernel.org/show_bug.cgi?id=10503
Tested-by: [email protected] <[email protected]>
Signed-off-by: Zhang Rui <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/scan.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index f6f52c1..5ce14ae 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -744,6 +744,16 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
if (!acpi_match_device_ids(device, button_device_ids))
device->wakeup.flags.run_wake = 1;
+ /*
+ * Don't set Power button GPE as run_wake
+ * if Fixed Power button is used
+ */
+ if (!strcmp(device->pnp.hardware_id, "PNP0C0C") &&
+ !(acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON)) {
+ device->wakeup.flags.run_wake = 0;
+ device->wakeup.flags.valid = 0;
+ }
+
end:
if (ACPI_FAILURE(status))
device->flags.wake_capable = 0;
--
1.5.5.1
From: Len Brown <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
MAINTAINERS | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index cad81a2..7212af7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1417,8 +1417,8 @@ M: [email protected]
S: Maintained
DOCKING STATION DRIVER
-P: Kristen Carlson Accardi
-M: [email protected]
+P: Shaohua Li
+M: [email protected]
L: [email protected]
S: Supported
--
1.5.5.1
From: Shaohua Li <[email protected]>
add a sysfs file to present dock type. Suggested by Holger.
Signed-off-by: Shaohua Li <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/dock.c | 25 +++++++++++++++++++++++++
1 files changed, 25 insertions(+), 0 deletions(-)
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index c877cc5..b7d1581 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -911,6 +911,26 @@ static ssize_t show_dock_uid(struct device *dev,
}
static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
+static ssize_t show_dock_type(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dock_station *dock_station = *((struct dock_station **)
+ dev->platform_data);
+ char *type;
+
+ if (dock_station->flags & DOCK_IS_DOCK)
+ type = "dock_station";
+ else if (dock_station->flags & DOCK_IS_ATA)
+ type = "ata_bay";
+ else if (dock_station->flags & DOCK_IS_BAT)
+ type = "battery_bay";
+ else
+ type = "unknown";
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", type);
+}
+static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL);
+
/**
* dock_add - add a new dock station
* @handle: the dock station handle
@@ -999,6 +1019,9 @@ static int dock_add(acpi_handle handle)
dock_station = NULL;
return ret;
}
+ ret = device_create_file(&dock_device->dev, &dev_attr_type);
+ if (ret)
+ printk(KERN_ERR"Error %d adding sysfs file\n", ret);
/* Find dependent devices */
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
@@ -1020,6 +1043,7 @@ static int dock_add(acpi_handle handle)
return 0;
dock_add_err_unregister:
+ device_remove_file(&dock_device->dev, &dev_attr_type);
device_remove_file(&dock_device->dev, &dev_attr_docked);
device_remove_file(&dock_device->dev, &dev_attr_undock);
device_remove_file(&dock_device->dev, &dev_attr_uid);
@@ -1047,6 +1071,7 @@ static int dock_remove(struct dock_station *dock_station)
kfree(dd);
/* cleanup sysfs */
+ device_remove_file(&dock_device->dev, &dev_attr_type);
device_remove_file(&dock_device->dev, &dev_attr_docked);
device_remove_file(&dock_device->dev, &dev_attr_undock);
device_remove_file(&dock_device->dev, &dev_attr_uid);
--
1.5.5.1
From: Alexey Starikovskiy <[email protected]>
No functional changes.
Signed-off-by: Alexey Starikovskiy <[email protected]>
Acked-by: Rafael J. Wysocki <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/ec.c | 118 ++++++++++++++++++++++++++++-------------------------
1 files changed, 63 insertions(+), 55 deletions(-)
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 7f0d81c..453ba1e 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -95,10 +95,11 @@ struct acpi_ec_query_handler {
u8 query_bit;
};
-struct transaction_data {
+struct transaction {
const u8 *wdata;
u8 *rdata;
unsigned short irq_count;
+ u8 command;
u8 wlen;
u8 rlen;
};
@@ -113,8 +114,8 @@ static struct acpi_ec {
struct mutex lock;
wait_queue_head_t wait;
struct list_head list;
- struct transaction_data *t;
- spinlock_t t_lock;
+ struct transaction *curr;
+ spinlock_t curr_lock;
} *boot_ec, *first_ec;
/*
@@ -176,37 +177,37 @@ static int ec_transaction_done(struct acpi_ec *ec)
{
unsigned long flags;
int ret = 0;
- spin_lock_irqsave(&ec->t_lock, flags);
- if (!ec->t || (!ec->t->wlen && !ec->t->rlen))
+ spin_lock_irqsave(&ec->curr_lock, flags);
+ if (!ec->curr || (!ec->curr->wlen && !ec->curr->rlen))
ret = 1;
- spin_unlock_irqrestore(&ec->t_lock, flags);
+ spin_unlock_irqrestore(&ec->curr_lock, flags);
return ret;
}
static void gpe_transaction(struct acpi_ec *ec, u8 status)
{
unsigned long flags;
- spin_lock_irqsave(&ec->t_lock, flags);
- if (!ec->t)
+ spin_lock_irqsave(&ec->curr_lock, flags);
+ if (!ec->curr)
goto unlock;
- if (ec->t->wlen > 0) {
+ if (ec->curr->wlen > 0) {
if ((status & ACPI_EC_FLAG_IBF) == 0) {
- acpi_ec_write_data(ec, *(ec->t->wdata++));
- --ec->t->wlen;
+ acpi_ec_write_data(ec, *(ec->curr->wdata++));
+ --ec->curr->wlen;
} else
/* false interrupt, state didn't change */
- ++ec->t->irq_count;
+ ++ec->curr->irq_count;
- } else if (ec->t->rlen > 0) {
+ } else if (ec->curr->rlen > 0) {
if ((status & ACPI_EC_FLAG_OBF) == 1) {
- *(ec->t->rdata++) = acpi_ec_read_data(ec);
- --ec->t->rlen;
+ *(ec->curr->rdata++) = acpi_ec_read_data(ec);
+ --ec->curr->rlen;
} else
/* false interrupt, state didn't change */
- ++ec->t->irq_count;
+ ++ec->curr->irq_count;
}
unlock:
- spin_unlock_irqrestore(&ec->t_lock, flags);
+ spin_unlock_irqrestore(&ec->curr_lock, flags);
}
static int acpi_ec_wait(struct acpi_ec *ec)
@@ -248,15 +249,11 @@ static int ec_poll(struct acpi_ec *ec)
return -ETIME;
}
-static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
- const u8 * wdata, unsigned wdata_len,
- u8 * rdata, unsigned rdata_len,
+static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
+ struct transaction *t,
int force_poll)
{
unsigned long tmp;
- struct transaction_data t = {.wdata = wdata, .rdata = rdata,
- .wlen = wdata_len, .rlen = rdata_len,
- .irq_count = 0};
int ret = 0;
pr_debug(PREFIX "transaction start\n");
/* disable GPE during transaction if storm is detected */
@@ -265,29 +262,30 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
}
/* start transaction */
- spin_lock_irqsave(&ec->t_lock, tmp);
+ spin_lock_irqsave(&ec->curr_lock, tmp);
/* following two actions should be kept atomic */
- ec->t = &t;
- acpi_ec_write_cmd(ec, command);
- if (command == ACPI_EC_COMMAND_QUERY)
+ t->irq_count = 0;
+ ec->curr = t;
+ acpi_ec_write_cmd(ec, ec->curr->command);
+ if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
- spin_unlock_irqrestore(&ec->t_lock, tmp);
+ spin_unlock_irqrestore(&ec->curr_lock, tmp);
/* if we selected poll mode or failed in GPE-mode do a poll loop */
if (force_poll ||
!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) ||
acpi_ec_wait(ec))
ret = ec_poll(ec);
pr_debug(PREFIX "transaction end\n");
- spin_lock_irqsave(&ec->t_lock, tmp);
- ec->t = NULL;
- spin_unlock_irqrestore(&ec->t_lock, tmp);
+ spin_lock_irqsave(&ec->curr_lock, tmp);
+ ec->curr = NULL;
+ spin_unlock_irqrestore(&ec->curr_lock, tmp);
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
/* check if we received SCI during transaction */
ec_check_sci(ec, acpi_ec_read_status(ec));
/* it is safe to enable GPE outside of transaction */
acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
} else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
- t.irq_count > ACPI_EC_STORM_THRESHOLD) {
+ t->irq_count > ACPI_EC_STORM_THRESHOLD) {
pr_debug(PREFIX "GPE storm detected\n");
set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
}
@@ -300,17 +298,15 @@ static int ec_check_ibf0(struct acpi_ec *ec)
return (status & ACPI_EC_FLAG_IBF) == 0;
}
-static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
- const u8 * wdata, unsigned wdata_len,
- u8 * rdata, unsigned rdata_len,
+static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t,
int force_poll)
{
int status;
u32 glk;
- if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata))
+ if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata))
return -EINVAL;
- if (rdata)
- memset(rdata, 0, rdata_len);
+ if (t->rdata)
+ memset(t->rdata, 0, t->rlen);
mutex_lock(&ec->lock);
if (ec->global_lock) {
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
@@ -326,10 +322,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
status = -ETIME;
goto end;
}
- status = acpi_ec_transaction_unlocked(ec, command,
- wdata, wdata_len,
- rdata, rdata_len,
- force_poll);
+ status = acpi_ec_transaction_unlocked(ec, t, force_poll);
end:
if (ec->global_lock)
acpi_release_global_lock(glk);
@@ -345,23 +338,32 @@ unlock:
int acpi_ec_burst_enable(struct acpi_ec *ec)
{
u8 d;
- return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1, 0);
+ struct transaction t = {.command = ACPI_EC_BURST_ENABLE,
+ .wdata = NULL, .rdata = &d,
+ .wlen = 0, .rlen = 1};
+
+ return acpi_ec_transaction(ec, &t, 0);
}
int acpi_ec_burst_disable(struct acpi_ec *ec)
{
+ struct transaction t = {.command = ACPI_EC_BURST_DISABLE,
+ .wdata = NULL, .rdata = NULL,
+ .wlen = 0, .rlen = 0};
+
return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ?
- acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE,
- NULL, 0, NULL, 0, 0) : 0;
+ acpi_ec_transaction(ec, &t, 0) : 0;
}
static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
{
int result;
u8 d;
+ struct transaction t = {.command = ACPI_EC_COMMAND_READ,
+ .wdata = &address, .rdata = &d,
+ .wlen = 1, .rlen = 1};
- result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ,
- &address, 1, &d, 1, 0);
+ result = acpi_ec_transaction(ec, &t, 0);
*data = d;
return result;
}
@@ -369,8 +371,11 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
{
u8 wdata[2] = { address, data };
- return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE,
- wdata, 2, NULL, 0, 0);
+ struct transaction t = {.command = ACPI_EC_COMMAND_WRITE,
+ .wdata = wdata, .rdata = NULL,
+ .wlen = 2, .rlen = 0};
+
+ return acpi_ec_transaction(ec, &t, 0);
}
/*
@@ -432,12 +437,13 @@ int ec_transaction(u8 command,
u8 * rdata, unsigned rdata_len,
int force_poll)
{
+ struct transaction t = {.command = command,
+ .wdata = wdata, .rdata = rdata,
+ .wlen = wdata_len, .rlen = rdata_len};
if (!first_ec)
return -ENODEV;
- return acpi_ec_transaction(first_ec, command, wdata,
- wdata_len, rdata, rdata_len,
- force_poll);
+ return acpi_ec_transaction(first_ec, &t, force_poll);
}
EXPORT_SYMBOL(ec_transaction);
@@ -446,7 +452,9 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
{
int result;
u8 d;
-
+ struct transaction t = {.command = ACPI_EC_COMMAND_QUERY,
+ .wdata = NULL, .rdata = &d,
+ .wlen = 0, .rlen = 1};
if (!ec || !data)
return -EINVAL;
@@ -456,7 +464,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
* bit to be cleared (and thus clearing the interrupt source).
*/
- result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1, 0);
+ result = acpi_ec_transaction(ec, &t, 0);
if (result)
return result;
@@ -696,7 +704,7 @@ static struct acpi_ec *make_acpi_ec(void)
mutex_init(&ec->lock);
init_waitqueue_head(&ec->wait);
INIT_LIST_HEAD(&ec->list);
- spin_lock_init(&ec->t_lock);
+ spin_lock_init(&ec->curr_lock);
return ec;
}
--
1.5.5.1
From: Zhao Yakui <[email protected]>
According to ACPI spec when the status of some device is not present
but functional, the device is valid and the children of this device
should be enumerated. It means that the device should be added to
linux acpi device tree. But the device driver for this device should not
be loaded.
The detailed info can be found in the section 6.3.7 of ACPI 3.0b spec.
_STA may return bit 0 clear (not present) with bit 3 set (device is
functional). This case is used to indicate a valid device for which no
device driver should be loaded (for example, a bridge device.).
Children of this device may be present and valid. OS should continue
enumeration below a device whose _STA returns this bit combination
http://bugzilla.kernel.org/show_bug.cgi?id=3358
Signed-off-by: Zhao Yakui <[email protected]>
Signed-off-by: Li Shaohua <[email protected]>
Signed-off-by: Zhang Rui <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
---
drivers/acpi/bus.c | 16 ++++++++--------
drivers/acpi/scan.c | 35 +++++++++++++++++++++++++----------
drivers/pnp/pnpacpi/core.c | 6 +++++-
3 files changed, 38 insertions(+), 19 deletions(-)
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 945cd2f..e9b116d 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -112,21 +112,21 @@ int acpi_bus_get_status(struct acpi_device *device)
}
/*
- * Otherwise we assume the status of our parent (unless we don't
- * have one, in which case status is implied).
+ * According to ACPI spec some device can be present and functional
+ * even if the parent is not present but functional.
+ * In such conditions the child device should not inherit the status
+ * from the parent.
*/
- else if (device->parent)
- device->status = device->parent->status;
else
STRUCT_TO_INT(device->status) =
ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING;
if (device->status.functional && !device->status.present) {
- printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: "
- "functional but not present; setting present\n",
- device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status));
- device->status.present = 1;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]: "
+ "functional but not present;\n",
+ device->pnp.bus_id,
+ (u32) STRUCT_TO_INT(device->status)));
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n",
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index ad06798..89c112e 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -276,6 +276,13 @@ int acpi_match_device_ids(struct acpi_device *device,
{
const struct acpi_device_id *id;
+ /*
+ * If the device is not present, it is unnecessary to load device
+ * driver for it.
+ */
+ if (!device->status.present)
+ return -ENODEV;
+
if (device->flags.hardware_id) {
for (id = ids; id->id[0]; id++) {
if (!strcmp((char*)id->id, device->pnp.hardware_id))
@@ -1222,15 +1229,18 @@ acpi_add_single_object(struct acpi_device **child,
result = -ENODEV;
goto end;
}
- if (!device->status.present) {
- /* Bay and dock should be handled even if absent */
- if (!ACPI_SUCCESS(
- acpi_is_child_device(device, acpi_bay_match)) &&
- !ACPI_SUCCESS(
- acpi_is_child_device(device, acpi_dock_match))) {
- result = -ENODEV;
- goto end;
- }
+ /*
+ * When the device is neither present nor functional, the
+ * device should not be added to Linux ACPI device tree.
+ * When the status of the device is not present but functinal,
+ * it should be added to Linux ACPI tree. For example : bay
+ * device , dock device.
+ * In such conditions it is unncessary to check whether it is
+ * bay device or dock device.
+ */
+ if (!device->status.present && !device->status.functional) {
+ result = -ENODEV;
+ goto end;
}
break;
default:
@@ -1411,7 +1421,12 @@ static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops)
* TBD: Need notifications and other detection mechanisms
* in place before we can fully implement this.
*/
- if (child->status.present) {
+ /*
+ * When the device is not present but functional, it is also
+ * necessary to scan the children of this device.
+ */
+ if (child->status.present || (!child->status.present &&
+ child->status.functional)) {
status = acpi_get_next_object(ACPI_TYPE_ANY, chandle,
NULL, NULL);
if (ACPI_SUCCESS(status)) {
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index c1b9ea3..98b9df7 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -148,9 +148,13 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
acpi_status status;
struct pnp_dev *dev;
+ /*
+ * If a PnPacpi device is not present , the device
+ * driver should not be loaded.
+ */
status = acpi_get_handle(device->handle, "_CRS", &temp);
if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) ||
- is_exclusive_device(device))
+ is_exclusive_device(device) || (!device->status.present))
return 0;
dev = pnp_alloc_dev(&pnpacpi_protocol, num, acpi_device_hid(device));
--
1.5.5.1
From: Zhang Rui <[email protected]>
The hotplug notification handler and drivers' notification handler all
run in one workqueue. Before hotplug removes an acpi device, the
device driver's notification handler is already be recorded to run just
after global notification handler. After hotplug notification handler
runs, acpica will notice a NULL notification handler and crash.
So now we run run hotplug in another workqueue and wait
for all acpi notication handlers finish.
This was found in battery hotplug, but actually all
hotplug can be affected.
Signed-off-by: Zhang Rui <[email protected]>
Signed-off-by: Shaohua Li <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/dock.c | 25 ++++++++++++++++++++++++-
drivers/acpi/osl.c | 46 +++++++++++++++++++++++++++++++++++++++++-----
include/acpi/acpiosxf.h | 3 +++
3 files changed, 68 insertions(+), 6 deletions(-)
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 2563bc6..4b395b1 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -748,6 +748,20 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
}
}
+struct dock_data {
+ acpi_handle handle;
+ unsigned long event;
+ struct dock_station *ds;
+};
+
+static void acpi_dock_deferred_cb(void *context)
+{
+ struct dock_data *data = (struct dock_data *)context;
+
+ dock_notify(data->handle, data->event, data->ds);
+ kfree(data);
+}
+
static int acpi_dock_notifier_call(struct notifier_block *this,
unsigned long event, void *data)
{
@@ -759,7 +773,16 @@ static int acpi_dock_notifier_call(struct notifier_block *this,
return 0;
list_for_each_entry(dock_station, &dock_stations, sibiling) {
if (dock_station->handle == handle) {
- dock_notify(handle, event, dock_station);
+ struct dock_data *dock_data;
+
+ dock_data = kmalloc(sizeof(*dock_data), GFP_KERNEL);
+ if (!dock_data)
+ return 0;
+ dock_data->handle = handle;
+ dock_data->event = event;
+ dock_data->ds = dock_station;
+ acpi_os_hotplug_execute(acpi_dock_deferred_cb,
+ dock_data);
return 0 ;
}
}
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 235a138..750e0df 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -682,6 +682,22 @@ static void acpi_os_execute_deferred(struct work_struct *work)
return;
}
+static void acpi_os_execute_hp_deferred(struct work_struct *work)
+{
+ struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
+ if (!dpc) {
+ printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
+ return;
+ }
+
+ acpi_os_wait_events_complete(NULL);
+
+ dpc->function(dpc->context);
+ kfree(dpc);
+
+ return;
+}
+
/*******************************************************************************
*
* FUNCTION: acpi_os_execute
@@ -697,12 +713,13 @@ static void acpi_os_execute_deferred(struct work_struct *work)
*
******************************************************************************/
-acpi_status acpi_os_execute(acpi_execute_type type,
- acpi_osd_exec_callback function, void *context)
+static acpi_status __acpi_os_execute(acpi_execute_type type,
+ acpi_osd_exec_callback function, void *context, int hp)
{
acpi_status status = AE_OK;
struct acpi_os_dpc *dpc;
struct workqueue_struct *queue;
+ int ret;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Scheduling function [%p(%p)] for deferred execution.\n",
function, context));
@@ -726,9 +743,17 @@ acpi_status acpi_os_execute(acpi_execute_type type,
dpc->function = function;
dpc->context = context;
- INIT_WORK(&dpc->work, acpi_os_execute_deferred);
- queue = (type == OSL_NOTIFY_HANDLER) ? kacpi_notify_wq : kacpid_wq;
- if (!queue_work(queue, &dpc->work)) {
+ if (!hp) {
+ INIT_WORK(&dpc->work, acpi_os_execute_deferred);
+ queue = (type == OSL_NOTIFY_HANDLER) ?
+ kacpi_notify_wq : kacpid_wq;
+ ret = queue_work(queue, &dpc->work);
+ } else {
+ INIT_WORK(&dpc->work, acpi_os_execute_hp_deferred);
+ ret = schedule_work(&dpc->work);
+ }
+
+ if (!ret) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Call to queue_work() failed.\n"));
status = AE_ERROR;
@@ -737,8 +762,19 @@ acpi_status acpi_os_execute(acpi_execute_type type,
return_ACPI_STATUS(status);
}
+acpi_status acpi_os_execute(acpi_execute_type type,
+ acpi_osd_exec_callback function, void *context)
+{
+ return __acpi_os_execute(type, function, context, 0);
+}
EXPORT_SYMBOL(acpi_os_execute);
+acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function,
+ void *context)
+{
+ return __acpi_os_execute(0, function, context, 1);
+}
+
void acpi_os_wait_events_complete(void *context)
{
flush_workqueue(kacpid_wq);
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 3f93a6b..b91440a 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -193,6 +193,9 @@ acpi_status
acpi_os_execute(acpi_execute_type type,
acpi_osd_exec_callback function, void *context);
+acpi_status
+acpi_os_hotplug_execute(acpi_osd_exec_callback function, void *context);
+
void acpi_os_wait_events_complete(void *context);
void acpi_os_sleep(acpi_integer milliseconds);
--
1.5.5.1
From: Shaohua Li <[email protected]>
The battery driver already registers notification handler.
To avoid registering notification handler again,
introduce a notifier chain in global system notifier handler
and use it in dock driver.
Signed-off-by: Shaohua Li <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/bus.c | 15 +++++++++++++++
drivers/acpi/dock.c | 46 ++++++++++++++++++++++++----------------------
include/acpi/acpi_bus.h | 3 +++
3 files changed, 42 insertions(+), 22 deletions(-)
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index ccae305..0dc4494 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -496,6 +496,19 @@ static int acpi_bus_check_scope(struct acpi_device *device)
return 0;
}
+static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list);
+int register_acpi_bus_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&acpi_bus_notify_list, nb);
+}
+EXPORT_SYMBOL_GPL(register_acpi_bus_notifier);
+
+void unregister_acpi_bus_notifier(struct notifier_block *nb)
+{
+ blocking_notifier_chain_unregister(&acpi_bus_notify_list, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_acpi_bus_notifier);
+
/**
* acpi_bus_notify
* ---------------
@@ -506,6 +519,8 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
int result = 0;
struct acpi_device *device = NULL;
+ blocking_notifier_call_chain(&acpi_bus_notify_list,
+ type, (void *)handle);
if (acpi_bus_get_device(handle, &device))
return;
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 799a0fd..2563bc6 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -748,6 +748,28 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
}
}
+static int acpi_dock_notifier_call(struct notifier_block *this,
+ unsigned long event, void *data)
+{
+ struct dock_station *dock_station;
+ acpi_handle handle = (acpi_handle)data;
+
+ if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
+ && event != ACPI_NOTIFY_EJECT_REQUEST)
+ return 0;
+ list_for_each_entry(dock_station, &dock_stations, sibiling) {
+ if (dock_station->handle == handle) {
+ dock_notify(handle, event, dock_station);
+ return 0 ;
+ }
+ }
+ return 0;
+}
+
+static struct notifier_block dock_acpi_notifier = {
+ .notifier_call = acpi_dock_notifier_call,
+};
+
/**
* find_dock_devices - find devices on the dock station
* @handle: the handle of the device we are examining
@@ -861,7 +883,6 @@ static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
static int dock_add(acpi_handle handle)
{
int ret;
- acpi_status status;
struct dock_dependent_device *dd;
struct dock_station *dock_station;
struct platform_device *dock_device;
@@ -956,23 +977,10 @@ static int dock_add(acpi_handle handle)
}
add_dock_dependent_device(dock_station, dd);
- /* register for dock events */
- status = acpi_install_notify_handler(dock_station->handle,
- ACPI_SYSTEM_NOTIFY,
- dock_notify, dock_station);
-
- if (ACPI_FAILURE(status)) {
- printk(KERN_ERR PREFIX "Error installing notify handler\n");
- ret = -ENODEV;
- goto dock_add_err;
- }
-
dock_station_count++;
list_add(&dock_station->sibiling, &dock_stations);
return 0;
-dock_add_err:
- kfree(dd);
dock_add_err_unregister:
device_remove_file(&dock_device->dev, &dev_attr_docked);
device_remove_file(&dock_device->dev, &dev_attr_undock);
@@ -990,7 +998,6 @@ dock_add_err_unregister:
static int dock_remove(struct dock_station *dock_station)
{
struct dock_dependent_device *dd, *tmp;
- acpi_status status;
struct platform_device *dock_device = dock_station->dock_device;
if (!dock_station_count)
@@ -1001,13 +1008,6 @@ static int dock_remove(struct dock_station *dock_station)
list)
kfree(dd);
- /* remove dock notify handler */
- status = acpi_remove_notify_handler(dock_station->handle,
- ACPI_SYSTEM_NOTIFY,
- dock_notify);
- if (ACPI_FAILURE(status))
- printk(KERN_ERR "Error removing notify handler\n");
-
/* cleanup sysfs */
device_remove_file(&dock_device->dev, &dev_attr_docked);
device_remove_file(&dock_device->dev, &dev_attr_undock);
@@ -1069,6 +1069,7 @@ static int __init dock_init(void)
return 0;
}
+ register_acpi_bus_notifier(&dock_acpi_notifier);
printk(KERN_INFO PREFIX "%s: %d docks/bays found\n",
ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
return 0;
@@ -1078,6 +1079,7 @@ static void __exit dock_exit(void)
{
struct dock_station *dock_station;
+ unregister_acpi_bus_notifier(&dock_acpi_notifier);
list_for_each_entry(dock_station, &dock_stations, sibiling)
dock_remove(dock_station);
}
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index a5ac0bc..f74f882 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -327,6 +327,9 @@ int acpi_bus_get_private_data(acpi_handle, void **);
extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);
extern int register_acpi_notifier(struct notifier_block *);
extern int unregister_acpi_notifier(struct notifier_block *);
+
+extern int register_acpi_bus_notifier(struct notifier_block *nb);
+extern void unregister_acpi_bus_notifier(struct notifier_block *nb);
/*
* External Functions
*/
--
1.5.5.1
From: Shaohua Li <[email protected]>
Make the dock driver support bay and battery hotplug.
They are all regarded as dock, so handling can be unified.
Signed-off-by: Shaohua Li <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/dock.c | 223 ++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 175 insertions(+), 48 deletions(-)
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 7bdf93b..799a0fd 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -48,7 +48,6 @@ MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to "
" before undocking");
static struct atomic_notifier_head dock_notifier_list;
-static struct platform_device *dock_device;
static char dock_device_name[] = "dock";
static const struct acpi_device_id dock_device_ids[] = {
@@ -65,7 +64,12 @@ struct dock_station {
struct mutex hp_lock;
struct list_head dependent_devices;
struct list_head hotplug_devices;
+
+ struct list_head sibiling;
+ struct platform_device *dock_device;
};
+static LIST_HEAD(dock_stations);
+static int dock_station_count;
struct dock_dependent_device {
struct list_head list;
@@ -77,11 +81,12 @@ struct dock_dependent_device {
#define DOCK_DOCKING 0x00000001
#define DOCK_UNDOCKING 0x00000002
+#define DOCK_IS_DOCK 0x00000010
+#define DOCK_IS_ATA 0x00000020
+#define DOCK_IS_BAT 0x00000040
#define DOCK_EVENT 3
#define UNDOCK_EVENT 2
-static struct dock_station *dock_station;
-
/*****************************************************************************
* Dock Dependent device functions *
*****************************************************************************/
@@ -199,6 +204,60 @@ static int is_dock(acpi_handle handle)
return 1;
}
+static int is_ejectable(acpi_handle handle)
+{
+ acpi_status status;
+ acpi_handle tmp;
+
+ status = acpi_get_handle(handle, "_EJ0", &tmp);
+ if (ACPI_FAILURE(status))
+ return 0;
+ return 1;
+}
+
+static int is_ata(acpi_handle handle)
+{
+ acpi_handle tmp;
+
+ if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||
+ (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||
+ (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||
+ (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))
+ return 1;
+
+ return 0;
+}
+
+static int is_battery(acpi_handle handle)
+{
+ struct acpi_device_info *info;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ int ret = 1;
+
+ if (!ACPI_SUCCESS(acpi_get_object_info(handle, &buffer)))
+ return 0;
+ info = buffer.pointer;
+ if (!(info->valid & ACPI_VALID_HID))
+ ret = 0;
+ else
+ ret = !strcmp("PNP0C0A", info->hardware_id.value);
+
+ kfree(buffer.pointer);
+ return ret;
+}
+
+static int is_ejectable_bay(acpi_handle handle)
+{
+ acpi_handle phandle;
+ if (!is_ejectable(handle))
+ return 0;
+ if (is_battery(handle) || is_ata(handle))
+ return 1;
+ if (!acpi_get_parent(handle, &phandle) && is_ata(phandle))
+ return 1;
+ return 0;
+}
+
/**
* is_dock_device - see if a device is on a dock station
* @handle: acpi handle of the device
@@ -209,11 +268,17 @@ static int is_dock(acpi_handle handle)
*/
int is_dock_device(acpi_handle handle)
{
- if (!dock_station)
+ struct dock_station *dock_station;
+
+ if (!dock_station_count)
return 0;
- if (is_dock(handle) || find_dock_dependent_device(dock_station, handle))
+ if (is_dock(handle))
return 1;
+ list_for_each_entry(dock_station, &dock_stations, sibiling) {
+ if (find_dock_dependent_device(dock_station, handle))
+ return 1;
+ }
return 0;
}
@@ -341,7 +406,7 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
static void dock_event(struct dock_station *ds, u32 event, int num)
{
- struct device *dev = &dock_device->dev;
+ struct device *dev = &ds->dock_device->dev;
char event_string[13];
char *envp[] = { event_string, NULL };
@@ -414,7 +479,7 @@ static void handle_dock(struct dock_station *ds, int dock)
arg.type = ACPI_TYPE_INTEGER;
arg.integer.value = dock;
status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer);
- if (ACPI_FAILURE(status))
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
printk(KERN_ERR PREFIX "%s - failed to execute _DCK\n",
(char *)name_buffer.pointer);
kfree(buffer.pointer);
@@ -498,7 +563,7 @@ static int dock_in_progress(struct dock_station *ds)
*/
int register_dock_notifier(struct notifier_block *nb)
{
- if (!dock_station)
+ if (!dock_station_count)
return -ENODEV;
return atomic_notifier_chain_register(&dock_notifier_list, nb);
@@ -512,7 +577,7 @@ EXPORT_SYMBOL_GPL(register_dock_notifier);
*/
void unregister_dock_notifier(struct notifier_block *nb)
{
- if (!dock_station)
+ if (!dock_station_count)
return;
atomic_notifier_chain_unregister(&dock_notifier_list, nb);
@@ -535,20 +600,23 @@ register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler,
void *context)
{
struct dock_dependent_device *dd;
+ struct dock_station *dock_station;
- if (!dock_station)
+ if (!dock_station_count)
return -ENODEV;
/*
* make sure this handle is for a device dependent on the dock,
* this would include the dock station itself
*/
- dd = find_dock_dependent_device(dock_station, handle);
- if (dd) {
- dd->handler = handler;
- dd->context = context;
- dock_add_hotplug_device(dock_station, dd);
- return 0;
+ list_for_each_entry(dock_station, &dock_stations, sibiling) {
+ dd = find_dock_dependent_device(dock_station, handle);
+ if (dd) {
+ dd->handler = handler;
+ dd->context = context;
+ dock_add_hotplug_device(dock_station, dd);
+ return 0;
+ }
}
return -EINVAL;
@@ -563,13 +631,16 @@ EXPORT_SYMBOL_GPL(register_hotplug_dock_device);
void unregister_hotplug_dock_device(acpi_handle handle)
{
struct dock_dependent_device *dd;
+ struct dock_station *dock_station;
- if (!dock_station)
+ if (!dock_station_count)
return;
- dd = find_dock_dependent_device(dock_station, handle);
- if (dd)
- dock_del_hotplug_device(dock_station, dd);
+ list_for_each_entry(dock_station, &dock_stations, sibiling) {
+ dd = find_dock_dependent_device(dock_station, handle);
+ if (dd)
+ dock_del_hotplug_device(dock_station, dd);
+ }
}
EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
@@ -620,9 +691,28 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
{
struct dock_station *ds = data;
struct acpi_device *tmp;
+ int surprise_removal = 0;
+ /*
+ * According to acpi spec 3.0a, if a DEVICE_CHECK notification
+ * is sent and _DCK is present, it is assumed to mean an undock
+ * request.
+ */
+ if ((ds->flags & DOCK_IS_DOCK) && event == ACPI_NOTIFY_DEVICE_CHECK)
+ event = ACPI_NOTIFY_EJECT_REQUEST;
+
+ /*
+ * dock station: BUS_CHECK - docked or surprise removal
+ * DEVICE_CHECK - undocked
+ * other device: BUS_CHECK/DEVICE_CHECK - added or surprise removal
+ *
+ * To simplify event handling, dock dependent device handler always
+ * get ACPI_NOTIFY_BUS_CHECK/ACPI_NOTIFY_DEVICE_CHECK for add and
+ * ACPI_NOTIFY_EJECT_REQUEST for removal
+ */
switch (event) {
case ACPI_NOTIFY_BUS_CHECK:
+ case ACPI_NOTIFY_DEVICE_CHECK:
if (!dock_in_progress(ds) && acpi_bus_get_device(ds->handle,
&tmp)) {
begin_dock(ds);
@@ -638,20 +728,17 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
complete_dock(ds);
dock_event(ds, event, DOCK_EVENT);
dock_lock(ds, 1);
+ break;
}
- break;
- case ACPI_NOTIFY_DEVICE_CHECK:
- /*
- * According to acpi spec 3.0a, if a DEVICE_CHECK notification
- * is sent and _DCK is present, it is assumed to mean an
- * undock request. This notify routine will only be called
- * for objects defining _DCK, so we will fall through to eject
- * request here. However, we will pass an eject request through
- * to the driver who wish to hotplug.
- */
+ if (dock_present(ds) || dock_in_progress(ds))
+ break;
+ /* This is a surprise removal */
+ surprise_removal = 1;
+ event = ACPI_NOTIFY_EJECT_REQUEST;
+ /* Fall back */
case ACPI_NOTIFY_EJECT_REQUEST:
begin_undock(ds);
- if (immediate_undock)
+ if (immediate_undock || surprise_removal)
handle_eject_request(ds, event);
else
dock_event(ds, event, UNDOCK_EVENT);
@@ -707,6 +794,8 @@ fdd_out:
static ssize_t show_docked(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct dock_station *dock_station = *((struct dock_station **)
+ dev->platform_data);
return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station));
}
@@ -718,6 +807,8 @@ static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
static ssize_t show_flags(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct dock_station *dock_station = *((struct dock_station **)
+ dev->platform_data);
return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
}
@@ -730,6 +821,8 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
+ struct dock_station *dock_station = *((struct dock_station **)
+ dev->platform_data);
if (!count)
return -EINVAL;
@@ -747,6 +840,8 @@ static ssize_t show_dock_uid(struct device *dev,
struct device_attribute *attr, char *buf)
{
unsigned long lbuf;
+ struct dock_station *dock_station = *((struct dock_station **)
+ dev->platform_data);
acpi_status status = acpi_evaluate_integer(dock_station->handle,
"_UID", NULL, &lbuf);
if (ACPI_FAILURE(status))
@@ -768,6 +863,8 @@ static int dock_add(acpi_handle handle)
int ret;
acpi_status status;
struct dock_dependent_device *dd;
+ struct dock_station *dock_station;
+ struct platform_device *dock_device;
/* allocate & initialize the dock_station private data */
dock_station = kzalloc(sizeof(*dock_station), GFP_KERNEL);
@@ -777,22 +874,34 @@ static int dock_add(acpi_handle handle)
dock_station->last_dock_time = jiffies - HZ;
INIT_LIST_HEAD(&dock_station->dependent_devices);
INIT_LIST_HEAD(&dock_station->hotplug_devices);
+ INIT_LIST_HEAD(&dock_station->sibiling);
spin_lock_init(&dock_station->dd_lock);
mutex_init(&dock_station->hp_lock);
ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
/* initialize platform device stuff */
- dock_device =
- platform_device_register_simple(dock_device_name, 0, NULL, 0);
+ dock_station->dock_device =
+ platform_device_register_simple(dock_device_name,
+ dock_station_count, NULL, 0);
+ dock_device = dock_station->dock_device;
if (IS_ERR(dock_device)) {
kfree(dock_station);
dock_station = NULL;
return PTR_ERR(dock_device);
}
+ platform_device_add_data(dock_device, &dock_station,
+ sizeof(struct dock_station *));
/* we want the dock device to send uevents */
dock_device->dev.uevent_suppress = 0;
+ if (is_dock(handle))
+ dock_station->flags |= DOCK_IS_DOCK;
+ if (is_ata(handle))
+ dock_station->flags |= DOCK_IS_ATA;
+ if (is_battery(handle))
+ dock_station->flags |= DOCK_IS_BAT;
+
ret = device_create_file(&dock_device->dev, &dev_attr_docked);
if (ret) {
printk("Error %d adding sysfs file\n", ret);
@@ -858,8 +967,8 @@ static int dock_add(acpi_handle handle)
goto dock_add_err;
}
- printk(KERN_INFO PREFIX "%s\n", ACPI_DOCK_DRIVER_DESCRIPTION);
-
+ dock_station_count++;
+ list_add(&dock_station->sibiling, &dock_stations);
return 0;
dock_add_err:
@@ -878,12 +987,13 @@ dock_add_err_unregister:
/**
* dock_remove - free up resources related to the dock station
*/
-static int dock_remove(void)
+static int dock_remove(struct dock_station *dock_station)
{
struct dock_dependent_device *dd, *tmp;
acpi_status status;
+ struct platform_device *dock_device = dock_station->dock_device;
- if (!dock_station)
+ if (!dock_station_count)
return 0;
/* remove dependent devices */
@@ -923,41 +1033,58 @@ static int dock_remove(void)
static acpi_status
find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
{
- int *count = context;
acpi_status status = AE_OK;
if (is_dock(handle)) {
if (dock_add(handle) >= 0) {
- (*count)++;
status = AE_CTRL_TERMINATE;
}
}
return status;
}
-static int __init dock_init(void)
+static acpi_status
+find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
{
- int num = 0;
-
- dock_station = NULL;
+ /* If bay is in a dock, it's already handled */
+ if (is_ejectable_bay(handle) && !is_dock_device(handle))
+ dock_add(handle);
+ return AE_OK;
+}
+static int __init dock_init(void)
+{
if (acpi_disabled)
return 0;
/* look for a dock station */
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, find_dock, &num, NULL);
+ ACPI_UINT32_MAX, find_dock, NULL, NULL);
- if (!num)
- printk(KERN_INFO "No dock devices found.\n");
+ /* look for bay */
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, find_bay, NULL, NULL);
+ if (!dock_station_count) {
+ printk(KERN_INFO PREFIX "No dock devices found.\n");
+ return 0;
+ }
+ printk(KERN_INFO PREFIX "%s: %d docks/bays found\n",
+ ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
return 0;
}
static void __exit dock_exit(void)
{
- dock_remove();
+ struct dock_station *dock_station;
+
+ list_for_each_entry(dock_station, &dock_stations, sibiling)
+ dock_remove(dock_station);
}
-postcore_initcall(dock_init);
+/*
+ * Must be called before drivers of devices in dock, otherwise we can't know
+ * which devices are in a dock
+ */
+subsys_initcall(dock_init);
module_exit(dock_exit);
--
1.5.5.1
From: Thomas Renninger <[email protected]>
Make use of FW_BUG interface to give vendors and users the ability to
automatically check for powernow-k8 related BIOS bugs by:
dmesg |grep "Firmware Bug"
Signed-off-by: Thomas Renninger <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 42 ++++++++++++++++------------
1 files changed, 24 insertions(+), 18 deletions(-)
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
index 84bb395..4e0c6ab 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
@@ -45,7 +45,6 @@
#endif
#define PFX "powernow-k8: "
-#define BFX PFX "BIOS error: "
#define VERSION "version 2.20.00"
#include "powernow-k8.h"
@@ -536,35 +535,40 @@ static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst, u8
for (j = 0; j < data->numps; j++) {
if (pst[j].vid > LEAST_VID) {
- printk(KERN_ERR PFX "vid %d invalid : 0x%x\n", j, pst[j].vid);
+ printk(KERN_ERR FW_BUG PFX "vid %d invalid : 0x%x\n",
+ j, pst[j].vid);
return -EINVAL;
}
if (pst[j].vid < data->rvo) { /* vid + rvo >= 0 */
- printk(KERN_ERR BFX "0 vid exceeded with pstate %d\n", j);
+ printk(KERN_ERR FW_BUG PFX "0 vid exceeded with pstate"
+ " %d\n", j);
return -ENODEV;
}
if (pst[j].vid < maxvid + data->rvo) { /* vid + rvo >= maxvid */
- printk(KERN_ERR BFX "maxvid exceeded with pstate %d\n", j);
+ printk(KERN_ERR FW_BUG PFX "maxvid exceeded with pstate"
+ " %d\n", j);
return -ENODEV;
}
if (pst[j].fid > MAX_FID) {
- printk(KERN_ERR BFX "maxfid exceeded with pstate %d\n", j);
+ printk(KERN_ERR FW_BUG PFX "maxfid exceeded with pstate"
+ " %d\n", j);
return -ENODEV;
}
if (j && (pst[j].fid < HI_FID_TABLE_BOTTOM)) {
/* Only first fid is allowed to be in "low" range */
- printk(KERN_ERR BFX "two low fids - %d : 0x%x\n", j, pst[j].fid);
+ printk(KERN_ERR FW_BUG PFX "two low fids - %d : "
+ "0x%x\n", j, pst[j].fid);
return -EINVAL;
}
if (pst[j].fid < lastfid)
lastfid = pst[j].fid;
}
if (lastfid & 1) {
- printk(KERN_ERR BFX "lastfid invalid\n");
+ printk(KERN_ERR FW_BUG PFX "lastfid invalid\n");
return -EINVAL;
}
if (lastfid > LO_FID_TABLE_TOP)
- printk(KERN_INFO BFX "first fid not from lo freq table\n");
+ printk(KERN_INFO FW_BUG PFX "first fid not from lo freq table\n");
return 0;
}
@@ -672,13 +676,13 @@ static int find_psb_table(struct powernow_k8_data *data)
dprintk("table vers: 0x%x\n", psb->tableversion);
if (psb->tableversion != PSB_VERSION_1_4) {
- printk(KERN_ERR BFX "PSB table is not v1.4\n");
+ printk(KERN_ERR FW_BUG PFX "PSB table is not v1.4\n");
return -ENODEV;
}
dprintk("flags: 0x%x\n", psb->flags1);
if (psb->flags1) {
- printk(KERN_ERR BFX "unknown flags\n");
+ printk(KERN_ERR FW_BUG PFX "unknown flags\n");
return -ENODEV;
}
@@ -705,7 +709,7 @@ static int find_psb_table(struct powernow_k8_data *data)
}
}
if (cpst != 1) {
- printk(KERN_ERR BFX "numpst must be 1\n");
+ printk(KERN_ERR FW_BUG PFX "numpst must be 1\n");
return -ENODEV;
}
@@ -1130,17 +1134,19 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
"ACPI Processor module before starting this "
"driver.\n");
#else
- printk(KERN_ERR PFX "Your BIOS does not provide ACPI "
- "_PSS objects in a way that Linux understands. "
- "Please report this to the Linux ACPI maintainers"
- " and complain to your BIOS vendor.\n");
+ printk(KERN_ERR FW_BUG PFX "Your BIOS does not provide"
+ " ACPI _PSS objects in a way that Linux "
+ "understands. Please report this to the Linux "
+ "ACPI maintainers and complain to your BIOS "
+ "vendor.\n");
#endif
kfree(data);
return -ENODEV;
}
if (pol->cpu != 0) {
- printk(KERN_ERR PFX "No ACPI _PSS objects for CPU other than "
- "CPU0. Complain to your BIOS vendor.\n");
+ printk(KERN_ERR FW_BUG PFX "No ACPI _PSS objects for "
+ "CPU other than CPU0. Complain to your BIOS "
+ "vendor.\n");
kfree(data);
return -ENODEV;
}
@@ -1193,7 +1199,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
/* min/max the cpu is capable of */
if (cpufreq_frequency_table_cpuinfo(pol, data->powernow_table)) {
- printk(KERN_ERR PFX "invalid powernow_table\n");
+ printk(KERN_ERR FW_BUG PFX "invalid powernow_table\n");
powernow_k8_cpu_exit_acpi(data);
kfree(data->powernow_table);
kfree(data);
--
1.5.5.1
From: Zhao Yakui <[email protected]>
Add the DMI check to disable power check in the course of device power
transistion.
http://bugzilla.kernel.org/show_bug.cgi?id=11000
Signed-off-by: Zhao Yakui <[email protected]>
Signed-off-by: Li Shaohua <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
---
drivers/acpi/bus.c | 23 ++++++++++++++++++++++-
1 files changed, 22 insertions(+), 1 deletions(-)
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 91bdeb3..945cd2f 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -48,6 +48,23 @@ EXPORT_SYMBOL(acpi_root_dir);
#define STRUCT_TO_INT(s) (*((int*)&s))
+static int set_power_nocheck(const struct dmi_system_id *id)
+{
+ printk(KERN_NOTICE PREFIX "%s detected - "
+ "disable power check in power transistion\n", id->ident);
+ acpi_power_nocheck = 1;
+ return 0;
+}
+static struct dmi_system_id __cpuinitdata power_nocheck_dmi_table[] = {
+ {
+ set_power_nocheck, "HP Pavilion 05", {
+ DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+ DMI_MATCH(DMI_SYS_VENDOR, "HP Pavilion 05"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "2001211RE101GLEND") }, NULL},
+ {},
+};
+
+
/* --------------------------------------------------------------------------
Device Management
-------------------------------------------------------------------------- */
@@ -830,7 +847,11 @@ static int __init acpi_init(void)
}
} else
disable_acpi();
-
+ /*
+ * If the laptop falls into the DMI check table, the power state check
+ * will be disabled in the course of device power transistion.
+ */
+ dmi_check_system(power_nocheck_dmi_table);
return result;
}
--
1.5.5.1
From: Bob Moore <[email protected]>
Removed unused macros. Ensure that multiple parameters always have a space
after a comma. Cleanup some comments.
Signed-off-by: Bob Moore <[email protected]>
Signed-off-by: Lin Ming <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
include/acpi/acmacros.h | 248 ++++++++++++++++++++++-------------------------
1 files changed, 115 insertions(+), 133 deletions(-)
diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h
index 57ab9e9..2106f91 100644
--- a/include/acpi/acmacros.h
+++ b/include/acpi/acmacros.h
@@ -62,7 +62,7 @@
#define ACPI_ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
/*
- * Extract data using a pointer. Any more than a byte and we
+ * Extract data using a pointer. Any more than a byte and we
* get into potential aligment issues -- see the STORE macros below.
* Use with care.
*/
@@ -80,21 +80,21 @@
*/
#define ACPI_CAST_PTR(t, p) ((t *) (acpi_uintptr_t) (p))
#define ACPI_CAST_INDIRECT_PTR(t, p) ((t **) (acpi_uintptr_t) (p))
-#define ACPI_ADD_PTR(t, a, b) ACPI_CAST_PTR (t, (ACPI_CAST_PTR (u8,(a)) + (acpi_size)(b)))
-#define ACPI_PTR_DIFF(a, b) (acpi_size) (ACPI_CAST_PTR (u8,(a)) - ACPI_CAST_PTR (u8,(b)))
+#define ACPI_ADD_PTR(t, a, b) ACPI_CAST_PTR (t, (ACPI_CAST_PTR (u8, (a)) + (acpi_size)(b)))
+#define ACPI_PTR_DIFF(a, b) (acpi_size) (ACPI_CAST_PTR (u8, (a)) - ACPI_CAST_PTR (u8, (b)))
/* Pointer/Integer type conversions */
#define ACPI_TO_POINTER(i) ACPI_ADD_PTR (void, (void *) NULL, (acpi_size) i)
-#define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p,(void *) NULL)
-#define ACPI_OFFSET(d,f) (acpi_size) ACPI_PTR_DIFF (&(((d *)0)->f),(void *) NULL)
+#define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) NULL)
+#define ACPI_OFFSET(d, f) (acpi_size) ACPI_PTR_DIFF (&(((d *)0)->f), (void *) NULL)
#define ACPI_PHYSADDR_TO_PTR(i) ACPI_TO_POINTER(i)
#define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i)
#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
-#define ACPI_COMPARE_NAME(a,b) (*ACPI_CAST_PTR (u32,(a)) == *ACPI_CAST_PTR (u32,(b)))
+#define ACPI_COMPARE_NAME(a, b) (*ACPI_CAST_PTR (u32, (a)) == *ACPI_CAST_PTR (u32, (b)))
#else
-#define ACPI_COMPARE_NAME(a,b) (!ACPI_STRNCMP (ACPI_CAST_PTR (char,(a)), ACPI_CAST_PTR (char,(b)), ACPI_NAME_SIZE))
+#define ACPI_COMPARE_NAME(a, b) (!ACPI_STRNCMP (ACPI_CAST_PTR (char, (a)), ACPI_CAST_PTR (char, (b)), ACPI_NAME_SIZE))
#endif
/*
@@ -114,7 +114,7 @@ struct acpi_integer_overlay {
/* Split 64-bit integer into two 32-bit values. Use with %8.8_x%8.8_x */
-#define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i),ACPI_LODWORD(i)
+#define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i), ACPI_LODWORD(i)
#if ACPI_MACHINE_WIDTH == 64
#define ACPI_FORMAT_NATIVE_UINT(i) ACPI_FORMAT_UINT64(i)
@@ -132,37 +132,33 @@ struct acpi_integer_overlay {
* Macros for big-endian machines
*/
-/* This macro sets a buffer index, starting from the end of the buffer */
-
-#define ACPI_BUFFER_INDEX(buf_len,buf_offset,byte_gran) ((buf_len) - (((buf_offset)+1) * (byte_gran)))
-
/* These macros reverse the bytes during the move, converting little-endian to big endian */
/* Big Endian <== Little Endian */
/* Hi...Lo Lo...Hi */
/* 16-bit source, 16/32/64 destination */
-#define ACPI_MOVE_16_TO_16(d,s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[1];\
+#define ACPI_MOVE_16_TO_16(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[1];\
(( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];}
-#define ACPI_MOVE_16_TO_32(d,s) {(*(u32 *)(void *)(d))=0;\
+#define ACPI_MOVE_16_TO_32(d, s) {(*(u32 *)(void *)(d))=0;\
((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
-#define ACPI_MOVE_16_TO_64(d,s) {(*(u64 *)(void *)(d))=0;\
+#define ACPI_MOVE_16_TO_64(d, s) {(*(u64 *)(void *)(d))=0;\
((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\
((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];}
/* 32-bit source, 16/32/64 destination */
-#define ACPI_MOVE_32_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
+#define ACPI_MOVE_32_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */
-#define ACPI_MOVE_32_TO_32(d,s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[3];\
+#define ACPI_MOVE_32_TO_32(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[3];\
(( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\
(( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
(( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
-#define ACPI_MOVE_32_TO_64(d,s) {(*(u64 *)(void *)(d))=0;\
+#define ACPI_MOVE_32_TO_64(d, s) {(*(u64 *)(void *)(d))=0;\
((u8 *)(void *)(d))[4] = ((u8 *)(void *)(s))[3];\
((u8 *)(void *)(d))[5] = ((u8 *)(void *)(s))[2];\
((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\
@@ -170,11 +166,11 @@ struct acpi_integer_overlay {
/* 64-bit source, 16/32/64 destination */
-#define ACPI_MOVE_64_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
+#define ACPI_MOVE_64_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */
-#define ACPI_MOVE_64_TO_32(d,s) ACPI_MOVE_32_TO_32(d,s) /* Truncate to 32 */
+#define ACPI_MOVE_64_TO_32(d, s) ACPI_MOVE_32_TO_32(d, s) /* Truncate to 32 */
-#define ACPI_MOVE_64_TO_64(d,s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[7];\
+#define ACPI_MOVE_64_TO_64(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[7];\
(( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[6];\
(( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[5];\
(( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[4];\
@@ -187,63 +183,59 @@ struct acpi_integer_overlay {
* Macros for little-endian machines
*/
-/* This macro sets a buffer index, starting from the beginning of the buffer */
-
-#define ACPI_BUFFER_INDEX(buf_len,buf_offset,byte_gran) (buf_offset)
-
#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
/* The hardware supports unaligned transfers, just do the little-endian move */
/* 16-bit source, 16/32/64 destination */
-#define ACPI_MOVE_16_TO_16(d,s) *(u16 *)(void *)(d) = *(u16 *)(void *)(s)
-#define ACPI_MOVE_16_TO_32(d,s) *(u32 *)(void *)(d) = *(u16 *)(void *)(s)
-#define ACPI_MOVE_16_TO_64(d,s) *(u64 *)(void *)(d) = *(u16 *)(void *)(s)
+#define ACPI_MOVE_16_TO_16(d, s) *(u16 *)(void *)(d) = *(u16 *)(void *)(s)
+#define ACPI_MOVE_16_TO_32(d, s) *(u32 *)(void *)(d) = *(u16 *)(void *)(s)
+#define ACPI_MOVE_16_TO_64(d, s) *(u64 *)(void *)(d) = *(u16 *)(void *)(s)
/* 32-bit source, 16/32/64 destination */
-#define ACPI_MOVE_32_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
-#define ACPI_MOVE_32_TO_32(d,s) *(u32 *)(void *)(d) = *(u32 *)(void *)(s)
-#define ACPI_MOVE_32_TO_64(d,s) *(u64 *)(void *)(d) = *(u32 *)(void *)(s)
+#define ACPI_MOVE_32_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */
+#define ACPI_MOVE_32_TO_32(d, s) *(u32 *)(void *)(d) = *(u32 *)(void *)(s)
+#define ACPI_MOVE_32_TO_64(d, s) *(u64 *)(void *)(d) = *(u32 *)(void *)(s)
/* 64-bit source, 16/32/64 destination */
-#define ACPI_MOVE_64_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
-#define ACPI_MOVE_64_TO_32(d,s) ACPI_MOVE_32_TO_32(d,s) /* Truncate to 32 */
-#define ACPI_MOVE_64_TO_64(d,s) *(u64 *)(void *)(d) = *(u64 *)(void *)(s)
+#define ACPI_MOVE_64_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */
+#define ACPI_MOVE_64_TO_32(d, s) ACPI_MOVE_32_TO_32(d, s) /* Truncate to 32 */
+#define ACPI_MOVE_64_TO_64(d, s) *(u64 *)(void *)(d) = *(u64 *)(void *)(s)
#else
/*
- * The hardware does not support unaligned transfers. We must move the
- * data one byte at a time. These macros work whether the source or
+ * The hardware does not support unaligned transfers. We must move the
+ * data one byte at a time. These macros work whether the source or
* the destination (or both) is/are unaligned. (Little-endian move)
*/
/* 16-bit source, 16/32/64 destination */
-#define ACPI_MOVE_16_TO_16(d,s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[0];\
+#define ACPI_MOVE_16_TO_16(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[0];\
(( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[1];}
-#define ACPI_MOVE_16_TO_32(d,s) {(*(u32 *)(void *)(d)) = 0; ACPI_MOVE_16_TO_16(d,s);}
-#define ACPI_MOVE_16_TO_64(d,s) {(*(u64 *)(void *)(d)) = 0; ACPI_MOVE_16_TO_16(d,s);}
+#define ACPI_MOVE_16_TO_32(d, s) {(*(u32 *)(void *)(d)) = 0; ACPI_MOVE_16_TO_16(d, s);}
+#define ACPI_MOVE_16_TO_64(d, s) {(*(u64 *)(void *)(d)) = 0; ACPI_MOVE_16_TO_16(d, s);}
/* 32-bit source, 16/32/64 destination */
-#define ACPI_MOVE_32_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
+#define ACPI_MOVE_32_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */
-#define ACPI_MOVE_32_TO_32(d,s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[0];\
+#define ACPI_MOVE_32_TO_32(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[0];\
(( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[1];\
(( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[2];\
(( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[3];}
-#define ACPI_MOVE_32_TO_64(d,s) {(*(u64 *)(void *)(d)) = 0; ACPI_MOVE_32_TO_32(d,s);}
+#define ACPI_MOVE_32_TO_64(d, s) {(*(u64 *)(void *)(d)) = 0; ACPI_MOVE_32_TO_32(d, s);}
/* 64-bit source, 16/32/64 destination */
-#define ACPI_MOVE_64_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
-#define ACPI_MOVE_64_TO_32(d,s) ACPI_MOVE_32_TO_32(d,s) /* Truncate to 32 */
-#define ACPI_MOVE_64_TO_64(d,s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[0];\
+#define ACPI_MOVE_64_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */
+#define ACPI_MOVE_64_TO_32(d, s) ACPI_MOVE_32_TO_32(d, s) /* Truncate to 32 */
+#define ACPI_MOVE_64_TO_64(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[0];\
(( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[1];\
(( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[2];\
(( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[3];\
@@ -257,10 +249,10 @@ struct acpi_integer_overlay {
/* Macros based on machine integer width */
#if ACPI_MACHINE_WIDTH == 32
-#define ACPI_MOVE_SIZE_TO_16(d,s) ACPI_MOVE_32_TO_16(d,s)
+#define ACPI_MOVE_SIZE_TO_16(d, s) ACPI_MOVE_32_TO_16(d, s)
#elif ACPI_MACHINE_WIDTH == 64
-#define ACPI_MOVE_SIZE_TO_16(d,s) ACPI_MOVE_64_TO_16(d,s)
+#define ACPI_MOVE_SIZE_TO_16(d, s) ACPI_MOVE_64_TO_16(d, s)
#else
#error unknown ACPI_MACHINE_WIDTH
@@ -269,29 +261,29 @@ struct acpi_integer_overlay {
/*
* Fast power-of-two math macros for non-optimized compilers
*/
-#define _ACPI_DIV(value,power_of2) ((u32) ((value) >> (power_of2)))
-#define _ACPI_MUL(value,power_of2) ((u32) ((value) << (power_of2)))
-#define _ACPI_MOD(value,divisor) ((u32) ((value) & ((divisor) -1)))
+#define _ACPI_DIV(value, power_of2) ((u32) ((value) >> (power_of2)))
+#define _ACPI_MUL(value, power_of2) ((u32) ((value) << (power_of2)))
+#define _ACPI_MOD(value, divisor) ((u32) ((value) & ((divisor) -1)))
-#define ACPI_DIV_2(a) _ACPI_DIV(a,1)
-#define ACPI_MUL_2(a) _ACPI_MUL(a,1)
-#define ACPI_MOD_2(a) _ACPI_MOD(a,2)
+#define ACPI_DIV_2(a) _ACPI_DIV(a, 1)
+#define ACPI_MUL_2(a) _ACPI_MUL(a, 1)
+#define ACPI_MOD_2(a) _ACPI_MOD(a, 2)
-#define ACPI_DIV_4(a) _ACPI_DIV(a,2)
-#define ACPI_MUL_4(a) _ACPI_MUL(a,2)
-#define ACPI_MOD_4(a) _ACPI_MOD(a,4)
+#define ACPI_DIV_4(a) _ACPI_DIV(a, 2)
+#define ACPI_MUL_4(a) _ACPI_MUL(a, 2)
+#define ACPI_MOD_4(a) _ACPI_MOD(a, 4)
-#define ACPI_DIV_8(a) _ACPI_DIV(a,3)
-#define ACPI_MUL_8(a) _ACPI_MUL(a,3)
-#define ACPI_MOD_8(a) _ACPI_MOD(a,8)
+#define ACPI_DIV_8(a) _ACPI_DIV(a, 3)
+#define ACPI_MUL_8(a) _ACPI_MUL(a, 3)
+#define ACPI_MOD_8(a) _ACPI_MOD(a, 8)
-#define ACPI_DIV_16(a) _ACPI_DIV(a,4)
-#define ACPI_MUL_16(a) _ACPI_MUL(a,4)
-#define ACPI_MOD_16(a) _ACPI_MOD(a,16)
+#define ACPI_DIV_16(a) _ACPI_DIV(a, 4)
+#define ACPI_MUL_16(a) _ACPI_MUL(a, 4)
+#define ACPI_MOD_16(a) _ACPI_MOD(a, 16)
-#define ACPI_DIV_32(a) _ACPI_DIV(a,5)
-#define ACPI_MUL_32(a) _ACPI_MUL(a,5)
-#define ACPI_MOD_32(a) _ACPI_MOD(a,32)
+#define ACPI_DIV_32(a) _ACPI_DIV(a, 5)
+#define ACPI_MUL_32(a) _ACPI_MUL(a, 5)
+#define ACPI_MOD_32(a) _ACPI_MOD(a, 32)
/*
* Rounding macros (Power of two boundaries only)
@@ -305,13 +297,13 @@ struct acpi_integer_overlay {
/* Note: sizeof(acpi_size) evaluates to either 4 or 8 (32- vs 64-bit mode) */
-#define ACPI_ROUND_DOWN_TO_32BIT(a) ACPI_ROUND_DOWN(a,4)
-#define ACPI_ROUND_DOWN_TO_64BIT(a) ACPI_ROUND_DOWN(a,8)
-#define ACPI_ROUND_DOWN_TO_NATIVE_WORD(a) ACPI_ROUND_DOWN(a,sizeof(acpi_size))
+#define ACPI_ROUND_DOWN_TO_32BIT(a) ACPI_ROUND_DOWN(a, 4)
+#define ACPI_ROUND_DOWN_TO_64BIT(a) ACPI_ROUND_DOWN(a, 8)
+#define ACPI_ROUND_DOWN_TO_NATIVE_WORD(a) ACPI_ROUND_DOWN(a, sizeof(acpi_size))
-#define ACPI_ROUND_UP_TO_32BIT(a) ACPI_ROUND_UP(a,4)
-#define ACPI_ROUND_UP_TO_64BIT(a) ACPI_ROUND_UP(a,8)
-#define ACPI_ROUND_UP_TO_NATIVE_WORD(a) ACPI_ROUND_UP(a,sizeof(acpi_size))
+#define ACPI_ROUND_UP_TO_32BIT(a) ACPI_ROUND_UP(a, 4)
+#define ACPI_ROUND_UP_TO_64BIT(a) ACPI_ROUND_UP(a, 8)
+#define ACPI_ROUND_UP_TO_NATIVE_WORD(a) ACPI_ROUND_UP(a, sizeof(acpi_size))
#define ACPI_ROUND_BITS_UP_TO_BYTES(a) ACPI_DIV_8((a) + 7)
#define ACPI_ROUND_BITS_DOWN_TO_BYTES(a) ACPI_DIV_8((a))
@@ -320,9 +312,9 @@ struct acpi_integer_overlay {
/* Generic (non-power-of-two) rounding */
-#define ACPI_ROUND_UP_TO(value,boundary) (((value) + ((boundary)-1)) / (boundary))
+#define ACPI_ROUND_UP_TO(value, boundary) (((value) + ((boundary)-1)) / (boundary))
-#define ACPI_IS_MISALIGNED(value) (((acpi_size)value) & (sizeof(acpi_size)-1))
+#define ACPI_IS_MISALIGNED(value) (((acpi_size) value) & (sizeof(acpi_size)-1))
/*
* Bitmask creation
@@ -333,8 +325,6 @@ struct acpi_integer_overlay {
#define ACPI_MASK_BITS_ABOVE(position) (~((ACPI_INTEGER_MAX) << ((u32) (position))))
#define ACPI_MASK_BITS_BELOW(position) ((ACPI_INTEGER_MAX) << ((u32) (position)))
-#define ACPI_IS_OCTAL_DIGIT(d) (((char)(d) >= '0') && ((char)(d) <= '7'))
-
/* Bitfields within ACPI registers */
#define ACPI_REGISTER_PREPARE_BITS(val, pos, mask) ((val << pos) & mask)
@@ -342,39 +332,29 @@ struct acpi_integer_overlay {
#define ACPI_INSERT_BITS(target, mask, source) target = ((target & (~(mask))) | (source & mask))
-/* Generate a UUID */
-
-#define ACPI_INIT_UUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
- (a) & 0xFF, ((a) >> 8) & 0xFF, ((a) >> 16) & 0xFF, ((a) >> 24) & 0xFF, \
- (b) & 0xFF, ((b) >> 8) & 0xFF, \
- (c) & 0xFF, ((c) >> 8) & 0xFF, \
- (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)
-
/*
- * An struct acpi_namespace_node * can appear in some contexts,
- * where a pointer to an union acpi_operand_object can also
- * appear. This macro is used to distinguish them.
+ * An struct acpi_namespace_node can appear in some contexts
+ * where a pointer to an union acpi_operand_object can also
+ * appear. This macro is used to distinguish them.
*
* The "Descriptor" field is the first field in both structures.
*/
#define ACPI_GET_DESCRIPTOR_TYPE(d) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type)
-#define ACPI_SET_DESCRIPTOR_TYPE(d,t) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type = t)
+#define ACPI_SET_DESCRIPTOR_TYPE(d, t) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type = t)
/* Macro to test the object type */
#define ACPI_GET_OBJECT_TYPE(d) (((union acpi_operand_object *)(void *)(d))->common.type)
-/* Macro to check the table flags for SINGLE or MULTIPLE tables are allowed */
-
-#define ACPI_IS_SINGLE_TABLE(x) (((x) & 0x01) == ACPI_TABLE_SINGLE ? 1 : 0)
-
/*
* Macros for the master AML opcode table
*/
-#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT)
-#define ACPI_OP(name,Pargs,Iargs,obj_type,class,type,flags) {name,(u32)(Pargs),(u32)(Iargs),(u32)(flags),obj_type,class,type}
+#if defined (ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT)
+#define ACPI_OP(name, Pargs, Iargs, obj_type, class, type, flags) \
+ {name, (u32)(Pargs), (u32)(Iargs), (u32)(flags), obj_type, class, type}
#else
-#define ACPI_OP(name,Pargs,Iargs,obj_type,class,type,flags) {(u32)(Pargs),(u32)(Iargs),(u32)(flags),obj_type,class,type}
+#define ACPI_OP(name, Pargs, Iargs, obj_type, class, type, flags) \
+ {(u32)(Pargs), (u32)(Iargs), (u32)(flags), obj_type, class, type}
#endif
#ifdef ACPI_DISASSEMBLER
@@ -392,18 +372,18 @@ struct acpi_integer_overlay {
#define ARG_6(x) ((u32)(x) << (5 * ARG_TYPE_WIDTH))
#define ARGI_LIST1(a) (ARG_1(a))
-#define ARGI_LIST2(a,b) (ARG_1(b)|ARG_2(a))
-#define ARGI_LIST3(a,b,c) (ARG_1(c)|ARG_2(b)|ARG_3(a))
-#define ARGI_LIST4(a,b,c,d) (ARG_1(d)|ARG_2(c)|ARG_3(b)|ARG_4(a))
-#define ARGI_LIST5(a,b,c,d,e) (ARG_1(e)|ARG_2(d)|ARG_3(c)|ARG_4(b)|ARG_5(a))
-#define ARGI_LIST6(a,b,c,d,e,f) (ARG_1(f)|ARG_2(e)|ARG_3(d)|ARG_4(c)|ARG_5(b)|ARG_6(a))
+#define ARGI_LIST2(a, b) (ARG_1(b)|ARG_2(a))
+#define ARGI_LIST3(a, b, c) (ARG_1(c)|ARG_2(b)|ARG_3(a))
+#define ARGI_LIST4(a, b, c, d) (ARG_1(d)|ARG_2(c)|ARG_3(b)|ARG_4(a))
+#define ARGI_LIST5(a, b, c, d, e) (ARG_1(e)|ARG_2(d)|ARG_3(c)|ARG_4(b)|ARG_5(a))
+#define ARGI_LIST6(a, b, c, d, e, f) (ARG_1(f)|ARG_2(e)|ARG_3(d)|ARG_4(c)|ARG_5(b)|ARG_6(a))
#define ARGP_LIST1(a) (ARG_1(a))
-#define ARGP_LIST2(a,b) (ARG_1(a)|ARG_2(b))
-#define ARGP_LIST3(a,b,c) (ARG_1(a)|ARG_2(b)|ARG_3(c))
-#define ARGP_LIST4(a,b,c,d) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d))
-#define ARGP_LIST5(a,b,c,d,e) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d)|ARG_5(e))
-#define ARGP_LIST6(a,b,c,d,e,f) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d)|ARG_5(e)|ARG_6(f))
+#define ARGP_LIST2(a, b) (ARG_1(a)|ARG_2(b))
+#define ARGP_LIST3(a, b, c) (ARG_1(a)|ARG_2(b)|ARG_3(c))
+#define ARGP_LIST4(a, b, c, d) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d))
+#define ARGP_LIST5(a, b, c, d, e) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d)|ARG_5(e))
+#define ARGP_LIST6(a, b, c, d, e, f) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d)|ARG_5(e)|ARG_6(f))
#define GET_CURRENT_ARG_TYPE(list) (list & ((u32) 0x1F))
#define INCREMENT_ARG_LIST(list) (list >>= ((u32) ARG_TYPE_WIDTH))
@@ -434,8 +414,8 @@ struct acpi_integer_overlay {
#define ACPI_WARNING(plist) acpi_ut_warning plist
#define ACPI_EXCEPTION(plist) acpi_ut_exception plist
#define ACPI_ERROR(plist) acpi_ut_error plist
-#define ACPI_ERROR_NAMESPACE(s,e) acpi_ns_report_error (AE_INFO, s, e);
-#define ACPI_ERROR_METHOD(s,n,p,e) acpi_ns_report_method_error (AE_INFO, s, n, p, e);
+#define ACPI_ERROR_NAMESPACE(s, e) acpi_ns_report_error (AE_INFO, s, e);
+#define ACPI_ERROR_METHOD(s, n, p, e) acpi_ns_report_method_error (AE_INFO, s, n, p, e);
#else
@@ -445,8 +425,8 @@ struct acpi_integer_overlay {
#define ACPI_WARNING(plist)
#define ACPI_EXCEPTION(plist)
#define ACPI_ERROR(plist)
-#define ACPI_ERROR_NAMESPACE(s,e)
-#define ACPI_ERROR_METHOD(s,n,p,e)
+#define ACPI_ERROR_NAMESPACE(s, e)
+#define ACPI_ERROR_METHOD(s, n, p, e)
#endif
/*
@@ -489,18 +469,18 @@ struct acpi_integer_overlay {
#define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \
acpi_ut_trace(ACPI_DEBUG_PARAMETERS)
-#define ACPI_FUNCTION_TRACE_PTR(a,b) ACPI_FUNCTION_NAME(a) \
- acpi_ut_trace_ptr(ACPI_DEBUG_PARAMETERS,(void *)b)
-#define ACPI_FUNCTION_TRACE_U32(a,b) ACPI_FUNCTION_NAME(a) \
- acpi_ut_trace_u32(ACPI_DEBUG_PARAMETERS,(u32)b)
-#define ACPI_FUNCTION_TRACE_STR(a,b) ACPI_FUNCTION_NAME(a) \
- acpi_ut_trace_str(ACPI_DEBUG_PARAMETERS,(char *)b)
+#define ACPI_FUNCTION_TRACE_PTR(a, b) ACPI_FUNCTION_NAME(a) \
+ acpi_ut_trace_ptr(ACPI_DEBUG_PARAMETERS, (void *)b)
+#define ACPI_FUNCTION_TRACE_U32(a, b) ACPI_FUNCTION_NAME(a) \
+ acpi_ut_trace_u32(ACPI_DEBUG_PARAMETERS, (u32)b)
+#define ACPI_FUNCTION_TRACE_STR(a, b) ACPI_FUNCTION_NAME(a) \
+ acpi_ut_trace_str(ACPI_DEBUG_PARAMETERS, (char *)b)
#define ACPI_FUNCTION_ENTRY() acpi_ut_track_stack_ptr()
/*
* Function exit tracing.
- * WARNING: These macros include a return statement. This is usually considered
+ * WARNING: These macros include a return statement. This is usually considered
* bad form, but having a separate exit macro is very ugly and difficult to maintain.
* One of the FUNCTION_TRACE macros above must be used in conjunction with these macros
* so that "_AcpiFunctionName" is defined.
@@ -596,13 +576,13 @@ struct acpi_integer_overlay {
/* Stack and buffer dumping */
-#define ACPI_DUMP_STACK_ENTRY(a) acpi_ex_dump_operand((a),0)
-#define ACPI_DUMP_OPERANDS(a,b,c) acpi_ex_dump_operands(a,b,c)
+#define ACPI_DUMP_STACK_ENTRY(a) acpi_ex_dump_operand((a), 0)
+#define ACPI_DUMP_OPERANDS(a, b, c) acpi_ex_dump_operands(a, b, c)
-#define ACPI_DUMP_ENTRY(a,b) acpi_ns_dump_entry (a,b)
-#define ACPI_DUMP_PATHNAME(a,b,c,d) acpi_ns_dump_pathname(a,b,c,d)
+#define ACPI_DUMP_ENTRY(a, b) acpi_ns_dump_entry (a, b)
+#define ACPI_DUMP_PATHNAME(a, b, c, d) acpi_ns_dump_pathname(a, b, c, d)
#define ACPI_DUMP_RESOURCE_LIST(a) acpi_rs_dump_resource_list(a)
-#define ACPI_DUMP_BUFFER(a,b) acpi_ut_dump_buffer((u8 *)a,b,DB_BYTE_DISPLAY,_COMPONENT)
+#define ACPI_DUMP_BUFFER(a, b) acpi_ut_dump_buffer((u8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT)
/*
* Master debug print macros
@@ -625,20 +605,20 @@ struct acpi_integer_overlay {
#define ACPI_DEBUG_ONLY_MEMBERS(a) do { } while(0)
#define ACPI_FUNCTION_NAME(a) do { } while(0)
#define ACPI_FUNCTION_TRACE(a) do { } while(0)
-#define ACPI_FUNCTION_TRACE_PTR(a,b) do { } while(0)
-#define ACPI_FUNCTION_TRACE_U32(a,b) do { } while(0)
-#define ACPI_FUNCTION_TRACE_STR(a,b) do { } while(0)
+#define ACPI_FUNCTION_TRACE_PTR(a, b) do { } while(0)
+#define ACPI_FUNCTION_TRACE_U32(a, b) do { } while(0)
+#define ACPI_FUNCTION_TRACE_STR(a, b) do { } while(0)
#define ACPI_FUNCTION_EXIT do { } while(0)
#define ACPI_FUNCTION_STATUS_EXIT(s) do { } while(0)
#define ACPI_FUNCTION_VALUE_EXIT(s) do { } while(0)
#define ACPI_FUNCTION_ENTRY() do { } while(0)
#define ACPI_DUMP_STACK_ENTRY(a) do { } while(0)
-#define ACPI_DUMP_OPERANDS(a,b,c) do { } while(0)
-#define ACPI_DUMP_ENTRY(a,b) do { } while(0)
-#define ACPI_DUMP_TABLES(a,b) do { } while(0)
-#define ACPI_DUMP_PATHNAME(a,b,c,d) do { } while(0)
+#define ACPI_DUMP_OPERANDS(a, b, c) do { } while(0)
+#define ACPI_DUMP_ENTRY(a, b) do { } while(0)
+#define ACPI_DUMP_TABLES(a, b) do { } while(0)
+#define ACPI_DUMP_PATHNAME(a, b, c, d) do { } while(0)
#define ACPI_DUMP_RESOURCE_LIST(a) do { } while(0)
-#define ACPI_DUMP_BUFFER(a,b) do { } while(0)
+#define ACPI_DUMP_BUFFER(a, b) do { } while(0)
#define ACPI_DEBUG_PRINT(pl) do { } while(0)
#define ACPI_DEBUG_PRINT_RAW(pl) do { } while(0)
@@ -677,15 +657,17 @@ struct acpi_integer_overlay {
/*
* Memory allocation tracking (DEBUG ONLY)
*/
+#define ACPI_MEM_PARAMETERS _COMPONENT, _acpi_module_name, __LINE__
+
#ifndef ACPI_DBG_TRACK_ALLOCATIONS
/* Memory allocation */
#ifndef ACPI_ALLOCATE
-#define ACPI_ALLOCATE(a) acpi_ut_allocate((acpi_size)(a),_COMPONENT,_acpi_module_name,__LINE__)
+#define ACPI_ALLOCATE(a) acpi_ut_allocate((acpi_size)(a), ACPI_MEM_PARAMETERS)
#endif
#ifndef ACPI_ALLOCATE_ZEROED
-#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__)
+#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed((acpi_size)(a), ACPI_MEM_PARAMETERS)
#endif
#ifndef ACPI_FREE
#define ACPI_FREE(a) acpio_os_free(a)
@@ -696,9 +678,9 @@ struct acpi_integer_overlay {
/* Memory allocation */
-#define ACPI_ALLOCATE(a) acpi_ut_allocate_and_track((acpi_size)(a),_COMPONENT,_acpi_module_name,__LINE__)
-#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed_and_track((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__)
-#define ACPI_FREE(a) acpi_ut_free_and_track(a,_COMPONENT,_acpi_module_name,__LINE__)
+#define ACPI_ALLOCATE(a) acpi_ut_allocate_and_track((acpi_size)(a), ACPI_MEM_PARAMETERS)
+#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed_and_track((acpi_size)(a), ACPI_MEM_PARAMETERS)
+#define ACPI_FREE(a) acpi_ut_free_and_track(a, ACPI_MEM_PARAMETERS)
#define ACPI_MEM_TRACKING(a) a
#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
--
1.5.5.1
From: Bob Moore <[email protected]>
Signed-off-by: Bob Moore <[email protected]>
Signed-off-by: Lin Ming <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
include/acpi/acconfig.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index 328caee..4da88b1 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -63,7 +63,7 @@
/* Current ACPICA subsystem version in YYYYMMDD format */
-#define ACPI_CA_VERSION 0x20080701
+#define ACPI_CA_VERSION 0x20080729
/*
* OS name, used for the _OS object. The _OS object is essentially obsolete,
--
1.5.5.1
From: Shaohua Li <[email protected]>
In some BIOSes, every _STA method call will send a notification again,
this cause freeze. And in some BIOSes, it appears _STA should be called
after _DCK. This tries to avoid calls _STA, and still keep the device
present check.
http://bugzilla.kernel.org/show_bug.cgi?id=10431
Signed-off-by: Shaohua Li <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/dock.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 7d2edf1..25d2161 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -604,14 +604,17 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
static void dock_notify(acpi_handle handle, u32 event, void *data)
{
struct dock_station *ds = data;
+ struct acpi_device *tmp;
switch (event) {
case ACPI_NOTIFY_BUS_CHECK:
- if (!dock_in_progress(ds) && dock_present(ds)) {
+ if (!dock_in_progress(ds) && acpi_bus_get_device(ds->handle,
+ &tmp)) {
begin_dock(ds);
dock(ds);
if (!dock_present(ds)) {
printk(KERN_ERR PREFIX "Unable to dock!\n");
+ complete_dock(ds);
break;
}
atomic_notifier_call_chain(&dock_notifier_list,
--
1.5.5.1
From: Bob Moore <[email protected]>
Support for the x2APIC. There are 2 new subtables for the MADT and
one new subtable for the SRAT. Includes disassembler and acpisrc
support. Data from the Intel 64 Architecture x2APIC Specification,
June 2008.
Signed-off-by: Bob Moore <[email protected]>
Signed-off-by: Lin Ming <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
include/acpi/acdisasm.h | 4 +++
include/acpi/actbl1.h | 51 +++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 49 insertions(+), 6 deletions(-)
diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h
index f53faca..0c1ed38 100644
--- a/include/acpi/acdisasm.h
+++ b/include/acpi/acdisasm.h
@@ -186,6 +186,8 @@ extern struct acpi_dmtable_info acpi_dm_table_info_madt5[];
extern struct acpi_dmtable_info acpi_dm_table_info_madt6[];
extern struct acpi_dmtable_info acpi_dm_table_info_madt7[];
extern struct acpi_dmtable_info acpi_dm_table_info_madt8[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt9[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt10[];
extern struct acpi_dmtable_info acpi_dm_table_info_madt_hdr[];
extern struct acpi_dmtable_info acpi_dm_table_info_mcfg[];
extern struct acpi_dmtable_info acpi_dm_table_info_mcfg0[];
@@ -197,8 +199,10 @@ extern struct acpi_dmtable_info acpi_dm_table_info_slit[];
extern struct acpi_dmtable_info acpi_dm_table_info_spcr[];
extern struct acpi_dmtable_info acpi_dm_table_info_spmi[];
extern struct acpi_dmtable_info acpi_dm_table_info_srat[];
+extern struct acpi_dmtable_info acpi_dm_table_info_srat_hdr[];
extern struct acpi_dmtable_info acpi_dm_table_info_srat0[];
extern struct acpi_dmtable_info acpi_dm_table_info_srat1[];
+extern struct acpi_dmtable_info acpi_dm_table_info_srat2[];
extern struct acpi_dmtable_info acpi_dm_table_info_tcpa[];
extern struct acpi_dmtable_info acpi_dm_table_info_wdrt[];
diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h
index d38f9be..63f5b4c 100644
--- a/include/acpi/actbl1.h
+++ b/include/acpi/actbl1.h
@@ -908,7 +908,9 @@ enum acpi_madt_type {
ACPI_MADT_TYPE_IO_SAPIC = 6,
ACPI_MADT_TYPE_LOCAL_SAPIC = 7,
ACPI_MADT_TYPE_INTERRUPT_SOURCE = 8,
- ACPI_MADT_TYPE_RESERVED = 9 /* 9 and greater are reserved */
+ ACPI_MADT_TYPE_LOCAL_X2APIC = 9,
+ ACPI_MADT_TYPE_LOCAL_X2APIC_NMI = 10,
+ ACPI_MADT_TYPE_RESERVED = 11 /* 11 and greater are reserved */
};
/*
@@ -1009,6 +1011,26 @@ struct acpi_madt_interrupt_source {
#define ACPI_MADT_CPEI_OVERRIDE (1)
+/* 9: Processor Local X2_APIC (07/2008) */
+
+struct acpi_madt_local_x2apic {
+ struct acpi_subtable_header header;
+ u16 reserved; /* Reserved - must be zero */
+ u32 local_apic_id; /* Processor X2_APIC ID */
+ u32 lapic_flags;
+ u32 uid; /* Extended X2_APIC processor ID */
+};
+
+/* 10: Local X2APIC NMI (07/2008) */
+
+struct acpi_madt_local_x2apic_nmi {
+ struct acpi_subtable_header header;
+ u16 inti_flags;
+ u32 uid; /* Processor X2_APIC ID */
+ u8 lint; /* LINTn to which NMI is connected */
+ u8 reserved[3];
+};
+
/*
* Common flags fields for MADT subtables
*/
@@ -1150,10 +1172,15 @@ struct acpi_table_srat {
enum acpi_srat_type {
ACPI_SRAT_TYPE_CPU_AFFINITY = 0,
ACPI_SRAT_TYPE_MEMORY_AFFINITY = 1,
- ACPI_SRAT_TYPE_RESERVED = 2
+ ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY = 2,
+ ACPI_SRAT_TYPE_RESERVED = 3 /* 3 and greater are reserved */
};
-/* SRAT sub-tables */
+/*
+ * SRAT Sub-tables, correspond to Type in struct acpi_subtable_header
+ */
+
+/* 0: Processor Local APIC/SAPIC Affinity */
struct acpi_srat_cpu_affinity {
struct acpi_subtable_header header;
@@ -1165,9 +1192,7 @@ struct acpi_srat_cpu_affinity {
u32 reserved; /* Reserved, must be zero */
};
-/* Flags */
-
-#define ACPI_SRAT_CPU_ENABLED (1) /* 00: Use affinity structure */
+/* 1: Memory Affinity */
struct acpi_srat_mem_affinity {
struct acpi_subtable_header header;
@@ -1186,6 +1211,20 @@ struct acpi_srat_mem_affinity {
#define ACPI_SRAT_MEM_HOT_PLUGGABLE (1<<1) /* 01: Memory region is hot pluggable */
#define ACPI_SRAT_MEM_NON_VOLATILE (1<<2) /* 02: Memory region is non-volatile */
+/* 2: Processor Local X2_APIC Affinity (07/2008) */
+
+struct acpi_srat_x2apic_cpu_affinity {
+ struct acpi_subtable_header header;
+ u16 reserved; /* Reserved, must be zero */
+ u32 proximity_domain;
+ u32 apic_id;
+ u32 flags;
+};
+
+/* Flags for struct acpi_srat_cpu_affinity and struct acpi_srat_x2apic_cpu_affinity */
+
+#define ACPI_SRAT_CPU_ENABLED (1) /* 00: Use affinity structure */
+
/*******************************************************************************
*
* TCPA - Trusted Computing Platform Alliance table
--
1.5.5.1
From: Bob Moore <[email protected]>
Update version to 20080701.
Signed-off-by: Bob Moore <[email protected]>
Signed-off-by: Lin Ming <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
include/acpi/acconfig.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index 4eb75a8..328caee 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -63,7 +63,7 @@
/* Current ACPICA subsystem version in YYYYMMDD format */
-#define ACPI_CA_VERSION 0x20080609
+#define ACPI_CA_VERSION 0x20080701
/*
* OS name, used for the _OS object. The _OS object is essentially obsolete,
--
1.5.5.1
From: Bob Moore <[email protected]>
Created for improved error messages.
Signed-off-by: Bob Moore <[email protected]>
Signed-off-by: Lin Ming <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/utilities/utglobal.c | 36 ++++++++++++++++++++++++++++++++++++
include/acpi/acutils.h | 2 ++
2 files changed, 38 insertions(+), 0 deletions(-)
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
index a6e71b8..5e57ed9 100644
--- a/drivers/acpi/utilities/utglobal.c
+++ b/drivers/acpi/utilities/utglobal.c
@@ -45,6 +45,7 @@
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
+#include <acpi/amlcode.h>
ACPI_EXPORT_SYMBOL(acpi_gbl_FADT)
#define _COMPONENT ACPI_UTILITIES
@@ -575,6 +576,41 @@ char *acpi_ut_get_descriptor_name(void *object)
}
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_get_reference_name
+ *
+ * PARAMETERS: Object - An ACPI reference object
+ *
+ * RETURN: Pointer to a string
+ *
+ * DESCRIPTION: Decode a reference object sub-type to a string.
+ *
+ ******************************************************************************/
+
+/* Printable names of reference object sub-types */
+
+const char *acpi_ut_get_reference_name(union acpi_operand_object *object)
+{
+
+ switch (object->reference.opcode) {
+ case AML_INT_NAMEPATH_OP:
+ return "Name";
+
+ case AML_LOAD_OP:
+ return "DDB-Handle";
+
+ case AML_REF_OF_OP:
+ return "RefOf";
+
+ case AML_INDEX_OP:
+ return "Index";
+
+ default:
+ return "Unknown";
+ }
+}
+
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
/*
* Strings and procedures used for debug only
diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h
index 69f8888..f827822 100644
--- a/include/acpi/acutils.h
+++ b/include/acpi/acutils.h
@@ -126,6 +126,8 @@ char *acpi_ut_get_node_name(void *object);
char *acpi_ut_get_descriptor_name(void *object);
+const char *acpi_ut_get_reference_name(union acpi_operand_object *object);
+
char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc);
char *acpi_ut_get_region_name(u8 space_id);
--
1.5.5.1
From: Bob Moore <[email protected]>
Without this change, a table cannot be loaded again once it has
been loaded/unloaded one time. The current mechanism does not
unregister a table upon an unload. During a load, if the same
table is found, this no longer returns an exception.
http://www.acpica.org/bugzilla/show_bug.cgi?id=722
Signed-off-by: Bob Moore <[email protected]>
Signed-off-by: Lin Ming <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/tables/tbinstal.c | 49 ++++++++++++++++++++++++++++++++++-----
1 files changed, 42 insertions(+), 7 deletions(-)
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
index b22185f..905dc38 100644
--- a/drivers/acpi/tables/tbinstal.c
+++ b/drivers/acpi/tables/tbinstal.c
@@ -145,6 +145,8 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
}
}
+ /* Check for a table match on the entire table length */
+
length = ACPI_MIN(table_desc->length,
acpi_gbl_root_table_list.tables[i].length);
if (ACPI_MEMCMP(table_desc->pointer,
@@ -153,17 +155,49 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
continue;
}
- /* Table is already registered */
-
+ /*
+ * Note: the current mechanism does not unregister a table if it is
+ * dynamically unloaded. The related namespace entries are deleted,
+ * but the table remains in the root table list.
+ *
+ * The assumption here is that the number of different tables that
+ * will be loaded is actually small, and there is minimal overhead
+ * in just keeping the table in case it is needed again.
+ *
+ * If this assumption changes in the future (perhaps on large
+ * machines with many table load/unload operations), tables will
+ * need to be unregistered when they are unloaded, and slots in the
+ * root table list should be reused when empty.
+ */
+
+ /*
+ * Table is already registered.
+ * We can delete the table that was passed as a parameter.
+ */
acpi_tb_delete_table(table_desc);
*table_index = i;
- status = AE_ALREADY_EXISTS;
- goto release;
+
+ if (acpi_gbl_root_table_list.tables[i].
+ flags & ACPI_TABLE_IS_LOADED) {
+
+ /* Table is still loaded, this is an error */
+
+ status = AE_ALREADY_EXISTS;
+ goto release;
+ } else {
+ /* Table was unloaded, allow it to be reloaded */
+
+ table_desc->pointer =
+ acpi_gbl_root_table_list.tables[i].pointer;
+ table_desc->address =
+ acpi_gbl_root_table_list.tables[i].address;
+ status = AE_OK;
+ goto print_header;
+ }
}
- /*
- * Add the table to the global table list
- */
+ /* Add the table to the global root table list */
+
status = acpi_tb_store_table(table_desc->address, table_desc->pointer,
table_desc->length, table_desc->flags,
table_index);
@@ -171,6 +205,7 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
goto release;
}
+ print_header:
acpi_tb_print_table_header(table_desc->address, table_desc->pointer);
release:
--
1.5.5.1
From: Zhao Yakui <[email protected]>
Attach the ACPI device to the ACPI handle as early as possible so that OS
can get the corresponding ACPI device by the acpi handle in the course
of getting the power/wakeup/performance flags.
http://bugzilla.kernel.org/show_bug.cgi?id=8049
http://bugzilla.kernel.org/show_bug.cgi?id=11000
Signed-off-by: Zhao Yakui <[email protected]>
Signed-off-by: Zhang Rui <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
---
drivers/acpi/scan.c | 12 ++++++++++--
1 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 308ddb1..ad06798 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1253,6 +1253,16 @@ acpi_add_single_object(struct acpi_device **child,
acpi_device_set_id(device, parent, handle, type);
/*
+ * The ACPI device is attached to acpi handle before getting
+ * the power/wakeup/peformance flags. Otherwise OS can't get
+ * the corresponding ACPI device by the acpi handle in the course
+ * of getting the power/wakeup/performance flags.
+ */
+ result = acpi_device_set_context(device, type);
+ if (result)
+ goto end;
+
+ /*
* Power Management
* ----------------
*/
@@ -1282,8 +1292,6 @@ acpi_add_single_object(struct acpi_device **child,
goto end;
}
- if ((result = acpi_device_set_context(device, type)))
- goto end;
result = acpi_device_register(device, parent);
--
1.5.5.1
From: Lin Ming <[email protected]>
The AE_BAD_ADDRESS exception code is now unused in ACPICA.
For linux, it's only used at wmi.c and acer-wmi.c.
I checked both wmi.c and acer-wmi.c, the AE_BAD_ADDRESS exception code
has no special meaning. The parent functions just call AE_SUCCESS() or
AE_FAILURE() to check the return status.
So it's safe to replace AE_BAD_ADDRESS with AE_ERROR.
Signed-off-by Lin Ming <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
---
drivers/acpi/wmi.c | 10 +++++-----
drivers/misc/acer-wmi.c | 10 +++++-----
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/acpi/wmi.c b/drivers/acpi/wmi.c
index cfe2c83..5b94be3 100644
--- a/drivers/acpi/wmi.c
+++ b/drivers/acpi/wmi.c
@@ -242,7 +242,7 @@ u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)
char method[4] = "WM";
if (!find_guid(guid_string, &wblock))
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
block = &wblock->gblock;
handle = wblock->handle;
@@ -304,7 +304,7 @@ struct acpi_buffer *out)
return AE_BAD_PARAMETER;
if (!find_guid(guid_string, &wblock))
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
block = &wblock->gblock;
handle = wblock->handle;
@@ -314,7 +314,7 @@ struct acpi_buffer *out)
/* Check GUID is a data block */
if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
input.count = 1;
input.pointer = wq_params;
@@ -385,7 +385,7 @@ const struct acpi_buffer *in)
return AE_BAD_DATA;
if (!find_guid(guid_string, &wblock))
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
block = &wblock->gblock;
handle = wblock->handle;
@@ -395,7 +395,7 @@ const struct acpi_buffer *in)
/* Check GUID is a data block */
if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
input.count = 2;
input.pointer = params;
diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c
index d8b0d32..a67aef5 100644
--- a/drivers/misc/acer-wmi.c
+++ b/drivers/misc/acer-wmi.c
@@ -476,7 +476,7 @@ struct wmi_interface *iface)
}
break;
default:
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
}
return AE_OK;
}
@@ -514,7 +514,7 @@ static acpi_status AMW0_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
break;
}
default:
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
}
/* Actually do the set */
@@ -689,7 +689,7 @@ struct wmi_interface *iface)
return 0;
}
default:
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
}
status = WMI_execute_u32(method_id, 0, &result);
@@ -735,7 +735,7 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
}
break;
default:
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
}
return WMI_execute_u32(method_id, (u32)value, NULL);
}
@@ -785,7 +785,7 @@ static struct wmi_interface wmid_interface = {
static acpi_status get_u32(u32 *value, u32 cap)
{
- acpi_status status = AE_BAD_ADDRESS;
+ acpi_status status = AE_ERROR;
switch (interface->type) {
case ACER_AMW0:
--
1.5.5.1
From: Zhao Yakui <[email protected]>
Get the device power state in the course of scanning device if the device
power flag is power_managable. i.e. The device has the _PSx/_PRx object.
At the same time before the drivers/acpi/power module is loaded, there is no
relation between acpi_power_resource and acpi device. So the first parameter
of acpi_power_get_state is changed to acpi_handle.
http://bugzilla.kernel.org/show_bug.cgi?id=8049
http://bugzilla.kernel.org/show_bug.cgi?id=11000
Signed-off-by: Zhao Yakui <[email protected]>
Signed-off-by: Li Shaohua <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
---
drivers/acpi/power.c | 30 ++++++++++++++++--------------
drivers/acpi/scan.c | 1 +
2 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 4ab21cb..e7bab75 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -128,16 +128,16 @@ acpi_power_get_context(acpi_handle handle,
return 0;
}
-static int acpi_power_get_state(struct acpi_power_resource *resource, int *state)
+static int acpi_power_get_state(acpi_handle handle, int *state)
{
acpi_status status = AE_OK;
unsigned long sta = 0;
- if (!resource || !state)
+ if (!handle || !state)
return -EINVAL;
- status = acpi_evaluate_integer(resource->device->handle, "_STA", NULL, &sta);
+ status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status))
return -ENODEV;
@@ -145,7 +145,7 @@ static int acpi_power_get_state(struct acpi_power_resource *resource, int *state
ACPI_POWER_RESOURCE_STATE_OFF;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n",
- resource->name, state ? "on" : "off"));
+ acpi_ut_get_node_name(handle), state ? "on" : "off"));
return 0;
}
@@ -153,7 +153,6 @@ static int acpi_power_get_state(struct acpi_power_resource *resource, int *state
static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
{
int result = 0, state1;
- struct acpi_power_resource *resource = NULL;
u32 i = 0;
@@ -161,12 +160,15 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
return -EINVAL;
/* The state of the list is 'on' IFF all resources are 'on'. */
+ /* */
for (i = 0; i < list->count; i++) {
- result = acpi_power_get_context(list->handles[i], &resource);
- if (result)
- return result;
- result = acpi_power_get_state(resource, &state1);
+ /*
+ * The state of the power resource can be obtained by
+ * using the ACPI handle. In such case it is unnecessary to
+ * get the Power resource first and then get its state again.
+ */
+ result = acpi_power_get_state(list->handles[i], &state1);
if (result)
return result;
@@ -226,7 +228,7 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
if (ACPI_FAILURE(status))
return -ENODEV;
- result = acpi_power_get_state(resource, &state);
+ result = acpi_power_get_state(resource->device->handle, &state);
if (result)
return result;
if (state != ACPI_POWER_RESOURCE_STATE_ON)
@@ -277,7 +279,7 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
if (ACPI_FAILURE(status))
return -ENODEV;
- result = acpi_power_get_state(resource, &state);
+ result = acpi_power_get_state(handle, &state);
if (result)
return result;
if (state != ACPI_POWER_RESOURCE_STATE_OFF)
@@ -555,7 +557,7 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
if (!resource)
goto end;
- result = acpi_power_get_state(resource, &state);
+ result = acpi_power_get_state(resource->device->handle, &state);
if (result)
goto end;
@@ -668,7 +670,7 @@ static int acpi_power_add(struct acpi_device *device)
resource->system_level = acpi_object.power_resource.system_level;
resource->order = acpi_object.power_resource.resource_order;
- result = acpi_power_get_state(resource, &state);
+ result = acpi_power_get_state(device->handle, &state);
if (result)
goto end;
@@ -735,7 +737,7 @@ static int acpi_power_resume(struct acpi_device *device)
resource = (struct acpi_power_resource *)acpi_driver_data(device);
- result = acpi_power_get_state(resource, &state);
+ result = acpi_power_get_state(device->handle, &state);
if (result)
return result;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index f6f52c1..308ddb1 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -807,6 +807,7 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
/* TBD: System wake support and resource requirements. */
device->power.state = ACPI_STATE_UNKNOWN;
+ acpi_bus_get_power(device->handle, &(device->power.state));
return 0;
}
--
1.5.5.1
From: Fiodor Suietov <[email protected]>
Return AE_BAD_PARAMETER if input handle is invalid.
http://www.acpica.org/bugzilla/show_bug.cgi?id=474
Signed-off-by: Fiodor Suietov <[email protected]>
Signed-off-by: Bob Moore <[email protected]>
Signed-off-by: Lin Ming <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/namespace/nsxfname.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
index a287ed5..3cb910d 100644
--- a/drivers/acpi/namespace/nsxfname.c
+++ b/drivers/acpi/namespace/nsxfname.c
@@ -253,6 +253,7 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
node = acpi_ns_map_handle_to_node(handle);
if (!node) {
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ status = AE_BAD_PARAMETER;
goto cleanup;
}
--
1.5.5.1
From: Bob Moore <[email protected]>
Split the ACPI table compare. First check that the lengths match
exactly. Then compare the data.
Signed-off-by: Bob Moore <[email protected]>
Signed-off-by: Lin Ming <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/tables/tbinstal.c | 14 +++++++++-----
1 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
index 905dc38..18747ce 100644
--- a/drivers/acpi/tables/tbinstal.c
+++ b/drivers/acpi/tables/tbinstal.c
@@ -110,7 +110,6 @@ acpi_status
acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
{
u32 i;
- u32 length;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(tb_add_table);
@@ -145,13 +144,18 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
}
}
- /* Check for a table match on the entire table length */
+ /*
+ * Check for a table match on the entire table length,
+ * not just the header.
+ */
+ if (table_desc->length !=
+ acpi_gbl_root_table_list.tables[i].length) {
+ continue;
+ }
- length = ACPI_MIN(table_desc->length,
- acpi_gbl_root_table_list.tables[i].length);
if (ACPI_MEMCMP(table_desc->pointer,
acpi_gbl_root_table_list.tables[i].pointer,
- length)) {
+ acpi_gbl_root_table_list.tables[i].length)) {
continue;
}
--
1.5.5.1
From: Bob Moore <[email protected]>
Also update the debugger so that the correct number of arguments is
passed to the method. Prevents a warning message from the debugger.
Signed-off-by: Bob Moore <[email protected]>
Signed-off-by: Lin Ming <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/namespace/nsxfname.c | 4 ++++
include/acpi/actypes.h | 1 +
2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
index a287ed5..6d31a1f 100644
--- a/drivers/acpi/namespace/nsxfname.c
+++ b/drivers/acpi/namespace/nsxfname.c
@@ -264,6 +264,10 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
info->name = node->name.integer;
info->valid = 0;
+ if (node->type == ACPI_TYPE_METHOD) {
+ info->param_count = node->object->method.param_count;
+ }
+
status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
goto cleanup;
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 4ea4f40..298c636 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -859,6 +859,7 @@ struct acpi_obj_info_header {
struct acpi_device_info {
ACPI_COMMON_OBJ_INFO;
+ u32 param_count; /* If a method, required parameter count */
u32 valid; /* Indicates which fields below are valid */
u32 current_status; /* _STA value */
acpi_integer address; /* _ADR value if any */
--
1.5.5.1
From: Zhao Yakui <[email protected]>
The _TTS object is defined in the section 7.3 of acpi 3.0b spec.
The _TTS control method is executed by the OSPM at the beginning of
the sleep transition process for S1,S2, S3, S4, and orderly S5 shutdown.
OS will invoke _TTS before it has notified any native mode device drivers
of the sleep state transition. The target sleeping state value is passed to
the _TTS control method.
The _TTS control method is also executed by the OSPM at the end of
any sleep transition process when the system transitions to S0 from
S1, S2, S3, or S4. The _TTS object should be evaluated after it has
notified any native mode device drivers of the end of the sleep state
transition. The working state value (0) is passed to the _TTS control method.
So it is necessary to add the support for _TTS object. The _TTS object
will be evaluated if it exists.
At the same time a block notifier is added to the reboot notifier list so
that the _TTS object will also be evaluated when the system shutdown.
lenb: note that as of Sep 2008, I've not yet seen _TTS in any shipping BIOS.
So this patch is to future-proof Linux, rather than fix the installed base.
http://bugzilla.kernel.org/show_bug.cgi?id=11132
Signed-off-by: Zhao Yakui <[email protected]>
Signed-off-by: Li Shaohua <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/sleep/main.c | 49 ++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 48 insertions(+), 1 deletions(-)
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index d13194a..c7f0c9c 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -15,6 +15,7 @@
#include <linux/dmi.h>
#include <linux/device.h>
#include <linux/suspend.h>
+#include <linux/reboot.h>
#include <asm/io.h>
@@ -24,6 +25,36 @@
u8 sleep_states[ACPI_S_STATE_COUNT];
+static void acpi_sleep_tts_switch(u32 acpi_state)
+{
+ union acpi_object in_arg = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list arg_list = { 1, &in_arg };
+ acpi_status status = AE_OK;
+
+ in_arg.integer.value = acpi_state;
+ status = acpi_evaluate_object(NULL, "\\_TTS", &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ /*
+ * OS can't evaluate the _TTS object correctly. Some warning
+ * message will be printed. But it won't break anything.
+ */
+ printk(KERN_NOTICE "Failure in evaluating _TTS object\n");
+ }
+}
+
+static int tts_notify_reboot(struct notifier_block *this,
+ unsigned long code, void *x)
+{
+ acpi_sleep_tts_switch(ACPI_STATE_S5);
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block tts_notifier = {
+ .notifier_call = tts_notify_reboot,
+ .next = NULL,
+ .priority = 0,
+};
+
static int acpi_sleep_prepare(u32 acpi_state)
{
#ifdef CONFIG_ACPI_SLEEP
@@ -131,6 +162,7 @@ static void acpi_pm_end(void)
* failing transition to a sleep state.
*/
acpi_target_sleep_state = ACPI_STATE_S0;
+ acpi_sleep_tts_switch(acpi_target_sleep_state);
}
#endif /* CONFIG_PM_SLEEP */
@@ -155,6 +187,7 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
if (sleep_states[acpi_state]) {
acpi_target_sleep_state = acpi_state;
+ acpi_sleep_tts_switch(acpi_target_sleep_state);
} else {
printk(KERN_ERR "ACPI does not support this state: %d\n",
pm_state);
@@ -313,6 +346,7 @@ void __init acpi_no_s4_hw_signature(void)
static int acpi_hibernation_begin(void)
{
acpi_target_sleep_state = ACPI_STATE_S4;
+ acpi_sleep_tts_switch(acpi_target_sleep_state);
return 0;
}
@@ -376,7 +410,15 @@ static struct platform_hibernation_ops acpi_hibernation_ops = {
*/
static int acpi_hibernation_begin_old(void)
{
- int error = acpi_sleep_prepare(ACPI_STATE_S4);
+ int error;
+ /*
+ * The _TTS object should always be evaluated before the _PTS object.
+ * When the old_suspended_ordering is true, the _PTS object is
+ * evaluated in the acpi_sleep_prepare.
+ */
+ acpi_sleep_tts_switch(ACPI_STATE_S4);
+
+ error = acpi_sleep_prepare(ACPI_STATE_S4);
if (!error)
acpi_target_sleep_state = ACPI_STATE_S4;
@@ -596,5 +638,10 @@ int __init acpi_sleep_init(void)
pm_power_off = acpi_power_off;
}
printk(")\n");
+ /*
+ * Register the tts_notifier to reboot notifier list so that the _TTS
+ * object can also be evaluated when the system enters S5.
+ */
+ register_reboot_notifier(&tts_notifier);
return 0;
}
--
1.5.5.1
From: Shaohua Li <[email protected]>
dock's uevent reported itself, not ata. It might be difficult to find an
ata device just according to a dock. This patch introduces docking ops
for each device in a dock. when docking, dock driver can send device
specific uevent. This should help dock station too (not just bay)
Signed-off-by: Shaohua Li <[email protected]>
Acked-by: Tejun Heo <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/dock.c | 22 ++++++++++++-----
drivers/ata/libata-acpi.c | 44 ++++++++++++++++++++++++++++++++++-
drivers/pci/hotplug/acpiphp_glue.c | 6 +++-
include/acpi/acpi_drivers.h | 9 +++++-
4 files changed, 68 insertions(+), 13 deletions(-)
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index f19f643..ac7dfef 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -75,7 +75,7 @@ struct dock_dependent_device {
struct list_head list;
struct list_head hotplug_list;
acpi_handle handle;
- acpi_notify_handler handler;
+ struct acpi_dock_ops *ops;
void *context;
};
@@ -385,8 +385,8 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
* First call driver specific hotplug functions
*/
list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) {
- if (dd->handler)
- dd->handler(dd->handle, event, dd->context);
+ if (dd->ops && dd->ops->handler)
+ dd->ops->handler(dd->handle, event, dd->context);
}
/*
@@ -409,6 +409,7 @@ static void dock_event(struct dock_station *ds, u32 event, int num)
struct device *dev = &ds->dock_device->dev;
char event_string[13];
char *envp[] = { event_string, NULL };
+ struct dock_dependent_device *dd;
if (num == UNDOCK_EVENT)
sprintf(event_string, "EVENT=undock");
@@ -419,7 +420,14 @@ static void dock_event(struct dock_station *ds, u32 event, int num)
* Indicate that the status of the dock station has
* changed.
*/
- kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
+ if (num == DOCK_EVENT)
+ kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
+
+ list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list)
+ if (dd->ops && dd->ops->uevent)
+ dd->ops->uevent(dd->handle, event, dd->context);
+ if (num != DOCK_EVENT)
+ kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
}
/**
@@ -588,7 +596,7 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier);
/**
* register_hotplug_dock_device - register a hotplug function
* @handle: the handle of the device
- * @handler: the acpi_notifier_handler to call after docking
+ * @ops: handlers to call after docking
* @context: device specific data
*
* If a driver would like to perform a hotplug operation after a dock
@@ -596,7 +604,7 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier);
* the dock driver after _DCK is executed.
*/
int
-register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler,
+register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops,
void *context)
{
struct dock_dependent_device *dd;
@@ -612,7 +620,7 @@ register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler,
list_for_each_entry(dock_station, &dock_stations, sibiling) {
dd = find_dock_dependent_device(dock_station, handle);
if (dd) {
- dd->handler = handler;
+ dd->ops = ops;
dd->context = context;
dock_add_hotplug_device(dock_station, dd);
return 0;
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 97727be..c012307 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -209,6 +209,46 @@ static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data)
ata_acpi_handle_hotplug(ap, NULL, event);
}
+static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev,
+ u32 event)
+{
+ struct kobject *kobj = NULL;
+ char event_string[20];
+ char *envp[] = { event_string, NULL };
+
+ if (dev) {
+ if (dev->sdev)
+ kobj = &dev->sdev->sdev_gendev.kobj;
+ } else
+ kobj = &ap->dev->kobj;
+
+ if (kobj) {
+ snprintf(event_string, 20, "BAY_EVENT=%d", event);
+ kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
+ }
+}
+
+static void ata_acpi_ap_uevent(acpi_handle handle, u32 event, void *data)
+{
+ ata_acpi_uevent(data, NULL, event);
+}
+
+static void ata_acpi_dev_uevent(acpi_handle handle, u32 event, void *data)
+{
+ struct ata_device *dev = data;
+ ata_acpi_uevent(dev->link->ap, dev, event);
+}
+
+static struct acpi_dock_ops ata_acpi_dev_dock_ops = {
+ .handler = ata_acpi_dev_notify_dock,
+ .uevent = ata_acpi_dev_uevent,
+};
+
+static struct acpi_dock_ops ata_acpi_ap_dock_ops = {
+ .handler = ata_acpi_ap_notify_dock,
+ .uevent = ata_acpi_ap_uevent,
+};
+
/**
* ata_acpi_associate - associate ATA host with ACPI objects
* @host: target ATA host
@@ -244,7 +284,7 @@ void ata_acpi_associate(struct ata_host *host)
if (ap->acpi_handle) {
/* we might be on a docking station */
register_hotplug_dock_device(ap->acpi_handle,
- ata_acpi_ap_notify_dock, ap);
+ &ata_acpi_ap_dock_ops, ap);
}
for (j = 0; j < ata_link_max_devices(&ap->link); j++) {
@@ -253,7 +293,7 @@ void ata_acpi_associate(struct ata_host *host)
if (dev->acpi_handle) {
/* we might be on a docking station */
register_hotplug_dock_device(dev->acpi_handle,
- ata_acpi_dev_notify_dock, dev);
+ &ata_acpi_dev_dock_ops, dev);
}
}
}
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index a3e4705..db54c5e 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -169,7 +169,9 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
}
-
+static struct acpi_dock_ops acpiphp_dock_ops = {
+ .handler = handle_hotplug_event_func,
+};
/* callback routine to register each ACPI PCI slot object */
static acpi_status
@@ -285,7 +287,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
*/
newfunc->flags &= ~FUNC_HAS_EJ0;
if (register_hotplug_dock_device(handle,
- handle_hotplug_event_func, newfunc))
+ &acpiphp_dock_ops, newfunc))
dbg("failed to register dock device\n");
/* we need to be notified when dock events happen
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index e5f38e5..4f5042a 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -115,12 +115,17 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type);
/*--------------------------------------------------------------------------
Dock Station
-------------------------------------------------------------------------- */
+struct acpi_dock_ops {
+ acpi_notify_handler handler;
+ acpi_notify_handler uevent;
+};
+
#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
extern int is_dock_device(acpi_handle handle);
extern int register_dock_notifier(struct notifier_block *nb);
extern void unregister_dock_notifier(struct notifier_block *nb);
extern int register_hotplug_dock_device(acpi_handle handle,
- acpi_notify_handler handler,
+ struct acpi_dock_ops *ops,
void *context);
extern void unregister_hotplug_dock_device(acpi_handle handle);
#else
@@ -136,7 +141,7 @@ static inline void unregister_dock_notifier(struct notifier_block *nb)
{
}
static inline int register_hotplug_dock_device(acpi_handle handle,
- acpi_notify_handler handler,
+ struct acpi_dock_ops *ops,
void *context)
{
return -ENODEV;
--
1.5.5.1
From: Rafael J. Wysocki <[email protected]>
ACPI Suspend: Enable ACPI during resume if SCI_EN is not set
On some machines, like for example MSI Wind U100, the BIOS doesn't
enable ACPI before returning control to the OS, which sometimes
causes resume to fail. This is against the ACPI specification,
which clearly states that "When the platform is waking from an S1, S2
or S3 state, OSPM assumes the hardware is already in the ACPI mode
and will not issue an ACPI_ENABLE", but it won't hurt to check the
SCI_EN bit and enable ACPI during resume from S3 if this bit is not
set.
Fortunately, we already have acpi_enable() for that, so use it in the
resume code path, before executing _BFS, in analogy with the
resume-from-hibernation code path.
NOTE: We aren't supposed to set SCI_EN directly, because it's owned
by the hardware.
Signed-off-by: Rafael J. Wysocki <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/sleep/main.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index c7f0c9c..5419938 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -233,6 +233,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
break;
}
+ /* If ACPI is not enabled by the BIOS, we need to enable it here. */
+ acpi_enable();
/* Reprogram control registers and execute _BFS */
acpi_leave_sleep_state_prep(acpi_state);
--
1.5.5.1
From: Carlos Corbacho <[email protected]>
This patch implements rfkill support for the wireless and bluetooth devices
commonly found on Acer laptops.
For now, we will always poll these devices once a second to guarantee we
can catch state changes. On newer Acer laptops, it may be possible to rely
on WMI events to do this instead, and experimental support for this will be
added in a later patch.
3G has been deliberately left off for now, as we still have no way to
detect it, (nor, AFAIK, has any Linux user tried the code) and on laptops
that don't support 3G, trying to poll for the status will leave the logs
full of ACPI tracebacks.
The old sysfs interface for wireless and bluetooth will be removed in a
later patch.
(Thanks to Henrique de Moraes Holschuh and Dmitry Torokhov for reviewing
this patch).
Signed-off-by: Carlos Corbacho <[email protected]>
Acked-by: Henrique de Moraes Holschuh <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/misc/Kconfig | 1 +
drivers/misc/acer-wmi.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 130 insertions(+), 1 deletions(-)
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index a726f3b..6abb959 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -145,6 +145,7 @@ config ACER_WMI
depends on NEW_LEDS
depends on BACKLIGHT_CLASS_DEVICE
depends on SERIO_I8042
+ depends on RFKILL
select ACPI_WMI
---help---
This is a driver for newer Acer (and Wistron) laptops. It adds
diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c
index d8b0d32..e3e11e8 100644
--- a/drivers/misc/acer-wmi.c
+++ b/drivers/misc/acer-wmi.c
@@ -33,6 +33,8 @@
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/i8042.h>
+#include <linux/rfkill.h>
+#include <linux/workqueue.h>
#include <linux/debugfs.h>
#include <acpi/acpi_drivers.h>
@@ -157,6 +159,9 @@ struct acer_debug {
u32 wmid_devices;
};
+static struct rfkill *wireless_rfkill;
+static struct rfkill *bluetooth_rfkill;
+
/* Each low-level interface must define at least some of the following */
struct wmi_interface {
/* The WMI device type */
@@ -933,6 +938,125 @@ static void acer_backlight_exit(void)
}
/*
+ * Rfkill devices
+ */
+static struct workqueue_struct *rfkill_workqueue;
+
+static void acer_rfkill_update(struct work_struct *ignored);
+static DECLARE_DELAYED_WORK(acer_rfkill_work, acer_rfkill_update);
+static void acer_rfkill_update(struct work_struct *ignored)
+{
+ u32 state;
+ acpi_status status;
+
+ status = get_u32(&state, ACER_CAP_WIRELESS);
+ if (ACPI_SUCCESS(status))
+ rfkill_force_state(wireless_rfkill, state ?
+ RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED);
+
+ if (has_cap(ACER_CAP_BLUETOOTH)) {
+ status = get_u32(&state, ACER_CAP_BLUETOOTH);
+ if (ACPI_SUCCESS(status))
+ rfkill_force_state(bluetooth_rfkill, state ?
+ RFKILL_STATE_UNBLOCKED :
+ RFKILL_STATE_SOFT_BLOCKED);
+ }
+
+ queue_delayed_work(rfkill_workqueue, &acer_rfkill_work,
+ round_jiffies_relative(HZ));
+}
+
+static int acer_rfkill_set(void *data, enum rfkill_state state)
+{
+ acpi_status status;
+ u32 *cap = data;
+ status = set_u32((u32) (state == RFKILL_STATE_UNBLOCKED), *cap);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+ return 0;
+}
+
+static struct rfkill * acer_rfkill_register(struct device *dev,
+enum rfkill_type type, char *name, u32 cap)
+{
+ int err;
+ u32 state;
+ u32 *data;
+ struct rfkill *rfkill_dev;
+
+ rfkill_dev = rfkill_allocate(dev, type);
+ if (!rfkill_dev)
+ return ERR_PTR(-ENOMEM);
+ rfkill_dev->name = name;
+ get_u32(&state, cap);
+ rfkill_dev->state = state ? RFKILL_STATE_UNBLOCKED :
+ RFKILL_STATE_SOFT_BLOCKED;
+ data = kzalloc(sizeof(u32), GFP_KERNEL);
+ if (!data) {
+ rfkill_free(rfkill_dev);
+ return ERR_PTR(-ENOMEM);
+ }
+ *data = cap;
+ rfkill_dev->data = data;
+ rfkill_dev->toggle_radio = acer_rfkill_set;
+ rfkill_dev->user_claim_unsupported = 1;
+
+ err = rfkill_register(rfkill_dev);
+ if (err) {
+ kfree(rfkill_dev->data);
+ rfkill_free(rfkill_dev);
+ return ERR_PTR(err);
+ }
+ return rfkill_dev;
+}
+
+static int acer_rfkill_init(struct device *dev)
+{
+ wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN,
+ "acer-wireless", ACER_CAP_WIRELESS);
+ if (IS_ERR(wireless_rfkill))
+ return PTR_ERR(wireless_rfkill);
+
+ if (has_cap(ACER_CAP_BLUETOOTH)) {
+ bluetooth_rfkill = acer_rfkill_register(dev,
+ RFKILL_TYPE_BLUETOOTH, "acer-bluetooth",
+ ACER_CAP_BLUETOOTH);
+ if (IS_ERR(bluetooth_rfkill)) {
+ kfree(wireless_rfkill->data);
+ rfkill_unregister(wireless_rfkill);
+ return PTR_ERR(bluetooth_rfkill);
+ }
+ }
+
+ rfkill_workqueue = create_singlethread_workqueue("rfkill_workqueue");
+ if (!rfkill_workqueue) {
+ if (has_cap(ACER_CAP_BLUETOOTH)) {
+ kfree(bluetooth_rfkill->data);
+ rfkill_unregister(bluetooth_rfkill);
+ }
+ kfree(wireless_rfkill->data);
+ rfkill_unregister(wireless_rfkill);
+ return -ENOMEM;
+ }
+ queue_delayed_work(rfkill_workqueue, &acer_rfkill_work, HZ);
+
+ return 0;
+}
+
+static void acer_rfkill_exit(void)
+{
+ cancel_delayed_work_sync(&acer_rfkill_work);
+ destroy_workqueue(rfkill_workqueue);
+ kfree(wireless_rfkill->data);
+ rfkill_unregister(wireless_rfkill);
+ if (has_cap(ACER_CAP_BLUETOOTH)) {
+ kfree(wireless_rfkill->data);
+ rfkill_unregister(bluetooth_rfkill);
+ }
+ return;
+}
+
+/*
* Read/ write bool sysfs macro
*/
#define show_set_bool(value, cap) \
@@ -1026,7 +1150,9 @@ static int __devinit acer_platform_probe(struct platform_device *device)
goto error_brightness;
}
- return 0;
+ err = acer_rfkill_init(&device->dev);
+
+ return err;
error_brightness:
acer_led_exit();
@@ -1040,6 +1166,8 @@ static int acer_platform_remove(struct platform_device *device)
acer_led_exit();
if (has_cap(ACER_CAP_BRIGHTNESS))
acer_backlight_exit();
+
+ acer_rfkill_exit();
return 0;
}
--
1.5.5.1
From: Carlos Corbacho <[email protected]>
These are now replaced by the rfkill interface.
Signed-off-by: Carlos Corbacho <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
Documentation/laptops/acer-wmi.txt | 28 ++---------
drivers/misc/acer-wmi.c | 101 ++++++++----------------------------
2 files changed, 25 insertions(+), 104 deletions(-)
diff --git a/Documentation/laptops/acer-wmi.txt b/Documentation/laptops/acer-wmi.txt
index 69b5dd4..2b3a6b5 100644
--- a/Documentation/laptops/acer-wmi.txt
+++ b/Documentation/laptops/acer-wmi.txt
@@ -1,7 +1,7 @@
Acer Laptop WMI Extras Driver
http://code.google.com/p/aceracpi
-Version 0.1
-9th February 2008
+Version 0.2
+18th August 2008
Copyright 2007-2008 Carlos Corbacho <[email protected]>
@@ -87,17 +87,7 @@ acer-wmi come with built-in wireless. However, should you feel so inclined to
ever wish to remove the card, or swap it out at some point, please get in touch
with me, as we may well be able to gain some data on wireless card detection.
-To read the status of the wireless radio (0=off, 1=on):
-cat /sys/devices/platform/acer-wmi/wireless
-
-To enable the wireless radio:
-echo 1 > /sys/devices/platform/acer-wmi/wireless
-
-To disable the wireless radio:
-echo 0 > /sys/devices/platform/acer-wmi/wireless
-
-To set the state of the wireless radio when loading acer-wmi, pass:
-wireless=X (where X is 0 or 1)
+The wireless radio is exposed through rfkill.
Bluetooth
*********
@@ -117,17 +107,7 @@ For the adventurously minded - if you want to buy an internal bluetooth
module off the internet that is compatible with your laptop and fit it, then
it will work just fine with acer-wmi.
-To read the status of the bluetooth module (0=off, 1=on):
-cat /sys/devices/platform/acer-wmi/wireless
-
-To enable the bluetooth module:
-echo 1 > /sys/devices/platform/acer-wmi/bluetooth
-
-To disable the bluetooth module:
-echo 0 > /sys/devices/platform/acer-wmi/bluetooth
-
-To set the state of the bluetooth module when loading acer-wmi, pass:
-bluetooth=X (where X is 0 or 1)
+Bluetooth is exposed through rfkill.
3G
**
diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c
index e3e11e8..8708d31 100644
--- a/drivers/misc/acer-wmi.c
+++ b/drivers/misc/acer-wmi.c
@@ -125,21 +125,15 @@ enum interface_flags {
static int max_brightness = 0xF;
-static int wireless = -1;
-static int bluetooth = -1;
static int mailled = -1;
static int brightness = -1;
static int threeg = -1;
static int force_series;
module_param(mailled, int, 0444);
-module_param(wireless, int, 0444);
-module_param(bluetooth, int, 0444);
module_param(brightness, int, 0444);
module_param(threeg, int, 0444);
module_param(force_series, int, 0444);
-MODULE_PARM_DESC(wireless, "Set initial state of Wireless hardware");
-MODULE_PARM_DESC(bluetooth, "Set initial state of Bluetooth hardware");
MODULE_PARM_DESC(mailled, "Set initial state of Mail LED");
MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness");
MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware");
@@ -147,8 +141,6 @@ MODULE_PARM_DESC(force_series, "Force a different laptop series");
struct acer_data {
int mailled;
- int wireless;
- int bluetooth;
int threeg;
int brightness;
};
@@ -851,8 +843,6 @@ static void __init acer_commandline_init(void)
* capability isn't available on the given interface
*/
set_u32(mailled, ACER_CAP_MAILLED);
- set_u32(wireless, ACER_CAP_WIRELESS);
- set_u32(bluetooth, ACER_CAP_BLUETOOTH);
set_u32(threeg, ACER_CAP_THREEG);
set_u32(brightness, ACER_CAP_BRIGHTNESS);
}
@@ -1057,40 +1047,30 @@ static void acer_rfkill_exit(void)
}
/*
- * Read/ write bool sysfs macro
+ * sysfs interface
*/
-#define show_set_bool(value, cap) \
-static ssize_t \
-show_bool_##value(struct device *dev, struct device_attribute *attr, \
- char *buf) \
-{ \
+static ssize_t show_bool_threeg(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
u32 result; \
- acpi_status status = get_u32(&result, cap); \
- if (ACPI_SUCCESS(status)) \
- return sprintf(buf, "%u\n", result); \
- return sprintf(buf, "Read error\n"); \
-} \
-\
-static ssize_t \
-set_bool_##value(struct device *dev, struct device_attribute *attr, \
- const char *buf, size_t count) \
-{ \
- u32 tmp = simple_strtoul(buf, NULL, 10); \
- acpi_status status = set_u32(tmp, cap); \
- if (ACPI_FAILURE(status)) \
- return -EINVAL; \
- return count; \
-} \
-static DEVICE_ATTR(value, S_IWUGO | S_IRUGO | S_IWUSR, \
- show_bool_##value, set_bool_##value);
-
-show_set_bool(wireless, ACER_CAP_WIRELESS);
-show_set_bool(bluetooth, ACER_CAP_BLUETOOTH);
-show_set_bool(threeg, ACER_CAP_THREEG);
+ acpi_status status = get_u32(&result, ACER_CAP_THREEG);
+ if (ACPI_SUCCESS(status))
+ return sprintf(buf, "%u\n", result);
+ return sprintf(buf, "Read error\n");
+}
+
+static ssize_t set_bool_threeg(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ u32 tmp = simple_strtoul(buf, NULL, 10);
+ acpi_status status = set_u32(tmp, ACER_CAP_THREEG);
+ if (ACPI_FAILURE(status))
+ return -EINVAL;
+ return count;
+}
+static DEVICE_ATTR(threeg, S_IWUGO | S_IRUGO | S_IWUSR, show_bool_threeg,
+ set_bool_threeg);
-/*
- * Read interface sysfs macro
- */
static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -1180,16 +1160,6 @@ pm_message_t state)
if (!data)
return -ENOMEM;
- if (has_cap(ACER_CAP_WIRELESS)) {
- get_u32(&value, ACER_CAP_WIRELESS);
- data->wireless = value;
- }
-
- if (has_cap(ACER_CAP_BLUETOOTH)) {
- get_u32(&value, ACER_CAP_BLUETOOTH);
- data->bluetooth = value;
- }
-
if (has_cap(ACER_CAP_MAILLED)) {
get_u32(&value, ACER_CAP_MAILLED);
data->mailled = value;
@@ -1210,15 +1180,6 @@ static int acer_platform_resume(struct platform_device *device)
if (!data)
return -ENOMEM;
- if (has_cap(ACER_CAP_WIRELESS))
- set_u32(data->wireless, ACER_CAP_WIRELESS);
-
- if (has_cap(ACER_CAP_BLUETOOTH))
- set_u32(data->bluetooth, ACER_CAP_BLUETOOTH);
-
- if (has_cap(ACER_CAP_THREEG))
- set_u32(data->threeg, ACER_CAP_THREEG);
-
if (has_cap(ACER_CAP_MAILLED))
set_u32(data->mailled, ACER_CAP_MAILLED);
@@ -1243,12 +1204,6 @@ static struct platform_device *acer_platform_device;
static int remove_sysfs(struct platform_device *device)
{
- if (has_cap(ACER_CAP_WIRELESS))
- device_remove_file(&device->dev, &dev_attr_wireless);
-
- if (has_cap(ACER_CAP_BLUETOOTH))
- device_remove_file(&device->dev, &dev_attr_bluetooth);
-
if (has_cap(ACER_CAP_THREEG))
device_remove_file(&device->dev, &dev_attr_threeg);
@@ -1261,20 +1216,6 @@ static int create_sysfs(void)
{
int retval = -ENOMEM;
- if (has_cap(ACER_CAP_WIRELESS)) {
- retval = device_create_file(&acer_platform_device->dev,
- &dev_attr_wireless);
- if (retval)
- goto error_sysfs;
- }
-
- if (has_cap(ACER_CAP_BLUETOOTH)) {
- retval = device_create_file(&acer_platform_device->dev,
- &dev_attr_bluetooth);
- if (retval)
- goto error_sysfs;
- }
-
if (has_cap(ACER_CAP_THREEG)) {
retval = device_create_file(&acer_platform_device->dev,
&dev_attr_threeg);
--
1.5.5.1
From: Alexey Starikovskiy <[email protected]>
Signed-off-by: Alexey Starikovskiy <[email protected]>
CC: Hannes Reinecke <[email protected]>
Signed-off-by: Alexey Starikovskiy <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/scan.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index f6f52c1..e7b8853 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -384,7 +384,7 @@ static int acpi_device_remove(struct device * dev)
acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type);
}
acpi_dev->driver = NULL;
- acpi_driver_data(dev) = NULL;
+ acpi_driver_data(acpi_dev) = NULL;
put_device(dev);
return 0;
--
1.5.5.1
From: Yinghai Lu <[email protected]>
Signed-off-by: Yinghai Lu <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
index dd097b8..9943b4c 100644
--- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -779,6 +779,9 @@ static int __init acpi_cpufreq_init(void)
{
int ret;
+ if (acpi_disabled)
+ return 0;
+
dprintk("acpi_cpufreq_init\n");
ret = acpi_cpufreq_early_init();
--
1.5.5.1
From: Thomas Renninger <[email protected]>
Signed-off-by: Thomas Renninger <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/fan.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 2655bc1..393934e 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -327,8 +327,8 @@ static int acpi_fan_resume(struct acpi_device *device)
result = acpi_bus_get_power(device->handle, &power_state);
if (result) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error reading fan power state\n"));
+ printk(KERN_ERR "Error reading fan power state [%d]\n",
+ result);
return result;
}
--
1.5.5.1
From: Pavel Machek <[email protected]>
Catch attempts to use of acpi_driver_data on pointers of wrong type.
akpm: rewritten to use proper C typechecking and remove the
"function"-used-as-lvalue thing.
Signed-off-by: Pavel Machek <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/ac.c | 2 +-
drivers/acpi/acpi_memhotplug.c | 2 +-
drivers/acpi/asus_acpi.c | 2 +-
drivers/acpi/battery.c | 2 +-
drivers/acpi/button.c | 2 +-
drivers/acpi/container.c | 2 +-
drivers/acpi/ec.c | 4 ++--
drivers/acpi/fan.c | 2 +-
drivers/acpi/pci_link.c | 2 +-
drivers/acpi/pci_root.c | 2 +-
drivers/acpi/power.c | 4 ++--
drivers/acpi/processor_core.c | 2 +-
drivers/acpi/sbs.c | 2 +-
drivers/acpi/sbshc.c | 4 ++--
drivers/acpi/scan.c | 4 ++--
drivers/acpi/thermal.c | 2 +-
drivers/acpi/video.c | 6 +++---
drivers/misc/asus-laptop.c | 2 +-
drivers/misc/eeepc-laptop.c | 2 +-
drivers/misc/fujitsu-laptop.c | 4 ++--
drivers/misc/intel_menlow.c | 2 +-
drivers/misc/thinkpad_acpi.c | 2 +-
include/acpi/acpi_bus.h | 6 +++++-
23 files changed, 34 insertions(+), 30 deletions(-)
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 831883b..8b6a84a 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -269,7 +269,7 @@ static int acpi_ac_add(struct acpi_device *device)
ac->device = device;
strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_AC_CLASS);
- acpi_driver_data(device) = ac;
+ device->driver_data = ac;
result = acpi_ac_get_state(ac);
if (result)
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 5f1127a..afd955f 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -403,7 +403,7 @@ static int acpi_memory_device_add(struct acpi_device *device)
mem_device->device = device;
sprintf(acpi_device_name(device), "%s", ACPI_MEMORY_DEVICE_NAME);
sprintf(acpi_device_class(device), "%s", ACPI_MEMORY_DEVICE_CLASS);
- acpi_driver_data(device) = mem_device;
+ device->driver_data = mem_device;
/* Get the range from the _CRS */
result = acpi_memory_get_device_resources(mem_device);
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index d3d0886..91571fc 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -1321,7 +1321,7 @@ static int asus_hotk_add(struct acpi_device *device)
hotk->handle = device->handle;
strcpy(acpi_device_name(device), ACPI_HOTK_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_HOTK_CLASS);
- acpi_driver_data(device) = hotk;
+ device->driver_data = hotk;
hotk->device = device;
result = asus_hotk_check();
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index b1c723f..de80469 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -804,7 +804,7 @@ static int acpi_battery_add(struct acpi_device *device)
battery->device = device;
strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
- acpi_driver_data(device) = battery;
+ device->driver_data = battery;
mutex_init(&battery->lock);
acpi_battery_update(battery);
#ifdef CONFIG_ACPI_PROCFS_POWER
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 1dfec41..e22033e 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -384,7 +384,7 @@ static int acpi_button_add(struct acpi_device *device)
return -ENOMEM;
button->device = device;
- acpi_driver_data(device) = button;
+ device->driver_data = button;
button->input = input = input_allocate_device();
if (!input) {
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 3c25ec7..03ea847 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -108,7 +108,7 @@ static int acpi_container_add(struct acpi_device *device)
container->handle = device->handle;
strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
- acpi_driver_data(device) = container;
+ device->driver_data = container;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n",
acpi_device_name(device), acpi_device_bid(device)));
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 13593f9..5741d99 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -788,7 +788,7 @@ static int acpi_ec_add(struct acpi_device *device)
if (!first_ec)
first_ec = ec;
- acpi_driver_data(device) = ec;
+ device->driver_data = ec;
acpi_ec_add_fs(device);
pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
ec->gpe, ec->command_addr, ec->data_addr);
@@ -813,7 +813,7 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
}
mutex_unlock(&ec->lock);
acpi_ec_remove_fs(device);
- acpi_driver_data(device) = NULL;
+ device->driver_data = NULL;
if (ec == first_ec)
first_ec = NULL;
kfree(ec);
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 2655bc1..e603e40 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -265,7 +265,7 @@ static int acpi_fan_add(struct acpi_device *device)
dev_info(&device->dev, "registered as cooling_device%d\n", cdev->id);
- acpi_driver_data(device) = cdev;
+ device->driver_data = cdev;
result = sysfs_create_link(&device->dev.kobj,
&cdev->device.kobj,
"thermal_cooling");
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index cf47805..54cd77a 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -737,7 +737,7 @@ static int acpi_pci_link_add(struct acpi_device *device)
link->device = device;
strcpy(acpi_device_name(device), ACPI_PCI_LINK_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS);
- acpi_driver_data(device) = link;
+ device->driver_data = link;
mutex_lock(&acpi_link_lock);
result = acpi_pci_link_get_possible(link);
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index c3fed31..add1a19 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -206,7 +206,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
root->device = device;
strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
- acpi_driver_data(device) = root;
+ device->driver_data = root;
device->ops.bind = acpi_pci_bind;
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 4ab21cb..1bef942 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -657,7 +657,7 @@ static int acpi_power_add(struct acpi_device *device)
strcpy(resource->name, device->pnp.bus_id);
strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
- acpi_driver_data(device) = resource;
+ device->driver_data = resource;
/* Evalute the object to get the system level and resource order. */
status = acpi_evaluate_object(device->handle, NULL, NULL, &buffer);
@@ -733,7 +733,7 @@ static int acpi_power_resume(struct acpi_device *device)
if (!device || !acpi_driver_data(device))
return -EINVAL;
- resource = (struct acpi_power_resource *)acpi_driver_data(device);
+ resource = acpi_driver_data(device);
result = acpi_power_get_state(resource, &state);
if (result)
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index ee68ac5..2894616 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -818,7 +818,7 @@ static int acpi_processor_add(struct acpi_device *device)
pr->handle = device->handle;
strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
- acpi_driver_data(device) = pr;
+ device->driver_data = pr;
return 0;
}
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 10a3651..d003325 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -931,7 +931,7 @@ static int acpi_sbs_add(struct acpi_device *device)
sbs->device = device;
strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
- acpi_driver_data(device) = sbs;
+ device->driver_data = sbs;
result = acpi_charger_add(sbs);
if (result)
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index a4e3767..001d914 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -282,7 +282,7 @@ static int acpi_smbus_hc_add(struct acpi_device *device)
hc->ec = acpi_driver_data(device->parent);
hc->offset = (val >> 8) & 0xff;
hc->query_bit = val & 0xff;
- acpi_driver_data(device) = hc;
+ device->driver_data = hc;
acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc);
printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n",
@@ -303,7 +303,7 @@ static int acpi_smbus_hc_remove(struct acpi_device *device, int type)
hc = acpi_driver_data(device);
acpi_ec_remove_query_handler(hc->ec, hc->query_bit);
kfree(hc);
- acpi_driver_data(device) = NULL;
+ device->driver_data = NULL;
return 0;
}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index e7b8853..b88536a 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -384,7 +384,7 @@ static int acpi_device_remove(struct device * dev)
acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type);
}
acpi_dev->driver = NULL;
- acpi_driver_data(acpi_dev) = NULL;
+ acpi_dev->driver_data = NULL;
put_device(dev);
return 0;
@@ -537,7 +537,7 @@ acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver)
result = driver->ops.add(device);
if (result) {
device->driver = NULL;
- acpi_driver_data(device) = NULL;
+ device->driver_data = NULL;
return result;
}
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 9127036..e052a75 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -1647,7 +1647,7 @@ static int acpi_thermal_add(struct acpi_device *device)
strcpy(tz->name, device->pnp.bus_id);
strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
- acpi_driver_data(device) = tz;
+ device->driver_data = tz;
mutex_init(&tz->lock);
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index e8a51a1..85c6554 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -1491,7 +1491,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
- acpi_driver_data(device) = data;
+ device->driver_data = data;
data->device_id = device_id;
data->video = video;
@@ -1982,7 +1982,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
video->device = device;
strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
- acpi_driver_data(device) = video;
+ device->driver_data = video;
acpi_video_bus_find_cap(video);
error = acpi_video_bus_check(video);
@@ -2058,7 +2058,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
acpi_video_bus_remove_fs(device);
err_free_video:
kfree(video);
- acpi_driver_data(device) = NULL;
+ device->driver_data = NULL;
return error;
}
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c
index 7c6dfd0..de82f2f 100644
--- a/drivers/misc/asus-laptop.c
+++ b/drivers/misc/asus-laptop.c
@@ -996,7 +996,7 @@ static int asus_hotk_add(struct acpi_device *device)
hotk->handle = device->handle;
strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME);
strcpy(acpi_device_class(device), ASUS_HOTK_CLASS);
- acpi_driver_data(device) = hotk;
+ device->driver_data = hotk;
hotk->device = device;
result = asus_hotk_check();
diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c
index 1ee8501..c124705 100644
--- a/drivers/misc/eeepc-laptop.c
+++ b/drivers/misc/eeepc-laptop.c
@@ -411,7 +411,7 @@ static int eeepc_hotk_add(struct acpi_device *device)
ehotk->handle = device->handle;
strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);
strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS);
- acpi_driver_data(device) = ehotk;
+ device->driver_data = ehotk;
ehotk->device = device;
result = eeepc_hotk_check();
if (result)
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c
index 3e56203..7b69cfb 100644
--- a/drivers/misc/fujitsu-laptop.c
+++ b/drivers/misc/fujitsu-laptop.c
@@ -490,7 +490,7 @@ static int acpi_fujitsu_add(struct acpi_device *device)
fujitsu->acpi_handle = device->handle;
sprintf(acpi_device_name(device), "%s", ACPI_FUJITSU_DEVICE_NAME);
sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
- acpi_driver_data(device) = fujitsu;
+ device->driver_data = fujitsu;
status = acpi_install_notify_handler(device->handle,
ACPI_DEVICE_NOTIFY,
@@ -703,7 +703,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
sprintf(acpi_device_name(device), "%s",
ACPI_FUJITSU_HOTKEY_DEVICE_NAME);
sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
- acpi_driver_data(device) = fujitsu_hotkey;
+ device->driver_data = fujitsu_hotkey;
status = acpi_install_notify_handler(device->handle,
ACPI_DEVICE_NOTIFY,
diff --git a/drivers/misc/intel_menlow.c b/drivers/misc/intel_menlow.c
index 80a1363..cd3ea7f 100644
--- a/drivers/misc/intel_menlow.c
+++ b/drivers/misc/intel_menlow.c
@@ -175,7 +175,7 @@ static int intel_menlow_memory_add(struct acpi_device *device)
goto end;
}
- acpi_driver_data(device) = cdev;
+ device->driver_data = cdev;
result = sysfs_create_link(&device->dev.kobj,
&cdev->device.kobj, "thermal_cooling");
if (result)
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index 6b93007..62aebaa 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -543,7 +543,7 @@ static int __init setup_acpi_notify(struct ibm_struct *ibm)
return -ENODEV;
}
- acpi_driver_data(ibm->acpi->device) = ibm;
+ ibm->acpi->device->driver_data = ibm;
sprintf(acpi_device_class(ibm->acpi->device), "%s/%s",
TPACPI_ACPI_EVENT_PREFIX,
ibm->name);
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index a5ac0bc..4768246 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -300,7 +300,11 @@ struct acpi_device {
enum acpi_bus_removal_type removal_type; /* indicate for different removal type */
};
-#define acpi_driver_data(d) ((d)->driver_data)
+static inline void *acpi_driver_data(struct acpi_device *d)
+{
+ return d->driver_data;
+}
+
#define to_acpi_device(d) container_of(d, struct acpi_device, dev)
#define to_acpi_driver(d) container_of(d, struct acpi_driver, drv)
--
1.5.5.1
From: Bjorn Helgaas <[email protected]>
This adds the core function pnp_dbg() and a new config option to
enable it.
The PNP core debugging messages can be enabled at boot-time with the
"pnp.debug" kernel parameter.
Signed-off-by: Bjorn Helgaas <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
Documentation/kernel-parameters.txt | 4 ++++
drivers/pnp/Kconfig | 14 ++++++++++++++
drivers/pnp/base.h | 10 ++++++++++
drivers/pnp/core.c | 11 +++++++++++
4 files changed, 39 insertions(+), 0 deletions(-)
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 1150444..7164d4e 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1660,6 +1660,10 @@ and is between 256 and 4096 characters. It is defined in the file
Override pmtimer IOPort with a hex value.
e.g. pmtmr=0x508
+ pnp.debug [PNP]
+ Enable PNP debug messages. This depends on the
+ CONFIG_PNP_DEBUG_MESSAGES option.
+
pnpacpi= [ACPI]
{ off }
diff --git a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig
index 821933f..8a3237f 100644
--- a/drivers/pnp/Kconfig
+++ b/drivers/pnp/Kconfig
@@ -20,6 +20,20 @@ menuconfig PNP
If unsure, say Y.
+config PNP_DEBUG_MESSAGES
+ default y
+ bool "PNP debugging messages"
+ depends on PNP
+ help
+ Say Y here if you want the PNP layer to be able to produce debugging
+ messages if needed. The messages can be enabled at boot-time with
+ the pnp.debug kernel parameter.
+
+ This option allows you to save a bit of space if you do not want
+ the messages to even be built into the kernel.
+
+ If you have any doubts about this, say Y here.
+
if PNP
config PNP_DEBUG
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index 9fd7bb9..5e4e82c 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -166,3 +166,13 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
resource_size_t start,
resource_size_t end, int flags);
+
+extern int pnp_debug;
+
+#if defined(CONFIG_PNP_DEBUG_MESSAGES)
+#define pnp_dbg(dev, format, arg...) \
+ ({ if (pnp_debug) dev_printk(KERN_DEBUG, dev, format, ## arg); 0; })
+#else
+#define pnp_dbg(dev, format, arg...) \
+ ({ if (0) dev_printk(KERN_DEBUG, dev, format, ## arg); 0; })
+#endif
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index 7cb1ffc..61291b5 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -221,3 +221,14 @@ static int __init pnp_init(void)
}
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);
+#endif
--
1.5.5.1
From: Yinghai Lu <[email protected]>
This was a workaround for 32bit numa SRAT processing, and we removed those
workarounds, making 32 bit more like 64 bit. HAVE_ARCH_PARSE_SRAT is no
longer defined anywhere.
Signed-off-by: Yinghai Lu <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
include/linux/acpi.h | 8 --------
1 files changed, 0 insertions(+), 8 deletions(-)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 702f79d..fd6a452 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -94,18 +94,10 @@ int acpi_parse_mcfg (struct acpi_table_header *header);
void acpi_table_print_madt_entry (struct acpi_subtable_header *madt);
/* the following four functions are architecture-dependent */
-#ifdef CONFIG_HAVE_ARCH_PARSE_SRAT
-#define NR_NODE_MEMBLKS MAX_NUMNODES
-#define acpi_numa_slit_init(slit) do {} while (0)
-#define acpi_numa_processor_affinity_init(pa) do {} while (0)
-#define acpi_numa_memory_affinity_init(ma) do {} while (0)
-#define acpi_numa_arch_fixup() do {} while (0)
-#else
void acpi_numa_slit_init (struct acpi_table_slit *slit);
void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa);
void acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma);
void acpi_numa_arch_fixup(void);
-#endif
#ifdef CONFIG_ACPI_HOTPLUG_CPU
/* Arch dependent functions for cpu hotplug support */
--
1.5.5.1
From: Thomas Renninger <[email protected]>
Signed-off-by: Thomas Renninger <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/acpi/scan.c | 11 ++++++-----
1 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index f6f52c1..0d46347 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -113,16 +113,16 @@ static int acpi_bus_hot_remove_device(void *context)
if (acpi_bus_trim(device, 1)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Removing device failed\n"));
+ printk(KERN_ERR "Removing device [%s] failed\n",
+ acpi_device_bid(device));
return -1;
}
/* power off device */
status = acpi_evaluate_object(handle, "_PS3", NULL, NULL);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Power-off device failed\n"));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Power-off device failed"));
if (device->flags.lockable) {
arg_list.count = 1;
@@ -477,7 +477,8 @@ static int acpi_device_register(struct acpi_device *device,
result = acpi_device_setup_files(device);
if(result)
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error creating sysfs interface for device %s\n", device->dev.bus_id));
+ printk(KERN_ERR "Error creating sysfs interface for device"
+ " %s [%d]\n", device->dev.bus_id, result);
device->removal_type = ACPI_BUS_REMOVAL_NORMAL;
return 0;
--
1.5.5.1
Len,
* Len Brown <[email protected]> wrote:
> --- a/arch/x86/kernel/process_64.c
> +++ b/arch/x86/kernel/process_64.c
> @@ -62,6 +62,13 @@ void idle_notifier_register(struct notifier_block *n)
> {
> atomic_notifier_chain_register(&idle_notifier, n);
> }
> +EXPORT_SYMBOL_GPL(idle_notifier_register);
> +
> +void idle_notifier_unregister(struct notifier_block *n)
> +{
> + atomic_notifier_chain_unregister(&idle_notifier, n);
> +}
> +EXPORT_SYMBOL_GPL(idle_notifier_unregister);
hm, such x86 infrastructure changes should be submitted via the x86
tree, and you should at least have Cc:-ed the maintainers.
The thing is, we are _getting rid_ of the idle notifiers, not extending
them. The last thing we need is random opaque stuff getting called in
weird ordering when we enter/exit idle state. We want all that be
visible and have explicit, in-source-code ordering.
Ingo
Am Samstag, 11. Oktober 2008 schrieb Len Brown:
> From: Matthew Garrett <[email protected]>
>
> The leading other brand OS appears to clear the WAK_STS flag on resume.
> When rebooted, certain BIOSes assume that the system is actually
> resuming if it's still set and so fail to reboot correctly. Make sure
> that it's cleared at resume time.
>
> Comment clarified as suggested by Bob Moore
>
> Signed-off-by: Matthew Garrett <[email protected]>
> Signed-off-by: Andi Kleen <[email protected]>
> Signed-off-by: Len Brown <[email protected]>
This patch fixes reboot after suspend on my ASUS P5K.
Acked-by: Christian Borntraeger <[email protected]>
From: Len Brown <[email protected]>
sync with acpi_driver_data(device)
and acpi_evaluate_integer(..., long long)
changes that happened since this driver
was checked in.
Signed-off-by: Len Brown <[email protected]>
---
drivers/misc/panasonic-laptop.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/misc/panasonic-laptop.c b/drivers/misc/panasonic-laptop.c
index 9aecda5..a2cb598 100644
--- a/drivers/misc/panasonic-laptop.c
+++ b/drivers/misc/panasonic-laptop.c
@@ -252,7 +252,7 @@ static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val)
static inline int acpi_pcc_get_sqty(struct acpi_device *device)
{
- unsigned long s;
+ unsigned long long s;
acpi_status status;
ACPI_FUNCTION_TRACE("acpi_pcc_get_sqty");
@@ -500,7 +500,7 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
struct input_dev *hotk_input_dev = pcc->input_dev;
int rc;
int key_code, hkey_num;
- unsigned long result;
+ unsigned long long result;
ACPI_FUNCTION_TRACE("acpi_pcc_generate_keyinput");
@@ -645,7 +645,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
pcc->device = device;
pcc->handle = device->handle;
pcc->num_sifr = num_sifr;
- acpi_driver_data(device) = pcc;
+ device->driver_data = pcc;
strcpy(acpi_device_name(device), ACPI_PCC_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_PCC_CLASS);
--
1.5.5.1
From: Bjorn Helgaas <[email protected]>
Use the '%pF' format to get rid of an "#ifdef DEBUG".
Signed-off-by: Bjorn Helgaas <[email protected]>
Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
drivers/pnp/quirks.c | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 0bdf9b8..414bb09 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -337,10 +337,8 @@ void pnp_fixup_device(struct pnp_dev *dev)
for (f = pnp_fixups; *f->id; f++) {
if (!compare_pnp_id(dev->id, f->id))
continue;
-#ifdef DEBUG
- dev_dbg(&dev->dev, "%s: calling ", f->id);
- print_fn_descriptor_symbol("%s\n", f->quirk_function);
-#endif
+ dev_dbg(&dev->dev, "%s: calling %pF\n", f->id,
+ f->quirk_function);
f->quirk_function(dev);
}
}
--
1.5.5.1
> > --- a/arch/x86/kernel/process_64.c
> > +++ b/arch/x86/kernel/process_64.c
> > @@ -62,6 +62,13 @@ void idle_notifier_register(struct notifier_block *n)
> > {
> > atomic_notifier_chain_register(&idle_notifier, n);
> > }
> > +EXPORT_SYMBOL_GPL(idle_notifier_register);
> > +
> > +void idle_notifier_unregister(struct notifier_block *n)
> > +{
> > + atomic_notifier_chain_unregister(&idle_notifier, n);
> > +}
> > +EXPORT_SYMBOL_GPL(idle_notifier_unregister);
>
> hm, such x86 infrastructure changes should be submitted via the x86
> tree, and you should at least have Cc:-ed the maintainers.
I agree that this patch did not hit the list in the conventional way.
I apologize for that, and I thank you, Ingo, for noticing the patch.
> The thing is, we are _getting rid_ of the idle notifiers, not extending
> them. The last thing we need is random opaque stuff getting called in
> weird ordering when we enter/exit idle state. We want all that be
> visible and have explicit, in-source-code ordering.
The patch on the table is basically a platform (chipset) idle hook.
When the system is very idle, it saves energy in the memory sub-system.
Linux customers are asking for this capability b/c it allows them
to save energy and save money.
We considered putting a platform hook into the cpuidle code,
but it seemed simpler this way -- since the new platform hook
would end up looking almost exactly like the idle notifier
that we have already. So x86-wise, all we did here is
expose the register/unregister so the driver can be modular.
I'm certainly open to suggestions.
thanks,
-Len
From: Venkatesh Pallipadi <[email protected]>
needed if the i7300_idle driver is to be a module.
Signed-off-by: Venkatesh Pallipadi <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
arch/x86/kernel/process_64.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index e12e0e4..3e3d503 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -62,6 +62,13 @@ void idle_notifier_register(struct notifier_block *n)
{
atomic_notifier_chain_register(&idle_notifier, n);
}
+EXPORT_SYMBOL_GPL(idle_notifier_register);
+
+void idle_notifier_unregister(struct notifier_block *n)
+{
+ atomic_notifier_chain_unregister(&idle_notifier, n);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_unregister);
void enter_idle(void)
{
--
1.6.0.2.532.g84ed4c
From: Andy Henroid <[email protected]>
The Intel 7300 Memory Controller supports dynamic throttling of memory which can
be used to save power when system is idle. This driver does the memory
throttling when all CPUs are idle on such a system.
Refer to "Intel 7300 Memory Controller Hub (MCH)" datasheet
for the config space description.
Signed-off-by: Andy Henroid <[email protected]>
Signed-off-by: Len Brown <[email protected]>
Signed-off-by: Venkatesh Pallipadi <[email protected]>
---
MAINTAINERS | 6 +
arch/x86/Kconfig | 2 +
drivers/Makefile | 1 +
drivers/dma/ioat_dma.c | 3 +
drivers/idle/Kconfig | 16 +
drivers/idle/Makefile | 2 +
drivers/idle/i7300_idle.c | 674 +++++++++++++++++++++++++++++++++++++++++++++
include/asm-x86/idle.h | 1 +
include/linux/pci_ids.h | 1 +
9 files changed, 706 insertions(+), 0 deletions(-)
create mode 100644 drivers/idle/Kconfig
create mode 100644 drivers/idle/Makefile
create mode 100644 drivers/idle/i7300_idle.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 8dae455..43f71b0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2078,6 +2078,12 @@ L: [email protected]
L: [email protected]
S: Orphan
+IDLE-I7300
+P: Andy Henroid
+M: [email protected]
+L: [email protected]
+S: Supported
+
IEEE 1394 SUBSYSTEM (drivers/ieee1394)
P: Ben Collins
M: [email protected]
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ed92864..19cdfe1 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1536,6 +1536,8 @@ source "arch/x86/kernel/cpu/cpufreq/Kconfig"
source "drivers/cpuidle/Kconfig"
+source "drivers/idle/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 2735bde..f443a8a 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_EISA) += eisa/
obj-y += lguest/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_CPU_IDLE) += cpuidle/
+obj-y += idle/
obj-$(CONFIG_MMC) += mmc/
obj-$(CONFIG_MEMSTICK) += memstick/
obj-$(CONFIG_NEW_LEDS) += leds/
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
index bc8c6e3..f8396ca 100644
--- a/drivers/dma/ioat_dma.c
+++ b/drivers/dma/ioat_dma.c
@@ -171,6 +171,9 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET);
xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
+#if CONFIG_I7300_IDLE_IOAT_CHANNEL
+ device->common.chancnt--;
+#endif
for (i = 0; i < device->common.chancnt; i++) {
ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL);
if (!ioat_chan) {
diff --git a/drivers/idle/Kconfig b/drivers/idle/Kconfig
new file mode 100644
index 0000000..f5b26dd
--- /dev/null
+++ b/drivers/idle/Kconfig
@@ -0,0 +1,16 @@
+
+menu "Memory power savings"
+
+config I7300_IDLE_IOAT_CHANNEL
+ bool
+
+config I7300_IDLE
+ tristate "Intel chipset idle power saving driver"
+ select I7300_IDLE_IOAT_CHANNEL
+ depends on X86_64
+ help
+ Enable idle power savings with certain Intel server chipsets.
+ The chipset must have I/O AT support, such as the Intel 7300.
+ The power savings depends on the type and quantity of DRAM devices.
+
+endmenu
diff --git a/drivers/idle/Makefile b/drivers/idle/Makefile
new file mode 100644
index 0000000..5f68fc3
--- /dev/null
+++ b/drivers/idle/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_I7300_IDLE) += i7300_idle.o
+
diff --git a/drivers/idle/i7300_idle.c b/drivers/idle/i7300_idle.c
new file mode 100644
index 0000000..59d1bbc
--- /dev/null
+++ b/drivers/idle/i7300_idle.c
@@ -0,0 +1,674 @@
+/*
+ * (C) Copyright 2008 Intel Corporation
+ * Authors:
+ * Andy Henroid <[email protected]>
+ * Venkatesh Pallipadi <[email protected]>
+ */
+
+/*
+ * Save DIMM power on Intel 7300-based platforms when all CPUs/cores
+ * are idle, using the DIMM thermal throttling capability.
+ *
+ * This driver depends on the Intel integrated DMA controller (I/O AT).
+ * If the driver for I/O AT (drivers/dma/ioatdma*) is also enabled,
+ * this driver should work cooperatively.
+ */
+
+/* #define DEBUG */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/cpumask.h>
+#include <linux/ktime.h>
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/stop_machine.h>
+
+#include <asm/idle.h>
+
+#include "../dma/ioatdma_hw.h"
+#include "../dma/ioatdma_registers.h"
+
+#define I7300_IDLE_DRIVER_VERSION "1.55"
+#define I7300_PRINT "i7300_idle:"
+
+static int debug;
+module_param_named(debug, debug, uint, 0644);
+MODULE_PARM_DESC(debug, "Enable debug printks in this driver");
+
+#define dprintk(fmt, arg...) \
+ do { if (debug) printk(KERN_INFO I7300_PRINT fmt, ##arg); } while (0)
+
+/*
+ * Value to set THRTLOW to when initiating throttling
+ * 0 = No throttling
+ * 1 = Throttle when > 4 activations per eval window (Maximum throttling)
+ * 2 = Throttle when > 8 activations
+ * 168 = Throttle when > 168 activations (Minimum throttling)
+ */
+#define MAX_THRTLWLIMIT 168
+static uint i7300_idle_thrtlowlm = 1;
+module_param_named(thrtlwlimit, i7300_idle_thrtlowlm, uint, 0644);
+MODULE_PARM_DESC(thrtlwlimit,
+ "Value for THRTLOWLM activation field "
+ "(0 = disable throttle, 1 = Max throttle, 168 = Min throttle)");
+
+/*
+ * simple invocation and duration statistics
+ */
+static unsigned long total_starts;
+static unsigned long total_us;
+
+#ifdef DEBUG
+static unsigned long past_skip;
+#endif
+
+static struct pci_dev *fbd_dev;
+
+static spinlock_t i7300_idle_lock;
+static int i7300_idle_active;
+
+static u8 i7300_idle_thrtctl_saved;
+static u8 i7300_idle_thrtlow_saved;
+static u32 i7300_idle_mc_saved;
+
+static cpumask_t idle_cpumask;
+static ktime_t start_ktime;
+static unsigned long avg_idle_us;
+
+static struct dentry *debugfs_dir;
+
+/* Begin: I/O AT Helper routines */
+
+#define IOAT_CHANBASE(ioat_ctl, chan) (ioat_ctl + 0x80 + 0x80 * chan)
+/* Snoop control (disable snoops when coherency is not important) */
+#define IOAT_DESC_SADDR_SNP_CTL (1UL << 1)
+#define IOAT_DESC_DADDR_SNP_CTL (1UL << 2)
+
+static struct pci_dev *ioat_dev;
+static struct ioat_dma_descriptor *ioat_desc; /* I/O AT desc & data (1 page) */
+static unsigned long ioat_desc_phys;
+static u8 *ioat_iomap; /* I/O AT memory-mapped control regs (aka CB_BAR) */
+static u8 *ioat_chanbase;
+
+/* Start I/O AT memory copy */
+static int i7300_idle_ioat_start(void)
+{
+ u32 err;
+ /* Clear error (due to circular descriptor pointer) */
+ err = readl(ioat_chanbase + IOAT_CHANERR_OFFSET);
+ if (err)
+ writel(err, ioat_chanbase + IOAT_CHANERR_OFFSET);
+
+ writeb(IOAT_CHANCMD_START, ioat_chanbase + IOAT1_CHANCMD_OFFSET);
+ return 0;
+}
+
+/* Stop I/O AT memory copy */
+static void i7300_idle_ioat_stop(void)
+{
+ int i;
+ u8 sts;
+
+ for (i = 0; i < 5; i++) {
+ writeb(IOAT_CHANCMD_RESET,
+ ioat_chanbase + IOAT1_CHANCMD_OFFSET);
+
+ udelay(10);
+
+ sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
+ IOAT_CHANSTS_DMA_TRANSFER_STATUS;
+
+ if (sts != IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE)
+ break;
+
+ }
+
+ if (i == 5)
+ dprintk("failed to suspend+reset I/O AT after 5 retries\n");
+
+}
+
+/* Test I/O AT by copying 1024 byte from 2k to 1k */
+static int __init i7300_idle_ioat_selftest(u8 *ctl,
+ struct ioat_dma_descriptor *desc, unsigned long desc_phys)
+{
+ u64 chan_sts;
+
+ memset(desc, 0, 2048);
+ memset((u8 *) desc + 2048, 0xab, 1024);
+
+ desc[0].size = 1024;
+ desc[0].ctl = 0;
+ desc[0].src_addr = desc_phys + 2048;
+ desc[0].dst_addr = desc_phys + 1024;
+ desc[0].next = 0;
+
+ writeb(IOAT_CHANCMD_RESET, ioat_chanbase + IOAT1_CHANCMD_OFFSET);
+ writeb(IOAT_CHANCMD_START, ioat_chanbase + IOAT1_CHANCMD_OFFSET);
+
+ udelay(1000);
+
+ chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
+ IOAT_CHANSTS_DMA_TRANSFER_STATUS;
+
+ if (chan_sts != IOAT_CHANSTS_DMA_TRANSFER_STATUS_DONE) {
+ /* Not complete, reset the channel */
+ writeb(IOAT_CHANCMD_RESET,
+ ioat_chanbase + IOAT1_CHANCMD_OFFSET);
+ return -1;
+ }
+
+ if (*(u32 *) ((u8 *) desc + 3068) != 0xabababab ||
+ *(u32 *) ((u8 *) desc + 2044) != 0xabababab) {
+ dprintk("Data values src 0x%x, dest 0x%x, memset 0x%x\n",
+ *(u32 *) ((u8 *) desc + 2048),
+ *(u32 *) ((u8 *) desc + 1024),
+ *(u32 *) ((u8 *) desc + 3072));
+ return -1;
+ }
+ return 0;
+}
+
+static struct device dummy_dma_dev = {
+ .bus_id = "fallback device",
+ .coherent_dma_mask = DMA_64BIT_MASK,
+ .dma_mask = &dummy_dma_dev.coherent_dma_mask,
+};
+
+/* Setup and initialize I/O AT */
+/* This driver needs I/O AT as the throttling takes effect only when there is
+ * some memory activity. We use I/O AT to set up a dummy copy, while all CPUs
+ * go idle and memory is throttled.
+ */
+static int __init i7300_idle_ioat_init(void)
+{
+ u8 ver, chan_count, ioat_chan;
+ u16 chan_ctl;
+
+ ioat_iomap = (u8 *) ioremap_nocache(pci_resource_start(ioat_dev, 0),
+ pci_resource_len(ioat_dev, 0));
+
+ if (!ioat_iomap) {
+ printk(KERN_ERR I7300_PRINT "failed to map I/O AT registers\n");
+ goto err_ret;
+ }
+
+ ver = readb(ioat_iomap + IOAT_VER_OFFSET);
+ if (ver != IOAT_VER_1_2) {
+ printk(KERN_ERR I7300_PRINT "unknown I/O AT version (%u.%u)\n",
+ ver >> 4, ver & 0xf);
+ goto err_unmap;
+ }
+
+ chan_count = readb(ioat_iomap + IOAT_CHANCNT_OFFSET);
+ if (!chan_count) {
+ printk(KERN_ERR I7300_PRINT "unexpected # of I/O AT channels "
+ "(%u)\n",
+ chan_count);
+ goto err_unmap;
+ }
+
+ ioat_chan = chan_count - 1;
+ ioat_chanbase = IOAT_CHANBASE(ioat_iomap, ioat_chan);
+
+ chan_ctl = readw(ioat_chanbase + IOAT_CHANCTRL_OFFSET);
+ if (chan_ctl & IOAT_CHANCTRL_CHANNEL_IN_USE) {
+ printk(KERN_ERR I7300_PRINT "channel %d in use\n", ioat_chan);
+ goto err_unmap;
+ }
+
+ writew(IOAT_CHANCTRL_CHANNEL_IN_USE,
+ ioat_chanbase + IOAT_CHANCTRL_OFFSET);
+
+ ioat_desc = (struct ioat_dma_descriptor *)dma_alloc_coherent(
+ &dummy_dma_dev, 4096,
+ (dma_addr_t *)&ioat_desc_phys, GFP_KERNEL);
+ if (!ioat_desc) {
+ printk(KERN_ERR I7300_PRINT "failed to allocate I/O AT desc\n");
+ goto err_mark_unused;
+ }
+
+ writel(ioat_desc_phys & 0xffffffffUL,
+ ioat_chanbase + IOAT1_CHAINADDR_OFFSET_LOW);
+ writel(ioat_desc_phys >> 32,
+ ioat_chanbase + IOAT1_CHAINADDR_OFFSET_HIGH);
+
+ if (i7300_idle_ioat_selftest(ioat_iomap, ioat_desc, ioat_desc_phys)) {
+ printk(KERN_ERR I7300_PRINT "I/O AT self-test failed\n");
+ goto err_free;
+ }
+
+ /* Setup circular I/O AT descriptor chain */
+ ioat_desc[0].ctl = IOAT_DESC_SADDR_SNP_CTL | IOAT_DESC_DADDR_SNP_CTL;
+ ioat_desc[0].src_addr = ioat_desc_phys + 2048;
+ ioat_desc[0].dst_addr = ioat_desc_phys + 3072;
+ ioat_desc[0].size = 128;
+ ioat_desc[0].next = ioat_desc_phys + sizeof(struct ioat_dma_descriptor);
+
+ ioat_desc[1].ctl = ioat_desc[0].ctl;
+ ioat_desc[1].src_addr = ioat_desc[0].src_addr;
+ ioat_desc[1].dst_addr = ioat_desc[0].dst_addr;
+ ioat_desc[1].size = ioat_desc[0].size;
+ ioat_desc[1].next = ioat_desc_phys;
+
+ return 0;
+
+err_free:
+ dma_free_coherent(&dummy_dma_dev, 4096, (void *)ioat_desc, 0);
+err_mark_unused:
+ writew(0, ioat_chanbase + IOAT_CHANCTRL_OFFSET);
+err_unmap:
+ iounmap(ioat_iomap);
+err_ret:
+ return -ENODEV;
+}
+
+/* Cleanup I/O AT */
+static void __exit i7300_idle_ioat_exit(void)
+{
+ int i;
+ u64 chan_sts;
+
+ i7300_idle_ioat_stop();
+
+ /* Wait for a while for the channel to halt before releasing */
+ for (i = 0; i < 10; i++) {
+ writeb(IOAT_CHANCMD_RESET,
+ ioat_chanbase + IOAT1_CHANCMD_OFFSET);
+
+ chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
+ IOAT_CHANSTS_DMA_TRANSFER_STATUS;
+
+ if (chan_sts != IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE) {
+ writew(0, ioat_chanbase + IOAT_CHANCTRL_OFFSET);
+ break;
+ }
+ udelay(1000);
+ }
+
+ chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
+ IOAT_CHANSTS_DMA_TRANSFER_STATUS;
+
+ /*
+ * We tried to reset multiple times. If IO A/T channel is still active
+ * flag an error and return without cleanup. Memory leak is better
+ * than random corruption in that extreme error situation.
+ */
+ if (chan_sts == IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE) {
+ printk(KERN_ERR I7300_PRINT "Unable to stop IO A/T channels."
+ " Not freeing resources\n");
+ return;
+ }
+
+ dma_free_coherent(&dummy_dma_dev, 4096, (void *)ioat_desc, 0);
+ iounmap(ioat_iomap);
+}
+
+/* End: I/O AT Helper routines */
+
+#define DIMM_THRTLOW 0x64
+#define DIMM_THRTCTL 0x67
+#define DIMM_THRTCTL_THRMHUNT (1UL << 0)
+#define DIMM_MC 0x40
+#define DIMM_GTW_MODE (1UL << 17)
+#define DIMM_GBLACT 0x60
+
+/*
+ * Keep track of an exponential-decaying average of recent idle durations.
+ * The latest duration gets DURATION_WEIGHT_PCT percentage weight
+ * in this average, with the old average getting the remaining weight.
+ *
+ * High weights emphasize recent history, low weights include long history.
+ */
+#define DURATION_WEIGHT_PCT 55
+
+/*
+ * When the decaying average of recent durations or the predicted duration
+ * of the next timer interrupt is shorter than duration_threshold, the
+ * driver will decline to throttle.
+ */
+#define DURATION_THRESHOLD_US 100
+
+
+/* Store DIMM thermal throttle configuration */
+static int i7300_idle_thrt_save(void)
+{
+ u32 new_mc_val;
+ u8 gblactlm;
+
+ pci_read_config_byte(fbd_dev, DIMM_THRTCTL, &i7300_idle_thrtctl_saved);
+ pci_read_config_byte(fbd_dev, DIMM_THRTLOW, &i7300_idle_thrtlow_saved);
+ pci_read_config_dword(fbd_dev, DIMM_MC, &i7300_idle_mc_saved);
+ /*
+ * Make sure we have Global Throttling Window Mode set to have a
+ * "short" window. This (mostly) works around an issue where
+ * throttling persists until the end of the global throttling window
+ * size. On the tested system, this was resulting in a maximum of
+ * 64 ms to exit throttling (average 32 ms). The actual numbers
+ * depends on system frequencies. Setting the short window reduces
+ * this by a factor of 4096.
+ *
+ * We will only do this only if the system is set for
+ * unlimited-activations while in open-loop throttling (i.e., when
+ * Global Activation Throttle Limit is zero).
+ */
+ pci_read_config_byte(fbd_dev, DIMM_GBLACT, &gblactlm);
+ dprintk("thrtctl_saved = 0x%02x, thrtlow_saved = 0x%02x\n",
+ i7300_idle_thrtctl_saved,
+ i7300_idle_thrtlow_saved);
+ dprintk("mc_saved = 0x%08x, gblactlm = 0x%02x\n",
+ i7300_idle_mc_saved,
+ gblactlm);
+ if (gblactlm == 0) {
+ new_mc_val = i7300_idle_mc_saved | DIMM_GTW_MODE;
+ pci_write_config_dword(fbd_dev, DIMM_MC, new_mc_val);
+ return 0;
+ } else {
+ dprintk("could not set GTW_MODE = 1 (OLTT enabled)\n");
+ return -ENODEV;
+ }
+}
+
+/* Restore DIMM thermal throttle configuration */
+static void i7300_idle_thrt_restore(void)
+{
+ pci_write_config_dword(fbd_dev, DIMM_MC, i7300_idle_mc_saved);
+ pci_write_config_byte(fbd_dev, DIMM_THRTLOW, i7300_idle_thrtlow_saved);
+ pci_write_config_byte(fbd_dev, DIMM_THRTCTL, i7300_idle_thrtctl_saved);
+}
+
+/* Enable DIMM thermal throttling */
+static void i7300_idle_start(void)
+{
+ u8 new_ctl;
+ u8 limit;
+
+ new_ctl = i7300_idle_thrtctl_saved & ~DIMM_THRTCTL_THRMHUNT;
+ pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl);
+
+ limit = i7300_idle_thrtlowlm;
+ if (unlikely(limit > MAX_THRTLWLIMIT))
+ limit = MAX_THRTLWLIMIT;
+
+ pci_write_config_byte(fbd_dev, DIMM_THRTLOW, limit);
+
+ new_ctl = i7300_idle_thrtctl_saved | DIMM_THRTCTL_THRMHUNT;
+ pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl);
+}
+
+/* Disable DIMM thermal throttling */
+static void i7300_idle_stop(void)
+{
+ u8 new_ctl;
+ u8 got_ctl;
+
+ new_ctl = i7300_idle_thrtctl_saved & ~DIMM_THRTCTL_THRMHUNT;
+ pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl);
+
+ pci_write_config_byte(fbd_dev, DIMM_THRTLOW, i7300_idle_thrtlow_saved);
+ pci_write_config_byte(fbd_dev, DIMM_THRTCTL, i7300_idle_thrtctl_saved);
+ pci_read_config_byte(fbd_dev, DIMM_THRTCTL, &got_ctl);
+ WARN_ON_ONCE(got_ctl != i7300_idle_thrtctl_saved);
+}
+
+
+/*
+ * i7300_avg_duration_check()
+ * return 0 if the decaying average of recent idle durations is
+ * more than DURATION_THRESHOLD_US
+ */
+static int i7300_avg_duration_check(void)
+{
+ if (avg_idle_us >= DURATION_THRESHOLD_US)
+ return 0;
+
+#ifdef DEBUG
+ past_skip++;
+#endif
+ return 1;
+}
+
+/* Idle notifier to look at idle CPUs */
+static int i7300_idle_notifier(struct notifier_block *nb, unsigned long val,
+ void *data)
+{
+ unsigned long flags;
+ ktime_t now_ktime;
+ static ktime_t idle_begin_time;
+ static int time_init = 1;
+
+ if (!i7300_idle_thrtlowlm)
+ return 0;
+
+ if (unlikely(time_init)) {
+ time_init = 0;
+ idle_begin_time = ktime_get();
+ }
+
+ spin_lock_irqsave(&i7300_idle_lock, flags);
+ if (val == IDLE_START) {
+
+ cpu_set(smp_processor_id(), idle_cpumask);
+
+ if (cpus_weight(idle_cpumask) != num_online_cpus())
+ goto end;
+
+ now_ktime = ktime_get();
+ idle_begin_time = now_ktime;
+
+ if (i7300_avg_duration_check())
+ goto end;
+
+ i7300_idle_active = 1;
+ total_starts++;
+ start_ktime = now_ktime;
+
+ i7300_idle_start();
+ i7300_idle_ioat_start();
+
+ } else if (val == IDLE_END) {
+ cpu_clear(smp_processor_id(), idle_cpumask);
+ if (cpus_weight(idle_cpumask) == (num_online_cpus() - 1)) {
+ /* First CPU coming out of idle */
+ u64 idle_duration_us;
+
+ now_ktime = ktime_get();
+
+ idle_duration_us = ktime_to_us(ktime_sub
+ (now_ktime, idle_begin_time));
+
+ avg_idle_us =
+ ((100 - DURATION_WEIGHT_PCT) * avg_idle_us +
+ DURATION_WEIGHT_PCT * idle_duration_us) / 100;
+
+ if (i7300_idle_active) {
+ ktime_t idle_ktime;
+
+ idle_ktime = ktime_sub(now_ktime, start_ktime);
+ total_us += ktime_to_us(idle_ktime);
+
+ i7300_idle_ioat_stop();
+ i7300_idle_stop();
+ i7300_idle_active = 0;
+ }
+ }
+ }
+end:
+ spin_unlock_irqrestore(&i7300_idle_lock, flags);
+ return 0;
+}
+
+static struct notifier_block i7300_idle_nb = {
+ .notifier_call = i7300_idle_notifier,
+};
+
+/*
+ * I/O AT controls (PCI bus 0 device 8 function 0)
+ * DIMM controls (PCI bus 0 device 16 function 1)
+ */
+#define IOAT_BUS 0
+#define IOAT_DEVFN PCI_DEVFN(8, 0)
+#define MEMCTL_BUS 0
+#define MEMCTL_DEVFN PCI_DEVFN(16, 1)
+
+struct fbd_ioat {
+ unsigned int vendor;
+ unsigned int ioat_dev;
+};
+
+/*
+ * The i5000 chip-set has the same hooks as the i7300
+ * but support is disabled by default because this driver
+ * has not been validated on that platform.
+ */
+#define SUPPORT_I5000 0
+
+static const struct fbd_ioat fbd_ioat_list[] = {
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB},
+#if SUPPORT_I5000
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT},
+#endif
+ {0, 0}
+};
+
+/* table of devices that work with this driver */
+static const struct pci_device_id pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FBD_CNB) },
+#if SUPPORT_I5000
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) },
+#endif
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(pci, pci_tbl);
+
+/* Check for known platforms with I/O-AT */
+static int __init i7300_idle_platform_probe(void)
+{
+ int i;
+
+ fbd_dev = pci_get_bus_and_slot(MEMCTL_BUS, MEMCTL_DEVFN);
+ if (!fbd_dev)
+ return -ENODEV;
+
+ for (i = 0; pci_tbl[i].vendor != 0; i++) {
+ if (fbd_dev->vendor == pci_tbl[i].vendor &&
+ fbd_dev->device == pci_tbl[i].device) {
+ break;
+ }
+ }
+ if (pci_tbl[i].vendor == 0)
+ return -ENODEV;
+
+ ioat_dev = pci_get_bus_and_slot(IOAT_BUS, IOAT_DEVFN);
+ if (!ioat_dev)
+ return -ENODEV;
+
+ for (i = 0; fbd_ioat_list[i].vendor != 0; i++) {
+ if (ioat_dev->vendor == fbd_ioat_list[i].vendor &&
+ ioat_dev->device == fbd_ioat_list[i].ioat_dev) {
+ return 0;
+ }
+ }
+ return -ENODEV;
+}
+
+int stats_open_generic(struct inode *inode, struct file *fp)
+{
+ fp->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t stats_read_ul(struct file *fp, char __user *ubuf, size_t count,
+ loff_t *off)
+{
+ unsigned long *p = fp->private_data;
+ char buf[32];
+ int len;
+
+ len = snprintf(buf, 32, "%lu\n", *p);
+ return simple_read_from_buffer(ubuf, count, off, buf, len);
+}
+
+static const struct file_operations idle_fops = {
+ .open = stats_open_generic,
+ .read = stats_read_ul,
+};
+
+struct debugfs_file_info {
+ void *ptr;
+ char name[32];
+ struct dentry *file;
+} debugfs_file_list[] = {
+ {&total_starts, "total_starts", NULL},
+ {&total_us, "total_us", NULL},
+#ifdef DEBUG
+ {&past_skip, "past_skip", NULL},
+#endif
+ {NULL, "", NULL}
+ };
+
+static int __init i7300_idle_init(void)
+{
+ spin_lock_init(&i7300_idle_lock);
+ cpus_clear(idle_cpumask);
+ total_us = 0;
+
+ if (i7300_idle_platform_probe())
+ return -ENODEV;
+
+ if (i7300_idle_thrt_save())
+ return -ENODEV;
+
+ if (i7300_idle_ioat_init())
+ return -ENODEV;
+
+ debugfs_dir = debugfs_create_dir("i7300_idle", NULL);
+ if (debugfs_dir) {
+ int i = 0;
+
+ while (debugfs_file_list[i].ptr != NULL) {
+ debugfs_file_list[i].file = debugfs_create_file(
+ debugfs_file_list[i].name,
+ S_IRUSR,
+ debugfs_dir,
+ debugfs_file_list[i].ptr,
+ &idle_fops);
+ i++;
+ }
+ }
+
+ idle_notifier_register(&i7300_idle_nb);
+
+ printk(KERN_INFO "i7300_idle: loaded v%s\n", I7300_IDLE_DRIVER_VERSION);
+ return 0;
+}
+
+static void __exit i7300_idle_exit(void)
+{
+ idle_notifier_unregister(&i7300_idle_nb);
+
+ if (debugfs_dir) {
+ int i = 0;
+
+ while (debugfs_file_list[i].file != NULL) {
+ debugfs_remove(debugfs_file_list[i].file);
+ i++;
+ }
+
+ debugfs_remove(debugfs_dir);
+ }
+ i7300_idle_thrt_restore();
+ i7300_idle_ioat_exit();
+}
+
+module_init(i7300_idle_init);
+module_exit(i7300_idle_exit);
+
+MODULE_AUTHOR("Andy Henroid <[email protected]>");
+MODULE_DESCRIPTION("Intel Chipset DIMM Idle Power Saving Driver v"
+ I7300_IDLE_DRIVER_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/include/asm-x86/idle.h b/include/asm-x86/idle.h
index cbb6491..54ce018 100644
--- a/include/asm-x86/idle.h
+++ b/include/asm-x86/idle.h
@@ -6,6 +6,7 @@
struct notifier_block;
void idle_notifier_register(struct notifier_block *n);
+void idle_notifier_unregister(struct notifier_block *n);
void enter_idle(void);
void exit_idle(void);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index f1624b3..efb786d 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2422,6 +2422,7 @@
#define PCI_DEVICE_ID_INTEL_MCH_PC1 0x359a
#define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e
#define PCI_DEVICE_ID_INTEL_IOAT_CNB 0x360b
+#define PCI_DEVICE_ID_INTEL_FBD_CNB 0x360c
#define PCI_DEVICE_ID_INTEL_ICH10_0 0x3a14
#define PCI_DEVICE_ID_INTEL_ICH10_1 0x3a16
#define PCI_DEVICE_ID_INTEL_ICH10_2 0x3a18
--
1.6.0.2.532.g84ed4c
On Thu, 16 Oct 2008 18:08:01 -0400 (EDT) Len Brown wrote:
> From: Andy Henroid <[email protected]>
>
> The Intel 7300 Memory Controller supports dynamic throttling of memory which can
> be used to save power when system is idle. This driver does the memory
> throttling when all CPUs are idle on such a system.
>
> Refer to "Intel 7300 Memory Controller Hub (MCH)" datasheet
> for the config space description.
>
> Signed-off-by: Andy Henroid <[email protected]>
> Signed-off-by: Len Brown <[email protected]>
> Signed-off-by: Venkatesh Pallipadi <[email protected]>
> ---
> MAINTAINERS | 6 +
> arch/x86/Kconfig | 2 +
> drivers/Makefile | 1 +
> drivers/dma/ioat_dma.c | 3 +
> drivers/idle/Kconfig | 16 +
> drivers/idle/Makefile | 2 +
> drivers/idle/i7300_idle.c | 674 +++++++++++++++++++++++++++++++++++++++++++++
Why not just use drivers/power/ instead of a new sub-directory?
> include/asm-x86/idle.h | 1 +
> include/linux/pci_ids.h | 1 +
> 9 files changed, 706 insertions(+), 0 deletions(-)
> create mode 100644 drivers/idle/Kconfig
> create mode 100644 drivers/idle/Makefile
> create mode 100644 drivers/idle/i7300_idle.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 8dae455..43f71b0 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2078,6 +2078,12 @@ L: [email protected]
> L: [email protected]
> S: Orphan
>
> +IDLE-I7300
> +P: Andy Henroid
> +M: [email protected]
welcome back.
> +L: [email protected]
> +S: Supported
> +
> IEEE 1394 SUBSYSTEM (drivers/ieee1394)
> P: Ben Collins
> M: [email protected]
> diff --git a/drivers/idle/i7300_idle.c b/drivers/idle/i7300_idle.c
> new file mode 100644
> index 0000000..59d1bbc
> --- /dev/null
> +++ b/drivers/idle/i7300_idle.c
> @@ -0,0 +1,674 @@
> +/*
> + * (C) Copyright 2008 Intel Corporation
> + * Authors:
> + * Andy Henroid <[email protected]>
> + * Venkatesh Pallipadi <[email protected]>
> + */
> +
> +
> +/*
> + * Value to set THRTLOW to when initiating throttling
> + * 0 = No throttling
> + * 1 = Throttle when > 4 activations per eval window (Maximum throttling)
> + * 2 = Throttle when > 8 activations
> + * 168 = Throttle when > 168 activations (Minimum throttling)
Why do some numbers mean > their value (i.e., 168) but others don't?
Is it a linear value or logarithmic or what?
> + */
> +#define MAX_THRTLWLIMIT 168
> +static uint i7300_idle_thrtlowlm = 1;
> +module_param_named(thrtlwlimit, i7300_idle_thrtlowlm, uint, 0644);
> +MODULE_PARM_DESC(thrtlwlimit,
> + "Value for THRTLOWLM activation field "
> + "(0 = disable throttle, 1 = Max throttle, 168 = Min throttle)");
> +
> +/* Stop I/O AT memory copy */
> +static void i7300_idle_ioat_stop(void)
> +{
> + int i;
> + u8 sts;
> +
> + for (i = 0; i < 5; i++) {
> + writeb(IOAT_CHANCMD_RESET,
> + ioat_chanbase + IOAT1_CHANCMD_OFFSET);
> +
> + udelay(10);
> +
> + sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
> + IOAT_CHANSTS_DMA_TRANSFER_STATUS;
readq() returns 64 bits. You only want to LS-byte of it here?
> + if (sts != IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE)
> + break;
> +
> + }
> +
> + if (i == 5)
> + dprintk("failed to suspend+reset I/O AT after 5 retries\n");
> +
> +}
> +struct debugfs_file_info {
> + void *ptr;
> + char name[32];
> + struct dentry *file;
> +} debugfs_file_list[] = {
> + {&total_starts, "total_starts", NULL},
> + {&total_us, "total_us", NULL},
> +#ifdef DEBUG
> + {&past_skip, "past_skip", NULL},
> +#endif
> + {NULL, "", NULL}
> + };
What is debugfs used for? any docs for it?
Does this build/work if CONFIG_DEBUG_FS=n?
> +static int __init i7300_idle_init(void)
> +{
> + spin_lock_init(&i7300_idle_lock);
> + cpus_clear(idle_cpumask);
> + total_us = 0;
> +
> + if (i7300_idle_platform_probe())
> + return -ENODEV;
> +
> + if (i7300_idle_thrt_save())
> + return -ENODEV;
> +
> + if (i7300_idle_ioat_init())
> + return -ENODEV;
> +
> + debugfs_dir = debugfs_create_dir("i7300_idle", NULL);
> + if (debugfs_dir) {
> + int i = 0;
> +
> + while (debugfs_file_list[i].ptr != NULL) {
> + debugfs_file_list[i].file = debugfs_create_file(
> + debugfs_file_list[i].name,
> + S_IRUSR,
> + debugfs_dir,
> + debugfs_file_list[i].ptr,
> + &idle_fops);
> + i++;
> + }
> + }
> +
> + idle_notifier_register(&i7300_idle_nb);
> +
> + printk(KERN_INFO "i7300_idle: loaded v%s\n", I7300_IDLE_DRIVER_VERSION);
> + return 0;
> +}
---
~Randy
Ingo,
How shall we proceed?
If you take this patch, we can ship a modular i7300_idle driver.
If you do not take this patch, then we'll need to build it into
the kernel and not allow it to un-register.
thanks,
-Len
On Thu, 16 Oct 2008, Len Brown wrote:
> From: Venkatesh Pallipadi <[email protected]>
>
> needed if the i7300_idle driver is to be a module.
>
> Signed-off-by: Venkatesh Pallipadi <[email protected]>
> Signed-off-by: Len Brown <[email protected]>
> ---
> arch/x86/kernel/process_64.c | 7 +++++++
> 1 files changed, 7 insertions(+), 0 deletions(-)
>
> diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
> index e12e0e4..3e3d503 100644
> --- a/arch/x86/kernel/process_64.c
> +++ b/arch/x86/kernel/process_64.c
> @@ -62,6 +62,13 @@ void idle_notifier_register(struct notifier_block *n)
> {
> atomic_notifier_chain_register(&idle_notifier, n);
> }
> +EXPORT_SYMBOL_GPL(idle_notifier_register);
> +
> +void idle_notifier_unregister(struct notifier_block *n)
> +{
> + atomic_notifier_chain_unregister(&idle_notifier, n);
> +}
> +EXPORT_SYMBOL_GPL(idle_notifier_unregister);
>
> void enter_idle(void)
> {
> --
> 1.6.0.2.532.g84ed4c
>
>
* Len Brown <[email protected]> wrote:
> Ingo,
> How shall we proceed?
> If you take this patch, we can ship a modular i7300_idle driver.
> If you do not take this patch, then we'll need to build it into
> the kernel and not allow it to un-register.
sorry - i got held up with other stuff.
Please just commit the export via your tree, we'll sort it out
afterwards. Your use of the idle callback certainly looks reasonable for
your purposes and the infrastructure was there after all. I dont want to
complicate your workflow in any case.
Acked-by: Ingo Molnar <[email protected]>
Ingo
Len Brown wrote:
> diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
> index bc8c6e3..f8396ca 100644
> --- a/drivers/dma/ioat_dma.c
> +++ b/drivers/dma/ioat_dma.c
> @@ -171,6 +171,9 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
> xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET);
> xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
>
> +#if CONFIG_I7300_IDLE_IOAT_CHANNEL
> + device->common.chancnt--;
> +#endif
I still think this lone decrement looks fishy. Can there please be some
explanation how it exactly relates to the i7300 idle driver, where the
matching increment is, etc.?
> +config I7300_IDLE
> + tristate "Intel chipset idle power saving driver"
It would be probably good to mention the word memory here.
> + select I7300_IDLE_IOAT_CHANNEL
> + depends on X86_64
> + help
> + Enable idle power savings with certain Intel server chipsets.
And here too.
> + The chipset must have I/O AT support, such as the Intel 7300.
> + The power savings depends on the type and quantity of DRAM devices.
> +static int debug;
> +module_param_named(debug, debug, uint, 0644);
> +MODULE_PARM_DESC(debug, "Enable debug printks in this driver");
> +#define dprintk(fmt, arg...) \
> + do { if (debug) printk(KERN_INFO I7300_PRINT fmt, ##arg); } while (0)
2.6.28 just got a new dynamic printk facility, which could be used.
> +
> +/*
> + * Value to set THRTLOW to when initiating throttling
> + * 0 = No throttling
> + * 1 = Throttle when > 4 activations per eval window (Maximum throttling)
> + * 2 = Throttle when > 8 activations
> + * 168 = Throttle when > 168 activations (Minimum throttling)
> + */
> +#define MAX_THRTLWLIMIT 168
> +static uint i7300_idle_thrtlowlm = 1;
> +module_param_named(thrtlwlimit, i7300_idle_thrtlowlm, uint, 0644);
Just imagining how someone would pronounce this parameter @) Will they
get damages when their tongue ends up in a knot?
> +static cpumask_t idle_cpumask;
Would it make sense to cache align this field? I could imagine
it false sharing with some frequently written variable could be quite
bad.
> + writeb(IOAT_CHANCMD_RESET, ioat_chanbase + IOAT1_CHANCMD_OFFSET);
> + writeb(IOAT_CHANCMD_START, ioat_chanbase + IOAT1_CHANCMD_OFFSET);
> +
> + udelay(1000);
> +
> + chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
> + IOAT_CHANSTS_DMA_TRANSFER_STATUS;
Wouldn't it be better to poll here instead of udelay?
> + /* Wait for a while for the channel to halt before releasing */
> + for (i = 0; i < 10; i++) {
> + writeb(IOAT_CHANCMD_RESET,
> + ioat_chanbase + IOAT1_CHANCMD_OFFSET);
> +
> + chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
> + IOAT_CHANSTS_DMA_TRANSFER_STATUS;
> +
> + if (chan_sts != IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE) {
> + writew(0, ioat_chanbase + IOAT_CHANCTRL_OFFSET);
> + break;
> + }
> + udelay(1000);
Same here.
> + spin_lock_irqsave(&i7300_idle_lock, flags);
This lock still scares me. In the worst case with very frequent
idle frequencies this could bounce around a lot.
It would be better to only invoke it less frequently,
i.e. when the driver determines there is a long idle
time coming up.
> +/* Check for known platforms with I/O-AT */
> +static int __init i7300_idle_platform_probe(void)
> +{
> + int i;
> +
> + fbd_dev = pci_get_bus_and_slot(MEMCTL_BUS, MEMCTL_DEVFN)
Is there a specific reason you cannot match this by pci vendor/devid
like all standard drivers do?
If there is a good reason add a comment.
;
> +static void __exit i7300_idle_exit(void)
> +{
> + idle_notifier_unregister(&i7300_idle_nb);
I still think this needs some kind of idle synchronization.
-Andi
Thanks for the review. Some comments below.
Thanks,
Venki
>-----Original Message-----
>From: Randy Dunlap [mailto:[email protected]]
>Sent: Monday, October 20, 2008 10:32 AM
>To: Len Brown
>Cc: Ingo Molnar; [email protected]; Linux Kernel
>Mailing List; Pallipadi, Venkatesh; Henroid, Andrew D; Linus
>Torvalds; Thomas Gleixner; H. Peter Anvin; Andi Kleen
>Subject: Re: [PATCH 2/2] i7300_idle driver v1.55
>
>On Thu, 16 Oct 2008 18:08:01 -0400 (EDT) Len Brown wrote:
>
>> Signed-off-by: Andy Henroid <[email protected]>
>> Signed-off-by: Len Brown <[email protected]>
>> Signed-off-by: Venkatesh Pallipadi <[email protected]>
>> ---
>> MAINTAINERS | 6 +
>> arch/x86/Kconfig | 2 +
>> drivers/Makefile | 1 +
>> drivers/dma/ioat_dma.c | 3 +
>> drivers/idle/Kconfig | 16 +
>> drivers/idle/Makefile | 2 +
>> drivers/idle/i7300_idle.c | 674
>+++++++++++++++++++++++++++++++++++++++++++++
>
>Why not just use drivers/power/ instead of a new sub-directory?
As the driver was specific to idle system and specific to few
platforms/chipset, we decided to put it in a separate directory.
We had called the new directory as drivers/memory initially.
But, idle seemed to suit it better.
I have no issues moving this over to drivers/power. Will send a
incremental patch to move it if that suits better. But, if we
Expect other platforms to have similar platform specific idle
power savings through drivers like this, then having a separate
dir to deal with idle optimization should be better.
>> +/*
>> + * Value to set THRTLOW to when initiating throttling
>> + * 0 = No throttling
>> + * 1 = Throttle when > 4 activations per eval window
>(Maximum throttling)
>> + * 2 = Throttle when > 8 activations
>> + * 168 = Throttle when > 168 activations (Minimum throttling)
>
>Why do some numbers mean > their value (i.e., 168) but others don't?
>Is it a linear value or logarithmic or what?
That is a typo in the comment. These values are simple "multiply by 4".
So, 168 should be 672 activations, and that is the minimum
possible throttling.
>> + */
>> +#define MAX_THRTLWLIMIT 168
>> +static uint i7300_idle_thrtlowlm = 1;
>> +module_param_named(thrtlwlimit, i7300_idle_thrtlowlm, uint, 0644);
>> +MODULE_PARM_DESC(thrtlwlimit,
>> + "Value for THRTLOWLM activation field "
>> + "(0 = disable throttle, 1 = Max throttle, 168
>= Min throttle)");
>> +
>
>> +/* Stop I/O AT memory copy */
>> +static void i7300_idle_ioat_stop(void)
>> +{
>> + int i;
>> + u8 sts;
>> +
>> + for (i = 0; i < 5; i++) {
>> + writeb(IOAT_CHANCMD_RESET,
>> + ioat_chanbase + IOAT1_CHANCMD_OFFSET);
>> +
>> + udelay(10);
>> +
>> + sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
>> + IOAT_CHANSTS_DMA_TRANSFER_STATUS;
>
>readq() returns 64 bits. You only want to LS-byte of it here?
CHANSTS is a 64 bit register and we only use lower few bits
around here. But, agree with your comment and will change it
sts to u64 with an update patch. That will make it consistent
with other reads of this register in this file
>
>> + if (sts != IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE)
>> + break;
>> +
>> + }
>> +
>> + if (i == 5)
>> + dprintk("failed to suspend+reset I/O AT after
>5 retries\n");
>> +
>> +}
>
>
>> +struct debugfs_file_info {
>> + void *ptr;
>> + char name[32];
>> + struct dentry *file;
>> +} debugfs_file_list[] = {
>> + {&total_starts, "total_starts", NULL},
>> + {&total_us, "total_us", NULL},
>> +#ifdef DEBUG
>> + {&past_skip, "past_skip", NULL},
>> +#endif
>> + {NULL, "", NULL}
>> + };
>
>What is debugfs used for? any docs for it?
It has some statistics about how many times we went
into "memory throttling" state and how long we stayed
there since the boot. And one tunable that tunes a
parameter changing the policy to start throttling.
Will document this with an update patch.
>
>Does this build/work if CONFIG_DEBUG_FS=n?
Yes. Did not see any breakage with DEBIG_FS=n
Pallipadi, Venkatesh wrote:
> Thanks for the review. Some comments below.
>
> Thanks,
> Venki
>
>> What is debugfs used for? any docs for it?
>
> It has some statistics about how many times we went
> into "memory throttling" state and how long we stayed
> there since the boot. And one tunable that tunes a
> parameter changing the policy to start throttling.
> Will document this with an update patch.
"Normal" tunables should be in sysfs, not debugfs.
Or is this just a debugging tunable?
You surely can't be certain (or require) that debugfs
be available.
~Randy
>-----Original Message-----
>From: Andi Kleen [mailto:[email protected]]
>Sent: Tuesday, October 21, 2008 9:48 AM
>To: Len Brown
>Cc: Ingo Molnar; [email protected]; Linux Kernel
>Mailing List; Pallipadi, Venkatesh; Henroid, Andrew D; Linus
>Torvalds; Thomas Gleixner; H. Peter Anvin
>Subject: Re: [PATCH 2/2] i7300_idle driver v1.55
>
>Len Brown wrote:
>
>> diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
>> index bc8c6e3..f8396ca 100644
>> --- a/drivers/dma/ioat_dma.c
>> +++ b/drivers/dma/ioat_dma.c
>> @@ -171,6 +171,9 @@ static int
>ioat_dma_enumerate_channels(struct ioatdma_device *device)
>> xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET);
>> xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
>>
>> +#if CONFIG_I7300_IDLE_IOAT_CHANNEL
>> + device->common.chancnt--;
>> +#endif
>
>I still think this lone decrement looks fishy. Can there please be some
>explanation how it exactly relates to the i7300 idle driver, where the
>matching increment is, etc.?
No. This is not a increment/decrement thing. It is basically telling other
Users of IOAT that they have one IOAT channel less that they can use.
The last IOAT channel is used by i7300 idle driver to get the throttling to
work.
>> +config I7300_IDLE
>> + tristate "Intel chipset idle power saving driver"
>
>It would be probably good to mention the word memory here.
>
>> + select I7300_IDLE_IOAT_CHANNEL
>> + depends on X86_64
>> + help
>> + Enable idle power savings with certain Intel server chipsets.
>
>And here too.
OK. Will do.
>> + The chipset must have I/O AT support, such as the Intel 7300.
>> + The power savings depends on the type and quantity
>of DRAM devices.
>
>
>> +static int debug;
>> +module_param_named(debug, debug, uint, 0644);
>> +MODULE_PARM_DESC(debug, "Enable debug printks in this driver");
>
>> +#define dprintk(fmt, arg...) \
>> + do { if (debug) printk(KERN_INFO I7300_PRINT fmt,
>##arg); } while (0)
>
>2.6.28 just got a new dynamic printk facility, which could be used.
Haven't looked at dynamic printk yet. Will take a look at it and update.
>> +
>> +/*
>> + * Value to set THRTLOW to when initiating throttling
>> + * 0 = No throttling
>> + * 1 = Throttle when > 4 activations per eval window
>(Maximum throttling)
>> + * 2 = Throttle when > 8 activations
>> + * 168 = Throttle when > 168 activations (Minimum throttling)
>> + */
>> +#define MAX_THRTLWLIMIT 168
>> +static uint i7300_idle_thrtlowlm = 1;
>> +module_param_named(thrtlwlimit, i7300_idle_thrtlowlm, uint, 0644);
>
>Just imagining how someone would pronounce this parameter @) Will they
>get damages when their tongue ends up in a knot?
:-). It was a balance between keeping the name short and have all the
words idle, 7300, throttle, low and limit. And initially it wasn't through
mod param. I guess this being modparam, I can remove i7300 and idle and
make it just throttle_limit
>> +static cpumask_t idle_cpumask;
>
>Would it make sense to cache align this field? I could imagine
>it false sharing with some frequently written variable could be quite
>bad.
>
>> + writeb(IOAT_CHANCMD_RESET, ioat_chanbase +
>IOAT1_CHANCMD_OFFSET);
>> + writeb(IOAT_CHANCMD_START, ioat_chanbase +
>IOAT1_CHANCMD_OFFSET);
>> +
>> + udelay(1000);
>> +
>> + chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
>> + IOAT_CHANSTS_DMA_TRANSFER_STATUS;
>
>Wouldn't it be better to poll here instead of udelay?
udelay may be more power efficient than polling. We wont be
reading from chipset continuously. But on the other hand
polling seems better choice if we are too far off from
our 1000 uS guess. Will try polling and check how long we
are really waiting here...
>
>> + /* Wait for a while for the channel to halt before releasing */
>> + for (i = 0; i < 10; i++) {
>> + writeb(IOAT_CHANCMD_RESET,
>> + ioat_chanbase + IOAT1_CHANCMD_OFFSET);
>> +
>> + chan_sts = readq(ioat_chanbase +
>IOAT1_CHANSTS_OFFSET) &
>> + IOAT_CHANSTS_DMA_TRANSFER_STATUS;
>> +
>> + if (chan_sts !=
>IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE) {
>> + writew(0, ioat_chanbase +
>IOAT_CHANCTRL_OFFSET);
>> + break;
>> + }
>> + udelay(1000);
>
>Same here.
>
>
>> + spin_lock_irqsave(&i7300_idle_lock, flags);
>
>This lock still scares me. In the worst case with very frequent
>idle frequencies this could bounce around a lot.
>
>It would be better to only invoke it less frequently,
>i.e. when the driver determines there is a long idle
>time coming up.
Agreed. First version was to get the low hanging fruit of huge
power savings that we can get on these platforms by throttling
memory. We did not spend enough time on optimizing this for
performance. Will do this as a follow up.
>> +/* Check for known platforms with I/O-AT */
>> +static int __init i7300_idle_platform_probe(void)
>> +{
>> + int i;
>> +
>> + fbd_dev = pci_get_bus_and_slot(MEMCTL_BUS, MEMCTL_DEVFN)
>
>Is there a specific reason you cannot match this by pci vendor/devid
>like all standard drivers do?
>
>If there is a good reason add a comment.
They have to match vendor device and function. Its not unique to
just vendor and device id.
>;
>> +static void __exit i7300_idle_exit(void)
>> +{
>> + idle_notifier_unregister(&i7300_idle_nb);
>
>I still think this needs some kind of idle synchronization.
This unregister uses atomic_notifier_chain_unregister() which
uses RCU and handles the race conditions that way. I did not
see any race conditions with module unload in my analysis.
Thanks,
Venki
>-----Original Message-----
>From: Randy Dunlap [mailto:[email protected]]
>Sent: Tuesday, October 21, 2008 3:15 PM
>To: Pallipadi, Venkatesh
>Cc: Randy Dunlap; Len Brown; Ingo Molnar;
>[email protected]; Linux Kernel Mailing List;
>Henroid, Andrew D; Linus Torvalds; Thomas Gleixner; H. Peter
>Anvin; Andi Kleen
>Subject: Re: [PATCH 2/2] i7300_idle driver v1.55
>
>Pallipadi, Venkatesh wrote:
>> Thanks for the review. Some comments below.
>>
>> Thanks,
>> Venki
>>
>>> What is debugfs used for? any docs for it?
>>
>> It has some statistics about how many times we went
>> into "memory throttling" state and how long we stayed
>> there since the boot. And one tunable that tunes a
>> parameter changing the policy to start throttling.
>> Will document this with an update patch.
>
>"Normal" tunables should be in sysfs, not debugfs.
>Or is this just a debugging tunable?
>
>You surely can't be certain (or require) that debugfs
>be available.
>
The lone tunable is debug only. It needs driver to be
compiled with DEBUG flag to be present in debugfs.
We don't want export it in sysfs and some random user
app starts using it and then end up providing backward
compatibility for it in future.
The other two read only variables give some stats about
the driver usage and also kind of debuggish info that
we used during development. Didn't seem worthy enough
to go under sysfs.
Thanks,
Venki
Pallipadi, Venkatesh wrote:
>
>>> +#if CONFIG_I7300_IDLE_IOAT_CHANNEL
>>> + device->common.chancnt--;
>>> +#endif
>> I still think this lone decrement looks fishy. Can there please be some
>> explanation how it exactly relates to the i7300 idle driver, where the
>> matching increment is, etc.?
>
> No. This is not a increment/decrement thing. It is basically telling other
> Users of IOAT that they have one IOAT channel less that they can use.
> The last IOAT channel is used by i7300 idle driver to get the throttling to
> work.
Ok then it should be made conditional on the i7300 actually be available
in the system? It looks like you do it always no matter what chipset is in there.
> udelay may be more power efficient than polling.
Isn't that function a one off anyways?
>>> +/* Check for known platforms with I/O-AT */
>>> +static int __init i7300_idle_platform_probe(void)
>>> +{
>>> + int i;
>>> +
>>> + fbd_dev = pci_get_bus_and_slot(MEMCTL_BUS, MEMCTL_DEVFN)
>> Is there a specific reason you cannot match this by pci vendor/devid
>> like all standard drivers do?
>>
>> If there is a good reason add a comment.
>
> They have to match vendor device and function. Its not unique to
> just vendor and device id.
It might be still better then to use the standard callback style and just ignore
devices that don't match?
>
>> ;
>>> +static void __exit i7300_idle_exit(void)
>>> +{
>>> + idle_notifier_unregister(&i7300_idle_nb);
>> I still think this needs some kind of idle synchronization.
>
> This unregister uses atomic_notifier_chain_unregister() which
> uses RCU and handles the race conditions that way.
I didn't do a full analysis, but I didn't think RCU protects
against the idle handler itself. At least not standard RCU.
You would need to go through at least two quiescent periods,
not one as standard code.
There used to be an older
idle synchronization interface for this case (which was removed
at some point), perhaps it needs to be readded.
Or just use stop_machine(). That protects against idle too
and while it's a big hammer for unloading it should be ok.
-Andi
On Wed, Oct 22, 2008 at 12:19:22AM -0700, Andi Kleen wrote:
> Pallipadi, Venkatesh wrote:
> >
> >>> +#if CONFIG_I7300_IDLE_IOAT_CHANNEL
> >>> + device->common.chancnt--;
> >>> +#endif
> >> I still think this lone decrement looks fishy. Can there please be some
> >> explanation how it exactly relates to the i7300 idle driver, where the
> >> matching increment is, etc.?
> >
> > No. This is not a increment/decrement thing. It is basically telling other
> > Users of IOAT that they have one IOAT channel less that they can use.
> > The last IOAT channel is used by i7300 idle driver to get the throttling to
> > work.
>
> Ok then it should be made conditional on the i7300 actually be available
> in the system? It looks like you do it always no matter what chipset is in there.
Does the patch below look OK?
Thanks,
Venki
Based on input from Andi Kleen:
share the platform detection code with ioat_dma and disable the channel in
dma engine only for specific platforms.
Signed-off-by: Venkatesh Pallipadi <[email protected]>
---
drivers/dma/ioat_dma.c | 5 ++
drivers/idle/i7300_idle.c | 72 +--------------------------------------
include/linux/i7300_idle.h | 83 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 89 insertions(+), 71 deletions(-)
Index: linux-acpi-2.6/drivers/idle/i7300_idle.c
===================================================================
--- linux-acpi-2.6.orig/drivers/idle/i7300_idle.c 2008-10-22 11:42:04.000000000 -0700
+++ linux-acpi-2.6/drivers/idle/i7300_idle.c 2008-10-22 11:42:46.000000000 -0700
@@ -25,6 +25,7 @@
#include <linux/delay.h>
#include <linux/debugfs.h>
#include <linux/stop_machine.h>
+#include <linux/i7300_idle.h>
#include <asm/idle.h>
@@ -505,77 +506,8 @@ static struct notifier_block i7300_idle_
.notifier_call = i7300_idle_notifier,
};
-/*
- * I/O AT controls (PCI bus 0 device 8 function 0)
- * DIMM controls (PCI bus 0 device 16 function 1)
- */
-#define IOAT_BUS 0
-#define IOAT_DEVFN PCI_DEVFN(8, 0)
-#define MEMCTL_BUS 0
-#define MEMCTL_DEVFN PCI_DEVFN(16, 1)
-
-struct fbd_ioat {
- unsigned int vendor;
- unsigned int ioat_dev;
-};
-
-/*
- * The i5000 chip-set has the same hooks as the i7300
- * but support is disabled by default because this driver
- * has not been validated on that platform.
- */
-#define SUPPORT_I5000 0
-
-static const struct fbd_ioat fbd_ioat_list[] = {
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB},
-#if SUPPORT_I5000
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT},
-#endif
- {0, 0}
-};
-
-/* table of devices that work with this driver */
-static const struct pci_device_id pci_tbl[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FBD_CNB) },
-#if SUPPORT_I5000
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) },
-#endif
- { } /* Terminating entry */
-};
-
MODULE_DEVICE_TABLE(pci, pci_tbl);
-/* Check for known platforms with I/O-AT */
-static int __init i7300_idle_platform_probe(void)
-{
- int i;
-
- fbd_dev = pci_get_bus_and_slot(MEMCTL_BUS, MEMCTL_DEVFN);
- if (!fbd_dev)
- return -ENODEV;
-
- for (i = 0; pci_tbl[i].vendor != 0; i++) {
- if (fbd_dev->vendor == pci_tbl[i].vendor &&
- fbd_dev->device == pci_tbl[i].device) {
- break;
- }
- }
- if (pci_tbl[i].vendor == 0)
- return -ENODEV;
-
- ioat_dev = pci_get_bus_and_slot(IOAT_BUS, IOAT_DEVFN);
- if (!ioat_dev)
- return -ENODEV;
-
- for (i = 0; fbd_ioat_list[i].vendor != 0; i++) {
- if (ioat_dev->vendor == fbd_ioat_list[i].vendor &&
- ioat_dev->device == fbd_ioat_list[i].ioat_dev) {
- return 0;
- }
- }
- return -ENODEV;
-}
-
int stats_open_generic(struct inode *inode, struct file *fp)
{
fp->private_data = inode->i_private;
@@ -617,7 +549,7 @@ static int __init i7300_idle_init(void)
cpus_clear(idle_cpumask);
total_us = 0;
- if (i7300_idle_platform_probe())
+ if (i7300_idle_platform_probe(&fbd_dev, &ioat_dev))
return -ENODEV;
if (i7300_idle_thrt_save())
Index: linux-acpi-2.6/include/linux/i7300_idle.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-acpi-2.6/include/linux/i7300_idle.h 2008-10-22 11:42:46.000000000 -0700
@@ -0,0 +1,83 @@
+
+#ifndef I7300_IDLE_H
+#define I7300_IDLE_H
+
+#include <linux/pci.h>
+
+/*
+ * I/O AT controls (PCI bus 0 device 8 function 0)
+ * DIMM controls (PCI bus 0 device 16 function 1)
+ */
+#define IOAT_BUS 0
+#define IOAT_DEVFN PCI_DEVFN(8, 0)
+#define MEMCTL_BUS 0
+#define MEMCTL_DEVFN PCI_DEVFN(16, 1)
+
+struct fbd_ioat {
+ unsigned int vendor;
+ unsigned int ioat_dev;
+};
+
+/*
+ * The i5000 chip-set has the same hooks as the i7300
+ * but support is disabled by default because this driver
+ * has not been validated on that platform.
+ */
+#define SUPPORT_I5000 0
+
+static const struct fbd_ioat fbd_ioat_list[] = {
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB},
+#if SUPPORT_I5000
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT},
+#endif
+ {0, 0}
+};
+
+/* table of devices that work with this driver */
+static const struct pci_device_id pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FBD_CNB) },
+#if SUPPORT_I5000
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) },
+#endif
+ { } /* Terminating entry */
+};
+
+/* Check for known platforms with I/O-AT */
+static inline int i7300_idle_platform_probe(struct pci_dev **fbd_dev,
+ struct pci_dev **ioat_dev)
+{
+ int i;
+ struct pci_dev *memdev, *dmadev;
+
+ memdev = pci_get_bus_and_slot(MEMCTL_BUS, MEMCTL_DEVFN);
+ if (!memdev)
+ return -ENODEV;
+
+ for (i = 0; pci_tbl[i].vendor != 0; i++) {
+ if (memdev->vendor == pci_tbl[i].vendor &&
+ memdev->device == pci_tbl[i].device) {
+ break;
+ }
+ }
+ if (pci_tbl[i].vendor == 0)
+ return -ENODEV;
+
+ dmadev = pci_get_bus_and_slot(IOAT_BUS, IOAT_DEVFN);
+ if (!dmadev)
+ return -ENODEV;
+
+ for (i = 0; fbd_ioat_list[i].vendor != 0; i++) {
+ if (dmadev->vendor == fbd_ioat_list[i].vendor &&
+ dmadev->device == fbd_ioat_list[i].ioat_dev) {
+ if (fbd_dev)
+ *fbd_dev = memdev;
+ if (ioat_dev)
+ *ioat_dev = dmadev;
+
+ return 0;
+ }
+ }
+ return -ENODEV;
+}
+
+#endif
Index: linux-acpi-2.6/drivers/dma/ioat_dma.c
===================================================================
--- linux-acpi-2.6.orig/drivers/dma/ioat_dma.c 2008-10-22 11:42:04.000000000 -0700
+++ linux-acpi-2.6/drivers/dma/ioat_dma.c 2008-10-22 11:42:46.000000000 -0700
@@ -33,6 +33,7 @@
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/workqueue.h>
+#include <linux/i7300_idle.h>
#include "ioatdma.h"
#include "ioatdma_registers.h"
#include "ioatdma_hw.h"
@@ -172,7 +173,9 @@ static int ioat_dma_enumerate_channels(s
xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
#if CONFIG_I7300_IDLE_IOAT_CHANNEL
- device->common.chancnt--;
+ if (i7300_idle_platform_probe(NULL, NULL) == 0) {
+ device->common.chancnt--;
+ }
#endif
for (i = 0; i < device->common.chancnt; i++) {
ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL);
On Wed, Oct 22, 2008 at 12:19:22AM -0700, Andi Kleen wrote:
> Pallipadi, Venkatesh wrote:
> >
> > udelay may be more power efficient than polling.
>
> Isn't that function a one off anyways?
Which function is one off?
> >
> >> ;
> >>> +static void __exit i7300_idle_exit(void)
> >>> +{
> >>> + idle_notifier_unregister(&i7300_idle_nb);
> >> I still think this needs some kind of idle synchronization.
> >
> > This unregister uses atomic_notifier_chain_unregister() which
> > uses RCU and handles the race conditions that way.
>
> I didn't do a full analysis, but I didn't think RCU protects
> against the idle handler itself. At least not standard RCU.
> You would need to go through at least two quiescent periods,
> not one as standard code.
>
> There used to be an older
> idle synchronization interface for this case (which was removed
> at some point), perhaps it needs to be readded.
>
> Or just use stop_machine(). That protects against idle too
> and while it's a big hammer for unloading it should be ok.
>
stop_machine() for unregistering idle callback will deadlock due to RCU.
I am not sure why we need two cycles. RCU in the unregister makes
sure that no CPU is executing the callback handler and only then unregister
returns. So, that will mean no one can be in the callback rountine and we are
safe to remove the module. Correct?
Thanks,
Venki
Cleanup of i7300 idle driver based on review comments from Randy Dunlap,
Andi Kleen and Len Brown.
Signed-off-by: Venkatesh Pallipadi <[email protected]>
---
drivers/idle/Kconfig | 11 ++++++-----
drivers/idle/i7300_idle.c | 33 ++++++++++++++++++---------------
2 files changed, 24 insertions(+), 20 deletions(-)
Index: linux-acpi-2.6/drivers/idle/Kconfig
===================================================================
--- linux-acpi-2.6.orig/drivers/idle/Kconfig 2008-10-22 11:43:08.000000000 -0700
+++ linux-acpi-2.6/drivers/idle/Kconfig 2008-10-22 11:43:37.000000000 -0700
@@ -5,12 +5,13 @@ config I7300_IDLE_IOAT_CHANNEL
bool
config I7300_IDLE
- tristate "Intel chipset idle power saving driver"
+ tristate "Intel chipset idle memory power saving driver"
select I7300_IDLE_IOAT_CHANNEL
- depends on X86_64
+ depends on X86_64 && EXPERIMENTAL
help
- Enable idle power savings with certain Intel server chipsets.
- The chipset must have I/O AT support, such as the Intel 7300.
- The power savings depends on the type and quantity of DRAM devices.
+ Enable memory power savings when idle with certain Intel server
+ chipsets. The chipset must have I/O AT support, such as the
+ Intel 7300. The power savings depends on the type and quantity of
+ DRAM devices.
endmenu
Index: linux-acpi-2.6/drivers/idle/i7300_idle.c
===================================================================
--- linux-acpi-2.6.orig/drivers/idle/i7300_idle.c 2008-10-22 11:43:08.000000000 -0700
+++ linux-acpi-2.6/drivers/idle/i7300_idle.c 2008-10-22 11:43:37.000000000 -0700
@@ -35,6 +35,8 @@
#define I7300_IDLE_DRIVER_VERSION "1.55"
#define I7300_PRINT "i7300_idle:"
+#define MAX_STOP_RETRIES 10
+
static int debug;
module_param_named(debug, debug, uint, 0644);
MODULE_PARM_DESC(debug, "Enable debug printks in this driver");
@@ -47,12 +49,12 @@ MODULE_PARM_DESC(debug, "Enable debug pr
* 0 = No throttling
* 1 = Throttle when > 4 activations per eval window (Maximum throttling)
* 2 = Throttle when > 8 activations
- * 168 = Throttle when > 168 activations (Minimum throttling)
+ * 168 = Throttle when > 672 activations (Minimum throttling)
*/
-#define MAX_THRTLWLIMIT 168
-static uint i7300_idle_thrtlowlm = 1;
-module_param_named(thrtlwlimit, i7300_idle_thrtlowlm, uint, 0644);
-MODULE_PARM_DESC(thrtlwlimit,
+#define MAX_THROTTLE_LOW_LIMIT 168
+static uint throttle_low_limit = 1;
+module_param_named(throttle_low_limit, throttle_low_limit, uint, 0644);
+MODULE_PARM_DESC(throttle_low_limit,
"Value for THRTLOWLM activation field "
"(0 = disable throttle, 1 = Max throttle, 168 = Min throttle)");
@@ -111,9 +113,9 @@ static int i7300_idle_ioat_start(void)
static void i7300_idle_ioat_stop(void)
{
int i;
- u8 sts;
+ u64 sts;
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < MAX_STOP_RETRIES; i++) {
writeb(IOAT_CHANCMD_RESET,
ioat_chanbase + IOAT1_CHANCMD_OFFSET);
@@ -127,9 +129,10 @@ static void i7300_idle_ioat_stop(void)
}
- if (i == 5)
- dprintk("failed to suspend+reset I/O AT after 5 retries\n");
-
+ if (i == MAX_STOP_RETRIES) {
+ dprintk("failed to stop I/O AT after %d retries\n",
+ MAX_STOP_RETRIES);
+ }
}
/* Test I/O AT by copying 1024 byte from 2k to 1k */
@@ -276,7 +279,7 @@ static void __exit i7300_idle_ioat_exit(
i7300_idle_ioat_stop();
/* Wait for a while for the channel to halt before releasing */
- for (i = 0; i < 10; i++) {
+ for (i = 0; i < MAX_STOP_RETRIES; i++) {
writeb(IOAT_CHANCMD_RESET,
ioat_chanbase + IOAT1_CHANCMD_OFFSET);
@@ -390,9 +393,9 @@ static void i7300_idle_start(void)
new_ctl = i7300_idle_thrtctl_saved & ~DIMM_THRTCTL_THRMHUNT;
pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl);
- limit = i7300_idle_thrtlowlm;
- if (unlikely(limit > MAX_THRTLWLIMIT))
- limit = MAX_THRTLWLIMIT;
+ limit = throttle_low_limit;
+ if (unlikely(limit > MAX_THROTTLE_LOW_LIMIT))
+ limit = MAX_THROTTLE_LOW_LIMIT;
pci_write_config_byte(fbd_dev, DIMM_THRTLOW, limit);
@@ -441,7 +444,7 @@ static int i7300_idle_notifier(struct no
static ktime_t idle_begin_time;
static int time_init = 1;
- if (!i7300_idle_thrtlowlm)
+ if (!throttle_low_limit)
return 0;
if (unlikely(time_init)) {
Venki Pallipadi wrote:
> On Wed, Oct 22, 2008 at 12:19:22AM -0700, Andi Kleen wrote:
>> Pallipadi, Venkatesh wrote:
>>> udelay may be more power efficient than polling.
>> Isn't that function a one off anyways?
>
> Which function is one off?
The one with the udelays, as in being init code. Or maybe I misread
the code.
>>>> ;
>>>>> +static void __exit i7300_idle_exit(void)
>>>>> +{
>>>>> + idle_notifier_unregister(&i7300_idle_nb);
>>>> I still think this needs some kind of idle synchronization.
>>> This unregister uses atomic_notifier_chain_unregister() which
>>> uses RCU and handles the race conditions that way.
>> I didn't do a full analysis, but I didn't think RCU protects
>> against the idle handler itself. At least not standard RCU.
>> You would need to go through at least two quiescent periods,
>> not one as standard code.
>>
>> There used to be an older
>> idle synchronization interface for this case (which was removed
>> at some point), perhaps it needs to be readded.
>>
>> Or just use stop_machine(). That protects against idle too
>> and while it's a big hammer for unloading it should be ok.
>>
>
> stop_machine() for unregistering idle callback will deadlock due to RCU.
>
> I am not sure why we need two cycles. RCU in the unregister makes
> sure that no CPU is executing the callback handler
> and only then unregister
> returns. So, that will mean no one can be in the callback rountine and we are
> safe to remove the module. Correct?
Perhaps I'm confused, but I thought with noidlehz the RCU code
got changed to take out idle CPUs out of the rcu masks. This makes
normally sense because you don't want to delay the grace period
for potentially very long sleeping CPUs.
But it means it won't work for code inside the idle loop. Ok maybe
if you're very careful with the ordering, but I'm not sure that's
the case currently.
Yes two cycles won't work either, sorry was confused earlier,
because even the second cycle wouldn't force the CPU out of idle.
The old idle sync code was more a thread that just cycled through
all the CPus. That would work.
cc Paul
-Andi
>-----Original Message-----
>From: Andi Kleen [mailto:[email protected]]
>Sent: Wednesday, October 22, 2008 6:11 PM
>To: Pallipadi, Venkatesh
>Cc: Len Brown; Ingo Molnar; [email protected]; Linux
>Kernel Mailing List; Henroid, Andrew D; Linus Torvalds; Thomas
>Gleixner; H. Peter Anvin; [email protected]
>Subject: Re: [PATCH 2/2] i7300_idle driver v1.55
>
>>>>> ;
>>>>>> +static void __exit i7300_idle_exit(void)
>>>>>> +{
>>>>>> + idle_notifier_unregister(&i7300_idle_nb);
>>>>> I still think this needs some kind of idle synchronization.
>>>> This unregister uses atomic_notifier_chain_unregister() which
>>>> uses RCU and handles the race conditions that way.
>>> I didn't do a full analysis, but I didn't think RCU protects
>>> against the idle handler itself. At least not standard RCU.
>>> You would need to go through at least two quiescent periods,
>>> not one as standard code.
>>>
>>> There used to be an older
>>> idle synchronization interface for this case (which was removed
>>> at some point), perhaps it needs to be readded.
>>>
>>> Or just use stop_machine(). That protects against idle too
>>> and while it's a big hammer for unloading it should be ok.
>>>
>>
>> stop_machine() for unregistering idle callback will deadlock
>due to RCU.
>>
>> I am not sure why we need two cycles. RCU in the unregister makes
>> sure that no CPU is executing the callback handler
>> and only then unregister
>> returns. So, that will mean no one can be in the callback
>rountine and we are
>> safe to remove the module. Correct?
>
>Perhaps I'm confused, but I thought with noidlehz the RCU code
>got changed to take out idle CPUs out of the rcu masks. This makes
>normally sense because you don't want to delay the grace period
>for potentially very long sleeping CPUs.
>
>But it means it won't work for code inside the idle loop. Ok maybe
>if you're very careful with the ordering, but I'm not sure that's
>the case currently.
>
>Yes two cycles won't work either, sorry was confused earlier,
>because even the second cycle wouldn't force the CPU out of idle.
>
>The old idle sync code was more a thread that just cycled through
>all the CPus. That would work.
>
This should not matter as we can safely remove the module even when
one or more CPUs are idle. As long as one CPU is running, we are sure
that throttling is not in effect. And as long as we make sure no one
is executing the notifier that is going to be rmmoded, we should
be OK. Say one CPU comes out of the idle later, it wont see the notifier
in the notifier list anymore, because of RCU in atomic notifier
and things will work fine. I mean we are not rmmoding the routine
that enters the idle state. We are just rmmoding the routine that
Can get called before and after idle routine.
Thanks,
Venki
> This should not matter as we can safely remove the module even when
> one or more CPUs are idle. As long as one CPU is running, we are sure
> that throttling is not in effect. And as long as we make sure no one
> is executing the notifier that is going to be rmmoded, we should
> be OK. Say one CPU comes out of the idle later, it wont see the notifier
> in the notifier list anymore, because of RCU in atomic notifier
> and things will work fine. I mean we are not rmmoding the routine
> that enters the idle state. We are just rmmoding the routine that
> Can get called before and after idle routine.
That means there is a ordering dependency between the RCU idle
state getting updated and your code running. That is what I meant with
"very careful with idle". Even if it worked right now would
seem fragile to me.
-Andi
On Wed, Oct 22, 2008 at 09:59:30PM -0700, Pallipadi, Venkatesh wrote:
>
>
> >-----Original Message-----
> >From: Andi Kleen [mailto:[email protected]]
> >Sent: Wednesday, October 22, 2008 6:11 PM
> >To: Pallipadi, Venkatesh
> >Cc: Len Brown; Ingo Molnar; [email protected]; Linux
> >Kernel Mailing List; Henroid, Andrew D; Linus Torvalds; Thomas
> >Gleixner; H. Peter Anvin; [email protected]
> >Subject: Re: [PATCH 2/2] i7300_idle driver v1.55
> >
> >>>>> ;
> >>>>>> +static void __exit i7300_idle_exit(void)
> >>>>>> +{
> >>>>>> + idle_notifier_unregister(&i7300_idle_nb);
> >>>>> I still think this needs some kind of idle synchronization.
> >>>> This unregister uses atomic_notifier_chain_unregister() which
> >>>> uses RCU and handles the race conditions that way.
> >>> I didn't do a full analysis, but I didn't think RCU protects
> >>> against the idle handler itself. At least not standard RCU.
> >>> You would need to go through at least two quiescent periods,
> >>> not one as standard code.
> >>>
> >>> There used to be an older
> >>> idle synchronization interface for this case (which was removed
> >>> at some point), perhaps it needs to be readded.
> >>>
> >>> Or just use stop_machine(). That protects against idle too
> >>> and while it's a big hammer for unloading it should be ok.
> >>>
> >>
> >> stop_machine() for unregistering idle callback will deadlock
> >due to RCU.
> >>
> >> I am not sure why we need two cycles. RCU in the unregister makes
> >> sure that no CPU is executing the callback handler
> >> and only then unregister
> >> returns. So, that will mean no one can be in the callback
> >rountine and we are
> >> safe to remove the module. Correct?
> >
> >Perhaps I'm confused, but I thought with noidlehz the RCU code
> >got changed to take out idle CPUs out of the rcu masks. This makes
> >normally sense because you don't want to delay the grace period
> >for potentially very long sleeping CPUs.
> >
> >But it means it won't work for code inside the idle loop. Ok maybe
> >if you're very careful with the ordering, but I'm not sure that's
> >the case currently.
> >
> >Yes two cycles won't work either, sorry was confused earlier,
> >because even the second cycle wouldn't force the CPU out of idle.
> >
> >The old idle sync code was more a thread that just cycled through
> >all the CPus. That would work.
> >
>
> This should not matter as we can safely remove the module even when
> one or more CPUs are idle. As long as one CPU is running, we are sure
> that throttling is not in effect. And as long as we make sure no one
> is executing the notifier that is going to be rmmoded, we should
> be OK. Say one CPU comes out of the idle later, it wont see the notifier
> in the notifier list anymore, because of RCU in atomic notifier
> and things will work fine. I mean we are not rmmoding the routine
> that enters the idle state. We are just rmmoding the routine that
> Can get called before and after idle routine.
Suppose that one of the idle CPUs takes an interrupt, whose handler
accesses the module being removed. How is this handled?
Thanx, Paul
> Suppose that one of the idle CPUs takes an interrupt, whose handler
> accesses the module being removed. How is this handled?
We're just talking about idle notifier code here. Interrupts shouldn't
ever call idle notifiers directly.
-Andi
applied to acpi-test
thanks,
-len
On Wed, 22 Oct 2008, Venki Pallipadi wrote:
> On Wed, Oct 22, 2008 at 12:19:22AM -0700, Andi Kleen wrote:
> > Pallipadi, Venkatesh wrote:
> > >
> > >>> +#if CONFIG_I7300_IDLE_IOAT_CHANNEL
> > >>> + device->common.chancnt--;
> > >>> +#endif
> > >> I still think this lone decrement looks fishy. Can there please be some
> > >> explanation how it exactly relates to the i7300 idle driver, where the
> > >> matching increment is, etc.?
> > >
> > > No. This is not a increment/decrement thing. It is basically telling other
> > > Users of IOAT that they have one IOAT channel less that they can use.
> > > The last IOAT channel is used by i7300 idle driver to get the throttling to
> > > work.
> >
> > Ok then it should be made conditional on the i7300 actually be available
> > in the system? It looks like you do it always no matter what chipset is in there.
>
> Does the patch below look OK?
>
> Thanks,
> Venki
>
> Based on input from Andi Kleen:
> share the platform detection code with ioat_dma and disable the channel in
> dma engine only for specific platforms.
>
> Signed-off-by: Venkatesh Pallipadi <[email protected]>
>
> ---
> drivers/dma/ioat_dma.c | 5 ++
> drivers/idle/i7300_idle.c | 72 +--------------------------------------
> include/linux/i7300_idle.h | 83 +++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 89 insertions(+), 71 deletions(-)
>
> Index: linux-acpi-2.6/drivers/idle/i7300_idle.c
> ===================================================================
> --- linux-acpi-2.6.orig/drivers/idle/i7300_idle.c 2008-10-22 11:42:04.000000000 -0700
> +++ linux-acpi-2.6/drivers/idle/i7300_idle.c 2008-10-22 11:42:46.000000000 -0700
> @@ -25,6 +25,7 @@
> #include <linux/delay.h>
> #include <linux/debugfs.h>
> #include <linux/stop_machine.h>
> +#include <linux/i7300_idle.h>
>
> #include <asm/idle.h>
>
> @@ -505,77 +506,8 @@ static struct notifier_block i7300_idle_
> .notifier_call = i7300_idle_notifier,
> };
>
> -/*
> - * I/O AT controls (PCI bus 0 device 8 function 0)
> - * DIMM controls (PCI bus 0 device 16 function 1)
> - */
> -#define IOAT_BUS 0
> -#define IOAT_DEVFN PCI_DEVFN(8, 0)
> -#define MEMCTL_BUS 0
> -#define MEMCTL_DEVFN PCI_DEVFN(16, 1)
> -
> -struct fbd_ioat {
> - unsigned int vendor;
> - unsigned int ioat_dev;
> -};
> -
> -/*
> - * The i5000 chip-set has the same hooks as the i7300
> - * but support is disabled by default because this driver
> - * has not been validated on that platform.
> - */
> -#define SUPPORT_I5000 0
> -
> -static const struct fbd_ioat fbd_ioat_list[] = {
> - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB},
> -#if SUPPORT_I5000
> - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT},
> -#endif
> - {0, 0}
> -};
> -
> -/* table of devices that work with this driver */
> -static const struct pci_device_id pci_tbl[] = {
> - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FBD_CNB) },
> -#if SUPPORT_I5000
> - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) },
> -#endif
> - { } /* Terminating entry */
> -};
> -
> MODULE_DEVICE_TABLE(pci, pci_tbl);
>
> -/* Check for known platforms with I/O-AT */
> -static int __init i7300_idle_platform_probe(void)
> -{
> - int i;
> -
> - fbd_dev = pci_get_bus_and_slot(MEMCTL_BUS, MEMCTL_DEVFN);
> - if (!fbd_dev)
> - return -ENODEV;
> -
> - for (i = 0; pci_tbl[i].vendor != 0; i++) {
> - if (fbd_dev->vendor == pci_tbl[i].vendor &&
> - fbd_dev->device == pci_tbl[i].device) {
> - break;
> - }
> - }
> - if (pci_tbl[i].vendor == 0)
> - return -ENODEV;
> -
> - ioat_dev = pci_get_bus_and_slot(IOAT_BUS, IOAT_DEVFN);
> - if (!ioat_dev)
> - return -ENODEV;
> -
> - for (i = 0; fbd_ioat_list[i].vendor != 0; i++) {
> - if (ioat_dev->vendor == fbd_ioat_list[i].vendor &&
> - ioat_dev->device == fbd_ioat_list[i].ioat_dev) {
> - return 0;
> - }
> - }
> - return -ENODEV;
> -}
> -
> int stats_open_generic(struct inode *inode, struct file *fp)
> {
> fp->private_data = inode->i_private;
> @@ -617,7 +549,7 @@ static int __init i7300_idle_init(void)
> cpus_clear(idle_cpumask);
> total_us = 0;
>
> - if (i7300_idle_platform_probe())
> + if (i7300_idle_platform_probe(&fbd_dev, &ioat_dev))
> return -ENODEV;
>
> if (i7300_idle_thrt_save())
> Index: linux-acpi-2.6/include/linux/i7300_idle.h
> ===================================================================
> --- /dev/null 1970-01-01 00:00:00.000000000 +0000
> +++ linux-acpi-2.6/include/linux/i7300_idle.h 2008-10-22 11:42:46.000000000 -0700
> @@ -0,0 +1,83 @@
> +
> +#ifndef I7300_IDLE_H
> +#define I7300_IDLE_H
> +
> +#include <linux/pci.h>
> +
> +/*
> + * I/O AT controls (PCI bus 0 device 8 function 0)
> + * DIMM controls (PCI bus 0 device 16 function 1)
> + */
> +#define IOAT_BUS 0
> +#define IOAT_DEVFN PCI_DEVFN(8, 0)
> +#define MEMCTL_BUS 0
> +#define MEMCTL_DEVFN PCI_DEVFN(16, 1)
> +
> +struct fbd_ioat {
> + unsigned int vendor;
> + unsigned int ioat_dev;
> +};
> +
> +/*
> + * The i5000 chip-set has the same hooks as the i7300
> + * but support is disabled by default because this driver
> + * has not been validated on that platform.
> + */
> +#define SUPPORT_I5000 0
> +
> +static const struct fbd_ioat fbd_ioat_list[] = {
> + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB},
> +#if SUPPORT_I5000
> + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT},
> +#endif
> + {0, 0}
> +};
> +
> +/* table of devices that work with this driver */
> +static const struct pci_device_id pci_tbl[] = {
> + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FBD_CNB) },
> +#if SUPPORT_I5000
> + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) },
> +#endif
> + { } /* Terminating entry */
> +};
> +
> +/* Check for known platforms with I/O-AT */
> +static inline int i7300_idle_platform_probe(struct pci_dev **fbd_dev,
> + struct pci_dev **ioat_dev)
> +{
> + int i;
> + struct pci_dev *memdev, *dmadev;
> +
> + memdev = pci_get_bus_and_slot(MEMCTL_BUS, MEMCTL_DEVFN);
> + if (!memdev)
> + return -ENODEV;
> +
> + for (i = 0; pci_tbl[i].vendor != 0; i++) {
> + if (memdev->vendor == pci_tbl[i].vendor &&
> + memdev->device == pci_tbl[i].device) {
> + break;
> + }
> + }
> + if (pci_tbl[i].vendor == 0)
> + return -ENODEV;
> +
> + dmadev = pci_get_bus_and_slot(IOAT_BUS, IOAT_DEVFN);
> + if (!dmadev)
> + return -ENODEV;
> +
> + for (i = 0; fbd_ioat_list[i].vendor != 0; i++) {
> + if (dmadev->vendor == fbd_ioat_list[i].vendor &&
> + dmadev->device == fbd_ioat_list[i].ioat_dev) {
> + if (fbd_dev)
> + *fbd_dev = memdev;
> + if (ioat_dev)
> + *ioat_dev = dmadev;
> +
> + return 0;
> + }
> + }
> + return -ENODEV;
> +}
> +
> +#endif
> Index: linux-acpi-2.6/drivers/dma/ioat_dma.c
> ===================================================================
> --- linux-acpi-2.6.orig/drivers/dma/ioat_dma.c 2008-10-22 11:42:04.000000000 -0700
> +++ linux-acpi-2.6/drivers/dma/ioat_dma.c 2008-10-22 11:42:46.000000000 -0700
> @@ -33,6 +33,7 @@
> #include <linux/delay.h>
> #include <linux/dma-mapping.h>
> #include <linux/workqueue.h>
> +#include <linux/i7300_idle.h>
> #include "ioatdma.h"
> #include "ioatdma_registers.h"
> #include "ioatdma_hw.h"
> @@ -172,7 +173,9 @@ static int ioat_dma_enumerate_channels(s
> xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
>
> #if CONFIG_I7300_IDLE_IOAT_CHANNEL
> - device->common.chancnt--;
> + if (i7300_idle_platform_probe(NULL, NULL) == 0) {
> + device->common.chancnt--;
> + }
> #endif
> for (i = 0; i < device->common.chancnt; i++) {
> ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL);
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
applied to acpi-test
thanks,
-len
On Wed, 22 Oct 2008, Venki Pallipadi wrote:
>
>
> Cleanup of i7300 idle driver based on review comments from Randy Dunlap,
> Andi Kleen and Len Brown.
>
> Signed-off-by: Venkatesh Pallipadi <[email protected]>
>
> ---
> drivers/idle/Kconfig | 11 ++++++-----
> drivers/idle/i7300_idle.c | 33 ++++++++++++++++++---------------
> 2 files changed, 24 insertions(+), 20 deletions(-)
>
> Index: linux-acpi-2.6/drivers/idle/Kconfig
> ===================================================================
> --- linux-acpi-2.6.orig/drivers/idle/Kconfig 2008-10-22 11:43:08.000000000 -0700
> +++ linux-acpi-2.6/drivers/idle/Kconfig 2008-10-22 11:43:37.000000000 -0700
> @@ -5,12 +5,13 @@ config I7300_IDLE_IOAT_CHANNEL
> bool
>
> config I7300_IDLE
> - tristate "Intel chipset idle power saving driver"
> + tristate "Intel chipset idle memory power saving driver"
> select I7300_IDLE_IOAT_CHANNEL
> - depends on X86_64
> + depends on X86_64 && EXPERIMENTAL
> help
> - Enable idle power savings with certain Intel server chipsets.
> - The chipset must have I/O AT support, such as the Intel 7300.
> - The power savings depends on the type and quantity of DRAM devices.
> + Enable memory power savings when idle with certain Intel server
> + chipsets. The chipset must have I/O AT support, such as the
> + Intel 7300. The power savings depends on the type and quantity of
> + DRAM devices.
>
> endmenu
> Index: linux-acpi-2.6/drivers/idle/i7300_idle.c
> ===================================================================
> --- linux-acpi-2.6.orig/drivers/idle/i7300_idle.c 2008-10-22 11:43:08.000000000 -0700
> +++ linux-acpi-2.6/drivers/idle/i7300_idle.c 2008-10-22 11:43:37.000000000 -0700
> @@ -35,6 +35,8 @@
> #define I7300_IDLE_DRIVER_VERSION "1.55"
> #define I7300_PRINT "i7300_idle:"
>
> +#define MAX_STOP_RETRIES 10
> +
> static int debug;
> module_param_named(debug, debug, uint, 0644);
> MODULE_PARM_DESC(debug, "Enable debug printks in this driver");
> @@ -47,12 +49,12 @@ MODULE_PARM_DESC(debug, "Enable debug pr
> * 0 = No throttling
> * 1 = Throttle when > 4 activations per eval window (Maximum throttling)
> * 2 = Throttle when > 8 activations
> - * 168 = Throttle when > 168 activations (Minimum throttling)
> + * 168 = Throttle when > 672 activations (Minimum throttling)
> */
> -#define MAX_THRTLWLIMIT 168
> -static uint i7300_idle_thrtlowlm = 1;
> -module_param_named(thrtlwlimit, i7300_idle_thrtlowlm, uint, 0644);
> -MODULE_PARM_DESC(thrtlwlimit,
> +#define MAX_THROTTLE_LOW_LIMIT 168
> +static uint throttle_low_limit = 1;
> +module_param_named(throttle_low_limit, throttle_low_limit, uint, 0644);
> +MODULE_PARM_DESC(throttle_low_limit,
> "Value for THRTLOWLM activation field "
> "(0 = disable throttle, 1 = Max throttle, 168 = Min throttle)");
>
> @@ -111,9 +113,9 @@ static int i7300_idle_ioat_start(void)
> static void i7300_idle_ioat_stop(void)
> {
> int i;
> - u8 sts;
> + u64 sts;
>
> - for (i = 0; i < 5; i++) {
> + for (i = 0; i < MAX_STOP_RETRIES; i++) {
> writeb(IOAT_CHANCMD_RESET,
> ioat_chanbase + IOAT1_CHANCMD_OFFSET);
>
> @@ -127,9 +129,10 @@ static void i7300_idle_ioat_stop(void)
>
> }
>
> - if (i == 5)
> - dprintk("failed to suspend+reset I/O AT after 5 retries\n");
> -
> + if (i == MAX_STOP_RETRIES) {
> + dprintk("failed to stop I/O AT after %d retries\n",
> + MAX_STOP_RETRIES);
> + }
> }
>
> /* Test I/O AT by copying 1024 byte from 2k to 1k */
> @@ -276,7 +279,7 @@ static void __exit i7300_idle_ioat_exit(
> i7300_idle_ioat_stop();
>
> /* Wait for a while for the channel to halt before releasing */
> - for (i = 0; i < 10; i++) {
> + for (i = 0; i < MAX_STOP_RETRIES; i++) {
> writeb(IOAT_CHANCMD_RESET,
> ioat_chanbase + IOAT1_CHANCMD_OFFSET);
>
> @@ -390,9 +393,9 @@ static void i7300_idle_start(void)
> new_ctl = i7300_idle_thrtctl_saved & ~DIMM_THRTCTL_THRMHUNT;
> pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl);
>
> - limit = i7300_idle_thrtlowlm;
> - if (unlikely(limit > MAX_THRTLWLIMIT))
> - limit = MAX_THRTLWLIMIT;
> + limit = throttle_low_limit;
> + if (unlikely(limit > MAX_THROTTLE_LOW_LIMIT))
> + limit = MAX_THROTTLE_LOW_LIMIT;
>
> pci_write_config_byte(fbd_dev, DIMM_THRTLOW, limit);
>
> @@ -441,7 +444,7 @@ static int i7300_idle_notifier(struct no
> static ktime_t idle_begin_time;
> static int time_init = 1;
>
> - if (!i7300_idle_thrtlowlm)
> + if (!throttle_low_limit)
> return 0;
>
> if (unlikely(time_init)) {
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
> ---------- Original message ----------
> From: Venki Pallipadi <[email protected]>
> Date: Oct 23, 2008 12:34 AM
> Subject: [PATCH] Disable ioat channel only on platforms where ile
> driver can load
> To: Andi Kleen <[email protected]>
> Cc: "Pallipadi, Venkatesh" <[email protected]>, Len Brown
> <[email protected]>, Ingo Molnar <[email protected]>,
> "[email protected]" <[email protected]>, Linux
> Kernel Mailing List <[email protected]>, "Henroid, Andrew
> D" <[email protected]>, Linus Torvalds
> <[email protected]>, Thomas Gleixner <[email protected]>,
> "H. Peter Anvin" <[email protected]>
>
>
> On Wed, Oct 22, 2008 at 12:19:22AM -0700, Andi Kleen wrote:
>> Pallipadi, Venkatesh wrote:
>>>
>>>>> +#if CONFIG_I7300_IDLE_IOAT_CHANNEL
>>>>> + device->common.chancnt--;
>>>>> +#endif
>>>> I still think this lone decrement looks fishy. Can there please be
>>>> some explanation how it exactly relates to the i7300 idle driver,
>>>> where the matching increment is, etc.?
>>>
>>> No. This is not a increment/decrement thing. It is basically
>>> telling other Users of IOAT that they have one IOAT channel less
>>> that they can use.
>>> The last IOAT channel is used by i7300 idle driver to get the
>>> throttling to work.
>>
>> Ok then it should be made conditional on the i7300 actually be
>> available
>> in the system? It looks like you do it always no matter what
>> chipset is in there.
>
> Does the patch below look OK?
>
> Thanks,
> Venki
>
> Based on input from Andi Kleen:
> share the platform detection code with ioat_dma and disable the
> channel in
> dma engine only for specific platforms.
>
> Signed-off-by: Venkatesh Pallipadi <[email protected]>
>
> ---
Hi Venki,
Why for your purposes don't you use dmaengine to request an ioatdma
channel from ioatdma driver?
This way sharing of this channel with other clients
(like TCP which uses ioatdma for receive offloading) would be possible .
In the previous approach your change was not acceptable from ioatdma
perspective
(for IOAT_VER_3_0 there are 8 ioat devices, each with single channel
- in this case you would take away all 8 channels and make ioat ver.3.0
totally disfunctional).
Even with this approach (assuming that it would affect IOAT_VER_1_2
only)
you reserve one channel of four statically for your purposes only,
leaving for TCP receive offloading 75% of ioatdma resources and thus
affecting its efficiency.
Dan, what do you think?
BTW, could you please next time in case of ioat/dmaengine changes
include Dan and me in the list?
Thanks,
Maciej
> Index: linux-acpi-2.6/drivers/dma/ioat_dma.c
> ===================================================================
> --- linux-acpi-2.6.orig/drivers/dma/ioat_dma.c 2008-10-22
> 11:42:04.000000000 -0700
> +++ linux-acpi-2.6/drivers/dma/ioat_dma.c 2008-10-22
> 11:42:46.000000000 -0700
> @@ -33,6 +33,7 @@
> #include <linux/delay.h>
> #include <linux/dma-mapping.h>
> #include <linux/workqueue.h>
> +#include <linux/i7300_idle.h>
> #include "ioatdma.h"
> #include "ioatdma_registers.h"
> #include "ioatdma_hw.h"
> @@ -172,7 +173,9 @@ static int ioat_dma_enumerate_channels(s
> xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
>
> #if CONFIG_I7300_IDLE_IOAT_CHANNEL
> - device->common.chancnt--;
> + if (i7300_idle_platform_probe(NULL, NULL) == 0) {
> + device->common.chancnt--;
> + }
> #endif
> for (i = 0; i < device->common.chancnt; i++) {
> ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL);