@@ -49,5 +49,7 @@ LIBABIVER := 1
# all source are stored in SRCS-y
#
SRCS-$(CONFIG_RTE_LIBRTE_NFP_PMD) += nfp_net.c
+SRCS-$(CONFIG_RTE_LIBRTE_NFP_PMD) += nfp_nfpu.c
+SRCS-$(CONFIG_RTE_LIBRTE_NFP_PMD) += nfp_nspu.c
include $(RTE_SDK)/mk/rte.lib.mk
new file mode 100644
@@ -0,0 +1,103 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/types.h>
+
+#include <rte_pci.h>
+#include <rte_malloc.h>
+
+#include "nfp_nfpu.h"
+
+/* PF BAR and expansion BAR for the NSP interface */
+#define NFP_CFG_PCIE_BAR 0
+#define NFP_CFG_EXP_BAR 7
+
+#define NFP_CFG_EXP_BAR_CFG_BASE 0x30000
+
+/* There could be other NFP userspace tools using the NSP interface.
+ * Make sure there is no other process using it and locking the access for
+ * avoiding problems.
+ */
+static int
+nspv_aquire_process_lock(nfpu_desc_t *desc)
+{
+ int rc;
+ struct flock lock;
+ char lockname[30];
+
+ memset(&lock, 0, sizeof(lock));
+
+ snprintf(lockname, sizeof(lockname), "/var/lock/nfp%d", desc->nfp);
+
+ /* Using S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH */
+ desc->lock = open(lockname, O_RDWR | O_CREAT, 0666);
+
+ if (desc->lock < 0)
+ return desc->lock;
+
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ rc = -1;
+ while (rc != 0) {
+ rc = fcntl(desc->lock, F_SETLK, &lock);
+ if (rc < 0) {
+ if ((errno != EAGAIN) && (errno != EACCES)) {
+ close(desc->lock);
+ return rc;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+nfpu_open(struct rte_pci_device *pci_dev, nfpu_desc_t *desc, int nfp)
+{
+ void *cfg_base, *mem_base;
+ size_t barsz;
+ int ret = 0;
+ int i = 0;
+
+ desc->nfp = nfp;
+
+ ret = nspv_aquire_process_lock(desc);
+ if (ret)
+ return -1;
+
+ barsz = pci_dev->mem_resource[0].len;
+
+ /* barsz in log2 */
+ while (barsz >>= 1)
+ i++;
+ barsz = i;
+
+ /* Getting address for NFP expansion BAR registers */
+ cfg_base = pci_dev->mem_resource[0].addr;
+ cfg_base = (uint8_t *)cfg_base + NFP_CFG_EXP_BAR_CFG_BASE;
+
+ /* Getting address for NFP NSP interface registers */
+ mem_base = pci_dev->mem_resource[0].addr;
+ mem_base = (uint8_t *)mem_base + (NFP_CFG_EXP_BAR << (barsz - 3));
+
+
+ desc->nspu = rte_malloc("nfp nspu", sizeof(nspu_desc_t), 0);
+ nfp_nspu_init(desc->nspu, desc->nfp, NFP_CFG_PCIE_BAR, barsz,
+ NFP_CFG_EXP_BAR, cfg_base, mem_base);
+
+ return ret;
+}
+
+int
+nfpu_close(nfpu_desc_t *desc)
+{
+ rte_free(desc->nspu);
+ close(desc->lock);
+ unlink("/var/lock/nfp0");
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017 Netronome Systems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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
+ *
+ * 3. Neither the name of the copyright holder 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 HOLDER 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.
+ */
+
+/*
+ * vim:shiftwidth=8:noexpandtab
+ *
+ * @file dpdk/pmd/nfp_nfpu.h
+ *
+ * Netronome NFP_NET PDM driver
+ */
+
+/*
+ * NFP User interface creates a window for talking with NFP NSP processor
+ */
+
+
+#include <rte_pci.h>
+#include "nfp_nspu.h"
+
+typedef struct {
+ int nfp;
+ int lock;
+ nspu_desc_t *nspu;
+} nfpu_desc_t;
+
+int nfpu_open(struct rte_pci_device *pci_dev, nfpu_desc_t *desc, int nfp);
+int nfpu_close(nfpu_desc_t *desc);
new file mode 100644
@@ -0,0 +1,129 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <rte_log.h>
+
+#include "nfp_nfpu.h"
+
+#define CFG_EXP_BAR_ADDR_SZ 1
+#define CFG_EXP_BAR_MAP_TYPE 1
+
+#define EXP_BAR_TARGET_SHIFT 23
+#define EXP_BAR_LENGTH_SHIFT 27 /* 0=32, 1=64 bit increment */
+#define EXP_BAR_MAP_TYPE_SHIFT 29 /* Bulk BAR map */
+
+/* NFP target for NSP access */
+#define NFP_NSP_TARGET 7
+
+/*
+ * This is an NFP internal address used for configuring properly an NFP
+ * expansion BAR.
+ */
+#define MEM_CMD_BASE_ADDR 0x8100000000
+
+/* NSP interface registers */
+#define NSP_BASE (MEM_CMD_BASE_ADDR + 0x22100)
+#define NSP_STATUS 0x00
+#define NSP_COMMAND 0x08
+#define NSP_BUFFER 0x10
+#define NSP_DEFAULT_BUFFER 0x18
+#define NSP_DEFAULT_BUFFER_CFG 0x20
+
+#define NSP_MAGIC 0xab10
+#define NSP_STATUS_MAGIC(x) (((x) >> 48) & 0xffff)
+#define NSP_STATUS_MAJOR(x) (int)(((x) >> 44) & 0xf)
+#define NSP_STATUS_MINOR(x) (int)(((x) >> 32) & 0xfff)
+
+#define NSP_REG_ADDR(d, off, reg) ((uint8_t *)(d)->mem_base + (off) + (reg))
+#define NSP_REG_VAL(p) (*(uint64_t *)(p))
+
+/*
+ * An NFP expansion BAR is configured for allowing access to a specific NFP
+ * target:
+ *
+ * IN:
+ * desc: struct with basic NSP addresses to work with
+ * expbar: NFP PF expansion BAR index to configure
+ * tgt: NFP target to configure access
+ * addr: NFP target address
+ *
+ * OUT:
+ * pcie_offset: NFP PCI BAR offset to work with
+ */
+static void
+nfp_nspu_mem_bar_cfg(nspu_desc_t *desc, int expbar, int tgt,
+ uint64_t addr, uint64_t *pcie_offset)
+{
+ uint64_t x, y, barsz;
+ uint32_t *expbar_ptr;
+
+ barsz = desc->barsz;
+
+ /*
+ * NFP CPP address to configure. This comes from NFP 6000
+ * datasheet document based on Bulk mapping.
+ */
+ x = (addr >> (barsz - 3)) << (21 - (40 - (barsz - 3)));
+ x |= CFG_EXP_BAR_MAP_TYPE << EXP_BAR_MAP_TYPE_SHIFT;
+ x |= CFG_EXP_BAR_ADDR_SZ << EXP_BAR_LENGTH_SHIFT;
+ x |= tgt << EXP_BAR_TARGET_SHIFT;
+
+ /* Getting expansion bar configuration register address */
+ expbar_ptr = (uint32_t *)desc->cfg_base;
+ /* Each physical PCI BAR has 8 NFP expansion BARs */
+ expbar_ptr += (desc->pcie_bar * 8) + expbar;
+
+ /* Writing to the expansion BAR register */
+ *expbar_ptr = (uint32_t)x;
+
+ /* Getting the pcie offset to work with from userspace */
+ y = addr & ((uint64_t)(1 << (barsz - 3)) - 1);
+ *pcie_offset = y;
+}
+
+/*
+ * Configuring an expansion bar for accessing NSP userspace interface. This
+ * function configures always the same expansion bar, which implies access to
+ * previously configured NFP target is lost.
+ */
+static void
+nspu_xlate(nspu_desc_t *desc, uint64_t addr, uint64_t *pcie_offset)
+{
+ nfp_nspu_mem_bar_cfg(desc, desc->exp_bar, NFP_NSP_TARGET, addr,
+ pcie_offset);
+}
+
+int
+nfp_nsp_get_abi_version(nspu_desc_t *desc, int *major, int *minor)
+{
+ uint64_t pcie_offset;
+ uint64_t nsp_reg;
+
+ nspu_xlate(desc, NSP_BASE, &pcie_offset);
+ nsp_reg = NSP_REG_VAL(NSP_REG_ADDR(desc, pcie_offset, NSP_STATUS));
+
+ if (NSP_STATUS_MAGIC(nsp_reg) != NSP_MAGIC)
+ return -1;
+
+ *major = NSP_STATUS_MAJOR(nsp_reg);
+ *minor = NSP_STATUS_MINOR(nsp_reg);
+
+ return 0;
+}
+
+int
+nfp_nspu_init(nspu_desc_t *desc, int nfp, int pcie_bar, size_t pcie_barsz,
+ int exp_bar, void *exp_bar_cfg_base, void *exp_bar_mmap)
+{
+ desc->nfp = nfp;
+ desc->pcie_bar = pcie_bar;
+ desc->exp_bar = exp_bar;
+ desc->barsz = pcie_barsz;
+ desc->cfg_base = exp_bar_cfg_base;
+ desc->mem_base = exp_bar_mmap;
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017 Netronome Systems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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
+ *
+ * 3. Neither the name of the copyright holder 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 HOLDER 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.
+ */
+
+/*
+ * vim:shiftwidth=8:noexpandtab
+ *
+ * @file dpdk/pmd/nfp_nspu.h
+ *
+ * Netronome NFP_NET PDM driver
+ */
+
+/*
+ * NSP is the NFP Service Processor. NSPU is NSP Userspace interface.
+ *
+ * NFP NSP helps with firmware/hardware configuration. NSP is another component
+ * in NFP programmable processor and accessing it from host requires to firstly
+ * configure a specific NFP PCI expansion BAR.
+ *
+ * Once access is ready, configuration can be done reading and writing
+ * from/to a specific PF PCI BAR window. This same interface will allow to
+ * create other PCI BAR windows for accessing other NFP components.
+ *
+ * This file includes low-level functions, using the NSPU interface, and high
+ * level functions, invoked by the PMD for using NSP services. This allows
+ * firmware upload, vNIC PCI BARs mapping and other low-level configurations
+ * like link setup.
+ *
+ * NSP access is done during initialization and it is not involved at all with
+ * the fast path.
+ */
+
+typedef struct {
+ int nfp; /* NFP device */
+ int pcie_bar; /* PF PCI BAR to work with */
+ int exp_bar; /* Expansion BAR number used by NSPU */
+ int barsz; /* PCIE BAR log2 size */
+ void *cfg_base; /* Expansion BARs address */
+ void *mem_base; /* NSP interface */
+} nspu_desc_t;
+
+int nfp_nspu_init(nspu_desc_t *desc, int nfp, int pcie_bar, size_t pcie_barsz,
+ int exp_bar, void *exp_bar_cfg_base, void *exp_bar_mmap);
+int nfp_nsp_get_abi_version(nspu_desc_t *desc, int *major, int *minor);