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.
5 Content-Type: text/plain; charset=UTF-8
6 Content-Transfer-Encoding: 8bit
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
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.
17 This patch switches code to proper types and increases the maximum
18 number of supported flowrings to 512.
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 ...
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.
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+.
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>
41 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
42 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
44 #define BRCMF_FLOWRING_LOW (BRCMF_FLOWRING_HIGH - 256)
45 #define BRCMF_FLOWRING_INVALID_IFIDX 0xff
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)
51 static const u8 brcmf_flowring_prio2fifo[] = {
52 @@ -68,7 +68,7 @@ u32 brcmf_flowring_lookup(struct brcmf_f
55 struct brcmf_flowring_hash *hash;
61 @@ -88,6 +88,7 @@ u32 brcmf_flowring_lookup(struct brcmf_f
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);
68 for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
69 @@ -98,6 +99,7 @@ u32 brcmf_flowring_lookup(struct brcmf_f
73 + hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1);
76 return hash[hash_idx].flowid;
77 @@ -111,7 +113,7 @@ u32 brcmf_flowring_create(struct brcmf_f
79 struct brcmf_flowring_ring *ring;
80 struct brcmf_flowring_hash *hash;
86 @@ -131,6 +133,7 @@ u32 brcmf_flowring_create(struct brcmf_f
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);
93 for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
94 @@ -140,6 +143,7 @@ u32 brcmf_flowring_create(struct brcmf_f
98 + hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1);
101 for (i = 0; i < flow->nrofrings; i++) {
102 @@ -169,7 +173,7 @@ u32 brcmf_flowring_create(struct brcmf_f
106 -u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid)
107 +u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u16 flowid)
109 struct brcmf_flowring_ring *ring;
111 @@ -179,7 +183,7 @@ u8 brcmf_flowring_tid(struct brcmf_flowr
115 -static void brcmf_flowring_block(struct brcmf_flowring *flow, u8 flowid,
116 +static void brcmf_flowring_block(struct brcmf_flowring *flow, u16 flowid,
119 struct brcmf_flowring_ring *ring;
120 @@ -228,10 +232,10 @@ static void brcmf_flowring_block(struct
124 -void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid)
125 +void brcmf_flowring_delete(struct brcmf_flowring *flow, u16 flowid)
127 struct brcmf_flowring_ring *ring;
132 ring = flow->rings[flowid];
133 @@ -253,7 +257,7 @@ void brcmf_flowring_delete(struct brcmf_
137 -u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
138 +u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u16 flowid,
141 struct brcmf_flowring_ring *ring;
142 @@ -279,7 +283,7 @@ u32 brcmf_flowring_enqueue(struct brcmf_
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)
149 struct brcmf_flowring_ring *ring;
151 @@ -300,7 +304,7 @@ struct sk_buff *brcmf_flowring_dequeue(s
155 -void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid,
156 +void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u16 flowid,
159 struct brcmf_flowring_ring *ring;
160 @@ -311,7 +315,7 @@ void brcmf_flowring_reinsert(struct brcm
164 -u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid)
165 +u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u16 flowid)
167 struct brcmf_flowring_ring *ring;
169 @@ -326,7 +330,7 @@ u32 brcmf_flowring_qlen(struct brcmf_flo
173 -void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid)
174 +void brcmf_flowring_open(struct brcmf_flowring *flow, u16 flowid)
176 struct brcmf_flowring_ring *ring;
178 @@ -340,10 +344,10 @@ void brcmf_flowring_open(struct brcmf_fl
182 -u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u8 flowid)
183 +u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u16 flowid)
185 struct brcmf_flowring_ring *ring;
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;
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;
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;
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
221 #define BRCMFMAC_FLOWRING_H
224 -#define BRCMF_FLOWRING_HASHSIZE 256
225 +#define BRCMF_FLOWRING_HASHSIZE 512 /* has to be 2^x */
226 #define BRCMF_FLOWRING_INVALID_ID 0xFFFFFFFF
229 @@ -24,7 +24,7 @@ struct brcmf_flowring_hash {
238 @@ -61,16 +61,16 @@ u32 brcmf_flowring_lookup(struct brcmf_f
240 u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
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(
269 -static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u8 flowid)
270 +static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid)
272 struct brcmf_flowring *flow = msgbuf->flow;
273 struct brcmf_commonring *commonring;
274 @@ -1310,7 +1310,7 @@ int brcmf_proto_msgbuf_rx_trigger(struct
278 -void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid)
279 +void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid)
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
286 if_msgbuf = drvr->bus_if->msgbuf;
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;
294 msgbuf = kzalloc(sizeof(*msgbuf), GFP_KERNEL);
297 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
298 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
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);