From patchwork Thu May 11 18:52:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 13238359 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 80D2FC7EE22 for ; Thu, 11 May 2023 18:53:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238890AbjEKSxC (ORCPT ); Thu, 11 May 2023 14:53:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57228 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238927AbjEKSxB (ORCPT ); Thu, 11 May 2023 14:53:01 -0400 Received: from mail-pg1-x530.google.com (mail-pg1-x530.google.com [IPv6:2607:f8b0:4864:20::530]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8F7E919A6; Thu, 11 May 2023 11:52:59 -0700 (PDT) Received: by mail-pg1-x530.google.com with SMTP id 41be03b00d2f7-52c690f7fa4so6025583a12.0; Thu, 11 May 2023 11:52:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683831178; x=1686423178; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fmpqhd4kEVSfc34qTZPnmcAbaqtTD/WUYsFYDWaUQYA=; b=J0KpfIPyc27+FlEt8VAmD2SccAPF4n7ZCciZPT8YjZZ3OvVuBy6CXG0fheIGnSRwae pSYJzpOPHwXRaUvK9BoyDG564kWXnp709DFrpvOsFwSFCFm4PtRTHgGqXOLS6mGEvgiw 5P0aOCHbZXSkky/PGZEKxR3jimkFN+8FpL27nE9qjNKEIHnsWuBP+9mJyimoPMvnMxbz a6PCxNlE3is/Wy0y1tOKnS6mf+HaXoZ+X3M7UlMggcbpOXxw4uqf3xSZcR7VOtojfTbu 76y5GuuADkhlBTouj2pF2HpwYQEhX+UHGYMYowmMdrqENY0DkH7kD2QRq14zzdTd+8Io HjlA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683831178; x=1686423178; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=fmpqhd4kEVSfc34qTZPnmcAbaqtTD/WUYsFYDWaUQYA=; b=LV0b92E2Eb2RWUHbMAsgHcqSrHmSOLMvKJiC2ZM57CRVNnXtVZAW1ws+xPkKvmGvMV xxpGmKVngrdqMGoAGIxsV5T9wloeO5xG+eK7HHRUq8fJS9htj29vAfPpt5OqhsLwEIyT bKnlE5qt3iDtDXaPAs+W7uPj3RvOkngwBb6fZT28dwSZft+u6TTyIz2FfDfWVTUiHYXD 0ekYaGKjnJW0H/BKcPqBAyjcYRWZFWlHwecaz6+EMiNW1n8wyTR+1qluOiOo5PDPPY9o YDoBpzx3KPdBevfRP8E0Ao8DDdpAEObGLfCux/N3QxnPUV/OLZDNLeYY5e4/fKyNAARQ Jh5g== X-Gm-Message-State: AC+VfDy1+KLz36ed0Tk+xDXY0EQEBjQnIp5e9TTyQm7MqBC5oKORlep1 33nhgdlyN/fIyUdBQln8PE8QEcot1j8= X-Google-Smtp-Source: ACHHUZ741L7hlP7jXwh/IFnUETPT50KLKqUeoIuUpHADj/AKOZUcKoRqsYoN9P2PMbacALxCdl4+Tw== X-Received: by 2002:a17:903:44c:b0:1ab:27e7:ad76 with SMTP id iw12-20020a170903044c00b001ab27e7ad76mr21361645plb.45.1683831178172; Thu, 11 May 2023 11:52:58 -0700 (PDT) Received: from dtor-ws.mtv.corp.google.com ([2620:15c:9d:2:84a:ed9c:4024:c347]) by smtp.gmail.com with ESMTPSA id q5-20020a170902788500b001a980a23804sm6288995pll.4.2023.05.11.11.52.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 May 2023 11:52:57 -0700 (PDT) From: Dmitry Torokhov To: linux-input@vger.kernel.org Cc: Raul E Rangel , linux-kernel@vger.kernel.org Subject: [PATCH 1/7] Input: libps2 - attach ps2dev instances as serio port's drvdata Date: Thu, 11 May 2023 11:52:41 -0700 Message-ID: <20230511185252.386941-2-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.40.1.606.ga4b1b128d6-goog In-Reply-To: <20230511185252.386941-1-dmitry.torokhov@gmail.com> References: <20230511185252.386941-1-dmitry.torokhov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org In preparation of having unified interrupt handler for PS/2 devices, instead of attaching instances of psmouse and atkbd structures as serio's driver data, switch to attaching ps2dev instances. Signed-off-by: Dmitry Torokhov Reviewed-by: Raul Rangel --- drivers/input/keyboard/atkbd.c | 23 +++++++++++++------- drivers/input/mouse/psmouse-base.c | 35 +++++++++++++++++------------- drivers/input/mouse/psmouse.h | 2 ++ drivers/input/mouse/synaptics.c | 10 ++++----- drivers/input/mouse/trackpoint.c | 2 +- drivers/input/serio/libps2.c | 1 + 6 files changed, 44 insertions(+), 29 deletions(-) diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 246958795f60..2fb2ad73e796 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -309,12 +309,19 @@ static ssize_t atkbd_show_function_row_physmap(struct atkbd *atkbd, char *buf) return vivaldi_function_row_physmap_show(&atkbd->vdata, buf); } +static struct atkbd *atkbd_from_serio(struct serio *serio) +{ + struct ps2dev *ps2dev = serio_get_drvdata(serio); + + return container_of(ps2dev, struct atkbd, ps2dev); +} + static umode_t atkbd_attr_is_visible(struct kobject *kobj, struct attribute *attr, int i) { struct device *dev = kobj_to_dev(kobj); struct serio *serio = to_serio_port(dev); - struct atkbd *atkbd = serio_get_drvdata(serio); + struct atkbd *atkbd = atkbd_from_serio(serio); if (attr == &atkbd_attr_function_row_physmap.attr && !atkbd->vdata.num_function_row_keys) @@ -399,7 +406,7 @@ static unsigned int atkbd_compat_scancode(struct atkbd *atkbd, unsigned int code static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, unsigned int flags) { - struct atkbd *atkbd = serio_get_drvdata(serio); + struct atkbd *atkbd = atkbd_from_serio(serio); struct input_dev *dev = atkbd->dev; unsigned int code = data; int scroll = 0, hscroll = 0, click = -1; @@ -909,7 +916,7 @@ static int atkbd_reset_state(struct atkbd *atkbd) static void atkbd_cleanup(struct serio *serio) { - struct atkbd *atkbd = serio_get_drvdata(serio); + struct atkbd *atkbd = atkbd_from_serio(serio); atkbd_disable(atkbd); ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_DEF); @@ -922,7 +929,7 @@ static void atkbd_cleanup(struct serio *serio) static void atkbd_disconnect(struct serio *serio) { - struct atkbd *atkbd = serio_get_drvdata(serio); + struct atkbd *atkbd = atkbd_from_serio(serio); atkbd_disable(atkbd); @@ -1188,7 +1195,7 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd) static void atkbd_parse_fwnode_data(struct serio *serio) { - struct atkbd *atkbd = serio_get_drvdata(serio); + struct atkbd *atkbd = atkbd_from_serio(serio); struct device *dev = &serio->dev; int n; @@ -1295,7 +1302,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) static int atkbd_reconnect(struct serio *serio) { - struct atkbd *atkbd = serio_get_drvdata(serio); + struct atkbd *atkbd = atkbd_from_serio(serio); struct serio_driver *drv = serio->drv; int retval = -1; @@ -1389,7 +1396,7 @@ static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, ssize_t (*handler)(struct atkbd *, char *)) { struct serio *serio = to_serio_port(dev); - struct atkbd *atkbd = serio_get_drvdata(serio); + struct atkbd *atkbd = atkbd_from_serio(serio); return handler(atkbd, buf); } @@ -1398,7 +1405,7 @@ static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t ssize_t (*handler)(struct atkbd *, const char *, size_t)) { struct serio *serio = to_serio_port(dev); - struct atkbd *atkbd = serio_get_drvdata(serio); + struct atkbd *atkbd = atkbd_from_serio(serio); int retval; retval = mutex_lock_interruptible(&atkbd->mutex); diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index c9a7e87b273e..ed5376099fba 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -116,6 +116,13 @@ static DEFINE_MUTEX(psmouse_mutex); static struct workqueue_struct *kpsmoused_wq; +struct psmouse *psmouse_from_serio(struct serio *serio) +{ + struct ps2dev *ps2dev = serio_get_drvdata(serio); + + return container_of(ps2dev, struct psmouse, ps2dev); +} + void psmouse_report_standard_buttons(struct input_dev *dev, u8 buttons) { input_report_key(dev, BTN_LEFT, buttons & BIT(0)); @@ -336,7 +343,7 @@ static void psmouse_handle_oob_data(struct psmouse *psmouse, u8 data) static irqreturn_t psmouse_interrupt(struct serio *serio, u8 data, unsigned int flags) { - struct psmouse *psmouse = serio_get_drvdata(serio); + struct psmouse *psmouse = psmouse_from_serio(serio); if (psmouse->state == PSMOUSE_IGNORE) goto out; @@ -1344,7 +1351,7 @@ static void psmouse_resync(struct work_struct *work) goto out; if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); + parent = psmouse_from_serio(serio->parent); psmouse_deactivate(parent); } @@ -1428,13 +1435,13 @@ static void psmouse_resync(struct work_struct *work) */ static void psmouse_cleanup(struct serio *serio) { - struct psmouse *psmouse = serio_get_drvdata(serio); + struct psmouse *psmouse = psmouse_from_serio(serio); struct psmouse *parent = NULL; mutex_lock(&psmouse_mutex); if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); + parent = psmouse_from_serio(serio->parent); psmouse_deactivate(parent); } @@ -1476,7 +1483,7 @@ static void psmouse_cleanup(struct serio *serio) */ static void psmouse_disconnect(struct serio *serio) { - struct psmouse *psmouse = serio_get_drvdata(serio); + struct psmouse *psmouse = psmouse_from_serio(serio); struct psmouse *parent = NULL; mutex_lock(&psmouse_mutex); @@ -1489,7 +1496,7 @@ static void psmouse_disconnect(struct serio *serio) mutex_lock(&psmouse_mutex); if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); + parent = psmouse_from_serio(serio->parent); psmouse_deactivate(parent); } @@ -1588,7 +1595,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) * connected to this port can be successfully identified */ if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); + parent = psmouse_from_serio(serio->parent); psmouse_deactivate(parent); } @@ -1604,8 +1611,6 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); - serio_set_drvdata(serio, psmouse); - error = serio_open(serio, drv); if (error) goto err_clear_drvdata; @@ -1676,7 +1681,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) static int __psmouse_reconnect(struct serio *serio, bool fast_reconnect) { - struct psmouse *psmouse = serio_get_drvdata(serio); + struct psmouse *psmouse = psmouse_from_serio(serio); struct psmouse *parent = NULL; int (*reconnect_handler)(struct psmouse *); enum psmouse_type type; @@ -1695,7 +1700,7 @@ static int __psmouse_reconnect(struct serio *serio, bool fast_reconnect) } if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); + parent = psmouse_from_serio(serio->parent); psmouse_deactivate(parent); } @@ -1794,7 +1799,7 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *de { struct serio *serio = to_serio_port(dev); struct psmouse_attribute *attr = to_psmouse_attr(devattr); - struct psmouse *psmouse = serio_get_drvdata(serio); + struct psmouse *psmouse = psmouse_from_serio(serio); if (psmouse->protocol->smbus_companion && devattr != &psmouse_attr_protocol.dattr) @@ -1815,7 +1820,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev if (retval) goto out; - psmouse = serio_get_drvdata(serio); + psmouse = psmouse_from_serio(serio); if (psmouse->protocol->smbus_companion && devattr != &psmouse_attr_protocol.dattr) { @@ -1830,7 +1835,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev } if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); + parent = psmouse_from_serio(serio->parent); psmouse_deactivate(parent); } @@ -1925,7 +1930,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co } if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); + parent = psmouse_from_serio(serio->parent); if (parent->pt_deactivate) parent->pt_deactivate(parent); } diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 64c3a5d3fb3e..4d8acfe0d82a 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -130,6 +130,8 @@ struct psmouse { void (*pt_deactivate)(struct psmouse *psmouse); }; +struct psmouse *psmouse_from_serio(struct serio *serio); + void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work, unsigned long delay); int psmouse_reset(struct psmouse *psmouse); diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index fa021af8506e..ada299ec5bba 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -628,7 +628,7 @@ static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate) ****************************************************************************/ static int synaptics_pt_write(struct serio *serio, u8 c) { - struct psmouse *parent = serio_get_drvdata(serio->parent); + struct psmouse *parent = psmouse_from_serio(serio->parent); u8 rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */ int error; @@ -645,7 +645,7 @@ static int synaptics_pt_write(struct serio *serio, u8 c) static int synaptics_pt_start(struct serio *serio) { - struct psmouse *parent = serio_get_drvdata(serio->parent); + struct psmouse *parent = psmouse_from_serio(serio->parent); struct synaptics_data *priv = parent->private; serio_pause_rx(parent->ps2dev.serio); @@ -657,7 +657,7 @@ static int synaptics_pt_start(struct serio *serio) static void synaptics_pt_stop(struct serio *serio) { - struct psmouse *parent = serio_get_drvdata(serio->parent); + struct psmouse *parent = psmouse_from_serio(serio->parent); struct synaptics_data *priv = parent->private; serio_pause_rx(parent->ps2dev.serio); @@ -672,7 +672,7 @@ static int synaptics_is_pt_packet(u8 *buf) static void synaptics_pass_pt_packet(struct serio *ptport, u8 *packet) { - struct psmouse *child = serio_get_drvdata(ptport); + struct psmouse *child = psmouse_from_serio(ptport); if (child && child->state == PSMOUSE_ACTIVATED) { serio_interrupt(ptport, packet[1], 0); @@ -688,7 +688,7 @@ static void synaptics_pass_pt_packet(struct serio *ptport, u8 *packet) static void synaptics_pt_activate(struct psmouse *psmouse) { struct synaptics_data *priv = psmouse->private; - struct psmouse *child = serio_get_drvdata(priv->pt_port); + struct psmouse *child = psmouse_from_serio(priv->pt_port); /* adjust the touchpad to child's choice of protocol */ if (child) { diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index 4a86b3e31d3b..5f6643b69a2c 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c @@ -216,7 +216,7 @@ static umode_t trackpoint_is_attr_visible(struct kobject *kobj, { struct device *dev = kobj_to_dev(kobj); struct serio *serio = to_serio_port(dev); - struct psmouse *psmouse = serio_get_drvdata(serio); + struct psmouse *psmouse = psmouse_from_serio(serio); return trackpoint_is_attr_available(psmouse, attr) ? attr->mode : 0; } diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index 3e19344eda93..764990723847 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -382,6 +382,7 @@ void ps2_init(struct ps2dev *ps2dev, struct serio *serio) lockdep_set_subclass(&ps2dev->cmd_mutex, serio->depth); init_waitqueue_head(&ps2dev->wait); ps2dev->serio = serio; + serio_set_drvdata(serio, ps2dev); } EXPORT_SYMBOL(ps2_init); From patchwork Thu May 11 18:52:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 13238360 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 20EA3C7EE24 for ; Thu, 11 May 2023 18:53:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238949AbjEKSxD (ORCPT ); Thu, 11 May 2023 14:53:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57230 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238932AbjEKSxB (ORCPT ); Thu, 11 May 2023 14:53:01 -0400 Received: from mail-pl1-x632.google.com (mail-pl1-x632.google.com [IPv6:2607:f8b0:4864:20::632]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E212240E0; Thu, 11 May 2023 11:53:00 -0700 (PDT) Received: by mail-pl1-x632.google.com with SMTP id d9443c01a7336-1ab1ce53ca6so65247925ad.0; Thu, 11 May 2023 11:53:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683831180; x=1686423180; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7o+RBiVTUR0DwkNdBEw9knQ1VGeDnk1pNXEP3ntY+eU=; b=UqOBntZpH/hTxsSnqz6tqittgDaSy8/jKh9JGoQD2vwaYlDE1I4i5F0jBM7KlIss6m GWh/4BzyyZnyi/Osozdzroc8kydLSG1vSH6ny+FmMdfkrQl0IFA6XiIazPxJ8ENZW8Re qtTUOSr4JLt8ChpKuMV9uIvLVb+SQylG9waLkaSbR2sSFUmo5GTT0KrCgaAE74e1lrr3 SCJI4yDXl2e92y5Fe3aUx+VrOe4s93XEWxbR7nE8ikb5BhMr1wTiCCpl2cntTtDHYOxV 0H6LFeoMC8d/vYo2eD+Q9VA4BYVRbfB2dyzTz9d/b/jLsGeY9vdJQp9calmojFD4b/O3 Mwuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683831180; x=1686423180; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7o+RBiVTUR0DwkNdBEw9knQ1VGeDnk1pNXEP3ntY+eU=; b=UKsANxMu33Qt9IsMG4WyCX804QeDoHTAK6NBT9uAY562BjBonJmnvuK+9PAFuJADJf R+fkXZv0qvMYURE1+bbW1i5gMTrwAAJIQWK2PXogpnPFP+qbtUM6qJ5gGAlP7wLUi2Va owu0IL0MAGNvWV1w3E7I5gUdOg69KQG6nCwoeJp9LYc58hPBNmy6jAKjCUlH5QapqQMW 857Gjqwal+OaFPjkHmsgd2AMztywiotD1dLoI+JyKeIpLTSsIbYhO5rqeov0DVIRrn/l x0sJRSJNFlAwV24UOAX4R/EWVGDvoJRdr4RRC0z/ZY6eYBpmrcIgOjLAJLY3g91kFZuA MrhQ== X-Gm-Message-State: AC+VfDw/feXdTrYzsFI6ncPc2vgzNCFeL8dawjsuyMwWVg1ncNNUm466 k3jM3X+k+JwKXodrLxfwK3xv+yUkR7M= X-Google-Smtp-Source: ACHHUZ70yb4hK5Vbnzzkv1SlgUrq3839eTz9Wvz8+q/sIhLk6M8C93hOhcBVB75jsS89Wm45+FTPWQ== X-Received: by 2002:a17:902:c40b:b0:1aa:fd48:f5e2 with SMTP id k11-20020a170902c40b00b001aafd48f5e2mr29678853plk.32.1683831179734; Thu, 11 May 2023 11:52:59 -0700 (PDT) Received: from dtor-ws.mtv.corp.google.com ([2620:15c:9d:2:84a:ed9c:4024:c347]) by smtp.gmail.com with ESMTPSA id q5-20020a170902788500b001a980a23804sm6288995pll.4.2023.05.11.11.52.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 May 2023 11:52:58 -0700 (PDT) From: Dmitry Torokhov To: linux-input@vger.kernel.org Cc: Raul E Rangel , linux-kernel@vger.kernel.org Subject: [PATCH 2/7] Input: libps2 - remove special handling of ACK for command byte Date: Thu, 11 May 2023 11:52:42 -0700 Message-ID: <20230511185252.386941-3-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.40.1.606.ga4b1b128d6-goog In-Reply-To: <20230511185252.386941-1-dmitry.torokhov@gmail.com> References: <20230511185252.386941-1-dmitry.torokhov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org When getting unexpected data while waiting for an acknowledgement it does not matter what command phase is currently executed, and ps2_handle_ack() should indicate that no further processing is needed for the received data byte. Remove PS2_FLAG_ACK_CMD and associated handling. Note that while it is possible to make ps2_handle_ack (and ps2_handle_repsonse) return void, it will be done when the code will be converted to common PS/2 interrupt handler later. Signed-off-by: Dmitry Torokhov Reviewed-by: Raul E Rangel --- drivers/input/serio/libps2.c | 9 ++------- include/linux/libps2.h | 1 - 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index 764990723847..399cda0d34f5 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -253,9 +253,6 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command) for (i = 0; i < receive; i++) ps2dev->cmdbuf[(receive - 1) - i] = param[i]; - /* Signal that we are sending the command byte */ - ps2dev->flags |= PS2_FLAG_ACK_CMD; - /* * Some devices (Synaptics) peform the reset before * ACKing the reset command, and so it can take a long @@ -267,9 +264,7 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command) if (rc) goto out_reset_flags; - /* Now we are sending command parameters, if any */ - ps2dev->flags &= ~PS2_FLAG_ACK_CMD; - + /* Send command parameters, if any. */ for (i = 0; i < send; i++) { rc = ps2_do_sendbyte(ps2dev, param[i], 200, 2); if (rc) @@ -436,7 +431,7 @@ bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data) */ dev_dbg(&ps2dev->serio->dev, "unexpected %#02x\n", data); ps2dev->flags &= ~PS2_FLAG_WAITID; - return ps2dev->flags & PS2_FLAG_ACK_CMD; + return true; } if (!ps2dev->nak) { diff --git a/include/linux/libps2.h b/include/linux/libps2.h index 53f7e4d0f4b7..193dd53ad18b 100644 --- a/include/linux/libps2.h +++ b/include/linux/libps2.h @@ -28,7 +28,6 @@ #define PS2_FLAG_CMD1 BIT(2) /* Waiting for the first byte of command response */ #define PS2_FLAG_WAITID BIT(3) /* Command executing is GET ID */ #define PS2_FLAG_NAK BIT(4) /* Last transmission was NAKed */ -#define PS2_FLAG_ACK_CMD BIT(5) /* Waiting to ACK the command (first) byte */ struct ps2dev { struct serio *serio; From patchwork Thu May 11 18:52:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 13238361 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 51314C77B7C for ; Thu, 11 May 2023 18:53:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238954AbjEKSxF (ORCPT ); Thu, 11 May 2023 14:53:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57292 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238948AbjEKSxD (ORCPT ); Thu, 11 May 2023 14:53:03 -0400 Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 515C949FA; Thu, 11 May 2023 11:53:02 -0700 (PDT) Received: by mail-pl1-x62d.google.com with SMTP id d9443c01a7336-1ab0c697c84so69234255ad.3; Thu, 11 May 2023 11:53:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683831181; x=1686423181; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=HKXVPvgyQquk1TSIQ/OU7pvBBko0Yowmo5LV3A9+bSA=; b=YGArolRMbIDSSJke8TGKqCTntbcRR7Lo0Aq2TLUYrFxRcW80O8kX6d+iXPcW7ZgmH3 a90HDabJvBrKVrd7xGL4AKttT9Xd1un9Wi+NvvSdxN1e3hqPVY+0zYGw06Kt5rjQYF5x TteODwJFs0qpMZ5yzX3izLpggoJ6pz5c6bjha1a3bRFlQoqEJuobpE23nr2YDjPRhXOp 2+fKwcbFsS7QQHe7j1syiVq/6VAofn8C78hpAseTjpArAruJTgUmjWETo3rvb6jDxdfA MLOrITIrnuxA5QP/UEgIdEKbgZ4J0ia91cQpfgmjZASwFMhVULSmstIXU3ZebGqZnqDE 6dYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683831181; x=1686423181; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=HKXVPvgyQquk1TSIQ/OU7pvBBko0Yowmo5LV3A9+bSA=; b=d5FXh9FzU9fjc2JxSryJO2oYP+FTlxMjLq5oix6ZaGlFZ6ZV30Okg1aegSdDRCQScH vmxQTIc7nCUYYFuswmbLrZJ/hdWx9/tlCd5w5M84zxwfVIbGUwpBSGPwYblVHt+6kex0 hoKbirkVqgNykffieH3qal7J6XEHomx7Wkck2qXfd42CLx3+gg3IdlYZESZHTf0YBfdw 62yg/LaE7yqgx9Lg5bgXXGCv0FLJ0VDiz0i7JJCPD6PMF0DqXDUKpui/6WqzrMcbcaXX p9tyzXIbPKZTItQ/hHUUcUCoAZS10ljWJCQj0XokMPr8oy4sJb3l6iQY+bcM6H7URYlW G0WA== X-Gm-Message-State: AC+VfDx8tdgxec8PknUrB3UQB8jCuS6GmMNdpSy8wbthv1DHzIH1XzoB 9besB7nOgZn8n7OajkoR0hMFpstAeZk= X-Google-Smtp-Source: ACHHUZ4iYtXDja/WYrLCsLdZdvRrKMJWXkSRRf2mDFbhxqu65bFNoZsLKcdkXTcODEYUt/FIKPHdbg== X-Received: by 2002:a17:903:185:b0:1a9:6bd4:236a with SMTP id z5-20020a170903018500b001a96bd4236amr28122650plg.69.1683831181145; Thu, 11 May 2023 11:53:01 -0700 (PDT) Received: from dtor-ws.mtv.corp.google.com ([2620:15c:9d:2:84a:ed9c:4024:c347]) by smtp.gmail.com with ESMTPSA id q5-20020a170902788500b001a980a23804sm6288995pll.4.2023.05.11.11.52.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 May 2023 11:53:00 -0700 (PDT) From: Dmitry Torokhov To: linux-input@vger.kernel.org Cc: Raul E Rangel , linux-kernel@vger.kernel.org Subject: [PATCH 3/7] Input: libps2 - rework handling of command response Date: Thu, 11 May 2023 11:52:43 -0700 Message-ID: <20230511185252.386941-4-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.40.1.606.ga4b1b128d6-goog In-Reply-To: <20230511185252.386941-1-dmitry.torokhov@gmail.com> References: <20230511185252.386941-1-dmitry.torokhov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org It is not entirely correct that libps2 sets PS2_FLAG_CMD1 after the device acknowledges each byte sent to the device by the host. Rework the code so that PS2_FLAG_CMD1 and PS2_FLAG_CMD are set only once, at the beginning of PS/2 command execution. Signed-off-by: Dmitry Torokhov Reviewed-by: Raul E Rangel --- drivers/input/serio/libps2.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index 399cda0d34f5..d09450eca9a7 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -247,14 +247,19 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command) serio_pause_rx(ps2dev->serio); + /* Some mice do not ACK the "get ID" command, prepare to handle this. */ ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0; ps2dev->cmdcnt = receive; - if (receive && param) - for (i = 0; i < receive; i++) - ps2dev->cmdbuf[(receive - 1) - i] = param[i]; + if (receive) { + /* Indicate that we expect response to the command. */ + ps2dev->flags |= PS2_FLAG_CMD | PS2_FLAG_CMD1; + if (param) + for (i = 0; i < receive; i++) + ps2dev->cmdbuf[(receive - 1) - i] = param[i]; + } /* - * Some devices (Synaptics) peform the reset before + * Some devices (Synaptics) perform the reset before * ACKing the reset command, and so it can take a long * time before the ACK arrives. */ @@ -434,11 +439,8 @@ bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data) return true; } - if (!ps2dev->nak) { + if (!ps2dev->nak) ps2dev->flags &= ~PS2_FLAG_NAK; - if (ps2dev->cmdcnt) - ps2dev->flags |= PS2_FLAG_CMD | PS2_FLAG_CMD1; - } ps2dev->flags &= ~PS2_FLAG_ACK; wake_up(&ps2dev->wait); From patchwork Thu May 11 18:52:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 13238363 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 08B99C7EE24 for ; Thu, 11 May 2023 18:53:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239021AbjEKSxI (ORCPT ); Thu, 11 May 2023 14:53:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57318 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238964AbjEKSxE (ORCPT ); Thu, 11 May 2023 14:53:04 -0400 Received: from mail-pg1-x530.google.com (mail-pg1-x530.google.com [IPv6:2607:f8b0:4864:20::530]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A3BDC72A4; Thu, 11 May 2023 11:53:03 -0700 (PDT) Received: by mail-pg1-x530.google.com with SMTP id 41be03b00d2f7-51b4ef5378bso7988424a12.1; Thu, 11 May 2023 11:53:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683831182; x=1686423182; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=i3ptun2f4y66KVFb6kOCBJTEK7iEiDfMyju3agHSIDU=; b=m8bqGYoPywm+QbP1vtb894kCXei4JcogvpUZrKHVPNU2EywkY4I3ID3QHncecPB4z1 yoTNAUdBaf7DeOkGUnKGS8rXrE8oEyAXAUQKJJo/TIEeO7jVcVNffO1lFxnV6zXV4/+5 n2XvuQGq/S2vtdlFE3ScYbFVDc63nCur3gFQZKiR9w6RULUhQWKKkf3VYH5Eer9T8uoN 6daUCS9SK93Bc8rYd8VayLTNZA8uwMTWytPzvlzc4WIWZHqsE3+go2ov8xqUJNAZPZml glGvQ11IHUaB/9JztRLHRkaY1syT80uEiYIKjaS1lnQKnZvu2YWedzMtrvtKLTcanCDK um2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683831182; x=1686423182; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=i3ptun2f4y66KVFb6kOCBJTEK7iEiDfMyju3agHSIDU=; b=U7uPI+RL1dw99e+TA2f76qjcWEv9hitzhoCo/m+pAp56vTuGRKK0tadB9/UydYesEQ TrmBJp5b8Z//tuRVp55MtWFzI9aHZ0AmahjcN2Z4rwgdW0tSzbT/ywPS9M+bqyM2aRrW F5EbJ2hSFZ13naE8YQb1EOV+yI09gevOtCNauSRATZsbhTpZoqBAF9Ek3ATVmCJRgN/1 zOh2dr3IRSE4Xv6N6UNUyLc9+zIGZ5NBpc6zwZRB38JaQPsfYPywOgZyabRNFM3XbyZZ o8mwtYTT3pLw0ATY8RJQtgHHJX0n0InVLDZH49p+sd/yRFWrmO4SbclYlbXvDQnqqLZZ 516w== X-Gm-Message-State: AC+VfDwp9KemX1x8XJC+zXhXzLwwFHp80CHW3wLIuuwlRiegC9joUQIC RinqIxiXWXb7kQUYIWJj9tMCRqltiC0= X-Google-Smtp-Source: ACHHUZ4zWpMmX3jPa8NHHY21Rf1rPbKb3X7P+tVNICK0kzA4XG2YbkcmM1fvY6ZB13gNboOQV2G7/Q== X-Received: by 2002:a17:902:7402:b0:1a9:7a7c:2086 with SMTP id g2-20020a170902740200b001a97a7c2086mr22678782pll.27.1683831182415; Thu, 11 May 2023 11:53:02 -0700 (PDT) Received: from dtor-ws.mtv.corp.google.com ([2620:15c:9d:2:84a:ed9c:4024:c347]) by smtp.gmail.com with ESMTPSA id q5-20020a170902788500b001a980a23804sm6288995pll.4.2023.05.11.11.53.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 May 2023 11:53:01 -0700 (PDT) From: Dmitry Torokhov To: linux-input@vger.kernel.org Cc: Raul E Rangel , linux-kernel@vger.kernel.org Subject: [PATCH 4/7] Input: libps2 - fix NAK handling Date: Thu, 11 May 2023 11:52:44 -0700 Message-ID: <20230511185252.386941-5-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.40.1.606.ga4b1b128d6-goog In-Reply-To: <20230511185252.386941-1-dmitry.torokhov@gmail.com> References: <20230511185252.386941-1-dmitry.torokhov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Do not try to process "resend" or "reject" responses from the device as normal response data for a command. Signed-off-by: Dmitry Torokhov Reviewed-by: Raul E Rangel --- drivers/input/serio/libps2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index d09450eca9a7..14b70a78875d 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -445,7 +445,7 @@ bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data) ps2dev->flags &= ~PS2_FLAG_ACK; wake_up(&ps2dev->wait); - if (data != PS2_RET_ACK) + if (!ps2dev->nak && data != PS2_RET_ACK) ps2_handle_response(ps2dev, data); return true; From patchwork Thu May 11 18:52:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 13238362 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B1A36C7EE22 for ; Thu, 11 May 2023 18:53:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238993AbjEKSxH (ORCPT ); Thu, 11 May 2023 14:53:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57362 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238998AbjEKSxF (ORCPT ); Thu, 11 May 2023 14:53:05 -0400 Received: from mail-pl1-x631.google.com (mail-pl1-x631.google.com [IPv6:2607:f8b0:4864:20::631]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 084C24205; Thu, 11 May 2023 11:53:05 -0700 (PDT) Received: by mail-pl1-x631.google.com with SMTP id d9443c01a7336-1aae5c2423dso86859325ad.3; Thu, 11 May 2023 11:53:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683831184; x=1686423184; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ctA+VGh2kOJyEKyjSwRtHrOrZKFDYE1YmUqRifhUcQY=; b=hlXN1gvmobF0Je9jVGGIrqy0ejPcdWkOScD+rmAwgtq0xmfiih5SUuFBDTvIzzYwBR RrfRc5GgZcWgD9aOa9H9dFXmYjXDLCUY3TXp/33qCYMg9N1buQHDyzANh0R/lx9G0LwE 7zR44Hcg+J68hJMymYmWl/eL8nkY/1OZilYnadl6uPLKiecEn4A06k6TSpqa9xjXST9R lr8eiHTSdNZNoA5nAIHijYLFiG3bkF8hEvjYmvBJ2bxbcZH0yXkoTAy6pHzW/MFzHaEn w0eOApZ/vf8c+KQEaTSpHPR9XJYbWsSwf4i0P+F0QkoSDXJzXNDpz6fmGIG+D5brinZ2 rbug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683831184; x=1686423184; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ctA+VGh2kOJyEKyjSwRtHrOrZKFDYE1YmUqRifhUcQY=; b=iY09DzWS7HCrNd4tXiLLDkcKaoMjF23+DZ+jeAXeQHpliAIv0wlQFTUVpChTmKQ/8p Trq0LToLp+ONecIg04RuSKWPZXR8hq+qo4ApuFTA4PrgyOaQt7GQxYZufXOoYW4MLlGM Rx/sXtMQhBCQ30x09sm/PoMnygXiuiLxd/ITSzGM3mxgZCBmBfdnwssjH6S1Nz7FTYfq CxY/+AAJKOIna7YhWsrb5rGMACQXd02ORj1pYoUQLYcdSdgF8hA6G1iGtKJx/MjTwoB0 dz2mFw4T8jrdtNVkfRfAQDtF0NCaf8C23jj7q9PL3xOKNtMfXLAypErL6o7xcSzIrWZB CtPQ== X-Gm-Message-State: AC+VfDxFjz8jpz2tJg8ytjuLJ+9uQZ9oqLC8wvFzef/jdqhGYs2JIu4s pz/6udUaNpzZx8Oyjd2wIWBIn0LslKI= X-Google-Smtp-Source: ACHHUZ5//gGGqgjBRnaQ8NIZhlUIr4csEhHPEQzmlyqnWdobR9awbFV/U5flbJWtMPHxDiXZbe4xqA== X-Received: by 2002:a17:903:280b:b0:1ab:197d:2de1 with SMTP id kp11-20020a170903280b00b001ab197d2de1mr19744403plb.2.1683831183766; Thu, 11 May 2023 11:53:03 -0700 (PDT) Received: from dtor-ws.mtv.corp.google.com ([2620:15c:9d:2:84a:ed9c:4024:c347]) by smtp.gmail.com with ESMTPSA id q5-20020a170902788500b001a980a23804sm6288995pll.4.2023.05.11.11.53.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 May 2023 11:53:03 -0700 (PDT) From: Dmitry Torokhov To: linux-input@vger.kernel.org Cc: Raul E Rangel , linux-kernel@vger.kernel.org Subject: [PATCH 5/7] Input: libps2 - fix aborting PS/2 commands Date: Thu, 11 May 2023 11:52:45 -0700 Message-ID: <20230511185252.386941-6-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.40.1.606.ga4b1b128d6-goog In-Reply-To: <20230511185252.386941-1-dmitry.torokhov@gmail.com> References: <20230511185252.386941-1-dmitry.torokhov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org When aborting PS/2 command the kernel should [re]set all flags before waking up waiters, otherwise waiting thread may read obsolete values of flags. Reported-by: Raul Rangel Signed-off-by: Dmitry Torokhov Reviewed-by: Raul E Rangel --- drivers/input/serio/libps2.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index 14b70a78875d..09eb605364bb 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -478,15 +478,22 @@ bool ps2_handle_response(struct ps2dev *ps2dev, u8 data) } EXPORT_SYMBOL(ps2_handle_response); +/* + * Clears state of PS/2 device after communication error by resetting majority + * of flags and waking up waiters, if any. + */ void ps2_cmd_aborted(struct ps2dev *ps2dev) { - if (ps2dev->flags & PS2_FLAG_ACK) + unsigned long old_flags = ps2dev->flags; + + /* reset all flags except last nak */ + ps2dev->flags &= PS2_FLAG_NAK; + + if (old_flags & PS2_FLAG_ACK) ps2dev->nak = 1; - if (ps2dev->flags & (PS2_FLAG_ACK | PS2_FLAG_CMD)) + if (old_flags & (PS2_FLAG_ACK | PS2_FLAG_CMD)) wake_up(&ps2dev->wait); - /* reset all flags except last nack */ - ps2dev->flags &= PS2_FLAG_NAK; } EXPORT_SYMBOL(ps2_cmd_aborted); From patchwork Thu May 11 18:52:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 13238365 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C904AC7EE22 for ; Thu, 11 May 2023 18:53:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239035AbjEKSxY (ORCPT ); Thu, 11 May 2023 14:53:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57628 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239034AbjEKSxM (ORCPT ); Thu, 11 May 2023 14:53:12 -0400 Received: from mail-pg1-x532.google.com (mail-pg1-x532.google.com [IPv6:2607:f8b0:4864:20::532]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E4EF54C20; Thu, 11 May 2023 11:53:07 -0700 (PDT) Received: by mail-pg1-x532.google.com with SMTP id 41be03b00d2f7-52160f75920so6116440a12.2; Thu, 11 May 2023 11:53:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683831186; x=1686423186; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ozDcr45ZL3uhTxX7nQir9HbKe06QNXc1uJkqNoy0VS4=; b=KgVUjZQYjLl/1MCLY3aQnypFe6JFHjcjAurP02168P9jK7OOvrUxM09CtPlSgxfuXq eOQC940ITjc7ww/JMwJwaW4dZv46ESZZTmjc81VHB+y+GCFL67GKK7lyRM+BYYA9qPgf MvISNJDcUr8oQoNvKB5EN/sxJnY7VVl3NyA/1tXamvb7ImN7uHPIm5qy1pTcPatjgwWY yvUVlEjoBP0gjaRKP27plcYCscQtRxwqh+yirNutszrFkEaZkgNV99nWsNEKy5pnONgH yJXCITiqbvSgogORDm2L4cGrwWA/TJMexPE2g4OR01h0PusdaEweyuIRJOqwIuxaHY2I zpIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683831186; x=1686423186; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ozDcr45ZL3uhTxX7nQir9HbKe06QNXc1uJkqNoy0VS4=; b=JxVZ895J0RX51NcQpzetVzHTaNE0J1VKTRH9MhvtwPjcJ0GB8Ztt/Drl3ctOqeJ9yr xbafPHScbbWLRKNPdgNRr5jz38em2giKutTXP1nXsTlOEOdm7ftcDnSHphJcbk7Cj/3e AGBCuYwIvJiq58Pk9VnPJAoFBXL6QQINUTLJCfGJS4YwxLdZ7W5VBPehNL4vA+iZhSHj SlA9Tvtqzz+ObMVA8wph8uqUptS5AIB/R9ZsuGWXvWWP1McsznoT3uxnLBqc2XnoFHgX sD6lEVTyXWOpTZatw0wS98KxuP7FTtW8M0ZizurCIM9gtCtgNBR1fGLMYuEhmtztWc2q D0RA== X-Gm-Message-State: AC+VfDwHWzhWCxSlimomQDs356s9kyjCL9ZxMNFAvkLMKN59dqNiO5A5 vH8zWvTJH65Fw1wsg3gWKJygZ+zvc+4= X-Google-Smtp-Source: ACHHUZ5gJ20+rxrTl6B1DSn1eQYAf1XPUxuCXKGcTn+RqYVhJF5MHbAPiz6/rKDe/m3zmQOpaprwzA== X-Received: by 2002:a17:902:c40a:b0:1ab:28ec:bf10 with SMTP id k10-20020a170902c40a00b001ab28ecbf10mr31282200plk.51.1683831185438; Thu, 11 May 2023 11:53:05 -0700 (PDT) Received: from dtor-ws.mtv.corp.google.com ([2620:15c:9d:2:84a:ed9c:4024:c347]) by smtp.gmail.com with ESMTPSA id q5-20020a170902788500b001a980a23804sm6288995pll.4.2023.05.11.11.53.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 May 2023 11:53:04 -0700 (PDT) From: Dmitry Torokhov To: linux-input@vger.kernel.org Cc: Raul E Rangel , linux-kernel@vger.kernel.org Subject: [PATCH 6/7] Input: libps2 - introduce common interrupt handler Date: Thu, 11 May 2023 11:52:46 -0700 Message-ID: <20230511185252.386941-7-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.40.1.606.ga4b1b128d6-goog In-Reply-To: <20230511185252.386941-1-dmitry.torokhov@gmail.com> References: <20230511185252.386941-1-dmitry.torokhov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Instead of exposing inner workings of libps2 to drivers such as atkbd and psmouse, have them define pre-receive and receive callbacks, and provide a common handler that can be used with underlying serio port. While at this add kerneldoc to the module. Signed-off-by: Dmitry Torokhov Reviewed-by: Raul E Rangel --- drivers/input/keyboard/atkbd.c | 73 +++++----- drivers/input/mouse/psmouse-base.c | 53 +++---- drivers/input/serio/libps2.c | 226 ++++++++++++++++++++--------- include/linux/libps2.h | 61 +++++--- 4 files changed, 259 insertions(+), 154 deletions(-) diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 2fb2ad73e796..8ef663a589b3 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -398,47 +398,49 @@ static unsigned int atkbd_compat_scancode(struct atkbd *atkbd, unsigned int code return code; } -/* - * atkbd_interrupt(). Here takes place processing of data received from - * the keyboard into events. - */ - -static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, - unsigned int flags) +static enum ps2_disposition atkbd_pre_receive_byte(struct ps2dev *ps2dev, + u8 data, unsigned int flags) { - struct atkbd *atkbd = atkbd_from_serio(serio); - struct input_dev *dev = atkbd->dev; - unsigned int code = data; - int scroll = 0, hscroll = 0, click = -1; - int value; - unsigned short keycode; + struct serio *serio = ps2dev->serio; dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, flags); #if !defined(__i386__) && !defined (__x86_64__) - if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) { - dev_warn(&serio->dev, "Frame/parity error: %02x\n", flags); - serio_write(serio, ATKBD_CMD_RESEND); - atkbd->resend = true; - goto out; + if ((flags & (SERIO_FRAME | SERIO_PARITY)) && + (~flags & SERIO_TIMEOUT)) { + struct atkbd *atkbd = container_of(ps2dev, struct atkbd, + ps2dev); + + if (!atkbd->resend && atkbd->write) { + dev_warn(&serio->dev, + "Frame/parity error: %02x\n", flags); + serio_write(serio, ATKBD_CMD_RESEND); + atkbd->resend = true; + return PS2_IGNORE; + } } if (!flags && data == ATKBD_RET_ACK) atkbd->resend = false; #endif - if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_ACK)) - if (ps2_handle_ack(&atkbd->ps2dev, data)) - goto out; + return PS2_PROCESS; +} - if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_CMD)) - if (ps2_handle_response(&atkbd->ps2dev, data)) - goto out; +static void atkbd_receive_byte(struct ps2dev *ps2dev, u8 data) +{ + struct serio *serio = ps2dev->serio; + struct atkbd *atkbd = container_of(ps2dev, struct atkbd, ps2dev); + struct input_dev *dev = atkbd->dev; + unsigned int code = data; + int scroll = 0, hscroll = 0, click = -1; + int value; + unsigned short keycode; pm_wakeup_event(&serio->dev, 0); if (!atkbd->enabled) - goto out; + return; input_event(dev, EV_MSC, MSC_RAW, code); @@ -460,16 +462,16 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, case ATKBD_RET_BAT: atkbd->enabled = false; serio_reconnect(atkbd->ps2dev.serio); - goto out; + return; case ATKBD_RET_EMUL0: atkbd->emul = 1; - goto out; + return; case ATKBD_RET_EMUL1: atkbd->emul = 2; - goto out; + return; case ATKBD_RET_RELEASE: atkbd->release = true; - goto out; + return; case ATKBD_RET_ACK: case ATKBD_RET_NAK: if (printk_ratelimit()) @@ -477,18 +479,18 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, "Spurious %s on %s. " "Some program might be trying to access hardware directly.\n", data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); - goto out; + return; case ATKBD_RET_ERR: atkbd->err_count++; dev_dbg(&serio->dev, "Keyboard on %s reports too many keys pressed.\n", serio->phys); - goto out; + return; } code = atkbd_compat_scancode(atkbd, code); if (atkbd->emul && --atkbd->emul) - goto out; + return; keycode = atkbd->keycode[code]; @@ -564,8 +566,6 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, } atkbd->release = false; -out: - return IRQ_HANDLED; } static int atkbd_set_repeat_rate(struct atkbd *atkbd) @@ -1229,7 +1229,8 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) goto fail1; atkbd->dev = dev; - ps2_init(&atkbd->ps2dev, serio); + ps2_init(&atkbd->ps2dev, serio, + atkbd_pre_receive_byte, atkbd_receive_byte); INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work); mutex_init(&atkbd->mutex); @@ -1385,7 +1386,7 @@ static struct serio_driver atkbd_drv = { }, .description = DRIVER_DESC, .id_table = atkbd_serio_ids, - .interrupt = atkbd_interrupt, + .interrupt = ps2_interrupt, .connect = atkbd_connect, .reconnect = atkbd_reconnect, .disconnect = atkbd_disconnect, diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index ed5376099fba..a0aac76b1e41 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -336,17 +336,14 @@ static void psmouse_handle_oob_data(struct psmouse *psmouse, u8 data) } } -/* - * psmouse_interrupt() handles incoming characters, either passing them - * for normal processing or gathering them as command response. - */ -static irqreturn_t psmouse_interrupt(struct serio *serio, - u8 data, unsigned int flags) +static enum ps2_disposition psmouse_pre_receive_byte(struct ps2dev *ps2dev, + u8 data, + unsigned int flags) { - struct psmouse *psmouse = psmouse_from_serio(serio); + struct psmouse *psmouse = container_of(ps2dev, struct psmouse, ps2dev); if (psmouse->state == PSMOUSE_IGNORE) - goto out; + return PS2_IGNORE; if (unlikely((flags & SERIO_TIMEOUT) || ((flags & SERIO_PARITY) && @@ -357,27 +354,25 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, "bad data from KBC -%s%s\n", flags & SERIO_TIMEOUT ? " timeout" : "", flags & SERIO_PARITY ? " bad parity" : ""); - ps2_cmd_aborted(&psmouse->ps2dev); - goto out; + return PS2_ERROR; } if (flags & SERIO_OOB_DATA) { psmouse_handle_oob_data(psmouse, data); - goto out; + return PS2_IGNORE; } - if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_ACK)) - if (ps2_handle_ack(&psmouse->ps2dev, data)) - goto out; + return PS2_PROCESS; +} - if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_CMD)) - if (ps2_handle_response(&psmouse->ps2dev, data)) - goto out; +static void psmouse_receive_byte(struct ps2dev *ps2dev, u8 data) +{ + struct psmouse *psmouse = container_of(ps2dev, struct psmouse, ps2dev); - pm_wakeup_event(&serio->dev, 0); + pm_wakeup_event(&ps2dev->serio->dev, 0); if (psmouse->state <= PSMOUSE_RESYNCING) - goto out; + return; if (psmouse->state == PSMOUSE_ACTIVATED && psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { @@ -386,7 +381,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, psmouse->badbyte = psmouse->packet[0]; __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); psmouse_queue_work(psmouse, &psmouse->resync_work, 0); - goto out; + return; } psmouse->packet[psmouse->pktcnt++] = data; @@ -395,21 +390,21 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) { if (psmouse->pktcnt == 1) { psmouse->last = jiffies; - goto out; + return; } if (psmouse->packet[1] == PSMOUSE_RET_ID || (psmouse->protocol->type == PSMOUSE_HGPK && psmouse->packet[1] == PSMOUSE_RET_BAT)) { __psmouse_set_state(psmouse, PSMOUSE_IGNORE); - serio_reconnect(serio); - goto out; + serio_reconnect(ps2dev->serio); + return; } /* Not a new device, try processing first byte normally */ psmouse->pktcnt = 1; if (psmouse_handle_byte(psmouse)) - goto out; + return; psmouse->packet[psmouse->pktcnt++] = data; } @@ -424,14 +419,11 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, psmouse->badbyte = psmouse->packet[0]; __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); psmouse_queue_work(psmouse, &psmouse->resync_work, 0); - goto out; + return; } psmouse->last = jiffies; psmouse_handle_byte(psmouse); - - out: - return IRQ_HANDLED; } /* @@ -1604,7 +1596,8 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) if (!psmouse || !input_dev) goto err_free; - ps2_init(&psmouse->ps2dev, serio); + ps2_init(&psmouse->ps2dev, serio, + psmouse_pre_receive_byte, psmouse_receive_byte); INIT_DELAYED_WORK(&psmouse->resync_work, psmouse_resync); psmouse->dev = input_dev; snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys); @@ -1786,7 +1779,7 @@ static struct serio_driver psmouse_drv = { }, .description = DRIVER_DESC, .id_table = psmouse_serio_ids, - .interrupt = psmouse_interrupt, + .interrupt = ps2_interrupt, .connect = psmouse_connect, .reconnect = psmouse_reconnect, .fast_reconnect = psmouse_fast_reconnect, diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index 09eb605364bb..7c5fc853072a 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -19,9 +19,22 @@ #define DRIVER_DESC "PS/2 driver library" -MODULE_AUTHOR("Dmitry Torokhov "); -MODULE_DESCRIPTION("PS/2 driver library"); -MODULE_LICENSE("GPL"); +#define PS2_CMD_SETSCALE11 0x00e6 +#define PS2_CMD_SETRES 0x10e8 +#define PS2_CMD_GETID 0x02f2 +#define PS2_CMD_RESET_BAT 0x02ff + +#define PS2_RET_BAT 0xaa +#define PS2_RET_ID 0x00 +#define PS2_RET_ACK 0xfa +#define PS2_RET_NAK 0xfe +#define PS2_RET_ERR 0xfc + +#define PS2_FLAG_ACK BIT(0) /* Waiting for ACK/NAK */ +#define PS2_FLAG_CMD BIT(1) /* Waiting for a command to finish */ +#define PS2_FLAG_CMD1 BIT(2) /* Waiting for the first byte of command response */ +#define PS2_FLAG_WAITID BIT(3) /* Command executing is GET ID */ +#define PS2_FLAG_NAK BIT(4) /* Last transmission was NAKed */ static int ps2_do_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout, unsigned int max_attempts) @@ -76,14 +89,17 @@ static int ps2_do_sendbyte(struct ps2dev *ps2dev, u8 byte, return error; } -/* - * ps2_sendbyte() sends a byte to the device and waits for acknowledge. - * It doesn't handle retransmission, the caller is expected to handle +/** + * ps2_sendbyte - sends a byte to the device and wait for acknowledgement + * @ps2dev: a PS/2 device to send the data to + * @byte: data to be sent to the device + * @timeout: timeout for sending the data and receiving an acknowledge + * + * The function doesn't handle retransmission, the caller is expected to handle * it when needed. * * ps2_sendbyte() can only be called from a process context. */ - int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout) { int retval; @@ -99,6 +115,13 @@ int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout) } EXPORT_SYMBOL(ps2_sendbyte); +/** + * ps2_begin_command - mark beginning of execution of a complex command + * @ps2dev: a PS/2 device executing the command + * + * Serializes a complex/compound command. Once command is finished + * ps2_end_command() should be called. + */ void ps2_begin_command(struct ps2dev *ps2dev) { struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex; @@ -107,6 +130,10 @@ void ps2_begin_command(struct ps2dev *ps2dev) } EXPORT_SYMBOL(ps2_begin_command); +/** + * ps2_end_command - mark end of execution of a complex command + * @ps2dev: a PS/2 device executing the command + */ void ps2_end_command(struct ps2dev *ps2dev) { struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex; @@ -115,11 +142,13 @@ void ps2_end_command(struct ps2dev *ps2dev) } EXPORT_SYMBOL(ps2_end_command); -/* - * ps2_drain() waits for device to transmit requested number of bytes - * and discards them. +/** + * ps2_drain - waits for device to transmit requested number of bytes + * and discards them + * @ps2dev: the PS/2 device that should be drained + * @maxbytes: maximum number of bytes to be drained + * @timeout: time to drain the device */ - void ps2_drain(struct ps2dev *ps2dev, size_t maxbytes, unsigned int timeout) { if (maxbytes > sizeof(ps2dev->cmdbuf)) { @@ -142,11 +171,11 @@ void ps2_drain(struct ps2dev *ps2dev, size_t maxbytes, unsigned int timeout) } EXPORT_SYMBOL(ps2_drain); -/* - * ps2_is_keyboard_id() checks received ID byte against the list of - * known keyboard IDs. +/** + * ps2_is_keyboard_id - checks received ID byte against the list of + * known keyboard IDs + * @id_byte: data byte that should be checked */ - bool ps2_is_keyboard_id(u8 id_byte) { static const u8 keyboard_ids[] = { @@ -167,7 +196,6 @@ EXPORT_SYMBOL(ps2_is_keyboard_id); * response and tries to reduce remaining timeout to speed up command * completion. */ - static int ps2_adjust_timeout(struct ps2dev *ps2dev, unsigned int command, unsigned int timeout) { @@ -217,13 +245,19 @@ static int ps2_adjust_timeout(struct ps2dev *ps2dev, return timeout; } -/* - * ps2_command() sends a command and its parameters to the mouse, - * then waits for the response and puts it in the param array. +/** + * __ps2_command - send a command to PS/2 device + * @ps2dev: the PS/2 device that should execute the command + * @param: a buffer containing parameters to be sent along with the command, + * or place where the results of the command execution will be deposited, + * or both + * @command: command word that encodes the command itself, as well as number of + * additional parameter bytes that should be sent to the device and expected + * length of the command response * - * ps2_command() can only be called from a process context + * Not serialized. Callers should use ps2_begin_command() and ps2_end_command() + * to ensure proper serialization for complex commands. */ - int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command) { unsigned int timeout; @@ -327,6 +361,20 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command) } EXPORT_SYMBOL(__ps2_command); +/** + * ps2_command - send a command to PS/2 device + * @ps2dev: the PS/2 device that should execute the command + * @param: a buffer containing parameters to be sent along with the command, + * or place where the results of the command execution will be deposited, + * or both + * @command: command word that encodes the command itself, as well as number of + * additional parameter bytes that should be sent to the device and expected + * length of the command response + * + * Note: ps2_command() serializes the command execution so that only one + * command can be executed at a time for either individual port or the entire + * 8042 controller. + */ int ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command) { int rc; @@ -339,14 +387,16 @@ int ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command) } EXPORT_SYMBOL(ps2_command); -/* - * ps2_sliced_command() sends an extended PS/2 command to the mouse - * using sliced syntax, understood by advanced devices, such as Logitech - * or Synaptics touchpads. The command is encoded as: +/** + * ps2_sliced_command - sends an extended PS/2 command to a mouse + * @ps2dev: the PS/2 device that should execute the command + * @command: command byte + * + * The command is sent using "sliced" syntax understood by advanced devices, + * such as Logitech or Synaptics touchpads. The command is encoded as: * 0xE6 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where (rr*64)+(ss*16)+(tt*4)+uu * is the command. */ - int ps2_sliced_command(struct ps2dev *ps2dev, u8 command) { int i; @@ -372,12 +422,22 @@ int ps2_sliced_command(struct ps2dev *ps2dev, u8 command) } EXPORT_SYMBOL(ps2_sliced_command); -/* - * ps2_init() initializes ps2dev structure +/** + * ps2_init - initializes ps2dev structure + * @ps2dev: structure to be initialized + * @serio: serio port associated with the PS/2 device + * @pre_receive_handler: validation handler to check basic communication state + * @receive_handler: main protocol handler + * + * Prepares ps2dev structure for use in drivers for PS/2 devices. */ - -void ps2_init(struct ps2dev *ps2dev, struct serio *serio) +void ps2_init(struct ps2dev *ps2dev, struct serio *serio, + ps2_pre_receive_handler_t pre_receive_handler, + ps2_receive_handler_t receive_handler) { + ps2dev->pre_receive_handler = pre_receive_handler; + ps2dev->receive_handler = receive_handler; + mutex_init(&ps2dev->cmd_mutex); lockdep_set_subclass(&ps2dev->cmd_mutex, serio->depth); init_waitqueue_head(&ps2dev->wait); @@ -387,11 +447,35 @@ void ps2_init(struct ps2dev *ps2dev, struct serio *serio) EXPORT_SYMBOL(ps2_init); /* - * ps2_handle_ack() is supposed to be used in interrupt handler - * to properly process ACK/NAK of a command from a PS/2 device. + * ps2_handle_response() stores device's response to a command and notifies + * the process waiting for completion of the command. Note that there is a + * distinction between waiting for the first byte of the response, and + * waiting for subsequent bytes. It is done so that callers could shorten + * timeouts once first byte of response is received. */ +static void ps2_handle_response(struct ps2dev *ps2dev, u8 data) +{ + if (ps2dev->cmdcnt) + ps2dev->cmdbuf[--ps2dev->cmdcnt] = data; -bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data) + if (ps2dev->flags & PS2_FLAG_CMD1) { + ps2dev->flags &= ~PS2_FLAG_CMD1; + if (ps2dev->cmdcnt) + wake_up(&ps2dev->wait); + } + + if (!ps2dev->cmdcnt) { + ps2dev->flags &= ~PS2_FLAG_CMD; + wake_up(&ps2dev->wait); + } +} + +/* + * ps2_handle_ack() processes ACK/NAK of a command from a PS/2 device, + * possibly applying workarounds for mice not acknowledging the "get ID" + * command. + */ +static void ps2_handle_ack(struct ps2dev *ps2dev, u8 data) { switch (data) { case PS2_RET_ACK: @@ -436,53 +520,25 @@ bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data) */ dev_dbg(&ps2dev->serio->dev, "unexpected %#02x\n", data); ps2dev->flags &= ~PS2_FLAG_WAITID; - return true; + return; } if (!ps2dev->nak) ps2dev->flags &= ~PS2_FLAG_NAK; ps2dev->flags &= ~PS2_FLAG_ACK; - wake_up(&ps2dev->wait); if (!ps2dev->nak && data != PS2_RET_ACK) ps2_handle_response(ps2dev, data); - - return true; -} -EXPORT_SYMBOL(ps2_handle_ack); - -/* - * ps2_handle_response() is supposed to be used in interrupt handler - * to properly store device's response to a command and notify process - * waiting for completion of the command. - */ - -bool ps2_handle_response(struct ps2dev *ps2dev, u8 data) -{ - if (ps2dev->cmdcnt) - ps2dev->cmdbuf[--ps2dev->cmdcnt] = data; - - if (ps2dev->flags & PS2_FLAG_CMD1) { - ps2dev->flags &= ~PS2_FLAG_CMD1; - if (ps2dev->cmdcnt) - wake_up(&ps2dev->wait); - } - - if (!ps2dev->cmdcnt) { - ps2dev->flags &= ~PS2_FLAG_CMD; + else wake_up(&ps2dev->wait); - } - - return true; } -EXPORT_SYMBOL(ps2_handle_response); /* * Clears state of PS/2 device after communication error by resetting majority * of flags and waking up waiters, if any. */ -void ps2_cmd_aborted(struct ps2dev *ps2dev) +static void ps2_cleanup(struct ps2dev *ps2dev) { unsigned long old_flags = ps2dev->flags; @@ -494,6 +550,46 @@ void ps2_cmd_aborted(struct ps2dev *ps2dev) if (old_flags & (PS2_FLAG_ACK | PS2_FLAG_CMD)) wake_up(&ps2dev->wait); +} +/** + * ps2_interrupt - common interrupt handler for PS/2 devices + * @serio: serio port for the device + * @data: a data byte received from the device + * @flags: flags such as %SERIO_PARITY or %SERIO_TIMEOUT indicating state of + * the data transfer + * + * ps2_interrupt() invokes pre-receive handler, optionally handles command + * acknowledgement and response from the device, and finally passes the data + * to the main protocol handler for future processing. + */ +irqreturn_t ps2_interrupt(struct serio *serio, u8 data, unsigned int flags) { + struct ps2dev *ps2dev = serio_get_drvdata(serio); + enum ps2_disposition rc; + + rc = ps2dev->pre_receive_handler(ps2dev, data, flags); + switch (rc) { + case PS2_ERROR: + ps2_cleanup(ps2dev); + break; + + case PS2_IGNORE: + break; + + case PS2_PROCESS: + if (ps2dev->flags & PS2_FLAG_ACK) + ps2_handle_ack(ps2dev, data); + else if (ps2dev->flags & PS2_FLAG_CMD) + ps2_handle_response(ps2dev, data); + else + ps2dev->receive_handler(ps2dev, data); + break; + } + + return IRQ_HANDLED; } -EXPORT_SYMBOL(ps2_cmd_aborted); +EXPORT_SYMBOL(ps2_interrupt); + +MODULE_AUTHOR("Dmitry Torokhov "); +MODULE_DESCRIPTION("PS/2 driver library"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/libps2.h b/include/linux/libps2.h index 193dd53ad18b..9ca9ce4e6e64 100644 --- a/include/linux/libps2.h +++ b/include/linux/libps2.h @@ -8,43 +8,59 @@ */ #include +#include #include #include #include -#define PS2_CMD_SETSCALE11 0x00e6 -#define PS2_CMD_SETRES 0x10e8 -#define PS2_CMD_GETID 0x02f2 -#define PS2_CMD_RESET_BAT 0x02ff +struct ps2dev; -#define PS2_RET_BAT 0xaa -#define PS2_RET_ID 0x00 -#define PS2_RET_ACK 0xfa -#define PS2_RET_NAK 0xfe -#define PS2_RET_ERR 0xfc +/** + * enum ps2_disposition - indicates how received byte should be handled + * @PS2_PROCESS: pass to the main protocol handler, process normally + * @PS2_IGNORE: skip the byte + * @PS2_ERROR: do not process the byte, abort command in progress + */ +enum ps2_disposition { + PS2_PROCESS, + PS2_IGNORE, + PS2_ERROR, +}; -#define PS2_FLAG_ACK BIT(0) /* Waiting for ACK/NAK */ -#define PS2_FLAG_CMD BIT(1) /* Waiting for a command to finish */ -#define PS2_FLAG_CMD1 BIT(2) /* Waiting for the first byte of command response */ -#define PS2_FLAG_WAITID BIT(3) /* Command executing is GET ID */ -#define PS2_FLAG_NAK BIT(4) /* Last transmission was NAKed */ +typedef enum ps2_disposition (*ps2_pre_receive_handler_t)(struct ps2dev *, u8, + unsigned int); +typedef void (*ps2_receive_handler_t)(struct ps2dev *, u8); +/** + * struct ps2dev - represents a device using PS/2 protocol + * @serio: a serio port used by the PS/2 device + * @cmd_mutex: a mutex ensuring that only one command is executing at a time + * @wait: a waitqueue used to signal completion from the serio interrupt handler + * @flags: various internal flags indicating stages of PS/2 command execution + * @cmdbuf: buffer holding command response + * @cmdcnt: outstanding number of bytes of the command response + * @nak: a byte transmitted by the device when it refuses command + * @pre_receive_handler: checks communication errors and returns disposition + * (&enum ps2_disposition) of the received data byte + * @receive_handler: main handler of particular PS/2 protocol, such as keyboard + * or mouse protocol + */ struct ps2dev { struct serio *serio; - - /* Ensures that only one command is executing at a time */ struct mutex cmd_mutex; - - /* Used to signal completion from interrupt handler */ wait_queue_head_t wait; - unsigned long flags; u8 cmdbuf[8]; u8 cmdcnt; u8 nak; + + ps2_pre_receive_handler_t pre_receive_handler; + ps2_receive_handler_t receive_handler; }; -void ps2_init(struct ps2dev *ps2dev, struct serio *serio); +void ps2_init(struct ps2dev *ps2dev, struct serio *serio, + ps2_pre_receive_handler_t pre_receive_handler, + ps2_receive_handler_t receive_handler); int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout); void ps2_drain(struct ps2dev *ps2dev, size_t maxbytes, unsigned int timeout); void ps2_begin_command(struct ps2dev *ps2dev); @@ -52,9 +68,8 @@ void ps2_end_command(struct ps2dev *ps2dev); int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command); int ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command); int ps2_sliced_command(struct ps2dev *ps2dev, u8 command); -bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data); -bool ps2_handle_response(struct ps2dev *ps2dev, u8 data); -void ps2_cmd_aborted(struct ps2dev *ps2dev); bool ps2_is_keyboard_id(u8 id); +irqreturn_t ps2_interrupt(struct serio *serio, u8 data, unsigned int flags); + #endif /* _LIBPS2_H */ From patchwork Thu May 11 18:52:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 13238364 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3CF60C7EE22 for ; Thu, 11 May 2023 18:53:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238927AbjEKSxO (ORCPT ); Thu, 11 May 2023 14:53:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57588 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238932AbjEKSxL (ORCPT ); Thu, 11 May 2023 14:53:11 -0400 Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E281C49FA; Thu, 11 May 2023 11:53:07 -0700 (PDT) Received: by mail-pl1-x62d.google.com with SMTP id d9443c01a7336-1aad5245632so64988175ad.3; Thu, 11 May 2023 11:53:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683831187; x=1686423187; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=b3FHdxcnZDHBJfwaP/5YmMMNOS9nBKD4If1FaL3R/o8=; b=ec49sEyTE5xx2tkdVvEwvcakKrHRzVcHLnXJA2iPrdp29iMdhPkl+peowh9GGhMeby RyzV24uF5jeUp7LYejufSY9mWDxWI0GHjGcZDvBVbRCcue5ofVy+wLNq1UX13CWUbgj6 xycCENFG8MLMeQ3KvsZa1MTXqJ4aVnME/GvxhYpDGf0WH/ewu4zOzL+tJ27cpRX4KUCW Hs11e0UtOZLlNdbAEJnCWSG9dLqCpbfmtInVdZ5SzKnnIpuolJQo6YtOV3vjp3E+qtVP Dv0iKOx1atQtPn4E2Gz0tb5GB4u4eS4Wda3TZIOCXUJiUpxgNPO5zXlCVDeQcJWLGInE P5Hg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683831187; x=1686423187; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=b3FHdxcnZDHBJfwaP/5YmMMNOS9nBKD4If1FaL3R/o8=; b=NEHLjq5L9RAhqBV9GBgK3vnawOkRWkI5jfyn2fCaU3CLnIDnUL2HOVF5G9WKuHmlWx klleMQXLycEJu4thQ0LTh7dw/wYxObLAgi6Ws9YHE6nHICOIzGyHXYU+k/RRcSdgUnX2 31Ax8hixl6fLb/sXA0qAa8EpKhMX2crRvptOV8NP3S+Q5e4LOKE8qbxFSOJD05QkG2Oe BcZ40ZRiPSSQ/dLpflPvblVszY8jm8MB7VBXBm6iqM4HSiDhhaHZnN0VglHy2oW0Cmjt umlO8yLlFcZt1/varPiIr/RQgTaz/LXrvPbL0IrEoTxpqrFk2P0zln2A+f/5sD2+4vwR Vezg== X-Gm-Message-State: AC+VfDw8kqF2AzuJCKpAdG8BjAkgU/0LhCXtcGPLvtUoxetn+fsOzKpP wjMYNyY1Tf7+A5tvd8wz6pQjucPxbz4= X-Google-Smtp-Source: ACHHUZ5PFqhArb3xXxeEE0naJWLQMFeiWuCjw2lAkk4uUP+2VZdnKQwzTZbSviNJEokbv5vbMHBrqQ== X-Received: by 2002:a17:903:44c:b0:1ab:27e7:ad76 with SMTP id iw12-20020a170903044c00b001ab27e7ad76mr21361943plb.45.1683831186628; Thu, 11 May 2023 11:53:06 -0700 (PDT) Received: from dtor-ws.mtv.corp.google.com ([2620:15c:9d:2:84a:ed9c:4024:c347]) by smtp.gmail.com with ESMTPSA id q5-20020a170902788500b001a980a23804sm6288995pll.4.2023.05.11.11.53.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 May 2023 11:53:06 -0700 (PDT) From: Dmitry Torokhov To: linux-input@vger.kernel.org Cc: Raul E Rangel , linux-kernel@vger.kernel.org Subject: [PATCH 7/7] Input: libps2 - do not discard non-ack bytes when controlling LEDs Date: Thu, 11 May 2023 11:52:47 -0700 Message-ID: <20230511185252.386941-8-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.40.1.606.ga4b1b128d6-goog In-Reply-To: <20230511185252.386941-1-dmitry.torokhov@gmail.com> References: <20230511185252.386941-1-dmitry.torokhov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Upon receiving a PS/2 command the device and controller are supposed to stop sending normal data (scancodes or movement packets) and instead immediately start delivering ACK/NAK and command response. Unfortunately often EC has an output buffer which may contain latched data by the time the EC receives a command from the host. The kernel used to ignore such data, but that may cause "stuck" keys if the data dropped happens to be a break code or a part of a break code. This occasionally happens, for example, on Chromebooks when the kernel tries to toggle CapsLock LED on a keyboard while user releases Alt+Search keyboard shortcut. Fix this by passing the first non-ACK byte to the normal handler for a handful of PS/2 commands that are expected to be used during normal device operation (as opposed to probe/configuration time). Signed-off-by: Dmitry Torokhov Reviewed-by: Raul E Rangel --- drivers/input/serio/libps2.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index 7c5fc853072a..6d78a1fe00c1 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -21,7 +21,10 @@ #define PS2_CMD_SETSCALE11 0x00e6 #define PS2_CMD_SETRES 0x10e8 +#define PS2_CMD_EX_SETLEDS 0x20eb +#define PS2_CMD_SETLEDS 0x10ed #define PS2_CMD_GETID 0x02f2 +#define PS2_CMD_SETREP 0x10f3 /* Set repeat rate/set report rate */ #define PS2_CMD_RESET_BAT 0x02ff #define PS2_RET_BAT 0xaa @@ -35,6 +38,7 @@ #define PS2_FLAG_CMD1 BIT(2) /* Waiting for the first byte of command response */ #define PS2_FLAG_WAITID BIT(3) /* Command executing is GET ID */ #define PS2_FLAG_NAK BIT(4) /* Last transmission was NAKed */ +#define PS2_FLAG_PASS_NOACK BIT(5) /* Pass non-ACK byte to receive handler */ static int ps2_do_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout, unsigned int max_attempts) @@ -281,9 +285,28 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command) serio_pause_rx(ps2dev->serio); - /* Some mice do not ACK the "get ID" command, prepare to handle this. */ - ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0; ps2dev->cmdcnt = receive; + + switch (command) { + case PS2_CMD_GETID: + /* + * Some mice do not ACK the "get ID" command, prepare to + * handle this. + */ + ps2dev->flags = PS2_FLAG_WAITID; + break; + + case PS2_CMD_SETLEDS: + case PS2_CMD_EX_SETLEDS: + case PS2_CMD_SETREP: + ps2dev->flags = PS2_FLAG_PASS_NOACK; + break; + + default: + ps2dev->flags = 0; + break; + } + if (receive) { /* Indicate that we expect response to the command. */ ps2dev->flags |= PS2_FLAG_CMD | PS2_FLAG_CMD1; @@ -512,14 +535,19 @@ static void ps2_handle_ack(struct ps2dev *ps2dev, u8 data) * Do not signal errors if we get unexpected reply while * waiting for an ACK to the initial (first) command byte: * the device might not be quiesced yet and continue - * delivering data. + * delivering data. For certain commands (such as set leds and + * set repeat rate) that can be used during normal device + * operation, we even pass this data byte to the normal receive + * handler. * Note that we reset PS2_FLAG_WAITID flag, so the workaround * for mice not acknowledging the Get ID command only triggers * on the 1st byte; if device spews data we really want to see * a real ACK from it. */ dev_dbg(&ps2dev->serio->dev, "unexpected %#02x\n", data); - ps2dev->flags &= ~PS2_FLAG_WAITID; + if (ps2dev->flags & PS2_FLAG_PASS_NOACK) + ps2dev->receive_handler(ps2dev, data); + ps2dev->flags &= ~(PS2_FLAG_WAITID | PS2_FLAG_PASS_NOACK); return; }