diff --git a/dp/wifi3.0/be/dp_be_tx.c b/dp/wifi3.0/be/dp_be_tx.c index 05a9d843e3..fba8ab3497 100644 --- a/dp/wifi3.0/be/dp_be_tx.c +++ b/dp/wifi3.0/be/dp_be_tx.c @@ -1582,7 +1582,7 @@ qdf_nbuf_t dp_tx_fast_send_be(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, DP_STATS_INC(vdev, tx_i.rcvd_per_core[desc_pool_id], 1); pdev = vdev->pdev; - if (dp_tx_limit_check(vdev)) + if (dp_tx_limit_check(vdev, nbuf)) return nbuf; tx_desc = dp_tx_desc_alloc(soc, desc_pool_id); diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 14a6cbc07e..a6e29d019b 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -15562,7 +15562,7 @@ void *dp_soc_init(struct dp_soc *soc, HTC_HANDLE htc_handle, qdf_atomic_init(&soc->num_tx_exception); soc->num_tx_allowed = wlan_cfg_get_dp_soc_tx_device_limit(soc->wlan_cfg_ctx); - + soc->num_reg_tx_allowed = soc->num_tx_allowed - MAX_TX_SPL_DESC; if (soc->cdp_soc.ol_ops->get_dp_cfg_param) { int ret = soc->cdp_soc.ol_ops->get_dp_cfg_param(soc->ctrl_psoc, CDP_CFG_MAX_PEER_ID); @@ -17170,6 +17170,7 @@ static QDF_STATUS dp_pdev_init(struct cdp_soc_t *txrx_soc, qdf_event_create(&pdev->fw_obss_stats_event); pdev->num_tx_allowed = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx); + pdev->num_reg_tx_allowed = pdev->num_tx_allowed - MAX_TX_SPL_DESC; if (dp_rxdma_ring_setup(soc, pdev)) { dp_init_err("%pK: RXDMA ring config failed", soc); diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 9267b1cbbe..51190ad202 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -1155,7 +1155,7 @@ struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev, struct dp_pdev *pdev = vdev->pdev; struct dp_soc *soc = pdev->soc; - if (dp_tx_limit_check(vdev)) + if (dp_tx_limit_check(vdev, nbuf)) return NULL; /* Allocate software Tx descriptor */ @@ -1300,7 +1300,7 @@ static struct dp_tx_desc_s *dp_tx_prepare_desc(struct dp_vdev *vdev, struct dp_pdev *pdev = vdev->pdev; struct dp_soc *soc = pdev->soc; - if (dp_tx_limit_check(vdev)) + if (dp_tx_limit_check(vdev, nbuf)) return NULL; /* Allocate software Tx descriptor */ diff --git a/dp/wifi3.0/dp_tx.h b/dp/wifi3.0/dp_tx.h index 04f7353135..086258313f 100644 --- a/dp/wifi3.0/dp_tx.h +++ b/dp/wifi3.0/dp_tx.h @@ -1162,33 +1162,77 @@ dp_update_tx_desc_stats(struct dp_pdev *pdev) #endif /* CONFIG_WLAN_SYSFS_MEM_STATS */ #ifdef QCA_TX_LIMIT_CHECK +static inline bool is_spl_packet(qdf_nbuf_t nbuf) +{ + if (qdf_nbuf_is_ipv4_eapol_pkt(nbuf)) + return true; + return false; +} + /** - * dp_tx_limit_check - Check if allocated tx descriptors reached - * soc max limit and pdev max limit + * is_dp_spl_tx_limit_reached - Check if the packet is a special packet to allow + * allocation if allocated tx descriptors are within the soc max limit + * and pdev max limit. * @vdev: DP vdev handle * * Return: true if allocated tx descriptors reached max configured value, else * false */ static inline bool -dp_tx_limit_check(struct dp_vdev *vdev) +is_dp_spl_tx_limit_reached(struct dp_vdev *vdev, qdf_nbuf_t nbuf) +{ + struct dp_pdev *pdev = vdev->pdev; + struct dp_soc *soc = pdev->soc; + + if (is_spl_packet(nbuf)) { + if (qdf_atomic_read(&soc->num_tx_outstanding) >= + soc->num_tx_allowed) + return true; + + if (qdf_atomic_read(&pdev->num_tx_outstanding) >= + pdev->num_tx_allowed) + return true; + + return false; + } + + return true; +} + +/** + * dp_tx_limit_check - Check if allocated tx descriptors reached + * soc max reg limit and pdev max reg limit for regular packets. Also check if + * the limit is reached for special packets. + * @vdev: DP vdev handle + * + * Return: true if allocated tx descriptors reached max limit for regular + * packets and in case of special packets, if the limit is reached max + * configured vale for the soc/pdev, else false + */ +static inline bool +dp_tx_limit_check(struct dp_vdev *vdev, qdf_nbuf_t nbuf) { struct dp_pdev *pdev = vdev->pdev; struct dp_soc *soc = pdev->soc; if (qdf_atomic_read(&soc->num_tx_outstanding) >= - soc->num_tx_allowed) { - dp_tx_info("queued packets are more than max tx, drop the frame"); - DP_STATS_INC(vdev, tx_i.dropped.desc_na.num, 1); - return true; + soc->num_reg_tx_allowed) { + if (is_dp_spl_tx_limit_reached(vdev, nbuf)) { + dp_tx_info("queued packets are more than max tx, drop the frame"); + DP_STATS_INC(vdev, tx_i.dropped.desc_na.num, 1); + return true; + } } if (qdf_atomic_read(&pdev->num_tx_outstanding) >= - pdev->num_tx_allowed) { - dp_tx_info("queued packets are more than max tx, drop the frame"); - DP_STATS_INC(vdev, tx_i.dropped.desc_na.num, 1); - DP_STATS_INC(vdev, tx_i.dropped.desc_na_exc_outstand.num, 1); - return true; + pdev->num_reg_tx_allowed) { + if (is_dp_spl_tx_limit_reached(vdev, nbuf)) { + dp_tx_info("queued packets are more than max tx, drop the frame"); + DP_STATS_INC(vdev, tx_i.dropped.desc_na.num, 1); + DP_STATS_INC(vdev, + tx_i.dropped.desc_na_exc_outstand.num, 1); + return true; + } } return false; } @@ -1251,7 +1295,7 @@ dp_tx_outstanding_dec(struct dp_pdev *pdev) #else //QCA_TX_LIMIT_CHECK static inline bool -dp_tx_limit_check(struct dp_vdev *vdev) +dp_tx_limit_check(struct dp_vdev *vdev, qdf_nbuf_t nbuf) { return false; } diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index aac9d51857..a16b61de89 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -81,6 +81,9 @@ #define MAX_TXDESC_POOLS 4 #endif +/* Max no of descriptors to handle special frames like EAPOL */ +#define MAX_TX_SPL_DESC 1024 + #define MAX_RXDESC_POOLS 4 #define MAX_PPE_TXDESC_POOLS 1 @@ -2473,6 +2476,8 @@ struct dp_soc { qdf_atomic_t num_tx_exception; /* Num Tx allowed */ uint32_t num_tx_allowed; + /* Num Regular Tx allowed */ + uint32_t num_reg_tx_allowed; /* Preferred HW mode */ uint8_t preferred_hw_mode; @@ -3139,6 +3144,12 @@ struct dp_pdev { /* User configured max number of tx buffers */ uint32_t num_tx_allowed; + /* + * User configured max num of tx buffers excluding the + * number of buffers reserved for handling special frames + */ + uint32_t num_reg_tx_allowed; + /* unique cookie required for peer session */ uint32_t next_peer_cookie;