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