• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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