From patchwork Fri Oct 25 10:57:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 839106 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 4833D22B65A; Fri, 25 Oct 2024 10:57: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=1729853854; cv=none; b=YGFmsGf8S5E4O4xmwg2nxrzxRe8CAOm1RuO+CJMysuxbivzQJ5gctrSEigPf3CKpwJQxT0rtENTw+zzl4LbqUQ0m0udmf6MdEjdbso0pEjL0YCrA2oRVJ7HDPxdtwgzYUCi5GdrCD9W7tCWQdfxXJBRBFnsam18pNzoPoUIOWDg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729853854; c=relaxed/simple; bh=PBj2BP4NeY2S1hM+Iyobipy6hAiL2dOKPCN9j5DWbdc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=E+FE0bDV7QzbxgU1u/lqJS2dg/3IfCEf9JfS1c9md8zUU1S+GdK53dn+xWo5Ego4o9ZKtwzQ5FGMZiJRreICfiNv9OLOqlsGUeWOYgnYNuioK3w/VuExUP4h1La95oFKa0LdCF6sinFTbsNd1nB/S2es06kOVZR+iTDu1Ftd7D4= 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=wSw70WpB; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=/Z0Cl54o; 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="wSw70WpB"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="/Z0Cl54o" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1729853850; 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=4p/TMBIF+40aWKwCg6mhGWi1HCgLwJELTVe/GEMslzk=; b=wSw70WpBb/F3DXSghnDsWjzEU05DO2cspdnqmTn9OmN0zFBUrqpbM4qLY29gZ5mOt/hr03 mxoWuF/ZGOgbNYyw76/Iuc2Xyxc1ti3hiVktXleti7Yg8aLEDarLdU9zBgmE0Ou2ZZMN8Z Q3iUxOIbhU+AID4q52l+0wRLrce3VMJMiBEX8FHjMwvn4bKqkRL3SiaIsh4loBRyk2APYw GEiaX74vXVJ5+alvSKXJ+kcxjMlF8CfbigCJyiDli+eKVNhpNDn846NHd3mI2XSCesZsHu MmyFgOxRiaCRNqSPkRY7PRLKeDr9vhIi9WnC/aKtKW5mHNRo7ErLmAWacolg4Q== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1729853850; 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=4p/TMBIF+40aWKwCg6mhGWi1HCgLwJELTVe/GEMslzk=; b=/Z0Cl54oRWaU1yrSCt1Kjyct/3vz+0IUMHIn+v60lSvb+9Zjr5LVB/zKFpxTsdey742+FF cTwd6zGQazskO0CQ== 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 , Rengarajan S , Jeff Johnson , Serge Semin , Lino Sanfilippo , Wander Lairson Costa Subject: [PATCH tty-next v3 1/6] serial: 8250: Adjust the timeout for FIFO mode Date: Fri, 25 Oct 2024 13:03:23 +0206 Message-Id: <20241025105728.602310-2-john.ogness@linutronix.de> In-Reply-To: <20241025105728.602310-1-john.ogness@linutronix.de> References: <20241025105728.602310-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 fed a line into TX, it uses wait_for_xmitr() to wait until the data has been sent out before returning to the printk code. 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. However, 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 max 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 --- drivers/tty/serial/8250/8250_port.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 3509af7dc52b..adc48eeeac2b 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2059,11 +2059,12 @@ 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; - /* Wait up to 10ms for the character(s) to be sent. */ + /* Wait up to 10ms for the character to be sent. */ for (;;) { status = serial_lsr_in(up); @@ -2074,10 +2075,13 @@ 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 + * with timeout */ static void wait_for_xmitr(struct uart_8250_port *up, int bits) { @@ -3306,13 +3310,18 @@ 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. */ + for (i = 0; i < fifosize; i++) { + if (wait_for_lsr(up, UART_LSR_THRE)) + break; + } for (i = 0; i < fifosize && s != end; ++i) { if (*s == '\n' && !cr_sent) { @@ -3323,6 +3332,13 @@ static void serial8250_console_fifo_write(struct uart_8250_port *up, cr_sent = false; } } + tx_count = i; + } + + /* Allow timeout for each byte written. */ + for (i = 0; i < tx_count; i++) { + if (wait_for_lsr(up, UART_LSR_THRE)) + break; } } From patchwork Fri Oct 25 10:57:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 839105 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 C34FE1F80CB; Fri, 25 Oct 2024 10:57: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=1729853854; cv=none; b=eLSgcpI54Ko4e4YBm4S2QL4j1lYRtdq1Ii2BYXWt1yOP6ggmbMeA69ePdlF4fVf1LfFqQ5XQbHcNJ+0PDqDVGA9Iby08mqcVKAE5+xIKbYmDjj9tgB0xqK3Ztm0L3oMFkwf/S0ct1MBBOb0TOpw4L5sKgCXQIi7N1l/9VLmIwNQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729853854; c=relaxed/simple; bh=f3+cAPfK4RNXXSnDuLv/8Vb+cYWmESyrDKzGzGUS+f0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ML2rtf/k+aL0Dx8Sj3+yOMRJxekszNUY1Y/Fc8s0Xyis5oZpwkm53s6mg1y+Y+a50VIenLrOw2SfJU4TAo7uzx3obP17gnBgbUj5yyPDLtzvWE1jw1W/c9IHP/TShz0z/2U3SCNpnms0orfrjXQd2xfv9R3VaMLY+DsdTsx1W3U= 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=0KEa8E1l; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=cYx1aTc9; 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="0KEa8E1l"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="cYx1aTc9" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1729853851; 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=Uqo1w8ChYQdngURCDum4RxzHCiFXSNcp0ppGWjfcIRs=; b=0KEa8E1lizdsEtz/CP98LmuxFbdk0lKDtf0vyc0eP9p9JPkwo456dzbW/B4O7vfy2W3iA5 WRvANjE9vpkAJwkw3LaykMKUJa+AWEqhRZLg1V05qTWfBnwfpb+hfFpaKSA82QK/aaqMGv yG3Mmt3q4KpHEKALOjKfM87Hvd8LBXdarnoTtY+MuMNt5n/QrVMot6UHpiIaDIvPlSVqsP 4iq1pJAQbN1hc34dbgMD4dbJSE6j69KVJ171Mrq6bYsaiRNuu7YEfnbLHOkbd/oDlQgGpC zX3FrpGRr78G2oOowVXi/ixAbQ+CM4H5WOXLNPtqPcsSo71Z30Zq84JE0HjCzQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1729853851; 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=Uqo1w8ChYQdngURCDum4RxzHCiFXSNcp0ppGWjfcIRs=; b=cYx1aTc9gdCNISApxi3ofM1UDkCWGROWg8TZ3+MkNPzEJa0DOKj5VFEcZB42zyFyRH4nEK FUi59G7fNy6IjPDA== 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 , Rengarajan S , Serge Semin , Lino Sanfilippo Subject: [PATCH tty-next v3 2/6] serial: 8250: Use high-level write function for FIFO Date: Fri, 25 Oct 2024 13:03:24 +0206 Message-Id: <20241025105728.602310-3-john.ogness@linutronix.de> In-Reply-To: <20241025105728.602310-1-john.ogness@linutronix.de> References: <20241025105728.602310-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. That 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: 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 adc48eeeac2b..8f7c9968ad41 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -3268,11 +3268,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); } /* @@ -3312,6 +3317,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; @@ -3325,10 +3331,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; } } @@ -3408,7 +3414,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 Oct 25 10:57:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 838687 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 AA7081F80D7; Fri, 25 Oct 2024 10:57: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=1729853855; cv=none; b=NiOkmU/lwEcFr5LRrU0IGQm5GuzVVL0k7ELEoSrC/fEmY/jFWUR5y4j99/XFlAw4OhXga2yIsXBzP6Y3uh7J4EDQhUAlsdPCOg+sxLKFVfftV7D2bQ7RrW0gNqmEQbHw9XSwYhnxI2SzH3VZ5qUlwaKjKTzDpmlSRf9XKJ+McnI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729853855; c=relaxed/simple; bh=2hzU5AqMr50CjQLw4l8M/44tP5riHfjOe+aLhjrYJHk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=a0kcaHNQPQPtoCGP84Gs4y6Ul48kD0jQ5FxcaSOeFwgOXK+4XrVCuIQJDxjKTzrjRVYpF7xpN4B7y0IodYf8zcvLQCyGV8ZbwCPL3T/8+EBokWuYa/opXs1o3xiu1Bdn/XxMgYVodqLOE/b0F56HBH7YmVcuFFkjc8rTcpbixhY= 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=FC/WpYCT; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=NAwLaY8u; 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="FC/WpYCT"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="NAwLaY8u" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1729853851; 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=7tv/1ishCi4YLrF78NQVKLK5eMVaeJDJpcjhAQwH+sE=; b=FC/WpYCT7mzyvi0bXizR5NCHCSobYzOioq6IWged4MAA+OPJ5h5dlPs1GdnqR+ooIZ6KKp IfK5UmlM4H1Mox62K8IgzF8mFpwuGphaHsysWZlZzDE6h6rbPxMNg4NtrQUMcS/fPtNpPc gCUNJCrt0R6TY1TGbnIH3sJ6+KCdwdvCHroqzDM5VJSwbBsX+U/2zC/EG+KL8iZhR4XuEs 9DyESKdi9qGFT1UE3XrQ9NU5MRF6YIO8B3EJdZ2Cs8ZtS2Qrw+oWgiizkFNIn7WTO7yY8r tdQfEAHD919T/tBWdLXi0iOAdktqGZctzk/3zp4zyjjrlopqTzQwLGU7x71+eg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1729853851; 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=7tv/1ishCi4YLrF78NQVKLK5eMVaeJDJpcjhAQwH+sE=; b=NAwLaY8u+FpxWk77r2KwWtU9b6UnhkeJc4uwJfpGqz01NQc83Trfjnr4NgP6BlKjAH6C7f 2g0AFEg5FJkXfFAw== 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 , Rengarajan S , Peter Collingbourne , Serge Semin , Lino Sanfilippo Subject: [PATCH tty-next v3 3/6] serial: 8250: Split out rx stop/start code into helpers Date: Fri, 25 Oct 2024 13:03:25 +0206 Message-Id: <20241025105728.602310-4-john.ogness@linutronix.de> In-Reply-To: <20241025105728.602310-1-john.ogness@linutronix.de> References: <20241025105728.602310-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 rx stop/start callbacks also disable/enable interrupts. This is not acceptable for the console write callback since it must manage all interrupt disabling/enabling. Move the interrupt disabling/enabling/masking into helper functions so that the console write callback can make use of the appropriate parts in a follow-up commit. This is essentially refactoring and should cause no functional change. Signed-off-by: John Ogness Reviewed-by: Andy Shevchenko Reviewed-by: Petr Mladek --- drivers/tty/serial/8250/8250_port.c | 37 ++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 8f7c9968ad41..09ac521d232a 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1360,18 +1360,37 @@ static void autoconfig_irq(struct uart_8250_port *up) port->irq = (irq > 0) ? irq : 0; } -static void serial8250_stop_rx(struct uart_port *port) +static void __serial8250_stop_rx_mask_dr(struct uart_port *port) { - struct uart_8250_port *up = up_to_u8250p(port); + port->read_status_mask &= ~UART_LSR_DR; +} +static void __serial8250_stop_rx_int(struct uart_8250_port *p) +{ /* Port locked to synchronize UART_IER access against the console. */ - lockdep_assert_held_once(&port->lock); + lockdep_assert_held_once(&p->port.lock); + + p->ier &= ~(UART_IER_RLSI | UART_IER_RDI); + serial_port_out(&p->port, UART_IER, p->ier); +} + +static void __serial8250_start_rx_int(struct uart_8250_port *p) +{ + /* 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); +} + +static void serial8250_stop_rx(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); serial8250_rpm_get(up); - up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); - up->port.read_status_mask &= ~UART_LSR_DR; - serial_port_out(port, UART_IER, up->ier); + __serial8250_stop_rx_mask_dr(port); + __serial8250_stop_rx_int(up); serial8250_rpm_put(up); } @@ -1386,9 +1405,6 @@ void serial8250_em485_stop_tx(struct uart_8250_port *p) { 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 @@ -1403,8 +1419,7 @@ 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); + __serial8250_start_rx_int(p); } } EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx); From patchwork Fri Oct 25 10:57:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 839104 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 4BFF11F80D8; Fri, 25 Oct 2024 10:57: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=1729853856; cv=none; b=Ot48Mr3e1yBzSRiJsBHoZ03z71PlmCH2e3Iotl/hvp2a8J5UQSh/Qt1B6w5OK/bsYeq/mLr88Pu30GOXN93SBvPmbMJBgjicN0BIHQQvQR7sSPfc+K2RBqB4Z6rsCW1vEK1bfNWwaXK4q/RXtUbsCF+Vc7gNaw8yV+of5VjTDJE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729853856; c=relaxed/simple; bh=vXRWkgXiczn96x/I0cfbeAy+ExITWcvoS1QIlW3Lt1A=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ZSZw8K0gQL1X3xvY+PnnasGx8cCAN5VICMJ669bKGM48MWdRQer/CsaynrLtdOQS39I5p9K8bYHXwyL1qS7KQUbmuNfRhwvZ2NNrXLHBApi4A3vKAsv1Vm2u0Ft4B37nB8XKmVl2+xayzy7FesxbSV8cD1ySlzDFPi0pcnBxog8= 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=slrwLbOG; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=6Ai98LwU; 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="slrwLbOG"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="6Ai98LwU" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1729853852; 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=4tycoxXMZP2qAEgVyWrz9W3wqW1U06QeuS7WtgHLseQ=; b=slrwLbOGv/F1VYgap0ous/jqd4LPXjiFrtb3BPBmMYFkSuDjBh2mFPfkGJq8sK8x4nmjx0 xFB9z/WVqzVLbBRThpuzYmmOBp608Huy6bcjs7jh81z2Sl3VXw73z12YkTfTQWR6dL4z8n OQv9j8/0lhf9zs3KKpUwRpaYQJ4L0GUpPkDlpClY7+Q8CF4hYfLQuR4hRjfesw/EU5Toau C3NM22ABiGRgs7ijV/HSzw8SUAn7RJ/2Y9vcFsEnpboXYztmNXVccx6aNISD/9bGUpvNy3 sdt6SL5ml+TsDGGlv8HVFHQUeoI8VUf0jQA6Ki5j1mAIAzbgFTsRAKoLGzaF+g== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1729853852; 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=4tycoxXMZP2qAEgVyWrz9W3wqW1U06QeuS7WtgHLseQ=; b=6Ai98LwU1yRYVVR8VovVPP2dQVZbVhhWcHFPpUNgmaYbyJCHM0FfZyU778L/xjXWeBhio3 y13LfZg0w+N6aLAA== 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 , Broadcom internal kernel review list , Ray Jui , Scott Branden , Andy Shevchenko , "Paul E. McKenney" , Arnd Bergmann , Stefan Wahren , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Kevin Hilman , Markus Schneider-Pargmann , Ronald Wahl , Udit Kumar , Griffin Kroah-Hartman , Rengarajan S , Lino Sanfilippo , Serge Semin , linux-rpi-kernel@lists.infradead.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH tty-next v3 4/6] serial: 8250: Specify console context for rs485_start/stop_tx Date: Fri, 25 Oct 2024 13:03:26 +0206 Message-Id: <20241025105728.602310-5-john.ogness@linutronix.de> In-Reply-To: <20241025105728.602310-1-john.ogness@linutronix.de> References: <20241025105728.602310-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/stop_tx() callbacks. However, these callbacks will disable/enable interrupts, which is a problem for console write, as it must be responsible for disabling/enabling interrupts. Add an argument @in_con to the rs485_start/stop_tx() callbacks to specify if they are being called from console write. If so, the callbacks will not handle interrupt disabling/enabling. For all call sites other than console write, 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 | 34 +++++++++++++++-------- include/linux/serial_8250.h | 4 +-- 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index e5310c65cf52..0d8717be0df7 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 in_con); +void serial8250_em485_stop_tx(struct uart_8250_port *p, bool in_con); 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..c9a106a86b56 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 in_con) { 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 in_con) { 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 b3be0fb184a3..fcbed7e98231 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, false); } /* diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 09ac521d232a..7c50387194ad 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -558,7 +558,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, false); 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 + * @in_con: true if called from console write, otherwise false * * 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 in_con) { unsigned char mcr = serial8250_in_MCR(p); @@ -1419,7 +1420,9 @@ 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); - __serial8250_start_rx_int(p); + /* In console context, caller handles interrupt enabling. */ + if (!in_con) + __serial8250_start_rx_int(p); } } EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx); @@ -1434,7 +1437,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, false); em485->active_timer = NULL; em485->tx_stopped = true; } @@ -1466,7 +1469,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, false); em485->active_timer = NULL; em485->tx_stopped = true; } @@ -1555,6 +1558,7 @@ static inline void __start_tx(struct uart_port *port) /** * serial8250_em485_start_tx() - generic ->rs485_start_tx() callback * @up: uart 8250 port + * @in_con: true if called from console write, otherwise false * * 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. @@ -1562,12 +1566,20 @@ 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 in_con) { unsigned char mcr = serial8250_in_MCR(up); - if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) - serial8250_stop_rx(&up->port); + if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) { + /* + * In console context, caller handles interrupt disabling. So + * only LSR_DR masking is needed. + */ + if (in_con) + __serial8250_stop_rx_mask_dr(&up->port); + else + serial8250_stop_rx(&up->port); + } if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND) mcr |= UART_MCR_RTS; @@ -1600,7 +1612,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, false); if (up->port.rs485.delay_rts_before_send > 0) { em485->active_timer = &em485->start_tx_timer; @@ -3402,7 +3414,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, true); mdelay(port->rs485.delay_rts_before_send); } @@ -3440,7 +3452,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, true); } serial_port_out(port, UART_IER, ier); diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index e0717c8393d7..c25c026d173d 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 in_con); + void (*rs485_stop_tx)(struct uart_8250_port *up, bool in_con); /* Serial port overrun backoff */ struct delayed_work overrun_backoff; From patchwork Fri Oct 25 10:57:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 839103 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 CB30F1FDF87; Fri, 25 Oct 2024 10:57:35 +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=1729853858; cv=none; b=No1kiQsdNVlC+fkEB3uGOM5yqtD/WAXWUPF1QExM5mUtRnvfUaV1pztPsD3UhipPTF55tE1cXT8tVMDHxbuq4s8CO5UIAk4cT2JfRYuq69dSSneCZ84zfJjwYDi4A8FQKprHrIyeI9rpyiktWy3XBJPbR7W8cYtGFuPie6Lhpzw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729853858; c=relaxed/simple; bh=3h+txqWzyjQpA7zaMYUC0Z5J9ymUMNDS1VQdHw/pS7E=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=L39ZM8NpCvlogEdQE/DnW2bAf8G4X3ond41bW/+m8XUpTuPYKVhJ0R+2mBF1OignESk4DvI2Tn9rxt+u5aQFW4kLERGI0lPlgOsUp1XEQ+dXFgTawUNDLAYq/uKwIWraOrgNPQJVxSKg0AaDTfvn8F38DRK+XHjMPCwcctndHwA= 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=m+7GBTgU; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=JpfBptI6; 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="m+7GBTgU"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="JpfBptI6" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1729853853; 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=WcQUijP5hAsE4CbjXcrwMKxgGZrjYODkUVfif5UcrIs=; b=m+7GBTgUwqEJjvIub/v3OqICAiG1GIHCYdH0eJqBAt99HhbHMKWjQp1MAaPZT8nhPIL8WS 5g4N7lisjhZWt+EJ7v/evBZOtpSsmA8Kf6lbAc5n8efcwyZvOz8pYZfjor53+UxhOb+dmr VgzxfyRVf20ZA8hHLr+UQRlaIHFS6d0C8Ro3ZhvA+aTU9FZ0fexxLe4InivYjoNX87PrYD cNzVnqzUYYuq3MQaWM5Ugqb/qr6bw4YU/uRX3UrejBcNkeXrCyL5rghJUsSxzU7yhhMR7i nJnuGlu//Lb0JHcKFxN1LAJndTjCsYIJVNV4uV1HMBsMn9oPm/jNo4EFkMZHIw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1729853853; 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=WcQUijP5hAsE4CbjXcrwMKxgGZrjYODkUVfif5UcrIs=; b=JpfBptI6BFNZWYGAELUhnPUEvGCHt/IQr72Vp41PhE6n3QomSN60EkyFevEH9+SuxLOWJJ LIqyMvg4iY319ICQ== 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 , Geert Uytterhoeven , Arnd Bergmann , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Tony Lindgren , Rengarajan S , Peter Collingbourne , Serge Semin , Lino Sanfilippo Subject: [PATCH tty-next v3 5/6] serial: 8250: Switch to nbcon console Date: Fri, 25 Oct 2024 13:03:27 +0206 Message-Id: <20241025105728.602310-6-john.ogness@linutronix.de> In-Reply-To: <20241025105728.602310-1-john.ogness@linutronix.de> References: <20241025105728.602310-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 callbacks allow safe handover/takeover per byte and add a preceding newline if they take over mid-line. For the write_atomic() case, a new irq_work is used to defer modem control since it may be a context that does not allow waking up tasks. Signed-off-by: John Ogness --- drivers/tty/serial/8250/8250_core.c | 35 +++++- drivers/tty/serial/8250/8250_port.c | 159 ++++++++++++++++++++++------ include/linux/serial_8250.h | 7 +- 3 files changed, 164 insertions(+), 37 deletions(-) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 5f9f06911795..7184100129bd 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 *con, unsigned long *flags) +{ + struct uart_port *up = &serial8250_ports[con->index].port; + + __uart_port_lock_irqsave(up, flags); +} + +static void univ8250_console_device_unlock(struct console *con, unsigned long flags) +{ + struct uart_port *up = &serial8250_ports[con->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 7c50387194ad..0b3596fab061 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -691,7 +691,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 console write callbacks, 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); @@ -699,6 +704,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. @@ -3296,7 +3306,14 @@ 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); + + if (ch == '\n') + up->console_line_ended = true; + else + up->console_line_ended = false; } static void serial8250_console_wait_putchar(struct uart_port *port, unsigned char ch) @@ -3340,9 +3357,10 @@ static void serial8250_console_restore(struct uart_8250_port *up) * 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; + const char *s = READ_ONCE(wctxt->outbuf); + const char *end = s + READ_ONCE(wctxt->len); unsigned int fifosize = up->tx_loadsz; struct uart_port *port = &up->port; unsigned int tx_count = 0; @@ -3352,10 +3370,19 @@ static void serial8250_console_fifo_write(struct uart_8250_port *up, while (s != end) { /* Allow timeout for each byte of a possibly full FIFO. */ for (i = 0; i < fifosize; i++) { + if (!nbcon_enter_unsafe(wctxt)) + return; + if (wait_for_lsr(up, UART_LSR_THRE)) break; + + if (!nbcon_exit_unsafe(wctxt)) + return; } + if (!nbcon_enter_unsafe(wctxt)) + return; + for (i = 0; i < fifosize && s != end; ++i) { if (*s == '\n' && !cr_sent) { serial8250_console_putchar(port, '\r'); @@ -3366,45 +3393,74 @@ static void serial8250_console_fifo_write(struct uart_8250_port *up, } } tx_count = i; + + if (!nbcon_exit_unsafe(wctxt)) + return; } /* Allow timeout for each byte written. */ for (i = 0; i < tx_count; i++) { + if (!nbcon_enter_unsafe(wctxt)) + return; + if (wait_for_lsr(up, UART_LSR_THRE)) break; + + if (!nbcon_exit_unsafe(wctxt)) + return; + } +} + +static void serial8250_console_byte_write(struct uart_8250_port *up, + struct nbcon_write_context *wctxt) +{ + const char *s = READ_ONCE(wctxt->outbuf); + const char *end = s + READ_ONCE(wctxt->len); + struct uart_port *port = &up->port; + + /* + * Write out the message. Toggle unsafe for each byte in order to give + * another (higher priority) context the opportunity for a friendly + * takeover. If such a takeover occurs, this must abort writing since + * wctxt->outbuf and wctxt->len are no longer valid. + */ + while (s != end) { + if (!nbcon_enter_unsafe(wctxt)) + return; + + uart_console_write(port, s++, 1, serial8250_console_wait_putchar); + + if (!nbcon_exit_unsafe(wctxt)) + return; } } /* - * 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 IER then disable the interrupts. The special variant + * to clear 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))) { @@ -3418,6 +3474,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 @@ -3438,10 +3502,19 @@ 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); - else - uart_console_write(port, s, count, serial8250_console_wait_putchar); + if (nbcon_exit_unsafe(wctxt)) { + if (likely(use_fifo)) + serial8250_console_fifo_write(up, wctxt); + else + 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 @@ -3464,11 +3537,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) @@ -3486,8 +3566,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'; @@ -3497,6 +3593,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; + up->modem_status_work = IRQ_WORK_INIT(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 c25c026d173d..c6c391b15efc 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -152,6 +152,9 @@ struct uart_8250_port { u16 lsr_save_mask; #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA unsigned char msr_saved_flags; + struct irq_work modem_status_work; + + bool console_line_ended; /* line fully output */ struct uart_8250_dma *dma; const struct uart_8250_ops *ops; @@ -202,8 +205,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 Oct 25 10:57:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 838686 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 CB3691FDF89; Fri, 25 Oct 2024 10:57:35 +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=1729853857; cv=none; b=S7769Am51GNqZsKfNOMTHLe41ylXjF0i9dMaiB7lZF5TlvdZK+JHXRCo/98vYX35STgE8eZbFYp7SLlfDiqfp+rtBAXwhNnVm3JfzzqtrOeRN4kyp2W9skIU4U7MZnmqbUmiVW/sqnWJZdrMzjTCSGw1Wu41bWJqNwRTmjCLXdQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729853857; c=relaxed/simple; bh=uCi25v7dZPwJgSMo0oWApVBb4GIOCxuUJNEt29mFJas=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=BM3A9VY87DStW/CwZ/D4MV68OL+vsIiCWpKH2Y5FJYhLC8KnDQpXFwxCgFl+goCchIiYIZztKKmuu+L49IQBniJRdd0arLUV26db3pgeuD/Nkvc2q1VvNGcyjcekPDGO95emt9ikqn0JlsGxhd8wxqwPRR+HoLaeOgP2b3wP26U= 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=0mo9aEbL; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=iSH4i65F; 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="0mo9aEbL"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="iSH4i65F" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1729853853; 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=4ckN3By33osOOhRu/7ilSfmb+7G76g/geNYlu+/gEoU=; b=0mo9aEbLzREU4cfbGF2y5izFQahu2ae32q4Ia6v82UAR9CwoIMaSwFz2jxfs68leoOGykG ljg2fbSA4X9jElNoZNo9UlgpXC1gi+5LaBLREFq4WVbg38WBPv25NwZkFzjDHt2rMelQOe HvVSUYOzbFTduUX2wzF2WD54yFV+MJfieR/TVzlqGs0orzp3FeAMgiyMQmO3qMzCJL+cEd 9gWdfABggE6reYDTQkcnDHg2vII1pbl3Pn7aNigY3lkq0Z+RvKF5qqR1Sl3wTBfLjU5LZQ ene6hOVjPFreuStAO6cE5K5+IaK3ZA7yGBIe4yI61rmIzjS9+3RP7nTRU5Fkew== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1729853853; 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=4ckN3By33osOOhRu/7ilSfmb+7G76g/geNYlu+/gEoU=; b=iSH4i65FcFCuVT0n3G4AJF/yOrpOrN1FJILpJmGqTbok/MwMA5aGA1X8CtHEqlKb8PmAQr z+/WaDVZX28OoLDw== 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 , Rengarajan S , Peter Collingbourne , Serge Semin , Lino Sanfilippo Subject: [PATCH tty-next v3 6/6] serial: 8250: Revert "drop lockdep annotation from serial8250_clear_IER()" Date: Fri, 25 Oct 2024 13:03:28 +0206 Message-Id: <20241025105728.602310-7-john.ogness@linutronix.de> In-Reply-To: <20241025105728.602310-1-john.ogness@linutronix.de> References: <20241025105728.602310-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 Reviewed-by: Petr Mladek --- 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 0b3596fab061..5c8778ec30a3 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -706,6 +706,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); }