From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id CCDB8A2EFC for ; Tue, 15 Oct 2019 10:23:40 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 0167C1E540; Tue, 15 Oct 2019 10:23:05 +0200 (CEST) Received: from mail.ntop.org (mail-digitalocean.ntop.org [167.99.215.164]) by dpdk.org (Postfix) with ESMTP id 3E6941DFE3 for ; Tue, 15 Oct 2019 10:22:46 +0200 (CEST) Received: from devele.ntop.org (net-93-145-196-230.cust.vodafonedsl.it [93.145.196.230]) by mail.ntop.org (Postfix) with ESMTPSA id E098241C16; Tue, 15 Oct 2019 10:22:45 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ntop.org; s=mail; t=1571127766; bh=nicK6+7BUxeFnGbPtF8tPvE0Am23+cINFVF7w2SYBZk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=P1BokF4u3rkAix0wLh/mY/wAF39ZuTbZtN15xrNjqXIEX59NAriuaPbLrl/GnuyYe qI87WBVC/InurwiVs2AjMdbUkBmuRaXfhQGeKoVp9XzxUDow+/XYZqzHGYDFNYZXMZ Bbaxyqx84WO04DvvJyr/KFG6U0sivu/5+RpdW4wk= From: Alfredo Cardigliano To: Alfredo Cardigliano , Anatoly Burakov Cc: dev@dpdk.org Date: Tue, 15 Oct 2019 10:22:24 +0200 Message-Id: <20191015082235.28639-7-cardigliano@ntop.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191015082235.28639-1-cardigliano@ntop.org> References: <20191015082235.28639-1-cardigliano@ntop.org> Subject: [dpdk-dev] [PATCH v2 06/17] net/ionic: add basic lif support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" 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 Reviewed-by: Shannon Nelson --- drivers/net/ionic/Makefile | 1 + 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, 377 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 69fb7dcf1..8c402b17b 100644 --- a/drivers/net/ionic/Makefile +++ b/drivers/net/ionic/Makefile @@ -56,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 #include #include +#include #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..6f078c111 --- /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 +#include + +#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 + +#include +#include + +#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' ) -- 2.17.1