From patchwork Thu Sep 5 04:17:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 13791716 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 59698CD4F50 for ; Thu, 5 Sep 2024 04:28:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=5IVs44o6ciGNOoB3tvSvkl1E7l7ddGpRPi+mMdxWbfc=; b=QZW0HAChTcJtYo+k8yqrYdgaAd UX2cydBkLW91cXMCQeu2/9zAQbvXVhviurp1HbXQgDuQBqHhnj91T1kIRzlPlvbEb+NbT44WKCq0F FjFXDSOQOqxaxd9bo9+pYKkxEEGOTL5MN7CGkvrJOTN+xATgLqgirBcyzNeONOoU03T+dugnRbUDQ rQP/dq8MzgRH0jVpCDGYzb+54l5ZHimYX75cb+BGYJEuV+zEWKLEPTLhq6lzIOts1iJDihXMQmjSn 9Kc3B7a4nhin74ZInamyH0BE72p2eLes/BtY8a8d1XgonJFN15w+wFQdk/v1oyTfIJbQDv6Tg2nEg PtVgk8sg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sm46U-00000006vrH-3wrF; Thu, 05 Sep 2024 04:28:18 +0000 Received: from mail-pf1-x42e.google.com ([2607:f8b0:4864:20::42e]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sm3wV-00000006tQU-35I1 for linux-arm-kernel@lists.infradead.org; Thu, 05 Sep 2024 04:18:01 +0000 Received: by mail-pf1-x42e.google.com with SMTP id d2e1a72fcca58-7143ae1b48fso210505b3a.1 for ; Wed, 04 Sep 2024 21:17:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1725509878; x=1726114678; darn=lists.infradead.org; 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=5IVs44o6ciGNOoB3tvSvkl1E7l7ddGpRPi+mMdxWbfc=; b=MtVB5W2aEjaqYi0QoUOpKOvNbFkZAlqP+f0/a1e0dCdJOUx6EUnnsErpj1D+xZNMrM 20278LxCbl3fKNTyM0aJHyHrWrMoNb2zg6mxCvBSqzcQcGTUSLsUBtvK9ZDLjm/kazi/ okDjAnKB9gN36C1nXrFn8/rxk9UCOnHyzJukgjF/KhDs/jiFHXU7pyHtaY2ndwwIvJ60 9Tr/JuANseHKxhf3w+GATpNLqKmzYQww3m9QORIWzpM2a3lTn7jVCO6poKQiIFvtaY5k s+IC5efTfwFfKap7LwRICkWB3PmWBAfAW7rTOHCmlZBdpvpkiv2OqBUWSWxsyV1wiTSY TPTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725509878; x=1726114678; 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=5IVs44o6ciGNOoB3tvSvkl1E7l7ddGpRPi+mMdxWbfc=; b=UfSZ/4gRyTPhe86XirD1ja4BLub6UZnCrN7ypcw/AMtL/mJw6TrybS47ihYZOuxPej /U3ze95jad8bC7emgWNLT29PAqyowvbDtfN0o2mojfuOqblTS6kIPGd8vfABOj3lXeGD gTTkouaugBH4jEpTMA5ucSecR64NL89VydRFVmdmMQRms8dmYqeUWGvfliZk4QsUTXwl tqSBEKnNHss4RKTpQiwtWI6ox4uQhwenNanzg53P3xnrdaDYLkgypT3nqAyMd+VZIUEU lL+rKUqkwNv0lcYnvuANuTTazkTfIB5ufia/35H2x2U46t1KJkCKBYiaoNzcjKmiVDVg NoLw== X-Forwarded-Encrypted: i=1; AJvYcCWWhthi63iQvQj5rl/TXytI2BuckCNm+YxBfg6/YtYkgT1ohT2zTty+jwyisn2uEH4/qj443IrUDEOUMu7k5B1f@lists.infradead.org X-Gm-Message-State: AOJu0YyI1OOi1ibGRpBOrIwh1U7UW9M1B6bCY+oO2W8JrdCpxY/ijF5t O7U449e2ZLEBlljab2rsdWLQLYCgPjRmEqxD/Uqq5pRArSgkSSCJA/bFTQ== X-Google-Smtp-Source: AGHT+IHw/pyP6EniZwd1+0N9t+8Gq3aDd7Fq8D4lnLSFHwaJBTj9phdK/nCIOoeA80+G8TcVQfUhXg== X-Received: by 2002:a05:6a00:2da8:b0:70e:8070:f9d0 with SMTP id d2e1a72fcca58-7173fa40bcfmr14087981b3a.9.1725509878530; Wed, 04 Sep 2024 21:17:58 -0700 (PDT) Received: from dtor-ws.sjc.corp.google.com ([2620:15c:9d:2:13bd:b4e:4c0f:4c37]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-7d4fbd8d52esm2450216a12.32.2024.09.04.21.17.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Sep 2024 21:17:58 -0700 (PDT) From: Dmitry Torokhov To: linux-input@vger.kernel.org Cc: =?utf-8?q?Pali_Roh=C3=A1r?= , Helge Deller , "K. Y. Srinivasan" , Wei Liu , Dexuan Cui , Samuel Holland , Lyude Paul , Michal Simek , Hans de Goede , linux-kernel@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev Subject: [PATCH 10/24] Input: gscps2 - use guard notation when acquiring spinlock Date: Wed, 4 Sep 2024 21:17:15 -0700 Message-ID: <20240905041732.2034348-11-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.46.0.469.g59c65b2a67-goog In-Reply-To: <20240905041732.2034348-1-dmitry.torokhov@gmail.com> References: <20240905041732.2034348-1-dmitry.torokhov@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240904_211759_816725_AE21DEBC X-CRM114-Status: GOOD ( 17.56 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Using guard notation makes the code more compact and error handling more robust by ensuring that locks are released in all code paths when control leaves critical section. Signed-off-by: Dmitry Torokhov --- drivers/input/serio/gscps2.c | 114 +++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 52 deletions(-) diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index d94c01eb3fc9..cf0603d1a113 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -145,7 +145,6 @@ static void gscps2_flush(struct gscps2port *ps2port) static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data) { - unsigned long flags; char __iomem *addr = ps2port->addr; if (!wait_TBE(addr)) { @@ -156,9 +155,8 @@ static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data) while (gscps2_readb_status(addr) & GSC_STAT_RBNE) /* wait */; - spin_lock_irqsave(&ps2port->lock, flags); - writeb(data, addr+GSC_XMTDATA); - spin_unlock_irqrestore(&ps2port->lock, flags); + scoped_guard(spinlock_irqsave, &ps2port->lock) + writeb(data, addr+GSC_XMTDATA); /* this is ugly, but due to timing of the port it seems to be necessary. */ mdelay(6); @@ -177,19 +175,19 @@ static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data) static void gscps2_enable(struct gscps2port *ps2port, int enable) { - unsigned long flags; u8 data; /* now enable/disable the port */ - spin_lock_irqsave(&ps2port->lock, flags); - gscps2_flush(ps2port); - data = gscps2_readb_control(ps2port->addr); - if (enable) - data |= GSC_CTRL_ENBL; - else - data &= ~GSC_CTRL_ENBL; - gscps2_writeb_control(data, ps2port->addr); - spin_unlock_irqrestore(&ps2port->lock, flags); + scoped_guard(spinlock_irqsave, &ps2port->lock) { + gscps2_flush(ps2port); + data = gscps2_readb_control(ps2port->addr); + if (enable) + data |= GSC_CTRL_ENBL; + else + data &= ~GSC_CTRL_ENBL; + gscps2_writeb_control(data, ps2port->addr); + } + wait_TBE(ps2port->addr); gscps2_flush(ps2port); } @@ -203,15 +201,56 @@ static void gscps2_reset(struct gscps2port *ps2port) unsigned long flags; /* reset the interface */ - spin_lock_irqsave(&ps2port->lock, flags); + guard(spinlock_irqsave)(&ps2port->lock); gscps2_flush(ps2port); writeb(0xff, ps2port->addr + GSC_RESET); gscps2_flush(ps2port); - spin_unlock_irqrestore(&ps2port->lock, flags); } static LIST_HEAD(ps2port_list); +static void gscps2_read_data(struct gscps2port *ps2port) +{ + u8 status; + + do { + status = gscps2_readb_status(ps2port->addr); + if (!(status & GSC_STAT_RBNE)) + break; + + ps2port->buffer[ps2port->append].ste = status; + ps2port->buffer[ps2port->append].data = + gscps2_readb_input(ps2port->addr); + } while (true); +} + +static bool gscps2_report_data(struct gscps2port *ps2port) +{ + unsigned int rxflags; + u8 data, status; + + while (ps2port->act != ps2port->append) { + /* + * Did new data arrived while we read existing data ? + * If yes, exit now and let the new irq handler start + * over again. + */ + if (gscps2_readb_status(ps2port->addr) & GSC_STAT_CMPINTR) + return true; + + status = ps2port->buffer[ps2port->act].str; + data = ps2port->buffer[ps2port->act].data; + + ps2port->act = (ps2port->act + 1) & BUFFER_SIZE; + rxflags = ((status & GSC_STAT_TERR) ? SERIO_TIMEOUT : 0 ) | + ((status & GSC_STAT_PERR) ? SERIO_PARITY : 0 ); + + serio_interrupt(ps2port->port, data, rxflags); + } + + return false; +} + /** * gscps2_interrupt() - Interruption service routine * @@ -229,47 +268,18 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev) struct gscps2port *ps2port; list_for_each_entry(ps2port, &ps2port_list, node) { + guard(spinlock_irqsave)(&ps2port->lock); - unsigned long flags; - spin_lock_irqsave(&ps2port->lock, flags); - - while ( (ps2port->buffer[ps2port->append].str = - gscps2_readb_status(ps2port->addr)) & GSC_STAT_RBNE ) { - ps2port->buffer[ps2port->append].data = - gscps2_readb_input(ps2port->addr); - ps2port->append = ((ps2port->append+1) & BUFFER_SIZE); - } - - spin_unlock_irqrestore(&ps2port->lock, flags); - + gscps2_read_data(ps2port); } /* list_for_each_entry */ /* all data was read from the ports - now report the data to upper layer */ - list_for_each_entry(ps2port, &ps2port_list, node) { - - while (ps2port->act != ps2port->append) { - - unsigned int rxflags; - u8 data, status; - - /* Did new data arrived while we read existing data ? - If yes, exit now and let the new irq handler start over again */ - if (gscps2_readb_status(ps2port->addr) & GSC_STAT_CMPINTR) - return IRQ_HANDLED; - - status = ps2port->buffer[ps2port->act].str; - data = ps2port->buffer[ps2port->act].data; - - ps2port->act = ((ps2port->act+1) & BUFFER_SIZE); - rxflags = ((status & GSC_STAT_TERR) ? SERIO_TIMEOUT : 0 ) | - ((status & GSC_STAT_PERR) ? SERIO_PARITY : 0 ); - - serio_interrupt(ps2port->port, data, rxflags); - - } /* while() */ - - } /* list_for_each_entry */ + if (gscps2_report_data(ps2port)) { + /* More data ready - break early to restart interrupt */ + break; + } + } return IRQ_HANDLED; }