diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 2dbc733185..139997da1d 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -2251,8 +2251,8 @@ dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf, tx_desc = dp_tx_prepare_desc_single(vdev, nbuf, tx_q->desc_pool_id, msdu_info, tx_exc_metadata); if (!tx_desc) { - dp_err_rl("Tx_desc prepare Fail vdev %pK queue %d", - vdev, tx_q->desc_pool_id); + dp_err_rl("Tx_desc prepare Fail vdev_id %d vdev %pK queue %d", + vdev->vdev_id, vdev, tx_q->desc_pool_id); drop_code = TX_DESC_ERR; goto fail_return; } diff --git a/dp/wifi3.0/dp_tx_desc.h b/dp/wifi3.0/dp_tx_desc.h index ce974d96da..98f03cb57f 100644 --- a/dp/wifi3.0/dp_tx_desc.h +++ b/dp/wifi3.0/dp_tx_desc.h @@ -382,6 +382,7 @@ dp_tx_desc_alloc(struct dp_soc *soc, uint8_t desc_pool_id) } qdf_spin_unlock_bh(&pool->flow_pool_lock); } else { + dp_err_rl("NULL desc pool pool_id %d", desc_pool_id); soc->pool_stats.pkt_drop_no_pool++; } diff --git a/dp/wifi3.0/dp_tx_flow_control.c b/dp/wifi3.0/dp_tx_flow_control.c index ff877c131e..c2168d50b8 100644 --- a/dp/wifi3.0/dp_tx_flow_control.c +++ b/dp/wifi3.0/dp_tx_flow_control.c @@ -375,6 +375,43 @@ struct dp_tx_desc_pool_s *dp_tx_create_flow_pool(struct dp_soc *soc, return pool; } +/** + * dp_is_tx_flow_pool_delete_allowed() - Can flow pool be deleted + * @soc: Handle to struct dp_soc + * @vdev_id: vdev_id corresponding to flow pool + * + * Check if it is OK to go ahead delete the flow pool. One of the case is + * MLO where it is not OK to delete the flow pool when link switch happens. + * + * Return: 0 for success or error + */ +static bool dp_is_tx_flow_pool_delete_allowed(struct dp_soc *soc, + uint8_t vdev_id) +{ + struct dp_vdev *vdev = NULL; + bool is_allow = true; + + vdev = dp_vdev_get_ref_by_id(soc, vdev_id, DP_MOD_ID_MISC); + + /* only check for sta mode */ + if (!vdev || vdev->opmode != wlan_op_mode_sta) + goto comp_ret; + + /* + * Only if current vdev is belong to MLO connection and connected, + * then it's not allowed to delete current pool, for legacy + * connection, allowed always. + */ + is_allow = policy_mgr_is_mlo_sta_disconnected( + (struct wlan_objmgr_psoc *)soc->ctrl_psoc, + vdev_id); +comp_ret: + if (vdev) + dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_MISC); + + return is_allow; +} + /** * dp_tx_delete_flow_pool() - delete flow pool * @soc: Handle to struct dp_soc @@ -400,9 +437,16 @@ int dp_tx_delete_flow_pool(struct dp_soc *soc, struct dp_tx_desc_pool_s *pool, return ENOMEM; } - dp_info("pool create_cnt=%d, avail_desc=%d, size=%d, status=%d", - pool->pool_create_cnt, pool->avail_desc, + dp_info("pool_id %d create_cnt=%d, avail_desc=%d, size=%d, status=%d", + pool->flow_pool_id, pool->pool_create_cnt, pool->avail_desc, pool->pool_size, pool->status); + + if (!dp_is_tx_flow_pool_delete_allowed(soc, pool->flow_pool_id)) { + dp_info("skip pool id %d delete as it's not allowed", + pool->flow_pool_id); + return -EAGAIN; + } + qdf_spin_lock_bh(&pool->flow_pool_lock); if (!pool->pool_create_cnt) { qdf_spin_unlock_bh(&pool->flow_pool_lock); @@ -568,9 +612,8 @@ void dp_tx_flow_pool_unmap_handler(struct dp_pdev *pdev, uint8_t flow_id, struct dp_tx_desc_pool_s *pool; enum htt_flow_type type = flow_type; - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "%s: flow_id %d flow_type %d flow_pool_id %d", - __func__, flow_id, flow_type, flow_pool_id); + dp_info("flow_id %d flow_type %d flow_pool_id %d", flow_id, flow_type, + flow_pool_id); if (qdf_unlikely(!pdev)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,