wlan: Add traffic monitor on SAP/P2P-GO mode
To address the issue wherein APPS fails to power collapse
when OBSS protection is enabled,
we need to implement an IDLE traffic monitoring
logic in the HDD: it needs to detect 2 states:
IDLE STATE: HDD transitions to that STATE
when there is no traffic for a configuration duration in cfg file.
ACTIVE STATE: this is the initial state when SAP comes up.
HDD moves also to that state
when it sees traffic when in IDLE State.
Change-Id: I45dda8a1b8d7aa588ec940cc3b115b918b01c932
CRs-fixed: 495899
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index f51d361..ee7bae4 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -1743,6 +1743,19 @@
#define CFG_MAX_MEDIUM_TIME_STAMAX WNI_CFG_MAX_MEDIUM_TIME_STAMAX
#define CFG_MAX_MEDIUM_TIME_STADEFAULT WNI_CFG_MAX_MEDIUM_TIME_STADEF
+/*
+ * SAP/P2P-GO mode traffic monitor
+ */
+#define CFG_ENABLE_TRAFFIC_MONITOR "gEnableTrafficMonitor"
+#define CFG_ENABLE_TRAFFIC_MONITOR_MIN ( 0 )
+#define CFG_ENABLE_TRAFFIC_MONITOR_MAX ( 1 )
+#define CFG_ENABLE_TRAFFIC_MONITOR_DEFAULT ( 0 )
+
+#define CFG_TRAFFIC_IDLE_TIMEOUT "gTrafficIdleTimeout"
+#define CFG_TRAFFIC_IDLE_TIMEOUT_MIN ( 3000 )
+#define CFG_TRAFFIC_IDLE_TIMEOUT_MAX ( 10000 )
+#define CFG_TRAFFIC_IDLE_TIMEOUT_DEFAULT ( 5000 )
+
/*---------------------------------------------------------------------------
Type declarations
-------------------------------------------------------------------------*/
@@ -2117,6 +2130,8 @@
v_BOOL_t enableSSR;
char listOfNon11acCountryCode[128];
v_U32_t cfgMaxMediumTime;
+ v_U8_t enableTrafficMonitor;
+ v_U32_t trafficIdleTimeout;
} hdd_config_t;
/*---------------------------------------------------------------------------
Function declarations and documenation
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 848f439..7a9440a 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -856,6 +856,15 @@
int total_len;
}hdd_priv_data_t;
+typedef struct
+{
+ vos_timer_t trafficTimer;
+ atomic_t isActiveMode;
+ v_U8_t isInitialized;
+ vos_lock_t trafficLock;
+ v_TIME_t lastFrameTs;
+}hdd_traffic_monitor_t;
+
/** Adapter stucture definition */
struct hdd_context_s
@@ -1002,6 +1011,8 @@
tANI_U16 connected_peer_count;
tdls_scan_context_t tdls_scan_ctxt;
#endif
+
+ hdd_traffic_monitor_t traffic_monitor;
};
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index f7a72af..98fc710 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -2267,6 +2267,19 @@
CFG_MAX_MEDIUM_TIME_STAMIN,
CFG_MAX_MEDIUM_TIME_STAMAX ),
+ REG_VARIABLE( CFG_ENABLE_TRAFFIC_MONITOR, WLAN_PARAM_Integer,
+ hdd_config_t, enableTrafficMonitor,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_TRAFFIC_MONITOR_DEFAULT,
+ CFG_ENABLE_TRAFFIC_MONITOR_MIN,
+ CFG_ENABLE_TRAFFIC_MONITOR_MAX),
+
+ REG_VARIABLE( CFG_TRAFFIC_IDLE_TIMEOUT, WLAN_PARAM_Integer,
+ hdd_config_t, trafficIdleTimeout,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_TRAFFIC_IDLE_TIMEOUT_DEFAULT,
+ CFG_TRAFFIC_IDLE_TIMEOUT_MIN,
+ CFG_TRAFFIC_IDLE_TIMEOUT_MAX),
};
/*
@@ -2647,6 +2660,8 @@
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableLpwrImgTransition] Value = [%u] ",pHddCtx->cfg_ini->enableLpwrImgTransition);
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableSSR] Value = [%u] ",pHddCtx->cfg_ini->enableSSR);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableTrafficMonitor] Value = [%u] ", pHddCtx->cfg_ini->enableTrafficMonitor);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gTrafficIdleTimeout] Value = [%u] ", pHddCtx->cfg_ini->trafficIdleTimeout);
}
diff --git a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
index 0f66baa..7326079 100644
--- a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
+++ b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
@@ -98,6 +98,45 @@
skb->data[13], skb->data[14], skb->data[15]);
}
#endif
+
+extern void hdd_set_wlan_suspend_mode(bool suspend);
+
+/**============================================================================
+ @brief hdd_softap_traffic_monitor_timeout_handler() -
+ SAP/P2P GO traffin monitor timeout handler function
+ If no traffic during programmed time, trigger suspand mode
+
+ @param pUsrData : [in] pointer to hdd context
+ @return : NONE
+ ===========================================================================*/
+void hdd_softap_traffic_monitor_timeout_handler( void *pUsrData )
+{
+ hdd_context_t *pHddCtx = (hdd_context_t *)pUsrData;
+ v_TIME_t currentTS;
+
+ if (NULL == pHddCtx)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid user data, context", __func__);
+ return;
+ }
+
+ currentTS = vos_timer_get_system_time();
+ if (pHddCtx->cfg_ini->trafficIdleTimeout <
+ (currentTS - pHddCtx->traffic_monitor.lastFrameTs))
+ {
+ hdd_set_wlan_suspend_mode(1);
+ atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 0);
+ }
+ else
+ {
+ vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
+ pHddCtx->cfg_ini->trafficIdleTimeout);
+ }
+
+ return;
+}
+
/**============================================================================
@brief hdd_softap_flush_tx_queues() - Utility function to flush the TX queues
@@ -521,6 +560,9 @@
HDD_SOFTAP_VI_WEIGHT_DEFAULT,
HDD_SOFTAP_VO_WEIGHT_DEFAULT
};
+
+ hdd_context_t *pHddCtx = NULL;
+
pAdapter->isVosOutOfResource = VOS_FALSE;
vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
@@ -550,6 +592,31 @@
/* Update the AC weights suitable for SoftAP mode of operation */
WLANTL_SetACWeights((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pACWeights);
+ /* Initialize SAP/P2P-GO traffin monitor */
+ pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+ if (NULL == pHddCtx)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid HDD cntxt", __func__ );
+ return VOS_STATUS_E_INVAL;
+ }
+ if ((pHddCtx->cfg_ini->enableTrafficMonitor) &&
+ (!pHddCtx->traffic_monitor.isInitialized))
+ {
+ atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
+ vos_timer_init(&pHddCtx->traffic_monitor.trafficTimer,
+ VOS_TIMER_TYPE_SW,
+ hdd_softap_traffic_monitor_timeout_handler,
+ pHddCtx);
+ vos_lock_init(&pHddCtx->traffic_monitor.trafficLock);
+ pHddCtx->traffic_monitor.isInitialized = 1;
+ pHddCtx->traffic_monitor.lastFrameTs = 0;
+ /* Start traffic monitor timer here
+ * If no AP assoc, immediatly go into suspend */
+ vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
+ pHddCtx->cfg_ini->trafficIdleTimeout);
+ }
+
return status;
}
@@ -564,6 +631,26 @@
VOS_STATUS hdd_softap_deinit_tx_rx( hdd_adapter_t *pAdapter )
{
VOS_STATUS status = VOS_STATUS_SUCCESS;
+ hdd_context_t *pHddCtx = NULL;
+
+ pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+ if (NULL == pHddCtx)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid HDD cntxt", __func__ );
+ return VOS_STATUS_E_INVAL;
+ }
+ if (pHddCtx->traffic_monitor.isInitialized)
+ {
+ if (VOS_TIMER_STATE_STOPPED !=
+ vos_timer_getCurrentState(&pHddCtx->traffic_monitor.trafficTimer))
+ {
+ vos_timer_stop(&pHddCtx->traffic_monitor.trafficTimer);
+ }
+ vos_timer_destroy(&pHddCtx->traffic_monitor.trafficTimer);
+ vos_lock_destroy(&pHddCtx->traffic_monitor.trafficLock);
+ pHddCtx->traffic_monitor.isInitialized = 0;
+ }
status = hdd_softap_flush_tx_queues(pAdapter);
@@ -853,6 +940,26 @@
return VOS_STATUS_E_FAILURE;
}
+ /* Monitor traffic */
+ if ( pHddCtx->cfg_ini->enableTrafficMonitor )
+ {
+ pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time();
+ if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
+ {
+ vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock);
+ /* It was IDLE mode,
+ * this is new state, then switch mode from suspend to resume */
+ if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
+ {
+ hdd_set_wlan_suspend_mode(0);
+ vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
+ pHddCtx->cfg_ini->trafficIdleTimeout);
+ atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
+ }
+ vos_lock_release(&pHddCtx->traffic_monitor.trafficLock);
+ }
+ }
+
++pAdapter->hdd_stats.hddTxRxStats.txFetched;
STAId = *pStaId;
@@ -1148,7 +1255,27 @@
VOS_ASSERT(0);
return VOS_STATUS_E_FAILURE;
}
-
+
+ /* Monitor traffic */
+ if ( pHddCtx->cfg_ini->enableTrafficMonitor )
+ {
+ pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time();
+ if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
+ {
+ vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock);
+ /* It was IDLE mode,
+ * this is new state, then switch mode from suspend to resume */
+ if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
+ {
+ hdd_set_wlan_suspend_mode(0);
+ vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
+ pHddCtx->cfg_ini->trafficIdleTimeout);
+ atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
+ }
+ vos_lock_release(&pHddCtx->traffic_monitor.trafficLock);
+ }
+ }
+
++pAdapter->hdd_stats.hddTxRxStats.rxChains;
// walk the chain until all are processed