add chaos_calmer branch
[15.05/openwrt.git] / package / kernel / mac80211 / patches / 372-brcmfmac-add-support-for-dma-indices-feature.patch
1 From: Franky Lin <frankyl@broadcom.com>
2 Date: Wed, 20 May 2015 14:09:51 +0200
3 Subject: [PATCH] brcmfmac: add support for dma indices feature
4
5 PCIe full dongle firmware can support a dma indices feature with which
6 firmware can update/fetch the read/write indices of message buffer
7 rings on both host to dongle and dongle to host directions. The support is
8 announced by firmware through shared flags.
9
10 Reviewed-by: Arend Van Spriel <arend@broadcom.com>
11 Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
12 Signed-off-by: Franky Lin <frankyl@broadcom.com>
13 Signed-off-by: Arend van Spriel <arend@broadcom.com>
14 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
15 ---
16
17 --- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
18 +++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
19 @@ -115,6 +115,8 @@ enum brcmf_pcie_state {
20  #define BRCMF_PCIE_MIN_SHARED_VERSION          5
21  #define BRCMF_PCIE_MAX_SHARED_VERSION          5
22  #define BRCMF_PCIE_SHARED_VERSION_MASK         0x00FF
23 +#define BRCMF_PCIE_SHARED_DMA_INDEX            0x10000
24 +#define BRCMF_PCIE_SHARED_DMA_2B_IDX           0x100000
25  
26  #define BRCMF_PCIE_FLAGS_HTOD_SPLIT            0x4000
27  #define BRCMF_PCIE_FLAGS_DTOH_SPLIT            0x8000
28 @@ -146,6 +148,10 @@ enum brcmf_pcie_state {
29  #define BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET 8
30  #define BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET 12
31  #define BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET 16
32 +#define BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET  20
33 +#define BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET  28
34 +#define BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET  36
35 +#define BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET  44
36  #define BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET    0
37  #define BRCMF_SHARED_RING_MAX_SUB_QUEUES       52
38  
39 @@ -247,6 +253,13 @@ struct brcmf_pciedev_info {
40         bool mbdata_completed;
41         bool irq_allocated;
42         bool wowl_enabled;
43 +       u8 dma_idx_sz;
44 +       void *idxbuf;
45 +       u32 idxbuf_sz;
46 +       dma_addr_t idxbuf_dmahandle;
47 +       u16 (*read_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset);
48 +       void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
49 +                         u16 value);
50  };
51  
52  struct brcmf_pcie_ringbuf {
53 @@ -323,6 +336,25 @@ brcmf_pcie_write_tcm16(struct brcmf_pcie
54  }
55  
56  
57 +static u16
58 +brcmf_pcie_read_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
59 +{
60 +       u16 *address = devinfo->idxbuf + mem_offset;
61 +
62 +       return (*(address));
63 +}
64 +
65 +
66 +static void
67 +brcmf_pcie_write_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
68 +                    u16 value)
69 +{
70 +       u16 *address = devinfo->idxbuf + mem_offset;
71 +
72 +       *(address) = value;
73 +}
74 +
75 +
76  static u32
77  brcmf_pcie_read_tcm32(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
78  {
79 @@ -868,7 +900,7 @@ static int brcmf_pcie_ring_mb_write_rptr
80         brcmf_dbg(PCIE, "W r_ptr %d (%d), ring %d\n", commonring->r_ptr,
81                   commonring->w_ptr, ring->id);
82  
83 -       brcmf_pcie_write_tcm16(devinfo, ring->r_idx_addr, commonring->r_ptr);
84 +       devinfo->write_ptr(devinfo, ring->r_idx_addr, commonring->r_ptr);
85  
86         return 0;
87  }
88 @@ -886,7 +918,7 @@ static int brcmf_pcie_ring_mb_write_wptr
89         brcmf_dbg(PCIE, "W w_ptr %d (%d), ring %d\n", commonring->w_ptr,
90                   commonring->r_ptr, ring->id);
91  
92 -       brcmf_pcie_write_tcm16(devinfo, ring->w_idx_addr, commonring->w_ptr);
93 +       devinfo->write_ptr(devinfo, ring->w_idx_addr, commonring->w_ptr);
94  
95         return 0;
96  }
97 @@ -915,7 +947,7 @@ static int brcmf_pcie_ring_mb_update_rpt
98         if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
99                 return -EIO;
100  
101 -       commonring->r_ptr = brcmf_pcie_read_tcm16(devinfo, ring->r_idx_addr);
102 +       commonring->r_ptr = devinfo->read_ptr(devinfo, ring->r_idx_addr);
103  
104         brcmf_dbg(PCIE, "R r_ptr %d (%d), ring %d\n", commonring->r_ptr,
105                   commonring->w_ptr, ring->id);
106 @@ -933,7 +965,7 @@ static int brcmf_pcie_ring_mb_update_wpt
107         if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
108                 return -EIO;
109  
110 -       commonring->w_ptr = brcmf_pcie_read_tcm16(devinfo, ring->w_idx_addr);
111 +       commonring->w_ptr = devinfo->read_ptr(devinfo, ring->w_idx_addr);
112  
113         brcmf_dbg(PCIE, "R w_ptr %d (%d), ring %d\n", commonring->w_ptr,
114                   commonring->r_ptr, ring->id);
115 @@ -1038,6 +1070,13 @@ static void brcmf_pcie_release_ringbuffe
116         }
117         kfree(devinfo->shared.flowrings);
118         devinfo->shared.flowrings = NULL;
119 +       if (devinfo->idxbuf) {
120 +               dma_free_coherent(&devinfo->pdev->dev,
121 +                                 devinfo->idxbuf_sz,
122 +                                 devinfo->idxbuf,
123 +                                 devinfo->idxbuf_dmahandle);
124 +               devinfo->idxbuf = NULL;
125 +       }
126  }
127  
128  
129 @@ -1053,19 +1092,72 @@ static int brcmf_pcie_init_ringbuffers(s
130         u32 addr;
131         u32 ring_mem_ptr;
132         u32 i;
133 +       u64 address;
134 +       u32 bufsz;
135         u16 max_sub_queues;
136 +       u8 idx_offset;
137  
138         ring_addr = devinfo->shared.ring_info_addr;
139         brcmf_dbg(PCIE, "Base ring addr = 0x%08x\n", ring_addr);
140 +       addr = ring_addr + BRCMF_SHARED_RING_MAX_SUB_QUEUES;
141 +       max_sub_queues = brcmf_pcie_read_tcm16(devinfo, addr);
142  
143 -       addr = ring_addr + BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET;
144 -       d2h_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
145 -       addr = ring_addr + BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET;
146 -       d2h_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
147 -       addr = ring_addr + BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET;
148 -       h2d_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
149 -       addr = ring_addr + BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET;
150 -       h2d_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
151 +       if (devinfo->dma_idx_sz != 0) {
152 +               bufsz = (BRCMF_NROF_D2H_COMMON_MSGRINGS + max_sub_queues) *
153 +                       devinfo->dma_idx_sz * 2;
154 +               devinfo->idxbuf = dma_alloc_coherent(&devinfo->pdev->dev, bufsz,
155 +                                                    &devinfo->idxbuf_dmahandle,
156 +                                                    GFP_KERNEL);
157 +               if (!devinfo->idxbuf)
158 +                       devinfo->dma_idx_sz = 0;
159 +       }
160 +
161 +       if (devinfo->dma_idx_sz == 0) {
162 +               addr = ring_addr + BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET;
163 +               d2h_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
164 +               addr = ring_addr + BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET;
165 +               d2h_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
166 +               addr = ring_addr + BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET;
167 +               h2d_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
168 +               addr = ring_addr + BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET;
169 +               h2d_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
170 +               idx_offset = sizeof(u32);
171 +               devinfo->write_ptr = brcmf_pcie_write_tcm16;
172 +               devinfo->read_ptr = brcmf_pcie_read_tcm16;
173 +               brcmf_dbg(PCIE, "Using TCM indices\n");
174 +       } else {
175 +               memset(devinfo->idxbuf, 0, bufsz);
176 +               devinfo->idxbuf_sz = bufsz;
177 +               idx_offset = devinfo->dma_idx_sz;
178 +               devinfo->write_ptr = brcmf_pcie_write_idx;
179 +               devinfo->read_ptr = brcmf_pcie_read_idx;
180 +
181 +               h2d_w_idx_ptr = 0;
182 +               addr = ring_addr + BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET;
183 +               address = (u64)devinfo->idxbuf_dmahandle;
184 +               brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
185 +               brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
186 +
187 +               h2d_r_idx_ptr = h2d_w_idx_ptr + max_sub_queues * idx_offset;
188 +               addr = ring_addr + BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET;
189 +               address += max_sub_queues * idx_offset;
190 +               brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
191 +               brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
192 +
193 +               d2h_w_idx_ptr = h2d_r_idx_ptr + max_sub_queues * idx_offset;
194 +               addr = ring_addr + BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET;
195 +               address += max_sub_queues * idx_offset;
196 +               brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
197 +               brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
198 +
199 +               d2h_r_idx_ptr = d2h_w_idx_ptr +
200 +                               BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset;
201 +               addr = ring_addr + BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET;
202 +               address += BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset;
203 +               brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
204 +               brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
205 +               brcmf_dbg(PCIE, "Using host memory indices\n");
206 +       }
207  
208         addr = ring_addr + BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET;
209         ring_mem_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
210 @@ -1079,8 +1171,8 @@ static int brcmf_pcie_init_ringbuffers(s
211                 ring->id = i;
212                 devinfo->shared.commonrings[i] = ring;
213  
214 -               h2d_w_idx_ptr += sizeof(u32);
215 -               h2d_r_idx_ptr += sizeof(u32);
216 +               h2d_w_idx_ptr += idx_offset;
217 +               h2d_r_idx_ptr += idx_offset;
218                 ring_mem_ptr += BRCMF_RING_MEM_SZ;
219         }
220  
221 @@ -1094,13 +1186,11 @@ static int brcmf_pcie_init_ringbuffers(s
222                 ring->id = i;
223                 devinfo->shared.commonrings[i] = ring;
224  
225 -               d2h_w_idx_ptr += sizeof(u32);
226 -               d2h_r_idx_ptr += sizeof(u32);
227 +               d2h_w_idx_ptr += idx_offset;
228 +               d2h_r_idx_ptr += idx_offset;
229                 ring_mem_ptr += BRCMF_RING_MEM_SZ;
230         }
231  
232 -       addr = ring_addr + BRCMF_SHARED_RING_MAX_SUB_QUEUES;
233 -       max_sub_queues = brcmf_pcie_read_tcm16(devinfo, addr);
234         devinfo->shared.nrof_flowrings =
235                         max_sub_queues - BRCMF_NROF_H2D_COMMON_MSGRINGS;
236         rings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*ring),
237 @@ -1124,15 +1214,15 @@ static int brcmf_pcie_init_ringbuffers(s
238                                              ring);
239                 ring->w_idx_addr = h2d_w_idx_ptr;
240                 ring->r_idx_addr = h2d_r_idx_ptr;
241 -               h2d_w_idx_ptr += sizeof(u32);
242 -               h2d_r_idx_ptr += sizeof(u32);
243 +               h2d_w_idx_ptr += idx_offset;
244 +               h2d_r_idx_ptr += idx_offset;
245         }
246         devinfo->shared.flowrings = rings;
247  
248         return 0;
249  
250  fail:
251 -       brcmf_err("Allocating commonring buffers failed\n");
252 +       brcmf_err("Allocating ring buffers failed\n");
253         brcmf_pcie_release_ringbuffers(devinfo);
254         return -ENOMEM;
255  }
256 @@ -1269,6 +1359,14 @@ brcmf_pcie_init_share_ram_info(struct br
257                 return -EINVAL;
258         }
259  
260 +       /* check firmware support dma indicies */
261 +       if (shared->flags & BRCMF_PCIE_SHARED_DMA_INDEX) {
262 +               if (shared->flags & BRCMF_PCIE_SHARED_DMA_2B_IDX)
263 +                       devinfo->dma_idx_sz = sizeof(u16);
264 +               else
265 +                       devinfo->dma_idx_sz = sizeof(u32);
266 +       }
267 +
268         addr = sharedram_addr + BRCMF_SHARED_MAX_RXBUFPOST_OFFSET;
269         shared->max_rxbufpost = brcmf_pcie_read_tcm16(devinfo, addr);
270         if (shared->max_rxbufpost == 0)