image.mk: fix emitting profiles for targets that have no subtargets
[openwrt/staging/mkresin.git] / package / kernel / mac80211 / patches / 331-brcmfmac-Increase-nr-of-supported-flowrings.patch
1 From: Hante Meuleman <meuleman@broadcom.com>
2 Date: Sun, 7 Feb 2016 18:08:24 +0100
3 Subject: [PATCH] brcmfmac: Increase nr of supported flowrings.
4 MIME-Version: 1.0
5 Content-Type: text/plain; charset=UTF-8
6 Content-Transfer-Encoding: 8bit
7
8 New generation devices have firmware which has more than 256 flowrings.
9 E.g. following debugging message comes from 14e4:4365 BCM4366:
10 [ 194.606245] brcmfmac: brcmf_pcie_init_ringbuffers Nr of flowrings is 264
11
12 At various code places (related to flowrings) we were using u8 which
13 could lead to storing wrong number or infinite loops when indexing with
14 this type. This issue was quite easy to spot in brcmf_flowring_detach
15 where it led to infinite loop e.g. on failed initialization.
16
17 This patch switches code to proper types and increases the maximum
18 number of supported flowrings to 512.
19
20 Originally this change was sent in September 2015, but back it was
21 causing a regression on BCM43602 resulting in:
22 Unable to handle kernel NULL pointer dereference at virtual address ...
23
24 The reason for this regression was missing update (s/u8/u16) of struct
25 brcmf_flowring_ring. This problem was handled in 9f64df9 ("brcmfmac: Fix
26 bug in flowring management."). Starting with that it's safe to apply
27 this original patch as it doesn't cause a regression anymore.
28
29 This patch fixes an infinite loop on BCM4366 which is supported since
30 4.4 so it makes sense to apply it to stable 4.4+.
31
32 Cc: <stable@vger.kernel.org> # 4.4+
33 Reviewed-by: Arend Van Spriel <arend@broadcom.com>
34 Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
35 Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
36 Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
37 Signed-off-by: Arend van Spriel <arend@broadcom.com>
38 Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
39 ---
40
41 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
42 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
43 @@ -32,7 +32,7 @@
44 #define BRCMF_FLOWRING_LOW (BRCMF_FLOWRING_HIGH - 256)
45 #define BRCMF_FLOWRING_INVALID_IFIDX 0xff
46
47 -#define BRCMF_FLOWRING_HASH_AP(da, fifo, ifidx) (da[5] + fifo + ifidx * 16)
48 +#define BRCMF_FLOWRING_HASH_AP(da, fifo, ifidx) (da[5] * 2 + fifo + ifidx * 16)
49 #define BRCMF_FLOWRING_HASH_STA(fifo, ifidx) (fifo + ifidx * 16)
50
51 static const u8 brcmf_flowring_prio2fifo[] = {
52 @@ -68,7 +68,7 @@ u32 brcmf_flowring_lookup(struct brcmf_f
53 u8 prio, u8 ifidx)
54 {
55 struct brcmf_flowring_hash *hash;
56 - u8 hash_idx;
57 + u16 hash_idx;
58 u32 i;
59 bool found;
60 bool sta;
61 @@ -88,6 +88,7 @@ u32 brcmf_flowring_lookup(struct brcmf_f
62 }
63 hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) :
64 BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
65 + hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1);
66 found = false;
67 hash = flow->hash;
68 for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
69 @@ -98,6 +99,7 @@ u32 brcmf_flowring_lookup(struct brcmf_f
70 break;
71 }
72 hash_idx++;
73 + hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1);
74 }
75 if (found)
76 return hash[hash_idx].flowid;
77 @@ -111,7 +113,7 @@ u32 brcmf_flowring_create(struct brcmf_f
78 {
79 struct brcmf_flowring_ring *ring;
80 struct brcmf_flowring_hash *hash;
81 - u8 hash_idx;
82 + u16 hash_idx;
83 u32 i;
84 bool found;
85 u8 fifo;
86 @@ -131,6 +133,7 @@ u32 brcmf_flowring_create(struct brcmf_f
87 }
88 hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) :
89 BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
90 + hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1);
91 found = false;
92 hash = flow->hash;
93 for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
94 @@ -140,6 +143,7 @@ u32 brcmf_flowring_create(struct brcmf_f
95 break;
96 }
97 hash_idx++;
98 + hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1);
99 }
100 if (found) {
101 for (i = 0; i < flow->nrofrings; i++) {
102 @@ -169,7 +173,7 @@ u32 brcmf_flowring_create(struct brcmf_f
103 }
104
105
106 -u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid)
107 +u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u16 flowid)
108 {
109 struct brcmf_flowring_ring *ring;
110
111 @@ -179,7 +183,7 @@ u8 brcmf_flowring_tid(struct brcmf_flowr
112 }
113
114
115 -static void brcmf_flowring_block(struct brcmf_flowring *flow, u8 flowid,
116 +static void brcmf_flowring_block(struct brcmf_flowring *flow, u16 flowid,
117 bool blocked)
118 {
119 struct brcmf_flowring_ring *ring;
120 @@ -228,10 +232,10 @@ static void brcmf_flowring_block(struct
121 }
122
123
124 -void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid)
125 +void brcmf_flowring_delete(struct brcmf_flowring *flow, u16 flowid)
126 {
127 struct brcmf_flowring_ring *ring;
128 - u8 hash_idx;
129 + u16 hash_idx;
130 struct sk_buff *skb;
131
132 ring = flow->rings[flowid];
133 @@ -253,7 +257,7 @@ void brcmf_flowring_delete(struct brcmf_
134 }
135
136
137 -u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
138 +u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u16 flowid,
139 struct sk_buff *skb)
140 {
141 struct brcmf_flowring_ring *ring;
142 @@ -279,7 +283,7 @@ u32 brcmf_flowring_enqueue(struct brcmf_
143 }
144
145
146 -struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid)
147 +struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u16 flowid)
148 {
149 struct brcmf_flowring_ring *ring;
150 struct sk_buff *skb;
151 @@ -300,7 +304,7 @@ struct sk_buff *brcmf_flowring_dequeue(s
152 }
153
154
155 -void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid,
156 +void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u16 flowid,
157 struct sk_buff *skb)
158 {
159 struct brcmf_flowring_ring *ring;
160 @@ -311,7 +315,7 @@ void brcmf_flowring_reinsert(struct brcm
161 }
162
163
164 -u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid)
165 +u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u16 flowid)
166 {
167 struct brcmf_flowring_ring *ring;
168
169 @@ -326,7 +330,7 @@ u32 brcmf_flowring_qlen(struct brcmf_flo
170 }
171
172
173 -void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid)
174 +void brcmf_flowring_open(struct brcmf_flowring *flow, u16 flowid)
175 {
176 struct brcmf_flowring_ring *ring;
177
178 @@ -340,10 +344,10 @@ void brcmf_flowring_open(struct brcmf_fl
179 }
180
181
182 -u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u8 flowid)
183 +u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u16 flowid)
184 {
185 struct brcmf_flowring_ring *ring;
186 - u8 hash_idx;
187 + u16 hash_idx;
188
189 ring = flow->rings[flowid];
190 hash_idx = ring->hash_id;
191 @@ -384,7 +388,7 @@ void brcmf_flowring_detach(struct brcmf_
192 struct brcmf_pub *drvr = bus_if->drvr;
193 struct brcmf_flowring_tdls_entry *search;
194 struct brcmf_flowring_tdls_entry *remove;
195 - u8 flowid;
196 + u16 flowid;
197
198 for (flowid = 0; flowid < flow->nrofrings; flowid++) {
199 if (flow->rings[flowid])
200 @@ -408,7 +412,7 @@ void brcmf_flowring_configure_addr_mode(
201 struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
202 struct brcmf_pub *drvr = bus_if->drvr;
203 u32 i;
204 - u8 flowid;
205 + u16 flowid;
206
207 if (flow->addr_mode[ifidx] != addr_mode) {
208 for (i = 0; i < ARRAY_SIZE(flow->hash); i++) {
209 @@ -434,7 +438,7 @@ void brcmf_flowring_delete_peer(struct b
210 struct brcmf_flowring_tdls_entry *prev;
211 struct brcmf_flowring_tdls_entry *search;
212 u32 i;
213 - u8 flowid;
214 + u16 flowid;
215 bool sta;
216
217 sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT);
218 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h
219 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h
220 @@ -16,7 +16,7 @@
221 #define BRCMFMAC_FLOWRING_H
222
223
224 -#define BRCMF_FLOWRING_HASHSIZE 256
225 +#define BRCMF_FLOWRING_HASHSIZE 512 /* has to be 2^x */
226 #define BRCMF_FLOWRING_INVALID_ID 0xFFFFFFFF
227
228
229 @@ -24,7 +24,7 @@ struct brcmf_flowring_hash {
230 u8 mac[ETH_ALEN];
231 u8 fifo;
232 u8 ifidx;
233 - u8 flowid;
234 + u16 flowid;
235 };
236
237 enum ring_status {
238 @@ -61,16 +61,16 @@ u32 brcmf_flowring_lookup(struct brcmf_f
239 u8 prio, u8 ifidx);
240 u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
241 u8 prio, u8 ifidx);
242 -void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid);
243 -void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid);
244 -u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid);
245 -u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
246 +void brcmf_flowring_delete(struct brcmf_flowring *flow, u16 flowid);
247 +void brcmf_flowring_open(struct brcmf_flowring *flow, u16 flowid);
248 +u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u16 flowid);
249 +u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u16 flowid,
250 struct sk_buff *skb);
251 -struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid);
252 -void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid,
253 +struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u16 flowid);
254 +void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u16 flowid,
255 struct sk_buff *skb);
256 -u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid);
257 -u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u8 flowid);
258 +u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u16 flowid);
259 +u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u16 flowid);
260 struct brcmf_flowring *brcmf_flowring_attach(struct device *dev, u16 nrofrings);
261 void brcmf_flowring_detach(struct brcmf_flowring *flow);
262 void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx,
263 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
264 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
265 @@ -677,7 +677,7 @@ static u32 brcmf_msgbuf_flowring_create(
266 }
267
268
269 -static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u8 flowid)
270 +static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid)
271 {
272 struct brcmf_flowring *flow = msgbuf->flow;
273 struct brcmf_commonring *commonring;
274 @@ -1310,7 +1310,7 @@ int brcmf_proto_msgbuf_rx_trigger(struct
275 }
276
277
278 -void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid)
279 +void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid)
280 {
281 struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
282 struct msgbuf_tx_flowring_delete_req *delete;
283 @@ -1415,6 +1415,13 @@ int brcmf_proto_msgbuf_attach(struct brc
284 u32 count;
285
286 if_msgbuf = drvr->bus_if->msgbuf;
287 +
288 + if (if_msgbuf->nrof_flowrings >= BRCMF_FLOWRING_HASHSIZE) {
289 + brcmf_err("driver not configured for this many flowrings %d\n",
290 + if_msgbuf->nrof_flowrings);
291 + if_msgbuf->nrof_flowrings = BRCMF_FLOWRING_HASHSIZE - 1;
292 + }
293 +
294 msgbuf = kzalloc(sizeof(*msgbuf), GFP_KERNEL);
295 if (!msgbuf)
296 goto fail;
297 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
298 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
299 @@ -33,7 +33,7 @@
300
301
302 int brcmf_proto_msgbuf_rx_trigger(struct device *dev);
303 -void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid);
304 +void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid);
305 int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr);
306 void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr);
307 #else