From patchwork Fri Sep 13 14:05:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 828596 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 8153743144; Fri, 13 Sep 2024 14:05:42 +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=1726236344; cv=none; b=cqDFoGbKB5rjuDxuI2Qb7PD7cmalx4BLbWxjTk2QBz7AiRvirg/MWFaps9UQUlG4nT5I7I0Jq43xXX1iZmOMLUANakcZ2mRXY8f7hsvKB+Syhuw30NghaRkBBB4vfQ24BjvDBADDViopMUeEoxoG/DgxIoRv+8nCzwXXDvSfbxs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726236344; c=relaxed/simple; bh=S5uPkoT9yo7idV+N+2sbJKMsKlKO8GaUe/m9ysT6lvY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=cYVlZofsl4CTa1bH983p+cOQ2Y7DoE8/EqHhWHJ3zJ5qFOXIkf+V/aNl4UYgl4uEd3fi7d8Tt9a+wtD34Z2dedx7vO2V9gw7Fm2FqI6tPJlMgjrnUcDR/PYFBYPnyECzuMxNByJmH7ve6MnVVqer7MnGnkpTE5HKWeSa0UhPgO4= 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=YO3EBjdY; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=9lYq6idM; 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="YO3EBjdY"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="9lYq6idM" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1726236340; 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=rYB7nNBL+zvMdCuk+woBwavomuKxjvWKg5JZQriJJBA=; b=YO3EBjdYG4KJDNN/HlxajsvfsOdF47cI4yzlWKG4VIQk/MOQeoxB/PmtwiLv2UPaEBWyp3 kTWVt4gMPR0NNgH4kwv2RAMD9JqfmjQn2R6O5xAu1mUj9yFflzeUww13cAzsh7JcvonWBj Z+fDESke4Q1YRVuPdQc8jvl4/8k/+TUtWbNN4AH07rGIbHYprSxtCpHkWTpMUvTaTtKy5V bq28tRbq4eVt8J4rWwjLW3A1M2qRUPysEB/4Jw12hsNY2WmNpdBwGdsWlKpfieApUZr1oB LJ99D8lW+/p/tjhBFF1k/M3QVjcVF7zfk0BPWOkZa+UCqLTvNQ193EqCI7bNhg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1726236340; 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=rYB7nNBL+zvMdCuk+woBwavomuKxjvWKg5JZQriJJBA=; b=9lYq6idML3UQwt4B0sMBRzIpLEgcec9pkloDjQkY0Sr+qc6p2zOPyDTfsSZcXzy9WsgIL5 r92mMqE95aCvLPAg== 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 , Sunil V L , Arnd Bergmann , Florian Fainelli , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Lino Sanfilippo , Rengarajan S , Serge Semin Subject: [PATCH next v2 1/4] serial: 8250: Split out IER from rs485_start_tx() Date: Fri, 13 Sep 2024 16:11:35 +0206 Message-Id: <20240913140538.221708-2-john.ogness@linutronix.de> In-Reply-To: <20240913140538.221708-1-john.ogness@linutronix.de> References: <20240913140538.221708-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 Move IER handling out of rs485_start_tx() callback and into a new wrapper serial8250_rs485_start_tx(). Replace all callback call sites with wrapper, except for the console write() callback, where it is inappropriate to modify IER. Signed-off-by: John Ogness --- drivers/tty/serial/8250/8250.h | 2 ++ drivers/tty/serial/8250/8250_port.c | 27 +++++++++++++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index e5310c65cf52..6e90223ba1d6 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -236,6 +236,8 @@ void serial8250_em485_stop_tx(struct uart_8250_port *p); void serial8250_em485_destroy(struct uart_8250_port *p); extern struct serial_rs485 serial8250_em485_supported; +void serial8250_rs485_start_tx(struct uart_8250_port *up); + /* MCR <-> TIOCM conversion */ static inline int serial8250_TIOCM_to_MCR(int tiocm) { diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 2786918aea98..ba8d9cefc451 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1370,7 +1370,6 @@ static void serial8250_stop_rx(struct uart_port *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_rpm_put(up); @@ -1543,16 +1542,20 @@ static inline void __start_tx(struct uart_port *port) * * 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. - * (Some chips use inverse semantics.) Further assumes that reception is - * 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.) + * (Some chips use inverse semantics.) + * It does not disable RX interrupts. Use the wrapper function + * serial8250_rs485_start_tx() if that is also needed. */ void serial8250_em485_start_tx(struct uart_8250_port *up) { unsigned char mcr = serial8250_in_MCR(up); + /* + * Some chips set the UART_LSR_DR bit even when UART_IER_RDI is + * disabled, so explicitly mask it. + */ if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) - serial8250_stop_rx(&up->port); + up->port.read_status_mask &= ~UART_LSR_DR; if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND) mcr |= UART_MCR_RTS; @@ -1562,6 +1565,18 @@ void serial8250_em485_start_tx(struct uart_8250_port *up) } EXPORT_SYMBOL_GPL(serial8250_em485_start_tx); +/** + * serial8250_rs485_start_tx() - stop rs485 reception, enable transmission + * @up: uart 8250 port + */ +void serial8250_rs485_start_tx(struct uart_8250_port *up) +{ + if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) + serial8250_stop_rx(&up->port); + + up->rs485_start_tx(up); +} + /* Returns false, if start_tx_timer was setup to defer TX start */ static bool start_tx_rs485(struct uart_port *port) { @@ -1585,7 +1600,7 @@ static bool start_tx_rs485(struct uart_port *port) if (em485->tx_stopped) { em485->tx_stopped = false; - up->rs485_start_tx(up); + serial8250_rs485_start_tx(up); if (up->port.rs485.delay_rts_before_send > 0) { em485->active_timer = &em485->start_tx_timer; From patchwork Fri Sep 13 14:05:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 828595 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 4B3F61DB94E; Fri, 13 Sep 2024 14:05:43 +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=1726236346; cv=none; b=vFEhKOxefOHw/KQ2BFk3Bb9g5iZy7Fvz1RfkHFQnW3Y0mCI7XBqXnL2tMG/XQivzyXG2y8niWAI2JE8xtwBqkjRIPkEJcWG3BpA/Pbjcb/ACjRSw5V261QX0sCVSQIKZ1Um+E+lnCt7ldqww/52Phjs5k7r3JkU8ad+/RWbabh4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726236346; c=relaxed/simple; bh=vy7FDh7ONPzOVel+4x+VAurMui0tfYqeBSQf9+QBcAY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ARNPjjz2hHsHSwsBNfANJ/QN5b+Bd4AAA7dThsWWz8rCXnHhnkpPUKYyUnSZqHEE+lUfsYJZFY3LbYNgfVX/G9aJlMb7Dv/JuEeAoDzBCgengQyxgWJU1ybkErq6QdbDd/Obmwxb6037db5lCYjRMnjSIdP5BJgNPbO2UFby6RM= 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=UG6Uips7; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=4oR+/q8L; 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="UG6Uips7"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="4oR+/q8L" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1726236341; 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=eiGBWq4TbC9YpmLgN+63GvyKHjjpCb6BuHISr4eHJzI=; b=UG6Uips7GTBkxyDY8+Zxbbs4P7EyaDAY+9RSA14yZLfMXnsYHcJxqpqzoaFYEwi8Tuishe clnrMfSRP00rjN9i7g9btJOJeQo2XcyJZd7RnauLpr0Ntm+33Gvf6/vKzGxK9ndGxso7c8 KZ1LDnwXF0z/1QOKHzcGEQ9VBLGZQ/x6/dJIaX3RHXTDhoCr4Fsp4J/l0kEA1fDV9Swxap idDjB9sQKDKl+Wgpv7II0Rf620NAvs2LNl9adWjFHCtQ4cGgn0vUzC374DcRODOjeeAzny ydfrE/o5A3C+77CwfJ9QchKOG4cuO8qdD70g+bY8vRcf9iE2sJOHE4Y3W7Ia/g== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1726236341; 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=eiGBWq4TbC9YpmLgN+63GvyKHjjpCb6BuHISr4eHJzI=; b=4oR+/q8Llb+SI0hdGq9ERbrJTbkx5KIrm9eRoX9o9AyxahXkVSunySR9CWIjnIJlaLK6pI zX9jd95UAiniQODQ== 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 , "Paul E. McKenney" , Sunil V L , Arnd Bergmann , Tony Lindgren , Udit Kumar , Ronald Wahl , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Thomas Richard , Griffin Kroah-Hartman , Florian Fainelli , Rengarajan S , Serge Semin Subject: [PATCH next v2 2/4] serial: 8250: Split out IER from rs485_stop_tx() Date: Fri, 13 Sep 2024 16:11:36 +0206 Message-Id: <20240913140538.221708-3-john.ogness@linutronix.de> In-Reply-To: <20240913140538.221708-1-john.ogness@linutronix.de> References: <20240913140538.221708-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 Move IER handling out of rs485_stop_tx() callback and into a new wrapper serial8250_rs485_stop_tx(). Replace all callback call sites with wrapper, except for the console write() callback, where it is inappropriate to modify IER. Signed-off-by: John Ogness --- drivers/tty/serial/8250/8250.h | 1 + drivers/tty/serial/8250/8250_omap.c | 2 +- drivers/tty/serial/8250/8250_port.c | 30 ++++++++++++++++++++--------- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 6e90223ba1d6..b1e4b5fef8cc 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -237,6 +237,7 @@ void serial8250_em485_destroy(struct uart_8250_port *p); extern struct serial_rs485 serial8250_em485_supported; void serial8250_rs485_start_tx(struct uart_8250_port *up); +void serial8250_rs485_stop_tx(struct uart_8250_port *p); /* MCR <-> TIOCM conversion */ static inline int serial8250_TIOCM_to_MCR(int tiocm) diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index afef1dd4ddf4..2b62d49a935d 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -366,7 +366,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_rs485_stop_tx(up); } /* diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index ba8d9cefc451..7ee74ec944d2 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); + serial8250_rs485_stop_tx(p); return 0; } @@ -1380,14 +1380,13 @@ static void serial8250_stop_rx(struct uart_port *port) * @p: uart 8250 port * * Generic callback usable by 8250 uart drivers to stop rs485 transmission. + * It does not restore RX interrupts. Use the wrapper function + * serial8250_rs485_stop_tx() if that is also needed. */ 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 @@ -1397,16 +1396,29 @@ void serial8250_em485_stop_tx(struct uart_8250_port *p) /* * Empty the RX FIFO, we are not interested in anything * received during the half-duplex transmission. - * Enable previously disabled RX interrupts. */ - if (!(p->port.rs485.flags & SER_RS485_RX_DURING_TX)) { + if (!(p->port.rs485.flags & SER_RS485_RX_DURING_TX)) serial8250_clear_and_reinit_fifos(p); +} +EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx); + +/** + * serial8250_rs485_stop_tx() - stop rs485 transmission, restore RX interrupts + * @p: uart 8250 port + */ +void serial8250_rs485_stop_tx(struct uart_8250_port *p) +{ + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&p->port.lock); + + p->rs485_stop_tx(p); + /* Enable previously disabled RX interrupts. */ + if (!(p->port.rs485.flags & SER_RS485_RX_DURING_TX)) { p->ier |= UART_IER_RLSI | UART_IER_RDI; serial_port_out(&p->port, UART_IER, p->ier); } } -EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx); static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t) { @@ -1418,7 +1430,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); + serial8250_rs485_stop_tx(p); em485->active_timer = NULL; em485->tx_stopped = true; } @@ -1450,7 +1462,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); + serial8250_rs485_stop_tx(p); em485->active_timer = NULL; em485->tx_stopped = true; } From patchwork Fri Sep 13 14:05:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 828939 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 ABABD1DB95B; Fri, 13 Sep 2024 14:05:44 +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=1726236346; cv=none; b=I7AAyZ0RT6g+t7zD8myI+QYeV3ywS9Quq0GBpVftwFCO8ebss70JYYJyAHOPfzLESWD/N+3zNdAbUaRK8VXxz1k40X3Hd7fkm8vDgqABe7CA9N5xzOOMEmnFD5O+pHu4gIPRytPSr48Akr9XdbjCUDLe8Z9igtKaseexphYV75I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726236346; c=relaxed/simple; bh=Z4P8fplRtRJxbblPa1IezvMhKSCwBWjB0dsIGXU/7MY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=NRUJ138/l3xb2Gj7tnHJFtT6p+2CoQ2df/gnMlSLCrVp0xEOwqXZSJ8KOuMCdJNmkx+FbCFktAX8Dv+OVWm4p/RCGGV6DAAdvx7pXC373MdTtQQrqdfPPNgK5moRBKwno87IL8poVGs/cnydagAdsuVeNvJD7G5zE2sQqXV4W94= 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=NeCuqiOV; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=nROeLSSr; 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="NeCuqiOV"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="nROeLSSr" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1726236342; 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=W2qJgL7jg1r93GblbWHh8/o4/Jb12CtOJKsX7tOR3Bc=; b=NeCuqiOVND4UnhKFpsa1AgkLYbVfOSefh4BLd2tEJ6bOXBOkqoP1/j3J44eOJFq44/5UfM +zyvBSgyOZUb+KxGr/32trqsmbZvW3skCAkoaS07l48lfFMgYSqQNPgPZvEkaR6x2bhbFn vpksO1tksRWZKItTriqIbQMp2MKf2UQlgwU5aDQNYZoMLbiJ1wxY3tT8gNjcsYujtO8Ovy sTQkcnwxjaTTWuVjOCsUFevsmfFSZwDrj3oxz4Z0YVegqs0gj1pkAr+JBcMgHof0KQ6THx kfggRwItfDeEFJ8Gv6BmiZ6P2+GDnKgUokhpRnFYlTQ7RAV9elopeQ/PVIdVLQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1726236342; 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=W2qJgL7jg1r93GblbWHh8/o4/Jb12CtOJKsX7tOR3Bc=; b=nROeLSSrUbe8oNFFUkX9fFEEURLg7Lfi8keZGvr/Gju+haqhbWDlK+z4wLpKAYC8wO8FAl cDyXia57DzkcUZDg== 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 , Tony Lindgren , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , =?utf-8?q?U?= =?utf-8?q?we_Kleine-K=C3=B6nig?= , Arnd Bergmann , Florian Fainelli , Serge Semin , Wolfram Sang , Lino Sanfilippo Subject: [PATCH next v2 3/4] serial: 8250: Switch to nbcon console Date: Fri, 13 Sep 2024 16:11:37 +0206 Message-Id: <20240913140538.221708-4-john.ogness@linutronix.de> In-Reply-To: <20240913140538.221708-1-john.ogness@linutronix.de> References: <20240913140538.221708-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_thread() callback allows safe handover/takeover per byte. The write_atomic() callback allows safe handover/takeover per printk record and adds a preceding newline if it took 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 | 188 +++++++++++++++++----------- include/linux/serial_8250.h | 9 +- 3 files changed, 151 insertions(+), 81 deletions(-) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 5f9f06911795..2d690ff32a32 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_atomic(up, wctxt); +} + +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_thread(up, wctxt); +} + +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 7ee74ec944d2..d58a0fa95e3b 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. @@ -1864,6 +1874,8 @@ unsigned int serial8250_modem_status(struct uart_8250_port *up) struct uart_port *port = &up->port; unsigned int status = serial_in(up, UART_MSR); + lockdep_assert_held_once(&port->lock); + status |= up->msr_saved_flags; up->msr_saved_flags = 0; if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI && @@ -1884,6 +1896,21 @@ unsigned int serial8250_modem_status(struct uart_8250_port *up) } EXPORT_SYMBOL_GPL(serial8250_modem_status); +/* + * 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); +} + static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) { switch (iir & 0x3f) { @@ -3296,6 +3323,11 @@ static void serial8250_console_putchar(struct uart_port *port, unsigned char ch) wait_for_xmitr(up, UART_LSR_THRE); serial_port_out(port, UART_TX, ch); + + if (ch == '\n') + up->console_line_ended = true; + else + up->console_line_ended = false; } /* @@ -3324,65 +3356,68 @@ static void serial8250_console_restore(struct uart_8250_port *up) serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS); } -/* - * Print a string to the serial port using the device FIFO - * - * It sends fifosize bytes and then waits for the fifo - * to get empty. - */ -static void serial8250_console_fifo_write(struct uart_8250_port *up, - const char *s, unsigned int count) +static void __serial8250_console_write_thread(struct uart_8250_port *up, + struct nbcon_write_context *wctxt) { - int i; - const char *end = s + count; - unsigned int fifosize = up->tx_loadsz; - bool cr_sent = false; - - while (s != end) { - wait_for_lsr(up, UART_LSR_THRE); - - for (i = 0; i < fifosize && s != end; ++i) { - if (*s == '\n' && !cr_sent) { - serial_out(up, UART_TX, '\r'); - cr_sent = true; - } else { - serial_out(up, UART_TX, *s++); - cr_sent = false; - } + unsigned int len = READ_ONCE(wctxt->len); + struct uart_port *port = &up->port; + unsigned int i; + + if (nbcon_exit_unsafe(wctxt)) { + /* + * 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. + */ + for (i = 0; i < len; i++) { + if (!nbcon_enter_unsafe(wctxt)) + break; + + uart_console_write(port, wctxt->outbuf + i, 1, serial8250_console_putchar); + + if (!nbcon_exit_unsafe(wctxt)) + break; } } + + /* + * 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); } -/* - * 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. - */ -void serial8250_console_write(struct uart_8250_port *up, const char *s, - unsigned int count) +static void __serial8250_console_write_atomic(struct uart_8250_port *up, + struct nbcon_write_context *wctxt) { - 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(); + if (!up->console_line_ended) + uart_console_write(port, "\n", 1, serial8250_console_putchar); + uart_console_write(port, wctxt->outbuf, wctxt->len, serial8250_console_putchar); +} - if (oops_in_progress) - locked = uart_port_trylock_irqsave(port, &flags); - else - uart_port_lock_irqsave(port, &flags); +static 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 int ier; + + 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))) { @@ -3396,30 +3431,10 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, mdelay(port->rs485.delay_rts_before_send); } - use_fifo = (up->capabilities & UART_CAP_FIFO) && - /* - * BCM283x requires to check the fifo - * after each byte. - */ - !(up->capabilities & UART_CAP_MINI) && - /* - * tx_loadsz contains the transmit fifo size - */ - up->tx_loadsz > 1 && - (up->fcr & UART_FCR_ENABLE_FIFO) && - port->state && - test_bit(TTY_PORT_INITIALIZED, &port->state->port.iflags) && - /* - * After we put a data in the fifo, the controller will send - * it regardless of the CTS state. Therefore, only use fifo - * if we don't use control flow. - */ - !(up->port.flags & UPF_CONS_FLOW); - - if (likely(use_fifo)) - serial8250_console_fifo_write(up, s, count); + if (is_atomic) + __serial8250_console_write_atomic(up, wctxt); else - uart_console_write(port, s, count, serial8250_console_putchar); + __serial8250_console_write_thread(up, wctxt); /* * Finally, wait for transmitter to become empty @@ -3442,11 +3457,32 @@ 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); +} + +void serial8250_console_write_thread(struct uart_8250_port *up, + struct nbcon_write_context *wctxt) +{ + serial8250_console_write(up, wctxt, false); +} + +void serial8250_console_write_atomic(struct uart_8250_port *up, + struct nbcon_write_context *wctxt) +{ + touch_nmi_watchdog(); + + serial8250_console_write(up, wctxt, true); } static unsigned int probe_baud(struct uart_port *port) @@ -3466,6 +3502,7 @@ static unsigned int probe_baud(struct uart_port *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'; @@ -3475,6 +3512,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 fd59ed2cca53..75c1f93fec73 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,10 @@ 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_atomic(struct uart_8250_port *up, + struct nbcon_write_context *wctxt); +void serial8250_console_write_thread(struct uart_8250_port *up, + struct nbcon_write_context *wctxt); int serial8250_console_setup(struct uart_port *port, char *options, bool probe); int serial8250_console_exit(struct uart_port *port); From patchwork Fri Sep 13 14:05:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 828594 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 923091DB94D; Fri, 13 Sep 2024 14:05:45 +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=1726236347; cv=none; b=gVjZZxVrVvh+Jp6z0wqmYVFErddTz0qfVC3Cky7jz5BAytOSTnLJ5EAo0+rYKTmOgEB76TNY5ynNsWIhF+zHLKD1XtD/sX1Mg/ktkw/fqqsDjJhX9yvKWKEGb0aEBL3aCIflhfigzKy03M9OFhtgle5DvAQG3nyQ8/kws/RKJfQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726236347; c=relaxed/simple; bh=qOLlB2ODIZHd9tadFjGmdop49h0yAytpCHar4CpvpYM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=sks8Ky7pAM/FT83zkBSjSZpkfe7jSLjkwO8fDUdPqUDCiMRuG2q2lP2JM8w7TLVSJVuthpsmyIxvJ7NhYFU77SK8s1GXa908UNblBvDNj+6WGebJH/j2AZVOQo33FtZeRkhv3yZdL9TmjQx5OOkT+wtwgJLtuer1I66zpMb30r4= 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=IFp1Ksdd; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=lPiu3/6x; 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="IFp1Ksdd"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="lPiu3/6x" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1726236343; 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=P8MmvbSxGrzA2amsSYnDkpZhNgQm94vpI9KV4RVr0co=; b=IFp1KsddfJeXyxTmgTnEHkZrw44Bgmp3mTutq06MHLiE3lyMlHOzyWLMlrDpwu3Cht4Puu 5fL9UMNfmfaz1GE6W9UxkDOSxU6yk9DlN46OX9N5rK6ljdxeBMOG7YYve1e36eXKUDF8Ex y+oNqP/NKHvnnVXjPFrfWTo0c+VH1eLb+IW7aSsdCuXcOexR4ILFnp3PioLCst0odPNmzq FqYOa7fcUdbwiLKFdvjz6i8j5V/KX4xJfO2DjfyWZA4qKc8VQY8o11SSs+KZFnwy8hyKbF YBOff2m6TqO9WvuvE+ZFcT6kyghVqf8mBeqX46KOOxWA84jL5fA9jO+QJ9mk9g== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1726236343; 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=P8MmvbSxGrzA2amsSYnDkpZhNgQm94vpI9KV4RVr0co=; b=lPiu3/6xN4ewvXHEFOrqhvILd/pCS0vHbt8IFr5rLywXuK6mKdOYcdceBBIQNlnH9DhrLF SlAG+xsowFGU6bDw== 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 , Florian Fainelli , Rengarajan S , Peter Collingbourne , Wolfram Sang , Serge Semin Subject: [PATCH next v2 4/4] serial: 8250: Revert "drop lockdep annotation from serial8250_clear_IER()" Date: Fri, 13 Sep 2024 16:11:38 +0206 Message-Id: <20240913140538.221708-5-john.ogness@linutronix.de> In-Reply-To: <20240913140538.221708-1-john.ogness@linutronix.de> References: <20240913140538.221708-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 d58a0fa95e3b..fdef0cd01b2d 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); }