ソースを参照

qcacmn: Create a list of skbs to be freed at once

Create a list of skbs to be freed at once in dp tx completion path

Change-Id: I42129b4306206f7224ceabc87d07e2a87b8fcab6
CRs-Fixed: 3274945
Neha Bisht 3 年 前
コミット
5d0b7ea33f

+ 3 - 0
dp/wifi3.0/be/dp_be_tx.c

@@ -1514,6 +1514,9 @@ qdf_nbuf_t dp_tx_fast_send_be(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
 	tx_desc->flags |= DP_TX_DESC_FLAG_SIMPLE;
 	tx_desc->nbuf->fast_recycled = 1;
 
+	if (nbuf->is_from_recycler && nbuf->fast_xmit)
+		tx_desc->flags |= DP_TX_DESC_FLAG_FAST;
+
 	paddr =  dp_tx_nbuf_map_be(vdev, tx_desc, nbuf);
 	if (!paddr) {
 		/* Handle failure */

+ 50 - 8
dp/wifi3.0/dp_tx.c

@@ -5400,14 +5400,8 @@ void dp_tx_prefetch_next_nbuf_data(struct dp_tx_desc_s *next)
 
 	if (next)
 		nbuf = next->nbuf;
-	if (nbuf) {
-		/* prefetch skb->next and first few bytes of skb->cb */
-		qdf_prefetch(next->shinfo_addr);
+	if (nbuf)
 		qdf_prefetch(nbuf);
-		/* prefetch skb fields present in different cachelines */
-		qdf_prefetch(&nbuf->len);
-		qdf_prefetch(&nbuf->users);
-	}
 }
 #else
 static inline
@@ -5460,6 +5454,50 @@ dp_tx_mcast_reinject_handler(struct dp_soc *soc, struct dp_tx_desc_s *desc)
 }
 #endif
 
+#ifdef QCA_DP_TX_NBUF_LIST_FREE
+static inline void
+dp_tx_nbuf_queue_head_init(qdf_nbuf_queue_head_t *nbuf_queue_head)
+{
+	qdf_nbuf_queue_head_init(nbuf_queue_head);
+}
+
+static inline void
+dp_tx_nbuf_dev_queue_free(qdf_nbuf_queue_head_t *nbuf_queue_head,
+			  struct dp_tx_desc_s *desc)
+{
+	qdf_nbuf_t nbuf = NULL;
+
+	nbuf = desc->nbuf;
+	if (qdf_likely(desc->flags & DP_TX_DESC_FLAG_FAST))
+		qdf_nbuf_dev_queue_head(nbuf_queue_head, nbuf);
+	else
+		qdf_nbuf_free(nbuf);
+}
+
+static inline void
+dp_tx_nbuf_dev_kfree_list(qdf_nbuf_queue_head_t *nbuf_queue_head)
+{
+	qdf_nbuf_dev_kfree_list(nbuf_queue_head);
+}
+#else
+static inline void
+dp_tx_nbuf_queue_head_init(qdf_nbuf_queue_head_t *nbuf_queue_head)
+{
+}
+
+static inline void
+dp_tx_nbuf_dev_queue_free(qdf_nbuf_queue_head_t *nbuf_queue_head,
+			  struct dp_tx_desc_s *desc)
+{
+	qdf_nbuf_free(desc->nbuf);
+}
+
+static inline void
+dp_tx_nbuf_dev_kfree_list(qdf_nbuf_queue_head_t *nbuf_queue_head)
+{
+}
+#endif
+
 /**
  * dp_tx_comp_process_desc_list() - Tx complete software descriptor handler
  * @soc: core txrx main context
@@ -5481,9 +5519,12 @@ dp_tx_comp_process_desc_list(struct dp_soc *soc,
 	struct dp_txrx_peer *txrx_peer = NULL;
 	uint16_t peer_id = DP_INVALID_PEER;
 	dp_txrx_ref_handle txrx_ref_handle = NULL;
+	qdf_nbuf_queue_head_t h;
 
 	desc = comp_head;
 
+	dp_tx_nbuf_queue_head_init(&h);
+
 	while (desc) {
 		next = desc->next;
 		dp_tx_prefetch_next_nbuf_data(next);
@@ -5534,7 +5575,7 @@ dp_tx_comp_process_desc_list(struct dp_soc *soc,
 			dp_tx_desc_history_add(soc, desc->dma_addr, desc->nbuf,
 					       desc->id, DP_TX_COMP_UNMAP);
 			dp_tx_nbuf_unmap(soc, desc);
-			qdf_nbuf_free_simple(desc->nbuf);
+			dp_tx_nbuf_dev_queue_free(&h, desc);
 			dp_tx_desc_free(soc, desc, desc->pool_id);
 			desc = next;
 			continue;
@@ -5550,6 +5591,7 @@ dp_tx_comp_process_desc_list(struct dp_soc *soc,
 		dp_tx_desc_release(desc, desc->pool_id);
 		desc = next;
 	}
+	dp_tx_nbuf_dev_kfree_list(&h);
 	if (txrx_peer)
 		dp_txrx_peer_unref_delete(txrx_ref_handle, DP_MOD_ID_TX_COMP);
 }

+ 2 - 1
dp/wifi3.0/dp_tx.h

@@ -64,9 +64,10 @@
 /*
  * Since the Tx descriptor flag is of only 16-bit and no more bit is free for
  * any new flag, therefore for time being overloading PPEDS flag with that of
- * FLUSH flag.
+ * FLUSH flag and FLAG_FAST with TDLS which is not enabled for WIN.
  */
 #define DP_TX_DESC_FLAG_PPEDS		0x2000
+#define DP_TX_DESC_FLAG_FAST		0x100
 
 #define DP_TX_EXT_DESC_FLAG_METADATA_VALID 0x1
 

+ 57 - 0
qdf/inc/qdf_nbuf.h

@@ -1375,6 +1375,18 @@ void qdf_nbuf_queue_head_purge(qdf_nbuf_queue_head_t *nbuf_queue_head)
 	return __qdf_nbuf_queue_head_purge(nbuf_queue_head);
 }
 
+/**
+ * qdf_nbuf_queue_empty() - dequeue nbuf from the head of queue
+ * @nbuf_queue_head: pointer to nbuf queue head
+ *
+ * Return: true if queue is empty else false
+ */
+static inline
+int qdf_nbuf_queue_empty(qdf_nbuf_queue_head_t *nbuf_queue_head)
+{
+	return __qdf_nbuf_queue_empty(nbuf_queue_head);
+}
+
 /**
  * qdf_nbuf_queue_head_lock() - Acquire the nbuf_queue_head lock
  * @head: nbuf_queue_head of the nbuf_list for which lock is to be acquired
@@ -2233,6 +2245,21 @@ qdf_nbuf_t
 qdf_nbuf_unshare_debug(qdf_nbuf_t buf, const char *func_name,
 		       uint32_t line_num);
 
+/**
+ * qdf_nbuf_kfree_list() - Free nbuf list using kfree
+ * @buf: Pointer to network buffer head
+ *
+ * This function is called to free the nbuf list on failure cases
+ *
+ * Return: None
+ */
+#define qdf_nbuf_dev_kfree_list(d) \
+	qdf_nbuf_dev_kfree_list_debug(d, __func__, __LINE__)
+
+void
+qdf_nbuf_dev_kfree_list_debug(qdf_nbuf_queue_head_t *nbuf_queue_head,
+			      const char *func_name,
+			      uint32_t line_num);
 #else /* NBUF_MEMORY_DEBUG */
 
 static inline void qdf_net_buf_debug_init(void) {}
@@ -2362,8 +2389,38 @@ static inline qdf_nbuf_t qdf_nbuf_unshare(qdf_nbuf_t buf)
 {
 	return __qdf_nbuf_unshare(buf);
 }
+
+/**
+ * qdf_nbuf_kfree_list() - Free nbuf list using kfree
+ * @buf: Pointer to network buffer head
+ *
+ * This function is called to free the nbuf list on failure cases
+ *
+ * Return: None
+ */
+static inline void
+qdf_nbuf_dev_kfree_list(qdf_nbuf_queue_head_t *nbuf_queue_head)
+{
+	__qdf_nbuf_dev_kfree_list(nbuf_queue_head);
+}
 #endif /* NBUF_MEMORY_DEBUG */
 
+/**
+ * qdf_nbuf_dev_queue_head() - Queue a buffer at the list head
+ * @nbuf_queue_head: Pointer to buffer list head
+ * @buff: Pointer to network buffer head
+ *
+ * This function is called to queue a buffer at the list head
+ *
+ * Return: None
+ */
+static inline void
+qdf_nbuf_dev_queue_head(qdf_nbuf_queue_head_t *nbuf_queue_head,
+			qdf_nbuf_t buf)
+{
+	__qdf_nbuf_dev_queue_head(nbuf_queue_head, buf);
+}
+
 /**
  * qdf_nbuf_kfree() - Free nbuf using kfree
  * @buf: Pointer to network buffer

+ 33 - 0
qdf/linux/src/i_qdf_nbuf.h

@@ -2595,6 +2595,12 @@ void __qdf_nbuf_queue_head_purge(struct sk_buff_head *skb_queue_head)
 	return skb_queue_purge(skb_queue_head);
 }
 
+static inline
+int __qdf_nbuf_queue_empty(__qdf_nbuf_queue_head_t *nbuf_queue_head)
+{
+	return skb_queue_empty(nbuf_queue_head);
+}
+
 /**
  * __qdf_nbuf_queue_head_lock() - Acquire the skb list lock
  * @head: skb list for which lock is to be acquired
@@ -2905,6 +2911,33 @@ static inline void __qdf_nbuf_kfree(struct sk_buff *skb)
 	kfree_skb(skb);
 }
 
+/**
+ * __qdf_nbuf_dev_kfree_list() - Free nbuf list using dev based os call
+ * @skb_queue_head: Pointer to nbuf queue head
+ *
+ * This function is called to free the nbuf list on failure cases
+ *
+ * Return: None
+ */
+void
+__qdf_nbuf_dev_kfree_list(__qdf_nbuf_queue_head_t *nbuf_queue_head);
+
+/**
+ * __qdf_nbuf_dev_queue_head() - queue a buffer using dev at the list head
+ * @skb_queue_head: Pointer to skb list head
+ * @buff: Pointer to nbuf
+ *
+ * This function is called to queue buffer at the skb list head
+ *
+ * Return: None
+ */
+static inline void
+__qdf_nbuf_dev_queue_head(__qdf_nbuf_queue_head_t *nbuf_queue_head,
+			  __qdf_nbuf_t buff)
+{
+	 __skb_queue_head(nbuf_queue_head, buff);
+}
+
 /**
  * __qdf_nbuf_dev_kfree() - Free nbuf using dev based os call
  * @buf: Pointer to network buffer

+ 32 - 0
qdf/linux/src/qdf_nbuf.c

@@ -746,6 +746,21 @@ __qdf_nbuf_t __qdf_nbuf_clone(__qdf_nbuf_t skb)
 
 qdf_export_symbol(__qdf_nbuf_clone);
 
+#ifdef QCA_DP_TX_NBUF_LIST_FREE
+void
+__qdf_nbuf_dev_kfree_list(__qdf_nbuf_queue_head_t *nbuf_queue_head)
+{
+	dev_kfree_skb_list_fast(nbuf_queue_head);
+}
+#else
+void
+__qdf_nbuf_dev_kfree_list(__qdf_nbuf_queue_head_t *nbuf_queue_head)
+{
+}
+#endif
+
+qdf_export_symbol(__qdf_nbuf_dev_kfree_list);
+
 #ifdef NBUF_MEMORY_DEBUG
 struct qdf_nbuf_event {
 	qdf_nbuf_t nbuf;
@@ -3892,6 +3907,23 @@ unshare_buf:
 
 qdf_export_symbol(qdf_nbuf_unshare_debug);
 
+void
+qdf_nbuf_dev_kfree_list_debug(__qdf_nbuf_queue_head_t *nbuf_queue_head,
+			      const char *func, uint32_t line)
+{
+	qdf_nbuf_t  buf;
+
+	if (qdf_nbuf_queue_empty(nbuf_queue_head))
+		return;
+
+	if (is_initial_mem_debug_disabled)
+		return __qdf_nbuf_dev_kfree_list(nbuf_queue_head);
+
+	while ((buf = qdf_nbuf_queue_head_dequeue(nbuf_queue_head)) != NULL)
+		qdf_nbuf_free_debug(buf, func, line);
+}
+
+qdf_export_symbol(qdf_nbuf_dev_kfree_list_debug);
 #endif /* NBUF_MEMORY_DEBUG */
 
 #if defined(FEATURE_TSO)