]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
mmc: sdhci: unmap the bounce buffer before device release
authorMyeonghun Pak <mhun512@gmail.com>
Mon, 27 Jul 2026 14:03:22 +0000 (23:03 +0900)
committerUlf Hansson <ulfh@kernel.org>
Tue, 4 Aug 2026 11:24:20 +0000 (13:24 +0200)
sdhci_allocate_bounce_buffer() allocates its buffer with devm_kmalloc()
but maps it with dma_map_single(). The buffer is therefore released by
devres without the streaming DMA mapping being unmapped.

Register a managed action after dma_map_single() succeeds so the mapping
is removed before devres releases the buffer. The action is registered
only for buffers allocated and mapped by the SDHCI core, leaving buffers
provided by host drivers under their existing ownership.

Fixes: bd9b902798ab ("mmc: sdhci: Implement an SDHCI-specific bounce buffer")
Cc: stable@vger.kernel.org
Co-developed-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Ulf Hansson <ulfh@kernel.org>
drivers/mmc/host/sdhci.c

index e3bf901b10aafbc4b47f49676f88d67ed198b03d..efb4c7742fe21817e96b6f2e6fc4bee526162d2c 100644 (file)
@@ -4187,6 +4187,14 @@ void __sdhci_read_caps(struct sdhci_host *host, const u16 *ver,
 }
 EXPORT_SYMBOL_GPL(__sdhci_read_caps);
 
+static void sdhci_unmap_bounce_buffer(void *data)
+{
+       struct sdhci_host *host = data;
+
+       dma_unmap_single(mmc_dev(host->mmc), host->bounce_addr,
+                        host->bounce_buffer_size, DMA_BIDIRECTIONAL);
+}
+
 static void sdhci_allocate_bounce_buffer(struct sdhci_host *host)
 {
        struct mmc_host *mmc = host->mmc;
@@ -4247,6 +4255,14 @@ static void sdhci_allocate_bounce_buffer(struct sdhci_host *host)
        }
 
        host->bounce_buffer_size = bounce_size;
+       ret = devm_add_action_or_reset(mmc_dev(mmc),
+                                      sdhci_unmap_bounce_buffer, host);
+       if (ret) {
+               devm_kfree(mmc_dev(mmc), host->bounce_buffer);
+               host->bounce_buffer = NULL;
+               host->bounce_buffer_size = 0;
+               return;
+       }
 
 out:
        /* Lie about this since we're bouncing */