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