]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
ufs: fix dcache flush and invalidate range calculation
authorNeil Armstrong <neil.armstrong@linaro.org>
Mon, 30 Sep 2024 12:44:24 +0000 (14:44 +0200)
committerNeil Armstrong <neil.armstrong@linaro.org>
Mon, 14 Oct 2024 06:55:28 +0000 (08:55 +0200)
The current calculation will omit doing a flush/invalidate on the last
cacheline if the base address is not aligned with DMA_MINALIGN.

This causes commands failures and write corruptions on Qualcomm
platforms.

Reviewed-by: Neha Malcom Francis <n-francis@ti.com>
Tested-by: Venkatesh Yadav Abbarapu <venkatesh.abbarapu@amd.com>
Tested-by: Julius Lehmann <lehmanju@devpi.de>
Link: https://lore.kernel.org/r/20240930-topic-ufs-enhancements-v3-2-58234f84ab89@linaro.org
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
drivers/ufs/ufs.c

index e005cc90608e564796f1cb6a09490ee19fbe52fc..3d9a7d7ee121be8974176cc905c675b8bd699f4e 100644 (file)
@@ -703,11 +703,11 @@ static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba)
  */
 static void ufshcd_cache_flush_and_invalidate(void *addr, unsigned long size)
 {
-       uintptr_t aaddr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1);
-       unsigned long asize = ALIGN(size, ARCH_DMA_MINALIGN);
+       uintptr_t start_addr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1);
+       uintptr_t end_addr = ALIGN((uintptr_t)addr + size, ARCH_DMA_MINALIGN);
 
-       flush_dcache_range(aaddr, aaddr + asize);
-       invalidate_dcache_range(aaddr, aaddr + asize);
+       flush_dcache_range(start_addr, end_addr);
+       invalidate_dcache_range(start_addr, end_addr);
 }
 
 /**
@@ -1466,13 +1466,13 @@ static void prepare_prdt_table(struct ufs_hba *hba, struct scsi_cmd *pccb)
        }
 
        if (pccb->dma_dir == DMA_TO_DEVICE) {   /* Write to device */
-               flush_dcache_range(aaddr, aaddr +
-                                  ALIGN(datalen, ARCH_DMA_MINALIGN));
+               flush_dcache_range(aaddr,
+                                  ALIGN((uintptr_t)pccb->pdata + datalen, ARCH_DMA_MINALIGN));
        }
 
        /* In any case, invalidate cache to avoid stale data in it. */
-       invalidate_dcache_range(aaddr, aaddr +
-                               ALIGN(datalen, ARCH_DMA_MINALIGN));
+       invalidate_dcache_range(aaddr,
+                               ALIGN((uintptr_t)pccb->pdata + datalen, ARCH_DMA_MINALIGN));
 
        table_length = DIV_ROUND_UP(pccb->datalen, MAX_PRDT_ENTRY);
        buf = pccb->pdata;