Re: [PATCH v2] mmc: bcm2835: DMA mapping improvements

Ulf Hansson <[email protected]> Thu, 16 Jul 2026 15:19:05 +0200
Newsgroups org.kernel.vger.linux-mmc
Message-ID <CAPx+jO8ZeheZrOk536XbNVnbLu9ue8kZ8KEDMvnioBsQX2D1Sw@mail.gmail.com>
On Tue, Jul 14, 2026 at 10:45 AM John Garry <[email protected]> wrote:
>
> As pointed out by sashiko bot in [0], recent proposed changes to
> dma_max_mapping_size() may affect the driver.
>
> While the issue reported may be a false positive, Robin pointed out some
> other DMA-related issues in the driver which are addressed here:
> - the DMA max mapping size is irrelevant for the programmed IO mode of
>   operation
> - we should not call dma_max_mapping_size() on the MMC host platform
>   device, but rather the DMA engine device
>
> In addition, it's better to use the device returned from
> dmaengine_get_dma_device() for dma_umap_sg() and dma_unmap_sg(), and not
> reference the DMA channel device directly.
>
> [0] https://lore.kernel.org/linux-scsi/[email protected]/#t
>
> Signed-off-by: John Garry <[email protected]>

Applied for next, thanks!

Kind regards
Uffe

> ---
> Compile tested only, so HW testing also would be preferred - this HW
> seems to be on rpi1 (which I don't have access to).
>
> Differences to v1:
> - fix logic in bcm2835_add_host() (Robin)
> - stop unnecessarily NULLifying dma_dev
> - use dma_dev pointer in bcm2835_dma_complete_work() -> dma_unmap_sg()
>
> diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
> index ee63835b3ca0a..c949a3eaae794 100644
> --- a/drivers/mmc/host/bcm2835.c
> +++ b/drivers/mmc/host/bcm2835.c
> @@ -188,7 +188,7 @@ struct bcm2835_host {
>         u32                     drain_words;
>         struct page             *drain_page;
>         u32                     drain_offset;
> -       bool                    use_dma;
> +       struct device           *dma_dev;
>  };
>
>  static void bcm2835_dumpcmd(struct bcm2835_host *host, struct mmc_command *cmd,
> @@ -494,8 +494,7 @@ void bcm2835_prepare_dma(struct bcm2835_host *host, struct mmc_data *data)
>                                      &host->dma_cfg_rx :
>                                      &host->dma_cfg_tx);
>
> -       sg_len = dma_map_sg(dma_chan->device->dev, data->sg, data->sg_len,
> -                           dir_data);
> +       sg_len = dma_map_sg(host->dma_dev, data->sg, data->sg_len, dir_data);
>         if (!sg_len)
>                 return;
>
> @@ -503,8 +502,7 @@ void bcm2835_prepare_dma(struct bcm2835_host *host, struct mmc_data *data)
>                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
>
>         if (!desc) {
> -               dma_unmap_sg(dma_chan->device->dev, data->sg, data->sg_len,
> -                            dir_data);
> +               dma_unmap_sg(host->dma_dev, data->sg, data->sg_len, dir_data);
>                 return;
>         }
>
> @@ -1057,7 +1055,7 @@ static void bcm2835_dma_complete_work(struct work_struct *work)
>         data = host->data;
>
>         if (host->dma_chan) {
> -               dma_unmap_sg(host->dma_chan->device->dev,
> +               dma_unmap_sg(host->dma_dev,
>                              data->sg, data->sg_len,
>                              host->dma_dir);
>
> @@ -1201,7 +1199,7 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
>                 return;
>         }
>
> -       if (host->use_dma && mrq->data && (mrq->data->blocks > PIO_THRESHOLD))
> +       if (host->dma_dev && mrq->data && (mrq->data->blocks > PIO_THRESHOLD))
>                 bcm2835_prepare_dma(host, mrq->data);
>
>         host->use_sbc = !!mrq->sbc && host->mrq->data &&
> @@ -1281,10 +1279,7 @@ static int bcm2835_add_host(struct bcm2835_host *host)
>
>         if (!host->dma_chan_rxtx) {
>                 dev_warn(dev, "unable to initialise DMA channel. Falling back to PIO\n");
> -               host->use_dma = false;
>         } else {
> -               host->use_dma = true;
> -
>                 host->dma_cfg_tx.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
>                 host->dma_cfg_tx.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
>                 host->dma_cfg_tx.direction = DMA_MEM_TO_DEV;
> @@ -1297,15 +1292,21 @@ static int bcm2835_add_host(struct bcm2835_host *host)
>                 host->dma_cfg_rx.src_addr = host->phys_addr + SDDATA;
>                 host->dma_cfg_rx.dst_addr = 0;
>
> -               if (dmaengine_slave_config(host->dma_chan_rxtx,
> -                                          &host->dma_cfg_tx) != 0 ||
> -                   dmaengine_slave_config(host->dma_chan_rxtx,
> -                                          &host->dma_cfg_rx) != 0)
> -                       host->use_dma = false;
> +               if (!dmaengine_slave_config(host->dma_chan_rxtx,
> +                                          &host->dma_cfg_tx) &&
> +                   !dmaengine_slave_config(host->dma_chan_rxtx,
> +                                          &host->dma_cfg_rx)) {
> +                       host->dma_dev =
> +                               dmaengine_get_dma_device(host->dma_chan_rxtx);
> +               }
>         }
>
>         mmc->max_segs = 128;
> -       mmc->max_req_size = min_t(size_t, 524288, dma_max_mapping_size(dev));
> +       mmc->max_req_size = 524288;
> +       if (host->dma_dev) {
> +               mmc->max_req_size = min_t(size_t, mmc->max_req_size,
> +                               dma_max_mapping_size(host->dma_dev));
> +       }
>         mmc->max_seg_size = mmc->max_req_size;
>         mmc->max_blk_size = 1024;
>         mmc->max_blk_count =  65535;
> @@ -1336,10 +1337,10 @@ static int bcm2835_add_host(struct bcm2835_host *host)
>         }
>
>         pio_limit_string[0] = '\0';
> -       if (host->use_dma && (PIO_THRESHOLD > 0))
> +       if (host->dma_dev && (PIO_THRESHOLD > 0))
>                 sprintf(pio_limit_string, " (>%d)", PIO_THRESHOLD);
>         dev_info(dev, "loaded - DMA %s%s\n",
> -                host->use_dma ? "enabled" : "disabled", pio_limit_string);
> +                host->dma_dev ? "enabled" : "disabled", pio_limit_string);
>
>         return 0;
>  }
> --
> 2.43.7
>