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