Skip to content

Commit

Permalink
spi: sh-msiof: Use correct device for DMA mapping with IOMMU
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Geert Uytterhoeven authored and Mark Brown committed Jul 16, 2014
1 parent 279d237 commit 5dabcf2
Showing 1 changed file with 16 additions and 10 deletions.
26 changes: 16 additions & 10 deletions drivers/spi/spi-sh-msiof.c
Original file line number Diff line number Diff line change
Expand Up @@ -638,8 +638,8 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,

if (tx) {
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,
p->tx_dma_addr, len, DMA_TO_DEVICE,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
Expand Down Expand Up @@ -717,7 +717,8 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
}

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);

return 0;
Expand Down Expand Up @@ -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 resource *res;
struct spi_master *master;
struct device *tx_dev, *rx_dev;

if (!info || !info->dma_tx_id || !info->dma_rx_id)
return 0; /* The driver assumes no error */
Expand Down Expand Up @@ -1033,21 +1035,23 @@ static int sh_msiof_request_dma(struct sh_msiof_spi_priv *p)
if (!p->rx_dma_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);
if (dma_mapping_error(dev, p->tx_dma_addr))
if (dma_mapping_error(tx_dev, p->tx_dma_addr))
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);
if (dma_mapping_error(dev, p->rx_dma_addr))
if (dma_mapping_error(rx_dev, p->rx_dma_addr))
goto unmap_tx_page;

dev_info(dev, "DMA available");
return 0;

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_page((unsigned long)p->rx_dma_page);
free_tx_page:
Expand All @@ -1069,8 +1073,10 @@ static void sh_msiof_release_dma(struct sh_msiof_spi_priv *p)
return;

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->tx_dma_page);
dma_release_channel(master->dma_rx);
Expand Down

0 comments on commit 5dabcf2

Please sign in to comment.