diff options
| author | bings <bings@codeaurora.org> | 2016-12-09 11:25:37 +0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-02-16 22:04:36 -0800 |
| commit | bf0a083bad132b449d6a6afb88a6a15850a3670f (patch) | |
| tree | 8f093117a21e5e01ccdcef25f118af76510d2443 | |
| parent | 2eb6b84b51523c36edc59c435b1ea5b47e724129 (diff) | |
qcacld-2.0: WAR for radar false detection
Currently some WiFi chips imitate to radar type pulses with our SAP.
War is required to ignore since these are not real pulses.
Ignore radar found 500ms before assoc request packet and 300ms after
assoc request packet.
Create new queue and collect radar pulse with pulse index1 and pulse
index2. Save 32 radar pulses for the new queue. Once radar is found,
for radar pulse in the new queue, remove radar pulse that happens 20ms
ago. Find the biggest and smallest dur for the rest radar pulse in the
new queue. If they have more than 10 difference, then ignore this radar
found.
Change-Id: Id1db0d811c0b3b47f45c621b6bec3b3e636e330f
CRs-Fixed: 1105728
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_cfg.h | 14 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_cfg.c | 7 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_cfg80211.c | 1 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_ftm.c | 4 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_main.c | 24 | ||||
| -rw-r--r-- | CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c | 8 | ||||
| -rw-r--r-- | CORE/SAP/inc/sapApi.h | 2 | ||||
| -rw-r--r-- | CORE/SAP/src/sapModule.c | 3 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/wma_dfs_interface.h | 3 | ||||
| -rw-r--r-- | CORE/SERVICES/DFS/inc/dfs.h | 37 | ||||
| -rw-r--r-- | CORE/SERVICES/DFS/src/dfs.c | 163 | ||||
| -rw-r--r-- | CORE/SERVICES/DFS/src/dfs_process_radarevent.c | 70 | ||||
| -rw-r--r-- | CORE/SERVICES/WMA/wma.c | 89 | ||||
| -rw-r--r-- | CORE/SERVICES/WMA/wma.h | 31 | ||||
| -rw-r--r-- | CORE/VOSS/src/vos_api.c | 3 | ||||
| -rw-r--r-- | CORE/WDA/inc/wlan_qct_wda.h | 3 |
16 files changed, 400 insertions, 62 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h index d83b1cd8adb1..2b2e6d89cf83 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/CORE/HDD/inc/wlan_hdd_cfg.h @@ -1482,6 +1482,11 @@ typedef enum #define CFG_DISABLE_DFS_CH_SWITCH_MAX ( 1 ) #define CFG_DISABLE_DFS_CH_SWITCH_DEFAULT ( 0 ) +#define CFG_ENABLE_RADAR_WAR "gEnableRadarAssocWar" +#define CFG_ENABLE_RADAR_WAR_MIN ( 0 ) +#define CFG_ENABLE_RADAR_WAR_MAX ( 1 ) +#define CFG_ENABLE_RADAR_WAR_DEFAULT ( 1 ) + #define CFG_ENABLE_DFS_MASTER_CAPABILITY "gEnableDFSMasterCap" #define CFG_ENABLE_DFS_MASTER_CAPABILITY_MIN ( 0 ) #define CFG_ENABLE_DFS_MASTER_CAPABILITY_MAX ( 1 ) @@ -5055,6 +5060,7 @@ struct hdd_config { v_U8_t max_sap_peers; v_U8_t max_go_peers; v_U8_t disableDFSChSwitch; + v_U8_t enable_radar_war; v_U8_t enableDFSMasterCap; v_U16_t thermalTempMinLevel0; v_U16_t thermalTempMaxLevel0; @@ -5558,6 +5564,14 @@ tANI_BOOLEAN hdd_is_okc_mode_enabled(hdd_context_t *pHddCtx); VOS_STATUS hdd_set_idle_ps_config(hdd_context_t *pHddCtx, v_U32_t val); void hdd_update_tgt_cfg(void *context, void *param); +/** + * hdd_update_dfs_cac_block_tx_flag() - to set dfs_cac_block_tx flag + * @context: Pointer to hdd contex + * @cac_block_tx: value to be set + * + * Return: none + */ +void hdd_update_dfs_cac_block_tx_flag(void *context, bool cac_block_tx); bool hdd_dfs_indicate_radar(void *context, void *param); VOS_STATUS hdd_string_to_u8_array( char *str, tANI_U8 *intArray, tANI_U8 *len, diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c index 25475d14a458..0aef2048a1fe 100644 --- a/CORE/HDD/src/wlan_hdd_cfg.c +++ b/CORE/HDD/src/wlan_hdd_cfg.c @@ -2364,6 +2364,13 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_DISABLE_DFS_CH_SWITCH_MIN, CFG_DISABLE_DFS_CH_SWITCH_MAX ), + REG_VARIABLE( CFG_ENABLE_RADAR_WAR, WLAN_PARAM_Integer, + hdd_config_t, enable_radar_war, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_RADAR_WAR_DEFAULT, + CFG_ENABLE_RADAR_WAR_MIN, + CFG_ENABLE_RADAR_WAR_MAX ), + REG_VARIABLE( CFG_ENABLE_DFS_MASTER_CAPABILITY, WLAN_PARAM_Integer, hdd_config_t, enableDFSMasterCap, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 01d0a83037a2..0b5acbbc880e 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -15806,6 +15806,7 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int; pConfig->disableDFSChSwitch = iniConfig->disableDFSChSwitch; + pConfig->enable_radar_war = iniConfig->enable_radar_war; pConfig->sap_chanswitch_beacon_cnt = iniConfig->sap_chanswitch_beacon_cnt; diff --git a/CORE/HDD/src/wlan_hdd_ftm.c b/CORE/HDD/src/wlan_hdd_ftm.c index 62b4ceb2f8fd..1310e75f1ccc 100644 --- a/CORE/HDD/src/wlan_hdd_ftm.c +++ b/CORE/HDD/src/wlan_hdd_ftm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -346,7 +346,7 @@ static VOS_STATUS wlan_ftm_vos_open( v_CONTEXT_t pVosContext, v_SIZE_t hddContex macOpenParms.powersaveOffloadEnabled = pHddCtx->cfg_ini->enablePowersaveOffload; vStatus = WDA_open(gpVosContext, gpVosContext->pHDDContext, - wlan_hdd_ftm_update_tgt_cfg, NULL, + wlan_hdd_ftm_update_tgt_cfg, NULL, NULL, &macOpenParms); if (!VOS_IS_STATUS_SUCCESS(vStatus)) { diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 664c8fd585b8..36e391bd44cc 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -9018,6 +9018,30 @@ void hdd_update_tgt_cfg(void *context, void *param) hdd_ctx->max_mc_addr_list = cfg->max_mc_addr_list; } +void hdd_update_dfs_cac_block_tx_flag(void *context, bool cac_block_tx) +{ + hdd_context_t *hdd_ctx = (hdd_context_t *)context; + hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; + hdd_adapter_t *adapter; + VOS_STATUS status; + + if (wlan_hdd_validate_context(hdd_ctx)) + return; + if (hdd_ctx->cfg_ini->disableDFSChSwitch) + return; + status = hdd_get_front_adapter(hdd_ctx, &adapter_node); + while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) { + adapter = adapter_node->pAdapter; + if (WLAN_HDD_SOFTAP == adapter->device_mode || + WLAN_HDD_P2P_GO == adapter->device_mode) + WLAN_HDD_GET_AP_CTX_PTR(adapter)->dfs_cac_block_tx = + cac_block_tx; + + status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next); + adapter_node = next; + } +} + /* This function is invoked in atomic context when a radar * is found on the SAP current operating channel and Data * Tx from netif has to be stopped to honor the DFS regulations. diff --git a/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c b/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c index 489f7a95a6bf..320db4233407 100644 --- a/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c +++ b/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -57,6 +57,7 @@ #include "vos_types.h" #include "vos_utils.h" +#include "wma.h" /** * limConvertSupportedChannels * @@ -264,6 +265,11 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, psessionEntry->peSessionId, GET_LIM_SYSTEM_ROLE(psessionEntry), psessionEntry->limMlmState, MAC_ADDR_ARRAY(pHdr->sa)); + if (pMac->sap.SapDfsInfo.sap_enable_radar_war && (NV_CHANNEL_DFS == + vos_nv_getChannelEnabledState(psessionEntry->currentOperChannel))) { + wma_ignore_radar_soon_after_assoc(); + wma_stop_radar_delay_timer(); + } if (LIM_IS_STA_ROLE(psessionEntry) || LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { limLog(pMac, LOGE, FL("received unexpected ASSOC REQ on sessionid: %d " diff --git a/CORE/SAP/inc/sapApi.h b/CORE/SAP/inc/sapApi.h index 3c89961b0fd7..fb37edad6d25 100644 --- a/CORE/SAP/inc/sapApi.h +++ b/CORE/SAP/inc/sapApi.h @@ -570,6 +570,7 @@ typedef struct sap_Config { v_U32_t ht_op_mode_fixed; tVOS_CON_MODE persona; /*Tells us which persona it is GO or AP for now*/ v_U8_t disableDFSChSwitch; + v_U8_t enable_radar_war; eCsrBand scanBandPreference; v_BOOL_t enOverLapCh; v_U16_t acsBandSwitchThreshold; @@ -720,6 +721,7 @@ typedef struct sSapDfsInfo * channel switch is disabled. */ v_U8_t disable_dfs_ch_switch; + v_U8_t sap_enable_radar_war; uint16_t tx_leakage_threshold; uint8_t new_sub20_channelwidth; /* beacon count before channel switch */ diff --git a/CORE/SAP/src/sapModule.c b/CORE/SAP/src/sapModule.c index 7920e1f8e733..f240ab7d7658 100644 --- a/CORE/SAP/src/sapModule.c +++ b/CORE/SAP/src/sapModule.c @@ -820,6 +820,8 @@ WLANSAP_StartBss * Copy the DFS Test Mode setting to pmac for * access in lower layers */ + pmac->sap.SapDfsInfo.sap_enable_radar_war = + pConfig->enable_radar_war; pmac->sap.SapDfsInfo.disable_dfs_ch_switch = pConfig->disableDFSChSwitch; pmac->sap.SapDfsInfo.sap_ch_switch_beacon_cnt = @@ -834,6 +836,7 @@ WLANSAP_StartBss if (pConfig->sub20_switch_mode == SUB20_STATIC) pmac->sap.SapDfsInfo.new_sub20_channelwidth = pmac->sub20_channelwidth; + // Copy MAC filtering settings to sap context pSapCtx->eSapMacAddrAclMode = pConfig->SapMacaddr_acl; vos_mem_copy(pSapCtx->acceptMacList, pConfig->accept_mac, sizeof(pConfig->accept_mac)); diff --git a/CORE/SERVICES/COMMON/wma_dfs_interface.h b/CORE/SERVICES/COMMON/wma_dfs_interface.h index 3aad4665b0d5..66161db41b8e 100644 --- a/CORE/SERVICES/COMMON/wma_dfs_interface.h +++ b/CORE/SERVICES/COMMON/wma_dfs_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2014, 2016-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -202,6 +202,7 @@ typedef struct ieee80211com int (*ic_dfs_control)(struct ieee80211com *ic, u_int id, void *indata, u_int32_t insize, void *outdata, u_int32_t *outsize); + void (*ic_update_dfs_cac_block_tx)(bool cac_block_tx); HAL_DFS_DOMAIN current_dfs_regdomain; u_int8_t vdev_id; u_int8_t last_radar_found_chan; diff --git a/CORE/SERVICES/DFS/inc/dfs.h b/CORE/SERVICES/DFS/inc/dfs.h index 4824320c269d..b86e095262bd 100644 --- a/CORE/SERVICES/DFS/inc/dfs.h +++ b/CORE/SERVICES/DFS/inc/dfs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2014, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2005-2014, 2016-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -230,6 +230,15 @@ #define DFS_ETSI_TYPE3_WAR_PRI_UPPER_LIMIT 435 #define DFS_ETSI_WAR_VALID_PULSE_DURATION 15 +#define DFS_RADAR_DELAY 500 +#define DFS_RADAR_IGNORE 300 +#define DFS_RADAR_FALSE_PRI_START 5 +#define DFS_RADAR_FLASE_PRI_END 14 +#define DFS_SIDX1_SIDX2_SIZE 0x20 +#define DFS_SIDX1_SIDX2_MASK 0x1f +#define DFS_SIDX1_SIDX2_TIME_WINDOW 20000 +#define DFS_SIDX1_SIDX2_DR_LIM 10 + typedef adf_os_spinlock_t dfsq_lock_t; #ifdef WIN32 @@ -247,6 +256,13 @@ struct dfs_pulseparams { #ifdef WIN32 #pragma pack(push, dfs_pulseline, 1) #endif +struct dfs_sidx1_sidx2_pulse_line { + /* pl_elems - array of pulses in delay line */ + struct dfs_pulseparams pl_elems[DFS_SIDX1_SIDX2_SIZE]; + u_int32_t pl_firstelem; /* Index of the first element */ + u_int32_t pl_lastelem; /* Index of the last element */ + u_int32_t pl_numelems; /* Number of elements in the delay line */ +} adf_os_packed; struct dfs_pulseline { /* pl_elems - array of pulses in delay line */ struct dfs_pulseparams pl_elems[DFS_MAX_PULSE_BUFFER_SIZE]; @@ -588,11 +604,14 @@ struct ath_dfs { struct dfs_stats ath_dfs_stats; /* DFS related stats */ struct dfs_pulseline *pulses; /* pulse history */ struct dfs_event *events; /* Events structure */ + struct dfs_sidx1_sidx2_pulse_line sidx1_sidx2_elems; u_int32_t ath_radar_tasksched:1, /* radar task is scheduled */ ath_dfswait:1, /* waiting on channel for radar detect */ - ath_dfstest:1; /* Test timer in progress */ + ath_dfstest:1, /* Test timer in progress */ + ath_radar_delaysched:1, /*radar found event delay*/ + ath_radar_ignore_after_assoc:1; /*ignore radar 300ms after assoc*/ struct ath_dfs_caps dfs_caps; u_int8_t ath_dfstest_ieeechan; /* IEEE chan num to return to after * a dfs mute test */ @@ -605,6 +624,8 @@ struct ath_dfs { u_int8_t dfs_bangradar; #endif os_timer_t ath_dfs_task_timer; /* dfs wait timer */ + vos_timer_t ath_dfs_radar_ignore_timer; /*ignore radar timer*/ + vos_timer_t ath_dfs_radar_delay_timer; /*radar found event delay timer*/ int dur_multiplier; u_int16_t ath_dfs_isdfsregdomain; /* true when we are DFS domain */ @@ -628,6 +649,18 @@ struct ath_dfs { * channel switch is disabled. */ int8_t disable_dfs_ch_switch; + /* + * Currently some WiFi chips sends radar, so add war as below + * Ignore radar found 500ms before assoc request packet and 300ms after + * assoc request packet. + * Create new queue and collect radar pulse with pulse index1 and pulse + * index2. Save 32 radar pulses for the new queue. Once radar is found, + * for radar pulse in the new queue, remove radar pulse that happens 20ms + * ago. Find the biggest and smallest dur for the rest radar pulse in the + * new queue. If they have more than 10 difference, then ignore this radar + * found. + */ + int8_t dfs_enable_radar_war; }; /* This should match the table from if_ath.c */ diff --git a/CORE/SERVICES/DFS/src/dfs.c b/CORE/SERVICES/DFS/src/dfs.c index da1fbd7994e5..f118f0a1ad36 100644 --- a/CORE/SERVICES/DFS/src/dfs.c +++ b/CORE/SERVICES/DFS/src/dfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2014, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2002-2014, 2016-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -127,59 +127,109 @@ dfs_channel_mark_radar(struct ath_dfs *dfs, struct ieee80211_channel *chan) } #endif /* #if 0 */ -static OS_TIMER_FUNC(dfs_task) +/** + * dfs_radar_ignore() - ignore radar found event + * @data: pointer to struct ieee80211com + * + * Return: none + */ +static void dfs_radar_ignore(void *data) { - struct ieee80211com *ic; - struct ath_dfs *dfs = NULL; - - OS_GET_TIMER_ARG(ic, struct ieee80211com *); - dfs = (struct ath_dfs *)ic->ic_dfs; - /* - * XXX no locking?! - */ - if (dfs_process_radarevent(dfs, ic->ic_curchan)) { -#ifndef ATH_DFS_RADAR_DETECTION_ONLY + struct ieee80211com *ic = (struct ieee80211com *)data; + struct ath_dfs *dfs = NULL; - /* - * This marks the channel (and the extension channel, if HT40) as - * having seen a radar event. It marks CHAN_INTERFERENCE and - * will add it to the local NOL implementation. - * - * This is only done for 'usenol=1', as the other two modes - * don't do radar notification or CAC/CSA/NOL; it just notes - * there was a radar. - */ + dfs = (struct ath_dfs *)ic->ic_dfs; + dfs->ath_radar_ignore_after_assoc = false; +} - if (dfs->dfs_rinfo.rn_use_nol == 1) { - //dfs_channel_mark_radar(dfs, ic->ic_curchan); - } -#endif /* ATH_DFS_RADAR_DETECTION_ONLY */ +/** + * dfs_radar_delay() - delay radar found event + * @data: pointer to struct ieee80211com + * + * Return: none + */ +static void dfs_radar_delay(void *data) +{ + struct ieee80211com *ic = (struct ieee80211com *)data; + struct ath_dfs *dfs = NULL; + + dfs = (struct ath_dfs *)ic->ic_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 IEEE80211_CHAN_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. + */ + if (dfs->dfs_rinfo.rn_use_nol == 1) { + ic->ic_dfs_notify_radar(ic, ic->ic_curchan); + } else if (dfs->dfs_rinfo.rn_use_nol == 0) { + /* + * For the test mode, don't do a CSA here; but setup the + * test timer so we get a CSA _back_ to the original channel. + */ + OS_CANCEL_TIMER(&dfs->ath_dfstesttimer); + dfs->ath_dfstest = 1; + adf_os_spin_lock_bh(&ic->chan_lock); + dfs->ath_dfstest_ieeechan = ic->ic_curchan->ic_ieee; + adf_os_spin_unlock_bh(&ic->chan_lock); + dfs->ath_dfstesttime = 1; /* 1ms */ + OS_SET_TIMER(&dfs->ath_dfstesttimer, dfs->ath_dfstesttime); + } + dfs->ath_radar_delaysched = 0; +} - /* - * 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 IEEE80211_CHAN_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. - */ - if (dfs->dfs_rinfo.rn_use_nol == 1) { - ic->ic_dfs_notify_radar(ic, ic->ic_curchan); - } else if (dfs->dfs_rinfo.rn_use_nol == 0) { - /* - * For the test mode, don't do a CSA here; but setup the - * test timer so we get a CSA _back_ to the original channel. - */ - OS_CANCEL_TIMER(&dfs->ath_dfstesttimer); - dfs->ath_dfstest = 1; - adf_os_spin_lock_bh(&ic->chan_lock); - dfs->ath_dfstest_ieeechan = ic->ic_curchan->ic_ieee; - adf_os_spin_unlock_bh(&ic->chan_lock); - dfs->ath_dfstesttime = 1; /* 1ms */ - OS_SET_TIMER(&dfs->ath_dfstesttimer, dfs->ath_dfstesttime); - } - } - dfs->ath_radar_tasksched = 0; +static OS_TIMER_FUNC(dfs_task) +{ + struct ieee80211com *ic; + struct ath_dfs *dfs = NULL; + + OS_GET_TIMER_ARG(ic, struct ieee80211com *); + dfs = (struct ath_dfs *)ic->ic_dfs; + + if (dfs_process_radarevent(dfs, ic->ic_curchan)) { + if (!dfs->dfs_enable_radar_war) { + /* + * 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 + * IEEE80211_CHAN_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. + */ + if (dfs->dfs_rinfo.rn_use_nol == 1) { + ic->ic_dfs_notify_radar(ic, ic->ic_curchan); + } else if (dfs->dfs_rinfo.rn_use_nol == 0) { + /* + * For the test mode, don't do a CSA here; but + * setup the test timer so we get a CSA _back_ + * to the original channel. + */ + OS_CANCEL_TIMER(&dfs->ath_dfstesttimer); + dfs->ath_dfstest = 1; + adf_os_spin_lock_bh(&ic->chan_lock); + dfs->ath_dfstest_ieeechan = + ic->ic_curchan->ic_ieee; + adf_os_spin_unlock_bh(&ic->chan_lock); + dfs->ath_dfstesttime = 1; /* 1ms */ + OS_SET_TIMER(&dfs->ath_dfstesttimer, + dfs->ath_dfstesttime); + } + } else { + if ((!dfs->ath_radar_delaysched) && + (!dfs->ath_radar_ignore_after_assoc)) { + ic->ic_update_dfs_cac_block_tx(true); + vos_timer_start(&dfs->ath_dfs_radar_delay_timer, + DFS_RADAR_DELAY); + dfs->ath_radar_delaysched = 1; + } + } + } + dfs->ath_radar_tasksched = 0; } static @@ -323,6 +373,14 @@ dfs_attach(struct ieee80211com *ic) dfs->dfs_event_log_on = 0; OS_INIT_TIMER(NULL, &(dfs->ath_dfs_task_timer), dfs_task, (void *) (ic), ADF_DEFERRABLE_TIMER); + vos_timer_init(&(dfs->ath_dfs_radar_delay_timer), VOS_TIMER_TYPE_SW, + dfs_radar_delay, (void *) (ic)); + vos_timer_init(&(dfs->ath_dfs_radar_ignore_timer), VOS_TIMER_TYPE_SW, + dfs_radar_ignore, (void *) (ic)); + + dfs->sidx1_sidx2_elems.pl_firstelem = 0; + dfs->sidx1_sidx2_elems.pl_lastelem = DFS_SIDX1_SIDX2_MASK; + dfs->sidx1_sidx2_elems.pl_numelems = 0; #ifndef ATH_DFS_RADAR_DETECTION_ONLY OS_INIT_TIMER(NULL, &(dfs->ath_dfstesttimer), dfs_testtimer_task, (void *) ic, ADF_DEFERRABLE_TIMER); @@ -533,6 +591,11 @@ dfs_detach(struct ieee80211com *ic) dfs->ath_radar_tasksched = 0; } + vos_timer_stop(&dfs->ath_dfs_radar_delay_timer); + vos_timer_destroy(&dfs->ath_dfs_radar_delay_timer); + + vos_timer_stop(&dfs->ath_dfs_radar_ignore_timer); + vos_timer_destroy(&dfs->ath_dfs_radar_ignore_timer); if (dfs->ath_dfstest) { OS_CANCEL_TIMER(&dfs->ath_dfstesttimer); dfs->ath_dfstest = 0; diff --git a/CORE/SERVICES/DFS/src/dfs_process_radarevent.c b/CORE/SERVICES/DFS/src/dfs_process_radarevent.c index e89800caac82..bf7a776dda46 100644 --- a/CORE/SERVICES/DFS/src/dfs_process_radarevent.c +++ b/CORE/SERVICES/DFS/src/dfs_process_radarevent.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2014, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2002-2014, 2016-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -276,6 +276,44 @@ static void dfs_process_dc_pulse(struct ath_dfs *dfs, struct dfs_event *event, } } +/** + * dfs_cal_sidx1_sidx2_dur_diff() - cal dur difference in sidx1_sidx2 + * pluse line + * @dfs: pointer to dfs structure + * + * Return: max dur difference in sidx1_sidx2 pulse line + */ +static int dfs_cal_sidx1_sidx2_dur_diff(struct ath_dfs *dfs) +{ + u_int32_t index, loop; + u_int32_t lowdur, highdur; + struct dfs_sidx1_sidx2_pulse_line *sidx1_sidx2_p; + struct dfs_pulseline *pl; + + if (dfs == NULL) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s[%d]: dfs is NULL", __func__, __LINE__); + return 0; + } + pl = dfs->pulses; + sidx1_sidx2_p = &dfs->sidx1_sidx2_elems; + lowdur = highdur = + sidx1_sidx2_p->pl_elems[sidx1_sidx2_p->pl_lastelem].p_dur; + for (loop = 0; loop < sidx1_sidx2_p->pl_numelems; loop++) { + index = sidx1_sidx2_p->pl_firstelem + loop; + index &= DFS_SIDX1_SIDX2_MASK; + if (sidx1_sidx2_p->pl_elems[index].p_time > + pl->pl_elems[pl->pl_lastelem].p_time - + DFS_SIDX1_SIDX2_TIME_WINDOW) { + if (sidx1_sidx2_p->pl_elems[index].p_dur < lowdur) + lowdur = sidx1_sidx2_p->pl_elems[index].p_dur; + if (sidx1_sidx2_p->pl_elems[index].p_dur > highdur) + highdur = sidx1_sidx2_p->pl_elems[index].p_dur; + } + } + return highdur - lowdur; +} + /* * Process a radar event. * @@ -289,18 +327,17 @@ static void dfs_process_dc_pulse(struct ath_dfs *dfs, struct dfs_event *event, int dfs_process_radarevent(struct ath_dfs *dfs, struct ieee80211_channel *chan) { -//commenting for now to validate radar indication msg to SAP -//#if 0 struct dfs_event re,*event; struct dfs_state *rs=NULL; struct dfs_filtertype *ft; struct dfs_filter *rf; int found, retval = 0, p, empty; int events_processed = 0; - u_int32_t tabledepth, index; + u_int32_t tabledepth, index, sidx1_sidx2_index; u_int64_t deltafull_ts = 0, this_ts, deltaT; struct ieee80211_channel *thischan; struct dfs_pulseline *pl; + struct dfs_sidx1_sidx2_pulse_line *sidx1_sidx2_p; static u_int32_t test_ts = 0; static u_int32_t diff_ts = 0; int ext_chan_event_flag = 0; @@ -315,6 +352,7 @@ dfs_process_radarevent(struct ath_dfs *dfs, struct ieee80211_channel *chan) return 0; } pl = dfs->pulses; + sidx1_sidx2_p = &dfs->sidx1_sidx2_elems; adf_os_spin_lock_bh(&dfs->ic->chan_lock); if ( !(IEEE80211_IS_CHAN_DFS(dfs->ic->ic_curchan))) { adf_os_spin_unlock_bh(&dfs->ic->chan_lock); @@ -540,6 +578,22 @@ dfs_process_radarevent(struct ath_dfs *dfs, struct ieee80211_channel *chan) pl->pl_elems[index].p_time = this_ts; pl->pl_elems[index].p_dur = re.re_dur; pl->pl_elems[index].p_rssi = re.re_rssi; + if (dfs->dfs_enable_radar_war && + (re.sidx == 1 || re.sidx == 2)) { + sidx1_sidx2_index = (sidx1_sidx2_p->pl_lastelem + 1) & + DFS_SIDX1_SIDX2_MASK; + if (sidx1_sidx2_p->pl_numelems == DFS_SIDX1_SIDX2_SIZE) + sidx1_sidx2_p->pl_firstelem = + (sidx1_sidx2_p->pl_firstelem + 1) & + DFS_SIDX1_SIDX2_MASK; + else + sidx1_sidx2_p->pl_numelems++; + sidx1_sidx2_p->pl_lastelem = sidx1_sidx2_index; + sidx1_sidx2_p->pl_elems[sidx1_sidx2_index].p_time = + this_ts; + sidx1_sidx2_p->pl_elems[sidx1_sidx2_index].p_dur = + re.re_dur; + } diff_ts = (u_int32_t)this_ts - test_ts; test_ts = (u_int32_t)this_ts; DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,"ts%u %u %u diff %u pl->pl_lastelem.p_time=%llu",(u_int32_t)this_ts, re.re_dur, re.re_rssi, diff_ts, (unsigned long long)pl->pl_elems[index].p_time); @@ -830,6 +884,13 @@ VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]:filterID= %d :: Rejec } dfsfound: if (retval) { + if (dfs->dfs_enable_radar_war && + (DFS_SIDX1_SIDX2_DR_LIM < dfs_cal_sidx1_sidx2_dur_diff(dfs))) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s [%d] false detection",__func__,__LINE__); + return 0; + } + /* Collect stats */ dfs->ath_dfs_stats.num_radar_detects++; thischan = &rs->rs_chan; @@ -881,7 +942,6 @@ thischan->ic_freq); } //VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "IN FUNC %s[%d]: retval = %d ",__func__,__LINE__,retval); return retval; -//#endif // return 1; } diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c index 09cfaab52a78..98119fb6b1a1 100644 --- a/CORE/SERVICES/WMA/wma.c +++ b/CORE/SERVICES/WMA/wma.c @@ -6440,6 +6440,68 @@ static void wma_update_probe_resp_noa(tp_wma_handle wma_handle, 0); } +void wma_ignore_radar_soon_after_assoc(void) +{ + void *vos_context; + tp_wma_handle wma; + struct ieee80211com *ic = NULL; + struct ath_dfs *dfs = NULL; + + vos_context = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL); + if (!vos_context) { + WMA_LOGE("%s: VOS context is invald!", __func__); + return; + } + + wma = (tp_wma_handle)vos_get_context(VOS_MODULE_ID_WDA, + vos_context); + + if (!wma) { + WMA_LOGE("%s: WMA context is invald!", __func__); + return; + } + + ic = wma->dfs_ic; + if (ic && ic->ic_dfs) { + dfs = (struct ath_dfs *)ic->ic_dfs; + dfs->ath_radar_ignore_after_assoc = true; + vos_timer_start(&dfs->ath_dfs_radar_ignore_timer, + DFS_RADAR_IGNORE); + } +} + +void wma_stop_radar_delay_timer(void) +{ + void *vos_context; + tp_wma_handle wma; + struct ieee80211com *ic = NULL; + struct ath_dfs *dfs = NULL; + + vos_context = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL); + if (!vos_context) { + WMA_LOGE("%s: VOS context is invald!", __func__); + return; + } + + wma = (tp_wma_handle)vos_get_context(VOS_MODULE_ID_WDA, + vos_context); + + if (!wma) { + WMA_LOGE("%s: WMA context is invald!", __func__); + return; + } + + ic = wma->dfs_ic; + if (ic && ic->ic_dfs) { + dfs = (struct ath_dfs *)ic->ic_dfs; + if (dfs->ath_radar_delaysched) { + wma_update_dfs_cac_block_tx(false); + vos_timer_stop(&dfs->ath_dfs_radar_delay_timer); + dfs->ath_radar_delaysched = 0; + } + } +} + static void wma_send_bcn_buf_ll(tp_wma_handle wma, ol_txrx_pdev_handle pdev, u_int8_t vdev_id, @@ -8617,6 +8679,7 @@ struct wma_version_info g_wmi_version_info; VOS_STATUS WDA_open(v_VOID_t *vos_context, v_VOID_t *os_ctx, wda_tgt_cfg_cb tgt_cfg_cb, wda_dfs_radar_indication_cb radar_ind_cb, + wda_dfs_block_tx_cb dfs_block_tx_cb, tMacOpenParameters *mac_params) { tp_wma_handle wma_handle; @@ -8809,6 +8872,7 @@ VOS_STATUS WDA_open(v_VOID_t *vos_context, v_VOID_t *os_ctx, wma_handle->tgt_cfg_update_cb = tgt_cfg_cb; wma_handle->dfs_radar_indication_cb = radar_ind_cb; + wma_handle->dfs_block_tx_cb = dfs_block_tx_cb; vos_status = vos_event_init(&wma_handle->wma_ready_event); if (vos_status != VOS_STATUS_SUCCESS) { @@ -14023,6 +14087,8 @@ VOS_STATUS wma_vdev_start(tp_wma_handle wma, wma_unified_dfs_phyerr_filter_offload_enable(wma); dfs->disable_dfs_ch_switch = pmac->sap.SapDfsInfo.disable_dfs_ch_switch; + dfs->dfs_enable_radar_war = + pmac->sap.SapDfsInfo.sap_enable_radar_war; } } @@ -38404,6 +38470,7 @@ struct ieee80211com* wma_dfs_attach(struct ieee80211com *dfs_ic) * and shared DFS code */ dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs; + dfs_ic->ic_update_dfs_cac_block_tx = ieee80211_update_dfs_cac_block_tx; adf_os_spinlock_init(&dfs_ic->chan_lock); /* Initializes DFS Data Structures and queues*/ dfs_attach(dfs_ic); @@ -38662,6 +38729,28 @@ int wma_get_channels(struct ieee80211_channel *ichan, return chan_list->nchannels; } +void wma_update_dfs_cac_block_tx(bool cac_block_tx) +{ + tp_wma_handle wma; + void *hdd_ctx; + void *vos_context; + + vos_context = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL); + if (!vos_context) { + WMA_LOGE("%s: VOS context is invald!", __func__); + return; + } + + wma = (tp_wma_handle) vos_get_context(VOS_MODULE_ID_WDA, vos_context); + + if (wma == NULL) { + WMA_LOGE("%s: DFS- Invalid wma", __func__); + return; + } + hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, wma->vos_context); + wma->dfs_block_tx_cb(hdd_ctx, cac_block_tx); +} + /* * Indicate Radar to SAP/HDD */ diff --git a/CORE/SERVICES/WMA/wma.h b/CORE/SERVICES/WMA/wma.h index 2332d0156c04..f88400115418 100644 --- a/CORE/SERVICES/WMA/wma.h +++ b/CORE/SERVICES/WMA/wma.h @@ -776,6 +776,7 @@ typedef struct wma_handle { wda_tgt_cfg_cb tgt_cfg_update_cb; /*Callback to indicate radar to HDD*/ wda_dfs_radar_indication_cb dfs_radar_indication_cb; + wda_dfs_block_tx_cb dfs_block_tx_cb; HAL_REG_CAPABILITIES reg_cap; u_int32_t scan_id; struct wma_txrx_node *interfaces; @@ -1689,6 +1690,22 @@ int ol_if_dfs_get_mib_cycle_counts_pct(struct ieee80211com *ic, u_int16_t ol_if_dfs_usenol(struct ieee80211com *ic); void ieee80211_mark_dfs(struct ieee80211com *ic, struct ieee80211_channel *ichan); +/** + * wma_update_dfs_cac_block_tx - to set dfs_cac_block_tx flag + * @cac_block_tx: value to be set + * + * Return: none + */ +void wma_update_dfs_cac_block_tx(bool cac_block_tx); +/** + * ieee80211_update_dfs_cac_block_tx() - to set dfs_cac_block_tx flag + * @cac_block_tx: value to be set + * + * Return: none + */ +static inline void ieee80211_update_dfs_cac_block_tx(bool cac_block_tx) { + wma_update_dfs_cac_block_tx(cac_block_tx); +} int wma_dfs_indicate_radar(struct ieee80211com *ic, struct ieee80211_channel *ichan); u_int16_t dfs_usenol(struct ieee80211com *ic); @@ -1863,6 +1880,20 @@ struct wma_version_info { u_int32_t revision; }; +/** + * wma_stop_radar_delay_timer() - stop radar delay found event timer + * + * Return: none + */ +void wma_stop_radar_delay_timer(void); + +/** + * wma_ignore_radar_soon_after_assoc() - ignore radar found 300ms after assoc + * + * Return: none + */ +void wma_ignore_radar_soon_after_assoc(void); + void wma_remove_peer(tp_wma_handle wma, u_int8_t *bssid, u_int8_t vdev_id, ol_txrx_peer_handle peer, v_BOOL_t roam_synch_in_progress); diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c index 96af126a9e37..617a4c0e3f22 100644 --- a/CORE/VOSS/src/vos_api.c +++ b/CORE/VOSS/src/vos_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -649,6 +649,7 @@ VOS_STATUS vos_open( v_CONTEXT_t *pVosContext, v_SIZE_t hddContextSize ) vStatus = WDA_open( gpVosContext, gpVosContext->pHDDContext, hdd_update_tgt_cfg, hdd_dfs_indicate_radar, + hdd_update_dfs_cac_block_tx_flag, &macOpenParms ); if (!VOS_IS_STATUS_SUCCESS(vStatus)) diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h index a4569bb524bd..e831bfabc3e5 100644 --- a/CORE/WDA/inc/wlan_qct_wda.h +++ b/CORE/WDA/inc/wlan_qct_wda.h @@ -318,6 +318,8 @@ typedef void (*wda_tgt_cfg_cb) (void *context, void *param); */ typedef bool (*wda_dfs_radar_indication_cb) (void *context, void *param); +typedef void (*wda_dfs_block_tx_cb) (void *context, bool cac_block_tx); + typedef struct { tANI_U16 ucValidStaIndex ; @@ -449,6 +451,7 @@ VOS_STATUS WDA_TxPacket(void *pWDA, VOS_STATUS WDA_open(v_PVOID_t pVosContext, v_PVOID_t pOSContext, wda_tgt_cfg_cb pTgtUpdCB, wda_dfs_radar_indication_cb radar_ind_cb, + wda_dfs_block_tx_cb dfs_block_tx_cb, tMacOpenParameters *pMacParams ) ; #define WDA_start wma_start |
