Linux Input/HID development
 help / color / mirror / Atom feed
* Re: [REGRESSION] Sino Wealth 258a:002a keyboard enters stuck shift state on USB disconnect
From: Michal Pecio @ 2026-06-05  9:00 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Orlando Ulises Aguilar Rojas, linux-input, linux-usb,
	benjamin.tissoires
In-Reply-To: <aiJvV_DEOOFcqTtZ@beelink>

On Fri, 5 Jun 2026 09:03:42 +0200, Benjamin Tissoires wrote:
> > Trigger captured via udevadm monitor: when a separate Realtek
> > wireless mouse receiver fires unbind -> remove on the USB bus, the
> > Sino Wealth spurious mouse interface reacts to the hub topology
> > change, emits a short report, and the zero-fill behavior causes the
> > keyboard to output "!@#!@#" (Shift held).  
> 
> That is seriously wrong. It's not uncommon for keyboards to expose a
> mouse node when the support "macros" that you can configure in their
> firmware. That allows them to send button events, or even control the
> mouse.
> 
> That being said, if your keyboard reacts to USB events from other
> devices, then there is something seriously wrong in the firmware.
> 
> In any cases, the fix is not to revert the restored behavior, but to
> fix your bogus device.

It's practically impossible for a USB device to respond to disconnection
of another device, but I recall reports of disconnections apparently
causing corruption of other ongoing transactions. These should complete
with -EPIPE, -EPROTO or similar status then. Possibly the kernel or the
device doesn't handle things rigth.

Perhaps a packet trace from usbmon or Wireshark would help understand
what's going on.

> > Physically unplugging and replugging the
> > keyboard does not clear this state; a system reboot is required to
> > restore normal functionality.

When I disconnect a keyboard while holding the SHIFT key, it turns off.
Is there more to this bug than just failing to ignore bogus reports? 

Regards,
Michal

^ permalink raw reply

* [PATCH] Input: atkbd - skip deactivate for HONOR BCC-N's internal keyboard
From: Cryolitia PukNgae @ 2026-06-05  7:27 UTC (permalink / raw)
  To: Dmitry Torokhov, Hans de Goede
  Cc: linux-input, linux-kernel, zhanjun, niecheng1, Mingcong Bai,
	Kexy Biscuit, kernel, Hongfei Ren, stable, Cryolitia PukNgae

After commit 9cf6e24c9fbf17e52de9fff07f12be7565ea6d61 ("Input: atkbd -
do not skip atkbd_deactivate() when skipping ATKBD_CMD_GETID"), HONOR
BCC-N, aka HONOR MagicBook 14 2026's internal keyboard stops
working. Adding the atkbd_deactivate_fixup quirk fixes it.

DMI: HONOR BCC-N/BCC-N-PCB, BIOS 1.04 04/07/2026

Fixes: 9cf6e24c9fbf17e52de9fff07f12be7565ea6d61 ("Input: atkbd - do not skip atkbd_deactivate() when skipping ATKBD_CMD_GETID")
Reported-by: Hongfei Ren <lcrhf@outlook.com>
Link: https://github.com/colorcube/Linux-on-Honor-Magicbook-14-Pro/issues/1#issuecomment-4562679891
Tested-by: Hongfei Ren <lcrhf@outlook.com>
Cc: stable@kernel.org
Signed-off-by: Cryolitia PukNgae <cryolitia.pukngae@linux.dev>
---
 drivers/input/keyboard/atkbd.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index c8ad55f26ea8..de8edab3cb0f 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -1923,6 +1923,13 @@ static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = {
 		},
 		.callback = atkbd_deactivate_fixup,
 	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HONOR"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "BCC-N"),
+		},
+		.callback = atkbd_deactivate_fixup,
+	},
 	{ }
 };
 

---
base-commit: ddd664bbff63e09e7a7f9acae9c43605d4cf185f
change-id: 20260605-honor-5c3dc4df853b

Best regards,
--  
Cryolitia PukNgae <cryolitia.pukngae@linux.dev>



^ permalink raw reply related

* [PATCH v4 7/7] arm64: dts: allwinner: A133: add support for Baijie Helper A133 board
From: Alexander Sverdlin @ 2026-06-05  7:09 UTC (permalink / raw)
  To: linux-arm-kernel, linux-sunxi
  Cc: Alexander Sverdlin, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Hans de Goede, Dmitry Torokhov, Andre Przywara, Jun Yan,
	Lukas Schmid, J. Neuschäfer, Eric Biggers, Michal Simek,
	Luca Weiss, Sven Peter, Maxime Ripard, devicetree, linux-kernel,
	linux-input
In-Reply-To: <20260605070923.3045073-1-alexander.sverdlin@gmail.com>

Baijie Helper A133 board is a development board around Baijie A133 Core
SBC. Features:

- 1/2/4GiB LPDDR4 DRAM
- 8/16/32GiB eMMC
- AXP707 PMIC
- USB-C OTG port in peripheral mode (via onboard hub)
- 2 USB 2.0 ports
- MicroSD slot and on-board eMMC module
- Gigabit Ethernet
- Bluetooth
- WiFi

Add initial support for both the Helper and Core boards, including UART,
PMU, eMMC, USB, Ethernet, LRADC-connected buttons.

UART1 can only be used for Bluetooth module, but BT-WiFi combo Allwinner
AW869A chip has no mainline driver currently.

Signed-off-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
---
Changelog:
v4:
- renamed "sun50i-a133-baijie-helper.dtb" -> "sun50i-a133-helperboard.dtb"
- added "model" property into root of sun50i-a133-helperboard-core.dtsi
- added "cap-mmc-highspeed" and "max-frequency" into &mmc2
- added "x-powers,drive-vbus-en" and "*-supply" into &axp803
- dropped all "regulator-enable-ramp-delay" properties
- replaced &reg_dcdc3 with a "polyphased" comment
- exact DRAM voltage in &reg_dcdc5
- disabled &reg_dcdc6 to avoid "[   31.710641] dcdc6: disabling"
- added &reg_vdd5v "root" regulator
- added "disable-wp" into &mmc0
- commented &usb_otg
- assigned usb1_vbus-supply in &usbphy
v3:
- added my copyrights into the newly introduced DTs
- all DT nodes sorted alphabetically
- all always-on regulators commented/propetly named
- all regulators got proper voltages (not default ranges)
- ADC-sensed buttons K1..K5 added
- re-labelled "eth_phy" -> "rgmii_phy"
- usbphy 0 switched from host into peripheral mode (downstream from an
  onboard hub)
- typo sun50i-a133-baije-core.dtsi -> sun50i-a133-baijie-core.dtsi
v2:
- introduced baijie,helper-a133-core compatible for the Core (SoM) board

 arch/arm64/boot/dts/allwinner/Makefile        |   1 +
 .../sun50i-a133-helperboard-core.dtsi         | 197 ++++++++++++++++++
 .../dts/allwinner/sun50i-a133-helperboard.dts | 148 +++++++++++++
 3 files changed, 346 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard-core.dtsi
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard.dts

diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index d116864b6c2b..cf8434064b0d 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -18,6 +18,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-sopine-baseboard.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-teres-i.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h64-remix-mini-pc.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a100-allwinner-perf1.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a133-helperboard.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a133-liontron-h-a133l.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-bananapi-m2-plus.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-bananapi-m2-plus-v1.2.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard-core.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard-core.dtsi
new file mode 100644
index 000000000000..545972d2324a
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard-core.dtsi
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2025 Arm Ltd.
+ * Copyright (c) 2026 Alexander Sverdlin <alexander.sverdlin@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "sun50i-a100.dtsi"
+#include "sun50i-a100-cpu-opp.dtsi"
+
+/{
+	model = "Baijie A133 HelperBoard Core";
+	compatible = "baijie,helperboard-a133-core",
+		     "allwinner,sun50i-a100";
+
+	aliases {
+		serial1 = &uart1;	/* BT module */
+	};
+};
+
+&cpu0 {
+	cpu-supply = <&reg_dcdc2>;
+};
+
+&lradc {
+	vref-supply = <&reg_aldo1>;
+};
+
+&mmc2 {
+	vmmc-supply = <&reg_dcdc1>;
+	vqmmc-supply = <&reg_eldo1>;
+	cap-mmc-highspeed;
+	cap-mmc-hw-reset;
+	max-frequency = <100000000>;
+	non-removable;
+	bus-width = <8>;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+	status = "okay";
+};
+
+&pio {
+	vcc-pb-supply = <&reg_dcdc1>;
+	vcc-pc-supply = <&reg_eldo1>;
+	vcc-pd-supply = <&reg_dcdc1>;
+	vcc-pe-supply = <&reg_dldo2>;
+	vcc-pf-supply = <&reg_dcdc1>;
+	vcc-pg-supply = <&reg_dldo1>;
+	vcc-ph-supply = <&reg_dcdc1>;
+	/*
+	 * PL0/PL1 are the I2C connection to PMIC, but it would create a
+	 * circular dependency:
+	 * vcc-pl-supply = <&reg_aldo3>;
+	 */
+};
+
+&r_i2c0 {
+	status = "okay";
+
+	axp803: pmic@34 {
+		compatible = "x-powers,axp803";
+		reg = <0x34>;
+		interrupt-parent = <&r_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		x-powers,drive-vbus-en;		/* set N_VBUSEN as output pin */
+		aldoin-supply = <&reg_vdd5v>;
+		dldoin-supply = <&reg_vdd5v>;
+		eldoin-supply = <&reg_vdd5v>;
+		fldoin-supply = <&reg_dcdc5>;
+		vin1-supply = <&reg_vdd5v>;
+		vin2-supply = <&reg_vdd5v>;
+		vin3-supply = <&reg_vdd5v>;
+		vin4-supply = <&reg_vdd5v>;
+		vin5-supply = <&reg_vdd5v>;
+		vin6-supply = <&reg_vdd5v>;
+		drivevbus-supply = <&reg_vdd5v>;
+	};
+};
+
+#include "axp803.dtsi"
+
+&ac_power_supply {
+	status = "okay";
+};
+
+&reg_aldo1 {
+	/* PLL + LRADC analog reference */
+	regulator-always-on;
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vcc-pll";
+};
+
+&reg_aldo2 {
+	/* LPDDR */
+	regulator-always-on;
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vdd18-lpddr";
+};
+
+&reg_aldo3 {
+	/*
+	 * Port L, but linking it to &pio node would create a circular
+	 * dependency because of PL0/PL1 I2C connection to PMIC
+	 */
+	regulator-always-on;
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vcc-pl";
+};
+
+&reg_dcdc1 {
+	/* Besides Port D it also powers analog part of USB IP and SoC I/O */
+	regulator-always-on;
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-3v3";
+};
+
+&reg_dcdc2 {
+	regulator-always-on;
+	regulator-min-microvolt = <810000>;
+	regulator-max-microvolt = <1200000>;
+	regulator-name = "vdd-cpu";
+};
+
+/* DCDC3 is polyphased with DCDC2 */
+
+&reg_dcdc4 {
+	/* Digital part of USB IP, "System" SoC power rail */
+	regulator-always-on;
+	regulator-min-microvolt = <950000>;
+	regulator-max-microvolt = <950000>;
+	regulator-name = "vdd-sys";
+};
+
+&reg_dcdc5 {
+	regulator-always-on;
+	regulator-min-microvolt = <1100000>;
+	regulator-max-microvolt = <1100000>;
+	regulator-name = "vcc-dram";
+};
+
+/* DCDC6 unused */
+&reg_dcdc6 {
+	status = "disabled";
+};
+
+&reg_dldo1 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vcc-pg";
+};
+
+&reg_dldo2 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vcc-pe";
+};
+
+&reg_dldo3 {
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+	regulator-name = "avdd-csi";
+};
+
+&reg_dldo4 {
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+	regulator-name = "afvcc-csi";
+};
+
+&reg_eldo1 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vcc-pc";
+};
+
+&reg_eldo2 {
+	regulator-min-microvolt = <1200000>;
+	regulator-max-microvolt = <1200000>;
+	regulator-name = "dvdd-csi";
+};
+
+/* ELDO3 unused */
+
+&reg_fldo1 {
+	/* CPUS power rail */
+	regulator-always-on;
+	regulator-min-microvolt = <900000>;
+	regulator-max-microvolt = <900000>;
+	regulator-name = "vdd-cpus";
+};
+
+/* reg_drivevbus unused */
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard.dts
new file mode 100644
index 000000000000..694c0cacf906
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard.dts
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2025 Arm Ltd.
+ * Copyright (c) 2026 Alexander Sverdlin <alexander.sverdlin@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "sun50i-a133-helperboard-core.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/leds/common.h>
+
+/{
+	model = "Baijie HelperBoard A133";
+	compatible = "baijie,helperboard-a133",
+		     "baijie,helperboard-a133-core",
+		     "allwinner,sun50i-a100";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led {
+			function = LED_FUNCTION_INDICATOR;
+			color = <LED_COLOR_ID_GREEN>;
+			gpios = <&pio 7 13 GPIO_ACTIVE_LOW>;	/* PH13 */
+		};
+	};
+
+	reg_vdd5v: vdd5v {
+		/* board wide 5V supply from a 12V->5V regulator */
+		compatible = "regulator-fixed";
+		regulator-name = "vdd-5v";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&emac0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii0_pins>;
+	phy-handle = <&rgmii_phy>;
+	phy-mode = "rgmii-id";
+	allwinner,rx-delay-ps = <200>;
+	allwinner,tx-delay-ps = <200>;
+	status = "okay";
+};
+
+&lradc {
+	wakeup-source;
+	status = "okay";
+
+	button-115 {
+		label = "K1";
+		linux,code = <KEY_1>;
+		channel = <0>;
+		voltage = <114607>;
+	};
+
+	button-235 {
+		label = "K2";
+		linux,code = <KEY_2>;
+		channel = <0>;
+		voltage = <234783>;
+	};
+
+	button-360 {
+		label = "K3";
+		linux,code = <KEY_3>;
+		channel = <0>;
+		voltage = <360000>;
+	};
+
+	button-476 {
+		label = "K4";
+		linux,code = <KEY_4>;
+		channel = <0>;
+		voltage = <476471>;
+	};
+
+	button-592 {
+		label = "K5";
+		linux,code = <KEY_5>;
+		channel = <0>;
+		voltage = <591946>;
+	};
+};
+
+&mdio0 {
+	reset-gpios = <&pio 7 11 GPIO_ACTIVE_LOW>;	/* PH11 */
+	reset-delay-us = <10000>;
+	reset-post-delay-us = <150000>;
+
+	rgmii_phy: ethernet-phy@1 {
+		compatible = "ethernet-phy-ieee802.3-c22";
+		reg = <1>;
+	};
+};
+
+&mmc0 {
+	vmmc-supply = <&reg_dcdc1>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;	/* PF6 */
+	bus-width = <4>;
+	disable-wp;
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&rgmii0_pins {
+	drive-strength = <30>;
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pb_pins>;
+	status = "okay";
+};
+
+&usb_otg {
+	/*
+	 * Connected to a downstream port of an onboard hub, therefore only
+	 * "peripheral" mode will work here.
+	 */
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
+&usbphy {
+	usb1_vbus-supply = <&reg_vdd5v>;
+	status = "okay";
+};
-- 
2.54.0


^ permalink raw reply related

* [PATCH v4 6/7] arm64: dts: allwinner: a100: reserve RAM for ATF
From: Alexander Sverdlin @ 2026-06-05  7:09 UTC (permalink / raw)
  To: linux-arm-kernel, linux-sunxi
  Cc: Alexander Sverdlin, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Hans de Goede, Dmitry Torokhov, Andre Przywara, Jun Yan,
	Lukas Schmid, J. Neuschäfer, Eric Biggers, Michal Simek,
	Luca Weiss, Sven Peter, Maxime Ripard, devicetree, linux-kernel,
	linux-input
In-Reply-To: <20260605070923.3045073-1-alexander.sverdlin@gmail.com>

Add reserved-memory node carving out Trusted Firmware-A region spanning
fixed 256K from physical address 0x40000000. Even though Allwinner ATF
itself passes the address range in the fdt to U-Boot, U-Boot currently
only reserves this memory internally, but doesn't carve out the region
in the fdt passed to Linux.

Signed-off-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
---
Changelog:
v4:
- new patch

 arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
index 7cb06b19b5a5..d8391663fd1d 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
@@ -87,6 +87,22 @@ osc32k: osc32k-clk {
 		#clock-cells = <0>;
 	};
 
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		/*
+		 * 256 KiB reserved for Trusted Firmware-A (BL31).
+		 * This is added by BL31 itself, but some bootloaders fail
+		 * to propagate this into the DTB handed to kernels.
+		 */
+		secmon@40000000 {
+			reg = <0x0 0x40000000 0x0 0x40000>;
+			no-map;
+		};
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13
-- 
2.54.0


^ permalink raw reply related

* [PATCH v4 5/7] arm64: dts: allwinner: a100: Add LRADC node
From: Alexander Sverdlin @ 2026-06-05  7:09 UTC (permalink / raw)
  To: linux-arm-kernel, linux-sunxi
  Cc: Alexander Sverdlin, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Hans de Goede, Dmitry Torokhov, Andre Przywara, Jun Yan,
	Lukas Schmid, J. Neuschäfer, Eric Biggers, Michal Simek,
	Luca Weiss, Sven Peter, Maxime Ripard, devicetree, linux-kernel,
	linux-input
In-Reply-To: <20260605070923.3045073-1-alexander.sverdlin@gmail.com>

A100/A133 SoCs feature a Low Rate ADC (LRADC) for Key application.

Specs:
- Power supply voltage: 1.8 V
- Reference voltage: 1.35 V
- Interrupt support
- Support Hold Key and General Key
- Support normal, continue and single work mode
- 6-bits resolution, sample rate up to 2 kHz
- Voltage input range between 0 and 1.35 V

Signed-off-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
---
Changelog:
v4:
- added allwinner,sun50i-a100-lradc compatible
v3:
- new patch

 arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
index b3fb1e0ee796..7cb06b19b5a5 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
@@ -466,6 +466,15 @@ ths: thermal-sensor@5070400 {
 			#thermal-sensor-cells = <1>;
 		};
 
+		lradc: lradc@5070800 {
+			compatible = "allwinner,sun50i-a100-lradc", "allwinner,sun50i-r329-lradc";
+			reg = <0x05070800 0x400>;
+			interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_LRADC>;
+			resets = <&ccu RST_BUS_LRADC>;
+			status = "disabled";
+		};
+
 		usb_otg: usb@5100000 {
 			compatible = "allwinner,sun50i-a100-musb",
 				     "allwinner,sun8i-a33-musb";
-- 
2.54.0


^ permalink raw reply related

* [PATCH v4 4/7] dt-bindings: input: sun4i-lradc-keys: Add A100/A133 compatible
From: Alexander Sverdlin @ 2026-06-05  7:09 UTC (permalink / raw)
  To: linux-arm-kernel, linux-sunxi
  Cc: Alexander Sverdlin, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Hans de Goede, Dmitry Torokhov, Andre Przywara, Jun Yan,
	Lukas Schmid, J. Neuschäfer, Eric Biggers, Michal Simek,
	Luca Weiss, Sven Peter, Maxime Ripard, devicetree, linux-kernel,
	linux-input
In-Reply-To: <20260605070923.3045073-1-alexander.sverdlin@gmail.com>

The Allwinner A100/A133 SoCs have an LRADC which is compatible with the
versions in existing SoCs. Add a compatible string for A100, with the R329
fallback.

Signed-off-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
---
Changelog:
v4:
- new patch

 .../bindings/input/allwinner,sun4i-a10-lradc-keys.yaml           | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml b/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
index 6bdb8040be65..524c8b51f53f 100644
--- a/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
+++ b/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
@@ -23,6 +23,7 @@ properties:
       - const: allwinner,sun50i-r329-lradc
       - items:
           - enum:
+              - allwinner,sun50i-a100-lradc
               - allwinner,sun50i-h616-lradc
               - allwinner,sun20i-d1-lradc
           - const: allwinner,sun50i-r329-lradc
-- 
2.54.0


^ permalink raw reply related

* [PATCH v4 3/7] dt-bindings: arm: sunxi: Add Baijie HelperBoard A133 compatible
From: Alexander Sverdlin @ 2026-06-05  7:09 UTC (permalink / raw)
  To: linux-arm-kernel, linux-sunxi
  Cc: Alexander Sverdlin, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Hans de Goede, Dmitry Torokhov, Andre Przywara, Jun Yan,
	Lukas Schmid, J. Neuschäfer, Eric Biggers, Michal Simek,
	Luca Weiss, Sven Peter, Maxime Ripard, devicetree, linux-kernel,
	linux-input, Conor Dooley
In-Reply-To: <20260605070923.3045073-1-alexander.sverdlin@gmail.com>

Baijie HelperBoard A133 is a development board around their A133 Core
board. Introduce a compatible for both the Core and the development
boards.

Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
---
Changelog:
v4:
- renamed "Baijie Helper A133" -> "Baijie A133 HelperBoard"
- renamed "baijie,helper-a133" -> "baijie,helperboard-a133"
v3:
- no separate section for "core" .dtsi
v2:
- introduced baijie,helper-a133-core compatible for the Core (SoM) board
 Documentation/devicetree/bindings/arm/sunxi.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
index e6443c266fa1..82dd58b95f8a 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.yaml
+++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
@@ -96,6 +96,12 @@ properties:
           - const: allwinner,ba10-tvbox
           - const: allwinner,sun4i-a10
 
+      - description: Baijie A133 HelperBoard
+        items:
+          - const: baijie,helperboard-a133
+          - const: baijie,helperboard-a133-core
+          - const: allwinner,sun50i-a100
+
       - description: BananaPi
         items:
           - const: lemaker,bananapi
-- 
2.54.0


^ permalink raw reply related

* [PATCH v4 2/7] dt-bindings: vendor-prefixes: Add Shenzhen Baijie Technology Co., Ltd.
From: Alexander Sverdlin @ 2026-06-05  7:09 UTC (permalink / raw)
  To: linux-arm-kernel, linux-sunxi
  Cc: Alexander Sverdlin, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Hans de Goede, Dmitry Torokhov, Andre Przywara, Jun Yan,
	Lukas Schmid, J. Neuschäfer, Eric Biggers, Michal Simek,
	Luca Weiss, Sven Peter, Maxime Ripard, devicetree, linux-kernel,
	linux-input, Conor Dooley, Paul Kocialkowski
In-Reply-To: <20260605070923.3045073-1-alexander.sverdlin@gmail.com>

Shenzhen Baijie Technology Co., Ltd. focuses on R&D and production of
embedded products as well as customization of embedded solutions.

Link: https://szbaijie.com/
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Paul Kocialkowski <paulk@sys-base.io>
Signed-off-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 28784d66ae7b..095cf654787f 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -229,6 +229,8 @@ patternProperties:
     description: Azoteq (Pty) Ltd
   "^azw,.*":
     description: Shenzhen AZW Technology Co., Ltd.
+  "^baijie,.*":
+    description: Shenzhen Baijie Technology Co., Ltd.
   "^baikal,.*":
     description: BAIKAL ELECTRONICS, JSC
   "^bananapi,.*":
-- 
2.54.0


^ permalink raw reply related

* [PATCH v4 1/7] arm64: defconfig: Enable Allwinner LRADC input driver
From: Alexander Sverdlin @ 2026-06-05  7:09 UTC (permalink / raw)
  To: linux-arm-kernel, linux-sunxi
  Cc: Alexander Sverdlin, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Hans de Goede, Dmitry Torokhov, Andre Przywara, Jun Yan,
	Lukas Schmid, J. Neuschäfer, Eric Biggers, Michal Simek,
	Luca Weiss, Sven Peter, Maxime Ripard, devicetree, linux-kernel,
	linux-input
In-Reply-To: <20260605070923.3045073-1-alexander.sverdlin@gmail.com>

Enable Allwinner LRADC input driver as module to support buttons on Baijie
HelperBoard A133.

Signed-off-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
---
Changelog:
v4:
- no changes
v3:
- new patch

 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 96ce783f24e7..faf6d86d0555 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -479,6 +479,7 @@ CONFIG_KEYBOARD_GPIO=y
 CONFIG_KEYBOARD_GPIO_POLLED=m
 CONFIG_KEYBOARD_SNVS_PWRKEY=m
 CONFIG_KEYBOARD_IMX_SC_KEY=m
+CONFIG_KEYBOARD_SUN4I_LRADC=m
 CONFIG_KEYBOARD_CROS_EC=y
 CONFIG_KEYBOARD_MTK_PMIC=m
 CONFIG_MOUSE_ELAN_I2C=m
-- 
2.54.0


^ permalink raw reply related

* [PATCH v4 0/7] Add support for Baijie Helper A133 board
From: Alexander Sverdlin @ 2026-06-05  7:09 UTC (permalink / raw)
  To: linux-arm-kernel, linux-sunxi
  Cc: Alexander Sverdlin, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Hans de Goede, Dmitry Torokhov, Andre Przywara, Jun Yan,
	Lukas Schmid, J. Neuschäfer, Eric Biggers, Michal Simek,
	Luca Weiss, Sven Peter, Maxime Ripard, devicetree, linux-kernel,
	linux-input

Baijie Helper A133 board is a development board around Baijie A133 Core
SBC. Features:

- 1/2/4GiB LPDDR4 DRAM
- 8/16/32GiB eMMC
- AXP707 PMIC
- USB-C OTG port in peripheral mode (via onboard hub)
- 2 USB 2.0 ports
- MicroSD slot and on-board eMMC module
- Gigabit Ethernet
- Bluetooth
- WiFi

Add initial support for both the Helper and Core boards, including UART,
PMU, eMMC, USB, Ethernet, LRADC-connected buttons.

UART1 can only be used for Bluetooth module, but BT-WiFi combo Allwinner
AW869A chip has not mainline driver currently.

Link: https://szbaijie.com/index/product/product_detail.html?product_id=23&language=en

Changelog:
v4:
- reserve RAM for ATF
- sun4i-lradc-keys: Add A100/A133 compatible
- dt-bindings: renamed "Baijie Helper A133" -> "Baijie A133 HelperBoard"
- dt-bindings: renamed "baijie,helper-a133" -> "baijie,helperboard-a133"
- dt-bindings: introduced allwinner,sun50i-a100-lradc
- reserve RAM for ATF
- renamed "sun50i-a133-baijie-helper.dtb" -> "sun50i-a133-helperboard.dtb"
- added "model" property into root of sun50i-a133-helperboard-core.dtsi
- added "cap-mmc-highspeed" and "max-frequency" into &mmc2
- added "x-powers,drive-vbus-en" and "*-supply" into &axp803
- dropped all "regulator-enable-ramp-delay" properties
- replaced &reg_dcdc3 with a "polyphased" comment
- exact DRAM voltage in &reg_dcdc5
- disabled &reg_dcdc6 to avoid "[   31.710641] dcdc6: disabling"
- added &reg_vdd5v "root" regulator
- added "disable-wp" into &mmc0
- commented &usb_otg
- assigned usb1_vbus-supply in &usbphy
v3:
- added lradc node to sun50i-a100.dtsi
- enabled LRADC driver in arm64 defconfig
- added my copyrights into the newly introduced DTs
- all DT nodes sorted alphabetically
- all always-on regulators commented/propetly named
- all regulators got proper voltages (not default ranges)
- ADC-sensed buttons K1..K5 added
- re-labelled "eth_phy" -> "rgmii_phy"
- usbphy 0 switched from host into peripheral mode (downstream from an
  onboard hub)
- typo sun50i-a133-baije-core.dtsi -> sun50i-a133-baijie-core.dtsi
- https://lore.kernel.org/all/20260517234134.2737320-1-alexander.sverdlin@gmail.com/
v2:
- introduced baijie,helper-a133-core compatible for the Core (SoM) board
- https://lore.kernel.org/all/20260510201644.4143710-1-alexander.sverdlin@gmail.com/
v1:
- https://lore.kernel.org/all/20260503191842.2736130-1-alexander.sverdlin@gmail.com/

Alexander Sverdlin (7):
  arm64: defconfig: Enable Allwinner LRADC input driver
  dt-bindings: vendor-prefixes: Add Shenzhen Baijie Technology Co., Ltd.
  dt-bindings: arm: sunxi: Add Baijie HelperBoard A133 compatible
  dt-bindings: input: sun4i-lradc-keys: Add A100/A133 compatible
  arm64: dts: allwinner: a100: Add LRADC node
  arm64: dts: allwinner: a100: reserve RAM for ATF
  arm64: dts: allwinner: A133: add support for Baijie Helper A133 board

 .../devicetree/bindings/arm/sunxi.yaml        |   6 +
 .../input/allwinner,sun4i-a10-lradc-keys.yaml |   1 +
 .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
 arch/arm64/boot/dts/allwinner/Makefile        |   1 +
 .../arm64/boot/dts/allwinner/sun50i-a100.dtsi |  25 +++
 .../sun50i-a133-helperboard-core.dtsi         | 197 ++++++++++++++++++
 .../dts/allwinner/sun50i-a133-helperboard.dts | 148 +++++++++++++
 arch/arm64/configs/defconfig                  |   1 +
 8 files changed, 381 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard-core.dtsi
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard.dts

-- 
2.54.0


^ permalink raw reply

* Re: [PATCH v2 4/4] Input: snvs_pwrkey - report press event in interrupt handler
From: Bough Chen @ 2026-06-05  6:59 UTC (permalink / raw)
  To: Joy Zou
  Cc: Dmitry Torokhov, Frank Li, Peng Fan, Jacky Bai, Ye Li, imx,
	linux-input, linux-kernel
In-Reply-To: <20260604-pwrkey-cleanup-v2-4-59fa0ddf0d7c@nxp.com>

On Thu, Jun 04, 2026 at 02:56:24PM +0800, Joy Zou wrote:
> The driver implements debounce protection using a timer-based mechanism:
> when a key interrupt occurs, a timer is scheduled to verify the key state
> after DEBOUNCE_TIME before reporting the event. This works well during
> normal operation.
> 
> However, key press events can be lost during system resume on platforms
> like i.MX8MQ-EVK because:
> 1. During the no_irq resume phase, PCIe driver restoration can take up to
> 200ms with IRQs disabled.
> 2. The power key interrupt remains pending during the no_irq phase.
> 3. If the key is released before IRQs are re-enabled, the timer eventually
> runs but sees the key as released and skips reporting the event.
> 
> Report key press events directly in interrupt handler to prevent event
> loss during system suspend. This is safe because:
> 
> 1. Only one event is reported per suspend cycle.
> 2. Normal operation retains the existing timer-based debounce mechanism.
> 
> Signed-off-by: Joy Zou <joy.zou@nxp.com>
> ---
> Changes for v2:
> 1. Add a boolean variable suspended and PM callback functions to replace
>    the use of the is_suspended field per AI review comments.
> 2. Move event report handle to else branch in suspended state, since the
>    pdata->minor_rev == 0 branch has no debounce detection per AI review
>    comments.
> 3. Modify the commit message.
> ---
>  drivers/input/keyboard/snvs_pwrkey.c | 35 +++++++++++++++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
> 
> diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c
> index 4a1d04898482669894e9978014b62e4e9774b4e4..f212a6b26185d13e1af62728e7b2add5010adc5a 100644
> --- a/drivers/input/keyboard/snvs_pwrkey.c
> +++ b/drivers/input/keyboard/snvs_pwrkey.c
> @@ -39,6 +39,7 @@ struct pwrkey_drv_data {
>  	int keycode;
>  	int keystate;  /* 1:pressed */
>  	int wakeup;
> +	bool suspended; /* Track suspend state */
>  	struct timer_list check_timer;
>  	struct input_dev *input;
>  	u8 minor_rev;
> @@ -92,6 +93,15 @@ static irqreturn_t imx_snvs_pwrkey_interrupt(int irq, void *dev_id)
>  			input_sync(input);
>  			pm_relax(input->dev.parent);
>  		} else {
> +			/*
> +			 * Report key press events directly in interrupt handler to prevent event
> +			 * loss during system suspend.
> +			 */
> +			if (pdata->suspended) {

Here, pdata->suspended should not be safe for SMP system, maybe to use atomic_read() to make the code more stronger.

> +				pdata->keystate = 1;
> +				input_report_key(input, pdata->keycode, 1);
> +				input_sync(input);
> +			}
>  			mod_timer(&pdata->check_timer,
>  			          jiffies + msecs_to_jiffies(DEBOUNCE_TIME));

Here already report the key when pdata->suspend == true, seems do not need to trigger the timer again.
Is it more reasonable to change like this?
if (atomic_read(&pdata->suspended)) {
	...
} else {
	mode_timer()
}

>  		}
> @@ -219,6 +229,30 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
>  	return 0;
>  }
>  
> +static int __maybe_unused imx_snvs_pwrkey_suspend(struct device *dev)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
> +
> +	pdata->suspended = true;
> +

atomic_set(&pdata->suspended, 1) 

> +	return 0;
> +}
> +
> +static int __maybe_unused imx_snvs_pwrkey_resume(struct device *dev)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
> +
> +	pdata->suspended = false;
> +

atomic_set(&pdata->suspended, 0);

Regards
Haibo Chen
> +	return 0;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(imx_snvs_pwrkey_pm_ops,
> +			 imx_snvs_pwrkey_suspend,
> +			 imx_snvs_pwrkey_resume);
> +
>  static const struct of_device_id imx_snvs_pwrkey_ids[] = {
>  	{ .compatible = "fsl,sec-v4.0-pwrkey" },
>  	{ /* sentinel */ }
> @@ -229,6 +263,7 @@ static struct platform_driver imx_snvs_pwrkey_driver = {
>  	.driver = {
>  		.name = "snvs_pwrkey",
>  		.of_match_table = imx_snvs_pwrkey_ids,
> +		.pm   = &imx_snvs_pwrkey_pm_ops,
>  	},
>  	.probe = imx_snvs_pwrkey_probe,
>  };
> 
> -- 
> 2.50.1
> 

^ permalink raw reply

* Re: [REGRESSION] Sino Wealth 258a:002a keyboard enters stuck shift state on USB disconnect
From: Benjamin Tissoires @ 2026-06-05  7:03 UTC (permalink / raw)
  To: Orlando Ulises Aguilar Rojas; +Cc: linux-input, linux-usb, benjamin.tissoires
In-Reply-To: <CAE=pYEp=RZCeRbAtweZ0_zkPr7cUZUu=uoDRkqko7xduVUMEKA@mail.gmail.com>

Hi,

On Jun 04 2026, Orlando Ulises Aguilar Rojas wrote:
> Hi everyone,
> 
> I am reporting a regression that I first observed in linux-zen
> 7.0.8-zen1. The zen-kernel maintainer (heftig) confirmed that the
> responsible commits also landed in upstream stable 7.0.10, so this is
> not zen-specific:
>   - HID: pass the buffer size to hid_report_raw_event
>   - HID: core: introduce hid_safe_input_report()

This is... surprising:
these commits are restoring the previous behavior that has been running
under linux for the past 20+ years, that was broken by 0a3fe972a7cb
("HID: core: Mitigate potential OOB by removing bogus memset()").

So basically, there was a short period of time in 7.0 (it was introduced
in 7.0-rc5) where the device would have been working fine.

Can you check if kernel v6.18.21 (the last one before 0a3fe972a7cb was
backported to the 6.18 series) was also showing the behavior? I strongly
suspect it will, unless there was a USB change that also triggered this
bug.

anyway...

> 
> 
> --- Summary ---
> 
> A Sino Wealth 258a:002a generic mechanical keyboard (Machenike K500)
> enters a permanent "stuck shift" / modifier ghosting state when any
> other USB device disconnects from the host. This worked flawlessly on
> 7.0.7.

ouch, very much ouch

> 
> --- Root cause ---
> 
> Before these commits, a report where csize < rsize returned -EINVAL
> and was discarded in hid_report_raw_event().
> 
> After the commits, the same condition is silently zero-padded and
> processed. Additionally, drivers/hid/usbhid/hid-core.c was updated to
> call hid_safe_input_report() passing urb->transfer_buffer_length as
> bufsize instead of urb->actual_length. Since the USB transfer
> buffer (typically 64 bytes) is always larger than rsize for this
> device, the new bsize < rsize early-exit guard never fires. The code
> reaches the zero-fill path unconditionally.

Yes. This is expected

> 
> This produces no kernel warnings — dbg_hid is not visible in normal
> dmesg — which is why the fault leaves no trace in the logs.
> 
> 
> --- Affected device ---
> 
> Bus 001 Device XXX: ID 258a:002a Sino Wealth (Machenike K500)
> USB Host: Intel xHCI 0000:00:14.0, port 1-2.2
> 
> This keyboard uses a non-compliant NKRO implementation. It registers a
> spurious mouse interface alongside its real keyboard interfaces:
> 
>   SINO WEALTH Gaming Keyboard        -> input0 (interface 0)
>   SINO WEALTH Gaming Keyboard        -> input1 (interface 1)
>   SINO WEALTH Gaming Keyboard Mouse  -> input1 (interface 1) <- spurious
> 
> That spurious mouse interface has always emitted short/malformed
> reports. Under 7.0.7 those reports were safely discarded. Under 7.0.8+
> they are zero-padded, processed, and produce a modifier key event with
> Shift held.
> 
> 
> --- Exact trigger ---
> 
> The fault occurs at runtime, not at boot. Boot dmesg is structurally
> identical on both kernels.
> 
> Trigger captured via udevadm monitor: when a separate Realtek wireless
> mouse receiver fires unbind -> remove on the USB bus, the Sino Wealth
> spurious mouse interface reacts to the hub topology change, emits a
> short report, and the zero-fill behavior causes the keyboard to output
> "!@#!@#" (Shift held).

That is seriously wrong. It's not uncommon for keyboards to expose a
mouse node when the support "macros" that you can configure in their
firmware. That allows them to send button events, or even control the mouse.

That being said, if your keyboard reacts to USB events from other
devices, then there is something seriously wrong in the firmware.

In any cases, the fix is not to revert the restored behavior, but to fix
your bogus device.

> Physically unplugging and replugging the
> keyboard does not clear this state; a system reboot is required to
> restore normal functionality.
> 
> 
> --- What does NOT mitigate the issue ---
> 
>   - Forcing power/control = on on the device USB path
>   - usbhid.quirks=0x258a:002a:0x00000004 boot parameter
> 
> 
> --- Suggested fix ---
> 
> Reconsider the zero-fill path introduced in hid_report_raw_event():
> the pre-7.0.8 behavior (discard short reports with -EINVAL) was safer
> for devices with non-compliant NKRO implementations that have always
> emitted structurally invalid reports.

No, this is not possible, the behavior was restored because it broke
several devices.

> 
> If the zero-fill behavior is intentional, adding 258a:002a to the HID
> quirks table with a discard-on-short-report quirk would be an
> acceptable mitigation.

Well, you have 2 options actually:
- write a new kernel driver that maps to the device and discards short
  reports emitted on the mouse node
- or write a HID-BPF program (see
  https://libevdev.pages.freedesktop.org/udev-hid-bpf/tutorial.html)
  that does exactly that as well, but it's simpler to debug/implement
  because you don't need a full kernel rebuild.

I don't see the benefit of adding a new generic quirk for fixing 1
device.

If I were you, I would seriously lean toward a HID-BPF program, because
that's much easier to write and test.

Cheers,
Benjamin

> 
> --- System ---
> 
> OS:             CachyOS x86_64
> Working kernel: Linux 7.0.7-zen2-1-zen
> Broken kernel:  Linux 7.0.8-zen1 through 7.0.11-zen (upstream: 7.0.10+)
> CPU:            Intel Core i5-13600KF
> 
> dmesg (working/broken) and udev runtime event logs are available on
> request, or can be viewed in the downstream zen-kernel issue:
> https://github.com/zen-kernel/zen-kernel/issues/414
> 
> Thanks for your time.
> 

^ permalink raw reply

* Re: [PATCH] HID: i2c-hid: Refactor _DSM helper and add i2c-hid-acpi-prp0001 driver
From: sashiko-bot @ 2026-06-05  1:41 UTC (permalink / raw)
  Cc: linux-input, dmitry.torokhov
In-Reply-To: <tencent_9F8936ABE7C35AED6FF779A83DFF2729D005@qq.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Missing `acpi_device_fix_up_power()` before device probe may leave the touchpad unpowered.
- [Low] Compilation error due to omitted parameter name in C function definition.
--

commit a6cad016330e4f17120f69020be7c1d0cb8f3e5d
Author: 谢致邦 (XIE Zhibang) <Yeking@Red54.com>

HID: i2c-hid: Refactor _DSM helper and add i2c-hid-acpi-prp0001 driver

This patch adds a new i2c-hid-acpi-prp0001 driver to support devices with
_HID "PRP0001" that lack the "hid-descr-addr" property but provide the HID
descriptor address via an ACPI _DSM. It also refactors the _DSM helper out
of i2c-hid-acpi.c into a shared header.

> diff --git a/drivers/hid/i2c-hid/i2c-hid-acpi-prp0001.c b/drivers/hid/i2c-hid/i2c-hid-acpi-prp0001.c
> new file mode 100644
> index 0000000000000..35cbbab347acf
> --- /dev/null
> +++ b/drivers/hid/i2c-hid/i2c-hid-acpi-prp0001.c
[ ... ]
> +static int i2c_hid_acpi_prp0001_power_up(struct i2chid_ops *)
> +{

[Severity: Low]
Does omitting the parameter name here cause a compilation error? 

Standard C requires parameter names in function definitions, and omitting
them generally results in a build failure.

> +	/* give the device time to power up */
> +	msleep(250);
> +	return 0;
> +}
[ ... ]
> +	adev = ACPI_COMPANION(dev);
> +	if (!adev)
> +		return -ENODEV;
> +
> +	ret = i2c_hid_acpi_get_descriptor(adev);
> +	if (ret < 0)
> +		return ret;
> +	hid_descriptor_address = ret;
> +

[Severity: High]
Should acpi_device_fix_up_power() be called on the ACPI companion device
before calling i2c_hid_core_probe()?

ACPI I2C HID devices frequently lack the _PSC (Power State Current) object. 
For such devices, standard ACPI PM attach assumes the device is already in
D0 and skips executing the _PS0 method, leaving the device unpowered.

The core i2c-hid-acpi driver explicitly works around this by calling
acpi_device_fix_up_power(). 

Without it here, will affected touchpads remain unpowered and result in I2C
timeouts during probe?

> +	return i2c_hid_core_probe(client, &i2c_hid_acpi_prp0001_ops,
> +				  hid_descriptor_address, 0);
> +}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/tencent_9F8936ABE7C35AED6FF779A83DFF2729D005@qq.com?part=1

^ permalink raw reply

* [PATCH] HID: i2c-hid: Refactor _DSM helper and add i2c-hid-acpi-prp0001 driver
From: 谢致邦 (XIE Zhibang) @ 2026-06-05  1:29 UTC (permalink / raw)
  To: linux-input, hansg, dmitry.torokhov, bentiss, yeking
  Cc: dianders, error27, jikos, kenkinming2002, linux-kernel, raoxu,
	superm1, treapking, u.kleine-koenig,
	谢致邦 (XIE Zhibang)
In-Reply-To: <tencent_F6FC553D1BB737FC00062AD0FEF43C580F0A@qq.com>

Move the _DSM call that gets the HID descriptor address from
i2c-hid-acpi.c into i2c-hid-acpi.h as a static inline so both the ACPI
and the new PRP0001 driver can use it. While refactoring, move the
blacklist check and the _DSM call to the top of probe() to avoid a
pointless alloc when the device is blacklisted or does not implement the
_DSM.

Some devices, for example the Lenovo KaiTian N60d and Inspur CP300L3,
are declared with _HID "PRP0001" and _DSD compatible "hid-over-i2c" but
lack "hid-descr-addr" from the _DSD and provide the HID descriptor
address only through an ACPI _DSM. The OF driver fails to probe them
because it requires hid-descr-addr. Add a new driver that handles these
devices by calling the shared _DSM helper.

Fixes: b33752c30023 ("HID: i2c-hid: Reorganize so ACPI and OF are separate modules")
Signed-off-by: 谢致邦 (XIE Zhibang) <Yeking@Red54.com>
---
 drivers/hid/i2c-hid/Kconfig                | 18 +++++
 drivers/hid/i2c-hid/Makefile               |  1 +
 drivers/hid/i2c-hid/i2c-hid-acpi-prp0001.c | 92 ++++++++++++++++++++++
 drivers/hid/i2c-hid/i2c-hid-acpi.c         | 48 +++--------
 drivers/hid/i2c-hid/i2c-hid-acpi.h         | 32 ++++++++
 5 files changed, 155 insertions(+), 36 deletions(-)
 create mode 100644 drivers/hid/i2c-hid/i2c-hid-acpi-prp0001.c
 create mode 100644 drivers/hid/i2c-hid/i2c-hid-acpi.h

diff --git a/drivers/hid/i2c-hid/Kconfig b/drivers/hid/i2c-hid/Kconfig
index e8d51f410cc1..7db8b2abff78 100644
--- a/drivers/hid/i2c-hid/Kconfig
+++ b/drivers/hid/i2c-hid/Kconfig
@@ -22,6 +22,24 @@ config I2C_HID_ACPI
 	  will be called i2c-hid-acpi.  It will also build/depend on the
 	  module i2c-hid.
 
+config I2C_HID_ACPI_PRP0001
+	tristate "Driver for PRP0001 devices missing hid-descr-addr"
+	depends on ACPI
+	depends on DRM || !DRM
+	select I2C_HID_CORE
+	help
+	  Say Y here if you want support for I2C HID touchpads that
+	  are declared with _HID "PRP0001" and _DSD compatible
+	  "hid-over-i2c" but lack the "hid-descr-addr" property from
+	  the _DSD. The HID descriptor address is instead provided
+	  through an ACPI _DSM. Known affected devices include the
+	  Lenovo KaiTian N60d and Inspur CP300L3.
+
+	  If unsure, say N.
+
+	  This support is also available as a module. If so, the
+	  module will be called i2c-hid-acpi-prp0001.
+
 config I2C_HID_OF
 	tristate "HID over I2C transport layer Open Firmware driver"
 	# No "depends on OF" because this can also be used for manually
diff --git a/drivers/hid/i2c-hid/Makefile b/drivers/hid/i2c-hid/Makefile
index 55bd5e0f35af..da420c1a8ec6 100644
--- a/drivers/hid/i2c-hid/Makefile
+++ b/drivers/hid/i2c-hid/Makefile
@@ -9,6 +9,7 @@ i2c-hid-objs					=  i2c-hid-core.o
 i2c-hid-$(CONFIG_DMI)				+= i2c-hid-dmi-quirks.o
 
 obj-$(CONFIG_I2C_HID_ACPI)			+= i2c-hid-acpi.o
+obj-$(CONFIG_I2C_HID_ACPI_PRP0001)		+= i2c-hid-acpi-prp0001.o
 obj-$(CONFIG_I2C_HID_OF)			+= i2c-hid-of.o
 obj-$(CONFIG_I2C_HID_OF_ELAN)			+= i2c-hid-of-elan.o
 obj-$(CONFIG_I2C_HID_OF_GOODIX)			+= i2c-hid-of-goodix.o
diff --git a/drivers/hid/i2c-hid/i2c-hid-acpi-prp0001.c b/drivers/hid/i2c-hid/i2c-hid-acpi-prp0001.c
new file mode 100644
index 000000000000..35cbbab347ac
--- /dev/null
+++ b/drivers/hid/i2c-hid/i2c-hid-acpi-prp0001.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * HID over I2C driver for PRP0001 devices missing hid-descr-addr
+ *
+ * Some devices, for example the Lenovo KaiTian N60d and Inspur CP300L3, use
+ * _HID "PRP0001" with _DSD compatible "hid-over-i2c" but lack "hid-descr-addr"
+ * from the _DSD. The HID descriptor address is provided only through an ACPI
+ * _DSM. The TPD0 node in the DSDT shows _DSM Function 1 returning 0x20.
+ *
+ * Copyright (C) 2026 谢致邦 (XIE Zhibang) <Yeking@Red54.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#include "i2c-hid.h"
+#include "i2c-hid-acpi.h"
+
+static int i2c_hid_acpi_prp0001_power_up(struct i2chid_ops *)
+{
+	/* give the device time to power up */
+	msleep(250);
+	return 0;
+}
+
+static struct i2chid_ops i2c_hid_acpi_prp0001_ops = {
+	.power_up = i2c_hid_acpi_prp0001_power_up,
+	/*
+	 * No .restore_sequence needed: the _DSM on these devices returns a
+	 * constant (0x20) with no side effects, unlike some PNP0C50 _DSM
+	 * implementations that switch the hardware between PS/2 and I2C modes.
+	 */
+};
+
+static int i2c_hid_acpi_prp0001_probe(struct i2c_client *client)
+{
+	struct device *dev = &client->dev;
+	struct acpi_device *adev;
+	u16 hid_descriptor_address;
+	int ret;
+
+	/* If hid-descr-addr is present, let i2c-hid-of handle it */
+	if (device_property_present(dev, "hid-descr-addr"))
+		return -ENODEV;
+
+	adev = ACPI_COMPANION(dev);
+	if (!adev)
+		return -ENODEV;
+
+	ret = i2c_hid_acpi_get_descriptor(adev);
+	if (ret < 0)
+		return ret;
+	hid_descriptor_address = ret;
+
+	return i2c_hid_core_probe(client, &i2c_hid_acpi_prp0001_ops,
+				  hid_descriptor_address, 0);
+}
+
+static const struct of_device_id i2c_hid_acpi_prp0001_of_match[] = {
+	{ .compatible = "hid-over-i2c" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, i2c_hid_acpi_prp0001_of_match);
+
+static const struct i2c_device_id i2c_hid_acpi_prp0001_id[] = {
+	{ .name = "hid-over-i2c" },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, i2c_hid_acpi_prp0001_id);
+
+static struct i2c_driver i2c_hid_acpi_prp0001_driver = {
+	.driver = {
+		.name	= "i2c_hid_acpi_prp0001",
+		.pm	= &i2c_hid_core_pm,
+		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+		.of_match_table = of_match_ptr(i2c_hid_acpi_prp0001_of_match),
+	},
+
+	.probe		= i2c_hid_acpi_prp0001_probe,
+	.remove		= i2c_hid_core_remove,
+	.shutdown	= i2c_hid_core_shutdown,
+	.id_table	= i2c_hid_acpi_prp0001_id,
+};
+
+module_i2c_driver(i2c_hid_acpi_prp0001_driver);
+
+MODULE_DESCRIPTION("HID over I2C driver for PRP0001 devices missing hid-descr-addr");
+MODULE_AUTHOR("谢致邦 (XIE Zhibang) <Yeking@Red54.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/i2c-hid/i2c-hid-acpi.c b/drivers/hid/i2c-hid/i2c-hid-acpi.c
index abd700a101f4..f0bcfb2663ef 100644
--- a/drivers/hid/i2c-hid/i2c-hid-acpi.c
+++ b/drivers/hid/i2c-hid/i2c-hid-acpi.c
@@ -25,9 +25,9 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pm.h>
-#include <linux/uuid.h>
 
 #include "i2c-hid.h"
+#include "i2c-hid-acpi.h"
 
 struct i2c_hid_acpi {
 	struct i2chid_ops ops;
@@ -48,39 +48,11 @@ static const struct acpi_device_id i2c_hid_acpi_blacklist[] = {
 	{ }
 };
 
-/* HID I²C Device: 3cdff6f7-4267-4555-ad05-b30a3d8938de */
-static guid_t i2c_hid_guid =
-	GUID_INIT(0x3CDFF6F7, 0x4267, 0x4555,
-		  0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE);
-
-static int i2c_hid_acpi_get_descriptor(struct i2c_hid_acpi *ihid_acpi)
-{
-	struct acpi_device *adev = ihid_acpi->adev;
-	acpi_handle handle = acpi_device_handle(adev);
-	union acpi_object *obj;
-	u16 hid_descriptor_address;
-
-	if (acpi_match_device_ids(adev, i2c_hid_acpi_blacklist) == 0)
-		return -ENODEV;
-
-	obj = acpi_evaluate_dsm_typed(handle, &i2c_hid_guid, 1, 1, NULL,
-				      ACPI_TYPE_INTEGER);
-	if (!obj) {
-		acpi_handle_err(handle, "Error _DSM call to get HID descriptor address failed\n");
-		return -ENODEV;
-	}
-
-	hid_descriptor_address = obj->integer.value;
-	ACPI_FREE(obj);
-
-	return hid_descriptor_address;
-}
-
 static void i2c_hid_acpi_restore_sequence(struct i2chid_ops *ops)
 {
 	struct i2c_hid_acpi *ihid_acpi = container_of(ops, struct i2c_hid_acpi, ops);
 
-	i2c_hid_acpi_get_descriptor(ihid_acpi);
+	i2c_hid_acpi_get_descriptor(ihid_acpi->adev);
 }
 
 static void i2c_hid_acpi_shutdown_tail(struct i2chid_ops *ops)
@@ -93,23 +65,27 @@ static void i2c_hid_acpi_shutdown_tail(struct i2chid_ops *ops)
 static int i2c_hid_acpi_probe(struct i2c_client *client)
 {
 	struct device *dev = &client->dev;
+	struct acpi_device *adev = ACPI_COMPANION(dev);
 	struct i2c_hid_acpi *ihid_acpi;
 	u16 hid_descriptor_address;
 	int ret;
 
+	if (acpi_match_device_ids(adev, i2c_hid_acpi_blacklist) == 0)
+		return -ENODEV;
+
+	ret = i2c_hid_acpi_get_descriptor(adev);
+	if (ret < 0)
+		return ret;
+	hid_descriptor_address = ret;
+
 	ihid_acpi = devm_kzalloc(&client->dev, sizeof(*ihid_acpi), GFP_KERNEL);
 	if (!ihid_acpi)
 		return -ENOMEM;
 
-	ihid_acpi->adev = ACPI_COMPANION(dev);
+	ihid_acpi->adev = adev;
 	ihid_acpi->ops.shutdown_tail = i2c_hid_acpi_shutdown_tail;
 	ihid_acpi->ops.restore_sequence = i2c_hid_acpi_restore_sequence;
 
-	ret = i2c_hid_acpi_get_descriptor(ihid_acpi);
-	if (ret < 0)
-		return ret;
-	hid_descriptor_address = ret;
-
 	acpi_device_fix_up_power(ihid_acpi->adev);
 
 	return i2c_hid_core_probe(client, &ihid_acpi->ops,
diff --git a/drivers/hid/i2c-hid/i2c-hid-acpi.h b/drivers/hid/i2c-hid/i2c-hid-acpi.h
new file mode 100644
index 000000000000..8cebbeebcc23
--- /dev/null
+++ b/drivers/hid/i2c-hid/i2c-hid-acpi.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _I2C_HID_ACPI_H
+#define _I2C_HID_ACPI_H
+
+#include <linux/acpi.h>
+#include <linux/uuid.h>
+
+static inline int i2c_hid_acpi_get_descriptor(struct acpi_device *adev)
+{
+	/* HID I²C Device: 3cdff6f7-4267-4555-ad05-b30a3d8938de */
+	static const guid_t i2c_hid_guid =
+		GUID_INIT(0x3CDFF6F7, 0x4267, 0x4555,
+			  0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE);
+
+	acpi_handle handle = acpi_device_handle(adev);
+	union acpi_object *obj;
+	u16 addr;
+
+	obj = acpi_evaluate_dsm_typed(handle, &i2c_hid_guid,
+				      1, 1, NULL, ACPI_TYPE_INTEGER);
+	if (!obj) {
+		acpi_handle_err(handle, "Error _DSM call to get HID descriptor address failed\n");
+		return -ENODEV;
+	}
+
+	addr = obj->integer.value;
+	ACPI_FREE(obj);
+	return addr;
+}
+
+#endif
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH v2 0/4] dt-bindings: remove redundant .txt redirect stubs
From: patchwork-bot+netdevbpf @ 2026-06-05  1:30 UTC (permalink / raw)
  To: Akash Sukhavasi
  Cc: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni, robh,
	krzk+dt, conor+dt, mchehab, olteanv, horms, corbet, skhan,
	dmitry.torokhov, thierry.reding, jonathanh, lee, netdev,
	devicetree, linux-kernel, linux-media, linux-doc, linux-input,
	linux-tegra
In-Reply-To: <20260603-b4-remove-redirect-stubs-v2-0-c8c19876ab64@gmail.com>

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Wed, 03 Jun 2026 15:42:17 -0500 you wrote:
> Several .txt files under Documentation/devicetree/bindings/ contain
> only a redirect notice pointing to a .yaml schema with the same base
> filename in the same directory. These stubs were useful during the
> .txt to .yaml transition but are now redundant, since the .yaml is
> discoverable by name. Meanwhile, other documentation still references
> some of these stubs, forcing readers through an unnecessary extra hop
> to reach the actual schema.
> 
> [...]

Here is the summary with links:
  - [v2,1/4] dt-bindings: net: remove obsolete mdio.txt
    https://git.kernel.org/netdev/net-next/c/ed2b921b542b
  - [v2,2/4] dt-bindings: media: remove obsolete rc.txt
    (no matching commit)
  - [v2,3/4] dt-bindings: net: dsa: remove obsolete dsa.txt
    https://git.kernel.org/netdev/net-next/c/0fbbc19482bd
  - [v2,4/4] dt-bindings: input: remove obsolete matrix-keymap.txt
    (no matching commit)

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* Re: [PATCH] HID: intel-thc-hid: intel-quickspi: reset touch IC on system resume
From: d3z @ 2026-06-04 20:26 UTC (permalink / raw)
  To: even.xu, xinpeng.sun, jikos, bentiss
  Cc: Danny D ., linux-input, linux-kernel, abhishektamboli9,
	sakari.ailus
In-Reply-To: <IA1PR11MB60989CC8623B35747E0EFF7EF4132@IA1PR11MB6098.namprd11.prod.outlook.com>

From: Danny D. <d3z.the.dev@gmail.com>

Hi Even,

Good catch on the missing state restore. I rebuilt with your version and
re-ran the test.

This is exactly your proposal: reset_tic() after thc_dma_configure(),
then qsdev->state = QUICKSPI_ENABLED, with no thc_spi_*_config and no
thc_ltr_*. I built it as a module and swapped it into a clean
linux-surface 6.19.8 on the Surface Pro 10.

It still doesn't survive s2idle - touch is fine at probe, but after one
suspend/resume it's dead again. This time resume() fails outright instead
of coming back quietly broken:

    intel_quickspi 0000:00:10.0: Wait DEVICE_DESCRIPTOR timeout, ret:0
    intel_quickspi 0000:00:10.0: PM: dpm_run_callback(): pci_pm_resume returns -110
    intel_quickspi 0000:00:10.0: PM: failed to resume async: error -110

So reset_tic() can't complete here. It clears the reset handshake, then
times out in quickspi_get_device_descriptor() and the whole resume bails
with -ETIMEDOUT. The device isn't a wake source on this box - "Can't find
wake GPIO resource" - so device_may_wakeup() is false and we're on the
reset path, as expected.

And the timeout is the THC, not the touch IC: across s2idle its SPI
input/output address and read/write config are gone, so reset_tic()'s
descriptor exchange has nothing valid to run against. Reprogram those
first - the thc_spi_input_output_address_config + read_config +
write_config block, same as quickspi_restore(), same as v2 on the no-wake
path - and reset_tic() completes and touch comes back. That's exactly why
v2 reconfigures the THC instead of only resetting the IC.

One more platform note: the SP10 never reaches S3. Firmware only offers
s2idle - mem_sleep is just "[s2idle]", with no "deep" entry to select -
yet the THC still loses its context across plain s2idle. So a reset gated
on S3 would never fire here, which is why it has to run on the ordinary
resume path.

Thanks,
Danny

^ permalink raw reply

* [REGRESSION] Sino Wealth 258a:002a keyboard enters stuck shift state on USB disconnect
From: Orlando Ulises Aguilar Rojas @ 2026-06-04 15:43 UTC (permalink / raw)
  To: linux-input; +Cc: linux-usb, benjamin.tissoires

Hi everyone,

I am reporting a regression that I first observed in linux-zen
7.0.8-zen1. The zen-kernel maintainer (heftig) confirmed that the
responsible commits also landed in upstream stable 7.0.10, so this is
not zen-specific:
  - HID: pass the buffer size to hid_report_raw_event
  - HID: core: introduce hid_safe_input_report()


--- Summary ---

A Sino Wealth 258a:002a generic mechanical keyboard (Machenike K500)
enters a permanent "stuck shift" / modifier ghosting state when any
other USB device disconnects from the host. This worked flawlessly on
7.0.7.

--- Root cause ---

Before these commits, a report where csize < rsize returned -EINVAL
and was discarded in hid_report_raw_event().

After the commits, the same condition is silently zero-padded and
processed. Additionally, drivers/hid/usbhid/hid-core.c was updated to
call hid_safe_input_report() passing urb->transfer_buffer_length as
bufsize instead of urb->actual_length. Since the USB transfer
buffer (typically 64 bytes) is always larger than rsize for this
device, the new bsize < rsize early-exit guard never fires. The code
reaches the zero-fill path unconditionally.

This produces no kernel warnings — dbg_hid is not visible in normal
dmesg — which is why the fault leaves no trace in the logs.


--- Affected device ---

Bus 001 Device XXX: ID 258a:002a Sino Wealth (Machenike K500)
USB Host: Intel xHCI 0000:00:14.0, port 1-2.2

This keyboard uses a non-compliant NKRO implementation. It registers a
spurious mouse interface alongside its real keyboard interfaces:

  SINO WEALTH Gaming Keyboard        -> input0 (interface 0)
  SINO WEALTH Gaming Keyboard        -> input1 (interface 1)
  SINO WEALTH Gaming Keyboard Mouse  -> input1 (interface 1) <- spurious

That spurious mouse interface has always emitted short/malformed
reports. Under 7.0.7 those reports were safely discarded. Under 7.0.8+
they are zero-padded, processed, and produce a modifier key event with
Shift held.


--- Exact trigger ---

The fault occurs at runtime, not at boot. Boot dmesg is structurally
identical on both kernels.

Trigger captured via udevadm monitor: when a separate Realtek wireless
mouse receiver fires unbind -> remove on the USB bus, the Sino Wealth
spurious mouse interface reacts to the hub topology change, emits a
short report, and the zero-fill behavior causes the keyboard to output
"!@#!@#" (Shift held). Physically unplugging and replugging the
keyboard does not clear this state; a system reboot is required to
restore normal functionality.


--- What does NOT mitigate the issue ---

  - Forcing power/control = on on the device USB path
  - usbhid.quirks=0x258a:002a:0x00000004 boot parameter


--- Suggested fix ---

Reconsider the zero-fill path introduced in hid_report_raw_event():
the pre-7.0.8 behavior (discard short reports with -EINVAL) was safer
for devices with non-compliant NKRO implementations that have always
emitted structurally invalid reports.

If the zero-fill behavior is intentional, adding 258a:002a to the HID
quirks table with a discard-on-short-report quirk would be an
acceptable mitigation.

--- System ---

OS:             CachyOS x86_64
Working kernel: Linux 7.0.7-zen2-1-zen
Broken kernel:  Linux 7.0.8-zen1 through 7.0.11-zen (upstream: 7.0.10+)
CPU:            Intel Core i5-13600KF

dmesg (working/broken) and udev runtime event logs are available on
request, or can be viewed in the downstream zen-kernel issue:
https://github.com/zen-kernel/zen-kernel/issues/414

Thanks for your time.

^ permalink raw reply

* Re: [PATCH v14 2/2] HID: cp2112: Configure I2C bus speed from firmware
From: Danny Kaehn @ 2026-06-04 14:23 UTC (permalink / raw)
  To: Benjamin Tissoires; +Cc: sashiko-reviews, dmitry.torokhov, linux-input
In-Reply-To: <ah6MeSb-NlzniiCA@beelink>

Hi Benjamin,

Thanks for the review; will fix the issue pointed out here.

On Tue, Jun 02, 2026 at 09:59:23AM +0200, Benjamin Tissoires wrote:
> On May 20 2026, sashiko-bot@kernel.org wrote:
> > Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
> > 
> > New issues:
> > - [Medium] The driver silently overwrites custom hardware I2C clock speeds with a 100kHz default for devices without firmware nodes.
> > 
> > Pre-existing issues:
> > - [High] Firmware nodes are attached to device structures without holding a reference, leading to a dangling pointer and use-after-free.
> > - [High] The delayed work `gpio_poll_worker` is not canceled in the probe error path, leading to a use-after-free if the probe fails.
> > --
> > 
> > commit 07ff467e4d8df706a7a27476591cd82570fb8287
> > Author: Danny Kaehn <danny.kaehn@plexus.com>
> > 
> >     HID: cp2112: Configure I2C bus speed from firmware
> >     
> >     Now that the I2C adapter on the CP2112 can have an associated firmware
> >     node, set the bus speed based on firmware configuration.
> > 
> > > diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
> > > index e960fc988058f..04379db93571b 100644
> > > --- a/drivers/hid/hid-cp2112.c
> > > +++ b/drivers/hid/hid-cp2112.c
> > [ ... ]
> > > @@ -1308,6 +1309,9 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
...
> > > +	config.clock_speed = cpu_to_be32(timings.bus_freq_hz);
> > 
> > [Severity: Medium]
> > Since use_defaults is set to true, does this overwrite custom hardware I2C
> > clock speeds with a 100kHz default for devices without firmware nodes?
> > 
> > Before this patch, it looks like cp2112_probe() read the current SMBus
> > configuration from the device, only modified retry_time, and wrote it back.
> > This preserved the device's original configured clock speed (which might be
> > set to 400kHz in the EEPROM).
> > 
> > By calling i2c_parse_fw_timings() with an uninitialized local timings
> > struct and use_defaults = true, timings.bus_freq_hz will be
> > unconditionally set to 100kHz if the device lacks a firmware property.
> > 
> > Is it intended to silently downgrade the speed and override user-configured
> > EEPROM settings?
> 
> I think we should fix this:
> i2c_parse_fw_timings(&dev->adap.dev, &timings, false);
> if (timings.bus_freq_hz)
>     config.clock_speed = cpu_to_be32(timings.bus_freq_hz);
>

Yeah, agreed, a good find. The CP2112's default is 100kHz, but
technically possible the bootloader or something has changed it from the
default. Will fix.

> > 
> > [Severity: High]
> > This is a pre-existing issue, but is there a missing cancellation of the
> > delayed work in the probe error path?
> 
> This one would be nice to fix in a follow up patch.
>

(Not planning to include with this patchset for sake of churn, but could
perhaps be fixed separately in the future... I do have a handfull of
other CP2112 patches to send on once these merge).

> > >  
> > >  	ret = cp2112_hid_output(hdev, (u8 *)&config, sizeof(config),
> > 
> > -- 
> > Sashiko AI review · https://sashiko.dev/#/patchset/20260520-cp2112-dt-v14-0-b1b4b6734b6f@plexus.com?part=2
> > 
> 
> Cheers,
> Benjamin

Thanks,

Danny Kaehn


^ permalink raw reply

* Re: [PATCH v14 1/2] HID: cp2112: Add fwnode support
From: Benjamin Tissoires @ 2026-06-04 14:41 UTC (permalink / raw)
  To: Danny Kaehn; +Cc: sashiko-reviews, dmitry.torokhov, linux-input
In-Reply-To: <20260604143104.GB1355442@LNDCL34533.neenah.na.plexus.com>

On Jun 04 2026, Danny Kaehn wrote:
> 
> 
> On Tue, Jun 02, 2026 at 09:55:18AM +0200, Benjamin Tissoires wrote:
> > On May 20 2026, sashiko-bot@kernel.org wrote:
> > > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> > > - [High] Premature release of firmware node references results in use-after-free vulnerabilities when assigning the I2C adapter and GPIO chip firmware nodes.
> > > --
> > > 
> > > commit 3dfaf368e855835bf23009205c4b93a2a070aae1
> > > Author: Danny Kaehn <danny.kaehn@plexus.com>
> > > 
> > > HID: cp2112: Add fwnode support
> > > 
> > > This commit adds firmware node support to describe the CP2112's I2C and
> > > GPIO interfaces. It differentiates between ACPI and DeviceTree bindings,
> > > mapping the child nodes to the respective adapter and gpio_chip devices.
> > > 
> > > > diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
> > > > index 803b883ae8750..e960fc988058f 100644
> > > > --- a/drivers/hid/hid-cp2112.c
> > > > +++ b/drivers/hid/hid-cp2112.c
> > > [ ... ]
> > > > @@ -1226,6 +1241,28 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
> > > >  		return ret;
> > > >  	}
> > > >  
> > > > +	cp2112_fwnode = dev_fwnode(&hdev->dev);
> > > > +	if (is_acpi_device_node(cp2112_fwnode)) {
> > > > +		fwnode_for_each_child_node(cp2112_fwnode, child) {
> > > > +			ret = acpi_get_local_address(ACPI_HANDLE_FWNODE(child), &addr);
> > > > +			if (ret)
> > > > +				continue;
> > > > +
> > > > +			switch (addr) {
> > > > +			case CP2112_I2C_ADR:
> > > > +				device_set_node(&dev->adap.dev, child);
> > > > +				break;
> > > > +			case CP2112_GPIO_ADR:
> > > > +				dev->gc.fwnode = child;
> > > > +				break;
> > > > +			}
> > > 
> > > [Severity: High]
> > > Does this code leave dangling pointers in the device structures?
> > > 
> > > The fwnode_for_each_child_node() macro automatically drops the reference to
> > > the child node when advancing to the next node or exiting the loop.
> > > 
> > > Because device_set_node() and direct pointer assignments do not increment
> > > the reference count, the nodes assigned here could be prematurely freed
> > > resulting in a use-after-free.
> > 
> > Sashiko is overly cautious here. ACPI handles are not refcounted, so we
> > are fine.
> > 
> > That being said, we could unify the OF and ACPI behaviour by calling the
> > noops fwnode_handle_get(child) for ACPI as well and clean them up in
> > cp2112_remove(). This would also shut up the next warning from Sashiko
> > below.
> > 
> > > 
> > > > +		}
> > > > +	} else if (is_of_node(cp2112_fwnode)) {
> > > > +		child = fwnode_get_named_child_node(cp2112_fwnode, "i2c");
> > > > +		device_set_node(&dev->adap.dev, child);
> > > > +		fwnode_handle_put(child);
> > > 
> > > [Severity: High]
> > > Are we releasing the firmware node prematurely here?
> > > 
> > > fwnode_get_named_child_node() returns a node with an incremented reference
> > > count. However, since device_set_node() does not take its own reference on
> > > the child node, dropping the reference immediately after could leave
> > > dev->adap.dev with a dangling pointer if the node is later removed.
> > 
> > OF children are tied to the lifespan of the OF device, so we are fine,
> > but technically incorrect, as mentioned by Sashiko.
> > 
> > If you regroup the 2 behaviours and clean them in cp2112_remove(), this
> > would be cleaner IMO.
> >
> 
> Ack, this is something I've gone back-and-forth on in the revisions of
> this patch. Will update the driver to hold the fwnode reference for the
> I2C subnode.
> 
> However, for the GPIO chip, DT uses the parent node (which shouldn't
> need an increment to the refcount), while ACPI uses a child node. Given

Oh, if they are different, then maybe following that advice is not such
a good idea.

> this discussion, it sounds like I ought to still increment the refcount
> for the GPIO child node to comply to the interface, even though ACPI
> handles aren't refcounted.

Yeah, sashiko says that this is harmless and would provide symetrical
behavior (but artificial)

> This will require another bit of DT/ACPI
> diverging behavior in _remove(), which is fine by me, just announcing
> that intent in case it doesn't match your expectation / might appear as
> a code smell in the follow-up patch.

I thought you would just deref the stored node, so it doesn't matter
whether the original node is a parent or a child. Especially because it
would be a noop for ACPI.

But if there are no way of having a single fwnode_handle_put(node) (per
ref, of course), then maybe we can stick to the current code.

We should probably fix the other speed downgrade from 2/2.

Cheers,
Benjamin

> 
> 
> 
> 
> > Cheers,
> > Benjamin
> > 
> > > -- 
> > > Sashiko AI review � https://sashiko.dev/#/patchset/20260520-cp2112-dt-v14-0-b1b4b6734b6f@plexus.com?part=1
> 
> Thanks,
> 
> Danny Kaehn
> 
> 

^ permalink raw reply

* Re: [PATCH v14 1/2] HID: cp2112: Add fwnode support
From: Danny Kaehn @ 2026-06-04 14:31 UTC (permalink / raw)
  To: Benjamin Tissoires; +Cc: sashiko-reviews, dmitry.torokhov, linux-input
In-Reply-To: <ah6LJw5bgVyrtnyI@beelink>



On Tue, Jun 02, 2026 at 09:55:18AM +0200, Benjamin Tissoires wrote:
> On May 20 2026, sashiko-bot@kernel.org wrote:
> > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> > - [High] Premature release of firmware node references results in use-after-free vulnerabilities when assigning the I2C adapter and GPIO chip firmware nodes.
> > --
> > 
> > commit 3dfaf368e855835bf23009205c4b93a2a070aae1
> > Author: Danny Kaehn <danny.kaehn@plexus.com>
> > 
> > HID: cp2112: Add fwnode support
> > 
> > This commit adds firmware node support to describe the CP2112's I2C and
> > GPIO interfaces. It differentiates between ACPI and DeviceTree bindings,
> > mapping the child nodes to the respective adapter and gpio_chip devices.
> > 
> > > diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
> > > index 803b883ae8750..e960fc988058f 100644
> > > --- a/drivers/hid/hid-cp2112.c
> > > +++ b/drivers/hid/hid-cp2112.c
> > [ ... ]
> > > @@ -1226,6 +1241,28 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
> > >  		return ret;
> > >  	}
> > >  
> > > +	cp2112_fwnode = dev_fwnode(&hdev->dev);
> > > +	if (is_acpi_device_node(cp2112_fwnode)) {
> > > +		fwnode_for_each_child_node(cp2112_fwnode, child) {
> > > +			ret = acpi_get_local_address(ACPI_HANDLE_FWNODE(child), &addr);
> > > +			if (ret)
> > > +				continue;
> > > +
> > > +			switch (addr) {
> > > +			case CP2112_I2C_ADR:
> > > +				device_set_node(&dev->adap.dev, child);
> > > +				break;
> > > +			case CP2112_GPIO_ADR:
> > > +				dev->gc.fwnode = child;
> > > +				break;
> > > +			}
> > 
> > [Severity: High]
> > Does this code leave dangling pointers in the device structures?
> > 
> > The fwnode_for_each_child_node() macro automatically drops the reference to
> > the child node when advancing to the next node or exiting the loop.
> > 
> > Because device_set_node() and direct pointer assignments do not increment
> > the reference count, the nodes assigned here could be prematurely freed
> > resulting in a use-after-free.
> 
> Sashiko is overly cautious here. ACPI handles are not refcounted, so we
> are fine.
> 
> That being said, we could unify the OF and ACPI behaviour by calling the
> noops fwnode_handle_get(child) for ACPI as well and clean them up in
> cp2112_remove(). This would also shut up the next warning from Sashiko
> below.
> 
> > 
> > > +		}
> > > +	} else if (is_of_node(cp2112_fwnode)) {
> > > +		child = fwnode_get_named_child_node(cp2112_fwnode, "i2c");
> > > +		device_set_node(&dev->adap.dev, child);
> > > +		fwnode_handle_put(child);
> > 
> > [Severity: High]
> > Are we releasing the firmware node prematurely here?
> > 
> > fwnode_get_named_child_node() returns a node with an incremented reference
> > count. However, since device_set_node() does not take its own reference on
> > the child node, dropping the reference immediately after could leave
> > dev->adap.dev with a dangling pointer if the node is later removed.
> 
> OF children are tied to the lifespan of the OF device, so we are fine,
> but technically incorrect, as mentioned by Sashiko.
> 
> If you regroup the 2 behaviours and clean them in cp2112_remove(), this
> would be cleaner IMO.
>

Ack, this is something I've gone back-and-forth on in the revisions of
this patch. Will update the driver to hold the fwnode reference for the
I2C subnode.

However, for the GPIO chip, DT uses the parent node (which shouldn't
need an increment to the refcount), while ACPI uses a child node. Given
this discussion, it sounds like I ought to still increment the refcount
for the GPIO child node to comply to the interface, even though ACPI
handles aren't refcounted. This will require another bit of DT/ACPI
diverging behavior in _remove(), which is fine by me, just announcing
that intent in case it doesn't match your expectation / might appear as
a code smell in the follow-up patch.




> Cheers,
> Benjamin
> 
> > -- 
> > Sashiko AI review · https://sashiko.dev/#/patchset/20260520-cp2112-dt-v14-0-b1b4b6734b6f@plexus.com?part=1

Thanks,

Danny Kaehn


^ permalink raw reply

* Re: [PATCH] Input: psmouse-smbus - schedule deferred rescan when adapter present but device not ready
From: sashiko-bot @ 2026-06-04 13:27 UTC (permalink / raw)
  To: Raphaël Larocque; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260604131211.9442-1-rlarocque@disroot.org>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Infinite unbind/rebind loop breaks the PS/2 fallback if the SMBus companion device never responds.
--

commit 18a210ed3c950add4486fdb9a71222e2b1590d6a
Author: Raphaël Larocque <rlarocque@disroot.org>

Input: psmouse-smbus - schedule deferred rescan when adapter present but device not ready

This commit addresses an issue where the SMBus adapter is registered early
but the companion device is not yet responsive. It schedules a deferred
rescan using a delayed work queue to retry the probe without blocking boot.

> diff --git a/drivers/input/mouse/psmouse-smbus.c b/drivers/input/mouse/psmouse-smbus.c
> index 7fb4cbb2aca2f..704d8c2a028ba 100644
> --- a/drivers/input/mouse/psmouse-smbus.c
> +++ b/drivers/input/mouse/psmouse-smbus.c

[ ... ]

> +static void psmouse_smbus_rescan_work_fn(struct work_struct *work)
> +{
> +	struct psmouse_smbus_dev *smbdev =
> +		container_of(to_delayed_work(work),
> +			     struct psmouse_smbus_dev, rescan_work);
>  
>  	guard(mutex)(&psmouse_smbus_mutex);
>  
> +	if (!smbdev->dead && !smbdev->client) {
> +		psmouse_dbg(smbdev->psmouse,
> +			    "SMBus adapter present but device not yet ready, retrying\n");
> +		serio_rescan(smbdev->psmouse->ps2dev.serio);

[Severity: High]
Does this serio_rescan() call introduce an infinite unbind/rebind loop if the
SMBus companion device never responds?

When serio_rescan() triggers, it tears down the PS/2 driver and initiates a
reprobe. During the reprobe, psmouse_smbus_init() runs again.

> +	}
> +}

[ ... ]

> @@ -290,6 +372,18 @@ int psmouse_smbus_init(struct psmouse *psmouse,
>  		}
>  
>  		kfree(smbdev);
> +	} else if (smbdev->adapter_seen) {
> +		/*
> +		 * A HOST_NOTIFY-capable adapter was already registered when we
> +		 * scanned (so BUS_NOTIFY_ADD_DEVICE has already fired for it
> +		 * and won't fire again), but the companion device at 0x2c was
> +		 * not yet responsive — typical of a cold boot on machines like
> +		 * the ThinkPad T440p.  Schedule a deferred rescan so we retry
> +		 * without blocking the boot path, mirroring what
> +		 * psmouse_smbus_check_adapter() does for late-arriving adapters.
> +		 */
> +		queue_delayed_work(psmouse_smbus_wq, &smbdev->rescan_work,
> +				   msecs_to_jiffies(PSMOUSE_SMBUS_RESCAN_DELAY_MS));
>  	}
>  
>  	return error < 0 ? error : -EAGAIN;

[Severity: High]
If the I2C device is permanently unresponsive (e.g. the hardware is physically
wired only for PS/2 despite firmware capabilities), won't the reprobe hit this
path again?

Since a new smbdev is allocated on every probe and there is no persistent
state tracking the retry count, this appears to unconditionally queue the
rescan again.

This would repeatedly destroy and recreate the PS/2 fallback every 1 second,
rendering the touchpad unusable. Can we limit the number of retry attempts or
track the state to avoid this loop?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260604131211.9442-1-rlarocque@disroot.org?part=1

^ permalink raw reply

* [PATCH] Input: psmouse-smbus - schedule deferred rescan when adapter present but device not ready
From: Raphaël Larocque @ 2026-06-04 13:12 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: linux-input, linux-kernel, kees, marco.crivellari,
	Raphaël Larocque

On some machines (e.g.: ThinkPad T440p 20AWS0H800) the Intel LPSS I2C
adapter that hosts the Synaptics RMI4 touchpad is already registered
by the time psmouse probes during early boot.  psmouse_smbus_init()
finds that adapter via i2c_for_each_dev(), but i2c_new_scanned_device()
fails because the device at 0x2c is not yet responsive; -EAGAIN is
returned with breadcrumbs left in psmouse_smbus_list.

Because the adapter is already registered, BUS_NOTIFY_ADD_DEVICE has
already fired for it and will not fire again.  The breadcrumb sits
idle until some other HOST_NOTIFY-capable adapter happens to appear
later and incidentally triggers psmouse_smbus_check_adapter().  When
this happens is non-deterministic: on one boot the rescan fires at
~11 s, on another at ~200 s, on a third never within the observation
window.  The touchpad falls back to PS/2 mode in the interim.

Fix this by scheduling a one-shot deferred serio_rescan() from
psmouse_smbus_init() whenever a HOST_NOTIFY adapter was found but the
companion device was not yet ready.  The work fires asynchronously
(1 s delay) without blocking the boot path, exactly as
psmouse_smbus_check_adapter() already does for late-arriving adapters.
If the device is still not ready on that attempt, a fresh breadcrumb
is left and the work is re-queued, retrying until the device responds.

rescan_work is always INIT_DELAYED_WORK'd so that
cancel_delayed_work_sync() is safe to call unconditionally in all
cleanup paths.  All paths that free a psmouse_smbus_dev are
restructured to release psmouse_smbus_mutex before calling
cancel_delayed_work_sync(), preventing a deadlock with the work
function which also acquires that mutex.

Fixes: 2a02f6c8af14 ("Input: psmouse - fix SMBus companion")
Tested-by: Raphaël Larocque <rlarocque@disroot.org>
Signed-off-by: Raphaël Larocque <rlarocque@disroot.org>
---
 drivers/input/mouse/psmouse-smbus.c | 168 ++++++++++++++++++++++------
 1 file changed, 131 insertions(+), 37 deletions(-)

diff --git a/drivers/input/mouse/psmouse-smbus.c b/drivers/input/mouse/psmouse-smbus.c
index 7fb4cbb2aca2..704d8c2a028b 100644
--- a/drivers/input/mouse/psmouse-smbus.c
+++ b/drivers/input/mouse/psmouse-smbus.c
@@ -21,6 +21,8 @@ struct psmouse_smbus_dev {
 	struct list_head node;
 	bool dead;
 	bool need_deactivate;
+	bool adapter_seen;		/* HOST_NOTIFY adapter found, device not yet ready */
+	struct delayed_work rescan_work;
 };
 
 static LIST_HEAD(psmouse_smbus_list);
@@ -28,6 +30,13 @@ static DEFINE_MUTEX(psmouse_smbus_mutex);
 
 static struct workqueue_struct *psmouse_smbus_wq;
 
+/*
+ * Delay before re-scanning after a HOST_NOTIFY adapter was present but the
+ * companion device did not respond.  The rescan is asynchronous so this does
+ * not add latency to the boot path.
+ */
+#define PSMOUSE_SMBUS_RESCAN_DELAY_MS	1000
+
 static void psmouse_smbus_check_adapter(struct i2c_adapter *adapter)
 {
 	struct psmouse_smbus_dev *smbdev;
@@ -57,32 +66,68 @@ static void psmouse_smbus_check_adapter(struct i2c_adapter *adapter)
 	}
 }
 
-static void psmouse_smbus_detach_i2c_client(struct i2c_client *client)
+/*
+ * psmouse_smbus_rescan_work_fn - deferred rescan when adapter was present
+ * but companion device was not yet ready during psmouse_smbus_init().
+ *
+ * On some machines (e.g. ThinkPad T440p) the LPSS I2C adapter is already
+ * registered by the time psmouse probes, so BUS_NOTIFY_ADD_DEVICE has
+ * already fired and will not fire again.  If the RMI4 device at 0x2c was
+ * not yet responsive at probe time, nothing would ever trigger a rescan.
+ * This work item closes that gap by calling serio_rescan() asynchronously,
+ * exactly as psmouse_smbus_check_adapter() does for late-arriving adapters.
+ */
+static void psmouse_smbus_rescan_work_fn(struct work_struct *work)
 {
-	struct psmouse_smbus_dev *smbdev, *tmp;
+	struct psmouse_smbus_dev *smbdev =
+		container_of(to_delayed_work(work),
+			     struct psmouse_smbus_dev, rescan_work);
 
 	guard(mutex)(&psmouse_smbus_mutex);
 
-	list_for_each_entry_safe(smbdev, tmp, &psmouse_smbus_list, node) {
-		if (smbdev->client != client)
-			continue;
+	if (!smbdev->dead && !smbdev->client) {
+		psmouse_dbg(smbdev->psmouse,
+			    "SMBus adapter present but device not yet ready, retrying\n");
+		serio_rescan(smbdev->psmouse->ps2dev.serio);
+	}
+}
 
-		kfree(client->dev.platform_data);
-		client->dev.platform_data = NULL;
+static void psmouse_smbus_detach_i2c_client(struct i2c_client *client)
+{
+	struct psmouse_smbus_dev *smbdev, *tmp;
+	LIST_HEAD(orphans);
 
-		if (!smbdev->dead) {
-			psmouse_dbg(smbdev->psmouse,
-				    "Marking SMBus companion %s as gone\n",
-				    dev_name(&smbdev->client->dev));
-			smbdev->dead = true;
-			device_link_remove(&smbdev->client->dev,
-					   &smbdev->psmouse->ps2dev.serio->dev);
-			serio_rescan(smbdev->psmouse->ps2dev.serio);
-		} else {
-			list_del(&smbdev->node);
-			kfree(smbdev);
+	scoped_guard(mutex, &psmouse_smbus_mutex) {
+		list_for_each_entry_safe(smbdev, tmp, &psmouse_smbus_list, node) {
+			if (smbdev->client != client)
+				continue;
+
+			kfree(client->dev.platform_data);
+			client->dev.platform_data = NULL;
+
+			if (!smbdev->dead) {
+				psmouse_dbg(smbdev->psmouse,
+					    "Marking SMBus companion %s as gone\n",
+					    dev_name(&smbdev->client->dev));
+				smbdev->dead = true;
+				device_link_remove(&smbdev->client->dev,
+						   &smbdev->psmouse->ps2dev.serio->dev);
+				serio_rescan(smbdev->psmouse->ps2dev.serio);
+			} else {
+				list_del(&smbdev->node);
+				list_add_tail(&smbdev->node, &orphans);
+			}
 		}
 	}
+
+	/*
+	 * Cancel any pending rescan work and free outside the mutex to avoid
+	 * a potential deadlock with the work function.
+	 */
+	list_for_each_entry_safe(smbdev, tmp, &orphans, node) {
+		cancel_delayed_work_sync(&smbdev->rescan_work);
+		kfree(smbdev);
+	}
 }
 
 static int psmouse_smbus_notifier_call(struct notifier_block *nb,
@@ -166,23 +211,29 @@ static void psmouse_smbus_schedule_remove(struct i2c_client *client)
 static void psmouse_smbus_disconnect(struct psmouse *psmouse)
 {
 	struct psmouse_smbus_dev *smbdev = psmouse->private;
+	struct psmouse_smbus_dev *free_smbdev = NULL;
 
-	guard(mutex)(&psmouse_smbus_mutex);
+	scoped_guard(mutex, &psmouse_smbus_mutex) {
+		if (smbdev->dead) {
+			list_del(&smbdev->node);
+			free_smbdev = smbdev;
+		} else {
+			smbdev->dead = true;
+			device_link_remove(&smbdev->client->dev,
+					   &psmouse->ps2dev.serio->dev);
+			psmouse_dbg(smbdev->psmouse,
+				    "posting removal request for SMBus companion %s\n",
+				    dev_name(&smbdev->client->dev));
+			psmouse_smbus_schedule_remove(smbdev->client);
+		}
 
-	if (smbdev->dead) {
-		list_del(&smbdev->node);
-		kfree(smbdev);
-	} else {
-		smbdev->dead = true;
-		device_link_remove(&smbdev->client->dev,
-				   &psmouse->ps2dev.serio->dev);
-		psmouse_dbg(smbdev->psmouse,
-			    "posting removal request for SMBus companion %s\n",
-			    dev_name(&smbdev->client->dev));
-		psmouse_smbus_schedule_remove(smbdev->client);
+		psmouse->private = NULL;
 	}
 
-	psmouse->private = NULL;
+	if (free_smbdev) {
+		cancel_delayed_work_sync(&free_smbdev->rescan_work);
+		kfree(free_smbdev);
+	}
 }
 
 static int psmouse_smbus_create_companion(struct device *dev, void *data)
@@ -199,6 +250,14 @@ static int psmouse_smbus_create_companion(struct device *dev, void *data)
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HOST_NOTIFY))
 		return 0;
 
+	/*
+	 * Remember that a suitable adapter was seen; if the device scan
+	 * below fails (device not yet ready), we know to schedule a deferred
+	 * rescan rather than relying solely on BUS_NOTIFY_ADD_DEVICE (which
+	 * won't fire again for an already-registered adapter).
+	 */
+	smbdev->adapter_seen = true;
+
 	client = i2c_new_scanned_device(adapter, &smbdev->board,
 					addr_list, NULL);
 	if (IS_ERR(client))
@@ -212,15 +271,32 @@ static int psmouse_smbus_create_companion(struct device *dev, void *data)
 void psmouse_smbus_cleanup(struct psmouse *psmouse)
 {
 	struct psmouse_smbus_dev *smbdev, *tmp;
+	LIST_HEAD(orphans);
 
-	guard(mutex)(&psmouse_smbus_mutex);
-
-	list_for_each_entry_safe(smbdev, tmp, &psmouse_smbus_list, node) {
-		if (psmouse == smbdev->psmouse) {
-			list_del(&smbdev->node);
-			kfree(smbdev);
+	scoped_guard(mutex, &psmouse_smbus_mutex) {
+		list_for_each_entry_safe(smbdev, tmp, &psmouse_smbus_list, node) {
+			if (psmouse == smbdev->psmouse) {
+				/*
+				 * Prevent the work function from calling
+				 * serio_rescan() after we release the mutex.
+				 */
+				smbdev->dead = true;
+				list_del(&smbdev->node);
+				list_add_tail(&smbdev->node, &orphans);
+			}
 		}
 	}
+
+	/*
+	 * Cancel any pending rescan work outside the mutex.  The work
+	 * function also takes psmouse_smbus_mutex, so calling
+	 * cancel_delayed_work_sync() under it would deadlock if the work
+	 * happened to be running concurrently.
+	 */
+	list_for_each_entry_safe(smbdev, tmp, &orphans, node) {
+		cancel_delayed_work_sync(&smbdev->rescan_work);
+		kfree(smbdev);
+	}
 }
 
 int psmouse_smbus_init(struct psmouse *psmouse,
@@ -249,6 +325,12 @@ int psmouse_smbus_init(struct psmouse *psmouse,
 		}
 	}
 
+	/*
+	 * Always initialise the delayed work so cancel_delayed_work_sync()
+	 * is safe to call unconditionally in all cleanup paths.
+	 */
+	INIT_DELAYED_WORK(&smbdev->rescan_work, psmouse_smbus_rescan_work_fn);
+
 	if (need_deactivate)
 		psmouse_deactivate(psmouse);
 
@@ -290,6 +372,18 @@ int psmouse_smbus_init(struct psmouse *psmouse,
 		}
 
 		kfree(smbdev);
+	} else if (smbdev->adapter_seen) {
+		/*
+		 * A HOST_NOTIFY-capable adapter was already registered when we
+		 * scanned (so BUS_NOTIFY_ADD_DEVICE has already fired for it
+		 * and won't fire again), but the companion device at 0x2c was
+		 * not yet responsive — typical of a cold boot on machines like
+		 * the ThinkPad T440p.  Schedule a deferred rescan so we retry
+		 * without blocking the boot path, mirroring what
+		 * psmouse_smbus_check_adapter() does for late-arriving adapters.
+		 */
+		queue_delayed_work(psmouse_smbus_wq, &smbdev->rescan_work,
+				   msecs_to_jiffies(PSMOUSE_SMBUS_RESCAN_DELAY_MS));
 	}
 
 	return error < 0 ? error : -EAGAIN;
-- 
2.53.0


^ permalink raw reply related

* Re: [PATCH v14 1/2] HID: cp2112: Add fwnode support
From: Bartosz Golaszewski @ 2026-06-04 12:45 UTC (permalink / raw)
  To: Danny Kaehn
  Cc: Jiri Kosina, linux-input, Dmitry Torokhov, Ethan Twardy,
	linux-i2c, linux-kernel, Leo Huang, Arun D Patil, Willie Thai,
	Ting-Kai Chen, Bartosz Golaszewski, Benjamin Tissoires,
	Andy Shevchenko, Andi Shyti, Conor Dooley
In-Reply-To: <20260520-cp2112-dt-v14-1-b1b4b6734b6f@plexus.com>

On Wed, 20 May 2026 18:13:06 +0200, Danny Kaehn <danny.kaehn@plexus.com> said:
> Support describing the CP2112's I2C and GPIO interfaces in firmware.
>
> Bindings between the firmware nodes and the functions of the device
> are distinct between ACPI and DeviceTree.
>
> For ACPI, the i2c_adapter will use the child with _ADR equal to Zero
> and the gpio_chip will use the child with _ADR equal to One.
>
> For DeviceTree, the i2c_adapter will use the child with name "i2c",
> but the gpio_chip will share a firmware node with the CP2112.
>
> Signed-off-by: Danny Kaehn <danny.kaehn@plexus.com>
> ---

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>

^ permalink raw reply

* [dtor-input:next] BUILD SUCCESS c6f1363abbff69e5bd1cd1fcf060e1510e8d6d31
From: kernel test robot @ 2026-06-04 11:09 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
branch HEAD: c6f1363abbff69e5bd1cd1fcf060e1510e8d6d31  Input: userio - allow setting other id values

elapsed time: 2118m

configs tested: 223
configs skipped: 4

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-15.2.0
alpha                            allyesconfig    gcc-15.2.0
alpha                               defconfig    gcc-16.1.0
arc                              allmodconfig    clang-17
arc                              allmodconfig    gcc-15.2.0
arc                               allnoconfig    gcc-15.2.0
arc                              allyesconfig    clang-23
arc                              allyesconfig    gcc-15.2.0
arc                                 defconfig    gcc-16.1.0
arc                   randconfig-001-20260604    clang-17
arc                   randconfig-002-20260604    clang-17
arm                               allnoconfig    clang-23
arm                               allnoconfig    gcc-15.2.0
arm                              allyesconfig    clang-17
arm                              allyesconfig    gcc-15.2.0
arm                                 defconfig    gcc-16.1.0
arm                   randconfig-001-20260604    clang-17
arm                   randconfig-002-20260604    clang-17
arm                   randconfig-003-20260604    clang-17
arm                   randconfig-004-20260604    clang-17
arm64                            allmodconfig    clang-19
arm64                            allmodconfig    clang-23
arm64                             allnoconfig    gcc-15.2.0
arm64                               defconfig    gcc-16.1.0
arm64                 randconfig-001-20260604    clang-17
arm64                 randconfig-002-20260604    clang-17
arm64                 randconfig-003-20260604    clang-17
arm64                 randconfig-004-20260604    clang-17
csky                             allmodconfig    gcc-15.2.0
csky                             allmodconfig    gcc-16.1.0
csky                              allnoconfig    gcc-15.2.0
csky                                defconfig    gcc-16.1.0
csky                  randconfig-001-20260604    clang-17
csky                  randconfig-002-20260604    clang-17
hexagon                          allmodconfig    clang-17
hexagon                          allmodconfig    gcc-15.2.0
hexagon                           allnoconfig    clang-23
hexagon                           allnoconfig    gcc-15.2.0
hexagon                             defconfig    gcc-16.1.0
hexagon                        randconfig-001    gcc-11.5.0
hexagon               randconfig-001-20260604    gcc-11.5.0
hexagon                        randconfig-002    gcc-11.5.0
hexagon               randconfig-002-20260604    gcc-11.5.0
i386                             allmodconfig    gcc-14
i386                              allnoconfig    gcc-14
i386                              allnoconfig    gcc-15.2.0
i386        buildonly-randconfig-001-20260604    clang-20
i386        buildonly-randconfig-002-20260604    clang-20
i386        buildonly-randconfig-003-20260604    clang-20
i386        buildonly-randconfig-004-20260604    clang-20
i386        buildonly-randconfig-005-20260604    clang-20
i386        buildonly-randconfig-006-20260604    clang-20
i386                                defconfig    gcc-16.1.0
i386                  randconfig-001-20260604    clang-20
i386                  randconfig-002-20260604    clang-20
i386                  randconfig-003-20260604    clang-20
i386                  randconfig-004-20260604    clang-20
i386                  randconfig-005-20260604    clang-20
i386                  randconfig-006-20260604    clang-20
i386                  randconfig-007-20260604    clang-20
i386                  randconfig-011-20260604    gcc-14
i386                  randconfig-012-20260604    gcc-14
i386                  randconfig-013-20260604    gcc-14
i386                  randconfig-014-20260604    gcc-14
i386                  randconfig-015-20260604    gcc-14
i386                  randconfig-016-20260604    gcc-14
i386                  randconfig-017-20260604    gcc-14
loongarch                        allmodconfig    clang-19
loongarch                        allmodconfig    clang-23
loongarch                         allnoconfig    clang-23
loongarch                         allnoconfig    gcc-15.2.0
loongarch                           defconfig    clang-23
loongarch                      randconfig-001    gcc-11.5.0
loongarch             randconfig-001-20260604    gcc-11.5.0
loongarch                      randconfig-002    gcc-11.5.0
loongarch             randconfig-002-20260604    gcc-11.5.0
m68k                             allmodconfig    gcc-15.2.0
m68k                             allmodconfig    gcc-16.1.0
m68k                              allnoconfig    gcc-15.2.0
m68k                             allyesconfig    clang-17
m68k                             allyesconfig    gcc-15.2.0
m68k                                defconfig    clang-23
microblaze                        allnoconfig    gcc-15.2.0
microblaze                       allyesconfig    gcc-15.2.0
microblaze                       allyesconfig    gcc-16.1.0
microblaze                          defconfig    clang-23
mips                             allmodconfig    gcc-15.2.0
mips                              allnoconfig    gcc-15.2.0
mips                             allyesconfig    gcc-15.2.0
mips                             allyesconfig    gcc-16.1.0
nios2                            allmodconfig    gcc-11.5.0
nios2                             allnoconfig    clang-17
nios2                             allnoconfig    gcc-11.5.0
nios2                               defconfig    clang-23
nios2                          randconfig-001    gcc-11.5.0
nios2                 randconfig-001-20260604    gcc-11.5.0
nios2                          randconfig-002    gcc-11.5.0
nios2                 randconfig-002-20260604    gcc-11.5.0
openrisc                         allmodconfig    gcc-16.1.0
openrisc                          allnoconfig    clang-17
openrisc                          allnoconfig    gcc-15.2.0
openrisc                            defconfig    gcc-16.1.0
parisc                           allmodconfig    gcc-15.2.0
parisc                            allnoconfig    clang-17
parisc                            allnoconfig    gcc-15.2.0
parisc                           allyesconfig    clang-19
parisc                           allyesconfig    gcc-15.2.0
parisc                              defconfig    gcc-16.1.0
parisc                         randconfig-001    gcc-8.5.0
parisc                randconfig-001-20260604    gcc-8.5.0
parisc                         randconfig-002    gcc-8.5.0
parisc                randconfig-002-20260604    gcc-8.5.0
parisc64                            defconfig    clang-23
powerpc                          allmodconfig    gcc-15.2.0
powerpc                           allnoconfig    clang-17
powerpc                           allnoconfig    gcc-15.2.0
powerpc                        randconfig-001    gcc-8.5.0
powerpc               randconfig-001-20260604    gcc-8.5.0
powerpc                        randconfig-002    gcc-8.5.0
powerpc               randconfig-002-20260604    gcc-8.5.0
powerpc64                      randconfig-001    gcc-8.5.0
powerpc64             randconfig-001-20260604    gcc-8.5.0
powerpc64                      randconfig-002    gcc-8.5.0
powerpc64             randconfig-002-20260604    gcc-8.5.0
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    clang-17
riscv                             allnoconfig    gcc-15.2.0
riscv                            allyesconfig    clang-16
riscv                            allyesconfig    clang-17
riscv                               defconfig    gcc-16.1.0
riscv                          randconfig-001    clang-17
riscv                 randconfig-001-20260604    clang-17
riscv                          randconfig-002    clang-17
riscv                 randconfig-002-20260604    clang-17
s390                             allmodconfig    clang-18
s390                             allmodconfig    clang-19
s390                              allnoconfig    clang-17
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-15.2.0
s390                                defconfig    gcc-16.1.0
s390                           randconfig-001    clang-17
s390                  randconfig-001-20260604    clang-17
s390                           randconfig-002    clang-17
s390                  randconfig-002-20260604    clang-17
sh                               allmodconfig    gcc-15.2.0
sh                                allnoconfig    clang-17
sh                                allnoconfig    gcc-15.2.0
sh                               allyesconfig    clang-19
sh                               allyesconfig    gcc-15.2.0
sh                                  defconfig    gcc-14
sh                             randconfig-001    clang-17
sh                    randconfig-001-20260604    clang-17
sh                             randconfig-002    clang-17
sh                    randconfig-002-20260604    clang-17
sh                          urquell_defconfig    gcc-16.1.0
sparc                             allnoconfig    clang-17
sparc                             allnoconfig    gcc-15.2.0
sparc                               defconfig    gcc-16.1.0
sparc                          randconfig-001    gcc-11.5.0
sparc                 randconfig-001-20260604    gcc-11.5.0
sparc                          randconfig-002    gcc-11.5.0
sparc                 randconfig-002-20260604    gcc-11.5.0
sparc64                          allmodconfig    clang-20
sparc64                             defconfig    gcc-14
sparc64                        randconfig-001    gcc-11.5.0
sparc64               randconfig-001-20260604    gcc-11.5.0
sparc64                        randconfig-002    gcc-11.5.0
sparc64               randconfig-002-20260604    gcc-11.5.0
um                               allmodconfig    clang-19
um                                allnoconfig    clang-17
um                                allnoconfig    clang-23
um                               allyesconfig    gcc-14
um                               allyesconfig    gcc-15.2.0
um                                  defconfig    gcc-14
um                             i386_defconfig    gcc-14
um                             randconfig-001    gcc-11.5.0
um                    randconfig-001-20260604    gcc-11.5.0
um                             randconfig-002    gcc-11.5.0
um                    randconfig-002-20260604    gcc-11.5.0
um                           x86_64_defconfig    gcc-14
x86_64                           allmodconfig    clang-20
x86_64                            allnoconfig    clang-17
x86_64                            allnoconfig    clang-20
x86_64                           allyesconfig    clang-20
x86_64      buildonly-randconfig-001-20260604    gcc-14
x86_64      buildonly-randconfig-002-20260604    gcc-14
x86_64      buildonly-randconfig-003-20260604    gcc-14
x86_64      buildonly-randconfig-004-20260604    gcc-14
x86_64      buildonly-randconfig-005-20260604    gcc-14
x86_64      buildonly-randconfig-006-20260604    gcc-14
x86_64                              defconfig    gcc-14
x86_64                                  kexec    clang-22
x86_64                randconfig-001-20260604    clang-20
x86_64                randconfig-002-20260604    clang-20
x86_64                randconfig-003-20260604    clang-20
x86_64                randconfig-004-20260604    clang-20
x86_64                randconfig-005-20260604    clang-20
x86_64                randconfig-006-20260604    clang-20
x86_64                randconfig-011-20260604    clang-22
x86_64                randconfig-012-20260604    clang-22
x86_64                randconfig-013-20260604    clang-22
x86_64                randconfig-014-20260604    clang-22
x86_64                randconfig-015-20260604    clang-22
x86_64                randconfig-016-20260604    clang-22
x86_64                randconfig-071-20260604    clang-22
x86_64                randconfig-072-20260604    clang-22
x86_64                randconfig-073-20260604    clang-22
x86_64                randconfig-074-20260604    clang-22
x86_64                randconfig-075-20260604    clang-22
x86_64                randconfig-076-20260604    clang-22
x86_64                               rhel-9.4    clang-22
x86_64                           rhel-9.4-bpf    gcc-14
x86_64                          rhel-9.4-func    clang-22
x86_64                    rhel-9.4-kselftests    clang-22
x86_64                         rhel-9.4-kunit    gcc-14
x86_64                           rhel-9.4-ltp    gcc-14
x86_64                          rhel-9.4-rust    clang-20
xtensa                            allnoconfig    clang-17
xtensa                            allnoconfig    gcc-15.2.0
xtensa                         randconfig-001    gcc-11.5.0
xtensa                randconfig-001-20260604    gcc-11.5.0
xtensa                         randconfig-002    gcc-11.5.0
xtensa                randconfig-002-20260604    gcc-11.5.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [linux-5.15.y 2/3] HID: pass the buffer size to hid_report_raw_event
From: sashiko-bot @ 2026-06-04  9:39 UTC (permalink / raw)
  To: Lee Jones; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260604092659.3953067-2-lee@kernel.org>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] The patch fails to resolve the short report rejection regression for most HID devices because `hid_input_report()` unconditionally sets `bufsize = size`.
- [High] Incorrect `bufsize` argument in `wacom_wac_queue_flush` defeats the mitigation for short reports.
- [Low] Format string mismatch for `size_t` variable `bsize` causes compiler warnings and potential build failures on 32-bit platforms.
--

commit 410a0d731bb14f8c3685faa86ca65503898cc6f0
Author: Benjamin Tissoires <bentiss@kernel.org>

HID: pass the buffer size to hid_report_raw_event

This commit passes the buffer size along with the data size to
hid_report_raw_event() to make a better decision on whether to reject the
buffer or safely memset it to 0 and pass it to the rest of the stack.

> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> index 4fb573ee31b2c..a8d4673c7b8e1 100644
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -1775,8 +1775,8 @@ int __hid_request(struct hid_device *hid, struct hid_report *report,
>  }
>  EXPORT_SYMBOL_GPL(__hid_request);
>  
> -int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
> -		int interrupt)
> +int hid_report_raw_event(struct hid_device *hid, int type, u8 *data,
> +			 size_t bufsize, u32 size, int interrupt)
>  {
>  	struct hid_report_enum *report_enum = hid->report_enum + type;
>  	struct hid_report *report;
> @@ -1784,16 +1784,24 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
>  	int max_buffer_size = HID_MAX_BUFFER_SIZE;
>  	unsigned int a;
>  	u32 rsize, csize = size;
> +	size_t bsize = bufsize;
>  	u8 *cdata = data;
>  	int ret = 0;
>  
>  	report = hid_get_report(report_enum, data);
>  	if (!report)
> -		goto out;
> +		return 0;
> +
> +	if (unlikely(bsize < csize)) {
> +		hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n",
> +				     report->id, csize, bsize);

[Severity: Low]
Does this cause a compiler warning on 32-bit platforms? bsize is a size_t,
but is being printed with the %ld format specifier, which might trigger a
-Wformat warning since size_t is usually an unsigned int on those
architectures. Should this use %zu instead?

> +		return -EINVAL;
> +	}
>  
>  	if (report_enum->numbered) {
>  		cdata++;
>  		csize--;
> +		bsize--;
>  	}
>  
>  	rsize = hid_compute_report_size(report);
> @@ -1806,9 +1814,15 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
>  	else if (rsize > max_buffer_size)
>  		rsize = max_buffer_size;
>  
> +	if (bsize < rsize) {
> +		hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n",
> +				     report->id, rsize, bsize);

[Severity: Low]
This isn't a bug, but there's another instance here where bsize is printed
with %ld instead of %zu.

> +		return -EINVAL;
> +	}
> +
>  	if (csize < rsize) {
>  		dbg_hid("report %d is too short, (%d < %d)\n", report->id,
> -				csize, rsize);
> +			csize, rsize);
>  		memset(cdata + csize, 0, rsize - csize);
>  	}

[ ... ]

> @@ -1851,6 +1865,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, u32 size, int i
>  	struct hid_report_enum *report_enum;
>  	struct hid_driver *hdrv;
>  	struct hid_report *report;
> +	size_t bufsize = size;
>  	int ret = 0;
>  
>  	if (!hid)
> @@ -1889,7 +1904,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, u32 size, int i
>  			goto unlock;
>  	}
>  
> -	ret = hid_report_raw_event(hid, type, data, size, interrupt);
> +	ret = hid_report_raw_event(hid, type, data, bufsize, size, interrupt);

[Severity: High]
Does this defeat the short report mitigation for most devices?

Since hid_input_report() is the primary entry point for HID transport
drivers and lacks a bufsize argument, it sets bufsize equal to size (the
payload length). When a short report is received, this guarantees that
bsize < rsize evaluates to true in hid_report_raw_event().

Will this incorrectly drop valid short reports for most HID devices by
triggering the -EINVAL rejection path?

>  
>  unlock:
>  	up(&hid->driver_input_lock);

[ ... ]

> diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
> index c8a8daedff3d0..1b130ac45acad 100644
> --- a/drivers/hid/wacom_sys.c
> +++ b/drivers/hid/wacom_sys.c
> @@ -79,7 +79,7 @@ static void wacom_wac_queue_flush(struct hid_device *hdev,
>  		int err;
>  
>  		size = kfifo_out(fifo, buf, sizeof(buf));
> -		err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, false);
> +		err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, size, false);

[Severity: High]
Should the bufsize argument here be sizeof(buf) instead of size?

Because bufsize is being passed as the short data length rather than the
true allocated buffer size, hid_report_raw_event() will evaluate
bsize < rsize as true and incorrectly reject valid short wacom reports
with -EINVAL.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260604092659.3953067-2-lee@kernel.org?part=1

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox