FAILED: patch "[PATCH] serial: sc16is7xx: fix invalid sc16is7xx_lines bitfield in" failed to apply to 4.19-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.19-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-4.19.y
git checkout FETCH_HEAD
git cherry-pick -x 8a1060ce974919f2a79807527ad82ac39336eda2
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2024012653-unframed-creation-e7d8@gregkh' --subject-prefix 'PATCH 4.19.y' HEAD^..
Possible dependencies:
8a1060ce9749 ("serial: sc16is7xx: fix invalid sc16is7xx_lines bitfield in case of probe error") 4409df5866b7 ("serial: sc16is7xx: change EFR lock to operate on each channels") 41a308cbedb2 ("serial: sc16is7xx: remove unused line structure member") 3837a0379533 ("serial: sc16is7xx: improve regmap debugfs by using one regmap per port") b4a778303ea0 ("serial: sc16is7xx: add missing support for rs485 devicetree properties") 049994292834 ("serial: sc16is7xx: fix regression with GPIO configuration") dabc54a45711 ("serial: sc16is7xx: remove obsolete out_thread label") c8f71b49ee4d ("serial: sc16is7xx: setup GPIO controller later in probe") 267913ecf737 ("serial: sc16is7xx: Fill in rs485_supported")21144bab4f11 ("sc16is7xx: Handle modem status lines")cc4c1d05eb10 ("sc16is7xx: Properly resume TX after stop")d4ab5487cc77 ("Merge 5.17-rc6 into tty-next")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 8a1060ce974919f2a79807527ad82ac39336eda2 Mon Sep 17 00:00:00 2001
From: Hugo Villeneuve <[email protected]>
Date: Thu, 21 Dec 2023 18:18:08 -0500
Subject: [PATCH] serial: sc16is7xx: fix invalid sc16is7xx_lines bitfield in
case of probe error
If an error occurs during probing, the sc16is7xx_lines bitfield may be left in a state that doesn't represent the correct state of lines allocation.
For example, in a system with two SC16 devices, if an error occurs only during probing of channel (port) B of the second device, sc16is7xx_lines final state will be 00001011b instead of the expected 00000011b.
This is caused in part because of the "i--" in the for/loop located in the out_ports: error path.
Fix this by checking the return value of uart_add_one_port() and set line allocation bit only if this was successful. This allows the refactor of the obfuscated for(i--...) loop in the error path, and properly call uart_remove_one_port() only when needed, and properly unset line allocation bits.
Also use same mechanism in remove() when calling uart_remove_one_port().
drivers/tty/serial/sc16is7xx.c +18 -26
@@ -407,19 +407,6 @@ static void sc16is7xx_port_update(struct uart_port *port, u8 reg,regmap_update_bits (one->regmap, reg, mask, val); } -static int sc16is7xx_alloc_line (void ) -{ -int i; - -BUILD_BUG_ON (SC16IS7XX_MAX_DEVS >BITS_PER_LONG ); - -for (i =0 ; i <SC16IS7XX_MAX_DEVS ; i++) -if (!test_and_set_bit (i, &sc16is7xx_lines)) -break ; - -return i; -} -static void sc16is7xx_power (struct uart_port *port,int on) { sc16is7xx_port_update(port, SC16IS7XX_IER_REG,
@@ -1550,6 +1537,13 @@ static int sc16is7xx_probe(struct device *dev, SC16IS7XX_IOCONTROL_SRESET_BIT);for (i =0 ; i < devtype->nr_uart; ++i) { + s->p[i].port.line =find_first_zero_bit (&sc16is7xx_lines, +SC16IS7XX_MAX_DEVS ); +if (s->p[i].port.line >=SC16IS7XX_MAX_DEVS ) { + ret = -ERANGE ; + goto out_ports; + } +/* Initialize port data */ s->p[i].port.dev = dev; s->p[i].port.irq = irq;
@@ -1569,14 +1563,8 @@ static int sc16is7xx_probe(struct device *dev, s->p[i].port.rs485_supported = sc16is7xx_rs485_supported; s->p[i].port.ops = &sc16is7xx_ops; s->p[i].old_mctrl =0 ; - s->p[i].port.line =sc16is7xx_alloc_line (); s->p[i].regmap = regmaps[i]; -if (s->p[i].port.line >=SC16IS7XX_MAX_DEVS ) { - ret = -ENOMEM ; - goto out_ports; - } -mutex_init (&s->p[i].efr_lock); ret =uart_get_rs485_mode (&s->p[i].port);
@@ -1594,8 +1582,13 @@ static int sc16is7xx_probe(struct device *dev,kthread_init_work (&s->p[i].tx_work, sc16is7xx_tx_proc);kthread_init_work (&s->p[i].reg_work, sc16is7xx_reg_proc);kthread_init_delayed_work (&s->p[i].ms_work, sc16is7xx_ms_proc); +/* Register port */ -uart_add_one_port (&sc16is7xx_uart, &s->p[i].port); + ret =uart_add_one_port (&sc16is7xx_uart, &s->p[i].port); +if (ret) + goto out_ports; + +set_bit (s->p[i].port.line, &sc16is7xx_lines);/* Enable EFR */ sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_LCR_REG,
@@ -1653,10 +1646,9 @@ static int sc16is7xx_probe(struct device *dev,#endif out_ports: -for (i--; i >=0 ; i--) { -uart_remove_one_port (&sc16is7xx_uart, &s->p[i].port); -clear_bit (s->p[i].port.line, &sc16is7xx_lines); - } +for (i =0 ; i < devtype->nr_uart; i++) +if (test_and_clear_bit (s->p[i].port.line, &sc16is7xx_lines)) +uart_remove_one_port (&sc16is7xx_uart, &s->p[i].port);kthread_stop (s->kworker_task);
@@ -1678,8 +1670,8 @@ static void sc16is7xx_remove(struct device *dev)for (i =0 ; i < s->devtype->nr_uart; i++) {kthread_cancel_delayed_work_sync (&s->p[i].ms_work); -uart_remove_one_port (&sc16is7xx_uart, &s->p[i].port); -clear_bit (s->p[i].port.line, &sc16is7xx_lines); +if (test_and_clear_bit (s->p[i].port.line, &sc16is7xx_lines)) +uart_remove_one_port (&sc16is7xx_uart, &s->p[i].port);sc16is7xx_power (&s->p[i].port,0 ); }