Commit 33d42bde authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'platform-drivers-x86-v6.7-3' of...

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
parents f35e4663 3494a594
Loading
Loading
Loading
Loading
+26 −13
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@

#define MLXBF_BOOTCTL_SB_SECURE_MASK		0x03
#define MLXBF_BOOTCTL_SB_TEST_MASK		0x0c
#define MLXBF_BOOTCTL_SB_DEV_MASK		BIT(4)

#define MLXBF_SB_KEY_NUM			4

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

enum {
	MLXBF_BOOTCTL_SB_LIFECYCLE_PRODUCTION = 0,
	MLXBF_BOOTCTL_SB_LIFECYCLE_GA_SECURE = 1,
	MLXBF_BOOTCTL_SB_LIFECYCLE_GA_NON_SECURE = 2,
	MLXBF_BOOTCTL_SB_LIFECYCLE_RMA = 3
};

static const char * const mlxbf_bootctl_lifecycle_states[] = {
	[0] = "Production",
	[1] = "GA Secured",
	[2] = "GA Non-Secured",
	[3] = "RMA",
	[MLXBF_BOOTCTL_SB_LIFECYCLE_PRODUCTION] = "Production",
	[MLXBF_BOOTCTL_SB_LIFECYCLE_GA_SECURE] = "GA Secured",
	[MLXBF_BOOTCTL_SB_LIFECYCLE_GA_NON_SECURE] = "GA Non-Secured",
	[MLXBF_BOOTCTL_SB_LIFECYCLE_RMA] = "RMA",
};

/* Log header format. */
@@ -247,25 +255,30 @@ static ssize_t second_reset_action_store(struct device *dev,
static ssize_t lifecycle_state_show(struct device *dev,
				    struct device_attribute *attr, char *buf)
{
	int status_bits;
	int use_dev_key;
	int test_state;
	int lc_state;

	lc_state = mlxbf_bootctl_smc(MLXBF_BOOTCTL_GET_TBB_FUSE_STATUS,
	status_bits = mlxbf_bootctl_smc(MLXBF_BOOTCTL_GET_TBB_FUSE_STATUS,
					MLXBF_BOOTCTL_FUSE_STATUS_LIFECYCLE);
	if (lc_state < 0)
		return lc_state;
	if (status_bits < 0)
		return status_bits;

	lc_state &=
		MLXBF_BOOTCTL_SB_TEST_MASK | MLXBF_BOOTCTL_SB_SECURE_MASK;
	use_dev_key = status_bits & MLXBF_BOOTCTL_SB_DEV_MASK;
	test_state = status_bits & MLXBF_BOOTCTL_SB_TEST_MASK;
	lc_state = status_bits & MLXBF_BOOTCTL_SB_SECURE_MASK;

	/*
	 * If the test bits are set, we specify that the current state may be
	 * due to using the test bits.
	 */
	if (lc_state & MLXBF_BOOTCTL_SB_TEST_MASK) {
		lc_state &= MLXBF_BOOTCTL_SB_SECURE_MASK;

	if (test_state) {
		return sprintf(buf, "%s(test)\n",
			       mlxbf_bootctl_lifecycle_states[lc_state]);
	} else if (use_dev_key &&
		   (lc_state == MLXBF_BOOTCTL_SB_LIFECYCLE_GA_SECURE)) {
		return sprintf(buf, "Secured (development)\n");
	}

	return sprintf(buf, "%s\n", mlxbf_bootctl_lifecycle_states[lc_state]);
+14 −0
Original line number Diff line number Diff line
@@ -1771,6 +1771,8 @@ static int mlxbf_pmc_init_perftype_counter(struct device *dev, int blk_num)
	attr->dev_attr.show = mlxbf_pmc_event_list_show;
	attr->nr = blk_num;
	attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "event_list");
	if (!attr->dev_attr.attr.name)
		return -ENOMEM;
	pmc->block[blk_num].block_attr[i] = &attr->dev_attr.attr;
	attr = NULL;

@@ -1784,6 +1786,8 @@ static int mlxbf_pmc_init_perftype_counter(struct device *dev, int blk_num)
		attr->nr = blk_num;
		attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
							  "enable");
		if (!attr->dev_attr.attr.name)
			return -ENOMEM;
		pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr;
		attr = NULL;
	}
@@ -1810,6 +1814,8 @@ static int mlxbf_pmc_init_perftype_counter(struct device *dev, int blk_num)
		attr->nr = blk_num;
		attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
							  "counter%d", j);
		if (!attr->dev_attr.attr.name)
			return -ENOMEM;
		pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr;
		attr = NULL;

@@ -1821,6 +1827,8 @@ static int mlxbf_pmc_init_perftype_counter(struct device *dev, int blk_num)
		attr->nr = blk_num;
		attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
							  "event%d", j);
		if (!attr->dev_attr.attr.name)
			return -ENOMEM;
		pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr;
		attr = NULL;
	}
@@ -1853,6 +1861,8 @@ static int mlxbf_pmc_init_perftype_reg(struct device *dev, int blk_num)
		attr->nr = blk_num;
		attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
							  events[j].evt_name);
		if (!attr->dev_attr.attr.name)
			return -ENOMEM;
		pmc->block[blk_num].block_attr[i] = &attr->dev_attr.attr;
		attr = NULL;
		i++;
@@ -1882,6 +1892,8 @@ static int mlxbf_pmc_create_groups(struct device *dev, int blk_num)
	pmc->block[blk_num].block_attr_grp.attrs = pmc->block[blk_num].block_attr;
	pmc->block[blk_num].block_attr_grp.name = devm_kasprintf(
		dev, GFP_KERNEL, pmc->block_name[blk_num]);
	if (!pmc->block[blk_num].block_attr_grp.name)
		return -ENOMEM;
	pmc->groups[pmc->group_num] = &pmc->block[blk_num].block_attr_grp;
	pmc->group_num++;

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

	pmc->hwmon_dev = devm_hwmon_device_register_with_groups(
		dev, "bfperf", pmc, pmc->groups);
	if (IS_ERR(pmc->hwmon_dev))
		return PTR_ERR(pmc->hwmon_dev);
	platform_set_drvdata(pdev, pmc);

	return 0;
+4 −1
Original line number Diff line number Diff line
@@ -231,9 +231,12 @@ static int ssam_receive_buf(struct serdev_device *dev, const unsigned char *buf,
			    size_t n)
{
	struct ssam_controller *ctrl;
	int ret;

	ctrl = serdev_device_get_drvdata(dev);
	return ssam_controller_receive_buf(ctrl, buf, n);
	ret = ssam_controller_receive_buf(ctrl, buf, n);

	return ret < 0 ? 0 : ret;
}

static void ssam_write_wakeup(struct serdev_device *dev)
+1 −1
Original line number Diff line number Diff line
@@ -263,6 +263,7 @@ config ASUS_WMI
	depends on RFKILL || RFKILL = n
	depends on HOTPLUG_PCI
	depends on ACPI_VIDEO || ACPI_VIDEO = n
	depends on SERIO_I8042 || SERIO_I8042 = n
	select INPUT_SPARSEKMAP
	select LEDS_CLASS
	select NEW_LEDS
@@ -279,7 +280,6 @@ config ASUS_WMI
config ASUS_NB_WMI
	tristate "Asus Notebook WMI Driver"
	depends on ASUS_WMI
	depends on SERIO_I8042 || SERIO_I8042 = n
	help
	  This is a driver for newer Asus notebooks. It adds extra features
	  like wireless radio and bluetooth control, leds, hotkeys, backlight...
+38 −23
Original line number Diff line number Diff line
@@ -48,25 +48,43 @@ module_param(tablet_mode_sw, uint, 0444);
MODULE_PARM_DESC(tablet_mode_sw, "Tablet mode detect: -1:auto 0:disable 1:kbd-dock 2:lid-flip 3:lid-flip-rog");

static struct quirk_entry *quirks;
static bool atkbd_reports_vol_keys;

static bool asus_q500a_i8042_filter(unsigned char data, unsigned char str,
			      struct serio *port)
static bool asus_i8042_filter(unsigned char data, unsigned char str, struct serio *port)
{
	static bool extended;
	bool ret = false;
	static bool extended_e0;
	static bool extended_e1;

	if (str & I8042_STR_AUXDATA)
		return false;

	if (unlikely(data == 0xe1)) {
		extended = true;
		ret = true;
	} else if (unlikely(extended)) {
		extended = false;
		ret = true;
	if (quirks->filter_i8042_e1_extended_codes) {
		if (data == 0xe1) {
			extended_e1 = true;
			return true;
		}

	return ret;
		if (extended_e1) {
			extended_e1 = false;
			return true;
		}
	}

	if (data == 0xe0) {
		extended_e0 = true;
	} else if (extended_e0) {
		extended_e0 = false;

		switch (data & 0x7f) {
		case 0x20: /* e0 20 / e0 a0, Volume Mute press / release */
		case 0x2e: /* e0 2e / e0 ae, Volume Down press / release */
		case 0x30: /* e0 30 / e0 b0, Volume Up press / release */
			atkbd_reports_vol_keys = true;
			break;
		}
	}

	return false;
}

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

static struct quirk_entry quirk_asus_q500a = {
	.i8042_filter = asus_q500a_i8042_filter,
	.filter_i8042_e1_extended_codes = true,
	.wmi_backlight_set_devstate = true,
};

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

static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver)
{
	int ret;

	quirks = &quirk_asus_unknown;
	dmi_check_system(asus_quirks);

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

	if (tablet_mode_sw != -1)
		quirks->tablet_switch_mode = tablet_mode_sw;

	if (quirks->i8042_filter) {
		ret = i8042_install_filter(quirks->i8042_filter);
		if (ret) {
			pr_warn("Unable to install key filter\n");
			return;
		}
		pr_info("Using i8042 filter function for receiving events\n");
	}
}

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,
		if (acpi_video_handles_brightness_key_presses())
			*code = ASUS_WMI_KEY_IGNORE;

		break;
	case 0x30: /* Volume Up */
	case 0x31: /* Volume Down */
	case 0x32: /* Volume Mute */
		if (atkbd_reports_vol_keys)
			*code = ASUS_WMI_KEY_IGNORE;

		break;
	}
}
@@ -630,6 +644,7 @@ static struct asus_wmi_driver asus_nb_wmi_driver = {
	.input_phys = ASUS_NB_WMI_FILE "/input0",
	.detect_quirks = asus_nb_wmi_quirks,
	.key_filter = asus_nb_wmi_key_filter,
	.i8042_filter = asus_i8042_filter,
};


Loading