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 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 #include "osif_vdev_sync.h"
19 #include "wlan_hdd_hostapd.h"
20 #include "wlan_hdd_pre_cac.h"
21 #include <qdf_types.h>
22 #include "osif_pre_cac.h"
23 #include "wlan_pre_cac_ucfg_api.h"
24 #include "wlan_ipa_ucfg_api.h"
25 #include "wlan_hdd_son.h"
26 #include "wlan_dp_ucfg_api.h"
27 
28 /**
29  * wlan_hdd_pre_cac_failure() - Process the pre cac failure
30  * @adapter: AP adapter
31  *
32  * Deletes the pre cac adapter
33  *
34  * Return: None
35  */
wlan_hdd_pre_cac_failure(struct hdd_adapter * adapter)36 static void wlan_hdd_pre_cac_failure(struct hdd_adapter *adapter)
37 {
38 	struct hdd_context *hdd_ctx;
39 
40 	hdd_enter();
41 
42 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
43 	if (wlan_hdd_validate_context(hdd_ctx))
44 		return;
45 
46 	wlan_hdd_stop_sap(adapter);
47 	hdd_stop_adapter(hdd_ctx, adapter);
48 
49 	hdd_exit();
50 }
51 
52 /**
53  * wlan_hdd_pre_cac_success() - Process the pre cac result
54  * @adapter: AP adapter
55  *
56  * Stops the pre cac adapter and moves the existing SAP to the pre cac
57  * channel
58  *
59  * Return: None
60  */
wlan_hdd_pre_cac_success(struct hdd_adapter * adapter)61 static void wlan_hdd_pre_cac_success(struct hdd_adapter *adapter)
62 {
63 	struct hdd_adapter *ap_adapter;
64 	int i;
65 	struct hdd_context *hdd_ctx;
66 	enum phy_ch_width pre_cac_ch_width;
67 	qdf_freq_t chan_freq;
68 
69 	hdd_enter();
70 
71 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
72 	if (!hdd_ctx) {
73 		hdd_err("HDD context is null");
74 		return;
75 	}
76 
77 	pre_cac_ch_width = wlansap_get_chan_width(
78 				WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink));
79 
80 	hdd_stop_adapter(hdd_ctx, adapter);
81 
82 	/* Prepare to switch AP from 2.4GHz channel to the pre CAC channel */
83 	ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
84 	if (!ap_adapter) {
85 		hdd_err("failed to get SAP adapter, no restart on pre CAC channel");
86 		return;
87 	}
88 
89 	/*
90 	 * Setting of the pre cac complete status will ensure that on channel
91 	 * switch to the pre CAC DFS channel, there is no CAC again.
92 	 */
93 	ucfg_pre_cac_complete_set(ap_adapter->deflink->vdev, true);
94 
95 	wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, ap_adapter->deflink->vdev_id,
96 				    CSA_REASON_PRE_CAC_SUCCESS);
97 	chan_freq = ucfg_pre_cac_get_freq(ap_adapter->deflink->vdev);
98 	i = hdd_softap_set_channel_change(ap_adapter->dev,
99 					  chan_freq,
100 					  pre_cac_ch_width, false);
101 	if (i) {
102 		hdd_err("failed to change channel");
103 		ucfg_pre_cac_complete_set(ap_adapter->deflink->vdev, false);
104 	}
105 
106 	hdd_exit();
107 }
108 
hdd_close_pre_cac_adapter(struct hdd_context * hdd_ctx)109 void hdd_close_pre_cac_adapter(struct hdd_context *hdd_ctx)
110 {
111 	struct hdd_adapter *pre_cac_adapter;
112 	struct osif_vdev_sync *vdev_sync;
113 	int errno;
114 
115 	pre_cac_adapter = hdd_get_adapter_by_iface_name(hdd_ctx,
116 							SAP_PRE_CAC_IFNAME);
117 	if (!pre_cac_adapter)
118 		return;
119 
120 	ucfg_pre_cac_clear_work(hdd_ctx->psoc);
121 	errno = osif_vdev_sync_trans_start_wait(pre_cac_adapter->dev,
122 						&vdev_sync);
123 	if (errno)
124 		return;
125 
126 	osif_vdev_sync_unregister(pre_cac_adapter->dev);
127 	osif_vdev_sync_wait_for_ops(vdev_sync);
128 
129 	wlan_hdd_release_intf_addr(hdd_ctx, pre_cac_adapter->mac_addr.bytes);
130 	pre_cac_adapter->is_virtual_iface = true;
131 	hdd_close_adapter(hdd_ctx, pre_cac_adapter, true);
132 
133 	osif_vdev_sync_trans_stop(vdev_sync);
134 	osif_vdev_sync_destroy(vdev_sync);
135 }
136 
wlan_set_def_pre_cac_chan(struct hdd_context * hdd_ctx,uint32_t pre_cac_ch_freq,struct cfg80211_chan_def * chandef,enum nl80211_channel_type * chantype,enum phy_ch_width * ch_width)137 static int wlan_set_def_pre_cac_chan(struct hdd_context *hdd_ctx,
138 				     uint32_t pre_cac_ch_freq,
139 				     struct cfg80211_chan_def *chandef,
140 				     enum nl80211_channel_type *chantype,
141 				     enum phy_ch_width *ch_width)
142 {
143 	enum nl80211_channel_type channel_type;
144 	struct ieee80211_channel *ieee_chan;
145 	struct ch_params ch_params = {0};
146 
147 	ieee_chan = ieee80211_get_channel(hdd_ctx->wiphy,
148 					  pre_cac_ch_freq);
149 	if (!ieee_chan) {
150 		hdd_err("channel conversion failed %d", pre_cac_ch_freq);
151 		return -EINVAL;
152 	}
153 	ch_params.ch_width = *ch_width;
154 	wlan_reg_set_channel_params_for_pwrmode(hdd_ctx->pdev,
155 						pre_cac_ch_freq, 0,
156 						&ch_params,
157 						REG_CURRENT_PWR_MODE);
158 	switch (ch_params.sec_ch_offset) {
159 	case HIGH_PRIMARY_CH:
160 		channel_type = NL80211_CHAN_HT40MINUS;
161 		break;
162 	case LOW_PRIMARY_CH:
163 		channel_type = NL80211_CHAN_HT40PLUS;
164 		break;
165 	default:
166 		channel_type = NL80211_CHAN_HT20;
167 		break;
168 	}
169 	cfg80211_chandef_create(chandef, ieee_chan, channel_type);
170 	switch (ch_params.ch_width) {
171 	case CH_WIDTH_80MHZ:
172 		chandef->width = NL80211_CHAN_WIDTH_80;
173 		break;
174 	case CH_WIDTH_80P80MHZ:
175 		chandef->width = NL80211_CHAN_WIDTH_80P80;
176 		if (ch_params.mhz_freq_seg1)
177 			chandef->center_freq2 = ch_params.mhz_freq_seg1;
178 		break;
179 	case CH_WIDTH_160MHZ:
180 		chandef->width = NL80211_CHAN_WIDTH_160;
181 		break;
182 	default:
183 		break;
184 	}
185 	if (ch_params.ch_width == CH_WIDTH_80MHZ ||
186 	    ch_params.ch_width == CH_WIDTH_80P80MHZ ||
187 	    ch_params.ch_width == CH_WIDTH_160MHZ) {
188 		if (ch_params.mhz_freq_seg0)
189 			chandef->center_freq1 = ch_params.mhz_freq_seg0;
190 	}
191 	*chantype = channel_type;
192 	*ch_width = ch_params.ch_width;
193 	hdd_debug("pre cac ch def: chan:%d width:%d freq1:%d freq2:%d",
194 		  chandef->chan->center_freq, chandef->width,
195 		  chandef->center_freq1, chandef->center_freq2);
196 
197 	return 0;
198 }
199 
200 /**
201  * __wlan_hdd_request_pre_cac() - Start pre CAC in the driver
202  * @hdd_ctx: the HDD context to operate against
203  * @chan_freq: Channel frequency option provided by userspace
204  * @out_adapter: out parameter for the newly created pre-cac adapter
205  *
206  * Sets the driver to the required hardware mode and start an adapter for
207  * pre CAC which will mimic an AP.
208  *
209  * Return: Zero on success, non-zero value on error
210  */
__wlan_hdd_request_pre_cac(struct hdd_context * hdd_ctx,uint32_t chan_freq,struct hdd_adapter ** out_adapter)211 static int __wlan_hdd_request_pre_cac(struct hdd_context *hdd_ctx,
212 				      uint32_t chan_freq,
213 				      struct hdd_adapter **out_adapter)
214 {
215 	uint8_t *mac_addr = NULL;
216 	uint32_t pre_cac_chan_freq = 0;
217 	int ret;
218 	struct hdd_adapter *ap_adapter, *pre_cac_adapter = NULL;
219 	struct hdd_ap_ctx *hdd_ap_ctx, *pre_cac_ap_ctx;
220 	QDF_STATUS status;
221 	struct wiphy *wiphy;
222 	struct net_device *dev;
223 	struct cfg80211_chan_def chandef;
224 	enum nl80211_channel_type channel_type;
225 	mac_handle_t mac_handle;
226 	enum phy_ch_width cac_ch_width;
227 	struct hdd_adapter_create_param params = {0};
228 	struct wlan_hdd_link_info *pre_cac_link_info, *link_info;
229 	bool is_rtnl_locked = false;
230 
231 	if (!policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc)) {
232 		hdd_debug("Pre CAC is not supported on non-dbs platforms");
233 		return -EINVAL;
234 	}
235 
236 	if (policy_mgr_get_connection_count(hdd_ctx->psoc) > 1) {
237 		hdd_err("pre cac not allowed in concurrency");
238 		return -EINVAL;
239 	}
240 
241 	ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
242 	if (!ap_adapter) {
243 		hdd_err("unable to get SAP adapter");
244 		return -EINVAL;
245 	}
246 
247 	link_info = ap_adapter->deflink;
248 	hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
249 
250 	if (qdf_atomic_read(&hdd_ap_ctx->ch_switch_in_progress)) {
251 		hdd_err("pre cac not allowed during CSA");
252 		return -EINVAL;
253 	}
254 
255 	mac_handle = hdd_ctx->mac_handle;
256 
257 	if (wlan_reg_is_dfs_for_freq(hdd_ctx->pdev,
258 				     hdd_ap_ctx->operating_chan_freq)) {
259 		hdd_err("SAP is already on DFS channel:%d",
260 			hdd_ap_ctx->operating_chan_freq);
261 		return -EINVAL;
262 	}
263 
264 	if (!WLAN_REG_IS_24GHZ_CH_FREQ(hdd_ap_ctx->operating_chan_freq)) {
265 		hdd_err("pre CAC allowed only when SAP is in 2.4GHz:%d",
266 			hdd_ap_ctx->operating_chan_freq);
267 		return -EINVAL;
268 	}
269 
270 	cac_ch_width = wlansap_get_max_bw_by_phymode(hdd_ap_ctx->sap_context);
271 	if (cac_ch_width > DEFAULT_PRE_CAC_BANDWIDTH)
272 		cac_ch_width = DEFAULT_PRE_CAC_BANDWIDTH;
273 	if (chan_freq) {
274 		qdf_mem_zero(&chandef, sizeof(struct cfg80211_chan_def));
275 		if (wlan_set_def_pre_cac_chan(hdd_ctx, chan_freq, &chandef,
276 					      &channel_type, &cac_ch_width)) {
277 			hdd_err("failed to set pre_cac channel %d", chan_freq);
278 			return -EINVAL;
279 		}
280 	}
281 	hdd_debug("channel: %d bw: %d", chan_freq, cac_ch_width);
282 
283 	ret = ucfg_pre_cac_validate_and_get_freq(hdd_ctx->pdev, chan_freq,
284 						 &pre_cac_chan_freq,
285 						 cac_ch_width);
286 	if (ret != 0) {
287 		hdd_err("can't validate pre-cac channel");
288 		goto release_intf_addr_and_return_failure;
289 	}
290 
291 	hdd_debug("starting pre cac SAP  adapter");
292 
293 	mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_SAP_MODE);
294 	if (!mac_addr) {
295 		hdd_err("can't add virtual intf: Not getting valid mac addr");
296 		return -EINVAL;
297 	}
298 
299 	/**
300 	 * Starting a SAP adapter:
301 	 * Instead of opening an adapter, we could just do a SME open
302 	 * session for AP type. But, start BSS would still need an
303 	 * adapter. So, this option is not taken.
304 	 *
305 	 * hdd open adapter is going to register this precac interface
306 	 * with user space. This interface though exposed to user space
307 	 * will be in DOWN state. Consideration was done to avoid this
308 	 * registration to the user space. But, as part of SAP
309 	 * operations multiple events are sent to user space. Some of
310 	 * these events received from unregistered interface was
311 	 * causing crashes. So, retaining the registration.
312 	 *
313 	 * So, this interface would remain registered and will remain
314 	 * in DOWN state for the CAC duration. We will add notes in the
315 	 * feature announcement to not use this temporary interface for
316 	 * any activity from user space.
317 	 */
318 
319 	params.is_add_virtual_iface = 1;
320 	params.is_pre_cac_adapter = 1;
321 	if (rtnl_trylock()) {
322 		pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE,
323 						   SAP_PRE_CAC_IFNAME,
324 						   mac_addr, NET_NAME_UNKNOWN,
325 						   true, &params);
326 		rtnl_unlock();
327 	}
328 
329 	if (!pre_cac_adapter) {
330 		hdd_err("error opening the pre cac adapter");
331 		goto release_intf_addr_and_return_failure;
332 	}
333 
334 	pre_cac_link_info = pre_cac_adapter->deflink;
335 	pre_cac_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pre_cac_link_info);
336 	sap_clear_global_dfs_param(mac_handle, pre_cac_ap_ctx->sap_context);
337 
338 	/*
339 	 * This interface is internally created by the driver. So, no interface
340 	 * up comes for this interface from user space and hence starting
341 	 * the adapter internally.
342 	 */
343 	if (hdd_start_adapter(pre_cac_adapter, false)) {
344 		hdd_err("error starting the pre cac adapter");
345 		goto close_pre_cac_adapter;
346 	}
347 
348 	hdd_debug("preparing for start ap/bss on the pre cac adapter");
349 
350 	wiphy = hdd_ctx->wiphy;
351 	dev = pre_cac_adapter->dev;
352 
353 	/* Since this is only a dummy interface lets us use the IEs from the
354 	 * other active SAP interface. In regular scenarios, these IEs would
355 	 * come from the user space entity
356 	 */
357 	pre_cac_ap_ctx->beacon = qdf_mem_malloc(sizeof(*hdd_ap_ctx->beacon));
358 	if (!pre_cac_ap_ctx->beacon)
359 		goto stop_close_pre_cac_adapter;
360 
361 	qdf_mem_copy(pre_cac_ap_ctx->beacon, hdd_ap_ctx->beacon,
362 		     sizeof(*pre_cac_ap_ctx->beacon));
363 	pre_cac_ap_ctx->sap_config.authType = hdd_ap_ctx->sap_config.authType;
364 	pre_cac_ap_ctx->sap_config.ch_width_orig =
365 					hdd_ap_ctx->sap_config.ch_width_orig;
366 
367 	/* The original premise is that on moving from 2.4GHz to 5GHz, the SAP
368 	 * will continue to operate on the same bandwidth as that of the 2.4GHz
369 	 * operations. Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
370 	 * Now some customer request to start AP on higher BW such as 80Mhz.
371 	 * Hence use max possible supported BW based on phymode configurated
372 	 * on SAP.
373 	 */
374 	cac_ch_width = wlansap_get_max_bw_by_phymode(hdd_ap_ctx->sap_context);
375 	if (cac_ch_width > DEFAULT_PRE_CAC_BANDWIDTH)
376 		cac_ch_width = DEFAULT_PRE_CAC_BANDWIDTH;
377 
378 	qdf_mem_zero(&chandef, sizeof(struct cfg80211_chan_def));
379 	if (wlan_set_def_pre_cac_chan(hdd_ctx, pre_cac_chan_freq, &chandef,
380 				      &channel_type, &cac_ch_width)) {
381 		hdd_err("error set pre_cac channel %d", pre_cac_chan_freq);
382 		goto close_pre_cac_adapter;
383 	}
384 	pre_cac_ap_ctx->sap_config.ch_width_orig =
385 					hdd_map_nl_chan_width(chandef.width);
386 
387 	hdd_debug("existing ap phymode:%d pre cac ch_width:%d freq:%d",
388 		  hdd_ap_ctx->sap_config.SapHw_mode,
389 		  cac_ch_width, pre_cac_chan_freq);
390 	/*
391 	 * Doing update after opening and starting pre-cac adapter will make
392 	 * sure that driver won't do hardware mode change if there are any
393 	 * initial hick-ups or issues in pre-cac adapter's configuration.
394 	 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
395 	 * connection update should result in DBS mode
396 	 */
397 	status = policy_mgr_update_and_wait_for_connection_update(
398 					    hdd_ctx->psoc,
399 					    link_info->vdev_id,
400 					    pre_cac_chan_freq,
401 					    POLICY_MGR_UPDATE_REASON_PRE_CAC);
402 	if (QDF_IS_STATUS_ERROR(status)) {
403 		hdd_err("error in moving to DBS mode");
404 		goto stop_close_pre_cac_adapter;
405 	}
406 
407 	ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
408 	if (ret != 0) {
409 		hdd_err("failed to set channel");
410 		goto stop_close_pre_cac_adapter;
411 	}
412 
413 	status = wlan_hdd_cfg80211_start_bss(pre_cac_link_info,
414 					     NULL, PRE_CAC_SSID,
415 					     qdf_str_len(PRE_CAC_SSID),
416 					     NL80211_HIDDEN_SSID_NOT_IN_USE,
417 					     false);
418 	if (QDF_IS_STATUS_ERROR(status)) {
419 		hdd_err("start bss failed");
420 		goto stop_close_pre_cac_adapter;
421 	}
422 
423 	/*
424 	 * The pre cac status is set here. But, it would not be reset explicitly
425 	 * anywhere, since after the pre cac success/failure, the pre cac
426 	 * adapter itself would be removed.
427 	 */
428 	ret = ucfg_pre_cac_set_status(pre_cac_link_info->vdev, true);
429 	if (ret != 0) {
430 		hdd_err("failed to set pre cac status");
431 		goto stop_close_pre_cac_adapter;
432 	}
433 
434 	ucfg_pre_cac_set_freq_before_pre_cac(link_info->vdev,
435 					     hdd_ap_ctx->operating_chan_freq);
436 	ucfg_pre_cac_set_freq(link_info->vdev, pre_cac_chan_freq);
437 	ucfg_pre_cac_adapter_set(pre_cac_link_info->vdev, true);
438 	*out_adapter = pre_cac_adapter;
439 
440 	return 0;
441 
442 stop_close_pre_cac_adapter:
443 	pre_cac_adapter->is_virtual_iface = true;
444 	hdd_stop_adapter(hdd_ctx, pre_cac_adapter);
445 	qdf_mem_free(pre_cac_ap_ctx->beacon);
446 	pre_cac_ap_ctx->beacon = NULL;
447 close_pre_cac_adapter:
448 	if (rtnl_trylock())
449 		is_rtnl_locked = true;
450 
451 	hdd_close_adapter(hdd_ctx, pre_cac_adapter, true);
452 
453 	if (is_rtnl_locked)
454 		rtnl_unlock();
455 release_intf_addr_and_return_failure:
456 	/*
457 	 * Release the interface address as the adapter
458 	 * failed to start, if you don't release then next
459 	 * adapter which is trying to come wouldn't get valid
460 	 * mac address. Remember we have limited pool of mac addresses
461 	 */
462 	if (mac_addr)
463 		wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
464 	return -EINVAL;
465 }
466 
467 static int
wlan_hdd_start_pre_cac_trans(struct hdd_context * hdd_ctx,struct osif_vdev_sync ** out_vdev_sync,bool * is_vdev_sync_created)468 wlan_hdd_start_pre_cac_trans(struct hdd_context *hdd_ctx,
469 			     struct osif_vdev_sync **out_vdev_sync,
470 			     bool *is_vdev_sync_created)
471 {
472 	struct hdd_adapter *adapter, *next_adapter = NULL;
473 	wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_START_PRE_CAC_TRANS;
474 	int errno;
475 
476 	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
477 					   dbgid) {
478 		if (!qdf_str_cmp(adapter->dev->name, SAP_PRE_CAC_IFNAME)) {
479 			errno = osif_vdev_sync_trans_start(adapter->dev,
480 							   out_vdev_sync);
481 
482 			hdd_adapter_dev_put_debug(adapter, dbgid);
483 			if (next_adapter)
484 				hdd_adapter_dev_put_debug(next_adapter,
485 							  dbgid);
486 			return errno;
487 		}
488 		hdd_adapter_dev_put_debug(adapter, dbgid);
489 	}
490 
491 	errno = osif_vdev_sync_create_and_trans(hdd_ctx->parent_dev,
492 						out_vdev_sync);
493 	if (errno)
494 		return errno;
495 
496 	*is_vdev_sync_created = true;
497 	return 0;
498 }
499 
wlan_hdd_request_pre_cac(struct hdd_context * hdd_ctx,uint32_t chan_freq)500 int wlan_hdd_request_pre_cac(struct hdd_context *hdd_ctx, uint32_t chan_freq)
501 {
502 	struct hdd_adapter *adapter;
503 	struct osif_vdev_sync *vdev_sync;
504 	int errno;
505 	bool is_vdev_sync_created = false;
506 
507 	errno = wlan_hdd_start_pre_cac_trans(hdd_ctx, &vdev_sync,
508 					     &is_vdev_sync_created);
509 	if (errno)
510 		return errno;
511 
512 	errno = __wlan_hdd_request_pre_cac(hdd_ctx, chan_freq, &adapter);
513 	if (errno)
514 		goto destroy_sync;
515 
516 	if (is_vdev_sync_created)
517 		osif_vdev_sync_register(adapter->dev, vdev_sync);
518 	osif_vdev_sync_trans_stop(vdev_sync);
519 
520 	return 0;
521 
522 destroy_sync:
523 	osif_vdev_sync_trans_stop(vdev_sync);
524 	if (is_vdev_sync_created)
525 		osif_vdev_sync_destroy(vdev_sync);
526 
527 	return errno;
528 }
529 
530 static void
wlan_hdd_pre_cac_conditional_freq_switch_ind(struct wlan_objmgr_vdev * vdev,bool completed)531 wlan_hdd_pre_cac_conditional_freq_switch_ind(struct wlan_objmgr_vdev *vdev,
532 					     bool completed)
533 {
534 	struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
535 	uint8_t vdev_id = vdev->vdev_objmgr.vdev_id;
536 	struct hdd_adapter *adapter;
537 	struct wlan_hdd_link_info *link_info;
538 	struct hdd_ap_ctx *ap_ctx;
539 
540 	link_info = wlan_hdd_get_link_info_from_vdev(psoc, vdev_id);
541 	if (!link_info) {
542 		hdd_err("Invalid vdev");
543 		return;
544 	}
545 
546 	adapter = link_info->adapter;
547 	if (completed) {
548 		ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
549 		ap_ctx->dfs_cac_block_tx = false;
550 		ucfg_ipa_set_dfs_cac_tx(adapter->hdd_ctx->pdev,
551 					ap_ctx->dfs_cac_block_tx);
552 		ucfg_dp_set_dfs_cac_tx(vdev, ap_ctx->dfs_cac_block_tx);
553 		adapter->hdd_ctx->dev_dfs_cac_status = DFS_CAC_ALREADY_DONE;
554 	} else {
555 		adapter->hdd_ctx->dev_dfs_cac_status = DFS_CAC_NEVER_DONE;
556 		hdd_son_deliver_cac_status_event(adapter,
557 						 ucfg_pre_cac_get_freq(vdev),
558 						 true);
559 	}
560 }
561 
562 static void
wlan_hdd_pre_cac_complete(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,QDF_STATUS status)563 wlan_hdd_pre_cac_complete(struct wlan_objmgr_psoc *psoc,
564 			  uint8_t vdev_id,
565 			  QDF_STATUS status)
566 {
567 	struct wlan_hdd_link_info *link_info;
568 
569 	link_info = wlan_hdd_get_link_info_from_vdev(psoc, vdev_id);
570 	if (!link_info) {
571 		hdd_err("Invalid vdev %d", vdev_id);
572 		return;
573 	}
574 
575 	if (QDF_IS_STATUS_SUCCESS(status))
576 		wlan_hdd_pre_cac_success(link_info->adapter);
577 	else
578 		wlan_hdd_pre_cac_failure(link_info->adapter);
579 }
580 
581 struct osif_pre_cac_legacy_ops pre_cac_legacy_ops = {
582 	.conditional_csa_ind_legacy_cb =
583 		wlan_hdd_pre_cac_conditional_freq_switch_ind,
584 	.pre_cac_complete_legacy_cb = wlan_hdd_pre_cac_complete,
585 };
586 
hdd_pre_cac_register_cb(void)587 QDF_STATUS hdd_pre_cac_register_cb(void)
588 {
589 	osif_pre_cac_set_legacy_cb(&pre_cac_legacy_ops);
590 
591 	return osif_pre_cac_register_cb();
592 }
593 
hdd_pre_cac_unregister_cb(void)594 void hdd_pre_cac_unregister_cb(void)
595 {
596 	osif_pre_cac_reset_legacy_cb();
597 }
598