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