wlan: Dynamically change tcp delay ack using hdd stats
We start a periodic timer in which we monitor number of rx
packets received. Using this count we decide bus width/rx_level.
We send this throughput level to cnss-daemon so that daemon can
dynamically set tcp delay ack value based on current receive
traffic situation to improve tcp performace. Added ini item to
enable this feature.
CRs-Fixed: 763246
Change-Id: I61f8a55ec9215a8fe86433d9f34a8ee7082a04bb
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index f269ca6..f789725 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -1531,6 +1531,10 @@
#define CFG_MULTICAST_HOST_FW_MSGS_MAX (1)
#define CFG_MULTICAST_HOST_FW_MSGS_DEFAULT (1)
+#define CFG_ENABLE_TCP_DELACK_NAME "gEnableDelAck"
+#define CFG_ENABLE_TCP_DELACK_MIN (0)
+#define CFG_ENABLE_TCP_DELACK_MAX (1)
+#define CFG_ENABLE_TCP_DELACK_DEFAULT (1)
/* In cfg.dat 1=1MBPS, 2=2MBPS, 3=5_5MBPS, 4=11MBPS, 5=6MBPS, 6=9MBPS,
* 7=12MBPS, 8=18MBPS, 9=24MBPS. But 6=9MBPS and 8=18MBPS are not basic
@@ -2270,6 +2274,21 @@
#define CFG_ROAMING_DFS_CHANNEL_MAX (1)
#define CFG_ROAMING_DFS_CHANNEL_DEFAULT (1)
+#define CFG_TCP_DELACK_COMPUTE_INTERVAL "gTcpDelAckComputeInterval"
+#define CFG_TCP_DELACK_COMPUTE_INTERVAL_DEFAULT ( 2000 )
+#define CFG_TCP_DELACK_COMPUTE_INTERVAL_MIN ( 1000 )
+#define CFG_TCP_DELACK_COMPUTE_INTERVAL_MAX ( 10000 )
+
+#define CFG_TCP_DELACK_THRESHOLD_HIGH "gTcpDelAckThresholdHigh"
+#define CFG_TCP_DELACK_THRESHOLD_HIGH_DEFAULT ( 17000 )
+#define CFG_TCP_DELACK_THRESHOLD_HIGH_MIN ( 1000 )
+#define CFG_TCP_DELACK_THRESHOLD_HIGH_MAX ( 25000 )
+
+#define CFG_TCP_DELACK_THRESHOLD_LOW "gTcpDelAckThresholdLow"
+#define CFG_TCP_DELACK_THRESHOLD_LOW_DEFAULT ( 12000 )
+#define CFG_TCP_DELACK_THRESHOLD_LOW_MIN ( 0 )
+#define CFG_TCP_DELACK_THRESHOLD_LOW_MAX ( 25000 )
+
#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
//Enable WLAN Logging to app space
@@ -3065,6 +3084,9 @@
v_U32_t cfgBtcCriticalHidnSniffBlkGuidance;
v_U32_t cfgBtcA2dpTxQueueThold;
v_U32_t cfgBtcOppTxQueueThold;
+ v_U32_t tcpDelAckComputeInterval;
+ v_U32_t tcpDelAckThresholdHigh;
+ v_U32_t tcpDelAckThresholdLow;
#ifdef WLAN_FEATURE_11W
v_U32_t pmfSaQueryMaxRetries;
@@ -3119,6 +3141,7 @@
v_U16_t rps_mask;
v_BOOL_t fEnableWifiConfig;
v_BOOL_t crash_inject_enabled;
+ v_U32_t enable_delack;
} hdd_config_t;
/*---------------------------------------------------------------------------
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index ecaab10..b037679 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1141,6 +1141,7 @@
#endif
/* Flag to ensure PSB is configured through framework */
v_U8_t psbChanged;
+ v_ULONG_t prev_rx_packets;
/* UAPSD psb value configured through framework */
v_U8_t configuredPsb;
v_BOOL_t is_roc_inprogress;
@@ -1563,8 +1564,26 @@
/* work queue to defer mac spoofing */
struct delayed_work spoof_mac_addr_work;
+
+ vos_timer_t delack_timer;
+ struct mutex cur_rx_level_lock;
+ v_U32_t cur_rx_level;
+ v_U64_t prev_rx;
+ v_ULONG_t mode;
};
+typedef enum {
+ TP_IND_LOW = 1,
+ TP_IND_MEDIUM,
+ TP_IND_HIGH,
+}TP_IND_TYPE;
+
+/* Use to notify the TDLS or BTCOEX is mode enable */
+typedef enum
+{
+ WLAN_TDLS_MODE,
+ WLAN_BTCOEX_MODE,
+} WLAN_MODE_TYPE;
#define WLAN_HDD_IS_LOAD_IN_PROGRESS(pHddCtx) \
(pHddCtx->isLoadUnloadInProgress & WLAN_HDD_LOAD_IN_PROGRESS)
@@ -1726,6 +1745,25 @@
#endif
int hdd_wmmps_helper(hdd_adapter_t *pAdapter, tANI_U8 *ptr);
+/*
+ * start/stop bandwidth compute timer, Based on which tcp delack
+ * value will be configured
+ */
+void hdd_manage_delack_timer(hdd_context_t *pHddCtx);
+
+void hdd_update_prev_rx_packet_count(hdd_context_t *pHddCtx);
+void hdd_start_delack_timer(hdd_context_t *pHddCtx);
+void hdd_set_default_stop_delack_timer(hdd_context_t *pHddCtx);
+v_U8_t hdd_get_total_sessions(hdd_context_t *pHddCtx);
+void hdd_set_delack_value(hdd_context_t *pHddCtx, v_U32_t next_rx_level);
+
+/*
+ * Calculate the packet channel bandwidth and send notification to cnss demon
+ */
+void hdd_request_tcp_delack(hdd_context_t *pHddCtx,
+ uint64_t rx_packets);
+void hdd_tcp_delack_compute_function(void *priv);
+
#ifdef FEATURE_WLAN_BATCH_SCAN
/**---------------------------------------------------------------------------
diff --git a/CORE/HDD/inc/wlan_hdd_softap_tx_rx.h b/CORE/HDD/inc/wlan_hdd_softap_tx_rx.h
index 249dda1..d7c23ec 100644
--- a/CORE/HDD/inc/wlan_hdd_softap_tx_rx.h
+++ b/CORE/HDD/inc/wlan_hdd_softap_tx_rx.h
@@ -64,6 +64,17 @@
-------------------------------------------------------------------------*/
/**============================================================================
+ @brief hdd_softap_get_connected_sta() - Function to get numbeer of connected
+ stations with softap
+
+ @param pHostapdAdapter : [in] pointer to saftap adapter
+
+ @return : Number of connected peer with softap
+ ===========================================================================*/
+
+v_U8_t hdd_softap_get_connected_sta(hdd_adapter_t *pHostapdAdapter);
+
+/**============================================================================
@brief hdd_softap_hard_start_xmit() - Function registered with the Linux OS for
transmitting packets
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
index 4956bb4..40716c8 100644
--- a/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -675,6 +675,8 @@
MAC_ADDR_ARRAY(wrqu.ap_addr.sa_data));
hdd_SendUpdateBeaconIEsEvent(pAdapter, pCsrRoamInfo);
+ hdd_manage_delack_timer(pHddCtx);
+
/* Send IWEVASSOCRESPIE Event if WLAN_FEATURE_CIQ_METRICS is Enabled Or
* Send IWEVASSOCRESPIE Event if WLAN_FEATURE_VOWIFI_11R is Enabled
* and fFTEnable is TRUE */
@@ -705,6 +707,8 @@
pr_info("wlan: disconnected\n");
type = WLAN_STA_DISASSOC_DONE_IND;
memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
+
+ hdd_manage_delack_timer(pHddCtx);
}
hdd_dump_concurrency_info(pHddCtx);
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index 9e7c6e3..7263728 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -3398,6 +3398,27 @@
CFG_BTC_STATIC_OPP_WLAN_IDLE_BT_LEN_MIN,
CFG_BTC_STATIC_OPP_WLAN_IDLE_BT_LEN_MAX ),
+ REG_VARIABLE( CFG_TCP_DELACK_COMPUTE_INTERVAL, WLAN_PARAM_Integer,
+ hdd_config_t, tcpDelAckComputeInterval,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_TCP_DELACK_COMPUTE_INTERVAL_DEFAULT,
+ CFG_TCP_DELACK_COMPUTE_INTERVAL_MIN,
+ CFG_TCP_DELACK_COMPUTE_INTERVAL_MAX),
+
+ REG_VARIABLE( CFG_TCP_DELACK_THRESHOLD_HIGH, WLAN_PARAM_Integer,
+ hdd_config_t, tcpDelAckThresholdHigh,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_TCP_DELACK_THRESHOLD_HIGH_DEFAULT,
+ CFG_TCP_DELACK_THRESHOLD_HIGH_MIN,
+ CFG_TCP_DELACK_THRESHOLD_HIGH_MAX ),
+
+ REG_VARIABLE( CFG_TCP_DELACK_THRESHOLD_LOW, WLAN_PARAM_Integer,
+ hdd_config_t, tcpDelAckThresholdLow,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_TCP_DELACK_THRESHOLD_LOW_DEFAULT,
+ CFG_TCP_DELACK_THRESHOLD_LOW_MIN,
+ CFG_TCP_DELACK_THRESHOLD_LOW_MAX ),
+
REG_VARIABLE( CFG_LINK_FAIL_TIMEOUT_NAME , WLAN_PARAM_Integer,
hdd_config_t, linkFailTimeout,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
@@ -3460,6 +3481,13 @@
CFG_ENABLE_CRASH_INJECT_DEFAULT,
CFG_ENABLE_CRASH_INJECT_MIN,
CFG_ENABLE_CRASH_INJECT_MAX),
+
+ REG_VARIABLE( CFG_ENABLE_TCP_DELACK_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, enable_delack,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_TCP_DELACK_DEFAULT,
+ CFG_ENABLE_TCP_DELACK_MIN,
+ CFG_ENABLE_TCP_DELACK_MAX ),
};
/*
@@ -3888,6 +3916,18 @@
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [toggleArpBDRates] Value = [%u] ", pHddCtx->cfg_ini->toggleArpBDRates);
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [ExtScanConcMode] Value = [%u] ", pHddCtx->cfg_ini->cfgExtScanConcMode);
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableForceTargetAssert] Value = [%u] ", pHddCtx->cfg_ini->crash_inject_enabled);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+ "Name = [gTcpDelAckComputeInterval] Value = [%u] ",
+ pHddCtx->cfg_ini->tcpDelAckComputeInterval);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+ "Name = [gTcpDelAckThresholdHigh] Value = [%u] ",
+ pHddCtx->cfg_ini->tcpDelAckThresholdHigh);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+ "Name = [gTcpDelAckThresholdLow] Value = [%u] ",
+ pHddCtx->cfg_ini->tcpDelAckThresholdLow);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+ "Name = [gEnableDelAck] Value = [%u] ",
+ pHddCtx->cfg_ini->enable_delack);
}
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 0125dc6..8a1ab9c 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -18033,6 +18033,9 @@
}
}
}
+ /* stop TCP delack timer if TDLS is enable */
+ set_bit(WLAN_TDLS_MODE, &pHddCtx->mode);
+ hdd_manage_delack_timer(pHddCtx);
}
break;
case NL80211_TDLS_DISABLE_LINK:
@@ -18174,6 +18177,11 @@
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: TDLS Peer Station doesn't exist.", __func__);
}
+ if (numCurrTdlsPeers == 0) {
+ /* start TCP delack timer if TDLS is disable */
+ clear_bit(WLAN_TDLS_MODE, &pHddCtx->mode);
+ hdd_manage_delack_timer(pHddCtx);
+ }
}
break;
case NL80211_TDLS_TEARDOWN:
diff --git a/CORE/HDD/src/wlan_hdd_early_suspend.c b/CORE/HDD/src/wlan_hdd_early_suspend.c
index 63f264a..b8eaba8 100644
--- a/CORE/HDD/src/wlan_hdd_early_suspend.c
+++ b/CORE/HDD/src/wlan_hdd_early_suspend.c
@@ -1921,6 +1921,10 @@
vos_flush_delayed_work(&pHddCtx->spoof_mac_addr_work);
hdd_reset_all_adapters(pHddCtx);
+
+ /* set default value of Tcp delack and stop timer */
+ hdd_set_default_stop_delack_timer(pHddCtx);
+
/* DeRegister with platform driver as client for Suspend/Resume */
vosStatus = hddDeregisterPmOps(pHddCtx);
if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index e3494ae..3cce315 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -1087,6 +1087,8 @@
}
}
#endif
+ hdd_manage_delack_timer(pHddCtx);
+
pScanInfo = &pHddCtx->scan_info;
// Lets do abort scan to ensure smooth authentication for client
if ((pScanInfo != NULL) && pScanInfo->mScanPending)
@@ -1151,6 +1153,7 @@
hddLog(LOGE, "%s: failed to update Beacon interval %d",
__func__, vos_status);
}
+ hdd_manage_delack_timer(pHddCtx);
break;
case eSAP_WPS_PBC_PROBE_REQ_EVENT:
{
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 6795ca1..cfd03d2 100755
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -7072,6 +7072,7 @@
INIT_DELAYED_WORK(&pAdapter->roc_work,
hdd_p2p_roc_work_queue);
}
+
break;
}
case WLAN_HDD_MONITOR:
@@ -8761,6 +8762,17 @@
"%s: Cannot deallocate Traffic monitor timer", __func__);
}
+ if (VOS_TIMER_STATE_RUNNING ==
+ vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
+ vos_timer_stop(&pHddCtx->delack_timer);
+ }
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
+ &pHddCtx->delack_timer))) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Cannot deallocate Bus bandwidth timer", __func__);
+ }
+
//Disable IMPS/BMPS as we do not want the device to enter any power
//save mode during shutdown
sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
@@ -9261,6 +9273,14 @@
nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
break;
+ case WLAN_SVC_WLAN_TP_IND:
+ ani_hdr->length = len;
+ nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)
+ + len));
+ nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
+ memcpy(nl_data, data, len);
+ skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
+ break;
case WLAN_MSG_RPS_ENABLE_IND:
ani_hdr->length = len;
nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
@@ -9280,7 +9300,68 @@
return;
}
+/**
+ * hdd_request_tcp_delack() - Find the Delack value based on RX packet
+ * @pHddCtx: Valid Global HDD context pointer
+ * @rx_packets: Number of RX packet in perticular time
+ *
+ * Based on the RX packet this function calculate next value of tcp delack.
+ * This function compare rx packet value to high and low threshold limit.
+ *
+ * Return: void
+ */
+void hdd_request_tcp_delack(hdd_context_t *pHddCtx, uint64_t rx_packets)
+{
+ /* average of rx_packets and prev_rx is taken so that
+ bus width doesnot fluctuate much */
+ uint64_t temp_rx = (rx_packets + pHddCtx->prev_rx)/2;
+ TP_IND_TYPE next_rx_level = pHddCtx->cur_rx_level;
+ pHddCtx->prev_rx = rx_packets;
+ if (temp_rx > pHddCtx->cfg_ini->tcpDelAckThresholdHigh)
+ next_rx_level = TP_IND_HIGH;
+ else if (temp_rx <= pHddCtx->cfg_ini->tcpDelAckThresholdLow)
+ next_rx_level = TP_IND_LOW;
+
+ hdd_set_delack_value(pHddCtx, next_rx_level);
+}
+
+#define HDD_BW_GET_DIFF(x, y) ((x) >= (y) ? (x) - (y) : (ULONG_MAX - (y) + (x)))
+
+/**
+ * hdd_tcp_delack_compute_function() - get link status
+ * @priv: Valid Global HDD context pointer
+ *
+ * This function find number of RX packet during timer life span.
+ * It request tcp delack with number of RX packet and re-configure delack timer
+ * for tcpDelAckComputeInterval timer interval.
+ *
+ * Return: void
+ */
+void hdd_tcp_delack_compute_function(void *priv)
+{
+ hdd_context_t *pHddCtx = (hdd_context_t *)priv;
+ hdd_adapter_t *pAdapter = NULL;
+ v_U32_t rx_packets = 0;
+ hdd_adapter_list_node_t *pAdapterNode = NULL;
+ VOS_STATUS status = 0;
+
+ for (status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
+ NULL != pAdapterNode && VOS_STATUS_SUCCESS == status;
+ status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pAdapterNode)) {
+ if ((pAdapter = pAdapterNode->pAdapter) == NULL)
+ continue;
+
+ rx_packets += HDD_BW_GET_DIFF(pAdapter->stats.rx_packets,
+ pAdapter->prev_rx_packets);
+ pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
+ }
+
+ hdd_request_tcp_delack(pHddCtx, rx_packets);
+
+ vos_timer_start(&pHddCtx->delack_timer,
+ pHddCtx->cfg_ini->tcpDelAckComputeInterval);
+}
/**---------------------------------------------------------------------------
@@ -10497,6 +10578,10 @@
}
wlan_hdd_cfg80211_nan_init(pHddCtx);
+ mutex_init(&pHddCtx->cur_rx_level_lock);
+ vos_timer_init(&pHddCtx->delack_timer, VOS_TIMER_TYPE_SW,
+ hdd_tcp_delack_compute_function,(void *)pHddCtx);
+
#ifdef WLAN_FEATURE_EXTSCAN
sme_EXTScanRegisterCallback(pHddCtx->hHal,
wlan_hdd_cfg80211_extscan_callback,
@@ -11403,6 +11488,7 @@
* --------------------------------------------------------------------------*/
void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
{
+
switch (mode) {
case VOS_STA_MODE:
case VOS_P2P_CLIENT_MODE:
@@ -11615,6 +11701,178 @@
return status;
}
+/**
+ * hdd_get_total_sessions() - provide total number of active sessions
+ * @pHddCtx: Valid Global HDD context pointer
+ *
+ * This function iterates through pAdaptors and find the number of all active
+ * sessions. This active sessions includes connected sta, p2p client and number
+ * of client connected to sap/p2p go.
+ *
+ * Return: Total number of active sessions.
+ */
+v_U8_t hdd_get_total_sessions(hdd_context_t *pHddCtx)
+{
+ v_U8_t active_session = 0;
+ hdd_station_ctx_t *pHddStaCtx;
+ hdd_adapter_list_node_t *pAdapterNode, *pNext;
+ hdd_adapter_t *pAdapter;
+ VOS_STATUS status;
+
+ status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
+ while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
+ pAdapter = pAdapterNode->pAdapter;
+ switch (pAdapter->device_mode) {
+ case VOS_STA_MODE:
+ case VOS_P2P_CLIENT_MODE:
+ pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ if(eConnectionState_Associated == pHddStaCtx->conn_info.connState)
+ active_session += 1;
+ break;
+ case VOS_STA_SAP_MODE:
+ case VOS_P2P_GO_MODE:
+ active_session += hdd_softap_get_connected_sta(pAdapter);
+ break;
+ default:
+ break;
+ }
+
+ status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
+ pAdapterNode = pNext;
+ }
+
+ return active_session;
+}
+
+/**
+ * hdd_set_delack_value() - Set delack value
+ * @pHddCtx: Valid Global HDD context pointer
+ * @next_rx_level: Value to set for delack
+ *
+ * This function compare present value and next value of delack. If the both
+ * are diffrent then it sets next value .
+ *
+ * Return: void.
+ */
+void hdd_set_delack_value(hdd_context_t *pHddCtx, v_U32_t next_rx_level)
+{
+ if (pHddCtx->cur_rx_level != next_rx_level) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
+ "%s: TCP DELACK trigger level %d",
+ __func__, next_rx_level);
+ mutex_lock(&pHddCtx->cur_rx_level_lock);
+ pHddCtx->cur_rx_level = next_rx_level;
+ mutex_unlock(&pHddCtx->cur_rx_level_lock);
+ wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND, &next_rx_level,
+ sizeof(next_rx_level));
+ }
+}
+
+/**
+ * hdd_set_default_stop_delack_timer() - Start delack timer
+ * @pHddCtx: Valid Global HDD context pointer
+ *
+ * This function stop delack timer and set delack value to default..
+ *
+ * Return: void.
+ */
+
+void hdd_set_default_stop_delack_timer(hdd_context_t *pHddCtx)
+{
+ if (VOS_TIMER_STATE_RUNNING !=
+ vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
+ "%s: Can not stop timer", __func__);
+ return;
+ }
+
+ vos_timer_stop(&pHddCtx->delack_timer);
+ hdd_set_delack_value(pHddCtx, TP_IND_LOW);
+}
+
+/**
+ * hdd_start_delack_timer() - Start delack timer
+ * @pHddCtx: Valid Global HDD context pointer
+ *
+ * This function starts the delack timer for tcpDelAckComputeInterval time
+ * interval.The default timer value is 2 second.
+ *
+ * Return: void.
+ */
+void hdd_start_delack_timer(hdd_context_t *pHddCtx)
+{
+ if (VOS_TIMER_STATE_RUNNING ==
+ vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
+ "%s: Timer is already running", __func__);
+ return;
+ }
+
+ vos_timer_start(&pHddCtx->delack_timer,
+ pHddCtx->cfg_ini->tcpDelAckComputeInterval);
+}
+
+/**
+ * hdd_update_prev_rx_packet_count() - Update previous rx packet count
+ * @pHddCtx: Valid Global HDD context pointer
+ *
+ * This function updates the prev_rx_packets count from the corresponding
+ * pAdapter states. This prev_rx_packets will diffed with the packet count
+ * at the end of delack timer. That can give number of RX packet is spacific
+ * time.
+ *
+ * Return: void.
+ */
+void hdd_update_prev_rx_packet_count(hdd_context_t *pHddCtx)
+{
+ hdd_adapter_list_node_t *pAdapterNode, *pNext;
+ hdd_adapter_t *pAdapter;
+ VOS_STATUS status;
+
+ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
+ while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
+ pAdapter = pAdapterNode->pAdapter;
+ pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
+ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+ pAdapterNode = pNext;
+ }
+}
+
+/**
+ * hdd_manage_delack_timer() - start\stop delack timer
+ * @pHddCtx: Valid Global HDD context pointer
+ *
+ * This function check the number of concerent session present, it starts the
+ * delack timer if only one session is present.
+ * In the case of BT_COEX and TDLS mode it blindly stop delack functionality.
+ *
+ * Return: void.
+ */
+void hdd_manage_delack_timer(hdd_context_t *pHddCtx)
+{
+ uint8_t sessions;
+
+ if (!pHddCtx->cfg_ini->enable_delack) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
+ "%s: TCP DELACK is not enabled", __func__);
+ return;
+ }
+
+ /* Blindly stop timer of BTCOEX and TDLS Session is up */
+ if (pHddCtx->mode != 0) {
+ hdd_set_default_stop_delack_timer(pHddCtx);
+ return;
+ }
+
+ sessions = hdd_get_total_sessions(pHddCtx);
+ if (sessions == 1) {
+ hdd_update_prev_rx_packet_count(pHddCtx);
+ hdd_start_delack_timer(pHddCtx);
+ } else {
+ hdd_set_default_stop_delack_timer(pHddCtx);
+ }
+}
+
/**---------------------------------------------------------------------------
*
* \brief wlan_hdd_init_channels
diff --git a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
index 3bcf17f..b4c919c 100644
--- a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
+++ b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
@@ -278,6 +278,41 @@
return status;
}
+/**
+ * hdd_softap_get_connected_sta() - provide number of connected STA
+ * @pHostapdAdapter: pAdapter for SAP
+ *
+ * This function is invoked for SAP mode to get connected STA.
+ *
+ * Return: Total number of connected STA to SAP.
+ */
+v_U8_t hdd_softap_get_connected_sta(hdd_adapter_t *pHostapdAdapter)
+{
+ v_U8_t i, sta_ct = 0;
+ v_CONTEXT_t pVosContext = NULL;
+ ptSapContext pSapCtx = NULL;
+
+ pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
+ pSapCtx = VOS_GET_SAP_CB(pVosContext);
+ if (pSapCtx == NULL) {
+ VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO,
+ FL("psapCtx is NULL"));
+ goto error;
+ }
+
+ spin_lock_bh(&pSapCtx->staInfo_lock);
+ // get stations associated with SAP
+ for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
+ if (pSapCtx->aStaInfo[i].isUsed &&
+ (!vos_is_macaddr_broadcast(&pSapCtx->aStaInfo[i].macAddrSTA)))
+ sta_ct++;
+ }
+ spin_unlock_bh( &pSapCtx->staInfo_lock );
+
+error:
+ return sta_ct;
+}
+
/**============================================================================
@brief hdd_softap_hard_start_xmit() - Function registered with the Linux OS for
transmitting packets. There are 2 versions of this function. One that uses
diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c
index 0b0f418..e548cf9 100644
--- a/CORE/HDD/src/wlan_hdd_tdls.c
+++ b/CORE/HDD/src/wlan_hdd_tdls.c
@@ -802,6 +802,7 @@
hdd_context_t *pHddCtx;
u16 connectedTdlsPeers;
hddTdlsPeer_t *currPeer;
+ tANI_U16 numCurrTdlsPeers = 0;
ENTER();
if ((NULL == data) || (indType < 0))
@@ -887,6 +888,9 @@
}
}
}
+ /* stop TCP delack timer if BtCoex is enable */
+ set_bit(WLAN_BTCOEX_MODE, &pHddCtx->mode);
+ hdd_manage_delack_timer(pHddCtx);
}
/* BtCoex notification type enabled, Enable TDLS */
else if (indType == SIR_COEX_IND_TYPE_TDLS_ENABLE)
@@ -903,7 +907,15 @@
pHddCtx->is_tdls_btc_enabled = TRUE;
wlan_hdd_tdls_set_mode(pHddCtx, pHddCtx->tdls_mode_last, FALSE);
}
- }
+
+ clear_bit(WLAN_BTCOEX_MODE, &pHddCtx->mode);
+ numCurrTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter);
+ if(numCurrTdlsPeers == 0) {
+ /* start delack timer if BtCoex is disable and tdls is not present */
+ hdd_manage_delack_timer(pHddCtx);
+ }
+ }
+
EXIT();
return;
}
diff --git a/CORE/SVC/external/wlan_nlink_common.h b/CORE/SVC/external/wlan_nlink_common.h
index 75d0625..6ffcee6 100644
--- a/CORE/SVC/external/wlan_nlink_common.h
+++ b/CORE/SVC/external/wlan_nlink_common.h
@@ -89,6 +89,7 @@
#define WLAN_SVC_IFACE_NUM_QUEUES 6
#define WLAN_SVC_SAP_RESTART_IND 0x108
+#define WLAN_SVC_WLAN_TP_IND 0x109
// Event data for WLAN_BTC_QUERY_STATE_RSP & WLAN_STA_ASSOC_DONE_IND
typedef struct
{