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