#include <fcntl.h>
#include <rte_log.h>
+#include <rte_byteorder.h>
#include "nfp_nfpu.h"
#define NFP_NSP_TARGET 7
/* Expansion BARs for mapping PF vnic BARs */
-#define NFP_NET_PF_CFG_EXP_BAR 6
+#define NFP_NET_PF_CFG_EXP_BAR 6
+#define NFP_NET_PF_HW_QUEUES_EXP_BAR 5
/*
* This is an NFP internal address used for configuring properly an NFP
#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)
return -ENOENT;
}
- fstat(fw_f, &file_stat);
+ if (fstat(fw_f, &file_stat) < 0) {
+ RTE_LOG(INFO, PMD, "Firmware file %s/%s size is unknown",
+ DEFAULT_FW_PATH, DEFAULT_FW_FILENAME);
+ close(fw_f);
+ return -ENOENT;
+ }
fsize = file_stat.st_size;
RTE_LOG(DEBUG, PMD, "Firmware file with size: %" PRIu64 "\n",
RTE_LOG(INFO, PMD, "fw file too big: %" PRIu64
" bytes (%" PRIu64 " max)",
(uint64_t)fsize, (uint64_t)size);
+ close(fw_f);
return -EINVAL;
}
fw_buf = malloc((size_t)size);
if (!fw_buf) {
RTE_LOG(INFO, PMD, "malloc failed for fw buffer");
+ close(fw_f);
return -ENOMEM;
}
memset(fw_buf, 0, size);
"Just %" PRIu64 " of %" PRIu64 " bytes read.",
(uint64_t)bytes, (uint64_t)fsize);
free(fw_buf);
+ close(fw_f);
return -EIO;
}
ret = nspu_command(nspu_desc, NSP_CMD_FW_LOAD, 0, 1, fw_buf, 0, bytes);
free(fw_buf);
+ close(fw_f);
return ret;
}
int ret = 0;
sym_buf = malloc(desc->buf_size);
+ if (!sym_buf)
+ return -ENOMEM;
+
strncpy(sym_buf, symbl, strlen(symbl));
ret = nspu_command(desc, NSP_CMD_GET_SYMBOL, 1, 1, sym_buf,
NFP_SYM_DESC_LEN, strlen(symbl));
return 0;
}
+
+/*
+ * This is a hardcoded fixed NFP internal CPP bus address for the hw queues unit
+ * inside the PCIE island.
+ */
+#define NFP_CPP_PCIE_QUEUES ((uint64_t)(1ULL << 39) | 0x80000 | \
+ ((uint64_t)0x4 & 0x3f) << 32)
+
+/* Configure a specific NFP expansion bar for accessing the vNIC rx/tx BARs */
+void
+nfp_nsp_map_queues_bar(nspu_desc_t *desc, uint64_t *pcie_offset)
+{
+ nfp_nspu_mem_bar_cfg(desc, NFP_NET_PF_HW_QUEUES_EXP_BAR, 0,
+ NFP_CPP_PCIE_QUEUES, 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);
+ free(entries);
+ 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);
+ free(entries);
+ 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);
+ free(entries);
+ return ret;
+}
+
+int
+nfp_nsp_eth_read_table(nspu_desc_t *desc, union eth_table_entry **table)
+{
+ int ret;
+
+ if (!table)
+ return -EINVAL;
+
+ RTE_LOG(INFO, PMD, "Reading hw ethernet table...\n");
+
+ /* port 0 allocates the eth table and read it using NSPU */
+ *table = malloc(NSP_ETH_TABLE_SIZE);
+ if (!*table)
+ return -ENOMEM;
+
+ ret = nspu_command(desc, NSP_CMD_READ_ETH_TABLE, 1, 0, *table,
+ NSP_ETH_TABLE_SIZE, 0);
+ if (ret)
+ return ret;
+
+ RTE_LOG(INFO, PMD, "Done\n");
+
+ return 0;
+}