From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
To: Friedrich Vock <friedrich.vock@gmx.de>
Cc: linux-input@vger.kernel.org,
Mario Limonciello <mario.limonciello@amd.com>
Subject: Re: [PATCH] Input: i8042 - Add quirk for polling the KBD port
Date: Fri, 21 Jul 2023 16:44:18 -0700 [thread overview]
Message-ID: <ZLsYUlSMIK0Gtr21@google.com> (raw)
In-Reply-To: <20230530153644.17262-1-friedrich.vock@gmx.de>
Hi Friedrich,
On Tue, May 30, 2023 at 05:36:44PM +0200, Friedrich Vock wrote:
> It seems like there are some devices in the ASUS TUF A16 laptops that
> just don't send any keyboard interrupts until you read from the KBD port.
I am sorry, but continuously polling keyboard port will absolutely wreck
battery life on these devices, so this can not be a real solution.
I wonder if this is yet another example of incorrect IRQ 1 polarity
override on devices with AMD chipsets (CC-ing Mario).
>
> Signed-off-by: Friedrich Vock <friedrich.vock@gmx.de>
> ---
> drivers/input/serio/i8042-acpipnpio.h | 30 +++++++++++++++--
> drivers/input/serio/i8042.c | 47 ++++++++++++++++++++++-----
> drivers/input/serio/i8042.h | 2 +-
> 3 files changed, 67 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h
> index 028e45bd050b..be2e72aaa658 100644
> --- a/drivers/input/serio/i8042-acpipnpio.h
> +++ b/drivers/input/serio/i8042-acpipnpio.h
> @@ -83,6 +83,7 @@ static inline void i8042_write_command(int val)
> #define SERIO_QUIRK_KBDRESET BIT(12)
> #define SERIO_QUIRK_DRITEK BIT(13)
> #define SERIO_QUIRK_NOPNP BIT(14)
> +#define SERIO_QUIRK_POLL_KBD BIT(15)
>
> /* Quirk table for different mainboards. Options similar or identical to i8042
> * module parameters.
> @@ -99,6 +100,26 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
> },
> .driver_data = (void *)(SERIO_QUIRK_NOMUX)
> },
> + /* Some laptops seem to not trigger any keyboard interrupts at all,
> + * even when there is data available. On these devices, manually
> + * polling the keyboard port is required.
> + */
> + {
> + /* ASUS TUF Gaming A16 with Ryzen 7 7735HS */
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
> + DMI_MATCH(DMI_PRODUCT_NAME, "FA617NS"),
> + },
> + .driver_data = (void *)(SERIO_QUIRK_POLL_KBD)
> + },
> + {
> + /* ASUS TUF Gaming A16 with Ryzen 9 7940HS */
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
> + DMI_MATCH(DMI_PRODUCT_NAME, "FA617XS"),
> + },
> + .driver_data = (void *)(SERIO_QUIRK_POLL_KBD)
> + },
> {
> .matches = {
> DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
> @@ -1634,6 +1655,8 @@ static void __init i8042_check_quirks(void)
> if (quirks & SERIO_QUIRK_NOPNP)
> i8042_nopnp = true;
> #endif
> + if (quirks & SERIO_QUIRK_POLL_KBD)
> + i8042_poll_kbd = true;
> }
> #else
> static inline void i8042_check_quirks(void) {}
> @@ -1667,7 +1690,7 @@ static int __init i8042_platform_init(void)
>
> 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_noaux ? " noaux" : "",
> i8042_nomux ? " nomux" : "",
> @@ -1687,10 +1710,11 @@ static int __init i8042_platform_init(void)
> "",
> #endif
> #ifdef CONFIG_PNP
> - i8042_nopnp ? " nopnp" : "");
> + i8042_nopnp ? " nopnp" : "",
> #else
> - "");
> + "",
> #endif
> + i8042_poll_kbd ? "poll_kbd" : "");
>
> retval = i8042_pnp_init();
> if (retval)
> diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
> index 6dac7c1853a5..7212263d3a41 100644
> --- a/drivers/input/serio/i8042.c
> +++ b/drivers/input/serio/i8042.c
> @@ -115,6 +115,10 @@ module_param_named(nopnp, i8042_nopnp, bool, 0);
> MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings");
> #endif
>
> +static bool i8042_poll_kbd;
> +module_param_named(poll_kbd, i8042_poll_kbd, bool, 0);
> +MODULE_PARM_DESC(poll_kbd, "Continuously poll the KBD port instead of relying on interrupts");
> +
> #define DEBUG
> #ifdef DEBUG
> static bool i8042_debug;
> @@ -178,6 +182,24 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id);
> static bool (*i8042_platform_filter)(unsigned char data, unsigned char str,
> struct serio *serio);
>
> +#define POLL_TIME 1
> +static void i8042_poll_func(struct timer_list *timer)
> +{
> + unsigned char status;
> + unsigned long flags;
> +
> + do {
> + spin_lock_irqsave(&i8042_lock, flags);
> + status = i8042_read_status();
> + spin_unlock_irqrestore(&i8042_lock, flags);
> + if (status & I8042_STR_OBF)
> + i8042_interrupt(0, NULL);
> + } while (status & I8042_STR_OBF);
> + mod_timer(timer, jiffies + msecs_to_jiffies(POLL_TIME));
> +}
> +
> +DEFINE_TIMER(poll_timer, i8042_poll_func);
> +
> void i8042_lock_chip(void)
> {
> mutex_lock(&i8042_mutex);
> @@ -1437,13 +1459,15 @@ static void i8042_unregister_ports(void)
> }
> }
>
> +
> static void i8042_free_irqs(void)
> {
> if (i8042_aux_irq_registered)
> free_irq(I8042_AUX_IRQ, i8042_platform_device);
> - if (i8042_kbd_irq_registered)
> + if (i8042_poll_kbd)
> + del_timer(&poll_timer);
> + else if (i8042_kbd_irq_registered)
> free_irq(I8042_KBD_IRQ, i8042_platform_device);
> -
> i8042_aux_irq_registered = i8042_kbd_irq_registered = false;
> }
>
> @@ -1497,10 +1521,14 @@ static int i8042_setup_kbd(void)
> if (error)
> return error;
>
> - error = request_irq(I8042_KBD_IRQ, i8042_interrupt, IRQF_SHARED,
> - "i8042", i8042_platform_device);
> - if (error)
> - goto err_free_port;
> + if (i8042_poll_kbd)
> + mod_timer(&poll_timer, msecs_to_jiffies(POLL_TIME));
> + else {
> + error = request_irq(I8042_KBD_IRQ, i8042_interrupt, IRQF_SHARED,
> + "i8042", i8042_platform_device);
> + if (error)
> + goto err_free_port;
> + }
>
> error = i8042_enable_kbd_port();
> if (error)
> @@ -1510,8 +1538,11 @@ static int i8042_setup_kbd(void)
> return 0;
>
> err_free_irq:
> - free_irq(I8042_KBD_IRQ, i8042_platform_device);
> - err_free_port:
> + if (i8042_poll_kbd)
> + del_timer(&poll_timer);
> + else
> + free_irq(I8042_KBD_IRQ, i8042_platform_device);
> +err_free_port:
> i8042_free_kbd_port();
> return error;
> }
> --
> 2.40.1
>
Thanks.
--
Dmitry
next prev parent reply other threads:[~2023-07-21 23:44 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-30 15:36 [PATCH] Input: i8042 - Add quirk for polling the KBD port Friedrich Vock
2023-07-21 23:44 ` Dmitry Torokhov [this message]
2023-07-22 15:35 ` Friedrich Vock
2023-07-23 15:45 ` Mario Limonciello
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZLsYUlSMIK0Gtr21@google.com \
--to=dmitry.torokhov@gmail.com \
--cc=friedrich.vock@gmx.de \
--cc=linux-input@vger.kernel.org \
--cc=mario.limonciello@amd.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox