Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+27 -36
+17 -4
drivers/tty/serial/8250/8250_dma.c
··· 43 43 struct uart_8250_dma *dma = p->dma; 44 44 struct tty_port *tty_port = &p->port.state->port; 45 45 struct dma_tx_state state; 46 + enum dma_status dma_status; 46 47 int count; 47 48 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; 50 57 51 58 count = dma->rx_size - state.residue; 52 59 53 60 tty_insert_flip_string(tty_port, dma->rx_buf, count); 54 61 p->port.icount.rx += count; 62 + dma->rx_running = 0; 55 63 56 64 tty_flip_buffer_push(tty_port); 57 65 } ··· 70 62 struct uart_8250_dma *dma = p->dma; 71 63 unsigned long flags; 72 64 73 - __dma_rx_complete(p); 74 - 75 65 spin_lock_irqsave(&p->port.lock, flags); 66 + if (dma->rx_running) 67 + __dma_rx_complete(p); 68 + 69 + /* 70 + * Cannot be combined with the previous check because __dma_rx_complete() 71 + * changes dma->rx_running. 72 + */ 76 73 if (!dma->rx_running && (serial_lsr_in(p) & UART_LSR_DR)) 77 74 p->dma->rx_dma(p); 78 75 spin_unlock_irqrestore(&p->port.lock, flags);
+5 -28
drivers/tty/serial/stm32-usart.c
··· 797 797 spin_unlock(&port->lock); 798 798 } 799 799 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 - 814 800 /* 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); 817 803 size = stm32_usart_receive_chars(port, false); 818 - uart_unlock_and_check_sysrq_irqrestore(port, flags); 804 + uart_unlock_and_check_sysrq(port); 819 805 if (size) 820 806 tty_flip_buffer_push(tport); 821 807 } ··· 1001 1015 u32 val; 1002 1016 int ret; 1003 1017 1004 - ret = request_threaded_irq(port->irq, stm32_usart_interrupt, 1005 - stm32_usart_threaded_interrupt, 1006 - IRQF_ONESHOT | IRQF_NO_SUSPEND, 1007 - name, port); 1018 + ret = request_irq(port->irq, stm32_usart_interrupt, 1019 + IRQF_NO_SUSPEND, name, port); 1008 1020 if (ret) 1009 1021 return ret; 1010 1022 ··· 1584 1600 struct device *dev = &pdev->dev; 1585 1601 struct dma_slave_config config; 1586 1602 int ret; 1587 - 1588 - /* 1589 - * Using DMA and threaded handler for the console could lead to 1590 - * deadlocks. 1591 - */ 1592 - if (uart_console(port)) 1593 - return -ENODEV; 1594 1603 1595 1604 stm32port->rx_buf = dma_alloc_coherent(dev, RX_BUF_L, 1596 1605 &stm32port->rx_dma_buf,
+5 -4
drivers/tty/vt/vc_screen.c
··· 386 386 387 387 uni_mode = use_unicode(inode); 388 388 attr = use_attributes(inode); 389 - ret = -ENXIO; 390 - vc = vcs_vc(inode, &viewed); 391 - if (!vc) 392 - goto unlock_out; 393 389 394 390 ret = -EINVAL; 395 391 if (pos < 0) ··· 402 406 while (count) { 403 407 unsigned int this_round, skip = 0; 404 408 int size; 409 + 410 + ret = -ENXIO; 411 + vc = vcs_vc(inode, &viewed); 412 + if (!vc) 413 + goto unlock_out; 405 414 406 415 /* Check whether we are above size each round, 407 416 * as copy_to_user at the end of this loop