xref: /wlan-driver/qcacld-3.0/core/dp/txrx/ol_txrx.c (revision 5113495b16420b49004c444715d2daae2066e7dc) !
1 /*
2  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 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 /*=== includes ===*/
21 /* header files for OS primitives */
22 #include <osdep.h>              /* uint32_t, etc. */
23 #include <qdf_mem.h>         /* qdf_mem_malloc,free */
24 #include <qdf_types.h>          /* qdf_device_t, qdf_print */
25 #include <qdf_lock.h>           /* qdf_spinlock */
26 #include <qdf_atomic.h>         /* qdf_atomic_read */
27 #include <qdf_debugfs.h>
28 
29 /* header files for utilities */
30 #include "queue.h"          /* TAILQ */
31 
32 /* header files for configuration API */
33 #include <ol_cfg.h>             /* ol_cfg_is_high_latency */
34 #include <ol_if_athvar.h>
35 
36 /* header files for HTT API */
37 #include <ol_htt_api.h>
38 #include <ol_htt_tx_api.h>
39 
40 /* header files for our own APIs */
41 #include <ol_txrx_api.h>
42 #include <ol_txrx_dbg.h>
43 #include <cdp_txrx_ocb.h>
44 #include <ol_txrx_ctrl_api.h>
45 #include <cdp_txrx_stats.h>
46 #include <ol_txrx_osif_api.h>
47 /* header files for our internal definitions */
48 #include <ol_txrx_internal.h>   /* TXRX_ASSERT, etc. */
49 #include <wdi_event.h>          /* WDI events */
50 #include <ol_tx.h>              /* ol_tx_ll */
51 #include <ol_rx.h>              /* ol_rx_deliver */
52 #include <ol_txrx_peer_find.h>  /* ol_txrx_peer_find_attach, etc. */
53 #include <ol_rx_pn.h>           /* ol_rx_pn_check, etc. */
54 #include <ol_rx_fwd.h>          /* ol_rx_fwd_check, etc. */
55 #include <ol_rx_reorder_timeout.h>      /* OL_RX_REORDER_TIMEOUT_INIT, etc. */
56 #include <ol_rx_reorder.h>
57 #include <ol_tx_send.h>         /* ol_tx_discard_target_frms */
58 #include <ol_tx_desc.h>         /* ol_tx_desc_frame_free */
59 #include <ol_tx_queue.h>
60 #include <ol_tx_sched.h>           /* ol_tx_sched_attach, etc. */
61 #include <ol_txrx.h>
62 #include <ol_txrx_types.h>
63 #include <ol_cfg.h>
64 #include <cdp_txrx_flow_ctrl_legacy.h>
65 #include <cdp_txrx_cmn_reg.h>
66 #include <cdp_txrx_bus.h>
67 #include <cdp_txrx_ipa.h>
68 #include <cdp_txrx_pmf.h>
69 #include "wma.h"
70 #include "hif.h"
71 #include "hif_main.h"
72 #include <cdp_txrx_peer_ops.h>
73 #ifndef REMOVE_PKT_LOG
74 #include "pktlog_ac.h"
75 #endif
76 #include <wlan_policy_mgr_api.h>
77 #include "epping_main.h"
78 #include <a_types.h>
79 #include <cdp_txrx_handle.h>
80 #include <cdp_txrx_cmn_reg.h>
81 #include "wlan_qct_sys.h"
82 
83 #include <htt_internal.h>
84 #include <ol_txrx_ipa.h>
85 #include "wlan_roam_debug.h"
86 #include "cfg_ucfg_api.h"
87 #ifdef DP_SUPPORT_RECOVERY_NOTIFY
88 #include <qdf_notifier.h>
89 #include <qdf_hang_event_notifier.h>
90 #endif
91 
92 #define DPT_DEBUGFS_PERMS	(QDF_FILE_USR_READ |	\
93 				QDF_FILE_USR_WRITE |	\
94 				QDF_FILE_GRP_READ |	\
95 				QDF_FILE_OTH_READ)
96 
97 #define DPT_DEBUGFS_NUMBER_BASE	10
98 /**
99  * enum dpt_set_param_debugfs - dpt set params
100  * @DPT_SET_PARAM_PROTO_BITMAP : set proto bitmap
101  * @DPT_SET_PARAM_NR_RECORDS: set num of records
102  * @DPT_SET_PARAM_VERBOSITY: set verbosity
103  */
104 enum dpt_set_param_debugfs {
105 	DPT_SET_PARAM_PROTO_BITMAP = 1,
106 	DPT_SET_PARAM_NR_RECORDS = 2,
107 	DPT_SET_PARAM_VERBOSITY = 3,
108 	DPT_SET_PARAM_NUM_RECORDS_TO_DUMP = 4,
109 	DPT_SET_PARAM_MAX,
110 };
111 
112 static void ol_vdev_rx_set_intrabss_fwd(struct cdp_soc_t *soc_hdl,
113 					uint8_t vdev_id, bool val);
114 uint32_t ol_txrx_get_tx_pending(struct cdp_pdev *pdev_handle);
115 extern void
116 ol_txrx_set_wmm_param(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
117 		      struct ol_tx_wmm_param_t wmm_param);
118 
119 /* thresh for peer's cached buf queue beyond which the elements are dropped */
120 #define OL_TXRX_CACHED_BUFQ_THRESH 128
121 
122 #ifdef DP_SUPPORT_RECOVERY_NOTIFY
123 static
ol_peer_recovery_notifier_cb(struct notifier_block * block,unsigned long state,void * data)124 int ol_peer_recovery_notifier_cb(struct notifier_block *block,
125 				 unsigned long state, void *data)
126 {
127 	struct qdf_notifer_data *notif_data = data;
128 	qdf_notif_block *notif_block;
129 	struct ol_txrx_peer_t *peer;
130 	struct peer_hang_data hang_data = {0};
131 	enum peer_debug_id_type dbg_id;
132 
133 	if (!data || !block)
134 		return -EINVAL;
135 
136 	notif_block = qdf_container_of(block, qdf_notif_block, notif_block);
137 
138 	peer = notif_block->priv_data;
139 	if (!peer)
140 		return -EINVAL;
141 
142 	if (notif_data->offset + sizeof(struct peer_hang_data) >
143 			QDF_WLAN_HANG_FW_OFFSET)
144 		return NOTIFY_STOP_MASK;
145 
146 	QDF_HANG_EVT_SET_HDR(&hang_data.tlv_header,
147 			     HANG_EVT_TAG_DP_PEER_INFO,
148 			     QDF_HANG_GET_STRUCT_TLVLEN(struct peer_hang_data));
149 
150 	qdf_mem_copy(&hang_data.peer_mac_addr, &peer->mac_addr.raw,
151 		     QDF_MAC_ADDR_SIZE);
152 
153 	for (dbg_id = 0; dbg_id < PEER_DEBUG_ID_MAX; dbg_id++)
154 		if (qdf_atomic_read(&peer->access_list[dbg_id]))
155 			hang_data.peer_timeout_bitmask |= (1 << dbg_id);
156 
157 	qdf_mem_copy(notif_data->hang_data + notif_data->offset,
158 		     &hang_data, sizeof(struct peer_hang_data));
159 	notif_data->offset += sizeof(struct peer_hang_data);
160 
161 	return 0;
162 }
163 
164 static qdf_notif_block ol_peer_recovery_notifier = {
165 	.notif_block.notifier_call = ol_peer_recovery_notifier_cb,
166 };
167 
168 static
ol_register_peer_recovery_notifier(struct ol_txrx_peer_t * peer)169 QDF_STATUS ol_register_peer_recovery_notifier(struct ol_txrx_peer_t *peer)
170 {
171 	ol_peer_recovery_notifier.priv_data = peer;
172 
173 	return qdf_hang_event_register_notifier(&ol_peer_recovery_notifier);
174 }
175 
176 static
ol_unregister_peer_recovery_notifier(void)177 QDF_STATUS ol_unregister_peer_recovery_notifier(void)
178 {
179 	return qdf_hang_event_unregister_notifier(&ol_peer_recovery_notifier);
180 }
181 #else
182 static inline
ol_register_peer_recovery_notifier(struct ol_txrx_peer_t * peer)183 QDF_STATUS ol_register_peer_recovery_notifier(struct ol_txrx_peer_t *peer)
184 {
185 	return QDF_STATUS_SUCCESS;
186 }
187 
188 static
ol_unregister_peer_recovery_notifier(void)189 QDF_STATUS ol_unregister_peer_recovery_notifier(void)
190 {
191 	return QDF_STATUS_SUCCESS;
192 }
193 #endif
194 
195 /**
196  * ol_tx_mark_first_wakeup_packet() - set flag to indicate that
197  *    fw is compatible for marking first packet after wow wakeup
198  * @soc_hdl: Datapath soc handle
199  * @pdev_id: id of data path pdev handle
200  * @value: 1 for enabled/ 0 for disabled
201  *
202  * Return: None
203  */
ol_tx_mark_first_wakeup_packet(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,uint8_t value)204 static void ol_tx_mark_first_wakeup_packet(struct cdp_soc_t *soc_hdl,
205 					   uint8_t pdev_id, uint8_t value)
206 {
207 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
208 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
209 
210 	if (!pdev) {
211 		ol_txrx_err("pdev is NULL");
212 		return;
213 	}
214 
215 	htt_mark_first_wakeup_packet(pdev->htt_pdev, value);
216 }
217 
218 /**
219  * ol_tx_set_is_mgmt_over_wmi_enabled() - set flag to indicate that mgmt over
220  *                                        wmi is enabled or not.
221  * @value: 1 for enabled/ 0 for disable
222  *
223  * Return: None
224  */
ol_tx_set_is_mgmt_over_wmi_enabled(uint8_t value)225 void ol_tx_set_is_mgmt_over_wmi_enabled(uint8_t value)
226 {
227 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
228 	ol_txrx_pdev_handle pdev;
229 
230 	if (qdf_unlikely(!soc))
231 		return;
232 
233 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
234 	if (!pdev) {
235 		ol_txrx_err("pdev is NULL");
236 		return;
237 	}
238 
239 	pdev->is_mgmt_over_wmi_enabled = value;
240 }
241 
242 /**
243  * ol_tx_get_is_mgmt_over_wmi_enabled() - get value of is_mgmt_over_wmi_enabled
244  *
245  * Return: is_mgmt_over_wmi_enabled
246  */
ol_tx_get_is_mgmt_over_wmi_enabled(void)247 uint8_t ol_tx_get_is_mgmt_over_wmi_enabled(void)
248 {
249 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
250 	ol_txrx_pdev_handle pdev;
251 
252 	if (qdf_unlikely(!soc))
253 		return 0;
254 
255 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
256 	if (!pdev) {
257 		ol_txrx_err("pdev is NULL");
258 		return 0;
259 	}
260 
261 	return pdev->is_mgmt_over_wmi_enabled;
262 }
263 
264 
265 #ifdef QCA_SUPPORT_TXRX_LOCAL_PEER_ID
266 static void *
ol_txrx_find_peer_by_addr_and_vdev(struct cdp_pdev * ppdev,struct cdp_vdev * pvdev,uint8_t * peer_addr)267 ol_txrx_find_peer_by_addr_and_vdev(struct cdp_pdev *ppdev,
268 	struct cdp_vdev *pvdev, uint8_t *peer_addr)
269 {
270 	struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)ppdev;
271 	struct ol_txrx_vdev_t *vdev = (struct ol_txrx_vdev_t *)pvdev;
272 	struct ol_txrx_peer_t *peer;
273 
274 	peer = ol_txrx_peer_vdev_find_hash(pdev, vdev, peer_addr, 0, 1);
275 	if (!peer)
276 		return NULL;
277 	ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_INTERNAL);
278 	return peer;
279 }
280 
281 /**
282  * ol_txrx_get_vdevid() - Get virtual interface id which peer registered
283  * @soc_hdl - data path soc handle
284  * @peer_mac - peer mac address
285  * @vdev_id - virtual interface id which peer registered
286  *
287  * Get virtual interface id which peer registered
288  *
289  * Return: QDF_STATUS_SUCCESS registration success
290  *         QDF_STATUS_E_NOSUPPORT not support this feature
291  */
ol_txrx_get_vdevid(struct cdp_soc_t * soc_hdl,uint8_t * peer_mac,uint8_t * vdev_id)292 static QDF_STATUS ol_txrx_get_vdevid(struct cdp_soc_t *soc_hdl,
293 				     uint8_t *peer_mac, uint8_t *vdev_id)
294 {
295 	uint8_t pdev_id = OL_TXRX_PDEV_ID;
296 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
297 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
298 	struct ol_txrx_peer_t *peer =
299 		ol_txrx_peer_find_hash_find_get_ref(pdev, peer_mac, 0, 1,
300 						    PEER_DEBUG_ID_OL_INTERNAL);
301 
302 	if (!peer) {
303 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
304 			  "peer argument is null!!");
305 		return QDF_STATUS_E_FAILURE;
306 	}
307 
308 	*vdev_id = peer->vdev->vdev_id;
309 	ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_INTERNAL);
310 
311 	return QDF_STATUS_SUCCESS;
312 }
313 
314 ol_txrx_vdev_handle
ol_txrx_get_vdev_by_peer_addr(struct cdp_pdev * ppdev,struct qdf_mac_addr peer_addr)315 ol_txrx_get_vdev_by_peer_addr(struct cdp_pdev *ppdev,
316 			      struct qdf_mac_addr peer_addr)
317 {
318 	struct ol_txrx_pdev_t *pdev = cdp_pdev_to_ol_txrx_pdev_t(ppdev);
319 	struct ol_txrx_peer_t *peer = NULL;
320 	ol_txrx_vdev_handle vdev;
321 
322 	if (!pdev) {
323 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH,
324 			  "PDEV not found for peer_addr: " QDF_MAC_ADDR_FMT,
325 			  QDF_MAC_ADDR_REF(peer_addr.bytes));
326 		return NULL;
327 	}
328 
329 	peer = ol_txrx_peer_get_ref_by_addr(pdev, peer_addr.bytes,
330 					    PEER_DEBUG_ID_OL_INTERNAL);
331 
332 	if (!peer) {
333 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH,
334 			  "Peer not found for peer_addr:" QDF_MAC_ADDR_FMT,
335 			  QDF_MAC_ADDR_REF(peer_addr.bytes));
336 		return NULL;
337 	}
338 
339 	vdev = peer->vdev;
340 	ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_INTERNAL);
341 
342 	return vdev;
343 }
344 
345 /**
346  * ol_txrx_wrapper_get_vdev_by_peer_addr() - Get vdev handle by peer mac address
347  * @ppdev - data path device instance
348  * @peer_addr - peer mac address
349  *
350  * Get virtual interface handle by local peer mac address
351  *
352  * Return: Virtual interface instance handle
353  *         NULL in case cannot find
354  */
355 static struct cdp_vdev *
ol_txrx_wrapper_get_vdev_by_peer_addr(struct cdp_pdev * ppdev,struct qdf_mac_addr peer_addr)356 ol_txrx_wrapper_get_vdev_by_peer_addr(struct cdp_pdev *ppdev,
357 				      struct qdf_mac_addr peer_addr)
358 {
359 	return (struct cdp_vdev *)ol_txrx_get_vdev_by_peer_addr(ppdev,
360 								peer_addr);
361 }
362 
363 /*
364  * ol_txrx_find_peer_exist - find peer if already exists
365  * @soc_hdl: datapath soc handle
366  * @pdev_id: physical device instance id
367  * @peer_mac_addr: peer mac address
368  *
369  * Return: true or false
370  */
ol_txrx_find_peer_exist(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,uint8_t * peer_addr)371 static bool ol_txrx_find_peer_exist(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
372 				    uint8_t *peer_addr)
373 {
374 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
375 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
376 
377 	if (!pdev)
378 		return false;
379 
380 	return !!ol_txrx_find_peer_by_addr(ol_txrx_pdev_t_to_cdp_pdev(pdev),
381 					   peer_addr);
382 }
383 
384 /*
385  * ol_txrx_find_peer_exist_on_vdev - find if duplicate peer exists
386  * on the given vdev
387  * @soc_hdl: datapath soc handle
388  * @vdev_id: vdev instance id
389  * @peer_mac_addr: peer mac address
390  *
391  * Return: true or false
392  */
ol_txrx_find_peer_exist_on_vdev(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,uint8_t * peer_addr)393 static bool ol_txrx_find_peer_exist_on_vdev(struct cdp_soc_t *soc_hdl,
394 					    uint8_t vdev_id,
395 					    uint8_t *peer_addr)
396 {
397 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
398 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
399 								     vdev_id);
400 
401 	if (!vdev)
402 		return false;
403 
404 	return !!ol_txrx_find_peer_by_addr_and_vdev(
405 					ol_txrx_pdev_t_to_cdp_pdev(vdev->pdev),
406 					ol_txrx_vdev_t_to_cdp_vdev(vdev),
407 					peer_addr);
408 }
409 
410 /*
411  * ol_txrx_find_peer_exist_on_other_vdev - find if duplicate peer exists
412  * on other than the given vdev
413  * @soc_hdl: datapath soc handle
414  * @vdev_id: vdev instance id
415  * @peer_mac_addr: peer mac address
416  * @max_bssid: max number of bssids
417  *
418  * Return: true or false
419  */
ol_txrx_find_peer_exist_on_other_vdev(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,uint8_t * peer_addr,uint16_t max_bssid)420 static bool ol_txrx_find_peer_exist_on_other_vdev(struct cdp_soc_t *soc_hdl,
421 						  uint8_t vdev_id,
422 						  uint8_t *peer_addr,
423 						  uint16_t max_bssid)
424 {
425 	int i;
426 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
427 	struct ol_txrx_vdev_t *vdev;
428 
429 	for (i = 0; i < max_bssid; i++) {
430 		vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc, i);
431 		/* Need to check vdevs other than the vdev_id */
432 		if (vdev_id == i || !vdev)
433 			continue;
434 		if (ol_txrx_find_peer_by_addr_and_vdev(
435 					ol_txrx_pdev_t_to_cdp_pdev(vdev->pdev),
436 					ol_txrx_vdev_t_to_cdp_vdev(vdev),
437 					peer_addr)) {
438 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
439 				  "%s: Duplicate peer "QDF_MAC_ADDR_FMT" already exist on vdev %d",
440 				  __func__, QDF_MAC_ADDR_REF(peer_addr), i);
441 			return true;
442 		}
443 	}
444 
445 	return false;
446 }
447 
448 /**
449  * ol_txrx_find_peer_by_addr() - find peer via peer mac addr and peer_id
450  * @ppdev: pointer of type cdp_pdev
451  * @peer_addr: peer mac addr
452  *
453  * This function finds a peer with given mac address and returns its peer_id.
454  * Note that this function does not increment the peer->ref_cnt.
455  * This means that the peer may be deleted in some other parallel context after
456  * its been found.
457  *
458  * Return: peer handle if peer is found, NULL if peer is not found.
459  */
ol_txrx_find_peer_by_addr(struct cdp_pdev * ppdev,uint8_t * peer_addr)460 void *ol_txrx_find_peer_by_addr(struct cdp_pdev *ppdev,
461 				uint8_t *peer_addr)
462 {
463 	struct ol_txrx_peer_t *peer;
464 	struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)ppdev;
465 
466 	peer = ol_txrx_peer_find_hash_find_get_ref(pdev, peer_addr, 0, 1,
467 						   PEER_DEBUG_ID_OL_INTERNAL);
468 	if (!peer)
469 		return NULL;
470 	ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_INTERNAL);
471 	return peer;
472 }
473 
474 /**
475  * ol_txrx_peer_get_ref_by_addr() - get peer ref via peer mac addr and peer_id
476  * @pdev: pointer of type ol_txrx_pdev_handle
477  * @peer_addr: peer mac addr
478  *
479  * This function finds the peer with given mac address and returns its peer_id.
480  * Note that this function increments the peer->ref_cnt.
481  * This makes sure that peer will be valid. This also means the caller needs to
482  * call the corresponding API - ol_txrx_peer_release_ref to delete the peer
483  * reference.
484  * Sample usage:
485  *    {
486  *      //the API call below increments the peer->ref_cnt
487  *      peer = ol_txrx_peer_get_ref_by_addr(pdev, peer_addr, peer_id, dbg_id);
488  *
489  *      // Once peer usage is done
490  *
491  *      //the API call below decrements the peer->ref_cnt
492  *       ol_txrx_peer_release_ref(peer, dbg_id);
493  *    }
494  *
495  * Return: peer handle if the peer is found, NULL if peer is not found.
496  */
ol_txrx_peer_get_ref_by_addr(ol_txrx_pdev_handle pdev,u8 * peer_addr,enum peer_debug_id_type dbg_id)497 ol_txrx_peer_handle ol_txrx_peer_get_ref_by_addr(ol_txrx_pdev_handle pdev,
498 						 u8 *peer_addr,
499 						 enum peer_debug_id_type dbg_id)
500 {
501 	struct ol_txrx_peer_t *peer;
502 
503 	peer = ol_txrx_peer_find_hash_find_get_ref(pdev, peer_addr, 0, 1,
504 						   dbg_id);
505 	if (!peer)
506 		return NULL;
507 
508 	return peer;
509 }
510 
511 /**
512  * @brief Find a txrx peer handle from a peer's local ID
513  * @param pdev - the data physical device object
514  * @param local_peer_id - the ID txrx assigned locally to the peer in question
515  * @dbg_id - debug_id to track caller
516  * @return handle to the txrx peer object
517  * @details
518  *  The control SW typically uses the txrx peer handle to refer to the peer.
519  *  In unusual circumstances, if it is infeasible for the control SW maintain
520  *  the txrx peer handle but it can maintain a small integer local peer ID,
521  *  this function allows the peer handled to be retrieved, based on the local
522  *  peer ID.
523  *
524  * Note that this function increments the peer->ref_cnt.
525  * This makes sure that peer will be valid. This also means the caller needs to
526  * call the corresponding API -
527  *          ol_txrx_peer_release_ref
528  *
529  * reference.
530  * Sample usage:
531  *    {
532  *      //the API call below increments the peer->ref_cnt
533  *      peer = ol_txrx_peer_get_ref_by_local_id(pdev,local_peer_id, dbg_id);
534  *
535  *      // Once peer usage is done
536  *
537  *      //the API call below decrements the peer->ref_cnt
538  *      ol_txrx_peer_release_ref(peer, dbg_id);
539  *    }
540  *
541  * Return: peer handle if the peer is found, NULL if peer is not found.
542  */
543 ol_txrx_peer_handle
ol_txrx_peer_get_ref_by_local_id(struct cdp_pdev * ppdev,uint8_t local_peer_id,enum peer_debug_id_type dbg_id)544 ol_txrx_peer_get_ref_by_local_id(struct cdp_pdev *ppdev,
545 			      uint8_t local_peer_id,
546 			      enum peer_debug_id_type dbg_id)
547 {
548 	struct ol_txrx_peer_t *peer = NULL;
549 	struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)ppdev;
550 
551 	if ((local_peer_id == OL_TXRX_INVALID_LOCAL_PEER_ID) ||
552 	    (local_peer_id >= OL_TXRX_NUM_LOCAL_PEER_IDS)) {
553 		return NULL;
554 	}
555 
556 	qdf_spin_lock_bh(&pdev->peer_ref_mutex);
557 	qdf_spin_lock_bh(&pdev->local_peer_ids.lock);
558 	peer = pdev->local_peer_ids.map[local_peer_id];
559 	qdf_spin_unlock_bh(&pdev->local_peer_ids.lock);
560 	if (peer && peer->valid)
561 		ol_txrx_peer_get_ref(peer, dbg_id);
562 	else
563 		peer = NULL;
564 	qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
565 
566 	return peer;
567 }
568 
ol_txrx_local_peer_id_pool_init(struct ol_txrx_pdev_t * pdev)569 static void ol_txrx_local_peer_id_pool_init(struct ol_txrx_pdev_t *pdev)
570 {
571 	int i;
572 
573 	/* point the freelist to the first ID */
574 	pdev->local_peer_ids.freelist = 0;
575 
576 	/* link each ID to the next one */
577 	for (i = 0; i < OL_TXRX_NUM_LOCAL_PEER_IDS; i++) {
578 		pdev->local_peer_ids.pool[i] = i + 1;
579 		pdev->local_peer_ids.map[i] = NULL;
580 	}
581 
582 	/* link the last ID to itself, to mark the end of the list */
583 	i = OL_TXRX_NUM_LOCAL_PEER_IDS;
584 	pdev->local_peer_ids.pool[i] = i;
585 
586 	qdf_spinlock_create(&pdev->local_peer_ids.lock);
587 }
588 
589 static void
ol_txrx_local_peer_id_alloc(struct ol_txrx_pdev_t * pdev,struct ol_txrx_peer_t * peer)590 ol_txrx_local_peer_id_alloc(struct ol_txrx_pdev_t *pdev,
591 			    struct ol_txrx_peer_t *peer)
592 {
593 	int i;
594 
595 	qdf_spin_lock_bh(&pdev->local_peer_ids.lock);
596 	i = pdev->local_peer_ids.freelist;
597 	if (pdev->local_peer_ids.pool[i] == i) {
598 		/* the list is empty, except for the list-end marker */
599 		peer->local_id = OL_TXRX_INVALID_LOCAL_PEER_ID;
600 	} else {
601 		/* take the head ID and advance the freelist */
602 		peer->local_id = i;
603 		pdev->local_peer_ids.freelist = pdev->local_peer_ids.pool[i];
604 		pdev->local_peer_ids.map[i] = peer;
605 	}
606 	qdf_spin_unlock_bh(&pdev->local_peer_ids.lock);
607 }
608 
609 static void
ol_txrx_local_peer_id_free(struct ol_txrx_pdev_t * pdev,struct ol_txrx_peer_t * peer)610 ol_txrx_local_peer_id_free(struct ol_txrx_pdev_t *pdev,
611 			   struct ol_txrx_peer_t *peer)
612 {
613 	int i = peer->local_id;
614 
615 	if ((i == OL_TXRX_INVALID_LOCAL_PEER_ID) ||
616 	    (i >= OL_TXRX_NUM_LOCAL_PEER_IDS)) {
617 		return;
618 	}
619 	/* put this ID on the head of the freelist */
620 	qdf_spin_lock_bh(&pdev->local_peer_ids.lock);
621 	pdev->local_peer_ids.pool[i] = pdev->local_peer_ids.freelist;
622 	pdev->local_peer_ids.freelist = i;
623 	pdev->local_peer_ids.map[i] = NULL;
624 	qdf_spin_unlock_bh(&pdev->local_peer_ids.lock);
625 }
626 
ol_txrx_local_peer_id_cleanup(struct ol_txrx_pdev_t * pdev)627 static void ol_txrx_local_peer_id_cleanup(struct ol_txrx_pdev_t *pdev)
628 {
629 	qdf_spinlock_destroy(&pdev->local_peer_ids.lock);
630 }
631 
632 #else
633 #define ol_txrx_local_peer_id_pool_init(pdev)   /* no-op */
634 #define ol_txrx_local_peer_id_alloc(pdev, peer) /* no-op */
635 #define ol_txrx_local_peer_id_free(pdev, peer)  /* no-op */
636 #define ol_txrx_local_peer_id_cleanup(pdev)     /* no-op */
637 #endif
638 
639 #if defined(CONFIG_DP_TRACE) && defined(WLAN_DEBUGFS)
640 /**
641  * ol_txrx_read_dpt_buff_debugfs() - read dp trace buffer
642  * @file: file to read
643  * @arg: pdev object
644  *
645  * Return: QDF_STATUS
646  */
ol_txrx_read_dpt_buff_debugfs(qdf_debugfs_file_t file,void * arg)647 static QDF_STATUS ol_txrx_read_dpt_buff_debugfs(qdf_debugfs_file_t file,
648 						void *arg)
649 {
650 	struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)arg;
651 	uint32_t i = 0;
652 	QDF_STATUS status = QDF_STATUS_SUCCESS;
653 
654 	if (pdev->state == QDF_DPT_DEBUGFS_STATE_SHOW_STATE_INVALID)
655 		return QDF_STATUS_E_INVAL;
656 	else if (pdev->state == QDF_DPT_DEBUGFS_STATE_SHOW_COMPLETE) {
657 		pdev->state = QDF_DPT_DEBUGFS_STATE_SHOW_STATE_INIT;
658 		return QDF_STATUS_SUCCESS;
659 	}
660 
661 	i = qdf_dpt_get_curr_pos_debugfs(file, pdev->state);
662 	status =  qdf_dpt_dump_stats_debugfs(file, i);
663 	if (status == QDF_STATUS_E_FAILURE)
664 		pdev->state = QDF_DPT_DEBUGFS_STATE_SHOW_IN_PROGRESS;
665 	else if (status == QDF_STATUS_SUCCESS)
666 		pdev->state = QDF_DPT_DEBUGFS_STATE_SHOW_COMPLETE;
667 
668 	return status;
669 }
670 
671 /**
672  * ol_txrx_conv_str_to_int_debugfs() - convert string to int
673  * @buf: buffer containing string
674  * @len: buffer len
675  * @proto_bitmap: defines the protocol to be tracked
676  * @nr_records: defines the nth packet which is traced
677  * @verbosity: defines the verbosity level
678  *
679  * This function expects char buffer to be null terminated.
680  * Otherwise results could be unexpected values.
681  *
682  * Return: 0 on success
683  */
ol_txrx_conv_str_to_int_debugfs(char * buf,qdf_size_t len,int * proto_bitmap,int * nr_records,int * verbosity,int * num_records_to_dump)684 static int ol_txrx_conv_str_to_int_debugfs(char *buf, qdf_size_t len,
685 					   int *proto_bitmap,
686 					   int *nr_records,
687 					   int *verbosity,
688 					   int *num_records_to_dump)
689 {
690 	int num_value = DPT_SET_PARAM_PROTO_BITMAP;
691 	int ret, param_value = 0;
692 	char *buf_param = buf;
693 	int i;
694 
695 	for (i = 1; i < DPT_SET_PARAM_MAX; i++) {
696 		/* Loop till you reach space as kstrtoint operates till
697 		 * null character. Replace space with null character
698 		 * to read each value.
699 		 * terminate the loop either at null terminated char or
700 		 * len is 0.
701 		 */
702 		while (*buf && len) {
703 			if (*buf == ' ') {
704 				*buf = '\0';
705 				buf++;
706 				len--;
707 				break;
708 			}
709 			buf++;
710 			len--;
711 		}
712 		/* get the parameter */
713 		ret = qdf_kstrtoint(buf_param,
714 				    DPT_DEBUGFS_NUMBER_BASE,
715 				    &param_value);
716 		if (ret) {
717 			QDF_TRACE(QDF_MODULE_ID_TXRX,
718 				  QDF_TRACE_LEVEL_ERROR,
719 				  "%s: Error while parsing buffer. ret %d",
720 				  __func__, ret);
721 			return ret;
722 		}
723 		switch (num_value) {
724 		case DPT_SET_PARAM_PROTO_BITMAP:
725 			*proto_bitmap = param_value;
726 			break;
727 		case DPT_SET_PARAM_NR_RECORDS:
728 			*nr_records = param_value;
729 			break;
730 		case DPT_SET_PARAM_VERBOSITY:
731 			*verbosity = param_value;
732 			break;
733 		case DPT_SET_PARAM_NUM_RECORDS_TO_DUMP:
734 			if (param_value > MAX_QDF_DP_TRACE_RECORDS)
735 				param_value = MAX_QDF_DP_TRACE_RECORDS;
736 			*num_records_to_dump = param_value;
737 			break;
738 		default:
739 			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
740 				  "%s %d: :Set command needs exactly 4 arguments in format <proto_bitmap> <number of record> <Verbosity> <number of records to dump>.",
741 				__func__, __LINE__);
742 			break;
743 		}
744 		num_value++;
745 		/*buf_param should now point to the next param value. */
746 		buf_param = buf;
747 	}
748 
749 	/* buf is not yet NULL implies more than 4 params are passed. */
750 	if (*buf) {
751 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
752 			  "%s %d: :Set command needs exactly 4 arguments in format <proto_bitmap> <number of record> <Verbosity> <number of records to dump>.",
753 			__func__, __LINE__);
754 		return -EINVAL;
755 	}
756 	return 0;
757 }
758 
759 /**
760  * ol_txrx_write_dpt_buff_debugfs() - set dp trace parameters
761  * @priv: pdev object
762  * @buf: buff to get value for dpt parameters
763  * @len: buf length
764  *
765  * Return: QDF_STATUS
766  */
ol_txrx_write_dpt_buff_debugfs(void * priv,const char * buf,qdf_size_t len)767 static QDF_STATUS ol_txrx_write_dpt_buff_debugfs(void *priv,
768 					      const char *buf,
769 					      qdf_size_t len)
770 {
771 	int ret;
772 	int proto_bitmap = 0;
773 	int nr_records = 0;
774 	int verbosity = 0;
775 	int num_records_to_dump = 0;
776 	char *buf1 = NULL;
777 
778 	if (!buf || !len) {
779 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
780 			  "%s: null buffer or len. len %u",
781 				__func__, (uint8_t)len);
782 		return QDF_STATUS_E_FAULT;
783 	}
784 
785 	buf1 = (char *)qdf_mem_malloc(len);
786 	if (!buf1)
787 		return QDF_STATUS_E_FAULT;
788 
789 	qdf_mem_copy(buf1, buf, len);
790 	ret = ol_txrx_conv_str_to_int_debugfs(buf1, len, &proto_bitmap,
791 					      &nr_records, &verbosity,
792 					      &num_records_to_dump);
793 	if (ret) {
794 		qdf_mem_free(buf1);
795 		return QDF_STATUS_E_INVAL;
796 	}
797 
798 	qdf_dpt_set_value_debugfs(proto_bitmap, nr_records, verbosity,
799 				  num_records_to_dump);
800 	qdf_mem_free(buf1);
801 	return QDF_STATUS_SUCCESS;
802 }
803 
ol_txrx_debugfs_init(struct ol_txrx_pdev_t * pdev)804 static int ol_txrx_debugfs_init(struct ol_txrx_pdev_t *pdev)
805 {
806 	pdev->dpt_debugfs_fops.show = ol_txrx_read_dpt_buff_debugfs;
807 	pdev->dpt_debugfs_fops.write = ol_txrx_write_dpt_buff_debugfs;
808 	pdev->dpt_debugfs_fops.priv = pdev;
809 
810 	pdev->dpt_stats_log_dir = qdf_debugfs_create_dir("dpt_stats", NULL);
811 
812 	if (!pdev->dpt_stats_log_dir) {
813 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
814 				"%s: error while creating debugfs dir for %s",
815 				__func__, "dpt_stats");
816 		pdev->state = QDF_DPT_DEBUGFS_STATE_SHOW_STATE_INVALID;
817 		return -EBUSY;
818 	}
819 
820 	if (!qdf_debugfs_create_file("dump_set_dpt_logs", DPT_DEBUGFS_PERMS,
821 				     pdev->dpt_stats_log_dir,
822 				     &pdev->dpt_debugfs_fops)) {
823 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
824 				"%s: debug Entry creation failed!",
825 				__func__);
826 		pdev->state = QDF_DPT_DEBUGFS_STATE_SHOW_STATE_INVALID;
827 		return -EBUSY;
828 	}
829 
830 	pdev->state = QDF_DPT_DEBUGFS_STATE_SHOW_STATE_INIT;
831 	return 0;
832 }
833 
ol_txrx_debugfs_exit(ol_txrx_pdev_handle pdev)834 static void ol_txrx_debugfs_exit(ol_txrx_pdev_handle pdev)
835 {
836 	qdf_debugfs_remove_dir_recursive(pdev->dpt_stats_log_dir);
837 }
838 #else
ol_txrx_debugfs_init(struct ol_txrx_pdev_t * pdev)839 static inline int ol_txrx_debugfs_init(struct ol_txrx_pdev_t *pdev)
840 {
841 	return 0;
842 }
843 
ol_txrx_debugfs_exit(ol_txrx_pdev_handle pdev)844 static inline void ol_txrx_debugfs_exit(ol_txrx_pdev_handle pdev)
845 {
846 }
847 #endif
848 
849 /**
850  * ol_txrx_pdev_attach() - allocate txrx pdev
851  * @soc_hdl: datapath soc handle
852  * @htc_pdev: HTC pdev
853  * @osdev: os dev
854  * @pdev_id: pdev identifier for pdev attach
855  *
856  * Return: QDF_STATUS_SUCCESS on success
857  *		QDF error code for failure
858  */
859 static QDF_STATUS
ol_txrx_pdev_attach(ol_txrx_soc_handle soc,struct cdp_pdev_attach_params * params)860 ol_txrx_pdev_attach(ol_txrx_soc_handle soc,
861 		    struct cdp_pdev_attach_params *params)
862 {
863 	struct ol_txrx_soc_t *ol_soc = cdp_soc_t_to_ol_txrx_soc_t(soc);
864 	struct ol_txrx_pdev_t *pdev;
865 	struct cdp_cfg *cfg_pdev = cds_get_context(QDF_MODULE_ID_CFG);
866 	QDF_STATUS status;
867 	int i, tid;
868 
869 	if (params->pdev_id == OL_TXRX_INVALID_PDEV_ID)
870 		return QDF_STATUS_E_INVAL;
871 
872 	pdev = qdf_mem_malloc(sizeof(*pdev));
873 	if (!pdev) {
874 		status = QDF_STATUS_E_NOMEM;
875 		goto fail0;
876 	}
877 
878 	/* init LL/HL cfg here */
879 	pdev->cfg.is_high_latency = ol_cfg_is_high_latency(cfg_pdev);
880 	/*
881 	 * Credit reporting through HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND
882 	 * enabled or not.
883 	 */
884 	pdev->cfg.credit_update_enabled =
885 		ol_cfg_is_credit_update_enabled(cfg_pdev);
886 
887 	/* Explicitly request TX Completions from FW */
888 	pdev->cfg.request_tx_comp = cds_is_ptp_rx_opt_enabled() ||
889 		cds_is_packet_log_enabled();
890 
891 	pdev->cfg.default_tx_comp_req = !ol_cfg_tx_free_at_download(cfg_pdev);
892 
893 	/* store provided params */
894 	pdev->ctrl_pdev = cfg_pdev;
895 	pdev->osdev = params->qdf_osdev;
896 	pdev->id = params->pdev_id;
897 	pdev->soc = ol_soc;
898 	ol_soc->pdev_list[params->pdev_id] = pdev;
899 
900 	for (i = 0; i < htt_num_sec_types; i++)
901 		pdev->sec_types[i] = (enum ol_sec_type)i;
902 
903 	TXRX_STATS_INIT(pdev);
904 	ol_txrx_tso_stats_init(pdev);
905 	ol_txrx_fw_stats_desc_pool_init(pdev, FW_STATS_DESC_POOL_SIZE);
906 
907 	TAILQ_INIT(&pdev->vdev_list);
908 
909 	TAILQ_INIT(&pdev->inactive_peer_list);
910 
911 	TAILQ_INIT(&pdev->req_list);
912 	pdev->req_list_depth = 0;
913 	qdf_spinlock_create(&pdev->req_list_spinlock);
914 	qdf_spinlock_create(&pdev->tx_mutex);
915 
916 	/* do initial set up of the peer ID -> peer object lookup map */
917 	if (ol_txrx_peer_find_attach(pdev)) {
918 		status = QDF_STATUS_E_FAILURE;
919 		goto fail1;
920 	}
921 
922 	/* initialize the counter of the target's tx buffer availability */
923 	qdf_atomic_init(&pdev->target_tx_credit);
924 	qdf_atomic_init(&pdev->orig_target_tx_credit);
925 	qdf_atomic_init(&pdev->pad_reserve_tx_credit);
926 	qdf_atomic_add(1, &pdev->pad_reserve_tx_credit);
927 
928 	if (ol_cfg_is_high_latency(cfg_pdev)) {
929 		qdf_spinlock_create(&pdev->tx_queue_spinlock);
930 		pdev->tx_sched.scheduler = ol_tx_sched_attach(pdev);
931 		if (!pdev->tx_sched.scheduler) {
932 			status = QDF_STATUS_E_FAILURE;
933 			goto fail2;
934 		}
935 	}
936 	ol_txrx_pdev_txq_log_init(pdev);
937 	ol_txrx_pdev_grp_stats_init(pdev);
938 
939 	pdev->htt_pdev =
940 		htt_pdev_alloc(pdev, cfg_pdev,
941 			       params->htc_handle, params->qdf_osdev);
942 	if (!pdev->htt_pdev) {
943 		status = QDF_STATUS_E_FAILURE;
944 		goto fail3;
945 	}
946 
947 	htt_register_rx_pkt_dump_callback(pdev->htt_pdev,
948 			ol_rx_pkt_dump_call);
949 
950 	/*
951 	 * Init the tid --> category table.
952 	 * Regular tids (0-15) map to their AC.
953 	 * Extension tids get their own categories.
954 	 */
955 	for (tid = 0; tid < OL_TX_NUM_QOS_TIDS; tid++) {
956 		int ac = TXRX_TID_TO_WMM_AC(tid);
957 
958 		pdev->tid_to_ac[tid] = ac;
959 	}
960 	pdev->tid_to_ac[OL_TX_NON_QOS_TID] =
961 		OL_TX_SCHED_WRR_ADV_CAT_NON_QOS_DATA;
962 	pdev->tid_to_ac[OL_TX_MGMT_TID] =
963 		OL_TX_SCHED_WRR_ADV_CAT_UCAST_MGMT;
964 	pdev->tid_to_ac[OL_TX_NUM_TIDS + OL_TX_VDEV_MCAST_BCAST] =
965 		OL_TX_SCHED_WRR_ADV_CAT_MCAST_DATA;
966 	pdev->tid_to_ac[OL_TX_NUM_TIDS + OL_TX_VDEV_DEFAULT_MGMT] =
967 		OL_TX_SCHED_WRR_ADV_CAT_MCAST_MGMT;
968 
969 	if (ol_cfg_is_flow_steering_enabled(pdev->ctrl_pdev))
970 		pdev->peer_id_unmap_ref_cnt =
971 			TXRX_RFS_ENABLE_PEER_ID_UNMAP_COUNT;
972 	else
973 		pdev->peer_id_unmap_ref_cnt =
974 			TXRX_RFS_DISABLE_PEER_ID_UNMAP_COUNT;
975 
976 	if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE)
977 		pdev->chan_noise_floor = NORMALIZED_TO_NOISE_FLOOR;
978 
979 	ol_txrx_debugfs_init(pdev);
980 
981 	return QDF_STATUS_SUCCESS;
982 
983 fail3:
984 	ol_txrx_peer_find_detach(pdev);
985 
986 fail2:
987 	if (ol_cfg_is_high_latency(cfg_pdev))
988 		qdf_spinlock_destroy(&pdev->tx_queue_spinlock);
989 
990 fail1:
991 	qdf_spinlock_destroy(&pdev->req_list_spinlock);
992 	qdf_spinlock_destroy(&pdev->tx_mutex);
993 	ol_txrx_tso_stats_deinit(pdev);
994 	ol_txrx_fw_stats_desc_pool_deinit(pdev);
995 	qdf_mem_free(pdev);
996 
997 fail0:
998 	return status;
999 }
1000 
1001 #if !defined(REMOVE_PKT_LOG) && !defined(QVIT)
1002 /**
1003  * htt_pkt_log_init() - API to initialize packet log
1004  * @soc_hdl: Datapath soc handle
1005  * @pdev_id: id of data path pdev handle
1006  * @scn: HIF context
1007  *
1008  * Return: void
1009  */
htt_pkt_log_init(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,void * scn)1010 void htt_pkt_log_init(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, void *scn)
1011 {
1012 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1013 	ol_txrx_pdev_handle handle =
1014 				ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
1015 
1016 	if (handle->pkt_log_init) {
1017 		ol_txrx_err("pktlog already initialized");
1018 		return;
1019 	}
1020 
1021 	if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE &&
1022 			!QDF_IS_EPPING_ENABLED(cds_get_conparam())) {
1023 		pktlog_sethandle(&handle->pl_dev, scn);
1024 		pktlog_set_pdev_id(handle->pl_dev, pdev_id);
1025 		pktlog_set_callback_regtype(PKTLOG_DEFAULT_CALLBACK_REGISTRATION);
1026 		if (pktlogmod_init(scn))
1027 			qdf_print(" pktlogmod_init failed");
1028 		else
1029 			handle->pkt_log_init = true;
1030 	} else {
1031 		ol_txrx_err("Invalid conn mode: %d", cds_get_conparam());
1032 	}
1033 }
1034 
1035 /**
1036  * htt_pktlogmod_exit() - API to cleanup pktlog info
1037  * @handle: Pdev handle
1038  * @scn: HIF Context
1039  *
1040  * Return: void
1041  */
htt_pktlogmod_exit(struct ol_txrx_pdev_t * handle)1042 static void htt_pktlogmod_exit(struct ol_txrx_pdev_t *handle)
1043 {
1044 	if (!handle->pkt_log_init) {
1045 		ol_txrx_err("pktlog is not initialized");
1046 		return;
1047 	}
1048 
1049 	if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE &&
1050 		!QDF_IS_EPPING_ENABLED(cds_get_conparam())) {
1051 		pktlogmod_exit(handle);
1052 		handle->pkt_log_init = false;
1053 	} else {
1054 		ol_txrx_err("Invalid conn mode: %d", cds_get_conparam());
1055 	}
1056 }
1057 
1058 #else
htt_pkt_log_init(struct cdp_soc_t * soc_hdl,uint8_t pdev,void * scn)1059 void htt_pkt_log_init(struct cdp_soc_t *soc_hdl, uint8_t pdev, void *scn) { }
htt_pktlogmod_exit(ol_txrx_pdev_handle handle)1060 static void htt_pktlogmod_exit(ol_txrx_pdev_handle handle)  { }
1061 #endif
1062 
1063 #ifdef QCA_LL_PDEV_TX_FLOW_CONTROL
1064 /**
1065  * ol_txrx_pdev_set_threshold() - set pdev pool stop/start threshold
1066  * @pdev: txrx pdev
1067  *
1068  * Return: void
1069  */
ol_txrx_pdev_set_threshold(struct ol_txrx_pdev_t * pdev)1070 static void ol_txrx_pdev_set_threshold(struct ol_txrx_pdev_t *pdev)
1071 {
1072 	uint32_t stop_threshold;
1073 	uint32_t start_threshold;
1074 	uint16_t desc_pool_size = pdev->tx_desc.pool_size;
1075 
1076 	stop_threshold = ol_cfg_get_tx_flow_stop_queue_th(pdev->ctrl_pdev);
1077 	start_threshold = stop_threshold +
1078 		ol_cfg_get_tx_flow_start_queue_offset(pdev->ctrl_pdev);
1079 	pdev->tx_desc.start_th = (start_threshold * desc_pool_size) / 100;
1080 	pdev->tx_desc.stop_th = (stop_threshold * desc_pool_size) / 100;
1081 	pdev->tx_desc.stop_priority_th =
1082 		(TX_PRIORITY_TH * pdev->tx_desc.stop_th) / 100;
1083 	if (pdev->tx_desc.stop_priority_th >= MAX_TSO_SEGMENT_DESC)
1084 		pdev->tx_desc.stop_priority_th -= MAX_TSO_SEGMENT_DESC;
1085 
1086 	pdev->tx_desc.start_priority_th =
1087 		(TX_PRIORITY_TH * pdev->tx_desc.start_th) / 100;
1088 	if (pdev->tx_desc.start_priority_th >= MAX_TSO_SEGMENT_DESC)
1089 		pdev->tx_desc.start_priority_th -= MAX_TSO_SEGMENT_DESC;
1090 	pdev->tx_desc.status = FLOW_POOL_ACTIVE_UNPAUSED;
1091 }
1092 #else
ol_txrx_pdev_set_threshold(struct ol_txrx_pdev_t * pdev)1093 static inline void ol_txrx_pdev_set_threshold(struct ol_txrx_pdev_t *pdev)
1094 {
1095 }
1096 #endif
1097 
1098 /**
1099  * ol_txrx_pdev_post_attach() - attach txrx pdev
1100  * @soc_hdl: datapath soc handle
1101  * @pdev_id: physical device instance id
1102  *
1103  * Return: 0 for success
1104  */
1105 int
ol_txrx_pdev_post_attach(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)1106 ol_txrx_pdev_post_attach(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
1107 {
1108 	uint16_t i;
1109 	uint16_t fail_idx = 0;
1110 	int ret = 0;
1111 	uint16_t desc_pool_size;
1112 	struct hif_opaque_softc *osc =  cds_get_context(QDF_MODULE_ID_HIF);
1113 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1114 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
1115 
1116 	uint16_t desc_element_size = sizeof(union ol_tx_desc_list_elem_t);
1117 	union ol_tx_desc_list_elem_t *c_element;
1118 	unsigned int sig_bit;
1119 	uint16_t desc_per_page;
1120 
1121 	if (!osc || !pdev) {
1122 		ret = -EINVAL;
1123 		goto ol_attach_fail;
1124 	}
1125 
1126 	/*
1127 	 * For LL, limit the number of host's tx descriptors to match
1128 	 * the number of target FW tx descriptors.
1129 	 * This simplifies the FW, by ensuring the host will never
1130 	 * download more tx descriptors than the target has space for.
1131 	 * The FW will drop/free low-priority tx descriptors when it
1132 	 * starts to run low, so that in theory the host should never
1133 	 * run out of tx descriptors.
1134 	 */
1135 
1136 	/*
1137 	 * LL - initialize the target credit ourselves.
1138 	 * HL - wait for a HTT target credit initialization
1139 	 * during htt_attach.
1140 	 */
1141 	desc_pool_size = ol_tx_get_desc_global_pool_size(pdev);
1142 	ol_tx_init_pdev(pdev);
1143 
1144 	ol_tx_desc_dup_detect_init(pdev, desc_pool_size);
1145 
1146 	ol_tx_setup_fastpath_ce_handles(osc, pdev);
1147 
1148 	if ((ol_txrx_get_new_htt_msg_format(pdev)))
1149 		ol_set_cfg_new_htt_format(pdev->ctrl_pdev, true);
1150 	else
1151 		ol_set_cfg_new_htt_format(pdev->ctrl_pdev, false);
1152 
1153 	ret = htt_attach(pdev->htt_pdev, desc_pool_size);
1154 	if (ret)
1155 		goto htt_attach_fail;
1156 
1157 	/* Attach micro controller data path offload resource */
1158 	if (ol_cfg_ipa_uc_offload_enabled(pdev->ctrl_pdev)) {
1159 		ret = htt_ipa_uc_attach(pdev->htt_pdev);
1160 		if (ret)
1161 			goto uc_attach_fail;
1162 	}
1163 
1164 	/* Calculate single element reserved size power of 2 */
1165 	pdev->tx_desc.desc_reserved_size = qdf_get_pwr2(desc_element_size);
1166 	qdf_mem_multi_pages_alloc(pdev->osdev, &pdev->tx_desc.desc_pages,
1167 		pdev->tx_desc.desc_reserved_size, desc_pool_size, 0, true);
1168 	if ((0 == pdev->tx_desc.desc_pages.num_pages) ||
1169 		(!pdev->tx_desc.desc_pages.cacheable_pages)) {
1170 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1171 			"Page alloc fail");
1172 		ret = -ENOMEM;
1173 		goto page_alloc_fail;
1174 	}
1175 	desc_per_page = pdev->tx_desc.desc_pages.num_element_per_page;
1176 	pdev->tx_desc.offset_filter = desc_per_page - 1;
1177 	/* Calculate page divider to find page number */
1178 	sig_bit = 0;
1179 	while (desc_per_page) {
1180 		sig_bit++;
1181 		desc_per_page = desc_per_page >> 1;
1182 	}
1183 	pdev->tx_desc.page_divider = (sig_bit - 1);
1184 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1185 		"page_divider 0x%x, offset_filter 0x%x num elem %d, ol desc num page %d, ol desc per page %d",
1186 		pdev->tx_desc.page_divider, pdev->tx_desc.offset_filter,
1187 		desc_pool_size, pdev->tx_desc.desc_pages.num_pages,
1188 		pdev->tx_desc.desc_pages.num_element_per_page);
1189 
1190 	/*
1191 	 * Each SW tx desc (used only within the tx datapath SW) has a
1192 	 * matching HTT tx desc (used for downloading tx meta-data to FW/HW).
1193 	 * Go ahead and allocate the HTT tx desc and link it with the SW tx
1194 	 * desc now, to avoid doing it during time-critical transmit.
1195 	 */
1196 	pdev->tx_desc.pool_size = desc_pool_size;
1197 	pdev->tx_desc.freelist =
1198 		(union ol_tx_desc_list_elem_t *)
1199 		(*pdev->tx_desc.desc_pages.cacheable_pages);
1200 	c_element = pdev->tx_desc.freelist;
1201 	for (i = 0; i < desc_pool_size; i++) {
1202 		void *htt_tx_desc;
1203 		void *htt_frag_desc = NULL;
1204 		qdf_dma_addr_t frag_paddr = 0;
1205 		qdf_dma_addr_t paddr;
1206 
1207 		if (i == (desc_pool_size - 1))
1208 			c_element->next = NULL;
1209 		else
1210 			c_element->next = (union ol_tx_desc_list_elem_t *)
1211 				ol_tx_desc_find(pdev, i + 1);
1212 
1213 		htt_tx_desc = htt_tx_desc_alloc(pdev->htt_pdev, &paddr, i);
1214 		if (!htt_tx_desc) {
1215 			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_FATAL,
1216 				  "%s: failed to alloc HTT tx desc (%d of %d)",
1217 				__func__, i, desc_pool_size);
1218 			fail_idx = i;
1219 			ret = -ENOMEM;
1220 			goto desc_alloc_fail;
1221 		}
1222 
1223 		c_element->tx_desc.htt_tx_desc = htt_tx_desc;
1224 		c_element->tx_desc.htt_tx_desc_paddr = paddr;
1225 		ret = htt_tx_frag_alloc(pdev->htt_pdev,
1226 					i, &frag_paddr, &htt_frag_desc);
1227 		if (ret) {
1228 			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1229 				"%s: failed to alloc HTT frag dsc (%d/%d)",
1230 				__func__, i, desc_pool_size);
1231 			/* Is there a leak here, is this handling correct? */
1232 			fail_idx = i;
1233 			goto desc_alloc_fail;
1234 		}
1235 		if (!ret && htt_frag_desc) {
1236 			/*
1237 			 * Initialize the first 6 words (TSO flags)
1238 			 * of the frag descriptor
1239 			 */
1240 			memset(htt_frag_desc, 0, 6 * sizeof(uint32_t));
1241 			c_element->tx_desc.htt_frag_desc = htt_frag_desc;
1242 			c_element->tx_desc.htt_frag_desc_paddr = frag_paddr;
1243 		}
1244 #ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS
1245 		c_element->tx_desc.pkt_type = 0xff;
1246 #ifdef QCA_COMPUTE_TX_DELAY
1247 		c_element->tx_desc.entry_timestamp_ticks =
1248 			0xffffffff;
1249 #endif
1250 #endif
1251 		c_element->tx_desc.id = i;
1252 		qdf_atomic_init(&c_element->tx_desc.ref_cnt);
1253 		c_element = c_element->next;
1254 		fail_idx = i;
1255 	}
1256 
1257 	/* link SW tx descs into a freelist */
1258 	pdev->tx_desc.num_free = desc_pool_size;
1259 	ol_txrx_dbg("first tx_desc:0x%pK Last tx desc:0x%pK",
1260 		    (uint32_t *)pdev->tx_desc.freelist,
1261 		    (uint32_t *)(pdev->tx_desc.freelist + desc_pool_size));
1262 
1263 	ol_txrx_pdev_set_threshold(pdev);
1264 
1265 	/* check what format of frames are expected to be delivered by the OS */
1266 	pdev->frame_format = ol_cfg_frame_type(pdev->ctrl_pdev);
1267 	if (pdev->frame_format == wlan_frm_fmt_native_wifi)
1268 		pdev->htt_pkt_type = htt_pkt_type_native_wifi;
1269 	else if (pdev->frame_format == wlan_frm_fmt_802_3) {
1270 		if (ol_cfg_is_ce_classify_enabled(pdev->ctrl_pdev))
1271 			pdev->htt_pkt_type = htt_pkt_type_eth2;
1272 		else
1273 			pdev->htt_pkt_type = htt_pkt_type_ethernet;
1274 	} else {
1275 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1276 			  "%s Invalid standard frame type: %d",
1277 			  __func__, pdev->frame_format);
1278 		ret = -EINVAL;
1279 		goto control_init_fail;
1280 	}
1281 
1282 	/* setup the global rx defrag waitlist */
1283 	TAILQ_INIT(&pdev->rx.defrag.waitlist);
1284 
1285 	/* configure where defrag timeout and duplicate detection is handled */
1286 	pdev->rx.flags.defrag_timeout_check =
1287 		pdev->rx.flags.dup_check =
1288 		ol_cfg_rx_host_defrag_timeout_duplicate_check(pdev->ctrl_pdev);
1289 
1290 #ifdef QCA_SUPPORT_SW_TXRX_ENCAP
1291 	/* Need to revisit this part. Currently,hardcode to riva's caps */
1292 	pdev->target_tx_tran_caps = wlan_frm_tran_cap_raw;
1293 	pdev->target_rx_tran_caps = wlan_frm_tran_cap_raw;
1294 	/*
1295 	 * The Riva HW de-aggregate doesn't have capability to generate 802.11
1296 	 * header for non-first subframe of A-MSDU.
1297 	 */
1298 	pdev->sw_subfrm_hdr_recovery_enable = 1;
1299 	/*
1300 	 * The Riva HW doesn't have the capability to set Protected Frame bit
1301 	 * in the MAC header for encrypted data frame.
1302 	 */
1303 	pdev->sw_pf_proc_enable = 1;
1304 
1305 	if (pdev->frame_format == wlan_frm_fmt_802_3) {
1306 		/*
1307 		 * sw llc process is only needed in
1308 		 * 802.3 to 802.11 transform case
1309 		 */
1310 		pdev->sw_tx_llc_proc_enable = 1;
1311 		pdev->sw_rx_llc_proc_enable = 1;
1312 	} else {
1313 		pdev->sw_tx_llc_proc_enable = 0;
1314 		pdev->sw_rx_llc_proc_enable = 0;
1315 	}
1316 
1317 	switch (pdev->frame_format) {
1318 	case wlan_frm_fmt_raw:
1319 		pdev->sw_tx_encap =
1320 			pdev->target_tx_tran_caps & wlan_frm_tran_cap_raw
1321 			? 0 : 1;
1322 		pdev->sw_rx_decap =
1323 			pdev->target_rx_tran_caps & wlan_frm_tran_cap_raw
1324 			? 0 : 1;
1325 		break;
1326 	case wlan_frm_fmt_native_wifi:
1327 		pdev->sw_tx_encap =
1328 			pdev->
1329 			target_tx_tran_caps & wlan_frm_tran_cap_native_wifi
1330 			? 0 : 1;
1331 		pdev->sw_rx_decap =
1332 			pdev->
1333 			target_rx_tran_caps & wlan_frm_tran_cap_native_wifi
1334 			? 0 : 1;
1335 		break;
1336 	case wlan_frm_fmt_802_3:
1337 		pdev->sw_tx_encap =
1338 			pdev->target_tx_tran_caps & wlan_frm_tran_cap_8023
1339 			? 0 : 1;
1340 		pdev->sw_rx_decap =
1341 			pdev->target_rx_tran_caps & wlan_frm_tran_cap_8023
1342 			? 0 : 1;
1343 		break;
1344 	default:
1345 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1346 			  "Invalid std frame type; [en/de]cap: f:%x t:%x r:%x",
1347 			  pdev->frame_format,
1348 			  pdev->target_tx_tran_caps, pdev->target_rx_tran_caps);
1349 		ret = -EINVAL;
1350 		goto control_init_fail;
1351 	}
1352 #endif
1353 
1354 	/*
1355 	 * Determine what rx processing steps are done within the host.
1356 	 * Possibilities:
1357 	 * 1.  Nothing - rx->tx forwarding and rx PN entirely within target.
1358 	 *     (This is unlikely; even if the target is doing rx->tx forwarding,
1359 	 *     the host should be doing rx->tx forwarding too, as a back up for
1360 	 *     the target's rx->tx forwarding, in case the target runs short on
1361 	 *     memory, and can't store rx->tx frames that are waiting for
1362 	 *     missing prior rx frames to arrive.)
1363 	 * 2.  Just rx -> tx forwarding.
1364 	 *     This is the typical configuration for HL, and a likely
1365 	 *     configuration for LL STA or small APs (e.g. retail APs).
1366 	 * 3.  Both PN check and rx -> tx forwarding.
1367 	 *     This is the typical configuration for large LL APs.
1368 	 * Host-side PN check without rx->tx forwarding is not a valid
1369 	 * configuration, since the PN check needs to be done prior to
1370 	 * the rx->tx forwarding.
1371 	 */
1372 	if (ol_cfg_is_full_reorder_offload(pdev->ctrl_pdev)) {
1373 		/*
1374 		 * PN check, rx-tx forwarding and rx reorder is done by
1375 		 * the target
1376 		 */
1377 		if (ol_cfg_rx_fwd_disabled(pdev->ctrl_pdev))
1378 			pdev->rx_opt_proc = ol_rx_in_order_deliver;
1379 		else
1380 			pdev->rx_opt_proc = ol_rx_fwd_check;
1381 	} else {
1382 		if (ol_cfg_rx_pn_check(pdev->ctrl_pdev)) {
1383 			if (ol_cfg_rx_fwd_disabled(pdev->ctrl_pdev)) {
1384 				/*
1385 				 * PN check done on host,
1386 				 * rx->tx forwarding not done at all.
1387 				 */
1388 				pdev->rx_opt_proc = ol_rx_pn_check_only;
1389 			} else if (ol_cfg_rx_fwd_check(pdev->ctrl_pdev)) {
1390 				/*
1391 				 * Both PN check and rx->tx forwarding done
1392 				 * on host.
1393 				 */
1394 				pdev->rx_opt_proc = ol_rx_pn_check;
1395 			} else {
1396 #define TRACESTR01 "invalid config: if rx PN check is on the host,"\
1397 "rx->tx forwarding check needs to also be on the host"
1398 				QDF_TRACE(QDF_MODULE_ID_TXRX,
1399 					  QDF_TRACE_LEVEL_ERROR,
1400 					  "%s: %s", __func__, TRACESTR01);
1401 #undef TRACESTR01
1402 				ret = -EINVAL;
1403 				goto control_init_fail;
1404 			}
1405 		} else {
1406 			/* PN check done on target */
1407 			if ((!ol_cfg_rx_fwd_disabled(pdev->ctrl_pdev)) &&
1408 			    ol_cfg_rx_fwd_check(pdev->ctrl_pdev)) {
1409 				/*
1410 				 * rx->tx forwarding done on host (possibly as
1411 				 * back-up for target-side primary rx->tx
1412 				 * forwarding)
1413 				 */
1414 				pdev->rx_opt_proc = ol_rx_fwd_check;
1415 			} else {
1416 				/*
1417 				 * rx->tx forwarding either done in target,
1418 				 * or not done at all
1419 				 */
1420 				pdev->rx_opt_proc = ol_rx_deliver;
1421 			}
1422 		}
1423 	}
1424 
1425 	/* initialize mutexes for tx desc alloc and peer lookup */
1426 	qdf_spinlock_create(&pdev->peer_ref_mutex);
1427 	qdf_spinlock_create(&pdev->rx.mutex);
1428 	qdf_spinlock_create(&pdev->last_real_peer_mutex);
1429 	qdf_spinlock_create(&pdev->peer_map_unmap_lock);
1430 	OL_TXRX_PEER_STATS_MUTEX_INIT(pdev);
1431 
1432 	if (OL_RX_REORDER_TRACE_ATTACH(pdev) != A_OK) {
1433 		ret = -ENOMEM;
1434 		goto reorder_trace_attach_fail;
1435 	}
1436 
1437 	if (OL_RX_PN_TRACE_ATTACH(pdev) != A_OK) {
1438 		ret = -ENOMEM;
1439 		goto pn_trace_attach_fail;
1440 	}
1441 
1442 	/*
1443 	 * WDI event attach
1444 	 */
1445 	wdi_event_attach(pdev);
1446 
1447 	/*
1448 	 * Initialize rx PN check characteristics for different security types.
1449 	 */
1450 	qdf_mem_zero(&pdev->rx_pn[0], sizeof(pdev->rx_pn));
1451 
1452 	/* TKIP: 48-bit TSC, CCMP: 48-bit PN */
1453 	pdev->rx_pn[htt_sec_type_tkip].len =
1454 		pdev->rx_pn[htt_sec_type_tkip_nomic].len =
1455 			pdev->rx_pn[htt_sec_type_aes_ccmp].len = 48;
1456 
1457 	pdev->rx_pn[htt_sec_type_aes_ccmp_256].len =
1458 		pdev->rx_pn[htt_sec_type_aes_gcmp].len =
1459 			pdev->rx_pn[htt_sec_type_aes_gcmp_256].len = 48;
1460 
1461 	pdev->rx_pn[htt_sec_type_tkip].cmp =
1462 		pdev->rx_pn[htt_sec_type_tkip_nomic].cmp =
1463 			pdev->rx_pn[htt_sec_type_aes_ccmp].cmp = ol_rx_pn_cmp48;
1464 
1465 	pdev->rx_pn[htt_sec_type_aes_ccmp_256].cmp =
1466 		pdev->rx_pn[htt_sec_type_aes_gcmp].cmp =
1467 		    pdev->rx_pn[htt_sec_type_aes_gcmp_256].cmp = ol_rx_pn_cmp48;
1468 
1469 	/* WAPI: 128-bit PN */
1470 	pdev->rx_pn[htt_sec_type_wapi].len = 128;
1471 	pdev->rx_pn[htt_sec_type_wapi].cmp = ol_rx_pn_wapi_cmp;
1472 
1473 	OL_RX_REORDER_TIMEOUT_INIT(pdev);
1474 
1475 	ol_txrx_dbg("Created pdev %pK", pdev);
1476 
1477 	pdev->cfg.host_addba = ol_cfg_host_addba(pdev->ctrl_pdev);
1478 
1479 #ifdef QCA_SUPPORT_PEER_DATA_RX_RSSI
1480 #define OL_TXRX_RSSI_UPDATE_SHIFT_DEFAULT 3
1481 
1482 /* #if 1 -- TODO: clean this up */
1483 #define OL_TXRX_RSSI_NEW_WEIGHT_DEFAULT	\
1484 	/* avg = 100% * new + 0% * old */ \
1485 	(1 << OL_TXRX_RSSI_UPDATE_SHIFT_DEFAULT)
1486 /*
1487  * #else
1488  * #define OL_TXRX_RSSI_NEW_WEIGHT_DEFAULT
1489  *	//avg = 25% * new + 25% * old
1490  *	(1 << (OL_TXRX_RSSI_UPDATE_SHIFT_DEFAULT-2))
1491  * #endif
1492  */
1493 	pdev->rssi_update_shift = OL_TXRX_RSSI_UPDATE_SHIFT_DEFAULT;
1494 	pdev->rssi_new_weight = OL_TXRX_RSSI_NEW_WEIGHT_DEFAULT;
1495 #endif
1496 
1497 	ol_txrx_local_peer_id_pool_init(pdev);
1498 
1499 	pdev->cfg.ll_pause_txq_limit =
1500 		ol_tx_cfg_max_tx_queue_depth_ll(pdev->ctrl_pdev);
1501 
1502 	/* TX flow control for peer who is in very bad link status */
1503 	ol_tx_badpeer_flow_cl_init(pdev);
1504 
1505 #ifdef QCA_COMPUTE_TX_DELAY
1506 	qdf_mem_zero(&pdev->tx_delay, sizeof(pdev->tx_delay));
1507 	qdf_spinlock_create(&pdev->tx_delay.mutex);
1508 
1509 	/* initialize compute interval with 5 seconds (ESE default) */
1510 	pdev->tx_delay.avg_period_ticks = qdf_system_msecs_to_ticks(5000);
1511 	{
1512 		uint32_t bin_width_1000ticks;
1513 
1514 		bin_width_1000ticks =
1515 			qdf_system_msecs_to_ticks
1516 				(QCA_TX_DELAY_HIST_INTERNAL_BIN_WIDTH_MS
1517 				 * 1000);
1518 		/*
1519 		 * Compute a factor and shift that together are equal to the
1520 		 * inverse of the bin_width time, so that rather than dividing
1521 		 * by the bin width time, approximately the same result can be
1522 		 * obtained much more efficiently by a multiply + shift.
1523 		 * multiply_factor >> shift = 1 / bin_width_time, so
1524 		 * multiply_factor = (1 << shift) / bin_width_time.
1525 		 *
1526 		 * Pick the shift semi-arbitrarily.
1527 		 * If we knew statically what the bin_width would be, we could
1528 		 * choose a shift that minimizes the error.
1529 		 * Since the bin_width is determined dynamically, simply use a
1530 		 * shift that is about half of the uint32_t size.  This should
1531 		 * result in a relatively large multiplier value, which
1532 		 * minimizes error from rounding the multiplier to an integer.
1533 		 * The rounding error only becomes significant if the tick units
1534 		 * are on the order of 1 microsecond.  In most systems, it is
1535 		 * expected that the tick units will be relatively low-res,
1536 		 * on the order of 1 millisecond.  In such systems the rounding
1537 		 * error is negligible.
1538 		 * It would be more accurate to dynamically try out different
1539 		 * shifts and choose the one that results in the smallest
1540 		 * rounding error, but that extra level of fidelity is
1541 		 * not needed.
1542 		 */
1543 		pdev->tx_delay.hist_internal_bin_width_shift = 16;
1544 		pdev->tx_delay.hist_internal_bin_width_mult =
1545 			((1 << pdev->tx_delay.hist_internal_bin_width_shift) *
1546 			 1000 + (bin_width_1000ticks >> 1)) /
1547 			bin_width_1000ticks;
1548 	}
1549 #endif /* QCA_COMPUTE_TX_DELAY */
1550 
1551 	/* Thermal Mitigation */
1552 	ol_tx_throttle_init(pdev);
1553 
1554 	ol_tso_seg_list_init(pdev, desc_pool_size);
1555 
1556 	ol_tso_num_seg_list_init(pdev, desc_pool_size);
1557 
1558 	ol_tx_register_flow_control(pdev);
1559 
1560 	return 0;            /* success */
1561 
1562 pn_trace_attach_fail:
1563 	OL_RX_REORDER_TRACE_DETACH(pdev);
1564 
1565 reorder_trace_attach_fail:
1566 	qdf_spinlock_destroy(&pdev->peer_ref_mutex);
1567 	qdf_spinlock_destroy(&pdev->rx.mutex);
1568 	qdf_spinlock_destroy(&pdev->last_real_peer_mutex);
1569 	qdf_spinlock_destroy(&pdev->peer_map_unmap_lock);
1570 	OL_TXRX_PEER_STATS_MUTEX_DESTROY(pdev);
1571 
1572 control_init_fail:
1573 desc_alloc_fail:
1574 	for (i = 0; i < fail_idx; i++)
1575 		htt_tx_desc_free(pdev->htt_pdev,
1576 			(ol_tx_desc_find(pdev, i))->htt_tx_desc);
1577 
1578 	qdf_mem_multi_pages_free(pdev->osdev,
1579 		&pdev->tx_desc.desc_pages, 0, true);
1580 
1581 page_alloc_fail:
1582 	if (ol_cfg_ipa_uc_offload_enabled(pdev->ctrl_pdev))
1583 		htt_ipa_uc_detach(pdev->htt_pdev);
1584 uc_attach_fail:
1585 	htt_detach(pdev->htt_pdev);
1586 htt_attach_fail:
1587 	ol_tx_desc_dup_detect_deinit(pdev);
1588 ol_attach_fail:
1589 	return ret;            /* fail */
1590 }
1591 
1592 /**
1593  * ol_txrx_pdev_attach_target() - send target configuration
1594  *
1595  * @soc_hdl - data path soc handle
1596  * @pdev_id - device instance id
1597  *
1598  * The majority of the data SW setup are done by the pdev_attach
1599  * functions, but this function completes the data SW setup by
1600  * sending datapath configuration messages to the target.
1601  *
1602  * Return: 0 - success 1 - failure
1603  */
ol_txrx_pdev_attach_target(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)1604 static int ol_txrx_pdev_attach_target(struct cdp_soc_t *soc_hdl,
1605 				      uint8_t pdev_id)
1606 {
1607 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1608 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
1609 
1610 	if (!pdev)
1611 		return QDF_STATUS_E_FAULT;
1612 
1613 	return htt_attach_target(pdev->htt_pdev) == QDF_STATUS_SUCCESS ? 0:1;
1614 }
1615 
1616 /**
1617  * ol_tx_free_descs_inuse - free tx descriptors which are in use
1618  * @pdev - the physical device for which tx descs need to be freed
1619  *
1620  * Cycle through the list of TX descriptors (for a pdev) which are in use,
1621  * for which TX completion has not been received and free them. Should be
1622  * called only when the interrupts are off and all lower layer RX is stopped.
1623  * Otherwise there may be a race condition with TX completions.
1624  *
1625  * Return: None
1626  */
ol_tx_free_descs_inuse(ol_txrx_pdev_handle pdev)1627 static void ol_tx_free_descs_inuse(ol_txrx_pdev_handle pdev)
1628 {
1629 	int i;
1630 	void *htt_tx_desc;
1631 	struct ol_tx_desc_t *tx_desc;
1632 	int num_freed_tx_desc = 0;
1633 
1634 	for (i = 0; i < pdev->tx_desc.pool_size; i++) {
1635 		tx_desc = ol_tx_desc_find(pdev, i);
1636 		/*
1637 		 * Confirm that each tx descriptor is "empty", i.e. it has
1638 		 * no tx frame attached.
1639 		 * In particular, check that there are no frames that have
1640 		 * been given to the target to transmit, for which the
1641 		 * target has never provided a response.
1642 		 *
1643 		 * Rome supports mgmt Tx via HTT interface, not via WMI.
1644 		 * When mgmt frame is sent, 2 tx desc is allocated:
1645 		 * mgmt_txrx_desc is allocated in wlan_mgmt_txrx_mgmt_frame_tx,
1646 		 * ol_tx_desc is allocated in ol_txrx_mgmt_send_ext.
1647 		 * They point to same net buffer.
1648 		 * net buffer is mapped in htt_tx_desc_init.
1649 		 *
1650 		 * When SSR during Rome STA connected, deauth frame is sent,
1651 		 * but no tx complete since firmware hung already.
1652 		 * Pending mgmt frames are unmapped and freed when destroy
1653 		 * vdev.
1654 		 * hdd_reset_all_adapters->hdd_stop_adapter->hdd_vdev_destroy
1655 		 * ->wma_handle_vdev_detach->wlan_mgmt_txrx_vdev_drain
1656 		 * ->wma_mgmt_frame_fill_peer_cb
1657 		 * ->mgmt_txrx_tx_completion_handler.
1658 		 *
1659 		 * Don't need unmap and free net buffer of mgmt frames again
1660 		 * during data path clean up, just free ol_tx_desc.
1661 		 * hdd_wlan_stop_modules->cds_post_disable->cdp_pdev_pre_detach
1662 		 * ->ol_txrx_pdev_pre_detach->ol_tx_free_descs_inuse.
1663 		 */
1664 		if (qdf_atomic_read(&tx_desc->ref_cnt)) {
1665 			if (!ol_tx_get_is_mgmt_over_wmi_enabled() &&
1666 			    tx_desc->pkt_type >= OL_TXRX_MGMT_TYPE_BASE) {
1667 				qdf_atomic_init(&tx_desc->ref_cnt);
1668 				ol_txrx_dbg("Pending mgmt frames nbuf unmapped and freed already when vdev destroyed");
1669 				/* free the tx desc */
1670 				ol_tx_desc_free(pdev, tx_desc);
1671 			} else {
1672 				ol_txrx_dbg("Warning: freeing tx frame (no compltn)");
1673 				ol_tx_desc_frame_free_nonstd(pdev, tx_desc, 1);
1674 			}
1675 			num_freed_tx_desc++;
1676 		}
1677 		htt_tx_desc = tx_desc->htt_tx_desc;
1678 		htt_tx_desc_free(pdev->htt_pdev, htt_tx_desc);
1679 	}
1680 
1681 	if (num_freed_tx_desc)
1682 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
1683 		"freed %d tx frames for which no resp from target",
1684 		num_freed_tx_desc);
1685 
1686 }
1687 
1688 /**
1689  * ol_txrx_pdev_pre_detach() - detach the data SW state
1690  * @soc_hdl - datapath soc handle
1691  * @pdev_id - the data physical device id being removed
1692  * @force - delete the pdev (and its vdevs and peers) even if
1693  * there are outstanding references by the target to the vdevs
1694  * and peers within the pdev
1695  *
1696  * This function is used when the WLAN driver is being removed to
1697  * detach the host data component within the driver.
1698  *
1699  * Return: none
1700  */
ol_txrx_pdev_pre_detach(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,int force)1701 static void ol_txrx_pdev_pre_detach(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
1702 					  int force)
1703 {
1704 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1705 	struct ol_txrx_pdev_t *pdev = ol_txrx_get_pdev_from_pdev_id(soc,
1706 								    pdev_id);
1707 
1708 	/* preconditions */
1709 	TXRX_ASSERT2(pdev);
1710 
1711 	/* check that the pdev has no vdevs allocated */
1712 	TXRX_ASSERT1(TAILQ_EMPTY(&pdev->vdev_list));
1713 
1714 #ifdef QCA_SUPPORT_TX_THROTTLE
1715 	/* Thermal Mitigation */
1716 	qdf_timer_stop(&pdev->tx_throttle.phase_timer);
1717 	qdf_timer_free(&pdev->tx_throttle.phase_timer);
1718 #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
1719 	qdf_timer_stop(&pdev->tx_throttle.tx_timer);
1720 	qdf_timer_free(&pdev->tx_throttle.tx_timer);
1721 #endif
1722 #endif
1723 
1724 	if (force) {
1725 		/*
1726 		 * The assertion above confirms that all vdevs within this pdev
1727 		 * were detached.  However, they may not have actually been
1728 		 * deleted.
1729 		 * If the vdev had peers which never received a PEER_UNMAP msg
1730 		 * from the target, then there are still zombie peer objects,
1731 		 * and the vdev parents of the zombie peers are also zombies,
1732 		 * hanging around until their final peer gets deleted.
1733 		 * Go through the peer hash table and delete any peers left.
1734 		 * As a side effect, this will complete the deletion of any
1735 		 * vdevs that are waiting for their peers to finish deletion.
1736 		 */
1737 		ol_txrx_dbg("Force delete for pdev %pK",
1738 			   pdev);
1739 		ol_txrx_peer_find_hash_erase(pdev);
1740 		ol_txrx_peer_free_inactive_list(pdev);
1741 	}
1742 
1743 	/* to get flow pool status before freeing descs */
1744 	ol_tx_dump_flow_pool_info(cds_get_context(QDF_MODULE_ID_SOC));
1745 	ol_tx_free_descs_inuse(pdev);
1746 	ol_tx_deregister_flow_control(pdev);
1747 
1748 	/*
1749 	 * ol_tso_seg_list_deinit should happen after
1750 	 * ol_tx_deinit_tx_desc_inuse as it tries to access the tso seg freelist
1751 	 * which is being de-initilized in ol_tso_seg_list_deinit
1752 	 */
1753 	ol_tso_seg_list_deinit(pdev);
1754 	ol_tso_num_seg_list_deinit(pdev);
1755 
1756 	/* Stop the communication between HTT and target at first */
1757 	htt_detach_target(pdev->htt_pdev);
1758 
1759 	qdf_mem_multi_pages_free(pdev->osdev,
1760 		&pdev->tx_desc.desc_pages, 0, true);
1761 	pdev->tx_desc.freelist = NULL;
1762 
1763 	/* Detach micro controller data path offload resource */
1764 	if (ol_cfg_ipa_uc_offload_enabled(pdev->ctrl_pdev))
1765 		htt_ipa_uc_detach(pdev->htt_pdev);
1766 
1767 	htt_detach(pdev->htt_pdev);
1768 	ol_tx_desc_dup_detect_deinit(pdev);
1769 
1770 	qdf_spinlock_destroy(&pdev->peer_ref_mutex);
1771 	qdf_spinlock_destroy(&pdev->last_real_peer_mutex);
1772 	qdf_spinlock_destroy(&pdev->rx.mutex);
1773 	qdf_spinlock_destroy(&pdev->peer_map_unmap_lock);
1774 #ifdef QCA_SUPPORT_TX_THROTTLE
1775 	/* Thermal Mitigation */
1776 	qdf_spinlock_destroy(&pdev->tx_throttle.mutex);
1777 #endif
1778 
1779 	/* TX flow control for peer who is in very bad link status */
1780 	ol_tx_badpeer_flow_cl_deinit(pdev);
1781 
1782 	OL_TXRX_PEER_STATS_MUTEX_DESTROY(pdev);
1783 
1784 	OL_RX_REORDER_TRACE_DETACH(pdev);
1785 	OL_RX_PN_TRACE_DETACH(pdev);
1786 
1787 	htt_pktlogmod_exit(pdev);
1788 
1789 	/*
1790 	 * WDI event detach
1791 	 */
1792 	wdi_event_detach(pdev);
1793 
1794 	ol_txrx_local_peer_id_cleanup(pdev);
1795 
1796 #ifdef QCA_COMPUTE_TX_DELAY
1797 	qdf_spinlock_destroy(&pdev->tx_delay.mutex);
1798 #endif
1799 
1800 	return;
1801 }
1802 
1803 /**
1804  * ol_txrx_pdev_detach() - delete the data SW state
1805  * @soc_hdl - data path soc handle
1806  * @pdev_id - device instance id
1807  * @force - delete the pdev (and its vdevs and peers) even if
1808  * there are outstanding references by the target to the vdevs
1809  * and peers within the pdev
1810  *
1811  * This function is used when the WLAN driver is being removed to
1812  * remove the host data component within the driver.
1813  * All virtual devices within the physical device need to be deleted
1814  * (ol_txrx_vdev_detach) before the physical device itself is deleted.
1815  *
1816  * Return: Success or Failure
1817  */
ol_txrx_pdev_detach(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,int force)1818 static QDF_STATUS ol_txrx_pdev_detach(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
1819 				      int force)
1820 {
1821 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1822 	struct ol_txrx_pdev_t *pdev = ol_txrx_get_pdev_from_pdev_id(soc,
1823 								    pdev_id);
1824 	struct ol_txrx_stats_req_internal *req, *temp_req;
1825 	int i = 0;
1826 
1827 	if (!soc) {
1828 		ol_txrx_err("soc is NULL");
1829 		return QDF_STATUS_E_FAILURE;
1830 	}
1831 
1832 	/*checking to ensure txrx pdev structure is not NULL */
1833 	if (!pdev) {
1834 		ol_txrx_err("pdev is NULL");
1835 		return QDF_STATUS_E_FAILURE;
1836 	}
1837 
1838 	qdf_spin_lock_bh(&pdev->req_list_spinlock);
1839 	if (pdev->req_list_depth > 0)
1840 		ol_txrx_err(
1841 			"Warning: the txrx req list is not empty, depth=%d",
1842 			pdev->req_list_depth
1843 			);
1844 	TAILQ_FOREACH_SAFE(req, &pdev->req_list, req_list_elem, temp_req) {
1845 		TAILQ_REMOVE(&pdev->req_list, req, req_list_elem);
1846 		pdev->req_list_depth--;
1847 		ol_txrx_err(
1848 			"%d: %pK,verbose(%d), concise(%d), up_m(0x%x), reset_m(0x%x)",
1849 			i++,
1850 			req,
1851 			req->base.print.verbose,
1852 			req->base.print.concise,
1853 			req->base.stats_type_upload_mask,
1854 			req->base.stats_type_reset_mask
1855 			);
1856 		qdf_mem_free(req);
1857 	}
1858 	qdf_spin_unlock_bh(&pdev->req_list_spinlock);
1859 
1860 	qdf_spinlock_destroy(&pdev->req_list_spinlock);
1861 	qdf_spinlock_destroy(&pdev->tx_mutex);
1862 
1863 	OL_RX_REORDER_TIMEOUT_CLEANUP(pdev);
1864 
1865 	if (pdev->cfg.is_high_latency)
1866 		ol_tx_sched_detach(pdev);
1867 
1868 	htt_deregister_rx_pkt_dump_callback(pdev->htt_pdev);
1869 
1870 	htt_pdev_free(pdev->htt_pdev);
1871 	ol_txrx_peer_find_detach(pdev);
1872 	ol_txrx_tso_stats_deinit(pdev);
1873 	ol_txrx_fw_stats_desc_pool_deinit(pdev);
1874 
1875 	ol_txrx_pdev_txq_log_destroy(pdev);
1876 	ol_txrx_pdev_grp_stat_destroy(pdev);
1877 
1878 	ol_txrx_debugfs_exit(pdev);
1879 	ol_unregister_peer_recovery_notifier();
1880 
1881 	soc->pdev_list[pdev->id] = NULL;
1882 	qdf_mem_free(pdev);
1883 
1884 	return QDF_STATUS_SUCCESS;
1885 }
1886 
1887 #if defined(QCA_HL_NETDEV_FLOW_CONTROL)
1888 
1889 /**
1890  * ol_txrx_vdev_per_vdev_tx_desc_init() - initialise per vdev tx desc count
1891  * related variables.
1892  * @vdev: the virtual device object
1893  *
1894  * Return: None
1895  */
1896 static inline void
ol_txrx_vdev_per_vdev_tx_desc_init(struct ol_txrx_vdev_t * vdev)1897 ol_txrx_vdev_per_vdev_tx_desc_init(struct ol_txrx_vdev_t *vdev)
1898 {
1899 	qdf_atomic_init(&vdev->tx_desc_count);
1900 	vdev->tx_desc_limit = 0;
1901 	vdev->queue_restart_th = 0;
1902 	vdev->prio_q_paused = 0;
1903 	vdev->queue_stop_th = 0;
1904 }
1905 #else
1906 
1907 static inline void
ol_txrx_vdev_per_vdev_tx_desc_init(struct ol_txrx_vdev_t * vdev)1908 ol_txrx_vdev_per_vdev_tx_desc_init(struct ol_txrx_vdev_t *vdev)
1909 {
1910 }
1911 #endif /* QCA_HL_NETDEV_FLOW_CONTROL */
1912 
1913 /**
1914  * ol_txrx_vdev_attach - Allocate and initialize the data object
1915  * for a new virtual device.
1916  *
1917  * @@soc_hdl - data path soc handle
1918  * @pdev_id - physical device instance id
1919  * @vdev_mac_addr - the MAC address of the virtual device
1920  * @vdev_id - the ID used to identify the virtual device to the target
1921  * @op_mode - whether this virtual device is operating as an AP,
1922  * an IBSS, or a STA
1923  * @subtype:  Subtype of the operating vdev
1924  *
1925  * Return: QDF_STATUS_SUCCESS on success,
1926 	   QDF error code on failure
1927  */
1928 static QDF_STATUS
ol_txrx_vdev_attach(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,struct cdp_vdev_info * vdev_info)1929 ol_txrx_vdev_attach(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
1930 		    struct cdp_vdev_info *vdev_info)
1931 {
1932 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1933 	struct ol_txrx_pdev_t *pdev = ol_txrx_get_pdev_from_pdev_id(soc,
1934 								    pdev_id);
1935 	uint8_t *vdev_mac_addr = vdev_info->vdev_mac_addr;
1936 	uint8_t vdev_id = vdev_info->vdev_id;
1937 	enum wlan_op_mode op_mode = vdev_info->op_mode;
1938 	enum wlan_op_subtype subtype = vdev_info->subtype;
1939 	enum QDF_OPMODE qdf_opmode = vdev_info->qdf_opmode;
1940 
1941 	struct ol_txrx_vdev_t *vdev;
1942 	QDF_STATUS qdf_status;
1943 
1944 	/* preconditions */
1945 	TXRX_ASSERT2(pdev);
1946 	TXRX_ASSERT2(vdev_mac_addr);
1947 
1948 	if (qdf_unlikely(!soc)) {
1949 		ol_txrx_err("soc is NULL");
1950 		return QDF_STATUS_E_INVAL;
1951 	}
1952 
1953 	vdev = qdf_mem_malloc(sizeof(*vdev));
1954 	if (!vdev)
1955 		return QDF_STATUS_E_NOMEM;    /* failure */
1956 
1957 	/* store provided params */
1958 	vdev->pdev = pdev;
1959 	vdev->vdev_id = vdev_id;
1960 	vdev->opmode = op_mode;
1961 	vdev->subtype = subtype;
1962 	vdev->qdf_opmode = qdf_opmode;
1963 
1964 	vdev->delete.pending = 0;
1965 	vdev->safemode = 0;
1966 	vdev->drop_unenc = 1;
1967 	vdev->num_filters = 0;
1968 	vdev->fwd_tx_packets = 0;
1969 	vdev->fwd_rx_packets = 0;
1970 
1971 	ol_txrx_vdev_per_vdev_tx_desc_init(vdev);
1972 
1973 	qdf_mem_copy(&vdev->mac_addr.raw[0], vdev_mac_addr,
1974 		     QDF_MAC_ADDR_SIZE);
1975 
1976 	TAILQ_INIT(&vdev->peer_list);
1977 	vdev->last_real_peer = NULL;
1978 
1979 #ifdef QCA_IBSS_SUPPORT
1980 	vdev->ibss_peer_num = 0;
1981 	vdev->ibss_peer_heart_beat_timer = 0;
1982 #endif
1983 
1984 	ol_txrx_vdev_txqs_init(vdev);
1985 
1986 	qdf_spinlock_create(&vdev->ll_pause.mutex);
1987 	vdev->ll_pause.paused_reason = 0;
1988 	vdev->ll_pause.txq.head = vdev->ll_pause.txq.tail = NULL;
1989 	vdev->ll_pause.txq.depth = 0;
1990 	qdf_atomic_init(&vdev->delete.detaching);
1991 	qdf_timer_init(pdev->osdev,
1992 			       &vdev->ll_pause.timer,
1993 			       ol_tx_vdev_ll_pause_queue_send, vdev,
1994 			       QDF_TIMER_TYPE_SW);
1995 	qdf_atomic_init(&vdev->os_q_paused);
1996 	qdf_atomic_set(&vdev->os_q_paused, 0);
1997 	vdev->tx_fl_lwm = 0;
1998 	vdev->tx_fl_hwm = 0;
1999 	vdev->rx = NULL;
2000 	vdev->wait_on_peer_id = OL_TXRX_INVALID_LOCAL_PEER_ID;
2001 	qdf_mem_zero(&vdev->last_peer_mac_addr,
2002 			sizeof(union ol_txrx_align_mac_addr_t));
2003 	qdf_spinlock_create(&vdev->flow_control_lock);
2004 	vdev->osif_flow_control_cb = NULL;
2005 	vdev->osif_flow_control_is_pause = NULL;
2006 	vdev->osif_fc_ctx = NULL;
2007 
2008 	vdev->txrx_stats.txack_success = 0;
2009 	vdev->txrx_stats.txack_failed = 0;
2010 
2011 	vdev->bundling_required = false;
2012 	qdf_spinlock_create(&vdev->bundle_queue.mutex);
2013 	vdev->bundle_queue.txq.head = NULL;
2014 	vdev->bundle_queue.txq.tail = NULL;
2015 	vdev->bundle_queue.txq.depth = 0;
2016 	qdf_timer_init(
2017 		pdev->osdev,
2018 		&vdev->bundle_queue.timer,
2019 		ol_tx_hl_vdev_bundle_timer,
2020 		vdev, QDF_TIMER_TYPE_SW);
2021 
2022 	/* Default MAX Q depth for every VDEV */
2023 	vdev->ll_pause.max_q_depth =
2024 		ol_tx_cfg_max_tx_queue_depth_ll(vdev->pdev->ctrl_pdev);
2025 	qdf_status = qdf_event_create(&vdev->wait_delete_comp);
2026 
2027 	ol_txrx_vdev_init_tcp_del_ack(vdev);
2028 
2029 	/* add this vdev into the pdev's list */
2030 	TAILQ_INSERT_TAIL(&pdev->vdev_list, vdev, vdev_list_elem);
2031 	if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2032 		pdev->monitor_vdev = vdev;
2033 
2034 	ol_txrx_hl_tdls_flag_reset(soc_hdl, vdev_id, false);
2035 
2036 	ol_txrx_dbg(
2037 		   "Created vdev %pK ("QDF_MAC_ADDR_FMT")",
2038 		   vdev,
2039 		   QDF_MAC_ADDR_REF(vdev->mac_addr.raw));
2040 
2041 	/*
2042 	 * We've verified that htt_op_mode == wlan_op_mode,
2043 	 * so no translation is needed.
2044 	 */
2045 	htt_vdev_attach(pdev->htt_pdev, vdev_id, op_mode);
2046 
2047 	return QDF_STATUS_SUCCESS;
2048 }
2049 
2050 /**
2051  * ol_txrx_vdev_register - Link a vdev's data object with the
2052  * matching OS shim vdev object.
2053  *
2054  * @soc_hdl: datapath soc handle
2055  * @vdev_id: the virtual device's id
2056  * @osif_vdev: the virtual device's OS shim object
2057  * @txrx_ops: (pointers to)functions used for tx and rx data xfer
2058  *
2059  *  The data object for a virtual device is created by the
2060  *  function ol_txrx_vdev_attach.  However, rather than fully
2061  *  linking the data vdev object with the vdev objects from the
2062  *  other subsystems that the data vdev object interacts with,
2063  *  the txrx_vdev_attach function focuses primarily on creating
2064  *  the data vdev object. After the creation of both the data
2065  *  vdev object and the OS shim vdev object, this
2066  *  txrx_osif_vdev_attach function is used to connect the two
2067  *  vdev objects, so the data SW can use the OS shim vdev handle
2068  *  when passing rx data received by a vdev up to the OS shim.
2069  */
ol_txrx_vdev_register(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,ol_osif_vdev_handle osif_vdev,struct ol_txrx_ops * txrx_ops)2070 static QDF_STATUS ol_txrx_vdev_register(struct cdp_soc_t *soc_hdl,
2071 					uint8_t vdev_id,
2072 					ol_osif_vdev_handle osif_vdev,
2073 					struct ol_txrx_ops *txrx_ops)
2074 {
2075 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
2076 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
2077 								     vdev_id);
2078 
2079 	if (qdf_unlikely(!vdev) || qdf_unlikely(!txrx_ops)) {
2080 		qdf_print("vdev/txrx_ops is NULL!");
2081 		qdf_assert(0);
2082 		return QDF_STATUS_E_FAILURE;
2083 	}
2084 
2085 	vdev->osif_dev = osif_vdev;
2086 	vdev->rx = txrx_ops->rx.rx;
2087 	vdev->stats_rx = txrx_ops->rx.stats_rx;
2088 	vdev->tx_comp = txrx_ops->tx.tx_comp;
2089 	vdev->vdev_del_notify = txrx_ops->vdev_del_notify;
2090 	txrx_ops->tx.tx = ol_tx_data;
2091 
2092 	return QDF_STATUS_SUCCESS;
2093 }
2094 
2095 /**
2096  * ol_txrx_set_privacy_filters - set the privacy filter
2097  * @vdev - the data virtual device object
2098  * @filter - filters to be set
2099  * @num - the number of filters
2100  *
2101  * Rx related. Set the privacy filters. When rx packets, check
2102  * the ether type, filter type and packet type to decide whether
2103  * discard these packets.
2104  */
2105 static void
ol_txrx_set_privacy_filters(ol_txrx_vdev_handle vdev,void * filters,uint32_t num)2106 ol_txrx_set_privacy_filters(ol_txrx_vdev_handle vdev,
2107 			    void *filters, uint32_t num)
2108 {
2109 	qdf_mem_copy(vdev->privacy_filters, filters,
2110 		     num * sizeof(struct privacy_exemption));
2111 	vdev->num_filters = num;
2112 }
2113 
2114 #if defined(CONFIG_HL_SUPPORT) || defined(QCA_LL_LEGACY_TX_FLOW_CONTROL)
2115 
2116 static void
ol_txrx_tx_desc_reset_vdev(ol_txrx_vdev_handle vdev)2117 ol_txrx_tx_desc_reset_vdev(ol_txrx_vdev_handle vdev)
2118 {
2119 	struct ol_txrx_pdev_t *pdev = vdev->pdev;
2120 	int i;
2121 	struct ol_tx_desc_t *tx_desc;
2122 
2123 	qdf_spin_lock_bh(&pdev->tx_mutex);
2124 	for (i = 0; i < pdev->tx_desc.pool_size; i++) {
2125 		tx_desc = ol_tx_desc_find(pdev, i);
2126 		if (tx_desc->vdev == vdev)
2127 			tx_desc->vdev = NULL;
2128 	}
2129 	qdf_spin_unlock_bh(&pdev->tx_mutex);
2130 }
2131 
2132 #else
2133 #ifdef QCA_LL_TX_FLOW_CONTROL_V2
ol_txrx_tx_desc_reset_vdev(ol_txrx_vdev_handle vdev)2134 static void ol_txrx_tx_desc_reset_vdev(ol_txrx_vdev_handle vdev)
2135 {
2136 	struct ol_txrx_pdev_t *pdev = vdev->pdev;
2137 	struct ol_tx_flow_pool_t *pool;
2138 	int i;
2139 	struct ol_tx_desc_t *tx_desc;
2140 
2141 	qdf_spin_lock_bh(&pdev->tx_desc.flow_pool_list_lock);
2142 	for (i = 0; i < pdev->tx_desc.pool_size; i++) {
2143 		tx_desc = ol_tx_desc_find(pdev, i);
2144 		if (!qdf_atomic_read(&tx_desc->ref_cnt))
2145 			/* not in use */
2146 			continue;
2147 
2148 		pool = tx_desc->pool;
2149 		qdf_spin_lock_bh(&pool->flow_pool_lock);
2150 		if (tx_desc->vdev == vdev)
2151 			tx_desc->vdev = NULL;
2152 		qdf_spin_unlock_bh(&pool->flow_pool_lock);
2153 	}
2154 	qdf_spin_unlock_bh(&pdev->tx_desc.flow_pool_list_lock);
2155 }
2156 
2157 #else
2158 static void
ol_txrx_tx_desc_reset_vdev(ol_txrx_vdev_handle vdev)2159 ol_txrx_tx_desc_reset_vdev(ol_txrx_vdev_handle vdev)
2160 {
2161 }
2162 #endif /* QCA_LL_TX_FLOW_CONTROL_V2 */
2163 #endif /* CONFIG_HL_SUPPORT */
2164 
2165 /**
2166  * ol_txrx_vdev_detach - Deallocate the specified data virtual
2167  * device object.
2168  * @soc_hdl - data path soc handle
2169  * @vdev_id: vdev id
2170  * @callback: function to call (if non-NULL) once the vdev has
2171  * been wholly deleted
2172  * @callback_context: context to provide in the callback
2173  *
2174  * All peers associated with the virtual device need to be deleted
2175  * (ol_txrx_peer_detach) before the virtual device itself is deleted.
2176  * However, for the peers to be fully deleted, the peer deletion has to
2177  * percolate through the target data FW and back up to the host data SW.
2178  * Thus, even though the host control SW may have issued a peer_detach
2179  * call for each of the vdev's peers, the peer objects may still be
2180  * allocated, pending removal of all references to them by the target FW.
2181  * In this case, though the vdev_detach function call will still return
2182  * immediately, the vdev itself won't actually be deleted, until the
2183  * deletions of all its peers complete.
2184  * The caller can provide a callback function pointer to be notified when
2185  * the vdev deletion actually happens - whether it's directly within the
2186  * vdev_detach call, or if it's deferred until all in-progress peer
2187  * deletions have completed.
2188  */
2189 static QDF_STATUS
ol_txrx_vdev_detach(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,ol_txrx_vdev_delete_cb callback,void * context)2190 ol_txrx_vdev_detach(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
2191 		    ol_txrx_vdev_delete_cb callback, void *context)
2192 {
2193 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
2194 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
2195 								     vdev_id);
2196 	struct ol_txrx_pdev_t *pdev;
2197 	ol_txrx_vdev_delete_cb vdev_del_notify;
2198 	void *vdev_del_context;
2199 
2200 	if (qdf_unlikely(!vdev))
2201 		return QDF_STATUS_E_FAILURE;
2202 
2203 	/* preconditions */
2204 	TXRX_ASSERT2(vdev);
2205 	pdev = vdev->pdev;
2206 
2207 	/* prevent anyone from restarting the ll_pause timer again */
2208 	qdf_atomic_set(&vdev->delete.detaching, 1);
2209 
2210 	vdev_del_notify = vdev->vdev_del_notify;
2211 	vdev_del_context = vdev->osif_dev;
2212 	ol_txrx_vdev_tx_queue_free(vdev);
2213 
2214 	qdf_spin_lock_bh(&vdev->ll_pause.mutex);
2215 	qdf_timer_stop(&vdev->ll_pause.timer);
2216 	vdev->ll_pause.is_q_timer_on = false;
2217 	while (vdev->ll_pause.txq.head) {
2218 		qdf_nbuf_t next = qdf_nbuf_next(vdev->ll_pause.txq.head);
2219 
2220 		qdf_nbuf_set_next(vdev->ll_pause.txq.head, NULL);
2221 		qdf_nbuf_tx_free(vdev->ll_pause.txq.head, QDF_NBUF_PKT_ERROR);
2222 		vdev->ll_pause.txq.head = next;
2223 	}
2224 	qdf_spin_unlock_bh(&vdev->ll_pause.mutex);
2225 
2226 	/* ll_pause timer should be deleted without any locks held, and
2227 	 * no timer function should be executed after this point because
2228 	 * qdf_timer_free is deleting the timer synchronously.
2229 	 */
2230 	qdf_timer_free(&vdev->ll_pause.timer);
2231 	qdf_spinlock_destroy(&vdev->ll_pause.mutex);
2232 
2233 	qdf_timer_free(&vdev->bundle_queue.timer);
2234 	qdf_spinlock_destroy(&vdev->bundle_queue.mutex);
2235 
2236 	qdf_spin_lock_bh(&vdev->flow_control_lock);
2237 	vdev->osif_flow_control_cb = NULL;
2238 	vdev->osif_flow_control_is_pause = NULL;
2239 	vdev->osif_fc_ctx = NULL;
2240 	qdf_spin_unlock_bh(&vdev->flow_control_lock);
2241 	qdf_spinlock_destroy(&vdev->flow_control_lock);
2242 
2243 	/* remove the vdev from its parent pdev's list */
2244 	TAILQ_REMOVE(&pdev->vdev_list, vdev, vdev_list_elem);
2245 
2246 	/*
2247 	 * Use peer_ref_mutex while accessing peer_list, in case
2248 	 * a peer is in the process of being removed from the list.
2249 	 */
2250 	qdf_spin_lock_bh(&pdev->peer_ref_mutex);
2251 	/* check that the vdev has no peers allocated */
2252 	if (!TAILQ_EMPTY(&vdev->peer_list)) {
2253 		/* debug print - will be removed later */
2254 		ol_txrx_dbg(
2255 			   "not deleting vdev object %pK ("QDF_MAC_ADDR_FMT") until deletion finishes for all its peers",
2256 			   vdev,
2257 			   QDF_MAC_ADDR_REF(vdev->mac_addr.raw));
2258 		/* indicate that the vdev needs to be deleted */
2259 		vdev->delete.pending = 1;
2260 		vdev->delete.callback = callback;
2261 		vdev->delete.context = context;
2262 		qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
2263 		return QDF_STATUS_E_FAILURE;
2264 	}
2265 	qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
2266 	qdf_event_destroy(&vdev->wait_delete_comp);
2267 
2268 	ol_txrx_dbg(
2269 		   "deleting vdev obj %pK ("QDF_MAC_ADDR_FMT")",
2270 		   vdev,
2271 		   QDF_MAC_ADDR_REF(vdev->mac_addr.raw));
2272 
2273 	htt_vdev_detach(pdev->htt_pdev, vdev->vdev_id);
2274 
2275 	/*
2276 	 * The ol_tx_desc_free might access the invalid content of vdev referred
2277 	 * by tx desc, since this vdev might be detached in another thread
2278 	 * asynchronous.
2279 	 *
2280 	 * Go through tx desc pool to set corresponding tx desc's vdev to NULL
2281 	 * when detach this vdev, and add vdev checking in the ol_tx_desc_free
2282 	 * to avoid crash.
2283 	 *
2284 	 */
2285 	ol_txrx_tx_desc_reset_vdev(vdev);
2286 
2287 	/*
2288 	 * Doesn't matter if there are outstanding tx frames -
2289 	 * they will be freed once the target sends a tx completion
2290 	 * message for them.
2291 	 */
2292 	qdf_mem_free(vdev);
2293 	if (callback)
2294 		callback(context);
2295 
2296 	if (vdev_del_notify)
2297 		vdev_del_notify(vdev_del_context);
2298 
2299 	return QDF_STATUS_SUCCESS;
2300 }
2301 
2302 /**
2303  * ol_txrx_flush_rx_frames() - flush cached rx frames
2304  * @peer: peer
2305  * @drop: set flag to drop frames
2306  *
2307  * Return: None
2308  */
ol_txrx_flush_rx_frames(struct ol_txrx_peer_t * peer,bool drop)2309 void ol_txrx_flush_rx_frames(struct ol_txrx_peer_t *peer,
2310 			     bool drop)
2311 {
2312 	struct ol_txrx_cached_bufq_t *bufqi;
2313 	struct ol_rx_cached_buf *cache_buf;
2314 	QDF_STATUS ret;
2315 	ol_txrx_rx_fp data_rx = NULL;
2316 
2317 	if (qdf_atomic_inc_return(&peer->flush_in_progress) > 1) {
2318 		qdf_atomic_dec(&peer->flush_in_progress);
2319 		return;
2320 	}
2321 
2322 	qdf_assert(peer->vdev);
2323 	qdf_spin_lock_bh(&peer->peer_info_lock);
2324 	bufqi = &peer->bufq_info;
2325 
2326 	if (peer->state >= OL_TXRX_PEER_STATE_CONN && peer->vdev->rx)
2327 		data_rx = peer->vdev->rx;
2328 	else
2329 		drop = true;
2330 	qdf_spin_unlock_bh(&peer->peer_info_lock);
2331 
2332 	qdf_spin_lock_bh(&bufqi->bufq_lock);
2333 	cache_buf = list_entry((&bufqi->cached_bufq)->next,
2334 				typeof(*cache_buf), list);
2335 	while (!list_empty(&bufqi->cached_bufq)) {
2336 		list_del(&cache_buf->list);
2337 		bufqi->curr--;
2338 		qdf_assert(bufqi->curr >= 0);
2339 		qdf_spin_unlock_bh(&bufqi->bufq_lock);
2340 		if (drop) {
2341 			qdf_nbuf_free(cache_buf->buf);
2342 		} else {
2343 			/* Flush the cached frames to HDD */
2344 			ret = data_rx(peer->vdev->osif_dev, cache_buf->buf);
2345 			if (ret != QDF_STATUS_SUCCESS)
2346 				qdf_nbuf_free(cache_buf->buf);
2347 		}
2348 		qdf_mem_free(cache_buf);
2349 		qdf_spin_lock_bh(&bufqi->bufq_lock);
2350 		cache_buf = list_entry((&bufqi->cached_bufq)->next,
2351 				typeof(*cache_buf), list);
2352 	}
2353 	bufqi->qdepth_no_thresh = bufqi->curr;
2354 	qdf_spin_unlock_bh(&bufqi->bufq_lock);
2355 	qdf_atomic_dec(&peer->flush_in_progress);
2356 }
2357 
ol_txrx_flush_cache_rx_queue(void)2358 static void ol_txrx_flush_cache_rx_queue(void)
2359 {
2360 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
2361 	struct ol_txrx_peer_t *peer;
2362 	struct ol_txrx_vdev_t *vdev;
2363 	ol_txrx_pdev_handle pdev;
2364 
2365 	if (qdf_unlikely(!soc))
2366 		return;
2367 
2368 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
2369 	if (!pdev)
2370 		return;
2371 
2372 	TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
2373 		TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) {
2374 			ol_txrx_flush_rx_frames(peer, 1);
2375 		}
2376 	}
2377 }
2378 
2379 /* Define short name to use in cds_trigger_recovery */
2380 #define PEER_DEL_TIMEOUT QDF_PEER_DELETION_TIMEDOUT
2381 
2382 /**
2383  * ol_txrx_dump_peer_access_list() - dump peer access list
2384  * @peer: peer handle
2385  *
2386  * This function will dump if any peer debug ids are still accessing peer
2387  *
2388  * Return: None
2389  */
ol_txrx_dump_peer_access_list(ol_txrx_peer_handle peer)2390 static void ol_txrx_dump_peer_access_list(ol_txrx_peer_handle peer)
2391 {
2392 	u32 i;
2393 	u32 pending_ref;
2394 
2395 	for (i = 0; i < PEER_DEBUG_ID_MAX; i++) {
2396 		pending_ref = qdf_atomic_read(&peer->access_list[i]);
2397 		if (pending_ref)
2398 			ol_txrx_info_high("id %d pending refs %d",
2399 					  i, pending_ref);
2400 	}
2401 }
2402 
2403 /**
2404  * ol_txrx_peer_attach - Allocate and set up references for a
2405  * data peer object.
2406  * @soc_hdl - data path soc handle
2407  * @vdev_id - virtual device instance id
2408  * @peer_mac_addr - MAC address of the new peer
2409  *
2410  * When an association with a peer starts, the host's control SW
2411  * uses this function to inform the host data SW.
2412  * The host data SW allocates its own peer object, and stores a
2413  * reference to the control peer object within the data peer object.
2414  * The host data SW also stores a reference to the virtual device
2415  * that the peer is associated with.  This virtual device handle is
2416  * used when the data SW delivers rx data frames to the OS shim layer.
2417  * The host data SW returns a handle to the new peer data object,
2418  * so a reference within the control peer object can be set to the
2419  * data peer object.
2420  *
2421  * Return: QDF status code
2422  */
2423 static QDF_STATUS
ol_txrx_peer_attach(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,uint8_t * peer_mac_addr,enum cdp_peer_type peer_type)2424 ol_txrx_peer_attach(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
2425 		    uint8_t *peer_mac_addr, enum cdp_peer_type peer_type)
2426 {
2427 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
2428 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
2429 								     vdev_id);
2430 	struct ol_txrx_peer_t *peer;
2431 	struct ol_txrx_peer_t *temp_peer;
2432 	uint8_t i;
2433 	bool wait_on_deletion = false;
2434 	unsigned long rc;
2435 	struct ol_txrx_pdev_t *pdev;
2436 	bool cmp_wait_mac = false;
2437 	uint8_t zero_mac_addr[QDF_MAC_ADDR_SIZE] = { 0, 0, 0, 0, 0, 0 };
2438 	u8 check_valid = 0;
2439 
2440 	/* preconditions */
2441 	TXRX_ASSERT2(vdev);
2442 	TXRX_ASSERT2(peer_mac_addr);
2443 
2444 	pdev = vdev->pdev;
2445 	TXRX_ASSERT2(pdev);
2446 
2447 	if (pdev->enable_peer_unmap_conf_support)
2448 		check_valid = 1;
2449 
2450 	if (qdf_mem_cmp(&zero_mac_addr, &vdev->last_peer_mac_addr,
2451 				QDF_MAC_ADDR_SIZE))
2452 		cmp_wait_mac = true;
2453 
2454 	qdf_spin_lock_bh(&pdev->peer_ref_mutex);
2455 	/* check for duplicate existing peer */
2456 	TAILQ_FOREACH(temp_peer, &vdev->peer_list, peer_list_elem) {
2457 		if (!ol_txrx_peer_find_mac_addr_cmp(&temp_peer->mac_addr,
2458 			(union ol_txrx_align_mac_addr_t *)peer_mac_addr) &&
2459 			(check_valid == 0 || temp_peer->valid)) {
2460 			ol_txrx_info_high(
2461 				"vdev_id %d ("QDF_MAC_ADDR_FMT") already exists",
2462 				vdev->vdev_id,
2463 				QDF_MAC_ADDR_REF(peer_mac_addr));
2464 			if (qdf_atomic_read(&temp_peer->delete_in_progress)) {
2465 				vdev->wait_on_peer_id = temp_peer->local_id;
2466 				qdf_event_reset(&vdev->wait_delete_comp);
2467 				wait_on_deletion = true;
2468 				break;
2469 			} else {
2470 				qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
2471 				return QDF_STATUS_E_FAILURE;
2472 			}
2473 		}
2474 		if (cmp_wait_mac && !ol_txrx_peer_find_mac_addr_cmp(
2475 					&temp_peer->mac_addr,
2476 					&vdev->last_peer_mac_addr) &&
2477 					(check_valid == 0 ||
2478 					 temp_peer->valid)) {
2479 			ol_txrx_info_high(
2480 				"vdev_id %d ("QDF_MAC_ADDR_FMT") old peer exists",
2481 				vdev->vdev_id,
2482 				QDF_MAC_ADDR_REF(vdev->last_peer_mac_addr.raw));
2483 			if (qdf_atomic_read(&temp_peer->delete_in_progress)) {
2484 				vdev->wait_on_peer_id = temp_peer->local_id;
2485 				qdf_event_reset(&vdev->wait_delete_comp);
2486 				wait_on_deletion = true;
2487 				break;
2488 			} else {
2489 				qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
2490 				ol_txrx_err("peer not found");
2491 				return QDF_STATUS_E_FAILURE;
2492 			}
2493 		}
2494 	}
2495 	qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
2496 
2497 	qdf_mem_zero(&vdev->last_peer_mac_addr,
2498 			sizeof(union ol_txrx_align_mac_addr_t));
2499 	if (wait_on_deletion) {
2500 		/* wait for peer deletion */
2501 		rc = qdf_wait_for_event_completion(&vdev->wait_delete_comp,
2502 					   PEER_DELETION_TIMEOUT);
2503 		if (QDF_STATUS_SUCCESS != rc) {
2504 			ol_txrx_err("error waiting for peer_id(%d) deletion, status %d",
2505 				    vdev->wait_on_peer_id, (int) rc);
2506 			/* Added for debugging only */
2507 			ol_txrx_dump_peer_access_list(temp_peer);
2508 			wlan_roam_debug_dump_table();
2509 			vdev->wait_on_peer_id = OL_TXRX_INVALID_LOCAL_PEER_ID;
2510 
2511 			return QDF_STATUS_E_FAILURE;
2512 		}
2513 	}
2514 
2515 	peer = qdf_mem_malloc(sizeof(*peer));
2516 	if (!peer)
2517 		return QDF_STATUS_E_NOMEM;
2518 
2519 	/* store provided params */
2520 	peer->vdev = vdev;
2521 	qdf_mem_copy(&peer->mac_addr.raw[0], peer_mac_addr,
2522 		     QDF_MAC_ADDR_SIZE);
2523 
2524 	ol_txrx_peer_txqs_init(pdev, peer);
2525 
2526 	INIT_LIST_HEAD(&peer->bufq_info.cached_bufq);
2527 	qdf_spin_lock_bh(&pdev->peer_ref_mutex);
2528 	/* add this peer into the vdev's list */
2529 	TAILQ_INSERT_TAIL(&vdev->peer_list, peer, peer_list_elem);
2530 	qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
2531 	/* check whether this is a real peer (peer mac addr != vdev mac addr) */
2532 	if (ol_txrx_peer_find_mac_addr_cmp(&vdev->mac_addr, &peer->mac_addr)) {
2533 		qdf_spin_lock_bh(&pdev->last_real_peer_mutex);
2534 		vdev->last_real_peer = peer;
2535 		qdf_spin_unlock_bh(&pdev->last_real_peer_mutex);
2536 	}
2537 
2538 	peer->rx_opt_proc = pdev->rx_opt_proc;
2539 
2540 	ol_rx_peer_init(pdev, peer);
2541 
2542 	/* initialize the peer_id */
2543 	for (i = 0; i < MAX_NUM_PEER_ID_PER_PEER; i++)
2544 		peer->peer_ids[i] = HTT_INVALID_PEER;
2545 
2546 	qdf_spinlock_create(&peer->peer_info_lock);
2547 	qdf_spinlock_create(&peer->bufq_info.bufq_lock);
2548 
2549 	peer->bufq_info.thresh = OL_TXRX_CACHED_BUFQ_THRESH;
2550 
2551 	qdf_atomic_init(&peer->delete_in_progress);
2552 	qdf_atomic_init(&peer->flush_in_progress);
2553 	qdf_atomic_init(&peer->ref_cnt);
2554 	qdf_atomic_init(&peer->del_ref_cnt);
2555 
2556 	for (i = 0; i < PEER_DEBUG_ID_MAX; i++)
2557 		qdf_atomic_init(&peer->access_list[i]);
2558 
2559 	/* keep one reference for attach */
2560 	ol_txrx_peer_get_ref(peer, PEER_DEBUG_ID_OL_PEER_ATTACH);
2561 
2562 	/* Set a flag to indicate peer create is pending in firmware */
2563 	qdf_atomic_init(&peer->fw_create_pending);
2564 	qdf_atomic_set(&peer->fw_create_pending, 1);
2565 
2566 	peer->valid = 1;
2567 	qdf_timer_init(pdev->osdev, &peer->peer_unmap_timer,
2568 		       peer_unmap_timer_handler, peer, QDF_TIMER_TYPE_SW);
2569 
2570 	ol_txrx_peer_find_hash_add(pdev, peer);
2571 
2572 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH,
2573 		   "vdev %pK created peer %pK ref_cnt %d ("QDF_MAC_ADDR_FMT")",
2574 		   vdev, peer, qdf_atomic_read(&peer->ref_cnt),
2575 		   QDF_MAC_ADDR_REF(peer->mac_addr.raw));
2576 	/*
2577 	 * For every peer MAp message search and set if bss_peer
2578 	 */
2579 	if (qdf_mem_cmp(peer->mac_addr.raw, vdev->mac_addr.raw,
2580 				QDF_MAC_ADDR_SIZE))
2581 		peer->bss_peer = 1;
2582 
2583 	/*
2584 	 * The peer starts in the "disc" state while association is in progress.
2585 	 * Once association completes, the peer will get updated to "auth" state
2586 	 * by a call to ol_txrx_peer_state_update if the peer is in open mode,
2587 	 * or else to the "conn" state. For non-open mode, the peer will
2588 	 * progress to "auth" state once the authentication completes.
2589 	 */
2590 	peer->state = OL_TXRX_PEER_STATE_INVALID;
2591 	ol_txrx_peer_state_update(soc_hdl, peer->mac_addr.raw,
2592 				  OL_TXRX_PEER_STATE_DISC);
2593 
2594 #ifdef QCA_SUPPORT_PEER_DATA_RX_RSSI
2595 	peer->rssi_dbm = HTT_RSSI_INVALID;
2596 #endif
2597 	if ((QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) &&
2598 	    !pdev->self_peer) {
2599 		pdev->self_peer = peer;
2600 		/*
2601 		 * No Tx in monitor mode, otherwise results in target assert.
2602 		 * Setting disable_intrabss_fwd to true
2603 		 */
2604 		ol_vdev_rx_set_intrabss_fwd(soc_hdl, vdev_id, true);
2605 	}
2606 
2607 	ol_txrx_local_peer_id_alloc(pdev, peer);
2608 
2609 	return QDF_STATUS_SUCCESS;
2610 }
2611 
2612 #undef PEER_DEL_TIMEOUT
2613 
2614 /*
2615  * Discarding tx filter - removes all data frames (disconnected state)
2616  */
ol_tx_filter_discard(struct ol_txrx_msdu_info_t * tx_msdu_info)2617 static A_STATUS ol_tx_filter_discard(struct ol_txrx_msdu_info_t *tx_msdu_info)
2618 {
2619 	return A_ERROR;
2620 }
2621 
2622 /*
2623  * Non-autentication tx filter - filters out data frames that are not
2624  * related to authentication, but allows EAPOL (PAE) or WAPI (WAI)
2625  * data frames (connected state)
2626  */
ol_tx_filter_non_auth(struct ol_txrx_msdu_info_t * tx_msdu_info)2627 static A_STATUS ol_tx_filter_non_auth(struct ol_txrx_msdu_info_t *tx_msdu_info)
2628 {
2629 	return
2630 		(tx_msdu_info->htt.info.ethertype == ETHERTYPE_PAE ||
2631 		 tx_msdu_info->htt.info.ethertype ==
2632 		 ETHERTYPE_WAI) ? A_OK : A_ERROR;
2633 }
2634 
2635 /*
2636  * Pass-through tx filter - lets all data frames through (authenticated state)
2637  */
ol_tx_filter_pass_thru(struct ol_txrx_msdu_info_t * tx_msdu_info)2638 static A_STATUS ol_tx_filter_pass_thru(struct ol_txrx_msdu_info_t *tx_msdu_info)
2639 {
2640 	return A_OK;
2641 }
2642 
2643 /**
2644  * ol_txrx_peer_get_peer_mac_addr() - return mac_addr from peer handle.
2645  * @peer: handle to peer
2646  *
2647  * returns mac addrs for module which do not know peer type
2648  *
2649  * Return: the mac_addr from peer
2650  */
2651 static uint8_t *
ol_txrx_peer_get_peer_mac_addr(void * ppeer)2652 ol_txrx_peer_get_peer_mac_addr(void *ppeer)
2653 {
2654 	ol_txrx_peer_handle peer = ppeer;
2655 
2656 	if (!peer)
2657 		return NULL;
2658 
2659 	return peer->mac_addr.raw;
2660 }
2661 
2662 /**
2663  * ol_txrx_get_pn_info() - Returns pn info from peer
2664  * @soc_hdl: soc handle
2665  * @peer_mac: mac address of the peer
2666  * @vdev_id: vdev identifier
2667  * @last_pn_valid: return last_rmf_pn_valid value from peer.
2668  * @last_pn: return last_rmf_pn value from peer.
2669  * @rmf_pn_replays: return rmf_pn_replays value from peer.
2670  *
2671  * Return: NONE
2672  */
2673 static void
ol_txrx_get_pn_info(struct cdp_soc_t * soc_hdl,uint8_t * peer_mac,uint8_t vdev_id,uint8_t ** last_pn_valid,uint64_t ** last_pn,uint32_t ** rmf_pn_replays)2674 ol_txrx_get_pn_info(struct cdp_soc_t *soc_hdl, uint8_t *peer_mac,
2675 		    uint8_t vdev_id, uint8_t **last_pn_valid,
2676 		    uint64_t **last_pn, uint32_t **rmf_pn_replays)
2677 {
2678 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
2679 	ol_txrx_pdev_handle pdev;
2680 	ol_txrx_peer_handle peer;
2681 
2682 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
2683 	if (!pdev) {
2684 		ol_txrx_err("pdev is NULL");
2685 		return;
2686 	}
2687 
2688 	peer =  ol_txrx_peer_find_hash_find_get_ref(pdev, peer_mac, 0, 1,
2689 						    PEER_DEBUG_ID_OL_INTERNAL);
2690 	if (!peer)
2691 		return;
2692 
2693 	*last_pn_valid = &peer->last_rmf_pn_valid;
2694 	*last_pn = &peer->last_rmf_pn;
2695 	*rmf_pn_replays = &peer->rmf_pn_replays;
2696 
2697 	ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_INTERNAL);
2698 }
2699 
2700 /**
2701  * ol_txrx_get_opmode() - Return operation mode of vdev
2702  * @soc_hdl: Datapath soc handle
2703  * @vdev_id: id of vdev
2704  *
2705  * Return: interface opmode if SUCCESS,
2706  *	   0 if interface does not exist.
2707  */
ol_txrx_get_opmode(struct cdp_soc_t * soc_hdl,uint8_t vdev_id)2708 static int ol_txrx_get_opmode(struct cdp_soc_t *soc_hdl, uint8_t vdev_id)
2709 {
2710 	struct ol_txrx_vdev_t *vdev;
2711 
2712 	vdev = (struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
2713 	if (!vdev) {
2714 		ol_txrx_err("vdev for id %d is NULL", vdev_id);
2715 		return 0;
2716 	}
2717 
2718 	return vdev->opmode;
2719 }
2720 
2721 /**
2722  * ol_txrx_get_peer_state() - Return peer state of peer
2723  * @soc_hdl: datapath soc handle
2724  * @vdev_id: virtual interface id
2725  * @peer_mac: peer mac addr
2726  * @slowpath: called from slow path or not
2727  *
2728  * Return: return peer state
2729  */
ol_txrx_get_peer_state(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,uint8_t * peer_mac,bool slowpath)2730 static int ol_txrx_get_peer_state(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
2731 				  uint8_t *peer_mac, bool slowpath)
2732 {
2733 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
2734 	ol_txrx_pdev_handle pdev =
2735 		ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
2736 	ol_txrx_peer_handle peer;
2737 	enum ol_txrx_peer_state peer_state;
2738 
2739 	if (!pdev)
2740 		return QDF_STATUS_E_FAILURE;
2741 
2742 	peer =  ol_txrx_peer_find_hash_find_get_ref(pdev, peer_mac, 0, 1,
2743 						    PEER_DEBUG_ID_OL_INTERNAL);
2744 	if (!peer)
2745 		return QDF_STATUS_E_FAILURE;
2746 
2747 	peer_state = peer->state;
2748 	ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_INTERNAL);
2749 	if (peer->vdev->vdev_id != vdev_id)
2750 		return OL_TXRX_PEER_STATE_INVALID;
2751 
2752 	return peer_state;
2753 }
2754 
2755 /**
2756  * ol_txrx_get_vdev_mac_addr() - Return mac addr of vdev
2757  * @soc_hdl: datapath soc handle
2758  x @vdev_id: virtual interface id
2759  *
2760  * Return: vdev mac address
2761  */
2762 static uint8_t *
ol_txrx_get_vdev_mac_addr(struct cdp_soc_t * soc_hdl,uint8_t vdev_id)2763 ol_txrx_get_vdev_mac_addr(struct cdp_soc_t *soc_hdl, uint8_t vdev_id)
2764 {
2765 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
2766 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
2767 								     vdev_id);
2768 
2769 	if (!vdev)
2770 		return NULL;
2771 
2772 	return vdev->mac_addr.raw;
2773 }
2774 
2775 #ifdef currently_unused
2776 /**
2777  * ol_txrx_get_vdev_struct_mac_addr() - Return handle to struct qdf_mac_addr of
2778  * vdev
2779  * @vdev: vdev handle
2780  *
2781  * Return: Handle to struct qdf_mac_addr
2782  */
2783 struct qdf_mac_addr *
ol_txrx_get_vdev_struct_mac_addr(ol_txrx_vdev_handle vdev)2784 ol_txrx_get_vdev_struct_mac_addr(ol_txrx_vdev_handle vdev)
2785 {
2786 	return (struct qdf_mac_addr *)&(vdev->mac_addr);
2787 }
2788 #endif
2789 
2790 #ifdef currently_unused
2791 /**
2792  * ol_txrx_get_pdev_from_vdev() - Return handle to pdev of vdev
2793  * @vdev: vdev handle
2794  *
2795  * Return: Handle to pdev
2796  */
ol_txrx_get_pdev_from_vdev(ol_txrx_vdev_handle vdev)2797 ol_txrx_pdev_handle ol_txrx_get_pdev_from_vdev(ol_txrx_vdev_handle vdev)
2798 {
2799 	return vdev->pdev;
2800 }
2801 #endif
2802 
2803 /**
2804  * ol_txrx_get_ctrl_pdev_from_vdev() - Return control pdev of vdev
2805  * @soc_hdl: datapath soc handle
2806  * @vdev_id: virtual interface id
2807  *
2808  * Return: Handle to control pdev
2809  */
2810 static struct cdp_cfg *
ol_txrx_get_ctrl_pdev_from_vdev(struct cdp_soc_t * soc_hdl,uint8_t vdev_id)2811 ol_txrx_get_ctrl_pdev_from_vdev(struct cdp_soc_t *soc_hdl, uint8_t vdev_id)
2812 {
2813 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
2814 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
2815 								     vdev_id);
2816 
2817 	if (!vdev)
2818 		return NULL;
2819 
2820 	return vdev->pdev->ctrl_pdev;
2821 }
2822 
2823 /**
2824  * ol_txrx_is_rx_fwd_disabled() - returns the rx_fwd_disabled status on vdev
2825  * @vdev: vdev handle
2826  *
2827  * Return: Rx Fwd disabled status
2828  */
2829 static uint8_t
ol_txrx_is_rx_fwd_disabled(struct cdp_vdev * pvdev)2830 ol_txrx_is_rx_fwd_disabled(struct cdp_vdev *pvdev)
2831 {
2832 	struct ol_txrx_vdev_t *vdev = (struct ol_txrx_vdev_t *)pvdev;
2833 	struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)
2834 					vdev->pdev->ctrl_pdev;
2835 	return cfg->rx_fwd_disabled;
2836 }
2837 
2838 #ifdef QCA_IBSS_SUPPORT
2839 /**
2840  * ol_txrx_update_ibss_add_peer_num_of_vdev() - update and return peer num
2841  * @soc_hdl: datapath soc handle
2842  * @vdev_id: virtual interface id
2843  * @peer_num_delta: peer nums to be adjusted
2844  *
2845  * Return: -1 for failure or total peer nums after adjustment.
2846  */
2847 static int16_t
ol_txrx_update_ibss_add_peer_num_of_vdev(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,int16_t peer_num_delta)2848 ol_txrx_update_ibss_add_peer_num_of_vdev(struct cdp_soc_t *soc_hdl,
2849 					 uint8_t vdev_id,
2850 					 int16_t peer_num_delta)
2851 {
2852 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
2853 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
2854 								     vdev_id);
2855 	int16_t new_peer_num;
2856 
2857 	if (!vdev)
2858 		return QDF_STATUS_E_FAILURE;
2859 
2860 	new_peer_num = vdev->ibss_peer_num + peer_num_delta;
2861 	if (new_peer_num > MAX_PEERS || new_peer_num < 0)
2862 		return OL_TXRX_INVALID_NUM_PEERS;
2863 
2864 	vdev->ibss_peer_num = new_peer_num;
2865 
2866 	return new_peer_num;
2867 }
2868 
2869 /**
2870  * ol_txrx_set_ibss_vdev_heart_beat_timer() - Update ibss vdev heart
2871  * beat timer
2872  * @soc_hdl: Datapath soc handle
2873  * @vdev_id: id of vdev
2874  * @timer_value_sec: new heart beat timer value
2875  *
2876  * Return: Old timer value set in vdev.
2877  */
2878 static uint16_t
ol_txrx_set_ibss_vdev_heart_beat_timer(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,uint16_t timer_value_sec)2879 ol_txrx_set_ibss_vdev_heart_beat_timer(struct cdp_soc_t *soc_hdl,
2880 				       uint8_t vdev_id,
2881 				       uint16_t timer_value_sec)
2882 {
2883 	struct ol_txrx_vdev_t *vdev =
2884 		(struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
2885 	uint16_t old_timer_value = vdev->ibss_peer_heart_beat_timer;
2886 
2887 	vdev->ibss_peer_heart_beat_timer = timer_value_sec;
2888 
2889 	return old_timer_value;
2890 }
2891 #else /* !QCA_IBSS_SUPPORT */
2892 static inline int16_t
ol_txrx_update_ibss_add_peer_num_of_vdev(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,int16_t peer_num_delta)2893 ol_txrx_update_ibss_add_peer_num_of_vdev(struct cdp_soc_t *soc_hdl,
2894 					 uint8_t vdev_id,
2895 					 int16_t peer_num_delta)
2896 {
2897 	return 0;
2898 }
2899 
ol_txrx_set_ibss_vdev_heart_beat_timer(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,uint16_t timer_value_sec)2900 static uint16_t ol_txrx_set_ibss_vdev_heart_beat_timer(
2901 				struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
2902 				uint16_t timer_value_sec)
2903 {
2904 	return 0;
2905 }
2906 #endif /* QCA_IBSS_SUPPORT */
2907 
2908 #ifdef WLAN_FEATURE_DSRC
2909 /**
2910  * ol_txrx_set_ocb_chan_info() - set OCB channel info to vdev.
2911  * @soc_hdl: Datapath soc handle
2912  * @vdev_id: id of vdev
2913  * @ocb_set_chan: OCB channel information to be set in vdev.
2914  *
2915  * Return: NONE
2916  */
2917 static void
ol_txrx_set_ocb_chan_info(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,struct ol_txrx_ocb_set_chan ocb_set_chan)2918 ol_txrx_set_ocb_chan_info(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
2919 			  struct ol_txrx_ocb_set_chan ocb_set_chan)
2920 {
2921 	struct ol_txrx_vdev_t *vdev =
2922 		(struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
2923 
2924 	if (qdf_unlikely(!vdev)) {
2925 		ol_txrx_err("pdev is NULL");
2926 		return;
2927 	}
2928 
2929 	vdev->ocb_channel_info = ocb_set_chan.ocb_channel_info;
2930 	vdev->ocb_channel_count = ocb_set_chan.ocb_channel_count;
2931 }
2932 
2933 /**
2934  * ol_txrx_get_ocb_chan_info() - return handle to vdev ocb_channel_info
2935  * @soc_hdl: Datapath soc handle
2936  * @vdev_id: id of vdev
2937  *
2938  * Return: handle to struct ol_txrx_ocb_chan_info
2939  */
2940 static struct ol_txrx_ocb_chan_info *
ol_txrx_get_ocb_chan_info(struct cdp_soc_t * soc_hdl,uint8_t vdev_id)2941 ol_txrx_get_ocb_chan_info(struct cdp_soc_t *soc_hdl, uint8_t vdev_id)
2942 {
2943 	struct ol_txrx_vdev_t *vdev =
2944 		(struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
2945 
2946 	if (qdf_unlikely(!vdev)) {
2947 		ol_txrx_err("pdev is NULL");
2948 		return NULL;
2949 	}
2950 
2951 	return vdev->ocb_channel_info;
2952 }
2953 #endif
2954 
ol_txrx_peer_state_update(struct cdp_soc_t * soc_hdl,uint8_t * peer_mac,enum ol_txrx_peer_state state)2955 QDF_STATUS ol_txrx_peer_state_update(struct cdp_soc_t *soc_hdl,
2956 				     uint8_t *peer_mac,
2957 				     enum ol_txrx_peer_state state)
2958 {
2959 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
2960 	ol_txrx_pdev_handle pdev =
2961 		ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
2962 	struct ol_txrx_peer_t *peer;
2963 	int    peer_ref_cnt;
2964 
2965 	if (qdf_unlikely(!pdev)) {
2966 		ol_txrx_err("Pdev is NULL");
2967 		qdf_assert(0);
2968 		return QDF_STATUS_E_INVAL;
2969 	}
2970 
2971 	peer =  ol_txrx_peer_find_hash_find_get_ref(pdev, peer_mac, 0, 1,
2972 						    PEER_DEBUG_ID_OL_INTERNAL);
2973 	if (!peer) {
2974 		ol_txrx_err(
2975 			   "peer is null for peer_mac 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
2976 			   peer_mac[0], peer_mac[1], peer_mac[2], peer_mac[3],
2977 			   peer_mac[4], peer_mac[5]);
2978 		return QDF_STATUS_E_INVAL;
2979 	}
2980 
2981 	/* TODO: Should we send WMI command of the connection state? */
2982 	/* avoid multiple auth state change. */
2983 	if (peer->state == state) {
2984 #ifdef TXRX_PRINT_VERBOSE_ENABLE
2985 		ol_txrx_dbg("no state change, returns directly");
2986 #endif
2987 		peer_ref_cnt = ol_txrx_peer_release_ref
2988 						(peer,
2989 						 PEER_DEBUG_ID_OL_INTERNAL);
2990 		return QDF_STATUS_SUCCESS;
2991 	}
2992 
2993 	ol_txrx_dbg("change from %d to %d",
2994 		    peer->state, state);
2995 
2996 	peer->tx_filter = (state == OL_TXRX_PEER_STATE_AUTH)
2997 		? ol_tx_filter_pass_thru
2998 		: ((state == OL_TXRX_PEER_STATE_CONN)
2999 		   ? ol_tx_filter_non_auth
3000 		   : ol_tx_filter_discard);
3001 
3002 	if (peer->vdev->pdev->cfg.host_addba) {
3003 		if (state == OL_TXRX_PEER_STATE_AUTH) {
3004 			int tid;
3005 			/*
3006 			 * Pause all regular (non-extended) TID tx queues until
3007 			 * data arrives and ADDBA negotiation has completed.
3008 			 */
3009 			ol_txrx_dbg("pause peer and unpause mgmt/non-qos");
3010 			ol_txrx_peer_pause(peer); /* pause all tx queues */
3011 			/* unpause mgmt and non-QoS tx queues */
3012 			for (tid = OL_TX_NUM_QOS_TIDS;
3013 			     tid < OL_TX_NUM_TIDS; tid++)
3014 				ol_txrx_peer_tid_unpause(peer, tid);
3015 		}
3016 	}
3017 	peer_ref_cnt = ol_txrx_peer_release_ref(peer,
3018 						PEER_DEBUG_ID_OL_INTERNAL);
3019 	/*
3020 	 * after ol_txrx_peer_release_ref, peer object cannot be accessed
3021 	 * if the return code was 0
3022 	 */
3023 	if (peer_ref_cnt > 0)
3024 		/*
3025 		 * Set the state after the Pause to avoid the race condiction
3026 		 * with ADDBA check in tx path
3027 		 */
3028 		peer->state = state;
3029 	return QDF_STATUS_SUCCESS;
3030 }
3031 
3032 void
ol_txrx_peer_keyinstalled_state_update(struct ol_txrx_peer_t * peer,uint8_t val)3033 ol_txrx_peer_keyinstalled_state_update(struct ol_txrx_peer_t *peer, uint8_t val)
3034 {
3035 	peer->keyinstalled = val;
3036 }
3037 
3038 void
ol_txrx_peer_update(ol_txrx_vdev_handle vdev,uint8_t * peer_mac,union ol_txrx_peer_update_param_t * param,enum ol_txrx_peer_update_select_t select)3039 ol_txrx_peer_update(ol_txrx_vdev_handle vdev,
3040 		    uint8_t *peer_mac,
3041 		    union ol_txrx_peer_update_param_t *param,
3042 		    enum ol_txrx_peer_update_select_t select)
3043 {
3044 	struct ol_txrx_peer_t *peer;
3045 
3046 	peer = ol_txrx_peer_find_hash_find_get_ref(vdev->pdev, peer_mac, 0, 1,
3047 						   PEER_DEBUG_ID_OL_INTERNAL);
3048 	if (!peer) {
3049 		ol_txrx_dbg("peer is null");
3050 		return;
3051 	}
3052 
3053 	switch (select) {
3054 	case ol_txrx_peer_update_qos_capable:
3055 	{
3056 		/* save qos_capable here txrx peer,
3057 		 * when HTT_ISOC_T2H_MSG_TYPE_PEER_INFO comes then save.
3058 		 */
3059 		peer->qos_capable = param->qos_capable;
3060 		/*
3061 		 * The following function call assumes that the peer has a
3062 		 * single ID. This is currently true, and
3063 		 * is expected to remain true.
3064 		 */
3065 		htt_peer_qos_update(peer->vdev->pdev->htt_pdev,
3066 				    peer->peer_ids[0],
3067 				    peer->qos_capable);
3068 		break;
3069 	}
3070 	case ol_txrx_peer_update_uapsdMask:
3071 	{
3072 		peer->uapsd_mask = param->uapsd_mask;
3073 		htt_peer_uapsdmask_update(peer->vdev->pdev->htt_pdev,
3074 					  peer->peer_ids[0],
3075 					  peer->uapsd_mask);
3076 		break;
3077 	}
3078 	case ol_txrx_peer_update_peer_security:
3079 	{
3080 		enum ol_sec_type sec_type = param->sec_type;
3081 		enum htt_sec_type peer_sec_type = htt_sec_type_none;
3082 
3083 		switch (sec_type) {
3084 		case ol_sec_type_none:
3085 			peer_sec_type = htt_sec_type_none;
3086 			break;
3087 		case ol_sec_type_wep128:
3088 			peer_sec_type = htt_sec_type_wep128;
3089 			break;
3090 		case ol_sec_type_wep104:
3091 			peer_sec_type = htt_sec_type_wep104;
3092 			break;
3093 		case ol_sec_type_wep40:
3094 			peer_sec_type = htt_sec_type_wep40;
3095 			break;
3096 		case ol_sec_type_tkip:
3097 			peer_sec_type = htt_sec_type_tkip;
3098 			break;
3099 		case ol_sec_type_tkip_nomic:
3100 			peer_sec_type = htt_sec_type_tkip_nomic;
3101 			break;
3102 		case ol_sec_type_aes_ccmp:
3103 			peer_sec_type = htt_sec_type_aes_ccmp;
3104 			break;
3105 		case ol_sec_type_wapi:
3106 			peer_sec_type = htt_sec_type_wapi;
3107 			break;
3108 		default:
3109 			peer_sec_type = htt_sec_type_none;
3110 			break;
3111 		}
3112 
3113 		peer->security[txrx_sec_ucast].sec_type =
3114 			peer->security[txrx_sec_mcast].sec_type =
3115 				peer_sec_type;
3116 
3117 		break;
3118 	}
3119 	default:
3120 	{
3121 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
3122 			  "ERROR: unknown param %d in %s", select,
3123 			  __func__);
3124 		break;
3125 	}
3126 	} /* switch */
3127 	ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_INTERNAL);
3128 }
3129 
3130 uint8_t
ol_txrx_peer_uapsdmask_get(struct ol_txrx_pdev_t * txrx_pdev,uint16_t peer_id)3131 ol_txrx_peer_uapsdmask_get(struct ol_txrx_pdev_t *txrx_pdev, uint16_t peer_id)
3132 {
3133 
3134 	struct ol_txrx_peer_t *peer;
3135 
3136 	peer = ol_txrx_peer_find_by_id(txrx_pdev, peer_id);
3137 	if (peer)
3138 		return peer->uapsd_mask;
3139 	return 0;
3140 }
3141 
3142 uint8_t
ol_txrx_peer_qoscapable_get(struct ol_txrx_pdev_t * txrx_pdev,uint16_t peer_id)3143 ol_txrx_peer_qoscapable_get(struct ol_txrx_pdev_t *txrx_pdev, uint16_t peer_id)
3144 {
3145 
3146 	struct ol_txrx_peer_t *peer_t =
3147 		ol_txrx_peer_find_by_id(txrx_pdev, peer_id);
3148 	if (peer_t)
3149 		return peer_t->qos_capable;
3150 	return 0;
3151 }
3152 
3153 /**
3154  * ol_txrx_peer_free_tids() - free tids for the peer
3155  * @peer: peer handle
3156  *
3157  * Return: None
3158  */
ol_txrx_peer_free_tids(ol_txrx_peer_handle peer)3159 static inline void ol_txrx_peer_free_tids(ol_txrx_peer_handle peer)
3160 {
3161 	int i = 0;
3162 	/*
3163 	 * 'array' is allocated in addba handler and is supposed to be
3164 	 * freed in delba handler. There is the case (for example, in
3165 	 * SSR) where delba handler is not called. Because array points
3166 	 * to address of 'base' by default and is reallocated in addba
3167 	 * handler later, only free the memory when the array does not
3168 	 * point to base.
3169 	 */
3170 	for (i = 0; i < OL_TXRX_NUM_EXT_TIDS; i++) {
3171 		if (peer->tids_rx_reorder[i].array !=
3172 		    &peer->tids_rx_reorder[i].base) {
3173 			ol_txrx_dbg("delete reorder arr, tid:%d", i);
3174 			qdf_mem_free(peer->tids_rx_reorder[i].array);
3175 			ol_rx_reorder_init(&peer->tids_rx_reorder[i],
3176 					   (uint8_t)i);
3177 		}
3178 	}
3179 }
3180 
3181 /**
3182  * ol_txrx_peer_drop_pending_frames() - drop pending frames in the RX queue
3183  * @peer: peer handle
3184  *
3185  * Drop pending packets pertaining to the peer from the RX thread queue.
3186  *
3187  * Return: None
3188  */
ol_txrx_peer_drop_pending_frames(struct ol_txrx_peer_t * peer)3189 static void ol_txrx_peer_drop_pending_frames(struct ol_txrx_peer_t *peer)
3190 {
3191 	p_cds_sched_context sched_ctx = get_cds_sched_ctxt();
3192 
3193 	if (sched_ctx)
3194 		cds_drop_rxpkt_by_staid(sched_ctx, peer->local_id);
3195 }
3196 
3197 /**
3198  * ol_txrx_peer_release_ref() - release peer reference
3199  * @peer: peer handle
3200  *
3201  * Release peer reference and delete peer if refcount is 0
3202  *
3203  * Return: Resulting peer ref_cnt after this function is invoked
3204  */
ol_txrx_peer_release_ref(ol_txrx_peer_handle peer,enum peer_debug_id_type debug_id)3205 int ol_txrx_peer_release_ref(ol_txrx_peer_handle peer,
3206 			     enum peer_debug_id_type debug_id)
3207 {
3208 	int    rc;
3209 	struct ol_txrx_vdev_t *vdev;
3210 	struct ol_txrx_pdev_t *pdev;
3211 	bool ref_silent = true;
3212 	int access_list = 0;
3213 	uint32_t err_code = 0;
3214 	int del_rc;
3215 
3216 	/* preconditions */
3217 	TXRX_ASSERT2(peer);
3218 
3219 	vdev = peer->vdev;
3220 	if (!vdev) {
3221 		ol_txrx_err("The vdev is not present anymore");
3222 		return -EINVAL;
3223 	}
3224 
3225 	pdev = vdev->pdev;
3226 	if (!pdev) {
3227 		ol_txrx_err("The pdev is not present anymore");
3228 		err_code = 0xbad2;
3229 		goto ERR_STATE;
3230 	}
3231 
3232 	if (debug_id >= PEER_DEBUG_ID_MAX || debug_id < 0) {
3233 		ol_txrx_err("incorrect debug_id %d ", debug_id);
3234 		err_code = 0xbad3;
3235 		goto ERR_STATE;
3236 	}
3237 
3238 	if (debug_id == PEER_DEBUG_ID_OL_RX_THREAD)
3239 		ref_silent = true;
3240 
3241 	if (!ref_silent)
3242 		wlan_roam_debug_log(vdev->vdev_id, DEBUG_PEER_UNREF_DELETE,
3243 				    DEBUG_INVALID_PEER_ID, &peer->mac_addr.raw,
3244 				    peer, 0xdead,
3245 				    qdf_atomic_read(&peer->ref_cnt));
3246 
3247 
3248 	/*
3249 	 * Hold the lock all the way from checking if the peer ref count
3250 	 * is zero until the peer references are removed from the hash
3251 	 * table and vdev list (if the peer ref count is zero).
3252 	 * This protects against a new HL tx operation starting to use the
3253 	 * peer object just after this function concludes it's done being used.
3254 	 * Furthermore, the lock needs to be held while checking whether the
3255 	 * vdev's list of peers is empty, to make sure that list is not modified
3256 	 * concurrently with the empty check.
3257 	 */
3258 	qdf_spin_lock_bh(&pdev->peer_ref_mutex);
3259 
3260 	/*
3261 	 * Check for the reference count before deleting the peer
3262 	 * as we noticed that sometimes we are re-entering this
3263 	 * function again which is leading to dead-lock.
3264 	 * (A double-free should never happen, so assert if it does.)
3265 	 */
3266 	rc = qdf_atomic_read(&(peer->ref_cnt));
3267 
3268 	if (rc == 0) {
3269 		qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
3270 		ol_txrx_err("The Peer is not present anymore");
3271 		qdf_assert(0);
3272 		return -EACCES;
3273 	}
3274 	/*
3275 	 * now decrement rc; this will be the return code.
3276 	 * 0 : peer deleted
3277 	 * >0: peer ref removed, but still has other references
3278 	 * <0: sanity failed - no changes to the state of the peer
3279 	 */
3280 	rc--;
3281 
3282 	if (!qdf_atomic_read(&peer->access_list[debug_id])) {
3283 		qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
3284 		ol_txrx_err("peer %pK ref was not taken by %d",
3285 			    peer, debug_id);
3286 		ol_txrx_dump_peer_access_list(peer);
3287 		QDF_BUG(0);
3288 		return -EACCES;
3289 	}
3290 	qdf_atomic_dec(&peer->access_list[debug_id]);
3291 
3292 	if (qdf_atomic_dec_and_test(&peer->ref_cnt)) {
3293 		u16 peer_id;
3294 		wlan_roam_debug_log(vdev->vdev_id,
3295 				    DEBUG_DELETING_PEER_OBJ,
3296 				    DEBUG_INVALID_PEER_ID,
3297 				    &peer->mac_addr.raw, peer, 0,
3298 				    qdf_atomic_read(&peer->ref_cnt));
3299 		peer_id = peer->local_id;
3300 
3301 		/* Drop all pending frames in the rx thread queue */
3302 		ol_txrx_peer_drop_pending_frames(peer);
3303 
3304 		/* remove the reference to the peer from the hash table */
3305 		ol_txrx_peer_find_hash_remove(pdev, peer);
3306 
3307 		/* remove the peer from its parent vdev's list */
3308 		TAILQ_REMOVE(&peer->vdev->peer_list, peer, peer_list_elem);
3309 
3310 		/* cleanup the Rx reorder queues for this peer */
3311 		ol_rx_peer_cleanup(vdev, peer);
3312 
3313 		qdf_spinlock_destroy(&peer->peer_info_lock);
3314 		qdf_spinlock_destroy(&peer->bufq_info.bufq_lock);
3315 
3316 		/* peer is removed from peer_list */
3317 		qdf_atomic_set(&peer->delete_in_progress, 0);
3318 
3319 		/*
3320 		 * Set wait_delete_comp event if the current peer id matches
3321 		 * with registered peer id.
3322 		 */
3323 		if (peer_id == vdev->wait_on_peer_id) {
3324 			qdf_event_set(&vdev->wait_delete_comp);
3325 			vdev->wait_on_peer_id = OL_TXRX_INVALID_LOCAL_PEER_ID;
3326 		}
3327 
3328 		qdf_timer_sync_cancel(&peer->peer_unmap_timer);
3329 		qdf_timer_free(&peer->peer_unmap_timer);
3330 
3331 		/* check whether the parent vdev has no peers left */
3332 		if (TAILQ_EMPTY(&vdev->peer_list)) {
3333 			/*
3334 			 * Check if the parent vdev was waiting for its peers
3335 			 * to be deleted, in order for it to be deleted too.
3336 			 */
3337 			if (vdev->delete.pending) {
3338 				ol_txrx_vdev_delete_cb vdev_delete_cb =
3339 					vdev->delete.callback;
3340 				void *vdev_delete_context =
3341 					vdev->delete.context;
3342 				ol_txrx_vdev_delete_cb vdev_del_notify =
3343 						vdev->vdev_del_notify;
3344 				void *vdev_del_context = vdev->osif_dev;
3345 				/*
3346 				 * Now that there are no references to the peer,
3347 				 * we can release the peer reference lock.
3348 				 */
3349 				qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
3350 
3351 				/*
3352 				 * The ol_tx_desc_free might access the invalid
3353 				 * content of vdev referred by tx desc, since
3354 				 * this vdev might be detached in another thread
3355 				 * asynchronous.
3356 				 *
3357 				 * Go through tx desc pool to set corresponding
3358 				 * tx desc's vdev to NULL when detach this vdev,
3359 				 * and add vdev checking in the ol_tx_desc_free
3360 				 * to avoid crash.
3361 				 */
3362 				ol_txrx_tx_desc_reset_vdev(vdev);
3363 				ol_txrx_dbg(
3364 					"deleting vdev object %pK ("QDF_MAC_ADDR_FMT") - its last peer is done",
3365 					vdev,
3366 					QDF_MAC_ADDR_REF(vdev->mac_addr.raw));
3367 				/* all peers are gone, go ahead and delete it */
3368 				qdf_mem_free(vdev);
3369 				if (vdev_delete_cb)
3370 					vdev_delete_cb(vdev_delete_context);
3371 
3372 				if (vdev_del_notify)
3373 					vdev_del_notify(vdev_del_context);
3374 			} else {
3375 				qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
3376 			}
3377 		} else {
3378 			qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
3379 		}
3380 
3381 		del_rc = qdf_atomic_read(&peer->del_ref_cnt);
3382 
3383 		ol_txrx_info_high("[%d][%d]: Deleting peer %pK ref_cnt -> %d del_ref_cnt -> %d %s",
3384 				  debug_id,
3385 				  qdf_atomic_read(&peer->access_list[debug_id]),
3386 				  peer, rc, del_rc,
3387 				  qdf_atomic_read(&peer->fw_create_pending) ==
3388 				  1 ? "(No Maps received)" : "");
3389 
3390 		ol_txrx_peer_tx_queue_free(pdev, peer);
3391 
3392 		/* Remove mappings from peer_id to peer object */
3393 		ol_txrx_peer_clear_map_peer(pdev, peer);
3394 
3395 		/* Remove peer pointer from local peer ID map */
3396 		ol_txrx_local_peer_id_free(pdev, peer);
3397 
3398 		ol_txrx_peer_free_tids(peer);
3399 
3400 		ol_txrx_dump_peer_access_list(peer);
3401 
3402 		if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() &&
3403 		    pdev->self_peer == peer)
3404 			pdev->self_peer = NULL;
3405 
3406 		if (!del_rc)
3407 			qdf_mem_free(peer);
3408 	} else {
3409 		access_list = qdf_atomic_read(&peer->access_list[debug_id]);
3410 		qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
3411 		if (!ref_silent)
3412 			ol_txrx_info_high("[%d][%d]: ref delete peer %pK ref_cnt -> %d",
3413 					  debug_id, access_list, peer, rc);
3414 	}
3415 	return rc;
3416 ERR_STATE:
3417 	wlan_roam_debug_log(vdev->vdev_id, DEBUG_PEER_UNREF_DELETE,
3418 			    DEBUG_INVALID_PEER_ID, &peer->mac_addr.raw,
3419 			    peer, err_code, qdf_atomic_read(&peer->ref_cnt));
3420 	return -EINVAL;
3421 }
3422 
3423 /**
3424  * ol_txrx_clear_peer_internal() - ol internal function to clear peer
3425  * @peer: pointer to ol txrx peer structure
3426  *
3427  * Return: QDF Status
3428  */
3429 static QDF_STATUS
ol_txrx_clear_peer_internal(struct ol_txrx_peer_t * peer)3430 ol_txrx_clear_peer_internal(struct ol_txrx_peer_t *peer)
3431 {
3432 	p_cds_sched_context sched_ctx = get_cds_sched_ctxt();
3433 	/* Drop pending Rx frames in CDS */
3434 	if (sched_ctx)
3435 		cds_drop_rxpkt_by_staid(sched_ctx, peer->local_id);
3436 
3437 	/* Purge the cached rx frame queue */
3438 	ol_txrx_flush_rx_frames(peer, 1);
3439 
3440 	qdf_spin_lock_bh(&peer->peer_info_lock);
3441 	peer->state = OL_TXRX_PEER_STATE_DISC;
3442 	qdf_spin_unlock_bh(&peer->peer_info_lock);
3443 
3444 	return QDF_STATUS_SUCCESS;
3445 }
3446 
3447 /**
3448  * ol_txrx_clear_peer() - clear peer
3449  * peer_addr: peer mac address
3450  *
3451  * Return: QDF Status
3452  */
3453 static QDF_STATUS
ol_txrx_clear_peer(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,struct qdf_mac_addr peer_addr)3454 ol_txrx_clear_peer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
3455 		   struct qdf_mac_addr peer_addr)
3456 {
3457 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
3458 	struct ol_txrx_pdev_t *pdev =
3459 			ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
3460 	struct ol_txrx_peer_t *peer;
3461 	QDF_STATUS status;
3462 
3463 	if (!pdev) {
3464 		ol_txrx_err("Unable to find pdev!");
3465 		return QDF_STATUS_E_FAILURE;
3466 	}
3467 
3468 	peer = ol_txrx_peer_get_ref_by_addr(pdev, peer_addr.bytes,
3469 					    PEER_DEBUG_ID_OL_INTERNAL);
3470 
3471 	/* Return success, if the peer is already cleared by
3472 	 * data path via peer detach function.
3473 	 */
3474 	if (!peer)
3475 		return QDF_STATUS_SUCCESS;
3476 
3477 	ol_txrx_dbg("Clear peer rx frames: " QDF_MAC_ADDR_FMT,
3478 		    QDF_MAC_ADDR_REF(peer->mac_addr.raw));
3479 	ol_txrx_clear_peer_internal(peer);
3480 	status = ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_INTERNAL);
3481 
3482 	return status;
3483 }
3484 
3485 /**
3486  * peer_unmap_timer_handler() - peer unmap timer function
3487  * @data: peer object pointer
3488  *
3489  * Return: none
3490  */
peer_unmap_timer_handler(void * data)3491 void peer_unmap_timer_handler(void *data)
3492 {
3493 	ol_txrx_peer_handle peer = (ol_txrx_peer_handle)data;
3494 
3495 	if (!peer)
3496 		return;
3497 
3498 	ol_txrx_err("all unmap events not received for peer %pK, ref_cnt %d",
3499 		    peer, qdf_atomic_read(&peer->ref_cnt));
3500 	ol_txrx_err("peer %pK ("QDF_MAC_ADDR_FMT")",
3501 		    peer,
3502 		    QDF_MAC_ADDR_REF(peer->mac_addr.raw));
3503 	ol_register_peer_recovery_notifier(peer);
3504 
3505 	cds_trigger_recovery(QDF_PEER_UNMAP_TIMEDOUT);
3506 }
3507 
3508 
3509 /**
3510  * ol_txrx_peer_detach() - Delete a peer's data object.
3511 
3512  * @soc_hdl: datapath soc handle
3513  * @vdev_id: virtual interface id
3514  * @peer_mac: peer MAC address
3515  * @bitmap: bitmap indicating special handling of request.
3516  * @peer_type: link or mld peer
3517  * When the host's control SW disassociates a peer, it calls
3518  * this function to detach and delete the peer. The reference
3519  * stored in the control peer object to the data peer
3520  * object (set up by a call to ol_peer_store()) is provided.
3521  *
3522  * Return: SUCCESS or Failure
3523  */
ol_txrx_peer_detach(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,uint8_t * peer_mac,uint32_t bitmap,enum cdp_peer_type peer_type)3524 static QDF_STATUS ol_txrx_peer_detach(struct cdp_soc_t *soc_hdl,
3525 				      uint8_t vdev_id, uint8_t *peer_mac,
3526 				      uint32_t bitmap,
3527 				      enum cdp_peer_type peer_type)
3528 {
3529 	ol_txrx_peer_handle peer;
3530 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
3531 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
3532 								     vdev_id);
3533 
3534 	if (!vdev)
3535 		return QDF_STATUS_E_FAILURE;
3536 
3537 	peer = ol_txrx_find_peer_by_addr((struct cdp_pdev *)vdev->pdev,
3538 					 peer_mac);
3539 	if (!peer)
3540 		return QDF_STATUS_E_FAILURE;
3541 
3542 	ol_txrx_info_high("peer %pK, peer->ref_cnt %d",
3543 			  peer, qdf_atomic_read(&peer->ref_cnt));
3544 
3545 	/* redirect peer's rx delivery function to point to a discard func */
3546 	peer->rx_opt_proc = ol_rx_discard;
3547 
3548 	peer->valid = 0;
3549 
3550 	/* flush all rx packets before clearing up the peer local_id */
3551 	ol_txrx_clear_peer_internal(peer);
3552 
3553 	/* debug print to dump rx reorder state */
3554 	/* htt_rx_reorder_log_print(vdev->pdev->htt_pdev); */
3555 
3556 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
3557 		   "%s:peer %pK ("QDF_MAC_ADDR_FMT")",
3558 		   __func__, peer,
3559 		   QDF_MAC_ADDR_REF(peer->mac_addr.raw));
3560 
3561 	qdf_spin_lock_bh(&vdev->pdev->last_real_peer_mutex);
3562 	if (vdev->last_real_peer == peer)
3563 		vdev->last_real_peer = NULL;
3564 	qdf_spin_unlock_bh(&vdev->pdev->last_real_peer_mutex);
3565 	htt_rx_reorder_log_print(peer->vdev->pdev->htt_pdev);
3566 
3567 	/*
3568 	 * set delete_in_progress to identify that wma
3569 	 * is waiting for unmap massage for this peer
3570 	 */
3571 	qdf_atomic_set(&peer->delete_in_progress, 1);
3572 
3573 	if (!(bitmap & (1 << CDP_PEER_DO_NOT_START_UNMAP_TIMER))) {
3574 		if (vdev->opmode == wlan_op_mode_sta) {
3575 			qdf_mem_copy(&peer->vdev->last_peer_mac_addr,
3576 				&peer->mac_addr,
3577 				sizeof(union ol_txrx_align_mac_addr_t));
3578 
3579 			/*
3580 			 * Create a timer to track unmap events when the
3581 			 * sta peer gets deleted.
3582 			 */
3583 			qdf_timer_start(&peer->peer_unmap_timer,
3584 					OL_TXRX_PEER_UNMAP_TIMEOUT);
3585 			ol_txrx_info_high
3586 				("started peer_unmap_timer for peer %pK",
3587 				  peer);
3588 		}
3589 	}
3590 
3591 	/*
3592 	 * Remove the reference added during peer_attach.
3593 	 * The peer will still be left allocated until the
3594 	 * PEER_UNMAP message arrives to remove the other
3595 	 * reference, added by the PEER_MAP message.
3596 	 */
3597 	peer->state = OL_TXRX_PEER_STATE_INVALID;
3598 	ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_PEER_ATTACH);
3599 
3600 	return QDF_STATUS_SUCCESS;
3601 }
3602 
3603 /**
3604  * ol_txrx_peer_detach_force_delete() - Detach and delete a peer's data object
3605  * @soc_hdl - datapath soc handle
3606  * @vdev_id - virtual interface id
3607  * @peer_mac - peer mac address
3608  *
3609  * Detach a peer and force peer object to be removed. It is called during
3610  * roaming scenario when the firmware has already deleted a peer.
3611  * Remove it from the peer_id_to_object map. Peer object is actually freed
3612  * when last reference is deleted.
3613  *
3614  * Return: None
3615  */
ol_txrx_peer_detach_force_delete(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,uint8_t * peer_mac)3616 static void ol_txrx_peer_detach_force_delete(struct cdp_soc_t *soc_hdl,
3617 					     uint8_t vdev_id, uint8_t *peer_mac)
3618 {
3619 	struct ol_txrx_peer_t *peer;
3620 	struct ol_txrx_pdev_t *pdev;
3621 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
3622 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
3623 								     vdev_id);
3624 
3625 	if (!vdev || !vdev->pdev)
3626 		return;
3627 
3628 	pdev = vdev->pdev;
3629 	peer = ol_txrx_find_peer_by_addr(ol_txrx_pdev_t_to_cdp_pdev(pdev),
3630 					 peer_mac);
3631 	if (!peer)
3632 		return;
3633 
3634 	/* Clear the peer_id_to_obj map entries */
3635 	ol_txrx_peer_remove_obj_map_entries(pdev, peer);
3636 	ol_txrx_peer_detach(soc_hdl, vdev_id, peer_mac,
3637 			    1 << CDP_PEER_DELETE_NO_SPECIAL,
3638 			    CDP_LINK_PEER_TYPE);
3639 }
3640 
3641 /**
3642  * ol_txrx_peer_detach_sync() - peer detach sync callback
3643  * @soc_hdl - datapath soc handle
3644  * @vdev_id - virtual interface id
3645  * @peer_mac - peer mac address
3646  * @peer_unmap_sync - peer unmap sync cb.
3647  * @bitmap - bitmap indicating special handling of request.
3648  *
3649  * Return: None
3650  */
ol_txrx_peer_detach_sync(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,uint8_t * peer_mac,ol_txrx_peer_unmap_sync_cb peer_unmap_sync,uint32_t bitmap)3651 static void ol_txrx_peer_detach_sync(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
3652 				     uint8_t *peer_mac,
3653 				     ol_txrx_peer_unmap_sync_cb peer_unmap_sync,
3654 				     uint32_t bitmap)
3655 {
3656 	struct ol_txrx_pdev_t *pdev;
3657 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
3658 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
3659 								     vdev_id);
3660 
3661 	if (!vdev || !vdev->pdev)
3662 		return;
3663 
3664 	pdev = vdev->pdev;
3665 	if (!pdev->peer_unmap_sync_cb)
3666 		pdev->peer_unmap_sync_cb = peer_unmap_sync;
3667 
3668 	ol_txrx_peer_detach(soc_hdl, vdev_id, peer_mac, bitmap,
3669 			    CDP_LINK_PEER_TYPE);
3670 }
3671 
3672 /**
3673  * ol_txrx_peer_unmap_sync_cb_set() - set peer unmap sync callback
3674  * @soc_hdl - datapath soc handle
3675  * pdev_id - physical device instance id
3676  * @peer_unmap_sync - peer unmap sync callback
3677  *
3678  * Return: None
3679  */
ol_txrx_peer_unmap_sync_cb_set(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,ol_txrx_peer_unmap_sync_cb peer_unmap_sync)3680 static void ol_txrx_peer_unmap_sync_cb_set(
3681 				struct cdp_soc_t *soc_hdl,
3682 				uint8_t pdev_id,
3683 				ol_txrx_peer_unmap_sync_cb peer_unmap_sync)
3684 {
3685 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
3686 	struct ol_txrx_pdev_t *pdev = ol_txrx_get_pdev_from_pdev_id(soc,
3687 								    pdev_id);
3688 
3689 	if (!pdev)
3690 		return;
3691 
3692 	if (!pdev->peer_unmap_sync_cb)
3693 		pdev->peer_unmap_sync_cb = peer_unmap_sync;
3694 }
3695 
3696 /**
3697  * ol_txrx_peer_flush_frags() - Flush fragments for a particular peer
3698  * @soc_hdl - datapath soc handle
3699  * @vdev_id - virtual device id
3700  * @peer_mac - peer mac address
3701  *
3702  * Return: None
3703  */
3704 static void
ol_txrx_peer_flush_frags(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,uint8_t * peer_mac)3705 ol_txrx_peer_flush_frags(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
3706 			 uint8_t *peer_mac)
3707 {
3708 	struct ol_txrx_peer_t *peer;
3709 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
3710 	struct ol_txrx_pdev_t *pdev =
3711 		ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
3712 
3713 	if (!pdev)
3714 		return;
3715 
3716 	peer =  ol_txrx_peer_find_hash_find_get_ref(pdev, peer_mac, 0, 1,
3717 						    PEER_DEBUG_ID_OL_INTERNAL);
3718 	if (!peer)
3719 		return;
3720 
3721 	ol_rx_reorder_peer_cleanup(peer->vdev, peer);
3722 
3723 	ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_INTERNAL);
3724 }
3725 
3726 /**
3727  * ol_txrx_dump_tx_desc() - dump tx desc total and free count
3728  * @txrx_pdev: Pointer to txrx pdev
3729  *
3730  * Return: none
3731  */
ol_txrx_dump_tx_desc(ol_txrx_pdev_handle pdev_handle)3732 static void ol_txrx_dump_tx_desc(ol_txrx_pdev_handle pdev_handle)
3733 {
3734 	struct ol_txrx_pdev_t *pdev = (ol_txrx_pdev_handle) pdev_handle;
3735 	uint32_t total, num_free;
3736 
3737 	if (ol_cfg_is_high_latency(pdev->ctrl_pdev))
3738 		total = qdf_atomic_read(&pdev->orig_target_tx_credit);
3739 	else
3740 		total = ol_tx_get_desc_global_pool_size(pdev);
3741 
3742 	num_free = ol_tx_get_total_free_desc(pdev);
3743 
3744 	ol_txrx_info_high(
3745 		   "total tx credit %d num_free %d",
3746 		   total, num_free);
3747 
3748 }
3749 
3750 /**
3751  * ol_txrx_wait_for_pending_tx() - wait for tx queue to be empty
3752  * @timeout: timeout in ms
3753  *
3754  * Wait for tx queue to be empty, return timeout error if
3755  * queue doesn't empty before timeout occurs.
3756  *
3757  * Return:
3758  *    QDF_STATUS_SUCCESS if the queue empties,
3759  *    QDF_STATUS_E_TIMEOUT in case of timeout,
3760  *    QDF_STATUS_E_FAULT in case of missing handle
3761  */
ol_txrx_wait_for_pending_tx(int timeout)3762 static QDF_STATUS ol_txrx_wait_for_pending_tx(int timeout)
3763 {
3764 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
3765 	struct ol_txrx_pdev_t *txrx_pdev;
3766 
3767 	if (qdf_unlikely(!soc))
3768 		return QDF_STATUS_E_FAULT;
3769 
3770 	txrx_pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
3771 	if (!txrx_pdev) {
3772 		ol_txrx_err("txrx context is null");
3773 		return QDF_STATUS_E_FAULT;
3774 	}
3775 
3776 	while (ol_txrx_get_tx_pending((struct cdp_pdev *)txrx_pdev)) {
3777 		qdf_sleep(OL_ATH_TX_DRAIN_WAIT_DELAY);
3778 		if (timeout <= 0) {
3779 			ol_txrx_err("tx frames are pending");
3780 			ol_txrx_dump_tx_desc(txrx_pdev);
3781 			return QDF_STATUS_E_TIMEOUT;
3782 		}
3783 		timeout = timeout - OL_ATH_TX_DRAIN_WAIT_DELAY;
3784 	}
3785 	return QDF_STATUS_SUCCESS;
3786 }
3787 
3788 #ifndef QCA_WIFI_3_0_EMU
3789 #define SUSPEND_DRAIN_WAIT 500
3790 #else
3791 #define SUSPEND_DRAIN_WAIT 3000
3792 #endif
3793 
3794 #ifdef FEATURE_RUNTIME_PM
3795 /**
3796  * ol_txrx_runtime_suspend() - ensure TXRX is ready to runtime suspend
3797  * @soc_hdl: Datapath soc handle
3798  * @pdev_id: id of data path pdev handle
3799  *
3800  * TXRX is ready to runtime suspend if there are no pending packets
3801  * in the tx queue.
3802  *
3803  * Return: QDF_STATUS
3804  */
ol_txrx_runtime_suspend(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)3805 static QDF_STATUS ol_txrx_runtime_suspend(struct cdp_soc_t *soc_hdl,
3806 					  uint8_t pdev_id)
3807 {
3808 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
3809 	struct cdp_pdev *txrx_pdev = (struct cdp_pdev *)
3810 				ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
3811 
3812 	if (ol_txrx_get_tx_pending(txrx_pdev))
3813 		return QDF_STATUS_E_BUSY;
3814 	else
3815 		return QDF_STATUS_SUCCESS;
3816 }
3817 
3818 /**
3819  * ol_txrx_runtime_resume() - ensure TXRX is ready to runtime resume
3820  * @soc_hdl: Datapath soc handle
3821  * @pdev_id: id of data path pdev handle
3822  *
3823  * This is a dummy function for symmetry.
3824  *
3825  * Return: QDF_STATUS_SUCCESS
3826  */
ol_txrx_runtime_resume(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)3827 static QDF_STATUS ol_txrx_runtime_resume(struct cdp_soc_t *soc_hdl,
3828 					 uint8_t pdev_id)
3829 {
3830 	return QDF_STATUS_SUCCESS;
3831 }
3832 #endif
3833 
3834 /**
3835  * ol_txrx_bus_suspend() - bus suspend
3836  * @soc_hdl: Datapath soc handle
3837  * @pdev_id: id of data path pdev handle
3838  *
3839  * Ensure that ol_txrx is ready for bus suspend
3840  *
3841  * Return: QDF_STATUS
3842  */
ol_txrx_bus_suspend(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)3843 static QDF_STATUS ol_txrx_bus_suspend(struct cdp_soc_t *soc_hdl,
3844 				      uint8_t pdev_id)
3845 {
3846 	return ol_txrx_wait_for_pending_tx(SUSPEND_DRAIN_WAIT);
3847 }
3848 
3849 /**
3850  * ol_txrx_bus_resume() - bus resume
3851  * @soc_hdl: Datapath soc handle
3852  * @pdev_id: id of data path pdev handle
3853  *
3854  * Dummy function for symmetry
3855  *
3856  * Return: QDF_STATUS_SUCCESS
3857  */
ol_txrx_bus_resume(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)3858 static QDF_STATUS ol_txrx_bus_resume(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
3859 {
3860 	return QDF_STATUS_SUCCESS;
3861 }
3862 
3863 /**
3864  * ol_txrx_get_tx_pending - Get the number of pending transmit
3865  * frames that are awaiting completion.
3866  *
3867  * @pdev - the data physical device object
3868  *  Mainly used in clean up path to make sure all buffers have been freed
3869  *
3870  * Return: count of pending frames
3871  */
ol_txrx_get_tx_pending(struct cdp_pdev * ppdev)3872 uint32_t ol_txrx_get_tx_pending(struct cdp_pdev *ppdev)
3873 {
3874 	struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)ppdev;
3875 	uint32_t total;
3876 
3877 	if (ol_cfg_is_high_latency(pdev->ctrl_pdev))
3878 		total = qdf_atomic_read(&pdev->orig_target_tx_credit);
3879 	else
3880 		total = ol_tx_get_desc_global_pool_size(pdev);
3881 
3882 	return total - ol_tx_get_total_free_desc(pdev);
3883 }
3884 
ol_txrx_discard_tx_pending(ol_txrx_pdev_handle pdev_handle)3885 void ol_txrx_discard_tx_pending(ol_txrx_pdev_handle pdev_handle)
3886 {
3887 	ol_tx_desc_list tx_descs;
3888 	/*
3889 	 * First let hif do the qdf_atomic_dec_and_test(&tx_desc->ref_cnt)
3890 	 * then let htt do the qdf_atomic_dec_and_test(&tx_desc->ref_cnt)
3891 	 * which is the same with normal data send complete path
3892 	 */
3893 	htt_tx_pending_discard(pdev_handle->htt_pdev);
3894 
3895 	TAILQ_INIT(&tx_descs);
3896 	ol_tx_queue_discard(pdev_handle, true, &tx_descs);
3897 	/* Discard Frames in Discard List */
3898 	ol_tx_desc_frame_list_free(pdev_handle, &tx_descs, 1 /* error */);
3899 
3900 	ol_tx_discard_target_frms(pdev_handle);
3901 }
3902 
3903 static inline
ol_txrx_stats_ptr_to_u64(struct ol_txrx_stats_req_internal * req)3904 uint64_t ol_txrx_stats_ptr_to_u64(struct ol_txrx_stats_req_internal *req)
3905 {
3906 	return (uint64_t) ((size_t) req);
3907 }
3908 
3909 static inline
ol_txrx_u64_to_stats_ptr(uint64_t cookie)3910 struct ol_txrx_stats_req_internal *ol_txrx_u64_to_stats_ptr(uint64_t cookie)
3911 {
3912 	return (struct ol_txrx_stats_req_internal *)((size_t) cookie);
3913 }
3914 
3915 #ifdef currently_unused
3916 void
ol_txrx_fw_stats_cfg(ol_txrx_vdev_handle vdev,uint8_t cfg_stats_type,uint32_t cfg_val)3917 ol_txrx_fw_stats_cfg(ol_txrx_vdev_handle vdev,
3918 		     uint8_t cfg_stats_type, uint32_t cfg_val)
3919 {
3920 	uint8_t dummy_cookie = 0;
3921 
3922 	htt_h2t_dbg_stats_get(vdev->pdev->htt_pdev, 0 /* upload mask */,
3923 			      0 /* reset mask */,
3924 			      cfg_stats_type, cfg_val, dummy_cookie);
3925 }
3926 #endif
3927 
3928 /**
3929  * ol_txrx_fw_stats_desc_pool_init() - Initialize the fw stats descriptor pool
3930  * @pdev: handle to ol txrx pdev
3931  * @pool_size: Size of fw stats descriptor pool
3932  *
3933  * Return: 0 for success, error code on failure.
3934  */
ol_txrx_fw_stats_desc_pool_init(struct ol_txrx_pdev_t * pdev,uint8_t pool_size)3935 int ol_txrx_fw_stats_desc_pool_init(struct ol_txrx_pdev_t *pdev,
3936 				    uint8_t pool_size)
3937 {
3938 	int i;
3939 
3940 	if (!pdev) {
3941 		ol_txrx_err("pdev is NULL");
3942 		return -EINVAL;
3943 	}
3944 	pdev->ol_txrx_fw_stats_desc_pool.pool = qdf_mem_malloc(pool_size *
3945 		sizeof(struct ol_txrx_fw_stats_desc_elem_t));
3946 	if (!pdev->ol_txrx_fw_stats_desc_pool.pool)
3947 		return -ENOMEM;
3948 
3949 	pdev->ol_txrx_fw_stats_desc_pool.freelist =
3950 		&pdev->ol_txrx_fw_stats_desc_pool.pool[0];
3951 	pdev->ol_txrx_fw_stats_desc_pool.pool_size = pool_size;
3952 
3953 	for (i = 0; i < (pool_size - 1); i++) {
3954 		pdev->ol_txrx_fw_stats_desc_pool.pool[i].desc.desc_id = i;
3955 		pdev->ol_txrx_fw_stats_desc_pool.pool[i].desc.req = NULL;
3956 		pdev->ol_txrx_fw_stats_desc_pool.pool[i].next =
3957 			&pdev->ol_txrx_fw_stats_desc_pool.pool[i + 1];
3958 	}
3959 	pdev->ol_txrx_fw_stats_desc_pool.pool[i].desc.desc_id = i;
3960 	pdev->ol_txrx_fw_stats_desc_pool.pool[i].desc.req = NULL;
3961 	pdev->ol_txrx_fw_stats_desc_pool.pool[i].next = NULL;
3962 	qdf_spinlock_create(&pdev->ol_txrx_fw_stats_desc_pool.pool_lock);
3963 	qdf_atomic_init(&pdev->ol_txrx_fw_stats_desc_pool.initialized);
3964 	qdf_atomic_set(&pdev->ol_txrx_fw_stats_desc_pool.initialized, 1);
3965 	return 0;
3966 }
3967 
3968 /**
3969  * ol_txrx_fw_stats_desc_pool_deinit() - Deinitialize the
3970  * fw stats descriptor pool
3971  * @pdev: handle to ol txrx pdev
3972  *
3973  * Return: None
3974  */
ol_txrx_fw_stats_desc_pool_deinit(struct ol_txrx_pdev_t * pdev)3975 void ol_txrx_fw_stats_desc_pool_deinit(struct ol_txrx_pdev_t *pdev)
3976 {
3977 	if (!pdev) {
3978 		ol_txrx_err("pdev is NULL");
3979 		return;
3980 	}
3981 	if (!qdf_atomic_read(&pdev->ol_txrx_fw_stats_desc_pool.initialized)) {
3982 		ol_txrx_err("Pool is not initialized");
3983 		return;
3984 	}
3985 	if (!pdev->ol_txrx_fw_stats_desc_pool.pool) {
3986 		ol_txrx_err("Pool is not allocated");
3987 		return;
3988 	}
3989 	qdf_spin_lock_bh(&pdev->ol_txrx_fw_stats_desc_pool.pool_lock);
3990 	qdf_atomic_set(&pdev->ol_txrx_fw_stats_desc_pool.initialized, 0);
3991 	qdf_mem_free(pdev->ol_txrx_fw_stats_desc_pool.pool);
3992 	pdev->ol_txrx_fw_stats_desc_pool.pool = NULL;
3993 
3994 	pdev->ol_txrx_fw_stats_desc_pool.freelist = NULL;
3995 	pdev->ol_txrx_fw_stats_desc_pool.pool_size = 0;
3996 	qdf_spin_unlock_bh(&pdev->ol_txrx_fw_stats_desc_pool.pool_lock);
3997 }
3998 
3999 /**
4000  * ol_txrx_fw_stats_desc_alloc() - Get fw stats descriptor from fw stats
4001  * free descriptor pool
4002  * @pdev: handle to ol txrx pdev
4003  *
4004  * Return: pointer to fw stats descriptor, NULL on failure
4005  */
4006 struct ol_txrx_fw_stats_desc_t
ol_txrx_fw_stats_desc_alloc(struct ol_txrx_pdev_t * pdev)4007 	*ol_txrx_fw_stats_desc_alloc(struct ol_txrx_pdev_t *pdev)
4008 {
4009 	struct ol_txrx_fw_stats_desc_t *desc = NULL;
4010 
4011 	qdf_spin_lock_bh(&pdev->ol_txrx_fw_stats_desc_pool.pool_lock);
4012 	if (!qdf_atomic_read(&pdev->ol_txrx_fw_stats_desc_pool.initialized)) {
4013 		qdf_spin_unlock_bh(&pdev->
4014 				   ol_txrx_fw_stats_desc_pool.pool_lock);
4015 		ol_txrx_err("Pool deinitialized");
4016 		return NULL;
4017 	}
4018 	if (pdev->ol_txrx_fw_stats_desc_pool.freelist) {
4019 		desc = &pdev->ol_txrx_fw_stats_desc_pool.freelist->desc;
4020 		pdev->ol_txrx_fw_stats_desc_pool.freelist =
4021 			pdev->ol_txrx_fw_stats_desc_pool.freelist->next;
4022 	}
4023 	qdf_spin_unlock_bh(&pdev->ol_txrx_fw_stats_desc_pool.pool_lock);
4024 
4025 	if (desc)
4026 		ol_txrx_dbg("desc_id %d allocated", desc->desc_id);
4027 	else
4028 		ol_txrx_err("fw stats descriptors are exhausted");
4029 
4030 	return desc;
4031 }
4032 
4033 /**
4034  * ol_txrx_fw_stats_desc_get_req() - Put fw stats descriptor
4035  * back into free pool
4036  * @pdev: handle to ol txrx pdev
4037  * @fw_stats_desc: fw_stats_desc_get descriptor
4038  *
4039  * Return: pointer to request
4040  */
4041 struct ol_txrx_stats_req_internal
ol_txrx_fw_stats_desc_get_req(struct ol_txrx_pdev_t * pdev,unsigned char desc_id)4042 	*ol_txrx_fw_stats_desc_get_req(struct ol_txrx_pdev_t *pdev,
4043 				       unsigned char desc_id)
4044 {
4045 	struct ol_txrx_fw_stats_desc_elem_t *desc_elem;
4046 	struct ol_txrx_stats_req_internal *req;
4047 
4048 	qdf_spin_lock_bh(&pdev->ol_txrx_fw_stats_desc_pool.pool_lock);
4049 	if (!qdf_atomic_read(&pdev->ol_txrx_fw_stats_desc_pool.initialized)) {
4050 		qdf_spin_unlock_bh(&pdev->
4051 				   ol_txrx_fw_stats_desc_pool.pool_lock);
4052 		ol_txrx_err("Desc ID %u Pool deinitialized", desc_id);
4053 		return NULL;
4054 	}
4055 	desc_elem = &pdev->ol_txrx_fw_stats_desc_pool.pool[desc_id];
4056 	req = desc_elem->desc.req;
4057 	desc_elem->desc.req = NULL;
4058 	desc_elem->next =
4059 		pdev->ol_txrx_fw_stats_desc_pool.freelist;
4060 	pdev->ol_txrx_fw_stats_desc_pool.freelist = desc_elem;
4061 	qdf_spin_unlock_bh(&pdev->ol_txrx_fw_stats_desc_pool.pool_lock);
4062 	return req;
4063 }
4064 
4065 /**
4066  * ol_txrx_fw_stats_get() - Get fw stats
4067  *
4068  * @soc_hdl: datapath soc handle
4069  * @vdev_id: virtual interface id
4070  * @req: specifications of stats request
4071  * @per_vdev: bool input whether stats requested per vdev or not
4072  * @response_expected: bool input whether expecting response or not
4073  *
4074  * Return: success or failure
4075  */
4076 static A_STATUS
ol_txrx_fw_stats_get(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,struct ol_txrx_stats_req * req,bool per_vdev,bool response_expected)4077 ol_txrx_fw_stats_get(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
4078 		     struct ol_txrx_stats_req *req, bool per_vdev,
4079 		     bool response_expected)
4080 {
4081 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
4082 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
4083 								     vdev_id);
4084 	struct ol_txrx_pdev_t *pdev;
4085 	uint8_t cookie = FW_STATS_DESC_POOL_SIZE;
4086 	struct ol_txrx_stats_req_internal *non_volatile_req;
4087 	struct ol_txrx_fw_stats_desc_t *desc = NULL;
4088 	struct ol_txrx_fw_stats_desc_elem_t *elem = NULL;
4089 
4090 	if (!vdev)
4091 		return A_EINVAL;
4092 
4093 	pdev = vdev->pdev;
4094 	if (!pdev ||
4095 	    req->stats_type_upload_mask >= 1 << HTT_DBG_NUM_STATS ||
4096 	    req->stats_type_reset_mask >= 1 << HTT_DBG_NUM_STATS) {
4097 		return A_EINVAL;
4098 	}
4099 
4100 	/*
4101 	 * Allocate a non-transient stats request object.
4102 	 * (The one provided as an argument is likely allocated on the stack.)
4103 	 */
4104 	non_volatile_req = qdf_mem_malloc(sizeof(*non_volatile_req));
4105 	if (!non_volatile_req)
4106 		return A_NO_MEMORY;
4107 
4108 	/* copy the caller's specifications */
4109 	non_volatile_req->base = *req;
4110 	non_volatile_req->serviced = 0;
4111 	non_volatile_req->offset = 0;
4112 	if (response_expected) {
4113 		desc = ol_txrx_fw_stats_desc_alloc(pdev);
4114 		if (!desc) {
4115 			qdf_mem_free(non_volatile_req);
4116 			return A_NO_MEMORY;
4117 		}
4118 
4119 		/* use the desc id as the cookie */
4120 		cookie = desc->desc_id;
4121 		desc->req = non_volatile_req;
4122 		qdf_spin_lock_bh(&pdev->req_list_spinlock);
4123 		TAILQ_INSERT_TAIL(&pdev->req_list, non_volatile_req, req_list_elem);
4124 		pdev->req_list_depth++;
4125 		qdf_spin_unlock_bh(&pdev->req_list_spinlock);
4126 	}
4127 
4128 	if (htt_h2t_dbg_stats_get(pdev->htt_pdev,
4129 				  req->stats_type_upload_mask,
4130 				  req->stats_type_reset_mask,
4131 				  HTT_H2T_STATS_REQ_CFG_STAT_TYPE_INVALID, 0,
4132 				  cookie)) {
4133 		if (response_expected) {
4134 			qdf_spin_lock_bh(&pdev->req_list_spinlock);
4135 			TAILQ_REMOVE(&pdev->req_list, non_volatile_req,
4136 				     req_list_elem);
4137 			pdev->req_list_depth--;
4138 			qdf_spin_unlock_bh(&pdev->req_list_spinlock);
4139 			if (desc) {
4140 				qdf_spin_lock_bh(&pdev->ol_txrx_fw_stats_desc_pool.
4141 						 pool_lock);
4142 				desc->req = NULL;
4143 				elem = container_of(desc,
4144 						    struct ol_txrx_fw_stats_desc_elem_t,
4145 						    desc);
4146 				elem->next =
4147 					pdev->ol_txrx_fw_stats_desc_pool.freelist;
4148 				pdev->ol_txrx_fw_stats_desc_pool.freelist = elem;
4149 				qdf_spin_unlock_bh(&pdev->
4150 						   ol_txrx_fw_stats_desc_pool.
4151 						   pool_lock);
4152 			}
4153 		}
4154 
4155 		qdf_mem_free(non_volatile_req);
4156 		return A_ERROR;
4157 	}
4158 
4159 	if (response_expected == false)
4160 		qdf_mem_free(non_volatile_req);
4161 
4162 	return A_OK;
4163 }
4164 
4165 void
ol_txrx_fw_stats_handler(ol_txrx_pdev_handle pdev,uint8_t cookie,uint8_t * stats_info_list)4166 ol_txrx_fw_stats_handler(ol_txrx_pdev_handle pdev,
4167 			 uint8_t cookie, uint8_t *stats_info_list)
4168 {
4169 	enum htt_dbg_stats_type type;
4170 	enum htt_cmn_dbg_stats_type cmn_type = HTT_DBG_CMN_NUM_STATS_INVALID;
4171 	enum htt_dbg_stats_status status;
4172 	int length;
4173 	uint8_t *stats_data;
4174 	struct ol_txrx_stats_req_internal *req, *tmp;
4175 	int more = 0;
4176 	int found = 0;
4177 
4178 	if (cookie >= FW_STATS_DESC_POOL_SIZE) {
4179 		ol_txrx_err("Cookie is not valid");
4180 		return;
4181 	}
4182 	req = ol_txrx_fw_stats_desc_get_req(pdev, (uint8_t)cookie);
4183 	if (!req) {
4184 		ol_txrx_err("Request not retrieved for cookie %u",
4185 			    (uint8_t)cookie);
4186 		return;
4187 	}
4188 	qdf_spin_lock_bh(&pdev->req_list_spinlock);
4189 	TAILQ_FOREACH(tmp, &pdev->req_list, req_list_elem) {
4190 		if (req == tmp) {
4191 			found = 1;
4192 			break;
4193 		}
4194 	}
4195 	qdf_spin_unlock_bh(&pdev->req_list_spinlock);
4196 
4197 	if (!found) {
4198 		ol_txrx_err(
4199 			"req(%pK) from firmware can't be found in the list", req);
4200 		return;
4201 	}
4202 
4203 	do {
4204 		htt_t2h_dbg_stats_hdr_parse(stats_info_list, &type, &status,
4205 					    &length, &stats_data);
4206 		if (status == HTT_DBG_STATS_STATUS_SERIES_DONE)
4207 			break;
4208 		if (status == HTT_DBG_STATS_STATUS_PRESENT ||
4209 		    status == HTT_DBG_STATS_STATUS_PARTIAL) {
4210 			uint8_t *buf;
4211 			int bytes = 0;
4212 
4213 			if (status == HTT_DBG_STATS_STATUS_PARTIAL)
4214 				more = 1;
4215 			if (req->base.print.verbose || req->base.print.concise)
4216 				/* provide the header along with the data */
4217 				htt_t2h_stats_print(stats_info_list,
4218 						    req->base.print.concise);
4219 
4220 			switch (type) {
4221 			case HTT_DBG_STATS_WAL_PDEV_TXRX:
4222 				bytes = sizeof(struct wlan_dbg_stats);
4223 				if (req->base.copy.buf) {
4224 					int lmt;
4225 
4226 					lmt = sizeof(struct wlan_dbg_stats);
4227 					if (req->base.copy.byte_limit < lmt)
4228 						lmt = req->base.copy.byte_limit;
4229 					buf = req->base.copy.buf + req->offset;
4230 					qdf_mem_copy(buf, stats_data, lmt);
4231 				}
4232 				break;
4233 			case HTT_DBG_STATS_RX_REORDER:
4234 				bytes = sizeof(struct rx_reorder_stats);
4235 				if (req->base.copy.buf) {
4236 					int lmt;
4237 
4238 					lmt = sizeof(struct rx_reorder_stats);
4239 					if (req->base.copy.byte_limit < lmt)
4240 						lmt = req->base.copy.byte_limit;
4241 					buf = req->base.copy.buf + req->offset;
4242 					qdf_mem_copy(buf, stats_data, lmt);
4243 				}
4244 				break;
4245 			case HTT_DBG_STATS_RX_RATE_INFO:
4246 				bytes = sizeof(wlan_dbg_rx_rate_info_t);
4247 				if (req->base.copy.buf) {
4248 					int lmt;
4249 
4250 					lmt = sizeof(wlan_dbg_rx_rate_info_t);
4251 					if (req->base.copy.byte_limit < lmt)
4252 						lmt = req->base.copy.byte_limit;
4253 					buf = req->base.copy.buf + req->offset;
4254 					qdf_mem_copy(buf, stats_data, lmt);
4255 				}
4256 				break;
4257 
4258 			case HTT_DBG_STATS_TX_RATE_INFO:
4259 				bytes = sizeof(wlan_dbg_tx_rate_info_t);
4260 				if (req->base.copy.buf) {
4261 					int lmt;
4262 
4263 					lmt = sizeof(wlan_dbg_tx_rate_info_t);
4264 					if (req->base.copy.byte_limit < lmt)
4265 						lmt = req->base.copy.byte_limit;
4266 					buf = req->base.copy.buf + req->offset;
4267 					qdf_mem_copy(buf, stats_data, lmt);
4268 				}
4269 				break;
4270 
4271 			case HTT_DBG_STATS_TX_PPDU_LOG:
4272 				bytes = 0;
4273 				/* TO DO: specify how many bytes are present */
4274 				/* TO DO: add copying to the requestor's buf */
4275 				fallthrough;
4276 			case HTT_DBG_STATS_RX_REMOTE_RING_BUFFER_INFO:
4277 				bytes = sizeof(struct
4278 						rx_remote_buffer_mgmt_stats);
4279 				if (req->base.copy.buf) {
4280 					int limit;
4281 
4282 					limit = sizeof(struct
4283 						rx_remote_buffer_mgmt_stats);
4284 					if (req->base.copy.byte_limit < limit)
4285 						limit = req->base.copy.
4286 							byte_limit;
4287 					buf = req->base.copy.buf + req->offset;
4288 					qdf_mem_copy(buf, stats_data, limit);
4289 				}
4290 				break;
4291 
4292 			case HTT_DBG_STATS_TXBF_INFO:
4293 				bytes = sizeof(struct wlan_dbg_txbf_data_stats);
4294 				if (req->base.copy.buf) {
4295 					int limit;
4296 
4297 					limit = sizeof(struct
4298 						wlan_dbg_txbf_data_stats);
4299 					if (req->base.copy.byte_limit < limit)
4300 						limit = req->base.copy.
4301 							byte_limit;
4302 					buf = req->base.copy.buf + req->offset;
4303 					qdf_mem_copy(buf, stats_data, limit);
4304 				}
4305 				break;
4306 
4307 			case HTT_DBG_STATS_SND_INFO:
4308 				bytes = sizeof(struct wlan_dbg_txbf_snd_stats);
4309 				if (req->base.copy.buf) {
4310 					int limit;
4311 
4312 					limit = sizeof(struct
4313 						wlan_dbg_txbf_snd_stats);
4314 					if (req->base.copy.byte_limit < limit)
4315 						limit = req->base.copy.
4316 							byte_limit;
4317 					buf = req->base.copy.buf + req->offset;
4318 					qdf_mem_copy(buf, stats_data, limit);
4319 				}
4320 				break;
4321 
4322 			case HTT_DBG_STATS_TX_SELFGEN_INFO:
4323 				bytes = sizeof(struct
4324 					wlan_dbg_tx_selfgen_stats);
4325 				if (req->base.copy.buf) {
4326 					int limit;
4327 
4328 					limit = sizeof(struct
4329 						wlan_dbg_tx_selfgen_stats);
4330 					if (req->base.copy.byte_limit < limit)
4331 						limit = req->base.copy.
4332 							byte_limit;
4333 					buf = req->base.copy.buf + req->offset;
4334 					qdf_mem_copy(buf, stats_data, limit);
4335 				}
4336 				break;
4337 
4338 			case HTT_DBG_STATS_ERROR_INFO:
4339 				bytes =
4340 				  sizeof(struct wlan_dbg_wifi2_error_stats);
4341 				if (req->base.copy.buf) {
4342 					int limit;
4343 
4344 					limit = sizeof(struct
4345 						wlan_dbg_wifi2_error_stats);
4346 					if (req->base.copy.byte_limit < limit)
4347 						limit = req->base.copy.
4348 							byte_limit;
4349 					buf = req->base.copy.buf + req->offset;
4350 					qdf_mem_copy(buf, stats_data, limit);
4351 				}
4352 				break;
4353 
4354 			case HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT:
4355 				bytes =
4356 				  sizeof(struct rx_txbf_musu_ndpa_pkts_stats);
4357 				if (req->base.copy.buf) {
4358 					int limit;
4359 
4360 					limit = sizeof(struct
4361 						rx_txbf_musu_ndpa_pkts_stats);
4362 					if (req->base.copy.byte_limit <	limit)
4363 						limit =
4364 						req->base.copy.byte_limit;
4365 					buf = req->base.copy.buf + req->offset;
4366 					qdf_mem_copy(buf, stats_data, limit);
4367 				}
4368 				break;
4369 
4370 			default:
4371 				break;
4372 			}
4373 			buf = req->base.copy.buf ?
4374 				req->base.copy.buf : stats_data;
4375 
4376 			/* Not implemented for MCL */
4377 			if (req->base.callback.fp)
4378 				req->base.callback.fp(req->base.callback.ctxt,
4379 						      cmn_type, buf, bytes);
4380 		}
4381 		stats_info_list += length;
4382 	} while (1);
4383 
4384 	if (!more) {
4385 		qdf_spin_lock_bh(&pdev->req_list_spinlock);
4386 		TAILQ_FOREACH(tmp, &pdev->req_list, req_list_elem) {
4387 			if (req == tmp) {
4388 				TAILQ_REMOVE(&pdev->req_list, req, req_list_elem);
4389 				pdev->req_list_depth--;
4390 				qdf_mem_free(req);
4391 				break;
4392 			}
4393 		}
4394 		qdf_spin_unlock_bh(&pdev->req_list_spinlock);
4395 	}
4396 }
4397 
4398 #ifndef ATH_PERF_PWR_OFFLOAD /*---------------------------------------------*/
ol_txrx_debug(ol_txrx_vdev_handle vdev,int debug_specs)4399 int ol_txrx_debug(ol_txrx_vdev_handle vdev, int debug_specs)
4400 {
4401 	if (debug_specs & TXRX_DBG_MASK_OBJS) {
4402 #if defined(TXRX_DEBUG_LEVEL) && TXRX_DEBUG_LEVEL > 5
4403 		ol_txrx_pdev_display(vdev->pdev, 0);
4404 #else
4405 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_FATAL,
4406 			  "The pdev,vdev,peer display functions are disabled.\n To enable them, recompile with TXRX_DEBUG_LEVEL > 5");
4407 #endif
4408 	}
4409 	if (debug_specs & TXRX_DBG_MASK_STATS)
4410 		ol_txrx_stats_display(vdev->pdev,
4411 				      QDF_STATS_VERBOSITY_LEVEL_HIGH);
4412 	if (debug_specs & TXRX_DBG_MASK_PROT_ANALYZE) {
4413 #if defined(ENABLE_TXRX_PROT_ANALYZE)
4414 		ol_txrx_prot_ans_display(vdev->pdev);
4415 #else
4416 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_FATAL,
4417 			  "txrx protocol analysis is disabled.\n To enable it, recompile with ENABLE_TXRX_PROT_ANALYZE defined");
4418 #endif
4419 	}
4420 	if (debug_specs & TXRX_DBG_MASK_RX_REORDER_TRACE) {
4421 #if defined(ENABLE_RX_REORDER_TRACE)
4422 		ol_rx_reorder_trace_display(vdev->pdev, 0, 0);
4423 #else
4424 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_FATAL,
4425 			  "rx reorder seq num trace is disabled.\n To enable it, recompile with ENABLE_RX_REORDER_TRACE defined");
4426 #endif
4427 
4428 	}
4429 	return 0;
4430 }
4431 #endif
4432 
4433 #ifdef currently_unused
ol_txrx_aggr_cfg(ol_txrx_vdev_handle vdev,int max_subfrms_ampdu,int max_subfrms_amsdu)4434 int ol_txrx_aggr_cfg(ol_txrx_vdev_handle vdev,
4435 		     int max_subfrms_ampdu, int max_subfrms_amsdu)
4436 {
4437 	return htt_h2t_aggr_cfg_msg(vdev->pdev->htt_pdev,
4438 				    max_subfrms_ampdu, max_subfrms_amsdu);
4439 }
4440 #endif
4441 
4442 #if defined(TXRX_DEBUG_LEVEL) && TXRX_DEBUG_LEVEL > 5
ol_txrx_pdev_display(ol_txrx_pdev_handle pdev,int indent)4443 void ol_txrx_pdev_display(ol_txrx_pdev_handle pdev, int indent)
4444 {
4445 	struct ol_txrx_vdev_t *vdev;
4446 
4447 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
4448 		  "%*s%s:\n", indent, " ", "txrx pdev");
4449 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
4450 		  "%*spdev object: %pK", indent + 4, " ", pdev);
4451 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
4452 		  "%*svdev list:", indent + 4, " ");
4453 	TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
4454 		      ol_txrx_vdev_display(vdev, indent + 8);
4455 	}
4456 	ol_txrx_peer_find_display(pdev, indent + 4);
4457 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
4458 		  "%*stx desc pool: %d elems @ %pK", indent + 4, " ",
4459 		  pdev->tx_desc.pool_size, pdev->tx_desc.array);
4460 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, " ");
4461 	htt_display(pdev->htt_pdev, indent);
4462 }
4463 
ol_txrx_vdev_display(ol_txrx_vdev_handle vdev,int indent)4464 void ol_txrx_vdev_display(ol_txrx_vdev_handle vdev, int indent)
4465 {
4466 	struct ol_txrx_peer_t *peer;
4467 
4468 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
4469 		  "%*stxrx vdev: %pK\n", indent, " ", vdev);
4470 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
4471 		  "%*sID: %d\n", indent + 4, " ", vdev->vdev_id);
4472 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
4473 		  "%*sMAC addr: %d:%d:%d:%d:%d:%d",
4474 		  indent + 4, " ",
4475 		  vdev->mac_addr.raw[0], vdev->mac_addr.raw[1],
4476 		  vdev->mac_addr.raw[2], vdev->mac_addr.raw[3],
4477 		  vdev->mac_addr.raw[4], vdev->mac_addr.raw[5]);
4478 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
4479 		  "%*speer list:", indent + 4, " ");
4480 	TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) {
4481 		      ol_txrx_peer_display(peer, indent + 8);
4482 	}
4483 }
4484 
ol_txrx_peer_display(ol_txrx_peer_handle peer,int indent)4485 void ol_txrx_peer_display(ol_txrx_peer_handle peer, int indent)
4486 {
4487 	int i;
4488 
4489 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
4490 		  "%*stxrx peer: %pK", indent, " ", peer);
4491 	for (i = 0; i < MAX_NUM_PEER_ID_PER_PEER; i++) {
4492 		if (peer->peer_ids[i] != HTT_INVALID_PEER) {
4493 			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
4494 				  "%*sID: %d", indent + 4, " ",
4495 				  peer->peer_ids[i]);
4496 		}
4497 	}
4498 }
4499 #endif /* TXRX_DEBUG_LEVEL */
4500 
4501 /**
4502  * ol_txrx_stats() - update ol layer stats
4503  * @vdev_id: vdev_id
4504  * @buffer: pointer to buffer
4505  * @buf_len: length of the buffer
4506  *
4507  * Return: length of string
4508  */
4509 static int
ol_txrx_stats(uint8_t vdev_id,char * buffer,unsigned int buf_len)4510 ol_txrx_stats(uint8_t vdev_id, char *buffer, unsigned int buf_len)
4511 {
4512 	uint32_t len = 0;
4513 
4514 	struct ol_txrx_vdev_t *vdev =
4515 			(struct ol_txrx_vdev_t *)
4516 			ol_txrx_get_vdev_from_vdev_id(vdev_id);
4517 
4518 	if (!vdev) {
4519 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
4520 			  "%s: vdev is NULL", __func__);
4521 		snprintf(buffer, buf_len, "vdev not found");
4522 		return len;
4523 	}
4524 
4525 	len = scnprintf(buffer, buf_len,
4526 			"\n\nTXRX stats:\nllQueue State : %s\npause %u unpause %u\noverflow %u\nllQueue timer state : %s",
4527 			((vdev->ll_pause.is_q_paused == false) ?
4528 			 "UNPAUSED" : "PAUSED"),
4529 			vdev->ll_pause.q_pause_cnt,
4530 			vdev->ll_pause.q_unpause_cnt,
4531 			vdev->ll_pause.q_overflow_cnt,
4532 			((vdev->ll_pause.is_q_timer_on == false)
4533 			 ? "NOT-RUNNING" : "RUNNING"));
4534 	return len;
4535 }
4536 
4537 #ifdef QCA_SUPPORT_TXRX_LOCAL_PEER_ID
4538 /**
4539  * ol_txrx_disp_peer_cached_bufq_stats() - display peer cached_bufq stats
4540  * @peer: peer pointer
4541  *
4542  * Return: None
4543  */
ol_txrx_disp_peer_cached_bufq_stats(struct ol_txrx_peer_t * peer)4544 static void ol_txrx_disp_peer_cached_bufq_stats(struct ol_txrx_peer_t *peer)
4545 {
4546 	txrx_nofl_info("cached_bufq: curr %d drops %d hwm %d whatifs %d thresh %d",
4547 		       peer->bufq_info.curr,
4548 		       peer->bufq_info.dropped,
4549 		       peer->bufq_info.high_water_mark,
4550 		       peer->bufq_info.qdepth_no_thresh,
4551 		       peer->bufq_info.thresh);
4552 }
4553 
4554 /**
4555  * ol_txrx_disp_peer_stats() - display peer stats
4556  * @pdev: pdev pointer
4557  *
4558  * Return: None
4559  */
ol_txrx_disp_peer_stats(ol_txrx_pdev_handle pdev)4560 static void ol_txrx_disp_peer_stats(ol_txrx_pdev_handle pdev)
4561 {	int i;
4562 	struct ol_txrx_peer_t *peer;
4563 	struct hif_opaque_softc *osc =  cds_get_context(QDF_MODULE_ID_HIF);
4564 
4565 	if (osc && hif_is_load_or_unload_in_progress(HIF_GET_SOFTC(osc)))
4566 		return;
4567 
4568 	for (i = 0; i < OL_TXRX_NUM_LOCAL_PEER_IDS; i++) {
4569 		qdf_spin_lock_bh(&pdev->peer_ref_mutex);
4570 		qdf_spin_lock_bh(&pdev->local_peer_ids.lock);
4571 		peer = pdev->local_peer_ids.map[i];
4572 		if (peer) {
4573 			ol_txrx_peer_get_ref(peer, PEER_DEBUG_ID_OL_INTERNAL);
4574 		}
4575 		qdf_spin_unlock_bh(&pdev->local_peer_ids.lock);
4576 		qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
4577 
4578 		if (peer) {
4579 			txrx_nofl_info("stats: peer 0x%pK local peer id %d",
4580 				       peer, i);
4581 			ol_txrx_disp_peer_cached_bufq_stats(peer);
4582 			ol_txrx_peer_release_ref(peer,
4583 						 PEER_DEBUG_ID_OL_INTERNAL);
4584 		}
4585 	}
4586 }
4587 #else
ol_txrx_disp_peer_stats(ol_txrx_pdev_handle pdev)4588 static void ol_txrx_disp_peer_stats(ol_txrx_pdev_handle pdev)
4589 {
4590 	txrx_nofl_info("peer stats not supported w/o QCA_SUPPORT_TXRX_LOCAL_PEER_ID");
4591 }
4592 #endif
4593 
ol_txrx_stats_display(ol_txrx_pdev_handle pdev,enum qdf_stats_verbosity_level level)4594 void ol_txrx_stats_display(ol_txrx_pdev_handle pdev,
4595 			   enum qdf_stats_verbosity_level level)
4596 {
4597 	u64 tx_dropped =
4598 		pdev->stats.pub.tx.dropped.download_fail.pkts
4599 		  + pdev->stats.pub.tx.dropped.target_discard.pkts
4600 		  + pdev->stats.pub.tx.dropped.no_ack.pkts
4601 		  + pdev->stats.pub.tx.dropped.target_drop.pkts
4602 		  + pdev->stats.pub.tx.dropped.others.pkts;
4603 
4604 	if (level == QDF_STATS_VERBOSITY_LEVEL_LOW) {
4605 		txrx_nofl_dbg("STATS |%u %u|TX: %lld tso %lld ok %lld drops(%u-%lld %u-%lld %u-%lld %u-%lld ?-%lld hR-%lld)|RX: %lld drops(E %lld PI %lld ME %lld) fwd(S %d F %d SF %d)|",
4606 			      pdev->tx_desc.num_free,
4607 			      pdev->tx_desc.pool_size,
4608 			      pdev->stats.pub.tx.from_stack.pkts,
4609 			      pdev->stats.pub.tx.tso.tso_pkts.pkts,
4610 			      pdev->stats.pub.tx.delivered.pkts,
4611 			      htt_tx_status_download_fail,
4612 			      pdev->stats.pub.tx.dropped.download_fail.pkts,
4613 			      htt_tx_status_discard,
4614 			      pdev->stats.pub.tx.dropped.
4615 					target_discard.pkts,
4616 			      htt_tx_status_no_ack,
4617 			      pdev->stats.pub.tx.dropped.no_ack.pkts,
4618 			      htt_tx_status_drop,
4619 			      pdev->stats.pub.tx.dropped.target_drop.pkts,
4620 			      pdev->stats.pub.tx.dropped.others.pkts,
4621 			      pdev->stats.pub.tx.dropped.host_reject.pkts,
4622 			      pdev->stats.pub.rx.delivered.pkts,
4623 			      pdev->stats.pub.rx.dropped_err.pkts,
4624 			      pdev->stats.pub.rx.dropped_peer_invalid.pkts,
4625 			      pdev->stats.pub.rx.dropped_mic_err.pkts,
4626 			      pdev->stats.pub.rx.intra_bss_fwd.
4627 					packets_stack,
4628 			      pdev->stats.pub.rx.intra_bss_fwd.
4629 					packets_fwd,
4630 			      pdev->stats.pub.rx.intra_bss_fwd.
4631 					packets_stack_n_fwd);
4632 		return;
4633 	}
4634 
4635 	txrx_nofl_info("TX PATH Statistics:");
4636 	txrx_nofl_info("sent %lld msdus (%lld B), host rejected %lld (%lld B), dropped %lld (%lld B)",
4637 		       pdev->stats.pub.tx.from_stack.pkts,
4638 		       pdev->stats.pub.tx.from_stack.bytes,
4639 		       pdev->stats.pub.tx.dropped.host_reject.pkts,
4640 		       pdev->stats.pub.tx.dropped.host_reject.bytes,
4641 			  tx_dropped,
4642 		       pdev->stats.pub.tx.dropped.download_fail.bytes
4643 			  + pdev->stats.pub.tx.dropped.target_discard.bytes
4644 			  + pdev->stats.pub.tx.dropped.target_drop.bytes
4645 			  + pdev->stats.pub.tx.dropped.no_ack.bytes);
4646 	txrx_nofl_info("successfully delivered: %lld (%lld B), download fail: %lld (%lld B), target discard: %lld (%lld B), no ack: %lld (%lld B),target drop: %lld (%lld B), others: %lld (%lld B)",
4647 		       pdev->stats.pub.tx.delivered.pkts,
4648 		       pdev->stats.pub.tx.delivered.bytes,
4649 		       pdev->stats.pub.tx.dropped.download_fail.pkts,
4650 		       pdev->stats.pub.tx.dropped.download_fail.bytes,
4651 		       pdev->stats.pub.tx.dropped.target_discard.pkts,
4652 		       pdev->stats.pub.tx.dropped.target_discard.bytes,
4653 		       pdev->stats.pub.tx.dropped.no_ack.pkts,
4654 		       pdev->stats.pub.tx.dropped.no_ack.bytes,
4655 		       pdev->stats.pub.tx.dropped.target_drop.pkts,
4656 		       pdev->stats.pub.tx.dropped.target_drop.bytes,
4657 		       pdev->stats.pub.tx.dropped.others.pkts,
4658 		       pdev->stats.pub.tx.dropped.others.bytes);
4659 	txrx_nofl_info("Tx completions per HTT message:\n"
4660 		       "Single Packet  %d\n"
4661 		       " 2-10 Packets  %d\n"
4662 		       "11-20 Packets  %d\n"
4663 		       "21-30 Packets  %d\n"
4664 		       "31-40 Packets  %d\n"
4665 		       "41-50 Packets  %d\n"
4666 		       "51-60 Packets  %d\n"
4667 		       "  60+ Packets  %d\n",
4668 		       pdev->stats.pub.tx.comp_histogram.pkts_1,
4669 		       pdev->stats.pub.tx.comp_histogram.pkts_2_10,
4670 		       pdev->stats.pub.tx.comp_histogram.pkts_11_20,
4671 		       pdev->stats.pub.tx.comp_histogram.pkts_21_30,
4672 		       pdev->stats.pub.tx.comp_histogram.pkts_31_40,
4673 		       pdev->stats.pub.tx.comp_histogram.pkts_41_50,
4674 		       pdev->stats.pub.tx.comp_histogram.pkts_51_60,
4675 		       pdev->stats.pub.tx.comp_histogram.pkts_61_plus);
4676 
4677 	txrx_nofl_info("RX PATH Statistics:");
4678 	txrx_nofl_info("%lld ppdus, %lld mpdus, %lld msdus, %lld bytes\n"
4679 		       "dropped: err %lld (%lld B), peer_invalid %lld (%lld B), mic_err %lld (%lld B)\n"
4680 		       "msdus with frag_ind: %d msdus with offload_ind: %d",
4681 		       pdev->stats.priv.rx.normal.ppdus,
4682 		       pdev->stats.priv.rx.normal.mpdus,
4683 		       pdev->stats.pub.rx.delivered.pkts,
4684 		       pdev->stats.pub.rx.delivered.bytes,
4685 		       pdev->stats.pub.rx.dropped_err.pkts,
4686 		       pdev->stats.pub.rx.dropped_err.bytes,
4687 		       pdev->stats.pub.rx.dropped_peer_invalid.pkts,
4688 		       pdev->stats.pub.rx.dropped_peer_invalid.bytes,
4689 		       pdev->stats.pub.rx.dropped_mic_err.pkts,
4690 		       pdev->stats.pub.rx.dropped_mic_err.bytes,
4691 		       pdev->stats.pub.rx.msdus_with_frag_ind,
4692 		       pdev->stats.pub.rx.msdus_with_offload_ind);
4693 
4694 	txrx_nofl_info("  fwd to stack %d, fwd to fw %d, fwd to stack & fw  %d\n",
4695 		       pdev->stats.pub.rx.intra_bss_fwd.packets_stack,
4696 		       pdev->stats.pub.rx.intra_bss_fwd.packets_fwd,
4697 		       pdev->stats.pub.rx.intra_bss_fwd.packets_stack_n_fwd);
4698 
4699 	txrx_nofl_info("packets per HTT message:\n"
4700 		       "Single Packet  %d\n"
4701 		       " 2-10 Packets  %d\n"
4702 		       "11-20 Packets  %d\n"
4703 		       "21-30 Packets  %d\n"
4704 		       "31-40 Packets  %d\n"
4705 		       "41-50 Packets  %d\n"
4706 		       "51-60 Packets  %d\n"
4707 		       "  60+ Packets  %d\n",
4708 		       pdev->stats.pub.rx.rx_ind_histogram.pkts_1,
4709 		       pdev->stats.pub.rx.rx_ind_histogram.pkts_2_10,
4710 		       pdev->stats.pub.rx.rx_ind_histogram.pkts_11_20,
4711 		       pdev->stats.pub.rx.rx_ind_histogram.pkts_21_30,
4712 		       pdev->stats.pub.rx.rx_ind_histogram.pkts_31_40,
4713 		       pdev->stats.pub.rx.rx_ind_histogram.pkts_41_50,
4714 		       pdev->stats.pub.rx.rx_ind_histogram.pkts_51_60,
4715 		       pdev->stats.pub.rx.rx_ind_histogram.pkts_61_plus);
4716 
4717 	ol_txrx_disp_peer_stats(pdev);
4718 }
4719 
ol_txrx_stats_clear(ol_txrx_pdev_handle pdev)4720 void ol_txrx_stats_clear(ol_txrx_pdev_handle pdev)
4721 {
4722 	qdf_mem_zero(&pdev->stats, sizeof(pdev->stats));
4723 }
4724 
4725 #if defined(ENABLE_TXRX_PROT_ANALYZE)
4726 
ol_txrx_prot_ans_display(ol_txrx_pdev_handle pdev)4727 void ol_txrx_prot_ans_display(ol_txrx_pdev_handle pdev)
4728 {
4729 	ol_txrx_prot_an_display(pdev->prot_an_tx_sent);
4730 	ol_txrx_prot_an_display(pdev->prot_an_rx_sent);
4731 }
4732 
4733 #endif /* ENABLE_TXRX_PROT_ANALYZE */
4734 
4735 #ifdef QCA_SUPPORT_PEER_DATA_RX_RSSI
ol_txrx_peer_rssi(ol_txrx_peer_handle peer)4736 int16_t ol_txrx_peer_rssi(ol_txrx_peer_handle peer)
4737 {
4738 	return (peer->rssi_dbm == HTT_RSSI_INVALID) ?
4739 	       OL_TXRX_RSSI_INVALID : peer->rssi_dbm;
4740 }
4741 #endif /* #ifdef QCA_SUPPORT_PEER_DATA_RX_RSSI */
4742 
4743 #ifdef QCA_ENABLE_OL_TXRX_PEER_STATS
4744 A_STATUS
ol_txrx_peer_stats_copy(ol_txrx_pdev_handle pdev,ol_txrx_peer_handle peer,ol_txrx_peer_stats_t * stats)4745 ol_txrx_peer_stats_copy(ol_txrx_pdev_handle pdev,
4746 			ol_txrx_peer_handle peer, ol_txrx_peer_stats_t *stats)
4747 {
4748 	qdf_assert(pdev && peer && stats);
4749 	qdf_spin_lock_bh(&pdev->peer_stat_mutex);
4750 	qdf_mem_copy(stats, &peer->stats, sizeof(*stats));
4751 	qdf_spin_unlock_bh(&pdev->peer_stat_mutex);
4752 	return A_OK;
4753 }
4754 #endif /* QCA_ENABLE_OL_TXRX_PEER_STATS */
4755 
4756 /**
4757  * ol_vdev_rx_set_intrabss_fwd() - Get fw stats
4758  *
4759  * @soc_hdl: datapath soc handle
4760  * @vdev_id: virtual interface id
4761  * @val: enable or disable
4762  *
4763  * Return: void
4764  */
ol_vdev_rx_set_intrabss_fwd(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,bool val)4765 static void ol_vdev_rx_set_intrabss_fwd(struct cdp_soc_t *soc_hdl,
4766 					uint8_t vdev_id, bool val)
4767 {
4768 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
4769 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
4770 								     vdev_id);
4771 
4772 	if (!vdev)
4773 		return;
4774 
4775 	vdev->disable_intrabss_fwd = val;
4776 }
4777 
4778 /**
4779  * ol_txrx_update_mac_id() - update mac_id for vdev
4780  * @soc_hdl: Datapath soc handle
4781  * @vdev_id: vdev id
4782  * @mac_id: mac id
4783  *
4784  * Return: none
4785  */
ol_txrx_update_mac_id(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,uint8_t mac_id)4786 static void ol_txrx_update_mac_id(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
4787 				  uint8_t mac_id)
4788 {
4789 	struct ol_txrx_vdev_t *vdev =
4790 			(struct ol_txrx_vdev_t *)
4791 			ol_txrx_get_vdev_from_vdev_id(vdev_id);
4792 
4793 	if (!vdev) {
4794 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
4795 			  "%s: Invalid vdev_id %d", __func__, vdev_id);
4796 		return;
4797 	}
4798 	vdev->mac_id = mac_id;
4799 }
4800 
4801 /**
4802  * ol_txrx_get_tx_ack_count() - get tx ack count
4803  * @soc_hdl: Datapath soc handle
4804  * @vdev_id: vdev_id
4805  *
4806  * Return: tx ack count
4807  */
ol_txrx_get_tx_ack_stats(struct cdp_soc_t * soc_hdl,uint8_t vdev_id)4808 static uint32_t ol_txrx_get_tx_ack_stats(struct cdp_soc_t *soc_hdl,
4809 					 uint8_t vdev_id)
4810 {
4811 	struct ol_txrx_vdev_t *vdev =
4812 		(struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
4813 
4814 	if (!vdev) {
4815 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
4816 			  "%s: Invalid vdev_id %d", __func__, vdev_id);
4817 		return 0;
4818 	}
4819 
4820 	return vdev->txrx_stats.txack_success;
4821 }
4822 
4823 /**
4824  * ol_txrx_display_stats() - Display OL TXRX display stats
4825  * @soc_hdl: Datapath soc handle
4826  * @value: Module id for which stats needs to be displayed
4827  * @verb_level: verbose level of stats to be displayed
4828  *
4829  * Return: status
4830  */
4831 static QDF_STATUS
ol_txrx_display_stats(struct cdp_soc_t * soc_hdl,uint16_t value,enum qdf_stats_verbosity_level verb_level)4832 ol_txrx_display_stats(struct cdp_soc_t *soc_hdl, uint16_t value,
4833 		      enum qdf_stats_verbosity_level verb_level)
4834 {
4835 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
4836 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(
4837 							soc,
4838 							OL_TXRX_PDEV_ID);
4839 	QDF_STATUS status = QDF_STATUS_SUCCESS;
4840 
4841 	if (!pdev) {
4842 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
4843 			  "%s: pdev is NULL", __func__);
4844 		return QDF_STATUS_E_NULL_VALUE;
4845 	}
4846 
4847 	switch (value) {
4848 	case CDP_TXRX_PATH_STATS:
4849 		ol_txrx_stats_display(pdev, verb_level);
4850 		break;
4851 	case CDP_TXRX_TSO_STATS:
4852 		ol_txrx_stats_display_tso(pdev);
4853 		break;
4854 	case CDP_DUMP_TX_FLOW_POOL_INFO:
4855 		if (verb_level == QDF_STATS_VERBOSITY_LEVEL_LOW)
4856 			ol_tx_dump_flow_pool_info_compact(pdev);
4857 		else
4858 			ol_tx_dump_flow_pool_info(soc_hdl);
4859 		break;
4860 	case CDP_TXRX_DESC_STATS:
4861 		qdf_nbuf_tx_desc_count_display();
4862 		break;
4863 	case CDP_WLAN_RX_BUF_DEBUG_STATS:
4864 		htt_display_rx_buf_debug(pdev->htt_pdev);
4865 		break;
4866 #ifdef CONFIG_HL_SUPPORT
4867 	case CDP_SCHEDULER_STATS:
4868 		ol_tx_sched_cur_state_display(pdev);
4869 		ol_tx_sched_stats_display(pdev);
4870 		break;
4871 	case CDP_TX_QUEUE_STATS:
4872 		ol_tx_queue_log_display(pdev);
4873 		break;
4874 #ifdef FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL
4875 	case CDP_CREDIT_STATS:
4876 		ol_tx_dump_group_credit_stats(pdev);
4877 		break;
4878 #endif
4879 
4880 #ifdef DEBUG_HL_LOGGING
4881 	case CDP_BUNDLE_STATS:
4882 		htt_dump_bundle_stats(pdev->htt_pdev);
4883 		break;
4884 #endif
4885 #endif
4886 	default:
4887 		status = QDF_STATUS_E_INVAL;
4888 		break;
4889 	}
4890 	return status;
4891 }
4892 
4893 /**
4894  * ol_txrx_clear_stats() - Clear OL TXRX stats
4895  * @soc - ol soc handle
4896  * @pdev_id: pdev identifier
4897  * @value - Module id for which stats needs to be cleared
4898  *
4899  * Return: 0 - success/ non-zero failure
4900  */
ol_txrx_clear_stats(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,uint8_t value)4901 static QDF_STATUS ol_txrx_clear_stats(struct cdp_soc_t *soc_hdl,
4902 				      uint8_t pdev_id, uint8_t value)
4903 {
4904 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
4905 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
4906 	QDF_STATUS status = QDF_STATUS_SUCCESS;
4907 
4908 	if (!pdev) {
4909 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
4910 			  "%s: pdev is NULL", __func__);
4911 		return QDF_STATUS_E_INVAL;
4912 	}
4913 
4914 	switch (value) {
4915 	case CDP_TXRX_PATH_STATS:
4916 		ol_txrx_stats_clear(pdev);
4917 		break;
4918 	case CDP_TXRX_TSO_STATS:
4919 		ol_txrx_tso_stats_clear(pdev);
4920 		break;
4921 	case CDP_DUMP_TX_FLOW_POOL_INFO:
4922 		ol_tx_clear_flow_pool_stats();
4923 		break;
4924 	case CDP_TXRX_DESC_STATS:
4925 		qdf_nbuf_tx_desc_count_clear();
4926 		break;
4927 #ifdef CONFIG_HL_SUPPORT
4928 	case CDP_SCHEDULER_STATS:
4929 		ol_tx_sched_stats_clear(pdev);
4930 		break;
4931 	case CDP_TX_QUEUE_STATS:
4932 		ol_tx_queue_log_clear(pdev);
4933 		break;
4934 #ifdef FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL
4935 	case CDP_CREDIT_STATS:
4936 		ol_tx_clear_group_credit_stats(pdev);
4937 		break;
4938 #endif
4939 	case CDP_BUNDLE_STATS:
4940 		htt_clear_bundle_stats(pdev->htt_pdev);
4941 		break;
4942 #endif
4943 	default:
4944 		status = QDF_STATUS_E_INVAL;
4945 		break;
4946 	}
4947 
4948 	return status;
4949 }
4950 
4951 /**
4952  * ol_txrx_drop_nbuf_list() - drop an nbuf list
4953  * @buf_list: buffer list to be dropepd
4954  *
4955  * Return: int (number of bufs dropped)
4956  */
ol_txrx_drop_nbuf_list(qdf_nbuf_t buf_list)4957 static inline int ol_txrx_drop_nbuf_list(qdf_nbuf_t buf_list)
4958 {
4959 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
4960 	ol_txrx_pdev_handle pdev;
4961 	int num_dropped = 0;
4962 	qdf_nbuf_t buf, next_buf;
4963 
4964 	if (qdf_unlikely(!soc))
4965 		return 0;
4966 
4967 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
4968 	if (!pdev) {
4969 		ol_txrx_err("pdev is NULL");
4970 		return 0;
4971 	}
4972 
4973 	buf = buf_list;
4974 	while (buf) {
4975 		QDF_NBUF_CB_RX_PEER_CACHED_FRM(buf) = 1;
4976 		next_buf = qdf_nbuf_queue_next(buf);
4977 		if (pdev)
4978 			TXRX_STATS_MSDU_INCR(pdev,
4979 				 rx.dropped_peer_invalid, buf);
4980 		qdf_nbuf_free(buf);
4981 		buf = next_buf;
4982 		num_dropped++;
4983 	}
4984 	return num_dropped;
4985 }
4986 
4987 /**
4988  * ol_rx_data_handler() - data rx handler
4989  * @pdev: dev handle
4990  * @buf_list: buffer list
4991  * @staid: Station id
4992  *
4993  * Return: None
4994  */
ol_rx_data_handler(struct ol_txrx_pdev_t * pdev,qdf_nbuf_t buf_list,uint16_t staid)4995 static void ol_rx_data_handler(struct ol_txrx_pdev_t *pdev,
4996 			       qdf_nbuf_t buf_list, uint16_t staid)
4997 {
4998 	void *osif_dev;
4999 	uint8_t drop_count = 0;
5000 	qdf_nbuf_t buf, next_buf;
5001 	QDF_STATUS ret;
5002 	ol_txrx_rx_fp data_rx = NULL;
5003 	struct ol_txrx_peer_t *peer;
5004 
5005 	if (qdf_unlikely(!pdev))
5006 		goto free_buf;
5007 
5008 	/* Do not use peer directly. Derive peer from staid to
5009 	 * make sure that peer is valid.
5010 	 */
5011 	peer = ol_txrx_peer_get_ref_by_local_id((struct cdp_pdev *)pdev,
5012 			staid, PEER_DEBUG_ID_OL_RX_THREAD);
5013 	if (!peer)
5014 		goto free_buf;
5015 
5016 	qdf_spin_lock_bh(&peer->peer_info_lock);
5017 	if (qdf_unlikely(!(peer->state >= OL_TXRX_PEER_STATE_CONN) ||
5018 					 !peer->vdev->rx)) {
5019 		qdf_spin_unlock_bh(&peer->peer_info_lock);
5020 		ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_RX_THREAD);
5021 		goto free_buf;
5022 	}
5023 
5024 	data_rx = peer->vdev->rx;
5025 	osif_dev = peer->vdev->osif_dev;
5026 	qdf_spin_unlock_bh(&peer->peer_info_lock);
5027 
5028 	qdf_spin_lock_bh(&peer->bufq_info.bufq_lock);
5029 	if (!list_empty(&peer->bufq_info.cached_bufq)) {
5030 		qdf_spin_unlock_bh(&peer->bufq_info.bufq_lock);
5031 		/* Flush the cached frames to HDD before passing new rx frame */
5032 		ol_txrx_flush_rx_frames(peer, 0);
5033 	} else
5034 		qdf_spin_unlock_bh(&peer->bufq_info.bufq_lock);
5035 
5036 	ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_RX_THREAD);
5037 
5038 	buf = buf_list;
5039 	while (buf) {
5040 		next_buf = qdf_nbuf_queue_next(buf);
5041 		qdf_nbuf_set_next(buf, NULL);   /* Add NULL terminator */
5042 		ret = data_rx(osif_dev, buf);
5043 		if (ret != QDF_STATUS_SUCCESS) {
5044 			ol_txrx_err("Frame Rx to HDD failed");
5045 			if (pdev)
5046 				TXRX_STATS_MSDU_INCR(pdev, rx.dropped_err, buf);
5047 			qdf_nbuf_free(buf);
5048 		}
5049 		buf = next_buf;
5050 	}
5051 	return;
5052 
5053 free_buf:
5054 	drop_count = ol_txrx_drop_nbuf_list(buf_list);
5055 	ol_txrx_warn("Dropped frames %u", drop_count);
5056 }
5057 
5058 /**
5059  * ol_rx_data_cb() - data rx callback
5060  * @context: dev handle
5061  * @buf_list: buffer list
5062  * @staid: Station id
5063  *
5064  * Return: None
5065  */
5066 static inline void
ol_rx_data_cb(void * context,qdf_nbuf_t buf_list,uint16_t staid)5067 ol_rx_data_cb(void *context, qdf_nbuf_t buf_list, uint16_t staid)
5068 {
5069 	struct ol_txrx_pdev_t *pdev = context;
5070 
5071 	ol_rx_data_handler(pdev, buf_list, staid);
5072 }
5073 
5074 /* print for every 16th packet */
5075 #define OL_TXRX_PRINT_RATE_LIMIT_THRESH 0x0f
5076 struct ol_rx_cached_buf *cache_buf;
5077 
5078 /** helper function to drop packets
5079  *  Note: caller must hold the cached buq lock before invoking
5080  *  this function. Also, it assumes that the pointers passed in
5081  *  are valid (non-NULL)
5082  */
ol_txrx_drop_frames(struct ol_txrx_cached_bufq_t * bufqi,qdf_nbuf_t rx_buf_list)5083 static inline void ol_txrx_drop_frames(
5084 					struct ol_txrx_cached_bufq_t *bufqi,
5085 					qdf_nbuf_t rx_buf_list)
5086 {
5087 	uint32_t dropped = ol_txrx_drop_nbuf_list(rx_buf_list);
5088 
5089 	bufqi->dropped += dropped;
5090 	bufqi->qdepth_no_thresh += dropped;
5091 
5092 	if (bufqi->qdepth_no_thresh > bufqi->high_water_mark)
5093 		bufqi->high_water_mark = bufqi->qdepth_no_thresh;
5094 }
5095 
ol_txrx_enqueue_rx_frames(struct ol_txrx_peer_t * peer,struct ol_txrx_cached_bufq_t * bufqi,qdf_nbuf_t rx_buf_list)5096 static QDF_STATUS ol_txrx_enqueue_rx_frames(
5097 					struct ol_txrx_peer_t *peer,
5098 					struct ol_txrx_cached_bufq_t *bufqi,
5099 					qdf_nbuf_t rx_buf_list)
5100 {
5101 	struct ol_rx_cached_buf *cache_buf;
5102 	qdf_nbuf_t buf, next_buf;
5103 	static uint32_t count;
5104 
5105 	if ((count++ & OL_TXRX_PRINT_RATE_LIMIT_THRESH) == 0)
5106 		ol_txrx_info_high(
5107 		   "Data on the peer before it is registered bufq->curr %d bufq->drops %d",
5108 		   bufqi->curr, bufqi->dropped);
5109 
5110 	qdf_spin_lock_bh(&bufqi->bufq_lock);
5111 	if (bufqi->curr >= bufqi->thresh) {
5112 		ol_txrx_drop_frames(bufqi, rx_buf_list);
5113 		qdf_spin_unlock_bh(&bufqi->bufq_lock);
5114 		return QDF_STATUS_E_FAULT;
5115 	}
5116 	qdf_spin_unlock_bh(&bufqi->bufq_lock);
5117 
5118 	buf = rx_buf_list;
5119 	while (buf) {
5120 		QDF_NBUF_CB_RX_PEER_CACHED_FRM(buf) = 1;
5121 		next_buf = qdf_nbuf_queue_next(buf);
5122 		cache_buf = qdf_mem_malloc(sizeof(*cache_buf));
5123 		if (!cache_buf) {
5124 			qdf_nbuf_free(buf);
5125 		} else {
5126 			/* Add NULL terminator */
5127 			qdf_nbuf_set_next(buf, NULL);
5128 			cache_buf->buf = buf;
5129 			if (peer && peer->valid) {
5130 				qdf_spin_lock_bh(&bufqi->bufq_lock);
5131 				list_add_tail(&cache_buf->list,
5132 				      &bufqi->cached_bufq);
5133 				bufqi->curr++;
5134 				qdf_spin_unlock_bh(&bufqi->bufq_lock);
5135 			} else {
5136 				qdf_mem_free(cache_buf);
5137 				rx_buf_list = buf;
5138 				qdf_nbuf_set_next(rx_buf_list, next_buf);
5139 				qdf_spin_lock_bh(&bufqi->bufq_lock);
5140 				ol_txrx_drop_frames(bufqi, rx_buf_list);
5141 				qdf_spin_unlock_bh(&bufqi->bufq_lock);
5142 				return QDF_STATUS_E_FAULT;
5143 			}
5144 		}
5145 		buf = next_buf;
5146 	}
5147 	return QDF_STATUS_SUCCESS;
5148 }
5149 /**
5150  * ol_rx_data_process() - process rx frame
5151  * @peer: peer
5152  * @rx_buf_list: rx buffer list
5153  *
5154  * Return: None
5155  */
ol_rx_data_process(struct ol_txrx_peer_t * peer,qdf_nbuf_t rx_buf_list)5156 void ol_rx_data_process(struct ol_txrx_peer_t *peer,
5157 			qdf_nbuf_t rx_buf_list)
5158 {
5159 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
5160 	ol_txrx_pdev_handle pdev;
5161 	/*
5162 	 * Firmware data path active response will use shim RX thread
5163 	 * T2H MSG running on SIRQ context,
5164 	 * IPA kernel module API should not be called on SIRQ CTXT
5165 	 */
5166 	ol_txrx_rx_fp data_rx = NULL;
5167 
5168 	if (qdf_unlikely(!soc))
5169 		goto drop_rx_buf;
5170 
5171 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
5172 	if ((!peer) || (!pdev)) {
5173 		ol_txrx_err("peer/pdev is NULL");
5174 		goto drop_rx_buf;
5175 	}
5176 
5177 	qdf_assert(peer->vdev);
5178 
5179 	qdf_spin_lock_bh(&peer->peer_info_lock);
5180 	if (peer->state >= OL_TXRX_PEER_STATE_CONN)
5181 		data_rx = peer->vdev->rx;
5182 	qdf_spin_unlock_bh(&peer->peer_info_lock);
5183 
5184 	/*
5185 	 * If there is a data frame from peer before the peer is
5186 	 * registered for data service, enqueue them on to pending queue
5187 	 * which will be flushed to HDD once that station is registered.
5188 	 */
5189 	if (!data_rx) {
5190 		if (ol_txrx_enqueue_rx_frames(peer, &peer->bufq_info,
5191 					      rx_buf_list)
5192 				!= QDF_STATUS_SUCCESS)
5193 			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH,
5194 				  "%s: failed to enqueue rx frm to cached_bufq",
5195 				  __func__);
5196 	} else {
5197 #ifdef WLAN_DP_LEGACY_OL_RX_THREAD
5198 		/*
5199 		 * If the kernel is SMP, schedule rx thread to
5200 		 * better use multicores.
5201 		 */
5202 		if (!ol_cfg_is_rx_thread_enabled(pdev->ctrl_pdev)) {
5203 			ol_rx_data_handler(pdev, rx_buf_list, peer->local_id);
5204 		} else {
5205 			p_cds_sched_context sched_ctx =
5206 				get_cds_sched_ctxt();
5207 			struct cds_ol_rx_pkt *pkt;
5208 
5209 			if (unlikely(!sched_ctx))
5210 				goto drop_rx_buf;
5211 
5212 			pkt = cds_alloc_ol_rx_pkt(sched_ctx);
5213 			if (!pkt)
5214 				goto drop_rx_buf;
5215 
5216 			pkt->callback = ol_rx_data_cb;
5217 			pkt->context = pdev;
5218 			pkt->Rxpkt = rx_buf_list;
5219 			pkt->staId = peer->local_id;
5220 			cds_indicate_rxpkt(sched_ctx, pkt);
5221 		}
5222 #else                           /* WLAN_DP_LEGACY_OL_RX_THREAD */
5223 		ol_rx_data_handler(pdev, rx_buf_list, peer->local_id);
5224 #endif /* WLAN_DP_LEGACY_OL_RX_THREAD */
5225 	}
5226 
5227 	return;
5228 
5229 drop_rx_buf:
5230 	ol_txrx_drop_nbuf_list(rx_buf_list);
5231 }
5232 
5233 /**
5234  * ol_txrx_register_peer() - register peer
5235  * @sta_desc: sta descriptor
5236  *
5237  * Return: QDF Status
5238  */
ol_txrx_register_peer(struct ol_txrx_desc_type * sta_desc)5239 static QDF_STATUS ol_txrx_register_peer(struct ol_txrx_desc_type *sta_desc)
5240 {
5241 	struct ol_txrx_peer_t *peer;
5242 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
5243 	ol_txrx_pdev_handle pdev;
5244 	union ol_txrx_peer_update_param_t param;
5245 	struct privacy_exemption privacy_filter;
5246 
5247 	if (!soc) {
5248 		ol_txrx_err("Soc is NULL");
5249 		return QDF_STATUS_E_INVAL;
5250 	}
5251 
5252 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
5253 
5254 	if (!pdev) {
5255 		ol_txrx_err("Pdev is NULL");
5256 		return QDF_STATUS_E_INVAL;
5257 	}
5258 
5259 	peer = ol_txrx_find_peer_by_addr((struct cdp_pdev *)pdev,
5260 					 sta_desc->peer_addr.bytes);
5261 
5262 	if (!peer)
5263 		return QDF_STATUS_E_FAULT;
5264 
5265 	qdf_spin_lock_bh(&peer->peer_info_lock);
5266 	peer->state = OL_TXRX_PEER_STATE_CONN;
5267 	qdf_spin_unlock_bh(&peer->peer_info_lock);
5268 
5269 	param.qos_capable = sta_desc->is_qos_enabled;
5270 	ol_txrx_peer_update(peer->vdev, peer->mac_addr.raw, &param,
5271 			    ol_txrx_peer_update_qos_capable);
5272 
5273 	if (sta_desc->is_wapi_supported) {
5274 		/*Privacy filter to accept unencrypted WAI frames */
5275 		privacy_filter.ether_type = ETHERTYPE_WAI;
5276 		privacy_filter.filter_type = PRIVACY_FILTER_ALWAYS;
5277 		privacy_filter.packet_type = PRIVACY_FILTER_PACKET_BOTH;
5278 		ol_txrx_set_privacy_filters(peer->vdev, &privacy_filter, 1);
5279 	}
5280 
5281 	ol_txrx_flush_rx_frames(peer, 0);
5282 	return QDF_STATUS_SUCCESS;
5283 }
5284 
5285 /**
5286  * ol_txrx_register_ocb_peer - Function to register the OCB peer
5287  * @mac_addr: MAC address of the self peer
5288  *
5289  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
5290  */
ol_txrx_register_ocb_peer(uint8_t * mac_addr)5291 static QDF_STATUS ol_txrx_register_ocb_peer(uint8_t *mac_addr)
5292 {
5293 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
5294 	ol_txrx_pdev_handle pdev;
5295 	ol_txrx_peer_handle peer;
5296 
5297 	if (!soc) {
5298 		ol_txrx_err("Unable to find soc!");
5299 		return QDF_STATUS_E_FAILURE;
5300 	}
5301 
5302 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
5303 
5304 	if (!pdev) {
5305 		ol_txrx_err("Unable to find pdev!");
5306 		return QDF_STATUS_E_FAILURE;
5307 	}
5308 
5309 	peer = ol_txrx_find_peer_by_addr((struct cdp_pdev *)pdev,
5310 					 mac_addr);
5311 	if (!peer) {
5312 		ol_txrx_err("Unable to find OCB peer!");
5313 		return QDF_STATUS_E_FAILURE;
5314 	}
5315 
5316 	ol_txrx_set_ocb_peer(pdev, peer);
5317 
5318 	/* Set peer state to connected */
5319 	ol_txrx_peer_state_update((struct cdp_soc_t *)soc, peer->mac_addr.raw,
5320 				  OL_TXRX_PEER_STATE_AUTH);
5321 
5322 	return QDF_STATUS_SUCCESS;
5323 }
5324 
5325 /**
5326  * ol_txrx_set_ocb_peer - Function to store the OCB peer
5327  * @pdev: Handle to the HTT instance
5328  * @peer: Pointer to the peer
5329  */
ol_txrx_set_ocb_peer(struct ol_txrx_pdev_t * pdev,struct ol_txrx_peer_t * peer)5330 void ol_txrx_set_ocb_peer(struct ol_txrx_pdev_t *pdev,
5331 			  struct ol_txrx_peer_t *peer)
5332 {
5333 	if (!pdev)
5334 		return;
5335 
5336 	pdev->ocb_peer = peer;
5337 	pdev->ocb_peer_valid = (NULL != peer);
5338 }
5339 
5340 /**
5341  * ol_txrx_get_ocb_peer - Function to retrieve the OCB peer
5342  * @pdev: Handle to the HTT instance
5343  * @peer: Pointer to the returned peer
5344  *
5345  * Return: true if the peer is valid, false if not
5346  */
ol_txrx_get_ocb_peer(struct ol_txrx_pdev_t * pdev,struct ol_txrx_peer_t ** peer)5347 bool ol_txrx_get_ocb_peer(struct ol_txrx_pdev_t *pdev,
5348 			  struct ol_txrx_peer_t **peer)
5349 {
5350 	int rc;
5351 
5352 	if ((!pdev) || (!peer)) {
5353 		rc = false;
5354 		goto exit;
5355 	}
5356 
5357 	if (pdev->ocb_peer_valid) {
5358 		*peer = pdev->ocb_peer;
5359 		rc = true;
5360 	} else {
5361 		rc = false;
5362 	}
5363 
5364 exit:
5365 	return rc;
5366 }
5367 
5368 /**
5369  * ol_txrx_register_pause_cb() - register pause callback
5370  * @soc_hdl: Datapath soc handle
5371  * @pause_cb: pause callback
5372  *
5373  * Return: QDF status
5374  */
ol_txrx_register_pause_cb(struct cdp_soc_t * soc_hdl,tx_pause_callback pause_cb)5375 static QDF_STATUS ol_txrx_register_pause_cb(struct cdp_soc_t *soc_hdl,
5376 					    tx_pause_callback pause_cb)
5377 {
5378 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
5379 	ol_txrx_pdev_handle pdev;
5380 
5381 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
5382 	if (!pdev || !pause_cb) {
5383 		ol_txrx_err("pdev or pause_cb is NULL");
5384 		return QDF_STATUS_E_INVAL;
5385 	}
5386 	pdev->pause_cb = pause_cb;
5387 	return QDF_STATUS_SUCCESS;
5388 }
5389 
5390 #ifdef RECEIVE_OFFLOAD
5391 /**
5392  * ol_txrx_offld_flush_handler() - offld flush handler
5393  * @context: dev handle
5394  * @rxpkt: rx data
5395  * @staid: station id
5396  *
5397  * This function handles an offld flush indication.
5398  * If the rx thread is enabled, it will be invoked by the rx
5399  * thread else it will be called in the tasklet context
5400  *
5401  * Return: none
5402  */
ol_txrx_offld_flush_handler(void * context,qdf_nbuf_t rxpkt,uint16_t staid)5403 static void ol_txrx_offld_flush_handler(void *context,
5404 					qdf_nbuf_t rxpkt,
5405 					uint16_t staid)
5406 {
5407 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
5408 	ol_txrx_pdev_handle pdev;
5409 
5410 	if (qdf_unlikely(!soc)) {
5411 		qdf_assert(0);
5412 		return;
5413 	}
5414 
5415 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
5416 	if (qdf_unlikely(!pdev)) {
5417 		ol_txrx_err("Invalid pdev context");
5418 		qdf_assert(0);
5419 		return;
5420 	}
5421 
5422 	if (pdev->offld_flush_cb)
5423 		pdev->offld_flush_cb(context);
5424 	else
5425 		ol_txrx_err("offld_flush_cb NULL");
5426 }
5427 
5428 /**
5429  * ol_txrx_offld_flush() - offld flush callback
5430  * @data: opaque data pointer
5431  *
5432  * This is the callback registered with CE to trigger
5433  * an offld flush
5434  *
5435  * Return: none
5436  */
ol_txrx_offld_flush(void * data)5437 static void ol_txrx_offld_flush(void *data)
5438 {
5439 	p_cds_sched_context sched_ctx = get_cds_sched_ctxt();
5440 	struct cds_ol_rx_pkt *pkt;
5441 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
5442 	ol_txrx_pdev_handle pdev;
5443 
5444 	if (qdf_unlikely(!sched_ctx))
5445 		return;
5446 
5447 	if (qdf_unlikely(!soc))
5448 		return;
5449 
5450 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
5451 	if (qdf_unlikely(!pdev)) {
5452 		ol_txrx_err("TXRX module context is NULL");
5453 		return;
5454 	}
5455 
5456 	if (!ol_cfg_is_rx_thread_enabled(pdev->ctrl_pdev)) {
5457 		ol_txrx_offld_flush_handler(data, NULL, 0);
5458 	} else {
5459 		pkt = cds_alloc_ol_rx_pkt(sched_ctx);
5460 		if (qdf_unlikely(!pkt))
5461 			return;
5462 
5463 		pkt->callback = ol_txrx_offld_flush_handler;
5464 		pkt->context = data;
5465 		pkt->Rxpkt = NULL;
5466 		pkt->staId = 0;
5467 		cds_indicate_rxpkt(sched_ctx, pkt);
5468 	}
5469 }
5470 
5471 /**
5472  * ol_register_offld_flush_cb() - register the offld flush callback
5473  * @offld_flush_cb: flush callback function
5474  * @offld_init_cb: Allocate and initialize offld data structure.
5475  *
5476  * Store the offld flush callback provided and in turn
5477  * register OL's offld flush handler with CE
5478  *
5479  * Return: none
5480  */
ol_register_offld_flush_cb(void (offld_flush_cb)(void *))5481 static void ol_register_offld_flush_cb(void (offld_flush_cb)(void *))
5482 {
5483 	struct hif_opaque_softc *hif_device;
5484 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
5485 	ol_txrx_pdev_handle pdev;
5486 
5487 	if (qdf_unlikely(!soc)) {
5488 		TXRX_ASSERT2(0);
5489 		goto out;
5490 	}
5491 
5492 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
5493 	if (!pdev) {
5494 		ol_txrx_err("pdev NULL!");
5495 		TXRX_ASSERT2(0);
5496 		goto out;
5497 	}
5498 	if (pdev->offld_flush_cb) {
5499 		ol_txrx_info("offld already initialised");
5500 		if (pdev->offld_flush_cb != offld_flush_cb) {
5501 			ol_txrx_err(
5502 				   "offld_flush_cb is differ to previously registered callback")
5503 			TXRX_ASSERT2(0);
5504 			goto out;
5505 		}
5506 		goto out;
5507 	}
5508 	pdev->offld_flush_cb = offld_flush_cb;
5509 	hif_device = cds_get_context(QDF_MODULE_ID_HIF);
5510 
5511 	if (qdf_unlikely(!hif_device)) {
5512 		qdf_assert(0);
5513 		goto out;
5514 	}
5515 
5516 	hif_offld_flush_cb_register(hif_device, ol_txrx_offld_flush);
5517 
5518 out:
5519 	return;
5520 }
5521 
5522 /**
5523  * ol_deregister_offld_flush_cb() - deregister the offld flush callback
5524  *
5525  * Remove the offld flush callback provided and in turn
5526  * deregister OL's offld flush handler with CE
5527  *
5528  * Return: none
5529  */
ol_deregister_offld_flush_cb(void)5530 static void ol_deregister_offld_flush_cb(void)
5531 {
5532 	struct hif_opaque_softc *hif_device;
5533 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
5534 	ol_txrx_pdev_handle pdev;
5535 
5536 	if (qdf_unlikely(!soc))
5537 		return;
5538 
5539 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
5540 	if (!pdev) {
5541 		ol_txrx_err("pdev NULL!");
5542 		return;
5543 	}
5544 	hif_device = cds_get_context(QDF_MODULE_ID_HIF);
5545 
5546 	if (qdf_unlikely(!hif_device)) {
5547 		qdf_assert(0);
5548 		return;
5549 	}
5550 
5551 	hif_offld_flush_cb_deregister(hif_device);
5552 
5553 	pdev->offld_flush_cb = NULL;
5554 }
5555 #endif /* RECEIVE_OFFLOAD */
5556 
5557 /**
5558  * ol_register_data_stall_detect_cb() - register data stall callback
5559  * @soc_hdl: Datapath soc handle
5560  * @pdev_id: id of data path pdev handle
5561  * @data_stall_detect_callback: data stall callback function
5562  *
5563  *
5564  * Return: QDF_STATUS Enumeration
5565  */
ol_register_data_stall_detect_cb(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,data_stall_detect_cb data_stall_detect_callback)5566 static QDF_STATUS ol_register_data_stall_detect_cb(
5567 			struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
5568 			data_stall_detect_cb data_stall_detect_callback)
5569 {
5570 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
5571 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
5572 
5573 	if (!pdev) {
5574 		ol_txrx_err("pdev NULL!");
5575 		return QDF_STATUS_E_INVAL;
5576 	}
5577 	pdev->data_stall_detect_callback = data_stall_detect_callback;
5578 	return QDF_STATUS_SUCCESS;
5579 }
5580 
5581 /**
5582  * ol_deregister_data_stall_detect_cb() - de-register data stall callback
5583  * @soc_hdl: Datapath soc handle
5584  * @pdev_id: id of data path pdev handle
5585  * @data_stall_detect_callback: data stall callback function
5586  *
5587  *
5588  * Return: QDF_STATUS Enumeration
5589  */
ol_deregister_data_stall_detect_cb(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,data_stall_detect_cb data_stall_detect_callback)5590 static QDF_STATUS ol_deregister_data_stall_detect_cb(
5591 			struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
5592 			data_stall_detect_cb data_stall_detect_callback)
5593 {
5594 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
5595 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
5596 
5597 	if (!pdev) {
5598 		ol_txrx_err("pdev NULL!");
5599 		return QDF_STATUS_E_INVAL;
5600 	}
5601 	pdev->data_stall_detect_callback = NULL;
5602 	return QDF_STATUS_SUCCESS;
5603 }
5604 
5605 /**
5606  * ol_txrx_post_data_stall_event() - post data stall event
5607  * @indicator: Module triggering data stall
5608  * @data_stall_type: data stall event type
5609  * @pdev_id: pdev id
5610  * @vdev_id_bitmap: vdev id bitmap
5611  * @recovery_type: data stall recovery type
5612  *
5613  * Return: None
5614  */
ol_txrx_post_data_stall_event(struct cdp_soc_t * soc_hdl,enum data_stall_log_event_indicator indicator,enum data_stall_log_event_type data_stall_type,uint32_t pdev_id,uint32_t vdev_id_bitmap,enum data_stall_log_recovery_type recovery_type)5615 static void ol_txrx_post_data_stall_event(
5616 				struct cdp_soc_t *soc_hdl,
5617 				enum data_stall_log_event_indicator indicator,
5618 				enum data_stall_log_event_type data_stall_type,
5619 				uint32_t pdev_id, uint32_t vdev_id_bitmap,
5620 				enum data_stall_log_recovery_type recovery_type)
5621 {
5622 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
5623 	struct data_stall_event_info data_stall_info;
5624 	ol_txrx_pdev_handle pdev;
5625 
5626 	if (qdf_unlikely(!soc)) {
5627 		ol_txrx_err("soc is NULL");
5628 		return;
5629 	}
5630 
5631 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
5632 	if (!pdev) {
5633 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
5634 			  "%s: pdev is NULL.", __func__);
5635 		return;
5636 	}
5637 
5638 	if (!pdev->data_stall_detect_callback) {
5639 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
5640 			  "%s: data stall cb not registered", __func__);
5641 		return;
5642 	}
5643 
5644 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
5645 		  "%s: data_stall_type: %x pdev_id: %d",
5646 		  __func__, data_stall_type, pdev_id);
5647 
5648 	data_stall_info.indicator = indicator;
5649 	data_stall_info.data_stall_type = data_stall_type;
5650 	data_stall_info.vdev_id_bitmap = vdev_id_bitmap;
5651 	data_stall_info.pdev_id = pdev_id;
5652 	data_stall_info.recovery_type = recovery_type;
5653 
5654 	if (data_stall_info.data_stall_type ==
5655 				DATA_STALL_LOG_FW_RX_REFILL_FAILED) {
5656 		htt_log_rx_ring_info(pdev->htt_pdev);
5657 		htt_rx_refill_failure(pdev->htt_pdev);
5658 	}
5659 
5660 	pdev->data_stall_detect_callback(&data_stall_info);
5661 }
5662 
5663 void
ol_txrx_dump_pkt(qdf_nbuf_t nbuf,uint32_t nbuf_paddr,int len)5664 ol_txrx_dump_pkt(qdf_nbuf_t nbuf, uint32_t nbuf_paddr, int len)
5665 {
5666 	qdf_print(" Pkt: VA 0x%pK PA 0x%llx len %d\n",
5667 		  qdf_nbuf_data(nbuf), (unsigned long long int)nbuf_paddr, len);
5668 	print_hex_dump(KERN_DEBUG, "Pkt:   ", DUMP_PREFIX_ADDRESS, 16, 4,
5669 		       qdf_nbuf_data(nbuf), len, true);
5670 }
5671 
ol_txrx_get_vdev_from_vdev_id(uint8_t vdev_id)5672 struct cdp_vdev *ol_txrx_get_vdev_from_vdev_id(uint8_t vdev_id)
5673 {
5674 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
5675 	ol_txrx_vdev_handle vdev = NULL;
5676 
5677 	if (qdf_unlikely(!soc))
5678 		return NULL;
5679 
5680 	vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc, vdev_id);
5681 
5682 	return ol_txrx_vdev_t_to_cdp_vdev(vdev);
5683 }
5684 
ol_txrx_get_vdev_from_soc_vdev_id(struct ol_txrx_soc_t * soc,uint8_t vdev_id)5685 struct ol_txrx_vdev_t *ol_txrx_get_vdev_from_soc_vdev_id(
5686 				struct ol_txrx_soc_t *soc, uint8_t vdev_id)
5687 {
5688 	ol_txrx_pdev_handle pdev;
5689 	ol_txrx_vdev_handle vdev = NULL;
5690 
5691 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
5692 	if (qdf_unlikely(!pdev))
5693 		return NULL;
5694 
5695 	TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
5696 		if (vdev->vdev_id == vdev_id)
5697 			break;
5698 	}
5699 
5700 	return vdev;
5701 }
5702 
5703 /**
5704  * ol_txrx_get_mon_vdev_from_pdev() - get monitor mode vdev from pdev
5705  * @soc_hdl: datapath soc handle
5706  * @pdev_id: the physical device id the virtual device belongs to
5707  *
5708  * Return: vdev id
5709  *            error if not found.
5710  */
ol_txrx_get_mon_vdev_from_pdev(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)5711 uint8_t ol_txrx_get_mon_vdev_from_pdev(struct cdp_soc_t *soc_hdl,
5712 				       uint8_t pdev_id)
5713 {
5714 	struct ol_txrx_soc_t *soc = (struct ol_txrx_soc_t *)soc_hdl;
5715 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
5716 
5717 	if (qdf_unlikely(!pdev))
5718 		return -EINVAL;
5719 
5720 	return pdev->monitor_vdev->vdev_id;
5721 }
5722 
5723 /**
5724  * ol_txrx_set_wisa_mode() - set wisa mode
5725  * @soc_hdl: Datapath soc handle
5726  * @vdev_id: vdev_id
5727  * @enable: enable flag
5728  *
5729  * Return: QDF STATUS
5730  */
ol_txrx_set_wisa_mode(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,bool enable)5731 static QDF_STATUS ol_txrx_set_wisa_mode(struct cdp_soc_t *soc_hdl,
5732 					uint8_t vdev_id, bool enable)
5733 {
5734 	struct ol_txrx_vdev_t *vdev =
5735 		(struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
5736 
5737 	if (!vdev)
5738 		return QDF_STATUS_E_INVAL;
5739 
5740 	vdev->is_wisa_mode_enable = enable;
5741 	return QDF_STATUS_SUCCESS;
5742 }
5743 
5744 /**
5745  * ol_txrx_get_vdev_id() - get interface id from interface context
5746  * @pvdev: vdev handle
5747  *
5748  * Return: virtual interface id
5749  */
ol_txrx_get_vdev_id(struct cdp_vdev * pvdev)5750 static uint16_t ol_txrx_get_vdev_id(struct cdp_vdev *pvdev)
5751 {
5752 	struct ol_txrx_vdev_t *vdev = (struct ol_txrx_vdev_t *)pvdev;
5753 
5754 	return vdev->vdev_id;
5755 }
5756 
5757 /**
5758  * ol_txrx_soc_attach_target() - attach soc target
5759  * @soc: soc handle
5760  *
5761  * MCL legacy OL do nothing here
5762  *
5763  * Return: 0
5764  */
ol_txrx_soc_attach_target(ol_txrx_soc_handle soc)5765 static QDF_STATUS ol_txrx_soc_attach_target(ol_txrx_soc_handle soc)
5766 {
5767 	/* MCL legacy OL do nothing here */
5768 	return QDF_STATUS_SUCCESS;
5769 }
5770 
5771 /**
5772  * ol_txrx_soc_detach() - detach soc target
5773  * @soc: soc handle
5774  *
5775  * MCL legacy OL do nothing here
5776  *
5777  * Return: none
5778  */
ol_txrx_soc_detach(struct cdp_soc_t * soc)5779 static void ol_txrx_soc_detach(struct cdp_soc_t *soc)
5780 {
5781 	qdf_mem_free(soc);
5782 }
5783 
5784 #ifdef REMOVE_PKT_LOG
5785 /**
5786  * ol_txrx_pkt_log_con_service() - connect packet log service
5787  * @soc_hdl: Datapath soc handle
5788  * @pdev_id: id of data path pdev handle
5789  * @scn: device context
5790  *
5791  * Return: none
5792  */
ol_txrx_pkt_log_con_service(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,void * scn)5793 static void ol_txrx_pkt_log_con_service(struct cdp_soc_t *soc_hdl,
5794 					uint8_t pdev_id, void *scn)
5795 {
5796 }
5797 
5798 /**
5799  * ol_txrx_pkt_log_exit() - cleanup packet log info
5800  * @soc_hdl: Datapath soc handle
5801  * @pdev_id: id of data path pdev handle
5802  *
5803  * Return: none
5804  */
ol_txrx_pkt_log_exit(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)5805 static void ol_txrx_pkt_log_exit(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
5806 {
5807 }
5808 
5809 #else
ol_txrx_pkt_log_con_service(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,void * scn)5810 static void ol_txrx_pkt_log_con_service(struct cdp_soc_t *soc_hdl,
5811 					uint8_t pdev_id, void *scn)
5812 {
5813 	htt_pkt_log_init(soc_hdl, pdev_id, scn);
5814 	pktlog_htc_attach();
5815 }
5816 
ol_txrx_pkt_log_exit(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)5817 static void ol_txrx_pkt_log_exit(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
5818 {
5819 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
5820 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
5821 
5822 	if (!pdev) {
5823 		ol_txrx_err("pdev handle is NULL");
5824 		return;
5825 	}
5826 
5827 	htt_pktlogmod_exit(pdev);
5828 }
5829 #endif
5830 
5831 /* OL wrapper functions for CDP abstraction */
5832 /**
5833  * ol_txrx_wrapper_flush_rx_frames() - flush rx frames on the queue
5834  * @soc: data path soc handle
5835  * @pdev_id: datapath pdev identifier
5836  * @peer_mac: peer mac address
5837  * @drop: rx packets drop or deliver
5838  *
5839  * Return: none
5840  */
ol_txrx_wrapper_flush_rx_frames(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,void * peer_mac,bool drop)5841 static void ol_txrx_wrapper_flush_rx_frames(struct cdp_soc_t *soc_hdl,
5842 					    uint8_t pdev_id, void *peer_mac,
5843 					    bool drop)
5844 {
5845 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
5846 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
5847 	struct ol_txrx_peer_t *peer;
5848 
5849 	if (!pdev) {
5850 		ol_txrx_err("pdev is NULL");
5851 		return;
5852 	}
5853 
5854 	peer = ol_txrx_peer_find_hash_find_get_ref(pdev, peer_mac, 0, 1,
5855 						   PEER_DEBUG_ID_OL_INTERNAL);
5856 	if (!peer) {
5857 		ol_txrx_err("peer "QDF_MAC_ADDR_FMT" not found",
5858 			    QDF_MAC_ADDR_REF(peer_mac));
5859 		return;
5860 	}
5861 
5862 	ol_txrx_flush_rx_frames(peer, drop);
5863 }
5864 
5865 /**
5866  * ol_txrx_wrapper_register_peer() - register peer
5867  * @pdev: pdev handle
5868  * @sta_desc: peer description
5869  *
5870  * Return: QDF STATUS
5871  */
ol_txrx_wrapper_register_peer(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,struct ol_txrx_desc_type * sta_desc)5872 static QDF_STATUS ol_txrx_wrapper_register_peer(
5873 					struct cdp_soc_t *soc_hdl,
5874 					uint8_t pdev_id,
5875 					struct ol_txrx_desc_type *sta_desc)
5876 {
5877 	return ol_txrx_register_peer(sta_desc);
5878 }
5879 
5880 /**
5881  * ol_txrx_wrapper_cfg_is_high_latency() - device is high or low latency device
5882  * @pdev: pdev handle
5883  *
5884  * Return: 1 high latency bus
5885  *         0 low latency bus
5886  */
ol_txrx_wrapper_cfg_is_high_latency(struct cdp_cfg * cfg_pdev)5887 static int ol_txrx_wrapper_cfg_is_high_latency(struct cdp_cfg *cfg_pdev)
5888 {
5889 	return ol_cfg_is_high_latency(cfg_pdev);
5890 }
5891 
5892 /**
5893  * ol_txrx_wrapper_peer_state_update() - specify the peer's authentication state
5894  * @soc_hdl - datapath soc handle
5895  * @peer_mac - mac address of which peer has changed its state
5896  * @state - the new state of the peer
5897  *
5898  *  Specify the peer's authentication state (none, connected, authenticated)
5899  *  to allow the data SW to determine whether to filter out invalid data frames.
5900  *  (In the "connected" state, where security is enabled, but authentication
5901  *  has not completed, tx and rx data frames other than EAPOL or WAPI should
5902  *  be discarded.)
5903  *  This function is only relevant for systems in which the tx and rx filtering
5904  *  are done in the host rather than in the target.
5905  *
5906  * Return: QDF Status
5907  */
ol_txrx_wrapper_peer_state_update(struct cdp_soc_t * soc_hdl,uint8_t * peer_mac,enum ol_txrx_peer_state state)5908 static QDF_STATUS ol_txrx_wrapper_peer_state_update(
5909 						struct cdp_soc_t *soc_hdl,
5910 						uint8_t *peer_mac,
5911 						enum ol_txrx_peer_state state)
5912 {
5913 	return ol_txrx_peer_state_update(soc_hdl, peer_mac, state);
5914 }
5915 
5916 /**
5917  * ol_txrx_wrapper_set_flow_control_parameters() - set flow control parameters
5918  * @cfg_ctx: cfg context
5919  * @cfg_param: cfg parameters
5920  *
5921  * Return: none
5922  */
5923 static void
ol_txrx_wrapper_set_flow_control_parameters(struct cdp_cfg * cfg_pdev,void * cfg_param)5924 ol_txrx_wrapper_set_flow_control_parameters(struct cdp_cfg *cfg_pdev,
5925 		void *cfg_param)
5926 {
5927 	return ol_tx_set_flow_control_parameters(
5928 		cfg_pdev,
5929 		(struct txrx_pdev_cfg_param_t *)cfg_param);
5930 }
5931 
5932 /**
5933  * ol_txrx_get_cfg() - get ini/cgf values in legacy dp
5934  * @soc_hdl: soc context
5935  * @cfg_param: cfg parameters
5936  *
5937  * Return: none
5938  */
ol_txrx_get_cfg(struct cdp_soc_t * soc_hdl,enum cdp_dp_cfg cfg)5939 static uint32_t ol_txrx_get_cfg(struct cdp_soc_t *soc_hdl, enum cdp_dp_cfg cfg)
5940 {
5941 	struct txrx_pdev_cfg_t *cfg_ctx;
5942 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
5943 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(
5944 							soc,
5945 							OL_TXRX_PDEV_ID);
5946 	uint32_t value = 0;
5947 
5948 	if (!pdev) {
5949 		qdf_print("pdev is NULL");
5950 		return 0;
5951 	}
5952 
5953 	cfg_ctx = (struct txrx_pdev_cfg_t *)(pdev->ctrl_pdev);
5954 	switch (cfg) {
5955 	case cfg_dp_enable_data_stall:
5956 		value = cfg_ctx->enable_data_stall_detection;
5957 		break;
5958 	case cfg_dp_enable_ip_tcp_udp_checksum_offload:
5959 		value = cfg_ctx->ip_tcp_udp_checksum_offload;
5960 		break;
5961 	case cfg_dp_enable_p2p_ip_tcp_udp_checksum_offload:
5962 		value = cfg_ctx->p2p_ip_tcp_udp_checksum_offload;
5963 		break;
5964 	case cfg_dp_enable_nan_ip_tcp_udp_checksum_offload:
5965 		value = cfg_ctx->nan_tcp_udp_checksumoffload;
5966 		break;
5967 	case cfg_dp_tso_enable:
5968 		value = cfg_ctx->tso_enable;
5969 		break;
5970 	case cfg_dp_lro_enable:
5971 		value = cfg_ctx->lro_enable;
5972 		break;
5973 	case cfg_dp_sg_enable:
5974 		value = cfg_ctx->sg_enable;
5975 		break;
5976 	case cfg_dp_gro_enable:
5977 		value = cfg_ctx->gro_enable;
5978 		break;
5979 #ifdef QCA_LL_TX_FLOW_CONTROL_V2
5980 	case cfg_dp_tx_flow_start_queue_offset:
5981 		value = cfg_ctx->tx_flow_start_queue_offset;
5982 		break;
5983 	case cfg_dp_tx_flow_stop_queue_threshold:
5984 		value = cfg_ctx->tx_flow_stop_queue_th;
5985 		break;
5986 #endif
5987 	case cfg_dp_ipa_uc_tx_buf_size:
5988 		value = cfg_ctx->uc_tx_buffer_size;
5989 		break;
5990 	case cfg_dp_ipa_uc_tx_partition_base:
5991 		value = cfg_ctx->uc_tx_partition_base;
5992 		break;
5993 	case cfg_dp_ipa_uc_rx_ind_ring_count:
5994 		value = cfg_ctx->uc_rx_indication_ring_count;
5995 		break;
5996 	case cfg_dp_enable_flow_steering:
5997 		value = cfg_ctx->enable_flow_steering;
5998 		break;
5999 	case cfg_dp_reorder_offload_supported:
6000 		value = cfg_ctx->is_full_reorder_offload;
6001 		break;
6002 	case cfg_dp_ce_classify_enable:
6003 		value = cfg_ctx->ce_classify_enabled;
6004 		break;
6005 	case cfg_dp_disable_intra_bss_fwd:
6006 		value = cfg_ctx->disable_intra_bss_fwd;
6007 		break;
6008 	case cfg_dp_pktlog_buffer_size:
6009 		value = cfg_ctx->pktlog_buffer_size;
6010 		break;
6011 	default:
6012 		value =  0;
6013 		break;
6014 	}
6015 
6016 	return value;
6017 }
6018 
6019 /*
6020  * ol_get_pdev_param: function to get parameters from pdev
6021  * @cdp_soc: txrx soc handle
6022  * @pdev_id: id of pdev handle
6023  * @param: parameter type to be get
6024  * @val: parameter type to be get
6025  *
6026  * Return: SUCCESS or FAILURE
6027  */
ol_get_pdev_param(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,enum cdp_pdev_param_type param,cdp_config_param_type * val)6028 static QDF_STATUS ol_get_pdev_param(struct cdp_soc_t *soc_hdl,  uint8_t pdev_id,
6029 				    enum cdp_pdev_param_type param,
6030 				    cdp_config_param_type *val)
6031 {
6032 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
6033 	struct ol_txrx_pdev_t *olpdev = ol_txrx_get_pdev_from_pdev_id(soc,
6034 								      pdev_id);
6035 	struct cdp_pdev *pdev = ol_txrx_pdev_t_to_cdp_pdev(olpdev);
6036 
6037 	if (!pdev)
6038 		return QDF_STATUS_E_FAILURE;
6039 
6040 	switch (param) {
6041 	case CDP_TX_PENDING:
6042 		val->cdp_pdev_param_tx_pending = ol_txrx_get_tx_pending(pdev);
6043 		break;
6044 	default:
6045 		return QDF_STATUS_E_INVAL;
6046 	}
6047 
6048 	return QDF_STATUS_SUCCESS;
6049 }
6050 
6051 /*
6052  * ol_set_pdev_param: function to get parameters from pdev
6053  * @cdp_soc: txrx soc handle
6054  * @pdev_id: id of pdev handle
6055  * @param: parameter type to be get
6056  * @val: parameter type to be get
6057  *
6058  * Return: SUCCESS or FAILURE
6059  */
ol_set_pdev_param(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,enum cdp_pdev_param_type param,cdp_config_param_type val)6060 static QDF_STATUS ol_set_pdev_param(struct cdp_soc_t *soc_hdl,  uint8_t pdev_id,
6061 				    enum cdp_pdev_param_type param,
6062 				    cdp_config_param_type val)
6063 {
6064 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
6065 	struct ol_txrx_pdev_t *olpdev = ol_txrx_get_pdev_from_pdev_id(soc,
6066 								      pdev_id);
6067 	struct cdp_pdev *pdev = ol_txrx_pdev_t_to_cdp_pdev(olpdev);
6068 
6069 	if (!pdev)
6070 		return QDF_STATUS_E_FAILURE;
6071 
6072 	switch (param) {
6073 	case CDP_MONITOR_CHANNEL:
6074 	{
6075 		ol_htt_mon_note_chan(pdev, val.cdp_pdev_param_monitor_chan);
6076 		break;
6077 	}
6078 	default:
6079 		return QDF_STATUS_E_INVAL;
6080 	}
6081 
6082 	return QDF_STATUS_SUCCESS;
6083 }
6084 
6085 #ifdef WDI_EVENT_ENABLE
ol_get_pldev(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)6086 void *ol_get_pldev(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
6087 {
6088 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
6089 	struct ol_txrx_pdev_t *pdev = ol_txrx_get_pdev_from_pdev_id(soc,
6090 								    pdev_id);
6091 
6092 	if (pdev)
6093 		return pdev->pl_dev;
6094 
6095 	return NULL;
6096 }
6097 #endif
6098 
6099 /**
6100  * ol_register_packetdump_callback() - registers
6101  *  tx data packet, tx mgmt. packet and rx data packet
6102  *  dump callback handler.
6103  *
6104  * @soc_hdl: Datapath soc handle
6105  * @pdev_id: id of data path pdev handle
6106  * @ol_tx_packetdump_cb: tx packetdump cb
6107  * @ol_rx_packetdump_cb: rx packetdump cb
6108  *
6109  * This function is used to register tx data pkt, tx mgmt.
6110  * pkt and rx data pkt dump callback
6111  *
6112  * Return: None
6113  *
6114  */
6115 static inline
ol_register_packetdump_callback(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,ol_txrx_pktdump_cb ol_tx_packetdump_cb,ol_txrx_pktdump_cb ol_rx_packetdump_cb)6116 void ol_register_packetdump_callback(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
6117 				     ol_txrx_pktdump_cb ol_tx_packetdump_cb,
6118 				     ol_txrx_pktdump_cb ol_rx_packetdump_cb)
6119 {
6120 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
6121 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
6122 
6123 	if (!pdev) {
6124 		ol_txrx_err("pdev is NULL");
6125 		return;
6126 	}
6127 
6128 	pdev->ol_tx_packetdump_cb = ol_tx_packetdump_cb;
6129 	pdev->ol_rx_packetdump_cb = ol_rx_packetdump_cb;
6130 }
6131 
6132 /**
6133  * ol_deregister_packetdump_callback() - deregidters
6134  *  tx data packet, tx mgmt. packet and rx data packet
6135  *  dump callback handler
6136  * @soc_hdl: Datapath soc handle
6137  * @pdev_id: id of data path pdev handle
6138  *
6139  * This function is used to deregidter tx data pkt.,
6140  * tx mgmt. pkt and rx data pkt. dump callback
6141  *
6142  * Return: None
6143  *
6144  */
6145 static inline
ol_deregister_packetdump_callback(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)6146 void ol_deregister_packetdump_callback(struct cdp_soc_t *soc_hdl,
6147 				       uint8_t pdev_id)
6148 {
6149 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
6150 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
6151 
6152 	if (!pdev) {
6153 		ol_txrx_err("pdev is NULL");
6154 		return;
6155 	}
6156 
6157 	pdev->ol_tx_packetdump_cb = NULL;
6158 	pdev->ol_rx_packetdump_cb = NULL;
6159 }
6160 
6161 static struct cdp_cmn_ops ol_ops_cmn = {
6162 	.txrx_soc_attach_target = ol_txrx_soc_attach_target,
6163 	.txrx_vdev_attach = ol_txrx_vdev_attach,
6164 	.txrx_vdev_detach = ol_txrx_vdev_detach,
6165 	.txrx_pdev_attach = ol_txrx_pdev_attach,
6166 	.txrx_pdev_attach_target = ol_txrx_pdev_attach_target,
6167 	.txrx_pdev_post_attach = ol_txrx_pdev_post_attach,
6168 	.txrx_pdev_pre_detach = ol_txrx_pdev_pre_detach,
6169 	.txrx_pdev_detach = ol_txrx_pdev_detach,
6170 	.txrx_peer_create = ol_txrx_peer_attach,
6171 	.txrx_peer_setup = NULL,
6172 	.txrx_peer_teardown = NULL,
6173 	.txrx_peer_delete = ol_txrx_peer_detach,
6174 	.txrx_peer_delete_sync = ol_txrx_peer_detach_sync,
6175 	.txrx_vdev_register = ol_txrx_vdev_register,
6176 	.txrx_soc_detach = ol_txrx_soc_detach,
6177 	.txrx_get_vdev_mac_addr = ol_txrx_get_vdev_mac_addr,
6178 	.txrx_get_ctrl_pdev_from_vdev = ol_txrx_get_ctrl_pdev_from_vdev,
6179 	.txrx_get_mon_vdev_from_pdev = ol_txrx_get_mon_vdev_from_pdev,
6180 	.txrx_mgmt_send_ext = ol_txrx_mgmt_send_ext,
6181 	.txrx_mgmt_tx_cb_set = ol_txrx_mgmt_tx_cb_set,
6182 	.txrx_data_tx_cb_set = ol_txrx_data_tx_cb_set,
6183 	.txrx_peer_unmap_sync_cb_set = ol_txrx_peer_unmap_sync_cb_set,
6184 	.flush_cache_rx_queue = ol_txrx_flush_cache_rx_queue,
6185 	.txrx_fw_stats_get = ol_txrx_fw_stats_get,
6186 	.display_stats = ol_txrx_display_stats,
6187 	.txrx_get_cfg = ol_txrx_get_cfg,
6188 	/* TODO: Add other functions */
6189 };
6190 
6191 static struct cdp_misc_ops ol_ops_misc = {
6192 	.set_ibss_vdev_heart_beat_timer =
6193 		ol_txrx_set_ibss_vdev_heart_beat_timer,
6194 #ifdef CONFIG_HL_SUPPORT
6195 	.set_wmm_param = ol_txrx_set_wmm_param,
6196 #endif /* CONFIG_HL_SUPPORT */
6197 	.bad_peer_txctl_set_setting = ol_txrx_bad_peer_txctl_set_setting,
6198 	.bad_peer_txctl_update_threshold =
6199 		ol_txrx_bad_peer_txctl_update_threshold,
6200 	.hl_tdls_flag_reset = ol_txrx_hl_tdls_flag_reset,
6201 	.tx_non_std = ol_tx_non_std,
6202 	.get_vdev_id = ol_txrx_get_vdev_id,
6203 	.get_tx_ack_stats = ol_txrx_get_tx_ack_stats,
6204 	.set_wisa_mode = ol_txrx_set_wisa_mode,
6205 	.txrx_data_stall_cb_register = ol_register_data_stall_detect_cb,
6206 	.txrx_data_stall_cb_deregister = ol_deregister_data_stall_detect_cb,
6207 	.txrx_post_data_stall_event = ol_txrx_post_data_stall_event,
6208 #ifdef FEATURE_RUNTIME_PM
6209 	.runtime_suspend = ol_txrx_runtime_suspend,
6210 	.runtime_resume = ol_txrx_runtime_resume,
6211 #endif /* FEATURE_RUNTIME_PM */
6212 	.get_opmode = ol_txrx_get_opmode,
6213 	.mark_first_wakeup_packet = ol_tx_mark_first_wakeup_packet,
6214 	.update_mac_id = ol_txrx_update_mac_id,
6215 	.flush_rx_frames = ol_txrx_wrapper_flush_rx_frames,
6216 	.get_intra_bss_fwd_pkts_count = ol_get_intra_bss_fwd_pkts_count,
6217 	.pkt_log_init = htt_pkt_log_init,
6218 	.pkt_log_con_service = ol_txrx_pkt_log_con_service,
6219 	.pkt_log_exit = ol_txrx_pkt_log_exit,
6220 	.register_pktdump_cb = ol_register_packetdump_callback,
6221 	.unregister_pktdump_cb = ol_deregister_packetdump_callback,
6222 #ifdef QCA_SUPPORT_TXRX_DRIVER_TCP_DEL_ACK
6223 	.pdev_reset_driver_del_ack = ol_tx_pdev_reset_driver_del_ack,
6224 	.vdev_set_driver_del_ack_enable = ol_tx_vdev_set_driver_del_ack_enable,
6225 #endif
6226 #ifdef WLAN_SUPPORT_TXRX_HL_BUNDLE
6227 	.vdev_set_bundle_require_flag = ol_tx_vdev_set_bundle_require,
6228 	.pdev_reset_bundle_require_flag = ol_tx_pdev_reset_bundle_require,
6229 #endif
6230 };
6231 
6232 static struct cdp_flowctl_ops ol_ops_flowctl = {
6233 	.register_pause_cb = ol_txrx_register_pause_cb,
6234 #ifdef QCA_LL_TX_FLOW_CONTROL_V2
6235 	.set_desc_global_pool_size = ol_tx_set_desc_global_pool_size,
6236 	.dump_flow_pool_info = ol_tx_dump_flow_pool_info,
6237 	.tx_desc_thresh_reached = ol_tx_desc_thresh_reached,
6238 #endif /* QCA_LL_TX_FLOW_CONTROL_V2 */
6239 };
6240 
6241 #if defined(QCA_LL_LEGACY_TX_FLOW_CONTROL)
6242 static struct cdp_lflowctl_ops ol_ops_l_flowctl = {
6243 	.register_tx_flow_control = ol_txrx_register_tx_flow_control,
6244 	.deregister_tx_flow_control_cb = ol_txrx_deregister_tx_flow_control_cb,
6245 	.flow_control_cb = ol_txrx_flow_control_cb,
6246 	.get_tx_resource = ol_txrx_get_tx_resource,
6247 	.ll_set_tx_pause_q_depth = ol_txrx_ll_set_tx_pause_q_depth,
6248 	.vdev_flush = ol_txrx_vdev_flush,
6249 	.vdev_pause = ol_txrx_vdev_pause,
6250 	.vdev_unpause = ol_txrx_vdev_unpause
6251 }; /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
6252 #elif defined(QCA_HL_NETDEV_FLOW_CONTROL)
6253 static struct cdp_lflowctl_ops ol_ops_l_flowctl = {
6254 	.register_tx_flow_control = ol_txrx_register_hl_flow_control,
6255 	.vdev_flush = ol_txrx_vdev_flush,
6256 	.vdev_pause = ol_txrx_vdev_pause,
6257 	.vdev_unpause = ol_txrx_vdev_unpause,
6258 	.set_vdev_os_queue_status = ol_txrx_set_vdev_os_queue_status,
6259 	.set_vdev_tx_desc_limit = ol_txrx_set_vdev_tx_desc_limit
6260 };
6261 #else /* QCA_HL_NETDEV_FLOW_CONTROL */
6262 static struct cdp_lflowctl_ops ol_ops_l_flowctl = { };
6263 #endif
6264 
6265 #ifdef IPA_OFFLOAD
6266 static struct cdp_ipa_ops ol_ops_ipa = {
6267 	.ipa_get_resource = ol_txrx_ipa_uc_get_resource,
6268 	.ipa_set_doorbell_paddr = ol_txrx_ipa_uc_set_doorbell_paddr,
6269 	.ipa_set_active = ol_txrx_ipa_uc_set_active,
6270 	.ipa_op_response = ol_txrx_ipa_uc_op_response,
6271 	.ipa_register_op_cb = ol_txrx_ipa_uc_register_op_cb,
6272 	.ipa_get_stat = ol_txrx_ipa_uc_get_stat,
6273 	.ipa_tx_data_frame = ol_tx_send_ipa_data_frame,
6274 	.ipa_set_uc_tx_partition_base = ol_cfg_set_ipa_uc_tx_partition_base,
6275 	.ipa_enable_autonomy = ol_txrx_ipa_enable_autonomy,
6276 	.ipa_disable_autonomy = ol_txrx_ipa_disable_autonomy,
6277 	.ipa_setup = ol_txrx_ipa_setup,
6278 	.ipa_cleanup = ol_txrx_ipa_cleanup,
6279 	.ipa_setup_iface = ol_txrx_ipa_setup_iface,
6280 	.ipa_cleanup_iface = ol_txrx_ipa_cleanup_iface,
6281 	.ipa_enable_pipes = ol_txrx_ipa_enable_pipes,
6282 	.ipa_disable_pipes = ol_txrx_ipa_disable_pipes,
6283 	.ipa_set_perf_level = ol_txrx_ipa_set_perf_level,
6284 #ifdef FEATURE_METERING
6285 	.ipa_uc_get_share_stats = ol_txrx_ipa_uc_get_share_stats,
6286 	.ipa_uc_set_quota = ol_txrx_ipa_uc_set_quota,
6287 #endif
6288 	.ipa_tx_buf_smmu_mapping = ol_txrx_ipa_tx_buf_smmu_mapping,
6289 	.ipa_tx_buf_smmu_unmapping = ol_txrx_ipa_tx_buf_smmu_unmapping
6290 };
6291 #endif
6292 
6293 #ifdef RECEIVE_OFFLOAD
6294 static struct cdp_rx_offld_ops ol_rx_offld_ops = {
6295 	.register_rx_offld_flush_cb = ol_register_offld_flush_cb,
6296 	.deregister_rx_offld_flush_cb = ol_deregister_offld_flush_cb
6297 };
6298 #endif
6299 
6300 static struct cdp_bus_ops ol_ops_bus = {
6301 	.bus_suspend = ol_txrx_bus_suspend,
6302 	.bus_resume = ol_txrx_bus_resume
6303 };
6304 
6305 #ifdef WLAN_FEATURE_DSRC
6306 static struct cdp_ocb_ops ol_ops_ocb = {
6307 	.set_ocb_chan_info = ol_txrx_set_ocb_chan_info,
6308 	.get_ocb_chan_info = ol_txrx_get_ocb_chan_info
6309 };
6310 #endif
6311 
6312 static struct cdp_throttle_ops ol_ops_throttle = {
6313 #ifdef QCA_SUPPORT_TX_THROTTLE
6314 	.throttle_init_period = ol_tx_throttle_init_period,
6315 	.throttle_set_level = ol_tx_throttle_set_level
6316 #endif /* QCA_SUPPORT_TX_THROTTLE */
6317 };
6318 
6319 static struct cdp_mob_stats_ops ol_ops_mob_stats = {
6320 	.clear_stats = ol_txrx_clear_stats,
6321 	.stats = ol_txrx_stats
6322 };
6323 
6324 static struct cdp_cfg_ops ol_ops_cfg = {
6325 	.set_cfg_rx_fwd_disabled = ol_set_cfg_rx_fwd_disabled,
6326 	.set_cfg_packet_log_enabled = ol_set_cfg_packet_log_enabled,
6327 	.cfg_attach = ol_pdev_cfg_attach,
6328 	.vdev_rx_set_intrabss_fwd = ol_vdev_rx_set_intrabss_fwd,
6329 	.is_rx_fwd_disabled = ol_txrx_is_rx_fwd_disabled,
6330 	.tx_set_is_mgmt_over_wmi_enabled = ol_tx_set_is_mgmt_over_wmi_enabled,
6331 	.is_high_latency = ol_txrx_wrapper_cfg_is_high_latency,
6332 	.set_flow_control_parameters =
6333 		ol_txrx_wrapper_set_flow_control_parameters,
6334 	.set_flow_steering = ol_set_cfg_flow_steering,
6335 	.set_ptp_rx_opt_enabled = ol_set_cfg_ptp_rx_opt_enabled,
6336 	.set_new_htt_msg_format =
6337 		ol_txrx_set_new_htt_msg_format,
6338 	.set_peer_unmap_conf_support = ol_txrx_set_peer_unmap_conf_support,
6339 	.get_peer_unmap_conf_support = ol_txrx_get_peer_unmap_conf_support,
6340 	.set_tx_compl_tsf64 = ol_txrx_set_tx_compl_tsf64,
6341 	.get_tx_compl_tsf64 = ol_txrx_get_tx_compl_tsf64,
6342 };
6343 
6344 static struct cdp_peer_ops ol_ops_peer = {
6345 	.register_peer = ol_txrx_wrapper_register_peer,
6346 	.clear_peer = ol_txrx_clear_peer,
6347 	.find_peer_exist = ol_txrx_find_peer_exist,
6348 	.find_peer_exist_on_vdev = ol_txrx_find_peer_exist_on_vdev,
6349 	.find_peer_exist_on_other_vdev = ol_txrx_find_peer_exist_on_other_vdev,
6350 	.peer_state_update = ol_txrx_wrapper_peer_state_update,
6351 	.get_vdevid = ol_txrx_get_vdevid,
6352 	.get_vdev_by_peer_addr = ol_txrx_wrapper_get_vdev_by_peer_addr,
6353 	.register_ocb_peer = ol_txrx_register_ocb_peer,
6354 	.peer_get_peer_mac_addr = ol_txrx_peer_get_peer_mac_addr,
6355 	.get_peer_state = ol_txrx_get_peer_state,
6356 	.update_ibss_add_peer_num_of_vdev =
6357 		ol_txrx_update_ibss_add_peer_num_of_vdev,
6358 #if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS)
6359 	.copy_mac_addr_raw = ol_txrx_copy_mac_addr_raw,
6360 	.add_last_real_peer = ol_txrx_add_last_real_peer,
6361 	.is_vdev_restore_last_peer = is_vdev_restore_last_peer,
6362 	.update_last_real_peer = ol_txrx_update_last_real_peer,
6363 	.set_tdls_offchan_enabled = ol_txrx_set_tdls_offchan_enabled,
6364 	.set_peer_as_tdls_peer = ol_txrx_set_peer_as_tdls_peer,
6365 #endif /* CONFIG_HL_SUPPORT */
6366 	.peer_detach_force_delete = ol_txrx_peer_detach_force_delete,
6367 	.peer_flush_frags = ol_txrx_peer_flush_frags,
6368 };
6369 
6370 static struct cdp_tx_delay_ops ol_ops_delay = {
6371 #ifdef QCA_COMPUTE_TX_DELAY
6372 	.tx_delay = ol_tx_delay,
6373 	.tx_delay_hist = ol_tx_delay_hist,
6374 	.tx_packet_count = ol_tx_packet_count,
6375 	.tx_set_compute_interval = ol_tx_set_compute_interval
6376 #endif /* QCA_COMPUTE_TX_DELAY */
6377 };
6378 
6379 static struct cdp_pmf_ops ol_ops_pmf = {
6380 	.get_pn_info = ol_txrx_get_pn_info
6381 };
6382 
6383 static struct cdp_ctrl_ops ol_ops_ctrl = {
6384 	.txrx_get_pldev = ol_get_pldev,
6385 	.txrx_wdi_event_sub = wdi_event_sub,
6386 	.txrx_wdi_event_unsub = wdi_event_unsub,
6387 	.txrx_get_pdev_param = ol_get_pdev_param,
6388 	.txrx_set_pdev_param = ol_set_pdev_param
6389 };
6390 
6391 /* WINplatform specific structures */
6392 static struct cdp_me_ops ol_ops_me = {
6393 	/* EMPTY FOR MCL */
6394 };
6395 
6396 static struct cdp_mon_ops ol_ops_mon = {
6397 	/* EMPTY FOR MCL */
6398 };
6399 
6400 static struct cdp_host_stats_ops ol_ops_host_stats = {
6401 	/* EMPTY FOR MCL */
6402 };
6403 
6404 static struct cdp_wds_ops ol_ops_wds = {
6405 	/* EMPTY FOR MCL */
6406 };
6407 
6408 static struct cdp_raw_ops ol_ops_raw = {
6409 	/* EMPTY FOR MCL */
6410 };
6411 
6412 static struct cdp_ops ol_txrx_ops = {
6413 	.cmn_drv_ops = &ol_ops_cmn,
6414 	.ctrl_ops = &ol_ops_ctrl,
6415 	.me_ops = &ol_ops_me,
6416 	.mon_ops = &ol_ops_mon,
6417 	.host_stats_ops = &ol_ops_host_stats,
6418 	.wds_ops = &ol_ops_wds,
6419 	.raw_ops = &ol_ops_raw,
6420 	.misc_ops = &ol_ops_misc,
6421 	.cfg_ops = &ol_ops_cfg,
6422 	.flowctl_ops = &ol_ops_flowctl,
6423 	.l_flowctl_ops = &ol_ops_l_flowctl,
6424 #ifdef IPA_OFFLOAD
6425 	.ipa_ops = &ol_ops_ipa,
6426 #endif
6427 #ifdef RECEIVE_OFFLOAD
6428 	.rx_offld_ops = &ol_rx_offld_ops,
6429 #endif
6430 	.bus_ops = &ol_ops_bus,
6431 #ifdef WLAN_FEATURE_DSRC
6432 	.ocb_ops = &ol_ops_ocb,
6433 #endif
6434 	.peer_ops = &ol_ops_peer,
6435 	.throttle_ops = &ol_ops_throttle,
6436 	.mob_stats_ops = &ol_ops_mob_stats,
6437 	.delay_ops = &ol_ops_delay,
6438 	.pmf_ops = &ol_ops_pmf,
6439 };
6440 
ol_txrx_soc_attach(void * scn_handle,struct ol_if_ops * dp_ol_if_ops)6441 ol_txrx_soc_handle ol_txrx_soc_attach(void *scn_handle,
6442 				      struct ol_if_ops *dp_ol_if_ops)
6443 {
6444 	struct ol_txrx_soc_t *soc;
6445 
6446 	soc = qdf_mem_malloc(sizeof(*soc));
6447 	if (!soc)
6448 		return NULL;
6449 
6450 	soc->psoc = scn_handle;
6451 	soc->cdp_soc.ops = &ol_txrx_ops;
6452 	soc->cdp_soc.ol_ops = dp_ol_if_ops;
6453 
6454 	return ol_txrx_soc_t_to_cdp_soc_t(soc);
6455 }
6456 
ol_txrx_get_new_htt_msg_format(struct ol_txrx_pdev_t * pdev)6457 bool ol_txrx_get_new_htt_msg_format(struct ol_txrx_pdev_t *pdev)
6458 {
6459 	if (!pdev) {
6460 		qdf_print("%s: pdev is NULL", __func__);
6461 		return false;
6462 	}
6463 	return pdev->new_htt_msg_format;
6464 }
6465 
ol_txrx_set_new_htt_msg_format(uint8_t val)6466 void ol_txrx_set_new_htt_msg_format(uint8_t val)
6467 {
6468 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
6469 	ol_txrx_pdev_handle pdev;
6470 
6471 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
6472 	if (!pdev) {
6473 		qdf_print("%s: pdev is NULL", __func__);
6474 		return;
6475 	}
6476 	pdev->new_htt_msg_format = val;
6477 }
6478 
ol_txrx_get_peer_unmap_conf_support(void)6479 bool ol_txrx_get_peer_unmap_conf_support(void)
6480 {
6481 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
6482 	ol_txrx_pdev_handle pdev;
6483 
6484 	if (qdf_unlikely(!soc))
6485 		return false;
6486 
6487 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
6488 	if (!pdev) {
6489 		qdf_print("%s: pdev is NULL", __func__);
6490 		return false;
6491 	}
6492 	return pdev->enable_peer_unmap_conf_support;
6493 }
6494 
ol_txrx_set_peer_unmap_conf_support(bool val)6495 void ol_txrx_set_peer_unmap_conf_support(bool val)
6496 {
6497 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
6498 	ol_txrx_pdev_handle pdev;
6499 
6500 	if (qdf_unlikely(!soc))
6501 		return;
6502 
6503 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
6504 	if (!pdev) {
6505 		qdf_print("%s: pdev is NULL", __func__);
6506 		return;
6507 	}
6508 	pdev->enable_peer_unmap_conf_support = val;
6509 }
6510 
6511 #ifdef WLAN_FEATURE_TSF_PLUS
ol_txrx_get_tx_compl_tsf64(void)6512 bool ol_txrx_get_tx_compl_tsf64(void)
6513 {
6514 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
6515 	ol_txrx_pdev_handle pdev;
6516 
6517 	if (qdf_unlikely(!soc))
6518 		return false;
6519 
6520 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
6521 	if (!pdev) {
6522 		qdf_print("%s: pdev is NULL", __func__);
6523 		return false;
6524 	}
6525 	return pdev->enable_tx_compl_tsf64;
6526 }
6527 
ol_txrx_set_tx_compl_tsf64(bool val)6528 void ol_txrx_set_tx_compl_tsf64(bool val)
6529 {
6530 	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
6531 	ol_txrx_pdev_handle pdev;
6532 
6533 	if (qdf_unlikely(!soc))
6534 		return;
6535 
6536 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
6537 	if (!pdev) {
6538 		ol_txrx_err("pdev is NULL");
6539 		return;
6540 	}
6541 
6542 	pdev->enable_tx_compl_tsf64 = val;
6543 }
6544 #else
ol_txrx_get_tx_compl_tsf64(void)6545 bool ol_txrx_get_tx_compl_tsf64(void)
6546 {
6547 	return false;
6548 }
6549 
ol_txrx_set_tx_compl_tsf64(bool val)6550 void ol_txrx_set_tx_compl_tsf64(bool val)
6551 {
6552 }
6553 #endif
6554