Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8e14ba8f authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Greg Kroah-Hartman
Browse files

serial: sh-sci: Use correct device for DMA mapping with IOMMU



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: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
Acked-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent b9258020
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -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,