1 /*
2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /**
21 * DOC: This file contains off channel tx API definitions
22 */
23
24 #include <wmi_unified_api.h>
25 #include <wlan_mgmt_txrx_utils_api.h>
26 #include <wlan_objmgr_psoc_obj.h>
27 #include <wlan_objmgr_peer_obj.h>
28 #include <wlan_utility.h>
29 #include <scheduler_api.h>
30 #include "wlan_p2p_public_struct.h"
31 #include "wlan_p2p_tgt_api.h"
32 #include "wlan_p2p_ucfg_api.h"
33 #include "wlan_p2p_roc.h"
34 #include "wlan_p2p_main.h"
35 #include "wlan_p2p_off_chan_tx.h"
36 #include "wlan_osif_request_manager.h"
37 #include <wlan_mlme_main.h>
38 #include "wlan_mlme_api.h"
39 #include <wlan_cm_api.h>
40 #include <wlan_mlo_mgr_sta.h>
41
42 /**
43 * p2p_psoc_get_tx_ops() - get p2p tx ops
44 * @psoc: psoc object
45 *
46 * This function returns p2p tx ops callbacks.
47 *
48 * Return: wlan_lmac_if_p2p_tx_ops
49 */
50 static inline struct wlan_lmac_if_p2p_tx_ops *
p2p_psoc_get_tx_ops(struct wlan_objmgr_psoc * psoc)51 p2p_psoc_get_tx_ops(struct wlan_objmgr_psoc *psoc)
52 {
53 return &psoc->soc_cb.tx_ops->p2p;
54 }
55
56 /**
57 * p2p_tx_context_check_valid() - check tx action context
58 * @tx_ctx: tx context
59 *
60 * This function check if tx action context and parameters are valid.
61 *
62 * Return: QDF_STATUS_SUCCESS - in case of success
63 */
p2p_tx_context_check_valid(struct tx_action_context * tx_ctx)64 static QDF_STATUS p2p_tx_context_check_valid(struct tx_action_context *tx_ctx)
65 {
66 struct wlan_objmgr_psoc *psoc;
67 struct p2p_soc_priv_obj *p2p_soc_obj;
68
69 if (!tx_ctx) {
70 p2p_err("null tx action context");
71 return QDF_STATUS_E_INVAL;
72 }
73
74 p2p_soc_obj = tx_ctx->p2p_soc_obj;
75 if (!p2p_soc_obj) {
76 p2p_err("null p2p soc private object");
77 return QDF_STATUS_E_INVAL;
78 }
79
80 psoc = p2p_soc_obj->soc;
81 if (!psoc) {
82 p2p_err("null p2p soc object");
83 return QDF_STATUS_E_INVAL;
84 }
85
86 if (!tx_ctx->buf) {
87 p2p_err("null tx buffer");
88 return QDF_STATUS_E_INVAL;
89 }
90
91 return QDF_STATUS_SUCCESS;
92 }
93
94 /**
95 * p2p_vdev_check_valid() - check vdev and vdev mode
96 * @tx_ctx: tx context
97 *
98 * This function check if vdev and vdev mode are valid. It will drop
99 * probe response in sta mode.
100 *
101 * Return: QDF_STATUS_SUCCESS - in case of success
102 */
103 #ifdef SUPPORT_P2P_BY_ONE_INTF_WLAN
p2p_vdev_check_valid(struct tx_action_context * tx_ctx)104 static QDF_STATUS p2p_vdev_check_valid(struct tx_action_context *tx_ctx)
105 {
106 enum QDF_OPMODE mode;
107 struct wlan_objmgr_vdev *vdev;
108 struct wlan_objmgr_psoc *psoc;
109 struct p2p_soc_priv_obj *p2p_soc_obj;
110 QDF_STATUS status = QDF_STATUS_SUCCESS;
111
112 p2p_soc_obj = tx_ctx->p2p_soc_obj;
113 psoc = p2p_soc_obj->soc;
114 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
115 psoc, tx_ctx->vdev_id, WLAN_P2P_ID);
116 if (!vdev) {
117 p2p_err("null vdev object");
118 return QDF_STATUS_E_INVAL;
119 }
120
121 mode = wlan_vdev_mlme_get_opmode(vdev);
122 p2p_debug("vdev mode:%d", mode);
123
124 /* drop probe response/disassoc/deauth for go, sap */
125 if ((mode == QDF_SAP_MODE ||
126 mode == QDF_P2P_GO_MODE) &&
127 ((tx_ctx->frame_info.sub_type == P2P_MGMT_PROBE_RSP) ||
128 (tx_ctx->frame_info.sub_type == P2P_MGMT_DISASSOC) ||
129 (tx_ctx->frame_info.sub_type == P2P_MGMT_DEAUTH))) {
130 p2p_debug("drop frame, mode:%d, sub type:%d", mode,
131 tx_ctx->frame_info.sub_type);
132 status = QDF_STATUS_E_FAILURE;
133 }
134
135 /* drop action frame for sap */
136 if ((mode == QDF_SAP_MODE) &&
137 (tx_ctx->frame_info.sub_type == P2P_MGMT_ACTION) &&
138 (tx_ctx->frame_info.public_action_type ==
139 P2P_PUBLIC_ACTION_NOT_SUPPORT) &&
140 (tx_ctx->frame_info.action_type == P2P_ACTION_NOT_SUPPORT) &&
141 !(wlan_vdev_mlme_feat_cap_get(vdev, WLAN_VDEV_F_SON) &&
142 !tx_ctx->off_chan)) {
143 p2p_debug("drop action frame for SAP");
144 status = QDF_STATUS_E_FAILURE;
145 }
146
147 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
148
149 return status;
150 }
151 #else
p2p_vdev_check_valid(struct tx_action_context * tx_ctx)152 static QDF_STATUS p2p_vdev_check_valid(struct tx_action_context *tx_ctx)
153 {
154 enum QDF_OPMODE mode;
155 struct wlan_objmgr_vdev *vdev;
156 struct wlan_objmgr_psoc *psoc;
157 struct p2p_soc_priv_obj *p2p_soc_obj;
158 QDF_STATUS status = QDF_STATUS_SUCCESS;
159
160 p2p_soc_obj = tx_ctx->p2p_soc_obj;
161 psoc = p2p_soc_obj->soc;
162 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
163 psoc, tx_ctx->vdev_id, WLAN_P2P_ID);
164 if (!vdev) {
165 p2p_err("null vdev object");
166 return QDF_STATUS_E_INVAL;
167 }
168
169 mode = wlan_vdev_mlme_get_opmode(vdev);
170 p2p_debug("vdev mode:%d", mode);
171
172 /* drop probe response/disassoc/deauth for sta, go, sap */
173 if ((mode == QDF_STA_MODE &&
174 tx_ctx->frame_info.sub_type == P2P_MGMT_PROBE_RSP) ||
175 ((mode == QDF_SAP_MODE || mode == QDF_P2P_GO_MODE) &&
176 ((tx_ctx->frame_info.sub_type == P2P_MGMT_PROBE_RSP) ||
177 (tx_ctx->frame_info.sub_type == P2P_MGMT_DISASSOC) ||
178 (tx_ctx->frame_info.sub_type == P2P_MGMT_DEAUTH)))) {
179 p2p_debug("drop frame, mode:%d, sub type:%d", mode,
180 tx_ctx->frame_info.sub_type);
181 status = QDF_STATUS_E_FAILURE;
182 }
183
184 /* drop ation frame for sap */
185 if ((mode == QDF_SAP_MODE) &&
186 (tx_ctx->frame_info.sub_type == P2P_MGMT_ACTION) &&
187 (tx_ctx->frame_info.public_action_type ==
188 P2P_PUBLIC_ACTION_NOT_SUPPORT) &&
189 (tx_ctx->frame_info.action_type == P2P_ACTION_NOT_SUPPORT) &&
190 !(wlan_vdev_mlme_feat_cap_get(vdev, WLAN_VDEV_F_SON) &&
191 !tx_ctx->off_chan)) {
192 p2p_debug("drop action frame for SAP");
193 status = QDF_STATUS_E_FAILURE;
194 }
195
196 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
197
198 return status;
199 }
200 #endif /* SUPPORT_P2P_BY_ONE_INTF_WLAN */
201
202 /**
203 * p2p_check_and_update_channel() - check and update tx channel
204 * @tx_ctx: tx context
205 *
206 * This function checks and updates tx channel if channel is 0 in tx context.
207 * It will update channel to current roc channel if vdev mode is
208 * P2P DEVICE/CLIENT/GO.
209 *
210 * Return: QDF_STATUS_SUCCESS - in case of success
211 */
p2p_check_and_update_channel(struct tx_action_context * tx_ctx)212 static QDF_STATUS p2p_check_and_update_channel(struct tx_action_context *tx_ctx)
213 {
214 enum QDF_OPMODE mode;
215 struct wlan_objmgr_vdev *vdev;
216 struct wlan_objmgr_psoc *psoc;
217 struct p2p_soc_priv_obj *p2p_soc_obj;
218 struct p2p_roc_context *curr_roc_ctx;
219
220 if (!tx_ctx || tx_ctx->chan_freq) {
221 p2p_err("NULL tx ctx or channel valid");
222 return QDF_STATUS_E_INVAL;
223 }
224
225 p2p_soc_obj = tx_ctx->p2p_soc_obj;
226 psoc = p2p_soc_obj->soc;
227 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
228 psoc, tx_ctx->vdev_id, WLAN_P2P_ID);
229 if (!vdev) {
230 p2p_err("null vdev object");
231 return QDF_STATUS_E_INVAL;
232 }
233
234 mode = wlan_vdev_mlme_get_opmode(vdev);
235 curr_roc_ctx = p2p_find_current_roc_ctx(p2p_soc_obj);
236
237 if (curr_roc_ctx &&
238 (mode == QDF_P2P_DEVICE_MODE ||
239 mode == QDF_P2P_CLIENT_MODE ||
240 mode == QDF_P2P_GO_MODE))
241 tx_ctx->chan_freq = curr_roc_ctx->chan_freq;
242
243 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
244
245 return QDF_STATUS_SUCCESS;
246 }
247
248 /**
249 * p2p_get_p2pie_ptr() - get the pointer to p2p ie
250 * @ie: source ie
251 * @ie_len: source ie length
252 *
253 * This function finds out p2p ie by p2p oui and return the pointer.
254 *
255 * Return: pointer to p2p ie
256 */
p2p_get_p2pie_ptr(const uint8_t * ie,uint16_t ie_len)257 const uint8_t *p2p_get_p2pie_ptr(const uint8_t *ie, uint16_t ie_len)
258 {
259 return wlan_get_vendor_ie_ptr_from_oui(P2P_OUI,
260 P2P_OUI_SIZE, ie, ie_len);
261 }
262
263 /**
264 * p2p_get_p2pie_from_probe_rsp() - get the pointer to p2p ie from
265 * probe response
266 * @tx_ctx: tx context
267 *
268 * This function finds out p2p ie and return the pointer if it is a
269 * probe response frame.
270 *
271 * Return: pointer to p2p ie
272 */
p2p_get_p2pie_from_probe_rsp(struct tx_action_context * tx_ctx)273 static const uint8_t *p2p_get_p2pie_from_probe_rsp(
274 struct tx_action_context *tx_ctx)
275 {
276 const uint8_t *ie;
277 const uint8_t *p2p_ie;
278 const uint8_t *tmp_p2p_ie = NULL;
279 uint16_t ie_len;
280
281 if (tx_ctx->buf_len <= PROBE_RSP_IE_OFFSET) {
282 p2p_err("Invalid header len for probe response");
283 return NULL;
284 }
285
286 ie = tx_ctx->buf + PROBE_RSP_IE_OFFSET;
287 ie_len = tx_ctx->buf_len - PROBE_RSP_IE_OFFSET;
288 p2p_ie = p2p_get_p2pie_ptr(ie, ie_len);
289 while ((p2p_ie) &&
290 (WLAN_MAX_IE_LEN == p2p_ie[1])) {
291 ie_len = tx_ctx->buf_len - (p2p_ie - tx_ctx->buf);
292 if (ie_len > 2) {
293 ie = p2p_ie + WLAN_MAX_IE_LEN + 2;
294 tmp_p2p_ie = p2p_get_p2pie_ptr(ie, ie_len);
295 }
296
297 if (tmp_p2p_ie) {
298 p2p_ie = tmp_p2p_ie;
299 tmp_p2p_ie = NULL;
300 } else {
301 break;
302 }
303 }
304
305 return p2p_ie;
306 }
307
308 /**
309 * p2p_get_presence_noa_attr() - get the pointer to noa attr
310 * @pies: source ie
311 * @length: source ie length
312 *
313 * This function finds out noa attr by noa eid and return the pointer.
314 *
315 * Return: pointer to noa attr
316 */
p2p_get_presence_noa_attr(const uint8_t * pies,int length)317 static const uint8_t *p2p_get_presence_noa_attr(const uint8_t *pies, int length)
318 {
319 int left = length;
320 const uint8_t *ptr = pies;
321 uint8_t elem_id;
322 uint16_t elem_len;
323
324 p2p_debug("pies:%pK, length:%d", pies, length);
325
326 while (left >= 3) {
327 elem_id = ptr[0];
328 elem_len = ((uint16_t) ptr[1]) | (ptr[2] << 8);
329
330 left -= 3;
331 if (elem_len > left) {
332 p2p_err("****Invalid IEs, elem_len=%d left=%d*****",
333 elem_len, left);
334 return NULL;
335 }
336 if (elem_id == P2P_NOA_ATTR)
337 return ptr;
338
339 left -= elem_len;
340 ptr += (elem_len + 3);
341 }
342
343 return NULL;
344 }
345
346 /**
347 * p2p_get_noa_attr_stream_in_mult_p2p_ies() - get the pointer to noa
348 * attr from multi p2p ie
349 * @noa_stream: noa stream
350 * @noa_len: noa stream length
351 * @overflow_len: overflow length
352 *
353 * This function finds out noa attr from multi p2p ies.
354 *
355 * Return: noa length
356 */
p2p_get_noa_attr_stream_in_mult_p2p_ies(uint8_t * noa_stream,uint8_t noa_len,uint8_t overflow_len)357 static uint8_t p2p_get_noa_attr_stream_in_mult_p2p_ies(uint8_t *noa_stream,
358 uint8_t noa_len, uint8_t overflow_len)
359 {
360 uint8_t overflow_p2p_stream[P2P_MAX_NOA_ATTR_LEN];
361
362 p2p_debug("noa_stream:%pK, noa_len:%d, overflow_len:%d",
363 noa_stream, noa_len, overflow_len);
364 if ((noa_len <= (P2P_MAX_NOA_ATTR_LEN + P2P_IE_HEADER_LEN)) &&
365 (noa_len >= overflow_len) &&
366 (overflow_len <= P2P_MAX_NOA_ATTR_LEN)) {
367 qdf_mem_copy(overflow_p2p_stream,
368 noa_stream + noa_len - overflow_len,
369 overflow_len);
370 noa_stream[noa_len - overflow_len] =
371 P2P_EID_VENDOR;
372 noa_stream[noa_len - overflow_len + 1] =
373 overflow_len + P2P_OUI_SIZE;
374 qdf_mem_copy(noa_stream + noa_len - overflow_len + 2,
375 P2P_OUI, P2P_OUI_SIZE);
376 qdf_mem_copy(noa_stream + noa_len + 2 + P2P_OUI_SIZE -
377 overflow_len, overflow_p2p_stream,
378 overflow_len);
379 }
380
381 return noa_len + P2P_IE_HEADER_LEN;
382 }
383
384 /**
385 * p2p_get_vdev_noa_info() - get vdev noa information
386 * @tx_ctx: tx context
387 *
388 * This function gets vdev noa information
389 *
390 * Return: pointer to noa information
391 */
p2p_get_vdev_noa_info(struct tx_action_context * tx_ctx)392 static struct p2p_noa_info *p2p_get_vdev_noa_info(
393 struct tx_action_context *tx_ctx)
394 {
395 struct p2p_vdev_priv_obj *p2p_vdev_obj;
396 struct p2p_soc_priv_obj *p2p_soc_obj;
397 struct wlan_objmgr_vdev *vdev;
398 struct wlan_objmgr_psoc *psoc;
399 enum QDF_OPMODE mode;
400 struct p2p_noa_info *noa_info = NULL;
401
402 p2p_soc_obj = tx_ctx->p2p_soc_obj;
403 psoc = p2p_soc_obj->soc;
404 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
405 tx_ctx->vdev_id, WLAN_P2P_ID);
406 if (!vdev) {
407 p2p_err("vdev obj is NULL");
408 return NULL;
409 }
410
411 mode = wlan_vdev_mlme_get_opmode(vdev);
412 p2p_debug("vdev mode:%d", mode);
413 if (mode != QDF_P2P_GO_MODE) {
414 p2p_debug("invalid p2p vdev mode:%d", mode);
415 goto fail;
416 }
417
418 p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(vdev,
419 WLAN_UMAC_COMP_P2P);
420
421 if (!p2p_vdev_obj || !(p2p_vdev_obj->noa_info)) {
422 p2p_debug("null noa info");
423 goto fail;
424 }
425
426 noa_info = p2p_vdev_obj->noa_info;
427
428 fail:
429 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
430
431 return noa_info;
432 }
433
434 /**
435 * p2p_get_noa_attr_stream() - get noa stream from p2p vdev object
436 * @tx_ctx: tx context
437 * @pnoa_stream: pointer to noa stream
438 *
439 * This function finds out noa stream from p2p vdev object
440 *
441 * Return: noa stream length
442 */
p2p_get_noa_attr_stream(struct tx_action_context * tx_ctx,uint8_t * pnoa_stream)443 static uint8_t p2p_get_noa_attr_stream(
444 struct tx_action_context *tx_ctx, uint8_t *pnoa_stream)
445 {
446 struct p2p_noa_info *noa_info;
447 struct noa_descriptor *noa_desc_0;
448 struct noa_descriptor *noa_desc_1;
449 uint8_t *pbody = pnoa_stream;
450 uint8_t len = 0;
451
452 noa_info = p2p_get_vdev_noa_info(tx_ctx);
453 if (!noa_info) {
454 p2p_debug("not valid noa information");
455 return 0;
456 }
457
458 noa_desc_0 = &(noa_info->noa_desc[0]);
459 noa_desc_1 = &(noa_info->noa_desc[1]);
460 if ((!(noa_desc_0->duration)) &&
461 (!(noa_desc_1->duration)) &&
462 (!noa_info->opps_ps)) {
463 p2p_debug("opps ps and duration are 0");
464 return 0;
465 }
466
467 pbody[0] = P2P_NOA_ATTR;
468 pbody[3] = noa_info->index;
469 pbody[4] = noa_info->ct_window | (noa_info->opps_ps << 7);
470 len = 5;
471 pbody += len;
472
473 if (noa_desc_0->duration) {
474 *pbody = noa_desc_0->type_count;
475 pbody += 1;
476 len += 1;
477
478 *((uint32_t *) (pbody)) = noa_desc_0->duration;
479 pbody += sizeof(uint32_t);
480 len += 4;
481
482 *((uint32_t *) (pbody)) = noa_desc_0->interval;
483 pbody += sizeof(uint32_t);
484 len += 4;
485
486 *((uint32_t *) (pbody)) = noa_desc_0->start_time;
487 pbody += sizeof(uint32_t);
488 len += 4;
489 }
490
491 if (noa_desc_1->duration) {
492 *pbody = noa_desc_1->type_count;
493 pbody += 1;
494 len += 1;
495
496 *((uint32_t *) (pbody)) = noa_desc_1->duration;
497 pbody += sizeof(uint32_t);
498 len += 4;
499
500 *((uint32_t *) (pbody)) = noa_desc_1->interval;
501 pbody += sizeof(uint32_t);
502 len += 4;
503
504 *((uint32_t *) (pbody)) = noa_desc_1->start_time;
505 pbody += sizeof(uint32_t);
506 len += 4;
507 }
508
509 pbody = pnoa_stream + 1;
510 /* one byte for Attr and 2 bytes for length */
511 *((uint16_t *) (pbody)) = len - 3;
512
513 return len;
514 }
515
516 /**
517 * p2p_update_noa_stream() - update noa stream
518 * @tx_ctx: tx context
519 * @p2p_ie: pointer to p2p ie
520 * @noa_attr: pointer to noa attr
521 * @total_len: pointer to total length of ie
522 * @noa_stream: noa stream
523 *
524 * This function updates noa stream.
525 *
526 * Return: noa stream length
527 */
p2p_update_noa_stream(struct tx_action_context * tx_ctx,uint8_t * p2p_ie,const uint8_t * noa_attr,uint32_t * total_len,uint8_t * noa_stream)528 static uint16_t p2p_update_noa_stream(struct tx_action_context *tx_ctx,
529 uint8_t *p2p_ie, const uint8_t *noa_attr, uint32_t *total_len,
530 uint8_t *noa_stream)
531 {
532 uint16_t noa_len;
533 uint16_t overflow_len;
534 uint8_t orig_len;
535 uint32_t nbytes_copy;
536 uint32_t buf_len = *total_len;
537
538 noa_len = p2p_get_noa_attr_stream(tx_ctx, noa_stream);
539 if (noa_len <= 0) {
540 p2p_debug("do not find out noa attr");
541 return 0;
542 }
543
544 orig_len = p2p_ie[1];
545 if (noa_attr) {
546 noa_len = noa_attr[1] | (noa_attr[2] << 8);
547 orig_len -= (noa_len + 1 + 2);
548 buf_len -= (noa_len + 1 + 2);
549 p2p_ie[1] = orig_len;
550 }
551
552 if ((p2p_ie[1] + noa_len) > WLAN_MAX_IE_LEN) {
553 overflow_len = p2p_ie[1] + noa_len -
554 WLAN_MAX_IE_LEN;
555 noa_len = p2p_get_noa_attr_stream_in_mult_p2p_ies(
556 noa_stream, noa_len, overflow_len);
557 p2p_ie[1] = WLAN_MAX_IE_LEN;
558 } else {
559 /* increment the length of P2P IE */
560 p2p_ie[1] += noa_len;
561 }
562
563 *total_len = buf_len;
564 nbytes_copy = (p2p_ie + orig_len + 2) - tx_ctx->buf;
565
566 p2p_debug("noa_len=%d orig_len=%d p2p_ie=%pK buf_len=%d nbytes copy=%d ",
567 noa_len, orig_len, p2p_ie, buf_len, nbytes_copy);
568
569 return noa_len;
570 }
571
572 /**
573 * p2p_set_ht_caps() - set ht capability
574 * @tx_ctx: tx context
575 * @num_bytes: number bytes
576 *
577 * This function sets ht capability
578 *
579 * Return: None
580 */
p2p_set_ht_caps(struct tx_action_context * tx_ctx,uint32_t num_bytes)581 static void p2p_set_ht_caps(struct tx_action_context *tx_ctx,
582 uint32_t num_bytes)
583 {
584 }
585
586 /**
587 * p2p_get_next_seq_num() - get next sequence number to fill mac header
588 * @peer: PEER object
589 * @tx_ctx: tx context
590 * @ta : transmitter address
591 *
592 * API to get next sequence number of action frame for the peer.
593 *
594 * Return: Next sequence number of the peer
595 */
p2p_get_next_seq_num(struct wlan_objmgr_peer * peer,struct tx_action_context * tx_ctx,uint8_t * ta)596 static uint16_t p2p_get_next_seq_num(struct wlan_objmgr_peer *peer,
597 struct tx_action_context *tx_ctx,
598 uint8_t *ta)
599 {
600 uint16_t random_num, random_num_bitmask = 0x03FF;
601 uint16_t seq_num, seq_num_bitmask = 0x0FFF;
602 struct p2p_vdev_priv_obj *p2p_vdev_obj;
603 struct wlan_objmgr_vdev *vdev;
604 bool is_new_random_ta;
605
606 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(tx_ctx->p2p_soc_obj->soc,
607 tx_ctx->vdev_id,
608 WLAN_P2P_ID);
609 if (!vdev) {
610 p2p_debug("vdev is null");
611 return false;
612 }
613
614 p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(
615 vdev, WLAN_UMAC_COMP_P2P);
616 if (!p2p_vdev_obj) {
617 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
618 p2p_debug("p2p vdev object is NULL");
619 return false;
620 }
621
622 is_new_random_ta = qdf_mem_cmp(p2p_vdev_obj->prev_action_frame_addr2,
623 ta, QDF_MAC_ADDR_SIZE);
624 if (is_new_random_ta &&
625 tx_ctx->p2p_soc_obj->param.is_random_seq_num_enabled) {
626 /**
627 * Increment the previous sequence number with 10-bits
628 * random number to get the next sequence number.
629 */
630
631 qdf_get_random_bytes(&random_num, sizeof(random_num));
632 random_num &= random_num_bitmask;
633 seq_num = (peer->peer_mlme.seq_num + random_num) &
634 seq_num_bitmask;
635 peer->peer_mlme.seq_num = seq_num;
636
637 qdf_mem_copy(p2p_vdev_obj->prev_action_frame_addr2, ta,
638 QDF_MAC_ADDR_SIZE);
639
640 } else {
641 seq_num = wlan_peer_mlme_get_next_seq_num(peer);
642 }
643
644 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
645
646 return seq_num;
647 }
648
649 /**
650 * p2p_populate_mac_header() - update sequence number
651 * @tx_ctx: tx context
652 *
653 * This function updates sequence number of this mgmt frame
654 *
655 * Return: QDF_STATUS_SUCCESS - in case of success
656 */
p2p_populate_mac_header(struct tx_action_context * tx_ctx)657 static QDF_STATUS p2p_populate_mac_header(
658 struct tx_action_context *tx_ctx)
659 {
660 struct wlan_seq_ctl *seq_ctl;
661 struct wlan_frame_hdr *wh;
662 struct wlan_objmgr_peer *peer;
663 struct wlan_objmgr_psoc *psoc;
664 void *mac_addr;
665 uint16_t seq_num;
666 uint8_t pdev_id;
667 struct wlan_objmgr_vdev *vdev;
668 enum QDF_OPMODE opmode;
669
670 psoc = tx_ctx->p2p_soc_obj->soc;
671
672 wh = (struct wlan_frame_hdr *)tx_ctx->buf;
673 /*
674 * Remove the WEP bit if already set, p2p_populate_rmf_field will set it
675 * if required.
676 */
677 wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
678 mac_addr = wh->i_addr1;
679 pdev_id = wlan_get_pdev_id_from_vdev_id(psoc, tx_ctx->vdev_id,
680 WLAN_P2P_ID);
681 peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr, WLAN_P2P_ID);
682 if (!peer) {
683 mac_addr = wh->i_addr2;
684 peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr,
685 WLAN_P2P_ID);
686 }
687 if (!peer) {
688 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
689 tx_ctx->vdev_id,
690 WLAN_P2P_ID);
691 if (vdev) {
692 opmode = wlan_vdev_mlme_get_opmode(vdev);
693 /*
694 * For NAN iface, retrieves mac address from vdev
695 * as it is self peer. Also, rand_mac_tx would be
696 * false as tx channel is not available.
697 */
698 if (opmode == QDF_NAN_DISC_MODE ||
699 tx_ctx->rand_mac_tx) {
700 mac_addr = wlan_vdev_mlme_get_macaddr(vdev);
701 peer = wlan_objmgr_get_peer(psoc, pdev_id,
702 mac_addr,
703 WLAN_P2P_ID);
704 }
705
706 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
707 }
708 }
709 if (!peer) {
710 p2p_err("no valid peer");
711 return QDF_STATUS_E_INVAL;
712 }
713 seq_num = (uint16_t)p2p_get_next_seq_num(peer, tx_ctx, wh->i_addr2);
714 seq_ctl = (struct wlan_seq_ctl *)(tx_ctx->buf +
715 WLAN_SEQ_CTL_OFFSET);
716 seq_ctl->seq_num_lo = (seq_num & WLAN_LOW_SEQ_NUM_MASK);
717 seq_ctl->seq_num_hi = ((seq_num & WLAN_HIGH_SEQ_NUM_MASK) >>
718 WLAN_HIGH_SEQ_NUM_OFFSET);
719 p2p_debug("seq num: %d", seq_num);
720
721 wlan_objmgr_peer_release_ref(peer, WLAN_P2P_ID);
722
723 return QDF_STATUS_SUCCESS;
724 }
725
726 /**
727 * p2p_get_frame_type_str() - parse frame type to string
728 * @frame_info: frame information
729 *
730 * This function parse frame type to string.
731 *
732 * Return: command string
733 */
p2p_get_frame_type_str(struct p2p_frame_info * frame_info)734 static char *p2p_get_frame_type_str(struct p2p_frame_info *frame_info)
735 {
736 if (frame_info->type == P2P_FRAME_NOT_SUPPORT)
737 return "Not support frame";
738
739 if (frame_info->sub_type == P2P_MGMT_NOT_SUPPORT)
740 return "Not support sub frame";
741
742 if (frame_info->action_type == P2P_ACTION_PRESENCE_REQ)
743 return "P2P action presence request";
744 if (frame_info->action_type == P2P_ACTION_PRESENCE_RSP)
745 return "P2P action presence response";
746
747 switch (frame_info->public_action_type) {
748 case P2P_PUBLIC_ACTION_NEG_REQ:
749 return "GO negotiation request frame";
750 case P2P_PUBLIC_ACTION_NEG_RSP:
751 return "GO negotiation response frame";
752 case P2P_PUBLIC_ACTION_NEG_CNF:
753 return "GO negotiation confirm frame";
754 case P2P_PUBLIC_ACTION_INVIT_REQ:
755 return "P2P invitation request";
756 case P2P_PUBLIC_ACTION_INVIT_RSP:
757 return "P2P invitation response";
758 case P2P_PUBLIC_ACTION_DEV_DIS_REQ:
759 return "Device discoverability request";
760 case P2P_PUBLIC_ACTION_DEV_DIS_RSP:
761 return "Device discoverability response";
762 case P2P_PUBLIC_ACTION_PROV_DIS_REQ:
763 return "Provision discovery request";
764 case P2P_PUBLIC_ACTION_PROV_DIS_RSP:
765 return "Provision discovery response";
766 case P2P_PUBLIC_ACTION_GAS_INIT_REQ:
767 return "GAS init request";
768 case P2P_PUBLIC_ACTION_GAS_INIT_RSP:
769 return "GAS init response";
770 case P2P_PUBLIC_ACTION_GAS_COMB_REQ:
771 return "GAS come back request";
772 case P2P_PUBLIC_ACTION_GAS_COMB_RSP:
773 return "GAS come back response";
774 case P2P_PUBLIC_ACTION_WNM_BTM_REQ:
775 return "BTM request";
776 case P2P_PUBLIC_ACTION_RRM_BEACON_REQ:
777 return "BEACON request";
778 case P2P_PUBLIC_ACTION_RRM_NEIGHBOR_RSP:
779 return "NEIGHBOR response";
780 default:
781 return "Other frame";
782 }
783 }
784
785 /**
786 * p2p_init_frame_info() - init frame information structure
787 * @frame_info: pointer to frame information
788 *
789 * This function init frame information structure.
790 *
791 * Return: None
792 */
p2p_init_frame_info(struct p2p_frame_info * frame_info)793 static void p2p_init_frame_info(struct p2p_frame_info *frame_info)
794 {
795 frame_info->type = P2P_FRAME_NOT_SUPPORT;
796 frame_info->sub_type = P2P_MGMT_NOT_SUPPORT;
797 frame_info->public_action_type =
798 P2P_PUBLIC_ACTION_NOT_SUPPORT;
799 frame_info->action_type = P2P_ACTION_NOT_SUPPORT;
800 }
801
802 /**
803 * p2p_get_frame_info() - get frame information from packet
804 * @data_buf: data buffer address
805 * @length: buffer length
806 * @frame_info: frame information
807 *
808 * This function gets frame information from packet.
809 *
810 * Return: QDF_STATUS_SUCCESS - in case of success
811 */
p2p_get_frame_info(uint8_t * data_buf,uint32_t length,struct p2p_frame_info * frame_info)812 QDF_STATUS p2p_get_frame_info(uint8_t *data_buf, uint32_t length,
813 struct p2p_frame_info *frame_info)
814 {
815 uint8_t type;
816 uint8_t sub_type;
817 uint8_t action_type;
818 uint8_t *buf = data_buf;
819
820 p2p_init_frame_info(frame_info);
821
822 if (length < P2P_ACTION_OFFSET + 1) {
823 p2p_err("invalid p2p mgmt hdr len");
824 return QDF_STATUS_E_INVAL;
825 }
826
827 type = P2P_GET_TYPE_FRM_FC(buf[0]);
828 sub_type = P2P_GET_SUBTYPE_FRM_FC(buf[0]);
829 if (type != P2P_FRAME_MGMT) {
830 p2p_err("just support mgmt frame");
831 return QDF_STATUS_E_FAILURE;
832 }
833
834 frame_info->type = type;
835 frame_info->sub_type = sub_type;
836
837 if (sub_type != P2P_MGMT_ACTION)
838 return QDF_STATUS_SUCCESS;
839
840 buf += P2P_ACTION_OFFSET;
841 if (length > P2P_PUBLIC_ACTION_FRAME_TYPE_OFFSET) {
842 switch (buf[0]) {
843 case P2P_PUBLIC_ACTION_FRAME:
844 if (buf[1] == P2P_PUBLIC_ACTION_VENDOR_SPECIFIC &&
845 !qdf_mem_cmp(&buf[2], P2P_OUI, P2P_OUI_SIZE)) {
846 buf = data_buf +
847 P2P_PUBLIC_ACTION_FRAME_TYPE_OFFSET;
848 action_type = buf[0];
849 if (action_type > P2P_PUBLIC_ACTION_PROV_DIS_RSP)
850 frame_info->public_action_type =
851 P2P_PUBLIC_ACTION_NOT_SUPPORT;
852 else
853 frame_info->public_action_type =
854 action_type;
855 }
856 break;
857 case WNM_ACTION_FRAME:
858 if (buf[1] == WNM_BSS_TM_REQUEST) {
859 action_type = buf[0];
860 frame_info->public_action_type =
861 P2P_PUBLIC_ACTION_WNM_BTM_REQ;
862 }
863 break;
864 case RRM_ACTION_FRAME:
865 if (buf[1] == RRM_RADIO_MEASURE_REQ) {
866 action_type = buf[0];
867 frame_info->public_action_type =
868 P2P_PUBLIC_ACTION_RRM_BEACON_REQ;
869 } else if (buf[1] == RRM_NEIGHBOR_RPT) {
870 action_type = buf[0];
871 frame_info->public_action_type =
872 P2P_PUBLIC_ACTION_RRM_NEIGHBOR_RSP;
873 }
874 break;
875 default:
876 break;
877 }
878 } else if (length > P2P_ACTION_FRAME_TYPE_OFFSET &&
879 buf[0] == P2P_ACTION_VENDOR_SPECIFIC_CATEGORY &&
880 !qdf_mem_cmp(&buf[1], P2P_OUI, P2P_OUI_SIZE)) {
881 buf = data_buf +
882 P2P_ACTION_FRAME_TYPE_OFFSET;
883 action_type = buf[0];
884 if (action_type == P2P_ACTION_PRESENCE_REQ)
885 frame_info->action_type =
886 P2P_ACTION_PRESENCE_REQ;
887 if (action_type == P2P_ACTION_PRESENCE_RSP)
888 frame_info->action_type =
889 P2P_ACTION_PRESENCE_RSP;
890 } else {
891 p2p_debug("this is not vendor specific p2p action frame");
892 return QDF_STATUS_SUCCESS;
893 }
894
895 p2p_debug("%s", p2p_get_frame_type_str(frame_info));
896
897 return QDF_STATUS_SUCCESS;
898 }
899
p2p_is_action_frame_of_p2p_type(uint8_t * data_buf,uint32_t length)900 bool p2p_is_action_frame_of_p2p_type(uint8_t *data_buf, uint32_t length)
901 {
902 struct p2p_frame_info frame_info = {0};
903 QDF_STATUS status;
904
905 status = p2p_get_frame_info(data_buf, length, &frame_info);
906 if (QDF_IS_STATUS_ERROR(status))
907 return false;
908
909 if (frame_info.public_action_type != P2P_PUBLIC_ACTION_NOT_SUPPORT ||
910 frame_info.action_type != P2P_ACTION_NOT_SUPPORT)
911 return true;
912
913 return false;
914 }
915
916 #ifdef WLAN_FEATURE_P2P_DEBUG
917 /**
918 * p2p_tx_update_connection_status() - Update P2P connection status
919 * with tx frame
920 * @p2p_soc_obj: P2P soc private object
921 * @tx_frame_info: frame information
922 * @mac_to: Pointer to dest MAC address
923 *
924 * This function updates P2P connection status with tx frame.
925 *
926 * Return: QDF_STATUS_SUCCESS - in case of success
927 */
p2p_tx_update_connection_status(struct p2p_soc_priv_obj * p2p_soc_obj,struct p2p_frame_info * tx_frame_info,uint8_t * mac_to)928 static QDF_STATUS p2p_tx_update_connection_status(
929 struct p2p_soc_priv_obj *p2p_soc_obj,
930 struct p2p_frame_info *tx_frame_info,
931 uint8_t *mac_to)
932 {
933 if (!p2p_soc_obj || !tx_frame_info || !mac_to) {
934 p2p_err("invalid p2p_soc_obj:%pK or tx_frame_info:%pK or mac_to:%pK",
935 p2p_soc_obj, tx_frame_info, mac_to);
936 return QDF_STATUS_E_INVAL;
937 }
938
939 if (tx_frame_info->public_action_type !=
940 P2P_PUBLIC_ACTION_NOT_SUPPORT)
941 p2p_debug("%s ---> OTA to " QDF_MAC_ADDR_FMT,
942 p2p_get_frame_type_str(tx_frame_info),
943 QDF_MAC_ADDR_REF(mac_to));
944
945 if ((tx_frame_info->public_action_type ==
946 P2P_PUBLIC_ACTION_PROV_DIS_REQ) ||
947 (tx_frame_info->public_action_type ==
948 P2P_PUBLIC_ACTION_INVIT_REQ) ||
949 (tx_frame_info->public_action_type ==
950 P2P_PUBLIC_ACTION_NEG_REQ) ||
951 (tx_frame_info->public_action_type ==
952 P2P_PUBLIC_ACTION_NEG_RSP)) {
953 p2p_status_update(p2p_soc_obj, P2P_GO_NEG_PROCESS);
954 p2p_debug("[P2P State]Inactive state to GO negotiation progress state");
955 } else if ((tx_frame_info->public_action_type ==
956 P2P_PUBLIC_ACTION_NEG_CNF) ||
957 (tx_frame_info->public_action_type ==
958 P2P_PUBLIC_ACTION_INVIT_RSP)) {
959 p2p_status_update(p2p_soc_obj, P2P_GO_NEG_COMPLETED);
960 p2p_debug("[P2P State]GO nego progress to GO nego completed state");
961 }
962
963 return QDF_STATUS_SUCCESS;
964 }
965
966 /**
967 * p2p_rx_update_connection_status() - Update P2P connection status
968 * with rx frame
969 * @p2p_soc_obj: P2P soc private object
970 * @rx_frame_info: frame information
971 * @mac_from: Pointer to source MAC address
972 *
973 * This function updates P2P connection status with rx frame.
974 *
975 * Return: QDF_STATUS_SUCCESS - in case of success
976 */
p2p_rx_update_connection_status(struct p2p_soc_priv_obj * p2p_soc_obj,struct p2p_frame_info * rx_frame_info,uint8_t * mac_from)977 static QDF_STATUS p2p_rx_update_connection_status(
978 struct p2p_soc_priv_obj *p2p_soc_obj,
979 struct p2p_frame_info *rx_frame_info,
980 uint8_t *mac_from)
981 {
982 if (!p2p_soc_obj || !rx_frame_info || !mac_from) {
983 p2p_err("invalid p2p_soc_obj:%pK or rx_frame_info:%pK, mac_from:%pK",
984 p2p_soc_obj, rx_frame_info, mac_from);
985 return QDF_STATUS_E_INVAL;
986 }
987
988 if (rx_frame_info->public_action_type !=
989 P2P_PUBLIC_ACTION_NOT_SUPPORT)
990 p2p_info_rl("%s <--- OTA from " QDF_MAC_ADDR_FMT,
991 p2p_get_frame_type_str(rx_frame_info),
992 QDF_MAC_ADDR_REF(mac_from));
993
994 if ((rx_frame_info->public_action_type ==
995 P2P_PUBLIC_ACTION_PROV_DIS_REQ) ||
996 (rx_frame_info->public_action_type ==
997 P2P_PUBLIC_ACTION_NEG_REQ) ||
998 (rx_frame_info->public_action_type ==
999 P2P_PUBLIC_ACTION_NEG_RSP)) {
1000 p2p_status_update(p2p_soc_obj, P2P_GO_NEG_PROCESS);
1001 p2p_info_rl("[P2P State]Inactive state to GO negotiation progress state");
1002 } else if (((rx_frame_info->public_action_type ==
1003 P2P_PUBLIC_ACTION_NEG_CNF) ||
1004 (rx_frame_info->public_action_type ==
1005 P2P_PUBLIC_ACTION_INVIT_RSP)) &&
1006 (p2p_soc_obj->connection_status ==
1007 P2P_GO_NEG_PROCESS)) {
1008 p2p_status_update(p2p_soc_obj, P2P_GO_NEG_COMPLETED);
1009 p2p_info_rl("[P2P State]GO negotiation progress to GO negotiation completed state");
1010 } else if ((rx_frame_info->public_action_type ==
1011 P2P_PUBLIC_ACTION_INVIT_REQ) &&
1012 (p2p_soc_obj->connection_status == P2P_NOT_ACTIVE)) {
1013 p2p_status_update(p2p_soc_obj, P2P_GO_NEG_COMPLETED);
1014 p2p_info_rl("[P2P State]Inactive state to GO negotiation completed state Autonomous GO formation");
1015 }
1016
1017 return QDF_STATUS_SUCCESS;
1018 }
1019 #else
p2p_tx_update_connection_status(struct p2p_soc_priv_obj * p2p_soc_obj,struct p2p_frame_info * tx_frame_info,uint8_t * mac_to)1020 static QDF_STATUS p2p_tx_update_connection_status(
1021 struct p2p_soc_priv_obj *p2p_soc_obj,
1022 struct p2p_frame_info *tx_frame_info,
1023 uint8_t *mac_to)
1024 {
1025 return QDF_STATUS_SUCCESS;
1026 }
1027
p2p_rx_update_connection_status(struct p2p_soc_priv_obj * p2p_soc_obj,struct p2p_frame_info * rx_frame_info,uint8_t * mac_from)1028 static QDF_STATUS p2p_rx_update_connection_status(
1029 struct p2p_soc_priv_obj *p2p_soc_obj,
1030 struct p2p_frame_info *rx_frame_info,
1031 uint8_t *mac_from)
1032 {
1033 return QDF_STATUS_SUCCESS;
1034 }
1035 #endif
1036
1037 /**
1038 * p2p_packet_alloc() - allocate qdf nbuf
1039 * @size: buffe size
1040 * @data: pointer to qdf nbuf data point
1041 * @ppPacket: pointer to qdf nbuf point
1042 *
1043 * This function allocates qdf nbuf.
1044 *
1045 * Return: QDF_STATUS_SUCCESS - in case of success
1046 */
p2p_packet_alloc(uint16_t size,void ** data,qdf_nbuf_t * ppPacket)1047 static QDF_STATUS p2p_packet_alloc(uint16_t size, void **data,
1048 qdf_nbuf_t *ppPacket)
1049 {
1050 QDF_STATUS status = QDF_STATUS_E_FAILURE;
1051 qdf_nbuf_t nbuf;
1052
1053 nbuf = qdf_nbuf_alloc(NULL,
1054 roundup(size + P2P_TX_PKT_MIN_HEADROOM, 4),
1055 P2P_TX_PKT_MIN_HEADROOM, sizeof(uint32_t),
1056 false);
1057
1058 if (nbuf) {
1059 qdf_nbuf_put_tail(nbuf, size);
1060 qdf_nbuf_set_protocol(nbuf, ETH_P_CONTROL);
1061 *ppPacket = nbuf;
1062 *data = qdf_nbuf_data(nbuf);
1063 qdf_mem_zero(*data, size);
1064 status = QDF_STATUS_SUCCESS;
1065 }
1066
1067 return status;
1068 }
1069
1070 /**
1071 * p2p_send_tx_conf() - send tx confirm
1072 * @tx_ctx: tx context
1073 * @status: tx status
1074 *
1075 * This function send tx confirm to osif
1076 *
1077 * Return: QDF_STATUS_SUCCESS - pointer to tx context
1078 */
p2p_send_tx_conf(struct tx_action_context * tx_ctx,bool status)1079 static QDF_STATUS p2p_send_tx_conf(struct tx_action_context *tx_ctx,
1080 bool status)
1081 {
1082 struct p2p_tx_cnf tx_cnf;
1083 struct p2p_soc_priv_obj *p2p_soc_obj;
1084 struct p2p_start_param *start_param;
1085
1086 p2p_soc_obj = tx_ctx->p2p_soc_obj;
1087
1088 if (!p2p_soc_obj || !(p2p_soc_obj->start_param)) {
1089 p2p_err("Invalid p2p soc object or start parameters");
1090 return QDF_STATUS_E_INVAL;
1091 }
1092
1093 start_param = p2p_soc_obj->start_param;
1094 if (!(start_param->tx_cnf_cb)) {
1095 p2p_err("no tx confirm callback");
1096 return QDF_STATUS_E_INVAL;
1097 }
1098
1099 if (tx_ctx->no_ack)
1100 tx_cnf.action_cookie = 0;
1101 else
1102 tx_cnf.action_cookie = (uint64_t)tx_ctx->id;
1103
1104 tx_cnf.vdev_id = tx_ctx->vdev_id;
1105 tx_cnf.buf = tx_ctx->buf;
1106 tx_cnf.buf_len = tx_ctx->buf_len;
1107 tx_cnf.status = status ? 0 : 1;
1108
1109 p2p_debug("soc:%pK, vdev_id:%d, action_cookie:%llx, len:%d, status:%d, buf:%pK",
1110 p2p_soc_obj->soc, tx_cnf.vdev_id,
1111 tx_cnf.action_cookie, tx_cnf.buf_len,
1112 tx_cnf.status, tx_cnf.buf);
1113
1114 p2p_rand_mac_tx_done(p2p_soc_obj->soc, tx_ctx);
1115
1116 start_param->tx_cnf_cb(start_param->tx_cnf_cb_data, &tx_cnf);
1117
1118 return QDF_STATUS_SUCCESS;
1119 }
1120
1121 /**
1122 * p2p_get_hw_retry_count() - Get hw tx retry count from config store
1123 * @psoc: psoc object
1124 * @tx_ctx: tx context
1125 *
1126 * This function return the hw tx retry count for p2p action frame.
1127 * 0 value means target will use fw default mgmt tx retry count 15.
1128 *
1129 * Return: frame hw tx retry count
1130 */
p2p_get_hw_retry_count(struct wlan_objmgr_psoc * psoc,struct tx_action_context * tx_ctx)1131 static uint8_t p2p_get_hw_retry_count(struct wlan_objmgr_psoc *psoc,
1132 struct tx_action_context *tx_ctx)
1133 {
1134 if (tx_ctx->frame_info.type != P2P_FRAME_MGMT)
1135 return 0;
1136
1137 if (tx_ctx->frame_info.sub_type != P2P_MGMT_ACTION)
1138 return 0;
1139
1140 switch (tx_ctx->frame_info.public_action_type) {
1141 case P2P_PUBLIC_ACTION_NEG_REQ:
1142 return wlan_mlme_get_mgmt_hw_tx_retry_count(
1143 psoc,
1144 CFG_GO_NEGOTIATION_REQ_FRAME_TYPE);
1145 case P2P_PUBLIC_ACTION_INVIT_REQ:
1146 return wlan_mlme_get_mgmt_hw_tx_retry_count(
1147 psoc,
1148 CFG_P2P_INVITATION_REQ_FRAME_TYPE);
1149 case P2P_PUBLIC_ACTION_PROV_DIS_REQ:
1150 return wlan_mlme_get_mgmt_hw_tx_retry_count(
1151 psoc,
1152 CFG_PROVISION_DISCOVERY_REQ_FRAME_TYPE);
1153 default:
1154 return 0;
1155 }
1156 }
1157
1158 #define GET_HW_RETRY_LIMIT(count) QDF_GET_BITS(count, 0, 4)
1159 #define GET_HW_RETRY_LIMIT_EXT(count) QDF_GET_BITS(count, 4, 3)
1160
1161 /**
1162 * p2p_mgmt_set_hw_retry_count() - Set mgmt hw tx retry count
1163 * @psoc: psoc object
1164 * @tx_ctx: tx context
1165 * @mgmt_param: mgmt frame tx parameter
1166 *
1167 * This function will set mgmt frame hw tx retry count to tx parameter
1168 *
1169 * Return: void
1170 */
1171 static void
p2p_mgmt_set_hw_retry_count(struct wlan_objmgr_psoc * psoc,struct tx_action_context * tx_ctx,struct wmi_mgmt_params * mgmt_param)1172 p2p_mgmt_set_hw_retry_count(struct wlan_objmgr_psoc *psoc,
1173 struct tx_action_context *tx_ctx,
1174 struct wmi_mgmt_params *mgmt_param)
1175 {
1176 uint8_t retry_count = p2p_get_hw_retry_count(psoc, tx_ctx);
1177
1178 mgmt_param->tx_param.retry_limit = GET_HW_RETRY_LIMIT(retry_count);
1179 mgmt_param->tx_param.retry_limit_ext =
1180 GET_HW_RETRY_LIMIT_EXT(retry_count);
1181 if (mgmt_param->tx_param.retry_limit ||
1182 mgmt_param->tx_param.retry_limit_ext)
1183 mgmt_param->tx_params_valid = true;
1184 }
1185
1186 /**
1187 * p2p_mgmt_tx() - call mgmt tx api
1188 * @tx_ctx: tx context
1189 * @buf_len: buffer length
1190 * @packet: pointer to qdf nbuf
1191 * @frame: pointer to qdf nbuf data
1192 *
1193 * This function call mgmt tx api to tx this action frame.
1194 *
1195 * Return: QDF_STATUS_SUCCESS - in case of success
1196 */
p2p_mgmt_tx(struct tx_action_context * tx_ctx,uint32_t buf_len,qdf_nbuf_t packet,uint8_t * frame)1197 static QDF_STATUS p2p_mgmt_tx(struct tx_action_context *tx_ctx,
1198 uint32_t buf_len, qdf_nbuf_t packet, uint8_t *frame)
1199 {
1200 QDF_STATUS status;
1201 mgmt_tx_download_comp_cb tx_comp_cb;
1202 mgmt_ota_comp_cb tx_ota_comp_cb;
1203 struct wlan_frame_hdr *wh;
1204 struct wlan_objmgr_peer *peer = NULL;
1205 struct wmi_mgmt_params mgmt_param = { 0 };
1206 struct wlan_objmgr_psoc *psoc;
1207 void *mac_addr;
1208 uint8_t pdev_id;
1209 struct wlan_objmgr_vdev *vdev;
1210 enum QDF_OPMODE opmode;
1211 bool mlo_link_agnostic;
1212
1213 psoc = tx_ctx->p2p_soc_obj->soc;
1214 mgmt_param.tx_frame = packet;
1215 mgmt_param.frm_len = buf_len;
1216 mgmt_param.vdev_id = tx_ctx->vdev_id;
1217 mgmt_param.pdata = frame;
1218 mgmt_param.chanfreq = tx_ctx->chan_freq;
1219 mgmt_param.qdf_ctx = wlan_psoc_get_qdf_dev(psoc);
1220 if (!(mgmt_param.qdf_ctx)) {
1221 p2p_err("qdf ctx is null");
1222 return QDF_STATUS_E_INVAL;
1223 }
1224 p2p_mgmt_set_hw_retry_count(psoc, tx_ctx, &mgmt_param);
1225
1226 wh = (struct wlan_frame_hdr *)frame;
1227 mac_addr = wh->i_addr1;
1228 pdev_id = wlan_get_pdev_id_from_vdev_id(psoc, tx_ctx->vdev_id,
1229 WLAN_P2P_ID);
1230 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, tx_ctx->vdev_id,
1231 WLAN_P2P_ID);
1232 if (!vdev) {
1233 p2p_err("VDEV null");
1234 return QDF_STATUS_E_INVAL;
1235 }
1236
1237 mlo_link_agnostic = wlan_get_mlo_link_agnostic_flag(vdev, mac_addr);
1238
1239 peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr, WLAN_P2P_ID);
1240 if (!peer) {
1241 mac_addr = wh->i_addr2;
1242 peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr,
1243 WLAN_P2P_ID);
1244 }
1245 if (!peer) {
1246 opmode = wlan_vdev_mlme_get_opmode(vdev);
1247 /*
1248 * For NAN iface, retrieves mac address from vdev
1249 * as it is self peer. Also, rand_mac_tx would be
1250 * false as tx channel is not available.
1251 */
1252 if (opmode == QDF_NAN_DISC_MODE || tx_ctx->rand_mac_tx) {
1253 mac_addr = wlan_vdev_mlme_get_mldaddr(vdev);
1254 /* for non-MLO case, mld address will zero */
1255 if (qdf_is_macaddr_zero(
1256 (struct qdf_mac_addr *)mac_addr))
1257 mac_addr = wlan_vdev_mlme_get_macaddr(vdev);
1258
1259 peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr,
1260 WLAN_P2P_ID);
1261 }
1262 }
1263 if (!peer) {
1264 p2p_err("no valid peer");
1265 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
1266 return QDF_STATUS_E_INVAL;
1267 }
1268
1269 if (tx_ctx->no_ack) {
1270 tx_comp_cb = tgt_p2p_mgmt_download_comp_cb;
1271 tx_ota_comp_cb = NULL;
1272 } else {
1273 tx_comp_cb = NULL;
1274 tx_ota_comp_cb = tgt_p2p_mgmt_ota_comp_cb;
1275 }
1276
1277 p2p_debug("length:%d, chanfreq:%d retry count:%d(%d, %d)",
1278 mgmt_param.frm_len, mgmt_param.chanfreq,
1279 (mgmt_param.tx_param.retry_limit_ext << 4) |
1280 mgmt_param.tx_param.retry_limit,
1281 mgmt_param.tx_param.retry_limit,
1282 mgmt_param.tx_param.retry_limit_ext);
1283
1284 tx_ctx->nbuf = packet;
1285
1286 if (mlo_is_mld_sta(vdev) && tx_ctx->frame_info.type == P2P_FRAME_MGMT &&
1287 tx_ctx->frame_info.sub_type == P2P_MGMT_ACTION &&
1288 mlo_link_agnostic) {
1289 mgmt_param.mlo_link_agnostic = true;
1290 }
1291 status = wlan_mgmt_txrx_mgmt_frame_tx(peer, tx_ctx->p2p_soc_obj,
1292 packet, tx_comp_cb, tx_ota_comp_cb,
1293 WLAN_UMAC_COMP_P2P, &mgmt_param);
1294
1295 wlan_objmgr_peer_release_ref(peer, WLAN_P2P_ID);
1296 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
1297
1298 return status;
1299 }
1300
1301 /**
1302 * p2p_roc_req_for_tx_action() - new a roc request for tx
1303 * @tx_ctx: tx context
1304 *
1305 * This function new a roc request for tx and call roc api to process
1306 * this new roc request.
1307 *
1308 * Return: QDF_STATUS_SUCCESS - in case of success
1309 */
p2p_roc_req_for_tx_action(struct tx_action_context * tx_ctx)1310 static QDF_STATUS p2p_roc_req_for_tx_action(
1311 struct tx_action_context *tx_ctx)
1312 {
1313 struct p2p_soc_priv_obj *p2p_soc_obj;
1314 struct p2p_roc_context *roc_ctx;
1315 QDF_STATUS status;
1316
1317 roc_ctx = qdf_mem_malloc(sizeof(struct p2p_roc_context));
1318 if (!roc_ctx)
1319 return QDF_STATUS_E_NOMEM;
1320
1321 p2p_soc_obj = tx_ctx->p2p_soc_obj;
1322 roc_ctx->p2p_soc_obj = p2p_soc_obj;
1323 roc_ctx->vdev_id = tx_ctx->vdev_id;
1324 roc_ctx->chan_freq = tx_ctx->chan_freq;
1325 roc_ctx->duration = tx_ctx->duration;
1326 roc_ctx->roc_state = ROC_STATE_IDLE;
1327 roc_ctx->roc_type = OFF_CHANNEL_TX;
1328 roc_ctx->tx_ctx = tx_ctx;
1329 roc_ctx->id = tx_ctx->id;
1330 tx_ctx->roc_cookie = (uintptr_t)roc_ctx;
1331
1332 p2p_debug("create roc request for off channel tx, tx ctx:%pK, roc ctx:%pK",
1333 tx_ctx, roc_ctx);
1334
1335 status = p2p_process_roc_req(roc_ctx);
1336 if (status != QDF_STATUS_SUCCESS) {
1337 p2p_err("request roc for tx action frrame fail");
1338 return status;
1339 }
1340
1341 status = qdf_list_insert_back(&p2p_soc_obj->tx_q_roc,
1342 &tx_ctx->node);
1343 if (status != QDF_STATUS_SUCCESS)
1344 p2p_err("Failed to insert off chan tx context to wait roc req queue");
1345
1346 return status;
1347 }
1348
1349 /**
1350 * p2p_find_tx_ctx() - find tx context by cookie
1351 * @p2p_soc_obj: p2p soc object
1352 * @cookie: cookie to this p2p tx context
1353 * @is_roc_q: it is in waiting for roc queue
1354 * @is_ack_q: it is in waiting for ack queue
1355 *
1356 * This function finds out tx context by cookie.
1357 *
1358 * Return: pointer to tx context
1359 */
p2p_find_tx_ctx(struct p2p_soc_priv_obj * p2p_soc_obj,uint64_t cookie,bool * is_roc_q,bool * is_ack_q)1360 static struct tx_action_context *p2p_find_tx_ctx(
1361 struct p2p_soc_priv_obj *p2p_soc_obj, uint64_t cookie,
1362 bool *is_roc_q, bool *is_ack_q)
1363 {
1364 struct tx_action_context *cur_tx_ctx;
1365 qdf_list_node_t *p_node;
1366 QDF_STATUS status;
1367 *is_roc_q = false;
1368 *is_ack_q = false;
1369
1370 p2p_debug("Start to find tx ctx, p2p soc_obj:%pK, cookie:%llx",
1371 p2p_soc_obj, cookie);
1372
1373 status = qdf_list_peek_front(&p2p_soc_obj->tx_q_roc, &p_node);
1374 while (QDF_IS_STATUS_SUCCESS(status)) {
1375 cur_tx_ctx = qdf_container_of(p_node,
1376 struct tx_action_context, node);
1377 if ((uintptr_t) cur_tx_ctx == cookie) {
1378 *is_roc_q = true;
1379 p2p_debug("find tx ctx, cookie:%llx", cookie);
1380 return cur_tx_ctx;
1381 }
1382 status = qdf_list_peek_next(&p2p_soc_obj->tx_q_roc,
1383 p_node, &p_node);
1384 }
1385
1386 status = qdf_list_peek_front(&p2p_soc_obj->tx_q_ack, &p_node);
1387 while (QDF_IS_STATUS_SUCCESS(status)) {
1388 cur_tx_ctx = qdf_container_of(p_node,
1389 struct tx_action_context, node);
1390 if ((uintptr_t) cur_tx_ctx == cookie) {
1391 *is_ack_q = true;
1392 p2p_debug("find tx ctx, cookie:%llx", cookie);
1393 return cur_tx_ctx;
1394 }
1395 status = qdf_list_peek_next(&p2p_soc_obj->tx_q_ack,
1396 p_node, &p_node);
1397 }
1398
1399 return NULL;
1400 }
1401
1402 /**
1403 * p2p_find_tx_ctx_by_roc() - find tx context by roc
1404 * @p2p_soc_obj: p2p soc object
1405 * @cookie: cookie to roc context
1406 *
1407 * This function finds out tx context by roc context.
1408 *
1409 * Return: pointer to tx context
1410 */
p2p_find_tx_ctx_by_roc(struct p2p_soc_priv_obj * p2p_soc_obj,uint64_t cookie)1411 static struct tx_action_context *p2p_find_tx_ctx_by_roc(
1412 struct p2p_soc_priv_obj *p2p_soc_obj, uint64_t cookie)
1413 {
1414 struct tx_action_context *cur_tx_ctx;
1415 qdf_list_node_t *p_node;
1416 QDF_STATUS status;
1417
1418 p2p_debug("Start to find tx ctx, p2p soc_obj:%pK, cookie:%llx",
1419 p2p_soc_obj, cookie);
1420
1421 status = qdf_list_peek_front(&p2p_soc_obj->tx_q_roc, &p_node);
1422 while (QDF_IS_STATUS_SUCCESS(status)) {
1423 cur_tx_ctx = qdf_container_of(p_node,
1424 struct tx_action_context, node);
1425 if (cur_tx_ctx->roc_cookie == cookie) {
1426 p2p_debug("find tx ctx, cookie:%llx", cookie);
1427 return cur_tx_ctx;
1428 }
1429 status = qdf_list_peek_next(&p2p_soc_obj->tx_q_roc,
1430 p_node, &p_node);
1431 }
1432
1433 return NULL;
1434 }
1435
1436 /**
1437 * p2p_move_tx_context_to_ack_queue() - move tx context to tx_q_ack
1438 * @tx_ctx: tx context
1439 *
1440 * This function moves tx context to waiting for ack queue.
1441 *
1442 * Return: QDF_STATUS_SUCCESS - in case of success
1443 */
p2p_move_tx_context_to_ack_queue(struct tx_action_context * tx_ctx)1444 static QDF_STATUS p2p_move_tx_context_to_ack_queue(
1445 struct tx_action_context *tx_ctx)
1446 {
1447 bool is_roc_q = false;
1448 bool is_ack_q = false;
1449 struct p2p_soc_priv_obj *p2p_soc_obj = tx_ctx->p2p_soc_obj;
1450 struct tx_action_context *cur_tx_ctx;
1451 QDF_STATUS status;
1452
1453 cur_tx_ctx = p2p_find_tx_ctx(p2p_soc_obj, (uintptr_t)tx_ctx,
1454 &is_roc_q, &is_ack_q);
1455 if (cur_tx_ctx) {
1456 if (is_roc_q) {
1457 p2p_debug("find in wait for roc queue");
1458 status = qdf_list_remove_node(
1459 &p2p_soc_obj->tx_q_roc,
1460 (qdf_list_node_t *)tx_ctx);
1461 if (status != QDF_STATUS_SUCCESS)
1462 p2p_err("Failed to remove off chan tx context from wait roc req queue");
1463 }
1464
1465 if (is_ack_q) {
1466 p2p_debug("Already in waiting for ack queue");
1467 return QDF_STATUS_SUCCESS;
1468 }
1469 }
1470
1471 status = qdf_list_insert_back(
1472 &p2p_soc_obj->tx_q_ack,
1473 &tx_ctx->node);
1474 if (status != QDF_STATUS_SUCCESS)
1475 p2p_err("Failed to insert off chan tx context to wait ack req queue");
1476
1477 return status;
1478 }
1479
1480 /**
1481 * p2p_extend_roc_timer() - extend roc timer
1482 * @p2p_soc_obj: p2p soc private object
1483 * @frame_info: pointer to frame information
1484 *
1485 * This function extends roc timer for some of p2p public action frame.
1486 *
1487 * Return: QDF_STATUS_SUCCESS - in case of success
1488 */
p2p_extend_roc_timer(struct p2p_soc_priv_obj * p2p_soc_obj,struct p2p_frame_info * frame_info)1489 static QDF_STATUS p2p_extend_roc_timer(
1490 struct p2p_soc_priv_obj *p2p_soc_obj,
1491 struct p2p_frame_info *frame_info)
1492 {
1493 struct p2p_roc_context *curr_roc_ctx;
1494 uint32_t extend_time;
1495
1496 curr_roc_ctx = p2p_find_current_roc_ctx(p2p_soc_obj);
1497 if (!curr_roc_ctx) {
1498 p2p_debug("no running roc request currently");
1499 return QDF_STATUS_SUCCESS;
1500 }
1501
1502 if (!frame_info) {
1503 p2p_err("invalid frame information");
1504 return QDF_STATUS_E_INVAL;
1505 }
1506
1507 switch (frame_info->public_action_type) {
1508 case P2P_PUBLIC_ACTION_NEG_REQ:
1509 case P2P_PUBLIC_ACTION_NEG_RSP:
1510 extend_time = 2 * P2P_ACTION_FRAME_DEFAULT_WAIT;
1511 break;
1512 case P2P_PUBLIC_ACTION_INVIT_REQ:
1513 case P2P_PUBLIC_ACTION_DEV_DIS_REQ:
1514 extend_time = P2P_ACTION_FRAME_DEFAULT_WAIT;
1515 break;
1516 default:
1517 extend_time = 0;
1518 break;
1519 }
1520
1521 if (extend_time) {
1522 p2p_debug("extend roc timer, duration:%d", extend_time);
1523 curr_roc_ctx->duration = extend_time;
1524 return p2p_restart_roc_timer(curr_roc_ctx);
1525 }
1526
1527 return QDF_STATUS_SUCCESS;
1528 }
1529
1530 /**
1531 * p2p_adjust_tx_wait() - adjust tx wait
1532 * @tx_ctx: tx context
1533 *
1534 * This function adjust wait time of this tx context
1535 *
1536 * Return: None
1537 */
p2p_adjust_tx_wait(struct tx_action_context * tx_ctx)1538 static void p2p_adjust_tx_wait(struct tx_action_context *tx_ctx)
1539 {
1540 struct p2p_frame_info *frame_info;
1541
1542 frame_info = &(tx_ctx->frame_info);
1543 switch (frame_info->public_action_type) {
1544 case P2P_PUBLIC_ACTION_NEG_RSP:
1545 case P2P_PUBLIC_ACTION_PROV_DIS_RSP:
1546 tx_ctx->duration += P2P_ACTION_FRAME_RSP_WAIT;
1547 break;
1548 case P2P_PUBLIC_ACTION_NEG_CNF:
1549 case P2P_PUBLIC_ACTION_INVIT_RSP:
1550 tx_ctx->duration += P2P_ACTION_FRAME_ACK_WAIT;
1551 break;
1552 default:
1553 break;
1554 }
1555 }
1556
1557 /**
1558 * p2p_remove_tx_context() - remove tx ctx from queue
1559 * @tx_ctx: tx context
1560 *
1561 * This function remove tx context from waiting for roc queue or
1562 * waiting for ack queue.
1563 *
1564 * Return: QDF_STATUS_SUCCESS - in case of success
1565 */
p2p_remove_tx_context(struct tx_action_context * tx_ctx)1566 static QDF_STATUS p2p_remove_tx_context(
1567 struct tx_action_context *tx_ctx)
1568 {
1569 bool is_roc_q = false;
1570 bool is_ack_q = false;
1571 struct tx_action_context *cur_tx_ctx;
1572 uint64_t cookie = (uintptr_t)tx_ctx;
1573 struct p2p_soc_priv_obj *p2p_soc_obj = tx_ctx->p2p_soc_obj;
1574 QDF_STATUS status = QDF_STATUS_E_FAILURE;
1575
1576 p2p_debug("tx context:%pK", tx_ctx);
1577
1578 cur_tx_ctx = p2p_find_tx_ctx(p2p_soc_obj, cookie, &is_roc_q,
1579 &is_ack_q);
1580
1581 /* for not off channel tx case, won't find from queue */
1582 if (!cur_tx_ctx) {
1583 p2p_debug("Do not find tx context from queue");
1584 goto end;
1585 }
1586
1587 if (is_roc_q) {
1588 status = qdf_list_remove_node(
1589 &p2p_soc_obj->tx_q_roc,
1590 (qdf_list_node_t *)cur_tx_ctx);
1591 if (status != QDF_STATUS_SUCCESS)
1592 p2p_err("Failed to tx context from wait roc req queue");
1593 }
1594
1595 if (is_ack_q) {
1596 status = qdf_list_remove_node(
1597 &p2p_soc_obj->tx_q_ack,
1598 (qdf_list_node_t *)cur_tx_ctx);
1599 if (status != QDF_STATUS_SUCCESS)
1600 p2p_err("Failed to tx context from wait ack req queue");
1601 }
1602
1603 end:
1604 if (!tx_ctx->roc_cookie)
1605 qdf_idr_remove(&p2p_soc_obj->p2p_idr, tx_ctx->id);
1606 qdf_mem_free(tx_ctx->buf);
1607 qdf_mem_free(tx_ctx);
1608
1609 return status;
1610 }
1611
1612 /**
1613 * p2p_tx_timeout() - Callback for tx timeout
1614 * @pdata: pointer to tx context
1615 *
1616 * This function is callback for tx time out.
1617 *
1618 * Return: None
1619 */
p2p_tx_timeout(void * pdata)1620 static void p2p_tx_timeout(void *pdata)
1621 {
1622 QDF_STATUS status, ret;
1623 qdf_list_node_t *p_node;
1624 struct tx_action_context *tx_ctx;
1625 struct p2p_soc_priv_obj *p2p_soc_obj;
1626
1627 p2p_info("pdata:%pK", pdata);
1628 p2p_soc_obj = (struct p2p_soc_priv_obj *)pdata;
1629 if (!p2p_soc_obj) {
1630 p2p_err("null p2p soc obj");
1631 return;
1632 }
1633
1634 status = qdf_list_peek_front(&p2p_soc_obj->tx_q_ack, &p_node);
1635 while (QDF_IS_STATUS_SUCCESS(status)) {
1636 tx_ctx = qdf_container_of(p_node,
1637 struct tx_action_context, node);
1638 status = qdf_list_peek_next(&p2p_soc_obj->tx_q_ack,
1639 p_node, &p_node);
1640 if (QDF_TIMER_STATE_STOPPED ==
1641 qdf_mc_timer_get_current_state(&tx_ctx->tx_timer)) {
1642 ret = qdf_list_remove_node(&p2p_soc_obj->tx_q_ack,
1643 &tx_ctx->node);
1644 if (ret == QDF_STATUS_SUCCESS) {
1645 qdf_mc_timer_destroy(&tx_ctx->tx_timer);
1646 p2p_send_tx_conf(tx_ctx, false);
1647 qdf_mem_free(tx_ctx->buf);
1648 qdf_mem_free(tx_ctx);
1649 } else
1650 p2p_err("remove %pK from roc_q fail",
1651 tx_ctx);
1652 }
1653 }
1654 }
1655
1656 /**
1657 * p2p_enable_tx_timer() - enable tx timer
1658 * @tx_ctx: tx context
1659 *
1660 * This function enable tx timer for action frame required ota tx.
1661 *
1662 * Return: QDF_STATUS_SUCCESS - in case of success
1663 */
p2p_enable_tx_timer(struct tx_action_context * tx_ctx)1664 static QDF_STATUS p2p_enable_tx_timer(struct tx_action_context *tx_ctx)
1665 {
1666 QDF_STATUS status;
1667
1668 status = qdf_mc_timer_init(&tx_ctx->tx_timer,
1669 QDF_TIMER_TYPE_SW, p2p_tx_timeout,
1670 tx_ctx->p2p_soc_obj);
1671 if (status != QDF_STATUS_SUCCESS) {
1672 p2p_err("failed to init tx timer tx_ctx:%pK", tx_ctx);
1673 return status;
1674 }
1675
1676 status = qdf_mc_timer_start(&tx_ctx->tx_timer,
1677 P2P_ACTION_FRAME_TX_TIMEOUT);
1678 if (status != QDF_STATUS_SUCCESS)
1679 p2p_err("tx timer start failed tx_ctx:%pK", tx_ctx);
1680
1681 return status;
1682 }
1683
1684 /**
1685 * p2p_disable_tx_timer() - disable tx timer
1686 * @tx_ctx: tx context
1687 *
1688 * This function disable tx timer for action frame required ota tx.
1689 *
1690 * Return: QDF_STATUS_SUCCESS - in case of success
1691 */
p2p_disable_tx_timer(struct tx_action_context * tx_ctx)1692 static QDF_STATUS p2p_disable_tx_timer(struct tx_action_context *tx_ctx)
1693 {
1694 QDF_STATUS status;
1695
1696 p2p_debug("tx context:%pK", tx_ctx);
1697
1698 status = qdf_mc_timer_stop(&tx_ctx->tx_timer);
1699 if (status != QDF_STATUS_SUCCESS)
1700 p2p_err("Failed to stop tx timer, status:%d", status);
1701
1702 status = qdf_mc_timer_destroy(&tx_ctx->tx_timer);
1703 if (status != QDF_STATUS_SUCCESS)
1704 p2p_err("Failed to destroy tx timer, status:%d", status);
1705
1706 return status;
1707 }
1708
1709 /**
1710 * p2p_populate_rmf_field() - populate unicast rmf frame
1711 * @tx_ctx: tx_action_context
1712 * @size: input size of frame, and output new size
1713 * @ppbuf: input frame ptr, and output new frame
1714 * @ppkt: input pkt, output new pkt.
1715 *
1716 * This function allocates new pkt for rmf frame. The
1717 * new frame has extra space for ccmp field.
1718 *
1719 * Return: QDF_STATUS_SUCCESS - in case of success
1720 */
p2p_populate_rmf_field(struct tx_action_context * tx_ctx,uint32_t * size,uint8_t ** ppbuf,qdf_nbuf_t * ppkt)1721 static QDF_STATUS p2p_populate_rmf_field(struct tx_action_context *tx_ctx,
1722 uint32_t *size, uint8_t **ppbuf, qdf_nbuf_t *ppkt)
1723 {
1724 struct wlan_frame_hdr *wh, *rmf_wh;
1725 struct action_frm_hdr *action_hdr;
1726 QDF_STATUS status = QDF_STATUS_SUCCESS;
1727 qdf_nbuf_t pkt = NULL;
1728 uint8_t *frame;
1729 uint32_t frame_len;
1730 struct p2p_soc_priv_obj *p2p_soc_obj;
1731 uint8_t action_category;
1732
1733 p2p_soc_obj = tx_ctx->p2p_soc_obj;
1734
1735 if (tx_ctx->frame_info.sub_type != P2P_MGMT_ACTION ||
1736 !p2p_soc_obj->p2p_cb.is_mgmt_protected)
1737 return QDF_STATUS_SUCCESS;
1738 if (*size < (sizeof(struct wlan_frame_hdr) +
1739 sizeof(struct action_frm_hdr))) {
1740 return QDF_STATUS_E_INVAL;
1741 }
1742
1743 wh = (struct wlan_frame_hdr *)(*ppbuf);
1744 action_hdr = (struct action_frm_hdr *)(*ppbuf + sizeof(*wh));
1745
1746 /*
1747 * For Action frame which are not handled, the resp is sent back to the
1748 * source without change, except that MSB of the Category set to 1, so
1749 * to get the actual action category we need to ignore the MSB.
1750 */
1751 action_category = action_hdr->action_category & 0x7f;
1752 if (!wlan_mgmt_is_rmf_mgmt_action_frame(action_category)) {
1753 p2p_debug("non rmf act frame 0x%x category %x",
1754 tx_ctx->frame_info.sub_type,
1755 action_hdr->action_category);
1756 return QDF_STATUS_SUCCESS;
1757 }
1758
1759 if (!p2p_soc_obj->p2p_cb.is_mgmt_protected(
1760 tx_ctx->vdev_id, wh->i_addr1)) {
1761 p2p_debug("non rmf connection vdev %d "QDF_MAC_ADDR_FMT,
1762 tx_ctx->vdev_id, QDF_MAC_ADDR_REF(wh->i_addr1));
1763 return QDF_STATUS_SUCCESS;
1764 }
1765 if (!qdf_is_macaddr_group((struct qdf_mac_addr *)wh->i_addr1) &&
1766 !qdf_is_macaddr_broadcast((struct qdf_mac_addr *)wh->i_addr1)) {
1767 uint8_t mic_len, mic_hdr_len, pdev_id;
1768
1769 pdev_id =
1770 wlan_get_pdev_id_from_vdev_id(tx_ctx->p2p_soc_obj->soc,
1771 tx_ctx->vdev_id,
1772 WLAN_P2P_ID);
1773 status = mlme_get_peer_mic_len(p2p_soc_obj->soc, pdev_id,
1774 wh->i_addr1, &mic_len,
1775 &mic_hdr_len);
1776 if (QDF_IS_STATUS_ERROR(status)) {
1777 p2p_err("Failed to get peer mic length.");
1778 return status;
1779 }
1780
1781 frame_len = *size + mic_hdr_len + mic_len;
1782 status = p2p_packet_alloc((uint16_t)frame_len, (void **)&frame,
1783 &pkt);
1784 if (status != QDF_STATUS_SUCCESS) {
1785 p2p_err("Failed to allocate %d bytes for rmf frame.",
1786 frame_len);
1787 return QDF_STATUS_E_NOMEM;
1788 }
1789
1790 qdf_mem_copy(frame, wh, sizeof(*wh));
1791 qdf_mem_copy(frame + sizeof(*wh) + mic_hdr_len,
1792 *ppbuf + sizeof(*wh),
1793 *size - sizeof(*wh));
1794 rmf_wh = (struct wlan_frame_hdr *)frame;
1795 (rmf_wh)->i_fc[1] |= IEEE80211_FC1_WEP;
1796 p2p_debug("set protection 0x%x cat %d "QDF_MAC_ADDR_FMT,
1797 tx_ctx->frame_info.sub_type,
1798 action_hdr->action_category,
1799 QDF_MAC_ADDR_REF(wh->i_addr1));
1800
1801 qdf_nbuf_free(*ppkt);
1802 *ppbuf = frame;
1803 *ppkt = pkt;
1804 *size = frame_len;
1805 /*
1806 * Some target which support sending mgmt frame based on htt
1807 * would DMA write this PMF tx frame buffer, it may cause smmu
1808 * check permission fault, set a flag to do bi-direction DMA
1809 * map, normal tx unmap is enough for this case.
1810 */
1811 QDF_NBUF_CB_TX_DMA_BI_MAP(pkt) = 1;
1812 }
1813
1814 return status;
1815 }
1816
1817 /**
1818 * p2p_execute_tx_action_frame() - execute tx action frame
1819 * @tx_ctx: tx context
1820 *
1821 * This function modify p2p ie and tx this action frame.
1822 *
1823 * Return: QDF_STATUS_SUCCESS - in case of success
1824 */
p2p_execute_tx_action_frame(struct tx_action_context * tx_ctx)1825 static QDF_STATUS p2p_execute_tx_action_frame(
1826 struct tx_action_context *tx_ctx)
1827 {
1828 uint8_t *frame;
1829 qdf_nbuf_t packet;
1830 QDF_STATUS status;
1831 uint8_t noa_len = 0;
1832 uint8_t noa_stream[P2P_NOA_STREAM_ARR_SIZE];
1833 uint8_t orig_len = 0;
1834 const uint8_t *ie;
1835 uint8_t ie_len;
1836 uint8_t *p2p_ie = NULL;
1837 const uint8_t *presence_noa_attr = NULL;
1838 uint32_t nbytes_copy;
1839 uint32_t buf_len = tx_ctx->buf_len;
1840 struct p2p_frame_info *frame_info;
1841 struct wlan_objmgr_vdev *vdev;
1842
1843 frame_info = &(tx_ctx->frame_info);
1844 if (frame_info->sub_type == P2P_MGMT_PROBE_RSP) {
1845 p2p_ie = (uint8_t *)p2p_get_p2pie_from_probe_rsp(tx_ctx);
1846 } else if (frame_info->action_type ==
1847 P2P_ACTION_PRESENCE_RSP) {
1848 ie = tx_ctx->buf +
1849 P2P_PUBLIC_ACTION_FRAME_TYPE_OFFSET;
1850 ie_len = tx_ctx->buf_len -
1851 P2P_PUBLIC_ACTION_FRAME_TYPE_OFFSET;
1852 p2p_ie = (uint8_t *)p2p_get_p2pie_ptr(ie, ie_len);
1853 if (p2p_ie) {
1854 /* extract the presence of NoA attribute inside
1855 * P2P IE */
1856 ie = p2p_ie + P2P_IE_HEADER_LEN;
1857 ie_len = p2p_ie[1];
1858 presence_noa_attr = p2p_get_presence_noa_attr(
1859 ie, ie_len);
1860 }
1861 } else if (frame_info->type == P2P_FRAME_MGMT &&
1862 frame_info->sub_type == P2P_MGMT_ACTION) {
1863 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
1864 tx_ctx->p2p_soc_obj->soc, tx_ctx->vdev_id,
1865 WLAN_P2P_ID);
1866
1867 if (vdev) {
1868 wlan_mlo_update_action_frame_from_user(vdev,
1869 tx_ctx->buf,
1870 tx_ctx->buf_len);
1871 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
1872 }
1873 }
1874
1875 if ((frame_info->sub_type != P2P_MGMT_NOT_SUPPORT) &&
1876 p2p_ie) {
1877 orig_len = p2p_ie[1];
1878 noa_len = p2p_update_noa_stream(tx_ctx, p2p_ie,
1879 presence_noa_attr, &buf_len,
1880 noa_stream);
1881 buf_len += noa_len;
1882 }
1883
1884 if (frame_info->sub_type == P2P_MGMT_PROBE_RSP)
1885 p2p_set_ht_caps(tx_ctx, buf_len);
1886
1887 /* Ok-- try to allocate some memory: */
1888 status = p2p_packet_alloc((uint16_t) buf_len, (void **)&frame,
1889 &packet);
1890 if (status != QDF_STATUS_SUCCESS) {
1891 p2p_err("Failed to allocate %d bytes for a Probe Request.",
1892 buf_len);
1893 return status;
1894 }
1895
1896 /*
1897 * Add sequence number to action frames
1898 * Frames are handed over in .11 format by supplicant already
1899 */
1900 p2p_populate_mac_header(tx_ctx);
1901
1902 if ((noa_len > 0) && p2p_ie
1903 && (noa_len < (P2P_MAX_NOA_ATTR_LEN +
1904 P2P_IE_HEADER_LEN))) {
1905 /* Add 2 bytes for length and Arribute field */
1906 nbytes_copy = (p2p_ie + orig_len + 2) - tx_ctx->buf;
1907 qdf_mem_copy(frame, tx_ctx->buf, nbytes_copy);
1908 qdf_mem_copy((frame + nbytes_copy), noa_stream,
1909 noa_len);
1910 qdf_mem_copy((frame + nbytes_copy + noa_len),
1911 tx_ctx->buf + nbytes_copy,
1912 buf_len - nbytes_copy - noa_len);
1913 } else {
1914 qdf_mem_copy(frame, tx_ctx->buf, buf_len);
1915 }
1916
1917 status = p2p_populate_rmf_field(tx_ctx, &buf_len, &frame, &packet);
1918 if (status != QDF_STATUS_SUCCESS) {
1919 p2p_err("failed to populate rmf frame");
1920 qdf_nbuf_free(packet);
1921 return status;
1922 }
1923
1924 status = p2p_mgmt_tx(tx_ctx, buf_len, packet, frame);
1925 if (status == QDF_STATUS_SUCCESS) {
1926 if (tx_ctx->no_ack) {
1927 p2p_send_tx_conf(tx_ctx, true);
1928 p2p_remove_tx_context(tx_ctx);
1929 } else {
1930 p2p_enable_tx_timer(tx_ctx);
1931 p2p_move_tx_context_to_ack_queue(tx_ctx);
1932 }
1933 } else {
1934 p2p_err("failed to tx mgmt frame");
1935 qdf_nbuf_free(packet);
1936 }
1937
1938 return status;
1939 }
1940
p2p_find_tx_ctx_by_nbuf(struct p2p_soc_priv_obj * p2p_soc_obj,void * nbuf)1941 struct tx_action_context *p2p_find_tx_ctx_by_nbuf(
1942 struct p2p_soc_priv_obj *p2p_soc_obj, void *nbuf)
1943 {
1944 struct tx_action_context *cur_tx_ctx;
1945 qdf_list_node_t *p_node;
1946 QDF_STATUS status;
1947
1948 if (!p2p_soc_obj) {
1949 p2p_err("invalid p2p soc object");
1950 return NULL;
1951 }
1952
1953 status = qdf_list_peek_front(&p2p_soc_obj->tx_q_ack, &p_node);
1954 while (QDF_IS_STATUS_SUCCESS(status)) {
1955 cur_tx_ctx =
1956 qdf_container_of(p_node, struct tx_action_context, node);
1957 if (cur_tx_ctx->nbuf == nbuf) {
1958 p2p_debug("find tx ctx, nbuf:%pK", nbuf);
1959 return cur_tx_ctx;
1960 }
1961 status = qdf_list_peek_next(&p2p_soc_obj->tx_q_ack,
1962 p_node, &p_node);
1963 }
1964
1965 return NULL;
1966 }
1967
p2p_dump_tx_queue(struct p2p_soc_priv_obj * p2p_soc_obj)1968 void p2p_dump_tx_queue(struct p2p_soc_priv_obj *p2p_soc_obj)
1969 {
1970 struct tx_action_context *tx_ctx;
1971 qdf_list_node_t *p_node;
1972 QDF_STATUS status;
1973
1974 p2p_debug("dump tx queue wait for roc, p2p soc obj:%pK, size:%d",
1975 p2p_soc_obj, qdf_list_size(&p2p_soc_obj->tx_q_roc));
1976
1977 status = qdf_list_peek_front(&p2p_soc_obj->tx_q_roc, &p_node);
1978 while (QDF_IS_STATUS_SUCCESS(status)) {
1979 tx_ctx = qdf_container_of(p_node,
1980 struct tx_action_context, node);
1981 p2p_debug("p2p soc object:%pK, tx ctx:%pK, vdev_id:%d, "
1982 "scan_id:%d, roc_cookie:%llx, freq:%d, buf:%pK, "
1983 "len:%d, off_chan:%d, cck:%d, ack:%d, duration:%d",
1984 p2p_soc_obj, tx_ctx,
1985 tx_ctx->vdev_id, tx_ctx->scan_id,
1986 tx_ctx->roc_cookie, tx_ctx->chan_freq,
1987 tx_ctx->buf, tx_ctx->buf_len,
1988 tx_ctx->off_chan, tx_ctx->no_cck,
1989 tx_ctx->no_ack, tx_ctx->duration);
1990
1991 status = qdf_list_peek_next(&p2p_soc_obj->tx_q_roc,
1992 p_node, &p_node);
1993 }
1994
1995 p2p_debug("dump tx queue wait for ack, size:%d",
1996 qdf_list_size(&p2p_soc_obj->tx_q_ack));
1997 status = qdf_list_peek_front(&p2p_soc_obj->tx_q_ack, &p_node);
1998 while (QDF_IS_STATUS_SUCCESS(status)) {
1999 tx_ctx = qdf_container_of(p_node,
2000 struct tx_action_context, node);
2001 p2p_debug("p2p soc object:%pK, tx_ctx:%pK, vdev_id:%d, "
2002 "scan_id:%d, roc_cookie:%llx, freq:%d, buf:%pK, "
2003 "len:%d, off_chan:%d, cck:%d, ack:%d, duration:%d",
2004 p2p_soc_obj, tx_ctx,
2005 tx_ctx->vdev_id, tx_ctx->scan_id,
2006 tx_ctx->roc_cookie, tx_ctx->chan_freq,
2007 tx_ctx->buf, tx_ctx->buf_len,
2008 tx_ctx->off_chan, tx_ctx->no_cck,
2009 tx_ctx->no_ack, tx_ctx->duration);
2010
2011 status = qdf_list_peek_next(&p2p_soc_obj->tx_q_ack,
2012 p_node, &p_node);
2013 }
2014 }
2015
p2p_ready_to_tx_frame(struct p2p_soc_priv_obj * p2p_soc_obj,uint64_t cookie)2016 QDF_STATUS p2p_ready_to_tx_frame(struct p2p_soc_priv_obj *p2p_soc_obj,
2017 uint64_t cookie)
2018 {
2019 struct tx_action_context *cur_tx_ctx;
2020 QDF_STATUS status = QDF_STATUS_SUCCESS;
2021
2022 cur_tx_ctx = p2p_find_tx_ctx_by_roc(p2p_soc_obj, cookie);
2023
2024 while (cur_tx_ctx) {
2025 p2p_debug("tx_ctx:%pK", cur_tx_ctx);
2026 status = p2p_execute_tx_action_frame(cur_tx_ctx);
2027 if (status != QDF_STATUS_SUCCESS) {
2028 p2p_send_tx_conf(cur_tx_ctx, false);
2029 p2p_remove_tx_context(cur_tx_ctx);
2030 }
2031 cur_tx_ctx = p2p_find_tx_ctx_by_roc(p2p_soc_obj, cookie);
2032 }
2033
2034 return status;
2035 }
2036
p2p_cleanup_tx_sync(struct p2p_soc_priv_obj * p2p_soc_obj,struct wlan_objmgr_vdev * vdev)2037 QDF_STATUS p2p_cleanup_tx_sync(
2038 struct p2p_soc_priv_obj *p2p_soc_obj,
2039 struct wlan_objmgr_vdev *vdev)
2040 {
2041 struct scheduler_msg msg = {0};
2042 struct p2p_cleanup_param *param;
2043 QDF_STATUS status;
2044 uint32_t vdev_id;
2045
2046 if (!p2p_soc_obj) {
2047 p2p_err("p2p soc context is NULL");
2048 return QDF_STATUS_E_FAILURE;
2049 }
2050
2051 p2p_debug("p2p_soc_obj:%pK, vdev:%pK", p2p_soc_obj, vdev);
2052 param = qdf_mem_malloc(sizeof(*param));
2053 if (!param)
2054 return QDF_STATUS_E_NOMEM;
2055
2056 param->p2p_soc_obj = p2p_soc_obj;
2057 if (vdev)
2058 vdev_id = (uint32_t)wlan_vdev_get_id(vdev);
2059 else
2060 vdev_id = P2P_INVALID_VDEV_ID;
2061 param->vdev_id = vdev_id;
2062 qdf_event_reset(&p2p_soc_obj->cleanup_tx_done);
2063 msg.type = P2P_CLEANUP_TX;
2064 msg.bodyptr = param;
2065 msg.callback = p2p_process_cmd;
2066 status = scheduler_post_message(QDF_MODULE_ID_P2P,
2067 QDF_MODULE_ID_P2P,
2068 QDF_MODULE_ID_OS_IF, &msg);
2069 if (status != QDF_STATUS_SUCCESS) {
2070 qdf_mem_free(param);
2071 return status;
2072 }
2073
2074 status = qdf_wait_single_event(
2075 &p2p_soc_obj->cleanup_tx_done,
2076 P2P_WAIT_CLEANUP_ROC);
2077
2078 if (status != QDF_STATUS_SUCCESS)
2079 p2p_err("wait for cleanup tx timeout, %d", status);
2080
2081 return status;
2082 }
2083
p2p_process_cleanup_tx_queue(struct p2p_cleanup_param * param)2084 QDF_STATUS p2p_process_cleanup_tx_queue(struct p2p_cleanup_param *param)
2085 {
2086 struct tx_action_context *curr_tx_ctx;
2087 qdf_list_node_t *p_node;
2088 struct p2p_soc_priv_obj *p2p_soc_obj;
2089 uint32_t vdev_id;
2090 QDF_STATUS status, ret;
2091
2092 if (!param || !(param->p2p_soc_obj)) {
2093 p2p_err("Invalid cleanup param");
2094 return QDF_STATUS_E_FAILURE;
2095 }
2096
2097 p2p_soc_obj = param->p2p_soc_obj;
2098 vdev_id = param->vdev_id;
2099
2100 p2p_debug("clean up tx queue wait for roc, size:%d, vdev_id:%d",
2101 qdf_list_size(&p2p_soc_obj->tx_q_roc), vdev_id);
2102
2103 status = qdf_list_peek_front(&p2p_soc_obj->tx_q_roc, &p_node);
2104 while (QDF_IS_STATUS_SUCCESS(status)) {
2105 curr_tx_ctx = qdf_container_of(p_node,
2106 struct tx_action_context, node);
2107 status = qdf_list_peek_next(&p2p_soc_obj->tx_q_roc,
2108 p_node, &p_node);
2109 if ((vdev_id == P2P_INVALID_VDEV_ID) ||
2110 (vdev_id == curr_tx_ctx->vdev_id)) {
2111 ret = qdf_list_remove_node(&p2p_soc_obj->tx_q_roc,
2112 &curr_tx_ctx->node);
2113 if (ret == QDF_STATUS_SUCCESS) {
2114 p2p_send_tx_conf(curr_tx_ctx, false);
2115 qdf_mem_free(curr_tx_ctx->buf);
2116 qdf_mem_free(curr_tx_ctx);
2117 } else
2118 p2p_err("remove %pK from roc_q fail",
2119 curr_tx_ctx);
2120 }
2121 }
2122
2123 p2p_debug("clean up tx queue wait for ack, size:%d",
2124 qdf_list_size(&p2p_soc_obj->tx_q_ack));
2125
2126 status = qdf_list_peek_front(&p2p_soc_obj->tx_q_ack, &p_node);
2127 while (QDF_IS_STATUS_SUCCESS(status)) {
2128 curr_tx_ctx = qdf_container_of(p_node,
2129 struct tx_action_context, node);
2130 status = qdf_list_peek_next(&p2p_soc_obj->tx_q_ack,
2131 p_node, &p_node);
2132 if ((vdev_id == P2P_INVALID_VDEV_ID) ||
2133 (vdev_id == curr_tx_ctx->vdev_id)) {
2134 ret = qdf_list_remove_node(&p2p_soc_obj->tx_q_ack,
2135 &curr_tx_ctx->node);
2136 if (ret == QDF_STATUS_SUCCESS) {
2137 p2p_disable_tx_timer(curr_tx_ctx);
2138 p2p_send_tx_conf(curr_tx_ctx, false);
2139 qdf_mem_free(curr_tx_ctx->buf);
2140 qdf_mem_free(curr_tx_ctx);
2141 } else
2142 p2p_err("remove %pK from roc_q fail",
2143 curr_tx_ctx);
2144 }
2145 }
2146
2147 qdf_event_set(&p2p_soc_obj->cleanup_tx_done);
2148
2149 return QDF_STATUS_SUCCESS;
2150 }
2151
p2p_check_random_mac(struct wlan_objmgr_psoc * soc,uint32_t vdev_id,uint8_t * random_mac_addr)2152 bool p2p_check_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
2153 uint8_t *random_mac_addr)
2154 {
2155 uint32_t i = 0;
2156 struct p2p_vdev_priv_obj *p2p_vdev_obj;
2157 struct wlan_objmgr_vdev *vdev;
2158
2159 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(soc, vdev_id, WLAN_P2P_ID);
2160 if (!vdev) {
2161 p2p_debug("vdev is null");
2162 return false;
2163 }
2164
2165 p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(
2166 vdev, WLAN_UMAC_COMP_P2P);
2167 if (!p2p_vdev_obj) {
2168 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2169 p2p_debug("p2p vdev object is NULL");
2170 return false;
2171 }
2172
2173 qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
2174 for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) {
2175 if ((p2p_vdev_obj->random_mac[i].in_use) &&
2176 (!qdf_mem_cmp(p2p_vdev_obj->random_mac[i].addr,
2177 random_mac_addr, QDF_MAC_ADDR_SIZE))) {
2178 qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
2179 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2180 return true;
2181 }
2182 }
2183 qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
2184 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2185
2186 return false;
2187 }
2188
2189 /**
2190 * find_action_frame_cookie() - Checks for action cookie in cookie list
2191 * @cookie_list: List of cookies
2192 * @rnd_cookie: Cookie to be searched
2193 *
2194 * Return: If search is successful return pointer to action_frame_cookie
2195 * object in which cookie item is encapsulated.
2196 */
2197 static struct action_frame_cookie *
find_action_frame_cookie(qdf_list_t * cookie_list,uint64_t rnd_cookie)2198 find_action_frame_cookie(qdf_list_t *cookie_list, uint64_t rnd_cookie)
2199 {
2200 struct action_frame_cookie *action_cookie;
2201
2202 qdf_list_for_each(cookie_list, action_cookie, cookie_node) {
2203 if (action_cookie->cookie == rnd_cookie)
2204 return action_cookie;
2205 }
2206
2207 return NULL;
2208 }
2209
2210 /**
2211 * allocate_action_frame_cookie() - Allocate and add action cookie to
2212 * given list
2213 * @cookie_list: List of cookies
2214 * @rnd_cookie: Cookie to be added
2215 *
2216 * Return: If allocation and addition is successful return pointer to
2217 * action_frame_cookie object in which cookie item is encapsulated.
2218 */
2219 static struct action_frame_cookie *
allocate_action_frame_cookie(qdf_list_t * cookie_list,uint64_t rnd_cookie)2220 allocate_action_frame_cookie(qdf_list_t *cookie_list, uint64_t rnd_cookie)
2221 {
2222 struct action_frame_cookie *action_cookie;
2223
2224 action_cookie = qdf_mem_malloc(sizeof(*action_cookie));
2225 if (!action_cookie)
2226 return NULL;
2227
2228 action_cookie->cookie = rnd_cookie;
2229 qdf_list_insert_front(cookie_list, &action_cookie->cookie_node);
2230
2231 return action_cookie;
2232 }
2233
2234 /**
2235 * delete_action_frame_cookie() - Delete the cookie from given list
2236 * @cookie_list: List of cookies
2237 * @action_cookie: Cookie to be deleted
2238 *
2239 * This function deletes the cookie item from given list and corresponding
2240 * object in which it is encapsulated.
2241 *
2242 * Return: None
2243 */
2244 static void
delete_action_frame_cookie(qdf_list_t * cookie_list,struct action_frame_cookie * action_cookie)2245 delete_action_frame_cookie(qdf_list_t *cookie_list,
2246 struct action_frame_cookie *action_cookie)
2247 {
2248 qdf_list_remove_node(cookie_list, &action_cookie->cookie_node);
2249 qdf_mem_free(action_cookie);
2250 }
2251
2252 /**
2253 * delete_all_action_frame_cookie() - Delete all the cookies to given list
2254 * @cookie_list: List of cookies
2255 *
2256 * This function deletes all the cookies from from given list.
2257 *
2258 * Return: None
2259 */
2260 static void
delete_all_action_frame_cookie(qdf_list_t * cookie_list)2261 delete_all_action_frame_cookie(qdf_list_t *cookie_list)
2262 {
2263 qdf_list_node_t *node = NULL;
2264
2265 p2p_debug("Delete cookie list %pK, size %d", cookie_list,
2266 qdf_list_size(cookie_list));
2267
2268 while (!qdf_list_empty(cookie_list)) {
2269 qdf_list_remove_front(cookie_list, &node);
2270 qdf_mem_free(node);
2271 }
2272 }
2273
2274 /**
2275 * append_action_frame_cookie() - Append action cookie to given list
2276 * @cookie_list: List of cookies
2277 * @rnd_cookie: Cookie to be append
2278 *
2279 * This is a wrapper function which invokes allocate_action_frame_cookie
2280 * if the cookie to be added is not duplicate
2281 *
2282 * Return: true - for successful case
2283 * false - failed.
2284 */
2285 static bool
append_action_frame_cookie(qdf_list_t * cookie_list,uint64_t rnd_cookie)2286 append_action_frame_cookie(qdf_list_t *cookie_list, uint64_t rnd_cookie)
2287 {
2288 struct action_frame_cookie *action_cookie;
2289
2290 /*
2291 * There should be no mac entry with empty cookie list,
2292 * check and ignore if duplicate
2293 */
2294 action_cookie = find_action_frame_cookie(cookie_list, rnd_cookie);
2295 if (action_cookie)
2296 /* random mac address is already programmed */
2297 return true;
2298
2299 /* insert new cookie in cookie list */
2300 action_cookie = allocate_action_frame_cookie(cookie_list, rnd_cookie);
2301 if (!action_cookie)
2302 return false;
2303
2304 return true;
2305 }
2306
2307 /**
2308 * p2p_add_random_mac() - add or append random mac to given vdev rand mac list
2309 * @soc: soc object
2310 * @vdev_id: vdev id
2311 * @mac: mac addr to be added or append
2312 * @freq: frequency
2313 * @rnd_cookie: random mac mgmt tx cookie
2314 *
2315 * This function will add or append the mac addr entry to vdev random mac list.
2316 * Once the mac addr filter is not needed, it can be removed by
2317 * p2p_del_random_mac.
2318 *
2319 * Return: QDF_STATUS_E_EXISTS - append to existing list
2320 * QDF_STATUS_SUCCESS - add a new entry.
2321 * other : failed to add the mac address entry.
2322 */
2323 static QDF_STATUS
p2p_add_random_mac(struct wlan_objmgr_psoc * soc,uint32_t vdev_id,uint8_t * mac,uint32_t freq,uint64_t rnd_cookie)2324 p2p_add_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
2325 uint8_t *mac, uint32_t freq, uint64_t rnd_cookie)
2326 {
2327 uint32_t i;
2328 uint32_t first_unused = MAX_RANDOM_MAC_ADDRS;
2329 struct action_frame_cookie *action_cookie;
2330 int32_t append_ret;
2331 struct p2p_vdev_priv_obj *p2p_vdev_obj;
2332 struct wlan_objmgr_vdev *vdev;
2333
2334 p2p_debug("random_mac:vdev %d mac_addr:"QDF_MAC_ADDR_FMT" rnd_cookie=%llu freq = %u",
2335 vdev_id, QDF_MAC_ADDR_REF(mac), rnd_cookie, freq);
2336
2337 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(soc, vdev_id, WLAN_P2P_ID);
2338 if (!vdev) {
2339 p2p_debug("vdev is null");
2340
2341 return QDF_STATUS_E_INVAL;
2342 }
2343
2344 p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(
2345 vdev, WLAN_UMAC_COMP_P2P);
2346 if (!p2p_vdev_obj) {
2347 p2p_debug("random_mac:p2p vdev object is NULL");
2348 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2349
2350 return QDF_STATUS_E_INVAL;
2351 }
2352
2353 qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
2354 /*
2355 * Following loop checks whether random mac entry is already
2356 * present, if present get the index of matched entry else
2357 * get the first unused slot to store this new random mac
2358 */
2359 for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) {
2360 if (!p2p_vdev_obj->random_mac[i].in_use) {
2361 if (first_unused == MAX_RANDOM_MAC_ADDRS)
2362 first_unused = i;
2363 continue;
2364 }
2365
2366 if (!qdf_mem_cmp(p2p_vdev_obj->random_mac[i].addr, mac,
2367 QDF_MAC_ADDR_SIZE))
2368 break;
2369 }
2370
2371 if (i != MAX_RANDOM_MAC_ADDRS) {
2372 append_ret = append_action_frame_cookie(
2373 &p2p_vdev_obj->random_mac[i].cookie_list,
2374 rnd_cookie);
2375 qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
2376 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2377 p2p_debug("random_mac:append %d vdev %d freq %d "QDF_MAC_ADDR_FMT" rnd_cookie %llu",
2378 append_ret, vdev_id, freq, QDF_MAC_ADDR_REF(mac), rnd_cookie);
2379 if (!append_ret) {
2380 p2p_debug("random_mac:failed to append rnd_cookie");
2381 return QDF_STATUS_E_NOMEM;
2382 }
2383
2384 return QDF_STATUS_E_EXISTS;
2385 }
2386
2387 if (first_unused == MAX_RANDOM_MAC_ADDRS) {
2388 qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
2389 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2390 p2p_debug("random_mac:Reached the limit of Max random addresses");
2391
2392 return QDF_STATUS_E_RESOURCES;
2393 }
2394
2395 /* get the first unused buf and store new random mac */
2396 i = first_unused;
2397
2398 action_cookie = allocate_action_frame_cookie(
2399 &p2p_vdev_obj->random_mac[i].cookie_list,
2400 rnd_cookie);
2401 if (!action_cookie) {
2402 qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
2403 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2404 p2p_err("random_mac:failed to alloc rnd cookie");
2405
2406 return QDF_STATUS_E_NOMEM;
2407 }
2408 qdf_mem_copy(p2p_vdev_obj->random_mac[i].addr, mac, QDF_MAC_ADDR_SIZE);
2409 p2p_vdev_obj->random_mac[i].in_use = true;
2410 p2p_vdev_obj->random_mac[i].freq = freq;
2411 qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
2412 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2413 p2p_debug("random_mac:add vdev %d freq %d "QDF_MAC_ADDR_FMT" rnd_cookie %llu",
2414 vdev_id, freq, QDF_MAC_ADDR_REF(mac), rnd_cookie);
2415
2416 return QDF_STATUS_SUCCESS;
2417 }
2418
2419 QDF_STATUS
p2p_del_random_mac(struct wlan_objmgr_psoc * soc,uint32_t vdev_id,uint64_t rnd_cookie)2420 p2p_del_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
2421 uint64_t rnd_cookie)
2422 {
2423 uint32_t i;
2424 struct action_frame_cookie *action_cookie;
2425 struct p2p_vdev_priv_obj *p2p_vdev_obj;
2426 struct wlan_objmgr_vdev *vdev;
2427
2428 p2p_debug("random_mac:vdev %d cookie %llu", vdev_id, rnd_cookie);
2429 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(soc, vdev_id,
2430 WLAN_P2P_ID);
2431 if (!vdev) {
2432 p2p_debug("vdev is null");
2433 return QDF_STATUS_E_INVAL;
2434 }
2435 p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(
2436 vdev, WLAN_UMAC_COMP_P2P);
2437 if (!p2p_vdev_obj) {
2438 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2439 p2p_debug("p2p vdev object is NULL");
2440 return QDF_STATUS_E_INVAL;
2441 }
2442
2443 qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
2444 for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) {
2445 struct action_frame_random_mac *random_mac;
2446 qdf_freq_t freq;
2447 uint8_t addr[QDF_MAC_ADDR_SIZE];
2448
2449 random_mac = &p2p_vdev_obj->random_mac[i];
2450 if (!random_mac->in_use)
2451 continue;
2452
2453 action_cookie = find_action_frame_cookie(
2454 &random_mac->cookie_list, rnd_cookie);
2455 if (!action_cookie)
2456 continue;
2457
2458 delete_action_frame_cookie(
2459 &random_mac->cookie_list,
2460 action_cookie);
2461
2462 if (qdf_list_empty(&random_mac->cookie_list)) {
2463 random_mac->in_use = false;
2464 freq = random_mac->freq;
2465 qdf_mem_copy(addr, random_mac->addr, QDF_MAC_ADDR_SIZE);
2466 qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
2467 if (qdf_mc_timer_get_current_state(
2468 &random_mac->clear_timer) ==
2469 QDF_TIMER_STATE_RUNNING) {
2470 p2p_debug("random_mac:stop timer on vdev %d addr " QDF_MAC_ADDR_FMT,
2471 vdev_id, QDF_MAC_ADDR_REF(addr));
2472 qdf_mc_timer_stop(&random_mac->clear_timer);
2473 }
2474
2475 p2p_clear_mac_filter(
2476 wlan_vdev_get_psoc(p2p_vdev_obj->vdev),
2477 vdev_id, addr, freq);
2478
2479 qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
2480 p2p_debug("random_mac:noref on vdev %d addr "QDF_MAC_ADDR_FMT,
2481 vdev_id, QDF_MAC_ADDR_REF(addr));
2482 }
2483 break;
2484 }
2485 qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
2486 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2487
2488 return QDF_STATUS_SUCCESS;
2489 }
2490
2491 QDF_STATUS
p2p_random_mac_handle_tx_done(struct wlan_objmgr_psoc * soc,uint32_t vdev_id,uint64_t rnd_cookie,uint32_t duration)2492 p2p_random_mac_handle_tx_done(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
2493 uint64_t rnd_cookie, uint32_t duration)
2494 {
2495 uint32_t i;
2496 struct action_frame_cookie *action_cookie;
2497 struct p2p_vdev_priv_obj *p2p_vdev_obj;
2498 struct wlan_objmgr_vdev *vdev;
2499
2500 p2p_debug("random_mac:vdev %d cookie %llu duration %d", vdev_id,
2501 rnd_cookie, duration);
2502 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(soc, vdev_id, WLAN_P2P_ID);
2503 if (!vdev) {
2504 p2p_debug("vdev is null");
2505 return QDF_STATUS_E_INVAL;
2506 }
2507
2508 p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(
2509 vdev, WLAN_UMAC_COMP_P2P);
2510 if (!p2p_vdev_obj) {
2511 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2512 p2p_debug("p2p vdev object is NULL");
2513 return QDF_STATUS_E_INVAL;
2514 }
2515
2516 qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
2517 for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) {
2518 struct action_frame_random_mac *random_mac;
2519 qdf_freq_t freq;
2520 uint8_t addr[QDF_MAC_ADDR_SIZE];
2521
2522 random_mac = &p2p_vdev_obj->random_mac[i];
2523 if (!random_mac->in_use)
2524 continue;
2525 action_cookie = find_action_frame_cookie(
2526 &random_mac->cookie_list, rnd_cookie);
2527 if (!action_cookie)
2528 continue;
2529
2530 /* If duration is zero then remove the cookie and also remove
2531 * the filter from firmware.
2532 */
2533 if (!duration) {
2534 delete_action_frame_cookie(&random_mac->cookie_list,
2535 action_cookie);
2536 p2p_debug("random mac:clear mac addr on vdev %d addr " QDF_MAC_ADDR_FMT,
2537 vdev_id, QDF_MAC_ADDR_REF(random_mac->addr));
2538
2539 if (qdf_list_empty(&random_mac->cookie_list)) {
2540 random_mac->in_use = false;
2541 freq = random_mac->freq;
2542 qdf_mem_copy(addr, random_mac->addr,
2543 QDF_MAC_ADDR_SIZE);
2544 qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
2545 p2p_clear_mac_filter(
2546 wlan_vdev_get_psoc(p2p_vdev_obj->vdev),
2547 vdev_id, addr, freq);
2548 qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
2549 }
2550 } else {
2551 /* As duration is non zero start the timer for this
2552 * duration. while the timer is running if tx cancel
2553 * comes from supplicant then cookie will be removed
2554 * and random mac filter will be removed from firmware.
2555 * same thing will happen if timer expires without tx
2556 * cancel from supplicant
2557 */
2558 qdf_mem_copy(addr, random_mac->addr, QDF_MAC_ADDR_SIZE);
2559
2560 qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
2561 if (qdf_mc_timer_get_current_state(
2562 &random_mac->clear_timer) ==
2563 QDF_TIMER_STATE_RUNNING)
2564 qdf_mc_timer_stop(&random_mac->clear_timer);
2565 qdf_mc_timer_start(&random_mac->clear_timer, duration);
2566 p2p_debug("random_mac:start timer on vdev %d addr " QDF_MAC_ADDR_FMT,
2567 vdev_id, QDF_MAC_ADDR_REF(addr));
2568
2569 qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
2570 }
2571 }
2572 qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
2573 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2574
2575 return QDF_STATUS_SUCCESS;
2576 }
2577
p2p_del_all_rand_mac_vdev(struct wlan_objmgr_vdev * vdev)2578 void p2p_del_all_rand_mac_vdev(struct wlan_objmgr_vdev *vdev)
2579 {
2580 int32_t i;
2581 uint32_t freq;
2582 uint8_t addr[QDF_MAC_ADDR_SIZE];
2583 struct p2p_vdev_priv_obj *p2p_vdev_obj;
2584
2585 if (!vdev)
2586 return;
2587 p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(
2588 vdev, WLAN_UMAC_COMP_P2P);
2589 if (!p2p_vdev_obj)
2590 return;
2591
2592 qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
2593 for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) {
2594 struct action_frame_cookie *action_cookie;
2595 struct action_frame_cookie *action_cookie_next;
2596
2597 if (!p2p_vdev_obj->random_mac[i].in_use)
2598 continue;
2599
2600 /* empty the list and clear random addr */
2601 qdf_list_for_each_del(&p2p_vdev_obj->random_mac[i].cookie_list,
2602 action_cookie, action_cookie_next,
2603 cookie_node) {
2604 qdf_list_remove_node(
2605 &p2p_vdev_obj->random_mac[i].cookie_list,
2606 &action_cookie->cookie_node);
2607 qdf_mem_free(action_cookie);
2608 }
2609
2610 p2p_vdev_obj->random_mac[i].in_use = false;
2611 freq = p2p_vdev_obj->random_mac[i].freq;
2612 qdf_mem_copy(addr, p2p_vdev_obj->random_mac[i].addr,
2613 QDF_MAC_ADDR_SIZE);
2614 qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
2615 qdf_mc_timer_stop(&p2p_vdev_obj->random_mac[i].clear_timer);
2616 p2p_clear_mac_filter(wlan_vdev_get_psoc(vdev),
2617 wlan_vdev_get_id(vdev), addr, freq);
2618 p2p_debug("random_mac:delall vdev %d freq %d addr "QDF_MAC_ADDR_FMT,
2619 wlan_vdev_get_id(vdev), freq, QDF_MAC_ADDR_REF(addr));
2620
2621 qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
2622 }
2623 qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
2624 }
2625
2626 static void
p2p_del_rand_mac_vdev_enum_handler(struct wlan_objmgr_psoc * psoc,void * obj,void * arg)2627 p2p_del_rand_mac_vdev_enum_handler(struct wlan_objmgr_psoc *psoc,
2628 void *obj, void *arg)
2629 {
2630 struct wlan_objmgr_vdev *vdev = obj;
2631
2632 if (!vdev) {
2633 p2p_err("random_mac:invalid vdev");
2634 return;
2635 }
2636
2637 if (!p2p_is_vdev_support_rand_mac(vdev))
2638 return;
2639
2640 p2p_del_all_rand_mac_vdev(vdev);
2641 }
2642
p2p_del_all_rand_mac_soc(struct wlan_objmgr_psoc * soc)2643 void p2p_del_all_rand_mac_soc(struct wlan_objmgr_psoc *soc)
2644 {
2645 if (!soc) {
2646 p2p_err("random_mac:soc object is NULL");
2647 return;
2648 }
2649
2650 wlan_objmgr_iterate_obj_list(soc, WLAN_VDEV_OP,
2651 p2p_del_rand_mac_vdev_enum_handler,
2652 NULL, 0, WLAN_P2P_ID);
2653 }
2654
2655 /**
2656 * p2p_is_random_mac() - check mac addr is random mac for vdev
2657 * @soc: soc object
2658 * @vdev_id: vdev id
2659 * @mac: mac addr to be added or append
2660 *
2661 * This function will check the source mac addr same as vdev's mac addr or not.
2662 * If not same, then the source mac addr should be random mac addr.
2663 *
2664 * Return: true if mac is random mac, otherwise false
2665 */
2666 static bool
p2p_is_random_mac(struct wlan_objmgr_psoc * soc,uint32_t vdev_id,uint8_t * mac)2667 p2p_is_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id, uint8_t *mac)
2668 {
2669 bool ret = false;
2670 struct wlan_objmgr_vdev *vdev;
2671
2672 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(soc, vdev_id, WLAN_P2P_ID);
2673 if (!vdev) {
2674 p2p_debug("random_mac:vdev is null");
2675 return false;
2676 }
2677
2678 if (qdf_mem_cmp(wlan_vdev_mlme_get_macaddr(vdev),
2679 mac, QDF_MAC_ADDR_SIZE))
2680 ret = true;
2681 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2682
2683 return ret;
2684 }
2685
p2p_set_mac_filter_callback(bool result,void * context)2686 static void p2p_set_mac_filter_callback(bool result, void *context)
2687 {
2688 struct osif_request *request;
2689 struct random_mac_priv *priv;
2690
2691 p2p_debug("random_mac:set random mac filter result %d", result);
2692 request = osif_request_get(context);
2693 if (!request) {
2694 p2p_err("random_mac:invalid response");
2695 return;
2696 }
2697
2698 priv = osif_request_priv(request);
2699 priv->result = result;
2700
2701 osif_request_complete(request);
2702 osif_request_put(request);
2703 }
2704
p2p_process_set_rand_mac_rsp(struct p2p_mac_filter_rsp * resp)2705 QDF_STATUS p2p_process_set_rand_mac_rsp(struct p2p_mac_filter_rsp *resp)
2706 {
2707 struct wlan_objmgr_psoc *soc;
2708 struct p2p_vdev_priv_obj *p2p_vdev_obj;
2709 struct wlan_objmgr_vdev *vdev;
2710
2711 if (!resp || !resp->p2p_soc_obj || !resp->p2p_soc_obj->soc) {
2712 p2p_debug("random_mac:set_filter_req is null");
2713 return QDF_STATUS_E_INVAL;
2714 }
2715 p2p_debug("random_mac:process rsp on vdev %d status %d", resp->vdev_id,
2716 resp->status);
2717 soc = resp->p2p_soc_obj->soc;
2718 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(soc, resp->vdev_id,
2719 WLAN_P2P_ID);
2720 if (!vdev) {
2721 p2p_debug("random_mac:vdev is null vdev %d", resp->vdev_id);
2722 return QDF_STATUS_E_INVAL;
2723 }
2724
2725 p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(
2726 vdev, WLAN_UMAC_COMP_P2P);
2727 if (!p2p_vdev_obj) {
2728 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2729 p2p_debug("random_mac:p2p_vdev_obj is null vdev %d",
2730 resp->vdev_id);
2731 return QDF_STATUS_E_INVAL;
2732 }
2733 if (!p2p_vdev_obj->pending_req.soc) {
2734 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2735 p2p_debug("random_mac:no pending set req for vdev %d",
2736 resp->vdev_id);
2737 return QDF_STATUS_E_INVAL;
2738 }
2739
2740 p2p_debug("random_mac:get pending req on vdev %d set %d mac filter "QDF_MAC_ADDR_FMT" freq %d",
2741 p2p_vdev_obj->pending_req.vdev_id,
2742 p2p_vdev_obj->pending_req.set,
2743 QDF_MAC_ADDR_REF(p2p_vdev_obj->pending_req.mac),
2744 p2p_vdev_obj->pending_req.freq);
2745 if (p2p_vdev_obj->pending_req.cb)
2746 p2p_vdev_obj->pending_req.cb(
2747 !!resp->status, p2p_vdev_obj->pending_req.req_cookie);
2748
2749 qdf_mem_zero(&p2p_vdev_obj->pending_req,
2750 sizeof(p2p_vdev_obj->pending_req));
2751 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2752
2753 return QDF_STATUS_SUCCESS;
2754 }
2755
2756 QDF_STATUS
p2p_process_set_rand_mac(struct p2p_set_mac_filter_req * set_filter_req)2757 p2p_process_set_rand_mac(struct p2p_set_mac_filter_req *set_filter_req)
2758 {
2759 struct wlan_objmgr_psoc *soc;
2760 struct wlan_lmac_if_p2p_tx_ops *p2p_ops;
2761 QDF_STATUS status = QDF_STATUS_E_FAILURE;
2762 struct set_rx_mac_filter param;
2763 struct p2p_vdev_priv_obj *p2p_vdev_obj;
2764 struct wlan_objmgr_vdev *vdev;
2765
2766 if (!set_filter_req || !set_filter_req->soc) {
2767 p2p_debug("random_mac:set_filter_req is null");
2768 return QDF_STATUS_E_INVAL;
2769 }
2770 p2p_debug("random_mac:vdev %d set %d mac filter "QDF_MAC_ADDR_FMT" freq %d",
2771 set_filter_req->vdev_id, set_filter_req->set,
2772 QDF_MAC_ADDR_REF(set_filter_req->mac), set_filter_req->freq);
2773
2774 soc = set_filter_req->soc;
2775 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
2776 soc, set_filter_req->vdev_id, WLAN_P2P_ID);
2777 if (!vdev) {
2778 p2p_debug("random_mac:vdev is null vdev %d",
2779 set_filter_req->vdev_id);
2780 goto get_vdev_failed;
2781 }
2782 p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(
2783 vdev, WLAN_UMAC_COMP_P2P);
2784 if (!p2p_vdev_obj) {
2785 p2p_debug("random_mac:p2p_vdev_obj is null vdev %d",
2786 set_filter_req->vdev_id);
2787 goto get_p2p_obj_failed;
2788 }
2789 if (p2p_vdev_obj->pending_req.soc) {
2790 p2p_debug("random_mac:Busy on vdev %d set %d mac filter "QDF_MAC_ADDR_FMT" freq %d",
2791 p2p_vdev_obj->pending_req.vdev_id,
2792 p2p_vdev_obj->pending_req.set,
2793 QDF_MAC_ADDR_REF(p2p_vdev_obj->pending_req.mac),
2794 p2p_vdev_obj->pending_req.freq);
2795 goto get_p2p_obj_failed;
2796 }
2797
2798 p2p_ops = p2p_psoc_get_tx_ops(soc);
2799 if (p2p_ops && p2p_ops->set_mac_addr_rx_filter_cmd) {
2800 qdf_mem_zero(¶m, sizeof(param));
2801 param.vdev_id = set_filter_req->vdev_id;
2802 qdf_mem_copy(param.mac, set_filter_req->mac,
2803 QDF_MAC_ADDR_SIZE);
2804 param.freq = set_filter_req->freq;
2805 param.set = set_filter_req->set;
2806 status = p2p_ops->set_mac_addr_rx_filter_cmd(soc, ¶m);
2807 if (status == QDF_STATUS_SUCCESS && set_filter_req->set)
2808 qdf_mem_copy(&p2p_vdev_obj->pending_req,
2809 set_filter_req, sizeof(*set_filter_req));
2810 p2p_debug("random_mac:p2p set mac addr rx filter, status:%d",
2811 status);
2812 }
2813
2814 get_p2p_obj_failed:
2815 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2816
2817 get_vdev_failed:
2818 if (status != QDF_STATUS_SUCCESS &&
2819 set_filter_req->cb)
2820 set_filter_req->cb(false, set_filter_req->req_cookie);
2821
2822 return status;
2823 }
2824
2825 /**
2826 * p2p_set_mac_filter() - send set mac addr filter cmd
2827 * @soc: soc
2828 * @vdev_id: vdev id
2829 * @mac: mac addr
2830 * @freq: freq
2831 * @set: set or clear
2832 * @cb: callback func to be called when the request completed.
2833 * @req_cookie: cookie to be returned
2834 *
2835 * This function send set random mac addr filter command to p2p component
2836 * msg core
2837 *
2838 * Return: QDF_STATUS_SUCCESS - if sent successfully.
2839 * otherwise : failed.
2840 */
2841 static QDF_STATUS
p2p_set_mac_filter(struct wlan_objmgr_psoc * soc,uint32_t vdev_id,uint8_t * mac,uint32_t freq,bool set,p2p_request_mgr_callback_t cb,void * req_cookie)2842 p2p_set_mac_filter(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
2843 uint8_t *mac, uint32_t freq, bool set,
2844 p2p_request_mgr_callback_t cb, void *req_cookie)
2845 {
2846 struct p2p_set_mac_filter_req *set_filter_req;
2847 struct scheduler_msg msg = {0};
2848 QDF_STATUS status;
2849
2850 p2p_debug("random_mac:vdev %d freq %d set %d "QDF_MAC_ADDR_FMT,
2851 vdev_id, freq, set, QDF_MAC_ADDR_REF(mac));
2852
2853 set_filter_req = qdf_mem_malloc(sizeof(*set_filter_req));
2854 if (!set_filter_req)
2855 return QDF_STATUS_E_NOMEM;
2856
2857 set_filter_req->soc = soc;
2858 set_filter_req->vdev_id = vdev_id;
2859 set_filter_req->freq = freq;
2860 qdf_mem_copy(set_filter_req->mac, mac, QDF_MAC_ADDR_SIZE);
2861 set_filter_req->set = set;
2862 set_filter_req->cb = cb;
2863 set_filter_req->req_cookie = req_cookie;
2864
2865 msg.type = P2P_SET_RANDOM_MAC;
2866 msg.bodyptr = set_filter_req;
2867 msg.callback = p2p_process_cmd;
2868 status = scheduler_post_message(QDF_MODULE_ID_P2P, QDF_MODULE_ID_P2P,
2869 QDF_MODULE_ID_OS_IF, &msg);
2870 if (status != QDF_STATUS_SUCCESS)
2871 qdf_mem_free(set_filter_req);
2872
2873 return status;
2874 }
2875
2876 QDF_STATUS
p2p_clear_mac_filter(struct wlan_objmgr_psoc * soc,uint32_t vdev_id,uint8_t * mac,uint32_t freq)2877 p2p_clear_mac_filter(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
2878 uint8_t *mac, uint32_t freq)
2879 {
2880 return p2p_set_mac_filter(soc, vdev_id, mac, freq, false, NULL, NULL);
2881 }
2882
2883 bool
p2p_is_vdev_support_rand_mac(struct wlan_objmgr_vdev * vdev)2884 p2p_is_vdev_support_rand_mac(struct wlan_objmgr_vdev *vdev)
2885 {
2886 enum QDF_OPMODE mode;
2887
2888 mode = wlan_vdev_mlme_get_opmode(vdev);
2889 if (mode == QDF_STA_MODE ||
2890 mode == QDF_P2P_CLIENT_MODE ||
2891 mode == QDF_P2P_DEVICE_MODE ||
2892 mode == QDF_NAN_DISC_MODE)
2893 return true;
2894 return false;
2895 }
2896
2897 /**
2898 * p2p_is_vdev_support_rand_mac_by_id() - check vdev type support random mac
2899 * mgmt tx or not
2900 * @soc: soc obj
2901 * @vdev_id: vdev id
2902 *
2903 * Return: true: support random mac mgmt tx
2904 * false: not support random mac mgmt tx.
2905 */
2906 static bool
p2p_is_vdev_support_rand_mac_by_id(struct wlan_objmgr_psoc * soc,uint32_t vdev_id)2907 p2p_is_vdev_support_rand_mac_by_id(struct wlan_objmgr_psoc *soc,
2908 uint32_t vdev_id)
2909 {
2910 struct wlan_objmgr_vdev *vdev;
2911 bool ret = false;
2912
2913 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(soc, vdev_id, WLAN_P2P_ID);
2914 if (!vdev)
2915 return false;
2916 ret = p2p_is_vdev_support_rand_mac(vdev);
2917 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
2918
2919 return ret;
2920 }
2921
2922 /**
2923 * p2p_set_rand_mac() - set random mac address rx filter
2924 * @soc: soc
2925 * @vdev_id: vdev id
2926 * @mac: mac addr
2927 * @freq: freq
2928 * @rnd_cookie: cookie to be returned
2929 *
2930 * This function will post msg to p2p core to set random mac addr rx filter.
2931 * It will wait the respone and return the result to caller.
2932 *
2933 * Return: true: set successfully
2934 * false: failed
2935 */
2936 static bool
p2p_set_rand_mac(struct wlan_objmgr_psoc * soc,uint32_t vdev_id,uint8_t * mac,uint32_t freq,uint64_t rnd_cookie)2937 p2p_set_rand_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
2938 uint8_t *mac, uint32_t freq, uint64_t rnd_cookie)
2939 {
2940 bool ret = false;
2941 int err;
2942 QDF_STATUS status;
2943 struct osif_request *request;
2944 static const struct osif_request_params params = {
2945 .priv_size = sizeof(struct random_mac_priv),
2946 .timeout_ms = WLAN_WAIT_TIME_SET_RND,
2947 };
2948 void *req_cookie;
2949 struct random_mac_priv *priv;
2950
2951 request = osif_request_alloc(¶ms);
2952 if (!request) {
2953 p2p_err("Request allocation failure");
2954 return false;
2955 }
2956
2957 req_cookie = osif_request_cookie(request);
2958
2959 status = p2p_set_mac_filter(soc, vdev_id, mac, freq, true,
2960 p2p_set_mac_filter_callback, req_cookie);
2961 if (status != QDF_STATUS_SUCCESS) {
2962 p2p_err("random_mac:set mac filter failure %d", status);
2963 } else {
2964 err = osif_request_wait_for_response(request);
2965 if (err) {
2966 p2p_err("random_mac:timeout for set mac filter %d",
2967 err);
2968 } else {
2969 priv = osif_request_priv(request);
2970 ret = priv->result;
2971 p2p_debug("random_mac:vdev %d freq %d result %d "QDF_MAC_ADDR_FMT" rnd_cookie %llu",
2972 vdev_id, freq, priv->result,
2973 QDF_MAC_ADDR_REF(mac), rnd_cookie);
2974 }
2975 }
2976 osif_request_put(request);
2977
2978 return ret;
2979 }
2980
2981 /**
2982 * p2p_mac_clear_timeout() - clear random mac filter timeout
2983 * @context: timer context
2984 *
2985 * This function will clear the mac addr rx filter in target if no
2986 * reference to it.
2987 *
2988 * Return: void
2989 */
p2p_mac_clear_timeout(void * context)2990 static void p2p_mac_clear_timeout(void *context)
2991 {
2992 struct action_frame_random_mac *random_mac = context;
2993 struct p2p_vdev_priv_obj *p2p_vdev_obj;
2994 uint32_t freq;
2995 uint8_t addr[QDF_MAC_ADDR_SIZE];
2996 uint32_t vdev_id;
2997
2998 if (!random_mac || !random_mac->p2p_vdev_obj) {
2999 p2p_err("invalid context for mac_clear timeout");
3000 return;
3001 }
3002 p2p_vdev_obj = random_mac->p2p_vdev_obj;
3003 if (!p2p_vdev_obj || !p2p_vdev_obj->vdev)
3004 return;
3005
3006 qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
3007
3008 delete_all_action_frame_cookie(&random_mac->cookie_list);
3009 random_mac->in_use = false;
3010 freq = random_mac->freq;
3011 qdf_mem_copy(addr, random_mac->addr, QDF_MAC_ADDR_SIZE);
3012 qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
3013
3014 vdev_id = wlan_vdev_get_id(p2p_vdev_obj->vdev);
3015 p2p_debug("random_mac:clear timeout vdev %d " QDF_MAC_ADDR_FMT " freq %d",
3016 vdev_id, QDF_MAC_ADDR_REF(addr), freq);
3017
3018 p2p_clear_mac_filter(wlan_vdev_get_psoc(p2p_vdev_obj->vdev),
3019 vdev_id, addr, freq);
3020 }
3021
3022 /**
3023 * p2p_request_random_mac() - request random mac mgmt tx
3024 * @soc: soc
3025 * @vdev_id: vdev id
3026 * @mac: mac addr
3027 * @freq: freq
3028 * @rnd_cookie: cookie to be returned
3029 * @duration: duration of tx timeout
3030 *
3031 * This function will add/append the random mac addr filter entry to vdev.
3032 * If it is new added entry, it will request to set filter in target.
3033 *
3034 * Return: QDF_STATUS_SUCCESS: request successfully
3035 * other: failed
3036 */
3037 static QDF_STATUS
p2p_request_random_mac(struct wlan_objmgr_psoc * soc,uint32_t vdev_id,uint8_t * mac,uint32_t freq,uint64_t rnd_cookie,uint32_t duration)3038 p2p_request_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
3039 uint8_t *mac, uint32_t freq, uint64_t rnd_cookie,
3040 uint32_t duration)
3041 {
3042 QDF_STATUS status;
3043 uint32_t i;
3044 struct wlan_objmgr_vdev *vdev;
3045 struct p2p_vdev_priv_obj *p2p_vdev_obj;
3046
3047 status = p2p_add_random_mac(soc, vdev_id, mac, freq, rnd_cookie);
3048 if (status == QDF_STATUS_E_EXISTS)
3049 return QDF_STATUS_SUCCESS;
3050
3051 else if (status != QDF_STATUS_SUCCESS)
3052 return status;
3053
3054 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(soc, vdev_id, WLAN_P2P_ID);
3055 if (!vdev) {
3056 p2p_debug("vdev is null");
3057 return QDF_STATUS_E_INVAL;
3058 }
3059
3060 p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(
3061 vdev, WLAN_UMAC_COMP_P2P);
3062 if (!p2p_vdev_obj) {
3063 p2p_debug("random_mac:p2p vdev object is NULL");
3064 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
3065 return QDF_STATUS_E_INVAL;
3066 }
3067
3068 if (!p2p_set_rand_mac(soc, vdev_id, mac, freq, rnd_cookie)) {
3069 p2p_debug("random mac: failed to set rand mac address");
3070
3071 qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
3072 for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) {
3073 if (!qdf_mem_cmp(p2p_vdev_obj->random_mac[i].addr, mac,
3074 QDF_MAC_ADDR_SIZE)) {
3075 qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
3076 p2p_mac_clear_timeout(
3077 &p2p_vdev_obj->random_mac[i]);
3078 status = QDF_STATUS_SUCCESS;
3079 qdf_spin_lock(&p2p_vdev_obj->random_mac_lock);
3080 break;
3081 }
3082 }
3083 qdf_spin_unlock(&p2p_vdev_obj->random_mac_lock);
3084 }
3085
3086 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
3087 return status;
3088 }
3089
p2p_rand_mac_tx(struct wlan_objmgr_pdev * pdev,struct tx_action_context * tx_action)3090 void p2p_rand_mac_tx(struct wlan_objmgr_pdev *pdev,
3091 struct tx_action_context *tx_action)
3092 {
3093 struct wlan_objmgr_psoc *soc;
3094 struct wlan_objmgr_vdev *vdev;
3095 QDF_STATUS status;
3096 bool is_vdev_up;
3097
3098 if (!tx_action || !tx_action->p2p_soc_obj ||
3099 !tx_action->p2p_soc_obj->soc)
3100 return;
3101 soc = tx_action->p2p_soc_obj->soc;
3102
3103 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, tx_action->vdev_id,
3104 WLAN_P2P_ID);
3105 if (!vdev) {
3106 p2p_err("vdev is null id:%d", tx_action->vdev_id);
3107 return;
3108 }
3109
3110 /*
3111 * For PASN authentication frames, fw may request PASN authentication
3112 * with source address same as vdev mac address when vdev is not already
3113 * started. Allow RX_FILTER configuration for vdev mac address also if
3114 * vdev is not started to prevent PASN authentication frame drops.
3115 */
3116 is_vdev_up = QDF_IS_STATUS_SUCCESS(wlan_vdev_is_up(vdev));
3117 if (!tx_action->no_ack && tx_action->chan_freq &&
3118 tx_action->buf_len > MIN_MAC_HEADER_LEN &&
3119 p2p_is_vdev_support_rand_mac_by_id(soc, tx_action->vdev_id) &&
3120 (p2p_is_random_mac(soc, tx_action->vdev_id,
3121 &tx_action->buf[SRC_MAC_ADDR_OFFSET]) ||
3122 !is_vdev_up)) {
3123 status = p2p_request_random_mac(
3124 soc, tx_action->vdev_id,
3125 &tx_action->buf[SRC_MAC_ADDR_OFFSET],
3126 tx_action->chan_freq,
3127 tx_action->id,
3128 tx_action->duration);
3129 if (status == QDF_STATUS_SUCCESS)
3130 tx_action->rand_mac_tx = true;
3131 else
3132 tx_action->rand_mac_tx = false;
3133 }
3134
3135 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
3136 }
3137
3138 void
p2p_rand_mac_tx_done(struct wlan_objmgr_psoc * soc,struct tx_action_context * tx_ctx)3139 p2p_rand_mac_tx_done(struct wlan_objmgr_psoc *soc,
3140 struct tx_action_context *tx_ctx)
3141 {
3142 if (!tx_ctx || !tx_ctx->rand_mac_tx || !soc)
3143 return;
3144
3145 p2p_random_mac_handle_tx_done(soc, tx_ctx->vdev_id, tx_ctx->id,
3146 tx_ctx->duration);
3147 }
3148
p2p_init_random_mac_vdev(struct p2p_vdev_priv_obj * p2p_vdev_obj)3149 void p2p_init_random_mac_vdev(struct p2p_vdev_priv_obj *p2p_vdev_obj)
3150 {
3151 int32_t i;
3152
3153 qdf_spinlock_create(&p2p_vdev_obj->random_mac_lock);
3154 for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) {
3155 qdf_mem_zero(&p2p_vdev_obj->random_mac[i],
3156 sizeof(struct action_frame_random_mac));
3157 p2p_vdev_obj->random_mac[i].in_use = false;
3158 p2p_vdev_obj->random_mac[i].p2p_vdev_obj = p2p_vdev_obj;
3159 qdf_list_create(&p2p_vdev_obj->random_mac[i].cookie_list, 0);
3160 qdf_mc_timer_init(&p2p_vdev_obj->random_mac[i].clear_timer,
3161 QDF_TIMER_TYPE_SW, p2p_mac_clear_timeout,
3162 &p2p_vdev_obj->random_mac[i]);
3163 }
3164 }
3165
p2p_deinit_random_mac_vdev(struct p2p_vdev_priv_obj * p2p_vdev_obj)3166 void p2p_deinit_random_mac_vdev(struct p2p_vdev_priv_obj *p2p_vdev_obj)
3167 {
3168 int32_t i;
3169
3170 p2p_del_all_rand_mac_vdev(p2p_vdev_obj->vdev);
3171 for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) {
3172 qdf_mc_timer_destroy(&p2p_vdev_obj->random_mac[i].clear_timer);
3173 qdf_list_destroy(&p2p_vdev_obj->random_mac[i].cookie_list);
3174 }
3175 qdf_spinlock_destroy(&p2p_vdev_obj->random_mac_lock);
3176 }
3177
p2p_process_mgmt_tx(struct tx_action_context * tx_ctx)3178 QDF_STATUS p2p_process_mgmt_tx(struct tx_action_context *tx_ctx)
3179 {
3180 struct p2p_soc_priv_obj *p2p_soc_obj;
3181 struct p2p_roc_context *curr_roc_ctx;
3182 uint8_t *mac_to;
3183 enum QDF_OPMODE mode;
3184 struct wlan_objmgr_vdev *vdev;
3185 QDF_STATUS status;
3186 bool is_vdev_connected = false;
3187
3188 status = p2p_tx_context_check_valid(tx_ctx);
3189 if (status != QDF_STATUS_SUCCESS) {
3190 p2p_err("invalid tx action context");
3191 if (tx_ctx) {
3192 if (tx_ctx->buf) {
3193 p2p_send_tx_conf(tx_ctx, false);
3194 qdf_mem_free(tx_ctx->buf);
3195 }
3196 qdf_mem_free(tx_ctx);
3197 }
3198 return QDF_STATUS_E_INVAL;
3199 }
3200
3201 p2p_soc_obj = tx_ctx->p2p_soc_obj;
3202
3203 p2p_debug("soc:%pK, tx_ctx:%pK, vdev_id:%d, scan_id:%d, "
3204 "roc_cookie:%llx, freq:%d, buf:%pK, len:%d, "
3205 "off_chan:%d, cck:%d, ack:%d, duration:%d",
3206 p2p_soc_obj->soc, tx_ctx, tx_ctx->vdev_id,
3207 tx_ctx->scan_id, tx_ctx->roc_cookie, tx_ctx->chan_freq,
3208 tx_ctx->buf, tx_ctx->buf_len, tx_ctx->off_chan,
3209 tx_ctx->no_cck, tx_ctx->no_ack, tx_ctx->duration);
3210
3211 status = p2p_get_frame_info(tx_ctx->buf, tx_ctx->buf_len,
3212 &(tx_ctx->frame_info));
3213 if (status != QDF_STATUS_SUCCESS) {
3214 p2p_err("unsupported frame");
3215 status = QDF_STATUS_E_INVAL;
3216 goto fail;
3217 }
3218
3219 /* update P2P connection status with tx frame info */
3220 mac_to = &(tx_ctx->buf[DST_MAC_ADDR_OFFSET]);
3221 p2p_tx_update_connection_status(p2p_soc_obj,
3222 &(tx_ctx->frame_info), mac_to);
3223
3224 status = p2p_vdev_check_valid(tx_ctx);
3225 if (status != QDF_STATUS_SUCCESS) {
3226 p2p_debug("invalid vdev or vdev mode");
3227 status = QDF_STATUS_E_INVAL;
3228 goto fail;
3229 }
3230
3231 /* Do not wait for ack for probe response */
3232 if (tx_ctx->frame_info.sub_type == P2P_MGMT_PROBE_RSP &&
3233 !(tx_ctx->no_ack)) {
3234 p2p_debug("Force set no ack to 1");
3235 tx_ctx->no_ack = 1;
3236 }
3237
3238 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
3239 p2p_soc_obj->soc, tx_ctx->vdev_id, WLAN_P2P_ID);
3240 if (!vdev) {
3241 p2p_err("null vdev object");
3242 goto fail;
3243 }
3244
3245 mode = wlan_vdev_mlme_get_opmode(vdev);
3246 if (mode == QDF_STA_MODE)
3247 is_vdev_connected = wlan_cm_is_vdev_connected(vdev);
3248
3249 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
3250
3251 if (!tx_ctx->off_chan || !tx_ctx->chan_freq) {
3252 if (!tx_ctx->chan_freq)
3253 p2p_check_and_update_channel(tx_ctx);
3254 if (!tx_ctx->chan_freq && mode == QDF_STA_MODE &&
3255 !is_vdev_connected) {
3256 p2p_debug("chan freq is zero, drop tx mgmt frame");
3257 goto fail;
3258 }
3259 status = p2p_execute_tx_action_frame(tx_ctx);
3260 if (status != QDF_STATUS_SUCCESS) {
3261 p2p_err("execute tx fail");
3262 goto fail;
3263 } else
3264 return QDF_STATUS_SUCCESS;
3265 }
3266
3267 /* For off channel tx case */
3268 curr_roc_ctx = p2p_find_current_roc_ctx(p2p_soc_obj);
3269 if (curr_roc_ctx && (curr_roc_ctx->chan_freq == tx_ctx->chan_freq)) {
3270 if ((curr_roc_ctx->roc_state == ROC_STATE_REQUESTED) ||
3271 (curr_roc_ctx->roc_state == ROC_STATE_STARTED)) {
3272 tx_ctx->roc_cookie = (uintptr_t)curr_roc_ctx;
3273 status = qdf_list_insert_back(
3274 &p2p_soc_obj->tx_q_roc,
3275 &tx_ctx->node);
3276 if (status != QDF_STATUS_SUCCESS) {
3277 p2p_err("Failed to insert off chan tx context to wait roc req queue");
3278 goto fail;
3279 } else
3280 return QDF_STATUS_SUCCESS;
3281 } else if (curr_roc_ctx->roc_state == ROC_STATE_ON_CHAN) {
3282 p2p_adjust_tx_wait(tx_ctx);
3283 if (curr_roc_ctx->duration < tx_ctx->duration)
3284 curr_roc_ctx->duration = tx_ctx->duration;
3285 status = p2p_restart_roc_timer(curr_roc_ctx);
3286 curr_roc_ctx->tx_ctx = tx_ctx;
3287 if (status != QDF_STATUS_SUCCESS) {
3288 p2p_err("restart roc timer fail");
3289 goto fail;
3290 }
3291 status = p2p_execute_tx_action_frame(tx_ctx);
3292 if (status != QDF_STATUS_SUCCESS) {
3293 p2p_err("execute tx fail");
3294 goto fail;
3295 } else
3296 return QDF_STATUS_SUCCESS;
3297 }
3298 }
3299
3300 curr_roc_ctx = p2p_find_roc_by_chan_freq(p2p_soc_obj,
3301 tx_ctx->chan_freq);
3302 if (curr_roc_ctx && (curr_roc_ctx->roc_state == ROC_STATE_IDLE)) {
3303 tx_ctx->roc_cookie = (uintptr_t)curr_roc_ctx;
3304 status = qdf_list_insert_back(
3305 &p2p_soc_obj->tx_q_roc,
3306 &tx_ctx->node);
3307 if (status != QDF_STATUS_SUCCESS) {
3308 p2p_err("Failed to insert off chan tx context to wait roc req queue");
3309 goto fail;
3310 } else {
3311 return QDF_STATUS_SUCCESS;
3312 }
3313 }
3314
3315 if (!tx_ctx->duration) {
3316 tx_ctx->duration = P2P_ACTION_FRAME_DEFAULT_WAIT;
3317 p2p_debug("use default wait %d",
3318 P2P_ACTION_FRAME_DEFAULT_WAIT);
3319 }
3320 status = p2p_roc_req_for_tx_action(tx_ctx);
3321 if (status != QDF_STATUS_SUCCESS) {
3322 p2p_err("Failed to request roc before off chan tx");
3323 goto fail;
3324 }
3325
3326 return QDF_STATUS_SUCCESS;
3327
3328 fail:
3329 p2p_send_tx_conf(tx_ctx, false);
3330 qdf_idr_remove(&p2p_soc_obj->p2p_idr, tx_ctx->id);
3331 qdf_mem_free(tx_ctx->buf);
3332 qdf_mem_free(tx_ctx);
3333
3334 return status;
3335 }
3336
p2p_process_mgmt_tx_cancel(struct cancel_roc_context * cancel_tx)3337 QDF_STATUS p2p_process_mgmt_tx_cancel(
3338 struct cancel_roc_context *cancel_tx)
3339 {
3340 bool is_roc_q = false;
3341 bool is_ack_q = false;
3342 struct tx_action_context *cur_tx_ctx;
3343 struct p2p_roc_context *cur_roc_ctx;
3344 struct cancel_roc_context cancel_roc;
3345
3346 if (!cancel_tx || !(cancel_tx->cookie)) {
3347 p2p_info("invalid cancel info");
3348 return QDF_STATUS_SUCCESS;
3349 }
3350
3351 cur_tx_ctx = p2p_find_tx_ctx(cancel_tx->p2p_soc_obj,
3352 cancel_tx->cookie, &is_roc_q, &is_ack_q);
3353 if (cur_tx_ctx) {
3354 if (is_roc_q) {
3355 cancel_roc.p2p_soc_obj =
3356 cancel_tx->p2p_soc_obj;
3357 cancel_roc.cookie =
3358 cur_tx_ctx->roc_cookie;
3359 p2p_remove_tx_context(cur_tx_ctx);
3360 return p2p_process_cancel_roc_req(&cancel_roc);
3361 }
3362 if (is_ack_q) {
3363 /*Has tx action frame, waiting for ack*/
3364 p2p_debug("Waiting for ack, cookie %llx",
3365 cancel_tx->cookie);
3366 }
3367 } else {
3368 p2p_debug("Failed to find tx ctx by cookie, cookie %llx",
3369 cancel_tx->cookie);
3370
3371 cur_roc_ctx = p2p_find_roc_by_tx_ctx(cancel_tx->p2p_soc_obj,
3372 cancel_tx->cookie);
3373 if (cur_roc_ctx) {
3374 p2p_debug("tx ctx:%llx, roc:%pK",
3375 cancel_tx->cookie, cur_roc_ctx);
3376 cancel_roc.p2p_soc_obj =
3377 cancel_tx->p2p_soc_obj;
3378 cancel_roc.cookie = (uintptr_t) cur_roc_ctx;
3379 return p2p_process_cancel_roc_req(&cancel_roc);
3380 }
3381
3382 p2p_debug("Failed to find roc by tx ctx");
3383 return QDF_STATUS_E_INVAL;
3384 }
3385
3386 return QDF_STATUS_SUCCESS;
3387 }
3388
p2p_process_mgmt_tx_ack_cnf(struct p2p_tx_conf_event * tx_cnf_event)3389 QDF_STATUS p2p_process_mgmt_tx_ack_cnf(
3390 struct p2p_tx_conf_event *tx_cnf_event)
3391 {
3392 struct p2p_tx_cnf tx_cnf;
3393 struct tx_action_context *tx_ctx;
3394 struct p2p_soc_priv_obj *p2p_soc_obj;
3395 struct p2p_start_param *start_param;
3396
3397 p2p_soc_obj = tx_cnf_event->p2p_soc_obj;
3398
3399 if (!p2p_soc_obj || !(p2p_soc_obj->start_param)) {
3400 qdf_nbuf_free(tx_cnf_event->nbuf);
3401 p2p_err("Invalid p2p soc object or start parameters");
3402 return QDF_STATUS_E_INVAL;
3403 }
3404
3405 tx_ctx = p2p_find_tx_ctx_by_nbuf(p2p_soc_obj, tx_cnf_event->nbuf);
3406 qdf_nbuf_free(tx_cnf_event->nbuf);
3407 if (!tx_ctx) {
3408 p2p_err("can't find tx_ctx, tx ack comes late");
3409 return QDF_STATUS_SUCCESS;
3410 }
3411
3412 /* disable tx timer */
3413 p2p_disable_tx_timer(tx_ctx);
3414 tx_cnf.vdev_id = tx_ctx->vdev_id;
3415 tx_cnf.action_cookie = (uint64_t)tx_ctx->id;
3416 tx_cnf.buf = tx_ctx->buf;
3417 tx_cnf.buf_len = tx_ctx->buf_len;
3418 tx_cnf.status = tx_cnf_event->status;
3419
3420 p2p_debug("soc:%pK, vdev_id:%d, action_cookie:%llx, len:%d, status:%d, buf:%pK",
3421 p2p_soc_obj->soc, tx_cnf.vdev_id,
3422 tx_cnf.action_cookie, tx_cnf.buf_len,
3423 tx_cnf.status, tx_cnf.buf);
3424
3425 p2p_rand_mac_tx_done(p2p_soc_obj->soc, tx_ctx);
3426
3427 start_param = p2p_soc_obj->start_param;
3428 if (start_param->tx_cnf_cb)
3429 start_param->tx_cnf_cb(start_param->tx_cnf_cb_data,
3430 &tx_cnf);
3431 else
3432 p2p_debug("Got tx conf, but no valid up layer callback");
3433
3434 p2p_remove_tx_context(tx_ctx);
3435
3436 return QDF_STATUS_SUCCESS;
3437 }
3438
3439 #define P2P_IS_SOCIAL_CHANNEL(center_freq) \
3440 (((center_freq) == 2412) || ((center_freq) == 2437) || \
3441 ((center_freq) == 2462))
3442
p2p_process_rx_mgmt(struct p2p_rx_mgmt_event * rx_mgmt_event)3443 QDF_STATUS p2p_process_rx_mgmt(
3444 struct p2p_rx_mgmt_event *rx_mgmt_event)
3445 {
3446 struct p2p_rx_mgmt_frame *rx_mgmt;
3447 struct p2p_soc_priv_obj *p2p_soc_obj;
3448 struct p2p_start_param *start_param;
3449 struct p2p_frame_info frame_info;
3450 uint8_t *mac_from;
3451
3452 p2p_soc_obj = rx_mgmt_event->p2p_soc_obj;
3453 rx_mgmt = rx_mgmt_event->rx_mgmt;
3454
3455 if (!p2p_soc_obj || !(p2p_soc_obj->start_param)) {
3456 p2p_err("Invalid psoc object or start parameters");
3457 qdf_mem_free(rx_mgmt);
3458 return QDF_STATUS_E_INVAL;
3459 }
3460
3461 p2p_debug("soc:%pK, frame_len:%d, rx_freq:%d, vdev_id:%d, frm_type:%d, rx_rssi:%d, buf:%pK",
3462 p2p_soc_obj->soc, rx_mgmt->frame_len,
3463 rx_mgmt->rx_freq, rx_mgmt->vdev_id, rx_mgmt->frm_type,
3464 rx_mgmt->rx_rssi, rx_mgmt->buf);
3465
3466 if (rx_mgmt->frm_type == MGMT_ACTION_VENDOR_SPECIFIC) {
3467 p2p_get_frame_info(rx_mgmt->buf, rx_mgmt->frame_len,
3468 &frame_info);
3469
3470 /* update P2P connection status with rx frame info */
3471 mac_from = &(rx_mgmt->buf[SRC_MAC_ADDR_OFFSET]);
3472 p2p_rx_update_connection_status(p2p_soc_obj,
3473 &frame_info, mac_from);
3474
3475 p2p_debug("action_sub_type %u, action_type %d",
3476 frame_info.public_action_type,
3477 frame_info.action_type);
3478
3479 if ((frame_info.public_action_type ==
3480 P2P_PUBLIC_ACTION_NOT_SUPPORT) &&
3481 (frame_info.action_type ==
3482 P2P_ACTION_NOT_SUPPORT)) {
3483 p2p_debug("non-p2p frame, drop it");
3484 qdf_mem_free(rx_mgmt);
3485 return QDF_STATUS_SUCCESS;
3486 } else {
3487 p2p_debug("p2p frame, extend roc accordingly");
3488 p2p_extend_roc_timer(p2p_soc_obj, &frame_info);
3489 }
3490
3491 if (frame_info.public_action_type ==
3492 P2P_PUBLIC_ACTION_NEG_REQ &&
3493 wlan_reg_is_24ghz_ch_freq(rx_mgmt->rx_freq) &&
3494 !P2P_IS_SOCIAL_CHANNEL(rx_mgmt->rx_freq)) {
3495 p2p_debug("Drop P2P Negotiation Req due to non-Social channel: %d",
3496 rx_mgmt->rx_freq);
3497 qdf_mem_free(rx_mgmt);
3498 return QDF_STATUS_SUCCESS;
3499 }
3500 }
3501
3502 if (rx_mgmt->frm_type == MGMT_ACTION_CATEGORY_VENDOR_SPECIFIC)
3503 p2p_get_frame_info(rx_mgmt->buf, rx_mgmt->frame_len,
3504 &frame_info);
3505
3506 start_param = p2p_soc_obj->start_param;
3507 if (start_param->rx_cb)
3508 start_param->rx_cb(start_param->rx_cb_data, rx_mgmt);
3509 else
3510 p2p_debug("rx mgmt, but no valid up layer callback");
3511
3512 qdf_mem_free(rx_mgmt);
3513
3514 return QDF_STATUS_SUCCESS;
3515 }
3516