xref: /wlan-dirver/qca-wifi-host-cmn/htc/htc_internal.h (revision a4b8d357569709a7889c418ba927c180e2cd45dc)
1 /*
2  * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
3  *
4  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5  *
6  *
7  * Permission to use, copy, modify, and/or distribute this software for
8  * any purpose with or without fee is hereby granted, provided that the
9  * above copyright notice and this permission notice appear in all
10  * copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19  * PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 /*
23  * This file was originally distributed by Qualcomm Atheros, Inc.
24  * under proprietary terms before Copyright ownership was assigned
25  * to the Linux Foundation.
26  */
27 
28 #ifndef _HTC_INTERNAL_H_
29 #define _HTC_INTERNAL_H_
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif /* __cplusplus */
34 
35 #include "htc_api.h"
36 #include "htc_packet.h"
37 #include <hif.h>
38 #include <htc.h>
39 #include <qdf_atomic.h>
40 #include <qdf_event.h>
41 #include <qdf_lock.h>
42 #include <qdf_nbuf.h>
43 #include <qdf_timer.h>
44 #include <qdf_types.h>
45 
46 /* HTC operational parameters */
47 #define HTC_TARGET_RESPONSE_TIMEOUT         2000        /* in ms */
48 #define HTC_TARGET_DEBUG_INTR_MASK          0x01
49 #define HTC_TARGET_CREDIT_INTR_MASK         0xF0
50 #define HTC_MIN_MSG_PER_BUNDLE              2
51 #if defined(HIF_USB)
52 #define HTC_MAX_MSG_PER_BUNDLE_RX           11
53 #define HTC_MAX_MSG_PER_BUNDLE_TX           8
54 #else
55 #define HTC_MAX_MSG_PER_BUNDLE_RX           64
56 #define HTC_MAX_MSG_PER_BUNDLE              16
57 #define HTC_MAX_MSG_PER_BUNDLE_TX           32
58 #endif
59 
60 /*
61  * HTC_MAX_TX_BUNDLE_SEND_LIMIT -
62  * This value is in units of tx frame fragments.
63  * It needs to be at least as large as the maximum number of tx frames in a
64  * HTC download bundle times the average number of fragments in each such frame
65  * (In certain operating systems, such as Linux, we expect to only have
66  * a single fragment per frame anyway.)
67  */
68 #define HTC_MAX_TX_BUNDLE_SEND_LIMIT        255
69 
70 #define HTC_PACKET_CONTAINER_ALLOCATION     32
71 #define NUM_CONTROL_TX_BUFFERS              2
72 #define HTC_CONTROL_BUFFER_SIZE             (HTC_MAX_CONTROL_MESSAGE_LENGTH + \
73 					     HTC_HDR_LENGTH)
74 #define HTC_CONTROL_BUFFER_ALIGN            32
75 #define HTC_TARGET_RESPONSE_POLL_MS         10
76 #if !defined(A_SIMOS_DEVHOST)
77 #define HTC_TARGET_MAX_RESPONSE_POLL        200 /* actual HW */
78 #else
79 #define HTC_TARGET_MAX_RESPONSE_POLL        600 /* host + target simulation */
80 #endif
81 
82 #define HTC_SERVICE_TX_PACKET_TAG  HTC_TX_PACKET_TAG_INTERNAL
83 
84 #define HTC_CREDIT_HISTORY_MAX              1024
85 
86 #define HTC_IS_EPPING_ENABLED(_x)           ((_x) == QDF_GLOBAL_EPPING_MODE)
87 
88 enum htc_credit_exchange_type {
89 	HTC_REQUEST_CREDIT,
90 	HTC_PROCESS_CREDIT_REPORT,
91 	HTC_SUSPEND_ACK,
92 	HTC_SUSPEND_NACK,
93 	HTC_INITIAL_WAKE_UP,
94 };
95 
96 static inline const char*
97 htc_credit_exchange_type_str(enum htc_credit_exchange_type type)
98 {
99 	switch (type) {
100 	case HTC_REQUEST_CREDIT:
101 		return "HTC_REQUEST_CREDIT";
102 	case HTC_PROCESS_CREDIT_REPORT:
103 		return "HTC_PROCESS_CREDIT_REPORT";
104 	case HTC_SUSPEND_ACK:
105 		return "HTC_SUSPEND_ACK";
106 	case HTC_SUSPEND_NACK:
107 		return "HTC_SUSPEND_NACK";
108 	case HTC_INITIAL_WAKE_UP:
109 		return "HTC_INITIAL_WAKE_UP";
110 	default:
111 		return "Unknown htc_credit_exchange_type";
112 	}
113 }
114 
115 struct HTC_CREDIT_HISTORY {
116 	enum htc_credit_exchange_type type;
117 	uint64_t time;
118 	uint32_t tx_credit;
119 	uint32_t htc_tx_queue_depth;
120 };
121 
122 typedef struct _HTC_ENDPOINT {
123 	HTC_ENDPOINT_ID Id;
124 
125 	/* service ID this endpoint is bound to
126 	 * non-zero value means this endpoint is in use
127 	 */
128 	HTC_SERVICE_ID service_id;
129 
130 	/* callbacks associated with this endpoint */
131 	struct htc_ep_callbacks EpCallBacks;
132 	/* HTC frame buffer TX queue */
133 	HTC_PACKET_QUEUE TxQueue;
134 	/* max depth of the TX queue before calling driver's full handler */
135 	int MaxTxQueueDepth;
136 	/* max length of endpoint message */
137 	int MaxMsgLength;
138 	uint8_t UL_PipeID;
139 	uint8_t DL_PipeID;
140 	/* Need to call HIF to get tx completion callbacks? */
141 	int ul_is_polled;
142 	qdf_timer_t ul_poll_timer;
143 	int ul_poll_timer_active;
144 	int ul_outstanding_cnt;
145 	/* Need to call HIF to fetch rx?  (Not currently supported.) */
146 	int dl_is_polled;
147 	/* not currently supported */
148 	/* qdf_timer_t dl_poll_timer; */
149 
150 	/* lookup queue to match netbufs to htc packets */
151 	HTC_PACKET_QUEUE TxLookupQueue;
152 	/* temporary hold queue for back compatibility */
153 	HTC_PACKET_QUEUE RxBufferHoldQueue;
154 	/* TX seq no (helpful) for debugging */
155 	uint8_t SeqNo;
156 	/* serialization */
157 	qdf_atomic_t TxProcessCount;
158 	struct _HTC_TARGET *target;
159 	/* TX credits available on this endpoint */
160 	int TxCredits;
161 	/* size in bytes of each credit (set by HTC) */
162 	int TxCreditSize;
163 	/* credits required per max message (precalculated) */
164 	int TxCreditsPerMaxMsg;
165 #ifdef HTC_EP_STAT_PROFILING
166 	/* endpoint statistics */
167 	struct htc_endpoint_stats endpoint_stats;
168 #endif
169 	bool TxCreditFlowEnabled;
170 	bool async_update;  /* packets can be queued asynchronously */
171 } HTC_ENDPOINT;
172 
173 #ifdef HTC_EP_STAT_PROFILING
174 #define INC_HTC_EP_STAT(p, stat, count) ((p)->endpoint_stats.stat += (count))
175 #else
176 #define INC_HTC_EP_STAT(p, stat, count)
177 #endif
178 
179 struct htc_service_tx_credit_allocation {
180 	uint16_t service_id;
181 	uint8_t CreditAllocation;
182 };
183 
184 #define HTC_MAX_SERVICE_ALLOC_ENTRIES 8
185 
186 /* Error codes for HTC layer packet stats*/
187 enum ol_ath_htc_pkt_ecodes {
188 	/* error- get packet at head of HTC_PACKET_Q */
189 	GET_HTC_PKT_Q_FAIL = 0,
190 	HTC_PKT_Q_EMPTY,
191 	HTC_SEND_Q_EMPTY
192 };
193 /* our HTC target state */
194 typedef struct _HTC_TARGET {
195 	struct hif_opaque_softc *hif_dev;
196 	HTC_ENDPOINT endpoint[ENDPOINT_MAX];
197 	qdf_spinlock_t HTCLock;
198 	qdf_spinlock_t HTCRxLock;
199 	qdf_spinlock_t HTCTxLock;
200 	qdf_spinlock_t HTCCreditLock;
201 	uint32_t HTCStateFlags;
202 	void *host_handle;
203 	struct htc_init_info HTCInitInfo;
204 	HTC_PACKET *pHTCPacketStructPool; /* pool of HTC packets */
205 	HTC_PACKET_QUEUE ControlBufferTXFreeList;
206 	uint8_t CtrlResponseBuffer[HTC_MAX_CONTROL_MESSAGE_LENGTH];
207 	int CtrlResponseLength;
208 	qdf_event_t ctrl_response_valid;
209 	bool CtrlResponseProcessing;
210 	int TotalTransmitCredits;
211 	struct htc_service_tx_credit_allocation
212 		ServiceTxAllocTable[HTC_MAX_SERVICE_ALLOC_ENTRIES];
213 	int TargetCreditSize;
214 #ifdef RX_SG_SUPPORT
215 	qdf_nbuf_queue_t RxSgQueue;
216 	bool IsRxSgInprogress;
217 	uint32_t CurRxSgTotalLen;               /* current total length */
218 	uint32_t ExpRxSgTotalLen;               /* expected total length */
219 #endif
220 	qdf_device_t osdev;
221 	struct ol_ath_htc_stats htc_pkt_stats;
222 	HTC_PACKET *pBundleFreeList;
223 	uint32_t ce_send_cnt;
224 	uint32_t TX_comp_cnt;
225 	uint8_t MaxMsgsPerHTCBundle;
226 	qdf_work_t queue_kicker;
227 
228 #ifdef HIF_SDIO
229 	A_UINT16 AltDataCreditSize;
230 #endif
231 	A_UINT32 avail_tx_credits;
232 #if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT)
233 	A_UINT32 rx_bundle_stats[HTC_MAX_MSG_PER_BUNDLE_RX];
234 	A_UINT32 tx_bundle_stats[HTC_MAX_MSG_PER_BUNDLE_TX];
235 #endif
236 
237 	uint32_t con_mode;
238 
239 	/*
240 	 * This flag is from the mboxping tool. It indicates that we cannot
241 	 * drop it. Besides, nodrop pkts have higher priority than normal pkts.
242 	 */
243 	A_BOOL is_nodrop_pkt;
244 
245 	/*
246 	 * Number of WMI endpoints used.
247 	 * Default value is 1. But it should be overidden after htc_create to
248 	 * reflect the actual count.
249 	 */
250 	uint8_t wmi_ep_count;
251 } HTC_TARGET;
252 
253 #if defined ENABLE_BUNDLE_TX
254 #define HTC_TX_BUNDLE_ENABLED(target) (target->MaxMsgsPerHTCBundle > 1)
255 #else
256 #define HTC_TX_BUNDLE_ENABLED(target) 0
257 #endif
258 
259 #if defined ENABLE_BUNDLE_RX
260 #define HTC_RX_BUNDLE_ENABLED(target) (target->MaxMsgsPerHTCBundle > 1)
261 #else
262 #define HTC_RX_BUNDLE_ENABLED(target) 0
263 #endif
264 
265 #define HTC_ENABLE_BUNDLE(target) (target->MaxMsgsPerHTCBundle > 1)
266 
267 #ifdef RX_SG_SUPPORT
268 #define RESET_RX_SG_CONFIG(_target) \
269 do { \
270 	_target->ExpRxSgTotalLen = 0; \
271 	_target->CurRxSgTotalLen = 0; \
272 	_target->IsRxSgInprogress = false; \
273 } while (0)
274 #endif
275 
276 #define HTC_STATE_STOPPING      (1 << 0)
277 #define HTC_STOPPING(t)         ((t)->HTCStateFlags & HTC_STATE_STOPPING)
278 #define LOCK_HTC(t)             qdf_spin_lock_bh(&(t)->HTCLock)
279 #define UNLOCK_HTC(t)           qdf_spin_unlock_bh(&(t)->HTCLock)
280 #define LOCK_HTC_RX(t)          qdf_spin_lock_bh(&(t)->HTCRxLock)
281 #define UNLOCK_HTC_RX(t)        qdf_spin_unlock_bh(&(t)->HTCRxLock)
282 #define LOCK_HTC_TX(t)          qdf_spin_lock_bh(&(t)->HTCTxLock)
283 #define UNLOCK_HTC_TX(t)        qdf_spin_unlock_bh(&(t)->HTCTxLock)
284 #define LOCK_HTC_CREDIT(t)      qdf_spin_lock_bh(&(t)->HTCCreditLock)
285 #define UNLOCK_HTC_CREDIT(t)    qdf_spin_unlock_bh(&(t)->HTCCreditLock)
286 
287 #define GET_HTC_TARGET_FROM_HANDLE(hnd) ((HTC_TARGET *)(hnd))
288 
289 #define IS_TX_CREDIT_FLOW_ENABLED(ep)  ((ep)->TxCreditFlowEnabled)
290 
291 #define HTC_POLL_CLEANUP_PERIOD_MS 10   /* milliseconds */
292 
293 /* Macro to Increment the  HTC_PACKET_ERRORS for Tx.*/
294 #define OL_ATH_HTC_PKT_ERROR_COUNT_INCR(_target, _ecode)	\
295 	do { \
296 		if (_ecode == GET_HTC_PKT_Q_FAIL) \
297 		(_target->htc_pkt_stats.htc_get_pkt_q_fail_count) += 1; \
298 		if (_ecode == HTC_PKT_Q_EMPTY) \
299 		(_target->htc_pkt_stats.htc_pkt_q_empty_count) += 1; \
300 		if (_ecode == HTC_SEND_Q_EMPTY) \
301 		(_target->htc_pkt_stats.htc_send_q_empty_count) += 1; \
302 	} while (0)
303 /* internal HTC functions */
304 
305 QDF_STATUS htc_rx_completion_handler(void *Context, qdf_nbuf_t netbuf,
306 				   uint8_t pipeID);
307 QDF_STATUS htc_tx_completion_handler(void *Context, qdf_nbuf_t netbuf,
308 					unsigned int transferID,
309 					uint32_t toeplitz_hash_result);
310 
311 HTC_PACKET *allocate_htc_bundle_packet(HTC_TARGET *target);
312 void free_htc_bundle_packet(HTC_TARGET *target, HTC_PACKET *pPacket);
313 
314 HTC_PACKET *allocate_htc_packet_container(HTC_TARGET *target);
315 void free_htc_packet_container(HTC_TARGET *target, HTC_PACKET *pPacket);
316 void htc_flush_rx_hold_queue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint);
317 void htc_flush_endpoint_tx(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint,
318 			   HTC_TX_TAG Tag);
319 void htc_recv_init(HTC_TARGET *target);
320 QDF_STATUS htc_wait_recv_ctrl_message(HTC_TARGET *target);
321 void htc_free_control_tx_packet(HTC_TARGET *target, HTC_PACKET *pPacket);
322 HTC_PACKET *htc_alloc_control_tx_packet(HTC_TARGET *target);
323 uint8_t htc_get_credit_allocation(HTC_TARGET *target, uint16_t service_id);
324 void htc_tx_resource_avail_handler(void *context, uint8_t pipeID);
325 void htc_control_rx_complete(void *Context, HTC_PACKET *pPacket);
326 void htc_process_credit_rpt(HTC_TARGET *target,
327 			    HTC_CREDIT_REPORT *pRpt,
328 			    int NumEntries, HTC_ENDPOINT_ID FromEndpoint);
329 void htc_fw_event_handler(void *context, QDF_STATUS status);
330 void htc_send_complete_check_cleanup(void *context);
331 #ifdef FEATURE_RUNTIME_PM
332 void htc_kick_queues(void *context);
333 #endif
334 
335 void htc_credit_record(enum htc_credit_exchange_type type, uint32_t tx_credit,
336 		       uint32_t htc_tx_queue_depth);
337 
338 static inline void htc_send_complete_poll_timer_stop(HTC_ENDPOINT *
339 						     pEndpoint) {
340 	LOCK_HTC_TX(pEndpoint->target);
341 	if (pEndpoint->ul_poll_timer_active) {
342 		/* qdf_timer_stop(&pEndpoint->ul_poll_timer); */
343 		pEndpoint->ul_poll_timer_active = 0;
344 	}
345 	UNLOCK_HTC_TX(pEndpoint->target);
346 }
347 
348 static inline void htc_send_complete_poll_timer_start(HTC_ENDPOINT *
349 						      pEndpoint) {
350 	LOCK_HTC_TX(pEndpoint->target);
351 	if (pEndpoint->ul_outstanding_cnt
352 	    && !pEndpoint->ul_poll_timer_active) {
353 		/* qdf_timer_start(
354 		 * &pEndpoint->ul_poll_timer, HTC_POLL_CLEANUP_PERIOD_MS);
355 		 */
356 		pEndpoint->ul_poll_timer_active = 1;
357 	}
358 	UNLOCK_HTC_TX(pEndpoint->target);
359 }
360 
361 static inline void
362 htc_send_complete_check(HTC_ENDPOINT *pEndpoint, int force) {
363 	/*
364 	 * Stop the polling-cleanup timer that will result in a later call to
365 	 * this function.  It may get started again below, if there are still
366 	 * outsending sends.
367 	 */
368 	htc_send_complete_poll_timer_stop(pEndpoint);
369 	/*
370 	 * Check whether HIF has any prior sends that have finished,
371 	 * have not had the post-processing done.
372 	 */
373 	hif_send_complete_check(pEndpoint->target->hif_dev,
374 				pEndpoint->UL_PipeID, force);
375 	/*
376 	 * If there are still outstanding sends after polling, start a timer
377 	 * to check again a little later.
378 	 */
379 	htc_send_complete_poll_timer_start(pEndpoint);
380 }
381 
382 #ifdef __cplusplus
383 }
384 #endif
385 
386 #ifndef DEBUG_BUNDLE
387 #define DEBUG_BUNDLE 0
388 #endif
389 
390 #if defined(HIF_SDIO) || defined(HIF_USB)
391 #ifndef ENABLE_BUNDLE_TX
392 #define ENABLE_BUNDLE_TX 1
393 #endif
394 
395 #ifndef ENABLE_BUNDLE_RX
396 #define ENABLE_BUNDLE_RX 1
397 #endif
398 #endif /*defined(HIF_SDIO) || defined(HIF_USB)*/
399 #endif /* !_HTC_HOST_INTERNAL_H_ */
400