From 316621da231097600de11257865580c5a6573387 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sun, 7 Feb 2010 21:56:49 -0200 Subject: [PATCH] thinkpad-acpi: fix bluetooth/wwan resume Studying the DSDTs of various thinkpads, it looks like bit 3 of the argument to SBDC and SWAN is not "set radio to last state on resume". Rather, it seems to be "if this bit is set, enable radio on resume, otherwise disable it on resume". So, the proper way to prepare the radios for S3 suspend is: disable radio and clear bit 3 on the SBDC/SWAN call to to resume with radio disabled, and enable radio and set bit 3 on the SBDC/SWAN call to resume with the radio enabled. Also, for persistent devices, the rfkill core does not restore state, so we really need to get the firmware to do the right thing. We don't sync the radio state on suspend, instead we trust the BIOS to not do anything weird if we never touched the radio state since boot. Time will tell if that's a wise way of doing things... This might even fix: http://bugzilla.kernel.org/show_bug.cgi?id=14545 But I am not holding my breath, as the current code really should not resume with bluetooth enabled... and that's exactly what the report #14545 claims to happen. Signed-off-by: Henrique de Moraes Holschuh --- drivers/platform/x86/thinkpad_acpi.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 4fbfdcf34e0..c20ede2893c 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3579,7 +3579,7 @@ enum { TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */ TP_ACPI_BLUETOOTH_RADIOSSW = 0x02, /* Bluetooth radio enabled */ TP_ACPI_BLUETOOTH_RESUMECTRL = 0x04, /* Bluetooth state at resume: - off / last state */ + 0 = disable, 1 = enable */ }; enum { @@ -3670,11 +3670,12 @@ static int bluetooth_set_radiosw(int radio_on, int update_rfk) } #endif - /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */ if (radio_on) - status = TP_ACPI_BLUETOOTH_RADIOSSW; + status = TP_ACPI_BLUETOOTH_RADIOSSW + | TP_ACPI_BLUETOOTH_RESUMECTRL; else status = 0; + if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status)) return -EIO; @@ -3896,7 +3897,7 @@ enum { TP_ACPI_WANCARD_HWPRESENT = 0x01, /* Wan hw available */ TP_ACPI_WANCARD_RADIOSSW = 0x02, /* Wan radio enabled */ TP_ACPI_WANCARD_RESUMECTRL = 0x04, /* Wan state at resume: - off / last state */ + 0 = disable, 1 = enable */ }; #define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw" @@ -3978,11 +3979,12 @@ static int wan_set_radiosw(int radio_on, int update_rfk) } #endif - /* We make sure to keep TP_ACPI_WANCARD_RESUMECTRL off */ if (radio_on) - status = TP_ACPI_WANCARD_RADIOSSW; + status = TP_ACPI_WANCARD_RADIOSSW + | TP_ACPI_WANCARD_RESUMECTRL; else status = 0; + if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) return -EIO; -- 2.11.4.GIT