All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrzej Ostruszka <amo@semihalf.com>
To: dev@dpdk.org
Cc: mw@semihalf.com, nadavh@marvell.com, Zyta Szpak <zr@semihalf.com>,
	Natalie Samsonov <nsamsono@marvell.com>
Subject: [PATCH v3 13/13] net/mvpp2: add Tx scatter/gather support
Date: Tue, 25 Sep 2018 09:05:09 +0200	[thread overview]
Message-ID: <1537859109-25659-14-git-send-email-amo@semihalf.com> (raw)
In-Reply-To: <1537859109-25659-1-git-send-email-amo@semihalf.com>

From: Zyta Szpak <zr@semihalf.com>

The patch introduces scatter/gather support on transmit path.
A separate Tx callback is added and set if the application
requests multisegment Tx offload. Multiple descriptors are
sent per one packet.

Signed-off-by: Zyta Szpak <zr@semihalf.com>
Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Reviewed-by: Yelena Krivosheev <yelena@marvell.com>
---
 drivers/net/mvpp2/mrvl_ethdev.c | 231 ++++++++++++++++++++++++++++++++++++----
 drivers/net/mvpp2/mrvl_ethdev.h |   1 +
 2 files changed, 212 insertions(+), 20 deletions(-)

diff --git a/drivers/net/mvpp2/mrvl_ethdev.c b/drivers/net/mvpp2/mrvl_ethdev.c
index 26497ef..0682c63 100644
--- a/drivers/net/mvpp2/mrvl_ethdev.c
+++ b/drivers/net/mvpp2/mrvl_ethdev.c
@@ -64,7 +64,8 @@
 /** Port Tx offloads capabilities */
 #define MRVL_TX_OFFLOADS (DEV_TX_OFFLOAD_IPV4_CKSUM | \
 			  DEV_TX_OFFLOAD_UDP_CKSUM | \
-			  DEV_TX_OFFLOAD_TCP_CKSUM)
+			  DEV_TX_OFFLOAD_TCP_CKSUM | \
+			  DEV_TX_OFFLOAD_MULTI_SEGS)
 
 static const char * const valid_args[] = {
 	MRVL_IFACE_NAME_ARG,
@@ -104,7 +105,9 @@ struct mrvl_shadow_txq {
 	int head;           /* write index - used when sending buffers */
 	int tail;           /* read index - used when releasing buffers */
 	u16 size;           /* queue occupied size */
-	u16 num_to_release; /* number of buffers sent, that can be released */
+	u16 num_to_release; /* number of descriptors sent, that can be
+			     * released
+			     */
 	struct buff_release_entry ent[MRVL_PP2_TX_SHADOWQ_SIZE]; /* q entries */
 };
 
@@ -136,6 +139,12 @@ static inline void mrvl_free_sent_buffers(struct pp2_ppio *ppio,
 			struct pp2_hif *hif, unsigned int core_id,
 			struct mrvl_shadow_txq *sq, int qid, int force);
 
+static uint16_t mrvl_tx_pkt_burst(void *txq, struct rte_mbuf **tx_pkts,
+				  uint16_t nb_pkts);
+static uint16_t mrvl_tx_sg_pkt_burst(void *txq,	struct rte_mbuf **tx_pkts,
+				     uint16_t nb_pkts);
+
+
 #define MRVL_XSTATS_TBL_ENTRY(name) { \
 	#name, offsetof(struct pp2_ppio_statistics, name),	\
 	sizeof(((struct pp2_ppio_statistics *)0)->name)		\
@@ -162,6 +171,31 @@ static struct {
 	MRVL_XSTATS_TBL_ENTRY(tx_errors)
 };
 
+static inline void
+mrvl_fill_shadowq(struct mrvl_shadow_txq *sq, struct rte_mbuf *buf)
+{
+	sq->ent[sq->head].buff.cookie = (uint64_t)buf;
+	sq->ent[sq->head].buff.addr = buf ?
+		rte_mbuf_data_iova_default(buf) : 0;
+
+	sq->ent[sq->head].bpool =
+		(unlikely(!buf || buf->port >= RTE_MAX_ETHPORTS ||
+		 buf->refcnt > 1)) ? NULL :
+		 mrvl_port_to_bpool_lookup[buf->port];
+
+	sq->head = (sq->head + 1) & MRVL_PP2_TX_SHADOWQ_MASK;
+	sq->size++;
+}
+
+static inline void
+mrvl_fill_desc(struct pp2_ppio_desc *desc, struct rte_mbuf *buf)
+{
+	pp2_ppio_outq_desc_reset(desc);
+	pp2_ppio_outq_desc_set_phys_addr(desc, rte_pktmbuf_iova(buf));
+	pp2_ppio_outq_desc_set_pkt_offset(desc, 0);
+	pp2_ppio_outq_desc_set_pkt_len(desc, rte_pktmbuf_data_len(buf));
+}
+
 static inline int
 mrvl_get_bpool_size(int pp2_id, int pool_id)
 {
@@ -241,6 +275,27 @@ mrvl_get_hif(struct mrvl_priv *priv, int core_id)
 }
 
 /**
+ * Set tx burst function according to offload flag
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mrvl_set_tx_function(struct rte_eth_dev *dev)
+{
+	struct mrvl_priv *priv = dev->data->dev_private;
+
+	/* Use a simple Tx queue (no offloads, no multi segs) if possible */
+	if (priv->multiseg) {
+		RTE_LOG(INFO, PMD, "Using multi-segment tx callback\n");
+		dev->tx_pkt_burst = mrvl_tx_sg_pkt_burst;
+	} else {
+		RTE_LOG(INFO, PMD, "Using single-segment tx callback\n");
+		dev->tx_pkt_burst = mrvl_tx_pkt_burst;
+	}
+}
+
+/**
  * Configure rss based on dpdk rss configuration.
  *
  * @param priv
@@ -316,6 +371,9 @@ mrvl_dev_configure(struct rte_eth_dev *dev)
 		dev->data->mtu = dev->data->dev_conf.rxmode.max_rx_pkt_len -
 				 MRVL_PP2_ETH_HDRS_LEN;
 
+	if (dev->data->dev_conf.txmode.offloads & DEV_TX_OFFLOAD_MULTI_SEGS)
+		priv->multiseg = 1;
+
 	ret = mrvl_configure_rxqs(priv, dev->data->port_id,
 				  dev->data->nb_rx_queues);
 	if (ret < 0)
@@ -663,6 +721,7 @@ mrvl_dev_start(struct rte_eth_dev *dev)
 
 	mrvl_flow_init(dev);
 	mrvl_mtr_init(dev);
+	mrvl_set_tx_function(dev);
 
 	return 0;
 out:
@@ -2429,22 +2488,8 @@ mrvl_tx_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 			rte_mbuf_prefetch_part2(pref_pkt_hdr);
 		}
 
-		sq->ent[sq->head].buff.cookie = (uint64_t)mbuf;
-		sq->ent[sq->head].buff.addr =
-			rte_mbuf_data_iova_default(mbuf);
-		sq->ent[sq->head].bpool =
-			(unlikely(mbuf->port >= RTE_MAX_ETHPORTS ||
-			 mbuf->refcnt > 1)) ? NULL :
-			 mrvl_port_to_bpool_lookup[mbuf->port];
-		sq->head = (sq->head + 1) & MRVL_PP2_TX_SHADOWQ_MASK;
-		sq->size++;
-
-		pp2_ppio_outq_desc_reset(&descs[i]);
-		pp2_ppio_outq_desc_set_phys_addr(&descs[i],
-						 rte_pktmbuf_iova(mbuf));
-		pp2_ppio_outq_desc_set_pkt_offset(&descs[i], 0);
-		pp2_ppio_outq_desc_set_pkt_len(&descs[i],
-					       rte_pktmbuf_pkt_len(mbuf));
+		mrvl_fill_shadowq(sq, mbuf);
+		mrvl_fill_desc(&descs[i], mbuf);
 
 		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
 		/*
@@ -2482,6 +2527,152 @@ mrvl_tx_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 	return nb_pkts;
 }
 
+/** DPDK callback for S/G transmit.
+ *
+ * @param txq
+ *   Generic pointer transmit queue.
+ * @param tx_pkts
+ *   Packets to transmit.
+ * @param nb_pkts
+ *   Number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully transmitted.
+ */
+static uint16_t
+mrvl_tx_sg_pkt_burst(void *txq, struct rte_mbuf **tx_pkts,
+		     uint16_t nb_pkts)
+{
+	struct mrvl_txq *q = txq;
+	struct mrvl_shadow_txq *sq;
+	struct pp2_hif *hif;
+	struct pp2_ppio_desc descs[nb_pkts * PP2_PPIO_DESC_NUM_FRAGS];
+	struct pp2_ppio_sg_pkts pkts;
+	uint8_t frags[nb_pkts];
+	unsigned int core_id = rte_lcore_id();
+	int i, j, ret, bytes_sent = 0;
+	int tail, tail_first;
+	uint16_t num, sq_free_size;
+	uint16_t nb_segs, total_descs = 0;
+	uint64_t addr;
+
+	hif = mrvl_get_hif(q->priv, core_id);
+	sq = &q->shadow_txqs[core_id];
+	pkts.frags = frags;
+	pkts.num = 0;
+
+	if (unlikely(!q->priv->ppio || !hif))
+		return 0;
+
+	if (sq->size)
+		mrvl_free_sent_buffers(q->priv->ppio, hif, core_id,
+				       sq, q->queue_id, 0);
+
+	/* Save shadow queue free size */
+	sq_free_size = MRVL_PP2_TX_SHADOWQ_SIZE - sq->size - 1;
+
+	tail = 0;
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf = tx_pkts[i];
+		struct rte_mbuf *seg = NULL;
+		int gen_l3_cksum, gen_l4_cksum;
+		enum pp2_outq_l3_type l3_type;
+		enum pp2_outq_l4_type l4_type;
+
+		nb_segs = mbuf->nb_segs;
+		tail_first = tail;
+		total_descs += nb_segs;
+
+		/*
+		 * Check if total_descs does not exceed
+		 * shadow queue free size
+		 */
+		if (unlikely(total_descs > sq_free_size)) {
+			total_descs -= nb_segs;
+			RTE_LOG(DEBUG, PMD,
+				"No room in shadow queue for %d packets! "
+				"%d packets will be sent.\n",
+				nb_pkts, i);
+			break;
+		}
+
+		/* Check if nb_segs does not exceed the max nb of desc per
+		 * fragmented packet
+		 */
+		if (nb_segs > PP2_PPIO_DESC_NUM_FRAGS) {
+			total_descs -= nb_segs;
+			RTE_LOG(ERR, PMD,
+				"Too many segments. Packet won't be sent.\n");
+			break;
+		}
+
+		if (likely(nb_pkts - i > MRVL_MUSDK_PREFETCH_SHIFT)) {
+			struct rte_mbuf *pref_pkt_hdr;
+
+			pref_pkt_hdr = tx_pkts[i + MRVL_MUSDK_PREFETCH_SHIFT];
+			rte_mbuf_prefetch_part1(pref_pkt_hdr);
+			rte_mbuf_prefetch_part2(pref_pkt_hdr);
+		}
+
+		pkts.frags[pkts.num] = nb_segs;
+		pkts.num++;
+
+		seg = mbuf;
+		for (j = 0; j < nb_segs - 1; j++) {
+			/* For the subsequent segments, set shadow queue
+			 * buffer to NULL
+			 */
+			mrvl_fill_shadowq(sq, NULL);
+			mrvl_fill_desc(&descs[tail], seg);
+
+			tail++;
+			seg = seg->next;
+		}
+		/* Put first mbuf info in last shadow queue entry */
+		mrvl_fill_shadowq(sq, mbuf);
+		/* Update descriptor with last segment */
+		mrvl_fill_desc(&descs[tail++], seg);
+
+		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
+		/* In case unsupported ol_flags were passed
+		 * do not update descriptor offload information
+		 */
+		ret = mrvl_prepare_proto_info(mbuf->ol_flags, mbuf->packet_type,
+					      &l3_type, &l4_type, &gen_l3_cksum,
+					      &gen_l4_cksum);
+		if (unlikely(ret))
+			continue;
+
+		pp2_ppio_outq_desc_set_proto_info(&descs[tail_first], l3_type,
+						  l4_type, mbuf->l2_len,
+						  mbuf->l2_len + mbuf->l3_len,
+						  gen_l3_cksum, gen_l4_cksum);
+	}
+
+	num = total_descs;
+	pp2_ppio_send_sg(q->priv->ppio, hif, q->queue_id, descs,
+			 &total_descs, &pkts);
+	/* number of packets that were not sent */
+	if (unlikely(num > total_descs)) {
+		for (i = total_descs; i < num; i++) {
+			sq->head = (MRVL_PP2_TX_SHADOWQ_SIZE + sq->head - 1) &
+				MRVL_PP2_TX_SHADOWQ_MASK;
+
+			addr = sq->ent[sq->head].buff.cookie;
+			if (addr)
+				bytes_sent -=
+					rte_pktmbuf_pkt_len((struct rte_mbuf *)
+						(cookie_addr_high | addr));
+		}
+		sq->size -= num - total_descs;
+		nb_pkts = pkts.num;
+	}
+
+	q->bytes_sent += bytes_sent;
+
+	return nb_pkts;
+}
+
 /**
  * Initialize packet processor.
  *
@@ -2610,11 +2801,11 @@ mrvl_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
 	       req.ifr_addr.sa_data, ETHER_ADDR_LEN);
 
-	eth_dev->rx_pkt_burst = mrvl_rx_pkt_burst;
-	eth_dev->tx_pkt_burst = mrvl_tx_pkt_burst;
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
 	eth_dev->data->dev_private = priv;
 	eth_dev->device = &vdev->device;
+	eth_dev->rx_pkt_burst = mrvl_rx_pkt_burst;
+	mrvl_set_tx_function(eth_dev);
 	eth_dev->dev_ops = &mrvl_ops;
 
 	rte_eth_dev_probing_finish(eth_dev);
diff --git a/drivers/net/mvpp2/mrvl_ethdev.h b/drivers/net/mvpp2/mrvl_ethdev.h
index f0ae983..0120b9e 100644
--- a/drivers/net/mvpp2/mrvl_ethdev.h
+++ b/drivers/net/mvpp2/mrvl_ethdev.h
@@ -188,6 +188,7 @@ struct mrvl_priv {
 	uint8_t uc_mc_flushed;
 	uint8_t vlan_flushed;
 	uint8_t isolated;
+	uint8_t multiseg;
 
 	struct pp2_ppio_params ppio_params;
 	struct pp2_cls_qos_tbl_params qos_tbl_params;
-- 
2.7.4

  parent reply	other threads:[~2018-09-25  7:05 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-04  7:10 [PATCH 0/8] net/mvpp2: add new features Tomasz Duszynski
2018-09-04  7:10 ` [PATCH 1/8] net/mvpp2: initialize ppio only once Tomasz Duszynski
2018-09-04  7:10 ` [PATCH 2/8] net/mvpp2: move common code Tomasz Duszynski
2018-09-04  7:10 ` [PATCH 3/8] net/mvpp2: add metering support Tomasz Duszynski
2018-09-04  7:10 ` [PATCH 4/8] net/mvpp2: change default policer configuration Tomasz Duszynski
2018-09-04  7:10 ` [PATCH 5/8] net/mvpp2: add init and deinit to flow Tomasz Duszynski
2018-09-04  7:10 ` [PATCH 6/8] net/mvpp2: add traffic manager support Tomasz Duszynski
2018-09-04  7:10 ` [PATCH 7/8] net/mvpp2: detach tx_qos from rx cls/qos config Tomasz Duszynski
2018-09-04  7:10 ` [PATCH 8/8] net/mvpp2: update MTU and MRU related calculations Tomasz Duszynski
2018-09-04 13:49 ` [PATCH v2 00/12] net/mvpp2: add new features Tomasz Duszynski
2018-09-04 13:49   ` [PATCH v2 01/12] net/mvpp2: initialize ppio only once Tomasz Duszynski
2018-09-04 13:49   ` [PATCH v2 02/12] net/mvpp2: move common code Tomasz Duszynski
2018-09-04 13:49   ` [PATCH v2 03/12] net/mvpp2: add metering support Tomasz Duszynski
2018-09-04 13:49   ` [PATCH v2 04/12] net/mvpp2: change default policer configuration Tomasz Duszynski
2018-09-04 13:49   ` [PATCH v2 05/12] net/mvpp2: add init and deinit to flow Tomasz Duszynski
2018-09-04 13:49   ` [PATCH v2 06/12] net/mvpp2: add traffic manager support Tomasz Duszynski
2018-09-04 13:49   ` [PATCH v2 07/12] net/mvpp2: detach tx_qos from rx cls/qos config Tomasz Duszynski
2018-09-04 13:49   ` [PATCH v2 08/12] net/mvpp2: update MTU and MRU related calculations Tomasz Duszynski
2018-09-04 13:49   ` [PATCH v2 09/12] net/mvpp2: align with MUSDK 18.09 Tomasz Duszynski
2018-09-04 13:49   ` [PATCH v2 10/12] net/mvpp2: align documentation " Tomasz Duszynski
2018-09-19 17:15     ` Ferruh Yigit
2018-09-23 22:40       ` Thomas Monjalon
2018-09-24 11:36         ` Ferruh Yigit
2018-09-24 11:51           ` Marcin Wojtas
2018-09-24 12:38             ` Ferruh Yigit
2018-09-24 12:44           ` Thomas Monjalon
2018-09-24 12:48             ` Marcin Wojtas
2018-09-24 12:50               ` Ferruh Yigit
2018-09-24 13:11                 ` Andrzej Ostruszka
2018-09-04 13:49   ` [PATCH v2 11/12] net/mvpp2: document MTR and TM usage Tomasz Duszynski
2018-09-23 22:45     ` Thomas Monjalon
2018-09-04 13:49   ` [PATCH v2 12/12] net/mvpp2: add Tx S/G support Tomasz Duszynski
2018-09-19 17:24   ` [PATCH v2 00/12] net/mvpp2: add new features Ferruh Yigit
2018-09-25  7:04   ` [PATCH v3 00/13] " Andrzej Ostruszka
2018-09-25  7:04     ` [PATCH v3 01/13] net/mvpp2: initialize ppio only once Andrzej Ostruszka
2018-09-25  7:04     ` [PATCH v3 02/13] net/mvpp2: move common code Andrzej Ostruszka
2018-09-25  7:04     ` [PATCH v3 03/13] net/mvpp2: add metering support Andrzej Ostruszka
2018-09-25  7:05     ` [PATCH v3 04/13] net/mvpp2: change default policer configuration Andrzej Ostruszka
2018-09-25  7:05     ` [PATCH v3 05/13] net/mvpp2: add init and deinit to flow Andrzej Ostruszka
2018-09-25  7:05     ` [PATCH v3 06/13] net/mvpp2: add traffic manager support Andrzej Ostruszka
2018-09-25  7:05     ` [PATCH v3 07/13] net/mvpp2: detach Tx QoS from Rx cls/QoS config Andrzej Ostruszka
2018-09-25  7:05     ` [PATCH v3 08/13] net/mvpp2: update MTU and MRU related calculations Andrzej Ostruszka
2018-09-25  7:05     ` [PATCH v3 09/13] net/mvpp2: align with MUSDK 18.09 Andrzej Ostruszka
2018-09-25  7:05     ` [PATCH v3 10/13] crypto/mvsam: get number of CIOs dynamically Andrzej Ostruszka
2018-09-25  7:05     ` [PATCH v3 11/13] net/mvpp2: align documentation with MUSDK 18.09 Andrzej Ostruszka
2018-09-25  7:05     ` [PATCH v3 12/13] net/mvpp2: document MTR and TM usage Andrzej Ostruszka
2018-09-25  7:05     ` Andrzej Ostruszka [this message]
2018-09-25 16:12     ` [PATCH v3 00/13] net/mvpp2: add new features Ferruh Yigit

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1537859109-25659-14-git-send-email-amo@semihalf.com \
    --to=amo@semihalf.com \
    --cc=dev@dpdk.org \
    --cc=mw@semihalf.com \
    --cc=nadavh@marvell.com \
    --cc=nsamsono@marvell.com \
    --cc=zr@semihalf.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.