Forráskód Böngészése

qcacld-3.0: Add IPA TX complete nbuf call back function

For IPA MCC SW TX path add IPA TX complete nbuf call back which
frees the IPA TX descriptor after TX completion.

Change-Id: Ic7baae3db11c6ae92daa722b30fa7028481c0f93
CRs-Fixed: 2240220
Sravan Kumar Kairam 6 éve
szülő
commit
1f8f8b320e

+ 2 - 1
components/ipa/core/inc/wlan_ipa_priv.h

@@ -588,7 +588,8 @@ struct wlan_ipa_priv {
 	qdf_spinlock_t q_lock;
 
 	qdf_list_node_t pend_desc_head;
-	qdf_list_t tx_desc_list;
+	struct wlan_ipa_tx_desc *tx_desc_pool;
+	qdf_list_t tx_desc_free_list;
 
 	struct wlan_ipa_stats stats;
 

+ 82 - 33
components/ipa/core/src/wlan_ipa_core.c

@@ -243,8 +243,8 @@ static void wlan_ipa_send_pkt_to_tl(
 
 	qdf_spin_lock_bh(&ipa_ctx->q_lock);
 	/* get free Tx desc and assign ipa_tx_desc pointer */
-	if (qdf_list_remove_front(&ipa_ctx->tx_desc_list,
-				 (qdf_list_node_t **)&tx_desc) ==
+	if (qdf_list_remove_front(&ipa_ctx->tx_desc_free_list,
+				  (qdf_list_node_t **)&tx_desc) ==
 	    QDF_STATUS_SUCCESS) {
 		tx_desc->ipa_tx_desc_ptr = ipa_tx_desc;
 		ipa_ctx->stats.num_tx_desc_q_cnt++;
@@ -1119,6 +1119,46 @@ static void wlan_ipa_cleanup_iface(struct wlan_ipa_iface_context *iface_context)
 	ipa_debug("exit: num_iface=%d", iface_context->ipa_ctx->num_iface);
 }
 
+/**
+ * wlan_ipa_nbuf_cb() - IPA TX complete callback
+ * @skb: packet buffer which was transmitted
+ *
+ * Return: None
+ */
+static void wlan_ipa_nbuf_cb(qdf_nbuf_t skb)
+{
+	struct wlan_ipa_priv *ipa_ctx = gp_ipa;
+	qdf_ipa_rx_data_t *ipa_tx_desc;
+	struct wlan_ipa_tx_desc *tx_desc;
+	uint16_t id;
+
+	if (!qdf_nbuf_ipa_owned_get(skb)) {
+		dev_kfree_skb_any(skb);
+		return;
+	}
+
+	/* Get Tx desc pointer from SKB CB */
+	id = QDF_NBUF_CB_TX_IPA_PRIV(skb);
+	tx_desc = &ipa_ctx->tx_desc_pool[id];
+	ipa_tx_desc = tx_desc->ipa_tx_desc_ptr;
+
+	/* Return Tx Desc to IPA */
+	qdf_ipa_free_skb(ipa_tx_desc);
+
+	/* Return to free tx desc list */
+	qdf_spin_lock_bh(&ipa_ctx->q_lock);
+	tx_desc->ipa_tx_desc_ptr = NULL;
+	qdf_list_insert_back(&ipa_ctx->tx_desc_free_list, &tx_desc->node);
+	ipa_ctx->stats.num_tx_desc_q_cnt--;
+	qdf_spin_unlock_bh(&ipa_ctx->q_lock);
+
+	ipa_ctx->stats.num_tx_comp_cnt++;
+
+	qdf_atomic_dec(&ipa_ctx->tx_ref_cnt);
+
+	wlan_ipa_wdi_rm_try_release(ipa_ctx);
+}
+
 /**
  * wlan_ipa_setup_iface() - Setup IPA on a given interface
  * @ipa_ctx: IPA IPA global context
@@ -1198,6 +1238,9 @@ static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx,
 	if (status != QDF_STATUS_SUCCESS)
 		goto end;
 
+	/* Register IPA Tx desc free callback */
+	qdf_nbuf_reg_free_cb(wlan_ipa_nbuf_cb);
+
 	ipa_ctx->num_iface++;
 
 	ipa_debug("exit: num_iface=%d", ipa_ctx->num_iface);
@@ -1930,54 +1973,65 @@ wlan_ipa_uc_proc_pending_event(struct wlan_ipa_priv *ipa_ctx, bool is_loading)
  */
 static inline void wlan_ipa_free_tx_desc_list(struct wlan_ipa_priv *ipa_ctx)
 {
-	struct wlan_ipa_tx_desc *tmp_desc;
+	int i;
 	qdf_ipa_rx_data_t *ipa_tx_desc;
-	qdf_list_node_t *node;
+	uint32_t pool_size;
 
-	while (qdf_list_remove_front(&ipa_ctx->tx_desc_list, &node) ==
-	       QDF_STATUS_SUCCESS) {
-		tmp_desc = qdf_container_of(node, struct wlan_ipa_tx_desc,
-					    node);
+	if (!ipa_ctx->tx_desc_pool)
+		return;
 
-		ipa_tx_desc = tmp_desc->ipa_tx_desc_ptr;
+	qdf_spin_lock_bh(&ipa_ctx->q_lock);
+	pool_size = ipa_ctx->tx_desc_free_list.max_size;
+	for (i = 0; i < pool_size; i++) {
+		ipa_tx_desc = ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr;
 		if (ipa_tx_desc)
 			qdf_ipa_free_skb(ipa_tx_desc);
 
-		qdf_mem_free(tmp_desc);
-		tmp_desc = NULL;
+		if (qdf_list_remove_node(&ipa_ctx->tx_desc_free_list,
+					 &ipa_ctx->tx_desc_pool[i].node) !=
+		    QDF_STATUS_SUCCESS)
+			ipa_err("Failed to remove node from tx desc freelist");
 	}
+	qdf_spin_unlock_bh(&ipa_ctx->q_lock);
+
+	qdf_list_destroy(&ipa_ctx->tx_desc_free_list);
+	qdf_mem_free(ipa_ctx->tx_desc_pool);
+	ipa_ctx->tx_desc_pool = NULL;
+
+	ipa_ctx->stats.num_tx_desc_q_cnt = 0;
+	ipa_ctx->stats.num_tx_desc_error = 0;
 }
 
 /**
- * wlan_ipa_alloc_tx_desc_list() - Allocate IPA Tx desc list
+ * wlan_ipa_alloc_tx_desc_free_list() - Allocate IPA Tx desc list
  * @ipa_ctx: IPA context
  *
  * Return: QDF_STATUS
  */
-static QDF_STATUS wlan_ipa_alloc_tx_desc_list(struct wlan_ipa_priv *ipa_ctx)
+static QDF_STATUS
+wlan_ipa_alloc_tx_desc_free_list(struct wlan_ipa_priv *ipa_ctx)
 {
 	int i;
 	uint32_t max_desc_cnt;
-	struct wlan_ipa_tx_desc *tmp_desc;
 
 	max_desc_cnt = ipa_ctx->config->txbuf_count;
 
-	qdf_list_create(&ipa_ctx->tx_desc_list, max_desc_cnt);
+	ipa_ctx->tx_desc_pool = qdf_mem_malloc(sizeof(struct wlan_ipa_tx_desc) *
+					       max_desc_cnt);
 
-	qdf_spin_lock_bh(&ipa_ctx->q_lock);
-	for (i = 0; i < max_desc_cnt; i++) {
-		tmp_desc = qdf_mem_malloc(sizeof(*tmp_desc));
+	if (!ipa_ctx->tx_desc_pool) {
+		ipa_err("Free Tx descriptor allocation failed");
+		return QDF_STATUS_E_NOMEM;
+	}
 
-		if (!tmp_desc) {
-			qdf_spin_unlock_bh(&ipa_ctx->q_lock);
-			goto alloc_fail;
-		}
+	qdf_list_create(&ipa_ctx->tx_desc_free_list, max_desc_cnt);
 
-		tmp_desc->id = i;
-		tmp_desc->ipa_tx_desc_ptr = NULL;
-		qdf_list_insert_back(&ipa_ctx->tx_desc_list,
-				     &tmp_desc->node);
-		tmp_desc++;
+	qdf_spin_lock_bh(&ipa_ctx->q_lock);
+	for (i = 0; i < max_desc_cnt; i++) {
+		ipa_ctx->tx_desc_pool[i].id = i;
+		ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr = NULL;
+		qdf_list_insert_back(&ipa_ctx->tx_desc_free_list,
+				     &ipa_ctx->tx_desc_pool[i].node);
 	}
 
 	ipa_ctx->stats.num_tx_desc_q_cnt = 0;
@@ -1986,11 +2040,6 @@ static QDF_STATUS wlan_ipa_alloc_tx_desc_list(struct wlan_ipa_priv *ipa_ctx)
 	qdf_spin_unlock_bh(&ipa_ctx->q_lock);
 
 	return QDF_STATUS_SUCCESS;
-
-alloc_fail:
-	wlan_ipa_free_tx_desc_list(ipa_ctx);
-	return QDF_STATUS_E_NOMEM;
-
 }
 
 #ifndef QCA_LL_TX_FLOW_CONTROL_V2
@@ -2167,7 +2216,7 @@ static int wlan_ipa_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
 	}
 
        /* Allocate free Tx desc list */
-	ret = wlan_ipa_alloc_tx_desc_list(ipa_ctx);
+	ret = wlan_ipa_alloc_tx_desc_free_list(ipa_ctx);
 	if (ret)
 		goto setup_sys_pipe_fail;
 

+ 1 - 1
components/ipa/core/src/wlan_ipa_stats.c

@@ -600,7 +600,7 @@ static void wlan_ipa_print_txrx_stats(struct wlan_ipa_priv *ipa_ctx)
 		ipa_ctx->tx_ref_cnt.counter,
 		ipa_ctx->suspended,
 		&ipa_ctx->pend_desc_head,
-		&ipa_ctx->tx_desc_list);
+		&ipa_ctx->tx_desc_free_list);
 
 	for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {