Browse Source

qcacmn: Reorganize skb unmap, free and tx_desc free logic for TSO

In TX completion, we need to handle TSO frames release in below
sequence: Unmap skb -> free skb -> free this tx desc. Thus separate
skb unmapping and free tx descriptors for TSO logic.

CRs-Fixed: 2250960
Change-Id: I6979b4ec64e3f51bc6d8e485e843e2ab35eee86e
chenguo 7 years ago
parent
commit
ee42a3202b
1 changed files with 62 additions and 32 deletions
  1. 62 32
      dp/wifi3.0/dp_tx.c

+ 62 - 32
dp/wifi3.0/dp_tx.c

@@ -105,53 +105,88 @@ static inline void dp_tx_get_queue(struct dp_vdev *vdev,
 
 #if defined(FEATURE_TSO)
 /**
- * dp_tx_tso_desc_release() - Release the tso segment
- *                            after unmapping all the fragments
+ * dp_tx_tso_unmap_segment() - Unmap TSO segment
  *
- * @pdev - physical device handle
+ * @soc - core txrx main context
+ * @tx_desc - Tx software descriptor
+ */
+static void dp_tx_tso_unmap_segment(struct dp_soc *soc,
+				    struct dp_tx_desc_s *tx_desc)
+{
+	TSO_DEBUG("%s: Unmap the tso segment", __func__);
+	if (qdf_unlikely(!tx_desc->tso_desc)) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			  "%s %d TSO desc is NULL!",
+			  __func__, __LINE__);
+		qdf_assert(0);
+	} else if (qdf_unlikely(!tx_desc->tso_num_desc)) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			  "%s %d TSO num desc is NULL!",
+			  __func__, __LINE__);
+		qdf_assert(0);
+	} else {
+		bool is_last_seg;
+		struct qdf_tso_num_seg_elem_t *tso_num_desc =
+			(struct qdf_tso_num_seg_elem_t *)tx_desc->tso_num_desc;
+
+		if (tso_num_desc->num_seg.tso_cmn_num_seg > 1)
+			is_last_seg = false;
+		else
+			is_last_seg = true;
+		tso_num_desc->num_seg.tso_cmn_num_seg--;
+		qdf_nbuf_unmap_tso_segment(soc->osdev,
+					   tx_desc->tso_desc, is_last_seg);
+	}
+}
+
+/**
+ * dp_tx_tso_desc_release() - Release the tso segment and tso_cmn_num_seg
+ *                            back to the freelist
+ *
+ * @soc - soc device handle
  * @tx_desc - Tx software descriptor
  */
 static void dp_tx_tso_desc_release(struct dp_soc *soc,
-		struct dp_tx_desc_s *tx_desc)
+				   struct dp_tx_desc_s *tx_desc)
 {
 	TSO_DEBUG("%s: Free the tso descriptor", __func__);
-	if (qdf_unlikely(tx_desc->tso_desc == NULL)) {
+	if (qdf_unlikely(!tx_desc->tso_desc)) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
-			"%s %d TSO desc is NULL!",
-			__func__, __LINE__);
+			  "%s %d TSO desc is NULL!",
+			  __func__, __LINE__);
 		qdf_assert(0);
-	} else if (qdf_unlikely(tx_desc->tso_num_desc == NULL)) {
-		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
-			"%s %d TSO common info is NULL!",
-			__func__, __LINE__);
+	} else if (qdf_unlikely(!tx_desc->tso_num_desc)) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			  "%s %d TSO num desc is NULL!",
+			  __func__, __LINE__);
 		qdf_assert(0);
 	} else {
 		struct qdf_tso_num_seg_elem_t *tso_num_desc =
-			(struct qdf_tso_num_seg_elem_t *) tx_desc->tso_num_desc;
+			(struct qdf_tso_num_seg_elem_t *)tx_desc->tso_num_desc;
 
-		if (tso_num_desc->num_seg.tso_cmn_num_seg > 1) {
-			tso_num_desc->num_seg.tso_cmn_num_seg--;
-			qdf_nbuf_unmap_tso_segment(soc->osdev,
-					tx_desc->tso_desc, false);
-		} else {
-			tso_num_desc->num_seg.tso_cmn_num_seg--;
-			qdf_assert(tso_num_desc->num_seg.tso_cmn_num_seg == 0);
-			qdf_nbuf_unmap_tso_segment(soc->osdev,
-					tx_desc->tso_desc, true);
+		/* Add the tso num segment into the free list */
+		if (tso_num_desc->num_seg.tso_cmn_num_seg == 0) {
 			dp_tso_num_seg_free(soc, tx_desc->pool_id,
-					tx_desc->tso_num_desc);
+					    tx_desc->tso_num_desc);
 			tx_desc->tso_num_desc = NULL;
 		}
+
+		/* Add the tso segment into the free list*/
 		dp_tx_tso_desc_free(soc,
-				tx_desc->pool_id, tx_desc->tso_desc);
+				    tx_desc->pool_id, tx_desc->tso_desc);
 		tx_desc->tso_desc = NULL;
 	}
 }
 #else
+static void dp_tx_tso_unmap_segment(struct dp_soc *soc,
+				    struct dp_tx_desc_s *tx_desc)
+
+{
+}
+
 static void dp_tx_tso_desc_release(struct dp_soc *soc,
-		struct dp_tx_desc_s *tx_desc)
+				   struct dp_tx_desc_s *tx_desc)
 {
-	return;
 }
 #endif
 /**
@@ -2351,13 +2386,8 @@ static inline void dp_tx_comp_free_buf(struct dp_soc *soc,
 		/* TSO free */
 		if (hal_tx_ext_desc_get_tso_enable(
 					desc->msdu_ext_desc->vaddr)) {
-			/* If remaining number of segment is 0
-			 * actual TSO may unmap and free */
-			if (qdf_nbuf_get_users(nbuf) == 1)
-				__qdf_nbuf_unmap_single(soc->osdev,
-						nbuf,
-						QDF_DMA_TO_DEVICE);
-
+			/* unmap eash TSO seg before free the nbuf */
+			dp_tx_tso_unmap_segment(soc, desc);
 			qdf_nbuf_free(nbuf);
 			return;
 		}