Bläddra i källkod

qcacmn: Do not free Tx flow pool in case of MLO link switch

In case of MLO same adapter maps to both vdevs. Tx is done with
primary link vdev pool. In link switch case vdev0 flow pool is
deleted and traffic will continue to flow with same vdev0 flow_id
This is resulting in packets drops within the driver due non-availibilty
of flow pool.
Fix this by skipping flow pool deletion in case of STA MLO connection.

Change-Id: Ie56ea221f7f254484bd31ec4880f2155779fb513
CRs-Fixed: 3292979
Prakash Manjunathappa 2 år sedan
förälder
incheckning
44ece0c600
3 ändrade filer med 51 tillägg och 7 borttagningar
  1. 2 2
      dp/wifi3.0/dp_tx.c
  2. 1 0
      dp/wifi3.0/dp_tx_desc.h
  3. 48 5
      dp/wifi3.0/dp_tx_flow_control.c

+ 2 - 2
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;
 	}

+ 1 - 0
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++;
 	}
 

+ 48 - 5
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,