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