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