From cbc53dd023e545ef7bfa45cd793f4148cbf4fa12 Mon Sep 17 00:00:00 2001 From: Shaakir Mohamed Date: Tue, 10 Jul 2018 14:05:39 -0700 Subject: [PATCH] qcacmn: Add support for reduced BW-Agile DFS When the beaconing channel is not affected by radar, reduce bandwidth of the AP while retaining the beaconing (control) channel. Since all subchannels were in ISM there is no need to perform CAC. Random channel selection is run if primary beaconing channel is affected by radar, wherein CAC will be run for new primary and secondary. Change-Id: I3c141a02449361e2290086f4c15f7b3eb08c6115 CRs-Fixed: 2284350 --- umac/dfs/core/src/dfs.h | 16 ++++- .../core/src/dfs_process_radar_found_ind.h | 2 + umac/dfs/core/src/filtering/dfs_bindetects.c | 9 +++ umac/dfs/core/src/filtering/dfs_fcc_bin5.c | 7 ++- .../src/filtering/dfs_process_radarevent.c | 11 ++++ umac/dfs/core/src/filtering/dfs_staggered.c | 6 +- umac/dfs/core/src/misc/dfs.c | 35 +++++++++++ .../src/misc/dfs_process_radar_found_ind.c | 12 ++++ umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h | 19 +++++- umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h | 18 ++++++ umac/dfs/dispatcher/src/wlan_dfs_utils_api.c | 60 +++++++++++++++++++ 11 files changed, 189 insertions(+), 6 deletions(-) diff --git a/umac/dfs/core/src/dfs.h b/umac/dfs/core/src/dfs.h index 9f2fb7aa5d9f..925c0026b469 100644 --- a/umac/dfs/core/src/dfs.h +++ b/umac/dfs/core/src/dfs.h @@ -966,9 +966,15 @@ struct dfs_event_log { * @dfs_no_res_from_fw: Indicates no response from fw. * @dfs_spoof_check_failed: Indicates if the spoof check has failed. * @dfs_spoof_test_done: Indicates if the sppof test is done. - * @dfs_seg_id: Segment ID of the radar hit channel. * @dfs_status_timeout_override: Used to change the timeout value of * dfs_host_wait_timer. + * @dfs_min_sidx: Minimum sidx of the received radar pulses. + * @dfs_max_sidx: Maximum sidx of the received radar pulses. + * @dfs_seg_id: Segment ID of the radar hit channel. + * @dfs_is_chirp: Radar Chirp in pulse present or not. + * @dfs_bw_reduced: DFS bandwidth reduced channel bit. + * @dfs_freq_offset: Frequency offset where radar was found. + * @dfs_enhanced_bangradar: DFS enhance bagradar bit for Full offload. */ struct wlan_dfs { uint32_t dfs_debug_mask; @@ -1087,10 +1093,16 @@ struct wlan_dfs { dfs_no_res_from_fw:1, dfs_spoof_check_failed:1, dfs_spoof_test_done:1; - uint8_t dfs_seg_id; struct dfs_channel dfs_radar_found_chan; int dfs_status_timeout_override; #endif + uint32_t dfs_min_sidx; + uint32_t dfs_max_sidx; + uint8_t dfs_seg_id; + uint8_t dfs_is_chirp; + uint8_t dfs_bw_reduced; + int32_t dfs_freq_offset; + uint8_t dfs_enhanced_bangradar; }; /** diff --git a/umac/dfs/core/src/dfs_process_radar_found_ind.h b/umac/dfs/core/src/dfs_process_radar_found_ind.h index b6ee1f48b3ca..26f739a27ac2 100644 --- a/umac/dfs/core/src/dfs_process_radar_found_ind.h +++ b/umac/dfs/core/src/dfs_process_radar_found_ind.h @@ -58,6 +58,8 @@ /* Frequency offset to sidx */ #define DFS_FREQ_OFFSET_TO_SIDX(_f) ((32 * (_f)) / 10) +/* Sidx to frequency offset */ +#define DFS_SIDX_TO_FREQ_OFFSET(_s) ((10 * (_s)) / 32) /* sidx offset boundary */ #define DFS_BOUNDARY_SIDX 32 /* freq offset for chirp */ diff --git a/umac/dfs/core/src/filtering/dfs_bindetects.c b/umac/dfs/core/src/filtering/dfs_bindetects.c index 13c500aba0f5..67548ad0a121 100644 --- a/umac/dfs/core/src/filtering/dfs_bindetects.c +++ b/umac/dfs/core/src/filtering/dfs_bindetects.c @@ -24,6 +24,7 @@ */ #include "../dfs.h" +#include "../dfs_process_radar_found_ind.h" /** * dfs_find_first_index_within_window() - Find first index within window @@ -169,8 +170,16 @@ static inline int dfs_pulses_within_window( refpri, index, dur, &numpulses)) break; } + if (dfs->dfs_min_sidx > pl->pl_elems[*index].p_sidx) + dfs->dfs_min_sidx = pl->pl_elems[*index].p_sidx; + + if (dfs->dfs_max_sidx < pl->pl_elems[*index].p_sidx) + dfs->dfs_max_sidx = pl->pl_elems[*index].p_sidx; } + dfs->dfs_freq_offset = + DFS_SIDX_TO_FREQ_OFFSET((dfs->dfs_min_sidx + + dfs->dfs_min_sidx) / 2); return numpulses; } diff --git a/umac/dfs/core/src/filtering/dfs_fcc_bin5.c b/umac/dfs/core/src/filtering/dfs_fcc_bin5.c index 347799cefc51..14b319a7ad9d 100644 --- a/umac/dfs/core/src/filtering/dfs_fcc_bin5.c +++ b/umac/dfs/core/src/filtering/dfs_fcc_bin5.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2016-2018 The Linux Foundation. All rights reserved. * Copyright (c) 2002-2010, Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any @@ -99,6 +99,11 @@ int dfs_bin5_addpulse(struct wlan_dfs *dfs, } } + if (dfs->dfs_min_sidx > re->re_sidx) + dfs->dfs_min_sidx = re->re_sidx; + + if (dfs->dfs_max_sidx < re->re_sidx) + dfs->dfs_max_sidx = re->re_sidx; /* Circular buffer of size 2^n. */ index = (br->br_lastelem + 1) & DFS_MAX_B5_MASK; br->br_lastelem = index; diff --git a/umac/dfs/core/src/filtering/dfs_process_radarevent.c b/umac/dfs/core/src/filtering/dfs_process_radarevent.c index 89c4f1f89f18..938b00486208 100644 --- a/umac/dfs/core/src/filtering/dfs_process_radarevent.c +++ b/umac/dfs/core/src/filtering/dfs_process_radarevent.c @@ -292,7 +292,11 @@ static int dfs_confirm_radar(struct wlan_dfs *dfs, rf->rf_threshold); return 0; } + dfs_debug(dfs, WLAN_DEBUG_DFS_FALSE_DET, "%s : dl->dl_min_sidx: %d , dl->dl_max_sidx :%d", + __func__, dl->dl_min_sidx, dl->dl_max_sidx); + dfs->dfs_freq_offset = DFS_SIDX_TO_FREQ_OFFSET((dl->dl_min_sidx + + dl->dl_max_sidx) / 2); return 1; } @@ -1238,9 +1242,16 @@ static inline int dfs_process_each_radarevent( dfs_conditional_clear_delaylines(dfs, diff_ts, this_ts, re); found = 0; + if (events_processed == 1) { + dfs->dfs_min_sidx = (re).re_sidx; + dfs->dfs_max_sidx = (re).re_sidx; + } + dfs_check_if_bin5(dfs, &re, this_ts, diff_ts, &found); if (found) { *retval |= found; + dfs->dfs_freq_offset = DFS_SIDX_TO_FREQ_OFFSET( + (dfs->dfs_min_sidx + dfs->dfs_max_sidx) / 2); return 1; } diff --git a/umac/dfs/core/src/filtering/dfs_staggered.c b/umac/dfs/core/src/filtering/dfs_staggered.c index 1be33310ddde..b0d08a69a5d6 100644 --- a/umac/dfs/core/src/filtering/dfs_staggered.c +++ b/umac/dfs/core/src/filtering/dfs_staggered.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2016-2018 The Linux Foundation. All rights reserved. * Copyright (c) 2002-2010, Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any @@ -24,6 +24,7 @@ */ #include "../dfs.h" +#include "../dfs_process_radar_found_ind.h" /** * dfs_is_pri_multiple() - Is PRI is multiple. @@ -144,6 +145,9 @@ int dfs_staggered_check(struct wlan_dfs *dfs, struct dfs_filter *rf, } } + dfs->dfs_freq_offset = DFS_SIDX_TO_FREQ_OFFSET( + (dl->dl_min_sidx + dl->dl_max_sidx) / 2); + for (n = 0; n < dl->dl_numelems; n++) { delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; refdur = dl->dl_elems[delayindex].de_time; diff --git a/umac/dfs/core/src/misc/dfs.c b/umac/dfs/core/src/misc/dfs.c index b6f9cc1a9eb7..5445ce466d9b 100644 --- a/umac/dfs/core/src/misc/dfs.c +++ b/umac/dfs/core/src/misc/dfs.c @@ -121,6 +121,7 @@ int dfs_attach(struct wlan_dfs *dfs) dfs_zero_cac_attach(dfs); dfs_etsi_precac_attach(dfs); dfs_nol_attach(dfs); + dfs->dfs_use_nol_subchannel_marking = 1; /* * Init of timer ,dfs_testtimer_task is required by both partial @@ -207,6 +208,7 @@ int dfs_control(struct wlan_dfs *dfs, { struct wlan_dfs_phyerr_param peout; struct dfs_ioctl_params *dfsparams; + struct dfs_bangradar_enh_params *bangradar_enh_params; int error = 0; uint32_t val = 0; struct dfsreq_nolinfo *nol; @@ -260,6 +262,39 @@ int dfs_control(struct wlan_dfs *dfs, dfsparams->dfs_maxlen)) error = -EINVAL; break; + case DFS_BANGRADAR_ENH: + if (insize < sizeof(struct dfs_bangradar_enh_params) || + !indata) { + dfs_debug(dfs, WLAN_DEBUG_DFS1, + "insize = %d, expected = %zu bytes, indata = %pK", + insize, + sizeof(struct dfs_bangradar_enh_params), + indata); + error = -EINVAL; + break; + } + bangradar_enh_params = + (struct dfs_bangradar_enh_params *)indata; + if (bangradar_enh_params) { + dfs->dfs_seg_id = bangradar_enh_params->seg_id; + dfs->dfs_is_chirp = bangradar_enh_params->is_chirp; + dfs->dfs_freq_offset = + bangradar_enh_params->freq_offset; + dfs->dfs_enhanced_bangradar = 1; + + if (dfs->dfs_is_offload_enabled) { + error = dfs_fill_emulate_bang_radar_test + (dfs, SEG_ID_PRIMARY, + &dfs_unit_test); + } else { + dfs->dfs_bangradar = 1; + error = dfs_start_host_based_bangradar(dfs); + } + } else { + dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "bangradar_enh_params is NULL"); + } + + break; case DFS_GET_THRESH: if (!outdata || !outsize || *outsize < sizeof(struct dfs_ioctl_params)) { 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 1fdc87fbac65..1f523140c920 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 @@ -479,6 +479,18 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, return QDF_STATUS_SUCCESS; } + /* For Full Offload, FW sends segment id,freq_offset and + * is chirp information and gets assigned when there is radar detect. + * In case of radartool bangradar enhanced command and real radar + * for FO and PO, we assign these information here. + */ + if (!dfs->dfs_is_offload_enabled || dfs->dfs_enhanced_bangradar) { + radar_found->segment_id = dfs->dfs_seg_id; + radar_found->freq_offset = dfs->dfs_freq_offset; + radar_found->is_chirp = dfs->dfs_is_chirp; + dfs->dfs_enhanced_bangradar = 0; + } + if (dfs->dfs_use_nol_subchannel_marking) num_channels = dfs_find_radar_affected_subchans(dfs, radar_found, diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h b/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h index 978dd2df9c52..87961ee88e17 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2016-2018 The Linux Foundation. All rights reserved. * Copyright (c) 2010, Atheros Communications Inc. * All Rights Reserved. * @@ -51,13 +51,14 @@ #define DFS_SECOND_SEGMENT_BANGRADAR 23 #define DFS_SHOW_PRECAC_LISTS 24 #define DFS_RESET_PRECAC_LISTS 25 +#define DFS_BANGRADAR_ENH 26 /* * Spectral IOCTLs use DFS_LAST_IOCTL as the base. * This must always be the last IOCTL in DFS and have * the highest value. */ -#define DFS_LAST_IOCTL 26 +#define DFS_LAST_IOCTL 27 #ifndef DFS_CHAN_MAX #define DFS_CHAN_MAX 1023 @@ -119,6 +120,17 @@ struct dfs_ioctl_params { int32_t dfs_maxlen; }; +/** + * struct dfs_bangradar_enh_params - DFS enhanced bangradr params. + * @seg_id: Segment ID information. + * @is_chirp: Chirp radar or not. + * @freq_offset: Frequency offset at which radar was found. + */ +struct dfs_bangradar_enh_params { + uint8_t seg_id; + uint8_t is_chirp; + int32_t freq_offset; +}; #define DFS_IOCTL_PARAM_NOVAL 65535 #define DFS_IOCTL_PARAM_ENABLE 0x8000 @@ -144,6 +156,9 @@ struct dfs_ioctl_params { /* Flag to exclude all 2.4GHz channels */ #define DFS_RANDOM_CH_FLAG_NO_2GHZ_CH 0x0040 /* 0000 0000 0100 0000 */ +/* Flag to enable Reduced BW Agile DFS */ +#define DFS_RANDOM_CH_FLAG_ENABLE_REDUCED_BW 0x0080 /* 0000 0000 1000 0000 */ + /** * struct wlan_dfs_caps - DFS capability structure. * @wlan_dfs_ext_chan_ok: Can radar be detected on the extension chan? diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h index 3a00f5c110c4..ccbf754fccc9 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h @@ -403,6 +403,24 @@ QDF_STATUS utils_dfs_get_random_channel(struct wlan_objmgr_pdev *pdev, uint32_t *hw_mode, uint8_t *target_chan, struct dfs_acs_info *acs_info); +/** + * utils_dfs_bw_reduced_channel() - Get BW reduced channel. + * @pdev: Pointer to DFS pdev object. + * @flags: Reduced bandwidth channel flags. + * @ch_params: current channel params. + * @hw_mode: current operating mode. + * @target_chan: Pointer to target_chan. + * + * wrapper function for get bw_reduced_channel. this + * function called from outside of dfs component. + * + * Return: QDF_STATUS + */ +QDF_STATUS utils_dfs_bw_reduced_channel(struct wlan_objmgr_pdev *pdev, + uint16_t flags, + struct ch_params *ch_params, + uint32_t *hw_mode, + uint8_t *target_chan); /** * utils_dfs_init_nol() - Initialize nol from platform driver. * @pdev: pdev handler. diff --git a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c index 61e09a3a1940..2b0b33dd52b9 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c @@ -419,6 +419,15 @@ QDF_STATUS utils_dfs_is_ignore_cac(struct wlan_objmgr_pdev *pdev, *ignore_cac = dfs->dfs_ignore_cac; + /* + * This is needed as, if after channel bandwidth reduction, channel + * change occurs using dothchanswitch or chan commands, resetting. + * dfs->dfs_ignore_cac will make sure we not skip CAC on the new channel + */ + + if (dfs->dfs_bw_reduced) + dfs->dfs_ignore_cac = 0; + return QDF_STATUS_SUCCESS; } qdf_export_symbol(utils_dfs_is_ignore_cac); @@ -752,6 +761,57 @@ random_chan_error: } qdf_export_symbol(utils_dfs_get_random_channel); +QDF_STATUS utils_dfs_bw_reduced_channel( + struct wlan_objmgr_pdev *pdev, + uint16_t flags, + struct ch_params *ch_params, + uint32_t *hw_mode, + uint8_t *target_chan) +{ + struct wlan_dfs *dfs = NULL; + struct wlan_objmgr_psoc *psoc; + enum channel_state ch_state; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + *target_chan = 0; + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); + return status; + } + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); + return status; + } + + ch_state = reg_get_channel_state(pdev, dfs->dfs_curchan->dfs_ch_ieee); + + if (ch_state == CHANNEL_STATE_DFS || + ch_state == CHANNEL_STATE_ENABLE) { + ch_params->center_freq_seg0 = + dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1; + ch_params->center_freq_seg1 = + dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2; + /*If bandwidth reduction is applied, + * dfs_ignore_cac ensures we skip CAC. + */ + dfs->dfs_ignore_cac = 1; + dfs->dfs_bw_reduced = 1; + wlan_reg_set_channel_params(pdev, + dfs->dfs_curchan->dfs_ch_ieee, + 0, ch_params); + + *target_chan = dfs->dfs_curchan->dfs_ch_ieee; + utils_dfs_get_max_phy_mode(pdev, hw_mode); + + return QDF_STATUS_SUCCESS; + } + + return status; +} + #ifdef QCA_DFS_NOL_PLATFORM_DRV_SUPPORT void utils_dfs_init_nol(struct wlan_objmgr_pdev *pdev) {