brcmfmac: remove redundant assignment to pointer 'entry'
[linux-2.6-microblaze.git] / drivers / net / wireless / broadcom / brcm80211 / brcmfmac / fwsignal.c
1 // SPDX-License-Identifier: ISC
2 /*
3  * Copyright (c) 2010 Broadcom Corporation
4  */
5 #include <linux/types.h>
6 #include <linux/module.h>
7 #include <linux/if_ether.h>
8 #include <linux/spinlock.h>
9 #include <linux/skbuff.h>
10 #include <linux/netdevice.h>
11 #include <linux/etherdevice.h>
12 #include <linux/err.h>
13 #include <linux/jiffies.h>
14 #include <net/cfg80211.h>
15
16 #include <brcmu_utils.h>
17 #include <brcmu_wifi.h>
18 #include "core.h"
19 #include "debug.h"
20 #include "bus.h"
21 #include "fwil.h"
22 #include "fwil_types.h"
23 #include "fweh.h"
24 #include "fwsignal.h"
25 #include "p2p.h"
26 #include "cfg80211.h"
27 #include "proto.h"
28 #include "bcdc.h"
29 #include "common.h"
30
31 /**
32  * DOC: Firmware Signalling
33  *
34  * Firmware can send signals to host and vice versa, which are passed in the
35  * data packets using TLV based header. This signalling layer is on top of the
36  * BDC bus protocol layer.
37  */
38
39 /*
40  * single definition for firmware-driver flow control tlv's.
41  *
42  * each tlv is specified by BRCMF_FWS_TLV_DEF(name, ID, length).
43  * A length value 0 indicates variable length tlv.
44  */
45 #define BRCMF_FWS_TLV_DEFLIST \
46         BRCMF_FWS_TLV_DEF(MAC_OPEN, 1, 1) \
47         BRCMF_FWS_TLV_DEF(MAC_CLOSE, 2, 1) \
48         BRCMF_FWS_TLV_DEF(MAC_REQUEST_CREDIT, 3, 2) \
49         BRCMF_FWS_TLV_DEF(TXSTATUS, 4, 4) \
50         BRCMF_FWS_TLV_DEF(PKTTAG, 5, 4) \
51         BRCMF_FWS_TLV_DEF(MACDESC_ADD,  6, 8) \
52         BRCMF_FWS_TLV_DEF(MACDESC_DEL, 7, 8) \
53         BRCMF_FWS_TLV_DEF(RSSI, 8, 1) \
54         BRCMF_FWS_TLV_DEF(INTERFACE_OPEN, 9, 1) \
55         BRCMF_FWS_TLV_DEF(INTERFACE_CLOSE, 10, 1) \
56         BRCMF_FWS_TLV_DEF(FIFO_CREDITBACK, 11, 6) \
57         BRCMF_FWS_TLV_DEF(PENDING_TRAFFIC_BMP, 12, 2) \
58         BRCMF_FWS_TLV_DEF(MAC_REQUEST_PACKET, 13, 3) \
59         BRCMF_FWS_TLV_DEF(HOST_REORDER_RXPKTS, 14, 10) \
60         BRCMF_FWS_TLV_DEF(TRANS_ID, 18, 6) \
61         BRCMF_FWS_TLV_DEF(COMP_TXSTATUS, 19, 1) \
62         BRCMF_FWS_TLV_DEF(FILLER, 255, 0)
63
64 /*
65  * enum brcmf_fws_tlv_type - definition of tlv identifiers.
66  */
67 #define BRCMF_FWS_TLV_DEF(name, id, len) \
68         BRCMF_FWS_TYPE_ ## name =  id,
69 enum brcmf_fws_tlv_type {
70         BRCMF_FWS_TLV_DEFLIST
71         BRCMF_FWS_TYPE_INVALID
72 };
73 #undef BRCMF_FWS_TLV_DEF
74
75 /*
76  * enum brcmf_fws_tlv_len - definition of tlv lengths.
77  */
78 #define BRCMF_FWS_TLV_DEF(name, id, len) \
79         BRCMF_FWS_TYPE_ ## name ## _LEN = (len),
80 enum brcmf_fws_tlv_len {
81         BRCMF_FWS_TLV_DEFLIST
82 };
83 #undef BRCMF_FWS_TLV_DEF
84
85 /* AMPDU rx reordering definitions */
86 #define BRCMF_RXREORDER_FLOWID_OFFSET           0
87 #define BRCMF_RXREORDER_MAXIDX_OFFSET           2
88 #define BRCMF_RXREORDER_FLAGS_OFFSET            4
89 #define BRCMF_RXREORDER_CURIDX_OFFSET           6
90 #define BRCMF_RXREORDER_EXPIDX_OFFSET           8
91
92 #define BRCMF_RXREORDER_DEL_FLOW                0x01
93 #define BRCMF_RXREORDER_FLUSH_ALL               0x02
94 #define BRCMF_RXREORDER_CURIDX_VALID            0x04
95 #define BRCMF_RXREORDER_EXPIDX_VALID            0x08
96 #define BRCMF_RXREORDER_NEW_HOLE                0x10
97
98 #ifdef DEBUG
99 /*
100  * brcmf_fws_tlv_names - array of tlv names.
101  */
102 #define BRCMF_FWS_TLV_DEF(name, id, len) \
103         { id, #name },
104 static struct {
105         enum brcmf_fws_tlv_type id;
106         const char *name;
107 } brcmf_fws_tlv_names[] = {
108         BRCMF_FWS_TLV_DEFLIST
109 };
110 #undef BRCMF_FWS_TLV_DEF
111
112
113 static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
114 {
115         int i;
116
117         for (i = 0; i < ARRAY_SIZE(brcmf_fws_tlv_names); i++)
118                 if (brcmf_fws_tlv_names[i].id == id)
119                         return brcmf_fws_tlv_names[i].name;
120
121         return "INVALID";
122 }
123 #else
124 static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
125 {
126         return "NODEBUG";
127 }
128 #endif /* DEBUG */
129
130 /*
131  * The PKTTAG tlv has additional bytes when firmware-signalling
132  * mode has REUSESEQ flag set.
133  */
134 #define BRCMF_FWS_TYPE_SEQ_LEN                          2
135
136 /*
137  * flags used to enable tlv signalling from firmware.
138  */
139 #define BRCMF_FWS_FLAGS_RSSI_SIGNALS                    0x0001
140 #define BRCMF_FWS_FLAGS_XONXOFF_SIGNALS                 0x0002
141 #define BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS           0x0004
142 #define BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE        0x0008
143 #define BRCMF_FWS_FLAGS_PSQ_GENERATIONFSM_ENABLE        0x0010
144 #define BRCMF_FWS_FLAGS_PSQ_ZERO_BUFFER_ENABLE          0x0020
145 #define BRCMF_FWS_FLAGS_HOST_RXREORDER_ACTIVE           0x0040
146
147 #define BRCMF_FWS_MAC_DESC_TABLE_SIZE                   32
148 #define BRCMF_FWS_MAC_DESC_ID_INVALID                   0xff
149
150 #define BRCMF_FWS_HOSTIF_FLOWSTATE_OFF                  0
151 #define BRCMF_FWS_HOSTIF_FLOWSTATE_ON                   1
152 #define BRCMF_FWS_FLOWCONTROL_HIWATER                   128
153 #define BRCMF_FWS_FLOWCONTROL_LOWATER                   64
154
155 #define BRCMF_FWS_PSQ_PREC_COUNT                ((BRCMF_FWS_FIFO_COUNT + 1) * 2)
156 #define BRCMF_FWS_PSQ_LEN                               256
157
158 #define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST                 0x01
159 #define BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED               0x02
160
161 #define BRCMF_FWS_RET_OK_NOSCHEDULE                     0
162 #define BRCMF_FWS_RET_OK_SCHEDULE                       1
163
164 #define BRCMF_FWS_MODE_REUSESEQ_SHIFT                   3       /* seq reuse */
165 #define BRCMF_FWS_MODE_SET_REUSESEQ(x, val)     ((x) = \
166                 ((x) & ~(1 << BRCMF_FWS_MODE_REUSESEQ_SHIFT)) | \
167                 (((val) & 1) << BRCMF_FWS_MODE_REUSESEQ_SHIFT))
168 #define BRCMF_FWS_MODE_GET_REUSESEQ(x)  \
169                 (((x) >> BRCMF_FWS_MODE_REUSESEQ_SHIFT) & 1)
170
171 /**
172  * enum brcmf_fws_skb_state - indicates processing state of skb.
173  *
174  * @BRCMF_FWS_SKBSTATE_NEW: sk_buff is newly arrived in the driver.
175  * @BRCMF_FWS_SKBSTATE_DELAYED: sk_buff had to wait on queue.
176  * @BRCMF_FWS_SKBSTATE_SUPPRESSED: sk_buff has been suppressed by firmware.
177  * @BRCMF_FWS_SKBSTATE_TIM: allocated for TIM update info.
178  */
179 enum brcmf_fws_skb_state {
180         BRCMF_FWS_SKBSTATE_NEW,
181         BRCMF_FWS_SKBSTATE_DELAYED,
182         BRCMF_FWS_SKBSTATE_SUPPRESSED,
183         BRCMF_FWS_SKBSTATE_TIM
184 };
185
186 /**
187  * struct brcmf_skbuff_cb - control buffer associated with skbuff.
188  *
189  * @bus_flags: 2 bytes reserved for bus specific parameters
190  * @if_flags: holds interface index and packet related flags.
191  * @htod: host to device packet identifier (used in PKTTAG tlv).
192  * @htod_seq: this 16-bit is original seq number for every suppress packet.
193  * @state: transmit state of the packet.
194  * @mac: descriptor related to destination for this packet.
195  *
196  * This information is stored in control buffer struct sk_buff::cb, which
197  * provides 48 bytes of storage so this structure should not exceed that.
198  */
199 struct brcmf_skbuff_cb {
200         u16 bus_flags;
201         u16 if_flags;
202         u32 htod;
203         u16 htod_seq;
204         enum brcmf_fws_skb_state state;
205         struct brcmf_fws_mac_descriptor *mac;
206 };
207
208 /*
209  * macro casting skbuff control buffer to struct brcmf_skbuff_cb.
210  */
211 #define brcmf_skbcb(skb)        ((struct brcmf_skbuff_cb *)((skb)->cb))
212
213 /*
214  * sk_buff control if flags
215  *
216  *      b[11]  - packet sent upon firmware request.
217  *      b[10]  - packet only contains signalling data.
218  *      b[9]   - packet is a tx packet.
219  *      b[8]   - packet used requested credit
220  *      b[7]   - interface in AP mode.
221  *      b[3:0] - interface index.
222  */
223 #define BRCMF_SKB_IF_FLAGS_REQUESTED_MASK       0x0800
224 #define BRCMF_SKB_IF_FLAGS_REQUESTED_SHIFT      11
225 #define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_MASK     0x0400
226 #define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_SHIFT    10
227 #define BRCMF_SKB_IF_FLAGS_TRANSMIT_MASK        0x0200
228 #define BRCMF_SKB_IF_FLAGS_TRANSMIT_SHIFT       9
229 #define BRCMF_SKB_IF_FLAGS_REQ_CREDIT_MASK      0x0100
230 #define BRCMF_SKB_IF_FLAGS_REQ_CREDIT_SHIFT     8
231 #define BRCMF_SKB_IF_FLAGS_IF_AP_MASK           0x0080
232 #define BRCMF_SKB_IF_FLAGS_IF_AP_SHIFT          7
233 #define BRCMF_SKB_IF_FLAGS_INDEX_MASK           0x000f
234 #define BRCMF_SKB_IF_FLAGS_INDEX_SHIFT          0
235
236 #define brcmf_skb_if_flags_set_field(skb, field, value) \
237         brcmu_maskset16(&(brcmf_skbcb(skb)->if_flags), \
238                         BRCMF_SKB_IF_FLAGS_ ## field ## _MASK, \
239                         BRCMF_SKB_IF_FLAGS_ ## field ## _SHIFT, (value))
240 #define brcmf_skb_if_flags_get_field(skb, field) \
241         brcmu_maskget16(brcmf_skbcb(skb)->if_flags, \
242                         BRCMF_SKB_IF_FLAGS_ ## field ## _MASK, \
243                         BRCMF_SKB_IF_FLAGS_ ## field ## _SHIFT)
244
245 /*
246  * sk_buff control packet identifier
247  *
248  * 32-bit packet identifier used in PKTTAG tlv from host to dongle.
249  *
250  * - Generated at the host (e.g. dhd)
251  * - Seen as a generic sequence number by firmware except for the flags field.
252  *
253  * Generation   : b[31] => generation number for this packet [host->fw]
254  *                         OR, current generation number [fw->host]
255  * Flags        : b[30:27] => command, status flags
256  * FIFO-AC      : b[26:24] => AC-FIFO id
257  * h-slot       : b[23:8] => hanger-slot
258  * freerun      : b[7:0] => A free running counter
259  */
260 #define BRCMF_SKB_HTOD_TAG_GENERATION_MASK              0x80000000
261 #define BRCMF_SKB_HTOD_TAG_GENERATION_SHIFT             31
262 #define BRCMF_SKB_HTOD_TAG_FLAGS_MASK                   0x78000000
263 #define BRCMF_SKB_HTOD_TAG_FLAGS_SHIFT                  27
264 #define BRCMF_SKB_HTOD_TAG_FIFO_MASK                    0x07000000
265 #define BRCMF_SKB_HTOD_TAG_FIFO_SHIFT                   24
266 #define BRCMF_SKB_HTOD_TAG_HSLOT_MASK                   0x00ffff00
267 #define BRCMF_SKB_HTOD_TAG_HSLOT_SHIFT                  8
268 #define BRCMF_SKB_HTOD_TAG_FREERUN_MASK                 0x000000ff
269 #define BRCMF_SKB_HTOD_TAG_FREERUN_SHIFT                0
270
271 #define brcmf_skb_htod_tag_set_field(skb, field, value) \
272         brcmu_maskset32(&(brcmf_skbcb(skb)->htod), \
273                         BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \
274                         BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT, (value))
275 #define brcmf_skb_htod_tag_get_field(skb, field) \
276         brcmu_maskget32(brcmf_skbcb(skb)->htod, \
277                         BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \
278                         BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT)
279
280 #define BRCMF_SKB_HTOD_SEQ_FROMFW_MASK                  0x2000
281 #define BRCMF_SKB_HTOD_SEQ_FROMFW_SHIFT                 13
282 #define BRCMF_SKB_HTOD_SEQ_FROMDRV_MASK                 0x1000
283 #define BRCMF_SKB_HTOD_SEQ_FROMDRV_SHIFT                12
284 #define BRCMF_SKB_HTOD_SEQ_NR_MASK                      0x0fff
285 #define BRCMF_SKB_HTOD_SEQ_NR_SHIFT                     0
286
287 #define brcmf_skb_htod_seq_set_field(skb, field, value) \
288         brcmu_maskset16(&(brcmf_skbcb(skb)->htod_seq), \
289                         BRCMF_SKB_HTOD_SEQ_ ## field ## _MASK, \
290                         BRCMF_SKB_HTOD_SEQ_ ## field ## _SHIFT, (value))
291 #define brcmf_skb_htod_seq_get_field(skb, field) \
292         brcmu_maskget16(brcmf_skbcb(skb)->htod_seq, \
293                         BRCMF_SKB_HTOD_SEQ_ ## field ## _MASK, \
294                         BRCMF_SKB_HTOD_SEQ_ ## field ## _SHIFT)
295
296 #define BRCMF_FWS_TXSTAT_GENERATION_MASK        0x80000000
297 #define BRCMF_FWS_TXSTAT_GENERATION_SHIFT       31
298 #define BRCMF_FWS_TXSTAT_FLAGS_MASK             0x78000000
299 #define BRCMF_FWS_TXSTAT_FLAGS_SHIFT            27
300 #define BRCMF_FWS_TXSTAT_FIFO_MASK              0x07000000
301 #define BRCMF_FWS_TXSTAT_FIFO_SHIFT             24
302 #define BRCMF_FWS_TXSTAT_HSLOT_MASK             0x00FFFF00
303 #define BRCMF_FWS_TXSTAT_HSLOT_SHIFT            8
304 #define BRCMF_FWS_TXSTAT_FREERUN_MASK           0x000000FF
305 #define BRCMF_FWS_TXSTAT_FREERUN_SHIFT          0
306
307 #define brcmf_txstatus_get_field(txs, field) \
308         brcmu_maskget32(txs, BRCMF_FWS_TXSTAT_ ## field ## _MASK, \
309                         BRCMF_FWS_TXSTAT_ ## field ## _SHIFT)
310
311 /* How long to defer borrowing in jiffies */
312 #define BRCMF_FWS_BORROW_DEFER_PERIOD           (HZ / 10)
313
314
315 /**
316  * enum brcmf_fws_txstatus - txstatus flag values.
317  *
318  * @BRCMF_FWS_TXSTATUS_DISCARD:
319  *      host is free to discard the packet.
320  * @BRCMF_FWS_TXSTATUS_CORE_SUPPRESS:
321  *      802.11 core suppressed the packet.
322  * @BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS:
323  *      firmware suppress the packet as device is already in PS mode.
324  * @BRCMF_FWS_TXSTATUS_FW_TOSSED:
325  *      firmware tossed the packet.
326  * @BRCMF_FWS_TXSTATUS_FW_DISCARD_NOACK:
327  *      firmware tossed the packet after retries.
328  * @BRCMF_FWS_TXSTATUS_FW_SUPPRESS_ACKED:
329  *      firmware wrongly reported suppressed previously, now fixing to acked.
330  * @BRCMF_FWS_TXSTATUS_HOST_TOSSED:
331  *      host tossed the packet.
332  */
333 enum brcmf_fws_txstatus {
334         BRCMF_FWS_TXSTATUS_DISCARD,
335         BRCMF_FWS_TXSTATUS_CORE_SUPPRESS,
336         BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS,
337         BRCMF_FWS_TXSTATUS_FW_TOSSED,
338         BRCMF_FWS_TXSTATUS_FW_DISCARD_NOACK,
339         BRCMF_FWS_TXSTATUS_FW_SUPPRESS_ACKED,
340         BRCMF_FWS_TXSTATUS_HOST_TOSSED
341 };
342
343 enum brcmf_fws_fcmode {
344         BRCMF_FWS_FCMODE_NONE,
345         BRCMF_FWS_FCMODE_IMPLIED_CREDIT,
346         BRCMF_FWS_FCMODE_EXPLICIT_CREDIT
347 };
348
349 enum brcmf_fws_mac_desc_state {
350         BRCMF_FWS_STATE_OPEN = 1,
351         BRCMF_FWS_STATE_CLOSE
352 };
353
354 /**
355  * struct brcmf_fws_mac_descriptor - firmware signalling data per node/interface
356  *
357  * @name: name of the descriptor.
358  * @occupied: slot is in use.
359  * @mac_handle: handle for mac entry determined by firmware.
360  * @interface_id: interface index.
361  * @state: current state.
362  * @suppressed: mac entry is suppressed.
363  * @generation: generation bit.
364  * @ac_bitmap: ac queue bitmap.
365  * @requested_credit: credits requested by firmware.
366  * @requested_packet: packet requested by firmware.
367  * @ea: ethernet address.
368  * @seq: per-node free-running sequence.
369  * @psq: power-save queue.
370  * @transit_count: packet in transit to firmware.
371  * @suppr_transit_count: suppressed packet in transit to firmware.
372  * @send_tim_signal: if set tim signal will be sent.
373  * @traffic_pending_bmp: traffic pending bitmap.
374  * @traffic_lastreported_bmp: traffic last reported bitmap.
375  */
376 struct brcmf_fws_mac_descriptor {
377         char name[16];
378         u8 occupied;
379         u8 mac_handle;
380         u8 interface_id;
381         u8 state;
382         bool suppressed;
383         u8 generation;
384         u8 ac_bitmap;
385         u8 requested_credit;
386         u8 requested_packet;
387         u8 ea[ETH_ALEN];
388         u8 seq[BRCMF_FWS_FIFO_COUNT];
389         struct pktq psq;
390         int transit_count;
391         int suppr_transit_count;
392         bool send_tim_signal;
393         u8 traffic_pending_bmp;
394         u8 traffic_lastreported_bmp;
395 };
396
397 #define BRCMF_FWS_HANGER_MAXITEMS       3072
398 #define BRCMF_BORROW_RATIO                      3
399
400 /**
401  * enum brcmf_fws_hanger_item_state - state of hanger item.
402  *
403  * @BRCMF_FWS_HANGER_ITEM_STATE_FREE: item is free for use.
404  * @BRCMF_FWS_HANGER_ITEM_STATE_INUSE: item is in use.
405  * @BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED: item was suppressed.
406  */
407 enum brcmf_fws_hanger_item_state {
408         BRCMF_FWS_HANGER_ITEM_STATE_FREE = 1,
409         BRCMF_FWS_HANGER_ITEM_STATE_INUSE,
410         BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED
411 };
412
413
414 /**
415  * struct brcmf_fws_hanger_item - single entry for tx pending packet.
416  *
417  * @state: entry is either free or occupied.
418  * @pkt: packet itself.
419  */
420 struct brcmf_fws_hanger_item {
421         enum brcmf_fws_hanger_item_state state;
422         struct sk_buff *pkt;
423 };
424
425 /**
426  * struct brcmf_fws_hanger - holds packets awaiting firmware txstatus.
427  *
428  * @pushed: packets pushed to await txstatus.
429  * @popped: packets popped upon handling txstatus.
430  * @failed_to_push: packets that could not be pushed.
431  * @failed_to_pop: packets that could not be popped.
432  * @failed_slotfind: packets for which failed to find an entry.
433  * @slot_pos: last returned item index for a free entry.
434  * @items: array of hanger items.
435  */
436 struct brcmf_fws_hanger {
437         u32 pushed;
438         u32 popped;
439         u32 failed_to_push;
440         u32 failed_to_pop;
441         u32 failed_slotfind;
442         u32 slot_pos;
443         struct brcmf_fws_hanger_item items[BRCMF_FWS_HANGER_MAXITEMS];
444 };
445
446 struct brcmf_fws_macdesc_table {
447         struct brcmf_fws_mac_descriptor nodes[BRCMF_FWS_MAC_DESC_TABLE_SIZE];
448         struct brcmf_fws_mac_descriptor iface[BRCMF_MAX_IFS];
449         struct brcmf_fws_mac_descriptor other;
450 };
451
452 struct brcmf_fws_stats {
453         u32 tlv_parse_failed;
454         u32 tlv_invalid_type;
455         u32 header_only_pkt;
456         u32 header_pulls;
457         u32 pkt2bus;
458         u32 send_pkts[5];
459         u32 requested_sent[5];
460         u32 generic_error;
461         u32 mac_update_failed;
462         u32 mac_ps_update_failed;
463         u32 if_update_failed;
464         u32 packet_request_failed;
465         u32 credit_request_failed;
466         u32 rollback_success;
467         u32 rollback_failed;
468         u32 delayq_full_error;
469         u32 supprq_full_error;
470         u32 txs_indicate;
471         u32 txs_discard;
472         u32 txs_supp_core;
473         u32 txs_supp_ps;
474         u32 txs_tossed;
475         u32 txs_host_tossed;
476         u32 bus_flow_block;
477         u32 fws_flow_block;
478 };
479
480 struct brcmf_fws_info {
481         struct brcmf_pub *drvr;
482         spinlock_t spinlock;
483         ulong flags;
484         struct brcmf_fws_stats stats;
485         struct brcmf_fws_hanger hanger;
486         enum brcmf_fws_fcmode fcmode;
487         bool fw_signals;
488         bool bcmc_credit_check;
489         struct brcmf_fws_macdesc_table desc;
490         struct workqueue_struct *fws_wq;
491         struct work_struct fws_dequeue_work;
492         u32 fifo_enqpkt[BRCMF_FWS_FIFO_COUNT];
493         int fifo_credit[BRCMF_FWS_FIFO_COUNT];
494         int init_fifo_credit[BRCMF_FWS_FIFO_COUNT];
495         int credits_borrowed[BRCMF_FWS_FIFO_AC_VO + 1]
496                 [BRCMF_FWS_FIFO_AC_VO + 1];
497         int deq_node_pos[BRCMF_FWS_FIFO_COUNT];
498         u32 fifo_credit_map;
499         u32 fifo_delay_map;
500         unsigned long borrow_defer_timestamp;
501         bool bus_flow_blocked;
502         bool creditmap_received;
503         u8 mode;
504         bool avoid_queueing;
505 };
506
507 #define BRCMF_FWS_TLV_DEF(name, id, len) \
508         case BRCMF_FWS_TYPE_ ## name: \
509                 return len;
510
511 /**
512  * brcmf_fws_get_tlv_len() - returns defined length for given tlv id.
513  *
514  * @fws: firmware-signalling information.
515  * @id: identifier of the TLV.
516  *
517  * Return: the specified length for the given TLV; Otherwise -EINVAL.
518  */
519 static int brcmf_fws_get_tlv_len(struct brcmf_fws_info *fws,
520                                  enum brcmf_fws_tlv_type id)
521 {
522         switch (id) {
523         BRCMF_FWS_TLV_DEFLIST
524         default:
525                 fws->stats.tlv_invalid_type++;
526                 break;
527         }
528         return -EINVAL;
529 }
530 #undef BRCMF_FWS_TLV_DEF
531
532 static void brcmf_fws_lock(struct brcmf_fws_info *fws)
533                 __acquires(&fws->spinlock)
534 {
535         spin_lock_irqsave(&fws->spinlock, fws->flags);
536 }
537
538 static void brcmf_fws_unlock(struct brcmf_fws_info *fws)
539                 __releases(&fws->spinlock)
540 {
541         spin_unlock_irqrestore(&fws->spinlock, fws->flags);
542 }
543
544 static bool brcmf_fws_ifidx_match(struct sk_buff *skb, void *arg)
545 {
546         u32 ifidx = brcmf_skb_if_flags_get_field(skb, INDEX);
547         return ifidx == *(int *)arg;
548 }
549
550 static void brcmf_fws_hanger_init(struct brcmf_fws_hanger *hanger)
551 {
552         int i;
553
554         memset(hanger, 0, sizeof(*hanger));
555         for (i = 0; i < ARRAY_SIZE(hanger->items); i++)
556                 hanger->items[i].state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
557 }
558
559 static u32 brcmf_fws_hanger_get_free_slot(struct brcmf_fws_hanger *h)
560 {
561         u32 i;
562
563         i = (h->slot_pos + 1) % BRCMF_FWS_HANGER_MAXITEMS;
564
565         while (i != h->slot_pos) {
566                 if (h->items[i].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
567                         h->slot_pos = i;
568                         goto done;
569                 }
570                 i++;
571                 if (i == BRCMF_FWS_HANGER_MAXITEMS)
572                         i = 0;
573         }
574         brcmf_err("all slots occupied\n");
575         h->failed_slotfind++;
576         i = BRCMF_FWS_HANGER_MAXITEMS;
577 done:
578         return i;
579 }
580
581 static int brcmf_fws_hanger_pushpkt(struct brcmf_fws_hanger *h,
582                                     struct sk_buff *pkt, u32 slot_id)
583 {
584         if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
585                 return -ENOENT;
586
587         if (h->items[slot_id].state != BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
588                 brcmf_err("slot is not free\n");
589                 h->failed_to_push++;
590                 return -EINVAL;
591         }
592
593         h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_INUSE;
594         h->items[slot_id].pkt = pkt;
595         h->pushed++;
596         return 0;
597 }
598
599 static inline int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h,
600                                           u32 slot_id, struct sk_buff **pktout,
601                                           bool remove_item)
602 {
603         if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
604                 return -ENOENT;
605
606         if (h->items[slot_id].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
607                 brcmf_err("entry not in use\n");
608                 h->failed_to_pop++;
609                 return -EINVAL;
610         }
611
612         *pktout = h->items[slot_id].pkt;
613         if (remove_item) {
614                 h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
615                 h->items[slot_id].pkt = NULL;
616                 h->popped++;
617         }
618         return 0;
619 }
620
621 static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q,
622                                 int ifidx)
623 {
624         struct brcmf_fws_hanger_item *hi;
625         bool (*matchfn)(struct sk_buff *, void *) = NULL;
626         struct sk_buff *skb;
627         int prec;
628         u32 hslot;
629
630         if (ifidx != -1)
631                 matchfn = brcmf_fws_ifidx_match;
632         for (prec = 0; prec < q->num_prec; prec++) {
633                 skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
634                 while (skb) {
635                         hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
636                         hi = &fws->hanger.items[hslot];
637                         WARN_ON(skb != hi->pkt);
638                         hi->state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
639                         brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
640                                                 true);
641                         brcmu_pkt_buf_free_skb(skb);
642                         skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
643                 }
644         }
645 }
646
647 static int brcmf_fws_hanger_mark_suppressed(struct brcmf_fws_hanger *h,
648                                             u32 slot_id)
649 {
650         if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
651                 return -ENOENT;
652
653         if (h->items[slot_id].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
654                 brcmf_err("entry not in use\n");
655                 return -EINVAL;
656         }
657
658         h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED;
659         return 0;
660 }
661
662 static void brcmf_fws_hanger_cleanup(struct brcmf_fws_info *fws,
663                                      bool (*fn)(struct sk_buff *, void *),
664                                      int ifidx)
665 {
666         struct brcmf_fws_hanger *h = &fws->hanger;
667         struct sk_buff *skb;
668         int i;
669         enum brcmf_fws_hanger_item_state s;
670
671         for (i = 0; i < ARRAY_SIZE(h->items); i++) {
672                 s = h->items[i].state;
673                 if (s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE ||
674                     s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED) {
675                         skb = h->items[i].pkt;
676                         if (fn == NULL || fn(skb, &ifidx)) {
677                                 /* suppress packets freed from psq */
678                                 if (s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE)
679                                         brcmu_pkt_buf_free_skb(skb);
680                                 h->items[i].state =
681                                         BRCMF_FWS_HANGER_ITEM_STATE_FREE;
682                         }
683                 }
684         }
685 }
686
687 static void brcmf_fws_macdesc_set_name(struct brcmf_fws_info *fws,
688                                        struct brcmf_fws_mac_descriptor *desc)
689 {
690         if (desc == &fws->desc.other)
691                 strlcpy(desc->name, "MAC-OTHER", sizeof(desc->name));
692         else if (desc->mac_handle)
693                 scnprintf(desc->name, sizeof(desc->name), "MAC-%d:%d",
694                           desc->mac_handle, desc->interface_id);
695         else
696                 scnprintf(desc->name, sizeof(desc->name), "MACIF:%d",
697                           desc->interface_id);
698 }
699
700 static void brcmf_fws_macdesc_init(struct brcmf_fws_mac_descriptor *desc,
701                                    u8 *addr, u8 ifidx)
702 {
703         brcmf_dbg(TRACE,
704                   "enter: desc %p ea=%pM, ifidx=%u\n", desc, addr, ifidx);
705         desc->occupied = 1;
706         desc->state = BRCMF_FWS_STATE_OPEN;
707         desc->requested_credit = 0;
708         desc->requested_packet = 0;
709         /* depending on use may need ifp->bsscfgidx instead */
710         desc->interface_id = ifidx;
711         desc->ac_bitmap = 0xff; /* update this when handling APSD */
712         if (addr)
713                 memcpy(&desc->ea[0], addr, ETH_ALEN);
714 }
715
716 static
717 void brcmf_fws_macdesc_deinit(struct brcmf_fws_mac_descriptor *desc)
718 {
719         brcmf_dbg(TRACE,
720                   "enter: ea=%pM, ifidx=%u\n", desc->ea, desc->interface_id);
721         desc->occupied = 0;
722         desc->state = BRCMF_FWS_STATE_CLOSE;
723         desc->requested_credit = 0;
724         desc->requested_packet = 0;
725 }
726
727 static struct brcmf_fws_mac_descriptor *
728 brcmf_fws_macdesc_lookup(struct brcmf_fws_info *fws, u8 *ea)
729 {
730         struct brcmf_fws_mac_descriptor *entry;
731         int i;
732
733         if (ea == NULL)
734                 return ERR_PTR(-EINVAL);
735
736         entry = &fws->desc.nodes[0];
737         for (i = 0; i < ARRAY_SIZE(fws->desc.nodes); i++) {
738                 if (entry->occupied && !memcmp(entry->ea, ea, ETH_ALEN))
739                         return entry;
740                 entry++;
741         }
742
743         return ERR_PTR(-ENOENT);
744 }
745
746 static struct brcmf_fws_mac_descriptor*
747 brcmf_fws_macdesc_find(struct brcmf_fws_info *fws, struct brcmf_if *ifp, u8 *da)
748 {
749         struct brcmf_fws_mac_descriptor *entry;
750         bool multicast;
751
752         multicast = is_multicast_ether_addr(da);
753
754         /* Multicast destination, STA and P2P clients get the interface entry.
755          * STA/GC gets the Mac Entry for TDLS destinations, TDLS destinations
756          * have their own entry.
757          */
758         if (multicast && ifp->fws_desc) {
759                 entry = ifp->fws_desc;
760                 goto done;
761         }
762
763         entry = brcmf_fws_macdesc_lookup(fws, da);
764         if (IS_ERR(entry))
765                 entry = ifp->fws_desc;
766
767 done:
768         return entry;
769 }
770
771 static bool brcmf_fws_macdesc_closed(struct brcmf_fws_info *fws,
772                                      struct brcmf_fws_mac_descriptor *entry,
773                                      int fifo)
774 {
775         struct brcmf_fws_mac_descriptor *if_entry;
776         bool closed;
777
778         /* for unique destination entries the related interface
779          * may be closed.
780          */
781         if (entry->mac_handle) {
782                 if_entry = &fws->desc.iface[entry->interface_id];
783                 if (if_entry->state == BRCMF_FWS_STATE_CLOSE)
784                         return true;
785         }
786         /* an entry is closed when the state is closed and
787          * the firmware did not request anything.
788          */
789         closed = entry->state == BRCMF_FWS_STATE_CLOSE &&
790                  !entry->requested_credit && !entry->requested_packet;
791
792         /* Or firmware does not allow traffic for given fifo */
793         return closed || !(entry->ac_bitmap & BIT(fifo));
794 }
795
796 static void brcmf_fws_macdesc_cleanup(struct brcmf_fws_info *fws,
797                                       struct brcmf_fws_mac_descriptor *entry,
798                                       int ifidx)
799 {
800         if (entry->occupied && (ifidx == -1 || ifidx == entry->interface_id)) {
801                 brcmf_fws_psq_flush(fws, &entry->psq, ifidx);
802                 entry->occupied = !!(entry->psq.len);
803         }
804 }
805
806 static void brcmf_fws_bus_txq_cleanup(struct brcmf_fws_info *fws,
807                                       bool (*fn)(struct sk_buff *, void *),
808                                       int ifidx)
809 {
810         struct brcmf_fws_hanger_item *hi;
811         struct pktq *txq;
812         struct sk_buff *skb;
813         int prec;
814         u32 hslot;
815
816         txq = brcmf_bus_gettxq(fws->drvr->bus_if);
817         if (IS_ERR(txq)) {
818                 brcmf_dbg(TRACE, "no txq to clean up\n");
819                 return;
820         }
821
822         for (prec = 0; prec < txq->num_prec; prec++) {
823                 skb = brcmu_pktq_pdeq_match(txq, prec, fn, &ifidx);
824                 while (skb) {
825                         hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
826                         hi = &fws->hanger.items[hslot];
827                         WARN_ON(skb != hi->pkt);
828                         hi->state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
829                         brcmu_pkt_buf_free_skb(skb);
830                         skb = brcmu_pktq_pdeq_match(txq, prec, fn, &ifidx);
831                 }
832         }
833 }
834
835 static void brcmf_fws_cleanup(struct brcmf_fws_info *fws, int ifidx)
836 {
837         int i;
838         struct brcmf_fws_mac_descriptor *table;
839         bool (*matchfn)(struct sk_buff *, void *) = NULL;
840
841         if (fws == NULL)
842                 return;
843
844         if (ifidx != -1)
845                 matchfn = brcmf_fws_ifidx_match;
846
847         /* cleanup individual nodes */
848         table = &fws->desc.nodes[0];
849         for (i = 0; i < ARRAY_SIZE(fws->desc.nodes); i++)
850                 brcmf_fws_macdesc_cleanup(fws, &table[i], ifidx);
851
852         brcmf_fws_macdesc_cleanup(fws, &fws->desc.other, ifidx);
853         brcmf_fws_bus_txq_cleanup(fws, matchfn, ifidx);
854         brcmf_fws_hanger_cleanup(fws, matchfn, ifidx);
855 }
856
857 static u8 brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
858 {
859         struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
860         u8 *wlh;
861         u16 data_offset = 0;
862         u8 fillers;
863         __le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod);
864         __le16 pktseq = cpu_to_le16(brcmf_skbcb(skb)->htod_seq);
865
866         brcmf_dbg(TRACE, "enter: %s, idx=%d hslot=%d htod %X seq %X\n",
867                   entry->name, brcmf_skb_if_flags_get_field(skb, INDEX),
868                   (le32_to_cpu(pkttag) >> 8) & 0xffff,
869                   brcmf_skbcb(skb)->htod, brcmf_skbcb(skb)->htod_seq);
870         if (entry->send_tim_signal)
871                 data_offset += 2 + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN;
872         if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode))
873                 data_offset += BRCMF_FWS_TYPE_SEQ_LEN;
874         /* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */
875         data_offset += 2 + BRCMF_FWS_TYPE_PKTTAG_LEN;
876         fillers = round_up(data_offset, 4) - data_offset;
877         data_offset += fillers;
878
879         skb_push(skb, data_offset);
880         wlh = skb->data;
881
882         wlh[0] = BRCMF_FWS_TYPE_PKTTAG;
883         wlh[1] = BRCMF_FWS_TYPE_PKTTAG_LEN;
884         memcpy(&wlh[2], &pkttag, sizeof(pkttag));
885         if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) {
886                 wlh[1] += BRCMF_FWS_TYPE_SEQ_LEN;
887                 memcpy(&wlh[2 + BRCMF_FWS_TYPE_PKTTAG_LEN], &pktseq,
888                        sizeof(pktseq));
889         }
890         wlh += wlh[1] + 2;
891
892         if (entry->send_tim_signal) {
893                 entry->send_tim_signal = false;
894                 wlh[0] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP;
895                 wlh[1] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN;
896                 wlh[2] = entry->mac_handle;
897                 wlh[3] = entry->traffic_pending_bmp;
898                 brcmf_dbg(TRACE, "adding TIM info: handle %d bmp 0x%X\n",
899                           entry->mac_handle, entry->traffic_pending_bmp);
900                 wlh += BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2;
901                 entry->traffic_lastreported_bmp = entry->traffic_pending_bmp;
902         }
903         if (fillers)
904                 memset(wlh, BRCMF_FWS_TYPE_FILLER, fillers);
905
906         return (u8)(data_offset >> 2);
907 }
908
909 static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws,
910                                  struct brcmf_fws_mac_descriptor *entry,
911                                  int fifo, bool send_immediately)
912 {
913         struct sk_buff *skb;
914         struct brcmf_skbuff_cb *skcb;
915         s32 err;
916         u32 len;
917         u8 data_offset;
918         int ifidx;
919
920         /* check delayedQ and suppressQ in one call using bitmap */
921         if (brcmu_pktq_mlen(&entry->psq, 3 << (fifo * 2)) == 0)
922                 entry->traffic_pending_bmp &= ~NBITVAL(fifo);
923         else
924                 entry->traffic_pending_bmp |= NBITVAL(fifo);
925
926         entry->send_tim_signal = false;
927         if (entry->traffic_lastreported_bmp != entry->traffic_pending_bmp)
928                 entry->send_tim_signal = true;
929         if (send_immediately && entry->send_tim_signal &&
930             entry->state == BRCMF_FWS_STATE_CLOSE) {
931                 /* create a dummy packet and sent that. The traffic          */
932                 /* bitmap info will automatically be attached to that packet */
933                 len = BRCMF_FWS_TYPE_PKTTAG_LEN + 2 +
934                       BRCMF_FWS_TYPE_SEQ_LEN +
935                       BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2 +
936                       4 + fws->drvr->hdrlen;
937                 skb = brcmu_pkt_buf_get_skb(len);
938                 if (skb == NULL)
939                         return false;
940                 skb_pull(skb, len);
941                 skcb = brcmf_skbcb(skb);
942                 skcb->mac = entry;
943                 skcb->state = BRCMF_FWS_SKBSTATE_TIM;
944                 skcb->htod = 0;
945                 skcb->htod_seq = 0;
946                 data_offset = brcmf_fws_hdrpush(fws, skb);
947                 ifidx = brcmf_skb_if_flags_get_field(skb, INDEX);
948                 brcmf_fws_unlock(fws);
949                 err = brcmf_proto_txdata(fws->drvr, ifidx, data_offset, skb);
950                 brcmf_fws_lock(fws);
951                 if (err)
952                         brcmu_pkt_buf_free_skb(skb);
953                 return true;
954         }
955         return false;
956 }
957
958 static void
959 brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq,
960                              u8 if_id)
961 {
962         struct brcmf_if *ifp = brcmf_get_ifp(fws->drvr, if_id);
963
964         if (WARN_ON(!ifp))
965                 return;
966
967         if ((ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) &&
968             pq->len <= BRCMF_FWS_FLOWCONTROL_LOWATER)
969                 brcmf_txflowblock_if(ifp,
970                                      BRCMF_NETIF_STOP_REASON_FWS_FC, false);
971         if (!(ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) &&
972             pq->len >= BRCMF_FWS_FLOWCONTROL_HIWATER) {
973                 fws->stats.fws_flow_block++;
974                 brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FWS_FC, true);
975         }
976         return;
977 }
978
979 static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi)
980 {
981         brcmf_dbg(CTL, "rssi %d\n", rssi);
982         return 0;
983 }
984
985 static
986 int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
987 {
988         struct brcmf_fws_mac_descriptor *entry, *existing;
989         u8 mac_handle;
990         u8 ifidx;
991         u8 *addr;
992
993         mac_handle = *data++;
994         ifidx = *data++;
995         addr = data;
996
997         entry = &fws->desc.nodes[mac_handle & 0x1F];
998         if (type == BRCMF_FWS_TYPE_MACDESC_DEL) {
999                 if (entry->occupied) {
1000                         brcmf_dbg(TRACE, "deleting %s mac %pM\n",
1001                                   entry->name, addr);
1002                         brcmf_fws_lock(fws);
1003                         brcmf_fws_macdesc_cleanup(fws, entry, -1);
1004                         brcmf_fws_macdesc_deinit(entry);
1005                         brcmf_fws_unlock(fws);
1006                 } else
1007                         fws->stats.mac_update_failed++;
1008                 return 0;
1009         }
1010
1011         existing = brcmf_fws_macdesc_lookup(fws, addr);
1012         if (IS_ERR(existing)) {
1013                 if (!entry->occupied) {
1014                         brcmf_fws_lock(fws);
1015                         entry->mac_handle = mac_handle;
1016                         brcmf_fws_macdesc_init(entry, addr, ifidx);
1017                         brcmf_fws_macdesc_set_name(fws, entry);
1018                         brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
1019                                         BRCMF_FWS_PSQ_LEN);
1020                         brcmf_fws_unlock(fws);
1021                         brcmf_dbg(TRACE, "add %s mac %pM\n", entry->name, addr);
1022                 } else {
1023                         fws->stats.mac_update_failed++;
1024                 }
1025         } else {
1026                 if (entry != existing) {
1027                         brcmf_dbg(TRACE, "copy mac %s\n", existing->name);
1028                         brcmf_fws_lock(fws);
1029                         memcpy(entry, existing,
1030                                offsetof(struct brcmf_fws_mac_descriptor, psq));
1031                         entry->mac_handle = mac_handle;
1032                         brcmf_fws_macdesc_deinit(existing);
1033                         brcmf_fws_macdesc_set_name(fws, entry);
1034                         brcmf_fws_unlock(fws);
1035                         brcmf_dbg(TRACE, "relocate %s mac %pM\n", entry->name,
1036                                   addr);
1037                 } else {
1038                         brcmf_dbg(TRACE, "use existing\n");
1039                         WARN_ON(entry->mac_handle != mac_handle);
1040                         /* TODO: what should we do here: continue, reinit, .. */
1041                 }
1042         }
1043         return 0;
1044 }
1045
1046 static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
1047                                             u8 type, u8 *data)
1048 {
1049         struct brcmf_fws_mac_descriptor *entry;
1050         u8 mac_handle;
1051         int ret;
1052
1053         mac_handle = data[0];
1054         entry = &fws->desc.nodes[mac_handle & 0x1F];
1055         if (!entry->occupied) {
1056                 fws->stats.mac_ps_update_failed++;
1057                 return -ESRCH;
1058         }
1059         brcmf_fws_lock(fws);
1060         /* a state update should wipe old credits */
1061         entry->requested_credit = 0;
1062         entry->requested_packet = 0;
1063         if (type == BRCMF_FWS_TYPE_MAC_OPEN) {
1064                 entry->state = BRCMF_FWS_STATE_OPEN;
1065                 ret = BRCMF_FWS_RET_OK_SCHEDULE;
1066         } else {
1067                 entry->state = BRCMF_FWS_STATE_CLOSE;
1068                 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BK, false);
1069                 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BE, false);
1070                 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VI, false);
1071                 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VO, true);
1072                 ret = BRCMF_FWS_RET_OK_NOSCHEDULE;
1073         }
1074         brcmf_fws_unlock(fws);
1075         return ret;
1076 }
1077
1078 static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
1079                                               u8 type, u8 *data)
1080 {
1081         struct brcmf_fws_mac_descriptor *entry;
1082         u8 ifidx;
1083         int ret;
1084
1085         ifidx = data[0];
1086
1087         if (ifidx >= BRCMF_MAX_IFS) {
1088                 ret = -ERANGE;
1089                 goto fail;
1090         }
1091
1092         entry = &fws->desc.iface[ifidx];
1093         if (!entry->occupied) {
1094                 ret = -ESRCH;
1095                 goto fail;
1096         }
1097
1098         brcmf_dbg(TRACE, "%s (%d): %s\n", brcmf_fws_get_tlv_name(type), type,
1099                   entry->name);
1100         brcmf_fws_lock(fws);
1101         switch (type) {
1102         case BRCMF_FWS_TYPE_INTERFACE_OPEN:
1103                 entry->state = BRCMF_FWS_STATE_OPEN;
1104                 ret = BRCMF_FWS_RET_OK_SCHEDULE;
1105                 break;
1106         case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
1107                 entry->state = BRCMF_FWS_STATE_CLOSE;
1108                 ret = BRCMF_FWS_RET_OK_NOSCHEDULE;
1109                 break;
1110         default:
1111                 ret = -EINVAL;
1112                 brcmf_fws_unlock(fws);
1113                 goto fail;
1114         }
1115         brcmf_fws_unlock(fws);
1116         return ret;
1117
1118 fail:
1119         fws->stats.if_update_failed++;
1120         return ret;
1121 }
1122
1123 static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
1124                                       u8 *data)
1125 {
1126         struct brcmf_fws_mac_descriptor *entry;
1127
1128         entry = &fws->desc.nodes[data[1] & 0x1F];
1129         if (!entry->occupied) {
1130                 if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT)
1131                         fws->stats.credit_request_failed++;
1132                 else
1133                         fws->stats.packet_request_failed++;
1134                 return -ESRCH;
1135         }
1136
1137         brcmf_dbg(TRACE, "%s (%d): %s cnt %d bmp %d\n",
1138                   brcmf_fws_get_tlv_name(type), type, entry->name,
1139                   data[0], data[2]);
1140         brcmf_fws_lock(fws);
1141         if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT)
1142                 entry->requested_credit = data[0];
1143         else
1144                 entry->requested_packet = data[0];
1145
1146         entry->ac_bitmap = data[2];
1147         brcmf_fws_unlock(fws);
1148         return BRCMF_FWS_RET_OK_SCHEDULE;
1149 }
1150
1151 static void
1152 brcmf_fws_macdesc_use_req_credit(struct brcmf_fws_mac_descriptor *entry,
1153                                  struct sk_buff *skb)
1154 {
1155         if (entry->requested_credit > 0) {
1156                 entry->requested_credit--;
1157                 brcmf_skb_if_flags_set_field(skb, REQUESTED, 1);
1158                 brcmf_skb_if_flags_set_field(skb, REQ_CREDIT, 1);
1159                 if (entry->state != BRCMF_FWS_STATE_CLOSE)
1160                         brcmf_err("requested credit set while mac not closed!\n");
1161         } else if (entry->requested_packet > 0) {
1162                 entry->requested_packet--;
1163                 brcmf_skb_if_flags_set_field(skb, REQUESTED, 1);
1164                 brcmf_skb_if_flags_set_field(skb, REQ_CREDIT, 0);
1165                 if (entry->state != BRCMF_FWS_STATE_CLOSE)
1166                         brcmf_err("requested packet set while mac not closed!\n");
1167         } else {
1168                 brcmf_skb_if_flags_set_field(skb, REQUESTED, 0);
1169                 brcmf_skb_if_flags_set_field(skb, REQ_CREDIT, 0);
1170         }
1171 }
1172
1173 static void brcmf_fws_macdesc_return_req_credit(struct sk_buff *skb)
1174 {
1175         struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
1176
1177         if ((brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) &&
1178             (entry->state == BRCMF_FWS_STATE_CLOSE))
1179                 entry->requested_credit++;
1180 }
1181
1182 static void brcmf_fws_return_credits(struct brcmf_fws_info *fws,
1183                                      u8 fifo, u8 credits)
1184 {
1185         int lender_ac;
1186         int *borrowed;
1187         int *fifo_credit;
1188
1189         if (!credits)
1190                 return;
1191
1192         fws->fifo_credit_map |= 1 << fifo;
1193
1194         if (fifo > BRCMF_FWS_FIFO_AC_BK &&
1195             fifo <= BRCMF_FWS_FIFO_AC_VO) {
1196                 for (lender_ac = BRCMF_FWS_FIFO_AC_VO; lender_ac >= 0;
1197                      lender_ac--) {
1198                         borrowed = &fws->credits_borrowed[fifo][lender_ac];
1199                         if (*borrowed) {
1200                                 fws->fifo_credit_map |= (1 << lender_ac);
1201                                 fifo_credit = &fws->fifo_credit[lender_ac];
1202                                 if (*borrowed >= credits) {
1203                                         *borrowed -= credits;
1204                                         *fifo_credit += credits;
1205                                         return;
1206                                 } else {
1207                                         credits -= *borrowed;
1208                                         *fifo_credit += *borrowed;
1209                                         *borrowed = 0;
1210                                 }
1211                         }
1212                 }
1213         }
1214
1215         if (credits) {
1216                 fws->fifo_credit[fifo] += credits;
1217         }
1218
1219         if (fws->fifo_credit[fifo] > fws->init_fifo_credit[fifo])
1220                 fws->fifo_credit[fifo] = fws->init_fifo_credit[fifo];
1221
1222 }
1223
1224 static void brcmf_fws_schedule_deq(struct brcmf_fws_info *fws)
1225 {
1226         /* only schedule dequeue when there are credits for delayed traffic */
1227         if ((fws->fifo_credit_map & fws->fifo_delay_map) ||
1228             (!brcmf_fws_fc_active(fws) && fws->fifo_delay_map))
1229                 queue_work(fws->fws_wq, &fws->fws_dequeue_work);
1230 }
1231
1232 static int brcmf_fws_enq(struct brcmf_fws_info *fws,
1233                          enum brcmf_fws_skb_state state, int fifo,
1234                          struct sk_buff *p)
1235 {
1236         struct brcmf_pub *drvr = fws->drvr;
1237         int prec = 2 * fifo;
1238         u32 *qfull_stat = &fws->stats.delayq_full_error;
1239         struct brcmf_fws_mac_descriptor *entry;
1240         struct pktq *pq;
1241         struct sk_buff_head *queue;
1242         struct sk_buff *p_head;
1243         struct sk_buff *p_tail;
1244         u32 fr_new;
1245         u32 fr_compare;
1246
1247         entry = brcmf_skbcb(p)->mac;
1248         if (entry == NULL) {
1249                 bphy_err(drvr, "no mac descriptor found for skb %p\n", p);
1250                 return -ENOENT;
1251         }
1252
1253         brcmf_dbg(DATA, "enter: fifo %d skb %p\n", fifo, p);
1254         if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) {
1255                 prec += 1;
1256                 qfull_stat = &fws->stats.supprq_full_error;
1257
1258                 /* Fix out of order delivery of frames. Dont assume frame    */
1259                 /* can be inserted at the end, but look for correct position */
1260                 pq = &entry->psq;
1261                 if (pktq_full(pq) || pktq_pfull(pq, prec)) {
1262                         *qfull_stat += 1;
1263                         return -ENFILE;
1264                 }
1265                 queue = &pq->q[prec].skblist;
1266
1267                 p_head = skb_peek(queue);
1268                 p_tail = skb_peek_tail(queue);
1269                 fr_new = brcmf_skb_htod_tag_get_field(p, FREERUN);
1270
1271                 while (p_head != p_tail) {
1272                         fr_compare = brcmf_skb_htod_tag_get_field(p_tail,
1273                                                                   FREERUN);
1274                         /* be sure to handle wrap of 256 */
1275                         if (((fr_new > fr_compare) &&
1276                              ((fr_new - fr_compare) < 128)) ||
1277                             ((fr_new < fr_compare) &&
1278                              ((fr_compare - fr_new) > 128)))
1279                                 break;
1280                         p_tail = skb_queue_prev(queue, p_tail);
1281                 }
1282                 /* Position found. Determine what to do */
1283                 if (p_tail == NULL) {
1284                         /* empty list */
1285                         __skb_queue_tail(queue, p);
1286                 } else {
1287                         fr_compare = brcmf_skb_htod_tag_get_field(p_tail,
1288                                                                   FREERUN);
1289                         if (((fr_new > fr_compare) &&
1290                              ((fr_new - fr_compare) < 128)) ||
1291                             ((fr_new < fr_compare) &&
1292                              ((fr_compare - fr_new) > 128))) {
1293                                 /* After tail */
1294                                 __skb_queue_after(queue, p_tail, p);
1295                         } else {
1296                                 /* Before tail */
1297                                 __skb_insert(p, p_tail->prev, p_tail, queue);
1298                         }
1299                 }
1300
1301                 /* Complete the counters and statistics */
1302                 pq->len++;
1303                 if (pq->hi_prec < prec)
1304                         pq->hi_prec = (u8) prec;
1305         } else if (brcmu_pktq_penq(&entry->psq, prec, p) == NULL) {
1306                 *qfull_stat += 1;
1307                 return -ENFILE;
1308         }
1309
1310         /* increment total enqueued packet count */
1311         fws->fifo_delay_map |= 1 << fifo;
1312         fws->fifo_enqpkt[fifo]++;
1313
1314         /* update the sk_buff state */
1315         brcmf_skbcb(p)->state = state;
1316
1317         /*
1318          * A packet has been pushed so update traffic
1319          * availability bitmap, if applicable
1320          */
1321         brcmf_fws_tim_update(fws, entry, fifo, true);
1322         brcmf_fws_flow_control_check(fws, &entry->psq,
1323                                      brcmf_skb_if_flags_get_field(p, INDEX));
1324         return 0;
1325 }
1326
1327 static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo)
1328 {
1329         struct brcmf_fws_mac_descriptor *table;
1330         struct brcmf_fws_mac_descriptor *entry;
1331         struct sk_buff *p;
1332         int num_nodes;
1333         int node_pos;
1334         int prec_out;
1335         int pmsk;
1336         int i;
1337
1338         table = (struct brcmf_fws_mac_descriptor *)&fws->desc;
1339         num_nodes = sizeof(fws->desc) / sizeof(struct brcmf_fws_mac_descriptor);
1340         node_pos = fws->deq_node_pos[fifo];
1341
1342         for (i = 0; i < num_nodes; i++) {
1343                 entry = &table[(node_pos + i) % num_nodes];
1344                 if (!entry->occupied ||
1345                     brcmf_fws_macdesc_closed(fws, entry, fifo))
1346                         continue;
1347
1348                 if (entry->suppressed)
1349                         pmsk = 2;
1350                 else
1351                         pmsk = 3;
1352                 p = brcmu_pktq_mdeq(&entry->psq, pmsk << (fifo * 2), &prec_out);
1353                 if (p == NULL) {
1354                         if (entry->suppressed) {
1355                                 if (entry->suppr_transit_count)
1356                                         continue;
1357                                 entry->suppressed = false;
1358                                 p = brcmu_pktq_mdeq(&entry->psq,
1359                                                     1 << (fifo * 2), &prec_out);
1360                         }
1361                 }
1362                 if  (p == NULL)
1363                         continue;
1364
1365                 brcmf_fws_macdesc_use_req_credit(entry, p);
1366
1367                 /* move dequeue position to ensure fair round-robin */
1368                 fws->deq_node_pos[fifo] = (node_pos + i + 1) % num_nodes;
1369                 brcmf_fws_flow_control_check(fws, &entry->psq,
1370                                              brcmf_skb_if_flags_get_field(p,
1371                                                                           INDEX)
1372                                              );
1373                 /*
1374                  * A packet has been picked up, update traffic
1375                  * availability bitmap, if applicable
1376                  */
1377                 brcmf_fws_tim_update(fws, entry, fifo, false);
1378
1379                 /*
1380                  * decrement total enqueued fifo packets and
1381                  * clear delay bitmap if done.
1382                  */
1383                 fws->fifo_enqpkt[fifo]--;
1384                 if (fws->fifo_enqpkt[fifo] == 0)
1385                         fws->fifo_delay_map &= ~(1 << fifo);
1386                 goto done;
1387         }
1388         p = NULL;
1389 done:
1390         brcmf_dbg(DATA, "exit: fifo %d skb %p\n", fifo, p);
1391         return p;
1392 }
1393
1394 static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
1395                                          struct sk_buff *skb,
1396                                          u32 genbit, u16 seq)
1397 {
1398         struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
1399         u32 hslot;
1400         int ret;
1401
1402         hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
1403
1404         /* this packet was suppressed */
1405         if (!entry->suppressed) {
1406                 entry->suppressed = true;
1407                 entry->suppr_transit_count = entry->transit_count;
1408                 brcmf_dbg(DATA, "suppress %s: transit %d\n",
1409                           entry->name, entry->transit_count);
1410         }
1411
1412         entry->generation = genbit;
1413
1414         brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit);
1415         brcmf_skbcb(skb)->htod_seq = seq;
1416         if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) {
1417                 brcmf_skb_htod_seq_set_field(skb, FROMDRV, 1);
1418                 brcmf_skb_htod_seq_set_field(skb, FROMFW, 0);
1419         } else {
1420                 brcmf_skb_htod_seq_set_field(skb, FROMDRV, 0);
1421         }
1422         ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, skb);
1423
1424         if (ret != 0) {
1425                 /* suppress q is full drop this packet */
1426                 brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, true);
1427         } else {
1428                 /* Mark suppressed to avoid a double free during wlfc cleanup */
1429                 brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot);
1430         }
1431
1432         return ret;
1433 }
1434
1435 static int
1436 brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
1437                       u32 genbit, u16 seq, u8 compcnt)
1438 {
1439         struct brcmf_pub *drvr = fws->drvr;
1440         u32 fifo;
1441         u8 cnt = 0;
1442         int ret;
1443         bool remove_from_hanger = true;
1444         struct sk_buff *skb;
1445         struct brcmf_skbuff_cb *skcb;
1446         struct brcmf_fws_mac_descriptor *entry = NULL;
1447         struct brcmf_if *ifp;
1448
1449         brcmf_dbg(DATA, "flags %d\n", flags);
1450
1451         if (flags == BRCMF_FWS_TXSTATUS_DISCARD)
1452                 fws->stats.txs_discard += compcnt;
1453         else if (flags == BRCMF_FWS_TXSTATUS_CORE_SUPPRESS) {
1454                 fws->stats.txs_supp_core += compcnt;
1455                 remove_from_hanger = false;
1456         } else if (flags == BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS) {
1457                 fws->stats.txs_supp_ps += compcnt;
1458                 remove_from_hanger = false;
1459         } else if (flags == BRCMF_FWS_TXSTATUS_FW_TOSSED)
1460                 fws->stats.txs_tossed += compcnt;
1461         else if (flags == BRCMF_FWS_TXSTATUS_FW_DISCARD_NOACK)
1462                 fws->stats.txs_discard += compcnt;
1463         else if (flags == BRCMF_FWS_TXSTATUS_FW_SUPPRESS_ACKED)
1464                 fws->stats.txs_discard += compcnt;
1465         else if (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED)
1466                 fws->stats.txs_host_tossed += compcnt;
1467         else
1468                 bphy_err(drvr, "unexpected txstatus\n");
1469
1470         while (cnt < compcnt) {
1471                 ret = brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
1472                                               remove_from_hanger);
1473                 if (ret != 0) {
1474                         bphy_err(drvr, "no packet in hanger slot: hslot=%d\n",
1475                                  hslot);
1476                         goto cont;
1477                 }
1478
1479                 skcb = brcmf_skbcb(skb);
1480                 entry = skcb->mac;
1481                 if (WARN_ON(!entry)) {
1482                         brcmu_pkt_buf_free_skb(skb);
1483                         goto cont;
1484                 }
1485                 entry->transit_count--;
1486                 if (entry->suppressed && entry->suppr_transit_count)
1487                         entry->suppr_transit_count--;
1488
1489                 brcmf_dbg(DATA, "%s flags %d htod %X seq %X\n", entry->name,
1490                           flags, skcb->htod, seq);
1491
1492                 /* pick up the implicit credit from this packet */
1493                 fifo = brcmf_skb_htod_tag_get_field(skb, FIFO);
1494                 if (fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT ||
1495                     (brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) ||
1496                     flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED) {
1497                         brcmf_fws_return_credits(fws, fifo, 1);
1498                         brcmf_fws_schedule_deq(fws);
1499                 }
1500                 brcmf_fws_macdesc_return_req_credit(skb);
1501
1502                 ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp);
1503                 if (ret) {
1504                         brcmu_pkt_buf_free_skb(skb);
1505                         goto cont;
1506                 }
1507                 if (!remove_from_hanger)
1508                         ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb,
1509                                                             genbit, seq);
1510                 if (remove_from_hanger || ret)
1511                         brcmf_txfinalize(ifp, skb, true);
1512
1513 cont:
1514                 hslot = (hslot + 1) & (BRCMF_FWS_TXSTAT_HSLOT_MASK >>
1515                                        BRCMF_FWS_TXSTAT_HSLOT_SHIFT);
1516                 if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode))
1517                         seq = (seq + 1) & BRCMF_SKB_HTOD_SEQ_NR_MASK;
1518
1519                 cnt++;
1520         }
1521
1522         return 0;
1523 }
1524
1525 static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
1526                                              u8 *data)
1527 {
1528         int i;
1529
1530         if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) {
1531                 brcmf_dbg(INFO, "ignored\n");
1532                 return BRCMF_FWS_RET_OK_NOSCHEDULE;
1533         }
1534
1535         brcmf_dbg(DATA, "enter: data %pM\n", data);
1536         brcmf_fws_lock(fws);
1537         for (i = 0; i < BRCMF_FWS_FIFO_COUNT; i++)
1538                 brcmf_fws_return_credits(fws, i, data[i]);
1539
1540         brcmf_dbg(DATA, "map: credit %x delay %x\n", fws->fifo_credit_map,
1541                   fws->fifo_delay_map);
1542         brcmf_fws_unlock(fws);
1543         return BRCMF_FWS_RET_OK_SCHEDULE;
1544 }
1545
1546 static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 type,
1547                                        u8 *data)
1548 {
1549         __le32 status_le;
1550         __le16 seq_le;
1551         u32 status;
1552         u32 hslot;
1553         u32 genbit;
1554         u8 flags;
1555         u16 seq;
1556         u8 compcnt;
1557         u8 compcnt_offset = BRCMF_FWS_TYPE_TXSTATUS_LEN;
1558
1559         memcpy(&status_le, data, sizeof(status_le));
1560         status = le32_to_cpu(status_le);
1561         flags = brcmf_txstatus_get_field(status, FLAGS);
1562         hslot = brcmf_txstatus_get_field(status, HSLOT);
1563         genbit = brcmf_txstatus_get_field(status, GENERATION);
1564         if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) {
1565                 memcpy(&seq_le, &data[BRCMF_FWS_TYPE_TXSTATUS_LEN],
1566                        sizeof(seq_le));
1567                 seq = le16_to_cpu(seq_le);
1568                 compcnt_offset += BRCMF_FWS_TYPE_SEQ_LEN;
1569         } else {
1570                 seq = 0;
1571         }
1572
1573         if (type == BRCMF_FWS_TYPE_COMP_TXSTATUS)
1574                 compcnt = data[compcnt_offset];
1575         else
1576                 compcnt = 1;
1577         fws->stats.txs_indicate += compcnt;
1578
1579         brcmf_fws_lock(fws);
1580         brcmf_fws_txs_process(fws, flags, hslot, genbit, seq, compcnt);
1581         brcmf_fws_unlock(fws);
1582         return BRCMF_FWS_RET_OK_NOSCHEDULE;
1583 }
1584
1585 static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data)
1586 {
1587         __le32 timestamp;
1588
1589         memcpy(&timestamp, &data[2], sizeof(timestamp));
1590         brcmf_dbg(CTL, "received: seq %d, timestamp %d\n", data[1],
1591                   le32_to_cpu(timestamp));
1592         return 0;
1593 }
1594
1595 static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp,
1596                                        const struct brcmf_event_msg *e,
1597                                        void *data)
1598 {
1599         struct brcmf_pub *drvr = ifp->drvr;
1600         struct brcmf_fws_info *fws = drvr_to_fws(drvr);
1601         int i;
1602         u8 *credits = data;
1603
1604         if (e->datalen < BRCMF_FWS_FIFO_COUNT) {
1605                 bphy_err(drvr, "event payload too small (%d)\n", e->datalen);
1606                 return -EINVAL;
1607         }
1608
1609         fws->creditmap_received = true;
1610
1611         brcmf_dbg(TRACE, "enter: credits %pM\n", credits);
1612         brcmf_fws_lock(fws);
1613         for (i = 0; i < ARRAY_SIZE(fws->fifo_credit); i++) {
1614                 fws->fifo_credit[i] += credits[i] - fws->init_fifo_credit[i];
1615                 fws->init_fifo_credit[i] = credits[i];
1616                 if (fws->fifo_credit[i] > 0)
1617                         fws->fifo_credit_map |= 1 << i;
1618                 else
1619                         fws->fifo_credit_map &= ~(1 << i);
1620                 WARN_ONCE(fws->fifo_credit[i] < 0,
1621                           "fifo_credit[%d] is negative(%d)\n", i,
1622                           fws->fifo_credit[i]);
1623         }
1624         brcmf_fws_schedule_deq(fws);
1625         brcmf_fws_unlock(fws);
1626         return 0;
1627 }
1628
1629 static int brcmf_fws_notify_bcmc_credit_support(struct brcmf_if *ifp,
1630                                                 const struct brcmf_event_msg *e,
1631                                                 void *data)
1632 {
1633         struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
1634
1635         if (fws) {
1636                 brcmf_fws_lock(fws);
1637                 fws->bcmc_credit_check = true;
1638                 brcmf_fws_unlock(fws);
1639         }
1640         return 0;
1641 }
1642
1643 static void brcmf_rxreorder_get_skb_list(struct brcmf_ampdu_rx_reorder *rfi,
1644                                          u8 start, u8 end,
1645                                          struct sk_buff_head *skb_list)
1646 {
1647         /* initialize return list */
1648         __skb_queue_head_init(skb_list);
1649
1650         if (rfi->pend_pkts == 0) {
1651                 brcmf_dbg(INFO, "no packets in reorder queue\n");
1652                 return;
1653         }
1654
1655         do {
1656                 if (rfi->pktslots[start]) {
1657                         __skb_queue_tail(skb_list, rfi->pktslots[start]);
1658                         rfi->pktslots[start] = NULL;
1659                 }
1660                 start++;
1661                 if (start > rfi->max_idx)
1662                         start = 0;
1663         } while (start != end);
1664         rfi->pend_pkts -= skb_queue_len(skb_list);
1665 }
1666
1667 void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt, bool inirq)
1668 {
1669         struct brcmf_pub *drvr = ifp->drvr;
1670         u8 *reorder_data;
1671         u8 flow_id, max_idx, cur_idx, exp_idx, end_idx;
1672         struct brcmf_ampdu_rx_reorder *rfi;
1673         struct sk_buff_head reorder_list;
1674         struct sk_buff *pnext;
1675         u8 flags;
1676         u32 buf_size;
1677
1678         reorder_data = ((struct brcmf_skb_reorder_data *)pkt->cb)->reorder;
1679         flow_id = reorder_data[BRCMF_RXREORDER_FLOWID_OFFSET];
1680         flags = reorder_data[BRCMF_RXREORDER_FLAGS_OFFSET];
1681
1682         /* validate flags and flow id */
1683         if (flags == 0xFF) {
1684                 bphy_err(drvr, "invalid flags...so ignore this packet\n");
1685                 brcmf_netif_rx(ifp, pkt, inirq);
1686                 return;
1687         }
1688
1689         rfi = ifp->drvr->reorder_flows[flow_id];
1690         if (flags & BRCMF_RXREORDER_DEL_FLOW) {
1691                 brcmf_dbg(INFO, "flow-%d: delete\n",
1692                           flow_id);
1693
1694                 if (rfi == NULL) {
1695                         brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n",
1696                                   flow_id);
1697                         brcmf_netif_rx(ifp, pkt, inirq);
1698                         return;
1699                 }
1700
1701                 brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, rfi->exp_idx,
1702                                              &reorder_list);
1703                 /* add the last packet */
1704                 __skb_queue_tail(&reorder_list, pkt);
1705                 kfree(rfi);
1706                 ifp->drvr->reorder_flows[flow_id] = NULL;
1707                 goto netif_rx;
1708         }
1709         /* from here on we need a flow reorder instance */
1710         if (rfi == NULL) {
1711                 buf_size = sizeof(*rfi);
1712                 max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
1713
1714                 buf_size += (max_idx + 1) * sizeof(pkt);
1715
1716                 /* allocate space for flow reorder info */
1717                 brcmf_dbg(INFO, "flow-%d: start, maxidx %d\n",
1718                           flow_id, max_idx);
1719                 rfi = kzalloc(buf_size, GFP_ATOMIC);
1720                 if (rfi == NULL) {
1721                         bphy_err(drvr, "failed to alloc buffer\n");
1722                         brcmf_netif_rx(ifp, pkt, inirq);
1723                         return;
1724                 }
1725
1726                 ifp->drvr->reorder_flows[flow_id] = rfi;
1727                 rfi->pktslots = (struct sk_buff **)(rfi + 1);
1728                 rfi->max_idx = max_idx;
1729         }
1730         if (flags & BRCMF_RXREORDER_NEW_HOLE)  {
1731                 if (rfi->pend_pkts) {
1732                         brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx,
1733                                                      rfi->exp_idx,
1734                                                      &reorder_list);
1735                         WARN_ON(rfi->pend_pkts);
1736                 } else {
1737                         __skb_queue_head_init(&reorder_list);
1738                 }
1739                 rfi->cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
1740                 rfi->exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
1741                 rfi->max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
1742                 rfi->pktslots[rfi->cur_idx] = pkt;
1743                 rfi->pend_pkts++;
1744                 brcmf_dbg(DATA, "flow-%d: new hole %d (%d), pending %d\n",
1745                           flow_id, rfi->cur_idx, rfi->exp_idx, rfi->pend_pkts);
1746         } else if (flags & BRCMF_RXREORDER_CURIDX_VALID) {
1747                 cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
1748                 exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
1749
1750                 if ((exp_idx == rfi->exp_idx) && (cur_idx != rfi->exp_idx)) {
1751                         /* still in the current hole */
1752                         /* enqueue the current on the buffer chain */
1753                         if (rfi->pktslots[cur_idx] != NULL) {
1754                                 brcmf_dbg(INFO, "HOLE: ERROR buffer pending..free it\n");
1755                                 brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
1756                                 rfi->pktslots[cur_idx] = NULL;
1757                         }
1758                         rfi->pktslots[cur_idx] = pkt;
1759                         rfi->pend_pkts++;
1760                         rfi->cur_idx = cur_idx;
1761                         brcmf_dbg(DATA, "flow-%d: store pkt %d (%d), pending %d\n",
1762                                   flow_id, cur_idx, exp_idx, rfi->pend_pkts);
1763
1764                         /* can return now as there is no reorder
1765                          * list to process.
1766                          */
1767                         return;
1768                 }
1769                 if (rfi->exp_idx == cur_idx) {
1770                         if (rfi->pktslots[cur_idx] != NULL) {
1771                                 brcmf_dbg(INFO, "error buffer pending..free it\n");
1772                                 brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
1773                                 rfi->pktslots[cur_idx] = NULL;
1774                         }
1775                         rfi->pktslots[cur_idx] = pkt;
1776                         rfi->pend_pkts++;
1777
1778                         /* got the expected one. flush from current to expected
1779                          * and update expected
1780                          */
1781                         brcmf_dbg(DATA, "flow-%d: expected %d (%d), pending %d\n",
1782                                   flow_id, cur_idx, exp_idx, rfi->pend_pkts);
1783
1784                         rfi->cur_idx = cur_idx;
1785                         rfi->exp_idx = exp_idx;
1786
1787                         brcmf_rxreorder_get_skb_list(rfi, cur_idx, exp_idx,
1788                                                      &reorder_list);
1789                         brcmf_dbg(DATA, "flow-%d: freeing buffers %d, pending %d\n",
1790                                   flow_id, skb_queue_len(&reorder_list),
1791                                   rfi->pend_pkts);
1792                 } else {
1793                         u8 end_idx;
1794
1795                         brcmf_dbg(DATA, "flow-%d (0x%x): both moved, old %d/%d, new %d/%d\n",
1796                                   flow_id, flags, rfi->cur_idx, rfi->exp_idx,
1797                                   cur_idx, exp_idx);
1798                         if (flags & BRCMF_RXREORDER_FLUSH_ALL)
1799                                 end_idx = rfi->exp_idx;
1800                         else
1801                                 end_idx = exp_idx;
1802
1803                         /* flush pkts first */
1804                         brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
1805                                                      &reorder_list);
1806
1807                         if (exp_idx == ((cur_idx + 1) % (rfi->max_idx + 1))) {
1808                                 __skb_queue_tail(&reorder_list, pkt);
1809                         } else {
1810                                 rfi->pktslots[cur_idx] = pkt;
1811                                 rfi->pend_pkts++;
1812                         }
1813                         rfi->exp_idx = exp_idx;
1814                         rfi->cur_idx = cur_idx;
1815                 }
1816         } else {
1817                 /* explicity window move updating the expected index */
1818                 exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
1819
1820                 brcmf_dbg(DATA, "flow-%d (0x%x): change expected: %d -> %d\n",
1821                           flow_id, flags, rfi->exp_idx, exp_idx);
1822                 if (flags & BRCMF_RXREORDER_FLUSH_ALL)
1823                         end_idx =  rfi->exp_idx;
1824                 else
1825                         end_idx =  exp_idx;
1826
1827                 brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
1828                                              &reorder_list);
1829                 __skb_queue_tail(&reorder_list, pkt);
1830                 /* set the new expected idx */
1831                 rfi->exp_idx = exp_idx;
1832         }
1833 netif_rx:
1834         skb_queue_walk_safe(&reorder_list, pkt, pnext) {
1835                 __skb_unlink(pkt, &reorder_list);
1836                 brcmf_netif_rx(ifp, pkt, inirq);
1837         }
1838 }
1839
1840 void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb)
1841 {
1842         struct brcmf_skb_reorder_data *rd;
1843         struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
1844         u8 *signal_data;
1845         s16 data_len;
1846         u8 type;
1847         u8 len;
1848         u8 *data;
1849         s32 status;
1850         s32 err;
1851
1852         brcmf_dbg(HDRS, "enter: ifidx %d, skblen %u, sig %d\n",
1853                   ifp->ifidx, skb->len, siglen);
1854
1855         WARN_ON(siglen > skb->len);
1856
1857         if (siglen > skb->len)
1858                 siglen = skb->len;
1859
1860         if (!siglen)
1861                 return;
1862         /* if flow control disabled, skip to packet data and leave */
1863         if ((!fws) || (!fws->fw_signals)) {
1864                 skb_pull(skb, siglen);
1865                 return;
1866         }
1867
1868         fws->stats.header_pulls++;
1869         data_len = siglen;
1870         signal_data = skb->data;
1871
1872         status = BRCMF_FWS_RET_OK_NOSCHEDULE;
1873         while (data_len > 0) {
1874                 /* extract tlv info */
1875                 type = signal_data[0];
1876
1877                 /* FILLER type is actually not a TLV, but
1878                  * a single byte that can be skipped.
1879                  */
1880                 if (type == BRCMF_FWS_TYPE_FILLER) {
1881                         signal_data += 1;
1882                         data_len -= 1;
1883                         continue;
1884                 }
1885                 len = signal_data[1];
1886                 data = signal_data + 2;
1887
1888                 brcmf_dbg(HDRS, "tlv type=%s (%d), len=%d (%d)\n",
1889                           brcmf_fws_get_tlv_name(type), type, len,
1890                           brcmf_fws_get_tlv_len(fws, type));
1891
1892                 /* abort parsing when length invalid */
1893                 if (data_len < len + 2)
1894                         break;
1895
1896                 if (len < brcmf_fws_get_tlv_len(fws, type))
1897                         break;
1898
1899                 err = BRCMF_FWS_RET_OK_NOSCHEDULE;
1900                 switch (type) {
1901                 case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS:
1902                         rd = (struct brcmf_skb_reorder_data *)skb->cb;
1903                         rd->reorder = data;
1904                         break;
1905                 case BRCMF_FWS_TYPE_MACDESC_ADD:
1906                 case BRCMF_FWS_TYPE_MACDESC_DEL:
1907                         brcmf_fws_macdesc_indicate(fws, type, data);
1908                         break;
1909                 case BRCMF_FWS_TYPE_MAC_OPEN:
1910                 case BRCMF_FWS_TYPE_MAC_CLOSE:
1911                         err = brcmf_fws_macdesc_state_indicate(fws, type, data);
1912                         break;
1913                 case BRCMF_FWS_TYPE_INTERFACE_OPEN:
1914                 case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
1915                         err = brcmf_fws_interface_state_indicate(fws, type,
1916                                                                  data);
1917                         break;
1918                 case BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT:
1919                 case BRCMF_FWS_TYPE_MAC_REQUEST_PACKET:
1920                         err = brcmf_fws_request_indicate(fws, type, data);
1921                         break;
1922                 case BRCMF_FWS_TYPE_TXSTATUS:
1923                 case BRCMF_FWS_TYPE_COMP_TXSTATUS:
1924                         brcmf_fws_txstatus_indicate(fws, type, data);
1925                         break;
1926                 case BRCMF_FWS_TYPE_FIFO_CREDITBACK:
1927                         err = brcmf_fws_fifocreditback_indicate(fws, data);
1928                         break;
1929                 case BRCMF_FWS_TYPE_RSSI:
1930                         brcmf_fws_rssi_indicate(fws, *data);
1931                         break;
1932                 case BRCMF_FWS_TYPE_TRANS_ID:
1933                         brcmf_fws_dbg_seqnum_check(fws, data);
1934                         break;
1935                 case BRCMF_FWS_TYPE_PKTTAG:
1936                 case BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP:
1937                 default:
1938                         fws->stats.tlv_invalid_type++;
1939                         break;
1940                 }
1941                 if (err == BRCMF_FWS_RET_OK_SCHEDULE)
1942                         status = BRCMF_FWS_RET_OK_SCHEDULE;
1943                 signal_data += len + 2;
1944                 data_len -= len + 2;
1945         }
1946
1947         if (data_len != 0)
1948                 fws->stats.tlv_parse_failed++;
1949
1950         if (status == BRCMF_FWS_RET_OK_SCHEDULE)
1951                 brcmf_fws_schedule_deq(fws);
1952
1953         /* signalling processing result does
1954          * not affect the actual ethernet packet.
1955          */
1956         skb_pull(skb, siglen);
1957
1958         /* this may be a signal-only packet
1959          */
1960         if (skb->len == 0)
1961                 fws->stats.header_only_pkt++;
1962 }
1963
1964 static u8 brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
1965                                    struct sk_buff *p)
1966 {
1967         struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
1968         struct brcmf_fws_mac_descriptor *entry = skcb->mac;
1969         u8 flags;
1970
1971         if (skcb->state != BRCMF_FWS_SKBSTATE_SUPPRESSED)
1972                 brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation);
1973         flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST;
1974         if (brcmf_skb_if_flags_get_field(p, REQUESTED)) {
1975                 /*
1976                  * Indicate that this packet is being sent in response to an
1977                  * explicit request from the firmware side.
1978                  */
1979                 flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED;
1980         }
1981         brcmf_skb_htod_tag_set_field(p, FLAGS, flags);
1982         return brcmf_fws_hdrpush(fws, p);
1983 }
1984
1985 static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
1986                                    struct sk_buff *skb, int fifo)
1987 {
1988         struct brcmf_pub *drvr = fws->drvr;
1989         struct brcmf_fws_mac_descriptor *entry;
1990         struct sk_buff *pktout;
1991         int qidx, hslot;
1992         int rc = 0;
1993
1994         entry = brcmf_skbcb(skb)->mac;
1995         if (entry->occupied) {
1996                 qidx = 2 * fifo;
1997                 if (brcmf_skbcb(skb)->state == BRCMF_FWS_SKBSTATE_SUPPRESSED)
1998                         qidx++;
1999
2000                 pktout = brcmu_pktq_penq_head(&entry->psq, qidx, skb);
2001                 if (pktout == NULL) {
2002                         bphy_err(drvr, "%s queue %d full\n", entry->name, qidx);
2003                         rc = -ENOSPC;
2004                 }
2005         } else {
2006                 bphy_err(drvr, "%s entry removed\n", entry->name);
2007                 rc = -ENOENT;
2008         }
2009
2010         if (rc) {
2011                 fws->stats.rollback_failed++;
2012                 hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
2013                 brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED,
2014                                       hslot, 0, 0, 1);
2015         } else {
2016                 fws->stats.rollback_success++;
2017                 brcmf_fws_return_credits(fws, fifo, 1);
2018                 brcmf_fws_macdesc_return_req_credit(skb);
2019         }
2020 }
2021
2022 static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws,
2023                                    int highest_lender_ac, int borrower_ac,
2024                                    bool borrow_all)
2025 {
2026         int lender_ac, borrow_limit = 0;
2027
2028         for (lender_ac = 0; lender_ac <= highest_lender_ac; lender_ac++) {
2029
2030                 if (!borrow_all)
2031                         borrow_limit =
2032                           fws->init_fifo_credit[lender_ac] / BRCMF_BORROW_RATIO;
2033                 else
2034                         borrow_limit = 0;
2035
2036                 if (fws->fifo_credit[lender_ac] > borrow_limit) {
2037                         fws->credits_borrowed[borrower_ac][lender_ac]++;
2038                         fws->fifo_credit[lender_ac]--;
2039                         if (fws->fifo_credit[lender_ac] == 0)
2040                                 fws->fifo_credit_map &= ~(1 << lender_ac);
2041                         fws->fifo_credit_map |= (1 << borrower_ac);
2042                         brcmf_dbg(DATA, "borrow credit from: %d\n", lender_ac);
2043                         return 0;
2044                 }
2045         }
2046         fws->fifo_credit_map &= ~(1 << borrower_ac);
2047         return -ENAVAIL;
2048 }
2049
2050 static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
2051                                 struct sk_buff *skb)
2052 {
2053         struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
2054         struct brcmf_fws_mac_descriptor *entry;
2055         int rc;
2056         u8 ifidx;
2057         u8 data_offset;
2058
2059         entry = skcb->mac;
2060         if (IS_ERR(entry))
2061                 return PTR_ERR(entry);
2062
2063         data_offset = brcmf_fws_precommit_skb(fws, fifo, skb);
2064         entry->transit_count++;
2065         if (entry->suppressed)
2066                 entry->suppr_transit_count++;
2067         ifidx = brcmf_skb_if_flags_get_field(skb, INDEX);
2068         brcmf_fws_unlock(fws);
2069         rc = brcmf_proto_txdata(fws->drvr, ifidx, data_offset, skb);
2070         brcmf_fws_lock(fws);
2071         brcmf_dbg(DATA, "%s flags %X htod %X bus_tx %d\n", entry->name,
2072                   skcb->if_flags, skcb->htod, rc);
2073         if (rc < 0) {
2074                 entry->transit_count--;
2075                 if (entry->suppressed)
2076                         entry->suppr_transit_count--;
2077                 (void)brcmf_proto_hdrpull(fws->drvr, false, skb, NULL);
2078                 goto rollback;
2079         }
2080
2081         fws->stats.pkt2bus++;
2082         fws->stats.send_pkts[fifo]++;
2083         if (brcmf_skb_if_flags_get_field(skb, REQUESTED))
2084                 fws->stats.requested_sent[fifo]++;
2085
2086         return rc;
2087
2088 rollback:
2089         brcmf_fws_rollback_toq(fws, skb, fifo);
2090         return rc;
2091 }
2092
2093 static int brcmf_fws_assign_htod(struct brcmf_fws_info *fws, struct sk_buff *p,
2094                                   int fifo)
2095 {
2096         struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
2097         int rc, hslot;
2098
2099         skcb->htod = 0;
2100         skcb->htod_seq = 0;
2101         hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger);
2102         brcmf_skb_htod_tag_set_field(p, HSLOT, hslot);
2103         brcmf_skb_htod_tag_set_field(p, FREERUN, skcb->mac->seq[fifo]);
2104         brcmf_skb_htod_tag_set_field(p, FIFO, fifo);
2105         rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot);
2106         if (!rc)
2107                 skcb->mac->seq[fifo]++;
2108         else
2109                 fws->stats.generic_error++;
2110         return rc;
2111 }
2112
2113 int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
2114 {
2115         struct brcmf_pub *drvr = ifp->drvr;
2116         struct brcmf_fws_info *fws = drvr_to_fws(drvr);
2117         struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
2118         struct ethhdr *eh = (struct ethhdr *)(skb->data);
2119         int fifo = BRCMF_FWS_FIFO_BCMC;
2120         bool multicast = is_multicast_ether_addr(eh->h_dest);
2121         int rc = 0;
2122
2123         brcmf_dbg(DATA, "tx proto=0x%X\n", ntohs(eh->h_proto));
2124
2125         /* set control buffer information */
2126         skcb->if_flags = 0;
2127         skcb->state = BRCMF_FWS_SKBSTATE_NEW;
2128         brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx);
2129
2130         /* mapping from 802.1d priority to firmware fifo index */
2131         if (!multicast)
2132                 fifo = brcmf_map_prio_to_aci(drvr->config, skb->priority);
2133
2134         brcmf_fws_lock(fws);
2135         if (fifo != BRCMF_FWS_FIFO_AC_BE && fifo < BRCMF_FWS_FIFO_BCMC)
2136                 fws->borrow_defer_timestamp = jiffies +
2137                                               BRCMF_FWS_BORROW_DEFER_PERIOD;
2138
2139         skcb->mac = brcmf_fws_macdesc_find(fws, ifp, eh->h_dest);
2140         brcmf_dbg(DATA, "%s mac %pM multi %d fifo %d\n", skcb->mac->name,
2141                   eh->h_dest, multicast, fifo);
2142         if (!brcmf_fws_assign_htod(fws, skb, fifo)) {
2143                 brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
2144                 brcmf_fws_schedule_deq(fws);
2145         } else {
2146                 bphy_err(drvr, "no hanger slot available\n");
2147                 rc = -ENOMEM;
2148         }
2149         brcmf_fws_unlock(fws);
2150
2151         return rc;
2152 }
2153
2154 void brcmf_fws_reset_interface(struct brcmf_if *ifp)
2155 {
2156         struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc;
2157
2158         brcmf_dbg(TRACE, "enter: bsscfgidx=%d\n", ifp->bsscfgidx);
2159         if (!entry)
2160                 return;
2161
2162         brcmf_fws_macdesc_init(entry, ifp->mac_addr, ifp->ifidx);
2163 }
2164
2165 void brcmf_fws_add_interface(struct brcmf_if *ifp)
2166 {
2167         struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
2168         struct brcmf_fws_mac_descriptor *entry;
2169
2170         if (!ifp->ndev || !brcmf_fws_queue_skbs(fws))
2171                 return;
2172
2173         entry = &fws->desc.iface[ifp->ifidx];
2174         ifp->fws_desc = entry;
2175         brcmf_fws_macdesc_init(entry, ifp->mac_addr, ifp->ifidx);
2176         brcmf_fws_macdesc_set_name(fws, entry);
2177         brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
2178                         BRCMF_FWS_PSQ_LEN);
2179         brcmf_dbg(TRACE, "added %s\n", entry->name);
2180 }
2181
2182 void brcmf_fws_del_interface(struct brcmf_if *ifp)
2183 {
2184         struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc;
2185         struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
2186
2187         if (!entry)
2188                 return;
2189
2190         brcmf_fws_lock(fws);
2191         ifp->fws_desc = NULL;
2192         brcmf_dbg(TRACE, "deleting %s\n", entry->name);
2193         brcmf_fws_macdesc_cleanup(fws, &fws->desc.iface[ifp->ifidx],
2194                                   ifp->ifidx);
2195         brcmf_fws_macdesc_deinit(entry);
2196         brcmf_fws_cleanup(fws, ifp->ifidx);
2197         brcmf_fws_unlock(fws);
2198 }
2199
2200 static void brcmf_fws_dequeue_worker(struct work_struct *worker)
2201 {
2202         struct brcmf_fws_info *fws;
2203         struct brcmf_pub *drvr;
2204         struct sk_buff *skb;
2205         int fifo;
2206         u32 hslot;
2207         u32 ifidx;
2208         int ret;
2209
2210         fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work);
2211         drvr = fws->drvr;
2212
2213         brcmf_fws_lock(fws);
2214         for (fifo = BRCMF_FWS_FIFO_BCMC; fifo >= 0 && !fws->bus_flow_blocked;
2215              fifo--) {
2216                 if (!brcmf_fws_fc_active(fws)) {
2217                         while ((skb = brcmf_fws_deq(fws, fifo)) != NULL) {
2218                                 hslot = brcmf_skb_htod_tag_get_field(skb,
2219                                                                      HSLOT);
2220                                 brcmf_fws_hanger_poppkt(&fws->hanger, hslot,
2221                                                         &skb, true);
2222                                 ifidx = brcmf_skb_if_flags_get_field(skb,
2223                                                                      INDEX);
2224                                 /* Use proto layer to send data frame */
2225                                 brcmf_fws_unlock(fws);
2226                                 ret = brcmf_proto_txdata(drvr, ifidx, 0, skb);
2227                                 brcmf_fws_lock(fws);
2228                                 if (ret < 0)
2229                                         brcmf_txfinalize(brcmf_get_ifp(drvr,
2230                                                                        ifidx),
2231                                                          skb, false);
2232                                 if (fws->bus_flow_blocked)
2233                                         break;
2234                         }
2235                         continue;
2236                 }
2237
2238                 while ((fws->fifo_credit[fifo]) ||
2239                        ((!fws->bcmc_credit_check) &&
2240                                 (fifo == BRCMF_FWS_FIFO_BCMC))) {
2241                         skb = brcmf_fws_deq(fws, fifo);
2242                         if (!skb)
2243                                 break;
2244                         fws->fifo_credit[fifo]--;
2245                         if (brcmf_fws_commit_skb(fws, fifo, skb))
2246                                 break;
2247                         if (fws->bus_flow_blocked)
2248                                 break;
2249                 }
2250
2251                 if (fifo >= BRCMF_FWS_FIFO_AC_BE &&
2252                     fifo <= BRCMF_FWS_FIFO_AC_VO &&
2253                     fws->fifo_credit[fifo] == 0 &&
2254                     !fws->bus_flow_blocked) {
2255                         while (brcmf_fws_borrow_credit(fws,
2256                                                        fifo - 1, fifo,
2257                                                        true) == 0) {
2258                                 skb = brcmf_fws_deq(fws, fifo);
2259                                 if (!skb) {
2260                                         brcmf_fws_return_credits(fws, fifo, 1);
2261                                         break;
2262                                 }
2263                                 if (brcmf_fws_commit_skb(fws, fifo, skb))
2264                                         break;
2265                                 if (fws->bus_flow_blocked)
2266                                         break;
2267                         }
2268                 }
2269         }
2270         brcmf_fws_unlock(fws);
2271 }
2272
2273 #ifdef DEBUG
2274 static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data)
2275 {
2276         struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
2277         struct brcmf_fws_stats *fwstats = &(drvr_to_fws(bus_if->drvr)->stats);
2278
2279         seq_printf(seq,
2280                    "header_pulls:      %u\n"
2281                    "header_only_pkt:   %u\n"
2282                    "tlv_parse_failed:  %u\n"
2283                    "tlv_invalid_type:  %u\n"
2284                    "mac_update_fails:  %u\n"
2285                    "ps_update_fails:   %u\n"
2286                    "if_update_fails:   %u\n"
2287                    "pkt2bus:           %u\n"
2288                    "generic_error:     %u\n"
2289                    "rollback_success:  %u\n"
2290                    "rollback_failed:   %u\n"
2291                    "delayq_full:       %u\n"
2292                    "supprq_full:       %u\n"
2293                    "txs_indicate:      %u\n"
2294                    "txs_discard:       %u\n"
2295                    "txs_suppr_core:    %u\n"
2296                    "txs_suppr_ps:      %u\n"
2297                    "txs_tossed:        %u\n"
2298                    "txs_host_tossed:   %u\n"
2299                    "bus_flow_block:    %u\n"
2300                    "fws_flow_block:    %u\n"
2301                    "send_pkts:         BK:%u BE:%u VO:%u VI:%u BCMC:%u\n"
2302                    "requested_sent:    BK:%u BE:%u VO:%u VI:%u BCMC:%u\n",
2303                    fwstats->header_pulls,
2304                    fwstats->header_only_pkt,
2305                    fwstats->tlv_parse_failed,
2306                    fwstats->tlv_invalid_type,
2307                    fwstats->mac_update_failed,
2308                    fwstats->mac_ps_update_failed,
2309                    fwstats->if_update_failed,
2310                    fwstats->pkt2bus,
2311                    fwstats->generic_error,
2312                    fwstats->rollback_success,
2313                    fwstats->rollback_failed,
2314                    fwstats->delayq_full_error,
2315                    fwstats->supprq_full_error,
2316                    fwstats->txs_indicate,
2317                    fwstats->txs_discard,
2318                    fwstats->txs_supp_core,
2319                    fwstats->txs_supp_ps,
2320                    fwstats->txs_tossed,
2321                    fwstats->txs_host_tossed,
2322                    fwstats->bus_flow_block,
2323                    fwstats->fws_flow_block,
2324                    fwstats->send_pkts[0], fwstats->send_pkts[1],
2325                    fwstats->send_pkts[2], fwstats->send_pkts[3],
2326                    fwstats->send_pkts[4],
2327                    fwstats->requested_sent[0],
2328                    fwstats->requested_sent[1],
2329                    fwstats->requested_sent[2],
2330                    fwstats->requested_sent[3],
2331                    fwstats->requested_sent[4]);
2332
2333         return 0;
2334 }
2335 #else
2336 static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data)
2337 {
2338         return 0;
2339 }
2340 #endif
2341
2342 struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr)
2343 {
2344         struct brcmf_fws_info *fws;
2345         struct brcmf_if *ifp;
2346         u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS;
2347         int rc;
2348         u32 mode;
2349
2350         fws = kzalloc(sizeof(*fws), GFP_KERNEL);
2351         if (!fws) {
2352                 rc = -ENOMEM;
2353                 goto fail;
2354         }
2355
2356         spin_lock_init(&fws->spinlock);
2357
2358         /* store drvr reference */
2359         fws->drvr = drvr;
2360         fws->fcmode = drvr->settings->fcmode;
2361
2362         if (!drvr->bus_if->always_use_fws_queue &&
2363             (fws->fcmode == BRCMF_FWS_FCMODE_NONE)) {
2364                 fws->avoid_queueing = true;
2365                 brcmf_dbg(INFO, "FWS queueing will be avoided\n");
2366                 return fws;
2367         }
2368
2369         fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq");
2370         if (fws->fws_wq == NULL) {
2371                 bphy_err(drvr, "workqueue creation failed\n");
2372                 rc = -EBADF;
2373                 goto fail;
2374         }
2375         INIT_WORK(&fws->fws_dequeue_work, brcmf_fws_dequeue_worker);
2376
2377         /* enable firmware signalling if fcmode active */
2378         if (fws->fcmode != BRCMF_FWS_FCMODE_NONE)
2379                 tlv |= BRCMF_FWS_FLAGS_XONXOFF_SIGNALS |
2380                        BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS |
2381                        BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE |
2382                        BRCMF_FWS_FLAGS_HOST_RXREORDER_ACTIVE;
2383
2384         rc = brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP,
2385                                  brcmf_fws_notify_credit_map);
2386         if (rc < 0) {
2387                 bphy_err(drvr, "register credit map handler failed\n");
2388                 goto fail;
2389         }
2390         rc = brcmf_fweh_register(drvr, BRCMF_E_BCMC_CREDIT_SUPPORT,
2391                                  brcmf_fws_notify_bcmc_credit_support);
2392         if (rc < 0) {
2393                 bphy_err(drvr, "register bcmc credit handler failed\n");
2394                 brcmf_fweh_unregister(drvr, BRCMF_E_FIFO_CREDIT_MAP);
2395                 goto fail;
2396         }
2397
2398         /* Setting the iovar may fail if feature is unsupported
2399          * so leave the rc as is so driver initialization can
2400          * continue. Set mode back to none indicating not enabled.
2401          */
2402         fws->fw_signals = true;
2403         ifp = brcmf_get_ifp(drvr, 0);
2404         if (brcmf_fil_iovar_int_set(ifp, "tlv", tlv)) {
2405                 bphy_err(drvr, "failed to set bdcv2 tlv signaling\n");
2406                 fws->fcmode = BRCMF_FWS_FCMODE_NONE;
2407                 fws->fw_signals = false;
2408         }
2409
2410         if (brcmf_fil_iovar_int_set(ifp, "ampdu_hostreorder", 1))
2411                 brcmf_dbg(INFO, "enabling AMPDU host-reorder failed\n");
2412
2413         /* Enable seq number reuse, if supported */
2414         if (brcmf_fil_iovar_int_get(ifp, "wlfc_mode", &mode) == 0) {
2415                 if (BRCMF_FWS_MODE_GET_REUSESEQ(mode)) {
2416                         mode = 0;
2417                         BRCMF_FWS_MODE_SET_REUSESEQ(mode, 1);
2418                         if (brcmf_fil_iovar_int_set(ifp,
2419                                                     "wlfc_mode", mode) == 0) {
2420                                 BRCMF_FWS_MODE_SET_REUSESEQ(fws->mode, 1);
2421                         }
2422                 }
2423         }
2424
2425         brcmf_fws_hanger_init(&fws->hanger);
2426         brcmf_fws_macdesc_init(&fws->desc.other, NULL, 0);
2427         brcmf_fws_macdesc_set_name(fws, &fws->desc.other);
2428         brcmf_dbg(INFO, "added %s\n", fws->desc.other.name);
2429         brcmu_pktq_init(&fws->desc.other.psq, BRCMF_FWS_PSQ_PREC_COUNT,
2430                         BRCMF_FWS_PSQ_LEN);
2431
2432         brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n",
2433                   fws->fw_signals ? "enabled" : "disabled", tlv);
2434         return fws;
2435
2436 fail:
2437         brcmf_fws_detach(fws);
2438         return ERR_PTR(rc);
2439 }
2440
2441 void brcmf_fws_detach(struct brcmf_fws_info *fws)
2442 {
2443         if (!fws)
2444                 return;
2445
2446         if (fws->fws_wq)
2447                 destroy_workqueue(fws->fws_wq);
2448
2449         /* cleanup */
2450         brcmf_fws_lock(fws);
2451         brcmf_fws_cleanup(fws, -1);
2452         brcmf_fws_unlock(fws);
2453
2454         /* free top structure */
2455         kfree(fws);
2456 }
2457
2458 void brcmf_fws_debugfs_create(struct brcmf_pub *drvr)
2459 {
2460         /* create debugfs file for statistics */
2461         brcmf_debugfs_add_entry(drvr, "fws_stats",
2462                                 brcmf_debugfs_fws_stats_read);
2463 }
2464
2465 bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws)
2466 {
2467         return !fws->avoid_queueing;
2468 }
2469
2470 bool brcmf_fws_fc_active(struct brcmf_fws_info *fws)
2471 {
2472         if (!fws->creditmap_received)
2473                 return false;
2474
2475         return fws->fcmode != BRCMF_FWS_FCMODE_NONE;
2476 }
2477
2478 void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb)
2479 {
2480         u32 hslot;
2481
2482         if (brcmf_skbcb(skb)->state == BRCMF_FWS_SKBSTATE_TIM) {
2483                 brcmu_pkt_buf_free_skb(skb);
2484                 return;
2485         }
2486         brcmf_fws_lock(fws);
2487         hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
2488         brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0, 0,
2489                               1);
2490         brcmf_fws_unlock(fws);
2491 }
2492
2493 void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked)
2494 {
2495         struct brcmf_fws_info *fws = drvr_to_fws(drvr);
2496         struct brcmf_if *ifp;
2497         int i;
2498
2499         if (fws->avoid_queueing) {
2500                 for (i = 0; i < BRCMF_MAX_IFS; i++) {
2501                         ifp = drvr->iflist[i];
2502                         if (!ifp || !ifp->ndev)
2503                                 continue;
2504                         brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FLOW,
2505                                              flow_blocked);
2506                 }
2507         } else {
2508                 fws->bus_flow_blocked = flow_blocked;
2509                 if (!flow_blocked)
2510                         brcmf_fws_schedule_deq(fws);
2511                 else
2512                         fws->stats.bus_flow_block++;
2513         }
2514 }