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