DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v2 1/3] crypto/aesni_gcm: fix J0 padding bytes for GCM
From: Azarewicz, PiotrX T @ 2016-12-29 13:08 UTC (permalink / raw)
  To: Kusztal, ArkadiuszX, dev@dpdk.org
  Cc: Trahe, Fiona, De Lara Guarch, Pablo, Griffin, John,
	Jain, Deepak K, Doherty, Declan, Kusztal, ArkadiuszX
In-Reply-To: <1482481493-4369-2-git-send-email-arkadiuszx.kusztal@intel.com>

Hi Arek,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Arek Kusztal
> Sent: Friday, December 23, 2016 9:25 AM
> To: dev@dpdk.org
> Cc: Trahe, Fiona <fiona.trahe@intel.com>; De Lara Guarch, Pablo
> <pablo.de.lara.guarch@intel.com>; Griffin, John <john.griffin@intel.com>;
> Jain, Deepak K <deepak.k.jain@intel.com>; Doherty, Declan
> <declan.doherty@intel.com>; Kusztal, ArkadiuszX
> <arkadiuszx.kusztal@intel.com>
> Subject: [dpdk-dev] [PATCH v2 1/3] crypto/aesni_gcm: fix J0 padding bytes
> for GCM
> 
> This commit fixes pre-counter block (J0) padding by clearing four most
> significant bytes before setting initial counter value.
> 
> Fixes: b2bb3597470c ("crypto/aesni_gcm: move pre-counter block to driver")
> 
> Signed-off-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
> ---
>  drivers/crypto/aesni_gcm/aesni_gcm_pmd.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
> b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
> index dba5e15..af3d60f 100644
> --- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
> +++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
> @@ -40,6 +40,7 @@
>  #include <rte_vdev.h>
>  #include <rte_malloc.h>
>  #include <rte_cpuflags.h>
> +#include <rte_byteorder.h>
> 
>  #include "aesni_gcm_pmd_private.h"
> 
> @@ -241,7 +242,8 @@ process_gcm_crypto_op(struct aesni_gcm_qp *qp,
> struct rte_crypto_sym_op *op,
>  	 * to set BE LSB to 1, driver expects that 16B is allocated

I think that 16B expected by driver while only 12B IV is supported is not clear from user perspective.
I think that we should expect 12B only and allocate 16B locally.

>  	 */
>  	if (op->cipher.iv.length == 12) {
> -		op->cipher.iv.data[15] = 1;
> +		uint32_t *iv_padd = (uint32_t *)&op->cipher.iv.data[12];
> +		*iv_padd = rte_bswap32(1);

Should not be that the last byte (number 15) always be set to 1?

>  	}
> 
>  	if (op->auth.aad.length != 12 && op->auth.aad.length != 8 &&
> --
> 2.1.0

^ permalink raw reply

* Re: [PATCH v2 3/7] net/virtio_user: move vhost user specific code
From: Tan, Jianfeng @ 2016-12-29  9:40 UTC (permalink / raw)
  To: Yuanhan Liu; +Cc: dev@dpdk.org, Yigit, Ferruh, Liang, Cunming
In-Reply-To: <20161226075745.GF19288@yliu-dev.sh.intel.com>

Hi Yuanhan,


On 12/26/2016 3:57 PM, Yuanhan Liu wrote:
> On Mon, Dec 26, 2016 at 06:58:58AM +0000, Tan, Jianfeng wrote:
>>
>>> -----Original Message-----
>>> From: Yuanhan Liu [mailto:yuanhan.liu@linux.intel.com]
>>> Sent: Monday, December 26, 2016 2:28 PM
>>> To: Tan, Jianfeng
>>> Cc: dev@dpdk.org; Yigit, Ferruh; Liang, Cunming
>>> Subject: Re: [PATCH v2 3/7] net/virtio_user: move vhost user specific code
>>>
>>> On Fri, Dec 23, 2016 at 07:14:22AM +0000, Jianfeng Tan wrote:
>>>> To support vhost kernel as the backend of net_virtio_user in coming
>>>> patches, we move vhost_user specific structs and macros into
>>>> vhost_user.c, and only keep common definitions in vhost.h.
>>> Good.
>>>
>>>> Besides, remove VHOST_USER_MQ feature check, it will be added back
>>>> in following multiqueue patch.
>>> Why then?
>> Only vhost user recognizes this feature bit, and vhost kernel does not. My intension is to put those vhost user specific code inside vhost user.
> That's okay. But why you have to remove it and then add it back?

After second thought , I agree that it's necessary to add it back. 
Currently, our vhost does not implement the semantics of 
VHOST_USER_F_PROTOCOL_FEATURES.

Besides, all other comments from you on this patch series will be 
addressed on next version. Thank you very much for those suggestions!

Thanks,
Jianfeng

>
> 	--yliu
>
>> And in fact, I forget to add it back. I should add it back in this patch.
>>
>> Thanks,
>> Jianfeng
>>> 	--yliu

^ permalink raw reply

* Re: [PATCH 2/2] vhost: start vhost servers once
From: Yuanhan Liu @ 2016-12-29  8:52 UTC (permalink / raw)
  To: Charles (Chas) Williams; +Cc: dev, mtetsuyah
In-Reply-To: <1482959452-18486-2-git-send-email-ciwillia@brocade.com>

On Wed, Dec 28, 2016 at 04:10:52PM -0500, Charles (Chas) Williams wrote:
> Start a vhost server once during devinit instead of during device start
> and stop.  Some vhost clients, QEMU, don't re-attaching to sockets when
> the vhost server is stopped and later started.  Preserve existing behavior
> for vhost clients.

I didn't quite get the idea what you are going to fix.

	--yliu

^ permalink raw reply

* Re: [PATCH 1/2] vhost: reference count fix for nb_started_ports
From: Yuanhan Liu @ 2016-12-29  8:51 UTC (permalink / raw)
  To: Charles (Chas) Williams; +Cc: dev, mtetsuyah, Wen Chiu
In-Reply-To: <1482959452-18486-1-git-send-email-ciwillia@brocade.com>

On Wed, Dec 28, 2016 at 04:10:51PM -0500, Charles (Chas) Williams wrote:
> From: Wen Chiu <wchiu@brocade.com>
> 
> Only increment and decrement nb_started_ports on the first and last
> device start and stop.  Otherwise, nb_started_ports can become negative
> if a device is stopped multiple times.

How could you be able to stop dev (precisely, invoke eth_dev_stop)
multiple times, judging that eth_dev_stop() will be invoked once
only?

    void
    rte_eth_dev_stop(uint8_t port_id)
    {
            struct rte_eth_dev *dev;
    
            RTE_ETH_VALID_PORTID_OR_RET(port_id);
            dev = &rte_eth_devices[port_id];
    
            RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_stop);
    
==>         if (dev->data->dev_started == 0) {
                    RTE_PMD_DEBUG_TRACE("Device with port_id=%" PRIu8
                            " already stopped\n",
                            port_id);
                    return;
            }
    
==>         dev->data->dev_started = 0;
            (*dev->dev_ops->dev_stop)(dev);
    }

Multiple threads?

	--yliu

^ permalink raw reply

* Re: [PATCH v2 0/9] rxq interrupt mode for virtio PMD
From: Tan, Jianfeng @ 2016-12-29  7:42 UTC (permalink / raw)
  To: dev@dpdk.org; +Cc: yuanhan.liu@linux.intel.com, stephen@networkplumber.org
In-Reply-To: <1482996643-113253-1-git-send-email-jianfeng.tan@intel.com>

Forget to mention a key part, when we bind virtio to vfio-pci driver in the VM, we need to insert vfio kernel module like this:

$ modprobe vfio enable_unsafe_noiommu_mode=1
$ modprobe vfio-pci

Thanks,
Jianfeng

> -----Original Message-----
> From: Tan, Jianfeng
> Sent: Thursday, December 29, 2016 3:31 PM
> To: dev@dpdk.org
> Cc: yuanhan.liu@linux.intel.com; stephen@networkplumber.org; Tan,
> Jianfeng
> Subject: [PATCH v2 0/9] rxq interrupt mode for virtio PMD
> 
> v2:
>   - Add PCI queue/irq config ops.
>   - Move rxq interrupt settings before sending DRIVER OK.
> 
> Historically, virtio PMD can only be binded to igb_uio or
> uio_pci_generic, and not for vfio-pci. Besides, quote from
> http://dpdk.org/doc/guides-16.11/rel_notes/release_2_1.html:
>   "Per queue RX interrupt events are only allowed in VFIO
>    which supports multiple MSI-X vectors."
> 
> As Linux starts to support vfio noiommu mode since 4.8.0, it's
> a good chance to enable rxq interrupt for virtio PMD.
> 
> How to test:
> 
> Step 1, prepare a VM image with kernel version >= 4.8.0.
> 
> Step 2, on the host, start a testpmd with a vhost port:
> $ testpmd -c 0x7 -m 1024 --vdev 'eth_vhost0,iface=/tmp/sock0,queues=2' \
> 	--no-pci -- -i --rxq=2 --txq=2 --nb-cores=2
> 
> Step 3, boot the VM:
> $ qemu ... -chardev socket,id=chr1,path=/tmp/sock0 \
> 	-netdev vhost-user,id=net1,chardev=chr1,vhostforce,queues=2 \
> 	-device virtio-net-pci,netdev=net1,mq=on,vectors=5 ...
> 
> Step 4, start l3fwd-power in VM:
> $ l3fwd-power -c 0x3 -n 4 -- -p 1 -P --config="(0,0,1),(0,1,1)" --no-numa
> 
> Step 5, send packets from testpmd on the host:
> $ start tx_first
> 
> Then l3fwd-power outputs:
> L3FWD_POWER: lcore 1 is waked up from rx interrupt on port 0 queue 0
> L3FWD_POWER: lcore 1 is waked up from rx interrupt on port 0 queue 1
> 
> Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
> Jianfeng Tan (9):
>   net/virtio: fix rewriting LSC flag
>   net/virtio: add Rx descriptor check
>   net/virtio: add PCI ops for queue/irq binding
>   net/virtio: add Rx queue intr enable/disable functions
>   net/virtio: setup rxq interrupts
>   net/virtio: unbind intr/eventfd when stop device
>   net/virtio: unmapping queue/irq when close device
>   examples/l3fwd: add parse-ptype option
>   examples/l3fwd-power: fix not stop and close device
> 
>  drivers/net/virtio/virtio_ethdev.c | 149
> +++++++++++++++++++++++++++++++++++--
>  drivers/net/virtio/virtio_ethdev.h |   3 +
>  drivers/net/virtio/virtio_pci.c    |  29 ++++++++
>  drivers/net/virtio/virtio_pci.h    |   5 ++
>  drivers/net/virtio/virtio_rxtx.c   |   9 +++
>  drivers/net/virtio/virtqueue.c     |  11 ---
>  drivers/net/virtio/virtqueue.h     |  24 +++++-
>  examples/l3fwd-power/main.c        |  70 ++++++++++++++++-
>  8 files changed, 282 insertions(+), 18 deletions(-)
> 
> --
> 2.7.4

^ permalink raw reply

* [PATCH v2 1/9] net/virtio: fix rewriting LSC flag
From: Jianfeng Tan @ 2016-12-29  7:30 UTC (permalink / raw)
  To: dev; +Cc: yuanhan.liu, stephen, Jianfeng Tan, stable
In-Reply-To: <1482996643-113253-1-git-send-email-jianfeng.tan@intel.com>

The LSC flag is decided according to if VIRTIO_NET_F_STATUS feature
is negotiated. Copy the PCI info after the judgement will rewrite
the correct result.

Fixes: 198ab33677c9 ("net/virtio: move device initialization in a function")

CC: stable@dpdk.org

Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
---
 drivers/net/virtio/virtio_ethdev.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 079fd6c..aaec338 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1204,14 +1204,14 @@ virtio_init_device(struct rte_eth_dev *eth_dev, uint64_t req_features)
 	if (virtio_negotiate_features(hw, req_features) < 0)
 		return -1;
 
+	rte_eth_copy_pci_info(eth_dev, pci_dev);
+
 	/* If host does not support status then disable LSC */
 	if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS))
 		eth_dev->data->dev_flags &= ~RTE_ETH_DEV_INTR_LSC;
 	else
 		eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
 
-	rte_eth_copy_pci_info(eth_dev, pci_dev);
-
 	rx_func_get(eth_dev);
 
 	/* Setting up rx_header size for the device */
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 9/9] examples/l3fwd-power: fix not stop and close device
From: Jianfeng Tan @ 2016-12-29  7:30 UTC (permalink / raw)
  To: dev; +Cc: yuanhan.liu, stephen, Jianfeng Tan
In-Reply-To: <1482996643-113253-1-git-send-email-jianfeng.tan@intel.com>

As it gets killed, in SIGINT signal handler, device is not stopped
and closed. In virtio's case, vector assignment in the KVM is not
deassigned.

This patch will invoke dev_stop() and dev_close() in signal handler.

Fixes: d7937e2e3d12 ("power: initial import")

Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
---
 examples/l3fwd-power/main.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c
index 44843ec..63e1796 100644
--- a/examples/l3fwd-power/main.c
+++ b/examples/l3fwd-power/main.c
@@ -379,6 +379,7 @@ static void
 signal_exit_now(int sigtype)
 {
 	unsigned lcore_id;
+	unsigned int portid, nb_ports;
 	int ret;
 
 	if (sigtype == SIGINT) {
@@ -393,6 +394,15 @@ signal_exit_now(int sigtype)
 					"library de-initialization failed on "
 							"core%u\n", lcore_id);
 		}
+
+		nb_ports = rte_eth_dev_count();
+		for (portid = 0; portid < nb_ports; portid++) {
+			if ((enabled_port_mask & (1 << portid)) == 0)
+				continue;
+
+			rte_eth_dev_stop(portid);
+			rte_eth_dev_close(portid);
+		}
 	}
 
 	rte_exit(EXIT_SUCCESS, "User forced exit\n");
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 8/9] examples/l3fwd: add parse-ptype option
From: Jianfeng Tan @ 2016-12-29  7:30 UTC (permalink / raw)
  To: dev; +Cc: yuanhan.liu, stephen, Jianfeng Tan
In-Reply-To: <1482996643-113253-1-git-send-email-jianfeng.tan@intel.com>

To support those devices that do not provide packet type info when
receiving packets, add a new option, --parse-ptype, to analyze
packet type in the Rx callback.

Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
---
 examples/l3fwd-power/main.c | 60 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 59 insertions(+), 1 deletion(-)

diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c
index b65d683..44843ec 100644
--- a/examples/l3fwd-power/main.c
+++ b/examples/l3fwd-power/main.c
@@ -164,6 +164,8 @@ static uint32_t enabled_port_mask = 0;
 static int promiscuous_on = 0;
 /* NUMA is enabled by default. */
 static int numa_on = 1;
+static int parse_ptype; /**< Parse packet type using rx callback, and */
+			/**< disabled by default */
 
 enum freq_scale_hint_t
 {
@@ -607,6 +609,48 @@ get_ipv4_dst_port(struct ipv4_hdr *ipv4_hdr, uint8_t portid,
 #endif
 
 static inline void
+parse_ptype_one(struct rte_mbuf *m)
+{
+	struct ether_hdr *eth_hdr;
+	uint32_t packet_type = RTE_PTYPE_UNKNOWN;
+	uint16_t ether_type;
+
+	eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
+	ether_type = eth_hdr->ether_type;
+	if (ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4))
+		packet_type |= RTE_PTYPE_L3_IPV4_EXT_UNKNOWN;
+	else if (ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv6))
+		packet_type |= RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;
+
+	m->packet_type = packet_type;
+}
+
+static uint16_t
+cb_parse_ptype(uint8_t port __rte_unused, uint16_t queue __rte_unused,
+	       struct rte_mbuf *pkts[], uint16_t nb_pkts,
+	       uint16_t max_pkts __rte_unused,
+	       void *user_param __rte_unused)
+{
+	unsigned int i;
+
+	for (i = 0; i < nb_pkts; ++i)
+		parse_ptype_one(pkts[i]);
+
+	return nb_pkts;
+}
+
+static int
+add_cb_parse_ptype(uint8_t portid, uint16_t queueid)
+{
+	printf("Port %d: softly parse packet type info\n", portid);
+	if (rte_eth_add_rx_callback(portid, queueid, cb_parse_ptype, NULL))
+		return 0;
+
+	printf("Failed to add rx callback: port=%d\n", portid);
+	return -1;
+}
+
+static inline void
 l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid,
 				struct lcore_conf *qconf)
 {
@@ -1108,7 +1152,8 @@ print_usage(const char *prgname)
 		"  --config (port,queue,lcore): rx queues configuration\n"
 		"  --no-numa: optional, disable numa awareness\n"
 		"  --enable-jumbo: enable jumbo frame"
-		" which max packet len is PKTLEN in decimal (64-9600)\n",
+		" which max packet len is PKTLEN in decimal (64-9600)\n"
+		"  --parse-ptype: parse packet type by software\n",
 		prgname);
 }
 
@@ -1202,6 +1247,8 @@ parse_config(const char *q_arg)
 	return 0;
 }
 
+#define CMD_LINE_OPT_PARSE_PTYPE "parse-ptype"
+
 /* Parse the argument given in the command line of the application */
 static int
 parse_args(int argc, char **argv)
@@ -1214,6 +1261,7 @@ parse_args(int argc, char **argv)
 		{"config", 1, 0, 0},
 		{"no-numa", 0, 0, 0},
 		{"enable-jumbo", 0, 0, 0},
+		{CMD_LINE_OPT_PARSE_PTYPE, 0, 0, 0},
 		{NULL, 0, 0, 0}
 	};
 
@@ -1284,6 +1332,13 @@ parse_args(int argc, char **argv)
 				(unsigned int)port_conf.rxmode.max_rx_pkt_len);
 			}
 
+			if (!strncmp(lgopts[option_index].name,
+				     CMD_LINE_OPT_PARSE_PTYPE,
+				     sizeof(CMD_LINE_OPT_PARSE_PTYPE))) {
+				printf("soft parse-ptype is enabled\n");
+				parse_ptype = 1;
+			}
+
 			break;
 
 		default:
@@ -1716,6 +1771,9 @@ main(int argc, char **argv)
 				rte_exit(EXIT_FAILURE,
 					"rte_eth_rx_queue_setup: err=%d, "
 						"port=%d\n", ret, portid);
+
+			if (parse_ptype && add_cb_parse_ptype(portid, queueid))
+				rte_exit(EXIT_FAILURE, "Fail to add ptype cb\n");
 		}
 	}
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 7/9] net/virtio: unmapping queue/irq when close device
From: Jianfeng Tan @ 2016-12-29  7:30 UTC (permalink / raw)
  To: dev; +Cc: yuanhan.liu, stephen, Jianfeng Tan
In-Reply-To: <1482996643-113253-1-git-send-email-jianfeng.tan@intel.com>

When closing virtio devices, close eventfds, free the struct to
store queue/irq mapping.

Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
---
 drivers/net/virtio/virtio_ethdev.c | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 0754ba0..d1a0afb 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -591,16 +591,30 @@ virtio_alloc_queues(struct rte_eth_dev *dev)
 	return 0;
 }
 
+static void virtio_queues_unbind_intr(struct rte_eth_dev *dev);
+
 static void
 virtio_dev_close(struct rte_eth_dev *dev)
 {
 	struct virtio_hw *hw = dev->data->dev_private;
+	struct rte_intr_conf *intr_conf = &dev->data->dev_conf.intr_conf;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 
 	PMD_INIT_LOG(DEBUG, "virtio_dev_close");
 
 	/* reset the NIC */
-	if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
+	if (intr_conf->lsc)
 		vtpci_irq_config(hw, VIRTIO_MSI_NO_VECTOR);
+	if (intr_conf->lsc)
+		virtio_queues_unbind_intr(dev);
+
+	if (intr_conf->lsc || intr_conf->rxq) {
+		rte_intr_disable(intr_handle);
+		rte_intr_efd_disable(intr_handle);
+		rte_free(intr_handle->intr_vec);
+		intr_handle->intr_vec = NULL;
+	}
+
 	vtpci_reset(hw);
 	virtio_dev_free_mbufs(dev);
 	virtio_free_queues(hw);
@@ -1232,6 +1246,17 @@ virtio_queues_bind_intr(struct rte_eth_dev *dev)
 	return 0;
 }
 
+static void
+virtio_queues_unbind_intr(struct rte_eth_dev *dev)
+{
+	uint32_t i;
+	struct virtio_hw *hw = dev->data->dev_private;
+
+	PMD_INIT_LOG(INFO, "queue/interrupt unbinding\n");
+	for (i = 0; i < dev->data->nb_rx_queues; ++i)
+		vtpci_irq_queue(hw->vqs[i * VTNET_CQ], VIRTIO_MSI_NO_VECTOR);
+}
+
 static int
 virtio_configure_intr(struct rte_eth_dev *dev)
 {
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 6/9] net/virtio: unbind intr/eventfd when stop device
From: Jianfeng Tan @ 2016-12-29  7:30 UTC (permalink / raw)
  To: dev; +Cc: yuanhan.liu, stephen, Jianfeng Tan
In-Reply-To: <1482996643-113253-1-git-send-email-jianfeng.tan@intel.com>

When virtio devices get stopped, we just tell the kernel to unbind
the mapping between interrupts and eventfds.

Note: it behaves differently from other NICs which close eventfds,
free struct. In virtio, we do those things when close device in
following patch.

Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
---
 drivers/net/virtio/virtio_ethdev.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 082346b..0754ba0 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1686,11 +1686,13 @@ static void
 virtio_dev_stop(struct rte_eth_dev *dev)
 {
 	struct rte_eth_link link;
+	struct rte_intr_conf *intr_conf = &dev->data->dev_conf.intr_conf;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 
 	PMD_INIT_LOG(DEBUG, "stop");
 
-	if (dev->data->dev_conf.intr_conf.lsc)
-		rte_intr_disable(&dev->pci_dev->intr_handle);
+	if (intr_conf->lsc || intr_conf->rxq)
+		rte_intr_disable(intr_handle);
 
 	memset(&link, 0, sizeof(link));
 	virtio_dev_atomic_write_link_status(dev, &link);
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 5/9] net/virtio: setup rxq interrupts
From: Jianfeng Tan @ 2016-12-29  7:30 UTC (permalink / raw)
  To: dev; +Cc: yuanhan.liu, stephen, Jianfeng Tan
In-Reply-To: <1482996643-113253-1-git-send-email-jianfeng.tan@intel.com>

This patch mainly allocates structure to store queue/irq mapping,
and configure queue/irq mapping down through PCI ops. It also creates
eventfds for each Rx queue and tell the kernel about the eventfd/intr
binding.

Mostly importantly, different from previous NICs (usually implements
these logic in dev_start()), virtio's interrupt settings should be
configured down to QEMU before sending DRIVER_OK notification.

Note: We only support 1:1 queue/irq mapping so far, which means, each
rx queue has one exclusive interrupt (corresponding to irqfd in the
qemu/kvm) to get notified when packets are available on that queue.

Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
---
 drivers/net/virtio/virtio_ethdev.c | 89 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 89 insertions(+)

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 3f8b90c..082346b 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1206,6 +1206,76 @@ rx_func_get(struct rte_eth_dev *eth_dev)
 		eth_dev->rx_pkt_burst = &virtio_recv_pkts;
 }
 
+/* Only support 1:1 queue/interrupt mapping so far.
+ * TODO: under below cases, lsc and rxq interrupt share one interrupt.
+ * a) binded to uio, igb_uio, vfio (type1);
+ * b) device only has one vec, see _vectors_ option in -device virtio-net-pci.
+ * TODO: support n:1 queue/interrupt mapping.
+ */
+static int
+virtio_queues_bind_intr(struct rte_eth_dev *dev)
+{
+	uint32_t i;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct virtio_hw *hw = dev->data->dev_private;
+
+	PMD_INIT_LOG(INFO, "queue/interrupt binding\n");
+	for (i = 0; i < dev->data->nb_rx_queues; ++i) {
+		intr_handle->intr_vec[i] = i + 1;
+		if (vtpci_irq_queue(hw->vqs[i * VTNET_CQ], i + 1) ==
+			VIRTIO_MSI_NO_VECTOR) {
+			PMD_DRV_LOG(ERR, "failed to set queue vector");
+			return -EBUSY;
+		}
+	}
+
+	return 0;
+}
+
+static int
+virtio_configure_intr(struct rte_eth_dev *dev)
+{
+	uint32_t intr_vector;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+
+	/* check if rxq interrupt is enabled */
+	if (!rte_intr_cap_multiple(intr_handle)) {
+		PMD_INIT_LOG(ERR, "Multiple intr vector not supported");
+		return -ENOTSUP;
+	}
+
+	intr_vector = dev->data->nb_rx_queues;
+	if (rte_intr_efd_enable(intr_handle, intr_vector)) {
+		PMD_INIT_LOG(ERR, "Fail to create eventfd");
+		return -1;
+	}
+
+	if (!intr_handle->intr_vec) {
+		intr_handle->intr_vec =
+			rte_zmalloc("intr_vec", intr_vector * sizeof(int), 0);
+		if (!intr_handle->intr_vec) {
+			PMD_INIT_LOG(ERR, "Failed to allocate %d rxq vectors",
+				     intr_vector);
+			return -ENOMEM;
+		}
+	}
+
+	if (virtio_queues_bind_intr(dev) < 0) {
+		PMD_INIT_LOG(ERR, "Failed to bind queue/interrupt");
+		return -1;
+	}
+
+	/* DO NOT try remove this! This function will enable msix, or QEMU
+	 * will encounter SIGSEGV.
+	 */
+	if (rte_intr_enable(intr_handle) < 0) {
+		PMD_DRV_LOG(ERR, "interrupt enable failed");
+		return -1;
+	}
+
+	return 0;
+}
+
 /* reset device and renegotiate features if needed */
 static int
 virtio_init_device(struct rte_eth_dev *eth_dev, uint64_t req_features)
@@ -1299,6 +1369,17 @@ virtio_init_device(struct rte_eth_dev *eth_dev, uint64_t req_features)
 	ret = virtio_alloc_queues(eth_dev);
 	if (ret < 0)
 		return ret;
+
+	/* Make sure rxq interrupt is configured before sending DRIVER_OK,
+	 * so that QEMU can properly set those irq into kvm.
+	 */
+	if (eth_dev->data->dev_conf.intr_conf.rxq) {
+		if (virtio_configure_intr(eth_dev) < 0) {
+			PMD_INIT_LOG(ERR, "failed to configure interrupt");
+			return -1;
+		}
+	}
+
 	vtpci_reinit_complete(hw);
 
 	if (pci_dev)
@@ -1503,7 +1584,15 @@ virtio_dev_start(struct rte_eth_dev *dev)
 			PMD_DRV_LOG(ERR, "link status not supported by host");
 			return -ENOTSUP;
 		}
+	}
 
+	/* Enable uio/vfio intr/eventfd mapping: althrough we already did that
+	 * in device configure, but it could be unmapped  when device is
+	 * stopped.
+	 */
+	if (dev->data->dev_conf.intr_conf.lsc ||
+	    dev->data->dev_conf.intr_conf.rxq) {
+		rte_intr_disable(&dev->pci_dev->intr_handle);
 		if (rte_intr_enable(&dev->pci_dev->intr_handle) < 0) {
 			PMD_DRV_LOG(ERR, "interrupt enable failed");
 			return -EIO;
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 4/9] net/virtio: add Rx queue intr enable/disable functions
From: Jianfeng Tan @ 2016-12-29  7:30 UTC (permalink / raw)
  To: dev; +Cc: yuanhan.liu, stephen, Jianfeng Tan
In-Reply-To: <1482996643-113253-1-git-send-email-jianfeng.tan@intel.com>

This patch implements interrupt enable/disable functions for each
Rx queue. And we rely on flags of avail queue as the hint for virtio
device to interrupt virtio driver or not.

Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
---
 drivers/net/virtio/virtio_ethdev.c | 22 ++++++++++++++++++++++
 drivers/net/virtio/virtqueue.c     | 11 -----------
 drivers/net/virtio/virtqueue.h     | 24 +++++++++++++++++++++++-
 3 files changed, 45 insertions(+), 12 deletions(-)

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index c2633c0..3f8b90c 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -715,6 +715,26 @@ virtio_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 	return 0;
 }
 
+static int
+virtio_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct virtnet_rx *rxvq = dev->data->rx_queues[queue_id];
+	struct virtqueue *vq = rxvq->vq;
+
+	virtqueue_enable_intr(vq);
+	return 0;
+}
+
+static int
+virtio_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct virtnet_rx *rxvq = dev->data->rx_queues[queue_id];
+	struct virtqueue *vq = rxvq->vq;
+
+	virtqueue_disable_intr(vq);
+	return 0;
+}
+
 /*
  * dev_ops for virtio, bare necessities for basic operation
  */
@@ -736,6 +756,8 @@ static const struct eth_dev_ops virtio_eth_dev_ops = {
 	.xstats_reset            = virtio_dev_stats_reset,
 	.link_update             = virtio_dev_link_update,
 	.rx_queue_setup          = virtio_dev_rx_queue_setup,
+	.rx_queue_intr_enable    = virtio_dev_rx_queue_intr_enable,
+	.rx_queue_intr_disable   = virtio_dev_rx_queue_intr_disable,
 	.rx_queue_release        = virtio_dev_queue_release,
 	.rx_descriptor_done      = virtio_dev_rx_queue_done,
 	.tx_queue_setup          = virtio_dev_tx_queue_setup,
diff --git a/drivers/net/virtio/virtqueue.c b/drivers/net/virtio/virtqueue.c
index 7f60e3e..9ad77b8 100644
--- a/drivers/net/virtio/virtqueue.c
+++ b/drivers/net/virtio/virtqueue.c
@@ -38,17 +38,6 @@
 #include "virtio_logs.h"
 #include "virtio_pci.h"
 
-void
-virtqueue_disable_intr(struct virtqueue *vq)
-{
-	/*
-	 * Set VRING_AVAIL_F_NO_INTERRUPT to hint host
-	 * not to interrupt when it consumes packets
-	 * Note: this is only considered a hint to the host
-	 */
-	vq->vq_ring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
-}
-
 /*
  * Two types of mbuf to be cleaned:
  * 1) mbuf that has been consumed by backend but not used by virtio.
diff --git a/drivers/net/virtio/virtqueue.h b/drivers/net/virtio/virtqueue.h
index f0bb089..62be136 100644
--- a/drivers/net/virtio/virtqueue.h
+++ b/drivers/net/virtio/virtqueue.h
@@ -274,7 +274,29 @@ vring_desc_init(struct vring_desc *dp, uint16_t n)
 /**
  * Tell the backend not to interrupt us.
  */
-void virtqueue_disable_intr(struct virtqueue *vq);
+static inline void
+virtqueue_disable_intr(struct virtqueue *vq)
+{
+	/* Set VRING_AVAIL_F_NO_INTERRUPT to hint host
+	 * not to interrupt when it consumes packets
+	 * Note: this is only considered a hint to the host
+	 */
+	vq->vq_ring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
+}
+
+/**
+ * Tell the backend to interrupt us.
+ */
+static inline void
+virtqueue_enable_intr(struct virtqueue *vq)
+{
+	/* Unset VRING_AVAIL_F_NO_INTERRUPT to hint host
+	 * to interrupt when it consumes packets
+	 * Note: this is only considered a hint to the host
+	 */
+	vq->vq_ring.avail->flags &= (~VRING_AVAIL_F_NO_INTERRUPT);
+}
+
 /**
  *  Dump virtqueue internal structures, for debug purpose only.
  */
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 3/9] net/virtio: add PCI ops for queue/irq binding
From: Jianfeng Tan @ 2016-12-29  7:30 UTC (permalink / raw)
  To: dev; +Cc: yuanhan.liu, stephen, Jianfeng Tan
In-Reply-To: <1482996643-113253-1-git-send-email-jianfeng.tan@intel.com>

Add handler in virtio_pci_ops to set queue/irq bind.

Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
---
 drivers/net/virtio/virtio_pci.c | 29 +++++++++++++++++++++++++++++
 drivers/net/virtio/virtio_pci.h |  5 +++++
 2 files changed, 34 insertions(+)

diff --git a/drivers/net/virtio/virtio_pci.c b/drivers/net/virtio/virtio_pci.c
index 9b47165..4e706cf 100644
--- a/drivers/net/virtio/virtio_pci.c
+++ b/drivers/net/virtio/virtio_pci.c
@@ -217,6 +217,18 @@ legacy_set_config_irq(struct virtio_hw *hw, uint16_t vec)
 }
 
 static uint16_t
+legacy_set_queue_irq(struct virtio_hw *hw, struct virtqueue *vq, uint16_t vec)
+{
+	uint16_t dst;
+
+	rte_eal_pci_ioport_write(&hw->io, &vq->vq_queue_index, 2,
+			 VIRTIO_PCI_QUEUE_SEL);
+	rte_eal_pci_ioport_write(&hw->io, &vec, 2, VIRTIO_MSI_QUEUE_VECTOR);
+	rte_eal_pci_ioport_read(&hw->io, &dst, 2, VIRTIO_MSI_QUEUE_VECTOR);
+	return dst;
+}
+
+static uint16_t
 legacy_get_queue_num(struct virtio_hw *hw, uint16_t queue_id)
 {
 	uint16_t dst;
@@ -310,6 +322,7 @@ static const struct virtio_pci_ops legacy_ops = {
 	.set_features	= legacy_set_features,
 	.get_isr	= legacy_get_isr,
 	.set_config_irq	= legacy_set_config_irq,
+	.set_queue_irq = legacy_set_queue_irq,
 	.get_queue_num	= legacy_get_queue_num,
 	.setup_queue	= legacy_setup_queue,
 	.del_queue	= legacy_del_queue,
@@ -449,6 +462,15 @@ modern_set_config_irq(struct virtio_hw *hw, uint16_t vec)
 }
 
 static uint16_t
+modern_set_queue_irq(struct virtio_hw *hw, struct virtqueue *vq, uint16_t vec)
+{
+	PMD_INIT_LOG(INFO, "vq: %u, vec: %u", vq->vq_queue_index, vec);
+	io_write16(vq->vq_queue_index, &hw->common_cfg->queue_select);
+	io_write16(vec, &hw->common_cfg->queue_msix_vector);
+	return io_read16(&hw->common_cfg->queue_msix_vector);
+}
+
+static uint16_t
 modern_get_queue_num(struct virtio_hw *hw, uint16_t queue_id)
 {
 	io_write16(queue_id, &hw->common_cfg->queue_select);
@@ -526,6 +548,7 @@ static const struct virtio_pci_ops modern_ops = {
 	.set_features	= modern_set_features,
 	.get_isr	= modern_get_isr,
 	.set_config_irq	= modern_set_config_irq,
+	.set_queue_irq = modern_set_queue_irq,
 	.get_queue_num	= modern_get_queue_num,
 	.setup_queue	= modern_setup_queue,
 	.del_queue	= modern_del_queue,
@@ -605,6 +628,12 @@ vtpci_irq_config(struct virtio_hw *hw, uint16_t vec)
 	return hw->vtpci_ops->set_config_irq(hw, vec);
 }
 
+uint16_t
+vtpci_irq_queue(struct virtqueue *vq, uint16_t vec)
+{
+	return vq->hw->vtpci_ops->set_queue_irq(vq->hw, vq, vec);
+}
+
 static void *
 get_cfg_addr(struct rte_pci_device *dev, struct virtio_pci_cap *cap)
 {
diff --git a/drivers/net/virtio/virtio_pci.h b/drivers/net/virtio/virtio_pci.h
index de271bf..d12d40f 100644
--- a/drivers/net/virtio/virtio_pci.h
+++ b/drivers/net/virtio/virtio_pci.h
@@ -235,6 +235,9 @@ struct virtio_pci_ops {
 
 	uint16_t (*set_config_irq)(struct virtio_hw *hw, uint16_t vec);
 
+	uint16_t (*set_queue_irq)(struct virtio_hw *hw, struct virtqueue *vq,
+			uint16_t vec);
+
 	uint16_t (*get_queue_num)(struct virtio_hw *hw, uint16_t queue_id);
 	int (*setup_queue)(struct virtio_hw *hw, struct virtqueue *vq);
 	void (*del_queue)(struct virtio_hw *hw, struct virtqueue *vq);
@@ -317,4 +320,6 @@ uint8_t vtpci_isr(struct virtio_hw *);
 
 uint16_t vtpci_irq_config(struct virtio_hw *, uint16_t);
 
+uint16_t vtpci_irq_queue(struct virtqueue *vq, uint16_t vec);
+
 #endif /* _VIRTIO_PCI_H_ */
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 2/9] net/virtio: add Rx descriptor check
From: Jianfeng Tan @ 2016-12-29  7:30 UTC (permalink / raw)
  To: dev; +Cc: yuanhan.liu, stephen, Jianfeng Tan
In-Reply-To: <1482996643-113253-1-git-send-email-jianfeng.tan@intel.com>

Under interrupt mode, rx_descriptor_done is used as an indicator
for applications to check if some number of packets are ready to
be received.

This patch enables this by checking used ring's local consumed idx
with shared (with backend) idx.

Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
---
 drivers/net/virtio/virtio_ethdev.c | 1 +
 drivers/net/virtio/virtio_ethdev.h | 3 +++
 drivers/net/virtio/virtio_rxtx.c   | 9 +++++++++
 3 files changed, 13 insertions(+)

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index aaec338..c2633c0 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -737,6 +737,7 @@ static const struct eth_dev_ops virtio_eth_dev_ops = {
 	.link_update             = virtio_dev_link_update,
 	.rx_queue_setup          = virtio_dev_rx_queue_setup,
 	.rx_queue_release        = virtio_dev_queue_release,
+	.rx_descriptor_done      = virtio_dev_rx_queue_done,
 	.tx_queue_setup          = virtio_dev_tx_queue_setup,
 	.tx_queue_release        = virtio_dev_queue_release,
 	/* collect stats per queue */
diff --git a/drivers/net/virtio/virtio_ethdev.h b/drivers/net/virtio/virtio_ethdev.h
index 27d9a19..4ab81c6 100644
--- a/drivers/net/virtio/virtio_ethdev.h
+++ b/drivers/net/virtio/virtio_ethdev.h
@@ -78,6 +78,9 @@ void virtio_dev_cq_start(struct rte_eth_dev *dev);
 /*
  * RX/TX function prototypes
  */
+
+int virtio_dev_rx_queue_done(void *rxq, uint16_t offset);
+
 int  virtio_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
 		uint16_t nb_rx_desc, unsigned int socket_id,
 		const struct rte_eth_rxconf *rx_conf,
diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c
index 22d97a4..aeea0db 100644
--- a/drivers/net/virtio/virtio_rxtx.c
+++ b/drivers/net/virtio/virtio_rxtx.c
@@ -72,6 +72,15 @@
 #define VIRTIO_SIMPLE_FLAGS ((uint32_t)ETH_TXQ_FLAGS_NOMULTSEGS | \
 	ETH_TXQ_FLAGS_NOOFFLOADS)
 
+int
+virtio_dev_rx_queue_done(void *rxq, uint16_t offset)
+{
+	struct virtnet_rx *rxvq = rxq;
+	struct virtqueue *vq = rxvq->vq;
+
+	return (VIRTQUEUE_NUSED(vq) >= offset);
+}
+
 static void
 vq_ring_free_chain(struct virtqueue *vq, uint16_t desc_idx)
 {
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 0/9] rxq interrupt mode for virtio PMD
From: Jianfeng Tan @ 2016-12-29  7:30 UTC (permalink / raw)
  To: dev; +Cc: yuanhan.liu, stephen, Jianfeng Tan
In-Reply-To: <1480810702-114815-1-git-send-email-jianfeng.tan@intel.com>

v2:
  - Add PCI queue/irq config ops.
  - Move rxq interrupt settings before sending DRIVER OK.

Historically, virtio PMD can only be binded to igb_uio or
uio_pci_generic, and not for vfio-pci. Besides, quote from
http://dpdk.org/doc/guides-16.11/rel_notes/release_2_1.html:
  "Per queue RX interrupt events are only allowed in VFIO
   which supports multiple MSI-X vectors."

As Linux starts to support vfio noiommu mode since 4.8.0, it's
a good chance to enable rxq interrupt for virtio PMD.

How to test:

Step 1, prepare a VM image with kernel version >= 4.8.0.

Step 2, on the host, start a testpmd with a vhost port:
$ testpmd -c 0x7 -m 1024 --vdev 'eth_vhost0,iface=/tmp/sock0,queues=2' \
	--no-pci -- -i --rxq=2 --txq=2 --nb-cores=2

Step 3, boot the VM:
$ qemu ... -chardev socket,id=chr1,path=/tmp/sock0 \
	-netdev vhost-user,id=net1,chardev=chr1,vhostforce,queues=2 \
	-device virtio-net-pci,netdev=net1,mq=on,vectors=5 ...

Step 4, start l3fwd-power in VM:
$ l3fwd-power -c 0x3 -n 4 -- -p 1 -P --config="(0,0,1),(0,1,1)" --no-numa

Step 5, send packets from testpmd on the host:
$ start tx_first

Then l3fwd-power outputs:
L3FWD_POWER: lcore 1 is waked up from rx interrupt on port 0 queue 0
L3FWD_POWER: lcore 1 is waked up from rx interrupt on port 0 queue 1

Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
Jianfeng Tan (9):
  net/virtio: fix rewriting LSC flag
  net/virtio: add Rx descriptor check
  net/virtio: add PCI ops for queue/irq binding
  net/virtio: add Rx queue intr enable/disable functions
  net/virtio: setup rxq interrupts
  net/virtio: unbind intr/eventfd when stop device
  net/virtio: unmapping queue/irq when close device
  examples/l3fwd: add parse-ptype option
  examples/l3fwd-power: fix not stop and close device

 drivers/net/virtio/virtio_ethdev.c | 149 +++++++++++++++++++++++++++++++++++--
 drivers/net/virtio/virtio_ethdev.h |   3 +
 drivers/net/virtio/virtio_pci.c    |  29 ++++++++
 drivers/net/virtio/virtio_pci.h    |   5 ++
 drivers/net/virtio/virtio_rxtx.c   |   9 +++
 drivers/net/virtio/virtqueue.c     |  11 ---
 drivers/net/virtio/virtqueue.h     |  24 +++++-
 examples/l3fwd-power/main.c        |  70 ++++++++++++++++-
 8 files changed, 282 insertions(+), 18 deletions(-)

-- 
2.7.4

^ permalink raw reply

* Re: [PATCH v3 16/33] drivers/pool/dpaa2: adding hw offloaded mempool
From: Santosh Shukla @ 2016-12-29  7:08 UTC (permalink / raw)
  To: Shreyansh Jain
  Cc: dev, thomas.monjalon, bruce.richardson, john.mcnamara,
	ferruh.yigit, jerin.jacob, Hemant Agrawal
In-Reply-To: <1482988612-6638-17-git-send-email-shreyansh.jain@nxp.com>

Hi Shreyansh,

On Thu, Dec 29, 2016 at 10:46:35AM +0530, Shreyansh Jain wrote:
> From: Hemant Agrawal <hemant.agrawal@nxp.com>
> 
> Adding NXP DPAA2 architecture specific mempool support
> Each mempool instance is represented by a DPBP object
> from the FSL-MC bus.
> 
> This patch also registers a dpaa2 type MEMPOOL OPS
> 
> Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
> ---
>  config/common_base                                |   1 +
>  config/defconfig_arm64-dpaa2-linuxapp-gcc         |   4 +
>  drivers/Makefile                                  |   1 +
>  drivers/bus/fslmc/Makefile                        |   2 +
>  drivers/bus/fslmc/fslmc_vfio.c                    |   9 +-
>  drivers/bus/fslmc/fslmc_vfio.h                    |   2 +
>  drivers/bus/fslmc/portal/dpaa2_hw_dpbp.c          | 137 +++++++++
>  drivers/bus/fslmc/portal/dpaa2_hw_pvt.h           |  19 ++
>  drivers/bus/fslmc/rte_pmd_fslmcbus_version.map    |   2 +
>  drivers/common/Makefile                           |   3 +
>  drivers/pool/Makefile                             |  38 +++
>  drivers/pool/dpaa2/Makefile                       |  67 +++++
>  drivers/pool/dpaa2/dpaa2_hw_mempool.c             | 339 ++++++++++++++++++++++
>  drivers/pool/dpaa2/dpaa2_hw_mempool.h             |  95 ++++++
>  drivers/pool/dpaa2/rte_pmd_dpaa2_pool_version.map |   8 +
>  mk/rte.app.mk                                     |   1 +
>  16 files changed, 727 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/bus/fslmc/portal/dpaa2_hw_dpbp.c
>  create mode 100644 drivers/pool/Makefile
>  create mode 100644 drivers/pool/dpaa2/Makefile
>  create mode 100644 drivers/pool/dpaa2/dpaa2_hw_mempool.c
>  create mode 100644 drivers/pool/dpaa2/dpaa2_hw_mempool.h
>  create mode 100644 drivers/pool/dpaa2/rte_pmd_dpaa2_pool_version.map
> 
> diff --git a/config/common_base b/config/common_base
> index d605e85..493811f 100644
> --- a/config/common_base
> +++ b/config/common_base
> @@ -276,6 +276,7 @@ CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_MBOX=n
>  # Compile Support Libraries for NXP DPAA2
>  #
>  CONFIG_RTE_LIBRTE_DPAA2_COMMON=n
> +CONFIG_RTE_LIBRTE_DPAA2_POOL=n
>  
>  #
>  # Compile NXP DPAA2 FSL-MC Bus
> diff --git a/config/defconfig_arm64-dpaa2-linuxapp-gcc b/config/defconfig_arm64-dpaa2-linuxapp-gcc
> index d3bc9d8..7665912 100644
> --- a/config/defconfig_arm64-dpaa2-linuxapp-gcc
> +++ b/config/defconfig_arm64-dpaa2-linuxapp-gcc
> @@ -42,10 +42,14 @@ CONFIG_RTE_ARCH_ARM_TUNE="cortex-a57+fp+simd"
>  CONFIG_RTE_MAX_LCORE=8
>  CONFIG_RTE_MAX_NUMA_NODES=1
>  
> +CONFIG_RTE_PKTMBUF_HEADROOM=256
> +
>  #
>  # Compile Support Libraries for DPAA2
>  #
>  CONFIG_RTE_LIBRTE_DPAA2_COMMON=y
> +CONFIG_RTE_LIBRTE_DPAA2_POOL=n
> +CONFIG_RTE_MBUF_DEFAULT_MEMPOOL_OPS="dpaa2"
>  
>  #
>  # Compile NXP DPAA2 FSL-MC Bus
> diff --git a/drivers/Makefile b/drivers/Makefile
> index bdae63b..9fd268e 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -33,6 +33,7 @@ include $(RTE_SDK)/mk/rte.vars.mk
>  
>  DIRS-y += common
>  DIRS-y += bus
> +DIRS-y += pool
>  DIRS-y += net
>  DIRS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += crypto
>  
> diff --git a/drivers/bus/fslmc/Makefile b/drivers/bus/fslmc/Makefile
> index 1b815dd..35f30ad 100644
> --- a/drivers/bus/fslmc/Makefile
> +++ b/drivers/bus/fslmc/Makefile
> @@ -47,6 +47,7 @@ CFLAGS += "-Wno-strict-aliasing"
>  CFLAGS += -I$(RTE_SDK)/drivers/bus/fslmc
>  CFLAGS += -I$(RTE_SDK)/drivers/bus/fslmc/mc
>  CFLAGS += -I$(RTE_SDK)/drivers/common/dpaa2/qbman/include
> +CFLAGS += -I$(RTE_SDK)/drivers/pool/dpaa2
>  CFLAGS += -I$(RTE_SDK)/lib/librte_eal/linuxapp/eal
>  
>  # versioning export map
> @@ -63,6 +64,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_FSLMC_BUS) += \
>          mc/mc_sys.c
>  
>  SRCS-$(CONFIG_RTE_LIBRTE_FSLMC_BUS) += portal/dpaa2_hw_dpio.c
> +SRCS-$(CONFIG_RTE_LIBRTE_FSLMC_BUS) += portal/dpaa2_hw_dpbp.c
>  SRCS-$(CONFIG_RTE_LIBRTE_FSLMC_BUS) += fslmc_vfio.c
>  SRCS-$(CONFIG_RTE_LIBRTE_FSLMC_BUS) += fslmc_bus.c
>  
> diff --git a/drivers/bus/fslmc/fslmc_vfio.c b/drivers/bus/fslmc/fslmc_vfio.c
> index ed0a8b9..4e47ec8 100644
> --- a/drivers/bus/fslmc/fslmc_vfio.c
> +++ b/drivers/bus/fslmc/fslmc_vfio.c
> @@ -268,7 +268,7 @@ int fslmc_vfio_process_group(struct rte_bus *bus)
>  	char path[PATH_MAX];
>  	int64_t v_addr;
>  	int ndev_count;
> -	int dpio_count = 0;
> +	int dpio_count = 0, dpbp_count = 0;
>  	struct fslmc_vfio_group *group = &vfio_groups[0];
>  	static int process_once;
>  
> @@ -418,6 +418,11 @@ int fslmc_vfio_process_group(struct rte_bus *bus)
>  			if (!ret)
>  				dpio_count++;
>  		}
> +		if (!strcmp(object_type, "dpbp")) {
> +			ret = dpaa2_create_dpbp_device(object_id);
> +			if (!ret)
> +				dpbp_count++;
> +		}
>  	}
>  	closedir(d);
>  
> @@ -425,6 +430,8 @@ int fslmc_vfio_process_group(struct rte_bus *bus)
>  	if (ret)
>  		FSLMC_VFIO_LOG(DEBUG, "Error in affining qbman swp %d", ret);
>  
> +	FSLMC_VFIO_LOG(DEBUG, "DPAA2: Added dpbp_count = %d dpio_count=%d\n",
> +		      dpbp_count, dpio_count);
>  	return 0;
>  
>  FAILURE:
> diff --git a/drivers/bus/fslmc/fslmc_vfio.h b/drivers/bus/fslmc/fslmc_vfio.h
> index e89d980..9bf69d4 100644
> --- a/drivers/bus/fslmc/fslmc_vfio.h
> +++ b/drivers/bus/fslmc/fslmc_vfio.h
> @@ -76,4 +76,6 @@ int dpaa2_create_dpio_device(struct fslmc_vfio_device *vdev,
>  			     struct vfio_device_info *obj_info,
>  			     int object_id);
>  
> +int dpaa2_create_dpbp_device(int dpbp_id);
> +
>  #endif /* _FSLMC_VFIO_H_ */
> diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpbp.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpbp.c
> new file mode 100644
> index 0000000..16d5b24
> --- /dev/null
> +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpbp.c
> @@ -0,0 +1,137 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
> + *   Copyright (c) 2016 NXP. All rights reserved.
> + *
> + *   Redistribution and use in source and binary forms, with or without
> + *   modification, are permitted provided that the following conditions
> + *   are met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in
> + *       the documentation and/or other materials provided with the
> + *       distribution.
> + *     * Neither the name of Freescale Semiconductor, Inc nor the names of its
> + *       contributors may be used to endorse or promote products derived
> + *       from this software without specific prior written permission.
> + *
> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <unistd.h>
> +#include <stdio.h>
> +#include <sys/types.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <fcntl.h>
> +#include <errno.h>
> +
> +#include <rte_malloc.h>
> +#include <rte_memcpy.h>
> +#include <rte_string_fns.h>
> +#include <rte_cycles.h>
> +#include <rte_kvargs.h>
> +#include <rte_dev.h>
> +#include <rte_ethdev.h>
> +
> +#include <fslmc_logs.h>
> +#include <fslmc_vfio.h>
> +#include <mc/fsl_dpbp.h>
> +#include "portal/dpaa2_hw_pvt.h"
> +#include "portal/dpaa2_hw_dpio.h"
> +
> +TAILQ_HEAD(dpbp_device_list, dpaa2_dpbp_dev);
> +static struct dpbp_device_list *dpbp_dev_list; /*!< DPBP device list */
> +
> +int
> +dpaa2_create_dpbp_device(
> +		int dpbp_id)
> +{
> +	struct dpaa2_dpbp_dev *dpbp_node;
> +	int ret;
> +
> +	if (!dpbp_dev_list) {
> +		dpbp_dev_list = malloc(sizeof(struct dpbp_device_list));
> +		if (!dpbp_dev_list) {
> +			PMD_INIT_LOG(ERR, "Memory alloc failed in DPBP list\n");
> +			return -1;
> +		}
> +		/* Initialize the DPBP List */
> +		TAILQ_INIT(dpbp_dev_list);
> +	}
> +
> +	/* Allocate DPAA2 dpbp handle */
> +	dpbp_node = (struct dpaa2_dpbp_dev *)
> +			malloc(sizeof(struct dpaa2_dpbp_dev));
> +	if (!dpbp_node) {
> +		PMD_INIT_LOG(ERR, "Memory allocation failed for DPBP Device");
> +		return -1;
> +	}
> +
> +	/* Open the dpbp object */
> +	dpbp_node->dpbp.regs = mcp_ptr_list[MC_PORTAL_INDEX];
> +	ret = dpbp_open(&dpbp_node->dpbp,
> +			CMD_PRI_LOW, dpbp_id, &dpbp_node->token);
> +	if (ret) {
> +		PMD_INIT_LOG(ERR, "Resource alloc failure with err code: %d",
> +			     ret);
> +		free(dpbp_node);
> +		return -1;
> +	}
> +
> +	/* Clean the device first */
> +	ret = dpbp_reset(&dpbp_node->dpbp, CMD_PRI_LOW, dpbp_node->token);
> +	if (ret) {
> +		PMD_INIT_LOG(ERR, "Failure cleaning dpbp device with"
> +					" error code %d\n", ret);
> +		return -1;
> +	}
> +
> +	dpbp_node->dpbp_id = dpbp_id;
> +	rte_atomic16_init(&dpbp_node->in_use);
> +
> +	TAILQ_INSERT_HEAD(dpbp_dev_list, dpbp_node, next);
> +
> +	PMD_INIT_LOG(DEBUG, "Buffer pool resource initialized %d", dpbp_id);
> +
> +	return 0;
> +}
> +
> +struct dpaa2_dpbp_dev *dpaa2_alloc_dpbp_dev(void)
> +{
> +	struct dpaa2_dpbp_dev *dpbp_dev = NULL;
> +
> +	/* Get DPBP dev handle from list using index */
> +	TAILQ_FOREACH(dpbp_dev, dpbp_dev_list, next) {
> +		if (dpbp_dev && rte_atomic16_test_and_set(&dpbp_dev->in_use))
> +			break;
> +	}
> +
> +	return dpbp_dev;
> +}
> +
> +void dpaa2_free_dpbp_dev(struct dpaa2_dpbp_dev *dpbp)
> +{
> +	struct dpaa2_dpbp_dev *dpbp_dev = NULL;
> +
> +	/* Match DPBP handle and mark it free */
> +	TAILQ_FOREACH(dpbp_dev, dpbp_dev_list, next) {
> +		if (dpbp_dev == dpbp) {
> +			rte_atomic16_dec(&dpbp_dev->in_use);
> +			return;
> +		}
> +	}
> +}
> diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h
> index ef3eb71..3b846a0 100644
> --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h
> +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h
> @@ -41,6 +41,13 @@
>  #define MC_PORTAL_INDEX		0
>  #define NUM_DPIO_REGIONS	2
>  
> +#define MEMPOOL_F_HW_PKT_POOL 0x8000 /**< mpool flag to check offloaded pool */
> +
> +/* Maximum release/acquire from QBMAN */
> +#define DPAA2_MBUF_MAX_ACQ_REL	7
> +
> +#define MAX_BPID 256
> +
>  struct dpaa2_dpio_dev {
>  	TAILQ_ENTRY(dpaa2_dpio_dev) next;
>  		/**< Pointer to Next device instance */
> @@ -63,6 +70,18 @@ struct dpaa2_dpio_dev {
>  	int32_t hw_id; /**< An unique ID of this DPIO device instance */
>  };
>  
> +struct dpaa2_dpbp_dev {
> +	TAILQ_ENTRY(dpaa2_dpbp_dev) next;
> +		/**< Pointer to Next device instance */
> +	struct fsl_mc_io dpbp;  /** handle to DPBP portal object */
> +	uint16_t token;
> +	rte_atomic16_t in_use;
> +	uint32_t dpbp_id; /*HW ID for DPBP object */
> +};
> +
>  /*! Global MCP list */
>  extern void *(*mcp_ptr_list);
> +struct dpaa2_dpbp_dev *dpaa2_alloc_dpbp_dev(void);
> +void dpaa2_free_dpbp_dev(struct dpaa2_dpbp_dev *dpbp);
> +
>  #endif
> diff --git a/drivers/bus/fslmc/rte_pmd_fslmcbus_version.map b/drivers/bus/fslmc/rte_pmd_fslmcbus_version.map
> index 4236377..76029b9 100644
> --- a/drivers/bus/fslmc/rte_pmd_fslmcbus_version.map
> +++ b/drivers/bus/fslmc/rte_pmd_fslmcbus_version.map
> @@ -2,6 +2,8 @@ DPDK_17.02 {
>  	global:
>  
>          dpaa2_affine_qbman_swp;
> +        dpaa2_alloc_dpbp_dev;
> +        dpaa2_free_dpbp_dev;
>          dpbp_disable;
>          dpbp_enable;
>          dpbp_get_attributes;
> diff --git a/drivers/common/Makefile b/drivers/common/Makefile
> index 434280f..0a6d8db 100644
> --- a/drivers/common/Makefile
> +++ b/drivers/common/Makefile
> @@ -34,6 +34,9 @@ include $(RTE_SDK)/mk/rte.vars.mk
>  CONFIG_RTE_LIBRTE_DPAA2_COMMON = $(CONFIG_RTE_LIBRTE_DPAA2_PMD)
>  
>  ifneq ($(CONFIG_RTE_LIBRTE_DPAA2_COMMON),y)
> +CONFIG_RTE_LIBRTE_DPAA2_COMMON = $(CONFIG_RTE_LIBRTE_DPAA2_POOL)
> +endif
> +ifneq ($(CONFIG_RTE_LIBRTE_DPAA2_COMMON),y)
>  CONFIG_RTE_LIBRTE_DPAA2_COMMON = $(CONFIG_RTE_LIBRTE_FSLMC_BUS)
>  endif
>  
> diff --git a/drivers/pool/Makefile b/drivers/pool/Makefile
> new file mode 100644
> index 0000000..4325edd
> --- /dev/null
> +++ b/drivers/pool/Makefile
> @@ -0,0 +1,38 @@
> +#   BSD LICENSE
> +#
> +#   Copyright(c) 2016 NXP. All rights reserved.
> +#   All rights reserved.
> +#
> +#   Redistribution and use in source and binary forms, with or without
> +#   modification, are permitted provided that the following conditions
> +#   are met:
> +#
> +#     * Redistributions of source code must retain the above copyright
> +#       notice, this list of conditions and the following disclaimer.
> +#     * Redistributions in binary form must reproduce the above copyright
> +#       notice, this list of conditions and the following disclaimer in
> +#       the documentation and/or other materials provided with the
> +#       distribution.
> +#     * Neither the name of NXP nor the names of its
> +#       contributors may be used to endorse or promote products derived
> +#       from this software without specific prior written permission.
> +#
> +#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> +#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> +#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> +#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> +#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> +#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> +#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> +#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> +#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> +#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> +#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +include $(RTE_SDK)/mk/rte.vars.mk
> +
> +CONFIG_RTE_LIBRTE_DPAA2_POOL = $(CONFIG_RTE_LIBRTE_DPAA2_PMD)
> +
> +DIRS-$(CONFIG_RTE_LIBRTE_DPAA2_COMMON) += dpaa2
> +
> +include $(RTE_SDK)/mk/rte.subdir.mk
> diff --git a/drivers/pool/dpaa2/Makefile b/drivers/pool/dpaa2/Makefile
> new file mode 100644
> index 0000000..9494756
> --- /dev/null
> +++ b/drivers/pool/dpaa2/Makefile
> @@ -0,0 +1,67 @@
> +#   BSD LICENSE
> +#
> +#   Copyright(c) 2016 NXP. All rights reserved.
> +#   All rights reserved.
> +#
> +#   Redistribution and use in source and binary forms, with or without
> +#   modification, are permitted provided that the following conditions
> +#   are met:
> +#
> +#     * Redistributions of source code must retain the above copyright
> +#       notice, this list of conditions and the following disclaimer.
> +#     * Redistributions in binary form must reproduce the above copyright
> +#       notice, this list of conditions and the following disclaimer in
> +#       the documentation and/or other materials provided with the
> +#       distribution.
> +#     * Neither the name of NXP nor the names of its
> +#       contributors may be used to endorse or promote products derived
> +#       from this software without specific prior written permission.
> +#
> +#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> +#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> +#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> +#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> +#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> +#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> +#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> +#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> +#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> +#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> +#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +include $(RTE_SDK)/mk/rte.vars.mk
> +
> +#
> +# library name
> +#
> +LIB = librte_pmd_dpaa2_pool.a
> +
> +ifeq ($(CONFIG_RTE_LIBRTE_DPAA2_DEBUG_INIT),y)
> +CFLAGS += -O0 -g
> +CFLAGS += "-Wno-error"
> +else
> +CFLAGS += -O3
> +CFLAGS += $(WERROR_FLAGS)
> +endif
> +
> +CFLAGS += -I$(RTE_SDK)/drivers/bus/fslmc
> +CFLAGS += -I$(RTE_SDK)/drivers/common/dpaa2/qbman/include
> +CFLAGS += -I$(RTE_SDK)/lib/librte_eal/linuxapp/eal
> +
> +# versioning export map
> +EXPORT_MAP := rte_pmd_dpaa2_pool_version.map
> +
> +# Lbrary version
> +LIBABIVER := 1
> +
> +# all source are stored in SRCS-y
> +#
> +SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_COMMON) += dpaa2_hw_mempool.c
> +
> +# library dependencies
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_DPAA2_COMMON) += lib/librte_eal
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_DPAA2_COMMON) += lib/librte_mempool
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_DPAA2_COMMON) += lib/librte_pmd_dpaa2_qbman
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_DPAA2_COMMON) += lib/librte_pmd_fslmcbus
> +
> +include $(RTE_SDK)/mk/rte.lib.mk
> diff --git a/drivers/pool/dpaa2/dpaa2_hw_mempool.c b/drivers/pool/dpaa2/dpaa2_hw_mempool.c
> new file mode 100644
> index 0000000..f36e909
> --- /dev/null
> +++ b/drivers/pool/dpaa2/dpaa2_hw_mempool.c
> @@ -0,0 +1,339 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
> + *   Copyright (c) 2016 NXP. All rights reserved.
> + *
> + *   Redistribution and use in source and binary forms, with or without
> + *   modification, are permitted provided that the following conditions
> + *   are met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in
> + *       the documentation and/or other materials provided with the
> + *       distribution.
> + *     * Neither the name of Freescale Semiconductor, Inc nor the names of its
> + *       contributors may be used to endorse or promote products derived
> + *       from this software without specific prior written permission.
> + *
> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <unistd.h>
> +#include <stdio.h>
> +#include <sys/types.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <fcntl.h>
> +#include <errno.h>
> +
> +#include <rte_mbuf.h>
> +#include <rte_ethdev.h>
> +#include <rte_malloc.h>
> +#include <rte_memcpy.h>
> +#include <rte_string_fns.h>
> +#include <rte_cycles.h>
> +#include <rte_kvargs.h>
> +#include <rte_dev.h>
> +#include <rte_ethdev.h>
> +
> +#include <fslmc_logs.h>
> +#include <mc/fsl_dpbp.h>
> +#include <portal/dpaa2_hw_pvt.h>
> +#include <portal/dpaa2_hw_dpio.h>
> +#include "dpaa2_hw_mempool.h"
> +
> +struct dpaa2_bp_info bpid_info[MAX_BPID];
> +static struct dpaa2_bp_list *h_bp_list;
> +
> +static int
> +hw_mbuf_create_pool(struct rte_mempool *mp)
> +{
> +	struct dpaa2_bp_list *bp_list;
> +	struct dpaa2_dpbp_dev *avail_dpbp;
> +	struct dpbp_attr dpbp_attr;
> +	uint32_t bpid;
> +	int ret;
> +
> +	avail_dpbp = dpaa2_alloc_dpbp_dev();
> +
> +	if (!avail_dpbp) {
> +		PMD_DRV_LOG(ERR, "DPAA2 resources not available");
> +		return -1;
> +	}
> +
> +	if (unlikely(!DPAA2_PER_LCORE_DPIO)) {
> +		ret = dpaa2_affine_qbman_swp();
> +		if (ret) {
> +			RTE_LOG(ERR, PMD, "Failure in affining portal\n");
> +			return 0;
> +		}
> +	}
> +
> +	ret = dpbp_enable(&avail_dpbp->dpbp, CMD_PRI_LOW, avail_dpbp->token);
> +	if (ret != 0) {
> +		PMD_INIT_LOG(ERR, "Resource enable failure with"
> +			" err code: %d\n", ret);
> +		return -1;
> +	}
> +
> +	ret = dpbp_get_attributes(&avail_dpbp->dpbp, CMD_PRI_LOW,
> +				  avail_dpbp->token, &dpbp_attr);
> +	if (ret != 0) {
> +		PMD_INIT_LOG(ERR, "Resource read failure with"
> +			     " err code: %d\n", ret);
> +		ret = dpbp_disable(&avail_dpbp->dpbp, CMD_PRI_LOW,
> +				   avail_dpbp->token);
> +		return -1;
> +	}
> +
> +	/* Allocate the bp_list which will be added into global_bp_list */
> +	bp_list = (struct dpaa2_bp_list *)malloc(sizeof(struct dpaa2_bp_list));
> +	if (!bp_list) {
> +		PMD_INIT_LOG(ERR, "No heap memory available");
> +		return -1;
> +	}
> +
> +	/* Set parameters of buffer pool list */
> +	bp_list->buf_pool.num_bufs = mp->size;
> +	bp_list->buf_pool.size = mp->elt_size
> +			- sizeof(struct rte_mbuf) - rte_pktmbuf_priv_size(mp);
> +	bp_list->buf_pool.bpid = dpbp_attr.bpid;
> +	bp_list->buf_pool.h_bpool_mem = NULL;

I am guessing that vfio-platform takes care of allocating memory to bman for
buffer management (Beside mapping the platform resource) Or bman hw internally
takes care and return a bpid handle to the application, right. Thus you don;t
care for allocating mz area for this mempool.

> +	bp_list->buf_pool.mp = mp;
> +	bp_list->buf_pool.dpbp_node = avail_dpbp;
> +	bp_list->next = h_bp_list;
> +
> +	bpid = dpbp_attr.bpid;
> +
> +
> +	bpid_info[bpid].meta_data_size = sizeof(struct rte_mbuf)
> +				+ rte_pktmbuf_priv_size(mp);
> +	bpid_info[bpid].bp_list = bp_list;
> +	bpid_info[bpid].bpid = bpid;
> +
> +	mp->pool_data = (void *)&bpid_info[bpid];
> +
> +	PMD_INIT_LOG(DEBUG, "BP List created for bpid =%d", dpbp_attr.bpid);
> +
> +	h_bp_list = bp_list;
> +	/* Identification for our offloaded pool_data structure
> +	 */
> +	mp->flags |= MEMPOOL_F_HW_PKT_POOL;
> +	return 0;
> +}
> +
> +static void
> +hw_mbuf_free_pool(struct rte_mempool *mp)
> +{
> +	struct dpaa2_bp_info *bpinfo;
> +	struct dpaa2_bp_list *bp;
> +	struct dpaa2_dpbp_dev *dpbp_node;
> +
> +	if (!mp->pool_data) {
> +		PMD_DRV_LOG(ERR, "Not a valid dpaa22 pool");
> +		return;
> +	}
> +
> +	bpinfo = (struct dpaa2_bp_info *)mp->pool_data;
> +	bp = bpinfo->bp_list;
> +	dpbp_node = bp->buf_pool.dpbp_node;
> +
> +	dpbp_disable(&(dpbp_node->dpbp), CMD_PRI_LOW, dpbp_node->token);
> +
> +	if (h_bp_list == bp) {
> +		h_bp_list = h_bp_list->next;
> +	} else { /* if it is not the first node */
> +		struct dpaa2_bp_list *prev = h_bp_list, *temp;
> +		temp = h_bp_list->next;
> +		while (temp) {
> +			if (temp == bp) {
> +				prev->next = temp->next;
> +				free(bp);

why not use rte_free()?

> +				break;
> +			}
> +			prev = temp;
> +			temp = temp->next;
> +		}
> +	}
> +
> +	dpaa2_free_dpbp_dev(dpbp_node);
> +}
> +
> +static
> +void dpaa2_mbuf_release(struct rte_mempool *pool __rte_unused,
> +			void * const *obj_table,
> +			uint32_t bpid,
> +			uint32_t meta_data_size,
> +			int count)
> +{
> +	struct qbman_release_desc releasedesc;
> +	struct qbman_swp *swp;
> +	int ret;
> +	int i, n;
> +	uint64_t bufs[DPAA2_MBUF_MAX_ACQ_REL];
> +
> +	if (unlikely(!DPAA2_PER_LCORE_DPIO)) {
> +		ret = dpaa2_affine_qbman_swp();
> +		if (ret != 0) {
> +			RTE_LOG(ERR, PMD, "Failed to allocate IO portal");
> +			return;
> +		}
> +	}
> +	swp = DPAA2_PER_LCORE_PORTAL;
> +
> +	/* Create a release descriptor required for releasing
> +	 * buffers into QBMAN
> +	 */
> +	qbman_release_desc_clear(&releasedesc);
> +	qbman_release_desc_set_bpid(&releasedesc, bpid);
> +
> +	n = count % DPAA2_MBUF_MAX_ACQ_REL;
> +
> +	/* convert mbuf to buffers  for the remainder*/
> +	for (i = 0; i < n ; i++)
> +		bufs[i] = (uint64_t)obj_table[i] + meta_data_size;
> +
> +	/* feed them to bman*/
> +	do {
> +		ret = qbman_swp_release(swp, &releasedesc, bufs, n);
> +	} while (ret == -EBUSY);
> +
> +	/* if there are more buffers to free */
> +	while (n < count) {
> +		/* convert mbuf to buffers */
> +		for (i = 0; i < DPAA2_MBUF_MAX_ACQ_REL; i++)
> +			bufs[i] = (uint64_t)obj_table[n + i] + meta_data_size;
> +
> +		do {
> +			ret = qbman_swp_release(swp, &releasedesc, bufs,
> +						DPAA2_MBUF_MAX_ACQ_REL);
> +			} while (ret == -EBUSY);
> +		n += DPAA2_MBUF_MAX_ACQ_REL;
> +	}
> +}
> +
> +int hw_mbuf_alloc_bulk(struct rte_mempool *pool,
> +		       void **obj_table, unsigned int count)
> +{
> +#ifdef RTE_LIBRTE_DPAA2_DEBUG_DRIVER
> +	static int alloc;
> +#endif
> +	struct qbman_swp *swp;
> +	uint32_t mbuf_size;
> +	uint16_t bpid;
> +	uint64_t bufs[DPAA2_MBUF_MAX_ACQ_REL];
> +	int i, ret;
> +	unsigned int n = 0;
> +	struct dpaa2_bp_info *bp_info;
> +
> +	bp_info = mempool_to_bpinfo(pool);
> +
> +	if (!(bp_info->bp_list)) {
> +		RTE_LOG(ERR, PMD, "DPAA2 buffer pool not configured\n");
> +		return -2;
> +	}
> +
> +	bpid = bp_info->bpid;
> +
> +	if (unlikely(!DPAA2_PER_LCORE_DPIO)) {
> +		ret = dpaa2_affine_qbman_swp();
> +		if (ret != 0) {
> +			RTE_LOG(ERR, PMD, "Failed to allocate IO portal");
> +			return -1;
> +		}
> +	}
> +	swp = DPAA2_PER_LCORE_PORTAL;
> +
> +	mbuf_size = sizeof(struct rte_mbuf) + rte_pktmbuf_priv_size(pool);
> +
> +	while (n < count) {
> +		/* Acquire is all-or-nothing, so we drain in 7s,
> +		 * then the remainder.
> +		 */
> +		if ((count - n) > DPAA2_MBUF_MAX_ACQ_REL) {
> +			ret = qbman_swp_acquire(swp, bpid, bufs,
> +						DPAA2_MBUF_MAX_ACQ_REL);
> +		} else {
> +			ret = qbman_swp_acquire(swp, bpid, bufs,
> +						count - n);
> +		}
> +		/* In case of less than requested number of buffers available
> +		 * in pool, qbman_swp_acquire returns 0
> +		 */
> +		if (ret <= 0) {
> +			PMD_TX_LOG(ERR, "Buffer acquire failed with"
> +				   " err code: %d", ret);
> +			/* The API expect the exact number of requested bufs */
> +			/* Releasing all buffers allocated */
> +			dpaa2_mbuf_release(pool, obj_table, bpid,
> +					   bp_info->meta_data_size, n);
> +			return -1;
> +		}
> +		/* assigning mbuf from the acquired objects */
> +		for (i = 0; (i < ret) && bufs[i]; i++) {
> +			/* TODO-errata - observed that bufs may be null
> +			 * i.e. first buffer is valid,
> +			 * remaining 6 buffers may be null
> +			 */
> +			obj_table[n] = (struct rte_mbuf *)(bufs[i] - mbuf_size);
> +			rte_mbuf_refcnt_set((struct rte_mbuf *)obj_table[n], 0);
> +			PMD_TX_LOG(DEBUG, "Acquired %p address %p from BMAN",
> +				   (void *)bufs[i], (void *)obj_table[n]);
> +			n++;
> +		}
> +	}
> +
> +#ifdef RTE_LIBRTE_DPAA2_DEBUG_DRIVER
> +	alloc += n;
> +	PMD_TX_LOG(DEBUG, "Total = %d , req = %d done = %d",
> +		   alloc, count, n);
> +#endif
> +	return 0;
> +}
> +
> +static int
> +hw_mbuf_free_bulk(struct rte_mempool *pool,
> +		  void * const *obj_table, unsigned int n)
> +{
> +	struct dpaa2_bp_info *bp_info;
> +
> +	bp_info = mempool_to_bpinfo(pool);
> +	if (!(bp_info->bp_list)) {
> +		RTE_LOG(ERR, PMD, "DPAA2 buffer pool not configured");
> +		return -1;
> +	}
> +	dpaa2_mbuf_release(pool, obj_table, bp_info->bpid,
> +			   bp_info->meta_data_size, n);
> +
> +	return 0;
> +}
> +
> +static unsigned
> +hw_mbuf_get_count(const struct rte_mempool *mp __rte_unused)
> +{
> +	return 0;
> +}
> +
> +struct rte_mempool_ops dpaa2_mpool_ops = {
> +	.name = "dpaa2",
> +	.alloc = hw_mbuf_create_pool,
> +	.free = hw_mbuf_free_pool,
> +	.enqueue = hw_mbuf_free_bulk,
> +	.dequeue = hw_mbuf_alloc_bulk,
> +	.get_count = hw_mbuf_get_count,
> +};
> +
> +MEMPOOL_REGISTER_OPS(dpaa2_mpool_ops);
> diff --git a/drivers/pool/dpaa2/dpaa2_hw_mempool.h b/drivers/pool/dpaa2/dpaa2_hw_mempool.h
> new file mode 100644
> index 0000000..2cd2564
> --- /dev/null
> +++ b/drivers/pool/dpaa2/dpaa2_hw_mempool.h
> @@ -0,0 +1,95 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
> + *   Copyright (c) 2016 NXP. All rights reserved.
> + *
> + *   Redistribution and use in source and binary forms, with or without
> + *   modification, are permitted provided that the following conditions
> + *   are met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in
> + *       the documentation and/or other materials provided with the
> + *       distribution.
> + *     * Neither the name of Freescale Semiconductor, Inc nor the names of its
> + *       contributors may be used to endorse or promote products derived
> + *       from this software without specific prior written permission.
> + *
> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#ifndef _DPAA2_HW_DPBP_H_
> +#define _DPAA2_HW_DPBP_H_
> +
> +#define DPAA2_MAX_BUF_POOLS	8
> +
> +struct buf_pool_cfg {
> +	void *addr; /*!< The address from where DPAA2 will carve out the
> +		     * buffers. 'addr' should be 'NULL' if user wants
> +		     * to create buffers from the memory which user
> +		     * asked DPAA2 to reserve during 'nadk init'
> +		     */
> +	phys_addr_t    phys_addr;  /*!< corresponding physical address
> +				    * of the memory provided in addr
> +				    */
> +	uint32_t num; /*!< number of buffers */
> +	uint32_t size; /*!< size of each buffer. 'size' should include
> +			* any headroom to be reserved and alignment
> +			*/
> +	uint16_t align; /*!< Buffer alignment (in bytes) */
> +	uint16_t bpid; /*!< The buffer pool id. This will be filled
> +			*in by DPAA2 for each buffer pool
> +			*/
> +};
> +
> +struct buf_pool {
> +	uint32_t size;
> +	uint32_t num_bufs;
> +	uint16_t bpid;
> +	uint8_t *h_bpool_mem;
> +	struct rte_mempool *mp;
> +	struct dpaa2_dpbp_dev *dpbp_node;
> +};
> +
> +/*!
> + * Buffer pool list configuration structure. User need to give DPAA2 the
> + * valid number of 'num_buf_pools'.
> + */
> +struct dpaa2_bp_list_cfg {
> +	struct buf_pool_cfg buf_pool; /* Configuration of each buffer pool*/
> +};
> +

isn't dpaa2_bp_list_cfg{} thus buf_pool_cfg{} redundant? I couldn't find
struct used in this patch Or perhaps someother patch using them, If so then
pl. ignore my comment.

> +struct dpaa2_bp_list {
> +	struct dpaa2_bp_list *next;
> +	struct rte_mempool *mp;
> +	struct buf_pool buf_pool;
> +};
> +
> +struct dpaa2_bp_info {
> +	uint32_t meta_data_size;
> +	uint32_t bpid;
> +	struct dpaa2_bp_list *bp_list;
> +};
> +
> +#define mempool_to_bpinfo(mp) ((struct dpaa2_bp_info *)(mp)->pool_data)
> +#define mempool_to_bpid(mp) ((mempool_to_bpinfo(mp))->bpid)
> +
> +extern struct dpaa2_bp_info bpid_info[MAX_BPID];
> +
> +int hw_mbuf_alloc_bulk(struct rte_mempool *pool,
> +		       void **obj_table, unsigned int count);
> +
> +#endif /* _DPAA2_HW_DPBP_H_ */
> diff --git a/drivers/pool/dpaa2/rte_pmd_dpaa2_pool_version.map b/drivers/pool/dpaa2/rte_pmd_dpaa2_pool_version.map
> new file mode 100644
> index 0000000..289ab10
> --- /dev/null
> +++ b/drivers/pool/dpaa2/rte_pmd_dpaa2_pool_version.map
> @@ -0,0 +1,8 @@
> +DPDK_17.02 {
> +	global:
> +
> +	bpid_info;
> +	hw_mbuf_alloc_bulk;
> +
> +	local: *;
> +};
> diff --git a/mk/rte.app.mk b/mk/rte.app.mk
> index 438fa2c..1bfb804 100644
> --- a/mk/rte.app.mk
> +++ b/mk/rte.app.mk
> @@ -112,6 +112,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CXGBE_PMD)      += -lrte_pmd_cxgbe
>  ifeq ($(CONFIG_RTE_LIBRTE_DPAA2_COMMON),y)
>  _LDLIBS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD)      += -lrte_pmd_dpaa2
>  _LDLIBS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD)      += -lrte_pmd_dpaa2_qbman
> +_LDLIBS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD)      += -lrte_pmd_dpaa2_pool
>  _LDLIBS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD)      += -lrte_pmd_fslmcbus
>  endif
>  _LDLIBS-$(CONFIG_RTE_LIBRTE_E1000_PMD)      += -lrte_pmd_e1000
> -- 
> 2.7.4
> 

^ permalink raw reply

* [PATCH v3 33/33] drivers/common/dpaa2: frame queue based dq storage alloc
From: Shreyansh Jain @ 2016-12-29  5:16 UTC (permalink / raw)
  To: dev
  Cc: thomas.monjalon, bruce.richardson, john.mcnamara, ferruh.yigit,
	jerin.jacob, Hemant Agrawal
In-Reply-To: <1482988612-6638-1-git-send-email-shreyansh.jain@nxp.com>

From: Hemant Agrawal <hemant.agrawal@nxp.com>

This patch adds generic functions for allowing dq storage
for the frame queues.
As the frame queues are common resource for different drivers
this is helpful.

Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c       | 32 ++++++++++++++++++++++++++
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.h       |  7 ++++++
 drivers/bus/fslmc/rte_pmd_fslmcbus_version.map |  2 ++
 drivers/net/dpaa2/dpaa2_ethdev.c               |  8 +++----
 4 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
index d7de0d5..55b5ad7 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
@@ -407,3 +407,35 @@ dpaa2_create_dpio_device(struct fslmc_vfio_device *vdev,
 
 	return 0;
 }
+
+void
+dpaa2_free_dq_storage(struct queue_storage_info_t *q_storage)
+{
+	int i = 0;
+
+	for (i = 0; i < NUM_DQS_PER_QUEUE; i++) {
+		if (q_storage->dq_storage[i])
+			rte_free(q_storage->dq_storage[i]);
+	}
+}
+
+int
+dpaa2_alloc_dq_storage(struct queue_storage_info_t *q_storage)
+{
+	int i = 0;
+
+	for (i = 0; i < NUM_DQS_PER_QUEUE; i++) {
+		q_storage->dq_storage[i] = rte_malloc(NULL,
+			DPAA2_DQRR_RING_SIZE * sizeof(struct qbman_result),
+			RTE_CACHE_LINE_SIZE);
+		if (!q_storage->dq_storage[i])
+			goto fail;
+	}
+	return 0;
+fail:
+	i -= 1;
+	while (i >= 0)
+		rte_free(q_storage->dq_storage[i]);
+
+	return -1;
+}
diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h
index b1a1b8f..f2e1168 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h
@@ -59,5 +59,12 @@ int dpaa2_affine_qbman_swp(void);
 /* Affine additional DPIO portal to current crypto processing thread */
 int dpaa2_affine_qbman_swp_sec(void);
 
+/* allocate memory for FQ - dq storage */
+int
+dpaa2_alloc_dq_storage(struct queue_storage_info_t *q_storage);
+
+/* free memory for FQ- dq storage */
+void
+dpaa2_free_dq_storage(struct queue_storage_info_t *q_storage);
 
 #endif /* _DPAA2_HW_DPIO_H_ */
diff --git a/drivers/bus/fslmc/rte_pmd_fslmcbus_version.map b/drivers/bus/fslmc/rte_pmd_fslmcbus_version.map
index 17befc7..bccdc75 100644
--- a/drivers/bus/fslmc/rte_pmd_fslmcbus_version.map
+++ b/drivers/bus/fslmc/rte_pmd_fslmcbus_version.map
@@ -4,7 +4,9 @@ DPDK_17.02 {
         dpaa2_affine_qbman_swp;
         dpaa2_affine_qbman_swp_sec;
         dpaa2_alloc_dpbp_dev;
+        dpaa2_alloc_dq_storage;
         dpaa2_free_dpbp_dev;
+        dpaa2_free_dq_storage;
         dpbp_disable;
         dpbp_enable;
         dpbp_get_attributes;
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 3a90e7c..43ae4cb 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -49,6 +49,7 @@
 #include <fslmc_vfio.h>
 #include <dpaa2_hw_pvt.h>
 #include <dpaa2_hw_mempool.h>
+#include <dpaa2_hw_dpio.h>
 
 #include "dpaa2_ethdev.h"
 
@@ -170,9 +171,8 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev)
 
 		memset(dpaa2_q->q_storage, 0,
 		       sizeof(struct queue_storage_info_t));
-		dpaa2_q->q_storage->dq_storage[0] = rte_malloc(NULL,
-			DPAA2_DQRR_RING_SIZE * sizeof(struct qbman_result),
-			RTE_CACHE_LINE_SIZE);
+		if (dpaa2_alloc_dq_storage(dpaa2_q->q_storage))
+			goto fail;
 	}
 
 	for (i = 0; i < priv->nb_tx_queues; i++) {
@@ -196,7 +196,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev)
 	mc_q = priv->rx_vq[0];
 	while (i >= 0) {
 		dpaa2_q = (struct dpaa2_queue *)priv->rx_vq[i];
-		rte_free(dpaa2_q->q_storage->dq_storage[0]);
+		dpaa2_free_dq_storage(dpaa2_q->q_storage);
 		rte_free(dpaa2_q->q_storage);
 		priv->rx_vq[i--] = NULL;
 	}
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 32/33] bus/fslmc: add support for dmamap to ARM SMMU
From: Shreyansh Jain @ 2016-12-29  5:16 UTC (permalink / raw)
  To: dev
  Cc: thomas.monjalon, bruce.richardson, john.mcnamara, ferruh.yigit,
	jerin.jacob, Hemant Agrawal
In-Reply-To: <1482988612-6638-1-git-send-email-shreyansh.jain@nxp.com>

From: Hemant Agrawal <hemant.agrawal@nxp.com>

Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
 drivers/bus/fslmc/fslmc_vfio.c                 | 97 ++++++++++++++++++++++++++
 drivers/bus/fslmc/fslmc_vfio.h                 |  1 +
 drivers/bus/fslmc/rte_pmd_fslmcbus_version.map |  1 +
 drivers/net/dpaa2/dpaa2_ethdev.c               |  2 +
 4 files changed, 101 insertions(+)

diff --git a/drivers/bus/fslmc/fslmc_vfio.c b/drivers/bus/fslmc/fslmc_vfio.c
index 4e47ec8..b9598ae 100644
--- a/drivers/bus/fslmc/fslmc_vfio.c
+++ b/drivers/bus/fslmc/fslmc_vfio.c
@@ -76,8 +76,10 @@
 static struct fslmc_vfio_group vfio_groups[VFIO_MAX_GRP];
 static struct fslmc_vfio_container vfio_containers[VFIO_MAX_CONTAINERS];
 static int container_device_fd;
+static uint32_t *msi_intr_vaddr;
 void *(*mcp_ptr_list);
 static uint32_t mcp_id;
+static int is_dma_done;
 
 static int vfio_connect_container(struct fslmc_vfio_group *vfio_group)
 {
@@ -147,6 +149,35 @@ static int vfio_connect_container(struct fslmc_vfio_group *vfio_group)
 	return 0;
 }
 
+static int vfio_map_irq_region(struct fslmc_vfio_group *group)
+{
+	int ret;
+	unsigned long *vaddr = NULL;
+	struct vfio_iommu_type1_dma_map map = {
+		.argsz = sizeof(map),
+		.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE,
+		.vaddr = 0x6030000,
+		.iova = 0x6030000,
+		.size = 0x1000,
+	};
+
+	vaddr = (unsigned long *)mmap(NULL, 0x1000, PROT_WRITE |
+		PROT_READ, MAP_SHARED, container_device_fd, 0x6030000);
+	if (vaddr == MAP_FAILED) {
+		FSLMC_VFIO_LOG(ERR, "Unable to map region (errno = %d)", errno);
+		return -errno;
+	}
+
+	msi_intr_vaddr = (uint32_t *)((char *)(vaddr) + 64);
+	map.vaddr = (unsigned long)vaddr;
+	ret = ioctl(group->container->fd, VFIO_IOMMU_MAP_DMA, &map);
+	if (ret == 0)
+		return 0;
+
+	FSLMC_VFIO_LOG(ERR, "VFIO_IOMMU_MAP_DMA fails (errno = %d)", errno);
+	return -errno;
+}
+
 int vfio_dmamap_mem_region(uint64_t vaddr,
 			   uint64_t iova,
 			   uint64_t size)
@@ -169,6 +200,72 @@ int vfio_dmamap_mem_region(uint64_t vaddr,
 	}
 	return 0;
 }
+
+int fslmc_vfio_dmamap(void)
+{
+	int ret;
+	struct fslmc_vfio_group *group;
+	struct vfio_iommu_type1_dma_map dma_map = {
+		.argsz = sizeof(struct vfio_iommu_type1_dma_map),
+		.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE,
+	};
+
+	int i;
+	const struct rte_memseg *memseg;
+
+	if (is_dma_done)
+		return 0;
+	is_dma_done = 1;
+
+	for (i = 0; i < RTE_MAX_MEMSEG; i++) {
+		memseg = rte_eal_get_physmem_layout();
+		if (memseg == NULL) {
+			FSLMC_VFIO_LOG(ERR, "Cannot get physical layout.");
+			return -ENODEV;
+		}
+
+		if (memseg[i].addr == NULL && memseg[i].len == 0)
+			break;
+
+		dma_map.size = memseg[i].len;
+		dma_map.vaddr = memseg[i].addr_64;
+#ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA
+		dma_map.iova = memseg[i].phys_addr;
+#else
+		dma_map.iova = dma_map.vaddr;
+#endif
+
+		/* SET DMA MAP for IOMMU */
+		group = &vfio_groups[0];
+
+		if (!group->container) {
+			FSLMC_VFIO_LOG(ERR, "Container is not connected ");
+			return -1;
+		}
+
+		FSLMC_VFIO_LOG(DEBUG, "-->Initial SHM Virtual ADDR %llX",
+			     dma_map.vaddr);
+		FSLMC_VFIO_LOG(DEBUG, "-----> DMA size 0x%llX\n", dma_map.size);
+		ret = ioctl(group->container->fd, VFIO_IOMMU_MAP_DMA,
+			    &dma_map);
+		if (ret) {
+			FSLMC_VFIO_LOG(ERR, "VFIO_IOMMU_MAP_DMA API"
+				       "(errno = %d)", errno);
+			return ret;
+		}
+		FSLMC_VFIO_LOG(DEBUG, "-----> dma_map.vaddr = 0x%llX",
+			     dma_map.vaddr);
+	}
+
+	/* TODO - This is a W.A. as VFIO currently does not add the mapping of
+	 * the interrupt region to SMMU. This should be removed once the
+	 * support is added in the Kernel.
+	 */
+	vfio_map_irq_region(group);
+
+	return 0;
+}
+
 static int64_t vfio_map_mcp_obj(struct fslmc_vfio_group *group, char *mcp_obj)
 {
 	int64_t v_addr = (int64_t)MAP_FAILED;
diff --git a/drivers/bus/fslmc/fslmc_vfio.h b/drivers/bus/fslmc/fslmc_vfio.h
index 9bf69d4..85fb70b 100644
--- a/drivers/bus/fslmc/fslmc_vfio.h
+++ b/drivers/bus/fslmc/fslmc_vfio.h
@@ -70,6 +70,7 @@ int vfio_dmamap_mem_region(
 
 int fslmc_vfio_setup_group(void);
 int fslmc_vfio_process_group(struct rte_bus *bus);
+int fslmc_vfio_dmamap(void);
 
 /* create dpio device */
 int dpaa2_create_dpio_device(struct fslmc_vfio_device *vdev,
diff --git a/drivers/bus/fslmc/rte_pmd_fslmcbus_version.map b/drivers/bus/fslmc/rte_pmd_fslmcbus_version.map
index 6937ad0..17befc7 100644
--- a/drivers/bus/fslmc/rte_pmd_fslmcbus_version.map
+++ b/drivers/bus/fslmc/rte_pmd_fslmcbus_version.map
@@ -49,6 +49,7 @@ DPDK_17.02 {
         dpseci_open;
         dpseci_reset;
         dpseci_set_rx_queue;
+        fslmc_vfio_dmamap;
         mcp_ptr_list;
         per_lcore__dpaa2_io;
         rte_fslmc_driver_register;
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index d1456d5..3a90e7c 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -911,6 +911,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev)
 
 	eth_dev->rx_pkt_burst = dpaa2_dev_rx;
 	eth_dev->tx_pkt_burst = dpaa2_dev_tx;
+	fslmc_vfio_dmamap();
+
 	return 0;
 }
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 31/33] net/dpaa2: enabling the use of physical addresses
From: Shreyansh Jain @ 2016-12-29  5:16 UTC (permalink / raw)
  To: dev
  Cc: thomas.monjalon, bruce.richardson, john.mcnamara, ferruh.yigit,
	jerin.jacob, Hemant Agrawal
In-Reply-To: <1482988612-6638-1-git-send-email-shreyansh.jain@nxp.com>

From: Hemant Agrawal <hemant.agrawal@nxp.com>

DPAA2 - ARM support both physical and virtual addressing.
This patch enables the compile time usages of physical
address instead of virtual address.

The current usages are also set to default as Physical
Address.

Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
 config/common_base                        |  1 +
 config/defconfig_arm64-dpaa2-linuxapp-gcc |  1 +
 drivers/bus/fslmc/portal/dpaa2_hw_pvt.h   | 66 +++++++++++++++++++++++++++++++
 drivers/net/dpaa2/base/dpaa2_hw_dpni.c    |  4 +-
 drivers/net/dpaa2/dpaa2_rxtx.c            | 16 ++++----
 drivers/pool/dpaa2/dpaa2_hw_mempool.c     | 19 +++++++--
 6 files changed, 95 insertions(+), 12 deletions(-)

diff --git a/config/common_base b/config/common_base
index 493811f..35a580e 100644
--- a/config/common_base
+++ b/config/common_base
@@ -277,6 +277,7 @@ CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_MBOX=n
 #
 CONFIG_RTE_LIBRTE_DPAA2_COMMON=n
 CONFIG_RTE_LIBRTE_DPAA2_POOL=n
+CONFIG_RTE_LIBRTE_DPAA2_USE_PHYS_IOVA=y
 
 #
 # Compile NXP DPAA2 FSL-MC Bus
diff --git a/config/defconfig_arm64-dpaa2-linuxapp-gcc b/config/defconfig_arm64-dpaa2-linuxapp-gcc
index 7665912..18c9589 100644
--- a/config/defconfig_arm64-dpaa2-linuxapp-gcc
+++ b/config/defconfig_arm64-dpaa2-linuxapp-gcc
@@ -50,6 +50,7 @@ CONFIG_RTE_PKTMBUF_HEADROOM=256
 CONFIG_RTE_LIBRTE_DPAA2_COMMON=y
 CONFIG_RTE_LIBRTE_DPAA2_POOL=n
 CONFIG_RTE_MBUF_DEFAULT_MEMPOOL_OPS="dpaa2"
+CONFIG_RTE_LIBRTE_DPAA2_USE_PHYS_IOVA=y
 
 #
 # Compile NXP DPAA2 FSL-MC Bus
diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h
index 158dfef..052a171 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h
@@ -175,6 +175,72 @@ struct qbman_fle {
  */
 #define DPAA2_EQ_RESP_ALWAYS		1
 
+#ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA
+static void *dpaa2_mem_ptov(phys_addr_t paddr) __attribute__((unused));
+/* todo - this is costly, need to write a fast coversion routine */
+static void *dpaa2_mem_ptov(phys_addr_t paddr)
+{
+	const struct rte_memseg *memseg = rte_eal_get_physmem_layout();
+	int i;
+
+	for (i = 0; i < RTE_MAX_MEMSEG && memseg[i].addr_64 != 0; i++) {
+		if (paddr >= memseg[i].phys_addr &&
+		   (char *)paddr < (char *)memseg[i].phys_addr + memseg[i].len)
+			return (void *)(memseg[i].addr_64
+				+ (paddr - memseg[i].phys_addr));
+	}
+	return NULL;
+}
+
+static phys_addr_t dpaa2_mem_vtop(uint64_t vaddr) __attribute__((unused));
+static phys_addr_t dpaa2_mem_vtop(uint64_t vaddr)
+{
+	const struct rte_memseg *memseg = rte_eal_get_physmem_layout();
+	int i;
+
+	for (i = 0; i < RTE_MAX_MEMSEG && memseg[i].addr_64 != 0; i++) {
+		if (vaddr >= memseg[i].addr_64 &&
+		    vaddr < memseg[i].addr_64 + memseg[i].len)
+			return memseg[i].phys_addr
+				+ (vaddr - memseg[i].addr_64);
+	}
+	return (phys_addr_t)(NULL);
+}
+
+/**
+ * When we are using Physical addresses as IO Virtual Addresses,
+ * Need to call conversion routines dpaa2_mem_vtop & dpaa2_mem_ptov
+ * whereever required.
+ * These routines are called with help of below MACRO's
+ */
+
+#define DPAA2_MBUF_VADDR_TO_IOVA(mbuf) ((mbuf)->buf_physaddr)
+
+/**
+ * macro to convert Virtual address to IOVA
+ */
+#define DPAA2_VADDR_TO_IOVA(_vaddr) dpaa2_mem_vtop((uint64_t)(_vaddr))
+
+/**
+ * macro to convert IOVA to Virtual address
+ */
+#define DPAA2_IOVA_TO_VADDR(_iova) dpaa2_mem_ptov((phys_addr_t)(_iova))
+
+/**
+ * macro to convert modify the memory containing IOVA to Virtual address
+ */
+#define DPAA2_MODIFY_IOVA_TO_VADDR(_mem, _type) \
+	{_mem = (_type)(dpaa2_mem_ptov((phys_addr_t)(_mem))); }
+
+#else	/* RTE_LIBRTE_DPAA2_USE_PHYS_IOVA */
+
+#define DPAA2_MBUF_VADDR_TO_IOVA(mbuf) ((mbuf)->buf_addr)
+#define DPAA2_VADDR_TO_IOVA(_vaddr) (_vaddr)
+#define DPAA2_IOVA_TO_VADDR(_iova) (_iova)
+#define DPAA2_MODIFY_IOVA_TO_VADDR(_mem, _type)
+
+#endif /* RTE_LIBRTE_DPAA2_USE_PHYS_IOVA */
+
 struct dpaa2_dpbp_dev *dpaa2_alloc_dpbp_dev(void);
 void dpaa2_free_dpbp_dev(struct dpaa2_dpbp_dev *dpbp);
 
diff --git a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c
index 08f53b3..3dc60cc 100644
--- a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c
+++ b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c
@@ -76,7 +76,7 @@ dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev,
 	memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg));
 
 	dpaa2_distset_to_dpkg_profile_cfg(req_dist_set, &kg_cfg);
-	tc_cfg.key_cfg_iova = (uint64_t)(p_params);
+	tc_cfg.key_cfg_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(p_params));
 	tc_cfg.dist_size = eth_dev->data->nb_rx_queues;
 	tc_cfg.dist_mode = DPNI_DIST_MODE_HASH;
 
@@ -119,7 +119,7 @@ int dpaa2_remove_flow_dist(
 	memset(p_params, 0, DIST_PARAM_IOVA_SIZE);
 	memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg));
 
-	tc_cfg.key_cfg_iova = (uint64_t)(p_params);
+	tc_cfg.key_cfg_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(p_params));
 	tc_cfg.dist_size = 0;
 	tc_cfg.dist_mode = DPNI_DIST_MODE_NONE;
 
diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c
index 55068e5..4596337 100644
--- a/drivers/net/dpaa2/dpaa2_rxtx.c
+++ b/drivers/net/dpaa2/dpaa2_rxtx.c
@@ -136,7 +136,7 @@ static inline struct rte_mbuf *__attribute__((hot))
 eth_fd_to_mbuf(const struct qbman_fd *fd)
 {
 	struct rte_mbuf *mbuf = DPAA2_INLINE_MBUF_FROM_BUF(
-			DPAA2_GET_FD_ADDR(fd),
+		DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)),
 			bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size);
 
 	/* need to repopulated some of the fields,
@@ -151,10 +151,11 @@ eth_fd_to_mbuf(const struct qbman_fd *fd)
 	/* Parse the packet */
 	/* parse results are after the private - sw annotation area */
 	mbuf->packet_type = dpaa2_dev_rx_parse(
-			(uint64_t)(DPAA2_GET_FD_ADDR(fd))
+			(uint64_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd))
 			 + DPAA2_FD_PTA_SIZE);
 
-	dpaa2_dev_rx_offload((uint64_t)(DPAA2_GET_FD_ADDR(fd)) +
+	dpaa2_dev_rx_offload((uint64_t)DPAA2_IOVA_TO_VADDR(
+			     DPAA2_GET_FD_ADDR(fd)) +
 			     DPAA2_FD_PTA_SIZE, mbuf);
 
 	mbuf->next = NULL;
@@ -177,7 +178,7 @@ eth_mbuf_to_fd(struct rte_mbuf *mbuf,
 	/*Resetting the buffer pool id and offset field*/
 	fd->simple.bpid_offset = 0;
 
-	DPAA2_SET_FD_ADDR(fd, (mbuf->buf_addr));
+	DPAA2_SET_FD_ADDR(fd, DPAA2_MBUF_VADDR_TO_IOVA(mbuf));
 	DPAA2_SET_FD_LEN(fd, mbuf->data_len);
 	DPAA2_SET_FD_BPID(fd, bpid);
 	DPAA2_SET_FD_OFFSET(fd, mbuf->data_off);
@@ -218,7 +219,7 @@ eth_copy_mbuf_to_fd(struct rte_mbuf *mbuf,
 	/*Resetting the buffer pool id and offset field*/
 	fd->simple.bpid_offset = 0;
 
-	DPAA2_SET_FD_ADDR(fd, (m->buf_addr));
+	DPAA2_SET_FD_ADDR(fd, DPAA2_MBUF_VADDR_TO_IOVA(m));
 	DPAA2_SET_FD_LEN(fd, mbuf->data_len);
 	DPAA2_SET_FD_BPID(fd, bpid);
 	DPAA2_SET_FD_OFFSET(fd, mbuf->data_off);
@@ -270,7 +271,7 @@ dpaa2_dev_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	qbman_pull_desc_set_fq(&pulldesc, fqid);
 	/* todo optimization - we can have dq_storage_phys available*/
 	qbman_pull_desc_set_storage(&pulldesc, dq_storage,
-			(dma_addr_t)(dq_storage), 1);
+			(dma_addr_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1);
 
 	/*Issue a volatile dequeue command. */
 	while (1) {
@@ -311,7 +312,8 @@ dpaa2_dev_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 		}
 
 		fd = qbman_result_DQ_fd(dq_storage);
-		mbuf = (struct rte_mbuf *)(DPAA2_GET_FD_ADDR(fd)
+		mbuf = (struct rte_mbuf *)DPAA2_IOVA_TO_VADDR(
+			DPAA2_GET_FD_ADDR(fd)
 			 - bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size);
 		/* Prefeth mbuf */
 		rte_prefetch0(mbuf);
diff --git a/drivers/pool/dpaa2/dpaa2_hw_mempool.c b/drivers/pool/dpaa2/dpaa2_hw_mempool.c
index f36e909..3875d7c 100644
--- a/drivers/pool/dpaa2/dpaa2_hw_mempool.c
+++ b/drivers/pool/dpaa2/dpaa2_hw_mempool.c
@@ -203,9 +203,14 @@ void dpaa2_mbuf_release(struct rte_mempool *pool __rte_unused,
 	n = count % DPAA2_MBUF_MAX_ACQ_REL;
 
 	/* convert mbuf to buffers  for the remainder*/
-	for (i = 0; i < n ; i++)
+	for (i = 0; i < n ; i++) {
+#ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA
+		bufs[i] = (uint64_t)rte_mempool_virt2phy(pool, obj_table[i])
+				+ meta_data_size;
+#else
 		bufs[i] = (uint64_t)obj_table[i] + meta_data_size;
-
+#endif
+	}
 	/* feed them to bman*/
 	do {
 		ret = qbman_swp_release(swp, &releasedesc, bufs, n);
@@ -214,8 +219,15 @@ void dpaa2_mbuf_release(struct rte_mempool *pool __rte_unused,
 	/* if there are more buffers to free */
 	while (n < count) {
 		/* convert mbuf to buffers */
-		for (i = 0; i < DPAA2_MBUF_MAX_ACQ_REL; i++)
+		for (i = 0; i < DPAA2_MBUF_MAX_ACQ_REL; i++) {
+#ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA
+			bufs[i] = (uint64_t)
+				rte_mempool_virt2phy(pool, obj_table[n + i])
+					+ meta_data_size;
+#else
 			bufs[i] = (uint64_t)obj_table[n + i] + meta_data_size;
+#endif
+		}
 
 		do {
 			ret = qbman_swp_release(swp, &releasedesc, bufs,
@@ -288,6 +300,7 @@ int hw_mbuf_alloc_bulk(struct rte_mempool *pool,
 			 * i.e. first buffer is valid,
 			 * remaining 6 buffers may be null
 			 */
+			DPAA2_MODIFY_IOVA_TO_VADDR(bufs[i], uint64_t);
 			obj_table[n] = (struct rte_mbuf *)(bufs[i] - mbuf_size);
 			rte_mbuf_refcnt_set((struct rte_mbuf *)obj_table[n], 0);
 			PMD_TX_LOG(DEBUG, "Acquired %p address %p from BMAN",
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 30/33] net/dpaa2: add support for non hw buffer pool packet transmit
From: Shreyansh Jain @ 2016-12-29  5:16 UTC (permalink / raw)
  To: dev
  Cc: thomas.monjalon, bruce.richardson, john.mcnamara, ferruh.yigit,
	jerin.jacob, Hemant Agrawal
In-Reply-To: <1482988612-6638-1-git-send-email-shreyansh.jain@nxp.com>

From: Hemant Agrawal <hemant.agrawal@nxp.com>

Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
 drivers/net/dpaa2/dpaa2_rxtx.c | 74 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 72 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c
index 7d73bde..55068e5 100644
--- a/drivers/net/dpaa2/dpaa2_rxtx.c
+++ b/drivers/net/dpaa2/dpaa2_rxtx.c
@@ -191,6 +191,54 @@ eth_mbuf_to_fd(struct rte_mbuf *mbuf,
 		DPAA2_GET_FD_BPID(fd), DPAA2_GET_FD_LEN(fd));
 }
 
+
+static inline int __attribute__((hot))
+eth_copy_mbuf_to_fd(struct rte_mbuf *mbuf,
+		    struct qbman_fd *fd, uint16_t bpid)
+{
+	struct rte_mbuf *m;
+	void *mb = NULL;
+
+	if (hw_mbuf_alloc_bulk(bpid_info[bpid].bp_list->buf_pool.mp, &mb, 1)) {
+		PMD_TX_LOG(WARNING, "Unable to allocated DPAA2 buffer");
+		rte_pktmbuf_free(mbuf);
+		return -1;
+	}
+	m = (struct rte_mbuf *)mb;
+	memcpy((char *)m->buf_addr + mbuf->data_off,
+	       (void *)((char *)mbuf->buf_addr + mbuf->data_off),
+		mbuf->pkt_len);
+
+	/* Copy required fields */
+	m->data_off = mbuf->data_off;
+	m->ol_flags = mbuf->ol_flags;
+	m->packet_type = mbuf->packet_type;
+	m->tx_offload = mbuf->tx_offload;
+
+	/*Resetting the buffer pool id and offset field*/
+	fd->simple.bpid_offset = 0;
+
+	DPAA2_SET_FD_ADDR(fd, (m->buf_addr));
+	DPAA2_SET_FD_LEN(fd, mbuf->data_len);
+	DPAA2_SET_FD_BPID(fd, bpid);
+	DPAA2_SET_FD_OFFSET(fd, mbuf->data_off);
+	DPAA2_SET_FD_ASAL(fd, DPAA2_ASAL_VAL);
+
+	PMD_TX_LOG(DEBUG, " mbuf %p BMAN buf addr %p",
+		   (void *)mbuf, mbuf->buf_addr);
+
+	PMD_TX_LOG(DEBUG, " fdaddr =%lx bpid =%d meta =%d off =%d, len =%d",
+		   DPAA2_GET_FD_ADDR(fd),
+		DPAA2_GET_FD_BPID(fd),
+		bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size,
+		DPAA2_GET_FD_OFFSET(fd),
+		DPAA2_GET_FD_LEN(fd));
+	/*free the original packet */
+	rte_pktmbuf_free(mbuf);
+
+	return 0;
+}
+
 uint16_t
 dpaa2_dev_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 {
@@ -331,8 +379,29 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 			DPAA2_RESET_FD_CTRL((&fd_arr[loop]));
 			DPAA2_SET_FD_FLC((&fd_arr[loop]), NULL);
 			mp = (*bufs)->pool;
-			bpid = mempool_to_bpid(mp);
-			eth_mbuf_to_fd(*bufs, &fd_arr[loop], bpid);
+			/* Not a hw_pkt pool allocated frame */
+			if (mp && !(mp->flags & MEMPOOL_F_HW_PKT_POOL)) {
+				PMD_TX_LOG(ERR, "non hw offload bufffer ");
+				/* alloc should be from the default buffer pool
+				 * attached to this interface
+				 */
+				if (priv->bp_list) {
+					bpid = priv->bp_list->buf_pool.bpid;
+				} else {
+					PMD_TX_LOG(ERR, "errr: why no bpool"
+						   " attached");
+					num_tx = 0;
+					goto skip_tx;
+				}
+				if (eth_copy_mbuf_to_fd(*bufs,
+							&fd_arr[loop], bpid)) {
+					bufs++;
+					continue;
+				}
+			} else {
+				bpid = mempool_to_bpid(mp);
+				eth_mbuf_to_fd(*bufs, &fd_arr[loop], bpid);
+			}
 			bufs++;
 		}
 		loop = 0;
@@ -345,5 +414,6 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 		dpaa2_q->tx_pkts += frames_to_send;
 		nb_pkts -= frames_to_send;
 	}
+skip_tx:
 	return num_tx;
 }
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 29/33] net/dpaa2: enable stashing for LS2088A devices
From: Shreyansh Jain @ 2016-12-29  5:16 UTC (permalink / raw)
  To: dev
  Cc: thomas.monjalon, bruce.richardson, john.mcnamara, ferruh.yigit,
	jerin.jacob, Hemant Agrawal
In-Reply-To: <1482988612-6638-1-git-send-email-shreyansh.jain@nxp.com>

From: Hemant Agrawal <hemant.agrawal@nxp.com>

As the hardware determines which core will process which packet,
performance is boosted by direct cache warming/stashing as well
as by providing biasing for core-to-flow affinity, which ensures
that flow-specific data structures can remain in the core’s cache.

This patch enables the one cache line data stashing for packet
annotation data and packet context

Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
 drivers/net/dpaa2/dpaa2_ethdev.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index d0cdc80..d1456d5 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -278,6 +278,17 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev,
 	options = options | DPNI_QUEUE_OPT_USER_CTX;
 	cfg.user_context = (uint64_t)(dpaa2_q);
 
+	/*if ls2088 or rev2 device, enable the stashing */
+	if ((qbman_get_version() & 0xFFFF0000) > QMAN_REV_4000) {
+		options |= DPNI_QUEUE_OPT_FLC;
+		cfg.flc.stash_control = true;
+		cfg.flc.value &= 0xFFFFFFFFFFFFFFC0;
+		/* 00 00 00 - last 6 bit represent annotation, context stashing,
+		 * data stashing setting 01 01 00 (0x14) to enable
+		 * 1 line annotation, 1 line context
+		 */
+		cfg.flc.value |= 0x14;
+	}
 	ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX,
 			     dpaa2_q->tc_index, flow_id, options, &cfg);
 	if (ret) {
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 28/33] net/dpaa2: basic stats support
From: Shreyansh Jain @ 2016-12-29  5:16 UTC (permalink / raw)
  To: dev
  Cc: thomas.monjalon, bruce.richardson, john.mcnamara, ferruh.yigit,
	jerin.jacob, Hemant Agrawal
In-Reply-To: <1482988612-6638-1-git-send-email-shreyansh.jain@nxp.com>

From: Hemant Agrawal <hemant.agrawal@nxp.com>

Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
 doc/guides/nics/features/dpaa2.ini |  1 +
 drivers/net/dpaa2/dpaa2_ethdev.c   | 86 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+)

diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini
index 0660cab..d43f404 100644
--- a/doc/guides/nics/features/dpaa2.ini
+++ b/doc/guides/nics/features/dpaa2.ini
@@ -12,6 +12,7 @@ RSS hash             = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
 Packet type parsing  = Y
+Basic stats          = Y
 Linux VFIO           = Y
 ARMv8                = Y
 Usage doc            = Y
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 0d53003..d0cdc80 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -589,6 +589,90 @@ dpaa2_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 	return 0;
 }
 
+static
+void dpaa2_dev_stats_get(struct rte_eth_dev *dev,
+			 struct rte_eth_stats *stats)
+{
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+	struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
+	int32_t  retcode;
+	uint8_t page0 = 0, page1 = 1, page2 = 2;
+	union dpni_statistics value;
+
+	memset(&value, 0, sizeof(union dpni_statistics));
+
+	PMD_INIT_FUNC_TRACE();
+
+	if (!dpni) {
+		RTE_LOG(ERR, PMD, "dpni is NULL");
+		return;
+	}
+
+	if (!stats) {
+		RTE_LOG(ERR, PMD, "stats is NULL");
+		return;
+	}
+
+	/*Get Counters from page_0*/
+	retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token,
+				      page0, &value);
+	if (retcode)
+		goto err;
+
+	stats->ipackets = value.page_0.ingress_all_frames;
+	stats->ibytes = value.page_0.ingress_all_bytes;
+
+	/*Get Counters from page_1*/
+	retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token,
+				      page1, &value);
+	if (retcode)
+		goto err;
+
+	stats->opackets = value.page_1.egress_all_frames;
+	stats->obytes = value.page_1.egress_all_bytes;
+
+	/*Get Counters from page_2*/
+	retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token,
+				      page2, &value);
+	if (retcode)
+		goto err;
+
+	stats->ierrors = value.page_2.ingress_discarded_frames;
+	stats->oerrors = value.page_2.egress_discarded_frames;
+	stats->imissed = value.page_2.ingress_nobuffer_discards;
+
+	return;
+
+err:
+	RTE_LOG(ERR, PMD, "Operation not completed:Error Code = %d\n", retcode);
+	return;
+};
+
+static
+void dpaa2_dev_stats_reset(struct rte_eth_dev *dev)
+{
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+	struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
+	int32_t  retcode;
+
+	PMD_INIT_FUNC_TRACE();
+
+	if (dpni == NULL) {
+		RTE_LOG(ERR, PMD, "dpni is NULL");
+		return;
+	}
+
+	retcode =  dpni_reset_statistics(dpni, CMD_PRI_LOW, priv->token);
+	if (retcode)
+		goto error;
+
+	return;
+
+error:
+	RTE_LOG(ERR, PMD, "Operation not completed:Error Code = %d\n", retcode);
+	return;
+};
+
 /* return 0 means link status changed, -1 means not changed */
 static int
 dpaa2_dev_link_update(struct rte_eth_dev *dev,
@@ -646,6 +730,8 @@ static struct eth_dev_ops dpaa2_ethdev_ops = {
 	.promiscuous_enable   = dpaa2_dev_promiscuous_enable,
 	.promiscuous_disable  = dpaa2_dev_promiscuous_disable,
 	.link_update	   = dpaa2_dev_link_update,
+	.stats_get	       = dpaa2_dev_stats_get,
+	.stats_reset	   = dpaa2_dev_stats_reset,
 	.dev_infos_get	   = dpaa2_dev_info_get,
 	.dev_supported_ptypes_get = dpaa2_supported_ptypes_get,
 	.mtu_set           = dpaa2_dev_mtu_set,
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 27/33] net/dpaa2: link status update
From: Shreyansh Jain @ 2016-12-29  5:16 UTC (permalink / raw)
  To: dev
  Cc: thomas.monjalon, bruce.richardson, john.mcnamara, ferruh.yigit,
	jerin.jacob, Hemant Agrawal
In-Reply-To: <1482988612-6638-1-git-send-email-shreyansh.jain@nxp.com>

From: Hemant Agrawal <hemant.agrawal@nxp.com>

Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
 doc/guides/nics/features/dpaa2.ini |   1 +
 drivers/net/dpaa2/dpaa2_ethdev.c   | 107 +++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)

diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini
index 0746d4b..0660cab 100644
--- a/doc/guides/nics/features/dpaa2.ini
+++ b/doc/guides/nics/features/dpaa2.ini
@@ -4,6 +4,7 @@
 ; Refer to default.ini for the full list of available PMD features.
 ;
 [Features]
+Link status          = Y
 Queue start/stop     = Y
 MTU update           = Y
 Promiscuous mode     = Y
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index c705014..0d53003 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -55,6 +55,58 @@
 /* Name of the DPAA2 Net PMD */
 static const char *drivername = "DPAA2 PMD";
 
+/**
+ * Atomically reads the link status information from global
+ * structure rte_eth_dev.
+ *
+ * @param dev
+ *   - Pointer to the structure rte_eth_dev to read from.
+ *   - Pointer to the buffer to be saved with the link status.
+ *
+ * @return
+ *   - On success, zero.
+ *   - On failure, negative value.
+ */
+static inline int
+dpaa2_dev_atomic_read_link_status(struct rte_eth_dev *dev,
+				  struct rte_eth_link *link)
+{
+	struct rte_eth_link *dst = link;
+	struct rte_eth_link *src = &dev->data->dev_link;
+
+	if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
+				*(uint64_t *)src) == 0)
+		return -1;
+
+	return 0;
+}
+
+/**
+ * Atomically writes the link status information into global
+ * structure rte_eth_dev.
+ *
+ * @param dev
+ *   - Pointer to the structure rte_eth_dev to read from.
+ *   - Pointer to the buffer to be saved with the link status.
+ *
+ * @return
+ *   - On success, zero.
+ *   - On failure, negative value.
+ */
+static inline int
+dpaa2_dev_atomic_write_link_status(struct rte_eth_dev *dev,
+				   struct rte_eth_link *link)
+{
+	struct rte_eth_link *dst = &dev->data->dev_link;
+	struct rte_eth_link *src = link;
+
+	if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
+				*(uint64_t *)src) == 0)
+		return -1;
+
+	return 0;
+}
+
 static void
 dpaa2_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
@@ -431,6 +483,7 @@ dpaa2_dev_stop(struct rte_eth_dev *dev)
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
 	struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
 	int ret;
+	struct rte_eth_link link;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -440,6 +493,10 @@ dpaa2_dev_stop(struct rte_eth_dev *dev)
 			     ret, priv->hw_id);
 		return;
 	}
+
+	/* clear the recorded link status */
+	memset(&link, 0, sizeof(link));
+	dpaa2_dev_atomic_write_link_status(dev, &link);
 }
 
 static void
@@ -532,6 +589,55 @@ dpaa2_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 	return 0;
 }
 
+/* return 0 means link status changed, -1 means not changed */
+static int
+dpaa2_dev_link_update(struct rte_eth_dev *dev,
+			int wait_to_complete __rte_unused)
+{
+	int ret;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+	struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
+	struct rte_eth_link link, old;
+	struct dpni_link_state state = {0};
+
+	PMD_INIT_FUNC_TRACE();
+
+	if (dpni == NULL) {
+		RTE_LOG(ERR, PMD, "error : dpni is NULL");
+		return 0;
+	}
+	memset(&old, 0, sizeof(old));
+	dpaa2_dev_atomic_read_link_status(dev, &old);
+
+	ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token, &state);
+	if (ret < 0) {
+		RTE_LOG(ERR, PMD, "error: dpni_get_link_state %d", ret);
+		return -1;
+	}
+
+	if ((old.link_status == state.up) && (old.link_speed == state.rate)) {
+		RTE_LOG(DEBUG, PMD, "No change in status\n");
+		return -1;
+	}
+
+	memset(&link, 0, sizeof(struct rte_eth_link));
+	link.link_status = state.up;
+	link.link_speed = state.rate;
+
+	if (state.options & DPNI_LINK_OPT_HALF_DUPLEX)
+		link.link_duplex = ETH_LINK_HALF_DUPLEX;
+	else
+		link.link_duplex = ETH_LINK_FULL_DUPLEX;
+
+	dpaa2_dev_atomic_write_link_status(dev, &link);
+
+	if (link.link_status)
+		PMD_DRV_LOG(INFO, "Port %d Link is Up\n", dev->data->port_id);
+	else
+		PMD_DRV_LOG(INFO, "Port %d Link is Down\n", dev->data->port_id);
+	return 0;
+}
+
 static struct eth_dev_ops dpaa2_ethdev_ops = {
 	.dev_configure	  = dpaa2_eth_dev_configure,
 	.dev_start	      = dpaa2_dev_start,
@@ -539,6 +645,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = {
 	.dev_close	      = dpaa2_dev_close,
 	.promiscuous_enable   = dpaa2_dev_promiscuous_enable,
 	.promiscuous_disable  = dpaa2_dev_promiscuous_disable,
+	.link_update	   = dpaa2_dev_link_update,
 	.dev_infos_get	   = dpaa2_dev_info_get,
 	.dev_supported_ptypes_get = dpaa2_supported_ptypes_get,
 	.mtu_set           = dpaa2_dev_mtu_set,
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 26/33] net/dpaa2: rx packet parsing and packet type support
From: Shreyansh Jain @ 2016-12-29  5:16 UTC (permalink / raw)
  To: dev
  Cc: thomas.monjalon, bruce.richardson, john.mcnamara, ferruh.yigit,
	jerin.jacob, Hemant Agrawal
In-Reply-To: <1482988612-6638-1-git-send-email-shreyansh.jain@nxp.com>

From: Hemant Agrawal <hemant.agrawal@nxp.com>

Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
 doc/guides/nics/features/dpaa2.ini           |   1 +
 drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h | 257 +++++++++++++++++++++++++++
 drivers/net/dpaa2/dpaa2_ethdev.c             |  23 +++
 drivers/net/dpaa2/dpaa2_rxtx.c               |  91 +++++++++-
 4 files changed, 371 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h

diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini
index a6b7964..0746d4b 100644
--- a/doc/guides/nics/features/dpaa2.ini
+++ b/doc/guides/nics/features/dpaa2.ini
@@ -10,6 +10,7 @@ Promiscuous mode     = Y
 RSS hash             = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
+Packet type parsing  = Y
 Linux VFIO           = Y
 ARMv8                = Y
 Usage doc            = Y
diff --git a/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h b/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h
new file mode 100644
index 0000000..9324c6a
--- /dev/null
+++ b/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h
@@ -0,0 +1,257 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
+ *   Copyright (c) 2016 NXP. All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Freescale Semiconductor, Inc nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ *
+ * DPNI packet parse results - implementation internal
+ */
+
+#ifndef _DPAA2_HW_DPNI_ANNOT_H_
+#define _DPAA2_HW_DPNI_ANNOT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Annotation valid bits in FD FRC */
+#define DPAA2_FD_FRC_FASV	0x8000
+#define DPAA2_FD_FRC_FAEADV	0x4000
+#define DPAA2_FD_FRC_FAPRV	0x2000
+#define DPAA2_FD_FRC_FAIADV	0x1000
+#define DPAA2_FD_FRC_FASWOV	0x0800
+#define DPAA2_FD_FRC_FAICFDV	0x0400
+
+/* Annotation bits in FD CTRL */
+#define DPAA2_FD_CTRL_ASAL	0x00020000      /* ASAL = 128 */
+#define DPAA2_FD_CTRL_PTA	0x00800000
+#define DPAA2_FD_CTRL_PTV1	0x00400000
+
+/* Frame annotation status */
+struct dpaa2_fas {
+	uint8_t reserved;
+	uint8_t ppid;
+	__le16 ifpid;
+	__le32 status;
+} __packed;
+
+/**
+ * HW Packet Annotation  Register structures
+ */
+struct dpaa2_annot_hdr {
+	/**<	word1: Frame Annotation Status (8 bytes)*/
+	uint64_t word1;
+
+	/**<	word2: Time Stamp (8 bytes)*/
+	uint64_t word2;
+
+	/**<	word3: Next Hdr + FAF Extension + FAF (2 + 2 + 4 bytes)*/
+	uint64_t word3;
+
+	/**<	word4: Frame Annotation Flags-FAF (8 bytes) */
+	uint64_t word4;
+
+	/**<	word5:
+	 *	ShimOffset_1 + ShimOffset_2 + IPPIDOffset + EthOffset +
+	 *	LLC+SNAPOffset + VLANTCIOffset_1 + VLANTCIOffset_n +
+	 *	LastETypeOffset (1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 bytes)
+	 */
+	uint64_t word5;
+
+	/**<	word6:
+	 *	PPPoEOffset + MPLSOffset_1 + MPLSOffset_n + ARPorIPOffset_1
+	 *	+ IPOffset_norMInEncapO + GREOffset + L4Offset +
+	 *	GTPorESPorIPSecOffset(1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 bytes)
+	 */
+	uint64_t word6;
+
+	/**<	word7:
+	 *	RoutingHdrOfset1 + RoutingHdrOfset2 + NxtHdrOffset
+	 *	+ IPv6FragOffset + GrossRunningSum
+	 *	+ RunningSum(1 + 1 + 1 + 1 + 2 + 2 bytes)
+	 */
+	uint64_t word7;
+
+	/**<	word8:
+	 *	ParseErrorcode + Soft Parsing Context (1 + 7 bytes)
+	 */
+	uint64_t word8;
+};
+
+/**
+ * Internal Macros to get/set Packet annotation header
+ */
+
+/** General Macro to define a particular bit position*/
+#define BIT_POS(x)			((uint64_t)1 << ((x)))
+/** Set a bit in the variable */
+#define BIT_SET_AT_POS(var, pos)	((var) |= (pos))
+/** Reset the bit in the variable */
+#define BIT_RESET_AT_POS(var, pos)	((var) &= ~(pos))
+/** Check the bit is set in the variable */
+#define BIT_ISSET_AT_POS(var, pos)	(((var) & (pos)) ? 1 : 0)
+/**
+ * Macrso to define bit position in word3
+ */
+#define NEXT_HDR(var)			((uint64_t)(var) & 0xFFFF000000000000)
+#define FAF_EXTN_IPV6_ROUTE_HDR_PRESENT(var)	BIT_POS(16)
+#define FAF_EXTN_RESERVED(var)		((uint64_t)(var) & 0x00007FFF00000000)
+#define FAF_USER_DEFINED_RESERVED(var)	((uint64_t)(var) & 0x00000000FF000000)
+#define SHIM_SHELL_SOFT_PARSING_ERRROR		BIT_POS(23)
+#define PARSING_ERROR				BIT_POS(22)
+#define L2_ETH_MAC_PRESENT			BIT_POS(21)
+#define L2_ETH_MAC_UNICAST			BIT_POS(20)
+#define L2_ETH_MAC_MULTICAST			BIT_POS(19)
+#define L2_ETH_MAC_BROADCAST			BIT_POS(18)
+#define L2_ETH_FRAME_IS_BPDU			BIT_POS(17)
+#define L2_ETH_FCOE_PRESENT			BIT_POS(16)
+#define L2_ETH_FIP_PRESENT			BIT_POS(15)
+#define L2_ETH_PARSING_ERROR			BIT_POS(14)
+#define L2_LLC_SNAP_PRESENT			BIT_POS(13)
+#define L2_UNKNOWN_LLC_OUI			BIT_POS(12)
+#define L2_LLC_SNAP_ERROR			BIT_POS(11)
+#define L2_VLAN_1_PRESENT			BIT_POS(10)
+#define L2_VLAN_N_PRESENT			BIT_POS(9)
+#define L2_VLAN_CFI_BIT_PRESENT			BIT_POS(8)
+#define L2_VLAN_PARSING_ERROR			BIT_POS(7)
+#define L2_PPPOE_PPP_PRESENT			BIT_POS(6)
+#define L2_PPPOE_PPP_PARSING_ERROR		BIT_POS(5)
+#define L2_MPLS_1_PRESENT			BIT_POS(4)
+#define L2_MPLS_N_PRESENT			BIT_POS(3)
+#define L2_MPLS_PARSING_ERROR			BIT_POS(2)
+#define L2_ARP_PRESENT				BIT_POS(1)
+#define L2_ARP_PARSING_ERROR			BIT_POS(0)
+/**
+ * Macrso to define bit position in word4
+ */
+#define L2_UNKNOWN_PROTOCOL			BIT_POS(63)
+#define L2_SOFT_PARSING_ERROR			BIT_POS(62)
+#define L3_IPV4_1_PRESENT			BIT_POS(61)
+#define L3_IPV4_1_UNICAST			BIT_POS(60)
+#define L3_IPV4_1_MULTICAST			BIT_POS(59)
+#define L3_IPV4_1_BROADCAST			BIT_POS(58)
+#define L3_IPV4_N_PRESENT			BIT_POS(57)
+#define L3_IPV4_N_UNICAST			BIT_POS(56)
+#define L3_IPV4_N_MULTICAST			BIT_POS(55)
+#define L3_IPV4_N_BROADCAST			BIT_POS(54)
+#define L3_IPV6_1_PRESENT			BIT_POS(53)
+#define L3_IPV6_1_UNICAST			BIT_POS(52)
+#define L3_IPV6_1_MULTICAST			BIT_POS(51)
+#define L3_IPV6_N_PRESENT			BIT_POS(50)
+#define L3_IPV6_N_UNICAST			BIT_POS(49)
+#define L3_IPV6_N_MULTICAST			BIT_POS(48)
+#define L3_IP_1_OPT_PRESENT			BIT_POS(47)
+#define L3_IP_1_UNKNOWN_PROTOCOL		BIT_POS(46)
+#define L3_IP_1_MORE_FRAGMENT			BIT_POS(45)
+#define L3_IP_1_FIRST_FRAGMENT			BIT_POS(44)
+#define L3_IP_1_PARSING_ERROR			BIT_POS(43)
+#define L3_IP_N_OPT_PRESENT			BIT_POS(42)
+#define L3_IP_N_UNKNOWN_PROTOCOL		BIT_POS(41)
+#define L3_IP_N_MORE_FRAGMENT			BIT_POS(40)
+#define L3_IP_N_FIRST_FRAGMENT			BIT_POS(39)
+#define L3_PROTO_ICMP_PRESENT			BIT_POS(38)
+#define L3_PROTO_IGMP_PRESENT			BIT_POS(37)
+#define L3_PROTO_ICMPV6_PRESENT			BIT_POS(36)
+#define L3_PROTO_UDP_LIGHT_PRESENT		BIT_POS(35)
+#define L3_IP_N_PARSING_ERROR			BIT_POS(34)
+#define L3_MIN_ENCAP_PRESENT			BIT_POS(33)
+#define L3_MIN_ENCAP_SBIT_PRESENT		BIT_POS(32)
+#define L3_MIN_ENCAP_PARSING_ERROR		BIT_POS(31)
+#define L3_PROTO_GRE_PRESENT			BIT_POS(30)
+#define L3_PROTO_GRE_RBIT_PRESENT		BIT_POS(29)
+#define L3_PROTO_GRE_PARSING_ERROR		BIT_POS(28)
+#define L3_IP_UNKNOWN_PROTOCOL			BIT_POS(27)
+#define L3_SOFT_PARSING_ERROR			BIT_POS(26)
+#define L3_PROTO_UDP_PRESENT			BIT_POS(25)
+#define L3_PROTO_UDP_PARSING_ERROR		BIT_POS(24)
+#define L3_PROTO_TCP_PRESENT			BIT_POS(23)
+#define L3_PROTO_TCP_OPT_PRESENT		BIT_POS(22)
+#define L3_PROTO_TCP_CTRL_BIT_6_TO_11_PRESENT	BIT_POS(21)
+#define L3_PROTO_TCP_CTRL_BIT_3_TO_5_PRESENT	BIT_POS(20)
+#define L3_PROTO_TCP_PARSING_ERROR		BIT_POS(19)
+#define L3_PROTO_IPSEC_PRESENT			BIT_POS(18)
+#define L3_PROTO_IPSEC_ESP_PRESENT		BIT_POS(17)
+#define L3_PROTO_IPSEC_AH_PRESENT		BIT_POS(16)
+#define L3_PROTO_IPSEC_PARSING_ERROR		BIT_POS(15)
+#define L3_PROTO_SCTP_PRESENT			BIT_POS(14)
+#define L3_PROTO_SCTP_PARSING_ERROR		BIT_POS(13)
+#define L3_PROTO_DCCP_PRESENT			BIT_POS(12)
+#define L3_PROTO_DCCP_PARSING_ERROR		BIT_POS(11)
+#define L4_UNKNOWN_PROTOCOL			BIT_POS(10)
+#define L4_SOFT_PARSING_ERROR			BIT_POS(9)
+#define L3_PROTO_GTP_PRESENT			BIT_POS(8)
+#define L3_PROTO_GTP_PARSING_ERROR		BIT_POS(7)
+#define L3_PROTO_ESP_PRESENT			BIT_POS(6)
+#define L3_PROTO_ESP_PARSING_ERROR		BIT_POS(5)
+#define L3_PROTO_ISCSI_PRESENT			BIT_POS(4)
+#define L3_PROTO_CAPWAN__CTRL_PRESENT		BIT_POS(3)
+#define L3_PROTO_CAPWAN__DATA_PRESENT		BIT_POS(2)
+#define L5_SOFT_PARSING_ERROR			BIT_POS(1)
+#define L3_IPV6_ROUTE_HDR_PRESENT		BIT_POS(0)
+
+/* Debug frame, otherwise supposed to be discarded */
+#define DPAA2_ETH_FAS_DISC	      0x80000000
+/* MACSEC frame */
+#define DPAA2_ETH_FAS_MS		0x40000000
+#define DPAA2_ETH_FAS_PTP	       0x08000000
+/* Ethernet multicast frame */
+#define DPAA2_ETH_FAS_MC		0x04000000
+/* Ethernet broadcast frame */
+#define DPAA2_ETH_FAS_BC		0x02000000
+#define DPAA2_ETH_FAS_KSE	       0x00040000
+#define DPAA2_ETH_FAS_EOFHE	     0x00020000
+#define DPAA2_ETH_FAS_MNLE	      0x00010000
+#define DPAA2_ETH_FAS_TIDE	      0x00008000
+#define DPAA2_ETH_FAS_PIEE	      0x00004000
+/* Frame length error */
+#define DPAA2_ETH_FAS_FLE	       0x00002000
+/* Frame physical error; our favourite pastime */
+#define DPAA2_ETH_FAS_FPE	       0x00001000
+#define DPAA2_ETH_FAS_PTE	       0x00000080
+#define DPAA2_ETH_FAS_ISP	       0x00000040
+#define DPAA2_ETH_FAS_PHE	       0x00000020
+#define DPAA2_ETH_FAS_BLE	       0x00000010
+/* L3 csum validation performed */
+#define DPAA2_ETH_FAS_L3CV	      0x00000008
+/* L3 csum error */
+#define DPAA2_ETH_FAS_L3CE	      0x00000004
+/* L4 csum validation performed */
+#define DPAA2_ETH_FAS_L4CV	      0x00000002
+/* L4 csum error */
+#define DPAA2_ETH_FAS_L4CE	      0x00000001
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 3c4ca28..c705014 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -311,6 +311,28 @@ dpaa2_dev_tx_queue_release(void *q __rte_unused)
 	PMD_INIT_FUNC_TRACE();
 }
 
+static const uint32_t *
+dpaa2_supported_ptypes_get(struct rte_eth_dev *dev)
+{
+	static const uint32_t ptypes[] = {
+		/*todo -= add more types */
+		RTE_PTYPE_L2_ETHER,
+		RTE_PTYPE_L3_IPV4,
+		RTE_PTYPE_L3_IPV4_EXT,
+		RTE_PTYPE_L3_IPV6,
+		RTE_PTYPE_L3_IPV6_EXT,
+		RTE_PTYPE_L4_TCP,
+		RTE_PTYPE_L4_UDP,
+		RTE_PTYPE_L4_SCTP,
+		RTE_PTYPE_L4_ICMP,
+		RTE_PTYPE_UNKNOWN
+	};
+
+	if (dev->rx_pkt_burst == dpaa2_dev_rx)
+		return ptypes;
+	return NULL;
+}
+
 static int
 dpaa2_dev_start(struct rte_eth_dev *dev)
 {
@@ -518,6 +540,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = {
 	.promiscuous_enable   = dpaa2_dev_promiscuous_enable,
 	.promiscuous_disable  = dpaa2_dev_promiscuous_disable,
 	.dev_infos_get	   = dpaa2_dev_info_get,
+	.dev_supported_ptypes_get = dpaa2_supported_ptypes_get,
 	.mtu_set           = dpaa2_dev_mtu_set,
 	.rx_queue_setup    = dpaa2_dev_rx_queue_setup,
 	.rx_queue_release  = dpaa2_dev_rx_queue_release,
diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c
index 4b76be5..7d73bde 100644
--- a/drivers/net/dpaa2/dpaa2_rxtx.c
+++ b/drivers/net/dpaa2/dpaa2_rxtx.c
@@ -49,6 +49,88 @@
 #include <dpaa2_hw_mempool.h>
 
 #include "dpaa2_ethdev.h"
+#include "base/dpaa2_hw_dpni_annot.h"
+
+static inline uint32_t __attribute__((hot))
+dpaa2_dev_rx_parse(uint64_t hw_annot_addr)
+{
+	uint32_t pkt_type = RTE_PTYPE_UNKNOWN;
+	struct dpaa2_annot_hdr *annotation =
+			(struct dpaa2_annot_hdr *)hw_annot_addr;
+
+	PMD_RX_LOG(DEBUG, "annotation = 0x%lx   ", annotation->word4);
+
+	if (BIT_ISSET_AT_POS(annotation->word3, L2_ARP_PRESENT)) {
+		pkt_type = RTE_PTYPE_L2_ETHER_ARP;
+		goto parse_done;
+	} else if (BIT_ISSET_AT_POS(annotation->word3, L2_ETH_MAC_PRESENT)) {
+		pkt_type = RTE_PTYPE_L2_ETHER;
+	} else {
+		goto parse_done;
+	}
+
+	if (BIT_ISSET_AT_POS(annotation->word4, L3_IPV4_1_PRESENT |
+			     L3_IPV4_N_PRESENT)) {
+		pkt_type |= RTE_PTYPE_L3_IPV4;
+		if (BIT_ISSET_AT_POS(annotation->word4, L3_IP_1_OPT_PRESENT |
+			L3_IP_N_OPT_PRESENT))
+			pkt_type |= RTE_PTYPE_L3_IPV4_EXT;
+
+	} else if (BIT_ISSET_AT_POS(annotation->word4, L3_IPV6_1_PRESENT |
+		  L3_IPV6_N_PRESENT)) {
+		pkt_type |= RTE_PTYPE_L3_IPV6;
+		if (BIT_ISSET_AT_POS(annotation->word4, L3_IP_1_OPT_PRESENT |
+		    L3_IP_N_OPT_PRESENT))
+			pkt_type |= RTE_PTYPE_L3_IPV6_EXT;
+	} else {
+		goto parse_done;
+	}
+
+	if (BIT_ISSET_AT_POS(annotation->word4, L3_IP_1_FIRST_FRAGMENT |
+	    L3_IP_1_MORE_FRAGMENT |
+	    L3_IP_N_FIRST_FRAGMENT |
+	    L3_IP_N_MORE_FRAGMENT)) {
+		pkt_type |= RTE_PTYPE_L4_FRAG;
+		goto parse_done;
+	} else {
+		pkt_type |= RTE_PTYPE_L4_NONFRAG;
+	}
+
+	if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_UDP_PRESENT))
+		pkt_type |= RTE_PTYPE_L4_UDP;
+
+	else if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_TCP_PRESENT))
+		pkt_type |= RTE_PTYPE_L4_TCP;
+
+	else if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_SCTP_PRESENT))
+		pkt_type |= RTE_PTYPE_L4_SCTP;
+
+	else if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_ICMP_PRESENT))
+		pkt_type |= RTE_PTYPE_L4_ICMP;
+
+	else if (BIT_ISSET_AT_POS(annotation->word4, L3_IP_UNKNOWN_PROTOCOL))
+		pkt_type |= RTE_PTYPE_UNKNOWN;
+
+parse_done:
+	return pkt_type;
+}
+
+static inline void __attribute__((hot))
+dpaa2_dev_rx_offload(uint64_t hw_annot_addr, struct rte_mbuf *mbuf)
+{
+	struct dpaa2_annot_hdr *annotation =
+		(struct dpaa2_annot_hdr *)hw_annot_addr;
+
+	if (BIT_ISSET_AT_POS(annotation->word3,
+			     L2_VLAN_1_PRESENT | L2_VLAN_N_PRESENT))
+		mbuf->ol_flags |= PKT_RX_VLAN_PKT;
+
+	if (BIT_ISSET_AT_POS(annotation->word8, DPAA2_ETH_FAS_L3CE))
+		mbuf->ol_flags |= PKT_RX_IP_CKSUM_BAD;
+
+	if (BIT_ISSET_AT_POS(annotation->word8, DPAA2_ETH_FAS_L4CE))
+		mbuf->ol_flags |= PKT_RX_L4_CKSUM_BAD;
+}
 
 static inline struct rte_mbuf *__attribute__((hot))
 eth_fd_to_mbuf(const struct qbman_fd *fd)
@@ -66,7 +148,14 @@ eth_fd_to_mbuf(const struct qbman_fd *fd)
 	mbuf->data_len = DPAA2_GET_FD_LEN(fd);
 	mbuf->pkt_len = mbuf->data_len;
 
-	mbuf->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4;
+	/* Parse the packet */
+	/* parse results are after the private - sw annotation area */
+	mbuf->packet_type = dpaa2_dev_rx_parse(
+			(uint64_t)(DPAA2_GET_FD_ADDR(fd))
+			 + DPAA2_FD_PTA_SIZE);
+
+	dpaa2_dev_rx_offload((uint64_t)(DPAA2_GET_FD_ADDR(fd)) +
+			     DPAA2_FD_PTA_SIZE, mbuf);
 
 	mbuf->next = NULL;
 	rte_mbuf_refcnt_set(mbuf, 1);
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 25/33] net/dpaa2: add packet rx and tx support
From: Shreyansh Jain @ 2016-12-29  5:16 UTC (permalink / raw)
  To: dev
  Cc: thomas.monjalon, bruce.richardson, john.mcnamara, ferruh.yigit,
	jerin.jacob, Hemant Agrawal
In-Reply-To: <1482988612-6638-1-git-send-email-shreyansh.jain@nxp.com>

From: Hemant Agrawal <hemant.agrawal@nxp.com>

Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
 drivers/bus/fslmc/portal/dpaa2_hw_pvt.h |  54 +++++++
 drivers/net/dpaa2/Makefile              |   1 +
 drivers/net/dpaa2/dpaa2_ethdev.c        |   4 +
 drivers/net/dpaa2/dpaa2_ethdev.h        |   3 +
 drivers/net/dpaa2/dpaa2_rxtx.c          | 260 ++++++++++++++++++++++++++++++++
 5 files changed, 322 insertions(+)
 create mode 100644 drivers/net/dpaa2/dpaa2_rxtx.c

diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h
index 7c6cc7e..158dfef 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h
@@ -43,10 +43,16 @@
 #ifndef true
 #define true       1
 #endif
+#define lower_32_bits(x) ((uint32_t)(x))
+#define upper_32_bits(x) ((uint32_t)(((x) >> 16) >> 16))
 
 #ifndef ETH_VLAN_HLEN
 #define ETH_VLAN_HLEN   4 /** < Vlan Header Length */
 #endif
+
+#define MAX_TX_RING_SLOTS	8
+	/** <Maximum number of slots available in TX ring*/
+
 #define DPAA2_DQRR_RING_SIZE	16
 	/** <Maximum number of slots available in RX ring*/
 
@@ -121,6 +127,54 @@ struct dpaa2_queue {
 
 /*! Global MCP list */
 extern void *(*mcp_ptr_list);
+
+/* Refer to Table 7-3 in SEC BG */
+struct qbman_fle {
+	uint32_t addr_lo;
+	uint32_t addr_hi;
+	uint32_t length;
+	/* FMT must be 00, MSB is final bit  */
+	uint32_t fin_bpid_offset;
+	uint32_t frc;
+	uint32_t reserved[3]; /* Not used currently */
+};
+
+/*Macros to define operations on FD*/
+#define DPAA2_SET_FD_ADDR(fd, addr) do {			\
+	fd->simple.addr_lo = lower_32_bits((uint64_t)(addr));	\
+	fd->simple.addr_hi = upper_32_bits((uint64_t)(addr));	\
+} while (0)
+#define DPAA2_SET_FD_LEN(fd, length)	(fd)->simple.len = length
+#define DPAA2_SET_FD_BPID(fd, bpid)	((fd)->simple.bpid_offset |= bpid)
+#define DPAA2_SET_FD_OFFSET(fd, offset)	\
+	((fd->simple.bpid_offset |= (uint32_t)(offset) << 16))
+#define DPAA2_RESET_FD_CTRL(fd)	(fd)->simple.ctrl = 0
+
+#define	DPAA2_SET_FD_ASAL(fd, asal)	((fd)->simple.ctrl |= (asal << 16))
+#define DPAA2_SET_FD_FLC(fd, addr)	do { \
+	fd->simple.flc_lo = lower_32_bits((uint64_t)(addr));	\
+	fd->simple.flc_hi = upper_32_bits((uint64_t)(addr));	\
+} while (0)
+#define DPAA2_GET_FD_ADDR(fd)	\
+((uint64_t)((((uint64_t)((fd)->simple.addr_hi)) << 32) + (fd)->simple.addr_lo))
+
+#define DPAA2_GET_FD_LEN(fd)	((fd)->simple.len)
+#define DPAA2_GET_FD_BPID(fd)	(((fd)->simple.bpid_offset & 0x00003FFF))
+#define DPAA2_GET_FD_OFFSET(fd)	(((fd)->simple.bpid_offset & 0x0FFF0000) >> 16)
+#define DPAA2_INLINE_MBUF_FROM_BUF(buf, meta_data_size) \
+	((struct rte_mbuf *)((uint64_t)(buf) - (meta_data_size)))
+
+#define DPAA2_ASAL_VAL (DPAA2_MBUF_HW_ANNOTATION / 64)
+
+/* Only Enqueue Error responses will be
+ * pushed on FQID_ERR of Enqueue FQ
+ */
+#define DPAA2_EQ_RESP_ERR_FQ		0
+/* All Enqueue responses will be pushed on address
+ * set with qbman_eq_desc_set_response
+ */
+#define DPAA2_EQ_RESP_ALWAYS		1
+
 struct dpaa2_dpbp_dev *dpaa2_alloc_dpbp_dev(void);
 void dpaa2_free_dpbp_dev(struct dpaa2_dpbp_dev *dpbp);
 
diff --git a/drivers/net/dpaa2/Makefile b/drivers/net/dpaa2/Makefile
index ca51402..5e669df 100644
--- a/drivers/net/dpaa2/Makefile
+++ b/drivers/net/dpaa2/Makefile
@@ -59,6 +59,7 @@ EXPORT_MAP := rte_pmd_dpaa2_version.map
 LIBABIVER := 1
 
 SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += base/dpaa2_hw_dpni.c
+SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += dpaa2_rxtx.c
 SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += dpaa2_ethdev.c
 
 # library dependencies
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 3264bbe..3c4ca28 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -682,6 +682,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev)
 	eth_dev->dev_ops = &dpaa2_ethdev_ops;
 	eth_dev->data->drv_name = drivername;
 
+	eth_dev->rx_pkt_burst = dpaa2_dev_rx;
+	eth_dev->tx_pkt_burst = dpaa2_dev_tx;
 	return 0;
 }
 
@@ -735,6 +737,8 @@ dpaa2_dev_uninit(struct rte_eth_dev *eth_dev)
 	free(dpni);
 
 	eth_dev->dev_ops = NULL;
+	eth_dev->rx_pkt_burst = NULL;
+	eth_dev->tx_pkt_burst = NULL;
 
 	return 0;
 }
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h
index a56b525..7196398 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.h
+++ b/drivers/net/dpaa2/dpaa2_ethdev.h
@@ -77,4 +77,7 @@ int dpaa2_remove_flow_dist(struct rte_eth_dev *eth_dev,
 
 int dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv, void *blist);
 
+uint16_t dpaa2_dev_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts);
+uint16_t dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts);
+
 #endif /* _DPAA2_ETHDEV_H */
diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c
new file mode 100644
index 0000000..4b76be5
--- /dev/null
+++ b/drivers/net/dpaa2/dpaa2_rxtx.c
@@ -0,0 +1,260 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
+ *   Copyright (c) 2016 NXP. All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Freescale Semiconductor, Inc nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <time.h>
+#include <net/if.h>
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_string_fns.h>
+#include <rte_dev.h>
+#include <rte_ethdev.h>
+
+#include <fslmc_logs.h>
+#include <fslmc_vfio.h>
+#include <dpaa2_hw_pvt.h>
+#include <dpaa2_hw_dpio.h>
+#include <dpaa2_hw_mempool.h>
+
+#include "dpaa2_ethdev.h"
+
+static inline struct rte_mbuf *__attribute__((hot))
+eth_fd_to_mbuf(const struct qbman_fd *fd)
+{
+	struct rte_mbuf *mbuf = DPAA2_INLINE_MBUF_FROM_BUF(
+			DPAA2_GET_FD_ADDR(fd),
+			bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size);
+
+	/* need to repopulated some of the fields,
+	 * as they may have changed in last transmission
+	 */
+	mbuf->nb_segs = 1;
+	mbuf->ol_flags = 0;
+	mbuf->data_off = DPAA2_GET_FD_OFFSET(fd);
+	mbuf->data_len = DPAA2_GET_FD_LEN(fd);
+	mbuf->pkt_len = mbuf->data_len;
+
+	mbuf->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4;
+
+	mbuf->next = NULL;
+	rte_mbuf_refcnt_set(mbuf, 1);
+
+	PMD_RX_LOG(DEBUG, "to mbuf - mbuf =%p, mbuf->buf_addr =%p, off = %d,"
+		"fd_off=%d fd =%lx, meta = %d  bpid =%d, len=%d\n",
+		mbuf, mbuf->buf_addr, mbuf->data_off,
+		DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ADDR(fd),
+		bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size,
+		DPAA2_GET_FD_BPID(fd), DPAA2_GET_FD_LEN(fd));
+
+	return mbuf;
+}
+
+static void __attribute__ ((noinline)) __attribute__((hot))
+eth_mbuf_to_fd(struct rte_mbuf *mbuf,
+	       struct qbman_fd *fd, uint16_t bpid)
+{
+	/*Resetting the buffer pool id and offset field*/
+	fd->simple.bpid_offset = 0;
+
+	DPAA2_SET_FD_ADDR(fd, (mbuf->buf_addr));
+	DPAA2_SET_FD_LEN(fd, mbuf->data_len);
+	DPAA2_SET_FD_BPID(fd, bpid);
+	DPAA2_SET_FD_OFFSET(fd, mbuf->data_off);
+	DPAA2_SET_FD_ASAL(fd, DPAA2_ASAL_VAL);
+
+	PMD_TX_LOG(DEBUG, "mbuf =%p, mbuf->buf_addr =%p, off = %d,"
+		"fd_off=%d fd =%lx, meta = %d  bpid =%d, len=%d\n",
+		mbuf, mbuf->buf_addr, mbuf->data_off,
+		DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ADDR(fd),
+		bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size,
+		DPAA2_GET_FD_BPID(fd), DPAA2_GET_FD_LEN(fd));
+}
+
+uint16_t
+dpaa2_dev_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+{
+	/* Function is responsible to receive frames for a given device and VQ*/
+	struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue;
+	struct qbman_result *dq_storage;
+	uint32_t fqid = dpaa2_q->fqid;
+	int ret, num_rx = 0;
+	uint8_t is_last = 0, status;
+	struct qbman_swp *swp;
+	const struct qbman_fd *fd;
+	struct qbman_pull_desc pulldesc;
+	struct rte_eth_dev *dev = dpaa2_q->dev;
+
+	if (unlikely(!DPAA2_PER_LCORE_DPIO)) {
+		ret = dpaa2_affine_qbman_swp();
+		if (ret) {
+			RTE_LOG(ERR, PMD, "Failure in affining portal\n");
+			return 0;
+		}
+	}
+	swp = DPAA2_PER_LCORE_PORTAL;
+	dq_storage = dpaa2_q->q_storage->dq_storage[0];
+
+	qbman_pull_desc_clear(&pulldesc);
+	qbman_pull_desc_set_numframes(&pulldesc,
+				      (nb_pkts > DPAA2_DQRR_RING_SIZE) ?
+				       DPAA2_DQRR_RING_SIZE : nb_pkts);
+	qbman_pull_desc_set_fq(&pulldesc, fqid);
+	/* todo optimization - we can have dq_storage_phys available*/
+	qbman_pull_desc_set_storage(&pulldesc, dq_storage,
+			(dma_addr_t)(dq_storage), 1);
+
+	/*Issue a volatile dequeue command. */
+	while (1) {
+		if (qbman_swp_pull(swp, &pulldesc)) {
+			PMD_RX_LOG(ERR, "VDQ command is not issued."
+				   "QBMAN is busy\n");
+			/* Portal was busy, try again */
+			continue;
+		}
+		break;
+	};
+
+	/* Receive the packets till Last Dequeue entry is found with
+	 * respect to the above issues PULL command.
+	 */
+	while (!is_last) {
+		struct rte_mbuf *mbuf;
+		/*Check if the previous issued command is completed.
+		 * Also seems like the SWP is shared between the
+		 * Ethernet Driver and the SEC driver.
+		 */
+		while (!qbman_check_command_complete(swp, dq_storage))
+			;
+		/* Loop until the dq_storage is updated with
+		 * new token by QBMAN
+		 */
+		while (!qbman_result_has_new_result(swp, dq_storage))
+			;
+		/* Check whether Last Pull command is Expired and
+		 * setting Condition for Loop termination
+		 */
+		if (qbman_result_DQ_is_pull_complete(dq_storage)) {
+			is_last = 1;
+			/* Check for valid frame. */
+			status = (uint8_t)qbman_result_DQ_flags(dq_storage);
+			if (unlikely((status & QBMAN_DQ_STAT_VALIDFRAME) == 0))
+				continue;
+		}
+
+		fd = qbman_result_DQ_fd(dq_storage);
+		mbuf = (struct rte_mbuf *)(DPAA2_GET_FD_ADDR(fd)
+			 - bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size);
+		/* Prefeth mbuf */
+		rte_prefetch0(mbuf);
+		/* Prefetch Annotation address for the parse results */
+		rte_prefetch0((void *)((uint64_t)DPAA2_GET_FD_ADDR(fd)
+						+ DPAA2_FD_PTA_SIZE + 16));
+
+		bufs[num_rx] = eth_fd_to_mbuf(fd);
+		bufs[num_rx]->port = dev->data->port_id;
+
+		num_rx++;
+		dq_storage++;
+	} /* End of Packet Rx loop */
+
+	dpaa2_q->rx_pkts += num_rx;
+
+	/*Return the total number of packets received to DPAA2 app*/
+	return num_rx;
+}
+
+/*
+ * Callback to handle sending packets through WRIOP based interface
+ */
+uint16_t
+dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+{
+	/* Function to transmit the frames to given device and VQ*/
+	uint32_t loop;
+	int32_t ret;
+	struct qbman_fd fd_arr[MAX_TX_RING_SLOTS];
+	uint32_t frames_to_send;
+	struct rte_mempool *mp;
+	struct qbman_eq_desc eqdesc;
+	struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue;
+	struct qbman_swp *swp;
+	uint16_t num_tx = 0;
+	uint16_t bpid;
+	struct rte_eth_dev *dev = dpaa2_q->dev;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+
+	if (unlikely(!DPAA2_PER_LCORE_DPIO)) {
+		ret = dpaa2_affine_qbman_swp();
+		if (ret) {
+			RTE_LOG(ERR, PMD, "Failure in affining portal\n");
+			return 0;
+		}
+	}
+	swp = DPAA2_PER_LCORE_PORTAL;
+
+	PMD_TX_LOG(DEBUG, "===> dev =%p, fqid =%d", dev, dpaa2_q->fqid);
+
+	/*Prepare enqueue descriptor*/
+	qbman_eq_desc_clear(&eqdesc);
+	qbman_eq_desc_set_no_orp(&eqdesc, DPAA2_EQ_RESP_ERR_FQ);
+	qbman_eq_desc_set_response(&eqdesc, 0, 0);
+	qbman_eq_desc_set_qd(&eqdesc, priv->qdid,
+			     dpaa2_q->flow_id, dpaa2_q->tc_index);
+
+	/*Clear the unused FD fields before sending*/
+	while (nb_pkts) {
+		frames_to_send = (nb_pkts >> 3) ? MAX_TX_RING_SLOTS : nb_pkts;
+
+		for (loop = 0; loop < frames_to_send; loop++) {
+			fd_arr[loop].simple.frc = 0;
+			DPAA2_RESET_FD_CTRL((&fd_arr[loop]));
+			DPAA2_SET_FD_FLC((&fd_arr[loop]), NULL);
+			mp = (*bufs)->pool;
+			bpid = mempool_to_bpid(mp);
+			eth_mbuf_to_fd(*bufs, &fd_arr[loop], bpid);
+			bufs++;
+		}
+		loop = 0;
+		while (loop < frames_to_send) {
+			loop += qbman_swp_send_multiple(swp, &eqdesc,
+					&fd_arr[loop], frames_to_send - loop);
+		}
+
+		num_tx += frames_to_send;
+		dpaa2_q->tx_pkts += frames_to_send;
+		nb_pkts -= frames_to_send;
+	}
+	return num_tx;
+}
-- 
2.7.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox