1 /* 2 * Copyright (c) 2020, The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "iot_sim_cmn_api_i.h" 18 #include "iot_sim_defs_i.h" 19 #include "wlan_iot_sim_tgt_api.h" 20 #include <qdf_mem.h> 21 #include <qdf_types.h> 22 #include <qdf_util.h> 23 #include <qdf_str.h> 24 #include <wmi_unified_param.h> 25 #include <wlan_iot_sim_utils_api.h> 26 27 /* 28 * iot_sim_oper_to_str - function to return iot sim operation string 29 * @oper: iot sim operation 30 * 31 * Return: string pointer 32 */ 33 uint8_t * 34 iot_sim_oper_to_str(enum iot_sim_operations oper) 35 { 36 switch (oper) { 37 case CONTENT_CHANGE: 38 return "content change"; 39 case DELAY: 40 return "delay"; 41 case DROP: 42 return "drop"; 43 default: 44 return "invalid"; 45 } 46 } 47 48 /* 49 * iot_sim_convert_offset_to_hex_str - function to convert offset into binary 50 * @offset: user provided offset value while action frame rule deletion 51 * @hex: buffer to store converted value 52 * @count: size of hex buffer 53 * 54 * Return: string pointer 55 */ 56 QDF_STATUS 57 iot_sim_convert_offset_to_hex_str(uint16_t offset, uint8_t *hex, int8_t count) 58 { 59 uint8_t temp[5]; 60 int ret; 61 62 snprintf(temp, sizeof(temp), "%04u", offset); 63 64 ret = qdf_hex_str_to_binary(hex, temp, count); 65 if (ret == -1) { 66 iot_sim_err("offset to hex conversion failed"); 67 return QDF_STATUS_E_FAILURE; 68 } 69 70 return QDF_STATUS_SUCCESS; 71 } 72 73 /* 74 * iot_sim_parse_action_frame - function to parse action frame to decode 75 * category and action code 76 * 77 * @length: length for content provided by user 78 * @offset: offset provided by user 79 * @content: user provided content 80 * @category: buffer to store iot specific category code 81 * @action: buffer to store iot specific action code 82 * 83 * Return: QDF_STATUS_SUCCESS on success otherwise failure 84 */ 85 QDF_STATUS 86 iot_sim_parse_action_frame(uint16_t length, uint16_t offset, uint8_t *content, 87 uint8_t *category, uint8_t *action) 88 { 89 QDF_STATUS status = QDF_STATUS_SUCCESS; 90 uint8_t hex[2], *ptr = NULL; 91 92 if (!length) { 93 status = iot_sim_convert_offset_to_hex_str(offset, hex, 94 sizeof(hex)); 95 if (QDF_IS_STATUS_ERROR(status)) 96 return status; 97 98 /* Offset represet category type and action type */ 99 status = iot_sim_get_index_for_action_frm(hex, category, 100 action); 101 if (status == QDF_STATUS_E_FAULT) { 102 iot_sim_err("Get indices for action failed"); 103 return status; 104 } 105 } else if (length && content) { 106 /* if offset is zero, move ptr post header */ 107 if (offset == 0) { 108 ptr = content + sizeof(struct ieee80211_frame); 109 } else if (offset == sizeof(struct ieee80211_frame)) { 110 ptr = content; 111 } else { 112 iot_sim_err("wrong offset for action frame content"); 113 return QDF_STATUS_E_FAILURE; 114 } 115 status = iot_sim_get_index_for_action_frm(ptr, category, 116 action); 117 } 118 return status; 119 } 120 121 /* 122 * iot_sim_find_peer_from_mac - function to find the iot sim peer data 123 * based on the mac address provided 124 * 125 * @isc: iot_sim pdev private object 126 * @mac: mac address of the peer 127 * 128 * Return: iot_sim_rule_per_peer reference if exists else NULL 129 */ 130 struct iot_sim_rule_per_peer * 131 iot_sim_find_peer_from_mac(struct iot_sim_context *isc, 132 struct qdf_mac_addr *mac) 133 { 134 if (qdf_is_macaddr_zero(mac) || qdf_is_macaddr_broadcast(mac)) 135 return &isc->bcast_peer; 136 else 137 return NULL; 138 } 139 140 /* 141 * iot_sim_validate_content - function to validate frame content. User provided 142 * content must be either full frame or full frame 143 * body or valid TLV formatted data. 144 * @buf: pointer to frame content in binary format 145 * @total_len: length of content 146 * @offset: offset provided by user 147 * 148 * Return: QDF_STATUS_SUCCESS on success 149 * QDF_STATUS_E_FAULT on failure 150 */ 151 static QDF_STATUS 152 iot_sim_validate_content(uint8_t *buf, 153 uint16_t total_len, 154 uint16_t offset) 155 { 156 char *ie = buf; 157 uint32_t len = 0, i = 0; 158 uint32_t fb = sizeof(struct ieee80211_frame); 159 160 if (offset == 0 || offset == fb) { 161 /* Replace the entire content set by user */ 162 return QDF_STATUS_SUCCESS; 163 } 164 165 /* Check for malformed IEs and proper IE 166 * boundaries in user content 167 */ 168 for (i = 0; i < total_len;) { 169 /* TLV: T(1) + L(1) + V(L)*/ 170 len = (1 + 1 + ie[1]); 171 i += len; 172 ie += len; 173 } 174 175 if (i == total_len) 176 return QDF_STATUS_SUCCESS; 177 178 iot_sim_err("iot_sim: cnt(bin) len:%u IE Parsed len:%u", 179 total_len, 180 i); 181 182 return QDF_STATUS_E_INVAL; 183 } 184 185 /* 186 * iot_sim_handle_frame_content - function to process frame content provided 187 * by user. This function will convert the ascii 188 * string into binary string and validate the 189 * content. 190 * @isc: iot sim context 191 * @pos: position to the frame content in the user buffer 192 * @storage: storage to store frame content after processing 193 * @offset: user provided offset 194 * @len: length of the user provided content in bytes 195 * 196 * Return: QDF_STATUS_SUCCESS on success 197 * QDF_STATUS_E_FAULT on hex str to binary conversion failure 198 * QDF_STATUS_E_NOMEM on memory allocation failure 199 */ 200 QDF_STATUS 201 iot_sim_handle_frame_content(struct iot_sim_context *isc, 202 const char *pos, 203 uint8_t **storage, 204 uint16_t offset, 205 uint16_t len) 206 { 207 QDF_STATUS status = QDF_STATUS_E_FAILURE; 208 int ret; 209 210 *storage = qdf_mem_malloc(len); 211 if (!*storage) { 212 iot_sim_err("iot_sim:storage allocation failed"); 213 return QDF_STATUS_E_NOMEM; 214 } 215 216 ret = qdf_hex_str_to_binary(*storage, pos, len); 217 if (ret == -1) { 218 iot_sim_err("iot_sim:hex2bin conversion failed"); 219 status = QDF_STATUS_E_FAULT; 220 goto error; 221 } 222 223 status = iot_sim_validate_content(*storage, len, offset); 224 if (QDF_IS_STATUS_ERROR(status)) { 225 iot_sim_err("iot_sim:User Content Invalid"); 226 goto error; 227 } 228 229 return QDF_STATUS_SUCCESS; 230 231 error: 232 qdf_mem_free(*storage); 233 *storage = NULL; 234 return status; 235 } 236 237 /* 238 * iot_sim_parse_user_input_content_change - function to parse user input into 239 * predefined format for content 240 * change operation. All arguments 241 * passed will be filled upon success 242 * @isc: iot sim context 243 * @userbuf: local copy of user input 244 * @count: length of userbuf 245 * @t_st: address of type variable 246 * @seq: address of seq variable 247 * @offset: address of offset variable 248 * @length: address of length variable 249 * @content: double pointer to storage to store frame content after processing 250 * @addr: pointer to mac address 251 * 252 * @storage: storage to store frame content after processing 253 * @offset: user provided offset 254 * @len: length of the user provided content in bytes 255 * 256 * Return: QDF_STATUS_SUCCESS on success 257 * QDF_STATUS_E_FAILURE otherwise 258 */ 259 QDF_STATUS 260 iot_sim_parse_user_input_content_change(struct iot_sim_context *isc, 261 char *userbuf, ssize_t count, 262 uint8_t *t_st, uint16_t *seq, 263 uint16_t *offset, uint16_t *length, 264 uint8_t **content, 265 struct qdf_mac_addr *addr) 266 { 267 QDF_STATUS status = QDF_STATUS_E_FAILURE; 268 char *argv[6], *delim = " ", *substr; 269 int argc = -1, ret = 0; 270 271 qdf_mem_zero(argv, sizeof(argv)); 272 userbuf = qdf_str_trim(userbuf); 273 274 while ((substr = qdf_str_sep(&userbuf, delim)) != NULL) { 275 if (!isspace(*substr) && *substr != '\0') 276 argv[++argc] = substr; 277 if (argc >= 5) 278 break; 279 } 280 281 if (argc < 3) { 282 iot_sim_err("Invalid argument count %d", (argc + 1)); 283 return status; 284 } 285 286 if (!argv[0] || !argv[1] || !argv[2] || !argv[3]) { 287 iot_sim_err("One or more arguments are null"); 288 return status; 289 } 290 291 ret = kstrtou8(argv[0], 16, t_st); 292 if (ret) 293 goto err; 294 ret = kstrtou16(argv[1], 10, seq); 295 if (ret) 296 goto err; 297 ret = kstrtou16(argv[2], 10, offset); 298 if (ret) 299 goto err; 300 ret = kstrtou16(argv[3], 10, length); 301 if (ret) 302 goto err; 303 /* 304 * User can send content change data in following format: 305 * 1. Add rule for specific peer 306 * <t_st> <seq> <offset> <length> <content> <MAC> 307 * 2. Add rule for broadcast peer 308 * <t_st> <seq> <offset> <length> <content> 309 * 3. Remove rule for specific peer 310 * <t_st> <seq> <offset> <length> <MAC> 311 * 4. Remove rule for broadcast peer 312 * <t_st> <seq> <offset> <length> 313 */ 314 315 /* 316 * If length is 0, this implies remove the rule 317 */ 318 if (!*length) { 319 /* 320 * 1. Ignore the frame content 321 * 2. argv[4] is not null, then it must be a valid mac 322 * If argv[4] is null, then set 'addr' as null 323 */ 324 *content = NULL; 325 if (argv[4]) { 326 status = qdf_mac_parse(argv[4], addr); 327 if (QDF_IS_STATUS_ERROR(status)) 328 iot_sim_err("iot_sim: argv4 is invalid mac for 0 len"); 329 } else { 330 qdf_mem_zero(addr, QDF_MAC_ADDR_SIZE); 331 status = QDF_STATUS_SUCCESS; 332 } 333 /* 334 * No need to parse further just return. 335 */ 336 return status; 337 } 338 339 /* 340 * If argv[4] is valid, this implies frame content 341 */ 342 if (argv[4]) { 343 status = iot_sim_handle_frame_content(isc, argv[4], 344 content, *offset, 345 *length); 346 if (QDF_IS_STATUS_ERROR(status)) 347 return status; 348 } 349 350 /* 351 * If argv[5] is valid, this must be mac address 352 */ 353 if (argv[5]) { 354 status = qdf_mac_parse(argv[5], addr); 355 if (QDF_IS_STATUS_ERROR(status)) 356 qdf_mem_free(content); 357 } 358 359 return status; 360 err: 361 iot_sim_err("kstrtoXX failed: %d", ret); 362 return status; 363 } 364 365 /* 366 * iot_sim_get_index_for_action_frm - function to convert 802.11 action frame 367 * category and action code into iot sim 368 * specific code. 369 * 370 * @frm: buf containing 802.11 action/category codes 371 * @cat_type: buf to hold converted category code 372 * @act_type: buf to hold converted action code 373 * 374 * Return: QDF_STATUS_SUCCESS on success, failure otherwise 375 */ 376 QDF_STATUS 377 iot_sim_get_index_for_action_frm(uint8_t *frm, uint8_t *cat_type, 378 uint8_t *act_type) 379 { 380 uint8_t category, action; 381 382 category = ((struct ieee80211_action *)(frm))->ia_category; 383 action = ((struct ieee80211_action *)(frm))->ia_action; 384 385 iot_sim_info("category %x action %x", category, action); 386 387 switch (category) { 388 case IEEE80211_ACTION_CAT_BA: 389 switch (action) { 390 case IEEE80211_ACTION_BA_ADDBA_REQUEST: 391 *cat_type = category; 392 *act_type = action; 393 break; 394 case IEEE80211_ACTION_BA_ADDBA_RESPONSE: 395 case IEEE80211_ACTION_BA_DELBA: 396 *cat_type = CAT_BA; 397 *act_type = action; 398 break; 399 default: 400 return QDF_STATUS_E_FAULT; 401 } 402 break; 403 case IEEE80211_ACTION_CAT_SA_QUERY: 404 switch (action) { 405 case IEEE80211_ACTION_SA_QUERY_REQUEST: 406 case IEEE80211_ACTION_SA_QUERY_RESPONSE: 407 *cat_type = CAT_SA_QUERY; 408 *act_type = action; 409 break; 410 default: 411 return QDF_STATUS_E_FAULT; 412 } 413 break; 414 default: 415 return QDF_STATUS_E_FAULT; 416 } 417 418 return QDF_STATUS_SUCCESS; 419 } 420 421 /* 422 * iot_sim_action_frame_supported_by_fw - function to find if action frame is 423 * supported by fw or not 424 * @category: iot_sim specific category code 425 * @action: iot_sim specific action code 426 * 427 * Return: true if supported else false 428 */ 429 bool 430 iot_sim_action_frame_supported_by_fw(uint8_t category, uint8_t action) 431 { 432 switch (category) { 433 case IEEE80211_ACTION_CAT_BA: 434 switch (action) { 435 case IEEE80211_ACTION_BA_ADDBA_REQUEST: 436 return true; 437 default: 438 return false; 439 } 440 default: 441 return false; 442 } 443 } 444 445 /* 446 * iot_sim_frame_supported_by_fw - function to find if frame is supported by fw 447 * @type: 802.11 frame type 448 * @subtype: 802.11 frame subtype 449 * 450 * Return: true if supported else false 451 */ 452 bool 453 iot_sim_frame_supported_by_fw(uint8_t type, uint8_t subtype, bool action) 454 { 455 if (action) 456 return iot_sim_action_frame_supported_by_fw(type, subtype); 457 458 switch (type << IEEE80211_FC0_TYPE_SHIFT) { 459 case IEEE80211_FC0_TYPE_MGT: 460 switch (subtype << IEEE80211_FC0_SUBTYPE_SHIFT) { 461 case IEEE80211_FC0_SUBTYPE_BEACON: 462 return true; 463 default: 464 return false; 465 } 466 case IEEE80211_FC0_TYPE_CTL: 467 switch (subtype << IEEE80211_FC0_SUBTYPE_SHIFT) { 468 case IEEE80211_FC0_SUBTYPE_TRIGGER: 469 case IEEE80211_FC0_SUBTYPE_BAR: 470 case IEEE80211_FC0_SUBTYPE_CTS: 471 case IEEE80211_FC0_SUBTYPE_ACK: 472 case IEEE80211_FC0_SUBTYPE_NDPA: 473 return true; 474 default: 475 return false; 476 } 477 case IEEE80211_FC0_TYPE_DATA: 478 switch (subtype << IEEE80211_FC0_SUBTYPE_SHIFT) { 479 default: 480 return true; 481 } 482 default: 483 return false; 484 } 485 } 486 487 /* 488 * iot_sim_remap_type_subtype - function to convert rules for response 489 * type frame into request type. This is 490 * used for drop/delay operation. This function 491 * will update the passed type and subtype value. 492 * 493 * @type: 802.11 frame type 494 * @subtype: 802.11 frame subtype 495 * @seq: authentication sequence number, mostly 0 for non-authentication frame 496 * @action: flag to indicate action frame 497 * 498 * Return: QDF_STATUS_SUCCESS 499 */ 500 QDF_STATUS 501 iot_sim_remap_type_subtype(uint8_t *type, uint8_t *subtype, 502 uint16_t *seq, bool action) 503 { 504 if (action) { 505 switch (*type) { 506 case CAT_BA: 507 switch (*subtype) { 508 case IEEE80211_ACTION_BA_ADDBA_RESPONSE: 509 *subtype = IEEE80211_ACTION_BA_ADDBA_REQUEST; 510 break; 511 default: 512 break; 513 } 514 break; 515 default: 516 break; 517 } 518 return QDF_STATUS_SUCCESS; 519 } 520 521 switch (*type << IEEE80211_FC0_TYPE_SHIFT) { 522 case IEEE80211_FC0_TYPE_MGT: 523 switch (*subtype << IEEE80211_FC0_SUBTYPE_SHIFT) { 524 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: 525 *subtype = IEEE80211_FC0_SUBTYPE_ASSOC_REQ; 526 *subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT; 527 break; 528 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: 529 *subtype = IEEE80211_FC0_SUBTYPE_REASSOC_REQ; 530 *subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT; 531 break; 532 case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 533 *subtype = IEEE80211_FC0_SUBTYPE_PROBE_REQ; 534 *subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT; 535 break; 536 case IEEE80211_FC0_SUBTYPE_AUTH: 537 *subtype = IEEE80211_FC0_SUBTYPE_AUTH; 538 *subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT; 539 /* If auth response (auth seq num 2) is marked as 540 * drop, then drop the auth request (auth seq num 1) 541 */ 542 if (*seq == IEEE80211_AUTH_OPEN_RESPONSE) 543 *seq = IEEE80211_AUTH_OPEN_REQUEST; 544 break; 545 default: 546 break; 547 } 548 default: 549 break; 550 } 551 552 return QDF_STATUS_SUCCESS; 553 } 554 555 /* 556 * iot_sim_send_rule_to_fw - function to send iot_sim rule to fw 557 * 558 * @isc: iot sim context 559 * @oper: iot sim operation 560 * @mac: peer mac address 561 * @type: 802.11 frame type 562 * @subtype: 802.11 frame subtype 563 * @seq: authentication sequence number, mostly 0 for non-authentication frame 564 * @offset: user provided offset 565 * @frm: user provided frame content 566 * @length: length of frm 567 * @action: flag to indicate action frame 568 * @drop: flag to indicate set drop rule 569 * @clear: flag to indicate set rule or clear 570 * 571 * Return: QDF_STATUS_SUCCESS 572 */ 573 QDF_STATUS 574 iot_sim_send_rule_to_fw(struct iot_sim_context *isc, 575 enum iot_sim_operations oper, 576 struct qdf_mac_addr *mac, 577 uint8_t type, uint8_t subtype, 578 uint16_t seq, uint16_t offset, 579 uint8_t *frm, uint16_t len, 580 bool action, bool clear) 581 { 582 struct simulation_test_params param; 583 584 if (FRAME_TYPE_IS_BEACON(type, subtype) && offset) { 585 iot_sim_info("Beacon update from offset:%d", offset); 586 return QDF_STATUS_E_NOSUPPORT; 587 } 588 589 if (iot_sim_frame_supported_by_fw(type, subtype, action)) { 590 qdf_mem_zero(¶m, sizeof(struct simulation_test_params)); 591 param.pdev_id = wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj); 592 qdf_mem_copy(param.peer_mac, mac, QDF_MAC_ADDR_SIZE); 593 param.test_cmd_type = oper; 594 /* subtype_cmd: Set subcmd based on action and clear flag */ 595 if (action) { 596 if (clear) 597 param.test_subcmd_type = DEL_RULE_ACTION; 598 else 599 param.test_subcmd_type = ADD_RULE_ACTION; 600 } else { 601 if (clear) 602 param.test_subcmd_type = DEL_RULE; 603 else 604 param.test_subcmd_type = ADD_RULE; 605 } 606 param.frame_type = type; 607 param.frame_subtype = subtype; 608 param.seq = seq; 609 param.offset = offset; 610 param.frame_length = len; 611 param.buf_len = len; 612 param.bufp = frm; 613 if (QDF_IS_STATUS_ERROR(tgt_send_simulation_cmd(isc->pdev_obj, 614 ¶m))) 615 iot_sim_err("Sending del rule to fw failed!"); 616 617 if (FRAME_TYPE_IS_BEACON(type, subtype) && clear) 618 return QDF_STATUS_E_NOSUPPORT; 619 620 return QDF_STATUS_SUCCESS; 621 } 622 623 return QDF_STATUS_E_NOSUPPORT; 624 } 625 626 /* 627 * iot_sim_del_rule - function to delete iot_sim rule 628 * 629 * @s_e: address of seq for which rule to be removed 630 * @f_e: address of the rule present in s_e to be removed 631 * @oper: iot sim operation 632 * 633 * Return: QDF_STATUS_SUCCESS 634 */ 635 QDF_STATUS 636 iot_sim_del_rule(struct iot_sim_rule_per_seq **s_e, 637 struct iot_sim_rule **f_e, 638 enum iot_sim_operations oper) 639 { 640 if (oper == CONTENT_CHANGE) { 641 qdf_mem_free((*f_e)->frm_content); 642 (*f_e)->frm_content = NULL; 643 } else if (oper == DROP) { 644 (*f_e)->drop = false; 645 } else if (oper == DELAY) { 646 /* TBD */ 647 } 648 649 if (qdf_test_bit(oper, (unsigned long *) 650 &(*f_e)->rule_bitmap)) { 651 (*s_e)->use_count--; 652 qdf_clear_bit(oper, (unsigned long *) 653 &(*f_e)->rule_bitmap); 654 } 655 656 if (!(*f_e)->rule_bitmap) { 657 qdf_mem_free(*f_e); 658 *f_e = NULL; 659 } 660 if ((*s_e)->use_count == 0) { 661 qdf_mem_free(*s_e); 662 *s_e = NULL; 663 } 664 return QDF_STATUS_SUCCESS; 665 } 666 667 /* 668 * iot_sim_delete_rule_for_mac - function to delete content change rule 669 * for given peer mac 670 * @isc: iot sim context 671 * @oper: iot sim operation 672 * @seq: authentication sequence number, mostly 0 for non-authentication frame 673 * @type: 802.11 frame type 674 * @subtype: 802.11 frame subtype 675 * @mac: peer mac address 676 * @action: action frame or not 677 * 678 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE otherwise 679 */ 680 QDF_STATUS 681 iot_sim_delete_rule_for_mac(struct iot_sim_context *isc, 682 enum iot_sim_operations oper, 683 uint16_t seq, uint8_t type, 684 uint8_t subtype, 685 struct qdf_mac_addr *mac, 686 bool action) 687 { 688 QDF_STATUS status = QDF_STATUS_SUCCESS; 689 struct iot_sim_rule_per_seq **s_e; 690 struct iot_sim_rule **f_e; 691 struct iot_sim_rule_per_peer *peer; 692 693 if (qdf_is_macaddr_zero(mac)) 694 iot_sim_info("Rule deletion for all peers"); 695 else 696 iot_sim_info("Rule deletion for " QDF_MAC_ADDR_STR, 697 QDF_MAC_ADDR_ARRAY(mac->bytes)); 698 699 iot_sim_debug("oper:%s seq: %hu %s:%hu/%hu", 700 iot_sim_oper_to_str(oper), seq, 701 action ? "category/action code" : "type/subtype", 702 type, subtype); 703 704 if (!isc) { 705 iot_sim_err("iot_sim: isc is null"); 706 return QDF_STATUS_E_FAILURE; 707 } 708 709 if (oper == DROP || oper == DELAY) 710 iot_sim_remap_type_subtype(&type, &subtype, &seq, action); 711 712 peer = iot_sim_find_peer_from_mac(isc, mac); 713 if (peer) { 714 qdf_spin_lock(&peer->iot_sim_lock); 715 s_e = &peer->rule_per_seq[seq]; 716 if (!*s_e) { 717 qdf_spin_unlock(&peer->iot_sim_lock); 718 return QDF_STATUS_SUCCESS; 719 } 720 721 if (action) 722 f_e = &((*s_e)->rule_per_action_frm[type][subtype]); 723 else 724 f_e = &((*s_e)->rule_per_type[type][subtype]); 725 726 if (*f_e) 727 status = iot_sim_del_rule(s_e, f_e, oper); 728 qdf_spin_unlock(&peer->iot_sim_lock); 729 } 730 731 return status; 732 } 733 734 /* 735 * iot_sim_add_rule - function to add iot_sim rule 736 * 737 * @s_e: address of seq for which rule to be added 738 * @f_e: address of the rule present in s_e to be added 739 * @oper: iot sim operation 740 * @frm: user provided frame content 741 * @offset: user provided offset 742 * @len: length of the user provided frame content 743 * 744 * Return: QDF_STATUS_SUCCESS 745 */ 746 QDF_STATUS 747 iot_sim_add_rule(struct iot_sim_rule_per_seq **s_e, 748 struct iot_sim_rule **f_e, 749 enum iot_sim_operations oper, 750 uint8_t *frm, uint16_t offset, uint16_t len) 751 { 752 if (!*f_e) { 753 *f_e = qdf_mem_malloc(sizeof(struct iot_sim_rule)); 754 if (!*f_e) { 755 iot_sim_err("can't allocate f_e"); 756 return QDF_STATUS_E_NOMEM; 757 } 758 } 759 760 if (oper == CONTENT_CHANGE) { 761 (*f_e)->frm_content = qdf_mem_malloc(len); 762 if (!((*f_e)->frm_content)) 763 return QDF_STATUS_E_NOMEM; 764 qdf_mem_copy((*f_e)->frm_content, frm, len); 765 (*f_e)->len = len; 766 (*f_e)->offset = offset; 767 } else if (oper == DROP) { 768 (*f_e)->drop = true; 769 } else if (oper == DELAY) { 770 /* TBD */ 771 } 772 773 (*s_e)->use_count++; 774 qdf_set_bit(oper, (unsigned long *) 775 &(*f_e)->rule_bitmap); 776 777 return QDF_STATUS_SUCCESS; 778 } 779 780 /* 781 * iot_sim_add_rule_for_mac - function to add content change rule 782 * for given peer mac 783 * @isc: iot sim context 784 * @oper: iot sim operation 785 * @mac: peer mac address 786 * @type: 802.11 frame type 787 * @subtype: 802.11 frame subtype 788 * @seq: authentication sequence number, mostly 0 for non-authentication frame 789 * @offset: user provided offset 790 * @frm: user provided frame content 791 * @len: length of frm 792 * @action: boolean to indicate action frame 793 * 794 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE otherwise 795 */ 796 QDF_STATUS 797 iot_sim_add_rule_for_mac(struct iot_sim_context *isc, 798 enum iot_sim_operations oper, 799 struct qdf_mac_addr *mac, 800 uint8_t type, uint8_t subtype, 801 uint16_t seq, uint16_t offset, 802 uint8_t *frm, uint16_t len, 803 uint8_t drop, bool action) 804 { 805 QDF_STATUS status = QDF_STATUS_E_FAILURE; 806 struct iot_sim_rule_per_peer *peer; 807 struct iot_sim_rule_per_seq **s_e = NULL; 808 struct iot_sim_rule **f_e = NULL; 809 810 if (!isc) { 811 iot_sim_err("iot_sim: isc is null"); 812 return status; 813 } 814 815 status = iot_sim_delete_rule_for_mac(isc, oper, seq, 816 type, subtype, mac, 817 action); 818 if (status == QDF_STATUS_E_FAILURE) { 819 iot_sim_err("iot_sim: Rule removed - Fail"); 820 return status; 821 } 822 823 if (oper == DROP || oper == DELAY) 824 iot_sim_remap_type_subtype(&type, &subtype, &seq, action); 825 826 peer = iot_sim_find_peer_from_mac(isc, mac); 827 if (peer) { 828 qdf_spin_lock(&peer->iot_sim_lock); 829 s_e = &peer->rule_per_seq[seq]; 830 if (!*s_e) { 831 *s_e = qdf_mem_malloc(sizeof(struct 832 iot_sim_rule_per_seq)); 833 if (!*s_e) { 834 iot_sim_err("can't allocate s_e"); 835 qdf_spin_unlock(&peer->iot_sim_lock); 836 return QDF_STATUS_E_NOMEM; 837 } 838 } 839 840 if (action) 841 f_e = &((*s_e)->rule_per_action_frm[type][subtype]); 842 else 843 f_e = &((*s_e)->rule_per_type[type][subtype]); 844 845 if (qdf_is_macaddr_zero(mac)) 846 iot_sim_info("Rule addition for all peers"); 847 else 848 iot_sim_info("Rule addition for " QDF_MAC_ADDR_STR, 849 QDF_MAC_ADDR_ARRAY(mac->bytes)); 850 851 iot_sim_info("oper:%s seq: %hu %s:%hu/%hu", 852 iot_sim_oper_to_str(oper), seq, 853 action ? "category/action code" : "type/subtype", 854 type, subtype); 855 856 status = iot_sim_add_rule(s_e, f_e, oper, frm, offset, len); 857 qdf_spin_unlock(&peer->iot_sim_lock); 858 } else { 859 /* TBD: clear the rules for peer with address 'mac'*/ 860 } 861 862 return status; 863 } 864 865 /* 866 * IOT SIM User Command Format 867 * 868 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 869 * | FrmType/subtype | Seq | Offset | Length | content | Mac Addr | 870 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 871 * | 1Byte | 2Byte | 2Bytes | 2Bytes | Length | 6 Bytes | 872 * 873 */ 874 875 /* 876 * iot_sim_debug_content_change_write - Write Handler for content change 877 * operation 878 * @file: debugfs file pointer 879 * @buf: buf of user input 880 * @count: buf count 881 * @ppos: offset on file 882 * 883 * Return: character read on success, failure otherwise 884 */ 885 static ssize_t 886 iot_sim_debug_content_change_write(struct file *file, 887 const char __user *buf, 888 size_t count, loff_t *ppos) 889 { 890 QDF_STATUS status = QDF_STATUS_SUCCESS; 891 unsigned char t_st, type, subtype, *content = NULL; 892 uint16_t offset = 0, length = 0, seq = 0; 893 char *locbuf = NULL; 894 enum iot_sim_operations oper = CONTENT_CHANGE; 895 struct qdf_mac_addr mac_addr = QDF_MAC_ADDR_BCAST_INIT; 896 struct iot_sim_context *isc = 897 ((struct seq_file *)file->private_data)->private; 898 uint8_t action = 0, category = 0; 899 bool is_action = 0, clear = false; 900 mlme_pdev_ext_t *ext = NULL; 901 902 if ((!buf) || (count > USER_BUF_LEN) || (count < 7)) 903 return -EFAULT; 904 905 locbuf = qdf_mem_malloc(USER_BUF_LEN + 1); 906 if (!locbuf) 907 return -ENOMEM; 908 909 if (copy_from_user(locbuf, buf, count)) { 910 qdf_mem_free(locbuf); 911 return -EFAULT; 912 } 913 914 status = iot_sim_parse_user_input_content_change(isc, locbuf, count, 915 &t_st, &seq, &offset, 916 &length, &content, 917 &mac_addr); 918 if (QDF_IS_STATUS_ERROR(status)) 919 goto free; 920 921 type = (t_st & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT; 922 subtype = (t_st & IEEE80211_FC0_SUBTYPE_MASK); 923 subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT; 924 925 if (type > N_FRAME_TYPE || subtype > N_FRAME_SUBTYPE || seq > MAX_SEQ) 926 goto free; 927 928 if (FRAME_TYPE_IS_ACTION(type, subtype)) { 929 status = iot_sim_parse_action_frame(length, offset, content, 930 &category, &action); 931 if (QDF_IS_STATUS_ERROR(status)) 932 goto free; 933 934 is_action = 1; 935 type = category; 936 subtype = action; 937 } 938 939 clear = length ? false : true; 940 status = iot_sim_send_rule_to_fw(isc, oper, &mac_addr, type, subtype, 941 seq, offset, content, length, 942 is_action, clear); 943 if (QDF_IS_STATUS_SUCCESS(status)) 944 goto free; 945 946 /* check for rule removal */ 947 if (!length || !content) { 948 status = iot_sim_delete_rule_for_mac(isc, oper, seq, 949 type, subtype, 950 &mac_addr, 951 is_action); 952 953 } else { 954 status = iot_sim_add_rule_for_mac(isc, oper, &mac_addr, 955 type, subtype, seq, offset, 956 content, length, 0, 957 is_action); 958 } 959 if (QDF_IS_STATUS_SUCCESS(status)) { 960 iot_sim_err("iot_sim: Content Change Operation - success"); 961 if (FRAME_TYPE_IS_BEACON(type, subtype)) { 962 if (isc->bcn_buf && (!length || !content)) { 963 qdf_nbuf_free(isc->bcn_buf); 964 isc->bcn_buf = NULL; 965 } 966 ext = wlan_pdev_mlme_get_ext_hdl(isc->pdev_obj); 967 if (ext) { 968 isc->iot_sim_update_beacon_trigger(ext); 969 iot_sim_info("Beacon update triggered"); 970 } else { 971 iot_sim_err("mlme_pdev_ext is null"); 972 } 973 } 974 } else { 975 iot_sim_err("iot_sim: Content Change Operation - Fail"); 976 } 977 free: 978 qdf_mem_free(content); 979 qdf_mem_free(locbuf); 980 return count; 981 } 982 983 /* 984 * iot_sim_debug_delay_write - Write Handler for delay operation 985 * @file: debugfs file pointer 986 * @buf: buf of user input 987 * @count: buf count 988 * @ppos: offset on file 989 * 990 * Return: character read 991 */ 992 static ssize_t 993 iot_sim_debug_delay_write(struct file *file, 994 const char __user *buf, 995 size_t count, loff_t *ppos) 996 { 997 iot_sim_err("delay iot sim ops called"); 998 return count; 999 } 1000 1001 /* 1002 * iot_sim_parse_user_input_drop - function to parse user input into 1003 * predefined format for drop operation. 1004 * All arguments passed will be filled 1005 * upon success 1006 * @isc: iot sim context 1007 * @userbuf: local copy of user input 1008 * @count: length of userbuf 1009 * @t_st: address of type variable 1010 * @seq: address of seq variable 1011 * @cat_type: 802.11 action frame category code 1012 * @act_type: 802.11 action frame action code 1013 * @drop: address of drop variable to specify drop the frame or not 1014 * @addr: pointer to mac address 1015 * 1016 * Return: QDF_STATUS_SUCCESS on success 1017 * QDF_STATUS_E_FAILURE otherwise 1018 */ 1019 QDF_STATUS 1020 iot_sim_parse_user_input_drop(struct iot_sim_context *isc, 1021 char *userbuf, ssize_t count, 1022 uint8_t *t_st, uint16_t *seq, 1023 uint8_t *cat_type, uint8_t *act_type, 1024 uint8_t *drop, struct qdf_mac_addr *addr) 1025 { 1026 QDF_STATUS status = QDF_STATUS_SUCCESS; 1027 char *argv[6], *delim = " ", *substr; 1028 int argc = -1, ret = 0; 1029 1030 qdf_mem_zero(argv, sizeof(argv)); 1031 userbuf = qdf_str_trim(userbuf); 1032 1033 while ((substr = qdf_str_sep(&userbuf, delim)) != NULL) { 1034 if (!isspace(*substr) && *substr != '\0') 1035 argv[++argc] = substr; 1036 if (argc >= 5) 1037 break; 1038 } 1039 1040 if (argc < 3) { 1041 iot_sim_err("Invalid argument count %d", (argc + 1)); 1042 return status; 1043 } 1044 1045 if (!argv[0] || !argv[1] || !argv[2] || !argv[3] || !argv[4]) { 1046 iot_sim_err("One or more arguments are null"); 1047 return status; 1048 } 1049 /* 1050 * User can send drop data in following format: 1051 * 1. Add drop rule for specific peer 1052 * <t_st> <seq> <category_type> <action_type> <drop> <MAC> 1053 * 2. Add drop rule for broadcast peer 1054 * <t_st> <seq> <category_type> <action_type> <drop> 1055 * 3. Remove drop rule for specific peer 1056 * <t_st> <seq> <category_type> <action_type> <drop> <MAC> 1057 * 4. Remove drop rule for broadcast peer 1058 * <t_st> <seq> <category_type> <action_type> <drop> <BCAST_MAC> 1059 * 5. Remove drop rule for all peer 1060 * <t_st> <seq> <category_type> <action_type> <drop> 1061 */ 1062 1063 ret = kstrtou8(argv[0], 16, t_st); 1064 if (ret) 1065 goto err; 1066 ret = kstrtou16(argv[1], 10, seq); 1067 if (ret) 1068 goto err; 1069 ret = kstrtou8(argv[2], 10, cat_type); 1070 if (ret) 1071 goto err; 1072 ret = kstrtou8(argv[3], 10, act_type); 1073 if (ret) 1074 goto err; 1075 ret = kstrtou8(argv[4], 10, drop); 1076 if (ret) 1077 goto err; 1078 1079 /* 1080 * If argv[5] is valid, this must be mac address 1081 */ 1082 if (argv[5]) 1083 status = qdf_mac_parse(argv[5], addr); 1084 1085 return status; 1086 err: 1087 iot_sim_err("kstrtoXX failed: %d", ret); 1088 return QDF_STATUS_E_FAILURE; 1089 } 1090 1091 /* 1092 * iot_sim_debug_drop_write - Write Handler for drop operation 1093 * @file: debugfs file pointer 1094 * @buf: buf of user input 1095 * @count: buf count 1096 * @ppos: offset on file 1097 * 1098 * Return: character read 1099 */ 1100 static ssize_t 1101 iot_sim_debug_drop_write(struct file *file, 1102 const char __user *buf, 1103 size_t count, loff_t *ppos) 1104 { 1105 QDF_STATUS status = QDF_STATUS_SUCCESS; 1106 unsigned char t_st, type, subtype; 1107 uint16_t seq = 0; 1108 char *locbuf = NULL; 1109 enum iot_sim_operations oper = DROP; 1110 struct qdf_mac_addr mac_addr = QDF_MAC_ADDR_BCAST_INIT; 1111 struct iot_sim_context *isc = 1112 ((struct seq_file *)file->private_data)->private; 1113 uint8_t action = 0, category = 0, tmp[2], drop = 0; 1114 bool is_action = false, clear = false; 1115 1116 if ((!buf) || (count > USER_BUF_LEN_DROP) || (count < 6)) 1117 return -EFAULT; 1118 1119 locbuf = qdf_mem_malloc(USER_BUF_LEN_DROP + 1); 1120 if (!locbuf) 1121 return -ENOMEM; 1122 1123 if (copy_from_user(locbuf, buf, count)) { 1124 qdf_mem_free(locbuf); 1125 return -EFAULT; 1126 } 1127 1128 status = iot_sim_parse_user_input_drop(isc, locbuf, count, 1129 &t_st, &seq, &category, 1130 &action, &drop, &mac_addr); 1131 if (QDF_IS_STATUS_ERROR(status)) 1132 goto free; 1133 1134 type = (t_st & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT; 1135 subtype = (t_st & IEEE80211_FC0_SUBTYPE_MASK); 1136 subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT; 1137 1138 if (type > N_FRAME_TYPE || subtype > N_FRAME_SUBTYPE || seq > MAX_SEQ) 1139 goto free; 1140 1141 if (FRAME_TYPE_IS_ACTION(type, subtype)) { 1142 tmp[0] = category; 1143 tmp[1] = action; 1144 /* 1145 * convert 802.11 category and action code to iot sim codes 1146 */ 1147 status = iot_sim_get_index_for_action_frm(tmp, &category, 1148 &action); 1149 if (QDF_IS_STATUS_ERROR(status)) 1150 goto free; 1151 1152 is_action = 1; 1153 type = category; 1154 subtype = action; 1155 } 1156 1157 clear = drop ? false : true; 1158 status = iot_sim_send_rule_to_fw(isc, oper, &mac_addr, type, subtype, 1159 seq, 0, NULL, 0, is_action, clear); 1160 if (QDF_IS_STATUS_SUCCESS(status)) 1161 goto free; 1162 1163 /* check for rule removal */ 1164 if (!drop) { 1165 status = iot_sim_delete_rule_for_mac(isc, oper, seq, 1166 type, subtype, 1167 &mac_addr, 1168 is_action); 1169 } else { 1170 status = iot_sim_add_rule_for_mac(isc, oper, &mac_addr, 1171 type, subtype, seq, 0, 1172 NULL, 0, drop, is_action); 1173 } 1174 if (QDF_IS_STATUS_SUCCESS(status)) 1175 iot_sim_debug("iot_sim: Rule update Drop Operation - Success"); 1176 else 1177 iot_sim_err("iot_sim: Rule update Drop Operation - Fail"); 1178 free: 1179 qdf_mem_free(locbuf); 1180 return count; 1181 } 1182 1183 /* 1184 * debug_iot_sim_##func_base##_show() - debugfs functions to display content 1185 * dummy function 1186 * Return: success 1187 */ 1188 #define GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(func_base) \ 1189 static int iot_sim_debug_##func_base##_show(struct seq_file *m, \ 1190 void *v) \ 1191 { \ 1192 return qdf_status_to_os_return(QDF_STATUS_SUCCESS); \ 1193 } 1194 1195 GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(content_change); 1196 GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(delay); 1197 GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(drop); 1198 1199 /* 1200 * debug_##func_base##_open() - Open debugfs entry for respective command 1201 * and event buffer. 1202 * 1203 * @inode: node for debug dir entry 1204 * @file: file handler 1205 * 1206 * Return: open status 1207 */ 1208 #define GENERATE_DEBUG_IOT_SIM_STRUCTS(func_base) \ 1209 static int debug_##func_base##_open(struct inode *inode, \ 1210 struct file *file) \ 1211 { \ 1212 return single_open(file, iot_sim_debug_##func_base##_show, \ 1213 inode->i_private); \ 1214 } \ 1215 \ 1216 static const struct file_operations debug_##func_base##_ops = { \ 1217 .open = debug_##func_base##_open, \ 1218 .read = seq_read, \ 1219 .llseek = seq_lseek, \ 1220 .write = iot_sim_debug_##func_base##_write, \ 1221 .release = single_release, \ 1222 } 1223 1224 GENERATE_DEBUG_IOT_SIM_STRUCTS(content_change); 1225 GENERATE_DEBUG_IOT_SIM_STRUCTS(drop); 1226 GENERATE_DEBUG_IOT_SIM_STRUCTS(delay); 1227 1228 /* Structure to maintain debug information */ 1229 struct iot_sim_dbgfs_file { 1230 const char *name; 1231 const struct file_operations *ops; 1232 }; 1233 1234 #define DEBUG_IOT_SIM(func_base) { .name = #func_base, \ 1235 .ops = &debug_##func_base##_ops \ 1236 } 1237 1238 struct iot_sim_dbgfs_file iot_sim_dbgfs_files[IOT_SIM_DEBUGFS_FILE_NUM] = { 1239 DEBUG_IOT_SIM(content_change), 1240 DEBUG_IOT_SIM(drop), 1241 DEBUG_IOT_SIM(delay), 1242 }; 1243 1244 /** 1245 * iot_sim_debugfs_deinit() - Deinit functions to remove debugfs directory and 1246 * it's file enteries. 1247 * @isc: iot_sim context 1248 * 1249 * Return: init status 1250 */ 1251 static QDF_STATUS 1252 iot_sim_debugfs_deinit(struct iot_sim_context *isc) 1253 { 1254 debugfs_remove_recursive(isc->iot_sim_dbgfs_ctx.iot_sim_dir_de); 1255 1256 return QDF_STATUS_SUCCESS; 1257 } 1258 1259 /* 1260 * iot_sim_remove_all_oper_rules - Function to remove all configured rules 1261 * for given operation 1262 * 1263 * @isc: iot sim context 1264 * @oper: iot sim operation 1265 * 1266 * Return: void 1267 */ 1268 static void 1269 iot_sim_remove_all_oper_rules(struct iot_sim_context *isc, 1270 enum iot_sim_operations oper) 1271 { 1272 uint16_t seq; 1273 uint8_t type, subtype, category = 0, action = 0; 1274 struct qdf_mac_addr zero_mac_addr = QDF_MAC_ADDR_ZERO_INIT; 1275 1276 for (seq = 0; seq < MAX_SEQ; seq++) { 1277 /* Remove rules for non-action type frames */ 1278 for (type = 0; type < N_FRAME_TYPE; type++) 1279 for (subtype = 0; subtype < N_FRAME_SUBTYPE; subtype++) 1280 iot_sim_delete_rule_for_mac(isc, oper, seq, 1281 type, subtype, 1282 &zero_mac_addr, 0); 1283 /* Remove rules for action frames */ 1284 for (category = 0; category < IOT_SIM_MAX_CAT; category++) 1285 for (action = 0; action < MAX_ACTION; action++) 1286 iot_sim_delete_rule_for_mac(isc, oper, seq, 1287 category, action, 1288 &zero_mac_addr, 1); 1289 } 1290 } 1291 1292 /* 1293 * iot_sim_remove_all_rules - Function to remove all configured rules 1294 * 1295 * @isc: iot sim context 1296 * 1297 * Return: void 1298 */ 1299 static void 1300 iot_sim_remove_all_rules(struct iot_sim_context *isc) 1301 { 1302 enum iot_sim_operations oper; 1303 1304 if (!isc) 1305 return; 1306 1307 for (oper = CONTENT_CHANGE; oper < IOT_SIM_MAX_OPERATION; oper++) 1308 iot_sim_remove_all_oper_rules(isc, oper); 1309 } 1310 1311 /** 1312 * iot_sim_debugfs_init() - debugfs functions to create debugfs directory and to 1313 * create debugfs enteries. 1314 * @isc: iot_sim context 1315 * 1316 * Return: init status 1317 */ 1318 static QDF_STATUS 1319 iot_sim_debugfs_init(struct iot_sim_context *isc) 1320 { 1321 struct dentry *dbgfs_dir = NULL; 1322 struct dentry *de = NULL; 1323 uint8_t i, pdev_id; 1324 char buf[32]; 1325 1326 if (!isc) 1327 return QDF_STATUS_E_FAILURE; 1328 1329 pdev_id = wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj); 1330 1331 qdf_mem_zero(buf, sizeof(buf)); 1332 snprintf(buf, sizeof(buf), "iot_sim_pdev%u", pdev_id); 1333 1334 dbgfs_dir = debugfs_create_dir(buf, NULL); 1335 isc->iot_sim_dbgfs_ctx.iot_sim_dir_de = dbgfs_dir; 1336 1337 if (!isc->iot_sim_dbgfs_ctx.iot_sim_dir_de) { 1338 iot_sim_err("dbgfs dir creation failed for pdev%u", pdev_id); 1339 return QDF_STATUS_E_FAILURE; 1340 } 1341 1342 for (i = 0; i < IOT_SIM_DEBUGFS_FILE_NUM; ++i) { 1343 de = debugfs_create_file(iot_sim_dbgfs_files[i].name, 1344 0644, 1345 dbgfs_dir, isc, 1346 iot_sim_dbgfs_files[i].ops); 1347 1348 if (!de) { 1349 iot_sim_err("dbgfs file creation failed for pdev%u", 1350 pdev_id); 1351 goto out; 1352 } 1353 isc->iot_sim_dbgfs_ctx.iot_sim_file_de[i] = de; 1354 } 1355 1356 return QDF_STATUS_SUCCESS; 1357 1358 out: 1359 debugfs_remove_recursive(dbgfs_dir); 1360 qdf_mem_set(isc->iot_sim_dbgfs_ctx.iot_sim_file_de, 1361 sizeof(isc->iot_sim_dbgfs_ctx.iot_sim_file_de), 0); 1362 1363 return QDF_STATUS_E_FAILURE; 1364 } 1365 1366 QDF_STATUS 1367 wlan_iot_sim_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, void *arg) 1368 { 1369 struct iot_sim_context *isc = NULL; 1370 1371 if (!pdev) { 1372 iot_sim_err("pdev is NULL"); 1373 return QDF_STATUS_E_NULL_VALUE; 1374 } 1375 1376 isc = qdf_mem_malloc(sizeof(struct iot_sim_context)); 1377 if (!isc) 1378 return QDF_STATUS_E_NOMEM; 1379 1380 isc->pdev_obj = pdev; 1381 1382 if (QDF_IS_STATUS_ERROR(iot_sim_debugfs_init(isc))) { 1383 qdf_mem_free(isc); 1384 iot_sim_info("iot_sim debugfs file creation failed"); 1385 return QDF_STATUS_E_FAILURE; 1386 } 1387 1388 qdf_set_macaddr_broadcast(&isc->bcast_peer.addr); 1389 qdf_spinlock_create(&isc->bcast_peer.iot_sim_lock); 1390 qdf_list_create(&isc->bcast_peer.list, 0); 1391 isc->bcn_buf = NULL; 1392 1393 wlan_objmgr_pdev_component_obj_attach(pdev, WLAN_IOT_SIM_COMP, 1394 (void *)isc, QDF_STATUS_SUCCESS); 1395 1396 iot_sim_debug("iot_sim component pdev%u object created", 1397 wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj)); 1398 1399 return QDF_STATUS_SUCCESS; 1400 } 1401 1402 QDF_STATUS 1403 wlan_iot_sim_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev, 1404 void *arg) 1405 { 1406 struct iot_sim_context *isc = NULL; 1407 1408 if (!pdev) { 1409 iot_sim_err("pdev is NULL"); 1410 return QDF_STATUS_E_NULL_VALUE; 1411 } 1412 1413 isc = wlan_objmgr_pdev_get_comp_private_obj(pdev, 1414 WLAN_IOT_SIM_COMP); 1415 if (isc) { 1416 wlan_objmgr_pdev_component_obj_detach(pdev, 1417 WLAN_IOT_SIM_COMP, 1418 (void *)isc); 1419 /* Deinitilise function pointers from iot_sim context */ 1420 iot_sim_debugfs_deinit(isc); 1421 iot_sim_remove_all_rules(isc); 1422 if (isc->bcn_buf) 1423 qdf_nbuf_free(isc->bcn_buf); 1424 qdf_spinlock_destroy(&isc->bcast_peer.iot_sim_lock); 1425 qdf_mem_free(isc); 1426 } 1427 iot_sim_debug("iot_sim component pdev%u object destroyed", 1428 wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj)); 1429 1430 return QDF_STATUS_SUCCESS; 1431 } 1432 1433