Initialize LIFs (Logical Interfaces) which represents external connections. The NIC can multiplex many LIFs to a single port, but in most setups, LIF0 is the primary control for the port. Create a device for each LIF.
Signed-off-by: Alfredo Cardigliano <cardigli...@ntop.org> Reviewed-by: Shannon Nelson <snel...@pensando.io> --- drivers/net/ionic/Makefile | 2 + drivers/net/ionic/ionic.h | 5 + drivers/net/ionic/ionic_dev.c | 38 ++++++++++ drivers/net/ionic/ionic_dev.h | 8 ++ drivers/net/ionic/ionic_ethdev.c | 119 ++++++++++++++++++++++++++++++++ drivers/net/ionic/ionic_ethdev.h | 14 ++++ drivers/net/ionic/ionic_lif.c | 142 ++++++++++++++++++++++++++++++++++++++ drivers/net/ionic/ionic_lif.h | 49 +++++++++++++ drivers/net/ionic/meson.build | 4 + 9 files changed, 378 insertions(+), 3 deletions(-) create mode 100644 drivers/net/ionic/ionic_ethdev.h create mode 100644 drivers/net/ionic/ionic_lif.c create mode 100644 drivers/net/ionic/ionic_lif.h diff --git a/drivers/net/ionic/Makefile b/drivers/net/ionic/Makefile index 4d42e3778..a1378bdbe 100644 --- a/drivers/net/ionic/Makefile +++ b/drivers/net/ionic/Makefile @@ -37,6 +37,7 @@ ifeq ($(shell test $(GCC_VERSION) -ge 44 && echo 1), 1) CFLAGS += -Wno-deprecated -Wno-unused-parameter -Wno-unused-value CFLAGS += -Wno-strict-aliasing -Wno-format-extra-args CFLAGS += -Wno-missing-field-initializers -Wno-pointer-arith +CFLAGS += -Wno-deprecated-declarations endif ifeq ($(shell test $(GCC_VERSION) -ge 70 && echo 1), 1) @@ -55,6 +56,7 @@ LDLIBS += -lrte_bus_pci SRCS-$(CONFIG_RTE_LIBRTE_IONIC_PMD) += ionic_mac_api.c SRCS-$(CONFIG_RTE_LIBRTE_IONIC_PMD) += ionic_dev.c SRCS-$(CONFIG_RTE_LIBRTE_IONIC_PMD) += ionic_ethdev.c +SRCS-$(CONFIG_RTE_LIBRTE_IONIC_PMD) += ionic_lif.c SRCS-$(CONFIG_RTE_LIBRTE_IONIC_PMD) += ionic_main.c include $(RTE_SDK)/mk/rte.lib.mk diff --git a/drivers/net/ionic/ionic.h b/drivers/net/ionic/ionic.h index c15dc6b44..a30e1cf20 100644 --- a/drivers/net/ionic/ionic.h +++ b/drivers/net/ionic/ionic.h @@ -49,7 +49,12 @@ struct ionic_adapter { struct ionic_dev idev; struct ionic_dev_bar bars[IONIC_BARS_MAX]; struct ionic_identity ident; + struct ionic_lif *lifs[IONIC_LIFS_MAX]; uint32_t num_bars; + uint32_t nlifs; + uint32_t max_ntxqs_per_lif; + uint32_t max_nrxqs_per_lif; + uint32_t nintrs; bool is_mgmt_nic; struct rte_pci_device *pci_dev; LIST_ENTRY(ionic_adapter) pci_adapters; diff --git a/drivers/net/ionic/ionic_dev.c b/drivers/net/ionic/ionic_dev.c index 7a9890175..9d25c5e15 100644 --- a/drivers/net/ionic/ionic_dev.c +++ b/drivers/net/ionic/ionic_dev.c @@ -253,3 +253,41 @@ ionic_dev_cmd_port_loopback(struct ionic_dev *idev, uint8_t loopback_mode) ionic_dev_cmd_go(idev, &cmd); } + +/* LIF commands */ + +void +ionic_dev_cmd_lif_identify(struct ionic_dev *idev, uint8_t type, uint8_t ver) +{ + union ionic_dev_cmd cmd = { + .lif_identify.opcode = IONIC_CMD_LIF_IDENTIFY, + .lif_identify.type = type, + .lif_identify.ver = ver, + }; + + ionic_dev_cmd_go(idev, &cmd); +} + +void +ionic_dev_cmd_lif_init(struct ionic_dev *idev, uint16_t lif_index, + rte_iova_t info_pa) +{ + union ionic_dev_cmd cmd = { + .lif_init.opcode = IONIC_CMD_LIF_INIT, + .lif_init.index = lif_index, + .lif_init.info_pa = info_pa, + }; + + ionic_dev_cmd_go(idev, &cmd); +} + +void +ionic_dev_cmd_lif_reset(struct ionic_dev *idev, uint16_t lif_index) +{ + union ionic_dev_cmd cmd = { + .lif_init.opcode = IONIC_CMD_LIF_RESET, + .lif_init.index = lif_index, + }; + + ionic_dev_cmd_go(idev, &cmd); +} diff --git a/drivers/net/ionic/ionic_dev.h b/drivers/net/ionic/ionic_dev.h index aaa031980..9ab482c8a 100644 --- a/drivers/net/ionic/ionic_dev.h +++ b/drivers/net/ionic/ionic_dev.h @@ -20,6 +20,8 @@ */ #define IONIC_API_VERSION "3" +#define IONIC_LIFS_MAX 1024 + #define IONIC_DEVCMD_TIMEOUT 30 /* devcmd_timeout */ #define IONIC_ALIGN 4096 @@ -153,4 +155,10 @@ void ionic_dev_cmd_port_pause(struct ionic_dev *idev, uint8_t pause_type); void ionic_dev_cmd_port_loopback(struct ionic_dev *idev, uint8_t loopback_mode); +void ionic_dev_cmd_lif_identify(struct ionic_dev *idev, uint8_t type, + uint8_t ver); +void ionic_dev_cmd_lif_init(struct ionic_dev *idev, uint16_t lif_index, + rte_iova_t addr); +void ionic_dev_cmd_lif_reset(struct ionic_dev *idev, uint16_t lif_index); + #endif /* _IONIC_DEV_H_ */ diff --git a/drivers/net/ionic/ionic_ethdev.c b/drivers/net/ionic/ionic_ethdev.c index 61999bf1d..a0a788ab3 100644 --- a/drivers/net/ionic/ionic_ethdev.c +++ b/drivers/net/ionic/ionic_ethdev.c @@ -7,11 +7,17 @@ #include <rte_ethdev.h> #include <rte_ethdev_driver.h> #include <rte_malloc.h> +#include <rte_ethdev_pci.h> #include "ionic_logs.h" #include "ionic.h" #include "ionic_dev.h" #include "ionic_mac_api.h" +#include "ionic_lif.h" +#include "ionic_ethdev.h" + +static int eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params); +static int eth_ionic_dev_uninit(struct rte_eth_dev *eth_dev); int ionic_logtype_init; int ionic_logtype_driver; @@ -23,6 +29,9 @@ static const struct rte_pci_id pci_id_ionic_map[] = { { .vendor_id = 0, /* sentinel */ }, }; +static const struct eth_dev_ops ionic_eth_dev_ops = { +}; + /* * There is no room in struct rte_pci_driver to keep a reference * to the adapter, using a static list for the time being. @@ -31,10 +40,75 @@ static LIST_HEAD(ionic_pci_adapters_list, ionic_adapter) ionic_pci_adapters = LIST_HEAD_INITIALIZER(ionic_pci_adapters); static rte_spinlock_t ionic_pci_adapters_lock = RTE_SPINLOCK_INITIALIZER; +static int +eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params) +{ + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); + struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); + struct ionic_adapter *adapter = (struct ionic_adapter *)init_params; + int err; + + ionic_init_print_call(); + + eth_dev->dev_ops = &ionic_eth_dev_ops; + + /* Multi-process not supported, primary does initialization anyway */ + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return 0; + + rte_eth_copy_pci_info(eth_dev, pci_dev); + + lif->index = adapter->nlifs; + lif->eth_dev = eth_dev; + lif->adapter = adapter; + adapter->lifs[adapter->nlifs] = lif; + + err = ionic_lif_alloc(lif); + + if (err) { + ionic_init_print(ERR, "Cannot allocate LIFs: %d, aborting", + err); + return err; + } + + err = ionic_lif_init(lif); + + if (err) { + ionic_init_print(ERR, "Cannot init LIFs: %d, aborting", err); + return err; + } + + ionic_init_print(DEBUG, "Port %u initialized", eth_dev->data->port_id); + + return 0; +} + +static int +eth_ionic_dev_uninit(struct rte_eth_dev *eth_dev) +{ + struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); + struct ionic_adapter *adapter = lif->adapter; + + ionic_init_print_call(); + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return 0; + + adapter->lifs[lif->index] = NULL; + + ionic_lif_deinit(lif); + ionic_lif_free(lif); + + eth_dev->dev_ops = NULL; + + return 0; +} + static int eth_ionic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, struct rte_pci_device *pci_dev) { + char name[RTE_ETH_NAME_MAX_LEN]; struct rte_mem_resource *resource; struct ionic_adapter *adapter; struct ionic_hw *hw; @@ -119,6 +193,41 @@ eth_ionic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, return err; } + /* Configure LIFs */ + err = ionic_lif_identify(adapter); + + if (err) { + ionic_init_print(ERR, "Cannot identify lif: %d, aborting", err); + return err; + } + + /* Allocate and init LIFs */ + err = ionic_lifs_size(adapter); + + if (err) { + ionic_init_print(ERR, "Cannot size LIFs: %d, aborting", err); + return err; + } + + adapter->nlifs = 0; + for (i = 0; i < adapter->ident.dev.nlifs; i++) { + snprintf(name, sizeof(name), "net_%s_lif_%lu", + pci_dev->device.name, i); + + err = rte_eth_dev_create(&pci_dev->device, name, + sizeof(struct ionic_lif), + NULL, NULL, + eth_ionic_dev_init, adapter); + + if (err) { + ionic_init_print(ERR, "Cannot create eth device for " + "ionic lif %s", name); + break; + } + + adapter->nlifs++; + } + rte_spinlock_lock(&ionic_pci_adapters_lock); LIST_INSERT_HEAD(&ionic_pci_adapters, adapter, pci_adapters); rte_spinlock_unlock(&ionic_pci_adapters_lock); @@ -130,6 +239,8 @@ static int eth_ionic_pci_remove(struct rte_pci_device *pci_dev) { struct ionic_adapter *adapter = NULL; + struct ionic_lif *lif; + uint32_t i; rte_spinlock_lock(&ionic_pci_adapters_lock); LIST_FOREACH(adapter, &ionic_pci_adapters, pci_adapters) { @@ -142,8 +253,14 @@ eth_ionic_pci_remove(struct rte_pci_device *pci_dev) LIST_REMOVE(adapter, pci_adapters); rte_spinlock_unlock(&ionic_pci_adapters_lock); - if (adapter) + if (adapter) { + for (i = 0; i < adapter->nlifs; i++) { + lif = adapter->lifs[i]; + rte_eth_dev_destroy(lif->eth_dev, eth_ionic_dev_uninit); + } + rte_free(adapter); + } return 0; } diff --git a/drivers/net/ionic/ionic_ethdev.h b/drivers/net/ionic/ionic_ethdev.h new file mode 100644 index 000000000..9f1c0320d --- /dev/null +++ b/drivers/net/ionic/ionic_ethdev.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 + * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. + */ + +#ifndef _IONIC_ETHDEV_H_ +#define _IONIC_ETHDEV_H_ + +#define IONIC_ETH_DEV_TO_LIF(eth_dev) ((struct ionic_lif *) \ + eth_dev->data->dev_private) +#define IONIC_ETH_DEV_TO_ADAPTER(eth_dev) \ + (IONIC_ETH_DEV_TO_LIF(eth_dev)->adapter) + +#endif /* _IONIC_ETHDEV_H_ */ + diff --git a/drivers/net/ionic/ionic_lif.c b/drivers/net/ionic/ionic_lif.c new file mode 100644 index 000000000..c67619d85 --- /dev/null +++ b/drivers/net/ionic/ionic_lif.c @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: GPL-2.0 + * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. + */ + +#include <rte_malloc.h> +#include <rte_ethdev_driver.h> + +#include "ionic.h" +#include "ionic_logs.h" +#include "ionic_lif.h" +#include "ionic_ethdev.h" + +int +ionic_lif_alloc(struct ionic_lif *lif) +{ + uint32_t socket_id = rte_socket_id(); + + snprintf(lif->name, sizeof(lif->name), "lif%u", lif->index); + + ionic_init_print(DEBUG, "Allocating Lif Info"); + + lif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE); + + lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev, + "lif_info", 0 /* queue_idx*/, + lif->info_sz, IONIC_ALIGN, socket_id); + + if (!lif->info_z) { + ionic_init_print(ERR, "Cannot allocate lif info memory"); + return -ENOMEM; + } + + lif->info = lif->info_z->addr; + lif->info_pa = lif->info_z->iova; + + return 0; +} + +void +ionic_lif_free(struct ionic_lif *lif) +{ + if (lif->info) + rte_memzone_free(lif->info_z); +} + +int +ionic_lif_init(struct ionic_lif *lif) +{ + struct ionic_dev *idev = &lif->adapter->idev; + struct ionic_q_init_comp comp; + int err; + + ionic_dev_cmd_lif_init(idev, lif->index, lif->info_pa); + err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); + ionic_dev_cmd_comp(idev, &comp); + if (err) + return err; + + lif->hw_index = comp.hw_index; + + lif->state |= IONIC_LIF_F_INITED; + + return 0; +} + +void +ionic_lif_deinit(struct ionic_lif *lif) +{ + if (!(lif->state & IONIC_LIF_F_INITED)) + return; + + lif->state &= ~IONIC_LIF_F_INITED; +} + +int +ionic_lif_identify(struct ionic_adapter *adapter) +{ + struct ionic_dev *idev = &adapter->idev; + struct ionic_identity *ident = &adapter->ident; + int err; + unsigned int i; + unsigned int lif_words = sizeof(ident->lif.words) / + sizeof(ident->lif.words[0]); + unsigned int cmd_words = sizeof(idev->dev_cmd->data) / + sizeof(idev->dev_cmd->data[0]); + unsigned int nwords; + + ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC, + IONIC_IDENTITY_VERSION_1); + err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); + if (err) + return (err); + + nwords = RTE_MIN(lif_words, cmd_words); + for (i = 0; i < nwords; i++) + ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]); + + ionic_init_print(INFO, "capabilities 0x%lx ", ident->lif.capabilities); + + ionic_init_print(INFO, "eth.max_ucast_filters 0x%x ", + ident->lif.eth.max_ucast_filters); + ionic_init_print(INFO, "eth.max_mcast_filters 0x%x ", + ident->lif.eth.max_mcast_filters); + + ionic_init_print(INFO, "eth.features 0x%lx ", + ident->lif.eth.config.features); + ionic_init_print(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%x ", + ident->lif.eth.config.queue_count[IONIC_QTYPE_ADMINQ]); + ionic_init_print(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%x ", + ident->lif.eth.config.queue_count[IONIC_QTYPE_NOTIFYQ]); + ionic_init_print(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%x ", + ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]); + ionic_init_print(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%x ", + ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]); + + return 0; +} + +int +ionic_lifs_size(struct ionic_adapter *adapter) +{ + struct ionic_identity *ident = &adapter->ident; + uint32_t nlifs = ident->dev.nlifs; + uint32_t nintrs, dev_nintrs = ident->dev.nintrs; + + adapter->max_ntxqs_per_lif = + ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]; + adapter->max_nrxqs_per_lif = + ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]; + + nintrs = nlifs * 1 /* notifyq */; + + if (nintrs > dev_nintrs) { + ionic_init_print(ERR, "At most %d intr queues supported, minimum required is %u", + dev_nintrs, nintrs); + return -ENOSPC; + } + + adapter->nintrs = nintrs; + + return 0; +} diff --git a/drivers/net/ionic/ionic_lif.h b/drivers/net/ionic/ionic_lif.h new file mode 100644 index 000000000..374cebd05 --- /dev/null +++ b/drivers/net/ionic/ionic_lif.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 + * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. + */ + +#ifndef _IONIC_LIF_H_ +#define _IONIC_LIF_H_ + +#include <inttypes.h> + +#include <rte_ethdev.h> +#include <rte_ether.h> + +#include "ionic_osdep.h" +#include "ionic_dev.h" + +#define IONIC_LIF_F_INITED BIT(0) + +#define IONIC_LIF_NAME_MAX_SZ (32) + +struct ionic_lif { + struct ionic_adapter *adapter; + struct rte_eth_dev *eth_dev; + uint16_t port_id; /**< Device port identifier */ + uint32_t index; + uint32_t hw_index; + char name[IONIC_LIF_NAME_MAX_SZ]; + uint32_t state; + uint32_t info_sz; + struct ionic_lif_info *info; + rte_iova_t info_pa; + const struct rte_memzone *info_z; +}; + +int ionic_lif_identify(struct ionic_adapter *adapter); +int ionic_lifs_size(struct ionic_adapter *ionic); + +int ionic_lif_alloc(struct ionic_lif *lif); +void ionic_lif_free(struct ionic_lif *lif); + +int ionic_lif_init(struct ionic_lif *lif); +void ionic_lif_deinit(struct ionic_lif *lif); + +int ionic_lif_start(struct ionic_lif *lif); +int ionic_lif_stop(struct ionic_lif *lif); + +int ionic_lif_configure(struct ionic_lif *lif); +void ionic_lif_reset(struct ionic_lif *lif); + +#endif /* _IONIC_LIF_H_ */ diff --git a/drivers/net/ionic/meson.build b/drivers/net/ionic/meson.build index bd63e6136..0cf5a0cc7 100644 --- a/drivers/net/ionic/meson.build +++ b/drivers/net/ionic/meson.build @@ -7,7 +7,7 @@ sources = files( 'ionic_mac_api.c', 'ionic_dev.c', 'ionic_ethdev.c', - 'ionic_main.c', - 'ionic_ethdev.c' + 'ionic_lif.c', + 'ionic_main.c' )