diff --git a/umac/dfs/core/src/dfs.h b/umac/dfs/core/src/dfs.h index 967e209cd399..fcb9576329cc 100644 --- a/umac/dfs/core/src/dfs.h +++ b/umac/dfs/core/src/dfs.h @@ -882,6 +882,8 @@ struct dfs_event_log { #define RSSI_POSSIBLY_FALSE 50 #define SEARCH_FFT_REPORT_PEAK_MAG_THRSH 40 +#define MIN_DFS_SUBCHAN_BW 20 /* Minimum bandwidth of each subchannel. */ + /** * struct wlan_dfs - The main dfs structure. * @dfs_debug_mask: Current debug bitmask. @@ -1016,6 +1018,16 @@ struct dfs_event_log { * all the filtering data structures. For * example: dfs_bin5radars, dfs_filtertype, * etc. + * @dfs_nol_ie_bandwidth: Minimum Bandwidth of subchannels that + * are added to NOL. + * @dfs_nol_ie_startfreq: The centre frequency of the starting + * subchannel in the current channel list + * to be sent in NOL IE with RCSA. + * @dfs_nol_ie_bitmap: The bitmap of radar affected subchannels + * in the current channel list + * to be sent in NOL IE with RCSA. + * @dfs_is_rcsa_ie_sent To send or to not send RCSA IE. + * @dfs_is_nol_ie_sent To send or to not send NOL IE. */ struct wlan_dfs { uint32_t dfs_debug_mask; @@ -1150,6 +1162,11 @@ struct wlan_dfs { int32_t dfs_freq_offset; bool dfs_cac_aborted; qdf_spinlock_t dfs_data_struct_lock; + uint8_t dfs_nol_ie_bandwidth; + uint16_t dfs_nol_ie_startfreq; + uint8_t dfs_nol_ie_bitmap; + bool dfs_is_rcsa_ie_sent; + bool dfs_is_nol_ie_sent; }; /** @@ -2488,6 +2505,37 @@ void dfs_nol_free_list(struct wlan_dfs *dfs); */ int dfs_second_segment_radar_disable(struct wlan_dfs *dfs); +/** + * dfs_fetch_nol_ie_info() - Fill NOL information to be sent with RCSA. + * @dfs - Pointer to wlan_dfs structure. + * @nol_ie_bandwidth - Minimum subchannel bandwidth. + * @nol_ie_startfreq - Radar affected channel list's first subchannel's + * - centre frequency. + * @nol_ie_bitmap - NOL bitmap denoting affected subchannels. + */ +void dfs_fetch_nol_ie_info(struct wlan_dfs *dfs, uint8_t *nol_ie_bandwidth, + uint16_t *nol_ie_startfreq, uint8_t *nol_ie_bitmap); + +/** + * dfs_set_rcsa_flags() - Set flags that are required for sending RCSA and + * NOL IE. + * @dfs: Pointer to wlan_dfs structure. + * @is_rcsa_ie_sent: Boolean to check if RCSA IE should be sent or not. + * @is_nol_ie_sent: Boolean to check if NOL IE should be sent or not. + */ +void dfs_set_rcsa_flags(struct wlan_dfs *dfs, bool is_rcsa_ie_sent, + bool is_nol_ie_sent); + +/** + * dfs_get_rcsa_flags() - Get flags that are required for sending RCSA and + * NOL IE. + * @dfs: Pointer to wlan_dfs structure. + * @is_rcsa_ie_sent: Boolean to check if RCSA IE should be sent or not. + * @is_nol_ie_sent: Boolean to check if NOL IE should be sent or not. + */ +void dfs_get_rcsa_flags(struct wlan_dfs *dfs, bool *is_rcsa_ie_sent, + bool *is_nol_ie_sent); + /** * dfs_check_for_cac_start() - Check for DFS CAC start conditions. * @dfs: Pointer to wlan_dfs structure. 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 31ae9cc0056f..a8ccf0f52e37 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 @@ -562,6 +562,80 @@ static inline void dfs_reset_bangradar(struct wlan_dfs *dfs) dfs->dfs_second_segment_bangradar = 0; } +/* dfs_prepare_nol_ie_bitmap: Create a Bitmap from the radar found subchannels + * to be sent along with RCSA. + * + * Get the subchannels affected by radar and all the channels in current + * channel. + * start from the first bit pointing to first subchannel in the current + * channel, set as 1 if radar affected, 0 if unaffected. + * If the number of subchannels increases (future cases), the bitmap should + * be an array of required size. + * + * Please change macro "MIN_DFS_SUBCHAN_BW" when NOL logic changes. + */ +static void dfs_prepare_nol_ie_bitmap(struct wlan_dfs *dfs, + struct radar_found_info *radar_found, + uint8_t *in_sub_channels) +{ + uint8_t cur_subchans[NUM_CHANNELS_160MHZ]; + uint8_t n_cur_subchans; + uint8_t i; + uint8_t j; + uint8_t bits = 0x01; + + n_cur_subchans = dfs_get_bonding_channels(dfs, dfs->dfs_curchan, + radar_found->segment_id, + cur_subchans); + dfs->dfs_nol_ie_bandwidth = MIN_DFS_SUBCHAN_BW; + dfs->dfs_nol_ie_startfreq = + (uint16_t)utils_dfs_chan_to_freq(cur_subchans[0]); + + /* To fill the bitmap, only one loop is required + * since both the arrays (current channel's subchannel list + * and radar affected subchannels list) are sorted. + + * We're doing a sorted search, please change it to O(n^2) + * if the arrays ever become non sorted. + */ + for (i = 0, j = 0; i < n_cur_subchans; i++) { + if (cur_subchans[i] == in_sub_channels[j]) { + j++; + dfs->dfs_nol_ie_bitmap |= bits; + } + bits <<= 1; + } +} + +void dfs_fetch_nol_ie_info(struct wlan_dfs *dfs, + uint8_t *nol_ie_bandwidth, + uint16_t *nol_ie_startfreq, + uint8_t *nol_ie_bitmap) +{ + if (nol_ie_bandwidth) + *nol_ie_bandwidth = dfs->dfs_nol_ie_bandwidth; + if (nol_ie_startfreq) + *nol_ie_startfreq = dfs->dfs_nol_ie_startfreq; + if (nol_ie_bitmap) + *nol_ie_bitmap = dfs->dfs_nol_ie_bitmap; +} + +void dfs_get_rcsa_flags(struct wlan_dfs *dfs, bool *is_rcsa_ie_sent, + bool *is_nol_ie_sent) +{ + if (is_rcsa_ie_sent) + *is_rcsa_ie_sent = dfs->dfs_is_rcsa_ie_sent; + if (is_nol_ie_sent) + *is_nol_ie_sent = dfs->dfs_is_nol_ie_sent; +} + +void dfs_set_rcsa_flags(struct wlan_dfs *dfs, bool is_rcsa_ie_sent, + bool is_nol_ie_sent) +{ + dfs->dfs_is_rcsa_ie_sent = is_rcsa_ie_sent; + dfs->dfs_is_nol_ie_sent = is_nol_ie_sent; +} + QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, struct radar_found_info *radar_found) { @@ -660,12 +734,12 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, "found_on_second=%d is_pre=%d", dfs->is_radar_found_on_secondary_seg, dfs_is_precac_timer_running(dfs)); - /* * Even if radar found on primary, we need to move the channel * from precac-required-list and precac-done-list to * precac-nol-list. */ + if (dfs->dfs_precac_enable) dfs_mark_precac_dfs(dfs, dfs->is_radar_found_on_secondary_seg); @@ -676,6 +750,24 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, __func__, __LINE__); dfs_mark_etsi_precac_dfs(dfs, channels, num_channels); } + /* + * This calls into the umac DFS code, which sets the umac + * related radar flags and begins the channel change + * machinery. + + * Even during precac, this API is called, but with a flag + * saying not to send RCSA, but only the radar affected subchannel + * information. + */ + dfs->dfs_is_nol_ie_sent = false; + (dfs->is_radar_during_precac) ? + (dfs->dfs_is_rcsa_ie_sent = false) : + (dfs->dfs_is_rcsa_ie_sent = true); + if (dfs->dfs_use_nol_subchannel_marking) { + dfs_prepare_nol_ie_bitmap(dfs, radar_found, channels); + dfs->dfs_is_nol_ie_sent = true; + } + dfs_mlme_start_rcsa(dfs->dfs_pdev_obj, &wait_for_csa); if (!dfs->dfs_is_offload_enabled && dfs->is_radar_found_on_secondary_seg) { @@ -689,15 +781,11 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, } /* - * This calls into the umac DFS code, which sets the umac - * related radar flags and begins the channel change - * machinery. * XXX TODO: the umac NOL code isn't used, but * WLAN_CHAN_DFS_RADAR still gets set. Since the umac * NOL code isn't used, that flag is never cleared. This * needs to be fixed. See EV 105776. */ - dfs_mlme_start_rcsa(dfs->dfs_pdev_obj, &wait_for_csa); if (wait_for_csa) return QDF_STATUS_SUCCESS; diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h index b24eb07426ce..022d8c9b427e 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h @@ -315,6 +315,44 @@ QDF_STATUS utils_dfs_nol_update(struct wlan_objmgr_pdev *pdev); QDF_STATUS utils_dfs_second_segment_radar_disable( struct wlan_objmgr_pdev *pdev); +/** + * utils_dfs_fetch_nol_ie_info() - Fills the arguments with NOL information + * needed for sending RCSA. + * pdev: Pointer to DFS pdev object. + * nol_ie_bandwidth: Minimum DFS subchannel Bandwidth. + * nol_ie_startfreq: Radar affected channel list start subchannel's centre + * frequency. + * nol_ie_bitmap: Bitmap of radar affected subchannels. + */ +QDF_STATUS utils_dfs_fetch_nol_ie_info(struct wlan_objmgr_pdev *pdev, + uint8_t *nol_ie_bandwidth, + uint16_t *nol_ie_startfreq, + uint8_t *nol_ie_bitmap); + +/** + * utils_dfs_set_rcsa_flags() - Set flags that are required for sending + * RCSA and NOL IE. + * pdev: Pointer to DFS pdev object. + * is_rcsa_ie_sent: Boolean to check if RCSA IE should be sent or not. + * is_nol_ie_sent: Boolean to check if NOL IE should be sent or not. + */ + +QDF_STATUS utils_dfs_set_rcsa_flags(struct wlan_objmgr_pdev *pdev, + bool is_rcsa_ie_sent, + bool is_nol_ie_sent); + +/** + * utils_dfs_get_rcsa_flags() - Get flags that are required for sending + * RCSA and NOL IE. + * pdev: Pointer to DFS pdev object. + * is_rcsa_ie_sent: Boolean to check if RCSA IE should be sent or not. + * is_nol_ie_sent: Boolean to check if NOL IE should be sent or not. + */ + +QDF_STATUS utils_dfs_get_rcsa_flags(struct wlan_objmgr_pdev *pdev, + bool *is_rcsa_ie_sent, + bool *is_nol_ie_sent); + /** * utils_dfs_set_cac_timer_running() - Sets the cac timer running. * @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 1328ac36ec7c..b186d9f21336 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c @@ -368,6 +368,53 @@ QDF_STATUS utils_dfs_second_segment_radar_disable(struct wlan_objmgr_pdev *pdev) return QDF_STATUS_SUCCESS; } +QDF_STATUS utils_dfs_fetch_nol_ie_info(struct wlan_objmgr_pdev *pdev, + uint8_t *nol_ie_bandwidth, + uint16_t *nol_ie_startfreq, + uint8_t *nol_ie_bitmap) +{ + struct wlan_dfs *dfs; + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) + return QDF_STATUS_E_FAILURE; + + dfs_fetch_nol_ie_info(dfs, nol_ie_bandwidth, nol_ie_startfreq, + nol_ie_bitmap); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS utils_dfs_set_rcsa_flags(struct wlan_objmgr_pdev *pdev, + bool is_rcsa_ie_sent, + bool is_nol_ie_sent) +{ + struct wlan_dfs *dfs; + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) + return QDF_STATUS_E_FAILURE; + + dfs_set_rcsa_flags(dfs, is_rcsa_ie_sent, is_nol_ie_sent); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS utils_dfs_get_rcsa_flags(struct wlan_objmgr_pdev *pdev, + bool *is_rcsa_ie_sent, + bool *is_nol_ie_sent) +{ + struct wlan_dfs *dfs; + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) + return QDF_STATUS_E_FAILURE; + + dfs_get_rcsa_flags(dfs, is_rcsa_ie_sent, is_nol_ie_sent); + + return QDF_STATUS_SUCCESS; +} + QDF_STATUS utils_dfs_set_cac_timer_running(struct wlan_objmgr_pdev *pdev, int val) {