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