diff --git a/umac/dfs/core/src/dfs.h b/umac/dfs/core/src/dfs.h index 1d047c0790..3f6d11f453 100644 --- a/umac/dfs/core/src/dfs.h +++ b/umac/dfs/core/src/dfs.h @@ -1143,6 +1143,10 @@ struct dfs_rcac_params { * @dfs_chan_postnol_mode: Phymode the AP switches to, post NOL. * @dfs_chan_postnol_cfreq2: Secondary center frequency the AP * switches to, post NOL. + * @dfs_channel_state_array: Stores the channel states like CAC STARTED, + * CAC REQUIRED, CAC COMPLETED, NOL, + * PRECAC STARTED, PRECAC COMPLETED etc. of + * all the DFS channels. */ struct wlan_dfs { uint32_t dfs_debug_mask; @@ -1322,6 +1326,9 @@ struct wlan_dfs { enum phy_ch_width dfs_chan_postnol_mode; qdf_freq_t dfs_chan_postnol_cfreq2; #endif +#if defined(WLAN_DISP_CHAN_INFO) + enum channel_dfs_state dfs_channel_state_array[NUM_DFS_CHANS]; +#endif /* WLAN_DISP_CHAN_INFO */ }; #if defined(QCA_SUPPORT_AGILE_DFS) || defined(ATH_SUPPORT_ZERO_CAC_DFS) diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h b/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h index 4654e0f4e1..edeb223809 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h @@ -280,20 +280,26 @@ struct wlan_dfs_phyerr_param { /** * enum WLAN_DFS_EVENTS - DFS Events that will be sent to userspace * @WLAN_EV_RADAR_DETECTED: Radar is detected + * @WLAN_EV_CAC_RESET: CAC started or CAC completed status is reset * @WLAN_EV_CAC_STARTED: CAC timer has started * @WLAN_EV_CAC_COMPLETED: CAC timer completed * @WLAN_EV_NOL_STARTED: NOL started * @WLAN_EV_NOL_FINISHED: NOL Completed + * @WLAN_EV_PCAC_STARTED: PreCAC Started + * @WLAN_EV_PCAC_COMPLETED: PreCAC Completed * * DFS events such as radar detected, CAC started, * CAC completed, NOL started, NOL finished */ enum WLAN_DFS_EVENTS { WLAN_EV_RADAR_DETECTED, + WLAN_EV_CAC_RESET, WLAN_EV_CAC_STARTED, WLAN_EV_CAC_COMPLETED, WLAN_EV_NOL_STARTED, WLAN_EV_NOL_FINISHED, + WLAN_EV_PCAC_STARTED, + WLAN_EV_PCAC_COMPLETED, }; #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(WLAN_DFS_SYNTHETIC_RADAR) diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_public_struct.h b/umac/dfs/dispatcher/inc/wlan_dfs_public_struct.h index fb524159ff..b30933d317 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_public_struct.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_public_struct.h @@ -23,7 +23,7 @@ #ifndef __WLAN_DFS_PUBLIC_STRUCT_H_ #define __WLAN_DFS_PUBLIC_STRUCT_H_ - +#include /* TODO: This structure has many redundant variables, needs cleanup */ /** * struct radar_found_info - radar found info @@ -164,4 +164,35 @@ struct dfs_agile_cac_params { uint32_t max_precac_timeout; enum adfs_ocac_mode ocac_mode; }; + +/* The first DFS channel number is 52 and the last DFS channel number is 161(in + * case of ETSI EN302502). So, the array size is taken as (161 - 52) / 4 ~= 30. + */ +#define NUM_DFS_CHANS 30 + +/** + * enum channel_dfs_state - DFS channel states. + * @CH_DFS_S_INVALID: The DFS state for invalid channel numbers that are not + * part of the radio's channel list. + * @CH_DFS_S_CAC_REQ: Indicates that the CAC/Off-channel CAC has to performed + * before Tx on the DFS channel. + * @CH_DFS_S_CAC_STARTED: Indicates that the CAC has been started for the DFS + * channel. + * @CH_DFS_S_CAC_COMPLETED: Indicates that the CAC has been completed for the + * DFS channel. + * @CH_DFS_S_NOL: Indicates that the DFS channel is in NOL. + * @CH_DFS_S_PRECAC_STARTED: Indicates that the PreCAC has been started for the + * DFS channel. + * @CH_DFS_S_PRECAC_COMPLETED: Indicates that the PreCAC has been completed for + * the DFS channel. + */ +enum channel_dfs_state { + CH_DFS_S_INVALID, + CH_DFS_S_CAC_REQ, + CH_DFS_S_CAC_STARTED, + CH_DFS_S_CAC_COMPLETED, + CH_DFS_S_NOL, + CH_DFS_S_PRECAC_STARTED, + CH_DFS_S_PRECAC_COMPLETED, +}; #endif diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h index e89e188b15..c86fe301bb 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h @@ -1051,4 +1051,60 @@ utils_dfs_precac_status_for_channel(struct wlan_objmgr_pdev *pdev, } #endif +#if defined(WLAN_DISP_CHAN_INFO) +/** + * utils_dfs_get_chan_dfs_state() - Get the channel state array of the channels + * in a radio. + * @pdev: Pointer to the pdev. + * @dfs_ch_s: Output channel state array of the dfs channels in the radio. + * + * Return: QDF_STATUS. + */ +QDF_STATUS utils_dfs_get_chan_dfs_state(struct wlan_objmgr_pdev *pdev, + enum channel_dfs_state *dfs_ch_s); + +/** + * utils_dfs_update_chan_state_array() - Update the channel state of the dfs + * channel indicated by the frequency. The dfs event is converted to + * appropriate dfs state. + * @pdev: Pointer to the pdev. + * @freq: Input frequency. + * @event: Input dfs event. + * + * Return: QDF_STATUS. + */ +QDF_STATUS utils_dfs_update_chan_state_array(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + enum WLAN_DFS_EVENTS event); + +/** + * dfs_init_chan_state_array() - Initialize the dfs channel state array. + * + * @pdev: Pointer to the pdev. + * + * Return: QDF_STATUS. + */ +QDF_STATUS dfs_init_chan_state_array(struct wlan_objmgr_pdev *pdev); +#else +static inline +QDF_STATUS utils_dfs_get_chan_dfs_state(struct wlan_objmgr_pdev *pdev, + enum channel_dfs_state *dfs_ch_s) +{ + return QDF_STATUS_E_NOSUPPORT; +} + +static inline +QDF_STATUS utils_dfs_update_chan_state_array(struct wlan_objmgr_pdev *pdev, + uint16_t freq, + enum WLAN_DFS_EVENTS event) +{ + return QDF_STATUS_E_NOSUPPORT; +} + +static inline +QDF_STATUS dfs_init_chan_state_array(struct wlan_objmgr_pdev *pdev) +{ + return QDF_STATUS_E_NOSUPPORT; +} +#endif /* WLAN_DISP_CHAN_INFO */ #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 03b5ea5825..9dff3d3ab1 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c @@ -55,6 +55,7 @@ QDF_STATUS utils_dfs_reset(struct wlan_objmgr_pdev *pdev) dfs_reset(dfs); dfs_nol_update(dfs); dfs_reset_precaclists(dfs); + dfs_init_chan_state_array(pdev); return QDF_STATUS_SUCCESS; } @@ -1733,3 +1734,161 @@ utils_dfs_precac_status_for_channel(struct wlan_objmgr_pdev *pdev, return dfs_precac_status_for_channel(dfs, &chan); } #endif + +#if defined(WLAN_DISP_CHAN_INFO) +#define FIRST_DFS_CHAN_NUM 52 +#define CHAN_NUM_SPACING 4 +#define INVALID_INDEX (-1) +#define IS_CHAN_DFS(_flags) ((_flags) & REGULATORY_CHAN_RADAR) +/** + * utils_dfs_convert_freq_to_index() - Converts a DFS channel frequency + * to the DFS channel state array index. The input frequency should be a DFS + * channel frequency and this check should be done in the caller. + * @freq: Input DFS channel frequency. + * @index: Output DFS channel state array index. + * + * Return: QDF_STATUS. + */ +static void utils_dfs_convert_freq_to_index(qdf_freq_t freq, int8_t *index) +{ + uint16_t chan_num; + int8_t tmp_index; + + chan_num = (freq - WLAN_5_GHZ_BASE_FREQ) / WLAN_CHAN_SPACING_5MHZ; + tmp_index = (chan_num - FIRST_DFS_CHAN_NUM) / CHAN_NUM_SPACING; + *index = ((tmp_index >= 0) && (tmp_index < NUM_DFS_CHANS)) ? + tmp_index : INVALID_INDEX; +} + +/** + * utils_dfs_update_chan_state_array_element() - Update the per dfs channel + * state array element indexed by the frequency with the new state. + * + * @freq: Input DFS Channel frequency which will converted to channel state + * array index. + * @state: Input DFS state with which the value indexed by frequency will be + * updated with. + * + * Return: void. + */ +static QDF_STATUS +utils_dfs_update_chan_state_array_element(struct wlan_dfs *dfs, + qdf_freq_t freq, + enum channel_dfs_state state) +{ + int8_t index; + + if (state == CH_DFS_S_INVALID) + return QDF_STATUS_E_INVAL; + + utils_dfs_convert_freq_to_index(freq, &index); + + if (index == INVALID_INDEX) + return QDF_STATUS_E_INVAL; + + dfs->dfs_channel_state_array[index] = state; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS dfs_init_chan_state_array(struct wlan_objmgr_pdev *pdev) +{ + struct regulatory_channel *cur_chan_list; + struct wlan_dfs *dfs; + int i; + + dfs = wlan_pdev_get_dfs_obj(pdev); + + if (!dfs) + return QDF_STATUS_E_FAILURE; + + cur_chan_list = qdf_mem_malloc(NUM_CHANNELS * + sizeof(struct regulatory_channel)); + + if (!cur_chan_list) + return QDF_STATUS_E_NOMEM; + + if (wlan_reg_get_current_chan_list( + pdev, cur_chan_list) != QDF_STATUS_SUCCESS) { + dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, + "failed to get curr channel list"); + return QDF_STATUS_E_FAILURE; + } + + for (i = 0; i < NUM_CHANNELS; i++) { + qdf_freq_t freq = cur_chan_list[i].center_freq; + + if (!IS_CHAN_DFS(cur_chan_list[i].chan_flags)) + continue; + + utils_dfs_update_chan_state_array_element(dfs, + freq, + CH_DFS_S_CAC_REQ); + } + + qdf_mem_free(cur_chan_list); + qdf_err("channel state array initialized"); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS utils_dfs_get_chan_dfs_state(struct wlan_objmgr_pdev *pdev, + enum channel_dfs_state *dfs_ch_s) +{ + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + + if (!dfs) + return QDF_STATUS_E_FAILURE; + + qdf_mem_copy(dfs_ch_s, + dfs->dfs_channel_state_array, + sizeof(dfs->dfs_channel_state_array)); + + return QDF_STATUS_SUCCESS; +} + +qdf_export_symbol(utils_dfs_get_chan_dfs_state); + +/** + * convert_event_to_state() - Coverts the dfs events WLAN_DFS_EVENTS to dfs + * states channel_dfs_state. + * @event: Input DFS event. + * @state: Output DFS state. + * + * Return: void. + */ +static +void convert_event_to_state(enum WLAN_DFS_EVENTS event, + enum channel_dfs_state *state) +{ + static const + enum channel_dfs_state ev_to_state[WLAN_EV_PCAC_COMPLETED + 1] = { + [WLAN_EV_RADAR_DETECTED] = CH_DFS_S_INVALID, + [WLAN_EV_CAC_RESET] = CH_DFS_S_CAC_REQ, + [WLAN_EV_CAC_STARTED] = CH_DFS_S_CAC_STARTED, + [WLAN_EV_CAC_COMPLETED] = CH_DFS_S_CAC_COMPLETED, + [WLAN_EV_NOL_STARTED] = CH_DFS_S_NOL, + [WLAN_EV_NOL_FINISHED] = CH_DFS_S_CAC_REQ, + [WLAN_EV_PCAC_STARTED] = CH_DFS_S_PRECAC_STARTED, + [WLAN_EV_PCAC_COMPLETED] = CH_DFS_S_PRECAC_COMPLETED, + }; + + *state = ev_to_state[event]; +} + +QDF_STATUS utils_dfs_update_chan_state_array(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + enum WLAN_DFS_EVENTS event) +{ + enum channel_dfs_state state; + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) + return QDF_STATUS_E_FAILURE; + + convert_event_to_state(event, &state); + return utils_dfs_update_chan_state_array_element(dfs, freq, state); +} +#endif /* WLAN_DISP_CHAN_INFO */