From 7da8fb27eff04e7283d24b0e483c300c8b1a9f5c Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 23 Nov 2013 21:02:51 +0800 Subject: [PATCH 01/18] dell-laptop: fix to return error code in dell_send_intensity() Fix to return error code instead always return 0 from function dell_send_intensity(). Signed-off-by: Wei Yongjun Signed-off-by: Matthew Garrett --- drivers/platform/x86/dell-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index c608b1d33f4a..9d7d6a02ae07 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -684,7 +684,7 @@ static int dell_send_intensity(struct backlight_device *bd) out: release_buffer(); - return 0; + return ret; } static int dell_get_intensity(struct backlight_device *bd) From cf508f4496f7dc7c162a8ac4440165d466f68d4b Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 23 Nov 2013 11:03:19 -0800 Subject: [PATCH 02/18] compal-laptop: Use devm_kzalloc to allocate local data structure Reduce code size and simplify error path. Signed-off-by: Guenter Roeck Signed-off-by: Matthew Garrett --- drivers/platform/x86/compal-laptop.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c index eaa78edb1f4e..7155d79d6b3a 100644 --- a/drivers/platform/x86/compal-laptop.c +++ b/drivers/platform/x86/compal-laptop.c @@ -1026,24 +1026,21 @@ static int compal_probe(struct platform_device *pdev) return 0; /* Fan control */ - data = kzalloc(sizeof(struct compal_data), GFP_KERNEL); + data = devm_kzalloc(&pdev->dev, sizeof(struct compal_data), GFP_KERNEL); if (!data) return -ENOMEM; initialize_fan_control_data(data); err = sysfs_create_group(&pdev->dev.kobj, &compal_attribute_group); - if (err) { - kfree(data); + if (err) return err; - } data->hwmon_dev = hwmon_device_register(&pdev->dev); if (IS_ERR(data->hwmon_dev)) { err = PTR_ERR(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &compal_attribute_group); - kfree(data); return err; } @@ -1083,8 +1080,6 @@ static int compal_remove(struct platform_device *pdev) hwmon_device_unregister(data->hwmon_dev); power_supply_unregister(&data->psy); - kfree(data); - sysfs_remove_group(&pdev->dev.kobj, &compal_attribute_group); return 0; From f0c34c97b3193fee87a3942047c415d476615db1 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 23 Nov 2013 11:03:21 -0800 Subject: [PATCH 03/18] eeepc-laptop: Convert to use devm_hwmon_device_register_with_groups Simplify the code and avoid race condition caused by creating sysfs attributes after creating the hwmon device. Also replace SENSOR_DEVICE_ATTR with DEVICE_ATTR since the extra argument is not used and SENSOR_DEVICE_ATTR is not needed. Signed-off-by: Guenter Roeck Signed-off-by: Matthew Garrett --- drivers/platform/x86/eeepc-laptop.c | 52 ++++++----------------------- 1 file changed, 10 insertions(+), 42 deletions(-) diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index dec68e7a99c7..b2ef152297c9 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -166,7 +166,6 @@ struct eeepc_laptop { struct platform_device *platform_device; struct acpi_device *device; /* the device we are in */ - struct device *hwmon_device; struct backlight_device *backlight_device; struct input_dev *inputdev; @@ -1067,7 +1066,7 @@ static ssize_t show_sys_hwmon(int (*get)(void), char *buf) { \ return store_sys_hwmon(_get, buf, count); \ } \ - static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0); + static DEVICE_ATTR(_name, _mode, show_##_name, store_##_name); EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL); EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR, @@ -1075,55 +1074,26 @@ EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR, EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, eeepc_get_fan_ctrl, eeepc_set_fan_ctrl); -static ssize_t -show_name(struct device *dev, struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "eeepc\n"); -} -static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); - -static struct attribute *hwmon_attributes[] = { - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_name.dev_attr.attr, +static struct attribute *hwmon_attrs[] = { + &dev_attr_pwm1.attr, + &dev_attr_fan1_input.attr, + &dev_attr_pwm1_enable.attr, NULL }; - -static struct attribute_group hwmon_attribute_group = { - .attrs = hwmon_attributes -}; - -static void eeepc_hwmon_exit(struct eeepc_laptop *eeepc) -{ - struct device *hwmon; - - hwmon = eeepc->hwmon_device; - if (!hwmon) - return; - sysfs_remove_group(&hwmon->kobj, - &hwmon_attribute_group); - hwmon_device_unregister(hwmon); - eeepc->hwmon_device = NULL; -} +ATTRIBUTE_GROUPS(hwmon); static int eeepc_hwmon_init(struct eeepc_laptop *eeepc) { + struct device *dev = &eeepc->platform_device->dev; struct device *hwmon; - int result; - hwmon = hwmon_device_register(&eeepc->platform_device->dev); + hwmon = devm_hwmon_device_register_with_groups(dev, "eeepc", NULL, + hwmon_groups); if (IS_ERR(hwmon)) { pr_err("Could not register eeepc hwmon device\n"); - eeepc->hwmon_device = NULL; return PTR_ERR(hwmon); } - eeepc->hwmon_device = hwmon; - result = sysfs_create_group(&hwmon->kobj, - &hwmon_attribute_group); - if (result) - eeepc_hwmon_exit(eeepc); - return result; + return 0; } /* @@ -1479,7 +1449,6 @@ static int eeepc_acpi_add(struct acpi_device *device) fail_rfkill: eeepc_led_exit(eeepc); fail_led: - eeepc_hwmon_exit(eeepc); fail_hwmon: eeepc_input_exit(eeepc); fail_input: @@ -1499,7 +1468,6 @@ static int eeepc_acpi_remove(struct acpi_device *device) eeepc_backlight_exit(eeepc); eeepc_rfkill_exit(eeepc); eeepc_input_exit(eeepc); - eeepc_hwmon_exit(eeepc); eeepc_led_exit(eeepc); eeepc_platform_exit(eeepc); From 4e062581cc95cc0a12f8e48778a0d3ebb48fa980 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 23 Nov 2013 11:03:18 -0800 Subject: [PATCH 04/18] compal-laptop: Replace SENSOR_DEVICE_ATTR with DEVICE_ATTR The extra argument to SENSOR_DEVICE_ATTR is not used. It is therefore not necessary to use SENSOR_DEVICE_ATTR in the first place. Replace it with DEVICE_ATTR. Signed-off-by: Guenter Roeck Signed-off-by: Matthew Garrett --- drivers/platform/x86/compal-laptop.c | 66 ++++++++++++++-------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c index 7155d79d6b3a..9deb0350b8e6 100644 --- a/drivers/platform/x86/compal-laptop.c +++ b/drivers/platform/x86/compal-laptop.c @@ -665,23 +665,23 @@ static DEVICE_ATTR(wake_up_key, static DEVICE_ATTR(wake_up_mouse, 0644, wake_up_mouse_show, wake_up_mouse_store); -static SENSOR_DEVICE_ATTR(name, S_IRUGO, hwmon_name_show, NULL, 1); -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, fan_show, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, temp_cpu, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, temp_cpu_local, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, temp_cpu_DTS, NULL, 1); -static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, temp_northbridge, NULL, 1); -static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, temp_vga, NULL, 1); -static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, temp_SKIN, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, label_cpu, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, label_cpu_local, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, label_cpu_DTS, NULL, 1); -static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, label_northbridge, NULL, 1); -static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO, label_vga, NULL, 1); -static SENSOR_DEVICE_ATTR(temp6_label, S_IRUGO, label_SKIN, NULL, 1); -static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, pwm_show, pwm_store, 1); -static SENSOR_DEVICE_ATTR(pwm1_enable, - S_IRUGO | S_IWUSR, pwm_enable_show, pwm_enable_store, 0); +static DEVICE_ATTR(name, S_IRUGO, hwmon_name_show, NULL); +static DEVICE_ATTR(fan1_input, S_IRUGO, fan_show, NULL); +static DEVICE_ATTR(temp1_input, S_IRUGO, temp_cpu, NULL); +static DEVICE_ATTR(temp2_input, S_IRUGO, temp_cpu_local, NULL); +static DEVICE_ATTR(temp3_input, S_IRUGO, temp_cpu_DTS, NULL); +static DEVICE_ATTR(temp4_input, S_IRUGO, temp_northbridge, NULL); +static DEVICE_ATTR(temp5_input, S_IRUGO, temp_vga, NULL); +static DEVICE_ATTR(temp6_input, S_IRUGO, temp_SKIN, NULL); +static DEVICE_ATTR(temp1_label, S_IRUGO, label_cpu, NULL); +static DEVICE_ATTR(temp2_label, S_IRUGO, label_cpu_local, NULL); +static DEVICE_ATTR(temp3_label, S_IRUGO, label_cpu_DTS, NULL); +static DEVICE_ATTR(temp4_label, S_IRUGO, label_northbridge, NULL); +static DEVICE_ATTR(temp5_label, S_IRUGO, label_vga, NULL); +static DEVICE_ATTR(temp6_label, S_IRUGO, label_SKIN, NULL); +static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, pwm_show, pwm_store); +static DEVICE_ATTR(pwm1_enable, + S_IRUGO | S_IWUSR, pwm_enable_show, pwm_enable_store); static struct attribute *compal_attributes[] = { &dev_attr_wake_up_pme.attr, @@ -692,22 +692,22 @@ static struct attribute *compal_attributes[] = { &dev_attr_wake_up_mouse.attr, /* Maybe put the sensor-stuff in a separate hwmon-driver? That way, * the hwmon sysfs won't be cluttered with the above files. */ - &sensor_dev_attr_name.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_temp5_input.dev_attr.attr, - &sensor_dev_attr_temp6_input.dev_attr.attr, - &sensor_dev_attr_temp1_label.dev_attr.attr, - &sensor_dev_attr_temp2_label.dev_attr.attr, - &sensor_dev_attr_temp3_label.dev_attr.attr, - &sensor_dev_attr_temp4_label.dev_attr.attr, - &sensor_dev_attr_temp5_label.dev_attr.attr, - &sensor_dev_attr_temp6_label.dev_attr.attr, + &dev_attr_name.attr, + &dev_attr_pwm1_enable.attr, + &dev_attr_pwm1.attr, + &dev_attr_fan1_input.attr, + &dev_attr_temp1_input.attr, + &dev_attr_temp2_input.attr, + &dev_attr_temp3_input.attr, + &dev_attr_temp4_input.attr, + &dev_attr_temp5_input.attr, + &dev_attr_temp6_input.attr, + &dev_attr_temp1_label.attr, + &dev_attr_temp2_label.attr, + &dev_attr_temp3_label.attr, + &dev_attr_temp4_label.attr, + &dev_attr_temp5_label.attr, + &dev_attr_temp6_label.attr, NULL }; From c2be45f09bb0b37ba1f87f39fbb04886f94e3e58 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 23 Nov 2013 11:03:20 -0800 Subject: [PATCH 05/18] compal-laptop: Use devm_hwmon_device_register_with_groups Simplify the code and create hwmon attributes as well as hwmon device in one go. With the new hwmon API, hwmon attributes are now attached to the hwmon device. Therefore, split hwmon and device attributes into two separate groups. Platform attributes are still attached to the platform device. Also use devm_kzalloc to allocate local data structures for further simplification. Signed-off-by: Guenter Roeck Signed-off-by: Matthew Garrett --- drivers/platform/x86/compal-laptop.c | 52 ++++++++++++---------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c index 9deb0350b8e6..7297df2ebf50 100644 --- a/drivers/platform/x86/compal-laptop.c +++ b/drivers/platform/x86/compal-laptop.c @@ -173,8 +173,7 @@ /* ======= */ struct compal_data{ /* Fan control */ - struct device *hwmon_dev; - int pwm_enable; /* 0:full on, 1:set by pwm1, 2:control by moterboard */ + int pwm_enable; /* 0:full on, 1:set by pwm1, 2:control by motherboard */ unsigned char curr_pwm; /* Power supply */ @@ -402,15 +401,6 @@ SIMPLE_MASKED_STORE_SHOW(wake_up_wlan, WAKE_UP_ADDR, WAKE_UP_WLAN) SIMPLE_MASKED_STORE_SHOW(wake_up_key, WAKE_UP_ADDR, WAKE_UP_KEY) SIMPLE_MASKED_STORE_SHOW(wake_up_mouse, WAKE_UP_ADDR, WAKE_UP_MOUSE) - -/* General hwmon interface */ -static ssize_t hwmon_name_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%s\n", DRIVER_NAME); -} - - /* Fan control interface */ static ssize_t pwm_enable_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -665,7 +655,6 @@ static DEVICE_ATTR(wake_up_key, static DEVICE_ATTR(wake_up_mouse, 0644, wake_up_mouse_show, wake_up_mouse_store); -static DEVICE_ATTR(name, S_IRUGO, hwmon_name_show, NULL); static DEVICE_ATTR(fan1_input, S_IRUGO, fan_show, NULL); static DEVICE_ATTR(temp1_input, S_IRUGO, temp_cpu, NULL); static DEVICE_ATTR(temp2_input, S_IRUGO, temp_cpu_local, NULL); @@ -683,16 +672,20 @@ static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, pwm_show, pwm_store); static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, pwm_enable_show, pwm_enable_store); -static struct attribute *compal_attributes[] = { +static struct attribute *compal_platform_attrs[] = { &dev_attr_wake_up_pme.attr, &dev_attr_wake_up_modem.attr, &dev_attr_wake_up_lan.attr, &dev_attr_wake_up_wlan.attr, &dev_attr_wake_up_key.attr, &dev_attr_wake_up_mouse.attr, - /* Maybe put the sensor-stuff in a separate hwmon-driver? That way, - * the hwmon sysfs won't be cluttered with the above files. */ - &dev_attr_name.attr, + NULL +}; +static struct attribute_group compal_platform_attr_group = { + .attrs = compal_platform_attrs +}; + +static struct attribute *compal_hwmon_attrs[] = { &dev_attr_pwm1_enable.attr, &dev_attr_pwm1.attr, &dev_attr_fan1_input.attr, @@ -710,10 +703,7 @@ static struct attribute *compal_attributes[] = { &dev_attr_temp6_label.attr, NULL }; - -static struct attribute_group compal_attribute_group = { - .attrs = compal_attributes -}; +ATTRIBUTE_GROUPS(compal_hwmon); static int compal_probe(struct platform_device *); static int compal_remove(struct platform_device *); @@ -1021,6 +1011,7 @@ static int compal_probe(struct platform_device *pdev) { int err; struct compal_data *data; + struct device *hwmon_dev; if (!extra_features) return 0; @@ -1032,16 +1023,16 @@ static int compal_probe(struct platform_device *pdev) initialize_fan_control_data(data); - err = sysfs_create_group(&pdev->dev.kobj, &compal_attribute_group); + err = sysfs_create_group(&pdev->dev.kobj, &compal_platform_attr_group); if (err) return err; - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - sysfs_remove_group(&pdev->dev.kobj, - &compal_attribute_group); - return err; + hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, + DRIVER_NAME, data, + compal_hwmon_groups); + if (IS_ERR(hwmon_dev)) { + err = PTR_ERR(hwmon_dev); + goto remove; } /* Power supply */ @@ -1051,6 +1042,10 @@ static int compal_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); return 0; + +remove: + sysfs_remove_group(&pdev->dev.kobj, &compal_platform_attr_group); + return err; } static void __exit compal_cleanup(void) @@ -1077,10 +1072,9 @@ static int compal_remove(struct platform_device *pdev) pwm_disable_control(); data = platform_get_drvdata(pdev); - hwmon_device_unregister(data->hwmon_dev); power_supply_unregister(&data->psy); - sysfs_remove_group(&pdev->dev.kobj, &compal_attribute_group); + sysfs_remove_group(&pdev->dev.kobj, &compal_platform_attr_group); return 0; } From 50a639fb158c6aafe86ba7d6104de69518a9d09a Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 23 Nov 2013 11:03:17 -0800 Subject: [PATCH 06/18] asus-wmi: Convert to use devm_hwmon_device_register_with_groups Simplify the code and avoid race conditions due to late sysfs attribute registration. Also replace SENSOR_DEVICE_ATTR with DEVICE_ATTR; the additional parameter is not used and thus unnecessary. Signed-off-by: Guenter Roeck Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-wmi.c | 48 ++++++++------------------------- 1 file changed, 11 insertions(+), 37 deletions(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 19c313b056c3..e9e22a51e703 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -184,7 +184,6 @@ struct asus_wmi { struct input_dev *inputdev; struct backlight_device *backlight_device; - struct device *hwmon_device; struct platform_device *platform_device; struct led_classdev wlan_led; @@ -1071,20 +1070,12 @@ static ssize_t asus_hwmon_temp1(struct device *dev, return sprintf(buf, "%d\n", value); } -static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, asus_hwmon_pwm1, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL, 0); - -static ssize_t -show_name(struct device *dev, struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "asus\n"); -} -static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); +static DEVICE_ATTR(pwm1, S_IRUGO, asus_hwmon_pwm1, NULL); +static DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL); static struct attribute *hwmon_attributes[] = { - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_name.dev_attr.attr, + &dev_attr_pwm1.attr, + &dev_attr_temp1_input.attr, NULL }; @@ -1098,9 +1089,9 @@ static umode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj, int dev_id = -1; u32 value = ASUS_WMI_UNSUPPORTED_METHOD; - if (attr == &sensor_dev_attr_pwm1.dev_attr.attr) + if (attr == &dev_attr_pwm1.attr) dev_id = ASUS_WMI_DEVID_FAN_CTRL; - else if (attr == &sensor_dev_attr_temp1_input.dev_attr.attr) + else if (attr == &dev_attr_temp1_input.attr) dev_id = ASUS_WMI_DEVID_THERMAL_CTRL; if (dev_id != -1) { @@ -1135,35 +1126,20 @@ static struct attribute_group hwmon_attribute_group = { .is_visible = asus_hwmon_sysfs_is_visible, .attrs = hwmon_attributes }; - -static void asus_wmi_hwmon_exit(struct asus_wmi *asus) -{ - struct device *hwmon; - - hwmon = asus->hwmon_device; - if (!hwmon) - return; - sysfs_remove_group(&hwmon->kobj, &hwmon_attribute_group); - hwmon_device_unregister(hwmon); - asus->hwmon_device = NULL; -} +__ATTRIBUTE_GROUPS(hwmon_attribute); static int asus_wmi_hwmon_init(struct asus_wmi *asus) { struct device *hwmon; - int result; - hwmon = hwmon_device_register(&asus->platform_device->dev); + hwmon = hwmon_device_register_with_groups(&asus->platform_device->dev, + "asus", asus, + hwmon_attribute_groups); if (IS_ERR(hwmon)) { pr_err("Could not register asus hwmon device\n"); return PTR_ERR(hwmon); } - dev_set_drvdata(hwmon, asus); - asus->hwmon_device = hwmon; - result = sysfs_create_group(&hwmon->kobj, &hwmon_attribute_group); - if (result) - asus_wmi_hwmon_exit(asus); - return result; + return 0; } /* @@ -1834,7 +1810,6 @@ fail_backlight: fail_rfkill: asus_wmi_led_exit(asus); fail_leds: - asus_wmi_hwmon_exit(asus); fail_hwmon: asus_wmi_input_exit(asus); fail_input: @@ -1852,7 +1827,6 @@ static int asus_wmi_remove(struct platform_device *device) wmi_remove_notify_handler(asus->driver->event_guid); asus_wmi_backlight_exit(asus); asus_wmi_input_exit(asus); - asus_wmi_hwmon_exit(asus); asus_wmi_led_exit(asus); asus_wmi_rfkill_exit(asus); asus_wmi_debugfs_exit(asus); From 694e523cfe07e908d170c6b9691882e101f82cd6 Mon Sep 17 00:00:00 2001 From: David Cohen Date: Mon, 2 Dec 2013 16:20:00 -0800 Subject: [PATCH 07/18] ipc: simplify platform data approach This patch removes the unnecessary enum for platform type to handle the array of pdatas. We can set pdata directly to pci_device_id struct instead. Signed-off-by: David Cohen Signed-off-by: Matthew Garrett --- drivers/platform/x86/intel_scu_ipc.c | 84 +++++++++++++--------------- 1 file changed, 40 insertions(+), 44 deletions(-) diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index 60ea476a9130..259969d31055 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c @@ -62,13 +62,6 @@ #define IPC_RWBUF_SIZE 20 /* IPC Read buffer Size */ #define IPC_IOC 0x100 /* IPC command register IOC bit */ -enum { - SCU_IPC_LINCROFT, - SCU_IPC_PENWELL, - SCU_IPC_CLOVERVIEW, - SCU_IPC_TANGIER, -}; - /* intel scu ipc driver data*/ struct intel_scu_ipc_pdata_t { u32 ipc_base; @@ -78,35 +71,29 @@ struct intel_scu_ipc_pdata_t { u8 irq_mode; }; -static struct intel_scu_ipc_pdata_t intel_scu_ipc_pdata[] = { - [SCU_IPC_LINCROFT] = { - .ipc_base = 0xff11c000, - .i2c_base = 0xff12b000, - .ipc_len = 0x100, - .i2c_len = 0x10, - .irq_mode = 0, - }, - [SCU_IPC_PENWELL] = { - .ipc_base = 0xff11c000, - .i2c_base = 0xff12b000, - .ipc_len = 0x100, - .i2c_len = 0x10, - .irq_mode = 1, - }, - [SCU_IPC_CLOVERVIEW] = { - .ipc_base = 0xff11c000, - .i2c_base = 0xff12b000, - .ipc_len = 0x100, - .i2c_len = 0x10, - .irq_mode = 1, - }, - [SCU_IPC_TANGIER] = { - .ipc_base = 0xff009000, - .i2c_base = 0xff00d000, - .ipc_len = 0x100, - .i2c_len = 0x10, - .irq_mode = 0, - }, +static struct intel_scu_ipc_pdata_t intel_scu_ipc_lincroft_pdata = { + .ipc_base = 0xff11c000, + .i2c_base = 0xff12b000, + .ipc_len = 0x100, + .i2c_len = 0x10, + .irq_mode = 0, +}; + +/* Penwell and Cloverview */ +static struct intel_scu_ipc_pdata_t intel_scu_ipc_penwell_pdata = { + .ipc_base = 0xff11c000, + .i2c_base = 0xff12b000, + .ipc_len = 0x100, + .i2c_len = 0x10, + .irq_mode = 1, +}; + +static struct intel_scu_ipc_pdata_t intel_scu_ipc_tangier_pdata = { + .ipc_base = 0xff009000, + .i2c_base = 0xff00d000, + .ipc_len = 0x100, + .i2c_len = 0x10, + .irq_mode = 0, }; static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id); @@ -583,15 +570,14 @@ static irqreturn_t ioc(int irq, void *dev_id) */ static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id) { - int err, pid; + int err; struct intel_scu_ipc_pdata_t *pdata; resource_size_t pci_resource; if (ipcdev.pdev) /* We support only one SCU */ return -EBUSY; - pid = id->driver_data; - pdata = &intel_scu_ipc_pdata[pid]; + pdata = (struct intel_scu_ipc_pdata_t *)id->driver_data; ipcdev.pdev = pci_dev_get(dev); ipcdev.irq_mode = pdata->irq_mode; @@ -650,11 +636,21 @@ static void ipc_remove(struct pci_dev *pdev) } static DEFINE_PCI_DEVICE_TABLE(pci_ids) = { - {PCI_VDEVICE(INTEL, 0x082a), SCU_IPC_LINCROFT}, - {PCI_VDEVICE(INTEL, 0x080e), SCU_IPC_PENWELL}, - {PCI_VDEVICE(INTEL, 0x08ea), SCU_IPC_CLOVERVIEW}, - {PCI_VDEVICE(INTEL, 0x11a0), SCU_IPC_TANGIER}, - { 0,} + { + PCI_VDEVICE(INTEL, 0x082a), + (kernel_ulong_t)&intel_scu_ipc_lincroft_pdata, + }, { + PCI_VDEVICE(INTEL, 0x080e), + (kernel_ulong_t)&intel_scu_ipc_penwell_pdata, + }, { + PCI_VDEVICE(INTEL, 0x08ea), + (kernel_ulong_t)&intel_scu_ipc_penwell_pdata, + }, { + PCI_VDEVICE(INTEL, 0x11a0), + (kernel_ulong_t)&intel_scu_ipc_tangier_pdata, + }, { + 0, + } }; MODULE_DEVICE_TABLE(pci, pci_ids); From ba5194f18637a95692b5d146004d1aa8be08c525 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 6 Dec 2013 12:17:27 +0100 Subject: [PATCH 08/18] dell-laptop: rkill whitelist Precision models Given that Precision mobile workstations are top of the line Dell products, I expect the functionality of rfkill there to be as reliable as on Latitudes so whitelist Precisions. https://bugzilla.kernel.org/show_bug.cgi?id=65731 Reported-by: Calum Lind Signed-off-by: Hans de Goede Signed-off-by: Matthew Garrett --- drivers/platform/x86/dell-laptop.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 9d7d6a02ae07..d2ceb761a7a2 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -562,16 +562,19 @@ static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); static int __init dell_setup_rfkill(void) { - int status; - int ret; + int status, ret, whitelisted; const char *product; /* - * rfkill causes trouble on various non Latitudes, according to Dell - * actually testing the rfkill functionality is only done on Latitudes. + * rfkill support causes trouble on various models, mostly Inspirons. + * So we whitelist certain series, and don't support rfkill on others. */ + whitelisted = 0; product = dmi_get_system_info(DMI_PRODUCT_NAME); - if (!force_rfkill && (!product || strncmp(product, "Latitude", 8))) + if (product && (strncmp(product, "Latitude", 8) == 0 || + strncmp(product, "Precision", 9) == 0)) + whitelisted = 1; + if (!force_rfkill && !whitelisted) return 0; get_buffer(); From 04b73387419942a6ba3e6a10327b72f43b760979 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Fri, 13 Dec 2013 12:56:34 +0530 Subject: [PATCH 09/18] drivers: platform: Mark functions as static in hp_accel.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch marks the functions lis3lv02d_acpi_init(), lis3lv02d_acpi_read() and lis3lv02d_acpi_write() as static in x86/hp_accel.c because they are not used outside this file. Thus, it also eliminates the following warnings in x86/hp_accel.c: drivers/platform/x86/hp_accel.c:91:5: warning: no previous prototype for ‘lis3lv02d_acpi_init’ [-Wmissing-prototypes] drivers/platform/x86/hp_accel.c:109:5: warning: no previous prototype for ‘lis3lv02d_acpi_read’ [-Wmissing-prototypes] drivers/platform/x86/hp_accel.c:132:5: warning: no previous prototype for ‘lis3lv02d_acpi_write’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Signed-off-by: Matthew Garrett --- drivers/platform/x86/hp_accel.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c index a8e43cf70fac..01b619eca38e 100644 --- a/drivers/platform/x86/hp_accel.c +++ b/drivers/platform/x86/hp_accel.c @@ -88,7 +88,7 @@ MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids); * * Returns 0 on success. */ -int lis3lv02d_acpi_init(struct lis3lv02d *lis3) +static int lis3lv02d_acpi_init(struct lis3lv02d *lis3) { struct acpi_device *dev = lis3->bus_priv; if (acpi_evaluate_object(dev->handle, METHOD_NAME__INI, @@ -106,7 +106,7 @@ int lis3lv02d_acpi_init(struct lis3lv02d *lis3) * * Returns 0 on success. */ -int lis3lv02d_acpi_read(struct lis3lv02d *lis3, int reg, u8 *ret) +static int lis3lv02d_acpi_read(struct lis3lv02d *lis3, int reg, u8 *ret) { struct acpi_device *dev = lis3->bus_priv; union acpi_object arg0 = { ACPI_TYPE_INTEGER }; @@ -129,7 +129,7 @@ int lis3lv02d_acpi_read(struct lis3lv02d *lis3, int reg, u8 *ret) * * Returns 0 on success. */ -int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val) +static int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val) { struct acpi_device *dev = lis3->bus_priv; unsigned long long ret; /* Not used when writting */ From 475879d65123eaf0b1490d603c4a4f5faac4179d Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Fri, 13 Dec 2013 12:59:52 +0530 Subject: [PATCH 10/18] drivers: platform: Include appropriate header file in mxm-wmi.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch includes appropriate header file linux/mxm-wmi.h in x86/mxm-wmi.c because functions mxm_wmi_call_mxds(), mxm_wmi_call_mxmx() and mxm_wmi_supported() have their prototype declaration in linux/mxm-wmi.h. Thus, it also eliminates the following warnings in x86/mxm-wmi.c: drivers/platform/x86/mxm-wmi.c:43:5: warning: no previous prototype for ‘mxm_wmi_call_mxds’ [-Wmissing-prototypes] drivers/platform/x86/mxm-wmi.c:68:5: warning: no previous prototype for ‘mxm_wmi_call_mxmx’ [-Wmissing-prototypes] drivers/platform/x86/mxm-wmi.c:93:6: warning: no previous prototype for ‘mxm_wmi_supported’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Signed-off-by: Matthew Garrett --- drivers/platform/x86/mxm-wmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/mxm-wmi.c b/drivers/platform/x86/mxm-wmi.c index 0aea63b3729a..7503d2b9b073 100644 --- a/drivers/platform/x86/mxm-wmi.c +++ b/drivers/platform/x86/mxm-wmi.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include From 997ab407d2b4e7d7ce2788d2de68435eb94fcfec Mon Sep 17 00:00:00 2001 From: "David E. Box" Date: Thu, 19 Dec 2013 10:37:22 -0800 Subject: [PATCH 11/18] X86 platform: New BayTrail IOSF-SB MBI driver Current Intel SOC cores use a MailBox Interface (MBI) to provide access to unit devices connected to the system fabric. This driver implements access to this interface on BayTrail platforms. This is a requirement for drivers that need access to unit registers on the platform (e.g. accessing the PUNIT for power management features such as RAPL). Serialized access is handled by all exported routines with spinlocks. The API includes 3 functions for access to unit registers: int bt_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr) int bt_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr) int bt_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask) port: indicating the unit being accessed opcode: the read or write port specific opcode offset: the register offset within the port mdr: the register data to be read, written, or modified mask: bit locations in mdr to change Returns nonzero on error Note: GPU code handles access to the GFX unit. Therefore access to that unit with this driver is disallowed to avoid conflicts. Signed-off-by: David E. Box Signed-off-by: Matthew Garrett --- drivers/platform/x86/Kconfig | 8 + drivers/platform/x86/Makefile | 1 + drivers/platform/x86/intel_baytrail.c | 224 ++++++++++++++++++++++++++ drivers/platform/x86/intel_baytrail.h | 90 +++++++++++ 4 files changed, 323 insertions(+) create mode 100644 drivers/platform/x86/intel_baytrail.c create mode 100644 drivers/platform/x86/intel_baytrail.h diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index d9dcd37b5a52..a698b928327d 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -808,4 +808,12 @@ config PVPANIC a paravirtualized device provided by QEMU; it lets a virtual machine (guest) communicate panic events to the host. +config INTEL_BAYTRAIL_MBI + tristate + depends on PCI + ---help--- + Needed on Baytrail platforms for access to the IOSF Sideband Mailbox + Interface. This is a requirement for systems that need to configure + the PUNIT for power management features such as RAPL. + endif # X86_PLATFORM_DEVICES diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index f0e6aa407ffb..79bd3c49be3d 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -54,3 +54,4 @@ obj-$(CONFIG_INTEL_RST) += intel-rst.o obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o obj-$(CONFIG_PVPANIC) += pvpanic.o +obj-$(CONFIG_INTEL_BAYTRAIL_MBI) += intel_baytrail.o diff --git a/drivers/platform/x86/intel_baytrail.c b/drivers/platform/x86/intel_baytrail.c new file mode 100644 index 000000000000..f96626b17260 --- /dev/null +++ b/drivers/platform/x86/intel_baytrail.c @@ -0,0 +1,224 @@ +/* + * Baytrail IOSF-SB MailBox Interface Driver + * Copyright (c) 2013, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * + * The IOSF-SB is a fabric bus available on Atom based SOC's that uses a + * mailbox interface (MBI) to communicate with mutiple devices. This + * driver implements BayTrail-specific access to this interface. + */ + +#include +#include +#include +#include + +#include "intel_baytrail.h" + +static DEFINE_SPINLOCK(iosf_mbi_lock); + +static inline u32 iosf_mbi_form_mcr(u8 op, u8 port, u8 offset) +{ + return (op << 24) | (port << 16) | (offset << 8) | BT_MBI_ENABLE; +} + +static struct pci_dev *mbi_pdev; /* one mbi device */ + +/* Hold lock before calling */ +static int iosf_mbi_pci_read_mdr(u32 mcrx, u32 mcr, u32 *mdr) +{ + int result; + + if (!mbi_pdev) + return -ENODEV; + + if (mcrx) { + result = pci_write_config_dword(mbi_pdev, + BT_MBI_MCRX_OFFSET, mcrx); + if (result < 0) + goto iosf_mbi_read_err; + } + + result = pci_write_config_dword(mbi_pdev, + BT_MBI_MCR_OFFSET, mcr); + if (result < 0) + goto iosf_mbi_read_err; + + result = pci_read_config_dword(mbi_pdev, + BT_MBI_MDR_OFFSET, mdr); + if (result < 0) + goto iosf_mbi_read_err; + + return 0; + +iosf_mbi_read_err: + dev_err(&mbi_pdev->dev, "error: PCI config operation returned %d\n", + result); + return result; +} + +/* Hold lock before calling */ +static int iosf_mbi_pci_write_mdr(u32 mcrx, u32 mcr, u32 mdr) +{ + int result; + + if (!mbi_pdev) + return -ENODEV; + + result = pci_write_config_dword(mbi_pdev, + BT_MBI_MDR_OFFSET, mdr); + if (result < 0) + goto iosf_mbi_write_err; + + if (mcrx) { + result = pci_write_config_dword(mbi_pdev, + BT_MBI_MCRX_OFFSET, mcrx); + if (result < 0) + goto iosf_mbi_write_err; + } + + result = pci_write_config_dword(mbi_pdev, + BT_MBI_MCR_OFFSET, mcr); + if (result < 0) + goto iosf_mbi_write_err; + + return 0; + +iosf_mbi_write_err: + dev_err(&mbi_pdev->dev, "error: PCI config operation returned %d\n", + result); + return result; +} + +int bt_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr) +{ + u32 mcr, mcrx; + unsigned long flags; + int ret; + + /*Access to the GFX unit is handled by GPU code */ + BUG_ON(port == BT_MBI_UNIT_GFX); + + mcr = iosf_mbi_form_mcr(opcode, port, offset & BT_MBI_MASK_LO); + mcrx = offset & BT_MBI_MASK_HI; + + spin_lock_irqsave(&iosf_mbi_lock, flags); + ret = iosf_mbi_pci_read_mdr(mcrx, mcr, mdr); + spin_unlock_irqrestore(&iosf_mbi_lock, flags); + + return ret; +} +EXPORT_SYMBOL(bt_mbi_read); + +int bt_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr) +{ + u32 mcr, mcrx; + unsigned long flags; + int ret; + + /*Access to the GFX unit is handled by GPU code */ + BUG_ON(port == BT_MBI_UNIT_GFX); + + mcr = iosf_mbi_form_mcr(opcode, port, offset & BT_MBI_MASK_LO); + mcrx = offset & BT_MBI_MASK_HI; + + spin_lock_irqsave(&iosf_mbi_lock, flags); + ret = iosf_mbi_pci_write_mdr(mcrx, mcr, mdr); + spin_unlock_irqrestore(&iosf_mbi_lock, flags); + + return ret; +} +EXPORT_SYMBOL(bt_mbi_write); + +int bt_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask) +{ + u32 mcr, mcrx; + u32 value; + unsigned long flags; + int ret; + + /*Access to the GFX unit is handled by GPU code */ + BUG_ON(port == BT_MBI_UNIT_GFX); + + mcr = iosf_mbi_form_mcr(opcode, port, offset & BT_MBI_MASK_LO); + mcrx = offset & BT_MBI_MASK_HI; + + spin_lock_irqsave(&iosf_mbi_lock, flags); + + /* Read current mdr value */ + ret = iosf_mbi_pci_read_mdr(mcrx, mcr & BT_MBI_RD_MASK, &value); + if (ret < 0) { + spin_unlock_irqrestore(&iosf_mbi_lock, flags); + return ret; + } + + /* Apply mask */ + value &= ~mask; + mdr &= mask; + value |= mdr; + + /* Write back */ + ret = iosf_mbi_pci_write_mdr(mcrx, mcr | BT_MBI_WR_MASK, value); + + spin_unlock_irqrestore(&iosf_mbi_lock, flags); + + return ret; +} +EXPORT_SYMBOL(bt_mbi_modify); + +static int iosf_mbi_probe(struct pci_dev *pdev, + const struct pci_device_id *unused) +{ + int ret; + + ret = pci_enable_device(pdev); + if (ret < 0) { + dev_err(&pdev->dev, "error: could not enable device\n"); + return ret; + } + + mbi_pdev = pci_dev_get(pdev); + return 0; +} + +static DEFINE_PCI_DEVICE_TABLE(iosf_mbi_pci_ids) = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0F00) }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, iosf_mbi_pci_ids); + +static struct pci_driver iosf_mbi_pci_driver = { + .name = "iosf_mbi_pci", + .probe = iosf_mbi_probe, + .id_table = iosf_mbi_pci_ids, +}; + +static int __init bt_mbi_init(void) +{ + return pci_register_driver(&iosf_mbi_pci_driver); +} + +static void __exit bt_mbi_exit(void) +{ + pci_unregister_driver(&iosf_mbi_pci_driver); + if (mbi_pdev) { + pci_dev_put(mbi_pdev); + mbi_pdev = NULL; + } +} + +module_init(bt_mbi_init); +module_exit(bt_mbi_exit); + +MODULE_AUTHOR("David E. Box "); +MODULE_DESCRIPTION("BayTrail Mailbox Interface accessor"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/platform/x86/intel_baytrail.h b/drivers/platform/x86/intel_baytrail.h new file mode 100644 index 000000000000..8bcc311262e9 --- /dev/null +++ b/drivers/platform/x86/intel_baytrail.h @@ -0,0 +1,90 @@ +/* + * intel_baytrail.h: MailBox access support for Intel BayTrail platforms + */ + +#ifndef INTEL_BAYTRAIL_MBI_SYMS_H +#define INTEL_BAYTRAIL_MBI_SYMS_H + +#define BT_MBI_MCR_OFFSET 0xD0 +#define BT_MBI_MDR_OFFSET 0xD4 +#define BT_MBI_MCRX_OFFSET 0xD8 + +#define BT_MBI_RD_MASK 0xFEFFFFFF +#define BT_MBI_WR_MASK 0X01000000 + +#define BT_MBI_MASK_HI 0xFFFFFF00 +#define BT_MBI_MASK_LO 0x000000FF +#define BT_MBI_ENABLE 0xF0 + +/* BT-SB unit access methods */ +#define BT_MBI_UNIT_AUNIT 0x00 +#define BT_MBI_UNIT_SMC 0x01 +#define BT_MBI_UNIT_CPU 0x02 +#define BT_MBI_UNIT_BUNIT 0x03 +#define BT_MBI_UNIT_PMC 0x04 +#define BT_MBI_UNIT_GFX 0x06 +#define BT_MBI_UNIT_SMI 0x0C +#define BT_MBI_UNIT_USB 0x43 +#define BT_MBI_UNIT_SATA 0xA3 +#define BT_MBI_UNIT_PCIE 0xA6 + +/* Read/write opcodes */ +#define BT_MBI_AUNIT_READ 0x10 +#define BT_MBI_AUNIT_WRITE 0x11 +#define BT_MBI_SMC_READ 0x10 +#define BT_MBI_SMC_WRITE 0x11 +#define BT_MBI_CPU_READ 0x10 +#define BT_MBI_CPU_WRITE 0x11 +#define BT_MBI_BUNIT_READ 0x10 +#define BT_MBI_BUNIT_WRITE 0x11 +#define BT_MBI_PMC_READ 0x06 +#define BT_MBI_PMC_WRITE 0x07 +#define BT_MBI_GFX_READ 0x00 +#define BT_MBI_GFX_WRITE 0x01 +#define BT_MBI_SMIO_READ 0x06 +#define BT_MBI_SMIO_WRITE 0x07 +#define BT_MBI_USB_READ 0x06 +#define BT_MBI_USB_WRITE 0x07 +#define BT_MBI_SATA_READ 0x00 +#define BT_MBI_SATA_WRITE 0x01 +#define BT_MBI_PCIE_READ 0x00 +#define BT_MBI_PCIE_WRITE 0x01 + +/** + * bt_mbi_read() - MailBox Interface read command + * @port: port indicating subunit being accessed + * @opcode: port specific read or write opcode + * @offset: register address offset + * @mdr: register data to be read + * + * Locking is handled by spinlock - cannot sleep. + * Return: Nonzero on error + */ +int bt_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr); + +/** + * bt_mbi_write() - MailBox unmasked write command + * @port: port indicating subunit being accessed + * @opcode: port specific read or write opcode + * @offset: register address offset + * @mdr: register data to be written + * + * Locking is handled by spinlock - cannot sleep. + * Return: Nonzero on error + */ +int bt_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr); + +/** + * bt_mbi_modify() - MailBox masked write command + * @port: port indicating subunit being accessed + * @opcode: port specific read or write opcode + * @offset: register address offset + * @mdr: register data being modified + * @mask: mask indicating bits in mdr to be modified + * + * Locking is handled by spinlock - cannot sleep. + * Return: Nonzero on error + */ +int bt_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask); + +#endif /* INTEL_BAYTRAIL_MBI_SYMS_H */ From 97f440c23f2b02fac8af0558cba9ca0bed603794 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 24 Dec 2013 20:34:01 +0100 Subject: [PATCH 12/18] dell-laptop: Only install the i8042 filter when rfkill is active Installing the i8042 filter is not useful on machines where rfkill is not whitelisted, so move the filter installation into dell_setup_rfkill, after the whitelist check. This avoids doing a needless and potentially troublesome rfkill query (dell_send_request(buf, 17, 11)) when the wireless Fn key gets pressed on non whitelisted laptops. This patch was written as a result of: https://bugzilla.redhat.com/show_bug.cgi?id=1045807 It is not yet clear if this is related, but it is a good idea to not register the i8042 filter in general. Signed-off-by: Hans de Goede Signed-off-by: Matthew Garrett --- drivers/platform/x86/dell-laptop.c | 63 +++++++++++++++--------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index d2ceb761a7a2..fed4111ac31a 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -559,6 +559,29 @@ static void dell_update_rfkill(struct work_struct *ignored) } static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); +static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, + struct serio *port) +{ + static bool extended; + + if (str & 0x20) + return false; + + if (unlikely(data == 0xe0)) { + extended = true; + return false; + } else if (unlikely(extended)) { + switch (data) { + case 0x8: + schedule_delayed_work(&dell_rfkill_work, + round_jiffies_relative(HZ / 4)); + break; + } + extended = false; + } + + return false; +} static int __init dell_setup_rfkill(void) { @@ -636,7 +659,16 @@ static int __init dell_setup_rfkill(void) goto err_wwan; } + ret = i8042_install_filter(dell_laptop_i8042_filter); + if (ret) { + pr_warn("Unable to install key filter\n"); + goto err_filter; + } + return 0; +err_filter: + if (wwan_rfkill) + rfkill_unregister(wwan_rfkill); err_wwan: rfkill_destroy(wwan_rfkill); if (bluetooth_rfkill) @@ -758,30 +790,6 @@ static void touchpad_led_exit(void) led_classdev_unregister(&touchpad_led); } -static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, - struct serio *port) -{ - static bool extended; - - if (str & 0x20) - return false; - - if (unlikely(data == 0xe0)) { - extended = true; - return false; - } else if (unlikely(extended)) { - switch (data) { - case 0x8: - schedule_delayed_work(&dell_rfkill_work, - round_jiffies_relative(HZ / 4)); - break; - } - extended = false; - } - - return false; -} - static int __init dell_init(void) { int max_intensity = 0; @@ -831,12 +839,6 @@ static int __init dell_init(void) goto fail_rfkill; } - ret = i8042_install_filter(dell_laptop_i8042_filter); - if (ret) { - pr_warn("Unable to install key filter\n"); - goto fail_filter; - } - if (quirks && quirks->touchpad_led) touchpad_led_init(&platform_device->dev); @@ -888,7 +890,6 @@ static int __init dell_init(void) fail_backlight: i8042_remove_filter(dell_laptop_i8042_filter); cancel_delayed_work_sync(&dell_rfkill_work); -fail_filter: dell_cleanup_rfkill(); fail_rfkill: free_page((unsigned long)bufferpage); From b30bb89f0fb29502f573d01419391a1e2a4cc4f1 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Dec 2013 23:47:36 +0100 Subject: [PATCH 13/18] fujitsu-laptop: fix error return code These functions mix the use of result and error. In acpi_fujitsu_add, result does not seem useful; it would seem reasonable to propagate the return value of acpi_bus_update_power in an error case. On the other hand, in the case of acpi_fujitsu_hotkey_add, there is an initialization of result that can lead to what looks like a failure case, but that does not abort the function. The variable result is kept for this case. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Matthew Garrett --- drivers/platform/x86/fujitsu-laptop.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 9d30d69aa78f..be02bcc346d3 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -633,7 +633,6 @@ static struct dmi_system_id fujitsu_dmi_table[] = { static int acpi_fujitsu_add(struct acpi_device *device) { - int result = 0; int state = 0; struct input_dev *input; int error; @@ -669,8 +668,8 @@ static int acpi_fujitsu_add(struct acpi_device *device) if (error) goto err_free_input_dev; - result = acpi_bus_update_power(fujitsu->acpi_handle, &state); - if (result) { + error = acpi_bus_update_power(fujitsu->acpi_handle, &state); + if (error) { pr_err("Error reading power state\n"); goto err_unregister_input_dev; } @@ -700,7 +699,7 @@ static int acpi_fujitsu_add(struct acpi_device *device) fujitsu->max_brightness = FUJITSU_LCD_N_LEVELS; get_lcd_level(); - return result; + return 0; err_unregister_input_dev: input_unregister_device(input); @@ -708,7 +707,7 @@ err_unregister_input_dev: err_free_input_dev: input_free_device(input); err_stop: - return result; + return error; } static int acpi_fujitsu_remove(struct acpi_device *device) @@ -831,8 +830,8 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) if (error) goto err_free_input_dev; - result = acpi_bus_update_power(fujitsu_hotkey->acpi_handle, &state); - if (result) { + error = acpi_bus_update_power(fujitsu_hotkey->acpi_handle, &state); + if (error) { pr_err("Error reading power state\n"); goto err_unregister_input_dev; } @@ -907,7 +906,7 @@ err_free_input_dev: err_free_fifo: kfifo_free(&fujitsu_hotkey->fifo); err_stop: - return result; + return error; } static int acpi_fujitsu_hotkey_remove(struct acpi_device *device) From 2845f4772386fdbfeac20bd04e8c17e0e5d823f4 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 10 Jan 2014 14:04:24 +0000 Subject: [PATCH 14/18] sony-laptop: remove unnecessary assigment of len The assignment of len = len is unnecessary, so remove it. Signed-off-by: Colin Ian King Signed-off-by: Matthew Garrett --- drivers/platform/x86/sony-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index fb233ae7bb0e..61fa755b7efb 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -791,7 +791,7 @@ static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value, void *buffer, size_t buflen) { int ret = 0; - size_t len = len; + size_t len; union acpi_object *object = __call_snc_method(handle, name, value); if (!object) From b0ad4ff35d479a46a3b995a299db9aeb097acfce Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 13 Jan 2014 12:32:44 +0100 Subject: [PATCH 15/18] hp_accel: Add a new PnP ID HPQ6007 for new HP laptops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DriveGuard chips on the new HP laptops are with a new PnP ID "HPQ6007". It should be compatible with older chips. Acked-by: Éric Piel Cc: Signed-off-by: Takashi Iwai Signed-off-by: Matthew Garrett --- drivers/platform/x86/hp_accel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c index 01b619eca38e..7c75777af8eb 100644 --- a/drivers/platform/x86/hp_accel.c +++ b/drivers/platform/x86/hp_accel.c @@ -77,6 +77,7 @@ static inline void delayed_sysfs_set(struct led_classdev *led_cdev, static struct acpi_device_id lis3lv02d_device_ids[] = { {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */ {"HPQ6000", 0}, /* HP Mobile Data Protection System PNP */ + {"HPQ6007", 0}, /* HP Mobile Data Protection System PNP */ {"", 0}, }; MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids); From fec278a1ddcb0607db3c5e47817c3017df71936d Mon Sep 17 00:00:00 2001 From: Unai Uribarri Date: Tue, 14 Jan 2014 11:06:47 +0100 Subject: [PATCH 16/18] toshiba_acpi: Support RFKILL hotkey scancode This scancode is used in new 2013 models like Satellite P75-A7200. Signed-off-by: Unai Uribarri Signed-off-by: Matthew Garrett --- drivers/platform/x86/toshiba_acpi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 7fce391818d3..5d23ca263f5c 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -151,6 +151,7 @@ static const struct acpi_device_id toshiba_device_ids[] = { MODULE_DEVICE_TABLE(acpi, toshiba_device_ids); static const struct key_entry toshiba_acpi_keymap[] = { + { KE_KEY, 0x9e, { KEY_RFKILL } }, { KE_KEY, 0x101, { KEY_MUTE } }, { KE_KEY, 0x102, { KEY_ZOOMOUT } }, { KE_KEY, 0x103, { KEY_ZOOMIN } }, From 54290fa6980747b1e83e2d3a576115046df54b04 Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Thu, 16 Jan 2014 17:50:31 +0800 Subject: [PATCH 17/18] hp-wireless: new driver for hp wireless button for Windows 8 Signed-off-by: Alex Hung Signed-off-by: Matthew Garrett --- drivers/platform/x86/Kconfig | 11 +++ drivers/platform/x86/Makefile | 1 + drivers/platform/x86/hp-wireless.c | 132 +++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 drivers/platform/x86/hp-wireless.c diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index a698b928327d..5ae65c11d544 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -197,6 +197,17 @@ config HP_ACCEL To compile this driver as a module, choose M here: the module will be called hp_accel. +config HP_WIRELESS + tristate "HP WIRELESS" + depends on ACPI + depends on INPUT + help + This driver provides supports for new HP wireless button for Windows 8. + On such systems the driver should load automatically (via ACPI alias). + + To compile this driver as a module, choose M here: the module will + be called hp-wireless. + config HP_WMI tristate "HP WMI extras" depends on ACPI_WMI diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 79bd3c49be3d..9b87cfc42b84 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o obj-$(CONFIG_ACER_WMI) += acer-wmi.o obj-$(CONFIG_ACERHDF) += acerhdf.o obj-$(CONFIG_HP_ACCEL) += hp_accel.o +obj-$(CONFIG_HP_WIRELESS) += hp-wireless.o obj-$(CONFIG_HP_WMI) += hp-wmi.o obj-$(CONFIG_AMILO_RFKILL) += amilo-rfkill.o obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o diff --git a/drivers/platform/x86/hp-wireless.c b/drivers/platform/x86/hp-wireless.c new file mode 100644 index 000000000000..415348fc1210 --- /dev/null +++ b/drivers/platform/x86/hp-wireless.c @@ -0,0 +1,132 @@ +/* + * hp-wireless button for Windows 8 + * + * Copyright (C) 2014 Alex Hung + * + * 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 +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Alex Hung"); +MODULE_ALIAS("acpi*:HPQ6001:*"); + +static struct input_dev *hpwl_input_dev; + +static const struct acpi_device_id hpwl_ids[] = { + {"HPQ6001", 0}, + {"", 0}, +}; + +static int hp_wireless_input_setup(void) +{ + int err; + + hpwl_input_dev = input_allocate_device(); + if (!hpwl_input_dev) + return -ENOMEM; + + hpwl_input_dev->name = "HP Wireless hotkeys"; + hpwl_input_dev->phys = "hpq6001/input0"; + hpwl_input_dev->id.bustype = BUS_HOST; + hpwl_input_dev->evbit[0] = BIT(EV_KEY); + set_bit(KEY_RFKILL, hpwl_input_dev->keybit); + + err = input_register_device(hpwl_input_dev); + if (err) + goto err_free_dev; + + return 0; + +err_free_dev: + input_free_device(hpwl_input_dev); + return err; +} + +static void hp_wireless_input_destroy(void) +{ + input_unregister_device(hpwl_input_dev); +} + +static void hpwl_notify(struct acpi_device *acpi_dev, u32 event) +{ + if (event != 0x80) { + pr_info("Received unknown event (0x%x)\n", event); + return; + } + + input_report_key(hpwl_input_dev, KEY_RFKILL, 1); + input_sync(hpwl_input_dev); + input_report_key(hpwl_input_dev, KEY_RFKILL, 0); + input_sync(hpwl_input_dev); +} + +static int hpwl_add(struct acpi_device *device) +{ + int err; + + err = hp_wireless_input_setup(); + return err; +} + +static int hpwl_remove(struct acpi_device *device) +{ + hp_wireless_input_destroy(); + return 0; +} + +static struct acpi_driver hpwl_driver = { + .name = "hp-wireless", + .owner = THIS_MODULE, + .ids = hpwl_ids, + .ops = { + .add = hpwl_add, + .remove = hpwl_remove, + .notify = hpwl_notify, + }, +}; + +static int __init hpwl_init(void) +{ + int err; + + pr_info("Initializing HPQ6001 module\n"); + err = acpi_bus_register_driver(&hpwl_driver); + if (err) { + pr_err("Unable to register HP wireless control driver.\n"); + goto error_acpi_register; + } + + return 0; + +error_acpi_register: + return err; +} + +static void __exit hpwl_exit(void) +{ + pr_info("Exiting HPQ6001 module\n"); + acpi_bus_unregister_driver(&hpwl_driver); +} + +module_init(hpwl_init); +module_exit(hpwl_exit); From b4b0b4a9e0392dbd00e5f033e1329ce61ed06fef Mon Sep 17 00:00:00 2001 From: David Cohen Date: Mon, 2 Dec 2013 16:20:01 -0800 Subject: [PATCH 18/18] ipc: add intel-mid's pci id macros For readability matters, this patch replaces the hardcoded pci ids by human readable macros. Signed-off-by: David Cohen Signed-off-by: Matthew Garrett --- drivers/platform/x86/intel_scu_ipc.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index 259969d31055..76ca094ed012 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c @@ -62,6 +62,11 @@ #define IPC_RWBUF_SIZE 20 /* IPC Read buffer Size */ #define IPC_IOC 0x100 /* IPC command register IOC bit */ +#define PCI_DEVICE_ID_LINCROFT 0x082a +#define PCI_DEVICE_ID_PENWELL 0x080e +#define PCI_DEVICE_ID_CLOVERVIEW 0x08ea +#define PCI_DEVICE_ID_TANGIER 0x11a0 + /* intel scu ipc driver data*/ struct intel_scu_ipc_pdata_t { u32 ipc_base; @@ -637,16 +642,16 @@ static void ipc_remove(struct pci_dev *pdev) static DEFINE_PCI_DEVICE_TABLE(pci_ids) = { { - PCI_VDEVICE(INTEL, 0x082a), + PCI_VDEVICE(INTEL, PCI_DEVICE_ID_LINCROFT), (kernel_ulong_t)&intel_scu_ipc_lincroft_pdata, }, { - PCI_VDEVICE(INTEL, 0x080e), + PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PENWELL), (kernel_ulong_t)&intel_scu_ipc_penwell_pdata, }, { - PCI_VDEVICE(INTEL, 0x08ea), + PCI_VDEVICE(INTEL, PCI_DEVICE_ID_CLOVERVIEW), (kernel_ulong_t)&intel_scu_ipc_penwell_pdata, }, { - PCI_VDEVICE(INTEL, 0x11a0), + PCI_VDEVICE(INTEL, PCI_DEVICE_ID_TANGIER), (kernel_ulong_t)&intel_scu_ipc_tangier_pdata, }, { 0,