1 /*
2  * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /**
19  * DOC: wlan_hdd_dcs.c
20  *
21  * DCS implementation.
22  *
23  */
24 
25 #include <wlan_hdd_hostapd.h>
26 #include <wlan_hdd_dcs.h>
27 #include <wlan_hdd_includes.h>
28 #include <wlan_dcs_ucfg_api.h>
29 #include <wlan_dlm_ucfg_api.h>
30 #include <wlan_osif_priv.h>
31 #include <wlan_objmgr_vdev_obj.h>
32 #include <wlan_dcs_ucfg_api.h>
33 
34 /* Time(in milliseconds) before which the AP doesn't expect a connection */
35 #define HDD_DCS_AWGN_BSS_RETRY_DELAY (5 * 60 * 1000)
36 
37 /**
38  * hdd_dcs_add_bssid_to_reject_list() - add bssid to reject list
39  * @pdev: pdev ptr
40  * @bssid: bssid to be added
41  *
42  * Return: QDF_STATUS
43  */
44 static QDF_STATUS
hdd_dcs_add_bssid_to_reject_list(struct wlan_objmgr_pdev * pdev,struct qdf_mac_addr * bssid)45 hdd_dcs_add_bssid_to_reject_list(struct wlan_objmgr_pdev *pdev,
46 				 struct qdf_mac_addr *bssid)
47 {
48 	struct reject_ap_info ap_info;
49 
50 	qdf_mem_zero(&ap_info, sizeof(struct reject_ap_info));
51 	qdf_copy_macaddr(&ap_info.bssid, bssid);
52 	/* set retry_delay to reject new connect requests */
53 	ap_info.rssi_reject_params.retry_delay =
54 		HDD_DCS_AWGN_BSS_RETRY_DELAY;
55 	ap_info.reject_ap_type = DRIVER_RSSI_REJECT_TYPE;
56 	ap_info.reject_reason = REASON_STA_KICKOUT;
57 	ap_info.source = ADDED_BY_DRIVER;
58 	return ucfg_dlm_add_bssid_to_reject_list(pdev, &ap_info);
59 }
60 
61 /**
62  * hdd_dcs_switch_chan_cb() - hdd dcs switch channel callback
63  * @vdev: vdev ptr
64  * @tgt_freq: target channel frequency
65  * @tgt_width: target channel width
66  *
67  * This callback is registered with dcs component to trigger channel switch.
68  *
69  * Return: QDF_STATUS
70  */
hdd_dcs_switch_chan_cb(struct wlan_objmgr_vdev * vdev,qdf_freq_t tgt_freq,enum phy_ch_width tgt_width)71 static QDF_STATUS hdd_dcs_switch_chan_cb(struct wlan_objmgr_vdev *vdev,
72 					 qdf_freq_t tgt_freq,
73 					 enum phy_ch_width tgt_width)
74 {
75 	struct hdd_adapter *adapter;
76 	struct wlan_hdd_link_info *link_info;
77 	mac_handle_t mac_handle;
78 	struct qdf_mac_addr *bssid;
79 	int ret;
80 	QDF_STATUS status = QDF_STATUS_SUCCESS;
81 	struct wlan_objmgr_pdev *pdev;
82 	struct wlan_objmgr_psoc *psoc;
83 
84 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
85 	if (!link_info) {
86 		hdd_err("Invalid vdev %d", wlan_vdev_get_id(vdev));
87 		return QDF_STATUS_E_INVAL;
88 	}
89 
90 	adapter = link_info->adapter;
91 	switch (adapter->device_mode) {
92 	case QDF_STA_MODE:
93 		if (!hdd_cm_is_vdev_associated(link_info))
94 			return QDF_STATUS_E_INVAL;
95 
96 		bssid = &link_info->session.station.conn_info.bssid;
97 
98 		/* disconnect if got invalid freq or width */
99 		if (tgt_freq == 0 || tgt_width == CH_WIDTH_INVALID) {
100 			pdev = wlan_vdev_get_pdev(vdev);
101 			if (!pdev)
102 				return QDF_STATUS_E_INVAL;
103 
104 			hdd_dcs_add_bssid_to_reject_list(pdev, bssid);
105 			wlan_hdd_cm_issue_disconnect(link_info,
106 						     REASON_UNSPEC_FAILURE,
107 						     true);
108 			return QDF_STATUS_SUCCESS;
109 		}
110 
111 		mac_handle = hdd_context_get_mac_handle(adapter->hdd_ctx);
112 		if (!mac_handle)
113 			return QDF_STATUS_E_INVAL;
114 
115 		status = sme_switch_channel(mac_handle, bssid,
116 					    tgt_freq, tgt_width);
117 		break;
118 	case QDF_SAP_MODE:
119 		if (!test_bit(SOFTAP_BSS_STARTED, &link_info->link_flags))
120 			return QDF_STATUS_E_INVAL;
121 
122 		/* stop sap if got invalid freq or width */
123 		if (tgt_freq == 0 || tgt_width == CH_WIDTH_INVALID) {
124 			schedule_work(&adapter->sap_stop_bss_work);
125 			return QDF_STATUS_SUCCESS;
126 		}
127 
128 		psoc = wlan_vdev_get_psoc(vdev);
129 		if (!psoc)
130 			return QDF_STATUS_E_INVAL;
131 
132 		wlan_hdd_set_sap_csa_reason(psoc, link_info->vdev_id,
133 					    CSA_REASON_DCS);
134 		ret = hdd_softap_set_channel_change(adapter->dev, tgt_freq,
135 						    tgt_width, true);
136 		status = qdf_status_from_os_return(ret);
137 		break;
138 	default:
139 		hdd_err("OP mode %d not supported", adapter->device_mode);
140 		break;
141 	}
142 
143 	return status;
144 }
145 
146 #ifdef WLAN_FEATURE_SAP_ACS_OPTIMIZE
147 /**
148  * hdd_get_bw_for_freq - get BW for provided freq
149  * @res_msg: resp msg with freq info
150  * @freq: freq for which BW is required
151  * @total_chan: total no of channels
152  *
153  * Return: bandwidth
154  */
155 static enum phy_ch_width
hdd_get_bw_for_freq(struct get_usable_chan_res_params * res_msg,uint16_t freq,uint16_t total_chan)156 hdd_get_bw_for_freq(struct get_usable_chan_res_params *res_msg,
157 		    uint16_t freq, uint16_t total_chan)
158 {
159 	uint16_t i;
160 
161 	for (i = 0; i < total_chan; i++) {
162 		if (res_msg[i].freq == freq)
163 			return res_msg[i].bw;
164 	}
165 	return CH_WIDTH_INVALID;
166 }
167 
168 /**
169  * hdd_dcs_select_random_chan: To select random 6G channel
170  * for CSA
171  * @pdev: pdev object
172  * @vdev: vdevobject
173  *
174  * Return: success/failure
175  */
176 static QDF_STATUS
hdd_dcs_select_random_chan(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev)177 hdd_dcs_select_random_chan(struct wlan_objmgr_pdev *pdev,
178 			   struct wlan_objmgr_vdev *vdev)
179 {
180 	struct get_usable_chan_req_params req_msg;
181 	struct get_usable_chan_res_params *res_msg;
182 	enum phy_ch_width tgt_width;
183 	uint16_t final_lst[NUM_CHANNELS] = {0};
184 	uint16_t intf_ch_freq = 0;
185 	uint32_t count;
186 	uint32_t i;
187 	QDF_STATUS status = QDF_STATUS_E_EMPTY;
188 
189 	res_msg = qdf_mem_malloc(NUM_CHANNELS *
190 			sizeof(*res_msg));
191 
192 	if (!res_msg) {
193 		hdd_err("res_msg invalid");
194 		return QDF_STATUS_E_NOMEM;
195 	}
196 	req_msg.band_mask = BIT(REG_BAND_6G);
197 	req_msg.iface_mode_mask = BIT(NL80211_IFTYPE_AP);
198 	req_msg.filter_mask = 0;
199 	status = wlan_reg_get_usable_channel(pdev, req_msg, res_msg, &count,
200 					     REG_CURRENT_PWR_MODE);
201 	if (QDF_STATUS_SUCCESS != status) {
202 		hdd_err("get usable channel failed %d", status);
203 		qdf_mem_free(res_msg);
204 		return QDF_STATUS_E_INVAL;
205 	}
206 	hdd_debug("channel count %d for band %d", count, REG_BAND_6G);
207 	for (i = 0; i < count; i++)
208 		final_lst[i] = res_msg[i].freq;
209 
210 	intf_ch_freq = wlan_get_rand_from_lst_for_freq(final_lst, count);
211 	if (!intf_ch_freq || intf_ch_freq > wlan_reg_max_6ghz_chan_freq()) {
212 		hdd_debug("ch freq gt max 6g freq %d",
213 			  wlan_reg_max_6ghz_chan_freq());
214 		qdf_mem_free(res_msg);
215 		return QDF_STATUS_E_INVAL;
216 	}
217 	tgt_width = hdd_get_bw_for_freq(res_msg, intf_ch_freq, count);
218 	if (tgt_width >= CH_WIDTH_INVALID) {
219 		qdf_mem_free(res_msg);
220 		return QDF_STATUS_E_INVAL;
221 	}
222 	if (tgt_width > CH_WIDTH_160MHZ) {
223 		hdd_debug("restrict max bw to 160");
224 		tgt_width = CH_WIDTH_160MHZ;
225 	}
226 	qdf_mem_free(res_msg);
227 	return ucfg_dcs_switch_chan(vdev, intf_ch_freq,
228 				    tgt_width);
229 }
230 #else
231 static inline QDF_STATUS
hdd_dcs_select_random_chan(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev)232 hdd_dcs_select_random_chan(struct wlan_objmgr_pdev *pdev,
233 			   struct wlan_objmgr_vdev *vdev)
234 {
235 	return QDF_STATUS_E_NOSUPPORT;
236 }
237 #endif
238 
239 /**
240  * hdd_dcs_cb() - hdd dcs specific callback
241  * @psoc: psoc
242  * @mac_id: mac_id
243  * @interference_type: wlan or continuous wave interference type
244  * @arg: List of arguments
245  *
246  * This callback is registered with dcs component to start acs operation
247  *
248  * Return: None
249  */
hdd_dcs_cb(struct wlan_objmgr_psoc * psoc,uint8_t mac_id,uint8_t interference_type,void * arg)250 static void hdd_dcs_cb(struct wlan_objmgr_psoc *psoc, uint8_t mac_id,
251 		       uint8_t interference_type, void *arg)
252 {
253 	struct hdd_context *hdd_ctx = (struct hdd_context *)arg;
254 	struct wlan_hdd_link_info *link_info;
255 	struct sap_context *sap_ctx;
256 	uint32_t count;
257 	uint32_t list[MAX_NUMBER_OF_CONC_CONNECTIONS];
258 	uint32_t index;
259 	QDF_STATUS status;
260 
261 	/*
262 	 * so far CAP_DCS_CWIM interference mitigation is not supported
263 	 */
264 	if (interference_type == WLAN_HOST_DCS_CWIM) {
265 		hdd_debug("CW interference mitigation is not supported");
266 		return;
267 	}
268 
269 	if (policy_mgr_is_force_scc(psoc) &&
270 	    policy_mgr_is_sta_gc_active_on_mac(psoc, mac_id)) {
271 		ucfg_config_dcs_event_data(psoc, mac_id, true);
272 
273 		hdd_debug("force scc %d, mac id %d sta gc count %d",
274 			  policy_mgr_is_force_scc(psoc), mac_id,
275 			  policy_mgr_is_sta_gc_active_on_mac(psoc, mac_id));
276 		return;
277 	}
278 
279 	count = policy_mgr_get_sap_go_count_on_mac(psoc, list, mac_id);
280 	for (index = 0; index < count; index++) {
281 		link_info = hdd_get_link_info_by_vdev(hdd_ctx, list[index]);
282 		if (!link_info) {
283 			hdd_err("vdev_id %u does not exist with host",
284 				list[index]);
285 			return;
286 		}
287 
288 		sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
289 		if (!wlansap_dcs_is_wlan_interference_mitigation_enabled(sap_ctx))
290 			continue;
291 
292 		hdd_debug("DCS triggers ACS on vdev_id=%u, mac_id=%u",
293 			  list[index], mac_id);
294 		/*
295 		 * Select Random channel for low latency sap as
296 		 * ACS can't select channel of same MAC from which
297 		 * CSA is triggered because same MAC frequencies
298 		 * will not be present in scan list and results and
299 		 * selecting freq of other MAC may cause MCC with
300 		 * other modes if present.
301 		 */
302 		if (wlan_mlme_get_ap_policy(link_info->vdev) !=
303 		    HOST_CONCURRENT_AP_POLICY_UNSPECIFIED) {
304 			status = hdd_dcs_select_random_chan(hdd_ctx->pdev,
305 							    link_info->vdev);
306 			if (QDF_IS_STATUS_SUCCESS(status))
307 				return;
308 		}
309 		wlan_hdd_cfg80211_start_acs(link_info);
310 		return;
311 	}
312 }
313 
314 #ifdef CONFIG_AFC_SUPPORT
315 /**
316  * hdd_dcs_afc_sel_chan_cb() - Callback to select best SAP channel/bandwidth
317  *                             after channel state update by AFC
318  * @arg: argument
319  * @vdev_id: vdev id of SAP
320  * @cur_freq: SAP current channel frequency
321  * @cur_bw: SAP current channel bandwidth
322  * @pref_bw: pointer to channel bandwidth prefer to set as input and output
323  *           as target bandwidth can set
324  *
325  * Return: Target home channel frequency selected
326  */
hdd_dcs_afc_sel_chan_cb(void * arg,uint32_t vdev_id,qdf_freq_t cur_freq,enum phy_ch_width cur_bw,enum phy_ch_width * pref_bw)327 static qdf_freq_t hdd_dcs_afc_sel_chan_cb(void *arg,
328 					  uint32_t vdev_id,
329 					  qdf_freq_t cur_freq,
330 					  enum phy_ch_width cur_bw,
331 					  enum phy_ch_width *pref_bw)
332 {
333 	struct hdd_context *hdd_ctx = (struct hdd_context *)arg;
334 	struct wlan_hdd_link_info *link_info;
335 	struct sap_context *sap_ctx;
336 	qdf_freq_t target_freq;
337 
338 	if (!hdd_ctx)
339 		return 0;
340 
341 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
342 	if (!link_info)
343 		return 0;
344 
345 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
346 	if (!sap_ctx)
347 		return 0;
348 
349 	target_freq = sap_afc_dcs_sel_chan(sap_ctx, cur_freq, cur_bw, pref_bw);
350 
351 	return target_freq;
352 }
353 #else
hdd_dcs_afc_sel_chan_cb(void * arg,uint32_t vdev_id,qdf_freq_t cur_freq,enum phy_ch_width cur_bw,enum phy_ch_width * pref_bw)354 static inline qdf_freq_t hdd_dcs_afc_sel_chan_cb(void *arg,
355 						 uint32_t vdev_id,
356 						 qdf_freq_t cur_freq,
357 						 enum phy_ch_width cur_bw,
358 						 enum phy_ch_width *pref_bw)
359 {
360 	return 0;
361 }
362 #endif
363 
hdd_dcs_register_cb(struct hdd_context * hdd_ctx)364 void hdd_dcs_register_cb(struct hdd_context *hdd_ctx)
365 {
366 	ucfg_dcs_register_cb(hdd_ctx->psoc, hdd_dcs_cb, hdd_ctx);
367 	ucfg_dcs_register_awgn_cb(hdd_ctx->psoc, hdd_dcs_switch_chan_cb);
368 	ucfg_dcs_register_afc_sel_chan_cb(hdd_ctx->psoc,
369 					  hdd_dcs_afc_sel_chan_cb,
370 					  hdd_ctx);
371 }
372 
hdd_dcs_hostapd_set_chan(struct hdd_context * hdd_ctx,uint8_t vdev_id,qdf_freq_t dcs_ch_freq)373 QDF_STATUS hdd_dcs_hostapd_set_chan(struct hdd_context *hdd_ctx,
374 				    uint8_t vdev_id,
375 				    qdf_freq_t dcs_ch_freq)
376 {
377 	struct hdd_ap_ctx *ap_ctx;
378 	struct sap_context *sap_ctx;
379 	QDF_STATUS status;
380 	uint8_t mac_id;
381 	uint32_t list[MAX_NUMBER_OF_CONC_CONNECTIONS];
382 	uint32_t conn_idx, count;
383 	struct wlan_hdd_link_info *link_info;
384 	uint32_t dcs_ch = wlan_reg_freq_to_chan(hdd_ctx->pdev, dcs_ch_freq);
385 
386 	status = policy_mgr_get_mac_id_by_session_id(hdd_ctx->psoc, vdev_id,
387 						     &mac_id);
388 
389 	if (QDF_IS_STATUS_ERROR(status)) {
390 		hdd_err("get mac id failed");
391 		return QDF_STATUS_E_INVAL;
392 	}
393 	count = policy_mgr_get_sap_go_count_on_mac(hdd_ctx->psoc, list, mac_id);
394 
395 	/*
396 	 * Dcs can only be enabled after all vdev finish csa.
397 	 * Set vdev starting for every vdev before doing csa.
398 	 * The CSA triggered by DCS will be done in serial.
399 	 */
400 	for (conn_idx = 0; conn_idx < count; conn_idx++) {
401 		link_info = hdd_get_link_info_by_vdev(hdd_ctx, list[conn_idx]);
402 		if (!link_info) {
403 			hdd_err("vdev_id %u does not exist with host",
404 				list[conn_idx]);
405 			return QDF_STATUS_E_INVAL;
406 		}
407 
408 		ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
409 		sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
410 		if (ap_ctx->operating_chan_freq != dcs_ch_freq)
411 			wlansap_dcs_set_vdev_starting(sap_ctx, true);
412 		else
413 			wlansap_dcs_set_vdev_starting(sap_ctx, false);
414 	}
415 	for (conn_idx = 0; conn_idx < count; conn_idx++) {
416 		link_info = hdd_get_link_info_by_vdev(hdd_ctx, list[conn_idx]);
417 		if (!link_info) {
418 			hdd_err("vdev_id %u does not exist with host",
419 				list[conn_idx]);
420 			return QDF_STATUS_E_INVAL;
421 		}
422 
423 		ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
424 		if (ap_ctx->operating_chan_freq == dcs_ch_freq)
425 			continue;
426 
427 		hdd_ctx->acs_policy.acs_chan_freq = AUTO_CHANNEL_SELECT;
428 		hdd_debug("dcs triggers old ch:%d new ch:%d",
429 			  ap_ctx->operating_chan_freq, dcs_ch_freq);
430 		wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc,
431 					    link_info->vdev_id, CSA_REASON_DCS);
432 		status = hdd_switch_sap_channel(link_info, dcs_ch, true);
433 		if (status == QDF_STATUS_SUCCESS)
434 			status = QDF_STATUS_E_PENDING;
435 		return status;
436 	}
437 
438 	return QDF_STATUS_SUCCESS;
439 }
440 
441 /**
442  * hdd_dcs_hostapd_enable_wlan_interference_mitigation() - enable wlan
443  * interference mitigation
444  * @hdd_ctx: hdd ctx
445  * @vdev_id: vdev id
446  *
447  * This function is used to enable wlan interference mitigation through
448  * send dcs command.
449  *
450  * Return: None
451  */
hdd_dcs_hostapd_enable_wlan_interference_mitigation(struct hdd_context * hdd_ctx,uint8_t vdev_id)452 static void hdd_dcs_hostapd_enable_wlan_interference_mitigation(
453 					struct hdd_context *hdd_ctx,
454 					uint8_t vdev_id)
455 {
456 	QDF_STATUS status;
457 	uint8_t mac_id;
458 	struct wlan_hdd_link_info *link_info;
459 	struct hdd_ap_ctx *ap_ctx;
460 	struct sap_context *sap_ctx;
461 
462 	status = policy_mgr_get_mac_id_by_session_id(hdd_ctx->psoc, vdev_id,
463 						     &mac_id);
464 	if (QDF_IS_STATUS_ERROR(status)) {
465 		hdd_err("get mac id failed");
466 		return;
467 	}
468 
469 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
470 	if (!link_info) {
471 		hdd_err("vdev_id %u does not exist with host", vdev_id);
472 		return;
473 	}
474 
475 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
476 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
477 	if (wlansap_dcs_is_wlan_interference_mitigation_enabled(sap_ctx) &&
478 	    !WLAN_REG_IS_24GHZ_CH_FREQ(ap_ctx->operating_chan_freq))
479 		ucfg_config_dcs_event_data(hdd_ctx->psoc, mac_id, true);
480 }
481 
hdd_dcs_chan_select_complete(struct hdd_adapter * adapter)482 void hdd_dcs_chan_select_complete(struct hdd_adapter *adapter)
483 {
484 	qdf_freq_t dcs_freq;
485 	struct hdd_context *hdd_ctx;
486 	uint32_t chan_freq;
487 	struct hdd_ap_ctx *ap_ctx;
488 
489 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
490 	if (!hdd_ctx) {
491 		hdd_err("Invalid HDD context pointer");
492 		return;
493 	}
494 
495 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
496 	dcs_freq = wlansap_dcs_get_freq(ap_ctx->sap_context);
497 	chan_freq = ap_ctx->operating_chan_freq;
498 	if (dcs_freq && dcs_freq != chan_freq)
499 		hdd_dcs_hostapd_set_chan(hdd_ctx, adapter->deflink->vdev_id,
500 					 dcs_freq);
501 	else
502 		hdd_dcs_hostapd_enable_wlan_interference_mitigation(
503 					hdd_ctx, adapter->deflink->vdev_id);
504 
505 	qdf_atomic_set(&ap_ctx->acs_in_progress, 0);
506 }
507 
hdd_dcs_clear(struct hdd_adapter * adapter)508 void hdd_dcs_clear(struct hdd_adapter *adapter)
509 {
510 	QDF_STATUS status;
511 	uint8_t mac_id;
512 	struct hdd_context *hdd_ctx;
513 	struct wlan_objmgr_psoc *psoc;
514 	uint32_t list[MAX_NUMBER_OF_CONC_CONNECTIONS];
515 	struct sap_context *sap_ctx;
516 
517 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
518 	if (!hdd_ctx) {
519 		hdd_err("Invalid HDD context pointer");
520 		return;
521 	}
522 
523 	psoc = hdd_ctx->psoc;
524 
525 	status = policy_mgr_get_mac_id_by_session_id(psoc,
526 						     adapter->deflink->vdev_id,
527 						     &mac_id);
528 	if (QDF_IS_STATUS_ERROR(status)) {
529 		hdd_err("get mac id failed");
530 		return;
531 	}
532 
533 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink);
534 	if (policy_mgr_get_sap_go_count_on_mac(psoc, list, mac_id) <= 1) {
535 		ucfg_config_dcs_disable(psoc, mac_id, WLAN_HOST_DCS_WLANIM);
536 		ucfg_wlan_dcs_cmd(psoc, mac_id, true);
537 		if (wlansap_dcs_is_wlan_interference_mitigation_enabled(sap_ctx))
538 			ucfg_dcs_clear(psoc, mac_id);
539 	}
540 
541 	wlansap_dcs_set_vdev_wlan_interference_mitigation(sap_ctx, false);
542 	wlansap_dcs_set_vdev_starting(sap_ctx, false);
543 }
544