diff --git a/umac/dfs/core/src/dfs.h b/umac/dfs/core/src/dfs.h index 9f2fb7aa5d..925c0026b4 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 b6ee1f48b3..26f739a27a 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 13c500aba0..67548ad0a1 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 347799cefc..14b319a7ad 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 89c4f1f89f..938b004862 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 1be33310dd..b0d08a69a5 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 b6f9cc1a9e..5445ce466d 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 1fdc87fbac..1f523140c9 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 978dd2df9c..87961ee88e 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 3a00f5c110..ccbf754fcc 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 61e09a3a19..2b0b33dd52 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) {