1 /* 2 * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-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: wlan_hdd_p2p.c 22 * 23 * WLAN Host Device Driver implementation for P2P commands interface 24 */ 25 26 #include "osif_sync.h" 27 #include <wlan_hdd_includes.h> 28 #include <wlan_hdd_hostapd.h> 29 #include <net/cfg80211.h> 30 #include "sme_api.h" 31 #include "sme_qos_api.h" 32 #include "wlan_hdd_p2p.h" 33 #include "sap_api.h" 34 #include "wlan_hdd_main.h" 35 #include "qdf_trace.h" 36 #include <linux/netdevice.h> 37 #include <linux/skbuff.h> 38 #include <linux/etherdevice.h> 39 #include <net/ieee80211_radiotap.h> 40 #include "wlan_hdd_tdls.h" 41 #include "wlan_hdd_trace.h" 42 #include "qdf_types.h" 43 #include "qdf_trace.h" 44 #include "cds_sched.h" 45 #include "wlan_policy_mgr_api.h" 46 #include "cds_utils.h" 47 #include "wlan_p2p_public_struct.h" 48 #include "wlan_p2p_ucfg_api.h" 49 #include "wlan_cfg80211_p2p.h" 50 #include "wlan_p2p_cfg_api.h" 51 #include "wlan_policy_mgr_ucfg.h" 52 #include "nan_ucfg_api.h" 53 #include "wlan_pkt_capture_ucfg_api.h" 54 #include "wlan_hdd_object_manager.h" 55 #include "wlan_hdd_pre_cac.h" 56 #include "wlan_pre_cac_ucfg_api.h" 57 #include "wlan_dp_ucfg_api.h" 58 #include "wlan_psoc_mlme_ucfg_api.h" 59 #include "os_if_dp_local_pkt_capture.h" 60 61 /* Ms to Time Unit Micro Sec */ 62 #define MS_TO_TU_MUS(x) ((x) * 1024) 63 #define MAX_MUS_VAL (INT_MAX / 1024) 64 65 /* Clean up RoC context at hdd_stop_adapter*/ 66 void 67 wlan_hdd_cleanup_remain_on_channel_ctx(struct wlan_hdd_link_info *link_info) 68 { 69 struct wlan_objmgr_vdev *vdev; 70 71 vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_P2P_ID); 72 if (!vdev) 73 return; 74 75 ucfg_p2p_cleanup_roc_by_vdev(vdev); 76 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_P2P_ID); 77 } 78 79 void wlan_hdd_cleanup_actionframe(struct wlan_hdd_link_info *link_info) 80 { 81 struct wlan_objmgr_vdev *vdev; 82 83 vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_P2P_ID); 84 if (!vdev) 85 return; 86 ucfg_p2p_cleanup_tx_by_vdev(vdev); 87 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_P2P_ID); 88 } 89 90 static int __wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy, 91 struct wireless_dev *wdev, 92 struct ieee80211_channel *chan, 93 unsigned int duration, 94 u64 *cookie) 95 { 96 struct net_device *dev = wdev->netdev; 97 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 98 struct hdd_context *hdd_ctx; 99 struct wlan_objmgr_vdev *vdev; 100 QDF_STATUS status; 101 int ret; 102 103 hdd_enter(); 104 105 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 106 ret = wlan_hdd_validate_context(hdd_ctx); 107 if (0 != ret) 108 return ret; 109 110 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { 111 hdd_err("Command not allowed in FTM mode"); 112 return -EINVAL; 113 } 114 115 wlan_hdd_lpc_handle_concurrency(hdd_ctx, false); 116 if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc) && 117 !hdd_lpc_is_work_scheduled(hdd_ctx)) 118 return -EINVAL; 119 120 if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id)) 121 return -EINVAL; 122 123 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_P2P_ID); 124 if (!vdev) { 125 hdd_err("vdev is NULL"); 126 return -EINVAL; 127 } 128 129 if (!wlan_is_scan_allowed(vdev)) { 130 wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_P2P_ID); 131 return -EBUSY; 132 } 133 134 /* Disable NAN Discovery if enabled */ 135 ucfg_nan_disable_concurrency(hdd_ctx->psoc); 136 137 status = wlan_cfg80211_roc(vdev, chan, duration, cookie); 138 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_P2P_ID); 139 hdd_debug("remain on channel request, status:%d, cookie:0x%llx", 140 status, *cookie); 141 142 return qdf_status_to_os_return(status); 143 } 144 145 int wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy, 146 struct wireless_dev *wdev, 147 struct ieee80211_channel *chan, 148 unsigned int duration, u64 *cookie) 149 { 150 int errno; 151 struct osif_vdev_sync *vdev_sync; 152 153 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync); 154 if (errno) 155 return errno; 156 157 errno = __wlan_hdd_cfg80211_remain_on_channel(wiphy, wdev, chan, 158 duration, cookie); 159 160 osif_vdev_sync_op_stop(vdev_sync); 161 162 return errno; 163 } 164 165 static int 166 __wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, 167 struct wireless_dev *wdev, 168 u64 cookie) 169 { 170 QDF_STATUS status; 171 struct net_device *dev = wdev->netdev; 172 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 173 struct wlan_objmgr_vdev *vdev; 174 175 hdd_enter(); 176 177 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { 178 hdd_err("Command not allowed in FTM mode"); 179 return -EINVAL; 180 } 181 182 if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id)) 183 return -EINVAL; 184 185 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_P2P_ID); 186 if (!vdev) { 187 hdd_err("vdev is NULL"); 188 return -EINVAL; 189 } 190 191 status = wlan_cfg80211_cancel_roc(vdev, cookie); 192 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_P2P_ID); 193 194 hdd_debug("cancel remain on channel, status:%d", status); 195 196 return 0; 197 } 198 199 int wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, 200 struct wireless_dev *wdev, 201 u64 cookie) 202 { 203 int errno; 204 struct osif_vdev_sync *vdev_sync; 205 206 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync); 207 if (errno) 208 return errno; 209 210 errno = __wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy, wdev, 211 cookie); 212 213 osif_vdev_sync_op_stop(vdev_sync); 214 215 return errno; 216 } 217 218 #define WLAN_AUTH_FRAME_MIN_LEN 2 219 static int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, 220 struct ieee80211_channel *chan, bool offchan, 221 unsigned int wait, 222 const u8 *buf, size_t len, bool no_cck, 223 bool dont_wait_for_ack, u64 *cookie) 224 { 225 QDF_STATUS status; 226 struct net_device *dev = wdev->netdev; 227 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 228 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); 229 struct wlan_objmgr_vdev *vdev; 230 uint8_t type, sub_type; 231 uint16_t auth_algo; 232 QDF_STATUS qdf_status; 233 int ret; 234 uint32_t assoc_resp_len, ft_info_len = 0; 235 const uint8_t *assoc_resp; 236 void *ft_info; 237 struct hdd_ap_ctx *ap_ctx; 238 239 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { 240 hdd_err("Command not allowed in FTM mode"); 241 return -EINVAL; 242 } 243 244 if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id)) 245 return -EINVAL; 246 247 ret = wlan_hdd_validate_context(hdd_ctx); 248 if (ret) 249 return ret; 250 251 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]); 252 sub_type = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]); 253 hdd_debug("type %d, sub_type %d", type, sub_type); 254 255 /* When frame to be transmitted is auth mgmt, then trigger 256 * sme_send_mgmt_tx to send auth frame without need for policy manager. 257 * Where as wlan_cfg80211_mgmt_tx requires roc and requires approval 258 * from policy manager. 259 */ 260 if ((adapter->device_mode == QDF_STA_MODE || 261 adapter->device_mode == QDF_SAP_MODE || 262 adapter->device_mode == QDF_P2P_CLIENT_MODE || 263 adapter->device_mode == QDF_P2P_GO_MODE || 264 adapter->device_mode == QDF_NAN_DISC_MODE) && 265 (type == SIR_MAC_MGMT_FRAME && 266 sub_type == SIR_MAC_MGMT_AUTH)) { 267 /* Request ROC for PASN authentication frame */ 268 if (len > (sizeof(struct wlan_frame_hdr) + 269 WLAN_AUTH_FRAME_MIN_LEN)) { 270 auth_algo = 271 *(uint16_t *)(buf + 272 sizeof(struct wlan_frame_hdr)); 273 if (auth_algo == eSIR_AUTH_TYPE_PASN) 274 goto off_chan_tx; 275 if ((auth_algo == eSIR_FT_AUTH) && 276 (adapter->device_mode == QDF_SAP_MODE || 277 adapter->device_mode == QDF_P2P_GO_MODE)) { 278 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink); 279 ap_ctx->during_auth_offload = false; 280 } 281 } 282 283 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_SME, 284 TRACE_CODE_HDD_SEND_MGMT_TX, 285 adapter->deflink->vdev_id, 0); 286 287 qdf_status = sme_send_mgmt_tx(hdd_ctx->mac_handle, 288 adapter->deflink->vdev_id, 289 buf, len); 290 291 if (QDF_IS_STATUS_SUCCESS(qdf_status)) 292 return qdf_status_to_os_return(qdf_status); 293 else 294 return -EINVAL; 295 } 296 /* Only when SAP working on Fast BSS transition mode. Driver offload 297 * (re)assoc request to hostapd. Here driver receive (re)assoc response 298 * frame from hostapd. 299 */ 300 if ((adapter->device_mode == QDF_SAP_MODE || 301 adapter->device_mode == QDF_P2P_GO_MODE) && 302 (type == SIR_MAC_MGMT_FRAME) && 303 (sub_type == SIR_MAC_MGMT_ASSOC_RSP || 304 sub_type == SIR_MAC_MGMT_REASSOC_RSP)) { 305 assoc_resp = &((struct ieee80211_mgmt *)buf)->u.assoc_resp.variable[0]; 306 assoc_resp_len = len - WLAN_ASSOC_RSP_IES_OFFSET 307 - sizeof(struct wlan_frame_hdr); 308 if (!wlan_get_ie_ptr_from_eid(DOT11F_EID_FTINFO, 309 assoc_resp, assoc_resp_len)) { 310 hdd_debug("No FT info in Assoc rsp, send it directly"); 311 goto off_chan_tx; 312 } 313 ft_info = hdd_filter_ft_info(assoc_resp, len, &ft_info_len); 314 if (!ft_info || !ft_info_len) 315 return -EINVAL; 316 hdd_debug("get ft_info_len from Assoc rsp :%d", ft_info_len); 317 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink); 318 qdf_status = wlansap_update_ft_info(ap_ctx->sap_context, 319 ((struct ieee80211_mgmt *)buf)->da, 320 ft_info, ft_info_len, 0); 321 qdf_mem_free(ft_info); 322 323 if (QDF_IS_STATUS_SUCCESS(qdf_status)) 324 return qdf_status_to_os_return(qdf_status); 325 else 326 return -EINVAL; 327 } 328 329 off_chan_tx: 330 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_P2P_ID); 331 if (!vdev) { 332 hdd_err("vdev is NULL"); 333 return -EINVAL; 334 } 335 336 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_OS_IF, 337 TRACE_CODE_HDD_SEND_MGMT_TX, 338 wlan_vdev_get_id(vdev), 0); 339 340 status = wlan_cfg80211_mgmt_tx(vdev, chan, offchan, wait, buf, 341 len, no_cck, dont_wait_for_ack, cookie); 342 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_P2P_ID); 343 hdd_debug("device_mode:%d type:%d sub_type:%d chan:%d wait:%d offchan:%d do_not_wait_ack:%d mgmt tx, status:%d, cookie:0x%llx", 344 adapter->device_mode, type, sub_type, 345 chan ? chan->center_freq : 0, wait, offchan, 346 dont_wait_for_ack, status, *cookie); 347 348 return 0; 349 } 350 351 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) 352 int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, 353 struct cfg80211_mgmt_tx_params *params, u64 *cookie) 354 #else 355 int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, 356 struct ieee80211_channel *chan, bool offchan, 357 unsigned int wait, 358 const u8 *buf, size_t len, bool no_cck, 359 bool dont_wait_for_ack, u64 *cookie) 360 #endif /* LINUX_VERSION_CODE */ 361 { 362 int errno; 363 struct osif_vdev_sync *vdev_sync; 364 365 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync); 366 if (errno) 367 return errno; 368 369 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) 370 errno = __wlan_hdd_mgmt_tx(wiphy, wdev, params->chan, params->offchan, 371 params->wait, params->buf, params->len, 372 params->no_cck, params->dont_wait_for_ack, 373 cookie); 374 #else 375 errno = __wlan_hdd_mgmt_tx(wiphy, wdev, chan, offchan, 376 wait, buf, len, no_cck, 377 dont_wait_for_ack, cookie); 378 #endif /* LINUX_VERSION_CODE */ 379 380 osif_vdev_sync_op_stop(vdev_sync); 381 382 return errno; 383 } 384 385 static int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, 386 struct wireless_dev *wdev, 387 u64 cookie) 388 { 389 QDF_STATUS status; 390 struct net_device *dev = wdev->netdev; 391 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 392 struct wlan_objmgr_vdev *vdev; 393 394 hdd_enter(); 395 396 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { 397 hdd_err("Command not allowed in FTM mode"); 398 return -EINVAL; 399 } 400 401 if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id)) 402 return -EINVAL; 403 404 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_P2P_ID); 405 if (!vdev) { 406 hdd_err("vdev is NULL"); 407 return -EINVAL; 408 } 409 410 status = wlan_cfg80211_mgmt_tx_cancel(vdev, cookie); 411 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_P2P_ID); 412 413 hdd_debug("cancel mgmt tx, status:%d", status); 414 415 return 0; 416 } 417 418 int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, 419 struct wireless_dev *wdev, u64 cookie) 420 { 421 int errno; 422 struct osif_vdev_sync *vdev_sync; 423 424 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync); 425 if (errno) 426 return errno; 427 428 errno = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, cookie); 429 430 osif_vdev_sync_op_stop(vdev_sync); 431 432 return errno; 433 } 434 435 /** 436 * hdd_set_p2p_noa() - Handle P2P_SET_NOA command 437 * @dev: Pointer to net device structure 438 * @command: Pointer to command 439 * 440 * This function is called from hdd_hostapd_ioctl function when Driver 441 * get P2P_SET_NOA command from wpa_supplicant using private ioctl 442 * 443 * This function will construct the NoA Struct According to P2P Power 444 * save Option and Pass it to SME layer 445 * 446 * Return: 0 on success, negative errno if error 447 */ 448 449 int hdd_set_p2p_noa(struct net_device *dev, uint8_t *command) 450 { 451 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 452 struct p2p_ps_config noa = {0}; 453 int count, duration, interval, start = 0; 454 char *param; 455 int ret; 456 457 param = strnchr(command, strlen(command), ' '); 458 if (!param) { 459 hdd_err("strnchr failed to find delimiter"); 460 return -EINVAL; 461 } 462 param++; 463 ret = sscanf(param, "%d %d %d %d", &count, &start, &duration, 464 &interval); 465 if (ret < 3) { 466 hdd_err("P2P_SET GO noa: fail to read params, ret=%d", 467 ret); 468 return -EINVAL; 469 } 470 471 if (ret == 3) 472 interval = 100; 473 474 if (start < 0 || count < 0 || interval < 0 || duration < 0 || 475 start > MAX_MUS_VAL || interval > MAX_MUS_VAL || 476 duration > MAX_MUS_VAL) { 477 hdd_err("Invalid NOA parameters"); 478 return -EINVAL; 479 } 480 hdd_debug("P2P_SET GO noa: count=%d interval=%d duration=%d start=%d", 481 count, interval, duration, start); 482 duration = MS_TO_TU_MUS(duration); 483 interval = MS_TO_TU_MUS(interval); 484 /* PS Selection 485 * Periodic noa (2) 486 * Single NOA (4) 487 */ 488 noa.opp_ps = 0; 489 noa.ct_window = 0; 490 if (count == 1) { 491 if (duration > interval) 492 duration = interval; 493 noa.duration = 0; 494 noa.single_noa_duration = duration; 495 noa.ps_selection = P2P_POWER_SAVE_TYPE_SINGLE_NOA; 496 } else { 497 if (count && (duration >= interval)) { 498 hdd_err("Duration should be less than interval"); 499 return -EINVAL; 500 } 501 noa.duration = duration; 502 noa.single_noa_duration = 0; 503 noa.ps_selection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA; 504 } 505 506 noa.start = start; 507 noa.interval = interval; 508 noa.count = count; 509 noa.vdev_id = adapter->deflink->vdev_id; 510 511 hdd_debug("P2P_PS_ATTR:opp ps %d ct window %d count %d interval %d " 512 "duration %d start %d single noa duration %d " 513 "ps selection %x", noa.opp_ps, noa.ct_window, noa.count, 514 noa.interval, noa.duration, noa.start, 515 noa.single_noa_duration, noa.ps_selection); 516 517 return wlan_hdd_set_power_save(adapter, &noa); 518 } 519 520 /** 521 * hdd_set_p2p_opps() - Handle P2P_SET_PS command 522 * @dev: Pointer to net device structure 523 * @command: Pointer to command 524 * 525 * This function is called from hdd_hostapd_ioctl function when Driver 526 * get P2P_SET_PS command from wpa_supplicant using private ioctl. 527 * 528 * This function will construct the NoA Struct According to P2P Power 529 * save Option and Pass it to SME layer 530 * 531 * Return: 0 on success, negative errno if error 532 */ 533 534 int hdd_set_p2p_opps(struct net_device *dev, uint8_t *command) 535 { 536 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 537 struct p2p_ps_config noa = {0}; 538 char *param; 539 int legacy_ps, opp_ps, ctwindow; 540 int ret; 541 542 param = strnchr(command, strlen(command), ' '); 543 if (!param) { 544 hdd_err("strnchr failed to find delimiter"); 545 return -EINVAL; 546 } 547 param++; 548 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow); 549 if (ret != 3) { 550 hdd_err("P2P_SET GO PS: fail to read params, ret=%d", ret); 551 return -EINVAL; 552 } 553 554 if ((opp_ps != -1) && (opp_ps != 0) && (opp_ps != 1)) { 555 hdd_err("Invalid opp_ps value:%d", opp_ps); 556 return -EINVAL; 557 } 558 559 /* P2P spec: 3.3.2 Power Management and discovery: 560 * CTWindow should be at least 10 TU. 561 * P2P spec: Table 27 - CTWindow and OppPS Parameters field format: 562 * CTWindow and OppPS Parameters together is 8 bits. 563 * CTWindow uses 7 bits (0-6, Bit 7 is for OppPS) 564 * 0 indicates that there shall be no CTWindow 565 */ 566 if ((ctwindow != -1) && (ctwindow != 0) && 567 (!((ctwindow >= 10) && (ctwindow <= 127)))) { 568 hdd_err("Invalid CT window value:%d", ctwindow); 569 return -EINVAL; 570 } 571 572 hdd_debug("P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d", 573 legacy_ps, opp_ps, ctwindow); 574 575 /* PS Selection 576 * Opportunistic Power Save (1) 577 */ 578 579 /* From wpa_cli user need to use separate command to set ct_window 580 * and Opps when user want to set ct_window during that time other 581 * parameters values are coming from wpa_supplicant as -1. 582 * Example : User want to set ct_window with 30 then wpa_cli command : 583 * P2P_SET ctwindow 30 584 * Command Received at hdd_hostapd_ioctl is as below: 585 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30) 586 * 587 * e.g., 1: P2P_SET_PS 1 1 30 588 * Driver sets the Opps and CTwindow as 30 and send it to FW. 589 * e.g., 2: P2P_SET_PS 1 -1 15 590 * Driver caches the CTwindow value but not send the command to FW. 591 * e.g., 3: P2P_SET_PS 1 1 -1 592 * Driver sends the command to FW with Opps enabled and CT window as 593 * 15 (last cached CTWindow value). 594 * (or) : P2P_SET_PS 1 1 20 595 * Driver sends the command to FW with opps enabled and CT window 596 * as 20. 597 * 598 * legacy_ps param remains unused until required in the future. 599 */ 600 if (ctwindow != -1) 601 adapter->ctw = ctwindow; 602 603 /* Send command to FW when OppPS is either enabled(1)/disabled(0) */ 604 if (opp_ps != -1) { 605 adapter->ops = opp_ps; 606 noa.opp_ps = adapter->ops; 607 noa.ct_window = adapter->ctw; 608 noa.duration = 0; 609 noa.single_noa_duration = 0; 610 noa.interval = 0; 611 noa.count = 0; 612 noa.ps_selection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC; 613 noa.vdev_id = adapter->deflink->vdev_id; 614 615 hdd_debug("P2P_PS_ATTR: opp ps %d ct window %d duration %d interval %d count %d single noa duration %d ps selection %x", 616 noa.opp_ps, noa.ct_window, 617 noa.duration, noa.interval, noa.count, 618 noa.single_noa_duration, 619 noa.ps_selection); 620 621 wlan_hdd_set_power_save(adapter, &noa); 622 } 623 624 return 0; 625 } 626 627 int hdd_set_p2p_ps(struct net_device *dev, void *msgData) 628 { 629 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 630 struct p2p_ps_config noa = {0}; 631 struct p2p_app_set_ps *pappnoa = (struct p2p_app_set_ps *) msgData; 632 633 noa.opp_ps = pappnoa->opp_ps; 634 noa.ct_window = pappnoa->ct_window; 635 noa.duration = pappnoa->duration; 636 noa.interval = pappnoa->interval; 637 noa.count = pappnoa->count; 638 noa.single_noa_duration = pappnoa->single_noa_duration; 639 noa.ps_selection = pappnoa->ps_selection; 640 noa.vdev_id = adapter->deflink->vdev_id; 641 642 return wlan_hdd_set_power_save(adapter, &noa); 643 } 644 645 bool hdd_allow_new_intf(struct hdd_context *hdd_ctx, 646 enum QDF_OPMODE mode) 647 { 648 struct hdd_adapter *adapter = NULL; 649 struct hdd_adapter *next_adapter = NULL; 650 uint8_t num_active_adapter = 0; 651 652 if (mode != QDF_SAP_MODE) 653 return true; 654 655 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter, 656 NET_DEV_HOLD_ALLOW_NEW_INTF) { 657 if (hdd_is_interface_up(adapter) && 658 adapter->device_mode == mode) 659 num_active_adapter++; 660 661 hdd_adapter_dev_put_debug(adapter, 662 NET_DEV_HOLD_ALLOW_NEW_INTF); 663 } 664 665 if (num_active_adapter >= QDF_MAX_NO_OF_SAP_MODE) 666 hdd_err("sap max allowed intf %d, curr %d", 667 QDF_MAX_NO_OF_SAP_MODE, num_active_adapter); 668 669 return num_active_adapter < QDF_MAX_NO_OF_SAP_MODE; 670 } 671 672 /** 673 * __wlan_hdd_add_virtual_intf() - Add virtual interface 674 * @wiphy: wiphy pointer 675 * @name: User-visible name of the interface 676 * @name_assign_type: the name of assign type of the netdev 677 * @type: (virtual) interface types 678 * @flags: monitor configuration flags 679 * @params: virtual interface parameters (not used) 680 * 681 * Return: the pointer of wireless dev, otherwise ERR_PTR. 682 */ 683 static 684 struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy, 685 const char *name, 686 unsigned char name_assign_type, 687 enum nl80211_iftype type, 688 u32 *flags, 689 struct vif_params *params) 690 { 691 struct hdd_context *hdd_ctx = wiphy_priv(wiphy); 692 struct hdd_adapter *adapter = NULL; 693 bool p2p_dev_addr_admin = false; 694 enum QDF_OPMODE mode; 695 QDF_STATUS status; 696 struct wlan_objmgr_vdev *vdev; 697 int ret; 698 struct hdd_adapter_create_param create_params = {0}; 699 uint8_t *device_address = NULL; 700 701 hdd_enter(); 702 703 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) { 704 hdd_err("Command not allowed in FTM mode"); 705 return ERR_PTR(-EINVAL); 706 } 707 708 if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE) { 709 hdd_err("Concurrency not allowed with standalone monitor mode"); 710 return ERR_PTR(-EINVAL); 711 } 712 713 ret = wlan_hdd_validate_context(hdd_ctx); 714 if (ret) 715 return ERR_PTR(ret); 716 717 status = hdd_nl_to_qdf_iface_type(type, &mode); 718 if (QDF_IS_STATUS_ERROR(status)) 719 return ERR_PTR(qdf_status_to_os_return(status)); 720 721 if (mode == QDF_MONITOR_MODE && 722 !(QDF_MONITOR_FLAG_OTHER_BSS & *flags) && 723 !os_if_lpc_mon_intf_creation_allowed(hdd_ctx->psoc)) 724 return ERR_PTR(-EOPNOTSUPP); 725 726 wlan_hdd_lpc_handle_concurrency(hdd_ctx, true); 727 728 if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc) && 729 !hdd_lpc_is_work_scheduled(hdd_ctx)) 730 return ERR_PTR(-EINVAL); 731 732 if (wlan_hdd_is_mon_concurrency()) 733 return ERR_PTR(-EINVAL); 734 735 if (!hdd_allow_new_intf(hdd_ctx, mode)) 736 return ERR_PTR(-EOPNOTSUPP); 737 738 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD, 739 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, 740 NO_SESSION, type); 741 742 switch (mode) { 743 case QDF_SAP_MODE: 744 case QDF_P2P_GO_MODE: 745 case QDF_P2P_CLIENT_MODE: 746 case QDF_STA_MODE: 747 case QDF_MONITOR_MODE: 748 break; 749 default: 750 mode = QDF_STA_MODE; 751 break; 752 } 753 754 create_params.is_add_virtual_iface = 1; 755 756 adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE); 757 if (adapter && !wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id)) { 758 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, 759 WLAN_OSIF_P2P_ID); 760 if (vdev) { 761 if (ucfg_scan_get_vdev_status(vdev) != 762 SCAN_NOT_IN_PROGRESS) { 763 wlan_abort_scan(hdd_ctx->pdev, INVAL_PDEV_ID, 764 adapter->deflink->vdev_id, 765 INVALID_SCAN_ID, false); 766 } 767 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_P2P_ID); 768 } else { 769 hdd_err("vdev is NULL"); 770 } 771 } 772 773 adapter = NULL; 774 if (type == NL80211_IFTYPE_MONITOR) { 775 /* 776 * if QDF_MONITOR_FLAG_OTHER_BSS bit is set in monitor flags 777 * driver will assume current mode as STA + Monitor Mode. 778 * So if QDF_MONITOR_FLAG_OTHER_BSS bit is set in monitor 779 * interface flag STA+MON concurrency is not supported 780 * reject the request. 781 **/ 782 if ((ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc) && 783 !(QDF_MONITOR_FLAG_OTHER_BSS & *flags)) || 784 (ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc) && 785 (QDF_MONITOR_FLAG_OTHER_BSS & *flags)) || 786 ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != 787 PACKET_CAPTURE_MODE_DISABLE) { 788 ret = wlan_hdd_add_monitor_check(hdd_ctx, 789 &adapter, name, true, 790 name_assign_type); 791 if (ret) 792 return ERR_PTR(-EINVAL); 793 794 ucfg_dp_set_mon_conf_flags(hdd_ctx->psoc, *flags); 795 796 if (adapter) { 797 hdd_exit(); 798 return adapter->dev->ieee80211_ptr; 799 } 800 } else { 801 hdd_err("Adding monitor interface not supported"); 802 return ERR_PTR(-EINVAL); 803 } 804 } 805 806 adapter = NULL; 807 cfg_p2p_get_device_addr_admin(hdd_ctx->psoc, &p2p_dev_addr_admin); 808 if (p2p_dev_addr_admin && 809 (mode == QDF_P2P_GO_MODE || mode == QDF_P2P_CLIENT_MODE)) { 810 /* 811 * Generate the P2P Interface Address. this address must be 812 * different from the P2P Device Address. 813 */ 814 struct qdf_mac_addr p2p_device_address = 815 hdd_ctx->p2p_device_address; 816 p2p_device_address.bytes[4] ^= 0x80; 817 adapter = hdd_open_adapter(hdd_ctx, mode, name, 818 p2p_device_address.bytes, 819 name_assign_type, true, 820 &create_params); 821 } else { 822 if (strnstr(name, "p2p", 3) && mode == QDF_STA_MODE) { 823 hdd_debug("change mode to p2p device"); 824 mode = QDF_P2P_DEVICE_MODE; 825 } 826 827 device_address = wlan_hdd_get_intf_addr(hdd_ctx, mode); 828 if (!device_address) 829 return ERR_PTR(-EINVAL); 830 831 adapter = hdd_open_adapter(hdd_ctx, mode, name, 832 device_address, 833 name_assign_type, true, 834 &create_params); 835 if (!adapter) 836 wlan_hdd_release_intf_addr(hdd_ctx, device_address); 837 } 838 839 if (!adapter) { 840 hdd_err("hdd_open_adapter failed with iftype %d", type); 841 return ERR_PTR(-ENOSPC); 842 } 843 844 adapter->delete_in_progress = false; 845 846 /* ensure physical soc is up */ 847 ret = hdd_trigger_psoc_idle_restart(hdd_ctx); 848 if (ret) { 849 hdd_err("Failed to start the wlan_modules"); 850 goto close_adapter; 851 } 852 853 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID); 854 if (vdev) { 855 ucfg_dp_try_send_rps_ind(vdev); 856 hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID); 857 } 858 859 hdd_exit(); 860 861 return adapter->dev->ieee80211_ptr; 862 863 close_adapter: 864 if (device_address) 865 wlan_hdd_release_intf_addr(hdd_ctx, device_address); 866 hdd_close_adapter(hdd_ctx, adapter, true); 867 868 return ERR_PTR(-EINVAL); 869 } 870 871 static struct wireless_dev * 872 _wlan_hdd_add_virtual_intf(struct wiphy *wiphy, 873 const char *name, 874 unsigned char name_assign_type, 875 enum nl80211_iftype type, 876 u32 *flags, 877 struct vif_params *params) 878 { 879 struct wireless_dev *wdev; 880 struct osif_vdev_sync *vdev_sync; 881 int errno; 882 883 errno = osif_vdev_sync_create_and_trans(wiphy_dev(wiphy), &vdev_sync); 884 if (errno) 885 return ERR_PTR(errno); 886 887 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, 888 type, flags, params); 889 890 if (IS_ERR_OR_NULL(wdev)) 891 goto destroy_sync; 892 893 osif_vdev_sync_register(wdev->netdev, vdev_sync); 894 osif_vdev_sync_trans_stop(vdev_sync); 895 896 return wdev; 897 898 destroy_sync: 899 osif_vdev_sync_trans_stop(vdev_sync); 900 osif_vdev_sync_destroy(vdev_sync); 901 902 return wdev; 903 } 904 905 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) 906 struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, 907 const char *name, 908 unsigned char name_assign_type, 909 enum nl80211_iftype type, 910 struct vif_params *params) 911 { 912 return _wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, 913 type, ¶ms->flags, params); 914 } 915 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) || defined(WITH_BACKPORTS) 916 struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, 917 const char *name, 918 unsigned char name_assign_type, 919 enum nl80211_iftype type, 920 u32 *flags, 921 struct vif_params *params) 922 { 923 return _wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, 924 type, flags, params); 925 } 926 #else 927 struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, 928 const char *name, 929 enum nl80211_iftype type, 930 u32 *flags, 931 struct vif_params *params) 932 { 933 return _wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, 934 type, flags, params); 935 } 936 #endif 937 938 #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC) && \ 939 !defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV) 940 /** 941 * hdd_deinit_mlo_interfaces() - De-initialize link adapters 942 * @hdd_ctx: Pointer to hdd context 943 * @adapter: Pointer to adapter 944 * @rtnl_held: rtnl lock 945 * 946 * Return: None 947 */ 948 static void hdd_deinit_mlo_interfaces(struct hdd_context *hdd_ctx, 949 struct hdd_adapter *adapter, 950 bool rtnl_held) 951 { 952 int i; 953 struct hdd_mlo_adapter_info *mlo_adapter_info; 954 struct hdd_adapter *link_adapter; 955 956 mlo_adapter_info = &adapter->mlo_adapter_info; 957 for (i = 0; i < WLAN_MAX_MLD; i++) { 958 link_adapter = mlo_adapter_info->link_adapter[i]; 959 if (!link_adapter) 960 continue; 961 hdd_deinit_adapter(hdd_ctx, link_adapter, rtnl_held); 962 } 963 } 964 #else 965 static inline 966 void hdd_deinit_mlo_interfaces(struct hdd_context *hdd_ctx, 967 struct hdd_adapter *adapter, 968 bool rtnl_held) 969 { 970 } 971 #endif 972 973 void hdd_clean_up_interface(struct hdd_context *hdd_ctx, 974 struct hdd_adapter *adapter) 975 { 976 wlan_hdd_release_intf_addr(hdd_ctx, 977 adapter->mac_addr.bytes); 978 hdd_stop_adapter(hdd_ctx, adapter); 979 if (hdd_adapter_is_ml_adapter(adapter)) { 980 hdd_deinit_mlo_interfaces(hdd_ctx, adapter, true); 981 hdd_wlan_unregister_mlo_interfaces(adapter, true); 982 } 983 hdd_deinit_adapter(hdd_ctx, adapter, true); 984 hdd_close_adapter(hdd_ctx, adapter, true); 985 } 986 987 int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) 988 { 989 struct net_device *dev = wdev->netdev; 990 struct hdd_context *hdd_ctx = (struct hdd_context *) wiphy_priv(wiphy); 991 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 992 int errno; 993 994 hdd_enter(); 995 996 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { 997 hdd_err("Command not allowed in FTM mode"); 998 return -EINVAL; 999 } 1000 1001 /* 1002 * Clear SOFTAP_INIT_DONE flag to mark SAP unload, so that we do 1003 * not restart SAP after SSR as SAP is already stopped from user space. 1004 */ 1005 clear_bit(SOFTAP_INIT_DONE, &adapter->deflink->link_flags); 1006 1007 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD, 1008 TRACE_CODE_HDD_DEL_VIRTUAL_INTF, 1009 adapter->deflink->vdev_id, adapter->device_mode); 1010 1011 hdd_debug("Device_mode %s(%d)", 1012 qdf_opmode_str(adapter->device_mode), adapter->device_mode); 1013 1014 errno = wlan_hdd_validate_context(hdd_ctx); 1015 if (errno) 1016 return errno; 1017 1018 /* ensure physical soc is up */ 1019 errno = hdd_trigger_psoc_idle_restart(hdd_ctx); 1020 if (errno) 1021 return errno; 1022 1023 if (wlan_hdd_is_session_type_monitor(adapter->device_mode)) 1024 ucfg_dp_set_mon_conf_flags(hdd_ctx->psoc, 0); 1025 1026 if (adapter->device_mode == QDF_SAP_MODE && 1027 ucfg_pre_cac_is_active(hdd_ctx->psoc)) { 1028 ucfg_pre_cac_clean_up(hdd_ctx->psoc); 1029 hdd_clean_up_interface(hdd_ctx, adapter); 1030 } else if (wlan_hdd_is_session_type_monitor( 1031 adapter->device_mode) && 1032 ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != 1033 PACKET_CAPTURE_MODE_DISABLE) { 1034 wlan_hdd_del_monitor(hdd_ctx, adapter, TRUE); 1035 } else { 1036 hdd_clean_up_interface(hdd_ctx, adapter); 1037 } 1038 1039 if (!hdd_is_any_interface_open(hdd_ctx)) 1040 hdd_psoc_idle_timer_start(hdd_ctx); 1041 hdd_exit(); 1042 1043 return 0; 1044 } 1045 1046 int wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) 1047 { 1048 int errno; 1049 struct osif_vdev_sync *vdev_sync; 1050 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev); 1051 1052 adapter->delete_in_progress = true; 1053 errno = osif_vdev_sync_trans_start_wait(wdev->netdev, &vdev_sync); 1054 if (errno) 1055 return errno; 1056 1057 osif_vdev_sync_unregister(wdev->netdev); 1058 osif_vdev_sync_wait_for_ops(vdev_sync); 1059 1060 adapter->is_virtual_iface = true; 1061 errno = __wlan_hdd_del_virtual_intf(wiphy, wdev); 1062 1063 osif_vdev_sync_trans_stop(vdev_sync); 1064 osif_vdev_sync_destroy(vdev_sync); 1065 1066 return errno; 1067 } 1068 1069 /** 1070 * hdd_is_qos_action_frame() - check if frame is QOS action frame 1071 * @pb_frames: frame pointer 1072 * @frame_len: frame length 1073 * 1074 * Return: true if it is QOS action frame else false. 1075 */ 1076 static inline bool 1077 hdd_is_qos_action_frame(uint8_t *pb_frames, uint32_t frame_len) 1078 { 1079 if (frame_len <= WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET + 1) { 1080 hdd_debug("Not a QOS frame len: %d", frame_len); 1081 return false; 1082 } 1083 1084 return ((pb_frames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == 1085 WLAN_HDD_QOS_ACTION_FRAME) && 1086 (pb_frames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET + 1] == 1087 WLAN_HDD_QOS_MAP_CONFIGURE)); 1088 } 1089 1090 #if defined(WLAN_FEATURE_SAE) && defined(CFG80211_EXTERNAL_AUTH_AP_SUPPORT) 1091 /** 1092 * wlan_hdd_set_rxmgmt_external_auth_flag() - Set the EXTERNAL_AUTH flag 1093 * @nl80211_flag: flags to be sent to nl80211 from enum nl80211_rxmgmt_flags 1094 * 1095 * Set the flag NL80211_RXMGMT_FLAG_EXTERNAL_AUTH if supported. 1096 */ 1097 static void 1098 wlan_hdd_set_rxmgmt_external_auth_flag(enum nl80211_rxmgmt_flags *nl80211_flag) 1099 { 1100 *nl80211_flag |= NL80211_RXMGMT_FLAG_EXTERNAL_AUTH; 1101 } 1102 #else 1103 static void 1104 wlan_hdd_set_rxmgmt_external_auth_flag(enum nl80211_rxmgmt_flags *nl80211_flag) 1105 { 1106 } 1107 #endif 1108 1109 /** 1110 * wlan_hdd_cfg80211_convert_rxmgmt_flags() - Convert RXMGMT value 1111 * @nl80211_flag: Flags to be sent to nl80211 from enum nl80211_rxmgmt_flags 1112 * @flag: flags set by driver(SME/PE) from enum rxmgmt_flags 1113 * 1114 * Convert driver internal RXMGMT flag value to nl80211 defined RXMGMT flag 1115 * Return: void 1116 */ 1117 static void 1118 wlan_hdd_cfg80211_convert_rxmgmt_flags(enum rxmgmt_flags flag, 1119 enum nl80211_rxmgmt_flags *nl80211_flag) 1120 { 1121 1122 if (flag & RXMGMT_FLAG_EXTERNAL_AUTH) { 1123 wlan_hdd_set_rxmgmt_external_auth_flag(nl80211_flag); 1124 } 1125 1126 } 1127 1128 static void 1129 __hdd_indicate_mgmt_frame_to_user(struct hdd_adapter *adapter, 1130 uint32_t frm_len, uint8_t *pb_frames, 1131 uint8_t frame_type, uint32_t rx_freq, 1132 int8_t rx_rssi, enum rxmgmt_flags rx_flags) 1133 { 1134 uint8_t type = 0; 1135 uint8_t sub_type = 0; 1136 struct hdd_context *hdd_ctx; 1137 uint8_t *dest_addr = NULL; 1138 uint16_t auth_algo; 1139 enum nl80211_rxmgmt_flags nl80211_flag = 0; 1140 bool is_pasn_auth_frame = false; 1141 struct hdd_adapter *assoc_adapter; 1142 bool eht_capab; 1143 struct hdd_ap_ctx *ap_ctx; 1144 struct action_frm_hdr *action_hdr; 1145 tpSirMacVendorSpecificPublicActionFrameHdr vendor_specific; 1146 1147 hdd_debug("Frame Type = %d Frame Length = %d freq = %d", 1148 frame_type, frm_len, rx_freq); 1149 1150 if (!adapter) { 1151 hdd_err("adapter is NULL"); 1152 return; 1153 } 1154 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 1155 1156 if (!frm_len) { 1157 hdd_err("Frame Length is Invalid ZERO"); 1158 return; 1159 } 1160 1161 if (!pb_frames) { 1162 hdd_err("pbFrames is NULL"); 1163 return; 1164 } 1165 1166 type = WLAN_HDD_GET_TYPE_FRM_FC(pb_frames[0]); 1167 sub_type = WLAN_HDD_GET_SUBTYPE_FRM_FC(pb_frames[0]); 1168 if (type == SIR_MAC_MGMT_FRAME && 1169 sub_type == SIR_MAC_MGMT_AUTH && 1170 frm_len > (sizeof(struct wlan_frame_hdr) + 1171 WLAN_AUTH_FRAME_MIN_LEN)) { 1172 auth_algo = *(uint16_t *)(pb_frames + 1173 sizeof(struct wlan_frame_hdr)); 1174 if (auth_algo == eSIR_AUTH_TYPE_PASN) { 1175 is_pasn_auth_frame = true; 1176 } else if (auth_algo == eSIR_FT_AUTH && 1177 (adapter->device_mode == QDF_SAP_MODE || 1178 adapter->device_mode == QDF_P2P_GO_MODE)) { 1179 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink); 1180 ap_ctx->during_auth_offload = true; 1181 } 1182 } 1183 1184 if (type == WLAN_FC0_TYPE_MGMT && sub_type == WLAN_FC0_STYPE_ACTION && 1185 frm_len >= (sizeof(struct wlan_frame_hdr) + 1186 sizeof(*vendor_specific))) { 1187 action_hdr = (struct action_frm_hdr *)(pb_frames + 1188 sizeof(struct wlan_frame_hdr)); 1189 vendor_specific = 1190 (tpSirMacVendorSpecificPublicActionFrameHdr)action_hdr; 1191 if (is_nan_oui(vendor_specific->Oui)) { 1192 adapter = hdd_get_adapter(hdd_ctx, QDF_NAN_DISC_MODE); 1193 if (!adapter) { 1194 hdd_err("NAN adapter is null"); 1195 return; 1196 } 1197 1198 goto check_adapter; 1199 } 1200 } 1201 1202 /* Get adapter from Destination mac address of the frame */ 1203 if (type == SIR_MAC_MGMT_FRAME && 1204 sub_type != SIR_MAC_MGMT_PROBE_REQ && !is_pasn_auth_frame && 1205 !qdf_is_macaddr_broadcast( 1206 (struct qdf_mac_addr *)&pb_frames[WLAN_HDD_80211_FRM_DA_OFFSET])) { 1207 dest_addr = &pb_frames[WLAN_HDD_80211_FRM_DA_OFFSET]; 1208 adapter = hdd_get_adapter_by_macaddr(hdd_ctx, dest_addr); 1209 if (!adapter) 1210 adapter = hdd_get_adapter_by_rand_macaddr(hdd_ctx, 1211 dest_addr); 1212 if (!adapter) { 1213 /* 1214 * Under assumption that we don't receive any action 1215 * frame with BCST as destination, 1216 * we are dropping action frame 1217 */ 1218 hdd_err("adapter for action frame is NULL Macaddr = " 1219 QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(dest_addr)); 1220 hdd_debug("Frame Type = %d Frame Length = %d subType = %d", 1221 frame_type, frm_len, sub_type); 1222 /* 1223 * We will receive broadcast management frames 1224 * in OCB mode 1225 */ 1226 adapter = hdd_get_adapter(hdd_ctx, QDF_OCB_MODE); 1227 if (!adapter || !qdf_is_macaddr_broadcast( 1228 (struct qdf_mac_addr *)dest_addr)) { 1229 /* 1230 * Under assumption that we don't 1231 * receive any action frame with BCST 1232 * as destination, we are dropping 1233 * action frame 1234 */ 1235 return; 1236 } 1237 } 1238 } 1239 1240 check_adapter: 1241 if (!adapter->dev) { 1242 hdd_err("adapter->dev is NULL"); 1243 return; 1244 } 1245 1246 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) { 1247 hdd_err("adapter has invalid magic"); 1248 return; 1249 } 1250 1251 /* Channel indicated may be wrong. TODO */ 1252 /* Indicate an action frame. */ 1253 1254 if (hdd_is_qos_action_frame(pb_frames, frm_len)) 1255 sme_update_dsc_pto_up_mapping(hdd_ctx->mac_handle, 1256 adapter->dscp_to_up_map, 1257 adapter->deflink->vdev_id); 1258 1259 assoc_adapter = adapter; 1260 ucfg_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab); 1261 if (hdd_adapter_is_link_adapter(adapter) && eht_capab) { 1262 hdd_debug("adapter is not ml adapter move to ml adapter"); 1263 assoc_adapter = hdd_adapter_get_mlo_adapter_from_link(adapter); 1264 if (!assoc_adapter) { 1265 hdd_err("Assoc adapter is NULL"); 1266 return; 1267 } 1268 } 1269 1270 /* Indicate Frame Over Normal Interface */ 1271 hdd_debug("Indicate Frame over NL80211 sessionid : %d, idx :%d", 1272 assoc_adapter->deflink->vdev_id, 1273 assoc_adapter->dev->ifindex); 1274 1275 wlan_hdd_cfg80211_convert_rxmgmt_flags(rx_flags, &nl80211_flag); 1276 1277 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) 1278 cfg80211_rx_mgmt(assoc_adapter->dev->ieee80211_ptr, 1279 rx_freq, rx_rssi * 100, pb_frames, 1280 frm_len, NL80211_RXMGMT_FLAG_ANSWERED | nl80211_flag); 1281 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) 1282 cfg80211_rx_mgmt(assoc_adapter->dev->ieee80211_ptr, 1283 rx_freq, rx_rssi * 100, pb_frames, 1284 frm_len, NL80211_RXMGMT_FLAG_ANSWERED, 1285 GFP_ATOMIC); 1286 #else 1287 cfg80211_rx_mgmt(assoc_adapter->dev->ieee80211_ptr, rx_freq, 1288 rx_rssi * 100, 1289 pb_frames, frm_len, GFP_ATOMIC); 1290 #endif /* LINUX_VERSION_CODE */ 1291 } 1292 1293 void hdd_indicate_mgmt_frame_to_user(struct hdd_adapter *adapter, 1294 uint32_t frm_len, uint8_t *pb_frames, 1295 uint8_t frame_type, uint32_t rx_freq, 1296 int8_t rx_rssi, enum rxmgmt_flags rx_flags) 1297 { 1298 int errno; 1299 struct osif_vdev_sync *vdev_sync; 1300 1301 errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync); 1302 if (errno) 1303 return; 1304 1305 __hdd_indicate_mgmt_frame_to_user(adapter, frm_len, pb_frames, 1306 frame_type, rx_freq, 1307 rx_rssi, rx_flags); 1308 osif_vdev_sync_op_stop(vdev_sync); 1309 } 1310 1311 int wlan_hdd_set_power_save(struct hdd_adapter *adapter, 1312 struct p2p_ps_config *ps_config) 1313 { 1314 struct wlan_objmgr_psoc *psoc; 1315 struct hdd_context *hdd_ctx; 1316 QDF_STATUS status; 1317 1318 if (!adapter || !ps_config) { 1319 hdd_err("null param, adapter:%pK, ps_config:%pK", 1320 adapter, ps_config); 1321 return -EINVAL; 1322 } 1323 1324 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 1325 psoc = hdd_ctx->psoc; 1326 if (!psoc) { 1327 hdd_err("psoc is null"); 1328 return -EINVAL; 1329 } 1330 1331 hdd_debug("opp ps:%d, ct window:%d, duration:%d, interval:%d, count:%d start:%d, single noa duration:%d, ps selection:%d, vdev id:%d", 1332 ps_config->opp_ps, ps_config->ct_window, 1333 ps_config->duration, ps_config->interval, 1334 ps_config->count, ps_config->start, 1335 ps_config->single_noa_duration, 1336 ps_config->ps_selection, ps_config->vdev_id); 1337 1338 status = ucfg_p2p_set_ps(psoc, ps_config); 1339 hdd_debug("p2p set power save, status:%d", status); 1340 1341 /* P2P-GO-NOA and TWT do not go hand in hand */ 1342 if (ps_config->duration) { 1343 hdd_send_twt_role_disable_cmd(hdd_ctx, TWT_RESPONDER); 1344 } else { 1345 hdd_send_twt_requestor_enable_cmd(hdd_ctx); 1346 hdd_send_twt_responder_enable_cmd(hdd_ctx); 1347 } 1348 1349 return qdf_status_to_os_return(status); 1350 } 1351 1352 /** 1353 * wlan_hdd_update_mcc_p2p_quota() - Function to Update P2P 1354 * quota to FW 1355 * @adapter: Pointer to HDD adapter 1356 * @is_set: 0-reset, 1-set 1357 * 1358 * This function passes down the value of MAS to UMAC 1359 * 1360 * Return: none 1361 * 1362 */ 1363 static void wlan_hdd_update_mcc_p2p_quota(struct hdd_adapter *adapter, 1364 bool is_set) 1365 { 1366 1367 hdd_info("Set/reset P2P quota: %d", is_set); 1368 if (is_set) { 1369 if (adapter->device_mode == QDF_STA_MODE) 1370 wlan_hdd_set_mcc_p2p_quota(adapter, 1371 100 - HDD_DEFAULT_MCC_P2P_QUOTA 1372 ); 1373 else if (adapter->device_mode == QDF_P2P_GO_MODE) 1374 wlan_hdd_go_set_mcc_p2p_quota(adapter, 1375 HDD_DEFAULT_MCC_P2P_QUOTA); 1376 else 1377 wlan_hdd_set_mcc_p2p_quota(adapter, 1378 HDD_DEFAULT_MCC_P2P_QUOTA); 1379 } else { 1380 if (adapter->device_mode == QDF_P2P_GO_MODE) 1381 wlan_hdd_go_set_mcc_p2p_quota(adapter, 1382 HDD_RESET_MCC_P2P_QUOTA); 1383 else 1384 wlan_hdd_set_mcc_p2p_quota(adapter, 1385 HDD_RESET_MCC_P2P_QUOTA); 1386 } 1387 } 1388 1389 int32_t wlan_hdd_set_mas(struct hdd_adapter *adapter, uint8_t mas_value) 1390 { 1391 struct hdd_context *hdd_ctx; 1392 bool enable_mcc_adaptive_sch = false; 1393 1394 if (!adapter) { 1395 hdd_err("Adapter is NULL"); 1396 return -EINVAL; 1397 } 1398 1399 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 1400 if (!hdd_ctx) { 1401 hdd_err("HDD context is null"); 1402 return -EINVAL; 1403 } 1404 1405 if (mas_value) { 1406 hdd_info("Miracast is ON. Disable MAS and configure P2P quota"); 1407 ucfg_policy_mgr_get_mcc_adaptive_sch(hdd_ctx->psoc, 1408 &enable_mcc_adaptive_sch); 1409 if (enable_mcc_adaptive_sch) { 1410 ucfg_policy_mgr_set_dynamic_mcc_adaptive_sch( 1411 hdd_ctx->psoc, false); 1412 1413 if (QDF_STATUS_SUCCESS != sme_set_mas(false)) { 1414 hdd_err("Failed to disable MAS"); 1415 return -EAGAIN; 1416 } 1417 } 1418 1419 /* Config p2p quota */ 1420 wlan_hdd_update_mcc_p2p_quota(adapter, true); 1421 } else { 1422 hdd_info("Miracast is OFF. Enable MAS and reset P2P quota"); 1423 wlan_hdd_update_mcc_p2p_quota(adapter, false); 1424 1425 ucfg_policy_mgr_get_mcc_adaptive_sch(hdd_ctx->psoc, 1426 &enable_mcc_adaptive_sch); 1427 if (enable_mcc_adaptive_sch) { 1428 ucfg_policy_mgr_set_dynamic_mcc_adaptive_sch( 1429 hdd_ctx->psoc, true); 1430 1431 if (QDF_STATUS_SUCCESS != sme_set_mas(true)) { 1432 hdd_err("Failed to enable MAS"); 1433 return -EAGAIN; 1434 } 1435 } 1436 } 1437 1438 return 0; 1439 } 1440 1441 /** 1442 * set_first_connection_operating_channel() - Function to set 1443 * first connection oerating channel 1444 * @hdd_ctx: Hdd context 1445 * @set_value: First connection operating channel 1446 * @dev_mode: Device operating mode 1447 * 1448 * This function is used to set the first adapter operating 1449 * channel 1450 * 1451 * Return: operating channel updated in set value 1452 * 1453 */ 1454 static uint32_t set_first_connection_operating_channel( 1455 struct hdd_context *hdd_ctx, uint32_t set_value, 1456 enum QDF_OPMODE dev_mode) 1457 { 1458 uint8_t operating_channel; 1459 uint32_t oper_chan_freq; 1460 1461 oper_chan_freq = hdd_get_operating_chan_freq(hdd_ctx, dev_mode); 1462 if (!oper_chan_freq) { 1463 hdd_err(" First adapter operating channel is invalid"); 1464 return -EINVAL; 1465 } 1466 operating_channel = wlan_reg_freq_to_chan(hdd_ctx->pdev, 1467 oper_chan_freq); 1468 1469 hdd_info("First connection channel No.:%d and quota:%dms", 1470 operating_channel, set_value); 1471 /* Move the time quota for first channel to bits 15-8 */ 1472 set_value = set_value << 8; 1473 1474 /* 1475 * Store the channel number of 1st channel at bits 7-0 1476 * of the bit vector 1477 */ 1478 return set_value | operating_channel; 1479 } 1480 1481 /** 1482 * set_second_connection_operating_channel() - Function to set 1483 * second connection oerating channel 1484 * @hdd_ctx: Hdd context 1485 * @set_value: Second connection operating channel 1486 * @vdev_id: vdev id 1487 * 1488 * This function is used to set the first adapter operating 1489 * channel 1490 * 1491 * Return: operating channel updated in set value 1492 * 1493 */ 1494 static uint32_t set_second_connection_operating_channel( 1495 struct hdd_context *hdd_ctx, uint32_t set_value, 1496 uint8_t vdev_id) 1497 { 1498 uint8_t operating_channel; 1499 1500 operating_channel = wlan_reg_freq_to_chan(hdd_ctx->pdev, 1501 policy_mgr_get_mcc_operating_channel( 1502 hdd_ctx->psoc, vdev_id)); 1503 1504 if (operating_channel == 0) { 1505 hdd_err("Second adapter operating channel is invalid"); 1506 return -EINVAL; 1507 } 1508 1509 hdd_info("Second connection channel No.:%d and quota:%dms", 1510 operating_channel, set_value); 1511 /* 1512 * Now move the time quota and channel number of the 1513 * 1st adapter to bits 23-16 and bits 15-8 of the bit 1514 * vector, respectively. 1515 */ 1516 set_value = set_value << 8; 1517 1518 /* 1519 * Set the channel number for 2nd MCC vdev at bits 1520 * 7-0 of set_value 1521 */ 1522 return set_value | operating_channel; 1523 } 1524 1525 /** 1526 * wlan_hdd_set_mcc_p2p_quota() - Function to set quota for P2P 1527 * @adapter: HDD adapter 1528 * @set_value: Quota value for the interface 1529 * 1530 * This function is used to set the quota for P2P cases 1531 * 1532 * Return: Configuration message posting status, SUCCESS or Fail 1533 * 1534 */ 1535 int wlan_hdd_set_mcc_p2p_quota(struct hdd_adapter *adapter, 1536 uint32_t set_value) 1537 { 1538 int32_t ret = 0; 1539 uint32_t concurrent_state; 1540 struct hdd_context *hdd_ctx; 1541 uint32_t sta_cli_bit_mask = QDF_STA_MASK | QDF_P2P_CLIENT_MASK; 1542 uint32_t sta_go_bit_mask = QDF_STA_MASK | QDF_P2P_GO_MASK; 1543 1544 if (!adapter) { 1545 hdd_err("Invalid adapter"); 1546 return -EFAULT; 1547 } 1548 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 1549 if (!hdd_ctx) { 1550 hdd_err("HDD context is null"); 1551 return -EINVAL; 1552 } 1553 1554 concurrent_state = policy_mgr_get_concurrency_mode( 1555 hdd_ctx->psoc); 1556 /* 1557 * Check if concurrency mode is active. 1558 * Need to modify this code to support MCC modes other than STA/P2P 1559 */ 1560 if (((concurrent_state & sta_cli_bit_mask) == sta_cli_bit_mask) || 1561 ((concurrent_state & sta_go_bit_mask) == sta_go_bit_mask)) { 1562 hdd_info("STA & P2P are both enabled"); 1563 1564 /* 1565 * The channel numbers for both adapters and the time 1566 * quota for the 1st adapter, i.e., one specified in cmd 1567 * are formatted as a bit vector then passed on to WMA 1568 * +***********************************************************+ 1569 * |bit 31-24 | bit 23-16 | bits 15-8 | bits 7-0 | 1570 * | Unused | Quota for | chan. # for | chan. # for | 1571 * | | 1st chan. | 1st chan. | 2nd chan. | 1572 * +***********************************************************+ 1573 */ 1574 1575 set_value = set_first_connection_operating_channel( 1576 hdd_ctx, set_value, adapter->device_mode); 1577 1578 set_value = set_second_connection_operating_channel( 1579 hdd_ctx, set_value, adapter->deflink->vdev_id); 1580 1581 ret = wlan_hdd_send_mcc_vdev_quota(adapter, set_value); 1582 } else { 1583 hdd_info("MCC is not active. Exit w/o setting latency"); 1584 } 1585 1586 return ret; 1587 } 1588 1589 int wlan_hdd_go_set_mcc_p2p_quota(struct hdd_adapter *hostapd_adapter, 1590 uint32_t set_value) 1591 { 1592 return wlan_hdd_set_mcc_p2p_quota(hostapd_adapter, set_value); 1593 } 1594 1595 void wlan_hdd_set_mcc_latency(struct hdd_adapter *adapter, int set_value) 1596 { 1597 uint32_t concurrent_state; 1598 struct hdd_context *hdd_ctx; 1599 uint32_t sta_cli_bit_mask = QDF_STA_MASK | QDF_P2P_CLIENT_MASK; 1600 uint32_t sta_go_bit_mask = QDF_STA_MASK | QDF_P2P_GO_MASK; 1601 1602 if (!adapter) { 1603 hdd_err("Invalid adapter"); 1604 return; 1605 } 1606 1607 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 1608 if (!hdd_ctx) { 1609 hdd_err("HDD context is null"); 1610 return; 1611 } 1612 1613 concurrent_state = policy_mgr_get_concurrency_mode( 1614 hdd_ctx->psoc); 1615 /** 1616 * Check if concurrency mode is active. 1617 * Need to modify this code to support MCC modes other than STA/P2P 1618 */ 1619 if (((concurrent_state & sta_cli_bit_mask) == sta_cli_bit_mask) || 1620 ((concurrent_state & sta_go_bit_mask) == sta_go_bit_mask)) { 1621 hdd_info("STA & P2P are both enabled"); 1622 /* 1623 * The channel number and latency are formatted in 1624 * a bit vector then passed on to WMA layer. 1625 * +**********************************************+ 1626 * |bits 31-16 | bits 15-8 | bits 7-0 | 1627 * | Unused | latency - Chan. 1 | channel no. | 1628 * +**********************************************+ 1629 */ 1630 set_value = set_first_connection_operating_channel( 1631 hdd_ctx, set_value, adapter->device_mode); 1632 1633 wlan_hdd_send_mcc_latency(adapter, set_value); 1634 } else { 1635 hdd_info("MCC is not active. Exit w/o setting latency"); 1636 } 1637 } 1638