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