From patchwork Fri Feb 14 07:40:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 236336 List-Id: U-Boot discussion From: yamada.masahiro at socionext.com (Masahiro Yamada) Date: Fri, 14 Feb 2020 16:40:17 +0900 Subject: [PATCH v3 01/11] dma-mapping: fix the prototype of dma_map_single() In-Reply-To: <20200214074027.19824-1-yamada.masahiro@socionext.com> References: <20200214074027.19824-1-yamada.masahiro@socionext.com> Message-ID: <20200214074027.19824-2-yamada.masahiro@socionext.com> Make dma_map_single() return the dma address, and remove the pointless volatile. Signed-off-by: Masahiro Yamada --- Changes in v3: None Changes in v2: None arch/arm/include/asm/dma-mapping.h | 5 +++-- arch/nds32/include/asm/dma-mapping.h | 5 +++-- arch/riscv/include/asm/dma-mapping.h | 5 +++-- arch/x86/include/asm/dma-mapping.h | 5 +++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index d20703739fad..d0895a209666 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #define dma_mapping_error(x, y) 0 @@ -26,8 +27,8 @@ static inline void dma_free_coherent(void *addr) free(addr); } -static inline unsigned long dma_map_single(volatile void *vaddr, size_t len, - enum dma_data_direction dir) +static inline dma_addr_t dma_map_single(void *vaddr, size_t len, + enum dma_data_direction dir) { unsigned long addr = (unsigned long)vaddr; diff --git a/arch/nds32/include/asm/dma-mapping.h b/arch/nds32/include/asm/dma-mapping.h index c8876ceadda6..9387dec34768 100644 --- a/arch/nds32/include/asm/dma-mapping.h +++ b/arch/nds32/include/asm/dma-mapping.h @@ -10,6 +10,7 @@ #include #include #include +#include #include static void *dma_alloc_coherent(size_t len, unsigned long *handle) @@ -18,8 +19,8 @@ static void *dma_alloc_coherent(size_t len, unsigned long *handle) return (void *)*handle; } -static inline unsigned long dma_map_single(volatile void *vaddr, size_t len, - enum dma_data_direction dir) +static inline dma_addr_t dma_map_single(void *vaddr, size_t len, + enum dma_data_direction dir) { unsigned long addr = (unsigned long)vaddr; diff --git a/arch/riscv/include/asm/dma-mapping.h b/arch/riscv/include/asm/dma-mapping.h index 6cc39469590a..eac56f8fbdfa 100644 --- a/arch/riscv/include/asm/dma-mapping.h +++ b/arch/riscv/include/asm/dma-mapping.h @@ -10,6 +10,7 @@ #define __ASM_RISCV_DMA_MAPPING_H #include +#include #include #include #include @@ -28,8 +29,8 @@ static inline void dma_free_coherent(void *addr) free(addr); } -static inline unsigned long dma_map_single(volatile void *vaddr, size_t len, - enum dma_data_direction dir) +static inline dma_addr_t dma_map_single(void *vaddr, size_t len, + enum dma_data_direction dir) { unsigned long addr = (unsigned long)vaddr; diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h index 900b99b8a69a..7e205e3313ac 100644 --- a/arch/x86/include/asm/dma-mapping.h +++ b/arch/x86/include/asm/dma-mapping.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #define dma_mapping_error(x, y) 0 @@ -26,8 +27,8 @@ static inline void dma_free_coherent(void *addr) free(addr); } -static inline unsigned long dma_map_single(volatile void *vaddr, size_t len, - enum dma_data_direction dir) +static inline dma_addr_t dma_map_single(void *vaddr, size_t len, + enum dma_data_direction dir) { unsigned long addr = (unsigned long)vaddr; From patchwork Fri Feb 14 07:40:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 236339 List-Id: U-Boot discussion From: yamada.masahiro at socionext.com (Masahiro Yamada) Date: Fri, 14 Feb 2020 16:40:18 +0900 Subject: [PATCH v3 02/11] dma-mapping: fix the prototype of dma_unmap_single() In-Reply-To: <20200214074027.19824-1-yamada.masahiro@socionext.com> References: <20200214074027.19824-1-yamada.masahiro@socionext.com> Message-ID: <20200214074027.19824-3-yamada.masahiro@socionext.com> dma_unmap_single() takes the dma address, not virtual address. Signed-off-by: Masahiro Yamada --- Changes in v3: None Changes in v2: None arch/arm/include/asm/dma-mapping.h | 4 +--- arch/nds32/include/asm/dma-mapping.h | 4 +--- arch/riscv/include/asm/dma-mapping.h | 4 +--- arch/x86/include/asm/dma-mapping.h | 4 +--- drivers/mmc/tmio-common.c | 2 +- drivers/mtd/nand/raw/denali.c | 2 +- drivers/net/macb.c | 2 +- drivers/usb/dwc3/core.c | 6 +++--- drivers/usb/gadget/udc/udc-core.c | 2 +- 9 files changed, 11 insertions(+), 19 deletions(-) diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index d0895a209666..efdbed7280dd 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -42,11 +42,9 @@ static inline dma_addr_t dma_map_single(void *vaddr, size_t len, return addr; } -static inline void dma_unmap_single(volatile void *vaddr, size_t len, +static inline void dma_unmap_single(dma_addr_t addr, size_t len, enum dma_data_direction dir) { - unsigned long addr = (unsigned long)vaddr; - len = ALIGN(len, ARCH_DMA_MINALIGN); if (dir != DMA_TO_DEVICE) diff --git a/arch/nds32/include/asm/dma-mapping.h b/arch/nds32/include/asm/dma-mapping.h index 9387dec34768..784f489db54e 100644 --- a/arch/nds32/include/asm/dma-mapping.h +++ b/arch/nds32/include/asm/dma-mapping.h @@ -34,11 +34,9 @@ static inline dma_addr_t dma_map_single(void *vaddr, size_t len, return addr; } -static inline void dma_unmap_single(volatile void *vaddr, size_t len, +static inline void dma_unmap_single(dma_addr_t addr, size_t len, enum dma_data_direction dir) { - unsigned long addr = (unsigned long)vaddr; - len = ALIGN(len, ARCH_DMA_MINALIGN); if (dir != DMA_TO_DEVICE) diff --git a/arch/riscv/include/asm/dma-mapping.h b/arch/riscv/include/asm/dma-mapping.h index eac56f8fbdfa..1ac4a4fed58d 100644 --- a/arch/riscv/include/asm/dma-mapping.h +++ b/arch/riscv/include/asm/dma-mapping.h @@ -44,11 +44,9 @@ static inline dma_addr_t dma_map_single(void *vaddr, size_t len, return addr; } -static inline void dma_unmap_single(volatile void *vaddr, size_t len, +static inline void dma_unmap_single(dma_addr_t addr, size_t len, enum dma_data_direction dir) { - unsigned long addr = (unsigned long)vaddr; - len = ALIGN(len, ARCH_DMA_MINALIGN); if (dir != DMA_TO_DEVICE) diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h index 7e205e3313ac..37704da5dd4f 100644 --- a/arch/x86/include/asm/dma-mapping.h +++ b/arch/x86/include/asm/dma-mapping.h @@ -42,11 +42,9 @@ static inline dma_addr_t dma_map_single(void *vaddr, size_t len, return addr; } -static inline void dma_unmap_single(volatile void *vaddr, size_t len, +static inline void dma_unmap_single(dma_addr_t addr, size_t len, enum dma_data_direction dir) { - unsigned long addr = (unsigned long)vaddr; - len = ALIGN(len, ARCH_DMA_MINALIGN); if (dir != DMA_TO_DEVICE) diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 092b740f564e..53213888473b 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -353,7 +353,7 @@ static int tmio_sd_dma_xfer(struct udevice *dev, struct mmc_data *data) if (poll_flag == TMIO_SD_DMA_INFO1_END_RD) udelay(1); - dma_unmap_single(buf, len, dir); + dma_unmap_single(dma_addr, len, dir); return ret; } diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index f51d3e25c762..3e0ac39777d8 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -581,7 +581,7 @@ static int denali_dma_xfer(struct denali_nand_info *denali, void *buf, iowrite32(0, denali->reg + DMA_ENABLE); - dma_unmap_single(buf, size, dir); + dma_unmap_single(dma_addr, size, dir); if (irq_status & INTR__ERASED_PAGE) memset(buf, 0xff, size); diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 0d4929bec131..7a2b1abeeb03 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -342,7 +342,7 @@ static int _macb_send(struct macb_device *macb, const char *name, void *packet, udelay(1); } - dma_unmap_single(packet, length, DMA_TO_DEVICE); + dma_unmap_single(paddr, length, DMA_TO_DEVICE); if (i <= MACB_TX_TIMEOUT) { if (ctrl & MACB_BIT(TX_UNDERRUN)) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c5066529b7d0..6ad1000c9af6 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -288,8 +288,8 @@ static int dwc3_setup_scratch_buffers(struct dwc3 *dwc) return 0; err1: - dma_unmap_single((void *)(uintptr_t)dwc->scratch_addr, dwc->nr_scratch * - DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); + dma_unmap_single(scratch_addr, dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, + DMA_BIDIRECTIONAL); err0: return ret; @@ -303,7 +303,7 @@ static void dwc3_free_scratch_buffers(struct dwc3 *dwc) if (!dwc->nr_scratch) return; - dma_unmap_single((void *)(uintptr_t)dwc->scratch_addr, dwc->nr_scratch * + dma_unmap_single(dwc->scratch_addr, dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); kfree(dwc->scratchbuf); } diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index a33ab5c95d4e..528874507b41 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -67,7 +67,7 @@ void usb_gadget_unmap_request(struct usb_gadget *gadget, if (req->length == 0) return; - dma_unmap_single((void *)(uintptr_t)req->dma, req->length, + dma_unmap_single(req->dma, req->length, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); } EXPORT_SYMBOL_GPL(usb_gadget_unmap_request); From patchwork Fri Feb 14 07:40:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 236337 List-Id: U-Boot discussion From: yamada.masahiro at socionext.com (Masahiro Yamada) Date: Fri, 14 Feb 2020 16:40:19 +0900 Subject: [PATCH v3 03/11] dma-mapping: move dma_map_(un)single() to In-Reply-To: <20200214074027.19824-1-yamada.masahiro@socionext.com> References: <20200214074027.19824-1-yamada.masahiro@socionext.com> Message-ID: <20200214074027.19824-4-yamada.masahiro@socionext.com> The implementation of dma_map_single() and dma_unmap_single() is exactly the same for all the architectures that support them. Factor them out to , and make all drivers to include instead of . If we need to differentiate them for some architectures, we can move the generic definitions to . Add some comments to the helpers. The concept is quite similar to the DMA-API of Linux kernel. Drivers are agnostic about what is going on behind the scene. Just call dma_map_single() before the DMA, and dma_unmap_single() after it. Signed-off-by: Masahiro Yamada --- Changes in v3: - Rebase Changes in v2: - New patch arch/arm/include/asm/dma-mapping.h | 26 ------------ arch/nds32/include/asm/dma-mapping.h | 24 ----------- arch/riscv/include/asm/dma-mapping.h | 26 ------------ arch/x86/include/asm/dma-mapping.h | 26 ------------ drivers/dma/ti/k3-udma.c | 2 +- drivers/mmc/tmio-common.c | 3 +- drivers/mtd/nand/raw/denali.c | 3 +- drivers/net/altera_tse.c | 2 +- drivers/net/ftmac110.c | 2 +- drivers/net/macb.c | 2 +- drivers/soc/ti/k3-navss-ringacc.c | 2 +- drivers/ufs/ufs.c | 2 +- drivers/usb/cdns3/gadget.c | 2 +- drivers/usb/dwc3/core.c | 2 +- drivers/usb/dwc3/gadget.c | 2 +- drivers/usb/gadget/udc/udc-core.c | 2 +- include/linux/dma-mapping.h | 63 ++++++++++++++++++++++++++++ 17 files changed, 75 insertions(+), 116 deletions(-) create mode 100644 include/linux/dma-mapping.h diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index efdbed7280dd..8bb3fa2e0ee7 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -14,8 +14,6 @@ #include #include -#define dma_mapping_error(x, y) 0 - static inline void *dma_alloc_coherent(size_t len, unsigned long *handle) { *handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, ROUND(len, ARCH_DMA_MINALIGN)); @@ -27,28 +25,4 @@ static inline void dma_free_coherent(void *addr) free(addr); } -static inline dma_addr_t dma_map_single(void *vaddr, size_t len, - enum dma_data_direction dir) -{ - unsigned long addr = (unsigned long)vaddr; - - len = ALIGN(len, ARCH_DMA_MINALIGN); - - if (dir == DMA_FROM_DEVICE) - invalidate_dcache_range(addr, addr + len); - else - flush_dcache_range(addr, addr + len); - - return addr; -} - -static inline void dma_unmap_single(dma_addr_t addr, size_t len, - enum dma_data_direction dir) -{ - len = ALIGN(len, ARCH_DMA_MINALIGN); - - if (dir != DMA_TO_DEVICE) - invalidate_dcache_range(addr, addr + len); -} - #endif /* __ASM_ARM_DMA_MAPPING_H */ diff --git a/arch/nds32/include/asm/dma-mapping.h b/arch/nds32/include/asm/dma-mapping.h index 784f489db54e..f8668f1fe5db 100644 --- a/arch/nds32/include/asm/dma-mapping.h +++ b/arch/nds32/include/asm/dma-mapping.h @@ -19,28 +19,4 @@ static void *dma_alloc_coherent(size_t len, unsigned long *handle) return (void *)*handle; } -static inline dma_addr_t dma_map_single(void *vaddr, size_t len, - enum dma_data_direction dir) -{ - unsigned long addr = (unsigned long)vaddr; - - len = ALIGN(len, ARCH_DMA_MINALIGN); - - if (dir == DMA_FROM_DEVICE) - invalidate_dcache_range(addr, addr + len); - else - flush_dcache_range(addr, addr + len); - - return addr; -} - -static inline void dma_unmap_single(dma_addr_t addr, size_t len, - enum dma_data_direction dir) -{ - len = ALIGN(len, ARCH_DMA_MINALIGN); - - if (dir != DMA_TO_DEVICE) - invalidate_dcache_range(addr, addr + len); -} - #endif /* __ASM_NDS_DMA_MAPPING_H */ diff --git a/arch/riscv/include/asm/dma-mapping.h b/arch/riscv/include/asm/dma-mapping.h index 1ac4a4fed58d..6ecadab41cd9 100644 --- a/arch/riscv/include/asm/dma-mapping.h +++ b/arch/riscv/include/asm/dma-mapping.h @@ -16,8 +16,6 @@ #include #include -#define dma_mapping_error(x, y) 0 - static inline void *dma_alloc_coherent(size_t len, unsigned long *handle) { *handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len); @@ -29,28 +27,4 @@ static inline void dma_free_coherent(void *addr) free(addr); } -static inline dma_addr_t dma_map_single(void *vaddr, size_t len, - enum dma_data_direction dir) -{ - unsigned long addr = (unsigned long)vaddr; - - len = ALIGN(len, ARCH_DMA_MINALIGN); - - if (dir == DMA_FROM_DEVICE) - invalidate_dcache_range(addr, addr + len); - else - flush_dcache_range(addr, addr + len); - - return addr; -} - -static inline void dma_unmap_single(dma_addr_t addr, size_t len, - enum dma_data_direction dir) -{ - len = ALIGN(len, ARCH_DMA_MINALIGN); - - if (dir != DMA_TO_DEVICE) - invalidate_dcache_range(addr, addr + len); -} - #endif /* __ASM_RISCV_DMA_MAPPING_H */ diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h index 37704da5dd4f..8be1003e6baf 100644 --- a/arch/x86/include/asm/dma-mapping.h +++ b/arch/x86/include/asm/dma-mapping.h @@ -14,8 +14,6 @@ #include #include -#define dma_mapping_error(x, y) 0 - static inline void *dma_alloc_coherent(size_t len, unsigned long *handle) { *handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len); @@ -27,28 +25,4 @@ static inline void dma_free_coherent(void *addr) free(addr); } -static inline dma_addr_t dma_map_single(void *vaddr, size_t len, - enum dma_data_direction dir) -{ - unsigned long addr = (unsigned long)vaddr; - - len = ALIGN(len, ARCH_DMA_MINALIGN); - - if (dir == DMA_FROM_DEVICE) - invalidate_dcache_range(addr, addr + len); - else - flush_dcache_range(addr, addr + len); - - return addr; -} - -static inline void dma_unmap_single(dma_addr_t addr, size_t len, - enum dma_data_direction dir) -{ - len = ALIGN(len, ARCH_DMA_MINALIGN); - - if (dir != DMA_TO_DEVICE) - invalidate_dcache_range(addr, addr + len); -} - #endif /* __ASM_X86_DMA_MAPPING_H */ diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index f274100f3222..e587f1fcb2b4 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 53213888473b..faf18191b30d 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -4,7 +4,6 @@ * Author: Masahiro Yamada */ -#include #include #include #include @@ -14,7 +13,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 3e0ac39777d8..b525b1be5496 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -5,14 +5,13 @@ * Copyright (C) 2009-2010, Intel Corporation and its suppliers. */ -#include #include #include #include #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/altera_tse.c b/drivers/net/altera_tse.c index aabddd6bb698..a511068d9ae1 100644 --- a/drivers/net/altera_tse.c +++ b/drivers/net/altera_tse.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include "altera_tse.h" diff --git a/drivers/net/ftmac110.c b/drivers/net/ftmac110.c index 1fa93d4d5855..84082407d277 100644 --- a/drivers/net/ftmac110.c +++ b/drivers/net/ftmac110.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) #include diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 7a2b1abeeb03..631b53b0930a 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -38,7 +38,7 @@ #include #include -#include +#include #include #include diff --git a/drivers/soc/ti/k3-navss-ringacc.c b/drivers/soc/ti/k3-navss-ringacc.c index 8cbfe2bf49c3..c5661c52facc 100644 --- a/drivers/soc/ti/k3-navss-ringacc.c +++ b/drivers/soc/ti/k3-navss-ringacc.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -17,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index c9346c2edc8f..24e1bc2a19c2 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -19,7 +19,7 @@ #include #include -#include +#include #include "ufs.h" diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c index 22e90a57179f..8377eb458b6a 100644 --- a/drivers/usb/cdns3/gadget.c +++ b/drivers/usb/cdns3/gadget.c @@ -63,7 +63,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 6ad1000c9af6..4ec3f6df6a9a 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -17,9 +17,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 1502d67362a9..e445c705f18e 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -16,10 +16,10 @@ #include #include #include -#include #include #include #include +#include #include #include diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index 528874507b41..7f73926cb3e1 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h new file mode 100644 index 000000000000..20b6d60dd880 --- /dev/null +++ b/include/linux/dma-mapping.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_DMA_MAPPING_H +#define _LINUX_DMA_MAPPING_H + +#include +#include +#include +#include + +#define dma_mapping_error(x, y) 0 + +/** + * Map a buffer to make it available to the DMA device + * + * Linux-like DMA API that is intended to be used from drivers. This hides the + * underlying cache operation from drivers. Call this before starting the DMA + * transfer. In most of architectures in U-Boot, the virtual address matches to + * the physical address (but we have exceptions like sandbox). U-Boot does not + * support iommu at the driver level, so it also matches to the DMA address. + * Hence, this helper currently just performs the cache operation, then returns + * straight-mapped dma_address, which is intended to be set to the register of + * the DMA device. + * + * @vaddr: address of the buffer + * @len: length of the buffer + * @dir: the direction of DMA + */ +static inline dma_addr_t dma_map_single(void *vaddr, size_t len, + enum dma_data_direction dir) +{ + unsigned long addr = (unsigned long)vaddr; + + len = ALIGN(len, ARCH_DMA_MINALIGN); + + if (dir == DMA_FROM_DEVICE) + invalidate_dcache_range(addr, addr + len); + else + flush_dcache_range(addr, addr + len); + + return addr; +} + +/** + * Unmap a buffer to make it available to CPU + * + * Linux-like DMA API that is intended to be used from drivers. This hides the + * underlying cache operation from drivers. Call this after finishin the DMA + * transfer. + * + * @addr: DMA address + * @len: length of the buffer + * @dir: the direction of DMA + */ +static inline void dma_unmap_single(dma_addr_t addr, size_t len, + enum dma_data_direction dir) +{ + len = ALIGN(len, ARCH_DMA_MINALIGN); + + if (dir != DMA_TO_DEVICE) + invalidate_dcache_range(addr, addr + len); +} + +#endif From patchwork Fri Feb 14 07:40:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 236343 List-Id: U-Boot discussion From: yamada.masahiro at socionext.com (Masahiro Yamada) Date: Fri, 14 Feb 2020 16:40:20 +0900 Subject: [PATCH v3 04/11] dma-mapping: add for all architectures In-Reply-To: <20200214074027.19824-1-yamada.masahiro@socionext.com> References: <20200214074027.19824-1-yamada.masahiro@socionext.com> Message-ID: <20200214074027.19824-5-yamada.masahiro@socionext.com> To avoid "asm/dma-mapping.h: No such file or directory" error, we need something. Signed-off-by: Masahiro Yamada --- Changes in v3: None Changes in v2: - New patch arch/arc/include/asm/dma-mapping.h | 1 + arch/m68k/include/asm/dma-mapping.h | 1 + arch/microblaze/include/asm/dma-mapping.h | 1 + arch/mips/include/asm/dma-mapping.h | 1 + arch/nios2/include/asm/dma-mapping.h | 25 +---------------------- arch/powerpc/include/asm/dma-mapping.h | 1 + arch/sandbox/include/asm/dma-mapping.h | 1 + arch/sh/include/asm/dma-mapping.h | 1 + arch/xtensa/include/asm/dma-mapping.h | 1 + 9 files changed, 9 insertions(+), 24 deletions(-) create mode 100644 arch/arc/include/asm/dma-mapping.h create mode 100644 arch/m68k/include/asm/dma-mapping.h create mode 100644 arch/microblaze/include/asm/dma-mapping.h create mode 100644 arch/mips/include/asm/dma-mapping.h create mode 100644 arch/powerpc/include/asm/dma-mapping.h create mode 100644 arch/sandbox/include/asm/dma-mapping.h create mode 100644 arch/sh/include/asm/dma-mapping.h create mode 100644 arch/xtensa/include/asm/dma-mapping.h diff --git a/arch/arc/include/asm/dma-mapping.h b/arch/arc/include/asm/dma-mapping.h new file mode 100644 index 000000000000..853b0877b33d --- /dev/null +++ b/arch/arc/include/asm/dma-mapping.h @@ -0,0 +1 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ diff --git a/arch/m68k/include/asm/dma-mapping.h b/arch/m68k/include/asm/dma-mapping.h new file mode 100644 index 000000000000..853b0877b33d --- /dev/null +++ b/arch/m68k/include/asm/dma-mapping.h @@ -0,0 +1 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ diff --git a/arch/microblaze/include/asm/dma-mapping.h b/arch/microblaze/include/asm/dma-mapping.h new file mode 100644 index 000000000000..853b0877b33d --- /dev/null +++ b/arch/microblaze/include/asm/dma-mapping.h @@ -0,0 +1 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h new file mode 100644 index 000000000000..853b0877b33d --- /dev/null +++ b/arch/mips/include/asm/dma-mapping.h @@ -0,0 +1 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ diff --git a/arch/nios2/include/asm/dma-mapping.h b/arch/nios2/include/asm/dma-mapping.h index 65f67bc1f442..853b0877b33d 100644 --- a/arch/nios2/include/asm/dma-mapping.h +++ b/arch/nios2/include/asm/dma-mapping.h @@ -1,24 +1 @@ -#ifndef __ASM_NIOS2_DMA_MAPPING_H -#define __ASM_NIOS2_DMA_MAPPING_H - -#include -#include - -/* - * dma_alloc_coherent() return cache-line aligned allocation which is mapped - * to uncached io region. - */ -static inline void *dma_alloc_coherent(size_t len, unsigned long *handle) -{ - unsigned long addr = (unsigned long)malloc_cache_aligned(len); - - if (!addr) - return NULL; - - invalidate_dcache_range(addr, addr + len); - if (handle) - *handle = addr; - - return map_physmem(addr, len, MAP_NOCACHE); -} -#endif /* __ASM_NIOS2_DMA_MAPPING_H */ +/* SPDX-License-Identifier: GPL-2.0-only */ diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h new file mode 100644 index 000000000000..853b0877b33d --- /dev/null +++ b/arch/powerpc/include/asm/dma-mapping.h @@ -0,0 +1 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ diff --git a/arch/sandbox/include/asm/dma-mapping.h b/arch/sandbox/include/asm/dma-mapping.h new file mode 100644 index 000000000000..853b0877b33d --- /dev/null +++ b/arch/sandbox/include/asm/dma-mapping.h @@ -0,0 +1 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ diff --git a/arch/sh/include/asm/dma-mapping.h b/arch/sh/include/asm/dma-mapping.h new file mode 100644 index 000000000000..853b0877b33d --- /dev/null +++ b/arch/sh/include/asm/dma-mapping.h @@ -0,0 +1 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ diff --git a/arch/xtensa/include/asm/dma-mapping.h b/arch/xtensa/include/asm/dma-mapping.h new file mode 100644 index 000000000000..853b0877b33d --- /dev/null +++ b/arch/xtensa/include/asm/dma-mapping.h @@ -0,0 +1 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ From patchwork Fri Feb 14 07:40:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 236342 List-Id: U-Boot discussion From: yamada.masahiro at socionext.com (Masahiro Yamada) Date: Fri, 14 Feb 2020 16:40:21 +0900 Subject: [PATCH v3 05/11] mmc: sdhci: put the aligned buffer pointer to struct sdhci_host In-Reply-To: <20200214074027.19824-1-yamada.masahiro@socionext.com> References: <20200214074027.19824-1-yamada.masahiro@socionext.com> Message-ID: <20200214074027.19824-6-yamada.masahiro@socionext.com> Using the global variable does not look nice. Add a new field sthci::align_buffer to point to the bounce buffer. Signed-off-by: Masahiro Yamada Reviewed-by: Jaehoon Chung --- Changes in v3: None Changes in v2: None drivers/mmc/sdhci.c | 27 +++++++++++++-------------- include/sdhci.h | 1 + 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 01fa5a9d4d5b..18fbcb5f1864 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -16,12 +16,6 @@ #include #include -#if defined(CONFIG_FIXED_SDHCI_ALIGNED_BUFFER) -void *aligned_buffer = (void *)CONFIG_FIXED_SDHCI_ALIGNED_BUFFER; -#else -void *aligned_buffer; -#endif - static void sdhci_reset(struct sdhci_host *host, u8 mask) { unsigned long timeout; @@ -149,9 +143,10 @@ static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data, if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) && (host->start_addr & 0x7) != 0x0) { *is_aligned = 0; - host->start_addr = (unsigned long)aligned_buffer; + host->start_addr = (unsigned long)host->align_buffer; if (data->flags != MMC_DATA_READ) - memcpy(aligned_buffer, data->src, trans_bytes); + memcpy(host->align_buffer, data->src, + trans_bytes); } #if defined(CONFIG_FIXED_SDHCI_ALIGNED_BUFFER) @@ -160,9 +155,9 @@ static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data, * CONFIG_FIXED_SDHCI_ALIGNED_BUFFER is defined */ *is_aligned = 0; - host->start_addr = (unsigned long)aligned_buffer; + host->start_addr = (unsigned long)host->align_buffer; if (data->flags != MMC_DATA_READ) - memcpy(aligned_buffer, data->src, trans_bytes); + memcpy(host->align_buffer, data->src, trans_bytes); #endif sdhci_writel(host, host->start_addr, SDHCI_DMA_ADDRESS); @@ -381,7 +376,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, if (!ret) { if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) && !is_aligned && (data->flags == MMC_DATA_READ)) - memcpy(data->dest, aligned_buffer, trans_bytes); + memcpy(data->dest, host->align_buffer, trans_bytes); return 0; } @@ -630,14 +625,18 @@ static int sdhci_init(struct mmc *mmc) sdhci_reset(host, SDHCI_RESET_ALL); - if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) && !aligned_buffer) { - aligned_buffer = memalign(8, 512*1024); - if (!aligned_buffer) { +#if defined(CONFIG_FIXED_SDHCI_ALIGNED_BUFFER) + host->align_buffer = (void *)CONFIG_FIXED_SDHCI_ALIGNED_BUFFER; +#else + if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) { + host->align_buffer = memalign(8, 512 * 1024); + if (!host->align_buffer) { printf("%s: Aligned buffer alloc failed!!!\n", __func__); return -ENOMEM; } } +#endif sdhci_set_power(host, fls(mmc->cfg->voltages) - 1); diff --git a/include/sdhci.h b/include/sdhci.h index 01addb7a6036..1358218270b8 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -321,6 +321,7 @@ struct sdhci_host { uint voltages; struct mmc_config cfg; + void *align_buffer; dma_addr_t start_addr; int flags; #define USE_SDMA (0x1 << 0) From patchwork Fri Feb 14 07:40:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 236340 List-Id: U-Boot discussion From: yamada.masahiro at socionext.com (Masahiro Yamada) Date: Fri, 14 Feb 2020 16:40:22 +0900 Subject: [PATCH v3 06/11] mmc: sdhci: reduce code duplication for aligned buffer In-Reply-To: <20200214074027.19824-1-yamada.masahiro@socionext.com> References: <20200214074027.19824-1-yamada.masahiro@socionext.com> Message-ID: <20200214074027.19824-7-yamada.masahiro@socionext.com> The same code is run for both SDHCI_QUIRK_32BIT_DMA_ADDR and define(CONFIG_FIXED_SDHCI_ALIGNED_BUFFER). Unify the code. Signed-off-by: Masahiro Yamada Reviewed-by: Jaehoon Chung --- Changes in v3: None Changes in v2: None drivers/mmc/sdhci.c | 22 ++++++++-------------- include/sdhci.h | 2 ++ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 18fbcb5f1864..b4713e7b9bba 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -140,27 +140,16 @@ static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data, sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); if (host->flags & USE_SDMA) { - if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) && - (host->start_addr & 0x7) != 0x0) { + if (host->force_align_buffer || + (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR && + (host->start_addr & 0x7) != 0x0)) { *is_aligned = 0; host->start_addr = (unsigned long)host->align_buffer; if (data->flags != MMC_DATA_READ) memcpy(host->align_buffer, data->src, trans_bytes); } - -#if defined(CONFIG_FIXED_SDHCI_ALIGNED_BUFFER) - /* - * Always use this bounce-buffer when - * CONFIG_FIXED_SDHCI_ALIGNED_BUFFER is defined - */ - *is_aligned = 0; - host->start_addr = (unsigned long)host->align_buffer; - if (data->flags != MMC_DATA_READ) - memcpy(host->align_buffer, data->src, trans_bytes); -#endif sdhci_writel(host, host->start_addr, SDHCI_DMA_ADDRESS); - } else if (host->flags & (USE_ADMA | USE_ADMA64)) { sdhci_prepare_adma_table(host, data); @@ -627,6 +616,11 @@ static int sdhci_init(struct mmc *mmc) #if defined(CONFIG_FIXED_SDHCI_ALIGNED_BUFFER) host->align_buffer = (void *)CONFIG_FIXED_SDHCI_ALIGNED_BUFFER; + /* + * Always use this bounce-buffer when CONFIG_FIXED_SDHCI_ALIGNED_BUFFER + * is defined. + */ + host->force_align_buffer = true; #else if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) { host->align_buffer = memalign(8, 512 * 1024); diff --git a/include/sdhci.h b/include/sdhci.h index 1358218270b8..7f8feefa450b 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -9,6 +9,7 @@ #ifndef __SDHCI_HW_H #define __SDHCI_HW_H +#include #include #include #include @@ -322,6 +323,7 @@ struct sdhci_host { struct mmc_config cfg; void *align_buffer; + bool force_align_buffer; dma_addr_t start_addr; int flags; #define USE_SDMA (0x1 << 0) From patchwork Fri Feb 14 07:40:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 236338 List-Id: U-Boot discussion From: yamada.masahiro at socionext.com (Masahiro Yamada) Date: Fri, 14 Feb 2020 16:40:23 +0900 Subject: [PATCH v3 07/11] mmc: sdhci: use lower_32_bit2() and upper_32_bits() for setting adma_addr In-Reply-To: <20200214074027.19824-1-yamada.masahiro@socionext.com> References: <20200214074027.19824-1-yamada.masahiro@socionext.com> Message-ID: <20200214074027.19824-8-yamada.masahiro@socionext.com> Use {lower,upper}_32_bits() instead of the combination of cast and shift. Signed-off-by: Masahiro Yamada Reviewed-by: Jaehoon Chung --- Changes in v3: None Changes in v2: None drivers/mmc/sdhci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index b4713e7b9bba..fefe81016eb1 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -153,9 +153,10 @@ static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data, } else if (host->flags & (USE_ADMA | USE_ADMA64)) { sdhci_prepare_adma_table(host, data); - sdhci_writel(host, (u32)host->adma_addr, SDHCI_ADMA_ADDRESS); + sdhci_writel(host, lower_32_bits(host->adma_addr), + SDHCI_ADMA_ADDRESS); if (host->flags & USE_ADMA64) - sdhci_writel(host, (u64)host->adma_addr >> 32, + sdhci_writel(host, upper_32_bits(host->adma_addr), SDHCI_ADMA_ADDRESS_HI); } From patchwork Fri Feb 14 07:40:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 236345 List-Id: U-Boot discussion From: yamada.masahiro at socionext.com (Masahiro Yamada) Date: Fri, 14 Feb 2020 16:40:24 +0900 Subject: [PATCH v3 08/11] mmc: sdhci: remove unneeded casts In-Reply-To: <20200214074027.19824-1-yamada.masahiro@socionext.com> References: <20200214074027.19824-1-yamada.masahiro@socionext.com> Message-ID: <20200214074027.19824-9-yamada.masahiro@socionext.com> host->mmc is already (struct mmc *). memalign() returns an opaque pointer, so there is no need for casting. Signed-off-by: Masahiro Yamada Reviewed-by: Jaehoon Chung --- Changes in v3: None Changes in v2: None drivers/mmc/sdhci.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index fefe81016eb1..ee54d78a28f2 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -522,7 +522,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) void sdhci_set_uhs_timing(struct sdhci_host *host) { - struct mmc *mmc = (struct mmc *)host->mmc; + struct mmc *mmc = host->mmc; u32 reg; reg = sdhci_readw(host, SDHCI_HOST_CONTROL2); @@ -735,8 +735,7 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host, __func__); return -EINVAL; } - host->adma_desc_table = (struct sdhci_adma_desc *) - memalign(ARCH_DMA_MINALIGN, ADMA_TABLE_SZ); + host->adma_desc_table = memalign(ARCH_DMA_MINALIGN, ADMA_TABLE_SZ); host->adma_addr = (dma_addr_t)host->adma_desc_table; #ifdef CONFIG_DMA_ADDR_T_64BIT From patchwork Fri Feb 14 07:40:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 236346 List-Id: U-Boot discussion From: yamada.masahiro at socionext.com (Masahiro Yamada) Date: Fri, 14 Feb 2020 16:40:25 +0900 Subject: [PATCH v3 09/11] mmc: add mmc_get_dma_dir() helper In-Reply-To: <20200214074027.19824-1-yamada.masahiro@socionext.com> References: <20200214074027.19824-1-yamada.masahiro@socionext.com> Message-ID: <20200214074027.19824-10-yamada.masahiro@socionext.com> Copied from Linux kernel. include/linux/mmc/host.h Signed-off-by: Masahiro Yamada Reviewed-by: Jaehoon Chung --- Changes in v3: None Changes in v2: None include/mmc.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/mmc.h b/include/mmc.h index b5cb514f57d6..71e2e1735ad5 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) @@ -880,4 +881,9 @@ int mmc_get_env_dev(void); */ struct blk_desc *mmc_get_blk_desc(struct mmc *mmc); +static inline enum dma_data_direction mmc_get_dma_dir(struct mmc_data *data) +{ + return data->flags & MMC_DATA_WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE; +} + #endif /* _MMC_H_ */ From patchwork Fri Feb 14 07:40:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 236347 List-Id: U-Boot discussion From: yamada.masahiro at socionext.com (Masahiro Yamada) Date: Fri, 14 Feb 2020 16:40:26 +0900 Subject: [PATCH v3 10/11] mmc: sdhci: use dma_map_single() instead of flush_cache() before DMA In-Reply-To: <20200214074027.19824-1-yamada.masahiro@socionext.com> References: <20200214074027.19824-1-yamada.masahiro@socionext.com> Message-ID: <20200214074027.19824-11-yamada.masahiro@socionext.com> Currently, sdhci_prepare_dma() calls flush_cache() regardless of the DMA direction. Actually, cache invalidation is enough when reading data from the device. This is correctly handled by dma_map_single(), which mimics the DMA-API in Linux kernel. Drivers can be agnostic which cache operation occurs behind the scene. This commit also sanitizes the difference between the virtual address and the dma address. Signed-off-by: Masahiro Yamada --- Changes in v3: None Changes in v2: None drivers/mmc/sdhci.c | 51 ++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index ee54d78a28f2..77a88bc043e4 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -15,6 +15,7 @@ #include #include #include +#include static void sdhci_reset(struct sdhci_host *host, u8 mask) { @@ -65,8 +66,8 @@ static void sdhci_transfer_pio(struct sdhci_host *host, struct mmc_data *data) } #if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA) -static void sdhci_adma_desc(struct sdhci_host *host, char *buf, u16 len, - bool end) +static void sdhci_adma_desc(struct sdhci_host *host, dma_addr_t dma_addr, + u16 len, bool end) { struct sdhci_adma_desc *desc; u8 attr; @@ -82,9 +83,9 @@ static void sdhci_adma_desc(struct sdhci_host *host, char *buf, u16 len, desc->attr = attr; desc->len = len; desc->reserved = 0; - desc->addr_lo = (dma_addr_t)buf; + desc->addr_lo = lower_32_bits(dma_addr); #ifdef CONFIG_DMA_ADDR_T_64BIT - desc->addr_hi = (u64)buf >> 32; + desc->addr_hi = upper_32_bits(dma_addr); #endif } @@ -94,22 +95,17 @@ static void sdhci_prepare_adma_table(struct sdhci_host *host, uint trans_bytes = data->blocksize * data->blocks; uint desc_count = DIV_ROUND_UP(trans_bytes, ADMA_MAX_LEN); int i = desc_count; - char *buf; + dma_addr_t dma_addr = host->start_addr; host->desc_slot = 0; - if (data->flags & MMC_DATA_READ) - buf = data->dest; - else - buf = (char *)data->src; - while (--i) { - sdhci_adma_desc(host, buf, ADMA_MAX_LEN, false); - buf += ADMA_MAX_LEN; + sdhci_adma_desc(host, dma_addr, ADMA_MAX_LEN, false); + dma_addr += ADMA_MAX_LEN; trans_bytes -= ADMA_MAX_LEN; } - sdhci_adma_desc(host, buf, trans_bytes, true); + sdhci_adma_desc(host, dma_addr, trans_bytes, true); flush_cache((dma_addr_t)host->adma_desc_table, ROUND(desc_count * sizeof(struct sdhci_adma_desc), @@ -125,11 +121,12 @@ static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data, int *is_aligned, int trans_bytes) { unsigned char ctrl; + void *buf; if (data->flags == MMC_DATA_READ) - host->start_addr = (dma_addr_t)data->dest; + buf = data->dest; else - host->start_addr = (dma_addr_t)data->src; + buf = (void *)data->src; ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); ctrl &= ~SDHCI_CTRL_DMA_MASK; @@ -139,16 +136,20 @@ static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data, ctrl |= SDHCI_CTRL_ADMA32; sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); + if (host->flags & USE_SDMA && + (host->force_align_buffer || + (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR && + ((unsigned long)buf & 0x7) != 0x0))) { + *is_aligned = 0; + if (data->flags != MMC_DATA_READ) + memcpy(host->align_buffer, buf, trans_bytes); + buf = host->align_buffer; + } + + host->start_addr = dma_map_single(buf, trans_bytes, + mmc_get_dma_dir(data)); + if (host->flags & USE_SDMA) { - if (host->force_align_buffer || - (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR && - (host->start_addr & 0x7) != 0x0)) { - *is_aligned = 0; - host->start_addr = (unsigned long)host->align_buffer; - if (data->flags != MMC_DATA_READ) - memcpy(host->align_buffer, data->src, - trans_bytes); - } sdhci_writel(host, host->start_addr, SDHCI_DMA_ADDRESS); } else if (host->flags & (USE_ADMA | USE_ADMA64)) { sdhci_prepare_adma_table(host, data); @@ -159,8 +160,6 @@ static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data, sdhci_writel(host, upper_32_bits(host->adma_addr), SDHCI_ADMA_ADDRESS_HI); } - - flush_cache(host->start_addr, ROUND(trans_bytes, ARCH_DMA_MINALIGN)); } #else static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data, From patchwork Fri Feb 14 07:40:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 236344 List-Id: U-Boot discussion From: yamada.masahiro at socionext.com (Masahiro Yamada) Date: Fri, 14 Feb 2020 16:40:27 +0900 Subject: [PATCH v3 11/11] mmc: sdhci: fix missing cache invalidation after reading by DMA In-Reply-To: <20200214074027.19824-1-yamada.masahiro@socionext.com> References: <20200214074027.19824-1-yamada.masahiro@socionext.com> Message-ID: <20200214074027.19824-12-yamada.masahiro@socionext.com> This driver currently performs cache operation before the DMA start, but does nothing after the DMA completion. When reading data by DMA, the cache invalidation is needed also after finishing the DMA transfer. Otherwise, the CPU might read data from the cache instead of from the main memory when speculative memory read or memory prefetch occurs. Instead of calling the cache operation directly, this commit adds dma_unmap_single(), which performs cache invalidation internally, but drivers do not need which operation is being run. Signed-off-by: Masahiro Yamada --- Changes in v3: None Changes in v2: None drivers/mmc/sdhci.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 77a88bc043e4..9b7c5f8f684f 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -215,6 +215,10 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data) return -ETIMEDOUT; } } while (!(stat & SDHCI_INT_DATA_END)); + + dma_unmap_single(host->start_addr, data->blocks * data->blocksize, + mmc_get_dma_dir(data)); + return 0; }