1  /*
2   * Copyright (c) 2013-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  /**
21   *  DOC:  wma_mgmt.c
22   *
23   *  This file contains STA/SAP and protocol related functions.
24   */
25  
26  /* Header files */
27  
28  #include "wma.h"
29  #include "wma_api.h"
30  #include "cds_api.h"
31  #include "wmi_unified_api.h"
32  #include "wlan_qct_sys.h"
33  #include "wni_api.h"
34  #include "ani_global.h"
35  #include "wmi_unified.h"
36  #include "wni_cfg.h"
37  
38  #include "qdf_nbuf.h"
39  #include "qdf_types.h"
40  #include "qdf_mem.h"
41  
42  #include "wma_types.h"
43  #include "lim_api.h"
44  #include "lim_session_utils.h"
45  
46  #include "cds_utils.h"
47  #include "wlan_dlm_api.h"
48  #if defined(CONNECTIVITY_PKTLOG) || !defined(REMOVE_PKT_LOG)
49  #include "pktlog_ac.h"
50  #else
51  #include "pktlog_ac_fmt.h"
52  #endif /* REMOVE_PKT_LOG */
53  
54  #include "dbglog_host.h"
55  #include "csr_api.h"
56  #include "ol_fw.h"
57  #include "wma_internal.h"
58  #include "wlan_policy_mgr_api.h"
59  #include "cdp_txrx_flow_ctrl_legacy.h"
60  #include <cdp_txrx_peer_ops.h>
61  #include <cdp_txrx_pmf.h>
62  #include <cdp_txrx_cfg.h>
63  #include <cdp_txrx_cmn.h>
64  #include <cdp_txrx_misc.h>
65  #include <cdp_txrx_misc.h>
66  #include "wlan_mgmt_txrx_tgt_api.h"
67  #include "wlan_objmgr_psoc_obj.h"
68  #include "wlan_objmgr_pdev_obj.h"
69  #include "wlan_objmgr_vdev_obj.h"
70  #include "wlan_lmac_if_api.h"
71  #include <cdp_txrx_handle.h>
72  #include "wma_he.h"
73  #include "wma_eht.h"
74  #include <qdf_crypto.h>
75  #include "wma_twt.h"
76  #include "wlan_p2p_cfg_api.h"
77  #include "cfg_ucfg_api.h"
78  #include "cfg_mlme_sta.h"
79  #include "wlan_mlme_api.h"
80  #include "wmi_unified_bcn_api.h"
81  #include <wlan_crypto_global_api.h>
82  #include <wlan_mlme_main.h>
83  #include <../../core/src/vdev_mgr_ops.h>
84  #include "wlan_pkt_capture_ucfg_api.h"
85  
86  #if defined(CONNECTIVITY_PKTLOG) || !defined(REMOVE_PKT_LOG)
87  #include <wlan_logging_sock_svc.h>
88  #endif
89  #include "wlan_cm_roam_api.h"
90  #include "wlan_cm_api.h"
91  #include "wlan_mlo_link_force.h"
92  #include <target_if_spatial_reuse.h>
93  #include "wlan_nan_api_i.h"
94  
95  /* Max debug string size for WMM in bytes */
96  #define WMA_WMM_DEBUG_STRING_SIZE    512
97  
98  /**
99   * wma_send_bcn_buf_ll() - prepare and send beacon buffer to fw for LL
100   * @wma: wma handle
101   * @vdev_id: vdev id
102   * @param_buf: SWBA parameters
103   *
104   * Return: none
105   */
106  #ifdef WLAN_WMI_BCN
wma_send_bcn_buf_ll(tp_wma_handle wma,uint8_t vdev_id,WMI_HOST_SWBA_EVENTID_param_tlvs * param_buf)107  static void wma_send_bcn_buf_ll(tp_wma_handle wma,
108  				uint8_t vdev_id,
109  				WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf)
110  {
111  	struct ieee80211_frame *wh;
112  	struct beacon_info *bcn;
113  	wmi_tim_info *tim_info = param_buf->tim_info;
114  	uint8_t *bcn_payload;
115  	QDF_STATUS ret;
116  	struct beacon_tim_ie *tim_ie;
117  	wmi_p2p_noa_info *p2p_noa_info = param_buf->p2p_noa_info;
118  	struct p2p_sub_element_noa noa_ie;
119  	struct wmi_bcn_send_from_host params;
120  	uint8_t i;
121  
122  	bcn = wma->interfaces[vdev_id].beacon;
123  	if (!bcn || !bcn->buf) {
124  		wma_err("Invalid beacon buffer");
125  		return;
126  	}
127  
128  	if (!param_buf->tim_info || !param_buf->p2p_noa_info) {
129  		wma_err("Invalid tim info or p2p noa info");
130  		return;
131  	}
132  
133  	if (WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info) >
134  			WMI_P2P_MAX_NOA_DESCRIPTORS) {
135  		wma_err("Too many descriptors %d",
136  			WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info));
137  		return;
138  	}
139  
140  	qdf_spin_lock_bh(&bcn->lock);
141  
142  	bcn_payload = qdf_nbuf_data(bcn->buf);
143  
144  	tim_ie = (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]);
145  
146  	if (tim_info->tim_changed) {
147  		if (tim_info->tim_num_ps_pending)
148  			qdf_mem_copy(&tim_ie->tim_bitmap, tim_info->tim_bitmap,
149  				     WMA_TIM_SUPPORTED_PVB_LENGTH);
150  		else
151  			qdf_mem_zero(&tim_ie->tim_bitmap,
152  				     WMA_TIM_SUPPORTED_PVB_LENGTH);
153  		/*
154  		 * Currently we support fixed number of
155  		 * peers as limited by HAL_NUM_STA.
156  		 * tim offset is always 0
157  		 */
158  		tim_ie->tim_bitctl = 0;
159  	}
160  
161  	/* Update DTIM Count */
162  	if (tim_ie->dtim_count == 0)
163  		tim_ie->dtim_count = tim_ie->dtim_period - 1;
164  	else
165  		tim_ie->dtim_count--;
166  
167  	/*
168  	 * DTIM count needs to be backedup so that
169  	 * when umac updates the beacon template
170  	 * current dtim count can be updated properly
171  	 */
172  	bcn->dtim_count = tim_ie->dtim_count;
173  
174  	/* update state for buffered multicast frames on DTIM */
175  	if (tim_info->tim_mcast && (tim_ie->dtim_count == 0 ||
176  				    tim_ie->dtim_period == 1))
177  		tim_ie->tim_bitctl |= 1;
178  	else
179  		tim_ie->tim_bitctl &= ~1;
180  
181  	/* To avoid sw generated frame sequence the same as H/W generated frame,
182  	 * the value lower than min_sw_seq is reserved for HW generated frame
183  	 */
184  	if ((bcn->seq_no & IEEE80211_SEQ_MASK) < MIN_SW_SEQ)
185  		bcn->seq_no = MIN_SW_SEQ;
186  
187  	wh = (struct ieee80211_frame *)bcn_payload;
188  	*(uint16_t *) &wh->i_seq[0] = htole16(bcn->seq_no
189  					      << IEEE80211_SEQ_SEQ_SHIFT);
190  	bcn->seq_no++;
191  
192  	if (WMI_UNIFIED_NOA_ATTR_IS_MODIFIED(p2p_noa_info)) {
193  		qdf_mem_zero(&noa_ie, sizeof(noa_ie));
194  
195  		noa_ie.index =
196  			(uint8_t) WMI_UNIFIED_NOA_ATTR_INDEX_GET(p2p_noa_info);
197  		noa_ie.oppPS =
198  			(uint8_t) WMI_UNIFIED_NOA_ATTR_OPP_PS_GET(p2p_noa_info);
199  		noa_ie.ctwindow =
200  			(uint8_t) WMI_UNIFIED_NOA_ATTR_CTWIN_GET(p2p_noa_info);
201  		noa_ie.num_descriptors = (uint8_t)
202  				WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info);
203  		wma_debug("index %u, oppPs %u, ctwindow %u, num_descriptors = %u",
204  			 noa_ie.index,
205  			 noa_ie.oppPS, noa_ie.ctwindow, noa_ie.num_descriptors);
206  		for (i = 0; i < noa_ie.num_descriptors; i++) {
207  			noa_ie.noa_descriptors[i].type_count =
208  				(uint8_t) p2p_noa_info->noa_descriptors[i].
209  				type_count;
210  			noa_ie.noa_descriptors[i].duration =
211  				p2p_noa_info->noa_descriptors[i].duration;
212  			noa_ie.noa_descriptors[i].interval =
213  				p2p_noa_info->noa_descriptors[i].interval;
214  			noa_ie.noa_descriptors[i].start_time =
215  				p2p_noa_info->noa_descriptors[i].start_time;
216  			wma_debug("NoA descriptor[%d] type_count %u, duration %u, interval %u, start_time = %u",
217  				 i,
218  				 noa_ie.noa_descriptors[i].type_count,
219  				 noa_ie.noa_descriptors[i].duration,
220  				 noa_ie.noa_descriptors[i].interval,
221  				 noa_ie.noa_descriptors[i].start_time);
222  		}
223  		wma_update_noa(bcn, &noa_ie);
224  
225  		/* Send a msg to LIM to update the NoA IE in probe response
226  		 * frames transmitted by the host
227  		 */
228  		wma_update_probe_resp_noa(wma, &noa_ie);
229  	}
230  
231  	if (bcn->dma_mapped) {
232  		qdf_nbuf_unmap_single(wma->qdf_dev, bcn->buf, QDF_DMA_TO_DEVICE);
233  		bcn->dma_mapped = 0;
234  	}
235  	ret = qdf_nbuf_map_single(wma->qdf_dev, bcn->buf, QDF_DMA_TO_DEVICE);
236  	if (ret != QDF_STATUS_SUCCESS) {
237  		wma_err("failed map beacon buf to DMA region");
238  		qdf_spin_unlock_bh(&bcn->lock);
239  		return;
240  	}
241  
242  	bcn->dma_mapped = 1;
243  	params.vdev_id = vdev_id;
244  	params.data_len = bcn->len;
245  	params.frame_ctrl = *((A_UINT16 *) wh->i_fc);
246  	params.frag_ptr = qdf_nbuf_get_frag_paddr(bcn->buf, 0);
247  	params.dtim_flag = 0;
248  	/* notify Firmware of DTM and mcast/bcast traffic */
249  	if (tim_ie->dtim_count == 0) {
250  		params.dtim_flag |= WMI_BCN_SEND_DTIM_ZERO;
251  		/* deliver mcast/bcast traffic in next DTIM beacon */
252  		if (tim_ie->tim_bitctl & 0x01)
253  			params.dtim_flag |= WMI_BCN_SEND_DTIM_BITCTL_SET;
254  	}
255  
256  	wmi_unified_bcn_buf_ll_cmd(wma->wmi_handle,
257  					&params);
258  
259  	qdf_spin_unlock_bh(&bcn->lock);
260  }
261  #else
262  static inline void
wma_send_bcn_buf_ll(tp_wma_handle wma,uint8_t vdev_id,WMI_HOST_SWBA_EVENTID_param_tlvs * param_buf)263  wma_send_bcn_buf_ll(tp_wma_handle wma,
264  		    uint8_t vdev_id,
265  		    WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf)
266  {
267  }
268  #endif
269  /**
270   * wma_beacon_swba_handler() - swba event handler
271   * @handle: wma handle
272   * @event: event data
273   * @len: data length
274   *
275   * SWBA event is alert event to Host requesting host to Queue a beacon
276   * for transmission use only in host beacon mode
277   *
278   * Return: 0 for success or error code
279   */
280  #ifdef WLAN_WMI_BCN
wma_beacon_swba_handler(void * handle,uint8_t * event,uint32_t len)281  int wma_beacon_swba_handler(void *handle, uint8_t *event, uint32_t len)
282  {
283  	tp_wma_handle wma = (tp_wma_handle) handle;
284  	WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf;
285  	wmi_host_swba_event_fixed_param *swba_event;
286  	uint32_t vdev_map;
287  	uint8_t vdev_id = 0;
288  	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
289  
290  	param_buf = (WMI_HOST_SWBA_EVENTID_param_tlvs *) event;
291  	if (!param_buf) {
292  		wma_err("Invalid swba event buffer");
293  		return -EINVAL;
294  	}
295  	swba_event = param_buf->fixed_param;
296  	vdev_map = swba_event->vdev_map;
297  
298  	wma_debug("vdev_map = %d", vdev_map);
299  	for (; vdev_map && vdev_id < wma->max_bssid;
300  			vdev_id++, vdev_map >>= 1) {
301  		if (!(vdev_map & 0x1))
302  			continue;
303  		if (!cdp_cfg_is_high_latency(soc,
304  			(struct cdp_cfg *)cds_get_context(QDF_MODULE_ID_CFG)))
305  			wma_send_bcn_buf_ll(wma, vdev_id, param_buf);
306  		break;
307  	}
308  	return 0;
309  }
310  #else
311  static inline int
wma_beacon_swba_handler(void * handle,uint8_t * event,uint32_t len)312  wma_beacon_swba_handler(void *handle, uint8_t *event, uint32_t len)
313  {
314  	return 0;
315  }
316  #endif
317  
318  #ifdef FEATURE_WLAN_DIAG_SUPPORT
wma_sta_kickout_event(uint32_t kickout_reason,uint8_t vdev_id,uint8_t * macaddr)319  void wma_sta_kickout_event(uint32_t kickout_reason, uint8_t vdev_id,
320  			   uint8_t *macaddr)
321  {
322  	WLAN_HOST_DIAG_EVENT_DEF(sta_kickout, struct host_event_wlan_kickout);
323  	qdf_mem_zero(&sta_kickout, sizeof(sta_kickout));
324  	sta_kickout.reasoncode = kickout_reason;
325  	sta_kickout.vdev_id = vdev_id;
326  	if (macaddr)
327  		qdf_mem_copy(sta_kickout.peer_mac, macaddr,
328  			     QDF_MAC_ADDR_SIZE);
329  	WLAN_HOST_DIAG_EVENT_REPORT(&sta_kickout, EVENT_WLAN_STA_KICKOUT);
330  }
331  #endif
332  
wma_peer_sta_kickout_event_handler(void * handle,uint8_t * event,uint32_t len)333  int wma_peer_sta_kickout_event_handler(void *handle, uint8_t *event,
334  				       uint32_t len)
335  {
336  	tp_wma_handle wma = (tp_wma_handle) handle;
337  	WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *param_buf = NULL;
338  	wmi_peer_sta_kickout_event_fixed_param *kickout_event = NULL;
339  	uint8_t vdev_id, macaddr[QDF_MAC_ADDR_SIZE];
340  	tpDeleteStaContext del_sta_ctx;
341  	uint8_t *addr, *bssid;
342  	struct wlan_objmgr_vdev *vdev;
343  	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
344  
345  	param_buf = (WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *) event;
346  	kickout_event = param_buf->fixed_param;
347  	WMI_MAC_ADDR_TO_CHAR_ARRAY(&kickout_event->peer_macaddr, macaddr);
348  	if (cdp_peer_get_vdevid(soc, macaddr, &vdev_id) !=
349  			QDF_STATUS_SUCCESS) {
350  		wma_err("Not able to find BSSID for peer ["QDF_MAC_ADDR_FMT"]",
351  			 QDF_MAC_ADDR_REF(macaddr));
352  		return -EINVAL;
353  	}
354  
355  	if (!wma_is_vdev_valid(vdev_id))
356  		return -EINVAL;
357  
358  	vdev = wma->interfaces[vdev_id].vdev;
359  	if (!vdev) {
360  		wma_err("Not able to find vdev for VDEV_%d", vdev_id);
361  		return -EINVAL;
362  	}
363  	addr = wlan_vdev_mlme_get_macaddr(vdev);
364  
365  	wma_nofl_info("STA kickout for "QDF_MAC_ADDR_FMT", on mac "QDF_MAC_ADDR_FMT", vdev %d, reason:%d",
366  		      QDF_MAC_ADDR_REF(macaddr), QDF_MAC_ADDR_REF(addr),
367  		      vdev_id, kickout_event->reason);
368  
369  	if (wma_is_roam_in_progress(vdev_id)) {
370  		wma_err("vdev_id %d: Ignore STA kick out since roaming is in progress",
371  			vdev_id);
372  		return -EINVAL;
373  	}
374  	bssid = wma_get_vdev_bssid(vdev);
375  	if (!bssid) {
376  		wma_err("Failed to get bssid for vdev_%d", vdev_id);
377  		return -ENOMEM;
378  	}
379  
380  	switch (kickout_event->reason) {
381  	case WMI_PEER_STA_KICKOUT_REASON_IBSS_DISCONNECT:
382  		goto exit_handler;
383  #ifdef FEATURE_WLAN_TDLS
384  	case WMI_PEER_STA_KICKOUT_REASON_TDLS_DISCONNECT:
385  		del_sta_ctx = (tpDeleteStaContext)
386  			qdf_mem_malloc(sizeof(tDeleteStaContext));
387  		if (!del_sta_ctx) {
388  			wma_err("mem alloc failed for struct del_sta_context for TDLS peer: "QDF_MAC_ADDR_FMT,
389  				QDF_MAC_ADDR_REF(macaddr));
390  			return -ENOMEM;
391  		}
392  
393  		del_sta_ctx->is_tdls = true;
394  		del_sta_ctx->vdev_id = vdev_id;
395  		qdf_mem_copy(del_sta_ctx->addr2, macaddr, QDF_MAC_ADDR_SIZE);
396  		qdf_mem_copy(del_sta_ctx->bssId, bssid,
397  			     QDF_MAC_ADDR_SIZE);
398  		del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
399  		wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND,
400  			     (void *)del_sta_ctx, 0);
401  		goto exit_handler;
402  #endif /* FEATURE_WLAN_TDLS */
403  
404  	case WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED:
405  		/*
406  		 * Default legacy value used by original firmware implementation
407  		 */
408  		if (wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA &&
409  		    (wma->interfaces[vdev_id].sub_type == 0 ||
410  		     wma->interfaces[vdev_id].sub_type ==
411  		     WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) &&
412  		    !qdf_mem_cmp(bssid,
413  				    macaddr, QDF_MAC_ADDR_SIZE)) {
414  			wma_sta_kickout_event(
415  			HOST_STA_KICKOUT_REASON_UNSPECIFIED, vdev_id, macaddr);
416  			/*
417  			 * KICKOUT event is for current station-AP connection.
418  			 * Treat it like final beacon miss. Station may not have
419  			 * missed beacons but not able to transmit frames to AP
420  			 * for a long time. Must disconnect to get out of
421  			 * this sticky situation.
422  			 * In future implementation, roaming module will also
423  			 * handle this event and perform a scan.
424  			 */
425  			wma_warn("WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED event for STA");
426  			wma_beacon_miss_handler(wma, vdev_id,
427  						kickout_event->rssi);
428  			goto exit_handler;
429  		}
430  		break;
431  
432  	case WMI_PEER_STA_KICKOUT_REASON_XRETRY:
433  	case WMI_PEER_STA_KICKOUT_REASON_INACTIVITY:
434  	/*
435  	 * Handle SA query kickout is same as inactivity kickout.
436  	 * This could be for STA or SAP role
437  	 */
438  	case WMI_PEER_STA_KICKOUT_REASON_SA_QUERY_TIMEOUT:
439  	default:
440  		break;
441  	}
442  
443  	/*
444  	 * default action is to send delete station context indication to LIM
445  	 */
446  	del_sta_ctx =
447  		(tDeleteStaContext *) qdf_mem_malloc(sizeof(tDeleteStaContext));
448  	if (!del_sta_ctx) {
449  		wma_err("QDF MEM Alloc Failed for struct del_sta_context");
450  		return -ENOMEM;
451  	}
452  
453  	del_sta_ctx->is_tdls = false;
454  	del_sta_ctx->vdev_id = vdev_id;
455  	qdf_mem_copy(del_sta_ctx->addr2, macaddr, QDF_MAC_ADDR_SIZE);
456  	qdf_mem_copy(del_sta_ctx->bssId, addr, QDF_MAC_ADDR_SIZE);
457  	if (kickout_event->reason ==
458  		WMI_PEER_STA_KICKOUT_REASON_SA_QUERY_TIMEOUT)
459  		del_sta_ctx->reasonCode =
460  			HAL_DEL_STA_REASON_CODE_SA_QUERY_TIMEOUT;
461  	else if (kickout_event->reason == WMI_PEER_STA_KICKOUT_REASON_XRETRY)
462  		del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_XRETRY;
463  	else
464  		del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
465  
466  	if (wmi_service_enabled(wma->wmi_handle,
467  				wmi_service_hw_db2dbm_support))
468  		del_sta_ctx->rssi = kickout_event->rssi;
469  	else
470  		del_sta_ctx->rssi = kickout_event->rssi +
471  					WMA_TGT_NOISE_FLOOR_DBM;
472  	wma_sta_kickout_event(del_sta_ctx->reasonCode, vdev_id, macaddr);
473  	wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND, (void *)del_sta_ctx,
474  		     0);
475  	wma_lost_link_info_handler(wma, vdev_id, del_sta_ctx->rssi);
476  
477  exit_handler:
478  	return 0;
479  }
480  
wma_unified_bcntx_status_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)481  int wma_unified_bcntx_status_event_handler(void *handle,
482  					   uint8_t *cmd_param_info,
483  					   uint32_t len)
484  {
485  	tp_wma_handle wma = (tp_wma_handle) handle;
486  	WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *param_buf;
487  	wmi_offload_bcn_tx_status_event_fixed_param *resp_event;
488  	tSirFirstBeaconTxCompleteInd *beacon_tx_complete_ind;
489  
490  	param_buf =
491  		(WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *) cmd_param_info;
492  	if (!param_buf) {
493  		wma_err("Invalid bcn tx response event buffer");
494  		return -EINVAL;
495  	}
496  
497  	resp_event = param_buf->fixed_param;
498  
499  	if (resp_event->vdev_id >= wma->max_bssid) {
500  		wma_err("received invalid vdev_id %d", resp_event->vdev_id);
501  		return -EINVAL;
502  	}
503  
504  	/* Check for valid handle to ensure session is not
505  	 * deleted in any race
506  	 */
507  	if (!wma->interfaces[resp_event->vdev_id].vdev) {
508  		wma_err("vdev is NULL for vdev_%d", resp_event->vdev_id);
509  		return -EINVAL;
510  	}
511  
512  	/* Beacon Tx Indication supports only AP mode. Ignore in other modes */
513  	if (wma_is_vdev_in_ap_mode(wma, resp_event->vdev_id) == false) {
514  		wma_debug("Beacon Tx Indication does not support type %d and sub_type %d",
515  			 wma->interfaces[resp_event->vdev_id].type,
516  			 wma->interfaces[resp_event->vdev_id].sub_type);
517  		return 0;
518  	}
519  
520  	beacon_tx_complete_ind = (tSirFirstBeaconTxCompleteInd *)
521  			qdf_mem_malloc(sizeof(tSirFirstBeaconTxCompleteInd));
522  	if (!beacon_tx_complete_ind) {
523  		wma_err("Failed to alloc beacon_tx_complete_ind");
524  		return -ENOMEM;
525  	}
526  
527  	beacon_tx_complete_ind->messageType = WMA_DFS_BEACON_TX_SUCCESS_IND;
528  	beacon_tx_complete_ind->length = sizeof(tSirFirstBeaconTxCompleteInd);
529  	beacon_tx_complete_ind->bss_idx = resp_event->vdev_id;
530  
531  	wma_send_msg(wma, WMA_DFS_BEACON_TX_SUCCESS_IND,
532  		     (void *)beacon_tx_complete_ind, 0);
533  	return 0;
534  }
535  
536  /**
537   * wma_get_go_probe_timeout() - get P2P GO probe timeout
538   * @mac: UMAC handler
539   * @max_inactive_time: return max inactive time
540   * @max_unresponsive_time: return max unresponsive time
541   *
542   * Return: none
543   */
544  #ifdef CONVERGED_P2P_ENABLE
545  static inline void
wma_get_go_probe_timeout(struct mac_context * mac,uint32_t * max_inactive_time,uint32_t * max_unresponsive_time)546  wma_get_go_probe_timeout(struct mac_context *mac,
547  			 uint32_t *max_inactive_time,
548  			 uint32_t *max_unresponsive_time)
549  {
550  	uint32_t keep_alive;
551  	QDF_STATUS status;
552  
553  	status = cfg_p2p_get_go_link_monitor_period(mac->psoc,
554  						    max_inactive_time);
555  	if (QDF_IS_STATUS_ERROR(status)) {
556  		wma_err("Failed to go monitor period");
557  		*max_inactive_time = WMA_LINK_MONITOR_DEFAULT_TIME_SECS;
558  	}
559  	status = cfg_p2p_get_go_keepalive_period(mac->psoc,
560  						 &keep_alive);
561  	if (QDF_IS_STATUS_ERROR(status)) {
562  		wma_err("Failed to read go keep alive");
563  		keep_alive = WMA_KEEP_ALIVE_DEFAULT_TIME_SECS;
564  	}
565  
566  	*max_unresponsive_time = *max_inactive_time + keep_alive;
567  }
568  #else
569  static inline void
wma_get_go_probe_timeout(struct mac_context * mac,uint32_t * max_inactive_time,uint32_t * max_unresponsive_time)570  wma_get_go_probe_timeout(struct mac_context *mac,
571  			 uint32_t *max_inactive_time,
572  			 uint32_t *max_unresponsive_time)
573  {
574  }
575  #endif
576  
577  /**
578   * wma_get_link_probe_timeout() - get link timeout based on sub type
579   * @mac: UMAC handler
580   * @sub_type: vdev syb type
581   * @max_inactive_time: return max inactive time
582   * @max_unresponsive_time: return max unresponsive time
583   *
584   * Return: none
585   */
586  static inline void
wma_get_link_probe_timeout(struct mac_context * mac,uint32_t sub_type,uint32_t * max_inactive_time,uint32_t * max_unresponsive_time)587  wma_get_link_probe_timeout(struct mac_context *mac,
588  			   uint32_t sub_type,
589  			   uint32_t *max_inactive_time,
590  			   uint32_t *max_unresponsive_time)
591  {
592  	if (sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO) {
593  		wma_get_go_probe_timeout(mac, max_inactive_time,
594  					 max_unresponsive_time);
595  	} else {
596  		*max_inactive_time =
597  			mac->mlme_cfg->timeouts.ap_link_monitor_timeout;
598  		*max_unresponsive_time = *max_inactive_time +
599  			mac->mlme_cfg->timeouts.ap_keep_alive_timeout;
600  	}
601  }
602  
603  /**
604   * wma_verify_rate_code() - verify if rate code is valid.
605   * @rate_code:     rate code
606   * @band:     band information
607   *
608   * Return: verify result
609   */
wma_verify_rate_code(u_int32_t rate_code,enum cds_band_type band)610  static bool wma_verify_rate_code(u_int32_t rate_code, enum cds_band_type band)
611  {
612  	uint8_t preamble, nss, rate;
613  	bool valid = true;
614  
615  	preamble = (rate_code & 0xc0) >> 6;
616  	nss = (rate_code & 0x30) >> 4;
617  	rate = rate_code & 0xf;
618  
619  	switch (preamble) {
620  	case WMI_RATE_PREAMBLE_CCK:
621  		if (nss != 0 || rate > 3 || band == CDS_BAND_5GHZ)
622  			valid = false;
623  		break;
624  	case WMI_RATE_PREAMBLE_OFDM:
625  		if (nss != 0 || rate > 7)
626  			valid = false;
627  		break;
628  	case WMI_RATE_PREAMBLE_HT:
629  		if (nss != 0 || rate > 7)
630  			valid = false;
631  		break;
632  	case WMI_RATE_PREAMBLE_VHT:
633  		if (nss != 0 || rate > 9)
634  			valid = false;
635  		break;
636  	default:
637  		break;
638  	}
639  	return valid;
640  }
641  
642  #define TX_MGMT_RATE_2G_ENABLE_OFFSET 30
643  #define TX_MGMT_RATE_5G_ENABLE_OFFSET 31
644  #define TX_MGMT_RATE_2G_OFFSET 0
645  #define TX_MGMT_RATE_5G_OFFSET 12
646  
647  #define MAX_VDEV_MGMT_RATE_PARAMS 2
648  /* params being sent:
649   * wmi_vdev_param_mgmt_tx_rate
650   * wmi_vdev_param_per_band_mgmt_tx_rate
651   */
652  
653  /**
654   * wma_set_mgmt_rate() - set vdev mgmt rate.
655   * @wma:     wma handle
656   * @vdev_id: vdev id
657   *
658   * Return: None
659   */
wma_set_vdev_mgmt_rate(tp_wma_handle wma,uint8_t vdev_id)660  void wma_set_vdev_mgmt_rate(tp_wma_handle wma, uint8_t vdev_id)
661  {
662  	uint32_t cfg_val;
663  	uint32_t per_band_mgmt_tx_rate = 0;
664  	enum cds_band_type band = 0;
665  	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
666  	struct dev_set_param setparam[MAX_VDEV_MGMT_RATE_PARAMS] = {};
667  	uint8_t index = 0;
668  	QDF_STATUS status = QDF_STATUS_E_FAILURE;
669  
670  	if (!mac) {
671  		wma_err("Failed to get mac");
672  		return;
673  	}
674  
675  	cfg_val = mac->mlme_cfg->sap_cfg.rate_tx_mgmt;
676  	band = CDS_BAND_ALL;
677  	if ((cfg_val == MLME_CFG_TX_MGMT_RATE_DEF) ||
678  	    !wma_verify_rate_code(cfg_val, band)) {
679  		wma_nofl_debug("default WNI_CFG_RATE_FOR_TX_MGMT, ignore");
680  	} else {
681  		status = mlme_check_index_setparam(setparam,
682  						   wmi_vdev_param_mgmt_tx_rate,
683  						   cfg_val, index++,
684  						   MAX_VDEV_MGMT_RATE_PARAMS);
685  		if (QDF_IS_STATUS_ERROR(status)) {
686  			wma_err("failed at wmi_vdev_param_mgmt_tx_rate");
687  			goto error;
688  		}
689  	}
690  
691  	cfg_val = mac->mlme_cfg->sap_cfg.rate_tx_mgmt_2g;
692  	band = CDS_BAND_2GHZ;
693  	if ((cfg_val == MLME_CFG_TX_MGMT_2G_RATE_DEF) ||
694  	    !wma_verify_rate_code(cfg_val, band)) {
695  		wma_nofl_debug("use default 2G MGMT rate.");
696  		per_band_mgmt_tx_rate &=
697  		    ~(1 << TX_MGMT_RATE_2G_ENABLE_OFFSET);
698  	} else {
699  		per_band_mgmt_tx_rate |=
700  		    (1 << TX_MGMT_RATE_2G_ENABLE_OFFSET);
701  		per_band_mgmt_tx_rate |=
702  		    ((cfg_val & 0x7FF) << TX_MGMT_RATE_2G_OFFSET);
703  	}
704  
705  	cfg_val = mac->mlme_cfg->sap_cfg.rate_tx_mgmt;
706  	band = CDS_BAND_5GHZ;
707  	if ((cfg_val == MLME_CFG_TX_MGMT_5G_RATE_DEF) ||
708  	    !wma_verify_rate_code(cfg_val, band)) {
709  		wma_nofl_debug("use default 5G MGMT rate.");
710  		per_band_mgmt_tx_rate &=
711  		    ~(1 << TX_MGMT_RATE_5G_ENABLE_OFFSET);
712  	} else {
713  		per_band_mgmt_tx_rate |=
714  		    (1 << TX_MGMT_RATE_5G_ENABLE_OFFSET);
715  		per_band_mgmt_tx_rate |=
716  		    ((cfg_val & 0x7FF) << TX_MGMT_RATE_5G_OFFSET);
717  	}
718  
719  	status = mlme_check_index_setparam(setparam,
720  					   wmi_vdev_param_per_band_mgmt_tx_rate,
721  					   per_band_mgmt_tx_rate, index++,
722  					   MAX_VDEV_MGMT_RATE_PARAMS);
723  	if (QDF_IS_STATUS_ERROR(status)) {
724  		wma_err("failed at wmi_vdev_param_per_band_mgmt_tx_rate");
725  		goto error;
726  	}
727  
728  	status = wma_send_multi_pdev_vdev_set_params(MLME_VDEV_SETPARAM,
729  						     vdev_id, setparam, index);
730  	if (QDF_IS_STATUS_ERROR(status))
731  		wma_debug("failed to send MGMT_TX_RATE vdev set params stat:%d",
732  			  status);
733  error:
734  	return;
735  }
736  
737  #define MAX_VDEV_SAP_KEEPALIVE_PARAMS 3
738  /* params being sent:
739   * wmi_vdev_param_ap_keepalive_min_idle_inactive_time_secs
740   * wmi_vdev_param_ap_keepalive_max_idle_inactive_time_secs
741   * wmi_vdev_param_ap_keepalive_max_unresponsive_time_secs
742   */
743  
744  /**
745   * wma_set_sap_keepalive() - set SAP keep alive parameters to fw
746   * @wma: wma handle
747   * @vdev_id: vdev id
748   *
749   * Return: none
750   */
wma_set_sap_keepalive(tp_wma_handle wma,uint8_t vdev_id)751  void wma_set_sap_keepalive(tp_wma_handle wma, uint8_t vdev_id)
752  {
753  	uint32_t min_inactive_time, max_inactive_time, max_unresponsive_time;
754  	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
755  	QDF_STATUS status;
756  	struct dev_set_param setparam[MAX_VDEV_SAP_KEEPALIVE_PARAMS] = {};
757  	uint8_t index = 0;
758  
759  	if (!mac) {
760  		wma_err("Failed to get mac");
761  		return;
762  	}
763  
764  	wma_get_link_probe_timeout(mac, wma->interfaces[vdev_id].sub_type,
765  				   &max_inactive_time, &max_unresponsive_time);
766  
767  	min_inactive_time = max_inactive_time / 2;
768  	status = mlme_check_index_setparam(
769  			setparam,
770  			wmi_vdev_param_ap_keepalive_min_idle_inactive_time_secs,
771  			min_inactive_time, index++,
772  			MAX_VDEV_SAP_KEEPALIVE_PARAMS);
773  	if (QDF_IS_STATUS_ERROR(status)) {
774  		wma_err("failed to set wmi_vdev_param_ap_keepalive_min_idle_inactive_time_secs");
775  		goto error;
776  	}
777  	status = mlme_check_index_setparam(
778  			setparam,
779  			wmi_vdev_param_ap_keepalive_max_idle_inactive_time_secs,
780  			max_inactive_time, index++,
781  			MAX_VDEV_SAP_KEEPALIVE_PARAMS);
782  	if (QDF_IS_STATUS_ERROR(status)) {
783  		wma_err("failed to set wmi_vdev_param_ap_keepalive_max_idle_inactive_time_secs");
784  		goto error;
785  	}
786  	status = mlme_check_index_setparam(
787  			setparam,
788  			wmi_vdev_param_ap_keepalive_max_unresponsive_time_secs,
789  			max_unresponsive_time, index++,
790  			MAX_VDEV_SAP_KEEPALIVE_PARAMS);
791  	if (QDF_IS_STATUS_ERROR(status)) {
792  		wma_err("failed to set wmi_vdev_param_ap_keepalive_max_unresponsive_time_secs");
793  		goto error;
794  	}
795  
796  	status = wma_send_multi_pdev_vdev_set_params(MLME_VDEV_SETPARAM,
797  						     vdev_id, setparam, index);
798  	if (QDF_IS_STATUS_ERROR(status))
799  		wma_err("Failed to Set AP MIN/MAX IDLE INACTIVE TIME, MAX UNRESPONSIVE TIME:%d", status);
800  	else
801  		wma_debug("vdev_id:%d min_inactive_time: %u max_inactive_time: %u max_unresponsive_time: %u",
802  			  vdev_id, min_inactive_time, max_inactive_time,
803  			  max_unresponsive_time);
804  error:
805  	return;
806  }
807  
808  /**
809   * wma_set_sta_sa_query_param() - set sta sa query parameters
810   * @wma: wma handle
811   * @vdev_id: vdev id
812  
813   * This function sets sta query related parameters in fw.
814   *
815   * Return: none
816   */
817  
wma_set_sta_sa_query_param(tp_wma_handle wma,uint8_t vdev_id)818  void wma_set_sta_sa_query_param(tp_wma_handle wma,
819  				  uint8_t vdev_id)
820  {
821  	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
822  	uint8_t max_retries;
823  	uint16_t retry_interval;
824  
825  	if (!mac) {
826  		wma_err("mac context is NULL");
827  		return;
828  	}
829  
830  	max_retries = mac->mlme_cfg->gen.pmf_sa_query_max_retries;
831  	retry_interval = mac->mlme_cfg->gen.pmf_sa_query_retry_interval;
832  
833  	wmi_unified_set_sta_sa_query_param_cmd(wma->wmi_handle,
834  						vdev_id,
835  						max_retries,
836  						retry_interval);
837  }
838  
839  /**
840   * wma_set_sta_keep_alive() - set sta keep alive parameters
841   * @wma: wma handle
842   * @vdev_id: vdev id
843   * @method: method for keep alive
844   * @timeperiod: time period
845   * @hostv4addr: host ipv4 address
846   * @destv4addr: dst ipv4 address
847   * @destmac: destination mac
848   *
849   * This function sets keep alive related parameters in fw.
850   *
851   * Return: none
852   */
wma_set_sta_keep_alive(tp_wma_handle wma,uint8_t vdev_id,uint32_t method,uint32_t timeperiod,uint8_t * hostv4addr,uint8_t * destv4addr,uint8_t * destmac)853  void wma_set_sta_keep_alive(tp_wma_handle wma, uint8_t vdev_id,
854  			    uint32_t method, uint32_t timeperiod,
855  			    uint8_t *hostv4addr, uint8_t *destv4addr,
856  			    uint8_t *destmac)
857  {
858  	struct sta_keep_alive_params params = { 0 };
859  	struct wma_txrx_node *intr;
860  
861  	if (wma_validate_handle(wma))
862  		return;
863  
864  	intr = &wma->interfaces[vdev_id];
865  	if (timeperiod > cfg_max(CFG_INFRA_STA_KEEP_ALIVE_PERIOD)) {
866  		wmi_err("Invalid period %d Max limit %d", timeperiod,
867  			 cfg_max(CFG_INFRA_STA_KEEP_ALIVE_PERIOD));
868  		return;
869  	}
870  
871  	params.vdev_id = vdev_id;
872  	params.method = method;
873  	params.timeperiod = timeperiod;
874  	if (intr) {
875  		if (intr->bss_max_idle_period) {
876  			if (intr->bss_max_idle_period < timeperiod)
877  				params.timeperiod = intr->bss_max_idle_period;
878  
879  			if (method == WMI_KEEP_ALIVE_NULL_PKT)
880  				params.method = WMI_KEEP_ALIVE_MGMT_FRAME;
881  		}
882  
883  		wlan_mlme_set_keepalive_period(intr->vdev, params.timeperiod);
884  	}
885  
886  	if (hostv4addr)
887  		qdf_mem_copy(params.hostv4addr, hostv4addr, QDF_IPV4_ADDR_SIZE);
888  	if (destv4addr)
889  		qdf_mem_copy(params.destv4addr, destv4addr, QDF_IPV4_ADDR_SIZE);
890  	if (destmac)
891  		qdf_mem_copy(params.destmac, destmac, QDF_MAC_ADDR_SIZE);
892  
893  	wmi_unified_set_sta_keep_alive_cmd(wma->wmi_handle, &params);
894  }
895  
896  /*
897   * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
898   *   0 for no restriction
899   *   1 for 1/4 us - Our lower layer calculations limit our precision to 1 msec
900   *   2 for 1/2 us - Our lower layer calculations limit our precision to 1 msec
901   *   3 for 1 us
902   *   4 for 2 us
903   *   5 for 4 us
904   *   6 for 8 us
905   *   7 for 16 us
906   */
907  static const uint8_t wma_mpdu_spacing[] = { 0, 1, 1, 1, 2, 4, 8, 16 };
908  
909  /**
910   * wma_parse_mpdudensity() - give mpdu spacing from mpdu density
911   * @mpdudensity: mpdu density
912   *
913   * Return: mpdu spacing or 0 for error
914   */
wma_parse_mpdudensity(uint8_t mpdudensity)915  static inline uint8_t wma_parse_mpdudensity(uint8_t mpdudensity)
916  {
917  	if (mpdudensity < sizeof(wma_mpdu_spacing))
918  		return wma_mpdu_spacing[mpdudensity];
919  	else
920  		return 0;
921  }
922  
923  #define CFG_CTRL_MASK              0xFF00
924  #define CFG_DATA_MASK              0x00FF
925  
926  /**
927   * wma_mask_tx_ht_rate() - mask tx ht rate based on config
928   * @wma:     wma handle
929   * @mcs_set  mcs set buffer
930   *
931   * Return: None
932   */
wma_mask_tx_ht_rate(tp_wma_handle wma,uint8_t * mcs_set)933  static void wma_mask_tx_ht_rate(tp_wma_handle wma, uint8_t *mcs_set)
934  {
935  	uint32_t i, j;
936  	uint16_t mcs_limit;
937  	uint8_t *rate_pos = mcs_set;
938  	struct mac_context *mac = wma->mac_context;
939  
940  	/*
941  	 * Get MCS limit from ini configure, and map it to rate parameters
942  	 * This will limit HT rate upper bound. CFG_CTRL_MASK is used to
943  	 * check whether ini config is enabled and CFG_DATA_MASK to get the
944  	 * MCS value.
945  	 */
946  	mcs_limit = mac->mlme_cfg->rates.max_htmcs_txdata;
947  
948  	if (mcs_limit & CFG_CTRL_MASK) {
949  		wma_debug("set mcs_limit %x", mcs_limit);
950  
951  		mcs_limit &= CFG_DATA_MASK;
952  		for (i = 0, j = 0; i < MAX_SUPPORTED_RATES;) {
953  			if (j < mcs_limit / 8) {
954  				rate_pos[j] = 0xff;
955  				j++;
956  				i += 8;
957  			} else if (j < mcs_limit / 8 + 1) {
958  				if (i <= mcs_limit)
959  					rate_pos[i / 8] |= 1 << (i % 8);
960  				else
961  					rate_pos[i / 8] &= ~(1 << (i % 8));
962  				i++;
963  
964  				if (i >= (j + 1) * 8)
965  					j++;
966  			} else {
967  				rate_pos[j++] = 0;
968  				i += 8;
969  			}
970  		}
971  	}
972  }
973  
974  #if SUPPORT_11AX
975  /**
976   * wma_fw_to_host_phymode_11ax() - convert fw to host phymode for 11ax phymodes
977   * @phymode: phymode to convert
978   *
979   * Return: one of the 11ax values defined in enum wlan_phymode;
980   *         or WLAN_PHYMODE_AUTO if the input is not an 11ax phymode
981   */
982  static enum wlan_phymode
wma_fw_to_host_phymode_11ax(WMI_HOST_WLAN_PHY_MODE phymode)983  wma_fw_to_host_phymode_11ax(WMI_HOST_WLAN_PHY_MODE phymode)
984  {
985  	switch (phymode) {
986  	default:
987  		return WLAN_PHYMODE_AUTO;
988  	case WMI_HOST_MODE_11AX_HE20:
989  		return WLAN_PHYMODE_11AXA_HE20;
990  	case WMI_HOST_MODE_11AX_HE40:
991  		return WLAN_PHYMODE_11AXA_HE40;
992  	case WMI_HOST_MODE_11AX_HE80:
993  		return WLAN_PHYMODE_11AXA_HE80;
994  	case WMI_HOST_MODE_11AX_HE80_80:
995  		return WLAN_PHYMODE_11AXA_HE80_80;
996  	case WMI_HOST_MODE_11AX_HE160:
997  		return WLAN_PHYMODE_11AXA_HE160;
998  	case WMI_HOST_MODE_11AX_HE20_2G:
999  		return WLAN_PHYMODE_11AXG_HE20;
1000  	case WMI_HOST_MODE_11AX_HE40_2G:
1001  		return WLAN_PHYMODE_11AXG_HE40;
1002  	case WMI_HOST_MODE_11AX_HE80_2G:
1003  		return WLAN_PHYMODE_11AXG_HE80;
1004  	}
1005  	return WLAN_PHYMODE_AUTO;
1006  }
1007  #else
1008  static enum wlan_phymode
wma_fw_to_host_phymode_11ax(WMI_HOST_WLAN_PHY_MODE phymode)1009  wma_fw_to_host_phymode_11ax(WMI_HOST_WLAN_PHY_MODE phymode)
1010  {
1011  	return WLAN_PHYMODE_AUTO;
1012  }
1013  #endif
1014  
1015  #ifdef WLAN_FEATURE_11BE
1016  /**
1017   * wma_fw_to_host_phymode_11be() - convert fw to host phymode for 11be phymodes
1018   * @phymode: phymode to convert
1019   *
1020   * Return: one of the 11be values defined in enum wlan_phymode;
1021   *         or WLAN_PHYMODE_AUTO if the input is not an 11be phymode
1022   */
1023  static enum wlan_phymode
wma_fw_to_host_phymode_11be(WMI_HOST_WLAN_PHY_MODE phymode)1024  wma_fw_to_host_phymode_11be(WMI_HOST_WLAN_PHY_MODE phymode)
1025  {
1026  	switch (phymode) {
1027  	default:
1028  		return WLAN_PHYMODE_AUTO;
1029  	case WMI_HOST_MODE_11BE_EHT20:
1030  		return WLAN_PHYMODE_11BEA_EHT20;
1031  	case WMI_HOST_MODE_11BE_EHT40:
1032  		return WLAN_PHYMODE_11BEA_EHT40;
1033  	case WMI_HOST_MODE_11BE_EHT80:
1034  		return WLAN_PHYMODE_11BEA_EHT80;
1035  	case WMI_HOST_MODE_11BE_EHT160:
1036  		return WLAN_PHYMODE_11BEA_EHT160;
1037  	case WMI_HOST_MODE_11BE_EHT320:
1038  		return WLAN_PHYMODE_11BEA_EHT320;
1039  	case WMI_HOST_MODE_11BE_EHT20_2G:
1040  		return WLAN_PHYMODE_11BEG_EHT20;
1041  	case WMI_HOST_MODE_11BE_EHT40_2G:
1042  		return WLAN_PHYMODE_11BEG_EHT40;
1043  	}
1044  	return WLAN_PHYMODE_AUTO;
1045  }
1046  
wma_is_phymode_eht(enum wlan_phymode phymode)1047  static inline bool wma_is_phymode_eht(enum wlan_phymode phymode)
1048  {
1049  	return IS_WLAN_PHYMODE_EHT(phymode);
1050  }
1051  #else
1052  static enum wlan_phymode
wma_fw_to_host_phymode_11be(WMI_HOST_WLAN_PHY_MODE phymode)1053  wma_fw_to_host_phymode_11be(WMI_HOST_WLAN_PHY_MODE phymode)
1054  {
1055  	return WLAN_PHYMODE_AUTO;
1056  }
1057  
wma_is_phymode_eht(enum wlan_phymode phymode)1058  static inline bool wma_is_phymode_eht(enum wlan_phymode phymode)
1059  {
1060  	return false;
1061  }
1062  #endif
1063  
1064  #ifdef CONFIG_160MHZ_SUPPORT
1065  /**
1066   * wma_fw_to_host_phymode_160() - convert fw to host phymode for 160 mhz
1067   * phymodes
1068   * @phymode: phymode to convert
1069   *
1070   * Return: one of the 160 mhz values defined in enum wlan_phymode;
1071   *         or WLAN_PHYMODE_AUTO if the input is not a 160 mhz phymode
1072   */
1073  static enum wlan_phymode
wma_fw_to_host_phymode_160(WMI_HOST_WLAN_PHY_MODE phymode)1074  wma_fw_to_host_phymode_160(WMI_HOST_WLAN_PHY_MODE phymode)
1075  {
1076  	switch (phymode) {
1077  	default:
1078  		return WLAN_PHYMODE_AUTO;
1079  	case WMI_HOST_MODE_11AC_VHT80_80:
1080  		return WLAN_PHYMODE_11AC_VHT80_80;
1081  	case WMI_HOST_MODE_11AC_VHT160:
1082  		return WLAN_PHYMODE_11AC_VHT160;
1083  	}
1084  }
1085  #else
1086  static enum wlan_phymode
wma_fw_to_host_phymode_160(WMI_HOST_WLAN_PHY_MODE phymode)1087  wma_fw_to_host_phymode_160(WMI_HOST_WLAN_PHY_MODE phymode)
1088  {
1089  	return WLAN_PHYMODE_AUTO;
1090  }
1091  #endif
1092  
wma_fw_to_host_phymode(WMI_HOST_WLAN_PHY_MODE phymode)1093  enum wlan_phymode wma_fw_to_host_phymode(WMI_HOST_WLAN_PHY_MODE phymode)
1094  {
1095  	enum wlan_phymode host_phymode;
1096  	switch (phymode) {
1097  	default:
1098  		host_phymode = wma_fw_to_host_phymode_160(phymode);
1099  		if (host_phymode != WLAN_PHYMODE_AUTO)
1100  			return host_phymode;
1101  		host_phymode = wma_fw_to_host_phymode_11ax(phymode);
1102  		if (host_phymode != WLAN_PHYMODE_AUTO)
1103  			return host_phymode;
1104  		return wma_fw_to_host_phymode_11be(phymode);
1105  	case WMI_HOST_MODE_11A:
1106  		return WLAN_PHYMODE_11A;
1107  	case WMI_HOST_MODE_11G:
1108  		return WLAN_PHYMODE_11G;
1109  	case WMI_HOST_MODE_11B:
1110  		return WLAN_PHYMODE_11B;
1111  	case WMI_HOST_MODE_11GONLY:
1112  		return WLAN_PHYMODE_11G_ONLY;
1113  	case WMI_HOST_MODE_11NA_HT20:
1114  		return WLAN_PHYMODE_11NA_HT20;
1115  	case WMI_HOST_MODE_11NG_HT20:
1116  		return WLAN_PHYMODE_11NG_HT20;
1117  	case WMI_HOST_MODE_11NA_HT40:
1118  		return WLAN_PHYMODE_11NA_HT40;
1119  	case WMI_HOST_MODE_11NG_HT40:
1120  		return WLAN_PHYMODE_11NG_HT40;
1121  	case WMI_HOST_MODE_11AC_VHT20:
1122  		return WLAN_PHYMODE_11AC_VHT20;
1123  	case WMI_HOST_MODE_11AC_VHT40:
1124  		return WLAN_PHYMODE_11AC_VHT40;
1125  	case WMI_HOST_MODE_11AC_VHT80:
1126  		return WLAN_PHYMODE_11AC_VHT80;
1127  	case WMI_HOST_MODE_11AC_VHT20_2G:
1128  		return WLAN_PHYMODE_11AC_VHT20_2G;
1129  	case WMI_HOST_MODE_11AC_VHT40_2G:
1130  		return WLAN_PHYMODE_11AC_VHT40_2G;
1131  	case WMI_HOST_MODE_11AC_VHT80_2G:
1132  		return WLAN_PHYMODE_11AC_VHT80_2G;
1133  	}
1134  }
1135  
1136  #ifdef WLAN_FEATURE_11BE
wma_populate_peer_puncture(struct peer_assoc_params * peer,struct wlan_channel * des_chan)1137  static void wma_populate_peer_puncture(struct peer_assoc_params *peer,
1138  				       struct wlan_channel *des_chan)
1139  {
1140  	peer->puncture_bitmap = des_chan->puncture_bitmap;
1141  	wma_debug("Peer EHT puncture bitmap %d", peer->puncture_bitmap);
1142  }
1143  
wma_populate_peer_mlo_cap(struct peer_assoc_params * peer,tpAddStaParams params)1144  static void wma_populate_peer_mlo_cap(struct peer_assoc_params *peer,
1145  				      tpAddStaParams params)
1146  {
1147  	struct peer_assoc_ml_partner_links *ml_links;
1148  	struct peer_assoc_mlo_params *mlo_params;
1149  	struct peer_ml_info *ml_info;
1150  	uint8_t i;
1151  
1152  	ml_info = &params->ml_info;
1153  	mlo_params = &peer->mlo_params;
1154  	ml_links = &peer->ml_links;
1155  
1156  	/* Assoc link info */
1157  	mlo_params->vdev_id = ml_info->vdev_id;
1158  	mlo_params->ieee_link_id = ml_info->link_id;
1159  	qdf_mem_copy(&mlo_params->chan, &ml_info->channel_info,
1160  		     sizeof(struct wlan_channel));
1161  	qdf_mem_copy(&mlo_params->bssid, &ml_info->link_addr,
1162  		     QDF_MAC_ADDR_SIZE);
1163  	qdf_mem_copy(&mlo_params->mac_addr, &ml_info->self_mac_addr,
1164  		     QDF_MAC_ADDR_SIZE);
1165  
1166  	mlo_params->rec_max_simultaneous_links =
1167  		ml_info->rec_max_simultaneous_links;
1168  
1169  	/* Fill partner link info */
1170  	ml_links->num_links = ml_info->num_links;
1171  	for (i = 0; i < ml_links->num_links; i++) {
1172  		ml_links->partner_info[i].vdev_id =
1173  					ml_info->partner_info[i].vdev_id;
1174  		ml_links->partner_info[i].link_id =
1175  					ml_info->partner_info[i].link_id;
1176  		qdf_mem_copy(&ml_links->partner_info[i].chan,
1177  			     &ml_info->partner_info[i].channel_info,
1178  			     sizeof(struct wlan_channel));
1179  		qdf_mem_copy(&ml_links->partner_info[i].bssid,
1180  			     &ml_info->partner_info[i].link_addr,
1181  			     QDF_MAC_ADDR_SIZE);
1182  		qdf_mem_copy(&ml_links->partner_info[i].mac_addr,
1183  			     &ml_info->partner_info[i].self_mac_addr,
1184  			     QDF_MAC_ADDR_SIZE);
1185  	}
1186  }
1187  #else
wma_populate_peer_puncture(struct peer_assoc_params * peer,struct wlan_channel * des_chan)1188  static void wma_populate_peer_puncture(struct peer_assoc_params *peer,
1189  				       struct wlan_channel *des_chan)
1190  {
1191  }
1192  
wma_populate_peer_mlo_cap(struct peer_assoc_params * peer,tpAddStaParams params)1193  static void wma_populate_peer_mlo_cap(struct peer_assoc_params *peer,
1194  				      tpAddStaParams params)
1195  {
1196  }
1197  #endif
1198  
wma_objmgr_set_peer_mlme_nss(tp_wma_handle wma,uint8_t * mac_addr,uint8_t nss)1199  void wma_objmgr_set_peer_mlme_nss(tp_wma_handle wma, uint8_t *mac_addr,
1200  				  uint8_t nss)
1201  {
1202  	uint8_t pdev_id;
1203  	struct wlan_objmgr_peer *peer;
1204  	struct peer_mlme_priv_obj *peer_priv;
1205  	struct wlan_objmgr_psoc *psoc = wma->psoc;
1206  
1207  	pdev_id = wlan_objmgr_pdev_get_pdev_id(wma->pdev);
1208  	peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr,
1209  				    WLAN_LEGACY_WMA_ID);
1210  	if (!peer)
1211  		return;
1212  
1213  	peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
1214  							  WLAN_UMAC_COMP_MLME);
1215  	if (!peer_priv) {
1216  		wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
1217  		return;
1218  	}
1219  
1220  	peer_priv->nss = nss;
1221  	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
1222  }
1223  
wma_objmgr_get_peer_mlme_nss(tp_wma_handle wma,uint8_t * mac_addr)1224  uint8_t wma_objmgr_get_peer_mlme_nss(tp_wma_handle wma, uint8_t *mac_addr)
1225  {
1226  	uint8_t pdev_id;
1227  	struct wlan_objmgr_peer *peer;
1228  	struct peer_mlme_priv_obj *peer_priv;
1229  	struct wlan_objmgr_psoc *psoc = wma->psoc;
1230  	uint8_t nss;
1231  
1232  	pdev_id = wlan_objmgr_pdev_get_pdev_id(wma->pdev);
1233  	peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr,
1234  				    WLAN_LEGACY_WMA_ID);
1235  	if (!peer)
1236  		return 0;
1237  
1238  	peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
1239  							  WLAN_UMAC_COMP_MLME);
1240  	if (!peer_priv) {
1241  		wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
1242  		return 0;
1243  	}
1244  
1245  	nss = peer_priv->nss;
1246  	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
1247  	return nss;
1248  }
1249  
wma_objmgr_set_peer_mlme_phymode(tp_wma_handle wma,uint8_t * mac_addr,enum wlan_phymode phymode)1250  void wma_objmgr_set_peer_mlme_phymode(tp_wma_handle wma, uint8_t *mac_addr,
1251  				      enum wlan_phymode phymode)
1252  {
1253  	uint8_t pdev_id;
1254  	struct wlan_objmgr_peer *peer;
1255  	struct wlan_objmgr_psoc *psoc = wma->psoc;
1256  
1257  	pdev_id = wlan_objmgr_pdev_get_pdev_id(wma->pdev);
1258  	peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr,
1259  				    WLAN_LEGACY_WMA_ID);
1260  	if (!peer)
1261  		return;
1262  
1263  	wlan_peer_obj_lock(peer);
1264  	wlan_peer_set_phymode(peer, phymode);
1265  	wlan_peer_obj_unlock(peer);
1266  	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
1267  }
1268  
1269  /**
1270   * wma_objmgr_set_peer_mlme_type() - set peer type to peer object
1271   * @wma:      wma handle
1272   * @mac_addr: mac addr of peer
1273   * @peer_type:  peer type value to set
1274   *
1275   * Return: None
1276   */
wma_objmgr_set_peer_mlme_type(tp_wma_handle wma,uint8_t * mac_addr,enum wlan_peer_type peer_type)1277  static void wma_objmgr_set_peer_mlme_type(tp_wma_handle wma,
1278  					  uint8_t *mac_addr,
1279  					  enum wlan_peer_type peer_type)
1280  {
1281  	uint8_t pdev_id;
1282  	struct wlan_objmgr_peer *peer;
1283  	struct wlan_objmgr_psoc *psoc = wma->psoc;
1284  
1285  	pdev_id = wlan_objmgr_pdev_get_pdev_id(wma->pdev);
1286  	peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr,
1287  				    WLAN_LEGACY_WMA_ID);
1288  	if (!peer)
1289  		return;
1290  
1291  	wlan_peer_obj_lock(peer);
1292  	wlan_peer_set_peer_type(peer, peer_type);
1293  	wlan_peer_obj_unlock(peer);
1294  	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
1295  }
1296  
1297  #ifdef WLAN_FEATURE_11BE_MLO
1298  
1299  #define MIN_TIMEOUT_VAL 0
1300  #define MAX_TIMEOUT_VAL 11
1301  
1302  #define TIMEOUT_TO_US 6
1303  
1304  /*
1305   * wma_convert_trans_timeout_us() - API to convert
1306   * emlsr transition timeout to microseconds. Refer Table 9-401h
1307   * of IEEE802.11be specification
1308   * @timeout: EMLSR transition timeout
1309   *
1310   * Return: Timeout value in microseconds
1311   */
1312  static inline uint32_t
wma_convert_trans_timeout_us(uint16_t timeout)1313  wma_convert_trans_timeout_us(uint16_t timeout)
1314  {
1315  	uint32_t us = 0;
1316  
1317  	if (timeout > MIN_TIMEOUT_VAL && timeout < MAX_TIMEOUT_VAL) {
1318  		/* timeout = 1 is for 128us*/
1319  		us = (1 << (timeout + TIMEOUT_TO_US));
1320  	}
1321  
1322  	return us;
1323  }
1324  
1325  /**
1326   * wma_set_mlo_capability() - set MLO caps to the peer assoc request
1327   * @wma: wma handle
1328   * @vdev: vdev object
1329   * @params: Add sta params
1330   * @req: peer assoc request parameters
1331   *
1332   * Return: None
1333   */
wma_set_mlo_capability(tp_wma_handle wma,struct wlan_objmgr_vdev * vdev,tpAddStaParams params,struct peer_assoc_params * req)1334  static void wma_set_mlo_capability(tp_wma_handle wma,
1335  				   struct wlan_objmgr_vdev *vdev,
1336  				   tpAddStaParams params,
1337  				   struct peer_assoc_params *req)
1338  {
1339  	uint8_t pdev_id;
1340  	struct wlan_objmgr_peer *peer;
1341  	struct wlan_objmgr_psoc *psoc = wma->psoc;
1342  	uint16_t link_id_bitmap;
1343  
1344  	pdev_id = wlan_objmgr_pdev_get_pdev_id(wma->pdev);
1345  	peer = wlan_objmgr_get_peer(psoc, pdev_id, req->peer_mac,
1346  				    WLAN_LEGACY_WMA_ID);
1347  
1348  	if (!peer) {
1349  		wma_err("peer not valid");
1350  		return;
1351  	}
1352  
1353  	if (!qdf_is_macaddr_zero((struct qdf_mac_addr *)peer->mldaddr)) {
1354  		req->mlo_params.mlo_enabled = true;
1355  		req->mlo_params.mlo_assoc_link =
1356  					wlan_peer_mlme_is_assoc_peer(peer);
1357  		WLAN_ADDR_COPY(req->mlo_params.mld_mac, peer->mldaddr);
1358  		if (policy_mgr_ml_link_vdev_need_to_be_disabled(psoc, vdev,
1359  								true) ||
1360  		    policy_mgr_is_emlsr_sta_concurrency_present(psoc)) {
1361  			req->mlo_params.mlo_force_link_inactive = 1;
1362  			link_id_bitmap = 1 << params->link_id;
1363  			ml_nlink_set_curr_force_inactive_state(
1364  					psoc, vdev, link_id_bitmap, LINK_ADD);
1365  			ml_nlink_init_concurrency_link_request(psoc, vdev);
1366  		}
1367  		wma_debug("assoc_link %d" QDF_MAC_ADDR_FMT ", force inactive %d link id %d",
1368  			  req->mlo_params.mlo_assoc_link,
1369  			  QDF_MAC_ADDR_REF(peer->mldaddr),
1370  			  req->mlo_params.mlo_force_link_inactive,
1371  			  params->link_id);
1372  
1373  		req->mlo_params.emlsr_support = params->emlsr_support;
1374  		req->mlo_params.ieee_link_id = params->link_id;
1375  		if (req->mlo_params.emlsr_support) {
1376  			req->mlo_params.trans_timeout_us =
1377  			wma_convert_trans_timeout_us(params->emlsr_trans_timeout);
1378  		}
1379  		req->mlo_params.msd_cap_support = params->msd_caps_present;
1380  		req->mlo_params.medium_sync_duration =
1381  				params->msd_caps.med_sync_duration;
1382  		req->mlo_params.medium_sync_ofdm_ed_thresh =
1383  				params->msd_caps.med_sync_ofdm_ed_thresh;
1384  		req->mlo_params.medium_sync_max_txop_num =
1385  				params->msd_caps.med_sync_max_txop_num;
1386  		req->mlo_params.link_switch_in_progress =
1387  			wlan_vdev_mlme_is_mlo_link_switch_in_progress(vdev);
1388  		/*
1389  		 * Set max simultaneous links = 1 for MLSR, 2 for MLMR. The +1
1390  		 * is added as per the agreement with FW for backward
1391  		 * compatibility purposes. Our internal structures still
1392  		 * conform to the values as per spec i.e. 0 = MLSR, 1 = MLMR.
1393  		 */
1394  		req->mlo_params.max_num_simultaneous_links =
1395  			wlan_mlme_get_sta_mlo_simultaneous_links(psoc) + 1;
1396  	} else {
1397  		wma_debug("Peer MLO context is NULL");
1398  		req->mlo_params.mlo_enabled = false;
1399  		req->mlo_params.emlsr_support = false;
1400  	}
1401  	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
1402  }
1403  
wma_set_mlo_assoc_vdev(struct wlan_objmgr_vdev * vdev,struct peer_assoc_params * req)1404  static void wma_set_mlo_assoc_vdev(struct wlan_objmgr_vdev *vdev,
1405  				   struct peer_assoc_params *req)
1406  {
1407  	if (wlan_vdev_mlme_is_mlo_vdev(vdev) &&
1408  	    !wlan_vdev_mlme_is_mlo_link_vdev(vdev))
1409  		req->is_assoc_vdev = true;
1410  }
1411  #else
wma_set_mlo_capability(tp_wma_handle wma,struct wlan_objmgr_vdev * vdev,tpAddStaParams params,struct peer_assoc_params * req)1412  static inline void wma_set_mlo_capability(tp_wma_handle wma,
1413  					  struct wlan_objmgr_vdev *vdev,
1414  					  tpAddStaParams params,
1415  					  struct peer_assoc_params *req)
1416  {
1417  }
1418  
wma_set_mlo_assoc_vdev(struct wlan_objmgr_vdev * vdev,struct peer_assoc_params * req)1419  static inline void wma_set_mlo_assoc_vdev(struct wlan_objmgr_vdev *vdev,
1420  					  struct peer_assoc_params *req)
1421  {
1422  }
1423  #endif
1424  
1425  /**
1426   * wmi_unified_send_peer_assoc() - send peer assoc command to fw
1427   * @wma: wma handle
1428   * @nw_type: nw type
1429   * @params: add sta params
1430   *
1431   * This function send peer assoc command to firmware with
1432   * different parameters.
1433   *
1434   * Return: QDF_STATUS
1435   */
wma_send_peer_assoc(tp_wma_handle wma,tSirNwType nw_type,tpAddStaParams params)1436  QDF_STATUS wma_send_peer_assoc(tp_wma_handle wma,
1437  				    tSirNwType nw_type,
1438  				    tpAddStaParams params)
1439  {
1440  	struct peer_assoc_params *cmd;
1441  	int32_t ret, max_rates, i;
1442  	uint8_t *rate_pos;
1443  	wmi_rate_set peer_legacy_rates, peer_ht_rates;
1444  	uint32_t num_peer_11b_rates = 0;
1445  	uint32_t num_peer_11a_rates = 0;
1446  	enum wlan_phymode phymode, vdev_phymode;
1447  	uint32_t peer_nss = 1;
1448  	struct wma_txrx_node *intr = NULL;
1449  	bool is_he;
1450  	bool is_eht;
1451  	QDF_STATUS status;
1452  	struct mac_context *mac = wma->mac_context;
1453  	struct wlan_channel *des_chan;
1454  	int32_t keymgmt, uccipher, authmode;
1455  
1456  	cmd = qdf_mem_malloc(sizeof(struct peer_assoc_params));
1457  	if (!cmd) {
1458  		wma_err("Failed to allocate peer_assoc_params param");
1459  		return QDF_STATUS_E_NOMEM;
1460  	}
1461  
1462  	intr = &wma->interfaces[params->smesessionId];
1463  
1464  	wma_mask_tx_ht_rate(wma, params->supportedRates.supportedMCSSet);
1465  
1466  	qdf_mem_zero(&peer_legacy_rates, sizeof(wmi_rate_set));
1467  	qdf_mem_zero(&peer_ht_rates, sizeof(wmi_rate_set));
1468  	qdf_mem_zero(cmd, sizeof(struct peer_assoc_params));
1469  
1470  	is_he = wma_is_peer_he_capable(params);
1471  	is_eht = wma_is_peer_eht_capable(params);
1472  	if ((params->ch_width > CH_WIDTH_40MHZ) &&
1473  	    ((nw_type == eSIR_11G_NW_TYPE) ||
1474  	     (nw_type == eSIR_11B_NW_TYPE))) {
1475  		wma_err("ch_width %d sent in 11G, configure to 40MHz",
1476  			params->ch_width);
1477  		params->ch_width = CH_WIDTH_40MHZ;
1478  	}
1479  	phymode = wma_peer_phymode(nw_type, params->staType,
1480  				   params->htCapable, params->ch_width,
1481  				   params->vhtCapable, is_he, is_eht);
1482  
1483  	des_chan = wlan_vdev_mlme_get_des_chan(intr->vdev);
1484  	vdev_phymode = des_chan->ch_phymode;
1485  	if ((intr->type == WMI_VDEV_TYPE_AP) && (phymode > vdev_phymode)) {
1486  		wma_nofl_debug("Peer phymode %d is not allowed. Set it equal to sap/go phymode %d",
1487  			       phymode, vdev_phymode);
1488  		phymode = vdev_phymode;
1489  	}
1490  
1491  	if (!mac->mlme_cfg->rates.disable_abg_rate_txdata &&
1492  	    !WLAN_REG_IS_6GHZ_CHAN_FREQ(des_chan->ch_freq)) {
1493  		/* Legacy Rateset */
1494  		rate_pos = (uint8_t *) peer_legacy_rates.rates;
1495  		for (i = 0; i < SIR_NUM_11B_RATES; i++) {
1496  			if (!params->supportedRates.llbRates[i])
1497  				continue;
1498  			rate_pos[peer_legacy_rates.num_rates++] =
1499  				params->supportedRates.llbRates[i];
1500  			num_peer_11b_rates++;
1501  		}
1502  		for (i = 0; i < SIR_NUM_11A_RATES; i++) {
1503  			if (!params->supportedRates.llaRates[i])
1504  				continue;
1505  			rate_pos[peer_legacy_rates.num_rates++] =
1506  				params->supportedRates.llaRates[i];
1507  			num_peer_11a_rates++;
1508  		}
1509  	}
1510  
1511  	if ((phymode == WLAN_PHYMODE_11A && num_peer_11a_rates == 0) ||
1512  	    (phymode == WLAN_PHYMODE_11B && num_peer_11b_rates == 0)) {
1513  		wma_warn("Invalid phy rates. phymode 0x%x, 11b_rates %d, 11a_rates %d",
1514  			phymode, num_peer_11b_rates,
1515  			num_peer_11a_rates);
1516  		qdf_mem_free(cmd);
1517  		return QDF_STATUS_E_INVAL;
1518  	}
1519  
1520  	/* HT Rateset */
1521  	max_rates = sizeof(peer_ht_rates.rates) /
1522  		    sizeof(peer_ht_rates.rates[0]);
1523  	rate_pos = (uint8_t *) peer_ht_rates.rates;
1524  	for (i = 0; i < MAX_SUPPORTED_RATES; i++) {
1525  		if (params->supportedRates.supportedMCSSet[i / 8] &
1526  		    (1 << (i % 8))) {
1527  			rate_pos[peer_ht_rates.num_rates++] = i;
1528  			if (i >= 8) {
1529  				/* MCS8 or higher rate is present, must be 2x2 */
1530  				peer_nss = 2;
1531  			}
1532  		}
1533  		if (peer_ht_rates.num_rates == max_rates)
1534  			break;
1535  	}
1536  
1537  	if (params->htCapable && !peer_ht_rates.num_rates) {
1538  		uint8_t temp_ni_rates[8] = { 0x0, 0x1, 0x2, 0x3,
1539  					     0x4, 0x5, 0x6, 0x7};
1540  		/*
1541  		 * Workaround for EV 116382: The peer is marked HT but with
1542  		 * supported rx mcs set is set to 0. 11n spec mandates MCS0-7
1543  		 * for a HT STA. So forcing the supported rx mcs rate to
1544  		 * MCS 0-7. This workaround will be removed once we get
1545  		 * clarification from WFA regarding this STA behavior.
1546  		 */
1547  
1548  		/* TODO: Do we really need this? */
1549  		wma_warn("Peer is marked as HT capable but supported mcs rate is 0");
1550  		peer_ht_rates.num_rates = sizeof(temp_ni_rates);
1551  		qdf_mem_copy((uint8_t *) peer_ht_rates.rates, temp_ni_rates,
1552  			     peer_ht_rates.num_rates);
1553  	}
1554  
1555  	/* in ap mode and for tdls peer, use mac address of the peer in
1556  	 * the other end as the new peer address; in sta mode, use bss id to
1557  	 * be the new peer address
1558  	 */
1559  	if ((wma_is_vdev_in_ap_mode(wma, params->smesessionId))
1560  #ifdef FEATURE_WLAN_TDLS
1561  	    || (STA_ENTRY_TDLS_PEER == params->staType)
1562  #endif /* FEATURE_WLAN_TDLS */
1563  	    ) {
1564  		qdf_mem_copy(cmd->peer_mac, params->staMac,
1565  						sizeof(cmd->peer_mac));
1566  	} else {
1567  		qdf_mem_copy(cmd->peer_mac, params->bssId,
1568  						sizeof(cmd->peer_mac));
1569  	}
1570  	wma_objmgr_set_peer_mlme_phymode(wma, cmd->peer_mac, phymode);
1571  
1572  	cmd->vdev_id = params->smesessionId;
1573  	cmd->peer_new_assoc = 1;
1574  	cmd->peer_associd = params->assocId;
1575  
1576  	cmd->is_wme_set = 1;
1577  
1578  	if (params->wmmEnabled)
1579  		cmd->qos_flag = 1;
1580  
1581  	if (params->uAPSD) {
1582  		cmd->apsd_flag = 1;
1583  		wma_nofl_debug("Set WMI_PEER_APSD: uapsd Mask %d",
1584  			       params->uAPSD);
1585  	}
1586  
1587  	if (params->htCapable) {
1588  		cmd->ht_flag = 1;
1589  		cmd->qos_flag = 1;
1590  		cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
1591  	}
1592  
1593  	if (params->vhtCapable) {
1594  		cmd->ht_flag = 1;
1595  		cmd->qos_flag = 1;
1596  		cmd->vht_flag = 1;
1597  		cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
1598  	}
1599  
1600  	if (params->ch_width) {
1601  		cmd->peer_rate_caps |= WMI_RC_CW40_FLAG;
1602  		if (params->fShortGI40Mhz)
1603  			cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
1604  	} else if (params->fShortGI20Mhz) {
1605  		cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
1606  	}
1607  
1608  	switch (params->ch_width) {
1609  	case CH_WIDTH_320MHZ:
1610  		wma_set_peer_assoc_params_bw_320(cmd, params->ch_width);
1611  		fallthrough;
1612  	case CH_WIDTH_80P80MHZ:
1613  	case CH_WIDTH_160MHZ:
1614  		cmd->bw_160 = 1;
1615  		fallthrough;
1616  	case CH_WIDTH_80MHZ:
1617  		cmd->bw_80 = 1;
1618  		fallthrough;
1619  	case CH_WIDTH_40MHZ:
1620  		cmd->bw_40 = 1;
1621  		fallthrough;
1622  	default:
1623  		break;
1624  	}
1625  
1626  	cmd->peer_vht_caps = params->vht_caps;
1627  	if (params->p2pCapableSta) {
1628  		cmd->p2p_capable_sta = 1;
1629  		wma_objmgr_set_peer_mlme_type(wma, params->staMac,
1630  					      WLAN_PEER_P2P_CLI);
1631  	}
1632  
1633  	if (params->rmfEnabled)
1634  		cmd->is_pmf_enabled = 1;
1635  
1636  	if (params->stbc_capable)
1637  		cmd->stbc_flag = 1;
1638  
1639  	if (params->htLdpcCapable || params->vhtLdpcCapable)
1640  		cmd->ldpc_flag = 1;
1641  
1642  	switch (params->mimoPS) {
1643  	case eSIR_HT_MIMO_PS_STATIC:
1644  		cmd->static_mimops_flag = 1;
1645  		break;
1646  	case eSIR_HT_MIMO_PS_DYNAMIC:
1647  		cmd->dynamic_mimops_flag = 1;
1648  		break;
1649  	case eSIR_HT_MIMO_PS_NO_LIMIT:
1650  		cmd->spatial_mux_flag = 1;
1651  		break;
1652  	default:
1653  		break;
1654  	}
1655  
1656  	wma_set_twt_peer_caps(params, cmd);
1657  #ifdef FEATURE_WLAN_TDLS
1658  	if (STA_ENTRY_TDLS_PEER == params->staType)
1659  		cmd->auth_flag = 1;
1660  #endif /* FEATURE_WLAN_TDLS */
1661  
1662  	if (params->wpa_rsn
1663  #ifdef FEATURE_WLAN_WAPI
1664  	    || params->encryptType == eSIR_ED_WPI
1665  #endif /* FEATURE_WLAN_WAPI */
1666  	    ) {
1667  		if (!params->no_ptk_4_way) {
1668  			cmd->need_ptk_4_way = 1;
1669  			wlan_acquire_peer_key_wakelock(wma->pdev,
1670  						       cmd->peer_mac);
1671  		}
1672  	}
1673  
1674  	if (params->wpa_rsn >> 1)
1675  		cmd->need_gtk_2_way = 1;
1676  
1677  #ifdef FEATURE_WLAN_WAPI
1678  	if (params->encryptType == eSIR_ED_WPI) {
1679  		ret = wma_vdev_set_param(wma->wmi_handle, params->smesessionId,
1680  				      wmi_vdev_param_drop_unencry, false);
1681  		if (ret) {
1682  			wma_err("Set wmi_vdev_param_drop_unencry Param status:%d",
1683  				ret);
1684  			qdf_mem_free(cmd);
1685  			return ret;
1686  		}
1687  	}
1688  #endif /* FEATURE_WLAN_WAPI */
1689  
1690  	cmd->peer_caps = params->capab_info;
1691  	cmd->peer_listen_intval = params->listenInterval;
1692  	cmd->peer_ht_caps = params->ht_caps;
1693  	cmd->peer_max_mpdu = (1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
1694  				    params->maxAmpduSize)) - 1;
1695  	cmd->peer_mpdu_density = wma_parse_mpdudensity(params->maxAmpduDensity);
1696  
1697  	if (params->supportedRates.supportedMCSSet[1] &&
1698  	    params->supportedRates.supportedMCSSet[2])
1699  		cmd->peer_rate_caps |= WMI_RC_TS_FLAG;
1700  	else if (params->supportedRates.supportedMCSSet[1])
1701  		cmd->peer_rate_caps |= WMI_RC_DS_FLAG;
1702  
1703  	/* Update peer legacy rate information */
1704  	cmd->peer_legacy_rates.num_rates = peer_legacy_rates.num_rates;
1705  	qdf_mem_copy(cmd->peer_legacy_rates.rates, peer_legacy_rates.rates,
1706  		     peer_legacy_rates.num_rates);
1707  
1708  	/* Update peer HT rate information */
1709  	cmd->peer_ht_rates.num_rates = peer_ht_rates.num_rates;
1710  	qdf_mem_copy(cmd->peer_ht_rates.rates, peer_ht_rates.rates,
1711  				 peer_ht_rates.num_rates);
1712  
1713  	/* VHT Rates */
1714  
1715  	cmd->peer_nss = peer_nss;
1716  	/*
1717  	 * Because of DBS a vdev may come up in any of the two MACs with
1718  	 * different capabilities. STBC capab should be fetched for given
1719  	 * hard_mode->MAC_id combo. It is planned that firmware should provide
1720  	 * these dev capabilities. But for now number of tx streams can be used
1721  	 * to identify if Tx STBC needs to be disabled.
1722  	 */
1723  	if (intr->tx_streams < 2) {
1724  		cmd->peer_vht_caps &= ~(1 << SIR_MAC_VHT_CAP_TXSTBC);
1725  		wma_nofl_debug("Num tx_streams: %d, Disabled txSTBC",
1726  			       intr->tx_streams);
1727  	}
1728  
1729  	cmd->vht_capable = params->vhtCapable;
1730  	if (params->vhtCapable) {
1731  #define VHT2x2MCSMASK 0xc
1732  		cmd->rx_max_rate = params->supportedRates.vhtRxHighestDataRate;
1733  		cmd->rx_mcs_set = params->supportedRates.vhtRxMCSMap;
1734  		cmd->tx_max_rate = params->supportedRates.vhtTxHighestDataRate;
1735  		cmd->tx_mcs_set = params->supportedRates.vhtTxMCSMap;
1736  		/*
1737  		 *  tx_mcs_set is intersection of self tx NSS and peer rx mcs map
1738  		 */
1739  		if (params->vhtSupportedRxNss)
1740  			cmd->peer_nss = params->vhtSupportedRxNss;
1741  		else
1742  			cmd->peer_nss = ((cmd->tx_mcs_set & VHT2x2MCSMASK)
1743  					== VHT2x2MCSMASK) ? 1 : 2;
1744  
1745  		if (params->vht_mcs_10_11_supp) {
1746  			WMI_SET_BITS(cmd->tx_mcs_set, 16, cmd->peer_nss,
1747  				     ((1 << cmd->peer_nss) - 1));
1748  			WMI_VHT_MCS_NOTIFY_EXT_SS_SET(cmd->tx_mcs_set, 1);
1749  		}
1750  		if (params->vht_extended_nss_bw_cap &&
1751  		    (params->vht_160mhz_nss || params->vht_80p80mhz_nss)) {
1752  			/*
1753  			 * bit[2:0] : Represents value of Rx NSS for 160 MHz
1754  			 * bit[5:3] : Represents value of Rx NSS for 80_80 MHz
1755  			 *             Extended NSS support
1756  			 * bit[30:6]: Reserved
1757  			 * bit[31]  : MSB(0/1): 1 in case of valid data
1758  			 */
1759  			cmd->peer_bw_rxnss_override |= (1 << 31);
1760  			if (params->vht_160mhz_nss)
1761  				cmd->peer_bw_rxnss_override |=
1762  					(params->vht_160mhz_nss - 1);
1763  			if (params->vht_80p80mhz_nss)
1764  				cmd->peer_bw_rxnss_override |=
1765  					((params->vht_80p80mhz_nss - 1) << 3);
1766  			wma_debug("peer_bw_rxnss_override %0X",
1767  				  cmd->peer_bw_rxnss_override);
1768  		}
1769  	}
1770  
1771  	wma_set_mlo_capability(wma, intr->vdev, params, cmd);
1772  
1773  	wma_set_mlo_assoc_vdev(intr->vdev, cmd);
1774  
1775  	wma_debug("rx_max_rate %d, rx_mcs %x, tx_max_rate %d, tx_mcs: %x num rates %d need 4 way %d",
1776  		  cmd->rx_max_rate, cmd->rx_mcs_set, cmd->tx_max_rate,
1777  		  cmd->tx_mcs_set, peer_ht_rates.num_rates,
1778  		  cmd->need_ptk_4_way);
1779  
1780  	/*
1781  	 * Limit nss to max number of rf chain supported by target
1782  	 * Otherwise Fw will crash
1783  	 */
1784  	if (cmd->peer_nss > WMA_MAX_NSS) {
1785  		wma_err("peer Nss %d is more than supported", cmd->peer_nss);
1786  		cmd->peer_nss = WMA_MAX_NSS;
1787  	}
1788  
1789  	wma_populate_peer_he_cap(cmd, params);
1790  	wma_populate_peer_eht_cap(cmd, params);
1791  	wma_populate_peer_puncture(cmd, des_chan);
1792  	wma_populate_peer_mlo_cap(cmd, params);
1793  	if (!wma_is_vdev_in_ap_mode(wma, params->smesessionId))
1794  		intr->nss = cmd->peer_nss;
1795  	wma_objmgr_set_peer_mlme_nss(wma, cmd->peer_mac, cmd->peer_nss);
1796  
1797  	/* Till conversion is not done in WMI we need to fill fw phy mode */
1798  	cmd->peer_phymode = wmi_host_to_fw_phymode(phymode);
1799  
1800  	keymgmt = wlan_crypto_get_param(intr->vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
1801  	authmode = wlan_crypto_get_param(intr->vdev,
1802  					 WLAN_CRYPTO_PARAM_AUTH_MODE);
1803  	uccipher = wlan_crypto_get_param(intr->vdev,
1804  					 WLAN_CRYPTO_PARAM_UCAST_CIPHER);
1805  
1806  	cmd->akm = cm_crypto_authmode_to_wmi_authmode(authmode,
1807  						      keymgmt,
1808  						      uccipher);
1809  
1810  	status = wmi_unified_peer_assoc_send(wma->wmi_handle,
1811  					 cmd);
1812  	if (QDF_IS_STATUS_ERROR(status))
1813  		wma_alert("Failed to send peer assoc command status = %d",
1814  			 status);
1815  	qdf_mem_free(cmd);
1816  
1817  	return status;
1818  }
1819  
1820  /**
1821   * wmi_unified_vdev_set_gtx_cfg_send() - set GTX params
1822   * @wmi_handle: wmi handle
1823   * @if_id: vdev id
1824   * @gtx_info: GTX config params
1825   *
1826   * This function set GTX related params in firmware.
1827   *
1828   * Return: 0 for success or error code
1829   */
wmi_unified_vdev_set_gtx_cfg_send(wmi_unified_t wmi_handle,uint32_t if_id,gtx_config_t * gtx_info)1830  QDF_STATUS wmi_unified_vdev_set_gtx_cfg_send(wmi_unified_t wmi_handle,
1831  				  uint32_t if_id,
1832  				  gtx_config_t *gtx_info)
1833  {
1834  	struct wmi_gtx_config params;
1835  
1836  	params.gtx_rt_mask[0] = gtx_info->gtxRTMask[0];
1837  	params.gtx_rt_mask[1] = gtx_info->gtxRTMask[1];
1838  	params.gtx_usrcfg = gtx_info->gtxUsrcfg;
1839  	params.gtx_threshold = gtx_info->gtxPERThreshold;
1840  	params.gtx_margin = gtx_info->gtxPERMargin;
1841  	params.gtx_tpcstep = gtx_info->gtxTPCstep;
1842  	params.gtx_tpcmin = gtx_info->gtxTPCMin;
1843  	params.gtx_bwmask = gtx_info->gtxBWMask;
1844  
1845  	return wmi_unified_vdev_set_gtx_cfg_cmd(wmi_handle,
1846  						if_id, &params);
1847  
1848  }
1849  
1850  /**
1851   * wma_update_protection_mode() - update protection mode
1852   * @wma: wma handle
1853   * @vdev_id: vdev id
1854   * @llbcoexist: protection mode info
1855   *
1856   * This function set protection mode(RTS/CTS) to fw for passed vdev id.
1857   *
1858   * Return: none
1859   */
wma_update_protection_mode(tp_wma_handle wma,uint8_t vdev_id,uint8_t llbcoexist)1860  void wma_update_protection_mode(tp_wma_handle wma, uint8_t vdev_id,
1861  			   uint8_t llbcoexist)
1862  {
1863  	QDF_STATUS ret;
1864  	enum ieee80211_protmode prot_mode;
1865  
1866  	prot_mode = llbcoexist ? IEEE80211_PROT_CTSONLY : IEEE80211_PROT_NONE;
1867  
1868  	ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
1869  					      wmi_vdev_param_protection_mode,
1870  					      prot_mode);
1871  
1872  	if (QDF_IS_STATUS_ERROR(ret))
1873  		wma_err("Failed to send wmi protection mode cmd");
1874  	else
1875  		wma_nofl_debug("Updated protection mode %d to target",
1876  			       prot_mode);
1877  }
1878  
1879  void
wma_update_beacon_interval(tp_wma_handle wma,uint8_t vdev_id,uint16_t beaconInterval)1880  wma_update_beacon_interval(tp_wma_handle wma, uint8_t vdev_id,
1881  			   uint16_t beaconInterval)
1882  {
1883  	QDF_STATUS ret;
1884  
1885  	ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
1886  					      wmi_vdev_param_beacon_interval,
1887  					      beaconInterval);
1888  
1889  	if (QDF_IS_STATUS_ERROR(ret))
1890  		wma_err("Failed to update beacon interval");
1891  	else
1892  		wma_info("Updated beacon interval %d for vdev %d",
1893  			 beaconInterval, vdev_id);
1894  }
1895  
1896  #ifdef WLAN_FEATURE_11AX_BSS_COLOR
1897  /**
1898   * wma_update_bss_color() - update beacon bss color in fw
1899   * @wma: wma handle
1900   * @vdev_id: vdev id
1901   * @he_ops: HE operation, only the bss_color and bss_color_disabled fields
1902   * are updated.
1903   *
1904   * Return: none
1905   */
1906  static void
wma_update_bss_color(tp_wma_handle wma,uint8_t vdev_id,tUpdateBeaconParams * bcn_params)1907  wma_update_bss_color(tp_wma_handle wma, uint8_t vdev_id,
1908  		     tUpdateBeaconParams *bcn_params)
1909  {
1910  	QDF_STATUS ret;
1911  	uint32_t dword_he_ops = 0;
1912  
1913  	WMI_HEOPS_COLOR_SET(dword_he_ops, bcn_params->bss_color);
1914  	WMI_HEOPS_BSSCOLORDISABLE_SET(dword_he_ops,
1915  				bcn_params->bss_color_disabled);
1916  	wma_nofl_debug("vdev: %d, update bss color, HE_OPS: 0x%x",
1917  		       vdev_id, dword_he_ops);
1918  	ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
1919  			      wmi_vdev_param_he_bss_color, dword_he_ops);
1920  	if (QDF_IS_STATUS_ERROR(ret))
1921  		wma_err("Failed to update HE operations");
1922  }
1923  #else
wma_update_bss_color(tp_wma_handle wma,uint8_t vdev_id,tUpdateBeaconParams * bcn_params)1924  static void wma_update_bss_color(tp_wma_handle wma, uint8_t vdev_id,
1925  			   tUpdateBeaconParams *bcn_params)
1926  {
1927  }
1928  #endif
1929  
1930  /**
1931   * wma_process_update_beacon_params() - update beacon parameters to target
1932   * @wma: wma handle
1933   * @bcn_params: beacon parameters
1934   *
1935   * Return: none
1936   */
1937  void
wma_process_update_beacon_params(tp_wma_handle wma,tUpdateBeaconParams * bcn_params)1938  wma_process_update_beacon_params(tp_wma_handle wma,
1939  				 tUpdateBeaconParams *bcn_params)
1940  {
1941  	if (!bcn_params) {
1942  		wma_err("bcn_params NULL");
1943  		return;
1944  	}
1945  
1946  	if (bcn_params->vdev_id >= wma->max_bssid) {
1947  		wma_err("Invalid vdev id %d", bcn_params->vdev_id);
1948  		return;
1949  	}
1950  
1951  	if (bcn_params->paramChangeBitmap & PARAM_BCN_INTERVAL_CHANGED) {
1952  		wma_update_beacon_interval(wma, bcn_params->vdev_id,
1953  					   bcn_params->beaconInterval);
1954  	}
1955  
1956  	if (bcn_params->paramChangeBitmap & PARAM_llBCOEXIST_CHANGED)
1957  		wma_update_protection_mode(wma, bcn_params->vdev_id,
1958  					   bcn_params->llbCoexist);
1959  
1960  	if (bcn_params->paramChangeBitmap & PARAM_BSS_COLOR_CHANGED)
1961  		wma_update_bss_color(wma, bcn_params->vdev_id,
1962  				     bcn_params);
1963  }
1964  
wma_update_rts_params(tp_wma_handle wma,uint32_t value)1965  void wma_update_rts_params(tp_wma_handle wma, uint32_t value)
1966  {
1967  	uint8_t vdev_id;
1968  	QDF_STATUS ret;
1969  	struct wlan_objmgr_vdev *vdev;
1970  
1971  	for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
1972  		vdev = wma->interfaces[vdev_id].vdev;
1973  		if (!vdev)
1974  			continue;
1975  		ret = wma_vdev_set_param(wma->wmi_handle,
1976  					 vdev_id,
1977  					 wmi_vdev_param_rts_threshold,
1978  					 value);
1979  		if (QDF_IS_STATUS_ERROR(ret))
1980  			wma_err("Update cfg param fail for vdevId %d", vdev_id);
1981  	}
1982  }
1983  
wma_update_frag_params(tp_wma_handle wma,uint32_t value)1984  void wma_update_frag_params(tp_wma_handle wma, uint32_t value)
1985  {
1986  	uint8_t vdev_id;
1987  	QDF_STATUS ret;
1988  	struct wlan_objmgr_vdev *vdev;
1989  
1990  	for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
1991  		vdev = wma->interfaces[vdev_id].vdev;
1992  		if (!vdev)
1993  			continue;
1994  		ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
1995  					 wmi_vdev_param_fragmentation_threshold,
1996  					 value);
1997  		if (QDF_IS_STATUS_ERROR(ret))
1998  			wma_err("Update cfg params failed for vdevId %d",
1999  				 vdev_id);
2000  	}
2001  }
2002  
2003  /**
2004   * wma_process_update_edca_param_req() - update EDCA params
2005   * @handle: wma handle
2006   * @edca_params: edca parameters
2007   *
2008   * This function updates EDCA parameters to the target
2009   *
2010   * Return: QDF Status
2011   */
wma_process_update_edca_param_req(WMA_HANDLE handle,tEdcaParams * edca_params)2012  QDF_STATUS wma_process_update_edca_param_req(WMA_HANDLE handle,
2013  					     tEdcaParams *edca_params)
2014  {
2015  	tp_wma_handle wma_handle = (tp_wma_handle) handle;
2016  	struct wmi_host_wme_vparams wmm_param[QCA_WLAN_AC_ALL];
2017  	tSirMacEdcaParamRecord *edca_record;
2018  	int ac;
2019  	struct ol_tx_wmm_param_t ol_tx_wmm_param;
2020  	uint8_t vdev_id;
2021  	QDF_STATUS status;
2022  	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
2023  	uint8_t *debug_str;
2024  	uint32_t len = 0;
2025  
2026  	vdev_id = edca_params->vdev_id;
2027  	if (!wma_is_vdev_valid(vdev_id)) {
2028  		wma_err("vdev id:%d is not active ", vdev_id);
2029  		goto fail;
2030  	}
2031  
2032  	debug_str = qdf_mem_malloc(WMA_WMM_DEBUG_STRING_SIZE);
2033  	if (!debug_str)
2034  		goto fail;
2035  
2036  	for (ac = 0; ac < QCA_WLAN_AC_ALL; ac++) {
2037  		switch (ac) {
2038  		case QCA_WLAN_AC_BE:
2039  			edca_record = &edca_params->acbe;
2040  			break;
2041  		case QCA_WLAN_AC_BK:
2042  			edca_record = &edca_params->acbk;
2043  			break;
2044  		case QCA_WLAN_AC_VI:
2045  			edca_record = &edca_params->acvi;
2046  			break;
2047  		case QCA_WLAN_AC_VO:
2048  			edca_record = &edca_params->acvo;
2049  			break;
2050  		default:
2051  			qdf_mem_free(debug_str);
2052  			goto fail;
2053  		}
2054  
2055  		wma_update_edca_params_for_ac(edca_record, &wmm_param[ac], ac,
2056  					      edca_params->mu_edca_params,
2057  					      debug_str,
2058  					      WMA_WMM_DEBUG_STRING_SIZE, &len);
2059  
2060  		ol_tx_wmm_param.ac[ac].aifs = wmm_param[ac].aifs;
2061  		ol_tx_wmm_param.ac[ac].cwmin = wmm_param[ac].cwmin;
2062  		ol_tx_wmm_param.ac[ac].cwmax = wmm_param[ac].cwmax;
2063  	}
2064  
2065  	wma_nofl_debug("WMM params: %s", debug_str);
2066  	qdf_mem_free(debug_str);
2067  
2068  	status = wmi_unified_process_update_edca_param(wma_handle->wmi_handle,
2069  						vdev_id,
2070  						edca_params->mu_edca_params,
2071  						wmm_param);
2072  	if (status == QDF_STATUS_E_NOMEM)
2073  		return status;
2074  	else if (status == QDF_STATUS_E_FAILURE)
2075  		goto fail;
2076  
2077  	cdp_set_wmm_param(soc, WMI_PDEV_ID_SOC, ol_tx_wmm_param);
2078  
2079  	return QDF_STATUS_SUCCESS;
2080  
2081  fail:
2082  	wma_err("Failed to set WMM Parameters");
2083  	return QDF_STATUS_E_FAILURE;
2084  }
2085  
2086  /**
2087   * wmi_unified_probe_rsp_tmpl_send() - send probe response template to fw
2088   * @wma: wma handle
2089   * @vdev_id: vdev id
2090   * @probe_rsp_info: probe response info
2091   *
2092   * Return: 0 for success or error code
2093   */
wmi_unified_probe_rsp_tmpl_send(tp_wma_handle wma,uint8_t vdev_id,tpSendProbeRespParams probe_rsp_info)2094  static int wmi_unified_probe_rsp_tmpl_send(tp_wma_handle wma,
2095  				   uint8_t vdev_id,
2096  				   tpSendProbeRespParams probe_rsp_info)
2097  {
2098  	uint64_t adjusted_tsf_le;
2099  	struct ieee80211_frame *wh;
2100  	struct wmi_probe_resp_params params;
2101  
2102  	/*
2103  	 * Make the TSF offset negative so probe response in the same
2104  	 * staggered batch have the same TSF.
2105  	 */
2106  	adjusted_tsf_le = cpu_to_le64(0ULL -
2107  				      wma->interfaces[vdev_id].tsfadjust);
2108  	/* Update the timstamp in the probe response buffer with adjusted TSF */
2109  	wh = (struct ieee80211_frame *)probe_rsp_info->probeRespTemplate;
2110  	A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
2111  
2112  	params.prb_rsp_template_len = probe_rsp_info->probeRespTemplateLen;
2113  	params.prb_rsp_template_frm = probe_rsp_info->probeRespTemplate;
2114  	params.go_ignore_non_p2p_probe_req =
2115  		probe_rsp_info->go_ignore_non_p2p_probe_req;
2116  
2117  	return wmi_unified_probe_rsp_tmpl_send_cmd(wma->wmi_handle, vdev_id,
2118  						   &params);
2119  }
2120  
2121  #ifdef WLAN_FEATURE_11BE_MLO
2122  /**
2123   * wma_upt_mlo_partner_info() - update mlo info in beacon template
2124   * @params: beacon template params
2125   * @bcn_param: beacon params
2126   * @bytes_to_strip: bytes to strip
2127   *
2128   * Return: Void
2129   */
wma_upt_mlo_partner_info(struct beacon_tmpl_params * params,const tpSendbeaconParams bcn_param,uint8_t bytes_to_strip)2130  static void wma_upt_mlo_partner_info(struct beacon_tmpl_params *params,
2131  				     const tpSendbeaconParams bcn_param,
2132  				     uint8_t bytes_to_strip)
2133  {
2134  	struct ml_bcn_partner_info *bcn_info;
2135  	struct ml_bcn_partner_info *info;
2136  	int link;
2137  
2138  	params->mlo_partner.num_links = bcn_param->mlo_partner.num_links;
2139  	for (link = 0; link < params->mlo_partner.num_links; link++) {
2140  		bcn_info = &bcn_param->mlo_partner.partner_info[link];
2141  		info = &params->mlo_partner.partner_info[link];
2142  		info->vdev_id = bcn_info->vdev_id;
2143  		info->beacon_interval = bcn_info->beacon_interval;
2144  		if (bcn_info->csa_switch_count_offset &&
2145  		    bcn_info->csa_switch_count_offset > bytes_to_strip)
2146  			info->csa_switch_count_offset =
2147  				bcn_info->csa_switch_count_offset -
2148  					bytes_to_strip;
2149  		if (bcn_info->ext_csa_switch_count_offset &&
2150  		    bcn_info->ext_csa_switch_count_offset > bytes_to_strip)
2151  			info->ext_csa_switch_count_offset =
2152  				bcn_info->ext_csa_switch_count_offset -
2153  					bytes_to_strip;
2154  	}
2155  }
2156  #else
wma_upt_mlo_partner_info(struct beacon_tmpl_params * params,const tpSendbeaconParams bcn_param,uint8_t bytes_to_strip)2157  static void wma_upt_mlo_partner_info(struct beacon_tmpl_params *params,
2158  				     const tpSendbeaconParams bcn_param,
2159  				     uint8_t bytes_to_strip)
2160  {
2161  }
2162  #endif
2163  
2164  /**
2165   * wma_unified_bcn_tmpl_send() - send beacon template to fw
2166   * @wma:wma handle
2167   * @vdev_id: vdev id
2168   * @bcn_info: beacon info
2169   * @bytes_to_strip: bytes to strip
2170   *
2171   * Return: QDF_STATUS_SUCCESS for success or error code
2172   */
wma_unified_bcn_tmpl_send(tp_wma_handle wma,uint8_t vdev_id,const tpSendbeaconParams bcn_info,uint8_t bytes_to_strip)2173  static QDF_STATUS wma_unified_bcn_tmpl_send(tp_wma_handle wma,
2174  				     uint8_t vdev_id,
2175  				     const tpSendbeaconParams bcn_info,
2176  				     uint8_t bytes_to_strip)
2177  {
2178  	struct beacon_tmpl_params params = {0};
2179  	uint32_t tmpl_len, tmpl_len_aligned;
2180  	uint8_t *frm;
2181  	QDF_STATUS ret;
2182  	uint8_t *p2p_ie;
2183  	uint16_t p2p_ie_len = 0;
2184  	uint64_t adjusted_tsf_le;
2185  	struct ieee80211_frame *wh;
2186  
2187  	if (!wma_is_vdev_valid(vdev_id)) {
2188  		wma_err("vdev id:%d is not active ", vdev_id);
2189  		return QDF_STATUS_E_INVAL;
2190  	}
2191  
2192  	wma_nofl_debug("vdev %d: bcn update reason %d", vdev_id,
2193  		       bcn_info->reason);
2194  
2195  	if (bcn_info->p2pIeOffset) {
2196  		p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2197  		p2p_ie_len = (uint16_t) p2p_ie[1] + 2;
2198  	}
2199  
2200  	/*
2201  	 * XXX: The first byte of beacon buffer contains beacon length
2202  	 * only when UMAC in sending the beacon template. In othercases
2203  	 * (ex: from tbtt update) beacon length is read from beacon
2204  	 * information.
2205  	 */
2206  	if (bytes_to_strip)
2207  		tmpl_len = *(uint32_t *) &bcn_info->beacon[0];
2208  	else
2209  		tmpl_len = bcn_info->beaconLength;
2210  
2211  	if (tmpl_len > WMI_BEACON_TX_BUFFER_SIZE) {
2212  		wma_err("tmpl_len: %d > %d. Invalid tmpl len", tmpl_len,
2213  			WMI_BEACON_TX_BUFFER_SIZE);
2214  		return -EINVAL;
2215  	}
2216  
2217  	if (p2p_ie_len) {
2218  		if (tmpl_len <= p2p_ie_len) {
2219  			wma_err("tmpl_len %d <= p2p_ie_len %d, Invalid",
2220  				tmpl_len, p2p_ie_len);
2221  			return -EINVAL;
2222  		}
2223  		tmpl_len -= (uint32_t) p2p_ie_len;
2224  	}
2225  
2226  	frm = bcn_info->beacon + bytes_to_strip;
2227  	tmpl_len_aligned = roundup(tmpl_len, sizeof(A_UINT32));
2228  	/*
2229  	 * Make the TSF offset negative so beacons in the same
2230  	 * staggered batch have the same TSF.
2231  	 */
2232  	adjusted_tsf_le = cpu_to_le64(0ULL -
2233  				      wma->interfaces[vdev_id].tsfadjust);
2234  	/* Update the timstamp in the beacon buffer with adjusted TSF */
2235  	wh = (struct ieee80211_frame *)frm;
2236  	A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
2237  
2238  
2239  
2240  	params.vdev_id = vdev_id;
2241  	params.tim_ie_offset = bcn_info->timIeOffset - bytes_to_strip;
2242  	params.tmpl_len = tmpl_len;
2243  	params.frm = frm;
2244  	params.tmpl_len_aligned = tmpl_len_aligned;
2245  	params.enable_bigtk =
2246  		mlme_get_bigtk_support(wma->interfaces[vdev_id].vdev);
2247  	if (bcn_info->csa_count_offset &&
2248  	    (bcn_info->csa_count_offset > bytes_to_strip))
2249  		params.csa_switch_count_offset =
2250  			bcn_info->csa_count_offset - bytes_to_strip;
2251  	if (bcn_info->ecsa_count_offset &&
2252  	    (bcn_info->ecsa_count_offset > bytes_to_strip))
2253  		params.ext_csa_switch_count_offset =
2254  			bcn_info->ecsa_count_offset - bytes_to_strip;
2255  
2256  	wma_upt_mlo_partner_info(&params, bcn_info, bytes_to_strip);
2257  
2258  	ret = wmi_unified_beacon_tmpl_send_cmd(wma->wmi_handle,
2259  				 &params);
2260  	if (QDF_IS_STATUS_ERROR(ret))
2261  		wma_err("Failed to send bcn tmpl: %d", ret);
2262  
2263  	return ret;
2264  }
2265  
2266  /**
2267   * wma_store_bcn_tmpl() - store beacon template
2268   * @wma: wma handle
2269   * @vdev_id: vdev id
2270   * @bcn_info: beacon params
2271   *
2272   * This function stores beacon template locally.
2273   * This will send to target on the reception of
2274   * SWBA event.
2275   *
2276   * Return: QDF status
2277   */
wma_store_bcn_tmpl(tp_wma_handle wma,uint8_t vdev_id,tpSendbeaconParams bcn_info)2278  static QDF_STATUS wma_store_bcn_tmpl(tp_wma_handle wma, uint8_t vdev_id,
2279  				     tpSendbeaconParams bcn_info)
2280  {
2281  	struct beacon_info *bcn;
2282  	uint32_t len;
2283  	uint8_t *bcn_payload;
2284  	struct beacon_tim_ie *tim_ie;
2285  
2286  	bcn = wma->interfaces[vdev_id].beacon;
2287  	if (!bcn || !bcn->buf) {
2288  		wma_err("Memory is not allocated to hold bcn template");
2289  		return QDF_STATUS_E_INVAL;
2290  	}
2291  
2292  	len = *(uint32_t *) &bcn_info->beacon[0];
2293  	if (len > SIR_MAX_BEACON_SIZE - sizeof(uint32_t)) {
2294  		wma_err("Received beacon len %u exceeding max limit %lu",
2295  			len, (unsigned long)(
2296  			 SIR_MAX_BEACON_SIZE - sizeof(uint32_t)));
2297  		return QDF_STATUS_E_INVAL;
2298  	}
2299  	qdf_spin_lock_bh(&bcn->lock);
2300  
2301  	/*
2302  	 * Copy received beacon template content in local buffer.
2303  	 * this will be send to target on the reception of SWBA
2304  	 * event from target.
2305  	 */
2306  	qdf_nbuf_trim_tail(bcn->buf, qdf_nbuf_len(bcn->buf));
2307  	memcpy(qdf_nbuf_data(bcn->buf),
2308  	       bcn_info->beacon + 4 /* Exclude beacon length field */,
2309  	       len);
2310  	if (bcn_info->timIeOffset > 3)
2311  		bcn->tim_ie_offset = bcn_info->timIeOffset - 4;
2312  	else
2313  		bcn->tim_ie_offset = bcn_info->timIeOffset;
2314  
2315  	if (bcn_info->p2pIeOffset > 3)
2316  		bcn->p2p_ie_offset = bcn_info->p2pIeOffset - 4;
2317  	else
2318  		bcn->p2p_ie_offset = bcn_info->p2pIeOffset;
2319  
2320  	if (bcn_info->csa_count_offset > 3)
2321  		bcn->csa_count_offset = bcn_info->csa_count_offset - 4;
2322  	else
2323  		bcn->csa_count_offset = bcn_info->csa_count_offset;
2324  
2325  	if (bcn_info->ecsa_count_offset > 3)
2326  		bcn->ecsa_count_offset = bcn_info->ecsa_count_offset - 4;
2327  	else
2328  		bcn->ecsa_count_offset = bcn_info->ecsa_count_offset;
2329  
2330  	bcn_payload = qdf_nbuf_data(bcn->buf);
2331  	if (bcn->tim_ie_offset) {
2332  		tim_ie = (struct beacon_tim_ie *)
2333  				(&bcn_payload[bcn->tim_ie_offset]);
2334  		/*
2335  		 * Initial Value of bcn->dtim_count will be 0.
2336  		 * But if the beacon gets updated then current dtim
2337  		 * count will be restored
2338  		 */
2339  		tim_ie->dtim_count = bcn->dtim_count;
2340  		tim_ie->tim_bitctl = 0;
2341  	}
2342  
2343  	qdf_nbuf_put_tail(bcn->buf, len);
2344  	bcn->len = len;
2345  
2346  	qdf_spin_unlock_bh(&bcn->lock);
2347  
2348  	return QDF_STATUS_SUCCESS;
2349  }
2350  
wma_tbttoffset_update_event_handler(void * handle,uint8_t * event,uint32_t len)2351  int wma_tbttoffset_update_event_handler(void *handle, uint8_t *event,
2352  					       uint32_t len)
2353  {
2354  	tp_wma_handle wma = (tp_wma_handle) handle;
2355  	WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf;
2356  	wmi_tbtt_offset_event_fixed_param *tbtt_offset_event;
2357  	struct wma_txrx_node *intf;
2358  	struct beacon_info *bcn;
2359  	tSendbeaconParams bcn_info;
2360  	uint32_t *adjusted_tsf = NULL;
2361  	uint32_t if_id = 0, vdev_map;
2362  
2363  	if (wma_validate_handle(wma))
2364  		return -EINVAL;
2365  
2366  	param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *) event;
2367  	if (!param_buf) {
2368  		wma_err("Invalid tbtt update event buffer");
2369  		return -EINVAL;
2370  	}
2371  
2372  	tbtt_offset_event = param_buf->fixed_param;
2373  	intf = wma->interfaces;
2374  	vdev_map = tbtt_offset_event->vdev_map;
2375  	adjusted_tsf = param_buf->tbttoffset_list;
2376  	if (!adjusted_tsf) {
2377  		wma_err("Invalid adjusted_tsf");
2378  		return -EINVAL;
2379  	}
2380  
2381  	for (; (if_id < wma->max_bssid && vdev_map); vdev_map >>= 1, if_id++) {
2382  		if (!intf[if_id].vdev)
2383  			continue;
2384  
2385  		if (!(vdev_map & 0x1))
2386  			continue;
2387  
2388  		bcn = intf[if_id].beacon;
2389  		if (!bcn) {
2390  			wma_err("Invalid beacon");
2391  			return -EINVAL;
2392  		}
2393  		if (!bcn->buf) {
2394  			wma_err("Invalid beacon buffer");
2395  			return -EINVAL;
2396  		}
2397  		/* Save the adjusted TSF */
2398  		intf[if_id].tsfadjust = adjusted_tsf[if_id];
2399  
2400  		qdf_spin_lock_bh(&bcn->lock);
2401  		qdf_mem_zero(&bcn_info, sizeof(bcn_info));
2402  		qdf_mem_copy(bcn_info.beacon,
2403  			     qdf_nbuf_data(bcn->buf), bcn->len);
2404  		bcn_info.p2pIeOffset = bcn->p2p_ie_offset;
2405  		bcn_info.beaconLength = bcn->len;
2406  		bcn_info.timIeOffset = bcn->tim_ie_offset;
2407  		bcn_info.csa_count_offset = bcn->csa_count_offset;
2408  		bcn_info.ecsa_count_offset = bcn->ecsa_count_offset;
2409  		qdf_spin_unlock_bh(&bcn->lock);
2410  
2411  		wma_err_rl("Update beacon template for vdev %d due to TBTT offset update",
2412  			   if_id);
2413  		/* Update beacon template in firmware */
2414  		wma_unified_bcn_tmpl_send(wma, if_id, &bcn_info, 0);
2415  	}
2416  	return 0;
2417  }
2418  
2419  /**
2420   * wma_p2p_go_set_beacon_ie() - set beacon IE for p2p go
2421   * @wma_handle: wma handle
2422   * @vdev_id: vdev id
2423   * @p2pIe: p2p IE
2424   *
2425   * Return: 0 for success or error code
2426   */
wma_p2p_go_set_beacon_ie(t_wma_handle * wma_handle,A_UINT32 vdev_id,uint8_t * p2pIe)2427  static int wma_p2p_go_set_beacon_ie(t_wma_handle *wma_handle,
2428  				    A_UINT32 vdev_id, uint8_t *p2pIe)
2429  {
2430  	if (wma_validate_handle(wma_handle))
2431  		return QDF_STATUS_E_FAILURE;
2432  
2433  	return wmi_unified_p2p_go_set_beacon_ie_cmd(wma_handle->wmi_handle,
2434  							vdev_id, p2pIe);
2435  }
2436  
2437  /**
2438   * wma_send_probe_rsp_tmpl() - send probe resp template
2439   * @wma: wma handle
2440   * @probe_rsp_info: probe response info
2441   *
2442   * This function sends probe response template to fw which
2443   * firmware will use in case of probe response offload.
2444   *
2445   * Return: none
2446   */
wma_send_probe_rsp_tmpl(tp_wma_handle wma,tpSendProbeRespParams probe_rsp_info)2447  void wma_send_probe_rsp_tmpl(tp_wma_handle wma,
2448  				    tpSendProbeRespParams probe_rsp_info)
2449  {
2450  	uint8_t vdev_id;
2451  	struct sAniProbeRspStruct *probe_rsp;
2452  
2453  	if (!probe_rsp_info) {
2454  		wma_err("probe_rsp_info is NULL");
2455  		return;
2456  	}
2457  
2458  	probe_rsp = (struct sAniProbeRspStruct *)
2459  			(probe_rsp_info->probeRespTemplate);
2460  	if (!probe_rsp) {
2461  		wma_err("probe_rsp is NULL");
2462  		return;
2463  	}
2464  
2465  	if (wma_find_vdev_id_by_addr(wma, probe_rsp->macHdr.sa, &vdev_id)) {
2466  		wma_err("failed to get vdev id");
2467  		return;
2468  	}
2469  
2470  	if (wmi_service_enabled(wma->wmi_handle,
2471  				   wmi_service_beacon_offload)) {
2472  		if (wmi_unified_probe_rsp_tmpl_send(wma, vdev_id,
2473  						    probe_rsp_info) < 0) {
2474  			wma_err("wmi_unified_probe_rsp_tmpl_send Failed");
2475  			return;
2476  		}
2477  	}
2478  }
2479  
wma_set_ap_vdev_up(tp_wma_handle wma,uint8_t vdev_id)2480  QDF_STATUS wma_set_ap_vdev_up(tp_wma_handle wma, uint8_t vdev_id)
2481  {
2482  	QDF_STATUS status = QDF_STATUS_SUCCESS;
2483  	struct vdev_mlme_obj *mlme_obj;
2484  	struct wlan_objmgr_vdev *vdev;
2485  	struct wma_txrx_node *iface;
2486  
2487  	iface = &wma->interfaces[vdev_id];
2488  	vdev = iface->vdev;
2489  	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev);
2490  	if (!mlme_obj) {
2491  		wma_err("failed to get mlme_obj");
2492  		return QDF_STATUS_E_INVAL;
2493  	}
2494  	mlme_obj->proto.sta.assoc_id = 0;
2495  
2496  	status = vdev_mgr_up_send(mlme_obj);
2497  	if (QDF_IS_STATUS_ERROR(status)) {
2498  		wma_err("failed to send vdev up");
2499  		return status;
2500  	}
2501  	wma_set_sap_keepalive(wma, vdev_id);
2502  	wma_set_vdev_mgmt_rate(wma, vdev_id);
2503  	wma_vdev_set_he_bss_params(wma, vdev_id, &mlme_obj->proto.he_ops_info);
2504  	mlme_sr_update(vdev, true);
2505  
2506  	return status;
2507  }
2508  
2509  /**
2510   * wma_send_beacon() - send beacon template
2511   * @wma: wma handle
2512   * @bcn_info: beacon info
2513   *
2514   * This function store beacon template locally and
2515   * update keep alive parameters
2516   *
2517   * Return: none
2518   */
wma_send_beacon(tp_wma_handle wma,tpSendbeaconParams bcn_info)2519  void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info)
2520  {
2521  	uint8_t vdev_id;
2522  	QDF_STATUS status;
2523  	uint8_t *p2p_ie;
2524  	struct sAniBeaconStruct *beacon;
2525  
2526  	beacon = (struct sAniBeaconStruct *) (bcn_info->beacon);
2527  	if (wma_find_vdev_id_by_addr(wma, beacon->macHdr.sa, &vdev_id)) {
2528  		wma_err("failed to get vdev id");
2529  		status = QDF_STATUS_E_INVAL;
2530  		goto send_rsp;
2531  	}
2532  
2533  	if (wmi_service_enabled(wma->wmi_handle,
2534  				   wmi_service_beacon_offload)) {
2535  		status = wma_unified_bcn_tmpl_send(wma, vdev_id, bcn_info, 4);
2536  		if (QDF_IS_STATUS_ERROR(status)) {
2537  			wma_err("wmi_unified_bcn_tmpl_send Failed");
2538  			goto send_rsp;
2539  		}
2540  
2541  		if (bcn_info->p2pIeOffset) {
2542  			p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2543  			wma_debug("p2pIe is present - vdev_id %hu, p2p_ie = %pK, p2p ie len = %hu",
2544  				  vdev_id, p2p_ie, p2p_ie[1]);
2545  			if (wma_p2p_go_set_beacon_ie(wma, vdev_id,
2546  							 p2p_ie) < 0) {
2547  				wma_err("wmi_unified_bcn_tmpl_send Failed");
2548  				status = QDF_STATUS_E_INVAL;
2549  				goto send_rsp;
2550  			}
2551  		}
2552  	}
2553  	status = wma_store_bcn_tmpl(wma, vdev_id, bcn_info);
2554  	if (status != QDF_STATUS_SUCCESS) {
2555  		wma_err("wma_store_bcn_tmpl Failed");
2556  		goto send_rsp;
2557  	}
2558  
2559  send_rsp:
2560  	bcn_info->status = status;
2561  	wma_send_msg(wma, WMA_SEND_BCN_RSP, (void *)bcn_info, 0);
2562  }
2563  
2564  /**
2565   * wma_set_keepalive_req() - send keep alive request to fw
2566   * @wma: wma handle
2567   * @keepalive: keep alive parameters
2568   *
2569   * Return: none
2570   */
wma_set_keepalive_req(tp_wma_handle wma,struct keep_alive_req * keepalive)2571  void wma_set_keepalive_req(tp_wma_handle wma,
2572  			   struct keep_alive_req *keepalive)
2573  {
2574  	wma_nofl_debug("KEEPALIVE:PacketType:%d", keepalive->packetType);
2575  	wma_set_sta_keep_alive(wma, keepalive->sessionId,
2576  			       keepalive->packetType,
2577  			       keepalive->timePeriod,
2578  			       keepalive->hostIpv4Addr,
2579  			       keepalive->destIpv4Addr,
2580  			       keepalive->dest_macaddr.bytes);
2581  
2582  	qdf_mem_free(keepalive);
2583  }
2584  
2585  /**
2586   * wma_beacon_miss_handler() - beacon miss event handler
2587   * @wma: wma handle
2588   * @vdev_id: vdev id
2589   * @rssi: rssi value
2590   *
2591   * This function send beacon miss indication to upper layers.
2592   *
2593   * Return: none
2594   */
wma_beacon_miss_handler(tp_wma_handle wma,uint32_t vdev_id,int32_t rssi)2595  void wma_beacon_miss_handler(tp_wma_handle wma, uint32_t vdev_id, int32_t rssi)
2596  {
2597  	struct missed_beacon_ind *beacon_miss_ind;
2598  	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
2599  
2600  	beacon_miss_ind = qdf_mem_malloc(sizeof(*beacon_miss_ind));
2601  	if (!beacon_miss_ind)
2602  		return;
2603  
2604  	if (mac && mac->sme.tx_queue_cb)
2605  		mac->sme.tx_queue_cb(mac->hdd_handle, vdev_id,
2606  				     WLAN_STOP_ALL_NETIF_QUEUE,
2607  				     WLAN_CONTROL_PATH);
2608  	beacon_miss_ind->messageType = WMA_MISSED_BEACON_IND;
2609  	beacon_miss_ind->length = sizeof(*beacon_miss_ind);
2610  	beacon_miss_ind->bss_idx = vdev_id;
2611  	beacon_miss_ind->rssi = rssi;
2612  
2613  	wma_send_msg(wma, WMA_MISSED_BEACON_IND, beacon_miss_ind, 0);
2614  	if (!wmi_service_enabled(wma->wmi_handle,
2615  				 wmi_service_hw_db2dbm_support))
2616  		rssi += WMA_TGT_NOISE_FLOOR_DBM;
2617  	wma_lost_link_info_handler(wma, vdev_id, rssi);
2618  }
2619  
wlan_cm_send_beacon_miss(uint8_t vdev_id,int32_t rssi)2620  void wlan_cm_send_beacon_miss(uint8_t vdev_id, int32_t rssi)
2621  {
2622  	tp_wma_handle wma;
2623  
2624  	wma = cds_get_context(QDF_MODULE_ID_WMA);
2625  	if (!wma)
2626  		return;
2627  
2628  	wma_beacon_miss_handler(wma, vdev_id, rssi);
2629  }
2630  
2631  /**
2632   * wma_get_status_str() - get string of tx status from firmware
2633   * @status: tx status
2634   *
2635   * Return: converted string of tx status
2636   */
wma_get_status_str(uint32_t status)2637  static const char *wma_get_status_str(uint32_t status)
2638  {
2639  	switch (status) {
2640  	default:
2641  		return "unknown";
2642  	CASE_RETURN_STRING(WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK);
2643  	CASE_RETURN_STRING(WMI_MGMT_TX_COMP_TYPE_DISCARD);
2644  	CASE_RETURN_STRING(WMI_MGMT_TX_COMP_TYPE_INSPECT);
2645  	CASE_RETURN_STRING(WMI_MGMT_TX_COMP_TYPE_COMPLETE_NO_ACK);
2646  	CASE_RETURN_STRING(WMI_MGMT_TX_COMP_TYPE_MAX);
2647  	}
2648  }
2649  
2650  #ifdef CONFIG_HL_SUPPORT
wma_mgmt_unmap_buf(tp_wma_handle wma_handle,qdf_nbuf_t buf)2651  static inline void wma_mgmt_unmap_buf(tp_wma_handle wma_handle, qdf_nbuf_t buf)
2652  {
2653  }
2654  #else
wma_mgmt_unmap_buf(tp_wma_handle wma_handle,qdf_nbuf_t buf)2655  static inline void wma_mgmt_unmap_buf(tp_wma_handle wma_handle, qdf_nbuf_t buf)
2656  {
2657  	qdf_nbuf_unmap_single(wma_handle->qdf_dev, buf, QDF_DMA_TO_DEVICE);
2658  }
2659  #endif
2660  
2661  #if defined(CONNECTIVITY_PKTLOG) || !defined(REMOVE_PKT_LOG)
2662  /**
2663   * wma_mgmt_qdf_status_map() - map MGMT Tx completion status with
2664   * packet dump Tx status
2665   * @status: MGMT Tx completion status
2666   *
2667   * Return: packet dump tx_status enum
2668   */
2669  static inline enum qdf_dp_tx_rx_status
wma_mgmt_qdf_status_map(WMI_MGMT_TX_COMP_STATUS_TYPE status)2670  wma_mgmt_qdf_status_map(WMI_MGMT_TX_COMP_STATUS_TYPE status)
2671  {
2672  	enum qdf_dp_tx_rx_status pktdump_status;
2673  
2674  	switch (status) {
2675  	case WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK:
2676  		pktdump_status = QDF_TX_RX_STATUS_OK;
2677  		break;
2678  	case WMI_MGMT_TX_COMP_TYPE_DISCARD:
2679  		pktdump_status = QDF_TX_RX_STATUS_DROP;
2680  		break;
2681  	case WMI_MGMT_TX_COMP_TYPE_COMPLETE_NO_ACK:
2682  		pktdump_status = QDF_TX_RX_STATUS_NO_ACK;
2683  		break;
2684  	default:
2685  		pktdump_status = QDF_TX_RX_STATUS_DROP;
2686  		break;
2687  	}
2688  	return pktdump_status;
2689  }
2690  
2691  /**
2692   * wma_mgmt_pktdump_tx_handler() - calls tx cb if CONNECTIVITY_PKTLOG
2693   * feature is enabled
2694   * @wma_handle: wma handle
2695   * @buf: nbuf
2696   * @vdev_id : vdev id
2697   * @status : status
2698   *
2699   * Return: none
2700   */
wma_mgmt_pktdump_tx_handler(tp_wma_handle wma_handle,qdf_nbuf_t buf,uint8_t vdev_id,uint32_t status)2701  static inline void wma_mgmt_pktdump_tx_handler(tp_wma_handle wma_handle,
2702  					       qdf_nbuf_t buf, uint8_t vdev_id,
2703  					       uint32_t status)
2704  {
2705  	ol_txrx_pktdump_cb packetdump_cb;
2706  	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
2707  	enum qdf_dp_tx_rx_status pktdump_status;
2708  
2709  	packetdump_cb = wma_handle->wma_mgmt_tx_packetdump_cb;
2710  	pktdump_status = wma_mgmt_qdf_status_map(status);
2711  	if (packetdump_cb)
2712  		packetdump_cb(soc, WMI_PDEV_ID_SOC, vdev_id,
2713  			      buf, pktdump_status, QDF_TX_MGMT_PKT);
2714  }
2715  
2716  /**
2717   * wma_mgmt_pktdump_rx_handler() - calls rx cb if CONNECTIVITY_PKTLOG
2718   * feature is enabled
2719   * @mgmt_rx_params: mgmt rx params
2720   * @rx_pkt: cds packet
2721   * @wma_handle: wma handle
2722   * mgt_type: management type
2723   * mgt_subtype: management subtype
2724   *
2725   * Return: none
2726   */
wma_mgmt_pktdump_rx_handler(struct mgmt_rx_event_params * mgmt_rx_params,cds_pkt_t * rx_pkt,tp_wma_handle wma_handle,uint8_t mgt_type,uint8_t mgt_subtype)2727  static inline void wma_mgmt_pktdump_rx_handler(
2728  			struct mgmt_rx_event_params *mgmt_rx_params,
2729  			cds_pkt_t *rx_pkt, tp_wma_handle wma_handle,
2730  			uint8_t mgt_type, uint8_t mgt_subtype)
2731  {
2732  	ol_txrx_pktdump_cb packetdump_cb;
2733  	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
2734  
2735  	packetdump_cb = wma_handle->wma_mgmt_rx_packetdump_cb;
2736  	if ((mgt_type == IEEE80211_FC0_TYPE_MGT &&
2737  	     mgt_subtype != MGMT_SUBTYPE_BEACON) &&
2738  	     packetdump_cb)
2739  		packetdump_cb(soc, mgmt_rx_params->pdev_id,
2740  			      rx_pkt->pkt_meta.session_id, rx_pkt->pkt_buf,
2741  			      QDF_TX_RX_STATUS_OK, QDF_RX_MGMT_PKT);
2742  }
2743  
2744  #else
wma_mgmt_pktdump_tx_handler(tp_wma_handle wma_handle,qdf_nbuf_t buf,uint8_t vdev_id,uint32_t status)2745  static inline void wma_mgmt_pktdump_tx_handler(tp_wma_handle wma_handle,
2746  					       qdf_nbuf_t buf, uint8_t vdev_id,
2747  					       uint32_t status)
2748  {
2749  }
2750  
wma_mgmt_pktdump_rx_handler(struct mgmt_rx_event_params * mgmt_rx_params,cds_pkt_t * rx_pkt,tp_wma_handle wma_handle,uint8_t mgt_type,uint8_t mgt_subtype)2751  static inline void wma_mgmt_pktdump_rx_handler(
2752  			struct mgmt_rx_event_params *mgmt_rx_params,
2753  			cds_pkt_t *rx_pkt, tp_wma_handle wma_handle,
2754  			uint8_t mgt_type, uint8_t mgt_subtype)
2755  {
2756  }
2757  #endif
2758  
2759  /**
2760   * wma_process_mgmt_tx_completion() - process mgmt completion
2761   * @wma_handle: wma handle
2762   * @desc_id: descriptor id
2763   * @status: status
2764   *
2765   * Return: 0 for success or error code
2766   */
wma_process_mgmt_tx_completion(tp_wma_handle wma_handle,uint32_t desc_id,uint32_t status)2767  static int wma_process_mgmt_tx_completion(tp_wma_handle wma_handle,
2768  					  uint32_t desc_id, uint32_t status)
2769  {
2770  	struct wlan_objmgr_pdev *pdev;
2771  	qdf_nbuf_t buf = NULL;
2772  	QDF_STATUS ret;
2773  	uint8_t vdev_id = 0;
2774  	struct wmi_mgmt_params mgmt_params = {};
2775  
2776  	if (wma_validate_handle(wma_handle))
2777  		return -EINVAL;
2778  
2779  	wma_debug("status: %s wmi_desc_id: %d",
2780  		  wma_get_status_str(status), desc_id);
2781  
2782  	pdev = wma_handle->pdev;
2783  	if (!pdev) {
2784  		wma_err("psoc ptr is NULL");
2785  		return -EINVAL;
2786  	}
2787  
2788  	buf = mgmt_txrx_get_nbuf(pdev, desc_id);
2789  
2790  
2791  	if (buf)
2792  		wma_mgmt_unmap_buf(wma_handle, buf);
2793  
2794  	vdev_id = mgmt_txrx_get_vdev_id(pdev, desc_id);
2795  	mgmt_params.vdev_id = vdev_id;
2796  
2797  	wma_mgmt_pktdump_tx_handler(wma_handle, buf, vdev_id, status);
2798  	ret = mgmt_txrx_tx_completion_handler(pdev, desc_id, status,
2799  					      &mgmt_params);
2800  
2801  	if (ret != QDF_STATUS_SUCCESS) {
2802  		wma_err("Failed to process mgmt tx completion");
2803  		return -EINVAL;
2804  	}
2805  
2806  	return 0;
2807  }
2808  
2809  /**
2810   * wma_extract_mgmt_offload_event_params() - Extract mgmt event params
2811   * @params: Management offload event params
2812   * @hdr: Management header to extract
2813   *
2814   * Return: None
2815   */
wma_extract_mgmt_offload_event_params(struct mgmt_offload_event_params * params,wmi_mgmt_hdr * hdr)2816  static void wma_extract_mgmt_offload_event_params(
2817  				struct mgmt_offload_event_params *params,
2818  				wmi_mgmt_hdr *hdr)
2819  {
2820  	params->tsf_l32 = hdr->tsf_l32;
2821  	params->chan_freq = hdr->chan_freq;
2822  	params->rate_kbps = hdr->rate_kbps;
2823  	params->rssi = hdr->rssi;
2824  	params->buf_len = hdr->buf_len;
2825  	params->tx_status = hdr->tx_status;
2826  	params->tx_retry_cnt = hdr->tx_retry_cnt;
2827  }
2828  
2829  /**
2830   * wma_mgmt_tx_completion_handler() - wma mgmt Tx completion event handler
2831   * @handle: wma handle
2832   * @cmpl_event_params: completion event handler data
2833   * @len: length of @cmpl_event_params
2834   *
2835   * Return: 0 on success; error number otherwise
2836   */
2837  
wma_mgmt_tx_completion_handler(void * handle,uint8_t * cmpl_event_params,uint32_t len)2838  int wma_mgmt_tx_completion_handler(void *handle, uint8_t *cmpl_event_params,
2839  				   uint32_t len)
2840  {
2841  	tp_wma_handle wma_handle = (tp_wma_handle)handle;
2842  	WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *param_buf;
2843  	wmi_mgmt_tx_compl_event_fixed_param *cmpl_params;
2844  
2845  	param_buf = (WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *)
2846  		cmpl_event_params;
2847  	if (!param_buf || !wma_handle) {
2848  		wma_err("Invalid mgmt Tx completion event");
2849  		return -EINVAL;
2850  	}
2851  	cmpl_params = param_buf->fixed_param;
2852  
2853  	if ((ucfg_pkt_capture_get_pktcap_mode(wma_handle->psoc) &
2854  	    PKT_CAPTURE_MODE_MGMT_ONLY) && param_buf->mgmt_hdr) {
2855  		struct mgmt_offload_event_params params = {0};
2856  
2857  		wma_extract_mgmt_offload_event_params(
2858  					&params,
2859  					(wmi_mgmt_hdr *)param_buf->mgmt_hdr);
2860  		ucfg_pkt_capture_mgmt_tx_completion(wma_handle->pdev,
2861  						    cmpl_params->desc_id,
2862  						    cmpl_params->status,
2863  						    &params);
2864  	}
2865  
2866  	wma_process_mgmt_tx_completion(wma_handle, cmpl_params->desc_id,
2867  				       cmpl_params->status);
2868  
2869  	return 0;
2870  }
2871  
2872  /**
2873   * wma_mgmt_tx_bundle_completion_handler() - mgmt bundle comp handler
2874   * @handle: wma handle
2875   * @buf: buffer
2876   * @len: length
2877   *
2878   * Return: 0 for success or error code
2879   */
wma_mgmt_tx_bundle_completion_handler(void * handle,uint8_t * buf,uint32_t len)2880  int wma_mgmt_tx_bundle_completion_handler(void *handle, uint8_t *buf,
2881  				   uint32_t len)
2882  {
2883  	tp_wma_handle wma_handle = (tp_wma_handle)handle;
2884  	WMI_MGMT_TX_BUNDLE_COMPLETION_EVENTID_param_tlvs *param_buf;
2885  	wmi_mgmt_tx_compl_bundle_event_fixed_param	*cmpl_params;
2886  	uint32_t num_reports;
2887  	uint32_t *desc_ids;
2888  	uint32_t *status;
2889  	uint32_t i, buf_len;
2890  	bool excess_data = false;
2891  
2892  	param_buf = (WMI_MGMT_TX_BUNDLE_COMPLETION_EVENTID_param_tlvs *)buf;
2893  	if (!param_buf || !wma_handle) {
2894  		wma_err("Invalid mgmt Tx completion event");
2895  		return -EINVAL;
2896  	}
2897  	cmpl_params = param_buf->fixed_param;
2898  	num_reports = cmpl_params->num_reports;
2899  	desc_ids = (uint32_t *)(param_buf->desc_ids);
2900  	status = (uint32_t *)(param_buf->status);
2901  
2902  	/* buf contains num_reports * sizeof(uint32) len of desc_ids and
2903  	 * num_reports * sizeof(uint32) status,
2904  	 * so (2 x (num_reports * sizeof(uint32)) should not exceed MAX
2905  	 */
2906  	if (cmpl_params->num_reports > (WMI_SVC_MSG_MAX_SIZE /
2907  	    (2 * sizeof(uint32_t))))
2908  		excess_data = true;
2909  	else
2910  		buf_len = cmpl_params->num_reports * (2 * sizeof(uint32_t));
2911  
2912  	if (excess_data || (sizeof(*cmpl_params) > (WMI_SVC_MSG_MAX_SIZE -
2913  	    buf_len))) {
2914  		wma_err("excess wmi buffer: num_reports %d",
2915  			cmpl_params->num_reports);
2916  		return -EINVAL;
2917  	}
2918  
2919  	if ((cmpl_params->num_reports > param_buf->num_desc_ids) ||
2920  	    (cmpl_params->num_reports > param_buf->num_status)) {
2921  		wma_err("Invalid num_reports %d, num_desc_ids %d, num_status %d",
2922  			 cmpl_params->num_reports, param_buf->num_desc_ids,
2923  			 param_buf->num_status);
2924  		return -EINVAL;
2925  	}
2926  
2927  	for (i = 0; i < num_reports; i++) {
2928  		if ((ucfg_pkt_capture_get_pktcap_mode(wma_handle->psoc) &
2929  		    PKT_CAPTURE_MODE_MGMT_ONLY) && param_buf->mgmt_hdr) {
2930  			struct mgmt_offload_event_params params = {0};
2931  
2932  			wma_extract_mgmt_offload_event_params(
2933  				&params,
2934  				&((wmi_mgmt_hdr *)param_buf->mgmt_hdr)[i]);
2935  			ucfg_pkt_capture_mgmt_tx_completion(
2936  				wma_handle->pdev, desc_ids[i],
2937  				status[i], &params);
2938  		}
2939  
2940  		wma_process_mgmt_tx_completion(wma_handle,
2941  					       desc_ids[i], status[i]);
2942  	}
2943  	return 0;
2944  }
2945  
2946  /**
2947   * wma_process_update_opmode() - process update VHT opmode cmd from UMAC
2948   * @wma_handle: wma handle
2949   * @update_vht_opmode: vht opmode
2950   *
2951   * Return: none
2952   */
wma_process_update_opmode(tp_wma_handle wma_handle,tUpdateVHTOpMode * update_vht_opmode)2953  void wma_process_update_opmode(tp_wma_handle wma_handle,
2954  			       tUpdateVHTOpMode *update_vht_opmode)
2955  {
2956  	wmi_host_channel_width ch_width;
2957  	uint8_t pdev_id;
2958  	struct wlan_objmgr_peer *peer;
2959  	struct wlan_objmgr_psoc *psoc = wma_handle->psoc;
2960  	enum wlan_phymode peer_phymode;
2961  	uint32_t fw_phymode;
2962  	enum wlan_peer_type peer_type;
2963  
2964  	pdev_id = wlan_objmgr_pdev_get_pdev_id(wma_handle->pdev);
2965  	peer = wlan_objmgr_get_peer(psoc, pdev_id,
2966  				    update_vht_opmode->peer_mac,
2967  				    WLAN_LEGACY_WMA_ID);
2968  	if (!peer) {
2969  		wma_err("peer object invalid");
2970  		return;
2971  	}
2972  
2973  	peer_type = wlan_peer_get_peer_type(peer);
2974  	if (peer_type == WLAN_PEER_SELF) {
2975  		wma_err("self peer wrongly used");
2976  		wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
2977  		return;
2978  	}
2979  
2980  	wlan_peer_obj_lock(peer);
2981  	peer_phymode = wlan_peer_get_phymode(peer);
2982  	wlan_peer_obj_unlock(peer);
2983  	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
2984  
2985  	fw_phymode = wmi_host_to_fw_phymode(peer_phymode);
2986  
2987  	ch_width = wmi_get_ch_width_from_phy_mode(wma_handle->wmi_handle,
2988  						  fw_phymode);
2989  	wma_debug("ch_width: %d, fw phymode: %d peer_phymode: %d, op_mode: %d",
2990  		  ch_width, fw_phymode, peer_phymode,
2991  		  update_vht_opmode->opMode);
2992  
2993  	if (ch_width < update_vht_opmode->opMode) {
2994  		wma_err("Invalid peer bw update %d, self bw %d",
2995  			update_vht_opmode->opMode, ch_width);
2996  		return;
2997  	}
2998  
2999  	wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac,
3000  			   WMI_HOST_PEER_CHWIDTH, update_vht_opmode->opMode,
3001  			   update_vht_opmode->smesessionId);
3002  
3003  	wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac,
3004  			   WMI_HOST_PEER_PHYMODE,
3005  			   fw_phymode, update_vht_opmode->smesessionId);
3006  }
3007  
3008  /**
3009   * wma_process_update_rx_nss() - process update RX NSS cmd from UMAC
3010   * @wma_handle: wma handle
3011   * @update_rx_nss: rx nss value
3012   *
3013   * Return: none
3014   */
wma_process_update_rx_nss(tp_wma_handle wma_handle,tUpdateRxNss * update_rx_nss)3015  void wma_process_update_rx_nss(tp_wma_handle wma_handle,
3016  			       tUpdateRxNss *update_rx_nss)
3017  {
3018  	struct target_psoc_info *tgt_hdl;
3019  	struct wma_txrx_node *intr =
3020  		&wma_handle->interfaces[update_rx_nss->smesessionId];
3021  	int rx_nss = update_rx_nss->rxNss;
3022  	int num_rf_chains;
3023  
3024  	tgt_hdl = wlan_psoc_get_tgt_if_handle(wma_handle->psoc);
3025  	if (!tgt_hdl) {
3026  		wma_err("target psoc info is NULL");
3027  		return;
3028  	}
3029  
3030  	num_rf_chains = target_if_get_num_rf_chains(tgt_hdl);
3031  	if (rx_nss > num_rf_chains || rx_nss > WMA_MAX_NSS)
3032  		rx_nss = QDF_MIN(num_rf_chains, WMA_MAX_NSS);
3033  
3034  	intr->nss = (uint8_t)rx_nss;
3035  	update_rx_nss->rxNss = (uint32_t)rx_nss;
3036  
3037  	wma_debug("Rx Nss = %d", update_rx_nss->rxNss);
3038  
3039  	wma_set_peer_param(wma_handle, update_rx_nss->peer_mac,
3040  			   WMI_HOST_PEER_NSS, update_rx_nss->rxNss,
3041  			   update_rx_nss->smesessionId);
3042  }
3043  
3044  /**
3045   * wma_process_update_membership() - process update group membership cmd
3046   * @wma_handle: wma handle
3047   * @membership: group membership info
3048   *
3049   * Return: none
3050   */
wma_process_update_membership(tp_wma_handle wma_handle,tUpdateMembership * membership)3051  void wma_process_update_membership(tp_wma_handle wma_handle,
3052  				   tUpdateMembership *membership)
3053  {
3054  	wma_debug("membership = %x ", membership->membership);
3055  
3056  	wma_set_peer_param(wma_handle, membership->peer_mac,
3057  			   WMI_HOST_PEER_MEMBERSHIP, membership->membership,
3058  			   membership->smesessionId);
3059  }
3060  
3061  /**
3062   * wma_process_update_userpos() - process update user pos cmd from UMAC
3063   * @wma_handle: wma handle
3064   * @userpos: user pos value
3065   *
3066   * Return: none
3067   */
wma_process_update_userpos(tp_wma_handle wma_handle,tUpdateUserPos * userpos)3068  void wma_process_update_userpos(tp_wma_handle wma_handle,
3069  				tUpdateUserPos *userpos)
3070  {
3071  	wma_debug("userPos = %x ", userpos->userPos);
3072  
3073  	wma_set_peer_param(wma_handle, userpos->peer_mac,
3074  			   WMI_HOST_PEER_USERPOS, userpos->userPos,
3075  			   userpos->smesessionId);
3076  
3077  	/* Now that membership/userpos is updated in fw,
3078  	 * enable GID PPS.
3079  	 */
3080  	wma_set_ppsconfig(userpos->smesessionId, WMA_VHT_PPS_GID_MATCH, 1);
3081  
3082  }
3083  
wma_set_cts2self_for_p2p_go(void * wma_handle,uint32_t cts2self_for_p2p_go)3084  QDF_STATUS wma_set_cts2self_for_p2p_go(void *wma_handle,
3085  				    uint32_t cts2self_for_p2p_go)
3086  {
3087  	int32_t ret;
3088  	tp_wma_handle wma = (tp_wma_handle)wma_handle;
3089  	struct pdev_params pdevparam = {};
3090  
3091  	pdevparam.param_id = wmi_pdev_param_cts2self_for_p2p_go_config;
3092  	pdevparam.param_value = cts2self_for_p2p_go;
3093  
3094  	ret = wmi_unified_pdev_param_send(wma->wmi_handle,
3095  			&pdevparam,
3096  			WMA_WILDCARD_PDEV_ID);
3097  	if (ret) {
3098  		wma_err("Fail to Set CTS2SELF for p2p GO %d",
3099  			cts2self_for_p2p_go);
3100  		return QDF_STATUS_E_FAILURE;
3101  	}
3102  
3103  	wma_nofl_debug("Successfully Set CTS2SELF for p2p GO %d",
3104  		       cts2self_for_p2p_go);
3105  
3106  	return QDF_STATUS_SUCCESS;
3107  }
3108  
3109  
3110  /**
3111   * wma_set_htconfig() - set ht config parameters to target
3112   * @vdev_id: vdev id
3113   * @ht_capab: ht capability
3114   * @value: value of ht param
3115   *
3116   * Return: QDF status
3117   */
wma_set_htconfig(uint8_t vdev_id,uint16_t ht_capab,int value)3118  QDF_STATUS wma_set_htconfig(uint8_t vdev_id, uint16_t ht_capab, int value)
3119  {
3120  	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
3121  	QDF_STATUS ret = QDF_STATUS_E_FAILURE;
3122  
3123  	if (!wma)
3124  		return QDF_STATUS_E_INVAL;
3125  
3126  	switch (ht_capab) {
3127  	case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING:
3128  		ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
3129  						      wmi_vdev_param_ldpc,
3130  						      value);
3131  		break;
3132  	case WNI_CFG_HT_CAP_INFO_TX_STBC:
3133  		ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
3134  						      wmi_vdev_param_tx_stbc,
3135  						      value);
3136  		break;
3137  	case WNI_CFG_HT_CAP_INFO_RX_STBC:
3138  		ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
3139  						      wmi_vdev_param_rx_stbc,
3140  						      value);
3141  		break;
3142  	case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ:
3143  	case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ:
3144  		wma_err("ht_capab = %d, value = %d", ht_capab,
3145  			 value);
3146  		ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
3147  						wmi_vdev_param_sgi, value);
3148  		if (ret == QDF_STATUS_SUCCESS)
3149  			wma->interfaces[vdev_id].config.shortgi = value;
3150  		break;
3151  	default:
3152  		wma_err("INVALID HT CONFIG");
3153  	}
3154  
3155  	return ret;
3156  }
3157  
3158  /**
3159   * wma_extract_ccmp_pn() - extract 6 byte PN from the CCMP header
3160   * @ccmp_ptr: CCMP header
3161   *
3162   * Return: PN extracted from header.
3163   */
wma_extract_ccmp_pn(uint8_t * ccmp_ptr)3164  static uint64_t wma_extract_ccmp_pn(uint8_t *ccmp_ptr)
3165  {
3166  	uint8_t rsvd, key, pn[6];
3167  	uint64_t new_pn;
3168  
3169  	/*
3170  	 *   +-----+-----+------+----------+-----+-----+-----+-----+
3171  	 *   | PN0 | PN1 | rsvd | rsvd/key | PN2 | PN3 | PN4 | PN5 |
3172  	 *   +-----+-----+------+----------+-----+-----+-----+-----+
3173  	 *                   CCMP Header Format
3174  	 */
3175  
3176  	/* Extract individual bytes */
3177  	pn[0] = (uint8_t) *ccmp_ptr;
3178  	pn[1] = (uint8_t) *(ccmp_ptr + 1);
3179  	rsvd = (uint8_t) *(ccmp_ptr + 2);
3180  	key = (uint8_t) *(ccmp_ptr + 3);
3181  	pn[2] = (uint8_t) *(ccmp_ptr + 4);
3182  	pn[3] = (uint8_t) *(ccmp_ptr + 5);
3183  	pn[4] = (uint8_t) *(ccmp_ptr + 6);
3184  	pn[5] = (uint8_t) *(ccmp_ptr + 7);
3185  
3186  	/* Form 6 byte PN with 6 individual bytes of PN */
3187  	new_pn = ((uint64_t) pn[5] << 40) |
3188  		 ((uint64_t) pn[4] << 32) |
3189  		 ((uint64_t) pn[3] << 24) |
3190  		 ((uint64_t) pn[2] << 16) |
3191  		 ((uint64_t) pn[1] << 8) | ((uint64_t) pn[0] << 0);
3192  
3193  	return new_pn;
3194  }
3195  
3196  /**
3197   * wma_is_ccmp_pn_replay_attack() - detect replay attacking using PN in CCMP
3198   * @wma: wma context
3199   * @wh: 802.11 frame header
3200   * @ccmp_ptr: CCMP frame header
3201   *
3202   * Return: true/false
3203   */
3204  static bool
wma_is_ccmp_pn_replay_attack(tp_wma_handle wma,struct ieee80211_frame * wh,uint8_t * ccmp_ptr)3205  wma_is_ccmp_pn_replay_attack(tp_wma_handle wma, struct ieee80211_frame *wh,
3206  			     uint8_t *ccmp_ptr)
3207  {
3208  	uint64_t new_pn;
3209  	bool ret = false;
3210  	struct peer_mlme_priv_obj *peer_priv;
3211  	struct wlan_objmgr_peer *peer;
3212  
3213  	new_pn = wma_extract_ccmp_pn(ccmp_ptr);
3214  
3215  	peer = wlan_objmgr_get_peer_by_mac(wma->psoc, wh->i_addr2,
3216  					   WLAN_LEGACY_WMA_ID);
3217  	if (!peer)
3218  		return ret;
3219  
3220  	peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
3221  							  WLAN_UMAC_COMP_MLME);
3222  	if (!peer_priv) {
3223  		wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
3224  		return ret;
3225  	}
3226  
3227  	if (peer_priv->last_pn_valid) {
3228  		if (new_pn > peer_priv->last_pn) {
3229  			peer_priv->last_pn = new_pn;
3230  		} else {
3231  			wma_err_rl("PN Replay attack detected");
3232  			/* per 11W amendment, keeping track of replay attacks */
3233  			peer_priv->rmf_pn_replays += 1;
3234  			ret = true;
3235  		}
3236  	} else {
3237  		peer_priv->last_pn_valid = 1;
3238  		peer_priv->last_pn = new_pn;
3239  	}
3240  
3241  	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
3242  
3243  	return ret;
3244  }
3245  
3246  /**
3247   * wma_process_bip() - process mmie in rmf frame
3248   * @wma_handle: wma handle
3249   * @iface: txrx node
3250   * @wh: 80211 frame
3251   * @wbuf: Buffer
3252   *
3253   * Return: 0 for success or error code
3254   */
3255  static
wma_process_bip(tp_wma_handle wma_handle,struct wma_txrx_node * iface,struct ieee80211_frame * wh,qdf_nbuf_t wbuf)3256  int wma_process_bip(tp_wma_handle wma_handle, struct wma_txrx_node *iface,
3257  		    struct ieee80211_frame *wh, qdf_nbuf_t wbuf)
3258  {
3259  	uint16_t mmie_size;
3260  	uint8_t *efrm;
3261  	int32_t mgmtcipherset;
3262  	enum wlan_crypto_cipher_type key_cipher;
3263  
3264  	efrm = qdf_nbuf_data(wbuf) + qdf_nbuf_len(wbuf);
3265  
3266  	mgmtcipherset = wlan_crypto_get_param(iface->vdev,
3267  					      WLAN_CRYPTO_PARAM_MGMT_CIPHER);
3268  	if (mgmtcipherset <= 0) {
3269  		wma_err("Invalid key cipher %d", mgmtcipherset);
3270  		return -EINVAL;
3271  	}
3272  
3273  	if (mgmtcipherset & (1 << WLAN_CRYPTO_CIPHER_AES_CMAC)) {
3274  		key_cipher = WLAN_CRYPTO_CIPHER_AES_CMAC;
3275  		mmie_size = cds_get_mmie_size();
3276  	} else if (mgmtcipherset & (1 << WLAN_CRYPTO_CIPHER_AES_GMAC)) {
3277  		key_cipher = WLAN_CRYPTO_CIPHER_AES_GMAC;
3278  		mmie_size = cds_get_gmac_mmie_size();
3279  	} else if (mgmtcipherset & (1 << WLAN_CRYPTO_CIPHER_AES_GMAC_256)) {
3280  		key_cipher = WLAN_CRYPTO_CIPHER_AES_GMAC_256;
3281  		mmie_size = cds_get_gmac_mmie_size();
3282  	} else {
3283  		wma_err("Invalid key cipher %d", mgmtcipherset);
3284  		return -EINVAL;
3285  	}
3286  
3287  	/* Check if frame is invalid length */
3288  	if (efrm - (uint8_t *)wh < sizeof(*wh) + mmie_size) {
3289  		wma_err("Invalid frame length");
3290  		return -EINVAL;
3291  	}
3292  
3293  	switch (key_cipher) {
3294  	case WLAN_CRYPTO_CIPHER_AES_CMAC:
3295  		if (!wmi_service_enabled(wma_handle->wmi_handle,
3296  					 wmi_service_sta_pmf_offload)) {
3297  			if (!wlan_crypto_is_mmie_valid(iface->vdev,
3298  						       (uint8_t *)wh, efrm)) {
3299  				wma_debug("BC/MC MIC error or MMIE not present, dropping the frame");
3300  				return -EINVAL;
3301  			}
3302  		}
3303  		break;
3304  	case WLAN_CRYPTO_CIPHER_AES_GMAC:
3305  	case WLAN_CRYPTO_CIPHER_AES_GMAC_256:
3306  		if (!wmi_service_enabled(wma_handle->wmi_handle,
3307  					 wmi_service_gmac_offload_support)) {
3308  			if (!wlan_crypto_is_mmie_valid(iface->vdev,
3309  						       (uint8_t *)wh, efrm)) {
3310  				wma_debug("BC/MC GMAC MIC error or MMIE not present, dropping the frame");
3311  				return -EINVAL;
3312  			}
3313  		}
3314  		break;
3315  	default:
3316  		wma_err("Invalid key_type %d", key_cipher);
3317  		return -EINVAL;
3318  	}
3319  
3320  	qdf_nbuf_trim_tail(wbuf, mmie_size);
3321  
3322  	return 0;
3323  }
3324  
3325  /**
3326   * wma_process_rmf_frame() - process rmf frame
3327   * @wma_handle: wma handle
3328   * @iface: txrx node
3329   * @wh: 80211 frame
3330   * @rx_pkt: rx packet
3331   * @wbuf: Buffer
3332   *
3333   * Return: 0 for success or error code
3334   */
3335  static
wma_process_rmf_frame(tp_wma_handle wma_handle,struct wma_txrx_node * iface,struct ieee80211_frame * wh,cds_pkt_t * rx_pkt,qdf_nbuf_t wbuf)3336  int wma_process_rmf_frame(tp_wma_handle wma_handle,
3337  	struct wma_txrx_node *iface,
3338  	struct ieee80211_frame *wh,
3339  	cds_pkt_t *rx_pkt,
3340  	qdf_nbuf_t wbuf)
3341  {
3342  	uint8_t *orig_hdr;
3343  	uint8_t *ccmp;
3344  	uint8_t mic_len, hdr_len, pdev_id;
3345  	QDF_STATUS status;
3346  
3347  	if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) {
3348  		if (QDF_IS_ADDR_BROADCAST(wh->i_addr1) ||
3349  		    IEEE80211_IS_MULTICAST(wh->i_addr1)) {
3350  			wma_err("Encrypted BC/MC frame dropping the frame");
3351  			cds_pkt_return_packet(rx_pkt);
3352  			return -EINVAL;
3353  		}
3354  
3355  		if (iface->type == WMI_VDEV_TYPE_NDI ||
3356  		    iface->type == WMI_VDEV_TYPE_NAN) {
3357  			hdr_len = IEEE80211_CCMP_HEADERLEN;
3358  			mic_len = IEEE80211_CCMP_MICLEN;
3359  		} else {
3360  			pdev_id =
3361  				wlan_objmgr_pdev_get_pdev_id(wma_handle->pdev);
3362  			status = mlme_get_peer_mic_len(wma_handle->psoc,
3363  						       pdev_id, wh->i_addr2,
3364  						       &mic_len, &hdr_len);
3365  			if (QDF_IS_STATUS_ERROR(status)) {
3366  				wma_err("Failed to get mic hdr and length");
3367  				cds_pkt_return_packet(rx_pkt);
3368  				return -EINVAL;
3369  			}
3370  		}
3371  
3372  		if (qdf_nbuf_len(wbuf) < (sizeof(*wh) + hdr_len + mic_len)) {
3373  			wma_err("Buffer length less than expected %d",
3374  				 (int)qdf_nbuf_len(wbuf));
3375  			cds_pkt_return_packet(rx_pkt);
3376  			return -EINVAL;
3377  		}
3378  
3379  		orig_hdr = (uint8_t *) qdf_nbuf_data(wbuf);
3380  		/* Pointer to head of CCMP header */
3381  		ccmp = orig_hdr + sizeof(*wh);
3382  		if (wma_is_ccmp_pn_replay_attack(wma_handle, wh, ccmp)) {
3383  			wma_err_rl("Dropping the frame");
3384  			cds_pkt_return_packet(rx_pkt);
3385  			return -EINVAL;
3386  		}
3387  
3388  		/* Strip privacy headers (and trailer)
3389  		 * for a received frame
3390  		 */
3391  		qdf_mem_move(orig_hdr +
3392  			hdr_len, wh,
3393  			sizeof(*wh));
3394  		qdf_nbuf_pull_head(wbuf,
3395  			hdr_len);
3396  		qdf_nbuf_trim_tail(wbuf, mic_len);
3397  		/*
3398  		 * CCMP header has been pulled off
3399  		 * reinitialize the start pointer of mac header
3400  		 * to avoid accessing incorrect address
3401  		 */
3402  		wh = (struct ieee80211_frame *) qdf_nbuf_data(wbuf);
3403  		rx_pkt->pkt_meta.mpdu_hdr_ptr =
3404  				qdf_nbuf_data(wbuf);
3405  		rx_pkt->pkt_meta.mpdu_len = qdf_nbuf_len(wbuf);
3406  		rx_pkt->pkt_buf = wbuf;
3407  		if (rx_pkt->pkt_meta.mpdu_len >=
3408  			rx_pkt->pkt_meta.mpdu_hdr_len) {
3409  			rx_pkt->pkt_meta.mpdu_data_len =
3410  				rx_pkt->pkt_meta.mpdu_len -
3411  				rx_pkt->pkt_meta.mpdu_hdr_len;
3412  		} else {
3413  			wma_err("mpdu len %d less than hdr %d, dropping frame",
3414  				rx_pkt->pkt_meta.mpdu_len,
3415  				rx_pkt->pkt_meta.mpdu_hdr_len);
3416  			cds_pkt_return_packet(rx_pkt);
3417  			return -EINVAL;
3418  		}
3419  
3420  		if (rx_pkt->pkt_meta.mpdu_data_len > MAX_MGMT_MPDU_LEN) {
3421  			wma_err("Data Len %d greater than max, dropping frame",
3422  				rx_pkt->pkt_meta.mpdu_data_len);
3423  			cds_pkt_return_packet(rx_pkt);
3424  			return -EINVAL;
3425  		}
3426  		rx_pkt->pkt_meta.mpdu_data_ptr =
3427  		rx_pkt->pkt_meta.mpdu_hdr_ptr +
3428  		rx_pkt->pkt_meta.mpdu_hdr_len;
3429  		wma_debug("BSSID: "QDF_MAC_ADDR_FMT" tsf_delta: %u",
3430  			  QDF_MAC_ADDR_REF(wh->i_addr3),
3431  			  rx_pkt->pkt_meta.tsf_delta);
3432  	} else {
3433  		if (QDF_IS_ADDR_BROADCAST(wh->i_addr1) ||
3434  		    IEEE80211_IS_MULTICAST(wh->i_addr1)) {
3435  			if (0 != wma_process_bip(wma_handle, iface, wh, wbuf)) {
3436  				cds_pkt_return_packet(rx_pkt);
3437  				return -EINVAL;
3438  			}
3439  		} else {
3440  			wma_err_rl("Rx unprotected unicast mgmt frame");
3441  			rx_pkt->pkt_meta.dpuFeedback =
3442  				DPU_FEEDBACK_UNPROTECTED_ERROR;
3443  		}
3444  	}
3445  	return 0;
3446  }
3447  
3448  /**
3449   * wma_get_peer_pmf_status() - Get the PMF capability of peer
3450   * @wma: wma handle
3451   * @peer_mac: peer mac addr
3452   *
3453   * Return: True if PMF is enabled, false otherwise.
3454   */
3455  static bool
wma_get_peer_pmf_status(tp_wma_handle wma,uint8_t * peer_mac)3456  wma_get_peer_pmf_status(tp_wma_handle wma, uint8_t *peer_mac)
3457  {
3458  	struct wlan_objmgr_peer *peer;
3459  	bool is_pmf_enabled;
3460  
3461  	if (!peer_mac) {
3462  		wma_err("peer_mac is NULL");
3463  		return false;
3464  	}
3465  
3466  	peer = wlan_objmgr_get_peer(wma->psoc,
3467  				    wlan_objmgr_pdev_get_pdev_id(wma->pdev),
3468  				    peer_mac, WLAN_LEGACY_WMA_ID);
3469  	if (!peer) {
3470  		wma_debug("Peer of peer_mac " QDF_MAC_ADDR_FMT " not found",
3471  			  QDF_MAC_ADDR_REF(peer_mac));
3472  		return false;
3473  	}
3474  	is_pmf_enabled = mlme_get_peer_pmf_status(peer);
3475  	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
3476  	wma_nofl_debug("get is_pmf_enabled %d for "QDF_MAC_ADDR_FMT,
3477  		       is_pmf_enabled, QDF_MAC_ADDR_REF(peer_mac));
3478  
3479  	return is_pmf_enabled;
3480  }
3481  
3482  /**
3483   * wma_check_and_process_rmf_frame() - Process the frame if it is of rmf type
3484   * @wma_handle: wma handle
3485   * @vdev_id: vdev id
3486   * @wh: double pointer to 802.11 frame header which will be updated if the
3487   *	frame is of rmf type.
3488   * @rx_pkt: rx packet
3489   * @buf: Buffer
3490   *
3491   * Process the frame as rmf frame only if both DUT and peer are of PMF capable
3492   *
3493   * Return: 0 for success or error code
3494   */
3495  static int
wma_check_and_process_rmf_frame(tp_wma_handle wma_handle,uint8_t vdev_id,struct ieee80211_frame ** wh,cds_pkt_t * rx_pkt,qdf_nbuf_t buf)3496  wma_check_and_process_rmf_frame(tp_wma_handle wma_handle,
3497  				uint8_t vdev_id,
3498  				struct ieee80211_frame **wh,
3499  				cds_pkt_t *rx_pkt,
3500  				qdf_nbuf_t buf)
3501  {
3502  	int status;
3503  	struct wma_txrx_node *iface;
3504  	struct ieee80211_frame *hdr = *wh;
3505  
3506  	iface = &(wma_handle->interfaces[vdev_id]);
3507  	if ((iface->type != WMI_VDEV_TYPE_NDI &&
3508  	     iface->type != WMI_VDEV_TYPE_NAN) && !iface->rmfEnabled)
3509  		return 0;
3510  
3511  	if (qdf_is_macaddr_group((struct qdf_mac_addr *)(hdr->i_addr1)) ||
3512  	    qdf_is_macaddr_broadcast((struct qdf_mac_addr *)(hdr->i_addr1)) ||
3513  	    wma_get_peer_pmf_status(wma_handle, hdr->i_addr2) ||
3514  	    ((iface->type == WMI_VDEV_TYPE_NDI ||
3515  	      iface->type == WMI_VDEV_TYPE_NAN) &&
3516  	     (hdr->i_fc[1] & IEEE80211_FC1_WEP))) {
3517  		status = wma_process_rmf_frame(wma_handle, iface, hdr,
3518  					       rx_pkt, buf);
3519  		if (status)
3520  			return status;
3521  		/*
3522  		 * CCMP header might have been pulled off reinitialize the
3523  		 * start pointer of mac header
3524  		 */
3525  		*wh = (struct ieee80211_frame *)qdf_nbuf_data(buf);
3526  	}
3527  
3528  	return 0;
3529  }
3530  
3531  /**
3532   * wma_is_pkt_drop_candidate() - check if the mgmt frame should be dropped
3533   * @wma_handle: wma handle
3534   * @peer_addr: peer MAC address
3535   * @bssid: BSSID Address
3536   * @subtype: Management frame subtype
3537   *
3538   * This function is used to decide if a particular management frame should be
3539   * dropped to prevent DOS attack. Timestamp is used to decide the DOS attack.
3540   *
3541   * Return: true if the packet should be dropped and false otherwise
3542   */
wma_is_pkt_drop_candidate(tp_wma_handle wma_handle,uint8_t * peer_addr,uint8_t * bssid,uint8_t subtype)3543  static bool wma_is_pkt_drop_candidate(tp_wma_handle wma_handle,
3544  				      uint8_t *peer_addr, uint8_t *bssid,
3545  				      uint8_t subtype)
3546  {
3547  	bool should_drop = false;
3548  	uint8_t nan_addr[] = {0x50, 0x6F, 0x9A, 0x01, 0x00, 0x00};
3549  
3550  	/* Drop the beacons from NAN device */
3551  	if ((subtype == MGMT_SUBTYPE_BEACON) &&
3552  		(!qdf_mem_cmp(nan_addr, bssid, NAN_CLUSTER_ID_BYTES))) {
3553  			should_drop = true;
3554  			goto end;
3555  	}
3556  end:
3557  	return should_drop;
3558  }
3559  
3560  #define RATE_LIMIT 16
3561  
wma_form_rx_packet(qdf_nbuf_t buf,struct mgmt_rx_event_params * mgmt_rx_params,cds_pkt_t * rx_pkt)3562  int wma_form_rx_packet(qdf_nbuf_t buf,
3563  			struct mgmt_rx_event_params *mgmt_rx_params,
3564  			cds_pkt_t *rx_pkt)
3565  {
3566  	uint8_t vdev_id = WMA_INVALID_VDEV_ID;
3567  	struct ieee80211_frame *wh;
3568  	uint8_t mgt_type, mgt_subtype;
3569  	int status;
3570  	tp_wma_handle wma_handle = (tp_wma_handle)
3571  				cds_get_context(QDF_MODULE_ID_WMA);
3572  	static uint8_t limit_prints_invalid_len = RATE_LIMIT - 1;
3573  	static uint8_t limit_prints_load_unload = RATE_LIMIT - 1;
3574  	static uint8_t limit_prints_recovery = RATE_LIMIT - 1;
3575  
3576  	if (!wma_handle) {
3577  		qdf_nbuf_free(buf);
3578  		qdf_mem_free(rx_pkt);
3579  		return -EINVAL;
3580  	}
3581  
3582  	if (!mgmt_rx_params) {
3583  		limit_prints_invalid_len++;
3584  		if (limit_prints_invalid_len == RATE_LIMIT) {
3585  			wma_debug("mgmt rx params is NULL");
3586  			limit_prints_invalid_len = 0;
3587  		}
3588  		qdf_nbuf_free(buf);
3589  		qdf_mem_free(rx_pkt);
3590  		return -EINVAL;
3591  	}
3592  
3593  	if (cds_is_load_or_unload_in_progress()) {
3594  		limit_prints_load_unload++;
3595  		if (limit_prints_load_unload == RATE_LIMIT) {
3596  			wma_debug("Load/Unload in progress");
3597  			limit_prints_load_unload = 0;
3598  		}
3599  		qdf_nbuf_free(buf);
3600  		qdf_mem_free(rx_pkt);
3601  		return -EINVAL;
3602  	}
3603  
3604  	if (cds_is_driver_recovering()) {
3605  		limit_prints_recovery++;
3606  		if (limit_prints_recovery == RATE_LIMIT) {
3607  			wma_debug("Recovery in progress");
3608  			limit_prints_recovery = 0;
3609  		}
3610  		qdf_nbuf_free(buf);
3611  		qdf_mem_free(rx_pkt);
3612  		return -EINVAL;
3613  	}
3614  
3615  	if (cds_is_driver_in_bad_state()) {
3616  		limit_prints_recovery++;
3617  		if (limit_prints_recovery == RATE_LIMIT) {
3618  			wma_debug("Driver in bad state");
3619  			limit_prints_recovery = 0;
3620  		}
3621  		qdf_nbuf_free(buf);
3622  		qdf_mem_free(rx_pkt);
3623  		return -EINVAL;
3624  	}
3625  
3626  	/*
3627  	 * Fill in meta information needed by pe/lim
3628  	 * TODO: Try to maintain rx metainfo as part of skb->data.
3629  	 */
3630  	rx_pkt->pkt_meta.frequency = mgmt_rx_params->chan_freq;
3631  	rx_pkt->pkt_meta.scan_src = mgmt_rx_params->flags;
3632  
3633  	/*
3634  	 * Get the rssi value from the current snr value
3635  	 * using standard noise floor of -96.
3636  	 */
3637  	rx_pkt->pkt_meta.rssi = mgmt_rx_params->snr +
3638  				WMA_NOISE_FLOOR_DBM_DEFAULT;
3639  	rx_pkt->pkt_meta.snr = mgmt_rx_params->snr;
3640  
3641  	/* If absolute rssi is available from firmware, use it */
3642  	if (mgmt_rx_params->rssi != 0)
3643  		rx_pkt->pkt_meta.rssi_raw = mgmt_rx_params->rssi;
3644  	else
3645  		rx_pkt->pkt_meta.rssi_raw = rx_pkt->pkt_meta.rssi;
3646  
3647  
3648  	/*
3649  	 * FIXME: Assigning the local timestamp as hw timestamp is not
3650  	 * available. Need to see if pe/lim really uses this data.
3651  	 */
3652  	rx_pkt->pkt_meta.timestamp = (uint32_t) jiffies;
3653  	rx_pkt->pkt_meta.mpdu_hdr_len = sizeof(struct ieee80211_frame);
3654  	rx_pkt->pkt_meta.mpdu_len = mgmt_rx_params->buf_len;
3655  
3656  	/*
3657  	 * The buf_len should be at least 802.11 header len
3658  	 */
3659  	if (mgmt_rx_params->buf_len < rx_pkt->pkt_meta.mpdu_hdr_len) {
3660  		wma_err("MPDU Len %d lesser than header len %d",
3661  			 mgmt_rx_params->buf_len,
3662  			 rx_pkt->pkt_meta.mpdu_hdr_len);
3663  		qdf_nbuf_free(buf);
3664  		qdf_mem_free(rx_pkt);
3665  		return -EINVAL;
3666  	}
3667  
3668  	rx_pkt->pkt_meta.mpdu_data_len = mgmt_rx_params->buf_len -
3669  					 rx_pkt->pkt_meta.mpdu_hdr_len;
3670  
3671  	rx_pkt->pkt_meta.roamCandidateInd = 0;
3672  
3673  	wh = (struct ieee80211_frame *)qdf_nbuf_data(buf);
3674  
3675  	/*
3676  	 * If the mpdu_data_len is greater than Max (2k), drop the frame
3677  	 */
3678  	if (rx_pkt->pkt_meta.mpdu_data_len > MAX_MGMT_MPDU_LEN) {
3679  		wma_err("Data Len %d greater than max, dropping frame from "QDF_MAC_ADDR_FMT,
3680  			 rx_pkt->pkt_meta.mpdu_data_len,
3681  			 QDF_MAC_ADDR_REF(wh->i_addr3));
3682  		qdf_nbuf_free(buf);
3683  		qdf_mem_free(rx_pkt);
3684  		return -EINVAL;
3685  	}
3686  
3687  	rx_pkt->pkt_meta.mpdu_hdr_ptr = qdf_nbuf_data(buf);
3688  	rx_pkt->pkt_meta.mpdu_data_ptr = rx_pkt->pkt_meta.mpdu_hdr_ptr +
3689  					 rx_pkt->pkt_meta.mpdu_hdr_len;
3690  	rx_pkt->pkt_meta.tsf_delta = mgmt_rx_params->tsf_delta;
3691  	rx_pkt->pkt_buf = buf;
3692  	rx_pkt->pkt_meta.pkt_qdf_buf = buf;
3693  
3694  	/* If it is a beacon/probe response, save it for future use */
3695  	mgt_type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
3696  	mgt_subtype = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
3697  
3698  	if (mgt_type == IEEE80211_FC0_TYPE_MGT &&
3699  	    (mgt_subtype == MGMT_SUBTYPE_DISASSOC ||
3700  	     mgt_subtype == MGMT_SUBTYPE_DEAUTH ||
3701  	     mgt_subtype == MGMT_SUBTYPE_ACTION)) {
3702  		if (wma_find_vdev_id_by_bssid(wma_handle, wh->i_addr3,
3703  					      &vdev_id) == QDF_STATUS_SUCCESS) {
3704  			status = wma_check_and_process_rmf_frame(wma_handle,
3705  								 vdev_id,
3706  								 &wh,
3707  								 rx_pkt,
3708  								 buf);
3709  			if (status)
3710  				return status;
3711  		} else if (wma_find_vdev_id_by_addr(wma_handle, wh->i_addr1,
3712  					      &vdev_id) == QDF_STATUS_SUCCESS) {
3713  			status = wma_check_and_process_rmf_frame(wma_handle,
3714  								 vdev_id,
3715  								 &wh,
3716  								 rx_pkt,
3717  								 buf);
3718  			if (status)
3719  				return status;
3720  		} else if (mgt_subtype == MGMT_SUBTYPE_ACTION) {
3721  			/* NAN Action frame */
3722  			vdev_id = wlan_nan_get_vdev_id_from_bssid(
3723  							wma_handle->pdev,
3724  							wh->i_addr3,
3725  							WLAN_ACTION_OUI_ID);
3726  
3727  			if (vdev_id != WMA_INVALID_VDEV_ID) {
3728  				status = wma_check_and_process_rmf_frame(
3729  								wma_handle,
3730  								vdev_id, &wh,
3731  								rx_pkt, buf);
3732  				if (status)
3733  					return status;
3734  			}
3735  		}
3736  	}
3737  
3738  	rx_pkt->pkt_meta.session_id =
3739  		(vdev_id == WMA_INVALID_VDEV_ID ? 0 : vdev_id);
3740  
3741  	if (mgt_type == IEEE80211_FC0_TYPE_MGT &&
3742  	    (mgt_subtype == MGMT_SUBTYPE_BEACON ||
3743  	     mgt_subtype == MGMT_SUBTYPE_PROBE_RESP)) {
3744  		if (mgmt_rx_params->buf_len <=
3745  			(sizeof(struct ieee80211_frame) +
3746  			offsetof(struct wlan_bcn_frame, ie))) {
3747  			wma_debug("Dropping frame from "QDF_MAC_ADDR_FMT,
3748  				 QDF_MAC_ADDR_REF(wh->i_addr3));
3749  			cds_pkt_return_packet(rx_pkt);
3750  			return -EINVAL;
3751  		}
3752  	}
3753  
3754  	if (wma_is_pkt_drop_candidate(wma_handle, wh->i_addr2, wh->i_addr3,
3755  					mgt_subtype)) {
3756  		cds_pkt_return_packet(rx_pkt);
3757  		return -EINVAL;
3758  	}
3759  	wma_mgmt_pktdump_rx_handler(mgmt_rx_params, rx_pkt,
3760  				    wma_handle, mgt_type, mgt_subtype);
3761  
3762  	return 0;
3763  }
3764  
3765  /**
3766   * wma_mem_endianness_based_copy() - does memory copy from src to dst
3767   * @dst: destination address
3768   * @src: source address
3769   * @size: size to be copied
3770   *
3771   * This function copies the memory of size passed from source
3772   * address to destination address.
3773   *
3774   * Return: Nothing
3775   */
3776  #ifdef BIG_ENDIAN_HOST
wma_mem_endianness_based_copy(uint8_t * dst,uint8_t * src,uint32_t size)3777  static void wma_mem_endianness_based_copy(
3778  			uint8_t *dst, uint8_t *src, uint32_t size)
3779  {
3780  	/*
3781  	 * For big endian host, copy engine byte_swap is enabled
3782  	 * But the rx mgmt frame buffer content is in network byte order
3783  	 * Need to byte swap the mgmt frame buffer content - so when
3784  	 * copy engine does byte_swap - host gets buffer content in the
3785  	 * correct byte order.
3786  	 */
3787  
3788  	uint32_t i;
3789  	uint32_t *destp, *srcp;
3790  
3791  	destp = (uint32_t *) dst;
3792  	srcp = (uint32_t *) src;
3793  	for (i = 0; i < (roundup(size, sizeof(uint32_t)) / 4); i++) {
3794  		*destp = cpu_to_le32(*srcp);
3795  		destp++;
3796  		srcp++;
3797  	}
3798  }
3799  #else
wma_mem_endianness_based_copy(uint8_t * dst,uint8_t * src,uint32_t size)3800  static void wma_mem_endianness_based_copy(
3801  			uint8_t *dst, uint8_t *src, uint32_t size)
3802  {
3803  	qdf_mem_copy(dst, src, size);
3804  }
3805  #endif
3806  
3807  #define RESERVE_BYTES                   100
3808  /**
3809   * wma_mgmt_rx_process() - process management rx frame.
3810   * @handle: wma handle
3811   * @data: rx data
3812   * @data_len: data length
3813   *
3814   * Return: 0 for success or error code
3815   */
wma_mgmt_rx_process(void * handle,uint8_t * data,uint32_t data_len)3816  static int wma_mgmt_rx_process(void *handle, uint8_t *data,
3817  				  uint32_t data_len)
3818  {
3819  	tp_wma_handle wma_handle = (tp_wma_handle) handle;
3820  	struct mgmt_rx_event_params *mgmt_rx_params;
3821  	struct wlan_objmgr_psoc *psoc;
3822  	uint8_t *bufp;
3823  	qdf_nbuf_t wbuf;
3824  	QDF_STATUS status;
3825  
3826  	if (wma_validate_handle(wma_handle))
3827  		return -EINVAL;
3828  
3829  	mgmt_rx_params = qdf_mem_malloc(sizeof(*mgmt_rx_params));
3830  	if (!mgmt_rx_params) {
3831  		return -ENOMEM;
3832  	}
3833  
3834  	if (wmi_extract_mgmt_rx_params(wma_handle->wmi_handle,
3835  			data, mgmt_rx_params, &bufp) != QDF_STATUS_SUCCESS) {
3836  		wma_err_rl("Extraction of mgmt rx params failed");
3837  		qdf_mem_free(mgmt_rx_params);
3838  		return -EINVAL;
3839  	}
3840  
3841  	if (mgmt_rx_params->buf_len > data_len ||
3842  	    !mgmt_rx_params->buf_len ||
3843  	    !bufp) {
3844  		wma_err_rl("Invalid data_len %u, buf_len %u bufp %pK",
3845  			   data_len, mgmt_rx_params->buf_len, bufp);
3846  		qdf_mem_free(mgmt_rx_params);
3847  		return -EINVAL;
3848  	}
3849  
3850  	if (!mgmt_rx_params->chan_freq) {
3851  		/*
3852  		 * It indicates that FW is legacy and is operating on
3853  		 * channel numbers and it also indicates that BAND_6G support
3854  		 * is not there as BAND_6G works only on frequencies and channel
3855  		 * numbers can be treated as unique.
3856  		 */
3857  		mgmt_rx_params->chan_freq = wlan_reg_legacy_chan_to_freq(
3858  					    wma_handle->pdev,
3859  					    mgmt_rx_params->channel);
3860  	}
3861  
3862  	mgmt_rx_params->pdev_id = 0;
3863  	mgmt_rx_params->rx_params = NULL;
3864  
3865  	/*
3866  	 * Allocate the memory for this rx packet, add extra 100 bytes for:-
3867  	 *
3868  	 * 1.  Filling the missing RSN capabilities by some APs, which fill the
3869  	 *     RSN IE length as extra 2 bytes but dont fill the IE data with
3870  	 *     capabilities, resulting in failure in unpack core due to length
3871  	 *     mismatch. Check sir_validate_and_rectify_ies for more info.
3872  	 *
3873  	 * 2.  In the API wma_process_rmf_frame(), the driver trims the CCMP
3874  	 *     header by overwriting the IEEE header to memory occupied by CCMP
3875  	 *     header, but an overflow is possible if the memory allocated to
3876  	 *     frame is less than the sizeof(struct ieee80211_frame) +CCMP
3877  	 *     HEADER len, so allocating 100 bytes would solve this issue too.
3878  	 *
3879  	 * 3.  CCMP header is pointing to orig_hdr +
3880  	 *     sizeof(struct ieee80211_frame) which could also result in OOB
3881  	 *     access, if the data len is less than
3882  	 *     sizeof(struct ieee80211_frame), allocating extra bytes would
3883  	 *     result in solving this issue too.
3884  	 */
3885  	wbuf = qdf_nbuf_alloc(NULL, roundup(mgmt_rx_params->buf_len +
3886  							RESERVE_BYTES,
3887  							4), 0, 4, false);
3888  	if (!wbuf) {
3889  		qdf_mem_free(mgmt_rx_params);
3890  		return -ENOMEM;
3891  	}
3892  
3893  	qdf_nbuf_put_tail(wbuf, mgmt_rx_params->buf_len);
3894  	qdf_nbuf_set_protocol(wbuf, ETH_P_CONTROL);
3895  
3896  	qdf_mem_zero(((uint8_t *)qdf_nbuf_data(wbuf) + mgmt_rx_params->buf_len),
3897  		     (roundup(mgmt_rx_params->buf_len + RESERVE_BYTES, 4) -
3898  		     mgmt_rx_params->buf_len));
3899  
3900  	wma_mem_endianness_based_copy(qdf_nbuf_data(wbuf),
3901  			bufp, mgmt_rx_params->buf_len);
3902  
3903  	psoc = (struct wlan_objmgr_psoc *)
3904  				wma_handle->psoc;
3905  	if (!psoc) {
3906  		wma_err("psoc ctx is NULL");
3907  		qdf_nbuf_free(wbuf);
3908  		qdf_mem_free(mgmt_rx_params);
3909  		return -EINVAL;
3910  	}
3911  
3912  	status = mgmt_txrx_rx_handler(psoc, wbuf, mgmt_rx_params);
3913  	if (status != QDF_STATUS_SUCCESS) {
3914  		qdf_mem_free(mgmt_rx_params);
3915  		return -EINVAL;
3916  	}
3917  
3918  	qdf_mem_free(mgmt_rx_params);
3919  	return 0;
3920  }
3921  
3922  /**
3923   * wma_de_register_mgmt_frm_client() - deregister management frame
3924   *
3925   * This function deregisters the event handler registered for
3926   * WMI_MGMT_RX_EVENTID.
3927   *
3928   * Return: QDF status
3929   */
wma_de_register_mgmt_frm_client(void)3930  QDF_STATUS wma_de_register_mgmt_frm_client(void)
3931  {
3932  	tp_wma_handle wma_handle = (tp_wma_handle)
3933  				cds_get_context(QDF_MODULE_ID_WMA);
3934  
3935  	if (!wma_handle)
3936  		return QDF_STATUS_E_NULL_VALUE;
3937  
3938  #ifdef QCA_WIFI_FTM
3939  	if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE)
3940  		return QDF_STATUS_SUCCESS;
3941  #endif
3942  
3943  	if (wmi_unified_unregister_event_handler(wma_handle->wmi_handle,
3944  						 wmi_mgmt_rx_event_id) != 0) {
3945  		wma_err("Failed to Unregister rx mgmt handler with wmi");
3946  		return QDF_STATUS_E_FAILURE;
3947  	}
3948  	return QDF_STATUS_SUCCESS;
3949  }
3950  
3951  #ifdef WLAN_FEATURE_ROAM_OFFLOAD
3952  /**
3953   * wma_register_roaming_callbacks() - Register roaming callbacks
3954   * @csr_roam_auth_event_handle_cb: CSR callback routine pointer
3955   * @pe_roam_synch_cb: PE roam synch callback routine pointer
3956   *
3957   * Register the SME and PE callback routines with WMA for
3958   * handling roaming
3959   *
3960   * Return: Success or Failure Status
3961   */
wma_register_roaming_callbacks(QDF_STATUS (* csr_roam_auth_event_handle_cb)(struct mac_context * mac,uint8_t vdev_id,struct qdf_mac_addr bssid,uint32_t akm),pe_roam_synch_fn_t pe_roam_synch_cb,QDF_STATUS (* pe_disconnect_cb)(struct mac_context * mac,uint8_t vdev_id,uint8_t * deauth_disassoc_frame,uint16_t deauth_disassoc_frame_len,uint16_t reason_code),set_ies_fn_t pe_roam_set_ie_cb)3962  QDF_STATUS wma_register_roaming_callbacks(
3963  	QDF_STATUS (*csr_roam_auth_event_handle_cb)(struct mac_context *mac,
3964  						    uint8_t vdev_id,
3965  						    struct qdf_mac_addr bssid,
3966  						    uint32_t akm),
3967  	pe_roam_synch_fn_t pe_roam_synch_cb,
3968  	QDF_STATUS (*pe_disconnect_cb) (struct mac_context *mac,
3969  					uint8_t vdev_id,
3970  					uint8_t *deauth_disassoc_frame,
3971  					uint16_t deauth_disassoc_frame_len,
3972  					uint16_t reason_code),
3973  	set_ies_fn_t pe_roam_set_ie_cb)
3974  {
3975  
3976  	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
3977  
3978  	if (!wma)
3979  		return QDF_STATUS_E_FAILURE;
3980  
3981  	wma->csr_roam_auth_event_handle_cb = csr_roam_auth_event_handle_cb;
3982  	wma->pe_roam_synch_cb = pe_roam_synch_cb;
3983  	wma->pe_disconnect_cb = pe_disconnect_cb;
3984  	wma->pe_roam_set_ie_cb = pe_roam_set_ie_cb;
3985  	wma_debug("Registered roam synch callbacks with WMA successfully");
3986  
3987  	return QDF_STATUS_SUCCESS;
3988  }
3989  #endif
3990  
3991  /**
3992   * wma_register_mgmt_frm_client() - register management frame callback
3993   *
3994   * This function registers event handler for WMI_MGMT_RX_EVENTID.
3995   *
3996   * Return: QDF status
3997   */
wma_register_mgmt_frm_client(void)3998  QDF_STATUS wma_register_mgmt_frm_client(void)
3999  {
4000  	tp_wma_handle wma_handle = (tp_wma_handle)
4001  				cds_get_context(QDF_MODULE_ID_WMA);
4002  
4003  	if (!wma_handle)
4004  		return QDF_STATUS_E_NULL_VALUE;
4005  
4006  	if (wmi_unified_register_event_handler(wma_handle->wmi_handle,
4007  					       wmi_mgmt_rx_event_id,
4008  					       wma_mgmt_rx_process,
4009  					       WMA_RX_WORK_CTX) != 0) {
4010  		wma_err("Failed to register rx mgmt handler with wmi");
4011  		return QDF_STATUS_E_FAILURE;
4012  	}
4013  
4014  	return QDF_STATUS_SUCCESS;
4015  }
4016  
4017  /**
4018   * wma_register_packetdump_callback() - stores tx and rx mgmt packet dump
4019   *   callback handler
4020   * @tx_cb: tx mgmt packetdump cb
4021   * @rx_cb: rx mgmt packetdump cb
4022   *
4023   * This function is used to store tx and rx mgmt. packet dump callback
4024   *
4025   * Return: None
4026   *
4027   */
wma_register_packetdump_callback(ol_txrx_pktdump_cb tx_cb,ol_txrx_pktdump_cb rx_cb)4028  void wma_register_packetdump_callback(
4029  	ol_txrx_pktdump_cb tx_cb,
4030  	ol_txrx_pktdump_cb rx_cb)
4031  {
4032  	tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
4033  
4034  	if (!wma_handle)
4035  		return;
4036  
4037  	wma_handle->wma_mgmt_tx_packetdump_cb = tx_cb;
4038  	wma_handle->wma_mgmt_rx_packetdump_cb = rx_cb;
4039  }
4040  
4041  /**
4042   * wma_deregister_packetdump_callback() - removes tx and rx mgmt packet dump
4043   *   callback handler
4044   *
4045   * This function is used to remove tx and rx mgmt. packet dump callback
4046   *
4047   * Return: None
4048   *
4049   */
wma_deregister_packetdump_callback(void)4050  void wma_deregister_packetdump_callback(void)
4051  {
4052  	tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
4053  
4054  	if (!wma_handle)
4055  		return;
4056  
4057  	wma_handle->wma_mgmt_tx_packetdump_cb = NULL;
4058  	wma_handle->wma_mgmt_rx_packetdump_cb = NULL;
4059  }
4060  
wma_mgmt_unified_cmd_send(struct wlan_objmgr_vdev * vdev,qdf_nbuf_t buf,uint32_t desc_id,void * mgmt_tx_params)4061  QDF_STATUS wma_mgmt_unified_cmd_send(struct wlan_objmgr_vdev *vdev,
4062  				qdf_nbuf_t buf, uint32_t desc_id,
4063  				void *mgmt_tx_params)
4064  {
4065  	tp_wma_handle wma_handle;
4066  	int ret;
4067  	QDF_STATUS status = QDF_STATUS_E_INVAL;
4068  	struct wmi_mgmt_params *mgmt_params =
4069  			(struct wmi_mgmt_params *)mgmt_tx_params;
4070  	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
4071  
4072  	if (!mgmt_params) {
4073  		wma_err("mgmt_params ptr passed is NULL");
4074  		return QDF_STATUS_E_INVAL;
4075  	}
4076  	mgmt_params->desc_id = desc_id;
4077  
4078  	if (!vdev) {
4079  		wma_err("vdev ptr passed is NULL");
4080  		return QDF_STATUS_E_INVAL;
4081  	}
4082  
4083  	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
4084  	if (!wma_handle)
4085  		return QDF_STATUS_E_INVAL;
4086  
4087  	if (wmi_service_enabled(wma_handle->wmi_handle,
4088  				   wmi_service_mgmt_tx_wmi)) {
4089  		status = wmi_mgmt_unified_cmd_send(wma_handle->wmi_handle,
4090  						   mgmt_params);
4091  	} else {
4092  		QDF_NBUF_CB_MGMT_TXRX_DESC_ID(buf)
4093  						= mgmt_params->desc_id;
4094  
4095  		ret = cdp_mgmt_send_ext(soc, mgmt_params->vdev_id, buf,
4096  					mgmt_params->tx_type,
4097  					mgmt_params->use_6mbps,
4098  					mgmt_params->chanfreq);
4099  		status = qdf_status_from_os_return(ret);
4100  	}
4101  
4102  	if (status != QDF_STATUS_SUCCESS) {
4103  		wma_err("mgmt tx failed");
4104  		return status;
4105  	}
4106  
4107  	return QDF_STATUS_SUCCESS;
4108  }
4109  
4110  #ifndef CONFIG_HL_SUPPORT
wma_mgmt_nbuf_unmap_cb(struct wlan_objmgr_pdev * pdev,qdf_nbuf_t buf)4111  void wma_mgmt_nbuf_unmap_cb(struct wlan_objmgr_pdev *pdev,
4112  			    qdf_nbuf_t buf)
4113  {
4114  	struct wlan_objmgr_psoc *psoc;
4115  	qdf_device_t dev;
4116  
4117  	if (!buf)
4118  		return;
4119  
4120  	psoc = wlan_pdev_get_psoc(pdev);
4121  	if (!psoc) {
4122  		wma_err("Psoc handle NULL");
4123  		return;
4124  	}
4125  
4126  	dev = wlan_psoc_get_qdf_dev(psoc);
4127  	qdf_nbuf_unmap_single(dev, buf, QDF_DMA_TO_DEVICE);
4128  }
4129  
wma_mgmt_frame_fill_peer_cb(struct wlan_objmgr_peer * peer,qdf_nbuf_t buf)4130  QDF_STATUS wma_mgmt_frame_fill_peer_cb(struct wlan_objmgr_peer *peer,
4131  				       qdf_nbuf_t buf)
4132  {
4133  	struct wlan_objmgr_psoc *psoc;
4134  	struct wlan_objmgr_pdev *pdev;
4135  
4136  	psoc = wlan_peer_get_psoc(peer);
4137  	if (!psoc) {
4138  		wma_err("Psoc handle NULL");
4139  		return QDF_STATUS_E_INVAL;
4140  	}
4141  
4142  	pdev = wlan_objmgr_get_pdev_by_id((struct wlan_objmgr_psoc *)psoc,
4143  					  wlan_peer_get_pdev_id(peer),
4144  					  WLAN_LEGACY_WMA_ID);
4145  	if (!pdev) {
4146  		wma_err("Pdev handle NULL");
4147  		return QDF_STATUS_E_INVAL;
4148  	}
4149  	wma_mgmt_nbuf_unmap_cb(pdev, buf);
4150  	wlan_objmgr_pdev_release_ref(pdev, WLAN_LEGACY_WMA_ID);
4151  
4152  	return QDF_STATUS_SUCCESS;
4153  }
4154  
4155  QDF_STATUS
wma_update_edca_pifs_param(WMA_HANDLE handle,struct edca_pifs_vparam * edca_pifs_param)4156  wma_update_edca_pifs_param(WMA_HANDLE handle,
4157  			   struct edca_pifs_vparam *edca_pifs_param)
4158  {
4159  	tp_wma_handle wma_handle = (tp_wma_handle) handle;
4160  	QDF_STATUS status;
4161  
4162  	status = wmi_unified_update_edca_pifs_param(wma_handle->wmi_handle,
4163  						    edca_pifs_param);
4164  
4165  	if (QDF_IS_STATUS_ERROR(status))
4166  		wma_err("Failed to set EDCA/PIFS Parameters");
4167  
4168  	return status;
4169  }
4170  #endif
4171  
4172  QDF_STATUS
wma_update_bss_peer_phy_mode(struct wlan_channel * des_chan,struct wlan_objmgr_vdev * vdev)4173  wma_update_bss_peer_phy_mode(struct wlan_channel *des_chan,
4174  			     struct wlan_objmgr_vdev *vdev)
4175  {
4176  	struct wlan_objmgr_peer *bss_peer;
4177  	enum wlan_phymode old_peer_phymode, new_phymode;
4178  	tSirNwType nw_type;
4179  	struct vdev_mlme_obj *mlme_obj;
4180  
4181  	bss_peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_LEGACY_WMA_ID);
4182  	if (!bss_peer) {
4183  		wma_err("not able to find bss peer for vdev %d",
4184  			wlan_vdev_get_id(vdev));
4185  		return QDF_STATUS_E_INVAL;
4186  	}
4187  
4188  	old_peer_phymode = wlan_peer_get_phymode(bss_peer);
4189  
4190  	if (WLAN_REG_IS_24GHZ_CH_FREQ(des_chan->ch_freq)) {
4191  		if (des_chan->ch_phymode == WLAN_PHYMODE_11B ||
4192  		    old_peer_phymode == WLAN_PHYMODE_11B)
4193  			nw_type = eSIR_11B_NW_TYPE;
4194  		else
4195  			nw_type = eSIR_11G_NW_TYPE;
4196  	} else {
4197  		nw_type = eSIR_11A_NW_TYPE;
4198  	}
4199  
4200  	new_phymode = wma_peer_phymode(nw_type, STA_ENTRY_PEER,
4201  				       IS_WLAN_PHYMODE_HT(old_peer_phymode),
4202  				       des_chan->ch_width,
4203  				       IS_WLAN_PHYMODE_VHT(old_peer_phymode),
4204  				       IS_WLAN_PHYMODE_HE(old_peer_phymode),
4205  				       wma_is_phymode_eht(old_peer_phymode));
4206  
4207  	if (new_phymode == old_peer_phymode) {
4208  		wma_debug("Ignore update, old %d and new %d phymode are same, vdev_id : %d",
4209  			  old_peer_phymode, new_phymode,
4210  			  wlan_vdev_get_id(vdev));
4211  		wlan_objmgr_peer_release_ref(bss_peer, WLAN_LEGACY_WMA_ID);
4212  		return QDF_STATUS_SUCCESS;
4213  	}
4214  
4215  	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev);
4216  	if (!mlme_obj) {
4217  		wma_err("not able to get mlme_obj");
4218  		wlan_objmgr_peer_release_ref(bss_peer, WLAN_LEGACY_WMA_ID);
4219  		return QDF_STATUS_E_INVAL;
4220  	}
4221  
4222  	wlan_peer_obj_lock(bss_peer);
4223  	wlan_peer_set_phymode(bss_peer, new_phymode);
4224  	wlan_peer_obj_unlock(bss_peer);
4225  
4226  	wlan_objmgr_peer_release_ref(bss_peer, WLAN_LEGACY_WMA_ID);
4227  
4228  	mlme_obj->mgmt.generic.phy_mode = wmi_host_to_fw_phymode(new_phymode);
4229  	des_chan->ch_phymode = new_phymode;
4230  
4231  	return QDF_STATUS_SUCCESS;
4232  }
4233  
4234  QDF_STATUS
cm_send_ies_for_roam_invoke(struct wlan_objmgr_vdev * vdev,uint16_t dot11_mode)4235  cm_send_ies_for_roam_invoke(struct wlan_objmgr_vdev *vdev, uint16_t dot11_mode)
4236  {
4237  	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4238  	enum QDF_OPMODE op_mode;
4239  	QDF_STATUS status;
4240  	uint8_t vdev_id;
4241  
4242  	if (!wma)
4243  		return QDF_STATUS_E_FAILURE;
4244  
4245  	vdev_id = wlan_vdev_get_id(vdev);
4246  	op_mode = wlan_vdev_mlme_get_opmode(vdev);
4247  
4248  	status = wma->pe_roam_set_ie_cb(wma->mac_context, vdev_id, dot11_mode,
4249  					op_mode);
4250  	return status;
4251  }
4252