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