serial: sh-sci: Stop TX DMA workqueue during port shutdown
authorGeert Uytterhoeven <geert+renesas@glider.be>
Fri, 6 Jul 2018 09:05:42 +0000 (11:05 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 6 Jul 2018 14:41:15 +0000 (16:41 +0200)
The transmit DMA workqueue is never stopped, hence the work function may
be called after the port has been shut down.

Fix this race condition by cancelling queued work, if any, before DMA
release.  Don't initialize the work if DMA initialization failed, as it
won't be used anyway.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/sh-sci.c

index c5c891c8714e2836c59299aa53fa8f7b786d7828..f3432cca3fdcb9d3c449920835afe4ea4edddb91 100644 (file)
@@ -1293,6 +1293,7 @@ static void sci_tx_dma_release(struct sci_port *s)
 {
        struct dma_chan *chan = s->chan_tx_saved;
 
+       cancel_work_sync(&s->work_tx);
        s->chan_tx_saved = s->chan_tx = NULL;
        s->cookie_tx = -EINVAL;
        dmaengine_terminate_all(chan);
@@ -1548,10 +1549,9 @@ static void sci_request_dma(struct uart_port *port)
                                __func__, UART_XMIT_SIZE,
                                port->state->xmit.buf, &s->tx_dma_addr);
 
+                       INIT_WORK(&s->work_tx, work_fn_tx);
                        s->chan_tx_saved = s->chan_tx = chan;
                }
-
-               INIT_WORK(&s->work_tx, work_fn_tx);
        }
 
        chan = sci_request_dma_chan(port, DMA_DEV_TO_MEM);