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