Re: [PATCH] platform/x86: ideapad-laptop: Stop calling i8042_command()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 05 Aug 2024 at 16:16:08 +0200, Hans de Goede wrote:
> Commit 07a4a4fc83dd ("ideapad: add Lenovo IdeaPad Z570 support (part 2)")
> added an i8042_command(..., I8042_CMD_AUX_[EN|DIS]ABLE) call to
> the ideapad-laptop driver to suppress the touchpad events at the PS/2
> AUX controller level.
> 
> Commit c69e7d843d2c ("platform/x86: ideapad-laptop: Only toggle ps2 aux
> port on/off on select models") limited this to only do this by default
> on the IdeaPad Z570 to replace a growing list of models on which
> the i8042_command() call was disabled by quirks because it was causing
> issues.
> 
> A recent report shows that this is causing issues even on the Z570 for
> which it was originally added because it can happen on resume before
> the i8042 controller's own resume() method has run:
> 
> [   50.241235] ideapad_acpi VPC2004:00: PM: calling acpi_subsys_resume+0x0/0x5d @ 4492, parent: PNP0C09:00
> [   50.242055] snd_hda_intel 0000:00:0e.0: PM: pci_pm_resume+0x0/0xed returned 0 after 13511 usecs
> [   50.242120] snd_hda_codec_realtek hdaudioC0D0: PM: calling hda_codec_pm_resume+0x0/0x19 [snd_hda_codec] @ 4518, parent: 0000:00:0e.0
> [   50.247406] i8042: [49434] a8 -> i8042 (command)
> [   50.247468] ideapad_acpi VPC2004:00: PM: acpi_subsys_resume+0x0/0x5d returned 0 after 6220 usecs
> ...
> [   50.247883] i8042 kbd 00:01: PM: calling pnp_bus_resume+0x0/0x9d @ 4492, parent: pnp0
> [   50.247894] i8042 kbd 00:01: PM: pnp_bus_resume+0x0/0x9d returned 0 after 0 usecs
> [   50.247906] i8042 aux 00:02: PM: calling pnp_bus_resume+0x0/0x9d @ 4492, parent: pnp0
> [   50.247916] i8042 aux 00:02: PM: pnp_bus_resume+0x0/0x9d returned 0 after 0 usecs
> ...
> [   50.248301] i8042 i8042: PM: calling platform_pm_resume+0x0/0x41 @ 4492, parent: platform
> [   50.248377] i8042: [49434] 55 <- i8042 (flush, kbd)
> [   50.248407] i8042: [49435] aa -> i8042 (command)
> [   50.248601] i8042: [49435] 00 <- i8042 (return)
> [   50.248604] i8042: [49435] i8042 controller selftest: 0x0 != 0x55

What exactly is the issue? Is it just a few errors in dmesg, or does
8042 stop responding completely?

I've seen something similar when I enabled the touchpad while moving the
cursor, but it was just a matter of a few lines in dmesg and a protocol
resync, both touchpad and keyboard worked after that.

> Dmitry (input subsys maintainer) pointed out that just sending
> KEY_TOUCHPAD_OFF/KEY_TOUCHPAD_ON which the ideapad-laptop driver
> already does should be sufficient and that it then is up to userspace
> to filter out touchpad events after having received a KEY_TOUCHPAD_OFF.

I believe it's not the case (at least it wasn't back then). The whole
point of my patch in the first place was to make touchpad toggle work
properly on Z570.

Userspace (GNOME) supports two variants of hardware:

1. Laptops that disable touchpad themselves and send out
KEY_TOUCHPAD_ON/OFF to report the status. Upon receiving these keycodes,
GNOME just shows the status pop-up and relies on firmware to disable the
touchpad.

2. Laptops that just send KEY_TOUCHPAD_TOGGLE whenever the key is
pressed. GNOME maintains its own touchpad state and disables it in
software (as well as showing the pop-up).

That means, userspace is not filtering out events upon receiving
KEY_TOUCHPAD_OFF. If we wanted to rely on that, we would need to send
KEY_TOUCHPAD_TOGGLE from the driver, but we actually can't, because Z570
is weird. It maintains the touchpad state in firmware to light up the
status LED, but the firmware doesn't do the actual touchpad disablement.

That is, if we use TOGGLE, the LED will get out of sync. If we use
ON/OFF, the touchpad won't be disabled, unless we do it in the kernel.

> Given all the problems the i8042_command() call has been causing just
> removing it indeed seems best, so this removes it completely. Note that
> this only impacts the Ideapad Z570 since it was already disabled by
> default on all other models.

While I agree that i8042_command() is not a perfect solution, I don't
like the idea of breaking the touchpad toggle, even if "only one" laptop
model is affected. Can we suppress input events from the touchpad in
some other way, purely in software? I.e. don't call i8042_command(),
don't disrupt the PS/2 protocol, but instead let ideapad-laptop tell
psmouse to stop generating input events for a while?

> Fixes: c69e7d843d2c ("platform/x86: ideapad-laptop: Only toggle ps2 aux port on/off on select models")
> Reported-by: Jonathan Denose <jdenose@xxxxxxxxxxxx>
> Closes: https://lore.kernel.org/linux-input/20231102075243.1.Idb37ff8043a29f607beab6440c32b9ae52525825@changeid/
> Suggested-by: Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx>
> Cc: Maxim Mikityanskiy <maxtram95@xxxxxxxxx>
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx>
> ---
>  drivers/platform/x86/ideapad-laptop.c | 37 ---------------------------
>  1 file changed, 37 deletions(-)
> 
> diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
> index 1ace711f7442..255fb56ec9ee 100644
> --- a/drivers/platform/x86/ideapad-laptop.c
> +++ b/drivers/platform/x86/ideapad-laptop.c
> @@ -18,7 +18,6 @@
>  #include <linux/device.h>
>  #include <linux/dmi.h>
>  #include <linux/fb.h>
> -#include <linux/i8042.h>
>  #include <linux/init.h>
>  #include <linux/input.h>
>  #include <linux/input/sparse-keymap.h>
> @@ -144,7 +143,6 @@ struct ideapad_private {
>  		bool hw_rfkill_switch     : 1;
>  		bool kbd_bl               : 1;
>  		bool touchpad_ctrl_via_ec : 1;
> -		bool ctrl_ps2_aux_port    : 1;
>  		bool usb_charging         : 1;
>  	} features;
>  	struct {
> @@ -182,12 +180,6 @@ MODULE_PARM_DESC(set_fn_lock_led,
>  	"Enable driver based updates of the fn-lock LED on fn-lock changes. "
>  	"If you need this please report this to: platform-driver-x86@xxxxxxxxxxxxxxx");
>  
> -static bool ctrl_ps2_aux_port;
> -module_param(ctrl_ps2_aux_port, bool, 0444);
> -MODULE_PARM_DESC(ctrl_ps2_aux_port,
> -	"Enable driver based PS/2 aux port en-/dis-abling on touchpad on/off toggle. "
> -	"If you need this please report this to: platform-driver-x86@xxxxxxxxxxxxxxx");
> -
>  static bool touchpad_ctrl_via_ec;
>  module_param(touchpad_ctrl_via_ec, bool, 0444);
>  MODULE_PARM_DESC(touchpad_ctrl_via_ec,
> @@ -1560,7 +1552,6 @@ static void ideapad_fn_lock_led_exit(struct ideapad_private *priv)
>  static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_events)
>  {
>  	unsigned long value;
> -	unsigned char param;
>  	int ret;
>  
>  	/* Without reading from EC touchpad LED doesn't switch state */
> @@ -1568,15 +1559,6 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_
>  	if (ret)
>  		return;
>  
> -	/*
> -	 * Some IdeaPads don't really turn off touchpad - they only
> -	 * switch the LED state. We (de)activate KBC AUX port to turn
> -	 * touchpad off and on. We send KEY_TOUCHPAD_OFF and
> -	 * KEY_TOUCHPAD_ON to not to get out of sync with LED
> -	 */
> -	if (priv->features.ctrl_ps2_aux_port)
> -		i8042_command(&param, value ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE);
> -
>  	/*
>  	 * On older models the EC controls the touchpad and toggles it on/off
>  	 * itself, in this case we report KEY_TOUCHPAD_ON/_OFF. Some models do
> @@ -1699,23 +1681,6 @@ static const struct dmi_system_id hw_rfkill_list[] = {
>  	{}
>  };
>  
> -/*
> - * On some models the EC toggles the touchpad muted LED on touchpad toggle
> - * hotkey presses, but the EC does not actually disable the touchpad itself.
> - * On these models the driver needs to explicitly enable/disable the i8042
> - * (PS/2) aux port.
> - */
> -static const struct dmi_system_id ctrl_ps2_aux_port_list[] = {
> -	{
> -	/* Lenovo Ideapad Z570 */
> -	.matches = {
> -		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
> -		DMI_MATCH(DMI_PRODUCT_VERSION, "Ideapad Z570"),
> -		},
> -	},
> -	{}
> -};
> -
>  static void ideapad_check_features(struct ideapad_private *priv)
>  {
>  	acpi_handle handle = priv->adev->handle;
> @@ -1725,8 +1690,6 @@ static void ideapad_check_features(struct ideapad_private *priv)
>  		set_fn_lock_led || dmi_check_system(set_fn_lock_led_list);
>  	priv->features.hw_rfkill_switch =
>  		hw_rfkill_switch || dmi_check_system(hw_rfkill_list);
> -	priv->features.ctrl_ps2_aux_port =
> -		ctrl_ps2_aux_port || dmi_check_system(ctrl_ps2_aux_port_list);
>  	priv->features.touchpad_ctrl_via_ec = touchpad_ctrl_via_ec;
>  
>  	if (!read_ec_data(handle, VPCCMD_R_FAN, &val))
> -- 
> 2.45.2
> 




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux