mmc: mmc_spi: Allow the driver to be built when CONFIG_HAS_DMA is unset
The commitcd57d07b1e
("sh: don't allow non-coherent DMA for NOMMU") made CONFIG_NO_DMA to be set for some platforms, for good reasons. Consequentially, CONFIG_HAS_DMA doesn't get set, which makes the DMA mapping interface to be built as stub functions, but also prevent the mmc_spi driver from being built as it depends on CONFIG_HAS_DMA. It turns out that for some odd cases, the driver still relied on the DMA mapping interface, even if the DMA was not actively being used. To fixup the behaviour, let's drop the build dependency for CONFIG_HAS_DMA. Moreover, as to allow the driver to succeed probing, let's move the DMA initializations behind "#ifdef CONFIG_HAS_DMA". Fixes:cd57d07b1e
("sh: don't allow non-coherent DMA for NOMMU") Reported-by: Rich Felker <dalias@libc.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Tested-by: Rich Felker <dalias@libc.org> Link: https://lore.kernel.org/r/20200901150438.228887-1-ulf.hansson@linaro.org
This commit is contained in:
parent
9d5dcefb7b
commit
a395acf0f6
@ -602,7 +602,7 @@ config MMC_GOLDFISH
|
||||
|
||||
config MMC_SPI
|
||||
tristate "MMC/SD/SDIO over SPI"
|
||||
depends on SPI_MASTER && HAS_DMA
|
||||
depends on SPI_MASTER
|
||||
select CRC7
|
||||
select CRC_ITU_T
|
||||
help
|
||||
|
@ -1278,6 +1278,52 @@ mmc_spi_detect_irq(int irq, void *mmc)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAS_DMA
|
||||
static int mmc_spi_dma_alloc(struct mmc_spi_host *host)
|
||||
{
|
||||
struct spi_device *spi = host->spi;
|
||||
struct device *dev;
|
||||
|
||||
if (!spi->master->dev.parent->dma_mask)
|
||||
return 0;
|
||||
|
||||
dev = spi->master->dev.parent;
|
||||
|
||||
host->ones_dma = dma_map_single(dev, host->ones, MMC_SPI_BLOCKSIZE,
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(dev, host->ones_dma))
|
||||
return -ENOMEM;
|
||||
|
||||
host->data_dma = dma_map_single(dev, host->data, sizeof(*host->data),
|
||||
DMA_BIDIRECTIONAL);
|
||||
if (dma_mapping_error(dev, host->data_dma)) {
|
||||
dma_unmap_single(dev, host->ones_dma, MMC_SPI_BLOCKSIZE,
|
||||
DMA_TO_DEVICE);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dma_sync_single_for_cpu(dev, host->data_dma, sizeof(*host->data),
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
host->dma_dev = dev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mmc_spi_dma_free(struct mmc_spi_host *host)
|
||||
{
|
||||
if (!host->dma_dev)
|
||||
return;
|
||||
|
||||
dma_unmap_single(host->dma_dev, host->ones_dma, MMC_SPI_BLOCKSIZE,
|
||||
DMA_TO_DEVICE);
|
||||
dma_unmap_single(host->dma_dev, host->data_dma, sizeof(*host->data),
|
||||
DMA_BIDIRECTIONAL);
|
||||
}
|
||||
#else
|
||||
static inline mmc_spi_dma_alloc(struct mmc_spi_host *host) { return 0; }
|
||||
static inline void mmc_spi_dma_free(struct mmc_spi_host *host) {}
|
||||
#endif
|
||||
|
||||
static int mmc_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
void *ones;
|
||||
@ -1374,23 +1420,9 @@ static int mmc_spi_probe(struct spi_device *spi)
|
||||
if (!host->data)
|
||||
goto fail_nobuf1;
|
||||
|
||||
if (spi->master->dev.parent->dma_mask) {
|
||||
struct device *dev = spi->master->dev.parent;
|
||||
|
||||
host->dma_dev = dev;
|
||||
host->ones_dma = dma_map_single(dev, ones,
|
||||
MMC_SPI_BLOCKSIZE, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(dev, host->ones_dma))
|
||||
goto fail_ones_dma;
|
||||
host->data_dma = dma_map_single(dev, host->data,
|
||||
sizeof(*host->data), DMA_BIDIRECTIONAL);
|
||||
if (dma_mapping_error(dev, host->data_dma))
|
||||
goto fail_data_dma;
|
||||
|
||||
dma_sync_single_for_cpu(host->dma_dev,
|
||||
host->data_dma, sizeof(*host->data),
|
||||
DMA_BIDIRECTIONAL);
|
||||
}
|
||||
status = mmc_spi_dma_alloc(host);
|
||||
if (status)
|
||||
goto fail_dma;
|
||||
|
||||
/* setup message for status/busy readback */
|
||||
spi_message_init(&host->readback);
|
||||
@ -1458,20 +1490,12 @@ static int mmc_spi_probe(struct spi_device *spi)
|
||||
fail_add_host:
|
||||
mmc_remove_host(mmc);
|
||||
fail_glue_init:
|
||||
if (host->dma_dev)
|
||||
dma_unmap_single(host->dma_dev, host->data_dma,
|
||||
sizeof(*host->data), DMA_BIDIRECTIONAL);
|
||||
fail_data_dma:
|
||||
if (host->dma_dev)
|
||||
dma_unmap_single(host->dma_dev, host->ones_dma,
|
||||
MMC_SPI_BLOCKSIZE, DMA_TO_DEVICE);
|
||||
fail_ones_dma:
|
||||
mmc_spi_dma_free(host);
|
||||
fail_dma:
|
||||
kfree(host->data);
|
||||
|
||||
fail_nobuf1:
|
||||
mmc_free_host(mmc);
|
||||
mmc_spi_put_pdata(spi);
|
||||
|
||||
nomem:
|
||||
kfree(ones);
|
||||
return status;
|
||||
@ -1489,13 +1513,7 @@ static int mmc_spi_remove(struct spi_device *spi)
|
||||
|
||||
mmc_remove_host(mmc);
|
||||
|
||||
if (host->dma_dev) {
|
||||
dma_unmap_single(host->dma_dev, host->ones_dma,
|
||||
MMC_SPI_BLOCKSIZE, DMA_TO_DEVICE);
|
||||
dma_unmap_single(host->dma_dev, host->data_dma,
|
||||
sizeof(*host->data), DMA_BIDIRECTIONAL);
|
||||
}
|
||||
|
||||
mmc_spi_dma_free(host);
|
||||
kfree(host->data);
|
||||
kfree(host->ones);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user