Skip to content

Commit dc0ce18

Browse files
committed
Merge tag 'tty-6.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver fixes from Greg KH: "Here are some small serial and vt fixes. These include: - 8250 driver fixes relating to dma issues - stm32 serial driver fix for threaded irqs - vc_screen bugfix for reported problems. All have been in linux-next for a while with no reported problems" * tag 'tty-6.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: vc_screen: move load of struct vc_data pointer in vcs_read() to avoid UAF serial: 8250_dma: Fix DMA Rx rearm race serial: 8250_dma: Fix DMA Rx completion race serial: stm32: Merge hard IRQ and threaded IRQ handling into single IRQ handler
2 parents d3feaff + 226fae1 commit dc0ce18

File tree

3 files changed

+27
-36
lines changed

3 files changed

+27
-36
lines changed

drivers/tty/serial/8250/8250_dma.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,23 @@ static void __dma_rx_complete(struct uart_8250_port *p)
4343
struct uart_8250_dma *dma = p->dma;
4444
struct tty_port *tty_port = &p->port.state->port;
4545
struct dma_tx_state state;
46+
enum dma_status dma_status;
4647
int count;
4748

48-
dma->rx_running = 0;
49-
dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
49+
/*
50+
* New DMA Rx can be started during the completion handler before it
51+
* could acquire port's lock and it might still be ongoing. Don't to
52+
* anything in such case.
53+
*/
54+
dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
55+
if (dma_status == DMA_IN_PROGRESS)
56+
return;
5057

5158
count = dma->rx_size - state.residue;
5259

5360
tty_insert_flip_string(tty_port, dma->rx_buf, count);
5461
p->port.icount.rx += count;
62+
dma->rx_running = 0;
5563

5664
tty_flip_buffer_push(tty_port);
5765
}
@@ -62,9 +70,14 @@ static void dma_rx_complete(void *param)
6270
struct uart_8250_dma *dma = p->dma;
6371
unsigned long flags;
6472

65-
__dma_rx_complete(p);
66-
6773
spin_lock_irqsave(&p->port.lock, flags);
74+
if (dma->rx_running)
75+
__dma_rx_complete(p);
76+
77+
/*
78+
* Cannot be combined with the previous check because __dma_rx_complete()
79+
* changes dma->rx_running.
80+
*/
6881
if (!dma->rx_running && (serial_lsr_in(p) & UART_LSR_DR))
6982
p->dma->rx_dma(p);
7083
spin_unlock_irqrestore(&p->port.lock, flags);

drivers/tty/serial/stm32-usart.c

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -797,25 +797,11 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
797797
spin_unlock(&port->lock);
798798
}
799799

800-
if (stm32_usart_rx_dma_enabled(port))
801-
return IRQ_WAKE_THREAD;
802-
else
803-
return IRQ_HANDLED;
804-
}
805-
806-
static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr)
807-
{
808-
struct uart_port *port = ptr;
809-
struct tty_port *tport = &port->state->port;
810-
struct stm32_port *stm32_port = to_stm32_port(port);
811-
unsigned int size;
812-
unsigned long flags;
813-
814800
/* Receiver timeout irq for DMA RX */
815-
if (!stm32_port->throttled) {
816-
spin_lock_irqsave(&port->lock, flags);
801+
if (stm32_usart_rx_dma_enabled(port) && !stm32_port->throttled) {
802+
spin_lock(&port->lock);
817803
size = stm32_usart_receive_chars(port, false);
818-
uart_unlock_and_check_sysrq_irqrestore(port, flags);
804+
uart_unlock_and_check_sysrq(port);
819805
if (size)
820806
tty_flip_buffer_push(tport);
821807
}
@@ -1015,10 +1001,8 @@ static int stm32_usart_startup(struct uart_port *port)
10151001
u32 val;
10161002
int ret;
10171003

1018-
ret = request_threaded_irq(port->irq, stm32_usart_interrupt,
1019-
stm32_usart_threaded_interrupt,
1020-
IRQF_ONESHOT | IRQF_NO_SUSPEND,
1021-
name, port);
1004+
ret = request_irq(port->irq, stm32_usart_interrupt,
1005+
IRQF_NO_SUSPEND, name, port);
10221006
if (ret)
10231007
return ret;
10241008

@@ -1601,13 +1585,6 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
16011585
struct dma_slave_config config;
16021586
int ret;
16031587

1604-
/*
1605-
* Using DMA and threaded handler for the console could lead to
1606-
* deadlocks.
1607-
*/
1608-
if (uart_console(port))
1609-
return -ENODEV;
1610-
16111588
stm32port->rx_buf = dma_alloc_coherent(dev, RX_BUF_L,
16121589
&stm32port->rx_dma_buf,
16131590
GFP_KERNEL);

drivers/tty/vt/vc_screen.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -386,10 +386,6 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
386386

387387
uni_mode = use_unicode(inode);
388388
attr = use_attributes(inode);
389-
ret = -ENXIO;
390-
vc = vcs_vc(inode, &viewed);
391-
if (!vc)
392-
goto unlock_out;
393389

394390
ret = -EINVAL;
395391
if (pos < 0)
@@ -407,6 +403,11 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
407403
unsigned int this_round, skip = 0;
408404
int size;
409405

406+
ret = -ENXIO;
407+
vc = vcs_vc(inode, &viewed);
408+
if (!vc)
409+
goto unlock_out;
410+
410411
/* Check whether we are above size each round,
411412
* as copy_to_user at the end of this loop
412413
* could sleep.

0 commit comments

Comments
 (0)