diff options
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.patch | 104 |
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; |