From b1ca80e4a23b91fc90545919dda90a32ec558663 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 9 Feb 2018 11:53:40 +0000 Subject: [PATCH 01/41] platform/x86: GPD pocket fan: fix spelling mistake: "Mill-celcius" -> "millicelsius" Trivial fix to spelling mistake in MODULE_PARM_DESC text and remove unnecessary hyphen. Signed-off-by: Colin Ian King Signed-off-by: Andy Shevchenko --- drivers/platform/x86/gpd-pocket-fan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/gpd-pocket-fan.c b/drivers/platform/x86/gpd-pocket-fan.c index 2d645c505f81..be85ed966bf3 100644 --- a/drivers/platform/x86/gpd-pocket-fan.c +++ b/drivers/platform/x86/gpd-pocket-fan.c @@ -19,12 +19,12 @@ static int temp_limits[3] = { 55000, 60000, 65000 }; module_param_array(temp_limits, int, NULL, 0444); MODULE_PARM_DESC(temp_limits, - "Milli-celcius values above which the fan speed increases"); + "Millicelsius values above which the fan speed increases"); static int hysteresis = 3000; module_param(hysteresis, int, 0444); MODULE_PARM_DESC(hysteresis, - "Hysteresis in milli-celcius before lowering the fan speed"); + "Hysteresis in millicelsius before lowering the fan speed"); static int speed_on_ac = 2; module_param(speed_on_ac, int, 0444); From 04e4e888558ebe5d9701e31bba61d4e256ab71a8 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 12 Feb 2018 11:50:47 -0800 Subject: [PATCH 02/41] platform/x86: intel_turbo_max_3: Remove restriction for HWP platforms On systems supporting HWP (Hardware P-States) mode, we expected to enumerate core priority via ACPI-CPPC tables. Unfortunately deployment of TURBO 3.0 didn't use this method to show core priority. So users are not able to utilize this feature in HWP mode. So remove the loading restriction of this driver for HWP enabled systems. Even if there are some systems, which are providing the core priority via ACPI CPPC, this shouldn't cause any conflict as the source of priority definition is same. Signed-off-by: Srinivas Pandruvada Reported-and-tested-and-reviewed-by: Arjan van de Ven Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_turbo_max_3.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/platform/x86/intel_turbo_max_3.c b/drivers/platform/x86/intel_turbo_max_3.c index d4ea01805879..a6d5aa0c3c47 100644 --- a/drivers/platform/x86/intel_turbo_max_3.c +++ b/drivers/platform/x86/intel_turbo_max_3.c @@ -138,9 +138,6 @@ static int __init itmt_legacy_init(void) if (!id) return -ENODEV; - if (boot_cpu_has(X86_FEATURE_HWP)) - return -ENODEV; - ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "platform/x86/turbo_max_3:online", itmt_legacy_cpu_online, NULL); From 7f166addbebdcaeefe36997d5b8dceb96c5619fa Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 16 Feb 2018 17:40:24 +0200 Subject: [PATCH 03/41] platform/x86: wmi: Replace kmalloc + sprintf() with kasprintf() kasprintf() does the job of two: kmalloc() and sprintf(). Replace two calls with one. Reviewed-by: Darren Hart (VMware) Signed-off-by: Andy Shevchenko --- drivers/platform/x86/wmi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index c0c8945603cb..4e76ffcb5394 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -933,12 +933,11 @@ static int wmi_dev_probe(struct device *dev) goto probe_failure; } - buf = kmalloc(strlen(wdriver->driver.name) + 5, GFP_KERNEL); + buf = kasprintf(GFP_KERNEL, "wmi/%s", wdriver->driver.name); if (!buf) { ret = -ENOMEM; goto probe_string_failure; } - sprintf(buf, "wmi/%s", wdriver->driver.name); wblock->char_dev.minor = MISC_DYNAMIC_MINOR; wblock->char_dev.name = buf; wblock->char_dev.fops = &wmi_fops; From cedb3b2a7d7cb059b3646db14dfe2f833bf4d52d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 19 Feb 2018 17:02:28 +0200 Subject: [PATCH 04/41] platform/x86: wmi: Replace list_for_each() by list_for_each_entry() In all cases list_for_each() followed by list_entry(), so, replace them by list_for_each_entry() macro. Signed-off-by: Andy Shevchenko Reviewed-by: Darren Hart (VMware) --- drivers/platform/x86/wmi.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 4e76ffcb5394..f90ba83359f5 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -130,13 +130,11 @@ static bool find_guid(const char *guid_string, struct wmi_block **out) uuid_le guid_input; struct wmi_block *wblock; struct guid_block *block; - struct list_head *p; if (uuid_le_to_bin(guid_string, &guid_input)) return false; - list_for_each(p, &wmi_block_list) { - wblock = list_entry(p, struct wmi_block, list); + list_for_each_entry(wblock, &wmi_block_list, list) { block = &wblock->gblock; if (memcmp(block->guid, &guid_input, 16) == 0) { @@ -519,7 +517,6 @@ wmi_notify_handler handler, void *data) struct wmi_block *block; acpi_status status = AE_NOT_EXIST; uuid_le guid_input; - struct list_head *p; if (!guid || !handler) return AE_BAD_PARAMETER; @@ -527,9 +524,8 @@ wmi_notify_handler handler, void *data) if (uuid_le_to_bin(guid, &guid_input)) return AE_BAD_PARAMETER; - list_for_each(p, &wmi_block_list) { + list_for_each_entry(block, &wmi_block_list, list) { acpi_status wmi_status; - block = list_entry(p, struct wmi_block, list); if (memcmp(block->gblock.guid, &guid_input, 16) == 0) { if (block->handler && @@ -560,7 +556,6 @@ acpi_status wmi_remove_notify_handler(const char *guid) struct wmi_block *block; acpi_status status = AE_NOT_EXIST; uuid_le guid_input; - struct list_head *p; if (!guid) return AE_BAD_PARAMETER; @@ -568,9 +563,8 @@ acpi_status wmi_remove_notify_handler(const char *guid) if (uuid_le_to_bin(guid, &guid_input)) return AE_BAD_PARAMETER; - list_for_each(p, &wmi_block_list) { + list_for_each_entry(block, &wmi_block_list, list) { acpi_status wmi_status; - block = list_entry(p, struct wmi_block, list); if (memcmp(block->gblock.guid, &guid_input, 16) == 0) { if (!block->handler || @@ -610,15 +604,13 @@ acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out) union acpi_object params[1]; struct guid_block *gblock; struct wmi_block *wblock; - struct list_head *p; input.count = 1; input.pointer = params; params[0].type = ACPI_TYPE_INTEGER; params[0].integer.value = event; - list_for_each(p, &wmi_block_list) { - wblock = list_entry(p, struct wmi_block, list); + list_for_each_entry(wblock, &wmi_block_list, list) { gblock = &wblock->gblock; if ((gblock->flags & ACPI_WMI_EVENT) && @@ -1260,11 +1252,9 @@ static void acpi_wmi_notify_handler(acpi_handle handle, u32 event, { struct guid_block *block; struct wmi_block *wblock; - struct list_head *p; bool found_it = false; - list_for_each(p, &wmi_block_list) { - wblock = list_entry(p, struct wmi_block, list); + list_for_each_entry(wblock, &wmi_block_list, list) { block = &wblock->gblock; if (wblock->acpi_device->handle == handle && From 82acad40ca97f309ff066864ae63cbe68812f983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Dou=C3=A9zan-Grard?= Date: Wed, 21 Feb 2018 18:00:06 +0100 Subject: [PATCH 05/41] platform/x86: topstar-laptop: revert "convert to module_acpi_driver()" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Revert commit 15165594da65 ("topstar-laptop: convert to module_acpi_driver()") to later add a platform device. Signed-off-by: Guillaume Douézan-Grard Signed-off-by: Andy Shevchenko --- drivers/platform/x86/topstar-laptop.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c index 1032c00b907b..b4807b868a69 100644 --- a/drivers/platform/x86/topstar-laptop.c +++ b/drivers/platform/x86/topstar-laptop.c @@ -178,7 +178,27 @@ static struct acpi_driver acpi_topstar_driver = { .notify = acpi_topstar_notify, }, }; -module_acpi_driver(acpi_topstar_driver); + +static int __init topstar_laptop_init(void) +{ + int ret; + + ret = acpi_bus_register_driver(&acpi_topstar_driver); + if (ret < 0) + return ret; + + pr_info("ACPI extras driver loaded\n"); + + return 0; +} + +static void __exit topstar_laptop_exit(void) +{ + acpi_bus_unregister_driver(&acpi_topstar_driver); +} + +module_init(topstar_laptop_init); +module_exit(topstar_laptop_exit); MODULE_AUTHOR("Herton Ronaldo Krzesinski"); MODULE_DESCRIPTION("Topstar Laptop ACPI Extras driver"); From 66aa0d606b5025409bf71a23b5ae683346f1795a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Dou=C3=A9zan-Grard?= Date: Wed, 21 Feb 2018 18:00:16 +0100 Subject: [PATCH 06/41] platform/x86: topstar-laptop: use consistent naming scheme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * use module prefix naming scheme for functions and programming constructs, * consistent label names Signed-off-by: Guillaume Douézan-Grard Signed-off-by: Andy Shevchenko --- drivers/platform/x86/topstar-laptop.c | 82 +++++++++++++-------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c index b4807b868a69..17f22a085d9a 100644 --- a/drivers/platform/x86/topstar-laptop.c +++ b/drivers/platform/x86/topstar-laptop.c @@ -21,10 +21,10 @@ #include #include -#define ACPI_TOPSTAR_CLASS "topstar" +#define TOPSTAR_LAPTOP_CLASS "topstar" -struct topstar_hkey { - struct input_dev *inputdev; +struct topstar_laptop { + struct input_dev *input; }; static const struct key_entry topstar_keymap[] = { @@ -57,11 +57,11 @@ static const struct key_entry topstar_keymap[] = { { KE_END, 0 } }; -static void acpi_topstar_notify(struct acpi_device *device, u32 event) +static void topstar_acpi_notify(struct acpi_device *device, u32 event) { static bool dup_evnt[2]; bool *dup; - struct topstar_hkey *hkey = acpi_driver_data(device); + struct topstar_laptop *topstar = acpi_driver_data(device); /* 0x83 and 0x84 key events comes duplicated... */ if (event == 0x83 || event == 0x84) { @@ -73,11 +73,11 @@ static void acpi_topstar_notify(struct acpi_device *device, u32 event) *dup = true; } - if (!sparse_keymap_report_event(hkey->inputdev, event, 1, true)) + if (!sparse_keymap_report_event(topstar->input, event, 1, true)) pr_info("unknown event = 0x%02x\n", event); } -static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state) +static int topstar_acpi_fncx_switch(struct acpi_device *device, bool state) { acpi_status status; @@ -91,72 +91,72 @@ static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state) return 0; } -static int acpi_topstar_init_hkey(struct topstar_hkey *hkey) +static int topstar_input_init(struct topstar_laptop *topstar) { struct input_dev *input; - int error; + int err; input = input_allocate_device(); if (!input) return -ENOMEM; input->name = "Topstar Laptop extra buttons"; - input->phys = "topstar/input0"; + input->phys = TOPSTAR_LAPTOP_CLASS "/input0"; input->id.bustype = BUS_HOST; - error = sparse_keymap_setup(input, topstar_keymap, NULL); - if (error) { + err = sparse_keymap_setup(input, topstar_keymap, NULL); + if (err) { pr_err("Unable to setup input device keymap\n"); goto err_free_dev; } - error = input_register_device(input); - if (error) { + err = input_register_device(input); + if (err) { pr_err("Unable to register input device\n"); goto err_free_dev; } - hkey->inputdev = input; + topstar->input = input; return 0; - err_free_dev: +err_free_dev: input_free_device(input); - return error; + return err; } -static int acpi_topstar_add(struct acpi_device *device) +static int topstar_acpi_add(struct acpi_device *device) { - struct topstar_hkey *tps_hkey; + struct topstar_laptop *topstar; - tps_hkey = kzalloc(sizeof(struct topstar_hkey), GFP_KERNEL); - if (!tps_hkey) + topstar = kzalloc(sizeof(struct topstar_laptop), GFP_KERNEL); + if (!topstar) return -ENOMEM; strcpy(acpi_device_name(device), "Topstar TPSACPI"); - strcpy(acpi_device_class(device), ACPI_TOPSTAR_CLASS); + strcpy(acpi_device_class(device), TOPSTAR_LAPTOP_CLASS); - if (acpi_topstar_fncx_switch(device, true)) - goto add_err; + if (topstar_acpi_fncx_switch(device, true)) + goto err_free; - if (acpi_topstar_init_hkey(tps_hkey)) - goto add_err; + if (topstar_input_init(topstar)) + goto err_free; - device->driver_data = tps_hkey; + device->driver_data = topstar; return 0; -add_err: - kfree(tps_hkey); +err_free: + kfree(topstar); return -ENODEV; } -static int acpi_topstar_remove(struct acpi_device *device) +static int topstar_acpi_remove(struct acpi_device *device) { - struct topstar_hkey *tps_hkey = acpi_driver_data(device); + struct topstar_laptop *topstar = acpi_driver_data(device); - acpi_topstar_fncx_switch(device, false); + topstar_acpi_fncx_switch(device, false); - input_unregister_device(tps_hkey->inputdev); - kfree(tps_hkey); + input_unregister_device(topstar->input); + kfree(topstar); return 0; } @@ -168,14 +168,14 @@ static const struct acpi_device_id topstar_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, topstar_device_ids); -static struct acpi_driver acpi_topstar_driver = { +static struct acpi_driver topstar_acpi_driver = { .name = "Topstar laptop ACPI driver", - .class = ACPI_TOPSTAR_CLASS, + .class = TOPSTAR_LAPTOP_CLASS, .ids = topstar_device_ids, .ops = { - .add = acpi_topstar_add, - .remove = acpi_topstar_remove, - .notify = acpi_topstar_notify, + .add = topstar_acpi_add, + .remove = topstar_acpi_remove, + .notify = topstar_acpi_notify, }, }; @@ -183,7 +183,7 @@ static int __init topstar_laptop_init(void) { int ret; - ret = acpi_bus_register_driver(&acpi_topstar_driver); + ret = acpi_bus_register_driver(&topstar_acpi_driver); if (ret < 0) return ret; @@ -194,7 +194,7 @@ static int __init topstar_laptop_init(void) static void __exit topstar_laptop_exit(void) { - acpi_bus_unregister_driver(&acpi_topstar_driver); + acpi_bus_unregister_driver(&topstar_acpi_driver); } module_init(topstar_laptop_init); From 3093ced23640fdeabacbcb691c97af207fdb5a6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Dou=C3=A9zan-Grard?= Date: Wed, 21 Feb 2018 18:00:26 +0100 Subject: [PATCH 07/41] platform/x86: topstar-laptop: split ACPI events and input handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * get the `acpi_device` from the `topstar_laptop` struct, * split input registering and `sparse_keymap` events from ACPI events handling, * use notify, init and exit functions for ACPI and input handling Signed-off-by: Guillaume Douézan-Grard Signed-off-by: Andy Shevchenko --- drivers/platform/x86/topstar-laptop.c | 115 +++++++++++++++++--------- 1 file changed, 74 insertions(+), 41 deletions(-) diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c index 17f22a085d9a..fbf020e8a0e1 100644 --- a/drivers/platform/x86/topstar-laptop.c +++ b/drivers/platform/x86/topstar-laptop.c @@ -24,9 +24,14 @@ #define TOPSTAR_LAPTOP_CLASS "topstar" struct topstar_laptop { + struct acpi_device *device; struct input_dev *input; }; +/* + * Input + */ + static const struct key_entry topstar_keymap[] = { { KE_KEY, 0x80, { KEY_BRIGHTNESSUP } }, { KE_KEY, 0x81, { KEY_BRIGHTNESSDOWN } }, @@ -57,40 +62,12 @@ static const struct key_entry topstar_keymap[] = { { KE_END, 0 } }; -static void topstar_acpi_notify(struct acpi_device *device, u32 event) +static void topstar_input_notify(struct topstar_laptop *topstar, int event) { - static bool dup_evnt[2]; - bool *dup; - struct topstar_laptop *topstar = acpi_driver_data(device); - - /* 0x83 and 0x84 key events comes duplicated... */ - if (event == 0x83 || event == 0x84) { - dup = &dup_evnt[event - 0x83]; - if (*dup) { - *dup = false; - return; - } - *dup = true; - } - if (!sparse_keymap_report_event(topstar->input, event, 1, true)) pr_info("unknown event = 0x%02x\n", event); } -static int topstar_acpi_fncx_switch(struct acpi_device *device, bool state) -{ - acpi_status status; - - status = acpi_execute_simple_method(device->handle, "FNCX", - state ? 0x86 : 0x87); - if (ACPI_FAILURE(status)) { - pr_err("Unable to switch FNCX notifications\n"); - return -ENODEV; - } - - return 0; -} - static int topstar_input_init(struct topstar_laptop *topstar) { struct input_dev *input; @@ -124,9 +101,62 @@ err_free_dev: return err; } +static void topstar_input_exit(struct topstar_laptop *topstar) +{ + input_unregister_device(topstar->input); +} + +/* + * ACPI + */ + +static int topstar_acpi_fncx_switch(struct acpi_device *device, bool state) +{ + acpi_status status; + u64 arg = state ? 0x86 : 0x87; + + status = acpi_execute_simple_method(device->handle, "FNCX", arg); + if (ACPI_FAILURE(status)) { + pr_err("Unable to switch FNCX notifications\n"); + return -ENODEV; + } + + return 0; +} + +static void topstar_acpi_notify(struct acpi_device *device, u32 event) +{ + struct topstar_laptop *topstar = acpi_driver_data(device); + static bool dup_evnt[2]; + bool *dup; + + /* 0x83 and 0x84 key events comes duplicated... */ + if (event == 0x83 || event == 0x84) { + dup = &dup_evnt[event - 0x83]; + if (*dup) { + *dup = false; + return; + } + *dup = true; + } + + topstar_input_notify(topstar, event); +} + +static int topstar_acpi_init(struct topstar_laptop *topstar) +{ + return topstar_acpi_fncx_switch(topstar->device, true); +} + +static void topstar_acpi_exit(struct topstar_laptop *topstar) +{ + topstar_acpi_fncx_switch(topstar->device, false); +} + static int topstar_acpi_add(struct acpi_device *device) { struct topstar_laptop *topstar; + int err; topstar = kzalloc(sizeof(struct topstar_laptop), GFP_KERNEL); if (!topstar) @@ -134,30 +164,34 @@ static int topstar_acpi_add(struct acpi_device *device) strcpy(acpi_device_name(device), "Topstar TPSACPI"); strcpy(acpi_device_class(device), TOPSTAR_LAPTOP_CLASS); - - if (topstar_acpi_fncx_switch(device, true)) - goto err_free; - - if (topstar_input_init(topstar)) - goto err_free; - device->driver_data = topstar; + topstar->device = device; + + err = topstar_acpi_init(topstar); + if (err) + goto err_free; + + err = topstar_input_init(topstar); + if (err) + goto err_acpi_exit; + return 0; +err_acpi_exit: + topstar_acpi_exit(topstar); err_free: kfree(topstar); - return -ENODEV; + return err; } static int topstar_acpi_remove(struct acpi_device *device) { struct topstar_laptop *topstar = acpi_driver_data(device); - topstar_acpi_fncx_switch(device, false); + topstar_input_exit(topstar); + topstar_acpi_exit(topstar); - input_unregister_device(topstar->input); kfree(topstar); - return 0; } @@ -188,7 +222,6 @@ static int __init topstar_laptop_init(void) return ret; pr_info("ACPI extras driver loaded\n"); - return 0; } From 2c531437dd446306999528a122b14d7ef2acd768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Dou=C3=A9zan-Grard?= Date: Wed, 21 Feb 2018 18:00:35 +0100 Subject: [PATCH 08/41] platform/x86: topstar-laptop: add platform device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add a platform device to support further addition of a led subsystem, * register the existing input device to this platform device. Signed-off-by: Guillaume Douézan-Grard Signed-off-by: Andy Shevchenko --- drivers/platform/x86/topstar-laptop.c | 61 +++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c index fbf020e8a0e1..e82f57e893c8 100644 --- a/drivers/platform/x86/topstar-laptop.c +++ b/drivers/platform/x86/topstar-laptop.c @@ -1,5 +1,5 @@ /* - * ACPI driver for Topstar notebooks (hotkeys support only) + * Topstar Laptop ACPI Extras driver * * Copyright (c) 2009 Herton Ronaldo Krzesinski * @@ -20,11 +20,13 @@ #include #include #include +#include #define TOPSTAR_LAPTOP_CLASS "topstar" struct topstar_laptop { struct acpi_device *device; + struct platform_device *platform; struct input_dev *input; }; @@ -80,6 +82,7 @@ static int topstar_input_init(struct topstar_laptop *topstar) input->name = "Topstar Laptop extra buttons"; input->phys = TOPSTAR_LAPTOP_CLASS "/input0"; input->id.bustype = BUS_HOST; + input->dev.parent = &topstar->platform->dev; err = sparse_keymap_setup(input, topstar_keymap, NULL); if (err) { @@ -106,6 +109,42 @@ static void topstar_input_exit(struct topstar_laptop *topstar) input_unregister_device(topstar->input); } +/* + * Platform + */ + +static struct platform_driver topstar_platform_driver = { + .driver = { + .name = TOPSTAR_LAPTOP_CLASS, + }, +}; + +static int topstar_platform_init(struct topstar_laptop *topstar) +{ + int err; + + topstar->platform = platform_device_alloc(TOPSTAR_LAPTOP_CLASS, -1); + if (!topstar->platform) + return -ENOMEM; + + platform_set_drvdata(topstar->platform, topstar); + + err = platform_device_add(topstar->platform); + if (err) + goto err_device_put; + + return 0; + +err_device_put: + platform_device_put(topstar->platform); + return err; +} + +static void topstar_platform_exit(struct topstar_laptop *topstar) +{ + platform_device_unregister(topstar->platform); +} + /* * ACPI */ @@ -171,12 +210,18 @@ static int topstar_acpi_add(struct acpi_device *device) if (err) goto err_free; - err = topstar_input_init(topstar); + err = topstar_platform_init(topstar); if (err) goto err_acpi_exit; + err = topstar_input_init(topstar); + if (err) + goto err_platform_exit; + return 0; +err_platform_exit: + topstar_platform_exit(topstar); err_acpi_exit: topstar_acpi_exit(topstar); err_free: @@ -189,6 +234,7 @@ static int topstar_acpi_remove(struct acpi_device *device) struct topstar_laptop *topstar = acpi_driver_data(device); topstar_input_exit(topstar); + topstar_platform_exit(topstar); topstar_acpi_exit(topstar); kfree(topstar); @@ -217,17 +263,26 @@ static int __init topstar_laptop_init(void) { int ret; - ret = acpi_bus_register_driver(&topstar_acpi_driver); + ret = platform_driver_register(&topstar_platform_driver); if (ret < 0) return ret; + ret = acpi_bus_register_driver(&topstar_acpi_driver); + if (ret < 0) + goto err_driver_unreg; + pr_info("ACPI extras driver loaded\n"); return 0; + +err_driver_unreg: + platform_driver_unregister(&topstar_platform_driver); + return ret; } static void __exit topstar_laptop_exit(void) { acpi_bus_unregister_driver(&topstar_acpi_driver); + platform_driver_unregister(&topstar_platform_driver); } module_init(topstar_laptop_init); From bf8f65da31ca46ae41ba7d932d9f9849d1781b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Dou=C3=A9zan-Grard?= Date: Wed, 21 Feb 2018 18:00:45 +0100 Subject: [PATCH 09/41] platform/x86: topstar-laptop: add Topstar U931/RVP7 WLAN LED workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Topstar U931 laptops provide a LED synced with the WLAN adapter hard-blocking state. Unfortunately, some models seem to be defective, making impossible to hard-block the adapter with the WLAN switch and thus the LED is useless. An ACPI method is available to programmatically control this switch and it indirectly allows to control the LED. This commit registers the LED within the corresponding subsystem, making possible for instance to use an rfkill-based trigger to synchronize the LED with the device state. This workaround is enabled automatically for Topstar U931/RVP7 laptops based on a DMI check. Signed-off-by: Guillaume Douézan-Grard Signed-off-by: Andy Shevchenko --- drivers/platform/x86/Kconfig | 2 + drivers/platform/x86/topstar-laptop.c | 108 ++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 9a8f96465cdc..bc66a31757db 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -742,6 +742,8 @@ config TOPSTAR_LAPTOP depends on ACPI depends on INPUT select INPUT_SPARSEKMAP + select LEDS_CLASS + select NEW_LEDS ---help--- This driver adds support for hotkeys found on Topstar laptops. diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c index e82f57e893c8..30a6c5cbc58f 100644 --- a/drivers/platform/x86/topstar-laptop.c +++ b/drivers/platform/x86/topstar-laptop.c @@ -18,8 +18,10 @@ #include #include #include +#include #include #include +#include #include #define TOPSTAR_LAPTOP_CLASS "topstar" @@ -28,8 +30,77 @@ struct topstar_laptop { struct acpi_device *device; struct platform_device *platform; struct input_dev *input; + struct led_classdev led; }; +/* + * LED + */ + +static enum led_brightness topstar_led_get(struct led_classdev *led) +{ + return led->brightness; +} + +static int topstar_led_set(struct led_classdev *led, + enum led_brightness state) +{ + struct topstar_laptop *topstar = container_of(led, + struct topstar_laptop, led); + + struct acpi_object_list params; + union acpi_object in_obj; + unsigned long long int ret; + acpi_status status; + + params.count = 1; + params.pointer = &in_obj; + in_obj.type = ACPI_TYPE_INTEGER; + in_obj.integer.value = 0x83; + + /* + * Topstar ACPI returns 0x30001 when the LED is ON and 0x30000 when it + * is OFF. + */ + status = acpi_evaluate_integer(topstar->device->handle, + "GETX", ¶ms, &ret); + if (ACPI_FAILURE(status)) + return -1; + + /* + * FNCX(0x83) toggles the LED (more precisely, it is supposed to + * act as an hardware switch and disconnect the WLAN adapter but + * it seems to be faulty on some models like the Topstar U931 + * Notebook). + */ + if ((ret == 0x30001 && state == LED_OFF) + || (ret == 0x30000 && state != LED_OFF)) { + status = acpi_execute_simple_method(topstar->device->handle, + "FNCX", 0x83); + if (ACPI_FAILURE(status)) + return -1; + } + + return 0; +} + +static int topstar_led_init(struct topstar_laptop *topstar) +{ + topstar->led = (struct led_classdev) { + .default_trigger = "rfkill0", + .brightness_get = topstar_led_get, + .brightness_set_blocking = topstar_led_set, + .name = TOPSTAR_LAPTOP_CLASS "::wlan", + }; + + return led_classdev_register(&topstar->platform->dev, &topstar->led); +} + +static void topstar_led_exit(struct topstar_laptop *topstar) +{ + led_classdev_unregister(&topstar->led); +} + /* * Input */ @@ -192,11 +263,37 @@ static void topstar_acpi_exit(struct topstar_laptop *topstar) topstar_acpi_fncx_switch(topstar->device, false); } +/* + * Enable software-based WLAN LED control on systems with defective + * hardware switch. + */ +static bool led_workaround; + +static int dmi_led_workaround(const struct dmi_system_id *id) +{ + led_workaround = true; + return 0; +} + +static const struct dmi_system_id topstar_dmi_ids[] = { + { + .callback = dmi_led_workaround, + .ident = "Topstar U931/RVP7", + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "U931"), + DMI_MATCH(DMI_BOARD_VERSION, "RVP7"), + }, + }, + {} +}; + static int topstar_acpi_add(struct acpi_device *device) { struct topstar_laptop *topstar; int err; + dmi_check_system(topstar_dmi_ids); + topstar = kzalloc(sizeof(struct topstar_laptop), GFP_KERNEL); if (!topstar) return -ENOMEM; @@ -218,8 +315,16 @@ static int topstar_acpi_add(struct acpi_device *device) if (err) goto err_platform_exit; + if (led_workaround) { + err = topstar_led_init(topstar); + if (err) + goto err_input_exit; + } + return 0; +err_input_exit: + topstar_input_exit(topstar); err_platform_exit: topstar_platform_exit(topstar); err_acpi_exit: @@ -233,6 +338,9 @@ static int topstar_acpi_remove(struct acpi_device *device) { struct topstar_laptop *topstar = acpi_driver_data(device); + if (led_workaround) + topstar_led_exit(topstar); + topstar_input_exit(topstar); topstar_platform_exit(topstar); topstar_acpi_exit(topstar); From 7a580200d69fa19809335f950c08e77528b7abe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Dou=C3=A9zan-Grard?= Date: Wed, 21 Feb 2018 18:00:54 +0100 Subject: [PATCH 10/41] platform/x86: topstar-laptop: update copyright and fix some comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add myself as an author of the driver. Signed-off-by: Guillaume Douézan-Grard Signed-off-by: Andy Shevchenko --- drivers/platform/x86/topstar-laptop.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c index 30a6c5cbc58f..294729c98267 100644 --- a/drivers/platform/x86/topstar-laptop.c +++ b/drivers/platform/x86/topstar-laptop.c @@ -2,9 +2,10 @@ * Topstar Laptop ACPI Extras driver * * Copyright (c) 2009 Herton Ronaldo Krzesinski + * Copyright (c) 2018 Guillaume Douézan-Grard * * Implementation inspired by existing x86 platform drivers, in special - * asus/eepc/fujitsu-laptop, thanks to their authors + * asus/eepc/fujitsu-laptop, thanks to their authors. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -397,5 +398,6 @@ module_init(topstar_laptop_init); module_exit(topstar_laptop_exit); MODULE_AUTHOR("Herton Ronaldo Krzesinski"); +MODULE_AUTHOR("Guillaume Douézan-Grard"); MODULE_DESCRIPTION("Topstar Laptop ACPI Extras driver"); MODULE_LICENSE("GPL"); From 1019b9371247eff2b3349a065b7e5e7b0ab10b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Dou=C3=A9zan-Grard?= Date: Wed, 21 Feb 2018 18:01:04 +0100 Subject: [PATCH 11/41] platform/x86: topstar-laptop: replace licence text with SPDX tag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace verbatim GPLv2 license copy with SPDX identifier. Signed-off-by: Guillaume Douézan-Grard Signed-off-by: Andy Shevchenko --- drivers/platform/x86/topstar-laptop.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c index 294729c98267..f7761d98c0fd 100644 --- a/drivers/platform/x86/topstar-laptop.c +++ b/drivers/platform/x86/topstar-laptop.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Topstar Laptop ACPI Extras driver * @@ -6,10 +7,6 @@ * * Implementation inspired by existing x86 platform drivers, in special * asus/eepc/fujitsu-laptop, thanks to their authors. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt From 5488bfdf9f1929347fdf9ba391be4513f9f7c56f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 22 Feb 2018 11:18:38 +0100 Subject: [PATCH 12/41] platform/x86: silead_dmi: Add DMI match for the I.T.Works TW701 tablet The I.T.Works TW701 7" tablet is a differently branded version of the same generic 7" Windows tablet as the Trekstor ST70416-6. Add a DMI match-table entry for it pointing to the Trekstor's touchscreen info. Signed-off-by: Hans de Goede Signed-off-by: Andy Shevchenko --- drivers/platform/x86/silead_dmi.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/platform/x86/silead_dmi.c b/drivers/platform/x86/silead_dmi.c index 3a624090191d..1091539fa230 100644 --- a/drivers/platform/x86/silead_dmi.c +++ b/drivers/platform/x86/silead_dmi.c @@ -446,6 +446,15 @@ static const struct dmi_system_id silead_ts_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "X3 Plus"), }, }, + { + /* I.T.Works TW701 */ + .driver_data = (void *)&surftab_wintron70_st70416_6_data, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), + DMI_MATCH(DMI_PRODUCT_NAME, "i71c"), + DMI_MATCH(DMI_BIOS_VERSION, "itWORKS.G.WI71C.JGBMRB"), + }, + }, { }, }; From 14966e0277d48e6c4cfa5af06e77831b10b9f8ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Sun, 11 Feb 2018 22:07:21 +0100 Subject: [PATCH 13/41] platform/x86: fujitsu-laptop: Unify local variable naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Different functions in the module use varying names (error, result, status) for a local variable storing the return value of a function call that has to be checked for errors. Use a common name (ret) for all these local variables to improve code consistency. Merge integer variable declarations in acpi_fujitsu_laptop_add() into one line. Signed-off-by: Michał Kępień Reviewed-by: Jonathan Woithe Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/fujitsu-laptop.c | 85 +++++++++++++-------------- 1 file changed, 41 insertions(+), 44 deletions(-) diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 2cfbd3fa5136..b5f782807bfa 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -385,7 +385,7 @@ static int fujitsu_backlight_register(struct acpi_device *device) static int acpi_fujitsu_bl_add(struct acpi_device *device) { struct fujitsu_bl *priv; - int error; + int ret; if (acpi_video_get_backlight_type() != acpi_backlight_vendor) return -ENODEV; @@ -399,9 +399,9 @@ static int acpi_fujitsu_bl_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_FUJITSU_CLASS); device->driver_data = priv; - error = acpi_fujitsu_bl_input_setup(device); - if (error) - return error; + ret = acpi_fujitsu_bl_input_setup(device); + if (ret) + return ret; pr_info("ACPI: %s [%s]\n", acpi_device_name(device), acpi_device_bid(device)); @@ -410,9 +410,9 @@ static int acpi_fujitsu_bl_add(struct acpi_device *device) priv->max_brightness = FUJITSU_LCD_N_LEVELS; get_lcd_level(device); - error = fujitsu_backlight_register(device); - if (error) - return error; + ret = fujitsu_backlight_register(device); + if (ret) + return ret; return 0; } @@ -693,7 +693,7 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device) { struct fujitsu_laptop *priv = acpi_driver_data(device); struct led_classdev *led; - int result; + int ret; if (call_fext_func(device, FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) { @@ -704,9 +704,9 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device) led->name = "fujitsu::logolamp"; led->brightness_set_blocking = logolamp_set; led->brightness_get = logolamp_get; - result = devm_led_classdev_register(&device->dev, led); - if (result) - return result; + ret = devm_led_classdev_register(&device->dev, led); + if (ret) + return ret; } if ((call_fext_func(device, @@ -719,9 +719,9 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device) led->name = "fujitsu::kblamps"; led->brightness_set_blocking = kblamps_set; led->brightness_get = kblamps_get; - result = devm_led_classdev_register(&device->dev, led); - if (result) - return result; + ret = devm_led_classdev_register(&device->dev, led); + if (ret) + return ret; } /* @@ -742,9 +742,9 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device) led->brightness_set_blocking = radio_led_set; led->brightness_get = radio_led_get; led->default_trigger = "rfkill-any"; - result = devm_led_classdev_register(&device->dev, led); - if (result) - return result; + ret = devm_led_classdev_register(&device->dev, led); + if (ret) + return ret; } /* Support for eco led is not always signaled in bit corresponding @@ -762,9 +762,9 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device) led->name = "fujitsu::eco_led"; led->brightness_set_blocking = eco_led_set; led->brightness_get = eco_led_get; - result = devm_led_classdev_register(&device->dev, led); - if (result) - return result; + ret = devm_led_classdev_register(&device->dev, led); + if (ret) + return ret; } return 0; @@ -773,8 +773,7 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device) static int acpi_fujitsu_laptop_add(struct acpi_device *device) { struct fujitsu_laptop *priv; - int error; - int i; + int ret, i = 0; priv = devm_kzalloc(&device->dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -789,23 +788,22 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device) /* kfifo */ spin_lock_init(&priv->fifo_lock); - error = kfifo_alloc(&priv->fifo, RINGBUFFERSIZE * sizeof(int), - GFP_KERNEL); - if (error) { + ret = kfifo_alloc(&priv->fifo, RINGBUFFERSIZE * sizeof(int), + GFP_KERNEL); + if (ret) { pr_err("kfifo_alloc failed\n"); goto err_stop; } - error = acpi_fujitsu_laptop_input_setup(device); - if (error) + ret = acpi_fujitsu_laptop_input_setup(device); + if (ret) goto err_free_fifo; pr_info("ACPI: %s [%s]\n", acpi_device_name(device), acpi_device_bid(device)); - i = 0; - while (call_fext_func(device, FUNC_BUTTONS, 0x1, 0x0, 0x0) != 0 - && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) + while (call_fext_func(device, FUNC_BUTTONS, 0x1, 0x0, 0x0) != 0 && + i++ < MAX_HOTKEY_RINGBUFFER_SIZE) ; /* No action, result is discarded */ acpi_handle_debug(device->handle, "Discarded %i ringbuffer entries\n", i); @@ -835,12 +833,12 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device) fujitsu_bl->bl_device->props.power = FB_BLANK_UNBLANK; } - error = acpi_fujitsu_laptop_leds_register(device); - if (error) + ret = acpi_fujitsu_laptop_leds_register(device); + if (ret) goto err_free_fifo; - error = fujitsu_laptop_platform_add(device); - if (error) + ret = fujitsu_laptop_platform_add(device); + if (ret) goto err_free_fifo; return 0; @@ -848,7 +846,7 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device) err_free_fifo: kfifo_free(&priv->fifo); err_stop: - return error; + return ret; } static int acpi_fujitsu_laptop_remove(struct acpi_device *device) @@ -865,11 +863,11 @@ static int acpi_fujitsu_laptop_remove(struct acpi_device *device) static void acpi_fujitsu_laptop_press(struct acpi_device *device, int scancode) { struct fujitsu_laptop *priv = acpi_driver_data(device); - int status; + int ret; - status = kfifo_in_locked(&priv->fifo, (unsigned char *)&scancode, - sizeof(scancode), &priv->fifo_lock); - if (status != sizeof(scancode)) { + ret = kfifo_in_locked(&priv->fifo, (unsigned char *)&scancode, + sizeof(scancode), &priv->fifo_lock); + if (ret != sizeof(scancode)) { dev_info(&priv->input->dev, "Could not push scancode [0x%x]\n", scancode); return; @@ -882,13 +880,12 @@ static void acpi_fujitsu_laptop_press(struct acpi_device *device, int scancode) static void acpi_fujitsu_laptop_release(struct acpi_device *device) { struct fujitsu_laptop *priv = acpi_driver_data(device); - int scancode, status; + int scancode, ret; while (true) { - status = kfifo_out_locked(&priv->fifo, - (unsigned char *)&scancode, - sizeof(scancode), &priv->fifo_lock); - if (status != sizeof(scancode)) + ret = kfifo_out_locked(&priv->fifo, (unsigned char *)&scancode, + sizeof(scancode), &priv->fifo_lock); + if (ret != sizeof(scancode)) return; sparse_keymap_report_event(priv->input, scancode, 0, false); dev_dbg(&priv->input->dev, From a7a1ccbee3b61bdb044d3bbee958a3082cf8f9f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Sun, 11 Feb 2018 22:07:22 +0100 Subject: [PATCH 14/41] platform/x86: fujitsu-laptop: Defer input device registration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only register input devices after the device-specific data structures they access are fully initialized. Signed-off-by: Michał Kępień Reviewed-by: Jonathan Woithe Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/fujitsu-laptop.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index b5f782807bfa..7f30a427a16c 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -399,10 +399,6 @@ static int acpi_fujitsu_bl_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_FUJITSU_CLASS); device->driver_data = priv; - ret = acpi_fujitsu_bl_input_setup(device); - if (ret) - return ret; - pr_info("ACPI: %s [%s]\n", acpi_device_name(device), acpi_device_bid(device)); @@ -410,6 +406,10 @@ static int acpi_fujitsu_bl_add(struct acpi_device *device) priv->max_brightness = FUJITSU_LCD_N_LEVELS; get_lcd_level(device); + ret = acpi_fujitsu_bl_input_setup(device); + if (ret) + return ret; + ret = fujitsu_backlight_register(device); if (ret) return ret; @@ -795,10 +795,6 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device) goto err_stop; } - ret = acpi_fujitsu_laptop_input_setup(device); - if (ret) - goto err_free_fifo; - pr_info("ACPI: %s [%s]\n", acpi_device_name(device), acpi_device_bid(device)); @@ -833,6 +829,10 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device) fujitsu_bl->bl_device->props.power = FB_BLANK_UNBLANK; } + ret = acpi_fujitsu_laptop_input_setup(device); + if (ret) + goto err_free_fifo; + ret = acpi_fujitsu_laptop_leds_register(device); if (ret) goto err_free_fifo; From 7f83d410440e63b173a91c65bb2515fa38501092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Sun, 11 Feb 2018 22:07:23 +0100 Subject: [PATCH 15/41] platform/x86: fujitsu-laptop: Simplify error paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the last few lines of acpi_fujitsu_bl_add() with a simple return in order to improve code readability without changing the logic. As acpi_fujitsu_laptop_add() uses a managed memory allocation for device-specific data, it is fine to just return immediately upon kfifo allocation failure. Do that instead of jumping to the end of the function to improve code readability. Running out of memory while allocating the kfifo does not seem probable enough to warrant logging an error message, so do not do it. Signed-off-by: Michał Kępień Reviewed-by: Jonathan Woithe Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/fujitsu-laptop.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 7f30a427a16c..94ff7f86fa8f 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -410,11 +410,7 @@ static int acpi_fujitsu_bl_add(struct acpi_device *device) if (ret) return ret; - ret = fujitsu_backlight_register(device); - if (ret) - return ret; - - return 0; + return fujitsu_backlight_register(device); } /* Brightness notify */ @@ -790,10 +786,8 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device) spin_lock_init(&priv->fifo_lock); ret = kfifo_alloc(&priv->fifo, RINGBUFFERSIZE * sizeof(int), GFP_KERNEL); - if (ret) { - pr_err("kfifo_alloc failed\n"); - goto err_stop; - } + if (ret) + return ret; pr_info("ACPI: %s [%s]\n", acpi_device_name(device), acpi_device_bid(device)); @@ -845,7 +839,7 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device) err_free_fifo: kfifo_free(&priv->fifo); -err_stop: + return ret; } From 6cb1192f5615fdfc4d4cb8ab4d911e4e758689f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Sun, 11 Feb 2018 22:07:24 +0100 Subject: [PATCH 16/41] platform/x86: fujitsu-laptop: Clearly distinguish module parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to improve code clarity, move declarations of variables that are module parameters higher up and add a comment. Signed-off-by: Michał Kępień Reviewed-by: Jonathan Woithe Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/fujitsu-laptop.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 94ff7f86fa8f..7888b779d6c5 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -112,6 +112,10 @@ #define MAX_HOTKEY_RINGBUFFER_SIZE 100 #define RINGBUFFERSIZE 40 +/* Module parameters */ +static int use_alt_lcd_levels = -1; +static bool disable_brightness_adjust; + /* Device controlling the backlight and associated keys */ struct fujitsu_bl { struct input_dev *input; @@ -122,8 +126,6 @@ struct fujitsu_bl { }; static struct fujitsu_bl *fujitsu_bl; -static int use_alt_lcd_levels = -1; -static bool disable_brightness_adjust; /* Device used to access hotkeys and other features on the laptop */ struct fujitsu_laptop { From 7e6f97959abedcf75d1f11989eca43a3ddc4965d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Sun, 11 Feb 2018 22:07:25 +0100 Subject: [PATCH 17/41] platform/x86: fujitsu-laptop: Do not include linux/slab.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not include linux/slab.h as all module code now uses managed memory allocations and thus neither k*alloc() nor kfree() is used. Signed-off-by: Michał Kępień Reviewed-by: Jonathan Woithe Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/fujitsu-laptop.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 7888b779d6c5..17779b8b7f30 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -61,7 +61,6 @@ #include #include #include -#include #include #define FUJITSU_DRIVER_VERSION "0.6.0" From 2f60efa1e48884b8d83f1ea94433b871814543ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Tue, 20 Feb 2018 06:24:53 +0100 Subject: [PATCH 18/41] platform/x86: fujitsu-laptop: Define constants for backlight power control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use named constants instead of integers in call_fext_func() invocations related to backlight power control in order to more clearly convey the intent of each call. Signed-off-by: Michał Kępień Reviewed-by: Jonathan Woithe Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/fujitsu-laptop.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 17779b8b7f30..6b0484cbdcf2 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -101,6 +101,11 @@ #define ECO_LED 0x10000 #define ECO_LED_ON 0x80000 +/* FUNC interface - backlight power control */ +#define BACKLIGHT_PARAM_POWER 0x4 +#define BACKLIGHT_OFF 0x3 +#define BACKLIGHT_ON 0x0 + /* Hotkey details */ #define KEY1_CODE 0x410 /* codes for the keys in the GIRB register */ #define KEY2_CODE 0x411 @@ -257,9 +262,11 @@ static int bl_update_status(struct backlight_device *b) if (fext) { if (b->props.power == FB_BLANK_POWERDOWN) - call_fext_func(fext, FUNC_BACKLIGHT, 0x1, 0x4, 0x3); + call_fext_func(fext, FUNC_BACKLIGHT, 0x1, + BACKLIGHT_PARAM_POWER, BACKLIGHT_OFF); else - call_fext_func(fext, FUNC_BACKLIGHT, 0x1, 0x4, 0x0); + call_fext_func(fext, FUNC_BACKLIGHT, 0x1, + BACKLIGHT_PARAM_POWER, BACKLIGHT_ON); } return set_lcd_level(device, b->props.brightness); @@ -818,7 +825,8 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device) /* Sync backlight power status */ if (fujitsu_bl && fujitsu_bl->bl_device && acpi_video_get_backlight_type() == acpi_backlight_vendor) { - if (call_fext_func(fext, FUNC_BACKLIGHT, 0x2, 0x4, 0x0) == 3) + if (call_fext_func(fext, FUNC_BACKLIGHT, 0x2, + BACKLIGHT_PARAM_POWER, 0x0) == BACKLIGHT_OFF) fujitsu_bl->bl_device->props.power = FB_BLANK_POWERDOWN; else fujitsu_bl->bl_device->props.power = FB_BLANK_UNBLANK; From 819cddae7cfa9b7673c24c338199274ba175e2b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Tue, 20 Feb 2018 06:24:54 +0100 Subject: [PATCH 19/41] platform/x86: fujitsu-laptop: Clean up constants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Align all constant values defined in the module to a common indentation. Rename ACPI_FUJITSU_NOTIFY_CODE1 to ACPI_FUJITSU_NOTIFY_CODE as there is only one ACPI notification code used throughout the driver. Define all bitmasks using the BIT() macro. Clean up comments. Signed-off-by: Michał Kępień Reviewed-by: Jonathan Woithe Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/fujitsu-laptop.c | 66 ++++++++++++++------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 6b0484cbdcf2..13bcdfea5349 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -63,9 +64,9 @@ #include #include -#define FUJITSU_DRIVER_VERSION "0.6.0" +#define FUJITSU_DRIVER_VERSION "0.6.0" -#define FUJITSU_LCD_N_LEVELS 8 +#define FUJITSU_LCD_N_LEVELS 8 #define ACPI_FUJITSU_CLASS "fujitsu" #define ACPI_FUJITSU_BL_HID "FUJ02B1" @@ -75,46 +76,47 @@ #define ACPI_FUJITSU_LAPTOP_DRIVER_NAME "Fujitsu laptop FUJ02E3 ACPI hotkeys driver" #define ACPI_FUJITSU_LAPTOP_DEVICE_NAME "Fujitsu FUJ02E3" -#define ACPI_FUJITSU_NOTIFY_CODE1 0x80 +#define ACPI_FUJITSU_NOTIFY_CODE 0x80 /* FUNC interface - command values */ -#define FUNC_FLAGS 0x1000 -#define FUNC_LEDS 0x1001 -#define FUNC_BUTTONS 0x1002 -#define FUNC_BACKLIGHT 0x1004 +#define FUNC_FLAGS BIT(12) +#define FUNC_LEDS (BIT(12) | BIT(0)) +#define FUNC_BUTTONS (BIT(12) | BIT(1)) +#define FUNC_BACKLIGHT (BIT(12) | BIT(2)) /* FUNC interface - responses */ -#define UNSUPPORTED_CMD 0x80000000 +#define UNSUPPORTED_CMD BIT(31) /* FUNC interface - status flags */ -#define FLAG_RFKILL 0x020 -#define FLAG_LID 0x100 -#define FLAG_DOCK 0x200 +#define FLAG_RFKILL BIT(5) +#define FLAG_LID BIT(8) +#define FLAG_DOCK BIT(9) /* FUNC interface - LED control */ -#define FUNC_LED_OFF 0x1 -#define FUNC_LED_ON 0x30001 -#define KEYBOARD_LAMPS 0x100 -#define LOGOLAMP_POWERON 0x2000 -#define LOGOLAMP_ALWAYS 0x4000 -#define RADIO_LED_ON 0x20 -#define ECO_LED 0x10000 -#define ECO_LED_ON 0x80000 +#define FUNC_LED_OFF BIT(0) +#define FUNC_LED_ON (BIT(0) | BIT(16) | BIT(17)) +#define LOGOLAMP_POWERON BIT(13) +#define LOGOLAMP_ALWAYS BIT(14) +#define KEYBOARD_LAMPS BIT(8) +#define RADIO_LED_ON BIT(5) +#define ECO_LED BIT(16) +#define ECO_LED_ON BIT(19) /* FUNC interface - backlight power control */ -#define BACKLIGHT_PARAM_POWER 0x4 -#define BACKLIGHT_OFF 0x3 -#define BACKLIGHT_ON 0x0 +#define BACKLIGHT_PARAM_POWER BIT(2) +#define BACKLIGHT_OFF (BIT(0) | BIT(1)) +#define BACKLIGHT_ON 0 -/* Hotkey details */ -#define KEY1_CODE 0x410 /* codes for the keys in the GIRB register */ -#define KEY2_CODE 0x411 -#define KEY3_CODE 0x412 -#define KEY4_CODE 0x413 -#define KEY5_CODE 0x420 +/* Scancodes read from the GIRB register */ +#define KEY1_CODE 0x410 +#define KEY2_CODE 0x411 +#define KEY3_CODE 0x412 +#define KEY4_CODE 0x413 +#define KEY5_CODE 0x420 -#define MAX_HOTKEY_RINGBUFFER_SIZE 100 -#define RINGBUFFERSIZE 40 +/* Hotkey ringbuffer limits */ +#define MAX_HOTKEY_RINGBUFFER_SIZE 100 +#define RINGBUFFERSIZE 40 /* Module parameters */ static int use_alt_lcd_levels = -1; @@ -428,7 +430,7 @@ static void acpi_fujitsu_bl_notify(struct acpi_device *device, u32 event) struct fujitsu_bl *priv = acpi_driver_data(device); int oldb, newb; - if (event != ACPI_FUJITSU_NOTIFY_CODE1) { + if (event != ACPI_FUJITSU_NOTIFY_CODE) { acpi_handle_info(device->handle, "unsupported event [0x%x]\n", event); sparse_keymap_report_event(priv->input, -1, 1, true); @@ -902,7 +904,7 @@ static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event) int scancode, i = 0; unsigned int irb; - if (event != ACPI_FUJITSU_NOTIFY_CODE1) { + if (event != ACPI_FUJITSU_NOTIFY_CODE) { acpi_handle_info(device->handle, "Unsupported event [0x%x]\n", event); sparse_keymap_report_event(priv->input, -1, 1, true); From 027d50ccd6a01c6ca8969b49e69f26d64a8f94b2 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 22 Feb 2018 13:58:42 -0600 Subject: [PATCH 20/41] platform/x86: intel-vbtn: Only activate tablet mode switch on 2-in-1's Some laptops such as the XPS 9360 support the intel-vbtn INT33D6 interface but don't initialize the bit that intel-vbtn uses to represent switching tablet mode. By running this only on real 2-in-1's it shouldn't cause false positives. Fixes: 30323fb6d5 ("Support tablet mode switch") Reported-by: Jeremy Cline Signed-off-by: Mario Limonciello Tested-by: Jeremy Cline Tested-by: Darren Hart (VMware) Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/intel-vbtn.c | 46 +++++++++++++++++++------------ 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c index b703d6f5b099..8173307d6bb1 100644 --- a/drivers/platform/x86/intel-vbtn.c +++ b/drivers/platform/x86/intel-vbtn.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -97,9 +98,35 @@ out_unknown: dev_dbg(&device->dev, "unknown event index 0x%x\n", event); } +static void detect_tablet_mode(struct platform_device *device) +{ + const char *chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE); + struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev); + acpi_handle handle = ACPI_HANDLE(&device->dev); + struct acpi_buffer vgbs_output = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + acpi_status status; + int m; + + if (!(chassis_type && strcmp(chassis_type, "31") == 0)) + goto out; + + status = acpi_evaluate_object(handle, "VGBS", NULL, &vgbs_output); + if (ACPI_FAILURE(status)) + goto out; + + obj = vgbs_output.pointer; + if (!(obj && obj->type == ACPI_TYPE_INTEGER)) + goto out; + + m = !(obj->integer.value & TABLET_MODE_FLAG); + input_report_switch(priv->input_dev, SW_TABLET_MODE, m); +out: + kfree(vgbs_output.pointer); +} + static int intel_vbtn_probe(struct platform_device *device) { - struct acpi_buffer vgbs_output = { ACPI_ALLOCATE_BUFFER, NULL }; acpi_handle handle = ACPI_HANDLE(&device->dev); struct intel_vbtn_priv *priv; acpi_status status; @@ -122,22 +149,7 @@ static int intel_vbtn_probe(struct platform_device *device) return err; } - /* - * VGBS being present and returning something means we have - * a tablet mode switch. - */ - status = acpi_evaluate_object(handle, "VGBS", NULL, &vgbs_output); - if (ACPI_SUCCESS(status)) { - union acpi_object *obj = vgbs_output.pointer; - - if (obj && obj->type == ACPI_TYPE_INTEGER) { - int m = !(obj->integer.value & TABLET_MODE_FLAG); - - input_report_switch(priv->input_dev, SW_TABLET_MODE, m); - } - } - - kfree(vgbs_output.pointer); + detect_tablet_mode(device); status = acpi_install_notify_handler(handle, ACPI_DEVICE_NOTIFY, From 250b044e1a584887c06e6ba79446e523ffa3cc9c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 28 Feb 2018 12:09:56 +0100 Subject: [PATCH 21/41] platform/x86: intel-vbtn: Reset wakeup capable flag on removal The intel-vbtn device will not be able to wake up the system any more after removing the notify handler provided by its driver, so make its sysfs attributes reflect that. Fixes: 91f9e850d465 (platform: x86: intel-vbtn: Wake up the system from suspend-to-idle) Signed-off-by: Rafael J. Wysocki Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel-vbtn.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c index 8173307d6bb1..c13780b8dabb 100644 --- a/drivers/platform/x86/intel-vbtn.c +++ b/drivers/platform/x86/intel-vbtn.c @@ -166,6 +166,7 @@ static int intel_vbtn_remove(struct platform_device *device) { acpi_handle handle = ACPI_HANDLE(&device->dev); + device_init_wakeup(&device->dev, false); acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler); /* From 356b57752c91cffb35356abe6647065bf0edcad1 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 28 Feb 2018 12:10:59 +0100 Subject: [PATCH 22/41] platform/x86: intel-hid: Reset wakeup capable flag on removal The intel-hid device will not be able to wake up the system any more after removing the notify handler provided by its driver, so make its sysfs attributes reflect that. Fixes: ef884112e55c (platform: x86: intel-hid: Wake up the system from suspend-to-idle) Signed-off-by: Rafael J. Wysocki Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel-hid.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index d1a01311c1a2..5e3df194723e 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -376,6 +376,7 @@ static int intel_hid_remove(struct platform_device *device) { acpi_handle handle = ACPI_HANDLE(&device->dev); + device_init_wakeup(&device->dev, false); acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler); intel_hid_set_enable(&device->dev, false); intel_button_array_enable(&device->dev, false); From 501f7e52de8a7b910154740958ce8d902258bf72 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 1 Mar 2018 08:08:23 -0800 Subject: [PATCH 23/41] platform/x86: wmi: Fix misuse of vsprintf extension %pULL %pULL doesn't officially exist but %pUL does. Miscellanea: o Add missing newlines to a couple logging messages Signed-off-by: Joe Perches Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/wmi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index f90ba83359f5..8e3d0146ff8c 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -936,7 +936,7 @@ static int wmi_dev_probe(struct device *dev) wblock->char_dev.mode = 0444; ret = misc_register(&wblock->char_dev); if (ret) { - dev_warn(dev, "failed to register char dev: %d", ret); + dev_warn(dev, "failed to register char dev: %d\n", ret); ret = -ENOMEM; goto probe_misc_failure; } @@ -1039,7 +1039,7 @@ static int wmi_create_device(struct device *wmi_bus_dev, if (result) { dev_warn(wmi_bus_dev, - "%s data block query control method not found", + "%s data block query control method not found\n", method); return result; } @@ -1189,7 +1189,7 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device) retval = device_add(&wblock->dev.dev); if (retval) { - dev_err(wmi_bus_dev, "failed to register %pULL\n", + dev_err(wmi_bus_dev, "failed to register %pUL\n", wblock->gblock.guid); if (debug_event) wmi_method_enable(wblock, 0); From 98c76a3904261a7b7612821de8b99f0e3b41677c Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 27 Feb 2018 12:23:02 -0600 Subject: [PATCH 24/41] platform/x86: dell-smbios: Correct some style warnings WARNING: function definition argument 'struct calling_interface_buffer *' should also have an identifier name + int (*call_fn)(struct calling_interface_buffer *); WARNING: Block comments use * on subsequent lines + /* 4 bytes of table header, plus 7 bytes of Dell header, plus at least + 6 bytes of entry */ WARNING: Block comments use a trailing */ on a separate line + 6 bytes of entry */ Signed-off-by: Mario Limonciello Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/dell-smbios.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/dell-smbios.c b/drivers/platform/x86/dell-smbios.c index 8541cde4cb7d..76b9d7545447 100644 --- a/drivers/platform/x86/dell-smbios.c +++ b/drivers/platform/x86/dell-smbios.c @@ -36,7 +36,7 @@ static DEFINE_MUTEX(smbios_mutex); struct smbios_device { struct list_head list; struct device *device; - int (*call_fn)(struct calling_interface_buffer *); + int (*call_fn)(struct calling_interface_buffer *arg); }; struct smbios_call { @@ -352,8 +352,10 @@ static void __init parse_da_table(const struct dmi_header *dm) struct calling_interface_structure *table = container_of(dm, struct calling_interface_structure, header); - /* 4 bytes of table header, plus 7 bytes of Dell header, plus at least - 6 bytes of entry */ + /* + * 4 bytes of table header, plus 7 bytes of Dell header + * plus at least 6 bytes of entry + */ if (dm->length < 17) return; From ec34fe385984b447f62ef6763638874e6fbd1f43 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 27 Feb 2018 12:23:03 -0600 Subject: [PATCH 25/41] platform/x86: dell-smbios: Rename dell-smbios source to dell-smbios-base This is being done to faciliate a later change to link all the dell-smbios drivers together. Signed-off-by: Mario Limonciello Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/Makefile | 1 + drivers/platform/x86/{dell-smbios.c => dell-smbios-base.c} | 0 2 files changed, 1 insertion(+) rename drivers/platform/x86/{dell-smbios.c => dell-smbios-base.c} (100%) diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index c388608ad2a3..940b1180fbff 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o +dell-smbios-objs := dell-smbios-base.o obj-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o obj-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o diff --git a/drivers/platform/x86/dell-smbios.c b/drivers/platform/x86/dell-smbios-base.c similarity index 100% rename from drivers/platform/x86/dell-smbios.c rename to drivers/platform/x86/dell-smbios-base.c From 41e36f2f85af758fd2f4be76112ebe649d07a801 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 27 Feb 2018 12:23:04 -0600 Subject: [PATCH 26/41] platform/x86: dell-smbios: Link all dell-smbios-* modules together Some race conditions were raised due to dell-smbios and its backends not being ready by the time that a consumer would call one of the exported methods. To avoid this problem, guarantee that all initialization has been done by linking them all together and running init for them all. As part of this change the Kconfig needs to be adjusted so that CONFIG_DELL_SMBIOS_SMM and CONFIG_DELL_SMBIOS_WMI are boolean rather than modules. CONFIG_DELL_SMBIOS is a visually selectable option again and both CONFIG_DELL_SMBIOS_WMI and CONFIG_DELL_SMBIOS_SMM are optional. Signed-off-by: Mario Limonciello [dvhart: Update prompt and help text for DELL_SMBIOS_* backends] Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/Kconfig | 15 +++++++++----- drivers/platform/x86/Makefile | 4 ++-- drivers/platform/x86/dell-smbios-base.c | 21 ++++++++++++++++++- drivers/platform/x86/dell-smbios-smm.c | 18 ++++------------- drivers/platform/x86/dell-smbios-wmi.c | 14 ++++--------- drivers/platform/x86/dell-smbios.h | 27 ++++++++++++++++++++++++- 6 files changed, 66 insertions(+), 33 deletions(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index bc66a31757db..e3f682c669f5 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -106,10 +106,15 @@ config ASUS_LAPTOP If you have an ACPI-compatible ASUS laptop, say Y or M here. config DELL_SMBIOS - tristate + tristate "Dell SMBIOS driver" + ---help--- + This provides support for the Dell SMBIOS calling interface. + If you have a Dell computer you should enable this option. + + Be sure to select at least one backend for it to work properly. config DELL_SMBIOS_WMI - tristate "Dell SMBIOS calling interface (WMI implementation)" + bool "Dell SMBIOS driver WMI backend" depends on ACPI_WMI select DELL_WMI_DESCRIPTOR select DELL_SMBIOS @@ -117,19 +122,19 @@ config DELL_SMBIOS_WMI This provides an implementation for the Dell SMBIOS calling interface communicated over ACPI-WMI. - If you have a Dell computer from >2007 you should say Y or M here. + If you have a Dell computer from >2007 you should say Y here. If you aren't sure and this module doesn't work for your computer it just won't load. config DELL_SMBIOS_SMM - tristate "Dell SMBIOS calling interface (SMM implementation)" + bool "Dell SMBIOS driver SMM backend" depends on DCDBAS select DELL_SMBIOS ---help--- This provides an implementation for the Dell SMBIOS calling interface communicated over SMI/SMM. - If you have a Dell computer from <=2017 you should say Y or M here. + If you have a Dell computer from <=2017 you should say Y here. If you aren't sure and this module doesn't work for your computer it just won't load. diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 940b1180fbff..2ba6cb795338 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -14,8 +14,8 @@ obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o dell-smbios-objs := dell-smbios-base.o -obj-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o -obj-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o +dell-smbios-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o +dell-smbios-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o obj-$(CONFIG_DELL_WMI) += dell-wmi.o obj-$(CONFIG_DELL_WMI_DESCRIPTOR) += dell-wmi-descriptor.o diff --git a/drivers/platform/x86/dell-smbios-base.c b/drivers/platform/x86/dell-smbios-base.c index 76b9d7545447..5bcf8a18f785 100644 --- a/drivers/platform/x86/dell-smbios-base.c +++ b/drivers/platform/x86/dell-smbios-base.c @@ -556,7 +556,7 @@ static void free_group(struct platform_device *pdev) static int __init dell_smbios_init(void) { const struct dmi_device *valid; - int ret; + int ret, wmi, smm; valid = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "Dell System", NULL); if (!valid) { @@ -591,8 +591,24 @@ static int __init dell_smbios_init(void) if (ret) goto fail_create_group; + /* register backends */ + wmi = init_dell_smbios_wmi(); + if (wmi) + pr_debug("Failed to initialize WMI backend: %d\n", wmi); + smm = init_dell_smbios_smm(); + if (smm) + pr_debug("Failed to initialize SMM backend: %d\n", smm); + if (wmi && smm) { + pr_err("No SMBIOS backends available (wmi: %d, smm: %d)\n", + wmi, smm); + goto fail_sysfs; + } + return 0; +fail_sysfs: + free_group(platform_device); + fail_create_group: platform_device_del(platform_device); @@ -609,6 +625,8 @@ fail_platform_driver: static void __exit dell_smbios_exit(void) { + exit_dell_smbios_wmi(); + exit_dell_smbios_smm(); mutex_lock(&smbios_mutex); if (platform_device) { free_group(platform_device); @@ -625,5 +643,6 @@ module_exit(dell_smbios_exit); MODULE_AUTHOR("Matthew Garrett "); MODULE_AUTHOR("Gabriele Mazzotta "); MODULE_AUTHOR("Pali Rohár "); +MODULE_AUTHOR("Mario Limonciello "); MODULE_DESCRIPTION("Common functions for kernel modules using Dell SMBIOS"); MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/dell-smbios-smm.c b/drivers/platform/x86/dell-smbios-smm.c index 89f65c4651a0..e9e9da556318 100644 --- a/drivers/platform/x86/dell-smbios-smm.c +++ b/drivers/platform/x86/dell-smbios-smm.c @@ -58,7 +58,7 @@ static const struct dmi_system_id dell_device_table[] __initconst = { }; MODULE_DEVICE_TABLE(dmi, dell_device_table); -static void __init parse_da_table(const struct dmi_header *dm) +static void parse_da_table(const struct dmi_header *dm) { struct calling_interface_structure *table = container_of(dm, struct calling_interface_structure, header); @@ -73,7 +73,7 @@ static void __init parse_da_table(const struct dmi_header *dm) da_command_code = table->cmdIOCode; } -static void __init find_cmd_address(const struct dmi_header *dm, void *dummy) +static void find_cmd_address(const struct dmi_header *dm, void *dummy) { switch (dm->type) { case 0xda: /* Calling interface */ @@ -128,7 +128,7 @@ static bool test_wsmt_enabled(void) return false; } -static int __init dell_smbios_smm_init(void) +int init_dell_smbios_smm(void) { int ret; /* @@ -176,7 +176,7 @@ fail_platform_device_alloc: return ret; } -static void __exit dell_smbios_smm_exit(void) +void exit_dell_smbios_smm(void) { if (platform_device) { dell_smbios_unregister_device(&platform_device->dev); @@ -184,13 +184,3 @@ static void __exit dell_smbios_smm_exit(void) free_page((unsigned long)buffer); } } - -subsys_initcall(dell_smbios_smm_init); -module_exit(dell_smbios_smm_exit); - -MODULE_AUTHOR("Matthew Garrett "); -MODULE_AUTHOR("Gabriele Mazzotta "); -MODULE_AUTHOR("Pali Rohár "); -MODULE_AUTHOR("Mario Limonciello "); -MODULE_DESCRIPTION("Dell SMBIOS communications over SMI"); -MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/dell-smbios-wmi.c b/drivers/platform/x86/dell-smbios-wmi.c index 609557aa5868..fbefedb1c172 100644 --- a/drivers/platform/x86/dell-smbios-wmi.c +++ b/drivers/platform/x86/dell-smbios-wmi.c @@ -228,7 +228,7 @@ static const struct wmi_device_id dell_smbios_wmi_id_table[] = { { }, }; -static void __init parse_b1_table(const struct dmi_header *dm) +static void parse_b1_table(const struct dmi_header *dm) { struct misc_bios_flags_structure *flags = container_of(dm, struct misc_bios_flags_structure, header); @@ -242,7 +242,7 @@ static void __init parse_b1_table(const struct dmi_header *dm) wmi_supported = 1; } -static void __init find_b1(const struct dmi_header *dm, void *dummy) +static void find_b1(const struct dmi_header *dm, void *dummy) { switch (dm->type) { case 0xb1: /* misc bios flags */ @@ -261,7 +261,7 @@ static struct wmi_driver dell_smbios_wmi_driver = { .filter_callback = dell_smbios_wmi_filter, }; -static int __init init_dell_smbios_wmi(void) +int init_dell_smbios_wmi(void) { dmi_walk(find_b1, NULL); @@ -271,15 +271,9 @@ static int __init init_dell_smbios_wmi(void) return wmi_driver_register(&dell_smbios_wmi_driver); } -static void __exit exit_dell_smbios_wmi(void) +void exit_dell_smbios_wmi(void) { wmi_driver_unregister(&dell_smbios_wmi_driver); } -module_init(init_dell_smbios_wmi); -module_exit(exit_dell_smbios_wmi); - MODULE_ALIAS("wmi:" DELL_WMI_SMBIOS_GUID); -MODULE_AUTHOR("Mario Limonciello "); -MODULE_DESCRIPTION("Dell SMBIOS communications over WMI"); -MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/dell-smbios.h b/drivers/platform/x86/dell-smbios.h index 138d478d9adc..d8adaf959740 100644 --- a/drivers/platform/x86/dell-smbios.h +++ b/drivers/platform/x86/dell-smbios.h @@ -75,4 +75,29 @@ int dell_laptop_register_notifier(struct notifier_block *nb); int dell_laptop_unregister_notifier(struct notifier_block *nb); void dell_laptop_call_notifier(unsigned long action, void *data); -#endif +/* for the supported backends */ +#ifdef CONFIG_DELL_SMBIOS_WMI +int init_dell_smbios_wmi(void); +void exit_dell_smbios_wmi(void); +#else /* CONFIG_DELL_SMBIOS_WMI */ +static inline int init_dell_smbios_wmi(void) +{ + return -ENODEV; +} +static inline void exit_dell_smbios_wmi(void) +{} +#endif /* CONFIG_DELL_SMBIOS_WMI */ + +#ifdef CONFIG_DELL_SMBIOS_SMM +int init_dell_smbios_smm(void); +void exit_dell_smbios_smm(void); +#else /* CONFIG_DELL_SMBIOS_SMM */ +static inline int init_dell_smbios_smm(void) +{ + return -ENODEV; +} +static inline void exit_dell_smbios_smm(void) +{} +#endif /* CONFIG_DELL_SMBIOS_SMM */ + +#endif /* _DELL_SMBIOS_H_ */ From c715e4345581bdb475ae4fb378a243aee72579ba Mon Sep 17 00:00:00 2001 From: "Darren Hart (VMware)" Date: Fri, 2 Mar 2018 17:40:32 -0800 Subject: [PATCH 27/41] platform/x86: Allow for SMBIOS backend defaults Avoid accidental configurations by setting default y for DELL_SMBIOS backends. Avoid this impacting the default build size, by making them dependent on DELL_SMBIOS, so they only appear when DELL_SMBIOS is manually selected, or by DELL_LAPTOP or DELL_WMI. While DELL_SMBIOS does have a prompt, it does not have any dependencies. Keeping DELL_SMBIOS visible, despite being "select"ed by DELL_LAPTOP and DELL_WMI, is a deliberate choice to provide context for the WMI and SMM backends, which would otherwise appear to float without context within the menu. Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/Kconfig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index e3f682c669f5..022c83786aec 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -115,9 +115,10 @@ config DELL_SMBIOS config DELL_SMBIOS_WMI bool "Dell SMBIOS driver WMI backend" + default y depends on ACPI_WMI select DELL_WMI_DESCRIPTOR - select DELL_SMBIOS + depends on DELL_SMBIOS ---help--- This provides an implementation for the Dell SMBIOS calling interface communicated over ACPI-WMI. @@ -128,8 +129,9 @@ config DELL_SMBIOS_WMI config DELL_SMBIOS_SMM bool "Dell SMBIOS driver SMM backend" + default y depends on DCDBAS - select DELL_SMBIOS + depends on DELL_SMBIOS ---help--- This provides an implementation for the Dell SMBIOS calling interface communicated over SMI/SMM. From cc69c88fbeb915447b87e5179378d899d1f61554 Mon Sep 17 00:00:00 2001 From: "Darren Hart (VMware)" Date: Tue, 6 Mar 2018 18:01:04 -0800 Subject: [PATCH 28/41] platform/x86: dell-smbios: Resolve dependency error on DCDBAS When the DELL_SMBIOS_SMM backend is enabled, the DELL_SMBIOS symbol depends on DELL_DCDBAS, and we must avoid the situation where DELL_SMBIOS=y and DCDBAS=m. Adding the conditional dependency to DELL_SMBIOS such as: depends !DELL_SMBIOS_SMM || (DCDBAS || DCDBAS=n) results in the Kconfig tooling complaining about a circular dependency, although it appears to work in practice. Avoid the errors by simplifying the dependency and forcing DELL_SMBIOS to be <= DCDBAS if DCDBAS is enabled (thanks to Greg KH for the suggestion). Cc: Mario.Limonciello@dell.com Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 022c83786aec..e55b0089c06f 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -105,8 +105,14 @@ config ASUS_LAPTOP If you have an ACPI-compatible ASUS laptop, say Y or M here. +# +# If the DELL_SMBIOS_SMM feature is enabled, the DELL_SMBIOS driver +# becomes dependent on the DCDBAS driver. The "depends" line prevents a +# configuration where DELL_SMBIOS=y while DCDBAS=m. +# config DELL_SMBIOS tristate "Dell SMBIOS driver" + depends on DCDBAS || DCDBAS=n ---help--- This provides support for the Dell SMBIOS calling interface. If you have a Dell computer you should enable this option. From 4716007c23abeb0e42015786794539454aff487b Mon Sep 17 00:00:00 2001 From: Darren Hart Date: Sat, 10 Mar 2018 16:12:16 -0800 Subject: [PATCH 29/41] platform/x86: dell-smbios: Resolve dependency error on ACPI_WMI Similarly to DCDBAS for DELL_SMBIOS_SMM, if DELL_SMBIOS_WMI is enabled, DELL_SMBIOS becomes dependent on ACPI_WMI. Update the depends lines to prevent a configuration where DELL_SMBIOS=y and either backend dependency =m. Update the comment accordingly. Cc: Mario Limonciello Cc: Andy Shevchenko Cc: Dominik Brodowski Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/Kconfig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index e55b0089c06f..1868aab0282a 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -106,13 +106,14 @@ config ASUS_LAPTOP If you have an ACPI-compatible ASUS laptop, say Y or M here. # -# If the DELL_SMBIOS_SMM feature is enabled, the DELL_SMBIOS driver -# becomes dependent on the DCDBAS driver. The "depends" line prevents a -# configuration where DELL_SMBIOS=y while DCDBAS=m. +# The DELL_SMBIOS driver depends on ACPI_WMI and/or DCDBAS if those +# backends are selected. The "depends" line prevents a configuration +# where DELL_SMBIOS=y while either of those dependencies =m. # config DELL_SMBIOS tristate "Dell SMBIOS driver" depends on DCDBAS || DCDBAS=n + depends on ACPI_WMI || ACPI_WMI=n ---help--- This provides support for the Dell SMBIOS calling interface. If you have a Dell computer you should enable this option. From 7129707ec2356ef9ef9cce469ad14eb37fbbe67e Mon Sep 17 00:00:00 2001 From: "Darren Hart (VMware)" Date: Mon, 12 Mar 2018 23:28:00 -0700 Subject: [PATCH 30/41] platform/x86: Fix dell driver init order Update the initcall ordering to satisfy the following dependency ordering: 1. DCDBAS, ACPI_WMI 2. DELL_SMBIOS, DELL_RBTN 3. DELL_LAPTOP, DELL_WMI By assigning them to the following initcall levels: subsys_initcall: DCDBAS, ACPI_WMI module_init: DELL_SMBIOS, DELL_RBTN late_initcall: DELL_LAPTOP, DELL_WMI Cc: Dominik Brodowski Cc: Mario.Limonciello@dell.com Signed-off-by: Darren Hart (VMware) --- drivers/firmware/dcdbas.c | 2 +- drivers/platform/x86/dell-smbios-base.c | 2 +- drivers/platform/x86/dell-wmi.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index c16600f30611..0bdea60c65dd 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c @@ -639,7 +639,7 @@ static void __exit dcdbas_exit(void) platform_driver_unregister(&dcdbas_driver); } -module_init(dcdbas_init); +subsys_initcall_sync(dcdbas_init); module_exit(dcdbas_exit); MODULE_DESCRIPTION(DRIVER_DESCRIPTION " (version " DRIVER_VERSION ")"); diff --git a/drivers/platform/x86/dell-smbios-base.c b/drivers/platform/x86/dell-smbios-base.c index 5bcf8a18f785..2485c80a9fdd 100644 --- a/drivers/platform/x86/dell-smbios-base.c +++ b/drivers/platform/x86/dell-smbios-base.c @@ -637,7 +637,7 @@ static void __exit dell_smbios_exit(void) mutex_unlock(&smbios_mutex); } -subsys_initcall(dell_smbios_init); +module_init(dell_smbios_init); module_exit(dell_smbios_exit); MODULE_AUTHOR("Matthew Garrett "); diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 2c9927430d85..8d102195a392 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -714,7 +714,7 @@ static int __init dell_wmi_init(void) return wmi_driver_register(&dell_wmi_driver); } -module_init(dell_wmi_init); +late_initcall(dell_wmi_init); static void __exit dell_wmi_exit(void) { From 502ab004e6c4426b91460d8be8b9d4a4bf206657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Sat, 10 Mar 2018 21:43:53 +0100 Subject: [PATCH 31/41] platform/x86: fujitsu-laptop: Revert UNSUPPORTED_CMD back to an int MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UNSUPPORTED_CMD was previously 0x80000000 (int), but commit 819cddae7cfa ("platform/x86: fujitsu-laptop: Clean up constants") changed it into an unsigned long due to BIT() being used to define it. As call_fext_func() returns an int, 0x80000000 would get type promoted when compared to an unsigned long, which on a 64-bit system would cause it to become 0xffffffff80000000 due to sign extension. This causes one logical condition in fujitsu-laptop to always be true and another one to always be false on 64-bit systems. Fix this by reverting UNSUPPORTED_CMD back to an int. This patch fixes the following smatch warnings: drivers/platform/x86/fujitsu-laptop.c:763 acpi_fujitsu_laptop_leds_register() warn: always true condition '(call_fext_func(device, ((1 << (12)) | (1 << (0))), 2, (1 << (16)), 0) != (1 << (31))) => (s32min-s32max != 2147483648)' drivers/platform/x86/fujitsu-laptop.c:816 acpi_fujitsu_laptop_add() warn: impossible condition '(priv->flags_supported == (1 << (31))) => (0-2147483647,18446744071562067968-u64max == 2147483648)' Fixes: 819cddae7cfa ("platform/x86: fujitsu-laptop: Clean up constants") Reported-by: Dan Carpenter Signed-off-by: Michał Kępień Reviewed-by: Jonathan Woithe Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/fujitsu-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 13bcdfea5349..6f4a55a53ced 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -85,7 +85,7 @@ #define FUNC_BACKLIGHT (BIT(12) | BIT(2)) /* FUNC interface - responses */ -#define UNSUPPORTED_CMD BIT(31) +#define UNSUPPORTED_CMD 0x80000000 /* FUNC interface - status flags */ #define FLAG_RFKILL BIT(5) From d066f144d66728b8187bda5ef966b44c58935484 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Tue, 13 Feb 2018 22:09:33 +0000 Subject: [PATCH 32/41] platform/x86: mlx-platform: Use define for the channel numbers Add define for the channels number for mux device, instead of using hardcoded value inside the code in order to improve code readability. Signed-off-by: Vadim Pasternak Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/mlx-platform.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index 454e14f02285..71b452a89a6e 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c @@ -85,6 +85,9 @@ #define MLXPLAT_CPLD_FAN_MASK GENMASK(3, 0) #define MLXPLAT_CPLD_FAN_NG_MASK GENMASK(5, 0) +/* Number of channels in group */ +#define MLXPLAT_CPLD_GRP_CHNL_NUM 8 + /* Start channel numbers */ #define MLXPLAT_CPLD_CH1 2 #define MLXPLAT_CPLD_CH2 10 @@ -124,7 +127,7 @@ static const struct resource mlxplat_lpc_resources[] = { }; /* Platform default channels */ -static const int mlxplat_default_channels[][8] = { +static const int mlxplat_default_channels[][MLXPLAT_CPLD_GRP_CHNL_NUM] = { { MLXPLAT_CPLD_CH1, MLXPLAT_CPLD_CH1 + 1, MLXPLAT_CPLD_CH1 + 2, MLXPLAT_CPLD_CH1 + 3, MLXPLAT_CPLD_CH1 + 4, MLXPLAT_CPLD_CH1 + From d726f6b1997528354e1053accbb6223981e81802 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Tue, 13 Feb 2018 22:09:34 +0000 Subject: [PATCH 33/41] platform/x86: mlx-platform: Add deffered bus functionality mlx-platform activates i2c-mux-reg, which creates buses needed by mlxreg-hotplug. If the mlxreg-hotplug probe runs before the i2c-mux-reg probe completes, it may attempt to connect a device to an adapter number that has not been created yet, and fail. Make mlx-platform driver record the highest bus number in mlxreg-hotplug platform data and defer mlxreg-hotplug probe until all the buses are created. Signed-off-by: Vadim Pasternak [dvhart: rewrite commit message more concisely] Signed-off-by: Darren Hart (VMware) --- drivers/platform/mellanox/mlxreg-hotplug.c | 7 +++++++ drivers/platform/x86/mlx-platform.c | 10 ++++++++++ include/linux/platform_data/mlxreg.h | 2 ++ 3 files changed, 19 insertions(+) diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c index 313cf8ad77bf..fe4910bc0f96 100644 --- a/drivers/platform/mellanox/mlxreg-hotplug.c +++ b/drivers/platform/mellanox/mlxreg-hotplug.c @@ -550,6 +550,7 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev) { struct mlxreg_core_hotplug_platform_data *pdata; struct mlxreg_hotplug_priv_data *priv; + struct i2c_adapter *deferred_adap; int err; pdata = dev_get_platdata(&pdev->dev); @@ -558,6 +559,12 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev) return -EINVAL; } + /* Defer probing if the necessary adapter is not configured yet. */ + deferred_adap = i2c_get_adapter(pdata->deferred_nr); + if (!deferred_adap) + return -EPROBE_DEFER; + i2c_put_adapter(deferred_adap); + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index 71b452a89a6e..67f3c6d36988 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c @@ -697,6 +697,8 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) ARRAY_SIZE(mlxplat_default_channels[i]); } mlxplat_hotplug = &mlxplat_mlxcpld_default_data; + mlxplat_hotplug->deferred_nr = + mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; return 1; }; @@ -711,6 +713,8 @@ static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi) ARRAY_SIZE(mlxplat_msn21xx_channels); } mlxplat_hotplug = &mlxplat_mlxcpld_msn21xx_data; + mlxplat_hotplug->deferred_nr = + mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; return 1; }; @@ -725,6 +729,8 @@ static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi) ARRAY_SIZE(mlxplat_msn21xx_channels); } mlxplat_hotplug = &mlxplat_mlxcpld_msn274x_data; + mlxplat_hotplug->deferred_nr = + mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; return 1; }; @@ -739,6 +745,8 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi) ARRAY_SIZE(mlxplat_msn21xx_channels); } mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data; + mlxplat_hotplug->deferred_nr = + mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; return 1; }; @@ -753,6 +761,8 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi) ARRAY_SIZE(mlxplat_msn21xx_channels); } mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data; + mlxplat_hotplug->deferred_nr = + mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; return 1; }; diff --git a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h index fcdc707eab99..262910967476 100644 --- a/include/linux/platform_data/mlxreg.h +++ b/include/linux/platform_data/mlxreg.h @@ -129,6 +129,7 @@ struct mlxreg_core_platform_data { * @mask: top aggregation interrupt common mask; * @cell_low: location of low aggregation interrupt register; * @mask_low: low aggregation interrupt common mask; + * @deferred_nr: I2C adapter number must be exist prior probing execution; */ struct mlxreg_core_hotplug_platform_data { struct mlxreg_core_item *items; @@ -139,6 +140,7 @@ struct mlxreg_core_hotplug_platform_data { u32 mask; u32 cell_low; u32 mask_low; + int deferred_nr; }; #endif /* __LINUX_PLATFORM_DATA_MLXREG_H */ From f709e1bfb0c643a866b909d101442c7a7f425655 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Tue, 13 Feb 2018 22:09:35 +0000 Subject: [PATCH 34/41] platform/mellanox: mlxreg-hotplug: Change input for device create routine Change the first input parameter in mlxreg_hotplug_device_create to the pointer to mlxreg_hotplug private data in order to use the fields from the private data structure. Signed-off-by: Vadim Pasternak [dvhart: Cleaned up commit message] Signed-off-by: Darren Hart (VMware) --- drivers/platform/mellanox/mlxreg-hotplug.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c index fe4910bc0f96..c1e1c4f254ce 100644 --- a/drivers/platform/mellanox/mlxreg-hotplug.c +++ b/drivers/platform/mellanox/mlxreg-hotplug.c @@ -93,7 +93,7 @@ struct mlxreg_hotplug_priv_data { bool after_probe; }; -static int mlxreg_hotplug_device_create(struct device *dev, +static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv, struct mlxreg_core_data *data) { /* @@ -105,7 +105,7 @@ static int mlxreg_hotplug_device_create(struct device *dev, data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr); if (!data->hpdev.adapter) { - dev_err(dev, "Failed to get adapter for bus %d\n", + dev_err(priv->dev, "Failed to get adapter for bus %d\n", data->hpdev.nr); return -EFAULT; } @@ -113,7 +113,7 @@ static int mlxreg_hotplug_device_create(struct device *dev, data->hpdev.client = i2c_new_device(data->hpdev.adapter, data->hpdev.brdinfo); if (!data->hpdev.client) { - dev_err(dev, "Failed to create client %s at bus %d at addr 0x%02x\n", + dev_err(priv->dev, "Failed to create client %s at bus %d at addr 0x%02x\n", data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr); @@ -270,10 +270,10 @@ mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv, if (item->inversed) mlxreg_hotplug_device_destroy(data); else - mlxreg_hotplug_device_create(priv->dev, data); + mlxreg_hotplug_device_create(priv, data); } else { if (item->inversed) - mlxreg_hotplug_device_create(priv->dev, data); + mlxreg_hotplug_device_create(priv, data); else mlxreg_hotplug_device_destroy(data); } @@ -319,7 +319,7 @@ mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv, if (regval == MLXREG_HOTPLUG_HEALTH_MASK) { if ((data->health_cntr++ == MLXREG_HOTPLUG_RST_CNTR) || !priv->after_probe) { - mlxreg_hotplug_device_create(priv->dev, data); + mlxreg_hotplug_device_create(priv, data); data->attached = true; } } else { From ef0f62264b2a9e6fc73476ed22ade1ff1f3ad7f3 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Tue, 13 Feb 2018 22:09:36 +0000 Subject: [PATCH 35/41] platform/x86: mlx-platform: Add physical bus number auto detection mlx-platform does not provide a bus number to i2c-mlxcpld, assuming it is always one. On some x86 systems, other i2c drivers may probe before i2c-mlxcpld, causing bus one to be busy. Make mlx-platform determine which adapter number is free prior to activating i2c-mlxpld, adjusting the mux base numbers accordingly. Update the mlxreg-hotplug pdata similarly. This adds an explicit mlx-platform build dependency on I2C, update the Kconfig accordingly. Add the missing REGMAP dependency while we're at it. Signed-off-by: Vadim Pasternak [dvhart: Rewrite commit message more concisely] [dvhart: Add build dependencies] Signed-off-by: Darren Hart (VMware) --- drivers/platform/mellanox/mlxreg-hotplug.c | 12 +++-- drivers/platform/x86/Kconfig | 1 + drivers/platform/x86/mlx-platform.c | 53 +++++++++++++++++++++- include/linux/platform_data/mlxreg.h | 2 + 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c index c1e1c4f254ce..ea9e7f4479ca 100644 --- a/drivers/platform/mellanox/mlxreg-hotplug.c +++ b/drivers/platform/mellanox/mlxreg-hotplug.c @@ -96,6 +96,8 @@ struct mlxreg_hotplug_priv_data { static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv, struct mlxreg_core_data *data) { + struct mlxreg_core_hotplug_platform_data *pdata; + /* * Return if adapter number is negative. It could be in case hotplug * event is not associated with hotplug device. @@ -103,10 +105,12 @@ static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv, if (data->hpdev.nr < 0) return 0; - data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr); + pdata = dev_get_platdata(&priv->pdev->dev); + data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr + + pdata->shift_nr); if (!data->hpdev.adapter) { dev_err(priv->dev, "Failed to get adapter for bus %d\n", - data->hpdev.nr); + data->hpdev.nr + pdata->shift_nr); return -EFAULT; } @@ -114,8 +118,8 @@ static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv, data->hpdev.brdinfo); if (!data->hpdev.client) { dev_err(priv->dev, "Failed to create client %s at bus %d at addr 0x%02x\n", - data->hpdev.brdinfo->type, data->hpdev.nr, - data->hpdev.brdinfo->addr); + data->hpdev.brdinfo->type, data->hpdev.nr + + pdata->shift_nr, data->hpdev.brdinfo->addr); i2c_put_adapter(data->hpdev.adapter); data->hpdev.adapter = NULL; diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 1868aab0282a..b528e44ad8ae 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -1175,6 +1175,7 @@ config INTEL_TELEMETRY config MLX_PLATFORM tristate "Mellanox Technologies platform support" + depends on I2C && REGMAP ---help--- This option enables system support for the Mellanox Technologies platform. The Mellanox systems provide data center networking diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index 67f3c6d36988..7a0bd24c1ae2 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c @@ -85,6 +85,12 @@ #define MLXPLAT_CPLD_FAN_MASK GENMASK(3, 0) #define MLXPLAT_CPLD_FAN_NG_MASK GENMASK(5, 0) +/* Default I2C parent bus number */ +#define MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR 1 + +/* Maximum number of possible physical buses equipped on system */ +#define MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM 16 + /* Number of channels in group */ #define MLXPLAT_CPLD_GRP_CHNL_NUM 8 @@ -843,10 +849,48 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { MODULE_DEVICE_TABLE(dmi, mlxplat_dmi_table); +static int mlxplat_mlxcpld_verify_bus_topology(int *nr) +{ + struct i2c_adapter *search_adap; + int shift, i; + + /* Scan adapters from expected id to verify it is free. */ + *nr = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR; + for (i = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR; i < + MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; i++) { + search_adap = i2c_get_adapter(i); + if (search_adap) { + i2c_put_adapter(search_adap); + continue; + } + + /* Return if expected parent adapter is free. */ + if (i == MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR) + return 0; + break; + } + + /* Return with error if free id for adapter is not found. */ + if (i == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM) + return -ENODEV; + + /* Shift adapter ids, since expected parent adapter is not free. */ + *nr = i; + for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) { + shift = *nr - mlxplat_mux_data[i].parent; + mlxplat_mux_data[i].parent = *nr; + mlxplat_mux_data[i].base_nr += shift; + if (shift > 0) + mlxplat_hotplug->shift_nr = shift; + } + + return 0; +} + static int __init mlxplat_init(void) { struct mlxplat_priv *priv; - int i, err; + int i, nr, err; if (!dmi_check_system(mlxplat_dmi_table)) return -ENODEV; @@ -866,7 +910,12 @@ static int __init mlxplat_init(void) } platform_set_drvdata(mlxplat_dev, priv); - priv->pdev_i2c = platform_device_register_simple("i2c_mlxcpld", -1, + err = mlxplat_mlxcpld_verify_bus_topology(&nr); + if (nr < 0) + goto fail_alloc; + + nr = (nr == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM) ? -1 : nr; + priv->pdev_i2c = platform_device_register_simple("i2c_mlxcpld", nr, NULL, 0); if (IS_ERR(priv->pdev_i2c)) { err = PTR_ERR(priv->pdev_i2c); diff --git a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h index 262910967476..2744cff1b297 100644 --- a/include/linux/platform_data/mlxreg.h +++ b/include/linux/platform_data/mlxreg.h @@ -130,6 +130,7 @@ struct mlxreg_core_platform_data { * @cell_low: location of low aggregation interrupt register; * @mask_low: low aggregation interrupt common mask; * @deferred_nr: I2C adapter number must be exist prior probing execution; + * @shift_nr: I2C adapter numbers must be incremented by this value; */ struct mlxreg_core_hotplug_platform_data { struct mlxreg_core_item *items; @@ -141,6 +142,7 @@ struct mlxreg_core_hotplug_platform_data { u32 cell_low; u32 mask_low; int deferred_nr; + int shift_nr; }; #endif /* __LINUX_PLATFORM_DATA_MLXREG_H */ From 797195a376dc9ffa0341e64f28f9ffe5d1ed184f Mon Sep 17 00:00:00 2001 From: Jan-Marek Glogowski Date: Mon, 12 Feb 2018 13:08:51 +0100 Subject: [PATCH 36/41] platform/x86: fujitsu-laptop: Support Lifebook U7x7 hotkeys Generate input events for hotkeys present in Fujitsu Lifebook U727 and U757 laptops: - Fn+F1 (KEY_MICMUTE) - Fn+F5 (KEY_RFKILL) Signed-off-by: Jan-Marek Glogowski Reviewed-by: Jonathan Woithe Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/fujitsu-laptop.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 6f4a55a53ced..cd95b6f3a064 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -461,7 +461,9 @@ static const struct key_entry keymap_default[] = { { KE_KEY, KEY3_CODE, { KEY_PROG3 } }, { KE_KEY, KEY4_CODE, { KEY_PROG4 } }, { KE_KEY, KEY5_CODE, { KEY_RFKILL } }, + { KE_KEY, BIT(5), { KEY_RFKILL } }, { KE_KEY, BIT(26), { KEY_TOUCHPAD_TOGGLE } }, + { KE_KEY, BIT(29), { KEY_MICMUTE } }, { KE_END, 0 } }; @@ -901,7 +903,7 @@ static void acpi_fujitsu_laptop_release(struct acpi_device *device) static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event) { struct fujitsu_laptop *priv = acpi_driver_data(device); - int scancode, i = 0; + int scancode, i = 0, ret; unsigned int irb; if (event != ACPI_FUJITSU_NOTIFY_CODE) { @@ -932,9 +934,18 @@ static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event) * E736/E746/E756), the touchpad toggle hotkey (Fn+F4) is * handled in software; its state is queried using FUNC_FLAGS */ - if ((priv->flags_supported & BIT(26)) && - (call_fext_func(device, FUNC_FLAGS, 0x1, 0x0, 0x0) & BIT(26))) - sparse_keymap_report_event(priv->input, BIT(26), 1, true); + if (priv->flags_supported & (BIT(5) | BIT(26) | BIT(29))) { + ret = call_fext_func(device, FUNC_FLAGS, 0x1, 0x0, 0x0); + if (ret & BIT(5)) + sparse_keymap_report_event(priv->input, + BIT(5), 1, true); + if (ret & BIT(26)) + sparse_keymap_report_event(priv->input, + BIT(26), 1, true); + if (ret & BIT(29)) + sparse_keymap_report_event(priv->input, + BIT(29), 1, true); + } } /* Initialization */ From 24e2bb311ff4c8224c0c61fac3a0971d24b54380 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 9 Mar 2018 15:03:58 +0100 Subject: [PATCH 37/41] platform/x86: silead_dmi: Add entry for the Yours Y8W81 tablet Add an entry with touchscreen info for the Yours Y8W81 8" tablet. This tablet has the same case and mostly the same internals as the Chuwi Vi8. Both seem to be from an ODM called inet-tek. Both are labelled: "INET-I86M-REVxx" on the PCB, with the Chuwi Vi8 being REV03 (and having an ALC5640 audio codec) and the Yours Y8W81 being REV21 (and having an ALC5651 audio codec). The wifi, accelerometer and touchscreen are identical on both. Signed-off-by: Hans de Goede Signed-off-by: Andy Shevchenko --- drivers/platform/x86/silead_dmi.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/platform/x86/silead_dmi.c b/drivers/platform/x86/silead_dmi.c index 1091539fa230..452aacabaa8e 100644 --- a/drivers/platform/x86/silead_dmi.c +++ b/drivers/platform/x86/silead_dmi.c @@ -455,6 +455,14 @@ static const struct dmi_system_id silead_ts_dmi_table[] = { DMI_MATCH(DMI_BIOS_VERSION, "itWORKS.G.WI71C.JGBMRB"), }, }, + { + /* Yours Y8W81, same case and touchscreen as Chuwi Vi8 */ + .driver_data = (void *)&chuwi_vi8_data, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "YOURS"), + DMI_MATCH(DMI_PRODUCT_NAME, "Y8W81"), + }, + }, { }, }; From 28e8ed2a01bba317aab9bca1c5609924cbbf6cdc Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Thu, 15 Mar 2018 16:22:51 -0700 Subject: [PATCH 38/41] intel-hid: clean up and sort header files Removed unused header files and sorted them alphabetically. No functional changes are made. Signed-off-by: Alex Hung Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel-hid.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index 5e3df194723e..6b89ec7bc732 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -16,16 +16,14 @@ * */ +#include +#include +#include +#include #include #include -#include -#include #include -#include -#include #include -#include -#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Alex Hung"); From 2b5de0cc1fe0e2308dc1d2494de7917c707bd8ca Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Fri, 30 Mar 2018 16:54:54 -0700 Subject: [PATCH 39/41] intel-hid: support KEY_ROTATE_LOCK_TOGGLE KEY_ROTATE_LOCK_TOGGLE is introduced in 4.16 rc1 and this key event is emitted on Wacom MobileStudio Pro 13. Signed-off-by: Alex Hung Co-developed-by: Jason Gerecke Signed-off-by: Jason Gerecke Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel-hid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index 6b89ec7bc732..b5adba227783 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -65,8 +65,8 @@ static const struct key_entry intel_array_keymap[] = { { KE_IGNORE, 0xC5, { KEY_VOLUMEUP } }, /* Release */ { KE_KEY, 0xC6, { KEY_VOLUMEDOWN } }, /* Press */ { KE_IGNORE, 0xC7, { KEY_VOLUMEDOWN } }, /* Release */ - { KE_SW, 0xC8, { .sw = { SW_ROTATE_LOCK, 1 } } }, /* Press */ - { KE_SW, 0xC9, { .sw = { SW_ROTATE_LOCK, 0 } } }, /* Release */ + { KE_KEY, 0xC8, { KEY_ROTATE_LOCK_TOGGLE } }, /* Press */ + { KE_IGNORE, 0xC9, { KEY_ROTATE_LOCK_TOGGLE } }, /* Release */ { KE_KEY, 0xCE, { KEY_POWER } }, /* Press */ { KE_IGNORE, 0xCF, { KEY_POWER } }, /* Release */ { KE_END }, From 0e5b09b165510e2ea5c526e962c4edadd849ef4c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 16 Mar 2018 15:10:15 +0300 Subject: [PATCH 40/41] platform/x86: dell-smbios: Fix memory leaks in build_tokens_sysfs() We're freeing "value_name" which is NULL, so that's a no-op, but we intended to free "location_name" instead. And then we don't free the names in token_location_attrs[0] and token_value_attrs[0]. Fixes: 33b9ca1e53b4 ("platform/x86: dell-smbios: Add a sysfs interface for SMBIOS tokens") Signed-off-by: Dan Carpenter Signed-off-by: Andy Shevchenko --- drivers/platform/x86/dell-smbios-base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/dell-smbios-base.c b/drivers/platform/x86/dell-smbios-base.c index 2485c80a9fdd..33fb2a20458a 100644 --- a/drivers/platform/x86/dell-smbios-base.c +++ b/drivers/platform/x86/dell-smbios-base.c @@ -514,7 +514,7 @@ static int build_tokens_sysfs(struct platform_device *dev) continue; loop_fail_create_value: - kfree(value_name); + kfree(location_name); goto out_unwind_strings; } smbios_attribute_group.attrs = token_attrs; @@ -525,7 +525,7 @@ loop_fail_create_value: return 0; out_unwind_strings: - for (i = i-1; i > 0; i--) { + while (i--) { kfree(token_location_attrs[i].attr.name); kfree(token_value_attrs[i].attr.name); } From a986c75a7df027d2c649a8f087be9417372cbfb3 Mon Sep 17 00:00:00 2001 From: Alexander Kappner Date: Mon, 2 Apr 2018 11:27:01 -0700 Subject: [PATCH 41/41] platform/x86: thinkpad_acpi: Add 2nd Fan Support for Thinkpad P50 The Thinkpad P50 has 2 fans. Add the 2FAN quirk so the tpacpi driver properly reports both fan speeds. Because the P50 doesn't report the version of its EC controller, we need to identify it by BIOS version (N1). Signed-off-by: Alexander Kappner Acked-by: Henrique de Moraes Holschuh [andy: renamed macro, massaged changelog] Signed-off-by: Andy Shevchenko --- drivers/platform/x86/thinkpad_acpi.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index d5eaf3b1edba..761a0ba98fc9 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -8699,16 +8699,24 @@ static const struct attribute_group fan_attr_group = { .ec = TPID(__id1, __id2), \ .quirks = __quirks } +#define TPACPI_FAN_QB(__id1, __id2, __quirks) \ + { .vendor = PCI_VENDOR_ID_LENOVO, \ + .bios = TPID(__id1, __id2), \ + .ec = TPACPI_MATCH_ANY, \ + .quirks = __quirks } + static const struct tpacpi_quirk fan_quirk_table[] __initconst = { TPACPI_FAN_QI('1', 'Y', TPACPI_FAN_Q1), TPACPI_FAN_QI('7', '8', TPACPI_FAN_Q1), TPACPI_FAN_QI('7', '6', TPACPI_FAN_Q1), TPACPI_FAN_QI('7', '0', TPACPI_FAN_Q1), TPACPI_FAN_QL('7', 'M', TPACPI_FAN_2FAN), + TPACPI_FAN_QB('N', '1', TPACPI_FAN_2FAN), }; #undef TPACPI_FAN_QL #undef TPACPI_FAN_QI +#undef TPACPI_FAN_QB static int __init fan_init(struct ibm_init_struct *iibm) {