Skip to content

Commit 9e13ae1

Browse files
jhovoldgregkh
authored andcommitted
serial: qcom-geni: fix receiver enable
commit fa103d2 upstream. The receiver is supposed to be enabled in the startup() callback and not in set_termios() which is called also during console setup. This specifically avoids accepting input before the port has been opened (and interrupts enabled), something which can also break the GENI firmware (cancel fails and after abort, the "stale" counter handling appears to be broken so that later input is not processed until twelve chars have been received). There also does not appear to be any need to keep the receiver disabled while updating the port settings. Since commit 6f3c3ca ("serial: qcom-geni: disable interrupts during console writes") the calls to manipulate the secondary interrupts, which were done without holding the port lock, can also lead to the receiver being left disabled when set_termios() races with the console code (e.g. when init opens the tty during boot). This can manifest itself as a serial getty not accepting input. The calls to stop and start rx in set_termios() can similarly race with DMA completion and, for example, cause the DMA buffer to be unmapped twice or the mapping to be leaked. Fix this by only enabling the receiver during startup and while holding the port lock to avoid racing with the console code. Fixes: 6f3c3ca ("serial: qcom-geni: disable interrupts during console writes") Fixes: 2aaa43c ("tty: serial: qcom-geni-serial: add support for serial engine DMA") Fixes: c4f5287 ("tty: serial: msm_geni_serial: Add serial driver support for GENI based QUP") Cc: stable@vger.kernel.org # 6.3 Cc: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Signed-off-by: Johan Hovold <johan+linaro@kernel.org> Reviewed-by: Douglas Anderson <dianders@chromium.org> Link: https://lore.kernel.org/r/20241009145110.16847-6-johan+linaro@kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent f7f5d52 commit 9e13ae1

1 file changed

Lines changed: 6 additions & 4 deletions

File tree

drivers/tty/serial/qcom_geni_serial.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,11 @@ static int qcom_geni_serial_startup(struct uart_port *uport)
11791179
if (ret)
11801180
return ret;
11811181
}
1182+
1183+
uart_port_lock_irq(uport);
1184+
qcom_geni_serial_start_rx(uport);
1185+
uart_port_unlock_irq(uport);
1186+
11821187
enable_irq(uport->irq);
11831188

11841189
return 0;
@@ -1264,7 +1269,6 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
12641269
unsigned int avg_bw_core;
12651270
unsigned long timeout;
12661271

1267-
qcom_geni_serial_stop_rx(uport);
12681272
/* baud rate */
12691273
baud = uart_get_baud_rate(uport, termios, old, 300, 4000000);
12701274

@@ -1280,7 +1284,7 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
12801284
dev_err(port->se.dev,
12811285
"Couldn't find suitable clock rate for %u\n",
12821286
baud * sampling_rate);
1283-
goto out_restart_rx;
1287+
return;
12841288
}
12851289

12861290
dev_dbg(port->se.dev, "desired_rate = %u, clk_rate = %lu, clk_div = %u\n",
@@ -1371,8 +1375,6 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
13711375
writel(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN);
13721376
writel(ser_clk_cfg, uport->membase + GENI_SER_M_CLK_CFG);
13731377
writel(ser_clk_cfg, uport->membase + GENI_SER_S_CLK_CFG);
1374-
out_restart_rx:
1375-
qcom_geni_serial_start_rx(uport);
13761378
}
13771379

13781380
#ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE

0 commit comments

Comments
 (0)