summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorNeil Armstrong <neil.armstrong@linaro.org>2024-09-30 14:44:24 +0200
committerNeil Armstrong <neil.armstrong@linaro.org>2024-10-14 08:55:28 +0200
commitc64d22b57d8a9fe4d08ab677ba33d6004b98a468 (patch)
tree1a1403a5a9ba4504df76213a9e6a2d13a9859af5 /drivers
parent9c223d8d8b8fbad667971f36eabe203480a8c39b (diff)
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 <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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ufs/ufs.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index e005cc90608..3d9a7d7ee12 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;