1 /* 2 * Copyright (C) 1999-2013, 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 398418 2013-04-24 15:18:27Z $ 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 #define WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED 3 33 34 #define WLFC_PKTID_HSLOT_MASK 0xffff /* allow 16 bits only */ 35 #define WLFC_PKTID_HSLOT_SHIFT 8 36 37 /* x -> TXSTATUS TAG to/from firmware */ 38 #define WLFC_PKTID_HSLOT_GET(x) \ 39 (((x) >> WLFC_PKTID_HSLOT_SHIFT) & WLFC_PKTID_HSLOT_MASK) 40 #define WLFC_PKTID_HSLOT_SET(var, slot) \ 41 ((var) = ((var) & ~(WLFC_PKTID_HSLOT_MASK << WLFC_PKTID_HSLOT_SHIFT)) | \ 42 (((slot) & WLFC_PKTID_HSLOT_MASK) << WLFC_PKTID_HSLOT_SHIFT)) 43 44 #define WLFC_PKTID_FREERUNCTR_MASK 0xff 45 46 #define WLFC_PKTID_FREERUNCTR_GET(x) ((x) & WLFC_PKTID_FREERUNCTR_MASK) 47 #define WLFC_PKTID_FREERUNCTR_SET(var, ctr) \ 48 ((var) = (((var) & ~WLFC_PKTID_FREERUNCTR_MASK) | \ 49 (((ctr) & WLFC_PKTID_FREERUNCTR_MASK)))) 50 51 #define WLFC_PKTQ_PENQ(pq, prec, p) ((pktq_full((pq)) || pktq_pfull((pq), (prec)))? \ 52 NULL : pktq_penq((pq), (prec), (p))) 53 #define WLFC_PKTQ_PENQ_HEAD(pq, prec, p) ((pktq_full((pq)) || pktq_pfull((pq), (prec))) ? \ 54 NULL : pktq_penq_head((pq), (prec), (p))) 55 56 typedef enum ewlfc_packet_state { 57 eWLFC_PKTTYPE_NEW, 58 eWLFC_PKTTYPE_DELAYED, 59 eWLFC_PKTTYPE_SUPPRESSED, 60 eWLFC_PKTTYPE_MAX 61 } ewlfc_packet_state_t; 62 63 typedef enum ewlfc_mac_entry_action { 64 eWLFC_MAC_ENTRY_ACTION_ADD, 65 eWLFC_MAC_ENTRY_ACTION_DEL, 66 eWLFC_MAC_ENTRY_ACTION_UPDATE, 67 eWLFC_MAC_ENTRY_ACTION_MAX 68 } ewlfc_mac_entry_action_t; 69 70 typedef struct wlfc_hanger_item { 71 uint8 state; 72 uint8 gen; 73 uint8 pad[2]; 74 uint32 identifier; 75 void* pkt; 76 #ifdef PROP_TXSTATUS_DEBUG 77 uint32 push_time; 78 #endif 79 } wlfc_hanger_item_t; 80 81 typedef struct wlfc_hanger { 82 int max_items; 83 uint32 pushed; 84 uint32 popped; 85 uint32 failed_to_push; 86 uint32 failed_to_pop; 87 uint32 failed_slotfind; 88 uint32 slot_pos; 89 wlfc_hanger_item_t items[1]; 90 } wlfc_hanger_t; 91 92 #define WLFC_HANGER_SIZE(n) ((sizeof(wlfc_hanger_t) - \ 93 sizeof(wlfc_hanger_item_t)) + ((n)*sizeof(wlfc_hanger_item_t))) 94 95 #define WLFC_STATE_OPEN 1 96 #define WLFC_STATE_CLOSE 2 97 98 #define WLFC_PSQ_PREC_COUNT ((AC_COUNT + 1) * 2) /* 2 for each AC traffic and bc/mc */ 99 100 #define WLFC_PSQ_LEN 2048 101 102 #define WLFC_FLOWCONTROL_HIWATER (2048 - 256) 103 #define WLFC_FLOWCONTROL_LOWATER 256 104 105 typedef struct wlfc_mac_descriptor { 106 uint8 occupied; 107 uint8 interface_id; 108 uint8 iftype; 109 uint8 state; 110 uint8 ac_bitmap; /* for APSD */ 111 uint8 requested_credit; 112 uint8 requested_packet; 113 uint8 ea[ETHER_ADDR_LEN]; 114 /* 115 maintain (MAC,AC) based seq count for 116 packets going to the device. As well as bc/mc. 117 */ 118 uint8 seq[AC_COUNT + 1]; 119 uint8 generation; 120 struct pktq psq; 121 /* The AC pending bitmap that was reported to the fw at last change */ 122 uint8 traffic_lastreported_bmp; 123 /* The new AC pending bitmap */ 124 uint8 traffic_pending_bmp; 125 /* 1= send on next opportunity */ 126 uint8 send_tim_signal; 127 uint8 mac_handle; 128 /* Number of packets in transit for this entry. */ 129 uint transit_count; 130 /* Numbe of suppression to wait before evict from delayQ */ 131 uint suppr_transit_count; 132 /* Used when a new suppress is detected to track the number of 133 * packets getting suppressed 134 */ 135 uint suppress_count; 136 /* flag. TRUE when in suppress state */ 137 uint8 suppressed; 138 uint8 deleting; 139 140 #ifdef PROP_TXSTATUS_DEBUG 141 uint32 dstncredit_sent_packets; 142 uint32 dstncredit_acks; 143 uint32 opened_ct; 144 uint32 closed_ct; 145 #endif 146 } wlfc_mac_descriptor_t; 147 148 #define WLFC_DECR_SEQCOUNT(entry, prec) do { if (entry->seq[(prec)] == 0) {\ 149 entry->seq[prec] = 0xff; } else entry->seq[prec]--;} while (0) 150 151 #define WLFC_INCR_SEQCOUNT(entry, prec) entry->seq[(prec)]++ 152 #define WLFC_SEQCOUNT(entry, prec) entry->seq[(prec)] 153 154 typedef struct athost_wl_stat_counters { 155 uint32 pktin; 156 uint32 pkt2bus; 157 uint32 pktdropped; 158 uint32 tlv_parse_failed; 159 uint32 rollback; 160 uint32 rollback_failed; 161 uint32 delayq_full_error; 162 uint32 credit_request_failed; 163 uint32 packet_request_failed; 164 uint32 mac_update_failed; 165 uint32 psmode_update_failed; 166 uint32 interface_update_failed; 167 uint32 wlfc_header_only_pkt; 168 uint32 txstatus_in; 169 uint32 d11_suppress; 170 uint32 wl_suppress; 171 uint32 bad_suppress; 172 uint32 pkt_freed; 173 uint32 pkt_free_err; 174 uint32 psq_wlsup_retx; 175 uint32 psq_wlsup_enq; 176 uint32 psq_d11sup_retx; 177 uint32 psq_d11sup_enq; 178 uint32 psq_hostq_retx; 179 uint32 psq_hostq_enq; 180 uint32 mac_handle_notfound; 181 uint32 wlc_tossed_pkts; 182 uint32 dhd_hdrpulls; 183 uint32 generic_error; 184 /* an extra one for bc/mc traffic */ 185 uint32 send_pkts[AC_COUNT + 1]; 186 #ifdef PROP_TXSTATUS_DEBUG 187 /* all pkt2bus -> txstatus latency accumulated */ 188 uint32 latency_sample_count; 189 uint32 total_status_latency; 190 uint32 latency_most_recent; 191 int idx_delta; 192 uint32 deltas[10]; 193 uint32 fifo_credits_sent[6]; 194 uint32 fifo_credits_back[6]; 195 uint32 dropped_qfull[6]; 196 uint32 signal_only_pkts_sent; 197 uint32 signal_only_pkts_freed; 198 #endif 199 } athost_wl_stat_counters_t; 200 201 #ifdef PROP_TXSTATUS_DEBUG 202 #define WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac) do { \ 203 (ctx)->stats.fifo_credits_sent[(ac)]++;} while (0) 204 #define WLFC_HOST_FIFO_CREDIT_INC_BACKCTRS(ctx, ac) do { \ 205 (ctx)->stats.fifo_credits_back[(ac)]++;} while (0) 206 #define WLFC_HOST_FIFO_DROPPEDCTR_INC(ctx, ac) do { \ 207 (ctx)->stats.dropped_qfull[(ac)]++;} while (0) 208 #else 209 #define WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac) do {} while (0) 210 #define WLFC_HOST_FIFO_CREDIT_INC_BACKCTRS(ctx, ac) do {} while (0) 211 #define WLFC_HOST_FIFO_DROPPEDCTR_INC(ctx, ac) do {} while (0) 212 #endif 213 214 #define WLFC_FCMODE_NONE 0 215 #define WLFC_FCMODE_IMPLIED_CREDIT 1 216 #define WLFC_FCMODE_EXPLICIT_CREDIT 2 217 218 /* How long to defer borrowing in milliseconds */ 219 #define WLFC_BORROW_DEFER_PERIOD_MS 100 220 221 /* Mask to represent available ACs (note: BC/MC is ignored */ 222 #define WLFC_AC_MASK 0xF 223 224 /* Mask to check for only on-going AC_BE traffic */ 225 #define WLFC_AC_BE_TRAFFIC_ONLY 0xD 226 227 typedef struct athost_wl_status_info { 228 uint8 last_seqid_to_wlc; 229 230 /* OSL handle */ 231 osl_t* osh; 232 /* dhd pub */ 233 void* dhdp; 234 235 /* stats */ 236 athost_wl_stat_counters_t stats; 237 238 /* the additional ones are for bc/mc and ATIM FIFO */ 239 int FIFO_credit[AC_COUNT + 2]; 240 241 /* Credit borrow counts for each FIFO from each of the other FIFOs */ 242 int credits_borrowed[AC_COUNT + 2][AC_COUNT + 2]; 243 244 /* packet hanger and MAC->handle lookup table */ 245 void* hanger; 246 struct { 247 /* table for individual nodes */ 248 wlfc_mac_descriptor_t nodes[WLFC_MAC_DESC_TABLE_SIZE]; 249 /* table for interfaces */ 250 wlfc_mac_descriptor_t interfaces[WLFC_MAX_IFNUM]; 251 /* OS may send packets to unknown (unassociated) destinations */ 252 /* A place holder for bc/mc and packets to unknown destinations */ 253 wlfc_mac_descriptor_t other; 254 } destination_entries; 255 /* token position for different priority packets */ 256 uint8 token_pos[AC_COUNT+1]; 257 /* ON/OFF state for flow control to the host network interface */ 258 uint8 hostif_flow_state[WLFC_MAX_IFNUM]; 259 uint8 host_ifidx; 260 /* to flow control an OS interface */ 261 uint8 toggle_host_if; 262 263 /* 264 Mode in which the dhd flow control shall operate. Must be set before 265 traffic starts to the device. 266 0 - Do not do any proptxtstatus flow control 267 1 - Use implied credit from a packet status 268 2 - Use explicit credit 269 */ 270 uint8 proptxstatus_mode; 271 272 /* To borrow credits */ 273 uint8 allow_credit_borrow; 274 275 /* Timestamp to compute how long to defer borrowing for */ 276 uint32 borrow_defer_timestamp; 277 278 } athost_wl_status_info_t; 279 280 int dhd_wlfc_enable(dhd_pub_t *dhd); 281 int dhd_wlfc_interface_event(struct dhd_info *, 282 ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea); 283 int dhd_wlfc_FIFOcreditmap_event(struct dhd_info *dhd, uint8* event_data); 284 int dhd_wlfc_event(struct dhd_info *dhd); 285 int dhd_os_wlfc_block(dhd_pub_t *pub); 286 int dhd_os_wlfc_unblock(dhd_pub_t *pub); 287 288 void dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf); 289 int dhd_wlfc_init(dhd_pub_t *dhd); 290 void dhd_wlfc_deinit(dhd_pub_t *dhd); 291 int dhd_wlfc_parse_header_info(dhd_pub_t *dhd, void* pktbuf, int tlv_hdr_len, 292 uchar *reorder_info_buf, uint *reorder_info_len); 293 int dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, 294 void* commit_ctx, void *pktbuf); 295 void dhd_wlfc_cleanup(dhd_pub_t *dhd, ifpkt_cb_t fn, int arg); 296 bool ifpkt_fn(void* p, int ifid); 297 #endif /* __wlfc_host_driver_definitions_h__ */ 298