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