From b253c9d1d858a3f115f791ee4fe2b9399ae7dbbd Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Mon, 8 Jul 2013 11:44:40 -0400 Subject: hp-wmi: Enable hotkeys on some systems Kyle Evans discovered that he needed to set some bits in an EC register in order to receive hotkey events. Doing so blindly broke some otherwise working HP laptops. It turns out that there's a WMI call that accesses the same register, so let's try calling that instead. Signed-off-by: Matthew Garrett Cc: Kyle Evans --- drivers/platform/x86/hp-wmi.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index d111c8687f9b..6e142c3b5e97 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -53,6 +53,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); #define HPWMI_ALS_QUERY 0x3 #define HPWMI_HARDWARE_QUERY 0x4 #define HPWMI_WIRELESS_QUERY 0x5 +#define HPWMI_BIOS_QUERY 0x9 #define HPWMI_HOTKEY_QUERY 0xc #define HPWMI_WIRELESS2_QUERY 0x1b @@ -291,6 +292,19 @@ static int hp_wmi_tablet_state(void) return (state & 0x4) ? 1 : 0; } +static int hp_wmi_enable_hotkeys(void) +{ + int ret; + int query = 0x6e; + + ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, 1, &query, sizeof(query), + 0); + + if (ret) + return -EINVAL; + return 0; +} + static int hp_wmi_set_block(void *data, bool blocked) { enum hp_wmi_radio r = (enum hp_wmi_radio) data; @@ -948,6 +962,8 @@ static int __init hp_wmi_init(void) err = hp_wmi_input_setup(); if (err) return err; + + hp_wmi_enable_hotkeys(); } if (bios_capable) { -- cgit v1.2.3-59-g8ed1b From 9f2082025902b59193dbdcd63550c1e8bc58e706 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 9 May 2013 10:03:02 +0800 Subject: dell-laptop: fix error return code in dell_init() Fix to return -ENOMEM in the alloc_page() error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Signed-off-by: Matthew Garrett --- drivers/platform/x86/dell-laptop.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 1134119521ac..bb77e18b3dd4 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -551,9 +551,10 @@ static int __init dell_init(void) * is passed to SMI handler. */ bufferpage = alloc_page(GFP_KERNEL | GFP_DMA32); - - if (!bufferpage) + if (!bufferpage) { + ret = -ENOMEM; goto fail_buffer; + } buffer = page_address(bufferpage); if (quirks && quirks->touchpad_led) -- cgit v1.2.3-59-g8ed1b From e1a98e61c21694c9c690c7f253010cd44e89e7fd Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 14 May 2013 02:44:26 +0100 Subject: amilo-rfkill: Add dependency on SERIO_I8042 I forgot to add this when changing the driver to use the proper i8042 functions. Reported-by: kbuild test robot Signed-off-by: Ben Hutchings Signed-off-by: Matthew Garrett --- drivers/platform/x86/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 85772616efbf..37645b923c52 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -176,6 +176,7 @@ config FUJITSU_TABLET config AMILO_RFKILL tristate "Fujitsu-Siemens Amilo rfkill support" depends on RFKILL + depends on SERIO_I8042 ---help--- This is a driver for enabling wifi on some Fujitsu-Siemens Amilo laptops. -- cgit v1.2.3-59-g8ed1b From 4c241b364b5899e46924bfd4f9599c45f8e4a146 Mon Sep 17 00:00:00 2001 From: Libo Chen Date: Mon, 20 May 2013 10:30:07 +0800 Subject: x86: msi-laptop: fix memleak 1. fix two visible mistakes: * when load_scm_model_init faild, we should call platform_device_del(msipf_device) * msipf_attribute_group should be remove in err case 2. change some tags, give them real meaning. Signed-off-by: Libo Chen Signed-off-by: Matthew Garrett --- drivers/platform/x86/msi-laptop.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 6b2293875672..62f8030b9e77 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -1098,29 +1098,29 @@ static int __init msi_init(void) ret = platform_device_add(msipf_device); if (ret) - goto fail_platform_device1; + goto fail_device_add; if (quirks->load_scm_model && (load_scm_model_init(msipf_device) < 0)) { ret = -EINVAL; - goto fail_platform_device1; + goto fail_scm_model_init; } ret = sysfs_create_group(&msipf_device->dev.kobj, &msipf_attribute_group); if (ret) - goto fail_platform_device2; + goto fail_create_group; if (!quirks->old_ec_model) { if (threeg_exists) ret = device_create_file(&msipf_device->dev, &dev_attr_threeg); if (ret) - goto fail_platform_device2; + goto fail_create_attr; } else { ret = sysfs_create_group(&msipf_device->dev.kobj, &msipf_old_attribute_group); if (ret) - goto fail_platform_device2; + goto fail_create_attr; /* Disable automatic brightness control by default because * this module was probably loaded to do brightness control in @@ -1134,26 +1134,22 @@ static int __init msi_init(void) return 0; -fail_platform_device2: - +fail_create_attr: + sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group); +fail_create_group: if (quirks->load_scm_model) { i8042_remove_filter(msi_laptop_i8042_filter); cancel_delayed_work_sync(&msi_rfkill_dwork); cancel_work_sync(&msi_rfkill_work); rfkill_cleanup(); } +fail_scm_model_init: platform_device_del(msipf_device); - -fail_platform_device1: - +fail_device_add: platform_device_put(msipf_device); - fail_platform_driver: - platform_driver_unregister(&msipf_driver); - fail_backlight: - backlight_device_unregister(msibl_device); return ret; -- cgit v1.2.3-59-g8ed1b From 38bdd729ca39e1924a31970e41b13b6ce6ec1755 Mon Sep 17 00:00:00 2001 From: Libo Chen Date: Mon, 20 May 2013 10:30:24 +0800 Subject: x86: asus-laptop: fix invalid point access asus->name is null or point to const string,so it is not suitable to kfree it. Signed-off-by: Libo Chen Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-laptop.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 0eea09c1c134..8e268da6fdbd 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -1935,7 +1935,6 @@ fail_input: fail_backlight: asus_platform_exit(asus); fail_platform: - kfree(asus->name); kfree(asus); return result; -- cgit v1.2.3-59-g8ed1b From 0ed60654a24c730dcb555da8439e5639253b6eca Mon Sep 17 00:00:00 2001 From: vic Date: Wed, 22 May 2013 21:32:10 +0300 Subject: asus-wmi: append newline to messages Append newline to messages. Signed-off-by: Viktar Vauchkevich Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-wmi.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index c11b2426dac1..0e58d748d7f6 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -1045,7 +1045,7 @@ static ssize_t asus_hwmon_pwm1(struct device *dev, else if (value == 3) value = 255; else if (value != 0) { - pr_err("Unknown fan speed %#x", value); + pr_err("Unknown fan speed %#x\n", value); value = -1; } @@ -1557,11 +1557,11 @@ static int asus_wmi_platform_init(struct asus_wmi *asus) /* INIT enable hotkeys on some models */ if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_INIT, 0, 0, &rv)) - pr_info("Initialization: %#x", rv); + pr_info("Initialization: %#x\n", rv); /* We don't know yet what to do with this version... */ if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SPEC, 0, 0x9, &rv)) { - pr_info("BIOS WMI version: %d.%d", rv >> 16, rv & 0xFF); + pr_info("BIOS WMI version: %d.%d\n", rv >> 16, rv & 0xFF); asus->spec = rv; } @@ -1572,7 +1572,7 @@ static int asus_wmi_platform_init(struct asus_wmi *asus) * The significance of others is yet to be found. */ if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SFUN, 0, 0, &rv)) { - pr_info("SFUN value: %#x", rv); + pr_info("SFUN value: %#x\n", rv); asus->sfun = rv; } @@ -1712,7 +1712,7 @@ static int asus_wmi_debugfs_init(struct asus_wmi *asus) asus->debug.root = debugfs_create_dir(asus->driver->name, NULL); if (!asus->debug.root) { - pr_err("failed to create debugfs directory"); + pr_err("failed to create debugfs directory\n"); goto error_debugfs; } @@ -1985,17 +1985,17 @@ EXPORT_SYMBOL_GPL(asus_wmi_unregister_driver); static int __init asus_wmi_init(void) { if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) { - pr_info("Asus Management GUID not found"); + pr_info("Asus Management GUID not found\n"); return -ENODEV; } - pr_info("ASUS WMI generic driver loaded"); + pr_info("ASUS WMI generic driver loaded\n"); return 0; } static void __exit asus_wmi_exit(void) { - pr_info("ASUS WMI generic driver unloaded"); + pr_info("ASUS WMI generic driver unloaded\n"); } module_init(asus_wmi_init); -- cgit v1.2.3-59-g8ed1b From 3aabf444f70f5855d8a0a06285fdd55e76a740d5 Mon Sep 17 00:00:00 2001 From: Viktar Vauchkevich Date: Thu, 23 May 2013 07:17:11 +0300 Subject: asus-nb-wmi: ignore ALS notification key code Ignore Ambient Light Sensor notification key code 0xC6 found in ASUS UX31a. When the illuminance changes dmesg shows: [10814.939979] asus_wmi: Unknown key c6 pressed Signed-off-by: Viktar Vauchkevich Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-nb-wmi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 8fcb41e18b9c..7340566c5865 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -256,6 +256,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, 0xB5, { KEY_CALC } }, { KE_KEY, 0xC4, { KEY_KBDILLUMUP } }, { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } }, + { KE_IGNORE, 0xC6, }, /* Ambient Light Sensor notification */ { KE_END, 0}, }; -- cgit v1.2.3-59-g8ed1b From b5f4f9ef0125845cd03dc9de5dbe1344e60474d0 Mon Sep 17 00:00:00 2001 From: Libo Chen Date: Mon, 27 May 2013 10:31:33 +0800 Subject: drivers/platform/x86/intel_ips: Convert to module_pci_driver use module_pci_driver instead of init/exit, make code clean. Signed-off-by: Libo Chen Signed-off-by: Matthew Garrett --- drivers/platform/x86/intel_ips.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 5051aa970e0a..18dcb58ba965 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -1731,18 +1731,7 @@ static struct pci_driver ips_pci_driver = { .shutdown = ips_shutdown, }; -static int __init ips_init(void) -{ - return pci_register_driver(&ips_pci_driver); -} -module_init(ips_init); - -static void ips_exit(void) -{ - pci_unregister_driver(&ips_pci_driver); - return; -} -module_exit(ips_exit); +module_pci_driver(ips_pci_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jesse Barnes "); -- cgit v1.2.3-59-g8ed1b From e8f56c80aedacfb1552509c0e4ed265266328bc4 Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Thu, 30 May 2013 10:31:50 +0800 Subject: asus-wmi: control wlan-led only if wapf == 4 Controlling the wlan led seems to have some side effects to the machines with wapf value is not equal to 4. It will make the keyboard backlight out of order. So, the patch will enable the wlan led function only if the wapf == 4. Bug: https://bugzilla.kernel.org/show_bug.cgi?id=46791 Reported-by: Mirto Silvio Busico Tested-by: Karol Herbst Tested-by: drunkenbatman Signed-off-by: AceLan Kao Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-wmi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 0e58d748d7f6..19c313b056c3 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -558,7 +558,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus) goto error; } - if (wlan_led_presence(asus)) { + if (wlan_led_presence(asus) && (asus->driver->quirks->wapf == 4)) { INIT_WORK(&asus->wlan_led_work, wlan_led_update); asus->wlan_led.name = "asus::wlan"; @@ -886,7 +886,8 @@ static int asus_new_rfkill(struct asus_wmi *asus, if (!*rfkill) return -EINVAL; - if (dev_id == ASUS_WMI_DEVID_WLAN) + if ((dev_id == ASUS_WMI_DEVID_WLAN) && + (asus->driver->quirks->wapf == 4)) rfkill_set_led_trigger_name(*rfkill, "asus-wlan"); rfkill_init_sw_state(*rfkill, !result); -- cgit v1.2.3-59-g8ed1b From 8667ca9518bbe0eff2222e69d611f4c8549fcbde Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Thu, 13 Jun 2013 16:46:25 +0800 Subject: hp-wmi: add supports for POST code error HP laptops include a POST code error query 0x2A that reports which point BIOS fails to boot at. The error code is kept in CMOS until it is cleared. Signed-off-by: Alex Hung Signed-off-by: Matthew Garrett --- drivers/platform/x86/hp-wmi.c | 47 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 6e142c3b5e97..97bb05edcb5a 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -56,6 +56,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); #define HPWMI_BIOS_QUERY 0x9 #define HPWMI_HOTKEY_QUERY 0xc #define HPWMI_WIRELESS2_QUERY 0x1b +#define HPWMI_POSTCODEERROR_QUERY 0x2a enum hp_wmi_radio { HPWMI_WIFI = 0, @@ -400,6 +401,16 @@ static int hp_wmi_rfkill2_refresh(void) return 0; } +static int hp_wmi_post_code_state(void) +{ + int state = 0; + int ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, 0, &state, + sizeof(state), sizeof(state)); + if (ret) + return -EINVAL; + return state; +} + static ssize_t show_display(struct device *dev, struct device_attribute *attr, char *buf) { @@ -445,6 +456,16 @@ static ssize_t show_tablet(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", value); } +static ssize_t show_postcode(struct device *dev, struct device_attribute *attr, + char *buf) +{ + /* Get the POST error code of previous boot failure. */ + int value = hp_wmi_post_code_state(); + if (value < 0) + return -EINVAL; + return sprintf(buf, "0x%x\n", value); +} + static ssize_t set_als(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -457,11 +478,33 @@ static ssize_t set_als(struct device *dev, struct device_attribute *attr, return count; } +static ssize_t set_postcode(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret; + u32 tmp; + long unsigned int tmp2; + + ret = kstrtoul(buf, 10, &tmp2); + if (ret || tmp2 != 1) + return -EINVAL; + + /* Clear the POST error code. It is kept until until cleared. */ + tmp = (u32) tmp2; + ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, 1, &tmp, + sizeof(tmp), sizeof(tmp)); + if (ret) + return -EINVAL; + + return count; +} + static DEVICE_ATTR(display, S_IRUGO, show_display, NULL); static DEVICE_ATTR(hddtemp, S_IRUGO, show_hddtemp, NULL); static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als); static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL); +static DEVICE_ATTR(postcode, S_IRUGO | S_IWUSR, show_postcode, set_postcode); static void hp_wmi_notify(u32 value, void *context) { @@ -642,6 +685,7 @@ static void cleanup_sysfs(struct platform_device *device) device_remove_file(&device->dev, &dev_attr_als); device_remove_file(&device->dev, &dev_attr_dock); device_remove_file(&device->dev, &dev_attr_tablet); + device_remove_file(&device->dev, &dev_attr_postcode); } static int hp_wmi_rfkill_setup(struct platform_device *device) @@ -857,6 +901,9 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) if (err) goto add_sysfs_error; err = device_create_file(&device->dev, &dev_attr_tablet); + if (err) + goto add_sysfs_error; + err = device_create_file(&device->dev, &dev_attr_postcode); if (err) goto add_sysfs_error; return 0; -- cgit v1.2.3-59-g8ed1b From 34a956db3774e8cba3f6b52aa9c1d67cf9a496fe Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 2 Jul 2013 18:41:03 -0400 Subject: Add support driver for Intel Rapid Start Technology Intel Rapid Start Technology is a firmware-based suspend-to-disk implementation. Once placed in S3, the device will wake once either a timeout elapses or the battery reaches a critical level. It will then resume to the firmware and copy the contents of RAM to a specialised partition, and then power off the machine. If the user turns the machine back on the firmware will copy the contents of the partition back to RAM and then resume from S3 as normal. This driver provides an interface for configuring the wakeup events and timeout. It still requires firmware support and an appropriate suspend partition. Signed-off-by: Matthew Garrett Signed-off-by: Matthew Garrett --- .../ABI/testing/sysfs-driver-intel-rapid-start | 21 +++ drivers/platform/x86/Kconfig | 12 ++ drivers/platform/x86/Makefile | 1 + drivers/platform/x86/intel-rst.c | 209 +++++++++++++++++++++ 4 files changed, 243 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-driver-intel-rapid-start create mode 100644 drivers/platform/x86/intel-rst.c (limited to 'drivers') diff --git a/Documentation/ABI/testing/sysfs-driver-intel-rapid-start b/Documentation/ABI/testing/sysfs-driver-intel-rapid-start new file mode 100644 index 000000000000..5a7d2e217d40 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-intel-rapid-start @@ -0,0 +1,21 @@ +What: /sys/bus/acpi/intel-rapid-start/wakeup_events +Date: July 2, 2013 +KernelVersion: 3.11 +Contact: Matthew Garrett +Description: An integer representing a set of wakeup events as follows: + 1: Wake to enter hibernation when the wakeup timer expires + 2: Wake to enter hibernation when the battery reaches a + critical level + + These values are ORed together. For example, a value of 3 + indicates that the system will wake to enter hibernation when + either the wakeup timer expires or the battery reaches a + critical level. + +What: /sys/bus/acpi/intel-rapid-start/wakeup_time +Date: July 2, 2013 +KernelVersion: 3.11 +Contact: Matthew Garrett +Description: An integer representing the length of time the system will + remain asleep before waking up to enter hibernation. + This value is in minutes. diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 37645b923c52..36057f481162 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -782,6 +782,18 @@ config APPLE_GMUX graphics as well as the backlight. Currently only backlight control is supported by the driver. +config INTEL_RST + tristate "Intel Rapid Start Technology Driver" + depends on ACPI + ---help--- + This driver provides support for modifying paramaters on systems + equipped with Intel's Rapid Start Technology. When put in an ACPI + sleep state, these devices will wake after either a configured + timeout or when the system battery reaches a critical state, + automatically copying memory contents to disk. On resume, the + firmware will copy the memory contents back to RAM and resume the OS + as usual. + config PVPANIC tristate "pvpanic device support" depends on ACPI diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index ef0ec746f78c..5c669ce8d243 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -51,5 +51,6 @@ obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o +obj-$(CONFIG_INTEL_RST) += intel-rst.o obj-$(CONFIG_PVPANIC) += pvpanic.o diff --git a/drivers/platform/x86/intel-rst.c b/drivers/platform/x86/intel-rst.c new file mode 100644 index 000000000000..9385afd9b558 --- /dev/null +++ b/drivers/platform/x86/intel-rst.c @@ -0,0 +1,209 @@ +/* + * Copyright 2013 Matthew Garrett + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); + +static ssize_t irst_show_wakeup_events(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi; + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *result; + acpi_status status; + + acpi = to_acpi_device(dev); + + status = acpi_evaluate_object(acpi->handle, "GFFS", NULL, &output); + if (!ACPI_SUCCESS(status)) + return -EINVAL; + + result = output.pointer; + + if (result->type != ACPI_TYPE_INTEGER) { + kfree(result); + return -EINVAL; + } + + return sprintf(buf, "%lld\n", result->integer.value); +} + +static ssize_t irst_store_wakeup_events(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi; + struct acpi_object_list input; + union acpi_object param; + acpi_status status; + unsigned long value; + int error; + + acpi = to_acpi_device(dev); + + error = kstrtoul(buf, 0, &value); + + if (error) + return error; + + param.type = ACPI_TYPE_INTEGER; + param.integer.value = value; + + input.count = 1; + input.pointer = ¶m; + + status = acpi_evaluate_object(acpi->handle, "SFFS", &input, NULL); + + if (!ACPI_SUCCESS(status)) + return -EINVAL; + + return count; +} + +static struct device_attribute irst_wakeup_attr = { + .attr = { .name = "wakeup_events", .mode = 0600 }, + .show = irst_show_wakeup_events, + .store = irst_store_wakeup_events +}; + +static ssize_t irst_show_wakeup_time(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct acpi_device *acpi; + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *result; + acpi_status status; + + acpi = to_acpi_device(dev); + + status = acpi_evaluate_object(acpi->handle, "GFTV", NULL, &output); + if (!ACPI_SUCCESS(status)) + return -EINVAL; + + result = output.pointer; + + if (result->type != ACPI_TYPE_INTEGER) { + kfree(result); + return -EINVAL; + } + + return sprintf(buf, "%lld\n", result->integer.value); +} + +static ssize_t irst_store_wakeup_time(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi; + struct acpi_object_list input; + union acpi_object param; + acpi_status status; + unsigned long value; + int error; + + acpi = to_acpi_device(dev); + + error = kstrtoul(buf, 0, &value); + + if (error) + return error; + + param.type = ACPI_TYPE_INTEGER; + param.integer.value = value; + + input.count = 1; + input.pointer = ¶m; + + status = acpi_evaluate_object(acpi->handle, "SFTV", &input, NULL); + + if (!ACPI_SUCCESS(status)) + return -EINVAL; + + return count; +} + +static struct device_attribute irst_timeout_attr = { + .attr = { .name = "wakeup_time", .mode = 0600 }, + .show = irst_show_wakeup_time, + .store = irst_store_wakeup_time +}; + +static int irst_add(struct acpi_device *acpi) +{ + int error = 0; + + error = device_create_file(&acpi->dev, &irst_timeout_attr); + if (error) + goto out; + + error = device_create_file(&acpi->dev, &irst_wakeup_attr); + if (error) + goto out_timeout; + + return 0; + +out_timeout: + device_remove_file(&acpi->dev, &irst_timeout_attr); +out: + return error; +} + +static int irst_remove(struct acpi_device *acpi) +{ + device_remove_file(&acpi->dev, &irst_wakeup_attr); + device_remove_file(&acpi->dev, &irst_timeout_attr); + + return 0; +} + +static const struct acpi_device_id irst_ids[] = { + {"INT3392", 0}, + {"", 0} +}; + +static struct acpi_driver irst_driver = { + .owner = THIS_MODULE, + .name = "intel_rapid_start", + .class = "intel_rapid_start", + .ids = irst_ids, + .ops = { + .add = irst_add, + .remove = irst_remove, + }, +}; + +static int irst_init(void) +{ + return acpi_bus_register_driver(&irst_driver); +} + +static void irst_exit(void) +{ + acpi_bus_unregister_driver(&irst_driver); +} + +module_init(irst_init); +module_exit(irst_exit); + +MODULE_DEVICE_TABLE(acpi, irst_ids); -- cgit v1.2.3-59-g8ed1b From 5c7f80f75512557dd0728ada77e8e8a8c7c8458b Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 3 Jul 2013 00:50:13 -0400 Subject: Add trivial driver to disable Intel Smart Connect Intel Smart Connect is an Intel-specific ACPI interface for configuring devices to wake up at regular intervals so they can pull down mail or other internet updates, and then go to sleep again. If a user enables this in Windows and then reboots into Linux, the device may wake up if it's put to sleep. Since there's no Linux userland support for any of this, the machine will then remain awake until something else puts it back to sleep. I haven't figured out all that much about how this works (there's a bunch of different ACPI calls available on the device), but this seems to be enough to turn it off. We can add more features to this driver if anyone ever cares about figuring out what the rest of the calls do or writing some Linux userspace to implement the rest of it. Signed-off-by: Matthew Garrett Signed-off-by: Matthew Garrett --- drivers/platform/x86/Kconfig | 14 +++++ drivers/platform/x86/Makefile | 1 + drivers/platform/x86/intel-smartconnect.c | 90 +++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 drivers/platform/x86/intel-smartconnect.c (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 36057f481162..a3d76c59a394 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -794,6 +794,20 @@ config INTEL_RST firmware will copy the memory contents back to RAM and resume the OS as usual. +config INTEL_SMARTCONNECT + tristate "Intel Smart Connect disabling driver" + depends on ACPI + ---help--- + Intel Smart Connect is a technology intended to permit devices to + update state by resuming for a short period of time at regular + intervals. If a user enables this functionality under Windows and + then reboots into Linux, the system may remain configured to resume + on suspend. In the absence of any userspace to support it, the system + will then remain awake until something triggers another suspend. + + This driver checks to determine whether the device has Intel Smart + Connect enabled, and if so disables it. + config PVPANIC tristate "pvpanic device support" depends on ACPI diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 5c669ce8d243..5dbe19324351 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -52,5 +52,6 @@ obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o obj-$(CONFIG_INTEL_RST) += intel-rst.o +obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o obj-$(CONFIG_PVPANIC) += pvpanic.o diff --git a/drivers/platform/x86/intel-smartconnect.c b/drivers/platform/x86/intel-smartconnect.c new file mode 100644 index 000000000000..f74e93d096bc --- /dev/null +++ b/drivers/platform/x86/intel-smartconnect.c @@ -0,0 +1,90 @@ +/* + * Copyright 2013 Matthew Garrett + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + +#include +#include +#include + +MODULE_LICENSE("GPL"); + +static int smartconnect_acpi_init(struct acpi_device *acpi) +{ + struct acpi_object_list input; + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *result; + union acpi_object param; + acpi_status status; + + status = acpi_evaluate_object(acpi->handle, "GAOS", NULL, &output); + if (!ACPI_SUCCESS(status)) + return -EINVAL; + + result = output.pointer; + + if (result->type != ACPI_TYPE_INTEGER) { + kfree(result); + return -EINVAL; + } + + if (result->integer.value & 0x1) { + param.type = ACPI_TYPE_INTEGER; + param.integer.value = 0; + + input.count = 1; + input.pointer = ¶m; + + dev_info(&acpi->dev, "Disabling Intel Smart Connect\n"); + status = acpi_evaluate_object(acpi->handle, "SAOS", &input, + NULL); + } + + kfree(result); + + return 0; +} + +static const struct acpi_device_id smartconnect_ids[] = { + {"INT33A0", 0}, + {"", 0} +}; + +static struct acpi_driver smartconnect_driver = { + .owner = THIS_MODULE, + .name = "intel_smart_connect", + .class = "intel_smart_connect", + .ids = smartconnect_ids, + .ops = { + .add = smartconnect_acpi_init, + }, +}; + +static int smartconnect_init(void) +{ + return acpi_bus_register_driver(&smartconnect_driver); +} + +static void smartconnect_exit(void) +{ + acpi_bus_unregister_driver(&smartconnect_driver); +} + +module_init(smartconnect_init); +module_exit(smartconnect_exit); + +MODULE_DEVICE_TABLE(acpi, smartconnect_ids); -- cgit v1.2.3-59-g8ed1b From 144a19ac94526c4609fa8b8264e6f9c3d48f7a55 Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Wed, 3 Jul 2013 14:35:15 +0800 Subject: asus-nb-wmi: set wapf=4 for ASUSTeK COMPUTER INC. 1015E/U Need to set wapf to 4 for ASUSTeK COMPUTER INC. 1015E/U, so that user can toggle wifi function through function key correctly. Signed-off-by: AceLan Kao Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-nb-wmi.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 7340566c5865..563f59efa669 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -180,6 +180,24 @@ static struct dmi_system_id asus_quirks[] = { }, .driver_data = &quirk_asus_x401u, }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. 1015E", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "1015E"), + }, + .driver_data = &quirk_asus_x401u, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. 1015U", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "1015U"), + }, + .driver_data = &quirk_asus_x401u, + }, {}, }; -- cgit v1.2.3-59-g8ed1b From 283672e425b24fe4046535973460e8732f4bd485 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Wed, 3 Jul 2013 08:14:16 -0500 Subject: toshiba_acpi: Add dependency on SERIO_I8042 Configuring this option as a module with ACPI_TOSHIBA built-in results in the following errors: drivers/built-in.o: In function `toshiba_acpi_remove': >> toshiba_acpi.c:(.text+0x314bb0): undefined reference to `i8042_remove_filter' drivers/built-in.o: In function `toshiba_acpi_add': >> toshiba_acpi.c:(.devinit.text+0xb822): undefined reference to `i8042_install_filter' >> toshiba_acpi.c:(.devinit.text+0xb98b): undefined reference to `i8042_remove_filter' Add a dependency to prevent ACPI_TOSHIBA from being built-in when SERIO_I8042=m. Reported-by: kbuild test robot Cc: Azael Avalos Signed-off-by: Seth Forshee Signed-off-by: Matthew Garrett --- drivers/platform/x86/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index a3d76c59a394..36a9e6023395 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -592,6 +592,7 @@ config ACPI_TOSHIBA depends on BACKLIGHT_CLASS_DEVICE depends on INPUT depends on RFKILL || RFKILL = n + depends on SERIO_I8042 || SERIO_I8042 = n select INPUT_POLLDEV select INPUT_SPARSEKMAP ---help--- -- cgit v1.2.3-59-g8ed1b From fef8ce166b2d5cdba8bbf85fa48c4cb8d75ffec4 Mon Sep 17 00:00:00 2001 From: Libo Chen Date: Tue, 9 Jul 2013 20:34:28 +0800 Subject: x86 platform drivers: fix gpio leak when request_irq fails, we should release gpiochip v2: fix warning: ignoring return value of 'gpiochip_remove Signed-off-by: Libo Chen Signed-off-by: Matthew Garrett --- drivers/platform/x86/intel_pmic_gpio.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/intel_pmic_gpio.c b/drivers/platform/x86/intel_pmic_gpio.c index 6f4b7289a059..2805988485f6 100644 --- a/drivers/platform/x86/intel_pmic_gpio.c +++ b/drivers/platform/x86/intel_pmic_gpio.c @@ -288,7 +288,7 @@ static int platform_pmic_gpio_probe(struct platform_device *pdev) retval = request_irq(pg->irq, pmic_irq_handler, 0, "pmic", pg); if (retval) { pr_warn("Interrupt request failed\n"); - goto err; + goto fail_request_irq; } for (i = 0; i < 8; i++) { @@ -299,6 +299,10 @@ static int platform_pmic_gpio_probe(struct platform_device *pdev) irq_set_chip_data(i + pg->irq_base, pg); } return 0; + +fail_request_irq: + if (gpiochip_remove(&pg->chip)) + pr_err("gpiochip_remove failed\n"); err: iounmap(pg->gpiointr); err2: -- cgit v1.2.3-59-g8ed1b