]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
Merge remote-tracking branch 'driver-core/driver-core-next'
[karo-tx-linux.git] / drivers / net / wireless / brcm80211 / brcmfmac / fwsignal.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 #include <linux/types.h>
17 #include <linux/module.h>
18 #include <linux/if_ether.h>
19 #include <linux/spinlock.h>
20 #include <linux/skbuff.h>
21 #include <linux/netdevice.h>
22 #include <linux/etherdevice.h>
23 #include <linux/err.h>
24 #include <linux/jiffies.h>
25 #include <net/cfg80211.h>
26
27 #include <brcmu_utils.h>
28 #include <brcmu_wifi.h>
29 #include "dhd.h"
30 #include "dhd_proto.h"
31 #include "dhd_dbg.h"
32 #include "dhd_bus.h"
33 #include "fwil.h"
34 #include "fwil_types.h"
35 #include "fweh.h"
36 #include "fwsignal.h"
37 #include "p2p.h"
38 #include "wl_cfg80211.h"
39
40 /**
41  * DOC: Firmware Signalling
42  *
43  * Firmware can send signals to host and vice versa, which are passed in the
44  * data packets using TLV based header. This signalling layer is on top of the
45  * BDC bus protocol layer.
46  */
47
48 /*
49  * single definition for firmware-driver flow control tlv's.
50  *
51  * each tlv is specified by BRCMF_FWS_TLV_DEF(name, ID, length).
52  * A length value 0 indicates variable length tlv.
53  */
54 #define BRCMF_FWS_TLV_DEFLIST \
55         BRCMF_FWS_TLV_DEF(MAC_OPEN, 1, 1) \
56         BRCMF_FWS_TLV_DEF(MAC_CLOSE, 2, 1) \
57         BRCMF_FWS_TLV_DEF(MAC_REQUEST_CREDIT, 3, 2) \
58         BRCMF_FWS_TLV_DEF(TXSTATUS, 4, 4) \
59         BRCMF_FWS_TLV_DEF(PKTTAG, 5, 4) \
60         BRCMF_FWS_TLV_DEF(MACDESC_ADD,  6, 8) \
61         BRCMF_FWS_TLV_DEF(MACDESC_DEL, 7, 8) \
62         BRCMF_FWS_TLV_DEF(RSSI, 8, 1) \
63         BRCMF_FWS_TLV_DEF(INTERFACE_OPEN, 9, 1) \
64         BRCMF_FWS_TLV_DEF(INTERFACE_CLOSE, 10, 1) \
65         BRCMF_FWS_TLV_DEF(FIFO_CREDITBACK, 11, 6) \
66         BRCMF_FWS_TLV_DEF(PENDING_TRAFFIC_BMP, 12, 2) \
67         BRCMF_FWS_TLV_DEF(MAC_REQUEST_PACKET, 13, 3) \
68         BRCMF_FWS_TLV_DEF(HOST_REORDER_RXPKTS, 14, 10) \
69         BRCMF_FWS_TLV_DEF(TRANS_ID, 18, 6) \
70         BRCMF_FWS_TLV_DEF(COMP_TXSTATUS, 19, 1) \
71         BRCMF_FWS_TLV_DEF(FILLER, 255, 0)
72
73 /*
74  * enum brcmf_fws_tlv_type - definition of tlv identifiers.
75  */
76 #define BRCMF_FWS_TLV_DEF(name, id, len) \
77         BRCMF_FWS_TYPE_ ## name =  id,
78 enum brcmf_fws_tlv_type {
79         BRCMF_FWS_TLV_DEFLIST
80         BRCMF_FWS_TYPE_INVALID
81 };
82 #undef BRCMF_FWS_TLV_DEF
83
84 /*
85  * enum brcmf_fws_tlv_len - definition of tlv lengths.
86  */
87 #define BRCMF_FWS_TLV_DEF(name, id, len) \
88         BRCMF_FWS_TYPE_ ## name ## _LEN = (len),
89 enum brcmf_fws_tlv_len {
90         BRCMF_FWS_TLV_DEFLIST
91 };
92 #undef BRCMF_FWS_TLV_DEF
93
94 #ifdef DEBUG
95 /*
96  * brcmf_fws_tlv_names - array of tlv names.
97  */
98 #define BRCMF_FWS_TLV_DEF(name, id, len) \
99         { id, #name },
100 static struct {
101         enum brcmf_fws_tlv_type id;
102         const char *name;
103 } brcmf_fws_tlv_names[] = {
104         BRCMF_FWS_TLV_DEFLIST
105 };
106 #undef BRCMF_FWS_TLV_DEF
107
108 static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
109 {
110         int i;
111
112         for (i = 0; i < ARRAY_SIZE(brcmf_fws_tlv_names); i++)
113                 if (brcmf_fws_tlv_names[i].id == id)
114                         return brcmf_fws_tlv_names[i].name;
115
116         return "INVALID";
117 }
118 #else
119 static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
120 {
121         return "NODEBUG";
122 }
123 #endif /* DEBUG */
124
125 /*
126  * flags used to enable tlv signalling from firmware.
127  */
128 #define BRCMF_FWS_FLAGS_RSSI_SIGNALS                    0x0001
129 #define BRCMF_FWS_FLAGS_XONXOFF_SIGNALS                 0x0002
130 #define BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS           0x0004
131 #define BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE        0x0008
132 #define BRCMF_FWS_FLAGS_PSQ_GENERATIONFSM_ENABLE        0x0010
133 #define BRCMF_FWS_FLAGS_PSQ_ZERO_BUFFER_ENABLE          0x0020
134 #define BRCMF_FWS_FLAGS_HOST_RXREORDER_ACTIVE           0x0040
135
136 #define BRCMF_FWS_MAC_DESC_TABLE_SIZE                   32
137 #define BRCMF_FWS_MAC_DESC_ID_INVALID                   0xff
138
139 #define BRCMF_FWS_HOSTIF_FLOWSTATE_OFF                  0
140 #define BRCMF_FWS_HOSTIF_FLOWSTATE_ON                   1
141 #define BRCMF_FWS_FLOWCONTROL_HIWATER                   128
142 #define BRCMF_FWS_FLOWCONTROL_LOWATER                   64
143
144 #define BRCMF_FWS_PSQ_PREC_COUNT                ((BRCMF_FWS_FIFO_COUNT + 1) * 2)
145 #define BRCMF_FWS_PSQ_LEN                               256
146
147 #define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST                 0x01
148 #define BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED               0x02
149
150 #define BRCMF_FWS_RET_OK_NOSCHEDULE     0
151 #define BRCMF_FWS_RET_OK_SCHEDULE       1
152
153 /**
154  * enum brcmf_fws_skb_state - indicates processing state of skb.
155  *
156  * @BRCMF_FWS_SKBSTATE_NEW: sk_buff is newly arrived in the driver.
157  * @BRCMF_FWS_SKBSTATE_DELAYED: sk_buff had to wait on queue.
158  * @BRCMF_FWS_SKBSTATE_SUPPRESSED: sk_buff has been suppressed by firmware.
159  * @BRCMF_FWS_SKBSTATE_TIM: allocated for TIM update info.
160  */
161 enum brcmf_fws_skb_state {
162         BRCMF_FWS_SKBSTATE_NEW,
163         BRCMF_FWS_SKBSTATE_DELAYED,
164         BRCMF_FWS_SKBSTATE_SUPPRESSED,
165         BRCMF_FWS_SKBSTATE_TIM
166 };
167
168 /**
169  * struct brcmf_skbuff_cb - control buffer associated with skbuff.
170  *
171  * @bus_flags: 2 bytes reserved for bus specific parameters
172  * @if_flags: holds interface index and packet related flags.
173  * @htod: host to device packet identifier (used in PKTTAG tlv).
174  * @state: transmit state of the packet.
175  * @mac: descriptor related to destination for this packet.
176  *
177  * This information is stored in control buffer struct sk_buff::cb, which
178  * provides 48 bytes of storage so this structure should not exceed that.
179  */
180 struct brcmf_skbuff_cb {
181         u16 bus_flags;
182         u16 if_flags;
183         u32 htod;
184         enum brcmf_fws_skb_state state;
185         struct brcmf_fws_mac_descriptor *mac;
186 };
187
188 /*
189  * macro casting skbuff control buffer to struct brcmf_skbuff_cb.
190  */
191 #define brcmf_skbcb(skb)        ((struct brcmf_skbuff_cb *)((skb)->cb))
192
193 /*
194  * sk_buff control if flags
195  *
196  *      b[11]  - packet sent upon firmware request.
197  *      b[10]  - packet only contains signalling data.
198  *      b[9]   - packet is a tx packet.
199  *      b[8]   - packet used requested credit
200  *      b[7]   - interface in AP mode.
201  *      b[3:0] - interface index.
202  */
203 #define BRCMF_SKB_IF_FLAGS_REQUESTED_MASK       0x0800
204 #define BRCMF_SKB_IF_FLAGS_REQUESTED_SHIFT      11
205 #define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_MASK     0x0400
206 #define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_SHIFT    10
207 #define BRCMF_SKB_IF_FLAGS_TRANSMIT_MASK        0x0200
208 #define BRCMF_SKB_IF_FLAGS_TRANSMIT_SHIFT       9
209 #define BRCMF_SKB_IF_FLAGS_REQ_CREDIT_MASK      0x0100
210 #define BRCMF_SKB_IF_FLAGS_REQ_CREDIT_SHIFT     8
211 #define BRCMF_SKB_IF_FLAGS_IF_AP_MASK           0x0080
212 #define BRCMF_SKB_IF_FLAGS_IF_AP_SHIFT          7
213 #define BRCMF_SKB_IF_FLAGS_INDEX_MASK           0x000f
214 #define BRCMF_SKB_IF_FLAGS_INDEX_SHIFT          0
215
216 #define brcmf_skb_if_flags_set_field(skb, field, value) \
217         brcmu_maskset16(&(brcmf_skbcb(skb)->if_flags), \
218                         BRCMF_SKB_IF_FLAGS_ ## field ## _MASK, \
219                         BRCMF_SKB_IF_FLAGS_ ## field ## _SHIFT, (value))
220 #define brcmf_skb_if_flags_get_field(skb, field) \
221         brcmu_maskget16(brcmf_skbcb(skb)->if_flags, \
222                         BRCMF_SKB_IF_FLAGS_ ## field ## _MASK, \
223                         BRCMF_SKB_IF_FLAGS_ ## field ## _SHIFT)
224
225 /*
226  * sk_buff control packet identifier
227  *
228  * 32-bit packet identifier used in PKTTAG tlv from host to dongle.
229  *
230  * - Generated at the host (e.g. dhd)
231  * - Seen as a generic sequence number by firmware except for the flags field.
232  *
233  * Generation   : b[31] => generation number for this packet [host->fw]
234  *                         OR, current generation number [fw->host]
235  * Flags        : b[30:27] => command, status flags
236  * FIFO-AC      : b[26:24] => AC-FIFO id
237  * h-slot       : b[23:8] => hanger-slot
238  * freerun      : b[7:0] => A free running counter
239  */
240 #define BRCMF_SKB_HTOD_TAG_GENERATION_MASK              0x80000000
241 #define BRCMF_SKB_HTOD_TAG_GENERATION_SHIFT             31
242 #define BRCMF_SKB_HTOD_TAG_FLAGS_MASK                   0x78000000
243 #define BRCMF_SKB_HTOD_TAG_FLAGS_SHIFT                  27
244 #define BRCMF_SKB_HTOD_TAG_FIFO_MASK                    0x07000000
245 #define BRCMF_SKB_HTOD_TAG_FIFO_SHIFT                   24
246 #define BRCMF_SKB_HTOD_TAG_HSLOT_MASK                   0x00ffff00
247 #define BRCMF_SKB_HTOD_TAG_HSLOT_SHIFT                  8
248 #define BRCMF_SKB_HTOD_TAG_FREERUN_MASK                 0x000000ff
249 #define BRCMF_SKB_HTOD_TAG_FREERUN_SHIFT                0
250
251 #define brcmf_skb_htod_tag_set_field(skb, field, value) \
252         brcmu_maskset32(&(brcmf_skbcb(skb)->htod), \
253                         BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \
254                         BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT, (value))
255 #define brcmf_skb_htod_tag_get_field(skb, field) \
256         brcmu_maskget32(brcmf_skbcb(skb)->htod, \
257                         BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \
258                         BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT)
259
260 #define BRCMF_FWS_TXSTAT_GENERATION_MASK        0x80000000
261 #define BRCMF_FWS_TXSTAT_GENERATION_SHIFT       31
262 #define BRCMF_FWS_TXSTAT_FLAGS_MASK             0x78000000
263 #define BRCMF_FWS_TXSTAT_FLAGS_SHIFT            27
264 #define BRCMF_FWS_TXSTAT_FIFO_MASK              0x07000000
265 #define BRCMF_FWS_TXSTAT_FIFO_SHIFT             24
266 #define BRCMF_FWS_TXSTAT_HSLOT_MASK             0x00FFFF00
267 #define BRCMF_FWS_TXSTAT_HSLOT_SHIFT            8
268 #define BRCMF_FWS_TXSTAT_PKTID_MASK             0x00FFFFFF
269 #define BRCMF_FWS_TXSTAT_PKTID_SHIFT            0
270
271 #define brcmf_txstatus_get_field(txs, field) \
272         brcmu_maskget32(txs, BRCMF_FWS_TXSTAT_ ## field ## _MASK, \
273                         BRCMF_FWS_TXSTAT_ ## field ## _SHIFT)
274
275 /* How long to defer borrowing in jiffies */
276 #define BRCMF_FWS_BORROW_DEFER_PERIOD           (HZ / 10)
277
278 /**
279  * enum brcmf_fws_fifo - fifo indices used by dongle firmware.
280  *
281  * @BRCMF_FWS_FIFO_FIRST: first fifo, ie. background.
282  * @BRCMF_FWS_FIFO_AC_BK: fifo for background traffic.
283  * @BRCMF_FWS_FIFO_AC_BE: fifo for best-effort traffic.
284  * @BRCMF_FWS_FIFO_AC_VI: fifo for video traffic.
285  * @BRCMF_FWS_FIFO_AC_VO: fifo for voice traffic.
286  * @BRCMF_FWS_FIFO_BCMC: fifo for broadcast/multicast (AP only).
287  * @BRCMF_FWS_FIFO_ATIM: fifo for ATIM (AP only).
288  * @BRCMF_FWS_FIFO_COUNT: number of fifos.
289  */
290 enum brcmf_fws_fifo {
291         BRCMF_FWS_FIFO_FIRST,
292         BRCMF_FWS_FIFO_AC_BK = BRCMF_FWS_FIFO_FIRST,
293         BRCMF_FWS_FIFO_AC_BE,
294         BRCMF_FWS_FIFO_AC_VI,
295         BRCMF_FWS_FIFO_AC_VO,
296         BRCMF_FWS_FIFO_BCMC,
297         BRCMF_FWS_FIFO_ATIM,
298         BRCMF_FWS_FIFO_COUNT
299 };
300
301 /**
302  * enum brcmf_fws_txstatus - txstatus flag values.
303  *
304  * @BRCMF_FWS_TXSTATUS_DISCARD:
305  *      host is free to discard the packet.
306  * @BRCMF_FWS_TXSTATUS_CORE_SUPPRESS:
307  *      802.11 core suppressed the packet.
308  * @BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS:
309  *      firmware suppress the packet as device is already in PS mode.
310  * @BRCMF_FWS_TXSTATUS_FW_TOSSED:
311  *      firmware tossed the packet.
312  * @BRCMF_FWS_TXSTATUS_HOST_TOSSED:
313  *      host tossed the packet.
314  */
315 enum brcmf_fws_txstatus {
316         BRCMF_FWS_TXSTATUS_DISCARD,
317         BRCMF_FWS_TXSTATUS_CORE_SUPPRESS,
318         BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS,
319         BRCMF_FWS_TXSTATUS_FW_TOSSED,
320         BRCMF_FWS_TXSTATUS_HOST_TOSSED
321 };
322
323 enum brcmf_fws_fcmode {
324         BRCMF_FWS_FCMODE_NONE,
325         BRCMF_FWS_FCMODE_IMPLIED_CREDIT,
326         BRCMF_FWS_FCMODE_EXPLICIT_CREDIT
327 };
328
329 enum brcmf_fws_mac_desc_state {
330         BRCMF_FWS_STATE_OPEN = 1,
331         BRCMF_FWS_STATE_CLOSE
332 };
333
334 /**
335  * struct brcmf_fws_mac_descriptor - firmware signalling data per node/interface
336  *
337  * @occupied: slot is in use.
338  * @mac_handle: handle for mac entry determined by firmware.
339  * @interface_id: interface index.
340  * @state: current state.
341  * @suppressed: mac entry is suppressed.
342  * @generation: generation bit.
343  * @ac_bitmap: ac queue bitmap.
344  * @requested_credit: credits requested by firmware.
345  * @ea: ethernet address.
346  * @seq: per-node free-running sequence.
347  * @psq: power-save queue.
348  * @transit_count: packet in transit to firmware.
349  */
350 struct brcmf_fws_mac_descriptor {
351         char name[16];
352         u8 occupied;
353         u8 mac_handle;
354         u8 interface_id;
355         u8 state;
356         bool suppressed;
357         u8 generation;
358         u8 ac_bitmap;
359         u8 requested_credit;
360         u8 requested_packet;
361         u8 ea[ETH_ALEN];
362         u8 seq[BRCMF_FWS_FIFO_COUNT];
363         struct pktq psq;
364         int transit_count;
365         int suppr_transit_count;
366         bool send_tim_signal;
367         u8 traffic_pending_bmp;
368         u8 traffic_lastreported_bmp;
369 };
370
371 #define BRCMF_FWS_HANGER_MAXITEMS       1024
372
373 /**
374  * enum brcmf_fws_hanger_item_state - state of hanger item.
375  *
376  * @BRCMF_FWS_HANGER_ITEM_STATE_FREE: item is free for use.
377  * @BRCMF_FWS_HANGER_ITEM_STATE_INUSE: item is in use.
378  * @BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED: item was suppressed.
379  */
380 enum brcmf_fws_hanger_item_state {
381         BRCMF_FWS_HANGER_ITEM_STATE_FREE = 1,
382         BRCMF_FWS_HANGER_ITEM_STATE_INUSE,
383         BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED
384 };
385
386
387 /**
388  * struct brcmf_fws_hanger_item - single entry for tx pending packet.
389  *
390  * @state: entry is either free or occupied.
391  * @pkt: packet itself.
392  */
393 struct brcmf_fws_hanger_item {
394         enum brcmf_fws_hanger_item_state state;
395         struct sk_buff *pkt;
396 };
397
398 /**
399  * struct brcmf_fws_hanger - holds packets awaiting firmware txstatus.
400  *
401  * @pushed: packets pushed to await txstatus.
402  * @popped: packets popped upon handling txstatus.
403  * @failed_to_push: packets that could not be pushed.
404  * @failed_to_pop: packets that could not be popped.
405  * @failed_slotfind: packets for which failed to find an entry.
406  * @slot_pos: last returned item index for a free entry.
407  * @items: array of hanger items.
408  */
409 struct brcmf_fws_hanger {
410         u32 pushed;
411         u32 popped;
412         u32 failed_to_push;
413         u32 failed_to_pop;
414         u32 failed_slotfind;
415         u32 slot_pos;
416         struct brcmf_fws_hanger_item items[BRCMF_FWS_HANGER_MAXITEMS];
417 };
418
419 struct brcmf_fws_macdesc_table {
420         struct brcmf_fws_mac_descriptor nodes[BRCMF_FWS_MAC_DESC_TABLE_SIZE];
421         struct brcmf_fws_mac_descriptor iface[BRCMF_MAX_IFS];
422         struct brcmf_fws_mac_descriptor other;
423 };
424
425 struct brcmf_fws_info {
426         struct brcmf_pub *drvr;
427         spinlock_t spinlock;
428         ulong flags;
429         struct brcmf_fws_stats stats;
430         struct brcmf_fws_hanger hanger;
431         enum brcmf_fws_fcmode fcmode;
432         bool fw_signals;
433         bool bcmc_credit_check;
434         struct brcmf_fws_macdesc_table desc;
435         struct workqueue_struct *fws_wq;
436         struct work_struct fws_dequeue_work;
437         u32 fifo_enqpkt[BRCMF_FWS_FIFO_COUNT];
438         int fifo_credit[BRCMF_FWS_FIFO_COUNT];
439         int credits_borrowed[BRCMF_FWS_FIFO_AC_VO + 1];
440         int deq_node_pos[BRCMF_FWS_FIFO_COUNT];
441         u32 fifo_credit_map;
442         u32 fifo_delay_map;
443         unsigned long borrow_defer_timestamp;
444         bool bus_flow_blocked;
445         bool creditmap_received;
446 };
447
448 /*
449  * brcmf_fws_prio2fifo - mapping from 802.1d priority to firmware fifo index.
450  */
451 static const int brcmf_fws_prio2fifo[] = {
452         BRCMF_FWS_FIFO_AC_BE,
453         BRCMF_FWS_FIFO_AC_BK,
454         BRCMF_FWS_FIFO_AC_BK,
455         BRCMF_FWS_FIFO_AC_BE,
456         BRCMF_FWS_FIFO_AC_VI,
457         BRCMF_FWS_FIFO_AC_VI,
458         BRCMF_FWS_FIFO_AC_VO,
459         BRCMF_FWS_FIFO_AC_VO
460 };
461
462 static int fcmode;
463 module_param(fcmode, int, S_IRUSR);
464 MODULE_PARM_DESC(fcmode, "mode of firmware signalled flow control");
465
466 #define BRCMF_FWS_TLV_DEF(name, id, len) \
467         case BRCMF_FWS_TYPE_ ## name: \
468                 return len;
469
470 /**
471  * brcmf_fws_get_tlv_len() - returns defined length for given tlv id.
472  *
473  * @fws: firmware-signalling information.
474  * @id: identifier of the TLV.
475  *
476  * Return: the specified length for the given TLV; Otherwise -EINVAL.
477  */
478 static int brcmf_fws_get_tlv_len(struct brcmf_fws_info *fws,
479                                  enum brcmf_fws_tlv_type id)
480 {
481         switch (id) {
482         BRCMF_FWS_TLV_DEFLIST
483         default:
484                 fws->stats.tlv_invalid_type++;
485                 break;
486         }
487         return -EINVAL;
488 }
489 #undef BRCMF_FWS_TLV_DEF
490
491 static void brcmf_fws_lock(struct brcmf_fws_info *fws)
492                 __acquires(&fws->spinlock)
493 {
494         spin_lock_irqsave(&fws->spinlock, fws->flags);
495 }
496
497 static void brcmf_fws_unlock(struct brcmf_fws_info *fws)
498                 __releases(&fws->spinlock)
499 {
500         spin_unlock_irqrestore(&fws->spinlock, fws->flags);
501 }
502
503 static bool brcmf_fws_ifidx_match(struct sk_buff *skb, void *arg)
504 {
505         u32 ifidx = brcmf_skb_if_flags_get_field(skb, INDEX);
506         return ifidx == *(int *)arg;
507 }
508
509 static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q,
510                                 int ifidx)
511 {
512         bool (*matchfn)(struct sk_buff *, void *) = NULL;
513         struct sk_buff *skb;
514         int prec;
515
516         if (ifidx != -1)
517                 matchfn = brcmf_fws_ifidx_match;
518         for (prec = 0; prec < q->num_prec; prec++) {
519                 skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
520                 while (skb) {
521                         brcmu_pkt_buf_free_skb(skb);
522                         skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
523                 }
524         }
525 }
526
527 static void brcmf_fws_hanger_init(struct brcmf_fws_hanger *hanger)
528 {
529         int i;
530
531         memset(hanger, 0, sizeof(*hanger));
532         for (i = 0; i < ARRAY_SIZE(hanger->items); i++)
533                 hanger->items[i].state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
534 }
535
536 static u32 brcmf_fws_hanger_get_free_slot(struct brcmf_fws_hanger *h)
537 {
538         u32 i;
539
540         i = (h->slot_pos + 1) % BRCMF_FWS_HANGER_MAXITEMS;
541
542         while (i != h->slot_pos) {
543                 if (h->items[i].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
544                         h->slot_pos = i;
545                         goto done;
546                 }
547                 i++;
548                 if (i == BRCMF_FWS_HANGER_MAXITEMS)
549                         i = 0;
550         }
551         brcmf_err("all slots occupied\n");
552         h->failed_slotfind++;
553         i = BRCMF_FWS_HANGER_MAXITEMS;
554 done:
555         return i;
556 }
557
558 static int brcmf_fws_hanger_pushpkt(struct brcmf_fws_hanger *h,
559                                     struct sk_buff *pkt, u32 slot_id)
560 {
561         if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
562                 return -ENOENT;
563
564         if (h->items[slot_id].state != BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
565                 brcmf_err("slot is not free\n");
566                 h->failed_to_push++;
567                 return -EINVAL;
568         }
569
570         h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_INUSE;
571         h->items[slot_id].pkt = pkt;
572         h->pushed++;
573         return 0;
574 }
575
576 static int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h,
577                                           u32 slot_id, struct sk_buff **pktout,
578                                           bool remove_item)
579 {
580         if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
581                 return -ENOENT;
582
583         if (h->items[slot_id].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
584                 brcmf_err("entry not in use\n");
585                 h->failed_to_pop++;
586                 return -EINVAL;
587         }
588
589         *pktout = h->items[slot_id].pkt;
590         if (remove_item) {
591                 h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
592                 h->items[slot_id].pkt = NULL;
593                 h->popped++;
594         }
595         return 0;
596 }
597
598 static int brcmf_fws_hanger_mark_suppressed(struct brcmf_fws_hanger *h,
599                                             u32 slot_id)
600 {
601         if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
602                 return -ENOENT;
603
604         if (h->items[slot_id].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
605                 brcmf_err("entry not in use\n");
606                 return -EINVAL;
607         }
608
609         h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED;
610         return 0;
611 }
612
613 static void brcmf_fws_hanger_cleanup(struct brcmf_fws_info *fws,
614                                      bool (*fn)(struct sk_buff *, void *),
615                                      int ifidx)
616 {
617         struct brcmf_fws_hanger *h = &fws->hanger;
618         struct sk_buff *skb;
619         int i;
620         enum brcmf_fws_hanger_item_state s;
621
622         for (i = 0; i < ARRAY_SIZE(h->items); i++) {
623                 s = h->items[i].state;
624                 if (s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE ||
625                     s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED) {
626                         skb = h->items[i].pkt;
627                         if (fn == NULL || fn(skb, &ifidx)) {
628                                 /* suppress packets freed from psq */
629                                 if (s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE)
630                                         brcmu_pkt_buf_free_skb(skb);
631                                 h->items[i].state =
632                                         BRCMF_FWS_HANGER_ITEM_STATE_FREE;
633                         }
634                 }
635         }
636 }
637
638 static void brcmf_fws_macdesc_set_name(struct brcmf_fws_info *fws,
639                                        struct brcmf_fws_mac_descriptor *desc)
640 {
641         if (desc == &fws->desc.other)
642                 strlcpy(desc->name, "MAC-OTHER", sizeof(desc->name));
643         else if (desc->mac_handle)
644                 scnprintf(desc->name, sizeof(desc->name), "MAC-%d:%d",
645                           desc->mac_handle, desc->interface_id);
646         else
647                 scnprintf(desc->name, sizeof(desc->name), "MACIF:%d",
648                           desc->interface_id);
649 }
650
651 static void brcmf_fws_macdesc_init(struct brcmf_fws_mac_descriptor *desc,
652                                    u8 *addr, u8 ifidx)
653 {
654         brcmf_dbg(TRACE,
655                   "enter: desc %p ea=%pM, ifidx=%u\n", desc, addr, ifidx);
656         desc->occupied = 1;
657         desc->state = BRCMF_FWS_STATE_OPEN;
658         desc->requested_credit = 0;
659         desc->requested_packet = 0;
660         /* depending on use may need ifp->bssidx instead */
661         desc->interface_id = ifidx;
662         desc->ac_bitmap = 0xff; /* update this when handling APSD */
663         if (addr)
664                 memcpy(&desc->ea[0], addr, ETH_ALEN);
665 }
666
667 static
668 void brcmf_fws_macdesc_deinit(struct brcmf_fws_mac_descriptor *desc)
669 {
670         brcmf_dbg(TRACE,
671                   "enter: ea=%pM, ifidx=%u\n", desc->ea, desc->interface_id);
672         desc->occupied = 0;
673         desc->state = BRCMF_FWS_STATE_CLOSE;
674         desc->requested_credit = 0;
675         desc->requested_packet = 0;
676 }
677
678 static struct brcmf_fws_mac_descriptor *
679 brcmf_fws_macdesc_lookup(struct brcmf_fws_info *fws, u8 *ea)
680 {
681         struct brcmf_fws_mac_descriptor *entry;
682         int i;
683
684         if (ea == NULL)
685                 return ERR_PTR(-EINVAL);
686
687         entry = &fws->desc.nodes[0];
688         for (i = 0; i < ARRAY_SIZE(fws->desc.nodes); i++) {
689                 if (entry->occupied && !memcmp(entry->ea, ea, ETH_ALEN))
690                         return entry;
691                 entry++;
692         }
693
694         return ERR_PTR(-ENOENT);
695 }
696
697 static struct brcmf_fws_mac_descriptor*
698 brcmf_fws_macdesc_find(struct brcmf_fws_info *fws, struct brcmf_if *ifp, u8 *da)
699 {
700         struct brcmf_fws_mac_descriptor *entry = &fws->desc.other;
701         bool multicast;
702
703         multicast = is_multicast_ether_addr(da);
704
705         /* Multicast destination, STA and P2P clients get the interface entry.
706          * STA/GC gets the Mac Entry for TDLS destinations, TDLS destinations
707          * have their own entry.
708          */
709         if (multicast && ifp->fws_desc) {
710                 entry = ifp->fws_desc;
711                 goto done;
712         }
713
714         entry = brcmf_fws_macdesc_lookup(fws, da);
715         if (IS_ERR(entry))
716                 entry = ifp->fws_desc;
717
718 done:
719         return entry;
720 }
721
722 static bool brcmf_fws_macdesc_closed(struct brcmf_fws_info *fws,
723                                      struct brcmf_fws_mac_descriptor *entry,
724                                      int fifo)
725 {
726         struct brcmf_fws_mac_descriptor *if_entry;
727         bool closed;
728
729         /* for unique destination entries the related interface
730          * may be closed.
731          */
732         if (entry->mac_handle) {
733                 if_entry = &fws->desc.iface[entry->interface_id];
734                 if (if_entry->state == BRCMF_FWS_STATE_CLOSE)
735                         return true;
736         }
737         /* an entry is closed when the state is closed and
738          * the firmware did not request anything.
739          */
740         closed = entry->state == BRCMF_FWS_STATE_CLOSE &&
741                  !entry->requested_credit && !entry->requested_packet;
742
743         /* Or firmware does not allow traffic for given fifo */
744         return closed || !(entry->ac_bitmap & BIT(fifo));
745 }
746
747 static void brcmf_fws_macdesc_cleanup(struct brcmf_fws_info *fws,
748                                       struct brcmf_fws_mac_descriptor *entry,
749                                       int ifidx)
750 {
751         if (entry->occupied && (ifidx == -1 || ifidx == entry->interface_id)) {
752                 brcmf_fws_psq_flush(fws, &entry->psq, ifidx);
753                 entry->occupied = !!(entry->psq.len);
754         }
755 }
756
757 static void brcmf_fws_bus_txq_cleanup(struct brcmf_fws_info *fws,
758                                       bool (*fn)(struct sk_buff *, void *),
759                                       int ifidx)
760 {
761         struct brcmf_fws_hanger_item *hi;
762         struct pktq *txq;
763         struct sk_buff *skb;
764         int prec;
765         u32 hslot;
766
767         txq = brcmf_bus_gettxq(fws->drvr->bus_if);
768         if (IS_ERR(txq)) {
769                 brcmf_dbg(TRACE, "no txq to clean up\n");
770                 return;
771         }
772
773         for (prec = 0; prec < txq->num_prec; prec++) {
774                 skb = brcmu_pktq_pdeq_match(txq, prec, fn, &ifidx);
775                 while (skb) {
776                         hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
777                         hi = &fws->hanger.items[hslot];
778                         WARN_ON(skb != hi->pkt);
779                         hi->state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
780                         brcmu_pkt_buf_free_skb(skb);
781                         skb = brcmu_pktq_pdeq_match(txq, prec, fn, &ifidx);
782                 }
783         }
784 }
785
786 static void brcmf_fws_cleanup(struct brcmf_fws_info *fws, int ifidx)
787 {
788         int i;
789         struct brcmf_fws_mac_descriptor *table;
790         bool (*matchfn)(struct sk_buff *, void *) = NULL;
791
792         if (fws == NULL)
793                 return;
794
795         if (ifidx != -1)
796                 matchfn = brcmf_fws_ifidx_match;
797
798         /* cleanup individual nodes */
799         table = &fws->desc.nodes[0];
800         for (i = 0; i < ARRAY_SIZE(fws->desc.nodes); i++)
801                 brcmf_fws_macdesc_cleanup(fws, &table[i], ifidx);
802
803         brcmf_fws_macdesc_cleanup(fws, &fws->desc.other, ifidx);
804         brcmf_fws_bus_txq_cleanup(fws, matchfn, ifidx);
805         brcmf_fws_hanger_cleanup(fws, matchfn, ifidx);
806 }
807
808 static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
809 {
810         struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
811         u8 *wlh;
812         u16 data_offset = 0;
813         u8 fillers;
814         __le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod);
815
816         brcmf_dbg(TRACE, "enter: %s, idx=%d pkttag=0x%08X, hslot=%d\n",
817                   entry->name, brcmf_skb_if_flags_get_field(skb, INDEX),
818                   le32_to_cpu(pkttag), (le32_to_cpu(pkttag) >> 8) & 0xffff);
819         if (entry->send_tim_signal)
820                 data_offset += 2 + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN;
821
822         /* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */
823         data_offset += 2 + BRCMF_FWS_TYPE_PKTTAG_LEN;
824         fillers = round_up(data_offset, 4) - data_offset;
825         data_offset += fillers;
826
827         skb_push(skb, data_offset);
828         wlh = skb->data;
829
830         wlh[0] = BRCMF_FWS_TYPE_PKTTAG;
831         wlh[1] = BRCMF_FWS_TYPE_PKTTAG_LEN;
832         memcpy(&wlh[2], &pkttag, sizeof(pkttag));
833         wlh += BRCMF_FWS_TYPE_PKTTAG_LEN + 2;
834
835         if (entry->send_tim_signal) {
836                 entry->send_tim_signal = 0;
837                 wlh[0] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP;
838                 wlh[1] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN;
839                 wlh[2] = entry->mac_handle;
840                 wlh[3] = entry->traffic_pending_bmp;
841                 brcmf_dbg(TRACE, "adding TIM info: handle %d bmp 0x%X\n",
842                           entry->mac_handle, entry->traffic_pending_bmp);
843                 wlh += BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2;
844                 entry->traffic_lastreported_bmp = entry->traffic_pending_bmp;
845         }
846         if (fillers)
847                 memset(wlh, BRCMF_FWS_TYPE_FILLER, fillers);
848
849         brcmf_proto_hdrpush(fws->drvr, brcmf_skb_if_flags_get_field(skb, INDEX),
850                             data_offset >> 2, skb);
851         return 0;
852 }
853
854 static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws,
855                                  struct brcmf_fws_mac_descriptor *entry,
856                                  int fifo, bool send_immediately)
857 {
858         struct sk_buff *skb;
859         struct brcmf_bus *bus;
860         struct brcmf_skbuff_cb *skcb;
861         s32 err;
862         u32 len;
863
864         /* check delayedQ and suppressQ in one call using bitmap */
865         if (brcmu_pktq_mlen(&entry->psq, 3 << (fifo * 2)) == 0)
866                 entry->traffic_pending_bmp &= ~NBITVAL(fifo);
867         else
868                 entry->traffic_pending_bmp |= NBITVAL(fifo);
869
870         entry->send_tim_signal = false;
871         if (entry->traffic_lastreported_bmp != entry->traffic_pending_bmp)
872                 entry->send_tim_signal = true;
873         if (send_immediately && entry->send_tim_signal &&
874             entry->state == BRCMF_FWS_STATE_CLOSE) {
875                 /* create a dummy packet and sent that. The traffic          */
876                 /* bitmap info will automatically be attached to that packet */
877                 len = BRCMF_FWS_TYPE_PKTTAG_LEN + 2 +
878                       BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2 +
879                       4 + fws->drvr->hdrlen;
880                 skb = brcmu_pkt_buf_get_skb(len);
881                 if (skb == NULL)
882                         return false;
883                 skb_pull(skb, len);
884                 skcb = brcmf_skbcb(skb);
885                 skcb->mac = entry;
886                 skcb->state = BRCMF_FWS_SKBSTATE_TIM;
887                 bus = fws->drvr->bus_if;
888                 err = brcmf_fws_hdrpush(fws, skb);
889                 if (err == 0) {
890                         brcmf_fws_unlock(fws);
891                         err = brcmf_bus_txdata(bus, skb);
892                         brcmf_fws_lock(fws);
893                 }
894                 if (err)
895                         brcmu_pkt_buf_free_skb(skb);
896                 return true;
897         }
898         return false;
899 }
900
901 static void
902 brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq,
903                              u8 if_id)
904 {
905         struct brcmf_if *ifp = fws->drvr->iflist[!if_id ? 0 : if_id + 1];
906
907         if (WARN_ON(!ifp))
908                 return;
909
910         if ((ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) &&
911             pq->len <= BRCMF_FWS_FLOWCONTROL_LOWATER)
912                 brcmf_txflowblock_if(ifp,
913                                      BRCMF_NETIF_STOP_REASON_FWS_FC, false);
914         if (!(ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) &&
915             pq->len >= BRCMF_FWS_FLOWCONTROL_HIWATER) {
916                 fws->stats.fws_flow_block++;
917                 brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FWS_FC, true);
918         }
919         return;
920 }
921
922 static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi)
923 {
924         brcmf_dbg(CTL, "rssi %d\n", rssi);
925         return 0;
926 }
927
928 static
929 int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
930 {
931         struct brcmf_fws_mac_descriptor *entry, *existing;
932         u8 mac_handle;
933         u8 ifidx;
934         u8 *addr;
935
936         mac_handle = *data++;
937         ifidx = *data++;
938         addr = data;
939
940         entry = &fws->desc.nodes[mac_handle & 0x1F];
941         if (type == BRCMF_FWS_TYPE_MACDESC_DEL) {
942                 if (entry->occupied) {
943                         brcmf_dbg(TRACE, "deleting %s mac %pM\n",
944                                   entry->name, addr);
945                         brcmf_fws_lock(fws);
946                         brcmf_fws_macdesc_cleanup(fws, entry, -1);
947                         brcmf_fws_macdesc_deinit(entry);
948                         brcmf_fws_unlock(fws);
949                 } else
950                         fws->stats.mac_update_failed++;
951                 return 0;
952         }
953
954         existing = brcmf_fws_macdesc_lookup(fws, addr);
955         if (IS_ERR(existing)) {
956                 if (!entry->occupied) {
957                         brcmf_fws_lock(fws);
958                         entry->mac_handle = mac_handle;
959                         brcmf_fws_macdesc_init(entry, addr, ifidx);
960                         brcmf_fws_macdesc_set_name(fws, entry);
961                         brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
962                                         BRCMF_FWS_PSQ_LEN);
963                         brcmf_fws_unlock(fws);
964                         brcmf_dbg(TRACE, "add %s mac %pM\n", entry->name, addr);
965                 } else {
966                         fws->stats.mac_update_failed++;
967                 }
968         } else {
969                 if (entry != existing) {
970                         brcmf_dbg(TRACE, "copy mac %s\n", existing->name);
971                         brcmf_fws_lock(fws);
972                         memcpy(entry, existing,
973                                offsetof(struct brcmf_fws_mac_descriptor, psq));
974                         entry->mac_handle = mac_handle;
975                         brcmf_fws_macdesc_deinit(existing);
976                         brcmf_fws_macdesc_set_name(fws, entry);
977                         brcmf_fws_unlock(fws);
978                         brcmf_dbg(TRACE, "relocate %s mac %pM\n", entry->name,
979                                   addr);
980                 } else {
981                         brcmf_dbg(TRACE, "use existing\n");
982                         WARN_ON(entry->mac_handle != mac_handle);
983                         /* TODO: what should we do here: continue, reinit, .. */
984                 }
985         }
986         return 0;
987 }
988
989 static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
990                                             u8 type, u8 *data)
991 {
992         struct brcmf_fws_mac_descriptor *entry;
993         u8 mac_handle;
994         int ret;
995
996         mac_handle = data[0];
997         entry = &fws->desc.nodes[mac_handle & 0x1F];
998         if (!entry->occupied) {
999                 fws->stats.mac_ps_update_failed++;
1000                 return -ESRCH;
1001         }
1002         brcmf_fws_lock(fws);
1003         /* a state update should wipe old credits */
1004         entry->requested_credit = 0;
1005         entry->requested_packet = 0;
1006         if (type == BRCMF_FWS_TYPE_MAC_OPEN) {
1007                 entry->state = BRCMF_FWS_STATE_OPEN;
1008                 ret = BRCMF_FWS_RET_OK_SCHEDULE;
1009         } else {
1010                 entry->state = BRCMF_FWS_STATE_CLOSE;
1011                 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BK, false);
1012                 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BE, false);
1013                 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VI, false);
1014                 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VO, true);
1015                 ret = BRCMF_FWS_RET_OK_NOSCHEDULE;
1016         }
1017         brcmf_fws_unlock(fws);
1018         return ret;
1019 }
1020
1021 static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
1022                                               u8 type, u8 *data)
1023 {
1024         struct brcmf_fws_mac_descriptor *entry;
1025         u8 ifidx;
1026         int ret;
1027
1028         ifidx = data[0];
1029
1030         if (ifidx >= BRCMF_MAX_IFS) {
1031                 ret = -ERANGE;
1032                 goto fail;
1033         }
1034
1035         entry = &fws->desc.iface[ifidx];
1036         if (!entry->occupied) {
1037                 ret = -ESRCH;
1038                 goto fail;
1039         }
1040
1041         brcmf_dbg(TRACE, "%s (%d): %s\n", brcmf_fws_get_tlv_name(type), type,
1042                   entry->name);
1043         brcmf_fws_lock(fws);
1044         switch (type) {
1045         case BRCMF_FWS_TYPE_INTERFACE_OPEN:
1046                 entry->state = BRCMF_FWS_STATE_OPEN;
1047                 ret = BRCMF_FWS_RET_OK_SCHEDULE;
1048                 break;
1049         case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
1050                 entry->state = BRCMF_FWS_STATE_CLOSE;
1051                 ret = BRCMF_FWS_RET_OK_NOSCHEDULE;
1052                 break;
1053         default:
1054                 ret = -EINVAL;
1055                 brcmf_fws_unlock(fws);
1056                 goto fail;
1057         }
1058         brcmf_fws_unlock(fws);
1059         return ret;
1060
1061 fail:
1062         fws->stats.if_update_failed++;
1063         return ret;
1064 }
1065
1066 static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
1067                                       u8 *data)
1068 {
1069         struct brcmf_fws_mac_descriptor *entry;
1070
1071         entry = &fws->desc.nodes[data[1] & 0x1F];
1072         if (!entry->occupied) {
1073                 if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT)
1074                         fws->stats.credit_request_failed++;
1075                 else
1076                         fws->stats.packet_request_failed++;
1077                 return -ESRCH;
1078         }
1079
1080         brcmf_dbg(TRACE, "%s (%d): %s cnt %d bmp %d\n",
1081                   brcmf_fws_get_tlv_name(type), type, entry->name,
1082                   data[0], data[2]);
1083         brcmf_fws_lock(fws);
1084         if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT)
1085                 entry->requested_credit = data[0];
1086         else
1087                 entry->requested_packet = data[0];
1088
1089         entry->ac_bitmap = data[2];
1090         brcmf_fws_unlock(fws);
1091         return BRCMF_FWS_RET_OK_SCHEDULE;
1092 }
1093
1094 static void
1095 brcmf_fws_macdesc_use_req_credit(struct brcmf_fws_mac_descriptor *entry,
1096                                  struct sk_buff *skb)
1097 {
1098         if (entry->requested_credit > 0) {
1099                 entry->requested_credit--;
1100                 brcmf_skb_if_flags_set_field(skb, REQUESTED, 1);
1101                 brcmf_skb_if_flags_set_field(skb, REQ_CREDIT, 1);
1102                 if (entry->state != BRCMF_FWS_STATE_CLOSE)
1103                         brcmf_err("requested credit set while mac not closed!\n");
1104         } else if (entry->requested_packet > 0) {
1105                 entry->requested_packet--;
1106                 brcmf_skb_if_flags_set_field(skb, REQUESTED, 1);
1107                 brcmf_skb_if_flags_set_field(skb, REQ_CREDIT, 0);
1108                 if (entry->state != BRCMF_FWS_STATE_CLOSE)
1109                         brcmf_err("requested packet set while mac not closed!\n");
1110         } else {
1111                 brcmf_skb_if_flags_set_field(skb, REQUESTED, 0);
1112                 brcmf_skb_if_flags_set_field(skb, REQ_CREDIT, 0);
1113         }
1114 }
1115
1116 static void brcmf_fws_macdesc_return_req_credit(struct sk_buff *skb)
1117 {
1118         struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
1119
1120         if ((brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) &&
1121             (entry->state == BRCMF_FWS_STATE_CLOSE))
1122                 entry->requested_credit++;
1123 }
1124
1125 static void brcmf_fws_return_credits(struct brcmf_fws_info *fws,
1126                                      u8 fifo, u8 credits)
1127 {
1128         int lender_ac;
1129         int *borrowed;
1130         int *fifo_credit;
1131
1132         if (!credits)
1133                 return;
1134
1135         fws->fifo_credit_map |= 1 << fifo;
1136
1137         if ((fifo == BRCMF_FWS_FIFO_AC_BE) &&
1138             (fws->credits_borrowed[0])) {
1139                 for (lender_ac = BRCMF_FWS_FIFO_AC_VO; lender_ac >= 0;
1140                      lender_ac--) {
1141                         borrowed = &fws->credits_borrowed[lender_ac];
1142                         if (*borrowed) {
1143                                 fws->fifo_credit_map |= (1 << lender_ac);
1144                                 fifo_credit = &fws->fifo_credit[lender_ac];
1145                                 if (*borrowed >= credits) {
1146                                         *borrowed -= credits;
1147                                         *fifo_credit += credits;
1148                                         return;
1149                                 } else {
1150                                         credits -= *borrowed;
1151                                         *fifo_credit += *borrowed;
1152                                         *borrowed = 0;
1153                                 }
1154                         }
1155                 }
1156         }
1157
1158         fws->fifo_credit[fifo] += credits;
1159 }
1160
1161 static void brcmf_fws_schedule_deq(struct brcmf_fws_info *fws)
1162 {
1163         /* only schedule dequeue when there are credits for delayed traffic */
1164         if ((fws->fifo_credit_map & fws->fifo_delay_map) ||
1165             (!brcmf_fws_fc_active(fws) && fws->fifo_delay_map))
1166                 queue_work(fws->fws_wq, &fws->fws_dequeue_work);
1167 }
1168
1169 static int brcmf_fws_enq(struct brcmf_fws_info *fws,
1170                          enum brcmf_fws_skb_state state, int fifo,
1171                          struct sk_buff *p)
1172 {
1173         int prec = 2 * fifo;
1174         u32 *qfull_stat = &fws->stats.delayq_full_error;
1175
1176         struct brcmf_fws_mac_descriptor *entry;
1177
1178         entry = brcmf_skbcb(p)->mac;
1179         if (entry == NULL) {
1180                 brcmf_err("no mac descriptor found for skb %p\n", p);
1181                 return -ENOENT;
1182         }
1183
1184         brcmf_dbg(DATA, "enter: fifo %d skb %p\n", fifo, p);
1185         if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) {
1186                 prec += 1;
1187                 qfull_stat = &fws->stats.supprq_full_error;
1188         }
1189
1190         if (brcmu_pktq_penq(&entry->psq, prec, p) == NULL) {
1191                 *qfull_stat += 1;
1192                 return -ENFILE;
1193         }
1194
1195         /* increment total enqueued packet count */
1196         fws->fifo_delay_map |= 1 << fifo;
1197         fws->fifo_enqpkt[fifo]++;
1198
1199         /* update the sk_buff state */
1200         brcmf_skbcb(p)->state = state;
1201
1202         /*
1203          * A packet has been pushed so update traffic
1204          * availability bitmap, if applicable
1205          */
1206         brcmf_fws_tim_update(fws, entry, fifo, true);
1207         brcmf_fws_flow_control_check(fws, &entry->psq,
1208                                      brcmf_skb_if_flags_get_field(p, INDEX));
1209         return 0;
1210 }
1211
1212 static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo)
1213 {
1214         struct brcmf_fws_mac_descriptor *table;
1215         struct brcmf_fws_mac_descriptor *entry;
1216         struct sk_buff *p;
1217         int num_nodes;
1218         int node_pos;
1219         int prec_out;
1220         int pmsk;
1221         int i;
1222
1223         table = (struct brcmf_fws_mac_descriptor *)&fws->desc;
1224         num_nodes = sizeof(fws->desc) / sizeof(struct brcmf_fws_mac_descriptor);
1225         node_pos = fws->deq_node_pos[fifo];
1226
1227         for (i = 0; i < num_nodes; i++) {
1228                 entry = &table[(node_pos + i) % num_nodes];
1229                 if (!entry->occupied ||
1230                     brcmf_fws_macdesc_closed(fws, entry, fifo))
1231                         continue;
1232
1233                 if (entry->suppressed)
1234                         pmsk = 2;
1235                 else
1236                         pmsk = 3;
1237                 p = brcmu_pktq_mdeq(&entry->psq, pmsk << (fifo * 2), &prec_out);
1238                 if (p == NULL) {
1239                         if (entry->suppressed) {
1240                                 if (entry->suppr_transit_count)
1241                                         continue;
1242                                 entry->suppressed = false;
1243                                 p = brcmu_pktq_mdeq(&entry->psq,
1244                                                     1 << (fifo * 2), &prec_out);
1245                         }
1246                 }
1247                 if  (p == NULL)
1248                         continue;
1249
1250                 brcmf_fws_macdesc_use_req_credit(entry, p);
1251
1252                 /* move dequeue position to ensure fair round-robin */
1253                 fws->deq_node_pos[fifo] = (node_pos + i + 1) % num_nodes;
1254                 brcmf_fws_flow_control_check(fws, &entry->psq,
1255                                              brcmf_skb_if_flags_get_field(p,
1256                                                                           INDEX)
1257                                              );
1258                 /*
1259                  * A packet has been picked up, update traffic
1260                  * availability bitmap, if applicable
1261                  */
1262                 brcmf_fws_tim_update(fws, entry, fifo, false);
1263
1264                 /*
1265                  * decrement total enqueued fifo packets and
1266                  * clear delay bitmap if done.
1267                  */
1268                 fws->fifo_enqpkt[fifo]--;
1269                 if (fws->fifo_enqpkt[fifo] == 0)
1270                         fws->fifo_delay_map &= ~(1 << fifo);
1271                 goto done;
1272         }
1273         p = NULL;
1274 done:
1275         brcmf_dbg(DATA, "exit: fifo %d skb %p\n", fifo, p);
1276         return p;
1277 }
1278
1279 static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
1280                                          struct sk_buff *skb, u32 genbit)
1281 {
1282         struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
1283         u32 hslot;
1284         int ret;
1285         u8 ifidx;
1286
1287         hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
1288
1289         /* this packet was suppressed */
1290         if (!entry->suppressed) {
1291                 entry->suppressed = true;
1292                 entry->suppr_transit_count = entry->transit_count;
1293                 brcmf_dbg(DATA, "suppress %s: transit %d\n",
1294                           entry->name, entry->transit_count);
1295         }
1296
1297         entry->generation = genbit;
1298
1299         ret = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
1300         if (ret == 0)
1301                 ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo,
1302                                     skb);
1303         if (ret != 0) {
1304                 /* suppress q is full or hdrpull failed, drop this packet */
1305                 brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
1306                                         true);
1307         } else {
1308                 /*
1309                  * Mark suppressed to avoid a double free during
1310                  * wlfc cleanup
1311                  */
1312                 brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot);
1313         }
1314
1315         return ret;
1316 }
1317
1318 static int
1319 brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
1320                            u32 genbit)
1321 {
1322         u32 fifo;
1323         int ret;
1324         bool remove_from_hanger = true;
1325         struct sk_buff *skb;
1326         struct brcmf_skbuff_cb *skcb;
1327         struct brcmf_fws_mac_descriptor *entry = NULL;
1328
1329         brcmf_dbg(DATA, "flags %d\n", flags);
1330
1331         if (flags == BRCMF_FWS_TXSTATUS_DISCARD)
1332                 fws->stats.txs_discard++;
1333         else if (flags == BRCMF_FWS_TXSTATUS_CORE_SUPPRESS) {
1334                 fws->stats.txs_supp_core++;
1335                 remove_from_hanger = false;
1336         } else if (flags == BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS) {
1337                 fws->stats.txs_supp_ps++;
1338                 remove_from_hanger = false;
1339         } else if (flags == BRCMF_FWS_TXSTATUS_FW_TOSSED)
1340                 fws->stats.txs_tossed++;
1341         else if (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED)
1342                 fws->stats.txs_host_tossed++;
1343         else
1344                 brcmf_err("unexpected txstatus\n");
1345
1346         ret = brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
1347                                       remove_from_hanger);
1348         if (ret != 0) {
1349                 brcmf_err("no packet in hanger slot: hslot=%d\n", hslot);
1350                 return ret;
1351         }
1352
1353         skcb = brcmf_skbcb(skb);
1354         entry = skcb->mac;
1355         if (WARN_ON(!entry)) {
1356                 brcmu_pkt_buf_free_skb(skb);
1357                 return -EINVAL;
1358         }
1359         entry->transit_count--;
1360         if (entry->suppressed && entry->suppr_transit_count)
1361                 entry->suppr_transit_count--;
1362
1363         brcmf_dbg(DATA, "%s flags %X htod %X\n", entry->name, skcb->if_flags,
1364                   skcb->htod);
1365
1366         /* pick up the implicit credit from this packet */
1367         fifo = brcmf_skb_htod_tag_get_field(skb, FIFO);
1368         if ((fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT) ||
1369             (brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) ||
1370             (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED)) {
1371                 brcmf_fws_return_credits(fws, fifo, 1);
1372                 brcmf_fws_schedule_deq(fws);
1373         }
1374         brcmf_fws_macdesc_return_req_credit(skb);
1375
1376         if (!remove_from_hanger)
1377                 ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit);
1378
1379         if (remove_from_hanger || ret)
1380                 brcmf_txfinalize(fws->drvr, skb, true);
1381
1382         return 0;
1383 }
1384
1385 static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
1386                                              u8 *data)
1387 {
1388         int i;
1389
1390         if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) {
1391                 brcmf_dbg(INFO, "ignored\n");
1392                 return BRCMF_FWS_RET_OK_NOSCHEDULE;
1393         }
1394
1395         brcmf_dbg(DATA, "enter: data %pM\n", data);
1396         brcmf_fws_lock(fws);
1397         for (i = 0; i < BRCMF_FWS_FIFO_COUNT; i++)
1398                 brcmf_fws_return_credits(fws, i, data[i]);
1399
1400         brcmf_dbg(DATA, "map: credit %x delay %x\n", fws->fifo_credit_map,
1401                   fws->fifo_delay_map);
1402         brcmf_fws_unlock(fws);
1403         return BRCMF_FWS_RET_OK_SCHEDULE;
1404 }
1405
1406 static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
1407 {
1408         __le32 status_le;
1409         u32 status;
1410         u32 hslot;
1411         u32 genbit;
1412         u8 flags;
1413
1414         fws->stats.txs_indicate++;
1415         memcpy(&status_le, data, sizeof(status_le));
1416         status = le32_to_cpu(status_le);
1417         flags = brcmf_txstatus_get_field(status, FLAGS);
1418         hslot = brcmf_txstatus_get_field(status, HSLOT);
1419         genbit = brcmf_txstatus_get_field(status, GENERATION);
1420
1421         brcmf_fws_lock(fws);
1422         brcmf_fws_txs_process(fws, flags, hslot, genbit);
1423         brcmf_fws_unlock(fws);
1424         return BRCMF_FWS_RET_OK_NOSCHEDULE;
1425 }
1426
1427 static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data)
1428 {
1429         __le32 timestamp;
1430
1431         memcpy(&timestamp, &data[2], sizeof(timestamp));
1432         brcmf_dbg(CTL, "received: seq %d, timestamp %d\n", data[1],
1433                   le32_to_cpu(timestamp));
1434         return 0;
1435 }
1436
1437 static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp,
1438                                        const struct brcmf_event_msg *e,
1439                                        void *data)
1440 {
1441         struct brcmf_fws_info *fws = ifp->drvr->fws;
1442         int i;
1443         u8 *credits = data;
1444
1445         if (e->datalen < BRCMF_FWS_FIFO_COUNT) {
1446                 brcmf_err("event payload too small (%d)\n", e->datalen);
1447                 return -EINVAL;
1448         }
1449         if (fws->creditmap_received)
1450                 return 0;
1451
1452         fws->creditmap_received = true;
1453
1454         brcmf_dbg(TRACE, "enter: credits %pM\n", credits);
1455         brcmf_fws_lock(fws);
1456         for (i = 0; i < ARRAY_SIZE(fws->fifo_credit); i++) {
1457                 if (*credits)
1458                         fws->fifo_credit_map |= 1 << i;
1459                 else
1460                         fws->fifo_credit_map &= ~(1 << i);
1461                 fws->fifo_credit[i] = *credits++;
1462         }
1463         brcmf_fws_schedule_deq(fws);
1464         brcmf_fws_unlock(fws);
1465         return 0;
1466 }
1467
1468 static int brcmf_fws_notify_bcmc_credit_support(struct brcmf_if *ifp,
1469                                                 const struct brcmf_event_msg *e,
1470                                                 void *data)
1471 {
1472         struct brcmf_fws_info *fws = ifp->drvr->fws;
1473
1474         brcmf_fws_lock(fws);
1475         if (fws)
1476                 fws->bcmc_credit_check = true;
1477         brcmf_fws_unlock(fws);
1478         return 0;
1479 }
1480
1481 int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
1482                       struct sk_buff *skb)
1483 {
1484         struct brcmf_skb_reorder_data *rd;
1485         struct brcmf_fws_info *fws = drvr->fws;
1486         u8 *signal_data;
1487         s16 data_len;
1488         u8 type;
1489         u8 len;
1490         u8 *data;
1491         s32 status;
1492         s32 err;
1493
1494         brcmf_dbg(HDRS, "enter: ifidx %d, skblen %u, sig %d\n",
1495                   ifidx, skb->len, signal_len);
1496
1497         WARN_ON(signal_len > skb->len);
1498
1499         if (!signal_len)
1500                 return 0;
1501         /* if flow control disabled, skip to packet data and leave */
1502         if (!fws->fw_signals) {
1503                 skb_pull(skb, signal_len);
1504                 return 0;
1505         }
1506
1507         fws->stats.header_pulls++;
1508         data_len = signal_len;
1509         signal_data = skb->data;
1510
1511         status = BRCMF_FWS_RET_OK_NOSCHEDULE;
1512         while (data_len > 0) {
1513                 /* extract tlv info */
1514                 type = signal_data[0];
1515
1516                 /* FILLER type is actually not a TLV, but
1517                  * a single byte that can be skipped.
1518                  */
1519                 if (type == BRCMF_FWS_TYPE_FILLER) {
1520                         signal_data += 1;
1521                         data_len -= 1;
1522                         continue;
1523                 }
1524                 len = signal_data[1];
1525                 data = signal_data + 2;
1526
1527                 brcmf_dbg(HDRS, "tlv type=%s (%d), len=%d (%d)\n",
1528                           brcmf_fws_get_tlv_name(type), type, len,
1529                           brcmf_fws_get_tlv_len(fws, type));
1530
1531                 /* abort parsing when length invalid */
1532                 if (data_len < len + 2)
1533                         break;
1534
1535                 if (len < brcmf_fws_get_tlv_len(fws, type))
1536                         break;
1537
1538                 err = BRCMF_FWS_RET_OK_NOSCHEDULE;
1539                 switch (type) {
1540                 case BRCMF_FWS_TYPE_COMP_TXSTATUS:
1541                         break;
1542                 case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS:
1543                         rd = (struct brcmf_skb_reorder_data *)skb->cb;
1544                         rd->reorder = data;
1545                         break;
1546                 case BRCMF_FWS_TYPE_MACDESC_ADD:
1547                 case BRCMF_FWS_TYPE_MACDESC_DEL:
1548                         brcmf_fws_macdesc_indicate(fws, type, data);
1549                         break;
1550                 case BRCMF_FWS_TYPE_MAC_OPEN:
1551                 case BRCMF_FWS_TYPE_MAC_CLOSE:
1552                         err = brcmf_fws_macdesc_state_indicate(fws, type, data);
1553                         break;
1554                 case BRCMF_FWS_TYPE_INTERFACE_OPEN:
1555                 case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
1556                         err = brcmf_fws_interface_state_indicate(fws, type,
1557                                                                  data);
1558                         break;
1559                 case BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT:
1560                 case BRCMF_FWS_TYPE_MAC_REQUEST_PACKET:
1561                         err = brcmf_fws_request_indicate(fws, type, data);
1562                         break;
1563                 case BRCMF_FWS_TYPE_TXSTATUS:
1564                         brcmf_fws_txstatus_indicate(fws, data);
1565                         break;
1566                 case BRCMF_FWS_TYPE_FIFO_CREDITBACK:
1567                         err = brcmf_fws_fifocreditback_indicate(fws, data);
1568                         break;
1569                 case BRCMF_FWS_TYPE_RSSI:
1570                         brcmf_fws_rssi_indicate(fws, *data);
1571                         break;
1572                 case BRCMF_FWS_TYPE_TRANS_ID:
1573                         brcmf_fws_dbg_seqnum_check(fws, data);
1574                         break;
1575                 case BRCMF_FWS_TYPE_PKTTAG:
1576                 case BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP:
1577                 default:
1578                         fws->stats.tlv_invalid_type++;
1579                         break;
1580                 }
1581                 if (err == BRCMF_FWS_RET_OK_SCHEDULE)
1582                         status = BRCMF_FWS_RET_OK_SCHEDULE;
1583                 signal_data += len + 2;
1584                 data_len -= len + 2;
1585         }
1586
1587         if (data_len != 0)
1588                 fws->stats.tlv_parse_failed++;
1589
1590         if (status == BRCMF_FWS_RET_OK_SCHEDULE)
1591                 brcmf_fws_schedule_deq(fws);
1592
1593         /* signalling processing result does
1594          * not affect the actual ethernet packet.
1595          */
1596         skb_pull(skb, signal_len);
1597
1598         /* this may be a signal-only packet
1599          */
1600         if (skb->len == 0)
1601                 fws->stats.header_only_pkt++;
1602
1603         return 0;
1604 }
1605
1606 static void brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
1607                                    struct sk_buff *p)
1608 {
1609         struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
1610         struct brcmf_fws_mac_descriptor *entry = skcb->mac;
1611         u8 flags;
1612
1613         brcmf_skb_if_flags_set_field(p, TRANSMIT, 1);
1614         brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation);
1615         flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST;
1616         if (brcmf_skb_if_flags_get_field(p, REQUESTED)) {
1617                 /*
1618                  * Indicate that this packet is being sent in response to an
1619                  * explicit request from the firmware side.
1620                  */
1621                 flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED;
1622         }
1623         brcmf_skb_htod_tag_set_field(p, FLAGS, flags);
1624         brcmf_fws_hdrpush(fws, p);
1625 }
1626
1627 static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
1628                                    struct sk_buff *skb, int fifo)
1629 {
1630         struct brcmf_fws_mac_descriptor *entry;
1631         struct sk_buff *pktout;
1632         int qidx, hslot;
1633         int rc = 0;
1634
1635         entry = brcmf_skbcb(skb)->mac;
1636         if (entry->occupied) {
1637                 qidx = 2 * fifo;
1638                 if (brcmf_skbcb(skb)->state == BRCMF_FWS_SKBSTATE_SUPPRESSED)
1639                         qidx++;
1640
1641                 pktout = brcmu_pktq_penq_head(&entry->psq, qidx, skb);
1642                 if (pktout == NULL) {
1643                         brcmf_err("%s queue %d full\n", entry->name, qidx);
1644                         rc = -ENOSPC;
1645                 }
1646         } else {
1647                 brcmf_err("%s entry removed\n", entry->name);
1648                 rc = -ENOENT;
1649         }
1650
1651         if (rc) {
1652                 fws->stats.rollback_failed++;
1653                 hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
1654                 brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED,
1655                                       hslot, 0);
1656         } else {
1657                 fws->stats.rollback_success++;
1658                 brcmf_fws_return_credits(fws, fifo, 1);
1659                 brcmf_fws_macdesc_return_req_credit(skb);
1660         }
1661 }
1662
1663 static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws)
1664 {
1665         int lender_ac;
1666
1667         if (time_after(fws->borrow_defer_timestamp, jiffies)) {
1668                 fws->fifo_credit_map &= ~(1 << BRCMF_FWS_FIFO_AC_BE);
1669                 return -ENAVAIL;
1670         }
1671
1672         for (lender_ac = 0; lender_ac <= BRCMF_FWS_FIFO_AC_VO; lender_ac++) {
1673                 if (fws->fifo_credit[lender_ac]) {
1674                         fws->credits_borrowed[lender_ac]++;
1675                         fws->fifo_credit[lender_ac]--;
1676                         if (fws->fifo_credit[lender_ac] == 0)
1677                                 fws->fifo_credit_map &= ~(1 << lender_ac);
1678                         fws->fifo_credit_map |= (1 << BRCMF_FWS_FIFO_AC_BE);
1679                         brcmf_dbg(DATA, "borrow credit from: %d\n", lender_ac);
1680                         return 0;
1681                 }
1682         }
1683         fws->fifo_credit_map &= ~(1 << BRCMF_FWS_FIFO_AC_BE);
1684         return -ENAVAIL;
1685 }
1686
1687 static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
1688                                 struct sk_buff *skb)
1689 {
1690         struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
1691         struct brcmf_fws_mac_descriptor *entry;
1692         struct brcmf_bus *bus = fws->drvr->bus_if;
1693         int rc;
1694         u8 ifidx;
1695
1696         entry = skcb->mac;
1697         if (IS_ERR(entry))
1698                 return PTR_ERR(entry);
1699
1700         brcmf_fws_precommit_skb(fws, fifo, skb);
1701         entry->transit_count++;
1702         if (entry->suppressed)
1703                 entry->suppr_transit_count++;
1704         brcmf_fws_unlock(fws);
1705         rc = brcmf_bus_txdata(bus, skb);
1706         brcmf_fws_lock(fws);
1707         brcmf_dbg(DATA, "%s flags %X htod %X bus_tx %d\n", entry->name,
1708                   skcb->if_flags, skcb->htod, rc);
1709         if (rc < 0) {
1710                 entry->transit_count--;
1711                 if (entry->suppressed)
1712                         entry->suppr_transit_count--;
1713                 brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
1714                 goto rollback;
1715         }
1716
1717         fws->stats.pkt2bus++;
1718         fws->stats.send_pkts[fifo]++;
1719         if (brcmf_skb_if_flags_get_field(skb, REQUESTED))
1720                 fws->stats.requested_sent[fifo]++;
1721
1722         return rc;
1723
1724 rollback:
1725         brcmf_fws_rollback_toq(fws, skb, fifo);
1726         return rc;
1727 }
1728
1729 static int brcmf_fws_assign_htod(struct brcmf_fws_info *fws, struct sk_buff *p,
1730                                   int fifo)
1731 {
1732         struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
1733         int rc, hslot;
1734
1735         hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger);
1736         brcmf_skb_htod_tag_set_field(p, HSLOT, hslot);
1737         brcmf_skb_htod_tag_set_field(p, FREERUN, skcb->mac->seq[fifo]);
1738         brcmf_skb_htod_tag_set_field(p, FIFO, fifo);
1739         rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot);
1740         if (!rc)
1741                 skcb->mac->seq[fifo]++;
1742         else
1743                 fws->stats.generic_error++;
1744         return rc;
1745 }
1746
1747 int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
1748 {
1749         struct brcmf_pub *drvr = ifp->drvr;
1750         struct brcmf_fws_info *fws = drvr->fws;
1751         struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
1752         struct ethhdr *eh = (struct ethhdr *)(skb->data);
1753         int fifo = BRCMF_FWS_FIFO_BCMC;
1754         bool multicast = is_multicast_ether_addr(eh->h_dest);
1755         bool pae = eh->h_proto == htons(ETH_P_PAE);
1756
1757         brcmf_dbg(DATA, "tx proto=0x%X\n", ntohs(eh->h_proto));
1758         /* determine the priority */
1759         if (!skb->priority)
1760                 skb->priority = cfg80211_classify8021d(skb);
1761
1762         drvr->tx_multicast += !!multicast;
1763         if (pae)
1764                 atomic_inc(&ifp->pend_8021x_cnt);
1765
1766         /* set control buffer information */
1767         skcb->if_flags = 0;
1768         skcb->state = BRCMF_FWS_SKBSTATE_NEW;
1769         brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx);
1770         if (!multicast)
1771                 fifo = brcmf_fws_prio2fifo[skb->priority];
1772
1773         brcmf_fws_lock(fws);
1774         if (fifo != BRCMF_FWS_FIFO_AC_BE && fifo < BRCMF_FWS_FIFO_BCMC)
1775                 fws->borrow_defer_timestamp = jiffies +
1776                                               BRCMF_FWS_BORROW_DEFER_PERIOD;
1777
1778         skcb->mac = brcmf_fws_macdesc_find(fws, ifp, eh->h_dest);
1779         brcmf_dbg(DATA, "%s mac %pM multi %d fifo %d\n", skcb->mac->name,
1780                   eh->h_dest, multicast, fifo);
1781         if (!brcmf_fws_assign_htod(fws, skb, fifo)) {
1782                 brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
1783                 brcmf_fws_schedule_deq(fws);
1784         } else {
1785                 brcmf_err("drop skb: no hanger slot\n");
1786                 if (pae) {
1787                         atomic_dec(&ifp->pend_8021x_cnt);
1788                         if (waitqueue_active(&ifp->pend_8021x_wait))
1789                                 wake_up(&ifp->pend_8021x_wait);
1790                 }
1791                 brcmu_pkt_buf_free_skb(skb);
1792         }
1793         brcmf_fws_unlock(fws);
1794         return 0;
1795 }
1796
1797 void brcmf_fws_reset_interface(struct brcmf_if *ifp)
1798 {
1799         struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc;
1800
1801         brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx);
1802         if (!entry)
1803                 return;
1804
1805         brcmf_fws_macdesc_init(entry, ifp->mac_addr, ifp->ifidx);
1806 }
1807
1808 void brcmf_fws_add_interface(struct brcmf_if *ifp)
1809 {
1810         struct brcmf_fws_info *fws = ifp->drvr->fws;
1811         struct brcmf_fws_mac_descriptor *entry;
1812
1813         if (!ifp->ndev)
1814                 return;
1815
1816         entry = &fws->desc.iface[ifp->ifidx];
1817         ifp->fws_desc = entry;
1818         brcmf_fws_macdesc_init(entry, ifp->mac_addr, ifp->ifidx);
1819         brcmf_fws_macdesc_set_name(fws, entry);
1820         brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
1821                         BRCMF_FWS_PSQ_LEN);
1822         brcmf_dbg(TRACE, "added %s\n", entry->name);
1823 }
1824
1825 void brcmf_fws_del_interface(struct brcmf_if *ifp)
1826 {
1827         struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc;
1828
1829         if (!entry)
1830                 return;
1831
1832         brcmf_fws_lock(ifp->drvr->fws);
1833         ifp->fws_desc = NULL;
1834         brcmf_dbg(TRACE, "deleting %s\n", entry->name);
1835         brcmf_fws_macdesc_deinit(entry);
1836         brcmf_fws_cleanup(ifp->drvr->fws, ifp->ifidx);
1837         brcmf_fws_unlock(ifp->drvr->fws);
1838 }
1839
1840 static void brcmf_fws_dequeue_worker(struct work_struct *worker)
1841 {
1842         struct brcmf_fws_info *fws;
1843         struct brcmf_pub *drvr;
1844         struct sk_buff *skb;
1845         int fifo;
1846         u32 hslot;
1847         u32 ifidx;
1848         int ret;
1849
1850         fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work);
1851         drvr = fws->drvr;
1852
1853         brcmf_fws_lock(fws);
1854         for (fifo = BRCMF_FWS_FIFO_BCMC; fifo >= 0 && !fws->bus_flow_blocked;
1855              fifo--) {
1856                 if (!brcmf_fws_fc_active(fws)) {
1857                         while ((skb = brcmf_fws_deq(fws, fifo)) != NULL) {
1858                                 hslot = brcmf_skb_htod_tag_get_field(skb,
1859                                                                      HSLOT);
1860                                 brcmf_fws_hanger_poppkt(&fws->hanger, hslot,
1861                                                         &skb, true);
1862                                 ifidx = brcmf_skb_if_flags_get_field(skb,
1863                                                                      INDEX);
1864                                 brcmf_proto_hdrpush(drvr, ifidx, 0, skb);
1865                                 /* Use bus module to send data frame */
1866                                 brcmf_fws_unlock(fws);
1867                                 ret = brcmf_bus_txdata(drvr->bus_if, skb);
1868                                 brcmf_fws_lock(fws);
1869                                 if (ret < 0)
1870                                         brcmf_txfinalize(drvr, skb, false);
1871                                 if (fws->bus_flow_blocked)
1872                                         break;
1873                         }
1874                         continue;
1875                 }
1876                 while ((fws->fifo_credit[fifo]) || ((!fws->bcmc_credit_check) &&
1877                        (fifo == BRCMF_FWS_FIFO_BCMC))) {
1878                         skb = brcmf_fws_deq(fws, fifo);
1879                         if (!skb)
1880                                 break;
1881                         fws->fifo_credit[fifo]--;
1882                         if (brcmf_fws_commit_skb(fws, fifo, skb))
1883                                 break;
1884                         if (fws->bus_flow_blocked)
1885                                 break;
1886                 }
1887                 if ((fifo == BRCMF_FWS_FIFO_AC_BE) &&
1888                     (fws->fifo_credit[fifo] == 0) &&
1889                     (!fws->bus_flow_blocked)) {
1890                         while (brcmf_fws_borrow_credit(fws) == 0) {
1891                                 skb = brcmf_fws_deq(fws, fifo);
1892                                 if (!skb) {
1893                                         brcmf_fws_return_credits(fws, fifo, 1);
1894                                         break;
1895                                 }
1896                                 if (brcmf_fws_commit_skb(fws, fifo, skb))
1897                                         break;
1898                                 if (fws->bus_flow_blocked)
1899                                         break;
1900                         }
1901                 }
1902         }
1903         brcmf_fws_unlock(fws);
1904 }
1905
1906 int brcmf_fws_init(struct brcmf_pub *drvr)
1907 {
1908         struct brcmf_fws_info *fws;
1909         u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS;
1910         int rc;
1911
1912         drvr->fws = kzalloc(sizeof(*(drvr->fws)), GFP_KERNEL);
1913         if (!drvr->fws) {
1914                 rc = -ENOMEM;
1915                 goto fail;
1916         }
1917
1918         fws = drvr->fws;
1919
1920         spin_lock_init(&fws->spinlock);
1921
1922         /* set linkage back */
1923         fws->drvr = drvr;
1924         fws->fcmode = fcmode;
1925
1926         fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq");
1927         if (fws->fws_wq == NULL) {
1928                 brcmf_err("workqueue creation failed\n");
1929                 rc = -EBADF;
1930                 goto fail;
1931         }
1932         INIT_WORK(&fws->fws_dequeue_work, brcmf_fws_dequeue_worker);
1933
1934         /* enable firmware signalling if fcmode active */
1935         if (fws->fcmode != BRCMF_FWS_FCMODE_NONE)
1936                 tlv |= BRCMF_FWS_FLAGS_XONXOFF_SIGNALS |
1937                        BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS |
1938                        BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE |
1939                        BRCMF_FWS_FLAGS_HOST_RXREORDER_ACTIVE;
1940
1941         rc = brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP,
1942                                  brcmf_fws_notify_credit_map);
1943         if (rc < 0) {
1944                 brcmf_err("register credit map handler failed\n");
1945                 goto fail;
1946         }
1947         rc = brcmf_fweh_register(drvr, BRCMF_E_BCMC_CREDIT_SUPPORT,
1948                                  brcmf_fws_notify_bcmc_credit_support);
1949         if (rc < 0) {
1950                 brcmf_err("register bcmc credit handler failed\n");
1951                 brcmf_fweh_unregister(drvr, BRCMF_E_FIFO_CREDIT_MAP);
1952                 goto fail;
1953         }
1954
1955         /* Setting the iovar may fail if feature is unsupported
1956          * so leave the rc as is so driver initialization can
1957          * continue. Set mode back to none indicating not enabled.
1958          */
1959         fws->fw_signals = true;
1960         if (brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv)) {
1961                 brcmf_err("failed to set bdcv2 tlv signaling\n");
1962                 fws->fcmode = BRCMF_FWS_FCMODE_NONE;
1963                 fws->fw_signals = false;
1964         }
1965
1966         if (brcmf_fil_iovar_int_set(drvr->iflist[0], "ampdu_hostreorder", 1))
1967                 brcmf_dbg(INFO, "enabling AMPDU host-reorder failed\n");
1968
1969         brcmf_fws_hanger_init(&fws->hanger);
1970         brcmf_fws_macdesc_init(&fws->desc.other, NULL, 0);
1971         brcmf_fws_macdesc_set_name(fws, &fws->desc.other);
1972         brcmu_pktq_init(&fws->desc.other.psq, BRCMF_FWS_PSQ_PREC_COUNT,
1973                         BRCMF_FWS_PSQ_LEN);
1974
1975         /* create debugfs file for statistics */
1976         brcmf_debugfs_create_fws_stats(drvr, &fws->stats);
1977
1978         brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n",
1979                   fws->fw_signals ? "enabled" : "disabled", tlv);
1980         return 0;
1981
1982 fail:
1983         brcmf_fws_deinit(drvr);
1984         return rc;
1985 }
1986
1987 void brcmf_fws_deinit(struct brcmf_pub *drvr)
1988 {
1989         struct brcmf_fws_info *fws = drvr->fws;
1990
1991         if (!fws)
1992                 return;
1993
1994         if (drvr->fws->fws_wq)
1995                 destroy_workqueue(drvr->fws->fws_wq);
1996
1997         /* cleanup */
1998         brcmf_fws_lock(fws);
1999         brcmf_fws_cleanup(fws, -1);
2000         drvr->fws = NULL;
2001         brcmf_fws_unlock(fws);
2002
2003         /* free top structure */
2004         kfree(fws);
2005 }
2006
2007 bool brcmf_fws_fc_active(struct brcmf_fws_info *fws)
2008 {
2009         if (!fws->creditmap_received)
2010                 return false;
2011
2012         return fws->fcmode != BRCMF_FWS_FCMODE_NONE;
2013 }
2014
2015 void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb)
2016 {
2017         u32 hslot;
2018
2019         if (brcmf_skbcb(skb)->state == BRCMF_FWS_SKBSTATE_TIM) {
2020                 brcmu_pkt_buf_free_skb(skb);
2021                 return;
2022         }
2023         brcmf_fws_lock(fws);
2024         hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
2025         brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0);
2026         brcmf_fws_unlock(fws);
2027 }
2028
2029 void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked)
2030 {
2031         struct brcmf_fws_info *fws = drvr->fws;
2032
2033         fws->bus_flow_blocked = flow_blocked;
2034         if (!flow_blocked)
2035                 brcmf_fws_schedule_deq(fws);
2036         else
2037                 fws->stats.bus_flow_block++;
2038 }