1/* 2* Copyright (C) 1999-2012, Broadcom Corporation 3* 4* Unless you and Broadcom execute a separate written software license 5* agreement governing use of this software, this software is licensed to you 6* under the terms of the GNU General Public License version 2 (the "GPL"), 7* available at http://www.broadcom.com/licenses/GPLv2.php, with the 8* following added to such license: 9* 10* As a special exception, the copyright holders of this software give you 11* permission to link this software with independent modules, and to copy and 12* distribute the resulting executable under terms of your choice, provided that 13* you also meet, for each linked independent module, the terms and conditions of 14* the license of that module. An independent module is a module which is not 15* derived from this software. The special exception does not apply to any 16* modifications of the software. 17* 18* Notwithstanding the above, under no circumstances may you combine this 19* software in any way with any other Broadcom software provided under a license 20* other than the GPL, without Broadcom's express prior written consent. 21* $Id: dhd_wlfc.h 294267 2011-11-04 23:41:52Z $ 22* 23*/ 24#ifndef __wlfc_host_driver_definitions_h__ 25#define __wlfc_host_driver_definitions_h__ 26 27/* 16 bits will provide an absolute max of 65536 slots */ 28#define WLFC_HANGER_MAXITEMS 1024 29 30#define WLFC_HANGER_ITEM_STATE_FREE 1 31#define WLFC_HANGER_ITEM_STATE_INUSE 2 32 33#define WLFC_PKTID_HSLOT_MASK 0xffff /* allow 16 bits only */ 34#define WLFC_PKTID_HSLOT_SHIFT 8 35 36/* x -> TXSTATUS TAG to/from firmware */ 37#define WLFC_PKTID_HSLOT_GET(x) \ 38 (((x) >> WLFC_PKTID_HSLOT_SHIFT) & WLFC_PKTID_HSLOT_MASK) 39#define WLFC_PKTID_HSLOT_SET(var, slot) \ 40 ((var) = ((var) & ~(WLFC_PKTID_HSLOT_MASK << WLFC_PKTID_HSLOT_SHIFT)) | \ 41 (((slot) & WLFC_PKTID_HSLOT_MASK) << WLFC_PKTID_HSLOT_SHIFT)) 42 43#define WLFC_PKTID_FREERUNCTR_MASK 0xff 44 45#define WLFC_PKTID_FREERUNCTR_GET(x) ((x) & WLFC_PKTID_FREERUNCTR_MASK) 46#define WLFC_PKTID_FREERUNCTR_SET(var, ctr) \ 47 ((var) = (((var) & ~WLFC_PKTID_FREERUNCTR_MASK) | \ 48 (((ctr) & WLFC_PKTID_FREERUNCTR_MASK)))) 49 50#define WLFC_PKTQ_PENQ(pq, prec, p) ((pktq_full((pq)) || pktq_pfull((pq), (prec)))? \ 51 NULL : pktq_penq((pq), (prec), (p))) 52#define WLFC_PKTQ_PENQ_HEAD(pq, prec, p) ((pktq_full((pq)) || pktq_pfull((pq), (prec))) ? \ 53 NULL : pktq_penq_head((pq), (prec), (p))) 54 55typedef enum ewlfc_packet_state { 56 eWLFC_PKTTYPE_NEW, 57 eWLFC_PKTTYPE_DELAYED, 58 eWLFC_PKTTYPE_SUPPRESSED, 59 eWLFC_PKTTYPE_MAX 60} ewlfc_packet_state_t; 61 62typedef enum ewlfc_mac_entry_action { 63 eWLFC_MAC_ENTRY_ACTION_ADD, 64 eWLFC_MAC_ENTRY_ACTION_DEL, 65 eWLFC_MAC_ENTRY_ACTION_MAX 66} ewlfc_mac_entry_action_t; 67 68typedef struct wlfc_hanger_item { 69 uint8 state; 70 uint8 pad[3]; 71 uint32 identifier; 72 void* pkt; 73#ifdef PROP_TXSTATUS_DEBUG 74 uint32 push_time; 75#endif 76} wlfc_hanger_item_t; 77 78typedef struct wlfc_hanger { 79 int max_items; 80 uint32 pushed; 81 uint32 popped; 82 uint32 failed_to_push; 83 uint32 failed_to_pop; 84 uint32 failed_slotfind; 85 wlfc_hanger_item_t items[1]; 86} wlfc_hanger_t; 87 88#define WLFC_HANGER_SIZE(n) ((sizeof(wlfc_hanger_t) - \ 89 sizeof(wlfc_hanger_item_t)) + ((n)*sizeof(wlfc_hanger_item_t))) 90 91#define WLFC_STATE_OPEN 1 92#define WLFC_STATE_CLOSE 2 93 94#define WLFC_PSQ_PREC_COUNT ((AC_COUNT + 1) * 2) /* 2 for each AC traffic and bc/mc */ 95#define WLFC_PSQ_LEN 64 96#define WLFC_SENDQ_LEN 256 97 98#define WLFC_FLOWCONTROL_DELTA 8 99#define WLFC_FLOWCONTROL_HIWATER (WLFC_PSQ_LEN - WLFC_FLOWCONTROL_DELTA) 100#define WLFC_FLOWCONTROL_LOWATER (WLFC_FLOWCONTROL_HIWATER - WLFC_FLOWCONTROL_DELTA) 101 102typedef struct wlfc_mac_descriptor { 103 uint8 occupied; 104 uint8 interface_id; 105 uint8 iftype; 106 uint8 state; 107 uint8 ac_bitmap; /* for APSD */ 108 uint8 requested_credit; 109 uint8 requested_packet; 110 uint8 ea[ETHER_ADDR_LEN]; 111 /* 112 maintain (MAC,AC) based seq count for 113 packets going to the device. As well as bc/mc. 114 */ 115 uint8 seq[AC_COUNT + 1]; 116 uint8 generation; 117 struct pktq psq; 118 /* The AC pending bitmap that was reported to the fw at last change */ 119 uint8 traffic_lastreported_bmp; 120 /* The new AC pending bitmap */ 121 uint8 traffic_pending_bmp; 122 /* 1= send on next opportunity */ 123 uint8 send_tim_signal; 124 uint8 mac_handle; 125#ifdef PROP_TXSTATUS_DEBUG 126 uint32 dstncredit_sent_packets; 127 uint32 dstncredit_acks; 128 uint32 opened_ct; 129 uint32 closed_ct; 130#endif 131} wlfc_mac_descriptor_t; 132 133#define WLFC_DECR_SEQCOUNT(entry, prec) do { if (entry->seq[(prec)] == 0) {\ 134 entry->seq[prec] = 0xff; } else entry->seq[prec]--;} while (0) 135 136#define WLFC_INCR_SEQCOUNT(entry, prec) entry->seq[(prec)]++ 137#define WLFC_SEQCOUNT(entry, prec) entry->seq[(prec)] 138 139typedef struct athost_wl_stat_counters { 140 uint32 pktin; 141 uint32 pkt2bus; 142 uint32 pktdropped; 143 uint32 tlv_parse_failed; 144 uint32 rollback; 145 uint32 rollback_failed; 146 uint32 sendq_full_error; 147 uint32 delayq_full_error; 148 uint32 credit_request_failed; 149 uint32 packet_request_failed; 150 uint32 mac_update_failed; 151 uint32 psmode_update_failed; 152 uint32 interface_update_failed; 153 uint32 wlfc_header_only_pkt; 154 uint32 txstatus_in; 155 uint32 d11_suppress; 156 uint32 wl_suppress; 157 uint32 bad_suppress; 158 uint32 pkt_freed; 159 uint32 pkt_free_err; 160 uint32 psq_wlsup_retx; 161 uint32 psq_wlsup_enq; 162 uint32 psq_d11sup_retx; 163 uint32 psq_d11sup_enq; 164 uint32 psq_hostq_retx; 165 uint32 psq_hostq_enq; 166 uint32 mac_handle_notfound; 167 uint32 wlc_tossed_pkts; 168 uint32 dhd_hdrpulls; 169 uint32 generic_error; 170 /* an extra one for bc/mc traffic */ 171 uint32 sendq_pkts[AC_COUNT + 1]; 172#ifdef PROP_TXSTATUS_DEBUG 173 /* all pkt2bus -> txstatus latency accumulated */ 174 uint32 latency_sample_count; 175 uint32 total_status_latency; 176 uint32 latency_most_recent; 177 int idx_delta; 178 uint32 deltas[10]; 179 uint32 fifo_credits_sent[6]; 180 uint32 fifo_credits_back[6]; 181 uint32 dropped_qfull[6]; 182 uint32 signal_only_pkts_sent; 183 uint32 signal_only_pkts_freed; 184#endif 185} athost_wl_stat_counters_t; 186 187#ifdef PROP_TXSTATUS_DEBUG 188#define WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac) do { \ 189 (ctx)->stats.fifo_credits_sent[(ac)]++;} while (0) 190#define WLFC_HOST_FIFO_CREDIT_INC_BACKCTRS(ctx, ac) do { \ 191 (ctx)->stats.fifo_credits_back[(ac)]++;} while (0) 192#define WLFC_HOST_FIFO_DROPPEDCTR_INC(ctx, ac) do { \ 193 (ctx)->stats.dropped_qfull[(ac)]++;} while (0) 194#else 195#define WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac) do {} while (0) 196#define WLFC_HOST_FIFO_CREDIT_INC_BACKCTRS(ctx, ac) do {} while (0) 197#define WLFC_HOST_FIFO_DROPPEDCTR_INC(ctx, ac) do {} while (0) 198#endif 199 200#define WLFC_FCMODE_NONE 0 201#define WLFC_FCMODE_IMPLIED_CREDIT 1 202#define WLFC_FCMODE_EXPLICIT_CREDIT 2 203 204/* How long to defer borrowing in milliseconds */ 205#define WLFC_BORROW_DEFER_PERIOD_MS 100 206 207/* Mask to represent available ACs (note: BC/MC is ignored */ 208#define WLFC_AC_MASK 0xF 209 210/* Mask to check for only on-going AC_BE traffic */ 211#define WLFC_AC_BE_TRAFFIC_ONLY 0xD 212 213typedef struct athost_wl_status_info { 214 uint8 last_seqid_to_wlc; 215 216 /* OSL handle */ 217 osl_t* osh; 218 /* dhd pub */ 219 void* dhdp; 220 221 /* stats */ 222 athost_wl_stat_counters_t stats; 223 224 /* the additional ones are for bc/mc and ATIM FIFO */ 225 int FIFO_credit[AC_COUNT + 2]; 226 227 /* Credit borrow counts for each FIFO from each of the other FIFOs */ 228 int credits_borrowed[AC_COUNT + 2][AC_COUNT + 2]; 229 230 struct pktq SENDQ; 231 232 /* packet hanger and MAC->handle lookup table */ 233 void* hanger; 234 struct { 235 /* table for individual nodes */ 236 wlfc_mac_descriptor_t nodes[WLFC_MAC_DESC_TABLE_SIZE]; 237 /* table for interfaces */ 238 wlfc_mac_descriptor_t interfaces[WLFC_MAX_IFNUM]; 239 /* OS may send packets to unknown (unassociated) destinations */ 240 /* A place holder for bc/mc and packets to unknown destinations */ 241 wlfc_mac_descriptor_t other; 242 } destination_entries; 243 /* token position for different priority packets */ 244 uint8 token_pos[AC_COUNT+1]; 245 /* ON/OFF state for flow control to the host network interface */ 246 uint8 hostif_flow_state[WLFC_MAX_IFNUM]; 247 uint8 host_ifidx; 248 /* to flow control an OS interface */ 249 uint8 toggle_host_if; 250 251 /* 252 Mode in which the dhd flow control shall operate. Must be set before 253 traffic starts to the device. 254 0 - Do not do any proptxtstatus flow control 255 1 - Use implied credit from a packet status 256 2 - Use explicit credit 257 */ 258 uint8 proptxstatus_mode; 259 260 /* To borrow credits */ 261 uint8 allow_credit_borrow; 262 263 /* Timestamp to compute how long to defer borrowing for */ 264 uint32 borrow_defer_timestamp; 265 266} athost_wl_status_info_t; 267 268int dhd_wlfc_enable(dhd_pub_t *dhd); 269int dhd_wlfc_interface_event(struct dhd_info *, 270 ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea); 271int dhd_wlfc_FIFOcreditmap_event(struct dhd_info *dhd, uint8* event_data); 272int dhd_wlfc_event(struct dhd_info *dhd); 273int dhd_os_wlfc_block(dhd_pub_t *pub); 274int dhd_os_wlfc_unblock(dhd_pub_t *pub); 275 276#endif /* __wlfc_host_driver_definitions_h__ */ 277