diff options
| -rw-r--r-- | CORE/CLD_TXRX/TLSHIM/tl_shim.c | 74 | ||||
| -rw-r--r-- | CORE/CLD_TXRX/TLSHIM/tl_shim.h | 1 | ||||
| -rw-r--r-- | CORE/CLD_TXRX/TXRX/ol_tx.c | 2 | ||||
| -rw-r--r-- | CORE/CLD_TXRX/TXRX/ol_txrx.c | 17 | ||||
| -rw-r--r-- | CORE/CLD_TXRX/TXRX/ol_txrx_types.h | 1 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_cfg.h | 58 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_main.h | 8 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_softap_tx_rx.h | 25 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_cfg.c | 54 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_cfg80211.c | 48 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_main.c | 52 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_softap_tx_rx.c | 84 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_tx_rx.c | 42 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h | 18 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/wdi_in.h | 1 | ||||
| -rw-r--r-- | CORE/TL/inc/wlan_qct_tl.h | 33 |
16 files changed, 424 insertions, 94 deletions
diff --git a/CORE/CLD_TXRX/TLSHIM/tl_shim.c b/CORE/CLD_TXRX/TLSHIM/tl_shim.c index 44c4604f643c..8cb2491da3ff 100644 --- a/CORE/CLD_TXRX/TLSHIM/tl_shim.c +++ b/CORE/CLD_TXRX/TLSHIM/tl_shim.c @@ -926,6 +926,7 @@ void WLANTL_RegisterVdev(void *vos_ctx, void *vdev) #ifdef QCA_LL_TX_FLOW_CT txrx_ops.tx.flow_control_cb = WLANTL_TXFlowControlCb; + tl_shim->session_flow_control[vdev_handle->vdev_id].vdev = vdev; #endif /* QCA_LL_TX_FLOW_CT */ txrx_ops.rx.std = tlshim_data_rx_handler; wdi_in_osif_vdev_register(vdev_handle, tl_shim, &txrx_ops); @@ -1691,6 +1692,7 @@ VOS_STATUS WLANTL_Open(void *vos_ctx, WLANTL_ConfigInfoType *tl_cfg) tl_shim->session_flow_control[i].flowControl = NULL; tl_shim->session_flow_control[i].sessionId = 0xFF; tl_shim->session_flow_control[i].adpaterCtxt = NULL; + tl_shim->session_flow_control[i].vdev = NULL; } #endif /* QCA_LL_TX_FLOW_CT */ @@ -1788,7 +1790,9 @@ void *tl_shim_get_vdev_by_sta_id(void *vos_context, uint8_t sta_id) PARAMETERS IN vos_context : Pointer to VOS global context - sta_id : STA/VDEV instance to query TX resource + sessionId : VDEV instance to query TX resource + low_watermark : Low threashold to block OS Q + high_watermark_offset : Offset to high watermark from low watermark RETURN VALUE VOS_TRUE : Enough resource available, Not need to PAUSE TX OS Q @@ -1800,12 +1804,12 @@ void *tl_shim_get_vdev_by_sta_id(void *vos_context, uint8_t sta_id) v_BOOL_t WLANTL_GetTxResource ( void *vos_context, - uint8_t sta_id, + v_U8_t sessionId, unsigned int low_watermark, unsigned int high_watermark_offset ) { - struct ol_txrx_peer_t *peer = NULL; + struct txrx_tl_shim_ctx *tl_shim; /* If low watermark is zero, TX flow control is not enabled at all * return TRUE by default */ @@ -1813,16 +1817,18 @@ v_BOOL_t WLANTL_GetTxResource return VOS_TRUE; } - peer = ol_txrx_peer_find_by_local_id( - ((pVosContextType) vos_context)->pdev_txrx_ctx, - sta_id); - if (!peer) { + tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_context); + if ((!tl_shim) || (!tl_shim->session_flow_control[sessionId].vdev)) { + TLSHIM_LOGE("%s, tl_shim is NULL or session id %d", + __func__, sessionId); + /* Invalid instace */ return VOS_TRUE; } - return (v_BOOL_t)wdi_in_get_tx_resource(peer->vdev, - low_watermark, - high_watermark_offset); + return (v_BOOL_t)wdi_in_get_tx_resource( + (struct ol_txrx_vdev_t *)tl_shim->session_flow_control[sessionId].vdev, + low_watermark, + high_watermark_offset); } /*============================================================================= @@ -1909,7 +1915,7 @@ void WLANTL_RegisterTXFlowControl tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_ctx); if ((!tl_shim) || (!tl_shim->session_flow_control)) { - TLSHIM_LOGE("tl_shim is NULL"); + TLSHIM_LOGE("%s : Invalid ARG", __func__); return; } @@ -1919,5 +1925,51 @@ void WLANTL_RegisterTXFlowControl return; } + +/*============================================================================= + FUNCTION WLANTL_SetAdapterMaxQDepth + + DESCRIPTION + This function will be called by TL client. + Based on the adapter TX available bandwidth, set different TX Pause Q size + Low Bandwidth adapter will have less count of TX Pause Q size to prevent + reserve all TX descriptors which shared with FW. + High Bandwidth adapter will have more count of TX Pause Q size + !!! This function is place holder till MCC TX FLOW CT Enabled !!! + + PARAMETERS + IN + vos_ctx : Global OS context context + sessionId : adapter instance index + max_q_depth : Max pause Q depth for adapter + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_SetAdapterMaxQDepth +( + void *vos_ctx, + v_U8_t sessionId, + int max_q_depth +) +{ + struct txrx_tl_shim_ctx *tl_shim; + + tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_ctx); + if ((!tl_shim) || (!tl_shim->session_flow_control) || + (!tl_shim->session_flow_control[sessionId].vdev)) { + TLSHIM_LOGE("%s: TLSHIM NULL or session ID %d", + __func__, sessionId); + return; + } + + wdi_in_ll_set_tx_pause_q_depth( + (struct ol_txrx_vdev_t *)tl_shim->session_flow_control[sessionId].vdev, + max_q_depth); + return; +} #endif /* QCA_LL_TX_FLOW_CT */ diff --git a/CORE/CLD_TXRX/TLSHIM/tl_shim.h b/CORE/CLD_TXRX/TLSHIM/tl_shim.h index 14f0e3c84edf..8f1a08351ae3 100644 --- a/CORE/CLD_TXRX/TLSHIM/tl_shim.h +++ b/CORE/CLD_TXRX/TLSHIM/tl_shim.h @@ -63,6 +63,7 @@ struct tlshim_session_flow_Control { WLANTL_TxFlowControlCBType flowControl; v_U8_t sessionId; void *adpaterCtxt; + void *vdev; }; #endif /* QCA_LL_TX_FLOW_CT */ diff --git a/CORE/CLD_TXRX/TXRX/ol_tx.c b/CORE/CLD_TXRX/TXRX/ol_tx.c index 633287f74e40..fb920b6bd216 100644 --- a/CORE/CLD_TXRX/TXRX/ol_tx.c +++ b/CORE/CLD_TXRX/TXRX/ol_tx.c @@ -183,7 +183,7 @@ ol_tx_vdev_pause_queue_append( { adf_os_spin_lock_bh(&vdev->ll_pause.mutex); while (msdu_list && - vdev->ll_pause.txq.depth < vdev->pdev->cfg.ll_pause_txq_limit) + vdev->ll_pause.txq.depth < vdev->ll_pause.max_q_depth) { adf_nbuf_t next = adf_nbuf_next(msdu_list); diff --git a/CORE/CLD_TXRX/TXRX/ol_txrx.c b/CORE/CLD_TXRX/TXRX/ol_txrx.c index 6aaec4100346..9e083083e30b 100644 --- a/CORE/CLD_TXRX/TXRX/ol_txrx.c +++ b/CORE/CLD_TXRX/TXRX/ol_txrx.c @@ -843,7 +843,9 @@ ol_txrx_vdev_attach( vdev->tx_fl_lwm = 0; vdev->tx_fl_hwm = 0; vdev->osif_flow_control_cb = NULL; - + /* Default MAX Q depth for every VDEV */ + vdev->ll_pause.max_q_depth = + ol_tx_cfg_max_tx_queue_depth_ll(vdev->pdev->ctrl_pdev); /* add this vdev into the pdev's list */ TAILQ_INSERT_TAIL(&pdev->vdev_list, vdev, vdev_list_elem); @@ -1974,4 +1976,17 @@ ol_txrx_get_tx_resource( adf_os_spin_unlock_bh(&vdev->pdev->tx_mutex); return A_TRUE; } + +void +ol_txrx_ll_set_tx_pause_q_depth( + ol_txrx_vdev_handle vdev, + int pause_q_depth +) +{ + adf_os_spin_lock_bh(&vdev->ll_pause.mutex); + vdev->ll_pause.max_q_depth = pause_q_depth; + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); + + return; +} #endif /* QCA_LL_TX_FLOW_CT */ diff --git a/CORE/CLD_TXRX/TXRX/ol_txrx_types.h b/CORE/CLD_TXRX/TXRX/ol_txrx_types.h index bee76236be29..491cbabcffa5 100644 --- a/CORE/CLD_TXRX/TXRX/ol_txrx_types.h +++ b/CORE/CLD_TXRX/TXRX/ol_txrx_types.h @@ -752,6 +752,7 @@ struct ol_txrx_vdev_t { a_bool_t is_paused; adf_os_spinlock_t mutex; adf_os_timer_t timer; + int max_q_depth; } ll_pause; a_bool_t disable_intrabss_fwd; adf_os_atomic_t os_q_paused; diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h index 5b1ec92df677..21099a2bd63b 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/CORE/HDD/inc/wlan_hdd_cfg.h @@ -2293,25 +2293,35 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */ #define CFG_SET_TXPOWER_LIMIT5G_DEFAULT ( 15 ) #ifdef QCA_LL_TX_FLOW_CT -#define CFG_LL_TX_STA_FLOW_LWM "TxStaFlowLowWaterMark" -#define CFG_LL_TX_STA_FLOW_LWM_MIN ( 0 ) -#define CFG_LL_TX_STA_FLOW_LWM_MAX ( 1000 ) -#define CFG_LL_TX_STA_FLOW_LWM_DEFAULT ( 406 ) - -#define CFG_LL_TX_STA_FLOW_HWM_OFFSET "TxStaFlowHighWaterMarkOffset" -#define CFG_LL_TX_STA_FLOW_HWM_OFFSET_MIN ( 0 ) -#define CFG_LL_TX_STA_FLOW_HWM_OFFSET_MAX ( 300 ) -#define CFG_LL_TX_STA_FLOW_HWM_OFFSET_DEFAULT ( 50 ) - -#define CFG_LL_TX_IBSS_FLOW_LWM "TxIbssFlowLowWaterMark" -#define CFG_LL_TX_IBSS_FLOW_LWM_MIN ( 0 ) -#define CFG_LL_TX_IBSS_FLOW_LWM_MAX ( 1000 ) -#define CFG_LL_TX_IBSS_FLOW_LWM_DEFAULT ( 550 ) - -#define CFG_LL_TX_IBSS_FLOW_HWM_OFFSET "TxIbssFlowHighWaterMarkOffset" -#define CFG_LL_TX_IBSS_FLOW_HWM_OFFSET_MIN ( 0 ) -#define CFG_LL_TX_IBSS_FLOW_HWM_OFFSET_MAX ( 300 ) -#define CFG_LL_TX_IBSS_FLOW_HWM_OFFSET_DEFAULT ( 50 ) +#define CFG_LL_TX_LBW_FLOW_LWM "TxLbwFlowLowWaterMark" +#define CFG_LL_TX_LBW_FLOW_LWM_MIN ( 0 ) +#define CFG_LL_TX_LBW_FLOW_LWM_MAX ( 1000 ) +#define CFG_LL_TX_LBW_FLOW_LWM_DEFAULT ( 650 ) + +#define CFG_LL_TX_LBW_FLOW_HWM_OFFSET "TxLbwFlowHighWaterMarkOffset" +#define CFG_LL_TX_LBW_FLOW_HWM_OFFSET_MIN ( 0 ) +#define CFG_LL_TX_LBW_FLOW_HWM_OFFSET_MAX ( 300 ) +#define CFG_LL_TX_LBW_FLOW_HWM_OFFSET_DEFAULT ( 50 ) + +#define CFG_LL_TX_LBW_FLOW_MAX_Q_DEPTH "TxLbwFlowMaxQueueDepth" +#define CFG_LL_TX_LBW_FLOW_MAX_Q_DEPTH_MIN ( 400 ) +#define CFG_LL_TX_LBW_FLOW_MAX_Q_DEPTH_MAX ( 3500 ) +#define CFG_LL_TX_LBW_FLOW_MAX_Q_DEPTH_DEFAULT ( 750 ) + +#define CFG_LL_TX_HBW_FLOW_LWM "TxHbwFlowLowWaterMark" +#define CFG_LL_TX_HBW_FLOW_LWM_MIN ( 0 ) +#define CFG_LL_TX_HBW_FLOW_LWM_MAX ( 1000 ) +#define CFG_LL_TX_HBW_FLOW_LWM_DEFAULT ( 406 ) + +#define CFG_LL_TX_HBW_FLOW_HWM_OFFSET "TxHbwFlowHighWaterMarkOffset" +#define CFG_LL_TX_HBW_FLOW_HWM_OFFSET_MIN ( 0 ) +#define CFG_LL_TX_HBW_FLOW_HWM_OFFSET_MAX ( 300 ) +#define CFG_LL_TX_HBW_FLOW_HWM_OFFSET_DEFAULT ( 50 ) + +#define CFG_LL_TX_HBW_FLOW_MAX_Q_DEPTH "TxHbwFlowMaxQueueDepth" +#define CFG_LL_TX_HBW_FLOW_MAX_Q_DEPTH_MIN ( 400 ) +#define CFG_LL_TX_HBW_FLOW_MAX_Q_DEPTH_MAX ( 3500 ) +#define CFG_LL_TX_HBW_FLOW_MAX_Q_DEPTH_DEFAULT ( 1500 ) #endif /* QCA_LL_TX_FLOW_CT */ /*--------------------------------------------------------------------------- Type declarations @@ -2789,10 +2799,12 @@ typedef struct v_BOOL_t fRegChangeDefCountry; v_U8_t acsScanBandPreference; #ifdef QCA_LL_TX_FLOW_CT - v_U32_t TxStaFlowLowWaterMark; - v_U32_t TxStaFlowHighWaterMarkOffset; - v_U32_t TxIbssFlowLowWaterMark; - v_U32_t TxIbssFlowHighWaterMarkOffset; + v_U32_t TxLbwFlowLowWaterMark; + v_U32_t TxLbwFlowHighWaterMarkOffset; + v_U32_t TxLbwFlowMaxQueueDepth; + v_U32_t TxHbwFlowLowWaterMark; + v_U32_t TxHbwFlowHighWaterMarkOffset; + v_U32_t TxHbwFlowMaxQueueDepth; #endif /* QCA_LL_TX_FLOW_CT */ v_U16_t acsBandSwitchThreshold; } hdd_config_t; diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index 87f22d9b61f1..4b1d0072588b 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -296,6 +296,12 @@ extern spinlock_t hdd_context_lock; #endif #endif +#ifdef QCA_LL_TX_FLOW_CT +/* 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 +#define WLAN_HDD_TX_FLOW_CONTROL_MAX_24BAND_CH 14 +#endif /* QCA_LL_TX_FLOW_CT */ typedef struct hdd_tx_rx_stats_s { @@ -1058,6 +1064,8 @@ struct hdd_adapter_s #ifdef QCA_LL_TX_FLOW_CT vos_timer_t tx_flow_control_timer; + unsigned int tx_flow_low_watermark; + unsigned int tx_flow_high_watermark_offset; #endif /* QCA_LL_TX_FLOW_CT */ }; diff --git a/CORE/HDD/inc/wlan_hdd_softap_tx_rx.h b/CORE/HDD/inc/wlan_hdd_softap_tx_rx.h index 51c923d100a0..b78ec1c13be8 100644 --- a/CORE/HDD/inc/wlan_hdd_softap_tx_rx.h +++ b/CORE/HDD/inc/wlan_hdd_softap_tx_rx.h @@ -371,4 +371,29 @@ VOS_STATUS hdd_start_trafficMonitor( hdd_adapter_t *pAdapter ); ========================================================================== */ VOS_STATUS hdd_stop_trafficMonitor( hdd_adapter_t *pAdapter ); +#ifdef QCA_LL_TX_FLOW_CT +/**============================================================================ + @brief hdd_softap_tx_resume_timer_expired_handler() - Resume OS TX Q timer + expired handler for SAP and P2P GO interface. + If Blocked OS Q is not resumed during timeout period, to prevent + permanent stall, resume OS Q forcefully for SAP and P2P GO interface. + + @param adapter_context : [in] pointer to vdev adapter + + @return : NONE + ===========================================================================*/ +void hdd_softap_tx_resume_timer_expired_handler(void *adapter_context); + +/**============================================================================ + @brief hdd_softap_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 adapter + @param tx_resume : [in] TX Q resume trigger + + @return : NONE + ===========================================================================*/ +void hdd_softap_tx_resume_cb(void *adapter_context, + v_BOOL_t tx_resume); +#endif /* QCA_LL_TX_FLOW_CT */ #endif // end #if !defined( WLAN_HDD_SOFTAP_TX_RX_H ) diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c index f4414e6f9a35..3e78c81129f0 100644 --- a/CORE/HDD/src/wlan_hdd_cfg.c +++ b/CORE/HDD/src/wlan_hdd_cfg.c @@ -3216,33 +3216,47 @@ REG_VARIABLE( CFG_SAP_SCAN_BAND_PREFERENCE, WLAN_PARAM_Integer, CFG_SAP_SCAN_BAND_PREFERENCE_MAX ), #ifdef QCA_LL_TX_FLOW_CT -REG_VARIABLE( CFG_LL_TX_STA_FLOW_LWM, WLAN_PARAM_Integer, - hdd_config_t, TxStaFlowLowWaterMark, +REG_VARIABLE( CFG_LL_TX_LBW_FLOW_LWM, WLAN_PARAM_Integer, + hdd_config_t, TxLbwFlowLowWaterMark, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, - CFG_LL_TX_STA_FLOW_LWM_DEFAULT, - CFG_LL_TX_STA_FLOW_LWM_MIN, - CFG_LL_TX_STA_FLOW_LWM_MAX ), + CFG_LL_TX_LBW_FLOW_LWM_DEFAULT, + CFG_LL_TX_LBW_FLOW_LWM_MIN, + CFG_LL_TX_LBW_FLOW_LWM_MAX ), -REG_VARIABLE( CFG_LL_TX_STA_FLOW_HWM_OFFSET, WLAN_PARAM_Integer, - hdd_config_t, TxStaFlowHighWaterMarkOffset, +REG_VARIABLE( CFG_LL_TX_LBW_FLOW_HWM_OFFSET, WLAN_PARAM_Integer, + hdd_config_t, TxLbwFlowHighWaterMarkOffset, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, - CFG_LL_TX_STA_FLOW_HWM_OFFSET_DEFAULT, - CFG_LL_TX_STA_FLOW_HWM_OFFSET_MIN, - CFG_LL_TX_STA_FLOW_HWM_OFFSET_MAX ), + CFG_LL_TX_LBW_FLOW_HWM_OFFSET_DEFAULT, + CFG_LL_TX_LBW_FLOW_HWM_OFFSET_MIN, + CFG_LL_TX_LBW_FLOW_HWM_OFFSET_MAX ), -REG_VARIABLE( CFG_LL_TX_IBSS_FLOW_LWM, WLAN_PARAM_Integer, - hdd_config_t, TxIbssFlowLowWaterMark, +REG_VARIABLE( CFG_LL_TX_LBW_FLOW_MAX_Q_DEPTH, WLAN_PARAM_Integer, + hdd_config_t, TxLbwFlowMaxQueueDepth, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, - CFG_LL_TX_IBSS_FLOW_LWM_DEFAULT, - CFG_LL_TX_IBSS_FLOW_LWM_MIN, - CFG_LL_TX_IBSS_FLOW_LWM_MAX ), + CFG_LL_TX_LBW_FLOW_MAX_Q_DEPTH_DEFAULT, + CFG_LL_TX_LBW_FLOW_MAX_Q_DEPTH_MIN, + CFG_LL_TX_LBW_FLOW_MAX_Q_DEPTH_MAX ), -REG_VARIABLE( CFG_LL_TX_IBSS_FLOW_HWM_OFFSET, WLAN_PARAM_Integer, - hdd_config_t, TxIbssFlowHighWaterMarkOffset, +REG_VARIABLE( CFG_LL_TX_HBW_FLOW_LWM, WLAN_PARAM_Integer, + hdd_config_t, TxHbwFlowLowWaterMark, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, - CFG_LL_TX_IBSS_FLOW_HWM_OFFSET_DEFAULT, - CFG_LL_TX_IBSS_FLOW_HWM_OFFSET_MIN, - CFG_LL_TX_IBSS_FLOW_HWM_OFFSET_MAX ), + CFG_LL_TX_HBW_FLOW_LWM_DEFAULT, + CFG_LL_TX_HBW_FLOW_LWM_MIN, + CFG_LL_TX_HBW_FLOW_LWM_MAX ), + +REG_VARIABLE( CFG_LL_TX_HBW_FLOW_HWM_OFFSET, WLAN_PARAM_Integer, + hdd_config_t, TxHbwFlowHighWaterMarkOffset, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LL_TX_HBW_FLOW_HWM_OFFSET_DEFAULT, + CFG_LL_TX_HBW_FLOW_HWM_OFFSET_MIN, + CFG_LL_TX_HBW_FLOW_HWM_OFFSET_MAX ), + +REG_VARIABLE( CFG_LL_TX_HBW_FLOW_MAX_Q_DEPTH, WLAN_PARAM_Integer, + hdd_config_t, TxHbwFlowMaxQueueDepth, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LL_TX_HBW_FLOW_MAX_Q_DEPTH_DEFAULT, + CFG_LL_TX_HBW_FLOW_MAX_Q_DEPTH_MIN, + CFG_LL_TX_HBW_FLOW_MAX_Q_DEPTH_MAX ), #endif /* QCA_LL_TX_FLOW_CT */ REG_VARIABLE( CFG_ACS_BAND_SWITCH_THRESHOLD, WLAN_PARAM_Integer, hdd_config_t, acsBandSwitchThreshold, diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 495fd8855ec5..f7a07dff354e 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -3140,6 +3140,20 @@ int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy, if (status != VOS_STATUS_SUCCESS) return status; +#ifdef QCA_LL_TX_FLOW_CT + if (NL80211_IFTYPE_P2P_CLIENT == type) + { + 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 */ + goto done; #endif case NL80211_IFTYPE_ADHOC: @@ -3286,6 +3300,17 @@ int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy, } hdd_set_conparam(1); +#ifdef QCA_LL_TX_FLOW_CT + vos_timer_init(&pAdapter->tx_flow_control_timer, + VOS_TIMER_TYPE_SW, + hdd_softap_tx_resume_timer_expired_handler, + pAdapter); + WLANTL_RegisterTXFlowControl(pHddCtx->pvosContext, + hdd_softap_tx_resume_cb, + pAdapter->sessionId, + (void *)pAdapter); +#endif /* QCA_LL_TX_FLOW_CT */ + /*interface type changed update in wiphy structure*/ if(wdev) { @@ -3342,6 +3367,19 @@ int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy, hdd_set_pwrparams(pHddCtx); } hdd_enable_bmps_imps(pHddCtx); +#ifdef QCA_LL_TX_FLOW_CT + if (NL80211_IFTYPE_P2P_CLIENT == type) + { + 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 */ goto done; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: @@ -3349,6 +3387,16 @@ int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy, wdev->iftype = type; pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ? WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO; +#ifdef QCA_LL_TX_FLOW_CT + vos_timer_init(&pAdapter->tx_flow_control_timer, + VOS_TIMER_TYPE_SW, + hdd_softap_tx_resume_timer_expired_handler, + pAdapter); + WLANTL_RegisterTXFlowControl(pHddCtx->pvosContext, + hdd_softap_tx_resume_cb, + pAdapter->sessionId, + (void *)pAdapter); +#endif /* QCA_LL_TX_FLOW_CT */ goto done; default: hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type", diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 56309744750a..b1336fd42f1e 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -7264,6 +7264,9 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, netif_carrier_off(pAdapter->dev); #ifdef QCA_LL_TX_FLOW_CT + /* SAT mode default TX Flow control instance + * This instance will be used for + * STA mode, IBSS mode and TDLS mode */ vos_timer_init(&pAdapter->tx_flow_control_timer, VOS_TIMER_TYPE_SW, hdd_tx_resume_timer_expired_handler, @@ -7707,6 +7710,15 @@ VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ) } } +#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 */ + mutex_lock(&pHddCtx->sap_lock); if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags)) { @@ -8029,6 +8041,10 @@ void hdd_dump_concurrency_info(hdd_context_t *pHddCtx) const char *p2pMode = "DEV"; const char *ccMode = "Standalone"; +#ifdef QCA_LL_TX_FLOW_CT + v_U8_t targetChannel = 0; +#endif /* QCA_LL_TX_FLOW_CT */ + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) { @@ -8039,6 +8055,9 @@ void hdd_dump_concurrency_info(hdd_context_t *pHddCtx) if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) { staChannel = pHddStaCtx->conn_info.operationChannel; memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid)); +#ifdef QCA_LL_TX_FLOW_CT + targetChannel = staChannel; +#endif /* QCA_LL_TX_FLOW_CT */ } break; case WLAN_HDD_P2P_CLIENT: @@ -8047,6 +8066,9 @@ void hdd_dump_concurrency_info(hdd_context_t *pHddCtx) p2pChannel = pHddStaCtx->conn_info.operationChannel; memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid)); p2pMode = "CLI"; +#ifdef QCA_LL_TX_FLOW_CT + targetChannel = p2pChannel; +#endif /* QCA_LL_TX_FLOW_CT */ } break; case WLAN_HDD_P2P_GO: @@ -8055,6 +8077,9 @@ void hdd_dump_concurrency_info(hdd_context_t *pHddCtx) if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) { p2pChannel = pHddApCtx->operatingChannel; memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid)); +#ifdef QCA_LL_TX_FLOW_CT + targetChannel = p2pChannel; +#endif /* QCA_LL_TX_FLOW_CT */ } p2pMode = "GO"; break; @@ -8064,6 +8089,9 @@ void hdd_dump_concurrency_info(hdd_context_t *pHddCtx) if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) { apChannel = pHddApCtx->operatingChannel; memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid)); +#ifdef QCA_LL_TX_FLOW_CT + targetChannel = apChannel; +#endif /* QCA_LL_TX_FLOW_CT */ } break; case WLAN_HDD_IBSS: @@ -8071,6 +8099,30 @@ void hdd_dump_concurrency_info(hdd_context_t *pHddCtx) default: break; } +#ifdef QCA_LL_TX_FLOW_CT + /* First stage implementation for all interface TX flow control + * All interfaces will have same flow control threshold + * 2nd stage will have MCC-Bandwidth dependent TX flow control + * TL/TXRX APIs are not called */ + if (targetChannel) + { + pAdapter->tx_flow_low_watermark = + pHddCtx->cfg_ini->TxHbwFlowLowWaterMark; + pAdapter->tx_flow_high_watermark_offset = + pHddCtx->cfg_ini->TxHbwFlowHighWaterMarkOffset; + /* Temporary set log level as error + * TX Flow control feature settled down, will lower log level */ + hddLog(VOS_TRACE_LEVEL_ERROR, + "MODE %d, CH %d, LWM %d, HWM %d, TXQDEP %d", + pAdapter->device_mode, + targetChannel, + pAdapter->tx_flow_low_watermark, + pAdapter->tx_flow_low_watermark + + pAdapter->tx_flow_high_watermark_offset, + pHddCtx->cfg_ini->TxHbwFlowMaxQueueDepth); + } + targetChannel = 0; +#endif /* QCA_LL_TX_FLOW_CT */ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); pAdapterNode = pNext; } diff --git a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c index 22a56e2fe189..2dbfcb559e39 100644 --- a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c +++ b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c @@ -459,6 +459,72 @@ xmit_done: #else +#ifdef QCA_LL_TX_FLOW_CT +/**============================================================================ + @brief hdd_softap_tx_resume_timer_expired_handler() - Resume OS TX Q timer + expired handler for SAP and P2P GO interface. + If Blocked OS Q is not resumed during timeout period, to prevent + permanent stall, resume OS Q forcefully for SAP and P2P GO interface. + + @param adapter_context : [in] pointer to vdev adapter + + @return : NONE + ===========================================================================*/ +void hdd_softap_tx_resume_timer_expired_handler(void *adapter_context) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *)adapter_context; + + if (!pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: INV ARG", __func__); + /* INVALID ARG */ + return; + } + + netif_tx_wake_all_queues(pAdapter->dev); + return; +} + +/**============================================================================ + @brief hdd_softap_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 adapter + @param tx_resume : [in] TX Q resume trigger + + @return : NONE + ===========================================================================*/ +void hdd_softap_tx_resume_cb(void *adapter_context, + v_BOOL_t tx_resume) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *)adapter_context; + + if (!pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: INV ARG", __func__); + /* INVALID ARG */ + return; + } + + /* 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); + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Resume DEV 0x%x", (unsigned int)pAdapter->dev); + netif_tx_wake_all_queues(pAdapter->dev); + } + return; +} +#endif /* QCA_LL_TX_FLOW_CT */ + /**============================================================================ @brief hdd_softap_hard_start_xmit() - Function registered with the Linux OS for transmitting packets. @@ -538,6 +604,22 @@ int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } } +#ifdef QCA_LL_TX_FLOW_CT + if (VOS_FALSE == WLANTL_GetTxResource((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + pAdapter->sessionId, + pAdapter->tx_flow_low_watermark, + pAdapter->tx_flow_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 */ + //Get TL AC corresponding to Qdisc queue index/AC. ac = hdd_QdiscAcToTlAC[skb->queue_mapping]; @@ -746,7 +828,7 @@ xmit_end: ===========================================================================*/ void hdd_softap_tx_timeout(struct net_device *dev) { - VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, + VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_DEBUG, "%s: Transmission timeout occurred", __func__); //Getting here implies we disabled the TX queues for too long. Queues are //disabled either because of disassociation or low resource scenarios. In diff --git a/CORE/HDD/src/wlan_hdd_tx_rx.c b/CORE/HDD/src/wlan_hdd_tx_rx.c index d8b82187b2b2..0ceb81519a2c 100644 --- a/CORE/HDD/src/wlan_hdd_tx_rx.c +++ b/CORE/HDD/src/wlan_hdd_tx_rx.c @@ -61,10 +61,6 @@ /*--------------------------------------------------------------------------- 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, SME_QOS_WMM_UP_EE, @@ -907,20 +903,11 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) v_BOOL_t granted; v_U8_t STAId = WLAN_MAX_STA_COUNT; hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station; - -#if defined(QCA_PKT_PROTO_TRACE) || defined (QCA_LL_TX_FLOW_CT) - hdd_context_t *hddCtxt = WLAN_HDD_GET_CTX(pAdapter); -#endif /* defined(QCA_PKT_PROTO_TRACE) || defined (QCA_LL_TX_FLOW_CT) */ - #ifdef QCA_PKT_PROTO_TRACE + hdd_context_t *hddCtxt = WLAN_HDD_GET_CTX(pAdapter); v_U8_t proto_type = 0; #endif /* QCA_PKT_PROTO_TRACE */ -#ifdef QCA_LL_TX_FLOW_CT - unsigned int low_watermark = 0; - unsigned int high_watermark_offset = 0; -#endif /* QCA_LL_TX_FLOW_CT */ - #ifdef QCA_WIFI_FTM if (hdd_get_conparam() == VOS_FTM_MODE) { kfree_skb(skb); @@ -953,35 +940,18 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) kfree_skb(skb); return NETDEV_TX_OK; } -#ifdef QCA_LL_TX_FLOW_CT - low_watermark = hddCtxt->cfg_ini->TxIbssFlowLowWaterMark; - high_watermark_offset = hddCtxt->cfg_ini->TxIbssFlowHighWaterMarkOffset; -#endif /* QCA_LL_TX_FLOW_CT */ } else { STAId = pHddStaCtx->conn_info.staId[0]; -#ifdef QCA_LL_TX_FLOW_CT - /* 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 */ } #ifdef QCA_LL_TX_FLOW_CT if (VOS_FALSE == WLANTL_GetTxResource((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, - STAId, - low_watermark, - high_watermark_offset)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, - "%s: Out of TX resource, stop Q, LWM %d, HWM %d", - __func__, low_watermark, - (low_watermark + high_watermark_offset)); + pAdapter->sessionId, + pAdapter->tx_flow_low_watermark, + pAdapter->tx_flow_high_watermark_offset)) + { netif_tx_stop_all_queues(dev); if (VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pAdapter->tx_flow_control_timer)) @@ -1177,7 +1147,7 @@ void hdd_tx_timeout(struct net_device *dev) return; } - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG, "%s: Transmission timeout occurred", __func__); //Getting here implies we disabled the TX queues for too long. Queues are //disabled either because of disassociation or low resource scenarios. In diff --git a/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h b/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h index d3642544222f..52a3ff88ed8d 100644 --- a/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h +++ b/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h @@ -1017,6 +1017,24 @@ ol_txrx_get_tx_resource( unsigned int low_watermark, unsigned int high_watermark_offset ); + +/** + * @brief Set MAX LL TX Pause Q depth per vdev + * @details + * Each vdev will have different TX Pause Q depth + * High bandwidth vdev may have more TX Pause Q depth + * Low bandwidth vdev will have less TX Pause Q depth not to block + * high bandwidth vdev + * + * @param vdev - the virtual device + * @param pause_q_depth - TX Pause Q depth per vdev + * @return NONE + */ +void +ol_txrx_ll_set_tx_pause_q_depth( + ol_txrx_vdev_handle vdev, + int pause_q_depth +); #endif /* QCA_LL_TX_FLOW_CT */ #endif /* _OL_TXRX_CTRL_API__H_ */ diff --git a/CORE/SERVICES/COMMON/wdi_in.h b/CORE/SERVICES/COMMON/wdi_in.h index b015b24828b0..202984785fc5 100644 --- a/CORE/SERVICES/COMMON/wdi_in.h +++ b/CORE/SERVICES/COMMON/wdi_in.h @@ -1224,6 +1224,7 @@ ol_tx_queue_log_display(ol_txrx_pdev_handle pdev); #define wdi_in_vdev_rx_fwd_disabled ol_vdev_rx_set_intrabss_fwd #ifdef QCA_LL_TX_FLOW_CT #define wdi_in_get_tx_resource ol_txrx_get_tx_resource +#define wdi_in_ll_set_tx_pause_q_depth ol_txrx_ll_set_tx_pause_q_depth #endif /* QCA_LL_TX_FLOW_CT */ #include <ol_txrx_dbg.h> diff --git a/CORE/TL/inc/wlan_qct_tl.h b/CORE/TL/inc/wlan_qct_tl.h index 3f38f7cb23b9..950de16100e2 100644 --- a/CORE/TL/inc/wlan_qct_tl.h +++ b/CORE/TL/inc/wlan_qct_tl.h @@ -3034,6 +3034,8 @@ WLANTL_TLDebugMessage IN vos_context : Pointer to VOS global context sta_id : STA/VDEV instance to query TX resource + low_watermark : Low threashold to block OS Q + high_watermark_offset : Offset to high watermark from low watermark RETURN VALUE VOS_TRUE : Enough resource available, Not need to PAUSE TX OS Q @@ -3045,7 +3047,7 @@ WLANTL_TLDebugMessage v_BOOL_t WLANTL_GetTxResource ( void *vos_context, - uint8_t sta_id, + v_U8_t sessionId, unsigned int low_watermark, unsigned int high_watermark_offset ); @@ -3107,6 +3109,35 @@ void WLANTL_RegisterTXFlowControl v_U8_t sessionId, void *adpaterCtxt ); + +/*============================================================================= + FUNCTION WLANTL_SetAdapterMaxQDepth + + DESCRIPTION + This function will be called by TL client. + Based on the adapter TX available bandwidth, set different TX Pause Q size + Low Bandwidth adapter will have less count of TX Pause Q size to prevent + reserve all TX descriptors which shared with FW. + High Bandwidth adapter will have more count of TX Pause Q size + + PARAMETERS + IN + vos_ctx : Global OS context context + sessionId : adapter instance index + max_q_depth : Max pause Q depth for adapter + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_SetAdapterMaxQDepth +( + void *vos_ctx, + v_U8_t sessionId, + int max_q_depth +); #endif /* QCA_LL_TX_FLOW_CT */ #endif /* QCA_WIFI_2_0 */ |
