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