mac80211: update to 2015-12-03
[openwrt/staging/mkresin.git] / package / kernel / mac80211 / patches / 303-ath10k-do-not-use-coherent-memory-for-allocated-devi.patch
1 From: Felix Fietkau <nbd@openwrt.org>
2 Date: Sun, 22 Nov 2015 14:03:40 +0100
3 Subject: [PATCH] ath10k: do not use coherent memory for allocated device
4 memory chunks
5
6 Coherent memory is more expensive to allocate (and constrained on some
7 architectures where it has to be pre-allocated). It is also completely
8 unnecessary, since the host has no reason to even access these allocated
9 memory spaces
10
11 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
12 ---
13
14 --- a/drivers/net/wireless/ath/ath10k/wmi.c
15 +++ b/drivers/net/wireless/ath/ath10k/wmi.c
16 @@ -4312,34 +4312,58 @@ void ath10k_wmi_event_vdev_resume_req(st
17 ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_RESUME_REQ_EVENTID\n");
18 }
19
20 -static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
21 - u32 num_units, u32 unit_len)
22 +static int ath10k_wmi_alloc_chunk(struct ath10k *ar, u32 req_id,
23 + u32 num_units, u32 unit_len)
24 {
25 dma_addr_t paddr;
26 - u32 pool_size;
27 + u32 pool_size = 0;
28 int idx = ar->wmi.num_mem_chunks;
29 + void *vaddr = NULL;
30
31 - pool_size = num_units * round_up(unit_len, 4);
32 + if (ar->wmi.num_mem_chunks == ARRAY_SIZE(ar->wmi.mem_chunks))
33 + return -ENOMEM;
34
35 - if (!pool_size)
36 - return -EINVAL;
37 + while (!vaddr && num_units) {
38 + pool_size = num_units * round_up(unit_len, 4);
39 + if (!pool_size)
40 + return -EINVAL;
41
42 - ar->wmi.mem_chunks[idx].vaddr = dma_alloc_coherent(ar->dev,
43 - pool_size,
44 - &paddr,
45 - GFP_KERNEL);
46 - if (!ar->wmi.mem_chunks[idx].vaddr) {
47 - ath10k_warn(ar, "failed to allocate memory chunk\n");
48 - return -ENOMEM;
49 + vaddr = kzalloc(pool_size, GFP_KERNEL | __GFP_NOWARN);
50 + if (!vaddr)
51 + num_units /= 2;
52 }
53
54 - memset(ar->wmi.mem_chunks[idx].vaddr, 0, pool_size);
55 + if (!num_units)
56 + return -ENOMEM;
57 +
58 + paddr = dma_map_single(ar->dev, vaddr, pool_size, DMA_TO_DEVICE);
59 + if (dma_mapping_error(ar->dev, paddr)) {
60 + kfree(vaddr);
61 + return -ENOMEM;
62 + }
63
64 + ar->wmi.mem_chunks[idx].vaddr = vaddr;
65 ar->wmi.mem_chunks[idx].paddr = paddr;
66 ar->wmi.mem_chunks[idx].len = pool_size;
67 ar->wmi.mem_chunks[idx].req_id = req_id;
68 ar->wmi.num_mem_chunks++;
69
70 + return num_units;
71 +}
72 +
73 +static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
74 + u32 num_units, u32 unit_len)
75 +{
76 + int ret;
77 +
78 + while (num_units) {
79 + ret = ath10k_wmi_alloc_chunk(ar, req_id, num_units, unit_len);
80 + if (ret < 0)
81 + return ret;
82 +
83 + num_units -= ret;
84 + }
85 +
86 return 0;
87 }
88
89 @@ -7717,10 +7741,11 @@ void ath10k_wmi_free_host_mem(struct ath
90
91 /* free the host memory chunks requested by firmware */
92 for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
93 - dma_free_coherent(ar->dev,
94 - ar->wmi.mem_chunks[i].len,
95 - ar->wmi.mem_chunks[i].vaddr,
96 - ar->wmi.mem_chunks[i].paddr);
97 + dma_unmap_single(ar->dev,
98 + ar->wmi.mem_chunks[i].paddr,
99 + ar->wmi.mem_chunks[i].len,
100 + DMA_TO_DEVICE);
101 + kfree(ar->wmi.mem_chunks[i].vaddr);
102 }
103
104 ar->wmi.num_mem_chunks = 0;