DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 01/56] net/sfc: libefx-based PMD stub sufficient to build and init
From: Ferruh Yigit @ 2016-11-25 10:17 UTC (permalink / raw)
  To: Andrew Rybchenko, dev
In-Reply-To: <f300afdb-5120-ad2a-0e4a-f182d0361499@solarflare.com>

On 11/24/2016 3:59 PM, Andrew Rybchenko wrote:
> On 11/23/2016 06:26 PM, Ferruh Yigit wrote:
>> On 11/21/2016 3:00 PM, Andrew Rybchenko wrote:
>>> The PMD is put into the sfc/efx subdirectory to have a place for
>>> the second PMD and library shared by both.
>>>
>>> Enable the PMD by default on supported configuratons.
>>>
>>> Reviewed-by: Andy Moreton <amoreton@solarflare.com>
>>> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
>>> ---
>>>   MAINTAINERS                                     |   6 ++
>>>   config/common_base                              |   6 ++
>>>   config/defconfig_arm-armv7a-linuxapp-gcc        |   1 +
>>>   config/defconfig_arm64-armv8a-linuxapp-gcc      |   1 +
>>>   config/defconfig_i686-native-linuxapp-gcc       |   5 +
>>>   config/defconfig_i686-native-linuxapp-icc       |   5 +
>>>   config/defconfig_ppc_64-power8-linuxapp-gcc     |   1 +
>>>   config/defconfig_tile-tilegx-linuxapp-gcc       |   1 +
>>>   config/defconfig_x86_64-native-linuxapp-icc     |   5 +
>>>   config/defconfig_x86_x32-native-linuxapp-gcc    |   5 +
>>>   doc/guides/nics/features/sfc_efx.ini            |  10 ++
>>>   doc/guides/nics/index.rst                       |   1 +
>>>   doc/guides/nics/sfc_efx.rst                     | 109 +++++++++++++++++++++
>> Can you also update release notes please, to announce new driver.
> 
> Thanks, will do in v2.
> 
>> <...>
>>
>>> diff --git a/drivers/net/sfc/efx/Makefile b/drivers/net/sfc/efx/Makefile
>>> new file mode 100644
>>> index 0000000..71f07ca
>>> --- /dev/null
>>> +++ b/drivers/net/sfc/efx/Makefile
>>> @@ -0,0 +1,81 @@
>> <...>
>>> +
>>> +include $(RTE_SDK)/mk/rte.vars.mk
>>> +
>>> +#
>>> +# library name
>>> +#
>>> +LIB = librte_pmd_sfc_efx.a
>>> +
>>> +CFLAGS += -O3
>>> +
>>> +# Enable basic warnings but disable some which are accepted
>>> +CFLAGS += -Wall
>> It is possible to use $(WERROR_FLAGS), which set automatically based on
>> selected compiler. See mk/toolchain/* .
> 
> Thanks, will do in v2.
> 
>> And you can add extra options here, please keep in mind that there are
>> three compiler supported right now: gcc, clang and icc. You may require
>> to add compiler and version checks..
> 
> I've tried to disable the driver build on ICC since we've never tested it.

I believe we don't support selective config per compiler. Currently if a
code is enabled by default, it should support compilation with all three
compilers.

> I've failed to find list of compiler versions which must/should be checked.

That list is not clear as far as I know. Mostly version related fixes
added based on reported build errors. So you can leave as it is right
now, or can test with default compiler versions of some common
distributions.

> I've tested versions which come with RHEL 7.2, Debian Jessie and Sid.
> (In v1 I've lost my fixes for clang which produce warnings because of
> unsupported -W option)
> 
>>> +CFLAGS += -Wno-strict-aliasing
>>> +
>>> +# Enable extra warnings but disable some which are accepted
>>> +CFLAGS += -Wextra
>>> +CFLAGS += -Wno-empty-body
>>> +CFLAGS += -Wno-sign-compare
>>> +CFLAGS += -Wno-type-limits
>>> +CFLAGS += -Wno-unused-parameter
>> Is there a way to not disable these warnings but fix in the source code?
>> Or move to CFLAGS_BASE_DRIVER, if the reason is the base driver?
> 
> Will do in v2.
> 
>>> +
>>> +# More warnings not enabled by above aggregators
>>> +CFLAGS += -Waggregate-return
>>> +CFLAGS += -Wbad-function-cast
>>> +CFLAGS += -Wcast-qual
>>> +CFLAGS += -Wdisabled-optimization
>>> +CFLAGS += -Wmissing-declarations
>>> +CFLAGS += -Wmissing-prototypes
>>> +CFLAGS += -Wnested-externs
>>> +CFLAGS += -Wold-style-definition
>>> +CFLAGS += -Wpointer-arith
>>> +CFLAGS += -Wstrict-prototypes
>>> +CFLAGS += -Wundef
>>> +CFLAGS += -Wwrite-strings
>> If you believe some can be useful for everybody, please feel free to add
>> to mk/toolchain/* .
> 
> I'll definitely remove duplicates which are already included in 
> $(WERROR_FLAGS).
> I'd prefer to keep the rest just here for now. I think that adding it 
> world-wide
> requires testing on really many compiler versions etc.
> 
>>> +
>>> +EXPORT_MAP := rte_pmd_sfc_efx_version.map
>>> +
>>> +LIBABIVER := 1
>>> +
>>> +#
>>> +# all source are stored in SRCS-y
>>> +#
>>> +SRCS-$(CONFIG_RTE_LIBRTE_SFC_EFX_PMD) += sfc_ethdev.c
>>> +SRCS-$(CONFIG_RTE_LIBRTE_SFC_EFX_PMD) += sfc_kvargs.c
>>> +
>>> +
>>> +# this lib depends upon:
>>> +DEPDIRS-$(CONFIG_RTE_LIBRTE_SFC_EFX_PMD) += lib/librte_eal
>>> +DEPDIRS-$(CONFIG_RTE_LIBRTE_SFC_EFX_PMD) += lib/librte_kvargs
>>> +DEPDIRS-$(CONFIG_RTE_LIBRTE_SFC_EFX_PMD) += lib/librte_ether
>>> +DEPDIRS-$(CONFIG_RTE_LIBRTE_SFC_EFX_PMD) += lib/librte_mempool
>>> +DEPDIRS-$(CONFIG_RTE_LIBRTE_SFC_EFX_PMD) += lib/librte_mbuf
>>> +
>>> +include $(RTE_SDK)/mk/rte.lib.mk
>>> diff --git a/drivers/net/sfc/efx/rte_pmd_sfc_efx_version.map b/drivers/net/sfc/efx/rte_pmd_sfc_efx_version.map
>>> new file mode 100644
>>> index 0000000..1901bcb
>>> --- /dev/null
>>> +++ b/drivers/net/sfc/efx/rte_pmd_sfc_efx_version.map
>>> @@ -0,0 +1,4 @@
>>> +DPDK_16.07 {
>> Now this become 17.02
> 
> Thanks, will fix in v2.
> 
>>> +
>>> +	local: *;
>>> +};
>>> diff --git a/drivers/net/sfc/efx/sfc.h b/drivers/net/sfc/efx/sfc.h
>>> new file mode 100644
>>> index 0000000..16fd2bb
>>> --- /dev/null
>>> +++ b/drivers/net/sfc/efx/sfc.h
>>> @@ -0,0 +1,53 @@
>> <..>
>>> +
>>> +#ifndef _SFC_H
>>> +#define	_SFC_H
>> s/^I/ /
>> This also exists in other locations and files..
> 
> Will fix in v2.
> I thought that DPDK prefers TAB after #define as FreeBSD does, but 
> counting shows that space is really preferred.
> I think that such things should be caught by checkpatch.
> 
>> <...>
> 
> 

^ permalink raw reply

* Re: [PATCH 2/4] eventdev: implement the northbound APIs
From: Richardson, Bruce @ 2016-11-25  9:55 UTC (permalink / raw)
  To: Jerin Jacob, Thomas Monjalon
  Cc: dev@dpdk.org, Van Haaren, Harry, hemant.agrawal@nxp.com,
	Eads, Gage
In-Reply-To: <20161125041750.GA18469@localhost.localdomain>


> -----Original Message-----
> From: Jerin Jacob [mailto:jerin.jacob@caviumnetworks.com]
> Sent: Friday, November 25, 2016 4:18 AM
> To: Thomas Monjalon <thomas.monjalon@6wind.com>
> Cc: dev@dpdk.org; Richardson, Bruce <bruce.richardson@intel.com>; Van
> Haaren, Harry <harry.van.haaren@intel.com>; hemant.agrawal@nxp.com; Eads,
> Gage <gage.eads@intel.com>
> Subject: Re: [dpdk-dev] [PATCH 2/4] eventdev: implement the northbound
> APIs
> 
> On Wed, Nov 23, 2016 at 08:18:09PM +0100, Thomas Monjalon wrote:
> > 2016-11-18 11:15, Jerin Jacob:
> > > This patch set defines the southbound driver interface and
> > > implements the common code required for northbound eventdev API
> > > interface.
> >
> > Please make two separate patches.
> 
> OK
> 
> >
> > > +#ifdef RTE_LIBRTE_EVENTDEV_DEBUG
> > > +#define RTE_PMD_DEBUG_TRACE(...) \
> > > +	rte_pmd_debug_trace(__func__, __VA_ARGS__) #else #define
> > > +RTE_PMD_DEBUG_TRACE(...) #endif
> >
> > I would like to discuss the need for a debug option as there is
> > already a log level.
> 
> IMO, we don't need this. However, RTE_FUNC_PTR_OR_ERR_RET needs the
> definition of RTE_PMD_DEBUG_TRACE inorder to compile. I think we can
> remove it when it get fixed in EAL layer.
> 
> >
> > > +/* Logging Macros */
> > > +#define EDEV_LOG_ERR(fmt, args...) \
> >
> > Every symbols and macros in an exported header must be prefixed by RTE_.
> >
> OK. I will fix it
> 
> > > +/* Macros to check for valid device */ #define
> > > +RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, retval) do { \
> >
> > Sometimes you use RTE_EVENT_DEV_ and sometimes RTE_EVENTDEV.
> > (I prefer the latter).
> 
> I choose the naming conversion based on the interface. API side it is
> rte_event_ and driver side it is rte_eventdev_*
> 
> rte_event_dev_count;
> rte_event_dev_get_dev_id
> rte_event_dev_socket_id;
> rte_event_dev_info_get;
> rte_event_dev_configure;
> rte_event_dev_start;
> rte_event_dev_stop;
> rte_event_dev_close;
> rte_event_dev_dump;
> 
> rte_event_port_default_conf_get;
> rte_event_port_setup;
> rte_event_port_dequeue_depth;
> rte_event_port_enqueue_depth;
> rte_event_port_count;
> rte_event_port_link;
> rte_event_port_unlink;
> rte_event_port_links_get;
> 
> rte_event_queue_default_conf_get
> rte_event_queue_setup;
> rte_event_queue_count;
> rte_event_queue_priority;
> 
> rte_event_dequeue_wait_time;
> 
> rte_eventdev_pmd_allocate;
> rte_eventdev_pmd_release;
> rte_eventdev_pmd_vdev_init;
> rte_eventdev_pmd_pci_probe;
> rte_eventdev_pmd_pci_remove;

For this last set, you probably are ok prefixing with just "rte_event_pmd_", and drop the "dev" as unnecessary. That makes everything have a prefix of "rte_event_" and thereafter dev, port, queue, or pmd as appropriate.

/Bruce

^ permalink raw reply

* [PATCH] kni: avoid using lsb_release script
From: Robin Jarry @ 2016-11-25  9:52 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev

The lsb_release script is part of an optional package which is not
always installed. On the other hand, /etc/lsb-release is always present
even on minimal Ubuntu installations.

    root@ubuntu1604:~# dpkg -S /etc/lsb-release
    base-files: /etc/lsb-release

Read the file if present and use the variables defined in it.

Signed-off-by: Robin Jarry <robin.jarry@6wind.com>
---
 lib/librte_eal/linuxapp/kni/Makefile | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/lib/librte_eal/linuxapp/kni/Makefile b/lib/librte_eal/linuxapp/kni/Makefile
index 4e99e07e7aec..63b9ac8779f8 100644
--- a/lib/librte_eal/linuxapp/kni/Makefile
+++ b/lib/librte_eal/linuxapp/kni/Makefile
@@ -44,8 +44,12 @@ MODULE_CFLAGS += -I$(RTE_OUTPUT)/include -I$(SRCDIR)/ethtool/ixgbe -I$(SRCDIR)/e
 MODULE_CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h
 MODULE_CFLAGS += -Wall -Werror
 
-ifeq ($(shell lsb_release -si 2>/dev/null),Ubuntu)
-MODULE_CFLAGS += -DUBUNTU_RELEASE_CODE=$(shell lsb_release -sr | tr -d .)
+ifneq ($(wildcard /etc/lsb-release),)
+include /etc/lsb-release
+endif
+
+ifeq ($(DISTRIB_ID),Ubuntu)
+MODULE_CFLAGS += -DUBUNTU_RELEASE_CODE=$(subst .,,$(DISTRIB_ID))
 UBUNTU_KERNEL_CODE := $(shell echo `grep UTS_RELEASE $(RTE_KERNELDIR)/include/generated/utsrelease.h \
 	 | cut -d '"' -f2 | cut -d- -f1,2 | tr .- ,`,1)
 MODULE_CFLAGS += -D"UBUNTU_KERNEL_CODE=UBUNTU_KERNEL_VERSION($(UBUNTU_KERNEL_CODE))"
-- 
2.1.4

^ permalink raw reply related

* Re: [PATCH] doc: introduce PVP reference benchmark
From: Maxime Coquelin @ 2016-11-25  9:29 UTC (permalink / raw)
  To: Mcnamara, John, yuanhan.liu@linux.intel.com,
	thomas.monjalon@6wind.com, Yang, Zhiyong, dev@dpdk.org
  Cc: fbaudin@redhat.com
In-Reply-To: <B27915DBBA3421428155699D51E4CFE20266939E@IRSMSX103.ger.corp.intel.com>

Hi John,

On 11/24/2016 06:38 PM, Mcnamara, John wrote:
>> -----Original Message-----
>> From: Maxime Coquelin [mailto:maxime.coquelin@redhat.com]
>> Sent: Wednesday, November 23, 2016 9:00 PM
>> To: yuanhan.liu@linux.intel.com; thomas.monjalon@6wind.com; Mcnamara, John
>> <john.mcnamara@intel.com>; Yang, Zhiyong <zhiyong.yang@intel.com>;
>> dev@dpdk.org
>> Cc: fbaudin@redhat.com; Maxime Coquelin <maxime.coquelin@redhat.com>
>> Subject: [PATCH] doc: introduce PVP reference benchmark
>>
>> Having reference benchmarks is important in order to obtain reproducible
>> performance figures.
>>
>> This patch describes required steps to configure a PVP setup using testpmd
>> in both host and guest.
>>
>> Not relying on external vSwitch ease integration in a CI loop by not being
>> impacted by DPDK API changes.
>
> Hi Maxime,
>
> Thanks for the detailed doc and this initiative. Some minor documentation
> comments below.
>
>
>
>> +
>> +Setup overview
>> +..............
>
> This level header should be ---------, even if it looks like dots in the
> contribution guide:
>
>     http://dpdk.org/doc/guides/contributing/documentation.html#section-headers
>
>
>> +
>> +.. figure:: img/pvp_2nics.svg
>> +
>> +  PVP setup using 2 NICs
>> +
>
> The figure needs a target so it can be used with :numref:, like this:
>
> .. _figure_pvp_2nics:
>
> .. figure:: img/pvp_2nics.*
>
>    PVP setup using 2 NICs
>
>
>> +DPDK build
>> +~~~~~~~~~~
>> +
>
> Put a one line description at the start of each section, even if it is just: Build DPDK:
Ok.
>
>
>
>> +Testpmd launch
>> +~~~~~~~~~~~~~~
>> +
>> +#. Assign NICs to DPDK:
>> +
>> +   .. code-block:: console
>> +
>> +    modprobe vfio-pci
>> +    $RTE_SDK/install/sbin/dpdk-devbind -b vfio-pci 0000:11:00.0
>> + 0000:11:00.1
>> +
>> +*Note: Sandy Bridge family seems to have some limitations wrt its
>> +IOMMU, giving poor performance results. To achieve good performance on
>> +these machines, consider using UIO instead.*
>
> This would be better as an RST note:
>
> #. Assign NICs to DPDK:
>
>    .. code-block:: console
>
>       modprobe vfio-pci
>       $RTE_SDK/install/sbin/dpdk-devbind -b vfio-pci 0000:11:00.0 0000:11:00.1
>
>    .. Note::
>
>       The Sandy Bridge family seems to have some IOMMU limitations giving poor
>       performance results. To achieve good performance on these machines
>       consider using UIO instead.
This is indeed better, thanks for the tip!

About this note, I couldn't find official information about this
problem.

Do you confirm the issue, or I misconfigured something?

I'll also add something about security implications of using UIO.
>
>
>
>> +First, SELinux policy needs to be set to permissiven, as testpmd is run
>> +as root (reboot required):
>
> s/permissiven/permissive/
>
>
> There are a couple of trailing whitespace errors as well at build as well.

Ok, I will rework all this.

Thanks for the review,
Maxime

^ permalink raw reply

* Re: [PATCH v2 2/7] pci: Separate detaching ethernet ports from PCI devices
From: Shreyansh Jain @ 2016-11-25  9:25 UTC (permalink / raw)
  To: Ben Walker; +Cc: dev
In-Reply-To: <1479931644-78960-2-git-send-email-benjamin.walker@intel.com>

On Thursday 24 November 2016 01:37 AM, Ben Walker wrote:
> Attaching and detaching ethernet ports from an application
> is not the same thing as physically removing a PCI device,
> so clarify the flags indicating support. All PCI devices
> are assumed to be physically removable, so no flag is
> necessary in the PCI layer.
>
> Signed-off-by: Ben Walker <benjamin.walker@intel.com>
> ---
>  doc/guides/prog_guide/port_hotplug_framework.rst | 2 +-
>  drivers/net/bnxt/bnxt_ethdev.c                   | 3 ++-
>  drivers/net/e1000/em_ethdev.c                    | 4 ++--
>  drivers/net/e1000/igb_ethdev.c                   | 7 ++++---
>  drivers/net/fm10k/fm10k_ethdev.c                 | 4 ++--
>  drivers/net/i40e/i40e_ethdev.c                   | 4 ++--
>  drivers/net/i40e/i40e_ethdev_vf.c                | 3 ++-
>  drivers/net/ixgbe/ixgbe_ethdev.c                 | 7 ++++---
>  drivers/net/nfp/nfp_net.c                        | 4 ++--
>  drivers/net/virtio/virtio_ethdev.c               | 3 ++-
>  drivers/net/vmxnet3/vmxnet3_ethdev.c             | 3 ++-
>  drivers/net/xenvirt/rte_eth_xenvirt.c            | 2 +-
>  lib/librte_eal/common/include/rte_pci.h          | 2 --
>  lib/librte_ether/rte_ethdev.c                    | 2 --
>  14 files changed, 26 insertions(+), 24 deletions(-)
>
> diff --git a/doc/guides/prog_guide/port_hotplug_framework.rst b/doc/guides/prog_guide/port_hotplug_framework.rst
> index 6e4436e..d68d08e 100644
> --- a/doc/guides/prog_guide/port_hotplug_framework.rst
> +++ b/doc/guides/prog_guide/port_hotplug_framework.rst
> @@ -106,5 +106,5 @@ Limitations
>
>  *       Not all PMDs support detaching feature.
>          To know whether a PMD can support detaching, search for the
> -        "RTE_PCI_DRV_DETACHABLE" flag in PMD implementation. If the flag is
> +        "RTE_ETH_DEV_DETAHABLE" flag in rte_eth_dev::data::dev_flags. If the flag is

Incorrect spelling. Should be 'RTE_ETH_DEV_DETACHABLE'.

>          defined in the PMD, detaching is supported.
> diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
> index 035fe07..a2100f6 100644
> --- a/drivers/net/bnxt/bnxt_ethdev.c
> +++ b/drivers/net/bnxt/bnxt_ethdev.c
> @@ -1051,6 +1051,7 @@ bnxt_dev_init(struct rte_eth_dev *eth_dev)
>  		RTE_LOG(INFO, PMD, "%s", bnxt_version);
>
>  	rte_eth_copy_pci_info(eth_dev, eth_dev->pci_dev);
> +	eth_dev->data->dev_flags = RTE_ETH_DEV_DETACHABLE;
>  	bp = eth_dev->data->dev_private;
>
>  	if (bnxt_vf_pciid(eth_dev->pci_dev->id.device_id))
[...]

-
Shreyansh

^ permalink raw reply

* Re: [PATCH v2 1/7] pci: If a driver's probe function fails, unmap resources.
From: Shreyansh Jain @ 2016-11-25  9:21 UTC (permalink / raw)
  To: Ben Walker; +Cc: dev
In-Reply-To: <1479931644-78960-1-git-send-email-benjamin.walker@intel.com>

On Thursday 24 November 2016 01:37 AM, Ben Walker wrote:
> If resources were mapped prior to probe, unmap them
> if probe fails.
>
> This does not handle the case where the kernel driver was
> forcibly unbound prior to probe.
>
> Signed-off-by: Ben Walker <benjamin.walker@intel.com>
> ---
>  lib/librte_eal/common/eal_common_pci.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
> index 6bff675..4f8c3a0 100644
> --- a/lib/librte_eal/common/eal_common_pci.c
> +++ b/lib/librte_eal/common/eal_common_pci.c
> @@ -215,8 +215,11 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *d
>
>  		/* call the driver probe() function */
>  		ret = dr->probe(dr, dev);
> -		if (ret)
> +		if (ret) {
>  			dev->driver = NULL;
> +			if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
> +				rte_eal_pci_unmap_device(dev);
> +		}
>
>  		return ret;
>  	}
>

Acked-by: Shreyansh Jain <shreyansh.jain@nxp.com>

^ permalink raw reply

* [PATCH 1/1] net/i40e: enable auto link update for XXV710
From: Qi Zhang @ 2016-11-24 23:43 UTC (permalink / raw)
  To: jingjing.wu, helin.zhang; +Cc: dev, Qi Zhang

This patch remove the limitation that XXV710 device does
not support auto link update.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 67778ba..b7a916d 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1628,6 +1628,8 @@ i40e_phy_conf_link(struct i40e_hw *hw,
 
 	/* use get_phy_abilities_resp value for the rest */
 	phy_conf.phy_type = phy_ab.phy_type;
+	phy_conf.phy_type_ext = phy_ab.phy_type_ext;
+	phy_conf.fec_config = phy_ab.mod_type_ext;
 	phy_conf.eee_capability = phy_ab.eee_capability;
 	phy_conf.eeer = phy_ab.eeer_val;
 	phy_conf.low_power_ctrl = phy_ab.d3_lpan;
@@ -1653,8 +1655,7 @@ i40e_apply_link_speed(struct rte_eth_dev *dev)
 	struct rte_eth_conf *conf = &dev->data->dev_conf;
 
 	speed = i40e_parse_link_speeds(conf->link_speeds);
-	if (!I40E_PHY_TYPE_SUPPORT_25G(hw->phy.phy_types))
-		abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+	abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
 	if (!(conf->link_speeds & ETH_LINK_SPEED_FIXED))
 		abilities |= I40E_AQ_PHY_AN_ENABLED;
 	abilities |= I40E_AQ_PHY_LINK_ENABLED;
@@ -1990,8 +1991,7 @@ i40e_dev_set_link_down(struct rte_eth_dev *dev)
 	uint8_t abilities = 0;
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
-	if (!I40E_PHY_TYPE_SUPPORT_25G(hw->phy.phy_types))
-		abilities = I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+	abilities = I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
 	return i40e_phy_conf_link(hw, abilities, speed);
 }
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH] lpm: rte_lpm_iterate() - iterate through the routes
From: chunguang yang @ 2016-11-25  6:31 UTC (permalink / raw)
  To: dev; +Cc: Weiwei.Wang, mark.asselstine

From: Jörgen Grahn <grahn+src@snipabacken.se>

In practice, there's a need to iterate through the entries
of a rte_lpm, apart from the usual insert/delete/lookup
operations.  This is useful for debugging and perhaps for
things like removing all entries referencing a certain nexthop.

This patch implements this through rte_lpm_iterate(), which
uses a cursor (or iterator) to keep track of the current
position.  Client code doesn't need to be aware of rte_lpm
implementation details.

Change-Id: I28ea3d7d92f318988444553ee2bb30b709bcb3b6
Signed-off-by: Jorgen Grahn <jorgen.grahn@hiq.se>
Signed-off-by: alloc <alloc.young@gmail.com>
---
 lib/librte_lpm/Makefile          |  4 +-
 lib/librte_lpm/rte_lpm_iterate.c | 81 ++++++++++++++++++++++++++++++++++++++++
 lib/librte_lpm/rte_lpm_iterate.h | 56 +++++++++++++++++++++++++++
 3 files changed, 139 insertions(+), 2 deletions(-)
 create mode 100644 lib/librte_lpm/rte_lpm_iterate.c
 create mode 100644 lib/librte_lpm/rte_lpm_iterate.h

diff --git a/lib/librte_lpm/Makefile b/lib/librte_lpm/Makefile
index 3dc549d..c45da19 100644
--- a/lib/librte_lpm/Makefile
+++ b/lib/librte_lpm/Makefile
@@ -42,10 +42,10 @@ EXPORT_MAP := rte_lpm_version.map
 LIBABIVER := 2
 
 # all source are stored in SRCS-y
-SRCS-$(CONFIG_RTE_LIBRTE_LPM) := rte_lpm.c rte_lpm6.c
+SRCS-$(CONFIG_RTE_LIBRTE_LPM) := rte_lpm.c rte_lpm6.c rte_lpm_iterate.c
 
 # install this header file
-SYMLINK-$(CONFIG_RTE_LIBRTE_LPM)-include := rte_lpm.h rte_lpm6.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_LPM)-include := rte_lpm.h rte_lpm6.h rte_lpm_iterate.h
 
 ifneq ($(filter y,$(CONFIG_RTE_ARCH_ARM) $(CONFIG_RTE_ARCH_ARM64)),)
 SYMLINK-$(CONFIG_RTE_LIBRTE_LPM)-include += rte_lpm_neon.h
diff --git a/lib/librte_lpm/rte_lpm_iterate.c b/lib/librte_lpm/rte_lpm_iterate.c
new file mode 100644
index 0000000..f643764
--- /dev/null
+++ b/lib/librte_lpm/rte_lpm_iterate.c
@@ -0,0 +1,81 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2014 Jörgen Grahn. 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 Intel Corporation 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_lpm_iterate.h"
+#include "rte_lpm.h"
+
+#include <arpa/inet.h>
+
+
+/**
+ * Iterate through the lpm, pulling out at most 'buflen' valid routes
+ * (less means we've hit the end).  The cursor should be initialized
+ * to { 0, 0 } before the first call.
+ *
+ * The routes are partially sorted, by prefix length.  Undefined
+ * results if the lpm is modified in parallel with or inbetween calls,
+ * although the iteration will still terminate properly.
+ */
+unsigned
+rte_lpm_iterate(struct rte_lpm_route* const buf, unsigned buflen,
+		const struct rte_lpm* lpm,
+		struct rte_lpm_cursor* const cursor)
+{
+	struct rte_lpm_route* p = buf;
+	struct rte_lpm_route* const end = p + buflen;
+
+	const struct rte_lpm_rule_info* const rinfo = lpm->rule_info;
+	const struct rte_lpm_rule* const rtbl = lpm->rules_tbl;
+
+	unsigned d = cursor->d;
+	unsigned n = cursor->n;
+
+	while(p!=end) {
+		if(d==32) break;
+		if(n>=rinfo[d].used_rules) {
+			d++;
+			n = 0;
+			continue;
+		}
+		const struct rte_lpm_rule rule = rtbl[rinfo[d].first_rule + n];
+		p->addr.s_addr = htonl(rule.ip);
+		p->plen = d+1;
+		p->nh = rule.next_hop;
+		p++;
+		n++;
+	}
+
+	cursor->d = d;
+	cursor->n = n;
+
+	return p - buf;
+}
diff --git a/lib/librte_lpm/rte_lpm_iterate.h b/lib/librte_lpm/rte_lpm_iterate.h
new file mode 100644
index 0000000..25c7841
--- /dev/null
+++ b/lib/librte_lpm/rte_lpm_iterate.h
@@ -0,0 +1,56 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2014 Jörgen Grahn. 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 Intel Corporation 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 _RTE_LPM_ITERATE_H_
+#define _RTE_LPM_ITERATE_H_
+
+#include <stdint.h>
+#include <netinet/in.h>
+
+struct rte_lpm;
+
+struct rte_lpm_cursor {
+	unsigned d;
+	unsigned n;
+};
+
+struct rte_lpm_route {
+	struct in_addr addr;
+	uint8_t plen;
+	uint8_t nh;
+};
+
+unsigned rte_lpm_iterate(struct rte_lpm_route* buf, unsigned buflen,
+			 const struct rte_lpm* lpm,
+			 struct rte_lpm_cursor* cursor);
+
+#endif
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH 2/4] eventdev: implement the northbound APIs
From: Jerin Jacob @ 2016-11-25  4:17 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, bruce.richardson, harry.van.haaren, hemant.agrawal,
	gage.eads
In-Reply-To: <4871697.UraAQdum7A@xps13>

On Wed, Nov 23, 2016 at 08:18:09PM +0100, Thomas Monjalon wrote:
> 2016-11-18 11:15, Jerin Jacob:
> > This patch set defines the southbound driver interface
> > and implements the common code required for northbound
> > eventdev API interface.
> 
> Please make two separate patches.

OK

> 
> > +#ifdef RTE_LIBRTE_EVENTDEV_DEBUG
> > +#define RTE_PMD_DEBUG_TRACE(...) \
> > +	rte_pmd_debug_trace(__func__, __VA_ARGS__)
> > +#else
> > +#define RTE_PMD_DEBUG_TRACE(...)
> > +#endif
> 
> I would like to discuss the need for a debug option as there is
> already a log level.

IMO, we don't need this. However, RTE_FUNC_PTR_OR_ERR_RET needs the
definition of RTE_PMD_DEBUG_TRACE inorder to compile. I think we can
remove it when it get fixed in EAL layer.

> 
> > +/* Logging Macros */
> > +#define EDEV_LOG_ERR(fmt, args...) \
> 
> Every symbols and macros in an exported header must be prefixed by RTE_.
> 
OK. I will fix it

> > +/* Macros to check for valid device */
> > +#define RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, retval) do { \
> 
> Sometimes you use RTE_EVENT_DEV_ and sometimes RTE_EVENTDEV.
> (I prefer the latter).

I choose the naming conversion based on the interface. API side it
is rte_event_ and driver side it is rte_eventdev_*

rte_event_dev_count;
rte_event_dev_get_dev_id
rte_event_dev_socket_id;
rte_event_dev_info_get;
rte_event_dev_configure;
rte_event_dev_start;
rte_event_dev_stop;
rte_event_dev_close;
rte_event_dev_dump;

rte_event_port_default_conf_get;
rte_event_port_setup;
rte_event_port_dequeue_depth;
rte_event_port_enqueue_depth;
rte_event_port_count;
rte_event_port_link;
rte_event_port_unlink;
rte_event_port_links_get;

rte_event_queue_default_conf_get
rte_event_queue_setup;
rte_event_queue_count;
rte_event_queue_priority;

rte_event_dequeue_wait_time;

rte_eventdev_pmd_allocate;
rte_eventdev_pmd_release;
rte_eventdev_pmd_vdev_init;
rte_eventdev_pmd_pci_probe;
rte_eventdev_pmd_pci_remove;

^ permalink raw reply

* [PATCH] tools/dpdkdevbind.py: remove call to lower case for mod path
From: alloc @ 2016-11-25  3:16 UTC (permalink / raw)
  To: dev; +Cc: Mark Asselstine, Wang, Weiwei

If the module path has upper case chars, the dpdk-devbind.py script will
crunch them to lower case.  This will result in the script never
finding a module.

Port patch to dpdk-1.7.0

dpdk_nic_bind.py has been renamed to dpdk-devbind.py in 16.11, so
just change file name.
Signed-off-by: Paul Barrette <paul.barrette@windriver.com>
Signed-off-by: Pengyu Ma <pengyu.ma@windriver.com>
Signed-off-by: chunguang yang <chunguang.yang@windriver.com>
---
  tools/dpdk-devbind.py | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/dpdk-devbind.py b/tools/dpdk-devbind.py
index f1d374d..d66d68c 100755
--- a/tools/dpdk-devbind.py
+++ b/tools/dpdk-devbind.py
@@ -141,7 +141,7 @@ def find_module(mod):
      # check using depmod
      try:
          depmod_out = check_output(["modinfo", "-n", mod],
-                                  stderr=subprocess.STDOUT).lower()
+                                  stderr=subprocess.STDOUT)
          if "error" not in depmod_out:
              path = depmod_out.strip()
              if exists(path):
-- 
2.9.3

^ permalink raw reply related

* [PATCH] tools/dpdkdevbind.py: remove call to lower case for mod path
From: alloc @ 2016-11-25  3:10 UTC (permalink / raw)
  To: dev



^ permalink raw reply

* Re: [PATCH 1/4] eventdev: introduce event driven programming model
From: Jerin Jacob @ 2016-11-25  0:23 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, bruce.richardson, harry.van.haaren, hemant.agrawal,
	gage.eads
In-Reply-To: <1883454.103LptOkIX@xps13>

On Thu, Nov 24, 2016 at 04:35:56PM +0100, Thomas Monjalon wrote:
> 2016-11-24 07:29, Jerin Jacob:
> > On Wed, Nov 23, 2016 at 07:39:09PM +0100, Thomas Monjalon wrote:
> > > 2016-11-18 11:14, Jerin Jacob:
> > > > +Eventdev API - EXPERIMENTAL
> > > > +M: Jerin Jacob <jerin.jacob@caviumnetworks.com>
> > > > +F: lib/librte_eventdev/
> > > 
> > > OK to mark it experimental.
> > > What is the plan to remove the experimental word?
> > 
> > IMO, EXPERIMENTAL status can be changed when
> > - At least two event drivers available(Intel and Cavium are working on
> >   SW and HW event drivers)
> > - Functional test applications are fine with at least two drivers
> > - Portable example application to showcase the features of the library
> > - eventdev integration with another dpdk subsystem such as ethdev
> > 
> > Thoughts?. I am not sure the criteria used in cryptodev case.
> 
> Sounds good.
> We will be more confident when drivers and tests will be implemented.
> 
> I think the roadmap for the SW driver targets the release 17.05.
> Do you still plan 17.02 for this API and the Cavium driver?

No. 17.02 too short for up-streaming the Cavium driver.However, I think API and
skeleton event driver can go in 17.02 if there are no objections.

> 
> > > > +#define EVENTDEV_NAME_SKELETON_PMD event_skeleton
> > > > +/**< Skeleton event device PMD name */
> > > 
> > > I do not understand this #define.
> > 
> > Applications can explicitly request the a specific driver though driver
> > name. This will go as argument to rte_event_dev_get_dev_id(const char *name).
> > The reason for keeping this #define in rte_eventdev.h is that,
> > application needs to include only rte_eventdev.h not rte_eventdev_pmd.h.
> 
> So each driver must register its name in the API?
> Is it really needed?

Otherwise how application knows the name of the driver.
The similar scheme used in cryptodev.
http://dpdk.org/browse/dpdk/tree/lib/librte_cryptodev/rte_cryptodev.h#n53
No strong opinion here. Open for suggestions.

> 
> > > > +struct rte_event_dev_config {
> > > > +	uint32_t dequeue_wait_ns;
> > > > +	/**< rte_event_dequeue() wait for *dequeue_wait_ns* ns on this device.
> > > 
> > > Please explain exactly when the wait occurs and why.
> > 
> > Here is the explanation from rte_event_dequeue() API definition,
> > -
> > @param wait
> > 0 - no-wait, returns immediately if there is no event.
> > >0 - wait for the event, if the device is configured with
> > RTE_EVENT_DEV_CFG_PER_DEQUEUE_WAIT then this function will wait until
> > the event available or *wait* time.
> > if the device is not configured with RTE_EVENT_DEV_CFG_PER_DEQUEUE_WAIT
> > then this function will wait until the event available or *dequeue_wait_ns*
> >                                                       ^^^^^^^^^^^^^^^^^^^^^^
> > ns which was previously supplied to rte_event_dev_configure()
> > -
> > This is provides the application to have control over, how long the
> > implementation should wait if event is not available.
> > 
> > Let me know what exact changes are required if details are not enough in
> > rte_event_dequeue() API definition.
> 
> Maybe that timeout would be a better name.
> It waits only if there is nothing in the queue.
> It can be interesting to highlight in this comment that this parameter
> makes the dequeue function a blocking call.

OK. I will change to timeout then

> 
> > > > +/** Event port configuration structure */
> > > > +struct rte_event_port_conf {
> > > > +	int32_t new_event_threshold;
> > > > +	/**< A backpressure threshold for new event enqueues on this port.
> > > > +	 * Use for *closed system* event dev where event capacity is limited,
> > > > +	 * and cannot exceed the capacity of the event dev.
> > > > +	 * Configuring ports with different thresholds can make higher priority
> > > > +	 * traffic less likely to  be backpressured.
> > > > +	 * For example, a port used to inject NIC Rx packets into the event dev
> > > > +	 * can have a lower threshold so as not to overwhelm the device,
> > > > +	 * while ports used for worker pools can have a higher threshold.
> > > > +	 * This value cannot exceed the *nb_events_limit*
> > > > +	 * which previously supplied to rte_event_dev_configure()
> > > > +	 */
> > > > +	uint8_t dequeue_depth;
> > > > +	/**< Configure number of bulk dequeues for this event port.
> > > > +	 * This value cannot exceed the *nb_event_port_dequeue_depth*
> > > > +	 * which previously supplied to rte_event_dev_configure()
> > > > +	 */
> > > > +	uint8_t enqueue_depth;
> > > > +	/**< Configure number of bulk enqueues for this event port.
> > > > +	 * This value cannot exceed the *nb_event_port_enqueue_depth*
> > > > +	 * which previously supplied to rte_event_dev_configure()
> > > > +	 */
> > > > +};
> > > 
> > > The depth configuration is not clear to me.
> > 
> > Basically the maximum number of events can be enqueued/dequeued at time
> > from a given event port. depth of one == non burst mode.
> 
> OK so depth is the queue size. Please could you reword?

OK

> 
> > > > +/* Event types to classify the event source */
> > > 
> > > Why this classification is needed?
> > 
> > This for application pipeling and the cases like, if application wants to know which
> > subsystem generated the event.
> > 
> > example packet forwarding loop on the worker cores:
> > while(1) {
> > 	ev = dequeue()
> > 	// event from ethdev subsystem
> > 	if (ev.event_type == RTE_EVENT_TYPE_ETHDEV) {
> > 		- swap the mac address
> > 		- push to atomic queue for ingress flow order maintenance
> > 		  by CORE
> > 	/* events from core */
> > 	} else if (ev.event_type == RTE_EVENT_TYPE_CORE) {
> > 
> > 	}
> > 	enqueue(ev);
> > }
> 
> I don't know why but I feel this classification is weak.
> You need to track the source of the event. Does it make sense to go beyond
> and identify the source device?

No, dequeue has dev_id argument, so event comes only from that device

> 
> > > > +#define RTE_EVENT_TYPE_ETHDEV           0x0
> > > > +/**< The event generated from ethdev subsystem */
> > > > +#define RTE_EVENT_TYPE_CRYPTODEV        0x1
> > > > +/**< The event generated from crypodev subsystem */
> > > > +#define RTE_EVENT_TYPE_TIMERDEV         0x2
> > > > +/**< The event generated from timerdev subsystem */
> > > > +#define RTE_EVENT_TYPE_CORE             0x3
> > > > +/**< The event generated from core.
> > > 
> > > What is core?
> > 
> > The event are generated by lcore for pipeling. Any suggestion for
> > better name? lcore?
> 
> What about CPU or SW?

No strong opinion here. I will go with CPU then

> 
> > > > +		/**< Opaque event pointer */
> > > > +		struct rte_mbuf *mbuf;
> > > > +		/**< mbuf pointer if dequeued event is associated with mbuf */
> > > 
> > > How do we know that an event is associated with mbuf?
> > 
> > By looking at the event source/type RTE_EVENT_TYPE_*
> > 
> > > Does it mean that such events are always converted into mbuf even if the
> > > application does not need it?
> > 
> > Hardware has dependency on getting physical address of the event, so any
> > struct that has "phys_addr_t buf_physaddr" works.
> 
> I do not understand.

In HW based implementations, the event pointer will be submitted to HW.
As you know, since HW can't understand the virtual address and it needs
to converted to the physical address, any DPDK object that provides phys_addr_t
such as mbuf can be used with libeventdev.

> 
> I tought that decoding the event would be the responsibility of the app
> by calling a function like
> rte_eventdev_convert_to_mbuf(struct rte_event *, struct rte_mbuf *).

It can be. But it is costly.i.e Yet another function pointer based
driver interface on fastpath. Instead, if the driver itself can
convert to mbuf(in case of ETHDEV device) and tag the source/event type
as RTE_EVENT_TYPE_ETHDEV.
IMO the proposed schemed helps in SW based implementation as their no real
mbuf conversation. Something we can revisit in ethdev integration if
required.

> 
> > > > +struct rte_eventdev_driver;
> > > > +struct rte_eventdev_ops;
> > > 
> > > I think it is better to split API and driver interface in two files.
> > > (we should do this split in ethdev)
> > 
> > I thought so, but then the "static inline" versions of northbound
> > API(like rte_event_enqueue) will go another file(due to the fact that
> > implementation need to deference "dev->data->ports[port_id]"). Do you want that way?
> > I would like to keep all northbound API in rte_eventdev.h and not any of them
> > in rte_eventdev_pmd.h.
> 
> My comment was confusing.
> You are doing 2 files, one for API (what you call northbound I think)
> and the other one for driver interface (what you call southbound I think),
> it's very fine.
> 
> > > > +/**
> > > > + * Enqueue the event object supplied in the *rte_event* structure on an
> > > > + * event device designated by its *dev_id* through the event port specified by
> > > > + * *port_id*. The event object specifies the event queue on which this
> > > > + * event will be enqueued.
> > > > + *
> > > > + * @param dev_id
> > > > + *   Event device identifier.
> > > > + * @param port_id
> > > > + *   The identifier of the event port.
> > > > + * @param ev
> > > > + *   Pointer to struct rte_event
> > > > + *
> > > > + * @return
> > > > + *  - 0 on success
> > > > + *  - <0 on failure. Failure can occur if the event port's output queue is
> > > > + *     backpressured, for instance.
> > > > + */
> > > > +static inline int
> > > > +rte_event_enqueue(uint8_t dev_id, uint8_t port_id, struct rte_event *ev)
> > > 
> > > Is it really needed to have non-burst variant of enqueue/dequeue?
> > 
> > Yes. certain HW can work only with non burst variants.
> 
> Same comment as Bruce, we must keep only the burst variant.
> We cannot have different API for different HW.

I don't think there is any portability issue here, I can explain.

The application level, we have two more use case to deal with non burst
variant

- latency critical work
- on dequeue, if application wants to deal with only one flow(i.e to
  avoid processing two different application flows to avoid cache trashing)

Selection of the burst variants will be based on
rte_event_dev_info_get() and rte_event_dev_configure()(see, max_event_port_dequeue_depth,
max_event_port_enqueue_depth, nb_event_port_dequeue_depth, nb_event_port_enqueue_depth )
So I don't think their is portability issue here and I don't want to waste my
CPU cycles on the for loop if application known to be working with non
bursts variant like below

nb_events = rte_event_dequeue_burst();
for(i=0; i < nb_events; i++){
	process ev[i]
}

And mostly importantly the NPU can get almost same throughput
without burst variant so why not?

> 
> > > > +/**
> > > > + * Converts nanoseconds to *wait* value for rte_event_dequeue()
> > > > + *
> > > > + * If the device is configured with RTE_EVENT_DEV_CFG_PER_DEQUEUE_WAIT flag then
> > > > + * application can use this function to convert wait value in nanoseconds to
> > > > + * implementations specific wait value supplied in rte_event_dequeue()
> > > 
> > > Why is it implementation-specific?
> > > Why this conversion is not internal in the driver?
> > 
> > This is for performance optimization, otherwise in drivers
> > need to convert ns to ticks in "fast path"
> 
> So why not defining the unit of this timeout as CPU cycles like the ones
> returned by rte_get_timer_cycles()?

Because HW co-processor can run in different clock domain. Need not be at
CPU frequency.

> 
> 

^ permalink raw reply

* Re: [PATCH 1/4] eventdev: introduce event driven programming model
From: Jerin Jacob @ 2016-11-24 19:30 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev, harry.van.haaren, hemant.agrawal, gage.eads
In-Reply-To: <20161124162410.GA136296@bricha3-MOBL3.ger.corp.intel.com>

On Thu, Nov 24, 2016 at 04:24:11PM +0000, Bruce Richardson wrote:
> On Fri, Nov 18, 2016 at 11:14:59AM +0530, Jerin Jacob wrote:
> > In a polling model, lcores poll ethdev ports and associated
> > rx queues directly to look for packet. In an event driven model,
> > by contrast, lcores call the scheduler that selects packets for
> > them based on programmer-specified criteria. Eventdev library
> > adds support for event driven programming model, which offer
> > applications automatic multicore scaling, dynamic load balancing,
> > pipelining, packet ingress order maintenance and
> > synchronization services to simplify application packet processing.
> > 
> > By introducing event driven programming model, DPDK can support
> > both polling and event driven programming models for packet processing,
> > and applications are free to choose whatever model
> > (or combination of the two) that best suits their needs.
> > 
> > Signed-off-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
> > ---
> 
> Hi Jerin,
> 
> Thanks for the patchset. A few minor comments in general on the API that
> we found from working with it (thus far - more may follow :-) ).

Thanks Bruce.

> 
> 1. Priorities: priorities are used in a number of places in the API, but
>    all are uint8_t types and have their own MAX/NORMAL/MIN values. I think
>    it would be simpler for the user just to have one priority type in the
>    library, and use that everywhere. I suggest using RTE_EVENT_PRIORITY_*
>    and drop the separate defines for SERVICE_PRIORITY, and QUEUE_PRIORITY
>    etc. Ideally, I'd see things like this converted to enums too, rather
>    than defines, but I'm not sure it's possible in this case.

OK. I will address it in v2

> 
> 2. Functions for config and setup can have their structure parameter
>    types as const as they don't/shouldn't change the values internally.
>    So add "const" to parameters to:
>      rte_event_dev_configure()
>      rte_event_queue_setup()
>      rte_event_port_setup()
>      rte_event_port_link()
> 

OK. I will address it in v2

> 3. in event schedule() function, the dev->schedule() function needs the
>    dev instance pointer passed in as parameter.

OK. I will address it in v2

> 
> 4. The event op values and the event type values would be better as
>    enums rather than as a set of #defines.

OK. I will address it in v2

I will reply to your other comments in Thomas's email.

> 
> Regards,
> /Bruce

^ permalink raw reply

* [PATCH] test: adding AES cipher-only tests on QAT PMD
From: Fiona Trahe @ 2016-11-24 18:29 UTC (permalink / raw)
  To: dev; +Cc: pablo.de.lara.guarch, fiona.trahe, john.griffin,
	arkadiuszx.kusztal

Extended functional AES-CBC and AES-CTR cipher-only
tests to run on QAT PMD.
Added AES_CBC cipher-only performance tests on QAT PMD.
No driver changes, but as now tested, QAT documentation
is updated to remove constraint.

Signed-off-by: Fiona Trahe <fiona.trahe@intel.com>
---
 app/test/test_cryptodev.c                  | 18 ++++++
 app/test/test_cryptodev_aes_test_vectors.h | 36 +++++++----
 app/test/test_cryptodev_perf.c             | 96 +++++++++++++++++++-----------
 doc/guides/cryptodevs/qat.rst              |  1 -
 4 files changed, 102 insertions(+), 49 deletions(-)

diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index 872f8b4..00dced5 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -1530,6 +1530,22 @@ test_AES_chain_qat_all(void)
 }
 
 static int
+test_AES_cipheronly_qat_all(void)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	int status;
+
+	status = test_blockcipher_all_tests(ts_params->mbuf_pool,
+		ts_params->op_mpool, ts_params->valid_devs[0],
+		RTE_CRYPTODEV_QAT_SYM_PMD,
+		BLKCIPHER_AES_CIPHERONLY_TYPE);
+
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return TEST_SUCCESS;
+}
+
+static int
 test_authonly_openssl_all(void)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -6032,6 +6048,8 @@ static struct unit_test_suite cryptodev_qat_testsuite  = {
 				test_multi_session),
 
 		TEST_CASE_ST(ut_setup, ut_teardown, test_AES_chain_qat_all),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+						test_AES_cipheronly_qat_all),
 		TEST_CASE_ST(ut_setup, ut_teardown, test_3DES_chain_qat_all),
 		TEST_CASE_ST(ut_setup, ut_teardown,
 						test_3DES_cipheronly_qat_all),
diff --git a/app/test/test_cryptodev_aes_test_vectors.h b/app/test/test_cryptodev_aes_test_vectors.h
index 1c68f93..efbe7da 100644
--- a/app/test/test_cryptodev_aes_test_vectors.h
+++ b/app/test/test_cryptodev_aes_test_vectors.h
@@ -1024,73 +1024,85 @@ static const struct blockcipher_test_case aes_cipheronly_test_cases[] = {
 		.test_descr = "AES-128-CBC Encryption",
 		.test_data = &aes_test_data_4,
 		.op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
-		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
 		.test_descr = "AES-128-CBC Decryption",
 		.test_data = &aes_test_data_4,
 		.op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
-		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
 		.test_descr = "AES-192-CBC Encryption",
 		.test_data = &aes_test_data_10,
 		.op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
-		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
 		.test_descr = "AES-192-CBC Decryption",
 		.test_data = &aes_test_data_10,
 		.op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
-		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
 		.test_descr = "AES-256-CBC Encryption",
 		.test_data = &aes_test_data_11,
 		.op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
-		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
 		.test_descr = "AES-256-CBC Decryption",
 		.test_data = &aes_test_data_11,
 		.op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
-		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
 		.test_descr = "AES-128-CTR Encryption",
 		.test_data = &aes_test_data_1,
 		.op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
-		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
 		.test_descr = "AES-128-CTR Decryption",
 		.test_data = &aes_test_data_1,
 		.op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
-		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
 		.test_descr = "AES-192-CTR Encryption",
 		.test_data = &aes_test_data_2,
 		.op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
-		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
 		.test_descr = "AES-192-CTR Decryption",
 		.test_data = &aes_test_data_2,
 		.op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
-		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
 		.test_descr = "AES-256-CTR Encryption",
 		.test_data = &aes_test_data_3,
 		.op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
-		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
 		.test_descr = "AES-256-CTR Decryption",
 		.test_data = &aes_test_data_3,
 		.op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
-		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 };
 
diff --git a/app/test/test_cryptodev_perf.c b/app/test/test_cryptodev_perf.c
index 59a6891..7751ff2 100644
--- a/app/test/test_cryptodev_perf.c
+++ b/app/test/test_cryptodev_perf.c
@@ -166,15 +166,15 @@ test_perf_set_crypto_op_snow3g(struct rte_crypto_op *op, struct rte_mbuf *m,
 static inline struct rte_crypto_op *
 test_perf_set_crypto_op_aes(struct rte_crypto_op *op, struct rte_mbuf *m,
 		struct rte_cryptodev_sym_session *sess, unsigned int data_len,
-		unsigned int digest_len);
+		unsigned int digest_len, enum chain_mode chain);
 static inline struct rte_crypto_op *
 test_perf_set_crypto_op_aes_gcm(struct rte_crypto_op *op, struct rte_mbuf *m,
 		struct rte_cryptodev_sym_session *sess, unsigned int data_len,
-		unsigned int digest_len);
+		unsigned int digest_len, enum chain_mode chain __rte_unused);
 static inline struct rte_crypto_op *
 test_perf_set_crypto_op_3des(struct rte_crypto_op *op, struct rte_mbuf *m,
 		struct rte_cryptodev_sym_session *sess, unsigned int data_len,
-		unsigned int digest_len);
+		unsigned int digest_len, enum chain_mode chain __rte_unused);
 static uint32_t get_auth_digest_length(enum rte_crypto_auth_algorithm algo);
 
 
@@ -2285,7 +2285,8 @@ test_perf_openssl_optimise_cyclecount(struct perf_test_params *pparams)
 	static struct rte_crypto_op *(*test_perf_set_crypto_op)
 			(struct rte_crypto_op *, struct rte_mbuf *,
 					struct rte_cryptodev_sym_session *,
-					unsigned int, unsigned int);
+					unsigned int, unsigned int,
+					enum chain_mode);
 
 	unsigned int digest_length = get_auth_digest_length(pparams->auth_algo);
 
@@ -2323,14 +2324,14 @@ test_perf_openssl_optimise_cyclecount(struct perf_test_params *pparams)
 			break;
 		case RTE_CRYPTO_CIPHER_AES_GCM:
 			test_perf_set_crypto_op =
-					test_perf_set_crypto_op_aes_gcm;
+						test_perf_set_crypto_op_aes_gcm;
 			break;
 		default:
 			return TEST_FAILED;
 		}
 
 		op = test_perf_set_crypto_op(op, m, sess, pparams->buf_size,
-				digest_length);
+				digest_length, pparams->chain);
 		TEST_ASSERT_NOT_NULL(op, "Failed to attach op to session");
 
 		c_ops[i] = op;
@@ -2539,16 +2540,16 @@ test_perf_create_aes_sha_session(uint8_t dev_id, enum chain_mode chain,
 
 	cipher_xform.cipher.key.data = aes_key;
 	cipher_xform.cipher.key.length = cipher_key_len;
-
-	/* Setup HMAC Parameters */
-	auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
-	auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
-	auth_xform.auth.algo = auth_algo;
-
-	auth_xform.auth.key.data = hmac_sha_key;
-	auth_xform.auth.key.length =  get_auth_key_max_length(auth_algo);
-	auth_xform.auth.digest_length = get_auth_digest_length(auth_algo);
-
+	if (chain != CIPHER_ONLY) {
+		/* Setup HMAC Parameters */
+		auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+		auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
+		auth_xform.auth.algo = auth_algo;
+		auth_xform.auth.key.data = hmac_sha_key;
+		auth_xform.auth.key.length = get_auth_key_max_length(auth_algo);
+		auth_xform.auth.digest_length =
+					get_auth_digest_length(auth_algo);
+	}
 	switch (chain) {
 	case CIPHER_HASH:
 		cipher_xform.next = &auth_xform;
@@ -2560,6 +2561,10 @@ test_perf_create_aes_sha_session(uint8_t dev_id, enum chain_mode chain,
 		cipher_xform.next = NULL;
 		/* Create Crypto session*/
 		return rte_cryptodev_sym_session_create(dev_id,	&auth_xform);
+	case CIPHER_ONLY:
+		cipher_xform.next = NULL;
+		/* Create Crypto session*/
+		return rte_cryptodev_sym_session_create(dev_id,	&cipher_xform);
 	default:
 		return NULL;
 	}
@@ -2706,8 +2711,8 @@ test_perf_create_pktmbuf(struct rte_mempool *mpool, unsigned buf_sz)
 
 static inline struct rte_crypto_op *
 test_perf_set_crypto_op_aes(struct rte_crypto_op *op, struct rte_mbuf *m,
-		struct rte_cryptodev_sym_session *sess, unsigned data_len,
-		unsigned digest_len)
+		struct rte_cryptodev_sym_session *sess, unsigned int data_len,
+		unsigned int digest_len, enum chain_mode chain)
 {
 	if (rte_crypto_op_attach_sym_session(op, sess) != 0) {
 		rte_crypto_op_free(op);
@@ -2715,13 +2720,26 @@ test_perf_set_crypto_op_aes(struct rte_crypto_op *op, struct rte_mbuf *m,
 	}
 
 	/* Authentication Parameters */
-	op->sym->auth.digest.data = rte_pktmbuf_mtod_offset(m, uint8_t *,
-			AES_CIPHER_IV_LENGTH + data_len);
-	op->sym->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset(m,
-			AES_CIPHER_IV_LENGTH + data_len);
-	op->sym->auth.digest.length = digest_len;
-	op->sym->auth.aad.data = aes_iv;
-	op->sym->auth.aad.length = AES_CIPHER_IV_LENGTH;
+	if (chain == CIPHER_ONLY) {
+		op->sym->auth.digest.data = NULL;
+		op->sym->auth.digest.phys_addr = 0;
+		op->sym->auth.digest.length = 0;
+		op->sym->auth.aad.data = NULL;
+		op->sym->auth.aad.length = 0;
+		op->sym->auth.data.offset = 0;
+		op->sym->auth.data.length = 0;
+	} else {
+		op->sym->auth.digest.data = rte_pktmbuf_mtod_offset(m,
+				 uint8_t *, AES_CIPHER_IV_LENGTH + data_len);
+		op->sym->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset(m,
+				AES_CIPHER_IV_LENGTH + data_len);
+		op->sym->auth.digest.length = digest_len;
+		op->sym->auth.aad.data = aes_iv;
+		op->sym->auth.aad.length = AES_CIPHER_IV_LENGTH;
+		op->sym->auth.data.offset = AES_CIPHER_IV_LENGTH;
+		op->sym->auth.data.length = data_len;
+	}
+
 
 	/* Cipher Parameters */
 	op->sym->cipher.iv.data = rte_pktmbuf_mtod(m, uint8_t *);
@@ -2730,10 +2748,6 @@ test_perf_set_crypto_op_aes(struct rte_crypto_op *op, struct rte_mbuf *m,
 
 	rte_memcpy(op->sym->cipher.iv.data, aes_iv, AES_CIPHER_IV_LENGTH);
 
-	/* Data lengths/offsets Parameters */
-	op->sym->auth.data.offset = AES_CIPHER_IV_LENGTH;
-	op->sym->auth.data.length = data_len;
-
 	op->sym->cipher.data.offset = AES_CIPHER_IV_LENGTH;
 	op->sym->cipher.data.length = data_len;
 
@@ -2745,7 +2759,7 @@ test_perf_set_crypto_op_aes(struct rte_crypto_op *op, struct rte_mbuf *m,
 static inline struct rte_crypto_op *
 test_perf_set_crypto_op_aes_gcm(struct rte_crypto_op *op, struct rte_mbuf *m,
 		struct rte_cryptodev_sym_session *sess, unsigned int data_len,
-		unsigned int digest_len)
+		unsigned int digest_len, enum chain_mode chain __rte_unused)
 {
 	if (rte_crypto_op_attach_sym_session(op, sess) != 0) {
 		rte_crypto_op_free(op);
@@ -2878,7 +2892,7 @@ test_perf_set_crypto_op_snow3g_hash(struct rte_crypto_op *op,
 static inline struct rte_crypto_op *
 test_perf_set_crypto_op_3des(struct rte_crypto_op *op, struct rte_mbuf *m,
 		struct rte_cryptodev_sym_session *sess, unsigned int data_len,
-		unsigned int digest_len)
+		unsigned int digest_len, enum chain_mode chain __rte_unused)
 {
 	if (rte_crypto_op_attach_sym_session(op, sess) != 0) {
 		rte_crypto_op_free(op);
@@ -2961,8 +2975,10 @@ test_perf_aes_sha(uint8_t dev_id, uint16_t queue_id,
 				rte_pktmbuf_free(mbufs[k]);
 			return -1;
 		}
+
 		/* Make room for Digest and IV in mbuf */
-		rte_pktmbuf_append(mbufs[i], digest_length);
+		if (pparams->chain != CIPHER_ONLY)
+			rte_pktmbuf_append(mbufs[i], digest_length);
 		rte_pktmbuf_prepend(mbufs[i], AES_CIPHER_IV_LENGTH);
 	}
 
@@ -2984,7 +3000,8 @@ test_perf_aes_sha(uint8_t dev_id, uint16_t queue_id,
 				ops[i] = test_perf_set_crypto_op_aes(ops[i],
 					mbufs[i + (pparams->burst_size *
 						(j % NUM_MBUF_SETS))],
-					sess, pparams->buf_size, digest_length);
+					sess, pparams->buf_size, digest_length,
+					pparams->chain);
 
 			/* enqueue burst */
 			burst_enqueued = rte_cryptodev_enqueue_burst(dev_id,
@@ -3233,7 +3250,8 @@ test_perf_openssl(uint8_t dev_id, uint16_t queue_id,
 	static struct rte_crypto_op *(*test_perf_set_crypto_op)
 			(struct rte_crypto_op *, struct rte_mbuf *,
 					struct rte_cryptodev_sym_session *,
-					unsigned int, unsigned int);
+					unsigned int, unsigned int,
+					enum chain_mode);
 
 	switch (pparams->cipher_algo) {
 	case RTE_CRYPTO_CIPHER_3DES_CBC:
@@ -3294,7 +3312,8 @@ test_perf_openssl(uint8_t dev_id, uint16_t queue_id,
 				ops[i] = test_perf_set_crypto_op(ops[i],
 					mbufs[i + (pparams->burst_size *
 						(j % NUM_MBUF_SETS))],
-					sess, pparams->buf_size, digest_length);
+					sess, pparams->buf_size, digest_length,
+					pparams->chain);
 
 			/* enqueue burst */
 			burst_enqueued = rte_cryptodev_enqueue_burst(dev_id,
@@ -3380,8 +3399,13 @@ test_perf_aes_cbc_encrypt_digest_vary_pkt_size(void)
 
 	struct perf_test_params params_set[] = {
 		{
+			.chain = CIPHER_ONLY,
+			.cipher_algo  = RTE_CRYPTO_CIPHER_AES_CBC,
+			.cipher_key_length = 16,
+			.auth_algo = RTE_CRYPTO_AUTH_NULL
+		},
+		{
 			.chain = CIPHER_HASH,
-
 			.cipher_algo  = RTE_CRYPTO_CIPHER_AES_CBC,
 			.cipher_key_length = 16,
 			.auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC
diff --git a/doc/guides/cryptodevs/qat.rst b/doc/guides/cryptodevs/qat.rst
index 52a9ae3..607d244 100644
--- a/doc/guides/cryptodevs/qat.rst
+++ b/doc/guides/cryptodevs/qat.rst
@@ -75,7 +75,6 @@ Limitations
 
 * Chained mbufs are not supported.
 * Hash only is not supported except SNOW 3G UIA2 and KASUMI F9.
-* Cipher only is not supported except SNOW 3G UEA2, KASUMI F8 and 3DES.
 * Only supports the session-oriented API implementation (session-less APIs are not supported).
 * SNOW 3G (UEA2) and KASUMI (F8) supported only if cipher length, cipher offset fields are byte-aligned.
 * SNOW 3G (UIA2) and KASUMI (F9) supported only if hash length, hash offset fields are byte-aligned.
-- 
2.5.0

^ permalink raw reply related

* Re: [PATCH] doc: introduce PVP reference benchmark
From: Mcnamara, John @ 2016-11-24 17:38 UTC (permalink / raw)
  To: Maxime Coquelin, yuanhan.liu@linux.intel.com,
	thomas.monjalon@6wind.com, Yang, Zhiyong, dev@dpdk.org
  Cc: fbaudin@redhat.com
In-Reply-To: <20161123210006.7113-1-maxime.coquelin@redhat.com>

> -----Original Message-----
> From: Maxime Coquelin [mailto:maxime.coquelin@redhat.com]
> Sent: Wednesday, November 23, 2016 9:00 PM
> To: yuanhan.liu@linux.intel.com; thomas.monjalon@6wind.com; Mcnamara, John
> <john.mcnamara@intel.com>; Yang, Zhiyong <zhiyong.yang@intel.com>;
> dev@dpdk.org
> Cc: fbaudin@redhat.com; Maxime Coquelin <maxime.coquelin@redhat.com>
> Subject: [PATCH] doc: introduce PVP reference benchmark
> 
> Having reference benchmarks is important in order to obtain reproducible
> performance figures.
> 
> This patch describes required steps to configure a PVP setup using testpmd
> in both host and guest.
> 
> Not relying on external vSwitch ease integration in a CI loop by not being
> impacted by DPDK API changes.

Hi Maxime,

Thanks for the detailed doc and this initiative. Some minor documentation
comments below.



> +
> +Setup overview
> +..............

This level header should be ---------, even if it looks like dots in the
contribution guide:

    http://dpdk.org/doc/guides/contributing/documentation.html#section-headers


> +
> +.. figure:: img/pvp_2nics.svg
> +
> +  PVP setup using 2 NICs
> +

The figure needs a target so it can be used with :numref:, like this:

.. _figure_pvp_2nics:

.. figure:: img/pvp_2nics.*

   PVP setup using 2 NICs


> +DPDK build
> +~~~~~~~~~~
> +

Put a one line description at the start of each section, even if it is just: Build DPDK:



> +Testpmd launch
> +~~~~~~~~~~~~~~
> +
> +#. Assign NICs to DPDK:
> +
> +   .. code-block:: console
> +
> +    modprobe vfio-pci
> +    $RTE_SDK/install/sbin/dpdk-devbind -b vfio-pci 0000:11:00.0
> + 0000:11:00.1
> +
> +*Note: Sandy Bridge family seems to have some limitations wrt its
> +IOMMU, giving poor performance results. To achieve good performance on
> +these machines, consider using UIO instead.*

This would be better as an RST note:

#. Assign NICs to DPDK:

   .. code-block:: console

      modprobe vfio-pci
      $RTE_SDK/install/sbin/dpdk-devbind -b vfio-pci 0000:11:00.0 0000:11:00.1

   .. Note::

      The Sandy Bridge family seems to have some IOMMU limitations giving poor
      performance results. To achieve good performance on these machines
      consider using UIO instead.



> +First, SELinux policy needs to be set to permissiven, as testpmd is run
> +as root (reboot required):

s/permissiven/permissive/


There are a couple of trailing whitespace errors as well at build as well.


John

^ permalink raw reply

* Re: [PATCH v2] ethdev: check number of queues less than RTE_ETHDEV_QUEUE_STAT_CNTRS
From: Olivier Matz @ 2016-11-24 16:59 UTC (permalink / raw)
  To: Alejandro Lucero, dev; +Cc: Bert van Leeuwen, thomas.monjalon
In-Reply-To: <1479722378-23959-1-git-send-email-alejandro.lucero@netronome.com>

Hi,

On Mon, 2016-11-21 at 09:59 +0000, Alejandro Lucero wrote:
> From: Bert van Leeuwen <bert.vanleeuwen@netronome.com>
> 
> Arrays inside rte_eth_stats have size=RTE_ETHDEV_QUEUE_STAT_CNTRS.
> Some devices report more queues than that and this code blindly uses
> the reported number of queues by the device to fill those arrays up.
> This patch fixes the problem using MIN between the reported number of
> queues and RTE_ETHDEV_QUEUE_STAT_CNTRS.
> 
> Signed-off-by: Alejandro Lucero <alejandro.lucero@netronome.com>
> 

Reviewed-by: Olivier Matz <olivier.matz@6wind.com>


As a next step, I'm wondering if it would be possible to remove
this limitation. We could replace the tables in struct rte_eth_stats
by a pointer to an array allocated dynamically at pmd setup.

It would break the API, so it should be announced first. I'm thinking
of something like:

struct rte_eth_generic_stats {
        uint64_t ipackets;
        uint64_t opackets;
        uint64_t ibytes;
        uint64_t obytes;
        uint64_t imissed;
        uint64_t ierrors;
        uint64_t oerrors;
        uint64_t rx_nombuf
};

struct rte_eth_stats {
	struct rte_eth_generic_stats port_stats;
	struct rte_eth_generic_stats *queue_stats;
};

The queue_stats array would always be indexed by queue_id.
The xstats would continue to report the generic stats per-port and
per-queue.

About the mapping API, either we keep it as-is, or it could
become a driver-specific API.


Thomas, what do you think?

Regards,
Olivier

^ permalink raw reply

* Re: [PATCH 1/4] eventdev: introduce event driven programming model
From: Bruce Richardson @ 2016-11-24 16:24 UTC (permalink / raw)
  To: Jerin Jacob; +Cc: dev, harry.van.haaren, hemant.agrawal, gage.eads
In-Reply-To: <1479447902-3700-2-git-send-email-jerin.jacob@caviumnetworks.com>

On Fri, Nov 18, 2016 at 11:14:59AM +0530, Jerin Jacob wrote:
> In a polling model, lcores poll ethdev ports and associated
> rx queues directly to look for packet. In an event driven model,
> by contrast, lcores call the scheduler that selects packets for
> them based on programmer-specified criteria. Eventdev library
> adds support for event driven programming model, which offer
> applications automatic multicore scaling, dynamic load balancing,
> pipelining, packet ingress order maintenance and
> synchronization services to simplify application packet processing.
> 
> By introducing event driven programming model, DPDK can support
> both polling and event driven programming models for packet processing,
> and applications are free to choose whatever model
> (or combination of the two) that best suits their needs.
> 
> Signed-off-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
> ---

Hi Jerin,

Thanks for the patchset. A few minor comments in general on the API that
we found from working with it (thus far - more may follow :-) ).

1. Priorities: priorities are used in a number of places in the API, but
   all are uint8_t types and have their own MAX/NORMAL/MIN values. I think
   it would be simpler for the user just to have one priority type in the
   library, and use that everywhere. I suggest using RTE_EVENT_PRIORITY_*
   and drop the separate defines for SERVICE_PRIORITY, and QUEUE_PRIORITY
   etc. Ideally, I'd see things like this converted to enums too, rather
   than defines, but I'm not sure it's possible in this case.

2. Functions for config and setup can have their structure parameter
   types as const as they don't/shouldn't change the values internally.
   So add "const" to parameters to:
     rte_event_dev_configure()
     rte_event_queue_setup()
     rte_event_port_setup()
     rte_event_port_link()

3. in event schedule() function, the dev->schedule() function needs the
   dev instance pointer passed in as parameter.

4. The event op values and the event type values would be better as
   enums rather than as a set of #defines.

Regards,
/Bruce

^ permalink raw reply

* Re: [PATCH 00/56] Solarflare libefx-based PMD
From: Andrew Rybchenko @ 2016-11-24 16:15 UTC (permalink / raw)
  To: Ferruh Yigit, dev
In-Reply-To: <bf2e928f-2f19-ab64-247a-bbc3242ad5c6@intel.com>

On 11/23/2016 06:29 PM, Ferruh Yigit wrote:
> On 11/21/2016 3:00 PM, Andrew Rybchenko wrote:
>> The patch series adds Solarflare libefx-based network PMD.
>>
>> This version of the driver supports Solarflare SFN7xxx and SFN8xxx
>> families of 10/40 Gbps adapters.
>>
>> libefx is a platform-independent library to implement drivers for
>> Solarflare network adapters. It provides unified adapter family
>> independent interface (if possible). FreeBSD [1] and illumos [2]
>> drivers are built on top of the library.
>>
>> The patch series could be logically structured into 5 sub-series:
>>   1. (1) add the driver skeleton including documentation
>>   2. (2-30) import libefx and include it in build with the latest patch
>>   3. (31-43) implement minimal device level operations in steps
>>   4. (44-51) implement Rx subsystem
>>   5. (52-56) implement Tx subsystem
>>
>> Functional driver with multi-queue support capable to send and receive
>> traffic appears with the last patch in the series.
>>
>> The following design decisions are made during development:
>>
>>   1. Since libefx uses positive errno return codes, positive errno
>>      return codes are used inside the driver and coversion to negative
>>      is done on return from eth_dev_ops callbacks. We think that it
>>      is the less error-prone way.
>>
>>   2. Another Solarflare PMD with in-kernel part (for control operations)
>>      is considered and could be added in the future. Code for data path
>>      should be shared by these two drivers. libefx-based PMD is put into
>>      'efx' subdirectory to have a space for another PMD and shared code.
>>
>>   3. Own event queue (a way to deliver events from HW to host CPU) is
>>      used for house-keeping (e.g. link status notifications), each Tx
>>      and each Rx queue. No locks on datapath are requires in this case.
>>
>>   4. Alarm is used to periodically poll house-keeping event queue.
>>      The event queue is used to deliver link status change notifications,
>>      Rx/Tx queue flush events, SRAM events. It is not used on datapath.
>>      The event queue polling is protected using spin-lock since
>>      concurrent access from different contexts is possible (e.g. device
>>      stop when polling alarm is running).
>>
>> [1] https://svnweb.freebsd.org/base/head/sys/dev/sfxge/common/
>> [2] https://github.com/illumos/illumos-gate/tree/master/usr/src/uts/common/io/sfxge/common/
>>
>> ---
> I would like to note that very well organized patchset. Thank you for
> your effort.

Thanks a lot, it is very pleasant to read it.

Please, see my questions in thread for patches 01/56 (about compiler
versions to test on) and 30/56 (about libefx configuration documentation).

Also I'd like to ask a question about the further patches submission.
We have about 40 patches which support various features (RSS, stats,
flow control and many others). What is the preferred way to submit it?
A. Separately since they are not so tightly related (but in fact cannot be
applied in random order since some touch the same lines in code)
B. As a series to process everything in one go.

Thanks,
Andrew.

^ permalink raw reply

* [PATCH 7/7] net/mlx5: remove inefficient prefetching
From: Nelio Laranjeiro @ 2016-11-24 16:03 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon, Adrien Mazarguil
In-Reply-To: <cover.1479995764.git.nelio.laranjeiro@6wind.com>

Prefetching completion queue entries is inefficient because too few CPU
cycles are spent before their use, which results into cache misses anyway.

Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
 drivers/net/mlx5/mlx5_rxtx.c | 21 ---------------------
 1 file changed, 21 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index 4b8c197..9f74fd4 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -348,23 +348,6 @@ mlx5_tx_dbrec(struct txq *txq)
 }
 
 /**
- * Prefetch a CQE.
- *
- * @param txq
- *   Pointer to TX queue structure.
- * @param cqe_ci
- *   CQE consumer index.
- */
-static inline void
-tx_prefetch_cqe(struct txq *txq, uint16_t ci)
-{
-	volatile struct mlx5_cqe *cqe;
-
-	cqe = &(*txq->cqes)[ci & ((1 << txq->cqe_n) - 1)];
-	rte_prefetch0(cqe);
-}
-
-/**
  * DPDK callback for TX.
  *
  * @param dpdk_txq
@@ -395,8 +378,6 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 	if (unlikely(!pkts_n))
 		return 0;
 	/* Prefetch first packet cacheline. */
-	tx_prefetch_cqe(txq, txq->cq_ci);
-	tx_prefetch_cqe(txq, txq->cq_ci + 1);
 	rte_prefetch0(*pkts);
 	/* Start processing. */
 	txq_complete(txq);
@@ -733,7 +714,6 @@ mlx5_tx_burst_mpw(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 	if (unlikely(!pkts_n))
 		return 0;
 	/* Prefetch first packet cacheline. */
-	tx_prefetch_cqe(txq, txq->cq_ci);
 	rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci));
 	rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci + 1));
 	/* Start processing. */
@@ -938,7 +918,6 @@ mlx5_tx_burst_mpw_inline(void *dpdk_txq, struct rte_mbuf **pkts,
 	if (unlikely(!pkts_n))
 		return 0;
 	/* Prefetch first packet cacheline. */
-	tx_prefetch_cqe(txq, txq->cq_ci);
 	rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci));
 	rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci + 1));
 	/* Start processing. */
-- 
2.1.4

^ permalink raw reply related

* [PATCH 6/7] net/mlx5: optimize copy of Ethernet header
From: Nelio Laranjeiro @ 2016-11-24 16:03 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon, Adrien Mazarguil
In-Reply-To: <cover.1479995764.git.nelio.laranjeiro@6wind.com>

Use fewer instructions to copy the first two bytes of Ethernet headers to
work queue elements.

Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
 drivers/net/mlx5/mlx5_rxtx.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index 0d0b807..4b8c197 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -409,7 +409,7 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 		unsigned int ds = 0;
 		uintptr_t addr;
 		uint16_t pkt_inline_sz = MLX5_WQE_DWORD_SIZE;
-		uint8_t ehdr[2];
+		uint16_t ehdr;
 		uint8_t cs_flags = 0;
 #ifdef MLX5_PMD_SOFT_COUNTERS
 		uint32_t total_length = 0;
@@ -436,8 +436,8 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 			rte_prefetch0(*pkts);
 		addr = rte_pktmbuf_mtod(buf, uintptr_t);
 		length = DATA_LEN(buf);
-		ehdr[0] = ((uint8_t *)addr)[0];
-		ehdr[1] = ((uint8_t *)addr)[1];
+		ehdr = (((uint8_t *)addr)[1] << 8) |
+		       ((uint8_t *)addr)[0];
 #ifdef MLX5_PMD_SOFT_COUNTERS
 		total_length = length;
 #endif
@@ -600,8 +600,7 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 			0,
 			cs_flags,
 			0,
-			(ehdr[1] << 24) | (ehdr[0] << 16) |
-			htons(pkt_inline_sz),
+			(ehdr << 16) | htons(pkt_inline_sz),
 		};
 		txq->wqe_ci += (ds + 3) / 4;
 #ifdef MLX5_PMD_SOFT_COUNTERS
-- 
2.1.4

^ permalink raw reply related

* [PATCH 5/7] net/mlx5: move static prototype
From: Nelio Laranjeiro @ 2016-11-24 16:03 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon, Adrien Mazarguil
In-Reply-To: <cover.1479995764.git.nelio.laranjeiro@6wind.com>

Gather function prototypes at the beginning of the file.

Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
 drivers/net/mlx5/mlx5_rxtx.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index 52733da..0d0b807 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -76,6 +76,9 @@ check_cqe(volatile struct mlx5_cqe *cqe,
 	  unsigned int cqes_n, const uint16_t ci)
 	  __attribute__((always_inline));
 
+static inline void
+txq_complete(struct txq *txq) __attribute__((always_inline));
+
 static inline uint32_t
 txq_mp2mr(struct txq *txq, struct rte_mempool *mp)
 	__attribute__((always_inline));
@@ -192,9 +195,6 @@ tx_mlx5_wqe(struct txq *txq, uint16_t ci)
 	return (uintptr_t *)((uintptr_t)txq->wqes + ci * MLX5_WQE_SIZE);
 }
 
-static inline void
-txq_complete(struct txq *txq) __attribute__((always_inline));
-
 /**
  * Manage TX completions.
  *
-- 
2.1.4

^ permalink raw reply related

* [PATCH 4/7] net/mlx5: fix missing inline attributes
From: Nelio Laranjeiro @ 2016-11-24 16:03 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon, Adrien Mazarguil, stable
In-Reply-To: <cover.1479995764.git.nelio.laranjeiro@6wind.com>

These functions must be forced inline for better performance.

Fixes: 99c12dcca65d ("net/mlx5: handle Rx CQE compression")
Fixes: 1d88ba171942 ("net/mlx5: refactor Tx data path")
Fixes: 67fa62bc672d ("mlx5: support checksum offload")

CC: stable@dpdk.org
Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
 drivers/net/mlx5/mlx5_rxtx.c | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index e161cd9..52733da 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -71,6 +71,31 @@
 #include "mlx5_defs.h"
 #include "mlx5_prm.h"
 
+static inline int
+check_cqe(volatile struct mlx5_cqe *cqe,
+	  unsigned int cqes_n, const uint16_t ci)
+	  __attribute__((always_inline));
+
+static inline uint32_t
+txq_mp2mr(struct txq *txq, struct rte_mempool *mp)
+	__attribute__((always_inline));
+
+static inline void
+mlx5_tx_dbrec(struct txq *txq) __attribute__((always_inline));
+
+static inline uint32_t
+rxq_cq_to_pkt_type(volatile struct mlx5_cqe *cqe)
+	__attribute__((always_inline));
+
+static inline int
+mlx5_rx_poll_len(struct rxq *rxq, volatile struct mlx5_cqe *cqe,
+		 uint16_t cqe_cnt, uint32_t *rss_hash)
+		 __attribute__((always_inline));
+
+static inline uint32_t
+rxq_cq_to_ol_flags(struct rxq *rxq, volatile struct mlx5_cqe *cqe)
+		   __attribute__((always_inline));
+
 #ifndef NDEBUG
 
 /**
@@ -100,11 +125,6 @@ check_cqe_seen(volatile struct mlx5_cqe *cqe)
 
 #endif /* NDEBUG */
 
-static inline int
-check_cqe(volatile struct mlx5_cqe *cqe,
-	  unsigned int cqes_n, const uint16_t ci)
-	  __attribute__((always_inline));
-
 /**
  * Check whether CQE is valid.
  *
@@ -266,10 +286,6 @@ txq_mb2mp(struct rte_mbuf *buf)
 	return buf->pool;
 }
 
-static inline uint32_t
-txq_mp2mr(struct txq *txq, struct rte_mempool *mp)
-	__attribute__((always_inline));
-
 /**
  * Get Memory Region (MR) <-> Memory Pool (MP) association from txq->mp2mr[].
  * Add MP to txq->mp2mr[] if it's not registered yet. If mp2mr[] is full,
-- 
2.1.4

^ permalink raw reply related

* [PATCH 3/7] net/mlx5: use vector types to speed up processing
From: Nelio Laranjeiro @ 2016-11-24 16:03 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon, Adrien Mazarguil
In-Reply-To: <cover.1479995764.git.nelio.laranjeiro@6wind.com>

Let compiler automatically use the vector capabilities of the target
machine to optimize instructions.

Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
 drivers/net/mlx5/mlx5_prm.h  |  7 +++++
 drivers/net/mlx5/mlx5_rxtx.c | 74 +++++++++++++++++++++++---------------------
 2 files changed, 46 insertions(+), 35 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_prm.h b/drivers/net/mlx5/mlx5_prm.h
index 3dd4cbe..9cd9fdf 100644
--- a/drivers/net/mlx5/mlx5_prm.h
+++ b/drivers/net/mlx5/mlx5_prm.h
@@ -44,6 +44,7 @@
 #pragma GCC diagnostic error "-Wpedantic"
 #endif
 
+#include <rte_vect.h>
 #include "mlx5_autoconf.h"
 
 /* Get CQE owner bit. */
@@ -134,6 +135,12 @@ struct mlx5_wqe {
 	struct mlx5_wqe_eth_seg_small eseg;
 };
 
+/* Vectorize WQE header. */
+struct mlx5_wqe_v {
+	rte_v128u32_t ctrl;
+	rte_v128u32_t eseg;
+};
+
 /* WQE. */
 struct mlx5_wqe64 {
 	struct mlx5_wqe hdr;
diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index ada8e74..e161cd9 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -371,7 +371,7 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 	unsigned int j = 0;
 	unsigned int max;
 	unsigned int comp;
-	volatile struct mlx5_wqe *wqe = NULL;
+	volatile struct mlx5_wqe_v *wqe = NULL;
 	unsigned int segs_n = 0;
 	struct rte_mbuf *buf = NULL;
 	uint8_t *raw;
@@ -388,12 +388,13 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 	if (max > elts_n)
 		max -= elts_n;
 	do {
-		volatile struct mlx5_wqe_data_seg *dseg = NULL;
+		volatile rte_v128u32_t *dseg = NULL;
 		uint32_t length;
 		unsigned int ds = 0;
 		uintptr_t addr;
 		uint16_t pkt_inline_sz = MLX5_WQE_DWORD_SIZE;
 		uint8_t ehdr[2];
+		uint8_t cs_flags = 0;
 #ifdef MLX5_PMD_SOFT_COUNTERS
 		uint32_t total_length = 0;
 #endif
@@ -412,7 +413,7 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 		--segs_n;
 		if (!segs_n)
 			--pkts_n;
-		wqe = (volatile struct mlx5_wqe *)
+		wqe = (volatile struct mlx5_wqe_v *)
 			tx_mlx5_wqe(txq, txq->wqe_ci);
 		rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci + 1));
 		if (pkts_n > 1)
@@ -438,11 +439,7 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 		/* Should we enable HW CKSUM offload */
 		if (buf->ol_flags &
 		    (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM)) {
-			wqe->eseg.cs_flags =
-				MLX5_ETH_WQE_L3_CSUM |
-				MLX5_ETH_WQE_L4_CSUM;
-		} else {
-			wqe->eseg.cs_flags = 0;
+			cs_flags = MLX5_ETH_WQE_L3_CSUM | MLX5_ETH_WQE_L4_CSUM;
 		}
 		raw = ((uint8_t *)(uintptr_t)wqe) + 2 * MLX5_WQE_DWORD_SIZE;
 		/*
@@ -498,12 +495,11 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 			 */
 			ds = 2 + MLX5_WQE_DS(pkt_inline_sz - 2);
 			if (length > 0) {
-				dseg = (volatile struct mlx5_wqe_data_seg *)
+				dseg = (volatile rte_v128u32_t *)
 					((uintptr_t)wqe +
 					 (ds * MLX5_WQE_DWORD_SIZE));
 				if ((uintptr_t)dseg >= end)
-					dseg = (volatile struct
-						mlx5_wqe_data_seg *)
+					dseg = (volatile rte_v128u32_t *)
 					       txq->wqes;
 				goto use_dseg;
 			} else if (!segs_n) {
@@ -516,16 +512,17 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 			 * No inline has been done in the packet, only the
 			 * Ethernet Header as been stored.
 			 */
-			wqe->eseg.inline_hdr_sz = htons(MLX5_WQE_DWORD_SIZE);
-			dseg = (volatile struct mlx5_wqe_data_seg *)
+			dseg = (volatile rte_v128u32_t *)
 				((uintptr_t)wqe + (3 * MLX5_WQE_DWORD_SIZE));
 			ds = 3;
 use_dseg:
 			/* Add the remaining packet as a simple ds. */
-			*dseg = (volatile struct mlx5_wqe_data_seg) {
-				.addr = htonll(addr),
-				.byte_count = htonl(length),
-				.lkey = txq_mp2mr(txq, txq_mb2mp(buf)),
+			addr = htonll(addr);
+			*dseg = (rte_v128u32_t){
+				htonl(length),
+				txq_mp2mr(txq, txq_mb2mp(buf)),
+				addr,
+				addr >> 32,
 			};
 			++ds;
 			if (!segs_n)
@@ -545,7 +542,7 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 			unsigned int n = (txq->wqe_ci + ((ds + 3) / 4)) &
 				((1 << txq->wqe_n) - 1);
 
-			dseg = (volatile struct mlx5_wqe_data_seg *)
+			dseg = (volatile rte_v128u32_t *)
 			       tx_mlx5_wqe(txq, n);
 			rte_prefetch0(tx_mlx5_wqe(txq, n + 1));
 		} else {
@@ -559,10 +556,12 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 		total_length += length;
 #endif
 		/* Store segment information. */
-		*dseg = (volatile struct mlx5_wqe_data_seg) {
-			.addr = htonll(rte_pktmbuf_mtod(buf, uintptr_t)),
-			.byte_count = htonl(length),
-			.lkey = txq_mp2mr(txq, txq_mb2mp(buf)),
+		addr = htonll(rte_pktmbuf_mtod(buf, uintptr_t));
+		*dseg = (rte_v128u32_t){
+			htonl(length),
+			txq_mp2mr(txq, txq_mb2mp(buf)),
+			addr,
+			addr >> 32,
 		};
 		(*txq->elts)[elts_head] = buf;
 		elts_head = (elts_head + 1) & (elts_n - 1);
@@ -575,17 +574,19 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 next_pkt:
 		++i;
 		/* Initialize known and common part of the WQE structure. */
-		wqe->ctrl[0] = htonl((txq->wqe_ci << 8) | MLX5_OPCODE_SEND);
-		wqe->ctrl[1] = htonl(txq->qp_num_8s | ds);
-		wqe->ctrl[2] = 0;
-		wqe->ctrl[3] = 0;
-		wqe->eseg.rsvd0 = 0;
-		wqe->eseg.rsvd1 = 0;
-		wqe->eseg.mss = 0;
-		wqe->eseg.rsvd2 = 0;
-		wqe->eseg.inline_hdr_sz = htons(pkt_inline_sz);
-		wqe->eseg.inline_hdr[0] = ehdr[0];
-		wqe->eseg.inline_hdr[1] = ehdr[1];
+		wqe->ctrl = (rte_v128u32_t){
+			htonl((txq->wqe_ci << 8) | MLX5_OPCODE_SEND),
+			htonl(txq->qp_num_8s | ds),
+			0,
+			0,
+		};
+		wqe->eseg = (rte_v128u32_t){
+			0,
+			cs_flags,
+			0,
+			(ehdr[1] << 24) | (ehdr[0] << 16) |
+			htons(pkt_inline_sz),
+		};
 		txq->wqe_ci += (ds + 3) / 4;
 #ifdef MLX5_PMD_SOFT_COUNTERS
 		/* Increment sent bytes counter. */
@@ -598,10 +599,13 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 	/* Check whether completion threshold has been reached. */
 	comp = txq->elts_comp + i + j;
 	if (comp >= MLX5_TX_COMP_THRESH) {
+		volatile struct mlx5_wqe_ctrl *w =
+			(volatile struct mlx5_wqe_ctrl *)wqe;
+
 		/* Request completion on last WQE. */
-		wqe->ctrl[2] = htonl(8);
+		w->ctrl2 = htonl(8);
 		/* Save elts_head in unused "immediate" field of WQE. */
-		wqe->ctrl[3] = elts_head;
+		w->ctrl3 = elts_head;
 		txq->elts_comp = 0;
 	} else {
 		txq->elts_comp = comp;
-- 
2.1.4

^ permalink raw reply related

* [PATCH 2/7] net/mlx5: use work queue buffer as a raw buffer
From: Nelio Laranjeiro @ 2016-11-24 16:03 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon, Adrien Mazarguil
In-Reply-To: <cover.1479995764.git.nelio.laranjeiro@6wind.com>

Define a single work queue element type that encompasses them all.  It
includes control, Ethernet segment and raw data all grouped in a single
place.

Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
 drivers/net/mlx5/mlx5_prm.h  |  13 ++++--
 drivers/net/mlx5/mlx5_rxtx.c | 103 ++++++++++++++++++++++---------------------
 drivers/net/mlx5/mlx5_rxtx.h |   2 +-
 drivers/net/mlx5/mlx5_txq.c  |   8 ++--
 4 files changed, 68 insertions(+), 58 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_prm.h b/drivers/net/mlx5/mlx5_prm.h
index 7f31a2f..3dd4cbe 100644
--- a/drivers/net/mlx5/mlx5_prm.h
+++ b/drivers/net/mlx5/mlx5_prm.h
@@ -114,12 +114,19 @@ struct mlx5_wqe_eth_seg_small {
 	uint32_t rsvd2;
 	uint16_t inline_hdr_sz;
 	uint8_t inline_hdr[2];
-};
+} __rte_aligned(MLX5_WQE_DWORD_SIZE);
 
 struct mlx5_wqe_inl_small {
 	uint32_t byte_cnt;
 	uint8_t raw;
-};
+} __rte_aligned(MLX5_WQE_DWORD_SIZE);
+
+struct mlx5_wqe_ctrl {
+	uint32_t ctrl0;
+	uint32_t ctrl1;
+	uint32_t ctrl2;
+	uint32_t ctrl3;
+} __rte_aligned(MLX5_WQE_DWORD_SIZE);
 
 /* Small common part of the WQE. */
 struct mlx5_wqe {
@@ -131,7 +138,7 @@ struct mlx5_wqe {
 struct mlx5_wqe64 {
 	struct mlx5_wqe hdr;
 	uint8_t raw[32];
-} __rte_aligned(64);
+} __rte_aligned(MLX5_WQE_SIZE);
 
 /* MPW session status. */
 enum mlx5_mpw_state {
diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index 5dacd93..ada8e74 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -154,6 +154,24 @@ check_cqe(volatile struct mlx5_cqe *cqe,
 	return 0;
 }
 
+/**
+ * Return the address of the WQE.
+ *
+ * @param txq
+ *   Pointer to TX queue structure.
+ * @param  wqe_ci
+ *   WQE consumer index.
+ *
+ * @return
+ *   WQE address.
+ */
+static inline uintptr_t *
+tx_mlx5_wqe(struct txq *txq, uint16_t ci)
+{
+	ci &= ((1 << txq->wqe_n) - 1);
+	return (uintptr_t *)((uintptr_t)txq->wqes + ci * MLX5_WQE_SIZE);
+}
+
 static inline void
 txq_complete(struct txq *txq) __attribute__((always_inline));
 
@@ -175,7 +193,7 @@ txq_complete(struct txq *txq)
 	uint16_t elts_tail;
 	uint16_t cq_ci = txq->cq_ci;
 	volatile struct mlx5_cqe *cqe = NULL;
-	volatile struct mlx5_wqe *wqe;
+	volatile struct mlx5_wqe_ctrl *ctrl;
 
 	do {
 		volatile struct mlx5_cqe *tmp;
@@ -201,9 +219,9 @@ txq_complete(struct txq *txq)
 	} while (1);
 	if (unlikely(cqe == NULL))
 		return;
-	wqe = &(*txq->wqes)[ntohs(cqe->wqe_counter) &
-			    ((1 << txq->wqe_n) - 1)].hdr;
-	elts_tail = wqe->ctrl[3];
+	ctrl = (volatile struct mlx5_wqe_ctrl *)
+		tx_mlx5_wqe(txq, ntohs(cqe->wqe_counter));
+	elts_tail = ctrl->ctrl3;
 	assert(elts_tail < (1 << txq->wqe_n));
 	/* Free buffers. */
 	while (elts_free != elts_tail) {
@@ -331,23 +349,6 @@ tx_prefetch_cqe(struct txq *txq, uint16_t ci)
 }
 
 /**
- * Prefetch a WQE.
- *
- * @param txq
- *   Pointer to TX queue structure.
- * @param  wqe_ci
- *   WQE consumer index.
- */
-static inline void
-tx_prefetch_wqe(struct txq *txq, uint16_t ci)
-{
-	volatile struct mlx5_wqe64 *wqe;
-
-	wqe = &(*txq->wqes)[ci & ((1 << txq->wqe_n) - 1)];
-	rte_prefetch0(wqe);
-}
-
-/**
  * DPDK callback for TX.
  *
  * @param dpdk_txq
@@ -411,9 +412,9 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 		--segs_n;
 		if (!segs_n)
 			--pkts_n;
-		wqe = &(*txq->wqes)[txq->wqe_ci &
-				    ((1 << txq->wqe_n) - 1)].hdr;
-		tx_prefetch_wqe(txq, txq->wqe_ci + 1);
+		wqe = (volatile struct mlx5_wqe *)
+			tx_mlx5_wqe(txq, txq->wqe_ci);
+		rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci + 1));
 		if (pkts_n > 1)
 			rte_prefetch0(*pkts);
 		addr = rte_pktmbuf_mtod(buf, uintptr_t);
@@ -464,8 +465,9 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 		}
 		/* Inline if enough room. */
 		if (txq->max_inline != 0) {
-			uintptr_t end =
-				(uintptr_t)&(*txq->wqes)[1 << txq->wqe_n];
+			uintptr_t end = (uintptr_t)
+				(((uintptr_t)txq->wqes) +
+				 (1 << txq->wqe_n) * MLX5_WQE_SIZE);
 			uint16_t max_inline =
 				txq->max_inline * RTE_CACHE_LINE_SIZE;
 			uint16_t room;
@@ -496,12 +498,13 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 			 */
 			ds = 2 + MLX5_WQE_DS(pkt_inline_sz - 2);
 			if (length > 0) {
-				dseg = (struct mlx5_wqe_data_seg *)
+				dseg = (volatile struct mlx5_wqe_data_seg *)
 					((uintptr_t)wqe +
 					 (ds * MLX5_WQE_DWORD_SIZE));
 				if ((uintptr_t)dseg >= end)
-					dseg = (struct mlx5_wqe_data_seg *)
-						((uintptr_t)&(*txq->wqes)[0]);
+					dseg = (volatile struct
+						mlx5_wqe_data_seg *)
+					       txq->wqes;
 				goto use_dseg;
 			} else if (!segs_n) {
 				goto next_pkt;
@@ -514,12 +517,12 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 			 * Ethernet Header as been stored.
 			 */
 			wqe->eseg.inline_hdr_sz = htons(MLX5_WQE_DWORD_SIZE);
-			dseg = (struct mlx5_wqe_data_seg *)
+			dseg = (volatile struct mlx5_wqe_data_seg *)
 				((uintptr_t)wqe + (3 * MLX5_WQE_DWORD_SIZE));
 			ds = 3;
 use_dseg:
 			/* Add the remaining packet as a simple ds. */
-			*dseg = (struct mlx5_wqe_data_seg) {
+			*dseg = (volatile struct mlx5_wqe_data_seg) {
 				.addr = htonll(addr),
 				.byte_count = htonl(length),
 				.lkey = txq_mp2mr(txq, txq_mb2mp(buf)),
@@ -542,9 +545,9 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 			unsigned int n = (txq->wqe_ci + ((ds + 3) / 4)) &
 				((1 << txq->wqe_n) - 1);
 
-			dseg = (struct mlx5_wqe_data_seg *)
-				((uintptr_t)&(*txq->wqes)[n]);
-			tx_prefetch_wqe(txq, n + 1);
+			dseg = (volatile struct mlx5_wqe_data_seg *)
+			       tx_mlx5_wqe(txq, n);
+			rte_prefetch0(tx_mlx5_wqe(txq, n + 1));
 		} else {
 			++dseg;
 		}
@@ -556,7 +559,7 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 		total_length += length;
 #endif
 		/* Store segment information. */
-		*dseg = (struct mlx5_wqe_data_seg) {
+		*dseg = (volatile struct mlx5_wqe_data_seg) {
 			.addr = htonll(rte_pktmbuf_mtod(buf, uintptr_t)),
 			.byte_count = htonl(length),
 			.lkey = txq_mp2mr(txq, txq_mb2mp(buf)),
@@ -629,13 +632,13 @@ mlx5_mpw_new(struct txq *txq, struct mlx5_mpw *mpw, uint32_t length)
 	uint16_t idx = txq->wqe_ci & ((1 << txq->wqe_n) - 1);
 	volatile struct mlx5_wqe_data_seg (*dseg)[MLX5_MPW_DSEG_MAX] =
 		(volatile struct mlx5_wqe_data_seg (*)[])
-		(uintptr_t)&(*txq->wqes)[(idx + 1) & ((1 << txq->wqe_n) - 1)];
+		tx_mlx5_wqe(txq, idx + 1);
 
 	mpw->state = MLX5_MPW_STATE_OPENED;
 	mpw->pkts_n = 0;
 	mpw->len = length;
 	mpw->total_len = 0;
-	mpw->wqe = (volatile struct mlx5_wqe *)&(*txq->wqes)[idx].hdr;
+	mpw->wqe = (volatile struct mlx5_wqe *)tx_mlx5_wqe(txq, idx);
 	mpw->wqe->eseg.mss = htons(length);
 	mpw->wqe->eseg.inline_hdr_sz = 0;
 	mpw->wqe->eseg.rsvd0 = 0;
@@ -677,8 +680,8 @@ mlx5_mpw_close(struct txq *txq, struct mlx5_mpw *mpw)
 		++txq->wqe_ci;
 	else
 		txq->wqe_ci += 2;
-	tx_prefetch_wqe(txq, txq->wqe_ci);
-	tx_prefetch_wqe(txq, txq->wqe_ci + 1);
+	rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci));
+	rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci + 1));
 }
 
 /**
@@ -712,8 +715,8 @@ mlx5_tx_burst_mpw(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 		return 0;
 	/* Prefetch first packet cacheline. */
 	tx_prefetch_cqe(txq, txq->cq_ci);
-	tx_prefetch_wqe(txq, txq->wqe_ci);
-	tx_prefetch_wqe(txq, txq->wqe_ci + 1);
+	rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci));
+	rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci + 1));
 	/* Start processing. */
 	txq_complete(txq);
 	max = (elts_n - (elts_head - txq->elts_tail));
@@ -841,7 +844,7 @@ mlx5_mpw_inline_new(struct txq *txq, struct mlx5_mpw *mpw, uint32_t length)
 	mpw->pkts_n = 0;
 	mpw->len = length;
 	mpw->total_len = 0;
-	mpw->wqe = (volatile struct mlx5_wqe *)&(*txq->wqes)[idx].hdr;
+	mpw->wqe = (volatile struct mlx5_wqe *)tx_mlx5_wqe(txq, idx);
 	mpw->wqe->ctrl[0] = htonl((MLX5_OPC_MOD_MPW << 24) |
 				  (txq->wqe_ci << 8) |
 				  MLX5_OPCODE_TSO);
@@ -917,8 +920,8 @@ mlx5_tx_burst_mpw_inline(void *dpdk_txq, struct rte_mbuf **pkts,
 		return 0;
 	/* Prefetch first packet cacheline. */
 	tx_prefetch_cqe(txq, txq->cq_ci);
-	tx_prefetch_wqe(txq, txq->wqe_ci);
-	tx_prefetch_wqe(txq, txq->wqe_ci + 1);
+	rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci));
+	rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci + 1));
 	/* Start processing. */
 	txq_complete(txq);
 	max = (elts_n - (elts_head - txq->elts_tail));
@@ -1019,14 +1022,15 @@ mlx5_tx_burst_mpw_inline(void *dpdk_txq, struct rte_mbuf **pkts,
 			addr = rte_pktmbuf_mtod(buf, uintptr_t);
 			(*txq->elts)[elts_head] = buf;
 			/* Maximum number of bytes before wrapping. */
-			max = ((uintptr_t)&(*txq->wqes)[1 << txq->wqe_n] -
+			max = ((((uintptr_t)(txq->wqes)) +
+				(1 << txq->wqe_n) *
+				MLX5_WQE_SIZE) -
 			       (uintptr_t)mpw.data.raw);
 			if (length > max) {
 				rte_memcpy((void *)(uintptr_t)mpw.data.raw,
 					   (void *)addr,
 					   max);
-				mpw.data.raw =
-					(volatile void *)&(*txq->wqes)[0];
+				mpw.data.raw = (volatile void *)txq->wqes;
 				rte_memcpy((void *)(uintptr_t)mpw.data.raw,
 					   (void *)(addr + max),
 					   length - max);
@@ -1038,9 +1042,8 @@ mlx5_tx_burst_mpw_inline(void *dpdk_txq, struct rte_mbuf **pkts,
 				mpw.data.raw += length;
 			}
 			if ((uintptr_t)mpw.data.raw ==
-			    (uintptr_t)&(*txq->wqes)[1 << txq->wqe_n])
-				mpw.data.raw =
-					(volatile void *)&(*txq->wqes)[0];
+			    (uintptr_t)tx_mlx5_wqe(txq, 1 << txq->wqe_n))
+				mpw.data.raw = (volatile void *)txq->wqes;
 			++mpw.pkts_n;
 			++j;
 			if (mpw.pkts_n == MLX5_MPW_DSEG_MAX) {
diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h
index 8f2cddb..b9b90a7 100644
--- a/drivers/net/mlx5/mlx5_rxtx.h
+++ b/drivers/net/mlx5/mlx5_rxtx.h
@@ -259,7 +259,7 @@ struct txq {
 	uint16_t max_inline; /* Multiple of RTE_CACHE_LINE_SIZE to inline. */
 	uint32_t qp_num_8s; /* QP number shifted by 8. */
 	volatile struct mlx5_cqe (*cqes)[]; /* Completion queue. */
-	volatile struct mlx5_wqe64 (*wqes)[]; /* Work queue. */
+	volatile void *wqes; /* Work queue (use volatile to write into). */
 	volatile uint32_t *qp_db; /* Work queue doorbell. */
 	volatile uint32_t *cq_db; /* Completion queue doorbell. */
 	volatile void *bf_reg; /* Blueflame register. */
diff --git a/drivers/net/mlx5/mlx5_txq.c b/drivers/net/mlx5/mlx5_txq.c
index 053665d..f4c6682 100644
--- a/drivers/net/mlx5/mlx5_txq.c
+++ b/drivers/net/mlx5/mlx5_txq.c
@@ -82,7 +82,9 @@ txq_alloc_elts(struct txq_ctrl *txq_ctrl, unsigned int elts_n)
 	for (i = 0; (i != elts_n); ++i)
 		(*txq_ctrl->txq.elts)[i] = NULL;
 	for (i = 0; (i != (1u << txq_ctrl->txq.wqe_n)); ++i) {
-		volatile struct mlx5_wqe64 *wqe = &(*txq_ctrl->txq.wqes)[i];
+		volatile struct mlx5_wqe64 *wqe =
+			(volatile struct mlx5_wqe64 *)
+			txq_ctrl->txq.wqes + i;
 
 		memset((void *)(uintptr_t)wqe, 0x0, sizeof(*wqe));
 	}
@@ -214,9 +216,7 @@ txq_setup(struct txq_ctrl *tmpl, struct txq_ctrl *txq_ctrl)
 	}
 	tmpl->txq.cqe_n = log2above(ibcq->cqe);
 	tmpl->txq.qp_num_8s = qp->ctrl_seg.qp_num << 8;
-	tmpl->txq.wqes =
-		(volatile struct mlx5_wqe64 (*)[])
-		(uintptr_t)qp->gen_data.sqstart;
+	tmpl->txq.wqes = qp->gen_data.sqstart;
 	tmpl->txq.wqe_n = log2above(qp->sq.wqe_cnt);
 	tmpl->txq.qp_db = &qp->gen_data.db[MLX5_SND_DBR];
 	tmpl->txq.bf_reg = qp->gen_data.bf->reg;
-- 
2.1.4

^ permalink raw reply related

* [PATCH 1/7] net/mlx5: prepare Tx vectorization
From: Nelio Laranjeiro @ 2016-11-24 16:03 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon, Adrien Mazarguil, Elad Persiko
In-Reply-To: <cover.1479995764.git.nelio.laranjeiro@6wind.com>

Prepare the code to write the Work Queue Element with vectorized
instructions.

Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
Signed-off-by: Elad Persiko <eladpe@mellanox.com>
Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
 drivers/net/mlx5/mlx5_rxtx.c | 44 ++++++++++++++++++++++++++++----------------
 1 file changed, 28 insertions(+), 16 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index ffd09ac..5dacd93 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -391,6 +391,8 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 		uint32_t length;
 		unsigned int ds = 0;
 		uintptr_t addr;
+		uint16_t pkt_inline_sz = MLX5_WQE_DWORD_SIZE;
+		uint8_t ehdr[2];
 #ifdef MLX5_PMD_SOFT_COUNTERS
 		uint32_t total_length = 0;
 #endif
@@ -416,6 +418,8 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 			rte_prefetch0(*pkts);
 		addr = rte_pktmbuf_mtod(buf, uintptr_t);
 		length = DATA_LEN(buf);
+		ehdr[0] = ((uint8_t *)addr)[0];
+		ehdr[1] = ((uint8_t *)addr)[1];
 #ifdef MLX5_PMD_SOFT_COUNTERS
 		total_length = length;
 #endif
@@ -439,24 +443,20 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 		} else {
 			wqe->eseg.cs_flags = 0;
 		}
-		raw  = (uint8_t *)(uintptr_t)&wqe->eseg.inline_hdr[0];
-		/* Start the know and common part of the WQE structure. */
-		wqe->ctrl[0] = htonl((txq->wqe_ci << 8) | MLX5_OPCODE_SEND);
-		wqe->ctrl[2] = 0;
-		wqe->ctrl[3] = 0;
-		wqe->eseg.rsvd0 = 0;
-		wqe->eseg.rsvd1 = 0;
-		wqe->eseg.mss = 0;
-		wqe->eseg.rsvd2 = 0;
-		/* Start by copying the Ethernet Header. */
-		memcpy((uint8_t *)raw, ((uint8_t *)addr), 16);
+		raw = ((uint8_t *)(uintptr_t)wqe) + 2 * MLX5_WQE_DWORD_SIZE;
+		/*
+		 * Start by copying the Ethernet header minus the first two
+		 * bytes which will be appended at the end of the Ethernet
+		 * segment.
+		 */
+		memcpy((uint8_t *)raw, ((uint8_t *)addr) + 2, 16);
 		length -= MLX5_WQE_DWORD_SIZE;
 		addr += MLX5_WQE_DWORD_SIZE;
 		/* Replace the Ethernet type by the VLAN if necessary. */
 		if (buf->ol_flags & PKT_TX_VLAN_PKT) {
 			uint32_t vlan = htonl(0x81000000 | buf->vlan_tci);
 
-			memcpy((uint8_t *)(raw + MLX5_WQE_DWORD_SIZE -
+			memcpy((uint8_t *)(raw + MLX5_WQE_DWORD_SIZE - 2 -
 					   sizeof(vlan)),
 			       &vlan, sizeof(vlan));
 			addr -= sizeof(vlan);
@@ -468,10 +468,13 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 				(uintptr_t)&(*txq->wqes)[1 << txq->wqe_n];
 			uint16_t max_inline =
 				txq->max_inline * RTE_CACHE_LINE_SIZE;
-			uint16_t pkt_inline_sz = MLX5_WQE_DWORD_SIZE;
 			uint16_t room;
 
-			raw += MLX5_WQE_DWORD_SIZE;
+			/*
+			 * raw starts two bytes before the boundary to
+			 * continue the above copy of packet data.
+			 */
+			raw += MLX5_WQE_DWORD_SIZE - 2;
 			room = end - (uintptr_t)raw;
 			if (room > max_inline) {
 				uintptr_t addr_end = (addr + max_inline) &
@@ -487,8 +490,6 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 				/* Sanity check. */
 				assert(addr <= addr_end);
 			}
-			/* Store the inlined packet size in the WQE. */
-			wqe->eseg.inline_hdr_sz = htons(pkt_inline_sz);
 			/*
 			 * 2 DWORDs consumed by the WQE header + 1 DSEG +
 			 * the size of the inline part of the packet.
@@ -570,7 +571,18 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 			--pkts_n;
 next_pkt:
 		++i;
+		/* Initialize known and common part of the WQE structure. */
+		wqe->ctrl[0] = htonl((txq->wqe_ci << 8) | MLX5_OPCODE_SEND);
 		wqe->ctrl[1] = htonl(txq->qp_num_8s | ds);
+		wqe->ctrl[2] = 0;
+		wqe->ctrl[3] = 0;
+		wqe->eseg.rsvd0 = 0;
+		wqe->eseg.rsvd1 = 0;
+		wqe->eseg.mss = 0;
+		wqe->eseg.rsvd2 = 0;
+		wqe->eseg.inline_hdr_sz = htons(pkt_inline_sz);
+		wqe->eseg.inline_hdr[0] = ehdr[0];
+		wqe->eseg.inline_hdr[1] = ehdr[1];
 		txq->wqe_ci += (ds + 3) / 4;
 #ifdef MLX5_PMD_SOFT_COUNTERS
 		/* Increment sent bytes counter. */
-- 
2.1.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