Skip to contentSkip to conversation

ACPI patches for 2.6.29-rc1

PATCH New Len Brown 1 participant 24 messages Jan 16, 2009

Subsystems (12)
Documentation x86 ACPI PCI +8 more subsystems
lore
Share & tools
lore

Len Brown

author reviewer
#0 lore raw

pushing this batch now, hopefully to make rc2

cheers,
-Len

author reviewer
#1 lore raw

PATCH 1/23 ACPI: thinkpad-acpi: update documents for the new location

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

Update documentation to reflect the new location of the thinkpad-acpi driver.

---
 Documentation/laptops/thinkpad-acpi.txt |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)
Documentation/laptops/thinkpad-acpi.txt +2 -1
index 898b498..ddc371e 100644
@@ -16,7 +16,8 @@ supported by the generic Linux ACPI drivers.
 This driver used to be named ibm-acpi until kernel 2.6.21 and release
 0.13-20070314.  It used to be in the drivers/acpi tree, but it was
 moved to the drivers/misc tree and renamed to thinkpad-acpi for kernel
-2.6.22, and release 0.14.
+2.6.22, and release 0.14.  It was moved to drivers/platform/x86 for
+kernel 2.6.29.
 
 The driver is named "thinkpad-acpi".  In some places, like module
 names, "thinkpad_acpi" is used because of userspace issues.
Signature · 1 line
1.5.6.6
author reviewer
#2 lore raw

PATCH 2/23 ACPI: thinkpad-acpi: struct device - replace bus_id with dev_name(), dev_set_name()

In reply to Len Brown

From: Kay Sievers <[email protected]>

---
 drivers/platform/x86/thinkpad_acpi.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)
drivers/platform/x86/thinkpad_acpi.c +4 -4
index 3478453..ee3fa00 100644
@@ -2375,7 +2375,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 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,
+					dev_name(&ibm->acpi->device->dev),
 					event, 0);
 		return;
 	}
@@ -2505,7 +2505,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 		if (!ignore_acpi_ev && send_acpi_ev) {
 			acpi_bus_generate_netlink_event(
 					ibm->acpi->device->pnp.device_class,
-					ibm->acpi->device->dev.bus_id,
+					dev_name(&ibm->acpi->device->dev),
 					event, hkey);
 		}
 	}
@@ -3724,7 +3724,7 @@ static void dock_notify(struct ibm_struct *ibm, u32 event)
 	}
 	acpi_bus_generate_proc_event(ibm->acpi->device, event, data);
 	acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
-					  ibm->acpi->device->dev.bus_id,
+					  dev_name(&ibm->acpi->device->dev),
 					  event, data);
 }
 
@@ -3826,7 +3826,7 @@ static void bay_notify(struct ibm_struct *ibm, u32 event)
 {
 	acpi_bus_generate_proc_event(ibm->acpi->device, event, 0);
 	acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
-					  ibm->acpi->device->dev.bus_id,
+					  dev_name(&ibm->acpi->device->dev),
 					  event, 0);
 }
 
Signature · 1 line
1.5.6.6
author reviewer
#3 lore raw

PATCH 3/23 ACPI: thinkpad-acpi: debug facility to emulate the rf switches

In reply to Len Brown

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

This code is required to keep the thinkpad-acpi maintainer sane, and it is disabled by default.

Add a debug facility to simulate an rfkill hardware rocker switch, a bluetooth rfkill soft-switch, a WWAN rfkill soft-switch on thinkpads.

The simulated switches obviously do not kill any radios in hardware or firmware (unlike the real one). They also don't issue deprecated proc events.

---
 drivers/platform/x86/Kconfig         |   11 ++
 drivers/platform/x86/thinkpad_acpi.c |  190 ++++++++++++++++++++++++++++++++++
 2 files changed, 201 insertions(+), 0 deletions(-)
drivers/platform/x86/Kconfig +11 -0
index e65448e..431772b 100644
@@ -192,6 +192,17 @@ config THINKPAD_ACPI
 
 	  If you have an IBM or Lenovo ThinkPad laptop, say Y or M here.
 
+config THINKPAD_ACPI_DEBUGFACILITIES
+	bool "Maintainer debug facilities"
+	depends on THINKPAD_ACPI
+	default n
+	---help---
+	  Enables extra stuff in the thinkpad-acpi which is completely useless
+	  for normal use.  Read the driver source to find out what it does.
+
+	  Say N here, unless you were told by a kernel maintainer to do
+	  otherwise.
+
 config THINKPAD_ACPI_DEBUG
 	bool "Verbose debug mode"
 	depends on THINKPAD_ACPI
drivers/platform/x86/thinkpad_acpi.c +190 -0

268 lines not on this page · raw message

Signature · 1 line
1.5.6.6
author reviewer
#4 lore raw

PATCH 4/23 ACPI: thinkpad-acpi: resume with radios disabled

In reply to Len Brown

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

Instruct the firmware to not enable the radios when resuming. This is safer, and the rfkill core will take care to manually enable any radios that need to be enabled.

---
 drivers/platform/x86/thinkpad_acpi.c |   66 ++++++++++++++++++++++++++++-----
 1 files changed, 56 insertions(+), 10 deletions(-)
drivers/platform/x86/thinkpad_acpi.c +56 -10
index a086ce8..b2c5913 100644
@@ -122,6 +122,27 @@ enum {
 #define TPACPI_HKEY_INPUT_PRODUCT	0x5054 /* "TP" */
 #define TPACPI_HKEY_INPUT_VERSION	0x4101
 
+/* ACPI \WGSV commands */
+enum {
+	TP_ACPI_WGSV_GET_STATE		= 0x01, /* Get state information */
+	TP_ACPI_WGSV_PWR_ON_ON_RESUME	= 0x02, /* Resume WWAN powered on */
+	TP_ACPI_WGSV_PWR_OFF_ON_RESUME	= 0x03,	/* Resume WWAN powered off */
+	TP_ACPI_WGSV_SAVE_STATE		= 0x04, /* Save state for S4/S5 */
+};
+
+/* TP_ACPI_WGSV_GET_STATE bits */
+enum {
+	TP_ACPI_WGSV_STATE_WWANEXIST	= 0x0001, /* WWAN hw available */
+	TP_ACPI_WGSV_STATE_WWANPWR	= 0x0002, /* WWAN radio enabled */
+	TP_ACPI_WGSV_STATE_WWANPWRRES	= 0x0004, /* WWAN state at resume */
+	TP_ACPI_WGSV_STATE_WWANBIOSOFF	= 0x0008, /* WWAN disabled in BIOS */
+	TP_ACPI_WGSV_STATE_BLTHEXIST	= 0x0001, /* BLTH hw available */
+	TP_ACPI_WGSV_STATE_BLTHPWR	= 0x0002, /* BLTH radio enabled */
+	TP_ACPI_WGSV_STATE_BLTHPWRRES	= 0x0004, /* BLTH state at resume */
+	TP_ACPI_WGSV_STATE_BLTHBIOSOFF	= 0x0008, /* BLTH disabled in BIOS */
+	TP_ACPI_WGSV_STATE_UWBEXIST	= 0x0010, /* UWB hw available */
+	TP_ACPI_WGSV_STATE_UWBPWR	= 0x0020, /* UWB radio enabled */
+};
 
 /****************************************************************************
  * Main driver
@@ -2766,11 +2787,28 @@ 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 */
+	TP_ACPI_BLUETOOTH_RESUMECTRL	= 0x04,	/* Bluetooth state at resume:
+						   off / last state */
+};
+
+enum {
+	/* ACPI \BLTH commands */
+	TP_ACPI_BLTH_GET_ULTRAPORT_ID	= 0x00, /* Get Ultraport BT ID */
+	TP_ACPI_BLTH_GET_PWR_ON_RESUME	= 0x01, /* Get power-on-resume state */
+	TP_ACPI_BLTH_PWR_ON_ON_RESUME	= 0x02, /* Resume powered on */
+	TP_ACPI_BLTH_PWR_OFF_ON_RESUME	= 0x03,	/* Resume powered off */
+	TP_ACPI_BLTH_SAVE_STATE		= 0x05, /* Save state for S4/S5 */
 };
 
 static struct rfkill *tpacpi_bluetooth_rfkill;
 
+static void bluetooth_suspend(pm_message_t state)
+{
+	/* Try to make sure radio will resume powered off */
+	acpi_evalf(NULL, NULL, "\\BLTH", "vd",
+		   TP_ACPI_BLTH_PWR_OFF_ON_RESUME);
+}
+
 static int bluetooth_get_radiosw(void)
 {
 	int status;
@@ -2830,12 +2868,11 @@ static int bluetooth_set_radiosw(int radio_on, int update_rfk)
 	}
 #endif
 
-	if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
-		return -EIO;
+	/* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */
 	if (radio_on)
-		status |= TP_ACPI_BLUETOOTH_RADIOSSW;
+		status = TP_ACPI_BLUETOOTH_RADIOSSW;
 	else
-		status &= ~TP_ACPI_BLUETOOTH_RADIOSSW;
+		status = 0;
 	if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
 		return -EIO;
 
@@ -3012,6 +3049,7 @@ static struct ibm_struct bluetooth_driver_data = {
 	.read = bluetooth_read,
 	.write = bluetooth_write,
 	.exit = bluetooth_exit,
+	.suspend = bluetooth_suspend,
 };
 
 /*************************************************************************
@@ -3022,11 +3060,19 @@ 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 */
+	TP_ACPI_WANCARD_RESUMECTRL	= 0x04,	/* Wan state at resume:
+						   off / last state */
 };
 
 static struct rfkill *tpacpi_wan_rfkill;
 
+static void wan_suspend(pm_message_t state)
+{
+	/* Try to make sure radio will resume powered off */
+	acpi_evalf(NULL, NULL, "\\WGSV", "qvd",
+		   TP_ACPI_WGSV_PWR_OFF_ON_RESUME);
+}
+
 static int wan_get_radiosw(void)
 {
 	int status;
@@ -3086,12 +3132,11 @@ static int wan_set_radiosw(int radio_on, int update_rfk)
 	}
 #endif
 
-	if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
-		return -EIO;
+	/* We make sure to keep TP_ACPI_WANCARD_RESUMECTRL off */
 	if (radio_on)
-		status |= TP_ACPI_WANCARD_RADIOSSW;
+		status = TP_ACPI_WANCARD_RADIOSSW;
 	else
-		status &= ~TP_ACPI_WANCARD_RADIOSSW;
+		status = 0;
 	if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
 		return -EIO;
 
@@ -3266,6 +3311,7 @@ static struct ibm_struct wan_driver_data = {
 	.read = wan_read,
 	.write = wan_write,
 	.exit = wan_exit,
+	.suspend = wan_suspend,
 };
 
 /*************************************************************************
Signature · 1 line
1.5.6.6
author reviewer
#5 lore raw

PATCH 5/23 ACPI: thinkpad-acpi: preserve radio state across shutdown

In reply to Len Brown

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

Store in firmware NVRAM the radio state on machine shutdown for WWAN and bluetooth. Also, try to set the initial boot state of these radios as the rfkill default state for their respective classes.

---
 drivers/platform/x86/thinkpad_acpi.c |   59 +++++++++++++++++++++++++++++++--
 1 files changed, 55 insertions(+), 4 deletions(-)
drivers/platform/x86/thinkpad_acpi.c +55 -4
index b2c5913..27d709b 100644
@@ -222,6 +222,7 @@ struct ibm_struct {
 	void (*exit) (void);
 	void (*resume) (void);
 	void (*suspend) (pm_message_t state);
+	void (*shutdown) (void);
 
 	struct list_head all_drivers;
 
@@ -759,6 +760,18 @@ static int tpacpi_resume_handler(struct platform_device *pdev)
 	return 0;
 }
 
+static void tpacpi_shutdown_handler(struct platform_device *pdev)
+{
+	struct ibm_struct *ibm, *itmp;
+
+	list_for_each_entry_safe(ibm, itmp,
+				 &tpacpi_all_drivers,
+				 all_drivers) {
+		if (ibm->shutdown)
+			(ibm->shutdown)();
+	}
+}
+
 static struct platform_driver tpacpi_pdriver = {
 	.driver = {
 		.name = TPACPI_DRVR_NAME,
@@ -766,6 +779,7 @@ static struct platform_driver tpacpi_pdriver = {
 	},
 	.suspend = tpacpi_suspend_handler,
 	.resume = tpacpi_resume_handler,
+	.shutdown = tpacpi_shutdown_handler,
 };
 
 static struct platform_driver tpacpi_hwmon_pdriver = {
@@ -957,7 +971,22 @@ static int __init tpacpi_new_rfkill(const unsigned int id,
 			int (*get_state)(void *, enum rfkill_state *))
 {
 	int res;
-	enum rfkill_state initial_state;
+	enum rfkill_state initial_state = RFKILL_STATE_SOFT_BLOCKED;
+
+	res = get_state(NULL, &initial_state);
+	if (res < 0) {
+		printk(TPACPI_ERR
+			"failed to read initial state for %s, error %d; "
+			"will turn radio off\n", name, res);
+	} else {
+		/* try to set the initial state as the default for the rfkill
+		 * type, since we ask the firmware to preserve it across S5 in
+		 * NVRAM */
+		rfkill_set_default(rfktype,
+				(initial_state == RFKILL_STATE_UNBLOCKED) ?
+					RFKILL_STATE_UNBLOCKED :
+					RFKILL_STATE_SOFT_BLOCKED);
+	}
 
 	*rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype);
 	if (!*rfk) {
@@ -969,9 +998,7 @@ static int __init tpacpi_new_rfkill(const unsigned int id,
 	(*rfk)->name = name;
 	(*rfk)->get_state = get_state;
 	(*rfk)->toggle_radio = toggle_radio;
-
-	if (!get_state(NULL, &initial_state))
-		(*rfk)->state = initial_state;
+	(*rfk)->state = initial_state;
 
 	res = rfkill_register(*rfk);
 	if (res < 0) {
@@ -2943,8 +2970,19 @@ static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state)
 	return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
 }
 
+static void bluetooth_shutdown(void)
+{
+	/* Order firmware to save current state to NVRAM */
+	if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd",
+			TP_ACPI_BLTH_SAVE_STATE))
+		printk(TPACPI_NOTICE
+			"failed to save bluetooth state to NVRAM\n");
+}
+
 static void bluetooth_exit(void)
 {
+	bluetooth_shutdown();
+
 	if (tpacpi_bluetooth_rfkill)
 		rfkill_unregister(tpacpi_bluetooth_rfkill);
 
@@ -3050,6 +3088,7 @@ static struct ibm_struct bluetooth_driver_data = {
 	.write = bluetooth_write,
 	.exit = bluetooth_exit,
 	.suspend = bluetooth_suspend,
+	.shutdown = bluetooth_shutdown,
 };
 
 /*************************************************************************
@@ -3207,8 +3246,19 @@ static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state)
 	return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
 }
 
+static void wan_shutdown(void)
+{
+	/* Order firmware to save current state to NVRAM */
+	if (!acpi_evalf(NULL, NULL, "\\WGSV", "vd",
+			TP_ACPI_WGSV_SAVE_STATE))
+		printk(TPACPI_NOTICE
+			"failed to save WWAN state to NVRAM\n");
+}
+
 static void wan_exit(void)
 {
+	wan_shutdown();
+
 	if (tpacpi_wan_rfkill)
 		rfkill_unregister(tpacpi_wan_rfkill);
 
@@ -3312,6 +3362,7 @@ static struct ibm_struct wan_driver_data = {
 	.write = wan_write,
 	.exit = wan_exit,
 	.suspend = wan_suspend,
+	.shutdown = wan_shutdown,
 };
 
 /*************************************************************************
Signature · 1 line
1.5.6.6
author reviewer
#6 lore raw

PATCH 6/23 ACPI: thinkpad-acpi: add UWB radio support

In reply to Len Brown

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

Add rfkill support for USB UWB radio devices on very recent ThinkPad laptop models.

The new subdriver is moslty a trimmed down copy of the wwan subdriver.

---
 Documentation/laptops/thinkpad-acpi.txt |   18 +++
 drivers/platform/x86/thinkpad_acpi.c    |  206 ++++++++++++++++++++++++++++++-
 2 files changed, 223 insertions(+), 1 deletions(-)
Documentation/laptops/thinkpad-acpi.txt +18 -0
index ddc371e..91c0001 100644
@@ -1413,6 +1413,24 @@ Sysfs notes:
 	rfkill controller switch "tpacpi_wwan_sw": refer to
 	Documentation/rfkill.txt for details.
 
+EXPERIMENTAL: UWB
+-----------------
+
+This feature is marked EXPERIMENTAL because it has not been extensively
+tested and validated in various ThinkPad models yet.  The feature may not
+work as expected. USE WITH CAUTION! To use this feature, you need to supply
+the experimental=1 parameter when loading the module.
+
+sysfs rfkill class: switch "tpacpi_uwb_sw"
+
+This feature exports an rfkill controller for the UWB device, if one is
+present and enabled in the BIOS.
+
+Sysfs notes:
+
+	rfkill controller switch "tpacpi_uwb_sw": refer to
+	Documentation/rfkill.txt for details.
+
 Multiple Commands, Module Parameters
 ------------------------------------
 
drivers/platform/x86/thinkpad_acpi.c +205 -1

296 lines not on this page · raw message

Signature · 1 line
1.5.6.6
author reviewer
#7 lore raw

PATCH 7/23 ACPI: thinkpad-acpi: use killable instead of interruptible mutexes

In reply to Len Brown

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

Unfortunately, POSIX in all of its braindamage, do not state that userspace has to deal with EINTR in read/write and friends... so, lesser code just doesn't.

Switch from *_interruptible to *_killable on the sysfs- and procfs-related mutexes. This closes this possible can of worms.

---
 drivers/platform/x86/thinkpad_acpi.c |   26 +++++++++++++-------------
 1 files changed, 13 insertions(+), 13 deletions(-)
drivers/platform/x86/thinkpad_acpi.c +13 -13
index c1d4041..7670c8e 100644
@@ -1878,7 +1878,7 @@ static ssize_t hotkey_mask_show(struct device *dev,
 {
 	int res;
 
-	if (mutex_lock_interruptible(&hotkey_mutex))
+	if (mutex_lock_killable(&hotkey_mutex))
 		return -ERESTARTSYS;
 	res = hotkey_mask_get();
 	mutex_unlock(&hotkey_mutex);
@@ -1897,7 +1897,7 @@ static ssize_t hotkey_mask_store(struct device *dev,
 	if (parse_strtoul(buf, 0xffffffffUL, &t))
 		return -EINVAL;
 
-	if (mutex_lock_interruptible(&hotkey_mutex))
+	if (mutex_lock_killable(&hotkey_mutex))
 		return -ERESTARTSYS;
 
 	res = hotkey_mask_set(t);
@@ -1983,7 +1983,7 @@ static ssize_t hotkey_source_mask_store(struct device *dev,
 		((t & ~TPACPI_HKEY_NVRAM_KNOWN_MASK) != 0))
 		return -EINVAL;
 
-	if (mutex_lock_interruptible(&hotkey_mutex))
+	if (mutex_lock_killable(&hotkey_mutex))
 		return -ERESTARTSYS;
 
 	HOTKEY_CONFIG_CRITICAL_START
@@ -2018,7 +2018,7 @@ static ssize_t hotkey_poll_freq_store(struct device *dev,
 	if (parse_strtoul(buf, 25, &t))
 		return -EINVAL;
 
-	if (mutex_lock_interruptible(&hotkey_mutex))
+	if (mutex_lock_killable(&hotkey_mutex))
 		return -ERESTARTSYS;
 
 	hotkey_poll_freq = t;
@@ -2754,7 +2754,7 @@ static int hotkey_read(char *p)
 		return len;
 	}
 
-	if (mutex_lock_interruptible(&hotkey_mutex))
+	if (mutex_lock_killable(&hotkey_mutex))
 		return -ERESTARTSYS;
 	res = hotkey_status_get(&status);
 	if (!res)
@@ -2785,7 +2785,7 @@ static int hotkey_write(char *buf)
 	if (!tp_features.hotkey)
 		return -ENODEV;
 
-	if (mutex_lock_interruptible(&hotkey_mutex))
+	if (mutex_lock_killable(&hotkey_mutex))
 		return -ERESTARTSYS;
 
 	status = -1;
@@ -5311,7 +5311,7 @@ static int brightness_set(int value)
 	    value < 0)
 		return -EINVAL;
 
-	res = mutex_lock_interruptible(&brightness_mutex);
+	res = mutex_lock_killable(&brightness_mutex);
 	if (res < 0)
 		return res;
 
@@ -5849,7 +5849,7 @@ static int fan_get_status_safe(u8 *status)
 	int rc;
 	u8 s;
 
-	if (mutex_lock_interruptible(&fan_mutex))
+	if (mutex_lock_killable(&fan_mutex))
 		return -ERESTARTSYS;
 	rc = fan_get_status(&s);
 	if (!rc)
@@ -5932,7 +5932,7 @@ static int fan_set_level_safe(int level)
 	if (!fan_control_allowed)
 		return -EPERM;
 
-	if (mutex_lock_interruptible(&fan_mutex))
+	if (mutex_lock_killable(&fan_mutex))
 		return -ERESTARTSYS;
 
 	if (level == TPACPI_FAN_LAST_LEVEL)
@@ -5954,7 +5954,7 @@ static int fan_set_enable(void)
 	if (!fan_control_allowed)
 		return -EPERM;
 
-	if (mutex_lock_interruptible(&fan_mutex))
+	if (mutex_lock_killable(&fan_mutex))
 		return -ERESTARTSYS;
 
 	switch (fan_control_access_mode) {
@@ -6009,7 +6009,7 @@ static int fan_set_disable(void)
 	if (!fan_control_allowed)
 		return -EPERM;
 
-	if (mutex_lock_interruptible(&fan_mutex))
+	if (mutex_lock_killable(&fan_mutex))
 		return -ERESTARTSYS;
 
 	rc = 0;
@@ -6047,7 +6047,7 @@ static int fan_set_speed(int speed)
 	if (!fan_control_allowed)
 		return -EPERM;
 
-	if (mutex_lock_interruptible(&fan_mutex))
+	if (mutex_lock_killable(&fan_mutex))
 		return -ERESTARTSYS;
 
 	rc = 0;
@@ -6249,7 +6249,7 @@ static ssize_t fan_pwm1_store(struct device *dev,
 	/* scale down from 0-255 to 0-7 */
 	newlevel = (s >> 5) & 0x07;
 
-	if (mutex_lock_interruptible(&fan_mutex))
+	if (mutex_lock_killable(&fan_mutex))
 		return -ERESTARTSYS;
 
 	rc = fan_get_status(&status);
Signature · 1 line
1.5.6.6
author reviewer
#8 lore raw

PATCH 8/23 ACPI: thinkpad-acpi: clean up hotkey_notify()

In reply to Len Brown

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

Clean up the hotkey_notify() handler, which handles the HKEY notifications from the ACPI firmware. It was getting too long and deep.

No functional changes.

---
 drivers/platform/x86/thinkpad_acpi.c |  174 +++++++++++++++++++++-------------
 1 files changed, 109 insertions(+), 65 deletions(-)
drivers/platform/x86/thinkpad_acpi.c +109 -65
index 7670c8e..d833ee6 100644
@@ -2571,13 +2571,100 @@ err_exit:
 	return (res < 0)? res : 1;
 }
 
+static bool hotkey_notify_hotkey(const u32 hkey,
+				 bool *send_acpi_ev,
+				 bool *ignore_acpi_ev)
+{
+	/* 0x1000-0x1FFF: key presses */
+	unsigned int scancode = hkey & 0xfff;
+	*send_acpi_ev = true;
+	*ignore_acpi_ev = false;
+
+	if (scancode > 0 && scancode < 0x21) {
+		scancode--;
+		if (!(hotkey_source_mask & (1 << scancode))) {
+			tpacpi_input_send_key(scancode);
+			*send_acpi_ev = false;
+		} else {
+			*ignore_acpi_ev = true;
+		}
+		return true;
+	}
+	return false;
+}
+
+static bool hotkey_notify_wakeup(const u32 hkey,
+				 bool *send_acpi_ev,
+				 bool *ignore_acpi_ev)
+{
+	/* 0x2000-0x2FFF: Wakeup reason */
+	*send_acpi_ev = true;
+	*ignore_acpi_ev = false;
+
+	switch (hkey) {
+	case 0x2304: /* suspend, undock */
+	case 0x2404: /* hibernation, undock */
+		hotkey_wakeup_reason = TP_ACPI_WAKEUP_UNDOCK;
+		*ignore_acpi_ev = true;
+		break;
+
+	case 0x2305: /* suspend, bay eject */
+	case 0x2405: /* hibernation, bay eject */
+		hotkey_wakeup_reason = TP_ACPI_WAKEUP_BAYEJ;
+		*ignore_acpi_ev = true;
+		break;
+
+	default:
+		return false;
+	}
+
+	if (hotkey_wakeup_reason != TP_ACPI_WAKEUP_NONE) {
+		printk(TPACPI_INFO
+		       "woke up due to a hot-unplug "
+		       "request...\n");
+		hotkey_wakeup_reason_notify_change();
+	}
+	return true;
+}
+
+static bool hotkey_notify_usrevent(const u32 hkey,
+				 bool *send_acpi_ev,
+				 bool *ignore_acpi_ev)
+{
+	/* 0x5000-0x5FFF: human interface helpers */
+	*send_acpi_ev = true;
+	*ignore_acpi_ev = false;
+
+	switch (hkey) {
+	case 0x5010: /* Lenovo new BIOS: brightness changed */
+	case 0x500b: /* X61t: tablet pen inserted into bay */
+	case 0x500c: /* X61t: tablet pen removed from bay */
+		return true;
+
+	case 0x5009: /* X41t-X61t: swivel up (tablet mode) */
+	case 0x500a: /* X41t-X61t: swivel down (normal mode) */
+		tpacpi_input_send_tabletsw();
+		hotkey_tablet_mode_notify_change();
+		*send_acpi_ev = false;
+		return true;
+
+	case 0x5001:
+	case 0x5002:
+		/* LID switch events.  Do not propagate */
+		*ignore_acpi_ev = true;
+		return true;
+
+	default:
+		return false;
+	}
+}
+
 static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 {
 	u32 hkey;
-	unsigned int scancode;
-	int send_acpi_ev;
-	int ignore_acpi_ev;
-	int unk_ev;
+	bool send_acpi_ev;
+	bool ignore_acpi_ev;
+	bool known_ev;
 
 	if (event != 0x80) {
 		printk(TPACPI_ERR
@@ -2601,105 +2688,62 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 			return;
 		}
 
-		send_acpi_ev = 1;
-		ignore_acpi_ev = 0;
-		unk_ev = 0;
+		send_acpi_ev = true;
+		ignore_acpi_ev = false;
 
 		switch (hkey >> 12) {
 		case 1:
 			/* 0x1000-0x1FFF: key presses */
-			scancode = hkey & 0xfff;
-			if (scancode > 0 && scancode < 0x21) {
-				scancode--;
-				if (!(hotkey_source_mask & (1 << scancode))) {
-					tpacpi_input_send_key(scancode);
-					send_acpi_ev = 0;
-				} else {
-					ignore_acpi_ev = 1;
-				}
-			} else {
-				unk_ev = 1;
-			}
+			known_ev = hotkey_notify_hotkey(hkey, &send_acpi_ev,
+						 &ignore_acpi_ev);
 			break;
 		case 2:
-			/* Wakeup reason */
-			switch (hkey) {
-			case 0x2304: /* suspend, undock */
-			case 0x2404: /* hibernation, undock */
-				hotkey_wakeup_reason = TP_ACPI_WAKEUP_UNDOCK;
-				ignore_acpi_ev = 1;
-				break;
-			case 0x2305: /* suspend, bay eject */
-			case 0x2405: /* hibernation, bay eject */
-				hotkey_wakeup_reason = TP_ACPI_WAKEUP_BAYEJ;
-				ignore_acpi_ev = 1;
-				break;
-			default:
-				unk_ev = 1;
-			}
-			if (hotkey_wakeup_reason != TP_ACPI_WAKEUP_NONE) {
-				printk(TPACPI_INFO
-				       "woke up due to a hot-unplug "
-				       "request...\n");
-				hotkey_wakeup_reason_notify_change();
-			}
+			/* 0x2000-0x2FFF: Wakeup reason */
+			known_ev = hotkey_notify_wakeup(hkey, &send_acpi_ev,
+						 &ignore_acpi_ev);
 			break;
 		case 3:
-			/* bay-related wakeups */
+			/* 0x3000-0x3FFF: bay-related wakeups */
 			if (hkey == 0x3003) {
 				hotkey_autosleep_ack = 1;
 				printk(TPACPI_INFO
 				       "bay ejected\n");
 				hotkey_wakeup_hotunplug_complete_notify_change();
+				known_ev = true;
 			} else {
-				unk_ev = 1;
+				known_ev = false;
 			}
 			break;
 		case 4:
-			/* dock-related wakeups */
+			/* 0x4000-0x4FFF: dock-related wakeups */
 			if (hkey == 0x4003) {
 				hotkey_autosleep_ack = 1;
 				printk(TPACPI_INFO
 				       "undocked\n");
 				hotkey_wakeup_hotunplug_complete_notify_change();
+				known_ev = true;
 			} else {
-				unk_ev = 1;
+				known_ev = false;
 			}
 			break;
 		case 5:
 			/* 0x5000-0x5FFF: human interface helpers */
-			switch (hkey) {
-			case 0x5010: /* Lenovo new BIOS: brightness changed */
-			case 0x500b: /* X61t: tablet pen inserted into bay */
-			case 0x500c: /* X61t: tablet pen removed from bay */
-				break;
-			case 0x5009: /* X41t-X61t: swivel up (tablet mode) */
-			case 0x500a: /* X41t-X61t: swivel down (normal mode) */
-				tpacpi_input_send_tabletsw();
-				hotkey_tablet_mode_notify_change();
-				send_acpi_ev = 0;
-				break;
-			case 0x5001:
-			case 0x5002:
-				/* LID switch events.  Do not propagate */
-				ignore_acpi_ev = 1;
-				break;
-			default:
-				unk_ev = 1;
-			}
+			known_ev = hotkey_notify_usrevent(hkey, &send_acpi_ev,
+						 &ignore_acpi_ev);
 			break;
 		case 7:
 			/* 0x7000-0x7FFF: misc */
 			if (tp_features.hotkey_wlsw && hkey == 0x7000) {
 				tpacpi_send_radiosw_update();
 				send_acpi_ev = 0;
+				known_ev = true;
 				break;
 			}
 			/* fallthrough to default */
 		default:
-			unk_ev = 1;
+			known_ev = false;
 		}
-		if (unk_ev) {
+		if (!known_ev) {
 			printk(TPACPI_NOTICE
 			       "unhandled HKEY event 0x%04x\n", hkey);
 		}
Signature · 1 line
1.5.6.6
author reviewer
#9 lore raw

PATCH 9/23 ACPI: thinkpad-acpi: handle HKEY thermal and battery alarms

In reply to Len Brown

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

Handle some HKEY events that are actually firmware alarms. For now, we do the simple thing: log specific messages to the log and let the thinkpad-specific event pass to userspace.

In the future, these events will be migrated to generic notifications and subsystems.

These alarms are NOT available on all ThinkPads. E.g. the T43 only issues 0x6011 and 0x6012.

---
 drivers/platform/x86/thinkpad_acpi.c |   63 +++++++++++++++++++++++++++++++--
 1 files changed, 59 insertions(+), 4 deletions(-)
drivers/platform/x86/thinkpad_acpi.c +59 -4
index d833ee6..c4e4b64 100644
@@ -174,10 +174,12 @@ enum {
 
 /* Debugging */
 #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_ALERT	KERN_ALERT  TPACPI_LOG
+#define TPACPI_CRIT	KERN_CRIT   TPACPI_LOG
+#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_INIT		0x0001
@@ -2614,6 +2616,15 @@ static bool hotkey_notify_wakeup(const u32 hkey,
 		*ignore_acpi_ev = true;
 		break;
 
+	case 0x2313: /* Battery on critical low level (S3) */
+	case 0x2413: /* Battery on critical low level (S4) */
+		printk(TPACPI_ALERT
+			"EMERGENCY WAKEUP: battery almost empty\n");
+		/* how to auto-heal: */
+		/* 2313: woke up from S3, go to S4/S5 */
+		/* 2413: woke up from S4, go to S5 */
+		break;
+
 	default:
 		return false;
 	}
@@ -2659,6 +2670,45 @@ static bool hotkey_notify_usrevent(const u32 hkey,
 	}
 }
 
+static bool hotkey_notify_thermal(const u32 hkey,
+				 bool *send_acpi_ev,
+				 bool *ignore_acpi_ev)
+{
+	/* 0x6000-0x6FFF: thermal alarms */
+	*send_acpi_ev = true;
+	*ignore_acpi_ev = false;
+
+	switch (hkey) {
+	case 0x6011:
+		printk(TPACPI_CRIT
+			"THERMAL ALARM: battery is too hot!\n");
+		/* recommended action: warn user through gui */
+		return true;
+	case 0x6012:
+		printk(TPACPI_ALERT
+			"THERMAL EMERGENCY: battery is extremely hot!\n");
+		/* recommended action: immediate sleep/hibernate */
+		return true;
+	case 0x6021:
+		printk(TPACPI_CRIT
+			"THERMAL ALARM: "
+			"a sensor reports something is too hot!\n");
+		/* recommended action: warn user through gui, that */
+		/* some internal component is too hot */
+		return true;
+	case 0x6022:
+		printk(TPACPI_ALERT
+			"THERMAL EMERGENCY: "
+			"a sensor reports something is extremely hot!\n");
+		/* recommended action: immediate sleep/hibernate */
+		return true;
+	default:
+		printk(TPACPI_ALERT
+			 "THERMAL ALERT: unknown thermal alarm received\n");
+		return false;
+	}
+}
+
 static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 {
 	u32 hkey;
@@ -2731,6 +2781,11 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 			known_ev = hotkey_notify_usrevent(hkey, &send_acpi_ev,
 						 &ignore_acpi_ev);
 			break;
+		case 6:
+			/* 0x6000-0x6FFF: thermal alarms */
+			known_ev = hotkey_notify_thermal(hkey, &send_acpi_ev,
+						 &ignore_acpi_ev);
+			break;
 		case 7:
 			/* 0x7000-0x7FFF: misc */
 			if (tp_features.hotkey_wlsw && hkey == 0x7000) {
Signature · 1 line
1.5.6.6
author reviewer
#10 lore raw

PATCH 10/23 ACPI: thinkpad-acpi: start the event hunt season

In reply to Len Brown

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

Ask users to tell us about any unhandled events they find.

---
 drivers/platform/x86/thinkpad_acpi.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
drivers/platform/x86/thinkpad_acpi.c +3 -0
index c4e4b64..d7d41ae 100644
@@ -2801,6 +2801,9 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 		if (!known_ev) {
 			printk(TPACPI_NOTICE
 			       "unhandled HKEY event 0x%04x\n", hkey);
+			printk(TPACPI_NOTICE
+			       "please report the conditions when this "
+			       "event happened to %s\n", TPACPI_MAIL);
 		}
 
 		/* Legacy events */
Signature · 1 line
1.5.6.6
author reviewer
#11 lore raw

PATCH 11/23 ACPI: thinkpad-acpi: clean-up fan subdriver quirk

In reply to Len Brown

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

Better document the Unitialized HFSP quirk, and modularize it a bit. This makes the code flow easier to read and reduces LOC.

Apply the Unitialized HFSP closer to the source (i.e. inside the get_fan_status()), this fixes a harmless buglet where at driver init with the quirk active, the user could set the hwmon pwm1 attribute and switch out of pwm1_mode=2 to pwm1_mode=0 without changing pwm1_mode directly.

---
 drivers/platform/x86/thinkpad_acpi.c |  109 ++++++++++++++++++----------------
 1 files changed, 58 insertions(+), 51 deletions(-)
drivers/platform/x86/thinkpad_acpi.c +58 -51
index d7d41ae..213219d 100644
@@ -5897,6 +5897,60 @@ TPACPI_HANDLE(sfan, ec, "SFAN",	/* 570 */
 	   );			/* all others */
 
 /*
+ * Unitialized HFSP quirk: ACPI DSDT and EC fail to initialize the
+ * HFSP register at boot, so it contains 0x07 but the Thinkpad could
+ * be in auto mode (0x80).
+ *
+ * This is corrected by any write to HFSP either by the driver, or
+ * by the firmware.
+ *
+ * We assume 0x07 really means auto mode while this quirk is active,
+ * as this is far more likely than the ThinkPad being in level 7,
+ * which is only used by the firmware during thermal emergencies.
+ */
+
+static void fan_quirk1_detect(void)
+{
+	/* In some ThinkPads, neither the EC nor the ACPI
+	 * DSDT initialize the HFSP register, and it ends up
+	 * being initially set to 0x07 when it *could* be
+	 * either 0x07 or 0x80.
+	 *
+	 * Enable for TP-1Y (T43), TP-78 (R51e),
+	 * TP-76 (R52), TP-70 (T43, R52), which are known
+	 * to be buggy. */
+	if (fan_control_initial_status == 0x07) {
+		switch (thinkpad_id.ec_model) {
+		case 0x5931: /* TP-1Y */
+		case 0x3837: /* TP-78 */
+		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");
+			tp_features.fan_ctrl_status_undef = 1;
+			;;
+		}
+	}
+}
+
+static void fan_quirk1_handle(u8 *fan_status)
+{
+	if (unlikely(tp_features.fan_ctrl_status_undef)) {
+		if (*fan_status != fan_control_initial_status) {
+			/* something changed the HFSP regisnter since
+			 * driver init time, so it is not undefined
+			 * anymore */
+			tp_features.fan_ctrl_status_undef = 0;
+		} else {
+			/* Return most likely status. In fact, it
+			 * might be the only possible status */
+			*fan_status = TP_EC_FAN_AUTO;
+		}
+	}
+}
+
+/*
  * Call with fan_mutex held
  */
 static void fan_update_desired_level(u8 status)
@@ -5934,8 +5988,10 @@ static int fan_get_status(u8 *status)
 		if (unlikely(!acpi_ec_read(fan_status_offset, &s)))
 			return -EIO;
 
-		if (likely(status))
+		if (likely(status)) {
 			*status = s;
+			fan_quirk1_handle(status);
+		}
 
 		break;
 
@@ -6245,16 +6301,6 @@ static ssize_t fan_pwm1_enable_show(struct device *dev,
 	if (res)
 		return res;
 
-	if (unlikely(tp_features.fan_ctrl_status_undef)) {
-		if (status != fan_control_initial_status) {
-			tp_features.fan_ctrl_status_undef = 0;
-		} else {
-			/* Return most likely status. In fact, it
-			 * might be the only possible status */
-			status = TP_EC_FAN_AUTO;
-		}
-	}
-
 	if (status & TP_EC_FAN_FULLSPEED) {
 		mode = 0;
 	} else if (status & TP_EC_FAN_AUTO) {
@@ -6319,14 +6365,6 @@ static ssize_t fan_pwm1_show(struct device *dev,
 	if (res)
 		return res;
 
-	if (unlikely(tp_features.fan_ctrl_status_undef)) {
-		if (status != fan_control_initial_status) {
-			tp_features.fan_ctrl_status_undef = 0;
-		} else {
-			status = TP_EC_FAN_AUTO;
-		}
-	}
-
 	if ((status &
 	     (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) != 0)
 		status = fan_control_desired_level;
@@ -6458,29 +6496,7 @@ static int __init fan_init(struct ibm_init_struct *iibm)
 		if (likely(acpi_ec_read(fan_status_offset,
 					&fan_control_initial_status))) {
 			fan_status_access_mode = TPACPI_FAN_RD_TPEC;
-
-			/* In some ThinkPads, neither the EC nor the ACPI
-			 * DSDT initialize the fan status, and it ends up
-			 * being set to 0x07 when it *could* be either
-			 * 0x07 or 0x80.
-			 *
-			 * Enable for TP-1Y (T43), TP-78 (R51e),
-			 * TP-76 (R52), TP-70 (T43, R52), which are known
-			 * to be buggy. */
-			if (fan_control_initial_status == 0x07) {
-				switch (thinkpad_id.ec_model) {
-				case 0x5931: /* TP-1Y */
-				case 0x3837: /* TP-78 */
-				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");
-					tp_features.fan_ctrl_status_undef = 1;
-					;;
-				}
-			}
+			fan_quirk1_detect();
 		} else {
 			printk(TPACPI_ERR
 			       "ThinkPad ACPI EC access misbehaving, "
@@ -6669,15 +6685,6 @@ static int fan_read(char *p)
 		if (rc < 0)
 			return rc;
 
-		if (unlikely(tp_features.fan_ctrl_status_undef)) {
-			if (status != fan_control_initial_status)
-				tp_features.fan_ctrl_status_undef = 0;
-			else
-				/* Return most likely status. In fact, it
-				 * might be the only possible status */
-				status = TP_EC_FAN_AUTO;
-		}
-
 		len += sprintf(p + len, "status:\t\t%s\n",
 			       (status != 0) ? "enabled" : "disabled");
 
Signature · 1 line
1.5.6.6
author reviewer
#12 lore raw

PATCH 12/23 ACPI: thinkpad-acpi: handle HKEY event 6030

In reply to Len Brown

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

HKEY event 0x6030 is a helper for Lenovo's Advanced Thermal Management Windows driver, which is, of course, completely undocumented.

Silence any warnings about it being an unknown alarm, and report it unmodified for userspace.

---
 drivers/platform/x86/thinkpad_acpi.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)
drivers/platform/x86/thinkpad_acpi.c +6 -0
index 213219d..886a430 100644
@@ -2702,6 +2702,12 @@ static bool hotkey_notify_thermal(const u32 hkey,
 			"a sensor reports something is extremely hot!\n");
 		/* recommended action: immediate sleep/hibernate */
 		return true;
+	case 0x6030:
+		printk(TPACPI_INFO
+			"EC reports that Thermal Table has changed\n");
+		/* recommended action: do nothing, we don't have
+		 * Lenovo ATM information */
+		return true;
 	default:
 		printk(TPACPI_ALERT
 			 "THERMAL ALERT: unknown thermal alarm received\n");
Signature · 1 line
1.5.6.6
author reviewer
#13 lore raw

PATCH 13/23 ACPI: thinkpad-acpi: bump up version to 0.22

In reply to Len Brown

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

It is about time to bump up the version.

Features added since 0.21: fan suspend/resume support, preserve radio state across power off (for some radio types), built-in UWB radio rfkill support and thermal alarm events support.

---
 Documentation/laptops/thinkpad-acpi.txt |    6 +++---
 drivers/platform/x86/thinkpad_acpi.c    |    2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)
Documentation/laptops/thinkpad-acpi.txt +3 -3
index 91c0001..41bc99f 100644
@@ -1,7 +1,7 @@
 		     ThinkPad ACPI Extras Driver
 
-                            Version 0.21
-                           May 29th, 2008
+                            Version 0.22
+                        November 23rd,  2008
 
                Borislav Deianov <[email protected]>
              Henrique de Moraes Holschuh <[email protected]>
@@ -17,7 +17,7 @@ This driver used to be named ibm-acpi until kernel 2.6.21 and release
 0.13-20070314.  It used to be in the drivers/acpi tree, but it was
 moved to the drivers/misc tree and renamed to thinkpad-acpi for kernel
 2.6.22, and release 0.14.  It was moved to drivers/platform/x86 for
-kernel 2.6.29.
+kernel 2.6.29 and release 0.22.
 
 The driver is named "thinkpad-acpi".  In some places, like module
 names, "thinkpad_acpi" is used because of userspace issues.
drivers/platform/x86/thinkpad_acpi.c +1 -1
index 886a430..bcbc051 100644
@@ -21,7 +21,7 @@
  *  02110-1301, USA.
  */
 
-#define TPACPI_VERSION "0.21"
+#define TPACPI_VERSION "0.22"
 #define TPACPI_SYSFS_VERSION 0x020200
 
 /*
Signature · 1 line
1.5.6.6
author reviewer
#14 lore raw

PATCH 14/23 ACPI: EC: Limit workaround for ASUS notebooks even more

In reply to Len Brown

From: Alexey Starikovskiy <[email protected]>

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

---
 drivers/acpi/ec.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)
drivers/acpi/ec.c +2 -1
index 8dfcbb8..e079426 100644
@@ -1027,7 +1027,8 @@ int __init acpi_ec_ecdt_probe(void)
 	 * which needs it, has fake EC._INI method, so use it as flag.
 	 * Keep boot_ec struct as it will be needed soon.
 	 */
-	if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &dummy)))
+	if (!dmi_name_in_vendors("ASUS") ||
+	    ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &dummy)))
 		return -ENODEV;
 install:
 	if (!ec_install_handlers(boot_ec)) {
Signature · 1 line
1.5.6.6
author reviewer
#15 lore raw

PATCH 15/23 ACPI: EC: Don't trust ECDT tables from ASUS

In reply to Len Brown

From: Alexey Starikovskiy <[email protected]>

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

---
 drivers/acpi/ec.c |   74 +++++++++++++++++++++-------------------------------
 1 files changed, 30 insertions(+), 44 deletions(-)
drivers/acpi/ec.c +30 -44
index e079426..a2b82c9 100644
@@ -120,31 +120,6 @@ static struct acpi_ec {
 	spinlock_t curr_lock;
 } *boot_ec, *first_ec;
 
-/* 
- * Some Asus system have exchanged ECDT data/command IO addresses.
- */
-static int print_ecdt_error(const struct dmi_system_id *id)
-{
-	printk(KERN_NOTICE PREFIX "%s detected - "
-		"ECDT has exchanged control/data I/O address\n",
-		id->ident);
-	return 0;
-}
-
-static struct dmi_system_id __cpuinitdata ec_dmi_table[] = {
-	{
-	print_ecdt_error, "Asus L4R", {
-	DMI_MATCH(DMI_BIOS_VERSION, "1008.006"),
-	DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),
-	DMI_MATCH(DMI_BOARD_NAME, "L4R") }, NULL},
-	{
-	print_ecdt_error, "Asus M6R", {
-	DMI_MATCH(DMI_BIOS_VERSION, "0207"),
-	DMI_MATCH(DMI_PRODUCT_NAME, "M6R"),
-	DMI_MATCH(DMI_BOARD_NAME, "M6R") }, NULL},
-	{},
-};
-
 /* --------------------------------------------------------------------------
                              Transaction Management
    -------------------------------------------------------------------------- */
@@ -983,8 +958,8 @@ static const struct acpi_device_id ec_device_ids[] = {
 int __init acpi_ec_ecdt_probe(void)
 {
 	acpi_status status;
+	struct acpi_ec *saved_ec = NULL;
 	struct acpi_table_ecdt *ecdt_ptr;
-	acpi_handle dummy;
 
 	boot_ec = make_acpi_ec();
 	if (!boot_ec)
@@ -998,21 +973,16 @@ int __init acpi_ec_ecdt_probe(void)
 		pr_info(PREFIX "EC description table is found, configuring boot EC\n");
 		boot_ec->command_addr = ecdt_ptr->control.address;
 		boot_ec->data_addr = ecdt_ptr->data.address;
-		if (dmi_check_system(ec_dmi_table)) {
-			/*
-			 * If the board falls into ec_dmi_table, it means
-			 * that ECDT table gives the incorrect command/status
-			 * & data I/O address. Just fix it.
-			 */
-			boot_ec->data_addr = ecdt_ptr->control.address;
-			boot_ec->command_addr = ecdt_ptr->data.address;
-		}
 		boot_ec->gpe = ecdt_ptr->gpe;
 		boot_ec->handle = ACPI_ROOT_OBJECT;
 		acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle);
-		/* Add some basic check against completely broken table */
-		if (boot_ec->data_addr != boot_ec->command_addr)
+		/* Don't trust ECDT, which comes from ASUSTek */
+		if (!dmi_name_in_vendors("ASUS"))
 			goto install;
+		saved_ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
+		if (!saved_ec)
+			return -ENOMEM;
+		memcpy(&saved_ec, boot_ec, sizeof(saved_ec));
 	/* fall through */
 	}
 	/* This workaround is needed only on some broken machines,
@@ -1023,13 +993,29 @@ int __init acpi_ec_ecdt_probe(void)
 	/* Check that acpi_get_devices actually find something */
 	if (ACPI_FAILURE(status) || !boot_ec->handle)
 		goto error;
-	/* We really need to limit this workaround, the only ASUS,
-	 * which needs it, has fake EC._INI method, so use it as flag.
-	 * Keep boot_ec struct as it will be needed soon.
-	 */
-	if (!dmi_name_in_vendors("ASUS") ||
-	    ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &dummy)))
-		return -ENODEV;
+	if (saved_ec) {
+		/* try to find good ECDT from ASUSTek */
+		if (saved_ec->command_addr != boot_ec->command_addr ||
+		    saved_ec->data_addr != boot_ec->data_addr ||
+		    saved_ec->gpe != boot_ec->gpe ||
+		    saved_ec->handle != boot_ec->handle)
+			pr_info(PREFIX "ASUSTek keeps feeding us with broken "
+			"ECDT tables, which are very hard to workaround. "
+			"Trying to use DSDT EC info instead. Please send "
+			"output of acpidump to [email protected]\n");
+		kfree(saved_ec);
+		saved_ec = NULL;
+	} else {
+		/* We really need to limit this workaround, the only ASUS,
+		* which needs it, has fake EC._INI method, so use it as flag.
+		* Keep boot_ec struct as it will be needed soon.
+		*/
+		acpi_handle dummy;
+		if (!dmi_name_in_vendors("ASUS") ||
+		    ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI",
+							&dummy)))
+			return -ENODEV;
+	}
 install:
 	if (!ec_install_handlers(boot_ec)) {
 		first_ec = boot_ec;
Signature · 1 line
1.5.6.6
author reviewer
#16 lore raw

PATCH 16/23 thermal fixup for broken BIOS which has invalid trip points.

In reply to Len Brown

From: Zhang Rui <[email protected]>

ACPI thermal driver only re-evaluate VALID trip points.

For the broken BIOS show in
http://bugzilla.kernel.org/show_bug.cgi?id=8544
the active[0] is set to invalid at boot time and it will not be re-evaluated again.
We can still get a single warning message at boot time.

http://marc.info/?l=linux-kernel&m=120496222629983&w=2

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

---
 drivers/acpi/thermal.c |   16 ++++++++++++----
 1 files changed, 12 insertions(+), 4 deletions(-)
drivers/acpi/thermal.c +12 -4
index 073ff09..99e6f1f 100644
@@ -416,7 +416,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
 	}
 
 	/* Passive (optional) */
-	if (flag & ACPI_TRIPS_PASSIVE) {
+	if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.flags.valid) ||
+		(flag == ACPI_TRIPS_INIT)) {
 		valid = tz->trips.passive.flags.valid;
 		if (psv == -1) {
 			status = AE_SUPPORT;
@@ -462,8 +463,11 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
 		memset(&devices, 0, sizeof(struct acpi_handle_list));
 		status = acpi_evaluate_reference(tz->device->handle, "_PSL",
 							NULL, &devices);
-		if (ACPI_FAILURE(status))
+		if (ACPI_FAILURE(status)) {
+			printk(KERN_WARNING PREFIX
+				"Invalid passive threshold\n");
 			tz->trips.passive.flags.valid = 0;
+		}
 		else
 			tz->trips.passive.flags.valid = 1;
 
@@ -487,7 +491,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
 		if (act == -1)
 			break; /* disable all active trip points */
 
-		if (flag & ACPI_TRIPS_ACTIVE) {
+		if ((flag == ACPI_TRIPS_INIT) || ((flag & ACPI_TRIPS_ACTIVE) &&
+			tz->trips.active[i].flags.valid)) {
 			status = acpi_evaluate_integer(tz->device->handle,
 							name, NULL, &tmp);
 			if (ACPI_FAILURE(status)) {
@@ -521,8 +526,11 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
 			memset(&devices, 0, sizeof(struct acpi_handle_list));
 			status = acpi_evaluate_reference(tz->device->handle,
 						name, NULL, &devices);
-			if (ACPI_FAILURE(status))
+			if (ACPI_FAILURE(status)) {
+				printk(KERN_WARNING PREFIX
+					"Invalid active%d threshold\n", i);
 				tz->trips.active[i].flags.valid = 0;
+			}
 			else
 				tz->trips.active[i].flags.valid = 1;
 
Signature · 6 lines
1.5.6.6

--
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
#17 lore raw

PATCH 17/23 PM: Fix freezer compilation if PM_SLEEP is unset

In reply to Len Brown

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

Freezer fails to compile if with the following configuration settings:

CONFIG_CGROUPS=y
CONFIG_CGROUP_FREEZER=y
CONFIG_MODULES=y
CONFIG_FREEZER=y
CONFIG_PM=y
CONFIG_PM_SLEEP=n

Fix this by making process.o compilation depend on CONFIG_FREEZER.

---
 kernel/power/Makefile |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)
kernel/power/Makefile +2 -1
index 597823b..d7a1016 100644
@@ -4,7 +4,8 @@ EXTRA_CFLAGS	+=	-DDEBUG
 endif
 
 obj-y				:= main.o
-obj-$(CONFIG_PM_SLEEP)		+= process.o console.o
+obj-$(CONFIG_PM_SLEEP)		+= console.o
+obj-$(CONFIG_FREEZER)		+= process.o
 obj-$(CONFIG_HIBERNATION)	+= swsusp.o disk.o snapshot.o swap.o user.o
 
 obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
Signature · 1 line
1.5.6.6
author reviewer
#18 lore raw

PATCH 18/23 kprobes: check CONFIG_FREEZER instead of CONFIG_PM

In reply to Len Brown

From: Masami Hiramatsu <[email protected]>

Check CONFIG_FREEZER instead of CONFIG_PM because kprobe booster depends on freeze_processes() and thaw_processes() when CONFIG_PREEMPT=y.

This fixes a linkage error which occurs when CONFIG_PREEMPT=y, CONFIG_PM=y and CONFIG_FREEZER=n.

---
 arch/ia64/kernel/kprobes.c |    2 +-
 arch/x86/kernel/kprobes.c  |    2 +-
 kernel/kprobes.c           |    2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)
arch/ia64/kernel/kprobes.c +1 -1
index f90be51..9adac44 100644
@@ -870,7 +870,7 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
 		return 1;
 
 ss_probe:
-#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PM)
+#if !defined(CONFIG_PREEMPT) || defined(CONFIG_FREEZER)
 	if (p->ainsn.inst_flag == INST_FLAG_BOOSTABLE && !p->post_handler) {
 		/* Boost up -- we can execute copied instructions directly */
 		ia64_psr(regs)->ri = p->ainsn.slot;
arch/x86/kernel/kprobes.c +1 -1
index 884d985..e948b28 100644
@@ -446,7 +446,7 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 static void __kprobes setup_singlestep(struct kprobe *p, struct pt_regs *regs,
 				       struct kprobe_ctlblk *kcb)
 {
-#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PM)
+#if !defined(CONFIG_PREEMPT) || defined(CONFIG_FREEZER)
 	if (p->ainsn.boostable == 1 && !p->post_handler) {
 		/* Boost up -- we can execute copied instructions directly */
 		reset_current_kprobe();
kernel/kprobes.c +1 -1
index 1b9cbdc..7ba8cd9 100644
@@ -123,7 +123,7 @@ static int collect_garbage_slots(void);
 static int __kprobes check_safety(void)
 {
 	int ret = 0;
-#if defined(CONFIG_PREEMPT) && defined(CONFIG_PM)
+#if defined(CONFIG_PREEMPT) && defined(CONFIG_FREEZER)
 	ret = freeze_processes();
 	if (ret == 0) {
 		struct task_struct *p, *q;
Signature · 1 line
1.5.6.6
author reviewer
#19 lore raw

PATCH 19/23 ACPI: fix ACPI_FADT_S4_RTC_WAKE comment

In reply to Len Brown

From: David Brownell <[email protected]>

Make the comment for ACPI_FADT_S4_RTC_WAKE match the ACPI spec; that bit has nothing to do with status bits.

---
 include/acpi/actbl.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
include/acpi/actbl.h +1 -1
index 813e4b6..bf8d4cf 100644
@@ -245,7 +245,7 @@ struct acpi_table_fadt {
 #define ACPI_FADT_POWER_BUTTON      (1<<4)	/* 04: Power button is handled as a generic feature */
 #define ACPI_FADT_SLEEP_BUTTON      (1<<5)	/* 05: Sleep button is handled as a generic feature, or  not present */
 #define ACPI_FADT_FIXED_RTC         (1<<6)	/* 06: RTC wakeup stat not in fixed register space */
-#define ACPI_FADT_S4_RTC_WAKE       (1<<7)	/* 07: RTC wakeup stat not possible from S4 */
+#define ACPI_FADT_S4_RTC_WAKE       (1<<7)	/* 07: RTC wakeup possible from S4 */
 #define ACPI_FADT_32BIT_TIMER       (1<<8)	/* 08: tmr_val is 32 bits 0=24-bits */
 #define ACPI_FADT_DOCKING_SUPPORTED (1<<9)	/* 09: Docking supported */
 #define ACPI_FADT_RESET_REGISTER    (1<<10)	/* 10: System reset via the FADT RESET_REG supported */
Signature · 1 line
1.5.6.6
author reviewer
#20 lore raw

PATCH 20/23 eeepc-laptop: enable Bluetooth ACPI details

In reply to Len Brown

From: Jonathan McDowell <[email protected]>

Although rfkill support for the EEE bluetooth device has been added to 2.6.28-rc the appropriate ACPI accessor definitions were not added, so the support was non functional. The patch below adds the get and set accessors and has been verified to work on an EEE 901.

---
 drivers/platform/x86/eeepc-laptop.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/platform/x86/eeepc-laptop.c +2 -2
index 02fe2b8..9d93cb9 100644
@@ -90,7 +90,7 @@ enum {
 };
 
 static const char *cm_getv[] = {
-	"WLDG", NULL, NULL, NULL,
+	"WLDG", "BTHG", NULL, NULL,
 	"CAMG", NULL, NULL, NULL,
 	NULL, "PBLG", NULL, NULL,
 	"CFVG", NULL, NULL, NULL,
@@ -99,7 +99,7 @@ static const char *cm_getv[] = {
 };
 
 static const char *cm_setv[] = {
-	"WLDS", NULL, NULL, NULL,
+	"WLDS", "BTHS", NULL, NULL,
 	"CAMS", NULL, NULL, NULL,
 	"SDSP", "PBLS", "HDPS", NULL,
 	"CFVS", NULL, NULL, NULL,
Signature · 1 line
1.5.6.6
author reviewer
#21 lore raw

PATCH 21/23 dell-laptop: move to drivers/platform/x86/ from drivers/misc/

In reply to Len Brown

From: Len Brown <[email protected]>

---
 drivers/misc/Makefile                        |    1 -
 drivers/platform/x86/Kconfig                 |   12 ++++++++++++
 drivers/platform/x86/Makefile                |    1 +
 drivers/{misc => platform/x86}/dell-laptop.c |    2 +-
 4 files changed, 14 insertions(+), 2 deletions(-)
 rename drivers/{misc => platform/x86}/dell-laptop.c (99%)
drivers/misc/Makefile +0 -1
index 9cf8ae6..d5749a7 100644
@@ -10,7 +10,6 @@ obj-$(CONFIG_ATMEL_TCLIB)	+= atmel_tclib.o
 obj-$(CONFIG_ICS932S401)	+= ics932s401.o
 obj-$(CONFIG_LKDTM)		+= lkdtm.o
 obj-$(CONFIG_TIFM_CORE)       	+= tifm_core.o
-obj-$(CONFIG_DELL_LAPTOP)	+= dell-laptop.o
 obj-$(CONFIG_TIFM_7XX1)       	+= tifm_7xx1.o
 obj-$(CONFIG_PHANTOM)		+= phantom.o
 obj-$(CONFIG_SGI_IOC4)		+= ioc4.o
drivers/platform/x86/Kconfig +12 -0
index e65448e..9e8f948 100644
@@ -54,6 +54,18 @@ config ASUS_LAPTOP
 
 	  If you have an ACPI-compatible ASUS laptop, say Y or M here.
 
+config DELL_LAPTOP
+	tristate "Dell Laptop Extras (EXPERIMENTAL)"
+	depends on X86
+	depends on DCDBAS
+	depends on EXPERIMENTAL
+	depends on BACKLIGHT_CLASS_DEVICE
+	depends on RFKILL
+	default n
+	---help---
+	This driver adds support for rfkill and backlight control to Dell
+	laptops.
+
 config FUJITSU_LAPTOP
 	tristate "Fujitsu Laptop Extras"
 	depends on ACPI
drivers/platform/x86/Makefile +1 -0
index 1e9de2a..e290651 100644
@@ -6,6 +6,7 @@ obj-$(CONFIG_ASUS_LAPTOP)	+= asus-laptop.o
 obj-$(CONFIG_EEEPC_LAPTOP)	+= eeepc-laptop.o
 obj-$(CONFIG_MSI_LAPTOP)	+= msi-laptop.o
 obj-$(CONFIG_COMPAL_LAPTOP)	+= compal-laptop.o
+obj-$(CONFIG_DELL_LAPTOP)	+= dell-laptop.o
 obj-$(CONFIG_ACER_WMI)		+= acer-wmi.o
 obj-$(CONFIG_HP_WMI)		+= hp-wmi.o
 obj-$(CONFIG_TC1100_WMI)	+= tc1100-wmi.o
drivers/platform/x86/dell-laptop.c renamed from drivers/misc/dell-laptop.c +1 -1
similarity index 99%
rename from drivers/misc/dell-laptop.c
rename to drivers/platform/x86/dell-laptop.c
index 4d33a20..16e11c2 100644
@@ -22,7 +22,7 @@
 #include <linux/rfkill.h>
 #include <linux/power_supply.h>
 #include <linux/acpi.h>
-#include "../firmware/dcdbas.h"
+#include "../../firmware/dcdbas.h"
 
 #define BRIGHTNESS_TOKEN 0x7d
 
Signature · 1 line
1.5.6.6
author reviewer
#22 lore raw

PATCH 22/23 ACPI: rename main.c to sleep.c

In reply to Len Brown

From: Len Brown <[email protected]>

---
 drivers/acpi/Makefile            |    2 +-
 drivers/acpi/{main.c => sleep.c} |    0 
 2 files changed, 1 insertions(+), 1 deletions(-)
 rename drivers/acpi/{main.c => sleep.c} (100%)
drivers/acpi/Makefile +1 -1
index d80f4cc..65d90c7 100644
@@ -19,7 +19,7 @@ obj-y				+= osl.o utils.o reboot.o\
 
 # sleep related files
 obj-y				+= wakeup.o
-obj-y				+= main.o
+obj-y				+= sleep.o
 obj-$(CONFIG_ACPI_SLEEP)	+= proc.o
 
 
drivers/acpi/sleep.c renamed from drivers/acpi/main.c +0 -0
similarity index 100%
rename from drivers/acpi/main.c
rename to drivers/acpi/sleep.c
Signature · 1 line
1.5.6.6
author reviewer
#23 lore raw

PATCH 23/23 ACPI PCI hotplug: harden against panic regression

In reply to Len Brown

From: James Bottomley <[email protected]>

ACPI hotplug panic with current git head
http://lkml.org/lkml/2009/1/10/136

Rather than reverting the entire commit that causes the crash:
e8c331e963c58b83db24b7d0e39e8c07f687dbc6
"PCI hotplug: introduce functions for ACPI slot detection"

simply harden against it while the changes to
the hotplug code on this particularl machine are understood.

---
 drivers/pci/hotplug/acpiphp_glue.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/pci/hotplug/acpiphp_glue.c +2 -0
index f09b101..803d9dd 100644
@@ -266,6 +266,8 @@ static int detect_ejectable_slots(struct pci_bus *pbus)
 	int found = acpi_pci_detect_ejectable(pbus);
 	if (!found) {
 		acpi_handle bridge_handle = acpi_pci_get_bridge_handle(pbus);
+		if (!bridge_handle)
+			return 0;
 		acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1,
 				    is_pci_dock_device, (void *)&found, NULL);
 	}
Signature · 1 line
1.5.6.6