Эх сурвалжийг харах

spi: sh-msiof: Use correct device for DMA mapping with IOMMU

To function correctly in the presence of an IOMMU, the DMA buffers must be
mapped using the DMA channel's device instead of the MSIOF platform
device's device.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Mark Brown <broonie@linaro.org>
Geert Uytterhoeven 11 жил өмнө
parent
commit
5dabcf2f27

+ 16 - 10
drivers/spi/spi-sh-msiof.c

@@ -638,8 +638,8 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
 
 
 	if (tx) {
 	if (tx) {
 		ier_bits |= IER_TDREQE | IER_TDMAE;
 		ier_bits |= IER_TDREQE | IER_TDMAE;
-		dma_sync_single_for_device(&p->pdev->dev, p->tx_dma_addr, len,
-					   DMA_TO_DEVICE);
+		dma_sync_single_for_device(p->master->dma_tx->device->dev,
+					   p->tx_dma_addr, len, DMA_TO_DEVICE);
 		desc_tx = dmaengine_prep_slave_single(p->master->dma_tx,
 		desc_tx = dmaengine_prep_slave_single(p->master->dma_tx,
 					p->tx_dma_addr, len, DMA_TO_DEVICE,
 					p->tx_dma_addr, len, DMA_TO_DEVICE,
 					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
@@ -717,7 +717,8 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
 	}
 	}
 
 
 	if (rx)
 	if (rx)
-		dma_sync_single_for_cpu(&p->pdev->dev, p->rx_dma_addr, len,
+		dma_sync_single_for_cpu(p->master->dma_rx->device->dev,
+					p->rx_dma_addr, len,
 					DMA_FROM_DEVICE);
 					DMA_FROM_DEVICE);
 
 
 	return 0;
 	return 0;
@@ -1003,6 +1004,7 @@ static int sh_msiof_request_dma(struct sh_msiof_spi_priv *p)
 	const struct sh_msiof_spi_info *info = dev_get_platdata(dev);
 	const struct sh_msiof_spi_info *info = dev_get_platdata(dev);
 	const struct resource *res;
 	const struct resource *res;
 	struct spi_master *master;
 	struct spi_master *master;
+	struct device *tx_dev, *rx_dev;
 
 
 	if (!info || !info->dma_tx_id || !info->dma_rx_id)
 	if (!info || !info->dma_tx_id || !info->dma_rx_id)
 		return 0;	/* The driver assumes no error */
 		return 0;	/* The driver assumes no error */
@@ -1033,21 +1035,23 @@ static int sh_msiof_request_dma(struct sh_msiof_spi_priv *p)
 	if (!p->rx_dma_page)
 	if (!p->rx_dma_page)
 		goto free_tx_page;
 		goto free_tx_page;
 
 
-	p->tx_dma_addr = dma_map_single(dev, p->tx_dma_page, PAGE_SIZE,
+	tx_dev = master->dma_tx->device->dev;
+	p->tx_dma_addr = dma_map_single(tx_dev, p->tx_dma_page, PAGE_SIZE,
 					DMA_TO_DEVICE);
 					DMA_TO_DEVICE);
-	if (dma_mapping_error(dev, p->tx_dma_addr))
+	if (dma_mapping_error(tx_dev, p->tx_dma_addr))
 		goto free_rx_page;
 		goto free_rx_page;
 
 
-	p->rx_dma_addr = dma_map_single(dev, p->rx_dma_page, PAGE_SIZE,
+	rx_dev = master->dma_rx->device->dev;
+	p->rx_dma_addr = dma_map_single(rx_dev, p->rx_dma_page, PAGE_SIZE,
 					DMA_FROM_DEVICE);
 					DMA_FROM_DEVICE);
-	if (dma_mapping_error(dev, p->rx_dma_addr))
+	if (dma_mapping_error(rx_dev, p->rx_dma_addr))
 		goto unmap_tx_page;
 		goto unmap_tx_page;
 
 
 	dev_info(dev, "DMA available");
 	dev_info(dev, "DMA available");
 	return 0;
 	return 0;
 
 
 unmap_tx_page:
 unmap_tx_page:
-	dma_unmap_single(dev, p->tx_dma_addr, PAGE_SIZE, DMA_TO_DEVICE);
+	dma_unmap_single(tx_dev, p->tx_dma_addr, PAGE_SIZE, DMA_TO_DEVICE);
 free_rx_page:
 free_rx_page:
 	free_page((unsigned long)p->rx_dma_page);
 	free_page((unsigned long)p->rx_dma_page);
 free_tx_page:
 free_tx_page:
@@ -1069,8 +1073,10 @@ static void sh_msiof_release_dma(struct sh_msiof_spi_priv *p)
 		return;
 		return;
 
 
 	dev = &p->pdev->dev;
 	dev = &p->pdev->dev;
-	dma_unmap_single(dev, p->rx_dma_addr, PAGE_SIZE, DMA_FROM_DEVICE);
-	dma_unmap_single(dev, p->tx_dma_addr, PAGE_SIZE, DMA_TO_DEVICE);
+	dma_unmap_single(master->dma_rx->device->dev, p->rx_dma_addr,
+			 PAGE_SIZE, DMA_FROM_DEVICE);
+	dma_unmap_single(master->dma_tx->device->dev, p->tx_dma_addr,
+			 PAGE_SIZE, DMA_TO_DEVICE);
 	free_page((unsigned long)p->rx_dma_page);
 	free_page((unsigned long)p->rx_dma_page);
 	free_page((unsigned long)p->tx_dma_page);
 	free_page((unsigned long)p->tx_dma_page);
 	dma_release_channel(master->dma_rx);
 	dma_release_channel(master->dma_rx);