mirror of
https://github.com/torvalds/linux.git
synced 2024-12-03 17:41:22 +00:00
TTY/Serial driver fixes for 6.2-rc7
Here are some small serial and vt fixes for 6.2-rc7. 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. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCY9+W6w8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ykpdwCff46Sep4kONMNRiWsxP6FL+agXdgAmwfavWwG TAeFdhh+sUjncja8LcYI =M/L/ -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
dc0ce181af
@ -43,15 +43,23 @@ static void __dma_rx_complete(struct uart_8250_port *p)
|
||||
struct uart_8250_dma *dma = p->dma;
|
||||
struct tty_port *tty_port = &p->port.state->port;
|
||||
struct dma_tx_state state;
|
||||
enum dma_status dma_status;
|
||||
int count;
|
||||
|
||||
dma->rx_running = 0;
|
||||
dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
|
||||
/*
|
||||
* New DMA Rx can be started during the completion handler before it
|
||||
* could acquire port's lock and it might still be ongoing. Don't to
|
||||
* anything in such case.
|
||||
*/
|
||||
dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
|
||||
if (dma_status == DMA_IN_PROGRESS)
|
||||
return;
|
||||
|
||||
count = dma->rx_size - state.residue;
|
||||
|
||||
tty_insert_flip_string(tty_port, dma->rx_buf, count);
|
||||
p->port.icount.rx += count;
|
||||
dma->rx_running = 0;
|
||||
|
||||
tty_flip_buffer_push(tty_port);
|
||||
}
|
||||
@ -62,9 +70,14 @@ static void dma_rx_complete(void *param)
|
||||
struct uart_8250_dma *dma = p->dma;
|
||||
unsigned long flags;
|
||||
|
||||
__dma_rx_complete(p);
|
||||
|
||||
spin_lock_irqsave(&p->port.lock, flags);
|
||||
if (dma->rx_running)
|
||||
__dma_rx_complete(p);
|
||||
|
||||
/*
|
||||
* Cannot be combined with the previous check because __dma_rx_complete()
|
||||
* changes dma->rx_running.
|
||||
*/
|
||||
if (!dma->rx_running && (serial_lsr_in(p) & UART_LSR_DR))
|
||||
p->dma->rx_dma(p);
|
||||
spin_unlock_irqrestore(&p->port.lock, flags);
|
||||
|
@ -797,25 +797,11 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
|
||||
spin_unlock(&port->lock);
|
||||
}
|
||||
|
||||
if (stm32_usart_rx_dma_enabled(port))
|
||||
return IRQ_WAKE_THREAD;
|
||||
else
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr)
|
||||
{
|
||||
struct uart_port *port = ptr;
|
||||
struct tty_port *tport = &port->state->port;
|
||||
struct stm32_port *stm32_port = to_stm32_port(port);
|
||||
unsigned int size;
|
||||
unsigned long flags;
|
||||
|
||||
/* Receiver timeout irq for DMA RX */
|
||||
if (!stm32_port->throttled) {
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
if (stm32_usart_rx_dma_enabled(port) && !stm32_port->throttled) {
|
||||
spin_lock(&port->lock);
|
||||
size = stm32_usart_receive_chars(port, false);
|
||||
uart_unlock_and_check_sysrq_irqrestore(port, flags);
|
||||
uart_unlock_and_check_sysrq(port);
|
||||
if (size)
|
||||
tty_flip_buffer_push(tport);
|
||||
}
|
||||
@ -1015,10 +1001,8 @@ static int stm32_usart_startup(struct uart_port *port)
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = request_threaded_irq(port->irq, stm32_usart_interrupt,
|
||||
stm32_usart_threaded_interrupt,
|
||||
IRQF_ONESHOT | IRQF_NO_SUSPEND,
|
||||
name, port);
|
||||
ret = request_irq(port->irq, stm32_usart_interrupt,
|
||||
IRQF_NO_SUSPEND, name, port);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -1601,13 +1585,6 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
|
||||
struct dma_slave_config config;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Using DMA and threaded handler for the console could lead to
|
||||
* deadlocks.
|
||||
*/
|
||||
if (uart_console(port))
|
||||
return -ENODEV;
|
||||
|
||||
stm32port->rx_buf = dma_alloc_coherent(dev, RX_BUF_L,
|
||||
&stm32port->rx_dma_buf,
|
||||
GFP_KERNEL);
|
||||
|
@ -386,10 +386,6 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
|
||||
|
||||
uni_mode = use_unicode(inode);
|
||||
attr = use_attributes(inode);
|
||||
ret = -ENXIO;
|
||||
vc = vcs_vc(inode, &viewed);
|
||||
if (!vc)
|
||||
goto unlock_out;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (pos < 0)
|
||||
@ -407,6 +403,11 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
|
||||
unsigned int this_round, skip = 0;
|
||||
int size;
|
||||
|
||||
ret = -ENXIO;
|
||||
vc = vcs_vc(inode, &viewed);
|
||||
if (!vc)
|
||||
goto unlock_out;
|
||||
|
||||
/* Check whether we are above size each round,
|
||||
* as copy_to_user at the end of this loop
|
||||
* could sleep.
|
||||
|
Loading…
Reference in New Issue
Block a user