Commit 3d765ae2 authored by Werner Sembach's avatar Werner Sembach Committed by Dmitry Torokhov

Input: i8042 - add forcenorestore quirk to leave controller untouched even on s3

On s3 resume the i8042 driver tries to restore the controller to a known
state by reinitializing things, however this can confuse the controller
with different effects. Mostly occasionally unresponsive keyboards after
resume.

These issues do not rise on s0ix resume as here the controller is assumed
to preserved its state from before suspend.

This patch adds a quirk for devices where the reinitialization on s3 resume
is not needed and might be harmful as described above. It does this by
using the s0ix resume code path at selected locations.

This new quirk goes beyond what the preexisting reset=never quirk does,
which only skips some reinitialization steps.
Signed-off-by: default avatarWerner Sembach <wse@tuxedocomputers.com>
Cc: stable@vger.kernel.org
Reviewed-by: default avatarHans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20240104183118.779778-2-wse@tuxedocomputers.comSigned-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 7ce7c228
...@@ -83,6 +83,7 @@ static inline void i8042_write_command(int val) ...@@ -83,6 +83,7 @@ static inline void i8042_write_command(int val)
#define SERIO_QUIRK_KBDRESET BIT(12) #define SERIO_QUIRK_KBDRESET BIT(12)
#define SERIO_QUIRK_DRITEK BIT(13) #define SERIO_QUIRK_DRITEK BIT(13)
#define SERIO_QUIRK_NOPNP BIT(14) #define SERIO_QUIRK_NOPNP BIT(14)
#define SERIO_QUIRK_FORCENORESTORE BIT(15)
/* Quirk table for different mainboards. Options similar or identical to i8042 /* Quirk table for different mainboards. Options similar or identical to i8042
* module parameters. * module parameters.
...@@ -1694,6 +1695,8 @@ static void __init i8042_check_quirks(void) ...@@ -1694,6 +1695,8 @@ static void __init i8042_check_quirks(void)
if (quirks & SERIO_QUIRK_NOPNP) if (quirks & SERIO_QUIRK_NOPNP)
i8042_nopnp = true; i8042_nopnp = true;
#endif #endif
if (quirks & SERIO_QUIRK_FORCENORESTORE)
i8042_forcenorestore = true;
} }
#else #else
static inline void i8042_check_quirks(void) {} static inline void i8042_check_quirks(void) {}
...@@ -1727,7 +1730,7 @@ static int __init i8042_platform_init(void) ...@@ -1727,7 +1730,7 @@ static int __init i8042_platform_init(void)
i8042_check_quirks(); i8042_check_quirks();
pr_debug("Active quirks (empty means none):%s%s%s%s%s%s%s%s%s%s%s%s%s\n", pr_debug("Active quirks (empty means none):%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
i8042_nokbd ? " nokbd" : "", i8042_nokbd ? " nokbd" : "",
i8042_noaux ? " noaux" : "", i8042_noaux ? " noaux" : "",
i8042_nomux ? " nomux" : "", i8042_nomux ? " nomux" : "",
...@@ -1747,10 +1750,11 @@ static int __init i8042_platform_init(void) ...@@ -1747,10 +1750,11 @@ static int __init i8042_platform_init(void)
"", "",
#endif #endif
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
i8042_nopnp ? " nopnp" : ""); i8042_nopnp ? " nopnp" : "",
#else #else
""); "",
#endif #endif
i8042_forcenorestore ? " forcenorestore" : "");
retval = i8042_pnp_init(); retval = i8042_pnp_init();
if (retval) if (retval)
......
...@@ -115,6 +115,10 @@ module_param_named(nopnp, i8042_nopnp, bool, 0); ...@@ -115,6 +115,10 @@ module_param_named(nopnp, i8042_nopnp, bool, 0);
MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings"); MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings");
#endif #endif
static bool i8042_forcenorestore;
module_param_named(forcenorestore, i8042_forcenorestore, bool, 0);
MODULE_PARM_DESC(forcenorestore, "Force no restore on s3 resume, copying s2idle behaviour");
#define DEBUG #define DEBUG
#ifdef DEBUG #ifdef DEBUG
static bool i8042_debug; static bool i8042_debug;
...@@ -1232,7 +1236,7 @@ static int i8042_pm_suspend(struct device *dev) ...@@ -1232,7 +1236,7 @@ static int i8042_pm_suspend(struct device *dev)
{ {
int i; int i;
if (pm_suspend_via_firmware()) if (!i8042_forcenorestore && pm_suspend_via_firmware())
i8042_controller_reset(true); i8042_controller_reset(true);
/* Set up serio interrupts for system wakeup. */ /* Set up serio interrupts for system wakeup. */
...@@ -1248,7 +1252,7 @@ static int i8042_pm_suspend(struct device *dev) ...@@ -1248,7 +1252,7 @@ static int i8042_pm_suspend(struct device *dev)
static int i8042_pm_resume_noirq(struct device *dev) static int i8042_pm_resume_noirq(struct device *dev)
{ {
if (!pm_resume_via_firmware()) if (i8042_forcenorestore || !pm_resume_via_firmware())
i8042_interrupt(0, NULL); i8042_interrupt(0, NULL);
return 0; return 0;
...@@ -1271,7 +1275,7 @@ static int i8042_pm_resume(struct device *dev) ...@@ -1271,7 +1275,7 @@ static int i8042_pm_resume(struct device *dev)
* not restore the controller state to whatever it had been at boot * not restore the controller state to whatever it had been at boot
* time, so we do not need to do anything. * time, so we do not need to do anything.
*/ */
if (!pm_suspend_via_firmware()) if (i8042_forcenorestore || !pm_suspend_via_firmware())
return 0; return 0;
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment