1 /*
2  * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2023-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: wlan_tdls_mgmt.c
22  *
23  * TDLS management frames implementation
24  */
25 
26 #include "wlan_tdls_main.h"
27 #include "wlan_tdls_tgt_api.h"
28 #include <wlan_serialization_api.h>
29 #include "wlan_mgmt_txrx_utils_api.h"
30 #include "wlan_tdls_peer.h"
31 #include "wlan_tdls_ct.h"
32 #include "wlan_tdls_mgmt.h"
33 #include "wlan_policy_mgr_api.h"
34 #include <wlan_reg_services_api.h>
35 #include <wlan_mlo_mgr_sta.h>
36 #include "wlan_mlo_link_force.h"
37 
38 static
39 const char *const tdls_action_frames_type[] = { "TDLS Setup Request",
40 					 "TDLS Setup Response",
41 					 "TDLS Setup Confirm",
42 					 "TDLS Teardown",
43 					 "TDLS Peer Traffic Indication",
44 					 "TDLS Channel Switch Request",
45 					 "TDLS Channel Switch Response",
46 					 "TDLS Peer PSM Request",
47 					 "TDLS Peer PSM Response",
48 					 "TDLS Peer Traffic Response",
49 					 "TDLS Discovery Request"};
50 
tdls_set_rssi(struct wlan_objmgr_vdev * vdev,uint8_t * mac,int8_t rssi)51 QDF_STATUS tdls_set_rssi(struct wlan_objmgr_vdev *vdev,
52 			 uint8_t *mac, int8_t rssi)
53 {
54 	struct tdls_vdev_priv_obj *tdls_vdev;
55 	struct tdls_peer *curr_peer;
56 
57 	if (!vdev || !mac) {
58 		tdls_err("null pointer");
59 		return QDF_STATUS_E_INVAL;
60 	}
61 
62 	tdls_debug("rssi %d, peer " QDF_MAC_ADDR_FMT,
63 		   rssi, QDF_MAC_ADDR_REF(mac));
64 
65 	tdls_vdev = wlan_objmgr_vdev_get_comp_private_obj(
66 			vdev, WLAN_UMAC_COMP_TDLS);
67 
68 	if (!tdls_vdev) {
69 		tdls_err("null tdls vdev");
70 		return QDF_STATUS_E_EXISTS;
71 	}
72 
73 	curr_peer = tdls_find_peer(tdls_vdev, mac);
74 	if (!curr_peer) {
75 		tdls_debug("null peer");
76 		return QDF_STATUS_E_EXISTS;
77 	}
78 
79 	curr_peer->rssi = rssi;
80 
81 	return QDF_STATUS_SUCCESS;
82 }
83 
84 #ifdef WLAN_FEATURE_11BE_MLO
85 struct wlan_objmgr_vdev *
tdls_mlo_get_tdls_link_vdev(struct wlan_objmgr_vdev * vdev)86 tdls_mlo_get_tdls_link_vdev(struct wlan_objmgr_vdev *vdev)
87 {
88 	return wlan_mlo_get_tdls_link_vdev(vdev);
89 }
90 
91 void
tdls_set_remain_links_unforce(struct wlan_objmgr_vdev * vdev)92 tdls_set_remain_links_unforce(struct wlan_objmgr_vdev *vdev)
93 {
94 	struct wlan_mlo_dev_context *mlo_dev_ctx;
95 	struct wlan_objmgr_vdev *mlo_vdev;
96 	int i;
97 
98 	/* TDLS link is selected, unforce link for other vdevs */
99 	mlo_dev_ctx = vdev->mlo_dev_ctx;
100 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
101 		mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i];
102 		if (!mlo_vdev || mlo_vdev == vdev)
103 			continue;
104 
105 		tdls_debug("try to set vdev %d to unforce",
106 			   wlan_vdev_get_id(mlo_vdev));
107 		tdls_set_link_unforce(mlo_vdev);
108 	}
109 }
110 
111 QDF_STATUS
tdls_process_mlo_cal_tdls_link_score(struct wlan_objmgr_vdev * vdev)112 tdls_process_mlo_cal_tdls_link_score(struct wlan_objmgr_vdev *vdev)
113 {
114 	struct wlan_mlo_dev_context *mlo_dev_ctx;
115 	struct wlan_objmgr_vdev *mlo_vdev;
116 	struct tdls_vdev_priv_obj *tdls_vdev;
117 	struct tdls_rx_mgmt_frame *rx_mgmt;
118 	uint32_t score;
119 	int i;
120 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
121 
122 	mlo_dev_ctx = vdev->mlo_dev_ctx;
123 	for (i =  0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
124 		score = 0;
125 		mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i];
126 		if (!mlo_vdev)
127 			continue;
128 		tdls_vdev =
129 		     wlan_objmgr_vdev_get_comp_private_obj(mlo_vdev,
130 							   WLAN_UMAC_COMP_TDLS);
131 		tdls_vdev->link_score = 0;
132 		rx_mgmt = tdls_vdev->rx_mgmt;
133 		if (!rx_mgmt)
134 			continue;
135 
136 		switch (wlan_reg_freq_to_band(rx_mgmt->rx_freq)) {
137 		case REG_BAND_2G:
138 			score += 50;
139 			break;
140 		case REG_BAND_5G:
141 			score += 70;
142 			break;
143 		case REG_BAND_6G:
144 			score += 80;
145 			break;
146 		default:
147 			score += 40;
148 			break;
149 		}
150 
151 		tdls_vdev->link_score = score;
152 		status = QDF_STATUS_SUCCESS;
153 	}
154 
155 	return status;
156 }
157 
158 /**
159  * tdls_check_wait_more() - wait until the timer timeout if necessary
160  * @vdev: vdev object
161  *
162  * Return: true if need to wait else false
163  */
tdls_check_wait_more(struct wlan_objmgr_vdev * vdev)164 static bool tdls_check_wait_more(struct wlan_objmgr_vdev *vdev)
165 {
166 	struct wlan_mlo_dev_context *mlo_dev_ctx;
167 	struct wlan_objmgr_vdev *mlo_vdev;
168 	struct tdls_vdev_priv_obj *tdls_vdev;
169 	/* expect response number */
170 	int expect_num;
171 	/* received response number */
172 	int receive_num;
173 	int i;
174 
175 	expect_num = 0;
176 	receive_num = 0;
177 	mlo_dev_ctx = vdev->mlo_dev_ctx;
178 	for (i =  0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
179 		mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i];
180 		if (!mlo_vdev)
181 			continue;
182 
183 		expect_num++;
184 
185 		tdls_vdev =
186 		     wlan_objmgr_vdev_get_comp_private_obj(mlo_vdev,
187 							   WLAN_UMAC_COMP_TDLS);
188 		if (tdls_vdev->rx_mgmt)
189 			receive_num++;
190 	}
191 
192 	/* +1 means the one received last has not been recorded */
193 	if (expect_num > receive_num + 1)
194 		return true;
195 	else
196 		return false;
197 }
198 
199 struct wlan_objmgr_vdev *
tdls_process_mlo_choice_tdls_vdev(struct wlan_objmgr_vdev * vdev)200 tdls_process_mlo_choice_tdls_vdev(struct wlan_objmgr_vdev *vdev)
201 {
202 	struct wlan_mlo_dev_context *mlo_dev_ctx;
203 	struct wlan_objmgr_vdev *mlo_vdev;
204 	struct wlan_objmgr_vdev *select_vdev = NULL;
205 	struct tdls_vdev_priv_obj *tdls_vdev;
206 	uint32_t score = 0;
207 	int i;
208 
209 	mlo_dev_ctx = vdev->mlo_dev_ctx;
210 	for (i =  0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
211 		mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i];
212 		if (!mlo_vdev)
213 			continue;
214 		tdls_vdev =
215 		     wlan_objmgr_vdev_get_comp_private_obj(mlo_vdev,
216 							   WLAN_UMAC_COMP_TDLS);
217 		if (score < tdls_vdev->link_score) {
218 			select_vdev = mlo_vdev;
219 			score = tdls_vdev->link_score;
220 		}
221 	}
222 
223 	/* free the memory except the choice one */
224 	for (i =  0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
225 		mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i];
226 		if (!mlo_vdev || mlo_vdev == select_vdev)
227 			continue;
228 
229 		tdls_vdev =
230 		     wlan_objmgr_vdev_get_comp_private_obj(mlo_vdev,
231 							   WLAN_UMAC_COMP_TDLS);
232 		qdf_mem_free(tdls_vdev->rx_mgmt);
233 		tdls_vdev->rx_mgmt = NULL;
234 		tdls_vdev->link_score = 0;
235 	}
236 
237 	return select_vdev;
238 }
239 
240 static struct tdls_vdev_priv_obj
tdls_get_correct_vdev(struct tdls_vdev_priv_obj * tdls_vdev,struct tdls_rx_mgmt_frame * rx_mgmt)241 *tdls_get_correct_vdev(struct tdls_vdev_priv_obj *tdls_vdev,
242 		       struct tdls_rx_mgmt_frame *rx_mgmt)
243 {
244 	struct wlan_objmgr_pdev *pdev;
245 	struct wlan_objmgr_vdev *vdev;
246 	struct tdls_link_identifier *linkid_ie;
247 	uint8_t vdev_id;
248 	uint8_t *ies;
249 	uint32_t ie_len;
250 	uint8_t elem_id_param = WLAN_ELEMID_LINK_IDENTIFIER;
251 
252 	if (!tdls_vdev || !rx_mgmt)
253 		return NULL;
254 
255 	ies = &rx_mgmt->buf[TDLS_PUBLIC_ACTION_FRAME_TDLS_IE_OFFSET];
256 	ie_len = rx_mgmt->frame_len - TDLS_PUBLIC_ACTION_FRAME_TDLS_IE_OFFSET;
257 
258 	linkid_ie =
259 	  (struct tdls_link_identifier *)wlan_get_ie_ptr_from_eid(elem_id_param,
260 								  ies, ie_len);
261 	if (!linkid_ie)
262 		return tdls_vdev;
263 
264 	pdev = wlan_vdev_get_pdev(tdls_vdev->vdev);
265 	if (!pdev)
266 		return tdls_vdev;
267 
268 	if (!wlan_get_connected_vdev_by_bssid(pdev,
269 					      linkid_ie->bssid, &vdev_id))
270 		return tdls_vdev;
271 
272 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
273 						    WLAN_TDLS_NB_ID);
274 	if (!vdev)
275 		return tdls_vdev;
276 
277 	tdls_vdev = wlan_objmgr_vdev_get_comp_private_obj(vdev,
278 							  WLAN_UMAC_COMP_TDLS);
279 	rx_mgmt->vdev_id = vdev_id;
280 
281 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
282 	tdls_debug("received discovery response on vdev %d", rx_mgmt->vdev_id);
283 
284 	return tdls_vdev;
285 }
286 
tdls_check_peer_mlo_dev(struct wlan_objmgr_vdev * vdev,struct tdls_rx_mgmt_frame * rx_mgmt)287 static bool tdls_check_peer_mlo_dev(struct wlan_objmgr_vdev *vdev,
288 				    struct tdls_rx_mgmt_frame *rx_mgmt)
289 {
290 	uint8_t *ies;
291 	const uint8_t *ie;
292 	uint32_t ie_len;
293 	const uint8_t ext_id_param = WLAN_EXTN_ELEMID_MULTI_LINK;
294 	uint8_t elem_id_param = WLAN_ELEMID_LINK_IDENTIFIER;
295 
296 	if (!vdev || !rx_mgmt)
297 		return QDF_STATUS_E_INVAL;
298 
299 	ies = &rx_mgmt->buf[TDLS_PUBLIC_ACTION_FRAME_TDLS_IE_OFFSET];
300 	ie_len = rx_mgmt->frame_len - TDLS_PUBLIC_ACTION_FRAME_TDLS_IE_OFFSET;
301 
302 	ie = wlan_get_ie_ptr_from_eid(elem_id_param, ies, ie_len);
303 	if (ie)
304 		qdf_trace_hex_dump(QDF_MODULE_ID_TDLS, QDF_TRACE_LEVEL_DEBUG,
305 				   (void *)&ie[0], ie[1] + 2);
306 
307 	ie = wlan_get_ext_ie_ptr_from_ext_id(&ext_id_param,
308 					     1, ies, ie_len);
309 	if (ie)
310 		return true;
311 
312 	return false;
313 }
314 
315 static QDF_STATUS
tdls_process_mlo_rx_mgmt_sync(struct tdls_soc_priv_obj * tdls_soc,struct tdls_vdev_priv_obj * tdls_vdev,struct tdls_rx_mgmt_frame * rx_mgmt)316 tdls_process_mlo_rx_mgmt_sync(struct tdls_soc_priv_obj *tdls_soc,
317 			      struct tdls_vdev_priv_obj *tdls_vdev,
318 			      struct tdls_rx_mgmt_frame *rx_mgmt)
319 {
320 	QDF_STATUS status;
321 	struct wlan_objmgr_vdev *vdev;
322 	struct wlan_objmgr_vdev *mlo_vdev;
323 	struct wlan_mlo_dev_context *mlo_dev_ctx;
324 	bool peer_mlo;
325 	bool waitmore = false;
326 	uint8_t i;
327 
328 	vdev = tdls_vdev->vdev;
329 	peer_mlo = tdls_check_peer_mlo_dev(vdev, rx_mgmt);
330 	if (!peer_mlo) {
331 		mlo_dev_ctx = vdev->mlo_dev_ctx;
332 		/* stop all timers */
333 		for (i =  0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
334 			mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i];
335 			if (!mlo_vdev)
336 				continue;
337 
338 			tdls_vdev =
339 			       wlan_objmgr_vdev_get_comp_private_obj(mlo_vdev,
340 							   WLAN_UMAC_COMP_TDLS);
341 			tdls_vdev->discovery_sent_cnt = 0;
342 			if (QDF_TIMER_STATE_RUNNING ==
343 			    qdf_mc_timer_get_current_state(
344 					    &tdls_vdev->peer_discovery_timer)) {
345 				qdf_mc_timer_stop(
346 					      &tdls_vdev->peer_discovery_timer);
347 				qdf_atomic_dec(&tdls_soc->timer_cnt);
348 			}
349 		}
350 		tdls_debug("peer is legacy device, timer_cnt %d",
351 			   qdf_atomic_read(&tdls_soc->timer_cnt));
352 
353 		status = QDF_STATUS_E_INVAL;
354 	} else {
355 		tdls_debug("peer is mlo device, timer_cnt %d",
356 			   qdf_atomic_read(&tdls_soc->timer_cnt));
357 
358 		/* If peer is MLD, it uses ml mac address to send the
359 		 * disconvery response, it needs to find out the
360 		 * corresponding vdev per the bssid in link identifier ie.
361 		 */
362 		tdls_vdev = tdls_get_correct_vdev(tdls_vdev, rx_mgmt);
363 		status = QDF_STATUS_TDLS_MLO_SYNC;
364 		if (!tdls_vdev || tdls_vdev->rx_mgmt) {
365 			tdls_err("rx dup tdls discovery resp on same vdev.");
366 			goto exit;
367 		}
368 
369 		if (qdf_atomic_read(&tdls_soc->timer_cnt) == 1)
370 			waitmore = tdls_check_wait_more(vdev);
371 
372 		if (waitmore) {
373 			/* do not stop the timer */
374 			tdls_debug("wait more tdls response");
375 		} else {
376 			tdls_vdev->discovery_sent_cnt = 0;
377 			qdf_mc_timer_stop(&tdls_vdev->peer_discovery_timer);
378 			qdf_atomic_dec(&tdls_soc->timer_cnt);
379 		}
380 
381 		tdls_vdev->rx_mgmt = qdf_mem_malloc_atomic(sizeof(*rx_mgmt) +
382 							   rx_mgmt->frame_len);
383 		if (tdls_vdev->rx_mgmt) {
384 			tdls_vdev->rx_mgmt->frame_len = rx_mgmt->frame_len;
385 			tdls_vdev->rx_mgmt->rx_freq = rx_mgmt->rx_freq;
386 			tdls_vdev->rx_mgmt->vdev_id = rx_mgmt->vdev_id;
387 			tdls_vdev->rx_mgmt->frm_type = rx_mgmt->frm_type;
388 			tdls_vdev->rx_mgmt->rx_rssi = rx_mgmt->rx_rssi;
389 			qdf_mem_copy(tdls_vdev->rx_mgmt->buf,
390 				     rx_mgmt->buf, rx_mgmt->frame_len);
391 		} else {
392 			tdls_err("alloc rx mgmt buf error");
393 		}
394 
395 		if (qdf_atomic_read(&tdls_soc->timer_cnt) == 0) {
396 			tdls_process_mlo_cal_tdls_link_score(vdev);
397 			status = QDF_STATUS_SUCCESS;
398 		}
399 	}
400 
401 exit:
402 	return status;
403 }
404 
tdls_set_no_force_vdev(struct wlan_objmgr_vdev * vdev,bool flag)405 void tdls_set_no_force_vdev(struct wlan_objmgr_vdev *vdev, bool flag)
406 {
407 	uint8_t i;
408 	struct wlan_objmgr_psoc *psoc;
409 	struct wlan_objmgr_vdev *mlo_vdev;
410 	struct wlan_mlo_dev_context *mlo_dev_ctx;
411 	bool is_mlo_vdev;
412 	struct ml_nlink_change_event data;
413 	QDF_STATUS status;
414 
415 	if (!vdev)
416 		return;
417 
418 	is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev);
419 	if (!is_mlo_vdev)
420 		return;
421 
422 	psoc = wlan_vdev_get_psoc(vdev);
423 	if (!psoc)
424 		return;
425 
426 	qdf_mem_zero(&data, sizeof(data));
427 
428 	mlo_dev_ctx = vdev->mlo_dev_ctx;
429 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
430 		mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i];
431 		if (!mlo_vdev)
432 			continue;
433 
434 		/* flag: true means no force all vdevs,
435 		 * false means except the current one
436 		 */
437 		if (!flag && (mlo_vdev == vdev))
438 			continue;
439 		data.evt.tdls.link_bitmap |=
440 				1 << wlan_vdev_get_link_id(mlo_vdev);
441 		data.evt.tdls.mlo_vdev_lst[data.evt.tdls.vdev_count] =
442 				wlan_vdev_get_id(mlo_vdev);
443 		data.evt.tdls.vdev_count++;
444 	}
445 
446 	data.evt.tdls.mode = MLO_LINK_FORCE_MODE_NO_FORCE;
447 	data.evt.tdls.reason = MLO_LINK_FORCE_REASON_TDLS;
448 	status = ml_nlink_conn_change_notify(psoc,
449 					     wlan_vdev_get_id(vdev),
450 					     ml_nlink_tdls_request_evt,
451 					     &data);
452 }
453 #else
454 struct wlan_objmgr_vdev *
tdls_mlo_get_tdls_link_vdev(struct wlan_objmgr_vdev * vdev)455 tdls_mlo_get_tdls_link_vdev(struct wlan_objmgr_vdev *vdev)
456 {
457 	return NULL;
458 }
459 
460 void
tdls_set_remain_links_unforce(struct wlan_objmgr_vdev * vdev)461 tdls_set_remain_links_unforce(struct wlan_objmgr_vdev *vdev)
462 {
463 }
464 
465 QDF_STATUS
tdls_process_mlo_cal_tdls_link_score(struct wlan_objmgr_vdev * vdev)466 tdls_process_mlo_cal_tdls_link_score(struct wlan_objmgr_vdev *vdev)
467 {
468 	return QDF_STATUS_SUCCESS;
469 }
470 
471 struct wlan_objmgr_vdev *
tdls_process_mlo_choice_tdls_vdev(struct wlan_objmgr_vdev * vdev)472 tdls_process_mlo_choice_tdls_vdev(struct wlan_objmgr_vdev *vdev)
473 {
474 	return NULL;
475 }
476 
477 static struct tdls_vdev_priv_obj
tdls_get_correct_vdev(struct tdls_vdev_priv_obj * tdls_vdev,struct tdls_rx_mgmt_frame * rx_mgmt)478 *tdls_get_correct_vdev(struct tdls_vdev_priv_obj *tdls_vdev,
479 		       struct tdls_rx_mgmt_frame *rx_mgmt)
480 {
481 	return NULL;
482 }
483 
484 static QDF_STATUS
tdls_process_mlo_rx_mgmt_sync(struct tdls_soc_priv_obj * tdls_soc,struct tdls_vdev_priv_obj * tdls_vdev,struct tdls_rx_mgmt_frame * rx_mgmt)485 tdls_process_mlo_rx_mgmt_sync(struct tdls_soc_priv_obj *tdls_soc,
486 			      struct tdls_vdev_priv_obj *tdls_vdev,
487 			      struct tdls_rx_mgmt_frame *rx_mgmt)
488 {
489 	return QDF_STATUS_SUCCESS;
490 }
491 
tdls_set_no_force_vdev(struct wlan_objmgr_vdev * vdev,bool flag)492 void tdls_set_no_force_vdev(struct wlan_objmgr_vdev *vdev, bool flag)
493 {
494 }
495 #endif
496 
497 static bool
tdls_needs_wait_discovery_response(struct wlan_objmgr_vdev * vdev,struct tdls_soc_priv_obj * tdls_soc)498 tdls_needs_wait_discovery_response(struct wlan_objmgr_vdev *vdev,
499 				   struct tdls_soc_priv_obj *tdls_soc)
500 {
501 	bool is_mlo_vdev;
502 	bool wait = false;
503 
504 	is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev);
505 	if (is_mlo_vdev && qdf_atomic_read(&tdls_soc->timer_cnt))
506 		wait = true;
507 
508 	return wait;
509 }
510 
511 /**
512  * tdls_process_rx_mgmt() - process tdls rx mgmt frames
513  * @rx_mgmt_event: tdls rx mgmt event
514  * @tdls_vdev: tdls vdev object
515  *
516  * Return: QDF_STATUS
517  */
tdls_process_rx_mgmt(struct tdls_rx_mgmt_event * rx_mgmt_event,struct tdls_vdev_priv_obj * tdls_vdev)518 static QDF_STATUS tdls_process_rx_mgmt(
519 	struct tdls_rx_mgmt_event *rx_mgmt_event,
520 	struct tdls_vdev_priv_obj *tdls_vdev)
521 {
522 	struct tdls_rx_mgmt_frame *rx_mgmt;
523 	struct tdls_soc_priv_obj *tdls_soc_obj;
524 	uint8_t *mac;
525 	enum tdls_actioncode action_frame_type;
526 	struct wlan_objmgr_vdev *vdev;
527 	struct wlan_objmgr_vdev *tdls_link_vdev;
528 	bool tdls_vdev_select = false;
529 	QDF_STATUS status = QDF_STATUS_E_INVAL;
530 
531 	if (!rx_mgmt_event)
532 		return QDF_STATUS_E_INVAL;
533 
534 	tdls_soc_obj = rx_mgmt_event->tdls_soc_obj;
535 	rx_mgmt = rx_mgmt_event->rx_mgmt;
536 
537 	if (!tdls_soc_obj || !rx_mgmt) {
538 		tdls_err("invalid psoc object or rx mgmt");
539 		return QDF_STATUS_E_INVAL;
540 	}
541 
542 	vdev = tdls_vdev->vdev;
543 	tdls_debug("received mgmt on vdev %d", wlan_vdev_get_id(vdev));
544 	tdls_debug("soc:%pK, frame_len:%d, rx_freq:%d, vdev_id:%d, frm_type:%d, rx_rssi:%d, buf:%pK",
545 		   tdls_soc_obj->soc, rx_mgmt->frame_len,
546 		   rx_mgmt->rx_freq, rx_mgmt->vdev_id, rx_mgmt->frm_type,
547 		   rx_mgmt->rx_rssi, rx_mgmt->buf);
548 
549 	if (rx_mgmt->buf[TDLS_PUBLIC_ACTION_FRAME_OFFSET + 1] ==
550 	    TDLS_PUBLIC_ACTION_DISC_RESP) {
551 		if (tdls_needs_wait_discovery_response(vdev, tdls_soc_obj)) {
552 			status = tdls_process_mlo_rx_mgmt_sync(tdls_soc_obj,
553 							       tdls_vdev,
554 							       rx_mgmt);
555 			if (status == QDF_STATUS_TDLS_MLO_SYNC) {
556 				return QDF_STATUS_SUCCESS;
557 			} else if (status == QDF_STATUS_SUCCESS) {
558 				vdev = tdls_process_mlo_choice_tdls_vdev(vdev);
559 				if (!vdev)
560 					return QDF_STATUS_SUCCESS;
561 				tdls_vdev =
562 				     wlan_objmgr_vdev_get_comp_private_obj(vdev,
563 							   WLAN_UMAC_COMP_TDLS);
564 				if (!tdls_vdev)
565 					return QDF_STATUS_E_EXISTS;
566 				rx_mgmt = tdls_vdev->rx_mgmt;
567 				tdls_vdev_select = true;
568 				tdls_debug("choice vdev %d as tdls vdev",
569 					   wlan_vdev_get_id(vdev));
570 			} else {
571 				tdls_vdev = tdls_get_correct_vdev(tdls_vdev,
572 								  rx_mgmt);
573 				if (!tdls_vdev)
574 					return QDF_STATUS_SUCCESS;
575 				vdev = tdls_vdev->vdev;
576 			}
577 		} else {
578 			if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
579 				tdls_link_vdev =
580 					      tdls_mlo_get_tdls_link_vdev(vdev);
581 				tdls_vdev =
582 				      tdls_get_correct_vdev(tdls_vdev, rx_mgmt);
583 				if (!tdls_link_vdev || !tdls_vdev) {
584 					tdls_debug("not expected frame");
585 					return QDF_STATUS_SUCCESS;
586 				}
587 				if (tdls_link_vdev != tdls_vdev->vdev) {
588 					tdls_debug("not forward to userspace");
589 					return QDF_STATUS_SUCCESS;
590 				}
591 				rx_mgmt->vdev_id =
592 					       wlan_vdev_get_id(tdls_link_vdev);
593 				vdev = tdls_link_vdev;
594 			}
595 		}
596 
597 		/* this is mld mac address for mlo case*/
598 		mac = &rx_mgmt->buf[TDLS_80211_PEER_ADDR_OFFSET];
599 		tdls_notice("[TDLS] TDLS Discovery Response,"
600 			    QDF_MAC_ADDR_FMT " RSSI[%d] <--- OTA",
601 			    QDF_MAC_ADDR_REF(mac), rx_mgmt->rx_rssi);
602 
603 		tdls_debug("discovery resp on vdev %d", wlan_vdev_get_id(vdev));
604 		tdls_recv_discovery_resp(tdls_vdev, mac);
605 		tdls_set_rssi(tdls_vdev->vdev, mac, rx_mgmt->rx_rssi);
606 	}
607 
608 	if (rx_mgmt->buf[TDLS_PUBLIC_ACTION_FRAME_OFFSET] ==
609 	    TDLS_ACTION_FRAME) {
610 		action_frame_type =
611 			rx_mgmt->buf[TDLS_PUBLIC_ACTION_FRAME_OFFSET + 1];
612 		if (action_frame_type >= TDLS_ACTION_FRAME_TYPE_MAX) {
613 			tdls_debug("[TDLS] unknown[%d] <--- OTA",
614 				   action_frame_type);
615 		} else {
616 			tdls_notice("[TDLS] %s <--- OTA",
617 				   tdls_action_frames_type[action_frame_type]);
618 		}
619 	}
620 
621 	/* tdls_soc_obj->tdls_rx_cb ==> wlan_cfg80211_tdls_rx_callback() */
622 	if (tdls_soc_obj && tdls_soc_obj->tdls_rx_cb)
623 		tdls_soc_obj->tdls_rx_cb(tdls_soc_obj->tdls_rx_cb_data,
624 					 rx_mgmt);
625 	else
626 		tdls_debug("rx mgmt, but no valid up layer callback");
627 
628 	if (tdls_vdev_select && tdls_vdev->rx_mgmt) {
629 		qdf_mem_free(tdls_vdev->rx_mgmt);
630 		tdls_vdev->rx_mgmt = NULL;
631 		tdls_vdev->link_score = 0;
632 	}
633 
634 	return QDF_STATUS_SUCCESS;
635 }
636 
tdls_process_rx_frame(struct scheduler_msg * msg)637 QDF_STATUS tdls_process_rx_frame(struct scheduler_msg *msg)
638 {
639 	struct wlan_objmgr_vdev *vdev;
640 	struct tdls_rx_mgmt_event *tdls_rx;
641 	struct tdls_vdev_priv_obj *tdls_vdev;
642 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
643 
644 	if (!(msg->bodyptr)) {
645 		tdls_err("invalid message body");
646 		return QDF_STATUS_E_INVAL;
647 	}
648 
649 	tdls_rx = (struct tdls_rx_mgmt_event *) msg->bodyptr;
650 
651 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(tdls_rx->tdls_soc_obj->soc,
652 				tdls_rx->rx_mgmt->vdev_id, WLAN_TDLS_NB_ID);
653 
654 	if (vdev) {
655 		tdls_debug("tdls rx mgmt frame received");
656 		tdls_vdev = wlan_objmgr_vdev_get_comp_private_obj(vdev,
657 							WLAN_UMAC_COMP_TDLS);
658 		if (tdls_vdev)
659 			status = tdls_process_rx_mgmt(tdls_rx, tdls_vdev);
660 		wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
661 	}
662 
663 	qdf_mem_free(tdls_rx->rx_mgmt);
664 	qdf_mem_free(msg->bodyptr);
665 	msg->bodyptr = NULL;
666 
667 	return status;
668 }
669 
tdls_mgmt_rx_ops(struct wlan_objmgr_psoc * psoc,bool isregister)670 QDF_STATUS tdls_mgmt_rx_ops(struct wlan_objmgr_psoc *psoc,
671 	bool isregister)
672 {
673 	struct mgmt_txrx_mgmt_frame_cb_info frm_cb_info;
674 	QDF_STATUS status;
675 	int num_of_entries;
676 
677 	tdls_debug("psoc:%pK, is register rx:%d", psoc, isregister);
678 
679 	frm_cb_info.frm_type = MGMT_ACTION_TDLS_DISCRESP;
680 	frm_cb_info.mgmt_rx_cb = tgt_tdls_mgmt_frame_rx_cb;
681 	num_of_entries = 1;
682 
683 	if (isregister)
684 		status = wlan_mgmt_txrx_register_rx_cb(psoc,
685 				WLAN_UMAC_COMP_TDLS, &frm_cb_info,
686 				num_of_entries);
687 	else
688 		status = wlan_mgmt_txrx_deregister_rx_cb(psoc,
689 				WLAN_UMAC_COMP_TDLS, &frm_cb_info,
690 				num_of_entries);
691 
692 	return status;
693 }
694 
695 static QDF_STATUS
tdls_internal_send_mgmt_tx_done(struct tdls_action_frame_request * req,QDF_STATUS status)696 tdls_internal_send_mgmt_tx_done(struct tdls_action_frame_request *req,
697 				QDF_STATUS status)
698 {
699 	struct tdls_soc_priv_obj *tdls_soc_obj;
700 	struct tdls_osif_indication indication;
701 
702 	if (!req || !req->vdev)
703 		return QDF_STATUS_E_NULL_VALUE;
704 
705 	indication.status = status;
706 	indication.vdev = req->vdev;
707 	tdls_soc_obj = wlan_vdev_get_tdls_soc_obj(req->vdev);
708 	if (tdls_soc_obj && tdls_soc_obj->tdls_event_cb)
709 		tdls_soc_obj->tdls_event_cb(tdls_soc_obj->tdls_evt_cb_data,
710 			TDLS_EVENT_MGMT_TX_ACK_CNF, &indication);
711 	return QDF_STATUS_SUCCESS;
712 }
713 
tdls_activate_send_mgmt_request_flush_cb(struct scheduler_msg * msg)714 static QDF_STATUS tdls_activate_send_mgmt_request_flush_cb(
715 	struct scheduler_msg *msg)
716 {
717 	struct tdls_send_mgmt_request *tdls_mgmt_req;
718 
719 	tdls_mgmt_req = msg->bodyptr;
720 
721 	qdf_mem_free(tdls_mgmt_req);
722 	msg->bodyptr = NULL;
723 
724 	return QDF_STATUS_SUCCESS;
725 }
726 
727 static QDF_STATUS
tdls_activate_send_mgmt_request(struct tdls_action_frame_request * action_req)728 tdls_activate_send_mgmt_request(struct tdls_action_frame_request *action_req)
729 {
730 	struct tdls_soc_priv_obj *tdls_soc_obj;
731 	QDF_STATUS status;
732 	struct tdls_send_mgmt_request *tdls_mgmt_req;
733 	struct wlan_objmgr_peer *peer;
734 	struct scheduler_msg msg = {0};
735 	struct tdls_vdev_priv_obj *tdls_vdev;
736 
737 	if (!action_req || !action_req->vdev)
738 		return QDF_STATUS_E_NULL_VALUE;
739 
740 	tdls_soc_obj = wlan_vdev_get_tdls_soc_obj(action_req->vdev);
741 	if (!tdls_soc_obj) {
742 		status = QDF_STATUS_E_NULL_VALUE;
743 		goto release_cmd;
744 	}
745 
746 	tdls_mgmt_req = qdf_mem_malloc(sizeof(struct tdls_send_mgmt_request) +
747 				action_req->tdls_mgmt.len);
748 	if (!tdls_mgmt_req) {
749 		status = QDF_STATUS_E_NOMEM;
750 		goto release_cmd;
751 	}
752 
753 	tdls_debug("session_id %d "
754 		   "tdls_mgmt.dialog %d "
755 		   "tdls_mgmt.frame_type %d "
756 		   "tdls_mgmt.status_code %d "
757 		   "tdls_mgmt.responder %d "
758 		   "tdls_mgmt.peer_capability %d",
759 		   action_req->session_id,
760 		   action_req->tdls_mgmt.dialog,
761 		   action_req->tdls_mgmt.frame_type,
762 		   action_req->tdls_mgmt.status_code,
763 		   action_req->tdls_mgmt.responder,
764 		   action_req->tdls_mgmt.peer_capability);
765 
766 	tdls_mgmt_req->session_id = action_req->session_id;
767 	tdls_mgmt_req->req_type = action_req->tdls_mgmt.frame_type;
768 	tdls_mgmt_req->dialog = action_req->tdls_mgmt.dialog;
769 	tdls_mgmt_req->status_code = action_req->tdls_mgmt.status_code;
770 	tdls_mgmt_req->responder = action_req->tdls_mgmt.responder;
771 	tdls_mgmt_req->peer_capability = action_req->tdls_mgmt.peer_capability;
772 
773 	peer = wlan_objmgr_vdev_try_get_bsspeer(action_req->vdev,
774 						WLAN_TDLS_SB_ID);
775 	if (!peer) {
776 		tdls_err("bss peer is null");
777 		qdf_mem_free(tdls_mgmt_req);
778 		status = QDF_STATUS_E_NULL_VALUE;
779 		goto release_cmd;
780 	}
781 
782 	qdf_mem_copy(tdls_mgmt_req->bssid.bytes,
783 		     wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
784 
785 	wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_SB_ID);
786 
787 	qdf_mem_copy(tdls_mgmt_req->peer_mac.bytes,
788 		     action_req->tdls_mgmt.peer_mac.bytes, QDF_MAC_ADDR_SIZE);
789 
790 	if (action_req->tdls_mgmt.len) {
791 		qdf_mem_copy(tdls_mgmt_req->add_ie, action_req->tdls_mgmt.buf,
792 			     action_req->tdls_mgmt.len);
793 	}
794 
795 	tdls_mgmt_req->length = sizeof(struct tdls_send_mgmt_request) +
796 				action_req->tdls_mgmt.len;
797 	if (action_req->use_default_ac)
798 		tdls_mgmt_req->ac = WIFI_AC_VI;
799 	else
800 		tdls_mgmt_req->ac = WIFI_AC_BK;
801 
802 	if (wlan_vdev_mlme_is_mlo_vdev(action_req->vdev) &&
803 	    !tdls_mlo_get_tdls_link_vdev(action_req->vdev) &&
804 	    tdls_mgmt_req->req_type == TDLS_DISCOVERY_REQUEST) {
805 		tdls_vdev = wlan_vdev_get_tdls_vdev_obj(action_req->vdev);
806 		if (QDF_TIMER_STATE_RUNNING !=
807 		    qdf_mc_timer_get_current_state(
808 					  &tdls_vdev->peer_discovery_timer)) {
809 			tdls_timer_restart(tdls_vdev->vdev,
810 				     &tdls_vdev->peer_discovery_timer,
811 				     tdls_vdev->threshold_config.tx_period_t -
812 				     TDLS_DISCOVERY_TIMEOUT_ERE_UPDATE);
813 			qdf_atomic_inc(&tdls_soc_obj->timer_cnt);
814 		} else {
815 			qdf_mem_free(tdls_mgmt_req);
816 			status = QDF_STATUS_E_NULL_VALUE;
817 			goto release_cmd;
818 		}
819 	}
820 
821 	/* Send the request to PE. */
822 	qdf_mem_zero(&msg, sizeof(msg));
823 
824 	tdls_debug("sending TDLS Mgmt Frame req to PE ");
825 	tdls_mgmt_req->message_type = tdls_soc_obj->tdls_send_mgmt_req;
826 
827 	msg.type = tdls_soc_obj->tdls_send_mgmt_req;
828 	msg.bodyptr = tdls_mgmt_req;
829 	msg.flush_callback = tdls_activate_send_mgmt_request_flush_cb;
830 
831 	status = scheduler_post_message(QDF_MODULE_ID_TDLS,
832 					QDF_MODULE_ID_TDLS,
833 					QDF_MODULE_ID_PE, &msg);
834 	if (QDF_IS_STATUS_ERROR(status))
835 		qdf_mem_free(tdls_mgmt_req);
836 
837 release_cmd:
838 	/*update tdls nss infornation based on action code */
839 	tdls_reset_nss(tdls_soc_obj, action_req->chk_frame.action_code);
840 	if (QDF_IS_STATUS_ERROR(status)) {
841 		tdls_internal_send_mgmt_tx_done(action_req, status);
842 		tdls_release_serialization_command(action_req->vdev,
843 						   WLAN_SER_CMD_TDLS_SEND_MGMT);
844 	}
845 
846 	return status;
847 }
848 
849 static QDF_STATUS
tdls_send_mgmt_serialize_callback(struct wlan_serialization_command * cmd,enum wlan_serialization_cb_reason reason)850 tdls_send_mgmt_serialize_callback(struct wlan_serialization_command *cmd,
851 	 enum wlan_serialization_cb_reason reason)
852 {
853 	struct tdls_action_frame_request *req;
854 	QDF_STATUS status = QDF_STATUS_SUCCESS;
855 
856 	if (!cmd || !cmd->umac_cmd) {
857 		tdls_err("invalid params cmd: %pK, ", cmd);
858 		return QDF_STATUS_E_NULL_VALUE;
859 	}
860 	req = cmd->umac_cmd;
861 
862 	switch (reason) {
863 	case WLAN_SER_CB_ACTIVATE_CMD:
864 		/* command moved to active list */
865 		status = tdls_activate_send_mgmt_request(req);
866 		break;
867 
868 	case WLAN_SER_CB_CANCEL_CMD:
869 	case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
870 		/* command removed from pending list.
871 		 * notify status complete with failure
872 		 */
873 		status = tdls_internal_send_mgmt_tx_done(req,
874 				QDF_STATUS_E_FAILURE);
875 		break;
876 
877 	case WLAN_SER_CB_RELEASE_MEM_CMD:
878 		/* command successfully completed.
879 		 * release tdls_action_frame_request memory
880 		 */
881 		wlan_objmgr_vdev_release_ref(req->vdev, WLAN_TDLS_NB_ID);
882 		qdf_mem_free(req);
883 		break;
884 
885 	default:
886 		/* Do nothing but logging */
887 		QDF_ASSERT(0);
888 		status = QDF_STATUS_E_INVAL;
889 		break;
890 	}
891 
892 	return status;
893 }
894 
895 #ifdef WLAN_FEATURE_11BE_MLO
tdls_set_link_mode(struct tdls_action_frame_request * req)896 QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
897 {
898 	struct wlan_objmgr_psoc *psoc;
899 	struct wlan_objmgr_vdev *mlo_tdls_vdev;
900 	bool is_mlo_vdev;
901 	QDF_STATUS status = QDF_STATUS_SUCCESS;
902 	struct ml_nlink_change_event data;
903 	uint8_t num_ml_sta = 0;
904 	uint8_t ml_sta_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0};
905 
906 	is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(req->vdev);
907 	if (!is_mlo_vdev)
908 		return status;
909 
910 	psoc = wlan_vdev_get_psoc(req->vdev);
911 	if (!psoc) {
912 		tdls_err("psoc is NULL");
913 		return QDF_STATUS_E_NULL_VALUE;
914 	}
915 
916 
917 	if (req->tdls_mgmt.frame_type == TDLS_DISCOVERY_RESPONSE ||
918 	    req->tdls_mgmt.frame_type == TDLS_DISCOVERY_REQUEST) {
919 		mlo_tdls_vdev = wlan_mlo_get_tdls_link_vdev(req->vdev);
920 		if (mlo_tdls_vdev)
921 			return status;
922 
923 		status = policy_mgr_is_ml_links_in_mcc_allowed(
924 						psoc, req->vdev,
925 						ml_sta_vdev_lst,
926 						&num_ml_sta);
927 		if (QDF_IS_STATUS_SUCCESS(status)) {
928 			tdls_err("ML STA Links in MCC, so don't send the TDLS frames");
929 			return QDF_STATUS_E_FAILURE;
930 		}
931 
932 		qdf_mem_zero(&data, sizeof(data));
933 		data.evt.tdls.link_bitmap =
934 				1 << wlan_vdev_get_link_id(req->vdev);
935 		data.evt.tdls.mlo_vdev_lst[0] = wlan_vdev_get_id(req->vdev);
936 		data.evt.tdls.vdev_count = 1;
937 		data.evt.tdls.mode = MLO_LINK_FORCE_MODE_ACTIVE;
938 		data.evt.tdls.reason = MLO_LINK_FORCE_REASON_TDLS;
939 		status =
940 		ml_nlink_conn_change_notify(psoc,
941 					    wlan_vdev_get_id(req->vdev),
942 					    ml_nlink_tdls_request_evt,
943 					    &data);
944 		if (status == QDF_STATUS_SUCCESS ||
945 		    status == QDF_STATUS_E_PENDING)
946 			req->link_active = true;
947 	} else if (req->tdls_mgmt.frame_type == TDLS_MAX_ACTION_CODE) {
948 		qdf_mem_zero(&data, sizeof(data));
949 		data.evt.tdls.link_bitmap =
950 				1 << wlan_vdev_get_link_id(req->vdev);
951 		data.evt.tdls.mlo_vdev_lst[0] = wlan_vdev_get_id(req->vdev);
952 		data.evt.tdls.vdev_count = 1;
953 		data.evt.tdls.mode = MLO_LINK_FORCE_MODE_NO_FORCE;
954 		data.evt.tdls.reason = MLO_LINK_FORCE_REASON_TDLS;
955 		status =
956 		ml_nlink_conn_change_notify(psoc,
957 					    wlan_vdev_get_id(req->vdev),
958 					    ml_nlink_tdls_request_evt,
959 					    &data);
960 	}
961 	if (status == QDF_STATUS_E_PENDING)
962 		status = QDF_STATUS_SUCCESS;
963 
964 	return status;
965 }
966 #else
tdls_set_link_mode(struct tdls_action_frame_request * req)967 QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
968 {
969 	return QDF_STATUS_SUCCESS;
970 }
971 #endif
972 
tdls_process_mgmt_req(struct tdls_action_frame_request * tdls_mgmt_req)973 QDF_STATUS tdls_process_mgmt_req(
974 			struct tdls_action_frame_request *tdls_mgmt_req)
975 {
976 	QDF_STATUS status = QDF_STATUS_SUCCESS;
977 	struct wlan_serialization_command cmd = {0, };
978 	enum wlan_serialization_status ser_cmd_status;
979 
980 	/* If connected and in Infra. Only then allow this */
981 	status = tdls_validate_mgmt_request(tdls_mgmt_req);
982 	if (status != QDF_STATUS_SUCCESS) {
983 		status = tdls_internal_send_mgmt_tx_done(tdls_mgmt_req,
984 							 status);
985 		goto error_mgmt;
986 	}
987 
988 	status = tdls_set_link_mode(tdls_mgmt_req);
989 	if (status != QDF_STATUS_SUCCESS) {
990 		tdls_err("failed to set link:%d active",
991 			 wlan_vdev_get_link_id(tdls_mgmt_req->vdev));
992 		status = tdls_internal_send_mgmt_tx_done(tdls_mgmt_req,
993 							 status);
994 		goto error_mgmt;
995 	}
996 
997 	/* update the responder, status code information
998 	 * after the  cmd validation
999 	 */
1000 	tdls_mgmt_req->tdls_mgmt.responder =
1001 			!tdls_mgmt_req->chk_frame.responder;
1002 	tdls_mgmt_req->tdls_mgmt.status_code =
1003 			tdls_mgmt_req->chk_frame.status_code;
1004 
1005 	cmd.cmd_type = WLAN_SER_CMD_TDLS_SEND_MGMT;
1006 	/* Cmd Id not applicable for non scan cmds */
1007 	cmd.cmd_id = 0;
1008 	cmd.cmd_cb = tdls_send_mgmt_serialize_callback;
1009 	cmd.umac_cmd = tdls_mgmt_req;
1010 	cmd.source = WLAN_UMAC_COMP_TDLS;
1011 	cmd.is_high_priority = false;
1012 	cmd.cmd_timeout_duration = TDLS_DEFAULT_SERIALIZE_CMD_TIMEOUT;
1013 
1014 	cmd.vdev = tdls_mgmt_req->vdev;
1015 	cmd.is_blocking = true;
1016 
1017 	ser_cmd_status = wlan_serialization_request(&cmd);
1018 	tdls_debug("wlan_serialization_request status:%d", ser_cmd_status);
1019 
1020 	switch (ser_cmd_status) {
1021 	case WLAN_SER_CMD_PENDING:
1022 		/* command moved to pending list.Do nothing */
1023 		break;
1024 	case WLAN_SER_CMD_ACTIVE:
1025 		/* command moved to active list. Do nothing */
1026 		break;
1027 	case WLAN_SER_CMD_DENIED_LIST_FULL:
1028 	case WLAN_SER_CMD_DENIED_RULES_FAILED:
1029 	case WLAN_SER_CMD_DENIED_UNSPECIFIED:
1030 		status = QDF_STATUS_E_FAILURE;
1031 		goto error_mgmt;
1032 	default:
1033 		QDF_ASSERT(0);
1034 		status = QDF_STATUS_E_INVAL;
1035 		goto error_mgmt;
1036 	}
1037 	return status;
1038 
1039 error_mgmt:
1040 	wlan_objmgr_vdev_release_ref(tdls_mgmt_req->vdev, WLAN_TDLS_NB_ID);
1041 	qdf_mem_free(tdls_mgmt_req);
1042 	return status;
1043 }
1044