rpcd: iwinfo plugin fixes
[openwrt.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