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/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