summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CORE/CLD_TXRX/TLSHIM/tl_shim.c74
-rw-r--r--CORE/CLD_TXRX/TLSHIM/tl_shim.h1
-rw-r--r--CORE/CLD_TXRX/TXRX/ol_tx.c2
-rw-r--r--CORE/CLD_TXRX/TXRX/ol_txrx.c17
-rw-r--r--CORE/CLD_TXRX/TXRX/ol_txrx_types.h1
-rw-r--r--CORE/HDD/inc/wlan_hdd_cfg.h58
-rw-r--r--CORE/HDD/inc/wlan_hdd_main.h8
-rw-r--r--CORE/HDD/inc/wlan_hdd_softap_tx_rx.h25
-rw-r--r--CORE/HDD/src/wlan_hdd_cfg.c54
-rw-r--r--CORE/HDD/src/wlan_hdd_cfg80211.c48
-rw-r--r--CORE/HDD/src/wlan_hdd_main.c52
-rw-r--r--CORE/HDD/src/wlan_hdd_softap_tx_rx.c84
-rw-r--r--CORE/HDD/src/wlan_hdd_tx_rx.c42
-rw-r--r--CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h18
-rw-r--r--CORE/SERVICES/COMMON/wdi_in.h1
-rw-r--r--CORE/TL/inc/wlan_qct_tl.h33
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 */