FAILED: patch "[PATCH] serial: sc16is7xx: remove useless enable of enhanced features" failed to apply to 6.1-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x 1c05bf6c0262f946571a37678250193e46b1ff0f
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2025102739-fable-reroute-e6a6@gregkh' --subject-prefix 'PATCH 6.1.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 1c05bf6c0262f946571a37678250193e46b1ff0f Mon Sep 17 00:00:00 2001
From: Hugo Villeneuve <[email protected]>
Date: Mon, 6 Oct 2025 10:20:02 -0400
Subject: [PATCH] serial: sc16is7xx: remove useless enable of enhanced features
Commit 43c51bb573aa ("sc16is7xx: make sure device is in suspend once probed") permanently enabled access to the enhanced features in sc16is7xx_probe(), and it is never disabled after that.
Therefore, remove re-enable of enhanced features in sc16is7xx_set_baud(). This eliminates a potential useless read + write cycle each time the baud rate is reconfigured.
drivers/tty/serial/sc16is7xx.c +0 -7
@@ -588,13 +588,6 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud) div /= prescaler; } -/* Enable enhanced features */ -sc16is7xx_efr_lock (port); -sc16is7xx_port_update (port,SC16IS7XX_EFR_REG , -SC16IS7XX_EFR_ENABLE_BIT , -SC16IS7XX_EFR_ENABLE_BIT ); -sc16is7xx_efr_unlock (port); -/* If bit MCR_CLKSEL is set, the divide by 4 prescaler is activated. */ sc16is7xx_port_update(port, SC16IS7XX_MCR_REG, SC16IS7XX_MCR_CLKSEL_BIT,
Sasha Levin
maintainerPATCH 1/4 serial: sc16is7xx: remove unused to_sc16is7xx_port macro
From: Hugo Villeneuve <[email protected]>
[ Upstream commit 22a048b0749346b6e3291892d06b95278d5ba84a ]
This macro is not used anywhere.
Stable-dep-of: 1c05bf6c0262 ("serial: sc16is7xx: remove useless enable of enhanced features")
--- drivers/tty/serial/sc16is7xx.c | 1 - 1 file changed, 1 deletion(-)
drivers/tty/serial/sc16is7xx.c +0 -1
@@ -358,7 +358,6 @@ static struct uart_driver sc16is7xx_uart = {static void sc16is7xx_ier_set (struct uart_port *port,u8 bit);static void sc16is7xx_stop_tx (struct uart_port *port); -#define to_sc16is7xx_port (p,e) ((container_of((p), struct sc16is7xx_port, e)))#define to_sc16is7xx_one (p,e) ((container_of((p), struct sc16is7xx_one, e)))static u8 sc16is7xx_port_read (struct uart_port *port,u8 reg)
Signature · 1 line
2.51.0
Sasha Levin
maintainerPATCH 2/4 serial: sc16is7xx: reorder code to remove prototype declarations
From: Hugo Villeneuve <[email protected]>
[ Upstream commit 2de8a1b46756b5a79d8447f99afdfe49e914225a ]
Move/reorder some functions to remove sc16is7xx_ier_set() and sc16is7xx_stop_tx() prototypes declarations.
No functional change.
sc16is7xx_ier_set() was introduced in
commit cc4c1d05eb10 ("sc16is7xx: Properly resume TX after stop").
Stable-dep-of: 1c05bf6c0262 ("serial: sc16is7xx: remove useless enable of enhanced features")
--- drivers/tty/serial/sc16is7xx.c | 75 ++++++++++++++++------------------ 1 file changed, 36 insertions(+), 39 deletions(-)
drivers/tty/serial/sc16is7xx.c +36 -39
@@ -355,9 +355,6 @@ static struct uart_driver sc16is7xx_uart = { .nr = SC16IS7XX_MAX_DEVS, }; -static void sc16is7xx_ier_set (struct uart_port *port,u8 bit); -static void sc16is7xx_stop_tx (struct uart_port *port); -#define to_sc16is7xx_one (p,e) ((container_of((p), struct sc16is7xx_one, e)))static u8 sc16is7xx_port_read (struct uart_port *port,u8 reg)
@@ -415,6 +412,42 @@ static void sc16is7xx_power(struct uart_port *port, int on) on ? 0 : SC16IS7XX_IER_SLEEP_BIT); } +static void sc16is7xx_ier_clear (struct uart_port *port,u8 bit) +{ +struct sc16is7xx_port *s =dev_get_drvdata (port->dev); +struct sc16is7xx_one *one =to_sc16is7xx_one (port, port); + +lockdep_assert_held_once (&port->lock); + + one->config.flags |=SC16IS7XX_RECONF_IER ; + one->config.ier_mask |= bit; + one->config.ier_val &= ~bit; +kthread_queue_work (&s->kworker, &one->reg_work); +} + +static void sc16is7xx_ier_set (struct uart_port *port,u8 bit) +{ +struct sc16is7xx_port *s =dev_get_drvdata (port->dev); +struct sc16is7xx_one *one =to_sc16is7xx_one (port, port); + +lockdep_assert_held_once (&port->lock); + + one->config.flags |=SC16IS7XX_RECONF_IER ; + one->config.ier_mask |= bit; + one->config.ier_val |= bit; +kthread_queue_work (&s->kworker, &one->reg_work); +} + +static void sc16is7xx_stop_tx (struct uart_port *port) +{ +sc16is7xx_ier_clear (port,SC16IS7XX_IER_THRI_BIT ); +} + +static void sc16is7xx_stop_rx (struct uart_port *port) +{ +sc16is7xx_ier_clear (port,SC16IS7XX_IER_RDI_BIT ); +} +static const struct sc16is7xx_devtype sc16is74x_devtype = { .name ="SC16IS74X" , .nr_gpio =0 ,
@@ -891,42 +924,6 @@ static void sc16is7xx_reg_proc(struct kthread_work *ws)sc16is7xx_reconf_rs485 (&one->port); } -static void sc16is7xx_ier_clear (struct uart_port *port,u8 bit) -{ -struct sc16is7xx_port *s =dev_get_drvdata (port->dev); -struct sc16is7xx_one *one =to_sc16is7xx_one (port, port); - -lockdep_assert_held_once (&port->lock); - - one->config.flags |=SC16IS7XX_RECONF_IER ; - one->config.ier_mask |= bit; - one->config.ier_val &= ~bit; -kthread_queue_work (&s->kworker, &one->reg_work); -} - -static void sc16is7xx_ier_set (struct uart_port *port,u8 bit) -{ -struct sc16is7xx_port *s =dev_get_drvdata (port->dev); -struct sc16is7xx_one *one =to_sc16is7xx_one (port, port); - -lockdep_assert_held_once (&port->lock); - - one->config.flags |=SC16IS7XX_RECONF_IER ; - one->config.ier_mask |= bit; - one->config.ier_val |= bit; -kthread_queue_work (&s->kworker, &one->reg_work); -} - -static void sc16is7xx_stop_tx (struct uart_port *port) -{ -sc16is7xx_ier_clear (port,SC16IS7XX_IER_THRI_BIT ); -} - -static void sc16is7xx_stop_rx (struct uart_port *port) -{ -sc16is7xx_ier_clear (port,SC16IS7XX_IER_RDI_BIT ); -} -static void sc16is7xx_ms_proc (struct kthread_work *ws) {struct sc16is7xx_one *one =to_sc16is7xx_one (ws, ms_work.work);
Signature · 1 line
2.51.0
Sasha Levin
maintainerPATCH 3/4 serial: sc16is7xx: refactor EFR lock
In reply to Sasha LevinFrom: Hugo Villeneuve <[email protected]>
[ Upstream commit 0c84bea0cabc4e2b98a3de88eeb4ff798931f056 ]
Move common code for EFR lock/unlock of mutex into functions for code reuse and clarity.
With the addition of old_lcr, move irda_mode within struct sc16is7xx_one to reduce memory usage:
Before: /* size: 752, cachelines: 12, members: 10 */
After: /* size: 744, cachelines: 12, members: 10 */Stable-dep-of: 1c05bf6c0262 ("serial: sc16is7xx: remove useless enable of enhanced features")
--- drivers/tty/serial/sc16is7xx.c | 106 ++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 49 deletions(-)
drivers/tty/serial/sc16is7xx.c +57 -49
@@ -329,8 +329,9 @@ struct sc16is7xx_one {struct kthread_work reg_work;struct kthread_delayed_work ms_work;struct sc16is7xx_one_config config; -bool irda_mode;unsigned int old_mctrl; +u8 old_lcr;/* Value before EFR access. */ +bool irda_mode; };struct sc16is7xx_port {
@@ -412,6 +413,49 @@ static void sc16is7xx_power(struct uart_port *port, int on) on ? 0 : SC16IS7XX_IER_SLEEP_BIT); } +/* +* In an amazing feat of design, the Enhanced Features Register (EFR) +* shares the address of the Interrupt Identification Register (IIR). +* Access to EFR is switched on by writing a magic value (0xbf) to the +* Line Control Register (LCR). Any interrupt firing during this time will +* see the EFR where it expects the IIR to be, leading to +* "Unexpected interrupt" messages. +* +* Prevent this possibility by claiming a mutex while accessing the EFR, +* and claiming the same mutex from within the interrupt handler. This is +* similar to disabling the interrupt, but that doesn't work because the +* bulk of the interrupt processing is run as a workqueue job in thread +* context. +*/ +static void sc16is7xx_efr_lock (struct uart_port *port) +{ +struct sc16is7xx_one *one =to_sc16is7xx_one (port, port); + +mutex_lock (&one->efr_lock); + +/* Backup content of LCR. */ + one->old_lcr =sc16is7xx_port_read (port,SC16IS7XX_LCR_REG ); + +/* Enable access to Enhanced register set */ +sc16is7xx_port_write (port,SC16IS7XX_LCR_REG ,SC16IS7XX_LCR_CONF_MODE_B ); + +/* Disable cache updates when writing to EFR registers */ +regcache_cache_bypass (one->regmap, true); +} + +static void sc16is7xx_efr_unlock (struct uart_port *port) +{ +struct sc16is7xx_one *one =to_sc16is7xx_one (port, port); + +/* Re-enable cache updates when writing to normal registers */ +regcache_cache_bypass (one->regmap, false); + +/* Restore original content of LCR */ +sc16is7xx_port_write (port,SC16IS7XX_LCR_REG , one->old_lcr); + +mutex_unlock (&one->efr_lock); +} +static void sc16is7xx_ier_clear (struct uart_port *port,u8 bit) {struct sc16is7xx_port *s =dev_get_drvdata (port->dev);
@@ -538,39 +582,12 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud) div /= prescaler; } -/* In an amazing feat of design, the Enhanced Features Register shares -* the address of the Interrupt Identification Register, and is -* switched in by writing a magic value (0xbf) to the Line Control -* Register. Any interrupt firing during this time will see the EFR -* where it expects the IIR to be, leading to "Unexpected interrupt" -* messages. -* -* Prevent this possibility by claiming a mutex while accessing the -* EFR, and claiming the same mutex from within the interrupt handler. -* This is similar to disabling the interrupt, but that doesn't work -* because the bulk of the interrupt processing is run as a workqueue -* job in thread context. -*/ -mutex_lock (&one->efr_lock); - - lcr =sc16is7xx_port_read (port,SC16IS7XX_LCR_REG ); - -/* Open the LCR divisors for configuration */ -sc16is7xx_port_write (port,SC16IS7XX_LCR_REG , -SC16IS7XX_LCR_CONF_MODE_B ); -/* Enable enhanced features */ -regcache_cache_bypass (one->regmap, true); +sc16is7xx_efr_lock (port);sc16is7xx_port_update (port,SC16IS7XX_EFR_REG ,SC16IS7XX_EFR_ENABLE_BIT ,SC16IS7XX_EFR_ENABLE_BIT ); - -regcache_cache_bypass (one->regmap, false); - -/* Put LCR back to the normal mode */ -sc16is7xx_port_write (port,SC16IS7XX_LCR_REG , lcr); - -mutex_unlock (&one->efr_lock); +sc16is7xx_efr_unlock (port);/* If bit MCR_CLKSEL is set, the divide by 4 prescaler is activated. */ sc16is7xx_port_update(port, SC16IS7XX_MCR_REG,
@@ -580,7 +597,8 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)mutex_lock (&one->efr_lock); -/* Open the LCR divisors for configuration */ +/* Backup LCR and access special register set (DLL/DLH) */ + lcr =sc16is7xx_port_read (port,SC16IS7XX_LCR_REG );sc16is7xx_port_write (port,SC16IS7XX_LCR_REG ,SC16IS7XX_LCR_CONF_MODE_A );
@@ -590,7 +608,7 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)sc16is7xx_port_write (port,SC16IS7XX_DLL_REG , div %256 );regcache_cache_bypass (one->regmap, false); -/* Put LCR back to the normal mode */ +/* Restore LCR and access to general register set */ sc16is7xx_port_write (port,SC16IS7XX_LCR_REG , lcr);mutex_unlock (&one->efr_lock);
@@ -1073,17 +1091,7 @@ static void sc16is7xx_set_termios(struct uart_port *port,if (!(termios->c_cflag &CREAD )) port->ignore_status_mask |=SC16IS7XX_LSR_BRK_ERROR_MASK ; -/* As above, claim the mutex while accessing the EFR. */ -mutex_lock (&one->efr_lock); - -sc16is7xx_port_write (port,SC16IS7XX_LCR_REG , -SC16IS7XX_LCR_CONF_MODE_B ); -/* Configure flow control */ -regcache_cache_bypass (one->regmap, true); -sc16is7xx_port_write (port,SC16IS7XX_XON1_REG , termios->c_cc[VSTART ]); -sc16is7xx_port_write (port,SC16IS7XX_XOFF1_REG , termios->c_cc[VSTOP ]); - port->status &= ~(UPSTAT_AUTOCTS |UPSTAT_AUTORTS );if (termios->c_cflag &CRTSCTS ) { flow |= SC16IS7XX_EFR_AUTOCTS_BIT |
@@ -1095,16 +1103,16 @@ static void sc16is7xx_set_termios(struct uart_port *port,if (termios->c_iflag &IXOFF ) flow |=SC16IS7XX_EFR_SWFLOW1_BIT ; -sc16is7xx_port_update (port, -SC16IS7XX_EFR_REG , -SC16IS7XX_EFR_FLOWCTRL_BITS , - flow); -regcache_cache_bypass (one->regmap, false); -/* Update LCR register */ sc16is7xx_port_write (port,SC16IS7XX_LCR_REG , lcr); -mutex_unlock (&one->efr_lock); +/* Update EFR registers */ +sc16is7xx_efr_lock (port); +sc16is7xx_port_write (port,SC16IS7XX_XON1_REG , termios->c_cc[VSTART ]); +sc16is7xx_port_write (port,SC16IS7XX_XOFF1_REG , termios->c_cc[VSTOP ]); +sc16is7xx_port_update (port,SC16IS7XX_EFR_REG , +SC16IS7XX_EFR_FLOWCTRL_BITS , flow); +sc16is7xx_efr_unlock (port);/* Get baud rate generator configuration */ baud = uart_get_baud_rate(port, termios, old,
Signature · 1 line
2.51.0
Sasha Levin
maintainerPATCH 4/4 serial: sc16is7xx: remove useless enable of enhanced features
In reply to Sasha LevinFrom: Hugo Villeneuve <[email protected]>
[ Upstream commit 1c05bf6c0262f946571a37678250193e46b1ff0f ]
Commit 43c51bb573aa ("sc16is7xx: make sure device is in suspend once probed") permanently enabled access to the enhanced features in sc16is7xx_probe(), and it is never disabled after that.
Therefore, remove re-enable of enhanced features in sc16is7xx_set_baud(). This eliminates a potential useless read + write cycle each time the baud rate is reconfigured.
--- drivers/tty/serial/sc16is7xx.c | 7 ------- 1 file changed, 7 deletions(-)
drivers/tty/serial/sc16is7xx.c +0 -7
@@ -582,13 +582,6 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud) div /= prescaler; } -/* Enable enhanced features */ -sc16is7xx_efr_lock (port); -sc16is7xx_port_update (port,SC16IS7XX_EFR_REG , -SC16IS7XX_EFR_ENABLE_BIT , -SC16IS7XX_EFR_ENABLE_BIT ); -sc16is7xx_efr_unlock (port); -/* If bit MCR_CLKSEL is set, the divide by 4 prescaler is activated. */ sc16is7xx_port_update(port, SC16IS7XX_MCR_REG, SC16IS7XX_MCR_CLKSEL_BIT,
Signature · 1 line
2.51.0