From 9b38ea43cd19cc6bd9a1330c1d4ee9d9c77e448c Mon Sep 17 00:00:00 2001
From: Hari Chandrakanthan <haric@codeaurora.org>
Date: Fri, 25 Jun 2021 20:44:59 +0530
Subject: [PATCH] ath11k: fix CE and DP address alignment

srng dma address and virtual address should be aligned with byte instead
of pointer type. Alignment should be based on dma address instead
of virtual address. Also CE dma allocations are freed with unaligned
address instead of aligned address. so corrected all address alignment.

Signed-off-by: Hari Chandrakanthan <haric@codeaurora.org>
Signed-off-by: Karthikeyan Periyasamy <periyasa@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/ce.c  | 24 +++++++++++++-----------
 drivers/net/wireless/ath/ath11k/ce.h  |  4 ++--
 drivers/net/wireless/ath/ath11k/dp.c  | 14 ++++++++++----
 drivers/net/wireless/ath/ath11k/hal.h |  3 ++-
 4 files changed, 27 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/ce.c b/drivers/net/wireless/ath/ath11k/ce.c
index 453079a..4b5bbef 100644
--- a/drivers/net/wireless/ath/ath11k/ce.c
+++ b/drivers/net/wireless/ath/ath11k/ce.c
@@ -619,6 +619,7 @@ ath11k_ce_alloc_ring(struct ath11k_base *ab, int nentries, int desc_sz)
 {
 	struct ath11k_ce_ring *ce_ring;
 	dma_addr_t base_addr;
+	unsigned long off;
 
 	ce_ring = kzalloc(struct_size(ce_ring, skb, nentries), GFP_KERNEL);
 	if (ce_ring == NULL)
@@ -647,12 +648,13 @@ ath11k_ce_alloc_ring(struct ath11k_base *ab, int nentries, int desc_sz)
 
 	ce_ring->base_addr_ce_space_unaligned = base_addr;
 
-	ce_ring->base_addr_owner_space = PTR_ALIGN(
-			ce_ring->base_addr_owner_space_unaligned,
-			CE_DESC_RING_ALIGN);
-	ce_ring->base_addr_ce_space = ALIGN(
-			ce_ring->base_addr_ce_space_unaligned,
+	ce_ring->base_addr_ce_space = (dma_addr_t) ALIGN(
+			(unsigned long)ce_ring->base_addr_ce_space_unaligned,
 			CE_DESC_RING_ALIGN);
+	off = (unsigned long)ce_ring->base_addr_ce_space -
+		(unsigned long)ce_ring->base_addr_ce_space_unaligned;
+	ce_ring->base_addr_owner_space = (void *)
+			((unsigned long)ce_ring->base_addr_owner_space_unaligned + off);
 
 	return ce_ring;
 }
@@ -1004,8 +1006,8 @@ void ath11k_ce_free_pipes(struct ath11k_base *ab)
 			dma_free_coherent(ab->dev,
 					  pipe->src_ring->nentries * desc_sz +
 					  CE_DESC_RING_ALIGN,
-					  pipe->src_ring->base_addr_owner_space,
-					  pipe->src_ring->base_addr_ce_space);
+					  pipe->src_ring->base_addr_owner_space_unaligned,
+					  pipe->src_ring->base_addr_ce_space_unaligned);
 			ATH11K_MEMORY_STATS_DEC(ab, ce_ring_alloc,
 						pipe->src_ring->nentries * desc_sz +
 						CE_DESC_RING_ALIGN);
@@ -1018,8 +1020,8 @@ void ath11k_ce_free_pipes(struct ath11k_base *ab)
 			dma_free_coherent(ab->dev,
 					  pipe->dest_ring->nentries * desc_sz +
 					  CE_DESC_RING_ALIGN,
-					  pipe->dest_ring->base_addr_owner_space,
-					  pipe->dest_ring->base_addr_ce_space);
+					  pipe->dest_ring->base_addr_owner_space_unaligned,
+					  pipe->dest_ring->base_addr_ce_space_unaligned);
 			ATH11K_MEMORY_STATS_DEC(ab, ce_ring_alloc,
 						pipe->dest_ring->nentries * desc_sz +
 						CE_DESC_RING_ALIGN);
@@ -1033,8 +1035,8 @@ void ath11k_ce_free_pipes(struct ath11k_base *ab)
 			dma_free_coherent(ab->dev,
 					  pipe->status_ring->nentries * desc_sz +
 					  CE_DESC_RING_ALIGN,
-					  pipe->status_ring->base_addr_owner_space,
-					  pipe->status_ring->base_addr_ce_space);
+					  pipe->status_ring->base_addr_owner_space_unaligned,
+					  pipe->status_ring->base_addr_ce_space_unaligned);
 			ATH11K_MEMORY_STATS_DEC(ab, ce_ring_alloc,
 						pipe->status_ring->nentries * desc_sz +
 						CE_DESC_RING_ALIGN);
diff --git a/drivers/net/wireless/ath/ath11k/ce.h b/drivers/net/wireless/ath/ath11k/ce.h
index 5808be6..e099b14 100644
--- a/drivers/net/wireless/ath/ath11k/ce.h
+++ b/drivers/net/wireless/ath/ath11k/ce.h
@@ -140,7 +140,7 @@ struct ath11k_ce_ring {
 	/* Host address space */
 	void *base_addr_owner_space_unaligned;
 	/* CE address space */
-	u32 base_addr_ce_space_unaligned;
+	dma_addr_t base_addr_ce_space_unaligned;
 
 	/* Actual start of descriptors.
 	 * Aligned to descriptor-size boundary.
@@ -150,7 +150,7 @@ struct ath11k_ce_ring {
 	void *base_addr_owner_space;
 
 	/* CE address space */
-	u32 base_addr_ce_space;
+	dma_addr_t base_addr_ce_space;
 
 	/* HAL ring id */
 	u32 hal_ring_id;
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
index 157a21e..d42b867 100644
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -245,6 +245,8 @@ int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring,
 	int max_entries = ath11k_hal_srng_get_max_entries(ab, type);
 	int ret;
 	bool cached;
+	unsigned long off;
+	u8 align = HAL_RING_BASE_ALIGN;
 
 	if (max_entries < 0 || entry_sz < 0)
 		return -EINVAL;
@@ -252,6 +254,9 @@ int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring,
 	if (num_entries > max_entries)
 		num_entries = max_entries;
 
+	if (type == HAL_RXDMA_DIR_BUF)
+		align = HAL_RXDMA_DIR_BUF_RING_BASE_ALIGN;
+
 	/* Allocate the reo dst and tx completion rings from cacheable memory */
 	switch (type) {
 	case HAL_REO_DST:
@@ -265,7 +270,7 @@ int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring,
 	if (ab->nss.enabled)
 		cached = false;
 
-	ring->size = (num_entries * entry_sz) + HAL_RING_BASE_ALIGN - 1;
+	ring->size = (num_entries * entry_sz) + align - 1;
 
 	if (!cached) {
 		ring->vaddr_unaligned = dma_alloc_coherent(ab->dev, ring->size,
@@ -281,9 +286,10 @@ int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring,
 
 	ATH11K_MEMORY_STATS_INC(ab, dma_alloc, ring->size);
 
-	ring->vaddr = PTR_ALIGN(ring->vaddr_unaligned, HAL_RING_BASE_ALIGN);
-	ring->paddr = ring->paddr_unaligned + ((unsigned long)ring->vaddr -
-		      (unsigned long)ring->vaddr_unaligned);
+	ring->paddr = (dma_addr_t) ALIGN((unsigned long)ring->paddr_unaligned,
+					 align);
+	off = (unsigned long)ring->paddr - (unsigned long)ring->paddr_unaligned;
+	ring->vaddr = (u32 *) ((unsigned long)ring->vaddr_unaligned + off);
 
 	params.ring_base_vaddr = ring->vaddr;
 	params.ring_base_paddr = ring->paddr;
diff --git a/drivers/net/wireless/ath/ath11k/hal.h b/drivers/net/wireless/ath/ath11k/hal.h
index e9728fa..f1bdb99 100644
--- a/drivers/net/wireless/ath/ath11k/hal.h
+++ b/drivers/net/wireless/ath/ath11k/hal.h
@@ -21,7 +21,8 @@ struct ath11k_base;
 #define HAL_NUM_MPDU_LINKS_PER_QUEUE_DESC	12
 #define HAL_MAX_AVAIL_BLK_RES			3
 
-#define HAL_RING_BASE_ALIGN	8
+#define HAL_RING_BASE_ALIGN	32
+#define HAL_RXDMA_DIR_BUF_RING_BASE_ALIGN	8
 
 #define HAL_WBM_IDLE_SCATTER_BUF_SIZE_MAX	32704
 /* TODO: Check with hw team on the supported scatter buf size */
-- 
2.7.4

