From nobody Thu Dec 18 16:53:43 2025 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 E1F3EC10F05 for ; Mon, 11 Dec 2023 17:14:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344521AbjLKROI (ORCPT ); Mon, 11 Dec 2023 12:14:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52098 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344491AbjLKROE (ORCPT ); Mon, 11 Dec 2023 12:14:04 -0500 Received: from mail.hugovil.com (mail.hugovil.com [162.243.120.170]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CAD20BD; Mon, 11 Dec 2023 09:14:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=hugovil.com ; s=x; h=Subject:Content-Transfer-Encoding:MIME-Version:Message-Id:Date:Cc:To :From:subject:date:message-id:reply-to; bh=KQJGMCi+9vgzmcgkV00ZLgFOlfqhKFVUpyjrvhiM+CI=; b=Ca5GYD9GRgTNy7UiE9F73MCJjP mAEhiHSrDq9m0i4zEXMBP1l38WcG4dRKE0mk1Nl5bFphQM9qLZE58kJ3LKhFCWwNWEW2fq2MUPokU MwAufwxxOu7GBU0ZwL/AvkZlYOgcDA7uALJxMSotD/lfrxizqoiH6focpJh70OWRRm3Q=; Received: from modemcable168.174-80-70.mc.videotron.ca ([70.80.174.168]:56730 helo=pettiford.lan) by mail.hugovil.com with esmtpa (Exim 4.92) (envelope-from ) id 1rCjr1-0003yC-SU; Mon, 11 Dec 2023 12:14:05 -0500 From: Hugo Villeneuve To: gregkh@linuxfoundation.org, jirislaby@kernel.org, hvilleneuve@dimonoff.com, jringle@gridpoint.com, tomasz.mon@camlingroup.com Cc: linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org, hugo@hugovil.com, stable@vger.kernel.org Date: Mon, 11 Dec 2023 12:13:51 -0500 Message-Id: <20231211171353.2901416-5-hugo@hugovil.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231211171353.2901416-1-hugo@hugovil.com> References: <20231211171353.2901416-1-hugo@hugovil.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-SA-Exim-Connect-IP: 70.80.174.168 X-SA-Exim-Mail-From: hugo@hugovil.com Subject: [PATCH v2 4/6] serial: sc16is7xx: change EFR lock to operate on each channels X-SA-Exim-Version: 4.2.1 (built Wed, 08 May 2019 21:11:16 +0000) X-SA-Exim-Scanned: Yes (on mail.hugovil.com) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Hugo Villeneuve Now that the driver has been converted to use one regmap per port, change efr locking to operate on a channel basis instead of on the whole IC. Fixes: 3837a0379533 ("serial: sc16is7xx: improve regmap debugfs by using on= e regmap per port") Cc: stable@vger.kernel.org # 6.1.x: 3837a03 serial: sc16is7xx: improve regm= ap debugfs by using one regmap per port Signed-off-by: Hugo Villeneuve --- drivers/tty/serial/sc16is7xx.c | 49 ++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 0a7a9aa5c9fa..0bda9b74d096 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -323,6 +323,7 @@ struct sc16is7xx_one_config { struct sc16is7xx_one { struct uart_port port; struct regmap *regmap; + struct mutex efr_lock; /* EFR registers access */ struct kthread_work tx_work; struct kthread_work reg_work; struct kthread_delayed_work ms_work; @@ -342,7 +343,6 @@ struct sc16is7xx_port { unsigned char buf[SC16IS7XX_FIFO_SIZE]; struct kthread_worker kworker; struct task_struct *kworker_task; - struct mutex efr_lock; struct sc16is7xx_one p[]; }; =20 @@ -494,7 +494,6 @@ static bool sc16is7xx_regmap_precious(struct device *de= v, unsigned int reg) =20 static int sc16is7xx_set_baud(struct uart_port *port, int baud) { - struct sc16is7xx_port *s =3D dev_get_drvdata(port->dev); struct sc16is7xx_one *one =3D to_sc16is7xx_one(port, port); u8 lcr; u8 prescaler =3D 0; @@ -518,7 +517,7 @@ static int sc16is7xx_set_baud(struct uart_port *port, i= nt baud) * because the bulk of the interrupt processing is run as a workqueue * job in thread context. */ - mutex_lock(&s->efr_lock); + mutex_lock(&one->efr_lock); =20 lcr =3D sc16is7xx_port_read(port, SC16IS7XX_LCR_REG); =20 @@ -537,7 +536,7 @@ static int sc16is7xx_set_baud(struct uart_port *port, i= nt baud) /* Put LCR back to the normal mode */ sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr); =20 - mutex_unlock(&s->efr_lock); + mutex_unlock(&one->efr_lock); =20 sc16is7xx_port_update(port, SC16IS7XX_MCR_REG, SC16IS7XX_MCR_CLKSEL_BIT, @@ -705,11 +704,10 @@ static unsigned int sc16is7xx_get_hwmctrl(struct uart= _port *port) static void sc16is7xx_update_mlines(struct sc16is7xx_one *one) { struct uart_port *port =3D &one->port; - struct sc16is7xx_port *s =3D dev_get_drvdata(port->dev); unsigned long flags; unsigned int status, changed; =20 - lockdep_assert_held_once(&s->efr_lock); + lockdep_assert_held_once(&one->efr_lock); =20 status =3D sc16is7xx_get_hwmctrl(port); changed =3D status ^ one->old_mctrl; @@ -735,15 +733,20 @@ static void sc16is7xx_update_mlines(struct sc16is7xx_= one *one) =20 static bool sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno) { + bool rc =3D true; struct uart_port *port =3D &s->p[portno].port; + struct sc16is7xx_one *one =3D to_sc16is7xx_one(port, port); + + mutex_lock(&one->efr_lock); =20 do { unsigned int iir, rxlen; - struct sc16is7xx_one *one =3D to_sc16is7xx_one(port, port); =20 iir =3D sc16is7xx_port_read(port, SC16IS7XX_IIR_REG); - if (iir & SC16IS7XX_IIR_NO_INT_BIT) - return false; + if (iir & SC16IS7XX_IIR_NO_INT_BIT) { + rc =3D false; + goto out_port_irq; + } =20 iir &=3D SC16IS7XX_IIR_ID_MASK; =20 @@ -783,15 +786,17 @@ static bool sc16is7xx_port_irq(struct sc16is7xx_port = *s, int portno) break; } } while (0); - return true; + +out_port_irq: + mutex_unlock(&one->efr_lock); + + return rc; } =20 static irqreturn_t sc16is7xx_irq(int irq, void *dev_id) { struct sc16is7xx_port *s =3D (struct sc16is7xx_port *)dev_id; =20 - mutex_lock(&s->efr_lock); - while (1) { bool keep_polling =3D false; int i; @@ -802,24 +807,22 @@ static irqreturn_t sc16is7xx_irq(int irq, void *dev_i= d) break; } =20 - mutex_unlock(&s->efr_lock); - return IRQ_HANDLED; } =20 static void sc16is7xx_tx_proc(struct kthread_work *ws) { struct uart_port *port =3D &(to_sc16is7xx_one(ws, tx_work)->port); - struct sc16is7xx_port *s =3D dev_get_drvdata(port->dev); + struct sc16is7xx_one *one =3D to_sc16is7xx_one(port, port); unsigned long flags; =20 if ((port->rs485.flags & SER_RS485_ENABLED) && (port->rs485.delay_rts_before_send > 0)) msleep(port->rs485.delay_rts_before_send); =20 - mutex_lock(&s->efr_lock); + mutex_lock(&one->efr_lock); sc16is7xx_handle_tx(port); - mutex_unlock(&s->efr_lock); + mutex_unlock(&one->efr_lock); =20 uart_port_lock_irqsave(port, &flags); sc16is7xx_ier_set(port, SC16IS7XX_IER_THRI_BIT); @@ -926,9 +929,9 @@ static void sc16is7xx_ms_proc(struct kthread_work *ws) struct sc16is7xx_port *s =3D dev_get_drvdata(one->port.dev); =20 if (one->port.state) { - mutex_lock(&s->efr_lock); + mutex_lock(&one->efr_lock); sc16is7xx_update_mlines(one); - mutex_unlock(&s->efr_lock); + mutex_unlock(&one->efr_lock); =20 kthread_queue_delayed_work(&s->kworker, &one->ms_work, HZ); } @@ -1012,7 +1015,6 @@ static void sc16is7xx_set_termios(struct uart_port *p= ort, struct ktermios *termios, const struct ktermios *old) { - struct sc16is7xx_port *s =3D dev_get_drvdata(port->dev); struct sc16is7xx_one *one =3D to_sc16is7xx_one(port, port); unsigned int lcr, flow =3D 0; int baud; @@ -1071,7 +1073,7 @@ static void sc16is7xx_set_termios(struct uart_port *p= ort, port->ignore_status_mask |=3D SC16IS7XX_LSR_BRK_ERROR_MASK; =20 /* As above, claim the mutex while accessing the EFR. */ - mutex_lock(&s->efr_lock); + mutex_lock(&one->efr_lock); =20 sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, SC16IS7XX_LCR_CONF_MODE_B); @@ -1101,7 +1103,7 @@ static void sc16is7xx_set_termios(struct uart_port *p= ort, /* Update LCR register */ sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr); =20 - mutex_unlock(&s->efr_lock); + mutex_unlock(&one->efr_lock); =20 /* Get baud rate generator configuration */ baud =3D uart_get_baud_rate(port, termios, old, @@ -1535,7 +1537,6 @@ static int sc16is7xx_probe(struct device *dev, =20 s->devtype =3D devtype; dev_set_drvdata(dev, s); - mutex_init(&s->efr_lock); =20 kthread_init_worker(&s->kworker); s->kworker_task =3D kthread_run(kthread_worker_fn, &s->kworker, @@ -1578,6 +1579,8 @@ static int sc16is7xx_probe(struct device *dev, goto out_ports; } =20 + mutex_init(&s->p[i].efr_lock); + ret =3D uart_get_rs485_mode(&s->p[i].port); if (ret) goto out_ports; --=20 2.39.2