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, ¶ms);
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