1 /* 2 * Copyright (c) 2016-2018 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 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 /** 262 * mgmt_get_ht_action_subtype() - gets ht action subtype 263 * @action_code: action code 264 * 265 * This function returns the subtype for ht action 266 * category. 267 * 268 * Return: mgmt frame type 269 */ 270 static enum mgmt_frame_type 271 mgmt_get_ht_action_subtype(uint8_t action_code) 272 { 273 enum mgmt_frame_type frm_type; 274 275 switch (action_code) { 276 case HT_ACTION_NOTIFY_CHANWIDTH: 277 frm_type = MGMT_ACTION_HT_NOTIFY_CHANWIDTH; 278 break; 279 case HT_ACTION_SMPS: 280 frm_type = MGMT_ACTION_HT_SMPS; 281 break; 282 case HT_ACTION_PSMP: 283 frm_type = MGMT_ACTION_HT_PSMP; 284 break; 285 case HT_ACTION_PCO_PHASE: 286 frm_type = MGMT_ACTION_HT_PCO_PHASE; 287 break; 288 case HT_ACTION_CSI: 289 frm_type = MGMT_ACTION_HT_CSI; 290 break; 291 case HT_ACTION_NONCOMPRESSED_BF: 292 frm_type = MGMT_ACTION_HT_NONCOMPRESSED_BF; 293 break; 294 case HT_ACTION_COMPRESSED_BF: 295 frm_type = MGMT_ACTION_HT_COMPRESSED_BF; 296 break; 297 case HT_ACTION_ASEL_IDX_FEEDBACK: 298 frm_type = MGMT_ACTION_HT_ASEL_IDX_FEEDBACK; 299 break; 300 default: 301 frm_type = MGMT_FRM_UNSPECIFIED; 302 break; 303 } 304 305 return frm_type; 306 } 307 308 /** 309 * mgmt_get_sa_query_action_subtype() - gets sa query action subtype 310 * @action_code: action code 311 * 312 * This function returns the subtype for sa query action 313 * category. 314 * 315 * Return: mgmt frame type 316 */ 317 static enum mgmt_frame_type 318 mgmt_get_sa_query_action_subtype(uint8_t action_code) 319 { 320 enum mgmt_frame_type frm_type; 321 322 switch (action_code) { 323 case SA_QUERY_REQUEST: 324 frm_type = MGMT_ACTION_SA_QUERY_REQUEST; 325 break; 326 case SA_QUERY_RESPONSE: 327 frm_type = MGMT_ACTION_SA_QUERY_RESPONSE; 328 break; 329 default: 330 frm_type = MGMT_FRM_UNSPECIFIED; 331 break; 332 } 333 334 return frm_type; 335 } 336 337 /** 338 * mgmt_get_pdpa_action_subtype() - gets pdpa action subtype 339 * @action_code: action code 340 * 341 * This function returns the subtype for protected dual public 342 * action category. 343 * 344 * Return: mgmt frame type 345 */ 346 static enum mgmt_frame_type 347 mgmt_get_pdpa_action_subtype(uint8_t action_code) 348 { 349 enum mgmt_frame_type frm_type; 350 351 switch (action_code) { 352 case PDPA_GAS_INIT_REQ: 353 frm_type = MGMT_ACTION_PDPA_GAS_INIT_REQ; 354 break; 355 case PDPA_GAS_INIT_RSP: 356 frm_type = MGMT_ACTION_PDPA_GAS_INIT_RSP; 357 break; 358 case PDPA_GAS_COMEBACK_REQ: 359 frm_type = MGMT_ACTION_PDPA_GAS_COMEBACK_REQ; 360 break; 361 case PDPA_GAS_COMEBACK_RSP: 362 frm_type = MGMT_ACTION_PDPA_GAS_COMEBACK_RSP; 363 break; 364 default: 365 frm_type = MGMT_FRM_UNSPECIFIED; 366 break; 367 } 368 369 return frm_type; 370 } 371 372 /** 373 * mgmt_get_wnm_action_subtype() - gets wnm action subtype 374 * @action_code: action code 375 * 376 * This function returns the subtype for wnm action 377 * category. 378 * 379 * Return: mgmt frame type 380 */ 381 static enum mgmt_frame_type 382 mgmt_get_wnm_action_subtype(uint8_t action_code) 383 { 384 enum mgmt_frame_type frm_type; 385 386 switch (action_code) { 387 case WNM_BSS_TM_QUERY: 388 frm_type = MGMT_ACTION_WNM_BSS_TM_QUERY; 389 break; 390 case WNM_BSS_TM_REQUEST: 391 frm_type = MGMT_ACTION_WNM_BSS_TM_REQUEST; 392 break; 393 case WNM_BSS_TM_RESPONSE: 394 frm_type = MGMT_ACTION_WNM_BSS_TM_RESPONSE; 395 break; 396 case WNM_NOTIF_REQUEST: 397 frm_type = MGMT_ACTION_WNM_NOTIF_REQUEST; 398 break; 399 case WNM_NOTIF_RESPONSE: 400 frm_type = MGMT_ACTION_WNM_NOTIF_RESPONSE; 401 break; 402 case WNM_FMS_REQ: 403 frm_type = MGMT_ACTION_WNM_FMS_REQ; 404 break; 405 case WNM_FMS_RESP: 406 frm_type = MGMT_ACTION_WNM_FMS_RESP; 407 break; 408 case WNM_TFS_REQ: 409 frm_type = MGMT_ACTION_WNM_TFS_REQ; 410 break; 411 case WNM_TFS_RESP: 412 frm_type = MGMT_ACTION_WNM_TFS_RESP; 413 break; 414 case WNM_TFS_NOTIFY: 415 frm_type = MGMT_ACTION_WNM_TFS_NOTIFY; 416 break; 417 case WNM_SLEEP_REQ: 418 frm_type = MGMT_ACTION_WNM_SLEEP_REQ; 419 break; 420 case WNM_SLEEP_RESP: 421 frm_type = MGMT_ACTION_WNM_SLEEP_RESP; 422 break; 423 case WNM_TIM_REQ: 424 frm_type = MGMT_ACTION_WNM_TFS_REQ; 425 break; 426 case WNM_TIM_RESP: 427 frm_type = MGMT_ACTION_WNM_TFS_RESP; 428 break; 429 default: 430 frm_type = MGMT_FRM_UNSPECIFIED; 431 break; 432 } 433 434 return frm_type; 435 } 436 437 /** 438 * mgmt_get_wnm_action_subtype() - gets tdls action subtype 439 * @action_code: action code 440 * 441 * This function returns the subtype for tdls action 442 * category. 443 * 444 * Return: mgmt frame type 445 */ 446 static enum mgmt_frame_type 447 mgmt_get_tdls_action_subtype(uint8_t action_code) 448 { 449 enum mgmt_frame_type frm_type; 450 451 switch (action_code) { 452 case TDLS_SETUP_REQUEST: 453 frm_type = MGMT_ACTION_TDLS_SETUP_REQ; 454 break; 455 case TDLS_SETUP_RESPONSE: 456 frm_type = MGMT_ACTION_TDLS_SETUP_RSP; 457 break; 458 case TDLS_SETUP_CONFIRM: 459 frm_type = MGMT_ACTION_TDLS_SETUP_CNF; 460 break; 461 case TDLS_TEARDOWN: 462 frm_type = MGMT_ACTION_TDLS_TEARDOWN; 463 break; 464 case TDLS_PEER_TRAFFIC_INDICATION: 465 frm_type = MGMT_ACTION_TDLS_PEER_TRAFFIC_IND; 466 break; 467 case TDLS_CHANNEL_SWITCH_REQUEST: 468 frm_type = MGMT_ACTION_TDLS_CH_SWITCH_REQ; 469 break; 470 case TDLS_CHANNEL_SWITCH_RESPONSE: 471 frm_type = MGMT_ACTION_TDLS_CH_SWITCH_RSP; 472 break; 473 case TDLS_PEER_PSM_REQUEST: 474 frm_type = MGMT_ACTION_TDLS_PEER_PSM_REQUEST; 475 break; 476 case TDLS_PEER_PSM_RESPONSE: 477 frm_type = MGMT_ACTION_TDLS_PEER_PSM_RESPONSE; 478 break; 479 case TDLS_PEER_TRAFFIC_RESPONSE: 480 frm_type = MGMT_ACTION_TDLS_PEER_TRAFFIC_RSP; 481 break; 482 case TDLS_DISCOVERY_REQUEST: 483 frm_type = MGMT_ACTION_TDLS_DIS_REQ; 484 break; 485 default: 486 frm_type = MGMT_FRM_UNSPECIFIED; 487 break; 488 } 489 490 return frm_type; 491 } 492 493 /** 494 * mgmt_get_mesh_action_subtype() - gets mesh action subtype 495 * @action_code: action code 496 * 497 * This function returns the subtype for mesh action 498 * category. 499 * 500 * Return: mgmt frame type 501 */ 502 static enum mgmt_frame_type 503 mgmt_get_mesh_action_subtype(uint8_t action_code) 504 { 505 enum mgmt_frame_type frm_type; 506 507 switch (action_code) { 508 case MESH_ACTION_LINK_METRIC_REPORT: 509 frm_type = MGMT_ACTION_MESH_LINK_METRIC_REPORT; 510 break; 511 case MESH_ACTION_HWMP_PATH_SELECTION: 512 frm_type = MGMT_ACTION_MESH_HWMP_PATH_SELECTION; 513 break; 514 case MESH_ACTION_GATE_ANNOUNCEMENT: 515 frm_type = MGMT_ACTION_MESH_GATE_ANNOUNCEMENT; 516 break; 517 case MESH_ACTION_CONGESTION_CONTROL_NOTIFICATION: 518 frm_type = MGMT_ACTION_MESH_CONGESTION_CONTROL_NOTIFICATION; 519 break; 520 case MESH_ACTION_MCCA_SETUP_REQUEST: 521 frm_type = MGMT_ACTION_MESH_MCCA_SETUP_REQUEST; 522 break; 523 case MESH_ACTION_MCCA_SETUP_REPLY: 524 frm_type = MGMT_ACTION_MESH_MCCA_SETUP_REPLY; 525 break; 526 case MESH_ACTION_MCCA_ADVERTISEMENT_REQUEST: 527 frm_type = MGMT_ACTION_MESH_MCCA_ADVERTISEMENT_REQUEST; 528 break; 529 case MESH_ACTION_MCCA_ADVERTISEMENT: 530 frm_type = MGMT_ACTION_MESH_MCCA_ADVERTISEMENT; 531 break; 532 case MESH_ACTION_MCCA_TEARDOWN: 533 frm_type = MGMT_ACTION_MESH_MCCA_TEARDOWN; 534 break; 535 case MESH_ACTION_TBTT_ADJUSTMENT_REQUEST: 536 frm_type = MGMT_ACTION_MESH_TBTT_ADJUSTMENT_REQUEST; 537 break; 538 case MESH_ACTION_TBTT_ADJUSTMENT_RESPONSE: 539 frm_type = MGMT_ACTION_MESH_TBTT_ADJUSTMENT_RESPONSE; 540 break; 541 default: 542 frm_type = MGMT_FRM_UNSPECIFIED; 543 break; 544 } 545 546 return frm_type; 547 } 548 549 /** 550 * mgmt_get_self_prot_action_subtype() - gets self prot. action subtype 551 * @action_code: action code 552 * 553 * This function returns the subtype for self protected action 554 * category. 555 * 556 * Return: mgmt frame type 557 */ 558 static enum mgmt_frame_type 559 mgmt_get_self_prot_action_subtype(uint8_t action_code) 560 { 561 enum mgmt_frame_type frm_type; 562 563 switch (action_code) { 564 case SP_MESH_PEERING_OPEN: 565 frm_type = MGMT_ACTION_SP_MESH_PEERING_OPEN; 566 break; 567 case SP_MESH_PEERING_CONFIRM: 568 frm_type = MGMT_ACTION_SP_MESH_PEERING_CONFIRM; 569 break; 570 case SP_MESH_PEERING_CLOSE: 571 frm_type = MGMT_ACTION_SP_MESH_PEERING_CLOSE; 572 break; 573 case SP_MGK_INFORM: 574 frm_type = MGMT_ACTION_SP_MGK_INFORM; 575 break; 576 case SP_MGK_ACK: 577 frm_type = MGMT_ACTION_SP_MGK_ACK; 578 break; 579 default: 580 frm_type = MGMT_FRM_UNSPECIFIED; 581 break; 582 } 583 584 return frm_type; 585 } 586 587 /** 588 * mgmt_get_wmm_action_subtype() - gets wmm action subtype 589 * @action_code: action code 590 * 591 * This function returns the subtype for wmm action 592 * category. 593 * 594 * Return: mgmt frame type 595 */ 596 static enum mgmt_frame_type 597 mgmt_get_wmm_action_subtype(uint8_t action_code) 598 { 599 enum mgmt_frame_type frm_type; 600 601 switch (action_code) { 602 case WMM_QOS_SETUP_REQ: 603 frm_type = MGMT_ACTION_WMM_QOS_SETUP_REQ; 604 break; 605 case WMM_QOS_SETUP_RESP: 606 frm_type = MGMT_ACTION_WMM_QOS_SETUP_RESP; 607 break; 608 case WMM_QOS_TEARDOWN: 609 frm_type = MGMT_ACTION_WMM_QOS_TEARDOWN; 610 break; 611 default: 612 frm_type = MGMT_FRM_UNSPECIFIED; 613 break; 614 } 615 616 return frm_type; 617 } 618 619 /** 620 * mgmt_get_vht_action_subtype() - gets vht action subtype 621 * @action_code: action code 622 * 623 * This function returns the subtype for vht action 624 * category. 625 * 626 * Return: mgmt frame type 627 */ 628 static enum mgmt_frame_type 629 mgmt_get_vht_action_subtype(uint8_t action_code) 630 { 631 enum mgmt_frame_type frm_type; 632 633 switch (action_code) { 634 case VHT_ACTION_COMPRESSED_BF: 635 frm_type = MGMT_ACTION_VHT_COMPRESSED_BF; 636 break; 637 case VHT_ACTION_GID_NOTIF: 638 frm_type = MGMT_ACTION_VHT_GID_NOTIF; 639 break; 640 case VHT_ACTION_OPMODE_NOTIF: 641 frm_type = MGMT_ACTION_VHT_OPMODE_NOTIF; 642 break; 643 default: 644 frm_type = MGMT_FRM_UNSPECIFIED; 645 break; 646 } 647 648 return frm_type; 649 } 650 651 /** 652 * mgmt_txrx_get_action_frm_subtype() - gets action frm subtype 653 * @mpdu_data_ptr: pointer to mpdu data 654 * 655 * This function determines the action category of the frame 656 * and calls respective function to get mgmt frame type. 657 * 658 * Return: mgmt frame type 659 */ 660 static enum mgmt_frame_type 661 mgmt_txrx_get_action_frm_subtype(uint8_t *mpdu_data_ptr) 662 { 663 struct action_frm_hdr *action_hdr = 664 (struct action_frm_hdr *)mpdu_data_ptr; 665 enum mgmt_frame_type frm_type; 666 667 switch (action_hdr->action_category) { 668 case ACTION_CATEGORY_SPECTRUM_MGMT: 669 frm_type = mgmt_get_spec_mgmt_action_subtype( 670 action_hdr->action_code); 671 break; 672 case ACTION_CATEGORY_QOS: 673 frm_type = mgmt_get_qos_action_subtype(action_hdr->action_code); 674 break; 675 case ACTION_CATEGORY_DLS: 676 frm_type = mgmt_get_dls_action_subtype(action_hdr->action_code); 677 break; 678 case ACTION_CATEGORY_BACK: 679 frm_type = mgmt_get_back_action_subtype( 680 action_hdr->action_code); 681 break; 682 case ACTION_CATEGORY_PUBLIC: 683 frm_type = mgmt_get_public_action_subtype( 684 action_hdr->action_code); 685 break; 686 case ACTION_CATEGORY_RRM: 687 frm_type = mgmt_get_rrm_action_subtype(action_hdr->action_code); 688 break; 689 case ACTION_CATEGORY_HT: 690 frm_type = mgmt_get_ht_action_subtype(action_hdr->action_code); 691 break; 692 case ACTION_CATEGORY_SA_QUERY: 693 frm_type = mgmt_get_sa_query_action_subtype( 694 action_hdr->action_code); 695 break; 696 case ACTION_CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION: 697 frm_type = mgmt_get_pdpa_action_subtype( 698 action_hdr->action_code); 699 break; 700 case ACTION_CATEGORY_WNM: 701 frm_type = mgmt_get_wnm_action_subtype(action_hdr->action_code); 702 break; 703 case ACTION_CATEGORY_TDLS: 704 frm_type = mgmt_get_tdls_action_subtype( 705 action_hdr->action_code); 706 break; 707 case ACTION_CATEGORY_MESH_ACTION: 708 frm_type = mgmt_get_mesh_action_subtype( 709 action_hdr->action_code); 710 break; 711 case ACTION_CATEGORY_SELF_PROTECTED: 712 frm_type = mgmt_get_self_prot_action_subtype( 713 action_hdr->action_code); 714 break; 715 case ACTION_CATEGORY_WMM: 716 frm_type = mgmt_get_wmm_action_subtype(action_hdr->action_code); 717 break; 718 case ACTION_CATEGORY_VHT: 719 frm_type = mgmt_get_vht_action_subtype(action_hdr->action_code); 720 break; 721 case ACTION_CATEGORY_VENDOR_SPECIFIC: 722 frm_type = MGMT_ACTION_CATEGORY_VENDOR_SPECIFIC; 723 break; 724 default: 725 frm_type = MGMT_FRM_UNSPECIFIED; 726 break; 727 } 728 729 return frm_type; 730 } 731 732 /** 733 * mgmt_txrx_get_frm_type() - gets mgmt frm type 734 * @mgmt_subtype: mgmt subtype 735 * @mpdu_data_ptr: pointer to mpdu data 736 * 737 * This function returns mgmt frame type of the frame 738 * based on the mgmt subtype. 739 * 740 * Return: mgmt frame type 741 */ 742 static enum mgmt_frame_type 743 mgmt_txrx_get_frm_type(uint8_t mgmt_subtype, uint8_t *mpdu_data_ptr) 744 { 745 enum mgmt_frame_type frm_type; 746 747 switch (mgmt_subtype) { 748 case MGMT_SUBTYPE_ASSOC_REQ: 749 frm_type = MGMT_ASSOC_REQ; 750 break; 751 case MGMT_SUBTYPE_ASSOC_RESP: 752 frm_type = MGMT_ASSOC_RESP; 753 break; 754 case MGMT_SUBTYPE_REASSOC_REQ: 755 frm_type = MGMT_ASSOC_REQ; 756 break; 757 case MGMT_SUBTYPE_REASSOC_RESP: 758 frm_type = MGMT_REASSOC_RESP; 759 break; 760 case MGMT_SUBTYPE_PROBE_REQ: 761 frm_type = MGMT_PROBE_REQ; 762 break; 763 case MGMT_SUBTYPE_PROBE_RESP: 764 frm_type = MGMT_PROBE_RESP; 765 break; 766 case MGMT_SUBTYPE_BEACON: 767 frm_type = MGMT_BEACON; 768 break; 769 case MGMT_SUBTYPE_ATIM: 770 frm_type = MGMT_ATIM; 771 break; 772 case MGMT_SUBTYPE_DISASSOC: 773 frm_type = MGMT_DISASSOC; 774 break; 775 case MGMT_SUBTYPE_AUTH: 776 frm_type = MGMT_AUTH; 777 break; 778 case MGMT_SUBTYPE_DEAUTH: 779 frm_type = MGMT_DEAUTH; 780 break; 781 case MGMT_SUBTYPE_ACTION: 782 case MGMT_SUBTYPE_ACTION_NO_ACK: 783 frm_type = mgmt_txrx_get_action_frm_subtype(mpdu_data_ptr); 784 break; 785 default: 786 frm_type = MGMT_FRM_UNSPECIFIED; 787 break; 788 } 789 790 return frm_type; 791 } 792 793 /** 794 * wlan_mgmt_txrx_rx_handler_list_copy() - copies rx handler list 795 * @rx_handler: pointer to rx handler list 796 * @rx_handler_head: pointer to head of the copies list 797 * @rx_handler_tail: pointer to tail of the copies list 798 * 799 * This function copies the rx handler linked list into a local 800 * linked list. 801 * 802 * Return: QDF_STATUS_SUCCESS in case of success 803 */ 804 static QDF_STATUS wlan_mgmt_txrx_rx_handler_list_copy( 805 struct mgmt_rx_handler *rx_handler, 806 struct mgmt_rx_handler **rx_handler_head, 807 struct mgmt_rx_handler **rx_handler_tail) 808 { 809 struct mgmt_rx_handler *rx_handler_node; 810 811 while (rx_handler) { 812 rx_handler_node = qdf_mem_malloc(sizeof(*rx_handler_node)); 813 if (!rx_handler_node) { 814 mgmt_txrx_err("Couldn't allocate memory for rx handler node"); 815 return QDF_STATUS_E_NOMEM; 816 } 817 818 rx_handler_node->comp_id = rx_handler->comp_id; 819 rx_handler_node->rx_cb = rx_handler->rx_cb; 820 rx_handler_node->next = NULL; 821 822 if (!(*rx_handler_head)) { 823 *rx_handler_head = rx_handler_node; 824 *rx_handler_tail = *rx_handler_head; 825 } else { 826 (*rx_handler_tail)->next = rx_handler_node; 827 *rx_handler_tail = (*rx_handler_tail)->next; 828 } 829 rx_handler = rx_handler->next; 830 } 831 832 return QDF_STATUS_SUCCESS; 833 } 834 835 QDF_STATUS tgt_mgmt_txrx_rx_frame_handler( 836 struct wlan_objmgr_psoc *psoc, 837 qdf_nbuf_t buf, 838 struct mgmt_rx_event_params *mgmt_rx_params) 839 { 840 struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx; 841 struct ieee80211_frame *wh; 842 qdf_nbuf_t copy_buf; 843 struct wlan_objmgr_peer *peer = NULL; 844 uint8_t mgmt_type, mgmt_subtype; 845 uint8_t *mac_addr, *mpdu_data_ptr; 846 enum mgmt_frame_type frm_type; 847 struct mgmt_rx_handler *rx_handler; 848 struct mgmt_rx_handler *rx_handler_head = NULL, *rx_handler_tail = NULL; 849 u_int8_t *data, *ivp = NULL; 850 uint16_t buflen; 851 QDF_STATUS status = QDF_STATUS_SUCCESS; 852 853 if (!buf) { 854 mgmt_txrx_err("buffer passed is NULL"); 855 return QDF_STATUS_E_INVAL; 856 } 857 858 if (!psoc) { 859 mgmt_txrx_err("psoc_ctx passed is NULL"); 860 qdf_nbuf_free(buf); 861 return QDF_STATUS_E_INVAL; 862 } 863 864 data = (uint8_t *)qdf_nbuf_data(buf); 865 wh = (struct ieee80211_frame *)data; 866 buflen = qdf_nbuf_len(buf); 867 868 if (buflen > (sizeof(struct ieee80211_frame) + WLAN_HDR_EXT_IV_LEN)) 869 ivp = data + sizeof(struct ieee80211_frame); 870 871 /* peer can be NULL in following 2 scenarios: 872 * 1. broadcast frame received 873 * 2. operating in monitor mode 874 * 875 * and in both scenarios, the receiver of frame 876 * is expected to do processing accordingly considerng 877 * the fact that peer = NULL can be received and is a valid 878 * scenario. 879 */ 880 mac_addr = (uint8_t *)wh->i_addr2; 881 peer = wlan_objmgr_get_peer(psoc, mac_addr, WLAN_MGMT_SB_ID); 882 if (!peer) { 883 mac_addr = (uint8_t *)wh->i_addr1; 884 peer = wlan_objmgr_get_peer(psoc, mac_addr, WLAN_MGMT_SB_ID); 885 } 886 887 /** 888 * TO DO (calculate pdev) 889 * Waiting for a new parameter: pdev id to get added in rx event 890 */ 891 892 mgmt_type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 893 mgmt_subtype = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 894 895 if (mgmt_type != IEEE80211_FC0_TYPE_MGT) { 896 mgmt_txrx_err("Rx event doesn't conatin a mgmt. packet, %d", 897 mgmt_type); 898 qdf_nbuf_free(buf); 899 status = QDF_STATUS_E_FAILURE; 900 goto dec_peer_ref_cnt; 901 } 902 903 /* mpdu_data_ptr is pointer to action header */ 904 mpdu_data_ptr = (uint8_t *)qdf_nbuf_data(buf) + 905 sizeof(struct ieee80211_frame); 906 if ((wh->i_fc[1] & IEEE80211_FC1_WEP) && 907 !qdf_is_macaddr_group((struct qdf_mac_addr *)wh->i_addr1) && 908 !qdf_is_macaddr_broadcast((struct qdf_mac_addr *)wh->i_addr1)) { 909 if (ivp[WLAN_HDR_IV_LEN] & WLAN_HDR_EXT_IV_BIT) 910 mpdu_data_ptr += IEEE80211_CCMP_HEADERLEN; 911 else 912 mpdu_data_ptr += WLAN_HDR_EXT_IV_LEN; 913 } 914 915 frm_type = mgmt_txrx_get_frm_type(mgmt_subtype, mpdu_data_ptr); 916 if (frm_type == MGMT_FRM_UNSPECIFIED) { 917 mgmt_txrx_err("Unspecified mgmt frame type fc: %x %x", 918 wh->i_fc[0], wh->i_fc[1]); 919 qdf_nbuf_free(buf); 920 status = QDF_STATUS_E_FAILURE; 921 goto dec_peer_ref_cnt; 922 } 923 924 mgmt_txrx_info("Rcvd mgmt frame, mgmt txrx frm type: %u seq. no.: %u, peer: %pK fc: %x %x", 925 frm_type, *(uint16_t *)wh->i_seq, peer, wh->i_fc[0], 926 wh->i_fc[1]); 927 928 mgmt_txrx_psoc_ctx = (struct mgmt_txrx_priv_psoc_context *) 929 wlan_objmgr_psoc_get_comp_private_obj(psoc, 930 WLAN_UMAC_COMP_MGMT_TXRX); 931 932 qdf_spin_lock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock); 933 rx_handler = mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[frm_type]; 934 if (rx_handler) { 935 status = wlan_mgmt_txrx_rx_handler_list_copy(rx_handler, 936 &rx_handler_head, &rx_handler_tail); 937 if (status != QDF_STATUS_SUCCESS) { 938 qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock); 939 qdf_nbuf_free(buf); 940 goto rx_handler_mem_free; 941 } 942 } 943 944 rx_handler = mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[MGMT_FRAME_TYPE_ALL]; 945 if (rx_handler) { 946 status = wlan_mgmt_txrx_rx_handler_list_copy(rx_handler, 947 &rx_handler_head, &rx_handler_tail); 948 if (status != QDF_STATUS_SUCCESS) { 949 qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock); 950 qdf_nbuf_free(buf); 951 goto rx_handler_mem_free; 952 } 953 } 954 955 if (!rx_handler_head) { 956 qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock); 957 mgmt_txrx_info("No rx callback registered for frm_type: %d", 958 frm_type); 959 qdf_nbuf_free(buf); 960 status = QDF_STATUS_E_FAILURE; 961 goto dec_peer_ref_cnt; 962 } 963 qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock); 964 965 rx_handler = rx_handler_head; 966 while (rx_handler->next) { 967 copy_buf = qdf_nbuf_clone(buf); 968 rx_handler->rx_cb(psoc, peer, copy_buf, 969 mgmt_rx_params, frm_type); 970 rx_handler = rx_handler->next; 971 } 972 rx_handler->rx_cb(psoc, peer, buf, 973 mgmt_rx_params, frm_type); 974 975 rx_handler_mem_free: 976 while (rx_handler_head) { 977 rx_handler = rx_handler_head; 978 rx_handler_head = rx_handler_head->next; 979 qdf_mem_free(rx_handler); 980 } 981 dec_peer_ref_cnt: 982 if (peer) 983 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_SB_ID); 984 985 return status; 986 } 987 988 QDF_STATUS tgt_mgmt_txrx_tx_completion_handler( 989 struct wlan_objmgr_pdev *pdev, 990 uint32_t desc_id, uint32_t status, 991 void *tx_compl_params) 992 { 993 struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx; 994 struct mgmt_txrx_desc_elem_t *mgmt_desc; 995 void *cb_context; 996 mgmt_tx_download_comp_cb tx_compl_cb; 997 mgmt_ota_comp_cb ota_comp_cb; 998 qdf_nbuf_t nbuf; 999 1000 mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *) 1001 wlan_objmgr_pdev_get_comp_private_obj(pdev, 1002 WLAN_UMAC_COMP_MGMT_TXRX); 1003 if (!mgmt_txrx_pdev_ctx) { 1004 mgmt_txrx_err("Mgmt txrx context empty for pdev %pK", pdev); 1005 return QDF_STATUS_E_NULL_VALUE; 1006 } 1007 mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[desc_id]; 1008 if (!mgmt_desc) { 1009 mgmt_txrx_err("Mgmt desc empty for id %d pdev %pK ", 1010 desc_id, pdev); 1011 return QDF_STATUS_E_NULL_VALUE; 1012 } 1013 tx_compl_cb = mgmt_desc->tx_dwnld_cmpl_cb; 1014 ota_comp_cb = mgmt_desc->tx_ota_cmpl_cb; 1015 nbuf = mgmt_desc->nbuf; 1016 1017 /* 1018 * TO DO 1019 * Make the API more generic to handle tx download completion as well 1020 * as OTA completion separately. 1021 */ 1022 1023 /* 1024 * 1. If the tx frame is sent by any UMAC converged component then it 1025 * passes the context as NULL while calling mgmt txrx API for 1026 * sending mgmt frame. If context is NULL, peer will be passed as 1027 * cb_context in completion callbacks. 1028 * 2. If the tx frame is sent by legacy MLME then it passes the context 1029 * as its specific context (for ex- mac context in case of MCL) while 1030 * calling mgmt txrx API for sending mgmt frame. This caller specific 1031 * context is passed as cb_context in completion callbacks. 1032 */ 1033 if (mgmt_desc->context) 1034 cb_context = mgmt_desc->context; 1035 else 1036 cb_context = (void *)mgmt_desc->peer; 1037 1038 if (!tx_compl_cb && !ota_comp_cb) { 1039 qdf_nbuf_free(nbuf); 1040 goto no_registered_cb; 1041 } 1042 1043 if (tx_compl_cb) 1044 tx_compl_cb(cb_context, nbuf, status); 1045 1046 if (ota_comp_cb) 1047 ota_comp_cb(cb_context, nbuf, status, tx_compl_params); 1048 1049 no_registered_cb: 1050 /* 1051 * decrementing the peer ref count that was incremented while 1052 * accessing peer in wlan_mgmt_txrx_mgmt_frame_tx 1053 */ 1054 wlan_objmgr_peer_release_ref(mgmt_desc->peer, WLAN_MGMT_NB_ID); 1055 wlan_mgmt_txrx_desc_put(mgmt_txrx_pdev_ctx, desc_id); 1056 return QDF_STATUS_SUCCESS; 1057 } 1058 1059 qdf_nbuf_t tgt_mgmt_txrx_get_nbuf_from_desc_id( 1060 struct wlan_objmgr_pdev *pdev, 1061 uint32_t desc_id) 1062 { 1063 struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx; 1064 struct mgmt_txrx_desc_elem_t *mgmt_desc; 1065 qdf_nbuf_t buf; 1066 1067 mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *) 1068 wlan_objmgr_pdev_get_comp_private_obj(pdev, 1069 WLAN_UMAC_COMP_MGMT_TXRX); 1070 if (!mgmt_txrx_pdev_ctx) { 1071 mgmt_txrx_err("Mgmt txrx context empty for pdev %pK", pdev); 1072 goto fail; 1073 } 1074 mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[desc_id]; 1075 if (!mgmt_desc) { 1076 mgmt_txrx_err("Mgmt descriptor unavailable for id %d pdev %pK", 1077 desc_id, pdev); 1078 goto fail; 1079 } 1080 buf = mgmt_desc->nbuf; 1081 return buf; 1082 1083 fail: 1084 return NULL; 1085 } 1086 1087 struct wlan_objmgr_peer * 1088 tgt_mgmt_txrx_get_peer_from_desc_id( 1089 struct wlan_objmgr_pdev *pdev, 1090 uint32_t desc_id) 1091 { 1092 struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx; 1093 struct mgmt_txrx_desc_elem_t *mgmt_desc; 1094 struct wlan_objmgr_peer *peer; 1095 1096 mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *) 1097 wlan_objmgr_pdev_get_comp_private_obj(pdev, 1098 WLAN_UMAC_COMP_MGMT_TXRX); 1099 if (!mgmt_txrx_pdev_ctx) { 1100 mgmt_txrx_err("Mgmt txrx context empty for pdev %pK", pdev); 1101 goto fail; 1102 } 1103 1104 mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[desc_id]; 1105 if (!mgmt_desc) { 1106 mgmt_txrx_err("Mgmt descriptor unavailable for id %d pdev %pK", 1107 desc_id, pdev); 1108 goto fail; 1109 } 1110 1111 peer = mgmt_desc->peer; 1112 return peer; 1113 1114 fail: 1115 return NULL; 1116 } 1117 1118 uint8_t tgt_mgmt_txrx_get_vdev_id_from_desc_id( 1119 struct wlan_objmgr_pdev *pdev, 1120 uint32_t desc_id) 1121 { 1122 struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx; 1123 struct mgmt_txrx_desc_elem_t *mgmt_desc; 1124 uint8_t vdev_id; 1125 1126 mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *) 1127 wlan_objmgr_pdev_get_comp_private_obj(pdev, 1128 WLAN_UMAC_COMP_MGMT_TXRX); 1129 if (!mgmt_txrx_pdev_ctx) { 1130 mgmt_txrx_err("Mgmt txrx context empty for pdev %pK", pdev); 1131 goto fail; 1132 } 1133 1134 mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[desc_id]; 1135 if (!mgmt_desc) { 1136 mgmt_txrx_err("Mgmt descriptor unavailable for id %d pdev %pK", 1137 desc_id, pdev); 1138 goto fail; 1139 } 1140 1141 vdev_id = mgmt_desc->vdev_id; 1142 return vdev_id; 1143 1144 fail: 1145 return WLAN_UMAC_VDEV_ID_MAX; 1146 } 1147 1148 uint32_t tgt_mgmt_txrx_get_free_desc_pool_count( 1149 struct wlan_objmgr_pdev *pdev) 1150 { 1151 struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx; 1152 uint32_t free_desc_count = WLAN_INVALID_MGMT_DESC_COUNT; 1153 1154 mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *) 1155 wlan_objmgr_pdev_get_comp_private_obj(pdev, 1156 WLAN_UMAC_COMP_MGMT_TXRX); 1157 if (!mgmt_txrx_pdev_ctx) { 1158 mgmt_txrx_err("Mgmt txrx context empty for pdev %pK", pdev); 1159 goto fail; 1160 } 1161 1162 free_desc_count = qdf_list_size( 1163 &(mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list)); 1164 1165 fail: 1166 return free_desc_count; 1167 } 1168