Skip to content

Commit c01ac4b

Browse files
committed
Merge tag 'tty-6.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver fixes from Greg KH: "Here are some small tty and serial driver fixes for 6.12-rc4: - qcom-geni serial driver fixes, wow what a mess of a UART chip that thing is... - vt infoleak fix for odd font sizes - imx serial driver bugfix - yet-another n_gsm ldisc bugfix, slowly chipping down the issues in that piece of code All of these have been in linux-next for over a week with no reported issues" * tag 'tty-6.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: serial: qcom-geni: rename suspend functions serial: qcom-geni: drop unused receive parameter serial: qcom-geni: drop flip buffer WARN() serial: qcom-geni: fix rx cancel dma status bit serial: qcom-geni: fix receiver enable serial: qcom-geni: fix dma rx cancellation serial: qcom-geni: fix shutdown race serial: qcom-geni: revert broken hibernation support serial: qcom-geni: fix polled console initialisation serial: imx: Update mctrl old_status on RTSD interrupt tty: n_gsm: Fix use-after-free in gsm_cleanup_mux vt: prevent kernel-infoleak in con_font_get()
2 parents b68c189 + be847a3 commit c01ac4b

File tree

5 files changed

+67
-57
lines changed

5 files changed

+67
-57
lines changed

drivers/tty/n_gsm.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3157,6 +3157,8 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
31573157
mutex_unlock(&gsm->mutex);
31583158
/* Now wipe the queues */
31593159
tty_ldisc_flush(gsm->tty);
3160+
3161+
guard(spinlock_irqsave)(&gsm->tx_lock);
31603162
list_for_each_entry_safe(txq, ntxq, &gsm->tx_ctrl_list, list)
31613163
kfree(txq);
31623164
INIT_LIST_HEAD(&gsm->tx_ctrl_list);

drivers/tty/serial/imx.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,21 @@ static irqreturn_t __imx_uart_rtsint(int irq, void *dev_id)
762762

763763
imx_uart_writel(sport, USR1_RTSD, USR1);
764764
usr1 = imx_uart_readl(sport, USR1) & USR1_RTSS;
765+
/*
766+
* Update sport->old_status here, so any follow-up calls to
767+
* imx_uart_mctrl_check() will be able to recognize that RTS
768+
* state changed since last imx_uart_mctrl_check() call.
769+
*
770+
* In case RTS has been detected as asserted here and later on
771+
* deasserted by the time imx_uart_mctrl_check() was called,
772+
* imx_uart_mctrl_check() can detect the RTS state change and
773+
* trigger uart_handle_cts_change() to unblock the port for
774+
* further TX transfers.
775+
*/
776+
if (usr1 & USR1_RTSS)
777+
sport->old_status |= TIOCM_CTS;
778+
else
779+
sport->old_status &= ~TIOCM_CTS;
765780
uart_handle_cts_change(&sport->port, usr1);
766781
wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
767782

drivers/tty/serial/qcom_geni_serial.c

Lines changed: 48 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ static struct uart_driver qcom_geni_uart_driver;
147147

148148
static void __qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport);
149149
static void qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport);
150+
static int qcom_geni_serial_port_setup(struct uart_port *uport);
150151

151152
static inline struct qcom_geni_serial_port *to_dev_port(struct uart_port *uport)
152153
{
@@ -395,6 +396,23 @@ static void qcom_geni_serial_poll_put_char(struct uart_port *uport,
395396
writel(c, uport->membase + SE_GENI_TX_FIFOn);
396397
qcom_geni_serial_poll_tx_done(uport);
397398
}
399+
400+
static int qcom_geni_serial_poll_init(struct uart_port *uport)
401+
{
402+
struct qcom_geni_serial_port *port = to_dev_port(uport);
403+
int ret;
404+
405+
if (!port->setup) {
406+
ret = qcom_geni_serial_port_setup(uport);
407+
if (ret)
408+
return ret;
409+
}
410+
411+
if (!qcom_geni_serial_secondary_active(uport))
412+
geni_se_setup_s_cmd(&port->se, UART_START_READ, 0);
413+
414+
return 0;
415+
}
398416
#endif
399417

400418
#ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE
@@ -562,17 +580,16 @@ static void handle_rx_console(struct uart_port *uport, u32 bytes, bool drop)
562580
}
563581
#endif /* CONFIG_SERIAL_QCOM_GENI_CONSOLE */
564582

565-
static void handle_rx_uart(struct uart_port *uport, u32 bytes, bool drop)
583+
static void handle_rx_uart(struct uart_port *uport, u32 bytes)
566584
{
567585
struct qcom_geni_serial_port *port = to_dev_port(uport);
568586
struct tty_port *tport = &uport->state->port;
569587
int ret;
570588

571589
ret = tty_insert_flip_string(tport, port->rx_buf, bytes);
572590
if (ret != bytes) {
573-
dev_err(uport->dev, "%s:Unable to push data ret %d_bytes %d\n",
574-
__func__, ret, bytes);
575-
WARN_ON_ONCE(1);
591+
dev_err_ratelimited(uport->dev, "failed to push data (%d < %u)\n",
592+
ret, bytes);
576593
}
577594
uport->icount.rx += ret;
578595
tty_flip_buffer_push(tport);
@@ -787,17 +804,27 @@ static void qcom_geni_serial_start_rx_fifo(struct uart_port *uport)
787804
static void qcom_geni_serial_stop_rx_dma(struct uart_port *uport)
788805
{
789806
struct qcom_geni_serial_port *port = to_dev_port(uport);
807+
bool done;
790808

791809
if (!qcom_geni_serial_secondary_active(uport))
792810
return;
793811

794812
geni_se_cancel_s_cmd(&port->se);
795-
qcom_geni_serial_poll_bit(uport, SE_GENI_S_IRQ_STATUS,
796-
S_CMD_CANCEL_EN, true);
797-
798-
if (qcom_geni_serial_secondary_active(uport))
813+
done = qcom_geni_serial_poll_bit(uport, SE_DMA_RX_IRQ_STAT,
814+
RX_EOT, true);
815+
if (done) {
816+
writel(RX_EOT | RX_DMA_DONE,
817+
uport->membase + SE_DMA_RX_IRQ_CLR);
818+
} else {
799819
qcom_geni_serial_abort_rx(uport);
800820

821+
writel(1, uport->membase + SE_DMA_RX_FSM_RST);
822+
qcom_geni_serial_poll_bit(uport, SE_DMA_RX_IRQ_STAT,
823+
RX_RESET_DONE, true);
824+
writel(RX_RESET_DONE | RX_DMA_DONE,
825+
uport->membase + SE_DMA_RX_IRQ_CLR);
826+
}
827+
801828
if (port->rx_dma_addr) {
802829
geni_se_rx_dma_unprep(&port->se, port->rx_dma_addr,
803830
DMA_RX_BUF_SIZE);
@@ -846,7 +873,7 @@ static void qcom_geni_serial_handle_rx_dma(struct uart_port *uport, bool drop)
846873
}
847874

848875
if (!drop)
849-
handle_rx_uart(uport, rx_in, drop);
876+
handle_rx_uart(uport, rx_in);
850877

851878
ret = geni_se_rx_dma_prep(&port->se, port->rx_buf,
852879
DMA_RX_BUF_SIZE,
@@ -1096,10 +1123,12 @@ static void qcom_geni_serial_shutdown(struct uart_port *uport)
10961123
{
10971124
disable_irq(uport->irq);
10981125

1126+
uart_port_lock_irq(uport);
10991127
qcom_geni_serial_stop_tx(uport);
11001128
qcom_geni_serial_stop_rx(uport);
11011129

11021130
qcom_geni_serial_cancel_tx_cmd(uport);
1131+
uart_port_unlock_irq(uport);
11031132
}
11041133

11051134
static void qcom_geni_serial_flush_buffer(struct uart_port *uport)
@@ -1152,7 +1181,6 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport)
11521181
false, true, true);
11531182
geni_se_init(&port->se, UART_RX_WM, port->rx_fifo_depth - 2);
11541183
geni_se_select_mode(&port->se, port->dev_data->mode);
1155-
qcom_geni_serial_start_rx(uport);
11561184
port->setup = true;
11571185

11581186
return 0;
@@ -1168,6 +1196,11 @@ static int qcom_geni_serial_startup(struct uart_port *uport)
11681196
if (ret)
11691197
return ret;
11701198
}
1199+
1200+
uart_port_lock_irq(uport);
1201+
qcom_geni_serial_start_rx(uport);
1202+
uart_port_unlock_irq(uport);
1203+
11711204
enable_irq(uport->irq);
11721205

11731206
return 0;
@@ -1253,7 +1286,6 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
12531286
unsigned int avg_bw_core;
12541287
unsigned long timeout;
12551288

1256-
qcom_geni_serial_stop_rx(uport);
12571289
/* baud rate */
12581290
baud = uart_get_baud_rate(uport, termios, old, 300, 4000000);
12591291

@@ -1269,7 +1301,7 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
12691301
dev_err(port->se.dev,
12701302
"Couldn't find suitable clock rate for %u\n",
12711303
baud * sampling_rate);
1272-
goto out_restart_rx;
1304+
return;
12731305
}
12741306

12751307
dev_dbg(port->se.dev, "desired_rate = %u, clk_rate = %lu, clk_div = %u\n",
@@ -1360,8 +1392,6 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
13601392
writel(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN);
13611393
writel(ser_clk_cfg, uport->membase + GENI_SER_M_CLK_CFG);
13621394
writel(ser_clk_cfg, uport->membase + GENI_SER_S_CLK_CFG);
1363-
out_restart_rx:
1364-
qcom_geni_serial_start_rx(uport);
13651395
}
13661396

13671397
#ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE
@@ -1582,7 +1612,7 @@ static const struct uart_ops qcom_geni_console_pops = {
15821612
#ifdef CONFIG_CONSOLE_POLL
15831613
.poll_get_char = qcom_geni_serial_get_char,
15841614
.poll_put_char = qcom_geni_serial_poll_put_char,
1585-
.poll_init = qcom_geni_serial_port_setup,
1615+
.poll_init = qcom_geni_serial_poll_init,
15861616
#endif
15871617
.pm = qcom_geni_serial_pm,
15881618
};
@@ -1749,7 +1779,7 @@ static void qcom_geni_serial_remove(struct platform_device *pdev)
17491779
uart_remove_one_port(drv, &port->uport);
17501780
}
17511781

1752-
static int qcom_geni_serial_sys_suspend(struct device *dev)
1782+
static int qcom_geni_serial_suspend(struct device *dev)
17531783
{
17541784
struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
17551785
struct uart_port *uport = &port->uport;
@@ -1766,7 +1796,7 @@ static int qcom_geni_serial_sys_suspend(struct device *dev)
17661796
return uart_suspend_port(private_data->drv, uport);
17671797
}
17681798

1769-
static int qcom_geni_serial_sys_resume(struct device *dev)
1799+
static int qcom_geni_serial_resume(struct device *dev)
17701800
{
17711801
int ret;
17721802
struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
@@ -1781,38 +1811,6 @@ static int qcom_geni_serial_sys_resume(struct device *dev)
17811811
return ret;
17821812
}
17831813

1784-
static int qcom_geni_serial_sys_hib_resume(struct device *dev)
1785-
{
1786-
int ret = 0;
1787-
struct uart_port *uport;
1788-
struct qcom_geni_private_data *private_data;
1789-
struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
1790-
1791-
uport = &port->uport;
1792-
private_data = uport->private_data;
1793-
1794-
if (uart_console(uport)) {
1795-
geni_icc_set_tag(&port->se, QCOM_ICC_TAG_ALWAYS);
1796-
geni_icc_set_bw(&port->se);
1797-
ret = uart_resume_port(private_data->drv, uport);
1798-
/*
1799-
* For hibernation usecase clients for
1800-
* console UART won't call port setup during restore,
1801-
* hence call port setup for console uart.
1802-
*/
1803-
qcom_geni_serial_port_setup(uport);
1804-
} else {
1805-
/*
1806-
* Peripheral register settings are lost during hibernation.
1807-
* Update setup flag such that port setup happens again
1808-
* during next session. Clients of HS-UART will close and
1809-
* open the port during hibernation.
1810-
*/
1811-
port->setup = false;
1812-
}
1813-
return ret;
1814-
}
1815-
18161814
static const struct qcom_geni_device_data qcom_geni_console_data = {
18171815
.console = true,
18181816
.mode = GENI_SE_FIFO,
@@ -1824,12 +1822,7 @@ static const struct qcom_geni_device_data qcom_geni_uart_data = {
18241822
};
18251823

18261824
static const struct dev_pm_ops qcom_geni_serial_pm_ops = {
1827-
.suspend = pm_sleep_ptr(qcom_geni_serial_sys_suspend),
1828-
.resume = pm_sleep_ptr(qcom_geni_serial_sys_resume),
1829-
.freeze = pm_sleep_ptr(qcom_geni_serial_sys_suspend),
1830-
.poweroff = pm_sleep_ptr(qcom_geni_serial_sys_suspend),
1831-
.restore = pm_sleep_ptr(qcom_geni_serial_sys_hib_resume),
1832-
.thaw = pm_sleep_ptr(qcom_geni_serial_sys_hib_resume),
1825+
SYSTEM_SLEEP_PM_OPS(qcom_geni_serial_suspend, qcom_geni_serial_resume)
18331826
};
18341827

18351828
static const struct of_device_id qcom_geni_serial_match_table[] = {

drivers/tty/vt/vt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4726,7 +4726,7 @@ static int con_font_get(struct vc_data *vc, struct console_font_op *op)
47264726
return -EINVAL;
47274727

47284728
if (op->data) {
4729-
font.data = kvmalloc(max_font_size, GFP_KERNEL);
4729+
font.data = kvzalloc(max_font_size, GFP_KERNEL);
47304730
if (!font.data)
47314731
return -ENOMEM;
47324732
} else

include/linux/soc/qcom/geni-se.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,8 @@ struct geni_se {
258258
#define RX_DMA_PARITY_ERR BIT(5)
259259
#define RX_DMA_BREAK GENMASK(8, 7)
260260
#define RX_GENI_GP_IRQ GENMASK(10, 5)
261-
#define RX_GENI_CANCEL_IRQ BIT(11)
262261
#define RX_GENI_GP_IRQ_EXT GENMASK(13, 12)
262+
#define RX_GENI_CANCEL_IRQ BIT(14)
263263

264264
/* SE_HW_PARAM_0 fields */
265265
#define TX_FIFO_WIDTH_MSK GENMASK(29, 24)

0 commit comments

Comments
 (0)