summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-13 18:08:23 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-13 18:08:23 -0700
commit63345b4794aef4ebe16502cfe35b02bc9822d763 (patch)
tree758a127bad6b1035d4878c9a7a1cc7fac167b3b3
parent18fb38e2f58ff7a66e30cbb71af81425edf1c9a1 (diff)
parentfef8ce166b2d5cdba8bbf85fa48c4cb8d75ffec4 (diff)
Merge branch 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86
Pull x86 platform driver updates from Matthew Garrett: "Nothing overly exciting here - a couple of new drivers that don't do a great deal, along with some miscellaneous fixes and a couple of small feature enablement patches" * 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86: x86 platform drivers: fix gpio leak toshiba_acpi: Add dependency on SERIO_I8042 asus-nb-wmi: set wapf=4 for ASUSTeK COMPUTER INC. 1015E/U Add trivial driver to disable Intel Smart Connect Add support driver for Intel Rapid Start Technology hp-wmi: add supports for POST code error asus-wmi: control wlan-led only if wapf == 4 drivers/platform/x86/intel_ips: Convert to module_pci_driver asus-nb-wmi: ignore ALS notification key code asus-wmi: append newline to messages x86: asus-laptop: fix invalid point access x86: msi-laptop: fix memleak amilo-rfkill: Add dependency on SERIO_I8042 dell-laptop: fix error return code in dell_init() hp-wmi: Enable hotkeys on some systems
-rw-r--r--Documentation/ABI/testing/sysfs-driver-intel-rapid-start21
-rw-r--r--drivers/platform/x86/Kconfig28
-rw-r--r--drivers/platform/x86/Makefile2
-rw-r--r--drivers/platform/x86/asus-laptop.c1
-rw-r--r--drivers/platform/x86/asus-nb-wmi.c19
-rw-r--r--drivers/platform/x86/asus-wmi.c21
-rw-r--r--drivers/platform/x86/dell-laptop.c5
-rw-r--r--drivers/platform/x86/hp-wmi.c63
-rw-r--r--drivers/platform/x86/intel-rst.c209
-rw-r--r--drivers/platform/x86/intel-smartconnect.c90
-rw-r--r--drivers/platform/x86/intel_ips.c13
-rw-r--r--drivers/platform/x86/intel_pmic_gpio.c6
-rw-r--r--drivers/platform/x86/msi-laptop.c24
13 files changed, 462 insertions, 40 deletions
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 <mjg59@srcf.ucam.org>
+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 <mjg59@srcf.ucam.org>
+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 85772616efbf..36a9e6023395 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.
@@ -591,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---
@@ -781,6 +783,32 @@ 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 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 ef0ec746f78c..5dbe19324351 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -51,5 +51,7 @@ 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_INTEL_SMARTCONNECT) += intel-smartconnect.o
obj-$(CONFIG_PVPANIC) += pvpanic.o
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;
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
index 8fcb41e18b9c..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,
+ },
{},
};
@@ -256,6 +274,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},
};
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index c11b2426dac1..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);
@@ -1045,7 +1046,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 +1558,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 +1573,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 +1713,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 +1986,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);
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)
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index d111c8687f9b..97bb05edcb5a 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -53,8 +53,10 @@ 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
+#define HPWMI_POSTCODEERROR_QUERY 0x2a
enum hp_wmi_radio {
HPWMI_WIFI = 0,
@@ -291,6 +293,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;
@@ -386,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)
{
@@ -431,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)
{
@@ -443,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)
{
@@ -628,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)
@@ -845,6 +903,9 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
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;
add_sysfs_error:
@@ -948,6 +1009,8 @@ static int __init hp_wmi_init(void)
err = hp_wmi_input_setup();
if (err)
return err;
+
+ hp_wmi_enable_hotkeys();
}
if (bios_capable) {
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 <mjg59@srcf.ucam.org>
+ *
+ * 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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <acpi/acpi_drivers.h>
+
+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 = &param;
+
+ 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 = &param;
+
+ 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);
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 <mjg59@srcf.ucam.org>
+ *
+ * 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 <linux/init.h>
+#include <linux/module.h>
+#include <acpi/acpi_drivers.h>
+
+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 = &param;
+
+ 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);
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 <jbarnes@virtuousgeek.org>");
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:
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;