serial: sh-sci: Use correct device for DMA mapping with IOMMU
authorGeert Uytterhoeven <geert+renesas@glider.be>
Fri, 21 Aug 2015 18:02:40 +0000 (20:02 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 4 Oct 2015 16:33:48 +0000 (17:33 +0100)
To function correctly in the presence of an IOMMU, the DMA buffers must
be managed using the DMA channel's device instead of the platform
device's device.

Make sure to free the DMA memory before releasing the channel, not
after.

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

index ea6ab6173ce9f2395c77987b65ce9f2aa161d7f0..9aa9720d7f09d10f3760b7500c2b2767974eb4f0 100644 (file)
@@ -1370,9 +1370,9 @@ static void sci_rx_dma_release(struct sci_port *s, bool enable_pio)
 
        s->chan_rx = NULL;
        s->cookie_rx[0] = s->cookie_rx[1] = -EINVAL;
-       dma_release_channel(chan);
-       dma_free_coherent(port->dev, s->buf_len_rx * 2,
+       dma_free_coherent(chan->device->dev, s->buf_len_rx * 2,
                          sg_virt(&s->sg_rx[0]), sg_dma_address(&s->sg_rx[0]));
+       dma_release_channel(chan);
        if (enable_pio)
                sci_start_rx(port);
 }
@@ -1523,7 +1523,7 @@ static void work_fn_tx(struct work_struct *work)
                return;
        }
 
-       dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE);
+       dma_sync_sg_for_device(chan->device->dev, sg, 1, DMA_TO_DEVICE);
 
        spin_lock_irq(&port->lock);
        s->desc_tx = desc;
@@ -1705,7 +1705,8 @@ static void sci_request_dma(struct uart_port *port)
                sg_set_page(&s->sg_tx, virt_to_page(port->state->xmit.buf),
                            UART_XMIT_SIZE,
                            (uintptr_t)port->state->xmit.buf & ~PAGE_MASK);
-               nent = dma_map_sg(port->dev, &s->sg_tx, 1, DMA_TO_DEVICE);
+               nent = dma_map_sg(chan->device->dev, &s->sg_tx, 1,
+                                 DMA_TO_DEVICE);
                if (!nent) {
                        dev_warn(port->dev, "Failed mapping Tx DMA descriptor\n");
                        dma_release_channel(chan);
@@ -1737,8 +1738,9 @@ static void sci_request_dma(struct uart_port *port)
                s->chan_rx = chan;
 
                s->buf_len_rx = 2 * max(16, (int)port->fifosize);
-               buf[0] = dma_alloc_coherent(port->dev, s->buf_len_rx * 2,
-                                           &dma[0], GFP_KERNEL);
+               buf[0] = dma_alloc_coherent(chan->device->dev,
+                                           s->buf_len_rx * 2, &dma[0],
+                                           GFP_KERNEL);
 
                if (!buf[0]) {
                        dev_warn(port->dev,