xref: /wlan-driver/qcacld-3.0/components/tdls/core/src/wlan_tdls_cmds_process.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-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_cmds_process.c
22  *
23  * TDLS north bound commands implementation
24  */
25 #include <qdf_types.h>
26 #include <qdf_status.h>
27 #include <wlan_cmn.h>
28 #include <reg_services_public_struct.h>
29 #include <wlan_objmgr_psoc_obj.h>
30 #include <wlan_objmgr_pdev_obj.h>
31 #include <wlan_reg_services_api.h>
32 #include <wlan_serialization_api.h>
33 #include "wlan_tdls_main.h"
34 #include "wlan_tdls_peer.h"
35 #include "wlan_tdls_ct.h"
36 #include "wlan_tdls_mgmt.h"
37 #include "wlan_tdls_cmds_process.h"
38 #include "wlan_tdls_tgt_api.h"
39 #include "wlan_policy_mgr_api.h"
40 #include "nan_ucfg_api.h"
41 #include "wlan_mlme_main.h"
42 #include "wlan_policy_mgr_i.h"
43 
tdls_get_connected_peer_count(struct tdls_soc_priv_obj * soc_obj)44 static uint16_t tdls_get_connected_peer_count(struct tdls_soc_priv_obj *soc_obj)
45 {
46 	return soc_obj->connected_peer_count;
47 }
48 
tdls_get_connected_peer_count_from_vdev(struct wlan_objmgr_vdev * vdev)49 uint16_t tdls_get_connected_peer_count_from_vdev(struct wlan_objmgr_vdev *vdev)
50 {
51 	struct tdls_soc_priv_obj *soc_obj;
52 
53 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
54 
55 	if (!soc_obj)
56 		return 0;
57 
58 	return tdls_get_connected_peer_count(soc_obj);
59 }
60 
61 #ifdef WLAN_FEATURE_11AX
62 static
tdls_get_mlme_ch_power(struct vdev_mlme_obj * mlme_obj,qdf_freq_t freq)63 uint8_t tdls_get_mlme_ch_power(struct vdev_mlme_obj *mlme_obj, qdf_freq_t freq)
64 {
65 	uint8_t num_power = mlme_obj->reg_tpc_obj.num_pwr_levels;
66 	uint8_t idx;
67 	struct reg_tpc_power_info *reg_power_info;
68 
69 	reg_power_info = &mlme_obj->reg_tpc_obj;
70 	for (idx = 0; idx < num_power; idx++) {
71 		if (freq == reg_power_info->chan_power_info[idx].chan_cfreq)
72 			return reg_power_info->chan_power_info[idx].tx_power;
73 	}
74 
75 	tdls_debug("channel %d not present in reg power info", freq);
76 	return 0;
77 }
78 
79 static
tdls_set_mlme_ch_power(struct wlan_objmgr_vdev * vdev,struct vdev_mlme_obj * mlme_obj,struct tdls_soc_priv_obj * tdls_soc_obj,qdf_freq_t freq)80 void tdls_set_mlme_ch_power(struct wlan_objmgr_vdev *vdev,
81 			    struct vdev_mlme_obj *mlme_obj,
82 			    struct tdls_soc_priv_obj *tdls_soc_obj,
83 			    qdf_freq_t freq)
84 {
85 	uint8_t num_power = mlme_obj->reg_tpc_obj.num_pwr_levels;
86 	uint8_t idx, tx_power;
87 	struct reg_tpc_power_info *reg_power_info = &mlme_obj->reg_tpc_obj;
88 
89 	if (REG_VERY_LOW_POWER_AP == reg_power_info->power_type_6g)
90 		tx_power = tdls_get_6g_pwr_for_power_type(vdev, freq,
91 							  REG_CLI_DEF_VLP);
92 	else
93 		tx_power = tdls_soc_obj->bss_sta_power;
94 
95 	for (idx = 0; idx < num_power; idx++) {
96 		if (freq == reg_power_info->chan_power_info[idx].chan_cfreq) {
97 			reg_power_info->chan_power_info[idx].tx_power =
98 								tx_power;
99 			return;
100 		}
101 	}
102 
103 	tdls_debug("channel %d not present in reg power info", freq);
104 }
105 
106 static
tdls_update_6g_power(struct wlan_objmgr_vdev * vdev,struct tdls_soc_priv_obj * tdls_soc_obj,bool enable_link)107 void tdls_update_6g_power(struct wlan_objmgr_vdev *vdev,
108 			  struct tdls_soc_priv_obj *tdls_soc_obj,
109 			  bool enable_link)
110 {
111 	struct wlan_lmac_if_reg_tx_ops *tx_ops;
112 	struct vdev_mlme_obj *mlme_obj;
113 	struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
114 	qdf_freq_t freq = wlan_get_operation_chan_freq(vdev);
115 
116 	if (!psoc) {
117 		tdls_err("psoc is NULL");
118 		return;
119 	}
120 
121 	/*
122 	 * Check whether the frequency is 6ghz and tdls connection on 6ghz freq
123 	 * is allowed.
124 	 */
125 	if (!tdls_is_6g_freq_allowed(vdev, freq))
126 		return;
127 
128 	/*
129 	 * Since, 8 TDLS peers can be connected. If connected peer already
130 	 * exist then no need to set the power again.
131 	 * Similarly, for disconnection case, this function is called after
132 	 * just after connected peer count is decreased. If connected peer
133 	 * count exist after decrement of peer count that mean another peer
134 	 * exist and then no need to reset the BSS power.
135 	 * The power should only be set/reset when 1st peer gets connected or
136 	 * last connected peer gets disconnected.
137 	 */
138 	if (tdls_soc_obj->connected_peer_count) {
139 		tdls_debug("Number of connected peer %d",
140 			 tdls_soc_obj->connected_peer_count);
141 		return;
142 	}
143 
144 	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev);
145 	if (!mlme_obj) {
146 		tdls_err("vdev component object is NULL");
147 		return;
148 	}
149 
150 	if (enable_link) {
151 		tdls_soc_obj->bss_sta_power_type = REG_VERY_LOW_POWER_AP;
152 		/*
153 		 * No need to update power if BSS-STA link is already configured
154 		 * as VLP
155 		 */
156 		if (tdls_soc_obj->bss_sta_power_type ==
157 		    mlme_obj->reg_tpc_obj.power_type_6g)
158 			return;
159 
160 		tdls_soc_obj->bss_sta_power_type =
161 					mlme_obj->reg_tpc_obj.power_type_6g;
162 		mlme_obj->reg_tpc_obj.power_type_6g = REG_VERY_LOW_POWER_AP;
163 		tdls_soc_obj->bss_sta_power = tdls_get_mlme_ch_power(mlme_obj,
164 								     freq);
165 		tdls_debug("Updated power_type from %d to %d bss link power %d",
166 			   tdls_soc_obj->bss_sta_power_type,
167 			   mlme_obj->reg_tpc_obj.power_type_6g,
168 			   tdls_soc_obj->bss_sta_power);
169 	} else {
170 		if (REG_VERY_LOW_POWER_AP == tdls_soc_obj->bss_sta_power_type)
171 			return;
172 
173 		tdls_debug("Updated power_type_6g from %d to %d",
174 			   mlme_obj->reg_tpc_obj.power_type_6g,
175 			   tdls_soc_obj->bss_sta_power_type);
176 		mlme_obj->reg_tpc_obj.power_type_6g =
177 					tdls_soc_obj->bss_sta_power_type;
178 	}
179 	tdls_set_mlme_ch_power(vdev, mlme_obj, tdls_soc_obj, freq);
180 
181 	tx_ops = wlan_reg_get_tx_ops(psoc);
182 	if (tx_ops->set_tpc_power)
183 		tx_ops->set_tpc_power(psoc,
184 				      wlan_vdev_get_id(vdev),
185 				      &mlme_obj->reg_tpc_obj);
186 }
187 #else
188 static
tdls_update_6g_power(struct wlan_objmgr_vdev * vdev,struct tdls_soc_priv_obj * tdls_soc_obj,bool enable_link)189 void tdls_update_6g_power(struct wlan_objmgr_vdev *vdev,
190 			  struct tdls_soc_priv_obj *tdls_soc_obj,
191 			  bool enable_link)
192 {
193 }
194 #endif
195 
196 /**
197  * tdls_decrement_peer_count() - decrement connected TDLS peer counter
198  * @vdev: vdev object
199  * @soc_obj: TDLS soc object
200  *
201  * Used in scheduler thread context, no lock needed.
202  *
203  * Return: None.
204  */
tdls_decrement_peer_count(struct wlan_objmgr_vdev * vdev,struct tdls_soc_priv_obj * soc_obj)205 void tdls_decrement_peer_count(struct wlan_objmgr_vdev *vdev,
206 			       struct tdls_soc_priv_obj *soc_obj)
207 {
208 	if (soc_obj->connected_peer_count)
209 		soc_obj->connected_peer_count--;
210 
211 	tdls_debug("Connected peer count %d", soc_obj->connected_peer_count);
212 
213 	/* Need to update osif params when last peer gets disconnected */
214 	if (!soc_obj->connected_peer_count &&
215 	    soc_obj->tdls_osif_update_cb.tdls_osif_disconn_update)
216 		soc_obj->tdls_osif_update_cb.tdls_osif_disconn_update(vdev);
217 	tdls_update_6g_power(vdev, soc_obj, false);
218 
219 	/*
220 	 * Offchannel is allowed only when TDLS is connected with one peer.
221 	 * If more than one peer is connected then Offchannel is disabled by
222 	 * WMI_TDLS_SET_OFFCHAN_MODE_CMDID with DISABLE_CHANSWITCH.
223 	 * Hence, re-enable offchannel when only one connected peer is left.
224 	 */
225 	if (soc_obj->connected_peer_count == 1)
226 		tdls_set_tdls_offchannelmode(vdev, ENABLE_CHANSWITCH);
227 }
228 
229 /**
230  * tdls_increment_peer_count() - increment connected TDLS peer counter
231  * @soc_obj: TDLS soc object
232  *
233  * Used in scheduler thread context, no lock needed.
234  *
235  * Return: None.
236  */
tdls_increment_peer_count(struct tdls_soc_priv_obj * soc_obj)237 static void tdls_increment_peer_count(struct tdls_soc_priv_obj *soc_obj)
238 {
239 	soc_obj->connected_peer_count++;
240 	tdls_debug("Connected peer count %d", soc_obj->connected_peer_count);
241 }
242 
243 /**
244  * tdls_validate_current_mode() - check current TDL mode
245  * @soc_obj: TDLS soc object
246  *
247  * Return: QDF_STATUS_SUCCESS if TDLS enabled, other for disabled
248  */
tdls_validate_current_mode(struct tdls_soc_priv_obj * soc_obj)249 static QDF_STATUS tdls_validate_current_mode(struct tdls_soc_priv_obj *soc_obj)
250 {
251 	if (soc_obj->tdls_current_mode == TDLS_SUPPORT_DISABLED ||
252 	    soc_obj->tdls_current_mode == TDLS_SUPPORT_SUSPENDED) {
253 		tdls_err("TDLS mode disabled OR not enabled, current mode %d",
254 			 soc_obj->tdls_current_mode);
255 		return QDF_STATUS_E_NOSUPPORT;
256 	}
257 	return QDF_STATUS_SUCCESS;
258 }
259 
tdls_get_ser_cmd_str(enum wlan_serialization_cmd_type type)260 static char *tdls_get_ser_cmd_str(enum  wlan_serialization_cmd_type type)
261 {
262 	switch (type) {
263 	case WLAN_SER_CMD_TDLS_ADD_PEER:
264 		return "TDLS_ADD_PEER_CMD";
265 	case WLAN_SER_CMD_TDLS_DEL_PEER:
266 		return "TDLS_DEL_PEER_CMD";
267 	case WLAN_SER_CMD_TDLS_SEND_MGMT:
268 		return "TDLS_SEND_MGMT_CMD";
269 	default:
270 		return "UNKNOWN";
271 	}
272 }
273 
274 void
tdls_release_serialization_command(struct wlan_objmgr_vdev * vdev,enum wlan_serialization_cmd_type type)275 tdls_release_serialization_command(struct wlan_objmgr_vdev *vdev,
276 				   enum wlan_serialization_cmd_type type)
277 {
278 	struct wlan_serialization_queued_cmd_info cmd = {0};
279 
280 	cmd.cmd_type = type;
281 	cmd.cmd_id = 0;
282 	cmd.vdev = vdev;
283 
284 	tdls_debug("release %s", tdls_get_ser_cmd_str(type));
285 	/* Inform serialization for command completion */
286 	wlan_serialization_remove_cmd(&cmd);
287 }
288 
289 /**
290  * tdls_pe_add_peer() - send TDLS add peer request to PE
291  * @req: TDL add peer request
292  *
293  * Return: QDF_STATUS_SUCCESS for success; other values if failed
294  */
tdls_pe_add_peer(struct tdls_add_peer_request * req)295 static QDF_STATUS tdls_pe_add_peer(struct tdls_add_peer_request *req)
296 {
297 	struct tdls_add_sta_req *addstareq;
298 	struct wlan_objmgr_vdev *vdev;
299 	struct wlan_objmgr_peer *peer;
300 	struct tdls_soc_priv_obj *soc_obj;
301 	struct scheduler_msg msg = {0,};
302 	QDF_STATUS status;
303 
304 	addstareq = qdf_mem_malloc(sizeof(*addstareq));
305 	if (!addstareq)
306 		return QDF_STATUS_E_NOMEM;
307 
308 	vdev = req->vdev;
309 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
310 	if (!soc_obj) {
311 		tdls_err("NULL tdls soc object");
312 		status = QDF_STATUS_E_INVAL;
313 		goto error;
314 	}
315 
316 	addstareq->tdls_oper = TDLS_OPER_ADD;
317 	addstareq->transaction_id = 0;
318 
319 	addstareq->session_id = wlan_vdev_get_id(vdev);
320 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_TDLS_NB_ID);
321 	if (!peer) {
322 		tdls_err("bss peer is NULL");
323 		status = QDF_STATUS_E_INVAL;
324 		goto error;
325 	}
326 	wlan_peer_obj_lock(peer);
327 	qdf_mem_copy(addstareq->bssid.bytes,
328 		     wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
329 	wlan_peer_obj_unlock(peer);
330 	wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_NB_ID);
331 	qdf_mem_copy(addstareq->peermac.bytes, req->add_peer_req.peer_addr,
332 		     QDF_MAC_ADDR_SIZE);
333 
334 	tdls_debug("for " QDF_MAC_ADDR_FMT,
335 		   QDF_MAC_ADDR_REF(addstareq->peermac.bytes));
336 	msg.type = soc_obj->tdls_add_sta_req;
337 	msg.bodyptr = addstareq;
338 	status = scheduler_post_message(QDF_MODULE_ID_TDLS,
339 					QDF_MODULE_ID_PE,
340 					QDF_MODULE_ID_PE, &msg);
341 	if (QDF_IS_STATUS_ERROR(status)) {
342 		tdls_err("fail to post pe msg to add peer");
343 		goto error;
344 	}
345 	return status;
346 error:
347 	qdf_mem_free(addstareq);
348 	return status;
349 }
350 
351 /**
352  * tdls_pe_del_peer() - send TDLS delete peer request to PE
353  * @req: TDLS delete peer request
354  *
355  * Return: QDF_STATUS_SUCCESS for success; other values if failed
356  */
tdls_pe_del_peer(struct tdls_del_peer_request * req)357 QDF_STATUS tdls_pe_del_peer(struct tdls_del_peer_request *req)
358 {
359 	struct tdls_del_sta_req *delstareq;
360 	struct wlan_objmgr_vdev *vdev;
361 	struct wlan_objmgr_peer *peer;
362 	struct tdls_soc_priv_obj *soc_obj;
363 	struct scheduler_msg msg = {0,};
364 	QDF_STATUS status;
365 
366 	delstareq = qdf_mem_malloc(sizeof(*delstareq));
367 	if (!delstareq)
368 		return QDF_STATUS_E_NOMEM;
369 
370 	vdev = req->vdev;
371 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
372 	if (!soc_obj) {
373 		tdls_err("NULL tdls soc object");
374 		status = QDF_STATUS_E_INVAL;
375 		goto error;
376 	}
377 
378 	delstareq->transaction_id = 0;
379 
380 	delstareq->session_id = wlan_vdev_get_id(vdev);
381 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_TDLS_NB_ID);
382 	if (!peer) {
383 		tdls_err("bss peer is NULL");
384 		status = QDF_STATUS_E_INVAL;
385 		goto error;
386 	}
387 
388 	wlan_peer_obj_lock(peer);
389 	qdf_mem_copy(delstareq->bssid.bytes,
390 		     wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
391 	wlan_peer_obj_unlock(peer);
392 	wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_NB_ID);
393 	qdf_mem_copy(delstareq->peermac.bytes, req->del_peer_req.peer_addr,
394 		     QDF_MAC_ADDR_SIZE);
395 
396 	tdls_debug("for " QDF_MAC_ADDR_FMT,
397 		   QDF_MAC_ADDR_REF(delstareq->peermac.bytes));
398 	msg.type = soc_obj->tdls_del_sta_req;
399 	msg.bodyptr = delstareq;
400 	status = scheduler_post_message(QDF_MODULE_ID_TDLS,
401 					QDF_MODULE_ID_PE,
402 					QDF_MODULE_ID_PE, &msg);
403 	if (QDF_IS_STATUS_ERROR(status)) {
404 		tdls_err("fail to post pe msg to del peer");
405 		goto error;
406 	}
407 	return status;
408 error:
409 	qdf_mem_free(delstareq);
410 	return status;
411 }
412 #ifdef WLAN_FEATURE_11AX
tdls_pe_update_peer_6ghz_capa(struct tdls_add_sta_req * addstareq,struct tdls_update_peer_params * update_peer)413 static void tdls_pe_update_peer_6ghz_capa(struct tdls_add_sta_req *addstareq,
414 				struct tdls_update_peer_params *update_peer)
415 {
416 	qdf_mem_copy(&addstareq->he_6ghz_cap, &update_peer->he_6ghz_cap,
417 		     sizeof(update_peer->he_6ghz_cap));
418 }
419 
tdls_pe_update_peer_he_capa(struct tdls_add_sta_req * addstareq,struct tdls_update_peer_params * update_peer)420 static void tdls_pe_update_peer_he_capa(struct tdls_add_sta_req *addstareq,
421 				struct tdls_update_peer_params *update_peer)
422 {
423 	addstareq->he_cap_len = update_peer->he_cap_len;
424 	qdf_mem_copy(&addstareq->he_cap,
425 		     &update_peer->he_cap,
426 		     sizeof(update_peer->he_cap));
427 
428 	tdls_pe_update_peer_6ghz_capa(addstareq, update_peer);
429 }
430 #else
tdls_pe_update_peer_he_capa(struct tdls_add_sta_req * addstareq,struct tdls_update_peer_params * update_peer)431 static void tdls_pe_update_peer_he_capa(struct tdls_add_sta_req *addstareq,
432 				struct tdls_update_peer_params *update_peer)
433 {
434 }
435 #endif
436 
437 #ifdef WLAN_FEATURE_11BE
438 static inline void
tdls_pe_update_peer_eht_capa(struct tdls_add_sta_req * addstareq,struct tdls_update_peer_params * update_peer)439 tdls_pe_update_peer_eht_capa(struct tdls_add_sta_req *addstareq,
440 			     struct tdls_update_peer_params *update_peer)
441 {
442 	if (update_peer->ehtcap_present) {
443 		addstareq->ehtcap_present = update_peer->ehtcap_present;
444 		addstareq->eht_cap_len = update_peer->eht_cap_len;
445 		qdf_mem_copy(&addstareq->eht_cap,
446 			     &update_peer->eht_cap,
447 			     sizeof(update_peer->eht_cap));
448 	}
449 }
450 #else
451 static inline void
tdls_pe_update_peer_eht_capa(struct tdls_add_sta_req * addstareq,struct tdls_update_peer_params * update_peer)452 tdls_pe_update_peer_eht_capa(struct tdls_add_sta_req *addstareq,
453 			     struct tdls_update_peer_params *update_peer)
454 {
455 }
456 #endif
457 /**
458  * tdls_pe_update_peer() - send TDLS update peer request to PE
459  * @req: TDLS update peer request
460  *
461  * Return: QDF_STATUS_SUCCESS for success; other values if failed
462  */
tdls_pe_update_peer(struct tdls_update_peer_request * req)463 static QDF_STATUS tdls_pe_update_peer(struct tdls_update_peer_request *req)
464 {
465 	struct tdls_add_sta_req *addstareq;
466 	struct wlan_objmgr_vdev *vdev;
467 	struct wlan_objmgr_peer *peer;
468 	struct tdls_soc_priv_obj *soc_obj;
469 	struct scheduler_msg msg = {0,};
470 	struct tdls_update_peer_params *update_peer;
471 	QDF_STATUS status;
472 
473 	addstareq = qdf_mem_malloc(sizeof(*addstareq));
474 	if (!addstareq)
475 		return QDF_STATUS_E_NOMEM;
476 
477 	vdev = req->vdev;
478 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
479 	if (!soc_obj) {
480 		tdls_err("NULL tdls soc object");
481 		status = QDF_STATUS_E_INVAL;
482 		goto error;
483 	}
484 	update_peer = &req->update_peer_req;
485 
486 	addstareq->tdls_oper = TDLS_OPER_UPDATE;
487 	addstareq->transaction_id = 0;
488 
489 	addstareq->session_id = wlan_vdev_get_id(vdev);
490 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_TDLS_NB_ID);
491 	if (!peer) {
492 		tdls_err("bss peer is NULL");
493 		status = QDF_STATUS_E_INVAL;
494 		goto error;
495 	}
496 	wlan_peer_obj_lock(peer);
497 	qdf_mem_copy(addstareq->bssid.bytes,
498 		     wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
499 	wlan_peer_obj_unlock(peer);
500 	wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_NB_ID);
501 	qdf_mem_copy(addstareq->peermac.bytes, update_peer->peer_addr,
502 		     QDF_MAC_ADDR_SIZE);
503 	addstareq->capability = update_peer->capability;
504 	addstareq->uapsd_queues = update_peer->uapsd_queues;
505 	addstareq->max_sp = update_peer->max_sp;
506 
507 	qdf_mem_copy(addstareq->extn_capability,
508 		     update_peer->extn_capability, WLAN_MAC_MAX_EXTN_CAP);
509 	addstareq->htcap_present = update_peer->htcap_present;
510 	qdf_mem_copy(&addstareq->ht_cap,
511 		     &update_peer->ht_cap,
512 		     sizeof(update_peer->ht_cap));
513 	addstareq->vhtcap_present = update_peer->vhtcap_present;
514 	qdf_mem_copy(&addstareq->vht_cap,
515 		     &update_peer->vht_cap,
516 		     sizeof(update_peer->vht_cap));
517 	tdls_pe_update_peer_he_capa(addstareq, update_peer);
518 	tdls_pe_update_peer_eht_capa(addstareq, update_peer);
519 	addstareq->supported_rates_length = update_peer->supported_rates_len;
520 	addstareq->is_pmf = update_peer->is_pmf;
521 	qdf_mem_copy(&addstareq->supported_rates,
522 		     update_peer->supported_rates,
523 		     update_peer->supported_rates_len);
524 	tdls_debug("for " QDF_MAC_ADDR_FMT,
525 		   QDF_MAC_ADDR_REF(addstareq->peermac.bytes));
526 
527 	msg.type = soc_obj->tdls_add_sta_req;
528 	msg.bodyptr = addstareq;
529 	status = scheduler_post_message(QDF_MODULE_ID_TDLS,
530 					QDF_MODULE_ID_PE,
531 					QDF_MODULE_ID_PE, &msg);
532 	if (QDF_IS_STATUS_ERROR(status)) {
533 		tdls_err("fail to post pe msg to update peer");
534 		goto error;
535 	}
536 	return status;
537 error:
538 	qdf_mem_free(addstareq);
539 	return status;
540 }
541 
542 static QDF_STATUS
tdls_internal_add_peer_rsp(struct tdls_add_peer_request * req,QDF_STATUS status)543 tdls_internal_add_peer_rsp(struct tdls_add_peer_request *req,
544 			   QDF_STATUS status)
545 {
546 	struct tdls_soc_priv_obj *soc_obj;
547 	struct wlan_objmgr_vdev *vdev;
548 	struct tdls_osif_indication ind;
549 	QDF_STATUS ret;
550 
551 	if (!req || !req->vdev) {
552 		tdls_err("req: %pK", req);
553 		return QDF_STATUS_E_INVAL;
554 	}
555 	vdev = req->vdev;
556 	ret = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_SB_ID);
557 	if (QDF_IS_STATUS_ERROR(ret)) {
558 		tdls_err("can't get vdev object");
559 		return ret;
560 	}
561 
562 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
563 	if (soc_obj && soc_obj->tdls_event_cb) {
564 		ind.vdev = vdev;
565 		ind.status = status;
566 		soc_obj->tdls_event_cb(soc_obj->tdls_evt_cb_data,
567 				       TDLS_EVENT_ADD_PEER, &ind);
568 	}
569 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
570 
571 	return QDF_STATUS_SUCCESS;
572 }
573 
574 static QDF_STATUS
tdls_internal_update_peer_rsp(struct tdls_update_peer_request * req,QDF_STATUS status)575 tdls_internal_update_peer_rsp(struct tdls_update_peer_request *req,
576 			      QDF_STATUS status)
577 {
578 	struct tdls_soc_priv_obj *soc_obj;
579 	struct tdls_osif_indication ind;
580 	struct wlan_objmgr_vdev *vdev;
581 	QDF_STATUS ret;
582 
583 	if (!req || !req->vdev) {
584 		tdls_err("req: %pK", req);
585 		return QDF_STATUS_E_INVAL;
586 	}
587 	vdev = req->vdev;
588 	ret = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_SB_ID);
589 	if (QDF_IS_STATUS_ERROR(ret)) {
590 		tdls_err("can't get vdev object");
591 		return ret;
592 	}
593 
594 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
595 	if (soc_obj && soc_obj->tdls_event_cb) {
596 		ind.vdev = vdev;
597 		ind.status = status;
598 		soc_obj->tdls_event_cb(soc_obj->tdls_evt_cb_data,
599 				       TDLS_EVENT_ADD_PEER, &ind);
600 	}
601 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
602 
603 	return QDF_STATUS_SUCCESS;
604 }
605 
tdls_internal_del_peer_rsp(struct tdls_oper_request * req)606 static QDF_STATUS tdls_internal_del_peer_rsp(struct tdls_oper_request *req)
607 {
608 	struct tdls_soc_priv_obj *soc_obj;
609 	struct tdls_osif_indication ind;
610 	struct wlan_objmgr_vdev *vdev;
611 	QDF_STATUS status;
612 
613 	if (!req || !req->vdev) {
614 		tdls_err("req: %pK", req);
615 		return QDF_STATUS_E_INVAL;
616 	}
617 	vdev = req->vdev;
618 	status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
619 	if (QDF_IS_STATUS_ERROR(status)) {
620 		tdls_err("can't get vdev object");
621 		return status;
622 	}
623 
624 	soc_obj = wlan_vdev_get_tdls_soc_obj(req->vdev);
625 	if (soc_obj && soc_obj->tdls_event_cb) {
626 		ind.vdev = req->vdev;
627 		soc_obj->tdls_event_cb(soc_obj->tdls_evt_cb_data,
628 				       TDLS_EVENT_DEL_PEER, &ind);
629 	}
630 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
631 
632 	return QDF_STATUS_SUCCESS;
633 }
634 
tdls_activate_add_peer(struct tdls_add_peer_request * req)635 static QDF_STATUS tdls_activate_add_peer(struct tdls_add_peer_request *req)
636 {
637 	QDF_STATUS status;
638 	struct tdls_soc_priv_obj *soc_obj;
639 	struct tdls_vdev_priv_obj *vdev_obj;
640 	struct tdls_peer *peer;
641 	uint16_t curr_tdls_peers;
642 	const uint8_t *mac;
643 	struct tdls_osif_indication ind;
644 
645 	if (!req->vdev) {
646 		tdls_err("vdev null when add tdls peer");
647 		QDF_ASSERT(0);
648 		return QDF_STATUS_E_NULL_VALUE;
649 	}
650 
651 	mac = req->add_peer_req.peer_addr;
652 	soc_obj = wlan_vdev_get_tdls_soc_obj(req->vdev);
653 	vdev_obj = wlan_vdev_get_tdls_vdev_obj(req->vdev);
654 
655 	if (!soc_obj || !vdev_obj) {
656 		tdls_err("soc_obj: %pK, vdev_obj: %pK", soc_obj, vdev_obj);
657 		return QDF_STATUS_E_INVAL;
658 	}
659 	status = tdls_validate_current_mode(soc_obj);
660 	if (QDF_IS_STATUS_ERROR(status))
661 		goto addrsp;
662 
663 	peer = tdls_get_peer(vdev_obj, mac);
664 	if (!peer) {
665 		tdls_err("peer: " QDF_MAC_ADDR_FMT " not exist. invalid",
666 			 QDF_MAC_ADDR_REF(mac));
667 		status = QDF_STATUS_E_INVAL;
668 		goto addrsp;
669 	}
670 
671 	/* in add station, we accept existing valid sta_id if there is */
672 	if ((peer->link_status > TDLS_LINK_CONNECTING) ||
673 	    (peer->valid_entry)) {
674 		tdls_notice("link_status %d add peer ignored",
675 			    peer->link_status);
676 		status = QDF_STATUS_SUCCESS;
677 		goto addrsp;
678 	}
679 
680 	/* when others are on-going, we want to change link_status to idle */
681 	if (tdls_is_progress(vdev_obj, mac, true)) {
682 		tdls_notice(QDF_MAC_ADDR_FMT " TDLS setuping. Req declined.",
683 			    QDF_MAC_ADDR_REF(mac));
684 		status = QDF_STATUS_E_PERM;
685 		goto setlink;
686 	}
687 
688 	/* first to check if we reached to maximum supported TDLS peer. */
689 	curr_tdls_peers = tdls_get_connected_peer_count(soc_obj);
690 	if (soc_obj->max_num_tdls_sta <= curr_tdls_peers) {
691 		tdls_err(QDF_MAC_ADDR_FMT
692 			 " Request declined. Current %d, Max allowed %d.",
693 			 QDF_MAC_ADDR_REF(mac), curr_tdls_peers,
694 			 soc_obj->max_num_tdls_sta);
695 		status = QDF_STATUS_E_PERM;
696 		goto setlink;
697 	}
698 
699 	tdls_set_peer_link_status(peer,
700 				  TDLS_LINK_CONNECTING, TDLS_LINK_SUCCESS);
701 
702 	status = tdls_pe_add_peer(req);
703 	if (QDF_IS_STATUS_ERROR(status)) {
704 		tdls_err(QDF_MAC_ADDR_FMT " add peer failed with status %d",
705 			 QDF_MAC_ADDR_REF(mac), status);
706 		goto setlink;
707 	}
708 
709 	return QDF_STATUS_SUCCESS;
710 
711 setlink:
712 	tdls_set_link_status(vdev_obj, mac, TDLS_LINK_IDLE,
713 			     TDLS_LINK_UNSPECIFIED);
714 addrsp:
715 	if (soc_obj->tdls_event_cb) {
716 		ind.status = status;
717 		ind.vdev = req->vdev;
718 		soc_obj->tdls_event_cb(soc_obj->tdls_evt_cb_data,
719 				       TDLS_EVENT_ADD_PEER, &ind);
720 	}
721 
722 	return QDF_STATUS_E_PERM;
723 }
724 
725 static QDF_STATUS
tdls_add_peer_serialize_callback(struct wlan_serialization_command * cmd,enum wlan_serialization_cb_reason reason)726 tdls_add_peer_serialize_callback(struct wlan_serialization_command *cmd,
727 				 enum wlan_serialization_cb_reason reason)
728 {
729 	struct tdls_add_peer_request *req;
730 	QDF_STATUS status = QDF_STATUS_SUCCESS;
731 
732 	if (!cmd || !cmd->umac_cmd) {
733 		tdls_err("cmd: %pK, reason: %d", cmd, reason);
734 		return QDF_STATUS_E_NULL_VALUE;
735 	}
736 
737 	req = cmd->umac_cmd;
738 
739 	switch (reason) {
740 	case WLAN_SER_CB_ACTIVATE_CMD:
741 		/* command moved to active list
742 		 */
743 		status = tdls_activate_add_peer(req);
744 		break;
745 
746 	case WLAN_SER_CB_CANCEL_CMD:
747 		/* command removed from pending list.
748 		 * notify os interface the status
749 		 */
750 		status = tdls_internal_add_peer_rsp(req, QDF_STATUS_E_FAILURE);
751 		break;
752 
753 	case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
754 		/* active command time out. */
755 		status = tdls_internal_add_peer_rsp(req, QDF_STATUS_E_FAILURE);
756 		break;
757 
758 	case WLAN_SER_CB_RELEASE_MEM_CMD:
759 		/* command successfully completed.
760 		 * release memory & vdev reference count
761 		 */
762 		wlan_objmgr_vdev_release_ref(req->vdev, WLAN_TDLS_NB_ID);
763 		qdf_mem_free(req);
764 		break;
765 
766 	default:
767 		/* Do nothing but logging */
768 		QDF_ASSERT(0);
769 		status = QDF_STATUS_E_INVAL;
770 		break;
771 	}
772 
773 	return status;
774 }
775 
tdls_reset_nss(struct tdls_soc_priv_obj * tdls_soc,uint8_t action_code)776 void tdls_reset_nss(struct tdls_soc_priv_obj *tdls_soc,
777 				  uint8_t action_code)
778 {
779 	if (!tdls_soc)
780 		return;
781 
782 	if (TDLS_TEARDOWN != action_code ||
783 	    !tdls_soc->tdls_nss_switch_in_progress)
784 		return;
785 
786 	if (tdls_soc->tdls_teardown_peers_cnt != 0)
787 		tdls_soc->tdls_teardown_peers_cnt--;
788 	if (tdls_soc->tdls_teardown_peers_cnt == 0) {
789 		if (tdls_soc->tdls_nss_transition_mode ==
790 		    TDLS_NSS_TRANSITION_S_1x1_to_2x2) {
791 			/* TDLS NSS switch is fully completed, so
792 			 * reset the flags.
793 			 */
794 			tdls_notice("TDLS NSS switch is fully completed");
795 			tdls_soc->tdls_nss_switch_in_progress = false;
796 			tdls_soc->tdls_nss_teardown_complete = false;
797 		} else {
798 			/* TDLS NSS switch is not yet completed, but
799 			 * tdls teardown is completed for all the
800 			 * peers.
801 			 */
802 			tdls_notice("teardown done & NSS switch in progress");
803 			tdls_soc->tdls_nss_teardown_complete = true;
804 		}
805 		tdls_soc->tdls_nss_transition_mode =
806 			TDLS_NSS_TRANSITION_S_UNKNOWN;
807 	}
808 
809 }
810 
811 /**
812  * tdls_set_cap() - set TDLS capability type
813  * @tdls_vdev: tdls vdev object
814  * @mac: peer mac address
815  * @cap: TDLS capability type
816  *
817  * Return: 0 if successful or negative errno otherwise
818  */
tdls_set_cap(struct tdls_vdev_priv_obj * tdls_vdev,const uint8_t * mac,enum tdls_peer_capab cap)819 int tdls_set_cap(struct tdls_vdev_priv_obj *tdls_vdev, const uint8_t *mac,
820 			  enum tdls_peer_capab cap)
821 {
822 	struct tdls_peer *curr_peer;
823 
824 	curr_peer = tdls_get_peer(tdls_vdev, mac);
825 	if (!curr_peer) {
826 		tdls_err("curr_peer is NULL");
827 		return -EINVAL;
828 	}
829 
830 	curr_peer->tdls_support = cap;
831 	return 0;
832 }
833 
tdls_validate_setup_frames(struct tdls_soc_priv_obj * tdls_soc,struct tdls_validate_action_req * tdls_validate)834 static int tdls_validate_setup_frames(struct tdls_soc_priv_obj *tdls_soc,
835 				struct tdls_validate_action_req *tdls_validate)
836 {
837 	/* supplicant still sends tdls_mgmt(SETUP_REQ)
838 	 * even after we return error code at
839 	 * 'add_station()'. Hence we have this check
840 	 * again in addition to add_station().	Anyway,
841 	 * there is no harm to double-check.
842 	 */
843 	if (TDLS_SETUP_REQUEST == tdls_validate->action_code) {
844 		tdls_err(QDF_MAC_ADDR_FMT " TDLS Max peer already connected. action (%d) declined. Num of peers (%d), Max allowed (%d).",
845 			 QDF_MAC_ADDR_REF(tdls_validate->peer_mac),
846 			 tdls_validate->action_code,
847 			 tdls_soc->connected_peer_count,
848 			 tdls_soc->max_num_tdls_sta);
849 		return -EINVAL;
850 	}
851 	/* maximum reached. tweak to send
852 	 * error code to peer and return error
853 	 * code to supplicant
854 	 */
855 	tdls_validate->status_code = QDF_STATUS_E_RESOURCES;
856 	tdls_err(QDF_MAC_ADDR_FMT " TDLS Max peer already connected, send response status (%d). Num of peers (%d), Max allowed (%d).",
857 		 QDF_MAC_ADDR_REF(tdls_validate->peer_mac),
858 		 tdls_validate->action_code,
859 		 tdls_soc->connected_peer_count,
860 		 tdls_soc->max_num_tdls_sta);
861 
862 	return -EPERM;
863 }
864 
tdls_validate_mgmt_request(struct tdls_action_frame_request * tdls_mgmt_req)865 int tdls_validate_mgmt_request(struct tdls_action_frame_request *tdls_mgmt_req)
866 {
867 	struct tdls_vdev_priv_obj *tdls_vdev;
868 	struct tdls_soc_priv_obj *tdls_soc;
869 	struct tdls_peer *curr_peer;
870 	struct tdls_peer *temp_peer;
871 	QDF_STATUS status;
872 	uint8_t vdev_id;
873 
874 	struct wlan_objmgr_vdev *vdev = tdls_mgmt_req->vdev;
875 	struct tdls_validate_action_req *tdls_validate =
876 		&tdls_mgmt_req->chk_frame;
877 
878 	if (QDF_STATUS_SUCCESS != tdls_get_vdev_objects(vdev,
879 							&tdls_vdev,
880 							&tdls_soc))
881 		return -ENOTSUPP;
882 
883 	/*
884 	 * STA or P2P client should be connected and authenticated before
885 	 *  sending any TDLS frames
886 	 */
887 	if ((wlan_vdev_is_up(vdev) != QDF_STATUS_SUCCESS) ||
888 	    !tdls_is_vdev_authenticated(vdev)) {
889 		tdls_err("STA is not connected or not authenticated.");
890 		return -EAGAIN;
891 	}
892 
893 	/* other than teardown frame, mgmt frames are not sent if disabled */
894 	if (TDLS_TEARDOWN != tdls_validate->action_code) {
895 		if (!tdls_check_is_tdls_allowed(vdev)) {
896 			tdls_err("TDLS not allowed, reject MGMT, action = %d",
897 				tdls_validate->action_code);
898 			return -EPERM;
899 		}
900 		/* if tdls_mode is disabled, then decline the peer's request */
901 		if (TDLS_SUPPORT_DISABLED == tdls_soc->tdls_current_mode ||
902 		    TDLS_SUPPORT_SUSPENDED == tdls_soc->tdls_current_mode) {
903 			tdls_notice(QDF_MAC_ADDR_FMT
904 				" TDLS mode is disabled. action %d declined.",
905 				QDF_MAC_ADDR_REF(tdls_validate->peer_mac),
906 				tdls_validate->action_code);
907 			return -ENOTSUPP;
908 		}
909 		if (tdls_soc->tdls_nss_switch_in_progress) {
910 			tdls_err("nss switch in progress, action %d declined "
911 				QDF_MAC_ADDR_FMT,
912 				tdls_validate->action_code,
913 				QDF_MAC_ADDR_REF(tdls_validate->peer_mac));
914 			return -EAGAIN;
915 		}
916 	}
917 	/*
918 	 * In case another tdls request comes while tdls setup is already
919 	 * ongoing with one peer. Reject only when status code is 0. If status
920 	 * code is non-zero, it means supplicant already rejected it and
921 	 * the same should be notified to peer.
922 	 */
923 	if (TDLS_IS_SETUP_ACTION(tdls_validate->action_code)) {
924 		if (tdls_is_progress(tdls_vdev, tdls_validate->peer_mac,
925 				     true) &&
926 				     tdls_validate->status_code == 0) {
927 			tdls_err("setup is ongoing. action %d declined for "
928 				 QDF_MAC_ADDR_FMT,
929 				 tdls_validate->action_code,
930 				 QDF_MAC_ADDR_REF(tdls_validate->peer_mac));
931 			return -EPERM;
932 		}
933 	}
934 
935 	/*  call hdd_wmm_is_acm_allowed() */
936 	vdev_id = wlan_vdev_get_id(vdev);
937 	if (!tdls_soc->tdls_wmm_cb(vdev_id)) {
938 		tdls_debug("admission ctrl set to VI, send the frame with least AC (BK) for action %d",
939 			   tdls_validate->action_code);
940 		tdls_mgmt_req->use_default_ac = false;
941 	} else {
942 		tdls_mgmt_req->use_default_ac = true;
943 	}
944 
945 	if (TDLS_SETUP_REQUEST == tdls_validate->action_code ||
946 	    TDLS_SETUP_RESPONSE == tdls_validate->action_code) {
947 		if (tdls_soc->max_num_tdls_sta <=
948 			tdls_soc->connected_peer_count) {
949 			status = tdls_validate_setup_frames(tdls_soc,
950 							    tdls_validate);
951 			if (QDF_STATUS_SUCCESS != status)
952 				return status;
953 			/* fall through to send setup resp
954 			 * with failure status code
955 			 */
956 		} else {
957 			curr_peer =
958 				tdls_find_peer(tdls_vdev,
959 					       tdls_validate->peer_mac);
960 			if (curr_peer) {
961 				if (TDLS_IS_LINK_CONNECTED(curr_peer)) {
962 					tdls_err(QDF_MAC_ADDR_FMT " already connected action %d declined.",
963 						QDF_MAC_ADDR_REF(
964 						tdls_validate->peer_mac),
965 						tdls_validate->action_code);
966 
967 					return -EPERM;
968 				}
969 			}
970 		}
971 	}
972 
973 	tdls_debug("tdls_mgmt " QDF_MAC_ADDR_FMT " action %d, dialog_token %d status %d, len = %zu",
974 		   QDF_MAC_ADDR_REF(tdls_validate->peer_mac),
975 		   tdls_validate->action_code, tdls_validate->dialog_token,
976 		   tdls_validate->status_code, tdls_validate->len);
977 
978 	/*Except teardown responder will not be used so just make 0 */
979 	tdls_validate->responder = 0;
980 	if (TDLS_TEARDOWN == tdls_validate->action_code) {
981 		temp_peer = tdls_find_peer(tdls_vdev, tdls_validate->peer_mac);
982 		if (!temp_peer) {
983 			tdls_err(QDF_MAC_ADDR_FMT " peer doesn't exist",
984 				     QDF_MAC_ADDR_REF(
985 				     tdls_validate->peer_mac));
986 			return -EPERM;
987 		}
988 
989 		if (TDLS_IS_LINK_CONNECTED(temp_peer))
990 			tdls_validate->responder = temp_peer->is_responder;
991 		else {
992 			tdls_err(QDF_MAC_ADDR_FMT " peer doesn't exist or not connected %d dialog_token %d status %d, tdls_validate->len = %zu",
993 				 QDF_MAC_ADDR_REF(tdls_validate->peer_mac),
994 				 temp_peer->link_status,
995 				 tdls_validate->dialog_token,
996 				 tdls_validate->status_code,
997 				 tdls_validate->len);
998 			return -EPERM;
999 		}
1000 	}
1001 
1002 	/* For explicit trigger of DIS_REQ come out of BMPS for
1003 	 * successfully receiving DIS_RSP from peer.
1004 	 */
1005 	if ((TDLS_SETUP_RESPONSE == tdls_validate->action_code) ||
1006 	    (TDLS_SETUP_CONFIRM == tdls_validate->action_code) ||
1007 	    (TDLS_DISCOVERY_RESPONSE == tdls_validate->action_code) ||
1008 	    (TDLS_DISCOVERY_REQUEST == tdls_validate->action_code)) {
1009 		/* Fw will take care if PS offload is enabled. */
1010 		if (TDLS_DISCOVERY_REQUEST != tdls_validate->action_code)
1011 			tdls_set_cap(tdls_vdev, tdls_validate->peer_mac,
1012 					      TDLS_CAP_SUPPORTED);
1013 	}
1014 	return 0;
1015 }
1016 
tdls_process_add_peer(struct tdls_add_peer_request * req)1017 QDF_STATUS tdls_process_add_peer(struct tdls_add_peer_request *req)
1018 {
1019 	struct wlan_serialization_command cmd = {0,};
1020 	enum wlan_serialization_status ser_cmd_status;
1021 	struct wlan_objmgr_vdev *vdev;
1022 	QDF_STATUS status = QDF_STATUS_E_INVAL;
1023 	struct wlan_objmgr_psoc *psoc;
1024 
1025 	if (!req || !req->vdev) {
1026 		tdls_err("req: %pK", req);
1027 		goto free_req;
1028 	}
1029 	vdev = req->vdev;
1030 	if (!tdls_check_is_tdls_allowed(vdev)) {
1031 		tdls_err("TDLS not allowed, reject add station for vdev: %d",
1032 			 wlan_vdev_get_id(vdev));
1033 		goto error;
1034 	}
1035 
1036 	psoc = wlan_vdev_get_psoc(vdev);
1037 	if (!psoc) {
1038 		tdls_err("can't get psoc");
1039 		goto error;
1040 	}
1041 
1042 	status = QDF_STATUS_SUCCESS;
1043 
1044 	cmd.cmd_type = WLAN_SER_CMD_TDLS_ADD_PEER;
1045 	cmd.cmd_id = 0;
1046 	cmd.cmd_cb = tdls_add_peer_serialize_callback;
1047 	cmd.umac_cmd = req;
1048 	cmd.source = WLAN_UMAC_COMP_TDLS;
1049 	cmd.is_high_priority = false;
1050 	cmd.cmd_timeout_duration = TDLS_DEFAULT_SERIALIZE_CMD_TIMEOUT;
1051 	cmd.vdev = vdev;
1052 	cmd.is_blocking = true;
1053 
1054 	ser_cmd_status = wlan_serialization_request(&cmd);
1055 	tdls_debug("req: 0x%pK wlan_serialization_request status:%d", req,
1056 		   ser_cmd_status);
1057 
1058 	switch (ser_cmd_status) {
1059 	case WLAN_SER_CMD_PENDING:
1060 		/* command moved to pending list. Do nothing */
1061 		break;
1062 	case WLAN_SER_CMD_ACTIVE:
1063 		/* command moved to active list. Do nothing */
1064 		break;
1065 	default:
1066 		goto error;
1067 	}
1068 
1069 	return status;
1070 error:
1071 	/* notify os interface about internal error*/
1072 	status = tdls_internal_add_peer_rsp(req, QDF_STATUS_E_FAILURE);
1073 	wlan_objmgr_vdev_release_ref(req->vdev, WLAN_TDLS_NB_ID);
1074 free_req:
1075 	qdf_mem_free(req);
1076 	return status;
1077 }
1078 
1079 static QDF_STATUS
tdls_activate_update_peer(struct tdls_update_peer_request * req)1080 tdls_activate_update_peer(struct tdls_update_peer_request *req)
1081 {
1082 	QDF_STATUS status;
1083 	struct tdls_soc_priv_obj *soc_obj;
1084 	struct tdls_vdev_priv_obj *vdev_obj;
1085 	struct wlan_objmgr_vdev *vdev;
1086 	struct tdls_peer *curr_peer;
1087 	uint16_t curr_tdls_peers;
1088 	const uint8_t *mac;
1089 	struct tdls_update_peer_params *update_peer;
1090 	struct tdls_osif_indication ind;
1091 
1092 	if (!req->vdev) {
1093 		tdls_err("vdev object NULL when add TDLS peer");
1094 		QDF_ASSERT(0);
1095 		return QDF_STATUS_E_NULL_VALUE;
1096 	}
1097 
1098 	mac = req->update_peer_req.peer_addr;
1099 	vdev = req->vdev;
1100 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
1101 	vdev_obj = wlan_vdev_get_tdls_vdev_obj(vdev);
1102 	if (!soc_obj || !vdev_obj) {
1103 		tdls_err("soc_obj: %pK, vdev_obj: %pK", soc_obj, vdev_obj);
1104 		return QDF_STATUS_E_INVAL;
1105 	}
1106 
1107 	status = tdls_validate_current_mode(soc_obj);
1108 	if (QDF_IS_STATUS_ERROR(status))
1109 		goto updatersp;
1110 
1111 	curr_peer = tdls_find_peer(vdev_obj, mac);
1112 	if (!curr_peer) {
1113 		tdls_err(QDF_MAC_ADDR_FMT " not exist. return invalid",
1114 			 QDF_MAC_ADDR_REF(mac));
1115 		status = QDF_STATUS_E_INVAL;
1116 		goto updatersp;
1117 	}
1118 
1119 	/* in change station, we accept only when sta_id is valid */
1120 	if (curr_peer->link_status ==  TDLS_LINK_TEARING ||
1121 	    !curr_peer->valid_entry) {
1122 		tdls_err(QDF_MAC_ADDR_FMT " link %d. update peer rejected",
1123 			 QDF_MAC_ADDR_REF(mac), curr_peer->link_status);
1124 		status = QDF_STATUS_E_PERM;
1125 		goto updatersp;
1126 	}
1127 
1128 	if (curr_peer->link_status ==  TDLS_LINK_CONNECTED &&
1129 	    curr_peer->valid_entry) {
1130 		tdls_err(QDF_MAC_ADDR_FMT " link %d. update peer is igonored as tdls state is already connected ",
1131 			 QDF_MAC_ADDR_REF(mac), curr_peer->link_status);
1132 		status = QDF_STATUS_SUCCESS;
1133 		goto updatersp;
1134 	}
1135 
1136 	/* when others are on-going, we want to change link_status to idle */
1137 	if (tdls_is_progress(vdev_obj, mac, true)) {
1138 		tdls_notice(QDF_MAC_ADDR_FMT " TDLS setuping. Req declined.",
1139 			    QDF_MAC_ADDR_REF(mac));
1140 		status = QDF_STATUS_E_PERM;
1141 		goto setlink;
1142 	}
1143 
1144 	curr_tdls_peers = tdls_get_connected_peer_count(soc_obj);
1145 	if (soc_obj->max_num_tdls_sta <= curr_tdls_peers) {
1146 		tdls_err(QDF_MAC_ADDR_FMT
1147 			 " Request declined. Current: %d, Max allowed: %d.",
1148 			 QDF_MAC_ADDR_REF(mac), curr_tdls_peers,
1149 			 soc_obj->max_num_tdls_sta);
1150 		status = QDF_STATUS_E_PERM;
1151 		goto setlink;
1152 	}
1153 	update_peer = &req->update_peer_req;
1154 
1155 	if (update_peer->htcap_present)
1156 		curr_peer->spatial_streams = update_peer->ht_cap.mcsset[1];
1157 
1158 	tdls_set_peer_caps(vdev_obj, mac, &req->update_peer_req);
1159 	status = tdls_pe_update_peer(req);
1160 	if (QDF_IS_STATUS_ERROR(status)) {
1161 		tdls_err(QDF_MAC_ADDR_FMT " update peer failed with status %d",
1162 			 QDF_MAC_ADDR_REF(mac), status);
1163 		goto setlink;
1164 	}
1165 
1166 	return QDF_STATUS_SUCCESS;
1167 
1168 setlink:
1169 	tdls_set_link_status(vdev_obj, mac, TDLS_LINK_IDLE,
1170 			     TDLS_LINK_UNSPECIFIED);
1171 updatersp:
1172 	if (soc_obj->tdls_event_cb) {
1173 		ind.status = status;
1174 		ind.vdev = vdev;
1175 		soc_obj->tdls_event_cb(soc_obj->tdls_evt_cb_data,
1176 				       TDLS_EVENT_ADD_PEER, &ind);
1177 	}
1178 
1179 	return QDF_STATUS_E_PERM;
1180 }
1181 
1182 static QDF_STATUS
tdls_update_peer_serialize_callback(struct wlan_serialization_command * cmd,enum wlan_serialization_cb_reason reason)1183 tdls_update_peer_serialize_callback(struct wlan_serialization_command *cmd,
1184 				    enum wlan_serialization_cb_reason reason)
1185 {
1186 	struct tdls_update_peer_request *req;
1187 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1188 
1189 	if (!cmd || !cmd->umac_cmd) {
1190 		tdls_err("cmd: %pK, reason: %d", cmd, reason);
1191 		return QDF_STATUS_E_NULL_VALUE;
1192 	}
1193 
1194 	req = cmd->umac_cmd;
1195 
1196 	switch (reason) {
1197 	case WLAN_SER_CB_ACTIVATE_CMD:
1198 		/* command moved to active list
1199 		 */
1200 		status = tdls_activate_update_peer(req);
1201 		break;
1202 
1203 	case WLAN_SER_CB_CANCEL_CMD:
1204 		/* command removed from pending list.
1205 		 * notify os interface the status
1206 		 */
1207 		status = tdls_internal_update_peer_rsp(req,
1208 						       QDF_STATUS_E_FAILURE);
1209 		break;
1210 
1211 	case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
1212 		/* active command time out. */
1213 		status = tdls_internal_update_peer_rsp(req,
1214 						       QDF_STATUS_E_FAILURE);
1215 		break;
1216 
1217 	case WLAN_SER_CB_RELEASE_MEM_CMD:
1218 		/* command successfully completed.
1219 		 * release memory & release reference count
1220 		 */
1221 		wlan_objmgr_vdev_release_ref(req->vdev, WLAN_TDLS_NB_ID);
1222 		qdf_mem_free(req);
1223 		break;
1224 
1225 	default:
1226 		/* Do nothing but logging */
1227 		QDF_ASSERT(0);
1228 		status = QDF_STATUS_E_INVAL;
1229 		break;
1230 	}
1231 
1232 	return status;
1233 }
1234 
tdls_process_update_peer(struct tdls_update_peer_request * req)1235 QDF_STATUS tdls_process_update_peer(struct tdls_update_peer_request *req)
1236 {
1237 	struct wlan_serialization_command cmd = {0,};
1238 	enum wlan_serialization_status ser_cmd_status;
1239 	struct wlan_objmgr_vdev *vdev;
1240 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1241 
1242 	if (!req || !req->vdev) {
1243 		tdls_err("req: %pK", req);
1244 		status = QDF_STATUS_E_FAILURE;
1245 		goto free_req;
1246 	}
1247 
1248 	vdev = req->vdev;
1249 	cmd.cmd_type = WLAN_SER_CMD_TDLS_ADD_PEER;
1250 	cmd.cmd_id = 0;
1251 	cmd.cmd_cb = tdls_update_peer_serialize_callback;
1252 	cmd.umac_cmd = req;
1253 	cmd.source = WLAN_UMAC_COMP_TDLS;
1254 	cmd.is_high_priority = false;
1255 	cmd.cmd_timeout_duration = TDLS_DEFAULT_SERIALIZE_CMD_TIMEOUT;
1256 	cmd.vdev = req->vdev;
1257 	cmd.is_blocking = true;
1258 
1259 	ser_cmd_status = wlan_serialization_request(&cmd);
1260 	tdls_debug("req: 0x%pK wlan_serialization_request status:%d", req,
1261 		   ser_cmd_status);
1262 
1263 	switch (ser_cmd_status) {
1264 	case WLAN_SER_CMD_PENDING:
1265 		/* command moved to pending list. Do nothing */
1266 		break;
1267 	case WLAN_SER_CMD_ACTIVE:
1268 		/* command moved to active list. Do nothing */
1269 		break;
1270 	default:
1271 		goto error;
1272 	}
1273 
1274 	return status;
1275 error:
1276 	/* notify os interface about internal error*/
1277 	status = tdls_internal_update_peer_rsp(req, QDF_STATUS_E_FAILURE);
1278 	wlan_objmgr_vdev_release_ref(req->vdev, WLAN_TDLS_NB_ID);
1279 free_req:
1280 	qdf_mem_free(req);
1281 	return status;
1282 }
1283 
tdls_activate_del_peer(struct tdls_oper_request * req)1284 static QDF_STATUS tdls_activate_del_peer(struct tdls_oper_request *req)
1285 {
1286 	struct tdls_del_peer_request request = {0,};
1287 
1288 	request.vdev = req->vdev;
1289 	request.del_peer_req.peer_addr = req->peer_addr;
1290 
1291 	return tdls_pe_del_peer(&request);
1292 }
1293 
1294 static QDF_STATUS
tdls_del_peer_serialize_callback(struct wlan_serialization_command * cmd,enum wlan_serialization_cb_reason reason)1295 tdls_del_peer_serialize_callback(struct wlan_serialization_command *cmd,
1296 				 enum wlan_serialization_cb_reason reason)
1297 {
1298 	struct tdls_oper_request *req;
1299 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1300 
1301 	if (!cmd || !cmd->umac_cmd) {
1302 		tdls_err("cmd: %pK, reason: %d", cmd, reason);
1303 		return QDF_STATUS_E_NULL_VALUE;
1304 	}
1305 
1306 	req = cmd->umac_cmd;
1307 
1308 	switch (reason) {
1309 	case WLAN_SER_CB_ACTIVATE_CMD:
1310 		/* command moved to active list
1311 		 */
1312 		status = tdls_activate_del_peer(req);
1313 		break;
1314 
1315 	case WLAN_SER_CB_CANCEL_CMD:
1316 		/* command removed from pending list.
1317 		 * notify os interface the status
1318 		 */
1319 		status = tdls_internal_del_peer_rsp(req);
1320 		break;
1321 
1322 	case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
1323 		/* active command time out. */
1324 		status = tdls_internal_del_peer_rsp(req);
1325 		break;
1326 
1327 	case WLAN_SER_CB_RELEASE_MEM_CMD:
1328 		/* command successfully completed.
1329 		 * release memory & vdev reference count
1330 		 */
1331 		wlan_objmgr_vdev_release_ref(req->vdev, WLAN_TDLS_NB_ID);
1332 		qdf_mem_free(req);
1333 		break;
1334 
1335 	default:
1336 		/* Do nothing but logging */
1337 		QDF_ASSERT(0);
1338 		status = QDF_STATUS_E_INVAL;
1339 		break;
1340 	}
1341 
1342 	return status;
1343 }
1344 
tdls_process_del_peer(struct tdls_oper_request * req)1345 QDF_STATUS tdls_process_del_peer(struct tdls_oper_request *req)
1346 {
1347 	struct wlan_serialization_command cmd = {0,};
1348 	enum wlan_serialization_status ser_cmd_status;
1349 	struct wlan_objmgr_vdev *vdev;
1350 	struct tdls_vdev_priv_obj *vdev_obj;
1351 	struct tdls_soc_priv_obj *soc_obj;
1352 	uint8_t *mac;
1353 	struct tdls_peer *peer;
1354 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1355 
1356 	if (!req || !req->vdev) {
1357 		tdls_err("req: %pK", req);
1358 		status = QDF_STATUS_E_INVAL;
1359 		goto free_req;
1360 	}
1361 
1362 	vdev = req->vdev;
1363 
1364 	/* vdev reference cnt is acquired in ucfg_tdls_oper */
1365 	vdev_obj = wlan_vdev_get_tdls_vdev_obj(vdev);
1366 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
1367 
1368 	if (!vdev_obj || !soc_obj) {
1369 		tdls_err("tdls vdev_obj: %pK soc_obj: %pK", vdev_obj, soc_obj);
1370 		status = QDF_STATUS_E_NULL_VALUE;
1371 		goto error;
1372 	}
1373 
1374 	mac = req->peer_addr;
1375 	peer = tdls_find_peer(vdev_obj, mac);
1376 	if (!peer) {
1377 		tdls_err(QDF_MAC_ADDR_FMT
1378 			 " not found, ignore NL80211_TDLS_ENABLE_LINK",
1379 			 QDF_MAC_ADDR_REF(mac));
1380 		status = QDF_STATUS_E_INVAL;
1381 		goto error;
1382 	}
1383 
1384 	if (!peer->valid_entry) {
1385 		tdls_err("invalid peer:" QDF_MAC_ADDR_FMT " link state %d",
1386 			 QDF_MAC_ADDR_REF(mac), peer->link_status);
1387 		status = QDF_STATUS_E_INVAL;
1388 		goto error;
1389 	}
1390 
1391 	if (soc_obj->tdls_dp_vdev_update)
1392 		soc_obj->tdls_dp_vdev_update(&soc_obj->soc,
1393 					     wlan_vdev_get_id(vdev),
1394 					     soc_obj->tdls_update_dp_vdev_flags,
1395 					     false);
1396 
1397 	cmd.cmd_type = WLAN_SER_CMD_TDLS_DEL_PEER;
1398 	cmd.cmd_id = 0;
1399 	cmd.cmd_cb = tdls_del_peer_serialize_callback;
1400 	cmd.umac_cmd = req;
1401 	cmd.source = WLAN_UMAC_COMP_TDLS;
1402 	cmd.is_high_priority = false;
1403 	cmd.cmd_timeout_duration = TDLS_DELETE_PEER_CMD_TIMEOUT;
1404 	cmd.vdev = vdev;
1405 	cmd.is_blocking = true;
1406 
1407 	ser_cmd_status = wlan_serialization_request(&cmd);
1408 	tdls_debug("req: 0x%pK wlan_serialization_request status:%d", req,
1409 		   ser_cmd_status);
1410 
1411 	switch (ser_cmd_status) {
1412 	case WLAN_SER_CMD_PENDING:
1413 		/* command moved to pending list. Do nothing */
1414 		break;
1415 	case WLAN_SER_CMD_ACTIVE:
1416 		/* command moved to active list. Do nothing */
1417 		break;
1418 	default:
1419 		goto error;
1420 	}
1421 
1422 	return status;
1423 error:
1424 	/* notify os interface about internal error*/
1425 	status = tdls_internal_del_peer_rsp(req);
1426 	wlan_objmgr_vdev_release_ref(req->vdev, WLAN_TDLS_NB_ID);
1427 free_req:
1428 	qdf_mem_free(req);
1429 	return status;
1430 }
1431 
1432 /**
1433  * tdls_update_peer_rsp() - handle response for update TDLS peer
1434  * @rsp: TDLS add peer response
1435  *
1436  * Return: QDF_STATUS_SUCCESS for success; other values if failed
1437  */
tdls_update_peer_rsp(struct tdls_add_sta_rsp * rsp)1438 static QDF_STATUS tdls_update_peer_rsp(struct tdls_add_sta_rsp *rsp)
1439 {
1440 	struct wlan_objmgr_vdev *vdev;
1441 	struct wlan_objmgr_psoc *psoc;
1442 	struct tdls_soc_priv_obj *soc_obj;
1443 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1444 	struct tdls_osif_indication ind;
1445 
1446 	psoc = rsp->psoc;
1447 	if (!psoc) {
1448 		tdls_err("psoc is NULL");
1449 		QDF_ASSERT(0);
1450 		return QDF_STATUS_E_FAILURE;
1451 	}
1452 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, rsp->session_id,
1453 						    WLAN_TDLS_SB_ID);
1454 	if (!vdev) {
1455 		tdls_err("invalid vdev: %d", rsp->session_id);
1456 		status = QDF_STATUS_E_INVAL;
1457 		goto error;
1458 	}
1459 
1460 	tdls_release_serialization_command(vdev, WLAN_SER_CMD_TDLS_ADD_PEER);
1461 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
1462 error:
1463 	soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
1464 	if (soc_obj && soc_obj->tdls_event_cb) {
1465 		ind.status = rsp->status_code;
1466 		ind.vdev = vdev;
1467 		soc_obj->tdls_event_cb(soc_obj->tdls_evt_cb_data,
1468 				       TDLS_EVENT_ADD_PEER, &ind);
1469 	}
1470 	qdf_mem_free(rsp);
1471 
1472 	return status;
1473 }
1474 
1475 /**
1476  * tdls_process_send_mgmt_rsp() - handle response for send mgmt
1477  * @rsp: TDLS send mgmt response
1478  *
1479  * Return: QDF_STATUS_SUCCESS for success; other values if failed
1480  */
tdls_process_send_mgmt_rsp(struct tdls_send_mgmt_rsp * rsp)1481 QDF_STATUS tdls_process_send_mgmt_rsp(struct tdls_send_mgmt_rsp *rsp)
1482 {
1483 	struct wlan_objmgr_vdev *vdev;
1484 	struct wlan_objmgr_psoc *psoc;
1485 	struct tdls_vdev_priv_obj *tdls_vdev;
1486 	struct tdls_soc_priv_obj *tdls_soc = NULL;
1487 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1488 	struct tdls_osif_indication ind;
1489 
1490 	psoc = rsp->psoc;
1491 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, rsp->vdev_id,
1492 						    WLAN_TDLS_SB_ID);
1493 	if (!vdev) {
1494 		tdls_err("invalid vdev");
1495 		status =  QDF_STATUS_E_INVAL;
1496 		qdf_mem_free(rsp);
1497 		return status;
1498 	}
1499 	tdls_soc = wlan_psoc_get_tdls_soc_obj(psoc);
1500 	tdls_vdev = wlan_vdev_get_tdls_vdev_obj(vdev);
1501 	if (!tdls_soc || !tdls_vdev) {
1502 		tdls_err("soc object:%pK, vdev object:%pK", tdls_soc, tdls_vdev);
1503 		status = QDF_STATUS_E_FAILURE;
1504 	}
1505 
1506 	tdls_release_serialization_command(vdev, WLAN_SER_CMD_TDLS_SEND_MGMT);
1507 
1508 	if (legacy_result_success == rsp->status_code)
1509 		goto free_rsp;
1510 	tdls_err("send mgmt failed. status code(=%d)", rsp->status_code);
1511 	status = QDF_STATUS_E_FAILURE;
1512 
1513 	if (tdls_soc && tdls_soc->tdls_event_cb) {
1514 		ind.vdev = vdev;
1515 		ind.status = status;
1516 		tdls_soc->tdls_event_cb(tdls_soc->tdls_evt_cb_data,
1517 				       TDLS_EVENT_MGMT_TX_ACK_CNF, &ind);
1518 	}
1519 
1520 free_rsp:
1521 	qdf_mem_free(rsp);
1522 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
1523 	return status;
1524 }
1525 
1526 /**
1527  * tdls_send_mgmt_tx_completion() - process tx completion
1528  * @tx_complete: TDLS mgmt completion info
1529  *
1530  * Return: QDF_STATUS_SUCCESS for success; other values if failed
1531  */
tdls_send_mgmt_tx_completion(struct tdls_mgmt_tx_completion_ind * tx_complete)1532 QDF_STATUS tdls_send_mgmt_tx_completion(
1533 			struct tdls_mgmt_tx_completion_ind *tx_complete)
1534 {
1535 	struct wlan_objmgr_vdev *vdev;
1536 	struct wlan_objmgr_psoc *psoc;
1537 	struct tdls_vdev_priv_obj *tdls_vdev;
1538 	struct tdls_soc_priv_obj *tdls_soc = NULL;
1539 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1540 	struct tdls_osif_indication ind;
1541 
1542 	psoc = tx_complete->psoc;
1543 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
1544 						    tx_complete->vdev_id,
1545 						    WLAN_TDLS_SB_ID);
1546 
1547 	if (!vdev) {
1548 		tdls_err("invalid vdev");
1549 		status =  QDF_STATUS_E_INVAL;
1550 		goto free_tx_complete;
1551 	}
1552 
1553 	tdls_soc = wlan_psoc_get_tdls_soc_obj(psoc);
1554 	tdls_vdev = wlan_vdev_get_tdls_vdev_obj(vdev);
1555 
1556 	if (!tdls_soc || !tdls_vdev) {
1557 		tdls_err("soc object:%pK, vdev object:%pK", tdls_soc, tdls_vdev);
1558 		status = QDF_STATUS_E_FAILURE;
1559 	}
1560 
1561 	if (tdls_soc && tdls_soc->tdls_event_cb) {
1562 		ind.vdev = vdev;
1563 		ind.status = tx_complete->tx_complete_status;
1564 		tdls_soc->tdls_event_cb(tdls_soc->tdls_evt_cb_data,
1565 			       TDLS_EVENT_MGMT_TX_ACK_CNF, &ind);
1566 	}
1567 
1568 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
1569 free_tx_complete:
1570 	qdf_mem_free(tx_complete);
1571 	return status;
1572 }
1573 
1574 /**
1575  * tdls_add_peer_rsp() - handle response for add TDLS peer
1576  * @rsp: TDLS add peer response
1577  *
1578  * Return: QDF_STATUS_SUCCESS for success; other values if failed
1579  */
tdls_add_peer_rsp(struct tdls_add_sta_rsp * rsp)1580 static QDF_STATUS tdls_add_peer_rsp(struct tdls_add_sta_rsp *rsp)
1581 {
1582 	uint8_t sta_idx;
1583 	struct wlan_objmgr_vdev *vdev;
1584 	struct wlan_objmgr_psoc *psoc;
1585 	struct tdls_vdev_priv_obj *vdev_obj;
1586 	struct tdls_soc_priv_obj *soc_obj = NULL;
1587 	struct tdls_conn_info *conn_rec;
1588 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1589 	struct tdls_osif_indication ind;
1590 
1591 	psoc = rsp->psoc;
1592 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, rsp->session_id,
1593 						    WLAN_TDLS_SB_ID);
1594 	if (!vdev) {
1595 		tdls_err("invalid vdev: %d", rsp->session_id);
1596 		status =  QDF_STATUS_E_INVAL;
1597 		goto error;
1598 	}
1599 	soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
1600 	vdev_obj = wlan_vdev_get_tdls_vdev_obj(vdev);
1601 	if (!soc_obj || !vdev_obj) {
1602 		tdls_err("soc object:%pK, vdev object:%pK", soc_obj, vdev_obj);
1603 		status = QDF_STATUS_E_FAILURE;
1604 		goto cmddone;
1605 	}
1606 	if (rsp->status_code) {
1607 		tdls_err("add sta failed. status code(=%d)", rsp->status_code);
1608 		status = QDF_STATUS_E_FAILURE;
1609 	} else {
1610 		conn_rec = soc_obj->tdls_conn_info;
1611 		for (sta_idx = 0; sta_idx < soc_obj->max_num_tdls_sta;
1612 		     sta_idx++) {
1613 			if (!conn_rec[sta_idx].valid_entry) {
1614 				conn_rec[sta_idx].session_id = rsp->session_id;
1615 				conn_rec[sta_idx].valid_entry = true;
1616 				conn_rec[sta_idx].index = sta_idx;
1617 				qdf_copy_macaddr(&conn_rec[sta_idx].peer_mac,
1618 						 &rsp->peermac);
1619 				tdls_debug("TDLS: Add sta mac at idx %d"
1620 					   QDF_MAC_ADDR_FMT, sta_idx,
1621 					   QDF_MAC_ADDR_REF
1622 					   (rsp->peermac.bytes));
1623 				break;
1624 			}
1625 		}
1626 
1627 		if (sta_idx < soc_obj->max_num_tdls_sta) {
1628 			status = tdls_set_valid(vdev_obj, rsp->peermac.bytes);
1629 			if (QDF_IS_STATUS_ERROR(status)) {
1630 				tdls_err("set staid failed");
1631 				status = QDF_STATUS_E_FAILURE;
1632 			}
1633 		} else {
1634 			status = QDF_STATUS_E_FAILURE;
1635 		}
1636 	}
1637 
1638 cmddone:
1639 	tdls_release_serialization_command(vdev, WLAN_SER_CMD_TDLS_ADD_PEER);
1640 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
1641 error:
1642 	if (soc_obj && soc_obj->tdls_event_cb) {
1643 		ind.vdev = vdev;
1644 		ind.status = rsp->status_code;
1645 		soc_obj->tdls_event_cb(soc_obj->tdls_evt_cb_data,
1646 				       TDLS_EVENT_ADD_PEER, &ind);
1647 	}
1648 	qdf_mem_free(rsp);
1649 
1650 	return status;
1651 }
1652 
tdls_process_add_peer_rsp(struct tdls_add_sta_rsp * rsp)1653 QDF_STATUS tdls_process_add_peer_rsp(struct tdls_add_sta_rsp *rsp)
1654 {
1655 	tdls_debug("peer oper %d", rsp->tdls_oper);
1656 
1657 	if (rsp->tdls_oper == TDLS_OPER_ADD)
1658 		return tdls_add_peer_rsp(rsp);
1659 	else if (rsp->tdls_oper == TDLS_OPER_UPDATE)
1660 		return tdls_update_peer_rsp(rsp);
1661 
1662 	return QDF_STATUS_E_INVAL;
1663 }
1664 
tdls_process_unforce_link_mode(struct wlan_objmgr_vdev * vdev)1665 static void tdls_process_unforce_link_mode(struct wlan_objmgr_vdev *vdev)
1666 {
1667 	struct tdls_vdev_priv_obj *tdls_vdev;
1668 	struct tdls_peer *peer;
1669 	qdf_list_t *head;
1670 	qdf_list_node_t *p_node;
1671 	QDF_STATUS status;
1672 	bool unforce = true;
1673 	int i;
1674 
1675 	tdls_vdev = wlan_vdev_get_tdls_vdev_obj(vdev);
1676 	if (!tdls_vdev)
1677 		return;
1678 
1679 	for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
1680 		head = &tdls_vdev->peer_list[i];
1681 		status = qdf_list_peek_front(head, &p_node);
1682 		while (QDF_IS_STATUS_SUCCESS(status)) {
1683 			peer = qdf_container_of(p_node, struct tdls_peer, node);
1684 
1685 			tdls_debug("Peer: " QDF_MAC_ADDR_FMT "link status %d, vdev id %d",
1686 				   QDF_MAC_ADDR_REF(peer->peer_mac.bytes),
1687 				   peer->link_status, wlan_vdev_get_id(vdev));
1688 
1689 			if (peer->link_status == TDLS_LINK_CONNECTED ||
1690 			    peer->link_status == TDLS_LINK_CONNECTING) {
1691 				unforce = false;
1692 				goto unforce_exit;
1693 			}
1694 
1695 			status = qdf_list_peek_next(head, p_node, &p_node);
1696 		}
1697 	}
1698 
1699 unforce_exit:
1700 	if (unforce) {
1701 		tdls_debug("try to set vdev %d to unforce",
1702 			   wlan_vdev_get_id(vdev));
1703 		tdls_set_link_unforce(vdev);
1704 	}
1705 }
1706 
tdls_process_del_peer_rsp(struct tdls_del_sta_rsp * rsp)1707 QDF_STATUS tdls_process_del_peer_rsp(struct tdls_del_sta_rsp *rsp)
1708 {
1709 	uint8_t sta_idx, id;
1710 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1711 	struct wlan_objmgr_vdev *vdev;
1712 	struct wlan_objmgr_psoc *psoc;
1713 	struct tdls_vdev_priv_obj *vdev_obj;
1714 	struct tdls_soc_priv_obj *soc_obj = NULL;
1715 	struct tdls_conn_info *conn_rec;
1716 	struct tdls_peer *curr_peer = NULL;
1717 	const uint8_t *macaddr;
1718 	struct tdls_osif_indication ind;
1719 
1720 	tdls_debug("del peer rsp: vdev %d  peer " QDF_MAC_ADDR_FMT,
1721 		   rsp->session_id, QDF_MAC_ADDR_REF(rsp->peermac.bytes));
1722 	psoc = rsp->psoc;
1723 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, rsp->session_id,
1724 						    WLAN_TDLS_SB_ID);
1725 	if (!vdev) {
1726 		tdls_err("invalid vdev: %d", rsp->session_id);
1727 		status = QDF_STATUS_E_INVAL;
1728 		goto error;
1729 	}
1730 	soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
1731 	vdev_obj = wlan_vdev_get_tdls_vdev_obj(vdev);
1732 	if (!soc_obj || !vdev_obj) {
1733 		tdls_err("soc object:%pK, vdev object:%pK", soc_obj, vdev_obj);
1734 		status = QDF_STATUS_E_FAILURE;
1735 		goto cmddone;
1736 	}
1737 
1738 	conn_rec = soc_obj->tdls_conn_info;
1739 	for (sta_idx = 0; sta_idx < soc_obj->max_num_tdls_sta; sta_idx++) {
1740 		if (conn_rec[sta_idx].session_id != rsp->session_id ||
1741 			qdf_mem_cmp(conn_rec[sta_idx].peer_mac.bytes,
1742 				    rsp->peermac.bytes, QDF_MAC_ADDR_SIZE))
1743 			continue;
1744 
1745 		macaddr = rsp->peermac.bytes;
1746 		tdls_debug("TDLS: del STA with sta_idx %d", sta_idx);
1747 		curr_peer = tdls_find_peer(vdev_obj, macaddr);
1748 		if (curr_peer) {
1749 			tdls_debug(QDF_MAC_ADDR_FMT " status is %d",
1750 				   QDF_MAC_ADDR_REF(macaddr),
1751 				   curr_peer->link_status);
1752 
1753 			id = wlan_vdev_get_id(vdev);
1754 
1755 			if (TDLS_IS_LINK_CONNECTED(curr_peer))
1756 				tdls_decrement_peer_count(vdev, soc_obj);
1757 		}
1758 		tdls_reset_peer(vdev_obj, macaddr);
1759 		conn_rec[sta_idx].valid_entry = false;
1760 		conn_rec[sta_idx].session_id = 0xff;
1761 		conn_rec[sta_idx].index = INVALID_TDLS_PEER_INDEX;
1762 		qdf_mem_zero(&conn_rec[sta_idx].peer_mac,
1763 			     QDF_MAC_ADDR_SIZE);
1764 
1765 		status = QDF_STATUS_SUCCESS;
1766 		break;
1767 	}
1768 	macaddr = rsp->peermac.bytes;
1769 	if (!curr_peer) {
1770 		curr_peer = tdls_find_peer(vdev_obj, macaddr);
1771 
1772 		if (curr_peer)
1773 			tdls_set_peer_link_status(curr_peer, TDLS_LINK_IDLE,
1774 						  (curr_peer->link_status ==
1775 						   TDLS_LINK_TEARING) ?
1776 						  TDLS_LINK_UNSPECIFIED :
1777 						  TDLS_LINK_DROPPED_BY_REMOTE);
1778 	}
1779 
1780 	tdls_process_unforce_link_mode(vdev);
1781 
1782 cmddone:
1783 	tdls_release_serialization_command(vdev, WLAN_SER_CMD_TDLS_DEL_PEER);
1784 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
1785 error:
1786 
1787 	if (soc_obj && soc_obj->tdls_event_cb) {
1788 		ind.vdev = vdev;
1789 		soc_obj->tdls_event_cb(soc_obj->tdls_evt_cb_data,
1790 				       TDLS_EVENT_DEL_PEER, &ind);
1791 	}
1792 	qdf_mem_free(rsp);
1793 
1794 	return status;
1795 }
1796 
1797 static QDF_STATUS
tdls_wma_update_peer_state(struct tdls_soc_priv_obj * soc_obj,struct tdls_peer_update_state * peer_state)1798 tdls_wma_update_peer_state(struct tdls_soc_priv_obj *soc_obj,
1799 			   struct tdls_peer_update_state *peer_state)
1800 {
1801 	struct scheduler_msg msg = {0,};
1802 	QDF_STATUS status;
1803 
1804 	tdls_debug("update TDLS peer " QDF_MAC_ADDR_FMT " vdev %d, state %d",
1805 		   QDF_MAC_ADDR_REF(peer_state->peer_macaddr),
1806 		   peer_state->vdev_id, peer_state->peer_state);
1807 	msg.type = soc_obj->tdls_update_peer_state;
1808 	msg.reserved = 0;
1809 	msg.bodyptr = peer_state;
1810 
1811 	status = scheduler_post_message(QDF_MODULE_ID_TDLS,
1812 					QDF_MODULE_ID_WMA,
1813 					QDF_MODULE_ID_WMA, &msg);
1814 	if (QDF_IS_STATUS_ERROR(status)) {
1815 		tdls_err("scheduler_post_msg failed");
1816 		status = QDF_STATUS_E_FAILURE;
1817 	}
1818 
1819 	return status;
1820 }
1821 
tdls_process_enable_link(struct tdls_oper_request * req)1822 QDF_STATUS tdls_process_enable_link(struct tdls_oper_request *req)
1823 {
1824 	struct tdls_peer *peer;
1825 	struct tdls_vdev_priv_obj *vdev_obj;
1826 	struct tdls_soc_priv_obj *soc_obj;
1827 	struct wlan_objmgr_vdev *vdev;
1828 	uint8_t *mac;
1829 	struct tdls_peer_update_state *peer_update_param;
1830 	QDF_STATUS status;
1831 	uint32_t feature;
1832 	uint8_t id;
1833 
1834 	vdev = req->vdev;
1835 	if (!vdev) {
1836 		tdls_err("NULL vdev object");
1837 		qdf_mem_free(req);
1838 		return QDF_STATUS_E_NULL_VALUE;
1839 	}
1840 
1841 	/* vdev reference cnt is acquired in ucfg_tdls_oper */
1842 	vdev_obj = wlan_vdev_get_tdls_vdev_obj(vdev);
1843 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
1844 
1845 	if (!vdev_obj || !soc_obj) {
1846 		tdls_err("tdls vdev_obj: %pK soc_obj: %pK", vdev_obj, soc_obj);
1847 		status = QDF_STATUS_E_NULL_VALUE;
1848 		goto error;
1849 	}
1850 
1851 	mac = req->peer_addr;
1852 	peer = tdls_find_peer(vdev_obj, mac);
1853 	if (!peer) {
1854 		tdls_err(QDF_MAC_ADDR_FMT
1855 			 " not found, ignore NL80211_TDLS_ENABLE_LINK",
1856 			 QDF_MAC_ADDR_REF(mac));
1857 		status = QDF_STATUS_E_INVAL;
1858 		goto error;
1859 	}
1860 
1861 	tdls_debug("enable link for peer " QDF_MAC_ADDR_FMT " link state %d",
1862 		   QDF_MAC_ADDR_REF(mac), peer->link_status);
1863 	if (!peer->valid_entry) {
1864 		tdls_err("invalid entry " QDF_MAC_ADDR_FMT,
1865 			 QDF_MAC_ADDR_REF(mac));
1866 		status = QDF_STATUS_E_INVAL;
1867 		goto error;
1868 	}
1869 
1870 	/*
1871 	 * Offchannel is allowed only when TDLS is connected with one peer.
1872 	 * If more than one peer is connected then Disable Offchannel by sending
1873 	 * WMI_TDLS_SET_OFFCHAN_MODE_CMDID with DISABLE_CHANSWITCH.
1874 	 * So, basically when the 2nd peer enable_link is there, offchannel
1875 	 * should be disabled and will remain disabled for all subsequent
1876 	 * TDLS peer connection.
1877 	 * Offchannel will be re-enabled when connected peer count again
1878 	 * becomes 1.
1879 	 */
1880 	if (soc_obj->connected_peer_count == 1)
1881 		tdls_set_tdls_offchannelmode(vdev, DISABLE_CHANSWITCH);
1882 
1883 	peer->tdls_support = TDLS_CAP_SUPPORTED;
1884 	if (TDLS_LINK_CONNECTED != peer->link_status)
1885 		tdls_set_peer_link_status(peer, TDLS_LINK_CONNECTED,
1886 					  TDLS_LINK_SUCCESS);
1887 
1888 	id = wlan_vdev_get_id(vdev);
1889 	status = soc_obj->tdls_reg_peer(soc_obj->tdls_peer_context,
1890 					id, mac, peer->qos);
1891 	if (QDF_IS_STATUS_ERROR(status)) {
1892 		tdls_err("TDLS register peer fail, status %d", status);
1893 		goto error;
1894 	}
1895 
1896 	peer_update_param = qdf_mem_malloc(sizeof(*peer_update_param));
1897 	if (!peer_update_param) {
1898 		status = QDF_STATUS_E_NOMEM;
1899 		goto error;
1900 	}
1901 
1902 	tdls_extract_peer_state_param(peer_update_param, peer);
1903 
1904 	status = tdls_wma_update_peer_state(soc_obj, peer_update_param);
1905 	if (QDF_IS_STATUS_ERROR(status)) {
1906 		qdf_mem_free(peer_update_param);
1907 		status = QDF_STATUS_E_PERM;
1908 		goto error;
1909 	}
1910 
1911 	tdls_update_6g_power(vdev, soc_obj, true);
1912 	tdls_increment_peer_count(soc_obj);
1913 	/* Need to update osif params when first peer gets connected */
1914 	if (soc_obj->connected_peer_count == 1 &&
1915 	    soc_obj->tdls_osif_update_cb.tdls_osif_conn_update)
1916 		soc_obj->tdls_osif_update_cb.tdls_osif_conn_update(vdev);
1917 	feature = soc_obj->tdls_configs.tdls_feature_flags;
1918 
1919 	if (soc_obj->tdls_dp_vdev_update)
1920 		soc_obj->tdls_dp_vdev_update(
1921 				&soc_obj->soc,
1922 				wlan_vdev_get_id(vdev),
1923 				soc_obj->tdls_update_dp_vdev_flags,
1924 				((peer->link_status == TDLS_LINK_CONNECTED) ?
1925 				 true : false));
1926 
1927 	tdls_debug("TDLS buffer sta: %d, uapsd_mask %d",
1928 		   TDLS_IS_BUFFER_STA_ENABLED(feature),
1929 		   soc_obj->tdls_configs.tdls_uapsd_mask);
1930 
1931 error:
1932 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
1933 	qdf_mem_free(req);
1934 
1935 	return status;
1936 }
1937 
1938 /**
1939  * tdls_config_force_peer() - configure an externally controllable TDLS peer
1940  * @req: TDLS operation request
1941  *
1942  * This is not the tdls_process_cmd function. No need to acquire the reference
1943  * count, release reference count  and free the request, the caller handle it
1944  * correctly.
1945  *
1946  * Return: QDF_STATUS_SUCCESS if success; other values if failed
1947  */
tdls_config_force_peer(struct tdls_oper_config_force_peer_request * req)1948 static QDF_STATUS tdls_config_force_peer(
1949 	struct tdls_oper_config_force_peer_request *req)
1950 {
1951 	struct tdls_peer *peer;
1952 	struct tdls_soc_priv_obj *soc_obj;
1953 	struct tdls_vdev_priv_obj *vdev_obj;
1954 	struct wlan_objmgr_pdev *pdev;
1955 	struct wlan_objmgr_vdev *vdev;
1956 	const uint8_t *macaddr;
1957 	uint32_t feature;
1958 	QDF_STATUS status;
1959 	uint32_t chan_freq;
1960 	struct tdls_peer_update_state *peer_update_param;
1961 
1962 	macaddr = req->peer_addr;
1963 
1964 	vdev = req->vdev;
1965 	pdev = wlan_vdev_get_pdev(vdev);
1966 	vdev_obj = wlan_vdev_get_tdls_vdev_obj(vdev);
1967 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
1968 	if (!pdev || !vdev_obj || !soc_obj) {
1969 		tdls_err("pdev: %pK, vdev_obj: %pK, soc_obj: %pK",
1970 			 pdev, vdev_obj, soc_obj);
1971 		return QDF_STATUS_E_INVAL;
1972 	}
1973 
1974 	feature = soc_obj->tdls_configs.tdls_feature_flags;
1975 	if (!(TDLS_IS_EXTERNAL_CONTROL_ENABLED(feature) ||
1976 	    TDLS_IS_LIBERAL_EXTERNAL_CONTROL_ENABLED(feature)) ||
1977 	    !TDLS_IS_IMPLICIT_TRIG_ENABLED(feature)) {
1978 		tdls_err("TDLS ext ctrl or Imp Trig not enabled, %x", feature);
1979 		return QDF_STATUS_E_NOSUPPORT;
1980 	}
1981 
1982 	/*
1983 	 * In case of liberal external mode, supplicant will provide peer mac
1984 	 * address but driver has to behave similar to implicit mode ie
1985 	 * establish tdls link with any peer that supports tdls and meets stats
1986 	 */
1987 	if (TDLS_IS_LIBERAL_EXTERNAL_CONTROL_ENABLED(feature)) {
1988 		tdls_debug("liberal mode set");
1989 		return QDF_STATUS_SUCCESS;
1990 	}
1991 
1992 	peer_update_param = qdf_mem_malloc(sizeof(*peer_update_param));
1993 	if (!peer_update_param)
1994 		return QDF_STATUS_E_NOMEM;
1995 
1996 	peer = tdls_get_peer(vdev_obj, macaddr);
1997 	if (!peer) {
1998 		tdls_err("peer " QDF_MAC_ADDR_FMT " does not exist",
1999 			 QDF_MAC_ADDR_REF(macaddr));
2000 		status = QDF_STATUS_E_NULL_VALUE;
2001 		goto error;
2002 	}
2003 	status = tdls_set_force_peer(vdev_obj, macaddr, true);
2004 	if (QDF_IS_STATUS_ERROR(status)) {
2005 		tdls_err("set force peer failed");
2006 		goto error;
2007 	}
2008 
2009 	/* Update the peer mac to firmware, so firmware could update the
2010 	 * connection table
2011 	 */
2012 	peer_update_param->vdev_id = wlan_vdev_get_id(vdev);
2013 	qdf_mem_copy(peer_update_param->peer_macaddr,
2014 		     macaddr, QDF_MAC_ADDR_SIZE);
2015 	peer_update_param->peer_state = TDLS_PEER_ADD_MAC_ADDR;
2016 
2017 	status = tdls_wma_update_peer_state(soc_obj, peer_update_param);
2018 	if (QDF_IS_STATUS_ERROR(status)) {
2019 		tdls_err("update peer state failed");
2020 		goto error;
2021 	}
2022 
2023 	soc_obj->tdls_external_peer_count++;
2024 	chan_freq = req->ch_freq;
2025 
2026 	/* Validate if off channel is DFS channel */
2027 	if (wlan_reg_is_dfs_for_freq(pdev, chan_freq)) {
2028 		tdls_err("Resetting TDLS off-channel freq from %d to %d",
2029 			 req->ch_freq, WLAN_TDLS_PREFERRED_OFF_CHANNEL_FRQ_DEF);
2030 		req->ch_freq = WLAN_TDLS_PREFERRED_OFF_CHANNEL_FRQ_DEF;
2031 	}
2032 	tdls_set_extctrl_param(peer, req->ch_freq, req->max_latency,
2033 			       req->op_class, req->min_bandwidth);
2034 
2035 	tdls_set_callback(peer, req->callback);
2036 	tdls_set_ct_mode(soc_obj->soc, vdev);
2037 
2038 	return status;
2039 error:
2040 	qdf_mem_free(peer_update_param);
2041 	return status;
2042 }
2043 
2044 /**
2045  * tdls_process_setup_peer() - process configure an externally
2046  *                                    controllable TDLS peer
2047  * @req: TDLS operation request
2048  *
2049  * Return: QDF_STATUS_SUCCESS if success; other values if failed
2050  */
tdls_process_setup_peer(struct tdls_oper_request * req)2051 QDF_STATUS tdls_process_setup_peer(struct tdls_oper_request *req)
2052 {
2053 	struct tdls_oper_config_force_peer_request peer_req;
2054 	struct tdls_soc_priv_obj *soc_obj;
2055 	struct wlan_objmgr_vdev *vdev;
2056 	QDF_STATUS status;
2057 	uint8_t reg_bw_offset = 0;
2058 	qdf_freq_t pref_freq;
2059 	uint32_t pref_width;
2060 	struct wlan_objmgr_pdev *pdev;
2061 
2062 
2063 	/* reference cnt is acquired in ucfg_tdls_oper */
2064 	vdev = req->vdev;
2065 	if (!vdev) {
2066 		tdls_err("NULL vdev object");
2067 		status = QDF_STATUS_E_NULL_VALUE;
2068 		goto freereq;
2069 	}
2070 
2071 	if (!tdls_check_is_tdls_allowed(vdev)) {
2072 		tdls_err("TDLS not allowed on vdev:%d, Reject setup peer",
2073 			 wlan_vdev_get_id(vdev));
2074 		status = QDF_STATUS_E_INVAL;
2075 		goto error;
2076 	}
2077 
2078 	tdls_debug("vdev:%d Configure external TDLS peer " QDF_MAC_ADDR_FMT,
2079 		   wlan_vdev_get_id(vdev),
2080 		   QDF_MAC_ADDR_REF(req->peer_addr));
2081 	qdf_mem_zero(&peer_req, sizeof(peer_req));
2082 	peer_req.vdev = vdev;
2083 	qdf_mem_copy(peer_req.peer_addr, req->peer_addr, QDF_MAC_ADDR_SIZE);
2084 
2085 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
2086 	if (!soc_obj) {
2087 		tdls_err("NULL soc object");
2088 		status = QDF_STATUS_E_INVAL;
2089 		goto error;
2090 	}
2091 
2092 	pref_freq = tdls_get_offchan_freq(vdev, soc_obj);
2093 	pdev = wlan_vdev_get_pdev(vdev);
2094 	if (!pdev) {
2095 		tdls_err("NULL pdev object");
2096 		status = QDF_STATUS_E_INVAL;
2097 		goto error;
2098 	}
2099 
2100 	peer_req.ch_freq = pref_freq;
2101 	pref_width = tdls_get_offchan_bw(soc_obj, pref_freq);
2102 
2103 	if (!peer_req.op_class)
2104 		peer_req.op_class = tdls_get_opclass_from_bandwidth(vdev,
2105 								pref_freq,
2106 								pref_width,
2107 								&reg_bw_offset);
2108 
2109 	tdls_debug("peer chan %d peer opclass %d reg_bw_offset %d",
2110 		   peer_req.ch_freq,
2111 		   peer_req.op_class,
2112 		   reg_bw_offset);
2113 	status = tdls_config_force_peer(&peer_req);
2114 error:
2115 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
2116 freereq:
2117 	qdf_mem_free(req);
2118 
2119 	return status;
2120 }
2121 
tdls_process_remove_force_peer(struct tdls_oper_request * req)2122 QDF_STATUS tdls_process_remove_force_peer(struct tdls_oper_request *req)
2123 {
2124 	struct tdls_peer *peer;
2125 	struct tdls_soc_priv_obj *soc_obj;
2126 	struct tdls_vdev_priv_obj *vdev_obj;
2127 	struct wlan_objmgr_vdev *vdev;
2128 	const uint8_t *macaddr;
2129 	uint32_t feature;
2130 	QDF_STATUS status;
2131 	struct tdls_peer_update_state *peer_update_param;
2132 	struct tdls_osif_indication ind;
2133 
2134 	macaddr = req->peer_addr;
2135 	tdls_debug("NL80211_TDLS_TEARDOWN for " QDF_MAC_ADDR_FMT,
2136 		   QDF_MAC_ADDR_REF(macaddr));
2137 
2138 	vdev = req->vdev;
2139 	if (!vdev) {
2140 		tdls_err("NULL vdev object");
2141 		qdf_mem_free(req);
2142 		return QDF_STATUS_E_NULL_VALUE;
2143 	}
2144 
2145 	/* reference cnt is acquired in ucfg_tdls_oper */
2146 	vdev_obj = wlan_vdev_get_tdls_vdev_obj(req->vdev);
2147 	soc_obj = wlan_vdev_get_tdls_soc_obj(req->vdev);
2148 	if (!soc_obj || !vdev_obj) {
2149 		tdls_err("soc_obj: %pK, vdev_obj: %pK", soc_obj, vdev_obj);
2150 		status = QDF_STATUS_E_INVAL;
2151 		goto error;
2152 	}
2153 
2154 	feature = soc_obj->tdls_configs.tdls_feature_flags;
2155 	if (!(TDLS_IS_EXTERNAL_CONTROL_ENABLED(feature) ||
2156 	    TDLS_IS_LIBERAL_EXTERNAL_CONTROL_ENABLED(feature)) ||
2157 	    !TDLS_IS_IMPLICIT_TRIG_ENABLED(feature)) {
2158 		tdls_err("TDLS ext ctrl or Imp Trig not enabled, %x", feature);
2159 		status = QDF_STATUS_E_NOSUPPORT;
2160 		goto error;
2161 	}
2162 
2163 	peer = tdls_find_peer(vdev_obj, macaddr);
2164 	if (!peer) {
2165 		tdls_err("peer matching " QDF_MAC_ADDR_FMT " not found",
2166 			 QDF_MAC_ADDR_REF(macaddr));
2167 		status = QDF_STATUS_E_NULL_VALUE;
2168 		goto error;
2169 	}
2170 	if (peer->link_status == TDLS_LINK_CONNECTED)
2171 		tdls_set_peer_link_status(peer, TDLS_LINK_TEARING,
2172 					  TDLS_LINK_UNSPECIFIED);
2173 
2174 	if (soc_obj->tdls_dp_vdev_update)
2175 		soc_obj->tdls_dp_vdev_update(
2176 				&soc_obj->soc,
2177 				wlan_vdev_get_id(vdev),
2178 				soc_obj->tdls_update_dp_vdev_flags,
2179 				false);
2180 
2181 	if (soc_obj->tdls_event_cb) {
2182 		qdf_mem_copy(ind.peer_mac, macaddr, QDF_MAC_ADDR_SIZE);
2183 		ind.vdev = vdev;
2184 		ind.reason = TDLS_TEARDOWN_PEER_UNSPEC_REASON;
2185 		soc_obj->tdls_event_cb(soc_obj->tdls_evt_cb_data,
2186 				       TDLS_EVENT_TEARDOWN_REQ, &ind);
2187 	}
2188 
2189 	status = tdls_set_force_peer(vdev_obj, macaddr, false);
2190 	if (QDF_IS_STATUS_ERROR(status)) {
2191 		tdls_err("set force peer failed");
2192 		status = QDF_STATUS_E_INVAL;
2193 		goto error;
2194 	}
2195 
2196 	if (soc_obj->tdls_external_peer_count)
2197 		soc_obj->tdls_external_peer_count--;
2198 
2199 	tdls_set_callback(peer, NULL);
2200 	peer_update_param = qdf_mem_malloc(sizeof(*peer_update_param));
2201 	if (!peer_update_param) {
2202 		status = QDF_STATUS_E_NOMEM;
2203 		goto error;
2204 	}
2205 
2206 	peer_update_param->vdev_id = wlan_vdev_get_id(vdev);
2207 	qdf_mem_copy(peer_update_param->peer_macaddr,
2208 		     macaddr, QDF_MAC_ADDR_SIZE);
2209 	peer_update_param->peer_state = TDLS_PEER_REMOVE_MAC_ADDR;
2210 	status = tdls_wma_update_peer_state(soc_obj, peer_update_param);
2211 	if (QDF_IS_STATUS_ERROR(status)) {
2212 		qdf_mem_free(peer_update_param);
2213 		goto error;
2214 	}
2215 	tdls_set_ct_mode(soc_obj->soc, vdev);
2216 
2217 error:
2218 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
2219 	qdf_mem_free(req);
2220 
2221 	return status;
2222 }
2223 
tdls_evt_to_str(enum tdls_event_msg_type type)2224 static const char *tdls_evt_to_str(enum tdls_event_msg_type type)
2225 {
2226 	switch (type) {
2227 	case TDLS_SHOULD_DISCOVER:
2228 		return "SHOULD_DISCOVER";
2229 	case TDLS_SHOULD_TEARDOWN:
2230 		return "SHOULD_TEARDOWN";
2231 	case TDLS_PEER_DISCONNECTED:
2232 		return "SHOULD_PEER_DISCONNECTED";
2233 	case TDLS_CONNECTION_TRACKER_NOTIFY:
2234 		return "CONNECTION_TRACKER_NOTIFICATION";
2235 	default:
2236 		return "INVALID_TYPE";
2237 	}
2238 }
2239 
tdls_process_should_discover(struct wlan_objmgr_vdev * vdev,struct tdls_event_info * evt)2240 QDF_STATUS tdls_process_should_discover(struct wlan_objmgr_vdev *vdev,
2241 					struct tdls_event_info *evt)
2242 {
2243 	struct tdls_soc_priv_obj *soc_obj;
2244 	struct tdls_vdev_priv_obj *vdev_obj;
2245 	struct tdls_peer *curr_peer;
2246 	uint32_t feature;
2247 	uint16_t type;
2248 
2249 	/*TODO ignore this if any concurrency detected*/
2250 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
2251 	vdev_obj = wlan_vdev_get_tdls_vdev_obj(vdev);
2252 	type = evt->message_type;
2253 
2254 	tdls_debug("TDLS %s: " QDF_MAC_ADDR_FMT "reason %d",
2255 		   tdls_evt_to_str(type),
2256 		   QDF_MAC_ADDR_REF(evt->peermac.bytes),
2257 		   evt->peer_reason);
2258 	if (!soc_obj || !vdev_obj) {
2259 		tdls_err("soc_obj: %pK, vdev_obj: %pK, ignore %s",
2260 			 soc_obj, vdev_obj, tdls_evt_to_str(type));
2261 		return QDF_STATUS_E_NULL_VALUE;
2262 	}
2263 	if (soc_obj->tdls_nss_switch_in_progress) {
2264 		tdls_err("TDLS antenna switching, ignore %s",
2265 			 tdls_evt_to_str(type));
2266 		return QDF_STATUS_SUCCESS;
2267 	}
2268 
2269 	curr_peer = tdls_get_peer(vdev_obj, evt->peermac.bytes);
2270 	if (!curr_peer) {
2271 		tdls_notice("curr_peer is null");
2272 		return QDF_STATUS_E_NULL_VALUE;
2273 	}
2274 
2275 	if (TDLS_LINK_CONNECTED == curr_peer->link_status) {
2276 		tdls_err("TDLS link status is connected, ignore");
2277 		return QDF_STATUS_SUCCESS;
2278 	}
2279 
2280 	feature = soc_obj->tdls_configs.tdls_feature_flags;
2281 	if (TDLS_IS_EXTERNAL_CONTROL_ENABLED(feature) &&
2282 	    !curr_peer->is_forced_peer) {
2283 		tdls_debug("curr_peer is not forced, ignore %s",
2284 			   tdls_evt_to_str(type));
2285 		return QDF_STATUS_SUCCESS;
2286 	}
2287 
2288 	tdls_debug("initiate TDLS setup on %s, ext: %d, force: %d, reason: %d",
2289 		   tdls_evt_to_str(type),
2290 		   TDLS_IS_EXTERNAL_CONTROL_ENABLED(feature),
2291 		   curr_peer->is_forced_peer, evt->peer_reason);
2292 	vdev_obj->curr_candidate = curr_peer;
2293 	tdls_implicit_send_discovery_request(vdev_obj);
2294 
2295 	return QDF_STATUS_SUCCESS;
2296 }
2297 
tdls_process_should_teardown(struct wlan_objmgr_vdev * vdev,struct tdls_event_info * evt)2298 QDF_STATUS tdls_process_should_teardown(struct wlan_objmgr_vdev *vdev,
2299 					struct tdls_event_info *evt)
2300 {
2301 	struct tdls_soc_priv_obj *soc_obj;
2302 	struct tdls_vdev_priv_obj *vdev_obj;
2303 	struct tdls_peer *curr_peer;
2304 	uint32_t reason;
2305 	uint16_t type;
2306 
2307 	type = evt->message_type;
2308 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
2309 	vdev_obj = wlan_vdev_get_tdls_vdev_obj(vdev);
2310 
2311 	tdls_debug("TDLS %s: " QDF_MAC_ADDR_FMT "reason %d",
2312 		   tdls_evt_to_str(type),
2313 		   QDF_MAC_ADDR_REF(evt->peermac.bytes), evt->peer_reason);
2314 
2315 	if (!soc_obj || !vdev_obj) {
2316 		tdls_err("soc_obj: %pK, vdev_obj: %pK, ignore %s",
2317 			 soc_obj, vdev_obj, tdls_evt_to_str(type));
2318 		return QDF_STATUS_E_NULL_VALUE;
2319 	}
2320 
2321 	curr_peer = tdls_find_peer(vdev_obj, evt->peermac.bytes);
2322 	if (!curr_peer) {
2323 		tdls_notice("curr_peer is null");
2324 		return QDF_STATUS_E_NULL_VALUE;
2325 	}
2326 
2327 	reason = evt->peer_reason;
2328 	if (TDLS_LINK_CONNECTED == curr_peer->link_status) {
2329 		tdls_err("%s reason: %d for" QDF_MAC_ADDR_FMT,
2330 			 tdls_evt_to_str(type), evt->peer_reason,
2331 			 QDF_MAC_ADDR_REF(evt->peermac.bytes));
2332 		if (reason == TDLS_TEARDOWN_RSSI ||
2333 		    reason == TDLS_DISCONNECTED_PEER_DELETE ||
2334 		    reason == TDLS_TEARDOWN_PTR_TIMEOUT ||
2335 		    reason == TDLS_TEARDOWN_NO_RSP)
2336 			reason = TDLS_TEARDOWN_PEER_UNREACHABLE;
2337 		else
2338 			reason = TDLS_TEARDOWN_PEER_UNSPEC_REASON;
2339 
2340 		tdls_indicate_teardown(vdev_obj, curr_peer, reason);
2341 	} else {
2342 		tdls_err("TDLS link is not connected, ignore %s",
2343 			 tdls_evt_to_str(type));
2344 	}
2345 
2346 	return QDF_STATUS_SUCCESS;
2347 }
2348 
tdls_process_connection_tracker_notify(struct wlan_objmgr_vdev * vdev,struct tdls_event_info * evt)2349 QDF_STATUS tdls_process_connection_tracker_notify(struct wlan_objmgr_vdev *vdev,
2350 						  struct tdls_event_info *evt)
2351 {
2352 	struct tdls_soc_priv_obj *soc_obj;
2353 	struct tdls_vdev_priv_obj *vdev_obj;
2354 	uint16_t type;
2355 
2356 	type = evt->message_type;
2357 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
2358 	vdev_obj = wlan_vdev_get_tdls_vdev_obj(vdev);
2359 
2360 	if (!soc_obj || !vdev_obj) {
2361 		tdls_err("soc_obj: %pK, vdev_obj: %pK, ignore %s",
2362 			 soc_obj, vdev_obj, tdls_evt_to_str(type));
2363 		return QDF_STATUS_E_NULL_VALUE;
2364 	}
2365 
2366 	/*TODO connection tracker update*/
2367 	return QDF_STATUS_SUCCESS;
2368 }
2369 
2370 /**
2371  * tdls_process_set_responder() - Set/clear TDLS peer's responder role
2372  * @set_req: set responder request
2373  *
2374  * Return: 0 for success or -EINVAL otherwise
2375  */
2376 static
tdls_process_set_responder(struct tdls_set_responder_req * set_req)2377 int tdls_process_set_responder(struct tdls_set_responder_req *set_req)
2378 {
2379 	struct tdls_peer *curr_peer;
2380 	struct tdls_vdev_priv_obj *tdls_vdev;
2381 	struct wlan_objmgr_psoc *psoc;
2382 	QDF_STATUS status;
2383 
2384 	tdls_vdev = wlan_vdev_get_tdls_vdev_obj(set_req->vdev);
2385 	if (!tdls_vdev) {
2386 		tdls_err("tdls vdev obj is NULL");
2387 		return -EINVAL;
2388 	}
2389 	curr_peer = tdls_get_peer(tdls_vdev, set_req->peer_mac);
2390 	if (!curr_peer) {
2391 		tdls_err("curr_peer is NULL");
2392 		return -EINVAL;
2393 	}
2394 
2395 	curr_peer->is_responder = set_req->responder;
2396 
2397 	psoc = wlan_vdev_get_psoc(tdls_vdev->vdev);
2398 	if (!psoc) {
2399 		tdls_err("psoc not found");
2400 		return -EINVAL;
2401 	}
2402 
2403 	status = policy_mgr_update_nss_req(psoc,
2404 					   wlan_vdev_get_id(tdls_vdev->vdev),
2405 					   HW_MODE_SS_2x2, HW_MODE_SS_2x2);
2406 	if (QDF_IS_STATUS_ERROR(status)) {
2407 		tdls_err("Unable to process NSS request");
2408 		return -EINVAL;
2409 	}
2410 
2411 	return 0;
2412 }
2413 
2414 
2415 /**
2416  * tdls_set_responder() - Set/clear TDLS peer's responder role
2417  * @set_req: set responder request
2418  *
2419  * Return: 0 for success or -EINVAL otherwise
2420  */
tdls_set_responder(struct tdls_set_responder_req * set_req)2421 int tdls_set_responder(struct tdls_set_responder_req *set_req)
2422 {
2423 	int status;
2424 
2425 	if (!set_req) {
2426 		tdls_err("Invalid input params");
2427 		return  -EINVAL;
2428 	}
2429 
2430 	if (!set_req->vdev) {
2431 		tdls_err("Invalid input params %pK", set_req);
2432 		status = -EINVAL;
2433 		goto free_req;
2434 	}
2435 
2436 	status = wlan_objmgr_vdev_try_get_ref(set_req->vdev, WLAN_TDLS_NB_ID);
2437 	if (QDF_STATUS_SUCCESS != status) {
2438 		tdls_err("vdev object is deleted");
2439 		status = -EINVAL;
2440 		goto error;
2441 	}
2442 
2443 	status = tdls_process_set_responder(set_req);
2444 
2445 error:
2446 	wlan_objmgr_vdev_release_ref(set_req->vdev, WLAN_TDLS_NB_ID);
2447 free_req:
2448 	qdf_mem_free(set_req);
2449 	return status;
2450 }
2451 
tdls_teardown_links(struct tdls_soc_priv_obj * soc_obj,uint32_t mode)2452 static int tdls_teardown_links(struct tdls_soc_priv_obj *soc_obj, uint32_t mode)
2453 {
2454 	uint8_t staidx;
2455 	struct tdls_peer *curr_peer;
2456 	struct tdls_conn_info *conn_rec;
2457 	int ret = 0;
2458 
2459 	conn_rec = soc_obj->tdls_conn_info;
2460 	for (staidx = 0; staidx < soc_obj->max_num_tdls_sta; staidx++) {
2461 		if (!conn_rec[staidx].valid_entry)
2462 			continue;
2463 
2464 		curr_peer = tdls_find_all_peer(soc_obj,
2465 					       conn_rec[staidx].peer_mac.bytes);
2466 		if (!curr_peer)
2467 			continue;
2468 
2469 		/* if supported only 1x1, skip it */
2470 		if (curr_peer->spatial_streams == HW_MODE_SS_1x1)
2471 			continue;
2472 
2473 		tdls_debug("Indicate TDLS teardown peer bssid "
2474 			   QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(
2475 			   curr_peer->peer_mac.bytes));
2476 		tdls_indicate_teardown(curr_peer->vdev_priv, curr_peer,
2477 				       TDLS_TEARDOWN_PEER_UNSPEC_REASON);
2478 
2479 		soc_obj->tdls_teardown_peers_cnt++;
2480 	}
2481 
2482 	if (soc_obj->tdls_teardown_peers_cnt >= 1) {
2483 		soc_obj->tdls_nss_switch_in_progress = true;
2484 		tdls_debug("TDLS peers to be torn down = %d",
2485 			   soc_obj->tdls_teardown_peers_cnt);
2486 
2487 		/* set the antenna switch transition mode */
2488 		if (mode == HW_MODE_SS_1x1) {
2489 			soc_obj->tdls_nss_transition_mode =
2490 				TDLS_NSS_TRANSITION_S_2x2_to_1x1;
2491 			ret = -EAGAIN;
2492 		} else {
2493 			soc_obj->tdls_nss_transition_mode =
2494 				TDLS_NSS_TRANSITION_S_1x1_to_2x2;
2495 			ret = 0;
2496 		}
2497 		tdls_debug("TDLS teardown for antenna switch operation starts");
2498 	}
2499 
2500 	return ret;
2501 }
2502 
tdls_process_antenna_switch(struct tdls_antenna_switch_request * req)2503 QDF_STATUS tdls_process_antenna_switch(struct tdls_antenna_switch_request *req)
2504 {
2505 	QDF_STATUS status;
2506 	struct tdls_soc_priv_obj *soc_obj;
2507 	struct tdls_vdev_priv_obj *vdev_obj;
2508 	struct wlan_objmgr_vdev *vdev = NULL;
2509 	uint32_t vdev_nss;
2510 	int ant_switch_state = 0;
2511 	uint32_t vdev_id;
2512 	enum QDF_OPMODE opmode;
2513 	qdf_freq_t freq;
2514 	struct tdls_osif_indication ind;
2515 	enum policy_mgr_con_mode mode;
2516 
2517 	if (!req) {
2518 		tdls_err("null req");
2519 		return QDF_STATUS_E_INVAL;
2520 	}
2521 
2522 	vdev = req->vdev;
2523 	if (!vdev) {
2524 		tdls_err("null vdev");
2525 		qdf_mem_free(req);
2526 		return QDF_STATUS_E_INVAL;
2527 	}
2528 
2529 	status = tdls_get_vdev_objects(vdev, &vdev_obj, &soc_obj);
2530 	if (QDF_IS_STATUS_ERROR(status)) {
2531 		tdls_err("can't get vdev_obj & soc_obj");
2532 		goto get_obj_err;
2533 	}
2534 
2535 	if (soc_obj->connected_peer_count == 0)
2536 		goto ant_sw_done;
2537 
2538 	if (soc_obj->tdls_nss_switch_in_progress) {
2539 		if (!soc_obj->tdls_nss_teardown_complete) {
2540 			tdls_err("TDLS antenna switch is in progress");
2541 			goto ant_sw_in_progress;
2542 		} else {
2543 			goto ant_sw_done;
2544 		}
2545 	}
2546 
2547 	vdev_id = wlan_vdev_get_id(vdev);
2548 	opmode = wlan_vdev_mlme_get_opmode(vdev);
2549 	mode = policy_mgr_qdf_opmode_to_pm_con_mode(wlan_vdev_get_psoc(vdev),
2550 						    opmode, vdev_id);
2551 	freq = policy_mgr_get_channel(soc_obj->soc,
2552 				      mode,
2553 				      &vdev_id);
2554 
2555 	/* Check supported nss for TDLS, if is 1x1, no need to teardown links */
2556 	if (WLAN_REG_IS_24GHZ_CH_FREQ(freq))
2557 		vdev_nss = soc_obj->tdls_configs.tdls_vdev_nss_2g;
2558 	else
2559 		vdev_nss = soc_obj->tdls_configs.tdls_vdev_nss_5g;
2560 
2561 	if (vdev_nss == HW_MODE_SS_1x1) {
2562 		tdls_debug("Supported NSS is 1x1, no need to teardown TDLS links");
2563 		goto ant_sw_done;
2564 	}
2565 
2566 	if (tdls_teardown_links(soc_obj, req->mode) == 0)
2567 		goto ant_sw_done;
2568 
2569 ant_sw_in_progress:
2570 	ant_switch_state = -EAGAIN;
2571 ant_sw_done:
2572 	if (soc_obj->tdls_event_cb) {
2573 		ind.vdev = vdev;
2574 		ind.status = ant_switch_state;
2575 		soc_obj->tdls_event_cb(soc_obj->tdls_evt_cb_data,
2576 				       TDLS_EVENT_ANTENNA_SWITCH, &ind);
2577 	}
2578 
2579 	if (soc_obj->tdls_nss_switch_in_progress &&
2580 	    soc_obj->tdls_nss_teardown_complete) {
2581 		soc_obj->tdls_nss_switch_in_progress = false;
2582 		soc_obj->tdls_nss_teardown_complete = false;
2583 	}
2584 	tdls_debug("tdls_nss_switch_in_progress: %d tdls_nss_teardown_complete: %d",
2585 		   soc_obj->tdls_nss_switch_in_progress,
2586 		   soc_obj->tdls_nss_teardown_complete);
2587 
2588 get_obj_err:
2589 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
2590 	qdf_mem_free(req);
2591 
2592 	return status;
2593 }
2594 
tdls_antenna_switch_flush_callback(struct scheduler_msg * msg)2595 QDF_STATUS tdls_antenna_switch_flush_callback(struct scheduler_msg *msg)
2596 {
2597 	struct tdls_antenna_switch_request *req;
2598 
2599 	if (!msg || !msg->bodyptr) {
2600 		tdls_err("msg: 0x%pK", msg);
2601 		return QDF_STATUS_E_NULL_VALUE;
2602 	}
2603 	req = msg->bodyptr;
2604 	wlan_objmgr_vdev_release_ref(req->vdev, WLAN_TDLS_NB_ID);
2605 	qdf_mem_free(req);
2606 
2607 	return QDF_STATUS_SUCCESS;
2608 }
2609 
wlan_tdls_offchan_parms_callback(struct wlan_objmgr_vdev * vdev)2610 void wlan_tdls_offchan_parms_callback(struct wlan_objmgr_vdev *vdev)
2611 {
2612 	if (!vdev) {
2613 		tdls_err("vdev is NULL");
2614 		return;
2615 	}
2616 
2617 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
2618 }
2619 
tdls_process_set_offchannel(struct tdls_set_offchannel * req)2620 int tdls_process_set_offchannel(struct tdls_set_offchannel *req)
2621 {
2622 	int status;
2623 	struct tdls_vdev_priv_obj *tdls_vdev_obj;
2624 	struct tdls_soc_priv_obj *tdls_soc_obj;
2625 
2626 	if (tdls_get_vdev_objects(req->vdev, &tdls_vdev_obj, &tdls_soc_obj) !=
2627 		QDF_STATUS_SUCCESS) {
2628 		status = -ENOTSUPP;
2629 		goto free;
2630 	}
2631 
2632 	tdls_debug("TDLS offchannel to be configured %d", req->offchannel);
2633 
2634 	if (req->offchannel)
2635 		status = tdls_set_tdls_offchannel(tdls_soc_obj,
2636 						  req->offchannel);
2637 	else
2638 		status = -ENOTSUPP;
2639 
2640 free:
2641 
2642 	if (req->callback)
2643 		req->callback(req->vdev);
2644 	qdf_mem_free(req);
2645 
2646 	return status;
2647 }
2648 
tdls_process_set_offchan_mode(struct tdls_set_offchanmode * req)2649 int tdls_process_set_offchan_mode(struct tdls_set_offchanmode *req)
2650 {
2651 	int status = QDF_STATUS_E_FAILURE;
2652 	struct tdls_soc_priv_obj *tdls_soc_obj;
2653 
2654 	tdls_debug("TDLS offchan mode to be configured %d", req->offchan_mode);
2655 
2656 	tdls_soc_obj = wlan_vdev_get_tdls_soc_obj(req->vdev);
2657 	if (!tdls_soc_obj)
2658 		goto free;
2659 
2660 	if ((tdls_get_connected_peer_count(tdls_soc_obj) > 1) &&
2661 	    req->offchan_mode == ENABLE_CHANSWITCH) {
2662 		tdls_debug("Reject off chan enable, Connected peer count %d",
2663 			   tdls_get_connected_peer_count(tdls_soc_obj));
2664 		goto free;
2665 	}
2666 
2667 	status = tdls_set_tdls_offchannelmode(req->vdev, req->offchan_mode);
2668 
2669 	if (req->callback)
2670 		req->callback(req->vdev);
2671 
2672 free:
2673 	qdf_mem_free(req);
2674 
2675 	return status;
2676 }
2677 
tdls_process_set_secoffchanneloffset(struct tdls_set_secoffchanneloffset * req)2678 int tdls_process_set_secoffchanneloffset(
2679 		struct tdls_set_secoffchanneloffset *req)
2680 {
2681 	int status;
2682 	struct tdls_vdev_priv_obj *tdls_vdev_obj;
2683 	struct tdls_soc_priv_obj *tdls_soc_obj;
2684 
2685 	if (tdls_get_vdev_objects(req->vdev, &tdls_vdev_obj, &tdls_soc_obj) !=
2686 		QDF_STATUS_SUCCESS) {
2687 		status = -ENOTSUPP;
2688 		goto free;
2689 	}
2690 
2691 	tdls_debug("TDLS offchannel offset to be configured %d",
2692 		   req->offchan_offset);
2693 	status = tdls_set_tdls_secoffchanneloffset(tdls_soc_obj,
2694 						   req->offchan_offset);
2695 
2696 free:
2697 
2698 	if (req->callback)
2699 		req->callback(req->vdev);
2700 	qdf_mem_free(req);
2701 
2702 	return status;
2703 }
2704