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