From 07035aaed855ebce178cf69f17077ebbdcd2b6ea Mon Sep 17 00:00:00 2001 From: Vignesh Mohan Date: Tue, 30 Oct 2018 14:19:44 +0530 Subject: [PATCH] qcacmn: Enable RCSA with subchannel information Calculate the bitmap of subchannels that are affected by radar and store in dfs structure along with flags Algorithm: 1). Given the radar affected subchannels list, create a NOL bitmap, where 1 - Radar hit on Subchannel. 0 - Subchannel not affected. 2). Along with the NOL bitmap, send the Minimum Bandwidth for each subchannel and the Channel list's starting channel's centre frequency. Example: Mode : 100HT80, if radar affected subchannels are 100, 104 and 108. NOL bandwidth: 20. NOL start frequency: 5500. NOL Bitmap: 11100000. 3). During precac (precac timer running), if radar hits at secondary segment, the umac code that sends rcsa is still called, but add a new flag to not send rcsa, and in rootAP, channel change is not triggered, only NOL is updated. Add APIs that can be called from mlme to fetch the NOL and IE flags information from DFS structure during RCSA framing. If subchannel marking is disabled, the new NOL bitmap has no meaning and is hence, not sent. CRs-Fixed: 2328377 Change-Id: I3114ff5ca2704c316c9dc83220740fac9a6a00a1 --- umac/dfs/core/src/dfs.h | 48 +++++++++ .../src/misc/dfs_process_radar_found_ind.c | 98 ++++++++++++++++++- umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h | 38 +++++++ umac/dfs/dispatcher/src/wlan_dfs_utils_api.c | 47 +++++++++ 4 files changed, 226 insertions(+), 5 deletions(-) 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) {