1 /* 2 * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2023 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 /** 646 * hdd_allow_new_intf() - Allow new intf created or not 647 * @hdd_ctx: hdd context 648 * @mode: qdf opmode of new interface 649 * 650 * Return: true if allowed, otherwise false 651 */ 652 static bool hdd_allow_new_intf(struct hdd_context *hdd_ctx, 653 enum QDF_OPMODE mode) 654 { 655 struct hdd_adapter *adapter = NULL; 656 struct hdd_adapter *next_adapter = NULL; 657 uint8_t num_active_adapter = 0; 658 659 if (mode != QDF_SAP_MODE) 660 return true; 661 662 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter, 663 NET_DEV_HOLD_ALLOW_NEW_INTF) { 664 if (hdd_is_interface_up(adapter) && 665 adapter->device_mode == mode) 666 num_active_adapter++; 667 668 hdd_adapter_dev_put_debug(adapter, 669 NET_DEV_HOLD_ALLOW_NEW_INTF); 670 } 671 672 if (num_active_adapter >= QDF_MAX_NO_OF_SAP_MODE) 673 hdd_err("sap max allowed intf %d, curr %d", 674 QDF_MAX_NO_OF_SAP_MODE, num_active_adapter); 675 676 return num_active_adapter < QDF_MAX_NO_OF_SAP_MODE; 677 } 678 679 /** 680 * __wlan_hdd_add_virtual_intf() - Add virtual interface 681 * @wiphy: wiphy pointer 682 * @name: User-visible name of the interface 683 * @name_assign_type: the name of assign type of the netdev 684 * @type: (virtual) interface types 685 * @flags: monitor configuration flags (not used) 686 * @params: virtual interface parameters (not used) 687 * 688 * Return: the pointer of wireless dev, otherwise ERR_PTR. 689 */ 690 static 691 struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy, 692 const char *name, 693 unsigned char name_assign_type, 694 enum nl80211_iftype type, 695 u32 *flags, 696 struct vif_params *params) 697 { 698 struct hdd_context *hdd_ctx = wiphy_priv(wiphy); 699 struct hdd_adapter *adapter = NULL; 700 bool p2p_dev_addr_admin = false; 701 enum QDF_OPMODE mode; 702 QDF_STATUS status; 703 struct wlan_objmgr_vdev *vdev; 704 int ret; 705 struct hdd_adapter_create_param create_params = {0}; 706 uint8_t *device_address = NULL; 707 708 hdd_enter(); 709 710 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) { 711 hdd_err("Command not allowed in FTM mode"); 712 return ERR_PTR(-EINVAL); 713 } 714 715 if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE) { 716 hdd_err("Concurrency not allowed with standalone monitor mode"); 717 return ERR_PTR(-EINVAL); 718 } 719 720 ret = wlan_hdd_validate_context(hdd_ctx); 721 if (ret) 722 return ERR_PTR(ret); 723 724 status = hdd_nl_to_qdf_iface_type(type, &mode); 725 if (QDF_IS_STATUS_ERROR(status)) 726 return ERR_PTR(qdf_status_to_os_return(status)); 727 728 if (mode == QDF_MONITOR_MODE && 729 !os_if_lpc_mon_intf_creation_allowed(hdd_ctx->psoc)) 730 return ERR_PTR(-EOPNOTSUPP); 731 732 wlan_hdd_lpc_handle_concurrency(hdd_ctx, true); 733 734 if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc) && 735 !hdd_lpc_is_work_scheduled(hdd_ctx)) 736 return ERR_PTR(-EINVAL); 737 738 if (wlan_hdd_is_mon_concurrency()) 739 return ERR_PTR(-EINVAL); 740 741 if (!hdd_allow_new_intf(hdd_ctx, mode)) 742 return ERR_PTR(-EOPNOTSUPP); 743 744 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD, 745 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, 746 NO_SESSION, type); 747 748 switch (mode) { 749 case QDF_SAP_MODE: 750 case QDF_P2P_GO_MODE: 751 case QDF_P2P_CLIENT_MODE: 752 case QDF_STA_MODE: 753 case QDF_MONITOR_MODE: 754 break; 755 default: 756 mode = QDF_STA_MODE; 757 break; 758 } 759 760 create_params.is_add_virtual_iface = 1; 761 762 adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE); 763 if (adapter && !wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id)) { 764 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, 765 WLAN_OSIF_P2P_ID); 766 if (vdev) { 767 if (ucfg_scan_get_vdev_status(vdev) != 768 SCAN_NOT_IN_PROGRESS) { 769 wlan_abort_scan(hdd_ctx->pdev, INVAL_PDEV_ID, 770 adapter->deflink->vdev_id, 771 INVALID_SCAN_ID, false); 772 } 773 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_P2P_ID); 774 } else { 775 hdd_err("vdev is NULL"); 776 } 777 } 778 779 adapter = NULL; 780 if (type == NL80211_IFTYPE_MONITOR) { 781 if (ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc) || 782 ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc) || 783 ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != 784 PACKET_CAPTURE_MODE_DISABLE) { 785 ret = wlan_hdd_add_monitor_check(hdd_ctx, 786 &adapter, name, true, 787 name_assign_type); 788 if (ret) 789 return ERR_PTR(-EINVAL); 790 791 if (adapter) { 792 hdd_exit(); 793 return adapter->dev->ieee80211_ptr; 794 } 795 } else { 796 hdd_err("Adding monitor interface not supported"); 797 return ERR_PTR(-EINVAL); 798 } 799 } 800 801 adapter = NULL; 802 cfg_p2p_get_device_addr_admin(hdd_ctx->psoc, &p2p_dev_addr_admin); 803 if (p2p_dev_addr_admin && 804 (mode == QDF_P2P_GO_MODE || mode == QDF_P2P_CLIENT_MODE)) { 805 /* 806 * Generate the P2P Interface Address. this address must be 807 * different from the P2P Device Address. 808 */ 809 struct qdf_mac_addr p2p_device_address = 810 hdd_ctx->p2p_device_address; 811 p2p_device_address.bytes[4] ^= 0x80; 812 adapter = hdd_open_adapter(hdd_ctx, mode, name, 813 p2p_device_address.bytes, 814 name_assign_type, true, 815 &create_params); 816 } else { 817 if (strnstr(name, "p2p", 3) && mode == QDF_STA_MODE) { 818 hdd_debug("change mode to p2p device"); 819 mode = QDF_P2P_DEVICE_MODE; 820 } 821 822 device_address = wlan_hdd_get_intf_addr(hdd_ctx, mode); 823 if (!device_address) 824 return ERR_PTR(-EINVAL); 825 826 adapter = hdd_open_adapter(hdd_ctx, mode, name, 827 device_address, 828 name_assign_type, true, 829 &create_params); 830 if (!adapter) 831 wlan_hdd_release_intf_addr(hdd_ctx, device_address); 832 } 833 834 if (!adapter) { 835 hdd_err("hdd_open_adapter failed with iftype %d", type); 836 return ERR_PTR(-ENOSPC); 837 } 838 839 adapter->delete_in_progress = false; 840 841 /* ensure physical soc is up */ 842 ret = hdd_trigger_psoc_idle_restart(hdd_ctx); 843 if (ret) { 844 hdd_err("Failed to start the wlan_modules"); 845 goto close_adapter; 846 } 847 848 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID); 849 if (vdev) { 850 ucfg_dp_try_send_rps_ind(vdev); 851 hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID); 852 } 853 854 hdd_exit(); 855 856 return adapter->dev->ieee80211_ptr; 857 858 close_adapter: 859 if (device_address) 860 wlan_hdd_release_intf_addr(hdd_ctx, device_address); 861 hdd_close_adapter(hdd_ctx, adapter, true); 862 863 return ERR_PTR(-EINVAL); 864 } 865 866 static struct wireless_dev * 867 _wlan_hdd_add_virtual_intf(struct wiphy *wiphy, 868 const char *name, 869 unsigned char name_assign_type, 870 enum nl80211_iftype type, 871 u32 *flags, 872 struct vif_params *params) 873 { 874 struct wireless_dev *wdev; 875 struct osif_vdev_sync *vdev_sync; 876 int errno; 877 878 errno = osif_vdev_sync_create_and_trans(wiphy_dev(wiphy), &vdev_sync); 879 if (errno) 880 return ERR_PTR(errno); 881 882 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, 883 type, flags, params); 884 885 if (IS_ERR_OR_NULL(wdev)) 886 goto destroy_sync; 887 888 osif_vdev_sync_register(wdev->netdev, vdev_sync); 889 osif_vdev_sync_trans_stop(vdev_sync); 890 891 return wdev; 892 893 destroy_sync: 894 osif_vdev_sync_trans_stop(vdev_sync); 895 osif_vdev_sync_destroy(vdev_sync); 896 897 return wdev; 898 } 899 900 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) 901 struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, 902 const char *name, 903 unsigned char name_assign_type, 904 enum nl80211_iftype type, 905 struct vif_params *params) 906 { 907 return _wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, 908 type, ¶ms->flags, params); 909 } 910 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) || defined(WITH_BACKPORTS) 911 struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, 912 const char *name, 913 unsigned char name_assign_type, 914 enum nl80211_iftype type, 915 u32 *flags, 916 struct vif_params *params) 917 { 918 return _wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, 919 type, flags, params); 920 } 921 #else 922 struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, 923 const char *name, 924 enum nl80211_iftype type, 925 u32 *flags, 926 struct vif_params *params) 927 { 928 return _wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, 929 type, flags, params); 930 } 931 #endif 932 933 #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC) && \ 934 !defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV) 935 /** 936 * hdd_deinit_mlo_interfaces() - De-initialize link adapters 937 * @hdd_ctx: Pointer to hdd context 938 * @adapter: Pointer to adapter 939 * @rtnl_held: rtnl lock 940 * 941 * Return: None 942 */ 943 static void hdd_deinit_mlo_interfaces(struct hdd_context *hdd_ctx, 944 struct hdd_adapter *adapter, 945 bool rtnl_held) 946 { 947 int i; 948 struct hdd_mlo_adapter_info *mlo_adapter_info; 949 struct hdd_adapter *link_adapter; 950 951 mlo_adapter_info = &adapter->mlo_adapter_info; 952 for (i = 0; i < WLAN_MAX_MLD; i++) { 953 link_adapter = mlo_adapter_info->link_adapter[i]; 954 if (!link_adapter) 955 continue; 956 hdd_deinit_adapter(hdd_ctx, link_adapter, rtnl_held); 957 } 958 } 959 #else 960 static inline 961 void hdd_deinit_mlo_interfaces(struct hdd_context *hdd_ctx, 962 struct hdd_adapter *adapter, 963 bool rtnl_held) 964 { 965 } 966 #endif 967 968 void hdd_clean_up_interface(struct hdd_context *hdd_ctx, 969 struct hdd_adapter *adapter) 970 { 971 wlan_hdd_release_intf_addr(hdd_ctx, 972 adapter->mac_addr.bytes); 973 hdd_stop_adapter(hdd_ctx, adapter); 974 if (hdd_adapter_is_ml_adapter(adapter)) { 975 hdd_deinit_mlo_interfaces(hdd_ctx, adapter, true); 976 hdd_wlan_unregister_mlo_interfaces(adapter, true); 977 } 978 hdd_deinit_adapter(hdd_ctx, adapter, true); 979 hdd_close_adapter(hdd_ctx, adapter, true); 980 } 981 982 int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) 983 { 984 struct net_device *dev = wdev->netdev; 985 struct hdd_context *hdd_ctx = (struct hdd_context *) wiphy_priv(wiphy); 986 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 987 int errno; 988 989 hdd_enter(); 990 991 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { 992 hdd_err("Command not allowed in FTM mode"); 993 return -EINVAL; 994 } 995 996 /* 997 * Clear SOFTAP_INIT_DONE flag to mark SAP unload, so that we do 998 * not restart SAP after SSR as SAP is already stopped from user space. 999 */ 1000 clear_bit(SOFTAP_INIT_DONE, &adapter->deflink->link_flags); 1001 1002 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD, 1003 TRACE_CODE_HDD_DEL_VIRTUAL_INTF, 1004 adapter->deflink->vdev_id, adapter->device_mode); 1005 1006 hdd_debug("Device_mode %s(%d)", 1007 qdf_opmode_str(adapter->device_mode), adapter->device_mode); 1008 1009 errno = wlan_hdd_validate_context(hdd_ctx); 1010 if (errno) 1011 return errno; 1012 1013 /* ensure physical soc is up */ 1014 errno = hdd_trigger_psoc_idle_restart(hdd_ctx); 1015 if (errno) 1016 return errno; 1017 1018 if (adapter->device_mode == QDF_SAP_MODE && 1019 ucfg_pre_cac_is_active(hdd_ctx->psoc)) { 1020 ucfg_pre_cac_clean_up(hdd_ctx->psoc); 1021 hdd_clean_up_interface(hdd_ctx, adapter); 1022 } else if (wlan_hdd_is_session_type_monitor( 1023 adapter->device_mode) && 1024 ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != 1025 PACKET_CAPTURE_MODE_DISABLE) { 1026 wlan_hdd_del_monitor(hdd_ctx, adapter, TRUE); 1027 } else { 1028 hdd_clean_up_interface(hdd_ctx, adapter); 1029 } 1030 1031 if (!hdd_is_any_interface_open(hdd_ctx)) 1032 hdd_psoc_idle_timer_start(hdd_ctx); 1033 hdd_exit(); 1034 1035 return 0; 1036 } 1037 1038 int wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) 1039 { 1040 int errno; 1041 struct osif_vdev_sync *vdev_sync; 1042 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev); 1043 1044 adapter->delete_in_progress = true; 1045 errno = osif_vdev_sync_trans_start_wait(wdev->netdev, &vdev_sync); 1046 if (errno) 1047 return errno; 1048 1049 osif_vdev_sync_unregister(wdev->netdev); 1050 osif_vdev_sync_wait_for_ops(vdev_sync); 1051 1052 adapter->is_virtual_iface = true; 1053 errno = __wlan_hdd_del_virtual_intf(wiphy, wdev); 1054 1055 osif_vdev_sync_trans_stop(vdev_sync); 1056 osif_vdev_sync_destroy(vdev_sync); 1057 1058 return errno; 1059 } 1060 1061 /** 1062 * hdd_is_qos_action_frame() - check if frame is QOS action frame 1063 * @pb_frames: frame pointer 1064 * @frame_len: frame length 1065 * 1066 * Return: true if it is QOS action frame else false. 1067 */ 1068 static inline bool 1069 hdd_is_qos_action_frame(uint8_t *pb_frames, uint32_t frame_len) 1070 { 1071 if (frame_len <= WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET + 1) { 1072 hdd_debug("Not a QOS frame len: %d", frame_len); 1073 return false; 1074 } 1075 1076 return ((pb_frames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == 1077 WLAN_HDD_QOS_ACTION_FRAME) && 1078 (pb_frames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET + 1] == 1079 WLAN_HDD_QOS_MAP_CONFIGURE)); 1080 } 1081 1082 #if defined(WLAN_FEATURE_SAE) && defined(CFG80211_EXTERNAL_AUTH_AP_SUPPORT) 1083 /** 1084 * wlan_hdd_set_rxmgmt_external_auth_flag() - Set the EXTERNAL_AUTH flag 1085 * @nl80211_flag: flags to be sent to nl80211 from enum nl80211_rxmgmt_flags 1086 * 1087 * Set the flag NL80211_RXMGMT_FLAG_EXTERNAL_AUTH if supported. 1088 */ 1089 static void 1090 wlan_hdd_set_rxmgmt_external_auth_flag(enum nl80211_rxmgmt_flags *nl80211_flag) 1091 { 1092 *nl80211_flag |= NL80211_RXMGMT_FLAG_EXTERNAL_AUTH; 1093 } 1094 #else 1095 static void 1096 wlan_hdd_set_rxmgmt_external_auth_flag(enum nl80211_rxmgmt_flags *nl80211_flag) 1097 { 1098 } 1099 #endif 1100 1101 /** 1102 * wlan_hdd_cfg80211_convert_rxmgmt_flags() - Convert RXMGMT value 1103 * @nl80211_flag: Flags to be sent to nl80211 from enum nl80211_rxmgmt_flags 1104 * @flag: flags set by driver(SME/PE) from enum rxmgmt_flags 1105 * 1106 * Convert driver internal RXMGMT flag value to nl80211 defined RXMGMT flag 1107 * Return: void 1108 */ 1109 static void 1110 wlan_hdd_cfg80211_convert_rxmgmt_flags(enum rxmgmt_flags flag, 1111 enum nl80211_rxmgmt_flags *nl80211_flag) 1112 { 1113 1114 if (flag & RXMGMT_FLAG_EXTERNAL_AUTH) { 1115 wlan_hdd_set_rxmgmt_external_auth_flag(nl80211_flag); 1116 } 1117 1118 } 1119 1120 static void 1121 __hdd_indicate_mgmt_frame_to_user(struct hdd_adapter *adapter, 1122 uint32_t frm_len, uint8_t *pb_frames, 1123 uint8_t frame_type, uint32_t rx_freq, 1124 int8_t rx_rssi, enum rxmgmt_flags rx_flags) 1125 { 1126 uint8_t type = 0; 1127 uint8_t sub_type = 0; 1128 struct hdd_context *hdd_ctx; 1129 uint8_t *dest_addr = NULL; 1130 uint16_t auth_algo; 1131 enum nl80211_rxmgmt_flags nl80211_flag = 0; 1132 bool is_pasn_auth_frame = false; 1133 struct hdd_adapter *assoc_adapter; 1134 bool eht_capab; 1135 struct hdd_ap_ctx *ap_ctx; 1136 1137 hdd_debug("Frame Type = %d Frame Length = %d freq = %d", 1138 frame_type, frm_len, rx_freq); 1139 1140 if (!adapter) { 1141 hdd_err("adapter is NULL"); 1142 return; 1143 } 1144 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 1145 1146 if (!frm_len) { 1147 hdd_err("Frame Length is Invalid ZERO"); 1148 return; 1149 } 1150 1151 if (!pb_frames) { 1152 hdd_err("pbFrames is NULL"); 1153 return; 1154 } 1155 1156 type = WLAN_HDD_GET_TYPE_FRM_FC(pb_frames[0]); 1157 sub_type = WLAN_HDD_GET_SUBTYPE_FRM_FC(pb_frames[0]); 1158 if (type == SIR_MAC_MGMT_FRAME && 1159 sub_type == SIR_MAC_MGMT_AUTH && 1160 frm_len > (sizeof(struct wlan_frame_hdr) + 1161 WLAN_AUTH_FRAME_MIN_LEN)) { 1162 auth_algo = *(uint16_t *)(pb_frames + 1163 sizeof(struct wlan_frame_hdr)); 1164 if (auth_algo == eSIR_AUTH_TYPE_PASN) { 1165 is_pasn_auth_frame = true; 1166 } else if (auth_algo == eSIR_FT_AUTH && 1167 (adapter->device_mode == QDF_SAP_MODE || 1168 adapter->device_mode == QDF_P2P_GO_MODE)) { 1169 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink); 1170 ap_ctx->during_auth_offload = true; 1171 } 1172 } 1173 1174 /* Get adapter from Destination mac address of the frame */ 1175 if (type == SIR_MAC_MGMT_FRAME && 1176 sub_type != SIR_MAC_MGMT_PROBE_REQ && !is_pasn_auth_frame && 1177 !qdf_is_macaddr_broadcast( 1178 (struct qdf_mac_addr *)&pb_frames[WLAN_HDD_80211_FRM_DA_OFFSET])) { 1179 dest_addr = &pb_frames[WLAN_HDD_80211_FRM_DA_OFFSET]; 1180 adapter = hdd_get_adapter_by_macaddr(hdd_ctx, dest_addr); 1181 if (!adapter) 1182 adapter = hdd_get_adapter_by_rand_macaddr(hdd_ctx, 1183 dest_addr); 1184 if (!adapter) { 1185 /* 1186 * Under assumption that we don't receive any action 1187 * frame with BCST as destination, 1188 * we are dropping action frame 1189 */ 1190 hdd_err("adapter for action frame is NULL Macaddr = " 1191 QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(dest_addr)); 1192 hdd_debug("Frame Type = %d Frame Length = %d subType = %d", 1193 frame_type, frm_len, sub_type); 1194 /* 1195 * We will receive broadcast management frames 1196 * in OCB mode 1197 */ 1198 adapter = hdd_get_adapter(hdd_ctx, QDF_OCB_MODE); 1199 if (!adapter || !qdf_is_macaddr_broadcast( 1200 (struct qdf_mac_addr *)dest_addr)) { 1201 /* 1202 * Under assumption that we don't 1203 * receive any action frame with BCST 1204 * as destination, we are dropping 1205 * action frame 1206 */ 1207 return; 1208 } 1209 } 1210 } 1211 1212 if (!adapter->dev) { 1213 hdd_err("adapter->dev is NULL"); 1214 return; 1215 } 1216 1217 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) { 1218 hdd_err("adapter has invalid magic"); 1219 return; 1220 } 1221 1222 /* Channel indicated may be wrong. TODO */ 1223 /* Indicate an action frame. */ 1224 1225 if (hdd_is_qos_action_frame(pb_frames, frm_len)) 1226 sme_update_dsc_pto_up_mapping(hdd_ctx->mac_handle, 1227 adapter->dscp_to_up_map, 1228 adapter->deflink->vdev_id); 1229 1230 assoc_adapter = adapter; 1231 ucfg_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab); 1232 if (hdd_adapter_is_link_adapter(adapter) && eht_capab) { 1233 hdd_debug("adapter is not ml adapter move to ml adapter"); 1234 assoc_adapter = hdd_adapter_get_mlo_adapter_from_link(adapter); 1235 if (!assoc_adapter) { 1236 hdd_err("Assoc adapter is NULL"); 1237 return; 1238 } 1239 } 1240 1241 /* Indicate Frame Over Normal Interface */ 1242 hdd_debug("Indicate Frame over NL80211 sessionid : %d, idx :%d", 1243 assoc_adapter->deflink->vdev_id, 1244 assoc_adapter->dev->ifindex); 1245 1246 wlan_hdd_cfg80211_convert_rxmgmt_flags(rx_flags, &nl80211_flag); 1247 1248 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) 1249 cfg80211_rx_mgmt(assoc_adapter->dev->ieee80211_ptr, 1250 rx_freq, rx_rssi * 100, pb_frames, 1251 frm_len, NL80211_RXMGMT_FLAG_ANSWERED | nl80211_flag); 1252 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) 1253 cfg80211_rx_mgmt(assoc_adapter->dev->ieee80211_ptr, 1254 rx_freq, rx_rssi * 100, pb_frames, 1255 frm_len, NL80211_RXMGMT_FLAG_ANSWERED, 1256 GFP_ATOMIC); 1257 #else 1258 cfg80211_rx_mgmt(assoc_adapter->dev->ieee80211_ptr, rx_freq, 1259 rx_rssi * 100, 1260 pb_frames, frm_len, GFP_ATOMIC); 1261 #endif /* LINUX_VERSION_CODE */ 1262 } 1263 1264 void hdd_indicate_mgmt_frame_to_user(struct hdd_adapter *adapter, 1265 uint32_t frm_len, uint8_t *pb_frames, 1266 uint8_t frame_type, uint32_t rx_freq, 1267 int8_t rx_rssi, enum rxmgmt_flags rx_flags) 1268 { 1269 int errno; 1270 struct osif_vdev_sync *vdev_sync; 1271 1272 errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync); 1273 if (errno) 1274 return; 1275 1276 __hdd_indicate_mgmt_frame_to_user(adapter, frm_len, pb_frames, 1277 frame_type, rx_freq, 1278 rx_rssi, rx_flags); 1279 osif_vdev_sync_op_stop(vdev_sync); 1280 } 1281 1282 int wlan_hdd_set_power_save(struct hdd_adapter *adapter, 1283 struct p2p_ps_config *ps_config) 1284 { 1285 struct wlan_objmgr_psoc *psoc; 1286 struct hdd_context *hdd_ctx; 1287 QDF_STATUS status; 1288 1289 if (!adapter || !ps_config) { 1290 hdd_err("null param, adapter:%pK, ps_config:%pK", 1291 adapter, ps_config); 1292 return -EINVAL; 1293 } 1294 1295 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 1296 psoc = hdd_ctx->psoc; 1297 if (!psoc) { 1298 hdd_err("psoc is null"); 1299 return -EINVAL; 1300 } 1301 1302 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", 1303 ps_config->opp_ps, ps_config->ct_window, 1304 ps_config->duration, ps_config->interval, 1305 ps_config->count, ps_config->start, 1306 ps_config->single_noa_duration, 1307 ps_config->ps_selection, ps_config->vdev_id); 1308 1309 status = ucfg_p2p_set_ps(psoc, ps_config); 1310 hdd_debug("p2p set power save, status:%d", status); 1311 1312 /* P2P-GO-NOA and TWT do not go hand in hand */ 1313 if (ps_config->duration) { 1314 hdd_send_twt_role_disable_cmd(hdd_ctx, TWT_RESPONDER); 1315 } else { 1316 hdd_send_twt_requestor_enable_cmd(hdd_ctx); 1317 hdd_send_twt_responder_enable_cmd(hdd_ctx); 1318 } 1319 1320 return qdf_status_to_os_return(status); 1321 } 1322 1323 /** 1324 * wlan_hdd_update_mcc_p2p_quota() - Function to Update P2P 1325 * quota to FW 1326 * @adapter: Pointer to HDD adapter 1327 * @is_set: 0-reset, 1-set 1328 * 1329 * This function passes down the value of MAS to UMAC 1330 * 1331 * Return: none 1332 * 1333 */ 1334 static void wlan_hdd_update_mcc_p2p_quota(struct hdd_adapter *adapter, 1335 bool is_set) 1336 { 1337 1338 hdd_info("Set/reset P2P quota: %d", is_set); 1339 if (is_set) { 1340 if (adapter->device_mode == QDF_STA_MODE) 1341 wlan_hdd_set_mcc_p2p_quota(adapter, 1342 100 - HDD_DEFAULT_MCC_P2P_QUOTA 1343 ); 1344 else if (adapter->device_mode == QDF_P2P_GO_MODE) 1345 wlan_hdd_go_set_mcc_p2p_quota(adapter, 1346 HDD_DEFAULT_MCC_P2P_QUOTA); 1347 else 1348 wlan_hdd_set_mcc_p2p_quota(adapter, 1349 HDD_DEFAULT_MCC_P2P_QUOTA); 1350 } else { 1351 if (adapter->device_mode == QDF_P2P_GO_MODE) 1352 wlan_hdd_go_set_mcc_p2p_quota(adapter, 1353 HDD_RESET_MCC_P2P_QUOTA); 1354 else 1355 wlan_hdd_set_mcc_p2p_quota(adapter, 1356 HDD_RESET_MCC_P2P_QUOTA); 1357 } 1358 } 1359 1360 int32_t wlan_hdd_set_mas(struct hdd_adapter *adapter, uint8_t mas_value) 1361 { 1362 struct hdd_context *hdd_ctx; 1363 bool enable_mcc_adaptive_sch = false; 1364 1365 if (!adapter) { 1366 hdd_err("Adapter is NULL"); 1367 return -EINVAL; 1368 } 1369 1370 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 1371 if (!hdd_ctx) { 1372 hdd_err("HDD context is null"); 1373 return -EINVAL; 1374 } 1375 1376 if (mas_value) { 1377 hdd_info("Miracast is ON. Disable MAS and configure P2P quota"); 1378 ucfg_policy_mgr_get_mcc_adaptive_sch(hdd_ctx->psoc, 1379 &enable_mcc_adaptive_sch); 1380 if (enable_mcc_adaptive_sch) { 1381 ucfg_policy_mgr_set_dynamic_mcc_adaptive_sch( 1382 hdd_ctx->psoc, false); 1383 1384 if (QDF_STATUS_SUCCESS != sme_set_mas(false)) { 1385 hdd_err("Failed to disable MAS"); 1386 return -EAGAIN; 1387 } 1388 } 1389 1390 /* Config p2p quota */ 1391 wlan_hdd_update_mcc_p2p_quota(adapter, true); 1392 } else { 1393 hdd_info("Miracast is OFF. Enable MAS and reset P2P quota"); 1394 wlan_hdd_update_mcc_p2p_quota(adapter, false); 1395 1396 ucfg_policy_mgr_get_mcc_adaptive_sch(hdd_ctx->psoc, 1397 &enable_mcc_adaptive_sch); 1398 if (enable_mcc_adaptive_sch) { 1399 ucfg_policy_mgr_set_dynamic_mcc_adaptive_sch( 1400 hdd_ctx->psoc, true); 1401 1402 if (QDF_STATUS_SUCCESS != sme_set_mas(true)) { 1403 hdd_err("Failed to enable MAS"); 1404 return -EAGAIN; 1405 } 1406 } 1407 } 1408 1409 return 0; 1410 } 1411 1412 /** 1413 * set_first_connection_operating_channel() - Function to set 1414 * first connection oerating channel 1415 * @hdd_ctx: Hdd context 1416 * @set_value: First connection operating channel 1417 * @dev_mode: Device operating mode 1418 * 1419 * This function is used to set the first adapter operating 1420 * channel 1421 * 1422 * Return: operating channel updated in set value 1423 * 1424 */ 1425 static uint32_t set_first_connection_operating_channel( 1426 struct hdd_context *hdd_ctx, uint32_t set_value, 1427 enum QDF_OPMODE dev_mode) 1428 { 1429 uint8_t operating_channel; 1430 uint32_t oper_chan_freq; 1431 1432 oper_chan_freq = hdd_get_operating_chan_freq(hdd_ctx, dev_mode); 1433 if (!oper_chan_freq) { 1434 hdd_err(" First adapter operating channel is invalid"); 1435 return -EINVAL; 1436 } 1437 operating_channel = wlan_reg_freq_to_chan(hdd_ctx->pdev, 1438 oper_chan_freq); 1439 1440 hdd_info("First connection channel No.:%d and quota:%dms", 1441 operating_channel, set_value); 1442 /* Move the time quota for first channel to bits 15-8 */ 1443 set_value = set_value << 8; 1444 1445 /* 1446 * Store the channel number of 1st channel at bits 7-0 1447 * of the bit vector 1448 */ 1449 return set_value | operating_channel; 1450 } 1451 1452 /** 1453 * set_second_connection_operating_channel() - Function to set 1454 * second connection oerating channel 1455 * @hdd_ctx: Hdd context 1456 * @set_value: Second connection operating channel 1457 * @vdev_id: vdev id 1458 * 1459 * This function is used to set the first adapter operating 1460 * channel 1461 * 1462 * Return: operating channel updated in set value 1463 * 1464 */ 1465 static uint32_t set_second_connection_operating_channel( 1466 struct hdd_context *hdd_ctx, uint32_t set_value, 1467 uint8_t vdev_id) 1468 { 1469 uint8_t operating_channel; 1470 1471 operating_channel = wlan_reg_freq_to_chan(hdd_ctx->pdev, 1472 policy_mgr_get_mcc_operating_channel( 1473 hdd_ctx->psoc, vdev_id)); 1474 1475 if (operating_channel == 0) { 1476 hdd_err("Second adapter operating channel is invalid"); 1477 return -EINVAL; 1478 } 1479 1480 hdd_info("Second connection channel No.:%d and quota:%dms", 1481 operating_channel, set_value); 1482 /* 1483 * Now move the time quota and channel number of the 1484 * 1st adapter to bits 23-16 and bits 15-8 of the bit 1485 * vector, respectively. 1486 */ 1487 set_value = set_value << 8; 1488 1489 /* 1490 * Set the channel number for 2nd MCC vdev at bits 1491 * 7-0 of set_value 1492 */ 1493 return set_value | operating_channel; 1494 } 1495 1496 /** 1497 * wlan_hdd_set_mcc_p2p_quota() - Function to set quota for P2P 1498 * @adapter: HDD adapter 1499 * @set_value: Quota value for the interface 1500 * 1501 * This function is used to set the quota for P2P cases 1502 * 1503 * Return: Configuration message posting status, SUCCESS or Fail 1504 * 1505 */ 1506 int wlan_hdd_set_mcc_p2p_quota(struct hdd_adapter *adapter, 1507 uint32_t set_value) 1508 { 1509 int32_t ret = 0; 1510 uint32_t concurrent_state; 1511 struct hdd_context *hdd_ctx; 1512 uint32_t sta_cli_bit_mask = QDF_STA_MASK | QDF_P2P_CLIENT_MASK; 1513 uint32_t sta_go_bit_mask = QDF_STA_MASK | QDF_P2P_GO_MASK; 1514 1515 if (!adapter) { 1516 hdd_err("Invalid adapter"); 1517 return -EFAULT; 1518 } 1519 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 1520 if (!hdd_ctx) { 1521 hdd_err("HDD context is null"); 1522 return -EINVAL; 1523 } 1524 1525 concurrent_state = policy_mgr_get_concurrency_mode( 1526 hdd_ctx->psoc); 1527 /* 1528 * Check if concurrency mode is active. 1529 * Need to modify this code to support MCC modes other than STA/P2P 1530 */ 1531 if (((concurrent_state & sta_cli_bit_mask) == sta_cli_bit_mask) || 1532 ((concurrent_state & sta_go_bit_mask) == sta_go_bit_mask)) { 1533 hdd_info("STA & P2P are both enabled"); 1534 1535 /* 1536 * The channel numbers for both adapters and the time 1537 * quota for the 1st adapter, i.e., one specified in cmd 1538 * are formatted as a bit vector then passed on to WMA 1539 * +***********************************************************+ 1540 * |bit 31-24 | bit 23-16 | bits 15-8 | bits 7-0 | 1541 * | Unused | Quota for | chan. # for | chan. # for | 1542 * | | 1st chan. | 1st chan. | 2nd chan. | 1543 * +***********************************************************+ 1544 */ 1545 1546 set_value = set_first_connection_operating_channel( 1547 hdd_ctx, set_value, adapter->device_mode); 1548 1549 set_value = set_second_connection_operating_channel( 1550 hdd_ctx, set_value, adapter->deflink->vdev_id); 1551 1552 ret = wlan_hdd_send_mcc_vdev_quota(adapter, set_value); 1553 } else { 1554 hdd_info("MCC is not active. Exit w/o setting latency"); 1555 } 1556 1557 return ret; 1558 } 1559 1560 int wlan_hdd_go_set_mcc_p2p_quota(struct hdd_adapter *hostapd_adapter, 1561 uint32_t set_value) 1562 { 1563 return wlan_hdd_set_mcc_p2p_quota(hostapd_adapter, set_value); 1564 } 1565 1566 void wlan_hdd_set_mcc_latency(struct hdd_adapter *adapter, int set_value) 1567 { 1568 uint32_t concurrent_state; 1569 struct hdd_context *hdd_ctx; 1570 uint32_t sta_cli_bit_mask = QDF_STA_MASK | QDF_P2P_CLIENT_MASK; 1571 uint32_t sta_go_bit_mask = QDF_STA_MASK | QDF_P2P_GO_MASK; 1572 1573 if (!adapter) { 1574 hdd_err("Invalid adapter"); 1575 return; 1576 } 1577 1578 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 1579 if (!hdd_ctx) { 1580 hdd_err("HDD context is null"); 1581 return; 1582 } 1583 1584 concurrent_state = policy_mgr_get_concurrency_mode( 1585 hdd_ctx->psoc); 1586 /** 1587 * Check if concurrency mode is active. 1588 * Need to modify this code to support MCC modes other than STA/P2P 1589 */ 1590 if (((concurrent_state & sta_cli_bit_mask) == sta_cli_bit_mask) || 1591 ((concurrent_state & sta_go_bit_mask) == sta_go_bit_mask)) { 1592 hdd_info("STA & P2P are both enabled"); 1593 /* 1594 * The channel number and latency are formatted in 1595 * a bit vector then passed on to WMA layer. 1596 * +**********************************************+ 1597 * |bits 31-16 | bits 15-8 | bits 7-0 | 1598 * | Unused | latency - Chan. 1 | channel no. | 1599 * +**********************************************+ 1600 */ 1601 set_value = set_first_connection_operating_channel( 1602 hdd_ctx, set_value, adapter->device_mode); 1603 1604 wlan_hdd_send_mcc_latency(adapter, set_value); 1605 } else { 1606 hdd_info("MCC is not active. Exit w/o setting latency"); 1607 } 1608 } 1609