diff --git a/umac/dfs/core/src/dfs.h b/umac/dfs/core/src/dfs.h index 32ff9af8c90d..2438d404dcf1 100644 --- a/umac/dfs/core/src/dfs.h +++ b/umac/dfs/core/src/dfs.h @@ -1059,6 +1059,11 @@ struct wlan_dfs { TAILQ_HEAD(, dfs_precac_entry) dfs_precac_done_list; TAILQ_HEAD(, dfs_precac_entry) dfs_precac_nol_list; +#ifdef QCA_SUPPORT_ETSI_PRECAC_DFS + TAILQ_HEAD(, dfs_etsi_precac_entry) dfs_etsiprecac_required_list; + TAILQ_HEAD(, dfs_etsi_precac_entry) dfs_etsiprecac_done_list; +#endif + struct dfs_channel *dfs_curchan; struct wlan_objmgr_pdev *dfs_pdev_obj; bool dfs_is_offload_enabled; diff --git a/umac/dfs/core/src/dfs_etsi_precac.h b/umac/dfs/core/src/dfs_etsi_precac.h new file mode 100644 index 000000000000..1a297d06a962 --- /dev/null +++ b/umac/dfs/core/src/dfs_etsi_precac.h @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * DOC: This file has ETSI Pre-CAC DFS APIs. + */ + +#ifndef _DFS_ETSI_PRECAC_H_ +#define _DFS_ETSI_PRECAC_H_ + +#include "dfs.h" + +#define VHT160_IEEE_FREQ_DIFF 16 + +/** + * struct dfs_etsi_precac_entry - PreCAC entry for ETSI domain + * @pe_list: ETSI PreCAC entry. + * @freq: primary freq. + * @etsi_caclst_ticks start tick, OS speicfic. + * @dfs: Pointer to wlan_dfs structure. + */ +struct dfs_etsi_precac_entry { + TAILQ_ENTRY(dfs_etsi_precac_entry) pe_list; + uint16_t freq; + unsigned long etsi_caclst_ticks; + struct wlan_dfs *dfs; +}; + +/** + * dfs_print_etsi_precaclists() - Print etsi precac list. + * @dfs: Pointer to wlan_dfs structure. + */ +#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) +void dfs_print_etsi_precaclists(struct wlan_dfs *dfs); +#else +static inline void dfs_print_etsi_precaclists(struct wlan_dfs *dfs) +{ +} +#endif + +/** + * dfs_reset_etsi_precac_lists() - Resets the ETSI precac lists. + * @dfs: Pointer to wlan_dfs structure. + */ +#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) +void dfs_reset_etsi_precac_lists(struct wlan_dfs *dfs); +#else +static inline void dfs_reset_etsi_precac_lists(struct wlan_dfs *dfs) +{ +} +#endif + +/** + * dfs_reset_etsiprecaclists()- Clears and initializes etsi_precac_required_list + * etsi_precac_done_list. + * + * @dfs: Pointer to wlan_dfs structure. + */ +#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) +void dfs_reset_etsiprecaclists(struct wlan_dfs *dfs); +#else +static inline void dfs_reset_etsiprecaclists(struct wlan_dfs *dfs) +{ +} +#endif + +/** + * dfs_deinit_etsi_precac_list() - Clears the etsi precac list. + * @dfs: Pointer to wlan_dfs dtructure. + */ +#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) +void dfs_deinit_etsi_precac_list(struct wlan_dfs *dfs); +#else +static inline void dfs_deinit_etsi_precac_list(struct wlan_dfs *dfs) +{ +} +#endif + +/** + * dfs_etsi_precac_attach() - Initialize ETSI precac variables. + * @dfs: Pointer to DFS structure. + */ +#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) +void dfs_etsi_precac_attach(struct wlan_dfs *dfs); +#else +static inline void dfs_etsi_precac_attach(struct wlan_dfs *dfs) +{ +} +#endif + +/** + * dfs_etsi_precac_detach() - Free etsi_precac memory. + * @dfs: Pointer to wlan_dfs dtructure. + */ +#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) +void dfs_etsi_precac_detach(struct wlan_dfs *dfs); +#else +static inline void dfs_etsi_precac_detach(struct wlan_dfs *dfs) +{ +} +#endif + +/** + * dfs_init_etsiprecac_list() - Init ETSI precac list. + * @dfs: Pointer to wlan_dfs dtructure. + */ +#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) +void dfs_init_etsi_precac_list(struct wlan_dfs *dfs); +#else +static inline void dfs_init_etsi_precac_list(struct wlan_dfs *dfs) +{ +} +#endif + +/** + * dfs_is_subchan_in_etsi_precac_done_list() - Is HT20 sub channel + * in etsi precac done list. + * @dfs: Pointer to wlan_dfs structure. + * @channel: HT20 sub channel + * + * Return: If subchannel present in precac done list return 1. + * Otherwise return 0 + */ +#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) +int dfs_is_subchan_in_etsi_precac_done_list(struct wlan_dfs *dfs, + uint8_t channel); +#else +static inline int dfs_is_subchan_in_etsi_precac_done_list(struct wlan_dfs *dfs) +{ + return 0; +} +#endif +/** + * dfs_is_etsi_precac_done() - Is precac done. + * @dfs: Pointer to wlan_dfs structure. + * + * Return: If precac already done in channel, return 1. Otherwise return 0. + */ +#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) +bool dfs_is_etsi_precac_done(struct wlan_dfs *dfs); +#else +static inline bool dfs_is_etsi_precac_done(struct wlan_dfs *dfs) +{ + return false; +} +#endif + +/** + * dfs_mark_etsi_precac_dfs() - Mark the precac channel as radar for ETSI. + * @dfs: Pointer to wlan_dfs structure. + * @channels: List of HT20 primary channels + * @num_channels: Number of HT20 primary channels + */ +#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) +void dfs_mark_etsi_precac_dfs(struct wlan_dfs *dfs, + uint8_t *channels, uint8_t num_channels); +#else +static inline void dfs_mark_etsi_precac_dfs(struct wlan_dfs *dfs, + uint8_t *channels, + uint8_t num_channels) +{ +} +#endif + +/** + * dfs_add_chan_to_etsi_done_list() - Add subchannel to ETSI CAC done list, + * if present in ETSI CAC required list + * @dfs: Pointer to wlan_dfs structure. + * @channel: HT20 primary channel + * + * Return: If channel added to ETSI CAC done list, return 1. Otherwise return 0. + */ +#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) +int dfs_add_chan_to_etsi_done_list(struct wlan_dfs *dfs, uint8_t channel); +#else +static inline int dfs_add_chan_to_etsi_done_list(struct wlan_dfs *dfs, + uint8_t channel) +{ + return 0; +} +#endif + +/** + * dfs_add_to_etsi_precac_done_list() - Add channel to ETSI CAC done list + * @curchan: Pointer to dfs_channel structure. + * + */ +#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) +void dfs_add_to_etsi_precac_done_list(struct wlan_dfs *dfs); +#else +static inline void dfs_add_to_etsi_precac_done_list(struct wlan_dfs *dfs) +{ +} +#endif + +/** + * dfs_get_bonding_channels_without_seg_info() - Get bonding channels in curchan + * @curchan: Pointer to dfs_channel structure. + * @channels: channel array holding list of bonded channels. + * + * Return: number of sub channels in the current channel. + */ +#ifdef QCA_SUPPORT_ETSI_PRECAC_DFS +uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *curchan, + uint8_t *channels); +#else +static inline uint8_t +dfs_get_bonding_channels_without_seg_info(struct dfs_channel *curchan, + uint8_t *channels) +{ + return 0; +} +#endif + +#endif /* _DFS_ETSI_PRECAC_H_ */ diff --git a/umac/dfs/core/src/misc/dfs.c b/umac/dfs/core/src/misc/dfs.c index 4ffe07ba20f8..b47a4f01e8a0 100644 --- a/umac/dfs/core/src/misc/dfs.c +++ b/umac/dfs/core/src/misc/dfs.c @@ -30,6 +30,7 @@ #include "../dfs_filter_init.h" #include "../dfs_full_offload.h" #include "wlan_dfs_utils_api.h" +#include "../dfs_etsi_precac.h" /** * dfs_testtimer_task() - Sends CSA in the current channel. @@ -117,6 +118,7 @@ int dfs_attach(struct wlan_dfs *dfs) } dfs_cac_attach(dfs); dfs_zero_cac_attach(dfs); + dfs_etsi_precac_attach(dfs); dfs_nol_attach(dfs); /* @@ -153,6 +155,7 @@ void dfs_detach(struct wlan_dfs *dfs) { if (!dfs->dfs_is_offload_enabled) dfs_main_detach(dfs); + dfs_etsi_precac_detach(dfs); dfs_zero_cac_detach(dfs); dfs_nol_detach(dfs); } @@ -472,9 +475,11 @@ int dfs_control(struct wlan_dfs *dfs, break; case DFS_SHOW_PRECAC_LISTS: dfs_print_precaclists(dfs); + dfs_print_etsi_precaclists(dfs); break; case DFS_RESET_PRECAC_LISTS: dfs_reset_precac_lists(dfs); + dfs_reset_etsi_precac_lists(dfs); break; case DFS_SECOND_SEGMENT_BANGRADAR: if (dfs->dfs_is_offload_enabled) { diff --git a/umac/dfs/core/src/misc/dfs_cac.c b/umac/dfs/core/src/misc/dfs_cac.c index ca1fcfbc018c..8f5d91e45a36 100644 --- a/umac/dfs/core/src/misc/dfs_cac.c +++ b/umac/dfs/core/src/misc/dfs_cac.c @@ -30,6 +30,7 @@ #include "../dfs_channel.h" #include "../dfs_zero_cac.h" +#include "../dfs_etsi_precac.h" #include "wlan_dfs_utils_api.h" #include "wlan_dfs_mlme_api.h" #include "../dfs_internal.h" @@ -106,6 +107,11 @@ static os_timer_func(dfs_cac_timeout) dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "cac expired, chan %d curr time %d", dfs->dfs_curchan->dfs_ch_freq, (qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000)); + + /* Once CAC is done, add channel to ETSI precacdone list*/ + if (utils_get_dfsdomain(dfs->dfs_pdev_obj) == DFS_ETSI_DOMAIN) + dfs_add_to_etsi_precac_done_list(dfs); + /* * When radar is detected during a CAC we are woken up prematurely to * switch to a new channel. Check the channel to decide how to act. diff --git a/umac/dfs/core/src/misc/dfs_etsi_precac.c b/umac/dfs/core/src/misc/dfs_etsi_precac.c new file mode 100644 index 000000000000..3f4fbcc8734c --- /dev/null +++ b/umac/dfs/core/src/misc/dfs_etsi_precac.c @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * DOC: This file has ETSI CAC DFS functions. + * Summary: In ETSI domain, after CAC, channel is added to ETSI CAC cleared + * list, so that next time it can skip CAC if channel already present in this + * list. If radar found, remove channel from this list indicating to redo + * CAC,when channel is selected in future. + */ + +#include "../dfs_etsi_precac.h" +#include "wlan_dfs_lmac_api.h" +#include "wlan_dfs_mlme_api.h" +#include "wlan_dfs_utils_api.h" +#include "../dfs_internal.h" +#include "../dfs_process_radar_found_ind.h" + +#define ETSI_CAC_TIME_OUT_MS 86400000 +int dfs_is_subchan_in_etsi_precac_done_list(struct wlan_dfs *dfs, + uint8_t channel) +{ + struct dfs_etsi_precac_entry *precac_entry = NULL; + struct dfs_etsi_precac_entry *tmp_precac_entry = NULL; + uint8_t found = 0; + uint32_t diff_ms; + + if (utils_is_dfs_ch(dfs->dfs_pdev_obj, channel)) { + /*For each channel in the list here do the below operation*/ + PRECAC_LIST_LOCK(dfs); + if (TAILQ_EMPTY(&dfs->dfs_etsiprecac_done_list)) { + PRECAC_LIST_UNLOCK(dfs); + return 0; + } + + TAILQ_FOREACH_SAFE(precac_entry, &dfs->dfs_etsiprecac_done_list, + pe_list, tmp_precac_entry) { + diff_ms = qdf_system_ticks_to_msecs(qdf_system_ticks() - + precac_entry->etsi_caclst_ticks); + if (channel == precac_entry->freq && + diff_ms < ETSI_CAC_TIME_OUT_MS) { + found = 1; + break; + } + } + PRECAC_LIST_UNLOCK(dfs); + if (found) + return 1; + } else { + return 1; + } + + return 0; +} + +bool dfs_is_etsi_precac_done(struct wlan_dfs *dfs) +{ + bool ret_val = 1; + uint8_t channels[NUM_CHANNELS_160MHZ]; + uint8_t nchannels = 0; + int i; + + nchannels = dfs_get_bonding_channels_without_seg_info(dfs->dfs_curchan, + channels); + + for (i = 0; i < nchannels; i++) { + if (dfs_is_subchan_in_etsi_precac_done_list(dfs, channels[i])) { + continue; + } else { + ret_val = 0; + break; + } + } + + dfs_debug(dfs, WLAN_DEBUG_DFS, "ret_val = %d", ret_val); + + return ret_val; +} + +void dfs_mark_etsi_precac_dfs(struct wlan_dfs *dfs, uint8_t *channels, + uint8_t num_channels) +{ + struct dfs_etsi_precac_entry *precac_entry = NULL; + struct dfs_etsi_precac_entry *tmp_precac_entry = NULL; + int i = 0; + + if (num_channels > NUM_CHANNELS_160MHZ) { + dfs_err(dfs, WLAN_DEBUG_DFS, + "Invalid num channels: %d", num_channels); + return; + } + + PRECAC_LIST_LOCK(dfs); + for (i = 0; i < num_channels; i++) { + TAILQ_FOREACH_SAFE(precac_entry, &dfs->dfs_etsiprecac_done_list, + pe_list, tmp_precac_entry) { + if (channels[i] != precac_entry->freq) + continue; + + TAILQ_REMOVE(&dfs->dfs_etsiprecac_done_list, + precac_entry, pe_list); + TAILQ_INSERT_TAIL(&dfs->dfs_etsiprecac_required_list, + precac_entry, pe_list); + } + } + PRECAC_LIST_UNLOCK(dfs); +} + +void dfs_init_etsi_precac_list(struct wlan_dfs *dfs) +{ + u_int i; + uint8_t found; + struct dfs_etsi_precac_entry *tmp_precac_entry; + int nchans = 0; + + /* + * We need to prepare list of unique VHT20 center frequencies. + * But at the beginning we do not know how many unique frequencies + * are present. Therefore, we calculate the MAX size and allocate + * a temporary list/array. However we fill the temporary array with + * unique frequencies and copy the unique list of frequencies to + * the final list with exact size. + */ + TAILQ_INIT(&dfs->dfs_etsiprecac_done_list); + TAILQ_INIT(&dfs->dfs_etsiprecac_required_list); + + dfs_mlme_get_dfs_ch_nchans(dfs->dfs_pdev_obj, &nchans); + + PRECAC_LIST_LOCK(dfs); + /* Fill the precac-required-list with unique elements */ + for (i = 0; i < nchans; i++) { + struct dfs_channel *ichan = NULL, lc; + + ichan = &lc; + dfs_mlme_get_dfs_ch_channels(dfs->dfs_pdev_obj, + &ichan->dfs_ch_freq, + &ichan->dfs_ch_flags, + &ichan->dfs_ch_flagext, + &ichan->dfs_ch_ieee, + &ichan->dfs_ch_vhtop_ch_freq_seg1, + &ichan->dfs_ch_vhtop_ch_freq_seg2, + i); + + if (!WLAN_IS_CHAN_DFS(ichan)) + continue; + + found = 0; + TAILQ_FOREACH(tmp_precac_entry, + &dfs->dfs_etsiprecac_required_list, + pe_list) { + if (tmp_precac_entry->freq == + ichan->dfs_ch_vhtop_ch_freq_seg1) { + found = 1; + break; + } + } + if (!found) { + struct dfs_etsi_precac_entry *etsi_precac_entry; + + etsi_precac_entry = qdf_mem_malloc( + sizeof(*etsi_precac_entry)); + if (!etsi_precac_entry) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, + "etsi precac entry alloc fail"); + continue; + } + etsi_precac_entry->freq = + ichan->dfs_ch_vhtop_ch_freq_seg1; + etsi_precac_entry->dfs = dfs; + TAILQ_INSERT_TAIL(&dfs->dfs_etsiprecac_required_list, + etsi_precac_entry, pe_list); + } + } + PRECAC_LIST_UNLOCK(dfs); + + dfs_debug(dfs, WLAN_DEBUG_DFS, + "Print the list of VHT20 frequencies from linked list"); + TAILQ_FOREACH(tmp_precac_entry, + &dfs->dfs_etsiprecac_required_list, + pe_list) + dfs_info(dfs, WLAN_DEBUG_DFS, "freq=%u", + tmp_precac_entry->freq); +} + +void dfs_deinit_etsi_precac_list(struct wlan_dfs *dfs) +{ + struct dfs_etsi_precac_entry *tmp_precac_entry, *precac_entry; + + dfs_debug(dfs, WLAN_DEBUG_DFS, + "Free list of HT20/VHT20 freq from etsiprecac_required list"); + PRECAC_LIST_LOCK(dfs); + + if (!TAILQ_EMPTY(&dfs->dfs_etsiprecac_required_list)) + TAILQ_FOREACH_SAFE(precac_entry, + &dfs->dfs_etsiprecac_required_list, + pe_list, + tmp_precac_entry) { + TAILQ_REMOVE(&dfs->dfs_etsiprecac_required_list, + precac_entry, pe_list); + qdf_mem_free(precac_entry); + } + + dfs_debug(dfs, WLAN_DEBUG_DFS, + "Free list of HT20/VHT20 freq from etsipcac_done list"); + + if (!TAILQ_EMPTY(&dfs->dfs_etsiprecac_done_list)) + TAILQ_FOREACH_SAFE(precac_entry, + &dfs->dfs_etsiprecac_done_list, + pe_list, + tmp_precac_entry) { + TAILQ_REMOVE(&dfs->dfs_etsiprecac_done_list, + precac_entry, pe_list); + qdf_mem_free(precac_entry); + } + + PRECAC_LIST_UNLOCK(dfs); +} + +void dfs_etsi_precac_attach(struct wlan_dfs *dfs) +{ +} + +void dfs_etsi_precac_detach(struct wlan_dfs *dfs) +{ + dfs_deinit_etsi_precac_list(dfs); +} + +void dfs_print_etsi_precaclists(struct wlan_dfs *dfs) +{ + struct dfs_etsi_precac_entry *tmp_precac_entry; + + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + PRECAC_LIST_LOCK(dfs); + /* Print the ETSI Pre-CAC required List */ + dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, + "Pre-cac-required list of VHT20 frequencies"); + TAILQ_FOREACH(tmp_precac_entry, + &dfs->dfs_etsiprecac_required_list, + pe_list) { + dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, + "freq=%u ", + tmp_precac_entry->freq); + } + + /* Print the ETSI Pre-CAC done List */ + dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, + "Pre-cac-done list of VHT20 frequencies"); + TAILQ_FOREACH(tmp_precac_entry, + &dfs->dfs_etsiprecac_done_list, + pe_list) { + unsigned long time_added = + qdf_system_ticks_to_msecs( + tmp_precac_entry->etsi_caclst_ticks); + + dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, + "freq=%u added at (msec): %lu", + tmp_precac_entry->freq, + time_added); + } + PRECAC_LIST_UNLOCK(dfs); +} + +void dfs_reset_etsiprecaclists(struct wlan_dfs *dfs) +{ + dfs_debug(dfs, WLAN_DEBUG_DFS, + "Reset precaclist of VHT80 frequencies"); + dfs_deinit_etsi_precac_list(dfs); + dfs_init_etsi_precac_list(dfs); +} + +void dfs_reset_etsi_precac_lists(struct wlan_dfs *dfs) +{ + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + dfs_reset_etsiprecaclists(dfs); +} + +int dfs_add_chan_to_etsi_done_list(struct wlan_dfs *dfs, uint8_t channel) +{ + struct dfs_etsi_precac_entry *precac_entry, *tmp_precac_entry; + + PRECAC_LIST_LOCK(dfs); + TAILQ_FOREACH_SAFE(precac_entry, + &dfs->dfs_etsiprecac_required_list, + pe_list, tmp_precac_entry) { + if (channel == precac_entry->freq) { + TAILQ_REMOVE(&dfs->dfs_etsiprecac_required_list, + precac_entry, pe_list); + TAILQ_INSERT_TAIL(&dfs->dfs_etsiprecac_done_list, + precac_entry, + pe_list); + precac_entry->etsi_caclst_ticks = qdf_system_ticks(); + PRECAC_LIST_UNLOCK(dfs); + return 1; + } + } + PRECAC_LIST_UNLOCK(dfs); + + return 0; +} + +void dfs_add_to_etsi_precac_done_list(struct wlan_dfs *dfs) +{ + uint8_t channels[NUM_CHANNELS_160MHZ]; + uint8_t nchannels = 0; + int i = 0; + + nchannels = dfs_get_bonding_channels_without_seg_info(dfs->dfs_curchan, + channels); + for (i = 0; i < nchannels; i++) { + if (!utils_is_dfs_ch(dfs->dfs_pdev_obj, channels[i])) + continue; + + if (TAILQ_EMPTY(&dfs->dfs_etsiprecac_required_list)) + break; + + dfs_add_chan_to_etsi_done_list(dfs, channels[i]); + } +} + +uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *curchan, + uint8_t *channels) +{ + uint8_t center_chan; + uint8_t nchannels = 0; + + center_chan = curchan->dfs_ch_vhtop_ch_freq_seg1; + + if (WLAN_IS_CHAN_MODE_20(curchan)) { + nchannels = 1; + channels[0] = center_chan; + } else if (WLAN_IS_CHAN_MODE_40(curchan)) { + nchannels = 2; + channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; + } else if (WLAN_IS_CHAN_MODE_80(curchan)) { + nchannels = 4; + channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; + channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; + } else if (WLAN_IS_CHAN_MODE_80_80(curchan)) { + nchannels = 8; + channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; + channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; + center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2; + channels[4] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; + channels[5] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[6] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[7] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; + } else if (WLAN_IS_CHAN_MODE_160(curchan)) { + nchannels = 8; + center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2; + channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET; + channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET; + channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; + channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; + channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET; + channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET; + } + + return nchannels; +} diff --git a/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c b/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c index 8819305e95fd..1fdc87fbac65 100644 --- a/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c +++ b/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c @@ -23,11 +23,12 @@ #include "../dfs.h" #include "../dfs_zero_cac.h" +#include "../dfs_etsi_precac.h" #include "../dfs_process_radar_found_ind.h" #include #include #include "wlan_dfs_mlme_api.h" - +#include "../dfs_internal.h" /** * TODO: The code is not according to the following description needs * modification and correction. Code always adds left and right channels to @@ -157,7 +158,8 @@ static QDF_STATUS dfs_radar_add_channel_list_to_nol(struct wlan_dfs *dfs, (uint16_t)utils_dfs_chan_to_freq(channels[i]), dfs->wlan_dfs_nol_timeout); nollist[num_ch++] = last_chan; - dfs_info(dfs, WLAN_DEBUG_DFS, "ch=%d Added to NOL", last_chan); + dfs_info(dfs, WLAN_DEBUG_DFS_NOL, "ch=%d Added to NOL", + last_chan); } if (!num_ch) { @@ -358,14 +360,6 @@ static uint8_t dfs_find_radar_affected_subchans(struct wlan_dfs *dfs, return i; } -/** - * dfs_get_bonding_channels() - Get bonding channels. - * @curchan: Pointer to dfs_channels to know width and primary channel. - * @segment_id: Segment id, useful for 80+80/160 MHz operating band. - * @channels: Pointer to save radar affected channels. - * - * Return: Number of channels. - */ uint8_t dfs_get_bonding_channels(struct dfs_channel *curchan, uint32_t segment_id, uint8_t *channels) @@ -520,6 +514,14 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, if (dfs->dfs_precac_enable) dfs_mark_precac_dfs(dfs, dfs->is_radar_found_on_secondary_seg); + if (utils_get_dfsdomain(dfs->dfs_pdev_obj) == DFS_ETSI_DOMAIN) { + /* Remove chan from ETSI Pre-CAC Cleared List*/ + dfs_info(dfs, WLAN_DEBUG_DFS_NOL, + "%s : %d remove channel from ETSI PreCAC List\n", + __func__, __LINE__); + dfs_mark_etsi_precac_dfs(dfs, channels, num_channels); + } + if (!dfs->dfs_is_offload_enabled && dfs->is_radar_found_on_secondary_seg) { dfs_second_segment_radar_disable(dfs); diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h index 36523f96d573..9acb0145d665 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h @@ -107,6 +107,26 @@ QDF_STATUS utils_dfs_reset(struct wlan_objmgr_pdev *pdev); */ QDF_STATUS utils_dfs_reset_precaclists(struct wlan_objmgr_pdev *pdev); +/** + * utils_dfs_reset_etsi_precaclists() - Clears and initializes etsi + * precac_required_list, + * etsi precac_done_list and + * etsi precac_nol_list. + * @pdev: Pointer to DFS pdev object. + * + * Wrapper function for dfs_reset_etsiprecaclists(). This function called from + * outside of DFS component. + */ +#ifdef QCA_SUPPORT_ETSI_PRECAC_DFS +QDF_STATUS utils_dfs_reset_etsi_precaclists(struct wlan_objmgr_pdev *pdev); +#else +static inline QDF_STATUS utils_dfs_reset_etsi_precaclists( + struct wlan_objmgr_pdev *pdev) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /** * utils_dfs_cancel_precac_timer() - Cancel the precac timer. * @pdev: Pointer to DFS pdev object. @@ -126,6 +146,25 @@ QDF_STATUS utils_dfs_cancel_precac_timer(struct wlan_objmgr_pdev *pdev); QDF_STATUS utils_dfs_is_precac_done(struct wlan_objmgr_pdev *pdev, bool *is_precac_done); +/** + * utils_dfs_is_esti_precac_done() - Is ETSI precac done. + * @pdev: Pointer to DFS pdev object. + * + * wrapper function for dfs_is_etsi_precac_done(). This + * function called from outside of dfs component. + */ +#ifdef QCA_SUPPORT_ETSI_PRECAC_DFS +QDF_STATUS utils_dfs_is_etsi_precac_done(struct wlan_objmgr_pdev *pdev, + bool *is_etsi_precac_done); +#else +static inline QDF_STATUS utils_dfs_is_etsi_precac_done( + struct wlan_objmgr_pdev *pdev, + bool *is_etsi_precac_done) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /** * utils_dfs_cancel_cac_timer() - Cancels the CAC timer. * @pdev: Pointer to DFS pdev object. diff --git a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c index e9f4e3a7847b..62de86f4bb25 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c @@ -24,6 +24,7 @@ #include "wlan_dfs_utils_api.h" #include "../../core/src/dfs.h" #include "../../core/src/dfs_zero_cac.h" +#include "../../core/src/dfs_etsi_precac.h" #include #include "../../core/src/dfs_random_chan_sel.h" #ifdef QCA_DFS_USE_POLICY_MANAGER @@ -50,6 +51,7 @@ QDF_STATUS utils_dfs_reset(struct wlan_objmgr_pdev *pdev) dfs_reset(dfs); dfs_nol_update(dfs); dfs_reset_precaclists(dfs); + dfs_reset_etsiprecaclists(dfs); return QDF_STATUS_SUCCESS; } @@ -84,6 +86,23 @@ QDF_STATUS utils_dfs_reset_precaclists(struct wlan_objmgr_pdev *pdev) } qdf_export_symbol(utils_dfs_reset_precaclists); +#ifdef QCA_SUPPORT_ETSI_PRECAC_DFS +QDF_STATUS utils_dfs_reset_etsi_precaclists(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_dfs *dfs; + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) + return QDF_STATUS_E_FAILURE; + + dfs_reset_etsiprecaclists(dfs); + + return QDF_STATUS_SUCCESS; +} + +qdf_export_symbol(utils_dfs_reset_etsi_precaclists); +#endif + QDF_STATUS utils_dfs_cancel_precac_timer(struct wlan_objmgr_pdev *pdev) { struct wlan_dfs *dfs; @@ -113,6 +132,24 @@ QDF_STATUS utils_dfs_is_precac_done(struct wlan_objmgr_pdev *pdev, } qdf_export_symbol(utils_dfs_is_precac_done); +#ifdef QCA_SUPPORT_ETSI_PRECAC_DFS +QDF_STATUS utils_dfs_is_etsi_precac_done(struct wlan_objmgr_pdev *pdev, + bool *is_etsi_precac_done) +{ + struct wlan_dfs *dfs; + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) + return QDF_STATUS_E_FAILURE; + + *is_etsi_precac_done = dfs_is_etsi_precac_done(dfs); + + return QDF_STATUS_SUCCESS; +} + +qdf_export_symbol(utils_dfs_is_etsi_precac_done); +#endif + QDF_STATUS utils_dfs_cancel_cac_timer(struct wlan_objmgr_pdev *pdev) { struct wlan_dfs *dfs;