From patchwork Mon Jun 13 07:52:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ilpo_J=C3=A4rvinen?= X-Patchwork-Id: 12879116 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 50414C43334 for ; Mon, 13 Jun 2022 07:54:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=0Sq3yStauQI1CpQKch2H58Ek4FaBrZFEAu2kX/UjDrg=; b=tOLHFXCS1Q5PUR EeHL1Kn9qzPUk+oG4racsdieopmOIOXgJganwdxI99lyuzG8mA9YeEMvMDWZk6manMoO3e/defB0Y YHUw9WUDz4BzIUzW1ETKBxs/13/ocL5OmcuaEdnBas+84iu0qB0xLx/PKgd6f5T9YrJR7VbIaPABX RqZJx6qrfIjTGfqPwvoA4jU7xVu20J9FO3dRvG2Z27SVfOyDXiN9zu+g8u4T3TMss4zCHoqzBsfth Ksk9OMS1pqmu3g3OzjXwkqjByLtpOHMAnUpsMPINjazYrg3prXA6oZkg1OstX35WYHcG0bIDCre+g 0bSdMDb6tEaOklEyhAQA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1o0eso-0023ji-11; Mon, 13 Jun 2022 07:53:10 +0000 Received: from mga09.intel.com ([134.134.136.24]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1o0esj-0023d4-Hz for linux-arm-kernel@lists.infradead.org; Mon, 13 Jun 2022 07:53:07 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1655106785; x=1686642785; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ZPuHz6d6AI1KyIrHnPOMnRFf0bZSiby4n3W9TkKLSDk=; b=kKukIhlEzG4C0MGT2tlrknvUUioQIHoF7ISbwS66RGXnk4ccXGjMFWBj TNfyhfJD5LBuuG+aYCfVo7CE3wn+zSDWpdEehX6nUVSCj/4etkMaHdCPD gkCGcLLTKe8dcpW2t0MCa6TKHBUEkIEoD5zIDsxkGpoiQJtzVze0IjU2P sMUh8vdt5gXVY7FDsZP9jfs9hz/i5kaSwwkZ4R8CWvMPRJx7IIGMoz1tL KcFYYyQCnXO0roI393YPJcGjDsRLdK9+HVt7B9snGKxL+yyUv6/17HSVn khMDzeu5kG7lu1aXfF621vXCDtAkgPAIXzHrmcuYxV8gnZEhSkhx/o8L2 Q==; X-IronPort-AV: E=McAfee;i="6400,9594,10376"; a="278924904" X-IronPort-AV: E=Sophos;i="5.91,296,1647327600"; d="scan'208";a="278924904" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 13 Jun 2022 00:52:58 -0700 X-IronPort-AV: E=Sophos;i="5.91,296,1647327600"; d="scan'208";a="639593314" Received: from fnechitx-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.249.40.115]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 13 Jun 2022 00:52:52 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Andy Shevchenko , Vladimir Zapolskiy , Russell King , Richard Genoud , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Shawn Guo , Sascha Hauer , Pengutronix Kernel Team , Fabio Estevam , NXP Linux Team , Maxime Coquelin , Alexandre Torgue , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-stm32@st-md-mailman.stormreply.com Cc: Lukas Wunner , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , =?utf-8?q?Ilpo_J=C3=A4rvinen?= Subject: [PATCH v6 4/6] serial: take termios_rwsem for .rs485_config() & pass termios as param Date: Mon, 13 Jun 2022 10:52:25 +0300 Message-Id: <20220613075227.10394-5-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220613075227.10394-1-ilpo.jarvinen@linux.intel.com> References: <20220613075227.10394-1-ilpo.jarvinen@linux.intel.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220613_005305_761723_B813E6F5 X-CRM114-Status: GOOD ( 16.48 ) 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 To be able to alter ADDRB within .rs485_config(), take termios_rwsem before calling .rs485_config() and pass termios. Signed-off-by: Ilpo Järvinen --- drivers/tty/serial/8250/8250.h | 3 ++- drivers/tty/serial/8250/8250_dwlib.c | 3 ++- drivers/tty/serial/8250/8250_exar.c | 9 +++++---- drivers/tty/serial/8250/8250_fintek.c | 2 +- drivers/tty/serial/8250/8250_lpc18xx.c | 2 +- drivers/tty/serial/8250/8250_pci.c | 2 +- drivers/tty/serial/8250/8250_port.c | 3 ++- drivers/tty/serial/amba-pl011.c | 2 +- drivers/tty/serial/ar933x_uart.c | 2 +- drivers/tty/serial/atmel_serial.c | 2 +- drivers/tty/serial/fsl_lpuart.c | 4 ++-- drivers/tty/serial/imx.c | 2 +- drivers/tty/serial/max310x.c | 2 +- drivers/tty/serial/mcf.c | 3 ++- drivers/tty/serial/omap-serial.c | 3 ++- drivers/tty/serial/sc16is7xx.c | 2 +- drivers/tty/serial/serial_core.c | 15 +++++++++++---- drivers/tty/serial/stm32-usart.c | 2 +- include/linux/serial_core.h | 3 ++- 19 files changed, 40 insertions(+), 26 deletions(-) diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 36aebf3ec02c..3183bfe1334d 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -203,7 +203,8 @@ void serial8250_rpm_put(struct uart_8250_port *p); void serial8250_rpm_get_tx(struct uart_8250_port *p); void serial8250_rpm_put_tx(struct uart_8250_port *p); -int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485); +int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485, + struct ktermios *termios); void serial8250_em485_start_tx(struct uart_8250_port *p); void serial8250_em485_stop_tx(struct uart_8250_port *p); void serial8250_em485_destroy(struct uart_8250_port *p); diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c index c83e7eaf3877..c9d9bd7f7bd9 100644 --- a/drivers/tty/serial/8250/8250_dwlib.c +++ b/drivers/tty/serial/8250/8250_dwlib.c @@ -85,7 +85,8 @@ void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct } EXPORT_SYMBOL_GPL(dw8250_do_set_termios); -static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485) +static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485, + struct ktermios *termios) { u32 tcr; diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index 0eae2d8a9494..4988629135f6 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -112,7 +112,8 @@ struct exar8250; struct exar8250_platform { - int (*rs485_config)(struct uart_port *, struct serial_rs485 *); + int (*rs485_config)(struct uart_port *port, struct serial_rs485 *rs485, + struct ktermios *termios); const struct serial_rs485 *rs485_supported; int (*register_gpio)(struct pci_dev *, struct uart_8250_port *); void (*unregister_gpio)(struct uart_8250_port *); @@ -410,7 +411,7 @@ static void xr17v35x_unregister_gpio(struct uart_8250_port *port) } static int generic_rs485_config(struct uart_port *port, - struct serial_rs485 *rs485) + struct serial_rs485 *rs485, struct ktermios *termios) { bool is_rs485 = !!(rs485->flags & SER_RS485_ENABLED); u8 __iomem *p = port->membase; @@ -442,7 +443,7 @@ static const struct exar8250_platform exar8250_default_platform = { }; static int iot2040_rs485_config(struct uart_port *port, - struct serial_rs485 *rs485) + struct serial_rs485 *rs485, struct ktermios *termios) { bool is_rs485 = !!(rs485->flags & SER_RS485_ENABLED); u8 __iomem *p = port->membase; @@ -471,7 +472,7 @@ static int iot2040_rs485_config(struct uart_port *port, value |= mode; writeb(value, p + UART_EXAR_MPIOLVL_7_0); - return generic_rs485_config(port, rs485); + return generic_rs485_config(port, rs485, termios); } static const struct serial_rs485 iot2040_rs485_supported = { diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index 1fb86c73786c..e48d52534bef 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -192,7 +192,7 @@ static int fintek_8250_get_ldn_range(struct fintek_8250 *pdata, int *min, } static int fintek_8250_rs485_config(struct uart_port *port, - struct serial_rs485 *rs485) + struct serial_rs485 *rs485, struct ktermios *termios) { uint8_t config = 0; struct fintek_8250 *pdata = port->private_data; diff --git a/drivers/tty/serial/8250/8250_lpc18xx.c b/drivers/tty/serial/8250/8250_lpc18xx.c index 3a1cb51cbc91..1865f7bc5020 100644 --- a/drivers/tty/serial/8250/8250_lpc18xx.c +++ b/drivers/tty/serial/8250/8250_lpc18xx.c @@ -33,7 +33,7 @@ struct lpc18xx_uart_data { }; static int lpc18xx_rs485_config(struct uart_port *port, - struct serial_rs485 *rs485) + struct serial_rs485 *rs485, struct ktermios *termios) { struct uart_8250_port *up = up_to_u8250p(port); u32 rs485_ctrl_reg = 0; diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index b6d71268aa7d..35c799641e32 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1554,7 +1554,7 @@ pci_brcm_trumanage_setup(struct serial_private *priv, /* We should do proper H/W transceiver setting before change to RS485 mode */ static int pci_fintek_rs485_config(struct uart_port *port, - struct serial_rs485 *rs485) + struct serial_rs485 *rs485, struct ktermios *termios) { struct pci_dev *pci_dev = to_pci_dev(port->dev); u8 setting; diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 8ff9f4815c7b..8ab0584bdba2 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -664,7 +664,8 @@ EXPORT_SYMBOL_GPL(serial8250_em485_supported); * if the uart is incapable of driving RTS as a Transmit Enable signal in * hardware, relying on software emulation instead. */ -int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485) +int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485, + struct ktermios *termios) { struct uart_8250_port *up = up_to_u8250p(port); diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index eccd66625d25..aefb0600a82c 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2198,7 +2198,7 @@ static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser) } static int pl011_rs485_config(struct uart_port *port, - struct serial_rs485 *rs485) + struct serial_rs485 *rs485, struct ktermios *termios) { struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c index ab2c5b2a1ce8..930d9aed90f5 100644 --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -581,7 +581,7 @@ static const struct uart_ops ar933x_uart_ops = { }; static int ar933x_config_rs485(struct uart_port *port, - struct serial_rs485 *rs485conf) + struct serial_rs485 *rs485conf, struct ktermios *termios) { struct ar933x_uart_port *up = container_of(port, struct ar933x_uart_port, port); diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 74dd1d3ac46f..b032e7c30ce0 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -286,7 +286,7 @@ static void atmel_tasklet_schedule(struct atmel_uart_port *atmel_port, /* Enable or disable the rs485 support */ static int atmel_config_rs485(struct uart_port *port, - struct serial_rs485 *rs485conf) + struct serial_rs485 *rs485conf, struct ktermios *termios) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); unsigned int mode; diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index d35414cb3e4e..3e8da24a3f76 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -1356,7 +1356,7 @@ static void lpuart_dma_rx_free(struct uart_port *port) } static int lpuart_config_rs485(struct uart_port *port, - struct serial_rs485 *rs485) + struct serial_rs485 *rs485, struct ktermios *termios) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); @@ -1386,7 +1386,7 @@ static int lpuart_config_rs485(struct uart_port *port, } static int lpuart32_config_rs485(struct uart_port *port, - struct serial_rs485 *rs485) + struct serial_rs485 *rs485, struct ktermios *termios) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index f4edde54175f..8a63ab6e0d8e 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1908,7 +1908,7 @@ static void imx_uart_poll_put_char(struct uart_port *port, unsigned char c) /* called with port.lock taken and irqs off or from .probe without locking */ static int imx_uart_rs485_config(struct uart_port *port, - struct serial_rs485 *rs485conf) + struct serial_rs485 *rs485conf, struct ktermios *termios) { struct imx_port *sport = (struct imx_port *)port; u32 ucr2; diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index d7d1791fcb57..0e1dfad03825 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -1027,7 +1027,7 @@ static void max310x_rs_proc(struct work_struct *ws) } static int max310x_rs485_config(struct uart_port *port, - struct serial_rs485 *rs485) + struct serial_rs485 *rs485, struct ktermios *termios) { struct max310x_one *one = to_max310x_port(port); diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c index 036f178e3d66..fbdf8c53ddd0 100644 --- a/drivers/tty/serial/mcf.c +++ b/drivers/tty/serial/mcf.c @@ -431,7 +431,8 @@ static int mcf_verify_port(struct uart_port *port, struct serial_struct *ser) /****************************************************************************/ /* Enable or disable the RS485 support */ -static int mcf_config_rs485(struct uart_port *port, struct serial_rs485 *rs485) +static int mcf_config_rs485(struct uart_port *port, struct serial_rs485 *rs485, + struct ktermios *termios) { unsigned char mr1, mr2; diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 98622c35d896..07446bcbfa8c 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1325,7 +1325,8 @@ static inline void serial_omap_add_console_port(struct uart_omap_port *up) /* Enable or disable the rs485 support */ static int -serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485) +serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485, + struct ktermios *termios) { struct uart_omap_port *up = to_uart_omap_port(port); unsigned int mode; diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 2ceecaa4a478..f84c693ef5e7 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -1128,7 +1128,7 @@ static void sc16is7xx_set_termios(struct uart_port *port, } static int sc16is7xx_config_rs485(struct uart_port *port, - struct serial_rs485 *rs485) + struct serial_rs485 *rs485, struct ktermios *termios) { struct sc16is7xx_port *s = dev_get_drvdata(port->dev); struct sc16is7xx_one *one = to_sc16is7xx_one(port, port); diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 621fc15e2e54..76bb1b77b06e 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1359,7 +1359,8 @@ int uart_rs485_config(struct uart_port *port) uart_sanitize_serial_rs485(port, rs485); - ret = port->rs485_config(port, rs485); + ret = port->rs485_config(port, rs485, NULL); + if (ret) memset(rs485, 0, sizeof(*rs485)); @@ -1383,7 +1384,7 @@ static int uart_get_rs485_config(struct uart_port *port, return 0; } -static int uart_set_rs485_config(struct uart_port *port, +static int uart_set_rs485_config(struct tty_struct *tty, struct uart_port *port, struct serial_rs485 __user *rs485_user) { struct serial_rs485 rs485; @@ -1402,7 +1403,7 @@ static int uart_set_rs485_config(struct uart_port *port, uart_sanitize_serial_rs485(port, &rs485); spin_lock_irqsave(&port->lock, flags); - ret = port->rs485_config(port, &rs485); + ret = port->rs485_config(port, &rs485, &tty->termios); if (!ret) port->rs485 = rs485; spin_unlock_irqrestore(&port->lock, flags); @@ -1511,6 +1512,10 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) if (ret != -ENOIOCTLCMD) goto out; + /* rs485_config requires more locking than others */ + if (cmd == TIOCGRS485) + down_write(&tty->termios_rwsem); + mutex_lock(&port->mutex); uport = uart_port_check(state); @@ -1534,7 +1539,7 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) break; case TIOCSRS485: - ret = uart_set_rs485_config(uport, uarg); + ret = uart_set_rs485_config(tty, uport, uarg); break; case TIOCSISO7816: @@ -1551,6 +1556,8 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) } out_up: mutex_unlock(&port->mutex); + if (cmd == TIOCGRS485) + up_write(&tty->termios_rwsem); out: return ret; } diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index db3dd9731ee1..de8e3cbda4f3 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -98,7 +98,7 @@ static void stm32_usart_config_reg_rs485(u32 *cr1, u32 *cr3, u32 delay_ADE, } static int stm32_usart_config_rs485(struct uart_port *port, - struct serial_rs485 *rs485conf) + struct serial_rs485 *rs485conf, struct ktermios *termios) { struct stm32_port *stm32_port = to_stm32_port(port); const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 5518b70177b3..9577cffb5593 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -132,7 +132,8 @@ struct uart_port { unsigned int old); void (*handle_break)(struct uart_port *); int (*rs485_config)(struct uart_port *, - struct serial_rs485 *rs485); + struct serial_rs485 *rs485, + struct ktermios *termios); int (*iso7816_config)(struct uart_port *, struct serial_iso7816 *iso7816); unsigned int irq; /* irq number */