From: Neil Armstrong Date: Mon, 30 Sep 2024 12:44:24 +0000 (+0200) Subject: ufs: fix dcache flush and invalidate range calculation X-Git-Url: http://git.dujemihanovic.xyz/img/html/static/gitweb.css?a=commitdiff_plain;h=c64d22b57d8a9fe4d08ab677ba33d6004b98a468;p=u-boot.git ufs: fix dcache flush and invalidate range calculation 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 Tested-by: Venkatesh Yadav Abbarapu Tested-by: Julius Lehmann Link: https://lore.kernel.org/r/20240930-topic-ufs-enhancements-v3-2-58234f84ab89@linaro.org Signed-off-by: Neil Armstrong --- diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index e005cc9060..3d9a7d7ee1 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -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;