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 ®_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