summaryrefslogtreecommitdiff
path: root/package/kernel/mac80211/patches/303-ath10k-do-not-use-coherent-memory-for-allocated-devi.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/kernel/mac80211/patches/303-ath10k-do-not-use-coherent-memory-for-allocated-devi.patch')
-rw-r--r--package/kernel/mac80211/patches/303-ath10k-do-not-use-coherent-memory-for-allocated-devi.patch104
1 files changed, 104 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/303-ath10k-do-not-use-coherent-memory-for-allocated-devi.patch b/package/kernel/mac80211/patches/303-ath10k-do-not-use-coherent-memory-for-allocated-devi.patch
new file mode 100644
index 0000000..20bece6
--- /dev/null
+++ b/package/kernel/mac80211/patches/303-ath10k-do-not-use-coherent-memory-for-allocated-devi.patch
@@ -0,0 +1,104 @@
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sun, 22 Nov 2015 14:03:40 +0100
+Subject: [PATCH] ath10k: do not use coherent memory for allocated device
+ memory chunks
+
+Coherent memory is more expensive to allocate (and constrained on some
+architectures where it has to be pre-allocated). It is also completely
+unnecessary, since the host has no reason to even access these allocated
+memory spaces
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/wmi.c
++++ b/drivers/net/wireless/ath/ath10k/wmi.c
+@@ -4312,34 +4312,58 @@ void ath10k_wmi_event_vdev_resume_req(st
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_RESUME_REQ_EVENTID\n");
+ }
+
+-static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
+- u32 num_units, u32 unit_len)
++static int ath10k_wmi_alloc_chunk(struct ath10k *ar, u32 req_id,
++ u32 num_units, u32 unit_len)
+ {
+ dma_addr_t paddr;
+- u32 pool_size;
++ u32 pool_size = 0;
+ int idx = ar->wmi.num_mem_chunks;
++ void *vaddr = NULL;
+
+- pool_size = num_units * round_up(unit_len, 4);
++ if (ar->wmi.num_mem_chunks == ARRAY_SIZE(ar->wmi.mem_chunks))
++ return -ENOMEM;
+
+- if (!pool_size)
+- return -EINVAL;
++ while (!vaddr && num_units) {
++ pool_size = num_units * round_up(unit_len, 4);
++ if (!pool_size)
++ return -EINVAL;
+
+- ar->wmi.mem_chunks[idx].vaddr = dma_alloc_coherent(ar->dev,
+- pool_size,
+- &paddr,
+- GFP_KERNEL);
+- if (!ar->wmi.mem_chunks[idx].vaddr) {
+- ath10k_warn(ar, "failed to allocate memory chunk\n");
+- return -ENOMEM;
++ vaddr = kzalloc(pool_size, GFP_KERNEL | __GFP_NOWARN);
++ if (!vaddr)
++ num_units /= 2;
+ }
+
+- memset(ar->wmi.mem_chunks[idx].vaddr, 0, pool_size);
++ if (!num_units)
++ return -ENOMEM;
++
++ paddr = dma_map_single(ar->dev, vaddr, pool_size, DMA_TO_DEVICE);
++ if (dma_mapping_error(ar->dev, paddr)) {
++ kfree(vaddr);
++ return -ENOMEM;
++ }
+
++ ar->wmi.mem_chunks[idx].vaddr = vaddr;
+ ar->wmi.mem_chunks[idx].paddr = paddr;
+ ar->wmi.mem_chunks[idx].len = pool_size;
+ ar->wmi.mem_chunks[idx].req_id = req_id;
+ ar->wmi.num_mem_chunks++;
+
++ return num_units;
++}
++
++static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
++ u32 num_units, u32 unit_len)
++{
++ int ret;
++
++ while (num_units) {
++ ret = ath10k_wmi_alloc_chunk(ar, req_id, num_units, unit_len);
++ if (ret < 0)
++ return ret;
++
++ num_units -= ret;
++ }
++
+ return 0;
+ }
+
+@@ -7717,10 +7741,11 @@ void ath10k_wmi_free_host_mem(struct ath
+
+ /* free the host memory chunks requested by firmware */
+ for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
+- dma_free_coherent(ar->dev,
+- ar->wmi.mem_chunks[i].len,
+- ar->wmi.mem_chunks[i].vaddr,
+- ar->wmi.mem_chunks[i].paddr);
++ dma_unmap_single(ar->dev,
++ ar->wmi.mem_chunks[i].paddr,
++ ar->wmi.mem_chunks[i].len,
++ DMA_TO_DEVICE);
++ kfree(ar->wmi.mem_chunks[i].vaddr);
+ }
+
+ ar->wmi.num_mem_chunks = 0;