diff --git a/umac/dfs/core/src/dfs.h b/umac/dfs/core/src/dfs.h index 5f620d6f97a6..7fab5611e617 100644 --- a/umac/dfs/core/src/dfs.h +++ b/umac/dfs/core/src/dfs.h @@ -984,6 +984,7 @@ struct dfs_event_log { * @dfs_precac_list: PreCAC list (contains individual trees). * @dfs_precac_chwidth: PreCAC channel width enum. * @dfs_curchan: DFS current channel. + * @dfs_prevchan: DFS previous channel. * @dfs_cac_started_chan: CAC started channel. * @dfs_pdev_obj: DFS pdev object. * @dfs_is_offload_enabled: Set if DFS offload enabled. @@ -1140,6 +1141,7 @@ struct wlan_dfs { enum phy_ch_width dfs_precac_chwidth; struct dfs_channel *dfs_curchan; + struct dfs_channel *dfs_prevchan; struct dfs_channel dfs_cac_started_chan; struct wlan_objmgr_pdev *dfs_pdev_obj; struct dfs_soc_priv_obj *dfs_soc_obj; @@ -2638,4 +2640,12 @@ void dfs_reset_agile_config(struct dfs_soc_priv_obj *dfs_soc); * @dfs: Pointer to wlan_dfs. */ int dfs_reinit_timers(struct wlan_dfs *dfs); + +/** + * dfs_reset_dfs_prevchan() - Reset DFS previous channel structure. + * @dfs: Pointer to wlan_dfs object. + * + * Return: None. + */ +void dfs_reset_dfs_prevchan(struct wlan_dfs *dfs); #endif /* _DFS_H_ */ diff --git a/umac/dfs/core/src/misc/dfs.c b/umac/dfs/core/src/misc/dfs.c index 9571bff5bacd..33f7c6331602 100644 --- a/umac/dfs/core/src/misc/dfs.c +++ b/umac/dfs/core/src/misc/dfs.c @@ -68,15 +68,20 @@ static inline struct dfs_channel *dfs_alloc_dfs_curchan(void) return qdf_mem_malloc(sizeof(struct dfs_channel)); } +static inline struct dfs_channel *dfs_alloc_dfs_prevchan(void) +{ + return qdf_mem_malloc(sizeof(struct dfs_channel)); +} + /* - * dfs_free_dfs_curchan() - Free dfs_channel buffer - * @dfs_curchan: dfs_channel buffer pointer + * dfs_free_dfs_chan() - Free dfs_channel buffer + * @dfs_chan: dfs_channel buffer pointer * * Return: None */ -static inline void dfs_free_dfs_curchan(struct dfs_channel *dfs_curchan) +static inline void dfs_free_dfs_chan(struct dfs_channel *dfs_chan) { - qdf_mem_free(dfs_curchan); + qdf_mem_free(dfs_chan); } #else @@ -84,6 +89,7 @@ static inline void dfs_free_dfs_curchan(struct dfs_channel *dfs_curchan) /* Static buffers for DFS objects */ static struct wlan_dfs global_dfs; static struct dfs_channel global_dfs_curchan; +static struct dfs_channel global_dfs_prevchan; static inline struct wlan_dfs *dfs_alloc_wlan_dfs(void) { @@ -99,7 +105,12 @@ static inline struct dfs_channel *dfs_alloc_dfs_curchan(void) return &global_dfs_curchan; } -static inline void dfs_free_dfs_curchan(struct dfs_channel *dfs_curchan) +static inline struct dfs_channel *dfs_alloc_dfs_prevchan(void) +{ + return &global_dfs_prevchan; +} + +static inline void dfs_free_dfs_chan(struct dfs_channel *dfs_chan) { } #endif @@ -161,6 +172,12 @@ int dfs_create_object(struct wlan_dfs **dfs) return 1; } + (*dfs)->dfs_prevchan = dfs_alloc_dfs_prevchan(); + if (!((*dfs)->dfs_prevchan)) { + dfs_free_wlan_dfs(*dfs); + return 1; + } + qdf_mem_zero((*dfs)->dfs_prevchan, sizeof(struct dfs_channel)); return 0; } @@ -260,7 +277,8 @@ void dfs_detach(struct wlan_dfs *dfs) #ifndef WLAN_DFS_STATIC_MEM_ALLOC void dfs_destroy_object(struct wlan_dfs *dfs) { - dfs_free_dfs_curchan(dfs->dfs_curchan); + dfs_free_dfs_chan(dfs->dfs_prevchan); + dfs_free_dfs_chan(dfs->dfs_curchan); dfs_free_wlan_dfs(dfs); } #else @@ -729,6 +747,39 @@ bad: return error; } +/** + * dfs_is_curchan_same_as_given_chan() - Find if dfs_curchan has the same + * channel parameters provided. + * @dfs_curchan: Pointer to DFS current channel structure. + * @dfs_ch_freq: New curchan's primary frequency. + * @dfs_ch_flags: New curchan's channel flags. + * @dfs_ch_flagext: New curchan's channel flags extension. + * @dfs_ch_vhtop_ch_freq_seg1: New curchan's primary centre IEEE. + * @dfs_ch_vhtop_ch_freq_seg2: New curchan's secondary centre IEEE. + * + * Return: True if curchan has the same channel parameters of the given channel, + * else false. + */ +static bool +dfs_is_curchan_same_as_given_chan(struct dfs_channel *dfs_curchan, + uint16_t dfs_ch_freq, + uint64_t dfs_ch_flags, + uint16_t dfs_ch_flagext, + uint8_t dfs_ch_vhtop_ch_freq_seg1, + uint8_t dfs_ch_vhtop_ch_freq_seg2) +{ + if ((dfs_curchan->dfs_ch_freq == dfs_ch_freq) && + (dfs_curchan->dfs_ch_flags == dfs_ch_flags) && + (dfs_curchan->dfs_ch_flagext == dfs_ch_flagext) && + (dfs_curchan->dfs_ch_vhtop_ch_freq_seg1 == + dfs_ch_vhtop_ch_freq_seg1) && + (dfs_curchan->dfs_ch_vhtop_ch_freq_seg2 == + dfs_ch_vhtop_ch_freq_seg2)) + return true; + + return false; +} + void dfs_set_current_channel(struct wlan_dfs *dfs, uint16_t dfs_ch_freq, uint64_t dfs_ch_flags, @@ -742,6 +793,29 @@ void dfs_set_current_channel(struct wlan_dfs *dfs, return; } + if (!dfs->dfs_curchan) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_curchan is NULL"); + return; + } + + /* Check if the input parameters are the same as that of dfs_curchan */ + if (dfs_is_curchan_same_as_given_chan(dfs->dfs_curchan, + dfs_ch_freq, + dfs_ch_flags, + dfs_ch_flagext, + dfs_ch_vhtop_ch_freq_seg1, + dfs_ch_vhtop_ch_freq_seg2)) { + dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, + "dfs_curchan already updated"); + return; + } + + /* Update dfs previous channel with the old dfs_curchan, if it exists */ + if (dfs->dfs_curchan->dfs_ch_freq) + qdf_mem_copy(dfs->dfs_prevchan, + dfs->dfs_curchan, + sizeof(struct dfs_channel)); + dfs->dfs_curchan->dfs_ch_freq = dfs_ch_freq; dfs->dfs_curchan->dfs_ch_flags = dfs_ch_flags; dfs->dfs_curchan->dfs_ch_flagext = dfs_ch_flagext; @@ -766,3 +840,8 @@ int dfs_reinit_timers(struct wlan_dfs *dfs) dfs_main_task_testtimer_init(dfs); return 0; } + +void dfs_reset_dfs_prevchan(struct wlan_dfs *dfs) +{ + qdf_mem_zero(dfs->dfs_prevchan, sizeof(struct dfs_channel)); +} diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h index a14d39dc826e..ece0338e271f 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h @@ -707,6 +707,24 @@ bool utils_dfs_is_cac_required(struct wlan_objmgr_pdev *pdev, struct wlan_channel *prev_chan, bool *continue_current_cac); +/** + * utils_dfs_is_cac_required_on_dfs_curchan() - Check if CAC is required on the + * dfs_curchan. + * @pdev: pdev ptr + * @continue_current_cac: If AP can start CAC then this variable indicates + * whether to continue with the current CAC or restart the CAC. This variable + * is valid only if this function returns true. + * + * This API checks if the dfs_curchan is a subset of the dfs_prevchan. + * dfs_curchan and dfs_prevchan are updated after start response by + * dfs_set_current_channel(). + * + * Return: true if AP requires CAC or can continue current CAC, else false. + */ +bool +utils_dfs_is_cac_required_on_dfs_curchan(struct wlan_objmgr_pdev *pdev, + bool *continue_current_cac); + /** utils_dfs_is_precac_done() - Check if precac has been done in chosen channel * @pdev: Pointer to DFS pdev object. * @wlan_chan: Pointer to wlan channel object that can be accessed by other @@ -746,4 +764,12 @@ QDF_STATUS utils_dfs_get_disable_radar_marking(struct wlan_objmgr_pdev *pdev, */ void utils_dfs_deliver_event(struct wlan_objmgr_pdev *pdev, uint16_t freq, enum WLAN_DFS_EVENTS event); + +/** + * utils_dfs_reset_dfs_prevchan() - Reset DFS previous channel structure. + * @pdev: Pointer to DFS pdev object. + * + * Return: None. + */ +void utils_dfs_reset_dfs_prevchan(struct wlan_objmgr_pdev *pdev); #endif /* _WLAN_DFS_UTILS_API_H_ */ diff --git a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c index 476c69f7557c..ef12031ffb52 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c @@ -255,6 +255,22 @@ bool utils_dfs_is_cac_required(struct wlan_objmgr_pdev *pdev, continue_current_cac); } +bool +utils_dfs_is_cac_required_on_dfs_curchan(struct wlan_objmgr_pdev *pdev, + bool *continue_current_cac) +{ + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) + return false; + + return dfs_is_cac_required(dfs, + dfs->dfs_curchan, + dfs->dfs_prevchan, + continue_current_cac); +} + QDF_STATUS utils_dfs_stacac_stop(struct wlan_objmgr_pdev *pdev) { struct wlan_dfs *dfs; @@ -1219,3 +1235,19 @@ void utils_dfs_deliver_event(struct wlan_objmgr_pdev *pdev, uint16_t freq, if (global_dfs_to_mlme.mlme_dfs_deliver_event) global_dfs_to_mlme.mlme_dfs_deliver_event(pdev, freq, event); } + +void utils_dfs_reset_dfs_prevchan(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_dfs *dfs; + + if (!tgt_dfs_is_pdev_5ghz(pdev)) + return; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is null"); + return; + } + + dfs_reset_dfs_prevchan(dfs); +} 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 07ff75b3e56d..214a2249439b 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 @@ -1279,6 +1279,8 @@ struct wlan_lmac_if_wifi_pos_rx_ops { * @dfs_allow_hw_pulses: Set or unset dfs_allow_hw_pulses which * allow or disallow HW pulses. * @dfs_is_hw_pulses_allowed: Check if HW pulses are allowed or not. + * @dfs_set_fw_adfs_support: Set the agile DFS FW support in DFS. + * @dfs_reset_dfs_prevchan: Reset DFS previous channel structure. */ struct wlan_lmac_if_dfs_rx_ops { QDF_STATUS (*dfs_get_radars)(struct wlan_objmgr_pdev *pdev); @@ -1398,6 +1400,7 @@ struct wlan_lmac_if_dfs_rx_ops { void (*dfs_set_fw_adfs_support)(struct wlan_objmgr_pdev *pdev, bool fw_adfs_support_160, bool fw_adfs_support_non_160); + void (*dfs_reset_dfs_prevchan)(struct wlan_objmgr_pdev *pdev); }; /** 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 72dbef41517c..a470cd6d772a 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 @@ -435,6 +435,8 @@ wlan_lmac_if_umac_dfs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) ucfg_dfs_is_hw_pulses_allowed; dfs_rx_ops->dfs_set_fw_adfs_support = tgt_dfs_set_fw_adfs_support; + dfs_rx_ops->dfs_reset_dfs_prevchan = + utils_dfs_reset_dfs_prevchan; register_precac_auto_chan_rx_ops(dfs_rx_ops);