1 /* 2 * Copyright (c) 2013-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: wma_mgmt.c 21 * 22 * This file contains STA/SAP and protocol related functions. 23 */ 24 25 /* Header files */ 26 27 #include "wma.h" 28 #include "wma_api.h" 29 #include "cds_api.h" 30 #include "wmi_unified_api.h" 31 #include "wlan_qct_sys.h" 32 #include "wni_api.h" 33 #include "ani_global.h" 34 #include "wmi_unified.h" 35 #include "wni_cfg.h" 36 37 #include "qdf_nbuf.h" 38 #include "qdf_types.h" 39 #include "qdf_mem.h" 40 41 #include "wma_types.h" 42 #include "lim_api.h" 43 #include "lim_session_utils.h" 44 45 #include "cds_utils.h" 46 #include "wlan_blm_api.h" 47 #if !defined(REMOVE_PKT_LOG) 48 #include "pktlog_ac.h" 49 #else 50 #include "pktlog_ac_fmt.h" 51 #endif /* REMOVE_PKT_LOG */ 52 53 #include "dbglog_host.h" 54 #include "csr_api.h" 55 #include "ol_fw.h" 56 #include "wma_internal.h" 57 #include "wlan_policy_mgr_api.h" 58 #include "cdp_txrx_flow_ctrl_legacy.h" 59 #include <cdp_txrx_peer_ops.h> 60 #include <cdp_txrx_pmf.h> 61 #include <cdp_txrx_cfg.h> 62 #include <cdp_txrx_cmn.h> 63 #include <cdp_txrx_misc.h> 64 #include <cdp_txrx_misc.h> 65 #include "wlan_mgmt_txrx_tgt_api.h" 66 #include "wlan_objmgr_psoc_obj.h" 67 #include "wlan_objmgr_pdev_obj.h" 68 #include "wlan_objmgr_vdev_obj.h" 69 #include "wlan_lmac_if_api.h" 70 #include <cdp_txrx_handle.h> 71 #include "wma_he.h" 72 #include "wma_eht.h" 73 #include <qdf_crypto.h> 74 #include "wma_twt.h" 75 #include "wlan_p2p_cfg_api.h" 76 #include "cfg_ucfg_api.h" 77 #include "cfg_mlme_sta.h" 78 #include "wlan_mlme_api.h" 79 #include "wmi_unified_bcn_api.h" 80 #include <wlan_crypto_global_api.h> 81 #include <wlan_mlme_main.h> 82 #include <../../core/src/vdev_mgr_ops.h> 83 #include "wlan_pkt_capture_ucfg_api.h" 84 85 #if !defined(REMOVE_PKT_LOG) 86 #include <wlan_logging_sock_svc.h> 87 #endif 88 #include "wlan_cm_roam_api.h" 89 90 /** 91 * wma_send_bcn_buf_ll() - prepare and send beacon buffer to fw for LL 92 * @wma: wma handle 93 * @vdev_id: vdev id 94 * @param_buf: SWBA parameters 95 * 96 * Return: none 97 */ 98 #ifdef WLAN_WMI_BCN 99 static void wma_send_bcn_buf_ll(tp_wma_handle wma, 100 uint8_t vdev_id, 101 WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf) 102 { 103 struct ieee80211_frame *wh; 104 struct beacon_info *bcn; 105 wmi_tim_info *tim_info = param_buf->tim_info; 106 uint8_t *bcn_payload; 107 QDF_STATUS ret; 108 struct beacon_tim_ie *tim_ie; 109 wmi_p2p_noa_info *p2p_noa_info = param_buf->p2p_noa_info; 110 struct p2p_sub_element_noa noa_ie; 111 struct wmi_bcn_send_from_host params; 112 uint8_t i; 113 114 bcn = wma->interfaces[vdev_id].beacon; 115 if (!bcn || !bcn->buf) { 116 wma_err("Invalid beacon buffer"); 117 return; 118 } 119 120 if (!param_buf->tim_info || !param_buf->p2p_noa_info) { 121 wma_err("Invalid tim info or p2p noa info"); 122 return; 123 } 124 125 if (WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info) > 126 WMI_P2P_MAX_NOA_DESCRIPTORS) { 127 wma_err("Too many descriptors %d", 128 WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info)); 129 return; 130 } 131 132 qdf_spin_lock_bh(&bcn->lock); 133 134 bcn_payload = qdf_nbuf_data(bcn->buf); 135 136 tim_ie = (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]); 137 138 if (tim_info->tim_changed) { 139 if (tim_info->tim_num_ps_pending) 140 qdf_mem_copy(&tim_ie->tim_bitmap, tim_info->tim_bitmap, 141 WMA_TIM_SUPPORTED_PVB_LENGTH); 142 else 143 qdf_mem_zero(&tim_ie->tim_bitmap, 144 WMA_TIM_SUPPORTED_PVB_LENGTH); 145 /* 146 * Currently we support fixed number of 147 * peers as limited by HAL_NUM_STA. 148 * tim offset is always 0 149 */ 150 tim_ie->tim_bitctl = 0; 151 } 152 153 /* Update DTIM Count */ 154 if (tim_ie->dtim_count == 0) 155 tim_ie->dtim_count = tim_ie->dtim_period - 1; 156 else 157 tim_ie->dtim_count--; 158 159 /* 160 * DTIM count needs to be backedup so that 161 * when umac updates the beacon template 162 * current dtim count can be updated properly 163 */ 164 bcn->dtim_count = tim_ie->dtim_count; 165 166 /* update state for buffered multicast frames on DTIM */ 167 if (tim_info->tim_mcast && (tim_ie->dtim_count == 0 || 168 tim_ie->dtim_period == 1)) 169 tim_ie->tim_bitctl |= 1; 170 else 171 tim_ie->tim_bitctl &= ~1; 172 173 /* To avoid sw generated frame sequence the same as H/W generated frame, 174 * the value lower than min_sw_seq is reserved for HW generated frame 175 */ 176 if ((bcn->seq_no & IEEE80211_SEQ_MASK) < MIN_SW_SEQ) 177 bcn->seq_no = MIN_SW_SEQ; 178 179 wh = (struct ieee80211_frame *)bcn_payload; 180 *(uint16_t *) &wh->i_seq[0] = htole16(bcn->seq_no 181 << IEEE80211_SEQ_SEQ_SHIFT); 182 bcn->seq_no++; 183 184 if (WMI_UNIFIED_NOA_ATTR_IS_MODIFIED(p2p_noa_info)) { 185 qdf_mem_zero(&noa_ie, sizeof(noa_ie)); 186 187 noa_ie.index = 188 (uint8_t) WMI_UNIFIED_NOA_ATTR_INDEX_GET(p2p_noa_info); 189 noa_ie.oppPS = 190 (uint8_t) WMI_UNIFIED_NOA_ATTR_OPP_PS_GET(p2p_noa_info); 191 noa_ie.ctwindow = 192 (uint8_t) WMI_UNIFIED_NOA_ATTR_CTWIN_GET(p2p_noa_info); 193 noa_ie.num_descriptors = (uint8_t) 194 WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info); 195 wma_debug("index %u, oppPs %u, ctwindow %u, num_descriptors = %u", 196 noa_ie.index, 197 noa_ie.oppPS, noa_ie.ctwindow, noa_ie.num_descriptors); 198 for (i = 0; i < noa_ie.num_descriptors; i++) { 199 noa_ie.noa_descriptors[i].type_count = 200 (uint8_t) p2p_noa_info->noa_descriptors[i]. 201 type_count; 202 noa_ie.noa_descriptors[i].duration = 203 p2p_noa_info->noa_descriptors[i].duration; 204 noa_ie.noa_descriptors[i].interval = 205 p2p_noa_info->noa_descriptors[i].interval; 206 noa_ie.noa_descriptors[i].start_time = 207 p2p_noa_info->noa_descriptors[i].start_time; 208 wma_debug("NoA descriptor[%d] type_count %u, duration %u, interval %u, start_time = %u", 209 i, 210 noa_ie.noa_descriptors[i].type_count, 211 noa_ie.noa_descriptors[i].duration, 212 noa_ie.noa_descriptors[i].interval, 213 noa_ie.noa_descriptors[i].start_time); 214 } 215 wma_update_noa(bcn, &noa_ie); 216 217 /* Send a msg to LIM to update the NoA IE in probe response 218 * frames transmitted by the host 219 */ 220 wma_update_probe_resp_noa(wma, &noa_ie); 221 } 222 223 if (bcn->dma_mapped) { 224 qdf_nbuf_unmap_single(wma->qdf_dev, bcn->buf, QDF_DMA_TO_DEVICE); 225 bcn->dma_mapped = 0; 226 } 227 ret = qdf_nbuf_map_single(wma->qdf_dev, bcn->buf, QDF_DMA_TO_DEVICE); 228 if (ret != QDF_STATUS_SUCCESS) { 229 wma_err("failed map beacon buf to DMA region"); 230 qdf_spin_unlock_bh(&bcn->lock); 231 return; 232 } 233 234 bcn->dma_mapped = 1; 235 params.vdev_id = vdev_id; 236 params.data_len = bcn->len; 237 params.frame_ctrl = *((A_UINT16 *) wh->i_fc); 238 params.frag_ptr = qdf_nbuf_get_frag_paddr(bcn->buf, 0); 239 params.dtim_flag = 0; 240 /* notify Firmware of DTM and mcast/bcast traffic */ 241 if (tim_ie->dtim_count == 0) { 242 params.dtim_flag |= WMI_BCN_SEND_DTIM_ZERO; 243 /* deliver mcast/bcast traffic in next DTIM beacon */ 244 if (tim_ie->tim_bitctl & 0x01) 245 params.dtim_flag |= WMI_BCN_SEND_DTIM_BITCTL_SET; 246 } 247 248 wmi_unified_bcn_buf_ll_cmd(wma->wmi_handle, 249 ¶ms); 250 251 qdf_spin_unlock_bh(&bcn->lock); 252 } 253 #else 254 static inline void 255 wma_send_bcn_buf_ll(tp_wma_handle wma, 256 uint8_t vdev_id, 257 WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf) 258 { 259 } 260 #endif 261 /** 262 * wma_beacon_swba_handler() - swba event handler 263 * @handle: wma handle 264 * @event: event data 265 * @len: data length 266 * 267 * SWBA event is alert event to Host requesting host to Queue a beacon 268 * for transmission use only in host beacon mode 269 * 270 * Return: 0 for success or error code 271 */ 272 #ifdef WLAN_WMI_BCN 273 int wma_beacon_swba_handler(void *handle, uint8_t *event, uint32_t len) 274 { 275 tp_wma_handle wma = (tp_wma_handle) handle; 276 WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf; 277 wmi_host_swba_event_fixed_param *swba_event; 278 uint32_t vdev_map; 279 uint8_t vdev_id = 0; 280 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 281 282 param_buf = (WMI_HOST_SWBA_EVENTID_param_tlvs *) event; 283 if (!param_buf) { 284 wma_err("Invalid swba event buffer"); 285 return -EINVAL; 286 } 287 swba_event = param_buf->fixed_param; 288 vdev_map = swba_event->vdev_map; 289 290 wma_debug("vdev_map = %d", vdev_map); 291 for (; vdev_map && vdev_id < wma->max_bssid; 292 vdev_id++, vdev_map >>= 1) { 293 if (!(vdev_map & 0x1)) 294 continue; 295 if (!cdp_cfg_is_high_latency(soc, 296 (struct cdp_cfg *)cds_get_context(QDF_MODULE_ID_CFG))) 297 wma_send_bcn_buf_ll(wma, vdev_id, param_buf); 298 break; 299 } 300 return 0; 301 } 302 #else 303 static inline int 304 wma_beacon_swba_handler(void *handle, uint8_t *event, uint32_t len) 305 { 306 return 0; 307 } 308 #endif 309 310 #ifdef FEATURE_WLAN_DIAG_SUPPORT 311 void wma_sta_kickout_event(uint32_t kickout_reason, uint8_t vdev_id, 312 uint8_t *macaddr) 313 { 314 WLAN_HOST_DIAG_EVENT_DEF(sta_kickout, struct host_event_wlan_kickout); 315 qdf_mem_zero(&sta_kickout, sizeof(sta_kickout)); 316 sta_kickout.reasoncode = kickout_reason; 317 sta_kickout.vdev_id = vdev_id; 318 if (macaddr) 319 qdf_mem_copy(sta_kickout.peer_mac, macaddr, 320 QDF_MAC_ADDR_SIZE); 321 WLAN_HOST_DIAG_EVENT_REPORT(&sta_kickout, EVENT_WLAN_STA_KICKOUT); 322 } 323 #endif 324 325 int wma_peer_sta_kickout_event_handler(void *handle, uint8_t *event, 326 uint32_t len) 327 { 328 tp_wma_handle wma = (tp_wma_handle) handle; 329 WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *param_buf = NULL; 330 wmi_peer_sta_kickout_event_fixed_param *kickout_event = NULL; 331 uint8_t vdev_id, macaddr[QDF_MAC_ADDR_SIZE]; 332 tpDeleteStaContext del_sta_ctx; 333 uint8_t *addr, *bssid; 334 struct wlan_objmgr_vdev *vdev; 335 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 336 337 param_buf = (WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *) event; 338 kickout_event = param_buf->fixed_param; 339 WMI_MAC_ADDR_TO_CHAR_ARRAY(&kickout_event->peer_macaddr, macaddr); 340 if (cdp_peer_get_vdevid(soc, macaddr, &vdev_id) != 341 QDF_STATUS_SUCCESS) { 342 wma_err("Not able to find BSSID for peer ["QDF_MAC_ADDR_FMT"]", 343 QDF_MAC_ADDR_REF(macaddr)); 344 return -EINVAL; 345 } 346 vdev = wma->interfaces[vdev_id].vdev; 347 if (!vdev) { 348 wma_err("Not able to find vdev for VDEV_%d", vdev_id); 349 return -EINVAL; 350 } 351 addr = wlan_vdev_mlme_get_macaddr(vdev); 352 353 wma_nofl_info("STA kickout for "QDF_MAC_ADDR_FMT", on mac "QDF_MAC_ADDR_FMT", vdev %d, reason:%d", 354 QDF_MAC_ADDR_REF(macaddr), QDF_MAC_ADDR_REF(addr), 355 vdev_id, kickout_event->reason); 356 357 if (wma->interfaces[vdev_id].roaming_in_progress) { 358 wma_err("Ignore STA kick out since roaming is in progress"); 359 return -EINVAL; 360 } 361 bssid = wma_get_vdev_bssid(wma->interfaces[vdev_id].vdev); 362 if (!bssid) { 363 wma_err("Failed to get bssid for vdev_%d", vdev_id); 364 return -ENOMEM; 365 } 366 367 switch (kickout_event->reason) { 368 case WMI_PEER_STA_KICKOUT_REASON_IBSS_DISCONNECT: 369 goto exit_handler; 370 #ifdef FEATURE_WLAN_TDLS 371 case WMI_PEER_STA_KICKOUT_REASON_TDLS_DISCONNECT: 372 del_sta_ctx = (tpDeleteStaContext) 373 qdf_mem_malloc(sizeof(tDeleteStaContext)); 374 if (!del_sta_ctx) { 375 wma_err("mem alloc failed for struct del_sta_context for TDLS peer: "QDF_MAC_ADDR_FMT, 376 QDF_MAC_ADDR_REF(macaddr)); 377 return -ENOMEM; 378 } 379 380 del_sta_ctx->is_tdls = true; 381 del_sta_ctx->vdev_id = vdev_id; 382 qdf_mem_copy(del_sta_ctx->addr2, macaddr, QDF_MAC_ADDR_SIZE); 383 qdf_mem_copy(del_sta_ctx->bssId, bssid, 384 QDF_MAC_ADDR_SIZE); 385 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE; 386 wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND, 387 (void *)del_sta_ctx, 0); 388 goto exit_handler; 389 #endif /* FEATURE_WLAN_TDLS */ 390 391 case WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED: 392 /* 393 * Default legacy value used by original firmware implementation 394 */ 395 if (wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA && 396 (wma->interfaces[vdev_id].sub_type == 0 || 397 wma->interfaces[vdev_id].sub_type == 398 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) && 399 !qdf_mem_cmp(bssid, 400 macaddr, QDF_MAC_ADDR_SIZE)) { 401 wma_sta_kickout_event( 402 HOST_STA_KICKOUT_REASON_UNSPECIFIED, vdev_id, macaddr); 403 /* 404 * KICKOUT event is for current station-AP connection. 405 * Treat it like final beacon miss. Station may not have 406 * missed beacons but not able to transmit frames to AP 407 * for a long time. Must disconnect to get out of 408 * this sticky situation. 409 * In future implementation, roaming module will also 410 * handle this event and perform a scan. 411 */ 412 wma_warn("WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED event for STA"); 413 wma_beacon_miss_handler(wma, vdev_id, 414 kickout_event->rssi); 415 goto exit_handler; 416 } 417 break; 418 419 case WMI_PEER_STA_KICKOUT_REASON_XRETRY: 420 case WMI_PEER_STA_KICKOUT_REASON_INACTIVITY: 421 /* 422 * Handle SA query kickout is same as inactivity kickout. 423 * This could be for STA or SAP role 424 */ 425 case WMI_PEER_STA_KICKOUT_REASON_SA_QUERY_TIMEOUT: 426 default: 427 break; 428 } 429 430 /* 431 * default action is to send delete station context indication to LIM 432 */ 433 del_sta_ctx = 434 (tDeleteStaContext *) qdf_mem_malloc(sizeof(tDeleteStaContext)); 435 if (!del_sta_ctx) { 436 wma_err("QDF MEM Alloc Failed for struct del_sta_context"); 437 return -ENOMEM; 438 } 439 440 del_sta_ctx->is_tdls = false; 441 del_sta_ctx->vdev_id = vdev_id; 442 qdf_mem_copy(del_sta_ctx->addr2, macaddr, QDF_MAC_ADDR_SIZE); 443 qdf_mem_copy(del_sta_ctx->bssId, addr, QDF_MAC_ADDR_SIZE); 444 if (kickout_event->reason == 445 WMI_PEER_STA_KICKOUT_REASON_SA_QUERY_TIMEOUT) 446 del_sta_ctx->reasonCode = 447 HAL_DEL_STA_REASON_CODE_SA_QUERY_TIMEOUT; 448 else if (kickout_event->reason == WMI_PEER_STA_KICKOUT_REASON_XRETRY) 449 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_XRETRY; 450 else 451 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE; 452 453 if (wmi_service_enabled(wma->wmi_handle, 454 wmi_service_hw_db2dbm_support)) 455 del_sta_ctx->rssi = kickout_event->rssi; 456 else 457 del_sta_ctx->rssi = kickout_event->rssi + 458 WMA_TGT_NOISE_FLOOR_DBM; 459 wma_sta_kickout_event(del_sta_ctx->reasonCode, vdev_id, macaddr); 460 wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND, (void *)del_sta_ctx, 461 0); 462 wma_lost_link_info_handler(wma, vdev_id, del_sta_ctx->rssi); 463 464 exit_handler: 465 return 0; 466 } 467 468 int wma_unified_bcntx_status_event_handler(void *handle, 469 uint8_t *cmd_param_info, 470 uint32_t len) 471 { 472 tp_wma_handle wma = (tp_wma_handle) handle; 473 WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *param_buf; 474 wmi_offload_bcn_tx_status_event_fixed_param *resp_event; 475 tSirFirstBeaconTxCompleteInd *beacon_tx_complete_ind; 476 477 param_buf = 478 (WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *) cmd_param_info; 479 if (!param_buf) { 480 wma_err("Invalid bcn tx response event buffer"); 481 return -EINVAL; 482 } 483 484 resp_event = param_buf->fixed_param; 485 486 if (resp_event->vdev_id >= wma->max_bssid) { 487 wma_err("received invalid vdev_id %d", resp_event->vdev_id); 488 return -EINVAL; 489 } 490 491 /* Check for valid handle to ensure session is not 492 * deleted in any race 493 */ 494 if (!wma->interfaces[resp_event->vdev_id].vdev) { 495 wma_err("vdev is NULL for vdev_%d", resp_event->vdev_id); 496 return -EINVAL; 497 } 498 499 /* Beacon Tx Indication supports only AP mode. Ignore in other modes */ 500 if (wma_is_vdev_in_ap_mode(wma, resp_event->vdev_id) == false) { 501 wma_debug("Beacon Tx Indication does not support type %d and sub_type %d", 502 wma->interfaces[resp_event->vdev_id].type, 503 wma->interfaces[resp_event->vdev_id].sub_type); 504 return 0; 505 } 506 507 beacon_tx_complete_ind = (tSirFirstBeaconTxCompleteInd *) 508 qdf_mem_malloc(sizeof(tSirFirstBeaconTxCompleteInd)); 509 if (!beacon_tx_complete_ind) { 510 wma_err("Failed to alloc beacon_tx_complete_ind"); 511 return -ENOMEM; 512 } 513 514 beacon_tx_complete_ind->messageType = WMA_DFS_BEACON_TX_SUCCESS_IND; 515 beacon_tx_complete_ind->length = sizeof(tSirFirstBeaconTxCompleteInd); 516 beacon_tx_complete_ind->bss_idx = resp_event->vdev_id; 517 518 wma_send_msg(wma, WMA_DFS_BEACON_TX_SUCCESS_IND, 519 (void *)beacon_tx_complete_ind, 0); 520 return 0; 521 } 522 523 /** 524 * wma_get_go_probe_timeout() - get P2P GO probe timeout 525 * @mac: UMAC handler 526 * @max_inactive_time: return max inactive time 527 * @max_unresponsive_time: return max unresponsive time 528 * 529 * Return: none 530 */ 531 #ifdef CONVERGED_P2P_ENABLE 532 static inline void 533 wma_get_go_probe_timeout(struct mac_context *mac, 534 uint32_t *max_inactive_time, 535 uint32_t *max_unresponsive_time) 536 { 537 uint32_t keep_alive; 538 QDF_STATUS status; 539 540 status = cfg_p2p_get_go_link_monitor_period(mac->psoc, 541 max_inactive_time); 542 if (QDF_IS_STATUS_ERROR(status)) { 543 wma_err("Failed to go monitor period"); 544 *max_inactive_time = WMA_LINK_MONITOR_DEFAULT_TIME_SECS; 545 } 546 status = cfg_p2p_get_go_keepalive_period(mac->psoc, 547 &keep_alive); 548 if (QDF_IS_STATUS_ERROR(status)) { 549 wma_err("Failed to read go keep alive"); 550 keep_alive = WMA_KEEP_ALIVE_DEFAULT_TIME_SECS; 551 } 552 553 *max_unresponsive_time = *max_inactive_time + keep_alive; 554 } 555 #else 556 static inline void 557 wma_get_go_probe_timeout(struct mac_context *mac, 558 uint32_t *max_inactive_time, 559 uint32_t *max_unresponsive_time) 560 { 561 } 562 #endif 563 564 /** 565 * wma_get_link_probe_timeout() - get link timeout based on sub type 566 * @mac: UMAC handler 567 * @sub_type: vdev syb type 568 * @max_inactive_time: return max inactive time 569 * @max_unresponsive_time: return max unresponsive time 570 * 571 * Return: none 572 */ 573 static inline void 574 wma_get_link_probe_timeout(struct mac_context *mac, 575 uint32_t sub_type, 576 uint32_t *max_inactive_time, 577 uint32_t *max_unresponsive_time) 578 { 579 if (sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO) { 580 wma_get_go_probe_timeout(mac, max_inactive_time, 581 max_unresponsive_time); 582 } else { 583 *max_inactive_time = 584 mac->mlme_cfg->timeouts.ap_link_monitor_timeout; 585 *max_unresponsive_time = *max_inactive_time + 586 mac->mlme_cfg->timeouts.ap_keep_alive_timeout; 587 } 588 } 589 590 /** 591 * wma_verify_rate_code() - verify if rate code is valid. 592 * @rate_code: rate code 593 * @band: band information 594 * 595 * Return: verify result 596 */ 597 static bool wma_verify_rate_code(u_int32_t rate_code, enum cds_band_type band) 598 { 599 uint8_t preamble, nss, rate; 600 bool valid = true; 601 602 preamble = (rate_code & 0xc0) >> 6; 603 nss = (rate_code & 0x30) >> 4; 604 rate = rate_code & 0xf; 605 606 switch (preamble) { 607 case WMI_RATE_PREAMBLE_CCK: 608 if (nss != 0 || rate > 3 || band == CDS_BAND_5GHZ) 609 valid = false; 610 break; 611 case WMI_RATE_PREAMBLE_OFDM: 612 if (nss != 0 || rate > 7) 613 valid = false; 614 break; 615 case WMI_RATE_PREAMBLE_HT: 616 if (nss != 0 || rate > 7) 617 valid = false; 618 break; 619 case WMI_RATE_PREAMBLE_VHT: 620 if (nss != 0 || rate > 9) 621 valid = false; 622 break; 623 default: 624 break; 625 } 626 return valid; 627 } 628 629 #define TX_MGMT_RATE_2G_ENABLE_OFFSET 30 630 #define TX_MGMT_RATE_5G_ENABLE_OFFSET 31 631 #define TX_MGMT_RATE_2G_OFFSET 0 632 #define TX_MGMT_RATE_5G_OFFSET 12 633 634 /** 635 * wma_set_mgmt_rate() - set vdev mgmt rate. 636 * @wma: wma handle 637 * @vdev_id: vdev id 638 * 639 * Return: None 640 */ 641 void wma_set_vdev_mgmt_rate(tp_wma_handle wma, uint8_t vdev_id) 642 { 643 uint32_t cfg_val; 644 int ret; 645 uint32_t per_band_mgmt_tx_rate = 0; 646 enum cds_band_type band = 0; 647 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); 648 649 if (!mac) { 650 wma_err("Failed to get mac"); 651 return; 652 } 653 654 cfg_val = mac->mlme_cfg->sap_cfg.rate_tx_mgmt; 655 band = CDS_BAND_ALL; 656 if ((cfg_val == MLME_CFG_TX_MGMT_RATE_DEF) || 657 !wma_verify_rate_code(cfg_val, band)) { 658 wma_nofl_debug("default WNI_CFG_RATE_FOR_TX_MGMT, ignore"); 659 } else { 660 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id, 661 WMI_VDEV_PARAM_MGMT_TX_RATE, 662 cfg_val); 663 if (ret) 664 wma_err("Failed to set WMI_VDEV_PARAM_MGMT_TX_RATE"); 665 } 666 667 cfg_val = mac->mlme_cfg->sap_cfg.rate_tx_mgmt_2g; 668 band = CDS_BAND_2GHZ; 669 if ((cfg_val == MLME_CFG_TX_MGMT_2G_RATE_DEF) || 670 !wma_verify_rate_code(cfg_val, band)) { 671 wma_nofl_debug("use default 2G MGMT rate."); 672 per_band_mgmt_tx_rate &= 673 ~(1 << TX_MGMT_RATE_2G_ENABLE_OFFSET); 674 } else { 675 per_band_mgmt_tx_rate |= 676 (1 << TX_MGMT_RATE_2G_ENABLE_OFFSET); 677 per_band_mgmt_tx_rate |= 678 ((cfg_val & 0x7FF) << TX_MGMT_RATE_2G_OFFSET); 679 } 680 681 cfg_val = mac->mlme_cfg->sap_cfg.rate_tx_mgmt; 682 band = CDS_BAND_5GHZ; 683 if ((cfg_val == MLME_CFG_TX_MGMT_5G_RATE_DEF) || 684 !wma_verify_rate_code(cfg_val, band)) { 685 wma_nofl_debug("use default 5G MGMT rate."); 686 per_band_mgmt_tx_rate &= 687 ~(1 << TX_MGMT_RATE_5G_ENABLE_OFFSET); 688 } else { 689 per_band_mgmt_tx_rate |= 690 (1 << TX_MGMT_RATE_5G_ENABLE_OFFSET); 691 per_band_mgmt_tx_rate |= 692 ((cfg_val & 0x7FF) << TX_MGMT_RATE_5G_OFFSET); 693 } 694 695 ret = wma_vdev_set_param( 696 wma->wmi_handle, 697 vdev_id, 698 WMI_VDEV_PARAM_PER_BAND_MGMT_TX_RATE, 699 per_band_mgmt_tx_rate); 700 if (ret) 701 wma_err("Failed to set WMI_VDEV_PARAM_PER_BAND_MGMT_TX_RATE"); 702 703 } 704 705 /** 706 * wma_set_sap_keepalive() - set SAP keep alive parameters to fw 707 * @wma: wma handle 708 * @vdev_id: vdev id 709 * 710 * Return: none 711 */ 712 void wma_set_sap_keepalive(tp_wma_handle wma, uint8_t vdev_id) 713 { 714 uint32_t min_inactive_time, max_inactive_time, max_unresponsive_time; 715 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); 716 QDF_STATUS status; 717 718 if (!mac) { 719 wma_err("Failed to get mac"); 720 return; 721 } 722 723 wma_get_link_probe_timeout(mac, wma->interfaces[vdev_id].sub_type, 724 &max_inactive_time, &max_unresponsive_time); 725 726 min_inactive_time = max_inactive_time / 2; 727 728 status = wma_vdev_set_param(wma->wmi_handle, vdev_id, 729 WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS, 730 min_inactive_time); 731 if (QDF_IS_STATUS_ERROR(status)) 732 wma_err("Failed to Set AP MIN IDLE INACTIVE TIME"); 733 734 status = wma_vdev_set_param(wma->wmi_handle, vdev_id, 735 WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS, 736 max_inactive_time); 737 if (QDF_IS_STATUS_ERROR(status)) 738 wma_err("Failed to Set AP MAX IDLE INACTIVE TIME"); 739 740 status = wma_vdev_set_param(wma->wmi_handle, vdev_id, 741 WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS, 742 max_unresponsive_time); 743 if (QDF_IS_STATUS_ERROR(status)) 744 wma_err("Failed to Set MAX UNRESPONSIVE TIME"); 745 746 wma_debug("vdev_id:%d min_inactive_time: %u max_inactive_time: %u max_unresponsive_time: %u", 747 vdev_id, min_inactive_time, max_inactive_time, 748 max_unresponsive_time); 749 } 750 751 /** 752 * wma_set_sta_sa_query_param() - set sta sa query parameters 753 * @wma: wma handle 754 * @vdev_id: vdev id 755 756 * This function sets sta query related parameters in fw. 757 * 758 * Return: none 759 */ 760 761 void wma_set_sta_sa_query_param(tp_wma_handle wma, 762 uint8_t vdev_id) 763 { 764 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); 765 uint8_t max_retries; 766 uint16_t retry_interval; 767 768 if (!mac) { 769 wma_err("mac context is NULL"); 770 return; 771 } 772 773 max_retries = mac->mlme_cfg->gen.pmf_sa_query_max_retries; 774 retry_interval = mac->mlme_cfg->gen.pmf_sa_query_retry_interval; 775 776 wmi_unified_set_sta_sa_query_param_cmd(wma->wmi_handle, 777 vdev_id, 778 max_retries, 779 retry_interval); 780 } 781 782 /** 783 * wma_set_sta_keep_alive() - set sta keep alive parameters 784 * @wma: wma handle 785 * @vdev_id: vdev id 786 * @method: method for keep alive 787 * @timeperiod: time period 788 * @hostv4addr: host ipv4 address 789 * @destv4addr: dst ipv4 address 790 * @destmac: destination mac 791 * 792 * This function sets keep alive related parameters in fw. 793 * 794 * Return: none 795 */ 796 void wma_set_sta_keep_alive(tp_wma_handle wma, uint8_t vdev_id, 797 uint32_t method, uint32_t timeperiod, 798 uint8_t *hostv4addr, uint8_t *destv4addr, 799 uint8_t *destmac) 800 { 801 struct sta_keep_alive_params params = { 0 }; 802 struct wma_txrx_node *intr; 803 804 if (wma_validate_handle(wma)) 805 return; 806 807 intr = &wma->interfaces[vdev_id]; 808 if (timeperiod > cfg_max(CFG_INFRA_STA_KEEP_ALIVE_PERIOD)) { 809 wmi_err("Invalid period %d Max limit %d", timeperiod, 810 cfg_max(CFG_INFRA_STA_KEEP_ALIVE_PERIOD)); 811 return; 812 } 813 814 params.vdev_id = vdev_id; 815 params.method = method; 816 params.timeperiod = timeperiod; 817 if (intr) { 818 if (intr->bss_max_idle_period) 819 params.timeperiod = intr->bss_max_idle_period; 820 } 821 822 if (hostv4addr) 823 qdf_mem_copy(params.hostv4addr, hostv4addr, QDF_IPV4_ADDR_SIZE); 824 if (destv4addr) 825 qdf_mem_copy(params.destv4addr, destv4addr, QDF_IPV4_ADDR_SIZE); 826 if (destmac) 827 qdf_mem_copy(params.destmac, destmac, QDF_MAC_ADDR_SIZE); 828 829 wmi_unified_set_sta_keep_alive_cmd(wma->wmi_handle, ¶ms); 830 } 831 832 /** 833 * wma_vdev_install_key_complete_event_handler() - install key complete handler 834 * @handle: wma handle 835 * @event: event data 836 * @len: data length 837 * 838 * This event is sent by fw once WPA/WPA2 keys are installed in fw. 839 * 840 * Return: 0 for success or error code 841 */ 842 int wma_vdev_install_key_complete_event_handler(void *handle, 843 uint8_t *event, 844 uint32_t len) 845 { 846 WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *param_buf = NULL; 847 wmi_vdev_install_key_complete_event_fixed_param *key_fp = NULL; 848 849 if (!event) { 850 wma_err("event param null"); 851 return -EINVAL; 852 } 853 854 param_buf = (WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *) event; 855 if (!param_buf) { 856 wma_err("received null buf from target"); 857 return -EINVAL; 858 } 859 860 key_fp = param_buf->fixed_param; 861 if (!key_fp) { 862 wma_err("received null event data from target"); 863 return -EINVAL; 864 } 865 /* 866 * Do nothing for now. Completion of set key is already indicated to lim 867 */ 868 wma_debug("WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID"); 869 return 0; 870 } 871 /* 872 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": 873 * 0 for no restriction 874 * 1 for 1/4 us - Our lower layer calculations limit our precision to 1 msec 875 * 2 for 1/2 us - Our lower layer calculations limit our precision to 1 msec 876 * 3 for 1 us 877 * 4 for 2 us 878 * 5 for 4 us 879 * 6 for 8 us 880 * 7 for 16 us 881 */ 882 static const uint8_t wma_mpdu_spacing[] = { 0, 1, 1, 1, 2, 4, 8, 16 }; 883 884 /** 885 * wma_parse_mpdudensity() - give mpdu spacing from mpdu density 886 * @mpdudensity: mpdu density 887 * 888 * Return: mpdu spacing or 0 for error 889 */ 890 static inline uint8_t wma_parse_mpdudensity(uint8_t mpdudensity) 891 { 892 if (mpdudensity < sizeof(wma_mpdu_spacing)) 893 return wma_mpdu_spacing[mpdudensity]; 894 else 895 return 0; 896 } 897 898 #define CFG_CTRL_MASK 0xFF00 899 #define CFG_DATA_MASK 0x00FF 900 901 /** 902 * wma_mask_tx_ht_rate() - mask tx ht rate based on config 903 * @wma: wma handle 904 * @mcs_set mcs set buffer 905 * 906 * Return: None 907 */ 908 static void wma_mask_tx_ht_rate(tp_wma_handle wma, uint8_t *mcs_set) 909 { 910 uint32_t i, j; 911 uint16_t mcs_limit; 912 uint8_t *rate_pos = mcs_set; 913 struct mac_context *mac = wma->mac_context; 914 915 /* 916 * Get MCS limit from ini configure, and map it to rate parameters 917 * This will limit HT rate upper bound. CFG_CTRL_MASK is used to 918 * check whether ini config is enabled and CFG_DATA_MASK to get the 919 * MCS value. 920 */ 921 mcs_limit = mac->mlme_cfg->rates.max_htmcs_txdata; 922 923 if (mcs_limit & CFG_CTRL_MASK) { 924 wma_debug("set mcs_limit %x", mcs_limit); 925 926 mcs_limit &= CFG_DATA_MASK; 927 for (i = 0, j = 0; i < MAX_SUPPORTED_RATES;) { 928 if (j < mcs_limit / 8) { 929 rate_pos[j] = 0xff; 930 j++; 931 i += 8; 932 } else if (j < mcs_limit / 8 + 1) { 933 if (i <= mcs_limit) 934 rate_pos[i / 8] |= 1 << (i % 8); 935 else 936 rate_pos[i / 8] &= ~(1 << (i % 8)); 937 i++; 938 939 if (i >= (j + 1) * 8) 940 j++; 941 } else { 942 rate_pos[j++] = 0; 943 i += 8; 944 } 945 } 946 } 947 } 948 949 #if SUPPORT_11AX 950 /** 951 * wma_fw_to_host_phymode_11ax() - convert fw to host phymode for 11ax phymodes 952 * @phymode: phymode to convert 953 * 954 * Return: one of the 11ax values defined in enum wlan_phymode; 955 * or WLAN_PHYMODE_AUTO if the input is not an 11ax phymode 956 */ 957 static enum wlan_phymode 958 wma_fw_to_host_phymode_11ax(WMI_HOST_WLAN_PHY_MODE phymode) 959 { 960 switch (phymode) { 961 default: 962 return WLAN_PHYMODE_AUTO; 963 case WMI_HOST_MODE_11AX_HE20: 964 return WLAN_PHYMODE_11AXA_HE20; 965 case WMI_HOST_MODE_11AX_HE40: 966 return WLAN_PHYMODE_11AXA_HE40; 967 case WMI_HOST_MODE_11AX_HE80: 968 return WLAN_PHYMODE_11AXA_HE80; 969 case WMI_HOST_MODE_11AX_HE80_80: 970 return WLAN_PHYMODE_11AXA_HE80_80; 971 case WMI_HOST_MODE_11AX_HE160: 972 return WLAN_PHYMODE_11AXA_HE160; 973 case WMI_HOST_MODE_11AX_HE20_2G: 974 return WLAN_PHYMODE_11AXG_HE20; 975 case WMI_HOST_MODE_11AX_HE40_2G: 976 return WLAN_PHYMODE_11AXG_HE40; 977 case WMI_HOST_MODE_11AX_HE80_2G: 978 return WLAN_PHYMODE_11AXG_HE80; 979 } 980 return WLAN_PHYMODE_AUTO; 981 } 982 #else 983 static enum wlan_phymode 984 wma_fw_to_host_phymode_11ax(WMI_HOST_WLAN_PHY_MODE phymode) 985 { 986 return WLAN_PHYMODE_AUTO; 987 } 988 #endif 989 990 #ifdef WLAN_FEATURE_11BE 991 /** 992 * wma_fw_to_host_phymode_11be() - convert fw to host phymode for 11be phymodes 993 * @phymode: phymode to convert 994 * 995 * Return: one of the 11be values defined in enum wlan_phymode; 996 * or WLAN_PHYMODE_AUTO if the input is not an 11be phymode 997 */ 998 static enum wlan_phymode 999 wma_fw_to_host_phymode_11be(WMI_HOST_WLAN_PHY_MODE phymode) 1000 { 1001 switch (phymode) { 1002 default: 1003 return WLAN_PHYMODE_AUTO; 1004 case WMI_HOST_MODE_11BE_EHT20: 1005 return WLAN_PHYMODE_11BEA_EHT20; 1006 case WMI_HOST_MODE_11BE_EHT40: 1007 return WLAN_PHYMODE_11BEA_EHT40; 1008 case WMI_HOST_MODE_11BE_EHT80: 1009 return WLAN_PHYMODE_11BEA_EHT80; 1010 case WMI_HOST_MODE_11BE_EHT160: 1011 return WLAN_PHYMODE_11BEA_EHT160; 1012 case WMI_HOST_MODE_11BE_EHT320: 1013 return WLAN_PHYMODE_11BEA_EHT320; 1014 case WMI_HOST_MODE_11BE_EHT20_2G: 1015 return WLAN_PHYMODE_11BEG_EHT20; 1016 case WMI_HOST_MODE_11BE_EHT40_2G: 1017 return WLAN_PHYMODE_11BEG_EHT40; 1018 } 1019 return WLAN_PHYMODE_AUTO; 1020 } 1021 #else 1022 static enum wlan_phymode 1023 wma_fw_to_host_phymode_11be(WMI_HOST_WLAN_PHY_MODE phymode) 1024 { 1025 return WLAN_PHYMODE_AUTO; 1026 } 1027 #endif 1028 1029 #ifdef CONFIG_160MHZ_SUPPORT 1030 /** 1031 * wma_fw_to_host_phymode_160() - convert fw to host phymode for 160 mhz 1032 * phymodes 1033 * @phymode: phymode to convert 1034 * 1035 * Return: one of the 160 mhz values defined in enum wlan_phymode; 1036 * or WLAN_PHYMODE_AUTO if the input is not a 160 mhz phymode 1037 */ 1038 static enum wlan_phymode 1039 wma_fw_to_host_phymode_160(WMI_HOST_WLAN_PHY_MODE phymode) 1040 { 1041 switch (phymode) { 1042 default: 1043 return WLAN_PHYMODE_AUTO; 1044 case WMI_HOST_MODE_11AC_VHT80_80: 1045 return WLAN_PHYMODE_11AC_VHT80_80; 1046 case WMI_HOST_MODE_11AC_VHT160: 1047 return WLAN_PHYMODE_11AC_VHT160; 1048 } 1049 } 1050 #else 1051 static enum wlan_phymode 1052 wma_fw_to_host_phymode_160(WMI_HOST_WLAN_PHY_MODE phymode) 1053 { 1054 return WLAN_PHYMODE_AUTO; 1055 } 1056 #endif 1057 1058 enum wlan_phymode wma_fw_to_host_phymode(WMI_HOST_WLAN_PHY_MODE phymode) 1059 { 1060 enum wlan_phymode host_phymode; 1061 switch (phymode) { 1062 default: 1063 host_phymode = wma_fw_to_host_phymode_160(phymode); 1064 if (host_phymode != WLAN_PHYMODE_AUTO) 1065 return host_phymode; 1066 host_phymode = wma_fw_to_host_phymode_11ax(phymode); 1067 if (host_phymode != WLAN_PHYMODE_AUTO) 1068 return host_phymode; 1069 return wma_fw_to_host_phymode_11be(phymode); 1070 case WMI_HOST_MODE_11A: 1071 return WLAN_PHYMODE_11A; 1072 case WMI_HOST_MODE_11G: 1073 return WLAN_PHYMODE_11G; 1074 case WMI_HOST_MODE_11B: 1075 return WLAN_PHYMODE_11B; 1076 case WMI_HOST_MODE_11GONLY: 1077 return WLAN_PHYMODE_11G_ONLY; 1078 case WMI_HOST_MODE_11NA_HT20: 1079 return WLAN_PHYMODE_11NA_HT20; 1080 case WMI_HOST_MODE_11NG_HT20: 1081 return WLAN_PHYMODE_11NG_HT20; 1082 case WMI_HOST_MODE_11NA_HT40: 1083 return WLAN_PHYMODE_11NA_HT40; 1084 case WMI_HOST_MODE_11NG_HT40: 1085 return WLAN_PHYMODE_11NG_HT40; 1086 case WMI_HOST_MODE_11AC_VHT20: 1087 return WLAN_PHYMODE_11AC_VHT20; 1088 case WMI_HOST_MODE_11AC_VHT40: 1089 return WLAN_PHYMODE_11AC_VHT40; 1090 case WMI_HOST_MODE_11AC_VHT80: 1091 return WLAN_PHYMODE_11AC_VHT80; 1092 case WMI_HOST_MODE_11AC_VHT20_2G: 1093 return WLAN_PHYMODE_11AC_VHT20_2G; 1094 case WMI_HOST_MODE_11AC_VHT40_2G: 1095 return WLAN_PHYMODE_11AC_VHT40_2G; 1096 case WMI_HOST_MODE_11AC_VHT80_2G: 1097 return WLAN_PHYMODE_11AC_VHT80_2G; 1098 } 1099 } 1100 1101 #ifdef CONFIG_160MHZ_SUPPORT 1102 /** 1103 * wma_host_to_fw_phymode_160() - convert host to fw phymode for 160 mhz 1104 * @host_phymode: phymode to convert 1105 * 1106 * Return: one of the 160 mhz values defined in enum WMI_HOST_WLAN_PHY_MODE; 1107 * or WMI_HOST_MODE_UNKNOWN if the input is not a 160 mhz phymode 1108 */ 1109 static WMI_HOST_WLAN_PHY_MODE 1110 wma_host_to_fw_phymode_160(enum wlan_phymode host_phymode) 1111 { 1112 switch (host_phymode) { 1113 case WLAN_PHYMODE_11AC_VHT80_80: 1114 return WMI_HOST_MODE_11AC_VHT80_80; 1115 case WLAN_PHYMODE_11AC_VHT160: 1116 return WMI_HOST_MODE_11AC_VHT160; 1117 default: 1118 return WMI_HOST_MODE_UNKNOWN; 1119 } 1120 } 1121 #else 1122 static WMI_HOST_WLAN_PHY_MODE 1123 wma_host_to_fw_phymode_160(enum wlan_phymode host_phymode) 1124 { 1125 return WMI_HOST_MODE_UNKNOWN; 1126 } 1127 #endif 1128 1129 #if SUPPORT_11AX 1130 /** 1131 * wma_host_to_fw_phymode_11ax() - convert host to fw phymode for 11ax phymode 1132 * @host_phymode: phymode to convert 1133 * 1134 * Return: one of the 11ax values defined in enum WMI_HOST_WLAN_PHY_MODE; 1135 * or WMI_HOST_MODE_UNKNOWN if the input is not an 11ax phymode 1136 */ 1137 static WMI_HOST_WLAN_PHY_MODE 1138 wma_host_to_fw_phymode_11ax(enum wlan_phymode host_phymode) 1139 { 1140 switch (host_phymode) { 1141 case WLAN_PHYMODE_11AXA_HE20: 1142 return WMI_HOST_MODE_11AX_HE20; 1143 case WLAN_PHYMODE_11AXA_HE40: 1144 return WMI_HOST_MODE_11AX_HE40; 1145 case WLAN_PHYMODE_11AXA_HE80: 1146 return WMI_HOST_MODE_11AX_HE80; 1147 case WLAN_PHYMODE_11AXA_HE80_80: 1148 return WMI_HOST_MODE_11AX_HE80_80; 1149 case WLAN_PHYMODE_11AXA_HE160: 1150 return WMI_HOST_MODE_11AX_HE160; 1151 case WLAN_PHYMODE_11AXG_HE20: 1152 return WMI_HOST_MODE_11AX_HE20_2G; 1153 case WLAN_PHYMODE_11AXG_HE40: 1154 case WLAN_PHYMODE_11AXG_HE40PLUS: 1155 case WLAN_PHYMODE_11AXG_HE40MINUS: 1156 return WMI_HOST_MODE_11AX_HE40_2G; 1157 case WLAN_PHYMODE_11AXG_HE80: 1158 return WMI_HOST_MODE_11AX_HE80_2G; 1159 default: 1160 return WMI_HOST_MODE_UNKNOWN; 1161 } 1162 } 1163 #else 1164 static WMI_HOST_WLAN_PHY_MODE 1165 wma_host_to_fw_phymode_11ax(enum wlan_phymode host_phymode) 1166 { 1167 return WMI_HOST_MODE_UNKNOWN; 1168 } 1169 #endif 1170 1171 #ifdef WLAN_FEATURE_11BE 1172 /** 1173 * wma_host_to_fw_phymode_11be() - convert host to fw phymode for 11be phymode 1174 * @host_phymode: phymode to convert 1175 * 1176 * Return: one of the 11be values defined in enum WMI_HOST_WLAN_PHY_MODE; 1177 * or WMI_HOST_MODE_UNKNOWN if the input is not an 11be phymode 1178 */ 1179 static WMI_HOST_WLAN_PHY_MODE 1180 wma_host_to_fw_phymode_11be(enum wlan_phymode host_phymode) 1181 { 1182 switch (host_phymode) { 1183 case WLAN_PHYMODE_11BEA_EHT20: 1184 return WMI_HOST_MODE_11BE_EHT20; 1185 case WLAN_PHYMODE_11BEA_EHT40: 1186 return WMI_HOST_MODE_11BE_EHT40; 1187 case WLAN_PHYMODE_11BEA_EHT80: 1188 return WMI_HOST_MODE_11BE_EHT80; 1189 case WLAN_PHYMODE_11BEA_EHT160: 1190 return WMI_HOST_MODE_11BE_EHT160; 1191 case WLAN_PHYMODE_11BEA_EHT320: 1192 return WMI_HOST_MODE_11BE_EHT320; 1193 case WLAN_PHYMODE_11BEG_EHT20: 1194 return WMI_HOST_MODE_11BE_EHT20_2G; 1195 case WLAN_PHYMODE_11BEG_EHT40: 1196 case WLAN_PHYMODE_11BEG_EHT40PLUS: 1197 case WLAN_PHYMODE_11BEG_EHT40MINUS: 1198 return WMI_HOST_MODE_11BE_EHT40_2G; 1199 default: 1200 return WMI_HOST_MODE_UNKNOWN; 1201 } 1202 } 1203 #else 1204 static WMI_HOST_WLAN_PHY_MODE 1205 wma_host_to_fw_phymode_11be(enum wlan_phymode host_phymode) 1206 { 1207 return WMI_HOST_MODE_UNKNOWN; 1208 } 1209 #endif 1210 1211 WMI_HOST_WLAN_PHY_MODE wma_host_to_fw_phymode(enum wlan_phymode host_phymode) 1212 { 1213 WMI_HOST_WLAN_PHY_MODE fw_phymode; 1214 1215 switch (host_phymode) { 1216 case WLAN_PHYMODE_11A: 1217 return WMI_HOST_MODE_11A; 1218 case WLAN_PHYMODE_11G: 1219 return WMI_HOST_MODE_11G; 1220 case WLAN_PHYMODE_11B: 1221 return WMI_HOST_MODE_11B; 1222 case WLAN_PHYMODE_11G_ONLY: 1223 return WMI_HOST_MODE_11GONLY; 1224 case WLAN_PHYMODE_11NA_HT20: 1225 return WMI_HOST_MODE_11NA_HT20; 1226 case WLAN_PHYMODE_11NG_HT20: 1227 return WMI_HOST_MODE_11NG_HT20; 1228 case WLAN_PHYMODE_11NA_HT40: 1229 return WMI_HOST_MODE_11NA_HT40; 1230 case WLAN_PHYMODE_11NG_HT40: 1231 case WLAN_PHYMODE_11NG_HT40PLUS: 1232 case WLAN_PHYMODE_11NG_HT40MINUS: 1233 return WMI_HOST_MODE_11NG_HT40; 1234 case WLAN_PHYMODE_11AC_VHT20: 1235 return WMI_HOST_MODE_11AC_VHT20; 1236 case WLAN_PHYMODE_11AC_VHT40: 1237 return WMI_HOST_MODE_11AC_VHT40; 1238 case WLAN_PHYMODE_11AC_VHT80: 1239 return WMI_HOST_MODE_11AC_VHT80; 1240 case WLAN_PHYMODE_11AC_VHT20_2G: 1241 return WMI_HOST_MODE_11AC_VHT20_2G; 1242 case WLAN_PHYMODE_11AC_VHT40PLUS_2G: 1243 case WLAN_PHYMODE_11AC_VHT40MINUS_2G: 1244 case WLAN_PHYMODE_11AC_VHT40_2G: 1245 return WMI_HOST_MODE_11AC_VHT40_2G; 1246 case WLAN_PHYMODE_11AC_VHT80_2G: 1247 return WMI_HOST_MODE_11AC_VHT80_2G; 1248 default: 1249 fw_phymode = wma_host_to_fw_phymode_160(host_phymode); 1250 if (fw_phymode != WMI_HOST_MODE_UNKNOWN) 1251 return fw_phymode; 1252 fw_phymode = wma_host_to_fw_phymode_11ax(host_phymode); 1253 if (fw_phymode != WMI_HOST_MODE_UNKNOWN) 1254 return fw_phymode; 1255 return wma_host_to_fw_phymode_11be(host_phymode); 1256 } 1257 } 1258 1259 void wma_objmgr_set_peer_mlme_phymode(tp_wma_handle wma, uint8_t *mac_addr, 1260 enum wlan_phymode phymode) 1261 { 1262 uint8_t pdev_id; 1263 struct wlan_objmgr_peer *peer; 1264 struct wlan_objmgr_psoc *psoc = wma->psoc; 1265 1266 pdev_id = wlan_objmgr_pdev_get_pdev_id(wma->pdev); 1267 peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr, 1268 WLAN_LEGACY_WMA_ID); 1269 if (!peer) 1270 return; 1271 1272 wlan_peer_obj_lock(peer); 1273 wlan_peer_set_phymode(peer, phymode); 1274 wlan_peer_obj_unlock(peer); 1275 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID); 1276 } 1277 1278 /** 1279 * wma_objmgr_set_peer_mlme_type() - set peer type to peer object 1280 * @wma: wma handle 1281 * @mac_addr: mac addr of peer 1282 * @peer_type: peer type value to set 1283 * 1284 * Return: None 1285 */ 1286 static void wma_objmgr_set_peer_mlme_type(tp_wma_handle wma, 1287 uint8_t *mac_addr, 1288 enum wlan_peer_type peer_type) 1289 { 1290 uint8_t pdev_id; 1291 struct wlan_objmgr_peer *peer; 1292 struct wlan_objmgr_psoc *psoc = wma->psoc; 1293 1294 pdev_id = wlan_objmgr_pdev_get_pdev_id(wma->pdev); 1295 peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr, 1296 WLAN_LEGACY_WMA_ID); 1297 if (!peer) 1298 return; 1299 1300 wlan_peer_obj_lock(peer); 1301 wlan_peer_set_peer_type(peer, peer_type); 1302 wlan_peer_obj_unlock(peer); 1303 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID); 1304 } 1305 1306 /** 1307 * wmi_unified_send_peer_assoc() - send peer assoc command to fw 1308 * @wma: wma handle 1309 * @nw_type: nw type 1310 * @params: add sta params 1311 * 1312 * This function send peer assoc command to firmware with 1313 * different parameters. 1314 * 1315 * Return: QDF_STATUS 1316 */ 1317 QDF_STATUS wma_send_peer_assoc(tp_wma_handle wma, 1318 tSirNwType nw_type, 1319 tpAddStaParams params) 1320 { 1321 struct peer_assoc_params *cmd; 1322 int32_t ret, max_rates, i; 1323 uint8_t *rate_pos; 1324 wmi_rate_set peer_legacy_rates, peer_ht_rates; 1325 uint32_t num_peer_11b_rates = 0; 1326 uint32_t num_peer_11a_rates = 0; 1327 enum wlan_phymode phymode, vdev_phymode; 1328 uint32_t peer_nss = 1; 1329 struct wma_txrx_node *intr = NULL; 1330 bool is_he; 1331 bool is_eht; 1332 QDF_STATUS status; 1333 struct mac_context *mac = wma->mac_context; 1334 struct wlan_channel *des_chan; 1335 int32_t keymgmt, uccipher, authmode; 1336 1337 cmd = qdf_mem_malloc(sizeof(struct peer_assoc_params)); 1338 if (!cmd) { 1339 wma_err("Failed to allocate peer_assoc_params param"); 1340 return QDF_STATUS_E_NOMEM; 1341 } 1342 1343 intr = &wma->interfaces[params->smesessionId]; 1344 1345 wma_mask_tx_ht_rate(wma, params->supportedRates.supportedMCSSet); 1346 1347 qdf_mem_zero(&peer_legacy_rates, sizeof(wmi_rate_set)); 1348 qdf_mem_zero(&peer_ht_rates, sizeof(wmi_rate_set)); 1349 qdf_mem_zero(cmd, sizeof(struct peer_assoc_params)); 1350 1351 is_he = wma_is_peer_he_capable(params); 1352 is_eht = wma_is_peer_eht_capable(params); 1353 if ((params->ch_width > CH_WIDTH_40MHZ) && 1354 ((nw_type == eSIR_11G_NW_TYPE) || 1355 (nw_type == eSIR_11B_NW_TYPE))) { 1356 wma_err("ch_width %d sent in 11G, configure to 40MHz", 1357 params->ch_width); 1358 params->ch_width = CH_WIDTH_40MHZ; 1359 } 1360 phymode = wma_peer_phymode(nw_type, params->staType, 1361 params->htCapable, params->ch_width, 1362 params->vhtCapable, is_he, is_eht); 1363 1364 des_chan = wlan_vdev_mlme_get_des_chan(intr->vdev); 1365 vdev_phymode = des_chan->ch_phymode; 1366 if ((intr->type == WMI_VDEV_TYPE_AP) && (phymode > vdev_phymode)) { 1367 wma_nofl_debug("Peer phymode %d is not allowed. Set it equal to sap/go phymode %d", 1368 phymode, vdev_phymode); 1369 phymode = vdev_phymode; 1370 } 1371 1372 if (!mac->mlme_cfg->rates.disable_abg_rate_txdata) { 1373 /* Legacy Rateset */ 1374 rate_pos = (uint8_t *) peer_legacy_rates.rates; 1375 for (i = 0; i < SIR_NUM_11B_RATES; i++) { 1376 if (!params->supportedRates.llbRates[i]) 1377 continue; 1378 rate_pos[peer_legacy_rates.num_rates++] = 1379 params->supportedRates.llbRates[i]; 1380 num_peer_11b_rates++; 1381 } 1382 for (i = 0; i < SIR_NUM_11A_RATES; i++) { 1383 if (!params->supportedRates.llaRates[i]) 1384 continue; 1385 rate_pos[peer_legacy_rates.num_rates++] = 1386 params->supportedRates.llaRates[i]; 1387 num_peer_11a_rates++; 1388 } 1389 } 1390 1391 if ((phymode == WLAN_PHYMODE_11A && num_peer_11a_rates == 0) || 1392 (phymode == WLAN_PHYMODE_11B && num_peer_11b_rates == 0)) { 1393 wma_warn("Invalid phy rates. phymode 0x%x, 11b_rates %d, 11a_rates %d", 1394 phymode, num_peer_11b_rates, 1395 num_peer_11a_rates); 1396 qdf_mem_free(cmd); 1397 return QDF_STATUS_E_INVAL; 1398 } 1399 1400 /* HT Rateset */ 1401 max_rates = sizeof(peer_ht_rates.rates) / 1402 sizeof(peer_ht_rates.rates[0]); 1403 rate_pos = (uint8_t *) peer_ht_rates.rates; 1404 for (i = 0; i < MAX_SUPPORTED_RATES; i++) { 1405 if (params->supportedRates.supportedMCSSet[i / 8] & 1406 (1 << (i % 8))) { 1407 rate_pos[peer_ht_rates.num_rates++] = i; 1408 if (i >= 8) { 1409 /* MCS8 or higher rate is present, must be 2x2 */ 1410 peer_nss = 2; 1411 } 1412 } 1413 if (peer_ht_rates.num_rates == max_rates) 1414 break; 1415 } 1416 1417 if (params->htCapable && !peer_ht_rates.num_rates) { 1418 uint8_t temp_ni_rates[8] = { 0x0, 0x1, 0x2, 0x3, 1419 0x4, 0x5, 0x6, 0x7}; 1420 /* 1421 * Workaround for EV 116382: The peer is marked HT but with 1422 * supported rx mcs set is set to 0. 11n spec mandates MCS0-7 1423 * for a HT STA. So forcing the supported rx mcs rate to 1424 * MCS 0-7. This workaround will be removed once we get 1425 * clarification from WFA regarding this STA behavior. 1426 */ 1427 1428 /* TODO: Do we really need this? */ 1429 wma_warn("Peer is marked as HT capable but supported mcs rate is 0"); 1430 peer_ht_rates.num_rates = sizeof(temp_ni_rates); 1431 qdf_mem_copy((uint8_t *) peer_ht_rates.rates, temp_ni_rates, 1432 peer_ht_rates.num_rates); 1433 } 1434 1435 /* in ap mode and for tdls peer, use mac address of the peer in 1436 * the other end as the new peer address; in sta mode, use bss id to 1437 * be the new peer address 1438 */ 1439 if ((wma_is_vdev_in_ap_mode(wma, params->smesessionId)) 1440 #ifdef FEATURE_WLAN_TDLS 1441 || (STA_ENTRY_TDLS_PEER == params->staType) 1442 #endif /* FEATURE_WLAN_TDLS */ 1443 ) { 1444 qdf_mem_copy(cmd->peer_mac, params->staMac, 1445 sizeof(cmd->peer_mac)); 1446 } else { 1447 qdf_mem_copy(cmd->peer_mac, params->bssId, 1448 sizeof(cmd->peer_mac)); 1449 } 1450 wma_objmgr_set_peer_mlme_phymode(wma, cmd->peer_mac, phymode); 1451 1452 cmd->vdev_id = params->smesessionId; 1453 cmd->peer_new_assoc = 1; 1454 cmd->peer_associd = params->assocId; 1455 1456 cmd->is_wme_set = 1; 1457 1458 if (params->wmmEnabled) 1459 cmd->qos_flag = 1; 1460 1461 if (params->uAPSD) { 1462 cmd->apsd_flag = 1; 1463 wma_nofl_debug("Set WMI_PEER_APSD: uapsd Mask %d", 1464 params->uAPSD); 1465 } 1466 1467 if (params->htCapable) { 1468 cmd->ht_flag = 1; 1469 cmd->qos_flag = 1; 1470 cmd->peer_rate_caps |= WMI_RC_HT_FLAG; 1471 } 1472 1473 if (params->vhtCapable) { 1474 cmd->ht_flag = 1; 1475 cmd->qos_flag = 1; 1476 cmd->vht_flag = 1; 1477 cmd->peer_rate_caps |= WMI_RC_HT_FLAG; 1478 } 1479 1480 if (params->ch_width) { 1481 cmd->bw_40 = 1; 1482 cmd->peer_rate_caps |= WMI_RC_CW40_FLAG; 1483 if (params->fShortGI40Mhz) 1484 cmd->peer_rate_caps |= WMI_RC_SGI_FLAG; 1485 } else if (params->fShortGI20Mhz) { 1486 cmd->peer_rate_caps |= WMI_RC_SGI_FLAG; 1487 } 1488 1489 if (params->ch_width == CH_WIDTH_80MHZ) 1490 cmd->bw_80 = 1; 1491 else if (params->ch_width == CH_WIDTH_160MHZ) 1492 cmd->bw_160 = 1; 1493 else if (params->ch_width == CH_WIDTH_80P80MHZ) 1494 cmd->bw_160 = 1; 1495 1496 wma_set_peer_assoc_params_bw_320(cmd, params->ch_width); 1497 1498 cmd->peer_vht_caps = params->vht_caps; 1499 if (params->p2pCapableSta) { 1500 cmd->p2p_capable_sta = 1; 1501 wma_objmgr_set_peer_mlme_type(wma, params->staMac, 1502 WLAN_PEER_P2P_CLI); 1503 } 1504 1505 if (params->rmfEnabled) 1506 cmd->is_pmf_enabled = 1; 1507 1508 if (params->stbc_capable) 1509 cmd->stbc_flag = 1; 1510 1511 if (params->htLdpcCapable || params->vhtLdpcCapable) 1512 cmd->ldpc_flag = 1; 1513 1514 switch (params->mimoPS) { 1515 case eSIR_HT_MIMO_PS_STATIC: 1516 cmd->static_mimops_flag = 1; 1517 break; 1518 case eSIR_HT_MIMO_PS_DYNAMIC: 1519 cmd->dynamic_mimops_flag = 1; 1520 break; 1521 case eSIR_HT_MIMO_PS_NO_LIMIT: 1522 cmd->spatial_mux_flag = 1; 1523 break; 1524 default: 1525 break; 1526 } 1527 1528 wma_set_twt_peer_caps(params, cmd); 1529 #ifdef FEATURE_WLAN_TDLS 1530 if (STA_ENTRY_TDLS_PEER == params->staType) 1531 cmd->auth_flag = 1; 1532 #endif /* FEATURE_WLAN_TDLS */ 1533 1534 if (params->wpa_rsn 1535 #ifdef FEATURE_WLAN_WAPI 1536 || params->encryptType == eSIR_ED_WPI 1537 #endif /* FEATURE_WLAN_WAPI */ 1538 ) { 1539 if (!params->no_ptk_4_way) 1540 cmd->need_ptk_4_way = 1; 1541 wma_nofl_debug("Acquire set key wake lock for %d ms", 1542 WMA_VDEV_SET_KEY_WAKELOCK_TIMEOUT); 1543 wma_acquire_wakelock(&intr->vdev_set_key_wakelock, 1544 WMA_VDEV_SET_KEY_WAKELOCK_TIMEOUT); 1545 qdf_runtime_pm_prevent_suspend( 1546 &intr->vdev_set_key_runtime_wakelock); 1547 } 1548 if (params->wpa_rsn >> 1) 1549 cmd->need_gtk_2_way = 1; 1550 1551 #ifdef FEATURE_WLAN_WAPI 1552 if (params->encryptType == eSIR_ED_WPI) { 1553 ret = wma_vdev_set_param(wma->wmi_handle, params->smesessionId, 1554 WMI_VDEV_PARAM_DROP_UNENCRY, false); 1555 if (ret) { 1556 wma_err("Set WMI_VDEV_PARAM_DROP_UNENCRY Param status:%d", 1557 ret); 1558 qdf_mem_free(cmd); 1559 return ret; 1560 } 1561 } 1562 #endif /* FEATURE_WLAN_WAPI */ 1563 1564 cmd->peer_caps = params->capab_info; 1565 cmd->peer_listen_intval = params->listenInterval; 1566 cmd->peer_ht_caps = params->ht_caps; 1567 cmd->peer_max_mpdu = (1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + 1568 params->maxAmpduSize)) - 1; 1569 cmd->peer_mpdu_density = wma_parse_mpdudensity(params->maxAmpduDensity); 1570 1571 if (params->supportedRates.supportedMCSSet[1] && 1572 params->supportedRates.supportedMCSSet[2]) 1573 cmd->peer_rate_caps |= WMI_RC_TS_FLAG; 1574 else if (params->supportedRates.supportedMCSSet[1]) 1575 cmd->peer_rate_caps |= WMI_RC_DS_FLAG; 1576 1577 /* Update peer legacy rate information */ 1578 cmd->peer_legacy_rates.num_rates = peer_legacy_rates.num_rates; 1579 qdf_mem_copy(cmd->peer_legacy_rates.rates, peer_legacy_rates.rates, 1580 peer_legacy_rates.num_rates); 1581 1582 /* Update peer HT rate information */ 1583 cmd->peer_ht_rates.num_rates = peer_ht_rates.num_rates; 1584 qdf_mem_copy(cmd->peer_ht_rates.rates, peer_ht_rates.rates, 1585 peer_ht_rates.num_rates); 1586 1587 /* VHT Rates */ 1588 1589 cmd->peer_nss = peer_nss; 1590 /* 1591 * Because of DBS a vdev may come up in any of the two MACs with 1592 * different capabilities. STBC capab should be fetched for given 1593 * hard_mode->MAC_id combo. It is planned that firmware should provide 1594 * these dev capabilities. But for now number of tx streams can be used 1595 * to identify if Tx STBC needs to be disabled. 1596 */ 1597 if (intr->tx_streams < 2) { 1598 cmd->peer_vht_caps &= ~(1 << SIR_MAC_VHT_CAP_TXSTBC); 1599 wma_nofl_debug("Num tx_streams: %d, Disabled txSTBC", 1600 intr->tx_streams); 1601 } 1602 1603 cmd->vht_capable = params->vhtCapable; 1604 if (params->vhtCapable) { 1605 #define VHT2x2MCSMASK 0xc 1606 cmd->rx_max_rate = params->supportedRates.vhtRxHighestDataRate; 1607 cmd->rx_mcs_set = params->supportedRates.vhtRxMCSMap; 1608 cmd->tx_max_rate = params->supportedRates.vhtTxHighestDataRate; 1609 cmd->tx_mcs_set = params->supportedRates.vhtTxMCSMap; 1610 /* 1611 * tx_mcs_set is intersection of self tx NSS and peer rx mcs map 1612 */ 1613 if (params->vhtSupportedRxNss) 1614 cmd->peer_nss = params->vhtSupportedRxNss; 1615 else 1616 cmd->peer_nss = ((cmd->tx_mcs_set & VHT2x2MCSMASK) 1617 == VHT2x2MCSMASK) ? 1 : 2; 1618 1619 if (params->vht_mcs_10_11_supp) { 1620 WMI_SET_BITS(cmd->tx_mcs_set, 16, cmd->peer_nss, 1621 ((1 << cmd->peer_nss) - 1)); 1622 WMI_VHT_MCS_NOTIFY_EXT_SS_SET(cmd->tx_mcs_set, 1); 1623 } 1624 if (params->vht_extended_nss_bw_cap && 1625 (params->vht_160mhz_nss || params->vht_80p80mhz_nss)) { 1626 /* 1627 * bit[2:0] : Represents value of Rx NSS for 160 MHz 1628 * bit[5:3] : Represents value of Rx NSS for 80_80 MHz 1629 * Extended NSS support 1630 * bit[30:6]: Reserved 1631 * bit[31] : MSB(0/1): 1 in case of valid data 1632 */ 1633 cmd->peer_bw_rxnss_override |= (1 << 31); 1634 if (params->vht_160mhz_nss) 1635 cmd->peer_bw_rxnss_override |= 1636 (params->vht_160mhz_nss - 1); 1637 if (params->vht_80p80mhz_nss) 1638 cmd->peer_bw_rxnss_override |= 1639 ((params->vht_80p80mhz_nss - 1) << 3); 1640 wma_debug("peer_bw_rxnss_override %0X", 1641 cmd->peer_bw_rxnss_override); 1642 } 1643 } 1644 1645 wma_debug("rx_max_rate %d, rx_mcs %x, tx_max_rate %d, tx_mcs: %x num rates %d need 4 way %d", 1646 cmd->rx_max_rate, cmd->rx_mcs_set, cmd->tx_max_rate, 1647 cmd->tx_mcs_set, peer_ht_rates.num_rates, 1648 cmd->need_ptk_4_way); 1649 1650 /* 1651 * Limit nss to max number of rf chain supported by target 1652 * Otherwise Fw will crash 1653 */ 1654 if (cmd->peer_nss > WMA_MAX_NSS) { 1655 wma_err("peer Nss %d is more than supported", cmd->peer_nss); 1656 cmd->peer_nss = WMA_MAX_NSS; 1657 } 1658 1659 wma_populate_peer_he_cap(cmd, params); 1660 wma_populate_peer_eht_cap(cmd, params); 1661 if (!wma_is_vdev_in_ap_mode(wma, params->smesessionId)) 1662 intr->nss = cmd->peer_nss; 1663 1664 /* Till conversion is not done in WMI we need to fill fw phy mode */ 1665 cmd->peer_phymode = wma_host_to_fw_phymode(phymode); 1666 1667 keymgmt = wlan_crypto_get_param(intr->vdev, WLAN_CRYPTO_PARAM_KEY_MGMT); 1668 authmode = wlan_crypto_get_param(intr->vdev, 1669 WLAN_CRYPTO_PARAM_AUTH_MODE); 1670 uccipher = wlan_crypto_get_param(intr->vdev, 1671 WLAN_CRYPTO_PARAM_UCAST_CIPHER); 1672 1673 cmd->akm = cm_crypto_authmode_to_wmi_authmode(authmode, 1674 keymgmt, 1675 uccipher); 1676 1677 status = wmi_unified_peer_assoc_send(wma->wmi_handle, 1678 cmd); 1679 if (QDF_IS_STATUS_ERROR(status)) 1680 wma_alert("Failed to send peer assoc command status = %d", 1681 status); 1682 qdf_mem_free(cmd); 1683 1684 return status; 1685 } 1686 1687 /** 1688 * wmi_unified_vdev_set_gtx_cfg_send() - set GTX params 1689 * @wmi_handle: wmi handle 1690 * @if_id: vdev id 1691 * @gtx_info: GTX config params 1692 * 1693 * This function set GTX related params in firmware. 1694 * 1695 * Return: 0 for success or error code 1696 */ 1697 QDF_STATUS wmi_unified_vdev_set_gtx_cfg_send(wmi_unified_t wmi_handle, 1698 uint32_t if_id, 1699 gtx_config_t *gtx_info) 1700 { 1701 struct wmi_gtx_config params; 1702 1703 params.gtx_rt_mask[0] = gtx_info->gtxRTMask[0]; 1704 params.gtx_rt_mask[1] = gtx_info->gtxRTMask[1]; 1705 params.gtx_usrcfg = gtx_info->gtxUsrcfg; 1706 params.gtx_threshold = gtx_info->gtxPERThreshold; 1707 params.gtx_margin = gtx_info->gtxPERMargin; 1708 params.gtx_tpcstep = gtx_info->gtxTPCstep; 1709 params.gtx_tpcmin = gtx_info->gtxTPCMin; 1710 params.gtx_bwmask = gtx_info->gtxBWMask; 1711 1712 return wmi_unified_vdev_set_gtx_cfg_cmd(wmi_handle, 1713 if_id, ¶ms); 1714 1715 } 1716 1717 /** 1718 * wma_update_protection_mode() - update protection mode 1719 * @wma: wma handle 1720 * @vdev_id: vdev id 1721 * @llbcoexist: protection mode info 1722 * 1723 * This function set protection mode(RTS/CTS) to fw for passed vdev id. 1724 * 1725 * Return: none 1726 */ 1727 void wma_update_protection_mode(tp_wma_handle wma, uint8_t vdev_id, 1728 uint8_t llbcoexist) 1729 { 1730 QDF_STATUS ret; 1731 enum ieee80211_protmode prot_mode; 1732 1733 prot_mode = llbcoexist ? IEEE80211_PROT_CTSONLY : IEEE80211_PROT_NONE; 1734 1735 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id, 1736 WMI_VDEV_PARAM_PROTECTION_MODE, 1737 prot_mode); 1738 1739 if (QDF_IS_STATUS_ERROR(ret)) 1740 wma_err("Failed to send wmi protection mode cmd"); 1741 else 1742 wma_nofl_debug("Updated protection mode %d to target", 1743 prot_mode); 1744 } 1745 1746 void 1747 wma_update_beacon_interval(tp_wma_handle wma, uint8_t vdev_id, 1748 uint16_t beaconInterval) 1749 { 1750 QDF_STATUS ret; 1751 1752 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id, 1753 WMI_VDEV_PARAM_BEACON_INTERVAL, 1754 beaconInterval); 1755 1756 if (QDF_IS_STATUS_ERROR(ret)) 1757 wma_err("Failed to update beacon interval"); 1758 else 1759 wma_info("Updated beacon interval %d for vdev %d", 1760 beaconInterval, vdev_id); 1761 } 1762 1763 #ifdef WLAN_FEATURE_11AX_BSS_COLOR 1764 /** 1765 * wma_update_bss_color() - update beacon bss color in fw 1766 * @wma: wma handle 1767 * @vdev_id: vdev id 1768 * @he_ops: HE operation, only the bss_color and bss_color_disabled fields 1769 * are updated. 1770 * 1771 * Return: none 1772 */ 1773 static void 1774 wma_update_bss_color(tp_wma_handle wma, uint8_t vdev_id, 1775 tUpdateBeaconParams *bcn_params) 1776 { 1777 QDF_STATUS ret; 1778 uint32_t dword_he_ops = 0; 1779 1780 WMI_HEOPS_COLOR_SET(dword_he_ops, bcn_params->bss_color); 1781 WMI_HEOPS_BSSCOLORDISABLE_SET(dword_he_ops, 1782 bcn_params->bss_color_disabled); 1783 wma_nofl_debug("vdev: %d, update bss color, HE_OPS: 0x%x", 1784 vdev_id, dword_he_ops); 1785 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id, 1786 WMI_VDEV_PARAM_BSS_COLOR, dword_he_ops); 1787 if (QDF_IS_STATUS_ERROR(ret)) 1788 wma_err("Failed to update HE operations"); 1789 } 1790 #else 1791 static void wma_update_bss_color(tp_wma_handle wma, uint8_t vdev_id, 1792 tUpdateBeaconParams *bcn_params) 1793 { 1794 } 1795 #endif 1796 1797 /** 1798 * wma_process_update_beacon_params() - update beacon parameters to target 1799 * @wma: wma handle 1800 * @bcn_params: beacon parameters 1801 * 1802 * Return: none 1803 */ 1804 void 1805 wma_process_update_beacon_params(tp_wma_handle wma, 1806 tUpdateBeaconParams *bcn_params) 1807 { 1808 if (!bcn_params) { 1809 wma_err("bcn_params NULL"); 1810 return; 1811 } 1812 1813 if (bcn_params->vdev_id >= wma->max_bssid) { 1814 wma_err("Invalid vdev id %d", bcn_params->vdev_id); 1815 return; 1816 } 1817 1818 if (bcn_params->paramChangeBitmap & PARAM_BCN_INTERVAL_CHANGED) { 1819 wma_update_beacon_interval(wma, bcn_params->vdev_id, 1820 bcn_params->beaconInterval); 1821 } 1822 1823 if (bcn_params->paramChangeBitmap & PARAM_llBCOEXIST_CHANGED) 1824 wma_update_protection_mode(wma, bcn_params->vdev_id, 1825 bcn_params->llbCoexist); 1826 1827 if (bcn_params->paramChangeBitmap & PARAM_BSS_COLOR_CHANGED) 1828 wma_update_bss_color(wma, bcn_params->vdev_id, 1829 bcn_params); 1830 } 1831 1832 void wma_update_rts_params(tp_wma_handle wma, uint32_t value) 1833 { 1834 uint8_t vdev_id; 1835 QDF_STATUS ret; 1836 struct wlan_objmgr_vdev *vdev; 1837 1838 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) { 1839 vdev = wma->interfaces[vdev_id].vdev; 1840 if (!vdev) 1841 continue; 1842 ret = wma_vdev_set_param(wma->wmi_handle, 1843 vdev_id, 1844 WMI_VDEV_PARAM_RTS_THRESHOLD, 1845 value); 1846 if (QDF_IS_STATUS_ERROR(ret)) 1847 wma_err("Update cfg param fail for vdevId %d", vdev_id); 1848 } 1849 } 1850 1851 void wma_update_frag_params(tp_wma_handle wma, uint32_t value) 1852 { 1853 uint8_t vdev_id; 1854 QDF_STATUS ret; 1855 struct wlan_objmgr_vdev *vdev; 1856 1857 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) { 1858 vdev = wma->interfaces[vdev_id].vdev; 1859 if (!vdev) 1860 continue; 1861 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id, 1862 WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD, 1863 value); 1864 if (QDF_IS_STATUS_ERROR(ret)) 1865 wma_err("Update cfg params failed for vdevId %d", 1866 vdev_id); 1867 } 1868 } 1869 1870 #ifdef FEATURE_WLAN_WAPI 1871 #define WPI_IV_LEN 16 1872 #if defined(CONFIG_LITHIUM) || defined(CONFIG_BERYLLIUM) 1873 /** 1874 * wma_fill_in_wapi_key_params() - update key parameters about wapi 1875 * @key_params: wma key parameters 1876 * @params: parameters pointer to be set 1877 * @mode: operation mode 1878 * 1879 * Return: None 1880 */ 1881 static inline void wma_fill_in_wapi_key_params( 1882 struct wma_set_key_params *key_params, 1883 struct set_key_params *params, uint8_t mode) 1884 { 1885 /* 1886 * Since MCL shares same FW with WIN for Napier/Hasting, FW WAPI logic 1887 * is fit for WIN, change it to align with WIN. 1888 */ 1889 unsigned char iv_init_ap[16] = { 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 1890 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 1891 0x5c, 0x36, 0x5c, 0x37}; 1892 unsigned char iv_init_sta[16] = { 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 1893 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 1894 0x5c, 0x36, 0x5c, 0x36}; 1895 1896 if (mode == wlan_op_mode_ap) { 1897 qdf_mem_copy(params->rx_iv, iv_init_sta, 1898 WPI_IV_LEN); 1899 qdf_mem_copy(params->tx_iv, iv_init_ap, 1900 WPI_IV_LEN); 1901 } else { 1902 qdf_mem_copy(params->rx_iv, iv_init_ap, 1903 WPI_IV_LEN); 1904 qdf_mem_copy(params->tx_iv, iv_init_sta, 1905 WPI_IV_LEN); 1906 } 1907 1908 params->key_txmic_len = WMA_TXMIC_LEN; 1909 params->key_rxmic_len = WMA_RXMIC_LEN; 1910 1911 params->key_cipher = WMI_CIPHER_WAPI; 1912 } 1913 #else 1914 static inline void wma_fill_in_wapi_key_params( 1915 struct wma_set_key_params *key_params, 1916 struct set_key_params *params, uint8_t mode) 1917 { 1918 /*initialize receive and transmit IV with default values */ 1919 /* **Note: tx_iv must be sent in reverse** */ 1920 unsigned char tx_iv[16] = { 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 1921 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 1922 0x36, 0x5c, 0x36, 0x5c}; 1923 unsigned char rx_iv[16] = { 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 1924 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 1925 0x5c, 0x36, 0x5c, 0x37}; 1926 if (mode == wlan_op_mode_ap) { 1927 /* Authenticator initializes the value of PN as 1928 * 0x5C365C365C365C365C365C365C365C36 for MCastkeyUpdate 1929 */ 1930 if (key_params->unicast) 1931 tx_iv[0] = 0x37; 1932 1933 rx_iv[WPI_IV_LEN - 1] = 0x36; 1934 } else { 1935 if (!key_params->unicast) 1936 rx_iv[WPI_IV_LEN - 1] = 0x36; 1937 } 1938 1939 params->key_txmic_len = WMA_TXMIC_LEN; 1940 params->key_rxmic_len = WMA_RXMIC_LEN; 1941 1942 qdf_mem_copy(params->rx_iv, &rx_iv, 1943 WPI_IV_LEN); 1944 qdf_mem_copy(params->tx_iv, &tx_iv, 1945 WPI_IV_LEN); 1946 params->key_cipher = WMI_CIPHER_WAPI; 1947 } 1948 #endif 1949 #endif 1950 1951 /** 1952 * wma_process_update_edca_param_req() - update EDCA params 1953 * @handle: wma handle 1954 * @edca_params: edca parameters 1955 * 1956 * This function updates EDCA parameters to the target 1957 * 1958 * Return: QDF Status 1959 */ 1960 QDF_STATUS wma_process_update_edca_param_req(WMA_HANDLE handle, 1961 tEdcaParams *edca_params) 1962 { 1963 tp_wma_handle wma_handle = (tp_wma_handle) handle; 1964 struct wmi_host_wme_vparams wmm_param[QCA_WLAN_AC_ALL]; 1965 tSirMacEdcaParamRecord *edca_record; 1966 int ac; 1967 struct ol_tx_wmm_param_t ol_tx_wmm_param; 1968 uint8_t vdev_id; 1969 QDF_STATUS status; 1970 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 1971 1972 vdev_id = edca_params->vdev_id; 1973 if (!wma_is_vdev_valid(vdev_id)) { 1974 wma_err("vdev id:%d is not active ", vdev_id); 1975 goto fail; 1976 } 1977 1978 for (ac = 0; ac < QCA_WLAN_AC_ALL; ac++) { 1979 switch (ac) { 1980 case QCA_WLAN_AC_BE: 1981 edca_record = &edca_params->acbe; 1982 break; 1983 case QCA_WLAN_AC_BK: 1984 edca_record = &edca_params->acbk; 1985 break; 1986 case QCA_WLAN_AC_VI: 1987 edca_record = &edca_params->acvi; 1988 break; 1989 case QCA_WLAN_AC_VO: 1990 edca_record = &edca_params->acvo; 1991 break; 1992 default: 1993 goto fail; 1994 } 1995 1996 wma_update_edca_params_for_ac(edca_record, &wmm_param[ac], ac, 1997 edca_params->mu_edca_params); 1998 1999 ol_tx_wmm_param.ac[ac].aifs = wmm_param[ac].aifs; 2000 ol_tx_wmm_param.ac[ac].cwmin = wmm_param[ac].cwmin; 2001 ol_tx_wmm_param.ac[ac].cwmax = wmm_param[ac].cwmax; 2002 } 2003 2004 status = wmi_unified_process_update_edca_param(wma_handle->wmi_handle, 2005 vdev_id, 2006 edca_params->mu_edca_params, 2007 wmm_param); 2008 if (status == QDF_STATUS_E_NOMEM) 2009 return status; 2010 else if (status == QDF_STATUS_E_FAILURE) 2011 goto fail; 2012 2013 cdp_set_wmm_param(soc, WMI_PDEV_ID_SOC, ol_tx_wmm_param); 2014 2015 return QDF_STATUS_SUCCESS; 2016 2017 fail: 2018 wma_err("Failed to set WMM Paremeters"); 2019 return QDF_STATUS_E_FAILURE; 2020 } 2021 2022 /** 2023 * wmi_unified_probe_rsp_tmpl_send() - send probe response template to fw 2024 * @wma: wma handle 2025 * @vdev_id: vdev id 2026 * @probe_rsp_info: probe response info 2027 * 2028 * Return: 0 for success or error code 2029 */ 2030 static int wmi_unified_probe_rsp_tmpl_send(tp_wma_handle wma, 2031 uint8_t vdev_id, 2032 tpSendProbeRespParams probe_rsp_info) 2033 { 2034 uint64_t adjusted_tsf_le; 2035 struct ieee80211_frame *wh; 2036 struct wmi_probe_resp_params params; 2037 2038 wma_debug("Send probe response template for vdev %d", vdev_id); 2039 2040 /* 2041 * Make the TSF offset negative so probe response in the same 2042 * staggered batch have the same TSF. 2043 */ 2044 adjusted_tsf_le = cpu_to_le64(0ULL - 2045 wma->interfaces[vdev_id].tsfadjust); 2046 /* Update the timstamp in the probe response buffer with adjusted TSF */ 2047 wh = (struct ieee80211_frame *)probe_rsp_info->probeRespTemplate; 2048 A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le)); 2049 2050 params.prb_rsp_template_len = probe_rsp_info->probeRespTemplateLen; 2051 params.prb_rsp_template_frm = probe_rsp_info->probeRespTemplate; 2052 2053 return wmi_unified_probe_rsp_tmpl_send_cmd(wma->wmi_handle, vdev_id, 2054 ¶ms); 2055 } 2056 2057 /** 2058 * wma_unified_bcn_tmpl_send() - send beacon template to fw 2059 * @wma:wma handle 2060 * @vdev_id: vdev id 2061 * @bcn_info: beacon info 2062 * @bytes_to_strip: bytes to strip 2063 * 2064 * Return: QDF_STATUS_SUCCESS for success or error code 2065 */ 2066 static QDF_STATUS wma_unified_bcn_tmpl_send(tp_wma_handle wma, 2067 uint8_t vdev_id, 2068 const tpSendbeaconParams bcn_info, 2069 uint8_t bytes_to_strip) 2070 { 2071 struct beacon_tmpl_params params = {0}; 2072 uint32_t tmpl_len, tmpl_len_aligned; 2073 uint8_t *frm; 2074 QDF_STATUS ret; 2075 uint8_t *p2p_ie; 2076 uint16_t p2p_ie_len = 0; 2077 uint64_t adjusted_tsf_le; 2078 struct ieee80211_frame *wh; 2079 2080 if (!wma_is_vdev_valid(vdev_id)) { 2081 wma_err("vdev id:%d is not active ", vdev_id); 2082 return QDF_STATUS_E_INVAL; 2083 } 2084 2085 wma_nofl_debug("Send beacon template for vdev %d", vdev_id); 2086 2087 if (bcn_info->p2pIeOffset) { 2088 p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset; 2089 p2p_ie_len = (uint16_t) p2p_ie[1] + 2; 2090 } 2091 2092 /* 2093 * XXX: The first byte of beacon buffer contains beacon length 2094 * only when UMAC in sending the beacon template. In othercases 2095 * (ex: from tbtt update) beacon length is read from beacon 2096 * information. 2097 */ 2098 if (bytes_to_strip) 2099 tmpl_len = *(uint32_t *) &bcn_info->beacon[0]; 2100 else 2101 tmpl_len = bcn_info->beaconLength; 2102 2103 if (tmpl_len > WMI_BEACON_TX_BUFFER_SIZE) { 2104 wma_err("tmpl_len: %d > %d. Invalid tmpl len", tmpl_len, 2105 WMI_BEACON_TX_BUFFER_SIZE); 2106 return -EINVAL; 2107 } 2108 2109 if (p2p_ie_len) { 2110 if (tmpl_len <= p2p_ie_len) { 2111 wma_err("tmpl_len %d <= p2p_ie_len %d, Invalid", 2112 tmpl_len, p2p_ie_len); 2113 return -EINVAL; 2114 } 2115 tmpl_len -= (uint32_t) p2p_ie_len; 2116 } 2117 2118 frm = bcn_info->beacon + bytes_to_strip; 2119 tmpl_len_aligned = roundup(tmpl_len, sizeof(A_UINT32)); 2120 /* 2121 * Make the TSF offset negative so beacons in the same 2122 * staggered batch have the same TSF. 2123 */ 2124 adjusted_tsf_le = cpu_to_le64(0ULL - 2125 wma->interfaces[vdev_id].tsfadjust); 2126 /* Update the timstamp in the beacon buffer with adjusted TSF */ 2127 wh = (struct ieee80211_frame *)frm; 2128 A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le)); 2129 2130 2131 2132 params.vdev_id = vdev_id; 2133 params.tim_ie_offset = bcn_info->timIeOffset - bytes_to_strip; 2134 params.tmpl_len = tmpl_len; 2135 params.frm = frm; 2136 params.tmpl_len_aligned = tmpl_len_aligned; 2137 params.enable_bigtk = 2138 mlme_get_bigtk_support(wma->interfaces[vdev_id].vdev); 2139 if (bcn_info->csa_count_offset && 2140 (bcn_info->csa_count_offset > bytes_to_strip)) 2141 params.csa_switch_count_offset = 2142 bcn_info->csa_count_offset - bytes_to_strip; 2143 if (bcn_info->ecsa_count_offset && 2144 (bcn_info->ecsa_count_offset > bytes_to_strip)) 2145 params.ext_csa_switch_count_offset = 2146 bcn_info->ecsa_count_offset - bytes_to_strip; 2147 2148 ret = wmi_unified_beacon_tmpl_send_cmd(wma->wmi_handle, 2149 ¶ms); 2150 if (QDF_IS_STATUS_ERROR(ret)) 2151 wma_err("Failed to send bcn tmpl: %d", ret); 2152 2153 return ret; 2154 } 2155 2156 /** 2157 * wma_store_bcn_tmpl() - store beacon template 2158 * @wma: wma handle 2159 * @vdev_id: vdev id 2160 * @bcn_info: beacon params 2161 * 2162 * This function stores beacon template locally. 2163 * This will send to target on the reception of 2164 * SWBA event. 2165 * 2166 * Return: QDF status 2167 */ 2168 static QDF_STATUS wma_store_bcn_tmpl(tp_wma_handle wma, uint8_t vdev_id, 2169 tpSendbeaconParams bcn_info) 2170 { 2171 struct beacon_info *bcn; 2172 uint32_t len; 2173 uint8_t *bcn_payload; 2174 struct beacon_tim_ie *tim_ie; 2175 2176 bcn = wma->interfaces[vdev_id].beacon; 2177 if (!bcn || !bcn->buf) { 2178 wma_err("Memory is not allocated to hold bcn template"); 2179 return QDF_STATUS_E_INVAL; 2180 } 2181 2182 len = *(uint32_t *) &bcn_info->beacon[0]; 2183 if (len > SIR_MAX_BEACON_SIZE - sizeof(uint32_t)) { 2184 wma_err("Received beacon len %u exceeding max limit %lu", 2185 len, (unsigned long)( 2186 SIR_MAX_BEACON_SIZE - sizeof(uint32_t))); 2187 return QDF_STATUS_E_INVAL; 2188 } 2189 qdf_spin_lock_bh(&bcn->lock); 2190 2191 /* 2192 * Copy received beacon template content in local buffer. 2193 * this will be send to target on the reception of SWBA 2194 * event from target. 2195 */ 2196 qdf_nbuf_trim_tail(bcn->buf, qdf_nbuf_len(bcn->buf)); 2197 memcpy(qdf_nbuf_data(bcn->buf), 2198 bcn_info->beacon + 4 /* Exclude beacon length field */, 2199 len); 2200 if (bcn_info->timIeOffset > 3) 2201 bcn->tim_ie_offset = bcn_info->timIeOffset - 4; 2202 else 2203 bcn->tim_ie_offset = bcn_info->timIeOffset; 2204 2205 if (bcn_info->p2pIeOffset > 3) 2206 bcn->p2p_ie_offset = bcn_info->p2pIeOffset - 4; 2207 else 2208 bcn->p2p_ie_offset = bcn_info->p2pIeOffset; 2209 2210 bcn_payload = qdf_nbuf_data(bcn->buf); 2211 if (bcn->tim_ie_offset) { 2212 tim_ie = (struct beacon_tim_ie *) 2213 (&bcn_payload[bcn->tim_ie_offset]); 2214 /* 2215 * Initial Value of bcn->dtim_count will be 0. 2216 * But if the beacon gets updated then current dtim 2217 * count will be restored 2218 */ 2219 tim_ie->dtim_count = bcn->dtim_count; 2220 tim_ie->tim_bitctl = 0; 2221 } 2222 2223 qdf_nbuf_put_tail(bcn->buf, len); 2224 bcn->len = len; 2225 2226 qdf_spin_unlock_bh(&bcn->lock); 2227 2228 return QDF_STATUS_SUCCESS; 2229 } 2230 2231 int wma_tbttoffset_update_event_handler(void *handle, uint8_t *event, 2232 uint32_t len) 2233 { 2234 tp_wma_handle wma = (tp_wma_handle) handle; 2235 WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf; 2236 wmi_tbtt_offset_event_fixed_param *tbtt_offset_event; 2237 struct wma_txrx_node *intf; 2238 struct beacon_info *bcn; 2239 tSendbeaconParams bcn_info; 2240 uint32_t *adjusted_tsf = NULL; 2241 uint32_t if_id = 0, vdev_map; 2242 2243 if (wma_validate_handle(wma)) 2244 return -EINVAL; 2245 2246 param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *) event; 2247 if (!param_buf) { 2248 wma_err("Invalid tbtt update event buffer"); 2249 return -EINVAL; 2250 } 2251 2252 tbtt_offset_event = param_buf->fixed_param; 2253 intf = wma->interfaces; 2254 vdev_map = tbtt_offset_event->vdev_map; 2255 adjusted_tsf = param_buf->tbttoffset_list; 2256 if (!adjusted_tsf) { 2257 wma_err("Invalid adjusted_tsf"); 2258 return -EINVAL; 2259 } 2260 2261 for (; (if_id < wma->max_bssid && vdev_map); vdev_map >>= 1, if_id++) { 2262 if (!intf[if_id].vdev) 2263 continue; 2264 2265 if (!(vdev_map & 0x1)) 2266 continue; 2267 2268 bcn = intf[if_id].beacon; 2269 if (!bcn) { 2270 wma_err("Invalid beacon"); 2271 return -EINVAL; 2272 } 2273 if (!bcn->buf) { 2274 wma_err("Invalid beacon buffer"); 2275 return -EINVAL; 2276 } 2277 /* Save the adjusted TSF */ 2278 intf[if_id].tsfadjust = adjusted_tsf[if_id]; 2279 2280 qdf_spin_lock_bh(&bcn->lock); 2281 qdf_mem_zero(&bcn_info, sizeof(bcn_info)); 2282 qdf_mem_copy(bcn_info.beacon, 2283 qdf_nbuf_data(bcn->buf), bcn->len); 2284 bcn_info.p2pIeOffset = bcn->p2p_ie_offset; 2285 bcn_info.beaconLength = bcn->len; 2286 bcn_info.timIeOffset = bcn->tim_ie_offset; 2287 qdf_spin_unlock_bh(&bcn->lock); 2288 2289 /* Update beacon template in firmware */ 2290 wma_unified_bcn_tmpl_send(wma, if_id, &bcn_info, 0); 2291 } 2292 return 0; 2293 } 2294 2295 /** 2296 * wma_p2p_go_set_beacon_ie() - set beacon IE for p2p go 2297 * @wma_handle: wma handle 2298 * @vdev_id: vdev id 2299 * @p2pIe: p2p IE 2300 * 2301 * Return: 0 for success or error code 2302 */ 2303 static int wma_p2p_go_set_beacon_ie(t_wma_handle *wma_handle, 2304 A_UINT32 vdev_id, uint8_t *p2pIe) 2305 { 2306 if (wma_validate_handle(wma_handle)) 2307 return QDF_STATUS_E_FAILURE; 2308 2309 return wmi_unified_p2p_go_set_beacon_ie_cmd(wma_handle->wmi_handle, 2310 vdev_id, p2pIe); 2311 } 2312 2313 /** 2314 * wma_send_probe_rsp_tmpl() - send probe resp template 2315 * @wma: wma handle 2316 * @probe_rsp_info: probe response info 2317 * 2318 * This funciton sends probe response template to fw which 2319 * firmware will use in case of probe response offload. 2320 * 2321 * Return: none 2322 */ 2323 void wma_send_probe_rsp_tmpl(tp_wma_handle wma, 2324 tpSendProbeRespParams probe_rsp_info) 2325 { 2326 uint8_t vdev_id; 2327 struct sAniProbeRspStruct *probe_rsp; 2328 2329 if (!probe_rsp_info) { 2330 wma_err("probe_rsp_info is NULL"); 2331 return; 2332 } 2333 2334 probe_rsp = (struct sAniProbeRspStruct *) 2335 (probe_rsp_info->probeRespTemplate); 2336 if (!probe_rsp) { 2337 wma_err("probe_rsp is NULL"); 2338 return; 2339 } 2340 2341 if (wma_find_vdev_id_by_addr(wma, probe_rsp->macHdr.sa, &vdev_id)) { 2342 wma_err("failed to get vdev id"); 2343 return; 2344 } 2345 2346 if (wmi_service_enabled(wma->wmi_handle, 2347 wmi_service_beacon_offload)) { 2348 wma_nofl_debug("Beacon Offload Enabled Sending Unified command"); 2349 if (wmi_unified_probe_rsp_tmpl_send(wma, vdev_id, 2350 probe_rsp_info) < 0) { 2351 wma_err("wmi_unified_probe_rsp_tmpl_send Failed"); 2352 return; 2353 } 2354 } 2355 } 2356 2357 QDF_STATUS wma_set_ap_vdev_up(tp_wma_handle wma, uint8_t vdev_id) 2358 { 2359 QDF_STATUS status = QDF_STATUS_SUCCESS; 2360 struct vdev_mlme_obj *mlme_obj; 2361 struct wlan_objmgr_vdev *vdev; 2362 struct wma_txrx_node *iface; 2363 2364 iface = &wma->interfaces[vdev_id]; 2365 vdev = iface->vdev; 2366 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev); 2367 if (!mlme_obj) { 2368 wma_err("failed to get mlme_obj"); 2369 return QDF_STATUS_E_INVAL; 2370 } 2371 mlme_obj->proto.sta.assoc_id = 0; 2372 2373 status = vdev_mgr_up_send(mlme_obj); 2374 if (QDF_IS_STATUS_ERROR(status)) { 2375 wma_err("failed to send vdev up"); 2376 return status; 2377 } 2378 wma_set_sap_keepalive(wma, vdev_id); 2379 wma_set_vdev_mgmt_rate(wma, vdev_id); 2380 2381 return status; 2382 } 2383 2384 /** 2385 * wma_send_beacon() - send beacon template 2386 * @wma: wma handle 2387 * @bcn_info: beacon info 2388 * 2389 * This funciton store beacon template locally and 2390 * update keep alive parameters 2391 * 2392 * Return: none 2393 */ 2394 void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info) 2395 { 2396 uint8_t vdev_id; 2397 QDF_STATUS status; 2398 uint8_t *p2p_ie; 2399 struct sAniBeaconStruct *beacon; 2400 2401 wma_nofl_debug("Beacon update reason %d", bcn_info->reason); 2402 beacon = (struct sAniBeaconStruct *) (bcn_info->beacon); 2403 if (wma_find_vdev_id_by_addr(wma, beacon->macHdr.sa, &vdev_id)) { 2404 wma_err("failed to get vdev id"); 2405 status = QDF_STATUS_E_INVAL; 2406 goto send_rsp; 2407 } 2408 2409 if (wmi_service_enabled(wma->wmi_handle, 2410 wmi_service_beacon_offload)) { 2411 status = wma_unified_bcn_tmpl_send(wma, vdev_id, bcn_info, 4); 2412 if (QDF_IS_STATUS_ERROR(status)) { 2413 wma_err("wmi_unified_bcn_tmpl_send Failed"); 2414 goto send_rsp; 2415 } 2416 2417 if (bcn_info->p2pIeOffset) { 2418 p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset; 2419 wma_debug("p2pIe is present - vdev_id %hu, p2p_ie = %pK, p2p ie len = %hu", 2420 vdev_id, p2p_ie, p2p_ie[1]); 2421 if (wma_p2p_go_set_beacon_ie(wma, vdev_id, 2422 p2p_ie) < 0) { 2423 wma_err("wmi_unified_bcn_tmpl_send Failed"); 2424 status = QDF_STATUS_E_INVAL; 2425 goto send_rsp; 2426 } 2427 } 2428 } 2429 status = wma_store_bcn_tmpl(wma, vdev_id, bcn_info); 2430 if (status != QDF_STATUS_SUCCESS) { 2431 wma_err("wma_store_bcn_tmpl Failed"); 2432 goto send_rsp; 2433 } 2434 2435 send_rsp: 2436 bcn_info->status = status; 2437 wma_send_msg(wma, WMA_SEND_BCN_RSP, (void *)bcn_info, 0); 2438 } 2439 2440 /** 2441 * wma_set_keepalive_req() - send keep alive request to fw 2442 * @wma: wma handle 2443 * @keepalive: keep alive parameters 2444 * 2445 * Return: none 2446 */ 2447 void wma_set_keepalive_req(tp_wma_handle wma, 2448 struct keep_alive_req *keepalive) 2449 { 2450 wma_nofl_debug("KEEPALIVE:PacketType:%d", keepalive->packetType); 2451 wma_set_sta_keep_alive(wma, keepalive->sessionId, 2452 keepalive->packetType, 2453 keepalive->timePeriod, 2454 keepalive->hostIpv4Addr, 2455 keepalive->destIpv4Addr, 2456 keepalive->dest_macaddr.bytes); 2457 2458 qdf_mem_free(keepalive); 2459 } 2460 2461 /** 2462 * wma_beacon_miss_handler() - beacon miss event handler 2463 * @wma: wma handle 2464 * @vdev_id: vdev id 2465 * @riis: rssi value 2466 * 2467 * This function send beacon miss indication to upper layers. 2468 * 2469 * Return: none 2470 */ 2471 void wma_beacon_miss_handler(tp_wma_handle wma, uint32_t vdev_id, int32_t rssi) 2472 { 2473 struct missed_beacon_ind *beacon_miss_ind; 2474 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); 2475 2476 beacon_miss_ind = qdf_mem_malloc(sizeof(*beacon_miss_ind)); 2477 if (!beacon_miss_ind) 2478 return; 2479 2480 if (mac && mac->sme.tx_queue_cb) 2481 mac->sme.tx_queue_cb(mac->hdd_handle, vdev_id, 2482 WLAN_STOP_ALL_NETIF_QUEUE, 2483 WLAN_CONTROL_PATH); 2484 beacon_miss_ind->messageType = WMA_MISSED_BEACON_IND; 2485 beacon_miss_ind->length = sizeof(*beacon_miss_ind); 2486 beacon_miss_ind->bss_idx = vdev_id; 2487 2488 wma_send_msg(wma, WMA_MISSED_BEACON_IND, beacon_miss_ind, 0); 2489 if (!wmi_service_enabled(wma->wmi_handle, 2490 wmi_service_hw_db2dbm_support)) 2491 rssi += WMA_TGT_NOISE_FLOOR_DBM; 2492 wma_lost_link_info_handler(wma, vdev_id, rssi); 2493 } 2494 2495 void wlan_cm_send_beacon_miss(uint8_t vdev_id, int32_t rssi) 2496 { 2497 tp_wma_handle wma; 2498 2499 wma = cds_get_context(QDF_MODULE_ID_WMA); 2500 if (!wma) 2501 return; 2502 2503 wma_beacon_miss_handler(wma, vdev_id, rssi); 2504 } 2505 2506 /** 2507 * wma_get_status_str() - get string of tx status from firmware 2508 * @status: tx status 2509 * 2510 * Return: converted string of tx status 2511 */ 2512 static const char *wma_get_status_str(uint32_t status) 2513 { 2514 switch (status) { 2515 default: 2516 return "unknown"; 2517 CASE_RETURN_STRING(WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK); 2518 CASE_RETURN_STRING(WMI_MGMT_TX_COMP_TYPE_DISCARD); 2519 CASE_RETURN_STRING(WMI_MGMT_TX_COMP_TYPE_INSPECT); 2520 CASE_RETURN_STRING(WMI_MGMT_TX_COMP_TYPE_COMPLETE_NO_ACK); 2521 CASE_RETURN_STRING(WMI_MGMT_TX_COMP_TYPE_MAX); 2522 } 2523 } 2524 2525 #ifdef CONFIG_HL_SUPPORT 2526 static inline void wma_mgmt_unmap_buf(tp_wma_handle wma_handle, qdf_nbuf_t buf) 2527 { 2528 } 2529 #else 2530 static inline void wma_mgmt_unmap_buf(tp_wma_handle wma_handle, qdf_nbuf_t buf) 2531 { 2532 qdf_nbuf_unmap_single(wma_handle->qdf_dev, buf, QDF_DMA_TO_DEVICE); 2533 } 2534 #endif 2535 2536 #if !defined(REMOVE_PKT_LOG) 2537 /** 2538 * wma_mgmt_pktdump_status_map() - map MGMT Tx completion status with 2539 * packet dump Tx status 2540 * @status: MGMT Tx completion status 2541 * 2542 * Return: packet dump tx_status enum 2543 */ 2544 static inline enum tx_status 2545 wma_mgmt_pktdump_status_map(WMI_MGMT_TX_COMP_STATUS_TYPE status) 2546 { 2547 enum tx_status pktdump_status; 2548 2549 switch (status) { 2550 case WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK: 2551 pktdump_status = tx_status_ok; 2552 break; 2553 case WMI_MGMT_TX_COMP_TYPE_DISCARD: 2554 pktdump_status = tx_status_discard; 2555 break; 2556 case WMI_MGMT_TX_COMP_TYPE_COMPLETE_NO_ACK: 2557 pktdump_status = tx_status_no_ack; 2558 break; 2559 default: 2560 pktdump_status = tx_status_discard; 2561 break; 2562 } 2563 return pktdump_status; 2564 } 2565 #endif 2566 2567 /** 2568 * wma_process_mgmt_tx_completion() - process mgmt completion 2569 * @wma_handle: wma handle 2570 * @desc_id: descriptor id 2571 * @status: status 2572 * 2573 * Return: 0 for success or error code 2574 */ 2575 static int wma_process_mgmt_tx_completion(tp_wma_handle wma_handle, 2576 uint32_t desc_id, uint32_t status) 2577 { 2578 struct wlan_objmgr_pdev *pdev; 2579 qdf_nbuf_t buf = NULL; 2580 QDF_STATUS ret; 2581 #if !defined(REMOVE_PKT_LOG) 2582 uint8_t vdev_id = 0; 2583 ol_txrx_pktdump_cb packetdump_cb; 2584 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 2585 enum tx_status pktdump_status; 2586 #endif 2587 struct wmi_mgmt_params mgmt_params = {}; 2588 2589 if (wma_validate_handle(wma_handle)) 2590 return -EINVAL; 2591 2592 wma_debug("status: %s wmi_desc_id: %d", 2593 wma_get_status_str(status), desc_id); 2594 2595 pdev = wma_handle->pdev; 2596 if (!pdev) { 2597 wma_err("psoc ptr is NULL"); 2598 return -EINVAL; 2599 } 2600 2601 buf = mgmt_txrx_get_nbuf(pdev, desc_id); 2602 2603 2604 if (buf) 2605 wma_mgmt_unmap_buf(wma_handle, buf); 2606 2607 #if !defined(REMOVE_PKT_LOG) 2608 vdev_id = mgmt_txrx_get_vdev_id(pdev, desc_id); 2609 mgmt_params.vdev_id = vdev_id; 2610 packetdump_cb = wma_handle->wma_mgmt_tx_packetdump_cb; 2611 pktdump_status = wma_mgmt_pktdump_status_map(status); 2612 if (packetdump_cb) 2613 packetdump_cb(soc, WMI_PDEV_ID_SOC, vdev_id, 2614 buf, pktdump_status, TX_MGMT_PKT); 2615 #endif 2616 2617 ret = mgmt_txrx_tx_completion_handler(pdev, desc_id, status, 2618 &mgmt_params); 2619 2620 if (ret != QDF_STATUS_SUCCESS) { 2621 wma_err("Failed to process mgmt tx completion"); 2622 return -EINVAL; 2623 } 2624 2625 return 0; 2626 } 2627 2628 /** 2629 * wma_extract_mgmt_offload_event_params() - Extract mgmt event params 2630 * @params: Management offload event params 2631 * @hdr: Management header to extract 2632 * 2633 * Return: None 2634 */ 2635 static void wma_extract_mgmt_offload_event_params( 2636 struct mgmt_offload_event_params *params, 2637 wmi_mgmt_hdr *hdr) 2638 { 2639 params->tsf_l32 = hdr->tsf_l32; 2640 params->chan_freq = hdr->chan_freq; 2641 params->rate_kbps = hdr->rate_kbps; 2642 params->rssi = hdr->rssi; 2643 params->buf_len = hdr->buf_len; 2644 params->tx_status = hdr->tx_status; 2645 params->tx_retry_cnt = hdr->tx_retry_cnt; 2646 } 2647 2648 /** 2649 * wma_mgmt_tx_completion_handler() - wma mgmt Tx completion event handler 2650 * @handle: wma handle 2651 * @cmpl_event_params: completion event handler data 2652 * @len: length of @cmpl_event_params 2653 * 2654 * Return: 0 on success; error number otherwise 2655 */ 2656 2657 int wma_mgmt_tx_completion_handler(void *handle, uint8_t *cmpl_event_params, 2658 uint32_t len) 2659 { 2660 tp_wma_handle wma_handle = (tp_wma_handle)handle; 2661 WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *param_buf; 2662 wmi_mgmt_tx_compl_event_fixed_param *cmpl_params; 2663 2664 param_buf = (WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *) 2665 cmpl_event_params; 2666 if (!param_buf || !wma_handle) { 2667 wma_err("Invalid mgmt Tx completion event"); 2668 return -EINVAL; 2669 } 2670 cmpl_params = param_buf->fixed_param; 2671 2672 if ((ucfg_pkt_capture_get_pktcap_mode(wma_handle->psoc) & 2673 PKT_CAPTURE_MODE_MGMT_ONLY) && param_buf->mgmt_hdr) { 2674 struct mgmt_offload_event_params params = {0}; 2675 2676 wma_extract_mgmt_offload_event_params( 2677 ¶ms, 2678 (wmi_mgmt_hdr *)param_buf->mgmt_hdr); 2679 ucfg_pkt_capture_mgmt_tx_completion(wma_handle->pdev, 2680 cmpl_params->desc_id, 2681 cmpl_params->status, 2682 ¶ms); 2683 } 2684 2685 wma_process_mgmt_tx_completion(wma_handle, cmpl_params->desc_id, 2686 cmpl_params->status); 2687 2688 return 0; 2689 } 2690 2691 /** 2692 * wma_mgmt_tx_bundle_completion_handler() - mgmt bundle comp handler 2693 * @handle: wma handle 2694 * @buf: buffer 2695 * @len: length 2696 * 2697 * Return: 0 for success or error code 2698 */ 2699 int wma_mgmt_tx_bundle_completion_handler(void *handle, uint8_t *buf, 2700 uint32_t len) 2701 { 2702 tp_wma_handle wma_handle = (tp_wma_handle)handle; 2703 WMI_MGMT_TX_BUNDLE_COMPLETION_EVENTID_param_tlvs *param_buf; 2704 wmi_mgmt_tx_compl_bundle_event_fixed_param *cmpl_params; 2705 uint32_t num_reports; 2706 uint32_t *desc_ids; 2707 uint32_t *status; 2708 uint32_t i, buf_len; 2709 bool excess_data = false; 2710 2711 param_buf = (WMI_MGMT_TX_BUNDLE_COMPLETION_EVENTID_param_tlvs *)buf; 2712 if (!param_buf || !wma_handle) { 2713 wma_err("Invalid mgmt Tx completion event"); 2714 return -EINVAL; 2715 } 2716 cmpl_params = param_buf->fixed_param; 2717 num_reports = cmpl_params->num_reports; 2718 desc_ids = (uint32_t *)(param_buf->desc_ids); 2719 status = (uint32_t *)(param_buf->status); 2720 2721 /* buf contains num_reports * sizeof(uint32) len of desc_ids and 2722 * num_reports * sizeof(uint32) status, 2723 * so (2 x (num_reports * sizeof(uint32)) should not exceed MAX 2724 */ 2725 if (cmpl_params->num_reports > (WMI_SVC_MSG_MAX_SIZE / 2726 (2 * sizeof(uint32_t)))) 2727 excess_data = true; 2728 else 2729 buf_len = cmpl_params->num_reports * (2 * sizeof(uint32_t)); 2730 2731 if (excess_data || (sizeof(*cmpl_params) > (WMI_SVC_MSG_MAX_SIZE - 2732 buf_len))) { 2733 wma_err("excess wmi buffer: num_reports %d", 2734 cmpl_params->num_reports); 2735 return -EINVAL; 2736 } 2737 2738 if ((cmpl_params->num_reports > param_buf->num_desc_ids) || 2739 (cmpl_params->num_reports > param_buf->num_status)) { 2740 wma_err("Invalid num_reports %d, num_desc_ids %d, num_status %d", 2741 cmpl_params->num_reports, param_buf->num_desc_ids, 2742 param_buf->num_status); 2743 return -EINVAL; 2744 } 2745 2746 for (i = 0; i < num_reports; i++) { 2747 if ((ucfg_pkt_capture_get_pktcap_mode(wma_handle->psoc) & 2748 PKT_CAPTURE_MODE_MGMT_ONLY) && param_buf->mgmt_hdr) { 2749 struct mgmt_offload_event_params params = {0}; 2750 2751 wma_extract_mgmt_offload_event_params( 2752 ¶ms, 2753 &((wmi_mgmt_hdr *)param_buf->mgmt_hdr)[i]); 2754 ucfg_pkt_capture_mgmt_tx_completion( 2755 wma_handle->pdev, desc_ids[i], 2756 status[i], ¶ms); 2757 } 2758 2759 wma_process_mgmt_tx_completion(wma_handle, 2760 desc_ids[i], status[i]); 2761 } 2762 return 0; 2763 } 2764 2765 /** 2766 * wma_process_update_opmode() - process update VHT opmode cmd from UMAC 2767 * @wma_handle: wma handle 2768 * @update_vht_opmode: vht opmode 2769 * 2770 * Return: none 2771 */ 2772 void wma_process_update_opmode(tp_wma_handle wma_handle, 2773 tUpdateVHTOpMode *update_vht_opmode) 2774 { 2775 wmi_host_channel_width ch_width; 2776 uint8_t pdev_id; 2777 struct wlan_objmgr_peer *peer; 2778 struct wlan_objmgr_psoc *psoc = wma_handle->psoc; 2779 enum wlan_phymode peer_phymode; 2780 uint32_t fw_phymode; 2781 enum wlan_peer_type peer_type; 2782 2783 pdev_id = wlan_objmgr_pdev_get_pdev_id(wma_handle->pdev); 2784 peer = wlan_objmgr_get_peer(psoc, pdev_id, 2785 update_vht_opmode->peer_mac, 2786 WLAN_LEGACY_WMA_ID); 2787 if (!peer) { 2788 wma_err("peer object invalid"); 2789 return; 2790 } 2791 2792 peer_type = wlan_peer_get_peer_type(peer); 2793 if (peer_type == WLAN_PEER_SELF) { 2794 wma_err("self peer wrongly used"); 2795 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID); 2796 return; 2797 } 2798 2799 wlan_peer_obj_lock(peer); 2800 peer_phymode = wlan_peer_get_phymode(peer); 2801 wlan_peer_obj_unlock(peer); 2802 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID); 2803 2804 fw_phymode = wma_host_to_fw_phymode(peer_phymode); 2805 2806 ch_width = wmi_get_ch_width_from_phy_mode(wma_handle->wmi_handle, 2807 fw_phymode); 2808 wma_debug("ch_width: %d, fw phymode: %d peer_phymode %d", 2809 ch_width, fw_phymode, peer_phymode); 2810 if (ch_width < update_vht_opmode->opMode) { 2811 wma_err("Invalid peer bw update %d, self bw %d", 2812 update_vht_opmode->opMode, ch_width); 2813 return; 2814 } 2815 2816 wma_debug("opMode = %d", update_vht_opmode->opMode); 2817 wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac, 2818 WMI_PEER_CHWIDTH, update_vht_opmode->opMode, 2819 update_vht_opmode->smesessionId); 2820 } 2821 2822 /** 2823 * wma_process_update_rx_nss() - process update RX NSS cmd from UMAC 2824 * @wma_handle: wma handle 2825 * @update_rx_nss: rx nss value 2826 * 2827 * Return: none 2828 */ 2829 void wma_process_update_rx_nss(tp_wma_handle wma_handle, 2830 tUpdateRxNss *update_rx_nss) 2831 { 2832 struct target_psoc_info *tgt_hdl; 2833 struct wma_txrx_node *intr = 2834 &wma_handle->interfaces[update_rx_nss->smesessionId]; 2835 int rx_nss = update_rx_nss->rxNss; 2836 int num_rf_chains; 2837 2838 tgt_hdl = wlan_psoc_get_tgt_if_handle(wma_handle->psoc); 2839 if (!tgt_hdl) { 2840 wma_err("target psoc info is NULL"); 2841 return; 2842 } 2843 2844 num_rf_chains = target_if_get_num_rf_chains(tgt_hdl); 2845 if (rx_nss > num_rf_chains || rx_nss > WMA_MAX_NSS) 2846 rx_nss = QDF_MIN(num_rf_chains, WMA_MAX_NSS); 2847 2848 intr->nss = (uint8_t)rx_nss; 2849 update_rx_nss->rxNss = (uint32_t)rx_nss; 2850 2851 wma_debug("Rx Nss = %d", update_rx_nss->rxNss); 2852 2853 wma_set_peer_param(wma_handle, update_rx_nss->peer_mac, 2854 WMI_PEER_NSS, update_rx_nss->rxNss, 2855 update_rx_nss->smesessionId); 2856 } 2857 2858 /** 2859 * wma_process_update_membership() - process update group membership cmd 2860 * @wma_handle: wma handle 2861 * @membership: group membership info 2862 * 2863 * Return: none 2864 */ 2865 void wma_process_update_membership(tp_wma_handle wma_handle, 2866 tUpdateMembership *membership) 2867 { 2868 wma_debug("membership = %x ", membership->membership); 2869 2870 wma_set_peer_param(wma_handle, membership->peer_mac, 2871 WMI_PEER_MEMBERSHIP, membership->membership, 2872 membership->smesessionId); 2873 } 2874 2875 /** 2876 * wma_process_update_userpos() - process update user pos cmd from UMAC 2877 * @wma_handle: wma handle 2878 * @userpos: user pos value 2879 * 2880 * Return: none 2881 */ 2882 void wma_process_update_userpos(tp_wma_handle wma_handle, 2883 tUpdateUserPos *userpos) 2884 { 2885 wma_debug("userPos = %x ", userpos->userPos); 2886 2887 wma_set_peer_param(wma_handle, userpos->peer_mac, 2888 WMI_PEER_USERPOS, userpos->userPos, 2889 userpos->smesessionId); 2890 2891 /* Now that membership/userpos is updated in fw, 2892 * enable GID PPS. 2893 */ 2894 wma_set_ppsconfig(userpos->smesessionId, WMA_VHT_PPS_GID_MATCH, 1); 2895 2896 } 2897 2898 QDF_STATUS wma_set_cts2self_for_p2p_go(void *wma_handle, 2899 uint32_t cts2self_for_p2p_go) 2900 { 2901 int32_t ret; 2902 tp_wma_handle wma = (tp_wma_handle)wma_handle; 2903 struct pdev_params pdevparam; 2904 2905 pdevparam.param_id = WMI_PDEV_PARAM_CTS2SELF_FOR_P2P_GO_CONFIG; 2906 pdevparam.param_value = cts2self_for_p2p_go; 2907 2908 ret = wmi_unified_pdev_param_send(wma->wmi_handle, 2909 &pdevparam, 2910 WMA_WILDCARD_PDEV_ID); 2911 if (ret) { 2912 wma_err("Fail to Set CTS2SELF for p2p GO %d", 2913 cts2self_for_p2p_go); 2914 return QDF_STATUS_E_FAILURE; 2915 } 2916 2917 wma_nofl_debug("Successfully Set CTS2SELF for p2p GO %d", 2918 cts2self_for_p2p_go); 2919 2920 return QDF_STATUS_SUCCESS; 2921 } 2922 2923 2924 /** 2925 * wma_set_htconfig() - set ht config parameters to target 2926 * @vdev_id: vdev id 2927 * @ht_capab: ht capablity 2928 * @value: value of ht param 2929 * 2930 * Return: QDF status 2931 */ 2932 QDF_STATUS wma_set_htconfig(uint8_t vdev_id, uint16_t ht_capab, int value) 2933 { 2934 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); 2935 QDF_STATUS ret = QDF_STATUS_E_FAILURE; 2936 2937 if (!wma) 2938 return QDF_STATUS_E_INVAL; 2939 2940 switch (ht_capab) { 2941 case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING: 2942 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id, 2943 WMI_VDEV_PARAM_LDPC, 2944 value); 2945 break; 2946 case WNI_CFG_HT_CAP_INFO_TX_STBC: 2947 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id, 2948 WMI_VDEV_PARAM_TX_STBC, 2949 value); 2950 break; 2951 case WNI_CFG_HT_CAP_INFO_RX_STBC: 2952 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id, 2953 WMI_VDEV_PARAM_RX_STBC, 2954 value); 2955 break; 2956 case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ: 2957 case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ: 2958 wma_err("ht_capab = %d, value = %d", ht_capab, 2959 value); 2960 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id, 2961 WMI_VDEV_PARAM_SGI, value); 2962 if (ret == QDF_STATUS_SUCCESS) 2963 wma->interfaces[vdev_id].config.shortgi = value; 2964 break; 2965 default: 2966 wma_err("INVALID HT CONFIG"); 2967 } 2968 2969 return ret; 2970 } 2971 2972 /** 2973 * wma_extract_ccmp_pn() - extract 6 byte PN from the CCMP header 2974 * @ccmp_ptr: CCMP header 2975 * 2976 * Return: PN extracted from header. 2977 */ 2978 static uint64_t wma_extract_ccmp_pn(uint8_t *ccmp_ptr) 2979 { 2980 uint8_t rsvd, key, pn[6]; 2981 uint64_t new_pn; 2982 2983 /* 2984 * +-----+-----+------+----------+-----+-----+-----+-----+ 2985 * | PN0 | PN1 | rsvd | rsvd/key | PN2 | PN3 | PN4 | PN5 | 2986 * +-----+-----+------+----------+-----+-----+-----+-----+ 2987 * CCMP Header Format 2988 */ 2989 2990 /* Extract individual bytes */ 2991 pn[0] = (uint8_t) *ccmp_ptr; 2992 pn[1] = (uint8_t) *(ccmp_ptr + 1); 2993 rsvd = (uint8_t) *(ccmp_ptr + 2); 2994 key = (uint8_t) *(ccmp_ptr + 3); 2995 pn[2] = (uint8_t) *(ccmp_ptr + 4); 2996 pn[3] = (uint8_t) *(ccmp_ptr + 5); 2997 pn[4] = (uint8_t) *(ccmp_ptr + 6); 2998 pn[5] = (uint8_t) *(ccmp_ptr + 7); 2999 3000 /* Form 6 byte PN with 6 individual bytes of PN */ 3001 new_pn = ((uint64_t) pn[5] << 40) | 3002 ((uint64_t) pn[4] << 32) | 3003 ((uint64_t) pn[3] << 24) | 3004 ((uint64_t) pn[2] << 16) | 3005 ((uint64_t) pn[1] << 8) | ((uint64_t) pn[0] << 0); 3006 3007 return new_pn; 3008 } 3009 3010 /** 3011 * wma_is_ccmp_pn_replay_attack() - detect replay attacking using PN in CCMP 3012 * @wma: wma context 3013 * @wh: 802.11 frame header 3014 * @ccmp_ptr: CCMP frame header 3015 * 3016 * Return: true/false 3017 */ 3018 static bool 3019 wma_is_ccmp_pn_replay_attack(tp_wma_handle wma, struct ieee80211_frame *wh, 3020 uint8_t *ccmp_ptr) 3021 { 3022 uint64_t new_pn; 3023 bool ret = false; 3024 struct peer_mlme_priv_obj *peer_priv; 3025 struct wlan_objmgr_peer *peer; 3026 3027 new_pn = wma_extract_ccmp_pn(ccmp_ptr); 3028 3029 peer = wlan_objmgr_get_peer_by_mac(wma->psoc, wh->i_addr2, 3030 WLAN_LEGACY_WMA_ID); 3031 if (!peer) 3032 return ret; 3033 3034 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, 3035 WLAN_UMAC_COMP_MLME); 3036 if (!peer_priv) { 3037 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID); 3038 return ret; 3039 } 3040 3041 if (peer_priv->last_pn_valid) { 3042 if (new_pn > peer_priv->last_pn) { 3043 peer_priv->last_pn = new_pn; 3044 } else { 3045 wma_err_rl("PN Replay attack detected"); 3046 /* per 11W amendment, keeping track of replay attacks */ 3047 peer_priv->rmf_pn_replays += 1; 3048 ret = true; 3049 } 3050 } else { 3051 peer_priv->last_pn_valid = 1; 3052 peer_priv->last_pn = new_pn; 3053 } 3054 3055 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID); 3056 3057 return ret; 3058 } 3059 3060 /** 3061 * wma_process_bip() - process mmie in rmf frame 3062 * @wma_handle: wma handle 3063 * @iface: txrx node 3064 * @wh: 80211 frame 3065 * @wbuf: Buffer 3066 * 3067 * Return: 0 for success or error code 3068 */ 3069 static 3070 int wma_process_bip(tp_wma_handle wma_handle, struct wma_txrx_node *iface, 3071 struct ieee80211_frame *wh, qdf_nbuf_t wbuf) 3072 { 3073 uint16_t mmie_size; 3074 uint8_t *efrm; 3075 int32_t mgmtcipherset; 3076 enum wlan_crypto_cipher_type key_cipher; 3077 3078 efrm = qdf_nbuf_data(wbuf) + qdf_nbuf_len(wbuf); 3079 3080 mgmtcipherset = wlan_crypto_get_param(iface->vdev, 3081 WLAN_CRYPTO_PARAM_MGMT_CIPHER); 3082 if (mgmtcipherset <= 0) { 3083 wma_err("Invalid key cipher %d", mgmtcipherset); 3084 return -EINVAL; 3085 } 3086 3087 if (mgmtcipherset & (1 << WLAN_CRYPTO_CIPHER_AES_CMAC)) { 3088 key_cipher = WLAN_CRYPTO_CIPHER_AES_CMAC; 3089 mmie_size = cds_get_mmie_size(); 3090 } else if (mgmtcipherset & (1 << WLAN_CRYPTO_CIPHER_AES_GMAC)) { 3091 key_cipher = WLAN_CRYPTO_CIPHER_AES_GMAC; 3092 mmie_size = cds_get_gmac_mmie_size(); 3093 } else if (mgmtcipherset & (1 << WLAN_CRYPTO_CIPHER_AES_GMAC_256)) { 3094 key_cipher = WLAN_CRYPTO_CIPHER_AES_GMAC_256; 3095 mmie_size = cds_get_gmac_mmie_size(); 3096 } else { 3097 wma_err("Invalid key cipher %d", mgmtcipherset); 3098 return -EINVAL; 3099 } 3100 3101 /* Check if frame is invalid length */ 3102 if (efrm - (uint8_t *)wh < sizeof(*wh) + mmie_size) { 3103 wma_err("Invalid frame length"); 3104 return -EINVAL; 3105 } 3106 3107 switch (key_cipher) { 3108 case WLAN_CRYPTO_CIPHER_AES_CMAC: 3109 if (!wmi_service_enabled(wma_handle->wmi_handle, 3110 wmi_service_sta_pmf_offload)) { 3111 if (!wlan_crypto_is_mmie_valid(iface->vdev, 3112 (uint8_t *)wh, efrm)) { 3113 wma_debug("BC/MC MIC error or MMIE not present, dropping the frame"); 3114 return -EINVAL; 3115 } 3116 } 3117 break; 3118 case WLAN_CRYPTO_CIPHER_AES_GMAC: 3119 case WLAN_CRYPTO_CIPHER_AES_GMAC_256: 3120 if (!wmi_service_enabled(wma_handle->wmi_handle, 3121 wmi_service_gmac_offload_support)) { 3122 if (!wlan_crypto_is_mmie_valid(iface->vdev, 3123 (uint8_t *)wh, efrm)) { 3124 wma_debug("BC/MC GMAC MIC error or MMIE not present, dropping the frame"); 3125 return -EINVAL; 3126 } 3127 } 3128 break; 3129 default: 3130 wma_err("Invalid key_type %d", key_cipher); 3131 return -EINVAL; 3132 } 3133 3134 qdf_nbuf_trim_tail(wbuf, mmie_size); 3135 3136 return 0; 3137 } 3138 3139 /** 3140 * wma_process_rmf_frame() - process rmf frame 3141 * @wma_handle: wma handle 3142 * @iface: txrx node 3143 * @wh: 80211 frame 3144 * @rx_pkt: rx packet 3145 * @wbuf: Buffer 3146 * 3147 * Return: 0 for success or error code 3148 */ 3149 static 3150 int wma_process_rmf_frame(tp_wma_handle wma_handle, 3151 struct wma_txrx_node *iface, 3152 struct ieee80211_frame *wh, 3153 cds_pkt_t *rx_pkt, 3154 qdf_nbuf_t wbuf) 3155 { 3156 uint8_t *orig_hdr; 3157 uint8_t *ccmp; 3158 uint8_t mic_len, hdr_len, pdev_id; 3159 QDF_STATUS status; 3160 3161 if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) { 3162 if (QDF_IS_ADDR_BROADCAST(wh->i_addr1) || 3163 IEEE80211_IS_MULTICAST(wh->i_addr1)) { 3164 wma_err("Encrypted BC/MC frame dropping the frame"); 3165 cds_pkt_return_packet(rx_pkt); 3166 return -EINVAL; 3167 } 3168 3169 if (iface->type == WMI_VDEV_TYPE_NDI) { 3170 hdr_len = IEEE80211_CCMP_HEADERLEN; 3171 mic_len = IEEE80211_CCMP_MICLEN; 3172 } else { 3173 pdev_id = 3174 wlan_objmgr_pdev_get_pdev_id(wma_handle->pdev); 3175 status = mlme_get_peer_mic_len(wma_handle->psoc, 3176 pdev_id, wh->i_addr2, 3177 &mic_len, &hdr_len); 3178 if (QDF_IS_STATUS_ERROR(status)) { 3179 wma_err("Failed to get mic hdr and length"); 3180 cds_pkt_return_packet(rx_pkt); 3181 return -EINVAL; 3182 } 3183 } 3184 3185 if (qdf_nbuf_len(wbuf) < (sizeof(*wh) + hdr_len + mic_len)) { 3186 wma_err("Buffer length less than expected %d", 3187 (int)qdf_nbuf_len(wbuf)); 3188 cds_pkt_return_packet(rx_pkt); 3189 return -EINVAL; 3190 } 3191 3192 orig_hdr = (uint8_t *) qdf_nbuf_data(wbuf); 3193 /* Pointer to head of CCMP header */ 3194 ccmp = orig_hdr + sizeof(*wh); 3195 if (wma_is_ccmp_pn_replay_attack(wma_handle, wh, ccmp)) { 3196 wma_err_rl("Dropping the frame"); 3197 cds_pkt_return_packet(rx_pkt); 3198 return -EINVAL; 3199 } 3200 3201 /* Strip privacy headers (and trailer) 3202 * for a received frame 3203 */ 3204 qdf_mem_move(orig_hdr + 3205 hdr_len, wh, 3206 sizeof(*wh)); 3207 qdf_nbuf_pull_head(wbuf, 3208 hdr_len); 3209 qdf_nbuf_trim_tail(wbuf, mic_len); 3210 /* 3211 * CCMP header has been pulled off 3212 * reinitialize the start pointer of mac header 3213 * to avoid accessing incorrect address 3214 */ 3215 wh = (struct ieee80211_frame *) qdf_nbuf_data(wbuf); 3216 rx_pkt->pkt_meta.mpdu_hdr_ptr = 3217 qdf_nbuf_data(wbuf); 3218 rx_pkt->pkt_meta.mpdu_len = qdf_nbuf_len(wbuf); 3219 rx_pkt->pkt_buf = wbuf; 3220 if (rx_pkt->pkt_meta.mpdu_len >= 3221 rx_pkt->pkt_meta.mpdu_hdr_len) { 3222 rx_pkt->pkt_meta.mpdu_data_len = 3223 rx_pkt->pkt_meta.mpdu_len - 3224 rx_pkt->pkt_meta.mpdu_hdr_len; 3225 } else { 3226 wma_err("mpdu len %d less than hdr %d, dropping frame", 3227 rx_pkt->pkt_meta.mpdu_len, 3228 rx_pkt->pkt_meta.mpdu_hdr_len); 3229 cds_pkt_return_packet(rx_pkt); 3230 return -EINVAL; 3231 } 3232 3233 if (rx_pkt->pkt_meta.mpdu_data_len > MAX_MGMT_MPDU_LEN) { 3234 wma_err("Data Len %d greater than max, dropping frame", 3235 rx_pkt->pkt_meta.mpdu_data_len); 3236 cds_pkt_return_packet(rx_pkt); 3237 return -EINVAL; 3238 } 3239 rx_pkt->pkt_meta.mpdu_data_ptr = 3240 rx_pkt->pkt_meta.mpdu_hdr_ptr + 3241 rx_pkt->pkt_meta.mpdu_hdr_len; 3242 wma_debug("BSSID: "QDF_MAC_ADDR_FMT" tsf_delta: %u", 3243 QDF_MAC_ADDR_REF(wh->i_addr3), 3244 rx_pkt->pkt_meta.tsf_delta); 3245 } else { 3246 if (QDF_IS_ADDR_BROADCAST(wh->i_addr1) || 3247 IEEE80211_IS_MULTICAST(wh->i_addr1)) { 3248 if (0 != wma_process_bip(wma_handle, iface, wh, wbuf)) { 3249 cds_pkt_return_packet(rx_pkt); 3250 return -EINVAL; 3251 } 3252 } else { 3253 wma_err("Rx unprotected unicast mgmt frame"); 3254 rx_pkt->pkt_meta.dpuFeedback = 3255 DPU_FEEDBACK_UNPROTECTED_ERROR; 3256 } 3257 } 3258 return 0; 3259 } 3260 3261 /** 3262 * wma_get_peer_pmf_status() - Get the PMF capability of peer 3263 * @wma: wma handle 3264 * @peer_mac: peer mac addr 3265 * 3266 * Return: True if PMF is enabled, false otherwise. 3267 */ 3268 static bool 3269 wma_get_peer_pmf_status(tp_wma_handle wma, uint8_t *peer_mac) 3270 { 3271 struct wlan_objmgr_peer *peer; 3272 bool is_pmf_enabled; 3273 3274 if (!peer_mac) { 3275 wma_err("peer_mac is NULL"); 3276 return false; 3277 } 3278 3279 peer = wlan_objmgr_get_peer(wma->psoc, 3280 wlan_objmgr_pdev_get_pdev_id(wma->pdev), 3281 peer_mac, WLAN_LEGACY_WMA_ID); 3282 if (!peer) { 3283 wma_err("Peer of peer_mac "QDF_MAC_ADDR_FMT" not found", 3284 QDF_MAC_ADDR_REF(peer_mac)); 3285 return false; 3286 } 3287 is_pmf_enabled = mlme_get_peer_pmf_status(peer); 3288 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID); 3289 wma_nofl_debug("get is_pmf_enabled %d for "QDF_MAC_ADDR_FMT, 3290 is_pmf_enabled, QDF_MAC_ADDR_REF(peer_mac)); 3291 3292 return is_pmf_enabled; 3293 } 3294 3295 /** 3296 * wma_check_and_process_rmf_frame() - Process the frame if it is of rmf type 3297 * @wma_handle: wma handle 3298 * @vdev_id: vdev id 3299 * @wh: double pointer to 802.11 frame header which will be updated if the 3300 * frame is of rmf type. 3301 * @rx_pkt: rx packet 3302 * @buf: Buffer 3303 * 3304 * Process the frame as rmf frame only if both DUT and peer are of PMF capable 3305 * 3306 * Return: 0 for success or error code 3307 */ 3308 static int 3309 wma_check_and_process_rmf_frame(tp_wma_handle wma_handle, 3310 uint8_t vdev_id, 3311 struct ieee80211_frame **wh, 3312 cds_pkt_t *rx_pkt, 3313 qdf_nbuf_t buf) 3314 { 3315 int status; 3316 struct wma_txrx_node *iface; 3317 struct ieee80211_frame *hdr = *wh; 3318 3319 iface = &(wma_handle->interfaces[vdev_id]); 3320 if (iface->type != WMI_VDEV_TYPE_NDI && !iface->rmfEnabled) 3321 return 0; 3322 3323 if (qdf_is_macaddr_group((struct qdf_mac_addr *)(hdr->i_addr1)) || 3324 qdf_is_macaddr_broadcast((struct qdf_mac_addr *)(hdr->i_addr1)) || 3325 wma_get_peer_pmf_status(wma_handle, hdr->i_addr2) || 3326 (iface->type == WMI_VDEV_TYPE_NDI && 3327 (hdr->i_fc[1] & IEEE80211_FC1_WEP))) { 3328 status = wma_process_rmf_frame(wma_handle, iface, hdr, 3329 rx_pkt, buf); 3330 if (status) 3331 return status; 3332 /* 3333 * CCMP header might have been pulled off reinitialize the 3334 * start pointer of mac header 3335 */ 3336 *wh = (struct ieee80211_frame *)qdf_nbuf_data(buf); 3337 } 3338 3339 return 0; 3340 } 3341 3342 /** 3343 * wma_is_pkt_drop_candidate() - check if the mgmt frame should be droppped 3344 * @wma_handle: wma handle 3345 * @peer_addr: peer MAC address 3346 * @bssid: BSSID Address 3347 * @subtype: Management frame subtype 3348 * 3349 * This function is used to decide if a particular management frame should be 3350 * dropped to prevent DOS attack. Timestamp is used to decide the DOS attack. 3351 * 3352 * Return: true if the packet should be dropped and false oterwise 3353 */ 3354 static bool wma_is_pkt_drop_candidate(tp_wma_handle wma_handle, 3355 uint8_t *peer_addr, uint8_t *bssid, 3356 uint8_t subtype) 3357 { 3358 bool should_drop = false; 3359 uint8_t nan_addr[] = {0x50, 0x6F, 0x9A, 0x01, 0x00, 0x00}; 3360 3361 /* Drop the beacons from NAN device */ 3362 if ((subtype == MGMT_SUBTYPE_BEACON) && 3363 (!qdf_mem_cmp(nan_addr, bssid, NAN_CLUSTER_ID_BYTES))) { 3364 should_drop = true; 3365 goto end; 3366 } 3367 end: 3368 return should_drop; 3369 } 3370 3371 #define RATE_LIMIT 16 3372 3373 int wma_form_rx_packet(qdf_nbuf_t buf, 3374 struct mgmt_rx_event_params *mgmt_rx_params, 3375 cds_pkt_t *rx_pkt) 3376 { 3377 uint8_t vdev_id = WMA_INVALID_VDEV_ID; 3378 struct ieee80211_frame *wh; 3379 uint8_t mgt_type, mgt_subtype; 3380 int status; 3381 tp_wma_handle wma_handle = (tp_wma_handle) 3382 cds_get_context(QDF_MODULE_ID_WMA); 3383 #if !defined(REMOVE_PKT_LOG) 3384 ol_txrx_pktdump_cb packetdump_cb; 3385 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 3386 #endif 3387 static uint8_t limit_prints_invalid_len = RATE_LIMIT - 1; 3388 static uint8_t limit_prints_load_unload = RATE_LIMIT - 1; 3389 static uint8_t limit_prints_recovery = RATE_LIMIT - 1; 3390 3391 if (!wma_handle) { 3392 qdf_nbuf_free(buf); 3393 qdf_mem_free(rx_pkt); 3394 return -EINVAL; 3395 } 3396 3397 if (!mgmt_rx_params) { 3398 limit_prints_invalid_len++; 3399 if (limit_prints_invalid_len == RATE_LIMIT) { 3400 wma_debug("mgmt rx params is NULL"); 3401 limit_prints_invalid_len = 0; 3402 } 3403 qdf_nbuf_free(buf); 3404 qdf_mem_free(rx_pkt); 3405 return -EINVAL; 3406 } 3407 3408 if (cds_is_load_or_unload_in_progress()) { 3409 limit_prints_load_unload++; 3410 if (limit_prints_load_unload == RATE_LIMIT) { 3411 wma_debug("Load/Unload in progress"); 3412 limit_prints_load_unload = 0; 3413 } 3414 qdf_nbuf_free(buf); 3415 qdf_mem_free(rx_pkt); 3416 return -EINVAL; 3417 } 3418 3419 if (cds_is_driver_recovering()) { 3420 limit_prints_recovery++; 3421 if (limit_prints_recovery == RATE_LIMIT) { 3422 wma_debug("Recovery in progress"); 3423 limit_prints_recovery = 0; 3424 } 3425 qdf_nbuf_free(buf); 3426 qdf_mem_free(rx_pkt); 3427 return -EINVAL; 3428 } 3429 3430 if (cds_is_driver_in_bad_state()) { 3431 limit_prints_recovery++; 3432 if (limit_prints_recovery == RATE_LIMIT) { 3433 wma_debug("Driver in bad state"); 3434 limit_prints_recovery = 0; 3435 } 3436 qdf_nbuf_free(buf); 3437 qdf_mem_free(rx_pkt); 3438 return -EINVAL; 3439 } 3440 3441 /* 3442 * Fill in meta information needed by pe/lim 3443 * TODO: Try to maintain rx metainfo as part of skb->data. 3444 */ 3445 rx_pkt->pkt_meta.frequency = mgmt_rx_params->chan_freq; 3446 rx_pkt->pkt_meta.scan_src = mgmt_rx_params->flags; 3447 3448 /* 3449 * Get the rssi value from the current snr value 3450 * using standard noise floor of -96. 3451 */ 3452 rx_pkt->pkt_meta.rssi = mgmt_rx_params->snr + 3453 WMA_NOISE_FLOOR_DBM_DEFAULT; 3454 rx_pkt->pkt_meta.snr = mgmt_rx_params->snr; 3455 3456 /* If absolute rssi is available from firmware, use it */ 3457 if (mgmt_rx_params->rssi != 0) 3458 rx_pkt->pkt_meta.rssi_raw = mgmt_rx_params->rssi; 3459 else 3460 rx_pkt->pkt_meta.rssi_raw = rx_pkt->pkt_meta.rssi; 3461 3462 3463 /* 3464 * FIXME: Assigning the local timestamp as hw timestamp is not 3465 * available. Need to see if pe/lim really uses this data. 3466 */ 3467 rx_pkt->pkt_meta.timestamp = (uint32_t) jiffies; 3468 rx_pkt->pkt_meta.mpdu_hdr_len = sizeof(struct ieee80211_frame); 3469 rx_pkt->pkt_meta.mpdu_len = mgmt_rx_params->buf_len; 3470 3471 /* 3472 * The buf_len should be at least 802.11 header len 3473 */ 3474 if (mgmt_rx_params->buf_len < rx_pkt->pkt_meta.mpdu_hdr_len) { 3475 wma_err("MPDU Len %d lesser than header len %d", 3476 mgmt_rx_params->buf_len, 3477 rx_pkt->pkt_meta.mpdu_hdr_len); 3478 qdf_nbuf_free(buf); 3479 qdf_mem_free(rx_pkt); 3480 return -EINVAL; 3481 } 3482 3483 rx_pkt->pkt_meta.mpdu_data_len = mgmt_rx_params->buf_len - 3484 rx_pkt->pkt_meta.mpdu_hdr_len; 3485 3486 rx_pkt->pkt_meta.roamCandidateInd = 0; 3487 3488 wh = (struct ieee80211_frame *)qdf_nbuf_data(buf); 3489 3490 /* 3491 * If the mpdu_data_len is greater than Max (2k), drop the frame 3492 */ 3493 if (rx_pkt->pkt_meta.mpdu_data_len > MAX_MGMT_MPDU_LEN) { 3494 wma_err("Data Len %d greater than max, dropping frame from "QDF_MAC_ADDR_FMT, 3495 rx_pkt->pkt_meta.mpdu_data_len, 3496 QDF_MAC_ADDR_REF(wh->i_addr3)); 3497 qdf_nbuf_free(buf); 3498 qdf_mem_free(rx_pkt); 3499 return -EINVAL; 3500 } 3501 3502 rx_pkt->pkt_meta.mpdu_hdr_ptr = qdf_nbuf_data(buf); 3503 rx_pkt->pkt_meta.mpdu_data_ptr = rx_pkt->pkt_meta.mpdu_hdr_ptr + 3504 rx_pkt->pkt_meta.mpdu_hdr_len; 3505 rx_pkt->pkt_meta.tsf_delta = mgmt_rx_params->tsf_delta; 3506 rx_pkt->pkt_buf = buf; 3507 3508 /* If it is a beacon/probe response, save it for future use */ 3509 mgt_type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 3510 mgt_subtype = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 3511 3512 if (mgt_type == IEEE80211_FC0_TYPE_MGT && 3513 (mgt_subtype == MGMT_SUBTYPE_DISASSOC || 3514 mgt_subtype == MGMT_SUBTYPE_DEAUTH || 3515 mgt_subtype == MGMT_SUBTYPE_ACTION)) { 3516 if (wma_find_vdev_id_by_bssid(wma_handle, wh->i_addr3, 3517 &vdev_id) == QDF_STATUS_SUCCESS) { 3518 status = wma_check_and_process_rmf_frame(wma_handle, 3519 vdev_id, 3520 &wh, 3521 rx_pkt, 3522 buf); 3523 if (status) 3524 return status; 3525 } else if (wma_find_vdev_id_by_addr(wma_handle, wh->i_addr1, 3526 &vdev_id) == QDF_STATUS_SUCCESS) { 3527 status = wma_check_and_process_rmf_frame(wma_handle, 3528 vdev_id, 3529 &wh, 3530 rx_pkt, 3531 buf); 3532 if (status) 3533 return status; 3534 } 3535 } 3536 3537 rx_pkt->pkt_meta.session_id = 3538 (vdev_id == WMA_INVALID_VDEV_ID ? 0 : vdev_id); 3539 3540 if (mgt_type == IEEE80211_FC0_TYPE_MGT && 3541 (mgt_subtype == MGMT_SUBTYPE_BEACON || 3542 mgt_subtype == MGMT_SUBTYPE_PROBE_RESP)) { 3543 if (mgmt_rx_params->buf_len <= 3544 (sizeof(struct ieee80211_frame) + 3545 offsetof(struct wlan_bcn_frame, ie))) { 3546 wma_debug("Dropping frame from "QDF_MAC_ADDR_FMT, 3547 QDF_MAC_ADDR_REF(wh->i_addr3)); 3548 cds_pkt_return_packet(rx_pkt); 3549 return -EINVAL; 3550 } 3551 } 3552 3553 if (wma_is_pkt_drop_candidate(wma_handle, wh->i_addr2, wh->i_addr3, 3554 mgt_subtype)) { 3555 cds_pkt_return_packet(rx_pkt); 3556 return -EINVAL; 3557 } 3558 3559 #if !defined(REMOVE_PKT_LOG) 3560 packetdump_cb = wma_handle->wma_mgmt_rx_packetdump_cb; 3561 if ((mgt_type == IEEE80211_FC0_TYPE_MGT && 3562 mgt_subtype != MGMT_SUBTYPE_BEACON) && 3563 packetdump_cb) 3564 packetdump_cb(soc, mgmt_rx_params->pdev_id, 3565 rx_pkt->pkt_meta.session_id, rx_pkt->pkt_buf, 3566 QDF_STATUS_SUCCESS, RX_MGMT_PKT); 3567 #endif 3568 return 0; 3569 } 3570 3571 /** 3572 * wma_mem_endianness_based_copy() - does memory copy from src to dst 3573 * @dst: destination address 3574 * @src: source address 3575 * @size: size to be copied 3576 * 3577 * This function copies the memory of size passed from source 3578 * address to destination address. 3579 * 3580 * Return: Nothing 3581 */ 3582 #ifdef BIG_ENDIAN_HOST 3583 static void wma_mem_endianness_based_copy( 3584 uint8_t *dst, uint8_t *src, uint32_t size) 3585 { 3586 /* 3587 * For big endian host, copy engine byte_swap is enabled 3588 * But the rx mgmt frame buffer content is in network byte order 3589 * Need to byte swap the mgmt frame buffer content - so when 3590 * copy engine does byte_swap - host gets buffer content in the 3591 * correct byte order. 3592 */ 3593 3594 uint32_t i; 3595 uint32_t *destp, *srcp; 3596 3597 destp = (uint32_t *) dst; 3598 srcp = (uint32_t *) src; 3599 for (i = 0; i < (roundup(size, sizeof(uint32_t)) / 4); i++) { 3600 *destp = cpu_to_le32(*srcp); 3601 destp++; 3602 srcp++; 3603 } 3604 } 3605 #else 3606 static void wma_mem_endianness_based_copy( 3607 uint8_t *dst, uint8_t *src, uint32_t size) 3608 { 3609 qdf_mem_copy(dst, src, size); 3610 } 3611 #endif 3612 3613 #define RESERVE_BYTES 100 3614 /** 3615 * wma_mgmt_rx_process() - process management rx frame. 3616 * @handle: wma handle 3617 * @data: rx data 3618 * @data_len: data length 3619 * 3620 * Return: 0 for success or error code 3621 */ 3622 static int wma_mgmt_rx_process(void *handle, uint8_t *data, 3623 uint32_t data_len) 3624 { 3625 tp_wma_handle wma_handle = (tp_wma_handle) handle; 3626 struct mgmt_rx_event_params *mgmt_rx_params; 3627 struct wlan_objmgr_psoc *psoc; 3628 uint8_t *bufp; 3629 qdf_nbuf_t wbuf; 3630 QDF_STATUS status; 3631 3632 if (wma_validate_handle(wma_handle)) 3633 return -EINVAL; 3634 3635 mgmt_rx_params = qdf_mem_malloc(sizeof(*mgmt_rx_params)); 3636 if (!mgmt_rx_params) { 3637 wma_err("memory allocation failed"); 3638 return -ENOMEM; 3639 } 3640 3641 if (wmi_extract_mgmt_rx_params(wma_handle->wmi_handle, 3642 data, mgmt_rx_params, &bufp) != QDF_STATUS_SUCCESS) { 3643 wma_err("Extraction of mgmt rx params failed"); 3644 qdf_mem_free(mgmt_rx_params); 3645 return -EINVAL; 3646 } 3647 3648 if (mgmt_rx_params->buf_len > data_len || 3649 !mgmt_rx_params->buf_len || 3650 !bufp) { 3651 wma_err("Invalid data_len %u, buf_len %u bufp %pK", 3652 data_len, mgmt_rx_params->buf_len, bufp); 3653 qdf_mem_free(mgmt_rx_params); 3654 return -EINVAL; 3655 } 3656 3657 if (!mgmt_rx_params->chan_freq) { 3658 /* 3659 * It indicates that FW is legacy and is operating on 3660 * channel numbers and it also indicates that BAND_6G support 3661 * is not there as BAND_6G works only on frequencies and channel 3662 * numbers can be treated as unique. 3663 */ 3664 mgmt_rx_params->chan_freq = wlan_reg_legacy_chan_to_freq( 3665 wma_handle->pdev, 3666 mgmt_rx_params->channel); 3667 } 3668 3669 mgmt_rx_params->pdev_id = 0; 3670 mgmt_rx_params->rx_params = NULL; 3671 3672 /* 3673 * Allocate the memory for this rx packet, add extra 100 bytes for:- 3674 * 3675 * 1. Filling the missing RSN capabilites by some APs, which fill the 3676 * RSN IE length as extra 2 bytes but dont fill the IE data with 3677 * capabilities, resulting in failure in unpack core due to length 3678 * mismatch. Check sir_validate_and_rectify_ies for more info. 3679 * 3680 * 2. In the API wma_process_rmf_frame(), the driver trims the CCMP 3681 * header by overwriting the IEEE header to memory occupied by CCMP 3682 * header, but an overflow is possible if the memory allocated to 3683 * frame is less than the sizeof(struct ieee80211_frame) +CCMP 3684 * HEADER len, so allocating 100 bytes would solve this issue too. 3685 * 3686 * 3. CCMP header is pointing to orig_hdr + 3687 * sizeof(struct ieee80211_frame) which could also result in OOB 3688 * access, if the data len is less than 3689 * sizeof(struct ieee80211_frame), allocating extra bytes would 3690 * result in solving this issue too. 3691 */ 3692 wbuf = qdf_nbuf_alloc(NULL, roundup(mgmt_rx_params->buf_len + 3693 RESERVE_BYTES, 3694 4), 0, 4, false); 3695 if (!wbuf) { 3696 qdf_mem_free(mgmt_rx_params); 3697 return -ENOMEM; 3698 } 3699 3700 qdf_nbuf_put_tail(wbuf, mgmt_rx_params->buf_len); 3701 qdf_nbuf_set_protocol(wbuf, ETH_P_CONTROL); 3702 3703 qdf_mem_zero(((uint8_t *)qdf_nbuf_data(wbuf) + mgmt_rx_params->buf_len), 3704 (roundup(mgmt_rx_params->buf_len + RESERVE_BYTES, 4) - 3705 mgmt_rx_params->buf_len)); 3706 3707 wma_mem_endianness_based_copy(qdf_nbuf_data(wbuf), 3708 bufp, mgmt_rx_params->buf_len); 3709 3710 psoc = (struct wlan_objmgr_psoc *) 3711 wma_handle->psoc; 3712 if (!psoc) { 3713 wma_err("psoc ctx is NULL"); 3714 qdf_nbuf_free(wbuf); 3715 qdf_mem_free(mgmt_rx_params); 3716 return -EINVAL; 3717 } 3718 3719 status = mgmt_txrx_rx_handler(psoc, wbuf, mgmt_rx_params); 3720 if (status != QDF_STATUS_SUCCESS) { 3721 qdf_mem_free(mgmt_rx_params); 3722 return -EINVAL; 3723 } 3724 3725 qdf_mem_free(mgmt_rx_params); 3726 return 0; 3727 } 3728 3729 /** 3730 * wma_de_register_mgmt_frm_client() - deregister management frame 3731 * 3732 * This function deregisters the event handler registered for 3733 * WMI_MGMT_RX_EVENTID. 3734 * 3735 * Return: QDF status 3736 */ 3737 QDF_STATUS wma_de_register_mgmt_frm_client(void) 3738 { 3739 tp_wma_handle wma_handle = (tp_wma_handle) 3740 cds_get_context(QDF_MODULE_ID_WMA); 3741 3742 if (!wma_handle) 3743 return QDF_STATUS_E_NULL_VALUE; 3744 3745 #ifdef QCA_WIFI_FTM 3746 if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE) 3747 return QDF_STATUS_SUCCESS; 3748 #endif 3749 3750 if (wmi_unified_unregister_event_handler(wma_handle->wmi_handle, 3751 wmi_mgmt_rx_event_id) != 0) { 3752 wma_err("Failed to Unregister rx mgmt handler with wmi"); 3753 return QDF_STATUS_E_FAILURE; 3754 } 3755 return QDF_STATUS_SUCCESS; 3756 } 3757 3758 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 3759 /** 3760 * wma_register_roaming_callbacks() - Register roaming callbacks 3761 * @csr_roam_synch_cb: CSR roam synch callback routine pointer 3762 * @csr_roam_auth_event_handle_cb: CSR callback routine pointer 3763 * @pe_roam_synch_cb: PE roam synch callback routine pointer 3764 * 3765 * Register the SME and PE callback routines with WMA for 3766 * handling roaming 3767 * 3768 * Return: Success or Failure Status 3769 */ 3770 QDF_STATUS wma_register_roaming_callbacks( 3771 #ifndef FEATURE_CM_ENABLE 3772 csr_roam_synch_fn_t csr_roam_synch_cb, 3773 #endif 3774 QDF_STATUS (*csr_roam_auth_event_handle_cb)(struct mac_context *mac, 3775 uint8_t vdev_id, 3776 struct qdf_mac_addr bssid), 3777 pe_roam_synch_fn_t pe_roam_synch_cb, 3778 QDF_STATUS (*pe_disconnect_cb) (struct mac_context *mac, 3779 uint8_t vdev_id, 3780 uint8_t *deauth_disassoc_frame, 3781 uint16_t deauth_disassoc_frame_len, 3782 uint16_t reason_code)) 3783 { 3784 3785 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); 3786 3787 if (!wma) 3788 return QDF_STATUS_E_FAILURE; 3789 3790 #ifndef FEATURE_CM_ENABLE 3791 wma->csr_roam_synch_cb = csr_roam_synch_cb; 3792 #endif 3793 wma->csr_roam_auth_event_handle_cb = csr_roam_auth_event_handle_cb; 3794 wma->pe_roam_synch_cb = pe_roam_synch_cb; 3795 wma->pe_disconnect_cb = pe_disconnect_cb; 3796 wma_debug("Registered roam synch callbacks with WMA successfully"); 3797 3798 return QDF_STATUS_SUCCESS; 3799 } 3800 #endif 3801 3802 /** 3803 * wma_register_mgmt_frm_client() - register management frame callback 3804 * 3805 * This function registers event handler for WMI_MGMT_RX_EVENTID. 3806 * 3807 * Return: QDF status 3808 */ 3809 QDF_STATUS wma_register_mgmt_frm_client(void) 3810 { 3811 tp_wma_handle wma_handle = (tp_wma_handle) 3812 cds_get_context(QDF_MODULE_ID_WMA); 3813 3814 if (!wma_handle) 3815 return QDF_STATUS_E_NULL_VALUE; 3816 3817 if (wmi_unified_register_event_handler(wma_handle->wmi_handle, 3818 wmi_mgmt_rx_event_id, 3819 wma_mgmt_rx_process, 3820 WMA_RX_WORK_CTX) != 0) { 3821 wma_err("Failed to register rx mgmt handler with wmi"); 3822 return QDF_STATUS_E_FAILURE; 3823 } 3824 3825 return QDF_STATUS_SUCCESS; 3826 } 3827 3828 /** 3829 * wma_register_packetdump_callback() - stores tx and rx mgmt packet dump 3830 * callback handler 3831 * @tx_cb: tx mgmt packetdump cb 3832 * @rx_cb: rx mgmt packetdump cb 3833 * 3834 * This function is used to store tx and rx mgmt. packet dump callback 3835 * 3836 * Return: None 3837 * 3838 */ 3839 void wma_register_packetdump_callback( 3840 ol_txrx_pktdump_cb tx_cb, 3841 ol_txrx_pktdump_cb rx_cb) 3842 { 3843 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 3844 3845 if (!wma_handle) 3846 return; 3847 3848 wma_handle->wma_mgmt_tx_packetdump_cb = tx_cb; 3849 wma_handle->wma_mgmt_rx_packetdump_cb = rx_cb; 3850 } 3851 3852 /** 3853 * wma_deregister_packetdump_callback() - removes tx and rx mgmt packet dump 3854 * callback handler 3855 * 3856 * This function is used to remove tx and rx mgmt. packet dump callback 3857 * 3858 * Return: None 3859 * 3860 */ 3861 void wma_deregister_packetdump_callback(void) 3862 { 3863 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 3864 3865 if (!wma_handle) 3866 return; 3867 3868 wma_handle->wma_mgmt_tx_packetdump_cb = NULL; 3869 wma_handle->wma_mgmt_rx_packetdump_cb = NULL; 3870 } 3871 3872 QDF_STATUS wma_mgmt_unified_cmd_send(struct wlan_objmgr_vdev *vdev, 3873 qdf_nbuf_t buf, uint32_t desc_id, 3874 void *mgmt_tx_params) 3875 { 3876 tp_wma_handle wma_handle; 3877 int ret; 3878 QDF_STATUS status = QDF_STATUS_E_INVAL; 3879 struct wmi_mgmt_params *mgmt_params = 3880 (struct wmi_mgmt_params *)mgmt_tx_params; 3881 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 3882 3883 if (!mgmt_params) { 3884 wma_err("mgmt_params ptr passed is NULL"); 3885 return QDF_STATUS_E_INVAL; 3886 } 3887 mgmt_params->desc_id = desc_id; 3888 3889 if (!vdev) { 3890 wma_err("vdev ptr passed is NULL"); 3891 return QDF_STATUS_E_INVAL; 3892 } 3893 3894 wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 3895 if (!wma_handle) 3896 return QDF_STATUS_E_INVAL; 3897 3898 if (wmi_service_enabled(wma_handle->wmi_handle, 3899 wmi_service_mgmt_tx_wmi)) { 3900 status = wmi_mgmt_unified_cmd_send(wma_handle->wmi_handle, 3901 mgmt_params); 3902 } else { 3903 QDF_NBUF_CB_MGMT_TXRX_DESC_ID(buf) 3904 = mgmt_params->desc_id; 3905 3906 ret = cdp_mgmt_send_ext(soc, mgmt_params->vdev_id, buf, 3907 mgmt_params->tx_type, 3908 mgmt_params->use_6mbps, 3909 mgmt_params->chanfreq); 3910 status = qdf_status_from_os_return(ret); 3911 } 3912 3913 if (status != QDF_STATUS_SUCCESS) { 3914 wma_err("mgmt tx failed"); 3915 return status; 3916 } 3917 3918 return QDF_STATUS_SUCCESS; 3919 } 3920 3921 #ifndef CONFIG_HL_SUPPORT 3922 void wma_mgmt_nbuf_unmap_cb(struct wlan_objmgr_pdev *pdev, 3923 qdf_nbuf_t buf) 3924 { 3925 struct wlan_objmgr_psoc *psoc; 3926 qdf_device_t dev; 3927 3928 if (!buf) 3929 return; 3930 3931 psoc = wlan_pdev_get_psoc(pdev); 3932 if (!psoc) { 3933 wma_err("Psoc handle NULL"); 3934 return; 3935 } 3936 3937 dev = wlan_psoc_get_qdf_dev(psoc); 3938 qdf_nbuf_unmap_single(dev, buf, QDF_DMA_TO_DEVICE); 3939 } 3940 3941 QDF_STATUS wma_mgmt_frame_fill_peer_cb(struct wlan_objmgr_peer *peer, 3942 qdf_nbuf_t buf) 3943 { 3944 struct wlan_objmgr_psoc *psoc; 3945 struct wlan_objmgr_pdev *pdev; 3946 3947 psoc = wlan_peer_get_psoc(peer); 3948 if (!psoc) { 3949 wma_err("Psoc handle NULL"); 3950 return QDF_STATUS_E_INVAL; 3951 } 3952 3953 pdev = wlan_objmgr_get_pdev_by_id((struct wlan_objmgr_psoc *)psoc, 3954 wlan_peer_get_pdev_id(peer), 3955 WLAN_LEGACY_WMA_ID); 3956 if (!pdev) { 3957 wma_err("Pdev handle NULL"); 3958 return QDF_STATUS_E_INVAL; 3959 } 3960 wma_mgmt_nbuf_unmap_cb(pdev, buf); 3961 wlan_objmgr_pdev_release_ref(pdev, WLAN_LEGACY_WMA_ID); 3962 3963 return QDF_STATUS_SUCCESS; 3964 } 3965 #endif 3966