linux-next: manual merge of the tty tree with the tty.current tree

From: Mark Brown

Date: Fri Sep 25 2026 - 11:12:38 EST


Hi all,

Today's linux-next merge of the tty tree got conflicts in:

include/linux/soc/qcom/geni-se.h
drivers/tty/serial/qcom_geni_serial.c

between commits:

1cd9b1be5a9c5 ("soc: qcom: geni-se: Correct QUP Core ICC vote constants")
63ef71d1474b5 ("tty: serial: qcom_geni_serial: Keep console RX functional after deep idle")

from the tty.current tree and commits:

b815e9b19ea5c ("soc: qcom: geni-se: Correct QUP Core ICC vote constants")
d147a15be6840 ("tty: serial: qcom_geni_serial: Keep console RX functional after deep idle")

from the tty tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

diff --combined drivers/tty/serial/qcom_geni_serial.c
index a851b8f0ef047,3502a3b6675e8..0000000000000
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@@ -20,7 -20,6 +20,6 @@@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/panic_notifier.h>
- #include <linux/pm_domain.h>
#include <linux/pm_opp.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
@@@ -171,6 -170,7 +170,6 @@@ static void qcom_geni_serial_cancel_tx_
static int qcom_geni_serial_port_setup(struct uart_port *uport);
static void qcom_geni_serial_start_tx_fifo(struct uart_port *uport);
static void qcom_geni_serial_resume_tx(struct uart_port *uport);
-static void qcom_geni_serial_poll_rx_fifo_locked(struct uart_port *uport);

static inline struct qcom_geni_serial_port *to_dev_port(struct uart_port *uport)
{
@@@ -288,6 -288,10 +287,10 @@@ static struct qcom_geni_serial_port *ge
} else {
int max_alias_num = of_alias_get_highest_id("serial");

+ port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
+ if (!port)
+ return ERR_PTR(-ENOMEM);
+
if (line < 0 || line >= nr_ports)
line = ida_alloc_range(&port_ida, max_alias_num + 1,
nr_ports - 1, GFP_KERNEL);
@@@ -298,10 -302,6 +301,6 @@@
if (line < 0)
return ERR_PTR(-ENXIO);

- port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
- if (!port)
- return ERR_PTR(-ENOMEM);
-
port->uport.iotype = UPIO_MEM;
port->uport.ops = &qcom_geni_uart_pops;
port->uport.flags = UPF_BOOT_AUTOCONF;
@@@ -466,102 -466,6 +465,102 @@@ static int qcom_geni_serial_poll_init(s
#endif

#ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE
+static void handle_rx_console(struct uart_port *uport, u32 bytes, bool drop)
+{
+ u32 i;
+ unsigned char buf[sizeof(u32)];
+ struct tty_port *tport;
+ struct qcom_geni_serial_port *port = to_dev_port(uport);
+
+ tport = &uport->state->port;
+ for (i = 0; i < bytes; ) {
+ int c;
+ int chunk = min_t(int, bytes - i, BYTES_PER_FIFO_WORD);
+
+ ioread32_rep(uport->membase + SE_GENI_RX_FIFOn, buf, 1);
+ i += chunk;
+ if (drop)
+ continue;
+
+ for (c = 0; c < chunk; c++) {
+ int sysrq;
+
+ uport->icount.rx++;
+ if (port->brk && buf[c] == 0) {
+ port->brk = false;
+ if (uart_handle_break(uport))
+ continue;
+ }
+
+ sysrq = uart_prepare_sysrq_char(uport, buf[c]);
+
+ if (!sysrq)
+ tty_insert_flip_char(tport, buf[c], TTY_NORMAL);
+ }
+ }
+ if (!drop)
+ tty_flip_buffer_push(tport);
+}
+#else
+static void handle_rx_console(struct uart_port *uport, u32 bytes, bool drop)
+{
+
+}
+#endif
+
+static void qcom_geni_serial_handle_rx_fifo(struct uart_port *uport, bool drop)
+{
+ u32 status;
+ u32 word_cnt;
+ u32 last_word_byte_cnt;
+ u32 last_word_partial;
+ u32 total_bytes;
+
+ status = readl(uport->membase + SE_GENI_RX_FIFO_STATUS);
+ word_cnt = status & RX_FIFO_WC_MSK;
+ last_word_partial = status & RX_LAST;
+ last_word_byte_cnt = (status & RX_LAST_BYTE_VALID_MSK) >>
+ RX_LAST_BYTE_VALID_SHFT;
+
+ if (!word_cnt)
+ return;
+ total_bytes = BYTES_PER_FIFO_WORD * (word_cnt - 1);
+ if (last_word_partial && last_word_byte_cnt)
+ total_bytes += last_word_byte_cnt;
+ else
+ total_bytes += BYTES_PER_FIFO_WORD;
+ handle_rx_console(uport, total_bytes, drop);
+}
+
+#ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE
+/* Caller holds the UART port lock. */
+static void qcom_geni_serial_poll_rx_fifo_locked(struct uart_port *uport)
+{
+ struct qcom_geni_serial_port *port = to_dev_port(uport);
+ struct tty_port *tport = &uport->state->port;
+ u32 s_irq_status;
+ bool drop_rx = false;
+
+ s_irq_status = readl(uport->membase + SE_GENI_S_IRQ_STATUS);
+ writel(s_irq_status, uport->membase + SE_GENI_S_IRQ_CLEAR);
+
+ if (s_irq_status & S_RX_FIFO_WR_ERR_EN) {
+ uport->icount.overrun++;
+ tty_insert_flip_char(tport, 0, TTY_OVERRUN);
+ }
+
+ if (s_irq_status & (S_GP_IRQ_0_EN | S_GP_IRQ_1_EN)) {
+ if (s_irq_status & S_GP_IRQ_0_EN)
+ uport->icount.parity++;
+ drop_rx = true;
+ } else if (s_irq_status & (S_GP_IRQ_2_EN | S_GP_IRQ_3_EN)) {
+ uport->icount.brk++;
+ port->brk = true;
+ }
+
+ qcom_geni_serial_handle_rx_fifo(uport, drop_rx);
+}
+
static void qcom_geni_serial_drain_fifo(struct uart_port *uport)
{
struct qcom_geni_serial_port *port = to_dev_port(uport);
@@@ -771,6 -675,47 +770,6 @@@ static void qcom_geni_serial_console_de
#endif
}

-static void handle_rx_console(struct uart_port *uport, u32 bytes, bool drop)
-{
- u32 i;
- unsigned char buf[sizeof(u32)];
- struct tty_port *tport;
- struct qcom_geni_serial_port *port = to_dev_port(uport);
-
- tport = &uport->state->port;
- for (i = 0; i < bytes; ) {
- int c;
- int chunk = min_t(int, bytes - i, BYTES_PER_FIFO_WORD);
-
- ioread32_rep(uport->membase + SE_GENI_RX_FIFOn, buf, 1);
- i += chunk;
- if (drop)
- continue;
-
- for (c = 0; c < chunk; c++) {
- int sysrq;
-
- uport->icount.rx++;
- if (port->brk && buf[c] == 0) {
- port->brk = false;
- if (uart_handle_break(uport))
- continue;
- }
-
- sysrq = uart_prepare_sysrq_char(uport, buf[c]);
-
- if (!sysrq)
- tty_insert_flip_char(tport, buf[c], TTY_NORMAL);
- }
- }
- if (!drop)
- tty_flip_buffer_push(tport);
-}
-#else
-static void handle_rx_console(struct uart_port *uport, u32 bytes, bool drop)
-{
-
-}
#endif /* CONFIG_SERIAL_QCOM_GENI_CONSOLE */

static void handle_rx_uart(struct uart_port *uport, u32 bytes)
@@@ -944,6 -889,58 +943,6 @@@ static void qcom_geni_serial_cancel_tx_
port->tx_queued = 0;
}

-static void qcom_geni_serial_handle_rx_fifo(struct uart_port *uport, bool drop)
-{
- u32 status;
- u32 word_cnt;
- u32 last_word_byte_cnt;
- u32 last_word_partial;
- u32 total_bytes;
-
- status = readl(uport->membase + SE_GENI_RX_FIFO_STATUS);
- word_cnt = status & RX_FIFO_WC_MSK;
- last_word_partial = status & RX_LAST;
- last_word_byte_cnt = (status & RX_LAST_BYTE_VALID_MSK) >>
- RX_LAST_BYTE_VALID_SHFT;
-
- if (!word_cnt)
- return;
- total_bytes = BYTES_PER_FIFO_WORD * (word_cnt - 1);
- if (last_word_partial && last_word_byte_cnt)
- total_bytes += last_word_byte_cnt;
- else
- total_bytes += BYTES_PER_FIFO_WORD;
- handle_rx_console(uport, total_bytes, drop);
-}
-
-/* Caller holds the UART port lock. */
-static void qcom_geni_serial_poll_rx_fifo_locked(struct uart_port *uport)
-{
- struct qcom_geni_serial_port *port = to_dev_port(uport);
- struct tty_port *tport = &uport->state->port;
- u32 s_irq_status;
- bool drop_rx = false;
-
- s_irq_status = readl(uport->membase + SE_GENI_S_IRQ_STATUS);
- writel(s_irq_status, uport->membase + SE_GENI_S_IRQ_CLEAR);
-
- if (s_irq_status & S_RX_FIFO_WR_ERR_EN) {
- uport->icount.overrun++;
- tty_insert_flip_char(tport, 0, TTY_OVERRUN);
- }
-
- if (s_irq_status & (S_GP_IRQ_0_EN | S_GP_IRQ_1_EN)) {
- if (s_irq_status & S_GP_IRQ_0_EN)
- uport->icount.parity++;
- drop_rx = true;
- } else if (s_irq_status & (S_GP_IRQ_2_EN | S_GP_IRQ_3_EN)) {
- uport->icount.brk++;
- port->brk = true;
- }
-
- qcom_geni_serial_handle_rx_fifo(uport, drop_rx);
-}
-
static void qcom_geni_serial_stop_rx_fifo(struct uart_port *uport)
{
u32 irq_en;
@@@ -1293,7 -1290,6 +1292,6 @@@ out_unlock
static int setup_fifos(struct qcom_geni_serial_port *port)
{
struct uart_port *uport;
- u32 old_rx_fifo_depth = port->rx_fifo_depth;

uport = &port->uport;
port->tx_fifo_depth = geni_se_get_tx_fifo_depth(&port->se);
@@@ -1302,19 -1298,6 +1300,6 @@@
uport->fifosize =
(port->tx_fifo_depth * port->tx_fifo_width) / BITS_PER_BYTE;

- if (port->rx_buf && (old_rx_fifo_depth != port->rx_fifo_depth) && port->rx_fifo_depth) {
- /*
- * Use krealloc rather than krealloc_array because rx_buf is
- * accessed as 1 byte entries as well as 4 byte entries so it's
- * not necessarily an array.
- */
- port->rx_buf = devm_krealloc(uport->dev, port->rx_buf,
- port->rx_fifo_depth * sizeof(u32),
- GFP_KERNEL);
- if (!port->rx_buf)
- return -ENOMEM;
- }
-
return 0;
}

@@@ -1484,7 -1467,7 +1469,7 @@@ static int geni_serial_set_rate(struct
* Bump up BW vote on CPU and CORE path as driver supports FIFO mode
* only.
*/
- avg_bw_core = baud > 115200 ? CORE_2X_50_MHZ : CORE_2X_19_2_MHZ;
+ avg_bw_core = (baud > 115200) ? CORE_2X_50_MHZ : CORE_2X_19_2_MHZ;
port->se.icc_paths[GENI_TO_CORE].avg_bw = Bps_to_icc(avg_bw_core);
port->se.icc_paths[CPU_TO_GENI].avg_bw = Bps_to_icc(baud);
geni_icc_set_bw(&port->se);
@@@ -1626,37 -1609,16 +1611,37 @@@ static int qcom_geni_console_setup(stru
if (unlikely(!uport->membase))
return -ENXIO;

+ ret = pm_runtime_resume_and_get(uport->dev);
+ if (ret < 0)
+ return ret;
+
if (!port->setup) {
ret = qcom_geni_serial_port_setup(uport);
- if (ret)
+ if (ret) {
+ pm_runtime_put_sync(uport->dev);
return ret;
+ }
}

if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);

- return uart_set_options(uport, co, baud, parity, bits, flow);
+ ret = uart_set_options(uport, co, baud, parity, bits, flow);
+ if (ret)
+ pm_runtime_put_sync(uport->dev);
+
+ return ret;
+}
+
+static int qcom_geni_console_exit(struct console *co)
+{
+ struct qcom_geni_serial_port *port;
+
+ port = get_port_from_line(co->index, true, NULL);
+ if (IS_ERR(port))
+ return PTR_ERR(port);
+
+ return pm_runtime_put_sync(port->uport.dev);
}

static void qcom_geni_serial_earlycon_write(struct console *con,
@@@ -1773,7 -1735,6 +1758,7 @@@ static struct console cons_ops =
.device_unlock = qcom_geni_serial_console_device_unlock,
.device = uart_console_device,
.setup = qcom_geni_console_setup,
+ .exit = qcom_geni_console_exit,
.flags = CON_PRINTBUFFER | CON_NBCON,
.index = -1,
.data = &qcom_geni_console_driver,
@@@ -1920,7 -1881,7 +1905,7 @@@ static int qcom_geni_serial_probe(struc

ret = port->dev_data->resources_init(&port->se);
if (ret)
- return ret;
+ goto error;

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@@ -1970,8 -1931,13 +1955,13 @@@
uport->irq = irq;
uport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_QCOM_GENI_CONSOLE);

- if (!data->console)
+ if (!data->console) {
port->wakeup_irq = platform_get_irq_optional(pdev, 1);
+ if (port->wakeup_irq < 0 && port->wakeup_irq != -ENXIO) {
+ ret = port->wakeup_irq;
+ goto error;
+ }
+ }

if (of_property_read_bool(pdev->dev.of_node, "rx-tx-swap"))
port->rx_tx_swap = true;
@@@ -2002,7 -1968,6 +1992,6 @@@
port->wakeup_irq);
if (ret) {
device_init_wakeup(&pdev->dev, false);
- ida_free(&port_ida, uport->line);
goto error;
}
}
@@@ -2026,12 -1991,13 +2015,13 @@@
return 0;

error:
+ if (!data->console)
+ ida_free(&port_ida, uport->line);
if (port->rx_dma_addr) {
dma_unmap_single(pdev->dev.parent, port->rx_dma_addr,
DMA_RX_BUF_SIZE, DMA_FROM_DEVICE);
port->rx_dma_addr = 0;
}
- dev_pm_domain_detach_list(port->se.pd_list);
return ret;
}

@@@ -2047,7 -2013,8 +2037,8 @@@ static void qcom_geni_serial_remove(str
irq_work_sync(&port->tx_kick);
dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
- ida_free(&port_ida, uport->line);
+ if (!port->dev_data->console)
+ ida_free(&port_ida, uport->line);
uart_remove_one_port(drv, &port->uport);

if (port->rx_dma_addr) {
@@@ -2055,8 -2022,6 +2046,6 @@@
DMA_RX_BUF_SIZE, DMA_FROM_DEVICE);
port->rx_dma_addr = 0;
}
-
- dev_pm_domain_detach_list(port->se.pd_list);
}

static int __maybe_unused qcom_geni_serial_runtime_suspend(struct device *dev)
@@@ -2122,11 -2087,9 +2111,11 @@@ static int qcom_geni_serial_resume(stru
struct uart_port *uport = &port->uport;
struct qcom_geni_private_data *private_data = uport->private_data;

- ret = pm_runtime_force_resume(dev);
- if (ret)
- return ret;
+ if (console_suspend_enabled || !uart_console(uport)) {
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+ }

ret = uart_resume_port(private_data->drv, uport);
if (uart_console(uport)) {
diff --combined include/linux/soc/qcom/geni-se.h
index 5f18d281e6a42,2243005f5e2ee..0000000000000
--- a/include/linux/soc/qcom/geni-se.h
+++ b/include/linux/soc/qcom/geni-se.h
@@@ -347,12 -347,18 +347,18 @@@ struct geni_se
#define QUP_SE_VERSION_2_5 0x20050000

/*
- * QUP Core 2X clock votes used by GENI clients through the "qup-core" ICC
- * path. Values are in Bps and must be converted with Bps_to_icc() before
- * setting avg_bw.
+ * ICC bandwidth values in Bps for the GENI_TO_CORE ("qup-core") path.
+ * Convert them with Bps_to_icc() before setting avg_bw. The QUP ICC provider
+ * maps each threshold to the Core 2X rate named by the macro suffix.
+ *
+ * These values are core clock votes, not GENI transfer bandwidths.
*/
#define CORE_2X_19_2_MHZ 9600000
#define CORE_2X_50_MHZ 25000000
+ #define CORE_2X_100_MHZ 50000000
+ #define CORE_2X_150_MHZ 75000000
+ #define CORE_2X_200_MHZ 100000000
+ #define CORE_2X_236_MHZ 118000000

#define GENI_DEFAULT_BW Bps_to_icc(1000)

Attachment: signature.asc
Description: PGP signature