1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright (C) 1999-2019, Broadcom. 4 * 5 * Unless you and Broadcom execute a separate written software license 6 * agreement governing use of this software, this software is licensed to you 7 * under the terms of the GNU General Public License version 2 (the "GPL"), 8 * available at http://www.broadcom.com/licenses/GPLv2.php, with the 9 * following added to such license: 10 * 11 * As a special exception, the copyright holders of this software give you 12 * permission to link this software with independent modules, and to copy and 13 * distribute the resulting executable under terms of your choice, provided that 14 * you also meet, for each linked independent module, the terms and conditions of 15 * the license of that module. An independent module is a module which is not 16 * derived from this software. The special exception does not apply to any 17 * modifications of the software. 18 * 19 * Notwithstanding the above, under no circumstances may you combine this 20 * software in any way with any other Broadcom software provided under a license 21 * other than the GPL, without Broadcom's express prior written consent. 22 * 23 * 24 * <<Broadcom-WL-IPTag/Open:>> 25 * 26 * $Id: dhd_wlfc.h 690477 2017-03-16 10:17:17Z $ 27 * 28 */ 29 #ifndef __wlfc_host_driver_definitions_h__ 30 #define __wlfc_host_driver_definitions_h__ 31 32 #include <bcmsdbus.h> 33 #include <bcmsdpcm.h> 34 #include <sbsdpcmdev.h> 35 #include <hnd_cons.h> 36 /* #define OOO_DEBUG */ 37 38 #define KERNEL_THREAD_RETURN_TYPE int 39 40 typedef struct dhd_console { 41 uint count; /* Poll interval msec counter */ 42 uint log_addr; /* Log struct address (fixed) */ 43 hnd_log_t log; /* Log struct (host copy) */ 44 uint bufsize; /* Size of log buffer */ 45 uint8 *buf; /* Log buffer (host copy) */ 46 uint last; /* Last buffer read index */ 47 } dhd_console_t; 48 49 typedef int (*f_commitpkt_t)(struct dhd_bus* ctx, void* p); 50 typedef bool (*f_processpkt_t)(void* p, void* arg); 51 52 #define WLFC_UNSUPPORTED -9999 53 54 #define WLFC_NO_TRAFFIC -1 55 #define WLFC_MULTI_TRAFFIC 0 56 57 #define BUS_RETRIES 1 /* # of retries before aborting a bus tx operation */ 58 59 /* Space for header read, limit for data packets */ 60 #ifndef MAX_HDR_READ 61 #define MAX_HDR_READ 32 62 #endif // endif 63 /** 16 bits will provide an absolute max of 65536 slots */ 64 #define WLFC_HANGER_MAXITEMS 3072 65 66 #define WLFC_HANGER_ITEM_STATE_FREE 1 67 #define WLFC_HANGER_ITEM_STATE_INUSE 2 68 #define WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED 3 69 #define WLFC_HANGER_ITEM_STATE_FLUSHED 4 70 71 #define WLFC_HANGER_PKT_STATE_TXSTATUS 1 72 #define WLFC_HANGER_PKT_STATE_BUSRETURNED 2 73 #define WLFC_HANGER_PKT_STATE_COMPLETE \ 74 (WLFC_HANGER_PKT_STATE_TXSTATUS | WLFC_HANGER_PKT_STATE_BUSRETURNED) 75 76 /* Private data for SDIO bus interaction */ 77 typedef struct dhd_bus { 78 dhd_pub_t *dhd; 79 80 bcmsdh_info_t *sdh; /* Handle for BCMSDH calls */ 81 si_t *sih; /* Handle for SI calls */ 82 char *vars; /* Variables (from CIS and/or other) */ 83 uint varsz; /* Size of variables buffer */ 84 uint32 sbaddr; /* Current SB window pointer (-1, invalid) */ 85 86 sdpcmd_regs_t *regs; /* Registers for SDIO core */ 87 uint sdpcmrev; /* SDIO core revision */ 88 uint armrev; /* CPU core revision */ 89 uint ramrev; /* SOCRAM core revision */ 90 uint32 ramsize; /* Size of RAM in SOCRAM (bytes) */ 91 uint32 orig_ramsize; /* Size of RAM in SOCRAM (bytes) */ 92 uint32 srmemsize; /* Size of SRMEM */ 93 94 uint32 bus; /* gSPI or SDIO bus */ 95 uint32 bus_num; /* bus number */ 96 uint32 slot_num; /* slot ID */ 97 uint32 hostintmask; /* Copy of Host Interrupt Mask */ 98 uint32 intstatus; /* Intstatus bits (events) pending */ 99 bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */ 100 bool fcstate; /* State of dongle flow-control */ 101 102 uint16 cl_devid; /* cached devid for dhdsdio_probe_attach() */ 103 char *fw_path; /* module_param: path to firmware image */ 104 char *nv_path; /* module_param: path to nvram vars file */ 105 106 uint blocksize; /* Block size of SDIO transfers */ 107 uint roundup; /* Max roundup limit */ 108 109 struct pktq txq; /* Queue length used for flow-control */ 110 uint8 flowcontrol; /* per prio flow control bitmask */ 111 uint8 tx_seq; /* Transmit sequence number (next) */ 112 uint8 tx_max; /* Maximum transmit sequence allowed */ 113 114 #ifdef DYNAMIC_MAX_HDR_READ 115 uint8 *hdrbufp; 116 #else 117 uint8 hdrbuf[MAX_HDR_READ + DHD_SDALIGN]; 118 #endif 119 uint8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ 120 uint16 nextlen; /* Next Read Len from last header */ 121 uint8 rx_seq; /* Receive sequence number (expected) */ 122 bool rxskip; /* Skip receive (awaiting NAK ACK) */ 123 124 void *glomd; /* Packet containing glomming descriptor */ 125 void *glom; /* Packet chain for glommed superframe */ 126 uint glomerr; /* Glom packet read errors */ 127 128 uint8 *rxbuf; /* Buffer for receiving control packets */ 129 uint rxblen; /* Allocated length of rxbuf */ 130 uint8 *rxctl; /* Aligned pointer into rxbuf */ 131 uint8 *databuf; /* Buffer for receiving big glom packet */ 132 uint8 *dataptr; /* Aligned pointer into databuf */ 133 uint rxlen; /* Length of valid data in buffer */ 134 135 uint8 sdpcm_ver; /* Bus protocol reported by dongle */ 136 137 bool intr; /* Use interrupts */ 138 bool poll; /* Use polling */ 139 bool ipend; /* Device interrupt is pending */ 140 bool intdis; /* Interrupts disabled by isr */ 141 uint intrcount; /* Count of device interrupt callbacks */ 142 uint lastintrs; /* Count as of last watchdog timer */ 143 uint spurious; /* Count of spurious interrupts */ 144 uint pollrate; /* Ticks between device polls */ 145 uint polltick; /* Tick counter */ 146 uint pollcnt; /* Count of active polls */ 147 148 dhd_console_t console; /* Console output polling support */ 149 uint console_addr; /* Console address from shared struct */ 150 151 uint regfails; /* Count of R_REG/W_REG failures */ 152 153 uint clkstate; /* State of sd and backplane clock(s) */ 154 bool activity; /* Activity flag for clock down */ 155 int32 idletime; /* Control for activity timeout */ 156 int32 idlecount; /* Activity timeout counter */ 157 int32 idleclock; /* How to set bus driver when idle */ 158 int32 sd_divisor; /* Speed control to bus driver */ 159 int32 sd_mode; /* Mode control to bus driver */ 160 int32 sd_rxchain; /* If bcmsdh api accepts PKT chains */ 161 bool use_rxchain; /* If dhd should use PKT chains */ 162 bool sleeping; /* Is SDIO bus sleeping? */ 163 #if defined(SUPPORT_P2P_GO_PS) 164 wait_queue_head_t bus_sleep; 165 #endif /* LINUX && SUPPORT_P2P_GO_PS */ 166 bool ctrl_wait; 167 wait_queue_head_t ctrl_tx_wait; 168 uint rxflow_mode; /* Rx flow control mode */ 169 bool rxflow; /* Is rx flow control on */ 170 uint prev_rxlim_hit; /* Is prev rx limit exceeded (per dpc schedule) */ 171 bool alp_only; /* Don't use HT clock (ALP only) */ 172 /* Field to decide if rx of control frames happen in rxbuf or lb-pool */ 173 bool usebufpool; 174 int32 txinrx_thres; /* num of in-queued pkts */ 175 int32 dotxinrx; /* tx first in dhdsdio_readframes */ 176 #ifdef BCMSDIO_RXLIM_POST 177 bool rxlim_en; 178 uint32 rxlim_addr; 179 #endif /* BCMSDIO_RXLIM_POST */ 180 #ifdef SDTEST 181 /* external loopback */ 182 bool ext_loop; 183 uint8 loopid; 184 185 /* pktgen configuration */ 186 uint pktgen_freq; /* Ticks between bursts */ 187 uint pktgen_count; /* Packets to send each burst */ 188 uint pktgen_print; /* Bursts between count displays */ 189 uint pktgen_total; /* Stop after this many */ 190 uint pktgen_minlen; /* Minimum packet data len */ 191 uint pktgen_maxlen; /* Maximum packet data len */ 192 uint pktgen_mode; /* Configured mode: tx, rx, or echo */ 193 uint pktgen_stop; /* Number of tx failures causing stop */ 194 195 /* active pktgen fields */ 196 uint pktgen_tick; /* Tick counter for bursts */ 197 uint pktgen_ptick; /* Burst counter for printing */ 198 uint pktgen_sent; /* Number of test packets generated */ 199 uint pktgen_rcvd; /* Number of test packets received */ 200 uint pktgen_prev_time; /* Time at which previous stats where printed */ 201 uint pktgen_prev_sent; /* Number of test packets generated when 202 * previous stats were printed 203 */ 204 uint pktgen_prev_rcvd; /* Number of test packets received when 205 * previous stats were printed 206 */ 207 uint pktgen_fail; /* Number of failed send attempts */ 208 uint16 pktgen_len; /* Length of next packet to send */ 209 #define PKTGEN_RCV_IDLE (0) 210 #define PKTGEN_RCV_ONGOING (1) 211 uint16 pktgen_rcv_state; /* receive state */ 212 uint pktgen_rcvd_rcvsession; /* test pkts rcvd per rcv session. */ 213 #endif /* SDTEST */ 214 215 /* Some additional counters */ 216 uint tx_sderrs; /* Count of tx attempts with sd errors */ 217 uint fcqueued; /* Tx packets that got queued */ 218 uint rxrtx; /* Count of rtx requests (NAK to dongle) */ 219 uint rx_toolong; /* Receive frames too long to receive */ 220 uint rxc_errors; /* SDIO errors when reading control frames */ 221 uint rx_hdrfail; /* SDIO errors on header reads */ 222 uint rx_badhdr; /* Bad received headers (roosync?) */ 223 uint rx_badseq; /* Mismatched rx sequence number */ 224 uint fc_rcvd; /* Number of flow-control events received */ 225 uint fc_xoff; /* Number which turned on flow-control */ 226 uint fc_xon; /* Number which turned off flow-control */ 227 uint rxglomfail; /* Failed deglom attempts */ 228 uint rxglomframes; /* Number of glom frames (superframes) */ 229 uint rxglompkts; /* Number of packets from glom frames */ 230 uint f2rxhdrs; /* Number of header reads */ 231 uint f2rxdata; /* Number of frame data reads */ 232 uint f2txdata; /* Number of f2 frame writes */ 233 uint f1regdata; /* Number of f1 register accesses */ 234 wake_counts_t wake_counts; /* Wake up counter */ 235 #ifdef BCMSPI 236 bool dwordmode; 237 #endif /* BCMSPI */ 238 #ifdef DHDENABLE_TAILPAD 239 uint tx_tailpad_chain; /* Number of tail padding by chaining pad_pkt */ 240 uint tx_tailpad_pktget; /* Number of tail padding by new PKTGET */ 241 #endif /* DHDENABLE_TAILPAD */ 242 uint8 *ctrl_frame_buf; 243 uint32 ctrl_frame_len; 244 bool ctrl_frame_stat; 245 #ifndef BCMSPI 246 uint32 rxint_mode; /* rx interrupt mode */ 247 #endif /* BCMSPI */ 248 bool remap; /* Contiguous 1MB RAM: 512K socram + 512K devram 249 * Available with socram rev 16 250 * Remap region not DMA-able 251 */ 252 bool kso; 253 bool _slpauto; 254 bool _oobwakeup; 255 bool _srenab; 256 bool readframes; 257 bool reqbussleep; 258 uint32 resetinstr; 259 uint32 dongle_ram_base; 260 261 void *glom_pkt_arr[SDPCM_MAXGLOM_SIZE]; /* Array of pkts for glomming */ 262 uint32 txglom_cnt; /* Number of pkts in the glom array */ 263 uint32 txglom_total_len; /* Total length of pkts in glom array */ 264 bool txglom_enable; /* Flag to indicate whether tx glom is enabled/disabled */ 265 uint32 txglomsize; /* Glom size limitation */ 266 #ifdef DHDENABLE_TAILPAD 267 void *pad_pkt; 268 #endif /* DHDENABLE_TAILPAD */ 269 uint32 dongle_trap_addr; /* device trap addr location in device memory */ 270 #if defined(BT_OVER_SDIO) 271 char *btfw_path; /* module_param: path to BT firmware image */ 272 uint32 bt_use_count; /* Counter that tracks whether BT is using the bus */ 273 #endif /* defined (BT_OVER_SDIO) */ 274 uint txglomframes; /* Number of tx glom frames (superframes) */ 275 uint txglompkts; /* Number of packets from tx glom frames */ 276 #ifdef PKT_STATICS 277 struct pkt_statics tx_statics; 278 #endif 279 uint8 *membuf; /* Buffer for dhdsdio_membytes */ 280 #ifdef CONSOLE_DPC 281 char cons_cmd[16]; 282 #endif 283 } dhd_bus_t; 284 285 typedef enum { 286 Q_TYPE_PSQ, /**< Power Save Queue, contains both delayed and suppressed packets */ 287 Q_TYPE_AFQ /**< At Firmware Queue */ 288 } q_type_t; 289 290 typedef enum ewlfc_packet_state { 291 eWLFC_PKTTYPE_NEW, /**< unused in the code (Jan 2015) */ 292 eWLFC_PKTTYPE_DELAYED, /**< packet did not enter wlfc yet */ 293 eWLFC_PKTTYPE_SUPPRESSED, /**< packet entered wlfc and was suppressed by the dongle */ 294 eWLFC_PKTTYPE_MAX 295 } ewlfc_packet_state_t; 296 297 typedef enum ewlfc_mac_entry_action { 298 eWLFC_MAC_ENTRY_ACTION_ADD, 299 eWLFC_MAC_ENTRY_ACTION_DEL, 300 eWLFC_MAC_ENTRY_ACTION_UPDATE, 301 eWLFC_MAC_ENTRY_ACTION_MAX 302 } ewlfc_mac_entry_action_t; 303 304 typedef struct wlfc_hanger_item { 305 uint8 state; 306 uint8 gen; 307 uint8 pkt_state; /**< bitmask containing eg WLFC_HANGER_PKT_STATE_TXCOMPLETE */ 308 uint8 pkt_txstatus; 309 uint32 identifier; 310 void* pkt; 311 #ifdef PROP_TXSTATUS_DEBUG 312 uint32 push_time; 313 #endif // endif 314 struct wlfc_hanger_item *next; 315 } wlfc_hanger_item_t; 316 317 /** hanger contains packets that have been posted by the dhd to the dongle and are expected back */ 318 typedef struct wlfc_hanger { 319 int max_items; 320 uint32 pushed; 321 uint32 popped; 322 uint32 failed_to_push; 323 uint32 failed_to_pop; 324 uint32 failed_slotfind; 325 uint32 slot_pos; 326 wlfc_hanger_item_t items[1]; 327 } wlfc_hanger_t; 328 329 #define WLFC_HANGER_SIZE(n) ((sizeof(wlfc_hanger_t) - \ 330 sizeof(wlfc_hanger_item_t)) + ((n)*sizeof(wlfc_hanger_item_t))) 331 332 #define WLFC_STATE_OPEN 1 /**< remote MAC is able to receive packets */ 333 #define WLFC_STATE_CLOSE 2 /**< remote MAC is in power save mode */ 334 335 #define WLFC_PSQ_PREC_COUNT ((AC_COUNT + 1) * 2) /**< 2 for each AC traffic and bc/mc */ 336 #define WLFC_AFQ_PREC_COUNT (AC_COUNT + 1) 337 338 #define WLFC_PSQ_LEN (4096 * 8) 339 340 #ifdef BCMDBUS 341 #define WLFC_FLOWCONTROL_HIWATER 512 342 #define WLFC_FLOWCONTROL_LOWATER (WLFC_FLOWCONTROL_HIWATER / 4) 343 #else 344 #define WLFC_FLOWCONTROL_HIWATER ((4096 * 8) - 256) 345 #define WLFC_FLOWCONTROL_LOWATER 256 346 #endif 347 348 #if (WLFC_FLOWCONTROL_HIWATER >= (WLFC_PSQ_LEN - 256)) 349 #undef WLFC_FLOWCONTROL_HIWATER 350 #define WLFC_FLOWCONTROL_HIWATER (WLFC_PSQ_LEN - 256) 351 #undef WLFC_FLOWCONTROL_LOWATER 352 #define WLFC_FLOWCONTROL_LOWATER (WLFC_FLOWCONTROL_HIWATER / 4) 353 #endif // endif 354 355 #define WLFC_LOG_BUF_SIZE (1024*1024) 356 357 /** Properties related to a remote MAC entity */ 358 typedef struct wlfc_mac_descriptor { 359 uint8 occupied; /**< if 0, this descriptor is unused and thus can be (re)used */ 360 uint8 interface_id; 361 uint8 iftype; /**< eg WLC_E_IF_ROLE_STA */ 362 uint8 state; /**< eg WLFC_STATE_OPEN */ 363 uint8 ac_bitmap; /**< automatic power save delivery (APSD) */ 364 uint8 requested_credit; 365 uint8 requested_packet; /**< unit: [number of packets] */ 366 uint8 ea[ETHER_ADDR_LEN]; 367 368 /** maintain (MAC,AC) based seq count for packets going to the device. As well as bc/mc. */ 369 uint8 seq[AC_COUNT + 1]; 370 uint8 generation; /**< toggles between 0 and 1 */ 371 struct pktq psq; /**< contains both 'delayed' and 'suppressed' packets */ 372 /** packets at firmware queue */ 373 struct pktq afq; 374 /** The AC pending bitmap that was reported to the fw at last change */ 375 uint8 traffic_lastreported_bmp; 376 /** The new AC pending bitmap */ 377 uint8 traffic_pending_bmp; 378 /** 1= send on next opportunity */ 379 uint8 send_tim_signal; 380 uint8 mac_handle; /**< mac handles are assigned by the dongle */ 381 /** Number of packets at dongle for this entry. */ 382 int transit_count; 383 /** Number of suppression to wait before evict from delayQ */ 384 int suppr_transit_count; 385 /** pkt sent to bus but no bus TX complete yet */ 386 int onbus_pkts_count; 387 /** flag. TRUE when remote MAC is in suppressed state */ 388 uint8 suppressed; 389 390 #ifdef PROP_TXSTATUS_DEBUG 391 uint32 dstncredit_sent_packets; 392 uint32 dstncredit_acks; 393 uint32 opened_ct; 394 uint32 closed_ct; 395 #endif // endif 396 #ifdef PROPTX_MAXCOUNT 397 /** Max Number of packets at dongle for this entry. */ 398 int transit_maxcount; 399 #endif /* PROPTX_MAXCOUNT */ 400 struct wlfc_mac_descriptor* prev; 401 struct wlfc_mac_descriptor* next; 402 } wlfc_mac_descriptor_t; 403 404 /** A 'commit' is the hand over of a packet from the host OS layer to the layer below (eg DBUS) */ 405 typedef struct dhd_wlfc_commit_info { 406 uint8 needs_hdr; 407 uint8 ac_fifo_credit_spent; 408 ewlfc_packet_state_t pkt_type; 409 wlfc_mac_descriptor_t* mac_entry; 410 void* p; 411 } dhd_wlfc_commit_info_t; 412 413 #define WLFC_DECR_SEQCOUNT(entry, prec) do { if (entry->seq[(prec)] == 0) {\ 414 entry->seq[prec] = 0xff; } else entry->seq[prec]--;} while (0) 415 416 #define WLFC_INCR_SEQCOUNT(entry, prec) entry->seq[(prec)]++ 417 #define WLFC_SEQCOUNT(entry, prec) entry->seq[(prec)] 418 419 typedef struct athost_wl_stat_counters { 420 uint32 pktin; 421 uint32 pktout; 422 uint32 pkt2bus; 423 uint32 pktdropped; 424 uint32 tlv_parse_failed; 425 uint32 rollback; 426 uint32 rollback_failed; 427 uint32 delayq_full_error; 428 uint32 credit_request_failed; 429 uint32 packet_request_failed; 430 uint32 mac_update_failed; 431 uint32 psmode_update_failed; 432 uint32 interface_update_failed; 433 uint32 wlfc_header_only_pkt; 434 uint32 txstatus_in; 435 uint32 d11_suppress; 436 uint32 wl_suppress; 437 uint32 bad_suppress; 438 uint32 pkt_dropped; 439 uint32 pkt_exptime; 440 uint32 pkt_freed; 441 uint32 pkt_free_err; 442 uint32 psq_wlsup_retx; 443 uint32 psq_wlsup_enq; 444 uint32 psq_d11sup_retx; 445 uint32 psq_d11sup_enq; 446 uint32 psq_hostq_retx; 447 uint32 psq_hostq_enq; 448 uint32 mac_handle_notfound; 449 uint32 wlc_tossed_pkts; 450 uint32 dhd_hdrpulls; 451 uint32 generic_error; 452 /* an extra one for bc/mc traffic */ 453 uint32 send_pkts[AC_COUNT + 1]; 454 uint32 drop_pkts[WLFC_PSQ_PREC_COUNT]; 455 uint32 ooo_pkts[AC_COUNT + 1]; 456 #ifdef PROP_TXSTATUS_DEBUG 457 /** all pkt2bus -> txstatus latency accumulated */ 458 uint32 latency_sample_count; 459 uint32 total_status_latency; 460 uint32 latency_most_recent; 461 int idx_delta; 462 uint32 deltas[10]; 463 uint32 fifo_credits_sent[6]; 464 uint32 fifo_credits_back[6]; 465 uint32 dropped_qfull[6]; 466 uint32 signal_only_pkts_sent; 467 uint32 signal_only_pkts_freed; 468 #endif // endif 469 uint32 cleanup_txq_cnt; 470 uint32 cleanup_psq_cnt; 471 uint32 cleanup_fw_cnt; 472 } athost_wl_stat_counters_t; 473 474 #ifdef PROP_TXSTATUS_DEBUG 475 #define WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac) do { \ 476 (ctx)->stats.fifo_credits_sent[(ac)]++;} while (0) 477 #define WLFC_HOST_FIFO_CREDIT_INC_BACKCTRS(ctx, ac) do { \ 478 (ctx)->stats.fifo_credits_back[(ac)]++;} while (0) 479 #define WLFC_HOST_FIFO_DROPPEDCTR_INC(ctx, ac) do { \ 480 (ctx)->stats.dropped_qfull[(ac)]++;} while (0) 481 #else 482 #define WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac) do {} while (0) 483 #define WLFC_HOST_FIFO_CREDIT_INC_BACKCTRS(ctx, ac) do {} while (0) 484 #define WLFC_HOST_FIFO_DROPPEDCTR_INC(ctx, ac) do {} while (0) 485 #endif // endif 486 #define WLFC_PACKET_BOUND 10 487 #define WLFC_FCMODE_NONE 0 488 #define WLFC_FCMODE_IMPLIED_CREDIT 1 489 #define WLFC_FCMODE_EXPLICIT_CREDIT 2 490 #define WLFC_ONLY_AMPDU_HOSTREORDER 3 491 492 /** Reserved credits ratio when borrowed by hihger priority */ 493 #define WLFC_BORROW_LIMIT_RATIO 4 494 495 /** How long to defer borrowing in milliseconds */ 496 #define WLFC_BORROW_DEFER_PERIOD_MS 100 497 498 /** How long to defer flow control in milliseconds */ 499 #define WLFC_FC_DEFER_PERIOD_MS 200 500 501 /** How long to detect occurance per AC in miliseconds */ 502 #define WLFC_RX_DETECTION_THRESHOLD_MS 100 503 504 /** Mask to represent available ACs (note: BC/MC is ignored) */ 505 #define WLFC_AC_MASK 0xF 506 507 /** flow control specific information, only 1 instance during driver lifetime */ 508 typedef struct athost_wl_status_info { 509 uint8 last_seqid_to_wlc; 510 511 /** OSL handle */ 512 osl_t *osh; 513 /** dhd public struct pointer */ 514 void *dhdp; 515 516 f_commitpkt_t fcommit; 517 void* commit_ctx; 518 519 /** statistics */ 520 athost_wl_stat_counters_t stats; 521 522 /** incremented on eg receiving a credit map event from the dongle */ 523 int Init_FIFO_credit[AC_COUNT + 2]; 524 /** the additional ones are for bc/mc and ATIM FIFO */ 525 int FIFO_credit[AC_COUNT + 2]; 526 /** Credit borrow counts for each FIFO from each of the other FIFOs */ 527 int credits_borrowed[AC_COUNT + 2][AC_COUNT + 2]; 528 529 /** packet hanger and MAC->handle lookup table */ 530 void *hanger; 531 532 struct { 533 /** table for individual nodes */ 534 wlfc_mac_descriptor_t nodes[WLFC_MAC_DESC_TABLE_SIZE]; 535 /** table for interfaces */ 536 wlfc_mac_descriptor_t interfaces[WLFC_MAX_IFNUM]; 537 /* OS may send packets to unknown (unassociated) destinations */ 538 /** A place holder for bc/mc and packets to unknown destinations */ 539 wlfc_mac_descriptor_t other; 540 } destination_entries; 541 542 wlfc_mac_descriptor_t *active_entry_head; /**< a chain of MAC descriptors */ 543 int active_entry_count; 544 545 wlfc_mac_descriptor_t *requested_entry[WLFC_MAC_DESC_TABLE_SIZE]; 546 int requested_entry_count; 547 548 /* pkt counts for each interface and ac */ 549 int pkt_cnt_in_q[WLFC_MAX_IFNUM][AC_COUNT+1]; 550 int pkt_cnt_per_ac[AC_COUNT+1]; 551 int pkt_cnt_in_drv[WLFC_MAX_IFNUM][AC_COUNT+1]; 552 int pkt_cnt_in_psq; 553 uint8 allow_fc; /**< Boolean */ 554 uint32 fc_defer_timestamp; 555 uint32 rx_timestamp[AC_COUNT+1]; 556 557 /** ON/OFF state for flow control to the host network interface */ 558 uint8 hostif_flow_state[WLFC_MAX_IFNUM]; 559 uint8 host_ifidx; 560 561 /** to flow control an OS interface */ 562 uint8 toggle_host_if; 563 564 /** To borrow credits */ 565 uint8 allow_credit_borrow; 566 567 /** ac number for the first single ac traffic */ 568 uint8 single_ac; 569 570 /** Timestamp for the first single ac traffic */ 571 uint32 single_ac_timestamp; 572 573 bool bcmc_credit_supported; 574 575 } athost_wl_status_info_t; 576 577 /** Please be mindful that total pkttag space is 32 octets only */ 578 typedef struct dhd_pkttag { 579 580 #ifdef BCM_OBJECT_TRACE 581 /* if use this field, keep it at the first 4 bytes */ 582 uint32 sn; 583 #endif /* BCM_OBJECT_TRACE */ 584 585 /** 586 b[15] - 1 = wlfc packet 587 b[14:13] - encryption exemption 588 b[12 ] - 1 = event channel 589 b[11 ] - 1 = this packet was sent in response to one time packet request, 590 do not increment credit on status for this one. [WLFC_CTL_TYPE_MAC_REQUEST_PACKET]. 591 b[10 ] - 1 = signal-only-packet to firmware [i.e. nothing to piggyback on] 592 b[9 ] - 1 = packet is host->firmware (transmit direction) 593 - 0 = packet received from firmware (firmware->host) 594 b[8 ] - 1 = packet was sent due to credit_request (pspoll), 595 packet does not count against FIFO credit. 596 - 0 = normal transaction, packet counts against FIFO credit 597 b[7 ] - 1 = AP, 0 = STA 598 b[6:4] - AC FIFO number 599 b[3:0] - interface index 600 */ 601 uint16 if_flags; 602 603 /** 604 * destination MAC address for this packet so that not every module needs to open the packet 605 * to find this 606 */ 607 uint8 dstn_ether[ETHER_ADDR_LEN]; 608 609 /** This 32-bit goes from host to device for every packet. */ 610 uint32 htod_tag; 611 612 /** This 16-bit is original d11seq number for every suppressed packet. */ 613 uint16 htod_seq; 614 615 /** This address is mac entry for every packet. */ 616 void *entry; 617 618 /** bus specific stuff */ 619 union { 620 struct { 621 void *stuff; 622 uint32 thing1; 623 uint32 thing2; 624 } sd; 625 626 struct { 627 void *bus; 628 void *urb; 629 } usb; 630 } bus_specific; 631 } dhd_pkttag_t; 632 633 #define DHD_PKTTAG_WLFCPKT_MASK 0x1 634 #define DHD_PKTTAG_WLFCPKT_SHIFT 15 635 #define DHD_PKTTAG_WLFCPKT_SET(tag, value) ((dhd_pkttag_t*)(tag))->if_flags = \ 636 (((dhd_pkttag_t*)(tag))->if_flags & \ 637 ~(DHD_PKTTAG_WLFCPKT_MASK << DHD_PKTTAG_WLFCPKT_SHIFT)) | \ 638 (((value) & DHD_PKTTAG_WLFCPKT_MASK) << DHD_PKTTAG_WLFCPKT_SHIFT) 639 #define DHD_PKTTAG_WLFCPKT(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ 640 DHD_PKTTAG_WLFCPKT_SHIFT) & DHD_PKTTAG_WLFCPKT_MASK) 641 642 #define DHD_PKTTAG_EXEMPT_MASK 0x3 643 #define DHD_PKTTAG_EXEMPT_SHIFT 13 644 #define DHD_PKTTAG_EXEMPT_SET(tag, value) ((dhd_pkttag_t*)(tag))->if_flags = \ 645 (((dhd_pkttag_t*)(tag))->if_flags & \ 646 ~(DHD_PKTTAG_EXEMPT_MASK << DHD_PKTTAG_EXEMPT_SHIFT)) | \ 647 (((value) & DHD_PKTTAG_EXEMPT_MASK) << DHD_PKTTAG_EXEMPT_SHIFT) 648 #define DHD_PKTTAG_EXEMPT(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ 649 DHD_PKTTAG_EXEMPT_SHIFT) & DHD_PKTTAG_EXEMPT_MASK) 650 651 #define DHD_PKTTAG_EVENT_MASK 0x1 652 #define DHD_PKTTAG_EVENT_SHIFT 12 653 #define DHD_PKTTAG_SETEVENT(tag, event) ((dhd_pkttag_t*)(tag))->if_flags = \ 654 (((dhd_pkttag_t*)(tag))->if_flags & \ 655 ~(DHD_PKTTAG_EVENT_MASK << DHD_PKTTAG_EVENT_SHIFT)) | \ 656 (((event) & DHD_PKTTAG_EVENT_MASK) << DHD_PKTTAG_EVENT_SHIFT) 657 #define DHD_PKTTAG_EVENT(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ 658 DHD_PKTTAG_EVENT_SHIFT) & DHD_PKTTAG_EVENT_MASK) 659 660 #define DHD_PKTTAG_ONETIMEPKTRQST_MASK 0x1 661 #define DHD_PKTTAG_ONETIMEPKTRQST_SHIFT 11 662 #define DHD_PKTTAG_SETONETIMEPKTRQST(tag) ((dhd_pkttag_t*)(tag))->if_flags = \ 663 (((dhd_pkttag_t*)(tag))->if_flags & \ 664 ~(DHD_PKTTAG_ONETIMEPKTRQST_MASK << DHD_PKTTAG_ONETIMEPKTRQST_SHIFT)) | \ 665 (1 << DHD_PKTTAG_ONETIMEPKTRQST_SHIFT) 666 #define DHD_PKTTAG_ONETIMEPKTRQST(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ 667 DHD_PKTTAG_ONETIMEPKTRQST_SHIFT) & DHD_PKTTAG_ONETIMEPKTRQST_MASK) 668 669 #define DHD_PKTTAG_SIGNALONLY_MASK 0x1 670 #define DHD_PKTTAG_SIGNALONLY_SHIFT 10 671 #define DHD_PKTTAG_SETSIGNALONLY(tag, signalonly) ((dhd_pkttag_t*)(tag))->if_flags = \ 672 (((dhd_pkttag_t*)(tag))->if_flags & \ 673 ~(DHD_PKTTAG_SIGNALONLY_MASK << DHD_PKTTAG_SIGNALONLY_SHIFT)) | \ 674 (((signalonly) & DHD_PKTTAG_SIGNALONLY_MASK) << DHD_PKTTAG_SIGNALONLY_SHIFT) 675 #define DHD_PKTTAG_SIGNALONLY(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ 676 DHD_PKTTAG_SIGNALONLY_SHIFT) & DHD_PKTTAG_SIGNALONLY_MASK) 677 678 #define DHD_PKTTAG_PKTDIR_MASK 0x1 679 #define DHD_PKTTAG_PKTDIR_SHIFT 9 680 #define DHD_PKTTAG_SETPKTDIR(tag, dir) ((dhd_pkttag_t*)(tag))->if_flags = \ 681 (((dhd_pkttag_t*)(tag))->if_flags & \ 682 ~(DHD_PKTTAG_PKTDIR_MASK << DHD_PKTTAG_PKTDIR_SHIFT)) | \ 683 (((dir) & DHD_PKTTAG_PKTDIR_MASK) << DHD_PKTTAG_PKTDIR_SHIFT) 684 #define DHD_PKTTAG_PKTDIR(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ 685 DHD_PKTTAG_PKTDIR_SHIFT) & DHD_PKTTAG_PKTDIR_MASK) 686 687 #define DHD_PKTTAG_CREDITCHECK_MASK 0x1 688 #define DHD_PKTTAG_CREDITCHECK_SHIFT 8 689 #define DHD_PKTTAG_SETCREDITCHECK(tag, check) ((dhd_pkttag_t*)(tag))->if_flags = \ 690 (((dhd_pkttag_t*)(tag))->if_flags & \ 691 ~(DHD_PKTTAG_CREDITCHECK_MASK << DHD_PKTTAG_CREDITCHECK_SHIFT)) | \ 692 (((check) & DHD_PKTTAG_CREDITCHECK_MASK) << DHD_PKTTAG_CREDITCHECK_SHIFT) 693 #define DHD_PKTTAG_CREDITCHECK(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ 694 DHD_PKTTAG_CREDITCHECK_SHIFT) & DHD_PKTTAG_CREDITCHECK_MASK) 695 696 #define DHD_PKTTAG_IFTYPE_MASK 0x1 697 #define DHD_PKTTAG_IFTYPE_SHIFT 7 698 #define DHD_PKTTAG_SETIFTYPE(tag, isAP) ((dhd_pkttag_t*)(tag))->if_flags = \ 699 (((dhd_pkttag_t*)(tag))->if_flags & \ 700 ~(DHD_PKTTAG_IFTYPE_MASK << DHD_PKTTAG_IFTYPE_SHIFT)) | \ 701 (((isAP) & DHD_PKTTAG_IFTYPE_MASK) << DHD_PKTTAG_IFTYPE_SHIFT) 702 #define DHD_PKTTAG_IFTYPE(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ 703 DHD_PKTTAG_IFTYPE_SHIFT) & DHD_PKTTAG_IFTYPE_MASK) 704 705 #define DHD_PKTTAG_FIFO_MASK 0x7 706 #define DHD_PKTTAG_FIFO_SHIFT 4 707 #define DHD_PKTTAG_SETFIFO(tag, fifo) ((dhd_pkttag_t*)(tag))->if_flags = \ 708 (((dhd_pkttag_t*)(tag))->if_flags & ~(DHD_PKTTAG_FIFO_MASK << DHD_PKTTAG_FIFO_SHIFT)) | \ 709 (((fifo) & DHD_PKTTAG_FIFO_MASK) << DHD_PKTTAG_FIFO_SHIFT) 710 #define DHD_PKTTAG_FIFO(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ 711 DHD_PKTTAG_FIFO_SHIFT) & DHD_PKTTAG_FIFO_MASK) 712 713 #define DHD_PKTTAG_IF_MASK 0xf 714 #define DHD_PKTTAG_IF_SHIFT 0 715 #define DHD_PKTTAG_SETIF(tag, if) ((dhd_pkttag_t*)(tag))->if_flags = \ 716 (((dhd_pkttag_t*)(tag))->if_flags & ~(DHD_PKTTAG_IF_MASK << DHD_PKTTAG_IF_SHIFT)) | \ 717 (((if) & DHD_PKTTAG_IF_MASK) << DHD_PKTTAG_IF_SHIFT) 718 #define DHD_PKTTAG_IF(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ 719 DHD_PKTTAG_IF_SHIFT) & DHD_PKTTAG_IF_MASK) 720 721 #define DHD_PKTTAG_SETDSTN(tag, dstn_MAC_ea) memcpy(((dhd_pkttag_t*)((tag)))->dstn_ether, \ 722 (dstn_MAC_ea), ETHER_ADDR_LEN) 723 #define DHD_PKTTAG_DSTN(tag) ((dhd_pkttag_t*)(tag))->dstn_ether 724 725 #define DHD_PKTTAG_SET_H2DTAG(tag, h2dvalue) ((dhd_pkttag_t*)(tag))->htod_tag = (h2dvalue) 726 #define DHD_PKTTAG_H2DTAG(tag) (((dhd_pkttag_t*)(tag))->htod_tag) 727 728 #define DHD_PKTTAG_SET_H2DSEQ(tag, seq) ((dhd_pkttag_t*)(tag))->htod_seq = (seq) 729 #define DHD_PKTTAG_H2DSEQ(tag) (((dhd_pkttag_t*)(tag))->htod_seq) 730 731 #define DHD_PKTTAG_SET_ENTRY(tag, entry) ((dhd_pkttag_t*)(tag))->entry = (entry) 732 #define DHD_PKTTAG_ENTRY(tag) (((dhd_pkttag_t*)(tag))->entry) 733 734 #define PSQ_SUP_IDX(x) (x * 2 + 1) 735 #define PSQ_DLY_IDX(x) (x * 2) 736 737 #ifdef PROP_TXSTATUS_DEBUG 738 #define DHD_WLFC_CTRINC_MAC_CLOSE(entry) do { (entry)->closed_ct++; } while (0) 739 #define DHD_WLFC_CTRINC_MAC_OPEN(entry) do { (entry)->opened_ct++; } while (0) 740 #else 741 #define DHD_WLFC_CTRINC_MAC_CLOSE(entry) do {} while (0) 742 #define DHD_WLFC_CTRINC_MAC_OPEN(entry) do {} while (0) 743 #endif // endif 744 745 #ifdef BCM_OBJECT_TRACE 746 #define DHD_PKTTAG_SET_SN(tag, val) ((dhd_pkttag_t*)(tag))->sn = (val) 747 #define DHD_PKTTAG_SN(tag) (((dhd_pkttag_t*)(tag))->sn) 748 #endif /* BCM_OBJECT_TRACE */ 749 750 /* public functions */ 751 int dhd_wlfc_parse_header_info(dhd_pub_t *dhd, void* pktbuf, int tlv_hdr_len, 752 uchar *reorder_info_buf, uint *reorder_info_len); 753 KERNEL_THREAD_RETURN_TYPE dhd_wlfc_transfer_packets(void *data); 754 int dhd_wlfc_commit_packets(dhd_pub_t *dhdp, f_commitpkt_t fcommit, 755 void* commit_ctx, void *pktbuf, bool need_toggle_host_if); 756 int dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success); 757 int dhd_wlfc_init(dhd_pub_t *dhd); 758 #ifdef SUPPORT_P2P_GO_PS 759 int dhd_wlfc_suspend(dhd_pub_t *dhd); 760 int dhd_wlfc_resume(dhd_pub_t *dhd); 761 #endif /* SUPPORT_P2P_GO_PS */ 762 int dhd_wlfc_hostreorder_init(dhd_pub_t *dhd); 763 int dhd_wlfc_cleanup_txq(dhd_pub_t *dhd, f_processpkt_t fn, void *arg); 764 int dhd_wlfc_cleanup(dhd_pub_t *dhd, f_processpkt_t fn, void* arg); 765 int dhd_wlfc_deinit(dhd_pub_t *dhd); 766 int dhd_wlfc_interface_event(dhd_pub_t *dhdp, uint8 action, uint8 ifid, uint8 iftype, uint8* ea); 767 int dhd_wlfc_FIFOcreditmap_event(dhd_pub_t *dhdp, uint8* event_data); 768 #ifdef LIMIT_BORROW 769 int dhd_wlfc_disable_credit_borrow_event(dhd_pub_t *dhdp, uint8* event_data); 770 #endif /* LIMIT_BORROW */ 771 int dhd_wlfc_BCMCCredit_support_event(dhd_pub_t *dhdp); 772 int dhd_wlfc_enable(dhd_pub_t *dhdp); 773 int dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf); 774 int dhd_wlfc_clear_counts(dhd_pub_t *dhd); 775 int dhd_wlfc_get_enable(dhd_pub_t *dhd, bool *val); 776 int dhd_wlfc_get_mode(dhd_pub_t *dhd, int *val); 777 int dhd_wlfc_set_mode(dhd_pub_t *dhd, int val); 778 bool dhd_wlfc_is_supported(dhd_pub_t *dhd); 779 bool dhd_wlfc_is_header_only_pkt(dhd_pub_t * dhd, void *pktbuf); 780 int dhd_wlfc_flowcontrol(dhd_pub_t *dhdp, bool state, bool bAcquireLock); 781 int dhd_wlfc_save_rxpath_ac_time(dhd_pub_t * dhd, uint8 prio); 782 783 int dhd_wlfc_get_module_ignore(dhd_pub_t *dhd, int *val); 784 int dhd_wlfc_set_module_ignore(dhd_pub_t *dhd, int val); 785 int dhd_wlfc_get_credit_ignore(dhd_pub_t *dhd, int *val); 786 int dhd_wlfc_set_credit_ignore(dhd_pub_t *dhd, int val); 787 int dhd_wlfc_get_txstatus_ignore(dhd_pub_t *dhd, int *val); 788 int dhd_wlfc_set_txstatus_ignore(dhd_pub_t *dhd, int val); 789 790 int dhd_wlfc_get_rxpkt_chk(dhd_pub_t *dhd, int *val); 791 int dhd_wlfc_set_rxpkt_chk(dhd_pub_t *dhd, int val); 792 #ifdef PROPTX_MAXCOUNT 793 int dhd_wlfc_update_maxcount(dhd_pub_t *dhdp, uint8 ifid, int maxcount); 794 #endif /* PROPTX_MAXCOUNT */ 795 796 #endif /* __wlfc_host_driver_definitions_h__ */ 797