From 48e2255f1b634ed02e01d400e83335f0fd999411 Mon Sep 17 00:00:00 2001 From: Alejandro Lucero Date: Fri, 1 Sep 2017 15:12:16 +0100 Subject: [PATCH] net/nfp: add NSP support for HW link configuration 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 --- drivers/net/nfp/nfp_net_eth.h | 82 +++++++++++++++++++++++++++++++++++ drivers/net/nfp/nfp_nspu.c | 79 +++++++++++++++++++++++++++++++-- drivers/net/nfp/nfp_nspu.h | 4 ++ 3 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 drivers/net/nfp/nfp_net_eth.h diff --git a/drivers/net/nfp/nfp_net_eth.h b/drivers/net/nfp/nfp_net_eth.h new file mode 100644 index 0000000000..af57f03c5e --- /dev/null +++ b/drivers/net/nfp/nfp_net_eth.h @@ -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) diff --git a/drivers/net/nfp/nfp_nspu.c b/drivers/net/nfp/nfp_nspu.c index 56fd063140..2f5632dfb1 100644 --- a/drivers/net/nfp/nfp_nspu.c +++ b/drivers/net/nfp/nfp_nspu.c @@ -8,8 +8,10 @@ #include #include +#include #include "nfp_nfpu.h" +#include "nfp_net_eth.h" #define CFG_EXP_BAR_ADDR_SZ 1 #define CFG_EXP_BAR_MAP_TYPE 1 @@ -45,9 +47,11 @@ #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; +} diff --git a/drivers/net/nfp/nfp_nspu.h b/drivers/net/nfp/nfp_nspu.h index 4b09d4fccb..4e58986833 100644 --- a/drivers/net/nfp/nfp_nspu.h +++ b/drivers/net/nfp/nfp_nspu.h @@ -57,6 +57,8 @@ * the fast path. */ +#include + 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); -- 2.20.1