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