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