Skip to contentSkip to conversation

ACPI patches for 2.6.25-rc0

PATCH In review Len Brown 5 participants 123 messages Feb 7, 2008 – Feb 12, 2008 Page 1 of 2

Subsystems (15)
Documentation x86 VFS ACPI +11 more subsystems
lore
Share & tools
lore

Len Brown

author reviewer
#0 lore raw

This is the ACPI patch queue for 2.6.25-rc0

author reviewer
#1 lore raw

PATCH 1/112 ACPI: add control method tracing support

From: Zhang Rui <[email protected]>

Add debug tracing support during certain AML method execution.

Four more module parameters are created under /sys/module/acpi/parameters/:
trace_method_name: the AML method name that user wants to trace

trace_debug_layer: the temporary debug_layer used when tracing the method.

			Using 0xffffffff by default if it is 0.

trace_debug_level: the temporary debug_level used when tracing the method.

			Using 0x00ffffff by default if it is 0.

trace_state: The status of the tracing feature.
"enabled" means this feature is enabled
and the AML method is traced every time it's executed. "1" means this feature is enabled and the AML method will only be traced during the next execution. "disabled" means this feature is disabled. Users can enable/disable this debug tracing feature by "echo string > /sys/module/acpi/parameters/trace_state". "string" should be one of "enable", "disable" and "1".

http://bugzilla.kernel.org/show_bug.cgi?id=6629

---
 drivers/acpi/debug.c |   57 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 57 insertions(+), 0 deletions(-)
drivers/acpi/debug.c +57 -0
index bf513e0..6df564f 100644
@@ -130,6 +130,63 @@ static int param_get_debug_level(char *buffer, struct kernel_param *kp) {
 module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644);
 module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644);
 
+static char trace_method_name[6];
+module_param_string(trace_method_name, trace_method_name, 6, 0644);
+static unsigned int trace_debug_layer;
+module_param(trace_debug_layer, uint, 0644);
+static unsigned int trace_debug_level;
+module_param(trace_debug_level, uint, 0644);
+
+static int param_set_trace_state(const char *val, struct kernel_param *kp)
+{
+	int result = 0;
+
+	if (!strncmp(val, "enable", strlen("enable") - 1)) {
+		result = acpi_debug_trace(trace_method_name, trace_debug_level,
+					  trace_debug_layer, 0);
+		if (result)
+			result = -EBUSY;
+		goto exit;
+	}
+
+	if (!strncmp(val, "disable", strlen("disable") - 1)) {
+		int name = 0;
+		result = acpi_debug_trace((char *)&name, trace_debug_level,
+					  trace_debug_layer, 0);
+		if (result)
+			result = -EBUSY;
+		goto exit;
+	}
+
+	if (!strncmp(val, "1", 1)) {
+		result = acpi_debug_trace(trace_method_name, trace_debug_level,
+					  trace_debug_layer, 1);
+		if (result)
+			result = -EBUSY;
+		goto exit;
+	}
+
+	result = -EINVAL;
+exit:
+	return result;
+}
+
+static int param_get_trace_state(char *buffer, struct kernel_param *kp)
+{
+	if (!acpi_gbl_trace_method_name)
+		return sprintf(buffer, "disable");
+	else {
+		if (acpi_gbl_trace_flags & 1)
+			return sprintf(buffer, "1");
+		else
+			return sprintf(buffer, "enable");
+	}
+	return 0;
+}
+
+module_param_call(trace_state, param_set_trace_state, param_get_trace_state,
+		  NULL, 0644);
+
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
    -------------------------------------------------------------------------- */
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#2 lore raw

PATCH 2/112 ACPI: document method tracing hooks

In reply to Len Brown

From: Len Brown <[email protected]>

---
 Documentation/00-INDEX                |    3 +++
 Documentation/acpi/method-tracing.txt |   26 ++++++++++++++++++++++++++
 2 files changed, 29 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/acpi/method-tracing.txt
Documentation/00-INDEX +3 -0
index 299615d..161edbc 100644
@@ -14,6 +14,7 @@ Following translations are available on the WWW:
 	- this file.
 ABI/
 	- info on kernel <-> userspace ABI and relative interface stability.
+
 BUG-HUNTING
 	- brute force method of doing binary search of patches to find bug.
 Changes
@@ -66,6 +67,8 @@ VGA-softcursor.txt
 	- how to change your VGA cursor from a blinking underscore.
 accounting/
 	- documentation on accounting and taskstats.
+acpi/
+	- info on ACPI-specific hooks in the kernel.
 aoe/
 	- description of AoE (ATA over Ethernet) along with config examples.
 applying-patches.txt
Documentation/acpi/method-tracing.txt new file +26 -0
new file mode 100644
index 0000000..f6efb1e
@@ -0,0 +1,26 @@
+/sys/module/acpi/parameters/:
+
+trace_method_name
+	The AML method name that the user wants to trace
+
+trace_debug_layer
+	The temporary debug_layer used when tracing the method.
+	Using 0xffffffff by default if it is 0.
+
+trace_debug_level
+	The temporary debug_level used when tracing the method.
+	Using 0x00ffffff by default if it is 0.
+
+trace_state
+	The status of the tracing feature.
+
+	"enabled" means this feature is enabled
+	and the AML method is traced every time it's executed.
+
+	"1" means this feature is enabled and the AML method
+	will only be traced during the next execution.
+
+	"disabled" means this feature is disabled.
+	Users can enable/disable this debug tracing feature by
+	"echo string > /sys/module/acpi/parameters/trace_state".
+	"string" should be one of "enable", "disable" and "1".
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#3 lore raw

PATCH 3/112 ACPI: CONFIG_CPU_IDLE=ACPI by default

In reply to Len Brown

From: [email protected] <[email protected]>

In Linux-2.6.24, CPU_IDLE went upstream, default =n. For Linux-2.6.25, enable it by default on ACPI systems. For Linux-2.6.26, we plan to enable it always on ACPI systems.

---
 drivers/cpuidle/Kconfig |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/cpuidle/Kconfig +2 -2
index 3bed412..7dbc4a8 100644
@@ -1,13 +1,13 @@
 
 config CPU_IDLE
 	bool "CPU idle PM support"
+	default ACPI
 	help
 	  CPU idle is a generic framework for supporting software-controlled
 	  idle processor power management.  It includes modular cross-platform
 	  governors that can be swapped during runtime.
 
-	  If you're using a mobile platform that supports CPU idle PM (e.g.
-	  an ACPI-capable notebook), you should say Y here.
+	  If you're using an ACPI-enabled platform, you should say Y here.
 
 config CPU_IDLE_GOV_LADDER
 	bool
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#4 lore raw

PATCH 4/112 ACPI: disable stray GPE, prevent ACPI interrupt storm

In reply to Len Brown

From: Zhang Rui <[email protected]>

GPEs are disabled depending on their type -- WAKE, WAKE_RUN, and RUNTIME. An error is returned if we are asked to disable a GPE that has no type.

But at least one system exists that enables a GPE from AML that is not the EC GPE, and has no _Lxx/_Exx AML handler, and is thus never initialized.

In this case, when an external CRT is plugged in, the GPE fires, we attempt to disable the GPE,
but instead just return an error.
So the GPE stays asserted and an ACPI interrupt storm follows.

The fix is to disable a firing GPE,
even if it comes from outer space.

http://bugzilla.kernel.org/show_bug.cgi?id=6217

---
 drivers/acpi/events/evgpe.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)
drivers/acpi/events/evgpe.c +4 -4
index e22f4a9..056b788 100644
@@ -270,18 +270,18 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
 	case ACPI_GPE_TYPE_WAKE_RUN:
 		ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
 
-		/*lint -fallthrough */
+		/* fallthrough */
 
 	case ACPI_GPE_TYPE_RUNTIME:
 
 		/* Disable the requested runtime GPE */
 
 		ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
-		status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
-		break;
+
+		/* fallthrough */
 
 	default:
-		return_ACPI_STATUS(AE_BAD_PARAMETER);
+		acpi_hw_write_gpe_enable_reg(gpe_event_info);
 	}
 
 	return_ACPI_STATUS(AE_OK);
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#5 lore raw

PATCH 5/112 Revert "speedstep-lib.c: fix frequency multiplier for Pentium4 models 0&1"

In reply to Len Brown

From: Zhao Yakui <[email protected]>

For P4 model < 2, The MSR_FBC_REGISTER_ID ratio is undefined. Revert the commit that was added to handle that case, as it results in random MHz displayed. Something else will have to be done to properly handle model < 2.

//commit 3e4159ab35c88aef5e063ba78796b277b762a30a //Author: matthias.christian <matthias.christian>
//Date: Sat Feb 5 23:09:38 2005 +0000
//
// [PATCH] speedstep-lib.c: fix frequency multiplier for Pentium4 models 0&1
//
// The Pentium4 models 0&1 have a longer MSR_EBC_FREQUENCY_ID register as the
// models 2&3, so the bit shift must be bigger.
//

//    Signed-off-by: Matthias-Christian Ott <[email protected]>
//    Signed-off-by: Dominik Brodowski <[email protected]>
//    Signed-off-by: Andrew Morton <[email protected]>
//    Signed-off-by: Linus Torvalds <[email protected]>

//
// BKrev: 42055232eWM-NgjhZVir44mp5GXktQ

http://bugzilla.kernel.org/show_bug.cgi?id=7186

---
 arch/x86/kernel/cpu/cpufreq/speedstep-lib.c |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)
arch/x86/kernel/cpu/cpufreq/speedstep-lib.c +1 -4
index 76c3ab0..98d4fdb 100644
@@ -189,10 +189,7 @@ static unsigned int pentium4_get_frequency(void)
 		printk(KERN_DEBUG "speedstep-lib: couldn't detect FSB speed. Please send an e-mail to <[email protected]>\n");
 
 	/* Multiplier. */
-	if (c->x86_model < 2)
-		mult = msr_lo >> 27;
-	else
-		mult = msr_lo >> 24;
+	mult = msr_lo >> 24;
 
 	dprintk("P4 - FSB %u kHz; Multiplier %u; Speed %u kHz\n", fsb, mult, (fsb * mult));
 
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#6 lore raw

PATCH 6/112 ACPI: Defer enabling of level GPE until all pending notifies done

In reply to Len Brown

From: Alexey Starikovskiy <[email protected]>

Level GPE should not be enabled until all work caused by it is done, e.g. all Notify() methods are completed.
This can be accomplished by appending enable_gpe function to the end of notify queue.

---
 drivers/acpi/events/evgpe.c |   17 +++++++++++++----
 drivers/acpi/osl.c          |   42 ++++++++----------------------------------
 2 files changed, 21 insertions(+), 38 deletions(-)
drivers/acpi/events/evgpe.c +13 -4
index e22f4a9..b4509f9 100644
@@ -501,6 +501,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
  *              an interrupt handler.
  *
  ******************************************************************************/
+static void acpi_ev_asynch_enable_gpe(void *context);
 
 static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
 {
@@ -576,22 +577,30 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
 					 method_node)));
 		}
 	}
+	/* Defer enabling of GPE until all notify handlers are done */
+	acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_asynch_enable_gpe,
+				gpe_event_info);
+	return_VOID;
+}
 
-	if ((local_gpe_event_info.flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
+static void acpi_ev_asynch_enable_gpe(void *context)
+{
+	struct acpi_gpe_event_info *gpe_event_info = context;
+	acpi_status status;
+	if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
 	    ACPI_GPE_LEVEL_TRIGGERED) {
 		/*
 		 * GPE is level-triggered, we clear the GPE status bit after
 		 * handling the event.
 		 */
-		status = acpi_hw_clear_gpe(&local_gpe_event_info);
+		status = acpi_hw_clear_gpe(gpe_event_info);
 		if (ACPI_FAILURE(status)) {
 			return_VOID;
 		}
 	}
 
 	/* Enable this GPE */
-
-	(void)acpi_hw_write_gpe_enable_reg(&local_gpe_event_info);
+	(void)acpi_hw_write_gpe_enable_reg(gpe_event_info);
 	return_VOID;
 }
 
drivers/acpi/osl.c +8 -34

60 lines not on this page · raw message

Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#7 lore raw

PATCH 7/112 export thermal notification to userspace when nocrt is set

In reply to Len Brown

From: Zhang Rui <[email protected]>

module parameter is used to prevent the thermal_zone action upon critical trip points.
But exporting this notification to userspace is still useful. By setting nocrt with this patch applied, ACPI will take no action but exporting the events to userspace upon critical/hot trip points.

http://bugzilla.kernel.org/show_bug.cgi?id=9139

---
 drivers/acpi/thermal.c |   17 ++++++++++-------
 1 files changed, 10 insertions(+), 7 deletions(-)
drivers/acpi/thermal.c +10 -7
index 5f79b44..3a0af9a 100644
@@ -492,7 +492,7 @@ static int acpi_thermal_get_devices(struct acpi_thermal *tz)
 
 static int acpi_thermal_critical(struct acpi_thermal *tz)
 {
-	if (!tz || !tz->trips.critical.flags.valid || nocrt)
+	if (!tz || !tz->trips.critical.flags.valid)
 		return -EINVAL;
 
 	if (tz->temperature >= tz->trips.critical.temperature) {
@@ -501,9 +501,6 @@ static int acpi_thermal_critical(struct acpi_thermal *tz)
 	} else if (tz->trips.critical.flags.enabled)
 		tz->trips.critical.flags.enabled = 0;
 
-	printk(KERN_EMERG
-	       "Critical temperature reached (%ld C), shutting down.\n",
-	       KELVIN_TO_CELSIUS(tz->temperature));
 	acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL,
 				tz->trips.critical.flags.enabled);
 	acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
@@ -511,14 +508,20 @@ static int acpi_thermal_critical(struct acpi_thermal *tz)
 					  ACPI_THERMAL_NOTIFY_CRITICAL,
 					  tz->trips.critical.flags.enabled);
 
-	orderly_poweroff(true);
+	/* take no action if nocrt is set */
+	if(!nocrt) {
+		printk(KERN_EMERG
+			"Critical temperature reached (%ld C), shutting down.\n",
+			KELVIN_TO_CELSIUS(tz->temperature));
+		orderly_poweroff(true);
+	}
 
 	return 0;
 }
 
 static int acpi_thermal_hot(struct acpi_thermal *tz)
 {
-	if (!tz || !tz->trips.hot.flags.valid || nocrt)
+	if (!tz || !tz->trips.hot.flags.valid)
 		return -EINVAL;
 
 	if (tz->temperature >= tz->trips.hot.temperature) {
@@ -534,7 +537,7 @@ static int acpi_thermal_hot(struct acpi_thermal *tz)
 					  ACPI_THERMAL_NOTIFY_HOT,
 					  tz->trips.hot.flags.enabled);
 
-	/* TBD: Call user-mode "sleep(S4)" function */
+	/* TBD: Call user-mode "sleep(S4)" function if nocrt is cleared */
 
 	return 0;
 }
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#8 lore raw

PATCH 8/112 ACPI: Fix autloading of dock, video, bay and all linux specific HID drivers

In reply to Len Brown

From: Frank Seidel <[email protected]>

References: https://bugzilla.novell.com/show_bug.cgi?id=302482

Due to the new autloading of acpi drivers, the dock driver wasn't loaded anymore as there is no HID to identify it with (dock is needed if ACPI has a _DCK method).
This patch is a workaround for this, original by Thomas Renninger, revised first by Kay Sievers and last by Frank Seidel.
V2 of this patch fixed problems on systems without a defined _CID for the docking devices.

---
 drivers/acpi/scan.c |  100 +++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 85 insertions(+), 15 deletions(-)
drivers/acpi/scan.c +85 -15
index 5b4d462..bf07926 100644
@@ -941,6 +941,15 @@ static int acpi_bay_match(struct acpi_device *device){
 	return -ENODEV;
 }
 
+/*
+ * acpi_dock_match - see if a device has a _DCK method
+ */
+static int acpi_dock_match(struct acpi_device *device)
+{
+	acpi_handle tmp;
+	return acpi_get_handle(device->handle, "_DCK", &tmp);
+}
+
 static void acpi_device_set_id(struct acpi_device *device,
 			       struct acpi_device *parent, acpi_handle handle,
 			       int type)
@@ -950,6 +959,7 @@ static void acpi_device_set_id(struct acpi_device *device,
 	char *hid = NULL;
 	char *uid = NULL;
 	struct acpi_compatible_id_list *cid_list = NULL;
+	const char *cid_add = NULL;
 	acpi_status status;
 
 	switch (type) {
@@ -972,15 +982,18 @@ static void acpi_device_set_id(struct acpi_device *device,
 			device->flags.bus_address = 1;
 		}
 
-		if(!(info->valid & (ACPI_VALID_HID | ACPI_VALID_CID))){
-			status = acpi_video_bus_match(device);
-			if(ACPI_SUCCESS(status))
-				hid = ACPI_VIDEO_HID;
+		/* If we have a video/bay/dock device, add our selfdefined
+		   HID to the CID list. Like that the video/bay/dock drivers
+		   will get autoloaded and the device might still match
+		   against another driver.
+		*/
+		if (ACPI_SUCCESS(acpi_video_bus_match(device)))
+			cid_add = ACPI_VIDEO_HID;
+		else if (ACPI_SUCCESS(acpi_bay_match(device)))
+			cid_add = ACPI_BAY_HID;
+		else if (ACPI_SUCCESS(acpi_dock_match(device)))
+			cid_add = ACPI_DOCK_HID;
 
-			status = acpi_bay_match(device);
-			if (ACPI_SUCCESS(status))
-				hid = ACPI_BAY_HID;
-		}
 		break;
 	case ACPI_BUS_TYPE_POWER:
 		hid = ACPI_POWER_HID;
@@ -1021,11 +1034,44 @@ static void acpi_device_set_id(struct acpi_device *device,
 		strcpy(device->pnp.unique_id, uid);
 		device->flags.unique_id = 1;
 	}
-	if (cid_list) {
-		device->pnp.cid_list = kmalloc(cid_list->size, GFP_KERNEL);
-		if (device->pnp.cid_list)
-			memcpy(device->pnp.cid_list, cid_list, cid_list->size);
-		else
+	if (cid_list || cid_add) {
+		struct  acpi_compatible_id_list *list;
+		int size = 0;
+		int count = 0;
+
+		if (cid_list) {
+			size = cid_list->size;
+		} else if (cid_add) {
+			size = sizeof(struct acpi_compatible_id_list);
+			cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size);
+			if (!cid_list) {
+				printk(KERN_ERR "Memory allocation error\n");
+				kfree(buffer.pointer);
+				return;
+			} else {
+				cid_list->count = 0;
+				cid_list->size = size;
+			}
+		}
+		if (cid_add)
+			size += sizeof(struct acpi_compatible_id);
+		list = kmalloc(size, GFP_KERNEL);
+
+		if (list) {
+			if (cid_list) {
+				memcpy(list, cid_list, cid_list->size);
+				count = cid_list->count;
+			}
+			if (cid_add) {
+				strncpy(list->id[count].value, cid_add,
+					ACPI_MAX_CID_LENGTH);
+				count++;
+				device->flags.compatible_ids = 1;
+			}
+			list->size = size;
+			list->count = count;
+			device->pnp.cid_list = list;
+		} else
 			printk(KERN_ERR "Memory allocation error\n");
 	}
 
@@ -1081,6 +1127,20 @@ 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)
@@ -1131,10 +1191,20 @@ acpi_add_single_object(struct acpi_device **child,
 	case ACPI_BUS_TYPE_PROCESSOR:
 	case ACPI_BUS_TYPE_DEVICE:
 		result = acpi_bus_get_status(device);
-		if (ACPI_FAILURE(result) || !device->status.present) {
-			result = -ENOENT;
+		if (ACPI_FAILURE(result)) {
+			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;
+			}
+		}
 		break;
 	default:
 		STRUCT_TO_INT(device->status) =
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#9 lore raw

PATCH 9/112 ACPI: Add autoload info to dock driver

In reply to Len Brown

From: Frank Seidel <[email protected]>

References: https://bugzilla.novell.com/show_bug.cgi?id=302482

---
 drivers/acpi/dock.c         |    6 ++++++
 include/acpi/acpi_drivers.h |    1 +
 2 files changed, 7 insertions(+), 0 deletions(-)
drivers/acpi/dock.c +6 -0
index 1dabdf4..b3dec21 100644
@@ -51,6 +51,12 @@ 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[] = {
+	{"LNXDOCK", 0},
+	{"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, dock_device_ids);
+
 struct dock_station {
 	acpi_handle handle;
 	unsigned long last_dock_time;
include/acpi/acpi_drivers.h +1 -0
index f85f77a..581daa4 100644
@@ -48,6 +48,7 @@
 #define ACPI_BUTTON_HID_SLEEPF		"LNXSLPBN"
 #define ACPI_VIDEO_HID			"LNXVIDEO"
 #define ACPI_BAY_HID			"LNXIOBAY"
+#define ACPI_DOCK_HID			"LNXDOCK"
 
 /* --------------------------------------------------------------------------
                                        PCI
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#10 lore raw

PATCH 10/112 ACPI: Also autoload the bay driver, was forgotten...

In reply to Len Brown

From: Thomas Renninger <[email protected]>

---
 drivers/acpi/bay.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)
drivers/acpi/bay.c +6 -0
index 6daf608..4777114 100644
@@ -46,6 +46,12 @@ MODULE_LICENSE("GPL");
 	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;
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#11 lore raw

PATCH 11/112 acpi: make __acpi_map_table() and __init function

In reply to Len Brown

From: Jan Beulich <[email protected]>

.. as it it used only during early boot.

 arch/ia64/kernel/acpi.c     |    2 +-
 arch/x86/kernel/acpi/boot.c |    4 ++--
 drivers/acpi/osl.c          |    3 ++-
 3 files changed, 5 insertions(+), 4 deletions(-)
---
 arch/ia64/kernel/acpi.c     |    2 +-
 arch/x86/kernel/acpi/boot.c |    4 ++--
 drivers/acpi/osl.c          |    3 ++-
 3 files changed, 5 insertions(+), 4 deletions(-)
arch/ia64/kernel/acpi.c +1 -1
index 00b5d08..f932c48 100644
@@ -152,7 +152,7 @@ int acpi_request_vector(u32 int_type)
 	return vector;
 }
 
-char *__acpi_map_table(unsigned long phys_addr, unsigned long size)
+char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size)
 {
 	return __va(phys_addr);
 }
arch/x86/kernel/acpi/boot.c +2 -2
index 0ca27c7..b595522 100644
@@ -106,7 +106,7 @@ enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC;
 #ifdef	CONFIG_X86_64
 
 /* rely on all ACPI tables being in the direct mapping */
-char *__acpi_map_table(unsigned long phys_addr, unsigned long size)
+char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size)
 {
 	if (!phys_addr || !size)
 		return NULL;
@@ -131,7 +131,7 @@ char *__acpi_map_table(unsigned long phys_addr, unsigned long size)
  * from the fixed base.  That's why we start at FIX_IO_APIC_BASE_END and
  * count idx down while incrementing the phys address.
  */
-char *__acpi_map_table(unsigned long phys, unsigned long size)
+char *__init __acpi_map_table(unsigned long phys, unsigned long size)
 {
 	unsigned long base, offset, mapped_size;
 	int idx;
drivers/acpi/osl.c +2 -1
index e3a673a..82525d9 100644
@@ -211,7 +211,8 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
 		return acpi_find_rsdp();
 }
 
-void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
+void __iomem *__init_refok
+acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
 {
 	if (phys > ULONG_MAX) {
 		printk(KERN_ERR PREFIX "Cannot map memory that high\n");
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#12 lore raw

PATCH 12/112 cpuidle: create processor.latency_factor tunable

In reply to Len Brown

From: Len Brown <[email protected]>

Start with default value of 6, so by default,
there is no functional change in this patch.

---
 drivers/acpi/processor_idle.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)
drivers/acpi/processor_idle.c +4 -1
index f996d0e..26ade1f 100644
@@ -94,6 +94,9 @@ module_param(bm_history, uint, 0644);
 
 static int acpi_processor_set_power_policy(struct acpi_processor *pr);
 
+#else	/* CONFIG_CPU_IDLE */
+static unsigned int latency_factor __read_mostly = 6;
+module_param(latency_factor, uint, 0644);
 #endif
 
 /*
@@ -1576,7 +1579,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
 
 		snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i);
 		state->exit_latency = cx->latency;
-		state->target_residency = cx->latency * 6;
+		state->target_residency = cx->latency * latency_factor;
 		state->power_usage = cx->power;
 
 		state->flags = 0;
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#13 lore raw

PATCH 13/112 cpuidle: default processor.latency_factor=2

In reply to Len Brown

From: Len Brown <[email protected]>

More aggressively request deep C-states.

Note that the job of the OS is to minimize latency impact to expected break events such as interrupts.

It is not the job of the OS to try to calculate if the C-state will reach energy break-even. The platform doesn't give the OS enough information for it to make that calculation. Thus, it is up to the platform to decide if it is worth it to go as deep as the OS requested it to, or if it should internally demote to a more shallow C-state.

But the converse is not true. The platform can not promote into a deeper C-state than the OS requested else it may violate latency constraints. So it is important that the OS be aggressive in giving the platform permission to enter deep C-states.

---
 drivers/acpi/processor_idle.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/acpi/processor_idle.c +1 -1
index 26ade1f..bc99b7b 100644
@@ -95,7 +95,7 @@ module_param(bm_history, uint, 0644);
 static int acpi_processor_set_power_policy(struct acpi_processor *pr);
 
 #else	/* CONFIG_CPU_IDLE */
-static unsigned int latency_factor __read_mostly = 6;
+static unsigned int latency_factor __read_mostly = 2;
 module_param(latency_factor, uint, 0644);
 #endif
 
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#14 lore raw

PATCH 14/112 ACPI: tables: complete searching upon RSDP w/ bad checksum.

In reply to Len Brown

From: Len Brown <[email protected]>

ACPI tables follow a tree structure in memory.
The root of the tree is the RSDP (Root System Description Pointer).

To find the RSDP, the OS searches for the signature "RSD PTR " in well known physical memory locations. Then the OS computes a table checksum to verify that the signature is really part of a valid table header.

Some systems have a proper signature but an invalid checksum; followed elsewhere by a proper signature with valid checksum.

http://bugzilla.kernel.org/show_bug.cgi?id=9444

The Linux RSDP scanning code bailed out on those systems and as a result they booted with ACPI disabled.

Fix this by deleting the Linux RSDP scanning code and plugging in the ACPICA RSDP scanning code.

---
 arch/ia64/kernel/acpi.c        |   26 ++++++++++++++------------
 arch/x86/kernel/acpi/boot.c    |   40 ----------------------------------------
 arch/x86/kernel/srat_32.c      |    2 +-
 drivers/acpi/osl.c             |    8 ++++++--
 drivers/acpi/tables/Makefile   |    2 +-
 drivers/acpi/tables/tbxfroot.c |    4 +---
 include/linux/acpi.h           |    1 -
 7 files changed, 23 insertions(+), 60 deletions(-)
arch/ia64/kernel/acpi.c +14 -12
index 897e208..63d6dcd 100644
@@ -69,6 +69,20 @@ unsigned int acpi_cpei_phys_cpuid;
 
 unsigned long acpi_wakeup_address = 0;
 
+#ifdef CONFIG_IA64_GENERIC
+static unsigned long __init acpi_find_rsdp(void)
+{
+	unsigned long rsdp_phys = 0;
+
+	if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
+		rsdp_phys = efi.acpi20;
+	else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
+		printk(KERN_WARNING PREFIX
+		       "v1.0/r0.71 tables no longer supported\n");
+	return rsdp_phys;
+}
+#endif
+
 const char __init *
 acpi_get_sysname(void)
 {
@@ -631,18 +645,6 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
 	return 0;
 }
 
-unsigned long __init acpi_find_rsdp(void)
-{
-	unsigned long rsdp_phys = 0;
-
-	if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
-		rsdp_phys = efi.acpi20;
-	else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
-		printk(KERN_WARNING PREFIX
-		       "v1.0/r0.71 tables no longer supported\n");
-	return rsdp_phys;
-}
-
 int __init acpi_boot_init(void)
 {
 
arch/x86/kernel/acpi/boot.c +0 -40
index 0ca27c7..719c74b 100644
@@ -581,25 +581,6 @@ int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
 
 EXPORT_SYMBOL(acpi_unregister_ioapic);
 
-static unsigned long __init
-acpi_scan_rsdp(unsigned long start, unsigned long length)
-{
-	unsigned long offset = 0;
-	unsigned long sig_len = sizeof("RSD PTR ") - 1;
-
-	/*
-	 * Scan all 16-byte boundaries of the physical memory region for the
-	 * RSDP signature.
-	 */
-	for (offset = 0; offset < length; offset += 16) {
-		if (strncmp((char *)(phys_to_virt(start) + offset), "RSD PTR ", sig_len))
-			continue;
-		return (start + offset);
-	}
-
-	return 0;
-}
-
 static int __init acpi_parse_sbf(struct acpi_table_header *table)
 {
 	struct acpi_table_boot *sb;
@@ -742,27 +723,6 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
 	return 0;
 }
 
-unsigned long __init acpi_find_rsdp(void)
-{
-	unsigned long rsdp_phys = 0;
-
-	if (efi_enabled) {
-		if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
-			return efi.acpi20;
-		else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
-			return efi.acpi;
-	}
-	/*
-	 * Scan memory looking for the RSDP signature. First search EBDA (low
-	 * memory) paragraphs and then search upper memory (E0000-FFFFF).
-	 */
-	rsdp_phys = acpi_scan_rsdp(0, 0x400);
-	if (!rsdp_phys)
-		rsdp_phys = acpi_scan_rsdp(0xE0000, 0x20000);
-
-	return rsdp_phys;
-}
-
 #ifdef	CONFIG_X86_LOCAL_APIC
 /*
  * Parse LAPIC entries in MADT
arch/x86/kernel/srat_32.c +1 -1
index 2a8713e..b3b2c95 100644
@@ -276,7 +276,7 @@ int __init get_memcfg_from_srat(void)
 	int tables = 0;
 	int i = 0;
 
-	rsdp_address = acpi_find_rsdp();
+	rsdp_address = acpi_os_get_root_pointer();
 	if (!rsdp_address) {
 		printk("%s: System description tables not found\n",
 		       __FUNCTION__);
drivers/acpi/osl.c +6 -2
index aabc6ca..101691e 100644
@@ -207,8 +207,12 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
 			       "System description tables not found\n");
 			return 0;
 		}
-	} else
-		return acpi_find_rsdp();
+	} else {
+		acpi_physical_address pa = 0;
+
+		acpi_find_root_pointer(&pa);
+		return pa;
+	}
 }
 
 void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
drivers/acpi/tables/Makefile +1 -1
index 0a7d7af..7385efa 100644
@@ -2,6 +2,6 @@
 # Makefile for all Linux ACPI interpreter subdirectories
 #
 
-obj-y := tbxface.o tbinstal.o  tbutils.o tbfind.o tbfadt.o
+obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
 
 EXTRA_CFLAGS += $(ACPI_CFLAGS)
drivers/acpi/tables/tbxfroot.c +1 -3
index cf8fa51..9ecb4b6 100644
@@ -100,7 +100,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_tb_find_rsdp
+ * FUNCTION:    acpi_find_root_pointer
  *
  * PARAMETERS:  table_address           - Where the table pointer is returned
  *
@@ -219,8 +219,6 @@ acpi_status acpi_find_root_pointer(acpi_native_uint * table_address)
 	return_ACPI_STATUS(AE_NOT_FOUND);
 }
 
-ACPI_EXPORT_SYMBOL(acpi_find_root_pointer)
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_tb_scan_memory_for_rsdp
include/linux/acpi.h +0 -1
index 8ccedf7..8deb611 100644
@@ -79,7 +79,6 @@ typedef int (*acpi_table_handler) (struct acpi_table_header *table);
 typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
 
 char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
-unsigned long acpi_find_rsdp (void);
 int acpi_boot_init (void);
 int acpi_boot_table_init (void);
 int acpi_numa_init (void);
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#15 lore raw

PATCH 15/112 ACPI: /proc/acpi/alarm parsing: handle large numbers properly

In reply to Len Brown

From: Yi Yang <[email protected]>

In function acpi_system_write_alarm in file drivers/acpi/sleep/proc.c, big sec, min, hr, mo, day and yr are counted twice to get reasonable values, that is very superfluous, we can do that only once.

In additon, /proc/acpi/alarm can set a related value which can be specified as YYYY years MM months DD days HH hours MM minutes SS senconds, it isn't a date, so you can specify as +0000-00-00 96:00:00 , that means 3 days later, current code can't handle such a case.

This patch removes unnecessary code and does with the aforementioned situation.

Before applying this patch:

[root@localhost /]# cat /proc/acpi/alarm
2007-12-00 00:00:00
[root@localhost /]# echo "0000-00-00 96:180:180" > /proc/acpi/alarm [root@localhost /]# cat /proc/acpi/alarm
0007-12-02 **:**:**
[root@localhost /]#

After applying this patch:

[root@localhost ~]# echo "2007-12-00 00:00:00" > /proc/acpi/alarm [root@localhost ~]# cat /proc/acpi/alarm
2007-12-00 00:00:00
[root@localhost ~]# echo "0000-00-00 96:180:180" > /proc/acpi/alarm [root@localhost ~]# cat /proc/acpi/alarm
0007-12-04 03:03:00
[root@localhost ~]#

---
 drivers/acpi/sleep/proc.c |   41 ++++++++++-------------------------------
 1 files changed, 10 insertions(+), 31 deletions(-)
drivers/acpi/sleep/proc.c +10 -31
index 1538355..e19eb0c 100644
@@ -251,27 +251,6 @@ acpi_system_write_alarm(struct file *file,
 	if ((result = get_date_field(&p, &sec)))
 		goto end;
 
-	if (sec > 59) {
-		min += 1;
-		sec -= 60;
-	}
-	if (min > 59) {
-		hr += 1;
-		min -= 60;
-	}
-	if (hr > 23) {
-		day += 1;
-		hr -= 24;
-	}
-	if (day > 31) {
-		mo += 1;
-		day -= 31;
-	}
-	if (mo > 12) {
-		yr += 1;
-		mo -= 12;
-	}
-
 	spin_lock_irq(&rtc_lock);
 
 	rtc_control = CMOS_READ(RTC_CONTROL);
@@ -288,24 +267,24 @@ acpi_system_write_alarm(struct file *file,
 	spin_unlock_irq(&rtc_lock);
 
 	if (sec > 59) {
-		min++;
-		sec -= 60;
+		min += sec/60;
+		sec = sec%60;
 	}
 	if (min > 59) {
-		hr++;
-		min -= 60;
+		hr += min/60;
+		min = min%60;
 	}
 	if (hr > 23) {
-		day++;
-		hr -= 24;
+		day += hr/24;
+		hr = hr%24;
 	}
 	if (day > 31) {
-		mo++;
-		day -= 31;
+		mo += day/32;
+		day = day%32;
 	}
 	if (mo > 12) {
-		yr++;
-		mo -= 12;
+		yr += mo/13;
+		mo = mo%13;
 	}
 
 	spin_lock_irq(&rtc_lock);
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#16 lore raw

PATCH 16/112 ACPI: detect invalid argument written to /proc/acpi/alarm

In reply to Len Brown

From: Signed-off by Yi Yang <[email protected]>

/proc/acpi/alarm can't be set correctly, here is a sample:

[root@localhost /]# echo "2006 09" > /proc/acpi/alarm [root@localhost /]# cat /proc/acpi/alarm 2007-12-09 09:09:09
[root@localhost /]# echo "2006 04" > /proc/acpi/alarm [root@localhost /]# cat /proc/acpi/alarm 2007-12-04 04:04:04
[root@localhost /]#

Obviously, it is wrong, it should consider it as an invalid input.

after this patch:

[root@localhost /]# echo "2008 09" > /proc/acpi/alarm -bash: echo: write error: Invalid argument [root@localhost /]#

---
 drivers/acpi/sleep/proc.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)
drivers/acpi/sleep/proc.c +5 -0
index 1538355..fce78fb 100644
@@ -178,6 +178,9 @@ static int get_date_field(char **p, u32 * value)
 	 * Try to find delimeter, only to insert null.  The end of the
 	 * string won't have one, but is still valid.
 	 */
+	if (*p == NULL)
+		return result;
+
 	next = strpbrk(*p, "- :");
 	if (next)
 		*next++ = '\0';
@@ -190,6 +193,8 @@ static int get_date_field(char **p, u32 * value)
 
 	if (next)
 		*p = next;
+	else
+		*p = NULL;
 
 	return result;
 }
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#17 lore raw

PATCH 17/112 ACPI: add "processor.ignore_ppc" hook to workaround BIOS _PPC weirdness

In reply to Len Brown

From: Thomas Renninger <[email protected]>

There have been fixes using _PPC, which seem to unhide a problem on HP nx6125 (double cpufreq switch freezes the machine for several seconds).

This one should provide a workaround for the nx6125 and for possible other machines that show any weird _PPC behaviour.

---
 drivers/acpi/processor_perflib.c |   16 +++++++++++++++-
 1 files changed, 15 insertions(+), 1 deletions(-)
drivers/acpi/processor_perflib.c +15 -1
index 463b024..f32010b 100644
@@ -60,6 +60,11 @@ static DEFINE_MUTEX(performance_mutex);
  * policy is adjusted accordingly.
  */
 
+static unsigned int ignore_ppc = 0;
+module_param(ignore_ppc, uint, 0644);
+MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \
+		 "limited by BIOS, this should help");
+
 #define PPC_REGISTERED   1
 #define PPC_IN_USE       2
 
@@ -72,6 +77,9 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb,
 	struct acpi_processor *pr;
 	unsigned int ppc = 0;
 
+	if (ignore_ppc)
+		return 0;
+
 	mutex_lock(&performance_mutex);
 
 	if (event != CPUFREQ_INCOMPATIBLE)
@@ -130,7 +138,13 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
 
 int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
 {
-	int ret = acpi_processor_get_platform_limit(pr);
+	int ret;
+
+	if (ignore_ppc)
+		return 0;
+
+	ret = acpi_processor_get_platform_limit(pr);
+
 	if (ret < 0)
 		return (ret);
 	else
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#18 lore raw

PATCH 18/112 ACPI: ACPI Exception (): AE_NOT_FOUND, Processor Device is not present

In reply to Len Brown

From: Zhang Rui <[email protected]>

ACPI Exception (acpi_processor-0677): AE_NOT_FOUND, Processor Device is not present [20060707]

According to the ACPI spec 6.3.7,
"If a device object (including the processor object) does not have an _STA object, then OSPM assumes that all of the above bits are set, (in other words, the device is present, enabled, shown in the UI and funtioning)".

is_processor_present shoud return 1 if the processor device object exists while it doesn't have an _STA object.

http://bugzilla.kernel.org/show_bug.cgi?id=8570

---
 drivers/acpi/processor_core.c |   17 ++++++++++++-----
 1 files changed, 12 insertions(+), 5 deletions(-)
drivers/acpi/processor_core.c +12 -5
index e48ee4f..c53113e 100644
@@ -812,11 +812,18 @@ static int is_processor_present(acpi_handle handle)
 
 
 	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
-	if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT)) {
-		ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present"));
-		return 0;
-	}
-	return 1;
+	/*
+	 * if a processor object does not have an _STA object,
+	 * OSPM assumes that the processor is present.
+	 */
+	if (status == AE_NOT_FOUND)
+		return 1;
+
+	if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT))
+		return 1;
+
+	ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present"));
+	return 0;
 }
 
 static
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#19 lore raw

PATCH 19/112 ACPI: EC: Do the byte access with a fast path

In reply to Len Brown

From: Alexey Starikovskiy <[email protected]>

Specification allows only byte access for EC region, so make it separate from bug-compatible multi-byte access. Also do not allow return of garbage in supplied *value.

Reference: http://bugzilla.kernel.org/show_bug.cgi?id=9341

---
 drivers/acpi/ec.c |   15 +++++++++++----
 1 files changed, 11 insertions(+), 4 deletions(-)
drivers/acpi/ec.c +11 -4
index d411017..63862df 100644
@@ -563,7 +563,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
 		      void *handler_context, void *region_context)
 {
 	struct acpi_ec *ec = handler_context;
-	int result = 0, i = 0;
+	int result = 0, i;
 	u8 temp = 0;
 
 	if ((address > 0xFF) || !value || !handler_context)
@@ -575,7 +575,16 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
 	if (bits != 8 && acpi_strict)
 		return AE_BAD_PARAMETER;
 
-	while (bits - i > 0) {
+	if (function == ACPI_READ) {
+		result = acpi_ec_read(ec, address, &temp);
+		*value = temp;
+	} else {
+		temp = 0xff & (*value);
+		result = acpi_ec_write(ec, address, temp);
+	}
+
+	for (i = 8; unlikely(bits - i > 0); i += 8) {
+		++address;
 		if (function == ACPI_READ) {
 			result = acpi_ec_read(ec, address, &temp);
 			(*value) |= ((acpi_integer)temp) << i;
@@ -583,8 +592,6 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
 			temp = 0xff & ((*value) >> i);
 			result = acpi_ec_write(ec, address, temp);
 		}
-		i += 8;
-		++address;
 	}
 
 	switch (result) {
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#20 lore raw

PATCH 20/112 ACPI: EC: Some hardware requires burst mode to operate properly

In reply to Len Brown

From: Alexey Starikovskiy <[email protected]>

Burst mode temporary (50 ms) locks EC to do only transactions with driver, without it some hardware returns abstract garbage.

Reference: http://bugzilla.kernel.org/show_bug.cgi?id=9341

---
 drivers/acpi/ec.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
drivers/acpi/ec.c +4 -0
index 63862df..445ecba 100644
@@ -575,6 +575,8 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
 	if (bits != 8 && acpi_strict)
 		return AE_BAD_PARAMETER;
 
+	acpi_ec_burst_enable(ec);
+
 	if (function == ACPI_READ) {
 		result = acpi_ec_read(ec, address, &temp);
 		*value = temp;
@@ -594,6 +596,8 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
 		}
 	}
 
+	acpi_ec_burst_disable(ec);
+
 	switch (result) {
 	case -EINVAL:
 		return AE_BAD_PARAMETER;
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#21 lore raw

PATCH 21/112 ACPI: Fix acpi_pm_device_sleep_state()

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

Fix acpi_pm_device_sleep_state() to return the value returned by _SxD if the device is supposed to wake up the system from given sleep state and the evaluation of _SxW fails (e.g. _SxW is not present).

---
 drivers/acpi/sleep/main.c |   15 ++++++++++++---
 1 files changed, 12 insertions(+), 3 deletions(-)
drivers/acpi/sleep/main.c +12 -3
index 2c0b663..99181c8 100644
@@ -386,11 +386,20 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p)
 	if (acpi_target_sleep_state == ACPI_STATE_S0 ||
 	    (wake && adev->wakeup.state.enabled &&
 	     adev->wakeup.sleep_state <= acpi_target_sleep_state)) {
+		acpi_status status;
+
 		acpi_method[3] = 'W';
-		acpi_evaluate_integer(handle, acpi_method, NULL, &d_max);
-		/* Sanity check */
-		if (d_max < d_min)
+		status = acpi_evaluate_integer(handle, acpi_method, NULL,
+						&d_max);
+		if (ACPI_FAILURE(status)) {
+			d_max = d_min;
+		} else if (d_max < d_min) {
+			/* Warn the user of the broken DSDT */
+			printk(KERN_WARNING "ACPI: Wrong value from %s\n",
+				acpi_method);
+			/* Sanitize it */
 			d_min = d_max;
+		}
 	}
 
 	if (d_min_p)
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#22 lore raw

PATCH 22/112 ACPI: remove P2B-S from blacklist.

In reply to Len Brown

From: Dave Jones <[email protected]>

According to http://bugzilla.kernel.org/show_bug.cgi?id=6933
The latest BIOS for the P2B-S works fine.
Remove it from the blacklist.

---
 drivers/acpi/blacklist.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)
drivers/acpi/blacklist.c +0 -2
index 3ec110c..7c24a8d 100644
@@ -67,8 +67,6 @@ static struct acpi_blacklist_item acpi_blacklist[] __initdata = {
 	/* IBM 600E - _ADR should return 7, but it returns 1 */
 	{"IBM   ", "TP600E  ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal,
 	 "Incorrect _ADR", 1},
-	{"ASUS\0\0", "P2B-S   ", 0, ACPI_SIG_DSDT, all_versions,
-	 "Bogus PCI routing", 1},
 
 	{""}
 };
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#23 lore raw

PATCH 23/112 pnp: Failed to activate device 00:0a - Samsung P35 XVM 1600 III

In reply to Len Brown

From: Shaohua Li <[email protected]>

PNP_WRITE requires protocol supports .set. If ACPI doesn't support _SRS, .set ismeanless, so PNP_WRITE.

---
 drivers/pnp/pnpacpi/core.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/pnp/pnpacpi/core.c +1 -1
index dada899..662b4c2 100644
@@ -183,7 +183,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
 	if (ACPI_SUCCESS(status))
 		dev->capabilities |= PNP_CONFIGURABLE;
 	dev->capabilities |= PNP_READ;
-	if (device->flags.dynamic_status)
+	if (device->flags.dynamic_status && (dev->capabilities & PNP_CONFIGURABLE))
 		dev->capabilities |= PNP_WRITE;
 	if (device->flags.removable)
 		dev->capabilities |= PNP_REMOVABLE;
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#24 lore raw

PATCH 24/112 ACPI: Check for any matching CID when walking namespace.

In reply to Len Brown

From: Andrew Patterson <[email protected]>

The callback function acpi_ns_get_device_callback called from acpi_get_devices() will check CID's if the HID does not match. This code has a bug where it requires that all CIDs match the HID. Changed the code so that any CID match will do.

---
 drivers/acpi/namespace/nsxfeval.c |   10 +++++++---
 1 files changed, 7 insertions(+), 3 deletions(-)
drivers/acpi/namespace/nsxfeval.c +7 -3
index f39fbc6..b92133f 100644
@@ -443,6 +443,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
 	struct acpica_device_id hid;
 	struct acpi_compatible_id_list *cid;
 	acpi_native_uint i;
+	int found;
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE(status)) {
@@ -496,16 +497,19 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
 
 			/* Walk the CID list */
 
+			found = 0;
 			for (i = 0; i < cid->count; i++) {
 				if (ACPI_STRNCMP(cid->id[i].value, info->hid,
 						 sizeof(struct
-							acpi_compatible_id)) !=
+							acpi_compatible_id)) ==
 				    0) {
-					ACPI_FREE(cid);
-					return (AE_OK);
+					found = 1;
+					break;
 				}
 			}
 			ACPI_FREE(cid);
+			if (!found)
+				return (AE_OK);
 		}
 	}
 
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#25 lore raw

PATCH 25/112 sony-laptop: printk more info in sony_pic_call[123]

In reply to Len Brown

From: Mattia Dongili <[email protected]>

---
 drivers/misc/sony-laptop.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)
drivers/misc/sony-laptop.c +4 -3
index b0f6803..0435b3d 100644
@@ -1451,7 +1451,7 @@ static u8 sony_pic_call1(u8 dev)
 	outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
 	v1 = inb_p(spic_dev.cur_ioport->io1.minimum + 4);
 	v2 = inb_p(spic_dev.cur_ioport->io1.minimum);
-	dprintk("sony_pic_call1: 0x%.4x\n", (v2 << 8) | v1);
+	dprintk("sony_pic_call1(0x%.2x): 0x%.4x\n", dev, (v2 << 8) | v1);
 	return v2;
 }
 
@@ -1466,7 +1466,7 @@ static u8 sony_pic_call2(u8 dev, u8 fn)
 			ITERATIONS_LONG);
 	outb(fn, spic_dev.cur_ioport->io1.minimum);
 	v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
-	dprintk("sony_pic_call2: 0x%.4x\n", v1);
+	dprintk("sony_pic_call2(0x%.2x - 0x%.2x): 0x%.4x\n", dev, fn, v1);
 	return v1;
 }
 
@@ -1481,7 +1481,8 @@ static u8 sony_pic_call3(u8 dev, u8 fn, u8 v)
 	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
 	outb(v, spic_dev.cur_ioport->io1.minimum);
 	v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
-	dprintk("sony_pic_call3: 0x%.4x\n", v1);
+	dprintk("sony_pic_call3(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n",
+			dev, fn, v, v1);
 	return v1;
 }
 
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#26 lore raw

PATCH 26/112 sony-laptop: Add Vaio N series to the special init sequence to enable Fn keys

In reply to Len Brown

From: Mattia Dongili <[email protected]>

Also the recent Vaio N series need some more calls into the DSDT to enable reporting of FN key events to be delivered to the SNC device.

---
 drivers/misc/sony-laptop.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)
drivers/misc/sony-laptop.c +9 -0
index 0435b3d..7a32b35 100644
@@ -875,6 +875,15 @@ static const struct dmi_system_id sony_nc_ids[] = {
 				DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"),
 			},
 		},
+		{
+			.ident = "Sony Vaio N Series",
+			.callback = sony_nc_C_enable,
+			.driver_data = sony_C_events,
+			.matches = {
+				DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+				DMI_MATCH(DMI_PRODUCT_NAME, "VGN-N"),
+			},
+		},
 		{ }
 };
 
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#27 lore raw

PATCH 27/112 sony-laptop: refactor model types

In reply to Len Brown

From: Mattia Dongili <[email protected]>

Create mini drivers and allow callbacks for each model to be specified.
Following patches will make use of this feature to handle specific cases instead of just executing code and hope not to break other models.

---
 drivers/misc/sony-laptop.c |  186 ++++++++++++++++++++++++-------------------
 1 files changed, 104 insertions(+), 82 deletions(-)
drivers/misc/sony-laptop.c +104 -82
index 7a32b35..a650f25 100644
@@ -1194,18 +1194,33 @@ struct sony_pic_irq {
 	struct list_head		list;
 };
 
+struct sonypi_eventtypes {
+	u8			data;
+	unsigned long		mask;
+	struct sonypi_event	*events;
+};
+
+struct device_ctrl {
+	int				model;
+	int				(*handle_irq)(void);
+	u16				evport_offset;
+	u8				has_camera;
+	u8				has_bluetooth;
+	u8				has_wwan;
+	struct sonypi_eventtypes	*event_types;
+};
+
 struct sony_pic_dev {
-	int			model;
-	u16			evport_offset;
-	u8			camera_power;
-	u8			bluetooth_power;
-	u8			wwan_power;
+	struct device_ctrl	*control;
 	struct acpi_device	*acpi_dev;
 	struct sony_pic_irq	*cur_irq;
 	struct sony_pic_ioport	*cur_ioport;
 	struct list_head	interrupts;
 	struct list_head	ioports;
 	struct mutex		lock;
+	u8			camera_power;
+	u8			bluetooth_power;
+	u8			wwan_power;
 };
 
 static struct sony_pic_dev spic_dev = {
@@ -1370,74 +1385,92 @@ static struct sonypi_event sonypi_batteryev[] = {
 	{ 0, 0 }
 };
 
-static struct sonypi_eventtypes {
-	int			model;
-	u8			data;
-	unsigned long		mask;
-	struct sonypi_event *	events;
-} sony_pic_eventtypes[] = {
-	{ SONYPI_DEVICE_TYPE1, 0, 0xffffffff, sonypi_releaseev },
-	{ SONYPI_DEVICE_TYPE1, 0x70, SONYPI_MEYE_MASK, sonypi_meyeev },
-	{ SONYPI_DEVICE_TYPE1, 0x30, SONYPI_LID_MASK, sonypi_lidev },
-	{ SONYPI_DEVICE_TYPE1, 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev },
-	{ SONYPI_DEVICE_TYPE1, 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev },
-	{ SONYPI_DEVICE_TYPE1, 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
-	{ SONYPI_DEVICE_TYPE1, 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
-	{ SONYPI_DEVICE_TYPE1, 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev },
-	{ SONYPI_DEVICE_TYPE1, 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
-	{ SONYPI_DEVICE_TYPE1, 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev },
-
-	{ SONYPI_DEVICE_TYPE2, 0, 0xffffffff, sonypi_releaseev },
-	{ SONYPI_DEVICE_TYPE2, 0x38, SONYPI_LID_MASK, sonypi_lidev },
-	{ SONYPI_DEVICE_TYPE2, 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev },
-	{ SONYPI_DEVICE_TYPE2, 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev },
-	{ SONYPI_DEVICE_TYPE2, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
-	{ SONYPI_DEVICE_TYPE2, 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
-	{ SONYPI_DEVICE_TYPE2, 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev },
-	{ SONYPI_DEVICE_TYPE2, 0x11, SONYPI_BACK_MASK, sonypi_backev },
-	{ SONYPI_DEVICE_TYPE2, 0x21, SONYPI_HELP_MASK, sonypi_helpev },
-	{ SONYPI_DEVICE_TYPE2, 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev },
-	{ SONYPI_DEVICE_TYPE2, 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev },
-	{ SONYPI_DEVICE_TYPE2, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
-	{ SONYPI_DEVICE_TYPE2, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
-	{ SONYPI_DEVICE_TYPE2, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
-
-	{ SONYPI_DEVICE_TYPE3, 0, 0xffffffff, sonypi_releaseev },
-	{ SONYPI_DEVICE_TYPE3, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
-	{ SONYPI_DEVICE_TYPE3, 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev },
-	{ SONYPI_DEVICE_TYPE3, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
-	{ SONYPI_DEVICE_TYPE3, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
-	{ SONYPI_DEVICE_TYPE3, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
-	{ 0 }
+static struct sonypi_eventtypes type1_events[] = {
+	{ 0, 0xffffffff, sonypi_releaseev },
+	{ 0x70, SONYPI_MEYE_MASK, sonypi_meyeev },
+	{ 0x30, SONYPI_LID_MASK, sonypi_lidev },
+	{ 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev },
+	{ 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev },
+	{ 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
+	{ 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
+	{ 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev },
+	{ 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
+	{ 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev },
+	{ 0 },
+};
+static struct sonypi_eventtypes type2_events[] = {
+	{ 0, 0xffffffff, sonypi_releaseev },
+	{ 0x38, SONYPI_LID_MASK, sonypi_lidev },
+	{ 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev },
+	{ 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev },
+	{ 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
+	{ 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
+	{ 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev },
+	{ 0x11, SONYPI_BACK_MASK, sonypi_backev },
+	{ 0x21, SONYPI_HELP_MASK, sonypi_helpev },
+	{ 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev },
+	{ 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev },
+	{ 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
+	{ 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
+	{ 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
+	{ 0 },
+};
+static struct sonypi_eventtypes type3_events[] = {
+	{ 0, 0xffffffff, sonypi_releaseev },
+	{ 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
+	{ 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev },
+	{ 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
+	{ 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
+	{ 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
+	{ 0 },
 };
 
-static int sony_pic_detect_device_type(void)
+static struct device_ctrl spic_types[] = {
+	{
+		.model = SONYPI_DEVICE_TYPE1,
+		.handle_irq = NULL,
+		.evport_offset = SONYPI_TYPE1_OFFSET,
+		.event_types = type1_events,
+	},
+	{
+		.model = SONYPI_DEVICE_TYPE2,
+		.handle_irq = NULL,
+		.evport_offset = SONYPI_TYPE2_OFFSET,
+		.event_types = type2_events,
+	},
+	{
+		.model = SONYPI_DEVICE_TYPE3,
+		.handle_irq = NULL,
+		.evport_offset = SONYPI_TYPE3_OFFSET,
+		.event_types = type3_events,
+	},
+};
+
+static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
 {
 	struct pci_dev *pcidev;
-	int model = 0;
 
 	if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
 				     PCI_DEVICE_ID_INTEL_82371AB_3, NULL)))
-		model = SONYPI_DEVICE_TYPE1;
+		dev->control = &spic_types[0];
 
 	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
 					  PCI_DEVICE_ID_INTEL_ICH6_1, NULL)))
-		model = SONYPI_DEVICE_TYPE3;
+		dev->control = &spic_types[2];
 
 	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
 					  PCI_DEVICE_ID_INTEL_ICH7_1, NULL)))
-		model = SONYPI_DEVICE_TYPE3;
+		dev->control = &spic_types[2];
 
 	else
-		model = SONYPI_DEVICE_TYPE2;
+		dev->control = &spic_types[1];
 
 	if (pcidev)
 		pci_dev_put(pcidev);
 
 	printk(KERN_INFO DRV_PFX "detected Type%d model\n",
-			model == SONYPI_DEVICE_TYPE1 ? 1 :
-			model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
-	return model;
+			dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 :
+			dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
 }
 
 #define ITERATIONS_LONG		10000
@@ -2263,7 +2296,7 @@ static int sony_pic_enable(struct acpi_device *device,
 	buffer.pointer = resource;
 
 	/* setup Type 1 resources */
-	if (spic_dev.model == SONYPI_DEVICE_TYPE1) {
+	if (spic_dev.control->model == SONYPI_DEVICE_TYPE1) {
 
 		/* setup io resources */
 		resource->res1.type = ACPI_RESOURCE_TYPE_IO;
@@ -2345,39 +2378,42 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id)
 	if (dev->cur_ioport->io2.minimum)
 		data_mask = inb_p(dev->cur_ioport->io2.minimum);
 	else
-		data_mask = inb_p(dev->cur_ioport->io1.minimum + dev->evport_offset);
+		data_mask = inb_p(dev->cur_ioport->io1.minimum +
+				dev->control->evport_offset);
 
 	dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
-			ev, data_mask, dev->cur_ioport->io1.minimum, dev->evport_offset);
+			ev, data_mask, dev->cur_ioport->io1.minimum,
+			dev->control->evport_offset);
 
 	if (ev == 0x00 || ev == 0xff)
 		return IRQ_HANDLED;
 
-	for (i = 0; sony_pic_eventtypes[i].model; i++) {
+	for (i = 0; dev->control->event_types[i].mask; i++) {
 
-		if (spic_dev.model != sony_pic_eventtypes[i].model)
+		if ((data_mask & dev->control->event_types[i].data) !=
+		    dev->control->event_types[i].data)
 			continue;
 
-		if ((data_mask & sony_pic_eventtypes[i].data) !=
-		    sony_pic_eventtypes[i].data)
+		if (!(mask & dev->control->event_types[i].mask))
 			continue;
 
-		if (!(mask & sony_pic_eventtypes[i].mask))
-			continue;
-
-		for (j = 0; sony_pic_eventtypes[i].events[j].event; j++) {
-			if (ev == sony_pic_eventtypes[i].events[j].data) {
+		for (j = 0; dev->control->event_types[i].events[j].event; j++) {
+			if (ev == dev->control->event_types[i].events[j].data) {
 				device_event =
-					sony_pic_eventtypes[i].events[j].event;
+					dev->control->
+						event_types[i].events[j].event;
 				goto found;
 			}
 		}
 	}
+	dprintk("unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
+			ev, data_mask, dev->cur_ioport->io1.minimum,
+			dev->control->evport_offset);
 	return IRQ_HANDLED;
 
 found:
 	sony_laptop_report_input_event(device_event);
-	acpi_bus_generate_proc_event(spic_dev.acpi_dev, 1, device_event);
+	acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event);
 	sonypi_compat_report_event(device_event);
 
 	return IRQ_HANDLED;
@@ -2439,23 +2475,9 @@ static int sony_pic_add(struct acpi_device *device)
 
 	spic_dev.acpi_dev = device;
 	strcpy(acpi_device_class(device), "sony/hotkey");
-	spic_dev.model = sony_pic_detect_device_type();
+	sony_pic_detect_device_type(&spic_dev);
 	mutex_init(&spic_dev.lock);
 
-	/* model specific characteristics */
-	switch(spic_dev.model) {
-		case SONYPI_DEVICE_TYPE1:
-			spic_dev.evport_offset = SONYPI_TYPE1_OFFSET;
-			break;
-		case SONYPI_DEVICE_TYPE3:
-			spic_dev.evport_offset = SONYPI_TYPE3_OFFSET;
-			break;
-		case SONYPI_DEVICE_TYPE2:
-		default:
-			spic_dev.evport_offset = SONYPI_TYPE2_OFFSET;
-			break;
-	}
-
 	/* read _PRS resources */
 	result = sony_pic_possible_resources(device);
 	if (result) {
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#28 lore raw

PATCH 28/112 sony-laptop: bump version to 0.6

In reply to Len Brown

From: Mattia Dongili <[email protected]>

---
 drivers/misc/sony-laptop.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/misc/sony-laptop.c +1 -1
index a650f25..9869286 100644
@@ -73,7 +73,7 @@
 	if (debug) printk(KERN_WARNING DRV_PFX  msg);	\
 } while (0)
 
-#define SONY_LAPTOP_DRIVER_VERSION	"0.5"
+#define SONY_LAPTOP_DRIVER_VERSION	"0.6"
 
 #define SONY_NC_CLASS		"sony-nc"
 #define SONY_NC_HID		"SNY5001"
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#29 lore raw

PATCH 29/112 sony-laptop: add Type4 model

In reply to Len Brown

From: Mattia Dongili <[email protected]>

Recent Vaio models (UX, SZ and presumably TZ and others) add more events and a slightly different handling of Fn key events for additional hotkeys (s1, s2, zoom-in/out, etc.).

---
 drivers/misc/sony-laptop.c |  295 +++++++++++++++++++++++++++-----------------
 include/linux/sonypi.h     |    2 +
 2 files changed, 186 insertions(+), 111 deletions(-)
drivers/misc/sony-laptop.c +184 -111
index 9869286..70d5cc5 100644
@@ -146,68 +146,70 @@ struct sony_laptop_keypress {
  * and input layer indexes in the keymap
  */
 static int sony_laptop_input_index[] = {
-	-1,	/* no event */
-	-1,	/* SONYPI_EVENT_JOGDIAL_DOWN */
-	-1,	/* SONYPI_EVENT_JOGDIAL_UP */
-	-1,	/* SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */
-	-1,	/* SONYPI_EVENT_JOGDIAL_UP_PRESSED */
-	-1,	/* SONYPI_EVENT_JOGDIAL_PRESSED */
-	-1,	/* SONYPI_EVENT_JOGDIAL_RELEASED */
-	 0,	/* SONYPI_EVENT_CAPTURE_PRESSED */
-	 1,	/* SONYPI_EVENT_CAPTURE_RELEASED */
-	 2,	/* SONYPI_EVENT_CAPTURE_PARTIALPRESSED */
-	 3,	/* SONYPI_EVENT_CAPTURE_PARTIALRELEASED */
-	 4,	/* SONYPI_EVENT_FNKEY_ESC */
-	 5,	/* SONYPI_EVENT_FNKEY_F1 */
-	 6,	/* SONYPI_EVENT_FNKEY_F2 */
-	 7,	/* SONYPI_EVENT_FNKEY_F3 */
-	 8,	/* SONYPI_EVENT_FNKEY_F4 */
-	 9,	/* SONYPI_EVENT_FNKEY_F5 */
-	10,	/* SONYPI_EVENT_FNKEY_F6 */
-	11,	/* SONYPI_EVENT_FNKEY_F7 */
-	12,	/* SONYPI_EVENT_FNKEY_F8 */
-	13,	/* SONYPI_EVENT_FNKEY_F9 */
-	14,	/* SONYPI_EVENT_FNKEY_F10 */
-	15,	/* SONYPI_EVENT_FNKEY_F11 */
-	16,	/* SONYPI_EVENT_FNKEY_F12 */
-	17,	/* SONYPI_EVENT_FNKEY_1 */
-	18,	/* SONYPI_EVENT_FNKEY_2 */
-	19,	/* SONYPI_EVENT_FNKEY_D */
-	20,	/* SONYPI_EVENT_FNKEY_E */
-	21,	/* SONYPI_EVENT_FNKEY_F */
-	22,	/* SONYPI_EVENT_FNKEY_S */
-	23,	/* SONYPI_EVENT_FNKEY_B */
-	24,	/* SONYPI_EVENT_BLUETOOTH_PRESSED */
-	25,	/* SONYPI_EVENT_PKEY_P1 */
-	26,	/* SONYPI_EVENT_PKEY_P2 */
-	27,	/* SONYPI_EVENT_PKEY_P3 */
-	28,	/* SONYPI_EVENT_BACK_PRESSED */
-	-1,	/* SONYPI_EVENT_LID_CLOSED */
-	-1,	/* SONYPI_EVENT_LID_OPENED */
-	29,	/* SONYPI_EVENT_BLUETOOTH_ON */
-	30,	/* SONYPI_EVENT_BLUETOOTH_OFF */
-	31,	/* SONYPI_EVENT_HELP_PRESSED */
-	32,	/* SONYPI_EVENT_FNKEY_ONLY */
-	33,	/* SONYPI_EVENT_JOGDIAL_FAST_DOWN */
-	34,	/* SONYPI_EVENT_JOGDIAL_FAST_UP */
-	35,	/* SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */
-	36,	/* SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */
-	37,	/* SONYPI_EVENT_JOGDIAL_VFAST_DOWN */
-	38,	/* SONYPI_EVENT_JOGDIAL_VFAST_UP */
-	39,	/* SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */
-	40,	/* SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */
-	41,	/* SONYPI_EVENT_ZOOM_PRESSED */
-	42,	/* SONYPI_EVENT_THUMBPHRASE_PRESSED */
-	43,	/* SONYPI_EVENT_MEYE_FACE */
-	44,	/* SONYPI_EVENT_MEYE_OPPOSITE */
-	45,	/* SONYPI_EVENT_MEMORYSTICK_INSERT */
-	46,	/* SONYPI_EVENT_MEMORYSTICK_EJECT */
-	-1,	/* SONYPI_EVENT_ANYBUTTON_RELEASED */
-	-1,	/* SONYPI_EVENT_BATTERY_INSERT */
-	-1,	/* SONYPI_EVENT_BATTERY_REMOVE */
-	-1,	/* SONYPI_EVENT_FNKEY_RELEASED */
-	47,	/* SONYPI_EVENT_WIRELESS_ON */
-	48,	/* SONYPI_EVENT_WIRELESS_OFF */
+	-1,	/*  0 no event */
+	-1,	/*  1 SONYPI_EVENT_JOGDIAL_DOWN */
+	-1,	/*  2 SONYPI_EVENT_JOGDIAL_UP */
+	-1,	/*  3 SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */
+	-1,	/*  4 SONYPI_EVENT_JOGDIAL_UP_PRESSED */
+	-1,	/*  5 SONYPI_EVENT_JOGDIAL_PRESSED */
+	-1,	/*  6 SONYPI_EVENT_JOGDIAL_RELEASED */
+	 0,	/*  7 SONYPI_EVENT_CAPTURE_PRESSED */
+	 1,	/*  8 SONYPI_EVENT_CAPTURE_RELEASED */
+	 2,	/*  9 SONYPI_EVENT_CAPTURE_PARTIALPRESSED */
+	 3,	/* 10 SONYPI_EVENT_CAPTURE_PARTIALRELEASED */
+	 4,	/* 11 SONYPI_EVENT_FNKEY_ESC */
+	 5,	/* 12 SONYPI_EVENT_FNKEY_F1 */
+	 6,	/* 13 SONYPI_EVENT_FNKEY_F2 */
+	 7,	/* 14 SONYPI_EVENT_FNKEY_F3 */
+	 8,	/* 15 SONYPI_EVENT_FNKEY_F4 */
+	 9,	/* 16 SONYPI_EVENT_FNKEY_F5 */
+	10,	/* 17 SONYPI_EVENT_FNKEY_F6 */
+	11,	/* 18 SONYPI_EVENT_FNKEY_F7 */
+	12,	/* 19 SONYPI_EVENT_FNKEY_F8 */
+	13,	/* 20 SONYPI_EVENT_FNKEY_F9 */
+	14,	/* 21 SONYPI_EVENT_FNKEY_F10 */
+	15,	/* 22 SONYPI_EVENT_FNKEY_F11 */
+	16,	/* 23 SONYPI_EVENT_FNKEY_F12 */
+	17,	/* 24 SONYPI_EVENT_FNKEY_1 */
+	18,	/* 25 SONYPI_EVENT_FNKEY_2 */
+	19,	/* 26 SONYPI_EVENT_FNKEY_D */
+	20,	/* 27 SONYPI_EVENT_FNKEY_E */
+	21,	/* 28 SONYPI_EVENT_FNKEY_F */
+	22,	/* 29 SONYPI_EVENT_FNKEY_S */
+	23,	/* 30 SONYPI_EVENT_FNKEY_B */
+	24,	/* 31 SONYPI_EVENT_BLUETOOTH_PRESSED */
+	25,	/* 32 SONYPI_EVENT_PKEY_P1 */
+	26,	/* 33 SONYPI_EVENT_PKEY_P2 */
+	27,	/* 34 SONYPI_EVENT_PKEY_P3 */
+	28,	/* 35 SONYPI_EVENT_BACK_PRESSED */
+	-1,	/* 36 SONYPI_EVENT_LID_CLOSED */
+	-1,	/* 37 SONYPI_EVENT_LID_OPENED */
+	29,	/* 38 SONYPI_EVENT_BLUETOOTH_ON */
+	30,	/* 39 SONYPI_EVENT_BLUETOOTH_OFF */
+	31,	/* 40 SONYPI_EVENT_HELP_PRESSED */
+	32,	/* 41 SONYPI_EVENT_FNKEY_ONLY */
+	33,	/* 42 SONYPI_EVENT_JOGDIAL_FAST_DOWN */
+	34,	/* 43 SONYPI_EVENT_JOGDIAL_FAST_UP */
+	35,	/* 44 SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */
+	36,	/* 45 SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */
+	37,	/* 46 SONYPI_EVENT_JOGDIAL_VFAST_DOWN */
+	38,	/* 47 SONYPI_EVENT_JOGDIAL_VFAST_UP */
+	39,	/* 48 SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */
+	40,	/* 49 SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */
+	41,	/* 50 SONYPI_EVENT_ZOOM_PRESSED */
+	42,	/* 51 SONYPI_EVENT_THUMBPHRASE_PRESSED */
+	43,	/* 52 SONYPI_EVENT_MEYE_FACE */
+	44,	/* 53 SONYPI_EVENT_MEYE_OPPOSITE */
+	45,	/* 54 SONYPI_EVENT_MEMORYSTICK_INSERT */
+	46,	/* 55 SONYPI_EVENT_MEMORYSTICK_EJECT */
+	-1,	/* 56 SONYPI_EVENT_ANYBUTTON_RELEASED */
+	-1,	/* 57 SONYPI_EVENT_BATTERY_INSERT */
+	-1,	/* 58 SONYPI_EVENT_BATTERY_REMOVE */
+	-1,	/* 59 SONYPI_EVENT_FNKEY_RELEASED */
+	47,	/* 60 SONYPI_EVENT_WIRELESS_ON */
+	48,	/* 61 SONYPI_EVENT_WIRELESS_OFF */
+	49,	/* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */
+	50,	/* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */
 };
 
 static int sony_laptop_input_keycode_map[] = {
@@ -260,6 +262,8 @@ static int sony_laptop_input_keycode_map[] = {
 	KEY_RESERVED,	/* 46 SONYPI_EVENT_MEMORYSTICK_EJECT */
 	KEY_WLAN,	/* 47 SONYPI_EVENT_WIRELESS_ON */
 	KEY_WLAN,	/* 48 SONYPI_EVENT_WIRELESS_OFF */
+	KEY_ZOOMIN,	/* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */
+	KEY_ZOOMOUT	/* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */
 };
 
 /* release buttons after a short delay if pressed */
@@ -1178,10 +1182,12 @@ static struct acpi_driver sony_nc_driver = {
 #define SONYPI_DEVICE_TYPE1	0x00000001
 #define SONYPI_DEVICE_TYPE2	0x00000002
 #define SONYPI_DEVICE_TYPE3	0x00000004
+#define SONYPI_DEVICE_TYPE4	0x00000008
 
 #define SONYPI_TYPE1_OFFSET	0x04
 #define SONYPI_TYPE2_OFFSET	0x12
 #define SONYPI_TYPE3_OFFSET	0x12
+#define SONYPI_TYPE4_OFFSET	0x12
 
 struct sony_pic_ioport {
 	struct acpi_resource_io	io1;
@@ -1202,7 +1208,7 @@ struct sonypi_eventtypes {
 
 struct device_ctrl {
 	int				model;
-	int				(*handle_irq)(void);
+	int				(*handle_irq)(const u8, const u8);
 	u16				evport_offset;
 	u8				has_camera;
 	u8				has_bluetooth;
@@ -1277,6 +1283,7 @@ static struct sonypi_event sonypi_joggerev[] = {
 static struct sonypi_event sonypi_captureev[] = {
 	{ 0x05, SONYPI_EVENT_CAPTURE_PARTIALPRESSED },
 	{ 0x07, SONYPI_EVENT_CAPTURE_PRESSED },
+	{ 0x40, SONYPI_EVENT_CAPTURE_PRESSED },
 	{ 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED },
 	{ 0, 0 }
 };
@@ -1313,7 +1320,6 @@ static struct sonypi_event sonypi_pkeyev[] = {
 	{ 0x01, SONYPI_EVENT_PKEY_P1 },
 	{ 0x02, SONYPI_EVENT_PKEY_P2 },
 	{ 0x04, SONYPI_EVENT_PKEY_P3 },
-	{ 0x5c, SONYPI_EVENT_PKEY_P1 },
 	{ 0, 0 }
 };
 
@@ -1355,6 +1361,8 @@ static struct sonypi_event sonypi_lidev[] = {
 /* The set of possible zoom events */
 static struct sonypi_event sonypi_zoomev[] = {
 	{ 0x39, SONYPI_EVENT_ZOOM_PRESSED },
+	{ 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED },
+	{ 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED },
 	{ 0, 0 }
 };
 
@@ -1424,55 +1432,19 @@ static struct sonypi_eventtypes type3_events[] = {
 	{ 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
 	{ 0 },
 };
-
-static struct device_ctrl spic_types[] = {
-	{
-		.model = SONYPI_DEVICE_TYPE1,
-		.handle_irq = NULL,
-		.evport_offset = SONYPI_TYPE1_OFFSET,
-		.event_types = type1_events,
-	},
-	{
-		.model = SONYPI_DEVICE_TYPE2,
-		.handle_irq = NULL,
-		.evport_offset = SONYPI_TYPE2_OFFSET,
-		.event_types = type2_events,
-	},
-	{
-		.model = SONYPI_DEVICE_TYPE3,
-		.handle_irq = NULL,
-		.evport_offset = SONYPI_TYPE3_OFFSET,
-		.event_types = type3_events,
-	},
+static struct sonypi_eventtypes type4_events[] = {
+	{ 0, 0xffffffff, sonypi_releaseev },
+	{ 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
+	{ 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev },
+	{ 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
+	{ 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
+	{ 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev },
+	{ 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev },
+	{ 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev },
+	{ 0 },
 };
 
-static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
-{
-	struct pci_dev *pcidev;
-
-	if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
-				     PCI_DEVICE_ID_INTEL_82371AB_3, NULL)))
-		dev->control = &spic_types[0];
-
-	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
-					  PCI_DEVICE_ID_INTEL_ICH6_1, NULL)))
-		dev->control = &spic_types[2];
-
-	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
-					  PCI_DEVICE_ID_INTEL_ICH7_1, NULL)))
-		dev->control = &spic_types[2];
-
-	else
-		dev->control = &spic_types[1];
-
-	if (pcidev)
-		pci_dev_put(pcidev);
-
-	printk(KERN_INFO DRV_PFX "detected Type%d model\n",
-			dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 :
-			dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
-}
-
+/* low level spic calls */
 #define ITERATIONS_LONG		10000
 #define ITERATIONS_SHORT	10
 #define wait_on_command(command, iterations) {				\
@@ -1528,6 +1500,100 @@ static u8 sony_pic_call3(u8 dev, u8 fn, u8 v)
 	return v1;
 }
 
+/*
+ * minidrivers for SPIC models
+ */
+static int type4_handle_irq(const u8 data_mask, const u8 ev)
+{
+	/*
+	 * 0x31 could mean we have to take some extra action and wait for
+	 * the next irq for some Type4 models, it will generate a new
+	 * irq and we can read new data from the device:
+	 *  - 0x5c and 0x5f requires 0xA0
+	 *  - 0x61 requires 0xB3
+	 */
+	if (data_mask == 0x31) {
+		if (ev == 0x5c || ev == 0x5f)
+			sony_pic_call1(0xA0);
+		else if (ev == 0x61)
+			sony_pic_call1(0xB3);
+		return 0;
+	}
+	return 1;
+}
+
+static struct device_ctrl spic_types[] = {
+	{
+		.model = SONYPI_DEVICE_TYPE1,
+		.handle_irq = NULL,
+		.evport_offset = SONYPI_TYPE1_OFFSET,
+		.event_types = type1_events,
+	},
+	{
+		.model = SONYPI_DEVICE_TYPE2,
+		.handle_irq = NULL,
+		.evport_offset = SONYPI_TYPE2_OFFSET,
+		.event_types = type2_events,
+	},
+	{
+		.model = SONYPI_DEVICE_TYPE3,
+		.handle_irq = NULL,
+		.evport_offset = SONYPI_TYPE3_OFFSET,
+		.event_types = type3_events,
+	},
+	{
+		.model = SONYPI_DEVICE_TYPE4,
+		.handle_irq = type4_handle_irq,
+		.evport_offset = SONYPI_TYPE4_OFFSET,
+		.event_types = type4_events,
+	},
+};
+
+static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
+{
+	struct pci_dev *pcidev;
+
+	pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+			PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
+	if (pcidev) {
+		dev->control = &spic_types[0];
+		goto out;
+	}
+
+	pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+			PCI_DEVICE_ID_INTEL_ICH6_1, NULL);
+	if (pcidev) {
+		dev->control = &spic_types[2];
+		goto out;
+	}
+
+	pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+			PCI_DEVICE_ID_INTEL_ICH7_1, NULL);
+	if (pcidev) {
+		dev->control = &spic_types[3];
+		goto out;
+	}
+
+	pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+			PCI_DEVICE_ID_INTEL_ICH8_4, NULL);
+	if (pcidev) {
+		dev->control = &spic_types[3];
+		goto out;
+	}
+
+	/* default */
+	dev->control = &spic_types[1];
+
+out:
+	if (pcidev)
+		pci_dev_put(pcidev);
+
+	printk(KERN_INFO DRV_PFX "detected Type%d model\n",
+			dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 :
+			dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 :
+			dev->control->model == SONYPI_DEVICE_TYPE3 ? 3 : 4);
+}
+
 /* camera tests and poweron/poweroff */
 #define SONYPI_CAMERA_PICTURE		5
 #define SONYPI_CAMERA_CONTROL		0x10
@@ -2406,6 +2472,13 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id)
 			}
 		}
 	}
+	/* Still not able to decode the event try to pass
+	 * it over to the minidriver
+	 */
+	if (dev->control->handle_irq &&
+			dev->control->handle_irq(data_mask, ev) == 0)
+		return IRQ_HANDLED;
+
 	dprintk("unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
 			ev, data_mask, dev->cur_ioport->io1.minimum,
 			dev->control->evport_offset);
include/linux/sonypi.h +2 -0
index 40c7b5d..f41ffd7 100644
@@ -101,6 +101,8 @@
 #define SONYPI_EVENT_FNKEY_RELEASED		59
 #define SONYPI_EVENT_WIRELESS_ON		60
 #define SONYPI_EVENT_WIRELESS_OFF		61
+#define SONYPI_EVENT_ZOOM_IN_PRESSED		62
+#define SONYPI_EVENT_ZOOM_OUT_PRESSED		63
 
 /* get/set brightness */
 #define SONYPI_IOCGBRT		_IOR('v', 0, __u8)
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#30 lore raw

PATCH 30/112 sony-laptop: fix scancode decode

In reply to Len Brown

From: Mattia Dongili <[email protected]>

compare against the sony_laptop specific event list index to decode the input scancode to send.

---
 drivers/misc/sony-laptop.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/misc/sony-laptop.c +1 -1
index 70d5cc5..899e3f7 100644
@@ -315,7 +315,7 @@ static void sony_laptop_report_input_event(u8 event)
 		break;
 
 	default:
-		if (event > ARRAY_SIZE (sony_laptop_input_keycode_map)) {
+		if (event > ARRAY_SIZE(sony_laptop_input_index)) {
 			dprintk("sony_laptop_report_input_event, event not known: %d\n", event);
 			break;
 		}
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#31 lore raw

PATCH 31/112 cpuidle: build fix for non-x86

In reply to Len Brown

From: Kevin Hilman <[email protected]>

Convert cpu_idle_wait() to cpuidle_kick_cpus() macro which is SMP-only, and gives error on non supported CPU.

---
 arch/x86/Kconfig          |    3 +++
 drivers/cpuidle/cpuidle.c |    2 +-
 include/linux/cpuidle.h   |   13 +++++++++++++
 3 files changed, 17 insertions(+), 1 deletions(-)
arch/x86/Kconfig +3 -0
index 368864d..37d1297 100644
@@ -105,6 +105,9 @@ config ARCH_HAS_ILOG2_U32
 config ARCH_HAS_ILOG2_U64
 	def_bool n
 
+config ARCH_HAS_CPU_IDLE_WAIT
+	def_bool y
+
 config GENERIC_CALIBRATE_DELAY
 	def_bool y
 
drivers/cpuidle/cpuidle.c +1 -1
index d2fabe7..794962d 100644
@@ -82,7 +82,7 @@ void cpuidle_uninstall_idle_handler(void)
 {
 	if (enabled_devices && (pm_idle != pm_idle_old)) {
 		pm_idle = pm_idle_old;
-		cpu_idle_wait();
+		cpuidle_kick_cpus();
 	}
 }
 
include/linux/cpuidle.h +13 -0
index 16a5154..cb95f5a 100644
@@ -72,6 +72,19 @@ cpuidle_set_statedata(struct cpuidle_state *state, void *data)
 	state->driver_data = data;
 }
 
+#ifdef CONFIG_SMP
+#ifdef CONFIG_ARCH_HAS_CPU_IDLE_WAIT
+static inline void cpuidle_kick_cpus(void)
+{
+	cpu_idle_wait();
+}
+#else /* !CONFIG_ARCH_HAS_CPU_IDLE_WAIT */
+#error "Arch needs cpu_idle_wait() equivalent here"
+#endif /* !CONFIG_ARCH_HAS_CPU_IDLE_WAIT */
+#else /* !CONFIG_SMP */
+static inline void cpuidle_kick_cpus(void) {}
+#endif /* !CONFIG_SMP */
+
 struct cpuidle_state_kobj {
 	struct cpuidle_state *state;
 	struct completion kobj_unregister;
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#32 lore raw

PATCH 32/112 ACPI: thinkpad-acpi: document keymap gotcha's (v2)

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

Publish the requirements for keymap changes. This is a documentation change, only.

Currently, people look at the thinkpad-acpi default keymaps, and think:
"modifying this is a trivial thing, it can't break systems, and there are keys defined for foo and bar, but the driver has them as KEY_RESERVED. Must have been an oversight, let me change it."

And since they never get to see the bug reports, because they are not really a part of the Linux ThinkPad users community (linux-thinkpad mailinglist, thinkwiki wiki, thinkpad forums) and laptop users are slow to complain to distros about any breakages...

---
 drivers/misc/thinkpad_acpi.c |   68 ++++++++++++++++++++++++++++++++++++++---
 1 files changed, 63 insertions(+), 5 deletions(-)
drivers/misc/thinkpad_acpi.c +63 -5
index cf56647..7b1080f 100644
@@ -954,26 +954,67 @@ static struct attribute *hotkey_mask_attributes[] __initdata = {
 
 static int __init hotkey_init(struct ibm_init_struct *iibm)
 {
-
+	/* Requirements for changing the default keymaps:
+	 *
+	 * 1. Many of the keys are mapped to KEY_RESERVED for very
+	 *    good reasons.  Do not change them unless you have deep
+	 *    knowledge on the IBM and Lenovo ThinkPad firmware for
+	 *    the various ThinkPad models.  The driver behaves
+	 *    differently for KEY_RESERVED: such keys have their
+	 *    hot key mask *unset* in mask_recommended, and also
+	 *    in the initial hot key mask programmed into the
+	 *    firmware at driver load time, which means the firm-
+	 *    ware may react very differently if you change them to
+	 *    something else;
+	 *
+	 * 2. You must be subscribed to the linux-thinkpad and
+	 *    ibm-acpi-devel mailing lists, and you should read the
+	 *    list archives since 2007 if you want to change the
+	 *    keymaps.  This requirement exists so that you will
+	 *    know the past history of problems with the thinkpad-
+	 *    acpi driver keymaps, and also that you will be
+	 *    listening to any bug reports;
+	 *
+	 * 3. Do not send thinkpad-acpi specific patches directly to
+	 *    for merging, *ever*.  Send them to the linux-acpi
+	 *    mailinglist for comments.  Merging is to be done only
+	 *    through acpi-test and the ACPI maintainer.
+	 *
+	 * If the above is too much to ask, don't change the keymap.
+	 * Ask the thinkpad-acpi maintainer to do it, instead.
+	 */
 	static u16 ibm_keycode_map[] __initdata = {
 		/* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */
 		KEY_FN_F1,	KEY_FN_F2,	KEY_COFFEE,	KEY_SLEEP,
 		KEY_WLAN,	KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8,
 		KEY_FN_F9,	KEY_FN_F10,	KEY_FN_F11,	KEY_SUSPEND,
-		/* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */
+
+		/* Scan codes 0x0C to 0x1F: Other ACPI HKEY hot keys */
 		KEY_UNKNOWN,	/* 0x0C: FN+BACKSPACE */
 		KEY_UNKNOWN,	/* 0x0D: FN+INSERT */
 		KEY_UNKNOWN,	/* 0x0E: FN+DELETE */
+
+		/* brightness: firmware always reacts to them, unless
+		 * X.org did some tricks in the radeon BIOS scratch
+		 * registers of *some* models */
 		KEY_RESERVED,	/* 0x0F: FN+HOME (brightness up) */
-		/* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */
 		KEY_RESERVED,	/* 0x10: FN+END (brightness down) */
+
+		/* Thinklight: firmware always react to it */
 		KEY_RESERVED,	/* 0x11: FN+PGUP (thinklight toggle) */
+
 		KEY_UNKNOWN,	/* 0x12: FN+PGDOWN */
 		KEY_ZOOM,	/* 0x13: FN+SPACE (zoom) */
+
+		/* Volume: firmware always react to it and reprograms
+		 * the built-in *extra* mixer.  Never map it to control
+		 * another mixer by default. */
 		KEY_RESERVED,	/* 0x14: VOLUME UP */
 		KEY_RESERVED,	/* 0x15: VOLUME DOWN */
 		KEY_RESERVED,	/* 0x16: MUTE */
+
 		KEY_VENDOR,	/* 0x17: Thinkpad/AccessIBM/Lenovo */
+
 		/* (assignments unknown, please report if found) */
 		KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
 		KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
@@ -983,20 +1024,37 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 		KEY_FN_F1,	KEY_COFFEE,	KEY_BATTERY,	KEY_SLEEP,
 		KEY_WLAN,	KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8,
 		KEY_FN_F9,	KEY_FN_F10,	KEY_FN_F11,	KEY_SUSPEND,
-		/* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */
+
+		/* Scan codes 0x0C to 0x1F: Other ACPI HKEY hot keys */
 		KEY_UNKNOWN,	/* 0x0C: FN+BACKSPACE */
 		KEY_UNKNOWN,	/* 0x0D: FN+INSERT */
 		KEY_UNKNOWN,	/* 0x0E: FN+DELETE */
+
 		KEY_RESERVED,	/* 0x0F: FN+HOME (brightness up) */
-		/* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */
 		KEY_RESERVED,	/* 0x10: FN+END (brightness down) */
+
 		KEY_RESERVED,	/* 0x11: FN+PGUP (thinklight toggle) */
+
 		KEY_UNKNOWN,	/* 0x12: FN+PGDOWN */
 		KEY_ZOOM,	/* 0x13: FN+SPACE (zoom) */
+
+		/* Volume: z60/z61, T60 (BIOS version?): firmware always
+		 * react to it and reprograms the built-in *extra* mixer.
+		 * Never map it to control another mixer by default.
+		 *
+		 * T60?, T61, R60?, R61: firmware and EC tries to send
+		 * these over the regular keyboard, so these are no-ops,
+		 * but there are still weird bugs re. MUTE, so do not
+		 * change unless you get test reports from all Lenovo
+		 * models.  May cause the BIOS to interfere with the
+		 * HDA mixer.
+		 */
 		KEY_RESERVED,	/* 0x14: VOLUME UP */
 		KEY_RESERVED,	/* 0x15: VOLUME DOWN */
 		KEY_RESERVED,	/* 0x16: MUTE */
+
 		KEY_VENDOR,	/* 0x17: Thinkpad/AccessIBM/Lenovo */
+
 		/* (assignments unknown, please report if found) */
 		KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
 		KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#33 lore raw

PATCH 33/112 ACPI: thinkpad-acpi: refactor hotkey_get and hotkey_set (v2)

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

Refactor and organize the code a bit for the NVRAM polling support:

1. Split hotkey_get/set into hotkey_status_get/set and hotkey_mask_get/set;
2. Cache the status of hot key mask for later driver use;
3. Make sure the cache of hot key mask is refreshed when needed;
4. log a printk notice when the firmware doesn't set the hot key mask to exactly what we asked it to;
5. Add proper locking to the data structures.

Only (4) should be user-noticeable, but there is a chance (5) fixes some unknown/unreported race conditions.

---
 drivers/misc/thinkpad_acpi.c |  184 +++++++++++++++++++++++++-----------------
 drivers/misc/thinkpad_acpi.h |    2 -
 2 files changed, 109 insertions(+), 77 deletions(-)
drivers/misc/thinkpad_acpi.c +109 -75
index 7b1080f..49d4f4a 100644
@@ -777,6 +777,7 @@ static int hotkey_orig_status;
 static u32 hotkey_orig_mask;
 static u32 hotkey_all_mask;
 static u32 hotkey_reserved_mask;
+static u32 hotkey_mask;
 
 static u16 *hotkey_keycode_map;
 
@@ -789,15 +790,76 @@ static int hotkey_get_wlsw(int *status)
 	return 0;
 }
 
+/*
+ * Call with hotkey_mutex held
+ */
+static int hotkey_mask_get(void)
+{
+	if (tp_features.hotkey_mask) {
+		if (!acpi_evalf(hkey_handle, &hotkey_mask, "DHKN", "d"))
+			return -EIO;
+	}
+
+	return 0;
+}
+
+/*
+ * Call with hotkey_mutex held
+ */
+static int hotkey_mask_set(u32 mask)
+{
+	int i;
+	int rc = 0;
+
+	if (tp_features.hotkey_mask) {
+		for (i = 0; i < 32; i++) {
+			u32 m = 1 << i;
+			if (!acpi_evalf(hkey_handle,
+					NULL, "MHKM", "vdd", i + 1,
+					!!(mask & m))) {
+				rc = -EIO;
+				break;
+			} else {
+				hotkey_mask = (hotkey_mask & ~m) | (mask & m);
+			}
+		}
+
+		/* hotkey_mask_get must be called unconditionally below */
+		if (!hotkey_mask_get() && !rc && hotkey_mask != mask) {
+			printk(IBM_NOTICE
+			       "requested hot key mask 0x%08x, but "
+			       "firmware forced it to 0x%08x\n",
+			       mask, hotkey_mask);
+		}
+	}
+
+	return rc;
+}
+
+static int hotkey_status_get(int *status)
+{
+	if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
+		return -EIO;
+
+	return 0;
+}
+
+static int hotkey_status_set(int status)
+{
+	if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status))
+		return -EIO;
+
+	return 0;
+}
+
 /* sysfs hotkey enable ------------------------------------------------- */
 static ssize_t hotkey_enable_show(struct device *dev,
 			   struct device_attribute *attr,
 			   char *buf)
 {
 	int res, status;
-	u32 mask;
 
-	res = hotkey_get(&status, &mask);
+	res = hotkey_status_get(&status);
 	if (res)
 		return res;
 
@@ -809,15 +871,12 @@ static ssize_t hotkey_enable_store(struct device *dev,
 			    const char *buf, size_t count)
 {
 	unsigned long t;
-	int res, status;
-	u32 mask;
+	int res;
 
 	if (parse_strtoul(buf, 1, &t))
 		return -EINVAL;
 
-	res = hotkey_get(&status, &mask);
-	if (!res)
-		res = hotkey_set(t, mask);
+	res = hotkey_status_set(t);
 
 	return (res) ? res : count;
 }
@@ -831,14 +890,15 @@ static ssize_t hotkey_mask_show(struct device *dev,
 			   struct device_attribute *attr,
 			   char *buf)
 {
-	int res, status;
-	u32 mask;
+	int res;
 
-	res = hotkey_get(&status, &mask);
-	if (res)
-		return res;
+	if (mutex_lock_interruptible(&hotkey_mutex))
+		return -ERESTARTSYS;
+	res = hotkey_mask_get();
+	mutex_unlock(&hotkey_mutex);
 
-	return snprintf(buf, PAGE_SIZE, "0x%08x\n", mask);
+	return (res)?
+		res : snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_mask);
 }
 
 static ssize_t hotkey_mask_store(struct device *dev,
@@ -846,15 +906,16 @@ static ssize_t hotkey_mask_store(struct device *dev,
 			    const char *buf, size_t count)
 {
 	unsigned long t;
-	int res, status;
-	u32 mask;
+	int res;
 
 	if (parse_strtoul(buf, 0xffffffffUL, &t))
 		return -EINVAL;
 
-	res = hotkey_get(&status, &mask);
-	if (!res)
-		hotkey_set(status, t);
+	if (mutex_lock_interruptible(&hotkey_mutex))
+		return -ERESTARTSYS;
+
+	res = hotkey_mask_set(t);
+	mutex_unlock(&hotkey_mutex);
 
 	return (res) ? res : count;
 }
@@ -1123,11 +1184,16 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 			}
 		}
 
-		res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask);
+		res = hotkey_status_get(&hotkey_orig_status);
 		if (!res && tp_features.hotkey_mask) {
-			res = add_many_to_attr_set(hotkey_dev_attributes,
-				hotkey_mask_attributes,
-				ARRAY_SIZE(hotkey_mask_attributes));
+			res = hotkey_mask_get();
+			hotkey_orig_mask = hotkey_mask;
+			if (!res) {
+				res = add_many_to_attr_set(
+					hotkey_dev_attributes,
+					hotkey_mask_attributes,
+					ARRAY_SIZE(hotkey_mask_attributes));
+			}
 		}
 
 		/* Not all thinkpads have a hardware radio switch */
@@ -1191,7 +1257,10 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 
 		dbg_printk(TPACPI_DBG_INIT,
 				"enabling hot key handling\n");
-		res = hotkey_set(1, (hotkey_all_mask & ~hotkey_reserved_mask)
+		res = hotkey_status_set(1);
+		if (res)
+			return res;
+		res = hotkey_mask_set((hotkey_all_mask & ~hotkey_reserved_mask)
 					| hotkey_orig_mask);
 		if (res)
 			return res;
@@ -1207,13 +1276,12 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 
 static void hotkey_exit(void)
 {
-	int res;
-
 	if (tp_features.hotkey) {
-		dbg_printk(TPACPI_DBG_EXIT, "restoring original hotkey mask\n");
-		res = hotkey_set(hotkey_orig_status, hotkey_orig_mask);
-		if (res)
-			printk(IBM_ERR "failed to restore hotkey to BIOS defaults\n");
+		dbg_printk(TPACPI_DBG_EXIT, "restoring original hot key mask\n");
+		/* no short-circuit boolean operator below! */
+		if ((hotkey_mask_set(hotkey_orig_mask) |
+		     hotkey_status_set(hotkey_orig_status)) != 0)
+			printk(IBM_ERR "failed to restore hot key mask to BIOS defaults\n");
 	}
 
 	if (hotkey_dev_attributes) {
@@ -1349,50 +1417,15 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 
 static void hotkey_resume(void)
 {
+	if (hotkey_mask_get())
+		printk(IBM_ERR "error while trying to read hot key mask from firmware\n");
 	tpacpi_input_send_radiosw();
 }
 
-/*
- * Call with hotkey_mutex held
- */
-static int hotkey_get(int *status, u32 *mask)
-{
-	if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
-		return -EIO;
-
-	if (tp_features.hotkey_mask)
-		if (!acpi_evalf(hkey_handle, mask, "DHKN", "d"))
-			return -EIO;
-
-	return 0;
-}
-
-/*
- * Call with hotkey_mutex held
- */
-static int hotkey_set(int status, u32 mask)
-{
-	int i;
-
-	if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status))
-		return -EIO;
-
-	if (tp_features.hotkey_mask)
-		for (i = 0; i < 32; i++) {
-			int bit = ((1 << i) & mask) != 0;
-			if (!acpi_evalf(hkey_handle,
-					NULL, "MHKM", "vdd", i + 1, bit))
-				return -EIO;
-		}
-
-	return 0;
-}
-
 /* procfs -------------------------------------------------------------- */
 static int hotkey_read(char *p)
 {
 	int res, status;
-	u32 mask;
 	int len = 0;
 
 	if (!tp_features.hotkey) {
@@ -1402,14 +1435,16 @@ static int hotkey_read(char *p)
 
 	if (mutex_lock_interruptible(&hotkey_mutex))
 		return -ERESTARTSYS;
-	res = hotkey_get(&status, &mask);
+	res = hotkey_status_get(&status);
+	if (!res)
+		res = hotkey_mask_get();
 	mutex_unlock(&hotkey_mutex);
 	if (res)
 		return res;
 
 	len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
 	if (tp_features.hotkey_mask) {
-		len += sprintf(p + len, "mask:\t\t0x%08x\n", mask);
+		len += sprintf(p + len, "mask:\t\t0x%08x\n", hotkey_mask);
 		len += sprintf(p + len,
 			       "commands:\tenable, disable, reset, <mask>\n");
 	} else {
@@ -1425,7 +1460,6 @@ static int hotkey_write(char *buf)
 	int res, status;
 	u32 mask;
 	char *cmd;
-	int do_cmd = 0;
 
 	if (!tp_features.hotkey)
 		return -ENODEV;
@@ -1433,9 +1467,8 @@ static int hotkey_write(char *buf)
 	if (mutex_lock_interruptible(&hotkey_mutex))
 		return -ERESTARTSYS;
 
-	res = hotkey_get(&status, &mask);
-	if (res)
-		goto errexit;
+	status = -1;
+	mask = hotkey_mask;
 
 	res = 0;
 	while ((cmd = next_cmd(&buf))) {
@@ -1454,11 +1487,12 @@ static int hotkey_write(char *buf)
 			res = -EINVAL;
 			goto errexit;
 		}
-		do_cmd = 1;
 	}
+	if (status != -1)
+		res = hotkey_status_set(status);
 
-	if (do_cmd)
-		res = hotkey_set(status, mask);
+	if (!res && mask != hotkey_mask)
+		res = hotkey_mask_set(mask);
 
 errexit:
 	mutex_unlock(&hotkey_mutex);
drivers/misc/thinkpad_acpi.h +0 -2
index 8fba2bb..3b03134 100644
@@ -461,8 +461,6 @@ static struct mutex hotkey_mutex;
 
 static int hotkey_init(struct ibm_init_struct *iibm);
 static void hotkey_exit(void);
-static int hotkey_get(int *status, u32 *mask);
-static int hotkey_set(int status, u32 mask);
 static void hotkey_notify(struct ibm_struct *ibm, u32 event);
 static int hotkey_read(char *p);
 static int hotkey_write(char *buf);
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#34 lore raw

PATCH 34/112 ACPI: thinkpad-acpi: prepare for NVRAM polling support

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

Make some small internal thinkpad-acpi changes to the hotkey subdriver code that will make it easier to add NVRAM polling support.

---
 drivers/misc/thinkpad_acpi.c |   82 +++++++++++++++++++++--------------------
 1 files changed, 42 insertions(+), 40 deletions(-)
drivers/misc/thinkpad_acpi.c +42 -40
index 49d4f4a..e7ac1c8 100644
@@ -852,6 +852,46 @@ static int hotkey_status_set(int status)
 	return 0;
 }
 
+static void tpacpi_input_send_radiosw(void)
+{
+	int wlsw;
+
+	mutex_lock(&tpacpi_inputdev_send_mutex);
+
+	if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) {
+		input_report_switch(tpacpi_inputdev,
+				    SW_RADIO, !!wlsw);
+		input_sync(tpacpi_inputdev);
+	}
+
+	mutex_unlock(&tpacpi_inputdev_send_mutex);
+}
+
+static void tpacpi_input_send_key(unsigned int scancode)
+{
+	unsigned int keycode;
+
+	keycode = hotkey_keycode_map[scancode];
+
+	if (keycode != KEY_RESERVED) {
+		mutex_lock(&tpacpi_inputdev_send_mutex);
+
+		input_report_key(tpacpi_inputdev, keycode, 1);
+		if (keycode == KEY_UNKNOWN)
+			input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
+				    scancode);
+		input_sync(tpacpi_inputdev);
+
+		input_report_key(tpacpi_inputdev, keycode, 0);
+		if (keycode == KEY_UNKNOWN)
+			input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
+				    scancode);
+		input_sync(tpacpi_inputdev);
+
+		mutex_unlock(&tpacpi_inputdev_send_mutex);
+	}
+}
+
 /* sysfs hotkey enable ------------------------------------------------- */
 static ssize_t hotkey_enable_show(struct device *dev,
 			   struct device_attribute *attr,
@@ -1290,47 +1330,10 @@ static void hotkey_exit(void)
 	}
 }
 
-static void tpacpi_input_send_key(unsigned int scancode,
-				  unsigned int keycode)
-{
-	if (keycode != KEY_RESERVED) {
-		mutex_lock(&tpacpi_inputdev_send_mutex);
-
-		input_report_key(tpacpi_inputdev, keycode, 1);
-		if (keycode == KEY_UNKNOWN)
-			input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
-				    scancode);
-		input_sync(tpacpi_inputdev);
-
-		input_report_key(tpacpi_inputdev, keycode, 0);
-		if (keycode == KEY_UNKNOWN)
-			input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
-				    scancode);
-		input_sync(tpacpi_inputdev);
-
-		mutex_unlock(&tpacpi_inputdev_send_mutex);
-	}
-}
-
-static void tpacpi_input_send_radiosw(void)
-{
-	int wlsw;
-
-	mutex_lock(&tpacpi_inputdev_send_mutex);
-
-	if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) {
-		input_report_switch(tpacpi_inputdev,
-				    SW_RADIO, !!wlsw);
-		input_sync(tpacpi_inputdev);
-	}
-
-	mutex_unlock(&tpacpi_inputdev_send_mutex);
-}
-
 static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 {
 	u32 hkey;
-	unsigned int keycode, scancode;
+	unsigned int scancode;
 	int send_acpi_ev;
 	int ignore_acpi_ev;
 
@@ -1363,8 +1366,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 			scancode = hkey & 0xfff;
 			if (scancode > 0 && scancode < 0x21) {
 				scancode--;
-				keycode = hotkey_keycode_map[scancode];
-				tpacpi_input_send_key(scancode, keycode);
+				tpacpi_input_send_key(scancode);
 			} else {
 				printk(IBM_ERR
 				       "hotkey 0x%04x out of range for keyboard map\n",
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#35 lore raw

PATCH 35/112 ACPI: thinkpad-acpi: add CMOS NVRAM polling for hot keys (v9)

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

Older ThinkPad models do not export some of the hot keys over the event-based ACPI hot key interface. For these models, one has to poll the CMOS NVRAM to check the key state at a rate faster than the expected rate at which the user might repeatedly press the same hot key.

This patch implements this functionality for many of the hotkeys in a transparent way: hot keys will now Just Work, and the driver knows the best approach (events or NVRAM polling) to employ, based on the HKEY.MHKA ACPI method.

Also, the driver can turn off the polling when there are no users for the hot keys that need such polling.

The NVRAM-based hot keys of the A3x series that have never been implemented by later models are not supported, to avoid changes in the keymap of the input devices that could cause headaches in the future.

There is a Kconfig option to avoid compiling the NVRAM polling code, as it is not very small, and unlikely to be useful on any ThinkPad newer than a T40, X31 or R52.

This feature is based on a previous effort by Richard Hughes.

---
 Documentation/thinkpad-acpi.txt |   71 +++++-
 drivers/misc/Kconfig            |   19 ++
 drivers/misc/thinkpad_acpi.c    |  505 ++++++++++++++++++++++++++++++++++++++-
 drivers/misc/thinkpad_acpi.h    |   60 +++++-
 4 files changed, 632 insertions(+), 23 deletions(-)
Documentation/thinkpad-acpi.txt +65 -6
index 10c041c..70d91a5 100644
@@ -215,6 +215,11 @@ The following commands can be written to the /proc/acpi/ibm/hotkey file:
 	... any other 8-hex-digit mask ...
 	echo reset > /proc/acpi/ibm/hotkey -- restore the original mask
 
+The procfs interface does not support NVRAM polling control.  So as to
+maintain maximum bug-to-bug compatibility, it does not report any masks,
+nor does it allow one to manipulate the hot key mask when the firmware
+does not support masks at all, even if NVRAM polling is in use.
+
 sysfs notes:
 
 	hotkey_bios_enabled:
@@ -231,17 +236,26 @@ sysfs notes:
 		to this value.
 
 	hotkey_enable:
-		Enables/disables the hot keys feature, and reports
-		current status of the hot keys feature.
+		Enables/disables the hot keys feature in the ACPI
+		firmware, and reports current status of the hot keys
+		feature.  Has no effect on the NVRAM hot key polling
+		functionality.
 
 		0: disables the hot keys feature / feature disabled
 		1: enables the hot keys feature / feature enabled
 
 	hotkey_mask:
-		bit mask to enable driver-handling and ACPI event
-		generation for each hot key (see above).  Returns the
-		current status of the hot keys mask, and allows one to
-		modify it.
+		bit mask to enable driver-handling (and depending on
+		the firmware, ACPI event generation) for each hot key
+		(see above).  Returns the current status of the hot keys
+		mask, and allows one to modify it.
+
+		Note: when NVRAM polling is active, the firmware mask
+		will be different from the value returned by
+		hotkey_mask.  The driver will retain enabled bits for
+		hotkeys that are under NVRAM polling even if the
+		firmware refuses them, and will not set these bits on
+		the firmware hot key mask.
 
 	hotkey_all_mask:
 		bit mask that should enable event reporting for all
@@ -257,6 +271,40 @@ sysfs notes:
 		handled by the firmware anyway.  Echo it to
 		hotkey_mask above, to use.
 
+	hotkey_source_mask:
+		bit mask that selects which hot keys will the driver
+		poll the NVRAM for.  This is auto-detected by the driver
+		based on the capabilities reported by the ACPI firmware,
+		but it can be overridden at runtime.
+
+		Hot keys whose bits are set in both hotkey_source_mask
+		and also on hotkey_mask are polled for in NVRAM.  Only a
+		few hot keys are available through CMOS NVRAM polling.
+
+		Warning: when in NVRAM mode, the volume up/down/mute
+		keys are synthesized according to changes in the mixer,
+		so you have to use volume up or volume down to unmute,
+		as per the ThinkPad volume mixer user interface.  When
+		in ACPI event mode, volume up/down/mute are reported as
+		separate events, but this behaviour may be corrected in
+		future releases of this driver, in which case the
+		ThinkPad volume mixer user interface semanthics will be
+		enforced.
+
+	hotkey_poll_freq:
+		frequency in Hz for hot key polling. It must be between
+		0 and 25 Hz.  Polling is only carried out when strictly
+		needed.
+
+		Setting hotkey_poll_freq to zero disables polling, and
+		will cause hot key presses that require NVRAM polling
+		to never be reported.
+
+		Setting hotkey_poll_freq too low will cause repeated
+		pressings of the same hot key to be misreported as a
+		single key press, or to not even be detected at all.
+		The recommended polling frequency is 10Hz.
+
 	hotkey_radio_sw:
 		if the ThinkPad has a hardware radio switch, this
 		attribute will read 0 if the switch is in the "radios
@@ -1263,3 +1311,14 @@ Sysfs interface changelog:
 		and the hwmon class for libsensors4 (lm-sensors 3)
 		compatibility.  Moved all hwmon attributes to this
 		new platform device.
+
+0x020100:	Marker for thinkpad-acpi with hot key NVRAM polling
+		support.  If you must, use it to know you should not
+		start an userspace NVRAM poller (allows to detect when
+		NVRAM is compiled out by the user because it is
+		unneeded/undesired in the first place).
+0x020101:	Marker for thinkpad-acpi with hot key NVRAM polling
+		and proper hotkey_mask semanthics (version 8 of the
+		NVRAM polling patch).  Some development snapshots of
+		0.18 had an earlier version that did strange things
+		to hotkey_mask.
drivers/misc/Kconfig +19 -0
index b5e67c0..b1f9a40 100644
@@ -219,6 +219,25 @@ config THINKPAD_ACPI_BAY
 
 	  If you are not sure, say Y here.
 
+config THINKPAD_ACPI_HOTKEY_POLL
+	bool "Suport NVRAM polling for hot keys"
+	depends on THINKPAD_ACPI
+	default y
+	---help---
+	  Some thinkpad models benefit from NVRAM polling to detect a few of
+	  the hot key press events.  If you know your ThinkPad model does not
+	  need to do NVRAM polling to support any of the hot keys you use,
+	  unselecting this option will save about 1kB of memory.
+
+	  ThinkPads T40 and newer, R52 and newer, and X31 and newer are
+	  unlikely to need NVRAM polling in their latest BIOS versions.
+
+	  NVRAM polling can detect at most the following keys: ThinkPad/Access
+	  IBM, Zoom, Switch Display (fn+F7), ThinkLight, Volume up/down/mute,
+	  Brightness up/down, Display Expand (fn+F8), Hibernate (fn+F12).
+
+	  If you are not sure, say Y here.  The driver enables polling only if
+	  it is strictly necessary to do so.
 
 config ATMEL_SSC
 	tristate "Device driver for Atmel SSC peripheral"
drivers/misc/thinkpad_acpi.c +492 -13

663 lines not on this page · raw message

drivers/misc/thinkpad_acpi.h +56 -4

84 lines not on this page · raw message

Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#36 lore raw

PATCH 36/112 ACPI: thinkpad-acpi: bump up version to 0.18

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

The NVRAM polling support for hot keys is reason enough to bump up the version string. Do it.

---
 Documentation/thinkpad-acpi.txt |    4 ++--
 drivers/misc/thinkpad_acpi.c    |    2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)
Documentation/thinkpad-acpi.txt +2 -2
index 70d91a5..7c7bd47 100644
@@ -1,7 +1,7 @@
 		     ThinkPad ACPI Extras Driver
 
-                            Version 0.17
-                         October 04th, 2007
+                            Version 0.18
+                         October 08th, 2007
 
                Borislav Deianov <[email protected]>
              Henrique de Moraes Holschuh <[email protected]>
drivers/misc/thinkpad_acpi.c +1 -1
index 9ff9142..11ee444 100644
@@ -21,7 +21,7 @@
  *  02110-1301, USA.
  */
 
-#define IBM_VERSION "0.17"
+#define IBM_VERSION "0.18"
 #define TPACPI_SYSFS_VERSION 0x020101
 
 /*
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#37 lore raw

PATCH 37/112 ACPI: thinkpad-acpi: spring cleanup part 1

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

Remove the header file. Private header files used by a single .c file are in bad taste, and I know better now.

---
 drivers/misc/thinkpad_acpi.c |  632 ++++++++++++++++++++++++++++++++++++++++-
 drivers/misc/thinkpad_acpi.h |  656 ------------------------------------------
 2 files changed, 631 insertions(+), 657 deletions(-)
 delete mode 100644 drivers/misc/thinkpad_acpi.h
drivers/misc/thinkpad_acpi.c +631 -1
index 11ee444..59b127c 100644
@@ -82,7 +82,637 @@
  *  2004-08-09	0.1	initial release, support for X series
  */
 
-#include "thinkpad_acpi.h"
+/* ==================================================== BEGIN HEADER */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/delay.h>
+
+#include <linux/nvram.h>
+#include <linux/proc_fs.h>
+#include <linux/sysfs.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/input.h>
+#include <asm/uaccess.h>
+
+#include <linux/dmi.h>
+#include <linux/jiffies.h>
+#include <linux/workqueue.h>
+
+#include <acpi/acpi_drivers.h>
+#include <acpi/acnamesp.h>
+
+#include <linux/pci_ids.h>
+
+/****************************************************************************
+ * Main driver
+ */
+
+#define IBM_NAME "thinkpad"
+#define IBM_DESC "ThinkPad ACPI Extras"
+#define IBM_FILE IBM_NAME "_acpi"
+#define IBM_URL "http://ibm-acpi.sf.net/"
+#define IBM_MAIL "[email protected]"
+
+#define IBM_PROC_DIR "ibm"
+#define IBM_ACPI_EVENT_PREFIX "ibm"
+#define IBM_DRVR_NAME IBM_FILE
+#define IBM_HWMON_DRVR_NAME IBM_NAME "_hwmon"
+
+#define IBM_LOG IBM_FILE ": "
+#define IBM_ERR	   KERN_ERR    IBM_LOG
+#define IBM_NOTICE KERN_NOTICE IBM_LOG
+#define IBM_INFO   KERN_INFO   IBM_LOG
+#define IBM_DEBUG  KERN_DEBUG  IBM_LOG
+
+#define IBM_MAX_ACPI_ARGS 3
+
+/* ThinkPad CMOS commands */
+#define TP_CMOS_VOLUME_DOWN	0
+#define TP_CMOS_VOLUME_UP	1
+#define TP_CMOS_VOLUME_MUTE	2
+#define TP_CMOS_BRIGHTNESS_UP	4
+#define TP_CMOS_BRIGHTNESS_DOWN	5
+
+/* NVRAM Addresses */
+enum tp_nvram_addr {
+	TP_NVRAM_ADDR_HK2		= 0x57,
+	TP_NVRAM_ADDR_THINKLIGHT	= 0x58,
+	TP_NVRAM_ADDR_VIDEO		= 0x59,
+	TP_NVRAM_ADDR_BRIGHTNESS	= 0x5e,
+	TP_NVRAM_ADDR_MIXER		= 0x60,
+};
+
+/* NVRAM bit masks */
+enum {
+	TP_NVRAM_MASK_HKT_THINKPAD	= 0x08,
+	TP_NVRAM_MASK_HKT_ZOOM		= 0x20,
+	TP_NVRAM_MASK_HKT_DISPLAY	= 0x40,
+	TP_NVRAM_MASK_HKT_HIBERNATE	= 0x80,
+	TP_NVRAM_MASK_THINKLIGHT	= 0x10,
+	TP_NVRAM_MASK_HKT_DISPEXPND	= 0x30,
+	TP_NVRAM_MASK_HKT_BRIGHTNESS	= 0x20,
+	TP_NVRAM_MASK_LEVEL_BRIGHTNESS	= 0x0f,
+	TP_NVRAM_POS_LEVEL_BRIGHTNESS	= 0,
+	TP_NVRAM_MASK_MUTE		= 0x40,
+	TP_NVRAM_MASK_HKT_VOLUME	= 0x80,
+	TP_NVRAM_MASK_LEVEL_VOLUME	= 0x0f,
+	TP_NVRAM_POS_LEVEL_VOLUME	= 0,
+};
+
+#define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off")
+#define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
+#define strlencmp(a,b) (strncmp((a), (b), strlen(b)))
+
+/* Debugging */
+#define TPACPI_DBG_ALL		0xffff
+#define TPACPI_DBG_ALL		0xffff
+#define TPACPI_DBG_INIT		0x0001
+#define TPACPI_DBG_EXIT		0x0002
+#define dbg_printk(a_dbg_level, format, arg...) \
+	do { if (dbg_level & a_dbg_level) \
+		printk(IBM_DEBUG "%s: " format, __func__ , ## arg); } while (0)
+#ifdef CONFIG_THINKPAD_ACPI_DEBUG
+#define vdbg_printk(a_dbg_level, format, arg...) \
+	dbg_printk(a_dbg_level, format, ## arg)
+static const char *str_supported(int is_supported);
+#else
+#define vdbg_printk(a_dbg_level, format, arg...)
+#endif
+
+/* Input IDs */
+#define TPACPI_HKEY_INPUT_VENDOR	PCI_VENDOR_ID_IBM
+#define TPACPI_HKEY_INPUT_PRODUCT	0x5054 /* "TP" */
+#define TPACPI_HKEY_INPUT_VERSION	0x4101
+
+/* ACPI HIDs */
+#define IBM_HKEY_HID    "IBM0068"
+
+/* ACPI helpers */
+static int __must_check acpi_evalf(acpi_handle handle,
+		      void *res, char *method, char *fmt, ...);
+static int __must_check acpi_ec_read(int i, u8 * p);
+static int __must_check acpi_ec_write(int i, u8 v);
+static int __must_check _sta(acpi_handle handle);
+
+/* ACPI handles */
+static acpi_handle root_handle;			/* root namespace */
+static acpi_handle ec_handle;			/* EC */
+static acpi_handle ecrd_handle, ecwr_handle;	/* 570 EC access */
+static acpi_handle cmos_handle, hkey_handle;	/* basic thinkpad handles */
+
+static void drv_acpi_handle_init(char *name,
+		   acpi_handle *handle, acpi_handle parent,
+		   char **paths, int num_paths, char **path);
+#define IBM_ACPIHANDLE_INIT(object)						\
+	drv_acpi_handle_init(#object, &object##_handle, *object##_parent,	\
+		object##_paths, ARRAY_SIZE(object##_paths), &object##_path)
+
+/* ThinkPad ACPI helpers */
+static int issue_thinkpad_cmos_command(int cmos_cmd);
+
+/* procfs support */
+static struct proc_dir_entry *proc_dir;
+
+/* procfs helpers */
+static int dispatch_procfs_read(char *page, char **start, off_t off,
+		int count, int *eof, void *data);
+static int dispatch_procfs_write(struct file *file,
+		const char __user * userbuf,
+		unsigned long count, void *data);
+static char *next_cmd(char **cmds);
+
+/* sysfs support */
+struct attribute_set {
+	unsigned int members, max_members;
+	struct attribute_group group;
+};
+
+static struct attribute_set *create_attr_set(unsigned int max_members,
+						const char* name);
+#define destroy_attr_set(_set) \
+	kfree(_set);
+static int add_to_attr_set(struct attribute_set* s, struct attribute *attr);
+static int add_many_to_attr_set(struct attribute_set* s,
+			struct attribute **attr,
+			unsigned int count);
+#define register_attr_set_with_sysfs(_attr_set, _kobj) \
+	sysfs_create_group(_kobj, &_attr_set->group)
+static void delete_attr_set(struct attribute_set* s, struct kobject *kobj);
+
+static int parse_strtoul(const char *buf, unsigned long max,
+			unsigned long *value);
+
+/* Device model */
+static struct platform_device *tpacpi_pdev;
+static struct platform_device *tpacpi_sensors_pdev;
+static struct device *tpacpi_hwmon;
+static struct platform_driver tpacpi_pdriver;
+static struct input_dev *tpacpi_inputdev;
+static int tpacpi_create_driver_attributes(struct device_driver *drv);
+static void tpacpi_remove_driver_attributes(struct device_driver *drv);
+
+/* Module */
+static int experimental;
+static u32 dbg_level;
+static int force_load;
+static unsigned int hotkey_report_mode;
+
+static int thinkpad_acpi_module_init(void);
+static void thinkpad_acpi_module_exit(void);
+
+
+/****************************************************************************
+ * Subdrivers
+ */
+
+struct ibm_struct;
+
+struct tp_acpi_drv_struct {
+	const struct acpi_device_id *hid;
+	struct acpi_driver *driver;
+
+	void (*notify) (struct ibm_struct *, u32);
+	acpi_handle *handle;
+	u32 type;
+	struct acpi_device *device;
+};
+
+struct ibm_struct {
+	char *name;
+
+	int (*read) (char *);
+	int (*write) (char *);
+	void (*exit) (void);
+	void (*resume) (void);
+
+	struct list_head all_drivers;
+
+	struct tp_acpi_drv_struct *acpi;
+
+	struct {
+		u8 acpi_driver_registered:1;
+		u8 acpi_notify_installed:1;
+		u8 proc_created:1;
+		u8 init_called:1;
+		u8 experimental:1;
+	} flags;
+};
+
+struct ibm_init_struct {
+	char param[32];
+
+	int (*init) (struct ibm_init_struct *);
+	struct ibm_struct *data;
+};
+
+static struct {
+#ifdef CONFIG_THINKPAD_ACPI_BAY
+	u32 bay_status:1;
+	u32 bay_eject:1;
+	u32 bay_status2:1;
+	u32 bay_eject2:1;
+#endif
+	u32 bluetooth:1;
+	u32 hotkey:1;
+	u32 hotkey_mask:1;
+	u32 hotkey_wlsw:1;
+	u32 light:1;
+	u32 light_status:1;
+	u32 bright_16levels:1;
+	u32 wan:1;
+	u32 fan_ctrl_status_undef:1;
+	u32 input_device_registered:1;
+	u32 platform_drv_registered:1;
+	u32 platform_drv_attrs_registered:1;
+	u32 sensors_pdrv_registered:1;
+	u32 sensors_pdrv_attrs_registered:1;
+	u32 sensors_pdev_attrs_registered:1;
+	u32 hotkey_poll_active:1;
+} tp_features;
+
+struct thinkpad_id_data {
+	unsigned int vendor;	/* ThinkPad vendor:
+				 * PCI_VENDOR_ID_IBM/PCI_VENDOR_ID_LENOVO */
+
+	char *bios_version_str;	/* Something like 1ZET51WW (1.03z) */
+	char *ec_version_str;	/* Something like 1ZHT51WW-1.04a */
+
+	u16 bios_model;		/* Big Endian, TP-1Y = 0x5931, 0 = unknown */
+	u16 ec_model;
+
+	char *model_str;
+};
+
+static struct thinkpad_id_data thinkpad_id;
+
+static struct list_head tpacpi_all_drivers;
+
+static struct ibm_init_struct ibms_init[];
+static int set_ibm_param(const char *val, struct kernel_param *kp);
+static int ibm_init(struct ibm_init_struct *iibm);
+static void ibm_exit(struct ibm_struct *ibm);
+
+
+/*
+ * procfs master subdriver
+ */
+static int thinkpad_acpi_driver_init(struct ibm_init_struct *iibm);
+static int thinkpad_acpi_driver_read(char *p);
+
+
+/*
+ * Bay subdriver
+ */
+
+#ifdef CONFIG_THINKPAD_ACPI_BAY
+static acpi_handle bay_handle, bay_ej_handle;
+static acpi_handle bay2_handle, bay2_ej_handle;
+
+static int bay_init(struct ibm_init_struct *iibm);
+static void bay_notify(struct ibm_struct *ibm, u32 event);
+static int bay_read(char *p);
+static int bay_write(char *buf);
+#endif /* CONFIG_THINKPAD_ACPI_BAY */
+
+
+/*
+ * Beep subdriver
+ */
+
+static acpi_handle beep_handle;
+
+static int beep_read(char *p);
+static int beep_write(char *buf);
+
+
+/*
+ * Bluetooth subdriver
+ */
+
+enum {
+	/* ACPI GBDC/SBDC bits */
+	TP_ACPI_BLUETOOTH_HWPRESENT	= 0x01,	/* Bluetooth hw available */
+	TP_ACPI_BLUETOOTH_RADIOSSW	= 0x02,	/* Bluetooth radio enabled */
+	TP_ACPI_BLUETOOTH_UNK		= 0x04,	/* unknown function */
+};
+
+static int bluetooth_init(struct ibm_init_struct *iibm);
+static int bluetooth_get_radiosw(void);
+static int bluetooth_set_radiosw(int radio_on);
+static int bluetooth_read(char *p);
+static int bluetooth_write(char *buf);
+
+
+/*
+ * Brightness (backlight) subdriver
+ */
+
+#define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen"
+
+static struct backlight_device *ibm_backlight_device;
+static int brightness_offset = 0x31;
+static int brightness_mode;
+static unsigned int brightness_enable;	/* 0 = no, 1 = yes, 2 = auto */
+
+static int brightness_init(struct ibm_init_struct *iibm);
+static void brightness_exit(void);
+static int brightness_get(struct backlight_device *bd);
+static int brightness_set(int value);
+static int brightness_update_status(struct backlight_device *bd);
+static int brightness_read(char *p);
+static int brightness_write(char *buf);
+
+
+/*
+ * CMOS subdriver
+ */
+
+static int cmos_read(char *p);
+static int cmos_write(char *buf);
+
+
+/*
+ * Dock subdriver
+ */
+
+#ifdef CONFIG_THINKPAD_ACPI_DOCK
+static acpi_handle pci_handle;
+static acpi_handle dock_handle;
+
+static void dock_notify(struct ibm_struct *ibm, u32 event);
+static int dock_read(char *p);
+static int dock_write(char *buf);
+#endif /* CONFIG_THINKPAD_ACPI_DOCK */
+
+
+/*
+ * EC dump subdriver
+ */
+
+static int ecdump_read(char *p) ;
+static int ecdump_write(char *buf);
+
+
+/*
+ * Fan subdriver
+ */
+
+enum {					/* Fan control constants */
+	fan_status_offset = 0x2f,	/* EC register 0x2f */
+	fan_rpm_offset = 0x84,		/* EC register 0x84: LSB, 0x85 MSB (RPM)
+					 * 0x84 must be read before 0x85 */
+
+	TP_EC_FAN_FULLSPEED = 0x40,	/* EC fan mode: full speed */
+	TP_EC_FAN_AUTO	    = 0x80,	/* EC fan mode: auto fan control */
+
+	TPACPI_FAN_LAST_LEVEL = 0x100,	/* Use cached last-seen fan level */
+};
+
+enum fan_status_access_mode {
+	TPACPI_FAN_NONE = 0,		/* No fan status or control */
+	TPACPI_FAN_RD_ACPI_GFAN,	/* Use ACPI GFAN */
+	TPACPI_FAN_RD_TPEC,		/* Use ACPI EC regs 0x2f, 0x84-0x85 */
+};
+
+enum fan_control_access_mode {
+	TPACPI_FAN_WR_NONE = 0,		/* No fan control */
+	TPACPI_FAN_WR_ACPI_SFAN,	/* Use ACPI SFAN */
+	TPACPI_FAN_WR_TPEC,		/* Use ACPI EC reg 0x2f */
+	TPACPI_FAN_WR_ACPI_FANS,	/* Use ACPI FANS and EC reg 0x2f */
+};
+
+enum fan_control_commands {
+	TPACPI_FAN_CMD_SPEED 	= 0x0001,	/* speed command */
+	TPACPI_FAN_CMD_LEVEL 	= 0x0002,	/* level command  */
+	TPACPI_FAN_CMD_ENABLE	= 0x0004,	/* enable/disable cmd,
+						 * and also watchdog cmd */
+};
+
+static int fan_control_allowed;
+
+static enum fan_status_access_mode fan_status_access_mode;
+static enum fan_control_access_mode fan_control_access_mode;
+static enum fan_control_commands fan_control_commands;
+static u8 fan_control_initial_status;
+static u8 fan_control_desired_level;
+static int fan_watchdog_maxinterval;
+
+static struct mutex fan_mutex;
+
+static acpi_handle fans_handle, gfan_handle, sfan_handle;
+
+static int fan_init(struct ibm_init_struct *iibm);
+static void fan_exit(void);
+static int fan_get_status(u8 *status);
+static int fan_get_status_safe(u8 *status);
+static int fan_get_speed(unsigned int *speed);
+static void fan_update_desired_level(u8 status);
+static void fan_watchdog_fire(struct work_struct *ignored);
+static void fan_watchdog_reset(void);
+static int fan_set_level(int level);
+static int fan_set_level_safe(int level);
+static int fan_set_enable(void);
+static int fan_set_disable(void);
+static int fan_set_speed(int speed);
+static int fan_read(char *p);
+static int fan_write(char *buf);
+static int fan_write_cmd_level(const char *cmd, int *rc);
+static int fan_write_cmd_enable(const char *cmd, int *rc);
+static int fan_write_cmd_disable(const char *cmd, int *rc);
+static int fan_write_cmd_speed(const char *cmd, int *rc);
+static int fan_write_cmd_watchdog(const char *cmd, int *rc);
+
+
+/*
+ * Hotkey subdriver
+ */
+
+enum {	/* hot key scan codes (derived from ACPI DSDT) */
+	TP_ACPI_HOTKEYSCAN_FNF1		= 0,
+	TP_ACPI_HOTKEYSCAN_FNF2,
+	TP_ACPI_HOTKEYSCAN_FNF3,
+	TP_ACPI_HOTKEYSCAN_FNF4,
+	TP_ACPI_HOTKEYSCAN_FNF5,
+	TP_ACPI_HOTKEYSCAN_FNF6,
+	TP_ACPI_HOTKEYSCAN_FNF7,
+	TP_ACPI_HOTKEYSCAN_FNF8,
+	TP_ACPI_HOTKEYSCAN_FNF9,
+	TP_ACPI_HOTKEYSCAN_FNF10,
+	TP_ACPI_HOTKEYSCAN_FNF11,
+	TP_ACPI_HOTKEYSCAN_FNF12,
+	TP_ACPI_HOTKEYSCAN_FNBACKSPACE,
+	TP_ACPI_HOTKEYSCAN_FNINSERT,
+	TP_ACPI_HOTKEYSCAN_FNDELETE,
+	TP_ACPI_HOTKEYSCAN_FNHOME,
+	TP_ACPI_HOTKEYSCAN_FNEND,
+	TP_ACPI_HOTKEYSCAN_FNPAGEUP,
+	TP_ACPI_HOTKEYSCAN_FNPAGEDOWN,
+	TP_ACPI_HOTKEYSCAN_FNSPACE,
+	TP_ACPI_HOTKEYSCAN_VOLUMEUP,
+	TP_ACPI_HOTKEYSCAN_VOLUMEDOWN,
+	TP_ACPI_HOTKEYSCAN_MUTE,
+	TP_ACPI_HOTKEYSCAN_THINKPAD,
+};
+
+static int hotkey_orig_status;
+static u32 hotkey_orig_mask;
+
+static struct mutex hotkey_mutex;
+
+static int hotkey_init(struct ibm_init_struct *iibm);
+static void hotkey_exit(void);
+static void hotkey_notify(struct ibm_struct *ibm, u32 event);
+static int hotkey_read(char *p);
+static int hotkey_write(char *buf);
+
+
+/*
+ * LED subdriver
+ */
+
+enum led_access_mode {
+	TPACPI_LED_NONE = 0,
+	TPACPI_LED_570,	/* 570 */
+	TPACPI_LED_OLD,	/* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
+	TPACPI_LED_NEW,	/* all others */
+};
+
+enum {	/* For TPACPI_LED_OLD */
+	TPACPI_LED_EC_HLCL = 0x0c,	/* EC reg to get led to power on */
+	TPACPI_LED_EC_HLBL = 0x0d,	/* EC reg to blink a lit led */
+	TPACPI_LED_EC_HLMS = 0x0e,	/* EC reg to select led to command */
+};
+
+static enum led_access_mode led_supported;
+static acpi_handle led_handle;
+
+static int led_init(struct ibm_init_struct *iibm);
+static int led_read(char *p);
+static int led_write(char *buf);
+
+/*
+ * Light (thinklight) subdriver
+ */
+
+static acpi_handle lght_handle, ledb_handle;
+
+static int light_init(struct ibm_init_struct *iibm);
+static int light_read(char *p);
+static int light_write(char *buf);
+
+
+/*
+ * Thermal subdriver
+ */
+
+enum thermal_access_mode {
+	TPACPI_THERMAL_NONE = 0,	/* No thermal support */
+	TPACPI_THERMAL_ACPI_TMP07,	/* Use ACPI TMP0-7 */
+	TPACPI_THERMAL_ACPI_UPDT,	/* Use ACPI TMP0-7 with UPDT */
+	TPACPI_THERMAL_TPEC_8,		/* Use ACPI EC regs, 8 sensors */
+	TPACPI_THERMAL_TPEC_16,		/* Use ACPI EC regs, 16 sensors */
+};
+
+enum { /* TPACPI_THERMAL_TPEC_* */
+	TP_EC_THERMAL_TMP0 = 0x78,	/* ACPI EC regs TMP 0..7 */
+	TP_EC_THERMAL_TMP8 = 0xC0,	/* ACPI EC regs TMP 8..15 */
+	TP_EC_THERMAL_TMP_NA = -128,	/* ACPI EC sensor not available */
+};
+
+#define TPACPI_MAX_THERMAL_SENSORS 16	/* Max thermal sensors supported */
+struct ibm_thermal_sensors_struct {
+	s32 temp[TPACPI_MAX_THERMAL_SENSORS];
+};
+
+static enum thermal_access_mode thermal_read_mode;
+
+static int thermal_init(struct ibm_init_struct *iibm);
+static int thermal_get_sensor(int idx, s32 *value);
+static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s);
+static int thermal_read(char *p);
+
+
+/*
+ * Video subdriver
+ */
+
+enum video_access_mode {
+	TPACPI_VIDEO_NONE = 0,
+	TPACPI_VIDEO_570,	/* 570 */
+	TPACPI_VIDEO_770,	/* 600e/x, 770e, 770x */
+	TPACPI_VIDEO_NEW,	/* all others */
+};
+
+enum {	/* video status flags, based on VIDEO_570 */
+	TP_ACPI_VIDEO_S_LCD = 0x01,	/* LCD output enabled */
+	TP_ACPI_VIDEO_S_CRT = 0x02,	/* CRT output enabled */
+	TP_ACPI_VIDEO_S_DVI = 0x08,	/* DVI output enabled */
+};
+
+enum {  /* TPACPI_VIDEO_570 constants */
+	TP_ACPI_VIDEO_570_PHSCMD = 0x87,	/* unknown magic constant :( */
+	TP_ACPI_VIDEO_570_PHSMASK = 0x03,	/* PHS bits that map to
+						 * video_status_flags */
+	TP_ACPI_VIDEO_570_PHS2CMD = 0x8b,	/* unknown magic constant :( */
+	TP_ACPI_VIDEO_570_PHS2SET = 0x80,	/* unknown magic constant :( */
+};
+
+static enum video_access_mode video_supported;
+static int video_orig_autosw;
+static acpi_handle vid_handle, vid2_handle;
+
+static int video_init(struct ibm_init_struct *iibm);
+static void video_exit(void);
+static int video_outputsw_get(void);
+static int video_outputsw_set(int status);
+static int video_autosw_get(void);
+static int video_autosw_set(int enable);
+static int video_outputsw_cycle(void);
+static int video_expand_toggle(void);
+static int video_read(char *p);
+static int video_write(char *buf);
+
+
+/*
+ * Volume subdriver
+ */
+
+static int volume_offset = 0x30;
+
+static int volume_read(char *p);
+static int volume_write(char *buf);
+
+
+/*
+ * Wan subdriver
+ */
+
+enum {
+	/* ACPI GWAN/SWAN bits */
+	TP_ACPI_WANCARD_HWPRESENT	= 0x01,	/* Wan hw available */
+	TP_ACPI_WANCARD_RADIOSSW	= 0x02,	/* Wan radio enabled */
+	TP_ACPI_WANCARD_UNK		= 0x04,	/* unknown function */
+};
+
+static int wan_init(struct ibm_init_struct *iibm);
+static int wan_get_radiosw(void);
+static int wan_set_radiosw(int radio_on);
+static int wan_read(char *p);
+static int wan_write(char *buf);
+
+/* ==================================================== END HEADER */
 
 MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
 MODULE_DESCRIPTION(IBM_DESC);
drivers/misc/thinkpad_acpi.h deleted +0 -656

656 lines not on this page · raw message

Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#38 lore raw

PATCH 38/112 ACPI: thinkpad-acpi: spring cleanup part 2

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

Move most subdriver-related stuff imported from the header file closer to their subdriver code. Also, delete unneeded forward declarations.

---
 drivers/misc/thinkpad_acpi.c |  613 +++++++++++++-----------------------------
 1 files changed, 185 insertions(+), 428 deletions(-)
drivers/misc/thinkpad_acpi.c +185 -428
index 59b127c..e435b55 100644
@@ -82,8 +82,6 @@
  *  2004-08-09	0.1	initial release, support for X series
  */
 
-/* ==================================================== BEGIN HEADER */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -199,79 +197,22 @@ static const char *str_supported(int is_supported);
 /* ACPI HIDs */
 #define IBM_HKEY_HID    "IBM0068"
 
-/* ACPI helpers */
-static int __must_check acpi_evalf(acpi_handle handle,
-		      void *res, char *method, char *fmt, ...);
-static int __must_check acpi_ec_read(int i, u8 * p);
-static int __must_check acpi_ec_write(int i, u8 v);
-static int __must_check _sta(acpi_handle handle);
-
-/* ACPI handles */
-static acpi_handle root_handle;			/* root namespace */
-static acpi_handle ec_handle;			/* EC */
-static acpi_handle ecrd_handle, ecwr_handle;	/* 570 EC access */
-static acpi_handle cmos_handle, hkey_handle;	/* basic thinkpad handles */
-
-static void drv_acpi_handle_init(char *name,
-		   acpi_handle *handle, acpi_handle parent,
-		   char **paths, int num_paths, char **path);
-#define IBM_ACPIHANDLE_INIT(object)						\
-	drv_acpi_handle_init(#object, &object##_handle, *object##_parent,	\
-		object##_paths, ARRAY_SIZE(object##_paths), &object##_path)
-
-/* ThinkPad ACPI helpers */
-static int issue_thinkpad_cmos_command(int cmos_cmd);
-
-/* procfs support */
-static struct proc_dir_entry *proc_dir;
-
-/* procfs helpers */
-static int dispatch_procfs_read(char *page, char **start, off_t off,
-		int count, int *eof, void *data);
-static int dispatch_procfs_write(struct file *file,
-		const char __user * userbuf,
-		unsigned long count, void *data);
-static char *next_cmd(char **cmds);
-
 /* sysfs support */
 struct attribute_set {
 	unsigned int members, max_members;
 	struct attribute_group group;
 };
 
-static struct attribute_set *create_attr_set(unsigned int max_members,
-						const char* name);
-#define destroy_attr_set(_set) \
-	kfree(_set);
-static int add_to_attr_set(struct attribute_set* s, struct attribute *attr);
-static int add_many_to_attr_set(struct attribute_set* s,
-			struct attribute **attr,
-			unsigned int count);
-#define register_attr_set_with_sysfs(_attr_set, _kobj) \
-	sysfs_create_group(_kobj, &_attr_set->group)
-static void delete_attr_set(struct attribute_set* s, struct kobject *kobj);
-
+/* Helpers */
 static int parse_strtoul(const char *buf, unsigned long max,
 			unsigned long *value);
 
-/* Device model */
-static struct platform_device *tpacpi_pdev;
-static struct platform_device *tpacpi_sensors_pdev;
-static struct device *tpacpi_hwmon;
-static struct platform_driver tpacpi_pdriver;
-static struct input_dev *tpacpi_inputdev;
-static int tpacpi_create_driver_attributes(struct device_driver *drv);
-static void tpacpi_remove_driver_attributes(struct device_driver *drv);
-
 /* Module */
 static int experimental;
 static u32 dbg_level;
 static int force_load;
 static unsigned int hotkey_report_mode;
 
-static int thinkpad_acpi_module_init(void);
-static void thinkpad_acpi_module_exit(void);
-
 
 /****************************************************************************
  * Subdrivers
@@ -354,365 +295,9 @@ struct thinkpad_id_data {
 
 	char *model_str;
 };
-
 static struct thinkpad_id_data thinkpad_id;
 
-static struct list_head tpacpi_all_drivers;
-
-static struct ibm_init_struct ibms_init[];
-static int set_ibm_param(const char *val, struct kernel_param *kp);
-static int ibm_init(struct ibm_init_struct *iibm);
-static void ibm_exit(struct ibm_struct *ibm);
-
-
-/*
- * procfs master subdriver
- */
-static int thinkpad_acpi_driver_init(struct ibm_init_struct *iibm);
-static int thinkpad_acpi_driver_read(char *p);
-
-
-/*
- * Bay subdriver
- */
-
-#ifdef CONFIG_THINKPAD_ACPI_BAY
-static acpi_handle bay_handle, bay_ej_handle;
-static acpi_handle bay2_handle, bay2_ej_handle;
-
-static int bay_init(struct ibm_init_struct *iibm);
-static void bay_notify(struct ibm_struct *ibm, u32 event);
-static int bay_read(char *p);
-static int bay_write(char *buf);
-#endif /* CONFIG_THINKPAD_ACPI_BAY */
-
-
-/*
- * Beep subdriver
- */
-
-static acpi_handle beep_handle;
-
-static int beep_read(char *p);
-static int beep_write(char *buf);
-
-
-/*
- * Bluetooth subdriver
- */
-
-enum {
-	/* ACPI GBDC/SBDC bits */
-	TP_ACPI_BLUETOOTH_HWPRESENT	= 0x01,	/* Bluetooth hw available */
-	TP_ACPI_BLUETOOTH_RADIOSSW	= 0x02,	/* Bluetooth radio enabled */
-	TP_ACPI_BLUETOOTH_UNK		= 0x04,	/* unknown function */
-};
-
-static int bluetooth_init(struct ibm_init_struct *iibm);
-static int bluetooth_get_radiosw(void);
-static int bluetooth_set_radiosw(int radio_on);
-static int bluetooth_read(char *p);
-static int bluetooth_write(char *buf);
-
-
-/*
- * Brightness (backlight) subdriver
- */
-
-#define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen"
-
-static struct backlight_device *ibm_backlight_device;
-static int brightness_offset = 0x31;
-static int brightness_mode;
-static unsigned int brightness_enable;	/* 0 = no, 1 = yes, 2 = auto */
-
-static int brightness_init(struct ibm_init_struct *iibm);
-static void brightness_exit(void);
-static int brightness_get(struct backlight_device *bd);
-static int brightness_set(int value);
-static int brightness_update_status(struct backlight_device *bd);
-static int brightness_read(char *p);
-static int brightness_write(char *buf);
-
-
-/*
- * CMOS subdriver
- */
-
-static int cmos_read(char *p);
-static int cmos_write(char *buf);
-
-
-/*
- * Dock subdriver
- */
-
-#ifdef CONFIG_THINKPAD_ACPI_DOCK
-static acpi_handle pci_handle;
-static acpi_handle dock_handle;
-
-static void dock_notify(struct ibm_struct *ibm, u32 event);
-static int dock_read(char *p);
-static int dock_write(char *buf);
-#endif /* CONFIG_THINKPAD_ACPI_DOCK */
-
-
-/*
- * EC dump subdriver
- */
-
-static int ecdump_read(char *p) ;
-static int ecdump_write(char *buf);
-
-
-/*
- * Fan subdriver
- */
-
-enum {					/* Fan control constants */
-	fan_status_offset = 0x2f,	/* EC register 0x2f */
-	fan_rpm_offset = 0x84,		/* EC register 0x84: LSB, 0x85 MSB (RPM)
-					 * 0x84 must be read before 0x85 */
-
-	TP_EC_FAN_FULLSPEED = 0x40,	/* EC fan mode: full speed */
-	TP_EC_FAN_AUTO	    = 0x80,	/* EC fan mode: auto fan control */
-
-	TPACPI_FAN_LAST_LEVEL = 0x100,	/* Use cached last-seen fan level */
-};
-
-enum fan_status_access_mode {
-	TPACPI_FAN_NONE = 0,		/* No fan status or control */
-	TPACPI_FAN_RD_ACPI_GFAN,	/* Use ACPI GFAN */
-	TPACPI_FAN_RD_TPEC,		/* Use ACPI EC regs 0x2f, 0x84-0x85 */
-};
-
-enum fan_control_access_mode {
-	TPACPI_FAN_WR_NONE = 0,		/* No fan control */
-	TPACPI_FAN_WR_ACPI_SFAN,	/* Use ACPI SFAN */
-	TPACPI_FAN_WR_TPEC,		/* Use ACPI EC reg 0x2f */
-	TPACPI_FAN_WR_ACPI_FANS,	/* Use ACPI FANS and EC reg 0x2f */
-};
-
-enum fan_control_commands {
-	TPACPI_FAN_CMD_SPEED 	= 0x0001,	/* speed command */
-	TPACPI_FAN_CMD_LEVEL 	= 0x0002,	/* level command  */
-	TPACPI_FAN_CMD_ENABLE	= 0x0004,	/* enable/disable cmd,
-						 * and also watchdog cmd */
-};
-
-static int fan_control_allowed;
-
-static enum fan_status_access_mode fan_status_access_mode;
-static enum fan_control_access_mode fan_control_access_mode;
-static enum fan_control_commands fan_control_commands;
-static u8 fan_control_initial_status;
-static u8 fan_control_desired_level;
-static int fan_watchdog_maxinterval;
-
-static struct mutex fan_mutex;
-
-static acpi_handle fans_handle, gfan_handle, sfan_handle;
-
-static int fan_init(struct ibm_init_struct *iibm);
-static void fan_exit(void);
-static int fan_get_status(u8 *status);
-static int fan_get_status_safe(u8 *status);
-static int fan_get_speed(unsigned int *speed);
-static void fan_update_desired_level(u8 status);
-static void fan_watchdog_fire(struct work_struct *ignored);
-static void fan_watchdog_reset(void);
-static int fan_set_level(int level);
-static int fan_set_level_safe(int level);
-static int fan_set_enable(void);
-static int fan_set_disable(void);
-static int fan_set_speed(int speed);
-static int fan_read(char *p);
-static int fan_write(char *buf);
-static int fan_write_cmd_level(const char *cmd, int *rc);
-static int fan_write_cmd_enable(const char *cmd, int *rc);
-static int fan_write_cmd_disable(const char *cmd, int *rc);
-static int fan_write_cmd_speed(const char *cmd, int *rc);
-static int fan_write_cmd_watchdog(const char *cmd, int *rc);
-
-
-/*
- * Hotkey subdriver
- */
-
-enum {	/* hot key scan codes (derived from ACPI DSDT) */
-	TP_ACPI_HOTKEYSCAN_FNF1		= 0,
-	TP_ACPI_HOTKEYSCAN_FNF2,
-	TP_ACPI_HOTKEYSCAN_FNF3,
-	TP_ACPI_HOTKEYSCAN_FNF4,
-	TP_ACPI_HOTKEYSCAN_FNF5,
-	TP_ACPI_HOTKEYSCAN_FNF6,
-	TP_ACPI_HOTKEYSCAN_FNF7,
-	TP_ACPI_HOTKEYSCAN_FNF8,
-	TP_ACPI_HOTKEYSCAN_FNF9,
-	TP_ACPI_HOTKEYSCAN_FNF10,
-	TP_ACPI_HOTKEYSCAN_FNF11,
-	TP_ACPI_HOTKEYSCAN_FNF12,
-	TP_ACPI_HOTKEYSCAN_FNBACKSPACE,
-	TP_ACPI_HOTKEYSCAN_FNINSERT,
-	TP_ACPI_HOTKEYSCAN_FNDELETE,
-	TP_ACPI_HOTKEYSCAN_FNHOME,
-	TP_ACPI_HOTKEYSCAN_FNEND,
-	TP_ACPI_HOTKEYSCAN_FNPAGEUP,
-	TP_ACPI_HOTKEYSCAN_FNPAGEDOWN,
-	TP_ACPI_HOTKEYSCAN_FNSPACE,
-	TP_ACPI_HOTKEYSCAN_VOLUMEUP,
-	TP_ACPI_HOTKEYSCAN_VOLUMEDOWN,
-	TP_ACPI_HOTKEYSCAN_MUTE,
-	TP_ACPI_HOTKEYSCAN_THINKPAD,
-};
-
-static int hotkey_orig_status;
-static u32 hotkey_orig_mask;
-
-static struct mutex hotkey_mutex;
-
-static int hotkey_init(struct ibm_init_struct *iibm);
-static void hotkey_exit(void);
-static void hotkey_notify(struct ibm_struct *ibm, u32 event);
-static int hotkey_read(char *p);
-static int hotkey_write(char *buf);
-
-
-/*
- * LED subdriver
- */
-
-enum led_access_mode {
-	TPACPI_LED_NONE = 0,
-	TPACPI_LED_570,	/* 570 */
-	TPACPI_LED_OLD,	/* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
-	TPACPI_LED_NEW,	/* all others */
-};
-
-enum {	/* For TPACPI_LED_OLD */
-	TPACPI_LED_EC_HLCL = 0x0c,	/* EC reg to get led to power on */
-	TPACPI_LED_EC_HLBL = 0x0d,	/* EC reg to blink a lit led */
-	TPACPI_LED_EC_HLMS = 0x0e,	/* EC reg to select led to command */
-};
-
-static enum led_access_mode led_supported;
-static acpi_handle led_handle;
-
-static int led_init(struct ibm_init_struct *iibm);
-static int led_read(char *p);
-static int led_write(char *buf);
-
-/*
- * Light (thinklight) subdriver
- */
-
-static acpi_handle lght_handle, ledb_handle;
-
-static int light_init(struct ibm_init_struct *iibm);
-static int light_read(char *p);
-static int light_write(char *buf);
-
-
-/*
- * Thermal subdriver
- */
-
-enum thermal_access_mode {
-	TPACPI_THERMAL_NONE = 0,	/* No thermal support */
-	TPACPI_THERMAL_ACPI_TMP07,	/* Use ACPI TMP0-7 */
-	TPACPI_THERMAL_ACPI_UPDT,	/* Use ACPI TMP0-7 with UPDT */
-	TPACPI_THERMAL_TPEC_8,		/* Use ACPI EC regs, 8 sensors */
-	TPACPI_THERMAL_TPEC_16,		/* Use ACPI EC regs, 16 sensors */
-};
-
-enum { /* TPACPI_THERMAL_TPEC_* */
-	TP_EC_THERMAL_TMP0 = 0x78,	/* ACPI EC regs TMP 0..7 */
-	TP_EC_THERMAL_TMP8 = 0xC0,	/* ACPI EC regs TMP 8..15 */
-	TP_EC_THERMAL_TMP_NA = -128,	/* ACPI EC sensor not available */
-};
-
-#define TPACPI_MAX_THERMAL_SENSORS 16	/* Max thermal sensors supported */
-struct ibm_thermal_sensors_struct {
-	s32 temp[TPACPI_MAX_THERMAL_SENSORS];
-};
-
-static enum thermal_access_mode thermal_read_mode;
-
-static int thermal_init(struct ibm_init_struct *iibm);
-static int thermal_get_sensor(int idx, s32 *value);
-static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s);
-static int thermal_read(char *p);
-
-
-/*
- * Video subdriver
- */
-
-enum video_access_mode {
-	TPACPI_VIDEO_NONE = 0,
-	TPACPI_VIDEO_570,	/* 570 */
-	TPACPI_VIDEO_770,	/* 600e/x, 770e, 770x */
-	TPACPI_VIDEO_NEW,	/* all others */
-};
-
-enum {	/* video status flags, based on VIDEO_570 */
-	TP_ACPI_VIDEO_S_LCD = 0x01,	/* LCD output enabled */
-	TP_ACPI_VIDEO_S_CRT = 0x02,	/* CRT output enabled */
-	TP_ACPI_VIDEO_S_DVI = 0x08,	/* DVI output enabled */
-};
-
-enum {  /* TPACPI_VIDEO_570 constants */
-	TP_ACPI_VIDEO_570_PHSCMD = 0x87,	/* unknown magic constant :( */
-	TP_ACPI_VIDEO_570_PHSMASK = 0x03,	/* PHS bits that map to
-						 * video_status_flags */
-	TP_ACPI_VIDEO_570_PHS2CMD = 0x8b,	/* unknown magic constant :( */
-	TP_ACPI_VIDEO_570_PHS2SET = 0x80,	/* unknown magic constant :( */
-};
-
-static enum video_access_mode video_supported;
-static int video_orig_autosw;
-static acpi_handle vid_handle, vid2_handle;
-
-static int video_init(struct ibm_init_struct *iibm);
-static void video_exit(void);
-static int video_outputsw_get(void);
-static int video_outputsw_set(int status);
-static int video_autosw_get(void);
-static int video_autosw_set(int enable);
-static int video_outputsw_cycle(void);
-static int video_expand_toggle(void);
-static int video_read(char *p);
-static int video_write(char *buf);
-
-
-/*
- * Volume subdriver
- */
-
-static int volume_offset = 0x30;
-
-static int volume_read(char *p);
-static int volume_write(char *buf);
-
-
-/*
- * Wan subdriver
- */
-
-enum {
-	/* ACPI GWAN/SWAN bits */
-	TP_ACPI_WANCARD_HWPRESENT	= 0x01,	/* Wan hw available */
-	TP_ACPI_WANCARD_RADIOSSW	= 0x02,	/* Wan radio enabled */
-	TP_ACPI_WANCARD_UNK		= 0x04,	/* unknown function */
-};
-
-static int wan_init(struct ibm_init_struct *iibm);
-static int wan_get_radiosw(void);
-static int wan_set_radiosw(int radio_on);
-static int wan_read(char *p);
-static int wan_write(char *buf);
-
-/* ==================================================== END HEADER */
+static LIST_HEAD(tpacpi_all_drivers);
 
 MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
 MODULE_DESCRIPTION(IBM_DESC);
@@ -948,6 +533,10 @@ static int issue_thinkpad_cmos_command(int cmos_cmd)
  * ACPI device model
  */
 
+#define IBM_ACPIHANDLE_INIT(object)						\
+	drv_acpi_handle_init(#object, &object##_handle, *object##_parent,	\
+		object##_paths, ARRAY_SIZE(object##_paths), &object##_path)
+
 static void drv_acpi_handle_init(char *name,
 			   acpi_handle *handle, acpi_handle parent,
 			   char **paths, int num_paths, char **path)
@@ -1298,6 +887,9 @@ static struct attribute_set *create_attr_set(unsigned int max_members,
 	return &sobj->s;
 }
 
+#define destroy_attr_set(_set) \
+	kfree(_set);
+
 /* not multi-threaded safe, use it in a single thread per set */
 static int add_to_attr_set(struct attribute_set* s, struct attribute *attr)
 {
@@ -1334,6 +926,9 @@ static void delete_attr_set(struct attribute_set* s, struct kobject *kobj)
 	destroy_attr_set(s);
 }
 
+#define register_attr_set_with_sysfs(_attr_set, _kobj) \
+	sysfs_create_group(_kobj, &_attr_set->group)
+
 static int parse_strtoul(const char *buf,
 		unsigned long max, unsigned long *value)
 {
@@ -1403,6 +998,33 @@ static struct ibm_struct thinkpad_acpi_driver_data = {
  * Hotkey subdriver
  */
 
+enum {	/* hot key scan codes (derived from ACPI DSDT) */
+	TP_ACPI_HOTKEYSCAN_FNF1		= 0,
+	TP_ACPI_HOTKEYSCAN_FNF2,
+	TP_ACPI_HOTKEYSCAN_FNF3,
+	TP_ACPI_HOTKEYSCAN_FNF4,
+	TP_ACPI_HOTKEYSCAN_FNF5,
+	TP_ACPI_HOTKEYSCAN_FNF6,
+	TP_ACPI_HOTKEYSCAN_FNF7,
+	TP_ACPI_HOTKEYSCAN_FNF8,
+	TP_ACPI_HOTKEYSCAN_FNF9,
+	TP_ACPI_HOTKEYSCAN_FNF10,
+	TP_ACPI_HOTKEYSCAN_FNF11,
+	TP_ACPI_HOTKEYSCAN_FNF12,
+	TP_ACPI_HOTKEYSCAN_FNBACKSPACE,
+	TP_ACPI_HOTKEYSCAN_FNINSERT,
+	TP_ACPI_HOTKEYSCAN_FNDELETE,
+	TP_ACPI_HOTKEYSCAN_FNHOME,
+	TP_ACPI_HOTKEYSCAN_FNEND,
+	TP_ACPI_HOTKEYSCAN_FNPAGEUP,
+	TP_ACPI_HOTKEYSCAN_FNPAGEDOWN,
+	TP_ACPI_HOTKEYSCAN_FNSPACE,
+	TP_ACPI_HOTKEYSCAN_VOLUMEUP,
+	TP_ACPI_HOTKEYSCAN_VOLUMEDOWN,
+	TP_ACPI_HOTKEYSCAN_MUTE,
+	TP_ACPI_HOTKEYSCAN_THINKPAD,
+};
+
 enum {	/* Keys available through NVRAM polling */
 	TPACPI_HKEY_NVRAM_KNOWN_MASK = 0x00fb88c0U,
 	TPACPI_HKEY_NVRAM_GOOD_MASK  = 0x00fb8000U,
@@ -1464,6 +1086,8 @@ static unsigned int hotkey_config_change;
 
 #endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
 
+static struct mutex hotkey_mutex;
+
 static int hotkey_orig_status;
 static u32 hotkey_orig_mask;
 static u32 hotkey_all_mask;
@@ -2635,6 +2259,16 @@ static struct ibm_struct hotkey_driver_data = {
  * Bluetooth subdriver
  */
 
+enum {
+	/* ACPI GBDC/SBDC bits */
+	TP_ACPI_BLUETOOTH_HWPRESENT	= 0x01,	/* Bluetooth hw available */
+	TP_ACPI_BLUETOOTH_RADIOSSW	= 0x02,	/* Bluetooth radio enabled */
+	TP_ACPI_BLUETOOTH_UNK		= 0x04,	/* unknown function */
+};
+
+static int bluetooth_get_radiosw(void);
+static int bluetooth_set_radiosw(int radio_on);
+
 /* sysfs bluetooth enable ---------------------------------------------- */
 static ssize_t bluetooth_enable_show(struct device *dev,
 			   struct device_attribute *attr,
@@ -2799,6 +2433,16 @@ static struct ibm_struct bluetooth_driver_data = {
  * Wan subdriver
  */
 
+enum {
+	/* ACPI GWAN/SWAN bits */
+	TP_ACPI_WANCARD_HWPRESENT	= 0x01,	/* Wan hw available */
+	TP_ACPI_WANCARD_RADIOSSW	= 0x02,	/* Wan radio enabled */
+	TP_ACPI_WANCARD_UNK		= 0x04,	/* unknown function */
+};
+
+static int wan_get_radiosw(void);
+static int wan_set_radiosw(int radio_on);
+
 /* sysfs wan enable ---------------------------------------------------- */
 static ssize_t wan_enable_show(struct device *dev,
 			   struct device_attribute *attr,
@@ -2962,9 +2606,33 @@ static struct ibm_struct wan_driver_data = {
  * Video subdriver
  */
 
+enum video_access_mode {
+	TPACPI_VIDEO_NONE = 0,
+	TPACPI_VIDEO_570,	/* 570 */
+	TPACPI_VIDEO_770,	/* 600e/x, 770e, 770x */
+	TPACPI_VIDEO_NEW,	/* all others */
+};
+
+enum {	/* video status flags, based on VIDEO_570 */
+	TP_ACPI_VIDEO_S_LCD = 0x01,	/* LCD output enabled */
+	TP_ACPI_VIDEO_S_CRT = 0x02,	/* CRT output enabled */
+	TP_ACPI_VIDEO_S_DVI = 0x08,	/* DVI output enabled */
+};
+
+enum {  /* TPACPI_VIDEO_570 constants */
+	TP_ACPI_VIDEO_570_PHSCMD = 0x87,	/* unknown magic constant :( */
+	TP_ACPI_VIDEO_570_PHSMASK = 0x03,	/* PHS bits that map to
+						 * video_status_flags */
+	TP_ACPI_VIDEO_570_PHS2CMD = 0x8b,	/* unknown magic constant :( */
+	TP_ACPI_VIDEO_570_PHS2SET = 0x80,	/* unknown magic constant :( */
+};
+
 static enum video_access_mode video_supported;
 static int video_orig_autosw;
 
+static int video_autosw_get(void);
+static int video_autosw_set(int enable);
+
 IBM_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA",	/* 570 */
 	   "\\_SB.PCI0.AGP0.VID0",	/* 600e/x, 770x */
 	   "\\_SB.PCI0.VID0",	/* 770e */
@@ -3370,6 +3038,10 @@ static struct ibm_struct light_driver_data = {
 
 #ifdef CONFIG_THINKPAD_ACPI_DOCK
 
+static void dock_notify(struct ibm_struct *ibm, u32 event);
+static int dock_read(char *p);
+static int dock_write(char *buf);
+
 IBM_HANDLE(dock, root, "\\_SB.GDCK",	/* X30, X31, X40 */
 	   "\\_SB.PCI0.DOCK",	/* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */
 	   "\\_SB.PCI0.PCI1.DOCK",	/* all others */
@@ -3524,6 +3196,7 @@ static int dock_write(char *buf)
  */
 
 #ifdef CONFIG_THINKPAD_ACPI_BAY
+
 IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST",	/* 570 */
 	   "\\_SB.PCI0.IDE0.IDES.IDSM",	/* 600e/x, 770e, 770x */
 	   "\\_SB.PCI0.SATA.SCND.MSTR",	/* T60, X60, Z60 */
@@ -3741,6 +3414,19 @@ static struct ibm_struct cmos_driver_data = {
  * LED subdriver
  */
 
+enum led_access_mode {
+	TPACPI_LED_NONE = 0,
+	TPACPI_LED_570,	/* 570 */
+	TPACPI_LED_OLD,	/* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
+	TPACPI_LED_NEW,	/* all others */
+};
+
+enum {	/* For TPACPI_LED_OLD */
+	TPACPI_LED_EC_HLCL = 0x0c,	/* EC reg to get led to power on */
+	TPACPI_LED_EC_HLBL = 0x0d,	/* EC reg to blink a lit led */
+	TPACPI_LED_EC_HLMS = 0x0e,	/* EC reg to select led to command */
+};
+
 static enum led_access_mode led_supported;
 
 IBM_HANDLE(led, ec, "SLED",	/* 570 */
@@ -3930,8 +3616,30 @@ static struct ibm_struct beep_driver_data = {
  * Thermal subdriver
  */
 
+enum thermal_access_mode {
+	TPACPI_THERMAL_NONE = 0,	/* No thermal support */
+	TPACPI_THERMAL_ACPI_TMP07,	/* Use ACPI TMP0-7 */
+	TPACPI_THERMAL_ACPI_UPDT,	/* Use ACPI TMP0-7 with UPDT */
+	TPACPI_THERMAL_TPEC_8,		/* Use ACPI EC regs, 8 sensors */
+	TPACPI_THERMAL_TPEC_16,		/* Use ACPI EC regs, 16 sensors */
+};
+
+enum { /* TPACPI_THERMAL_TPEC_* */
+	TP_EC_THERMAL_TMP0 = 0x78,	/* ACPI EC regs TMP 0..7 */
+	TP_EC_THERMAL_TMP8 = 0xC0,	/* ACPI EC regs TMP 8..15 */
+	TP_EC_THERMAL_TMP_NA = -128,	/* ACPI EC sensor not available */
+};
+
+#define TPACPI_MAX_THERMAL_SENSORS 16	/* Max thermal sensors supported */
+struct ibm_thermal_sensors_struct {
+	s32 temp[TPACPI_MAX_THERMAL_SENSORS];
+};
+
 static enum thermal_access_mode thermal_read_mode;
 
+static int thermal_get_sensor(int idx, s32 *value);
+static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s);
+
 /* sysfs temp##_input -------------------------------------------------- */
 
 static ssize_t thermal_temp_input_show(struct device *dev,
@@ -4306,7 +4014,16 @@ static struct ibm_struct ecdump_driver_data = {
  * Backlight/brightness subdriver
  */
 
+#define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen"
+
 static struct backlight_device *ibm_backlight_device;
+static int brightness_offset = 0x31;
+static int brightness_mode;
+static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */
+
+static int brightness_get(struct backlight_device *bd);
+static int brightness_set(int value);
+static int brightness_update_status(struct backlight_device *bd);
 
 static struct backlight_ops ibm_backlight_data = {
         .get_brightness = brightness_get,
@@ -4628,6 +4345,8 @@ static struct ibm_struct brightness_driver_data = {
  * Volume subdriver
  */
 
+static int volume_offset = 0x30;
+
 static int volume_read(char *p)
 {
 	int len = 0;
@@ -4819,15 +4538,59 @@ static struct ibm_struct volume_driver_data = {
  * 	but the ACPI tables just mention level 7.
  */
 
+enum {					/* Fan control constants */
+	fan_status_offset = 0x2f,	/* EC register 0x2f */
+	fan_rpm_offset = 0x84,		/* EC register 0x84: LSB, 0x85 MSB (RPM)
+					 * 0x84 must be read before 0x85 */
+
+	TP_EC_FAN_FULLSPEED = 0x40,	/* EC fan mode: full speed */
+	TP_EC_FAN_AUTO	    = 0x80,	/* EC fan mode: auto fan control */
+
+	TPACPI_FAN_LAST_LEVEL = 0x100,	/* Use cached last-seen fan level */
+};
+
+enum fan_status_access_mode {
+	TPACPI_FAN_NONE = 0,		/* No fan status or control */
+	TPACPI_FAN_RD_ACPI_GFAN,	/* Use ACPI GFAN */
+	TPACPI_FAN_RD_TPEC,		/* Use ACPI EC regs 0x2f, 0x84-0x85 */
+};
+
+enum fan_control_access_mode {
+	TPACPI_FAN_WR_NONE = 0,		/* No fan control */
+	TPACPI_FAN_WR_ACPI_SFAN,	/* Use ACPI SFAN */
+	TPACPI_FAN_WR_TPEC,		/* Use ACPI EC reg 0x2f */
+	TPACPI_FAN_WR_ACPI_FANS,	/* Use ACPI FANS and EC reg 0x2f */
+};
+
+enum fan_control_commands {
+	TPACPI_FAN_CMD_SPEED 	= 0x0001,	/* speed command */
+	TPACPI_FAN_CMD_LEVEL 	= 0x0002,	/* level command  */
+	TPACPI_FAN_CMD_ENABLE	= 0x0004,	/* enable/disable cmd,
+						 * and also watchdog cmd */
+};
+
+static int fan_control_allowed;
+
 static enum fan_status_access_mode fan_status_access_mode;
 static enum fan_control_access_mode fan_control_access_mode;
 static enum fan_control_commands fan_control_commands;
 
 static u8 fan_control_initial_status;
 static u8 fan_control_desired_level;
+static int fan_watchdog_maxinterval;
+
+static struct mutex fan_mutex;
 
+static int fan_get_status(u8 *status);
+static int fan_get_status_safe(u8 *status);
+static int fan_get_speed(unsigned int *speed);
+static void fan_update_desired_level(u8 status);
 static void fan_watchdog_fire(struct work_struct *ignored);
-static int fan_watchdog_maxinterval;
+static void fan_watchdog_reset(void);
+static int fan_set_level(int level);
+static int fan_set_level_safe(int level);
+static int fan_set_enable(void);
+
 static DECLARE_DELAYED_WORK(fan_watchdog_task, fan_watchdog_fire);
 
 IBM_HANDLE(fans, ec, "FANS");	/* X31, X40, X41 */
@@ -5710,9 +5473,6 @@ static struct device_attribute dev_attr_thinkpad_acpi_pdev_name =
 /* /proc support */
 static struct proc_dir_entry *proc_dir;
 
-/* Subdriver registry */
-static LIST_HEAD(tpacpi_all_drivers);
-
 
 /*
  * Module and infrastructure proble, init and exit handling
@@ -5727,6 +5487,8 @@ static const char * __init str_supported(int is_supported)
 }
 #endif /* CONFIG_THINKPAD_ACPI_DEBUG */
 
+static void ibm_exit(struct ibm_struct *ibm);
+
 static int __init ibm_init(struct ibm_init_struct *iibm)
 {
 	int ret;
@@ -6042,25 +5804,18 @@ static int __init set_ibm_param(const char *val, struct kernel_param *kp)
 	return -EINVAL;
 }
 
-static int experimental;
 module_param(experimental, int, 0);
 
-static u32 dbg_level;
 module_param_named(debug, dbg_level, uint, 0);
 
-static int force_load;
 module_param(force_load, bool, 0);
 
-static int fan_control_allowed;
 module_param_named(fan_control, fan_control_allowed, bool, 0);
 
-static int brightness_mode;
 module_param_named(brightness_mode, brightness_mode, int, 0);
 
-static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */
 module_param(brightness_enable, uint, 0);
 
-static unsigned int hotkey_report_mode;
 module_param(hotkey_report_mode, uint, 0);
 
 #define IBM_PARAM(feature) \
@@ -6084,6 +5839,8 @@ IBM_PARAM(brightness);
 IBM_PARAM(volume);
 IBM_PARAM(fan);
 
+static void thinkpad_acpi_module_exit(void);
+
 static int __init thinkpad_acpi_module_init(void)
 {
 	int ret, i;
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#39 lore raw

PATCH 39/112 ACPI: thinkpad-acpi: spring cleanup part 3

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

Reorder code in the file to get rid of more of the forward declarations, and to make things cleaner and more organized.

---
 drivers/misc/thinkpad_acpi.c | 1493 +++++++++++++++++++++---------------------
 1 files changed, 734 insertions(+), 759 deletions(-)
drivers/misc/thinkpad_acpi.c +734 -759
index e435b55..b6293a4 100644
@@ -113,28 +113,6 @@
 
 #include <linux/pci_ids.h>
 
-/****************************************************************************
- * Main driver
- */
-
-#define IBM_NAME "thinkpad"
-#define IBM_DESC "ThinkPad ACPI Extras"
-#define IBM_FILE IBM_NAME "_acpi"
-#define IBM_URL "http://ibm-acpi.sf.net/"
-#define IBM_MAIL "[email protected]"
-
-#define IBM_PROC_DIR "ibm"
-#define IBM_ACPI_EVENT_PREFIX "ibm"
-#define IBM_DRVR_NAME IBM_FILE
-#define IBM_HWMON_DRVR_NAME IBM_NAME "_hwmon"
-
-#define IBM_LOG IBM_FILE ": "
-#define IBM_ERR	   KERN_ERR    IBM_LOG
-#define IBM_NOTICE KERN_NOTICE IBM_LOG
-#define IBM_INFO   KERN_INFO   IBM_LOG
-#define IBM_DEBUG  KERN_DEBUG  IBM_LOG
-
-#define IBM_MAX_ACPI_ARGS 3
 
 /* ThinkPad CMOS commands */
 #define TP_CMOS_VOLUME_DOWN	0
@@ -169,11 +147,70 @@ enum {
 	TP_NVRAM_POS_LEVEL_VOLUME	= 0,
 };
 
-#define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off")
-#define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
-#define strlencmp(a,b) (strncmp((a), (b), strlen(b)))
+/* ACPI HIDs */
+#define IBM_HKEY_HID    "IBM0068"
+
+/* Input IDs */
+#define TPACPI_HKEY_INPUT_PRODUCT	0x5054 /* "TP" */
+#define TPACPI_HKEY_INPUT_VERSION	0x4101
+
+
+/****************************************************************************
+ * Main driver
+ */
+
+/* Module */
+#define IBM_NAME "thinkpad"
+#define IBM_DESC "ThinkPad ACPI Extras"
+#define IBM_FILE IBM_NAME "_acpi"
+#define IBM_URL "http://ibm-acpi.sf.net/"
+#define IBM_MAIL "[email protected]"
+
+#define IBM_PROC_DIR "ibm"
+#define IBM_ACPI_EVENT_PREFIX "ibm"
+#define IBM_DRVR_NAME IBM_FILE
+#define IBM_HWMON_DRVR_NAME IBM_NAME "_hwmon"
+
+#define IBM_MAX_ACPI_ARGS 3
+
+MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
+MODULE_DESCRIPTION(IBM_DESC);
+MODULE_VERSION(IBM_VERSION);
+MODULE_LICENSE("GPL");
+
+/* Please remove this in year 2009 */
+MODULE_ALIAS("ibm_acpi");
+
+/*
+ * DMI matching for module autoloading
+ *
+ * See http://thinkwiki.org/wiki/List_of_DMI_IDs
+ * See http://thinkwiki.org/wiki/BIOS_Upgrade_Downloads
+ *
+ * Only models listed in thinkwiki will be supported, so add yours
+ * if it is not there yet.
+ */
+#define IBM_BIOS_MODULE_ALIAS(__type) \
+	MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW")
+
+/* Non-ancient thinkpads */
+MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*");
+MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*");
+
+/* Ancient thinkpad BIOSes have to be identified by
+ * BIOS type or model number, and there are far less
+ * BIOS types than model numbers... */
+IBM_BIOS_MODULE_ALIAS("I[B,D,H,I,M,N,O,T,W,V,Y,Z]");
+IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]");
+IBM_BIOS_MODULE_ALIAS("K[U,X-Z]");
 
 /* Debugging */
+#define IBM_LOG IBM_FILE ": "
+#define IBM_ERR	   KERN_ERR    IBM_LOG
+#define IBM_NOTICE KERN_NOTICE IBM_LOG
+#define IBM_INFO   KERN_INFO   IBM_LOG
+#define IBM_DEBUG  KERN_DEBUG  IBM_LOG
+
 #define TPACPI_DBG_ALL		0xffff
 #define TPACPI_DBG_ALL		0xffff
 #define TPACPI_DBG_INIT		0x0001
@@ -189,33 +226,13 @@ static const char *str_supported(int is_supported);
 #define vdbg_printk(a_dbg_level, format, arg...)
 #endif
 
-/* Input IDs */
-#define TPACPI_HKEY_INPUT_VENDOR	PCI_VENDOR_ID_IBM
-#define TPACPI_HKEY_INPUT_PRODUCT	0x5054 /* "TP" */
-#define TPACPI_HKEY_INPUT_VERSION	0x4101
-
-/* ACPI HIDs */
-#define IBM_HKEY_HID    "IBM0068"
-
-/* sysfs support */
-struct attribute_set {
-	unsigned int members, max_members;
-	struct attribute_group group;
-};
-
-/* Helpers */
-static int parse_strtoul(const char *buf, unsigned long max,
-			unsigned long *value);
-
-/* Module */
-static int experimental;
-static u32 dbg_level;
-static int force_load;
-static unsigned int hotkey_report_mode;
+#define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off")
+#define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
+#define strlencmp(a,b) (strncmp((a), (b), strlen(b)))
 
 
 /****************************************************************************
- * Subdrivers
+ * Driver-wide structs and misc. variables
  */
 
 struct ibm_struct;
@@ -297,39 +314,6 @@ struct thinkpad_id_data {
 };
 static struct thinkpad_id_data thinkpad_id;
 
-static LIST_HEAD(tpacpi_all_drivers);
-
-MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
-MODULE_DESCRIPTION(IBM_DESC);
-MODULE_VERSION(IBM_VERSION);
-MODULE_LICENSE("GPL");
-
-/* Please remove this in year 2009 */
-MODULE_ALIAS("ibm_acpi");
-
-/*
- * DMI matching for module autoloading
- *
- * See http://thinkwiki.org/wiki/List_of_DMI_IDs
- * See http://thinkwiki.org/wiki/BIOS_Upgrade_Downloads
- *
- * Only models listed in thinkwiki will be supported, so add yours
- * if it is not there yet.
- */
-#define IBM_BIOS_MODULE_ALIAS(__type) \
-	MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW")
-
-/* Non-ancient thinkpads */
-MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*");
-MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*");
-
-/* Ancient thinkpad BIOSes have to be identified by
- * BIOS type or model number, and there are far less
- * BIOS types than model numbers... */
-IBM_BIOS_MODULE_ALIAS("I[B,D,H,I,M,N,O,T,W,V,Y,Z]");
-IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]");
-IBM_BIOS_MODULE_ALIAS("K[U,X-Z]");
-
 #define __unused __attribute__ ((unused))
 
 static enum {
@@ -338,6 +322,9 @@ static enum {
 	TPACPI_LIFE_EXITING,
 } tpacpi_lifecycle;
 
+static int experimental;
+static u32 dbg_level;
+
 /****************************************************************************
  ****************************************************************************
  *
@@ -370,11 +357,6 @@ IBM_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0",	/* 240, 240x */
 IBM_HANDLE(ecrd, ec, "ECRD");	/* 570 */
 IBM_HANDLE(ecwr, ec, "ECWR");	/* 570 */
 
-
-/*************************************************************************
- * Misc ACPI handles
- */
-
 IBM_HANDLE(cmos, root, "\\UCMS",	/* R50, R50e, R50p, R51, T4x, X31, X40 */
 	   "\\CMOS",		/* A3x, G4x, R32, T23, T30, X22-24, X30 */
 	   "\\CMS",		/* R40, R40e */
@@ -749,7 +731,7 @@ static struct platform_device *tpacpi_sensors_pdev;
 static struct device *tpacpi_hwmon;
 static struct input_dev *tpacpi_inputdev;
 static struct mutex tpacpi_inputdev_send_mutex;
-
+static LIST_HEAD(tpacpi_all_drivers);
 
 static int tpacpi_resume_handler(struct platform_device *pdev)
 {
@@ -781,86 +763,14 @@ static struct platform_driver tpacpi_hwmon_pdriver = {
 };
 
 /*************************************************************************
- * thinkpad-acpi driver attributes
+ * sysfs support helpers
  */
 
-/* interface_version --------------------------------------------------- */
-static ssize_t tpacpi_driver_interface_version_show(
-				struct device_driver *drv,
-				char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "0x%08x\n", TPACPI_SYSFS_VERSION);
-}
-
-static DRIVER_ATTR(interface_version, S_IRUGO,
-		tpacpi_driver_interface_version_show, NULL);
-
-/* debug_level --------------------------------------------------------- */
-static ssize_t tpacpi_driver_debug_show(struct device_driver *drv,
-						char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "0x%04x\n", dbg_level);
-}
-
-static ssize_t tpacpi_driver_debug_store(struct device_driver *drv,
-						const char *buf, size_t count)
-{
-	unsigned long t;
-
-	if (parse_strtoul(buf, 0xffff, &t))
-		return -EINVAL;
-
-	dbg_level = t;
-
-	return count;
-}
-
-static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
-		tpacpi_driver_debug_show, tpacpi_driver_debug_store);
-
-/* version ------------------------------------------------------------- */
-static ssize_t tpacpi_driver_version_show(struct device_driver *drv,
-						char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%s v%s\n", IBM_DESC, IBM_VERSION);
-}
-
-static DRIVER_ATTR(version, S_IRUGO,
-		tpacpi_driver_version_show, NULL);
-
-/* --------------------------------------------------------------------- */
-
-static struct driver_attribute* tpacpi_driver_attributes[] = {
-	&driver_attr_debug_level, &driver_attr_version,
-	&driver_attr_interface_version,
+struct attribute_set {
+	unsigned int members, max_members;
+	struct attribute_group group;
 };
 
-static int __init tpacpi_create_driver_attributes(struct device_driver *drv)
-{
-	int i, res;
-
-	i = 0;
-	res = 0;
-	while (!res && i < ARRAY_SIZE(tpacpi_driver_attributes)) {
-		res = driver_create_file(drv, tpacpi_driver_attributes[i]);
-		i++;
-	}
-
-	return res;
-}
-
-static void tpacpi_remove_driver_attributes(struct device_driver *drv)
-{
-	int i;
-
-	for(i = 0; i < ARRAY_SIZE(tpacpi_driver_attributes); i++)
-		driver_remove_file(drv, tpacpi_driver_attributes[i]);
-}
-
-/*************************************************************************
- * sysfs support helpers
- */
-
 struct attribute_set_obj {
 	struct attribute_set s;
 	struct attribute *a;
@@ -945,6 +855,83 @@ static int parse_strtoul(const char *buf,
 	return 0;
 }
 
+/*************************************************************************
+ * thinkpad-acpi driver attributes
+ */
+
+/* interface_version --------------------------------------------------- */
+static ssize_t tpacpi_driver_interface_version_show(
+				struct device_driver *drv,
+				char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "0x%08x\n", TPACPI_SYSFS_VERSION);
+}
+
+static DRIVER_ATTR(interface_version, S_IRUGO,
+		tpacpi_driver_interface_version_show, NULL);
+
+/* debug_level --------------------------------------------------------- */
+static ssize_t tpacpi_driver_debug_show(struct device_driver *drv,
+						char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "0x%04x\n", dbg_level);
+}
+
+static ssize_t tpacpi_driver_debug_store(struct device_driver *drv,
+						const char *buf, size_t count)
+{
+	unsigned long t;
+
+	if (parse_strtoul(buf, 0xffff, &t))
+		return -EINVAL;
+
+	dbg_level = t;
+
+	return count;
+}
+
+static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
+		tpacpi_driver_debug_show, tpacpi_driver_debug_store);
+
+/* version ------------------------------------------------------------- */
+static ssize_t tpacpi_driver_version_show(struct device_driver *drv,
+						char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s v%s\n", IBM_DESC, IBM_VERSION);
+}
+
+static DRIVER_ATTR(version, S_IRUGO,
+		tpacpi_driver_version_show, NULL);
+
+/* --------------------------------------------------------------------- */
+
+static struct driver_attribute* tpacpi_driver_attributes[] = {
+	&driver_attr_debug_level, &driver_attr_version,
+	&driver_attr_interface_version,
+};
+
+static int __init tpacpi_create_driver_attributes(struct device_driver *drv)
+{
+	int i, res;
+
+	i = 0;
+	res = 0;
+	while (!res && i < ARRAY_SIZE(tpacpi_driver_attributes)) {
+		res = driver_create_file(drv, tpacpi_driver_attributes[i]);
+		i++;
+	}
+
+	return res;
+}
+
+static void tpacpi_remove_driver_attributes(struct device_driver *drv)
+{
+	int i;
+
+	for(i = 0; i < ARRAY_SIZE(tpacpi_driver_attributes); i++)
+		driver_remove_file(drv, tpacpi_driver_attributes[i]);
+}
+
 /****************************************************************************
  ****************************************************************************
  *
@@ -1094,6 +1081,8 @@ static u32 hotkey_all_mask;
 static u32 hotkey_reserved_mask;
 static u32 hotkey_mask;
 
+static unsigned int hotkey_report_mode;
+
 static u16 *hotkey_keycode_map;
 
 static struct attribute_set *hotkey_dev_attributes;
@@ -3637,8 +3626,87 @@ struct ibm_thermal_sensors_struct {
 
 static enum thermal_access_mode thermal_read_mode;
 
-static int thermal_get_sensor(int idx, s32 *value);
-static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s);
+/* idx is zero-based */
+static int thermal_get_sensor(int idx, s32 *value)
+{
+	int t;
+	s8 tmp;
+	char tmpi[5];
+
+	t = TP_EC_THERMAL_TMP0;
+
+	switch (thermal_read_mode) {
+#if TPACPI_MAX_THERMAL_SENSORS >= 16
+	case TPACPI_THERMAL_TPEC_16:
+		if (idx >= 8 && idx <= 15) {
+			t = TP_EC_THERMAL_TMP8;
+			idx -= 8;
+		}
+		/* fallthrough */
+#endif
+	case TPACPI_THERMAL_TPEC_8:
+		if (idx <= 7) {
+			if (!acpi_ec_read(t + idx, &tmp))
+				return -EIO;
+			*value = tmp * 1000;
+			return 0;
+		}
+		break;
+
+	case TPACPI_THERMAL_ACPI_UPDT:
+		if (idx <= 7) {
+			snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx);
+			if (!acpi_evalf(ec_handle, NULL, "UPDT", "v"))
+				return -EIO;
+			if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
+				return -EIO;
+			*value = (t - 2732) * 100;
+			return 0;
+		}
+		break;
+
+	case TPACPI_THERMAL_ACPI_TMP07:
+		if (idx <= 7) {
+			snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx);
+			if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
+				return -EIO;
+			if (t > 127 || t < -127)
+				t = TP_EC_THERMAL_TMP_NA;
+			*value = t * 1000;
+			return 0;
+		}
+		break;
+
+	case TPACPI_THERMAL_NONE:
+	default:
+		return -ENOSYS;
+	}
+
+	return -EINVAL;
+}
+
+static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s)
+{
+	int res, i;
+	int n;
+
+	n = 8;
+	i = 0;
+
+	if (!s)
+		return -EINVAL;
+
+	if (thermal_read_mode == TPACPI_THERMAL_TPEC_16)
+		n = 16;
+
+	for(i = 0 ; i < n; i++) {
+		res = thermal_get_sensor(i, &s->temp[i]);
+		if (res)
+			return res;
+	}
+
+	return n;
+}
 
 /* sysfs temp##_input -------------------------------------------------- */
 
@@ -3830,88 +3898,6 @@ static void thermal_exit(void)
 	}
 }
 
-/* idx is zero-based */
-static int thermal_get_sensor(int idx, s32 *value)
-{
-	int t;
-	s8 tmp;
-	char tmpi[5];
-
-	t = TP_EC_THERMAL_TMP0;
-
-	switch (thermal_read_mode) {
-#if TPACPI_MAX_THERMAL_SENSORS >= 16
-	case TPACPI_THERMAL_TPEC_16:
-		if (idx >= 8 && idx <= 15) {
-			t = TP_EC_THERMAL_TMP8;
-			idx -= 8;
-		}
-		/* fallthrough */
-#endif
-	case TPACPI_THERMAL_TPEC_8:
-		if (idx <= 7) {
-			if (!acpi_ec_read(t + idx, &tmp))
-				return -EIO;
-			*value = tmp * 1000;
-			return 0;
-		}
-		break;
-
-	case TPACPI_THERMAL_ACPI_UPDT:
-		if (idx <= 7) {
-			snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx);
-			if (!acpi_evalf(ec_handle, NULL, "UPDT", "v"))
-				return -EIO;
-			if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
-				return -EIO;
-			*value = (t - 2732) * 100;
-			return 0;
-		}
-		break;
-
-	case TPACPI_THERMAL_ACPI_TMP07:
-		if (idx <= 7) {
-			snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx);
-			if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
-				return -EIO;
-			if (t > 127 || t < -127)
-				t = TP_EC_THERMAL_TMP_NA;
-			*value = t * 1000;
-			return 0;
-		}
-		break;
-
-	case TPACPI_THERMAL_NONE:
-	default:
-		return -ENOSYS;
-	}
-
-	return -EINVAL;
-}
-
-static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s)
-{
-	int res, i;
-	int n;
-
-	n = 8;
-	i = 0;
-
-	if (!s)
-		return -EINVAL;
-
-	if (thermal_read_mode == TPACPI_THERMAL_TPEC_16)
-		n = 16;
-
-	for(i = 0 ; i < n; i++) {
-		res = thermal_get_sensor(i, &s->temp[i]);
-		if (res)
-			return res;
-	}
-
-	return n;
-}
-
 static int thermal_read(char *p)
 {
 	int len = 0;
@@ -4021,16 +4007,103 @@ static int brightness_offset = 0x31;
 static int brightness_mode;
 static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */
 
-static int brightness_get(struct backlight_device *bd);
-static int brightness_set(int value);
-static int brightness_update_status(struct backlight_device *bd);
+static struct mutex brightness_mutex;
+
+/*
+ * ThinkPads can read brightness from two places: EC 0x31, or
+ * CMOS NVRAM byte 0x5E, bits 0-3.
+ */
+static int brightness_get(struct backlight_device *bd)
+{
+	u8 lec = 0, lcmos = 0, level = 0;
+
+	if (brightness_mode & 1) {
+		if (!acpi_ec_read(brightness_offset, &lec))
+			return -EIO;
+		lec &= (tp_features.bright_16levels)? 0x0f : 0x07;
+		level = lec;
+	};
+	if (brightness_mode & 2) {
+		lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS)
+			 & TP_NVRAM_MASK_LEVEL_BRIGHTNESS)
+			>> TP_NVRAM_POS_LEVEL_BRIGHTNESS;
+		lcmos &= (tp_features.bright_16levels)? 0x0f : 0x07;
+		level = lcmos;
+	}
+
+	if (brightness_mode == 3 && lec != lcmos) {
+		printk(IBM_ERR
+			"CMOS NVRAM (%u) and EC (%u) do not agree "
+			"on display brightness level\n",
+			(unsigned int) lcmos,
+			(unsigned int) lec);
+		return -EIO;
+	}
+
+	return level;
+}
+
+/* May return EINTR which can always be mapped to ERESTARTSYS */
+static int brightness_set(int value)
+{
+	int cmos_cmd, inc, i, res;
+	int current_value;
+
+	if (value > ((tp_features.bright_16levels)? 15 : 7))
+		return -EINVAL;
+
+	res = mutex_lock_interruptible(&brightness_mutex);
+	if (res < 0)
+		return res;
+
+	current_value = brightness_get(NULL);
+	if (current_value < 0) {
+		res = current_value;
+		goto errout;
+	}
+
+	cmos_cmd = value > current_value ?
+			TP_CMOS_BRIGHTNESS_UP :
+			TP_CMOS_BRIGHTNESS_DOWN;
+	inc = (value > current_value)? 1 : -1;
+
+	res = 0;
+	for (i = current_value; i != value; i += inc) {
+		if ((brightness_mode & 2) &&
+		    issue_thinkpad_cmos_command(cmos_cmd)) {
+			res = -EIO;
+			goto errout;
+		}
+		if ((brightness_mode & 1) &&
+		    !acpi_ec_write(brightness_offset, i + inc)) {
+			res = -EIO;
+			goto errout;;
+		}
+	}
+
+errout:
+	mutex_unlock(&brightness_mutex);
+	return res;
+}
+
+/* sysfs backlight class ----------------------------------------------- */
+
+static int brightness_update_status(struct backlight_device *bd)
+{
+	/* it is the backlight class's job (caller) to handle
+	 * EINTR and other errors properly */
+	return brightness_set(
+		(bd->props.fb_blank == FB_BLANK_UNBLANK &&
+		 bd->props.power == FB_BLANK_UNBLANK) ?
+				bd->props.brightness : 0);
+}
 
 static struct backlight_ops ibm_backlight_data = {
         .get_brightness = brightness_get,
         .update_status  = brightness_update_status,
 };
 
-static struct mutex brightness_mutex;
+/* --------------------------------------------------------------------- */
 
 static int __init tpacpi_query_bcll_levels(acpi_handle handle)
 {
@@ -4196,93 +4269,6 @@ static void brightness_exit(void)
 	}
 }
 
-static int brightness_update_status(struct backlight_device *bd)
-{
-	/* it is the backlight class's job (caller) to handle
-	 * EINTR and other errors properly */
-	return brightness_set(
-		(bd->props.fb_blank == FB_BLANK_UNBLANK &&
-		 bd->props.power == FB_BLANK_UNBLANK) ?
-				bd->props.brightness : 0);
-}
-
-/*
- * ThinkPads can read brightness from two places: EC 0x31, or
- * CMOS NVRAM byte 0x5E, bits 0-3.
- */
-static int brightness_get(struct backlight_device *bd)
-{
-	u8 lec = 0, lcmos = 0, level = 0;
-
-	if (brightness_mode & 1) {
-		if (!acpi_ec_read(brightness_offset, &lec))
-			return -EIO;
-		lec &= (tp_features.bright_16levels)? 0x0f : 0x07;
-		level = lec;
-	};
-	if (brightness_mode & 2) {
-		lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS)
-			 & TP_NVRAM_MASK_LEVEL_BRIGHTNESS)
-			>> TP_NVRAM_POS_LEVEL_BRIGHTNESS;
-		lcmos &= (tp_features.bright_16levels)? 0x0f : 0x07;
-		level = lcmos;
-	}
-
-	if (brightness_mode == 3 && lec != lcmos) {
-		printk(IBM_ERR
-			"CMOS NVRAM (%u) and EC (%u) do not agree "
-			"on display brightness level\n",
-			(unsigned int) lcmos,
-			(unsigned int) lec);
-		return -EIO;
-	}
-
-	return level;
-}
-
-/* May return EINTR which can always be mapped to ERESTARTSYS */
-static int brightness_set(int value)
-{
-	int cmos_cmd, inc, i, res;
-	int current_value;
-
-	if (value > ((tp_features.bright_16levels)? 15 : 7))
-		return -EINVAL;
-
-	res = mutex_lock_interruptible(&brightness_mutex);
-	if (res < 0)
-		return res;
-
-	current_value = brightness_get(NULL);
-	if (current_value < 0) {
-		res = current_value;
-		goto errout;
-	}
-
-	cmos_cmd = value > current_value ?
-			TP_CMOS_BRIGHTNESS_UP :
-			TP_CMOS_BRIGHTNESS_DOWN;
-	inc = (value > current_value)? 1 : -1;
-
-	res = 0;
-	for (i = current_value; i != value; i += inc) {
-		if ((brightness_mode & 2) &&
-		    issue_thinkpad_cmos_command(cmos_cmd)) {
-			res = -EIO;
-			goto errout;
-		}
-		if ((brightness_mode & 1) &&
-		    !acpi_ec_write(brightness_offset, i + inc)) {
-			res = -EIO;
-			goto errout;;
-		}
-	}
-
-errout:
-	mutex_unlock(&brightness_mutex);
-	return res;
-}
-
 static int brightness_read(char *p)
 {
 	int len = 0;
@@ -4581,16 +4567,7 @@ static int fan_watchdog_maxinterval;
 
 static struct mutex fan_mutex;
 
-static int fan_get_status(u8 *status);
-static int fan_get_status_safe(u8 *status);
-static int fan_get_speed(unsigned int *speed);
-static void fan_update_desired_level(u8 status);
 static void fan_watchdog_fire(struct work_struct *ignored);
-static void fan_watchdog_reset(void);
-static int fan_set_level(int level);
-static int fan_set_level_safe(int level);
-static int fan_set_enable(void);
-
 static DECLARE_DELAYED_WORK(fan_watchdog_task, fan_watchdog_fire);
 
 IBM_HANDLE(fans, ec, "FANS");	/* X31, X40, X41 */
@@ -4602,6 +4579,321 @@ IBM_HANDLE(sfan, ec, "SFAN",	/* 570 */
 	   );			/* all others */
 
 /*
+ * Call with fan_mutex held
+ */
+static void fan_update_desired_level(u8 status)
+{
+	if ((status &
+	     (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) == 0) {
+		if (status > 7)
+			fan_control_desired_level = 7;
+		else
+			fan_control_desired_level = status;
+	}
+}
+
+static int fan_get_status(u8 *status)
+{
+	u8 s;
+
+	/* TODO:
+	 * Add TPACPI_FAN_RD_ACPI_FANS ? */
+
+	switch (fan_status_access_mode) {
+	case TPACPI_FAN_RD_ACPI_GFAN:
+		/* 570, 600e/x, 770e, 770x */
+
+		if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d")))
+			return -EIO;
+
+		if (likely(status))
+			*status = s & 0x07;
+
+		break;
+
+	case TPACPI_FAN_RD_TPEC:
+		/* all except 570, 600e/x, 770e, 770x */
+		if (unlikely(!acpi_ec_read(fan_status_offset, &s)))
+			return -EIO;
+
+		if (likely(status))
+			*status = s;
+
+		break;
+
+	default:
+		return -ENXIO;
+	}
+
+	return 0;
+}
+
+static int fan_get_status_safe(u8 *status)
+{
+	int rc;
+	u8 s;
+
+	if (mutex_lock_interruptible(&fan_mutex))
+		return -ERESTARTSYS;
+	rc = fan_get_status(&s);
+	if (!rc)
+		fan_update_desired_level(s);
+	mutex_unlock(&fan_mutex);
+
+	if (status)
+		*status = s;
+
+	return rc;
+}
+
+static int fan_get_speed(unsigned int *speed)
+{
+	u8 hi, lo;
+
+	switch (fan_status_access_mode) {
+	case TPACPI_FAN_RD_TPEC:
+		/* all except 570, 600e/x, 770e, 770x */
+		if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) ||
+			     !acpi_ec_read(fan_rpm_offset + 1, &hi)))
+			return -EIO;
+
+		if (likely(speed))
+			*speed = (hi << 8) | lo;
+
+		break;
+
+	default:
+		return -ENXIO;
+	}
+
+	return 0;
+}
+
+static int fan_set_level(int level)
+{
+	if (!fan_control_allowed)
+		return -EPERM;
+
+	switch (fan_control_access_mode) {
+	case TPACPI_FAN_WR_ACPI_SFAN:
+		if (level >= 0 && level <= 7) {
+			if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
+				return -EIO;
+		} else
+			return -EINVAL;
+		break;
+
+	case TPACPI_FAN_WR_ACPI_FANS:
+	case TPACPI_FAN_WR_TPEC:
+		if ((level != TP_EC_FAN_AUTO) &&
+		    (level != TP_EC_FAN_FULLSPEED) &&
+		    ((level < 0) || (level > 7)))
+			return -EINVAL;
+
+		/* safety net should the EC not support AUTO
+		 * or FULLSPEED mode bits and just ignore them */
+		if (level & TP_EC_FAN_FULLSPEED)
+			level |= 7;	/* safety min speed 7 */
+		else if (level & TP_EC_FAN_FULLSPEED)
+			level |= 4;	/* safety min speed 4 */
+
+		if (!acpi_ec_write(fan_status_offset, level))
+			return -EIO;
+		else
+			tp_features.fan_ctrl_status_undef = 0;
+		break;
+
+	default:
+		return -ENXIO;
+	}
+	return 0;
+}
+
+static int fan_set_level_safe(int level)
+{
+	int rc;
+
+	if (!fan_control_allowed)
+		return -EPERM;
+
+	if (mutex_lock_interruptible(&fan_mutex))
+		return -ERESTARTSYS;
+
+	if (level == TPACPI_FAN_LAST_LEVEL)
+		level = fan_control_desired_level;
+
+	rc = fan_set_level(level);
+	if (!rc)
+		fan_update_desired_level(level);
+
+	mutex_unlock(&fan_mutex);
+	return rc;
+}
+
+static int fan_set_enable(void)
+{
+	u8 s;
+	int rc;
+
+	if (!fan_control_allowed)
+		return -EPERM;
+
+	if (mutex_lock_interruptible(&fan_mutex))
+		return -ERESTARTSYS;
+
+	switch (fan_control_access_mode) {
+	case TPACPI_FAN_WR_ACPI_FANS:
+	case TPACPI_FAN_WR_TPEC:
+		rc = fan_get_status(&s);
+		if (rc < 0)
+			break;
+
+		/* Don't go out of emergency fan mode */
+		if (s != 7) {
+			s &= 0x07;
+			s |= TP_EC_FAN_AUTO | 4; /* min fan speed 4 */
+		}
+
+		if (!acpi_ec_write(fan_status_offset, s))
+			rc = -EIO;
+		else {
+			tp_features.fan_ctrl_status_undef = 0;
+			rc = 0;
+		}
+		break;
+
+	case TPACPI_FAN_WR_ACPI_SFAN:
+		rc = fan_get_status(&s);
+		if (rc < 0)
+			break;
+
+		s &= 0x07;
+
+		/* Set fan to at least level 4 */
+		s |= 4;
+
+		if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", s))
+			rc= -EIO;
+		else
+			rc = 0;
+		break;
+
+	default:
+		rc = -ENXIO;
+	}
+
+	mutex_unlock(&fan_mutex);
+	return rc;
+}
+
+static int fan_set_disable(void)
+{
+	int rc;
+
+	if (!fan_control_allowed)
+		return -EPERM;
+
+	if (mutex_lock_interruptible(&fan_mutex))
+		return -ERESTARTSYS;
+
+	rc = 0;
+	switch (fan_control_access_mode) {
+	case TPACPI_FAN_WR_ACPI_FANS:
+	case TPACPI_FAN_WR_TPEC:
+		if (!acpi_ec_write(fan_status_offset, 0x00))
+			rc = -EIO;
+		else {
+			fan_control_desired_level = 0;
+			tp_features.fan_ctrl_status_undef = 0;
+		}
+		break;
+
+	case TPACPI_FAN_WR_ACPI_SFAN:
+		if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", 0x00))
+			rc = -EIO;
+		else
+			fan_control_desired_level = 0;
+		break;
+
+	default:
+		rc = -ENXIO;
+	}
+
+
+	mutex_unlock(&fan_mutex);
+	return rc;
+}
+
+static int fan_set_speed(int speed)
+{
+	int rc;
+
+	if (!fan_control_allowed)
+		return -EPERM;
+
+	if (mutex_lock_interruptible(&fan_mutex))
+		return -ERESTARTSYS;
+
+	rc = 0;
+	switch (fan_control_access_mode) {
+	case TPACPI_FAN_WR_ACPI_FANS:
+		if (speed >= 0 && speed <= 65535) {
+			if (!acpi_evalf(fans_handle, NULL, NULL, "vddd",
+					speed, speed, speed))
+				rc = -EIO;
+		} else
+			rc = -EINVAL;
+		break;
+
+	default:
+		rc = -ENXIO;
+	}
+
+	mutex_unlock(&fan_mutex);
+	return rc;
+}
+
+static void fan_watchdog_reset(void)
+{
+	static int fan_watchdog_active;
+
+	if (fan_control_access_mode == TPACPI_FAN_WR_NONE)
+		return;
+
+	if (fan_watchdog_active)
+		cancel_delayed_work(&fan_watchdog_task);
+
+	if (fan_watchdog_maxinterval > 0 &&
+	    tpacpi_lifecycle != TPACPI_LIFE_EXITING) {
+		fan_watchdog_active = 1;
+		if (!schedule_delayed_work(&fan_watchdog_task,
+				msecs_to_jiffies(fan_watchdog_maxinterval
+						 * 1000))) {
+			printk(IBM_ERR "failed to schedule the fan watchdog, "
+			       "watchdog will not trigger\n");
+		}
+	} else
+		fan_watchdog_active = 0;
+}
+
+static void fan_watchdog_fire(struct work_struct *ignored)
+{
+	int rc;
+
+	if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING)
+		return;
+
+	printk(IBM_NOTICE "fan watchdog: enabling fan\n");
+	rc = fan_set_enable();
+	if (rc < 0) {
+		printk(IBM_ERR "fan watchdog: error %d while enabling fan, "
+			"will try again later...\n", -rc);
+		/* reschedule for later */
+		fan_watchdog_reset();
+	}
+}
+
+/*
  * SYSFS fan layout: hwmon compatible (device)
  *
  * pwm*_enable:
@@ -4936,74 +5228,6 @@ static int __init fan_init(struct ibm_init_struct *iibm)
 		return 1;
 }
 
-/*
- * Call with fan_mutex held
- */
-static void fan_update_desired_level(u8 status)
-{
-	if ((status &
-	     (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) == 0) {
-		if (status > 7)
-			fan_control_desired_level = 7;
-		else
-			fan_control_desired_level = status;
-	}
-}
-
-static int fan_get_status(u8 *status)
-{
-	u8 s;
-
-	/* TODO:
-	 * Add TPACPI_FAN_RD_ACPI_FANS ? */
-
-	switch (fan_status_access_mode) {
-	case TPACPI_FAN_RD_ACPI_GFAN:
-		/* 570, 600e/x, 770e, 770x */
-
-		if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d")))
-			return -EIO;
-
-		if (likely(status))
-			*status = s & 0x07;
-
-		break;
-
-	case TPACPI_FAN_RD_TPEC:
-		/* all except 570, 600e/x, 770e, 770x */
-		if (unlikely(!acpi_ec_read(fan_status_offset, &s)))
-			return -EIO;
-
-		if (likely(status))
-			*status = s;
-
-		break;
-
-	default:
-		return -ENXIO;
-	}
-
-	return 0;
-}
-
-static int fan_get_status_safe(u8 *status)
-{
-	int rc;
-	u8 s;
-
-	if (mutex_lock_interruptible(&fan_mutex))
-		return -ERESTARTSYS;
-	rc = fan_get_status(&s);
-	if (!rc)
-		fan_update_desired_level(s);
-	mutex_unlock(&fan_mutex);
-
-	if (status)
-		*status = s;
-
-	return rc;
-}
-
 static void fan_exit(void)
 {
 	vdbg_printk(TPACPI_DBG_EXIT, "cancelling any pending fan watchdog tasks\n");
@@ -5016,253 +5240,6 @@ static void fan_exit(void)
 	flush_scheduled_work();
 }
 
-static int fan_get_speed(unsigned int *speed)
-{
-	u8 hi, lo;
-
-	switch (fan_status_access_mode) {
-	case TPACPI_FAN_RD_TPEC:
-		/* all except 570, 600e/x, 770e, 770x */
-		if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) ||
-			     !acpi_ec_read(fan_rpm_offset + 1, &hi)))
-			return -EIO;
-
-		if (likely(speed))
-			*speed = (hi << 8) | lo;
-
-		break;
-
-	default:
-		return -ENXIO;
-	}
-
-	return 0;
-}
-
-static void fan_watchdog_fire(struct work_struct *ignored)
-{
-	int rc;
-
-	if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING)
-		return;
-
-	printk(IBM_NOTICE "fan watchdog: enabling fan\n");
-	rc = fan_set_enable();
-	if (rc < 0) {
-		printk(IBM_ERR "fan watchdog: error %d while enabling fan, "
-			"will try again later...\n", -rc);
-		/* reschedule for later */
-		fan_watchdog_reset();
-	}
-}
-
-static void fan_watchdog_reset(void)
-{
-	static int fan_watchdog_active;
-
-	if (fan_control_access_mode == TPACPI_FAN_WR_NONE)
-		return;
-
-	if (fan_watchdog_active)
-		cancel_delayed_work(&fan_watchdog_task);
-
-	if (fan_watchdog_maxinterval > 0 &&
-	    tpacpi_lifecycle != TPACPI_LIFE_EXITING) {
-		fan_watchdog_active = 1;
-		if (!schedule_delayed_work(&fan_watchdog_task,
-				msecs_to_jiffies(fan_watchdog_maxinterval
-						 * 1000))) {
-			printk(IBM_ERR "failed to schedule the fan watchdog, "
-			       "watchdog will not trigger\n");
-		}
-	} else
-		fan_watchdog_active = 0;
-}
-
-static int fan_set_level(int level)
-{
-	if (!fan_control_allowed)
-		return -EPERM;
-
-	switch (fan_control_access_mode) {
-	case TPACPI_FAN_WR_ACPI_SFAN:
-		if (level >= 0 && level <= 7) {
-			if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
-				return -EIO;
-		} else
-			return -EINVAL;
-		break;
-
-	case TPACPI_FAN_WR_ACPI_FANS:
-	case TPACPI_FAN_WR_TPEC:
-		if ((level != TP_EC_FAN_AUTO) &&
-		    (level != TP_EC_FAN_FULLSPEED) &&
-		    ((level < 0) || (level > 7)))
-			return -EINVAL;
-
-		/* safety net should the EC not support AUTO
-		 * or FULLSPEED mode bits and just ignore them */
-		if (level & TP_EC_FAN_FULLSPEED)
-			level |= 7;	/* safety min speed 7 */
-		else if (level & TP_EC_FAN_FULLSPEED)
-			level |= 4;	/* safety min speed 4 */
-
-		if (!acpi_ec_write(fan_status_offset, level))
-			return -EIO;
-		else
-			tp_features.fan_ctrl_status_undef = 0;
-		break;
-
-	default:
-		return -ENXIO;
-	}
-	return 0;
-}
-
-static int fan_set_level_safe(int level)
-{
-	int rc;
-
-	if (!fan_control_allowed)
-		return -EPERM;
-
-	if (mutex_lock_interruptible(&fan_mutex))
-		return -ERESTARTSYS;
-
-	if (level == TPACPI_FAN_LAST_LEVEL)
-		level = fan_control_desired_level;
-
-	rc = fan_set_level(level);
-	if (!rc)
-		fan_update_desired_level(level);
-
-	mutex_unlock(&fan_mutex);
-	return rc;
-}
-
-static int fan_set_enable(void)
-{
-	u8 s;
-	int rc;
-
-	if (!fan_control_allowed)
-		return -EPERM;
-
-	if (mutex_lock_interruptible(&fan_mutex))
-		return -ERESTARTSYS;
-
-	switch (fan_control_access_mode) {
-	case TPACPI_FAN_WR_ACPI_FANS:
-	case TPACPI_FAN_WR_TPEC:
-		rc = fan_get_status(&s);
-		if (rc < 0)
-			break;
-
-		/* Don't go out of emergency fan mode */
-		if (s != 7) {
-			s &= 0x07;
-			s |= TP_EC_FAN_AUTO | 4; /* min fan speed 4 */
-		}
-
-		if (!acpi_ec_write(fan_status_offset, s))
-			rc = -EIO;
-		else {
-			tp_features.fan_ctrl_status_undef = 0;
-			rc = 0;
-		}
-		break;
-
-	case TPACPI_FAN_WR_ACPI_SFAN:
-		rc = fan_get_status(&s);
-		if (rc < 0)
-			break;
-
-		s &= 0x07;
-
-		/* Set fan to at least level 4 */
-		s |= 4;
-
-		if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", s))
-			rc= -EIO;
-		else
-			rc = 0;
-		break;
-
-	default:
-		rc = -ENXIO;
-	}
-
-	mutex_unlock(&fan_mutex);
-	return rc;
-}
-
-static int fan_set_disable(void)
-{
-	int rc;
-
-	if (!fan_control_allowed)
-		return -EPERM;
-
-	if (mutex_lock_interruptible(&fan_mutex))
-		return -ERESTARTSYS;
-
-	rc = 0;
-	switch (fan_control_access_mode) {
-	case TPACPI_FAN_WR_ACPI_FANS:
-	case TPACPI_FAN_WR_TPEC:
-		if (!acpi_ec_write(fan_status_offset, 0x00))
-			rc = -EIO;
-		else {
-			fan_control_desired_level = 0;
-			tp_features.fan_ctrl_status_undef = 0;
-		}
-		break;
-
-	case TPACPI_FAN_WR_ACPI_SFAN:
-		if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", 0x00))
-			rc = -EIO;
-		else
-			fan_control_desired_level = 0;
-		break;
-
-	default:
-		rc = -ENXIO;
-	}
-
-
-	mutex_unlock(&fan_mutex);
-	return rc;
-}
-
-static int fan_set_speed(int speed)
-{
-	int rc;
-
-	if (!fan_control_allowed)
-		return -EPERM;
-
-	if (mutex_lock_interruptible(&fan_mutex))
-		return -ERESTARTSYS;
-
-	rc = 0;
-	switch (fan_control_access_mode) {
-	case TPACPI_FAN_WR_ACPI_FANS:
-		if (speed >= 0 && speed <= 65535) {
-			if (!acpi_evalf(fans_handle, NULL, NULL, "vddd",
-					speed, speed, speed))
-				rc = -EIO;
-		} else
-			rc = -EINVAL;
-		break;
-
-	default:
-		rc = -ENXIO;
-	}
-
-	mutex_unlock(&fan_mutex);
-	return rc;
-}
-
 static int fan_read(char *p)
 {
 	int len = 0;
@@ -5473,11 +5450,12 @@ static struct device_attribute dev_attr_thinkpad_acpi_pdev_name =
 /* /proc support */
 static struct proc_dir_entry *proc_dir;
 
-
 /*
  * Module and infrastructure proble, init and exit handling
  */
 
+static int force_load;
+
 #ifdef CONFIG_THINKPAD_ACPI_DEBUG
 static const char * __init str_supported(int is_supported)
 {
@@ -5487,7 +5465,47 @@ static const char * __init str_supported(int is_supported)
 }
 #endif /* CONFIG_THINKPAD_ACPI_DEBUG */
 
-static void ibm_exit(struct ibm_struct *ibm);
+static void ibm_exit(struct ibm_struct *ibm)
+{
+	dbg_printk(TPACPI_DBG_EXIT, "removing %s\n", ibm->name);
+
+	list_del_init(&ibm->all_drivers);
+
+	if (ibm->flags.acpi_notify_installed) {
+		dbg_printk(TPACPI_DBG_EXIT,
+			"%s: acpi_remove_notify_handler\n", ibm->name);
+		BUG_ON(!ibm->acpi);
+		acpi_remove_notify_handler(*ibm->acpi->handle,
+					   ibm->acpi->type,
+					   dispatch_acpi_notify);
+		ibm->flags.acpi_notify_installed = 0;
+		ibm->flags.acpi_notify_installed = 0;
+	}
+
+	if (ibm->flags.proc_created) {
+		dbg_printk(TPACPI_DBG_EXIT,
+			"%s: remove_proc_entry\n", ibm->name);
+		remove_proc_entry(ibm->name, proc_dir);
+		ibm->flags.proc_created = 0;
+	}
+
+	if (ibm->flags.acpi_driver_registered) {
+		dbg_printk(TPACPI_DBG_EXIT,
+			"%s: acpi_bus_unregister_driver\n", ibm->name);
+		BUG_ON(!ibm->acpi);
+		acpi_bus_unregister_driver(ibm->acpi->driver);
+		kfree(ibm->acpi->driver);
+		ibm->acpi->driver = NULL;
+		ibm->flags.acpi_driver_registered = 0;
+	}
+
+	if (ibm->flags.init_called && ibm->exit) {
+		ibm->exit();
+		ibm->flags.init_called = 0;
+	}
+
+	dbg_printk(TPACPI_DBG_INIT, "finished removing %s\n", ibm->name);
+}
 
 static int __init ibm_init(struct ibm_init_struct *iibm)
 {
@@ -5569,48 +5587,6 @@ err_out:
 	return (ret < 0)? ret : 0;
 }
 
-static void ibm_exit(struct ibm_struct *ibm)
-{
-	dbg_printk(TPACPI_DBG_EXIT, "removing %s\n", ibm->name);
-
-	list_del_init(&ibm->all_drivers);
-
-	if (ibm->flags.acpi_notify_installed) {
-		dbg_printk(TPACPI_DBG_EXIT,
-			"%s: acpi_remove_notify_handler\n", ibm->name);
-		BUG_ON(!ibm->acpi);
-		acpi_remove_notify_handler(*ibm->acpi->handle,
-					   ibm->acpi->type,
-					   dispatch_acpi_notify);
-		ibm->flags.acpi_notify_installed = 0;
-		ibm->flags.acpi_notify_installed = 0;
-	}
-
-	if (ibm->flags.proc_created) {
-		dbg_printk(TPACPI_DBG_EXIT,
-			"%s: remove_proc_entry\n", ibm->name);
-		remove_proc_entry(ibm->name, proc_dir);
-		ibm->flags.proc_created = 0;
-	}
-
-	if (ibm->flags.acpi_driver_registered) {
-		dbg_printk(TPACPI_DBG_EXIT,
-			"%s: acpi_bus_unregister_driver\n", ibm->name);
-		BUG_ON(!ibm->acpi);
-		acpi_bus_unregister_driver(ibm->acpi->driver);
-		kfree(ibm->acpi->driver);
-		ibm->acpi->driver = NULL;
-		ibm->flags.acpi_driver_registered = 0;
-	}
-
-	if (ibm->flags.init_called && ibm->exit) {
-		ibm->exit();
-		ibm->flags.init_called = 0;
-	}
-
-	dbg_printk(TPACPI_DBG_INIT, "finished removing %s\n", ibm->name);
-}
-
 /* Probing */
 
 static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp)
@@ -5839,7 +5815,57 @@ IBM_PARAM(brightness);
 IBM_PARAM(volume);
 IBM_PARAM(fan);
 
-static void thinkpad_acpi_module_exit(void);
+static void thinkpad_acpi_module_exit(void)
+{
+	struct ibm_struct *ibm, *itmp;
+
+	tpacpi_lifecycle = TPACPI_LIFE_EXITING;
+
+	list_for_each_entry_safe_reverse(ibm, itmp,
+					 &tpacpi_all_drivers,
+					 all_drivers) {
+		ibm_exit(ibm);
+	}
+
+	dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n");
+
+	if (tpacpi_inputdev) {
+		if (tp_features.input_device_registered)
+			input_unregister_device(tpacpi_inputdev);
+		else
+			input_free_device(tpacpi_inputdev);
+	}
+
+	if (tpacpi_hwmon)
+		hwmon_device_unregister(tpacpi_hwmon);
+
+	if (tp_features.sensors_pdev_attrs_registered)
+		device_remove_file(&tpacpi_sensors_pdev->dev,
+				   &dev_attr_thinkpad_acpi_pdev_name);
+	if (tpacpi_sensors_pdev)
+		platform_device_unregister(tpacpi_sensors_pdev);
+	if (tpacpi_pdev)
+		platform_device_unregister(tpacpi_pdev);
+
+	if (tp_features.sensors_pdrv_attrs_registered)
+		tpacpi_remove_driver_attributes(&tpacpi_hwmon_pdriver.driver);
+	if (tp_features.platform_drv_attrs_registered)
+		tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver);
+
+	if (tp_features.sensors_pdrv_registered)
+		platform_driver_unregister(&tpacpi_hwmon_pdriver);
+
+	if (tp_features.platform_drv_registered)
+		platform_driver_unregister(&tpacpi_pdriver);
+
+	if (proc_dir)
+		remove_proc_entry(IBM_PROC_DIR, acpi_root_dir);
+
+	kfree(thinkpad_id.bios_version_str);
+	kfree(thinkpad_id.ec_version_str);
+	kfree(thinkpad_id.model_str);
+}
+
 
 static int __init thinkpad_acpi_module_init(void)
 {
@@ -5978,56 +6004,5 @@ static int __init thinkpad_acpi_module_init(void)
 	return 0;
 }
 
-static void thinkpad_acpi_module_exit(void)
-{
-	struct ibm_struct *ibm, *itmp;
-
-	tpacpi_lifecycle = TPACPI_LIFE_EXITING;
-
-	list_for_each_entry_safe_reverse(ibm, itmp,
-					 &tpacpi_all_drivers,
-					 all_drivers) {
-		ibm_exit(ibm);
-	}
-
-	dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n");
-
-	if (tpacpi_inputdev) {
-		if (tp_features.input_device_registered)
-			input_unregister_device(tpacpi_inputdev);
-		else
-			input_free_device(tpacpi_inputdev);
-	}
-
-	if (tpacpi_hwmon)
-		hwmon_device_unregister(tpacpi_hwmon);
-
-	if (tp_features.sensors_pdev_attrs_registered)
-		device_remove_file(&tpacpi_sensors_pdev->dev,
-				   &dev_attr_thinkpad_acpi_pdev_name);
-	if (tpacpi_sensors_pdev)
-		platform_device_unregister(tpacpi_sensors_pdev);
-	if (tpacpi_pdev)
-		platform_device_unregister(tpacpi_pdev);
-
-	if (tp_features.sensors_pdrv_attrs_registered)
-		tpacpi_remove_driver_attributes(&tpacpi_hwmon_pdriver.driver);
-	if (tp_features.platform_drv_attrs_registered)
-		tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver);
-
-	if (tp_features.sensors_pdrv_registered)
-		platform_driver_unregister(&tpacpi_hwmon_pdriver);
-
-	if (tp_features.platform_drv_registered)
-		platform_driver_unregister(&tpacpi_pdriver);
-
-	if (proc_dir)
-		remove_proc_entry(IBM_PROC_DIR, acpi_root_dir);
-
-	kfree(thinkpad_id.bios_version_str);
-	kfree(thinkpad_id.ec_version_str);
-	kfree(thinkpad_id.model_str);
-}
-
 module_init(thinkpad_acpi_module_init);
 module_exit(thinkpad_acpi_module_exit);
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#40 lore raw

PATCH 40/112 ACPI: thinkpad-acpi: spring cleanup part 4

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

Remove dead code, and anything in the old changelog that is not a thank you credit, or a key point to track down history.

---
 drivers/misc/thinkpad_acpi.c |   55 +++--------------------------------------
 1 files changed, 4 insertions(+), 51 deletions(-)
drivers/misc/thinkpad_acpi.c +4 -51
index b6293a4..45be8e5 100644
@@ -26,6 +26,8 @@
 
 /*
  *  Changelog:
+ *  2007-10-20		changelog trimmed down
+ *
  *  2007-03-27  0.14	renamed to thinkpad_acpi and moved to
  *  			drivers/misc.
  *
@@ -33,53 +35,16 @@
  *  			changelog now lives in git commit history, and will
  *  			not be updated further in-file.
  *
- *  2005-08-17  0.12	fix compilation on 2.6.13-rc kernels
  *  2005-03-17	0.11	support for 600e, 770x
  *			    thanks to Jamie Lentin <[email protected]>
- *			support for 770e, G41
- *			G40 and G41 don't have a thinklight
- *			temperatures no longer experimental
- *			experimental brightness control
- *			experimental volume control
- *			experimental fan enable/disable
- *  2005-01-16	0.10	fix module loading on R30, R31
- *  2005-01-16	0.9	support for 570, R30, R31
- *			ultrabay support on A22p, A3x
- *			limit arg for cmos, led, beep, drop experimental status
- *			more capable led control on A21e, A22p, T20-22, X20
- *			experimental temperatures and fan speed
- *			experimental embedded controller register dump
- *			mark more functions as __init, drop incorrect __exit
- *			use MODULE_VERSION
+ *
+ *  2005-01-16	0.9	use MODULE_VERSION
  *			    thanks to Henrik Brix Andersen <[email protected]>
  *			fix parameter passing on module loading
  *			    thanks to Rusty Russell <[email protected]>
  *			    thanks to Jim Radford <[email protected]>
  *  2004-11-08	0.8	fix init error case, don't return from a macro
  *			    thanks to Chris Wright <[email protected]>
- *  2004-10-23	0.7	fix module loading on A21e, A22p, T20, T21, X20
- *			fix led control on A21e
- *  2004-10-19	0.6	use acpi_bus_register_driver() to claim HKEY device
- *  2004-10-18	0.5	thinklight support on A21e, G40, R32, T20, T21, X20
- *			proc file format changed
- *			video_switch command
- *			experimental cmos control
- *			experimental led control
- *			experimental acpi sounds
- *  2004-09-16	0.4	support for module parameters
- *			hotkey mask can be prefixed by 0x
- *			video output switching
- *			video expansion control
- *			ultrabay eject support
- *			removed lcd brightness/on/off control, didn't work
- *  2004-08-17	0.3	support for R40
- *			lcd off, brightness control
- *			thinklight on/off
- *  2004-08-14	0.2	support for T series, X20
- *			bluetooth enable/disable
- *			hotkey events disabled by default
- *			removed fan control, currently useless
- *  2004-08-09	0.1	initial release, support for X series
  */
 
 #include <linux/kernel.h>
@@ -314,8 +279,6 @@ struct thinkpad_id_data {
 };
 static struct thinkpad_id_data thinkpad_id;
 
-#define __unused __attribute__ ((unused))
-
 static enum {
 	TPACPI_LIFE_INIT = 0,
 	TPACPI_LIFE_RUNNING,
@@ -451,16 +414,6 @@ static int acpi_evalf(acpi_handle handle,
 	return success;
 }
 
-static void __unused acpi_print_int(acpi_handle handle, char *method)
-{
-	int i;
-
-	if (acpi_evalf(handle, &i, method, "d"))
-		printk(IBM_INFO "%s = 0x%x\n", method, i);
-	else
-		printk(IBM_ERR "error calling %s\n", method);
-}
-
 static int acpi_ec_read(int i, u8 * p)
 {
 	int v;
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#41 lore raw

PATCH 41/112 ACPI: thinkpad-acpi: module glue cleanups

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

General cleanup of module glue: Do some code reordering, and add missing parameter help text.

---
 drivers/misc/thinkpad_acpi.c |   83 +++++++++++++++++++++++++-----------------
 1 files changed, 50 insertions(+), 33 deletions(-)
drivers/misc/thinkpad_acpi.c +50 -33
index 45be8e5..be04f1c 100644
@@ -124,7 +124,6 @@ enum {
  * Main driver
  */
 
-/* Module */
 #define IBM_NAME "thinkpad"
 #define IBM_DESC "ThinkPad ACPI Extras"
 #define IBM_FILE IBM_NAME "_acpi"
@@ -138,37 +137,6 @@ enum {
 
 #define IBM_MAX_ACPI_ARGS 3
 
-MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
-MODULE_DESCRIPTION(IBM_DESC);
-MODULE_VERSION(IBM_VERSION);
-MODULE_LICENSE("GPL");
-
-/* Please remove this in year 2009 */
-MODULE_ALIAS("ibm_acpi");
-
-/*
- * DMI matching for module autoloading
- *
- * See http://thinkwiki.org/wiki/List_of_DMI_IDs
- * See http://thinkwiki.org/wiki/BIOS_Upgrade_Downloads
- *
- * Only models listed in thinkwiki will be supported, so add yours
- * if it is not there yet.
- */
-#define IBM_BIOS_MODULE_ALIAS(__type) \
-	MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW")
-
-/* Non-ancient thinkpads */
-MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*");
-MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*");
-
-/* Ancient thinkpad BIOSes have to be identified by
- * BIOS type or model number, and there are far less
- * BIOS types than model numbers... */
-IBM_BIOS_MODULE_ALIAS("I[B,D,H,I,M,N,O,T,W,V,Y,Z]");
-IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]");
-IBM_BIOS_MODULE_ALIAS("K[U,X-Z]");
-
 /* Debugging */
 #define IBM_LOG IBM_FILE ": "
 #define IBM_ERR	   KERN_ERR    IBM_LOG
@@ -5734,21 +5702,39 @@ static int __init set_ibm_param(const char *val, struct kernel_param *kp)
 }
 
 module_param(experimental, int, 0);
+MODULE_PARM_DESC(experimental,
+                 "Enables experimental features when non-zero");
 
 module_param_named(debug, dbg_level, uint, 0);
+MODULE_PARM_DESC(debug, "Sets debug level bit-mask");
 
 module_param(force_load, bool, 0);
+MODULE_PARM_DESC(force_load,
+                 "Attempts to load the driver even on a "
+                 "mis-identified ThinkPad when true");
 
 module_param_named(fan_control, fan_control_allowed, bool, 0);
+MODULE_PARM_DESC(fan_control,
+                 "Enables setting fan parameters features when true");
 
 module_param_named(brightness_mode, brightness_mode, int, 0);
+MODULE_PARM_DESC(brightness_mode,
+                 "Selects brightness control strategy: "
+                 "0=auto, 1=EC, 2=CMOS, 3=both");
 
 module_param(brightness_enable, uint, 0);
+MODULE_PARM_DESC(brightness_enable,
+                 "Enables backlight control when 1, disables when 0");
 
 module_param(hotkey_report_mode, uint, 0);
+MODULE_PARM_DESC(hotkey_report_mode,
+                 "used for backwards compatibility with userspace, "
+                 "see documentation");
 
 #define IBM_PARAM(feature) \
-	module_param_call(feature, set_ibm_param, NULL, NULL, 0)
+	module_param_call(feature, set_ibm_param, NULL, NULL, 0); \
+	MODULE_PARM_DESC(feature, "Simulates thinkpad-aci procfs command " \
+	                 "at module load, see documentation")
 
 IBM_PARAM(hotkey);
 IBM_PARAM(bluetooth);
@@ -5957,5 +5943,36 @@ static int __init thinkpad_acpi_module_init(void)
 	return 0;
 }
 
+/* Please remove this in year 2009 */
+MODULE_ALIAS("ibm_acpi");
+
+/*
+ * DMI matching for module autoloading
+ *
+ * See http://thinkwiki.org/wiki/List_of_DMI_IDs
+ * See http://thinkwiki.org/wiki/BIOS_Upgrade_Downloads
+ *
+ * Only models listed in thinkwiki will be supported, so add yours
+ * if it is not there yet.
+ */
+#define IBM_BIOS_MODULE_ALIAS(__type) \
+	MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW")
+
+/* Non-ancient thinkpads */
+MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*");
+MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*");
+
+/* Ancient thinkpad BIOSes have to be identified by
+ * BIOS type or model number, and there are far less
+ * BIOS types than model numbers... */
+IBM_BIOS_MODULE_ALIAS("I[B,D,H,I,M,N,O,T,W,V,Y,Z]");
+IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]");
+IBM_BIOS_MODULE_ALIAS("K[U,X-Z]");
+
+MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
+MODULE_DESCRIPTION(IBM_DESC);
+MODULE_VERSION(IBM_VERSION);
+MODULE_LICENSE("GPL");
+
 module_init(thinkpad_acpi_module_init);
 module_exit(thinkpad_acpi_module_exit);
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#62 lore raw

PATCH 55/112 ACPI: ACPI thermal zone handle notification correctly

In reply to Len Brown

From: Zhang Rui <[email protected]>

Change the ACPI thermal action upon notification 0x81 and 0x82.

According to the ACPI spec, we should:
re-evaluate _PSV and _ACx methods upon notification 0x81 re-evaluate _PSL and _ALx and _TZD upon notificaiton 0x82. But the current code re-evaluates all the trip points for 0x81 while only re-evaluates _TZD for 0x82.

Fix this violation of ACPI spec.

TODO: devices in _PSL, _ALx and _TZD may change after a notification 0x82.
At this time, we need to re-bind the cooling devices with the thermal zone.

---
 drivers/acpi/thermal.c |  325 +++++++++++++++++++++++++++---------------------
 1 files changed, 184 insertions(+), 141 deletions(-)
drivers/acpi/thermal.c +184 -141
index c6cfce4..d317da5 100644
@@ -323,173 +323,221 @@ static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
 	return 0;
 }
 
-static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
-{
-	acpi_status status = AE_OK;
-	int i = 0;
+#define ACPI_TRIPS_CRITICAL	0x01
+#define ACPI_TRIPS_HOT		0x02
+#define ACPI_TRIPS_PASSIVE	0x04
+#define ACPI_TRIPS_ACTIVE	0x08
+#define ACPI_TRIPS_DEVICES	0x10
 
+#define ACPI_TRIPS_REFRESH_THRESHOLDS	(ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE)
+#define ACPI_TRIPS_REFRESH_DEVICES	ACPI_TRIPS_DEVICES
 
-	if (!tz)
-		return -EINVAL;
+#define ACPI_TRIPS_INIT      (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT |	\
+			      ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE |	\
+			      ACPI_TRIPS_DEVICES)
 
-	/* Critical Shutdown (required) */
-
-	status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL,
-				       &tz->trips.critical.temperature);
-	if (ACPI_FAILURE(status)) {
-		tz->trips.critical.flags.valid = 0;
-		ACPI_EXCEPTION((AE_INFO, status, "No critical threshold"));
-		return -ENODEV;
-	} else {
-		tz->trips.critical.flags.valid = 1;
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Found critical threshold [%lu]\n",
-				  tz->trips.critical.temperature));
-	}
+/*
+ * This exception is thrown out in two cases:
+ * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid
+ *   when re-evaluating the AML code.
+ * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change.
+ *   We need to re-bind the cooling devices of a thermal zone when this occurs.
+ */
+#define ACPI_THERMAL_TRIPS_EXCEPTION(flags, str)	\
+do {	\
+	if (flags != ACPI_TRIPS_INIT)	\
+		ACPI_EXCEPTION((AE_INFO, AE_ERROR,	\
+		"ACPI thermal trip point %s changed\n"	\
+		"Please send acpidump to [email protected]\n", str)); \
+} while (0)
+
+static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
+{
+	acpi_status status = AE_OK;
+	struct acpi_handle_list devices;
+	int valid = 0;
+	int i;
 
-	if (tz->trips.critical.flags.valid == 1) {
-		if (crt == -1) {
+	/* Critical Shutdown (required) */
+	if (flag & ACPI_TRIPS_CRITICAL) {
+		status = acpi_evaluate_integer(tz->device->handle,
+				"_CRT", NULL, &tz->trips.critical.temperature);
+		if (ACPI_FAILURE(status)) {
 			tz->trips.critical.flags.valid = 0;
-		} else if (crt > 0) {
-			unsigned long crt_k = CELSIUS_TO_KELVIN(crt);
-
-			/*
-			 * Allow override to lower critical threshold
-			 */
-			if (crt_k < tz->trips.critical.temperature)
-				tz->trips.critical.temperature = crt_k;
+			ACPI_EXCEPTION((AE_INFO, status,
+					"No critical threshold"));
+			return -ENODEV;
+		} else {
+			tz->trips.critical.flags.valid = 1;
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+					"Found critical threshold [%lu]\n",
+					tz->trips.critical.temperature));
+		}
+		if (tz->trips.critical.flags.valid == 1) {
+			if (crt == -1) {
+				tz->trips.critical.flags.valid = 0;
+			} else if (crt > 0) {
+				unsigned long crt_k = CELSIUS_TO_KELVIN(crt);
+				/*
+				 * Allow override to lower critical threshold
+				 */
+				if (crt_k < tz->trips.critical.temperature)
+					tz->trips.critical.temperature = crt_k;
+			}
 		}
 	}
 
 	/* Critical Sleep (optional) */
-
-	status =
-	    acpi_evaluate_integer(tz->device->handle, "_HOT", NULL,
-				  &tz->trips.hot.temperature);
-	if (ACPI_FAILURE(status)) {
-		tz->trips.hot.flags.valid = 0;
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No hot threshold\n"));
-	} else {
-		tz->trips.hot.flags.valid = 1;
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n",
-				  tz->trips.hot.temperature));
-	}
-
-	/* Passive: Processors (optional) */
-
-	if (psv == -1) {
-		status = AE_SUPPORT;
-	} else if (psv > 0) {
-		tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv);
-		status = AE_OK;
-	} else {
+	if (flag & ACPI_TRIPS_HOT) {
 		status = acpi_evaluate_integer(tz->device->handle,
-			"_PSV", NULL, &tz->trips.passive.temperature);
+				"_HOT", NULL, &tz->trips.hot.temperature);
+		if (ACPI_FAILURE(status)) {
+			tz->trips.hot.flags.valid = 0;
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+					"No hot threshold\n"));
+		} else {
+			tz->trips.hot.flags.valid = 1;
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+					"Found hot threshold [%lu]\n",
+					tz->trips.critical.temperature));
+		}
 	}
 
-	if (ACPI_FAILURE(status)) {
-		tz->trips.passive.flags.valid = 0;
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n"));
-	} else {
-		tz->trips.passive.flags.valid = 1;
-
-		status =
-		    acpi_evaluate_integer(tz->device->handle, "_TC1", NULL,
-					  &tz->trips.passive.tc1);
-		if (ACPI_FAILURE(status))
-			tz->trips.passive.flags.valid = 0;
-
-		status =
-		    acpi_evaluate_integer(tz->device->handle, "_TC2", NULL,
-					  &tz->trips.passive.tc2);
-		if (ACPI_FAILURE(status))
-			tz->trips.passive.flags.valid = 0;
+	/* Passive (optional) */
+	if (flag & ACPI_TRIPS_PASSIVE) {
+		valid = tz->trips.passive.flags.valid;
+		if (psv == -1) {
+			status = AE_SUPPORT;
+		} else if (psv > 0) {
+			tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv);
+			status = AE_OK;
+		} else {
+			status = acpi_evaluate_integer(tz->device->handle,
+				"_PSV", NULL, &tz->trips.passive.temperature);
+		}
 
-		status =
-		    acpi_evaluate_integer(tz->device->handle, "_TSP", NULL,
-					  &tz->trips.passive.tsp);
 		if (ACPI_FAILURE(status))
 			tz->trips.passive.flags.valid = 0;
-
-		status =
-		    acpi_evaluate_reference(tz->device->handle, "_PSL", NULL,
-					    &tz->trips.passive.devices);
+		else {
+			tz->trips.passive.flags.valid = 1;
+			if (flag == ACPI_TRIPS_INIT) {
+				status = acpi_evaluate_integer(
+						tz->device->handle, "_TC1",
+						NULL, &tz->trips.passive.tc1);
+				if (ACPI_FAILURE(status))
+					tz->trips.passive.flags.valid = 0;
+				status = acpi_evaluate_integer(
+						tz->device->handle, "_TC2",
+						NULL, &tz->trips.passive.tc2);
+				if (ACPI_FAILURE(status))
+					tz->trips.passive.flags.valid = 0;
+				status = acpi_evaluate_integer(
+						tz->device->handle, "_TSP",
+						NULL, &tz->trips.passive.tsp);
+				if (ACPI_FAILURE(status))
+					tz->trips.passive.flags.valid = 0;
+			}
+		}
+	}
+	if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.flags.valid) {
+		memset(&devices, 0, sizeof(struct acpi_handle_list));
+		status = acpi_evaluate_reference(tz->device->handle, "_PSL",
+							NULL, &devices);
 		if (ACPI_FAILURE(status))
 			tz->trips.passive.flags.valid = 0;
-
-		if (!tz->trips.passive.flags.valid)
-			printk(KERN_WARNING PREFIX "Invalid passive threshold\n");
 		else
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-					  "Found passive threshold [%lu]\n",
-					  tz->trips.passive.temperature));
-	}
+			tz->trips.passive.flags.valid = 1;
 
-	/* Active: Fans, etc. (optional) */
+		if (memcmp(&tz->trips.passive.devices, &devices,
+				sizeof(struct acpi_handle_list))) {
+			memcpy(&tz->trips.passive.devices, &devices,
+				sizeof(struct acpi_handle_list));
+			ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
+		}
+	}
+	if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
+		if (valid != tz->trips.passive.flags.valid)
+				ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
+	}
 
+	/* Active (optional) */
 	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
-
 		char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
+		valid = tz->trips.active[i].flags.valid;
 
 		if (act == -1)
-			break;	/* disable all active trip points */
-
-		status = acpi_evaluate_integer(tz->device->handle,
-			name, NULL, &tz->trips.active[i].temperature);
-
-		if (ACPI_FAILURE(status)) {
-			if (i == 0)	/* no active trip points */
+			break; /* disable all active trip points */
+
+		if (flag & ACPI_TRIPS_ACTIVE) {
+			status = acpi_evaluate_integer(tz->device->handle,
+				name, NULL, &tz->trips.active[i].temperature);
+			if (ACPI_FAILURE(status)) {
+				tz->trips.active[i].flags.valid = 0;
+				if (i == 0)
+					break;
+				if (act <= 0)
+					break;
+				if (i == 1)
+					tz->trips.active[0].temperature =
+						CELSIUS_TO_KELVIN(act);
+				else
+					/*
+					 * Don't allow override higher than
+					 * the next higher trip point
+					 */
+					tz->trips.active[i - 1].temperature =
+						(tz->trips.active[i - 2].temperature <
+						CELSIUS_TO_KELVIN(act) ?
+						tz->trips.active[i - 2].temperature :
+						CELSIUS_TO_KELVIN(act));
 				break;
-			if (act <= 0)	/* no override requested */
-				break;
-			if (i == 1) {	/* 1 trip point */
-				tz->trips.active[0].temperature =
-					CELSIUS_TO_KELVIN(act);
-			} else {	/* multiple trips */
-				/*
-				 * Don't allow override higher than
-				 * the next higher trip point
-				 */
-				tz->trips.active[i - 1].temperature =
-				    (tz->trips.active[i - 2].temperature <
-					CELSIUS_TO_KELVIN(act) ?
-					tz->trips.active[i - 2].temperature :
-					CELSIUS_TO_KELVIN(act));
-			}
-			break;
+			} else
+				tz->trips.active[i].flags.valid = 1;
 		}
 
 		name[2] = 'L';
-		status =
-		    acpi_evaluate_reference(tz->device->handle, name, NULL,
-					    &tz->trips.active[i].devices);
-		if (ACPI_SUCCESS(status)) {
-			tz->trips.active[i].flags.valid = 1;
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-					  "Found active threshold [%d]:[%lu]\n",
-					  i, tz->trips.active[i].temperature));
-		} else
-			ACPI_EXCEPTION((AE_INFO, status,
-					"Invalid active threshold [%d]", i));
+		if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].flags.valid ) {
+			memset(&devices, 0, sizeof(struct acpi_handle_list));
+			status = acpi_evaluate_reference(tz->device->handle,
+						name, NULL, &devices);
+			if (ACPI_FAILURE(status))
+				tz->trips.active[i].flags.valid = 0;
+			else
+				tz->trips.active[i].flags.valid = 1;
+
+			if (memcmp(&tz->trips.active[i].devices, &devices,
+					sizeof(struct acpi_handle_list))) {
+				memcpy(&tz->trips.active[i].devices, &devices,
+					sizeof(struct acpi_handle_list));
+				ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
+			}
+		}
+		if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES))
+			if (valid != tz->trips.active[i].flags.valid)
+				ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
+
+		if (!tz->trips.active[i].flags.valid)
+			break;
+	}
+
+	if (flag & ACPI_TRIPS_DEVICES) {
+		memset(&devices, 0, sizeof(struct acpi_handle_list));
+		status = acpi_evaluate_reference(tz->device->handle, "_TZD",
+						NULL, &devices);
+		if (memcmp(&tz->devices, &devices,
+				sizeof(struct acpi_handle_list))) {
+			memcpy(&tz->devices, &devices,
+				sizeof(struct acpi_handle_list));
+			ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
+		}
 	}
 
 	return 0;
 }
 
-static int acpi_thermal_get_devices(struct acpi_thermal *tz)
+static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
 {
-	acpi_status status = AE_OK;
-
-
-	if (!tz)
-		return -EINVAL;
-
-	status =
-	    acpi_evaluate_reference(tz->device->handle, "_TZD", NULL, &tz->devices);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
-
-	return 0;
+	return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
 }
 
 static int acpi_thermal_critical(struct acpi_thermal *tz)
@@ -1453,15 +1501,15 @@ static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
 		acpi_thermal_check(tz);
 		break;
 	case ACPI_THERMAL_NOTIFY_THRESHOLDS:
-		acpi_thermal_get_trip_points(tz);
+		acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS);
 		acpi_thermal_check(tz);
 		acpi_bus_generate_proc_event(device, event, 0);
 		acpi_bus_generate_netlink_event(device->pnp.device_class,
 						  device->dev.bus_id, event, 0);
 		break;
 	case ACPI_THERMAL_NOTIFY_DEVICES:
-		if (tz->flags.devices)
-			acpi_thermal_get_devices(tz);
+		acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
+		acpi_thermal_check(tz);
 		acpi_bus_generate_proc_event(device, event, 0);
 		acpi_bus_generate_netlink_event(device->pnp.device_class,
 						  device->dev.bus_id, event, 0);
@@ -1504,11 +1552,6 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz)
 	else
 		acpi_thermal_get_polling_frequency(tz);
 
-	/* Get devices in this thermal zone [_TZD] (optional) */
-	result = acpi_thermal_get_devices(tz);
-	if (!result)
-		tz->flags.devices = 1;
-
 	return 0;
 }
 
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#42 lore raw

PATCH 42/112 ACPI: thinkpad-acpi: rename IBM in defines

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

Rename defines with IBM in their name that are related to the older driver name (ibm-acpi) to TPACPI, unless they are specific to IBM ThinkPads.

---
 drivers/misc/thinkpad_acpi.c |  324 +++++++++++++++++++++---------------------
 1 files changed, 162 insertions(+), 162 deletions(-)
drivers/misc/thinkpad_acpi.c +162 -162
index be04f1c..c92ae8d 100644
@@ -21,7 +21,7 @@
  *  02110-1301, USA.
  */
 
-#define IBM_VERSION "0.18"
+#define TPACPI_VERSION "0.18"
 #define TPACPI_SYSFS_VERSION 0x020101
 
 /*
@@ -113,7 +113,7 @@ enum {
 };
 
 /* ACPI HIDs */
-#define IBM_HKEY_HID    "IBM0068"
+#define TPACPI_ACPI_HKEY_HID		"IBM0068"
 
 /* Input IDs */
 #define TPACPI_HKEY_INPUT_PRODUCT	0x5054 /* "TP" */
@@ -124,25 +124,25 @@ enum {
  * Main driver
  */
 
-#define IBM_NAME "thinkpad"
-#define IBM_DESC "ThinkPad ACPI Extras"
-#define IBM_FILE IBM_NAME "_acpi"
-#define IBM_URL "http://ibm-acpi.sf.net/"
-#define IBM_MAIL "[email protected]"
+#define TPACPI_NAME "thinkpad"
+#define TPACPI_DESC "ThinkPad ACPI Extras"
+#define TPACPI_FILE TPACPI_NAME "_acpi"
+#define TPACPI_URL "http://ibm-acpi.sf.net/"
+#define TPACPI_MAIL "[email protected]"
 
-#define IBM_PROC_DIR "ibm"
-#define IBM_ACPI_EVENT_PREFIX "ibm"
-#define IBM_DRVR_NAME IBM_FILE
-#define IBM_HWMON_DRVR_NAME IBM_NAME "_hwmon"
+#define TPACPI_PROC_DIR "ibm"
+#define TPACPI_ACPI_EVENT_PREFIX "ibm"
+#define TPACPI_DRVR_NAME TPACPI_FILE
+#define TPACPI_HWMON_DRVR_NAME TPACPI_NAME "_hwmon"
 
-#define IBM_MAX_ACPI_ARGS 3
+#define TPACPI_MAX_ACPI_ARGS 3
 
 /* Debugging */
-#define IBM_LOG IBM_FILE ": "
-#define IBM_ERR	   KERN_ERR    IBM_LOG
-#define IBM_NOTICE KERN_NOTICE IBM_LOG
-#define IBM_INFO   KERN_INFO   IBM_LOG
-#define IBM_DEBUG  KERN_DEBUG  IBM_LOG
+#define TPACPI_LOG TPACPI_FILE ": "
+#define TPACPI_ERR	   KERN_ERR    TPACPI_LOG
+#define TPACPI_NOTICE KERN_NOTICE TPACPI_LOG
+#define TPACPI_INFO   KERN_INFO   TPACPI_LOG
+#define TPACPI_DEBUG  KERN_DEBUG  TPACPI_LOG
 
 #define TPACPI_DBG_ALL		0xffff
 #define TPACPI_DBG_ALL		0xffff
@@ -150,7 +150,7 @@ enum {
 #define TPACPI_DBG_EXIT		0x0002
 #define dbg_printk(a_dbg_level, format, arg...) \
 	do { if (dbg_level & a_dbg_level) \
-		printk(IBM_DEBUG "%s: " format, __func__ , ## arg); } while (0)
+		printk(TPACPI_DEBUG "%s: " format, __func__ , ## arg); } while (0)
 #ifdef CONFIG_THINKPAD_ACPI_DEBUG
 #define vdbg_printk(a_dbg_level, format, arg...) \
 	dbg_printk(a_dbg_level, format, ## arg)
@@ -270,13 +270,13 @@ static u32 dbg_level;
 
 static acpi_handle root_handle;
 
-#define IBM_HANDLE(object, parent, paths...)			\
+#define TPACPI_HANDLE(object, parent, paths...)			\
 	static acpi_handle  object##_handle;			\
 	static acpi_handle *object##_parent = &parent##_handle;	\
 	static char        *object##_path;			\
 	static char        *object##_paths[] = { paths }
 
-IBM_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0",	/* 240, 240x */
+TPACPI_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0",	/* 240, 240x */
 	   "\\_SB.PCI.ISA.EC",	/* 570 */
 	   "\\_SB.PCI0.ISA0.EC0",	/* 600e/x, 770e, 770x */
 	   "\\_SB.PCI0.ISA.EC",	/* A21e, A2xm/p, T20-22, X20-21 */
@@ -285,15 +285,15 @@ IBM_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0",	/* 240, 240x */
 	   "\\_SB.PCI0.LPC.EC",	/* all others */
 	   );
 
-IBM_HANDLE(ecrd, ec, "ECRD");	/* 570 */
-IBM_HANDLE(ecwr, ec, "ECWR");	/* 570 */
+TPACPI_HANDLE(ecrd, ec, "ECRD");	/* 570 */
+TPACPI_HANDLE(ecwr, ec, "ECWR");	/* 570 */
 
-IBM_HANDLE(cmos, root, "\\UCMS",	/* R50, R50e, R50p, R51, T4x, X31, X40 */
+TPACPI_HANDLE(cmos, root, "\\UCMS",	/* R50, R50e, R50p, R51, T4x, X31, X40 */
 	   "\\CMOS",		/* A3x, G4x, R32, T23, T30, X22-24, X30 */
 	   "\\CMS",		/* R40, R40e */
 	   );			/* all others */
 
-IBM_HANDLE(hkey, ec, "\\_SB.HKEY",	/* 600e/x, 770e, 770x */
+TPACPI_HANDLE(hkey, ec, "\\_SB.HKEY",	/* 600e/x, 770e, 770x */
 	   "^HKEY",		/* R30, R31 */
 	   "HKEY",		/* all others */
 	   );			/* 570 */
@@ -308,7 +308,7 @@ static int acpi_evalf(acpi_handle handle,
 {
 	char *fmt0 = fmt;
 	struct acpi_object_list params;
-	union acpi_object in_objs[IBM_MAX_ACPI_ARGS];
+	union acpi_object in_objs[TPACPI_MAX_ACPI_ARGS];
 	struct acpi_buffer result, *resultp;
 	union acpi_object out_obj;
 	acpi_status status;
@@ -318,7 +318,7 @@ static int acpi_evalf(acpi_handle handle,
 	int quiet;
 
 	if (!*fmt) {
-		printk(IBM_ERR "acpi_evalf() called with empty format\n");
+		printk(TPACPI_ERR "acpi_evalf() called with empty format\n");
 		return 0;
 	}
 
@@ -343,7 +343,7 @@ static int acpi_evalf(acpi_handle handle,
 			break;
 			/* add more types as needed */
 		default:
-			printk(IBM_ERR "acpi_evalf() called "
+			printk(TPACPI_ERR "acpi_evalf() called "
 			       "with invalid format character '%c'\n", c);
 			return 0;
 		}
@@ -370,13 +370,13 @@ static int acpi_evalf(acpi_handle handle,
 		break;
 		/* add more types as needed */
 	default:
-		printk(IBM_ERR "acpi_evalf() called "
+		printk(TPACPI_ERR "acpi_evalf() called "
 		       "with invalid format character '%c'\n", res_type);
 		return 0;
 	}
 
 	if (!success && !quiet)
-		printk(IBM_ERR "acpi_evalf(%s, %s, ...) failed: %d\n",
+		printk(TPACPI_ERR "acpi_evalf(%s, %s, ...) failed: %d\n",
 		       method, fmt0, status);
 
 	return success;
@@ -436,7 +436,7 @@ static int issue_thinkpad_cmos_command(int cmos_cmd)
  * ACPI device model
  */
 
-#define IBM_ACPIHANDLE_INIT(object)						\
+#define TPACPI_ACPIHANDLE_INIT(object)						\
 	drv_acpi_handle_init(#object, &object##_handle, *object##_parent,	\
 		object##_paths, ARRAY_SIZE(object##_paths), &object##_path)
 
@@ -494,24 +494,24 @@ static int __init setup_acpi_notify(struct ibm_struct *ibm)
 
 	rc = acpi_bus_get_device(*ibm->acpi->handle, &ibm->acpi->device);
 	if (rc < 0) {
-		printk(IBM_ERR "acpi_bus_get_device(%s) failed: %d\n",
+		printk(TPACPI_ERR "acpi_bus_get_device(%s) failed: %d\n",
 			ibm->name, rc);
 		return -ENODEV;
 	}
 
 	acpi_driver_data(ibm->acpi->device) = ibm;
 	sprintf(acpi_device_class(ibm->acpi->device), "%s/%s",
-		IBM_ACPI_EVENT_PREFIX,
+		TPACPI_ACPI_EVENT_PREFIX,
 		ibm->name);
 
 	status = acpi_install_notify_handler(*ibm->acpi->handle,
 			ibm->acpi->type, dispatch_acpi_notify, ibm);
 	if (ACPI_FAILURE(status)) {
 		if (status == AE_ALREADY_EXISTS) {
-			printk(IBM_NOTICE "another device driver is already handling %s events\n",
+			printk(TPACPI_NOTICE "another device driver is already handling %s events\n",
 				ibm->name);
 		} else {
-			printk(IBM_ERR "acpi_install_notify_handler(%s) failed: %d\n",
+			printk(TPACPI_ERR "acpi_install_notify_handler(%s) failed: %d\n",
 				ibm->name, status);
 		}
 		return -ENODEV;
@@ -536,18 +536,18 @@ static int __init register_tpacpi_subdriver(struct ibm_struct *ibm)
 
 	ibm->acpi->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL);
 	if (!ibm->acpi->driver) {
-		printk(IBM_ERR "kzalloc(ibm->driver) failed\n");
+		printk(TPACPI_ERR "kzalloc(ibm->driver) failed\n");
 		return -ENOMEM;
 	}
 
-	sprintf(ibm->acpi->driver->name, "%s_%s", IBM_NAME, ibm->name);
+	sprintf(ibm->acpi->driver->name, "%s_%s", TPACPI_NAME, ibm->name);
 	ibm->acpi->driver->ids = ibm->acpi->hid;
 
 	ibm->acpi->driver->ops.add = &tpacpi_device_add;
 
 	rc = acpi_bus_register_driver(ibm->acpi->driver);
 	if (rc < 0) {
-		printk(IBM_ERR "acpi_bus_register_driver(%s) failed: %d\n",
+		printk(TPACPI_ERR "acpi_bus_register_driver(%s) failed: %d\n",
 		       ibm->name, rc);
 		kfree(ibm->acpi->driver);
 		ibm->acpi->driver = NULL;
@@ -670,7 +670,7 @@ static int tpacpi_resume_handler(struct platform_device *pdev)
 
 static struct platform_driver tpacpi_pdriver = {
 	.driver = {
-		.name = IBM_DRVR_NAME,
+		.name = TPACPI_DRVR_NAME,
 		.owner = THIS_MODULE,
 	},
 	.resume = tpacpi_resume_handler,
@@ -678,7 +678,7 @@ static struct platform_driver tpacpi_pdriver = {
 
 static struct platform_driver tpacpi_hwmon_pdriver = {
 	.driver = {
-		.name = IBM_HWMON_DRVR_NAME,
+		.name = TPACPI_HWMON_DRVR_NAME,
 		.owner = THIS_MODULE,
 	},
 };
@@ -818,7 +818,7 @@ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
 static ssize_t tpacpi_driver_version_show(struct device_driver *drv,
 						char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%s v%s\n", IBM_DESC, IBM_VERSION);
+	return snprintf(buf, PAGE_SIZE, "%s v%s\n", TPACPI_DESC, TPACPI_VERSION);
 }
 
 static DRIVER_ATTR(version, S_IRUGO,
@@ -867,17 +867,17 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv)
 
 static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm)
 {
-	printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
-	printk(IBM_INFO "%s\n", IBM_URL);
+	printk(TPACPI_INFO "%s v%s\n", TPACPI_DESC, TPACPI_VERSION);
+	printk(TPACPI_INFO "%s\n", TPACPI_URL);
 
-	printk(IBM_INFO "ThinkPad BIOS %s, EC %s\n",
+	printk(TPACPI_INFO "ThinkPad BIOS %s, EC %s\n",
 		(thinkpad_id.bios_version_str) ?
 			thinkpad_id.bios_version_str : "unknown",
 		(thinkpad_id.ec_version_str) ?
 			thinkpad_id.ec_version_str : "unknown");
 
 	if (thinkpad_id.vendor && thinkpad_id.model_str)
-		printk(IBM_INFO "%s %s\n",
+		printk(TPACPI_INFO "%s %s\n",
 			(thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ?
 				"IBM" : ((thinkpad_id.vendor ==
 						PCI_VENDOR_ID_LENOVO) ?
@@ -891,8 +891,8 @@ static int thinkpad_acpi_driver_read(char *p)
 {
 	int len = 0;
 
-	len += sprintf(p + len, "driver:\t\t%s\n", IBM_DESC);
-	len += sprintf(p + len, "version:\t%s\n", IBM_VERSION);
+	len += sprintf(p + len, "driver:\t\t%s\n", TPACPI_DESC);
+	len += sprintf(p + len, "version:\t%s\n", TPACPI_VERSION);
 
 	return len;
 }
@@ -1073,7 +1073,7 @@ static int hotkey_mask_set(u32 mask)
 		if (!hotkey_mask_get() && !rc &&
 		    (hotkey_mask & ~hotkey_source_mask) !=
 		     (mask & ~hotkey_source_mask)) {
-			printk(IBM_NOTICE
+			printk(TPACPI_NOTICE
 			       "requested hot key mask 0x%08x, but "
 			       "firmware forced it to 0x%08x\n",
 			       mask, hotkey_mask);
@@ -1085,7 +1085,7 @@ static int hotkey_mask_set(u32 mask)
 		HOTKEY_CONFIG_CRITICAL_END
 		hotkey_mask_get();
 		if (hotkey_mask != mask) {
-			printk(IBM_NOTICE
+			printk(TPACPI_NOTICE
 			       "requested hot key mask 0x%08x, "
 			       "forced to 0x%08x (NVRAM poll mask is "
 			       "0x%08x): no firmware mask support\n",
@@ -1352,10 +1352,10 @@ static void hotkey_poll_setup(int may_warn)
 	    (tpacpi_inputdev->users > 0 || hotkey_report_mode < 2)) {
 		if (!tpacpi_hotkey_task) {
 			tpacpi_hotkey_task = kthread_run(hotkey_kthread,
-			                       NULL, IBM_FILE "d");
+			                       NULL, TPACPI_FILE "d");
 			if (IS_ERR(tpacpi_hotkey_task)) {
 				tpacpi_hotkey_task = NULL;
-				printk(IBM_ERR "could not create kernel thread "
+				printk(TPACPI_ERR "could not create kernel thread "
 				       "for hotkey polling\n");
 			}
 		}
@@ -1363,7 +1363,7 @@ static void hotkey_poll_setup(int may_warn)
 		hotkey_poll_stop_sync();
 		if (may_warn &&
 		    hotkey_source_mask != 0 && hotkey_poll_freq == 0) {
-			printk(IBM_NOTICE "hot keys 0x%08x require polling, "
+			printk(TPACPI_NOTICE "hot keys 0x%08x require polling, "
 				"which is currently disabled\n",
 				hotkey_source_mask);
 		}
@@ -1777,7 +1777,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 	BUG_ON(tpacpi_inputdev->open != NULL ||
 	       tpacpi_inputdev->close != NULL);
 
-	IBM_ACPIHANDLE_INIT(hkey);
+	TPACPI_ACPIHANDLE_INIT(hkey);
 	mutex_init(&hotkey_mutex);
 
 #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
@@ -1806,10 +1806,10 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 		   for HKEY interface version 0x100 */
 		if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
 			if ((hkeyv >> 8) != 1) {
-				printk(IBM_ERR "unknown version of the "
+				printk(TPACPI_ERR "unknown version of the "
 				       "HKEY interface: 0x%x\n", hkeyv);
-				printk(IBM_ERR "please report this to %s\n",
-				       IBM_MAIL);
+				printk(TPACPI_ERR "please report this to %s\n",
+				       TPACPI_MAIL);
 			} else {
 				/*
 				 * MHKV 0x100 in A31, R40, R40e,
@@ -1825,10 +1825,10 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 		if (tp_features.hotkey_mask) {
 			if (!acpi_evalf(hkey_handle, &hotkey_all_mask,
 					"MHKA", "qd")) {
-				printk(IBM_ERR
+				printk(TPACPI_ERR
 				       "missing MHKA handler, "
 				       "please report this to %s\n",
-				       IBM_MAIL);
+				       TPACPI_MAIL);
 				hotkey_all_mask = 0x080cU; /* FN+F12, FN+F4, FN+F3 */
 			}
 		}
@@ -1863,7 +1863,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 		/* Not all thinkpads have a hardware radio switch */
 		if (!res && acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
 			tp_features.hotkey_wlsw = 1;
-			printk(IBM_INFO
+			printk(TPACPI_INFO
 				"radio switch found; radios are %s\n",
 				enabled(status, 0));
 			res = add_to_attr_set(hotkey_dev_attributes,
@@ -1882,7 +1882,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 		hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
 						GFP_KERNEL);
 		if (!hotkey_keycode_map) {
-			printk(IBM_ERR "failed to allocate memory for key map\n");
+			printk(TPACPI_ERR "failed to allocate memory for key map\n");
 			return -ENOMEM;
 		}
 
@@ -1957,7 +1957,7 @@ static void hotkey_exit(void)
 		/* no short-circuit boolean operator below! */
 		if ((hotkey_mask_set(hotkey_orig_mask) |
 		     hotkey_status_set(hotkey_orig_status)) != 0)
-			printk(IBM_ERR "failed to restore hot key mask to BIOS defaults\n");
+			printk(TPACPI_ERR "failed to restore hot key mask to BIOS defaults\n");
 	}
 
 	if (hotkey_dev_attributes) {
@@ -1974,7 +1974,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 	int ignore_acpi_ev;
 
 	if (event != 0x80) {
-		printk(IBM_ERR "unknown HKEY notification event %d\n", event);
+		printk(TPACPI_ERR "unknown HKEY notification event %d\n", event);
 		/* forward it to userspace, maybe it knows how to handle it */
 		acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
 						ibm->acpi->device->dev.bus_id,
@@ -1984,7 +1984,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 
 	while (1) {
 		if (!acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) {
-			printk(IBM_ERR "failed to retrieve HKEY event\n");
+			printk(TPACPI_ERR "failed to retrieve HKEY event\n");
 			return;
 		}
 
@@ -2008,7 +2008,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 					ignore_acpi_ev = 1;
 				}
 			} else {
-				printk(IBM_ERR
+				printk(TPACPI_ERR
 				       "hotkey 0x%04x out of range for keyboard map\n",
 				       hkey);
 				send_acpi_ev = 1;
@@ -2019,7 +2019,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 			/* we don't handle it through this path, just
 			 * eat up known LID events */
 			if (hkey != 0x5001 && hkey != 0x5002) {
-				printk(IBM_ERR
+				printk(TPACPI_ERR
 				       "unknown LID-related HKEY event: 0x%04x\n",
 				       hkey);
 				send_acpi_ev = 1;
@@ -2039,7 +2039,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 			/*	0x2305 - T43 waking up due to bay lever eject while aslept */
 			/* case 3: ultra-bay related. maybe bay in dock? */
 			/*	0x3003 - T43 after wake up by bay lever eject (0x2305) */
-			printk(IBM_NOTICE "unhandled HKEY event 0x%04x\n", hkey);
+			printk(TPACPI_NOTICE "unhandled HKEY event 0x%04x\n", hkey);
 			send_acpi_ev = 1;
 		}
 
@@ -2060,7 +2060,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 static void hotkey_resume(void)
 {
 	if (hotkey_mask_get())
-		printk(IBM_ERR "error while trying to read hot key mask from firmware\n");
+		printk(TPACPI_ERR "error while trying to read hot key mask from firmware\n");
 	tpacpi_input_send_radiosw();
 #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
 	hotkey_poll_setup_safe(0);
@@ -2145,7 +2145,7 @@ errexit:
 }
 
 static const struct acpi_device_id ibm_htk_device_ids[] = {
-	{IBM_HKEY_HID, 0},
+	{TPACPI_ACPI_HKEY_HID, 0},
 	{"", 0},
 };
 
@@ -2230,7 +2230,7 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
 
 	vdbg_printk(TPACPI_DBG_INIT, "initializing bluetooth subdriver\n");
 
-	IBM_ACPIHANDLE_INIT(hkey);
+	TPACPI_ACPIHANDLE_INIT(hkey);
 
 	/* bluetooth not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
 	   G4x, R30, R31, R40e, R50e, T20-22, X20-21 */
@@ -2404,7 +2404,7 @@ static int __init wan_init(struct ibm_init_struct *iibm)
 
 	vdbg_printk(TPACPI_DBG_INIT, "initializing wan subdriver\n");
 
-	IBM_ACPIHANDLE_INIT(hkey);
+	TPACPI_ACPIHANDLE_INIT(hkey);
 
 	tp_features.wan = hkey_handle &&
 	    acpi_evalf(hkey_handle, &status, "GWAN", "qd");
@@ -2543,14 +2543,14 @@ static int video_orig_autosw;
 static int video_autosw_get(void);
 static int video_autosw_set(int enable);
 
-IBM_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA",	/* 570 */
+TPACPI_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA",	/* 570 */
 	   "\\_SB.PCI0.AGP0.VID0",	/* 600e/x, 770x */
 	   "\\_SB.PCI0.VID0",	/* 770e */
 	   "\\_SB.PCI0.VID",	/* A21e, G4x, R50e, X30, X40 */
 	   "\\_SB.PCI0.AGP.VID",	/* all others */
 	   );				/* R30, R31 */
 
-IBM_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID");	/* G41 */
+TPACPI_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID");	/* G41 */
 
 static int __init video_init(struct ibm_init_struct *iibm)
 {
@@ -2558,8 +2558,8 @@ static int __init video_init(struct ibm_init_struct *iibm)
 
 	vdbg_printk(TPACPI_DBG_INIT, "initializing video subdriver\n");
 
-	IBM_ACPIHANDLE_INIT(vid);
-	IBM_ACPIHANDLE_INIT(vid2);
+	TPACPI_ACPIHANDLE_INIT(vid);
+	TPACPI_ACPIHANDLE_INIT(vid2);
 
 	if (vid2_handle && acpi_evalf(NULL, &ivga, "\\IVGA", "d") && ivga)
 		/* G41, assume IVGA doesn't change */
@@ -2590,7 +2590,7 @@ static void video_exit(void)
 	dbg_printk(TPACPI_DBG_EXIT,
 		   "restoring original video autoswitch mode\n");
 	if (video_autosw_set(video_orig_autosw))
-		printk(IBM_ERR "error while trying to restore original "
+		printk(TPACPI_ERR "error while trying to restore original "
 			"video autoswitch mode\n");
 }
 
@@ -2663,7 +2663,7 @@ static int video_outputsw_set(int status)
 		res = acpi_evalf(vid_handle, NULL,
 				 "ASWT", "vdd", status * 0x100, 0);
 		if (!autosw && video_autosw_set(autosw)) {
-			printk(IBM_ERR "video auto-switch left enabled due to error\n");
+			printk(TPACPI_ERR "video auto-switch left enabled due to error\n");
 			return -EIO;
 		}
 		break;
@@ -2732,7 +2732,7 @@ static int video_outputsw_cycle(void)
 		return -ENOSYS;
 	}
 	if (!autosw && video_autosw_set(autosw)) {
-		printk(IBM_ERR "video auto-switch left enabled due to error\n");
+		printk(TPACPI_ERR "video auto-switch left enabled due to error\n");
 		return -EIO;
 	}
 
@@ -2861,16 +2861,16 @@ static struct ibm_struct video_driver_data = {
  * Light (thinklight) subdriver
  */
 
-IBM_HANDLE(lght, root, "\\LGHT");	/* A21e, A2xm/p, T20-22, X20-21 */
-IBM_HANDLE(ledb, ec, "LEDB");		/* G4x */
+TPACPI_HANDLE(lght, root, "\\LGHT");	/* A21e, A2xm/p, T20-22, X20-21 */
+TPACPI_HANDLE(ledb, ec, "LEDB");		/* G4x */
 
 static int __init light_init(struct ibm_init_struct *iibm)
 {
 	vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n");
 
-	IBM_ACPIHANDLE_INIT(ledb);
-	IBM_ACPIHANDLE_INIT(lght);
-	IBM_ACPIHANDLE_INIT(cmos);
+	TPACPI_ACPIHANDLE_INIT(ledb);
+	TPACPI_ACPIHANDLE_INIT(lght);
+	TPACPI_ACPIHANDLE_INIT(cmos);
 
 	/* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */
 	tp_features.light = (cmos_handle || lght_handle) && !ledb_handle;
@@ -2952,14 +2952,14 @@ static void dock_notify(struct ibm_struct *ibm, u32 event);
 static int dock_read(char *p);
 static int dock_write(char *buf);
 
-IBM_HANDLE(dock, root, "\\_SB.GDCK",	/* X30, X31, X40 */
+TPACPI_HANDLE(dock, root, "\\_SB.GDCK",	/* X30, X31, X40 */
 	   "\\_SB.PCI0.DOCK",	/* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */
 	   "\\_SB.PCI0.PCI1.DOCK",	/* all others */
 	   "\\_SB.PCI.ISA.SLCE",	/* 570 */
     );				/* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
 
 /* don't list other alternatives as we install a notify handler on the 570 */
-IBM_HANDLE(pci, root, "\\_SB.PCI");	/* 570 */
+TPACPI_HANDLE(pci, root, "\\_SB.PCI");	/* 570 */
 
 static const struct acpi_device_id ibm_pci_device_ids[] = {
 	{PCI_ROOT_HID_STRING, 0},
@@ -3002,7 +3002,7 @@ static int __init dock_init(struct ibm_init_struct *iibm)
 {
 	vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver\n");
 
-	IBM_ACPIHANDLE_INIT(dock);
+	TPACPI_ACPIHANDLE_INIT(dock);
 
 	vdbg_printk(TPACPI_DBG_INIT, "dock is %s\n",
 		str_supported(dock_handle != NULL));
@@ -3018,7 +3018,7 @@ static int __init dock_init2(struct ibm_init_struct *iibm)
 
 	if (dock_driver_data[0].flags.acpi_driver_registered &&
 	    dock_driver_data[0].flags.acpi_notify_installed) {
-		IBM_ACPIHANDLE_INIT(pci);
+		TPACPI_ACPIHANDLE_INIT(pci);
 		dock2_needed = (pci_handle != NULL);
 		vdbg_printk(TPACPI_DBG_INIT,
 			    "dock PCI handler for the TP 570 is %s\n",
@@ -3050,7 +3050,7 @@ static void dock_notify(struct ibm_struct *ibm, u32 event)
 	else if (event == 0 && docked)
 		data = 3;	/* dock */
 	else {
-		printk(IBM_ERR "unknown dock event %d, status %d\n",
+		printk(TPACPI_ERR "unknown dock event %d, status %d\n",
 		       event, _sta(dock_handle));
 		data = 0;	/* unknown */
 	}
@@ -3107,18 +3107,18 @@ static int dock_write(char *buf)
 
 #ifdef CONFIG_THINKPAD_ACPI_BAY
 
-IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST",	/* 570 */
+TPACPI_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST",	/* 570 */
 	   "\\_SB.PCI0.IDE0.IDES.IDSM",	/* 600e/x, 770e, 770x */
 	   "\\_SB.PCI0.SATA.SCND.MSTR",	/* T60, X60, Z60 */
 	   "\\_SB.PCI0.IDE0.SCND.MSTR",	/* all others */
 	   );				/* A21e, R30, R31 */
-IBM_HANDLE(bay_ej, bay, "_EJ3",	/* 600e/x, A2xm/p, A3x */
+TPACPI_HANDLE(bay_ej, bay, "_EJ3",	/* 600e/x, A2xm/p, A3x */
 	   "_EJ0",		/* all others */
 	   );			/* 570,A21e,G4x,R30,R31,R32,R40e,R50e */
-IBM_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV",	/* A3x, R32 */
+TPACPI_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV",	/* A3x, R32 */
 	   "\\_SB.PCI0.IDE0.IDEP.IDPS",	/* 600e/x, 770e, 770x */
 	   );				/* all others */
-IBM_HANDLE(bay2_ej, bay2, "_EJ3",	/* 600e/x, 770e, A3x */
+TPACPI_HANDLE(bay2_ej, bay2, "_EJ3",	/* 600e/x, 770e, A3x */
 	   "_EJ0",			/* 770x */
 	   );				/* all others */
 
@@ -3126,12 +3126,12 @@ static int __init bay_init(struct ibm_init_struct *iibm)
 {
 	vdbg_printk(TPACPI_DBG_INIT, "initializing bay subdriver\n");
 
-	IBM_ACPIHANDLE_INIT(bay);
+	TPACPI_ACPIHANDLE_INIT(bay);
 	if (bay_handle)
-		IBM_ACPIHANDLE_INIT(bay_ej);
-	IBM_ACPIHANDLE_INIT(bay2);
+		TPACPI_ACPIHANDLE_INIT(bay_ej);
+	TPACPI_ACPIHANDLE_INIT(bay2);
 	if (bay2_handle)
-		IBM_ACPIHANDLE_INIT(bay2_ej);
+		TPACPI_ACPIHANDLE_INIT(bay2_ej);
 
 	tp_features.bay_status = bay_handle &&
 		acpi_evalf(bay_handle, NULL, "_STA", "qv");
@@ -3260,7 +3260,7 @@ static int __init cmos_init(struct ibm_init_struct *iibm)
 	vdbg_printk(TPACPI_DBG_INIT,
 		"initializing cmos commands subdriver\n");
 
-	IBM_ACPIHANDLE_INIT(cmos);
+	TPACPI_ACPIHANDLE_INIT(cmos);
 
 	vdbg_printk(TPACPI_DBG_INIT, "cmos commands are %s\n",
 		str_supported(cmos_handle != NULL));
@@ -3339,7 +3339,7 @@ enum {	/* For TPACPI_LED_OLD */
 
 static enum led_access_mode led_supported;
 
-IBM_HANDLE(led, ec, "SLED",	/* 570 */
+TPACPI_HANDLE(led, ec, "SLED",	/* 570 */
 	   "SYSL",		/* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
 	   "LED",		/* all others */
 	   );			/* R30, R31 */
@@ -3348,7 +3348,7 @@ static int __init led_init(struct ibm_init_struct *iibm)
 {
 	vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n");
 
-	IBM_ACPIHANDLE_INIT(led);
+	TPACPI_ACPIHANDLE_INIT(led);
 
 	if (!led_handle)
 		/* led not supported on R30, R31 */
@@ -3467,13 +3467,13 @@ static struct ibm_struct led_driver_data = {
  * Beep subdriver
  */
 
-IBM_HANDLE(beep, ec, "BEEP");	/* all except R30, R31 */
+TPACPI_HANDLE(beep, ec, "BEEP");	/* all except R30, R31 */
 
 static int __init beep_init(struct ibm_init_struct *iibm)
 {
 	vdbg_printk(TPACPI_DBG_INIT, "initializing beep subdriver\n");
 
-	IBM_ACPIHANDLE_INIT(beep);
+	TPACPI_ACPIHANDLE_INIT(beep);
 
 	vdbg_printk(TPACPI_DBG_INIT, "beep is %s\n",
 		str_supported(beep_handle != NULL));
@@ -3745,12 +3745,12 @@ static int __init thermal_init(struct ibm_init_struct *iibm)
 		if (ta1 == 0) {
 			/* This is sheer paranoia, but we handle it anyway */
 			if (acpi_tmp7) {
-				printk(IBM_ERR
+				printk(TPACPI_ERR
 				       "ThinkPad ACPI EC access misbehaving, "
 				       "falling back to ACPI TMPx access mode\n");
 				thermal_read_mode = TPACPI_THERMAL_ACPI_TMP07;
 			} else {
-				printk(IBM_ERR
+				printk(TPACPI_ERR
 				       "ThinkPad ACPI EC access misbehaving, "
 				       "disabling thermal sensors access\n");
 				thermal_read_mode = TPACPI_THERMAL_NONE;
@@ -3953,7 +3953,7 @@ static int brightness_get(struct backlight_device *bd)
 	}
 
 	if (brightness_mode == 3 && lec != lcmos) {
-		printk(IBM_ERR
+		printk(TPACPI_ERR
 			"CMOS NVRAM (%u) and EC (%u) do not agree "
 			"on display brightness level\n",
 			(unsigned int) lcmos,
@@ -4035,8 +4035,8 @@ static int __init tpacpi_query_bcll_levels(acpi_handle handle)
 	if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) {
 		obj = (union acpi_object *)buffer.pointer;
 		if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
-			printk(IBM_ERR "Unknown BCLL data, "
-			       "please report this to %s\n", IBM_MAIL);
+			printk(TPACPI_ERR "Unknown BCLL data, "
+			       "please report this to %s\n", TPACPI_MAIL);
 			rc = 0;
 		} else {
 			rc = obj->package.count;
@@ -4074,7 +4074,7 @@ static int __init brightness_check_levels(void)
 	void *found_node = NULL;
 
 	if (!vid_handle) {
-		IBM_ACPIHANDLE_INIT(vid);
+		TPACPI_ACPIHANDLE_INIT(vid);
 	}
 	if (!vid_handle)
 		return 0;
@@ -4107,7 +4107,7 @@ static int __init brightness_check_std_acpi_support(void)
 	void *found_node = NULL;
 
 	if (!vid_handle) {
-		IBM_ACPIHANDLE_INIT(vid);
+		TPACPI_ACPIHANDLE_INIT(vid);
 	}
 	if (!vid_handle)
 		return 0;
@@ -4133,7 +4133,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
 		return 1;
 	} else if (brightness_enable > 1) {
 		if (brightness_check_std_acpi_support()) {
-			printk(IBM_NOTICE
+			printk(TPACPI_NOTICE
 			       "standard ACPI backlight interface available, not loading native one...\n");
 			return 1;
 		}
@@ -4161,13 +4161,13 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
 		return 1;
 
 	if (tp_features.bright_16levels)
-		printk(IBM_INFO "detected a 16-level brightness capable ThinkPad\n");
+		printk(TPACPI_INFO "detected a 16-level brightness capable ThinkPad\n");
 
 	ibm_backlight_device = backlight_device_register(
 					TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL,
 					&ibm_backlight_data);
 	if (IS_ERR(ibm_backlight_device)) {
-		printk(IBM_ERR "Could not register backlight device\n");
+		printk(TPACPI_ERR "Could not register backlight device\n");
 		return PTR_ERR(ibm_backlight_device);
 	}
 	vdbg_printk(TPACPI_DBG_INIT, "brightness is supported\n");
@@ -4491,11 +4491,11 @@ static struct mutex fan_mutex;
 static void fan_watchdog_fire(struct work_struct *ignored);
 static DECLARE_DELAYED_WORK(fan_watchdog_task, fan_watchdog_fire);
 
-IBM_HANDLE(fans, ec, "FANS");	/* X31, X40, X41 */
-IBM_HANDLE(gfan, ec, "GFAN",	/* 570 */
+TPACPI_HANDLE(fans, ec, "FANS");	/* X31, X40, X41 */
+TPACPI_HANDLE(gfan, ec, "GFAN",	/* 570 */
 	   "\\FSPD",		/* 600e/x, 770e, 770x */
 	   );			/* all others */
-IBM_HANDLE(sfan, ec, "SFAN",	/* 570 */
+TPACPI_HANDLE(sfan, ec, "SFAN",	/* 570 */
 	   "JFNS",		/* 770x-JL */
 	   );			/* all others */
 
@@ -4790,7 +4790,7 @@ static void fan_watchdog_reset(void)
 		if (!schedule_delayed_work(&fan_watchdog_task,
 				msecs_to_jiffies(fan_watchdog_maxinterval
 						 * 1000))) {
-			printk(IBM_ERR "failed to schedule the fan watchdog, "
+			printk(TPACPI_ERR "failed to schedule the fan watchdog, "
 			       "watchdog will not trigger\n");
 		}
 	} else
@@ -4804,10 +4804,10 @@ static void fan_watchdog_fire(struct work_struct *ignored)
 	if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING)
 		return;
 
-	printk(IBM_NOTICE "fan watchdog: enabling fan\n");
+	printk(TPACPI_NOTICE "fan watchdog: enabling fan\n");
 	rc = fan_set_enable();
 	if (rc < 0) {
-		printk(IBM_ERR "fan watchdog: error %d while enabling fan, "
+		printk(TPACPI_ERR "fan watchdog: error %d while enabling fan, "
 			"will try again later...\n", -rc);
 		/* reschedule for later */
 		fan_watchdog_reset();
@@ -5047,9 +5047,9 @@ static int __init fan_init(struct ibm_init_struct *iibm)
 	tp_features.fan_ctrl_status_undef = 0;
 	fan_control_desired_level = 7;
 
-	IBM_ACPIHANDLE_INIT(fans);
-	IBM_ACPIHANDLE_INIT(gfan);
-	IBM_ACPIHANDLE_INIT(sfan);
+	TPACPI_ACPIHANDLE_INIT(fans);
+	TPACPI_ACPIHANDLE_INIT(gfan);
+	TPACPI_ACPIHANDLE_INIT(sfan);
 
 	if (gfan_handle) {
 		/* 570, 600e/x, 770e, 770x */
@@ -5075,7 +5075,7 @@ static int __init fan_init(struct ibm_init_struct *iibm)
 				case 0x3837: /* TP-78 */
 				case 0x3637: /* TP-76 */
 				case 0x3037: /* TP-70 */
-					printk(IBM_NOTICE
+					printk(TPACPI_NOTICE
 					       "fan_init: initial fan status is "
 					       "unknown, assuming it is in auto "
 					       "mode\n");
@@ -5084,7 +5084,7 @@ static int __init fan_init(struct ibm_init_struct *iibm)
 				}
 			}
 		} else {
-			printk(IBM_ERR
+			printk(TPACPI_ERR
 			       "ThinkPad ACPI EC access misbehaving, "
 			       "fan status and control unavailable\n");
 			return 1;
@@ -5255,7 +5255,7 @@ static int fan_write_cmd_level(const char *cmd, int *rc)
 		return 0;
 
 	if ((*rc = fan_set_level_safe(level)) == -ENXIO)
-		printk(IBM_ERR "level command accepted for unsupported "
+		printk(TPACPI_ERR "level command accepted for unsupported "
 		       "access mode %d", fan_control_access_mode);
 
 	return 1;
@@ -5267,7 +5267,7 @@ static int fan_write_cmd_enable(const char *cmd, int *rc)
 		return 0;
 
 	if ((*rc = fan_set_enable()) == -ENXIO)
-		printk(IBM_ERR "enable command accepted for unsupported "
+		printk(TPACPI_ERR "enable command accepted for unsupported "
 		       "access mode %d", fan_control_access_mode);
 
 	return 1;
@@ -5279,7 +5279,7 @@ static int fan_write_cmd_disable(const char *cmd, int *rc)
 		return 0;
 
 	if ((*rc = fan_set_disable()) == -ENXIO)
-		printk(IBM_ERR "disable command accepted for unsupported "
+		printk(TPACPI_ERR "disable command accepted for unsupported "
 		       "access mode %d", fan_control_access_mode);
 
 	return 1;
@@ -5296,7 +5296,7 @@ static int fan_write_cmd_speed(const char *cmd, int *rc)
 		return 0;
 
 	if ((*rc = fan_set_speed(speed)) == -ENXIO)
-		printk(IBM_ERR "speed command accepted for unsupported "
+		printk(TPACPI_ERR "speed command accepted for unsupported "
 		       "access mode %d", fan_control_access_mode);
 
 	return 1;
@@ -5360,7 +5360,7 @@ static ssize_t thinkpad_acpi_pdev_name_show(struct device *dev,
 			   struct device_attribute *attr,
 			   char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%s\n", IBM_NAME);
+	return snprintf(buf, PAGE_SIZE, "%s\n", TPACPI_NAME);
 }
 
 static struct device_attribute dev_attr_thinkpad_acpi_pdev_name =
@@ -5464,7 +5464,7 @@ static int __init ibm_init(struct ibm_init_struct *iibm)
 		if (ibm->acpi->notify) {
 			ret = setup_acpi_notify(ibm);
 			if (ret == -ENODEV) {
-				printk(IBM_NOTICE "disabling subdriver %s\n",
+				printk(TPACPI_NOTICE "disabling subdriver %s\n",
 					ibm->name);
 				ret = 0;
 				goto err_out;
@@ -5482,7 +5482,7 @@ static int __init ibm_init(struct ibm_init_struct *iibm)
 					  S_IFREG | S_IRUGO | S_IWUSR,
 					  proc_dir);
 		if (!entry) {
-			printk(IBM_ERR "unable to create proc entry %s\n",
+			printk(TPACPI_ERR "unable to create proc entry %s\n",
 			       ibm->name);
 			ret = -ENODEV;
 			goto err_out;
@@ -5577,10 +5577,10 @@ static int __init probe_for_thinkpad(void)
 	is_thinkpad = (thinkpad_id.model_str != NULL);
 
 	/* ec is required because many other handles are relative to it */
-	IBM_ACPIHANDLE_INIT(ec);
+	TPACPI_ACPIHANDLE_INIT(ec);
 	if (!ec_handle) {
 		if (is_thinkpad)
-			printk(IBM_ERR
+			printk(TPACPI_ERR
 				"Not yet supported ThinkPad detected!\n");
 		return -ENODEV;
 	}
@@ -5731,28 +5731,28 @@ MODULE_PARM_DESC(hotkey_report_mode,
                  "used for backwards compatibility with userspace, "
                  "see documentation");
 
-#define IBM_PARAM(feature) \
+#define TPACPI_PARAM(feature) \
 	module_param_call(feature, set_ibm_param, NULL, NULL, 0); \
 	MODULE_PARM_DESC(feature, "Simulates thinkpad-aci procfs command " \
 	                 "at module load, see documentation")
 
-IBM_PARAM(hotkey);
-IBM_PARAM(bluetooth);
-IBM_PARAM(video);
-IBM_PARAM(light);
+TPACPI_PARAM(hotkey);
+TPACPI_PARAM(bluetooth);
+TPACPI_PARAM(video);
+TPACPI_PARAM(light);
 #ifdef CONFIG_THINKPAD_ACPI_DOCK
-IBM_PARAM(dock);
+TPACPI_PARAM(dock);
 #endif
 #ifdef CONFIG_THINKPAD_ACPI_BAY
-IBM_PARAM(bay);
+TPACPI_PARAM(bay);
 #endif /* CONFIG_THINKPAD_ACPI_BAY */
-IBM_PARAM(cmos);
-IBM_PARAM(led);
-IBM_PARAM(beep);
-IBM_PARAM(ecdump);
-IBM_PARAM(brightness);
-IBM_PARAM(volume);
-IBM_PARAM(fan);
+TPACPI_PARAM(cmos);
+TPACPI_PARAM(led);
+TPACPI_PARAM(beep);
+TPACPI_PARAM(ecdump);
+TPACPI_PARAM(brightness);
+TPACPI_PARAM(volume);
+TPACPI_PARAM(fan);
 
 static void thinkpad_acpi_module_exit(void)
 {
@@ -5798,7 +5798,7 @@ static void thinkpad_acpi_module_exit(void)
 		platform_driver_unregister(&tpacpi_pdriver);
 
 	if (proc_dir)
-		remove_proc_entry(IBM_PROC_DIR, acpi_root_dir);
+		remove_proc_entry(TPACPI_PROC_DIR, acpi_root_dir);
 
 	kfree(thinkpad_id.bios_version_str);
 	kfree(thinkpad_id.ec_version_str);
@@ -5827,12 +5827,12 @@ static int __init thinkpad_acpi_module_init(void)
 
 	/* Driver initialization */
 
-	IBM_ACPIHANDLE_INIT(ecrd);
-	IBM_ACPIHANDLE_INIT(ecwr);
+	TPACPI_ACPIHANDLE_INIT(ecrd);
+	TPACPI_ACPIHANDLE_INIT(ecwr);
 
-	proc_dir = proc_mkdir(IBM_PROC_DIR, acpi_root_dir);
+	proc_dir = proc_mkdir(TPACPI_PROC_DIR, acpi_root_dir);
 	if (!proc_dir) {
-		printk(IBM_ERR "unable to create proc dir " IBM_PROC_DIR);
+		printk(TPACPI_ERR "unable to create proc dir " TPACPI_PROC_DIR);
 		thinkpad_acpi_module_exit();
 		return -ENODEV;
 	}
@@ -5840,7 +5840,7 @@ static int __init thinkpad_acpi_module_init(void)
 
 	ret = platform_driver_register(&tpacpi_pdriver);
 	if (ret) {
-		printk(IBM_ERR "unable to register main platform driver\n");
+		printk(TPACPI_ERR "unable to register main platform driver\n");
 		thinkpad_acpi_module_exit();
 		return ret;
 	}
@@ -5848,7 +5848,7 @@ static int __init thinkpad_acpi_module_init(void)
 
 	ret = platform_driver_register(&tpacpi_hwmon_pdriver);
 	if (ret) {
-		printk(IBM_ERR "unable to register hwmon platform driver\n");
+		printk(TPACPI_ERR "unable to register hwmon platform driver\n");
 		thinkpad_acpi_module_exit();
 		return ret;
 	}
@@ -5860,7 +5860,7 @@ static int __init thinkpad_acpi_module_init(void)
 		ret = tpacpi_create_driver_attributes(&tpacpi_hwmon_pdriver.driver);
 	}
 	if (ret) {
-		printk(IBM_ERR "unable to create sysfs driver attributes\n");
+		printk(TPACPI_ERR "unable to create sysfs driver attributes\n");
 		thinkpad_acpi_module_exit();
 		return ret;
 	}
@@ -5868,29 +5868,29 @@ static int __init thinkpad_acpi_module_init(void)
 
 
 	/* Device initialization */
-	tpacpi_pdev = platform_device_register_simple(IBM_DRVR_NAME, -1,
+	tpacpi_pdev = platform_device_register_simple(TPACPI_DRVR_NAME, -1,
 							NULL, 0);
 	if (IS_ERR(tpacpi_pdev)) {
 		ret = PTR_ERR(tpacpi_pdev);
 		tpacpi_pdev = NULL;
-		printk(IBM_ERR "unable to register platform device\n");
+		printk(TPACPI_ERR "unable to register platform device\n");
 		thinkpad_acpi_module_exit();
 		return ret;
 	}
 	tpacpi_sensors_pdev = platform_device_register_simple(
-							IBM_HWMON_DRVR_NAME,
+							TPACPI_HWMON_DRVR_NAME,
 							-1, NULL, 0);
 	if (IS_ERR(tpacpi_sensors_pdev)) {
 		ret = PTR_ERR(tpacpi_sensors_pdev);
 		tpacpi_sensors_pdev = NULL;
-		printk(IBM_ERR "unable to register hwmon platform device\n");
+		printk(TPACPI_ERR "unable to register hwmon platform device\n");
 		thinkpad_acpi_module_exit();
 		return ret;
 	}
 	ret = device_create_file(&tpacpi_sensors_pdev->dev,
 				 &dev_attr_thinkpad_acpi_pdev_name);
 	if (ret) {
-		printk(IBM_ERR
+		printk(TPACPI_ERR
 			"unable to create sysfs hwmon device attributes\n");
 		thinkpad_acpi_module_exit();
 		return ret;
@@ -5900,20 +5900,20 @@ static int __init thinkpad_acpi_module_init(void)
 	if (IS_ERR(tpacpi_hwmon)) {
 		ret = PTR_ERR(tpacpi_hwmon);
 		tpacpi_hwmon = NULL;
-		printk(IBM_ERR "unable to register hwmon device\n");
+		printk(TPACPI_ERR "unable to register hwmon device\n");
 		thinkpad_acpi_module_exit();
 		return ret;
 	}
 	mutex_init(&tpacpi_inputdev_send_mutex);
 	tpacpi_inputdev = input_allocate_device();
 	if (!tpacpi_inputdev) {
-		printk(IBM_ERR "unable to allocate input device\n");
+		printk(TPACPI_ERR "unable to allocate input device\n");
 		thinkpad_acpi_module_exit();
 		return -ENOMEM;
 	} else {
 		/* Prepare input device, but don't register */
 		tpacpi_inputdev->name = "ThinkPad Extra Buttons";
-		tpacpi_inputdev->phys = IBM_DRVR_NAME "/input0";
+		tpacpi_inputdev->phys = TPACPI_DRVR_NAME "/input0";
 		tpacpi_inputdev->id.bustype = BUS_HOST;
 		tpacpi_inputdev->id.vendor = (thinkpad_id.vendor) ?
 						thinkpad_id.vendor :
@@ -5932,7 +5932,7 @@ static int __init thinkpad_acpi_module_init(void)
 	}
 	ret = input_register_device(tpacpi_inputdev);
 	if (ret < 0) {
-		printk(IBM_ERR "unable to register input device\n");
+		printk(TPACPI_ERR "unable to register input device\n");
 		thinkpad_acpi_module_exit();
 		return ret;
 	} else {
@@ -5970,8 +5970,8 @@ IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]");
 IBM_BIOS_MODULE_ALIAS("K[U,X-Z]");
 
 MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
-MODULE_DESCRIPTION(IBM_DESC);
-MODULE_VERSION(IBM_VERSION);
+MODULE_DESCRIPTION(TPACPI_DESC);
+MODULE_VERSION(TPACPI_VERSION);
 MODULE_LICENSE("GPL");
 
 module_init(thinkpad_acpi_module_init);
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#63 lore raw

PATCH 56/112 ACPI: register ACPI Fan as generic thermal cooling device

In reply to Len Brown

From: Zhang Rui <[email protected]>

Register ACPI Fan as thermal cooling device.

---
 drivers/acpi/fan.c |   90 +++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 83 insertions(+), 7 deletions(-)
drivers/acpi/fan.c +83 -7
index a6e149d..f6e8165 100644
@@ -30,7 +30,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <asm/uaccess.h>
-
+#include <linux/thermal.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
@@ -68,9 +68,55 @@ static struct acpi_driver acpi_fan_driver = {
 		},
 };
 
+/* thermal cooling device callbacks */
+static int fan_get_max_state(struct thermal_cooling_device *cdev, char *buf)
+{
+	/* ACPI fan device only support two states: ON/OFF */
+	return sprintf(buf, "1\n");
+}
+
+static int fan_get_cur_state(struct thermal_cooling_device *cdev, char *buf)
+{
+	struct acpi_device *device = cdev->devdata;
+	int state;
+	int result;
+
+	if (!device)
+		return -EINVAL;
+
+	result = acpi_bus_get_power(device->handle, &state);
+	if (result)
+		return result;
+
+	return sprintf(buf, "%s\n", state == ACPI_STATE_D3 ? "0" :
+			 (state == ACPI_STATE_D0 ? "1" : "unknown"));
+}
+
+static int
+fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state)
+{
+	struct acpi_device *device = cdev->devdata;
+	int result;
+
+	if (!device || (state != 0 && state != 1))
+		return -EINVAL;
+
+	result = acpi_bus_set_power(device->handle,
+				state ? ACPI_STATE_D0 : ACPI_STATE_D3);
+
+	return result;
+}
+
+static struct thermal_cooling_device_ops fan_cooling_ops = {
+	.get_max_state = fan_get_max_state,
+	.get_cur_state = fan_get_cur_state,
+	.set_cur_state = fan_set_cur_state,
+};
+
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
    -------------------------------------------------------------------------- */
+#ifdef CONFIG_ACPI_PROCFS
 
 static struct proc_dir_entry *acpi_fan_dir;
 
@@ -171,7 +217,17 @@ static int acpi_fan_remove_fs(struct acpi_device *device)
 
 	return 0;
 }
+#else
+static int acpi_fan_add_fs(struct acpi_device *device)
+{
+	return 0;
+}
 
+static int acpi_fan_remove_fs(struct acpi_device *device)
+{
+	return 0;
+}
+#endif
 /* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
@@ -179,9 +235,8 @@ static int acpi_fan_remove_fs(struct acpi_device *device)
 static int acpi_fan_add(struct acpi_device *device)
 {
 	int result = 0;
-	struct acpi_fan *fan = NULL;
 	int state = 0;
-
+	struct thermal_cooling_device *cdev;
 
 	if (!device)
 		return -EINVAL;
@@ -199,6 +254,25 @@ static int acpi_fan_add(struct acpi_device *device)
 	acpi_bus_set_power(device->handle, state);
 	device->flags.force_power_state = 0;
 
+	cdev = thermal_cooling_device_register("Fan", device,
+						&fan_cooling_ops);
+	if (cdev)
+		printk(KERN_INFO PREFIX
+			"%s is registered as cooling_device%d\n",
+			device->dev.bus_id, cdev->id);
+	else
+		goto end;
+	acpi_driver_data(device) = cdev;
+	result = sysfs_create_link(&device->dev.kobj, &cdev->device.kobj,
+					"thermal_cooling");
+	if (result)
+		return result;
+
+	result = sysfs_create_link(&cdev->device.kobj, &device->dev.kobj,
+                                       "device");
+        if (result)
+                return result;
+
 	result = acpi_fan_add_fs(device);
 	if (result)
 		goto end;
@@ -208,18 +282,20 @@ static int acpi_fan_add(struct acpi_device *device)
 	       !device->power.state ? "on" : "off");
 
       end:
-	if (result)
-		kfree(fan);
-
 	return result;
 }
 
 static int acpi_fan_remove(struct acpi_device *device, int type)
 {
-	if (!device || !acpi_driver_data(device))
+	struct thermal_cooling_device *cdev = acpi_driver_data(device);
+
+	if (!device || !cdev)
 		return -EINVAL;
 
 	acpi_fan_remove_fs(device);
+	sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
+	sysfs_remove_link(&cdev->device.kobj, "device");
+	thermal_cooling_device_unregister(cdev);
 
 	return 0;
 }
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#43 lore raw

PATCH 43/112 ACPI: thinkpad-acpi: some checkpatch.pl fluff

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

Fix some of the crap reported by checkpatch.pl.

---
 drivers/misc/thinkpad_acpi.c |  291 +++++++++++++++++++++++++-----------------
 1 files changed, 175 insertions(+), 116 deletions(-)
drivers/misc/thinkpad_acpi.c +175 -116
index c92ae8d..dd6fa81 100644
@@ -150,7 +150,8 @@ enum {
 #define TPACPI_DBG_EXIT		0x0002
 #define dbg_printk(a_dbg_level, format, arg...) \
 	do { if (dbg_level & a_dbg_level) \
-		printk(TPACPI_DEBUG "%s: " format, __func__ , ## arg); } while (0)
+		printk(TPACPI_DEBUG "%s: " format, __func__ , ## arg); \
+	} while (0)
 #ifdef CONFIG_THINKPAD_ACPI_DEBUG
 #define vdbg_printk(a_dbg_level, format, arg...) \
 	dbg_printk(a_dbg_level, format, ## arg)
@@ -159,9 +160,9 @@ static const char *str_supported(int is_supported);
 #define vdbg_printk(a_dbg_level, format, arg...)
 #endif
 
-#define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off")
-#define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
-#define strlencmp(a,b) (strncmp((a), (b), strlen(b)))
+#define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off")
+#define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
+#define strlencmp(a, b) (strncmp((a), (b), strlen(b)))
 
 
 /****************************************************************************
@@ -288,7 +289,8 @@ TPACPI_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0",	/* 240, 240x */
 TPACPI_HANDLE(ecrd, ec, "ECRD");	/* 570 */
 TPACPI_HANDLE(ecwr, ec, "ECWR");	/* 570 */
 
-TPACPI_HANDLE(cmos, root, "\\UCMS",	/* R50, R50e, R50p, R51, T4x, X31, X40 */
+TPACPI_HANDLE(cmos, root, "\\UCMS",	/* R50, R50e, R50p, R51, */
+					/* T4x, X31, X40 */
 	   "\\CMOS",		/* A3x, G4x, R32, T23, T30, X22-24, X30 */
 	   "\\CMS",		/* R40, R40e */
 	   );			/* all others */
@@ -382,7 +384,7 @@ static int acpi_evalf(acpi_handle handle,
 	return success;
 }
 
-static int acpi_ec_read(int i, u8 * p)
+static int acpi_ec_read(int i, u8 *p)
 {
 	int v;
 
@@ -436,8 +438,8 @@ static int issue_thinkpad_cmos_command(int cmos_cmd)
  * ACPI device model
  */
 
-#define TPACPI_ACPIHANDLE_INIT(object)						\
-	drv_acpi_handle_init(#object, &object##_handle, *object##_parent,	\
+#define TPACPI_ACPIHANDLE_INIT(object) \
+	drv_acpi_handle_init(#object, &object##_handle, *object##_parent, \
 		object##_paths, ARRAY_SIZE(object##_paths), &object##_path)
 
 static void drv_acpi_handle_init(char *name,
@@ -508,11 +510,13 @@ static int __init setup_acpi_notify(struct ibm_struct *ibm)
 			ibm->acpi->type, dispatch_acpi_notify, ibm);
 	if (ACPI_FAILURE(status)) {
 		if (status == AE_ALREADY_EXISTS) {
-			printk(TPACPI_NOTICE "another device driver is already handling %s events\n",
-				ibm->name);
+			printk(TPACPI_NOTICE
+			       "another device driver is already "
+			       "handling %s events\n", ibm->name);
 		} else {
-			printk(TPACPI_ERR "acpi_install_notify_handler(%s) failed: %d\n",
-				ibm->name, status);
+			printk(TPACPI_ERR
+			       "acpi_install_notify_handler(%s) failed: %d\n",
+			       ibm->name, status);
 		}
 		return -ENODEV;
 	}
@@ -592,7 +596,7 @@ static int dispatch_procfs_read(char *page, char **start, off_t off,
 }
 
 static int dispatch_procfs_write(struct file *file,
-			const char __user * userbuf,
+			const char __user *userbuf,
 			unsigned long count, void *data)
 {
 	struct ibm_struct *ibm = data;
@@ -698,7 +702,7 @@ struct attribute_set_obj {
 } __attribute__((packed));
 
 static struct attribute_set *create_attr_set(unsigned int max_members,
-						const char* name)
+						const char *name)
 {
 	struct attribute_set_obj *sobj;
 
@@ -722,7 +726,7 @@ static struct attribute_set *create_attr_set(unsigned int max_members,
 	kfree(_set);
 
 /* not multi-threaded safe, use it in a single thread per set */
-static int add_to_attr_set(struct attribute_set* s, struct attribute *attr)
+static int add_to_attr_set(struct attribute_set *s, struct attribute *attr)
 {
 	if (!s || !attr)
 		return -EINVAL;
@@ -736,7 +740,7 @@ static int add_to_attr_set(struct attribute_set* s, struct attribute *attr)
 	return 0;
 }
 
-static int add_many_to_attr_set(struct attribute_set* s,
+static int add_many_to_attr_set(struct attribute_set *s,
 			struct attribute **attr,
 			unsigned int count)
 {
@@ -751,7 +755,7 @@ static int add_many_to_attr_set(struct attribute_set* s,
 	return 0;
 }
 
-static void delete_attr_set(struct attribute_set* s, struct kobject *kobj)
+static void delete_attr_set(struct attribute_set *s, struct kobject *kobj)
 {
 	sysfs_remove_group(kobj, &s->group);
 	destroy_attr_set(s);
@@ -818,7 +822,8 @@ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
 static ssize_t tpacpi_driver_version_show(struct device_driver *drv,
 						char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%s v%s\n", TPACPI_DESC, TPACPI_VERSION);
+	return snprintf(buf, PAGE_SIZE, "%s v%s\n",
+			TPACPI_DESC, TPACPI_VERSION);
 }
 
 static DRIVER_ATTR(version, S_IRUGO,
@@ -826,7 +831,7 @@ static DRIVER_ATTR(version, S_IRUGO,
 
 /* --------------------------------------------------------------------- */
 
-static struct driver_attribute* tpacpi_driver_attributes[] = {
+static struct driver_attribute *tpacpi_driver_attributes[] = {
 	&driver_attr_debug_level, &driver_attr_version,
 	&driver_attr_interface_version,
 };
@@ -849,7 +854,7 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv)
 {
 	int i;
 
-	for(i = 0; i < ARRAY_SIZE(tpacpi_driver_attributes); i++)
+	for (i = 0; i < ARRAY_SIZE(tpacpi_driver_attributes); i++)
 		driver_remove_file(drv, tpacpi_driver_attributes[i]);
 }
 
@@ -1010,8 +1015,10 @@ static struct attribute_set *hotkey_dev_attributes;
 
 #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
 #define HOTKEY_CONFIG_CRITICAL_START \
-	mutex_lock(&hotkey_thread_data_mutex); \
-	hotkey_config_change++;
+	do { \
+		mutex_lock(&hotkey_thread_data_mutex); \
+		hotkey_config_change++; \
+	} while (0);
 #define HOTKEY_CONFIG_CRITICAL_END \
 	mutex_unlock(&hotkey_thread_data_mutex);
 #else
@@ -1205,15 +1212,18 @@ static void hotkey_read_nvram(struct tp_nvram_state *n, u32 m)
 }
 
 #define TPACPI_COMPARE_KEY(__scancode, __member) \
-	do { if ((mask & (1 << __scancode)) && oldn->__member != newn->__member) \
-		tpacpi_hotkey_send_key(__scancode); } while (0)
+	do { \
+		if ((mask & (1 << __scancode)) && \
+		    oldn->__member != newn->__member) \
+		tpacpi_hotkey_send_key(__scancode); \
+	} while (0)
 
 #define TPACPI_MAY_SEND_KEY(__scancode) \
 	do { if (mask & (1 << __scancode)) \
 		tpacpi_hotkey_send_key(__scancode); } while (0)
 
 static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn,
-                                           struct tp_nvram_state *newn,
+					   struct tp_nvram_state *newn,
 					   u32 mask)
 {
 	TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_THINKPAD, thinkpad_toggle);
@@ -1316,7 +1326,7 @@ static int hotkey_kthread(void *data)
 			hotkey_read_nvram(&s[si], mask);
 			if (likely(si != so)) {
 				hotkey_compare_and_issue_event(&s[so], &s[si],
-				                               mask);
+								mask);
 			}
 		}
 
@@ -1352,10 +1362,12 @@ static void hotkey_poll_setup(int may_warn)
 	    (tpacpi_inputdev->users > 0 || hotkey_report_mode < 2)) {
 		if (!tpacpi_hotkey_task) {
 			tpacpi_hotkey_task = kthread_run(hotkey_kthread,
-			                       NULL, TPACPI_FILE "d");
+							 NULL,
+							 TPACPI_FILE "d");
 			if (IS_ERR(tpacpi_hotkey_task)) {
 				tpacpi_hotkey_task = NULL;
-				printk(TPACPI_ERR "could not create kernel thread "
+				printk(TPACPI_ERR
+				       "could not create kernel thread "
 				       "for hotkey polling\n");
 			}
 		}
@@ -1363,7 +1375,8 @@ static void hotkey_poll_setup(int may_warn)
 		hotkey_poll_stop_sync();
 		if (may_warn &&
 		    hotkey_source_mask != 0 && hotkey_poll_freq == 0) {
-			printk(TPACPI_NOTICE "hot keys 0x%08x require polling, "
+			printk(TPACPI_NOTICE
+				"hot keys 0x%08x require polling, "
 				"which is currently disabled\n",
 				hotkey_source_mask);
 		}
@@ -1829,7 +1842,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 				       "missing MHKA handler, "
 				       "please report this to %s\n",
 				       TPACPI_MAIL);
-				hotkey_all_mask = 0x080cU; /* FN+F12, FN+F4, FN+F3 */
+				/* FN+F12, FN+F4, FN+F3 */
+				hotkey_all_mask = 0x080cU;
 			}
 		}
 
@@ -1882,7 +1896,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 		hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
 						GFP_KERNEL);
 		if (!hotkey_keycode_map) {
-			printk(TPACPI_ERR "failed to allocate memory for key map\n");
+			printk(TPACPI_ERR
+				"failed to allocate memory for key map\n");
 			return -ENOMEM;
 		}
 
@@ -1953,11 +1968,14 @@ static void hotkey_exit(void)
 #endif
 
 	if (tp_features.hotkey) {
-		dbg_printk(TPACPI_DBG_EXIT, "restoring original hot key mask\n");
+		dbg_printk(TPACPI_DBG_EXIT,
+			   "restoring original hot key mask\n");
 		/* no short-circuit boolean operator below! */
 		if ((hotkey_mask_set(hotkey_orig_mask) |
 		     hotkey_status_set(hotkey_orig_status)) != 0)
-			printk(TPACPI_ERR "failed to restore hot key mask to BIOS defaults\n");
+			printk(TPACPI_ERR
+			       "failed to restore hot key mask "
+			       "to BIOS defaults\n");
 	}
 
 	if (hotkey_dev_attributes) {
@@ -1974,11 +1992,13 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 	int ignore_acpi_ev;
 
 	if (event != 0x80) {
-		printk(TPACPI_ERR "unknown HKEY notification event %d\n", event);
+		printk(TPACPI_ERR
+		       "unknown HKEY notification event %d\n", event);
 		/* forward it to userspace, maybe it knows how to handle it */
-		acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
-						ibm->acpi->device->dev.bus_id,
-						event, 0);
+		acpi_bus_generate_netlink_event(
+					ibm->acpi->device->pnp.device_class,
+					ibm->acpi->device->dev.bus_id,
+					event, 0);
 		return;
 	}
 
@@ -2009,8 +2029,8 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 				}
 			} else {
 				printk(TPACPI_ERR
-				       "hotkey 0x%04x out of range for keyboard map\n",
-				       hkey);
+				       "hotkey 0x%04x out of range "
+				       "for keyboard map\n", hkey);
 				send_acpi_ev = 1;
 			}
 			break;
@@ -2020,8 +2040,8 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 			 * eat up known LID events */
 			if (hkey != 0x5001 && hkey != 0x5002) {
 				printk(TPACPI_ERR
-				       "unknown LID-related HKEY event: 0x%04x\n",
-				       hkey);
+				       "unknown LID-related HKEY event: "
+				       "0x%04x\n", hkey);
 				send_acpi_ev = 1;
 			} else {
 				ignore_acpi_ev = 1;
@@ -2036,23 +2056,29 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 			/* fallthrough to default */
 		default:
 			/* case 2: dock-related */
-			/*	0x2305 - T43 waking up due to bay lever eject while aslept */
+			/*	0x2305 - T43 waking up due to bay lever
+			 *	         eject while aslept */
 			/* case 3: ultra-bay related. maybe bay in dock? */
-			/*	0x3003 - T43 after wake up by bay lever eject (0x2305) */
-			printk(TPACPI_NOTICE "unhandled HKEY event 0x%04x\n", hkey);
+			/*	0x3003 - T43 after wake up by bay lever
+			 *	         eject (0x2305) */
+			printk(TPACPI_NOTICE
+			       "unhandled HKEY event 0x%04x\n", hkey);
 			send_acpi_ev = 1;
 		}
 
 		/* Legacy events */
-		if (!ignore_acpi_ev && (send_acpi_ev || hotkey_report_mode < 2)) {
-			acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey);
+		if (!ignore_acpi_ev &&
+		    (send_acpi_ev || hotkey_report_mode < 2)) {
+			acpi_bus_generate_proc_event(ibm->acpi->device,
+						     event, hkey);
 		}
 
 		/* netlink events */
 		if (!ignore_acpi_ev && send_acpi_ev) {
-			acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
-							ibm->acpi->device->dev.bus_id,
-							event, hkey);
+			acpi_bus_generate_netlink_event(
+					ibm->acpi->device->pnp.device_class,
+					ibm->acpi->device->dev.bus_id,
+					event, hkey);
 		}
 	}
 }
@@ -2060,7 +2086,9 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 static void hotkey_resume(void)
 {
 	if (hotkey_mask_get())
-		printk(TPACPI_ERR "error while trying to read hot key mask from firmware\n");
+		printk(TPACPI_ERR
+		       "error while trying to read hot key mask "
+		       "from firmware\n");
 	tpacpi_input_send_radiosw();
 #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
 	hotkey_poll_setup_safe(0);
@@ -2663,13 +2691,14 @@ static int video_outputsw_set(int status)
 		res = acpi_evalf(vid_handle, NULL,
 				 "ASWT", "vdd", status * 0x100, 0);
 		if (!autosw && video_autosw_set(autosw)) {
-			printk(TPACPI_ERR "video auto-switch left enabled due to error\n");
+			printk(TPACPI_ERR
+			       "video auto-switch left enabled due to error\n");
 			return -EIO;
 		}
 		break;
 	case TPACPI_VIDEO_NEW:
 		res = acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80) &&
-			acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1);
+		      acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1);
 		break;
 	default:
 		return -ENOSYS;
@@ -2732,7 +2761,8 @@ static int video_outputsw_cycle(void)
 		return -ENOSYS;
 	}
 	if (!autosw && video_autosw_set(autosw)) {
-		printk(TPACPI_ERR "video auto-switch left enabled due to error\n");
+		printk(TPACPI_ERR
+		       "video auto-switch left enabled due to error\n");
 		return -EIO;
 	}
 
@@ -3340,7 +3370,8 @@ enum {	/* For TPACPI_LED_OLD */
 static enum led_access_mode led_supported;
 
 TPACPI_HANDLE(led, ec, "SLED",	/* 570 */
-	   "SYSL",		/* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
+	   "SYSL",		/* 600e/x, 770e, 770x, A21e, A2xm/p, */
+				/* T20-22, X20-21 */
 	   "LED",		/* all others */
 	   );			/* R30, R31 */
 
@@ -3437,13 +3468,11 @@ static int led_write(char *buf)
 			led = 1 << led;
 			ret = ec_write(TPACPI_LED_EC_HLMS, led);
 			if (ret >= 0)
-				ret =
-				    ec_write(TPACPI_LED_EC_HLBL,
-				    	     led * led_exp_hlbl[ind]);
+				ret = ec_write(TPACPI_LED_EC_HLBL,
+						led * led_exp_hlbl[ind]);
 			if (ret >= 0)
-				ret =
-				    ec_write(TPACPI_LED_EC_HLCL,
-				    	     led * led_exp_hlcl[ind]);
+				ret = ec_write(TPACPI_LED_EC_HLCL,
+						led * led_exp_hlcl[ind]);
 			if (ret < 0)
 				return ret;
 		} else {
@@ -3620,7 +3649,7 @@ static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s)
 	if (thermal_read_mode == TPACPI_THERMAL_TPEC_16)
 		n = 16;
 
-	for(i = 0 ; i < n; i++) {
+	for (i = 0 ; i < n; i++) {
 		res = thermal_get_sensor(i, &s->temp[i]);
 		if (res)
 			return res;
@@ -3651,7 +3680,8 @@ static ssize_t thermal_temp_input_show(struct device *dev,
 }
 
 #define THERMAL_SENSOR_ATTR_TEMP(_idxA, _idxB) \
-	 SENSOR_ATTR(temp##_idxA##_input, S_IRUGO, thermal_temp_input_show, NULL, _idxB)
+	 SENSOR_ATTR(temp##_idxA##_input, S_IRUGO, \
+		     thermal_temp_input_show, NULL, _idxB)
 
 static struct sensor_device_attribute sensor_dev_attr_thermal_temp_input[] = {
 	THERMAL_SENSOR_ATTR_TEMP(1, 0),
@@ -3747,7 +3777,8 @@ static int __init thermal_init(struct ibm_init_struct *iibm)
 			if (acpi_tmp7) {
 				printk(TPACPI_ERR
 				       "ThinkPad ACPI EC access misbehaving, "
-				       "falling back to ACPI TMPx access mode\n");
+				       "falling back to ACPI TMPx access "
+				       "mode\n");
 				thermal_read_mode = TPACPI_THERMAL_ACPI_TMP07;
 			} else {
 				printk(TPACPI_ERR
@@ -3777,7 +3808,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm)
 		str_supported(thermal_read_mode != TPACPI_THERMAL_NONE),
 		thermal_read_mode);
 
-	switch(thermal_read_mode) {
+	switch (thermal_read_mode) {
 	case TPACPI_THERMAL_TPEC_16:
 		res = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
 				&thermal_temp_input16_group);
@@ -3802,7 +3833,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm)
 
 static void thermal_exit(void)
 {
-	switch(thermal_read_mode) {
+	switch (thermal_read_mode) {
 	case TPACPI_THERMAL_TPEC_16:
 		sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj,
 				   &thermal_temp_input16_group);
@@ -4020,8 +4051,8 @@ static int brightness_update_status(struct backlight_device *bd)
 }
 
 static struct backlight_ops ibm_backlight_data = {
-        .get_brightness = brightness_get,
-        .update_status  = brightness_update_status,
+	.get_brightness = brightness_get,
+	.update_status  = brightness_update_status,
 };
 
 /* --------------------------------------------------------------------- */
@@ -4081,7 +4112,8 @@ static int __init brightness_check_levels(void)
 
 	/* Search for a BCLL package with 16 levels */
 	status = acpi_walk_namespace(ACPI_TYPE_PACKAGE, vid_handle, 3,
-					brightness_find_bcll, NULL, &found_node);
+					brightness_find_bcll, NULL,
+					&found_node);
 
 	return (ACPI_SUCCESS(status) && found_node != NULL);
 }
@@ -4114,7 +4146,7 @@ static int __init brightness_check_std_acpi_support(void)
 
 	/* Search for a _BCL method, but don't execute it */
 	status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3,
-	                             brightness_find_bcl, NULL, &found_node);
+				     brightness_find_bcl, NULL, &found_node);
 
 	return (ACPI_SUCCESS(status) && found_node != NULL);
 }
@@ -4129,12 +4161,14 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
 
 	if (!brightness_enable) {
 		dbg_printk(TPACPI_DBG_INIT,
-		           "brightness support disabled by module parameter\n");
+			   "brightness support disabled by "
+			   "module parameter\n");
 		return 1;
 	} else if (brightness_enable > 1) {
 		if (brightness_check_std_acpi_support()) {
 			printk(TPACPI_NOTICE
-			       "standard ACPI backlight interface available, not loading native one...\n");
+			       "standard ACPI backlight interface "
+			       "available, not loading native one...\n");
 			return 1;
 		}
 	}
@@ -4161,7 +4195,8 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
 		return 1;
 
 	if (tp_features.bright_16levels)
-		printk(TPACPI_INFO "detected a 16-level brightness capable ThinkPad\n");
+		printk(TPACPI_INFO
+		       "detected a 16-level brightness capable ThinkPad\n");
 
 	ibm_backlight_device = backlight_device_register(
 					TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL,
@@ -4195,7 +4230,8 @@ static int brightness_read(char *p)
 	int len = 0;
 	int level;
 
-	if ((level = brightness_get(NULL)) < 0) {
+	level = brightness_get(NULL);
+	if (level < 0) {
 		len += sprintf(p + len, "level:\t\tunreadable\n");
 	} else {
 		len += sprintf(p + len, "level:\t\t%d\n", level);
@@ -4303,8 +4339,11 @@ static int volume_write(char *buf)
 		} else
 			return -EINVAL;
 
-		if (new_level != level) {	/* mute doesn't change */
-			cmos_cmd = new_level > level ? TP_CMOS_VOLUME_UP : TP_CMOS_VOLUME_DOWN;
+		if (new_level != level) {
+			/* mute doesn't change */
+
+			cmos_cmd = (new_level > level) ?
+					TP_CMOS_VOLUME_UP : TP_CMOS_VOLUME_DOWN;
 			inc = new_level > level ? 1 : -1;
 
 			if (mute && (issue_thinkpad_cmos_command(cmos_cmd) ||
@@ -4316,14 +4355,18 @@ static int volume_write(char *buf)
 				    !acpi_ec_write(volume_offset, i + inc))
 					return -EIO;
 
-			if (mute && (issue_thinkpad_cmos_command(TP_CMOS_VOLUME_MUTE) ||
-				     !acpi_ec_write(volume_offset,
-						    new_level + mute)))
+			if (mute &&
+			    (issue_thinkpad_cmos_command(TP_CMOS_VOLUME_MUTE) ||
+			     !acpi_ec_write(volume_offset, new_level + mute))) {
 				return -EIO;
+			}
 		}
 
-		if (new_mute != mute) {	/* level doesn't change */
-			cmos_cmd = new_mute ? TP_CMOS_VOLUME_MUTE : TP_CMOS_VOLUME_UP;
+		if (new_mute != mute) {
+			/* level doesn't change */
+
+			cmos_cmd = (new_mute) ?
+				   TP_CMOS_VOLUME_MUTE : TP_CMOS_VOLUME_UP;
 
 			if (issue_thinkpad_cmos_command(cmos_cmd) ||
 			    !acpi_ec_write(volume_offset, level + new_mute))
@@ -4694,7 +4737,7 @@ static int fan_set_enable(void)
 		s |= 4;
 
 		if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", s))
-			rc= -EIO;
+			rc = -EIO;
 		else
 			rc = 0;
 		break;
@@ -4790,7 +4833,8 @@ static void fan_watchdog_reset(void)
 		if (!schedule_delayed_work(&fan_watchdog_task,
 				msecs_to_jiffies(fan_watchdog_maxinterval
 						 * 1000))) {
-			printk(TPACPI_ERR "failed to schedule the fan watchdog, "
+			printk(TPACPI_ERR
+			       "failed to schedule the fan watchdog, "
 			       "watchdog will not trigger\n");
 		}
 	} else
@@ -5076,9 +5120,9 @@ static int __init fan_init(struct ibm_init_struct *iibm)
 				case 0x3637: /* TP-76 */
 				case 0x3037: /* TP-70 */
 					printk(TPACPI_NOTICE
-					       "fan_init: initial fan status is "
-					       "unknown, assuming it is in auto "
-					       "mode\n");
+					       "fan_init: initial fan status "
+					       "is unknown, assuming it is "
+					       "in auto mode\n");
 					tp_features.fan_ctrl_status_undef = 1;
 					;;
 				}
@@ -5151,11 +5195,13 @@ static int __init fan_init(struct ibm_init_struct *iibm)
 
 static void fan_exit(void)
 {
-	vdbg_printk(TPACPI_DBG_EXIT, "cancelling any pending fan watchdog tasks\n");
+	vdbg_printk(TPACPI_DBG_EXIT,
+		    "cancelling any pending fan watchdog tasks\n");
 
 	/* FIXME: can we really do this unconditionally? */
 	sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, &fan_attr_group);
-	driver_remove_file(&tpacpi_hwmon_pdriver.driver, &driver_attr_fan_watchdog);
+	driver_remove_file(&tpacpi_hwmon_pdriver.driver,
+			   &driver_attr_fan_watchdog);
 
 	cancel_delayed_work(&fan_watchdog_task);
 	flush_scheduled_work();
@@ -5171,7 +5217,8 @@ static int fan_read(char *p)
 	switch (fan_status_access_mode) {
 	case TPACPI_FAN_RD_ACPI_GFAN:
 		/* 570, 600e/x, 770e, 770x */
-		if ((rc = fan_get_status_safe(&status)) < 0)
+		rc = fan_get_status_safe(&status);
+		if (rc < 0)
 			return rc;
 
 		len += sprintf(p + len, "status:\t\t%s\n"
@@ -5181,7 +5228,8 @@ static int fan_read(char *p)
 
 	case TPACPI_FAN_RD_TPEC:
 		/* all except 570, 600e/x, 770e, 770x */
-		if ((rc = fan_get_status_safe(&status)) < 0)
+		rc = fan_get_status_safe(&status);
+		if (rc < 0)
 			return rc;
 
 		if (unlikely(tp_features.fan_ctrl_status_undef)) {
@@ -5196,7 +5244,8 @@ static int fan_read(char *p)
 		len += sprintf(p + len, "status:\t\t%s\n",
 			       (status != 0) ? "enabled" : "disabled");
 
-		if ((rc = fan_get_speed(&speed)) < 0)
+		rc = fan_get_speed(&speed);
+		if (rc < 0)
 			return rc;
 
 		len += sprintf(p + len, "speed:\t\t%d\n", speed);
@@ -5232,8 +5281,8 @@ static int fan_read(char *p)
 
 	if (fan_control_commands & TPACPI_FAN_CMD_ENABLE)
 		len += sprintf(p + len, "commands:\tenable, disable\n"
-			       "commands:\twatchdog <timeout> (<timeout> is 0 (off), "
-			       "1-120 (seconds))\n");
+			       "commands:\twatchdog <timeout> (<timeout> "
+			       "is 0 (off), 1-120 (seconds))\n");
 
 	if (fan_control_commands & TPACPI_FAN_CMD_SPEED)
 		len += sprintf(p + len, "commands:\tspeed <speed>"
@@ -5249,12 +5298,13 @@ static int fan_write_cmd_level(const char *cmd, int *rc)
 	if (strlencmp(cmd, "level auto") == 0)
 		level = TP_EC_FAN_AUTO;
 	else if ((strlencmp(cmd, "level disengaged") == 0) |
-	         (strlencmp(cmd, "level full-speed") == 0))
+			(strlencmp(cmd, "level full-speed") == 0))
 		level = TP_EC_FAN_FULLSPEED;
 	else if (sscanf(cmd, "level %d", &level) != 1)
 		return 0;
 
-	if ((*rc = fan_set_level_safe(level)) == -ENXIO)
+	*rc = fan_set_level_safe(level);
+	if (*rc == -ENXIO)
 		printk(TPACPI_ERR "level command accepted for unsupported "
 		       "access mode %d", fan_control_access_mode);
 
@@ -5266,7 +5316,8 @@ static int fan_write_cmd_enable(const char *cmd, int *rc)
 	if (strlencmp(cmd, "enable") != 0)
 		return 0;
 
-	if ((*rc = fan_set_enable()) == -ENXIO)
+	*rc = fan_set_enable();
+	if (*rc == -ENXIO)
 		printk(TPACPI_ERR "enable command accepted for unsupported "
 		       "access mode %d", fan_control_access_mode);
 
@@ -5278,7 +5329,8 @@ static int fan_write_cmd_disable(const char *cmd, int *rc)
 	if (strlencmp(cmd, "disable") != 0)
 		return 0;
 
-	if ((*rc = fan_set_disable()) == -ENXIO)
+	*rc = fan_set_disable();
+	if (*rc == -ENXIO)
 		printk(TPACPI_ERR "disable command accepted for unsupported "
 		       "access mode %d", fan_control_access_mode);
 
@@ -5295,7 +5347,8 @@ static int fan_write_cmd_speed(const char *cmd, int *rc)
 	if (sscanf(cmd, "speed %d", &speed) != 1)
 		return 0;
 
-	if ((*rc = fan_set_speed(speed)) == -ENXIO)
+	*rc = fan_set_speed(speed);
+	if (*rc == -ENXIO)
 		printk(TPACPI_ERR "speed command accepted for unsupported "
 		       "access mode %d", fan_control_access_mode);
 
@@ -5703,38 +5756,38 @@ static int __init set_ibm_param(const char *val, struct kernel_param *kp)
 
 module_param(experimental, int, 0);
 MODULE_PARM_DESC(experimental,
-                 "Enables experimental features when non-zero");
+		 "Enables experimental features when non-zero");
 
 module_param_named(debug, dbg_level, uint, 0);
 MODULE_PARM_DESC(debug, "Sets debug level bit-mask");
 
 module_param(force_load, bool, 0);
 MODULE_PARM_DESC(force_load,
-                 "Attempts to load the driver even on a "
-                 "mis-identified ThinkPad when true");
+		 "Attempts to load the driver even on a "
+		 "mis-identified ThinkPad when true");
 
 module_param_named(fan_control, fan_control_allowed, bool, 0);
 MODULE_PARM_DESC(fan_control,
-                 "Enables setting fan parameters features when true");
+		 "Enables setting fan parameters features when true");
 
 module_param_named(brightness_mode, brightness_mode, int, 0);
 MODULE_PARM_DESC(brightness_mode,
-                 "Selects brightness control strategy: "
-                 "0=auto, 1=EC, 2=CMOS, 3=both");
+		 "Selects brightness control strategy: "
+		 "0=auto, 1=EC, 2=CMOS, 3=both");
 
 module_param(brightness_enable, uint, 0);
 MODULE_PARM_DESC(brightness_enable,
-                 "Enables backlight control when 1, disables when 0");
+		 "Enables backlight control when 1, disables when 0");
 
 module_param(hotkey_report_mode, uint, 0);
 MODULE_PARM_DESC(hotkey_report_mode,
-                 "used for backwards compatibility with userspace, "
-                 "see documentation");
+		 "used for backwards compatibility with userspace, "
+		 "see documentation");
 
 #define TPACPI_PARAM(feature) \
 	module_param_call(feature, set_ibm_param, NULL, NULL, 0); \
 	MODULE_PARM_DESC(feature, "Simulates thinkpad-aci procfs command " \
-	                 "at module load, see documentation")
+			 "at module load, see documentation")
 
 TPACPI_PARAM(hotkey);
 TPACPI_PARAM(bluetooth);
@@ -5832,7 +5885,8 @@ static int __init thinkpad_acpi_module_init(void)
 
 	proc_dir = proc_mkdir(TPACPI_PROC_DIR, acpi_root_dir);
 	if (!proc_dir) {
-		printk(TPACPI_ERR "unable to create proc dir " TPACPI_PROC_DIR);
+		printk(TPACPI_ERR
+		       "unable to create proc dir " TPACPI_PROC_DIR);
 		thinkpad_acpi_module_exit();
 		return -ENODEV;
 	}
@@ -5840,7 +5894,8 @@ static int __init thinkpad_acpi_module_init(void)
 
 	ret = platform_driver_register(&tpacpi_pdriver);
 	if (ret) {
-		printk(TPACPI_ERR "unable to register main platform driver\n");
+		printk(TPACPI_ERR
+		       "unable to register main platform driver\n");
 		thinkpad_acpi_module_exit();
 		return ret;
 	}
@@ -5848,7 +5903,8 @@ static int __init thinkpad_acpi_module_init(void)
 
 	ret = platform_driver_register(&tpacpi_hwmon_pdriver);
 	if (ret) {
-		printk(TPACPI_ERR "unable to register hwmon platform driver\n");
+		printk(TPACPI_ERR
+		       "unable to register hwmon platform driver\n");
 		thinkpad_acpi_module_exit();
 		return ret;
 	}
@@ -5857,10 +5913,12 @@ static int __init thinkpad_acpi_module_init(void)
 	ret = tpacpi_create_driver_attributes(&tpacpi_pdriver.driver);
 	if (!ret) {
 		tp_features.platform_drv_attrs_registered = 1;
-		ret = tpacpi_create_driver_attributes(&tpacpi_hwmon_pdriver.driver);
+		ret = tpacpi_create_driver_attributes(
+					&tpacpi_hwmon_pdriver.driver);
 	}
 	if (ret) {
-		printk(TPACPI_ERR "unable to create sysfs driver attributes\n");
+		printk(TPACPI_ERR
+		       "unable to create sysfs driver attributes\n");
 		thinkpad_acpi_module_exit();
 		return ret;
 	}
@@ -5878,12 +5936,13 @@ static int __init thinkpad_acpi_module_init(void)
 		return ret;
 	}
 	tpacpi_sensors_pdev = platform_device_register_simple(
-							TPACPI_HWMON_DRVR_NAME,
-							-1, NULL, 0);
+						TPACPI_HWMON_DRVR_NAME,
+						-1, NULL, 0);
 	if (IS_ERR(tpacpi_sensors_pdev)) {
 		ret = PTR_ERR(tpacpi_sensors_pdev);
 		tpacpi_sensors_pdev = NULL;
-		printk(TPACPI_ERR "unable to register hwmon platform device\n");
+		printk(TPACPI_ERR
+		       "unable to register hwmon platform device\n");
 		thinkpad_acpi_module_exit();
 		return ret;
 	}
@@ -5891,7 +5950,7 @@ static int __init thinkpad_acpi_module_init(void)
 				 &dev_attr_thinkpad_acpi_pdev_name);
 	if (ret) {
 		printk(TPACPI_ERR
-			"unable to create sysfs hwmon device attributes\n");
+		       "unable to create sysfs hwmon device attributes\n");
 		thinkpad_acpi_module_exit();
 		return ret;
 	}
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#64 lore raw

PATCH 57/112 ACPI: register ACPI Processor as generic thermal cooling device

In reply to Len Brown

From: Zhang Rui <[email protected]>

Register ACPI processor as thermal cooling devices.
A combination of processor T-state and P-state are used for thermal throttling. the processor will reduce the frequency first and then set the T-state.

we use cpufreq_thermal_reduction_pctg to calculate the cpufreq limit, and call cpufreq_verify_with_limit to set the cpufreq limit.
if cpufreq driver is loaded, then we have four cooling state for cpufreq control. cooling state 0: cpufreq limit == max_freq
cooling state 1: cpufreq limit == max_freq * 80%
cooling state 2: cpufreq limit == max_freq * 60%
cooling state 3: cpufreq limit == max_freq * 40%

after the cpufreq limit is set to 40 percentage of the max_freq, we use T-state for cooling.

eg. a processor has P-state support, and it has 8 T-state (T0-T7), the max_state of the proceesor is 10:

state cpufreq-limit T-state
0: max_freq T0
1: max_freq * 80% T0
2: max_freq * 60% T0
3: max_freq * 40% T0
4: max_freq * 40% T1
5: max_freq * 40% T2
6: max_freq * 40% T3
7: max_freq * 40% T4
8: max_freq * 40% T5
9: max_freq * 40% T6
10: max_freq * 40% T7

---
 drivers/acpi/processor_core.c    |   23 +++++++
 drivers/acpi/processor_thermal.c |  134 ++++++++++++++++++++++++++++++++++++--
 include/acpi/processor.h         |    6 +-
 3 files changed, 155 insertions(+), 8 deletions(-)
drivers/acpi/processor_core.c +23 -0
index e48ee4f..5668c5e 100644
@@ -668,6 +668,24 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
 
 	acpi_processor_power_init(pr, device);
 
+	pr->cdev = thermal_cooling_device_register("Processor", device,
+						&processor_cooling_ops);
+	if (pr->cdev)
+		printk(KERN_INFO PREFIX
+			"%s is registered as cooling_device%d\n",
+			device->dev.bus_id, pr->cdev->id);
+	else
+		goto end;
+
+	result = sysfs_create_link(&device->dev.kobj, &pr->cdev->device.kobj,
+					"thermal_cooling");
+	if (result)
+		return result;
+	result = sysfs_create_link(&pr->cdev->device.kobj, &device->dev.kobj,
+					"device");
+	if (result)
+		return result;
+
 	if (pr->flags.throttling) {
 		printk(KERN_INFO PREFIX "%s [%s] (supports",
 		       acpi_device_name(device), acpi_device_bid(device));
@@ -791,6 +809,11 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
 
 	acpi_processor_remove_fs(device);
 
+	sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
+	sysfs_remove_link(&pr->cdev->device.kobj, "device");
+	thermal_cooling_device_unregister(pr->cdev);
+	pr->cdev = NULL;
+
 	processors[pr->id] = NULL;
 
 	kfree(pr);
drivers/acpi/processor_thermal.c +129 -5

182 lines not on this page · raw message

include/acpi/processor.h +3 -3
index 76411b1..0787635 100644
@@ -4,7 +4,7 @@
 #include <linux/kernel.h>
 #include <linux/cpu.h>
 #include <linux/cpuidle.h>
-
+#include <linux/thermal.h>
 #include <asm/acpi.h>
 
 #define ACPI_PROCESSOR_BUSY_METRIC	10
@@ -218,7 +218,7 @@ struct acpi_processor {
 	struct acpi_processor_performance *performance;
 	struct acpi_processor_throttling throttling;
 	struct acpi_processor_limit limit;
-
+	struct thermal_cooling_device *cdev;
 	/* the _PDC objects for this processor, if any */
 	struct acpi_object_list *pdc;
 };
@@ -330,7 +330,7 @@ extern struct cpuidle_driver acpi_idle_driver;
 /* in processor_thermal.c */
 int acpi_processor_get_limit_info(struct acpi_processor *pr);
 extern struct file_operations acpi_processor_limit_fops;
-
+extern struct thermal_cooling_device_ops processor_cooling_ops;
 #ifdef CONFIG_CPU_FREQ
 void acpi_thermal_cpufreq_init(void);
 void acpi_thermal_cpufreq_exit(void);
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#44 lore raw

PATCH 44/112 ACPI: thinkpad-acpi: add suspend handler

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

Add a handler for suspend events.

---
 drivers/misc/thinkpad_acpi.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)
drivers/misc/thinkpad_acpi.c +17 -0
index dd6fa81..c6c25a4 100644
@@ -188,6 +188,7 @@ struct ibm_struct {
 	int (*write) (char *);
 	void (*exit) (void);
 	void (*resume) (void);
+	void (*suspend) (pm_message_t state);
 
 	struct list_head all_drivers;
 
@@ -658,6 +659,21 @@ static struct input_dev *tpacpi_inputdev;
 static struct mutex tpacpi_inputdev_send_mutex;
 static LIST_HEAD(tpacpi_all_drivers);
 
+static int tpacpi_suspend_handler(struct platform_device *pdev,
+				  pm_message_t state)
+{
+	struct ibm_struct *ibm, *itmp;
+
+	list_for_each_entry_safe(ibm, itmp,
+				 &tpacpi_all_drivers,
+				 all_drivers) {
+		if (ibm->suspend)
+			(ibm->suspend)(state);
+	}
+
+	return 0;
+}
+
 static int tpacpi_resume_handler(struct platform_device *pdev)
 {
 	struct ibm_struct *ibm, *itmp;
@@ -677,6 +693,7 @@ static struct platform_driver tpacpi_pdriver = {
 		.name = TPACPI_DRVR_NAME,
 		.owner = THIS_MODULE,
 	},
+	.suspend = tpacpi_suspend_handler,
 	.resume = tpacpi_resume_handler,
 };
 
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#66 lore raw

PATCH 58/112 ACPI: register ACPI Video LCD as generic thermal cooling device

In reply to Len Brown

From: Zhang Rui <[email protected]>

Register ACPI video device as thermal cooling devices as they may be listed in _TZD method and the backlight control can be used for throttling.

---
 drivers/acpi/video.c |   78 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 77 insertions(+), 1 deletions(-)
drivers/acpi/video.c +77 -1
index bd77e81..eab9c42 100644
@@ -34,6 +34,7 @@
 #include <linux/seq_file.h>
 #include <linux/input.h>
 #include <linux/backlight.h>
+#include <linux/thermal.h>
 #include <linux/video_output.h>
 #include <asm/uaccess.h>
 
@@ -179,6 +180,7 @@ struct acpi_video_device {
 	struct acpi_device *dev;
 	struct acpi_video_device_brightness *brightness;
 	struct backlight_device *backlight;
+	struct thermal_cooling_device *cdev;
 	struct output_device *output_dev;
 };
 
@@ -334,6 +336,54 @@ static struct output_properties acpi_output_properties = {
 	.set_state = acpi_video_output_set,
 	.get_status = acpi_video_output_get,
 };
+
+
+/* thermal cooling device callbacks */
+static int video_get_max_state(struct thermal_cooling_device *cdev, char *buf)
+{
+	struct acpi_device *device = cdev->devdata;
+	struct acpi_video_device *video = acpi_driver_data(device);
+
+	return sprintf(buf, "%d\n", video->brightness->count - 3);
+}
+
+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;
+	int state;
+
+	acpi_video_device_lcd_get_level_current(video, &level);
+	for (state = 2; state < video->brightness->count; state++)
+		if (level == video->brightness->levels[state])
+			return sprintf(buf, "%d\n",
+				       video->brightness->count - state - 1);
+
+	return -EINVAL;
+}
+
+static int
+video_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state)
+{
+	struct acpi_device *device = cdev->devdata;
+	struct acpi_video_device *video = acpi_driver_data(device);
+	int level;
+
+	if ( state >= video->brightness->count - 2)
+		return -EINVAL;
+
+	state = video->brightness->count - state;
+	level = video->brightness->levels[state -1];
+	return acpi_video_device_lcd_set_level(video, level);
+}
+
+static struct thermal_cooling_device_ops video_cooling_ops = {
+	.get_max_state = video_get_max_state,
+	.get_cur_state = video_get_cur_state,
+	.set_cur_state = video_set_cur_state,
+};
+
 /* --------------------------------------------------------------------------
                                Video Management
    -------------------------------------------------------------------------- */
@@ -653,6 +703,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 
 	if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){
 		unsigned long tmp;
+		int result;
 		static int count = 0;
 		char *name;
 		name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
@@ -666,8 +717,25 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 		device->backlight->props.max_brightness = max_level;
 		device->backlight->props.brightness = (int)tmp;
 		backlight_update_status(device->backlight);
-
 		kfree(name);
+
+		device->cdev = thermal_cooling_device_register("LCD",
+					device->dev, &video_cooling_ops);
+		if (device->cdev) {
+			printk(KERN_INFO PREFIX
+				"%s is registered as cooling_device%d\n",
+				device->dev->dev.bus_id, device->cdev->id);
+			result = sysfs_create_link(&device->dev->dev.kobj,
+					  &device->cdev->device.kobj,
+					  "thermal_cooling");
+			if (result)
+				printk(KERN_ERR PREFIX "Create sysfs link\n");
+			result = sysfs_create_link(&device->cdev->device.kobj,
+					  &device->dev->dev.kobj,
+					  "device");
+                        if (result)
+				printk(KERN_ERR PREFIX "Create sysfs link\n");
+		}
 	}
 	if (device->cap._DCS && device->cap._DSS){
 		static int count = 0;
@@ -1729,6 +1797,14 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
 					    ACPI_DEVICE_NOTIFY,
 					    acpi_video_device_notify);
 	backlight_device_unregister(device->backlight);
+	if (device->cdev) {
+		sysfs_remove_link(&device->dev->dev.kobj,
+				  "thermal_cooling");
+		sysfs_remove_link(&device->cdev->device.kobj,
+				  "device");
+		thermal_cooling_device_unregister(device->cdev);
+		device->cdev = NULL;
+	}
 	video_output_unregister(device->output_dev);
 
 	return 0;
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#45 lore raw

PATCH 45/112 ACPI: thinkpad-acpi: cleanup hotkey_notify and HKEY log messages

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

Use a generic message on hotkey_notify to log unknown and unhandled events, and cleanup hotkey_notify a little.

Also, document event 0x5010 (brightness changed notification) and do not log it as an unknown event (even if we do not use it for anything right now).

---
 Documentation/thinkpad-acpi.txt |    4 ++++
 drivers/misc/thinkpad_acpi.c    |   35 ++++++++++++++++++++---------------
 2 files changed, 24 insertions(+), 15 deletions(-)
Documentation/thinkpad-acpi.txt +4 -0
index 7c7bd47..3fb8647 100644
@@ -475,6 +475,10 @@ Non hot-key ACPI HKEY event map:
 The above events are not propagated by the driver, except for legacy
 compatibility purposes when hotkey_report_mode is set to 1.
 
+0x5010		Brightness level changed (newer Lenovo BIOSes)
+
+The above events are propagated by the driver.
+
 Compatibility notes:
 
 ibm-acpi and thinkpad-acpi 0.15 (mainline kernels before 2.6.23) never
drivers/misc/thinkpad_acpi.c +20 -15
index c6c25a4..f5f306a 100644
@@ -2007,6 +2007,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 	unsigned int scancode;
 	int send_acpi_ev;
 	int ignore_acpi_ev;
+	int unk_ev;
 
 	if (event != 0x80) {
 		printk(TPACPI_ERR
@@ -2030,8 +2031,9 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 			return;
 		}
 
-		send_acpi_ev = 0;
+		send_acpi_ev = 1;
 		ignore_acpi_ev = 0;
+		unk_ev = 0;
 
 		switch (hkey >> 12) {
 		case 1:
@@ -2041,33 +2043,34 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 				scancode--;
 				if (!(hotkey_source_mask & (1 << scancode))) {
 					tpacpi_input_send_key(scancode);
+					send_acpi_ev = 0;
 				} else {
 					ignore_acpi_ev = 1;
 				}
 			} else {
-				printk(TPACPI_ERR
-				       "hotkey 0x%04x out of range "
-				       "for keyboard map\n", hkey);
-				send_acpi_ev = 1;
+				unk_ev = 1;
 			}
 			break;
 		case 5:
-			/* 0x5000-0x5FFF: LID */
-			/* we don't handle it through this path, just
-			 * eat up known LID events */
-			if (hkey != 0x5001 && hkey != 0x5002) {
-				printk(TPACPI_ERR
-				       "unknown LID-related HKEY event: "
-				       "0x%04x\n", hkey);
-				send_acpi_ev = 1;
-			} else {
+			/* 0x5000-0x5FFF: On screen display helpers */
+			switch (hkey) {
+			case 0x5010:
+				/* Lenovo Vista BIOS: brightness changed */
+				break;
+			case 0x5001:
+			case 0x5002:
+				/* LID switch events.  Do not propagate */
 				ignore_acpi_ev = 1;
+				break;
+			default:
+				unk_ev = 1;
 			}
 			break;
 		case 7:
 			/* 0x7000-0x7FFF: misc */
 			if (tp_features.hotkey_wlsw && hkey == 0x7000) {
 				tpacpi_input_send_radiosw();
+				send_acpi_ev = 0;
 				break;
 			}
 			/* fallthrough to default */
@@ -2078,9 +2081,11 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 			/* case 3: ultra-bay related. maybe bay in dock? */
 			/*	0x3003 - T43 after wake up by bay lever
 			 *	         eject (0x2305) */
+			unk_ev = 1;
+		}
+		if (unk_ev) {
 			printk(TPACPI_NOTICE
 			       "unhandled HKEY event 0x%04x\n", hkey);
-			send_acpi_ev = 1;
 		}
 
 		/* Legacy events */
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#67 lore raw

PATCH 59/112 ACPI: attach thermal zone info

In reply to Len Brown

From: Zhang Rui <[email protected]>

Intel menlow driver needs to get the pointer of themal_zone_device structure of an ACPI thermal zone.
Attach this to each ACPI thermal zone device object.

---
 drivers/acpi/bus.c      |   25 +++++++++++++++++++++++++
 drivers/acpi/thermal.c  |   11 +++++++++++
 include/acpi/acpi_bus.h |    2 ++
 3 files changed, 38 insertions(+), 0 deletions(-)
drivers/acpi/bus.c +25 -0
index 1b4cf98..8df325d 100644
@@ -122,6 +122,31 @@ int acpi_bus_get_status(struct acpi_device *device)
 
 EXPORT_SYMBOL(acpi_bus_get_status);
 
+void acpi_bus_private_data_handler(acpi_handle handle,
+				   u32 function, void *context)
+{
+	return;
+}
+EXPORT_SYMBOL(acpi_bus_private_data_handler);
+
+int acpi_bus_get_private_data(acpi_handle handle, void **data)
+{
+	acpi_status status = AE_OK;
+
+	if (!*data)
+		return -EINVAL;
+
+	status = acpi_get_data(handle, acpi_bus_private_data_handler, data);
+	if (ACPI_FAILURE(status) || !*data) {
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
+				handle));
+		return -ENODEV;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(acpi_bus_get_private_data);
+
 /* --------------------------------------------------------------------------
                                  Power Management
    -------------------------------------------------------------------------- */
drivers/acpi/thermal.c +11 -0
index d317da5..7400363 100644
@@ -1101,6 +1101,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
 {
 	int trips = 0;
 	int result;
+	acpi_status status;
 	int i;
 
 	if (tz->trips.critical.flags.valid)
@@ -1129,6 +1130,15 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
 	if (result)
 		return result;
 
+	status = acpi_attach_data(tz->device->handle,
+				  acpi_bus_private_data_handler,
+				  tz->thermal_zone);
+	if (ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+				"Error attaching device data\n"));
+		return -ENODEV;
+	}
+
 	tz->tz_enabled = 1;
 
 	printk(KERN_INFO PREFIX "%s is registered as thermal_zone%d\n",
@@ -1142,6 +1152,7 @@ static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
 	sysfs_remove_link(&tz->thermal_zone->device.kobj, "device");
 	thermal_zone_device_unregister(tz->thermal_zone);
 	tz->thermal_zone = NULL;
+	acpi_detach_data(tz->device->handle, acpi_bus_private_data_handler);
 }
 
 
include/acpi/acpi_bus.h +2 -0
index fb7171b..504af20 100644
@@ -321,6 +321,8 @@ struct acpi_bus_event {
 
 extern struct kobject *acpi_kobj;
 extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int);
+void acpi_bus_private_data_handler(acpi_handle, u32, void *);
+int acpi_bus_get_private_data(acpi_handle, void **);
 /*
  * External Functions
  */
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#68 lore raw

PATCH 60/112 ACPI: CELSIUS_TO_KELVIN fixup

In reply to Len Brown

From: Zhang Rui <[email protected]>

Fix an imprecision in CELSIUS_TO_KELVIN and move these two macroes to a proper place.

---
 drivers/acpi/thermal.c  |    3 ---
 include/linux/thermal.h |    4 ++++
 2 files changed, 4 insertions(+), 3 deletions(-)
drivers/acpi/thermal.c +0 -3
index 7400363..aee371f 100644
@@ -65,9 +65,6 @@
 #define ACPI_THERMAL_MAX_ACTIVE	10
 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
 
-#define KELVIN_TO_CELSIUS(t)    (long)(((long)t-2732>=0) ? ((long)t-2732+5)/10 : ((long)t-2732-5)/10)
-#define CELSIUS_TO_KELVIN(t)	((t+273)*10)
-
 #define _COMPONENT		ACPI_THERMAL_COMPONENT
 ACPI_MODULE_NAME("thermal");
 
include/linux/thermal.h +4 -0
index e4b76c7..bba7712 100644
@@ -61,6 +61,10 @@ struct thermal_cooling_device {
 	struct list_head node;
 };
 
+#define KELVIN_TO_CELSIUS(t)	(long)(((long)t-2732 >= 0) ?	\
+				((long)t-2732+5)/10 : ((long)t-2732-5)/10)
+#define CELSIUS_TO_KELVIN(t)	((t)*10+2732)
+
 struct thermal_zone_device {
 	int id;
 	char type[THERMAL_NAME_LENGTH];
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#46 lore raw

PATCH 46/112 ACPI: thinkpad-acpi: wakeup on hotunplug reporting

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

Handle some HKEY events that the firmware uses to report the reason for a wake up, and to also notify that the system could go back to sleep (if it woke up just to eject something from the bay, or to undock).

The driver will report the reason of the last wake up in the sysfs attribute "wakeup_reason": 0 for "none, unknown, or standard ACPI wake up event", 1 for "bay ejection request" and 2 for "undock request".

The firmware will also report if the operation that triggered the wake up has been completed, by issuing an HKEY 0x3003 or 0x4003 event. If the operation fails, no event is sent. When such a hotunplug sucessfull notification is issued, the driver sets the attribute "wakeup_hotunplug_complete" to 1.

While the firmware does tell us whether we are waking from a suspend or hibernation scenario, the Linux way of hibernating makes this information not reliable, and therefore it is not reported.

The idea is that if any of these attributes are non-zero, userspace might want to do something at the end of the "wake up from sleep" procedures, such as offering to send the machine back into sleep as soon as it is safe to do so.

---
 Documentation/thinkpad-acpi.txt |   24 ++++++++++
 drivers/misc/thinkpad_acpi.c    |   91 ++++++++++++++++++++++++++++++++++++---
 2 files changed, 108 insertions(+), 7 deletions(-)
Documentation/thinkpad-acpi.txt +24 -0
index 3fb8647..9d08e47 100644
@@ -325,6 +325,21 @@ sysfs notes:
 		May return -EPERM (write access locked out by module
 		parameter) or -EACCES (read-only).
 
+	wakeup_reason:
+		Set to 1 if the system is waking up because the user
+		requested a bay ejection.  Set to 2 if the system is
+		waking up because the user requested the system to
+		undock.  Set to zero for normal wake-ups or wake-ups
+		due to unknown reasons.
+
+	wakeup_hotunplug_complete:
+		Set to 1 if the system was waken up because of an
+		undock or bay ejection request, and that request
+		was sucessfully completed.  At this point, it might
+		be useful to send the system back to sleep, at the
+		user's choice.  Refer to HKEY events 0x4003 and
+		0x3003, below.
+
 input layer notes:
 
 A Hot key is mapped to a single input layer EV_KEY event, possibly
@@ -475,6 +490,15 @@ Non hot-key ACPI HKEY event map:
 The above events are not propagated by the driver, except for legacy
 compatibility purposes when hotkey_report_mode is set to 1.
 
+0x2304		System is waking up from suspend to undock
+0x2305		System is waking up from suspend to eject bay
+0x2404		System is waking up from hibernation to undock
+0x2405		System is waking up from hibernation to eject bay
+
+The above events are never propagated by the driver.
+
+0x3003		Bay ejection (see 0x2x05) complete, can sleep again
+0x4003		Undocked (see 0x2x04), can sleep again
 0x5010		Brightness level changed (newer Lenovo BIOSes)
 
 The above events are propagated by the driver.
drivers/misc/thinkpad_acpi.c +84 -7

139 lines not on this page · raw message

Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#47 lore raw

PATCH 47/112 ACPI: thinkpad-acpi: add X61t HKEY events

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

Tomas Carnecky reports that events 0x5009 and 0x500a are swivel events, and that 0x500b/0x500c are tablet pen storage bay events.

Document these events, and avoid nasty messages when they happen.

---
 Documentation/thinkpad-acpi.txt |    4 ++++
 drivers/misc/thinkpad_acpi.c    |    9 ++++++---
 2 files changed, 10 insertions(+), 3 deletions(-)
Documentation/thinkpad-acpi.txt +4 -0
index 9d08e47..e1c4550 100644
@@ -499,6 +499,10 @@ The above events are never propagated by the driver.
 
 0x3003		Bay ejection (see 0x2x05) complete, can sleep again
 0x4003		Undocked (see 0x2x04), can sleep again
+0x5009		Tablet swivel: switched to tablet mode
+0x500A		Tablet swivel: switched to normal mode
+0x500B		Tablet pen insterted into its storage bay
+0x500C		Tablet pen removed from its storage bay
 0x5010		Brightness level changed (newer Lenovo BIOSes)
 
 The above events are propagated by the driver.
drivers/misc/thinkpad_acpi.c +6 -3
index 9b0235d..049ec42 100644
@@ -2127,10 +2127,13 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 			}
 			break;
 		case 5:
-			/* 0x5000-0x5FFF: On screen display helpers */
+			/* 0x5000-0x5FFF: human interface helpers */
 			switch (hkey) {
-			case 0x5010:
-				/* Lenovo Vista BIOS: brightness changed */
+			case 0x5010: /* Lenovo new BIOS: brightness changed */
+			case 0x5009: /* X61t: swivel up (tablet mode) */
+			case 0x500a: /* X61t: swivel down (normal mode) */
+			case 0x500b: /* X61t: tablet pen inserted into bay */
+			case 0x500c: /* X61t: tablet pen removed from bay */
 				break;
 			case 0x5001:
 			case 0x5002:
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#69 lore raw

PATCH 61/112 intel_menlo: introduce new platform specific driver

In reply to Len Brown

From: Thomas Sujith <[email protected]>

Intel menlow platform specific driver for thermal management extension.

---
 drivers/misc/Kconfig        |    9 +
 drivers/misc/Makefile       |    1 +
 drivers/misc/intel_menlow.c |  526 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 536 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/intel_menlow.c
drivers/misc/Kconfig +9 -0
index b5e67c0..d1380a5 100644
@@ -232,4 +232,13 @@ config ATMEL_SSC
 
 	  If unsure, say N.
 
+config INTEL_MENLOW
+	tristate "Thermal Management driver for Intel menlow platform"
+	depends on ACPI_THERMAL
+	---help---
+	  ACPI thermal management enhancement driver on
+	  Intel Menlow platform.
+
+	  If unsure, say N.
+
 endif # MISC_DEVICES
drivers/misc/Makefile +1 -0
index 87f2685..a9e8faf 100644
@@ -17,3 +17,4 @@ obj-$(CONFIG_SONY_LAPTOP)	+= sony-laptop.o
 obj-$(CONFIG_THINKPAD_ACPI)	+= thinkpad_acpi.o
 obj-$(CONFIG_FUJITSU_LAPTOP)	+= fujitsu-laptop.o
 obj-$(CONFIG_EEPROM_93CX6)	+= eeprom_93cx6.o
+obj-$(CONFIG_INTEL_MENLOW)	+= intel_menlow.o
drivers/misc/intel_menlow.c new file +526 -0

526 lines not on this page · raw message

Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#70 lore raw

PATCH 62/112 ACPI: thermal fixup

In reply to Len Brown

From: Zhang Rui <[email protected]>

The alias name may be used in _PSL, _ALx and _TZD,
so we bind the cooling device only if the acpi_device node matches.

---
 drivers/acpi/thermal.c |   42 ++++++++++++++++++++++++------------------
 1 files changed, 24 insertions(+), 18 deletions(-)
drivers/acpi/thermal.c +24 -18
index aee371f..73f276b 100644
@@ -1015,7 +1015,9 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
 {
 	struct acpi_device *device = cdev->devdata;
 	struct acpi_thermal *tz = thermal->devdata;
-	acpi_handle handle = device->handle;
+	struct acpi_device *dev;
+	acpi_status status;
+	acpi_handle handle;
 	int i;
 	int j;
 	int trip = -1;
@@ -1031,12 +1033,13 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
 		trip++;
 		for (i = 0; i < tz->trips.passive.devices.count;
 		    i++) {
-			if (tz->trips.passive.devices.handles[i] !=
-				handle)
-				continue;
-			result = action(thermal, trip, cdev);
-			if (result)
-				goto failed;
+			handle = tz->trips.passive.devices.handles[i];
+			status = acpi_bus_get_device(handle, &dev);
+			if (ACPI_SUCCESS(status) && (dev == device)) {
+				result = action(thermal, trip, cdev);
+				if (result)
+					goto failed;
+			}
 		}
 	}
 
@@ -1047,21 +1050,24 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
 		for (j = 0;
 		    j < tz->trips.active[i].devices.count;
 		    j++) {
-			if (tz->trips.active[i].devices.
-						handles[j] != handle)
-				continue;
-			result = action(thermal, trip, cdev);
-			if (result)
-				goto failed;
+			handle = tz->trips.active[i].devices.handles[j];
+			status = acpi_bus_get_device(handle, &dev);
+			if (ACPI_SUCCESS(status) && (dev == device)) {
+				result = action(thermal, trip, cdev);
+				if (result)
+					goto failed;
+			}
 		}
 	}
 
 	for (i = 0; i < tz->devices.count; i++) {
-		if (tz->devices.handles[i] != handle)
-			continue;
-		result = action(thermal, -1, cdev);
-		if (result)
-			goto failed;
+		handle = tz->devices.handles[i];
+		status = acpi_bus_get_device(handle, &dev);
+		if (ACPI_SUCCESS(status) && (dev == device)) {
+			result = action(thermal, -1, cdev);
+			if (result)
+				goto failed;
+		}
 	}
 
 failed:
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#48 lore raw

PATCH 48/112 ACPI: thinkpad-acpi: silence _sta warning

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

When both CONFIG_THINKPAD_ACPI_DOCK and CONFIG_THINKPAD_ACPI_BAY are undefined, _sta is not used and that causes a gcc warning. Fix it (and I think this is a regression, I am pretty sure I fixed this once before, sorry about that).

Issue reported by: Pritt Laes.

---
 drivers/misc/thinkpad_acpi.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/misc/thinkpad_acpi.c +2 -0
index 049ec42..e18f1e1 100644
@@ -414,6 +414,7 @@ static int acpi_ec_write(int i, u8 v)
 	return 1;
 }
 
+#if defined(CONFIG_THINKPAD_ACPI_DOCK) || defined(CONFIG_THINKPAD_ACPI_BAY)
 static int _sta(acpi_handle handle)
 {
 	int status;
@@ -423,6 +424,7 @@ static int _sta(acpi_handle handle)
 
 	return status;
 }
+#endif
 
 static int issue_thinkpad_cmos_command(int cmos_cmd)
 {
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#71 lore raw

PATCH 63/112 ACPI: video: Ignore devices that aren't present in hardware

In reply to Len Brown

From: Matthew Garrett <[email protected]>

Vendors often ship machines with a choice of integrated or discrete graphics, and use the same DSDT for both. As a result, the ACPI video module will locate devices that may not exist on this specific platform. Attempt to determine whether the device exists or not, and abort the device creation if it doesn't.

http://bugzilla.kernel.org/show_bug.cgi?id=9614

---
 drivers/acpi/video.c |   29 +++++++++++++++++++++++++++++
 1 files changed, 29 insertions(+), 0 deletions(-)
drivers/acpi/video.c +29 -0
index bd77e81..2270144 100644
@@ -1256,8 +1256,37 @@ acpi_video_bus_write_DOS(struct file *file,
 
 static int acpi_video_bus_add_fs(struct acpi_device *device)
 {
+	long device_id;
+	int status;
 	struct proc_dir_entry *entry = NULL;
 	struct acpi_video_bus *video;
+	struct device *dev;
+
+	status =
+	    acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
+
+	if (!ACPI_SUCCESS(status))
+		return -ENODEV;
+
+	/* We need to attempt to determine whether the _ADR refers to a
+	   PCI device or not. There's no terribly good way to do this,
+	   so the best we can hope for is to assume that there'll never
+	   be a video device in the host bridge */
+	if (device_id >= 0x10000) {
+		/* It looks like a PCI device. Does it exist? */
+		dev = acpi_get_physical_device(device->handle);
+	} else {
+		/* It doesn't look like a PCI device. Does its parent
+		   exist? */
+		acpi_handle phandle;
+		if (acpi_get_parent(device->handle, &phandle))
+			return -ENODEV;
+		dev = acpi_get_physical_device(phandle);
+	}
+	if (!dev)
+		return -ENODEV;
+	put_device(dev);
+
 
 
 	video = acpi_driver_data(device);
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#49 lore raw

PATCH 49/112 ACPI: thinkpad-acpi: add poll() support to some sysfs attributes

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

Implement poll()/select() support through sysfs_notify() for some key attributes which userspace might want to poll() or select() on.

In order to let userspace know poll()/select() support is available for an attribute, the thinkpad-acpi sysfs interface version is also bumped up. Further changes that add poll()/select() capabilities to any pre-existing attributes will also increment the sysfs interface version.

---
 Documentation/thinkpad-acpi.txt |    9 +++++++++
 drivers/misc/thinkpad_acpi.c    |   36 ++++++++++++++++++++++++++++++++----
 2 files changed, 41 insertions(+), 4 deletions(-)
Documentation/thinkpad-acpi.txt +9 -0
index e1c4550..9bbd0f5 100644
@@ -311,6 +311,8 @@ sysfs notes:
 		disabled" postition, and 1 if the switch is in the
 		"radios enabled" position.
 
+		This attribute has poll()/select() support.
+
 	hotkey_report_mode:
 		Returns the state of the procfs ACPI event report mode
 		filter for hot keys.  If it is set to 1 (the default),
@@ -332,6 +334,8 @@ sysfs notes:
 		undock.  Set to zero for normal wake-ups or wake-ups
 		due to unknown reasons.
 
+		This attribute has poll()/select() support.
+
 	wakeup_hotunplug_complete:
 		Set to 1 if the system was waken up because of an
 		undock or bay ejection request, and that request
@@ -340,6 +344,8 @@ sysfs notes:
 		user's choice.  Refer to HKEY events 0x4003 and
 		0x3003, below.
 
+		This attribute has poll()/select() support.
+
 input layer notes:
 
 A Hot key is mapped to a single input layer EV_KEY event, possibly
@@ -1354,3 +1360,6 @@ Sysfs interface changelog:
 		NVRAM polling patch).  Some development snapshots of
 		0.18 had an earlier version that did strange things
 		to hotkey_mask.
+
+0x020200:	Add poll()/select() support to the following attributes:
+		hotkey_radio_sw, wakeup_hotunplug_complete, wakeup_reason
drivers/misc/thinkpad_acpi.c +32 -4
index e18f1e1..91bda31 100644
@@ -22,7 +22,7 @@
  */
 
 #define TPACPI_VERSION "0.18"
-#define TPACPI_SYSFS_VERSION 0x020101
+#define TPACPI_SYSFS_VERSION 0x020200
 
 /*
  *  Changelog:
@@ -1643,7 +1643,7 @@ static struct device_attribute dev_attr_hotkey_poll_freq =
 
 #endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
 
-/* sysfs hotkey radio_sw ----------------------------------------------- */
+/* sysfs hotkey radio_sw (pollable) ------------------------------------ */
 static ssize_t hotkey_radio_sw_show(struct device *dev,
 			   struct device_attribute *attr,
 			   char *buf)
@@ -1659,6 +1659,13 @@ static ssize_t hotkey_radio_sw_show(struct device *dev,
 static struct device_attribute dev_attr_hotkey_radio_sw =
 	__ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL);
 
+static void hotkey_radio_sw_notify_change(void)
+{
+	if (tp_features.hotkey_wlsw)
+		sysfs_notify(&tpacpi_pdev->dev.kobj, NULL,
+			     "hotkey_radio_sw");
+}
+
 /* sysfs hotkey report_mode -------------------------------------------- */
 static ssize_t hotkey_report_mode_show(struct device *dev,
 			   struct device_attribute *attr,
@@ -1671,7 +1678,7 @@ static ssize_t hotkey_report_mode_show(struct device *dev,
 static struct device_attribute dev_attr_hotkey_report_mode =
 	__ATTR(hotkey_report_mode, S_IRUGO, hotkey_report_mode_show, NULL);
 
-/* sysfs wakeup reason ------------------------------------------------- */
+/* sysfs wakeup reason (pollable) -------------------------------------- */
 static ssize_t hotkey_wakeup_reason_show(struct device *dev,
 			   struct device_attribute *attr,
 			   char *buf)
@@ -1682,7 +1689,14 @@ static ssize_t hotkey_wakeup_reason_show(struct device *dev,
 static struct device_attribute dev_attr_hotkey_wakeup_reason =
 	__ATTR(wakeup_reason, S_IRUGO, hotkey_wakeup_reason_show, NULL);
 
-/* sysfs wakeup hotunplug_complete ------------------------------------- */
+void hotkey_wakeup_reason_notify_change(void)
+{
+	if (tp_features.hotkey_mask)
+		sysfs_notify(&tpacpi_pdev->dev.kobj, NULL,
+			     "wakeup_reason");
+}
+
+/* sysfs wakeup hotunplug_complete (pollable) -------------------------- */
 static ssize_t hotkey_wakeup_hotunplug_complete_show(struct device *dev,
 			   struct device_attribute *attr,
 			   char *buf)
@@ -1694,6 +1708,13 @@ static struct device_attribute dev_attr_hotkey_wakeup_hotunplug_complete =
 	__ATTR(wakeup_hotunplug_complete, S_IRUGO,
 	       hotkey_wakeup_hotunplug_complete_show, NULL);
 
+void hotkey_wakeup_hotunplug_complete_notify_change(void)
+{
+	if (tp_features.hotkey_mask)
+		sysfs_notify(&tpacpi_pdev->dev.kobj, NULL,
+			     "wakeup_hotunplug_complete");
+}
+
 /* --------------------------------------------------------------------- */
 
 static struct attribute *hotkey_attributes[] __initdata = {
@@ -2106,6 +2127,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 				printk(TPACPI_INFO
 				       "woke up due to a hot-unplug "
 				       "request...\n");
+				hotkey_wakeup_reason_notify_change();
 			}
 			break;
 		case 3:
@@ -2114,6 +2136,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 				hotkey_autosleep_ack = 1;
 				printk(TPACPI_INFO
 				       "bay ejected\n");
+				hotkey_wakeup_hotunplug_complete_notify_change();
 			} else {
 				unk_ev = 1;
 			}
@@ -2124,6 +2147,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 				hotkey_autosleep_ack = 1;
 				printk(TPACPI_INFO
 				       "undocked\n");
+				hotkey_wakeup_hotunplug_complete_notify_change();
 			} else {
 				unk_ev = 1;
 			}
@@ -2150,6 +2174,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 			/* 0x7000-0x7FFF: misc */
 			if (tp_features.hotkey_wlsw && hkey == 0x7000) {
 				tpacpi_input_send_radiosw();
+				hotkey_radio_sw_notify_change();
 				send_acpi_ev = 0;
 				break;
 			}
@@ -2193,6 +2218,9 @@ static void hotkey_resume(void)
 		       "error while trying to read hot key mask "
 		       "from firmware\n");
 	tpacpi_input_send_radiosw();
+	hotkey_radio_sw_notify_change();
+	hotkey_wakeup_reason_notify_change();
+	hotkey_wakeup_hotunplug_complete_notify_change();
 #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
 	hotkey_poll_setup_safe(0);
 #endif
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#50 lore raw

PATCH 50/112 ACPI: thinkpad-acpi: update copyright dates to 2008

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

Update the copyright headers to include 2008.

---
 drivers/misc/thinkpad_acpi.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/misc/thinkpad_acpi.c +1 -1
index 91bda31..05f5329 100644
@@ -3,7 +3,7 @@
  *
  *
  *  Copyright (C) 2004-2005 Borislav Deianov <[email protected]>
- *  Copyright (C) 2006-2007 Henrique de Moraes Holschuh <[email protected]>
+ *  Copyright (C) 2006-2008 Henrique de Moraes Holschuh <[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
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#51 lore raw

PATCH 51/112 ACPI: thinkpad-acpi: bump up version to 0.19

In reply to Len Brown

From: Henrique de Moraes Holschuh <[email protected]>

The major code reorganization and cleanups, and new HKEY events, plus poll()/select() support are good reasons to checkpoint a new version...

---
 Documentation/thinkpad-acpi.txt |    4 ++--
 drivers/misc/thinkpad_acpi.c    |    2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)
Documentation/thinkpad-acpi.txt +2 -2
index 9bbd0f5..6c24777 100644
@@ -1,7 +1,7 @@
 		     ThinkPad ACPI Extras Driver
 
-                            Version 0.18
-                         October 08th, 2007
+                            Version 0.19
+                         January 06th, 2008
 
                Borislav Deianov <[email protected]>
              Henrique de Moraes Holschuh <[email protected]>
drivers/misc/thinkpad_acpi.c +1 -1
index 05f5329..8ef0afc 100644
@@ -21,7 +21,7 @@
  *  02110-1301, USA.
  */
 
-#define TPACPI_VERSION "0.18"
+#define TPACPI_VERSION "0.19"
 #define TPACPI_SYSFS_VERSION 0x020200
 
 /*
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#72 lore raw

PATCH 64/112 ACPI: Set _PSD ACPI_PDC_SMP_T_SWCOORD

In reply to Len Brown

From: Zhao Yakui <[email protected]>

The ACPI_PDC_SMP_T_SWCOORD bit is set by and OS that is capable of native ACPI throttling software coordination for mutli-processors using the _TSD information.

---
 arch/ia64/kernel/acpi-processor.c |    6 ++++++
 arch/x86/kernel/acpi/processor.c  |    6 ++++++
 2 files changed, 12 insertions(+), 0 deletions(-)
arch/ia64/kernel/acpi-processor.c +6 -0
index 5a216c0..cbe6cee 100644
@@ -45,6 +45,12 @@ static void init_intel_pdc(struct acpi_processor *pr)
 	buf[0] = ACPI_PDC_REVISION_ID;
 	buf[1] = 1;
 	buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
+	/*
+	 * The default of PDC_SMP_T_SWCOORD bit is set for IA64 cpu so
+	 * that OSPM is capable of native ACPI throttling software
+	 * coordination using BIOS supplied _TSD info.
+	 */
+	buf[2] |= ACPI_PDC_SMP_T_SWCOORD;
 
 	obj->type = ACPI_TYPE_BUFFER;
 	obj->buffer.length = 12;
arch/x86/kernel/acpi/processor.c +6 -0
index a25db51..324eb0c 100644
@@ -46,6 +46,12 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
 	buf[1] = 1;
 	buf[2] = ACPI_PDC_C_CAPABILITY_SMP;
 
+	/*
+	 * The default of PDC_SMP_T_SWCOORD bit is set for intel x86 cpu so
+	 * that OSPM is capable of native ACPI throttling software
+	 * coordination using BIOS supplied _TSD info.
+	 */
+	buf[2] |= ACPI_PDC_SMP_T_SWCOORD;
 	if (cpu_has(c, X86_FEATURE_EST))
 		buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP;
 
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#73 lore raw

PATCH 65/112 ACPI : Check parameter when calling acpi_processor_get/set_throttling

In reply to Len Brown

From: Zhao Yakui <[email protected]>

It is necessary to check the parameter when calling the function of acpi_processor_get/set_throttling function so as to avoid the NULL pointer reference in pr or throttling.

http://bugzilla.kernel.org/show_bug.cgi?id=9747

---
 drivers/acpi/processor_throttling.c |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)
drivers/acpi/processor_throttling.c +15 -0
index 1685b40..5d2eae2 100644
@@ -589,6 +589,11 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)
 	cpumask_t saved_mask;
 	int ret;
 
+	if (!pr)
+		return -EINVAL;
+
+	if (!pr->flags.throttling)
+		return -ENODEV;
 	/*
 	 * Migrate task to the cpu pointed by pr.
 	 */
@@ -743,6 +748,16 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
 {
 	cpumask_t saved_mask;
 	int ret;
+
+	if (!pr)
+		return -EINVAL;
+
+	if (!pr->flags.throttling)
+		return -ENODEV;
+
+	if ((state < 0) || (state > (pr->throttling.state_count - 1)))
+		return -EINVAL;
+
 	/*
 	 * Migrate task to the cpu pointed by pr.
 	 */
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#74 lore raw

PATCH 66/112 ACPI : Update T-state coordination after getting _TSD info

In reply to Len Brown

From: Zhao Yakui <[email protected]>

Accordint to ACPI spec, the _TSD object provides T-state control cross logical processor dependency information to OSPM.
After the _TSD data for all cpus are obtained, OSPM will set up the T-state coordination between CPUs.

Of course if the _TSD doesn't exist or _TSD data is incorrect , it is assumed that there is no T-state coordination and T-state is changed independently.

Now there is no proper solution to update T-state coordination after one cpu is hotplugged. So this patch won't support hotplugged cpu very well.

---
 drivers/acpi/processor_core.c       |    2 +
 drivers/acpi/processor_throttling.c |  180 ++++++++++++++++++++++++++++++++++-
 include/acpi/processor.h            |    4 +-
 3 files changed, 184 insertions(+), 2 deletions(-)
drivers/acpi/processor_core.c +2 -0
index e48ee4f..b3b5373 100644
@@ -1061,6 +1061,8 @@ static int __init acpi_processor_init(void)
 
 	acpi_processor_ppc_init();
 
+	acpi_processor_throttling_init();
+
 	return 0;
 
 out_cpuidle:
drivers/acpi/processor_throttling.c +179 -1

210 lines not on this page · raw message

include/acpi/processor.h +3 -1
index 76411b1..d90ad0d 100644
@@ -176,6 +176,8 @@ struct acpi_processor_throttling {
 	u32 address;
 	u8 duty_offset;
 	u8 duty_width;
+	u8 tsd_valid_flag;
+	unsigned int shared_type;
 	struct acpi_processor_tx states[ACPI_PROCESSOR_MAX_THROTTLING];
 };
 
@@ -316,7 +318,7 @@ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
 int acpi_processor_get_throttling_info(struct acpi_processor *pr);
 extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
 extern struct file_operations acpi_processor_throttling_fops;
-
+extern void acpi_processor_throttling_init(void);
 /* in processor_idle.c */
 int acpi_processor_power_init(struct acpi_processor *pr,
 			      struct acpi_device *device);
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#52 lore raw

PATCH 52/112 ACPI: video: Rationalise ACPI backlight implementation

In reply to Len Brown

From: Matthew Garrett <[email protected]>

The sysfs backlight class provides no mechanism for querying the acceptable brightness for a backlight. The ACPI spec states that values are only valid if they are reported as available by the firmware. Since we can't provide that information to userspace, instead collapse the range to the number of actual values that can be set.

http://bugzilla.kernel.org/show_bug.cgi?id=9277

---
 drivers/acpi/video.c |   20 +++++++++++++-------
 1 files changed, 13 insertions(+), 7 deletions(-)
drivers/acpi/video.c +13 -7
index bd77e81..59639c9 100644
@@ -292,18 +292,26 @@ static int acpi_video_device_set_state(struct acpi_video_device *device, int sta
 static int acpi_video_get_brightness(struct backlight_device *bd)
 {
 	unsigned long cur_level;
+	int i;
 	struct acpi_video_device *vd =
 		(struct acpi_video_device *)bl_get_data(bd);
 	acpi_video_device_lcd_get_level_current(vd, &cur_level);
-	return (int) cur_level;
+	for (i = 2; i < vd->brightness->count; i++) {
+		if (vd->brightness->levels[i] == cur_level)
+			/* The first two entries are special - see page 575
+			   of the ACPI spec 3.0 */
+			return i-2;
+	}
+	return 0;
 }
 
 static int acpi_video_set_brightness(struct backlight_device *bd)
 {
-	int request_level = bd->props.brightness;
+	int request_level = bd->props.brightness+2;
 	struct acpi_video_device *vd =
 		(struct acpi_video_device *)bl_get_data(bd);
-	acpi_video_device_lcd_set_level(vd, request_level);
+	acpi_video_device_lcd_set_level(vd,
+					vd->brightness->levels[request_level]);
 	return 0;
 }
 
@@ -652,7 +660,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 	kfree(obj);
 
 	if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){
-		unsigned long tmp;
 		static int count = 0;
 		char *name;
 		name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
@@ -660,11 +667,10 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 			return;
 
 		sprintf(name, "acpi_video%d", count++);
-		acpi_video_device_lcd_get_level_current(device, &tmp);
 		device->backlight = backlight_device_register(name,
 			NULL, device, &acpi_backlight_ops);
-		device->backlight->props.max_brightness = max_level;
-		device->backlight->props.brightness = (int)tmp;
+		device->backlight->props.max_brightness = device->brightness->count-3;
+		device->backlight->props.brightness = acpi_video_get_brightness(device->backlight);
 		backlight_update_status(device->backlight);
 
 		kfree(name);
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#53 lore raw

PATCH 53/112 the generic thermal sysfs driver

In reply to Len Brown

From: Zhang Rui <[email protected]>

The Generic Thermal sysfs driver for thermal management.

---
 Documentation/thermal/sysfs-api.txt |  246 ++++++++++++
 drivers/Kconfig                     |    2 +
 drivers/Makefile                    |    1 +
 drivers/thermal/Kconfig             |   15 +
 drivers/thermal/Makefile            |    5 +
 drivers/thermal/thermal.c           |  714 +++++++++++++++++++++++++++++++++++
 include/linux/thermal.h             |   90 +++++
 7 files changed, 1073 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/thermal/sysfs-api.txt
 create mode 100644 drivers/thermal/Kconfig
 create mode 100644 drivers/thermal/Makefile
 create mode 100644 drivers/thermal/thermal.c
 create mode 100644 include/linux/thermal.h
Documentation/thermal/sysfs-api.txt new file +246 -0
new file mode 100644
index 0000000..5776e09
@@ -0,0 +1,246 @@
+Generic Thermal Sysfs driver How To
+=========================
+
+Written by Sujith Thomas <[email protected]>, Zhang Rui <[email protected]>
+
+Updated: 2 January 2008
+
+Copyright (c)  2008 Intel Corporation
+
+
+0. Introduction
+
+The generic thermal sysfs provides a set of interfaces for thermal zone devices (sensors)
+and thermal cooling devices (fan, processor...) to register with the thermal management
+solution and to be a part of it.
+
+This how-to focusses on enabling new thermal zone and cooling devices to participate
+in thermal management.
+This solution is platform independent and any type of thermal zone devices and
+cooling devices should be able to make use of the infrastructure.
+
+The main task of the thermal sysfs driver is to expose thermal zone attributes as well
+as cooling device attributes to the user space.
+An intelligent thermal management application can make decisions based on inputs
+from thermal zone attributes (the current temperature and trip point temperature)
+and throttle appropriate devices.
+
+[0-*]	denotes any positive number starting from 0
+[1-*]	denotes any positive number starting from 1
+
+1. thermal sysfs driver interface functions
+
+1.1 thermal zone device interface
+1.1.1 struct thermal_zone_device *thermal_zone_device_register(char *name, int trips,
+				void *devdata, struct thermal_zone_device_ops *ops)
+
+	This interface function adds a new thermal zone device (sensor) to
+	/sys/class/thermal folder as thermal_zone[0-*].
+	It tries to bind all the thermal cooling devices registered at the same time.
+
+	name: the thermal zone name.
+	trips: the total number of trip points this thermal zone supports.
+	devdata: device private data
+	ops: thermal zone device callbacks.
+		.bind: bind the thermal zone device with a thermal cooling device.
+		.unbind: unbing the thermal zone device with a thermal cooling device.
+		.get_temp: get the current temperature of the thermal zone.
+		.get_mode: get the current mode (user/kernel) of the thermal zone.
+			   "kernel" means thermal management is done in kernel.
+			   "user" will prevent kernel thermal driver actions upon trip points
+			   so that user applications can take charge of thermal management.
+		.set_mode: set the mode (user/kernel) of the thermal zone.
+		.get_trip_type: get the type of certain trip point.
+		.get_trip_temp: get the temperature above which the certain trip point
+				will be fired.
+
+1.1.2 void thermal_zone_device_unregister(struct thermal_zone_device *tz)
+
+	This interface function removes the thermal zone device.
+	It deletes the corresponding entry form /sys/class/thermal folder and unbind all
+	the thermal cooling devices it uses.
+
+1.2 thermal cooling device interface
+1.2.1 struct thermal_cooling_device *thermal_cooling_device_register(char *name,
+					void *devdata, struct thermal_cooling_device_ops *)
+
+	This interface function adds a new thermal cooling device (fan/processor/...) to
+	/sys/class/thermal/ folder as cooling_device[0-*].
+	It tries to bind itself to all the thermal zone devices register at the same time.
+	name: the cooling device name.
+	devdata: device private data.
+	ops: thermal cooling devices callbacks.
+		.get_max_state: get the Maximum throttle state of the cooling device.
+		.get_cur_state: get the Current throttle state of the cooling device.
+		.set_cur_state: set the Current throttle state of the cooling device.
+
+1.2.2 void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
+
+	This interface function remove the thermal cooling device.
+	It deletes the corresponding entry form /sys/class/thermal folder and unbind
+	itself from all	the thermal zone devices using it.
+
+1.3 interface for binding a thermal zone device with a thermal cooling device
+1.3.1 int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
+			int trip, struct thermal_cooling_device *cdev);
+
+	This interface function bind a thermal cooling device to the certain trip point
+	of a thermal zone device.
+	This function is usually called in the thermal zone device .bind callback.
+	tz: the thermal zone device
+	cdev: thermal cooling device
+	trip: indicates which trip point the cooling devices is associated with
+		 in this thermal zone.
+
+1.3.2 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
+				int trip, struct thermal_cooling_device *cdev);
+
+	This interface function unbind a thermal cooling device from the certain trip point
+	of a thermal zone device.
+	This function is usually called in the thermal zone device .unbind callback.
+	tz: the thermal zone device
+	cdev: thermal cooling device
+	trip: indicates which trip point the cooling devices is associated with
+		in this thermal zone.
+
+2. sysfs attributes structure
+
+RO	read only value
+RW	read/write value
+
+All thermal sysfs attributes will be represented under /sys/class/thermal
+/sys/class/thermal/
+
+Thermal zone device sys I/F, created once it's registered:
+|thermal_zone[0-*]:
+	|-----type:			Type of the thermal zone
+	|-----temp:			Current temperature
+	|-----mode:			Working mode of the thermal zone
+	|-----trip_point_[0-*]_temp:	Trip point temperature
+	|-----trip_point_[0-*]_type:	Trip point type
+
+Thermal cooling device sys I/F, created once it's registered:
+|cooling_device[0-*]:
+	|-----type :			Type of the cooling device(processor/fan/...)
+	|-----max_state:		Maximum cooling state of the cooling device
+	|-----cur_state:		Current cooling state of the cooling device
+
+
+These two dynamic attributes are created/removed in pairs.
+They represent the relationship between a thermal zone and its associated cooling device.
+They are created/removed for each
+thermal_zone_bind_cooling_device/thermal_zone_unbind_cooling_device successful exection.
+
+|thermal_zone[0-*]
+	|-----cdev[0-*]:		The [0-*]th cooling device in the current thermal zone
+	|-----cdev[0-*]_trip_point:	Trip point that cdev[0-*] is associated with
+
+
+***************************
+* Thermal zone attributes *
+***************************
+
+type				Strings which represent the thermal zone type.
+				This is given by thermal zone driver as part of registration.
+				Eg: "ACPI thermal zone" indicates it's a ACPI thermal device
+				RO
+				Optional
+
+temp				Current temperature as reported by thermal zone (sensor)
+				Unit: degree celsius
+				RO
+				Required
+
+mode				One of the predifned values in [kernel, user]
+				This file gives information about the algorithm
+				that is currently managing the thermal zone.
+				It can be either default kernel based algorithm
+				or user space application.
+				RW
+				Optional
+				kernel	= Thermal management in kernel thermal zone driver.
+				user	= Preventing kernel thermal zone driver actions upon
+					  trip points so that user application can take full
+					  charge of the thermal management.
+
+trip_point_[0-*]_temp		The temperature above which trip point will be fired
+				Unit: degree celsius
+				RO
+				Optional
+
+trip_point_[0-*]_type 		Strings which indicate the type of the trip point
+				Eg. it can be one of critical, hot, passive,
+				    active[0-*] for ACPI thermal zone.
+				RO
+				Optional
+
+cdev[0-*]			Sysfs link to the thermal cooling device node where the sys I/F
+				for cooling device throttling control represents.
+				RO
+				Optional
+
+cdev[0-*]_trip_point		The trip point with which cdev[0-*] is assocated in this thermal zone
+				-1 means the cooling device is not associated with any trip point.
+				RO
+				Optional
+
+******************************
+* Cooling device  attributes *
+******************************
+
+type				String which represents the type of device
+				eg: For generic ACPI: this should be "Fan",
+				"Processor" or "LCD"
+				eg. For memory controller device on intel_menlow platform:
+				this should be "Memory controller"
+				RO
+				Optional
+
+max_state			The maximum permissible cooling state of this cooling device.
+				RO
+				Required
+
+cur_state			The current cooling state of this cooling device.
+				the value can any integer numbers between 0 and max_state,
+				cur_state == 0 means no cooling
+				cur_state == max_state means the maximum cooling.
+				RW
+				Required
+
+3. A simple implementation
+
+ACPI thermal zone may support multiple trip points like critical/hot/passive/active.
+If an ACPI thermal zone supports critical, passive, active[0] and active[1] at the same time,
+it may register itself as a thermale_zone_device (thermal_zone1) with 4 trip points in all.
+It has one processor and one fan, which are both registered as thermal_cooling_device.
+If the processor is listed in _PSL method, and the fan is listed in _AL0 method,
+the sys I/F structure will be built like this:
+
+/sys/class/thermal:
+
+|thermal_zone1:
+	|-----type:			ACPI thermal zone
+	|-----temp:			37
+	|-----mode:			kernel
+	|-----trip_point_0_temp:	100
+	|-----trip_point_0_type:	critical
+	|-----trip_point_1_temp:	80
+	|-----trip_point_1_type:	passive
+	|-----trip_point_2_temp:	70
+	|-----trip_point_2_type:	active[0]
+	|-----trip_point_3_temp:	60
+	|-----trip_point_3_type:	active[1]
+	|-----cdev0:			--->/sys/class/thermal/cooling_device0
+	|-----cdev0_trip_point:		1	/* cdev0 can be used for passive */
+	|-----cdev1:			--->/sys/class/thermal/cooling_device3
+	|-----cdev1_trip_point:		2	/* cdev1 can be used for active[0]*/
+
+|cooling_device0:
+	|-----type:			Processor
+	|-----max_state:		8
+	|-----cur_state:		0
+
+|cooling_device3:
+	|-----type:			Fan
+	|-----max_state:		2
+	|-----cur_state:		0
drivers/Kconfig +2 -0
index 08d4ae2..8e238cf 100644
@@ -58,6 +58,8 @@ source "drivers/power/Kconfig"
 
 source "drivers/hwmon/Kconfig"
 
+source "drivers/thermal/Kconfig"
+
 source "drivers/watchdog/Kconfig"
 
 source "drivers/ssb/Kconfig"
drivers/Makefile +1 -0
index 0ee9a8a..a516b8b 100644
@@ -64,6 +64,7 @@ obj-y				+= i2c/
 obj-$(CONFIG_W1)		+= w1/
 obj-$(CONFIG_POWER_SUPPLY)	+= power/
 obj-$(CONFIG_HWMON)		+= hwmon/
+obj-$(CONFIG_THERMAL)		+= thermal/
 obj-$(CONFIG_WATCHDOG)		+= watchdog/
 obj-$(CONFIG_PHONE)		+= telephony/
 obj-$(CONFIG_MD)		+= md/
drivers/thermal/Kconfig new file +15 -0
new file mode 100644
index 0000000..9b3f612
@@ -0,0 +1,15 @@
+#
+# Generic thermal sysfs drivers configuration
+#
+
+menuconfig THERMAL
+	bool "Generic Thermal sysfs driver"
+	default y
+	help
+	  Generic Thermal Sysfs driver offers a generic mechanism for
+	  thermal management. Usually it's made up of one or more thermal
+	  zone and cooling device.
+	  each thermal zone contains its own temperature, trip points,
+	  cooling devices.
+	  All platforms with ACPI thermal support can use this driver.
+	  If you want this support, you should say Y here
drivers/thermal/Makefile new file +5 -0
new file mode 100644
index 0000000..8ef1232
@@ -0,0 +1,5 @@
+#
+# Makefile for sensor chip drivers.
+#
+
+obj-$(CONFIG_THERMAL)		+= thermal.o
drivers/thermal/thermal.c new file +714 -0

714 lines not on this page · raw message

include/linux/thermal.h new file +90 -0

90 lines not on this page · raw message

Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#61 lore raw

PATCH 54/112 ACPI: register ACPI thermal zone as generic thermal zone devices

In reply to Len Brown

From: Zhang Rui <[email protected]>

Register ACPI thermal zone as thermal zone device.

the new sys I/F for ACPI thermal zone will be like this:

/sys/class/thermal:
|thermal_zone1:

	|-----type:			"ACPI thermal zone". RO
	|-----temp:			the current temperature. RO
	|-----mode:			the current working mode. RW.

the default value is "kernel" which means thermal management is done by ACPI thermal driver. "echo user > mode" prevents all the ACPI thermal driver actions upon any trip points.
|-----trip_point_0_temp: the threshold of trip point 0. RO.
|-----trip_point_0_type: "critical". RO.
the type of trip point 0
This may be one of critical/hot/passive/active[x] for an ACPI thermal zone.
...
|-----trip_point_3_temp:
|-----trip_point_3_type: "active[1]"

---
 drivers/acpi/Kconfig   |    1 +
 drivers/acpi/thermal.c |  301 ++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 292 insertions(+), 10 deletions(-)
drivers/acpi/Kconfig +1 -0
index ccf6ea9..5583729 100644
@@ -186,6 +186,7 @@ config ACPI_HOTPLUG_CPU
 config ACPI_THERMAL
 	tristate "Thermal Zone"
 	depends on ACPI_PROCESSOR
+	select THERMAL
 	default y
 	help
 	  This driver adds support for ACPI thermal zones.  Most mobile and
drivers/acpi/thermal.c +291 -10

354 lines not on this page · raw message

Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#75 lore raw

PATCH 67/112 ACPI : Add T-state event notifier function

In reply to Len Brown

From: Zhao Yakui <[email protected]>

The t-state coordination should be considered when T-state for one cpu is changed.It means that OSPM should select one proper target T-state for the all affected cpus before updating T-state.

So the function of acpi_processor_throttling_notifier is added. Before updating T-state it can be called for all the affected cpus to get the proper target T-state, which can meet the requirement of thermal, user and _TPC. After updating T-state, it can be called to update T-state flag.

---
 drivers/acpi/processor_throttling.c |   72 +++++++++++++++++++++++++++++++++++
 1 files changed, 72 insertions(+), 0 deletions(-)
drivers/acpi/processor_throttling.c +72 -0
index d6780f4..18a873a 100644
@@ -45,6 +45,14 @@
 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
 ACPI_MODULE_NAME("processor_throttling");
 
+struct throttling_tstate {
+	unsigned int cpu;		/* cpu nr */
+	int target_state;		/* target T-state */
+};
+
+#define THROTTLING_PRECHANGE       (1)
+#define THROTTLING_POSTCHANGE      (2)
+
 static int acpi_processor_get_throttling(struct acpi_processor *pr);
 int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
 
@@ -196,6 +204,70 @@ void acpi_processor_throttling_init(void)
 	return;
 }
 
+static int acpi_processor_throttling_notifier(unsigned long event, void *data)
+{
+	struct throttling_tstate *p_tstate = data;
+	struct acpi_processor *pr;
+	unsigned int cpu ;
+	int target_state;
+	struct acpi_processor_limit *p_limit;
+	struct acpi_processor_throttling *p_throttling;
+
+	cpu = p_tstate->cpu;
+	pr = processors[cpu];
+	if (!pr) {
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid pr pointer\n"));
+		return 0;
+	}
+	if (!pr->flags.throttling) {
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Throttling control is "
+				"unsupported on CPU %d\n", cpu));
+		return 0;
+	}
+	target_state = p_tstate->target_state;
+	p_throttling = &(pr->throttling);
+	switch (event) {
+	case THROTTLING_PRECHANGE:
+		/*
+		 * Prechange event is used to choose one proper t-state,
+		 * which meets the limits of thermal, user and _TPC.
+		 */
+		p_limit = &pr->limit;
+		if (p_limit->thermal.tx > target_state)
+			target_state = p_limit->thermal.tx;
+		if (p_limit->user.tx > target_state)
+			target_state = p_limit->user.tx;
+		if (pr->throttling_platform_limit > target_state)
+			target_state = pr->throttling_platform_limit;
+		if (target_state >= p_throttling->state_count) {
+			printk(KERN_WARNING
+				"Exceed the limit of T-state \n");
+			target_state = p_throttling->state_count - 1;
+		}
+		p_tstate->target_state = target_state;
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PreChange Event:"
+				"target T-state of CPU %d is T%d\n",
+				cpu, target_state));
+		break;
+	case THROTTLING_POSTCHANGE:
+		/*
+		 * Postchange event is only used to update the
+		 * T-state flag of acpi_processor_throttling.
+		 */
+		p_throttling->state = target_state;
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PostChange Event:"
+				"CPU %d is switched to T%d\n",
+				cpu, target_state));
+		break;
+	default:
+		printk(KERN_WARNING
+			"Unsupported Throttling notifier event\n");
+		break;
+	}
+
+	return 0;
+}
+
 /*
  * _TPC - Throttling Present Capabilities
  */
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#76 lore raw

PATCH 68/112 ACPI: Update the t-state for every affected cpu when t-state is changed

In reply to Len Brown

From: Zhao Yakui <[email protected]>

According to ACPI spec, the _TSD object provides T-state control cross logical processor dependency information to OSPM. So the t-state coordination should be considered when T-state for one cpu is changed.

According to ACPI spec, three types of coordination are defined. SW_ALL, SW_ANY and HW_ALL.

SW_ALL: it means that OSPM needs to initiate T-state transition on all processors in the domain. It is necessary to call throttling set function for all affected cpus.

SW_ANY: it means that OSPM may initiate T-state transition on any processor in the domain.

HW_ALL: Spec only says that hardware will perform the coordination and doesn't recommend how OSPM coordinate T-state among the affected cpus. So it is treated as the type of SW_ALL. It means that OSPM needs to initiate t-state transition on all the processors in the domain.

---
 drivers/acpi/processor_throttling.c |   79 ++++++++++++++++++++++++++++++++--
 1 files changed, 74 insertions(+), 5 deletions(-)
drivers/acpi/processor_throttling.c +74 -5
index 18a873a..86c790e 100644
@@ -68,7 +68,7 @@ static int acpi_processor_update_tsd_coord(void)
 
 	/*
 	 * Now that we have _TSD data from all CPUs, lets setup T-state
-	 * coordination among all CPUs.
+	 * coordination between all CPUs.
 	 */
 	for_each_possible_cpu(i) {
 		pr = processors[i];
@@ -988,6 +988,11 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
 {
 	cpumask_t saved_mask;
 	int ret;
+	unsigned int i;
+	struct acpi_processor *match_pr;
+	struct acpi_processor_throttling *p_throttling;
+	struct throttling_tstate t_state;
+	cpumask_t online_throttling_cpus;
 
 	if (!pr)
 		return -EINVAL;
@@ -998,12 +1003,76 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
 	if ((state < 0) || (state > (pr->throttling.state_count - 1)))
 		return -EINVAL;
 
+	saved_mask = current->cpus_allowed;
+	t_state.target_state = state;
+	p_throttling = &(pr->throttling);
+	cpus_and(online_throttling_cpus, cpu_online_map,
+			p_throttling->shared_cpu_map);
 	/*
-	 * Migrate task to the cpu pointed by pr.
+	 * The throttling notifier will be called for every
+	 * affected cpu in order to get one proper T-state.
+	 * The notifier event is THROTTLING_PRECHANGE.
 	 */
-	saved_mask = current->cpus_allowed;
-	set_cpus_allowed(current, cpumask_of_cpu(pr->id));
-	ret = pr->throttling.acpi_processor_set_throttling(pr, state);
+	for_each_cpu_mask(i, online_throttling_cpus) {
+		t_state.cpu = i;
+		acpi_processor_throttling_notifier(THROTTLING_PRECHANGE,
+							&t_state);
+	}
+	/*
+	 * The function of acpi_processor_set_throttling will be called
+	 * to switch T-state. If the coordination type is SW_ALL or HW_ALL,
+	 * it is necessary to call it for every affected cpu. Otherwise
+	 * it can be called only for the cpu pointed by pr.
+	 */
+	if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
+		set_cpus_allowed(current, cpumask_of_cpu(pr->id));
+		ret = p_throttling->acpi_processor_set_throttling(pr,
+						t_state.target_state);
+	} else {
+		/*
+		 * When the T-state coordination is SW_ALL or HW_ALL,
+		 * it is necessary to set T-state for every affected
+		 * cpus.
+		 */
+		for_each_cpu_mask(i, online_throttling_cpus) {
+			match_pr = processors[i];
+			/*
+			 * If the pointer is invalid, we will report the
+			 * error message and continue.
+			 */
+			if (!match_pr) {
+				ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+					"Invalid Pointer for CPU %d\n", i));
+				continue;
+			}
+			/*
+			 * If the throttling control is unsupported on CPU i,
+			 * we will report the error message and continue.
+			 */
+			if (!match_pr->flags.throttling) {
+				ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+					"Throttling Controll is unsupported "
+					"on CPU %d\n", i));
+				continue;
+			}
+			t_state.cpu = i;
+			set_cpus_allowed(current, cpumask_of_cpu(i));
+			ret = match_pr->throttling.
+				acpi_processor_set_throttling(
+				match_pr, t_state.target_state);
+		}
+	}
+	/*
+	 * After the set_throttling is called, the
+	 * throttling notifier is called for every
+	 * affected cpu to update the T-states.
+	 * The notifier event is THROTTLING_POSTCHANGE
+	 */
+	for_each_cpu_mask(i, online_throttling_cpus) {
+		t_state.cpu = i;
+		acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE,
+							&t_state);
+	}
 	/* restore the previous state */
 	set_cpus_allowed(current, saved_mask);
 	return ret;
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#77 lore raw

PATCH 69/112 ACPI: throttling: fix build warning

In reply to Len Brown

From: Len Brown <[email protected]>

---
 drivers/acpi/processor_throttling.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/acpi/processor_throttling.c +1 -1
index 86c790e..1b8e592 100644
@@ -987,7 +987,7 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
 int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
 {
 	cpumask_t saved_mask;
-	int ret;
+	int ret = 0;
 	unsigned int i;
 	struct acpi_processor *match_pr;
 	struct acpi_processor_throttling *p_throttling;
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#78 lore raw

PATCH 70/112 ACPI: fan: build fix for CONFIG_ACPI_PROCFS=n

In reply to Len Brown

From: Len Brown <[email protected]>

drivers/acpi/fan.c:340: error: ‘acpi_fan_dir’ undeclared (first use in this function)

---
 drivers/acpi/fan.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/acpi/fan.c +2 -0
index f6e8165..48cb705 100644
@@ -337,10 +337,12 @@ static int __init acpi_fan_init(void)
 	int result = 0;
 
 
+#ifdef CONFIG_ACPI_PROCFS
 	acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);
 	if (!acpi_fan_dir)
 		return -ENODEV;
 	acpi_fan_dir->owner = THIS_MODULE;
+#endif
 
 	result = acpi_bus_register_driver(&acpi_fan_driver);
 	if (result < 0) {
Signature · 6 lines
1.5.4.23.gef5b9

-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
author reviewer
#79 lore raw

PATCH 71/112 ACPI: remove redundant Acer blacklist entry

In reply to Len Brown

From: Len Brown <[email protected]>

dmi_check_system() does sub-string matching using strstr(), rather than exact string compares with !strcmp().

So delete the longer of the Acer blacklist entries, as its function is just a redundant console message.

---
 drivers/acpi/blacklist.c |   12 +++++-------
 1 files changed, 5 insertions(+), 7 deletions(-)
drivers/acpi/blacklist.c +5 -7
index 8809654..9ace219 100644
@@ -214,13 +214,11 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
 	 * _OSI(Linux) effect unknown:
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "Ferrari 5000"),
 	 */
-	{
-	.callback = dmi_disable_osi_linux,
-	.ident = "Acer, inc.",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "Acer, inc."),
-		},
-	},
+	/*
+	 * note that dmi_check_system() uses strstr()
+	 * to match sub-strings rather than !strcmp(),
+	 * so "Acer" below matches "Acer, inc." above.
+	 */
 	/*
 	 * Disable OSI(Linux) warnings on all "Acer"
 	 *
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#80 lore raw

PATCH 72/112 DMI: remove duplicate helper routine

In reply to Len Brown

From: Len Brown <[email protected]>

Use existing dmi_get_system_info(),
Delete duplicate dmi_get_slot()

---
 drivers/acpi/osl.c          |   12 ++++++------
 drivers/firmware/dmi_scan.c |    9 ---------
 include/linux/dmi.h         |    2 --
 3 files changed, 6 insertions(+), 17 deletions(-)
drivers/acpi/osl.c +6 -6
index e53fb51..347cda2 100644
@@ -1220,17 +1220,17 @@ int acpi_dmi_dump(void)
 		return -1;
 
 	printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n",
-		dmi_get_slot(DMI_SYS_VENDOR));
+		dmi_get_system_info(DMI_SYS_VENDOR));
 	printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n",
-		dmi_get_slot(DMI_PRODUCT_NAME));
+		dmi_get_system_info(DMI_PRODUCT_NAME));
 	printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n",
-		dmi_get_slot(DMI_PRODUCT_VERSION));
+		dmi_get_system_info(DMI_PRODUCT_VERSION));
 	printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n",
-		dmi_get_slot(DMI_BOARD_NAME));
+		dmi_get_system_info(DMI_BOARD_NAME));
 	printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n",
-		dmi_get_slot(DMI_BIOS_VENDOR));
+		dmi_get_system_info(DMI_BIOS_VENDOR));
 	printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n",
-		dmi_get_slot(DMI_BIOS_DATE));
+		dmi_get_system_info(DMI_BIOS_DATE));
 
 	return 0;
 }
drivers/firmware/dmi_scan.c +0 -9
index 9008ed5..e0bade7 100644
@@ -489,12 +489,3 @@ int dmi_get_year(int field)
 
 	return year;
 }
-
-/**
- *	dmi_get_slot - return dmi_ident[slot]
- *	@slot:	index into dmi_ident[]
- */
-char *dmi_get_slot(int slot)
-{
-	return(dmi_ident[slot]);
-}
include/linux/dmi.h +0 -2
index 5b42a65..b1251b2 100644
@@ -79,7 +79,6 @@ extern void dmi_scan_machine(void);
 extern int dmi_get_year(int field);
 extern int dmi_name_in_vendors(const char *str);
 extern int dmi_available;
-extern char *dmi_get_slot(int slot);
 
 #else
 
@@ -90,7 +89,6 @@ static inline const struct dmi_device * dmi_find_device(int type, const char *na
 static inline int dmi_get_year(int year) { return 0; }
 static inline int dmi_name_in_vendors(const char *s) { return 0; }
 #define dmi_available 0
-static inline char *dmi_get_slot(int slot) { return NULL; }
 
 #endif
 
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#81 lore raw

PATCH 73/112 ACPI: update blacklist comments

In reply to Len Brown

From: Len Brown <[email protected]>

...based on additional feedback -- no code change.

---
 drivers/acpi/blacklist.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)
drivers/acpi/blacklist.c +9 -2
index 9ace219..bd12c8e 100644
@@ -208,7 +208,9 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
 	 * Disable OSI(Linux) warnings on all "Acer, inc."
 	 *
 	 * _OSI(Linux) disables the latest Windows BIOS code:
+	 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3100"),
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5050"),
+	 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5580"),
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 3010"),
 	 * _OSI(Linux) effect unknown:
@@ -223,7 +225,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
 	 * Disable OSI(Linux) warnings on all "Acer"
 	 *
 	 * _OSI(Linux) effect unknown:
-	 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
+	 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"),
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720Z"),
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5520"),
@@ -298,7 +300,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
 		     DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
 		},
 	},
-	{ /* OSI(Linux) touches USB, breaks suspend to disk */
+	{ /* OSI(Linux) touches USB, unknown side-effect */
 	.callback = dmi_disable_osi_linux,
 	.ident = "Dell Dimension 5150",
 	.matches = {
@@ -472,6 +474,11 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
 	 *
 	 * _OSI(Linux) confirmed to be a NOP:
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "P1-J150B"),
+	 * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"),
+	 *
+	 * unknown:
+	 * DMI_MATCH(DMI_PRODUCT_NAME, "S1-MDGDG"),
+	 * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"),
 	 */
 	{
 	.callback = dmi_disable_osi_linux,
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#82 lore raw

PATCH 74/112 ACPI: make acpi_dmi_dump() static

In reply to Len Brown

From: Adrian Bunk <[email protected]>

---
 drivers/acpi/osl.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/acpi/osl.c +1 -1
index 347cda2..71b0c32 100644
@@ -1213,7 +1213,7 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
  *
  *	Returns 0 on success
  */
-int acpi_dmi_dump(void)
+static int acpi_dmi_dump(void)
 {
 
 	if (!dmi_available)
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#83 lore raw

PATCH 75/112 ACPI: make struct osi_linux static

In reply to Len Brown

From: Adrian Bunk <[email protected]>

---
 drivers/acpi/osl.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/acpi/osl.c +1 -1
index 71b0c32..fde7ac8 100644
@@ -120,7 +120,7 @@ static char osi_additional_string[OSI_STRING_LENGTH_MAX];
  */
 #define OSI_LINUX_ENABLE 0
 
-struct osi_linux {
+static struct osi_linux {
 	unsigned int	enable:1;
 	unsigned int	dmi:1;
 	unsigned int	cmdline:1;
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#84 lore raw

PATCH 76/112 ACPI: blacklist update

In reply to Len Brown

From: Len Brown <[email protected]>

move some OSI(Linux) to "disable" from "unknown"
to reduce dmesg lines that we don't really need.

update Acer 5315 comment
update Dell entries, add R200 entry
update Apple entries

---
 drivers/acpi/blacklist.c |   37 +++++++++++++++++++++++--------------
 1 files changed, 23 insertions(+), 14 deletions(-)
drivers/acpi/blacklist.c +23 -14
index bd12c8e..6dbaa2d 100644
@@ -70,8 +70,6 @@ static struct acpi_blacklist_item acpi_blacklist[] __initdata = {
 	/* IBM 600E - _ADR should return 7, but it returns 1 */
 	{"IBM   ", "TP600E  ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal,
 	 "Incorrect _ADR", 1},
-	{"ASUS\0\0", "P2B-S   ", 0, ACPI_SIG_DSDT, all_versions,
-	 "Bogus PCI routing", 1},
 
 	{""}
 };
@@ -225,16 +223,18 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
 	 * Disable OSI(Linux) warnings on all "Acer"
 	 *
 	 * _OSI(Linux) effect unknown:
-	 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"),
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720Z"),
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5520"),
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 6460"),
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 7510"),
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5220"),
+	 *
+	 * _OSI(Linux) is a NOP:
+	 * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"),
 	 */
 	{
-	.callback = dmi_unknown_osi_linux,
+	.callback = dmi_disable_osi_linux,
 	.ident = "Acer",
 	.matches = {
 		     DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -242,21 +242,22 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
 	},
 	/*
 	 * Disable OSI(Linux) warnings on all "Apple Computer, Inc."
+	 * Disable OSI(Linux) warnings on all "Apple Inc."
 	 *
 	 * _OSI(Linux) confirmed to be a NOP:
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"),
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"),
+	 * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
 	 * _OSI(Linux) effect unknown:
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "MacPro2,1"),
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"),
-	 * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
 	 */
 	{
 	.callback = dmi_disable_osi_linux,
 	.ident = "Apple",
 	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
+		     DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
 		},
 	},
 	/*
@@ -294,7 +295,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
 	 * DMI_MATCH(DMI_BOARD_NAME, "IFL91"),
 	 */
 	{
-	.callback = dmi_unknown_osi_linux,
+	.callback = dmi_disable_osi_linux,
 	.ident = "Compal",
 	.matches = {
 		     DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
@@ -310,7 +311,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
 	},
 	{ /* OSI(Linux) is a NOP */
 	.callback = dmi_disable_osi_linux,
-	.ident = "Dell",
+	.ident = "Dell i1501",
 	.matches = {
 		     DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 		     DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1501"),
@@ -318,7 +319,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
 	},
 	{ /* OSI(Linux) effect unknown */
 	.callback = dmi_unknown_osi_linux,
-	.ident = "Dell",
+	.ident = "Dell Latitude D830",
 	.matches = {
 		     DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 		     DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D830"),
@@ -326,7 +327,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
 	},
 	{ /* OSI(Linux) effect unknown */
 	.callback = dmi_unknown_osi_linux,
-	.ident = "Dell",
+	.ident = "Dell OP GX620",
 	.matches = {
 		     DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 		     DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX620"),
@@ -334,15 +335,23 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
 	},
 	{ /* OSI(Linux) effect unknown */
 	.callback = dmi_unknown_osi_linux,
-	.ident = "Dell",
+	.ident = "Dell PE 1900",
 	.matches = {
 		     DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 		     DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1900"),
 		},
 	},
+	{ /* OSI(Linux) is a NOP */
+	.callback = dmi_disable_osi_linux,
+	.ident = "Dell PE R200",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R200"),
+		},
+	},
 	{ /* OSI(Linux) touches USB */
 	.callback = dmi_disable_osi_linux,
-	.ident = "Dell",
+	.ident = "Dell PR 390",
 	.matches = {
 		     DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 		     DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 390"),
@@ -358,7 +367,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
 	},
 	{ /* OSI(Linux) effect unknown */
 	.callback = dmi_unknown_osi_linux,
-	.ident = "Dell",
+	.ident = "Dell PE SC440",
 	.matches = {
 		     DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 		     DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge SC440"),
@@ -521,7 +530,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
 	 * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ11M"),
 	 */
 	{
-	.callback = dmi_unknown_osi_linux,
+	.callback = dmi_disable_osi_linux,
 	.ident = "Sony",
 	.matches = {
 		     DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#85 lore raw

PATCH 77/112 ACPI: WMI: Add ACPI-WMI mapping driver

In reply to Len Brown

From: Carlos Corbacho <[email protected]>

The following is an implementation of the Windows Management Instrumentation (WMI) ACPI interface mapper (PNP0C14).

What it does:

Parses the _WDG method and exports functions to process WMI method calls, data block query/ set commands (both based on GUID) and does basic event handling.

How: WMI presents an in kernel interface here (essentially, a minimal wrapper around ACPI)

(const char *guid assume the 36 character ASCII representation of a GUID - e.g. 67C3371D-95A3-4C37-BB61-DD47B491DAAB)

wmi_evaluate_method(const char *guid, u8 instance, u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)

wmi_query_block(const char *guid, u8 instance,
struct acpi_buffer *out)

wmi_set_block(const char *guid, u38 instance,
const struct acpi_buffer *in)

wmi_install_notify_handler(acpi_notify_handler handler);

wmi_remove_notify_handler(void);

wmi_get_event_data(u32 event, struct acpi_buffer *out)

wmi_has_guid(const char guid*)

wmi_has_guid() is a helper function to find if a GUID exists or not on the system (a quick and easy way for WMI dependant drivers to see if the the method/ block they want exists, since GUIDs are supposed to be unique).

Event handling - allow a WMI based driver to register a notifier handler for each GUID with WMI. When a notification is sent to a GUID in WMI, the handler registered with WMI is then called (it is left to the caller to ask for the WMI event data associated with the GUID, if needed).

What it won't do:

Unicode - The MS article[1] calls for converting between ASCII and Unicode (or vice versa) if a GUID is marked as "string". This is left up to the calling driver.

Handle a MOF[1] - the WMI mapper just exports methods, data and events to userspace. MOF handling is down to userspace.

Userspace interface - this will be added later.

[1] http://www.microsoft.com/whdc/system/pnppwr/wmi/wmi-acpi.mspx

===
ChangeLog
==

v1 (2007-10-02):

* Initial release

v2 (2007-10-05):

* Cleaned up code - split up super "wmi_evaluate_block" -> each external symbol now handles its own ACPI calls, rather than handing off to a "super" method (and in turn, is a lot simpler to read)
* Added a find_guid() symbol - return true if a given GUID exists on the system
* wmi_* functions now return type acpi_status (since they are just fancy wrappers around acpi_evaluate_object())
* Removed extra debug code

v3 (2007-10-27)

* More code clean up - now passes checkpatch.pl
* Change data block calls - ref MS spec, method ID is not required for them, so drop it from the function parameters.
* Const'ify guid in the function call parameters.
* Fix _WDG buffer handling - copy the data to our own private structure.
* Change WMI from tristate to bool - otherwise the external functions are not exported in linux/acpi.h if you try to build WMI as a module.
* Fix more flag comparisons.
* Add a maintainers entry - since I wrote this, I should take the blame for it.

v4 (2007-10-30)

* Add missing brace from after fixing checkpatch errors.
* Rewrote event handling - allow external drivers to register with WMI to handle WMI events
* Clean up flags and sanitise flag handling

v5 (2007-11-03)

* Add sysfs interface for userspace. Export events over netlink again.
* Remove module left overs, fully convert to built-in driver.
* Tweak in-kernel API to use u8 for instance, since this is what the GUID blocks use (so instance cannot be greater than u8).
* Export wmi_get_event_data() for in kernel WMI drivers.

v6 (2007-11-07)

* Split out userspace into a different patch

v7 (2007-11-20)

* Fix driver to handle multiple PNP0C14 devices - store all GUIDs using the kernel's built in list functions, and just keep adding to the list every time we handle a PNP0C14 devices - GUIDs will always be unique, and WMI callers do not know or care about different devices.
* Change WMI event handler registration to use its' own event handling struct; we should not pass an acpi_handle down to any WMI based drivers
- they should be able to function with only the calls provided in WMI.
* Update my e-mail address

v8 (2007-11-28)

* Convert back to a module.
* Update Kconfig to default to building as a module.
* Remove an erroneous printk.
* Simply comments for string flag (since we now leave the handling to the caller).

v9 (2007-12-07)

* Add back missing MODULE_DEVICE_TABLE for autoloading
* Checkpatch fixes

v10 (2007-12-12)

* Workaround broken GUIDs declared expensive without a WCxx method.
* Minor cleanups

v11 (2007-12-17)

* More fixing for broken GUIDs declared expensive without a WCxx method.
* Add basic EmbeddedControl region handling.

v12 (2007-12-18)

* Changed EC region handling code, as per Alexey's comments.

v13 (2007-12-27)

* Changed event handling so that we can have one event handler registered per GUID, as per Matthew Garrett's suggestion.

v14 (2008-01-12)

* Remove ACPI debug statements

v15 (2008-02-01)

* Replace two remaining 'x == NULL' type tests with '!x'

v16 (2008-02-05)

* Change MAINTAINERS entry, as I am not, and never have been, paid to work on WMI
* Remove 'default' line from Kconfig

CC Matthew Garrett <[email protected]>
CC Alexey Starikovskiy <[email protected]>
---
 MAINTAINERS           |    7 +
 drivers/acpi/Kconfig  |   10 +
 drivers/acpi/Makefile |    1 +
 drivers/acpi/wmi.c    |  710 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/acpi.h  |   20 ++
 5 files changed, 748 insertions(+), 0 deletions(-)
 create mode 100644 drivers/acpi/wmi.c
MAINTAINERS +7 -0
index da30a72..12e26d7 100644
@@ -252,6 +252,13 @@ L:	[email protected]
 W:	http://acpi.sourceforge.net/
 S:	Supported
 
+ACPI WMI DRIVER
+P:      Carlos Corbacho
+M:      [email protected]
+L:      [email protected]
+W:      http://www.lesswatts.org/projects/acpi/
+S:      Maintained
+
 ADM1025 HARDWARE MONITOR DRIVER
 P:	Jean Delvare
 M:	[email protected]
drivers/acpi/Kconfig +10 -0
index ccf6ea9..f60cf6f 100644
@@ -199,6 +199,16 @@ config ACPI_NUMA
 	depends on (X86 || IA64)
 	default y if IA64_GENERIC || IA64_SGI_SN2
 
+config ACPI_WMI
+	tristate "WMI (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  This driver adds support for the ACPI-WMI mapper device (PNP0C14)
+	  found on some systems.
+
+	  NOTE: You will need another driver or userspace application on top of
+	  this to actually use anything defined in the ACPI-WMI mapper.
+
 config ACPI_ASUS
         tristate "ASUS/Medion Laptop Extras"
 	depends on X86
drivers/acpi/Makefile +1 -0
index 456446f..f29812a 100644
@@ -55,6 +55,7 @@ obj-$(CONFIG_ACPI_THERMAL)	+= thermal.o
 obj-$(CONFIG_ACPI_SYSTEM)	+= system.o event.o
 obj-$(CONFIG_ACPI_DEBUG)	+= debug.o
 obj-$(CONFIG_ACPI_NUMA)		+= numa.o
+obj-$(CONFIG_ACPI_WMI)		+= wmi.o
 obj-$(CONFIG_ACPI_ASUS)		+= asus_acpi.o
 obj-$(CONFIG_ACPI_TOSHIBA)	+= toshiba_acpi.o
 obj-$(CONFIG_ACPI_HOTPLUG_MEMORY)	+= acpi_memhotplug.o
drivers/acpi/wmi.c new file +710 -0

710 lines not on this page · raw message

include/linux/acpi.h +20 -0
index 63f2e6e..fab9f70 100644
@@ -192,6 +192,26 @@ extern int ec_transaction(u8 command,
 
 #endif /*CONFIG_ACPI_EC*/
 
+#if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE)
+
+typedef void (*wmi_notify_handler) (u32 value, void *context);
+
+extern acpi_status wmi_evaluate_method(const char *guid, u8 instance,
+					u32 method_id,
+					const struct acpi_buffer *in,
+					struct acpi_buffer *out);
+extern acpi_status wmi_query_block(const char *guid, u8 instance,
+					struct acpi_buffer *out);
+extern acpi_status wmi_set_block(const char *guid, u8 instance,
+					const struct acpi_buffer *in);
+extern acpi_status wmi_install_notify_handler(const char *guid,
+					wmi_notify_handler handler, void *data);
+extern acpi_status wmi_remove_notify_handler(const char *guid);
+extern acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out);
+extern bool wmi_has_guid(const char *guid);
+
+#endif	/* CONFIG_ACPI_WMI */
+
 extern int acpi_blacklisted(void);
 #ifdef CONFIG_DMI
 extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d);
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#86 lore raw

PATCH 78/112 acer-wmi: Add driver for newer Acer laptops

In reply to Len Brown

From: Carlos Corbacho <[email protected]>

This is a driver for newer Acer (and Wistron) laptops. It adds wireless radio and bluetooth control, and on some laptops, exposes the mail LED and LCD backlight.

v1:

* Initial release

v2:

* Replace left over ACPI references with WMI
* Add GUID based autoloading (depends on future work to WMI)
* Add DMI based autoloading (backup solution until WMI sysfs/ class work is available)
* Checkpatch fixes

v3:

* Add new EC quirks for Aspire 3100 & 5100, and Extensa 5220

v4:

* Simplified internal handling of WMID and AMW0 devices
* Add autodetection for bluetooth and maximum brightness on AMW0 V2 and WMID laptops.

v5:

* Add EC quirk for Medion MD 98000
* Add autodetection for AMW0, and mail LED on AMW0 and AMW0 V2.
* Improve error handling
* Fix AMW0 V2 bluetooth and wireless, by using both WMID and AMW0 methods to ensure that the correct value is always set.

v6:

* Fix 'use before initialisation' bug with quirks.

v7

* Fix bug on AMW0 where acer-wmi would exit if a mail LED was not detected.
* Add Acer Aspire 9110 mail LED support
* Fix section mismatch warnings

---
 MAINTAINERS             |    7 +
 drivers/misc/Kconfig    |   16 +
 drivers/misc/Makefile   |    1 +
 drivers/misc/acer-wmi.c | 1109 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 1133 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/acer-wmi.c
MAINTAINERS +7 -0
index 12e26d7..2eaeef4 100644
@@ -202,6 +202,13 @@ L:	[email protected]
 W:	http://www.adaptec.com/
 S:	Supported
 
+ACER WMI LAPTOP EXTRAS
+P:	Carlos Corbacho
+M:	[email protected]
+L:	[email protected] (subscribers-only)
+W:	http://code.google.com/p/aceracpi
+S:	Maintained
+
 ACPI
 P:	Len Brown
 M:	[email protected]
drivers/misc/Kconfig +16 -0
index b5e67c0..35d2c22 100644
@@ -92,6 +92,22 @@ config TIFM_7XX1
           To compile this driver as a module, choose M here: the module will
 	  be called tifm_7xx1.
 
+config ACER_WMI
+        tristate "Acer WMI Laptop Extras (EXPERIMENTAL)"
+	depends on X86
+	depends on EXPERIMENTAL
+	depends on ACPI
+	depends on ACPI_WMI
+	depends on LEDS_CLASS
+	depends on BACKLIGHT_CLASS_DEVICE
+	---help---
+	  This is a driver for newer Acer (and Wistron) laptops. It adds
+	  wireless radio and bluetooth control, and on some laptops,
+	  exposes the mail LED and LCD backlight.
+
+	  If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M
+	  here.
+
 config ASUS_LAPTOP
         tristate "Asus Laptop Extras (EXPERIMENTAL)"
         depends on X86
drivers/misc/Makefile +1 -0
index 87f2685..3da1491 100644
@@ -6,6 +6,7 @@ obj- := misc.o	# Dummy rule to force built-in.o to be made
 obj-$(CONFIG_IBM_ASM)		+= ibmasm/
 obj-$(CONFIG_HDPU_FEATURES)	+= hdpuftrs/
 obj-$(CONFIG_MSI_LAPTOP)     += msi-laptop.o
+obj-$(CONFIG_ACER_WMI)     += acer-wmi.o
 obj-$(CONFIG_ASUS_LAPTOP)     += asus-laptop.o
 obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o
 obj-$(CONFIG_LKDTM)		+= lkdtm.o
drivers/misc/acer-wmi.c new file +1109 -0

1,109 lines not on this page · raw message

Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#87 lore raw

PATCH 79/112 tc1100-wmi: Add driver for HP Compaq TC1100 Tablets

In reply to Len Brown

From: Carlos Corbacho <[email protected]>

This is based on the 2004 out-of-tree work of Jamey Hicks, to add support via WMI for controlling the jog dial and wireless on these tablets.

v1:

Original release

v2:

As per Joshua Wise's comments, change bluetooth to jogdial (an error from the original driver).

CC Matthew Garrett <[email protected]>
CC Jamey Hicks <[email protected]>
CC Joshua Wise <[email protected]>
---
 MAINTAINERS               |    5 +
 drivers/misc/Kconfig      |    9 ++
 drivers/misc/Makefile     |    1 +
 drivers/misc/tc1100-wmi.c |  290 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 305 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/tc1100-wmi.c
MAINTAINERS +5 -0
index 2eaeef4..db4bc14 100644
@@ -1794,6 +1794,11 @@ P:	Jaroslav Kysela
 M:	[email protected]
 S:	Maintained
 
+HP COMPAQ TC1100 TABLET WMI EXTRAS DRIVER
+P:	Carlos Corbacho
+M:	[email protected]
+S:	Odd Fixes
+
 HPET:	High Precision Event Timers driver (hpet.c)
 P:	Clemens Ladisch
 M:	[email protected]
drivers/misc/Kconfig +9 -0
index 35d2c22..0599741 100644
@@ -142,6 +142,15 @@ config FUJITSU_LAPTOP
 
 	  If you have a Fujitsu laptop, say Y or M here.
 
+config TC1100_WMI
+	tristate "HP Compaq TC1100 Tablet WMI Extras"
+	depends on X86 && !X86_64
+	depends on ACPI
+	depends on ACPI_WMI
+	---help---
+	  This is a driver for the WMI extensions (wireless and bluetooth power
+	  control) of the HP Compaq TC1100 tablet.
+
 config MSI_LAPTOP
         tristate "MSI Laptop Extras"
         depends on X86
drivers/misc/Makefile +1 -0
index 3da1491..51196c0 100644
@@ -9,6 +9,7 @@ obj-$(CONFIG_MSI_LAPTOP)     += msi-laptop.o
 obj-$(CONFIG_ACER_WMI)     += acer-wmi.o
 obj-$(CONFIG_ASUS_LAPTOP)     += asus-laptop.o
 obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o
+obj-$(CONFIG_TC1100_WMI)	+= tc1100-wmi.o
 obj-$(CONFIG_LKDTM)		+= lkdtm.o
 obj-$(CONFIG_TIFM_CORE)       	+= tifm_core.o
 obj-$(CONFIG_TIFM_7XX1)       	+= tifm_7xx1.o
drivers/misc/tc1100-wmi.c new file +290 -0

290 lines not on this page · raw message

Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#88 lore raw

PATCH 80/112 ACPI: battery: add sysfs serial number

In reply to Len Brown

From: maximilian attems <[email protected]>

egrep serial /proc/acpi/battery/BAT0/info
serial number: 32090

serial number can tell you from the imminent danger of beeing set on fire.

---
 drivers/acpi/battery.c             |    5 +++++
 drivers/power/power_supply_sysfs.c |    1 +
 include/linux/power_supply.h       |    1 +
 3 files changed, 7 insertions(+), 0 deletions(-)
drivers/acpi/battery.c +5 -0
index c4a769d..f6215e8 100644
@@ -194,6 +194,9 @@ static int acpi_battery_get_property(struct power_supply *psy,
 	case POWER_SUPPLY_PROP_MANUFACTURER:
 		val->strval = battery->oem_info;
 		break;
+	case POWER_SUPPLY_PROP_SERIAL_NUMBER:
+		val->strval = battery->serial_number;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -212,6 +215,7 @@ static enum power_supply_property charge_battery_props[] = {
 	POWER_SUPPLY_PROP_CHARGE_NOW,
 	POWER_SUPPLY_PROP_MODEL_NAME,
 	POWER_SUPPLY_PROP_MANUFACTURER,
+	POWER_SUPPLY_PROP_SERIAL_NUMBER,
 };
 
 static enum power_supply_property energy_battery_props[] = {
@@ -226,6 +230,7 @@ static enum power_supply_property energy_battery_props[] = {
 	POWER_SUPPLY_PROP_ENERGY_NOW,
 	POWER_SUPPLY_PROP_MODEL_NAME,
 	POWER_SUPPLY_PROP_MANUFACTURER,
+	POWER_SUPPLY_PROP_SERIAL_NUMBER,
 };
 #endif
 
drivers/power/power_supply_sysfs.c +1 -0
index d482484..ad2bed0 100644
@@ -116,6 +116,7 @@ static struct device_attribute power_supply_attrs[] = {
 	/* Properties of type `const char *' */
 	POWER_SUPPLY_ATTR(model_name),
 	POWER_SUPPLY_ATTR(manufacturer),
+	POWER_SUPPLY_ATTR(serial_number),
 };
 
 static ssize_t power_supply_show_static_attrs(struct device *dev,
include/linux/power_supply.h +1 -0
index 5cbf3e3..68ed19c 100644
@@ -94,6 +94,7 @@ enum power_supply_property {
 	/* Properties of type `const char *' */
 	POWER_SUPPLY_PROP_MODEL_NAME,
 	POWER_SUPPLY_PROP_MANUFACTURER,
+	POWER_SUPPLY_PROP_SERIAL_NUMBER,
 };
 
 enum power_supply_type {
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#89 lore raw

PATCH 81/112 ACPI: basic initramfs DSDT override support

In reply to Len Brown

From: Markus Gaugusch <[email protected]>

The basics of DSDT from initramfs. In case this option is selected, populate_rootfs() is called a bit earlier to have the initramfs content available during ACPI initialization.

This is a very similar path to the one available at
http://gaugusch.at/kernel.shtml but with some update in the documentation, default set to No and the change of populate_rootfs() the "Jeff Mahony way" (which avoids reading the initramfs twice).

---
 Documentation/acpi/dsdt-initrd.txt |   99 ++++++++++++++++++++++++++++++++++++
 drivers/acpi/Kconfig               |   17 ++++++
 drivers/acpi/osl.c                 |   73 +++++++++++++++++++++++++--
 init/initramfs.c                   |    8 +++-
 init/main.c                        |    7 +++
 5 files changed, 199 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/acpi/dsdt-initrd.txt
Documentation/acpi/dsdt-initrd.txt new file +99 -0
new file mode 100644
index 0000000..7360433
@@ -0,0 +1,99 @@
+ACPI Custom DSDT read from initramfs
+
+2003 by Markus Gaugusch < dsdt at gaugusch dot at >
+Special thanks go to Thomas Renninger from SuSE, who updated the patch for
+2.6.0 and later modified it to read inside initramfs
+2004 - 2008 maintained by Eric Piel < eric dot piel at tremplin-utc dot net >
+
+This option is intended for people who would like to hack their DSDT and don't
+want to recompile their kernel after every change. It can also be useful to
+distros which offers pre-compiled kernels and want to allow their users to use
+a modified DSDT. In the Kernel config, enable the initial RAM filesystem
+support (in General Setup) and enable ACPI_CUSTOM_DSDT_INITRD at the ACPI
+options (General Setup|ACPI Support|Read Custom DSDT from initramfs).
+
+A custom DSDT (Differentiated System Description Table) is useful when your
+computer uses ACPI but problems occur due to broken implementation. Typically,
+your computer works but there are some troubles with the hardware detection or
+the power management. You can check that troubles come from errors in the DSDT by
+activating the ACPI debug option and reading the logs. This table is provided
+by the BIOS, therefore it might be a good idea to check for BIOS update on your
+vendor website before going any further. Errors are often caused by vendors
+testing their hardware only with Windows or because there is code which is
+executed only on a specific OS with a specific version and Linux hasn't been
+considered during the development.
+
+Before you run away from customising your DSDT, you should note that already
+corrected tables are available for a fair amount of computers on this web-page:
+http://acpi.sf.net/dsdt . Be careful though, to work correctly a DSDT has to
+match closely the hardware, including the amount of RAM, the frequency of the
+processor and the PCI cards present! If you are part of the unluckies who
+cannot find their hardware in this database, you can modify your DSDT by
+yourself. This process is less painful than it sounds. Download the Intel ASL
+compiler/decompiler at http://www.intel.com/technology/IAPC/acpi/downloads.htm .
+As root, you then have to dump your DSDT and decompile it. By using the
+compiler messages as well as the kernel ACPI debug messages and the reference
+book (available at the Intel website and also at http://www.acpi.info), it is
+quite easy to obtain a fully working table.
+
+Once your new DSDT is ready you'll have to add it to an initramfs so that the
+kernel can read the table at the very beginning of the boot. As the file has to
+be accessed very early during the boot process the initramfs has to be an
+initramfs. The file is contained into the initramfs under the name /DSDT.aml .
+To obtain such an initramfs, you might have to modify your initramfs script or
+you can add it later to the initramfs with the script appended to this
+document. The command will look like:
+initramfs-add-dsdt initramfs.img my-dsdt.aml
+
+In case you don't use any initramfs, the possibilities you have are to either
+start using one (try mkinitrd or yaird), or use the "Include Custom DSDT"
+configure option to directly include your DSDT inside the kernel.
+
+The message "Looking for DSDT in initramfs..." will tell you if the DSDT was
+found or not. If you need to update your DSDT, generate a new initramfs and
+perform the steps above. Don't forget that with Lilo, you'll have to re-run it.
+
+
+====================== Here starts initramfs-add-dsdt ==========================
+#!/bin/bash
+# Adds a DSDT file to the initrd (if it's an initramfs)
+# first argument is the name of archive
+# second argument is the name of the file to add
+# The file will be copied as /DSDT.aml
+
+# 20060126: fix "Premature end of file" with some old cpio (Roland Robic)
+# 20060205: this time it should really work
+
+# check the arguments
+if [ $# -ne 2 ]; then
+	program_name=$(basename $0)
+	echo "\
+$program_name: too few arguments
+Usage: $program_name initrd-name.img DSDT-to-add.aml
+Adds a DSDT file to an initrd (in initramfs format)
+
+  initrd-name.img: filename of the initrd in initramfs format
+  DSDT-to-add.aml: filename of the DSDT file to add
+  " 1>&2
+    exit 1
+fi
+
+# we should check it's an initramfs
+
+tempcpio=$(mktemp -d)
+# cleanup on exit, hangup, interrupt, quit, termination
+trap 'rm -rf $tempcpio' 0 1 2 3 15
+
+# extract the archive
+gunzip -c "$1" > "$tempcpio"/initramfs.cpio || exit 1
+
+# copy the DSDT file at the root of the directory so that we can call it "/DSDT.aml"
+cp -f "$2" "$tempcpio"/DSDT.aml
+
+# add the file
+cd "$tempcpio"
+(echo DSDT.aml | cpio --quiet -H newc -o -A -O "$tempcpio"/initramfs.cpio) || exit 1
+cd "$OLDPWD"
+
+# re-compress the archive
+gzip -c "$tempcpio"/initramfs.cpio > "$1"
drivers/acpi/Kconfig +17 -0
index ccf6ea9..0442ae1 100644
@@ -274,6 +274,23 @@ config ACPI_CUSTOM_DSDT_FILE
 	  Enter the full path name to the file which includes the AmlCode
 	  declaration.
 
+config ACPI_CUSTOM_DSDT_INITRD
+	bool "Read Custom DSDT from initramfs"
+	depends on BLK_DEV_INITRD
+	default n
+	help
+	  The DSDT (Differentiated System Description Table) often needs to be
+	  overridden because of broken BIOS implementations. If this feature is
+	  activated you will be able to provide a customized DSDT by adding it
+	  to your initramfs. If your mkinitrd tool does not support this feature
+	  a script is provided in the documentation. For more details see
+	  <file:Documentation/dsdt-initrd.txt> or <http://gaugusch.at/kernel.shtml>.
+	  If there is no table found, it will fall-back to the custom DSDT
+	  in-kernel (if activated) or to the DSDT from the BIOS.
+
+	  Even if you do not need a new one at the moment, you may want to use a
+	  better DSDT later. It is safe to say Y here.
+
 config ACPI_BLACKLIST_YEAR
 	int "Disable ACPI for systems before Jan 1st this year" if X86_32
 	default 0
drivers/acpi/osl.c +69 -4

88 lines not on this page · raw message

init/initramfs.c +7 -1
index d53fee8..c0b1e05 100644
@@ -538,7 +538,7 @@ skip:
 	initrd_end = 0;
 }
 
-static int __init populate_rootfs(void)
+int __init populate_rootfs(void)
 {
 	char *err = unpack_to_rootfs(__initramfs_start,
 			 __initramfs_end - __initramfs_start, 0);
@@ -577,4 +577,10 @@ static int __init populate_rootfs(void)
 	}
 	return 0;
 }
+#ifndef CONFIG_ACPI_CUSTOM_DSDT_INITRD
+/*
+ * if this option is enabled, populate_rootfs() is called _earlier_ in the
+ * boot sequence. This insures that the ACPI initialisation can find the file.
+ */
 rootfs_initcall(populate_rootfs);
+#endif
init/main.c +7 -0
index c691f5f..2a78932 100644
@@ -102,6 +102,12 @@ static inline void mark_rodata_ro(void) { }
 extern void tc_init(void);
 #endif
 
+#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
+extern int populate_rootfs(void);
+#else
+static inline void populate_rootfs(void) {}
+#endif
+
 enum system_states system_state;
 EXPORT_SYMBOL(system_state);
 
@@ -648,6 +654,7 @@ asmlinkage void __init start_kernel(void)
 
 	check_bugs();
 
+	populate_rootfs(); /* For DSDT override from initramfs */
 	acpi_early_init(); /* before LAPIC and SMP init */
 
 	/* Do the rest non-__init'ed, we're now alive */
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#90 lore raw

PATCH 82/112 ACPI: Taint kernel on ACPI table override (format corrected)

In reply to Len Brown

From: Éric Piel <[email protected]>

When an ACPI table is overridden (for now this can happen only for DSDT) display a big warning and taint the kernel with flag A.

---
 drivers/acpi/osl.c     |    7 +++++++
 include/linux/kernel.h |    1 +
 kernel/panic.c         |    5 +++--
 3 files changed, 11 insertions(+), 2 deletions(-)
drivers/acpi/osl.c +7 -0
index 131936e..bbd8360 100644
@@ -392,6 +392,13 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
 			*new_table = initrd_table;
 	}
 #endif
+	if (*new_table != NULL) {
+		printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], "
+			   "this is unsafe: tainting kernel\n",
+		       existing_table->signature,
+		       existing_table->oem_table_id);
+		add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
+	}
 	return AE_OK;
 }
 
include/linux/kernel.h +1 -0
index 18222f2..9e01f37 100644
@@ -243,6 +243,7 @@ extern enum system_states {
 #define TAINT_BAD_PAGE			(1<<5)
 #define TAINT_USER			(1<<6)
 #define TAINT_DIE			(1<<7)
+#define TAINT_OVERRIDDEN_ACPI_TABLE	(1<<8)
 
 extern void dump_stack(void) __cold;
 
kernel/panic.c +3 -2
index d9e90cf..24af9f8 100644
@@ -161,7 +161,7 @@ const char *print_tainted(void)
 {
 	static char buf[20];
 	if (tainted) {
-		snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c%c",
+		snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c%c%c",
 			tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G',
 			tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
 			tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
@@ -169,7 +169,8 @@ const char *print_tainted(void)
 			tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
 			tainted & TAINT_BAD_PAGE ? 'B' : ' ',
 			tainted & TAINT_USER ? 'U' : ' ',
-			tainted & TAINT_DIE ? 'D' : ' ');
+			tainted & TAINT_DIE ? 'D' : ' ',
+			tainted & TAINT_OVERRIDDEN_ACPI_TABLE ? 'A' : ' ');
 	}
 	else
 		snprintf(buf, sizeof(buf), "Not tainted");
Signature · 6 lines
1.5.4.23.gef5b9

-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
author reviewer
#91 lore raw

PATCH 83/112 ACPI: create /sys/firmware/acpi/interrupts

In reply to Len Brown

From: Len Brown <[email protected]>

See Documentation/ABI/testing/sysfs-firmware-acpi

---
 Documentation/ABI/testing/sysfs-firmware-acpi |   99 ++++++++++++
 drivers/acpi/events/evevent.c                 |    2 +-
 drivers/acpi/events/evgpe.c                   |    2 +-
 drivers/acpi/osl.c                            |   12 ++-
 drivers/acpi/system.c                         |  208 +++++++++++++++++++++++++
 drivers/acpi/utilities/utglobal.c             |    2 -
 include/acpi/acglobal.h                       |    4 -
 include/acpi/acpiosxf.h                       |    3 +
 include/linux/acpi.h                          |    2 +
 9 files changed, 325 insertions(+), 9 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-firmware-acpi
Documentation/ABI/testing/sysfs-firmware-acpi new file +99 -0
new file mode 100644
index 0000000..9470ed9
@@ -0,0 +1,99 @@
+What:		/sys/firmware/acpi/interrupts/
+Date:		February 2008
+Contact:	Len Brown <[email protected]>
+Description:
+		All ACPI interrupts are handled via a single IRQ,
+		the System Control Interrupt (SCI), which appears
+		as "acpi" in /proc/interrupts.
+
+		However, one of the main functions of ACPI is to make
+		the platform understand random hardware without
+		special driver support.  So while the SCI handles a few
+		well known (fixed feature) interrupts sources, such
+		as the power button, it can also handle a variable
+		number of a "General Purpose Events" (GPE).
+
+		A GPE vectors to a specified handler in AML, which
+		can do a anything the BIOS writer wants from
+		OS context.  GPE 0x12, for example, would vector
+		to a level or edge handler called _L12 or _E12.
+		The handler may do its business and return.
+		Or the handler may send send a Notify event
+		to a Linux device driver registered on an ACPI device,
+		such as a battery, or a processor.
+
+		To figure out where all the SCI's are coming from,
+		/sys/firmware/acpi/interrupts contains a file listing
+		every possible source, and the count of how many
+		times it has triggered.
+
+		$ cd /sys/firmware/acpi/interrupts
+		$ grep . *
+		error:0
+		ff_gbl_lock:0
+		ff_pmtimer:0
+		ff_pwr_btn:0
+		ff_rt_clk:0
+		ff_slp_btn:0
+		gpe00:0
+		gpe01:0
+		gpe02:0
+		gpe03:0
+		gpe04:0
+		gpe05:0
+		gpe06:0
+		gpe07:0
+		gpe08:0
+		gpe09:174
+		gpe0A:0
+		gpe0B:0
+		gpe0C:0
+		gpe0D:0
+		gpe0E:0
+		gpe0F:0
+		gpe10:0
+		gpe11:60
+		gpe12:0
+		gpe13:0
+		gpe14:0
+		gpe15:0
+		gpe16:0
+		gpe17:0
+		gpe18:0
+		gpe19:7
+		gpe1A:0
+		gpe1B:0
+		gpe1C:0
+		gpe1D:0
+		gpe1E:0
+		gpe1F:0
+		gpe_all:241
+		sci:241
+
+		sci - The total number of times the ACPI SCI
+		has claimed an interrupt.
+
+		gpe_all - count of SCI caused by GPEs.
+
+		gpeXX - count for individual GPE source
+
+		ff_gbl_lock - Global Lock
+
+		ff_pmtimer - PM Timer
+
+		ff_pwr_btn - Power Button
+
+		ff_rt_clk - Real Time Clock
+
+		ff_slp_btn - Sleep Button
+
+		error - an interrupt that can't be accounted for above.
+
+		Root has permission to clear any of these counters.  Eg.
+		# echo 0 > gpe11
+
+		All counters can be cleared by clearing the total "sci":
+		# echo 0 > sci
+
+		None of these counters has an effect on the function
+		of the system, they are simply statistics.
drivers/acpi/events/evevent.c +1 -1
index e412878..3048801 100644
@@ -259,7 +259,7 @@ u32 acpi_ev_fixed_event_detect(void)
 			enable_bit_mask)) {
 
 			/* Found an active (signalled) event */
-
+			acpi_os_fixed_event_count(i);
 			int_status |= acpi_ev_fixed_event_dispatch((u32) i);
 		}
 	}
drivers/acpi/events/evgpe.c +1 -1
index e22f4a9..4bd9e22 100644
@@ -618,7 +618,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
 
 	ACPI_FUNCTION_TRACE(ev_gpe_dispatch);
 
-	acpi_gpe_count++;
+	acpi_os_gpe_count(gpe_number);
 
 	/*
 	 * If edge-triggered, clear the GPE status bit now.  Note that
drivers/acpi/osl.c +11 -1
index e53fb51..1087efe 100644
@@ -332,7 +332,15 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
 
 static irqreturn_t acpi_irq(int irq, void *dev_id)
 {
-	return (*acpi_irq_handler) (acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE;
+	u32 handled;
+
+	handled = (*acpi_irq_handler) (acpi_irq_context);
+
+	if (handled) {
+		acpi_irq_handled++;
+		return IRQ_HANDLED;
+	} else
+		return IRQ_NONE;
 }
 
 acpi_status
@@ -341,6 +349,8 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
 {
 	unsigned int irq;
 
+	acpi_irq_stats_init();
+
 	/*
 	 * Ignore the GSI from the core, and use the value in our copy of the
 	 * FADT. It may not be the same if an interrupt source override exists
drivers/acpi/system.c +208 -0

220 lines not on this page · raw message

drivers/acpi/utilities/utglobal.c +0 -2
index 93ea829..630c9a2 100644
@@ -671,7 +671,6 @@ void acpi_ut_init_globals(void)
 
 	/* GPE support */
 
-	acpi_gpe_count = 0;
 	acpi_gbl_gpe_xrupt_list_head = NULL;
 	acpi_gbl_gpe_fadt_blocks[0] = NULL;
 	acpi_gbl_gpe_fadt_blocks[1] = NULL;
@@ -735,4 +734,3 @@ void acpi_ut_init_globals(void)
 
 ACPI_EXPORT_SYMBOL(acpi_dbg_level)
     ACPI_EXPORT_SYMBOL(acpi_dbg_layer)
-    ACPI_EXPORT_SYMBOL(acpi_gpe_count)
include/acpi/acglobal.h +0 -4
index 347a911..47a1fd8 100644
@@ -117,10 +117,6 @@ extern u32 acpi_dbg_layer;
 
 extern u32 acpi_gbl_nesting_level;
 
-/* Event counters */
-
-ACPI_EXTERN u32 acpi_gpe_count;
-
 /* Support for dynamic control method tracing mechanism */
 
 ACPI_EXTERN u32 acpi_gbl_original_dbg_level;
include/acpi/acpiosxf.h +3 -0
index ca882b8..1a16cfb 100644
@@ -181,6 +181,9 @@ acpi_os_install_interrupt_handler(u32 gsi,
 acpi_status
 acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler service_routine);
 
+void acpi_os_gpe_count(u32 gpe_number);
+void acpi_os_fixed_event_count(u32 fixed_event_number);
+
 /*
  * Threads and Scheduling
  */
include/linux/acpi.h +2 -0
index 63f2e6e..cb911f3 100644
@@ -115,7 +115,9 @@ int acpi_unmap_lsapic(int cpu);
 
 int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base);
 int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base);
+void acpi_irq_stats_init(void);
 
+extern u32 acpi_irq_handled;
 extern int acpi_mp_config;
 
 extern struct acpi_mcfg_allocation *pci_mmcfg_config;
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#92 lore raw

PATCH 84/112 asus-laptop new write_acpi_int

In reply to Len Brown

From: Corentin CHARY <[email protected]>

Just a little modification of write_acpi_int

---
 drivers/misc/asus-laptop.c |   24 +++++++++++++++---------
 1 files changed, 15 insertions(+), 9 deletions(-)
drivers/misc/asus-laptop.c +15 -9
index 0846c33..34666ff 100644
@@ -254,7 +254,7 @@ ASUS_LED(gled, "gaming");
  * method is searched within the scope of the handle, can be NULL. The output
  * of the method is written is output, which can also be NULL
  *
- * returns 1 if write is successful, 0 else.
+ * returns 0 if write is successful, -1 else.
  */
 static int write_acpi_int(acpi_handle handle, const char *method, int val,
 			  struct acpi_buffer *output)
@@ -263,13 +263,19 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
 	union acpi_object in_obj;	//the only param we use
 	acpi_status status;
 
+	if (!handle)
+		return 0;
+
 	params.count = 1;
 	params.pointer = &in_obj;
 	in_obj.type = ACPI_TYPE_INTEGER;
 	in_obj.integer.value = val;
 
 	status = acpi_evaluate_object(handle, (char *)method, &params, output);
-	return (status == AE_OK);
+	if (status == AE_OK)
+		return 0;
+	else
+		return -1;
 }
 
 static int read_wireless_status(int mask)
@@ -335,7 +341,7 @@ static void write_status(acpi_handle handle, int out, int mask)
 		break;
 	}
 
-	if (handle && !write_acpi_int(handle, NULL, out, NULL))
+	if (write_acpi_int(handle, NULL, out, NULL))
 		printk(ASUS_WARNING " write failed %x\n", mask);
 }
 
@@ -415,7 +421,7 @@ static int set_brightness(struct backlight_device *bd, int value)
 	value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
 	/* 0 <= value <= 15 */
 
-	if (!write_acpi_int(brightness_set_handle, NULL, value, NULL)) {
+	if (write_acpi_int(brightness_set_handle, NULL, value, NULL)) {
 		printk(ASUS_WARNING "Error changing brightness\n");
 		ret = -EIO;
 	}
@@ -545,7 +551,7 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,
 
 	rv = parse_arg(buf, count, &value);
 	if (rv > 0) {
-		if (!write_acpi_int(ledd_set_handle, NULL, value, NULL))
+		if (write_acpi_int(ledd_set_handle, NULL, value, NULL))
 			printk(ASUS_WARNING "LED display write failed\n");
 		else
 			hotk->ledd_status = (u32) value;
@@ -590,7 +596,7 @@ static ssize_t store_bluetooth(struct device *dev,
 static void set_display(int value)
 {
 	/* no sanity check needed for now */
-	if (!write_acpi_int(display_set_handle, NULL, value, NULL))
+	if (write_acpi_int(display_set_handle, NULL, value, NULL))
 		printk(ASUS_WARNING "Error setting display\n");
 	return;
 }
@@ -647,7 +653,7 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr,
  */
 static void set_light_sens_switch(int value)
 {
-	if (!write_acpi_int(ls_switch_handle, NULL, value, NULL))
+	if (write_acpi_int(ls_switch_handle, NULL, value, NULL))
 		printk(ASUS_WARNING "Error setting light sensor switch\n");
 	hotk->light_switch = value;
 }
@@ -672,7 +678,7 @@ static ssize_t store_lssw(struct device *dev, struct device_attribute *attr,
 
 static void set_light_sens_level(int value)
 {
-	if (!write_acpi_int(ls_level_handle, NULL, value, NULL))
+	if (write_acpi_int(ls_level_handle, NULL, value, NULL))
 		printk(ASUS_WARNING "Error setting light sensor level\n");
 	hotk->light_level = value;
 }
@@ -860,7 +866,7 @@ static int asus_hotk_get_info(void)
 		printk(ASUS_WARNING "Couldn't get the DSDT table header\n");
 
 	/* We have to write 0 on init this far for all ASUS models */
-	if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
+	if (write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
 		printk(ASUS_ERR "Hotkey initialization failed\n");
 		return -ENODEV;
 	}
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#93 lore raw

PATCH 85/112 asus-laptop: add parentheses

In reply to Len Brown

From: Roel Kluin <[email protected]>

'!' has a higher priority than '&': bitanding has no effect.

---
 drivers/misc/asus-laptop.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/misc/asus-laptop.c +1 -1
index 34666ff..3bd8831 100644
@@ -327,7 +327,7 @@ static void write_status(acpi_handle handle, int out, int mask)
 
 	switch (mask) {
 	case MLED_ON:
-		out = !out & 0x1;
+		out = !(out & 0x1);
 		break;
 	case GLED_ON:
 		out = (out & 0x1) + 1;
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#94 lore raw

PATCH 86/112 asus_acpi: add support for F3Sa

In reply to Len Brown

From: Luca Tettamanti <[email protected]>

Add support for ASUS F3Sa notebook. Features:
- LCD on/off
- Brightness
- Wifi kill
- Bluetooth kill

---
 drivers/acpi/asus_acpi.c |   55 +++++++++++++++++++++++++++++++++++++--------
 1 files changed, 45 insertions(+), 10 deletions(-)
drivers/acpi/asus_acpi.c +45 -10
index d915fec..d25ef96 100644
@@ -142,6 +142,7 @@ struct asus_hotk {
 		xxN,		//M2400N, M3700N, M5200N, M6800N, S1300N, S5200N
 		A4S,            //Z81sp
 		//(Centrino)
+		F3Sa,
 		END_MODEL
 	} model;		//Models currently supported
 	u16 event_count[128];	//count for each event TODO make this better
@@ -405,7 +406,20 @@ static struct model_data model_conf[END_MODEL] = {
 		.brightness_get    = "GPLV",
 		.mt_bt_switch      = "BLED",
 		.mt_wled           = "WLED"
-	}
+	},
+
+	{
+		.name		= "F3Sa",
+		.mt_bt_switch	= "BLED",
+		.mt_wled	= "WLED",
+		.mt_mled	= "MLED",
+		.brightness_get	= "GPLV",
+		.brightness_set	= "SPLV",
+		.mt_lcd_switch	= "\\_SB.PCI0.SBRG.EC0._Q10",
+		.lcd_status	= "\\_SB.PCI0.SBRG.EC0.RPIN",
+		.display_get	= "\\ADVG",
+		.display_set	= "SDSP",
+	},
 
 };
 
@@ -710,15 +724,8 @@ static int get_lcd_state(void)
 {
 	int lcd = 0;
 
-	if (hotk->model != L3H) {
-		/* We don't have to check anything if we are here */
-		if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd))
-			printk(KERN_WARNING
-			       "Asus ACPI: Error reading LCD status\n");
-
-		if (hotk->model == L2D)
-			lcd = ~lcd;
-	} else {		/* L3H and the like have to be handled differently */
+	if (hotk->model == L3H) {
+		/* L3H and the like have to be handled differently */
 		acpi_status status = 0;
 		struct acpi_object_list input;
 		union acpi_object mt_params[2];
@@ -745,6 +752,32 @@ static int get_lcd_state(void)
 		if (out_obj.type == ACPI_TYPE_INTEGER)
 			/* That's what the AML code does */
 			lcd = out_obj.integer.value >> 8;
+	} else if (hotk->model == F3Sa) {
+		unsigned long tmp;
+		union acpi_object param;
+		struct acpi_object_list input;
+		acpi_status status;
+
+		/* Read pin 11 */
+		param.type = ACPI_TYPE_INTEGER;
+		param.integer.value = 0x11;
+		input.count = 1;
+		input.pointer = &param;
+
+		status = acpi_evaluate_integer(NULL, hotk->methods->lcd_status,
+						&input, &tmp);
+		if (status != AE_OK)
+			return -1;
+
+		lcd = tmp;
+	} else {
+		/* We don't have to check anything if we are here */
+		if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd))
+			printk(KERN_WARNING
+			       "Asus ACPI: Error reading LCD status\n");
+
+		if (hotk->model == L2D)
+			lcd = ~lcd;
 	}
 
 	return (lcd & 1);
@@ -1134,6 +1167,8 @@ static int asus_model_match(char *model)
 		return W5A;
 	else if (strncmp(model, "A4S", 3) == 0)
 		return A4S;
+	else if (strncmp(model, "F3Sa", 4) == 0)
+		return F3Sa;
 	else
 		return END_MODEL;
 }
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#95 lore raw

PATCH 87/112 ACPI: remove duplicated warning message

In reply to Len Brown

From: Miguel Botón <[email protected]>

Remove duplicated warning message in acpi_power_transition()

ACPI: Transitioning device [%s] to D%d\n

This warning message is printed by acpi_bus_set_power() so we don't need to print it again.

---
 drivers/acpi/power.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)
drivers/acpi/power.c +2 -4
index af1769a..76bf6d9 100644
@@ -458,11 +458,9 @@ int acpi_power_transition(struct acpi_device *device, int state)
 	}
 
      end:
-	if (result) {
+	if (result)
 		device->power.state = ACPI_STATE_UNKNOWN;
-		printk(KERN_WARNING PREFIX "Transitioning device [%s] to D%d\n",
-			      device->pnp.bus_id, state);
-	} else {
+	else {
 	/* We shouldn't change the state till all above operations succeed */
 		device->power.state = state;
 	}
Signature · 6 lines
1.5.4.23.gef5b9

-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
author reviewer
#96 lore raw

PATCH 88/112 ACPI: acpi_pci_irq_find_prt_entry(): use list_for_each_entry() instead of list_for_each()

In reply to Len Brown

From: Matthias Kaehlcke <[email protected]>

---
 drivers/acpi/pci_irq.c |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)
drivers/acpi/pci_irq.c +1 -4
index 62010c2..76d9c66 100644
@@ -51,10 +51,8 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment,
 							  int bus,
 							  int device, int pin)
 {
-	struct list_head *node = NULL;
 	struct acpi_prt_entry *entry = NULL;
 
-
 	if (!acpi_prt.count)
 		return NULL;
 
@@ -64,8 +62,7 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment,
 	 *
 	 */
 	spin_lock(&acpi_prt_lock);
-	list_for_each(node, &acpi_prt.entries) {
-		entry = list_entry(node, struct acpi_prt_entry, node);
+	list_for_each_entry(entry, &acpi_prt.entries, node) {
 		if ((segment == entry->id.segment)
 		    && (bus == entry->id.bus)
 		    && (device == entry->id.device)
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#97 lore raw

PATCH 89/112 ACPI: track opregion names to avoid driver resource conflicts.

In reply to Len Brown

From: Thomas Renninger <[email protected]>

Small ACPICA extension to be able to store the name of operation regions in osl.c later

In ACPI, AML can define accesses to IO ports and System Memory by Operation Regions. Those are not registered as done by PNPACPI using resource templates (and _CRS/_SRS methods).

The IO ports and System Memory regions may get accessed by arbitrary AML code.
When native drivers are accessing the same resources bad things can happen
(e.g. a critical shutdown temperature of 3000 C every 2 months or so).

It is not really possible to register the operation regions via request_resource, as they often overlap with pnp or other resources (e.g. statically setup IO resources below 0x100).

This approach stores all Operation Region declarations (IO and System Memory only) at ACPI table parse time. It offers a similar functionality like request_region and let drivers which are known to possibly use the same IO ports and Memory which are also often used by ACPI (hwmon and i2c) check for ACPI interference.

A boot parameter acpi_enforce_resources=strict/lax/no is provided, which is default set to lax:
- strict: let conflicting drivers fail to load with an error message
- lax: let conflicting driver work normal with a warning message
- no: no functional change at all
Depending on the feedback and the kind of interferences we see, this should be set to strict at later time.

Goal of this patch set is:
- Identify ACPI interferences in bug reports (very hard to reproduce and to identify)
- Find BIOSes for that an ACPI driver should exist for specific HW instead of a native one.
- stability in general

Provide acpi_check_{mem_}region.

Drivers can additionally check against possible ACPI interference by also invoking this shortly before they call request_region.
If -EBUSY is returned, the driver must not load.
Use acpi_enforce_resources=strict/lax/no options to:
- strict: let conflicting drivers fail to load with an error message
- lax: let conflicting driver work normal with a warning message
- no: no functional change at all

Cc "Mark M. Hoffman" <[email protected]>
Cc Jean Delvare <[email protected]>
Cc Len Brown <[email protected]>
Cc Bjorn Helgaas <[email protected]>
---
 drivers/acpi/dispatcher/dsopcode.c |    4 +-
 drivers/acpi/osl.c                 |  175 +++++++++++++++++++++++++++++++++++-
 include/acpi/acpiosxf.h            |    4 +-
 include/linux/acpi.h               |   17 ++++
 4 files changed, 195 insertions(+), 5 deletions(-)
drivers/acpi/dispatcher/dsopcode.c +3 -1
index fc9da48..f501e08 100644
@@ -359,7 +359,9 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
 
 	status = acpi_os_validate_address(obj_desc->region.space_id,
 					  obj_desc->region.address,
-					  (acpi_size) obj_desc->region.length);
+					  (acpi_size) obj_desc->region.length,
+					  acpi_ut_get_node_name(node));
+
 	if (ACPI_FAILURE(status)) {
 		/*
 		 * Invalid address/length. We will emit an error message and mark
drivers/acpi/osl.c +173 -2

201 lines not on this page · raw message

include/acpi/acpiosxf.h +2 -2
index ca882b8..c082c7d 100644
@@ -239,8 +239,8 @@ acpi_status acpi_os_validate_interface(char *interface);
 acpi_status acpi_osi_invalidate(char* interface);
 
 acpi_status
-acpi_os_validate_address(u8 space_id,
-			 acpi_physical_address address, acpi_size length);
+acpi_os_validate_address(u8 space_id, acpi_physical_address address,
+			 acpi_size length, char *name);
 
 u64 acpi_os_get_timer(void);
 
include/linux/acpi.h +17 -0
index 63f2e6e..893f90a 100644
@@ -217,6 +217,11 @@ extern int pnpacpi_disabled;
 #define PXM_INVAL	(-1)
 #define NID_INVAL	(-1)
 
+int acpi_check_region(resource_size_t start, resource_size_t n,
+		      const char *name);
+int acpi_check_mem_region(resource_size_t start, resource_size_t n,
+		      const char *name);
+
 #else	/* CONFIG_ACPI */
 
 static inline int acpi_boot_init(void)
@@ -229,5 +234,17 @@ static inline int acpi_boot_table_init(void)
 	return 0;
 }
 
+static inline int acpi_check_region(resource_size_t start, resource_size_t n,
+				    const char *name)
+{
+	return 0;
+}
+
+static inline int acpi_check_mem_region(resource_size_t start,
+					resource_size_t n, const char *name)
+{
+	return 0;
+}
+
 #endif	/* !CONFIG_ACPI */
 #endif	/*_LINUX_ACPI_H*/
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#98 lore raw

PATCH 90/112 ACPI: Export acpi_check_resource_conflict

In reply to Len Brown

From: Thomas Renninger <[email protected]>

Export acpi_check_resource_conflict(), sometimes drivers already have a struct resource at hand so no need to use the wrappers to build a new one.

---
 drivers/acpi/osl.c   |    3 ++-
 include/linux/acpi.h |    8 ++++++++
 2 files changed, 10 insertions(+), 1 deletions(-)
drivers/acpi/osl.c +2 -1
index 222f7b1..bc1604b 100644
@@ -1157,7 +1157,7 @@ __setup("acpi_enforce_resources=", acpi_enforce_resources_setup);
 
 /* Check for resource conflicts between ACPI OperationRegions and native
  * drivers */
-static int acpi_check_resource_conflict(struct resource *res)
+int acpi_check_resource_conflict(struct resource *res)
 {
 	struct acpi_res_list *res_list_elem;
 	int ioport;
@@ -1207,6 +1207,7 @@ static int acpi_check_resource_conflict(struct resource *res)
 	}
 	return 0;
 }
+EXPORT_SYMBOL(acpi_check_resource_conflict);
 
 int acpi_check_region(resource_size_t start, resource_size_t n,
 		      const char *name)
include/linux/acpi.h +8 -0
index 893f90a..a031df8 100644
@@ -25,6 +25,7 @@
 #ifndef _LINUX_ACPI_H
 #define _LINUX_ACPI_H
 
+#include <linux/ioport.h>	/* for struct resource */
 
 #ifdef	CONFIG_ACPI
 
@@ -217,6 +218,8 @@ extern int pnpacpi_disabled;
 #define PXM_INVAL	(-1)
 #define NID_INVAL	(-1)
 
+int acpi_check_resource_conflict(struct resource *res);
+
 int acpi_check_region(resource_size_t start, resource_size_t n,
 		      const char *name);
 int acpi_check_mem_region(resource_size_t start, resource_size_t n,
@@ -234,6 +237,11 @@ static inline int acpi_boot_table_init(void)
 	return 0;
 }
 
+static inline int acpi_check_resource_conflict(struct resource *res)
+{
+	return 0;
+}
+
 static inline int acpi_check_region(resource_size_t start, resource_size_t n,
 				    const char *name)
 {
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#99 lore raw

PATCH 91/112 ACPI: thinkpad-acpi: second TP_EC_FAN_FULLSPEED should be TP_EC_FAN_AUTO

In reply to Len Brown

From: Roel Kluin <[email protected]>

fix bug in safety net for TPEC fan control mode
eaa7571b2d1a08873e4bdd8e6db3431df61cd9ad

---
 drivers/misc/thinkpad_acpi.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/misc/thinkpad_acpi.c +1 -1
index 8ef0afc..7ba1aca 100644
@@ -4790,7 +4790,7 @@ static int fan_set_level(int level)
 		 * or FULLSPEED mode bits and just ignore them */
 		if (level & TP_EC_FAN_FULLSPEED)
 			level |= 7;	/* safety min speed 7 */
-		else if (level & TP_EC_FAN_FULLSPEED)
+		else if (level & TP_EC_FAN_AUTO)
 			level |= 4;	/* safety min speed 4 */
 
 		if (!acpi_ec_write(fan_status_offset, level))
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#100 lore raw

PATCH 92/112 PM: documentation cleanups

In reply to Len Brown

From: Pavel Machek <[email protected]>

---
 Documentation/kernel-parameters.txt |    6 ++++--
 Documentation/power/swsusp.txt      |    5 +++++
 drivers/acpi/hardware/hwsleep.c     |    2 +-
 drivers/acpi/sleep/main.c           |    2 +-
 kernel/power/Kconfig                |    9 ++++++---
 5 files changed, 17 insertions(+), 7 deletions(-)
Documentation/kernel-parameters.txt +4 -2
index 8fd5aa4..8ea41b6 100644
@@ -147,8 +147,10 @@ and is between 256 and 4096 characters. It is defined in the file
 			default: 0
 
 	acpi_sleep=	[HW,ACPI] Sleep options
-			Format: { s3_bios, s3_mode }
-			See Documentation/power/video.txt
+			Format: { s3_bios, s3_mode, s3_beep }
+			See Documentation/power/video.txt for s3_bios and s3_mode.
+			s3_beep is for debugging; it makes the PC's speaker beep
+			as soon as the kernel's real-mode entry point is called.
 
 	acpi_sci=	[HW,ACPI] ACPI System Control Interrupt trigger mode
 			Format: { level | edge | high | low }
Documentation/power/swsusp.txt +5 -0
index aea7e92..9d60ab7 100644
@@ -386,6 +386,11 @@ before suspending; then remount them after resuming.
 There is a work-around for this problem.  For more information, see
 Documentation/usb/persist.txt.
 
+Q: Can I suspend-to-disk using a swap partition under LVM?
+
+A: No. You can suspend successfully, but you'll not be able to
+resume. uswsusp should be able to work with LVM. See suspend.sf.net.
+
 Q: I upgraded the kernel from 2.6.15 to 2.6.16. Both kernels were
 compiled with the similar configuration files. Anyway I found that
 suspend to disk (and resume) is much slower on 2.6.16 compared to
drivers/acpi/hardware/hwsleep.c +1 -1
index fd1c4ba..058d0be 100644
@@ -286,13 +286,13 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
 	}
 
 	/*
+	 * 1) Disable/Clear all GPEs
 	 * 2) Enable all wakeup GPEs
 	 */
 	status = acpi_hw_disable_all_gpes();
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
-
 	acpi_gbl_system_awake_and_running = FALSE;
 
 	status = acpi_hw_enable_all_wakeup_gpes();
drivers/acpi/sleep/main.c +1 -1
index 485de13..c9a733f 100644
@@ -170,7 +170,7 @@ static int acpi_pm_enter(suspend_state_t pm_state)
 	/* Reprogram control registers and execute _BFS */
 	acpi_leave_sleep_state_prep(acpi_state);
 
-	/* ACPI 3.0 specs (P62) says that it's the responsabilty
+	/* ACPI 3.0 specs (P62) says that it's the responsibility
 	 * of the OSPM to clear the status bit [ implying that the
 	 * POWER_BUTTON event should not reach userspace ]
 	 */
kernel/power/Kconfig +6 -3
index ef9b802..7983317 100644
@@ -74,8 +74,8 @@ config PM_TRACE_RTC
 	RTC across reboots, so that you can debug a machine that just hangs
 	during suspend (or more commonly, during resume).
 
-	To use this debugging feature you should attempt to suspend the machine,
-	then reboot it, then run
+	To use this debugging feature you should attempt to suspend the
+	machine, reboot it and then run
 
 		dmesg -s 1000000 | grep 'hash matches'
 
@@ -123,7 +123,10 @@ config HIBERNATION
 	  called "hibernation" in user interfaces.  STD checkpoints the
 	  system and powers it off; and restores that checkpoint on reboot.
 
-	  You can suspend your machine with 'echo disk > /sys/power/state'.
+	  You can suspend your machine with 'echo disk > /sys/power/state'
+	  after placing resume=/dev/swappartition on the kernel command line
+	  in your bootloader's configuration file.
+
 	  Alternatively, you can use the additional userland tools available
 	  from <http://suspend.sf.net>.
 
Signature · 1 line
1.5.4.23.gef5b9
author reviewer
#101 lore raw

PATCH 93/112 ACPI: idle: Fix acpi_safe_halt usages and interrupt enabling/disabling

In reply to Len Brown

From: [email protected] <[email protected]>

acpi_safe_halt() needs interrupts to be disabled for atomic need_resched check and safe halt. Otherwise we may miss an interrupt and go into halt.

acpi_safe_halt() also does not enable interrupts on all return paths.

So the callers should handle enable and disable interrupts around it.

---
 drivers/acpi/processor_idle.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)
drivers/acpi/processor_idle.c +11 -0
index 199ea21..106a229 100644
@@ -201,6 +201,10 @@ static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2)
 		return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2);
 }
 
+/*
+ * Callers should disable interrupts before the call and enable
+ * interrupts after return.
+ */
 static void acpi_safe_halt(void)
 {
 	current_thread_info()->status &= ~TS_POLLING;
@@ -413,6 +417,8 @@ static void acpi_processor_idle(void)
 			pm_idle_save();
 		else
 			acpi_safe_halt();
+
+		local_irq_enable();
 		return;
 	}
 
@@ -521,6 +527,7 @@ static void acpi_processor_idle(void)
 		 *       skew otherwise.
 		 */
 		sleep_ticks = 0xFFFFFFFF;
+		local_irq_enable();
 		break;
 
 	case ACPI_STATE_C2:
@@ -1403,11 +1410,13 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
 	if (unlikely(!pr))
 		return 0;
 
+	local_irq_disable();
 	if (pr->flags.bm_check)
 		acpi_idle_update_bm_rld(pr, cx);
 
 	acpi_safe_halt();
 
+	local_irq_enable();
 	cx->usage++;
 
 	return 0;
@@ -1517,7 +1526,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
 		if (dev->safe_state) {
 			return dev->safe_state->enter(dev, dev->safe_state);
 		} else {
+			local_irq_disable();
 			acpi_safe_halt();
+			local_irq_enable();
 			return 0;
 		}
 	}
Signature · 1 line
1.5.4.23.gef5b9