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