[dpdk-dev] [PATCH 28/50] net/liquidio: add APIs for sg list

Shijith Thotton shijith.thotton at caviumnetworks.com
Tue Feb 21 10:26:43 CET 2017


SG list is used while sending packets with multiple segments.

Signed-off-by: Shijith Thotton <shijith.thotton at caviumnetworks.com>
Signed-off-by: Jerin Jacob <jerin.jacob at caviumnetworks.com>
Signed-off-by: Derek Chickles <derek.chickles at caviumnetworks.com>
Signed-off-by: Venkat Koppula <venkat.koppula at caviumnetworks.com>
Signed-off-by: Mallesham Jatharakonda <mjatharakonda at oneconvergence.com>
---
 drivers/net/liquidio/lio_ethdev.c |  23 ++++++++
 drivers/net/liquidio/lio_rxtx.c   | 107 ++++++++++++++++++++++++++++++++++++++
 drivers/net/liquidio/lio_rxtx.h   |   7 +++
 drivers/net/liquidio/lio_struct.h |  40 ++++++++++++++
 4 files changed, 177 insertions(+)

diff --git a/drivers/net/liquidio/lio_ethdev.c b/drivers/net/liquidio/lio_ethdev.c
index d096edc..8488342 100644
--- a/drivers/net/liquidio/lio_ethdev.c
+++ b/drivers/net/liquidio/lio_ethdev.c
@@ -202,6 +202,15 @@
 		return retval;
 	}
 
+	retval = lio_setup_sglists(lio_dev, q_no, fw_mapped_iq,
+				lio_dev->instr_queue[fw_mapped_iq]->max_count,
+				socket_id);
+
+	if (retval) {
+		lio_delete_instruction_queue(lio_dev, fw_mapped_iq);
+		return retval;
+	}
+
 	eth_dev->data->tx_queues[q_no] = lio_dev->instr_queue[fw_mapped_iq];
 
 	return 0;
@@ -334,6 +343,20 @@ static int lio_dev_configure(struct rte_eth_dev *eth_dev)
 	/* Copy the permanent MAC address */
 	ether_addr_copy((struct ether_addr *)mac, &eth_dev->data->mac_addrs[0]);
 
+	lio_dev->glist_lock =
+	    rte_zmalloc(NULL, sizeof(*lio_dev->glist_lock) * num_iqueues, 0);
+	if (lio_dev->glist_lock == NULL)
+		return -ENOMEM;
+
+	lio_dev->glist_head =
+		rte_zmalloc(NULL, sizeof(*lio_dev->glist_head) * num_iqueues,
+			    0);
+	if (lio_dev->glist_head == NULL) {
+		rte_free(lio_dev->glist_lock);
+		lio_dev->glist_lock = NULL;
+		return -ENOMEM;
+	}
+
 	lio_dev->port_configured = 1;
 
 	lio_free_soft_command(sc);
diff --git a/drivers/net/liquidio/lio_rxtx.c b/drivers/net/liquidio/lio_rxtx.c
index 11319b2..ec9e184 100644
--- a/drivers/net/liquidio/lio_rxtx.c
+++ b/drivers/net/liquidio/lio_rxtx.c
@@ -40,6 +40,8 @@
 #include "lio_ethdev.h"
 #include "lio_rxtx.h"
 
+#define LIO_MAX_SG 12
+
 static void
 lio_droq_compute_max_packet_bufs(struct lio_droq *droq)
 {
@@ -1272,3 +1274,108 @@ struct lio_soft_command *
 
 	return 0;
 }
+
+static inline struct lio_clist_node *
+list_delete_head(struct lio_clist_head *head)
+{
+	struct lio_clist_node *node;
+
+	if (CIRCLEQ_EMPTY(head))
+		node = NULL;
+	else
+		node = CIRCLEQ_FIRST(head);
+
+	if (node)
+		CIRCLEQ_REMOVE(head, node, entries);
+
+	return node;
+}
+
+static void
+lio_delete_sglist(struct lio_instr_queue *txq)
+{
+	struct lio_device *lio_dev = txq->lio_dev;
+	int iq_no = txq->q_index;
+	struct lio_gather *g;
+
+	if (lio_dev->glist_head == NULL)
+		return;
+
+	do {
+		g = (struct lio_gather *)list_delete_head(
+						&lio_dev->glist_head[iq_no]);
+		if (g) {
+			if (g->sg)
+				rte_free(
+				    (void *)((unsigned long)g->sg - g->adjust));
+			rte_free(g);
+		}
+	} while (g);
+}
+
+/**
+ * \brief Setup gather lists
+ * @param lio per-network private data
+ */
+int
+lio_setup_sglists(struct lio_device *lio_dev, int iq_no,
+		  int fw_mapped_iq, int num_descs, unsigned int socket_id)
+{
+	struct lio_gather *g;
+	int i;
+
+	rte_spinlock_init(&lio_dev->glist_lock[iq_no]);
+
+	CIRCLEQ_INIT(&lio_dev->glist_head[iq_no]);
+
+	for (i = 0; i < num_descs; i++) {
+		g = rte_zmalloc_socket(NULL, sizeof(*g), RTE_CACHE_LINE_SIZE,
+				       socket_id);
+		if (g == NULL) {
+			lio_dev_err(lio_dev,
+				    "lio_gather memory allocation failed for qno %d\n",
+				    iq_no);
+			break;
+		}
+
+		g->sg_size =
+		    ((ROUNDUP4(LIO_MAX_SG) >> 2) * LIO_SG_ENTRY_SIZE);
+
+		g->sg = rte_zmalloc_socket(NULL, g->sg_size + 8,
+					   RTE_CACHE_LINE_SIZE, socket_id);
+		if (g->sg == NULL) {
+			lio_dev_err(lio_dev,
+				    "sg list memory allocation failed for qno %d\n",
+				    iq_no);
+			rte_free(g);
+			break;
+		}
+
+		/* The gather component should be aligned on 64-bit boundary */
+		if (((unsigned long)g->sg) & 7) {
+			g->adjust = 8 - (((unsigned long)g->sg) & 7);
+			g->sg =
+			    (struct lio_sg_entry *)((unsigned long)g->sg +
+						       g->adjust);
+		}
+
+		CIRCLEQ_INSERT_TAIL(&lio_dev->glist_head[iq_no], &g->list,
+				    entries);
+	}
+
+	if (i != num_descs) {
+		lio_delete_sglist(lio_dev->instr_queue[fw_mapped_iq]);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void
+lio_delete_instruction_queue(struct lio_device *lio_dev, int iq_no)
+{
+	lio_delete_instr_queue(lio_dev, iq_no);
+	rte_free(lio_dev->instr_queue[iq_no]);
+	lio_dev->instr_queue[iq_no] = NULL;
+	lio_dev->num_iqs--;
+}
diff --git a/drivers/net/liquidio/lio_rxtx.h b/drivers/net/liquidio/lio_rxtx.h
index 6f8ec75..3fe178a 100644
--- a/drivers/net/liquidio/lio_rxtx.h
+++ b/drivers/net/liquidio/lio_rxtx.h
@@ -42,6 +42,10 @@
 
 #include "lio_struct.h"
 
+#ifndef ROUNDUP4
+#define ROUNDUP4(val) (((val) + 3) & 0xfffffffc)
+#endif
+
 #define LIO_CLIST_FIRST_ENTRY(ptr, type, elem)	\
 	(type *)((char *)((ptr)->cqh_first) - offsetof(type, elem))
 
@@ -548,9 +552,12 @@ uint16_t lio_dev_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 			   uint16_t budget);
 void lio_delete_droq_queue(struct lio_device *lio_dev, int oq_no);
 
+int lio_setup_sglists(struct lio_device *lio_dev, int iq_no,
+		      int fw_mapped_iq, int num_descs, unsigned int socket_id);
 int lio_setup_iq(struct lio_device *lio_dev, int q_index,
 		 union octeon_txpciq iq_no, uint32_t num_descs, void *app_ctx,
 		 unsigned int socket_id);
+void lio_delete_instruction_queue(struct lio_device *lio_dev, int iq_no);
 /** Setup instruction queue zero for the device
  *  @param lio_dev which lio device to setup
  *
diff --git a/drivers/net/liquidio/lio_struct.h b/drivers/net/liquidio/lio_struct.h
index bb4618f..1280785 100644
--- a/drivers/net/liquidio/lio_struct.h
+++ b/drivers/net/liquidio/lio_struct.h
@@ -298,6 +298,41 @@ struct lio_instr_queue {
 	const struct rte_memzone *iq_mz;
 };
 
+/* The Scatter-Gather List Entry. The scatter or gather component used with
+ * input instruction has this format.
+ */
+struct lio_sg_entry {
+	/** The first 64 bit gives the size of data in each dptr. */
+	union {
+		uint16_t size[4];
+		uint64_t size64;
+	} u;
+
+	/** The 4 dptr pointers for this entry. */
+	uint64_t ptr[4];
+};
+
+#define LIO_SG_ENTRY_SIZE	(sizeof(struct lio_sg_entry))
+
+/** Structure of a node in list of gather components maintained by
+ *  driver for each network device.
+ */
+struct lio_gather {
+	/** List manipulation. Next and prev pointers. */
+	struct lio_clist_node list;
+
+	/** Size of the gather component at sg in bytes. */
+	int sg_size;
+
+	/** Number of bytes that sg was adjusted to make it 8B-aligned. */
+	int adjust;
+
+	/** Gather component that can accommodate max sized fragment list
+	 *  received from the IP layer.
+	 */
+	struct lio_sg_entry *sg;
+};
+
 struct lio_io_enable {
 	uint64_t iq;
 	uint64_t oq;
@@ -516,6 +551,11 @@ struct lio_device {
 
 	uint32_t num_iqs;
 
+	/** Guards each glist */
+	rte_spinlock_t *glist_lock;
+	/** Array of gather component linked lists */
+	struct lio_clist_head *glist_head;
+
 	/* The pool containing pre allocated buffers used for soft commands */
 	struct rte_mempool *sc_buf_pool;
 
-- 
1.8.3.1



More information about the dev mailing list