From patchwork Mon Apr 4 08:29:07 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: 12799976 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 B4FDDC433FE for ; Mon, 4 Apr 2022 08:30:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237985AbiDDIcR (ORCPT ); Mon, 4 Apr 2022 04:32:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46722 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237592AbiDDIcQ (ORCPT ); Mon, 4 Apr 2022 04:32:16 -0400 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3047325590; Mon, 4 Apr 2022 01:30:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1649061020; x=1680597020; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ABizxv2oeYO2wwl4Dd5x36/ryIakHx/dr6Yh5+l52KI=; b=J91TomdTbrFgF+3NZ+k6Rqf9lTNSN9eW0jIXrPQlh9ytH5lXzaHai3mj 7v8u/DMKnrm9kJn/r3H6qhTyCcI7gX6CfOHN1VQY0ZIbgqL4UVUtzJSv+ EEDRQUwAl5Brg/8et5SHRuALN4fICWUlU0+g0Pn96mbRmm/VtDMYKN2Xn 21T7KYwR5cIDA7+VxKjuQV7RHqcVD36rJVVm84N9/QsrJkeVbaAXKGAjA /UUqJYA/l3mN6SeQ3BaVMWa1VSDJhzcq8vq2f4SxRR4d19kS9j7FfXI26 NJS508qoMnesTz5LjYhirai0/iokO1kESF//ZUCFbpgh9YbBegWQT9cgc w==; X-IronPort-AV: E=McAfee;i="6200,9189,10306"; a="323639795" X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="323639795" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:19 -0700 X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="569293542" Received: from rhamza-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.211.126]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:10 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Uwe_Kleine-K?= =?utf-8?q?=C3=B6nig?= , =?utf-8?q?Ilpo_J?= =?utf-8?q?=C3=A4rvinen?= , linux-api@vger.kernel.org, Ivan Kokshaysky , Matt Turner , linux-alpha@vger.kernel.org, Thomas Bogendoerfer , linux-mips@vger.kernel.org, "James E.J. Bottomley" , Helge Deller , linux-parisc@vger.kernel.org, Michael Ellerman , Benjamin Herrenschmidt , Paul Mackerras , linuxppc-dev@lists.ozlabs.org, "David S. Miller" , sparclinux@vger.kernel.org, Arnd Bergmann , linux-arch@vger.kernel.org, linux-usb@vger.kernel.org Subject: [PATCH v2 07/12] serial: termbits: ADDRB to indicate 9th bit addressing mode Date: Mon, 4 Apr 2022 11:29:07 +0300 Message-Id: <20220404082912.6885-8-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> References: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-parisc@vger.kernel.org Add ADDRB to termbits to indicate 9th bit addressing mode. This change is necessary for supporting devices with RS485 multipoint addressing [*]. A later patch in the patch series adds support for Synopsys Designware UART capable for 9th bit addressing mode. In this mode, 9th bit is used to indicate an address (byte) within the communication line. The 9th bit addressing mode is selected using ADDRB introduced by an earlier patch. [*] Technically, RS485 is just an electronic spec and does not itself specify the 9th bit addressing mode but 9th bit seems at least "semi-standard" way to do addressing with RS485. Cc: linux-api@vger.kernel.org Cc: Ivan Kokshaysky Cc: Matt Turner Cc: linux-alpha@vger.kernel.org Cc: Thomas Bogendoerfer Cc: linux-mips@vger.kernel.org Cc: "James E.J. Bottomley" Cc: Helge Deller Cc: linux-parisc@vger.kernel.org Cc: Michael Ellerman Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org Cc: "David S. Miller" Cc: sparclinux@vger.kernel.org Cc: Arnd Bergmann Cc: linux-arch@vger.kernel.org Cc: linux-usb@vger.kernel.org Signed-off-by: Ilpo Järvinen --- arch/alpha/include/uapi/asm/termbits.h | 1 + arch/mips/include/uapi/asm/termbits.h | 1 + arch/parisc/include/uapi/asm/termbits.h | 1 + arch/powerpc/include/uapi/asm/termbits.h | 1 + arch/sparc/include/uapi/asm/termbits.h | 1 + drivers/char/pcmcia/synclink_cs.c | 2 ++ drivers/ipack/devices/ipoctal.c | 2 ++ drivers/mmc/core/sdio_uart.c | 2 ++ drivers/net/usb/hso.c | 3 ++- drivers/s390/char/tty3270.c | 3 +++ drivers/staging/greybus/uart.c | 2 ++ drivers/tty/amiserial.c | 6 +++++- drivers/tty/moxa.c | 1 + drivers/tty/mxser.c | 1 + drivers/tty/serial/serial_core.c | 2 ++ drivers/tty/synclink_gt.c | 2 ++ drivers/tty/tty_ioctl.c | 2 ++ drivers/usb/class/cdc-acm.c | 2 ++ drivers/usb/serial/usb-serial.c | 6 ++++-- include/uapi/asm-generic/termbits.h | 1 + net/bluetooth/rfcomm/tty.c | 2 ++ 21 files changed, 40 insertions(+), 4 deletions(-) diff --git a/arch/alpha/include/uapi/asm/termbits.h b/arch/alpha/include/uapi/asm/termbits.h index 4575ba34a0ea..285169c794ec 100644 --- a/arch/alpha/include/uapi/asm/termbits.h +++ b/arch/alpha/include/uapi/asm/termbits.h @@ -180,6 +180,7 @@ struct ktermios { #define HUPCL 00040000 #define CLOCAL 00100000 +#define ADDRB 010000000 /* address bit */ #define CMSPAR 010000000000 /* mark or space (stick) parity */ #define CRTSCTS 020000000000 /* flow control */ diff --git a/arch/mips/include/uapi/asm/termbits.h b/arch/mips/include/uapi/asm/termbits.h index dfeffba729b7..e7ea31cfec78 100644 --- a/arch/mips/include/uapi/asm/termbits.h +++ b/arch/mips/include/uapi/asm/termbits.h @@ -181,6 +181,7 @@ struct ktermios { #define B3000000 0010015 #define B3500000 0010016 #define B4000000 0010017 +#define ADDRB 0020000 /* address bit */ #define CIBAUD 002003600000 /* input baud rate */ #define CMSPAR 010000000000 /* mark or space (stick) parity */ #define CRTSCTS 020000000000 /* flow control */ diff --git a/arch/parisc/include/uapi/asm/termbits.h b/arch/parisc/include/uapi/asm/termbits.h index 40e920f8d683..629be061f5d5 100644 --- a/arch/parisc/include/uapi/asm/termbits.h +++ b/arch/parisc/include/uapi/asm/termbits.h @@ -158,6 +158,7 @@ struct ktermios { #define B3000000 0010015 #define B3500000 0010016 #define B4000000 0010017 +#define ADDRB 0020000 /* address bit */ #define CIBAUD 002003600000 /* input baud rate */ #define CMSPAR 010000000000 /* mark or space (stick) parity */ #define CRTSCTS 020000000000 /* flow control */ diff --git a/arch/powerpc/include/uapi/asm/termbits.h b/arch/powerpc/include/uapi/asm/termbits.h index ed18bc61f63d..1b778ac562a4 100644 --- a/arch/powerpc/include/uapi/asm/termbits.h +++ b/arch/powerpc/include/uapi/asm/termbits.h @@ -171,6 +171,7 @@ struct ktermios { #define HUPCL 00040000 #define CLOCAL 00100000 +#define ADDRB 00200000 /* address bit */ #define CMSPAR 010000000000 /* mark or space (stick) parity */ #define CRTSCTS 020000000000 /* flow control */ diff --git a/arch/sparc/include/uapi/asm/termbits.h b/arch/sparc/include/uapi/asm/termbits.h index ce5ad5d0f105..4ad60c4acf65 100644 --- a/arch/sparc/include/uapi/asm/termbits.h +++ b/arch/sparc/include/uapi/asm/termbits.h @@ -200,6 +200,7 @@ struct ktermios { #define B3000000 0x00001011 #define B3500000 0x00001012 #define B4000000 0x00001013 */ +#define ADDRB 0x00002000 /* address bit */ #define CIBAUD 0x100f0000 /* input baud rate (not used) */ #define CMSPAR 0x40000000 /* mark or space (stick) parity */ #define CRTSCTS 0x80000000 /* flow control */ diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 78baba55a8b5..d179b9b57a25 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -2287,6 +2287,8 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term == RELEVANT_IFLAG(old_termios->c_iflag))) return; + tty->termios.c_cflag &= ~ADDRB; + mgslpc_change_params(info, tty); /* Handle transition to B0 status */ diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index 20d2b9ec1227..d66cc9683ebc 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -506,6 +506,8 @@ static void ipoctal_set_termios(struct tty_struct *tty, struct ipoctal_channel *channel = tty->driver_data; speed_t baud; + tty->termios.c_cflag &= ~ADDRB; + cflag = tty->termios.c_cflag; /* Disable and reset everything before change the setup */ diff --git a/drivers/mmc/core/sdio_uart.c b/drivers/mmc/core/sdio_uart.c index 04c0823e0359..7432b01379ef 100644 --- a/drivers/mmc/core/sdio_uart.c +++ b/drivers/mmc/core/sdio_uart.c @@ -880,6 +880,8 @@ static void sdio_uart_set_termios(struct tty_struct *tty, if (sdio_uart_claim_func(port) != 0) return; + tty->termios.c_cflag &= ~ADDRB; + sdio_uart_change_speed(port, &tty->termios, old_termios); /* Handle transition to B0 status */ diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index f97813a4e8d1..b687327bc7b1 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1099,7 +1099,8 @@ static void _hso_serial_set_termios(struct tty_struct *tty) ~(CSIZE /* no size */ | PARENB /* disable parity bit */ | CBAUD /* clear current baud rate */ - | CBAUDEX); /* clear current buad rate */ + | CBAUDEX /* clear current baud rate */ + | ADDRB); /* disable 9th (addr) bit */ tty->termios.c_cflag |= CS8; /* character size 8 bits */ diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index 5c83f71c1d0e..253d2997a1d3 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -1768,6 +1768,9 @@ tty3270_set_termios(struct tty_struct *tty, struct ktermios *old) tp = tty->driver_data; if (!tp) return; + + tty->termios.c_cflag &= ~ADDRB; + spin_lock_bh(&tp->view.lock); if (L_ICANON(tty)) { new = L_ECHO(tty) ? TF_INPUT: TF_INPUTN; diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index dc4ed0ff1ae2..83e73aefde0f 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -487,6 +487,8 @@ static void gb_tty_set_termios(struct tty_struct *tty, struct ktermios *termios = &tty->termios; u8 newctrl = gb_tty->ctrlout; + termios->c_cflag &= ~ADDRB; + newline.rate = cpu_to_le32(tty_get_baud_rate(tty)); newline.format = termios->c_cflag & CSTOPB ? GB_SERIAL_2_STOP_BITS : GB_SERIAL_1_STOP_BITS; diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 533d02b38e02..3ca97007bd6e 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -1175,7 +1175,11 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct serial_state *info = tty->driver_data; unsigned long flags; - unsigned int cflag = tty->termios.c_cflag; + unsigned int cflag; + + tty->termios.c_cflag &= ~ADDRB; + + cflag = tty->termios.c_cflag; change_speed(tty, info, old_termios); diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index f3c72ab1476c..07cd88152d58 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c @@ -2050,6 +2050,7 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio, ofsAddr = port->tableAddr; + termio->c_cflag &= ~ADDRB; mode = termio->c_cflag & CSIZE; if (mode == CS5) mode = MX_CS5; diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 836c9eca2946..220676363a07 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -577,6 +577,7 @@ static void mxser_change_speed(struct tty_struct *tty, struct ktermios *old_term struct mxser_port *info = tty->driver_data; unsigned cflag, cval; + tty->termios.c_cflag &= ~ADDRB; cflag = tty->termios.c_cflag; if (mxser_set_baud(tty, tty_get_baud_rate(tty))) { diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index c6ac91033e38..de198c2acefe 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1493,6 +1493,8 @@ static void uart_set_termios(struct tty_struct *tty, goto out; } + tty->termios.c_cflag &= ~ADDRB; + uart_change_speed(tty, state, old_termios); /* reload cflag from termios; port driver may have overridden flags */ cflag = tty->termios.c_cflag; diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index 25c558e65ece..ee767cea18ed 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -714,6 +714,8 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) DBGINFO(("%s set_termios\n", tty->driver->name)); + tty->termios.c_cflag &= ~ADDRB; + change_params(info); /* Handle transition to B0 status */ diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index 63181925ec1a..934037d78868 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -319,6 +319,8 @@ unsigned char tty_get_frame_size(unsigned int cflag) bits++; if (cflag & PARENB) bits++; + if (cflag & ADDRB) + bits++; return bits; } diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 9b9aea24d58c..fd246ec70da8 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1056,6 +1056,8 @@ static void acm_tty_set_termios(struct tty_struct *tty, struct usb_cdc_line_coding newline; int newctrl = acm->ctrlout; + termios->c_cflag &= ~ADDRB; + newline.dwDTERate = cpu_to_le32(tty_get_baud_rate(tty)); newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0; newline.bParityType = termios->c_cflag & PARENB ? diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 24101bd7fcad..8d1d170eb7e6 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -525,10 +525,12 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old) dev_dbg(&port->dev, "%s\n", __func__); - if (port->serial->type->set_termios) + if (port->serial->type->set_termios) { + tty->termios.c_cflag &= ~ADDRB; port->serial->type->set_termios(tty, port, old); - else + } else { tty_termios_copy_hw(&tty->termios, old); + } } static int serial_break(struct tty_struct *tty, int break_state) diff --git a/include/uapi/asm-generic/termbits.h b/include/uapi/asm-generic/termbits.h index 2fbaf9ae89dd..5f5228329d45 100644 --- a/include/uapi/asm-generic/termbits.h +++ b/include/uapi/asm-generic/termbits.h @@ -157,6 +157,7 @@ struct ktermios { #define B3000000 0010015 #define B3500000 0010016 #define B4000000 0010017 +#define ADDRB 0020000 /* address bit */ #define CIBAUD 002003600000 /* input baud rate */ #define CMSPAR 010000000000 /* mark or space (stick) parity */ #define CRTSCTS 020000000000 /* flow control */ diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index ebd78fdbd6e8..832e725f23ab 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -871,6 +871,8 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old) if (!dev || !dev->dlc || !dev->dlc->session) return; + new->c_cflag &= ~ADDRB; + /* Handle turning off CRTSCTS */ if ((old->c_cflag & CRTSCTS) && !(new->c_cflag & CRTSCTS)) BT_DBG("Turning off CRTSCTS unsupported"); From patchwork Mon Apr 4 08:29:08 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: 12799977 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 67275C43217 for ; Mon, 4 Apr 2022 08:30:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234768AbiDDIcg (ORCPT ); Mon, 4 Apr 2022 04:32:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47688 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238460AbiDDIc2 (ORCPT ); Mon, 4 Apr 2022 04:32:28 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AF2F331937; Mon, 4 Apr 2022 01:30:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1649061030; x=1680597030; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=maSL2cxRqazwpa1HcB3zULcND5265JQwoKkKrstAzyI=; b=XsgUyjLL7lS/rQA4FlMSwpHSUheSIGViHu6RFDBG5F1wlnnFSuTjt9mS Qgaw/XR91l7XebFA3qP/B2+CGEBj/TaWqJKICwSA1n0syhYC0GAU5Dnur lHnoADPBlFOpha9dgt4cZw8VP5ywNkr+UzWblpOos2q4FOcsVaYapbHE3 Q0cjTHYzZoR/9c/qta2ptn1hgcCn11KIV7xHCZFyZodJb7V4qfqA0t5z6 0no/Qm+Vd/TBzwbcXkAsL95TLQSO2aUHMpaaRSJ0C7YO37ik7W5KSI15R HMaESRyhC5g3i/5Qk9SgHIWe23IBd5xID2Uc0lyySV9oodUch+4ay2ZME w==; X-IronPort-AV: E=McAfee;i="6200,9189,10306"; a="241052980" X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="241052980" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:30 -0700 X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="569293625" Received: from rhamza-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.211.126]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:20 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Uwe_Kleine-K?= =?utf-8?q?=C3=B6nig?= , =?utf-8?q?Ilpo_J?= =?utf-8?q?=C3=A4rvinen?= , linux-api@vger.kernel.org, Ivan Kokshaysky , Matt Turner , linux-alpha@vger.kernel.org, Thomas Bogendoerfer , linux-mips@vger.kernel.org, "James E.J. Bottomley" , Helge Deller , linux-parisc@vger.kernel.org, Michael Ellerman , Benjamin Herrenschmidt , Paul Mackerras , linuxppc-dev@lists.ozlabs.org, Yoshinori Sato , Rich Felker , linux-sh@vger.kernel.org, "David S. Miller" , sparclinux@vger.kernel.org, Chris Zankel , Max Filippov , linux-xtensa@linux-xtensa.org, Arnd Bergmann , linux-arch@vger.kernel.org, linux-doc@vger.kernel.org Subject: [PATCH v2 08/12] serial: General support for multipoint addresses Date: Mon, 4 Apr 2022 11:29:08 +0300 Message-Id: <20220404082912.6885-9-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> References: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-parisc@vger.kernel.org Add generic support for serial multipoint addressing. Two new ioctls are added. TIOCSADDR is used to indicate the destination/receive address. TIOCGADDR returns the current address in use. The driver should implement set_addr and get_addr to support addressing mode. Adjust ADDRB clearing to happen only if driver does not provide set_addr (=the driver doesn't support address mode). This change is necessary for supporting devices with RS485 multipoint addressing [*]. A following patch in the patch series adds support for Synopsys Designware UART capable for 9th bit addressing mode. In this mode, 9th bit is used to indicate an address (byte) within the communication line. The 9th bit addressing mode is selected using ADDRB introduced by the previous patch. Transmit addresses / receiver filter are specified by setting the flags SER_ADDR_DEST and/or SER_ADDR_RECV. When the user supplies the transmit address, in the 9bit addressing mode it is sent out immediately with the 9th bit set to 1. After that, the subsequent normal data bytes are sent with 9th bit as 0 and they are intended to the device with the given address. It is up to receiver to enforce the filter using SER_ADDR_RECV. When userspace has supplied the receive address, the driver is expected to handle the matching of the address and only data with that address is forwarded to the user. Both SER_ADDR_DEST and SER_ADDR_RECV can be given at the same time in a single call if the addresses are the same. The user can clear the receive filter with SER_ADDR_RECV_CLEAR. [*] Technically, RS485 is just an electronic spec and does not itself specify the 9th bit addressing mode but 9th bit seems at least "semi-standard" way to do addressing with RS485. Cc: linux-api@vger.kernel.org Cc: Ivan Kokshaysky Cc: Matt Turner Cc: linux-alpha@vger.kernel.org Cc: Thomas Bogendoerfer Cc: linux-mips@vger.kernel.org Cc: "James E.J. Bottomley" Cc: Helge Deller Cc: linux-parisc@vger.kernel.org Cc: Michael Ellerman Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org Cc: Yoshinori Sato Cc: Rich Felker Cc: linux-sh@vger.kernel.org Cc: "David S. Miller" Cc: sparclinux@vger.kernel.org Cc: Chris Zankel Cc: Max Filippov Cc: linux-xtensa@linux-xtensa.org Cc: Arnd Bergmann Cc: linux-arch@vger.kernel.org Cc: linux-doc@vger.kernel.org Signed-off-by: Ilpo Järvinen --- .../driver-api/serial/serial-rs485.rst | 23 ++++++- arch/alpha/include/uapi/asm/ioctls.h | 3 + arch/mips/include/uapi/asm/ioctls.h | 3 + arch/parisc/include/uapi/asm/ioctls.h | 3 + arch/powerpc/include/uapi/asm/ioctls.h | 3 + arch/sh/include/uapi/asm/ioctls.h | 3 + arch/sparc/include/uapi/asm/ioctls.h | 3 + arch/xtensa/include/uapi/asm/ioctls.h | 3 + drivers/tty/serial/8250/8250_core.c | 2 + drivers/tty/serial/serial_core.c | 62 ++++++++++++++++++- include/linux/serial_core.h | 6 ++ include/uapi/asm-generic/ioctls.h | 3 + include/uapi/linux/serial.h | 8 +++ 13 files changed, 123 insertions(+), 2 deletions(-) diff --git a/Documentation/driver-api/serial/serial-rs485.rst b/Documentation/driver-api/serial/serial-rs485.rst index 6bc824f948f9..2f45f007fa5b 100644 --- a/Documentation/driver-api/serial/serial-rs485.rst +++ b/Documentation/driver-api/serial/serial-rs485.rst @@ -95,7 +95,28 @@ RS485 Serial Communications /* Error handling. See errno. */ } -5. References +5. Multipoint Addressing +======================== + + The Linux kernel provides serial_addr structure to handle addressing within + multipoint serial communications line such as RS485. 9th bit addressiong mode + is enabled by adding ADDRB flag in termios c_cflag. + + Serial core calls device specific set/get_addr in response to TIOCSADDR and + TIOCGADDR ioctls with a pointer to serial_addr. Destination and receive + address can be specified using serial_addr flags field. Receive address may + also be cleared using flags. Once an address is set, the communication + can occur only with the particular device and other peers are filtered out. + It is left up to the receiver side to enforce the filtering. + + Address flags: + - SER_ADDR_RECV: Receive (filter) address. + - SER_ADDR_RECV_CLEAR: Clear receive filter (only for TIOCSADDR). + - SER_ADDR_DEST: Destination address. + + Note: not all devices supporting RS485 support multipoint addressing. + +6. References ============= [1] include/uapi/linux/serial.h diff --git a/arch/alpha/include/uapi/asm/ioctls.h b/arch/alpha/include/uapi/asm/ioctls.h index 971311605288..500cab3e1d6b 100644 --- a/arch/alpha/include/uapi/asm/ioctls.h +++ b/arch/alpha/include/uapi/asm/ioctls.h @@ -125,4 +125,7 @@ #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define TIOCSADDR _IOWR('T', 0x63, struct serial_addr) +#define TIOCGADDR _IOWR('T', 0x64, struct serial_addr) + #endif /* _ASM_ALPHA_IOCTLS_H */ diff --git a/arch/mips/include/uapi/asm/ioctls.h b/arch/mips/include/uapi/asm/ioctls.h index 16aa8a766aec..3859dc46857e 100644 --- a/arch/mips/include/uapi/asm/ioctls.h +++ b/arch/mips/include/uapi/asm/ioctls.h @@ -96,6 +96,9 @@ #define TIOCGISO7816 _IOR('T', 0x42, struct serial_iso7816) #define TIOCSISO7816 _IOWR('T', 0x43, struct serial_iso7816) +#define TIOCSADDR _IOWR('T', 0x63, struct serial_addr) +#define TIOCGADDR _IOWR('T', 0x64, struct serial_addr) + /* I hope the range from 0x5480 on is free ... */ #define TIOCSCTTY 0x5480 /* become controlling tty */ #define TIOCGSOFTCAR 0x5481 diff --git a/arch/parisc/include/uapi/asm/ioctls.h b/arch/parisc/include/uapi/asm/ioctls.h index 82d1148c6379..62337743db64 100644 --- a/arch/parisc/include/uapi/asm/ioctls.h +++ b/arch/parisc/include/uapi/asm/ioctls.h @@ -86,6 +86,9 @@ #define TIOCSTOP 0x5462 #define TIOCSLTC 0x5462 +#define TIOCSADDR _IOWR('T', 0x63, struct serial_addr) +#define TIOCGADDR _IOWR('T', 0x64, struct serial_addr) + /* Used for packet mode */ #define TIOCPKT_DATA 0 #define TIOCPKT_FLUSHREAD 1 diff --git a/arch/powerpc/include/uapi/asm/ioctls.h b/arch/powerpc/include/uapi/asm/ioctls.h index 2c145da3b774..84fd69ac366a 100644 --- a/arch/powerpc/include/uapi/asm/ioctls.h +++ b/arch/powerpc/include/uapi/asm/ioctls.h @@ -120,4 +120,7 @@ #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define TIOCSADDR _IOWR('T', 0x63, struct serial_addr) +#define TIOCGADDR _IOWR('T', 0x64, struct serial_addr) + #endif /* _ASM_POWERPC_IOCTLS_H */ diff --git a/arch/sh/include/uapi/asm/ioctls.h b/arch/sh/include/uapi/asm/ioctls.h index 11866d4f60e1..f82966b7dba2 100644 --- a/arch/sh/include/uapi/asm/ioctls.h +++ b/arch/sh/include/uapi/asm/ioctls.h @@ -113,4 +113,7 @@ #define TIOCMIWAIT _IO('T', 92) /* 0x545C */ /* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define TIOCSADDR _IOWR('T', 0x63, struct serial_addr) +#define TIOCGADDR _IOWR('T', 0x64, struct serial_addr) + #endif /* __ASM_SH_IOCTLS_H */ diff --git a/arch/sparc/include/uapi/asm/ioctls.h b/arch/sparc/include/uapi/asm/ioctls.h index 7fd2f5873c9e..e44624c67c79 100644 --- a/arch/sparc/include/uapi/asm/ioctls.h +++ b/arch/sparc/include/uapi/asm/ioctls.h @@ -125,6 +125,9 @@ #define TIOCMIWAIT 0x545C /* Wait for change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* Read serial port inline interrupt counts */ +#define TIOCSADDR _IOWR('T', 0x63, struct serial_addr) +#define TIOCGADDR _IOWR('T', 0x64, struct serial_addr) + /* Kernel definitions */ /* Used for packet mode */ diff --git a/arch/xtensa/include/uapi/asm/ioctls.h b/arch/xtensa/include/uapi/asm/ioctls.h index 6d4a87296c95..759ca9377f2a 100644 --- a/arch/xtensa/include/uapi/asm/ioctls.h +++ b/arch/xtensa/include/uapi/asm/ioctls.h @@ -127,4 +127,7 @@ #define TIOCMIWAIT _IO('T', 92) /* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define TIOCSADDR _IOWR('T', 0x63, struct serial_addr) +#define TIOCGADDR _IOWR('T', 0x64, struct serial_addr) + #endif /* _XTENSA_IOCTLS_H */ diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 01d30f6ed8fb..f67bc3b76f65 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1008,6 +1008,8 @@ int serial8250_register_8250_port(const struct uart_8250_port *up) uart->port.rs485 = up->port.rs485; uart->rs485_start_tx = up->rs485_start_tx; uart->rs485_stop_tx = up->rs485_stop_tx; + uart->port.set_addr = up->port.set_addr; + uart->port.get_addr = up->port.get_addr; uart->dma = up->dma; /* Take tx_loadsz from fifosize if it wasn't set separately */ diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index de198c2acefe..2cd129c78ef6 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1350,6 +1350,56 @@ static int uart_set_iso7816_config(struct uart_port *port, return 0; } +static int uart_set_addr(struct uart_port *port, + struct serial_addr __user *serial_addr_user) +{ + struct serial_addr addr; + unsigned long flags; + int ret; + + if (!port->set_addr) + return -ENOTTY; + + if (copy_from_user(&addr, serial_addr_user, sizeof(*serial_addr_user))) + return -EFAULT; + + spin_lock_irqsave(&port->lock, flags); + ret = port->set_addr(port, &addr); + spin_unlock_irqrestore(&port->lock, flags); + if (ret) + return ret; + + if (copy_to_user(serial_addr_user, &addr, sizeof(addr))) + return -EFAULT; + + return 0; +} + +static int uart_get_addr(struct uart_port *port, + struct serial_addr __user *serial_addr_user) +{ + struct serial_addr addr; + unsigned long flags; + int ret; + + if (!port->get_addr) + return -ENOTTY; + + if (copy_from_user(&addr, serial_addr_user, sizeof(*serial_addr_user))) + return -EFAULT; + + spin_lock_irqsave(&port->lock, flags); + ret = port->get_addr(port, &addr); + spin_unlock_irqrestore(&port->lock, flags); + if (ret) + return ret; + + if (copy_to_user(serial_addr_user, &addr, sizeof(addr))) + return -EFAULT; + + return 0; +} + /* * Called via sys_ioctl. We can use spin_lock_irq() here. */ @@ -1427,6 +1477,15 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) case TIOCGISO7816: ret = uart_get_iso7816_config(state->uart_port, uarg); break; + + case TIOCSADDR: + ret = uart_set_addr(uport, uarg); + break; + + case TIOCGADDR: + ret = uart_get_addr(uport, uarg); + break; + default: if (uport->ops->ioctl) ret = uport->ops->ioctl(uport, cmd, arg); @@ -1493,7 +1552,8 @@ static void uart_set_termios(struct tty_struct *tty, goto out; } - tty->termios.c_cflag &= ~ADDRB; + if (!uport->set_addr) + tty->termios.c_cflag &= ~ADDRB; uart_change_speed(tty, state, old_termios); /* reload cflag from termios; port driver may have overridden flags */ diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 504d365e2803..a2efd3fe2635 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -135,6 +135,12 @@ struct uart_port { struct serial_rs485 *rs485); int (*iso7816_config)(struct uart_port *, struct serial_iso7816 *iso7816); + + int (*set_addr)(struct uart_port *p, + struct serial_addr *addr); + int (*get_addr)(struct uart_port *p, + struct serial_addr *addr); + unsigned int irq; /* irq number */ unsigned long irqflags; /* irq flags */ unsigned int uartclk; /* base uart clock */ diff --git a/include/uapi/asm-generic/ioctls.h b/include/uapi/asm-generic/ioctls.h index cdc9f4ca8c27..689743366091 100644 --- a/include/uapi/asm-generic/ioctls.h +++ b/include/uapi/asm-generic/ioctls.h @@ -106,6 +106,9 @@ # define FIOQSIZE 0x5460 #endif +#define TIOCSADDR _IOWR('T', 0x63, struct serial_addr) +#define TIOCGADDR _IOWR('T', 0x64, struct serial_addr) + /* Used for packet mode */ #define TIOCPKT_DATA 0 #define TIOCPKT_FLUSHREAD 1 diff --git a/include/uapi/linux/serial.h b/include/uapi/linux/serial.h index fa6b16e5fdd8..8cb785ea7087 100644 --- a/include/uapi/linux/serial.h +++ b/include/uapi/linux/serial.h @@ -149,4 +149,12 @@ struct serial_iso7816 { __u32 reserved[5]; }; +struct serial_addr { + __u32 flags; +#define SER_ADDR_RECV (1 << 0) +#define SER_ADDR_RECV_CLEAR (1 << 1) +#define SER_ADDR_DEST (1 << 2) + __u32 addr; +}; + #endif /* _UAPI_LINUX_SERIAL_H */