diff --git a/core/dp/txrx/ol_tx_queue.c b/core/dp/txrx/ol_tx_queue.c index 33485e7479..621f1c2b7d 100644 --- a/core/dp/txrx/ol_tx_queue.c +++ b/core/dp/txrx/ol_tx_queue.c @@ -1748,6 +1748,93 @@ ol_tx_ac_has_tx_queue_group( return false; } +#ifdef FEATURE_HL_DBS_GROUP_CREDIT_SHARING +static inline struct ol_tx_queue_group_t * +ol_tx_txq_find_other_group(struct ol_txrx_pdev_t *pdev, + struct ol_tx_queue_group_t *txq_grp) +{ + int i; + struct ol_tx_queue_group_t *other_grp = NULL; + + for (i = 0; i < OL_TX_MAX_TXQ_GROUPS; i++) { + if (&pdev->txq_grps[i] != txq_grp) { + other_grp = &pdev->txq_grps[i]; + break; + } + } + return other_grp; +} + +u32 ol_tx_txq_group_credit_limit( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + u32 credit) +{ + struct ol_tx_queue_group_t *txq_grp = txq->group_ptrs[0]; + struct ol_tx_queue_group_t *other_grp; + u32 ask; + u32 updated_credit; + u32 credit_oth_grp; + + if (qdf_unlikely(!txq_grp)) + return credit; + + updated_credit = qdf_atomic_read(&txq_grp->credit); + + if (credit <= updated_credit) + /* We have enough credits */ + return credit; + + ask = credit - updated_credit; + other_grp = ol_tx_txq_find_other_group(pdev, txq_grp); + if (qdf_unlikely(!other_grp)) + return credit; + + credit_oth_grp = qdf_atomic_read(&other_grp->credit); + if (other_grp->frm_count < credit_oth_grp) { + u32 spare = credit_oth_grp - other_grp->frm_count; + + if (pdev->limit_lend) { + if (spare > pdev->min_reserve) + spare -= pdev->min_reserve; + else + spare = 0; + } + updated_credit += min(spare, ask); + } + return updated_credit; +} + +u32 ol_tx_txq_update_borrowed_group_credits(struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + u32 credits_used) +{ + struct ol_tx_queue_group_t *txq_grp = txq->group_ptrs[0]; + u32 credits_cur_grp; + u32 credits_brwd; + + if (qdf_unlikely(!txq_grp)) + return credits_used; + + credits_cur_grp = qdf_atomic_read(&txq_grp->credit); + if (credits_used > credits_cur_grp) { + struct ol_tx_queue_group_t *other_grp = + ol_tx_txq_find_other_group(pdev, txq_grp); + + if (qdf_likely(other_grp)) { + credits_brwd = credits_used - credits_cur_grp; + /* + * All the credits were used from the active txq group. + */ + credits_used = credits_cur_grp; + /* Deduct credits borrowed from other group */ + ol_txrx_update_group_credit(other_grp, -credits_brwd, + 0); + } + } + return credits_used; +} +#else /* FEATURE_HL_DBS_GROUP_CREDIT_SHARING */ u_int32_t ol_tx_txq_group_credit_limit( struct ol_txrx_pdev_t *pdev, struct ol_tx_frms_queue_t *txq, @@ -1774,6 +1861,7 @@ u_int32_t ol_tx_txq_group_credit_limit( return credit; } +#endif /* FEATURE_HL_DBS_GROUP_CREDIT_SHARING */ void ol_tx_txq_group_credit_update( struct ol_txrx_pdev_t *pdev, diff --git a/core/dp/txrx/ol_tx_queue.h b/core/dp/txrx/ol_tx_queue.h index 3749ecb01e..a5e7fbef72 100644 --- a/core/dp/txrx/ol_tx_queue.h +++ b/core/dp/txrx/ol_tx_queue.h @@ -456,7 +456,6 @@ static inline void ol_tx_throttle_init_period(struct cdp_pdev *ppdev, #endif #ifdef FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL - static inline bool ol_tx_is_txq_last_serviced_queue(struct ol_txrx_pdev_t *pdev, struct ol_tx_frms_queue_t *txq) @@ -592,10 +591,22 @@ ol_tx_set_peer_group_ptr( * @param: num_frms - Number of frames to be added/removed from the group. */ void ol_tx_update_grp_frm_count(struct ol_tx_frms_queue_t *txq, int num_frms); + +u32 ol_tx_txq_update_borrowed_group_credits(struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + u32 credits_used); #else static inline void ol_tx_update_grp_frm_count(struct ol_tx_frms_queue_t *txq, int num_frms) {} + +static inline u32 +ol_tx_txq_update_borrowed_group_credits(struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + u32 credits_used) +{ + return credits_used; +} #endif /* * FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL && * FEATURE_HL_DBS_GROUP_CREDIT_SHARING diff --git a/core/dp/txrx/ol_tx_sched.c b/core/dp/txrx/ol_tx_sched.c index 2a2c43aebe..7049bd4ad7 100644 --- a/core/dp/txrx/ol_tx_sched.c +++ b/core/dp/txrx/ol_tx_sched.c @@ -842,7 +842,11 @@ ol_tx_sched_select_batch_wrr_adv( OL_TX_SCHED_WRR_ADV_CAT_STAT_INC_DISPATCHED(category, frames); + /* Update used global credits */ used_credits = credit; + credit = + ol_tx_txq_update_borrowed_group_credits(pdev, txq, + credit); category->state.frms -= frames; category->state.bytes -= bytes; if (txq->frms > 0) { diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 963914eb8e..dd66e171eb 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -1473,6 +1473,8 @@ ol_txrx_pdev_post_attach(struct cdp_pdev *ppdev) for (i = 0 ; i < OL_TX_MAX_TXQ_GROUPS; i++) qdf_atomic_init(&pdev->txq_grps[i].credit); + ol_txrx_init_txq_group_limit_lend(pdev); + ol_tx_target_credit_init(pdev, desc_pool_size); } else { qdf_atomic_add(ol_cfg_target_tx_credit(pdev->ctrl_pdev), diff --git a/core/dp/txrx/ol_txrx.h b/core/dp/txrx/ol_txrx.h index 090f02936d..ac99a7d5f3 100644 --- a/core/dp/txrx/ol_txrx.h +++ b/core/dp/txrx/ol_txrx.h @@ -210,4 +210,21 @@ bool ol_txrx_fwd_desc_thresh_check(struct ol_txrx_vdev_t *vdev) } #endif + +#if defined(FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL) && \ + defined(FEATURE_HL_DBS_GROUP_CREDIT_SHARING) +static inline void +ol_txrx_init_txq_group_limit_lend(struct ol_txrx_pdev_t *pdev) +{ + BUILD_BUG_ON(OL_TX_MAX_GROUPS_PER_QUEUE > 1); + BUILD_BUG_ON(OL_TX_MAX_TXQ_GROUPS > 2); + pdev->limit_lend = 0; + pdev->min_reserve = 0; +} +#else +static inline void +ol_txrx_init_txq_group_limit_lend(struct ol_txrx_pdev_t *pdev) +{} +#endif + #endif /* _OL_TXRX__H_ */ diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h index 3646f5dc01..c862f34526 100644 --- a/core/dp/txrx/ol_txrx_types.h +++ b/core/dp/txrx/ol_txrx_types.h @@ -995,6 +995,11 @@ struct ol_txrx_pdev_t { #endif /* CONFIG_Hl_SUPPORT && QCA_BAD_PEER_TX_FLOW_CL */ struct ol_tx_queue_group_t txq_grps[OL_TX_MAX_TXQ_GROUPS]; +#if defined(FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL) && \ + defined(FEATURE_HL_DBS_GROUP_CREDIT_SHARING) + bool limit_lend; + u16 min_reserve; +#endif #ifdef DEBUG_HL_LOGGING qdf_spinlock_t grp_stat_spinlock; struct ol_tx_group_credit_stats_t grp_stats;