diff options
| author | Leo Chang <schang@qca.qualcomm.com> | 2014-03-26 15:59:06 -0700 |
|---|---|---|
| committer | Akash Patel <c_akashp@qca.qualcomm.com> | 2014-03-27 09:22:10 -0700 |
| commit | 2c401a3e03b7bbedc5c1e8489cef7c29affd2517 (patch) | |
| tree | 51de1eb066c9569ae376eca1da134a01d2ea8ee9 | |
| parent | fb1506dc9076543d614253fee3b0256c0a22f9fc (diff) | |
qca-cld: Expand TX flow control to TDLS also
TX Flow control was only applicable for STA and IBSS interface.
It was enabled by STA ID based, but expand capability to support
TDLS also. Functionality will be controlled by session based.
Instead of peer based.
Change-Id: Ib8959078ede13e686cc67c481ab9542a77022ba7
CRs-fixed: 636987
| -rw-r--r-- | CORE/CLD_TXRX/TLSHIM/tl_shim.c | 58 | ||||
| -rw-r--r-- | CORE/CLD_TXRX/TLSHIM/tl_shim.h | 10 | ||||
| -rw-r--r-- | CORE/CLD_TXRX/TXRX/ol_tx_send.c | 1 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_main.h | 4 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_tx_rx.h | 14 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_assoc.c | 8 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_main.c | 20 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_tx_rx.c | 51 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/ol_txrx_osif_api.h | 3 | ||||
| -rw-r--r-- | CORE/TL/inc/wlan_qct_tl.h | 2 |
10 files changed, 130 insertions, 41 deletions
diff --git a/CORE/CLD_TXRX/TLSHIM/tl_shim.c b/CORE/CLD_TXRX/TLSHIM/tl_shim.c index 73c9e294796b..953b349a6d12 100644 --- a/CORE/CLD_TXRX/TLSHIM/tl_shim.c +++ b/CORE/CLD_TXRX/TLSHIM/tl_shim.c @@ -45,7 +45,9 @@ #include "adf_nbuf.h" #include "wma_api.h" #include "vos_utils.h" - +#ifdef QCA_LL_TX_FLOW_CT +#include "wdi_out.h" +#endif /* QCA_LL_TX_FLOW_CT */ #define ENTER() VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, "Enter:%s", __func__) #define TLSHIM_LOGD(args...) \ @@ -1609,6 +1611,10 @@ VOS_STATUS WLANTL_Close(void *vos_ctx) return VOS_STATUS_E_FAILURE; } +#ifdef QCA_LL_TX_FLOW_CT + adf_os_mem_free(tl_shim->session_flow_control); +#endif /* QCA_LL_TX_FLOW_CT */ + #ifdef FEATURE_WLAN_ESE vos_flush_work(&tl_shim->iapp_work.deferred_work); #endif @@ -1631,6 +1637,9 @@ VOS_STATUS WLANTL_Open(void *vos_ctx, WLANTL_ConfigInfoType *tl_cfg) struct txrx_tl_shim_ctx *tl_shim; VOS_STATUS status; u_int8_t i; +#ifdef QCA_LL_TX_FLOW_CT + int max_vdev; +#endif /* QCA_LL_TX_FLOW_CT */ ENTER(); status = vos_alloc_context(vos_ctx, VOS_MODULE_ID_TL, @@ -1656,11 +1665,6 @@ VOS_STATUS WLANTL_Open(void *vos_ctx, WLANTL_ConfigInfoType *tl_cfg) adf_os_spinlock_init(&tl_shim->sta_info[i].stainfo_lock); tl_shim->sta_info[i].flags = 0; INIT_LIST_HEAD(&tl_shim->sta_info[i].cached_bufq); -#ifdef QCA_LL_TX_FLOW_CT - tl_shim->sta_info[i].flowControl = NULL; - tl_shim->sta_info[i].sessionId = 0xFF; - tl_shim->sta_info[i].adpaterCtxt = NULL; -#endif /* QCA_LL_TX_FLOW_CT */ } INIT_WORK(&tl_shim->cache_flush_work, tl_shim_cache_flush_work); @@ -1673,6 +1677,23 @@ VOS_STATUS WLANTL_Open(void *vos_ctx, WLANTL_ConfigInfoType *tl_cfg) * vdevs to maintain tx callbacks per vdev. */ +#ifdef QCA_LL_TX_FLOW_CT + max_vdev = wdi_out_cfg_max_vdevs(((pVosContextType)vos_ctx)->cfg_ctx); + tl_shim->session_flow_control = adf_os_mem_alloc(NULL, + max_vdev * sizeof(struct tlshim_session_flow_Control)); + if (!tl_shim->session_flow_control) { + TLSHIM_LOGE("Failed to allocate memory for tx flow control"); + vos_free_context(vos_ctx, VOS_MODULE_ID_TL, tl_shim); + return VOS_STATUS_E_NOMEM; + } + + for (i = 0; i < max_vdev; i++) { + tl_shim->session_flow_control[i].flowControl = NULL; + tl_shim->session_flow_control[i].sessionId = 0xFF; + tl_shim->session_flow_control[i].adpaterCtxt = NULL; + } +#endif /* QCA_LL_TX_FLOW_CT */ + tl_shim->ip_checksum_offload = tl_cfg->ip_checksum_offload; tl_shim->delay_interval = tl_cfg->uDelayedTriggerFrmInt; tl_shim->enable_rxthread = tl_cfg->enable_rxthread; @@ -1786,7 +1807,9 @@ v_BOOL_t WLANTL_GetTxResource { struct ol_txrx_peer_t *peer = NULL; - if (!vos_context) { + /* If low watermark is zero, TX flow control is not enabled at all + * return TRUE by default */ + if ((!vos_context) || (!low_watermark)) { return VOS_TRUE; } @@ -1825,7 +1848,6 @@ v_BOOL_t WLANTL_GetTxResource void WLANTL_TXFlowControlCb ( void *tlContext, - v_U8_t peer_idx, v_U8_t sessionId, v_BOOL_t resume_tx ) @@ -1841,11 +1863,10 @@ void WLANTL_TXFlowControlCb return; } - if ((peer_idx < WLAN_MAX_STA_COUNT) && - (tl_shim->sta_info[peer_idx].sessionId == sessionId) && - (tl_shim->sta_info[peer_idx].flowControl)) { - flow_control_cb = tl_shim->sta_info[peer_idx].flowControl; - adpter_ctxt = tl_shim->sta_info[peer_idx].adpaterCtxt; + if ((tl_shim->session_flow_control[sessionId].sessionId == sessionId) && + (tl_shim->session_flow_control[sessionId].flowControl)) { + flow_control_cb = tl_shim->session_flow_control[sessionId].flowControl; + adpter_ctxt = tl_shim->session_flow_control[sessionId].adpaterCtxt; } if ((flow_control_cb) && (adpter_ctxt)) { @@ -1879,25 +1900,22 @@ void WLANTL_TXFlowControlCb void WLANTL_RegisterTXFlowControl ( void *vos_ctx, - v_U8_t sta_id, WLANTL_TxFlowControlCBType flowControl, v_U8_t sessionId, void *adpaterCtxt ) { struct txrx_tl_shim_ctx *tl_shim; - struct tlshim_sta_info *sta_info; tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_ctx); - if (!tl_shim) { + if ((!tl_shim) || (!tl_shim->session_flow_control)) { TLSHIM_LOGE("tl_shim is NULL"); return; } - sta_info = &tl_shim->sta_info[sta_id]; - sta_info->flowControl = flowControl; - sta_info->sessionId = sessionId; - sta_info->adpaterCtxt = adpaterCtxt; + tl_shim->session_flow_control[sessionId].flowControl = flowControl; + tl_shim->session_flow_control[sessionId].sessionId = sessionId; + tl_shim->session_flow_control[sessionId].adpaterCtxt = adpaterCtxt; return; } diff --git a/CORE/CLD_TXRX/TLSHIM/tl_shim.h b/CORE/CLD_TXRX/TLSHIM/tl_shim.h index 5f2779c53444..14f0e3c84edf 100644 --- a/CORE/CLD_TXRX/TLSHIM/tl_shim.h +++ b/CORE/CLD_TXRX/TLSHIM/tl_shim.h @@ -55,13 +55,16 @@ struct tlshim_sta_info { adf_os_spinlock_t stainfo_lock; struct list_head cached_bufq; unsigned long flags; + v_S7_t first_rssi; +}; + #ifdef QCA_LL_TX_FLOW_CT +struct tlshim_session_flow_Control { WLANTL_TxFlowControlCBType flowControl; v_U8_t sessionId; void *adpaterCtxt; -#endif /* QCA_LL_TX_FLOW_CT */ - v_S7_t first_rssi; }; +#endif /* QCA_LL_TX_FLOW_CT */ struct txrx_tl_shim_ctx { void *cfg_ctx; @@ -83,6 +86,9 @@ struct deferred_iapp_work iapp_work; u_int32_t last_beacon_len; u_int32_t delay_interval; v_BOOL_t enable_rxthread; +#ifdef QCA_LL_TX_FLOW_CT + struct tlshim_session_flow_Control *session_flow_control; +#endif /* QCA_LL_TX_FLOW_CT */ }; /* diff --git a/CORE/CLD_TXRX/TXRX/ol_tx_send.c b/CORE/CLD_TXRX/TXRX/ol_tx_send.c index 5518a6313367..d0a3632c289c 100644 --- a/CORE/CLD_TXRX/TXRX/ol_tx_send.c +++ b/CORE/CLD_TXRX/TXRX/ol_tx_send.c @@ -118,7 +118,6 @@ do { adf_os_spin_lock(&pdev->tx_mutex); \ if (pdev->tx_desc.num_free > vdev->tx_fl_hwm) { \ vdev->osif_flow_control_cb(vdev->osif_dev, \ - vdev->last_real_peer->local_id, \ vdev->vdev_id, A_TRUE); \ adf_os_atomic_set(&vdev->os_q_paused, 0); \ } \ diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index 2143ed750270..87f22d9b61f1 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -1055,6 +1055,10 @@ struct hdd_adapter_s int connection; #endif v_BOOL_t is_roc_inprogress; + +#ifdef QCA_LL_TX_FLOW_CT + vos_timer_t tx_flow_control_timer; +#endif /* QCA_LL_TX_FLOW_CT */ }; #define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station) diff --git a/CORE/HDD/inc/wlan_hdd_tx_rx.h b/CORE/HDD/inc/wlan_hdd_tx_rx.h index 1a7674f9821a..ca4944fe5506 100644 --- a/CORE/HDD/inc/wlan_hdd_tx_rx.h +++ b/CORE/HDD/inc/wlan_hdd_tx_rx.h @@ -315,12 +315,24 @@ void hdd_wmm_acquire_access_required(hdd_adapter_t *pAdapter, @brief hdd_tx_resume_cb() - Resume OS TX Q. Q was stopped due to WLAN TX path low resource condition - @param adapter_context : [in] pointer to vdev apdapter + @param adapter_context : [in] pointer to vdev adapter @param tx_resume : [in] TX Q resume trigger @return : NONE ===========================================================================*/ void hdd_tx_resume_cb(void *adapter_context, v_BOOL_t tx_resume); + +/**============================================================================ + @brief hdd_tx_resume_timer_expired_handler() - Resume OS TX Q timer expired + handler. + If Blocked OS Q is not resumed during timeout period, to prevent + permanent stall, resume OS Q forcefully. + + @param adapter_context : [in] pointer to vdev adapter + + @return : NONE + ===========================================================================*/ +void hdd_tx_resume_timer_expired_handler(void *adapter_context); #endif /* QCA_LL_TX_FLOW_CT */ #endif // end #if !defined( WLAN_HDD_TX_RX_H ) diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c index 99638ca4ecb5..1fba85c41a9b 100644 --- a/CORE/HDD/src/wlan_hdd_assoc.c +++ b/CORE/HDD/src/wlan_hdd_assoc.c @@ -1159,14 +1159,6 @@ static VOS_STATUS hdd_roamRegisterSTA( hdd_adapter_t *pAdapter, return vosStatus; } -#ifdef QCA_LL_TX_FLOW_CT - WLANTL_RegisterTXFlowControl(pHddCtx->pvosContext, - staDesc.ucSTAId, - hdd_tx_resume_cb, - pAdapter->sessionId, - (void *)pAdapter); -#endif /* QCA_LL_TX_FLOW_CT */ - if ( cfg_param->dynSplitscan && ( VOS_TIMER_STATE_RUNNING != vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))) diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 7ee35010eee3..accb04674934 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -7105,6 +7105,17 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, //netif_tx_disable(pWlanDev); netif_carrier_off(pAdapter->dev); +#ifdef QCA_LL_TX_FLOW_CT + vos_timer_init(&pAdapter->tx_flow_control_timer, + VOS_TIMER_TYPE_SW, + hdd_tx_resume_timer_expired_handler, + pAdapter); + WLANTL_RegisterTXFlowControl(pHddCtx->pvosContext, + hdd_tx_resume_cb, + pAdapter->sessionId, + (void *)pAdapter); +#endif /* QCA_LL_TX_FLOW_CT */ + break; } @@ -7507,7 +7518,14 @@ VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ) msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE)); } } - +#ifdef QCA_LL_TX_FLOW_CT + if(VOS_TIMER_STATE_STOPPED != + vos_timer_getCurrentState(&pAdapter->tx_flow_control_timer)) + { + vos_timer_stop(&pAdapter->tx_flow_control_timer); + } + vos_timer_destroy(&pAdapter->tx_flow_control_timer); +#endif /* QCA_LL_TX_FLOW_CT */ break; case WLAN_HDD_SOFTAP: diff --git a/CORE/HDD/src/wlan_hdd_tx_rx.c b/CORE/HDD/src/wlan_hdd_tx_rx.c index 7cb246db61ae..8d2062f25f55 100644 --- a/CORE/HDD/src/wlan_hdd_tx_rx.c +++ b/CORE/HDD/src/wlan_hdd_tx_rx.c @@ -61,6 +61,9 @@ /*--------------------------------------------------------------------------- Preprocessor definitions and constants -------------------------------------------------------------------------*/ +/* MAX OS Q block time value in msec + * Prevent from permanent stall, resume OS Q if timer expired */ +#define WLAN_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME 1000 const v_U8_t hddWmmAcToHighestUp[] = { SME_QOS_WMM_UP_RESV, @@ -821,6 +824,30 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) #else #ifdef QCA_LL_TX_FLOW_CT /**============================================================================ + @brief hdd_tx_resume_timer_expired_handler() - Resume OS TX Q timer expired + handler. + If Blocked OS Q is not resumed during timeout period, to prevent + permanent stall, resume OS Q forcefully. + + @param adapter_context : [in] pointer to vdev apdapter + + @return : NONE + ===========================================================================*/ +void hdd_tx_resume_timer_expired_handler(void *adapter_context) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *)adapter_context; + + if (!pAdapter) + { + /* INVALID ARG */ + return; + } + + netif_tx_wake_all_queues(pAdapter->dev); + return; +} + +/**============================================================================ @brief hdd_tx_resume_cb() - Resume OS TX Q. Q was stopped due to WLAN TX path low resource condition @@ -843,6 +870,11 @@ void hdd_tx_resume_cb(void *adapter_context, /* Resume TX */ if (VOS_TRUE == tx_resume) { + if (VOS_TIMER_STATE_STOPPED != + vos_timer_getCurrentState(&pAdapter->tx_flow_control_timer)) + { + vos_timer_stop(&pAdapter->tx_flow_control_timer); + } netif_tx_wake_all_queues(pAdapter->dev); } return; @@ -879,8 +911,8 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) #endif /* QCA_PKT_PROTO_TRACE */ #ifdef QCA_LL_TX_FLOW_CT - unsigned int low_watermark; - unsigned int high_watermark_offset; + unsigned int low_watermark = 0; + unsigned int high_watermark_offset = 0; #endif /* QCA_LL_TX_FLOW_CT */ #ifdef QCA_WIFI_FTM @@ -924,8 +956,13 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { STAId = pHddStaCtx->conn_info.staId[0]; #ifdef QCA_LL_TX_FLOW_CT - low_watermark = hddCtxt->cfg_ini->TxStaFlowLowWaterMark; - high_watermark_offset = hddCtxt->cfg_ini->TxStaFlowHighWaterMarkOffset; + /* P2P CLI mode, no TX Flow Control + * TDLS mode, will same flow control watermark values */ + if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) + { + low_watermark = hddCtxt->cfg_ini->TxStaFlowLowWaterMark; + high_watermark_offset = hddCtxt->cfg_ini->TxStaFlowHighWaterMarkOffset; + } #endif /* QCA_LL_TX_FLOW_CT */ } @@ -940,6 +977,12 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) __func__, low_watermark, (low_watermark + high_watermark_offset)); netif_tx_stop_all_queues(dev); + if (VOS_TIMER_STATE_STOPPED == + vos_timer_getCurrentState(&pAdapter->tx_flow_control_timer)) + { + vos_timer_start(&pAdapter->tx_flow_control_timer, + WLAN_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME); + } } #endif /* QCA_LL_TX_FLOW_CT */ diff --git a/CORE/SERVICES/COMMON/ol_txrx_osif_api.h b/CORE/SERVICES/COMMON/ol_txrx_osif_api.h index e3c1b3d1f6d6..6808f64a782a 100644 --- a/CORE/SERVICES/COMMON/ol_txrx_osif_api.h +++ b/CORE/SERVICES/COMMON/ol_txrx_osif_api.h @@ -93,11 +93,10 @@ typedef void (*ol_txrx_rx_fp)(void *osif_dev, adf_nbuf_t msdus); * @typedef ol_txrx_tx_fc_fp * @brief tx flow control notification function from txrx to OS shim * @param osif_dev - the virtual device's OS shim object - * @param peer_id - peer id belongs to virtual device * @param vdev_id - virtual device id * @param tx_resume - tx os q should be resumed or not */ -typedef void (*ol_txrx_tx_flow_control_fp)(void *osif_dev, u_int8_t peer_id, +typedef void (*ol_txrx_tx_flow_control_fp)(void *osif_dev, u_int8_t vdev_id, a_bool_t tx_resume); /** diff --git a/CORE/TL/inc/wlan_qct_tl.h b/CORE/TL/inc/wlan_qct_tl.h index 1edec996fb48..3f38f7cb23b9 100644 --- a/CORE/TL/inc/wlan_qct_tl.h +++ b/CORE/TL/inc/wlan_qct_tl.h @@ -3074,7 +3074,6 @@ v_BOOL_t WLANTL_GetTxResource void WLANTL_TXFlowControlCb ( void *tlContext, - v_U8_t peer_idx, v_U8_t sessionId, v_BOOL_t resume_tx ); @@ -3104,7 +3103,6 @@ void WLANTL_TXFlowControlCb void WLANTL_RegisterTXFlowControl ( void *vos_ctx, - v_U8_t sta_id, WLANTL_TxFlowControlCBType flowControl, v_U8_t sessionId, void *adpaterCtxt |
