DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture
@ 2014-12-08  8:59 Zhigang Lu
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 01/15] mk: introduce Tilera Tile architecture Zhigang Lu
                   ` (14 more replies)
  0 siblings, 15 replies; 32+ messages in thread
From: Zhigang Lu @ 2014-12-08  8:59 UTC (permalink / raw)
  To: dev

This patch set adds default configuration, compiling related rte.vars.mk
files for tile, and architecture-specific operations for EAL. TileGx
processor, as a SOC, contains a on-chip networking engine named mPIPE(
multicore Programmable Intelligent Packet Engine). This patch set also
adds poll mode driver for the mPIPE device. And to improve the performance
of memory allocation, mPIPE's buffer stack is used as the mempool provider.

Zhigang Lu (15):
  mk: introduce Tilera Tile architecture
  eal/tile: add atomic operations for TileGx
  eal/tile: add byte order operations for TileGx
  eal/tile: add spinlock operations for TileGx
  eal/tile: add prefetch operations for TileGx
  eal/tile: add memcpy operations for TileGx
  eal/tile: add CPU flags operations for TileGx
  eal/tile: add cycle operations for TileGx
  eal: split vector operations to architecture specific
  eal/tile: add vector operations for TileGx
  eal/tile: add EAL support for global mPIPE initialization
  eal/tile: add mPIPE buffer stack mempool provider
  pmd/tile: add mPIPE poll mode driver for TileGx
  app/test: turn off cpu flag checks for tile architecture
  eal: allow empty set of compile time cpuflags

 app/test-pmd/mempool_anon.c                        |    2 +-
 app/test/Makefile                                  |    6 +-
 app/test/test_cpuflags.c                           |    2 +-
 app/test/test_mempool_tile.c                       |  217 ++++
 config/defconfig_tile-tilegx-linuxapp-gcc          |   78 ++
 lib/Makefile                                       |    6 +
 lib/librte_eal/common/Makefile                     |    3 +-
 lib/librte_eal/common/eal_common_cpuflags.c        |    4 +-
 .../common/include/arch/ppc_64/rte_common_vect.h   |   73 ++
 .../common/include/arch/tile/rte_atomic.h          |   62 +
 .../common/include/arch/tile/rte_byteorder.h       |   70 +
 .../common/include/arch/tile/rte_common_vect.h     |   49 +
 .../common/include/arch/tile/rte_cpuflags.h        |   69 +
 .../common/include/arch/tile/rte_cycles.h          |   64 +
 .../common/include/arch/tile/rte_memcpy.h          |   97 ++
 .../common/include/arch/tile/rte_mpipe.h           |   67 +
 .../common/include/arch/tile/rte_prefetch.h        |   62 +
 .../common/include/arch/tile/rte_spinlock.h        |   47 +
 .../common/include/arch/x86/rte_common_vect.h      |   81 ++
 .../common/include/generic/rte_common_vect.h       |   51 +
 lib/librte_eal/common/include/rte_common_vect.h    |   93 --
 lib/librte_eal/linuxapp/eal/Makefile               |    7 +
 lib/librte_eal/linuxapp/eal/eal.c                  |    9 +
 lib/librte_eal/linuxapp/eal/eal_mpipe_tile.c       |  147 +++
 lib/librte_mempool_tile/Makefile                   |   48 +
 lib/librte_mempool_tile/rte_mempool.c              |  381 ++++++
 lib/librte_mempool_tile/rte_mempool.h              |  634 +++++++++
 lib/librte_pmd_mpipe/Makefile                      |   24 +
 lib/librte_pmd_mpipe/pmd_mpipe.c                   | 1343 ++++++++++++++++++++
 mk/arch/tile/rte.vars.mk                           |   59 +
 mk/machine/tilegx/rte.vars.mk                      |   58 +
 mk/rte.app.mk                                      |    8 +
 32 files changed, 3822 insertions(+), 99 deletions(-)
 create mode 100644 app/test/test_mempool_tile.c
 create mode 100644 config/defconfig_tile-tilegx-linuxapp-gcc
 create mode 100644 lib/librte_eal/common/include/arch/ppc_64/rte_common_vect.h
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_atomic.h
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_byteorder.h
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_common_vect.h
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_cpuflags.h
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_cycles.h
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_memcpy.h
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_mpipe.h
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_prefetch.h
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_spinlock.h
 create mode 100644 lib/librte_eal/common/include/arch/x86/rte_common_vect.h
 create mode 100644 lib/librte_eal/common/include/generic/rte_common_vect.h
 delete mode 100644 lib/librte_eal/common/include/rte_common_vect.h
 create mode 100644 lib/librte_eal/linuxapp/eal/eal_mpipe_tile.c
 create mode 100644 lib/librte_mempool_tile/Makefile
 create mode 100644 lib/librte_mempool_tile/rte_mempool.c
 create mode 100644 lib/librte_mempool_tile/rte_mempool.h
 create mode 100644 lib/librte_pmd_mpipe/Makefile
 create mode 100644 lib/librte_pmd_mpipe/pmd_mpipe.c
 create mode 100644 mk/arch/tile/rte.vars.mk
 create mode 100644 mk/machine/tilegx/rte.vars.mk

-- 
2.1.2

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [dpdk-dev] [PATCH 01/15] mk: introduce Tilera Tile architecture
  2014-12-08  8:59 [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture Zhigang Lu
@ 2014-12-08  8:59 ` Zhigang Lu
  2014-12-08 11:09   ` Bruce Richardson
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 02/15] eal/tile: add atomic operations for TileGx Zhigang Lu
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 32+ messages in thread
From: Zhigang Lu @ 2014-12-08  8:59 UTC (permalink / raw)
  To: dev; +Cc: Cyril Chemparathy

Add defconfig and rte.vars.mk files for Tile architecture.

Signed-off-by: Zhigang Lu <zlu@ezchip.com>
Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
---
 config/defconfig_tile-tilegx-linuxapp-gcc | 78 +++++++++++++++++++++++++++++++
 mk/arch/tile/rte.vars.mk                  | 59 +++++++++++++++++++++++
 mk/machine/tilegx/rte.vars.mk             | 58 +++++++++++++++++++++++
 3 files changed, 195 insertions(+)
 create mode 100644 config/defconfig_tile-tilegx-linuxapp-gcc
 create mode 100644 mk/arch/tile/rte.vars.mk
 create mode 100644 mk/machine/tilegx/rte.vars.mk

diff --git a/config/defconfig_tile-tilegx-linuxapp-gcc b/config/defconfig_tile-tilegx-linuxapp-gcc
new file mode 100644
index 0000000..5a944d5
--- /dev/null
+++ b/config/defconfig_tile-tilegx-linuxapp-gcc
@@ -0,0 +1,78 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2014 Tilera Corporation. 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 Tilera 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 "common_linuxapp"
+
+CONFIG_RTE_MACHINE="tilegx"
+
+CONFIG_RTE_ARCH="tile"
+CONFIG_RTE_ARCH_TILE=y
+CONFIG_RTE_ARCH_64=y
+
+CONFIG_RTE_TOOLCHAIN="gcc"
+CONFIG_RTE_TOOLCHAIN_GCC=y
+CONFIG_RTE_TOOLCHAIN_DEBUG=y
+
+CONFIG_RTE_FORCE_INTRINSICS=y
+CONFIG_RTE_LIBNAME="tile_dpdk"
+CONFIG_RTE_MAX_LCORE=128
+CONFIG_RTE_PKTMBUF_HEADROOM=66
+
+#
+# Compile burst-oriented MPIPE PMD driver
+#
+CONFIG_RTE_LIBRTE_MPIPE_PMD=y
+CONFIG_RTE_LIBRTE_MPIPE_DEBUG_INIT=y
+CONFIG_RTE_LIBRTE_MPIPE_DEBUG_RX=n
+CONFIG_RTE_LIBRTE_MPIPE_DEBUG_TX=n
+
+# Note: TileGx doesn't have this support
+CONFIG_RTE_EAL_IGB_UIO=n
+CONFIG_RTE_EAL_VFIO=n
+CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=n
+CONFIG_RTE_LIBRTE_EM_PMD=n
+CONFIG_RTE_LIBRTE_IGB_PMD=n
+CONFIG_RTE_LIBRTE_IXGBE_PMD=n
+CONFIG_RTE_LIBRTE_I40E_PMD=n
+CONFIG_RTE_LIBRTE_VIRTIO_PMD=n
+CONFIG_RTE_LIBRTE_VMXNET3_PMD=n
+CONFIG_RTE_LIBRTE_PMD_BOND=n
+CONFIG_RTE_LIBRTE_ENIC_PMD=n
+
+# The following libraries are not available on TileGx.
+CONFIG_RTE_LIBRTE_LPM=n
+CONFIG_RTE_LIBRTE_ACL=n
+CONFIG_RTE_LIBRTE_SCHED=n
+CONFIG_RTE_LIBRTE_PORT=n
+CONFIG_RTE_LIBRTE_TABLE=n
+CONFIG_RTE_LIBRTE_PIPELINE=n
+CONFIG_RTE_LIBRTE_KNI=n
diff --git a/mk/arch/tile/rte.vars.mk b/mk/arch/tile/rte.vars.mk
new file mode 100644
index 0000000..238bbe2
--- /dev/null
+++ b/mk/arch/tile/rte.vars.mk
@@ -0,0 +1,59 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2014 Tilera Corporation. 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 Tilera 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.
+
+#
+# arch:
+#
+#   - define ARCH variable (overriden by cmdline or by previous
+#     optional define in machine .mk)
+#   - define CROSS variable (overriden by cmdline or previous define
+#     in machine .mk)
+#   - define CPU_CFLAGS variable (overriden by cmdline or previous
+#     define in machine .mk)
+#   - define CPU_LDFLAGS variable (overriden by cmdline or previous
+#     define in machine .mk)
+#   - define CPU_ASFLAGS variable (overriden by cmdline or previous
+#     define in machine .mk)
+#   - may override any previously defined variable
+#
+# examples for CONFIG_RTE_ARCH: i686, x86_64, x86_64_32
+#
+
+ARCH  ?= tile
+# common arch dir in eal headers
+ARCH_DIR := tile
+CROSS ?= tile-
+
+CPU_CFLAGS  ?=
+CPU_LDFLAGS ?=
+CPU_ASFLAGS ?=
+
+export ARCH CROSS CPU_CFLAGS CPU_LDFLAGS CPU_ASFLAGS
diff --git a/mk/machine/tilegx/rte.vars.mk b/mk/machine/tilegx/rte.vars.mk
new file mode 100644
index 0000000..368ee12
--- /dev/null
+++ b/mk/machine/tilegx/rte.vars.mk
@@ -0,0 +1,58 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2014 Tilera Corporation. 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 Tilera 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.
+
+#
+# machine:
+#
+#   - can define ARCH variable (overriden by cmdline value)
+#   - can define CROSS variable (overriden by cmdline value)
+#   - define MACHINE_CFLAGS variable (overriden by cmdline value)
+#   - define MACHINE_LDFLAGS variable (overriden by cmdline value)
+#   - define MACHINE_ASFLAGS variable (overriden by cmdline value)
+#   - can define CPU_CFLAGS variable (overriden by cmdline value) that
+#     overrides the one defined in arch.
+#   - can define CPU_LDFLAGS variable (overriden by cmdline value) that
+#     overrides the one defined in arch.
+#   - can define CPU_ASFLAGS variable (overriden by cmdline value) that
+#     overrides the one defined in arch.
+#   - may override any previously defined variable
+#
+
+# ARCH =
+# CROSS =
+# MACHINE_CFLAGS =
+# MACHINE_LDFLAGS =
+# MACHINE_ASFLAGS =
+# CPU_CFLAGS =
+# CPU_LDFLAGS =
+# CPU_ASFLAGS =
+
+MACHINE_CFLAGS =
-- 
2.1.2

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [dpdk-dev] [PATCH 02/15] eal/tile: add atomic operations for TileGx
  2014-12-08  8:59 [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture Zhigang Lu
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 01/15] mk: introduce Tilera Tile architecture Zhigang Lu
@ 2014-12-08  8:59 ` Zhigang Lu
  2014-12-08 14:28   ` Neil Horman
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 03/15] eal/tile: add byte order " Zhigang Lu
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 32+ messages in thread
From: Zhigang Lu @ 2014-12-08  8:59 UTC (permalink / raw)
  To: dev; +Cc: Cyril Chemparathy

This patch adds architecture specific memory barrier operations for
TileGx.

Signed-off-by: Zhigang Lu <zlu@ezchip.com>
Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
---
 .../common/include/arch/tile/rte_atomic.h          | 62 ++++++++++++++++++++++
 1 file changed, 62 insertions(+)
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_atomic.h

diff --git a/lib/librte_eal/common/include/arch/tile/rte_atomic.h b/lib/librte_eal/common/include/arch/tile/rte_atomic.h
new file mode 100644
index 0000000..24c9b0a
--- /dev/null
+++ b/lib/librte_eal/common/include/arch/tile/rte_atomic.h
@@ -0,0 +1,62 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2014 Tilera Corporation. 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 Tilera 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_ATOMIC_TILE_H_
+#define _RTE_ATOMIC_TILE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "generic/rte_atomic.h"
+
+static inline void rte_mb(void)
+{
+	__sync_synchronize();
+}
+
+static inline void rte_wmb(void)
+{
+	__sync_synchronize();
+}
+
+static inline void rte_rmb(void)
+{
+	__sync_synchronize();
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_ATOMIC_TILE_H_ */
-- 
2.1.2

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [dpdk-dev] [PATCH 03/15] eal/tile: add byte order operations for TileGx
  2014-12-08  8:59 [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture Zhigang Lu
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 01/15] mk: introduce Tilera Tile architecture Zhigang Lu
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 02/15] eal/tile: add atomic operations for TileGx Zhigang Lu
@ 2014-12-08  8:59 ` Zhigang Lu
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 04/15] eal/tile: add spinlock " Zhigang Lu
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 32+ messages in thread
From: Zhigang Lu @ 2014-12-08  8:59 UTC (permalink / raw)
  To: dev; +Cc: Cyril Chemparathy

This patch adds architecture specific byte swap and endianness
operations for TileGx.

Signed-off-by: Zhigang Lu <zlu@ezchip.com>
Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
---
 .../common/include/arch/tile/rte_byteorder.h       | 70 ++++++++++++++++++++++
 1 file changed, 70 insertions(+)
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_byteorder.h

diff --git a/lib/librte_eal/common/include/arch/tile/rte_byteorder.h b/lib/librte_eal/common/include/arch/tile/rte_byteorder.h
new file mode 100644
index 0000000..38f3a23
--- /dev/null
+++ b/lib/librte_eal/common/include/arch/tile/rte_byteorder.h
@@ -0,0 +1,70 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2014 Tilera Corporation. 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 Tilera 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_BYTEORDER_TILE_H_
+#define _RTE_BYTEORDER_TILE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "generic/rte_byteorder.h"
+
+/*
+ * __builtin_bswap16 is only available gcc 4.8 and upwards
+ */
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)
+#define rte_bswap16(x) ((uint16_t)rte_constant_bswap16(x))
+#endif
+
+#define rte_cpu_to_le_16(x) (x)
+#define rte_cpu_to_le_32(x) (x)
+#define rte_cpu_to_le_64(x) (x)
+
+#define rte_cpu_to_be_16(x) rte_bswap16(x)
+#define rte_cpu_to_be_32(x) rte_bswap32(x)
+#define rte_cpu_to_be_64(x) rte_bswap64(x)
+
+#define rte_le_to_cpu_16(x) (x)
+#define rte_le_to_cpu_32(x) (x)
+#define rte_le_to_cpu_64(x) (x)
+
+#define rte_be_to_cpu_16(x) rte_bswap16(x)
+#define rte_be_to_cpu_32(x) rte_bswap32(x)
+#define rte_be_to_cpu_64(x) rte_bswap64(x)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_BYTEORDER_TILE_H_ */
-- 
2.1.2

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [dpdk-dev] [PATCH 04/15] eal/tile: add spinlock operations for TileGx
  2014-12-08  8:59 [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture Zhigang Lu
                   ` (2 preceding siblings ...)
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 03/15] eal/tile: add byte order " Zhigang Lu
@ 2014-12-08  8:59 ` Zhigang Lu
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 05/15] eal/tile: add prefetch " Zhigang Lu
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 32+ messages in thread
From: Zhigang Lu @ 2014-12-08  8:59 UTC (permalink / raw)
  To: dev; +Cc: Cyril Chemparathy

TileGx uses generic spinlock operations.

Signed-off-by: Zhigang Lu <zlu@ezchip.com>
Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
---
 .../common/include/arch/tile/rte_spinlock.h        | 47 ++++++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_spinlock.h

diff --git a/lib/librte_eal/common/include/arch/tile/rte_spinlock.h b/lib/librte_eal/common/include/arch/tile/rte_spinlock.h
new file mode 100644
index 0000000..1dc224e
--- /dev/null
+++ b/lib/librte_eal/common/include/arch/tile/rte_spinlock.h
@@ -0,0 +1,47 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2014 Tilera Corporation. 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 Tilera 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_SPINLOCK_TILE_H_
+#define _RTE_SPINLOCK_TILE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "generic/rte_spinlock.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_SPINLOCK_TILE_H_ */
-- 
2.1.2

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [dpdk-dev] [PATCH 05/15] eal/tile: add prefetch operations for TileGx
  2014-12-08  8:59 [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture Zhigang Lu
                   ` (3 preceding siblings ...)
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 04/15] eal/tile: add spinlock " Zhigang Lu
@ 2014-12-08  8:59 ` Zhigang Lu
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 06/15] eal/tile: add memcpy " Zhigang Lu
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 32+ messages in thread
From: Zhigang Lu @ 2014-12-08  8:59 UTC (permalink / raw)
  To: dev; +Cc: Cyril Chemparathy

Signed-off-by: Zhigang Lu <zlu@ezchip.com>
Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
---
 .../common/include/arch/tile/rte_prefetch.h        | 62 ++++++++++++++++++++++
 1 file changed, 62 insertions(+)
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_prefetch.h

diff --git a/lib/librte_eal/common/include/arch/tile/rte_prefetch.h b/lib/librte_eal/common/include/arch/tile/rte_prefetch.h
new file mode 100644
index 0000000..01a5d21
--- /dev/null
+++ b/lib/librte_eal/common/include/arch/tile/rte_prefetch.h
@@ -0,0 +1,62 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2014 Tilera Corporation. 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 Tilera 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_PREFETCH_TILE_H_
+#define _RTE_PREFETCH_TILE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "generic/rte_prefetch.h"
+
+static inline void rte_prefetch0(volatile void *p)
+{
+	__builtin_prefetch((const void *)(uintptr_t)p, 0, 3);
+}
+
+static inline void rte_prefetch1(volatile void *p)
+{
+	__builtin_prefetch((const void *)(uintptr_t)p, 0, 2);
+}
+
+static inline void rte_prefetch2(volatile void *p)
+{
+	__builtin_prefetch((const void *)(uintptr_t)p, 0, 1);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_PREFETCH_TILE_H_ */
-- 
2.1.2

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [dpdk-dev] [PATCH 06/15] eal/tile: add memcpy operations for TileGx
  2014-12-08  8:59 [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture Zhigang Lu
                   ` (4 preceding siblings ...)
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 05/15] eal/tile: add prefetch " Zhigang Lu
@ 2014-12-08  8:59 ` Zhigang Lu
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 07/15] eal/tile: add CPU flags " Zhigang Lu
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 32+ messages in thread
From: Zhigang Lu @ 2014-12-08  8:59 UTC (permalink / raw)
  To: dev; +Cc: Cyril Chemparathy

Signed-off-by: Zhigang Lu <zlu@ezchip.com>
Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
---
 .../common/include/arch/tile/rte_memcpy.h          | 97 ++++++++++++++++++++++
 1 file changed, 97 insertions(+)
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_memcpy.h

diff --git a/lib/librte_eal/common/include/arch/tile/rte_memcpy.h b/lib/librte_eal/common/include/arch/tile/rte_memcpy.h
new file mode 100644
index 0000000..ef68787
--- /dev/null
+++ b/lib/librte_eal/common/include/arch/tile/rte_memcpy.h
@@ -0,0 +1,97 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2014 Tilera Corporation. 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 Tilera 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_MEMCPY_TILE_H_
+#define _RTE_MEMCPY_TILE_H_
+
+#include <stdint.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "generic/rte_memcpy.h"
+
+static inline void
+rte_mov16(uint8_t *dst, const uint8_t *src)
+{
+	memcpy(dst, src, 16);
+}
+
+static inline void
+rte_mov32(uint8_t *dst, const uint8_t *src)
+{
+	memcpy(dst, src, 32);
+}
+
+static inline void
+rte_mov48(uint8_t *dst, const uint8_t *src)
+{
+	memcpy(dst, src, 48);
+}
+
+static inline void
+rte_mov64(uint8_t *dst, const uint8_t *src)
+{
+	memcpy(dst, src, 64);
+}
+
+static inline void
+rte_mov128(uint8_t *dst, const uint8_t *src)
+{
+	memcpy(dst, src, 128);
+}
+
+static inline void
+rte_mov256(uint8_t *dst, const uint8_t *src)
+{
+	memcpy(dst, src, 256);
+}
+
+#define rte_memcpy(dst, src, n)              \
+	((__builtin_constant_p(n)) ?          \
+	memcpy((dst), (src), (n)) :          \
+	rte_memcpy_func((dst), (src), (n)))
+
+static inline void *
+rte_memcpy_func(void *dst, const void *src, size_t n)
+{
+	return memcpy(dst, src, n);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_MEMCPY_TILE_H_ */
-- 
2.1.2

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [dpdk-dev] [PATCH 07/15] eal/tile: add CPU flags operations for TileGx
  2014-12-08  8:59 [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture Zhigang Lu
                   ` (5 preceding siblings ...)
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 06/15] eal/tile: add memcpy " Zhigang Lu
@ 2014-12-08  8:59 ` Zhigang Lu
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 08/15] eal/tile: add cycle " Zhigang Lu
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 32+ messages in thread
From: Zhigang Lu @ 2014-12-08  8:59 UTC (permalink / raw)
  To: dev; +Cc: Cyril Chemparathy

This patch adds empty functions for CPU flags operations to support DPDK,
since tile processor doesn't have CPU flag hardware registers.

Signed-off-by: Zhigang Lu <zlu@ezchip.com>
Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
---
 .../common/include/arch/tile/rte_cpuflags.h        | 69 ++++++++++++++++++++++
 1 file changed, 69 insertions(+)
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_cpuflags.h

diff --git a/lib/librte_eal/common/include/arch/tile/rte_cpuflags.h b/lib/librte_eal/common/include/arch/tile/rte_cpuflags.h
new file mode 100644
index 0000000..6b4c894
--- /dev/null
+++ b/lib/librte_eal/common/include/arch/tile/rte_cpuflags.h
@@ -0,0 +1,69 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2014 Tilera Corporation. 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 Tilera 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_CPUFLAGS_TILE_H_
+#define _RTE_CPUFLAGS_TILE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#include <rte_common.h>
+
+#include "generic/rte_cpuflags.h"
+
+enum rte_cpu_flag_t {
+	/* The last item */
+	RTE_CPUFLAG_NUMFLAGS,	/**< This should always be the last! */
+};
+
+static inline void
+rte_cpu_get_features(__rte_unused uint32_t leaf,
+		     __rte_unused uint32_t subleaf,
+		     __rte_unused cpuid_registers_t out)
+{
+}
+
+static inline int
+rte_cpu_get_flag_enabled(__rte_unused enum rte_cpu_flag_t feature)
+{
+	return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_CPUFLAGS_TILE_H_ */
-- 
2.1.2

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [dpdk-dev] [PATCH 08/15] eal/tile: add cycle operations for TileGx
  2014-12-08  8:59 [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture Zhigang Lu
                   ` (6 preceding siblings ...)
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 07/15] eal/tile: add CPU flags " Zhigang Lu
@ 2014-12-08  8:59 ` Zhigang Lu
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 09/15] eal: split vector operations to architecture specific Zhigang Lu
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 32+ messages in thread
From: Zhigang Lu @ 2014-12-08  8:59 UTC (permalink / raw)
  To: dev; +Cc: Cyril Chemparathy

This patch adds CPU TSC read operations for TileGx.

Signed-off-by: Zhigang Lu <zlu@ezchip.com>
Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
---
 .../common/include/arch/tile/rte_cycles.h          | 64 ++++++++++++++++++++++
 1 file changed, 64 insertions(+)
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_cycles.h

diff --git a/lib/librte_eal/common/include/arch/tile/rte_cycles.h b/lib/librte_eal/common/include/arch/tile/rte_cycles.h
new file mode 100644
index 0000000..74e11cf
--- /dev/null
+++ b/lib/librte_eal/common/include/arch/tile/rte_cycles.h
@@ -0,0 +1,64 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2014 Tilera Corporation. 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 Tilera 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_CYCLES_TILE_H_
+#define _RTE_CYCLES_TILE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "generic/rte_cycles.h"
+
+#include <arch/cycle.h>
+
+static inline uint64_t
+rte_rdtsc(void)
+{
+	return get_cycle_count();
+}
+
+static inline uint64_t
+rte_rdtsc_precise(void)
+{
+	return rte_rdtsc();
+}
+
+static inline uint64_t
+rte_get_tsc_cycles(void) { return rte_rdtsc(); }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_CYCLES_TILE_H_ */
-- 
2.1.2

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [dpdk-dev] [PATCH 09/15] eal: split vector operations to architecture specific
  2014-12-08  8:59 [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture Zhigang Lu
                   ` (7 preceding siblings ...)
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 08/15] eal/tile: add cycle " Zhigang Lu
@ 2014-12-08  8:59 ` Zhigang Lu
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 10/15] eal/tile: add vector operations for TileGx Zhigang Lu
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 32+ messages in thread
From: Zhigang Lu @ 2014-12-08  8:59 UTC (permalink / raw)
  To: dev; +Cc: Cyril Chemparathy

This patch splits vector operations from DPDK and push them
to architecture specific arch directories, so that other processor
architecture can implement its own vector functions to support DPDK.

Signed-off-by: Zhigang Lu <zlu@ezchip.com>
Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
---
 lib/librte_eal/common/Makefile                     |  3 +-
 .../common/include/arch/ppc_64/rte_common_vect.h   | 73 +++++++++++++++++
 .../common/include/arch/x86/rte_common_vect.h      | 81 +++++++++++++++++++
 .../common/include/generic/rte_common_vect.h       | 51 ++++++++++++
 lib/librte_eal/common/include/rte_common_vect.h    | 93 ----------------------
 5 files changed, 206 insertions(+), 95 deletions(-)
 create mode 100644 lib/librte_eal/common/include/arch/ppc_64/rte_common_vect.h
 create mode 100644 lib/librte_eal/common/include/arch/x86/rte_common_vect.h
 create mode 100644 lib/librte_eal/common/include/generic/rte_common_vect.h
 delete mode 100644 lib/librte_eal/common/include/rte_common_vect.h

diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index 52c1a5f..02cac22 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -39,7 +39,6 @@ INC += rte_rwlock.h rte_tailq.h rte_interrupts.h rte_alarm.h
 INC += rte_string_fns.h rte_version.h rte_tailq_elem.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
 INC += rte_hexdump.h rte_devargs.h rte_dev.h
-INC += rte_common_vect.h
 INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
 
 ifeq ($(CONFIG_RTE_INSECURE_FUNCTION_WARNING),y)
@@ -47,7 +46,7 @@ INC += rte_warnings.h
 endif
 
 GENERIC_INC := rte_atomic.h rte_byteorder.h rte_cycles.h rte_prefetch.h
-GENERIC_INC += rte_spinlock.h rte_memcpy.h rte_cpuflags.h
+GENERIC_INC += rte_spinlock.h rte_memcpy.h rte_cpuflags.h rte_common_vect.h
 # defined in mk/arch/$(RTE_ARCH)/rte.vars.mk
 ARCH_DIR ?= $(RTE_ARCH)
 ARCH_INC := $(notdir $(wildcard $(RTE_SDK)/lib/librte_eal/common/include/arch/$(ARCH_DIR)/*.h))
diff --git a/lib/librte_eal/common/include/arch/ppc_64/rte_common_vect.h b/lib/librte_eal/common/include/arch/ppc_64/rte_common_vect.h
new file mode 100644
index 0000000..485b7eb
--- /dev/null
+++ b/lib/librte_eal/common/include/arch/ppc_64/rte_common_vect.h
@@ -0,0 +1,73 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. 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_COMMON_VECT_PPC_64_H_
+#define _RTE_COMMON_VECT_PPC_64_H_
+
+/**
+ * @file
+ *
+ * RTE SSE/AVX related header.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "generic/rte_common_vect.h"
+
+#if (defined(__ICC) || (__GNUC__ == 4 &&  __GNUC_MINOR__ < 4))
+
+#ifdef __SSE__
+#include <xmmintrin.h>
+#endif
+
+#ifdef __SSE2__
+#include <emmintrin.h>
+#endif
+
+#if defined(__SSE4_2__) || defined(__SSE4_1__)
+#include <smmintrin.h>
+#endif
+
+#else
+
+#include <x86intrin.h>
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_COMMON__VECT_PPC_64_H_ */
diff --git a/lib/librte_eal/common/include/arch/x86/rte_common_vect.h b/lib/librte_eal/common/include/arch/x86/rte_common_vect.h
new file mode 100644
index 0000000..5ffe3fb
--- /dev/null
+++ b/lib/librte_eal/common/include/arch/x86/rte_common_vect.h
@@ -0,0 +1,81 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. 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_COMMON_VECT_X86_H_
+#define _RTE_COMMON_VECT_X86_H_
+
+/**
+ * @file
+ *
+ * RTE SSE/AVX related header.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "generic/rte_common_vect.h"
+
+#if (defined(__ICC) || (__GNUC__ == 4 &&  __GNUC_MINOR__ < 4))
+
+#ifdef __SSE__
+#include <xmmintrin.h>
+#endif
+
+#ifdef __SSE2__
+#include <emmintrin.h>
+#endif
+
+#if defined(__SSE4_2__) || defined(__SSE4_1__)
+#include <smmintrin.h>
+#endif
+
+#else
+
+#include <x86intrin.h>
+
+#endif
+
+#ifdef RTE_ARCH_I686
+#define _mm_cvtsi128_si64(a) ({ \
+	rte_xmm_t m;            \
+	m.m = (a);              \
+	(m.u64[0]);             \
+})
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_COMMON__VECT_X86_H_ */
diff --git a/lib/librte_eal/common/include/generic/rte_common_vect.h b/lib/librte_eal/common/include/generic/rte_common_vect.h
new file mode 100644
index 0000000..3e32682
--- /dev/null
+++ b/lib/librte_eal/common/include/generic/rte_common_vect.h
@@ -0,0 +1,51 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. 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_COMMON_VECT_H_
+#define _RTE_COMMON_VECT_H_
+
+typedef __m128i xmm_t;
+
+#define	XMM_SIZE	(sizeof(xmm_t))
+#define	XMM_MASK	(XMM_SIZE - 1)
+
+typedef union rte_xmm {
+	xmm_t    m;
+	uint8_t  u8[XMM_SIZE / sizeof(uint8_t)];
+	uint16_t u16[XMM_SIZE / sizeof(uint16_t)];
+	uint32_t u32[XMM_SIZE / sizeof(uint32_t)];
+	uint64_t u64[XMM_SIZE / sizeof(uint64_t)];
+	double   pd[XMM_SIZE / sizeof(double)];
+} rte_xmm_t;
+
+#endif /* _RTE_COMMON__VECT_H_ */
diff --git a/lib/librte_eal/common/include/rte_common_vect.h b/lib/librte_eal/common/include/rte_common_vect.h
deleted file mode 100644
index 95bf4b1..0000000
--- a/lib/librte_eal/common/include/rte_common_vect.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. 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_COMMON_VECT_H_
-#define _RTE_COMMON_VECT_H_
-
-/**
- * @file
- *
- * RTE SSE/AVX related header.
- */
-
-#if (defined(__ICC) || (__GNUC__ == 4 &&  __GNUC_MINOR__ < 4))
-
-#ifdef __SSE__
-#include <xmmintrin.h>
-#endif
-
-#ifdef __SSE2__
-#include <emmintrin.h>
-#endif
-
-#if defined(__SSE4_2__) || defined(__SSE4_1__)
-#include <smmintrin.h>
-#endif
-
-#else
-
-#include <x86intrin.h>
-
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef __m128i xmm_t;
-
-#define	XMM_SIZE	(sizeof(xmm_t))
-#define	XMM_MASK	(XMM_SIZE - 1)
-
-typedef union rte_xmm {
-	xmm_t    m;
-	uint8_t  u8[XMM_SIZE / sizeof(uint8_t)];
-	uint16_t u16[XMM_SIZE / sizeof(uint16_t)];
-	uint32_t u32[XMM_SIZE / sizeof(uint32_t)];
-	uint64_t u64[XMM_SIZE / sizeof(uint64_t)];
-	double   pd[XMM_SIZE / sizeof(double)];
-} rte_xmm_t;
-
-#ifdef RTE_ARCH_I686
-#define _mm_cvtsi128_si64(a) ({ \
-	rte_xmm_t m;            \
-	m.m = (a);              \
-	(m.u64[0]);             \
-})
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _RTE_COMMON__VECT_H_ */
-- 
2.1.2

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [dpdk-dev] [PATCH 10/15] eal/tile: add vector operations for TileGx
  2014-12-08  8:59 [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture Zhigang Lu
                   ` (8 preceding siblings ...)
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 09/15] eal: split vector operations to architecture specific Zhigang Lu
@ 2014-12-08  8:59 ` Zhigang Lu
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 11/15] eal/tile: add EAL support for global mPIPE initialization Zhigang Lu
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 32+ messages in thread
From: Zhigang Lu @ 2014-12-08  8:59 UTC (permalink / raw)
  To: dev; +Cc: Cyril Chemparathy

Signed-off-by: Zhigang Lu <zlu@ezchip.com>
Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
---
 .../common/include/arch/tile/rte_common_vect.h     | 49 ++++++++++++++++++++++
 1 file changed, 49 insertions(+)
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_common_vect.h

diff --git a/lib/librte_eal/common/include/arch/tile/rte_common_vect.h b/lib/librte_eal/common/include/arch/tile/rte_common_vect.h
new file mode 100644
index 0000000..f759a20
--- /dev/null
+++ b/lib/librte_eal/common/include/arch/tile/rte_common_vect.h
@@ -0,0 +1,49 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2014 Tilera Corporation. 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 Tilera 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_COMMON_VECT_TILE_H_
+#define _RTE_COMMON_VECT_TILE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "generic/rte_common_vect.h"
+
+typedef long __m128i __attribute__ ((__vector_size__ (16)));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_COMMON__VECT_X86_H_ */
-- 
2.1.2

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [dpdk-dev] [PATCH 11/15] eal/tile: add EAL support for global mPIPE initialization
  2014-12-08  8:59 [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture Zhigang Lu
                   ` (9 preceding siblings ...)
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 10/15] eal/tile: add vector operations for TileGx Zhigang Lu
@ 2014-12-08  8:59 ` Zhigang Lu
  2014-12-08 20:03   ` Neil Horman
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 12/15] eal/tile: add mPIPE buffer stack mempool provider Zhigang Lu
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 32+ messages in thread
From: Zhigang Lu @ 2014-12-08  8:59 UTC (permalink / raw)
  To: dev; +Cc: Cyril Chemparathy

The TileGx mPIPE hardware provides Ethernet connectivity,
packet classification, and packet load balancing services.

Signed-off-by: Zhigang Lu <zlu@ezchip.com>
Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
---
 .../common/include/arch/tile/rte_mpipe.h           |  67 ++++++++++
 lib/librte_eal/linuxapp/eal/Makefile               |   3 +
 lib/librte_eal/linuxapp/eal/eal.c                  |   9 ++
 lib/librte_eal/linuxapp/eal/eal_mpipe_tile.c       | 147 +++++++++++++++++++++
 mk/rte.app.mk                                      |   4 +
 5 files changed, 230 insertions(+)
 create mode 100644 lib/librte_eal/common/include/arch/tile/rte_mpipe.h
 create mode 100644 lib/librte_eal/linuxapp/eal/eal_mpipe_tile.c

diff --git a/lib/librte_eal/common/include/arch/tile/rte_mpipe.h b/lib/librte_eal/common/include/arch/tile/rte_mpipe.h
new file mode 100644
index 0000000..11b6485
--- /dev/null
+++ b/lib/librte_eal/common/include/arch/tile/rte_mpipe.h
@@ -0,0 +1,67 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2014 Tilera Corporation. 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 Tilera 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_TILE_MPIPE_H_
+#define _RTE_TILE_MPIPE_H_
+
+#define ARCH_ATOMIC_NO_NICKNAMES
+
+#include <gxio/mpipe.h>
+#include <arch/mpipe_xaui_def.h>
+#include <arch/mpipe_gbe_def.h>
+
+#define BSM_ALIGN_SIZE 128
+
+struct rte_eal_mpipe_channel_config {
+	int enable;
+	int first_bucket;
+	int num_buckets;
+	int headroom;
+	gxio_mpipe_rules_stacks_t stacks;
+};
+
+#define __bsm_aligned __attribute__((__aligned__(BSM_ALIGN_SIZE)))
+
+extern int rte_eal_mpipe_instances;
+
+extern int
+rte_eal_mpipe_init(void);
+
+extern gxio_mpipe_context_t *
+rte_eal_mpipe_context(int instance);
+
+extern int
+rte_eal_mpipe_channel_config(int instance, int channel,
+			     struct rte_eal_mpipe_channel_config *config);
+
+#endif /* _RTE_TILE_MPIPE_H_ */
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 72ecf3a..99536b6 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -70,6 +70,9 @@ SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_alarm.c
 ifeq ($(CONFIG_RTE_LIBRTE_IVSHMEM),y)
 SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_ivshmem.c
 endif
+ifeq ($(CONFIG_RTE_ARCH),"tile")
+SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_mpipe_tile.c
+endif
 
 # from common dir
 SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_memzone.c
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 89f3b5e..c97a090 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -78,6 +78,10 @@
 #include <malloc_heap.h>
 #include <rte_eth_ring.h>
 
+#ifdef RTE_ARCH_TILE
+#include <rte_mpipe.h>
+#endif
+
 #include "eal_private.h"
 #include "eal_thread.h"
 #include "eal_internal_cfg.h"
@@ -755,6 +759,11 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_init() < 0)
 		rte_panic("Cannot init PCI\n");
 
+#ifdef RTE_ARCH_TILE
+	if (rte_eal_mpipe_init() < 0)
+		rte_panic("Cannot init mPIPE\n");
+#endif
+
 #ifdef RTE_LIBRTE_IVSHMEM
 	if (rte_eal_ivshmem_init() < 0)
 		rte_panic("Cannot init IVSHMEM\n");
diff --git a/lib/librte_eal/linuxapp/eal/eal_mpipe_tile.c b/lib/librte_eal/linuxapp/eal/eal_mpipe_tile.c
new file mode 100644
index 0000000..7b0f94b
--- /dev/null
+++ b/lib/librte_eal/linuxapp/eal/eal_mpipe_tile.c
@@ -0,0 +1,147 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2014 Tilera Corporation. 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 Tilera 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 <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <sys/mman.h>
+#include <sys/queue.h>
+#include <pthread.h>
+#include <errno.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_cycles.h>
+#include <rte_tailq.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_spinlock.h>
+#include <rte_eal.h>
+#include <rte_debug.h>
+
+#include <rte_mpipe.h>
+
+#include "eal_private.h"
+#include "eal_internal_cfg.h"
+
+#define MPIPE_MAX_CHANNELS	128
+
+struct rte_eal_mpipe_context {
+	rte_spinlock_t        lock;
+	gxio_mpipe_context_t  context;
+	struct rte_eal_mpipe_channel_config channels[MPIPE_MAX_CHANNELS];
+};
+
+struct rte_eal_mpipe_context rte_eal_mpipe_contexts[GXIO_MPIPE_INSTANCE_MAX];
+int rte_eal_mpipe_instances;
+
+int
+rte_eal_mpipe_init(void)
+{
+	struct rte_eal_mpipe_context *context;
+	int rc, instance;
+
+	for (instance = 0; instance < GXIO_MPIPE_INSTANCE_MAX; instance++) {
+		context = &rte_eal_mpipe_contexts[instance];
+
+		rte_spinlock_init(&context->lock);
+		rc = gxio_mpipe_init(&context->context,
+				     instance);
+		if (rc < 0)
+			break;
+	}
+
+	rte_eal_mpipe_instances = instance;
+
+	return instance ? 0 : -ENODEV;
+}
+
+gxio_mpipe_context_t *
+rte_eal_mpipe_context(int instance)
+{
+	if (instance < 0 || instance >= rte_eal_mpipe_instances)
+		return NULL;
+	return &rte_eal_mpipe_contexts[instance].context;
+}
+
+int
+rte_eal_mpipe_channel_config(int instance, int channel,
+			     struct rte_eal_mpipe_channel_config *config)
+{
+	struct rte_eal_mpipe_channel_config *data;
+	struct rte_eal_mpipe_context *context;
+	gxio_mpipe_rules_t rules;
+	int idx, rc = 0;
+
+	if (instance < 0 || instance >= rte_eal_mpipe_instances ||
+	    channel < 0 || channel >= MPIPE_MAX_CHANNELS)
+		return -EINVAL;
+
+	context = &rte_eal_mpipe_contexts[instance];
+
+	rte_spinlock_lock(&context->lock);
+
+	gxio_mpipe_rules_init(&rules, &context->context);
+
+	for (idx = 0; idx < MPIPE_MAX_CHANNELS; idx++) {
+		data = (channel == idx) ? config : &context->channels[idx];
+
+		if (!data->enable)
+			continue;
+
+		rc = gxio_mpipe_rules_begin(&rules, data->first_bucket,
+					    data->num_buckets, &data->stacks);
+		if (rc < 0)
+			goto done;
+
+		rc = gxio_mpipe_rules_add_channel(&rules, idx);
+		if (rc < 0)
+			goto done;
+
+		rc = gxio_mpipe_rules_set_headroom(&rules, data->headroom);
+		if (rc < 0)
+			goto done;
+	}
+
+	rc = gxio_mpipe_rules_commit(&rules);
+	if (rc == 0)
+		memcpy(&context->channels[channel], config, sizeof(*config));
+
+done:
+	rte_spinlock_unlock(&context->lock);
+
+	return rc;
+}
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 84ec4df..565aa77 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -170,6 +170,10 @@ LDLIBS += -lrte_pmd_xenvirt
 LDLIBS += -lxenstore
 endif
 
+ifeq ($(CONFIG_RTE_ARCH),"tile")
+LDLIBS += -lgxio
+endif
+
 ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n)
 # plugins (link only if static libraries)
 
-- 
2.1.2

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [dpdk-dev] [PATCH 12/15] eal/tile: add mPIPE buffer stack mempool provider
  2014-12-08  8:59 [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture Zhigang Lu
                   ` (10 preceding siblings ...)
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 11/15] eal/tile: add EAL support for global mPIPE initialization Zhigang Lu
@ 2014-12-08  8:59 ` Zhigang Lu
  2014-12-09 14:07   ` Neil Horman
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 13/15] pmd/tile: add mPIPE poll mode driver for TileGx Zhigang Lu
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 32+ messages in thread
From: Zhigang Lu @ 2014-12-08  8:59 UTC (permalink / raw)
  To: dev; +Cc: Cyril Chemparathy

TileGX: Modified mempool to allow for variable metadata.
Signed-off-by: Zhigang Lu <zlu@ezchip.com>
Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
---
 app/test-pmd/mempool_anon.c           |   2 +-
 app/test/Makefile                     |   6 +-
 app/test/test_mempool_tile.c          | 217 ++++++++++++
 lib/Makefile                          |   5 +
 lib/librte_eal/linuxapp/eal/Makefile  |   4 +
 lib/librte_mempool_tile/Makefile      |  48 +++
 lib/librte_mempool_tile/rte_mempool.c | 381 ++++++++++++++++++++
 lib/librte_mempool_tile/rte_mempool.h | 634 ++++++++++++++++++++++++++++++++++
 8 files changed, 1295 insertions(+), 2 deletions(-)
 create mode 100644 app/test/test_mempool_tile.c
 create mode 100644 lib/librte_mempool_tile/Makefile
 create mode 100644 lib/librte_mempool_tile/rte_mempool.c
 create mode 100644 lib/librte_mempool_tile/rte_mempool.h

diff --git a/app/test-pmd/mempool_anon.c b/app/test-pmd/mempool_anon.c
index 559a625..05b4c77 100644
--- a/app/test-pmd/mempool_anon.c
+++ b/app/test-pmd/mempool_anon.c
@@ -36,7 +36,7 @@
 #include "mempool_osdep.h"
 #include <rte_errno.h>
 
-#ifdef RTE_EXEC_ENV_LINUXAPP
+#if defined(RTE_EXEC_ENV_LINUXAPP) && !defined(RTE_ARCH_TILE)
 
 #include <fcntl.h>
 #include <unistd.h>
diff --git a/app/test/Makefile b/app/test/Makefile
index 4311f96..40ad971 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -72,10 +72,14 @@ SRCS-y += test_rwlock.c
 SRCS-$(CONFIG_RTE_LIBRTE_TIMER) += test_timer.c
 SRCS-$(CONFIG_RTE_LIBRTE_TIMER) += test_timer_perf.c
 
+ifeq ($(CONFIG_RTE_ARCH),"tile")
+SRCS-y += test_mempool_tile.c
+else
 SRCS-y += test_mempool.c
 SRCS-y += test_mempool_perf.c
-
 SRCS-y += test_mbuf.c
+endif
+
 SRCS-y += test_logs.c
 
 SRCS-y += test_memcpy.c
diff --git a/app/test/test_mempool_tile.c b/app/test/test_mempool_tile.c
new file mode 100644
index 0000000..41a375d
--- /dev/null
+++ b/app/test/test_mempool_tile.c
@@ -0,0 +1,217 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. 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 <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_cycles.h>
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_spinlock.h>
+#include <rte_malloc.h>
+
+#include "test.h"
+
+/*
+ * Mempool
+ * =======
+ *
+ * Basic tests: done on one core with and without cache:
+ *
+ *    - Get one object, put one object
+ *    - Get two objects, put two objects
+ *    - Get all objects, test that their content is not modified and
+ *      put them back in the pool.
+ */
+
+#define MEMPOOL_ELT_SIZE 2048
+#define MEMPOOL_SIZE (8 * 1024)
+
+static struct rte_mempool *mp;
+
+
+/*
+ * save the object number in the first 4 bytes of object data. All
+ * other bytes are set to 0.
+ */
+static void
+my_obj_init(struct rte_mempool *mp, __attribute__((unused)) void *arg,
+	    void *obj, unsigned i)
+{
+	uint32_t *objnum = obj;
+
+	memset(obj, 0, mp->elt_size);
+	*objnum = i;
+}
+
+/* basic tests (done on one core) */
+static int
+test_mempool_basic(void)
+{
+	uint32_t *objnum;
+	void **objtable;
+	void *obj, *obj2;
+	char *obj_data;
+	int ret = 0;
+	unsigned i, j;
+
+	/* dump the mempool status */
+	rte_mempool_dump(stdout, mp);
+
+	printf("get an object\n");
+	if (rte_mempool_get(mp, &obj) < 0)
+		return -1;
+	rte_mempool_dump(stdout, mp);
+
+	printf("get private data\n");
+	if (rte_mempool_get_priv(mp) != (char *) mp + sizeof(*mp))
+		return -1;
+
+	printf("get physical address of an object\n");
+	if (rte_mempool_virt2phy(mp, obj) !=
+			(phys_addr_t) (mp->phys_addr +
+			(phys_addr_t) ((char *) obj - (char *) mp)))
+		return -1;
+
+	printf("put the object back\n");
+	rte_mempool_put(mp, obj);
+	rte_mempool_dump(stdout, mp);
+
+	printf("get 2 objects\n");
+	if (rte_mempool_get(mp, &obj) < 0)
+		return -1;
+	if (rte_mempool_get(mp, &obj2) < 0) {
+		rte_mempool_put(mp, obj);
+		return -1;
+	}
+	rte_mempool_dump(stdout, mp);
+
+	printf("put the objects back\n");
+	rte_mempool_put(mp, obj);
+	rte_mempool_put(mp, obj2);
+	rte_mempool_dump(stdout, mp);
+
+	/*
+	 * get many objects: we cannot get them all because the cache
+	 * on other cores may not be empty.
+	 */
+	objtable = malloc(MEMPOOL_SIZE * sizeof(void *));
+	if (objtable == NULL)
+		return -1;
+
+	for (i = 0; i < MEMPOOL_SIZE; i++) {
+		if (rte_mempool_get(mp, &objtable[i]) < 0)
+			break;
+	}
+
+	printf("got %d buffers\n", i);
+	rte_mempool_dump(stdout, mp);
+
+	/*
+	 * for each object, check that its content was not modified,
+	 * and put objects back in pool
+	 */
+	while (i--) {
+		obj = objtable[i];
+		obj_data = obj;
+		objnum = obj;
+		if (*objnum > MEMPOOL_SIZE) {
+			printf("bad object number %u @%p\n", *objnum, objnum);
+			ret = -1;
+			break;
+		}
+		for (j = sizeof(*objnum); j < mp->elt_size; j++) {
+			if (obj_data[j] != 0)
+				ret = -1;
+		}
+
+		rte_mempool_put(mp, objtable[i]);
+	}
+
+	free(objtable);
+	if (ret == -1)
+		printf("objects were modified!\n");
+
+	return ret;
+}
+
+static int
+test_mempool(void)
+{
+	/* create a mempool (without cache) */
+	if (mp == NULL)
+		mp = rte_mempool_create("test", MEMPOOL_SIZE,
+						MEMPOOL_ELT_SIZE, 0, 0,
+						NULL, NULL,
+						my_obj_init, NULL,
+						SOCKET_ID_ANY, 0);
+	if (mp == NULL)
+		return -1;
+
+	/* retrieve the mempool from its name */
+	if (rte_mempool_lookup("test") != mp) {
+		printf("Cannot lookup mempool from its name\n");
+		return -1;
+	}
+
+	/* basic tests without cache */
+	mp = mp;
+	if (test_mempool_basic() < 0)
+		return -1;
+
+	return 0;
+}
+
+static struct test_command mempool_cmd = {
+	.command = "mempool_autotest",
+	.callback = test_mempool,
+};
+REGISTER_TEST_COMMAND(mempool_cmd);
diff --git a/lib/Makefile b/lib/Makefile
index 0ffc982..60aa0ff 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -34,7 +34,12 @@ include $(RTE_SDK)/mk/rte.vars.mk
 DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal
 DIRS-$(CONFIG_RTE_LIBRTE_MALLOC) += librte_malloc
 DIRS-$(CONFIG_RTE_LIBRTE_RING) += librte_ring
+ifeq ($(CONFIG_RTE_ARCH),"tile")
+DIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += librte_mempool_tile
+ODIR-librte_mempool_tile = librte_mempool
+else
 DIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += librte_mempool
+endif
 DIRS-$(CONFIG_RTE_LIBRTE_MBUF) += librte_mbuf
 DIRS-$(CONFIG_RTE_LIBRTE_TIMER) += librte_timer
 DIRS-$(CONFIG_RTE_LIBRTE_CFGFILE) += librte_cfgfile
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 99536b6..74aa503 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -39,7 +39,11 @@ CFLAGS += -I$(SRCDIR)/include
 CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common
 CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include
 CFLAGS += -I$(RTE_SDK)/lib/librte_ring
+ifeq ($(CONFIG_RTE_ARCH),"tile")
+CFLAGS += -I$(RTE_SDK)/lib/librte_mempool_tile
+else
 CFLAGS += -I$(RTE_SDK)/lib/librte_mempool
+endif
 CFLAGS += -I$(RTE_SDK)/lib/librte_malloc
 CFLAGS += -I$(RTE_SDK)/lib/librte_ether
 CFLAGS += -I$(RTE_SDK)/lib/librte_ivshmem
diff --git a/lib/librte_mempool_tile/Makefile b/lib/librte_mempool_tile/Makefile
new file mode 100644
index 0000000..65e8fa0
--- /dev/null
+++ b/lib/librte_mempool_tile/Makefile
@@ -0,0 +1,48 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2010-2014 Intel Corporation. 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_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_mempool.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3
+CFLAGS += -I$(RTE_SDK)/lib/librte_mbuf
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_MEMPOOL) +=  rte_mempool.c
+# install includes
+SYMLINK-$(CONFIG_RTE_LIBRTE_MEMPOOL)-include := rte_mempool.h
+
+# this lib needs eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += lib/librte_eal
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_mempool_tile/rte_mempool.c b/lib/librte_mempool_tile/rte_mempool.c
new file mode 100644
index 0000000..96ecaac
--- /dev/null
+++ b/lib/librte_mempool_tile/rte_mempool.c
@@ -0,0 +1,381 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. 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 <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_malloc.h>
+#include <rte_atomic.h>
+#include <rte_launch.h>
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_mbuf.h>
+#include <rte_eal_memconfig.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_ring.h>
+#include <rte_errno.h>
+#include <rte_string_fns.h>
+#include <rte_spinlock.h>
+
+#include "rte_mempool.h"
+
+/*
+ * The mPIPE buffer stack requires 128 byte aligned buffers, and restricts
+ * available headroom to a max of 127 bytes.  As a result of these
+ * restrictions, we keep the buffer metadata (mbuf, ofpbuf, etc.) outside the
+ * "mPIPE buffer", with some careful alignment jugglery and probing.
+ *
+ * The layout of each element in the mPIPE mempool is therefore as follows:
+ *
+ *   +--------------------------------+
+ *   | variable sized pad space       |
+ *   +--------------------------------+ cacheline boundary
+ *   | struct rte_mempool_obj_header  |
+ *   +--------------------------------+ cacheline boundary
+ *   | struct rte_mbuf/ofpbuf/...     |
+ *   +--------------------------------+ 128 byte aligned boundary
+ *   | buffer data headroom           |
+ *   |                                |
+ *   | buffer data                    |
+ *   |                                |
+ *   +--------------------------------+
+ *
+ * The addresses pushed into the mPIPE buffer stack are the 128 byte aligned
+ * start address of the buffer headroom.  The mempool user transacts in
+ * objects that point to the start of the rte_mbuf/ofpbuf structures in the
+ * element.  These objects cannot directly be pushed into the mPIPE buffer
+ * stack.
+ */
+
+#define BSM_MEM_ALIGN		65536
+#define BSM_MAX_META		(4 * RTE_CACHE_LINE_SIZE)
+
+TAILQ_HEAD(rte_mempool_list, rte_tailq_entry);
+
+const struct rte_mempool *last_mp;
+
+/* register buffer memory with mPIPE. */
+static int
+__bsm_register_mem(struct rte_mempool *mp, void *mem, size_t size)
+{
+	uintptr_t pagesz = mp->mz->hugepage_sz;
+	uintptr_t start = (uintptr_t)mem & ~(pagesz - 1);
+	uintptr_t end = (uintptr_t)mem + size;
+	int rc, count = 0;
+
+	while (start < end) {
+		rc = gxio_mpipe_register_page(mp->context, mp->stack_idx,
+					      (void *)start, pagesz, 0);
+		if (rc < 0)
+			return rc;
+		start += pagesz;
+		count++;
+	}
+	return count;
+}
+
+/* Probe the element constructor to figure out the metadata size. */
+static unsigned
+__bsm_meta_size(unsigned elt_size, rte_mempool_obj_ctor_t *obj_init,
+		void *obj_init_arg)
+{
+	struct rte_mempool mp;
+	unsigned offset;
+	union {
+		struct rte_mbuf mbuf;
+		unsigned char data[elt_size];
+	} u;
+
+	if (!obj_init) {
+		RTE_LOG(ERR, MEMPOOL, "No constructor to probe meta size!\n");
+		return 0;
+	}
+
+	memset(&u, 0, sizeof(u));
+	memset(&mp, 0, sizeof(mp));
+
+	mp.elt_size = elt_size;
+
+	obj_init(&mp, obj_init_arg, &u.mbuf, 0);
+
+	offset = (uintptr_t)u.mbuf.buf_addr - (uintptr_t)&u.mbuf;
+	if (offset > BSM_MAX_META) {
+		RTE_LOG(ERR, MEMPOOL, "Meta data overflow (%d > %d)!\n",
+			offset, BSM_MAX_META);
+		return 0;
+	}
+
+	RTE_LOG(ERR, MEMPOOL, "Meta data probed to be %d\n",
+		offset);
+
+	return offset;
+}
+
+/* create the mempool */
+struct rte_mempool *
+rte_mempool_create(const char *name, unsigned n, unsigned elt_size,
+		   unsigned cache_size __rte_unused, unsigned private_data_size,
+		   rte_mempool_ctor_t *mp_init, void *mp_init_arg,
+		   rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg,
+		   int socket_id, unsigned flags)
+{
+	unsigned bsm_size, meta_size, pool_size, total_size, i;
+	int mz_flags = RTE_MEMZONE_1GB | RTE_MEMZONE_SIZE_HINT_ONLY;
+	gxio_mpipe_buffer_size_enum_t size_code;
+	char mz_name[RTE_MEMZONE_NAMESIZE];
+	gxio_mpipe_context_t *context;
+	const struct rte_memzone *mz;
+	int rc, instance, stack_idx;
+	struct rte_tailq_entry *te;
+	struct rte_mempool *mp;
+	void *obj, *buf;
+	char *mem;
+
+	instance = socket_id % rte_eal_mpipe_instances;
+	context = rte_eal_mpipe_context(instance);
+
+	if (!context) {
+		RTE_LOG(ERR, MEMPOOL, "No mPIPE context!\n");
+		return NULL;
+	}
+
+	/* check that we have an initialised tail queue */
+	if (RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_MEMPOOL,
+			rte_mempool_list) == NULL) {
+		RTE_LOG(ERR, MEMPOOL, "Uninitialized tailq list!\n");
+		return NULL;
+	}
+
+	/* We cannot operate without hugepages. */
+	if (!rte_eal_has_hugepages()) {
+		RTE_LOG(ERR, MEMPOOL, "Mempool requires hugepages!\n");
+		return NULL;
+	}
+
+	/* try to allocate tailq entry */
+	te = rte_zmalloc("MEMPOOL_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, MEMPOOL, "Cannot allocate tailq entry!\n");
+		return NULL;
+	}
+
+	bsm_size  = gxio_mpipe_calc_buffer_stack_bytes(n);
+	bsm_size  = RTE_ALIGN_CEIL(bsm_size, BSM_ALIGN_SIZE);
+
+	pool_size = sizeof(struct rte_mempool) + private_data_size;
+	pool_size = RTE_ALIGN_CEIL(pool_size, BSM_ALIGN_SIZE);
+
+	meta_size = __bsm_meta_size(elt_size, obj_init, obj_init_arg);
+	size_code =
+	gxio_mpipe_buffer_size_to_buffer_size_enum(elt_size - meta_size);
+	elt_size  = gxio_mpipe_buffer_size_enum_to_buffer_size(size_code) +
+			meta_size;
+
+	total_size = (BSM_MEM_ALIGN + bsm_size + pool_size + n * elt_size);
+
+	snprintf(mz_name, sizeof(mz_name), RTE_MEMPOOL_MZ_FORMAT, name);
+
+	rc = gxio_mpipe_alloc_buffer_stacks(context, 1, 0, 0);
+	if (rc < 0) {
+		RTE_LOG(ERR, MEMPOOL, "Cannot allocate buffer stack!\n");
+		return NULL;
+	}
+	stack_idx = rc;
+
+	rte_rwlock_write_lock(RTE_EAL_MEMPOOL_RWLOCK);
+
+	mz = rte_memzone_reserve(mz_name, total_size, socket_id, mz_flags);
+	if (!mz) {
+		rte_rwlock_write_unlock(RTE_EAL_MEMPOOL_RWLOCK);
+		return NULL;
+	}
+
+	mem = mz->addr;
+	mp  = mz->addr;
+	memset(mp, 0, sizeof(*mp));
+	snprintf(mp->name, sizeof(mp->name), "%s", name);
+	mp->phys_addr = mz->phys_addr;
+	mp->mz = mz;
+	mp->size = n;
+	mp->flags = flags;
+	mp->meta_size = meta_size;
+	mp->elt_size = elt_size;
+	mp->private_data_size = private_data_size;
+	mp->stack_idx = stack_idx;
+	mp->size_code = size_code;
+	mp->context = context;
+	mp->instance = instance;
+
+	mem += pool_size;
+
+	mem = RTE_PTR_ALIGN_CEIL(mem, BSM_MEM_ALIGN);
+	rc = gxio_mpipe_init_buffer_stack(context, stack_idx, size_code,
+					  mem, bsm_size, 0);
+	if (rc < 0) {
+		rte_rwlock_write_unlock(RTE_EAL_MEMPOOL_RWLOCK);
+		RTE_LOG(ERR, MEMPOOL, "Cannot initialize buffer stack!\n");
+		return NULL;
+	}
+	mem += bsm_size;
+
+	mem = RTE_PTR_ALIGN_CEIL(mem, BSM_ALIGN_SIZE);
+	rc = __bsm_register_mem(mp, mem, n * elt_size);
+	if (rc < 0) {
+		rte_rwlock_write_unlock(RTE_EAL_MEMPOOL_RWLOCK);
+		RTE_LOG(ERR, MEMPOOL, "Cannot register buffer mem (%d)!\n", rc);
+		return NULL;
+	}
+
+	/* call the initializer */
+	if (mp_init)
+		mp_init(mp, mp_init_arg);
+
+	for (i = 0; i < n; i++) {
+		buf = RTE_PTR_ALIGN_CEIL(mem + meta_size, BSM_ALIGN_SIZE);
+		obj = __mempool_buf_to_obj(mp, buf);
+
+		if (obj_init)
+			obj_init(mp, obj_init_arg, obj, i);
+		rte_mempool_mp_put(mp, obj);
+		mem = RTE_PTR_ADD(obj, mp->elt_size);
+	}
+
+	te->data = (void *) mp;
+	RTE_EAL_TAILQ_INSERT_TAIL(RTE_TAILQ_MEMPOOL, rte_mempool_list, te);
+
+	rte_rwlock_write_unlock(RTE_EAL_MEMPOOL_RWLOCK);
+
+	return mp;
+}
+
+/* dump the status of the mempool on the console */
+void
+rte_mempool_dump(FILE *f, const struct rte_mempool *mp)
+{
+	fprintf(f, "mempool <%s>@%p\n", mp->name, mp);
+	fprintf(f, "  flags=%x\n", mp->flags);
+	fprintf(f, "  count=%d\n", rte_mempool_count(mp));
+}
+
+/* dump the status of all mempools on the console */
+void
+rte_mempool_list_dump(FILE *f)
+{
+	const struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te;
+	struct rte_mempool_list *mempool_list;
+
+	mempool_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_MEMPOOL,
+						rte_mempool_list);
+	if (mempool_list == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
+
+	TAILQ_FOREACH(te, mempool_list, next) {
+		mp = (struct rte_mempool *) te->data;
+		rte_mempool_dump(f, mp);
+	}
+
+	rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK);
+}
+
+/* search a mempool from its name */
+struct rte_mempool *
+rte_mempool_lookup(const char *name)
+{
+	struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te;
+	struct rte_mempool_list *mempool_list;
+
+	mempool_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_MEMPOOL,
+						rte_mempool_list);
+	if (mempool_list == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return NULL;
+	}
+
+	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
+
+	TAILQ_FOREACH(te, mempool_list, next) {
+		mp = (struct rte_mempool *) te->data;
+		if (strncmp(name, mp->name, RTE_MEMPOOL_NAMESIZE) == 0)
+			break;
+	}
+
+	rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK);
+
+	if (te == NULL) {
+		rte_errno = ENOENT;
+		return NULL;
+	}
+
+	return mp;
+}
+
+void rte_mempool_walk(void (*func)(const struct rte_mempool *, void *),
+		      void *arg)
+{
+	struct rte_tailq_entry *te = NULL;
+	struct rte_mempool_list *mempool_list;
+
+	mempool_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_MEMPOOL,
+						rte_mempool_list);
+	if (mempool_list == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
+
+	TAILQ_FOREACH(te, mempool_list, next) {
+		(*func)((struct rte_mempool *) te->data, arg);
+	}
+
+	rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK);
+}
diff --git a/lib/librte_mempool_tile/rte_mempool.h b/lib/librte_mempool_tile/rte_mempool.h
new file mode 100644
index 0000000..ca893d5
--- /dev/null
+++ b/lib/librte_mempool_tile/rte_mempool.h
@@ -0,0 +1,634 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. 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_MEMPOOL_TILE_H_
+#define _RTE_MEMPOOL_TILE_H_
+
+/**
+ * @file
+ * RTE Mempool.
+ *
+ * A memory pool is an allocator of fixed-size object. It is
+ * identified by its name, and uses a ring to store free objects. It
+ * provides some other optional services, like a per-core object
+ * cache, and an alignment helper to ensure that objects are padded
+ * to spread them equally on all RAM channels, ranks, and so on.
+ *
+ * Objects owned by a mempool should never be added in another
+ * mempool. When an object is freed using rte_mempool_put() or
+ * equivalent, the object data is not modified; the user can save some
+ * meta-data in the object data and retrieve them when allocating a
+ * new object.
+ *
+ * Note: the mempool implementation is not preemptable. A lcore must
+ * not be interrupted by another task that uses the same mempool
+ * (because it uses a ring which is not preemptable). Also, mempool
+ * functions must not be used outside the DPDK environment: for
+ * example, in linuxapp environment, a thread that is not created by
+ * the EAL must not use mempools. This is due to the per-lcore cache
+ * that won't work as rte_lcore_id() will not return a correct value.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_lcore.h>
+#include <rte_common.h>
+#include <rte_memory.h>
+#include <rte_prefetch.h>
+#include <rte_branch_prediction.h>
+
+#include <rte_mpipe.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RTE_MEMPOOL_NAMESIZE	32
+#define RTE_MEMPOOL_MZ_PREFIX	"TMP_"
+#define	RTE_MEMPOOL_MZ_FORMAT	RTE_MEMPOOL_MZ_PREFIX "%s"
+#define	RTE_MEMPOOL_OBJ_NAME	RTE_MEMPOOL_MZ_FORMAT
+
+struct rte_mempool {
+	TAILQ_ENTRY(rte_mempool) next;   /**< Next in list. */
+	char         name[RTE_MEMPOOL_NAMESIZE]; /**< Name of mempool. */
+	uint32_t     flags;              /**< Flags of the mempool. */
+	uint32_t     size;               /*<< Number of elements in pool. */
+	uint32_t     elt_size;           /**< Size of an element. */
+	uint32_t     meta_size;          /**< Size of buffer metadata. */
+	int          stack_idx;          /**< mPIPE buffer stack index. */
+	int          instance;           /**< mPIPE instance. */
+	gxio_mpipe_buffer_size_enum_t size_code; /**< mPIPE buffer size enum. */
+	gxio_mpipe_context_t *context;   /**< mPIPE context. */
+	uint32_t     private_data_size;  /**< Size of private data. */
+	phys_addr_t  phys_addr;          /**< Phys. addr. of mempool struct. */
+	const struct rte_memzone *mz;    /**< Memory zone. */
+
+	char         private_data[0] __rte_cache_aligned;
+}  __rte_cache_aligned;
+
+#define MEMPOOL_F_NO_SPREAD      0x0001 /**< Do not spread in memory. */
+#define MEMPOOL_F_NO_CACHE_ALIGN 0x0002 /**< Do not align objs on cache lines.*/
+#define MEMPOOL_F_SP_PUT         0x0004 /**< Default put is "single-producer".*/
+#define MEMPOOL_F_SC_GET         0x0008 /**< Default get is "single-consumer".*/
+
+static inline void *__attribute__((always_inline))
+__mempool_buf_to_obj(const struct rte_mempool *mp, void *buf)
+{
+	return RTE_PTR_SUB(buf, mp->meta_size);
+}
+
+static inline void *__attribute__((always_inline))
+__mempool_obj_to_buf(const struct rte_mempool *mp, void *obj)
+{
+	return RTE_PTR_ADD(obj, mp->meta_size);
+}
+
+/**
+ * @internal Put several objects back in the mempool; used internally.
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_table
+ *   A pointer to a table of void * pointers (objects).
+ * @param n
+ *   The number of objects to store back in the mempool, must be strictly
+ *   positive.
+ * @param is_mp
+ *   Mono-producer (0) or multi-producers (1).
+ */
+static inline void __attribute__((always_inline))
+__mempool_put_bulk(struct rte_mempool *mp, void **obj_table,
+		    unsigned n)
+{
+	unsigned i;
+	void *buf;
+
+	for (i = 0; i < n; i++) {
+		buf = __mempool_obj_to_buf(mp, obj_table[i]);
+		gxio_mpipe_push_buffer(mp->context, mp->stack_idx, buf);
+	}
+}
+
+
+/**
+ * Put several objects back in the mempool (multi-producers safe).
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_table
+ *   A pointer to a table of void * pointers (objects).
+ * @param n
+ *   The number of objects to add in the mempool from the obj_table.
+ */
+static inline void __attribute__((always_inline))
+rte_mempool_mp_put_bulk(struct rte_mempool *mp, void **obj_table,
+			unsigned n)
+{
+	__mempool_put_bulk(mp, obj_table, n);
+}
+
+/**
+ * Put several objects back in the mempool (NOT multi-producers safe).
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_table
+ *   A pointer to a table of void * pointers (objects).
+ * @param n
+ *   The number of objects to add in the mempool from obj_table.
+ */
+static inline void __attribute__((always_inline))
+rte_mempool_sp_put_bulk(struct rte_mempool *mp, void **obj_table,
+			unsigned n)
+{
+	__mempool_put_bulk(mp, obj_table, n);
+}
+
+/**
+ * Put several objects back in the mempool.
+ *
+ * This function calls the multi-producer or the single-producer
+ * version depending on the default behavior that was specified at
+ * mempool creation time (see flags).
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_table
+ *   A pointer to a table of void * pointers (objects).
+ * @param n
+ *   The number of objects to add in the mempool from obj_table.
+ */
+static inline void __attribute__((always_inline))
+rte_mempool_put_bulk(struct rte_mempool *mp, void **obj_table,
+		     unsigned n)
+{
+	__mempool_put_bulk(mp, obj_table, n);
+}
+
+/**
+ * Put one object in the mempool (multi-producers safe).
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj
+ *   A pointer to the object to be added.
+ */
+static inline void __attribute__((always_inline))
+rte_mempool_mp_put(struct rte_mempool *mp, void *obj)
+{
+	rte_mempool_mp_put_bulk(mp, &obj, 1);
+}
+
+/**
+ * Put one object back in the mempool (NOT multi-producers safe).
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj
+ *   A pointer to the object to be added.
+ */
+static inline void __attribute__((always_inline))
+rte_mempool_sp_put(struct rte_mempool *mp, void *obj)
+{
+	rte_mempool_sp_put_bulk(mp, &obj, 1);
+}
+
+/**
+ * Put one object back in the mempool.
+ *
+ * This function calls the multi-producer or the single-producer
+ * version depending on the default behavior that was specified at
+ * mempool creation time (see flags).
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj
+ *   A pointer to the object to be added.
+ */
+static inline void __attribute__((always_inline))
+rte_mempool_put(struct rte_mempool *mp, void *obj)
+{
+	rte_mempool_put_bulk(mp, &obj, 1);
+}
+
+/**
+ * @internal Get several objects from the mempool; used internally.
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_table
+ *   A pointer to a table of void * pointers (objects).
+ * @param n
+ *   The number of objects to get, must be strictly positive.
+ * @param is_mc
+ *   Mono-consumer (0) or multi-consumers (1).
+ * @return
+ *   - >=0: Success; number of objects supplied.
+ *   - <0: Error; code of ring dequeue function.
+ */
+static inline int __attribute__((always_inline))
+__mempool_get_bulk(struct rte_mempool *mp, void **obj_table,
+		   unsigned n)
+{
+	unsigned i;
+	void *buf;
+
+	for (i = 0; i < n; i++) {
+		buf = gxio_mpipe_pop_buffer(mp->context, mp->stack_idx);
+		if (unlikely(!buf)) {
+			__mempool_put_bulk(mp, obj_table, i);
+			return -ENOENT;
+		}
+		obj_table[i] = __mempool_buf_to_obj(mp, buf);
+		rte_prefetch0(obj_table[i]);
+	}
+	return i;
+}
+
+/**
+ * Get several objects from the mempool (multi-consumers safe).
+ *
+ * If cache is enabled, objects will be retrieved first from cache,
+ * subsequently from the common pool. Note that it can return -ENOENT when
+ * the local cache and common pool are empty, even if cache from other
+ * lcores are full.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_table
+ *   A pointer to a table of void * pointers (objects) that will be filled.
+ * @param n
+ *   The number of objects to get from mempool to obj_table.
+ * @return
+ *   - 0: Success; objects taken.
+ *   - -ENOENT: Not enough entries in the mempool; no object is retrieved.
+ */
+static inline int __attribute__((always_inline))
+rte_mempool_mc_get_bulk(struct rte_mempool *mp, void **obj_table, unsigned n)
+{
+	return __mempool_get_bulk(mp, obj_table, n);
+}
+
+/**
+ * Get several objects from the mempool (NOT multi-consumers safe).
+ *
+ * If cache is enabled, objects will be retrieved first from cache,
+ * subsequently from the common pool. Note that it can return -ENOENT when
+ * the local cache and common pool are empty, even if cache from other
+ * lcores are full.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_table
+ *   A pointer to a table of void * pointers (objects) that will be filled.
+ * @param n
+ *   The number of objects to get from the mempool to obj_table.
+ * @return
+ *   - 0: Success; objects taken.
+ *   - -ENOENT: Not enough entries in the mempool; no object is
+ *     retrieved.
+ */
+static inline int __attribute__((always_inline))
+rte_mempool_sc_get_bulk(struct rte_mempool *mp, void **obj_table, unsigned n)
+{
+	return __mempool_get_bulk(mp, obj_table, n);
+}
+
+/**
+ * Get several objects from the mempool.
+ *
+ * This function calls the multi-consumers or the single-consumer
+ * version, depending on the default behaviour that was specified at
+ * mempool creation time (see flags).
+ *
+ * If cache is enabled, objects will be retrieved first from cache,
+ * subsequently from the common pool. Note that it can return -ENOENT when
+ * the local cache and common pool are empty, even if cache from other
+ * lcores are full.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_table
+ *   A pointer to a table of void * pointers (objects) that will be filled.
+ * @param n
+ *   The number of objects to get from the mempool to obj_table.
+ * @return
+ *   - 0: Success; objects taken
+ *   - -ENOENT: Not enough entries in the mempool; no object is retrieved.
+ */
+static inline int __attribute__((always_inline))
+rte_mempool_get_bulk(struct rte_mempool *mp, void **obj_table, unsigned n)
+{
+	return __mempool_get_bulk(mp, obj_table, n);
+}
+
+/**
+ * Get one object from the mempool (multi-consumers safe).
+ *
+ * If cache is enabled, objects will be retrieved first from cache,
+ * subsequently from the common pool. Note that it can return -ENOENT when
+ * the local cache and common pool are empty, even if cache from other
+ * lcores are full.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_p
+ *   A pointer to a void * pointer (object) that will be filled.
+ * @return
+ *   - 0: Success; objects taken.
+ *   - -ENOENT: Not enough entries in the mempool; no object is retrieved.
+ */
+static inline int __attribute__((always_inline))
+rte_mempool_mc_get(struct rte_mempool *mp, void **obj_p)
+{
+	return rte_mempool_mc_get_bulk(mp, obj_p, 1);
+}
+
+/**
+ * Get one object from the mempool (NOT multi-consumers safe).
+ *
+ * If cache is enabled, objects will be retrieved first from cache,
+ * subsequently from the common pool. Note that it can return -ENOENT when
+ * the local cache and common pool are empty, even if cache from other
+ * lcores are full.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_p
+ *   A pointer to a void * pointer (object) that will be filled.
+ * @return
+ *   - 0: Success; objects taken.
+ *   - -ENOENT: Not enough entries in the mempool; no object is retrieved.
+ */
+static inline int __attribute__((always_inline))
+rte_mempool_sc_get(struct rte_mempool *mp, void **obj_p)
+{
+	return rte_mempool_sc_get_bulk(mp, obj_p, 1);
+}
+
+/**
+ * Get one object from the mempool.
+ *
+ * This function calls the multi-consumers or the single-consumer
+ * version, depending on the default behavior that was specified at
+ * mempool creation (see flags).
+ *
+ * If cache is enabled, objects will be retrieved first from cache,
+ * subsequently from the common pool. Note that it can return -ENOENT when
+ * the local cache and common pool are empty, even if cache from other
+ * lcores are full.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_p
+ *   A pointer to a void * pointer (object) that will be filled.
+ * @return
+ *   - 0: Success; objects taken.
+ *   - -ENOENT: Not enough entries in the mempool; no object is retrieved.
+ */
+static inline int __attribute__((always_inline))
+rte_mempool_get(struct rte_mempool *mp, void **obj_p)
+{
+	return rte_mempool_get_bulk(mp, obj_p, 1);
+}
+
+/**
+ * An object constructor callback function for mempool.
+ *
+ * Arguments are the mempool, the opaque pointer given by the user in
+ * rte_mempool_create(), the pointer to the element and the index of
+ * the element in the pool.
+ */
+typedef void (rte_mempool_obj_ctor_t)(struct rte_mempool *, void *,
+				      void *, unsigned);
+
+/**
+ * A mempool constructor callback function.
+ *
+ * Arguments are the mempool and the opaque pointer given by the user in
+ * rte_mempool_create().
+ */
+typedef void (rte_mempool_ctor_t)(struct rte_mempool *, void *);
+
+/**
+ * Creates a new mempool named *name* in memory.
+ *
+ * This function uses ``memzone_reserve()`` to allocate memory. The
+ * pool contains n elements of elt_size. Its size is set to n.
+ * All elements of the mempool are allocated together with the mempool header,
+ * in one physically continuous chunk of memory.
+ *
+ * @param name
+ *   The name of the mempool.
+ * @param n
+ *   The number of elements in the mempool. The optimum size (in terms of
+ *   memory usage) for a mempool is when n is a power of two minus one:
+ *   n = (2^q - 1).
+ * @param elt_size
+ *   The size of each element.
+ * @param cache_size
+ *   If cache_size is non-zero, the rte_mempool library will try to
+ *   limit the accesses to the common lockless pool, by maintaining a
+ *   per-lcore object cache. This argument must be lower or equal to
+ *   CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE. It is advised to choose
+ *   cache_size to have "n modulo cache_size == 0": if this is
+ *   not the case, some elements will always stay in the pool and will
+ *   never be used. The access to the per-lcore table is of course
+ *   faster than the multi-producer/consumer pool. The cache can be
+ *   disabled if the cache_size argument is set to 0; it can be useful to
+ *   avoid losing objects in cache. Note that even if not used, the
+ *   memory space for cache is always reserved in a mempool structure,
+ *   except if CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE is set to 0.
+ * @param private_data_size
+ *   The size of the private data appended after the mempool
+ *   structure. This is useful for storing some private data after the
+ *   mempool structure, as is done for rte_mbuf_pool for example.
+ * @param mp_init
+ *   A function pointer that is called for initialization of the pool,
+ *   before object initialization. The user can initialize the private
+ *   data in this function if needed. This parameter can be NULL if
+ *   not needed.
+ * @param mp_init_arg
+ *   An opaque pointer to data that can be used in the mempool
+ *   constructor function.
+ * @param obj_init
+ *   A function pointer that is called for each object at
+ *   initialization of the pool. The user can set some meta data in
+ *   objects if needed. This parameter can be NULL if not needed.
+ *   The obj_init() function takes the mempool pointer, the init_arg,
+ *   the object pointer and the object number as parameters.
+ * @param obj_init_arg
+ *   An opaque pointer to data that can be used as an argument for
+ *   each call to the object constructor function.
+ * @param socket_id
+ *   The *socket_id* argument is the socket identifier in the case of
+ *   NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA
+ *   constraint for the reserved zone.
+ * @param flags
+ *   The *flags* arguments is an OR of following flags:
+ *   - MEMPOOL_F_NO_SPREAD: By default, objects addresses are spread
+ *     between channels in RAM: the pool allocator will add padding
+ *     between objects depending on the hardware configuration. See
+ *     Memory alignment constraints for details. If this flag is set,
+ *     the allocator will just align them to a cache line.
+ *   - MEMPOOL_F_NO_CACHE_ALIGN: By default, the returned objects are
+ *     cache-aligned. This flag removes this constraint, and no
+ *     padding will be present between objects. This flag implies
+ *     MEMPOOL_F_NO_SPREAD.
+ *   - MEMPOOL_F_SP_PUT: If this flag is set, the default behavior
+ *     when using rte_mempool_put() or rte_mempool_put_bulk() is
+ *     "single-producer". Otherwise, it is "multi-producers".
+ *   - MEMPOOL_F_SC_GET: If this flag is set, the default behavior
+ *     when using rte_mempool_get() or rte_mempool_get_bulk() is
+ *     "single-consumer". Otherwise, it is "multi-consumers".
+ * @return
+ *   The pointer to the new allocated mempool, on success. NULL on error
+ *   with rte_errno set appropriately. Possible rte_errno values include:
+ *    - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure
+ *    - E_RTE_SECONDARY - function was called from a secondary process instance
+ *    - E_RTE_NO_TAILQ - no tailq list could be got for the ring or mempool list
+ *    - EINVAL - cache size provided is too large
+ *    - ENOSPC - the maximum number of memzones has already been allocated
+ *    - EEXIST - a memzone with the same name already exists
+ *    - ENOMEM - no appropriate memory area found in which to create memzone
+ */
+struct rte_mempool *
+rte_mempool_create(const char *name, unsigned n, unsigned elt_size,
+		   unsigned cache_size, unsigned private_data_size,
+		   rte_mempool_ctor_t *mp_init, void *mp_init_arg,
+		   rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg,
+		   int socket_id, unsigned flags);
+
+/**
+ * Search a mempool from its name
+ *
+ * @param name
+ *   The name of the mempool.
+ * @return
+ *   The pointer to the mempool matching the name, or NULL if not found.
+ *   NULL on error
+ *   with rte_errno set appropriately. Possible rte_errno values include:
+ *    - ENOENT - required entry not available to return.
+ *
+ */
+struct rte_mempool *rte_mempool_lookup(const char *name);
+
+/**
+ * Dump the status of the mempool to the console.
+ *
+ * @param f
+ *   A pointer to a file for output
+ * @param mp
+ *   A pointer to the mempool structure.
+ */
+void rte_mempool_dump(FILE *f, const struct rte_mempool *mp);
+
+/**
+ * Dump the status of all mempools on the console
+ *
+ * @param f
+ *   A pointer to a file for output
+ */
+void rte_mempool_list_dump(FILE *f);
+
+/**
+ * Walk list of all memory pools
+ *
+ * @param func
+ *   Iterator function
+ * @param arg
+ *   Argument passed to iterator
+ */
+void rte_mempool_walk(void (*func)(const struct rte_mempool *, void *arg),
+		      void *arg);
+
+
+/**
+ * Return the physical address of elt, which is an element of the pool mp.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param elt
+ *   A pointer (virtual address) to the element of the pool.
+ * @return
+ *   The physical address of the elt element.
+ */
+static inline phys_addr_t __attribute__((always_inline))
+rte_mempool_virt2phy(const struct rte_mempool *mp, const void *elt)
+{
+	uintptr_t off = (const char *)elt - (const char *)mp;
+
+	return mp->phys_addr + off;
+}
+
+/**
+ * Return a pointer to the private data in an mempool structure.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @return
+ *   A pointer to the private data.
+ */
+static inline void *rte_mempool_get_priv(struct rte_mempool *mp)
+{
+	return mp->private_data;
+}
+
+/**
+ * Return the number of entries in the mempool.
+ *
+ * When cache is enabled, this function has to browse the length of
+ * all lcores, so it should not be used in a data path, but only for
+ * debug purposes.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @return
+ *   The number of entries in the mempool.
+ */
+static inline unsigned
+rte_mempool_count(const struct rte_mempool *mp)
+{
+	return gxio_mpipe_get_buffer_count(mp->context, mp->stack_idx);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_MEMPOOL_TILE_H_ */
-- 
2.1.2

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [dpdk-dev] [PATCH 13/15] pmd/tile: add mPIPE poll mode driver for TileGx
  2014-12-08  8:59 [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture Zhigang Lu
                   ` (11 preceding siblings ...)
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 12/15] eal/tile: add mPIPE buffer stack mempool provider Zhigang Lu
@ 2014-12-08  8:59 ` Zhigang Lu
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 14/15] app/test: turn off cpu flag checks for tile architecture Zhigang Lu
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 15/15] eal: allow empty set of compile time cpuflags Zhigang Lu
  14 siblings, 0 replies; 32+ messages in thread
From: Zhigang Lu @ 2014-12-08  8:59 UTC (permalink / raw)
  To: dev; +Cc: Cyril Chemparathy

Signed-off-by: Zhigang Lu <zlu@ezchip.com>
Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
---
 lib/Makefile                     |    1 +
 lib/librte_pmd_mpipe/Makefile    |   24 +
 lib/librte_pmd_mpipe/pmd_mpipe.c | 1343 ++++++++++++++++++++++++++++++++++++++
 mk/rte.app.mk                    |    4 +
 4 files changed, 1372 insertions(+)
 create mode 100644 lib/librte_pmd_mpipe/Makefile
 create mode 100644 lib/librte_pmd_mpipe/pmd_mpipe.c

diff --git a/lib/Makefile b/lib/Makefile
index 60aa0ff..c5e44bb 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -49,6 +49,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += librte_pmd_e1000
 DIRS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += librte_pmd_ixgbe
 DIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += librte_pmd_i40e
 DIRS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += librte_pmd_enic
+DIRS-$(CONFIG_RTE_LIBRTE_MPIPE_PMD) += librte_pmd_mpipe
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += librte_pmd_bond
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_RING) += librte_pmd_ring
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += librte_pmd_pcap
diff --git a/lib/librte_pmd_mpipe/Makefile b/lib/librte_pmd_mpipe/Makefile
new file mode 100644
index 0000000..db75cf3
--- /dev/null
+++ b/lib/librte_pmd_mpipe/Makefile
@@ -0,0 +1,24 @@
+# FIXME: License
+# referred librte_pmd_mpipe/Makefile
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_mpipe.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_MPIPE_PMD) += pmd_mpipe.c
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_MPIPE_PMD) += lib/librte_eal lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_MPIPE_PMD) += lib/librte_mempool lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_MPIPE_PMD) += lib/librte_net lib/librte_malloc
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_pmd_mpipe/pmd_mpipe.c b/lib/librte_pmd_mpipe/pmd_mpipe.c
new file mode 100644
index 0000000..bac880c
--- /dev/null
+++ b/lib/librte_pmd_mpipe/pmd_mpipe.c
@@ -0,0 +1,1343 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2014 Tilera Corporation. 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 Tilera 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 <unistd.h>
+
+#include <rte_eal.h>
+#include <rte_dev.h>
+#include <rte_eal_memconfig.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_cycles.h>
+
+#include <arch/mpipe_xaui_def.h>
+#include <arch/mpipe_gbe_def.h>
+
+#include <gxio/mpipe.h>
+
+#ifdef RTE_LIBRTE_MPIPE_DEBUG_INIT
+#define MPIPE_DEBUG_INIT
+#endif
+#ifdef RTE_LIBRTE_MPIPE_DEBUG_RX
+#define MPIPE_DEBUG_RX
+#endif
+#ifdef RTE_LIBRTE_MPIPE_DEBUG_TX
+#define MPIPE_DEBUG_TX
+#endif
+
+#ifdef MPIPE_DEBUG_INIT
+#define PMD_INIT_LOG(level, fmt, args...) \
+	RTE_LOG(level, PMD, "%s(): " fmt, __func__, ## args)
+#define PMD_INIT_FUNC_TRACE() PMD_INIT_LOG(DEBUG, " >>")
+#else
+#define PMD_INIT_LOG(level, fmt, args...) do { } while (0)
+#define PMD_INIT_FUNC_TRACE() do { } while (0)
+#endif
+
+#ifdef MPIPE_DEBUG_RX
+#define PMD_RX_LOG(level, fmt, args...) \
+	RTE_LOG(level, PMD, "%s() rx: " fmt, __func__, ## args)
+#else
+#define PMD_RX_LOG(level, fmt, args...) do { } while (0)
+#endif
+
+#ifdef MPIPE_DEBUG_TX
+#define PMD_TX_LOG(level, fmt, args...) \
+	RTE_LOG(level, PMD, "%s() tx: " fmt, __func__, ## args)
+#else
+#define PMD_TX_LOG(level, fmt, args...) do { } while (0)
+#endif
+
+#define MPIPE_TX_MAX_QUEUES		128
+#define MPIPE_TX_DESCS			512
+#define MPIPE_RX_MAX_QUEUES		16
+#define MPIPE_RX_BUCKETS		256
+
+#define MPIPE_LINK_UPDATE_TIMEOUT	10	/*  s */
+#define MPIPE_LINK_UPDATE_INTERVAL	100000	/* us */
+#define MPIPE_BSM_MAX_OFFSET		128
+
+#define MPIPE_XGBE_ENA_HASH_MULTI	\
+	(1UL << MPIPE_XAUI_RECEIVE_CONFIGURATION__ENA_HASH_MULTI_SHIFT)
+#define MPIPE_XGBE_ENA_HASH_UNI		\
+	(1UL << MPIPE_XAUI_RECEIVE_CONFIGURATION__ENA_HASH_UNI_SHIFT)
+#define MPIPE_XGBE_COPY_ALL		\
+	(1UL << MPIPE_XAUI_RECEIVE_CONFIGURATION__COPY_ALL_SHIFT)
+#define MPIPE_GBE_ENA_MULTI_HASH	\
+	(1UL << MPIPE_GBE_NETWORK_CONFIGURATION__MULTI_HASH_ENA_SHIFT)
+#define MPIPE_GBE_ENA_UNI_HASH		\
+	(1UL << MPIPE_GBE_NETWORK_CONFIGURATION__UNI_HASH_ENA_SHIFT)
+#define MPIPE_GBE_COPY_ALL		\
+	(1UL << MPIPE_GBE_NETWORK_CONFIGURATION__COPY_ALL_SHIFT)
+
+/* Per queue statistics. */
+struct mpipe_queue_stats {
+	uint64_t packets, bytes, errors;
+};
+
+/* Common tx/rx queue fields. */
+struct mpipe_queue {
+	struct mpipe_dev_priv *priv;	/* "priv" data of its device. */
+	uint16_t nb_desc;		/* Number of tx descriptors. */
+	uint16_t port_id;		/* Device index. */
+	uint16_t stat_idx;		/* Queue stats index. */
+	uint8_t queue_idx;		/* Queue index. */
+	uint8_t link_status;		/* 0 = link down. */
+	struct mpipe_queue_stats stats;	/* Stat data for the queue. */
+};
+
+/* Transmit queue description. */
+struct mpipe_tx_queue {
+	struct mpipe_queue q;		/* Common stuff. */
+};
+
+/* Receive queue description. */
+struct mpipe_rx_queue {
+	struct mpipe_queue q;		/* Common stuff. */
+	gxio_mpipe_iqueue_t iqueue;	/* mPIPE iqueue. */
+	gxio_mpipe_idesc_t *next_desc;	/* Next idesc to process. */
+	int avail_descs;		/* Number of available descs. */
+	int meta_size;			/* Size of mbuf structure. */
+	int max_rx_batch;		/* Limit on RX batch size. */
+	struct rte_mempool *mpool;	/* mpool used by the rx queue. */
+	void *rx_ring_mem;		/* DMA ring memory. */
+};
+
+struct mpipe_dev_priv {
+	gxio_mpipe_context_t *context;	/* mPIPE context. */
+	gxio_mpipe_link_t link;		/* mPIPE link for the device. */
+	gxio_mpipe_equeue_t equeue;	/* mPIPE equeue. */
+	gxio_mpipe_rules_stacks_t stacks; /* mPIPE buffer stacks. */
+	unsigned equeue_size;		/* mPIPE equeue desc count. */
+	int instance;			/* mPIPE instance. */
+	int ering;			/* mPIPE eDMA ring. */
+	int channel;			/* Device channel. */
+	int port_id;			/* DPDK port index. */
+	struct rte_eth_dev *eth_dev;	/* DPDK device. */
+	struct rte_pci_device pci_dev;	/* PCI device data. */
+	struct rte_mbuf **tx_comps;	/* TX completion array. */
+	int is_xaui:1,			/* Is this an xgbe or gbe? */
+	    initialized:1,		/* Initialized port? */
+	    running:1;			/* Running port? */
+	struct ether_addr mac_addr;	/* MAC address. */
+	unsigned nb_rx_queues;		/* Configured tx queues. */
+	unsigned nb_tx_queues;		/* Configured rx queues. */
+	int first_bucket;		/* mPIPE bucket start index. */
+	int first_ring;			/* mPIPE notif ring start index. */
+	int notif_group;		/* mPIPE notif group. */
+	int dp_count;			/* Active datapath thread count. */
+	int tx_stat_mapping[RTE_ETHDEV_QUEUE_STAT_CNTRS];
+	int rx_stat_mapping[RTE_ETHDEV_QUEUE_STAT_CNTRS];
+};
+
+#define mpipe_priv(dev)			\
+	((struct mpipe_dev_priv *)(dev)->data->dev_private)
+
+#define mpipe_name(priv)		\
+	((priv)->eth_dev->data->name)
+
+#define mpipe_rx_queue(priv, n)		\
+	((struct mpipe_rx_queue *)(priv)->eth_dev->data->rx_queues[n])
+
+#define mpipe_tx_queue(priv, n)		\
+	((struct mpipe_tx_queue *)(priv)->eth_dev->data->tx_queues[n])
+
+static void
+mpipe_xmit_flush(struct mpipe_dev_priv *priv);
+
+static void
+mpipe_recv_flush(struct mpipe_rx_queue *rx_queue);
+
+static unsigned mpipe_equeue_sizes[] = {
+	GXIO_MPIPE_EQUEUE_ENTRY_512,
+	GXIO_MPIPE_EQUEUE_ENTRY_2K,
+	GXIO_MPIPE_EQUEUE_ENTRY_8K,
+	GXIO_MPIPE_EQUEUE_ENTRY_64K,
+	-1
+};
+
+static unsigned mpipe_iqueue_sizes[] = {
+	GXIO_MPIPE_IQUEUE_ENTRY_128,
+	GXIO_MPIPE_IQUEUE_ENTRY_512,
+	GXIO_MPIPE_IQUEUE_ENTRY_2K,
+	GXIO_MPIPE_IQUEUE_ENTRY_64K,
+	-1
+};
+
+static int
+mpipe_ring_size(unsigned *sizes, unsigned nb_desc)
+{
+	while (*sizes < nb_desc)
+		sizes++;
+	return *sizes;
+}
+
+static int mpipe_equeue_size(int nb_desc)
+{
+	return mpipe_ring_size(mpipe_equeue_sizes, nb_desc);
+}
+
+static int mpipe_iqueue_size(int nb_desc)
+{
+	return mpipe_ring_size(mpipe_iqueue_sizes, nb_desc);
+}
+
+static inline int
+mpipe_dev_atomic_read_link_status(struct rte_eth_dev *dev,
+				  struct rte_eth_link *link)
+{
+	struct rte_eth_link *dst = link;
+	struct rte_eth_link *src = &(dev->data->dev_link);
+
+	if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
+				*(uint64_t *)src) == 0)
+		return -1;
+
+	return 0;
+}
+
+static inline int
+mpipe_dev_atomic_write_link_status(struct rte_eth_dev *dev,
+				   struct rte_eth_link *link)
+{
+	struct rte_eth_link *dst = &(dev->data->dev_link);
+	struct rte_eth_link *src = link;
+
+	if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
+				*(uint64_t *)src) == 0)
+		return -1;
+
+	return 0;
+}
+
+static void
+mpipe_infos_get(struct rte_eth_dev *dev __rte_unused,
+		struct rte_eth_dev_info *dev_info)
+{
+	dev_info->min_rx_bufsize  = 128;
+	dev_info->max_rx_pktlen   = 1518;
+	dev_info->max_tx_queues   = MPIPE_TX_MAX_QUEUES;
+	dev_info->max_rx_queues   = MPIPE_RX_MAX_QUEUES;
+	dev_info->max_mac_addrs   = 1;
+	dev_info->rx_offload_capa = 0;
+	dev_info->tx_offload_capa = 0;
+}
+
+static int
+mpipe_configure(struct rte_eth_dev *dev)
+{
+	struct mpipe_dev_priv *priv = mpipe_priv(dev);
+
+	if (dev->data->nb_tx_queues > MPIPE_TX_MAX_QUEUES) {
+		RTE_LOG(ERR, PMD, "%s: Too many tx queues: %d > %d\n",
+			mpipe_name(priv), dev->data->nb_tx_queues,
+			MPIPE_TX_MAX_QUEUES);
+		return -EINVAL;
+	}
+	priv->nb_tx_queues = dev->data->nb_tx_queues;
+
+	if (dev->data->nb_rx_queues > MPIPE_RX_MAX_QUEUES) {
+		RTE_LOG(ERR, PMD, "%s: Too many rx queues: %d > %d\n",
+			mpipe_name(priv), dev->data->nb_rx_queues,
+			MPIPE_RX_MAX_QUEUES);
+	}
+	priv->nb_rx_queues = dev->data->nb_rx_queues;
+
+	return 0;
+}
+
+static inline int
+mpipe_link_compare(struct rte_eth_link *link1,
+		   struct rte_eth_link *link2)
+{
+	return ((*(uint64_t *)link1 == *(uint64_t *)link2)
+		? -1 : 0);
+}
+
+static int
+mpipe_link_update(struct rte_eth_dev *dev, int wait_to_complete)
+{
+	struct mpipe_dev_priv *priv = mpipe_priv(dev);
+	struct rte_eth_link old, new;
+	int64_t state, speed;
+	int count, rc;
+
+	memset(&old, 0, sizeof(old));
+	memset(&new, 0, sizeof(new));
+	mpipe_dev_atomic_read_link_status(dev, &old);
+
+	for (count = 0, rc = 0; count < MPIPE_LINK_UPDATE_TIMEOUT; count++) {
+		if (!priv->initialized)
+			break;
+
+		state = gxio_mpipe_link_get_attr(&priv->link,
+						 GXIO_MPIPE_LINK_CURRENT_STATE);
+		if (state < 0)
+			break;
+
+		speed = state & GXIO_MPIPE_LINK_SPEED_MASK;
+
+		if (speed == GXIO_MPIPE_LINK_1G) {
+			new.link_speed = ETH_LINK_SPEED_1000;
+			new.link_duplex = ETH_LINK_FULL_DUPLEX;
+			new.link_status = 1;
+		} else if (speed == GXIO_MPIPE_LINK_10G) {
+			new.link_speed = ETH_LINK_SPEED_10000;
+			new.link_duplex = ETH_LINK_FULL_DUPLEX;
+			new.link_status = 1;
+		}
+
+		rc = mpipe_link_compare(&old, &new);
+		if (rc == 0 || !wait_to_complete)
+			break;
+
+		rte_delay_us(MPIPE_LINK_UPDATE_INTERVAL);
+	}
+
+	mpipe_dev_atomic_write_link_status(dev, &new);
+	return rc;
+}
+
+static int
+mpipe_set_link(struct rte_eth_dev *dev, int up)
+{
+	struct mpipe_dev_priv *priv = mpipe_priv(dev);
+	int rc;
+
+	rc = gxio_mpipe_link_set_attr(&priv->link,
+				      GXIO_MPIPE_LINK_DESIRED_STATE,
+				      up ? GXIO_MPIPE_LINK_ANYSPEED : 0);
+	if (rc < 0) {
+		RTE_LOG(ERR, PMD, "Failed to set link %s on %s.\n",
+			up ? "up" : "down", mpipe_name(priv));
+	} else {
+		mpipe_link_update(dev, 0);
+	}
+
+	return rc;
+}
+
+static int
+mpipe_set_link_up(struct rte_eth_dev *dev)
+{
+	return mpipe_set_link(dev, 1);
+}
+
+static int
+mpipe_set_link_down(struct rte_eth_dev *dev)
+{
+	return mpipe_set_link(dev, 0);
+}
+
+static inline int
+mpipe_dp_count(struct mpipe_dev_priv *priv, int adjust)
+{
+	/*
+	 * We could in theory have used atomic increment/decrement operations
+	 * here, but we cheat as follows to avoid the implicit memory barrier
+	 * in GCC sync operations.
+	 */
+	return arch_atomic_add(&priv->dp_count, adjust);
+}
+
+static inline void
+mpipe_dp_enter(struct mpipe_dev_priv *priv)
+{
+	__insn_mtspr(SPR_DSTREAM_PF, 0);
+	mpipe_dp_count(priv, 1);
+}
+
+static inline void
+mpipe_dp_exit(struct mpipe_dev_priv *priv)
+{
+	mpipe_dp_count(priv, -1);
+}
+
+static inline void
+mpipe_dp_wait(struct mpipe_dev_priv *priv)
+{
+	while (mpipe_dp_count(priv, 0) != 0)
+		rte_pause();
+}
+
+static int
+mpipe_recv_init(struct mpipe_dev_priv *priv)
+{
+	int rc;
+
+	/* Allocate one NotifRing for each queue. */
+	rc = gxio_mpipe_alloc_notif_rings(priv->context, MPIPE_RX_MAX_QUEUES,
+					  0, 0);
+	if (rc < 0) {
+		RTE_LOG(ERR, PMD, "Failed to allocate notif rings for %s.\n",
+			mpipe_name(priv));
+		return rc;
+	}
+	priv->first_ring = rc;
+
+	/* Allocate a NotifGroup. */
+	rc = gxio_mpipe_alloc_notif_groups(priv->context, 1, 0, 0);
+	if (rc < 0) {
+		RTE_LOG(ERR, PMD, "Failed to allocate rx group for %s.\n",
+			mpipe_name(priv));
+		return rc;
+	}
+	priv->notif_group = rc;
+
+	/* Allocate required buckets. */
+	rc = gxio_mpipe_alloc_buckets(priv->context, MPIPE_RX_BUCKETS, 0, 0);
+	if (rc < 0) {
+		RTE_LOG(ERR, PMD, "Failed to allocate buckets for %s.\n",
+			mpipe_name(priv));
+		return rc;
+	}
+	priv->first_bucket = rc;
+
+	return 0;
+}
+
+static int
+mpipe_xmit_init(struct mpipe_dev_priv *priv)
+{
+	size_t ring_size;
+	void *ring_mem;
+	int rc;
+
+	/* Allocate eDMA ring. */
+	rc = gxio_mpipe_alloc_edma_rings(priv->context, 1, 0, 0);
+	if (rc < 0) {
+		RTE_LOG(ERR, PMD, "Failed to alloc tx ring for %s.\n",
+			mpipe_name(priv));
+		return rc;
+	}
+	priv->ering = rc;
+
+	rc = mpipe_equeue_size(MPIPE_TX_DESCS);
+	if (rc < 0) {
+		RTE_LOG(ERR, PMD, "Cannot allocate %d equeue descs.\n",
+			(int)MPIPE_TX_DESCS);
+		return -ENOMEM;
+	}
+	priv->equeue_size = rc;
+
+	/* Initialize completion array. */
+	ring_size = sizeof(priv->tx_comps[0]) * priv->equeue_size;
+	priv->tx_comps = rte_zmalloc(NULL, ring_size, RTE_CACHE_LINE_SIZE);
+	if (!priv->tx_comps) {
+		RTE_LOG(ERR, PMD, "Failed to allocate egress completions "
+			"for %s.\n", mpipe_name(priv));
+		return -ENOMEM;
+	}
+
+	/* Allocate eDMA ring memory. */
+	ring_size = sizeof(gxio_mpipe_edesc_t) * priv->equeue_size;
+	ring_mem = rte_zmalloc(NULL, ring_size, ring_size);
+	if (!ring_mem) {
+		RTE_LOG(ERR, PMD, "Failed to allocate egress descs for %s.\n",
+			mpipe_name(priv));
+		return -ENOMEM;
+	}
+
+	/* Initialize eDMA ring. */
+	rc = gxio_mpipe_equeue_init(&priv->equeue, priv->context, priv->ering,
+				    priv->channel, ring_mem, ring_size, 0);
+	if (rc < 0) {
+		RTE_LOG(ERR, PMD, "Failed to init equeue for %s\n",
+			mpipe_name(priv));
+		return rc;
+	}
+
+	return 0;
+}
+
+static int
+mpipe_link_init(struct mpipe_dev_priv *priv)
+{
+	int rc;
+
+	/* Open the link. */
+	rc = gxio_mpipe_link_open(&priv->link, priv->context,
+				  mpipe_name(priv), GXIO_MPIPE_LINK_AUTO_NONE);
+	if (rc < 0) {
+		RTE_LOG(ERR, PMD, "Failed to open link %s.\n",
+			mpipe_name(priv));
+		return rc;
+	}
+
+	/* Get the channel index. */
+	rc = gxio_mpipe_link_channel(&priv->link);
+	if (rc < 0) {
+		RTE_LOG(ERR, PMD, "Bad channel for interface %s\n",
+			mpipe_name(priv));
+		return rc;
+	}
+	priv->channel = rc;
+
+	return 0;
+}
+
+static int
+mpipe_init(struct mpipe_dev_priv *priv)
+{
+	int rc;
+
+	if (priv->initialized)
+		return 0;
+
+	rc = mpipe_link_init(priv);
+	if (rc < 0) {
+		RTE_LOG(ERR, PMD, "Failed to init link for %s.\n",
+			mpipe_name(priv));
+		return rc;
+	}
+
+	rc = mpipe_recv_init(priv);
+	if (rc < 0) {
+		RTE_LOG(ERR, PMD, "Failed to init rx for %s.\n",
+			mpipe_name(priv));
+		return rc;
+	}
+
+	rc = mpipe_xmit_init(priv);
+	if (rc < 0) {
+		RTE_LOG(ERR, PMD, "Failed to init tx for %s.\n",
+			mpipe_name(priv));
+		rte_free(priv);
+		return rc;
+	}
+
+	priv->initialized = 1;
+
+	return 0;
+}
+
+static int
+mpipe_start(struct rte_eth_dev *dev)
+{
+	struct mpipe_dev_priv *priv = mpipe_priv(dev);
+	struct rte_eal_mpipe_channel_config config;
+	struct mpipe_rx_queue *rx_queue;
+	struct rte_eth_link eth_link;
+	size_t ring_size;
+	void *ring_mem;
+	unsigned queue;
+	int rc;
+
+	memset(&eth_link, 0, sizeof(eth_link));
+	mpipe_dev_atomic_write_link_status(dev, &eth_link);
+
+	rc = mpipe_init(priv);
+	if (rc < 0)
+		return rc;
+
+	/* Initialize NotifRings. */
+	for (queue = 0; queue < priv->nb_rx_queues; queue++) {
+		rx_queue = mpipe_rx_queue(priv, queue);
+		ring_size = rx_queue->q.nb_desc * sizeof(gxio_mpipe_idesc_t);
+
+		ring_mem = rte_malloc(NULL, ring_size, ring_size);
+		if (!ring_mem) {
+			RTE_LOG(ERR, PMD, "Failed to alloc rx descs for %s.\n",
+				mpipe_name(priv));
+			return -ENOMEM;
+		}
+
+		rc = gxio_mpipe_iqueue_init(&rx_queue->iqueue, priv->context,
+					    priv->first_ring + queue, ring_mem,
+					    ring_size, 0);
+		if (rc < 0) {
+			RTE_LOG(ERR, PMD, "Failed to init rx queue for %s.\n",
+				mpipe_name(priv));
+			return rc;
+		}
+
+		rx_queue->rx_ring_mem = ring_mem;
+	}
+
+	/* Initialize ingress NotifGroup and buckets. */
+	rc = gxio_mpipe_init_notif_group_and_buckets(priv->context,
+			priv->notif_group, priv->first_ring, priv->nb_rx_queues,
+			priv->first_bucket, MPIPE_RX_BUCKETS,
+			GXIO_MPIPE_BUCKET_STATIC_FLOW_AFFINITY);
+	if (rc < 0) {
+		RTE_LOG(ERR, PMD, "Failed to init notif group and buckets "
+			"for %s.\n", mpipe_name(priv));
+		return rc;
+	}
+
+	/* Configure the classifier to deliver packets from this port. */
+	config.enable = 1;
+	config.first_bucket = priv->first_bucket;
+	config.num_buckets = MPIPE_RX_BUCKETS;
+	config.headroom = RTE_PKTMBUF_HEADROOM;
+	config.stacks = priv->stacks;
+
+	rc = rte_eal_mpipe_channel_config(priv->instance, priv->channel,
+					  &config);
+	if (rc < 0) {
+		RTE_LOG(ERR, PMD, "Failed to setup classifier for %s.\n",
+			mpipe_name(priv));
+		return rc;
+	}
+
+	/* Bring up the link. */
+	mpipe_set_link_up(dev);
+
+	/* Start xmit/recv on queues. */
+	for (queue = 0; queue < priv->nb_tx_queues; queue++)
+		mpipe_tx_queue(priv, queue)->q.link_status = 1;
+	for (queue = 0; queue < priv->nb_rx_queues; queue++)
+		mpipe_rx_queue(priv, queue)->q.link_status = 1;
+	priv->running = 1;
+
+	return 0;
+}
+
+static void
+mpipe_stop(struct rte_eth_dev *dev)
+{
+	struct mpipe_dev_priv *priv = mpipe_priv(dev);
+	struct rte_eal_mpipe_channel_config config;
+	unsigned queue;
+	int rc;
+
+	for (queue = 0; queue < priv->nb_tx_queues; queue++)
+		mpipe_tx_queue(priv, queue)->q.link_status = 0;
+	for (queue = 0; queue < priv->nb_rx_queues; queue++)
+		mpipe_rx_queue(priv, queue)->q.link_status = 0;
+
+	/* Make sure the link_status writes land. */
+	rte_wmb();
+
+	/*
+	 * Wait for link_status change to register with straggling datapath
+	 * threads.
+	 */
+	mpipe_dp_wait(priv);
+
+	/* Bring down the link. */
+	mpipe_set_link_down(dev);
+
+	/* Remove classifier rules. */
+	memset(&config, 0, sizeof(config));
+	rc = rte_eal_mpipe_channel_config(priv->instance, priv->channel,
+					  &config);
+	if (rc < 0) {
+		RTE_LOG(ERR, PMD, "Failed to stop classifier for %s.\n",
+			mpipe_name(priv));
+	}
+
+	/* Flush completed xmit packets. */
+	mpipe_xmit_flush(priv);
+
+	/* Flush packets sitting in recv queues. */
+	for (queue = 0; queue < priv->nb_rx_queues; queue++) {
+		struct mpipe_rx_queue *rx_queue = mpipe_rx_queue(priv, queue);
+
+		mpipe_recv_flush(rx_queue);
+		rte_free(rx_queue->rx_ring_mem);
+	}
+
+	priv->running = 0;
+}
+
+static void
+mpipe_close(struct rte_eth_dev *dev)
+{
+	struct mpipe_dev_priv *priv = mpipe_priv(dev);
+
+	if (priv->running)
+		mpipe_stop(dev);
+}
+
+static void
+mpipe_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+	struct mpipe_dev_priv *priv = mpipe_priv(dev);
+	struct mpipe_tx_queue *tx_queue;
+	struct mpipe_rx_queue *rx_queue;
+	unsigned i;
+	uint16_t idx;
+
+	memset(stats, 0, sizeof(*stats));
+
+	for (i = 0; i < priv->nb_tx_queues; i++) {
+		tx_queue = mpipe_tx_queue(priv, i);
+
+		stats->opackets += tx_queue->q.stats.packets;
+		stats->obytes   += tx_queue->q.stats.bytes;
+		stats->oerrors  += tx_queue->q.stats.errors;
+
+		idx = tx_queue->q.stat_idx;
+		if (idx != (uint16_t)-1) {
+			stats->q_opackets[idx] += tx_queue->q.stats.packets;
+			stats->q_obytes[idx]   += tx_queue->q.stats.bytes;
+			stats->q_errors[idx]   += tx_queue->q.stats.errors;
+		}
+	}
+
+	for (i = 0; i < priv->nb_rx_queues; i++) {
+		rx_queue = mpipe_rx_queue(priv, i);
+
+		stats->ipackets += rx_queue->q.stats.packets;
+		stats->ibytes   += rx_queue->q.stats.bytes;
+		stats->ierrors  += rx_queue->q.stats.errors;
+
+		idx = rx_queue->q.stat_idx;
+		if (idx != (uint16_t)-1) {
+			stats->q_ipackets[idx] += rx_queue->q.stats.packets;
+			stats->q_ibytes[idx]   += rx_queue->q.stats.bytes;
+			stats->q_errors[idx]   += rx_queue->q.stats.errors;
+		}
+	}
+}
+
+static void
+mpipe_stats_reset(struct rte_eth_dev *dev)
+{
+	struct mpipe_dev_priv *priv = mpipe_priv(dev);
+	struct mpipe_tx_queue *tx_queue;
+	struct mpipe_rx_queue *rx_queue;
+	unsigned i;
+
+	for (i = 0; i < priv->nb_tx_queues; i++) {
+		tx_queue = mpipe_tx_queue(priv, i);
+		memset(&tx_queue->q.stats, 0, sizeof(tx_queue->q.stats));
+	}
+
+	for (i = 0; i < priv->nb_rx_queues; i++) {
+		rx_queue = mpipe_rx_queue(priv, i);
+		memset(&rx_queue->q.stats, 0, sizeof(rx_queue->q.stats));
+	}
+}
+
+static int
+mpipe_queue_stats_mapping_set(struct rte_eth_dev *dev, uint16_t queue_id,
+			      uint8_t stat_idx, uint8_t is_rx)
+{
+	struct mpipe_dev_priv *priv = mpipe_priv(dev);
+
+	if (is_rx)
+		priv->rx_stat_mapping[stat_idx] = queue_id;
+	else
+		priv->tx_stat_mapping[stat_idx] = queue_id;
+
+	return 0;
+}
+
+static int
+mpipe_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
+		     uint16_t nb_desc, unsigned int socket_id __rte_unused,
+		     const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+	struct mpipe_tx_queue *tx_queue = dev->data->tx_queues[queue_idx];
+	struct mpipe_dev_priv *priv = mpipe_priv(dev);
+	uint16_t idx;
+
+	tx_queue = rte_realloc(tx_queue, sizeof(*tx_queue),
+				RTE_CACHE_LINE_SIZE);
+	if (!tx_queue) {
+		RTE_LOG(ERR, PMD, "Failed to allocate TX queue.\n");
+		return -ENOMEM;
+	}
+
+	memset(&tx_queue->q, 0, sizeof(tx_queue->q));
+	tx_queue->q.priv = priv;
+	tx_queue->q.queue_idx = queue_idx;
+	tx_queue->q.port_id = dev->data->port_id;
+	tx_queue->q.nb_desc = nb_desc;
+
+	tx_queue->q.stat_idx = -1;
+	for (idx = 0; idx < RTE_ETHDEV_QUEUE_STAT_CNTRS; idx++) {
+		if (priv->tx_stat_mapping[idx] == queue_idx)
+			tx_queue->q.stat_idx = idx;
+	}
+
+	dev->data->tx_queues[queue_idx] = tx_queue;
+
+	return 0;
+}
+
+static void
+mpipe_tx_queue_release(void *_txq)
+{
+	rte_free(_txq);
+}
+
+static unsigned
+mpipe_get_max_rx_batch(unsigned meta_size)
+{
+	static unsigned cache_size;
+
+	if (!cache_size) {
+		/* Limit batch to occupy no more than half the cache. */
+		cache_size = sysconf(_SC_LEVEL1_DCACHE_SIZE) / 2;
+	}
+
+	/* Round up to cache line multiples. */
+	meta_size  = RTE_CACHE_LINE_ROUNDUP(meta_size);
+	/* Assume 2 lines of packet data. */
+	meta_size += 2 * RTE_CACHE_LINE_SIZE;
+
+	return cache_size / meta_size;
+}
+
+static int
+mpipe_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
+		     uint16_t nb_desc, unsigned int socket_id __rte_unused,
+		     const struct rte_eth_rxconf *rx_conf __rte_unused,
+		     struct rte_mempool *mp)
+{
+	struct mpipe_rx_queue *rx_queue = dev->data->rx_queues[queue_idx];
+	struct mpipe_dev_priv *priv = mpipe_priv(dev);
+	uint16_t idx;
+	int size, rc;
+
+	rc = mpipe_iqueue_size(nb_desc);
+	if (rc < 0) {
+		RTE_LOG(ERR, PMD, "Cannot allocate %d iqueue descs.\n",
+			(int)nb_desc);
+		return -ENOMEM;
+	}
+
+	if (rc != nb_desc) {
+		PMD_INIT_LOG(WARNING, "Extending RX descs from %d to %d.\n",
+			     (int)nb_desc, rc);
+		nb_desc = rc;
+	}
+
+	size = sizeof(*rx_queue);
+	rx_queue = rte_realloc(rx_queue, size, RTE_CACHE_LINE_SIZE);
+	if (!rx_queue) {
+		RTE_LOG(ERR, PMD, "Failed to allocate RX queue.\n");
+		return -ENOMEM;
+	}
+
+	memset(&rx_queue->q, 0, sizeof(rx_queue->q));
+	rx_queue->q.priv = priv;
+	rx_queue->q.nb_desc = nb_desc;
+	rx_queue->q.port_id = dev->data->port_id;
+	rx_queue->q.queue_idx = queue_idx;
+	rx_queue->mpool = mp;
+	rx_queue->meta_size = mp->meta_size;
+	rx_queue->max_rx_batch = mpipe_get_max_rx_batch(mp->meta_size);
+
+	rx_queue->q.stat_idx = -1;
+	for (idx = 0; idx < RTE_ETHDEV_QUEUE_STAT_CNTRS; idx++) {
+		if (priv->rx_stat_mapping[idx] == queue_idx)
+			rx_queue->q.stat_idx = idx;
+	}
+
+	dev->data->rx_queues[queue_idx] = rx_queue;
+
+	if (priv->stacks.stacks[mp->size_code] == 0xff)
+		priv->stacks.stacks[mp->size_code] = mp->stack_idx;
+
+	return 0;
+}
+
+static void
+mpipe_rx_queue_release(void *_rxq)
+{
+	rte_free(_rxq);
+}
+
+static void
+mpipe_promiscuous_enable(struct rte_eth_dev *dev)
+{
+	struct mpipe_dev_priv *priv = mpipe_priv(dev);
+	int64_t reg;
+	int addr;
+
+	if (priv->is_xaui) {
+		addr = MPIPE_XAUI_RECEIVE_CONFIGURATION;
+		reg  = gxio_mpipe_link_mac_rd(&priv->link, addr);
+		reg &= ~MPIPE_XGBE_ENA_HASH_MULTI;
+		reg &= ~MPIPE_XGBE_ENA_HASH_UNI;
+		reg |=  MPIPE_XGBE_COPY_ALL;
+		gxio_mpipe_link_mac_wr(&priv->link, addr, reg);
+	} else {
+		addr = MPIPE_GBE_NETWORK_CONFIGURATION;
+		reg  = gxio_mpipe_link_mac_rd(&priv->link, addr);
+		reg &= ~MPIPE_GBE_ENA_MULTI_HASH;
+		reg &= ~MPIPE_GBE_ENA_UNI_HASH;
+		reg |=  MPIPE_GBE_COPY_ALL;
+		gxio_mpipe_link_mac_wr(&priv->link, addr, reg);
+	}
+}
+
+static void
+mpipe_promiscuous_disable(struct rte_eth_dev *dev)
+{
+	struct mpipe_dev_priv *priv = mpipe_priv(dev);
+	int64_t reg;
+	int addr;
+
+	if (priv->is_xaui) {
+		addr = MPIPE_XAUI_RECEIVE_CONFIGURATION;
+		reg  = gxio_mpipe_link_mac_rd(&priv->link, addr);
+		reg |=  MPIPE_XGBE_ENA_HASH_MULTI;
+		reg |=  MPIPE_XGBE_ENA_HASH_UNI;
+		reg &= ~MPIPE_XGBE_COPY_ALL;
+		gxio_mpipe_link_mac_wr(&priv->link, addr, reg);
+	} else {
+		addr = MPIPE_GBE_NETWORK_CONFIGURATION;
+		reg  = gxio_mpipe_link_mac_rd(&priv->link, addr);
+		reg |=  MPIPE_GBE_ENA_MULTI_HASH;
+		reg |=  MPIPE_GBE_ENA_UNI_HASH;
+		reg &= ~MPIPE_GBE_COPY_ALL;
+		gxio_mpipe_link_mac_wr(&priv->link, addr, reg);
+	}
+}
+
+static struct eth_dev_ops mpipe_dev_ops = {
+	.dev_infos_get	         = mpipe_infos_get,
+	.dev_configure	         = mpipe_configure,
+	.dev_start	         = mpipe_start,
+	.dev_stop	         = mpipe_stop,
+	.dev_close	         = mpipe_close,
+	.stats_get	         = mpipe_stats_get,
+	.stats_reset	         = mpipe_stats_reset,
+	.queue_stats_mapping_set = mpipe_queue_stats_mapping_set,
+	.tx_queue_setup	         = mpipe_tx_queue_setup,
+	.rx_queue_setup	         = mpipe_rx_queue_setup,
+	.tx_queue_release	 = mpipe_tx_queue_release,
+	.rx_queue_release	 = mpipe_rx_queue_release,
+	.link_update	         = mpipe_link_update,
+	.dev_set_link_up         = mpipe_set_link_up,
+	.dev_set_link_down       = mpipe_set_link_down,
+	.promiscuous_enable      = mpipe_promiscuous_enable,
+	.promiscuous_disable     = mpipe_promiscuous_disable,
+};
+
+static inline bool
+mpipe_xmit_is_hwb(struct rte_mbuf *mbuf)
+{
+	/*
+	 * The code below is logically equivalent to:
+	 *	 return ((mbuf->nb_segs == 1) &&
+	 *	         (rte_mbuf_refcnt_read(mbuf) == 1) &&
+	 *	         (mbuf->data_off < MPIPE_BSM_MAX_OFFSET));
+	 *
+	 * However, the form chosen below is less branchy than above, and
+	 * therefore performs somewhat better.
+	 */
+	return !((mbuf->nb_segs - 1) |
+		 (rte_mbuf_refcnt_read(mbuf) - 1) |
+		 (mbuf->data_off & ~(MPIPE_BSM_MAX_OFFSET - 1)));
+}
+
+static inline void
+mpipe_xmit_put_slot(struct mpipe_dev_priv *priv, uint16_t slot,
+		    struct rte_mbuf *mbuf)
+{
+	uint16_t idx = slot & (priv->equeue_size - 1);
+	struct rte_mbuf **slot_p = &priv->tx_comps[idx];
+
+	mbuf = arch_atomic_exchange(slot_p, mbuf);
+	if (unlikely(mbuf != NULL))
+		rte_pktmbuf_free(mbuf);
+}
+
+static inline void
+mpipe_xmit_null(struct mpipe_dev_priv *priv, int64_t start, int64_t end)
+{
+	gxio_mpipe_edesc_t null_desc = { { .bound = 1, .ns = 1 } };
+	gxio_mpipe_equeue_t *equeue = &priv->equeue;
+	int64_t slot;
+
+	for (slot = start; slot < end; slot++)
+		gxio_mpipe_equeue_put_at(equeue, null_desc, slot);
+}
+
+static void
+mpipe_xmit_flush(struct mpipe_dev_priv *priv)
+{
+	gxio_mpipe_equeue_t *equeue = &priv->equeue;
+	int64_t slot;
+
+	/* Post a dummy descriptor and wait for its return. */
+	slot = gxio_mpipe_equeue_reserve(equeue, 1);
+	if (slot < 0) {
+		RTE_LOG(ERR, PMD, "Failed to reserve stop slot on %s.\n",
+			mpipe_name(priv));
+		return;
+	}
+
+	mpipe_xmit_null(priv, slot, slot + 1);
+
+	while (!gxio_mpipe_equeue_is_complete(equeue, slot, 1))
+		rte_pause();
+
+	for (slot = 0; slot < priv->equeue_size; slot++)
+		mpipe_xmit_put_slot(priv, slot, NULL);
+}
+
+static void
+mpipe_recv_flush(struct mpipe_rx_queue *rx_queue)
+{
+	gxio_mpipe_iqueue_t *iqueue = &rx_queue->iqueue;
+	gxio_mpipe_idesc_t idesc;
+
+	while (gxio_mpipe_iqueue_try_get(iqueue, &idesc) >= 0)
+		gxio_mpipe_iqueue_drop(iqueue, &idesc);
+}
+
+static inline uint16_t
+mpipe_do_xmit(struct mpipe_tx_queue *tx_queue, struct rte_mbuf **tx_pkts,
+	      uint16_t nb_pkts)
+{
+	struct mpipe_dev_priv *priv = tx_queue->q.priv;
+	gxio_mpipe_equeue_t *equeue = &priv->equeue;
+	unsigned nb_bytes = 0;
+	unsigned nb_sent = 0;
+	int nb_slots, i;
+
+	PMD_TX_LOG(DEBUG, "Trying to transmit %d packets fast on %s:%d.\n",
+		   nb_pkts, mpipe_name(tx_queue->q.priv),
+		   tx_queue->q.queue_idx);
+
+	/* Optimistic assumption that we need exactly one slot per packet. */
+	nb_slots = nb_pkts;
+
+	do {
+		struct rte_mbuf *mbuf = NULL, *pkt = NULL;
+		bool is_hwb = false;
+		int64_t slot;
+
+		/* Reserve eDMA ring slots. */
+		slot = gxio_mpipe_equeue_try_reserve_fast(equeue, nb_slots);
+		if (unlikely(slot < 0))
+			break;
+
+		/* Fill up slots with descriptor and completion info. */
+		for (i = 0; i < nb_slots; i++) {
+			gxio_mpipe_edesc_t desc;
+			struct rte_mbuf *next;
+
+			/* Starting on a new packet? */
+			if (likely(!mbuf)) {
+				int room = nb_slots - i;
+
+				pkt = mbuf = tx_pkts[nb_sent];
+				is_hwb = mpipe_xmit_is_hwb(pkt);
+
+				/* Bail out if we run out of descs. */
+				if (unlikely(pkt->nb_segs > room))
+					break;
+
+				nb_sent++;
+			}
+
+			/* We have a segment to send. */
+			next = mbuf->next;
+
+			desc = (gxio_mpipe_edesc_t) { {
+				.va        = rte_pktmbuf_mtod(mbuf, uintptr_t),
+				.stack_idx = mbuf->pool->stack_idx,
+				.inst      = mbuf->pool->instance,
+				.size      = mbuf->pool->size_code,
+				.xfer_size = rte_pktmbuf_data_len(mbuf),
+				.bound     = 1,
+				.hwb       = 1,
+			} };
+
+			if (unlikely(!is_hwb)) {
+				desc.hwb   = 0;
+				desc.bound = next ? 0 : 1;
+				mpipe_xmit_put_slot(priv, slot + i,
+						    next ? NULL : pkt);
+			}
+
+			nb_bytes += rte_pktmbuf_data_len(mbuf);
+			gxio_mpipe_equeue_put_at(equeue, desc, slot + i);
+
+			mbuf = next;
+		}
+
+		if (unlikely(nb_sent < nb_pkts)) {
+
+			/* Fill remaining slots with null descriptors. */
+			mpipe_xmit_null(priv, slot + i, slot + nb_slots);
+
+			/*
+			 * Calculate exact number of descriptors needed for
+			 * the next go around.
+			 */
+			nb_slots = 0;
+			for (i = nb_sent; i < nb_pkts; i++)
+				nb_slots += tx_pkts[i]->nb_segs;
+		}
+	} while (nb_sent < nb_pkts);
+
+	tx_queue->q.stats.packets += nb_sent;
+	tx_queue->q.stats.bytes   += nb_bytes;
+
+	return nb_sent;
+}
+
+static inline uint16_t
+mpipe_do_recv(struct mpipe_rx_queue *rx_queue, struct rte_mbuf **rx_pkts,
+	      uint16_t nb_pkts)
+{
+	gxio_mpipe_iqueue_t *iqueue = &rx_queue->iqueue;
+	struct rte_mempool *mpool = rx_queue->mpool;
+	gxio_mpipe_idesc_t    *first_idesc, *idesc, *last_idesc;
+	const unsigned meta_size = mpool->meta_size;
+	uint8_t  in_port = rx_queue->q.port_id;
+	const unsigned look_ahead = 8;
+	int room = nb_pkts, rc = 0;
+	unsigned nb_packets = 0;
+	unsigned nb_dropped = 0;
+	unsigned nb_bytes = 0;
+	unsigned nb_descs, i;
+
+	while (room && !rc) {
+		if (rx_queue->avail_descs < room) {
+			rc = gxio_mpipe_iqueue_try_peek(iqueue,
+							&rx_queue->next_desc);
+			rx_queue->avail_descs = rc < 0 ? 0 : rc;
+		}
+
+		if (unlikely(!rx_queue->avail_descs))
+			break;
+
+		nb_descs = RTE_MIN(room, rx_queue->avail_descs);
+
+		first_idesc = rx_queue->next_desc;
+		last_idesc  = first_idesc + nb_descs;
+
+		rx_queue->next_desc   += nb_descs;
+		rx_queue->avail_descs -= nb_descs;
+
+		for (i = 1; i < look_ahead; i++)
+			rte_prefetch0(first_idesc + i);
+
+		PMD_RX_LOG(DEBUG, "Trying to receive %d packets on %s:%d.\n",
+			   nb_descs, mpipe_name(rx_queue->q.priv),
+			   rx_queue->q.queue_idx);
+
+		for (idesc = first_idesc; idesc < last_idesc; idesc++) {
+			unsigned char *va, *buf;
+			struct rte_mbuf *mbuf;
+			uint32_t flow_hash;
+			uint16_t size;
+			uint8_t *ms;
+
+			rte_prefetch0(idesc + look_ahead);
+
+			if (unlikely(gxio_mpipe_idesc_has_error(idesc))) {
+				nb_dropped++;
+				gxio_mpipe_iqueue_drop(iqueue, idesc);
+				continue;
+			}
+
+			va   = gxio_mpipe_idesc_get_va(idesc);
+			buf  = va - RTE_PKTMBUF_HEADROOM;
+			mbuf = __mempool_buf_to_obj(mpool, buf);
+			ms   = (uint8_t *)mbuf;
+
+			size = gxio_mpipe_idesc_get_xfer_size(idesc);
+			flow_hash = gxio_mpipe_idesc_get_flow_hash(idesc);
+
+			mbuf->data_off = RTE_PKTMBUF_HEADROOM;
+			mbuf->nb_segs = 1;
+			mbuf->port = in_port;
+			mbuf->ol_flags = 0;
+			mbuf->packet_type = 0;
+			mbuf->data_len = size;
+			mbuf->pkt_len = size;
+			mbuf->hash.rss = flow_hash;
+			rte_mbuf_refcnt_set(mbuf, 1);
+
+			for (i = 0; i < meta_size; i += RTE_CACHE_LINE_SIZE)
+				rte_prefetch0(ms + i);
+			rte_prefetch0(va);
+
+			/* Update results and statistics counters. */
+			rx_pkts[nb_packets] = mbuf;
+			nb_bytes += size;
+			nb_packets++;
+		}
+
+		/*
+		 * We release the ring in bursts, but do not track and release
+		 * buckets.  This therefore breaks dynamic flow affinity, but
+		 * we always operate in static affinity mode, and so we're OK
+		 * with this optimization.
+		 */
+		gxio_mpipe_iqueue_advance(iqueue, nb_descs);
+		gxio_mpipe_credit(iqueue->context, iqueue->ring, -1, nb_descs);
+
+		/*
+		 * Go around once more if we haven't yet peeked the queue, and
+		 * if we have more room to receive.
+		 */
+		room = nb_pkts - nb_packets;
+	}
+
+	rx_queue->q.stats.packets += nb_packets;
+	rx_queue->q.stats.bytes   += nb_bytes;
+	rx_queue->q.stats.errors  += nb_dropped;
+
+	PMD_RX_LOG(DEBUG, "Received %d packets, %d bytes on %s:%d.\n",
+		   nb_descs, rx_bytes, mpipe_name(rx_queue->q.priv),
+		   rx_queue->q.queue_idx);
+
+	return nb_packets;
+}
+
+static uint16_t
+mpipe_recv_pkts(void *_rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+	struct mpipe_rx_queue *rx_queue = _rxq;
+	uint16_t result = 0;
+
+	if (rx_queue) {
+		mpipe_dp_enter(rx_queue->q.priv);
+		if (likely(rx_queue->q.link_status))
+			result = mpipe_do_recv(rx_queue, rx_pkts, nb_pkts);
+		mpipe_dp_exit(rx_queue->q.priv);
+	}
+
+	return result;
+}
+
+static uint16_t
+mpipe_xmit_pkts(void *_txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	struct mpipe_tx_queue *tx_queue = _txq;
+	uint16_t result = 0;
+
+	if (tx_queue) {
+		mpipe_dp_enter(tx_queue->q.priv);
+		if (likely(tx_queue->q.link_status))
+			result = mpipe_do_xmit(tx_queue, tx_pkts, nb_pkts);
+		mpipe_dp_exit(tx_queue->q.priv);
+	}
+
+	return result;
+}
+
+static int
+mpipe_link_mac(const char *ifname, uint8_t *mac)
+{
+	int rc, idx;
+	char name[GXIO_MPIPE_LINK_NAME_LEN];
+
+	for (idx = 0, rc = 0; !rc; idx++) {
+		rc = gxio_mpipe_link_enumerate_mac(idx, name, mac);
+		if (!rc && !strncmp(name, ifname, GXIO_MPIPE_LINK_NAME_LEN))
+			return 0;
+	}
+	return -ENODEV;
+}
+
+static int
+rte_pmd_mpipe_devinit(const char *ifname,
+		      const char *params __rte_unused)
+{
+	gxio_mpipe_context_t *context;
+	struct rte_eth_dev *eth_dev;
+	struct mpipe_dev_priv *priv;
+	int instance, rc;
+	uint8_t *mac;
+
+	/* Get the mPIPE instance that the device belongs to. */
+	instance = gxio_mpipe_link_instance(ifname);
+	context = rte_eal_mpipe_context(instance);
+	if (!context) {
+		RTE_LOG(ERR, PMD, "No device for link %s.\n", ifname);
+		return -ENODEV;
+	}
+
+	priv = rte_zmalloc(NULL, sizeof(*priv), 0);
+	if (!priv) {
+		RTE_LOG(ERR, PMD, "Failed to allocate priv for %s.\n", ifname);
+		return -ENOMEM;
+	}
+
+	memset(&priv->stacks, 0xff, sizeof(priv->stacks));
+	memset(&priv->tx_stat_mapping, 0xff, sizeof(priv->tx_stat_mapping));
+	memset(&priv->rx_stat_mapping, 0xff, sizeof(priv->rx_stat_mapping));
+	priv->context = context;
+	priv->instance = instance;
+	priv->is_xaui = (strncmp(ifname, "xgbe", 4) == 0);
+	priv->pci_dev.numa_node = instance;
+	priv->channel = -1;
+
+	mac = priv->mac_addr.addr_bytes;
+	rc = mpipe_link_mac(ifname, mac);
+	if (rc < 0) {
+		RTE_LOG(ERR, PMD, "Failed to enumerate link %s.\n", ifname);
+		rte_free(priv);
+		return -ENODEV;
+	}
+
+	eth_dev = rte_eth_dev_allocate(ifname);
+	if (!eth_dev) {
+		RTE_LOG(ERR, PMD, "Failed to allocate device %s.\n", ifname);
+		rte_free(priv);
+	}
+
+	PMD_INIT_LOG(INFO, "Initialized mpipe device %s "
+		     "(mac %02x:%02x:%02x:%02x:%02x:%02x).\n", ifname,
+		     mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+	priv->eth_dev = eth_dev;
+	priv->port_id = eth_dev->data->port_id;
+	eth_dev->data->dev_private = priv;
+	eth_dev->pci_dev = &priv->pci_dev;
+	eth_dev->data->mac_addrs = &priv->mac_addr;
+
+	eth_dev->dev_ops      = &mpipe_dev_ops;
+	eth_dev->rx_pkt_burst = &mpipe_recv_pkts;
+	eth_dev->tx_pkt_burst = &mpipe_xmit_pkts;
+
+	return 0;
+}
+
+static struct rte_driver pmd_mpipe_xgbe_drv = {
+	.name = "xgbe",
+	.type = PMD_VDEV,
+	.init = rte_pmd_mpipe_devinit,
+};
+
+static struct rte_driver pmd_mpipe_gbe_drv = {
+	.name = "gbe",
+	.type = PMD_VDEV,
+	.init = rte_pmd_mpipe_devinit,
+};
+
+PMD_REGISTER_DRIVER(pmd_mpipe_xgbe_drv);
+PMD_REGISTER_DRIVER(pmd_mpipe_gbe_drv);
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 565aa77..0b83d8b 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -218,6 +218,10 @@ ifeq ($(CONFIG_RTE_LIBRTE_PMD_AF_PACKET),y)
 LDLIBS += -lrte_pmd_af_packet
 endif
 
+ifeq ($(CONFIG_RTE_LIBRTE_MPIPE_PMD),y)
+LDLIBS += -lrte_pmd_mpipe
+endif
+
 endif # plugins
 
 LDLIBS += $(EXECENV_LDLIBS)
-- 
2.1.2

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [dpdk-dev] [PATCH 14/15] app/test: turn off cpu flag checks for tile architecture
  2014-12-08  8:59 [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture Zhigang Lu
                   ` (12 preceding siblings ...)
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 13/15] pmd/tile: add mPIPE poll mode driver for TileGx Zhigang Lu
@ 2014-12-08  8:59 ` Zhigang Lu
  2014-12-09 15:03   ` Neil Horman
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 15/15] eal: allow empty set of compile time cpuflags Zhigang Lu
  14 siblings, 1 reply; 32+ messages in thread
From: Zhigang Lu @ 2014-12-08  8:59 UTC (permalink / raw)
  To: dev; +Cc: Cyril Chemparathy

Tile processor doesn't have CPU flag hardware registers, so this patch
turns off cpu flag checks for tile.

Signed-off-by: Zhigang Lu <zlu@ezchip.com>
Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
---
 app/test/test_cpuflags.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/test/test_cpuflags.c b/app/test/test_cpuflags.c
index 5aeba5d..da93af5 100644
--- a/app/test/test_cpuflags.c
+++ b/app/test/test_cpuflags.c
@@ -113,7 +113,7 @@ test_cpuflags(void)
 
 	printf("Check for ICACHE_SNOOP:\t\t");
 	CHECK_FOR_FLAG(RTE_CPUFLAG_ICACHE_SNOOP);
-#else
+#elif !defined(RTE_ARCH_TILE)
 	printf("Check for SSE:\t\t");
 	CHECK_FOR_FLAG(RTE_CPUFLAG_SSE);
 
-- 
2.1.2

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [dpdk-dev] [PATCH 15/15] eal: allow empty set of compile time cpuflags
  2014-12-08  8:59 [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture Zhigang Lu
                   ` (13 preceding siblings ...)
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 14/15] app/test: turn off cpu flag checks for tile architecture Zhigang Lu
@ 2014-12-08  8:59 ` Zhigang Lu
  14 siblings, 0 replies; 32+ messages in thread
From: Zhigang Lu @ 2014-12-08  8:59 UTC (permalink / raw)
  To: dev; +Cc: Cyril Chemparathy

On architectures that do not rely on RTE_COMPILE_TIME_CPUFLAGS, the
compile_time_flags[] array can end up being zero sized.  This results in a
compiler complaint in the subsequent loop.  Pulling out the array size
computation silences this complaint.

Signed-off-by: Zhigang Lu <zlu@ezchip.com>
Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
---
 lib/librte_eal/common/eal_common_cpuflags.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/common/eal_common_cpuflags.c b/lib/librte_eal/common/eal_common_cpuflags.c
index 6fd360c..7a1ca26 100644
--- a/lib/librte_eal/common/eal_common_cpuflags.c
+++ b/lib/librte_eal/common/eal_common_cpuflags.c
@@ -62,10 +62,12 @@ rte_cpu_check_supported(void)
 	static const enum rte_cpu_flag_t compile_time_flags[] = {
 			RTE_COMPILE_TIME_CPUFLAGS
 	};
+	unsigned count =
+		sizeof(compile_time_flags)/sizeof(compile_time_flags[0]);
 	unsigned i;
 	int ret;
 
-	for (i = 0; i < sizeof(compile_time_flags)/sizeof(compile_time_flags[0]); i++) {
+	for (i = 0; i < count; i++) {
 		ret = rte_cpu_get_flag_enabled(compile_time_flags[i]);
 
 		if (ret < 0) {
-- 
2.1.2

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [dpdk-dev] [PATCH 01/15] mk: introduce Tilera Tile architecture
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 01/15] mk: introduce Tilera Tile architecture Zhigang Lu
@ 2014-12-08 11:09   ` Bruce Richardson
  2014-12-08 14:25     ` Neil Horman
  0 siblings, 1 reply; 32+ messages in thread
From: Bruce Richardson @ 2014-12-08 11:09 UTC (permalink / raw)
  To: Zhigang Lu; +Cc: dev, Cyril Chemparathy

On Mon, Dec 08, 2014 at 04:59:24PM +0800, Zhigang Lu wrote:
> Add defconfig and rte.vars.mk files for Tile architecture.
> 
> Signed-off-by: Zhigang Lu <zlu@ezchip.com>
> Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
> ---
>  config/defconfig_tile-tilegx-linuxapp-gcc | 78 +++++++++++++++++++++++++++++++
>  mk/arch/tile/rte.vars.mk                  | 59 +++++++++++++++++++++++
>  mk/machine/tilegx/rte.vars.mk             | 58 +++++++++++++++++++++++
>  3 files changed, 195 insertions(+)
>  create mode 100644 config/defconfig_tile-tilegx-linuxapp-gcc
>  create mode 100644 mk/arch/tile/rte.vars.mk
>  create mode 100644 mk/machine/tilegx/rte.vars.mk
>

I think this should probably be the final patch in the series, rather than the
first. It's generally best to set up all requirements first before enabling things
in the compile time configuration. Once this patch is added, there is a non-functional
target added for tile architecture. If it's added last, the moment the compile
time config is added it works correctly.

/Bruce

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [dpdk-dev] [PATCH 01/15] mk: introduce Tilera Tile architecture
  2014-12-08 11:09   ` Bruce Richardson
@ 2014-12-08 14:25     ` Neil Horman
  2014-12-08 21:34       ` Cyril Chemparathy
  0 siblings, 1 reply; 32+ messages in thread
From: Neil Horman @ 2014-12-08 14:25 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev, Cyril Chemparathy

On Mon, Dec 08, 2014 at 11:09:13AM +0000, Bruce Richardson wrote:
> On Mon, Dec 08, 2014 at 04:59:24PM +0800, Zhigang Lu wrote:
> > Add defconfig and rte.vars.mk files for Tile architecture.
> > 
> > Signed-off-by: Zhigang Lu <zlu@ezchip.com>
> > Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
> > ---
> >  config/defconfig_tile-tilegx-linuxapp-gcc | 78 +++++++++++++++++++++++++++++++
> >  mk/arch/tile/rte.vars.mk                  | 59 +++++++++++++++++++++++
> >  mk/machine/tilegx/rte.vars.mk             | 58 +++++++++++++++++++++++
> >  3 files changed, 195 insertions(+)
> >  create mode 100644 config/defconfig_tile-tilegx-linuxapp-gcc
> >  create mode 100644 mk/arch/tile/rte.vars.mk
> >  create mode 100644 mk/machine/tilegx/rte.vars.mk
> >
> 
> I think this should probably be the final patch in the series, rather than the
> first. It's generally best to set up all requirements first before enabling things
> in the compile time configuration. Once this patch is added, there is a non-functional
> target added for tile architecture. If it's added last, the moment the compile
> time config is added it works correctly.
> 
> /Bruce
> 
> 
Agreed, this should be last.  Also, just for clarity, you're posting this very
close to the 1.8 release.  I presume your intent is to add this in for the 2.0
release, correct?
Neil

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [dpdk-dev] [PATCH 02/15] eal/tile: add atomic operations for TileGx
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 02/15] eal/tile: add atomic operations for TileGx Zhigang Lu
@ 2014-12-08 14:28   ` Neil Horman
  2014-12-08 21:29     ` Cyril Chemparathy
  0 siblings, 1 reply; 32+ messages in thread
From: Neil Horman @ 2014-12-08 14:28 UTC (permalink / raw)
  To: Zhigang Lu; +Cc: dev, Cyril Chemparathy

On Mon, Dec 08, 2014 at 04:59:25PM +0800, Zhigang Lu wrote:
> This patch adds architecture specific memory barrier operations for
> TileGx.
> 
> Signed-off-by: Zhigang Lu <zlu@ezchip.com>
> Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
> ---
>  .../common/include/arch/tile/rte_atomic.h          | 62 ++++++++++++++++++++++
>  1 file changed, 62 insertions(+)
>  create mode 100644 lib/librte_eal/common/include/arch/tile/rte_atomic.h
> 
> diff --git a/lib/librte_eal/common/include/arch/tile/rte_atomic.h b/lib/librte_eal/common/include/arch/tile/rte_atomic.h
> new file mode 100644
> index 0000000..24c9b0a
> --- /dev/null
> +++ b/lib/librte_eal/common/include/arch/tile/rte_atomic.h
> @@ -0,0 +1,62 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2014 Tilera Corporation. 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 Tilera 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_ATOMIC_TILE_H_
> +#define _RTE_ATOMIC_TILE_H_
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#include "generic/rte_atomic.h"
> +
> +static inline void rte_mb(void)
> +{
> +	__sync_synchronize();
> +}
> +
> +static inline void rte_wmb(void)
> +{
> +	__sync_synchronize();
> +}
> +
> +static inline void rte_rmb(void)
> +{
> +	__sync_synchronize();
I don't see __sync_synchronize defined anywhere.  Is that an intrinsic for gcc,
or a library call?

Neil

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [dpdk-dev] [PATCH 11/15] eal/tile: add EAL support for global mPIPE initialization
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 11/15] eal/tile: add EAL support for global mPIPE initialization Zhigang Lu
@ 2014-12-08 20:03   ` Neil Horman
  2014-12-08 21:32     ` Cyril Chemparathy
  0 siblings, 1 reply; 32+ messages in thread
From: Neil Horman @ 2014-12-08 20:03 UTC (permalink / raw)
  To: Zhigang Lu; +Cc: dev, Cyril Chemparathy

On Mon, Dec 08, 2014 at 04:59:34PM +0800, Zhigang Lu wrote:
> The TileGx mPIPE hardware provides Ethernet connectivity,
> packet classification, and packet load balancing services.
> 
> Signed-off-by: Zhigang Lu <zlu@ezchip.com>
> Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
> ---
>  .../common/include/arch/tile/rte_mpipe.h           |  67 ++++++++++
>  lib/librte_eal/linuxapp/eal/Makefile               |   3 +
>  lib/librte_eal/linuxapp/eal/eal.c                  |   9 ++
>  lib/librte_eal/linuxapp/eal/eal_mpipe_tile.c       | 147 +++++++++++++++++++++
>  mk/rte.app.mk                                      |   4 +
>  5 files changed, 230 insertions(+)
>  create mode 100644 lib/librte_eal/common/include/arch/tile/rte_mpipe.h
>  create mode 100644 lib/librte_eal/linuxapp/eal/eal_mpipe_tile.c
> 

This seems like the wrong way to implement mpip access.  If you want to use it
for networking access, you should create a pmd to talk to it.  If you just want
raw gxio access, you already have a gxio library that applications can interface
to.  Theres no need to create addtional DPDK api services just to wrap it up,
especially given that those surfaces won't exist outside of the tile arch (i.e.
this allows for the creation of very non-portable applications).

NAK

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [dpdk-dev] [PATCH 02/15] eal/tile: add atomic operations for TileGx
  2014-12-08 14:28   ` Neil Horman
@ 2014-12-08 21:29     ` Cyril Chemparathy
  0 siblings, 0 replies; 32+ messages in thread
From: Cyril Chemparathy @ 2014-12-08 21:29 UTC (permalink / raw)
  To: Neil Horman, Zhigang Lu; +Cc: dev

On 12/8/2014 6:28 AM, Neil Horman wrote:
> On Mon, Dec 08, 2014 at 04:59:25PM +0800, Zhigang Lu wrote:
>> This patch adds architecture specific memory barrier operations for
>> TileGx.
>>
>> Signed-off-by: Zhigang Lu <zlu@ezchip.com>
>> Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
>> ---
[...]
>> +	__sync_synchronize();
> I don't see __sync_synchronize defined anywhere.  Is that an intrinsic for gcc,
> or a library call?

That is a GCC primitive.


-- Cyril.

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [dpdk-dev] [PATCH 11/15] eal/tile: add EAL support for global mPIPE initialization
  2014-12-08 20:03   ` Neil Horman
@ 2014-12-08 21:32     ` Cyril Chemparathy
  2014-12-09 11:36       ` Neil Horman
  0 siblings, 1 reply; 32+ messages in thread
From: Cyril Chemparathy @ 2014-12-08 21:32 UTC (permalink / raw)
  To: Neil Horman, Zhigang Lu; +Cc: dev

Hi Neil,


On 12/8/2014 12:03 PM, Neil Horman wrote:
> On Mon, Dec 08, 2014 at 04:59:34PM +0800, Zhigang Lu wrote:
>> The TileGx mPIPE hardware provides Ethernet connectivity,
>> packet classification, and packet load balancing services.
>>
>> Signed-off-by: Zhigang Lu <zlu@ezchip.com>
>> Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
>> ---
>>   .../common/include/arch/tile/rte_mpipe.h           |  67 ++++++++++
>>   lib/librte_eal/linuxapp/eal/Makefile               |   3 +
>>   lib/librte_eal/linuxapp/eal/eal.c                  |   9 ++
>>   lib/librte_eal/linuxapp/eal/eal_mpipe_tile.c       | 147 +++++++++++++++++++++
>>   mk/rte.app.mk                                      |   4 +
>>   5 files changed, 230 insertions(+)
>>   create mode 100644 lib/librte_eal/common/include/arch/tile/rte_mpipe.h
>>   create mode 100644 lib/librte_eal/linuxapp/eal/eal_mpipe_tile.c
>>
> This seems like the wrong way to implement mpip access.  If you want to use it
> for networking access, you should create a pmd to talk to it.  If you just want
> raw gxio access, you already have a gxio library that applications can interface
> to.  Theres no need to create addtional DPDK api services just to wrap it up,
> especially given that those surfaces won't exist outside of the tile arch (i.e.
> this allows for the creation of very non-portable applications).

Thanks for the taking a look.

The mPIPE hardware block includes hardware managed buffer pools, which 
we've abstracted under the mempool interface in the very next patch in 
the series.  As a result of this mempool dependency, mPIPE needs to be 
globally initialized on TileGX architecture.

The alternative is to not include support for the hardware managed 
buffer pool, but that decision incurs a significant performance hit.

Thanks
-- Cyril.

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [dpdk-dev] [PATCH 01/15] mk: introduce Tilera Tile architecture
  2014-12-08 14:25     ` Neil Horman
@ 2014-12-08 21:34       ` Cyril Chemparathy
  0 siblings, 0 replies; 32+ messages in thread
From: Cyril Chemparathy @ 2014-12-08 21:34 UTC (permalink / raw)
  To: dev

On 12/8/2014 6:25 AM, Neil Horman wrote:
> On Mon, Dec 08, 2014 at 11:09:13AM +0000, Bruce Richardson wrote:
>> On Mon, Dec 08, 2014 at 04:59:24PM +0800, Zhigang Lu wrote:
>>> Add defconfig and rte.vars.mk files for Tile architecture.
>>>
>>> Signed-off-by: Zhigang Lu <zlu@ezchip.com>
>>> Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
>>> ---
>>>   config/defconfig_tile-tilegx-linuxapp-gcc | 78 +++++++++++++++++++++++++++++++
>>>   mk/arch/tile/rte.vars.mk                  | 59 +++++++++++++++++++++++
>>>   mk/machine/tilegx/rte.vars.mk             | 58 +++++++++++++++++++++++
>>>   3 files changed, 195 insertions(+)
>>>   create mode 100644 config/defconfig_tile-tilegx-linuxapp-gcc
>>>   create mode 100644 mk/arch/tile/rte.vars.mk
>>>   create mode 100644 mk/machine/tilegx/rte.vars.mk
>>>
>> I think this should probably be the final patch in the series, rather than the
>> first. It's generally best to set up all requirements first before enabling things
>> in the compile time configuration. Once this patch is added, there is a non-functional
>> target added for tile architecture. If it's added last, the moment the compile
>> time config is added it works correctly.
>>
>> /Bruce
>>
>>
> Agreed, this should be last.  Also, just for clarity, you're posting this very
> close to the 1.8 release.  I presume your intent is to add this in for the 2.0
> release, correct?

Fair point.  Thanks.

We'll reorder in the next version of this series.

Thanks
-- Cyril.

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [dpdk-dev] [PATCH 11/15] eal/tile: add EAL support for global mPIPE initialization
  2014-12-08 21:32     ` Cyril Chemparathy
@ 2014-12-09 11:36       ` Neil Horman
  0 siblings, 0 replies; 32+ messages in thread
From: Neil Horman @ 2014-12-09 11:36 UTC (permalink / raw)
  To: Cyril Chemparathy; +Cc: dev

On Mon, Dec 08, 2014 at 01:32:30PM -0800, Cyril Chemparathy wrote:
> Hi Neil,
> 
> 
> On 12/8/2014 12:03 PM, Neil Horman wrote:
> >On Mon, Dec 08, 2014 at 04:59:34PM +0800, Zhigang Lu wrote:
> >>The TileGx mPIPE hardware provides Ethernet connectivity,
> >>packet classification, and packet load balancing services.
> >>
> >>Signed-off-by: Zhigang Lu <zlu@ezchip.com>
> >>Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
> >>---
> >>  .../common/include/arch/tile/rte_mpipe.h           |  67 ++++++++++
> >>  lib/librte_eal/linuxapp/eal/Makefile               |   3 +
> >>  lib/librte_eal/linuxapp/eal/eal.c                  |   9 ++
> >>  lib/librte_eal/linuxapp/eal/eal_mpipe_tile.c       | 147 +++++++++++++++++++++
> >>  mk/rte.app.mk                                      |   4 +
> >>  5 files changed, 230 insertions(+)
> >>  create mode 100644 lib/librte_eal/common/include/arch/tile/rte_mpipe.h
> >>  create mode 100644 lib/librte_eal/linuxapp/eal/eal_mpipe_tile.c
> >>
> >This seems like the wrong way to implement mpip access.  If you want to use it
> >for networking access, you should create a pmd to talk to it.  If you just want
> >raw gxio access, you already have a gxio library that applications can interface
> >to.  Theres no need to create addtional DPDK api services just to wrap it up,
> >especially given that those surfaces won't exist outside of the tile arch (i.e.
> >this allows for the creation of very non-portable applications).
> 
> Thanks for the taking a look.
> 
> The mPIPE hardware block includes hardware managed buffer pools, which we've
> abstracted under the mempool interface in the very next patch in the series.
> As a result of this mempool dependency, mPIPE needs to be globally
> initialized on TileGX architecture.
> 
Ok, but you already have a mechanism to do that, in that the application can use
the gxio library to do the initialization itself, and you don't need to provide
additional wrapper calls that are arch specific in a common library.

> The alternative is to not include support for the hardware managed buffer
> pool, but that decision incurs a significant performance hit.
> 
No, there are plenty of alternatives to just not doing it.  In fact, you can
create a constructor to do this initialization work, and manage the instance
id's so that the user never has to see it

Neil

> Thanks
> -- Cyril.
> 

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [dpdk-dev] [PATCH 12/15] eal/tile: add mPIPE buffer stack mempool provider
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 12/15] eal/tile: add mPIPE buffer stack mempool provider Zhigang Lu
@ 2014-12-09 14:07   ` Neil Horman
  2014-12-12  8:30     ` Tony Lu
  0 siblings, 1 reply; 32+ messages in thread
From: Neil Horman @ 2014-12-09 14:07 UTC (permalink / raw)
  To: Zhigang Lu; +Cc: dev

On Mon, Dec 08, 2014 at 04:59:35PM +0800, Zhigang Lu wrote:
> TileGX: Modified mempool to allow for variable metadata.
> Signed-off-by: Zhigang Lu <zlu@ezchip.com>
> Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
> ---
>  app/test-pmd/mempool_anon.c           |   2 +-
>  app/test/Makefile                     |   6 +-
>  app/test/test_mempool_tile.c          | 217 ++++++++++++
>  lib/Makefile                          |   5 +
>  lib/librte_eal/linuxapp/eal/Makefile  |   4 +
>  lib/librte_mempool_tile/Makefile      |  48 +++
>  lib/librte_mempool_tile/rte_mempool.c | 381 ++++++++++++++++++++
>  lib/librte_mempool_tile/rte_mempool.h | 634 ++++++++++++++++++++++++++++++++++
>  8 files changed, 1295 insertions(+), 2 deletions(-)
>  create mode 100644 app/test/test_mempool_tile.c
>  create mode 100644 lib/librte_mempool_tile/Makefile
>  create mode 100644 lib/librte_mempool_tile/rte_mempool.c
>  create mode 100644 lib/librte_mempool_tile/rte_mempool.h
> 
NAK, this creates an alternate, parallel implementation of the mempool api, that
re-implements some aspects of the mempool api, but not others.  This will make
for completely no-portable applications (both to and from the tile arch), and
create maintnence problems, in that features for mempool will need to be
implemented in multiple libraries.

I understand wanting to use mpipe, and thats perfectly fine, but creating
no-portable apis to do so isn't the right way to go.  Instead, why not just
allow applications to use mpipe by initalizing it via the gxio library and
crating a mempool using the existing libraries' rte_mempool_xmem_create api
call, which allows for existing allocated memory space to be managed as a
mempool?

Neil

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [dpdk-dev] [PATCH 14/15] app/test: turn off cpu flag checks for tile architecture
  2014-12-08  8:59 ` [dpdk-dev] [PATCH 14/15] app/test: turn off cpu flag checks for tile architecture Zhigang Lu
@ 2014-12-09 15:03   ` Neil Horman
  2014-12-11  4:43     ` Tony Lu
  0 siblings, 1 reply; 32+ messages in thread
From: Neil Horman @ 2014-12-09 15:03 UTC (permalink / raw)
  To: Zhigang Lu; +Cc: dev

On Mon, Dec 08, 2014 at 04:59:37PM +0800, Zhigang Lu wrote:
> Tile processor doesn't have CPU flag hardware registers, so this patch
> turns off cpu flag checks for tile.
> 
> Signed-off-by: Zhigang Lu <zlu@ezchip.com>
> Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
> ---
>  app/test/test_cpuflags.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/app/test/test_cpuflags.c b/app/test/test_cpuflags.c
> index 5aeba5d..da93af5 100644
> --- a/app/test/test_cpuflags.c
> +++ b/app/test/test_cpuflags.c
> @@ -113,7 +113,7 @@ test_cpuflags(void)
>  
>  	printf("Check for ICACHE_SNOOP:\t\t");
>  	CHECK_FOR_FLAG(RTE_CPUFLAG_ICACHE_SNOOP);
> -#else
> +#elif !defined(RTE_ARCH_TILE)
>  	printf("Check for SSE:\t\t");
>  	CHECK_FOR_FLAG(RTE_CPUFLAG_SSE);
>  
Please stop this.  It doesn't make sense for a library that supports multiple
arches, we need some way to generically test for flags that doesn't involve
forcing applications to do ton's of ifdeffing.  Perhaps rte_cpu_get_flag_enabled
needs to do a flag table lookup based on the detected arch at run time, and
return the appropriate response.  In the case of tile, it can just be an empty
table, so 0 is always returned.  But making an application responsible for doing
arch checks is a guarantee to write non-portable applications

Neil

> -- 
> 2.1.2
> 
> 

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [dpdk-dev] [PATCH 14/15] app/test: turn off cpu flag checks for tile architecture
  2014-12-09 15:03   ` Neil Horman
@ 2014-12-11  4:43     ` Tony Lu
  2014-12-11 13:39       ` Neil Horman
  0 siblings, 1 reply; 32+ messages in thread
From: Tony Lu @ 2014-12-11  4:43 UTC (permalink / raw)
  To: 'Neil Horman'; +Cc: dev

>-----Original Message-----
>From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Neil Horman
>Sent: Tuesday, December 09, 2014 11:03 PM
>To: Zhigang Lu
>Cc: dev@dpdk.org
>Subject: Re: [dpdk-dev] [PATCH 14/15] app/test: turn off cpu flag checks
for tile
>architecture
>
>On Mon, Dec 08, 2014 at 04:59:37PM +0800, Zhigang Lu wrote:
>> Tile processor doesn't have CPU flag hardware registers, so this patch
>> turns off cpu flag checks for tile.
>>
>> Signed-off-by: Zhigang Lu <zlu@ezchip.com>
>> Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
>> ---
>>  app/test/test_cpuflags.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/app/test/test_cpuflags.c b/app/test/test_cpuflags.c index
>> 5aeba5d..da93af5 100644
>> --- a/app/test/test_cpuflags.c
>> +++ b/app/test/test_cpuflags.c
>> @@ -113,7 +113,7 @@ test_cpuflags(void)
>>
>>  	printf("Check for ICACHE_SNOOP:\t\t");
>>  	CHECK_FOR_FLAG(RTE_CPUFLAG_ICACHE_SNOOP);
>> -#else
>> +#elif !defined(RTE_ARCH_TILE)
>>  	printf("Check for SSE:\t\t");
>>  	CHECK_FOR_FLAG(RTE_CPUFLAG_SSE);
>>
>Please stop this.  It doesn't make sense for a library that supports
multiple
>arches, we need some way to generically test for flags that doesn't involve
>forcing applications to do ton's of ifdeffing.  Perhaps
rte_cpu_get_flag_enabled
>needs to do a flag table lookup based on the detected arch at run time, and
>return the appropriate response.  In the case of tile, it can just be an
empty
>table, so 0 is always returned.  But making an application responsible for
doing
>arch checks is a guarantee to write non-portable applications
>
>Neil
>

Thanks for taking a look at this.
This change just follows what PPC did in commit 9ae15538. The root cause is
that
the test_cpuflags.c explicitly tests X86-specific CPU flags, so we might
need to revise
this test case to make it architecture-independent.

A alternative change to this test case is as follows.
--- a/app/test/test_cpuflags.c
+++ b/app/test/test_cpuflags.c
@@ -77,81 +77,13 @@ cpu_flag_result(int result)
 static int
 test_cpuflags(void)
 {
-       int result;
+       int i, result;
        printf("\nChecking for flags from different registers...\n");
 
-#ifdef RTE_ARCH_PPC_64
-       printf("Check for PPC64:\t\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_PPC64);
-
-       printf("Check for PPC32:\t\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_PPC32);
-
-       printf("Check for VSX:\t\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_VSX);
-
-       printf("Check for DFP:\t\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_DFP);
-
-       printf("Check for FPU:\t\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_FPU);
-
-       printf("Check for SMT:\t\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_SMT);
-
-       printf("Check for MMU:\t\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_MMU);
-
-       printf("Check for ALTIVEC:\t\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_ALTIVEC);
-
-       printf("Check for ARCH_2_06:\t\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_ARCH_2_06);
-
-       printf("Check for ARCH_2_07:\t\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_ARCH_2_07);
-
-       printf("Check for ICACHE_SNOOP:\t\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_ICACHE_SNOOP);
-#else
-       printf("Check for SSE:\t\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_SSE);
-
-       printf("Check for SSE2:\t\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_SSE2);
-
-       printf("Check for SSE3:\t\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_SSE3);
-
-       printf("Check for SSE4.1:\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_SSE4_1);
-
-       printf("Check for SSE4.2:\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_SSE4_2);
-
-       printf("Check for AVX:\t\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_AVX);
-
-       printf("Check for AVX2:\t\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_AVX2);
-
-       printf("Check for TRBOBST:\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_TRBOBST);
-
-       printf("Check for ENERGY_EFF:\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_ENERGY_EFF);
-
-       printf("Check for LAHF_SAHF:\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_LAHF_SAHF);
-
-       printf("Check for 1GB_PG:\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_1GB_PG);
-
-       printf("Check for INVTSC:\t");
-       CHECK_FOR_FLAG(RTE_CPUFLAG_INVTSC);
-
-
-#endif
+       for (i = 0; i < RTE_CPUFLAG_NUMFLAGS; i++) {
+               printf("Check for %s:\t\t", cpu_feature_table[i].name);
+               CHECK_FOR_FLAG(i);
+       }

Thanks
-Zhigang

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [dpdk-dev] [PATCH 14/15] app/test: turn off cpu flag checks for tile architecture
  2014-12-11  4:43     ` Tony Lu
@ 2014-12-11 13:39       ` Neil Horman
  2014-12-12  8:10         ` Tony Lu
  0 siblings, 1 reply; 32+ messages in thread
From: Neil Horman @ 2014-12-11 13:39 UTC (permalink / raw)
  To: Tony Lu; +Cc: dev

On Thu, Dec 11, 2014 at 12:43:36PM +0800, Tony Lu wrote:
> >-----Original Message-----
> >From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Neil Horman
> >Sent: Tuesday, December 09, 2014 11:03 PM
> >To: Zhigang Lu
> >Cc: dev@dpdk.org
> >Subject: Re: [dpdk-dev] [PATCH 14/15] app/test: turn off cpu flag checks
> for tile
> >architecture
> >
> >On Mon, Dec 08, 2014 at 04:59:37PM +0800, Zhigang Lu wrote:
> >> Tile processor doesn't have CPU flag hardware registers, so this patch
> >> turns off cpu flag checks for tile.
> >>
> >> Signed-off-by: Zhigang Lu <zlu@ezchip.com>
> >> Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
> >> ---
> >>  app/test/test_cpuflags.c | 2 +-
> >>  1 file changed, 1 insertion(+), 1 deletion(-)
> >>
> >> diff --git a/app/test/test_cpuflags.c b/app/test/test_cpuflags.c index
> >> 5aeba5d..da93af5 100644
> >> --- a/app/test/test_cpuflags.c
> >> +++ b/app/test/test_cpuflags.c
> >> @@ -113,7 +113,7 @@ test_cpuflags(void)
> >>
> >>  	printf("Check for ICACHE_SNOOP:\t\t");
> >>  	CHECK_FOR_FLAG(RTE_CPUFLAG_ICACHE_SNOOP);
> >> -#else
> >> +#elif !defined(RTE_ARCH_TILE)
> >>  	printf("Check for SSE:\t\t");
> >>  	CHECK_FOR_FLAG(RTE_CPUFLAG_SSE);
> >>
> >Please stop this.  It doesn't make sense for a library that supports
> multiple
> >arches, we need some way to generically test for flags that doesn't involve
> >forcing applications to do ton's of ifdeffing.  Perhaps
> rte_cpu_get_flag_enabled
> >needs to do a flag table lookup based on the detected arch at run time, and
> >return the appropriate response.  In the case of tile, it can just be an
> empty
> >table, so 0 is always returned.  But making an application responsible for
> doing
> >arch checks is a guarantee to write non-portable applications
> >
> >Neil
> >
> 
> Thanks for taking a look at this.
> This change just follows what PPC did in commit 9ae15538. The root cause is
Yes, and I objected to it there as well:
http://dpdk.org/ml/archives/dev/2014-November/008628.html

To which the response was effectively "Sure, we'll do that later".  You're
effectively making the same argument.  If no one ever steps up to change the
interface when adding a new arch, it will never get done, and we'll have a
fragmented cpuflag test mechanism that creates completely non-portable code
accross arches.

> that
> the test_cpuflags.c explicitly tests X86-specific CPU flags, so we might
> need to revise
> this test case to make it architecture-independent.
> 
Exactly what I said in my email to the powerpc people.  If you're going
to add a new arch, and a given interface doesn't support doing so, please try to
re-design the interface to make it more friendly, otherwise we'll be left with
unmaintainable code.

Thinking about it, you probably don't even need to change the api call to do
this.  You just need to create a unified map for all flags of all supported
arches, that is to say a two dimensional array with the indicies [arch][flag]
where the stored value is the arch specific data to help determine if the
feature is supported, or a universal "not supported" flag.

Neil

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [dpdk-dev] [PATCH 14/15] app/test: turn off cpu flag checks for tile architecture
  2014-12-11 13:39       ` Neil Horman
@ 2014-12-12  8:10         ` Tony Lu
  2014-12-12 13:07           ` Neil Horman
  0 siblings, 1 reply; 32+ messages in thread
From: Tony Lu @ 2014-12-12  8:10 UTC (permalink / raw)
  To: 'Neil Horman'; +Cc: dev

>-----Original Message-----
>From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Neil Horman
>Sent: Thursday, December 11, 2014 9:39 PM
>To: Tony Lu
>Cc: dev@dpdk.org
>Subject: Re: [dpdk-dev] [PATCH 14/15] app/test: turn off cpu flag checks
for tile
>architecture
>
>On Thu, Dec 11, 2014 at 12:43:36PM +0800, Tony Lu wrote:
>> >-----Original Message-----
>> >From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Neil Horman
>> >Sent: Tuesday, December 09, 2014 11:03 PM
>> >To: Zhigang Lu
>> >Cc: dev@dpdk.org
>> >Subject: Re: [dpdk-dev] [PATCH 14/15] app/test: turn off cpu flag
>> >checks
>> for tile
>> >architecture
>> >
>> >On Mon, Dec 08, 2014 at 04:59:37PM +0800, Zhigang Lu wrote:
>> >> Tile processor doesn't have CPU flag hardware registers, so this
>> >> patch turns off cpu flag checks for tile.
>> >>
>> >> Signed-off-by: Zhigang Lu <zlu@ezchip.com>
>> >> Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
>> >> ---
>> >>  app/test/test_cpuflags.c | 2 +-
>> >>  1 file changed, 1 insertion(+), 1 deletion(-)
>> >>
>> >> diff --git a/app/test/test_cpuflags.c b/app/test/test_cpuflags.c
>> >> index
>> >> 5aeba5d..da93af5 100644
>> >> --- a/app/test/test_cpuflags.c
>> >> +++ b/app/test/test_cpuflags.c
>> >> @@ -113,7 +113,7 @@ test_cpuflags(void)
>> >>
>> >>  	printf("Check for ICACHE_SNOOP:\t\t");
>> >>  	CHECK_FOR_FLAG(RTE_CPUFLAG_ICACHE_SNOOP);
>> >> -#else
>> >> +#elif !defined(RTE_ARCH_TILE)
>> >>  	printf("Check for SSE:\t\t");
>> >>  	CHECK_FOR_FLAG(RTE_CPUFLAG_SSE);
>> >>
>> >Please stop this.  It doesn't make sense for a library that supports
>> multiple
>> >arches, we need some way to generically test for flags that doesn't
>> >involve forcing applications to do ton's of ifdeffing.  Perhaps
>> rte_cpu_get_flag_enabled
>> >needs to do a flag table lookup based on the detected arch at run
>> >time, and return the appropriate response.  In the case of tile, it
>> >can just be an
>> empty
>> >table, so 0 is always returned.  But making an application
>> >responsible for
>> doing
>> >arch checks is a guarantee to write non-portable applications
>> >
>> >Neil
>> >
>>
>> Thanks for taking a look at this.
>> This change just follows what PPC did in commit 9ae15538. The root
>> cause is
>Yes, and I objected to it there as well:
>http://dpdk.org/ml/archives/dev/2014-November/008628.html
>
>To which the response was effectively "Sure, we'll do that later".  You're
>effectively making the same argument.  If no one ever steps up to change
the
>interface when adding a new arch, it will never get done, and we'll have a
>fragmented cpuflag test mechanism that creates completely non-portable code
>accross arches.
>
>> that
>> the test_cpuflags.c explicitly tests X86-specific CPU flags, so we
>> might need to revise this test case to make it
>> architecture-independent.
>>
>Exactly what I said in my email to the powerpc people.  If you're going to
add a
>new arch, and a given interface doesn't support doing so, please try to
re-design
>the interface to make it more friendly, otherwise we'll be left with
>unmaintainable code.

Agree, Make sense.

>Thinking about it, you probably don't even need to change the api call to
do this.
>You just need to create a unified map for all flags of all supported
arches, that is
>to say a two dimensional array with the indicies [arch][flag] where the
stored
>value is the arch specific data to help determine if the feature is
supported, or a
>universal "not supported" flag.

Yes, in order not to break ACL or other libs/apps, we need to make the flags
of all
supported arches accessible.  But I don't feel as strongly to create a
[arch][flag] array,
since checking if the specified flag is supported is at runtime, so we can
not assign it in
a predefine array according to its arch. For example, some old X86 processor
does not
support SSE3.

Instead I prefer a one dimensional arch-specific [flag] array which contains
all the flags
of all supported arches, and we mark the flags that do not belong to the
current arch
as "not available".

To implement this, we need to move the enum rte_cpu_flag_t from
arch-specific
rte_cpuflags.c to the generic one, and combine them as one enumeration.

ACL rte_acl_init() itself has a bug that it should check the return value of
rte_cpu_get_flag_enabled() if it is "1", but not "!0", as it may return
"-EFAULT".

Thanks
-Zhigang

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [dpdk-dev] [PATCH 12/15] eal/tile: add mPIPE buffer stack mempool provider
  2014-12-09 14:07   ` Neil Horman
@ 2014-12-12  8:30     ` Tony Lu
  2014-12-12 13:03       ` Neil Horman
  0 siblings, 1 reply; 32+ messages in thread
From: Tony Lu @ 2014-12-12  8:30 UTC (permalink / raw)
  To: 'Neil Horman'; +Cc: dev

>-----Original Message-----
>From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Neil Horman
>Sent: Tuesday, December 09, 2014 10:07 PM
>To: Zhigang Lu
>Cc: dev@dpdk.org
>Subject: Re: [dpdk-dev] [PATCH 12/15] eal/tile: add mPIPE buffer stack
mempool
>provider
>
>On Mon, Dec 08, 2014 at 04:59:35PM +0800, Zhigang Lu wrote:
>> TileGX: Modified mempool to allow for variable metadata.
>> Signed-off-by: Zhigang Lu <zlu@ezchip.com>
>> Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
>> ---
>>  app/test-pmd/mempool_anon.c           |   2 +-
>>  app/test/Makefile                     |   6 +-
>>  app/test/test_mempool_tile.c          | 217 ++++++++++++
>>  lib/Makefile                          |   5 +
>>  lib/librte_eal/linuxapp/eal/Makefile  |   4 +
>>  lib/librte_mempool_tile/Makefile      |  48 +++
>>  lib/librte_mempool_tile/rte_mempool.c | 381 ++++++++++++++++++++
>> lib/librte_mempool_tile/rte_mempool.h | 634
>> ++++++++++++++++++++++++++++++++++
>>  8 files changed, 1295 insertions(+), 2 deletions(-)  create mode
>> 100644 app/test/test_mempool_tile.c  create mode 100644
>> lib/librte_mempool_tile/Makefile  create mode 100644
>> lib/librte_mempool_tile/rte_mempool.c
>>  create mode 100644 lib/librte_mempool_tile/rte_mempool.h
>>
>NAK, this creates an alternate, parallel implementation of the mempool api,
>that re-implements some aspects of the mempool api, but not others.  This
will
>make for completely no-portable applications (both to and from the tile
arch),
>and create maintnence problems, in that features for mempool will need to
be
>implemented in multiple libraries.
>
>I understand wanting to use mpipe, and thats perfectly fine, but creating
>no-portable apis to do so isn't the right way to go.  Instead, why not just
allow
>applications to use mpipe by initalizing it via the gxio library and
crating a
>mempool using the existing libraries' rte_mempool_xmem_create api call,
which
>allows for existing allocated memory space to be managed as a mempool?

Yes, the mempool we are using is very much tile-specific, as we want to use
the mpipe
hardware managed buffer pool to implement the mempool, which greatly improve
the
performance of mempool.

As Cyril replied in a previous email:
The alternative is to not include support for the hardware managed buffer
pool, but that
decision incurs a significant performance hit.

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [dpdk-dev] [PATCH 12/15] eal/tile: add mPIPE buffer stack mempool provider
  2014-12-12  8:30     ` Tony Lu
@ 2014-12-12 13:03       ` Neil Horman
  0 siblings, 0 replies; 32+ messages in thread
From: Neil Horman @ 2014-12-12 13:03 UTC (permalink / raw)
  To: Tony Lu; +Cc: dev

On Fri, Dec 12, 2014 at 04:30:27PM +0800, Tony Lu wrote:
> >-----Original Message-----
> >From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Neil Horman
> >Sent: Tuesday, December 09, 2014 10:07 PM
> >To: Zhigang Lu
> >Cc: dev@dpdk.org
> >Subject: Re: [dpdk-dev] [PATCH 12/15] eal/tile: add mPIPE buffer stack
> mempool
> >provider
> >
> >On Mon, Dec 08, 2014 at 04:59:35PM +0800, Zhigang Lu wrote:
> >> TileGX: Modified mempool to allow for variable metadata.
> >> Signed-off-by: Zhigang Lu <zlu@ezchip.com>
> >> Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
> >> ---
> >>  app/test-pmd/mempool_anon.c           |   2 +-
> >>  app/test/Makefile                     |   6 +-
> >>  app/test/test_mempool_tile.c          | 217 ++++++++++++
> >>  lib/Makefile                          |   5 +
> >>  lib/librte_eal/linuxapp/eal/Makefile  |   4 +
> >>  lib/librte_mempool_tile/Makefile      |  48 +++
> >>  lib/librte_mempool_tile/rte_mempool.c | 381 ++++++++++++++++++++
> >> lib/librte_mempool_tile/rte_mempool.h | 634
> >> ++++++++++++++++++++++++++++++++++
> >>  8 files changed, 1295 insertions(+), 2 deletions(-)  create mode
> >> 100644 app/test/test_mempool_tile.c  create mode 100644
> >> lib/librte_mempool_tile/Makefile  create mode 100644
> >> lib/librte_mempool_tile/rte_mempool.c
> >>  create mode 100644 lib/librte_mempool_tile/rte_mempool.h
> >>
> >NAK, this creates an alternate, parallel implementation of the mempool api,
> >that re-implements some aspects of the mempool api, but not others.  This
> will
> >make for completely no-portable applications (both to and from the tile
> arch),
> >and create maintnence problems, in that features for mempool will need to
> be
> >implemented in multiple libraries.
> >
> >I understand wanting to use mpipe, and thats perfectly fine, but creating
> >no-portable apis to do so isn't the right way to go.  Instead, why not just
> allow
> >applications to use mpipe by initalizing it via the gxio library and
> crating a
> >mempool using the existing libraries' rte_mempool_xmem_create api call,
> which
> >allows for existing allocated memory space to be managed as a mempool?
> 
> Yes, the mempool we are using is very much tile-specific, as we want to use
> the mpipe
> hardware managed buffer pool to implement the mempool, which greatly improve
> the
> performance of mempool.
> 
> As Cyril replied in a previous email:
> The alternative is to not include support for the hardware managed buffer
> pool, but that
> decision incurs a significant performance hit.
> 
You're not reading my previous notes clearly.  There is no need to completely
re-implement the mempool interface.  Doing so is completely broken.  There
already exists a mechanism in the existing interface to allow you to pass
pre-allocated memory to mempool for management.  As such, you can use the
existing gxio library to allocate and initlize your mpipe hardware, and use the
existing mempool infrastructure to manage it.

Until then, I re-iterate my NAK

Neil

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [dpdk-dev] [PATCH 14/15] app/test: turn off cpu flag checks for tile architecture
  2014-12-12  8:10         ` Tony Lu
@ 2014-12-12 13:07           ` Neil Horman
  0 siblings, 0 replies; 32+ messages in thread
From: Neil Horman @ 2014-12-12 13:07 UTC (permalink / raw)
  To: Tony Lu; +Cc: dev

On Fri, Dec 12, 2014 at 04:10:21PM +0800, Tony Lu wrote:
> >-----Original Message-----
> >From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Neil Horman
> >Sent: Thursday, December 11, 2014 9:39 PM
> >To: Tony Lu
> >Cc: dev@dpdk.org
> >Subject: Re: [dpdk-dev] [PATCH 14/15] app/test: turn off cpu flag checks
> for tile
> >architecture
> >
> >On Thu, Dec 11, 2014 at 12:43:36PM +0800, Tony Lu wrote:
> >> >-----Original Message-----
> >> >From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Neil Horman
> >> >Sent: Tuesday, December 09, 2014 11:03 PM
> >> >To: Zhigang Lu
> >> >Cc: dev@dpdk.org
> >> >Subject: Re: [dpdk-dev] [PATCH 14/15] app/test: turn off cpu flag
> >> >checks
> >> for tile
> >> >architecture
> >> >
> >> >On Mon, Dec 08, 2014 at 04:59:37PM +0800, Zhigang Lu wrote:
> >> >> Tile processor doesn't have CPU flag hardware registers, so this
> >> >> patch turns off cpu flag checks for tile.
> >> >>
> >> >> Signed-off-by: Zhigang Lu <zlu@ezchip.com>
> >> >> Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
> >> >> ---
> >> >>  app/test/test_cpuflags.c | 2 +-
> >> >>  1 file changed, 1 insertion(+), 1 deletion(-)
> >> >>
> >> >> diff --git a/app/test/test_cpuflags.c b/app/test/test_cpuflags.c
> >> >> index
> >> >> 5aeba5d..da93af5 100644
> >> >> --- a/app/test/test_cpuflags.c
> >> >> +++ b/app/test/test_cpuflags.c
> >> >> @@ -113,7 +113,7 @@ test_cpuflags(void)
> >> >>
> >> >>  	printf("Check for ICACHE_SNOOP:\t\t");
> >> >>  	CHECK_FOR_FLAG(RTE_CPUFLAG_ICACHE_SNOOP);
> >> >> -#else
> >> >> +#elif !defined(RTE_ARCH_TILE)
> >> >>  	printf("Check for SSE:\t\t");
> >> >>  	CHECK_FOR_FLAG(RTE_CPUFLAG_SSE);
> >> >>
> >> >Please stop this.  It doesn't make sense for a library that supports
> >> multiple
> >> >arches, we need some way to generically test for flags that doesn't
> >> >involve forcing applications to do ton's of ifdeffing.  Perhaps
> >> rte_cpu_get_flag_enabled
> >> >needs to do a flag table lookup based on the detected arch at run
> >> >time, and return the appropriate response.  In the case of tile, it
> >> >can just be an
> >> empty
> >> >table, so 0 is always returned.  But making an application
> >> >responsible for
> >> doing
> >> >arch checks is a guarantee to write non-portable applications
> >> >
> >> >Neil
> >> >
> >>
> >> Thanks for taking a look at this.
> >> This change just follows what PPC did in commit 9ae15538. The root
> >> cause is
> >Yes, and I objected to it there as well:
> >http://dpdk.org/ml/archives/dev/2014-November/008628.html
> >
> >To which the response was effectively "Sure, we'll do that later".  You're
> >effectively making the same argument.  If no one ever steps up to change
> the
> >interface when adding a new arch, it will never get done, and we'll have a
> >fragmented cpuflag test mechanism that creates completely non-portable code
> >accross arches.
> >
> >> that
> >> the test_cpuflags.c explicitly tests X86-specific CPU flags, so we
> >> might need to revise this test case to make it
> >> architecture-independent.
> >>
> >Exactly what I said in my email to the powerpc people.  If you're going to
> add a
> >new arch, and a given interface doesn't support doing so, please try to
> re-design
> >the interface to make it more friendly, otherwise we'll be left with
> >unmaintainable code.
> 
> Agree, Make sense.
> 
> >Thinking about it, you probably don't even need to change the api call to
> do this.
> >You just need to create a unified map for all flags of all supported
> arches, that is
> >to say a two dimensional array with the indicies [arch][flag] where the
> stored
> >value is the arch specific data to help determine if the feature is
> supported, or a
> >universal "not supported" flag.
> 
> Yes, in order not to break ACL or other libs/apps, we need to make the flags
> of all
> supported arches accessible.  But I don't feel as strongly to create a
> [arch][flag] array,
> since checking if the specified flag is supported is at runtime, so we can
> not assign it in
> a predefine array according to its arch. For example, some old X86 processor
> does not
> support SSE3.
> 
> Instead I prefer a one dimensional arch-specific [flag] array which contains
> all the flags
> of all supported arches, and we mark the flags that do not belong to the
> current arch
> as "not available".
> 
> To implement this, we need to move the enum rte_cpu_flag_t from
> arch-specific
> rte_cpuflags.c to the generic one, and combine them as one enumeration.
> 
> ACL rte_acl_init() itself has a bug that it should check the return value of
> rte_cpu_get_flag_enabled() if it is "1", but not "!0", as it may return
> "-EFAULT".
> 

Thats all fine with me.  We can debate the relative merits of implementation
when its available.  Its getting the interface right that I think is currently
the priority.
Neil

> Thanks
> -Zhigang
> 
> 

^ permalink raw reply	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2014-12-12 13:07 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-08  8:59 [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 01/15] mk: introduce Tilera Tile architecture Zhigang Lu
2014-12-08 11:09   ` Bruce Richardson
2014-12-08 14:25     ` Neil Horman
2014-12-08 21:34       ` Cyril Chemparathy
2014-12-08  8:59 ` [dpdk-dev] [PATCH 02/15] eal/tile: add atomic operations for TileGx Zhigang Lu
2014-12-08 14:28   ` Neil Horman
2014-12-08 21:29     ` Cyril Chemparathy
2014-12-08  8:59 ` [dpdk-dev] [PATCH 03/15] eal/tile: add byte order " Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 04/15] eal/tile: add spinlock " Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 05/15] eal/tile: add prefetch " Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 06/15] eal/tile: add memcpy " Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 07/15] eal/tile: add CPU flags " Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 08/15] eal/tile: add cycle " Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 09/15] eal: split vector operations to architecture specific Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 10/15] eal/tile: add vector operations for TileGx Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 11/15] eal/tile: add EAL support for global mPIPE initialization Zhigang Lu
2014-12-08 20:03   ` Neil Horman
2014-12-08 21:32     ` Cyril Chemparathy
2014-12-09 11:36       ` Neil Horman
2014-12-08  8:59 ` [dpdk-dev] [PATCH 12/15] eal/tile: add mPIPE buffer stack mempool provider Zhigang Lu
2014-12-09 14:07   ` Neil Horman
2014-12-12  8:30     ` Tony Lu
2014-12-12 13:03       ` Neil Horman
2014-12-08  8:59 ` [dpdk-dev] [PATCH 13/15] pmd/tile: add mPIPE poll mode driver for TileGx Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 14/15] app/test: turn off cpu flag checks for tile architecture Zhigang Lu
2014-12-09 15:03   ` Neil Horman
2014-12-11  4:43     ` Tony Lu
2014-12-11 13:39       ` Neil Horman
2014-12-12  8:10         ` Tony Lu
2014-12-12 13:07           ` Neil Horman
2014-12-08  8:59 ` [dpdk-dev] [PATCH 15/15] eal: allow empty set of compile time cpuflags Zhigang Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).