net/nfp: add NSP support for HW link configuration
authorAlejandro Lucero <alejandro.lucero@netronome.com>
Fri, 1 Sep 2017 14:12:16 +0000 (15:12 +0100)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 6 Oct 2017 00:49:48 +0000 (02:49 +0200)
Adding a new NSPU command for being able to read and write the ethernet
port table from/to the NFP. This will allow the PMD to put the Link up
or down when a port is started or stopped. Until now, this was performed
by the firmware independently of PMD functionality.

The ethernet port table has also some other useful information that will
be used in further commits.

Usually NSPU is used at device probe time and that is sequential code
execution. However, reading and writing the NFP eth table can be done at
different times and from different cores, and it implies it could happen
a concurrent access. A spinlock is added to the global nspu object for
protecting the NFP and avoiding the concurrent access.

Signed-off-by: Alejandro Lucero <alejandro.lucero@netronome.com>
drivers/net/nfp/nfp_net_eth.h [new file with mode: 0644]
drivers/net/nfp/nfp_nspu.c
drivers/net/nfp/nfp_nspu.h

diff --git a/drivers/net/nfp/nfp_net_eth.h b/drivers/net/nfp/nfp_net_eth.h
new file mode 100644 (file)
index 0000000..af57f03
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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_net_eth.h
+ *
+ * Netronome NFP_NET PDM driver
+ */
+
+union eth_table_entry {
+       struct {
+               uint64_t port;
+               uint64_t state;
+               uint8_t mac_addr[6];
+               uint8_t resv[2];
+               uint64_t control;
+       };
+       uint64_t raw[4];
+};
+
+#ifndef BIT_ULL
+#define BIT_ULL(a) (1ULL << (a))
+#endif
+
+#define NSP_ETH_NBI_PORT_COUNT          24
+#define NSP_ETH_MAX_COUNT               (2 * NSP_ETH_NBI_PORT_COUNT)
+#define NSP_ETH_TABLE_SIZE   (NSP_ETH_MAX_COUNT * sizeof(union eth_table_entry))
+
+#define NSP_ETH_PORT_LANES              0xf
+#define NSP_ETH_PORT_INDEX              0xff00
+#define NSP_ETH_PORT_LABEL              0x3f000000000000
+#define NSP_ETH_PORT_PHYLABEL           0xfc0000000000000
+
+#define NSP_ETH_PORT_LANES_MASK         rte_cpu_to_le_64(NSP_ETH_PORT_LANES)
+
+#define NSP_ETH_STATE_CONFIGURED        BIT_ULL(0)
+#define NSP_ETH_STATE_ENABLED           BIT_ULL(1)
+#define NSP_ETH_STATE_TX_ENABLED        BIT_ULL(2)
+#define NSP_ETH_STATE_RX_ENABLED        BIT_ULL(3)
+#define NSP_ETH_STATE_RATE              0xf00
+#define NSP_ETH_STATE_INTERFACE         0xff000
+#define NSP_ETH_STATE_MEDIA             0x300000
+#define NSP_ETH_STATE_OVRD_CHNG         BIT_ULL(22)
+#define NSP_ETH_STATE_ANEG              0x3800000
+
+#define NSP_ETH_CTRL_CONFIGURED         BIT_ULL(0)
+#define NSP_ETH_CTRL_ENABLED            BIT_ULL(1)
+#define NSP_ETH_CTRL_TX_ENABLED         BIT_ULL(2)
+#define NSP_ETH_CTRL_RX_ENABLED         BIT_ULL(3)
+#define NSP_ETH_CTRL_SET_RATE           BIT_ULL(4)
+#define NSP_ETH_CTRL_SET_LANES          BIT_ULL(5)
+#define NSP_ETH_CTRL_SET_ANEG           BIT_ULL(6)
index 56fd063..2f5632d 100644 (file)
@@ -8,8 +8,10 @@
 #include <fcntl.h>
 
 #include <rte_log.h>
+#include <rte_byteorder.h>
 
 #include "nfp_nfpu.h"
+#include "nfp_net_eth.h"
 
 #define CFG_EXP_BAR_ADDR_SZ     1
 #define CFG_EXP_BAR_MAP_TYPE   1
 #define NSP_STATUS_MINOR(x)      (int)(((x) >> 32) & 0xfff)
 
 /* NSP commands */
-#define NSP_CMD_RESET          1
-#define NSP_CMD_FW_LOAD        6
-#define NSP_CMD_GET_SYMBOL     14
+#define NSP_CMD_RESET                   1
+#define NSP_CMD_FW_LOAD                 6
+#define NSP_CMD_READ_ETH_TABLE          7
+#define NSP_CMD_WRITE_ETH_TABLE         8
+#define NSP_CMD_GET_SYMBOL             14
 
 #define NSP_BUFFER_CFG_SIZE_MASK       (0xff)
 
@@ -528,3 +532,72 @@ nfp_nsp_map_queues_bar(nspu_desc_t *desc, uint64_t *pcie_offset)
        /* This is the pcie offset to use by the host */
        *pcie_offset |= ((NFP_NET_PF_HW_QUEUES_EXP_BAR & 0x7) << (27 - 3));
 }
+
+int
+nfp_nsp_eth_config(nspu_desc_t *desc, int port, int up)
+{
+       union eth_table_entry *entries, *entry;
+       int modified;
+       int ret, idx;
+       int i;
+
+       idx = port;
+
+       RTE_LOG(INFO, PMD, "Hw ethernet port %d configure...\n", port);
+       rte_spinlock_lock(&desc->nsp_lock);
+       entries = malloc(NSP_ETH_TABLE_SIZE);
+       if (!entries) {
+               rte_spinlock_unlock(&desc->nsp_lock);
+               return -ENOMEM;
+       }
+
+       ret = nspu_command(desc, NSP_CMD_READ_ETH_TABLE, 1, 0, entries,
+                          NSP_ETH_TABLE_SIZE, 0);
+       if (ret) {
+               rte_spinlock_unlock(&desc->nsp_lock);
+               return ret;
+       }
+
+       entry = entries;
+
+       for (i = 0; i < NSP_ETH_MAX_COUNT; i++) {
+               /* ports in use do not appear sequentially in the table */
+               if (!(entry->port & NSP_ETH_PORT_LANES_MASK)) {
+                       /* entry not in use */
+                       entry++;
+                       continue;
+               }
+               if (idx == 0)
+                       break;
+               idx--;
+               entry++;
+       }
+
+       if (i == NSP_ETH_MAX_COUNT) {
+               rte_spinlock_unlock(&desc->nsp_lock);
+               return -EINVAL;
+       }
+
+       if (up && !(entry->state & NSP_ETH_STATE_CONFIGURED)) {
+               entry->control |= NSP_ETH_STATE_CONFIGURED;
+               modified = 1;
+       }
+
+       if (!up && (entry->state & NSP_ETH_STATE_CONFIGURED)) {
+               entry->control &= ~NSP_ETH_STATE_CONFIGURED;
+               modified = 1;
+       }
+
+       if (modified) {
+               ret = nspu_command(desc, NSP_CMD_WRITE_ETH_TABLE, 0, 1, entries,
+                                  0, NSP_ETH_TABLE_SIZE);
+               if (!ret)
+                       RTE_LOG(INFO, PMD,
+                               "Hw ethernet port %d configure done\n", port);
+               else
+                       RTE_LOG(INFO, PMD,
+                               "Hw ethernet port %d configure failed\n", port);
+       }
+       rte_spinlock_unlock(&desc->nsp_lock);
+       return ret;
+}
index 4b09d4f..4e58986 100644 (file)
@@ -57,6 +57,8 @@
  * the fast path.
  */
 
+#include <rte_spinlock.h>
+
 typedef struct {
        int nfp;        /* NFP device */
        int pcie_bar;   /* PF PCI BAR to work with */
@@ -67,6 +69,7 @@ typedef struct {
        uint64_t windowsz; /* NSPU BAR window size */
        void *cfg_base; /* Expansion BARs address */
        void *mem_base; /* NSP interface */
+       rte_spinlock_t nsp_lock;
 } nspu_desc_t;
 
 int nfp_nspu_init(nspu_desc_t *desc, int nfp, int pcie_bar, size_t pcie_barsz,
@@ -75,3 +78,4 @@ int nfp_nsp_get_abi_version(nspu_desc_t *desc, int *major, int *minor);
 int nfp_nsp_fw_setup(nspu_desc_t *desc, const char *sym, uint64_t *pcie_offset);
 int nfp_nsp_map_ctrl_bar(nspu_desc_t *desc, uint64_t *pcie_offset);
 void nfp_nsp_map_queues_bar(nspu_desc_t *desc, uint64_t *pcie_offset);
+int nfp_nsp_eth_config(nspu_desc_t *desc, int port, int up);