diff --git a/umac/dfs/core/src/dfs.h b/umac/dfs/core/src/dfs.h index 42eeac994d89..135198e9f5f2 100644 --- a/umac/dfs/core/src/dfs.h +++ b/umac/dfs/core/src/dfs.h @@ -898,6 +898,9 @@ struct dfs_event_log { * @dfs_precac_primary_freq: Primary freq. * @dfs_precac_timer_running: Precac timer running. * @dfs_defer_precac_channel_change: Defer precac channel change. + * @dfs_precac_preferred_chan: Channel to change after precac. + * @dfs_precac_inter_chan: Intermediate non-DFS channel used while + * doing precac. * @dfs_pre_cac_timeout_channel_change: Channel change due to precac timeout. * @wlan_dfs_task_timer: Dfs wait timer. * @dur_multiplier: Duration multiplier. @@ -1017,6 +1020,10 @@ struct wlan_dfs { uint8_t dfs_precac_primary_freq; uint8_t dfs_precac_timer_running; uint8_t dfs_defer_precac_channel_change; +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT + uint8_t dfs_precac_preferred_chan; + uint8_t dfs_precac_inter_chan; +#endif uint8_t dfs_pre_cac_timeout_channel_change:1; os_timer_t wlan_dfs_task_timer; int dur_multiplier; @@ -2045,6 +2052,18 @@ void dfs_stacac_stop(struct wlan_dfs *dfs); void dfs_find_precac_secondary_vht80_chan(struct wlan_dfs *dfs, struct dfs_channel *chan); +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +/** + * dfs_precac_csa() - Automatically switch the channel to the DFS channel + * on which PreCAC was completed without finding a RADAR. + * Use CSA with TBTT_COUNT to switch the channel. + * @dfs: Pointer to dfs handler. + * + * Return: Void + */ +void dfs_precac_csa(struct wlan_dfs *dfs); +#endif + /** * dfs_phyerr_param_copy() - Function to copy src buf to dest buf. * @dst: dest buf. diff --git a/umac/dfs/core/src/dfs_zero_cac.h b/umac/dfs/core/src/dfs_zero_cac.h index 635412cb6fda..0d18c958e162 100644 --- a/umac/dfs/core/src/dfs_zero_cac.h +++ b/umac/dfs/core/src/dfs_zero_cac.h @@ -49,6 +49,22 @@ struct dfs_precac_entry { struct wlan_dfs *dfs; }; +/** + * enum precac_chan_state - Enum for PreCAC state of a channel. + * @PRECAC_ERR: Invalid preCAC state. + * @PRECAC_REQUIRED: preCAC need to be done on the channel. + * @PRECAC_NOW: preCAC is running on the channel. + * @PRECAC_DONE: preCAC is done and channel is clear. + * @PRECAC_NOL: preCAC is done and radar is detected. + */ +enum precac_chan_state { + PRECAC_ERR = -1, + PRECAC_REQUIRED, + PRECAC_NOW, + PRECAC_DONE, + PRECAC_NOL, +}; + /** * dfs_zero_cac_timer_init() - Initialize zero-cac timers * @dfs: Pointer to DFS structure. @@ -164,16 +180,42 @@ static inline void dfs_zero_cac_reset(struct wlan_dfs *dfs) /** * dfs_is_precac_done() - Is precac done. * @dfs: Pointer to wlan_dfs structure. + * @chan: Pointer to dfs_channel for which preCAC done is checked. + * + * Return: + * * True: If precac is done on channel. + * * False: If precac is not done on channel. */ #if defined(WLAN_DFS_PARTIAL_OFFLOAD) -bool dfs_is_precac_done(struct wlan_dfs *dfs); +bool dfs_is_precac_done(struct wlan_dfs *dfs, struct dfs_channel *chan); #else -static inline bool dfs_is_precac_done(struct wlan_dfs *dfs) +static inline bool dfs_is_precac_done(struct wlan_dfs *dfs, + struct dfs_channel *chan) { return false; } #endif +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +/** + * dfs_decide_precac_preferred_chan() - Choose operating channel among + * configured DFS channel and + * intermediate channel based on + * precac status of configured + * DFS channel. + * @dfs: Pointer to wlan_dfs structure. + * @pref_chan: Congigired DFS channel. + * + * Return: void. + */ +void dfs_decide_precac_preferred_chan(struct wlan_dfs *dfs, uint8_t *pref_chan); +#else +static inline void dfs_decide_precac_preferred_chan(struct wlan_dfs *dfs, + uint8_t *pref_chan) +{ +} +#endif + /** * dfs_get_freq_from_precac_required_list() - Get VHT80 freq from * precac_required_list. @@ -301,6 +343,67 @@ static inline uint32_t dfs_get_precac_enable(struct wlan_dfs *dfs) } #endif +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +/** + * dfs_set_precac_intermediate_chan() - Set intermediate chan to be used while + * doing precac. + * @dfs: Pointer to wlan_dfs structure. + * @value: input value for dfs_precac_enable flag. + * + * Return: + * * 0 - Successfully set intermediate channel. + * * -EINVAL - Invalid channel. + */ +int32_t dfs_set_precac_intermediate_chan(struct wlan_dfs *dfs, + uint32_t value); +#else +static inline int32_t dfs_set_precac_intermediate_chan(struct wlan_dfs *dfs, + uint32_t value) +{ + return 0; +} +#endif + +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +/** + * dfs_get_precac_intermediate_chan() - Get configured precac + * intermediate channel. + * @dfs: Pointer to wlan_dfs structure. + * + * Return: Configured intermediate channel number. + */ +uint32_t dfs_get_precac_intermediate_chan(struct wlan_dfs *dfs); +#else +static inline uint32_t dfs_get_intermediate_chan(struct wlan_dfs *dfs) +{ + return 0; +} +#endif + +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +/** + * dfs_get_precac_chan_state() - Get precac status of a given channel. + * @dfs: Pointer to wlan_dfs structure. + * @precac_chan: Channel number for which precac state need to be checked. + * + * Return: + * * PRECAC_REQUIRED: Precac has not done on precac_chan. + * * PRECAC_NOW : Precac is running on precac_chan. + * * PRECAC_DONE : precac_chan is in precac done list. + * * PRECAC_NOL : precac_chan is in precac NOL list. + * * PRECAC_ERR : Invalid precac state. + */ +enum precac_chan_state +dfs_get_precac_chan_state(struct wlan_dfs *dfs, uint8_t precac_chan); +#else +static inline enum precac_chan_state +dfs_get_precac_chan_state(struct wlan_dfs *dfs, + uint8_t precac_chan) +{ + return PRECAC_REQUIRED; +} +#endif + /** * dfs_zero_cac_reset() - Reset Zero cac DFS variables. * @dfs: Pointer to wlan_dfs structure. @@ -311,15 +414,27 @@ void dfs_zero_cac_reset(struct wlan_dfs *dfs); * dfs_is_ht20_40_80_chan_in_precac_done_list() - Is precac done on a * VHT20/40/80 channel. *@dfs: Pointer to wlan_dfs structure. + *@chan: Pointer to dfs_channel for which preCAC done is checked. + * + * Return: + * * True: If channel is present in precac-done list. + * * False: If channel is not present in precac-done list. */ -bool dfs_is_ht20_40_80_chan_in_precac_done_list(struct wlan_dfs *dfs); +bool dfs_is_ht20_40_80_chan_in_precac_done_list(struct wlan_dfs *dfs, + struct dfs_channel *chan); /** * dfs_is_ht80_80_chan_in_precac_done_list() - Is precac done on a VHT80+80 * channel. *@dfs: Pointer to wlan_dfs structure. + *@chan: Pointer to dfs_channel for which preCAC done is checked. + * + * Return: + * * True: If channel is present in precac-done list. + * * False: If channel is not present in precac-done list. */ -bool dfs_is_ht80_80_chan_in_precac_done_list(struct wlan_dfs *dfs); +bool dfs_is_ht80_80_chan_in_precac_done_list(struct wlan_dfs *dfs, + struct dfs_channel *chan); /** * dfs_mark_precac_dfs() - Mark the precac channel as radar. diff --git a/umac/dfs/core/src/misc/dfs_zero_cac.c b/umac/dfs/core/src/misc/dfs_zero_cac.c index b492763ac24d..a2edffde5d23 100644 --- a/umac/dfs/core/src/misc/dfs_zero_cac.c +++ b/umac/dfs/core/src/misc/dfs_zero_cac.c @@ -146,7 +146,8 @@ int dfs_get_override_precac_timeout(struct wlan_dfs *dfs, int *precac_timeout) #define IS_WITHIN_RANGE(_A, _B, _C) \ (((_A) >= ((_B)-(_C))) && ((_A) <= ((_B)+(_C)))) -bool dfs_is_ht20_40_80_chan_in_precac_done_list(struct wlan_dfs *dfs) +bool dfs_is_ht20_40_80_chan_in_precac_done_list(struct wlan_dfs *dfs, + struct dfs_channel *chan) { struct dfs_precac_entry *precac_entry; bool ret_val = 0; @@ -161,9 +162,9 @@ bool dfs_is_ht20_40_80_chan_in_precac_done_list(struct wlan_dfs *dfs) &dfs->dfs_precac_done_list, pe_list) { /* Find if the VHT80 freq1 is in Pre-CAC done list */ - if (IS_WITHIN_RANGE(dfs->dfs_curchan->dfs_ch_ieee, - precac_entry->vht80_freq, - VHT80_OFFSET)) { + if (IS_WITHIN_RANGE(chan->dfs_ch_ieee, + precac_entry->vht80_freq, + VHT80_OFFSET)) { ret_val = 1; break; } @@ -176,7 +177,8 @@ bool dfs_is_ht20_40_80_chan_in_precac_done_list(struct wlan_dfs *dfs) return ret_val; } -bool dfs_is_ht80_80_chan_in_precac_done_list(struct wlan_dfs *dfs) +bool dfs_is_ht80_80_chan_in_precac_done_list(struct wlan_dfs *dfs, + struct dfs_channel *chan) { struct dfs_precac_entry *precac_entry; bool ret_val = 0; @@ -185,11 +187,11 @@ bool dfs_is_ht80_80_chan_in_precac_done_list(struct wlan_dfs *dfs) if (!TAILQ_EMPTY(&dfs->dfs_precac_done_list)) { bool primary_found = 0; /* Check if primary is DFS then search */ - if (WLAN_IS_CHAN_DFS(dfs->dfs_curchan)) { + if (WLAN_IS_CHAN_DFS(chan)) { TAILQ_FOREACH(precac_entry, &dfs->dfs_precac_done_list, pe_list) { - if (dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1 + if (chan->dfs_ch_vhtop_ch_freq_seg1 == precac_entry->vht80_freq) { primary_found = 1; break; @@ -200,12 +202,12 @@ bool dfs_is_ht80_80_chan_in_precac_done_list(struct wlan_dfs *dfs) } /* Check if secondary DFS then search */ - if (WLAN_IS_CHAN_DFS_CFREQ2(dfs->dfs_curchan) && - primary_found) { + if (WLAN_IS_CHAN_DFS_CFREQ2(chan) && + primary_found) { TAILQ_FOREACH(precac_entry, &dfs->dfs_precac_done_list, pe_list) { - if (dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2 + if (chan->dfs_ch_vhtop_ch_freq_seg2 == precac_entry->vht80_freq) { /* Now secondary also found */ ret_val = 1; @@ -221,24 +223,24 @@ bool dfs_is_ht80_80_chan_in_precac_done_list(struct wlan_dfs *dfs) dfs_debug(dfs, WLAN_DEBUG_DFS, "freq_seg1 = %u freq_seq2 = %u ret_val = %d", - dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1, - dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2, + chan->dfs_ch_vhtop_ch_freq_seg1, + chan->dfs_ch_vhtop_ch_freq_seg2, ret_val); return ret_val; } -bool dfs_is_precac_done(struct wlan_dfs *dfs) +bool dfs_is_precac_done(struct wlan_dfs *dfs, struct dfs_channel *chan) { bool ret_val = 0; - if (WLAN_IS_CHAN_11AC_VHT20(dfs->dfs_curchan) || - WLAN_IS_CHAN_11AC_VHT40(dfs->dfs_curchan) || - WLAN_IS_CHAN_11AC_VHT80(dfs->dfs_curchan)) { - ret_val = dfs_is_ht20_40_80_chan_in_precac_done_list(dfs); - } else if (WLAN_IS_CHAN_11AC_VHT80_80(dfs->dfs_curchan) || - WLAN_IS_CHAN_11AC_VHT160(dfs->dfs_curchan)) { - ret_val = dfs_is_ht80_80_chan_in_precac_done_list(dfs); + if (WLAN_IS_CHAN_11AC_VHT20(chan) || + WLAN_IS_CHAN_11AC_VHT40(chan) || + WLAN_IS_CHAN_11AC_VHT80(chan)) { + ret_val = dfs_is_ht20_40_80_chan_in_precac_done_list(dfs, chan); + } else if (WLAN_IS_CHAN_11AC_VHT80_80(chan) || + WLAN_IS_CHAN_11AC_VHT160(chan)) { + ret_val = dfs_is_ht80_80_chan_in_precac_done_list(dfs, chan); } dfs_debug(dfs, WLAN_DEBUG_DFS, "ret_val = %d", ret_val); @@ -384,6 +386,95 @@ void dfs_find_precac_secondary_vht80_chan(struct wlan_dfs *dfs, &(chan->dfs_ch_vhtop_ch_freq_seg2)); } +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +void dfs_precac_csa(struct wlan_dfs *dfs) +{ + uint32_t ieeechan = dfs->dfs_precac_preferred_chan; + + /* + * Save current chan into intermediate chan, so that + * next time a DFS channel needs preCAC, there is no channel switch + * until preCAC finishes. + */ + dfs->dfs_precac_inter_chan = dfs->dfs_precac_preferred_chan; + + /* reset once the channel is used */ + dfs->dfs_precac_preferred_chan = 0; + + if (NULL != global_dfs_to_mlme.mlme_precac_chan_change_csa) + global_dfs_to_mlme.mlme_precac_chan_change_csa( + dfs->dfs_pdev_obj, + ieeechan); +} +#endif + +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +/** + * dfs_precac_check_home_chan_change() - Change the home channel + * after precac is done. + * + * @dfs: Pointer to dfs handler. + * + * If precac is done on the home channel, then change the channel from + * intermediate channel to home channel and continue precac on other channels. + * + * Return: Void. + */ +static void dfs_precac_check_home_chan_change(struct wlan_dfs *dfs) +{ + struct dfs_channel chan; + bool is_home_chan_changed = false; + + qdf_mem_zero(&chan, sizeof(struct dfs_channel)); + if (dfs->dfs_precac_preferred_chan) { + if (QDF_STATUS_SUCCESS != + dfs_mlme_find_dot11_channel(dfs->dfs_pdev_obj, + dfs->dfs_precac_preferred_chan, + 0, WLAN_PHYMODE_11AC_VHT80, + &chan.dfs_ch_freq, + &chan.dfs_ch_flags, + &chan.dfs_ch_flagext, + &chan.dfs_ch_ieee, + &chan.dfs_ch_vhtop_ch_freq_seg1, + &chan.dfs_ch_vhtop_ch_freq_seg2)) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, + "Invalid preferred channel %d", + dfs->dfs_precac_preferred_chan); + return; + } + is_home_chan_changed = dfs_is_precac_done(dfs, &chan); + } + /* + * Change home channel using CSA + * and continue to next preCAC channel. + */ + if (is_home_chan_changed) { + dfs_precac_csa(dfs); + } else { + /* + * Use same home channel, only change preCAC channel. + */ + + /* + * TODO xxx : Need to lock the channel change. + */ + dfs_mlme_channel_change_by_precac(dfs->dfs_pdev_obj); + } +} +#else +static inline void dfs_precac_check_home_chan_change(struct wlan_dfs *dfs) +{ + /* + * Use same home channel, only change preCAC channel. + */ + + /* + * TODO xxx : Need to lock the channel change. + */ + dfs_mlme_channel_change_by_precac(dfs->dfs_pdev_obj); +} +#endif + /** * dfs_precac_timeout() - Precac timeout. * @@ -428,10 +519,10 @@ static os_timer_func(dfs_precac_timeout) "Pre-cac expired, Precac Secondary chan %u curr time %d", dfs->dfs_precac_secondary_freq, (qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000)); - /* Do vdev restart so that we can change the secondary VHT80 channel. */ - - /* TODO xxx : Need to lock the channel change */ - dfs_mlme_channel_change_by_precac(dfs->dfs_pdev_obj); + /* + * Do vdev restart so that we can change the secondary VHT80 channel. + */ + dfs_precac_check_home_chan_change(dfs); } void dfs_zero_cac_timer_init(struct wlan_dfs *dfs) @@ -769,6 +860,151 @@ void dfs_reset_precac_lists(struct wlan_dfs *dfs) dfs_reset_precaclists(dfs); } +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +void dfs_set_precac_preferred_channel(struct wlan_dfs *dfs, + struct dfs_channel *chan) +{ + bool found = false; + struct dfs_precac_entry *precac_entry; + + dfs->dfs_precac_preferred_chan = chan->dfs_ch_ieee; + if (dfs_is_precac_timer_running(dfs) && + (dfs->dfs_precac_secondary_freq == chan->dfs_ch_freq)) { + return; + } + + /* Remove and insert into head, so that the user configured channel + * is picked first for preCAC. + */ + PRECAC_LIST_LOCK(dfs); + if (!TAILQ_EMPTY(&dfs->dfs_precac_required_list)) { + TAILQ_FOREACH(precac_entry, + &dfs->dfs_precac_required_list, pe_list) { + if (precac_entry->vht80_freq == + chan->dfs_ch_vhtop_ch_freq_seg1) { + found = true; + TAILQ_REMOVE(&dfs->dfs_precac_required_list, + precac_entry, pe_list); + TAILQ_INSERT_HEAD(&dfs->dfs_precac_required_list, + precac_entry, pe_list); + break; + } + } + } + PRECAC_LIST_UNLOCK(dfs); + + if (!found) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, + "frequency %d not found in precac list", + chan->dfs_ch_vhtop_ch_freq_seg1); + return; + } +} + +void dfs_decide_precac_preferred_chan(struct wlan_dfs *dfs, uint8_t *pref_chan) +{ + struct dfs_channel chan; + + qdf_mem_zero(&chan, sizeof(struct dfs_channel)); + if (QDF_STATUS_SUCCESS != + dfs_mlme_find_dot11_channel(dfs->dfs_pdev_obj, + *pref_chan, 0, + WLAN_PHYMODE_11AC_VHT80, + &chan.dfs_ch_freq, + &chan.dfs_ch_flags, + &chan.dfs_ch_flagext, + &chan.dfs_ch_ieee, + &chan.dfs_ch_vhtop_ch_freq_seg1, + &chan.dfs_ch_vhtop_ch_freq_seg2)) + return; + if (!dfs->dfs_precac_inter_chan) + return; + + /* + * If precac is done on this channel use it, else use a intermediate + * non-DFS channel and trigger a precac on this channel. + */ + if (WLAN_IS_CHAN_DFS(&chan) && !dfs_is_precac_done(dfs, &chan)) { + dfs_set_precac_preferred_channel(dfs, &chan); + *pref_chan = dfs->dfs_precac_inter_chan; + + } else { + dfs->dfs_precac_inter_chan = chan.dfs_ch_ieee; + } +} + +enum precac_chan_state +dfs_get_precac_chan_state(struct wlan_dfs *dfs, uint8_t precac_chan) +{ + struct dfs_channel chan; + struct dfs_precac_entry *tmp_precac_entry; + enum precac_chan_state ret = PRECAC_ERR; + + qdf_mem_zero(&chan, sizeof(struct dfs_channel)); + if (QDF_STATUS_SUCCESS != + dfs_mlme_find_dot11_channel(dfs->dfs_pdev_obj, + precac_chan, 0, + WLAN_PHYMODE_11AC_VHT80, + &chan.dfs_ch_freq, + &chan.dfs_ch_flags, + &chan.dfs_ch_flagext, + &chan.dfs_ch_ieee, + &chan.dfs_ch_vhtop_ch_freq_seg1, + &chan.dfs_ch_vhtop_ch_freq_seg2)) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, + "Intermediate channel not found"); + return PRECAC_ERR; + } + + if (!WLAN_IS_CHAN_DFS(&chan)) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, + "[%d] Not a DFS channel", precac_chan); + return PRECAC_ERR; + } + + PRECAC_LIST_LOCK(dfs); + if (dfs_is_precac_timer_running(dfs)) { + tmp_precac_entry = TAILQ_FIRST(&dfs->dfs_precac_required_list); + if (tmp_precac_entry && (tmp_precac_entry->vht80_freq == + chan.dfs_ch_vhtop_ch_freq_seg1)) { + ret = PRECAC_NOW; + goto end; + } + } + + TAILQ_FOREACH(tmp_precac_entry, + &dfs->dfs_precac_required_list, pe_list) { + if (tmp_precac_entry->vht80_freq == + chan.dfs_ch_vhtop_ch_freq_seg1) { + ret = PRECAC_REQUIRED; + goto end; + } + } + + TAILQ_FOREACH(tmp_precac_entry, + &dfs->dfs_precac_done_list, pe_list) { + if (tmp_precac_entry->vht80_freq == + chan.dfs_ch_vhtop_ch_freq_seg1) { + ret = PRECAC_DONE; + goto end; + } + } + + TAILQ_FOREACH(tmp_precac_entry, + &dfs->dfs_precac_nol_list, pe_list) { + if (tmp_precac_entry->vht80_freq == + chan.dfs_ch_vhtop_ch_freq_seg1) { + ret = PRECAC_NOL; + goto end; + } + } + +end: + PRECAC_LIST_UNLOCK(dfs); + return ret; +} +#endif + void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs, uint32_t chan_mode, uint8_t ch_freq_seg1, @@ -778,29 +1014,7 @@ void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs, bool *dfs_set_cfreq2, bool *set_agile) { - struct wlan_objmgr_psoc *psoc; - struct wlan_lmac_if_target_tx_ops *tx_ops; - uint32_t target_type; - - psoc = wlan_pdev_get_psoc(dfs->dfs_pdev_obj); - if (!psoc) { - dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "psoc is NULL"); - return; - } - - tx_ops = &(psoc->soc_cb.tx_ops.target_tx_ops); - target_type = lmac_get_target_type(dfs->dfs_pdev_obj); - if (chan_mode == WLAN_PHYMODE_11AC_VHT80) { - /* - * If - * 1) The chip is CASCADE - * 2) The user phy_mode is VHT80 and - * 3) The user has enabled Pre-CAC and - * 4) The regdomain the ETSI - * then find a center frequency for the secondary VHT80 and - * Change the mode to VHT80_80 or VHT160 - */ uint8_t ieee_freq; dfs_debug(dfs, WLAN_DEBUG_DFS, @@ -808,10 +1022,12 @@ void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs, dfs->dfs_precac_secondary_freq, dfs->dfs_precac_timer_running); - if (dfs->dfs_precac_enable && - tx_ops->tgt_is_tgt_type_qca9984(target_type) && - (utils_get_dfsdomain(dfs->dfs_pdev_obj) == - DFS_ETSI_DOMAIN)) { + /* + * If Pre-CAC is enabled then find a center frequency for + * the secondary VHT80 and Change the mode to + * VHT80_80 or VHT160. + */ + if (dfs->dfs_precac_enable) { /* * If precac timer is running then do not change the * secondary channel use the old secondary VHT80 @@ -903,6 +1119,8 @@ void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs, /* Start the pre_cac_timer */ dfs_start_precac_timer(dfs, dfs->dfs_precac_secondary_freq); + } else { + dfs->dfs_precac_secondary_freq = 0; } /* End of if(ieee_freq) */ } /* End of if(dfs->dfs_precac_enable) */ } @@ -910,10 +1128,83 @@ void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs, void dfs_set_precac_enable(struct wlan_dfs *dfs, uint32_t value) { - dfs->dfs_precac_enable = value; + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_target_tx_ops *tx_ops; + uint32_t target_type; + + psoc = wlan_pdev_get_psoc(dfs->dfs_pdev_obj); + if (!psoc) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "psoc is NULL"); + dfs->dfs_precac_enable = 0; + return; + } + + tx_ops = &psoc->soc_cb.tx_ops.target_tx_ops; + target_type = lmac_get_target_type(dfs->dfs_pdev_obj); + + /* + * If + * 1) The chip is CASCADE, + * 3) The user has enabled Pre-CAC and + * 4) The regdomain the ETSI, + * then enable preCAC. + */ + if ((1 == value) && tx_ops->tgt_is_tgt_type_qca9984(target_type) && + (utils_get_dfsdomain(dfs->dfs_pdev_obj) == DFS_ETSI_DOMAIN)) { + dfs->dfs_precac_enable = value; + } else { + dfs->dfs_precac_enable = 0; + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "preCAC disabled"); + } + if (dfs_is_precac_timer_running(dfs)) { + dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, + "Precac flag changed. Cancel the precac timer"); + dfs_cancel_precac_timer(dfs); + } } uint32_t dfs_get_precac_enable(struct wlan_dfs *dfs) { return dfs->dfs_precac_enable; } + +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +int32_t dfs_set_precac_intermediate_chan(struct wlan_dfs *dfs, uint32_t value) +{ + struct dfs_channel chan; + + qdf_mem_zero(&chan, sizeof(struct dfs_channel)); + if (QDF_STATUS_SUCCESS != + dfs_mlme_find_dot11_channel(dfs->dfs_pdev_obj, + value, 0, + WLAN_PHYMODE_11AC_VHT80, + &chan.dfs_ch_freq, + &chan.dfs_ch_flags, + &chan.dfs_ch_flagext, + &chan.dfs_ch_ieee, + &chan.dfs_ch_vhtop_ch_freq_seg1, + &chan.dfs_ch_vhtop_ch_freq_seg2)) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, + "Intermediate channel not found"); + return -EINVAL; + } + + /*Intermediate channel should be non-DFS channel*/ + if (!WLAN_IS_CHAN_DFS(&chan)) { + dfs->dfs_precac_inter_chan = value; + } else { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "intermediate channel %s", + (chan.dfs_ch_ieee == value) ? + "should not be DFS channel" : "is invalid"); + dfs->dfs_precac_inter_chan = 0; + return -EINVAL; + } + + return 0; +} + +uint32_t dfs_get_precac_intermediate_chan(struct wlan_dfs *dfs) +{ + return dfs->dfs_precac_inter_chan; +} +#endif diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h index 08cbdc7865bc..535c34a73c81 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h @@ -135,17 +135,22 @@ int dfs_mlme_ieee2mhz(struct wlan_objmgr_pdev *pdev, * @dfs_ch_vhtop_ch_freq_seg1: Channel Center frequency. * @dfs_ch_vhtop_ch_freq_seg2: Channel Center frequency applicable for 80+80MHz * mode of operation. + * + * Return: + * * QDF_STATUS_SUCCESS : Channel found. + * * QDF_STATUS_E_FAILURE: Channel not found. */ -void dfs_mlme_find_dot11_channel(struct wlan_objmgr_pdev *pdev, - uint8_t ieee, - uint8_t des_cfreq2, - int mode, - uint16_t *dfs_ch_freq, - uint64_t *dfs_ch_flags, - uint16_t *dfs_ch_flagext, - uint8_t *dfs_ch_ieee, - uint8_t *dfs_ch_vhtop_ch_freq_seg1, - uint8_t *dfs_ch_vhtop_ch_freq_seg2); +QDF_STATUS +dfs_mlme_find_dot11_channel(struct wlan_objmgr_pdev *pdev, + uint8_t ieee, + uint8_t des_cfreq2, + int mode, + uint16_t *dfs_ch_freq, + uint64_t *dfs_ch_flags, + uint16_t *dfs_ch_flagext, + uint8_t *dfs_ch_ieee, + uint8_t *dfs_ch_vhtop_ch_freq_seg1, + uint8_t *dfs_ch_vhtop_ch_freq_seg2); /** * dfs_mlme_get_dfs_ch_channels() - Get channel from channel list. @@ -160,13 +165,13 @@ void dfs_mlme_find_dot11_channel(struct wlan_objmgr_pdev *pdev, * @index: Index into channel list. */ void dfs_mlme_get_dfs_ch_channels(struct wlan_objmgr_pdev *pdev, - uint16_t *dfs_ch_freq, - uint64_t *dfs_ch_flags, - uint16_t *dfs_ch_flagext, - uint8_t *dfs_ch_ieee, - uint8_t *dfs_ch_vhtop_ch_freq_seg1, - uint8_t *dfs_ch_vhtop_ch_freq_seg2, - int index); + uint16_t *dfs_ch_freq, + uint64_t *dfs_ch_flags, + uint16_t *dfs_ch_flagext, + uint8_t *dfs_ch_ieee, + uint8_t *dfs_ch_vhtop_ch_freq_seg1, + uint8_t *dfs_ch_vhtop_ch_freq_seg2, + int index); /** * dfs_mlme_dfs_ch_flags_ext() - Get extension channel flags. diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h index 7e6387c52752..027c747fb3d3 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h @@ -48,6 +48,8 @@ * @mlme_get_dfs_ch_channels: Get the channel list. * @mlme_dfs_ch_flags_ext: Gets channel extension flag. * @mlme_channel_change_by_precac: Channel change triggered by PreCAC. + * @mlme_precac_chan_change_csa: Channel change triggered by PrCAC using + * Channel Switch Announcement. * @mlme_nol_timeout_notification: NOL timeout notification. * @mlme_clist_update: Updates the channel list. * @mlme_get_cac_timeout: Gets the CAC timeout. @@ -119,6 +121,10 @@ struct dfs_to_mlme { uint16_t *flag_ext); QDF_STATUS (*mlme_channel_change_by_precac)( struct wlan_objmgr_pdev *pdev); +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT + QDF_STATUS (*mlme_precac_chan_change_csa)(struct wlan_objmgr_pdev *pdev, + uint8_t ch_ieee); +#endif QDF_STATUS (*mlme_nol_timeout_notification)( struct wlan_objmgr_pdev *pdev); QDF_STATUS (*mlme_clist_update)(struct wlan_objmgr_pdev *pdev, @@ -227,7 +233,7 @@ QDF_STATUS ucfg_dfs_override_precac_timeout(struct wlan_objmgr_pdev *pdev, * This function called from outside of dfs component. */ QDF_STATUS ucfg_dfs_set_precac_enable(struct wlan_objmgr_pdev *pdev, - uint32_t value); + uint32_t value); /** * ucfg_dfs_get_precac_enable() - Get precac enable flag. @@ -239,6 +245,52 @@ QDF_STATUS ucfg_dfs_set_precac_enable(struct wlan_objmgr_pdev *pdev, */ QDF_STATUS ucfg_dfs_get_precac_enable(struct wlan_objmgr_pdev *pdev, int *buff); +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +/** + * ucfg_dfs_set_precac_intermediate_chan() - Set intermediate channel + * for preCAC. + * @pdev: Pointer to DFS pdev object. + * @value: Channel number of intermediate channel + * + * Wrapper function for dfs_set_precac_intermediate_chan(). + * This function is called from outside of dfs component. + * + * Return: + * * QDF_STATUS_SUCCESS : Successfully set intermediate channel. + * * QDF_STATUS_E_FAILURE: Failed to set intermediate channel. + */ +QDF_STATUS ucfg_dfs_set_precac_intermediate_chan(struct wlan_objmgr_pdev *pdev, + uint32_t value); + +/** + * ucfg_dfs_get_precac_intermediate_chan() - Get intermediate channel + * for preCAC. + * @pdev: Pointer to DFS pdev object. + * @buff: Pointer to Channel number of intermediate channel. + * + * Wrapper function for dfs_get_precac_intermediate_chan(). + * This function is called from outside of dfs component. + * + * Return: Configured intermediate precac channel. + */ +QDF_STATUS ucfg_dfs_get_precac_intermediate_chan(struct wlan_objmgr_pdev *pdev, + int *buff); + +/** + * ucfg_dfs_get_precac_chan_state() - Get precac status for the given channel. + * @pdev: Pointer to DFS pdev object. + * @precac_chan: Channel number for which precac state needs to be determined. + * + * Wrapper function for dfs_get_precac_chan_state(). + * This function called from outside of dfs component. + * + * Return: Precac state of the given channel. + */ +enum precac_chan_state +ucfg_dfs_get_precac_chan_state(struct wlan_objmgr_pdev *pdev, + uint8_t precac_chan); +#endif + #ifdef QCA_MCL_DFS_SUPPORT /** * ucfg_dfs_update_config() - Update DFS user config. diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h index 9acb0145d665..efb404565b46 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h @@ -136,6 +136,19 @@ static inline QDF_STATUS utils_dfs_reset_etsi_precaclists( */ QDF_STATUS utils_dfs_cancel_precac_timer(struct wlan_objmgr_pdev *pdev); +/** + * utils_dfs_start_precac_timer() - Start the precac timer. + * @pdev: Pointer to DFS pdev object. + * + * Wrapper function for dfs_start_precac_timer(). This function called from + * outside of dfs component. + * + * Return: + * * QDF_STATUS_E_FAILURE: Failed to start timer. + * * QDF_STATUS_SUCCESS: Timer started successfully. + */ +QDF_STATUS utils_dfs_start_precac_timer(struct wlan_objmgr_pdev *pdev); + /** * utils_dfs_is_precac_done() - Is precac done. * @pdev: Pointer to DFS pdev object. @@ -146,6 +159,23 @@ 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); +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +/** + * utils_dfs_precac_decide_pref_chan() - Choose preferred channel + * @pdev: Pointer to DFS pdev object. + * @ch_ieee: Pointer to channel number + + * Wrapper function for dfs_decide_precac_preferred_chan(). This + * function called from outside of dfs component. + * + * Return: + * * QDF_STATUS_E_FAILURE: Failed to decide preferred channel. + * * QDF_STATUS_SUCCESS: Set preferred channel successfully. + */ +QDF_STATUS utils_dfs_precac_decide_pref_chan(struct wlan_objmgr_pdev *pdev, + uint8_t *ch_ieee); +#endif + /** * utils_dfs_is_esti_precac_done() - Is ETSI precac done. * @pdev: Pointer to DFS pdev object. diff --git a/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c b/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c index 895f184dfab8..8f562b22cd8a 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c @@ -47,6 +47,23 @@ struct wlan_dfs *wlan_pdev_get_dfs_obj(struct wlan_objmgr_pdev *pdev) } #ifndef QCA_MCL_DFS_SUPPORT +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +static inline void +register_dfs_precac_auto_chan_callbacks(struct dfs_to_mlme *mlme_callback) +{ + if (!mlme_callback) + return; + + mlme_callback->mlme_precac_chan_change_csa = + mlme_dfs_precac_chan_change_csa; +} +#else +static inline void +register_dfs_precac_auto_chan_callbacks(struct dfs_to_mlme *mlme_callback) +{ +} +#endif + void register_dfs_callbacks(void) { struct dfs_to_mlme *tmp_dfs_to_mlme = &global_dfs_to_mlme; @@ -85,6 +102,11 @@ void register_dfs_callbacks(void) mlme_dfs_restart_vaps_with_non_dfs_chan; tmp_dfs_to_mlme->mlme_check_allowed_prim_chanlist = mlme_dfs_check_allowed_prim_chanlist; + + /* + * Register precac auto channel switch feature related callbacks + */ + register_dfs_precac_auto_chan_callbacks(tmp_dfs_to_mlme); } #else void register_dfs_callbacks(void) diff --git a/umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c b/umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c index 0aa73f93214a..ecead3f20f24 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c @@ -188,28 +188,30 @@ int dfs_mlme_ieee2mhz(struct wlan_objmgr_pdev *pdev, int ieee, uint64_t flag) return freq; } -void dfs_mlme_find_dot11_channel(struct wlan_objmgr_pdev *pdev, - uint8_t ieee, - uint8_t des_cfreq2, - int mode, - uint16_t *dfs_ch_freq, - uint64_t *dfs_ch_flags, - uint16_t *dfs_ch_flagext, - uint8_t *dfs_ch_ieee, - uint8_t *dfs_ch_vhtop_ch_freq_seg1, - uint8_t *dfs_ch_vhtop_ch_freq_seg2) +QDF_STATUS +dfs_mlme_find_dot11_channel(struct wlan_objmgr_pdev *pdev, + uint8_t ieee, + uint8_t des_cfreq2, + int mode, + uint16_t *dfs_ch_freq, + uint64_t *dfs_ch_flags, + uint16_t *dfs_ch_flagext, + uint8_t *dfs_ch_ieee, + uint8_t *dfs_ch_vhtop_ch_freq_seg1, + uint8_t *dfs_ch_vhtop_ch_freq_seg2) { if (global_dfs_to_mlme.mlme_find_dot11_channel != NULL) - global_dfs_to_mlme.mlme_find_dot11_channel(pdev, - ieee, - des_cfreq2, - mode, - dfs_ch_freq, - dfs_ch_flags, - dfs_ch_flagext, - dfs_ch_ieee, - dfs_ch_vhtop_ch_freq_seg1, - dfs_ch_vhtop_ch_freq_seg2); + return global_dfs_to_mlme.mlme_find_dot11_channel(pdev, + ieee, + des_cfreq2, + mode, + dfs_ch_freq, + dfs_ch_flags, + dfs_ch_flagext, + dfs_ch_ieee, + dfs_ch_vhtop_ch_freq_seg1, + dfs_ch_vhtop_ch_freq_seg2); + return QDF_STATUS_E_FAILURE; } void dfs_mlme_get_dfs_ch_channels(struct wlan_objmgr_pdev *pdev, diff --git a/umac/dfs/dispatcher/src/wlan_dfs_ucfg_api.c b/umac/dfs/dispatcher/src/wlan_dfs_ucfg_api.c index 6e4ac9bf7f75..bf3172bd6f66 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_ucfg_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_ucfg_api.c @@ -154,6 +154,62 @@ QDF_STATUS ucfg_dfs_get_precac_enable(struct wlan_objmgr_pdev *pdev, } qdf_export_symbol(ucfg_dfs_get_precac_enable); +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +QDF_STATUS ucfg_dfs_set_precac_intermediate_chan(struct wlan_objmgr_pdev *pdev, + uint32_t value) +{ + struct wlan_dfs *dfs; + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); + return QDF_STATUS_E_FAILURE; + } + + dfs_set_precac_intermediate_chan(dfs, value); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS ucfg_dfs_get_precac_intermediate_chan(struct wlan_objmgr_pdev *pdev, + int *buff) +{ + struct wlan_dfs *dfs; + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); + return QDF_STATUS_E_FAILURE; + } + + *buff = dfs_get_precac_intermediate_chan(dfs); + + return QDF_STATUS_SUCCESS; +} + +enum precac_chan_state +ucfg_dfs_get_precac_chan_state(struct wlan_objmgr_pdev *pdev, + uint8_t precac_chan) +{ + struct wlan_dfs *dfs; + enum precac_chan_state retval = PRECAC_ERR; + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); + return PRECAC_ERR; + } + + retval = dfs_get_precac_chan_state(dfs, precac_chan); + if (PRECAC_ERR == retval) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, + "Could not find precac channel state"); + } + + return retval; +} +#endif + #ifdef QCA_MCL_DFS_SUPPORT QDF_STATUS ucfg_dfs_update_config(struct wlan_objmgr_psoc *psoc, struct dfs_user_config *req) diff --git a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c index 9a956aa85ddf..8def886809cb 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c @@ -118,6 +118,36 @@ QDF_STATUS utils_dfs_cancel_precac_timer(struct wlan_objmgr_pdev *pdev) } qdf_export_symbol(utils_dfs_cancel_precac_timer); +QDF_STATUS utils_dfs_start_precac_timer(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_dfs *dfs; + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "NULL dfs"); + return QDF_STATUS_E_FAILURE; + } + dfs_start_precac_timer(dfs, dfs->dfs_precac_secondary_freq); + return QDF_STATUS_SUCCESS; +} + +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +QDF_STATUS utils_dfs_precac_decide_pref_chan(struct wlan_objmgr_pdev *pdev, + uint8_t *ch_ieee) +{ + struct wlan_dfs *dfs; + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "NULL dfs"); + return QDF_STATUS_E_FAILURE; + } + dfs_decide_precac_preferred_chan(dfs, ch_ieee); + + return QDF_STATUS_SUCCESS; +} +#endif + QDF_STATUS utils_dfs_is_precac_done(struct wlan_objmgr_pdev *pdev, bool *is_precac_done) { @@ -127,7 +157,7 @@ QDF_STATUS utils_dfs_is_precac_done(struct wlan_objmgr_pdev *pdev, if (!dfs) return QDF_STATUS_E_FAILURE; - *is_precac_done = dfs_is_precac_done(dfs); + *is_precac_done = dfs_is_precac_done(dfs, dfs->dfs_curchan); return QDF_STATUS_SUCCESS; } diff --git a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h index f24c90e3c7ed..9e430163deff 100644 --- a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h +++ b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h @@ -1037,6 +1037,12 @@ struct wlan_lmac_if_nan_rx_ops { * @dfs_override_precac_timeout: Override the default precac timeout. * @dfs_set_precac_enable: Set precac enable flag. * @dfs_get_precac_enable: Get precac enable flag. + * @dfs_set_precac_intermediate_chan: Set intermediate channel for precac. + * @dfs_get_precac_intermediate_chan: Get intermediate channel for precac. + * @dfs_precac_preferred_chan: Configure preferred channel during + * precac. + * dfs_get_precac_chan_state: Get precac status for given channel. + * dfs_start_precac_timer: Start precac timer. * @dfs_get_override_precac_timeout: Get precac timeout. * @dfs_set_current_channel: Set DFS current channel. * @dfs_process_radar_ind: Process radar found indication. @@ -1086,6 +1092,7 @@ struct wlan_lmac_if_dfs_rx_ops { uint32_t *phy_mode, bool *dfs_set_cfreq2, bool *set_agile); + QDF_STATUS (*dfs_start_precac_timer)(struct wlan_objmgr_pdev *pdev); QDF_STATUS (*dfs_cancel_precac_timer)(struct wlan_objmgr_pdev *pdev); QDF_STATUS (*dfs_override_precac_timeout)( struct wlan_objmgr_pdev *pdev, @@ -1094,6 +1101,16 @@ struct wlan_lmac_if_dfs_rx_ops { uint32_t value); QDF_STATUS (*dfs_get_precac_enable)(struct wlan_objmgr_pdev *pdev, int *buff); +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT + QDF_STATUS (*dfs_set_precac_intermediate_chan)(struct wlan_objmgr_pdev *pdev, + uint32_t value); + QDF_STATUS (*dfs_get_precac_intermediate_chan)(struct wlan_objmgr_pdev *pdev, + int *buff); + QDF_STATUS (*dfs_decide_precac_preferred_chan)(struct wlan_objmgr_pdev *pdev, + uint8_t *pref_chan); + enum precac_chan_state (*dfs_get_precac_chan_state)(struct wlan_objmgr_pdev *pdev, + uint8_t precac_chan); +#endif QDF_STATUS (*dfs_get_override_precac_timeout)( struct wlan_objmgr_pdev *pdev, int *precac_timeout); diff --git a/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c b/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c index db2ce5ca477f..535f89bdcdd3 100644 --- a/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c +++ b/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c @@ -301,6 +301,25 @@ static void wlan_lmac_if_umac_rx_ops_register_p2p( #endif #ifdef DFS_COMPONENT_ENABLE +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +static inline void +register_precac_auto_chan_rx_ops(struct wlan_lmac_if_dfs_rx_ops *rx_ops) +{ + if (!rx_ops) + return; + rx_ops->dfs_set_precac_intermediate_chan = + ucfg_dfs_set_precac_intermediate_chan; + rx_ops->dfs_get_precac_intermediate_chan = + ucfg_dfs_get_precac_intermediate_chan; + rx_ops->dfs_get_precac_chan_state = ucfg_dfs_get_precac_chan_state; +} +#else +static inline void +register_precac_auto_chan_rx_ops(struct wlan_lmac_if_dfs_rx_ops *rx_ops) +{ +} +#endif + static QDF_STATUS wlan_lmac_if_umac_dfs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) { @@ -318,6 +337,7 @@ wlan_lmac_if_umac_dfs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) tgt_dfs_is_precac_timer_running; dfs_rx_ops->dfs_find_vht80_chan_for_precac = tgt_dfs_find_vht80_chan_for_precac; + dfs_rx_ops->dfs_start_precac_timer = utils_dfs_start_precac_timer; dfs_rx_ops->dfs_cancel_precac_timer = utils_dfs_cancel_precac_timer; dfs_rx_ops->dfs_override_precac_timeout = ucfg_dfs_override_precac_timeout; @@ -341,6 +361,8 @@ wlan_lmac_if_umac_dfs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) dfs_rx_ops->dfs_reset_spoof_test = tgt_dfs_reset_spoof_test; + register_precac_auto_chan_rx_ops(dfs_rx_ops); + return QDF_STATUS_SUCCESS; } #else