1 /* 2 * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: wlan_mgmt_txrx_tgt_api.c 22 * This file contains mgmt txrx public API definitions for 23 * southbound interface. 24 */ 25 26 #include <wmi_unified_param.h> 27 28 #include "wlan_mgmt_txrx_tgt_api.h" 29 #include "wlan_mgmt_txrx_utils_api.h" 30 #include "../../core/src/wlan_mgmt_txrx_main_i.h" 31 #include "wlan_objmgr_psoc_obj.h" 32 #include "wlan_objmgr_peer_obj.h" 33 #include "wlan_objmgr_pdev_obj.h" 34 #include "wlan_mgmt_txrx_rx_reo_tgt_api.h" 35 36 /** 37 * mgmt_get_spec_mgmt_action_subtype() - gets spec mgmt action subtype 38 * @action_code: action code 39 * 40 * This function returns the subtype for spectrum management action 41 * category. 42 * 43 * Return: mgmt frame type 44 */ 45 static enum mgmt_frame_type 46 mgmt_get_spec_mgmt_action_subtype(uint8_t action_code) 47 { 48 enum mgmt_frame_type frm_type; 49 50 switch (action_code) { 51 case ACTION_SPCT_MSR_REQ: 52 frm_type = MGMT_ACTION_MEAS_REQUEST; 53 break; 54 case ACTION_SPCT_MSR_RPRT: 55 frm_type = MGMT_ACTION_MEAS_REPORT; 56 break; 57 case ACTION_SPCT_TPC_REQ: 58 frm_type = MGMT_ACTION_TPC_REQUEST; 59 break; 60 case ACTION_SPCT_TPC_RPRT: 61 frm_type = MGMT_ACTION_TPC_REPORT; 62 break; 63 case ACTION_SPCT_CHL_SWITCH: 64 frm_type = MGMT_ACTION_CHAN_SWITCH; 65 break; 66 default: 67 frm_type = MGMT_FRM_UNSPECIFIED; 68 break; 69 } 70 71 return frm_type; 72 } 73 74 /** 75 * mgmt_get_qos_action_subtype() - gets qos action subtype 76 * @action_code: action code 77 * 78 * This function returns the subtype for qos action 79 * category. 80 * 81 * Return: mgmt frame type 82 */ 83 static enum mgmt_frame_type 84 mgmt_get_qos_action_subtype(uint8_t action_code) 85 { 86 enum mgmt_frame_type frm_type; 87 88 switch (action_code) { 89 case QOS_ADD_TS_REQ: 90 frm_type = MGMT_ACTION_QOS_ADD_TS_REQ; 91 break; 92 case QOS_ADD_TS_RSP: 93 frm_type = MGMT_ACTION_QOS_ADD_TS_RSP; 94 break; 95 case QOS_DEL_TS_REQ: 96 frm_type = MGMT_ACTION_QOS_DEL_TS_REQ; 97 break; 98 case QOS_SCHEDULE: 99 frm_type = MGMT_ACTION_QOS_SCHEDULE; 100 break; 101 case QOS_MAP_CONFIGURE: 102 frm_type = MGMT_ACTION_QOS_MAP_CONFIGURE; 103 break; 104 default: 105 frm_type = MGMT_FRM_UNSPECIFIED; 106 break; 107 } 108 109 return frm_type; 110 } 111 112 /** 113 * mgmt_get_dls_action_subtype() - gets dls action subtype 114 * @action_code: action code 115 * 116 * This function returns the subtype for dls action 117 * category. 118 * 119 * Return: mgmt frame type 120 */ 121 static enum mgmt_frame_type 122 mgmt_get_dls_action_subtype(uint8_t action_code) 123 { 124 enum mgmt_frame_type frm_type; 125 126 switch (action_code) { 127 case DLS_REQUEST: 128 frm_type = MGMT_ACTION_DLS_REQUEST; 129 break; 130 case DLS_RESPONSE: 131 frm_type = MGMT_ACTION_DLS_RESPONSE; 132 break; 133 case DLS_TEARDOWN: 134 frm_type = MGMT_ACTION_DLS_TEARDOWN; 135 break; 136 default: 137 frm_type = MGMT_FRM_UNSPECIFIED; 138 break; 139 } 140 141 return frm_type; 142 } 143 144 /** 145 * mgmt_get_back_action_subtype() - gets block ack action subtype 146 * @action_code: action code 147 * 148 * This function returns the subtype for block ack action 149 * category. 150 * 151 * Return: mgmt frame type 152 */ 153 static enum mgmt_frame_type 154 mgmt_get_back_action_subtype(uint8_t action_code) 155 { 156 enum mgmt_frame_type frm_type; 157 158 switch (action_code) { 159 case ADDBA_REQUEST: 160 frm_type = MGMT_ACTION_BA_ADDBA_REQUEST; 161 break; 162 case ADDBA_RESPONSE: 163 frm_type = MGMT_ACTION_BA_ADDBA_RESPONSE; 164 break; 165 case DELBA: 166 frm_type = MGMT_ACTION_BA_DELBA; 167 break; 168 default: 169 frm_type = MGMT_FRM_UNSPECIFIED; 170 break; 171 } 172 173 return frm_type; 174 } 175 176 /** 177 * mgmt_get_public_action_subtype() - gets public action subtype 178 * @action_code: action code 179 * 180 * This function returns the subtype for public action 181 * category. 182 * 183 * Return: mgmt frame type 184 */ 185 static enum mgmt_frame_type 186 mgmt_get_public_action_subtype(uint8_t action_code) 187 { 188 enum mgmt_frame_type frm_type; 189 190 switch (action_code) { 191 case PUB_ACTION_2040_BSS_COEXISTENCE: 192 frm_type = MGMT_ACTION_2040_BSS_COEXISTENCE; 193 break; 194 case PUB_ACTION_EXT_CHANNEL_SWITCH_ID: 195 frm_type = MGMT_ACTION_EXT_CHANNEL_SWITCH_ID; 196 break; 197 case PUB_ACTION_VENDOR_SPECIFIC: 198 frm_type = MGMT_ACTION_VENDOR_SPECIFIC; 199 break; 200 case PUB_ACTION_TDLS_DISCRESP: 201 frm_type = MGMT_ACTION_TDLS_DISCRESP; 202 break; 203 case PUB_ACTION_GAS_INITIAL_REQUEST: 204 frm_type = MGMT_ACTION_GAS_INITIAL_REQUEST; 205 break; 206 case PUB_ACTION_GAS_INITIAL_RESPONSE: 207 frm_type = MGMT_ACTION_GAS_INITIAL_RESPONSE; 208 break; 209 case PUB_ACTION_GAS_COMEBACK_REQUEST: 210 frm_type = MGMT_ACTION_GAS_COMEBACK_REQUEST; 211 break; 212 case PUB_ACTION_GAS_COMEBACK_RESPONSE: 213 frm_type = MGMT_ACTION_GAS_COMEBACK_RESPONSE; 214 break; 215 default: 216 frm_type = MGMT_FRM_UNSPECIFIED; 217 break; 218 } 219 220 return frm_type; 221 } 222 223 /** 224 * mgmt_get_rrm_action_subtype() - gets rrm action subtype 225 * @action_code: action code 226 * 227 * This function returns the subtype for rrm action 228 * category. 229 * 230 * Return: mgmt frame type 231 */ 232 static enum mgmt_frame_type 233 mgmt_get_rrm_action_subtype(uint8_t action_code) 234 { 235 enum mgmt_frame_type frm_type; 236 237 switch (action_code) { 238 case RRM_RADIO_MEASURE_REQ: 239 frm_type = MGMT_ACTION_RRM_RADIO_MEASURE_REQ; 240 break; 241 case RRM_RADIO_MEASURE_RPT: 242 frm_type = MGMT_ACTION_RRM_RADIO_MEASURE_RPT; 243 break; 244 case RRM_LINK_MEASUREMENT_REQ: 245 frm_type = MGMT_ACTION_RRM_LINK_MEASUREMENT_REQ; 246 break; 247 case RRM_LINK_MEASUREMENT_RPT: 248 frm_type = MGMT_ACTION_RRM_LINK_MEASUREMENT_RPT; 249 break; 250 case RRM_NEIGHBOR_REQ: 251 frm_type = MGMT_ACTION_RRM_NEIGHBOR_REQ; 252 break; 253 case RRM_NEIGHBOR_RPT: 254 frm_type = MGMT_ACTION_RRM_NEIGHBOR_RPT; 255 break; 256 default: 257 frm_type = MGMT_FRM_UNSPECIFIED; 258 break; 259 } 260 261 return frm_type; 262 } 263 264 static enum mgmt_frame_type 265 mgmt_get_ft_action_subtype(uint8_t action_code) 266 { 267 enum mgmt_frame_type frm_type; 268 269 switch (action_code) { 270 case FT_FAST_BSS_TRNST_REQ: 271 frm_type = MGMT_ACTION_FT_REQUEST; 272 break; 273 case FT_FAST_BSS_TRNST_RES: 274 frm_type = MGMT_ACTION_FT_RESPONSE; 275 break; 276 case FT_FAST_BSS_TRNST_CONFIRM: 277 frm_type = MGMT_ACTION_FT_CONFIRM; 278 break; 279 case FT_FAST_BSS_TRNST_ACK: 280 frm_type = MGMT_ACTION_FT_ACK; 281 break; 282 default: 283 frm_type = MGMT_FRM_UNSPECIFIED; 284 break; 285 } 286 287 return frm_type; 288 } 289 290 /** 291 * mgmt_get_ht_action_subtype() - gets ht action subtype 292 * @action_code: action code 293 * 294 * This function returns the subtype for ht action 295 * category. 296 * 297 * Return: mgmt frame type 298 */ 299 static enum mgmt_frame_type 300 mgmt_get_ht_action_subtype(uint8_t action_code) 301 { 302 enum mgmt_frame_type frm_type; 303 304 switch (action_code) { 305 case HT_ACTION_NOTIFY_CHANWIDTH: 306 frm_type = MGMT_ACTION_HT_NOTIFY_CHANWIDTH; 307 break; 308 case HT_ACTION_SMPS: 309 frm_type = MGMT_ACTION_HT_SMPS; 310 break; 311 case HT_ACTION_PSMP: 312 frm_type = MGMT_ACTION_HT_PSMP; 313 break; 314 case HT_ACTION_PCO_PHASE: 315 frm_type = MGMT_ACTION_HT_PCO_PHASE; 316 break; 317 case HT_ACTION_CSI: 318 frm_type = MGMT_ACTION_HT_CSI; 319 break; 320 case HT_ACTION_NONCOMPRESSED_BF: 321 frm_type = MGMT_ACTION_HT_NONCOMPRESSED_BF; 322 break; 323 case HT_ACTION_COMPRESSED_BF: 324 frm_type = MGMT_ACTION_HT_COMPRESSED_BF; 325 break; 326 case HT_ACTION_ASEL_IDX_FEEDBACK: 327 frm_type = MGMT_ACTION_HT_ASEL_IDX_FEEDBACK; 328 break; 329 default: 330 frm_type = MGMT_FRM_UNSPECIFIED; 331 break; 332 } 333 334 return frm_type; 335 } 336 337 /** 338 * mgmt_get_sa_query_action_subtype() - gets sa query action subtype 339 * @action_code: action code 340 * 341 * This function returns the subtype for sa query action 342 * category. 343 * 344 * Return: mgmt frame type 345 */ 346 static enum mgmt_frame_type 347 mgmt_get_sa_query_action_subtype(uint8_t action_code) 348 { 349 enum mgmt_frame_type frm_type; 350 351 switch (action_code) { 352 case SA_QUERY_REQUEST: 353 frm_type = MGMT_ACTION_SA_QUERY_REQUEST; 354 break; 355 case SA_QUERY_RESPONSE: 356 frm_type = MGMT_ACTION_SA_QUERY_RESPONSE; 357 break; 358 default: 359 frm_type = MGMT_FRM_UNSPECIFIED; 360 break; 361 } 362 363 return frm_type; 364 } 365 366 /** 367 * mgmt_get_pdpa_action_subtype() - gets pdpa action subtype 368 * @action_code: action code 369 * 370 * This function returns the subtype for protected dual public 371 * action category. 372 * 373 * Return: mgmt frame type 374 */ 375 static enum mgmt_frame_type 376 mgmt_get_pdpa_action_subtype(uint8_t action_code) 377 { 378 enum mgmt_frame_type frm_type; 379 380 switch (action_code) { 381 case PDPA_GAS_INIT_REQ: 382 frm_type = MGMT_ACTION_PDPA_GAS_INIT_REQ; 383 break; 384 case PDPA_GAS_INIT_RSP: 385 frm_type = MGMT_ACTION_PDPA_GAS_INIT_RSP; 386 break; 387 case PDPA_GAS_COMEBACK_REQ: 388 frm_type = MGMT_ACTION_PDPA_GAS_COMEBACK_REQ; 389 break; 390 case PDPA_GAS_COMEBACK_RSP: 391 frm_type = MGMT_ACTION_PDPA_GAS_COMEBACK_RSP; 392 break; 393 default: 394 frm_type = MGMT_FRM_UNSPECIFIED; 395 break; 396 } 397 398 return frm_type; 399 } 400 401 /** 402 * mgmt_get_wnm_action_subtype() - gets wnm action subtype 403 * @action_code: action code 404 * 405 * This function returns the subtype for wnm action 406 * category. 407 * 408 * Return: mgmt frame type 409 */ 410 static enum mgmt_frame_type 411 mgmt_get_wnm_action_subtype(uint8_t action_code) 412 { 413 enum mgmt_frame_type frm_type; 414 415 switch (action_code) { 416 case WNM_BSS_TM_QUERY: 417 frm_type = MGMT_ACTION_WNM_BSS_TM_QUERY; 418 break; 419 case WNM_BSS_TM_REQUEST: 420 frm_type = MGMT_ACTION_WNM_BSS_TM_REQUEST; 421 break; 422 case WNM_BSS_TM_RESPONSE: 423 frm_type = MGMT_ACTION_WNM_BSS_TM_RESPONSE; 424 break; 425 case WNM_NOTIF_REQUEST: 426 frm_type = MGMT_ACTION_WNM_NOTIF_REQUEST; 427 break; 428 case WNM_NOTIF_RESPONSE: 429 frm_type = MGMT_ACTION_WNM_NOTIF_RESPONSE; 430 break; 431 case WNM_FMS_REQ: 432 frm_type = MGMT_ACTION_WNM_FMS_REQ; 433 break; 434 case WNM_FMS_RESP: 435 frm_type = MGMT_ACTION_WNM_FMS_RESP; 436 break; 437 case WNM_TFS_REQ: 438 frm_type = MGMT_ACTION_WNM_TFS_REQ; 439 break; 440 case WNM_TFS_RESP: 441 frm_type = MGMT_ACTION_WNM_TFS_RESP; 442 break; 443 case WNM_TFS_NOTIFY: 444 frm_type = MGMT_ACTION_WNM_TFS_NOTIFY; 445 break; 446 case WNM_SLEEP_REQ: 447 frm_type = MGMT_ACTION_WNM_SLEEP_REQ; 448 break; 449 case WNM_SLEEP_RESP: 450 frm_type = MGMT_ACTION_WNM_SLEEP_RESP; 451 break; 452 case WNM_TIM_REQ: 453 frm_type = MGMT_ACTION_WNM_TFS_REQ; 454 break; 455 case WNM_TIM_RESP: 456 frm_type = MGMT_ACTION_WNM_TFS_RESP; 457 break; 458 default: 459 frm_type = MGMT_FRM_UNSPECIFIED; 460 break; 461 } 462 463 return frm_type; 464 } 465 466 /** 467 * mgmt_get_wnm_action_subtype() - gets tdls action subtype 468 * @action_code: action code 469 * 470 * This function returns the subtype for tdls action 471 * category. 472 * 473 * Return: mgmt frame type 474 */ 475 static enum mgmt_frame_type 476 mgmt_get_tdls_action_subtype(uint8_t action_code) 477 { 478 enum mgmt_frame_type frm_type; 479 480 switch (action_code) { 481 case TDLS_SETUP_REQUEST: 482 frm_type = MGMT_ACTION_TDLS_SETUP_REQ; 483 break; 484 case TDLS_SETUP_RESPONSE: 485 frm_type = MGMT_ACTION_TDLS_SETUP_RSP; 486 break; 487 case TDLS_SETUP_CONFIRM: 488 frm_type = MGMT_ACTION_TDLS_SETUP_CNF; 489 break; 490 case TDLS_TEARDOWN: 491 frm_type = MGMT_ACTION_TDLS_TEARDOWN; 492 break; 493 case TDLS_PEER_TRAFFIC_INDICATION: 494 frm_type = MGMT_ACTION_TDLS_PEER_TRAFFIC_IND; 495 break; 496 case TDLS_CHANNEL_SWITCH_REQUEST: 497 frm_type = MGMT_ACTION_TDLS_CH_SWITCH_REQ; 498 break; 499 case TDLS_CHANNEL_SWITCH_RESPONSE: 500 frm_type = MGMT_ACTION_TDLS_CH_SWITCH_RSP; 501 break; 502 case TDLS_PEER_PSM_REQUEST: 503 frm_type = MGMT_ACTION_TDLS_PEER_PSM_REQUEST; 504 break; 505 case TDLS_PEER_PSM_RESPONSE: 506 frm_type = MGMT_ACTION_TDLS_PEER_PSM_RESPONSE; 507 break; 508 case TDLS_PEER_TRAFFIC_RESPONSE: 509 frm_type = MGMT_ACTION_TDLS_PEER_TRAFFIC_RSP; 510 break; 511 case TDLS_DISCOVERY_REQUEST: 512 frm_type = MGMT_ACTION_TDLS_DIS_REQ; 513 break; 514 default: 515 frm_type = MGMT_FRM_UNSPECIFIED; 516 break; 517 } 518 519 return frm_type; 520 } 521 522 /** 523 * mgmt_get_mesh_action_subtype() - gets mesh action subtype 524 * @action_code: action code 525 * 526 * This function returns the subtype for mesh action 527 * category. 528 * 529 * Return: mgmt frame type 530 */ 531 static enum mgmt_frame_type 532 mgmt_get_mesh_action_subtype(uint8_t action_code) 533 { 534 enum mgmt_frame_type frm_type; 535 536 switch (action_code) { 537 case MESH_ACTION_LINK_METRIC_REPORT: 538 frm_type = MGMT_ACTION_MESH_LINK_METRIC_REPORT; 539 break; 540 case MESH_ACTION_HWMP_PATH_SELECTION: 541 frm_type = MGMT_ACTION_MESH_HWMP_PATH_SELECTION; 542 break; 543 case MESH_ACTION_GATE_ANNOUNCEMENT: 544 frm_type = MGMT_ACTION_MESH_GATE_ANNOUNCEMENT; 545 break; 546 case MESH_ACTION_CONGESTION_CONTROL_NOTIFICATION: 547 frm_type = MGMT_ACTION_MESH_CONGESTION_CONTROL_NOTIFICATION; 548 break; 549 case MESH_ACTION_MCCA_SETUP_REQUEST: 550 frm_type = MGMT_ACTION_MESH_MCCA_SETUP_REQUEST; 551 break; 552 case MESH_ACTION_MCCA_SETUP_REPLY: 553 frm_type = MGMT_ACTION_MESH_MCCA_SETUP_REPLY; 554 break; 555 case MESH_ACTION_MCCA_ADVERTISEMENT_REQUEST: 556 frm_type = MGMT_ACTION_MESH_MCCA_ADVERTISEMENT_REQUEST; 557 break; 558 case MESH_ACTION_MCCA_ADVERTISEMENT: 559 frm_type = MGMT_ACTION_MESH_MCCA_ADVERTISEMENT; 560 break; 561 case MESH_ACTION_MCCA_TEARDOWN: 562 frm_type = MGMT_ACTION_MESH_MCCA_TEARDOWN; 563 break; 564 case MESH_ACTION_TBTT_ADJUSTMENT_REQUEST: 565 frm_type = MGMT_ACTION_MESH_TBTT_ADJUSTMENT_REQUEST; 566 break; 567 case MESH_ACTION_TBTT_ADJUSTMENT_RESPONSE: 568 frm_type = MGMT_ACTION_MESH_TBTT_ADJUSTMENT_RESPONSE; 569 break; 570 default: 571 frm_type = MGMT_FRM_UNSPECIFIED; 572 break; 573 } 574 575 return frm_type; 576 } 577 578 /** 579 * mgmt_get_self_prot_action_subtype() - gets self prot. action subtype 580 * @action_code: action code 581 * 582 * This function returns the subtype for self protected action 583 * category. 584 * 585 * Return: mgmt frame type 586 */ 587 static enum mgmt_frame_type 588 mgmt_get_self_prot_action_subtype(uint8_t action_code) 589 { 590 enum mgmt_frame_type frm_type; 591 592 switch (action_code) { 593 case SP_MESH_PEERING_OPEN: 594 frm_type = MGMT_ACTION_SP_MESH_PEERING_OPEN; 595 break; 596 case SP_MESH_PEERING_CONFIRM: 597 frm_type = MGMT_ACTION_SP_MESH_PEERING_CONFIRM; 598 break; 599 case SP_MESH_PEERING_CLOSE: 600 frm_type = MGMT_ACTION_SP_MESH_PEERING_CLOSE; 601 break; 602 case SP_MGK_INFORM: 603 frm_type = MGMT_ACTION_SP_MGK_INFORM; 604 break; 605 case SP_MGK_ACK: 606 frm_type = MGMT_ACTION_SP_MGK_ACK; 607 break; 608 default: 609 frm_type = MGMT_FRM_UNSPECIFIED; 610 break; 611 } 612 613 return frm_type; 614 } 615 616 /** 617 * mgmt_get_wmm_action_subtype() - gets wmm action subtype 618 * @action_code: action code 619 * 620 * This function returns the subtype for wmm action 621 * category. 622 * 623 * Return: mgmt frame type 624 */ 625 static enum mgmt_frame_type 626 mgmt_get_wmm_action_subtype(uint8_t action_code) 627 { 628 enum mgmt_frame_type frm_type; 629 630 switch (action_code) { 631 case WMM_QOS_SETUP_REQ: 632 frm_type = MGMT_ACTION_WMM_QOS_SETUP_REQ; 633 break; 634 case WMM_QOS_SETUP_RESP: 635 frm_type = MGMT_ACTION_WMM_QOS_SETUP_RESP; 636 break; 637 case WMM_QOS_TEARDOWN: 638 frm_type = MGMT_ACTION_WMM_QOS_TEARDOWN; 639 break; 640 default: 641 frm_type = MGMT_FRM_UNSPECIFIED; 642 break; 643 } 644 645 return frm_type; 646 } 647 648 /** 649 * mgmt_get_vht_action_subtype() - gets vht action subtype 650 * @action_code: action code 651 * 652 * This function returns the subtype for vht action 653 * category. 654 * 655 * Return: mgmt frame type 656 */ 657 static enum mgmt_frame_type 658 mgmt_get_vht_action_subtype(uint8_t action_code) 659 { 660 enum mgmt_frame_type frm_type; 661 662 switch (action_code) { 663 case VHT_ACTION_COMPRESSED_BF: 664 frm_type = MGMT_ACTION_VHT_COMPRESSED_BF; 665 break; 666 case VHT_ACTION_GID_NOTIF: 667 frm_type = MGMT_ACTION_VHT_GID_NOTIF; 668 break; 669 case VHT_ACTION_OPMODE_NOTIF: 670 frm_type = MGMT_ACTION_VHT_OPMODE_NOTIF; 671 break; 672 default: 673 frm_type = MGMT_FRM_UNSPECIFIED; 674 break; 675 } 676 677 return frm_type; 678 } 679 680 /** 681 * mgmt_get_fst_action_subtype() - gets fst action subtype 682 * @action_code: action code 683 * 684 * This function returns the subtype for fst action 685 * category. 686 * 687 * Return: mgmt frame type 688 */ 689 static enum mgmt_frame_type 690 mgmt_get_fst_action_subtype(uint8_t action_code) 691 { 692 enum mgmt_frame_type frm_type; 693 694 switch (action_code) { 695 case FST_SETUP_REQ: 696 frm_type = MGMT_ACTION_FST_SETUP_REQ; 697 break; 698 case FST_SETUP_RSP: 699 frm_type = MGMT_ACTION_FST_SETUP_RSP; 700 break; 701 case FST_TEAR_DOWN: 702 frm_type = MGMT_ACTION_FST_TEAR_DOWN; 703 break; 704 case FST_ACK_REQ: 705 frm_type = MGMT_ACTION_FST_ACK_REQ; 706 break; 707 case FST_ACK_RSP: 708 frm_type = MGMT_ACTION_FST_ACK_RSP; 709 break; 710 case FST_ON_CHANNEL_TUNNEL: 711 frm_type = MGMT_ACTION_FST_ON_CHANNEL_TUNNEL; 712 break; 713 default: 714 frm_type = MGMT_FRM_UNSPECIFIED; 715 break; 716 } 717 718 return frm_type; 719 } 720 721 /** 722 * mgmt_get_rvs_action_subtype() - gets rvs action subtype 723 * @action_code: action code 724 * 725 * This function returns the subtype for rvs action 726 * category. 727 * 728 * Return: mgmt frame type 729 */ 730 static enum mgmt_frame_type 731 mgmt_get_rvs_action_subtype(uint8_t action_code) 732 { 733 enum mgmt_frame_type frm_type; 734 735 switch (action_code) { 736 case SCS_REQ: 737 frm_type = MGMT_ACTION_SCS_REQ; 738 break; 739 case SCS_RSP: 740 frm_type = MGMT_ACTION_SCS_RSP; 741 break; 742 case GROUP_MEMBERSHIP_REQ: 743 frm_type = MGMT_ACTION_GROUP_MEMBERSHIP_REQ; 744 break; 745 case GROUP_MEMBERSHIP_RSP: 746 frm_type = MGMT_ACTION_GROUP_MEMBERSHIP_RSP; 747 break; 748 case MCSC_REQ: 749 frm_type = MGMT_ACTION_MCSC_REQ; 750 break; 751 case MCSC_RSP: 752 frm_type = MGMT_ACTION_MCSC_RSP; 753 break; 754 default: 755 frm_type = MGMT_FRM_UNSPECIFIED; 756 break; 757 } 758 759 return frm_type; 760 } 761 762 /** 763 * mgmt_get_twt_action_subtype() - gets twt action subtype 764 * @action_code: action code 765 * 766 * This function returns the subtype for twt action 767 * category. 768 * 769 * Return: mgmt frame type 770 */ 771 static enum mgmt_frame_type 772 mgmt_get_twt_action_subtype(uint8_t action_code) 773 { 774 enum mgmt_frame_type frm_type; 775 776 switch (action_code) { 777 case TWT_SETUP: 778 frm_type = MGMT_ACTION_TWT_SETUP; 779 break; 780 case TWT_TEARDOWN: 781 frm_type = MGMT_ACTION_TWT_TEARDOWN; 782 break; 783 case TWT_INFORMATION: 784 frm_type = MGMT_ACTION_TWT_INFORMATION; 785 break; 786 default: 787 frm_type = MGMT_FRM_UNSPECIFIED; 788 break; 789 } 790 791 return frm_type; 792 } 793 794 #ifdef WLAN_FEATURE_11BE 795 /** 796 * mgmt_get_protected_eht_action_subtype() - gets protected EHT action subtype 797 * @action_code: action code 798 * 799 * This function returns the subtype for protected EHT action category. 800 * 801 * Return: mgmt frame type 802 */ 803 static enum mgmt_frame_type 804 mgmt_get_protected_eht_action_subtype(uint8_t action_code) 805 { 806 enum mgmt_frame_type frm_type; 807 808 switch (action_code) { 809 case EHT_T2LM_REQUEST: 810 frm_type = MGMT_ACTION_EHT_T2LM_REQUEST; 811 break; 812 case EHT_T2LM_RESPONSE: 813 frm_type = MGMT_ACTION_EHT_T2LM_RESPONSE; 814 break; 815 case EHT_T2LM_TEARDOWN: 816 frm_type = MGMT_ACTION_EHT_T2LM_TEARDOWN; 817 break; 818 default: 819 frm_type = MGMT_FRM_UNSPECIFIED; 820 break; 821 } 822 823 return frm_type; 824 } 825 #else 826 static enum mgmt_frame_type 827 mgmt_get_protected_eht_action_subtype(uint8_t action_code) 828 { 829 return MGMT_FRM_UNSPECIFIED; 830 } 831 #endif /* WLAN_FEATURE_11BE */ 832 833 /** 834 * mgmt_txrx_get_action_frm_subtype() - gets action frm subtype 835 * @mpdu_data_ptr: pointer to mpdu data 836 * 837 * This function determines the action category of the frame 838 * and calls respective function to get mgmt frame type. 839 * 840 * Return: mgmt frame type 841 */ 842 static enum mgmt_frame_type 843 mgmt_txrx_get_action_frm_subtype(uint8_t *mpdu_data_ptr) 844 { 845 struct action_frm_hdr *action_hdr = 846 (struct action_frm_hdr *)mpdu_data_ptr; 847 enum mgmt_frame_type frm_type; 848 849 switch (action_hdr->action_category) { 850 case ACTION_CATEGORY_SPECTRUM_MGMT: 851 frm_type = mgmt_get_spec_mgmt_action_subtype( 852 action_hdr->action_code); 853 break; 854 case ACTION_FAST_BSS_TRNST: 855 frm_type = mgmt_get_ft_action_subtype(action_hdr->action_code); 856 break; 857 case ACTION_CATEGORY_QOS: 858 frm_type = mgmt_get_qos_action_subtype(action_hdr->action_code); 859 break; 860 case ACTION_CATEGORY_DLS: 861 frm_type = mgmt_get_dls_action_subtype(action_hdr->action_code); 862 break; 863 case ACTION_CATEGORY_BACK: 864 frm_type = mgmt_get_back_action_subtype( 865 action_hdr->action_code); 866 break; 867 case ACTION_CATEGORY_PUBLIC: 868 frm_type = mgmt_get_public_action_subtype( 869 action_hdr->action_code); 870 break; 871 case ACTION_CATEGORY_RRM: 872 frm_type = mgmt_get_rrm_action_subtype(action_hdr->action_code); 873 break; 874 case ACTION_CATEGORY_HT: 875 frm_type = mgmt_get_ht_action_subtype(action_hdr->action_code); 876 break; 877 case ACTION_CATEGORY_SA_QUERY: 878 frm_type = mgmt_get_sa_query_action_subtype( 879 action_hdr->action_code); 880 break; 881 case ACTION_CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION: 882 frm_type = mgmt_get_pdpa_action_subtype( 883 action_hdr->action_code); 884 break; 885 case ACTION_CATEGORY_WNM: 886 frm_type = mgmt_get_wnm_action_subtype(action_hdr->action_code); 887 break; 888 case ACTION_CATEGORY_TDLS: 889 frm_type = mgmt_get_tdls_action_subtype( 890 action_hdr->action_code); 891 break; 892 case ACTION_CATEGORY_MESH_ACTION: 893 frm_type = mgmt_get_mesh_action_subtype( 894 action_hdr->action_code); 895 break; 896 case ACTION_CATEGORY_SELF_PROTECTED: 897 frm_type = mgmt_get_self_prot_action_subtype( 898 action_hdr->action_code); 899 break; 900 case ACTION_CATEGORY_WMM: 901 frm_type = mgmt_get_wmm_action_subtype(action_hdr->action_code); 902 break; 903 case ACTION_CATEGORY_VHT: 904 frm_type = mgmt_get_vht_action_subtype(action_hdr->action_code); 905 break; 906 case ACTION_CATEGORY_VENDOR_SPECIFIC: 907 frm_type = MGMT_ACTION_CATEGORY_VENDOR_SPECIFIC; 908 break; 909 case ACTION_CATEGORY_VENDOR_SPECIFIC_PROTECTED: 910 frm_type = MGMT_ACTION_CATEGORY_VENDOR_SPECIFIC_PROTECTED; 911 break; 912 case ACTION_CATEGORY_FST: 913 frm_type = mgmt_get_fst_action_subtype(action_hdr->action_code); 914 break; 915 case ACTION_CATEGORY_RVS: 916 frm_type = 917 mgmt_get_rvs_action_subtype(action_hdr->action_code); 918 break; 919 case ACTION_CATEGORY_USIG: 920 frm_type = 921 mgmt_get_twt_action_subtype(action_hdr->action_code); 922 break; 923 case ACTION_CATEGORY_PROTECTED_EHT: 924 frm_type = mgmt_get_protected_eht_action_subtype( 925 action_hdr->action_code); 926 break; 927 default: 928 frm_type = MGMT_FRM_UNSPECIFIED; 929 break; 930 } 931 932 return frm_type; 933 } 934 935 /** 936 * mgmt_txrx_get_frm_type() - gets mgmt frm type 937 * @mgmt_subtype: mgmt subtype 938 * @mpdu_data_ptr: pointer to mpdu data 939 * 940 * This function returns mgmt frame type of the frame 941 * based on the mgmt subtype. 942 * 943 * Return: mgmt frame type 944 */ 945 static enum mgmt_frame_type 946 mgmt_txrx_get_frm_type(uint8_t mgmt_subtype, uint8_t *mpdu_data_ptr) 947 { 948 enum mgmt_frame_type frm_type; 949 950 switch (mgmt_subtype) { 951 case MGMT_SUBTYPE_ASSOC_REQ: 952 frm_type = MGMT_ASSOC_REQ; 953 break; 954 case MGMT_SUBTYPE_ASSOC_RESP: 955 frm_type = MGMT_ASSOC_RESP; 956 break; 957 case MGMT_SUBTYPE_REASSOC_REQ: 958 frm_type = MGMT_ASSOC_REQ; 959 break; 960 case MGMT_SUBTYPE_REASSOC_RESP: 961 frm_type = MGMT_REASSOC_RESP; 962 break; 963 case MGMT_SUBTYPE_PROBE_REQ: 964 frm_type = MGMT_PROBE_REQ; 965 break; 966 case MGMT_SUBTYPE_PROBE_RESP: 967 frm_type = MGMT_PROBE_RESP; 968 break; 969 case MGMT_SUBTYPE_BEACON: 970 frm_type = MGMT_BEACON; 971 break; 972 case MGMT_SUBTYPE_ATIM: 973 frm_type = MGMT_ATIM; 974 break; 975 case MGMT_SUBTYPE_DISASSOC: 976 frm_type = MGMT_DISASSOC; 977 break; 978 case MGMT_SUBTYPE_AUTH: 979 frm_type = MGMT_AUTH; 980 break; 981 case MGMT_SUBTYPE_DEAUTH: 982 frm_type = MGMT_DEAUTH; 983 break; 984 case MGMT_SUBTYPE_ACTION: 985 case MGMT_SUBTYPE_ACTION_NO_ACK: 986 frm_type = mgmt_txrx_get_action_frm_subtype(mpdu_data_ptr); 987 break; 988 default: 989 frm_type = MGMT_FRM_UNSPECIFIED; 990 break; 991 } 992 993 return frm_type; 994 } 995 996 #ifdef WLAN_IOT_SIM_SUPPORT 997 static QDF_STATUS simulation_frame_update(struct wlan_objmgr_psoc *psoc, 998 qdf_nbuf_t buf, 999 struct mgmt_rx_event_params *rx_param) 1000 { 1001 uint8_t *addr = NULL; 1002 struct wlan_objmgr_vdev *vdev = NULL; 1003 uint8_t pdevid = 0; 1004 wlan_objmgr_ref_dbgid dbgid; 1005 struct wlan_lmac_if_rx_ops *rx_ops = NULL; 1006 struct wlan_objmgr_pdev *pdev; 1007 struct ieee80211_frame *wh; 1008 u_int8_t *data; 1009 QDF_STATUS status = QDF_STATUS_SUCCESS; 1010 1011 rx_ops = wlan_psoc_get_lmac_if_rxops(psoc); 1012 if (rx_ops && rx_ops->iot_sim_rx_ops.iot_sim_cmd_handler) { 1013 data = (uint8_t *)qdf_nbuf_data(buf); 1014 wh = (struct ieee80211_frame *)data; 1015 addr = (uint8_t *)wh->i_addr3; 1016 pdevid = rx_param->pdev_id; 1017 dbgid = WLAN_IOT_SIM_ID; 1018 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)addr)) { 1019 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdevid, 1020 dbgid); 1021 if (pdev) { 1022 vdev = wlan_objmgr_pdev_get_first_vdev(pdev, 1023 dbgid); 1024 wlan_objmgr_pdev_release_ref(pdev, dbgid); 1025 } 1026 } else 1027 vdev = wlan_objmgr_get_vdev_by_macaddr_from_psoc(psoc, 1028 pdevid, 1029 addr, 1030 dbgid); 1031 if (vdev) { 1032 status = rx_ops->iot_sim_rx_ops. 1033 iot_sim_cmd_handler(vdev, buf, 1034 NULL, false, 1035 rx_param); 1036 if (status == QDF_STATUS_E_NULL_VALUE) { 1037 wlan_objmgr_vdev_release_ref(vdev, dbgid); 1038 mgmt_txrx_debug("iot_sim:Pkt processed at RX"); 1039 return status; 1040 } 1041 wlan_objmgr_vdev_release_ref(vdev, dbgid); 1042 } 1043 } 1044 return status; 1045 } 1046 #else 1047 static QDF_STATUS simulation_frame_update(struct wlan_objmgr_psoc *psoc, 1048 qdf_nbuf_t buf, 1049 struct mgmt_rx_event_params *rx_param) 1050 { 1051 return QDF_STATUS_SUCCESS; 1052 } 1053 #endif 1054 1055 /** 1056 * wlan_mgmt_rx_beacon_rate_limit() - rate limiting mgmt beacons 1057 * @psoc - pointer to psoc struct 1058 * @mgmt_rx_params - rx params 1059 * 1060 * This function will drop the beacons if the number of beacons 1061 * received is greater than the percentage of limit of beacons to max 1062 * count of beacons, when beacon rate limiting is enabled 1063 * 1064 * Return : QDF_STATUS if success, else QDF_STATUS_E_RESOURCES 1065 */ 1066 static QDF_STATUS wlan_mgmt_rx_beacon_rate_limit(struct wlan_objmgr_psoc *psoc, 1067 struct mgmt_rx_event_params 1068 *mgmt_rx_params) 1069 { 1070 struct wlan_objmgr_pdev *pdev = NULL; 1071 1072 pdev = wlan_objmgr_get_pdev_by_id(psoc, mgmt_rx_params->pdev_id, 1073 WLAN_MGMT_SB_ID); 1074 1075 if (pdev && pdev->pdev_objmgr.bcn.bcn_rate_limit) { 1076 uint64_t b_limit = qdf_do_div( 1077 (wlan_pdev_get_max_beacon_count(pdev) * 1078 wlan_pdev_get_max_beacon_limit(pdev)), 100); 1079 wlan_pdev_incr_wlan_beacon_count(pdev); 1080 1081 if (wlan_pdev_get_wlan_beacon_count(pdev) >= 1082 wlan_pdev_get_max_beacon_count(pdev)) 1083 wlan_pdev_set_wlan_beacon_count(pdev, 0); 1084 1085 if (wlan_pdev_get_wlan_beacon_count(pdev) >= b_limit) { 1086 wlan_pdev_incr_dropped_beacon_count(pdev); 1087 wlan_objmgr_pdev_release_ref(pdev, WLAN_MGMT_SB_ID); 1088 return QDF_STATUS_E_RESOURCES; 1089 } 1090 } 1091 1092 if (pdev) 1093 wlan_objmgr_pdev_release_ref(pdev, WLAN_MGMT_SB_ID); 1094 1095 return QDF_STATUS_SUCCESS; 1096 } 1097 1098 /** 1099 * wlan_mgmt_txrx_rx_handler_list_copy() - copies rx handler list 1100 * @rx_handler: pointer to rx handler list 1101 * @rx_handler_head: pointer to head of the copies list 1102 * @rx_handler_tail: pointer to tail of the copies list 1103 * 1104 * This function copies the rx handler linked list into a local 1105 * linked list. 1106 * 1107 * Return: QDF_STATUS_SUCCESS in case of success 1108 */ 1109 static QDF_STATUS wlan_mgmt_txrx_rx_handler_list_copy( 1110 struct mgmt_rx_handler *rx_handler, 1111 struct mgmt_rx_handler **rx_handler_head, 1112 struct mgmt_rx_handler **rx_handler_tail) 1113 { 1114 struct mgmt_rx_handler *rx_handler_node; 1115 1116 while (rx_handler) { 1117 rx_handler_node = 1118 qdf_mem_malloc_atomic(sizeof(*rx_handler_node)); 1119 if (!rx_handler_node) { 1120 mgmt_txrx_err_rl("Couldn't allocate memory for rx handler node"); 1121 return QDF_STATUS_E_NOMEM; 1122 } 1123 1124 rx_handler_node->comp_id = rx_handler->comp_id; 1125 rx_handler_node->rx_cb = rx_handler->rx_cb; 1126 rx_handler_node->next = NULL; 1127 1128 if (!(*rx_handler_head)) { 1129 *rx_handler_head = rx_handler_node; 1130 *rx_handler_tail = *rx_handler_head; 1131 } else { 1132 (*rx_handler_tail)->next = rx_handler_node; 1133 *rx_handler_tail = (*rx_handler_tail)->next; 1134 } 1135 rx_handler = rx_handler->next; 1136 } 1137 1138 return QDF_STATUS_SUCCESS; 1139 } 1140 1141 static bool 1142 mgmt_rx_is_bssid_valid(struct qdf_mac_addr *mac_addr) 1143 { 1144 if (qdf_is_macaddr_group(mac_addr) || 1145 qdf_is_macaddr_zero(mac_addr)) 1146 return false; 1147 1148 return true; 1149 } 1150 1151 QDF_STATUS tgt_mgmt_txrx_rx_frame_handler( 1152 struct wlan_objmgr_psoc *psoc, 1153 qdf_nbuf_t buf, 1154 struct mgmt_rx_event_params *mgmt_rx_params) 1155 { 1156 struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx; 1157 struct ieee80211_frame *wh; 1158 qdf_nbuf_t copy_buf; 1159 struct wlan_objmgr_peer *peer = NULL; 1160 uint8_t mgmt_type, mgmt_subtype; 1161 uint8_t *mac_addr, *mpdu_data_ptr; 1162 enum mgmt_frame_type frm_type; 1163 struct mgmt_rx_handler *rx_handler; 1164 struct mgmt_rx_handler *rx_handler_head = NULL, *rx_handler_tail = NULL; 1165 u_int8_t *data, *ivp = NULL; 1166 uint16_t buflen; 1167 uint16_t len = 0; 1168 QDF_STATUS status = QDF_STATUS_SUCCESS; 1169 bool is_from_addr_valid, is_bssid_valid; 1170 1171 if (!buf) { 1172 mgmt_txrx_err("buffer passed is NULL"); 1173 return QDF_STATUS_E_INVAL; 1174 } 1175 1176 if (!psoc) { 1177 mgmt_txrx_err("psoc_ctx passed is NULL"); 1178 qdf_nbuf_free(buf); 1179 return QDF_STATUS_E_INVAL; 1180 } 1181 1182 data = (uint8_t *)qdf_nbuf_data(buf); 1183 wh = (struct ieee80211_frame *)data; 1184 buflen = qdf_nbuf_len(buf); 1185 1186 /** 1187 * TO DO (calculate pdev) 1188 * Waiting for a new parameter: pdev id to get added in rx event 1189 */ 1190 1191 mgmt_type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 1192 mgmt_subtype = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 1193 1194 if (mgmt_type != IEEE80211_FC0_TYPE_MGT && 1195 mgmt_type != IEEE80211_FC0_TYPE_CTL) { 1196 mgmt_txrx_err("Rx event doesn't contain a mgmt/ctrl packet, %d", 1197 mgmt_type); 1198 qdf_nbuf_free(buf); 1199 return QDF_STATUS_E_FAILURE; 1200 } 1201 1202 is_from_addr_valid = mgmt_rx_is_bssid_valid((struct qdf_mac_addr *) 1203 wh->i_addr2); 1204 is_bssid_valid = mgmt_rx_is_bssid_valid((struct qdf_mac_addr *) 1205 wh->i_addr3); 1206 1207 if (!is_from_addr_valid && !is_bssid_valid) { 1208 mgmt_txrx_debug_rl("from addr "QDF_MAC_ADDR_FMT" bssid addr "QDF_MAC_ADDR_FMT" both not valid, dropping them", 1209 QDF_MAC_ADDR_REF(wh->i_addr2), 1210 QDF_MAC_ADDR_REF(wh->i_addr3)); 1211 qdf_nbuf_free(buf); 1212 return QDF_STATUS_E_FAILURE; 1213 } 1214 1215 if (mgmt_type == IEEE80211_FC0_TYPE_MGT && 1216 (mgmt_subtype == MGMT_SUBTYPE_BEACON || 1217 mgmt_subtype == MGMT_SUBTYPE_PROBE_RESP) && 1218 !(is_from_addr_valid && is_bssid_valid)) { 1219 mgmt_txrx_debug_rl("from addr "QDF_MAC_ADDR_FMT" bssid addr "QDF_MAC_ADDR_FMT" not valid, modifying them", 1220 QDF_MAC_ADDR_REF(wh->i_addr2), 1221 QDF_MAC_ADDR_REF(wh->i_addr3)); 1222 if (!is_from_addr_valid) 1223 qdf_mem_copy(wh->i_addr2, wh->i_addr3, 1224 QDF_MAC_ADDR_SIZE); 1225 else 1226 qdf_mem_copy(wh->i_addr3, wh->i_addr2, 1227 QDF_MAC_ADDR_SIZE); 1228 } 1229 1230 /* mpdu_data_ptr is pointer to action header */ 1231 mpdu_data_ptr = (uint8_t *)qdf_nbuf_data(buf) + 1232 sizeof(struct ieee80211_frame); 1233 1234 if (wh->i_fc[1] & IEEE80211_FC1_ORDER) { 1235 /* Adjust the offset taking into consideration HT control field 1236 * length, in the case when peer sends a frame with HT/VHT/HE 1237 * ctrl field in the header(when frame is transmitted in TB 1238 * PPDU format). 1239 */ 1240 mpdu_data_ptr += IEEE80211_HT_CTRL_LEN; 1241 len = IEEE80211_HT_CTRL_LEN; 1242 mgmt_txrx_debug_rl("HT control field present!"); 1243 } 1244 1245 if ((wh->i_fc[1] & IEEE80211_FC1_WEP) && 1246 !qdf_is_macaddr_group((struct qdf_mac_addr *)wh->i_addr1) && 1247 !qdf_is_macaddr_broadcast((struct qdf_mac_addr *)wh->i_addr1)) { 1248 1249 if (buflen > (sizeof(struct ieee80211_frame) + 1250 WLAN_HDR_EXT_IV_LEN)) 1251 ivp = data + sizeof(struct ieee80211_frame) + len; 1252 1253 /* Set mpdu_data_ptr based on EXT IV bit 1254 * if EXT IV bit set, CCMP using PMF 8 bytes of IV is present 1255 * else for WEP using PMF, 4 bytes of IV is present 1256 */ 1257 if (ivp && (ivp[WLAN_HDR_IV_LEN] & WLAN_HDR_EXT_IV_BIT)) { 1258 if (buflen <= (sizeof(struct ieee80211_frame) 1259 + IEEE80211_CCMP_HEADERLEN)) { 1260 qdf_nbuf_free(buf); 1261 return QDF_STATUS_E_FAILURE; 1262 } 1263 mpdu_data_ptr += IEEE80211_CCMP_HEADERLEN; 1264 } else { 1265 if (buflen <= (sizeof(struct ieee80211_frame) 1266 + WLAN_HDR_EXT_IV_LEN)) { 1267 qdf_nbuf_free(buf); 1268 return QDF_STATUS_E_FAILURE; 1269 } 1270 mpdu_data_ptr += WLAN_HDR_EXT_IV_LEN; 1271 } 1272 } 1273 1274 if (mgmt_type == IEEE80211_FC0_TYPE_MGT) { 1275 frm_type = mgmt_txrx_get_frm_type(mgmt_subtype, mpdu_data_ptr); 1276 if (frm_type == MGMT_FRM_UNSPECIFIED) { 1277 mgmt_txrx_debug_rl( 1278 "Unspecified mgmt frame type fc: %x %x", wh->i_fc[0], 1279 wh->i_fc[1]); 1280 qdf_nbuf_free(buf); 1281 return QDF_STATUS_E_FAILURE; 1282 } 1283 } else { 1284 frm_type = MGMT_CTRL_FRAME; 1285 } 1286 1287 if (mgmt_type == IEEE80211_FC0_TYPE_MGT && 1288 !(mgmt_subtype == MGMT_SUBTYPE_BEACON || 1289 mgmt_subtype == MGMT_SUBTYPE_PROBE_RESP || 1290 mgmt_subtype == MGMT_SUBTYPE_PROBE_REQ)) 1291 mgmt_txrx_debug("Rcvd mgmt frame subtype %x (frame type %u) from "QDF_MAC_ADDR_FMT", seq_num = %d, rssi = %d tsf_delta: %u", 1292 mgmt_subtype, frm_type, 1293 QDF_MAC_ADDR_REF(wh->i_addr2), 1294 (le16toh(*(uint16_t *)wh->i_seq) >> 1295 WLAN_SEQ_SEQ_SHIFT), mgmt_rx_params->rssi, 1296 mgmt_rx_params->tsf_delta); 1297 1298 /* Print a hexdump of packet for host debug */ 1299 if (mgmt_type == IEEE80211_FC0_TYPE_MGT && 1300 ((mgmt_rx_params->status & WMI_HOST_RXERR_PN) || 1301 (mgmt_rx_params->status & WMI_HOST_RXERR_CRC) || 1302 (mgmt_rx_params->status & WMI_HOST_RXERR_DECRYPT) || 1303 (mgmt_rx_params->status & WMI_HOST_RXERR_MIC) || 1304 (mgmt_rx_params->status & WMI_HOST_RXERR_KEY_CACHE_MISS))) { 1305 uint64_t curr_pn, prev_pn; 1306 uint8_t *pn = NULL; 1307 1308 pn = mgmt_rx_params->pn_params.curr_pn; 1309 curr_pn = qdf_le64_to_cpu(*((uint64_t *)pn)); 1310 1311 pn = mgmt_rx_params->pn_params.prev_pn; 1312 prev_pn = qdf_le64_to_cpu(*((uint64_t *)pn)); 1313 1314 mgmt_txrx_debug("Current PN=0x%llx Previous PN=0x%llx. Packet dumped below", 1315 curr_pn, prev_pn); 1316 qdf_trace_hex_dump(QDF_MODULE_ID_MGMT_TXRX, 1317 QDF_TRACE_LEVEL_DEBUG, data, buflen); 1318 } 1319 1320 if (simulation_frame_update(psoc, buf, mgmt_rx_params)) 1321 return QDF_STATUS_E_FAILURE; 1322 1323 mgmt_txrx_psoc_ctx = (struct mgmt_txrx_priv_psoc_context *) 1324 wlan_objmgr_psoc_get_comp_private_obj(psoc, 1325 WLAN_UMAC_COMP_MGMT_TXRX); 1326 1327 qdf_spin_lock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock); 1328 rx_handler = mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[frm_type]; 1329 if (rx_handler) { 1330 status = wlan_mgmt_txrx_rx_handler_list_copy(rx_handler, 1331 &rx_handler_head, &rx_handler_tail); 1332 if (status != QDF_STATUS_SUCCESS) { 1333 qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock); 1334 qdf_nbuf_free(buf); 1335 goto rx_handler_mem_free; 1336 } 1337 } 1338 1339 if (mgmt_type == IEEE80211_FC0_TYPE_MGT) { 1340 rx_handler = 1341 mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[MGMT_FRAME_TYPE_ALL]; 1342 if (rx_handler) { 1343 status = wlan_mgmt_txrx_rx_handler_list_copy( 1344 rx_handler, &rx_handler_head, &rx_handler_tail); 1345 if (status != QDF_STATUS_SUCCESS) { 1346 qdf_spin_unlock_bh( 1347 &mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock); 1348 qdf_nbuf_free(buf); 1349 goto rx_handler_mem_free; 1350 } 1351 } 1352 } 1353 1354 if (!rx_handler_head) { 1355 qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock); 1356 mgmt_txrx_debug("No rx callback registered for frm_type: %d", 1357 frm_type); 1358 qdf_nbuf_free(buf); 1359 return QDF_STATUS_E_FAILURE; 1360 } 1361 qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock); 1362 1363 if (mgmt_subtype == MGMT_SUBTYPE_BEACON && 1364 mgmt_rx_params->is_conn_ap.is_conn_ap_frm == 0) { 1365 status = wlan_mgmt_rx_beacon_rate_limit(psoc, mgmt_rx_params); 1366 if (QDF_IS_STATUS_ERROR(status)) { 1367 qdf_nbuf_free(buf); 1368 goto rx_handler_mem_free; 1369 } 1370 } 1371 1372 mac_addr = (uint8_t *)wh->i_addr2; 1373 /* 1374 * peer can be NULL in following 2 scenarios: 1375 * 1. broadcast frame received 1376 * 2. operating in monitor mode 1377 * 1378 * and in both scenarios, the receiver of frame 1379 * is expected to do processing accordingly considerng 1380 * the fact that peer = NULL can be received and is a valid 1381 * scenario. 1382 */ 1383 peer = wlan_objmgr_get_peer(psoc, mgmt_rx_params->pdev_id, 1384 mac_addr, WLAN_MGMT_SB_ID); 1385 if (!peer && !qdf_is_macaddr_broadcast( 1386 (struct qdf_mac_addr *)wh->i_addr1)) { 1387 mac_addr = (uint8_t *)wh->i_addr1; 1388 peer = wlan_objmgr_get_peer(psoc, 1389 mgmt_rx_params->pdev_id, 1390 mac_addr, WLAN_MGMT_SB_ID); 1391 } 1392 1393 rx_handler = rx_handler_head; 1394 while (rx_handler->next) { 1395 copy_buf = qdf_nbuf_clone(buf); 1396 1397 if (!copy_buf) { 1398 rx_handler = rx_handler->next; 1399 continue; 1400 } 1401 1402 rx_handler->rx_cb(psoc, peer, copy_buf, 1403 mgmt_rx_params, frm_type); 1404 rx_handler = rx_handler->next; 1405 } 1406 rx_handler->rx_cb(psoc, peer, buf, 1407 mgmt_rx_params, frm_type); 1408 1409 if (peer) 1410 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_SB_ID); 1411 1412 rx_handler_mem_free: 1413 while (rx_handler_head) { 1414 rx_handler = rx_handler_head; 1415 rx_handler_head = rx_handler_head->next; 1416 qdf_mem_free(rx_handler); 1417 } 1418 1419 return status; 1420 } 1421 1422 QDF_STATUS tgt_mgmt_txrx_tx_completion_handler( 1423 struct wlan_objmgr_pdev *pdev, 1424 uint32_t desc_id, uint32_t status, 1425 void *tx_compl_params) 1426 { 1427 struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx; 1428 struct mgmt_txrx_desc_elem_t *mgmt_desc; 1429 void *cb_context; 1430 mgmt_tx_download_comp_cb tx_compl_cb; 1431 mgmt_ota_comp_cb ota_comp_cb; 1432 qdf_nbuf_t nbuf; 1433 1434 mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *) 1435 wlan_objmgr_pdev_get_comp_private_obj(pdev, 1436 WLAN_UMAC_COMP_MGMT_TXRX); 1437 if (!mgmt_txrx_pdev_ctx) { 1438 mgmt_txrx_err("Mgmt txrx context empty for pdev %pK", pdev); 1439 return QDF_STATUS_E_NULL_VALUE; 1440 } 1441 if (desc_id >= MGMT_DESC_POOL_MAX) { 1442 mgmt_txrx_err("desc_id:%u is out of bounds", desc_id); 1443 return QDF_STATUS_E_INVAL; 1444 } 1445 mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[desc_id]; 1446 if (!mgmt_desc || !mgmt_desc->in_use) { 1447 mgmt_txrx_err("Mgmt desc empty for id %d pdev %pK ", 1448 desc_id, pdev); 1449 return QDF_STATUS_E_NULL_VALUE; 1450 } 1451 tx_compl_cb = mgmt_desc->tx_dwnld_cmpl_cb; 1452 ota_comp_cb = mgmt_desc->tx_ota_cmpl_cb; 1453 nbuf = mgmt_desc->nbuf; 1454 1455 /* 1456 * TO DO 1457 * Make the API more generic to handle tx download completion as well 1458 * as OTA completion separately. 1459 */ 1460 1461 /* 1462 * 1. If the tx frame is sent by any UMAC converged component then it 1463 * passes the context as NULL while calling mgmt txrx API for 1464 * sending mgmt frame. If context is NULL, peer will be passed as 1465 * cb_context in completion callbacks. 1466 * 2. If the tx frame is sent by legacy MLME then it passes the context 1467 * as its specific context (for ex- mac context in case of MCL) while 1468 * calling mgmt txrx API for sending mgmt frame. This caller specific 1469 * context is passed as cb_context in completion callbacks. 1470 */ 1471 if (mgmt_desc->context) 1472 cb_context = mgmt_desc->context; 1473 else 1474 cb_context = (void *)mgmt_desc->peer; 1475 1476 if (!tx_compl_cb && !ota_comp_cb) { 1477 qdf_nbuf_free(nbuf); 1478 goto no_registered_cb; 1479 } 1480 1481 if (tx_compl_cb) 1482 tx_compl_cb(cb_context, nbuf, status); 1483 1484 if (ota_comp_cb) 1485 ota_comp_cb(cb_context, nbuf, status, tx_compl_params); 1486 1487 no_registered_cb: 1488 /* 1489 * decrementing the peer ref count that was incremented while 1490 * accessing peer in wlan_mgmt_txrx_mgmt_frame_tx 1491 */ 1492 wlan_objmgr_peer_release_ref(mgmt_desc->peer, WLAN_MGMT_NB_ID); 1493 wlan_mgmt_txrx_desc_put(mgmt_txrx_pdev_ctx, desc_id); 1494 return QDF_STATUS_SUCCESS; 1495 } 1496 1497 qdf_nbuf_t tgt_mgmt_txrx_get_nbuf_from_desc_id( 1498 struct wlan_objmgr_pdev *pdev, 1499 uint32_t desc_id) 1500 { 1501 struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx; 1502 struct mgmt_txrx_desc_elem_t *mgmt_desc; 1503 qdf_nbuf_t buf; 1504 1505 mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *) 1506 wlan_objmgr_pdev_get_comp_private_obj(pdev, 1507 WLAN_UMAC_COMP_MGMT_TXRX); 1508 if (!mgmt_txrx_pdev_ctx) { 1509 mgmt_txrx_err("Mgmt txrx context empty for pdev %pK", pdev); 1510 goto fail; 1511 } 1512 if (desc_id >= MGMT_DESC_POOL_MAX) { 1513 mgmt_txrx_err("desc_id:%u is out of bounds", desc_id); 1514 goto fail; 1515 } 1516 1517 mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[desc_id]; 1518 if (!mgmt_desc || !mgmt_desc->in_use) { 1519 mgmt_txrx_err("Mgmt descriptor unavailable for id %d pdev %pK", 1520 desc_id, pdev); 1521 goto fail; 1522 } 1523 buf = mgmt_desc->nbuf; 1524 return buf; 1525 1526 fail: 1527 return NULL; 1528 } 1529 1530 struct wlan_objmgr_peer * 1531 tgt_mgmt_txrx_get_peer_from_desc_id( 1532 struct wlan_objmgr_pdev *pdev, 1533 uint32_t desc_id) 1534 { 1535 struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx; 1536 struct mgmt_txrx_desc_elem_t *mgmt_desc; 1537 struct wlan_objmgr_peer *peer; 1538 1539 mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *) 1540 wlan_objmgr_pdev_get_comp_private_obj(pdev, 1541 WLAN_UMAC_COMP_MGMT_TXRX); 1542 if (!mgmt_txrx_pdev_ctx) { 1543 mgmt_txrx_err("Mgmt txrx context empty for pdev %pK", pdev); 1544 goto fail; 1545 } 1546 1547 mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[desc_id]; 1548 if (!mgmt_desc || !mgmt_desc->in_use) { 1549 mgmt_txrx_err("Mgmt descriptor unavailable for id %d pdev %pK", 1550 desc_id, pdev); 1551 goto fail; 1552 } 1553 1554 peer = mgmt_desc->peer; 1555 return peer; 1556 1557 fail: 1558 return NULL; 1559 } 1560 1561 uint8_t tgt_mgmt_txrx_get_vdev_id_from_desc_id( 1562 struct wlan_objmgr_pdev *pdev, 1563 uint32_t desc_id) 1564 { 1565 struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx; 1566 struct mgmt_txrx_desc_elem_t *mgmt_desc; 1567 uint8_t vdev_id; 1568 1569 mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *) 1570 wlan_objmgr_pdev_get_comp_private_obj(pdev, 1571 WLAN_UMAC_COMP_MGMT_TXRX); 1572 if (!mgmt_txrx_pdev_ctx) { 1573 mgmt_txrx_err("Mgmt txrx context empty for pdev %pK", pdev); 1574 goto fail; 1575 } 1576 if (desc_id >= MGMT_DESC_POOL_MAX) { 1577 mgmt_txrx_err("desc_id:%u is out of bounds", desc_id); 1578 goto fail; 1579 } 1580 1581 mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[desc_id]; 1582 if (!mgmt_desc || !mgmt_desc->in_use) { 1583 mgmt_txrx_err("Mgmt descriptor unavailable for id %d pdev %pK", 1584 desc_id, pdev); 1585 goto fail; 1586 } 1587 1588 vdev_id = mgmt_desc->vdev_id; 1589 return vdev_id; 1590 1591 fail: 1592 return WLAN_UMAC_VDEV_ID_MAX; 1593 } 1594 1595 uint32_t tgt_mgmt_txrx_get_free_desc_pool_count( 1596 struct wlan_objmgr_pdev *pdev) 1597 { 1598 struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx; 1599 uint32_t free_desc_count = WLAN_INVALID_MGMT_DESC_COUNT; 1600 1601 mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *) 1602 wlan_objmgr_pdev_get_comp_private_obj(pdev, 1603 WLAN_UMAC_COMP_MGMT_TXRX); 1604 if (!mgmt_txrx_pdev_ctx) { 1605 mgmt_txrx_err("Mgmt txrx context empty for pdev %pK", pdev); 1606 goto fail; 1607 } 1608 1609 free_desc_count = qdf_list_size( 1610 &(mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list)); 1611 1612 fail: 1613 return free_desc_count; 1614 } 1615 1616 QDF_STATUS 1617 tgt_mgmt_txrx_register_ev_handler(struct wlan_objmgr_psoc *psoc) 1618 { 1619 struct wlan_lmac_if_mgmt_txrx_tx_ops *mgmt_txrx_tx_ops; 1620 1621 mgmt_txrx_tx_ops = wlan_psoc_get_mgmt_txrx_txops(psoc); 1622 if (!mgmt_txrx_tx_ops) { 1623 mgmt_txrx_err("txops is null for mgmt txrx module"); 1624 return QDF_STATUS_E_NULL_VALUE; 1625 } 1626 1627 if (mgmt_txrx_tx_ops->reg_ev_handler) 1628 return mgmt_txrx_tx_ops->reg_ev_handler(psoc); 1629 1630 return QDF_STATUS_SUCCESS; 1631 } 1632 1633 QDF_STATUS 1634 tgt_mgmt_txrx_unregister_ev_handler(struct wlan_objmgr_psoc *psoc) 1635 { 1636 struct wlan_lmac_if_mgmt_txrx_tx_ops *mgmt_txrx_tx_ops; 1637 1638 mgmt_txrx_tx_ops = wlan_psoc_get_mgmt_txrx_txops(psoc); 1639 if (!mgmt_txrx_tx_ops) { 1640 mgmt_txrx_err("txops is null for mgmt txrx module"); 1641 return QDF_STATUS_E_NULL_VALUE; 1642 } 1643 1644 if (mgmt_txrx_tx_ops->unreg_ev_handler) 1645 return mgmt_txrx_tx_ops->unreg_ev_handler(psoc); 1646 1647 return QDF_STATUS_SUCCESS; 1648 } 1649 1650 QDF_STATUS tgt_mgmt_txrx_process_rx_frame( 1651 struct wlan_objmgr_pdev *pdev, 1652 qdf_nbuf_t buf, 1653 struct mgmt_rx_event_params *mgmt_rx_params) 1654 { 1655 QDF_STATUS status; 1656 struct wlan_lmac_if_mgmt_txrx_tx_ops *mgmt_txrx_tx_ops; 1657 1658 mgmt_txrx_tx_ops = wlan_pdev_get_mgmt_txrx_txops(pdev); 1659 if (!mgmt_txrx_tx_ops) { 1660 mgmt_txrx_err("txops is null for mgmt txrx module"); 1661 qdf_nbuf_free(buf); 1662 free_mgmt_rx_event_params(mgmt_rx_params); 1663 return QDF_STATUS_E_NULL_VALUE; 1664 } 1665 1666 /* Call the legacy handler to actually process and deliver frames */ 1667 status = mgmt_txrx_tx_ops->rx_frame_legacy_handler(pdev, buf, 1668 mgmt_rx_params); 1669 /** 1670 * Free up the mgmt rx params. 1671 * nbuf shouldn't be freed here as it is taken care by 1672 * rx_frame_legacy_handler. 1673 */ 1674 free_mgmt_rx_event_params(mgmt_rx_params); 1675 1676 return status; 1677 } 1678 1679 QDF_STATUS tgt_mgmt_txrx_rx_frame_entry( 1680 struct wlan_objmgr_pdev *pdev, 1681 qdf_nbuf_t buf, 1682 struct mgmt_rx_event_params *mgmt_rx_params) 1683 { 1684 /* Call the MGMT Rx REO handler */ 1685 return tgt_mgmt_rx_reo_frame_handler(pdev, buf, mgmt_rx_params); 1686 } 1687