DPDK patches and discussions
 help / color / mirror / Atom feed
From: Pavan Nikhilesh Bhagavatula <pbhagavatula@marvell.com>
To: Andrzej Ostruszka <amo@semihalf.com>, "dev@dpdk.org" <dev@dpdk.org>
Subject: Re: [dpdk-dev] [PATCH 2/2] net/octeontx2: add devargs to lock Rx/Tx ctx
Date: Thu, 19 Mar 2020 13:56:51 +0000
Message-ID: <CY4PR1801MB1863D94239DC2A4DCE52CE3CDEF40@CY4PR1801MB1863.namprd18.prod.outlook.com> (raw)
In-Reply-To: <74f0a4d7-8148-f117-a1df-03d814cbe4c8@semihalf.com>



>-----Original Message-----
>From: dev <dev-bounces@dpdk.org> On Behalf Of Andrzej Ostruszka
>Sent: Thursday, March 19, 2020 3:07 PM
>To: dev@dpdk.org
>Subject: Re: [dpdk-dev] [PATCH 2/2] net/octeontx2: add devargs to lock
>Rx/Tx ctx
>
>On 3/6/20 5:35 PM, pbhagavatula@marvell.com wrote:
>> From: Pavan Nikhilesh <pbhagavatula@marvell.com>
>>
>> Add device arguments to lock Rx/Tx contexts.
>> Application can either choose to lock Rx or Tx contexts by using
>> 'lock_rx_ctx' or 'lock_tx_ctx' respectively per each port.
>>
>> Example:
>> 	-w 0002:02:00.0,lock_rx_ctx=1 -w 0002:03:00.0,lock_tx_ctx=1
>>
>> Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com>
>> ---
>>  doc/guides/nics/octeontx2.rst               |  14 ++
>>  drivers/net/octeontx2/otx2_ethdev.c         | 179
>+++++++++++++++++++-
>>  drivers/net/octeontx2/otx2_ethdev.h         |   2 +
>>  drivers/net/octeontx2/otx2_ethdev_devargs.c |  16 +-
>>  drivers/net/octeontx2/otx2_rss.c            |  23 +++
>>  5 files changed, 231 insertions(+), 3 deletions(-)
>>
>> diff --git a/doc/guides/nics/octeontx2.rst
>b/doc/guides/nics/octeontx2.rst
>> index 819d09e11..6a13c9b26 100644
>> --- a/doc/guides/nics/octeontx2.rst
>> +++ b/doc/guides/nics/octeontx2.rst
>> @@ -207,6 +207,20 @@ Runtime Config Options
>>     With the above configuration, application can enable inline IPsec
>processing
>>     on 128 SAs (SPI 0-127).
>>
>> +- ``Lock Rx contexts in NDC cache``
>> +
>> +   Lock Rx contexts in NDC cache by using ``lock_rx_ctx`` parameter.
>> +
>> +   For example::
>> +      -w 0002:02:00.0,lock_rx_ctx=1
>
>"=1" is needed because of kvargs require it?  If that is the case then
>I'll think about extending kvargs to accept simple keys - this syntax
>doesn't feel right when all one really wants is just to test the
>presence of flag (for 1/true) or its lack (for 0/false).
>

Kvargs requirea key value pair with RTE_KVARGS_KV_DELIM `=` as the delimiter.

>BTW - extra line break after "::"

Will fix in v2.

>
>> +
>> +- ``Lock Tx contexts in NDC cache``
>> +
>> +   Lock Tx contexts in NDC cache by using ``lock_tx_ctx`` parameter.
>> +
>> +   For example::
>> +      -w 0002:02:00.0,lock_tx_ctx=1
>
>Same as above
>
>[...]
>> diff --git a/drivers/net/octeontx2/otx2_ethdev.c
>b/drivers/net/octeontx2/otx2_ethdev.c
>> index e60f4901c..592fef458 100644
>> --- a/drivers/net/octeontx2/otx2_ethdev.c
>> +++ b/drivers/net/octeontx2/otx2_ethdev.c
>> @@ -381,6 +381,38 @@ nix_cq_rq_init(struct rte_eth_dev *eth_dev,
>struct otx2_eth_dev *dev,
>>  		goto fail;
>>  	}
>>
>> +	if (dev->lock_rx_ctx) {
>> +		aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
>> +		aq->qidx = qid;
>> +		aq->ctype = NIX_AQ_CTYPE_CQ;
>> +		aq->op = NIX_AQ_INSTOP_LOCK;
>> +
>> +		aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
>> +		if (!aq) {
>> +			/* The shared memory buffer can be full.
>> +			 * Flush it and retry
>> +			 */
>> +			otx2_mbox_msg_send(mbox, 0);
>> +			rc = otx2_mbox_wait_for_rsp(mbox, 0);
>> +			if (rc < 0) {
>> +				otx2_err("Failed to LOCK cq context");
>> +				return 0;
>
>Similar comments as for the previous patch.  Is this not a failure?  If
>so why "return 0"?  If not failure don't log it as an error. 

Since, NDC locking is done as FIFO Locking might fail but it is not a 
catastrophic failure as NIX will function normally. I'd still like to log
it as an error for visibility.

> BTW here
>the failure is not for locking but for flushing of the mbox (right?) 

otx2_mbox_msg_send will never fail. We might get timeout while waiting for the 
response which we should consider as AQ instruction failure.

>so maybe change the err-msg to differentiate from the case below.


>
>> +			}
>> +
>> +			aq =
>otx2_mbox_alloc_msg_nix_aq_enq(mbox);
>> +			if (!aq) {
>> +				otx2_err("Failed to LOCK rq context");
>> +				return 0;
>
>Same as above - error or not?
>
>> +			}
>> +		}
>> +		aq->qidx = qid;
>> +		aq->ctype = NIX_AQ_CTYPE_RQ;
>> +		aq->op = NIX_AQ_INSTOP_LOCK;
>> +		rc = otx2_mbox_process(mbox);
>> +		if (rc < 0)
>> +			otx2_err("Failed to LOCK rq context");
>
>Ditto.
>
>> +	}
>> +
>>  	return 0;
>>  fail:
>>  	return rc;
>
>Same comments for *rq_uninit (below) as those for *rq_init (above).
>
>> @@ -430,6 +462,38 @@ nix_cq_rq_uninit(struct rte_eth_dev
>*eth_dev, struct otx2_eth_rxq *rxq)
>>  		return rc;
>>  	}
>>
>> +	if (dev->lock_rx_ctx) {
>> +		aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
>> +		aq->qidx = rxq->rq;
>> +		aq->ctype = NIX_AQ_CTYPE_CQ;
>> +		aq->op = NIX_AQ_INSTOP_UNLOCK;
>> +
>> +		aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
>> +		if (!aq) {
>> +			/* The shared memory buffer can be full.
>> +			 * Flush it and retry
>> +			 */
>> +			otx2_mbox_msg_send(mbox, 0);
>> +			rc = otx2_mbox_wait_for_rsp(mbox, 0);
>> +			if (rc < 0) {
>> +				otx2_err("Failed to UNLOCK cq
>context");
>> +				return 0;
>> +			}
>> +
>> +			aq =
>otx2_mbox_alloc_msg_nix_aq_enq(mbox);
>> +			if (!aq) {
>> +				otx2_err("Failed to UNLOCK rq
>context");
>> +				return 0;
>> +			}
>> +		}
>> +		aq->qidx = rxq->rq;
>> +		aq->ctype = NIX_AQ_CTYPE_RQ;
>> +		aq->op = NIX_AQ_INSTOP_UNLOCK;
>> +		rc = otx2_mbox_process(mbox);
>> +		if (rc < 0)
>> +			otx2_err("Failed to UNLOCK rq context");
>> +	}
>> +
>>  	return 0;
>>  }
>>
>
>And the same set of comments apply below to *sqb_lock/unlock - in
>addition one comment about err-msg.
>
>> @@ -715,6 +779,90 @@ nix_tx_offload_flags(struct rte_eth_dev
>*eth_dev)
>>  	return flags;
>>  }
>>
>> +static int
>> +nix_sqb_lock(struct rte_mempool *mp)
>> +{
>> +	struct otx2_npa_lf *npa_lf = otx2_intra_dev_get_cfg()->npa_lf;
>> +	struct npa_aq_enq_req *req;
>> +	int rc;
>> +
>> +	req = otx2_mbox_alloc_msg_npa_aq_enq(npa_lf->mbox);
>> +	req->aura_id = npa_lf_aura_handle_to_aura(mp->pool_id);
>> +	req->ctype = NPA_AQ_CTYPE_AURA;
>> +	req->op = NPA_AQ_INSTOP_LOCK;
>> +
>> +	req = otx2_mbox_alloc_msg_npa_aq_enq(npa_lf->mbox);
>> +	if (!req) {
>> +		/* The shared memory buffer can be full.
>> +		 * Flush it and retry
>> +		 */
>> +		otx2_mbox_msg_send(npa_lf->mbox, 0);
>> +		rc = otx2_mbox_wait_for_rsp(npa_lf->mbox, 0);
>> +		if (rc < 0) {
>> +			otx2_err("Failed to LOCK AURA context");
>> +			return 0;
>> +		}
>> +
>> +		req = otx2_mbox_alloc_msg_npa_aq_enq(npa_lf-
>>mbox);
>> +		if (!req) {
>> +			otx2_err("Failed to LOCK POOL context");
>
>Apart from the general err-or-not-err comment here you have not
>attempted to lock pool yet, you do that below.  Just like before use
>different msg 6 lines above (since you have only flushed - not
>attepmted
>to lock) and here use the "Failed to LOCK AURA context".  The same
>comment applies below for unlock.
>

AURA message would have already been delivered to AQ here. I think a more 
appropriate message would be "failed to get mbox memory for locking pool ctx."

>> +			return 0;
>> +		}
>> +	}
>> +
>> +	req->aura_id = npa_lf_aura_handle_to_aura(mp->pool_id);
>> +	req->ctype = NPA_AQ_CTYPE_POOL;
>> +	req->op = NPA_AQ_INSTOP_LOCK;
>> +
>> +	rc = otx2_mbox_process(npa_lf->mbox);
>> +	if (rc < 0)
>> +		otx2_err("Unable to lock POOL in NDC");
>> +
>> +	return 0;
>> +}
>> +
>> +static int
>> +nix_sqb_unlock(struct rte_mempool *mp)
>> +{
>> +	struct otx2_npa_lf *npa_lf = otx2_intra_dev_get_cfg()->npa_lf;
>> +	struct npa_aq_enq_req *req;
>> +	int rc;
>> +
>> +	req = otx2_mbox_alloc_msg_npa_aq_enq(npa_lf->mbox);
>> +	req->aura_id = npa_lf_aura_handle_to_aura(mp->pool_id);
>> +	req->ctype = NPA_AQ_CTYPE_AURA;
>> +	req->op = NPA_AQ_INSTOP_UNLOCK;
>> +
>> +	req = otx2_mbox_alloc_msg_npa_aq_enq(npa_lf->mbox);
>> +	if (!req) {
>> +		/* The shared memory buffer can be full.
>> +		 * Flush it and retry
>> +		 */
>> +		otx2_mbox_msg_send(npa_lf->mbox, 0);
>> +		rc = otx2_mbox_wait_for_rsp(npa_lf->mbox, 0);
>> +		if (rc < 0) {
>> +			otx2_err("Failed to UNLOCK AURA context");
>> +			return 0;
>> +		}
>> +
>> +		req = otx2_mbox_alloc_msg_npa_aq_enq(npa_lf-
>>mbox);
>> +		if (!req) {
>> +			otx2_err("Failed to UNLOCK POOL context");
>> +			return 0;
>> +		}
>> +	}
>> +	req = otx2_mbox_alloc_msg_npa_aq_enq(npa_lf->mbox);
>> +	req->aura_id = npa_lf_aura_handle_to_aura(mp->pool_id);
>> +	req->ctype = NPA_AQ_CTYPE_POOL;
>> +	req->op = NPA_AQ_INSTOP_UNLOCK;
>> +
>> +	rc = otx2_mbox_process(npa_lf->mbox);
>> +	if (rc < 0)
>> +		otx2_err("Unable to UNLOCK AURA in NDC");
>> +
>> +	return 0;
>> +}
>> +
>>  static int
>>  nix_sq_init(struct otx2_eth_txq *txq)
>>  {
>> @@ -757,7 +905,20 @@ nix_sq_init(struct otx2_eth_txq *txq)
>>  	/* Many to one reduction */
>>  	sq->sq.qint_idx = txq->sq % dev->qints;
>>
>> -	return otx2_mbox_process(mbox);
>> +	rc = otx2_mbox_process(mbox);
>> +	if (rc < 0)
>> +		return rc;
>> +
>> +	if (dev->lock_tx_ctx) {
>> +		sq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
>> +		sq->qidx = txq->sq;
>> +		sq->ctype = NIX_AQ_CTYPE_SQ;
>> +		sq->op = NIX_AQ_INSTOP_LOCK;
>> +
>> +		rc = otx2_mbox_process(mbox);
>> +	}
>> +
>> +	return rc;
>>  }
>>
>>  static int
>> @@ -800,6 +961,20 @@ nix_sq_uninit(struct otx2_eth_txq *txq)
>>  	if (rc)
>>  		return rc;
>>
>> +	if (dev->lock_tx_ctx) {
>> +		/* Unlock sq */
>> +		aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
>> +		aq->qidx = txq->sq;
>> +		aq->ctype = NIX_AQ_CTYPE_SQ;
>> +		aq->op = NIX_AQ_INSTOP_UNLOCK;
>> +
>> +		rc = otx2_mbox_process(mbox);
>> +		if (rc < 0)
>> +			return rc;
>> +
>> +		nix_sqb_unlock(txq->sqb_pool);
>> +	}
>> +
>>  	/* Read SQ and free sqb's */
>>  	aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
>>  	aq->qidx = txq->sq;
>> @@ -921,6 +1096,8 @@ nix_alloc_sqb_pool(int port, struct
>otx2_eth_txq *txq, uint16_t nb_desc)
>>  	}
>>
>>  	nix_sqb_aura_limit_cfg(txq->sqb_pool, txq->nb_sqb_bufs);
>> +	if (dev->lock_tx_ctx)
>> +		nix_sqb_lock(txq->sqb_pool);
>>
>>  	return 0;
>>  fail:
>> diff --git a/drivers/net/octeontx2/otx2_ethdev.h
>b/drivers/net/octeontx2/otx2_ethdev.h
>> index e5684f9f0..71f8cf729 100644
>> --- a/drivers/net/octeontx2/otx2_ethdev.h
>> +++ b/drivers/net/octeontx2/otx2_ethdev.h
>> @@ -287,6 +287,8 @@ struct otx2_eth_dev {
>>  	uint16_t scalar_ena;
>>  	uint16_t rss_tag_as_xor;
>>  	uint16_t max_sqb_count;
>> +	uint16_t lock_rx_ctx;
>> +	uint16_t lock_tx_ctx;
>>  	uint16_t rx_offload_flags; /* Selected Rx offload
>flags(NIX_RX_*_F) */
>>  	uint64_t rx_offloads;
>>  	uint16_t tx_offload_flags; /* Selected Tx offload
>flags(NIX_TX_*_F) */
>> diff --git a/drivers/net/octeontx2/otx2_ethdev_devargs.c
>b/drivers/net/octeontx2/otx2_ethdev_devargs.c
>> index bc11f54b5..0857d8247 100644
>> --- a/drivers/net/octeontx2/otx2_ethdev_devargs.c
>> +++ b/drivers/net/octeontx2/otx2_ethdev_devargs.c
>> @@ -124,6 +124,8 @@ parse_switch_header_type(const char *key,
>const char *value, void *extra_args)
>>  #define OTX2_FLOW_MAX_PRIORITY "flow_max_priority"
>>  #define OTX2_SWITCH_HEADER_TYPE "switch_header"
>>  #define OTX2_RSS_TAG_AS_XOR "tag_as_xor"
>> +#define OTX2_LOCK_RX_CTX "lock_rx_ctx"
>> +#define OTX2_LOCK_TX_CTX "lock_tx_ctx"
>>
>>  int
>>  otx2_ethdev_parse_devargs(struct rte_devargs *devargs, struct
>otx2_eth_dev *dev)
>> @@ -134,9 +136,11 @@ otx2_ethdev_parse_devargs(struct
>rte_devargs *devargs, struct otx2_eth_dev *dev)
>>  	uint16_t switch_header_type = 0;
>>  	uint16_t flow_max_priority = 3;
>>  	uint16_t ipsec_in_max_spi = 1;
>> -	uint16_t scalar_enable = 0;
>>  	uint16_t rss_tag_as_xor = 0;
>> +	uint16_t scalar_enable = 0;
>>  	struct rte_kvargs *kvlist;
>> +	uint16_t lock_rx_ctx = 0;
>> +	uint16_t lock_tx_ctx = 0;
>>
>>  	if (devargs == NULL)
>>  		goto null_devargs;
>> @@ -161,6 +165,10 @@ otx2_ethdev_parse_devargs(struct
>rte_devargs *devargs, struct otx2_eth_dev *dev)
>>  			   &parse_switch_header_type,
>&switch_header_type);
>>  	rte_kvargs_process(kvlist, OTX2_RSS_TAG_AS_XOR,
>>  			   &parse_flag, &rss_tag_as_xor);
>> +	rte_kvargs_process(kvlist, OTX2_LOCK_RX_CTX,
>> +			   &parse_flag, &lock_rx_ctx);
>> +	rte_kvargs_process(kvlist, OTX2_LOCK_TX_CTX,
>> +			   &parse_flag, &lock_tx_ctx);
>>  	otx2_parse_common_devargs(kvlist);
>>  	rte_kvargs_free(kvlist);
>>
>> @@ -169,6 +177,8 @@ otx2_ethdev_parse_devargs(struct
>rte_devargs *devargs, struct otx2_eth_dev *dev)
>>  	dev->scalar_ena = scalar_enable;
>>  	dev->rss_tag_as_xor = rss_tag_as_xor;
>>  	dev->max_sqb_count = sqb_count;
>> +	dev->lock_rx_ctx = lock_rx_ctx;
>> +	dev->lock_tx_ctx = lock_tx_ctx;
>>  	dev->rss_info.rss_size = rss_size;
>>  	dev->npc_flow.flow_prealloc_size = flow_prealloc_size;
>>  	dev->npc_flow.flow_max_priority = flow_max_priority;
>> @@ -187,4 +197,6 @@
>RTE_PMD_REGISTER_PARAM_STRING(net_octeontx2,
>>  			      OTX2_FLOW_PREALLOC_SIZE "=<1-32>"
>>  			      OTX2_FLOW_MAX_PRIORITY "=<1-32>"
>>  			      OTX2_SWITCH_HEADER_TYPE
>"=<higig2|dsa>"
>> -			      OTX2_RSS_TAG_AS_XOR "=1");
>> +			      OTX2_RSS_TAG_AS_XOR "=1"
>> +			      OTX2_LOCK_RX_CTX "=<1-65535>"
>> +			      OTX2_LOCK_TX_CTX "=<1-65535>");
>
>AFAIU the "=1" is required due to kvargs parsing limitation.  But why
>the range here is 1-65535 when all you want is just a boolean flag (if
>the key is present or not).
>

My bad we were debating whether it should be per Rx/Tx queue which would 
use a mask. I will fix it in v2.

>> diff --git a/drivers/net/octeontx2/otx2_rss.c
>b/drivers/net/octeontx2/otx2_rss.c
>> index 7a8c8f3de..34005ef02 100644
>> --- a/drivers/net/octeontx2/otx2_rss.c
>> +++ b/drivers/net/octeontx2/otx2_rss.c
>> @@ -33,6 +33,29 @@ otx2_nix_rss_tbl_init(struct otx2_eth_dev
>*dev,
>>  		req->qidx = (group * rss->rss_size) + idx;
>>  		req->ctype = NIX_AQ_CTYPE_RSS;
>>  		req->op = NIX_AQ_INSTOP_INIT;
>> +
>> +		if (!dev->lock_rx_ctx)
>> +			continue;
>> +
>> +		req = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
>> +		if (!req) {
>> +			/* The shared memory buffer can be full.
>> +			 * Flush it and retry
>> +			 */
>> +			otx2_mbox_msg_send(mbox, 0);
>> +			rc = otx2_mbox_wait_for_rsp(mbox, 0);
>> +			if (rc < 0)
>> +				return rc;
>> +
>> +			req =
>otx2_mbox_alloc_msg_nix_aq_enq(mbox);
>> +			if (!req)
>> +				return -ENOMEM;
>> +		}
>> +		req->rss.rq = ind_tbl[idx];
>> +		/* Fill AQ info */
>> +		req->qidx = (group * rss->rss_size) + idx;
>> +		req->ctype = NIX_AQ_CTYPE_RSS;
>> +		req->op = NIX_AQ_INSTOP_LOCK;
>>  	}
>>
>>  	otx2_mbox_msg_send(mbox, 0);
>>
>
>And here you treat the locking errors as errors - so I think you need to
>just adapt to this style and fix the previous comments.

I think here we should continue creating the RSS table without locking it as
It is not mandatory. I will modify accordingly in v2.

>
>With regards
>Andrzej Ostruszka

Thanks,
Pavan.

  reply	other threads:[~2020-03-19 13:57 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-06 16:35 [dpdk-dev] [PATCH 1/2] mempool/octeontx2: add devargs to lock ctx in cache pbhagavatula
2020-03-06 16:35 ` [dpdk-dev] [PATCH 2/2] net/octeontx2: add devargs to lock Rx/Tx ctx pbhagavatula
2020-03-19  9:36   ` Andrzej Ostruszka
2020-03-19 13:56     ` Pavan Nikhilesh Bhagavatula [this message]
2020-03-19  9:36 ` [dpdk-dev] [PATCH 1/2] mempool/octeontx2: add devargs to lock ctx in cache Andrzej Ostruszka
2020-03-19 13:35   ` Pavan Nikhilesh Bhagavatula
2020-03-24 16:53 ` [dpdk-dev] [dpdk-dev v2] " pbhagavatula
2020-03-24 16:53   ` [dpdk-dev] [dpdk-dev v2] [PATCH 2/2] net/octeontx2: add devargs to lock Rx/Tx ctx pbhagavatula
2020-03-25  6:51   ` [dpdk-dev] [dpdk-dev v2] [PATCH 1/2] mempool/octeontx2: add devargs to lock ctx in cache Jerin Jacob
2020-03-26  6:33   ` [dpdk-dev] [dpdk-dev v3] [PATCH] net/octeontx2: add devargs to lock Rx/Tx ctx pbhagavatula
2020-03-26 15:56     ` Andrzej Ostruszka [C]
2020-03-27  9:53     ` [dpdk-dev] [PATCH v4] " pbhagavatula
2020-03-27 16:19       ` Andrzej Ostruszka
2020-03-27 17:49         ` [dpdk-dev] [EXT] " Pavan Nikhilesh Bhagavatula
2020-03-31 13:58       ` [dpdk-dev] [PATCH v5] " pbhagavatula
2020-06-26  5:00         ` Jerin Jacob
2020-06-28 22:18         ` [dpdk-dev] [PATCH v6] " pbhagavatula
2020-07-02  9:46           ` Jerin Jacob
2020-03-26  6:34   ` [dpdk-dev] [dpdk-dev v3] [PATCH] mempool/octeontx2: add devargs to lock ctx in cache pbhagavatula
2020-04-06  8:39     ` Jerin Jacob
2020-04-16 22:33       ` Thomas Monjalon
2020-04-21  7:37         ` [dpdk-dev] [EXT] " Pavan Nikhilesh Bhagavatula
2020-04-22  8:06     ` [dpdk-dev] [PATCH v4] " pbhagavatula
2020-05-01 10:21       ` Pavan Nikhilesh Bhagavatula
2020-05-04 22:43         ` Thomas Monjalon
2020-05-10 22:35           ` [dpdk-dev] [EXT] " Pavan Nikhilesh Bhagavatula
2020-05-11 10:07       ` [dpdk-dev] [PATCH v5] " pbhagavatula
2020-05-19 16:15         ` Thomas Monjalon

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=CY4PR1801MB1863D94239DC2A4DCE52CE3CDEF40@CY4PR1801MB1863.namprd18.prod.outlook.com \
    --to=pbhagavatula@marvell.com \
    --cc=amo@semihalf.com \
    --cc=dev@dpdk.org \
    /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

DPDK patches and discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://inbox.dpdk.org/dev/0 dev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dev dev/ https://inbox.dpdk.org/dev \
		dev@dpdk.org
	public-inbox-index dev

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://inbox.dpdk.org/inbox.dpdk.dev


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git