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