summary refs log tree commit diff
path: root/drivers
diff options
context:
space:
mode:
authorneil.shi <neil.shi@quectel.com>2023-05-23 17:37:25 +0800
committerPierre-Loup A. Griffais <pgriffais@valvesoftware.com>2023-11-02 16:05:17 -0700
commit44f76134707e8773f9ea2c86e0e01d8347fd3e43 (patch)
treee4c37eb4eab4fdfbd621dd58b4eb9362b254646c /drivers
parent323cc5feb68df12261563160b79ac030545870b9 (diff)
downloadlinux-44f76134707e8773f9ea2c86e0e01d8347fd3e43.tar.gz
wifi: ath11k: add dma36 bit support and direct dma
change mhi-iova_stop and dma_mask to 36 bit
export dma_direct_alloc and add a new API for ath11k
alloc DMA32 mem for CE ring
alloc DMA32 mem for QMI mem request
alloc DMA32 mem for DP ring rdp and wrp
alloc DMA32 mem for DP ring
alloc DMA32 mem for M3.bin

Signed-off-by: neil.shi <neil.shi@quectel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath11k/ce.c6
-rw-r--r--drivers/net/wireless/ath/ath11k/core.c35
-rw-r--r--drivers/net/wireless/ath/ath11k/core.h2
-rw-r--r--drivers/net/wireless/ath/ath11k/dp.c12
-rw-r--r--drivers/net/wireless/ath/ath11k/hal.c9
-rw-r--r--drivers/net/wireless/ath/ath11k/mhi.c2
-rw-r--r--drivers/net/wireless/ath/ath11k/pci.c2
-rw-r--r--drivers/net/wireless/ath/ath11k/qmi.c8
8 files changed, 57 insertions, 19 deletions
diff --git a/drivers/net/wireless/ath/ath11k/ce.c b/drivers/net/wireless/ath/ath11k/ce.c
index f2da95fd4253..6abcacbcb672 100644
--- a/drivers/net/wireless/ath/ath11k/ce.c
+++ b/drivers/net/wireless/ath/ath11k/ce.c
@@ -627,9 +627,9 @@ ath11k_ce_alloc_ring(struct ath11k_base *ab, int nentries, int desc_sz)
 	 * coherent DMA are unsupported
 	 */
 	ce_ring->base_addr_owner_space_unaligned =
-		dma_alloc_coherent(ab->dev,
-				   nentries * desc_sz + CE_DESC_RING_ALIGN,
-				   &base_addr, GFP_KERNEL);
+		ath11k_core_dma_alloc_coherent(ab->dev,
+						nentries * desc_sz + CE_DESC_RING_ALIGN,
+						&base_addr, GFP_KERNEL | GFP_DMA32);
 	if (!ce_ring->base_addr_owner_space_unaligned) {
 		kfree(ce_ring);
 		return ERR_PTR(-ENOMEM);
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index 54b0fd968d2c..1a3749bcb4fc 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -9,6 +9,7 @@
 #include <linux/remoteproc.h>
 #include <linux/firmware.h>
 #include <linux/of.h>
+#include <linux/dma-direct.h>
 
 #include "core.h"
 #include "dp_tx.h"
@@ -677,6 +678,40 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 	},
 };
 
+static const struct dma_map_ops *ath11k_core_get_dma_ops(struct device *dev)
+{
+	if (dev->dma_ops)
+		return dev->dma_ops;
+	return NULL;
+}
+
+void *ath11k_core_dma_alloc_coherent(struct device *dev, size_t size,
+				     dma_addr_t *dma_handle, gfp_t flag)
+{
+	unsigned long attrs = (flag & __GFP_NOWARN) ? DMA_ATTR_NO_WARN : 0;
+	const struct dma_map_ops *ops = ath11k_core_get_dma_ops(dev);
+	void *cpu_addr;
+
+	WARN_ON_ONCE(!dev->coherent_dma_mask);
+
+	/*
+	 * DMA allocations can never be turned back into a page pointer, so
+	 * requesting compound pages doesn't make sense (and can't even be
+	 * supported at all by various backends).
+	 */
+	if (WARN_ON_ONCE(flag & __GFP_COMP))
+		return NULL;
+
+	if (!ops)
+		cpu_addr = dma_direct_alloc(dev, size, dma_handle, flag, attrs);
+	else if (ops->alloc)
+		cpu_addr = ops->alloc(dev, size, dma_handle, flag, attrs);
+	else
+		return NULL;
+
+	return cpu_addr;
+}
+
 static inline struct ath11k_pdev *ath11k_core_get_single_pdev(struct ath11k_base *ab)
 {
 	WARN_ON(!ab->hw_params.single_pdev_only);
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index cbfa0d0a3068..5acd1dfa67b0 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -1248,4 +1248,6 @@ static inline const char *ath11k_bus_str(enum ath11k_bus bus)
 	return "unknown";
 }
 
+void *ath11k_core_dma_alloc_coherent(struct device *dev, size_t size,
+				     dma_addr_t *dma_handle, gfp_t flag);
 #endif /* _CORE_H_ */
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
index d070bcb3fe24..6b6d0ce4f790 100644
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -254,9 +254,9 @@ int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring,
 	}
 
 	if (!cached)
-		ring->vaddr_unaligned = dma_alloc_coherent(ab->dev, ring->size,
+		ring->vaddr_unaligned = ath11k_core_dma_alloc_coherent(ab->dev, ring->size,
 							   &ring->paddr_unaligned,
-							   GFP_KERNEL);
+							   GFP_KERNEL | GFP_DMA32);
 
 	if (!ring->vaddr_unaligned)
 		return -ENOMEM;
@@ -527,9 +527,9 @@ static int ath11k_dp_scatter_idle_link_desc_setup(struct ath11k_base *ab,
 		return -EINVAL;
 
 	for (i = 0; i < num_scatter_buf; i++) {
-		slist[i].vaddr = dma_alloc_coherent(ab->dev,
+		slist[i].vaddr = ath11k_core_dma_alloc_coherent(ab->dev,
 						    HAL_WBM_IDLE_SCATTER_BUF_SIZE_MAX,
-						    &slist[i].paddr, GFP_KERNEL);
+						    &slist[i].paddr, GFP_KERNEL | GFP_DMA32);
 		if (!slist[i].vaddr) {
 			ret = -ENOMEM;
 			goto err;
@@ -607,9 +607,9 @@ static int ath11k_dp_link_desc_bank_alloc(struct ath11k_base *ab,
 			desc_sz = last_bank_sz;
 
 		desc_bank[i].vaddr_unaligned =
-					dma_alloc_coherent(ab->dev, desc_sz,
+					ath11k_core_dma_alloc_coherent(ab->dev, desc_sz,
 							   &desc_bank[i].paddr_unaligned,
-							   GFP_KERNEL);
+							   GFP_KERNEL | GFP_DMA32);
 		if (!desc_bank[i].vaddr_unaligned) {
 			ret = -ENOMEM;
 			goto err;
diff --git a/drivers/net/wireless/ath/ath11k/hal.c b/drivers/net/wireless/ath/ath11k/hal.c
index 2fd224480d45..3f9f5cfe9d7c 100644
--- a/drivers/net/wireless/ath/ath11k/hal.c
+++ b/drivers/net/wireless/ath/ath11k/hal.c
@@ -8,6 +8,7 @@
 #include "debug.h"
 #include "hal_desc.h"
 #include "hif.h"
+#include "core.h"
 
 static const struct hal_srng_config hw_srng_config_template[] = {
 	/* TODO: max_rings can populated by querying HW capabilities */
@@ -196,8 +197,8 @@ static int ath11k_hal_alloc_cont_rdp(struct ath11k_base *ab)
 	size_t size;
 
 	size = sizeof(u32) * HAL_SRNG_RING_ID_MAX;
-	hal->rdp.vaddr = dma_alloc_coherent(ab->dev, size, &hal->rdp.paddr,
-					    GFP_KERNEL);
+	hal->rdp.vaddr = ath11k_core_dma_alloc_coherent(ab->dev, size, &hal->rdp.paddr,
+					    GFP_KERNEL | GFP_DMA32);
 	if (!hal->rdp.vaddr)
 		return -ENOMEM;
 
@@ -224,8 +225,8 @@ static int ath11k_hal_alloc_cont_wrp(struct ath11k_base *ab)
 	size_t size;
 
 	size = sizeof(u32) * HAL_SRNG_NUM_LMAC_RINGS;
-	hal->wrp.vaddr = dma_alloc_coherent(ab->dev, size, &hal->wrp.paddr,
-					    GFP_KERNEL);
+	hal->wrp.vaddr = ath11k_core_dma_alloc_coherent(ab->dev, size, &hal->wrp.paddr,
+					    GFP_KERNEL | GFP_DMA32);
 	if (!hal->wrp.vaddr)
 		return -ENOMEM;
 
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
index f834aab7f142..6247b48db627 100644
--- a/drivers/net/wireless/ath/ath11k/mhi.c
+++ b/drivers/net/wireless/ath/ath11k/mhi.c
@@ -415,7 +415,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
 			goto free_controller;
 	} else {
 		mhi_ctrl->iova_start = 0;
-		mhi_ctrl->iova_stop = 0xFFFFFFFF;
+		mhi_ctrl->iova_stop = 0xFFFFFFFFF;
 	}
 
 	mhi_ctrl->rddm_size = RDDM_DUMP_SIZE;
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index 7f95f6497793..61c8840a0559 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -18,7 +18,7 @@
 #include "coredump.h"
 
 #define ATH11K_PCI_BAR_NUM		0
-#define ATH11K_PCI_DMA_MASK		32
+#define ATH11K_PCI_DMA_MASK		36
 
 #define TCSR_SOC_HW_VERSION		0x0224
 #define TCSR_SOC_HW_VERSION_MAJOR_MASK	GENMASK(11, 8)
diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c
index f9be99b5b65e..113d3f9f0bf5 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -2040,10 +2040,10 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
 			chunk->vaddr = NULL;
 		}
 
-		chunk->vaddr = dma_alloc_coherent(ab->dev,
+		chunk->vaddr = ath11k_core_dma_alloc_coherent(ab->dev,
 						  chunk->size,
 						  &chunk->paddr,
-						  GFP_KERNEL | __GFP_NOWARN);
+						  GFP_KERNEL | __GFP_NOWARN | GFP_DMA32);
 		if (!chunk->vaddr) {
 			if (ab->qmi.mem_seg_count <= ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT) {
 				ath11k_dbg(ab, ATH11K_DBG_QMI,
@@ -2564,9 +2564,9 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab)
 	if (m3_mem->vaddr || m3_mem->size)
 		goto skip_m3_alloc;
 
-	m3_mem->vaddr = dma_alloc_coherent(ab->dev,
+	m3_mem->vaddr = ath11k_core_dma_alloc_coherent(ab->dev,
 					   fw->size, &m3_mem->paddr,
-					   GFP_KERNEL);
+					   GFP_KERNEL  | GFP_DMA32);
 	if (!m3_mem->vaddr) {
 		ath11k_err(ab, "failed to allocate memory for M3 with size %zu\n",
 			   fw->size);