1 /*
2 * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
3 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include "iot_sim_cmn_api_i.h"
19 #include "iot_sim_defs_i.h"
20 #include "wlan_iot_sim_tgt_api.h"
21 #include <qdf_mem.h>
22 #include <qdf_types.h>
23 #include <qdf_util.h>
24 #include <qdf_str.h>
25 #include <qdf_delayed_work.h>
26 #include <wmi_unified_param.h>
27 #include <wlan_iot_sim_utils_api.h>
28 #include <wlan_lmac_if_api.h>
29 #include <wlan_objmgr_peer_obj.h>
30
31 /*
32 * iot_sim_oper_to_str - function to return iot sim operation string
33 * @oper: iot sim operation
34 *
35 * Return: string pointer
36 */
37 uint8_t *
iot_sim_oper_to_str(enum iot_sim_operations oper)38 iot_sim_oper_to_str(enum iot_sim_operations oper)
39 {
40 switch (oper) {
41 case CONTENT_CHANGE:
42 return "content change";
43 case DELAY:
44 return "delay";
45 case DROP:
46 return "drop";
47 default:
48 return "invalid";
49 }
50 }
51
52 /*
53 * iot_sim_convert_offset_to_hex_str - function to convert offset into binary
54 * @offset: user provided offset value while action frame rule deletion
55 * @hex: buffer to store converted value
56 * @count: size of hex buffer
57 *
58 * Return: string pointer
59 */
60 QDF_STATUS
iot_sim_convert_offset_to_hex_str(uint16_t offset,uint8_t * hex,int8_t count)61 iot_sim_convert_offset_to_hex_str(uint16_t offset, uint8_t *hex, int8_t count)
62 {
63 uint8_t temp[5];
64 int ret;
65
66 snprintf(temp, sizeof(temp), "%04u", offset);
67
68 ret = qdf_hex_str_to_binary(hex, temp, count);
69 if (ret == -1) {
70 iot_sim_err("offset to hex conversion failed");
71 return QDF_STATUS_E_FAILURE;
72 }
73
74 return QDF_STATUS_SUCCESS;
75 }
76
77 /*
78 * iot_sim_parse_action_frame - function to parse action frame to decode
79 * category and action code
80 *
81 * @length: length for content provided by user
82 * @offset: offset provided by user
83 * @content: user provided content
84 * @category: buffer to store iot specific category code
85 * @action: buffer to store iot specific action code
86 *
87 * Return: QDF_STATUS_SUCCESS on success otherwise failure
88 */
89 QDF_STATUS
iot_sim_parse_action_frame(uint16_t length,uint16_t offset,uint8_t * content,uint8_t * category,uint8_t * action)90 iot_sim_parse_action_frame(uint16_t length, uint16_t offset, uint8_t *content,
91 uint8_t *category, uint8_t *action)
92 {
93 QDF_STATUS status = QDF_STATUS_SUCCESS;
94 uint8_t hex[2], *ptr = NULL;
95
96 if (!length) {
97 status = iot_sim_convert_offset_to_hex_str(offset, hex,
98 sizeof(hex));
99 if (QDF_IS_STATUS_ERROR(status))
100 return status;
101
102 /* Offset represet category type and action type */
103 status = iot_sim_get_index_for_action_frm(hex, category,
104 action, false);
105 if (status == QDF_STATUS_E_FAULT) {
106 iot_sim_err("Get indices for action failed");
107 return status;
108 }
109 } else if (length && content) {
110 /* if offset is zero, move ptr post header */
111 if (offset == 0) {
112 ptr = content + sizeof(struct ieee80211_frame);
113 } else if (offset == sizeof(struct ieee80211_frame)) {
114 ptr = content;
115 } else {
116 iot_sim_err("wrong offset for action frame content");
117 return QDF_STATUS_E_FAILURE;
118 }
119 status = iot_sim_get_index_for_action_frm(ptr, category,
120 action, false);
121 }
122 return status;
123 }
124
125 /*
126 * iot_sim_find_peer_from_mac - function to find the iot sim peer data
127 * based on the mac address provided
128 *
129 * @isc: iot_sim pdev private object
130 * @mac: mac address of the peer
131 *
132 * Return: iot_sim_rule_per_peer reference if exists else NULL
133 */
134 struct iot_sim_rule_per_peer *
iot_sim_find_peer_from_mac(struct iot_sim_context * isc,struct qdf_mac_addr * mac)135 iot_sim_find_peer_from_mac(struct iot_sim_context *isc,
136 struct qdf_mac_addr *mac)
137 {
138 struct iot_sim_rule_per_peer *peer_rule = NULL;
139 qdf_list_node_t *node = NULL, *next_node = NULL;
140
141 if (qdf_is_macaddr_zero(mac) || qdf_is_macaddr_broadcast(mac))
142 return &isc->bcast_peer;
143 else {
144 if (qdf_list_empty(&isc->peer_list)) {
145 iot_sim_debug("peer_list empty");
146 return NULL;
147 }
148
149 qdf_spin_lock_bh(&isc->iot_sim_lock);
150 if (QDF_STATUS_SUCCESS !=
151 qdf_list_peek_front(&isc->peer_list, &next_node)) {
152 qdf_spin_unlock_bh(&isc->iot_sim_lock);
153 iot_sim_err("Failed to get peer rule from peer_list");
154 return NULL;
155 }
156
157 do {
158 node = next_node;
159 peer_rule =
160 qdf_container_of(node,
161 struct iot_sim_rule_per_peer,
162 node);
163 if (qdf_is_macaddr_equal(&peer_rule->addr, mac)) {
164 qdf_spin_unlock_bh(&isc->iot_sim_lock);
165 return peer_rule;
166 }
167 } while (QDF_STATUS_SUCCESS ==
168 qdf_list_peek_next(&isc->peer_list, node, &next_node));
169
170 qdf_spin_unlock_bh(&isc->iot_sim_lock);
171 iot_sim_debug("Failed to find peer");
172 }
173
174 return NULL;
175 }
176
177 /*
178 * iot_sim_add_peer - function to add the iot sim peer data
179 *
180 * @isc: iot_sim pdev private object
181 * @mac: mac address of the peer
182 *
183 * Return: iot_sim_rule_per_peer reference
184 */
185 struct iot_sim_rule_per_peer *
iot_sim_add_peer(struct iot_sim_context * isc,struct qdf_mac_addr * mac)186 iot_sim_add_peer(struct iot_sim_context *isc, struct qdf_mac_addr *mac)
187 {
188 struct iot_sim_rule_per_peer *peer_rule = NULL;
189 QDF_STATUS status;
190
191 if (qdf_is_macaddr_zero(mac) || qdf_is_macaddr_broadcast(mac)) {
192 iot_sim_err("called iot_sim_add_peer for broadcast address");
193 return &isc->bcast_peer;
194 }
195
196 qdf_spin_lock_bh(&isc->iot_sim_lock);
197 if (qdf_list_size(&isc->peer_list) < MAX_PEER_COUNT) {
198 peer_rule = qdf_mem_malloc(sizeof
199 (struct iot_sim_rule_per_peer));
200 if (!peer_rule) {
201 iot_sim_err("Memory alloc failed for peer: "
202 QDF_MAC_ADDR_FMT,
203 QDF_MAC_ADDR_REF(mac->bytes));
204 goto rel_lock;
205 }
206
207 qdf_copy_macaddr(&peer_rule->addr, mac);
208 status = qdf_list_insert_back(&isc->peer_list,
209 &peer_rule->node);
210 if (QDF_IS_STATUS_ERROR(status)) {
211 iot_sim_err("peer_list enqueue failed for peer "
212 QDF_MAC_ADDR_FMT,
213 QDF_MAC_ADDR_REF(mac->bytes));
214 qdf_mem_free(peer_rule);
215 peer_rule = NULL;
216 }
217 } else {
218 iot_sim_err("peer_list already reached max limit");
219 }
220
221 rel_lock:
222 qdf_spin_unlock_bh(&isc->iot_sim_lock);
223 return peer_rule;
224 }
225
226 /*
227 * iot_sim_remove_peer - function to remove the iot sim peer data
228 *
229 * @isc: iot_sim pdev private object
230 * @mac: mac address of the peer
231 *
232 * Return: void
233 */
iot_sim_remove_peer(struct iot_sim_context * isc,struct iot_sim_rule_per_peer * peer_rule)234 void iot_sim_remove_peer(struct iot_sim_context *isc,
235 struct iot_sim_rule_per_peer *peer_rule)
236 {
237 qdf_spin_lock_bh(&isc->iot_sim_lock);
238 qdf_list_remove_node(&isc->peer_list, &peer_rule->node);
239 qdf_spin_unlock_bh(&isc->iot_sim_lock);
240 }
241
242 /*
243 * iot_sim_validate_content - function to validate frame content. User provided
244 * content must be either full frame or full frame
245 * body or valid TLV formatted data.
246 * @buf: pointer to frame content in binary format
247 * @total_len: length of content
248 * @offset: offset provided by user
249 *
250 * Return: QDF_STATUS_SUCCESS on success
251 * QDF_STATUS_E_FAULT on failure
252 */
253 static QDF_STATUS
iot_sim_validate_content(uint8_t * buf,uint16_t total_len,uint16_t offset)254 iot_sim_validate_content(uint8_t *buf,
255 uint16_t total_len,
256 uint16_t offset)
257 {
258 char *ie = buf;
259 uint32_t len = 0, i = 0;
260 uint32_t fb = sizeof(struct ieee80211_frame);
261
262 if (offset == 0 || offset == fb) {
263 /* Replace the entire content set by user */
264 return QDF_STATUS_SUCCESS;
265 }
266
267 /* Check for malformed IEs and proper IE
268 * boundaries in user content
269 */
270 for (i = 0; i < total_len;) {
271 /* TLV: T(1) + L(1) + V(L)*/
272 len = (1 + 1 + ie[1]);
273 i += len;
274 ie += len;
275 }
276
277 if (i == total_len)
278 return QDF_STATUS_SUCCESS;
279
280 iot_sim_err("iot_sim: cnt(bin) len:%u IE Parsed len:%u",
281 total_len,
282 i);
283
284 return QDF_STATUS_E_INVAL;
285 }
286
287 /*
288 * iot_sim_handle_frame_content - function to process frame content provided
289 * by user. This function will convert the ascii
290 * string into binary string and validate the
291 * content.
292 * @isc: iot sim context
293 * @pos: position to the frame content in the user buffer
294 * @storage: storage to store frame content after processing
295 * @offset: user provided offset
296 * @len: length of the user provided content in bytes
297 *
298 * Return: QDF_STATUS_SUCCESS on success
299 * QDF_STATUS_E_FAULT on hex str to binary conversion failure
300 * QDF_STATUS_E_NOMEM on memory allocation failure
301 */
302 QDF_STATUS
iot_sim_handle_frame_content(struct iot_sim_context * isc,const char * pos,uint8_t ** storage,uint16_t offset,uint16_t len)303 iot_sim_handle_frame_content(struct iot_sim_context *isc,
304 const char *pos,
305 uint8_t **storage,
306 uint16_t offset,
307 uint16_t len)
308 {
309 QDF_STATUS status = QDF_STATUS_E_FAILURE;
310 int ret;
311
312 *storage = qdf_mem_malloc(len);
313 if (!*storage) {
314 iot_sim_err("iot_sim:storage allocation failed");
315 return QDF_STATUS_E_NOMEM;
316 }
317
318 ret = qdf_hex_str_to_binary(*storage, pos, len);
319 if (ret == -1) {
320 iot_sim_err("iot_sim:hex2bin conversion failed");
321 status = QDF_STATUS_E_FAULT;
322 goto error;
323 }
324
325 status = iot_sim_validate_content(*storage, len, offset);
326 if (QDF_IS_STATUS_ERROR(status)) {
327 iot_sim_err("iot_sim:User Content Invalid");
328 goto error;
329 }
330
331 return QDF_STATUS_SUCCESS;
332
333 error:
334 qdf_mem_free(*storage);
335 *storage = NULL;
336 return status;
337 }
338
339 /*
340 * iot_sim_parse_user_input_content_change - function to parse user input into
341 * predefined format for content
342 * change operation. All arguments
343 * passed will be filled upon success
344 * @isc: iot sim context
345 * @userbuf: local copy of user input
346 * @count: length of userbuf
347 * @t_st: address of type variable
348 * @seq: address of seq variable
349 * @offset: address of offset variable
350 * @length: address of length variable
351 * @content: double pointer to storage to store frame content after processing
352 * @addr: pointer to mac address
353 *
354 * @storage: storage to store frame content after processing
355 * @offset: user provided offset
356 * @len: length of the user provided content in bytes
357 *
358 * Return: QDF_STATUS_SUCCESS on success
359 * QDF_STATUS_E_FAILURE otherwise
360 */
361 QDF_STATUS
iot_sim_parse_user_input_content_change(struct iot_sim_context * isc,char * userbuf,ssize_t count,uint8_t * t_st,uint16_t * seq,uint16_t * offset,uint16_t * length,uint8_t ** content,struct qdf_mac_addr * addr)362 iot_sim_parse_user_input_content_change(struct iot_sim_context *isc,
363 char *userbuf, ssize_t count,
364 uint8_t *t_st, uint16_t *seq,
365 uint16_t *offset, uint16_t *length,
366 uint8_t **content,
367 struct qdf_mac_addr *addr)
368 {
369 QDF_STATUS status = QDF_STATUS_E_FAILURE;
370 char *argv[6], *delim = " ", *substr;
371 int argc = -1, ret = 0;
372
373 qdf_mem_zero(argv, sizeof(argv));
374 userbuf = qdf_str_trim(userbuf);
375
376 while ((substr = qdf_str_sep(&userbuf, delim)) != NULL) {
377 if (!isspace(*substr) && *substr != '\0')
378 argv[++argc] = substr;
379 if (argc >= 5)
380 break;
381 }
382
383 if (argc < 3) {
384 iot_sim_err("Invalid argument count %d", (argc + 1));
385 return status;
386 }
387
388 if (!argv[0] || !argv[1] || !argv[2] || !argv[3]) {
389 iot_sim_err("One or more arguments are null");
390 return status;
391 }
392
393 ret = kstrtou8(argv[0], 16, t_st);
394 if (ret)
395 goto err;
396 ret = kstrtou16(argv[1], 10, seq);
397 if (ret)
398 goto err;
399 ret = kstrtou16(argv[2], 10, offset);
400 if (ret)
401 goto err;
402 ret = kstrtou16(argv[3], 10, length);
403 if (ret)
404 goto err;
405 /*
406 * User can send content change data in following format:
407 * 1. Add rule for specific peer
408 * <t_st> <seq> <offset> <length> <content> <MAC>
409 * 2. Add rule for broadcast peer
410 * <t_st> <seq> <offset> <length> <content>
411 * 3. Remove rule for specific peer
412 * <t_st> <seq> <offset> <length> <MAC>
413 * 4. Remove rule for broadcast peer
414 * <t_st> <seq> <offset> <length>
415 */
416
417 /*
418 * If length is 0, this implies remove the rule
419 */
420 if (!*length) {
421 /*
422 * 1. Ignore the frame content
423 * 2. argv[4] is not null, then it must be a valid mac
424 * If argv[4] is null, then set 'addr' as null
425 */
426 *content = NULL;
427 if (argv[4]) {
428 status = qdf_mac_parse(argv[4], addr);
429 if (QDF_IS_STATUS_ERROR(status))
430 iot_sim_err("iot_sim: argv4 is invalid mac for 0 len");
431 } else {
432 qdf_mem_zero(addr, QDF_MAC_ADDR_SIZE);
433 status = QDF_STATUS_SUCCESS;
434 }
435 /*
436 * No need to parse further just return.
437 */
438 return status;
439 }
440
441 /*
442 * If argv[4] is valid, this implies frame content
443 */
444 if (argv[4]) {
445 status = iot_sim_handle_frame_content(isc, argv[4],
446 content, *offset,
447 *length);
448 if (QDF_IS_STATUS_ERROR(status))
449 return status;
450 }
451
452 /*
453 * If argv[5] is valid, this must be mac address
454 */
455 if (argv[5]) {
456 status = qdf_mac_parse(argv[5], addr);
457 if (QDF_IS_STATUS_ERROR(status))
458 qdf_mem_free(content);
459 }
460
461 return status;
462 err:
463 iot_sim_err("kstrtoXX failed: %d", ret);
464 return status;
465 }
466
467 /*
468 * iot_sim_get_index_for_action_frm - function to convert 802.11 action frame
469 * category and action code into iot sim
470 * specific code.
471 *
472 * @frm: buf containing 802.11 action/category codes
473 * @cat_type: buf to hold converted category code
474 * @act_type: buf to hold converted action code
475 * @rx: TRUE if its getting called in the rx path
476 *
477 * Return: QDF_STATUS_SUCCESS on success, failure otherwise
478 */
479 QDF_STATUS
iot_sim_get_index_for_action_frm(uint8_t * frm,uint8_t * cat_type,uint8_t * act_type,bool rx)480 iot_sim_get_index_for_action_frm(uint8_t *frm, uint8_t *cat_type,
481 uint8_t *act_type, bool rx)
482 {
483 uint8_t category, action;
484
485 category = ((struct ieee80211_action *)(frm))->ia_category;
486 action = ((struct ieee80211_action *)(frm))->ia_action;
487
488 iot_sim_info("category %x action %x", category, action);
489
490 switch (category) {
491 case IEEE80211_ACTION_CAT_BA:
492 switch (action) {
493 case IEEE80211_ACTION_BA_ADDBA_REQUEST:
494 if (rx) {
495 *cat_type = CAT_BA;
496 *act_type = action;
497
498 } else {
499 *cat_type = category;
500 *act_type = action;
501 }
502 break;
503 case IEEE80211_ACTION_BA_ADDBA_RESPONSE:
504 case IEEE80211_ACTION_BA_DELBA:
505 *cat_type = CAT_BA;
506 *act_type = action;
507 break;
508 default:
509 return QDF_STATUS_E_FAULT;
510 }
511 break;
512 case IEEE80211_ACTION_CAT_SA_QUERY:
513 switch (action) {
514 case IEEE80211_ACTION_SA_QUERY_REQUEST:
515 case IEEE80211_ACTION_SA_QUERY_RESPONSE:
516 *cat_type = CAT_SA_QUERY;
517 *act_type = action;
518 break;
519 default:
520 return QDF_STATUS_E_FAULT;
521 }
522 break;
523 case IEEE80211_ACTION_CAT_RADIO:
524 *cat_type = CAT_RADIO;
525 *act_type = action;
526 break;
527 case IEEE80211_ACTION_CAT_FAST_BSS_TRNST:
528 *cat_type = CAT_FAST_BSS_TRNST;
529 *act_type = action;
530 break;
531 case IEEE80211_ACTION_CAT_SPECTRUM:
532 *cat_type = CAT_SPECTRUM;
533 *act_type = action;
534 break;
535 case IEEE80211_ACTION_CAT_QOS:
536 *cat_type = CAT_QOS;
537 *act_type = action;
538 break;
539 case IEEE80211_ACTION_CAT_DLS:
540 *cat_type = CAT_DLS;
541 *act_type = action;
542 break;
543 case IEEE80211_ACTION_CAT_HT:
544 *cat_type = CAT_HT;
545 *act_type = action;
546 break;
547 case IEEE80211_ACTION_CAT_WNM:
548 *cat_type = CAT_WNM;
549 *act_type = action;
550 break;
551 case IEEE80211_ACTION_CAT_VHT:
552 *cat_type = CAT_VHT;
553 *act_type = action;
554 break;
555 default:
556 return QDF_STATUS_E_FAULT;
557 }
558
559 return QDF_STATUS_SUCCESS;
560 }
561
562 /*
563 * iot_sim_action_frame_supported_by_fw - function to find if action frame is
564 * supported by fw or not
565 * @category: iot_sim specific category code
566 * @action: iot_sim specific action code
567 *
568 * Return: true if supported else false
569 */
570 bool
iot_sim_action_frame_supported_by_fw(uint8_t category,uint8_t action)571 iot_sim_action_frame_supported_by_fw(uint8_t category, uint8_t action)
572 {
573 switch (category) {
574 case IEEE80211_ACTION_CAT_BA:
575 switch (action) {
576 case IEEE80211_ACTION_BA_ADDBA_REQUEST:
577 return true;
578 default:
579 return false;
580 }
581 default:
582 return false;
583 }
584 }
585
586 /*
587 * iot_sim_frame_supported_by_fw - function to find if frame is supported by fw
588 * @type: 802.11 frame type
589 * @subtype: 802.11 frame subtype
590 *
591 * Return: true if supported else false
592 */
593 bool
iot_sim_frame_supported_by_fw(uint8_t type,uint8_t subtype,bool action)594 iot_sim_frame_supported_by_fw(uint8_t type, uint8_t subtype, bool action)
595 {
596 if (action)
597 return iot_sim_action_frame_supported_by_fw(type, subtype);
598
599 switch (type << IEEE80211_FC0_TYPE_SHIFT) {
600 case IEEE80211_FC0_TYPE_MGT:
601 switch (subtype << IEEE80211_FC0_SUBTYPE_SHIFT) {
602 case IEEE80211_FC0_SUBTYPE_BEACON:
603 return true;
604 default:
605 return false;
606 }
607 case IEEE80211_FC0_TYPE_CTL:
608 switch (subtype << IEEE80211_FC0_SUBTYPE_SHIFT) {
609 case IEEE80211_FC0_SUBTYPE_TRIGGER:
610 case IEEE80211_FC0_SUBTYPE_BAR:
611 case IEEE80211_FC0_SUBTYPE_CTS:
612 case IEEE80211_FC0_SUBTYPE_ACK:
613 case IEEE80211_FC0_SUBTYPE_NDPA:
614 return true;
615 default:
616 return false;
617 }
618 case IEEE80211_FC0_TYPE_DATA:
619 switch (subtype << IEEE80211_FC0_SUBTYPE_SHIFT) {
620 default:
621 return true;
622 }
623 default:
624 return false;
625 }
626 }
627
628 /*
629 * iot_sim_remap_type_subtype - function to convert rules for response
630 * type frame into request type. This is
631 * used for drop/delay operation. This function
632 * will update the passed type and subtype value.
633 *
634 * @type: 802.11 frame type
635 * @subtype: 802.11 frame subtype
636 * @seq: authentication sequence number, mostly 0 for non-authentication frame
637 * @action: flag to indicate action frame
638 *
639 * Return: QDF_STATUS_SUCCESS
640 */
641 QDF_STATUS
iot_sim_remap_type_subtype(uint8_t * type,uint8_t * subtype,uint16_t * seq,bool action)642 iot_sim_remap_type_subtype(uint8_t *type, uint8_t *subtype,
643 uint16_t *seq, bool action)
644 {
645 if (action) {
646 switch (*type) {
647 case CAT_BA:
648 switch (*subtype) {
649 case IEEE80211_ACTION_BA_ADDBA_RESPONSE:
650 *subtype = IEEE80211_ACTION_BA_ADDBA_REQUEST;
651 break;
652 default:
653 break;
654 }
655 break;
656 default:
657 break;
658 }
659 return QDF_STATUS_SUCCESS;
660 }
661
662 switch (*type << IEEE80211_FC0_TYPE_SHIFT) {
663 case IEEE80211_FC0_TYPE_MGT:
664 switch (*subtype << IEEE80211_FC0_SUBTYPE_SHIFT) {
665 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
666 *subtype = IEEE80211_FC0_SUBTYPE_ASSOC_REQ;
667 *subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
668 break;
669 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
670 *subtype = IEEE80211_FC0_SUBTYPE_REASSOC_REQ;
671 *subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
672 break;
673 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
674 *subtype = IEEE80211_FC0_SUBTYPE_PROBE_REQ;
675 *subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
676 break;
677 case IEEE80211_FC0_SUBTYPE_AUTH:
678 *subtype = IEEE80211_FC0_SUBTYPE_AUTH;
679 *subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
680 /* If auth response (auth seq num 2) is marked as
681 * drop, then drop the auth request (auth seq num 1)
682 */
683 if (*seq == IEEE80211_AUTH_OPEN_RESPONSE)
684 *seq = IEEE80211_AUTH_OPEN_REQUEST;
685 break;
686 default:
687 break;
688 }
689 default:
690 break;
691 }
692
693 return QDF_STATUS_SUCCESS;
694 }
695
696 /*
697 * iot_sim_send_rule_to_fw - function to send iot_sim rule to fw
698 *
699 * @isc: iot sim context
700 * @oper: iot sim operation
701 * @mac: peer mac address
702 * @type: 802.11 frame type
703 * @subtype: 802.11 frame subtype
704 * @seq: authentication sequence number, mostly 0 for non-authentication frame
705 * @offset: user provided offset
706 * @frm: user provided frame content
707 * @length: length of frm
708 * @action: flag to indicate action frame
709 * @drop: flag to indicate set drop rule
710 * @clear: flag to indicate set rule or clear
711 *
712 * Return: QDF_STATUS_SUCCESS
713 */
714 QDF_STATUS
iot_sim_send_rule_to_fw(struct iot_sim_context * isc,enum iot_sim_operations oper,struct qdf_mac_addr * mac,uint8_t type,uint8_t subtype,uint16_t seq,uint16_t offset,uint8_t * frm,uint16_t len,bool action,bool clear)715 iot_sim_send_rule_to_fw(struct iot_sim_context *isc,
716 enum iot_sim_operations oper,
717 struct qdf_mac_addr *mac,
718 uint8_t type, uint8_t subtype,
719 uint16_t seq, uint16_t offset,
720 uint8_t *frm, uint16_t len,
721 bool action, bool clear)
722 {
723 struct simulation_test_params param;
724
725 if (oper != DELAY && FRAME_TYPE_IS_BEACON(type, subtype) && offset) {
726 iot_sim_info("Beacon update from offset:%d", offset);
727 return QDF_STATUS_E_NOSUPPORT;
728 }
729
730 if (iot_sim_frame_supported_by_fw(type, subtype, action)) {
731 qdf_mem_zero(¶m, sizeof(struct simulation_test_params));
732 param.pdev_id = wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj);
733 qdf_mem_copy(param.peer_mac, mac, QDF_MAC_ADDR_SIZE);
734 param.test_cmd_type = oper;
735 /* subtype_cmd: Set subcmd based on action and clear flag */
736 if (action) {
737 if (clear)
738 param.test_subcmd_type = DEL_RULE_ACTION;
739 else
740 param.test_subcmd_type = ADD_RULE_ACTION;
741 } else {
742 if (clear)
743 param.test_subcmd_type = DEL_RULE;
744 else
745 param.test_subcmd_type = ADD_RULE;
746 }
747 param.frame_type = type;
748 param.frame_subtype = subtype;
749 param.seq = seq;
750 param.offset = offset;
751 param.frame_length = len;
752 param.buf_len = len;
753 param.bufp = frm;
754 if (QDF_IS_STATUS_ERROR(tgt_send_simulation_cmd(isc->pdev_obj,
755 ¶m)))
756 iot_sim_err("Sending del rule to fw failed!");
757
758 if (FRAME_TYPE_IS_BEACON(type, subtype) && clear)
759 return QDF_STATUS_E_NOSUPPORT;
760
761 return QDF_STATUS_SUCCESS;
762 }
763
764 return QDF_STATUS_E_NOSUPPORT;
765 }
766
767 /*
768 * iot_sim_del_rule - function to delete iot_sim rule
769 *
770 * @s_e: address of seq for which rule to be removed
771 * @f_e: address of the rule present in s_e to be removed
772 * @oper: iot sim operation
773 *
774 * Return: QDF_STATUS_SUCCESS
775 */
776 QDF_STATUS
iot_sim_del_rule(struct iot_sim_rule_per_seq ** s_e,struct iot_sim_rule ** f_e,enum iot_sim_operations oper,struct iot_sim_context * isc)777 iot_sim_del_rule(struct iot_sim_rule_per_seq **s_e,
778 struct iot_sim_rule **f_e,
779 enum iot_sim_operations oper,
780 struct iot_sim_context *isc)
781 {
782 if (oper == CONTENT_CHANGE) {
783 qdf_mem_free((*f_e)->frm_content);
784 (*f_e)->frm_content = NULL;
785 } else if (oper == DROP) {
786 (*f_e)->drop = false;
787 } else if (oper == DELAY) {
788 if (!qdf_delayed_work_stop((*f_e)->dwork)) {
789 iot_sim_err("delayed work is in running state");
790 /* iot_sim_lock need to be released for the delay */
791 /* work callback to complete execution */
792 /* Hence releasing the lock */
793 qdf_spin_unlock_bh(&isc->iot_sim_lock);
794 /* iot_sim_delay_lock will be freed only after delay */
795 /* work callback execution completion */
796 qdf_spin_lock_bh(&(*f_e)->iot_sim_delay_lock);
797 qdf_spin_lock_bh(&isc->iot_sim_lock);
798 qdf_delayed_work_stop_sync((*f_e)->dwork);
799 qdf_spin_unlock_bh(&(*f_e)->iot_sim_delay_lock);
800 }
801
802 qdf_delayed_work_destroy((*f_e)->dwork);
803 qdf_spinlock_destroy(&(*f_e)->iot_sim_delay_lock);
804 qdf_mem_free((*f_e)->dwork->context);
805 qdf_mem_free((*f_e)->dwork);
806 qdf_nbuf_free((*f_e)->nbuf_list[0]);
807 (*f_e)->nbuf_list[0] = NULL;
808 if ((*f_e)->peer) {
809 wlan_objmgr_peer_release_ref((*f_e)->peer,
810 WLAN_IOT_SIM_ID);
811 (*f_e)->peer = NULL;
812 }
813 qdf_nbuf_free((*f_e)->nbuf_list[1]);
814 (*f_e)->nbuf_list[1] = NULL;
815 (*f_e)->sec_buf = NULL;
816 qdf_mem_free((*f_e)->rx_param);
817 (*f_e)->rx_param = NULL;
818 }
819
820 if (qdf_test_bit(oper, (unsigned long *)
821 &(*f_e)->rule_bitmap)) {
822 (*s_e)->use_count--;
823 qdf_clear_bit(oper, (unsigned long *)
824 &(*f_e)->rule_bitmap);
825 }
826
827 if (!(*f_e)->rule_bitmap) {
828 qdf_mem_free(*f_e);
829 *f_e = NULL;
830 }
831 if ((*s_e)->use_count == 0) {
832 qdf_mem_free(*s_e);
833 *s_e = NULL;
834 }
835 return QDF_STATUS_SUCCESS;
836 }
837
838 /*
839 * iot_sim_delete_rule_for_mac - function to delete content change rule
840 * for given peer mac
841 * @isc: iot sim context
842 * @oper: iot sim operation
843 * @seq: authentication sequence number, mostly 0 for non-authentication frame
844 * @type: 802.11 frame type
845 * @subtype: 802.11 frame subtype
846 * @mac: peer mac address
847 * @action: action frame or not
848 *
849 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE otherwise
850 */
851 QDF_STATUS
iot_sim_delete_rule_for_mac(struct iot_sim_context * isc,enum iot_sim_operations oper,uint16_t seq,uint8_t type,uint8_t subtype,struct qdf_mac_addr * mac,bool action)852 iot_sim_delete_rule_for_mac(struct iot_sim_context *isc,
853 enum iot_sim_operations oper,
854 uint16_t seq, uint8_t type,
855 uint8_t subtype,
856 struct qdf_mac_addr *mac,
857 bool action)
858 {
859 QDF_STATUS status = QDF_STATUS_SUCCESS;
860 struct iot_sim_rule_per_seq **s_e;
861 struct iot_sim_rule **f_e;
862 struct iot_sim_rule_per_peer *peer;
863 bool peer_remove = 1, broadcast_peer = 0;
864 uint8_t i;
865
866 if (qdf_is_macaddr_zero(mac))
867 iot_sim_info("Rule deletion for all peers");
868 else
869 iot_sim_info("Rule deletion for " QDF_MAC_ADDR_FMT,
870 QDF_MAC_ADDR_REF(mac->bytes));
871
872 iot_sim_debug("oper:%s seq: %hu %s:%hu/%hu",
873 iot_sim_oper_to_str(oper), seq,
874 action ? "category/action code" : "type/subtype",
875 type, subtype);
876
877 if (!isc) {
878 iot_sim_err("iot_sim: isc is null");
879 return QDF_STATUS_E_FAILURE;
880 }
881
882 if (oper == DROP || oper == DELAY)
883 iot_sim_remap_type_subtype(&type, &subtype, &seq, action);
884
885 if (qdf_is_macaddr_zero(mac) || qdf_is_macaddr_broadcast(mac)) {
886 peer = &isc->bcast_peer;
887 broadcast_peer = 1;
888 } else
889 peer = iot_sim_find_peer_from_mac(isc, mac);
890 if (peer) {
891 qdf_spin_lock_bh(&isc->iot_sim_lock);
892 s_e = &peer->rule_per_seq[seq];
893 if (!*s_e) {
894 qdf_spin_unlock_bh(&isc->iot_sim_lock);
895 return QDF_STATUS_SUCCESS;
896 }
897
898 if (action)
899 f_e = &((*s_e)->rule_per_action_frm[type][subtype]);
900 else
901 f_e = &((*s_e)->rule_per_type[type][subtype]);
902
903 if (*f_e)
904 status = iot_sim_del_rule(s_e, f_e, oper, isc);
905
906 for (i = 0; i < MAX_SEQ; i++)
907 if (peer->rule_per_seq[i])
908 peer_remove = 0;
909 qdf_spin_unlock_bh(&isc->iot_sim_lock);
910 if (!broadcast_peer && peer_remove) {
911 iot_sim_remove_peer(isc, peer);
912 qdf_mem_free(peer);
913 }
914 }
915
916 return status;
917 }
918
919 /*
920 * iot_sim_delay_cb - Delayed work callback function
921 * to process delayed frames
922 *
923 * @context: Delayed work callback context
924 *
925 * Return: void
926 */
iot_sim_delay_cb(void * ctxt)927 static void iot_sim_delay_cb(void *ctxt)
928 {
929 struct wlan_objmgr_psoc *psoc = NULL;
930 struct iot_sim_cb_context *context = ctxt;
931 uint8_t *buf;
932 struct ieee80211_frame *wh;
933 struct qdf_mac_addr *mac_addr;
934 struct mgmt_rx_event_params *param = context->piot_sim_rule->rx_param;
935 struct wlan_objmgr_peer **peer = &context->piot_sim_rule->peer;
936
937 qdf_spin_lock_bh(&context->piot_sim_rule->iot_sim_delay_lock);
938 qdf_spin_lock_bh(&context->isc->iot_sim_lock);
939 psoc = wlan_pdev_get_psoc(context->isc->pdev_obj);
940 context->piot_sim_rule->sec_buf = context->piot_sim_rule->nbuf_list[0];
941 qdf_spin_unlock_bh(&context->isc->iot_sim_lock);
942 mgmt_txrx_rx_handler(psoc, context->piot_sim_rule->sec_buf,
943 context->piot_sim_rule->rx_param);
944 qdf_spin_lock_bh(&context->isc->iot_sim_lock);
945 if (*peer) {
946 wlan_objmgr_peer_release_ref(*peer, WLAN_IOT_SIM_ID);
947 *peer = NULL;
948 }
949 if (context->piot_sim_rule->nbuf_list[1]) {
950 context->piot_sim_rule->nbuf_list[0] =
951 context->piot_sim_rule->nbuf_list[1];
952 buf = qdf_nbuf_data(context->piot_sim_rule->nbuf_list[0]);
953 wh = (struct ieee80211_frame *)buf;
954 mac_addr = (struct qdf_mac_addr *)wh->i_addr2;
955 *peer = wlan_objmgr_get_peer(psoc, param->pdev_id,
956 (uint8_t *)mac_addr,
957 WLAN_IOT_SIM_ID);
958
959 if (!qdf_delayed_work_start(context->piot_sim_rule->dwork,
960 context->
961 piot_sim_rule->delay_dur)) {
962 iot_sim_err("delayed_work_start failed");
963 qdf_nbuf_free(context->piot_sim_rule->nbuf_list[0]);
964 if (*peer) {
965 wlan_objmgr_peer_release_ref(*peer,
966 WLAN_IOT_SIM_ID);
967 *peer = NULL;
968 }
969 qdf_mem_free(context->piot_sim_rule->
970 rx_param->rx_params);
971 qdf_mem_free(context->piot_sim_rule->rx_param);
972 context->piot_sim_rule->nbuf_list[0] = NULL;
973 context->piot_sim_rule->rx_param = NULL;
974 }
975 context->piot_sim_rule->nbuf_list[1] = NULL;
976 } else {
977 context->piot_sim_rule->nbuf_list[0] = NULL;
978 qdf_mem_free(context->piot_sim_rule->rx_param->rx_params);
979 qdf_mem_free(context->piot_sim_rule->rx_param);
980 context->piot_sim_rule->rx_param = NULL;
981 }
982
983 qdf_spin_unlock_bh(&context->isc->iot_sim_lock);
984 qdf_spin_unlock_bh(&context->piot_sim_rule->iot_sim_delay_lock);
985 }
986
987 /*
988 * iot_sim_add_rule - function to add iot_sim rule
989 *
990 * @s_e: address of seq for which rule to be added
991 * @f_e: address of the rule present in s_e to be added
992 * @oper: iot sim operation
993 * @frm: user provided frame content
994 * @offset: user provided offset
995 * @len: length of the user provided frame content
996 * @isc: iot sim context
997 *
998 * Return: QDF_STATUS_SUCCESS
999 */
1000 QDF_STATUS
iot_sim_add_rule(struct iot_sim_rule_per_seq ** s_e,struct iot_sim_rule ** f_e,enum iot_sim_operations oper,uint8_t * frm,uint16_t offset,uint16_t len,struct iot_sim_context * isc)1001 iot_sim_add_rule(struct iot_sim_rule_per_seq **s_e,
1002 struct iot_sim_rule **f_e,
1003 enum iot_sim_operations oper,
1004 uint8_t *frm, uint16_t offset, uint16_t len,
1005 struct iot_sim_context *isc)
1006 {
1007 struct iot_sim_cb_context *cb_context;
1008
1009 if (!*f_e) {
1010 *f_e = qdf_mem_malloc(sizeof(struct iot_sim_rule));
1011 if (!*f_e) {
1012 iot_sim_err("can't allocate f_e");
1013 return QDF_STATUS_E_NOMEM;
1014 }
1015 }
1016
1017 if (oper == CONTENT_CHANGE) {
1018 (*f_e)->frm_content = qdf_mem_malloc(len);
1019 if (!((*f_e)->frm_content))
1020 return QDF_STATUS_E_NOMEM;
1021 qdf_mem_copy((*f_e)->frm_content, frm, len);
1022 (*f_e)->len = len;
1023 (*f_e)->offset = offset;
1024 } else if (oper == DROP) {
1025 (*f_e)->drop = true;
1026 } else if (oper == DELAY) {
1027 (*f_e)->delay_dur = offset;
1028 (*f_e)->dwork = qdf_mem_malloc(sizeof(struct qdf_delayed_work));
1029 if (!(*f_e)->dwork) {
1030 iot_sim_err("can't allocate dwork");
1031 return QDF_STATUS_E_NOMEM;
1032 }
1033
1034 cb_context = qdf_mem_malloc(sizeof(struct iot_sim_cb_context));
1035 if (!cb_context) {
1036 iot_sim_err("can't allocate cb_context");
1037 qdf_mem_free((*f_e)->dwork);
1038 return QDF_STATUS_E_NOMEM;
1039 }
1040
1041 cb_context->isc = isc;
1042 cb_context->piot_sim_rule = *f_e;
1043 if (QDF_STATUS_SUCCESS !=
1044 qdf_delayed_work_create((*f_e)->dwork, iot_sim_delay_cb,
1045 cb_context)) {
1046 iot_sim_err("delayed_work_create failed");
1047 qdf_mem_free(cb_context);
1048 qdf_mem_free((*f_e)->dwork);
1049 return QDF_STATUS_E_NOMEM;
1050 }
1051
1052 (*f_e)->nbuf_list[0] = NULL;
1053 (*f_e)->nbuf_list[1] = NULL;
1054 (*f_e)->peer = NULL;
1055 iot_sim_err("delayed_work_created");
1056 qdf_spinlock_create(&((*f_e)->iot_sim_delay_lock));
1057 }
1058
1059 (*s_e)->use_count++;
1060 qdf_set_bit(oper, (unsigned long *)
1061 &(*f_e)->rule_bitmap);
1062
1063 return QDF_STATUS_SUCCESS;
1064 }
1065
1066 /*
1067 * iot_sim_add_rule_for_mac - function to add content change rule
1068 * for given peer mac
1069 * @isc: iot sim context
1070 * @oper: iot sim operation
1071 * @mac: peer mac address
1072 * @type: 802.11 frame type
1073 * @subtype: 802.11 frame subtype
1074 * @seq: authentication sequence number, mostly 0 for non-authentication frame
1075 * @offset: user provided offset
1076 * @frm: user provided frame content
1077 * @len: length of frm
1078 * @action: boolean to indicate action frame
1079 *
1080 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE otherwise
1081 */
1082 QDF_STATUS
iot_sim_add_rule_for_mac(struct iot_sim_context * isc,enum iot_sim_operations oper,struct qdf_mac_addr * mac,uint8_t type,uint8_t subtype,uint16_t seq,uint16_t offset,uint8_t * frm,uint16_t len,uint16_t drop,bool action)1083 iot_sim_add_rule_for_mac(struct iot_sim_context *isc,
1084 enum iot_sim_operations oper,
1085 struct qdf_mac_addr *mac,
1086 uint8_t type, uint8_t subtype,
1087 uint16_t seq, uint16_t offset,
1088 uint8_t *frm, uint16_t len,
1089 uint16_t drop, bool action)
1090 {
1091 QDF_STATUS status = QDF_STATUS_E_FAILURE;
1092 struct iot_sim_rule_per_peer *peer;
1093 struct iot_sim_rule_per_seq **s_e = NULL;
1094 struct iot_sim_rule **f_e = NULL;
1095
1096 if (!isc) {
1097 iot_sim_err("iot_sim: isc is null");
1098 return status;
1099 }
1100
1101 status = iot_sim_delete_rule_for_mac(isc, oper, seq,
1102 type, subtype, mac,
1103 action);
1104 if (status == QDF_STATUS_E_FAILURE) {
1105 iot_sim_err("iot_sim: Rule removed - Fail");
1106 return status;
1107 }
1108
1109 if (oper == DROP || oper == DELAY)
1110 iot_sim_remap_type_subtype(&type, &subtype, &seq, action);
1111
1112 peer = iot_sim_find_peer_from_mac(isc, mac);
1113 if (!peer)
1114 peer = iot_sim_add_peer(isc, mac);
1115 if (peer) {
1116 qdf_spin_lock_bh(&isc->iot_sim_lock);
1117 s_e = &peer->rule_per_seq[seq];
1118 if (!*s_e) {
1119 *s_e = qdf_mem_malloc(sizeof(struct
1120 iot_sim_rule_per_seq));
1121 if (!*s_e) {
1122 iot_sim_err("can't allocate s_e");
1123 qdf_spin_unlock_bh(&isc->iot_sim_lock);
1124 return QDF_STATUS_E_NOMEM;
1125 }
1126 }
1127
1128 if (action)
1129 f_e = &((*s_e)->rule_per_action_frm[type][subtype]);
1130 else
1131 f_e = &((*s_e)->rule_per_type[type][subtype]);
1132
1133 if (qdf_is_macaddr_zero(mac))
1134 iot_sim_info("Rule addition for all peers");
1135 else
1136 iot_sim_info("Rule addition for " QDF_MAC_ADDR_FMT,
1137 QDF_MAC_ADDR_REF(mac->bytes));
1138
1139 iot_sim_info("oper:%s seq: %hu %s:%hu/%hu delay:%hu",
1140 iot_sim_oper_to_str(oper), seq,
1141 action ? "category/action code" : "type/subtype",
1142 type, subtype, drop);
1143
1144 if (oper == DELAY)
1145 offset = drop;
1146
1147 status = iot_sim_add_rule(s_e, f_e, oper, frm,
1148 offset, len, isc);
1149 qdf_spin_unlock_bh(&isc->iot_sim_lock);
1150 } else {
1151 /* TBD: clear the rules for peer with address 'mac'*/
1152 }
1153
1154 return status;
1155 }
1156
1157 /*
1158 * IOT SIM User Command Format
1159 *
1160 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1161 * | FrmType/subtype | Seq | Offset | Length | content | Mac Addr |
1162 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1163 * | 1Byte | 2Byte | 2Bytes | 2Bytes | Length | 6 Bytes |
1164 *
1165 */
1166
1167 /*
1168 * iot_sim_debug_content_change_write - Write Handler for content change
1169 * operation
1170 * @file: debugfs file pointer
1171 * @buf: buf of user input
1172 * @count: buf count
1173 * @ppos: offset on file
1174 *
1175 * Return: character read on success, failure otherwise
1176 */
1177 static ssize_t
iot_sim_debug_content_change_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)1178 iot_sim_debug_content_change_write(struct file *file,
1179 const char __user *buf,
1180 size_t count, loff_t *ppos)
1181 {
1182 QDF_STATUS status = QDF_STATUS_SUCCESS;
1183 unsigned char t_st, type, subtype, *content = NULL;
1184 uint16_t offset = 0, length = 0, seq = 0;
1185 char *locbuf = NULL;
1186 enum iot_sim_operations oper = CONTENT_CHANGE;
1187 struct qdf_mac_addr mac_addr = QDF_MAC_ADDR_BCAST_INIT;
1188 struct iot_sim_context *isc =
1189 ((struct seq_file *)file->private_data)->private;
1190 uint8_t action = 0, category = 0;
1191 bool is_action = 0, clear = false;
1192 mlme_pdev_ext_t *ext = NULL;
1193
1194 if ((!buf) || (count > USER_BUF_LEN) || (count < 7))
1195 return -EFAULT;
1196
1197 locbuf = qdf_mem_malloc(USER_BUF_LEN + 1);
1198 if (!locbuf)
1199 return -ENOMEM;
1200
1201 if (copy_from_user(locbuf, buf, count)) {
1202 qdf_mem_free(locbuf);
1203 return -EFAULT;
1204 }
1205
1206 status = iot_sim_parse_user_input_content_change(isc, locbuf, count,
1207 &t_st, &seq, &offset,
1208 &length, &content,
1209 &mac_addr);
1210 if (QDF_IS_STATUS_ERROR(status))
1211 goto free;
1212
1213 type = (t_st & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT;
1214 subtype = (t_st & IEEE80211_FC0_SUBTYPE_MASK);
1215 subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
1216
1217 if (type > N_FRAME_TYPE || subtype > N_FRAME_SUBTYPE || seq > MAX_SEQ)
1218 goto free;
1219
1220 if (FRAME_TYPE_IS_ACTION(type, subtype)) {
1221 status = iot_sim_parse_action_frame(length, offset, content,
1222 &category, &action);
1223 if (QDF_IS_STATUS_ERROR(status))
1224 goto free;
1225
1226 is_action = 1;
1227 type = category;
1228 subtype = action;
1229 }
1230
1231 clear = length ? false : true;
1232 status = iot_sim_send_rule_to_fw(isc, oper, &mac_addr, type, subtype,
1233 seq, offset, content, length,
1234 is_action, clear);
1235 if (QDF_IS_STATUS_SUCCESS(status))
1236 goto free;
1237
1238 /* check for rule removal */
1239 if (!length || !content) {
1240 status = iot_sim_delete_rule_for_mac(isc, oper, seq,
1241 type, subtype,
1242 &mac_addr,
1243 is_action);
1244
1245 } else {
1246 status = iot_sim_add_rule_for_mac(isc, oper, &mac_addr,
1247 type, subtype, seq, offset,
1248 content, length, 0,
1249 is_action);
1250 }
1251 if (QDF_IS_STATUS_SUCCESS(status)) {
1252 iot_sim_err("iot_sim: Content Change Operation - success");
1253 if (FRAME_TYPE_IS_BEACON(type, subtype)) {
1254 if (isc->bcn_buf && (!length || !content)) {
1255 qdf_nbuf_free(isc->bcn_buf);
1256 isc->bcn_buf = NULL;
1257 }
1258 ext = wlan_pdev_mlme_get_ext_hdl(isc->pdev_obj);
1259 if (ext) {
1260 isc->iot_sim_update_beacon_trigger(ext);
1261 iot_sim_info("Beacon update triggered");
1262 } else {
1263 iot_sim_err("mlme_pdev_ext is null");
1264 }
1265 }
1266 } else {
1267 iot_sim_err("iot_sim: Content Change Operation - Fail");
1268 }
1269 free:
1270 qdf_mem_free(content);
1271 qdf_mem_free(locbuf);
1272 return count;
1273 }
1274
1275 /*
1276 * iot_sim_parse_user_input_delay - function to parse user input into
1277 * predefined format for delay operation.
1278 * All arguments passed will be filled
1279 * upon success
1280 * @isc: iot sim context
1281 * @userbuf: local copy of user input
1282 * @count: length of userbuf
1283 * @t_st: address of type variable
1284 * @seq: address of seq variable
1285 * @cat_type: 802.11 action frame category code
1286 * @act_type: 802.11 action frame action code
1287 * @delay: address of delay variable
1288 * @addr: pointer to mac address
1289 *
1290 * Return: QDF_STATUS_SUCCESS on success
1291 * QDF_STATUS_E_FAILURE otherwise
1292 */
1293 QDF_STATUS
iot_sim_parse_user_input_delay(struct iot_sim_context * isc,char * userbuf,ssize_t count,uint8_t * t_st,uint16_t * seq,uint8_t * cat_type,uint8_t * act_type,uint16_t * delay,struct qdf_mac_addr * addr)1294 iot_sim_parse_user_input_delay(struct iot_sim_context *isc,
1295 char *userbuf, ssize_t count,
1296 uint8_t *t_st, uint16_t *seq,
1297 uint8_t *cat_type, uint8_t *act_type,
1298 uint16_t *delay, struct qdf_mac_addr *addr)
1299 {
1300 QDF_STATUS status = QDF_STATUS_SUCCESS;
1301 char *argv[6], *delim = " ", *substr;
1302 int argc = -1, ret = 0;
1303
1304 qdf_mem_zero(argv, sizeof(argv));
1305 userbuf = qdf_str_trim(userbuf);
1306
1307 while ((substr = qdf_str_sep(&userbuf, delim)) != NULL) {
1308 if (!isspace(*substr) && *substr != '\0')
1309 argv[++argc] = substr;
1310 if (argc >= 5)
1311 break;
1312 }
1313
1314 if (argc < 3) {
1315 iot_sim_err("Invalid argument count %d", (argc + 1));
1316 return status;
1317 }
1318
1319 if (!argv[0] || !argv[1] || !argv[2] || !argv[3] || !argv[4]) {
1320 iot_sim_err("One or more arguments are null");
1321 return status;
1322 }
1323 /*
1324 * User can send delay data in following format:
1325 * 1. Add delay rule for specific peer
1326 * <t_st> <seq> <category_type> <action_type> <delay> <MAC>
1327 * 2. Remove delay rule for specific peer
1328 * <t_st> <seq> <category_type> <action_type> <delay> <MAC>
1329 */
1330
1331 ret = kstrtou8(argv[0], 16, t_st);
1332 if (ret)
1333 goto err;
1334 ret = kstrtou16(argv[1], 10, seq);
1335 if (ret)
1336 goto err;
1337 ret = kstrtou8(argv[2], 10, cat_type);
1338 if (ret)
1339 goto err;
1340 ret = kstrtou8(argv[3], 10, act_type);
1341 if (ret)
1342 goto err;
1343 ret = kstrtou16(argv[4], 10, delay);
1344 if (ret)
1345 goto err;
1346
1347 /*
1348 * If argv[5] is valid, this must be mac address
1349 */
1350 if (argv[5])
1351 status = qdf_mac_parse(argv[5], addr);
1352
1353 iot_sim_err("delay rule mac address " QDF_MAC_ADDR_FMT,
1354 QDF_MAC_ADDR_REF(addr->bytes));
1355
1356 return status;
1357 err:
1358 iot_sim_err("kstrtoXX failed: %d", ret);
1359 return QDF_STATUS_E_FAILURE;
1360 }
1361
1362 /*
1363 * iot_sim_debug_delay_write - Write Handler for delay operation
1364 * @file: debugfs file pointer
1365 * @buf: buf of user input
1366 * @count: buf count
1367 * @ppos: offset on file
1368 *
1369 * Return: character read
1370 */
1371 static ssize_t
iot_sim_debug_delay_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)1372 iot_sim_debug_delay_write(struct file *file,
1373 const char __user *buf,
1374 size_t count, loff_t *ppos)
1375 {
1376 QDF_STATUS status = QDF_STATUS_SUCCESS;
1377 unsigned char t_st, type, subtype;
1378 uint16_t seq = 0;
1379 char *locbuf = NULL;
1380 enum iot_sim_operations oper = DELAY;
1381 struct qdf_mac_addr mac_addr = QDF_MAC_ADDR_BCAST_INIT;
1382 struct iot_sim_context *isc =
1383 ((struct seq_file *)file->private_data)->private;
1384 uint8_t action = 0, category = 0, tmp[2];
1385 bool is_action = false, clear = false;
1386 uint16_t delay = 0;
1387
1388 if ((!buf) || (count > USER_BUF_LEN_DELAY) || (count < 6))
1389 return -EFAULT;
1390
1391 locbuf = qdf_mem_malloc(USER_BUF_LEN_DELAY + 1);
1392 if (!locbuf)
1393 return -ENOMEM;
1394
1395 if (copy_from_user(locbuf, buf, count)) {
1396 qdf_mem_free(locbuf);
1397 return -EFAULT;
1398 }
1399
1400 status = iot_sim_parse_user_input_delay(isc, locbuf, count,
1401 &t_st, &seq, &category,
1402 &action, &delay, &mac_addr);
1403 if (QDF_IS_STATUS_ERROR(status)) {
1404 iot_sim_err("iot_sim_parse_user_input_delay failed");
1405 goto free;
1406 }
1407 iot_sim_err("Delay rule t_st:%d, seq:%hu cat_type:%d, act_type:%d, delay:%hu",
1408 t_st, seq, category, action, delay);
1409
1410 type = (t_st & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT;
1411 subtype = (t_st & IEEE80211_FC0_SUBTYPE_MASK);
1412 subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
1413
1414 if (type > N_FRAME_TYPE || subtype > N_FRAME_SUBTYPE || seq > MAX_SEQ)
1415 goto free;
1416
1417 if (FRAME_TYPE_IS_ACTION(type, subtype)) {
1418 tmp[0] = category;
1419 tmp[1] = action;
1420 /*
1421 * convert 802.11 category and action code to iot sim codes
1422 */
1423 status = iot_sim_get_index_for_action_frm(tmp, &category,
1424 &action, false);
1425 if (QDF_IS_STATUS_ERROR(status))
1426 goto free;
1427
1428 is_action = 1;
1429 type = category;
1430 subtype = action;
1431 }
1432
1433 clear = delay ? false : true;
1434 status = iot_sim_send_rule_to_fw(isc, oper, &mac_addr, type, subtype,
1435 seq, delay, NULL, 0, is_action, clear);
1436 if (QDF_IS_STATUS_SUCCESS(status))
1437 goto free;
1438
1439 /* check for rule removal */
1440 if (!delay) {
1441 status = iot_sim_delete_rule_for_mac(isc, oper, seq,
1442 type, subtype,
1443 &mac_addr,
1444 is_action);
1445 } else {
1446 status = iot_sim_add_rule_for_mac(isc, oper, &mac_addr,
1447 type, subtype, seq, 0,
1448 NULL, 0, delay, is_action);
1449 }
1450 if (QDF_IS_STATUS_SUCCESS(status))
1451 iot_sim_debug("iot_sim: Rule update Delay Operation - Success");
1452 else
1453 iot_sim_err("iot_sim: Rule update Delay Operation - Fail");
1454 free:
1455 qdf_mem_free(locbuf);
1456 return count;
1457 }
1458
1459 /*
1460 * iot_sim_parse_user_input_drop - function to parse user input into
1461 * predefined format for drop operation.
1462 * All arguments passed will be filled
1463 * upon success
1464 * @isc: iot sim context
1465 * @userbuf: local copy of user input
1466 * @count: length of userbuf
1467 * @t_st: address of type variable
1468 * @seq: address of seq variable
1469 * @cat_type: 802.11 action frame category code
1470 * @act_type: 802.11 action frame action code
1471 * @drop: address of drop variable to specify drop the frame or not
1472 * @addr: pointer to mac address
1473 *
1474 * Return: QDF_STATUS_SUCCESS on success
1475 * QDF_STATUS_E_FAILURE otherwise
1476 */
1477 QDF_STATUS
iot_sim_parse_user_input_drop(struct iot_sim_context * isc,char * userbuf,ssize_t count,uint8_t * t_st,uint16_t * seq,uint8_t * cat_type,uint8_t * act_type,uint8_t * drop,struct qdf_mac_addr * addr)1478 iot_sim_parse_user_input_drop(struct iot_sim_context *isc,
1479 char *userbuf, ssize_t count,
1480 uint8_t *t_st, uint16_t *seq,
1481 uint8_t *cat_type, uint8_t *act_type,
1482 uint8_t *drop, struct qdf_mac_addr *addr)
1483 {
1484 QDF_STATUS status = QDF_STATUS_SUCCESS;
1485 char *argv[6], *delim = " ", *substr;
1486 int argc = -1, ret = 0;
1487
1488 qdf_mem_zero(argv, sizeof(argv));
1489 userbuf = qdf_str_trim(userbuf);
1490
1491 while ((substr = qdf_str_sep(&userbuf, delim)) != NULL) {
1492 if (!isspace(*substr) && *substr != '\0')
1493 argv[++argc] = substr;
1494 if (argc >= 5)
1495 break;
1496 }
1497
1498 if (argc < 3) {
1499 iot_sim_err("Invalid argument count %d", (argc + 1));
1500 return status;
1501 }
1502
1503 if (!argv[0] || !argv[1] || !argv[2] || !argv[3] || !argv[4]) {
1504 iot_sim_err("One or more arguments are null");
1505 return status;
1506 }
1507 /*
1508 * User can send drop data in following format:
1509 * 1. Add drop rule for specific peer
1510 * <t_st> <seq> <category_type> <action_type> <drop> <MAC>
1511 * 2. Add drop rule for broadcast peer
1512 * <t_st> <seq> <category_type> <action_type> <drop>
1513 * 3. Remove drop rule for specific peer
1514 * <t_st> <seq> <category_type> <action_type> <drop> <MAC>
1515 * 4. Remove drop rule for broadcast peer
1516 * <t_st> <seq> <category_type> <action_type> <drop> <BCAST_MAC>
1517 * 5. Remove drop rule for all peer
1518 * <t_st> <seq> <category_type> <action_type> <drop>
1519 */
1520
1521 ret = kstrtou8(argv[0], 16, t_st);
1522 if (ret)
1523 goto err;
1524 ret = kstrtou16(argv[1], 10, seq);
1525 if (ret)
1526 goto err;
1527 ret = kstrtou8(argv[2], 10, cat_type);
1528 if (ret)
1529 goto err;
1530 ret = kstrtou8(argv[3], 10, act_type);
1531 if (ret)
1532 goto err;
1533 ret = kstrtou8(argv[4], 10, drop);
1534 if (ret)
1535 goto err;
1536
1537 /*
1538 * If argv[5] is valid, this must be mac address
1539 */
1540 if (argv[5])
1541 status = qdf_mac_parse(argv[5], addr);
1542
1543 iot_sim_err("drop rule mac address " QDF_MAC_ADDR_FMT,
1544 QDF_MAC_ADDR_REF(addr->bytes));
1545
1546 return status;
1547 err:
1548 iot_sim_err("kstrtoXX failed: %d", ret);
1549 return QDF_STATUS_E_FAILURE;
1550 }
1551
1552 /*
1553 * iot_sim_debug_drop_write - Write Handler for drop operation
1554 * @file: debugfs file pointer
1555 * @buf: buf of user input
1556 * @count: buf count
1557 * @ppos: offset on file
1558 *
1559 * Return: character read
1560 */
1561 static ssize_t
iot_sim_debug_drop_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)1562 iot_sim_debug_drop_write(struct file *file,
1563 const char __user *buf,
1564 size_t count, loff_t *ppos)
1565 {
1566 QDF_STATUS status = QDF_STATUS_SUCCESS;
1567 unsigned char t_st, type, subtype;
1568 uint16_t seq = 0;
1569 char *locbuf = NULL;
1570 enum iot_sim_operations oper = DROP;
1571 struct qdf_mac_addr mac_addr = QDF_MAC_ADDR_BCAST_INIT;
1572 struct iot_sim_context *isc =
1573 ((struct seq_file *)file->private_data)->private;
1574 uint8_t action = 0, category = 0, tmp[2], drop = 0;
1575 bool is_action = false, clear = false;
1576
1577 if ((!buf) || (count > USER_BUF_LEN_DROP) || (count < 6))
1578 return -EFAULT;
1579
1580 locbuf = qdf_mem_malloc(USER_BUF_LEN_DROP + 1);
1581 if (!locbuf)
1582 return -ENOMEM;
1583
1584 if (copy_from_user(locbuf, buf, count)) {
1585 qdf_mem_free(locbuf);
1586 return -EFAULT;
1587 }
1588
1589 status = iot_sim_parse_user_input_drop(isc, locbuf, count,
1590 &t_st, &seq, &category,
1591 &action, &drop, &mac_addr);
1592 if (QDF_IS_STATUS_ERROR(status))
1593 goto free;
1594
1595 type = (t_st & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT;
1596 subtype = (t_st & IEEE80211_FC0_SUBTYPE_MASK);
1597 subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
1598
1599 if (type > N_FRAME_TYPE || subtype > N_FRAME_SUBTYPE || seq > MAX_SEQ)
1600 goto free;
1601
1602 if (FRAME_TYPE_IS_ACTION(type, subtype)) {
1603 tmp[0] = category;
1604 tmp[1] = action;
1605 /*
1606 * convert 802.11 category and action code to iot sim codes
1607 */
1608 status = iot_sim_get_index_for_action_frm(tmp, &category,
1609 &action, false);
1610 if (QDF_IS_STATUS_ERROR(status))
1611 goto free;
1612
1613 is_action = 1;
1614 type = category;
1615 subtype = action;
1616 }
1617
1618 clear = drop ? false : true;
1619 status = iot_sim_send_rule_to_fw(isc, oper, &mac_addr, type, subtype,
1620 seq, 0, NULL, 0, is_action, clear);
1621 if (QDF_IS_STATUS_SUCCESS(status))
1622 goto free;
1623
1624 /* check for rule removal */
1625 if (!drop) {
1626 status = iot_sim_delete_rule_for_mac(isc, oper, seq,
1627 type, subtype,
1628 &mac_addr,
1629 is_action);
1630 } else {
1631 status = iot_sim_add_rule_for_mac(isc, oper, &mac_addr,
1632 type, subtype, seq, 0,
1633 NULL, 0, drop, is_action);
1634 }
1635 if (QDF_IS_STATUS_SUCCESS(status))
1636 iot_sim_debug("iot_sim: Rule update Drop Operation - Success");
1637 else
1638 iot_sim_err("iot_sim: Rule update Drop Operation - Fail");
1639 free:
1640 qdf_mem_free(locbuf);
1641 return count;
1642 }
1643
1644 /*
1645 * debug_iot_sim_##func_base##_show() - debugfs functions to display content
1646 * dummy function
1647 * Return: success
1648 */
1649 #define GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(func_base) \
1650 static int iot_sim_debug_##func_base##_show(struct seq_file *m, \
1651 void *v) \
1652 { \
1653 return qdf_status_to_os_return(QDF_STATUS_SUCCESS); \
1654 }
1655
1656 GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(content_change);
1657 GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(delay);
1658 GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(drop);
1659
1660 /*
1661 * debug_##func_base##_open() - Open debugfs entry for respective command
1662 * and event buffer.
1663 *
1664 * @inode: node for debug dir entry
1665 * @file: file handler
1666 *
1667 * Return: open status
1668 */
1669 #define GENERATE_DEBUG_IOT_SIM_STRUCTS(func_base) \
1670 static int debug_##func_base##_open(struct inode *inode, \
1671 struct file *file) \
1672 { \
1673 return single_open(file, iot_sim_debug_##func_base##_show, \
1674 inode->i_private); \
1675 } \
1676 \
1677 static const struct file_operations debug_##func_base##_ops = { \
1678 .open = debug_##func_base##_open, \
1679 .read = seq_read, \
1680 .llseek = seq_lseek, \
1681 .write = iot_sim_debug_##func_base##_write, \
1682 .release = single_release, \
1683 }
1684
1685 GENERATE_DEBUG_IOT_SIM_STRUCTS(content_change);
1686 GENERATE_DEBUG_IOT_SIM_STRUCTS(drop);
1687 GENERATE_DEBUG_IOT_SIM_STRUCTS(delay);
1688
1689 /* Structure to maintain debug information */
1690 struct iot_sim_dbgfs_file {
1691 const char *name;
1692 const struct file_operations *ops;
1693 };
1694
1695 #define DEBUG_IOT_SIM(func_base) { .name = #func_base, \
1696 .ops = &debug_##func_base##_ops \
1697 }
1698
1699 struct iot_sim_dbgfs_file iot_sim_dbgfs_files[IOT_SIM_DEBUGFS_FILE_NUM] = {
1700 DEBUG_IOT_SIM(content_change),
1701 DEBUG_IOT_SIM(drop),
1702 DEBUG_IOT_SIM(delay),
1703 };
1704
1705 /**
1706 * iot_sim_debugfs_deinit() - Deinit functions to remove debugfs directory and
1707 * it's file enteries.
1708 * @isc: iot_sim context
1709 *
1710 * Return: init status
1711 */
1712 static QDF_STATUS
iot_sim_debugfs_deinit(struct iot_sim_context * isc)1713 iot_sim_debugfs_deinit(struct iot_sim_context *isc)
1714 {
1715 qdf_debugfs_remove_dir_recursive(isc->iot_sim_dbgfs_ctx.iot_sim_dir_de);
1716
1717 return QDF_STATUS_SUCCESS;
1718 }
1719
1720 /*
1721 * iot_sim_remove_all_oper_rules - Function to remove all configured rules
1722 * for given operation
1723 *
1724 * @isc: iot sim context
1725 * @oper: iot sim operation
1726 *
1727 * Return: void
1728 */
1729 static void
iot_sim_remove_all_oper_rules(struct iot_sim_context * isc,enum iot_sim_operations oper)1730 iot_sim_remove_all_oper_rules(struct iot_sim_context *isc,
1731 enum iot_sim_operations oper)
1732 {
1733 uint16_t seq;
1734 uint8_t type, subtype, category = 0, action = 0;
1735 struct qdf_mac_addr zero_mac_addr = QDF_MAC_ADDR_ZERO_INIT;
1736
1737 for (seq = 0; seq < MAX_SEQ; seq++) {
1738 /* Remove rules for non-action type frames */
1739 for (type = 0; type < N_FRAME_TYPE; type++)
1740 for (subtype = 0; subtype < N_FRAME_SUBTYPE; subtype++)
1741 iot_sim_delete_rule_for_mac(isc, oper, seq,
1742 type, subtype,
1743 &zero_mac_addr, 0);
1744 /* Remove rules for action frames */
1745 for (category = 0; category < IOT_SIM_MAX_CAT; category++)
1746 for (action = 0; action < MAX_ACTION; action++)
1747 iot_sim_delete_rule_for_mac(isc, oper, seq,
1748 category, action,
1749 &zero_mac_addr, 1);
1750 }
1751 }
1752
1753 /*
1754 * iot_sim_remove_all_rules - Function to remove all configured rules
1755 *
1756 * @isc: iot sim context
1757 *
1758 * Return: void
1759 */
1760 static void
iot_sim_remove_all_rules(struct iot_sim_context * isc)1761 iot_sim_remove_all_rules(struct iot_sim_context *isc)
1762 {
1763 enum iot_sim_operations oper;
1764
1765 if (!isc)
1766 return;
1767
1768 for (oper = CONTENT_CHANGE; oper < IOT_SIM_MAX_OPERATION; oper++)
1769 iot_sim_remove_all_oper_rules(isc, oper);
1770 }
1771
1772 /**
1773 * iot_sim_debugfs_init() - debugfs functions to create debugfs directory and to
1774 * create debugfs enteries.
1775 * @isc: iot_sim context
1776 *
1777 * Return: init status
1778 */
1779 static QDF_STATUS
iot_sim_debugfs_init(struct iot_sim_context * isc)1780 iot_sim_debugfs_init(struct iot_sim_context *isc)
1781 {
1782 struct dentry *dbgfs_dir = NULL;
1783 struct dentry *de = NULL;
1784 uint8_t i, pdev_id;
1785 char buf[32];
1786
1787 if (!isc)
1788 return QDF_STATUS_E_FAILURE;
1789
1790 pdev_id = wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj);
1791
1792 qdf_mem_zero(buf, sizeof(buf));
1793 snprintf(buf, sizeof(buf), "iot_sim_pdev%u", pdev_id);
1794
1795 dbgfs_dir = qdf_debugfs_create_dir(buf, NULL);
1796 isc->iot_sim_dbgfs_ctx.iot_sim_dir_de = dbgfs_dir;
1797
1798 if (!isc->iot_sim_dbgfs_ctx.iot_sim_dir_de) {
1799 iot_sim_err("dbgfs dir creation failed for pdev%u", pdev_id);
1800 return QDF_STATUS_E_FAILURE;
1801 }
1802
1803 for (i = 0; i < IOT_SIM_DEBUGFS_FILE_NUM; ++i) {
1804 de = qdf_debugfs_create_entry(iot_sim_dbgfs_files[i].name,
1805 IOT_SIM_DBG_FILE_PERM,
1806 dbgfs_dir, isc,
1807 iot_sim_dbgfs_files[i].ops);
1808
1809 if (!de) {
1810 iot_sim_err("dbgfs file creation failed for pdev%u",
1811 pdev_id);
1812 goto out;
1813 }
1814 isc->iot_sim_dbgfs_ctx.iot_sim_file_de[i] = de;
1815 }
1816
1817 return QDF_STATUS_SUCCESS;
1818
1819 out:
1820 qdf_debugfs_remove_dir_recursive(dbgfs_dir);
1821 qdf_mem_set(isc->iot_sim_dbgfs_ctx.iot_sim_file_de,
1822 sizeof(isc->iot_sim_dbgfs_ctx.iot_sim_file_de), 0);
1823
1824 return QDF_STATUS_E_FAILURE;
1825 }
1826
1827 QDF_STATUS
wlan_iot_sim_pdev_obj_create_handler(struct wlan_objmgr_pdev * pdev,void * arg)1828 wlan_iot_sim_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, void *arg)
1829 {
1830 struct iot_sim_context *isc = NULL;
1831
1832 if (!pdev) {
1833 iot_sim_err("pdev is NULL");
1834 return QDF_STATUS_E_NULL_VALUE;
1835 }
1836
1837 isc = qdf_mem_malloc(sizeof(struct iot_sim_context));
1838 if (!isc)
1839 return QDF_STATUS_E_NOMEM;
1840
1841 isc->pdev_obj = pdev;
1842
1843 if (QDF_IS_STATUS_ERROR(iot_sim_debugfs_init(isc))) {
1844 qdf_mem_free(isc);
1845 iot_sim_info("iot_sim debugfs file creation failed");
1846 return QDF_STATUS_E_FAILURE;
1847 }
1848
1849 qdf_set_macaddr_broadcast(&isc->bcast_peer.addr);
1850 qdf_spinlock_create(&isc->iot_sim_lock);
1851 qdf_list_create(&isc->peer_list, 2);
1852 isc->bcn_buf = NULL;
1853
1854 wlan_objmgr_pdev_component_obj_attach(pdev, WLAN_IOT_SIM_COMP,
1855 (void *)isc, QDF_STATUS_SUCCESS);
1856
1857 iot_sim_debug("iot_sim component pdev%u object created",
1858 wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj));
1859
1860 return QDF_STATUS_SUCCESS;
1861 }
1862
1863 QDF_STATUS
wlan_iot_sim_pdev_obj_destroy_handler(struct wlan_objmgr_pdev * pdev,void * arg)1864 wlan_iot_sim_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev,
1865 void *arg)
1866 {
1867 struct iot_sim_context *isc = NULL;
1868
1869 if (!pdev) {
1870 iot_sim_err("pdev is NULL");
1871 return QDF_STATUS_E_NULL_VALUE;
1872 }
1873
1874 isc = wlan_objmgr_pdev_get_comp_private_obj(pdev,
1875 WLAN_IOT_SIM_COMP);
1876 if (isc) {
1877 wlan_objmgr_pdev_component_obj_detach(pdev,
1878 WLAN_IOT_SIM_COMP,
1879 (void *)isc);
1880 /* Deinitilise function pointers from iot_sim context */
1881 iot_sim_debugfs_deinit(isc);
1882 iot_sim_remove_all_rules(isc);
1883 qdf_list_destroy(&isc->peer_list);
1884 if (isc->bcn_buf)
1885 qdf_nbuf_free(isc->bcn_buf);
1886 qdf_spinlock_destroy(&isc->iot_sim_lock);
1887 qdf_mem_free(isc);
1888 }
1889 iot_sim_debug("iot_sim component pdev%u object destroyed",
1890 wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj));
1891
1892 return QDF_STATUS_SUCCESS;
1893 }
1894
1895