Skip to content

Commit 33d42bd

Browse files
committed
Merge tag 'platform-drivers-x86-v6.7-3' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86
Pull x86 platform driver fixes from Ilpo Järvinen: - Fix i8042 filter resource handling, input, and suspend issues in asus-wmi - Skip zero instance WMI blocks to avoid issues with some laptops - Differentiate dev/production keys in mlxbf-bootctl - Correct surface serdev related return value to avoid leaking errno into userspace - Error checking fixes * tag 'platform-drivers-x86-v6.7-3' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: platform/mellanox: Check devm_hwmon_device_register_with_groups() return value platform/mellanox: Add null pointer checks for devm_kasprintf() mlxbf-bootctl: correctly identify secure boot with development keys platform/x86: wmi: Skip blocks with zero instances platform/surface: aggregator: fix recv_buf() return value platform/x86: asus-wmi: disable USB0 hub on ROG Ally before suspend platform/x86: asus-wmi: Filter Volume key presses if also reported via atkbd platform/x86: asus-wmi: Change q500a_i8042_filter() into a generic i8042-filter platform/x86: asus-wmi: Move i8042 filter install to shared asus-wmi code
2 parents f35e466 + 3494a59 commit 33d42bd

File tree

9 files changed

+153
-41
lines changed

9 files changed

+153
-41
lines changed

drivers/platform/mellanox/mlxbf-bootctl.c

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#define MLXBF_BOOTCTL_SB_SECURE_MASK 0x03
2222
#define MLXBF_BOOTCTL_SB_TEST_MASK 0x0c
23+
#define MLXBF_BOOTCTL_SB_DEV_MASK BIT(4)
2324

2425
#define MLXBF_SB_KEY_NUM 4
2526

@@ -40,11 +41,18 @@ static struct mlxbf_bootctl_name boot_names[] = {
4041
{ MLXBF_BOOTCTL_NONE, "none" },
4142
};
4243

44+
enum {
45+
MLXBF_BOOTCTL_SB_LIFECYCLE_PRODUCTION = 0,
46+
MLXBF_BOOTCTL_SB_LIFECYCLE_GA_SECURE = 1,
47+
MLXBF_BOOTCTL_SB_LIFECYCLE_GA_NON_SECURE = 2,
48+
MLXBF_BOOTCTL_SB_LIFECYCLE_RMA = 3
49+
};
50+
4351
static const char * const mlxbf_bootctl_lifecycle_states[] = {
44-
[0] = "Production",
45-
[1] = "GA Secured",
46-
[2] = "GA Non-Secured",
47-
[3] = "RMA",
52+
[MLXBF_BOOTCTL_SB_LIFECYCLE_PRODUCTION] = "Production",
53+
[MLXBF_BOOTCTL_SB_LIFECYCLE_GA_SECURE] = "GA Secured",
54+
[MLXBF_BOOTCTL_SB_LIFECYCLE_GA_NON_SECURE] = "GA Non-Secured",
55+
[MLXBF_BOOTCTL_SB_LIFECYCLE_RMA] = "RMA",
4856
};
4957

5058
/* Log header format. */
@@ -247,25 +255,30 @@ static ssize_t second_reset_action_store(struct device *dev,
247255
static ssize_t lifecycle_state_show(struct device *dev,
248256
struct device_attribute *attr, char *buf)
249257
{
258+
int status_bits;
259+
int use_dev_key;
260+
int test_state;
250261
int lc_state;
251262

252-
lc_state = mlxbf_bootctl_smc(MLXBF_BOOTCTL_GET_TBB_FUSE_STATUS,
253-
MLXBF_BOOTCTL_FUSE_STATUS_LIFECYCLE);
254-
if (lc_state < 0)
255-
return lc_state;
263+
status_bits = mlxbf_bootctl_smc(MLXBF_BOOTCTL_GET_TBB_FUSE_STATUS,
264+
MLXBF_BOOTCTL_FUSE_STATUS_LIFECYCLE);
265+
if (status_bits < 0)
266+
return status_bits;
256267

257-
lc_state &=
258-
MLXBF_BOOTCTL_SB_TEST_MASK | MLXBF_BOOTCTL_SB_SECURE_MASK;
268+
use_dev_key = status_bits & MLXBF_BOOTCTL_SB_DEV_MASK;
269+
test_state = status_bits & MLXBF_BOOTCTL_SB_TEST_MASK;
270+
lc_state = status_bits & MLXBF_BOOTCTL_SB_SECURE_MASK;
259271

260272
/*
261273
* If the test bits are set, we specify that the current state may be
262274
* due to using the test bits.
263275
*/
264-
if (lc_state & MLXBF_BOOTCTL_SB_TEST_MASK) {
265-
lc_state &= MLXBF_BOOTCTL_SB_SECURE_MASK;
266-
276+
if (test_state) {
267277
return sprintf(buf, "%s(test)\n",
268278
mlxbf_bootctl_lifecycle_states[lc_state]);
279+
} else if (use_dev_key &&
280+
(lc_state == MLXBF_BOOTCTL_SB_LIFECYCLE_GA_SECURE)) {
281+
return sprintf(buf, "Secured (development)\n");
269282
}
270283

271284
return sprintf(buf, "%s\n", mlxbf_bootctl_lifecycle_states[lc_state]);

drivers/platform/mellanox/mlxbf-pmc.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,6 +1771,8 @@ static int mlxbf_pmc_init_perftype_counter(struct device *dev, int blk_num)
17711771
attr->dev_attr.show = mlxbf_pmc_event_list_show;
17721772
attr->nr = blk_num;
17731773
attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "event_list");
1774+
if (!attr->dev_attr.attr.name)
1775+
return -ENOMEM;
17741776
pmc->block[blk_num].block_attr[i] = &attr->dev_attr.attr;
17751777
attr = NULL;
17761778

@@ -1784,6 +1786,8 @@ static int mlxbf_pmc_init_perftype_counter(struct device *dev, int blk_num)
17841786
attr->nr = blk_num;
17851787
attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
17861788
"enable");
1789+
if (!attr->dev_attr.attr.name)
1790+
return -ENOMEM;
17871791
pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr;
17881792
attr = NULL;
17891793
}
@@ -1810,6 +1814,8 @@ static int mlxbf_pmc_init_perftype_counter(struct device *dev, int blk_num)
18101814
attr->nr = blk_num;
18111815
attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
18121816
"counter%d", j);
1817+
if (!attr->dev_attr.attr.name)
1818+
return -ENOMEM;
18131819
pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr;
18141820
attr = NULL;
18151821

@@ -1821,6 +1827,8 @@ static int mlxbf_pmc_init_perftype_counter(struct device *dev, int blk_num)
18211827
attr->nr = blk_num;
18221828
attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
18231829
"event%d", j);
1830+
if (!attr->dev_attr.attr.name)
1831+
return -ENOMEM;
18241832
pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr;
18251833
attr = NULL;
18261834
}
@@ -1853,6 +1861,8 @@ static int mlxbf_pmc_init_perftype_reg(struct device *dev, int blk_num)
18531861
attr->nr = blk_num;
18541862
attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
18551863
events[j].evt_name);
1864+
if (!attr->dev_attr.attr.name)
1865+
return -ENOMEM;
18561866
pmc->block[blk_num].block_attr[i] = &attr->dev_attr.attr;
18571867
attr = NULL;
18581868
i++;
@@ -1882,6 +1892,8 @@ static int mlxbf_pmc_create_groups(struct device *dev, int blk_num)
18821892
pmc->block[blk_num].block_attr_grp.attrs = pmc->block[blk_num].block_attr;
18831893
pmc->block[blk_num].block_attr_grp.name = devm_kasprintf(
18841894
dev, GFP_KERNEL, pmc->block_name[blk_num]);
1895+
if (!pmc->block[blk_num].block_attr_grp.name)
1896+
return -ENOMEM;
18851897
pmc->groups[pmc->group_num] = &pmc->block[blk_num].block_attr_grp;
18861898
pmc->group_num++;
18871899

@@ -2063,6 +2075,8 @@ static int mlxbf_pmc_probe(struct platform_device *pdev)
20632075

20642076
pmc->hwmon_dev = devm_hwmon_device_register_with_groups(
20652077
dev, "bfperf", pmc, pmc->groups);
2078+
if (IS_ERR(pmc->hwmon_dev))
2079+
return PTR_ERR(pmc->hwmon_dev);
20662080
platform_set_drvdata(pdev, pmc);
20672081

20682082
return 0;

drivers/platform/surface/aggregator/core.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,12 @@ static int ssam_receive_buf(struct serdev_device *dev, const unsigned char *buf,
231231
size_t n)
232232
{
233233
struct ssam_controller *ctrl;
234+
int ret;
234235

235236
ctrl = serdev_device_get_drvdata(dev);
236-
return ssam_controller_receive_buf(ctrl, buf, n);
237+
ret = ssam_controller_receive_buf(ctrl, buf, n);
238+
239+
return ret < 0 ? 0 : ret;
237240
}
238241

239242
static void ssam_write_wakeup(struct serdev_device *dev)

drivers/platform/x86/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ config ASUS_WMI
263263
depends on RFKILL || RFKILL = n
264264
depends on HOTPLUG_PCI
265265
depends on ACPI_VIDEO || ACPI_VIDEO = n
266+
depends on SERIO_I8042 || SERIO_I8042 = n
266267
select INPUT_SPARSEKMAP
267268
select LEDS_CLASS
268269
select NEW_LEDS
@@ -279,7 +280,6 @@ config ASUS_WMI
279280
config ASUS_NB_WMI
280281
tristate "Asus Notebook WMI Driver"
281282
depends on ASUS_WMI
282-
depends on SERIO_I8042 || SERIO_I8042 = n
283283
help
284284
This is a driver for newer Asus notebooks. It adds extra features
285285
like wireless radio and bluetooth control, leds, hotkeys, backlight...

drivers/platform/x86/asus-nb-wmi.c

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -48,25 +48,43 @@ module_param(tablet_mode_sw, uint, 0444);
4848
MODULE_PARM_DESC(tablet_mode_sw, "Tablet mode detect: -1:auto 0:disable 1:kbd-dock 2:lid-flip 3:lid-flip-rog");
4949

5050
static struct quirk_entry *quirks;
51+
static bool atkbd_reports_vol_keys;
5152

52-
static bool asus_q500a_i8042_filter(unsigned char data, unsigned char str,
53-
struct serio *port)
53+
static bool asus_i8042_filter(unsigned char data, unsigned char str, struct serio *port)
5454
{
55-
static bool extended;
56-
bool ret = false;
55+
static bool extended_e0;
56+
static bool extended_e1;
5757

5858
if (str & I8042_STR_AUXDATA)
5959
return false;
6060

61-
if (unlikely(data == 0xe1)) {
62-
extended = true;
63-
ret = true;
64-
} else if (unlikely(extended)) {
65-
extended = false;
66-
ret = true;
61+
if (quirks->filter_i8042_e1_extended_codes) {
62+
if (data == 0xe1) {
63+
extended_e1 = true;
64+
return true;
65+
}
66+
67+
if (extended_e1) {
68+
extended_e1 = false;
69+
return true;
70+
}
6771
}
6872

69-
return ret;
73+
if (data == 0xe0) {
74+
extended_e0 = true;
75+
} else if (extended_e0) {
76+
extended_e0 = false;
77+
78+
switch (data & 0x7f) {
79+
case 0x20: /* e0 20 / e0 a0, Volume Mute press / release */
80+
case 0x2e: /* e0 2e / e0 ae, Volume Down press / release */
81+
case 0x30: /* e0 30 / e0 b0, Volume Up press / release */
82+
atkbd_reports_vol_keys = true;
83+
break;
84+
}
85+
}
86+
87+
return false;
7088
}
7189

7290
static struct quirk_entry quirk_asus_unknown = {
@@ -75,7 +93,7 @@ static struct quirk_entry quirk_asus_unknown = {
7593
};
7694

7795
static struct quirk_entry quirk_asus_q500a = {
78-
.i8042_filter = asus_q500a_i8042_filter,
96+
.filter_i8042_e1_extended_codes = true,
7997
.wmi_backlight_set_devstate = true,
8098
};
8199

@@ -503,8 +521,6 @@ static const struct dmi_system_id asus_quirks[] = {
503521

504522
static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver)
505523
{
506-
int ret;
507-
508524
quirks = &quirk_asus_unknown;
509525
dmi_check_system(asus_quirks);
510526

@@ -519,15 +535,6 @@ static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver)
519535

520536
if (tablet_mode_sw != -1)
521537
quirks->tablet_switch_mode = tablet_mode_sw;
522-
523-
if (quirks->i8042_filter) {
524-
ret = i8042_install_filter(quirks->i8042_filter);
525-
if (ret) {
526-
pr_warn("Unable to install key filter\n");
527-
return;
528-
}
529-
pr_info("Using i8042 filter function for receiving events\n");
530-
}
531538
}
532539

533540
static const struct key_entry asus_nb_wmi_keymap[] = {
@@ -617,6 +624,13 @@ static void asus_nb_wmi_key_filter(struct asus_wmi_driver *asus_wmi, int *code,
617624
if (acpi_video_handles_brightness_key_presses())
618625
*code = ASUS_WMI_KEY_IGNORE;
619626

627+
break;
628+
case 0x30: /* Volume Up */
629+
case 0x31: /* Volume Down */
630+
case 0x32: /* Volume Mute */
631+
if (atkbd_reports_vol_keys)
632+
*code = ASUS_WMI_KEY_IGNORE;
633+
620634
break;
621635
}
622636
}
@@ -630,6 +644,7 @@ static struct asus_wmi_driver asus_nb_wmi_driver = {
630644
.input_phys = ASUS_NB_WMI_FILE "/input0",
631645
.detect_quirks = asus_nb_wmi_quirks,
632646
.key_filter = asus_nb_wmi_key_filter,
647+
.i8042_filter = asus_i8042_filter,
633648
};
634649

635650

drivers/platform/x86/asus-wmi.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/acpi.h>
1717
#include <linux/backlight.h>
1818
#include <linux/debugfs.h>
19+
#include <linux/delay.h>
1920
#include <linux/dmi.h>
2021
#include <linux/fb.h>
2122
#include <linux/hwmon.h>
@@ -132,6 +133,11 @@ module_param(fnlock_default, bool, 0444);
132133
#define ASUS_SCREENPAD_BRIGHT_MAX 255
133134
#define ASUS_SCREENPAD_BRIGHT_DEFAULT 60
134135

136+
/* Controls the power state of the USB0 hub on ROG Ally which input is on */
137+
#define ASUS_USB0_PWR_EC0_CSEE "\\_SB.PCI0.SBRG.EC0.CSEE"
138+
/* 300ms so far seems to produce a reliable result on AC and battery */
139+
#define ASUS_USB0_PWR_EC0_CSEE_WAIT 300
140+
135141
static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL };
136142

137143
static int throttle_thermal_policy_write(struct asus_wmi *);
@@ -300,6 +306,9 @@ struct asus_wmi {
300306

301307
bool fnlock_locked;
302308

309+
/* The ROG Ally device requires the MCU USB device be disconnected before suspend */
310+
bool ally_mcu_usb_switch;
311+
303312
struct asus_wmi_debug debug;
304313

305314
struct asus_wmi_driver *driver;
@@ -4488,6 +4497,8 @@ static int asus_wmi_add(struct platform_device *pdev)
44884497
asus->nv_temp_tgt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_NV_THERM_TARGET);
44894498
asus->panel_overdrive_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PANEL_OD);
44904499
asus->mini_led_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE);
4500+
asus->ally_mcu_usb_switch = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE)
4501+
&& dmi_match(DMI_BOARD_NAME, "RC71L");
44914502

44924503
err = fan_boost_mode_check_present(asus);
44934504
if (err)
@@ -4567,6 +4578,12 @@ static int asus_wmi_add(struct platform_device *pdev)
45674578
goto fail_wmi_handler;
45684579
}
45694580

4581+
if (asus->driver->i8042_filter) {
4582+
err = i8042_install_filter(asus->driver->i8042_filter);
4583+
if (err)
4584+
pr_warn("Unable to install key filter - %d\n", err);
4585+
}
4586+
45704587
asus_wmi_battery_init(asus);
45714588

45724589
asus_wmi_debugfs_init(asus);
@@ -4603,6 +4620,8 @@ static int asus_wmi_remove(struct platform_device *device)
46034620
struct asus_wmi *asus;
46044621

46054622
asus = platform_get_drvdata(device);
4623+
if (asus->driver->i8042_filter)
4624+
i8042_remove_filter(asus->driver->i8042_filter);
46064625
wmi_remove_notify_handler(asus->driver->event_guid);
46074626
asus_wmi_backlight_exit(asus);
46084627
asus_screenpad_exit(asus);
@@ -4654,6 +4673,43 @@ static int asus_hotk_resume(struct device *device)
46544673
asus_wmi_fnlock_update(asus);
46554674

46564675
asus_wmi_tablet_mode_get_state(asus);
4676+
4677+
return 0;
4678+
}
4679+
4680+
static int asus_hotk_resume_early(struct device *device)
4681+
{
4682+
struct asus_wmi *asus = dev_get_drvdata(device);
4683+
4684+
if (asus->ally_mcu_usb_switch) {
4685+
if (ACPI_FAILURE(acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, 0xB8)))
4686+
dev_err(device, "ROG Ally MCU failed to connect USB dev\n");
4687+
else
4688+
msleep(ASUS_USB0_PWR_EC0_CSEE_WAIT);
4689+
}
4690+
return 0;
4691+
}
4692+
4693+
static int asus_hotk_prepare(struct device *device)
4694+
{
4695+
struct asus_wmi *asus = dev_get_drvdata(device);
4696+
int result, err;
4697+
4698+
if (asus->ally_mcu_usb_switch) {
4699+
/* When powersave is enabled it causes many issues with resume of USB hub */
4700+
result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_MCU_POWERSAVE);
4701+
if (result == 1) {
4702+
dev_warn(device, "MCU powersave enabled, disabling to prevent resume issues");
4703+
err = asus_wmi_set_devstate(ASUS_WMI_DEVID_MCU_POWERSAVE, 0, &result);
4704+
if (err || result != 1)
4705+
dev_err(device, "Failed to set MCU powersave mode: %d\n", err);
4706+
}
4707+
/* sleep required to ensure USB0 is disabled before sleep continues */
4708+
if (ACPI_FAILURE(acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, 0xB7)))
4709+
dev_err(device, "ROG Ally MCU failed to disconnect USB dev\n");
4710+
else
4711+
msleep(ASUS_USB0_PWR_EC0_CSEE_WAIT);
4712+
}
46574713
return 0;
46584714
}
46594715

@@ -4701,6 +4757,8 @@ static const struct dev_pm_ops asus_pm_ops = {
47014757
.thaw = asus_hotk_thaw,
47024758
.restore = asus_hotk_restore,
47034759
.resume = asus_hotk_resume,
4760+
.resume_early = asus_hotk_resume_early,
4761+
.prepare = asus_hotk_prepare,
47044762
};
47054763

47064764
/* Registration ***************************************************************/

0 commit comments

Comments
 (0)