wlan: Refactoring IBSS data path.
Added init/deinit tx/rx api for IBSS network.
Added support to register specific hard start xmit
API explicitly for IBSS and also call IBSS specific
init API in __wlan_hdd_cfg80211_change_iface when
interface is adhoc type. Also added snapshot of IBSS
queues in hdd_wmm_tx_snapshot.
Change-Id: Id7f7544d3062ea5242c04b5b0d4a4b2f1f806515
CRs-Fixed: 785358
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 2954310..3d4550d 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1496,6 +1496,7 @@
VOS_STATUS hdd_is_any_session_connected(hdd_context_t *pHddCtx);
void hdd_ipv4_notifier_work_queue(struct work_struct *work);
v_BOOL_t hdd_isConnectionInProgress( hdd_context_t *pHddCtx);
+void hdd_set_ibss_ops(hdd_adapter_t *pAdapter);
#ifdef WLAN_FEATURE_PACKET_FILTERING
int wlan_hdd_setIPv6Filter(hdd_context_t *pHddCtx, tANI_U8 filterType, tANI_U8 sessionId);
#endif
diff --git a/CORE/HDD/inc/wlan_hdd_tx_rx.h b/CORE/HDD/inc/wlan_hdd_tx_rx.h
index 3394afa..95b3eae 100644
--- a/CORE/HDD/inc/wlan_hdd_tx_rx.h
+++ b/CORE/HDD/inc/wlan_hdd_tx_rx.h
@@ -176,6 +176,26 @@
extern struct net_device_stats* hdd_stats(struct net_device *dev);
/**============================================================================
+ @brief hdd_ibss_init_tx_rx() - Init function to initialize Tx/RX
+ modules in HDD
+
+ @param pAdapter : [in] pointer to adapter context
+ @return : VOS_STATUS_E_FAILURE if any errors encountered
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+extern void hdd_ibss_init_tx_rx( hdd_adapter_t *pAdapter );
+
+/**============================================================================
+ @brief hdd_ibss_deinit_tx_rx() - Deinit function to clean up Tx/RX
+ modules in HDD
+
+ @param pAdapter : [in] pointer to adapter context..
+ @return : VOS_STATUS_E_FAILURE if any errors encountered.
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+extern VOS_STATUS hdd_ibss_deinit_tx_rx( hdd_adapter_t *pAdapter );
+
+/**============================================================================
@brief hdd_init_tx_rx() - Init function to initialize Tx/RX
modules in HDD
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
index 10437c4..e76c2c1 100644
--- a/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -745,6 +745,10 @@
VOS_STATUS hdd_ibss_deinit_tx_rx_sta ( hdd_adapter_t *pAdapter, v_U8_t STAId )
{
+ v_U8_t ac;
+ /**Track whether OS TX queue has been disabled.*/
+ v_BOOL_t txSuspended[NUM_TX_QUEUES];
+ v_U8_t tlAC;
v_U8_t i;
hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
hdd_ibss_peer_info_t *pPeerInfo;
@@ -755,6 +759,7 @@
"%s: HDD station context NULL ",__func__);
return VOS_STATUS_E_FAILURE;
}
+
pPeerInfo = &pHddStaCtx->ibss_peer_info;
if (FALSE == pPeerInfo->ibssStaInfo[STAId].isUsed)
{
@@ -764,8 +769,33 @@
}
hdd_flush_ibss_tx_queues(pAdapter, STAId);
+
+ for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
+ {
+ tlAC = hdd_QdiscAcToTlAC[ac];
+ txSuspended[ac] = pPeerInfo->ibssStaInfo[STAId].txSuspended[tlAC];
+ }
+
vos_mem_zero(&pPeerInfo->ibssStaInfo[STAId], sizeof(hdd_ibss_station_info_t));
+ /* re-init hdd list, since netdev can still open adapter until
+ * driver gets unloaded
+ */
+ for (i = 0; i < NUM_TX_QUEUES; i ++)
+ {
+ hdd_list_init(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i],
+ HDD_TX_QUEUE_MAX_LEN);
+ }
+
+ for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
+ {
+ if (txSuspended[ac])
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
+ "%s: TX queue re-enabled", __func__);
+ netif_wake_subqueue(pAdapter->dev, ac);
+ }
+ }
return VOS_STATUS_SUCCESS;
}
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 39cbac9..da39e18 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -7915,6 +7915,8 @@
hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
pAdapter->device_mode = WLAN_HDD_IBSS;
wdev->iftype = type;
+ hdd_set_ibss_ops( pAdapter );
+ hdd_ibss_init_tx_rx( pAdapter );
break;
case NL80211_IFTYPE_AP:
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 885200d..2036505 100755
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -6032,6 +6032,15 @@
#endif
}
+void hdd_set_ibss_ops( hdd_adapter_t *pAdapter )
+{
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
+ wlan_drv_ops.ndo_start_xmit = hdd_ibss_hard_start_xmit;
+ #else
+ pAdapter->dev->hard_start_xmit = hdd_ibss_hard_start_xmit;
+ #endif
+}
+
static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
{
struct net_device *pWlanDev = NULL;
@@ -6237,12 +6246,13 @@
status = VOS_STATUS_E_FAILURE;
goto error_register_wext;
}
+
//Safe to register the hard_start_xmit function again
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
- wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
-#else
- pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
-#endif
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
+ wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
+ #else
+ pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
+ #endif
//Set the Connection State to Not Connected
hddLog(VOS_TRACE_LEVEL_INFO,
@@ -6334,6 +6344,14 @@
ENTER();
switch ( pAdapter->device_mode )
{
+ case WLAN_HDD_IBSS:
+ {
+ if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
+ {
+ hdd_ibss_deinit_tx_rx( pAdapter );
+ clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
+ }
+ }
case WLAN_HDD_INFRA_STATION:
case WLAN_HDD_P2P_CLIENT:
case WLAN_HDD_P2P_DEVICE:
@@ -7398,6 +7416,9 @@
hdd_deinit_tx_rx(pAdapter);
+ if(pAdapter->device_mode == WLAN_HDD_IBSS )
+ hdd_ibss_deinit_tx_rx(pAdapter);
+
wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
diff --git a/CORE/HDD/src/wlan_hdd_tx_rx.c b/CORE/HDD/src/wlan_hdd_tx_rx.c
index 10f76b8..efbd607 100644
--- a/CORE/HDD/src/wlan_hdd_tx_rx.c
+++ b/CORE/HDD/src/wlan_hdd_tx_rx.c
@@ -1381,6 +1381,105 @@
}
/**============================================================================
+ @brief hdd_ibss_init_tx_rx() - Init function to initialize Tx/RX
+ modules in HDD
+
+ @param pAdapter : [in] pointer to adapter context
+ @return : VOS_STATUS_E_FAILURE if any errors encountered
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+void hdd_ibss_init_tx_rx( hdd_adapter_t *pAdapter )
+{
+ v_U8_t i;
+ v_U8_t STAId = 0;
+ hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
+ hdd_ibss_peer_info_t *pPeerInfo = &pHddStaCtx->ibss_peer_info;
+ v_U8_t pACWeights[] = {
+ HDD_SOFTAP_BK_WEIGHT_DEFAULT,
+ HDD_SOFTAP_BE_WEIGHT_DEFAULT,
+ HDD_SOFTAP_VI_WEIGHT_DEFAULT,
+ HDD_SOFTAP_VO_WEIGHT_DEFAULT
+ };
+
+ pAdapter->isVosOutOfResource = VOS_FALSE;
+ pAdapter->isVosLowResource = VOS_FALSE;
+
+ // Since SAP model is used for IBSS also. Using same queue length as in SAP.
+ pAdapter->aTxQueueLimit[WLANTL_AC_BK] = HDD_SOFTAP_TX_BK_QUEUE_MAX_LEN;
+ pAdapter->aTxQueueLimit[WLANTL_AC_BE] = HDD_SOFTAP_TX_BE_QUEUE_MAX_LEN;
+ pAdapter->aTxQueueLimit[WLANTL_AC_VI] = HDD_SOFTAP_TX_VI_QUEUE_MAX_LEN;
+ pAdapter->aTxQueueLimit[WLANTL_AC_VO] = HDD_SOFTAP_TX_VO_QUEUE_MAX_LEN;
+
+ for (STAId = 0; STAId < HDD_MAX_NUM_IBSS_STA; STAId++)
+ {
+ vos_mem_zero(&pPeerInfo->ibssStaInfo[STAId], sizeof(hdd_ibss_station_info_t));
+ for (i = 0; i < NUM_TX_QUEUES; i ++)
+ {
+ hdd_list_init(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
+ }
+ }
+
+ /* Update the AC weights suitable for SoftAP mode of operation */
+ WLANTL_SetACWeights((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pACWeights);
+}
+
+/**============================================================================
+ @brief hdd_ibss_deinit_tx_rx() - Deinit function to clean up Tx/RX
+ modules in HDD
+
+ @param pAdapter : [in] pointer to adapter context..
+ @return : VOS_STATUS_E_FAILURE if any errors encountered.
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+VOS_STATUS hdd_ibss_deinit_tx_rx( hdd_adapter_t *pAdapter )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ v_U8_t STAId = 0;
+ hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
+ hdd_ibss_peer_info_t * pPeerInfo = &pHddStaCtx->ibss_peer_info;
+ hdd_list_node_t *anchor = NULL;
+ skb_list_node_t *pktNode = NULL;
+ struct sk_buff *skb = NULL;
+ v_SINT_t i = -1;
+
+ for (STAId = 0; STAId < HDD_MAX_NUM_IBSS_STA; STAId++)
+ {
+ if (VOS_FALSE == pPeerInfo->ibssStaInfo[STAId].isUsed)
+ {
+ continue;
+ }
+ for (i = 0; i < NUM_TX_QUEUES; i ++)
+ {
+ spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i].lock);
+ while (true)
+ {
+ status = hdd_list_remove_front ( &pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i], &anchor);
+
+ if (VOS_STATUS_E_EMPTY != status)
+ {
+ //If success then we got a valid packet from some AC
+ pktNode = list_entry(anchor, skb_list_node_t, anchor);
+ skb = pktNode->skb;
+ ++pAdapter->stats.tx_dropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
+ kfree_skb(skb);
+ continue;
+ }
+
+ //current list is empty
+ break;
+ }
+ pPeerInfo->ibssStaInfo[STAId].txSuspended[i] = VOS_FALSE;
+ spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i].lock);
+ }
+ }
+ pAdapter->isVosLowResource = VOS_FALSE;
+
+ return status;
+}
+
+/**============================================================================
@brief hdd_init_tx_rx() - Init function to initialize Tx/RX
modules in HDD
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index f7535f5..3d5f265 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -6884,6 +6884,8 @@
int i = 0, j = 0;
v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ hdd_ibss_peer_info_t *pPeerInfo;
for ( i=0; i< NUM_TX_QUEUES; i++)
{
@@ -6919,6 +6921,37 @@
}
spin_unlock_bh(&pSapCtx->staInfo_lock);
+ if(pHddStaCtx == NULL){
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ FL("pHddStaCtx is NULL"));
+ return;
+ }
+
+ pPeerInfo = &pHddStaCtx->ibss_peer_info;
+ if(pPeerInfo == NULL){
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ FL("ppeerinfo is NULL"));
+ return;
+ }
+
+ for(i =0; i< HDD_MAX_NUM_IBSS_STA; i++)
+ {
+ if(pPeerInfo->ibssStaInfo[i].isUsed)
+ {
+ hddLog(LOGE, "******IBSS STAIndex: %d*********", i);
+ for ( j=0; j< NUM_TX_QUEUES; j++)
+ {
+ spin_lock_bh(&pPeerInfo->ibssStaInfo[i].wmm_tx_queue[j].lock);
+ hddLog(LOGE, "HDD TxQueue Info For AC: %d Count: %d PrevAdress:%p, NextAddress:%p",
+ j, pPeerInfo->ibssStaInfo[i].wmm_tx_queue[j].count,
+ pPeerInfo->ibssStaInfo[i].wmm_tx_queue[j].anchor.prev,
+ pPeerInfo->ibssStaInfo[i].wmm_tx_queue[j].anchor.next);
+ spin_unlock_bh(&pPeerInfo->ibssStaInfo[i].wmm_tx_queue[j].lock);
+ }
+ }
+ }
+
+
}
static int __iw_set_var_ints_getnone(struct net_device *dev,
struct iw_request_info *info,
diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c
index 3b9761a..e6847b8 100644
--- a/CORE/TL/src/wlan_qct_tl.c
+++ b/CORE/TL/src/wlan_qct_tl.c
@@ -11061,9 +11061,11 @@
#ifdef FEATURE_WLAN_TDLS
if ((eSYSTEM_AP_ROLE == systemRole) ||
+ (eSYSTEM_STA_IN_IBSS_ROLE == systemRole) ||
(vos_concurrent_open_sessions_running()) || pTLCb->ucTdlsPeerCount)
#else
if ((eSYSTEM_AP_ROLE == systemRole) ||
+ (eSYSTEM_STA_IN_IBSS_ROLE == systemRole) ||
(vos_concurrent_open_sessions_running()))
#endif
{