qcacmn: AC based TX flow control
Implement per access category flow control. Make sure lower AC traffic, such as BE, will not starve higher AC, such as VI and VO, traffic inside a single vdev. This change is part of FR49094 Change-Id: I6aa15832eb48e8f3ada00eb29a7bc00999edaafd CRs-Fixed: 2304436
This commit is contained in:
@@ -97,6 +97,11 @@ enum netif_action_type {
|
|||||||
WLAN_NETIF_CARRIER_OFF,
|
WLAN_NETIF_CARRIER_OFF,
|
||||||
WLAN_NETIF_PRIORITY_QUEUE_ON,
|
WLAN_NETIF_PRIORITY_QUEUE_ON,
|
||||||
WLAN_NETIF_PRIORITY_QUEUE_OFF,
|
WLAN_NETIF_PRIORITY_QUEUE_OFF,
|
||||||
|
WLAN_NETIF_VO_QUEUE_ON,
|
||||||
|
WLAN_NETIF_VO_QUEUE_OFF,
|
||||||
|
WLAN_NETIF_VI_QUEUE_ON,
|
||||||
|
WLAN_NETIF_VI_QUEUE_OFF,
|
||||||
|
WLAN_NETIF_BE_BK_QUEUE_OFF,
|
||||||
WLAN_WAKE_NON_PRIORITY_QUEUE,
|
WLAN_WAKE_NON_PRIORITY_QUEUE,
|
||||||
WLAN_STOP_NON_PRIORITY_QUEUE,
|
WLAN_STOP_NON_PRIORITY_QUEUE,
|
||||||
WLAN_NETIF_ACTION_TYPE_MAX,
|
WLAN_NETIF_ACTION_TYPE_MAX,
|
||||||
|
@@ -58,6 +58,11 @@
|
|||||||
#define TX_DESC_LOCK_UNLOCK(lock)
|
#define TX_DESC_LOCK_UNLOCK(lock)
|
||||||
#define IS_TX_DESC_POOL_STATUS_INACTIVE(pool) \
|
#define IS_TX_DESC_POOL_STATUS_INACTIVE(pool) \
|
||||||
((pool)->status == FLOW_POOL_INACTIVE)
|
((pool)->status == FLOW_POOL_INACTIVE)
|
||||||
|
#ifdef QCA_AC_BASED_FLOW_CONTROL
|
||||||
|
#define TX_DESC_POOL_MEMBER_CLEAN(_tx_desc_pool) \
|
||||||
|
dp_tx_flow_pool_member_clean(_tx_desc_pool)
|
||||||
|
|
||||||
|
#else /* !QCA_AC_BASED_FLOW_CONTROL */
|
||||||
#define TX_DESC_POOL_MEMBER_CLEAN(_tx_desc_pool) \
|
#define TX_DESC_POOL_MEMBER_CLEAN(_tx_desc_pool) \
|
||||||
do { \
|
do { \
|
||||||
(_tx_desc_pool)->elem_size = 0; \
|
(_tx_desc_pool)->elem_size = 0; \
|
||||||
@@ -68,6 +73,7 @@ do { \
|
|||||||
(_tx_desc_pool)->stop_th = 0; \
|
(_tx_desc_pool)->stop_th = 0; \
|
||||||
(_tx_desc_pool)->status = FLOW_POOL_INACTIVE; \
|
(_tx_desc_pool)->status = FLOW_POOL_INACTIVE; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
#endif /* QCA_AC_BASED_FLOW_CONTROL */
|
||||||
#else /* !QCA_LL_TX_FLOW_CONTROL_V2 */
|
#else /* !QCA_LL_TX_FLOW_CONTROL_V2 */
|
||||||
#define TX_DESC_LOCK_CREATE(lock) qdf_spinlock_create(lock)
|
#define TX_DESC_LOCK_CREATE(lock) qdf_spinlock_create(lock)
|
||||||
#define TX_DESC_LOCK_DESTROY(lock) qdf_spinlock_destroy(lock)
|
#define TX_DESC_LOCK_DESTROY(lock) qdf_spinlock_destroy(lock)
|
||||||
@@ -153,7 +159,224 @@ void dp_tx_put_desc_flow_pool(struct dp_tx_desc_pool_s *pool,
|
|||||||
pool->avail_desc++;
|
pool->avail_desc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef QCA_AC_BASED_FLOW_CONTROL
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dp_tx_flow_pool_member_clean() - Clean the members of TX flow pool
|
||||||
|
*
|
||||||
|
* @pool: flow pool
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
dp_tx_flow_pool_member_clean(struct dp_tx_desc_pool_s *pool)
|
||||||
|
{
|
||||||
|
pool->elem_size = 0;
|
||||||
|
pool->freelist = NULL;
|
||||||
|
pool->pool_size = 0;
|
||||||
|
pool->avail_desc = 0;
|
||||||
|
qdf_mem_zero(pool->start_th, FL_TH_MAX);
|
||||||
|
qdf_mem_zero(pool->stop_th, FL_TH_MAX);
|
||||||
|
pool->status = FLOW_POOL_INACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dp_tx_is_threshold_reached() - Check if current avail desc meet threshold
|
||||||
|
*
|
||||||
|
* @pool: flow pool
|
||||||
|
* @avail_desc: available descriptor number
|
||||||
|
*
|
||||||
|
* Return: true if threshold is met, false if not
|
||||||
|
*/
|
||||||
|
static inline bool
|
||||||
|
dp_tx_is_threshold_reached(struct dp_tx_desc_pool_s *pool, uint16_t avail_desc)
|
||||||
|
{
|
||||||
|
if (qdf_unlikely(avail_desc == pool->stop_th[DP_TH_BE_BK]))
|
||||||
|
return true;
|
||||||
|
else if (qdf_unlikely(avail_desc == pool->stop_th[DP_TH_VI]))
|
||||||
|
return true;
|
||||||
|
else if (qdf_unlikely(avail_desc == pool->stop_th[DP_TH_VO]))
|
||||||
|
return true;
|
||||||
|
else if (qdf_unlikely(avail_desc == pool->stop_th[DP_TH_HI]))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dp_tx_desc_alloc() - Allocate a Software Tx descriptor from given pool
|
||||||
|
*
|
||||||
|
* @soc: Handle to DP SoC structure
|
||||||
|
* @desc_pool_id: ID of the flow control fool
|
||||||
|
*
|
||||||
|
* Return: TX descriptor allocated or NULL
|
||||||
|
*/
|
||||||
|
static inline struct dp_tx_desc_s *
|
||||||
|
dp_tx_desc_alloc(struct dp_soc *soc, uint8_t desc_pool_id)
|
||||||
|
{
|
||||||
|
struct dp_tx_desc_s *tx_desc = NULL;
|
||||||
|
struct dp_tx_desc_pool_s *pool = &soc->tx_desc[desc_pool_id];
|
||||||
|
bool is_pause = false;
|
||||||
|
enum netif_action_type act = WLAN_WAKE_NON_PRIORITY_QUEUE;
|
||||||
|
enum dp_fl_ctrl_threshold level = DP_TH_BE_BK;
|
||||||
|
|
||||||
|
if (qdf_likely(pool)) {
|
||||||
|
qdf_spin_lock_bh(&pool->flow_pool_lock);
|
||||||
|
if (qdf_likely(pool->avail_desc)) {
|
||||||
|
tx_desc = dp_tx_get_desc_flow_pool(pool);
|
||||||
|
tx_desc->pool_id = desc_pool_id;
|
||||||
|
tx_desc->flags = DP_TX_DESC_FLAG_ALLOCATED;
|
||||||
|
is_pause = dp_tx_is_threshold_reached(pool,
|
||||||
|
pool->avail_desc);
|
||||||
|
|
||||||
|
if (qdf_unlikely(is_pause)) {
|
||||||
|
switch (pool->status) {
|
||||||
|
case FLOW_POOL_ACTIVE_UNPAUSED:
|
||||||
|
/* pause network BE\BK queue */
|
||||||
|
act = WLAN_NETIF_BE_BK_QUEUE_OFF;
|
||||||
|
level = DP_TH_BE_BK;
|
||||||
|
pool->status = FLOW_POOL_BE_BK_PAUSED;
|
||||||
|
break;
|
||||||
|
case FLOW_POOL_BE_BK_PAUSED:
|
||||||
|
/* pause network VI queue */
|
||||||
|
act = WLAN_NETIF_VI_QUEUE_OFF;
|
||||||
|
level = DP_TH_VI;
|
||||||
|
pool->status = FLOW_POOL_VI_PAUSED;
|
||||||
|
break;
|
||||||
|
case FLOW_POOL_VI_PAUSED:
|
||||||
|
/* pause network VO queue */
|
||||||
|
act = WLAN_NETIF_VO_QUEUE_OFF;
|
||||||
|
level = DP_TH_VO;
|
||||||
|
pool->status = FLOW_POOL_VO_PAUSED;
|
||||||
|
break;
|
||||||
|
case FLOW_POOL_VO_PAUSED:
|
||||||
|
/* pause network HI PRI queue */
|
||||||
|
act = WLAN_NETIF_PRIORITY_QUEUE_OFF;
|
||||||
|
level = DP_TH_HI;
|
||||||
|
pool->status = FLOW_POOL_ACTIVE_PAUSED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_DP,
|
||||||
|
QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"%s %d pool is %d status!",
|
||||||
|
__func__, __LINE__,
|
||||||
|
pool->status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pool->latest_pause_time[level] =
|
||||||
|
qdf_get_system_timestamp();
|
||||||
|
soc->pause_cb(desc_pool_id,
|
||||||
|
act, WLAN_DATA_FLOW_CONTROL);
|
||||||
|
qdf_spin_unlock_bh(&pool->flow_pool_lock);
|
||||||
|
} else {
|
||||||
|
qdf_spin_unlock_bh(&pool->flow_pool_lock);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pool->pkt_drop_no_desc++;
|
||||||
|
qdf_spin_unlock_bh(&pool->flow_pool_lock);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
soc->pool_stats.pkt_drop_no_pool++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx_desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dp_tx_desc_free() - Fee a tx descriptor and attach it to free list
|
||||||
|
*
|
||||||
|
* @soc: Handle to DP SoC structure
|
||||||
|
* @tx_desc: the tx descriptor to be freed
|
||||||
|
* @desc_pool_id: ID of the flow control fool
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
dp_tx_desc_free(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc,
|
||||||
|
uint8_t desc_pool_id)
|
||||||
|
{
|
||||||
|
struct dp_tx_desc_pool_s *pool = &soc->tx_desc[desc_pool_id];
|
||||||
|
qdf_time_t unpause_time = qdf_get_system_timestamp(), pause_dur;
|
||||||
|
enum netif_action_type act = WLAN_WAKE_ALL_NETIF_QUEUE;
|
||||||
|
|
||||||
|
qdf_spin_lock_bh(&pool->flow_pool_lock);
|
||||||
|
tx_desc->flags = 0;
|
||||||
|
dp_tx_put_desc_flow_pool(pool, tx_desc);
|
||||||
|
switch (pool->status) {
|
||||||
|
case FLOW_POOL_ACTIVE_PAUSED:
|
||||||
|
if (pool->avail_desc > pool->start_th[DP_TH_HI]) {
|
||||||
|
act = WLAN_NETIF_PRIORITY_QUEUE_ON;
|
||||||
|
pool->status = FLOW_POOL_VO_PAUSED;
|
||||||
|
|
||||||
|
/* Update maxinum pause duration for HI queue */
|
||||||
|
pause_dur = unpause_time -
|
||||||
|
pool->latest_pause_time[DP_TH_HI];
|
||||||
|
if (pool->max_pause_time[DP_TH_HI] < pause_dur)
|
||||||
|
pool->max_pause_time[DP_TH_HI] = pause_dur;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FLOW_POOL_VO_PAUSED:
|
||||||
|
if (pool->avail_desc > pool->start_th[DP_TH_VO]) {
|
||||||
|
act = WLAN_NETIF_VO_QUEUE_ON;
|
||||||
|
pool->status = FLOW_POOL_VI_PAUSED;
|
||||||
|
|
||||||
|
/* Update maxinum pause duration for VO queue */
|
||||||
|
pause_dur = unpause_time -
|
||||||
|
pool->latest_pause_time[DP_TH_VO];
|
||||||
|
if (pool->max_pause_time[DP_TH_VO] < pause_dur)
|
||||||
|
pool->max_pause_time[DP_TH_VO] = pause_dur;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FLOW_POOL_VI_PAUSED:
|
||||||
|
if (pool->avail_desc > pool->start_th[DP_TH_VI]) {
|
||||||
|
act = WLAN_NETIF_VI_QUEUE_ON;
|
||||||
|
pool->status = FLOW_POOL_BE_BK_PAUSED;
|
||||||
|
|
||||||
|
/* Update maxinum pause duration for VI queue */
|
||||||
|
pause_dur = unpause_time -
|
||||||
|
pool->latest_pause_time[DP_TH_VI];
|
||||||
|
if (pool->max_pause_time[DP_TH_VI] < pause_dur)
|
||||||
|
pool->max_pause_time[DP_TH_VI] = pause_dur;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FLOW_POOL_BE_BK_PAUSED:
|
||||||
|
if (pool->avail_desc > pool->start_th[DP_TH_BE_BK]) {
|
||||||
|
act = WLAN_WAKE_NON_PRIORITY_QUEUE;
|
||||||
|
pool->status = FLOW_POOL_ACTIVE_UNPAUSED;
|
||||||
|
|
||||||
|
/* Update maxinum pause duration for BE_BK queue */
|
||||||
|
pause_dur = unpause_time -
|
||||||
|
pool->latest_pause_time[DP_TH_BE_BK];
|
||||||
|
if (pool->max_pause_time[DP_TH_BE_BK] < pause_dur)
|
||||||
|
pool->max_pause_time[DP_TH_BE_BK] = pause_dur;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FLOW_POOL_INVALID:
|
||||||
|
if (pool->avail_desc == pool->pool_size) {
|
||||||
|
dp_tx_desc_pool_free(soc, desc_pool_id);
|
||||||
|
qdf_spin_unlock_bh(&pool->flow_pool_lock);
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"%s %d pool is freed!!",
|
||||||
|
__func__, __LINE__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FLOW_POOL_ACTIVE_UNPAUSED:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"%s %d pool is INACTIVE State!!",
|
||||||
|
__func__, __LINE__);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (act != WLAN_WAKE_ALL_NETIF_QUEUE)
|
||||||
|
soc->pause_cb(pool->flow_pool_id,
|
||||||
|
act, WLAN_DATA_FLOW_CONTROL);
|
||||||
|
qdf_spin_unlock_bh(&pool->flow_pool_lock);
|
||||||
|
}
|
||||||
|
#else /* QCA_AC_BASED_FLOW_CONTROL */
|
||||||
/**
|
/**
|
||||||
* dp_tx_desc_alloc() - Allocate a Software Tx Descriptor from given pool
|
* dp_tx_desc_alloc() - Allocate a Software Tx Descriptor from given pool
|
||||||
*
|
*
|
||||||
@@ -260,6 +483,8 @@ out:
|
|||||||
*/
|
*/
|
||||||
hif_pm_runtime_put(soc->hif_handle);
|
hif_pm_runtime_put(soc->hif_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* QCA_AC_BASED_FLOW_CONTROL */
|
||||||
#else /* QCA_LL_TX_FLOW_CONTROL_V2 */
|
#else /* QCA_LL_TX_FLOW_CONTROL_V2 */
|
||||||
|
|
||||||
static inline void dp_tx_flow_control_init(struct dp_soc *handle)
|
static inline void dp_tx_flow_control_init(struct dp_soc *handle)
|
||||||
|
@@ -30,6 +30,142 @@
|
|||||||
#define INVALID_FLOW_ID 0xFF
|
#define INVALID_FLOW_ID 0xFF
|
||||||
#define MAX_INVALID_BIN 3
|
#define MAX_INVALID_BIN 3
|
||||||
|
|
||||||
|
#ifdef QCA_AC_BASED_FLOW_CONTROL
|
||||||
|
/**
|
||||||
|
* dp_tx_initialize_threshold() - Threshold of flow Pool initialization
|
||||||
|
* @pool: flow_pool
|
||||||
|
* @stop_threshold: stop threshold of certian AC
|
||||||
|
* @start_threshold: start threshold of certian AC
|
||||||
|
* @flow_pool_size: flow pool size
|
||||||
|
*
|
||||||
|
* Return: none
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
dp_tx_initialize_threshold(struct dp_tx_desc_pool_s *pool,
|
||||||
|
uint32_t start_threshold,
|
||||||
|
uint32_t stop_threshold,
|
||||||
|
uint16_t flow_pool_size)
|
||||||
|
{
|
||||||
|
/* BE_BK threshold is same as previous threahold */
|
||||||
|
pool->start_th[DP_TH_BE_BK] = (start_threshold
|
||||||
|
* flow_pool_size) / 100;
|
||||||
|
pool->stop_th[DP_TH_BE_BK] = (stop_threshold
|
||||||
|
* flow_pool_size) / 100;
|
||||||
|
|
||||||
|
/* Update VI threshold based on BE_BK threashold */
|
||||||
|
pool->start_th[DP_TH_VI] = (pool->start_th[DP_TH_BE_BK]
|
||||||
|
* FL_TH_VI_PERCENTAGE) / 100;
|
||||||
|
pool->stop_th[DP_TH_VI] = (pool->stop_th[DP_TH_BE_BK]
|
||||||
|
* FL_TH_VI_PERCENTAGE) / 100;
|
||||||
|
|
||||||
|
/* Update VO threshold based on BE_BK threashold */
|
||||||
|
pool->start_th[DP_TH_VO] = (pool->start_th[DP_TH_BE_BK]
|
||||||
|
* FL_TH_VO_PERCENTAGE) / 100;
|
||||||
|
pool->stop_th[DP_TH_VO] = (pool->stop_th[DP_TH_BE_BK]
|
||||||
|
* FL_TH_VO_PERCENTAGE) / 100;
|
||||||
|
|
||||||
|
/* Update High Priority threshold based on BE_BK threashold */
|
||||||
|
pool->start_th[DP_TH_HI] = (pool->start_th[DP_TH_BE_BK]
|
||||||
|
* FL_TH_HI_PERCENTAGE) / 100;
|
||||||
|
pool->stop_th[DP_TH_HI] = (pool->stop_th[DP_TH_BE_BK]
|
||||||
|
* FL_TH_HI_PERCENTAGE) / 100;
|
||||||
|
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"%s: tx flow control threshold is set, pool size is %d",
|
||||||
|
__func__, flow_pool_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dp_tx_flow_pool_reattach() - Reattach flow_pool
|
||||||
|
* @pool: flow_pool
|
||||||
|
*
|
||||||
|
* Return: none
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
dp_tx_flow_pool_reattach(struct dp_tx_desc_pool_s *pool)
|
||||||
|
{
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"%s: flow pool already allocated, attached %d times",
|
||||||
|
__func__, pool->pool_create_cnt);
|
||||||
|
|
||||||
|
if (pool->avail_desc > pool->start_th[DP_TH_BE_BK])
|
||||||
|
pool->status = FLOW_POOL_ACTIVE_UNPAUSED;
|
||||||
|
if (pool->avail_desc <= pool->start_th[DP_TH_BE_BK] &&
|
||||||
|
pool->avail_desc > pool->start_th[DP_TH_VI])
|
||||||
|
pool->status = FLOW_POOL_BE_BK_PAUSED;
|
||||||
|
else if (pool->avail_desc <= pool->start_th[DP_TH_VI] &&
|
||||||
|
pool->avail_desc > pool->start_th[DP_TH_VO])
|
||||||
|
pool->status = FLOW_POOL_VI_PAUSED;
|
||||||
|
else if (pool->avail_desc <= pool->start_th[DP_TH_VO] &&
|
||||||
|
pool->avail_desc > pool->start_th[DP_TH_HI])
|
||||||
|
pool->status = FLOW_POOL_VO_PAUSED;
|
||||||
|
else
|
||||||
|
pool->status = FLOW_POOL_ACTIVE_PAUSED;
|
||||||
|
|
||||||
|
pool->pool_create_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dp_tx_flow_pool_dump_threshold() - Dump threshold of the flow_pool
|
||||||
|
* @pool: flow_pool
|
||||||
|
*
|
||||||
|
* Return: none
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
dp_tx_flow_pool_dump_threshold(struct dp_tx_desc_pool_s *pool)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < FL_TH_MAX; i++) {
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"Level %d :: Start threshold %d :: Stop threshold %d",
|
||||||
|
i, pool->start_th[i], pool->stop_th[i]);
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"Level %d :: Maximun pause time %lu ms",
|
||||||
|
i, pool->max_pause_time[i]);
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"Level %d :: Latest pause timestamp %lu",
|
||||||
|
i, pool->latest_pause_time[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
static inline void
|
||||||
|
dp_tx_initialize_threshold(struct dp_tx_desc_pool_s *pool,
|
||||||
|
uint32_t start_threshold,
|
||||||
|
uint32_t stop_threshold,
|
||||||
|
uint16_t flow_pool_size)
|
||||||
|
|
||||||
|
{
|
||||||
|
/* INI is in percentage so divide by 100 */
|
||||||
|
pool->start_th = (start_threshold * flow_pool_size) / 100;
|
||||||
|
pool->stop_th = (stop_threshold * flow_pool_size) / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
dp_tx_flow_pool_reattach(struct dp_tx_desc_pool_s *pool)
|
||||||
|
{
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"%s: flow pool already allocated, attached %d times",
|
||||||
|
__func__, pool->pool_create_cnt);
|
||||||
|
if (pool->avail_desc > pool->start_th)
|
||||||
|
pool->status = FLOW_POOL_ACTIVE_UNPAUSED;
|
||||||
|
else
|
||||||
|
pool->status = FLOW_POOL_ACTIVE_PAUSED;
|
||||||
|
|
||||||
|
pool->pool_create_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
dp_tx_flow_pool_dump_threshold(struct dp_tx_desc_pool_s *pool)
|
||||||
|
{
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"Start threshold %d :: Stop threshold %d",
|
||||||
|
pool->start_th, pool->stop_th);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dp_tx_dump_flow_pool_info() - dump global_pool and flow_pool info
|
* dp_tx_dump_flow_pool_info() - dump global_pool and flow_pool info
|
||||||
*
|
*
|
||||||
@@ -74,9 +210,7 @@ void dp_tx_dump_flow_pool_info(void *ctx)
|
|||||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||||
"Total %d :: Available %d",
|
"Total %d :: Available %d",
|
||||||
tmp_pool.pool_size, tmp_pool.avail_desc);
|
tmp_pool.pool_size, tmp_pool.avail_desc);
|
||||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
dp_tx_flow_pool_dump_threshold(&tmp_pool);
|
||||||
"Start threshold %d :: Stop threshold %d",
|
|
||||||
tmp_pool.start_th, tmp_pool.stop_th);
|
|
||||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||||
"Member flow_id %d :: flow_type %d",
|
"Member flow_id %d :: flow_type %d",
|
||||||
tmp_pool.flow_pool_id, tmp_pool.flow_type);
|
tmp_pool.flow_pool_id, tmp_pool.flow_type);
|
||||||
@@ -129,16 +263,7 @@ struct dp_tx_desc_pool_s *dp_tx_create_flow_pool(struct dp_soc *soc,
|
|||||||
pool = &soc->tx_desc[flow_pool_id];
|
pool = &soc->tx_desc[flow_pool_id];
|
||||||
qdf_spin_lock_bh(&pool->flow_pool_lock);
|
qdf_spin_lock_bh(&pool->flow_pool_lock);
|
||||||
if ((pool->status != FLOW_POOL_INACTIVE) || pool->pool_create_cnt) {
|
if ((pool->status != FLOW_POOL_INACTIVE) || pool->pool_create_cnt) {
|
||||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
dp_tx_flow_pool_reattach(pool);
|
||||||
"%s: flow pool already allocated, attached %d times",
|
|
||||||
__func__, pool->pool_create_cnt);
|
|
||||||
if (pool->avail_desc > pool->start_th)
|
|
||||||
pool->status = FLOW_POOL_ACTIVE_UNPAUSED;
|
|
||||||
else
|
|
||||||
pool->status = FLOW_POOL_ACTIVE_PAUSED;
|
|
||||||
|
|
||||||
pool->pool_create_cnt++;
|
|
||||||
|
|
||||||
qdf_spin_unlock_bh(&pool->flow_pool_lock);
|
qdf_spin_unlock_bh(&pool->flow_pool_lock);
|
||||||
return pool;
|
return pool;
|
||||||
}
|
}
|
||||||
@@ -156,9 +281,8 @@ struct dp_tx_desc_pool_s *dp_tx_create_flow_pool(struct dp_soc *soc,
|
|||||||
pool->pool_size = flow_pool_size;
|
pool->pool_size = flow_pool_size;
|
||||||
pool->avail_desc = flow_pool_size;
|
pool->avail_desc = flow_pool_size;
|
||||||
pool->status = FLOW_POOL_ACTIVE_UNPAUSED;
|
pool->status = FLOW_POOL_ACTIVE_UNPAUSED;
|
||||||
/* INI is in percentage so divide by 100 */
|
dp_tx_initialize_threshold(pool, start_threshold, stop_threshold,
|
||||||
pool->start_th = (start_threshold * flow_pool_size)/100;
|
flow_pool_size);
|
||||||
pool->stop_th = (stop_threshold * flow_pool_size)/100;
|
|
||||||
pool->pool_create_cnt++;
|
pool->pool_create_cnt++;
|
||||||
|
|
||||||
qdf_spin_unlock_bh(&pool->flow_pool_lock);
|
qdf_spin_unlock_bh(&pool->flow_pool_lock);
|
||||||
|
@@ -155,6 +155,25 @@ union dp_rx_desc_list_elem_t;
|
|||||||
#define DP_HW2SW_MACID(id) ((id) > 0 ? ((id) - 1) : 0)
|
#define DP_HW2SW_MACID(id) ((id) > 0 ? ((id) - 1) : 0)
|
||||||
#define DP_MAC_ADDR_LEN 6
|
#define DP_MAC_ADDR_LEN 6
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of Tx Queues
|
||||||
|
* enum and macro to define how many threshold levels is used
|
||||||
|
* for the AC based flow control
|
||||||
|
*/
|
||||||
|
#ifdef QCA_AC_BASED_FLOW_CONTROL
|
||||||
|
enum dp_fl_ctrl_threshold {
|
||||||
|
DP_TH_BE_BK = 0,
|
||||||
|
DP_TH_VI,
|
||||||
|
DP_TH_VO,
|
||||||
|
DP_TH_HI,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FL_TH_MAX (4)
|
||||||
|
#define FL_TH_VI_PERCENTAGE (80)
|
||||||
|
#define FL_TH_VO_PERCENTAGE (60)
|
||||||
|
#define FL_TH_HI_PERCENTAGE (40)
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum dp_intr_mode
|
* enum dp_intr_mode
|
||||||
* @DP_INTR_LEGACY: Legacy/Line interrupts, for WIN
|
* @DP_INTR_LEGACY: Legacy/Line interrupts, for WIN
|
||||||
@@ -314,8 +333,11 @@ struct dp_tx_desc_s {
|
|||||||
enum flow_pool_status {
|
enum flow_pool_status {
|
||||||
FLOW_POOL_ACTIVE_UNPAUSED = 0,
|
FLOW_POOL_ACTIVE_UNPAUSED = 0,
|
||||||
FLOW_POOL_ACTIVE_PAUSED = 1,
|
FLOW_POOL_ACTIVE_PAUSED = 1,
|
||||||
FLOW_POOL_INVALID = 2,
|
FLOW_POOL_BE_BK_PAUSED = 2,
|
||||||
FLOW_POOL_INACTIVE = 3,
|
FLOW_POOL_VI_PAUSED = 3,
|
||||||
|
FLOW_POOL_VO_PAUSED = 4,
|
||||||
|
FLOW_POOL_INVALID = 5,
|
||||||
|
FLOW_POOL_INACTIVE = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -377,8 +399,15 @@ struct dp_tx_desc_pool_s {
|
|||||||
uint16_t avail_desc;
|
uint16_t avail_desc;
|
||||||
enum flow_pool_status status;
|
enum flow_pool_status status;
|
||||||
enum htt_flow_type flow_type;
|
enum htt_flow_type flow_type;
|
||||||
|
#ifdef QCA_AC_BASED_FLOW_CONTROL
|
||||||
|
uint16_t stop_th[FL_TH_MAX];
|
||||||
|
uint16_t start_th[FL_TH_MAX];
|
||||||
|
qdf_time_t max_pause_time[FL_TH_MAX];
|
||||||
|
qdf_time_t latest_pause_time[FL_TH_MAX];
|
||||||
|
#else
|
||||||
uint16_t stop_th;
|
uint16_t stop_th;
|
||||||
uint16_t start_th;
|
uint16_t start_th;
|
||||||
|
#endif
|
||||||
uint16_t pkt_drop_no_desc;
|
uint16_t pkt_drop_no_desc;
|
||||||
qdf_spinlock_t flow_pool_lock;
|
qdf_spinlock_t flow_pool_lock;
|
||||||
uint8_t pool_create_cnt;
|
uint8_t pool_create_cnt;
|
||||||
|
Reference in New Issue
Block a user