From patchwork Fri Dec 27 22:45:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 853979 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4BD9313D518; Fri, 27 Dec 2024 22:45:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735339534; cv=none; b=YeiZmFESzjcati2hIGE8hLZ6rfDLvx4sD8btNkUnfRMuv8fRQfMO9jKxdhtgtjJL+4d9jBXbyMUZEw2U0MYmzAieMn2nj69hsMkkgedbebrCy/YKktoC0YRFFzW8L6LnV168rmwXszs7YGNVue0r6o2n5RjatOP+WzyuF9y+8QQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735339534; c=relaxed/simple; bh=2BzpnH0P0efFtE1Tbnr5i3eNkIVGDAWc3r18CJcfwIc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=YwZ8Qwi+ibHZ3zDwgIbT61OdGVQskTM+gAhUBY5ojYxbU2ghiwX65vOJxdujcUOwo11TBW+z+B6ksEOgIC6iK+WWP8fDA4IKCmBR5toLwi28YbwwHLgANCZu76dhdxJ+rRzZdYjHTJCspj4u//i95eBXs+eDV5ifGSsuiNu3NuE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=qA5wjkWg; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=uQjK0vpt; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="qA5wjkWg"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="uQjK0vpt" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1735339524; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uASmd5u/xWtAyaeV0vxHBkcxGYrtczlQqrX77S+KG1c=; b=qA5wjkWgOJuHMIXH34o12zQeK+ZeyEsTjboLIjjVEBtxj4UimdyR5xVba4MVcVBUiD7oVN DLyPFnVZkIxg6uSQ6mWZHrvAkbRSFrJocs08KXewD6wmOmHh3mxN9wfFCJ+ZaQV994Ssh8 hEVaOKU8JCj/HUgLN7ImouyykgxZbrcUYCwsJ2SFS9pDHR4ezT+VcXBTSKjhU7KQrA+0pP Y0+sbflknmSjfN5GIXW5q668hv+bfQ4N4LQW62WKh7jpKehFfRDFd3r9i0Vt5pKydwZSKV bc+vLqrNK6233a+uCq8XSEf/5cg1bD7dSDvNpcabe3JM8cazZYJBeYxinL6xXw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1735339524; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uASmd5u/xWtAyaeV0vxHBkcxGYrtczlQqrX77S+KG1c=; b=uQjK0vptV2fE3FlpE/zF+iPl8BrHVUktiMNexK34QZwM1QRvdDhikKbNBbFHakP/LmVrtM YvMA27RctXuoq1CA== To: Greg Kroah-Hartman Cc: Jiri Slaby , Petr Mladek , Sergey Senozhatsky , Steven Rostedt , Thomas Gleixner , Esben Haabendal , linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, Andy Shevchenko , Arnd Bergmann , Rengarajan S , Niklas Schnelle , Serge Semin , Wander Lairson Costa Subject: [PATCH tty-next v4 1/6] serial: 8250: Adjust the timeout for FIFO mode Date: Fri, 27 Dec 2024 23:51:17 +0106 Message-Id: <20241227224523.28131-2-john.ogness@linutronix.de> In-Reply-To: <20241227224523.28131-1-john.ogness@linutronix.de> References: <20241227224523.28131-1-john.ogness@linutronix.de> Precedence: bulk X-Mailing-List: linux-serial@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 After a console has written a record into UART_TX, it uses wait_for_xmitr() to wait until the data has been sent out before returning. However, wait_for_xmitr() will timeout after 10ms, regardless if the data has been transmitted or not. For single bytes, this timeout is sufficient even at very slow baud rates, such as 1200bps. However, when FIFO mode is used, there may be 64 bytes pushed into the FIFO at once. At a baud rate of 115200bps, the 10ms timeout is still sufficient. But when using lower baud rates (such as 57600bps), the timeout is _not_ sufficient. This causes longer lines to be cut off, resulting in lost and horribly misformatted output on the console. When using FIFO mode, take the number of bytes into account to determine an appropriate maximum timeout. Increasing the timeout does not affect performance since ideally the timeout never occurs. Fixes: 8f3631f0f6eb ("serial/8250: Use fifo in 8250 console driver") Signed-off-by: John Ogness Reviewed-by: Andy Shevchenko Reviewed-by: Wander Lairson Costa --- drivers/tty/serial/8250/8250_port.c | 32 +++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 1a65d3e5f3c0..3a946ebe9139 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2078,7 +2078,8 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state) serial8250_rpm_put(up); } -static void wait_for_lsr(struct uart_8250_port *up, int bits) +/* Returns true if @bits were set, false on timeout */ +static bool wait_for_lsr(struct uart_8250_port *up, int bits) { unsigned int status, tmout = 10000; @@ -2093,11 +2094,11 @@ static void wait_for_lsr(struct uart_8250_port *up, int bits) udelay(1); touch_nmi_watchdog(); } + + return (tmout != 0); } -/* - * Wait for transmitter & holding register to empty - */ +/* Wait for transmitter and holding register to empty with timeout */ static void wait_for_xmitr(struct uart_8250_port *up, int bits) { unsigned int tmout; @@ -3322,6 +3323,16 @@ static void serial8250_console_restore(struct uart_8250_port *up) serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS); } +static void fifo_wait_for_lsr(struct uart_8250_port *up, unsigned int count) +{ + unsigned int i; + + for (i = 0; i < count; i++) { + if (wait_for_lsr(up, UART_LSR_THRE)) + return; + } +} + /* * Print a string to the serial port using the device FIFO * @@ -3331,13 +3342,15 @@ static void serial8250_console_restore(struct uart_8250_port *up) static void serial8250_console_fifo_write(struct uart_8250_port *up, const char *s, unsigned int count) { - int i; const char *end = s + count; unsigned int fifosize = up->tx_loadsz; + unsigned int tx_count = 0; bool cr_sent = false; + unsigned int i; while (s != end) { - wait_for_lsr(up, UART_LSR_THRE); + /* Allow timeout for each byte of a possibly full FIFO */ + fifo_wait_for_lsr(up, fifosize); for (i = 0; i < fifosize && s != end; ++i) { if (*s == '\n' && !cr_sent) { @@ -3348,7 +3361,14 @@ static void serial8250_console_fifo_write(struct uart_8250_port *up, cr_sent = false; } } + tx_count = i; } + + /* + * Allow timeout for each byte written since the caller will only wait + * for UART_LSR_BOTH_EMPTY using the timeout of a single character + */ + fifo_wait_for_lsr(up, tx_count); } /* From patchwork Fri Dec 27 22:45:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 854159 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4BD4013C3C2; Fri, 27 Dec 2024 22:45:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735339533; cv=none; b=IGXL1Y6g5QmK4oyVHH4qnvtsWSLLMnhrOxv3+qoTfLffo+/q8vMkwhx9n/t/xj+ub60xwtXorESnQfyE5Z2JL6CL7HT0/DLfIc4d0Fnub9+aBxdiE0JeZC2F5yh5st/ImGDrXS9sjO3iwJD9FHIi9N5Bgf/UUbgJllg9RHgM9Ns= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735339533; c=relaxed/simple; bh=GSp3+UV8mlQfwSg8gpPLRwW4W9kFUA1xgRSYLnnjc3A=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ro5LcHalmqk8sPgYdW+zClUbX5h93ka0yC2nyrYGmq8fekDMfuoEWdBZ+7TERVR5cj+/g9YrANl002ururQeuGsvkqXIKPc11SlLKPv8eW2Uu81NbOmdTyLRfpXfYr8XIRM5FX74vICXXIf0n+R0KR20N32kSgIl80zTScF1pPY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=J3X4p1b4; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=avZndI4u; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="J3X4p1b4"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="avZndI4u" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1735339525; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=L3TkS8QLC2Kih29liLm4IkXScgF/yFQYpNLByhMWPz0=; b=J3X4p1b4QSUC+oqLKwC+sL5AL3KxKRwkIqnOjf31w/UB/1hbSKD7AAa/1FdNv6srXpI6eG kO9Nk2VYjxIgJ9l/h7OZhPCNQUxE9FRFE8pUag6yAEGy2lmT1831wo7W0xToV1IL1ihfBz B03XxsUe1g6y0QTB2j73fyNNGwkB6BtB4ALEUlohVDuEvP8udsvSVAeq2ZV9nhf4+GhGsR 6tqy+I4EWhMgjdDAiOr9pGb1hJQDyjkOO4naXp4Oh5mHx4FogzR6faV/m1fizmGgSooVxP JNcmXC8PX4gTeabxPU0S6+YZIolYbF2h1rbZ79V84wdz7xQ243layelaxK38xA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1735339525; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=L3TkS8QLC2Kih29liLm4IkXScgF/yFQYpNLByhMWPz0=; b=avZndI4uHRpAEAv8Aa6K0aAPF5EZesSdgUj5DzE70jGCDMVCI5Sgu90ZN798Q3nUdC2Kk9 PAM25iGBFEuoSqAA== To: Greg Kroah-Hartman Cc: Jiri Slaby , Petr Mladek , Sergey Senozhatsky , Steven Rostedt , Thomas Gleixner , Esben Haabendal , linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, Andy Shevchenko , Arnd Bergmann , Rengarajan S , Niklas Schnelle , Serge Semin Subject: [PATCH tty-next v4 2/6] serial: 8250: Use frame rate to determine timeout Date: Fri, 27 Dec 2024 23:51:18 +0106 Message-Id: <20241227224523.28131-3-john.ogness@linutronix.de> In-Reply-To: <20241227224523.28131-1-john.ogness@linutronix.de> References: <20241227224523.28131-1-john.ogness@linutronix.de> Precedence: bulk X-Mailing-List: linux-serial@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Rather than using a hard-coded per-character Tx-timeout of 10ms, use the frame rate to determine a timeout value. The value is doubled to ensure that a timeout is only hit during unexpected circumstances. Since the frame rate may not be available during early printing, the previous 10ms value is kept as a fallback. Signed-off-by: John Ogness --- drivers/tty/serial/8250/8250_port.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 3a946ebe9139..aeacf9d452e4 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2083,7 +2083,14 @@ static bool wait_for_lsr(struct uart_8250_port *up, int bits) { unsigned int status, tmout = 10000; - /* Wait up to 10ms for the character(s) to be sent. */ + /* + * Wait for a character to be sent. Fallback to a safe default + * timeout value if @frame_time is not available. + */ + + if (up->port.frame_time) + tmout = up->port.frame_time * 2 / NSEC_PER_USEC; + for (;;) { status = serial_lsr_in(up); From patchwork Fri Dec 27 22:45:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 854158 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 60C55155CB3; Fri, 27 Dec 2024 22:45:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735339534; cv=none; b=u9WfkBHf2VxDtrzXUkQv69trjz0gcyXnW0DIzYPl7gy646j/4wS2WhhsMEnlwPxb/rTgy/LF485fckCUkDCgAmxPM2zlUuB/vVcitwHPtr20YS5pbnTS5Gnstp+jDbQHcjOy1kRfRtO9ZqNFPt+74mEzCWnVAvf8J5elzuV7hFE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735339534; c=relaxed/simple; bh=847dnAyEyJU9u4HAy5/kzMTmcQ7OLra1Lu+DFPIQlm4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=N0rbX6n6EPPy0irmSXV28lx7+LWW/p4/cRXXVhKyhyDXd52QIEpOMlNCHUaxFQhcq35v5y95cyWaGO+76rCjp21zHVn09UTCrqrQgejXDkwPfWt+icQa16cBQcwxXci55auyyKpCVheCtAuRXY5K1SFtPRxzze4TvM3h6AWghFo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=abxtdc+e; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=dddETy03; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="abxtdc+e"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="dddETy03" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1735339525; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PRm5QPZ8g+hOoTns/vkCG62fDERJWECzx09fOxeCZMk=; b=abxtdc+eMP8oYVqwVJeHXRvtPnQmU1MZod0+tFOPuDfF83vdhKffvhAzTqmQN6fqZdjKek yOavVJ3l7/HxVCMEIrSDtLadM0t/c8iZuzAC1lekGKfNLhL24yKYDpI2atx4OZ8wgNGoy6 zMszJ7W6NxBYLxAX9djCohlbOgvSQ/29OsTIE9rGSZCu/3uD3RQ+WNHzDb31613kngHU4u /qaKrWHYfYg9Q1W9IYcaYdkCbiuff5TqZNBHp1YbTn1k6ESCCpEWKzzx6Wktday6o2aqjk 6gskrXzhQ5C+JtfyBU6Ni7t5HeqjDwfWef6l3t+tZWlALUV5/zoIVlnQIS2Q+A== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1735339525; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PRm5QPZ8g+hOoTns/vkCG62fDERJWECzx09fOxeCZMk=; b=dddETy03MjCIrFxjUMsaYMPUU1IdZScxuXGOHH1Dq7z6pQFZ9TFZooA0DHRa+71Hxie0d3 Ggw+Uq0g1iIFg4AA== To: Greg Kroah-Hartman Cc: Jiri Slaby , Petr Mladek , Sergey Senozhatsky , Steven Rostedt , Thomas Gleixner , Esben Haabendal , linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, Andy Shevchenko , Arnd Bergmann , Rengarajan S , Niklas Schnelle , Serge Semin Subject: [PATCH tty-next v4 3/6] serial: 8250: Use high-level writing function for FIFO Date: Fri, 27 Dec 2024 23:51:19 +0106 Message-Id: <20241227224523.28131-4-john.ogness@linutronix.de> In-Reply-To: <20241227224523.28131-1-john.ogness@linutronix.de> References: <20241227224523.28131-1-john.ogness@linutronix.de> Precedence: bulk X-Mailing-List: linux-serial@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Currently serial8250_console_fifo_write() directly writes into the UART_TX register rather than using the high-level function serial8250_console_putchar(). This is because serial8250_console_putchar() waits for the holding register to become empty, which would defeat the purpose of the FIFO code. Move the LSR_THRE waiting to a new function serial8250_console_wait_putchar() so that the FIFO code can use serial8250_console_putchar(). This will be particularly important for a follow-up commit, where output bytes are inspected to track newlines. This is only refactoring and has no functional change. Signed-off-by: John Ogness Reviewed-by: Andy Shevchenko Reviewed-by: Petr Mladek --- drivers/tty/serial/8250/8250_port.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index aeacf9d452e4..812f003c252d 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -3297,11 +3297,16 @@ EXPORT_SYMBOL_GPL(serial8250_set_defaults); #ifdef CONFIG_SERIAL_8250_CONSOLE static void serial8250_console_putchar(struct uart_port *port, unsigned char ch) +{ + serial_port_out(port, UART_TX, ch); +} + +static void serial8250_console_wait_putchar(struct uart_port *port, unsigned char ch) { struct uart_8250_port *up = up_to_u8250p(port); wait_for_xmitr(up, UART_LSR_THRE); - serial_port_out(port, UART_TX, ch); + serial8250_console_putchar(port, ch); } /* @@ -3351,6 +3356,7 @@ static void serial8250_console_fifo_write(struct uart_8250_port *up, { const char *end = s + count; unsigned int fifosize = up->tx_loadsz; + struct uart_port *port = &up->port; unsigned int tx_count = 0; bool cr_sent = false; unsigned int i; @@ -3361,10 +3367,10 @@ static void serial8250_console_fifo_write(struct uart_8250_port *up, for (i = 0; i < fifosize && s != end; ++i) { if (*s == '\n' && !cr_sent) { - serial_out(up, UART_TX, '\r'); + serial8250_console_putchar(port, '\r'); cr_sent = true; } else { - serial_out(up, UART_TX, *s++); + serial8250_console_putchar(port, *s++); cr_sent = false; } } @@ -3444,7 +3450,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, if (likely(use_fifo)) serial8250_console_fifo_write(up, s, count); else - uart_console_write(port, s, count, serial8250_console_putchar); + uart_console_write(port, s, count, serial8250_console_wait_putchar); /* * Finally, wait for transmitter to become empty From patchwork Fri Dec 27 22:45:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 854157 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 61FCF157E82; Fri, 27 Dec 2024 22:45:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735339536; cv=none; b=XCCzbdEuQdo7z35kzdVRf8uyvH67Xo4D1PnBdI0JkOdQC9MwmZpuDxCnUIT5cG8wLFjce0rhUEnneSjeeP20zTXlaw7YKE1Pcg1kPYUtFSZUodozF2h7NnbUEnMP60ry1YLBcJNNCZELgI/rp0EML2TSMr4lVizgjiJgeFD1REo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735339536; c=relaxed/simple; bh=BgDAW/j4qyu0YBOstKGTm7JxD7KvCBzhabJC69kgChw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=AsPd9KerWIJ2ih9t9GW0WXc8lAsfYv97WV6ylbel655i7HdQ/Hmv3fUiDgv6e6gzMkYUqdMxp6f7KB0zmfz8fTeVcI5tA3N6BYRu89IHfUAAlTCKyV25CRhmC/1ndfeIxTYvGYuIxaofmZf3dZ1wNDMrrj2UePPqStx61j6tDio= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=YGbNTbzB; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=oWsyHpU7; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="YGbNTbzB"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="oWsyHpU7" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1735339526; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=L823infgxoPboFK1hsbz+0QBq7B/x6XIBXkE7NZh1f8=; b=YGbNTbzBTy66oo55AeF5o775D61asoChdnm8Biwh8koJlPtqF6aee12UoeuOc1Bl3BET7K rl+TE1nVICwyB//mgl11pGUdHNpt4Q+uCHYvVXWN7tTkLpxfOOXpX85KZk4DKX8r7YbWfx hSsEDYz23eZEVKy6Dmvuiwej7PxxLf5Pbs0lHaipHjX7jOhm79QgC8hjBtDqQz7WAYY92o fvgZyQQANt7AWGgRXJbbw8NJo5fgQV2N69GzN3ox0uBUgbWV0FTzghta9cZV5urbNECuhQ dYmtLF5NWFoRX51JHmcMPRB+lTQINVKAFts3//9viw/rzs4ijbgZeH1wcAKkmA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1735339526; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=L823infgxoPboFK1hsbz+0QBq7B/x6XIBXkE7NZh1f8=; b=oWsyHpU7fUTd2Uyl0zR6i6Y1C96s5dNNwcaZBG/PLK2L4Wz7IUPWOsAAeYdvT9KDnhcfLM Zh93w+x+ytHgv0BQ== To: Greg Kroah-Hartman Cc: Jiri Slaby , Petr Mladek , Sergey Senozhatsky , Steven Rostedt , Thomas Gleixner , Esben Haabendal , linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, Florian Fainelli , Ray Jui , Scott Branden , Broadcom internal kernel review list , Andy Shevchenko , Arnd Bergmann , Sunil V L , Matt Turner , Stefan Wahren , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Kevin Hilman , Markus Schneider-Pargmann , Udit Kumar , Griffin Kroah-Hartman , Niklas Schnelle , Serge Semin , linux-rpi-kernel@lists.infradead.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH tty-next v4 4/6] serial: 8250: Provide flag for IER toggling for RS485 Date: Fri, 27 Dec 2024 23:51:20 +0106 Message-Id: <20241227224523.28131-5-john.ogness@linutronix.de> In-Reply-To: <20241227224523.28131-1-john.ogness@linutronix.de> References: <20241227224523.28131-1-john.ogness@linutronix.de> Precedence: bulk X-Mailing-List: linux-serial@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 For RS485 mode, if SER_RS485_RX_DURING_TX is not available, the console ->write() callback needs to enable/disable Tx. It does this by calling the ->rs485_start_tx() and ->rs485_stop_tx() callbacks. However, some of these callbacks also disable/enable interrupts and makes power management calls. This causes 2 problems for console writing: 1. A console write can occur in contexts that are illegal for pm_runtime_*(). It is not even necessary for console writing to use pm_runtime_*() because a console already does this in serial8250_console_setup() and serial8250_console_exit(). 2. The console ->write() callback already handles disabling/enabling the interrupts by properly restoring the previous IER value. Add an argument @toggle_ier to the ->rs485_start_tx() and ->rs485_stop_tx() callbacks to specify if they may disable/enable receive interrupts while using pm_runtime_*(). Console writing will not allow the toggling. For all call sites other than console writing there is no functional change. Signed-off-by: John Ogness --- drivers/tty/serial/8250/8250.h | 4 ++-- drivers/tty/serial/8250/8250_bcm2835aux.c | 4 ++-- drivers/tty/serial/8250/8250_omap.c | 2 +- drivers/tty/serial/8250/8250_port.c | 26 +++++++++++++---------- include/linux/serial_8250.h | 4 ++-- 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index e5310c65cf52..11e05aa014e5 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -231,8 +231,8 @@ void serial8250_rpm_put_tx(struct uart_8250_port *p); int serial8250_em485_config(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485); -void serial8250_em485_start_tx(struct uart_8250_port *p); -void serial8250_em485_stop_tx(struct uart_8250_port *p); +void serial8250_em485_start_tx(struct uart_8250_port *p, bool toggle_ier); +void serial8250_em485_stop_tx(struct uart_8250_port *p, bool toggle_ier); void serial8250_em485_destroy(struct uart_8250_port *p); extern struct serial_rs485 serial8250_em485_supported; diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c index fdb53b54e99e..0609582a62f7 100644 --- a/drivers/tty/serial/8250/8250_bcm2835aux.c +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -46,7 +46,7 @@ struct bcm2835aux_data { u32 cntl; }; -static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up) +static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up, bool toggle_ier) { if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) { struct bcm2835aux_data *data = dev_get_drvdata(up->port.dev); @@ -65,7 +65,7 @@ static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up) serial8250_out_MCR(up, UART_MCR_RTS); } -static void bcm2835aux_rs485_stop_tx(struct uart_8250_port *up) +static void bcm2835aux_rs485_stop_tx(struct uart_8250_port *up, bool toggle_ier) { if (up->port.rs485.flags & SER_RS485_RTS_AFTER_SEND) serial8250_out_MCR(up, 0); diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 42b4aa56b902..c2b75e3f106d 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -365,7 +365,7 @@ static void omap8250_restore_regs(struct uart_8250_port *up) if (up->port.rs485.flags & SER_RS485_ENABLED && up->port.rs485_config == serial8250_em485_config) - serial8250_em485_stop_tx(up); + serial8250_em485_stop_tx(up, true); } /* diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 812f003c252d..e38271f477d1 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -578,7 +578,7 @@ static int serial8250_em485_init(struct uart_8250_port *p) deassert_rts: if (p->em485->tx_stopped) - p->rs485_stop_tx(p); + p->rs485_stop_tx(p, true); return 0; } @@ -1398,10 +1398,11 @@ static void serial8250_stop_rx(struct uart_port *port) /** * serial8250_em485_stop_tx() - generic ->rs485_stop_tx() callback * @p: uart 8250 port + * @toggle_ier: true to allow enabling receive interrupts * * Generic callback usable by 8250 uart drivers to stop rs485 transmission. */ -void serial8250_em485_stop_tx(struct uart_8250_port *p) +void serial8250_em485_stop_tx(struct uart_8250_port *p, bool toggle_ier) { unsigned char mcr = serial8250_in_MCR(p); @@ -1422,8 +1423,10 @@ void serial8250_em485_stop_tx(struct uart_8250_port *p) if (!(p->port.rs485.flags & SER_RS485_RX_DURING_TX)) { serial8250_clear_and_reinit_fifos(p); - p->ier |= UART_IER_RLSI | UART_IER_RDI; - serial_port_out(&p->port, UART_IER, p->ier); + if (toggle_ier) { + p->ier |= UART_IER_RLSI | UART_IER_RDI; + serial_port_out(&p->port, UART_IER, p->ier); + } } } EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx); @@ -1438,7 +1441,7 @@ static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t) serial8250_rpm_get(p); uart_port_lock_irqsave(&p->port, &flags); if (em485->active_timer == &em485->stop_tx_timer) { - p->rs485_stop_tx(p); + p->rs485_stop_tx(p, true); em485->active_timer = NULL; em485->tx_stopped = true; } @@ -1470,7 +1473,7 @@ static void __stop_tx_rs485(struct uart_8250_port *p, u64 stop_delay) em485->active_timer = &em485->stop_tx_timer; hrtimer_start(&em485->stop_tx_timer, ns_to_ktime(stop_delay), HRTIMER_MODE_REL); } else { - p->rs485_stop_tx(p); + p->rs485_stop_tx(p, true); em485->active_timer = NULL; em485->tx_stopped = true; } @@ -1559,6 +1562,7 @@ static inline void __start_tx(struct uart_port *port) /** * serial8250_em485_start_tx() - generic ->rs485_start_tx() callback * @up: uart 8250 port + * @toggle_ier: true to allow disabling receive interrupts * * Generic callback usable by 8250 uart drivers to start rs485 transmission. * Assumes that setting the RTS bit in the MCR register means RTS is high. @@ -1566,11 +1570,11 @@ static inline void __start_tx(struct uart_port *port) * stoppable by disabling the UART_IER_RDI interrupt. (Some chips set the * UART_LSR_DR bit even when UART_IER_RDI is disabled, foiling this approach.) */ -void serial8250_em485_start_tx(struct uart_8250_port *up) +void serial8250_em485_start_tx(struct uart_8250_port *up, bool toggle_ier) { unsigned char mcr = serial8250_in_MCR(up); - if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) + if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX) && toggle_ier) serial8250_stop_rx(&up->port); if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND) @@ -1604,7 +1608,7 @@ static bool start_tx_rs485(struct uart_port *port) if (em485->tx_stopped) { em485->tx_stopped = false; - up->rs485_start_tx(up); + up->rs485_start_tx(up, true); if (up->port.rs485.delay_rts_before_send > 0) { em485->active_timer = &em485->start_tx_timer; @@ -3423,7 +3427,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, if (em485) { if (em485->tx_stopped) - up->rs485_start_tx(up); + up->rs485_start_tx(up, false); mdelay(port->rs485.delay_rts_before_send); } @@ -3461,7 +3465,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, if (em485) { mdelay(port->rs485.delay_rts_after_send); if (em485->tx_stopped) - up->rs485_stop_tx(up); + up->rs485_stop_tx(up, false); } serial_port_out(port, UART_IER, ier); diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index e0717c8393d7..144de7a7948d 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -161,8 +161,8 @@ struct uart_8250_port { void (*dl_write)(struct uart_8250_port *up, u32 value); struct uart_8250_em485 *em485; - void (*rs485_start_tx)(struct uart_8250_port *); - void (*rs485_stop_tx)(struct uart_8250_port *); + void (*rs485_start_tx)(struct uart_8250_port *up, bool toggle_ier); + void (*rs485_stop_tx)(struct uart_8250_port *up, bool toggle_ier); /* Serial port overrun backoff */ struct delayed_work overrun_backoff; From patchwork Fri Dec 27 22:45:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 853977 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 993F1158525; Fri, 27 Dec 2024 22:45:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735339536; cv=none; b=ET5xHiZPw3tBuwpmGLneXINxPhXu/d1Hm3ZF0ADwEhc5FCXWeWfeBfX/egSJEYdGU9ucB91vaElNtthfHvAPk5mN3HaTpXK6P/8OUu39rrlaT633/lsjQxg6X/TlxG0BBPyKVvLbbwTTAaMkqc3b2KIuxsL6gpZAtPHDJEFQgk4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735339536; c=relaxed/simple; bh=2ZGiIUgMsPX77GCLFu0Uu1nElWI3oLL1xw1QVNOvoOk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=eTpoRmXIyTuHWIQ31ljR9BBVGr2ZKGLx0tMxx0pkqrH4xbKrYYSkMeppcnGURw6LWC/fNA23oEpoyi9nvoenuzWBBEB2mAiFZ9/L1Qr3//JveoAopUj+BBf2PmJT5Rp3y/r+fJYwhM3wp/gduyan1pmdcIDyr4asaUL4g56RNMQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=qb/StGQ+; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=X4DP2cRt; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="qb/StGQ+"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="X4DP2cRt" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1735339527; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bkeDrc/RBAn/s0ivBR+9zpc2uVkypfbM9hDUcSXv7JU=; b=qb/StGQ+3taS87EFNEtTNh0s8xS6ZSp753xNzf5QuuKaLJtpblQ24jShwNC34o3qj4FIiE ZBvDmBw//JgUKa4ktx+5MTN6eGB8K5R5LfO/kkIU4NCsMiF6SDsPl95gk6AvCIiecFZz4t divwOJtahhkiXNMgKifaqf9zMkWYD27ZboKSRSuLP4ulVZdMvaA7Io3xedhPF9N7IQA38O mgqJqwMdyMJwaVocS+HypwKUP2HnWD9wI7V+jW45gPmNgLiysHJD3lXa1Q4MYB6qi7rTvb Et2f7wsxfaCP/c+MryMYjHylWyLLUPFpeITzbFcEnNZobJ/RWJQ9S5TEU7ZQ/A== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1735339527; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bkeDrc/RBAn/s0ivBR+9zpc2uVkypfbM9hDUcSXv7JU=; b=X4DP2cRtTuqfiMxO0MKnTimCkQSAnH67BJEDtlW+W5wkPZ0aToyNLFpLpuMqX/qIkgQeGD 3Nx6ObgCsmcf6BAg== To: Greg Kroah-Hartman Cc: Jiri Slaby , Petr Mladek , Sergey Senozhatsky , Steven Rostedt , Thomas Gleixner , Esben Haabendal , linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, Andy Shevchenko , Matt Turner , Tony Lindgren , Arnd Bergmann , Niklas Schnelle , Serge Semin Subject: [PATCH tty-next v4 5/6] serial: 8250: Switch to nbcon console Date: Fri, 27 Dec 2024 23:51:21 +0106 Message-Id: <20241227224523.28131-6-john.ogness@linutronix.de> In-Reply-To: <20241227224523.28131-1-john.ogness@linutronix.de> References: <20241227224523.28131-1-john.ogness@linutronix.de> Precedence: bulk X-Mailing-List: linux-serial@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Implement the necessary callbacks to switch the 8250 console driver to perform as an nbcon console. Add implementations for the nbcon console callbacks: ->write_atomic() ->write_thread() ->device_lock() ->device_unlock() and add CON_NBCON to the initial @flags. All register access in the callbacks are within unsafe sections. The ->write_atomic and ->write_therad() callbacks allow safe handover/takeover per byte and add a preceding newline if they take over from another context mid-line. For the ->write_atomic() callback, a new irq_work is used to defer modem control since it may be called from a context that does not allow waking up tasks. Note: A new __serial8250_clear_IER() is introduced for direct clearing of UART_IER. This will allow to restore the lockdep check to serial8250_clear_IER() in a follow-up commit. Signed-off-by: John Ogness --- drivers/tty/serial/8250/8250_core.c | 35 ++++++- drivers/tty/serial/8250/8250_port.c | 149 +++++++++++++++++++++------- include/linux/serial_8250.h | 8 +- 3 files changed, 150 insertions(+), 42 deletions(-) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 2b70e82dffeb..3d5a2183ff13 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -388,12 +388,34 @@ void __init serial8250_register_ports(struct uart_driver *drv, struct device *de #ifdef CONFIG_SERIAL_8250_CONSOLE -static void univ8250_console_write(struct console *co, const char *s, - unsigned int count) +static void univ8250_console_write_atomic(struct console *co, + struct nbcon_write_context *wctxt) { struct uart_8250_port *up = &serial8250_ports[co->index]; - serial8250_console_write(up, s, count); + serial8250_console_write(up, wctxt, true); +} + +static void univ8250_console_write_thread(struct console *co, + struct nbcon_write_context *wctxt) +{ + struct uart_8250_port *up = &serial8250_ports[co->index]; + + serial8250_console_write(up, wctxt, false); +} + +static void univ8250_console_device_lock(struct console *co, unsigned long *flags) +{ + struct uart_port *up = &serial8250_ports[co->index].port; + + __uart_port_lock_irqsave(up, flags); +} + +static void univ8250_console_device_unlock(struct console *co, unsigned long flags) +{ + struct uart_port *up = &serial8250_ports[co->index].port; + + __uart_port_unlock_irqrestore(up, flags); } static int univ8250_console_setup(struct console *co, char *options) @@ -494,12 +516,15 @@ static int univ8250_console_match(struct console *co, char *name, int idx, static struct console univ8250_console = { .name = "ttyS", - .write = univ8250_console_write, + .write_atomic = univ8250_console_write_atomic, + .write_thread = univ8250_console_write_thread, + .device_lock = univ8250_console_device_lock, + .device_unlock = univ8250_console_device_unlock, .device = uart_console_device, .setup = univ8250_console_setup, .exit = univ8250_console_exit, .match = univ8250_console_match, - .flags = CON_PRINTBUFFER | CON_ANYTIME, + .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_NBCON, .index = -1, .data = &serial8250_reg, }; diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index e38271f477d1..fbba4746eccc 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -711,7 +711,12 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) serial8250_rpm_put(p); } -static void serial8250_clear_IER(struct uart_8250_port *up) +/* + * Only to be used directly by the callback helper serial8250_console_write(), + * which may not require the port lock. Use serial8250_clear_IER() instead for + * all other cases. + */ +static void __serial8250_clear_IER(struct uart_8250_port *up) { if (up->capabilities & UART_CAP_UUE) serial_out(up, UART_IER, UART_IER_UUE); @@ -719,6 +724,11 @@ static void serial8250_clear_IER(struct uart_8250_port *up) serial_out(up, UART_IER, 0); } +static inline void serial8250_clear_IER(struct uart_8250_port *up) +{ + __serial8250_clear_IER(up); +} + #ifdef CONFIG_SERIAL_8250_RSA /* * Attempts to turn on the RSA FIFO. Returns zero on failure. @@ -1406,9 +1416,6 @@ void serial8250_em485_stop_tx(struct uart_8250_port *p, bool toggle_ier) { unsigned char mcr = serial8250_in_MCR(p); - /* Port locked to synchronize UART_IER access against the console. */ - lockdep_assert_held_once(&p->port.lock); - if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND) mcr |= UART_MCR_RTS; else @@ -1424,6 +1431,12 @@ void serial8250_em485_stop_tx(struct uart_8250_port *p, bool toggle_ier) serial8250_clear_and_reinit_fifos(p); if (toggle_ier) { + /* + * Port locked to synchronize UART_IER access + * against the console + */ + lockdep_assert_held_once(&p->port.lock); + p->ier |= UART_IER_RLSI | UART_IER_RDI; serial_port_out(&p->port, UART_IER, p->ier); } @@ -3302,7 +3315,11 @@ EXPORT_SYMBOL_GPL(serial8250_set_defaults); static void serial8250_console_putchar(struct uart_port *port, unsigned char ch) { + struct uart_8250_port *up = up_to_u8250p(port); + serial_port_out(port, UART_TX, ch); + + up->console_line_ended = (ch == '\n'); } static void serial8250_console_wait_putchar(struct uart_port *port, unsigned char ch) @@ -3339,14 +3356,21 @@ static void serial8250_console_restore(struct uart_8250_port *up) serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS); } -static void fifo_wait_for_lsr(struct uart_8250_port *up, unsigned int count) +static int fifo_wait_for_lsr(struct uart_8250_port *up, + struct nbcon_write_context *wctxt, + unsigned int count) { unsigned int i; for (i = 0; i < count; i++) { + if (!nbcon_can_proceed(wctxt)) + return -EPERM; + if (wait_for_lsr(up, UART_LSR_THRE)) - return; + return 0; } + + return -ETIMEDOUT; } /* @@ -3356,18 +3380,20 @@ static void fifo_wait_for_lsr(struct uart_8250_port *up, unsigned int count) * to get empty. */ static void serial8250_console_fifo_write(struct uart_8250_port *up, - const char *s, unsigned int count) + struct nbcon_write_context *wctxt) { - const char *end = s + count; unsigned int fifosize = up->tx_loadsz; struct uart_port *port = &up->port; + const char *s = wctxt->outbuf; + const char *end = s + wctxt->len; unsigned int tx_count = 0; bool cr_sent = false; unsigned int i; while (s != end) { /* Allow timeout for each byte of a possibly full FIFO */ - fifo_wait_for_lsr(up, fifosize); + if (fifo_wait_for_lsr(up, wctxt, fifosize) == -EPERM) + return; for (i = 0; i < fifosize && s != end; ++i) { if (*s == '\n' && !cr_sent) { @@ -3385,39 +3411,51 @@ static void serial8250_console_fifo_write(struct uart_8250_port *up, * Allow timeout for each byte written since the caller will only wait * for UART_LSR_BOTH_EMPTY using the timeout of a single character */ - fifo_wait_for_lsr(up, tx_count); + fifo_wait_for_lsr(up, wctxt, tx_count); +} + +static void serial8250_console_byte_write(struct uart_8250_port *up, + struct nbcon_write_context *wctxt) +{ + struct uart_port *port = &up->port; + const char *s = wctxt->outbuf; + const char *end = s + wctxt->len; + + /* + * Write out the message. If a handover or takeover occurs, writing + * must be aborted since wctxt->outbuf and wctxt->len are no longer + * valid. + */ + while (s != end && nbcon_can_proceed(wctxt)) + uart_console_write(port, s++, 1, serial8250_console_wait_putchar); } /* - * Print a string to the serial port trying not to disturb - * any possible real use of the port... + * Print a string to the serial port trying not to disturb + * any possible real use of the port... * - * The console_lock must be held when we get here. - * - * Doing runtime PM is really a bad idea for the kernel console. - * Thus, we assume the function is called when device is powered up. + * Doing runtime PM is really a bad idea for the kernel console. + * Thus, assume it is called when device is powered up. */ -void serial8250_console_write(struct uart_8250_port *up, const char *s, - unsigned int count) +void serial8250_console_write(struct uart_8250_port *up, + struct nbcon_write_context *wctxt, + bool is_atomic) { struct uart_8250_em485 *em485 = up->em485; struct uart_port *port = &up->port; - unsigned long flags; - unsigned int ier, use_fifo; - int locked = 1; - - touch_nmi_watchdog(); + unsigned int ier; + bool use_fifo; - if (oops_in_progress) - locked = uart_port_trylock_irqsave(port, &flags); - else - uart_port_lock_irqsave(port, &flags); + if (!nbcon_enter_unsafe(wctxt)) + return; /* - * First save the IER then disable the interrupts + * First, save the IER, then disable the interrupts. The special + * variant to clear the IER is used because console printing may + * occur without holding the port lock. */ ier = serial_port_in(port, UART_IER); - serial8250_clear_IER(up); + __serial8250_clear_IER(up); /* check scratch reg to see if port powered off during system sleep */ if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) { @@ -3431,6 +3469,14 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, mdelay(port->rs485.delay_rts_before_send); } + /* + * If console printer did not fully output the previous line, it must + * have been handed or taken over. Insert a newline in order to + * maintain clean output. + */ + if (!up->console_line_ended && nbcon_can_proceed(wctxt)) + uart_console_write(port, "\n", 1, serial8250_console_wait_putchar); + use_fifo = (up->capabilities & UART_CAP_FIFO) && /* * BCM283x requires to check the fifo @@ -3452,9 +3498,16 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, !(up->port.flags & UPF_CONS_FLOW); if (likely(use_fifo)) - serial8250_console_fifo_write(up, s, count); + serial8250_console_fifo_write(up, wctxt); else - uart_console_write(port, s, count, serial8250_console_wait_putchar); + serial8250_console_byte_write(up, wctxt); + + /* + * If ownership was lost, this context must reacquire ownership in + * order to perform final actions (such as re-enabling interrupts). + */ + while (!nbcon_enter_unsafe(wctxt)) + nbcon_reacquire_nobuf(wctxt); /* * Finally, wait for transmitter to become empty @@ -3477,11 +3530,18 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, * call it if we have saved something in the saved flags * while processing with interrupts off. */ - if (up->msr_saved_flags) - serial8250_modem_status(up); + if (up->msr_saved_flags) { + /* + * For atomic, it must be deferred to irq_work because this + * may be a context that does not permit waking up tasks. + */ + if (is_atomic) + irq_work_queue(&up->modem_status_work); + else + serial8250_modem_status(up); + } - if (locked) - uart_port_unlock_irqrestore(port, flags); + nbcon_exit_unsafe(wctxt); } static unsigned int probe_baud(struct uart_port *port) @@ -3499,8 +3559,24 @@ static unsigned int probe_baud(struct uart_port *port) return (port->uartclk / 16) / quot; } +/* + * irq_work handler to perform modem control. Only triggered via + * ->write_atomic() callback because it may be in a scheduler or + * NMI context, unable to wake tasks. + */ +static void modem_status_handler(struct irq_work *iwp) +{ + struct uart_8250_port *up = container_of(iwp, struct uart_8250_port, modem_status_work); + struct uart_port *port = &up->port; + + uart_port_lock(port); + serial8250_modem_status(up); + uart_port_unlock(port); +} + int serial8250_console_setup(struct uart_port *port, char *options, bool probe) { + struct uart_8250_port *up = up_to_u8250p(port); int baud = 9600; int bits = 8; int parity = 'n'; @@ -3510,6 +3586,9 @@ int serial8250_console_setup(struct uart_port *port, char *options, bool probe) if (!port->iobase && !port->membase) return -ENODEV; + up->console_line_ended = true; + init_irq_work(&up->modem_status_work, modem_status_handler); + if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); else if (probe) diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 144de7a7948d..5a804dc5e05e 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -150,8 +150,12 @@ struct uart_8250_port { #define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS u16 lsr_saved_flags; u16 lsr_save_mask; + + bool console_line_ended; /* line fully output */ + #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA unsigned char msr_saved_flags; + struct irq_work modem_status_work; struct uart_8250_dma *dma; const struct uart_8250_ops *ops; @@ -202,8 +206,8 @@ void serial8250_tx_chars(struct uart_8250_port *up); unsigned int serial8250_modem_status(struct uart_8250_port *up); void serial8250_init_port(struct uart_8250_port *up); void serial8250_set_defaults(struct uart_8250_port *up); -void serial8250_console_write(struct uart_8250_port *up, const char *s, - unsigned int count); +void serial8250_console_write(struct uart_8250_port *up, + struct nbcon_write_context *wctxt, bool in_atomic); int serial8250_console_setup(struct uart_port *port, char *options, bool probe); int serial8250_console_exit(struct uart_port *port); From patchwork Fri Dec 27 22:45:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 853978 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6201D157E88; Fri, 27 Dec 2024 22:45:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735339535; cv=none; b=f40AOhBo2deXP7ls1F6ykdv58NMhpJYzQytLPnlaiHeiNpO3Kwmz5WAyxLWMKfsfeb4scZqoqIdufopqq494G3On/S1B6ZTZR0Y3f2v94HkmpVmJ9l0v7GnWA1lL0lCDg+gIHW8hr+VNNdPpHLUTihFkeFobwBpnLLHmBkf3Uls= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735339535; c=relaxed/simple; bh=GkKtEopb/vxipA1rE+mu+UbFX4e/7ABwXI/xzZ7fn+E=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=MhIBRqsNmNPEhpijMaRXB/KiBh56TGOcOlbJdUattPG2sU/LN9R9RW1ZKcqAF198RBSnkKA3lEk8vXeAPoiF4MPsXvm6/WimSTKBD3Jng60mPYLw1hup2EtqHWn8yK/PcrLaZ+teSRLZhQEYB9OQ1plFMTY3IV2efTHW+4+xC+I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=X6uz2rsi; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=pbhOgYJn; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="X6uz2rsi"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="pbhOgYJn" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1735339527; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9X+WdzHUSBBjVLy5D98VD/ORPFzC0dNUp9SeiqSm6E8=; b=X6uz2rsiyzSwXG5rfJRLVj6wlz7PUe2Rqnnm+1t76UqM2thyrJ7jeHk1ZCJmx+2rMqgR+4 fp+fJVFk8DFXIYfwQfW9FGMAgTLfstwuebuq22hm17y6e3PZ4RcP9BUGoK5hRIvSyidGCv apzrq4Uy8rrvyiIXO2lq/pGeLV2iYTk3XUdb+gzS9BB/7Ldr391veVlQtCkPkvcWXsbHSl W78U3SjHcrOBd8wzpXM7REXlAdYWsTLRYZ4xs3J3BSfI3SpiavSOulMQa8ePcA/hApIxvR hpQWMRDZpPr2qR4ac3cUd0FchbwPoJfQY9atl3Ofm6nYn0xMI2JWyrwbKDYGaw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1735339527; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9X+WdzHUSBBjVLy5D98VD/ORPFzC0dNUp9SeiqSm6E8=; b=pbhOgYJnesnVhsiU2Ff21JX3XC8ACIpg4Gcjm9y3jmilnZAmGHhoZ8QgIb5ZLtesGti2NH RcnWD+2BYM8U22DA== To: Greg Kroah-Hartman Cc: Jiri Slaby , Petr Mladek , Sergey Senozhatsky , Steven Rostedt , Thomas Gleixner , Esben Haabendal , linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, Andy Shevchenko , Arnd Bergmann , Niklas Schnelle , Serge Semin Subject: [PATCH tty-next v4 6/6] serial: 8250: Revert "drop lockdep annotation from serial8250_clear_IER()" Date: Fri, 27 Dec 2024 23:51:22 +0106 Message-Id: <20241227224523.28131-7-john.ogness@linutronix.de> In-Reply-To: <20241227224523.28131-1-john.ogness@linutronix.de> References: <20241227224523.28131-1-john.ogness@linutronix.de> Precedence: bulk X-Mailing-List: linux-serial@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The 8250 driver no longer depends on @oops_in_progress and will no longer violate the port->lock locking constraints. This reverts commit 3d9e6f556e235ddcdc9f73600fdd46fe1736b090. Signed-off-by: John Ogness --- drivers/tty/serial/8250/8250_port.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index fbba4746eccc..bc70e660a403 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -726,6 +726,9 @@ static void __serial8250_clear_IER(struct uart_8250_port *up) static inline void serial8250_clear_IER(struct uart_8250_port *up) { + /* Port locked to synchronize UART_IER access against the console */ + lockdep_assert_held_once(&up->port.lock); + __serial8250_clear_IER(up); }