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 3E208A2EFC for ; Tue, 15 Oct 2019 10:23:19 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id D58741E4EB; Tue, 15 Oct 2019 10:22:58 +0200 (CEST) Received: from mail.ntop.org (mail-digitalocean.ntop.org [167.99.215.164]) by dpdk.org (Postfix) with ESMTP id 5A1AA1DFE5 for ; Tue, 15 Oct 2019 10:22:45 +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 E5D7A41C17; Tue, 15 Oct 2019 10:22:44 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ntop.org; s=mail; t=1571127765; bh=KAC8rHeSV/DKGUBn9m5Eo/V5LbDrlWcxLDpb0BY2O6A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lvsnpQ9AjSHAQ0KXTfdvxqixyZDLcsi/qVT5rp7ooPjZjaCUioz6in7ck7ZZjp9p6 hfrBf4IwHTRMX++wMccISYFV6yuhuf2jDDCx7rcebnz9MLuNkz0gh9ngz89E6vJ6KB TXL+RuZTyftzSfIlFXh1iQjJuv+J90Gc6z3oEwEk= From: Alfredo Cardigliano To: Alfredo Cardigliano , John McNamara , Marko Kovacevic , Anatoly Burakov Cc: dev@dpdk.org Date: Tue, 15 Oct 2019 10:22:22 +0200 Message-Id: <20191015082235.28639-5-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 04/17] net/ionic: register and initialize the adapter 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" Register the Pensando ionic PMD (net_ionic) and define initial probe and remove callbacks with adapter initialization. Signed-off-by: Alfredo Cardigliano Reviewed-by: Shannon Nelson --- doc/guides/nics/features/ionic.ini | 2 + drivers/net/ionic/Makefile | 3 + drivers/net/ionic/ionic.h | 63 +++++++++++++ drivers/net/ionic/ionic_dev.c | 128 ++++++++++++++++++++++++++ drivers/net/ionic/ionic_dev.h | 138 ++++++++++++++++++++++++++++ drivers/net/ionic/ionic_ethdev.c | 138 ++++++++++++++++++++++++++++ drivers/net/ionic/ionic_mac_api.c | 61 +++++++++++++ drivers/net/ionic/ionic_mac_api.h | 13 +++ drivers/net/ionic/ionic_main.c | 133 +++++++++++++++++++++++++++ drivers/net/ionic/ionic_osdep.h | 79 ++++++++++++++++ drivers/net/ionic/ionic_regs.h | 142 +++++++++++++++++++++++++++++ drivers/net/ionic/meson.build | 4 + 12 files changed, 904 insertions(+) create mode 100644 drivers/net/ionic/ionic.h create mode 100644 drivers/net/ionic/ionic_dev.c create mode 100644 drivers/net/ionic/ionic_dev.h create mode 100644 drivers/net/ionic/ionic_mac_api.c create mode 100644 drivers/net/ionic/ionic_mac_api.h create mode 100644 drivers/net/ionic/ionic_main.c create mode 100644 drivers/net/ionic/ionic_osdep.h create mode 100644 drivers/net/ionic/ionic_regs.h diff --git a/doc/guides/nics/features/ionic.ini b/doc/guides/nics/features/ionic.ini index 3a92eedc7..6915d9c42 100644 --- a/doc/guides/nics/features/ionic.ini +++ b/doc/guides/nics/features/ionic.ini @@ -4,5 +4,7 @@ ; Refer to default.ini for the full list of available PMD features. ; [Features] +Linux UIO = Y +Linux VFIO = Y x86-64 = Y Usage doc = Y diff --git a/drivers/net/ionic/Makefile b/drivers/net/ionic/Makefile index f9b9a6af9..69fb7dcf1 100644 --- a/drivers/net/ionic/Makefile +++ b/drivers/net/ionic/Makefile @@ -53,6 +53,9 @@ LDLIBS += -lrte_bus_pci # # all source are stored in SRCS-y # +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_main.c include $(RTE_SDK)/mk/rte.lib.mk diff --git a/drivers/net/ionic/ionic.h b/drivers/net/ionic/ionic.h new file mode 100644 index 000000000..1f91e0a10 --- /dev/null +++ b/drivers/net/ionic/ionic.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0 + * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. + */ + +#ifndef _IONIC_H_ +#define _IONIC_H_ + +#include + +#include "ionic_dev.h" +#include "ionic_if.h" +#include "ionic_osdep.h" + +#define IONIC_DRV_NAME "ionic" +#define IONIC_DRV_DESCRIPTION "Pensando Ethernet NIC Driver" +#define IONIC_DRV_VERSION "0.11.0-49" + +/* Vendor ID */ +#define IONIC_PENSANDO_VENDOR_ID 0x1dd8 + +/* Device IDs */ +#define IONIC_DEV_ID_ETH_PF 0x1002 +#define IONIC_DEV_ID_ETH_VF 0x1003 +#define IONIC_DEV_ID_ETH_MGMT 0x1004 + +enum ionic_mac_type { + IONIC_MAC_UNKNOWN = 0, + IONIC_MAC_CAPRI, + IONIC_NUM_MACS +}; + +struct ionic_mac_info { + enum ionic_mac_type type; +}; + +struct ionic_hw { + struct ionic_mac_info mac; + uint16_t device_id; + uint16_t vendor_id; +}; + +/* + * Structure to store private data for each driver instance (for each adapter). + */ +struct ionic_adapter { + struct ionic_hw hw; + struct ionic_dev idev; + struct ionic_dev_bar bars[IONIC_BARS_MAX]; + struct ionic_identity ident; + uint32_t num_bars; + bool is_mgmt_nic; + struct rte_pci_device *pci_dev; + LIST_ENTRY(ionic_adapter) pci_adapters; +}; + +int ionic_dev_cmd_wait_check(struct ionic_dev *idev, unsigned long max_wait); +int ionic_setup(struct ionic_adapter *adapter); + +int ionic_identify(struct ionic_adapter *adapter); +int ionic_init(struct ionic_adapter *adapter); +int ionic_reset(struct ionic_adapter *adapter); + +#endif /* _IONIC_H_ */ diff --git a/drivers/net/ionic/ionic_dev.c b/drivers/net/ionic/ionic_dev.c new file mode 100644 index 000000000..5cdcaa104 --- /dev/null +++ b/drivers/net/ionic/ionic_dev.c @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: GPL-2.0 + * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. + */ + +#include + +#include "ionic_dev.h" +#include "ionic.h" + +int +ionic_dev_setup(struct ionic_adapter *adapter) +{ + struct ionic_dev_bar *bar = adapter->bars; + unsigned int num_bars = adapter->num_bars; + struct ionic_dev *idev = &adapter->idev; + uint32_t sig; + + /* BAR0: dev_cmd and interrupts */ + if (num_bars < 1) { + ionic_init_print(ERR, "No bars found, aborting\n"); + return -EFAULT; + } + + if (bar->len < IONIC_BAR0_SIZE) { + ionic_init_print(ERR, + "Resource bar size %lu too small, aborting\n", + bar->len); + return -EFAULT; + } + + idev->dev_info = bar->vaddr + IONIC_BAR0_DEV_INFO_REGS_OFFSET; + idev->dev_cmd = bar->vaddr + IONIC_BAR0_DEV_CMD_REGS_OFFSET; + idev->intr_status = bar->vaddr + IONIC_BAR0_INTR_STATUS_OFFSET; + idev->intr_ctrl = bar->vaddr + IONIC_BAR0_INTR_CTRL_OFFSET; + + sig = ioread32(&idev->dev_info->signature); + if (sig != IONIC_DEV_INFO_SIGNATURE) { + ionic_init_print(ERR, "Incompatible firmware signature %x", + sig); + return -EFAULT; + } + + /* BAR1: doorbells */ + bar++; + if (num_bars < 2) { + ionic_init_print(ERR, "Doorbell bar missing, aborting\n"); + return -EFAULT; + } + + idev->db_pages = bar->vaddr; + idev->phy_db_pages = bar->bus_addr; + + return 0; +} + +/* Devcmd Interface */ + +uint8_t +ionic_dev_cmd_status(struct ionic_dev *idev) +{ + return ioread8(&idev->dev_cmd->comp.comp.status); +} + +bool +ionic_dev_cmd_done(struct ionic_dev *idev) +{ + return ioread32(&idev->dev_cmd->done) & IONIC_DEV_CMD_DONE; +} + +void +ionic_dev_cmd_comp(struct ionic_dev *idev, void *mem) +{ + union ionic_dev_cmd_comp *comp = mem; + unsigned int i; + uint32_t comp_size = sizeof(comp->words) / + sizeof(comp->words[0]); + + for (i = 0; i < comp_size; i++) + comp->words[i] = ioread32(&idev->dev_cmd->comp.words[i]); +} + +void +ionic_dev_cmd_go(struct ionic_dev *idev, union ionic_dev_cmd *cmd) +{ + unsigned int i; + uint32_t cmd_size = sizeof(cmd->words) / + sizeof(cmd->words[0]); + + for (i = 0; i < cmd_size; i++) + iowrite32(cmd->words[i], &idev->dev_cmd->cmd.words[i]); + + iowrite32(0, &idev->dev_cmd->done); + iowrite32(1, &idev->dev_cmd->doorbell); +} + +/* Device commands */ + +void +ionic_dev_cmd_identify(struct ionic_dev *idev, uint8_t ver) +{ + union ionic_dev_cmd cmd = { + .identify.opcode = IONIC_CMD_IDENTIFY, + .identify.ver = ver, + }; + + ionic_dev_cmd_go(idev, &cmd); +} + +void +ionic_dev_cmd_init(struct ionic_dev *idev) +{ + union ionic_dev_cmd cmd = { + .init.opcode = IONIC_CMD_INIT, + .init.type = 0, + }; + + ionic_dev_cmd_go(idev, &cmd); +} + +void +ionic_dev_cmd_reset(struct ionic_dev *idev) +{ + union ionic_dev_cmd cmd = { + .reset.opcode = IONIC_CMD_RESET, + }; + + ionic_dev_cmd_go(idev, &cmd); +} diff --git a/drivers/net/ionic/ionic_dev.h b/drivers/net/ionic/ionic_dev.h new file mode 100644 index 000000000..a157e4175 --- /dev/null +++ b/drivers/net/ionic/ionic_dev.h @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: GPL-2.0 + * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. + */ + +#ifndef _IONIC_DEV_H_ +#define _IONIC_DEV_H_ + +#include "ionic_osdep.h" +#include "ionic_if.h" +#include "ionic_regs.h" + +/** IONIC_API_VERSION - Version number of this interface. + * + * Any interface changes to this interface must also change the version. + * + * If drivers are compiled from different sources, + * they are compatible only if IONIC_API_VERSION is statically the same in both + * sources. Drivers must have matching values of IONIC_API_VERSION at compile + * time, to be considered compatible at run time. + */ +#define IONIC_API_VERSION "3" + +#define IONIC_DEVCMD_TIMEOUT 30 /* devcmd_timeout */ + +struct ionic_adapter; + +struct ionic_dev_bar { + void __iomem *vaddr; + rte_iova_t bus_addr; + unsigned long len; +}; + +static inline void ionic_struct_size_checks(void) +{ + RTE_BUILD_BUG_ON(sizeof(struct ionic_doorbell) != 8); + RTE_BUILD_BUG_ON(sizeof(struct ionic_intr) != 32); + RTE_BUILD_BUG_ON(sizeof(struct ionic_intr_status) != 8); + + RTE_BUILD_BUG_ON(sizeof(union ionic_dev_regs) != 4096); + RTE_BUILD_BUG_ON(sizeof(union ionic_dev_info_regs) != 2048); + RTE_BUILD_BUG_ON(sizeof(union ionic_dev_cmd_regs) != 2048); + + RTE_BUILD_BUG_ON(sizeof(struct ionic_lif_stats) != 1024); + + RTE_BUILD_BUG_ON(sizeof(struct ionic_admin_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_admin_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct ionic_nop_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_nop_comp) != 16); + + /* Device commands */ + RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_identify_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_identify_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_init_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_init_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_reset_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_reset_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_getattr_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_getattr_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_setattr_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_setattr_comp) != 16); + + /* Port commands */ + RTE_BUILD_BUG_ON(sizeof(struct ionic_port_identify_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_port_identify_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct ionic_port_init_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_port_init_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct ionic_port_reset_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_port_reset_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct ionic_port_getattr_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_port_getattr_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct ionic_port_setattr_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_port_setattr_comp) != 16); + + /* LIF commands */ + RTE_BUILD_BUG_ON(sizeof(struct ionic_lif_init_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_lif_init_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct ionic_lif_reset_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_lif_getattr_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_lif_getattr_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct ionic_lif_setattr_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_lif_setattr_comp) != 16); + + RTE_BUILD_BUG_ON(sizeof(struct ionic_q_init_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_q_init_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct ionic_q_control_cmd) != 64); + + RTE_BUILD_BUG_ON(sizeof(struct ionic_rx_mode_set_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_rx_filter_add_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_rx_filter_add_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct ionic_rx_filter_del_cmd) != 64); + + /* RDMA commands */ + RTE_BUILD_BUG_ON(sizeof(struct ionic_rdma_reset_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_rdma_queue_cmd) != 64); + + /* Events */ + RTE_BUILD_BUG_ON(sizeof(struct ionic_notifyq_cmd) != 4); + RTE_BUILD_BUG_ON(sizeof(union ionic_notifyq_comp) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_notifyq_event) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_link_change_event) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_reset_event) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_heartbeat_event) != 64); + RTE_BUILD_BUG_ON(sizeof(struct ionic_log_event) != 64); + + /* I/O */ + RTE_BUILD_BUG_ON(sizeof(struct ionic_txq_desc) != 16); + RTE_BUILD_BUG_ON(sizeof(struct ionic_txq_sg_desc) != 128); + RTE_BUILD_BUG_ON(sizeof(struct ionic_txq_comp) != 16); + + RTE_BUILD_BUG_ON(sizeof(struct ionic_rxq_desc) != 16); + RTE_BUILD_BUG_ON(sizeof(struct ionic_rxq_sg_desc) != 128); + RTE_BUILD_BUG_ON(sizeof(struct ionic_rxq_comp) != 16); +} + +struct ionic_dev { + union ionic_dev_info_regs __iomem *dev_info; + union ionic_dev_cmd_regs __iomem *dev_cmd; + + struct ionic_doorbell __iomem *db_pages; + rte_iova_t phy_db_pages; + + struct ionic_intr __iomem *intr_ctrl; + + struct ionic_intr_status __iomem *intr_status; +}; + +int ionic_dev_setup(struct ionic_adapter *adapter); + +void ionic_dev_cmd_go(struct ionic_dev *idev, union ionic_dev_cmd *cmd); +uint8_t ionic_dev_cmd_status(struct ionic_dev *idev); +bool ionic_dev_cmd_done(struct ionic_dev *idev); +void ionic_dev_cmd_comp(struct ionic_dev *idev, void *mem); + +void ionic_dev_cmd_identify(struct ionic_dev *idev, uint8_t ver); +void ionic_dev_cmd_init(struct ionic_dev *idev); +void ionic_dev_cmd_reset(struct ionic_dev *idev); + +#endif /* _IONIC_DEV_H_ */ diff --git a/drivers/net/ionic/ionic_ethdev.c b/drivers/net/ionic/ionic_ethdev.c index 863d20d19..148d6f236 100644 --- a/drivers/net/ionic/ionic_ethdev.c +++ b/drivers/net/ionic/ionic_ethdev.c @@ -2,11 +2,147 @@ * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. */ +#include +#include +#include +#include +#include + #include "ionic_logs.h" +#include "ionic.h" +#include "ionic_dev.h" +#include "ionic_mac_api.h" int ionic_logtype_init; int ionic_logtype_driver; +static const struct rte_pci_id pci_id_ionic_map[] = { + { RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_PF) }, + { RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_VF) }, + { RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_MGMT) }, + { .vendor_id = 0, /* sentinel */ }, +}; + +/* + * There is no room in struct rte_pci_driver to keep a reference + * to the adapter, using a static list for the time being. + */ +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_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, + struct rte_pci_device *pci_dev) +{ + struct rte_mem_resource *resource; + struct ionic_adapter *adapter; + struct ionic_hw *hw; + unsigned long i; + int err; + + /* Multi-process not supported */ + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return -EPERM; + + ionic_init_print(DEBUG, "Initializing device %s %s", + pci_dev->device.name, + rte_eal_process_type() == RTE_PROC_SECONDARY ? + "[SECONDARY]" : ""); + + adapter = rte_zmalloc("ionic", sizeof(*adapter), 0); + + if (!adapter) { + ionic_init_print(ERR, "OOM"); + return -ENOMEM; + } + + adapter->pci_dev = pci_dev; + hw = &adapter->hw; + + hw->device_id = pci_dev->id.device_id; + hw->vendor_id = pci_dev->id.vendor_id; + + err = ionic_init_mac(hw); + if (err != 0) { + ionic_init_print(ERR, "Mac init failed: %d", err); + return -EIO; + } + + adapter->is_mgmt_nic = (pci_dev->id.device_id == IONIC_DEV_ID_ETH_MGMT); + + adapter->num_bars = 0; + for (i = 0; i < PCI_MAX_RESOURCE && i < IONIC_BARS_MAX; i++) { + resource = &pci_dev->mem_resource[i]; + if (resource->phys_addr == 0 || resource->len == 0) + continue; + adapter->bars[adapter->num_bars].vaddr = resource->addr; + adapter->bars[adapter->num_bars].bus_addr = resource->phys_addr; + adapter->bars[adapter->num_bars].len = resource->len; + adapter->num_bars++; + } + + /* Discover ionic dev resources */ + + err = ionic_setup(adapter); + if (err) { + ionic_init_print(ERR, "Cannot setup device: %d, aborting", err); + return err; + } + + err = ionic_identify(adapter); + if (err) { + ionic_init_print(ERR, "Cannot identify device: %d, aborting", + err); + return err; + } + + err = ionic_init(adapter); + if (err) { + ionic_init_print(ERR, "Cannot init device: %d, aborting", err); + return err; + } + + rte_spinlock_lock(&ionic_pci_adapters_lock); + LIST_INSERT_HEAD(&ionic_pci_adapters, adapter, pci_adapters); + rte_spinlock_unlock(&ionic_pci_adapters_lock); + + return 0; +} + +static int +eth_ionic_pci_remove(struct rte_pci_device *pci_dev) +{ + struct ionic_adapter *adapter = NULL; + + rte_spinlock_lock(&ionic_pci_adapters_lock); + LIST_FOREACH(adapter, &ionic_pci_adapters, pci_adapters) { + if (adapter->pci_dev == pci_dev) + break; + + adapter = NULL; + } + if (adapter) + LIST_REMOVE(adapter, pci_adapters); + rte_spinlock_unlock(&ionic_pci_adapters_lock); + + if (adapter) + rte_free(adapter); + + return 0; +} + +static struct rte_pci_driver rte_ionic_pmd = { + .id_table = pci_id_ionic_map, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, + .probe = eth_ionic_pci_probe, + .remove = eth_ionic_pci_remove, +}; + +RTE_PMD_REGISTER_PCI(net_ionic, rte_ionic_pmd); +RTE_PMD_REGISTER_PCI_TABLE(net_ionic, pci_id_ionic_map); +RTE_PMD_REGISTER_KMOD_DEP(net_ionic, "* igb_uio | uio_pci_generic | vfio-pci"); + RTE_INIT(ionic_init_log) { ionic_logtype_init = rte_log_register("pmd.net.ionic.init"); @@ -14,6 +150,8 @@ RTE_INIT(ionic_init_log) if (ionic_logtype_init >= 0) rte_log_set_level(ionic_logtype_init, RTE_LOG_NOTICE); + ionic_struct_size_checks(); + ionic_logtype_driver = rte_log_register("pmd.net.ionic.driver"); if (ionic_logtype_driver >= 0) diff --git a/drivers/net/ionic/ionic_mac_api.c b/drivers/net/ionic/ionic_mac_api.c new file mode 100644 index 000000000..5413afa93 --- /dev/null +++ b/drivers/net/ionic/ionic_mac_api.c @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0 + * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. + */ + +#include "ionic_mac_api.h" + +int32_t +ionic_init_mac(struct ionic_hw *hw) +{ + int err = 0; + + ionic_drv_print_call(); + + /* + * Set the mac type + */ + ionic_set_mac_type(hw); + + switch (hw->mac.type) { + case IONIC_MAC_CAPRI: + break; + default: + err = -EINVAL; + break; + } + + return err; +} + +int32_t +ionic_set_mac_type(struct ionic_hw *hw) +{ + int err = 0; + + ionic_drv_print_call(); + + if (hw->vendor_id != IONIC_PENSANDO_VENDOR_ID) { + ionic_drv_print(ERR, "Unsupported vendor id: %x", + hw->vendor_id); + return -EINVAL; + } + + switch (hw->device_id) { + case IONIC_DEV_ID_ETH_PF: + case IONIC_DEV_ID_ETH_VF: + case IONIC_DEV_ID_ETH_MGMT: + hw->mac.type = IONIC_MAC_CAPRI; + break; + default: + err = -EINVAL; + ionic_drv_print(ERR, "Unsupported device id: %x", + hw->device_id); + break; + } + + ionic_drv_print(INFO, "Mac: %d (%d)\n", + hw->mac.type, err); + + return err; +} + diff --git a/drivers/net/ionic/ionic_mac_api.h b/drivers/net/ionic/ionic_mac_api.h new file mode 100644 index 000000000..41f9328f3 --- /dev/null +++ b/drivers/net/ionic/ionic_mac_api.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 + * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. + */ + +#ifndef _IONIC_API_H_ +#define _IONIC_API_H_ + +#include "ionic.h" + +int32_t ionic_init_mac(struct ionic_hw *hw); +int32_t ionic_set_mac_type(struct ionic_hw *hw); + +#endif /* _IONIC_API_H_ */ diff --git a/drivers/net/ionic/ionic_main.c b/drivers/net/ionic/ionic_main.c new file mode 100644 index 000000000..79a141140 --- /dev/null +++ b/drivers/net/ionic/ionic_main.c @@ -0,0 +1,133 @@ +/* SPDX-License-Identifier: GPL-2.0 + * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. + */ + +#include "ionic.h" + +static int +ionic_dev_cmd_wait(struct ionic_dev *idev, unsigned long max_wait) +{ + unsigned long step_msec = 100; + unsigned int max_wait_msec = max_wait * 1000; + unsigned long elapsed_msec = 0; + int done; + + /* Wait for dev cmd to complete.. but no more than max_wait sec */ + + do { + done = ionic_dev_cmd_done(idev); + + if (done) { + ionic_drv_print(DEBUG, "DEVCMD %d done took %ld msecs\n", + idev->dev_cmd->cmd.cmd.opcode, + elapsed_msec); + return 0; + } + + msec_delay(step_msec); + + elapsed_msec += step_msec; + } while (elapsed_msec < max_wait_msec); + + ionic_drv_print(DEBUG, "DEVCMD %d timeout after %ld msecs\n", + idev->dev_cmd->cmd.cmd.opcode, + elapsed_msec); + + return -ETIMEDOUT; +} + +static int +ionic_dev_cmd_check_error(struct ionic_dev *idev) +{ + uint8_t status; + + status = ionic_dev_cmd_status(idev); + + if (status == 0) + return 0; + + return -EIO; +} + +int +ionic_dev_cmd_wait_check(struct ionic_dev *idev, unsigned long max_wait) +{ + int err; + + err = ionic_dev_cmd_wait(idev, max_wait); + + if (err) + return err; + + return ionic_dev_cmd_check_error(idev); +} + +int +ionic_setup(struct ionic_adapter *adapter) +{ + return ionic_dev_setup(adapter); +} + +int +ionic_identify(struct ionic_adapter *adapter) +{ + struct ionic_dev *idev = &adapter->idev; + struct ionic_identity *ident = &adapter->ident; + int err = 0; + uint32_t i; + unsigned int nwords; + uint32_t drv_size = sizeof(ident->drv.words) / + sizeof(ident->drv.words[0]); + uint32_t cmd_size = sizeof(idev->dev_cmd->data) / + sizeof(idev->dev_cmd->data[0]); + uint32_t dev_size = sizeof(ident->dev.words) / + sizeof(ident->dev.words[0]); + + memset(ident, 0, sizeof(*ident)); + + ident->drv.os_type = IONIC_OS_TYPE_LINUX; + ident->drv.os_dist = 0; + snprintf(ident->drv.os_dist_str, + sizeof(ident->drv.os_dist_str), "Unknown"); + ident->drv.kernel_ver = 0; + snprintf(ident->drv.kernel_ver_str, + sizeof(ident->drv.kernel_ver_str), "DPDK"); + strncpy(ident->drv.driver_ver_str, IONIC_DRV_VERSION, + sizeof(ident->drv.driver_ver_str) - 1); + + nwords = RTE_MIN(drv_size, cmd_size); + for (i = 0; i < nwords; i++) + iowrite32(ident->drv.words[i], &idev->dev_cmd->data[i]); + + ionic_dev_cmd_identify(idev, IONIC_IDENTITY_VERSION_1); + err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); + if (!err) { + nwords = RTE_MIN(dev_size, cmd_size); + for (i = 0; i < nwords; i++) + ident->dev.words[i] = ioread32(&idev->dev_cmd->data[i]); + } + + return err; +} + +int +ionic_init(struct ionic_adapter *adapter) +{ + struct ionic_dev *idev = &adapter->idev; + int err; + + ionic_dev_cmd_init(idev); + err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); + return err; +} + +int +ionic_reset(struct ionic_adapter *adapter) +{ + struct ionic_dev *idev = &adapter->idev; + int err; + + ionic_dev_cmd_reset(idev); + err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); + return err; +} diff --git a/drivers/net/ionic/ionic_osdep.h b/drivers/net/ionic/ionic_osdep.h new file mode 100644 index 000000000..5b8baa67b --- /dev/null +++ b/drivers/net/ionic/ionic_osdep.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0 + * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. + */ + +#ifndef _IONIC_OSDEP_ +#define _IONIC_OSDEP_ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ionic_logs.h" + +#define DELAY(x) rte_delay_us(x) +#define usec_delay(x) DELAY(x) +#define msec_delay(x) DELAY(1000 * (x)) + +#define BIT(nr) (1UL << (nr)) +#define BIT_ULL(nr) (1ULL << (nr)) +#define BITS_TO_LONGS(nr) div_round_up(nr, 8 * sizeof(long)) + +#ifndef PAGE_SHIFT +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#endif + +#define __iomem + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef uint16_t __le16; +typedef uint32_t __le32; +typedef uint64_t __le64; + +#ifndef __cplusplus +typedef uint8_t bool; +#define false 0 +#define true 1 +#endif + +static inline uint32_t div_round_up(uint32_t n, uint32_t d) +{ + return (n + d - 1) / d; +} + +static inline uint16_t ilog2(uint32_t n) +{ + uint16_t logv = -1; + + if (n == 0) + return 0; + + while (n) { + logv++; + n >>= 1; + } + + return logv; +} + +#define ioread8(reg) rte_read8(reg) +#define ioread32(reg) rte_read32(reg) +#define iowrite8(value, reg) rte_write8(value, reg) +#define iowrite32(value, reg) rte_write32(value, reg) +#define writeq(value, reg) rte_write64(value, reg) + +#endif diff --git a/drivers/net/ionic/ionic_regs.h b/drivers/net/ionic/ionic_regs.h new file mode 100644 index 000000000..e213062c9 --- /dev/null +++ b/drivers/net/ionic/ionic_regs.h @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: GPL-2.0 + * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. + */ + +#ifndef _IONIC_REGS_H_ +#define _IONIC_REGS_H_ + +/** struct ionic_intr - interrupt control register set. + * @coal_init: coalesce timer initial value. + * @mask: interrupt mask value. + * @credits: interrupt credit count and return. + * @mask_assert: interrupt mask value on assert. + * @coal: coalesce timer time remaining. + */ +struct ionic_intr { + uint32_t coal_init; + uint32_t mask; + uint32_t credits; + uint32_t mask_assert; + uint32_t coal; + uint32_t rsvd[3]; +}; + +#define IONIC_INTR_CTRL_REGS_MAX 2048 +#define IONIC_INTR_CTRL_COAL_MAX 0x3F + +/** enum ionic_intr_mask_vals - valid values for mask and mask_assert. + * @IONIC_INTR_MASK_CLEAR: unmask interrupt. + * @IONIC_INTR_MASK_SET: mask interrupt. + */ +enum ionic_intr_mask_vals { + IONIC_INTR_MASK_CLEAR = 0, + IONIC_INTR_MASK_SET = 1, +}; + +/** enum ionic_intr_credits_bits - bitwise composition of credits values. + * @IONIC_INTR_CRED_COUNT: bit mask of credit count, no shift needed. + * @IONIC_INTR_CRED_COUNT_SIGNED: bit mask of credit count, including sign bit. + * @IONIC_INTR_CRED_UNMASK: unmask the interrupt. + * @IONIC_INTR_CRED_RESET_COALESCE: reset the coalesce timer. + * @IONIC_INTR_CRED_REARM: unmask the and reset the timer. + */ +enum ionic_intr_credits_bits { + IONIC_INTR_CRED_COUNT = 0x7fffu, + IONIC_INTR_CRED_COUNT_SIGNED = 0xffffu, + IONIC_INTR_CRED_UNMASK = 0x10000u, + IONIC_INTR_CRED_RESET_COALESCE = 0x20000u, + IONIC_INTR_CRED_REARM = (IONIC_INTR_CRED_UNMASK | + IONIC_INTR_CRED_RESET_COALESCE), +}; + +static inline void +ionic_intr_coal_init(struct ionic_intr __iomem *intr_ctrl, + int intr_idx, uint32_t coal) +{ + iowrite32(coal, &intr_ctrl[intr_idx].coal_init); +} + +static inline void +ionic_intr_mask(struct ionic_intr __iomem *intr_ctrl, + int intr_idx, uint32_t mask) +{ + iowrite32(mask, &intr_ctrl[intr_idx].mask); +} + +static inline void +ionic_intr_credits(struct ionic_intr __iomem *intr_ctrl, + int intr_idx, uint32_t cred, uint32_t flags) +{ + if (cred > IONIC_INTR_CRED_COUNT) { + IONIC_WARN_ON(cred > IONIC_INTR_CRED_COUNT); + cred = ioread32(&intr_ctrl[intr_idx].credits); + cred &= IONIC_INTR_CRED_COUNT_SIGNED; + } + + iowrite32(cred | flags, &intr_ctrl[intr_idx].credits); +} + +static inline void +ionic_intr_clean(struct ionic_intr __iomem *intr_ctrl, + int intr_idx) +{ + uint32_t cred; + + cred = ioread32(&intr_ctrl[intr_idx].credits); + cred &= IONIC_INTR_CRED_COUNT_SIGNED; + cred |= IONIC_INTR_CRED_RESET_COALESCE; + iowrite32(cred, &intr_ctrl[intr_idx].credits); +} + +static inline void +ionic_intr_mask_assert(struct ionic_intr __iomem *intr_ctrl, + int intr_idx, uint32_t mask) +{ + iowrite32(mask, &intr_ctrl[intr_idx].mask_assert); +} + +/** enum ionic_dbell_bits - bitwise composition of dbell values. + * + * @IONIC_DBELL_QID_MASK: unshifted mask of valid queue id bits. + * @IONIC_DBELL_QID_SHIFT: queue id shift amount in dbell value. + * @IONIC_DBELL_QID: macro to build QID component of dbell value. + * + * @IONIC_DBELL_RING_MASK: unshifted mask of valid ring bits. + * @IONIC_DBELL_RING_SHIFT: ring shift amount in dbell value. + * @IONIC_DBELL_RING: macro to build ring component of dbell value. + * + * @IONIC_DBELL_RING_0: ring zero dbell component value. + * @IONIC_DBELL_RING_1: ring one dbell component value. + * @IONIC_DBELL_RING_2: ring two dbell component value. + * @IONIC_DBELL_RING_3: ring three dbell component value. + * + * @IONIC_DBELL_INDEX_MASK: bit mask of valid index bits, no shift needed. + */ +enum ionic_dbell_bits { + IONIC_DBELL_QID_MASK = 0xffffff, + IONIC_DBELL_QID_SHIFT = 24, + +#define IONIC_DBELL_QID(n) \ + (((u64)(n) & IONIC_DBELL_QID_MASK) << IONIC_DBELL_QID_SHIFT) + + IONIC_DBELL_RING_MASK = 0x7, + IONIC_DBELL_RING_SHIFT = 16, + +#define IONIC_DBELL_RING(n) \ + (((u64)(n) & IONIC_DBELL_RING_MASK) << IONIC_DBELL_RING_SHIFT) + + IONIC_DBELL_RING_0 = 0, + IONIC_DBELL_RING_1 = IONIC_DBELL_RING(1), + IONIC_DBELL_RING_2 = IONIC_DBELL_RING(2), + IONIC_DBELL_RING_3 = IONIC_DBELL_RING(3), + + IONIC_DBELL_INDEX_MASK = 0xffff, +}; + +static inline void +ionic_dbell_ring(u64 __iomem *db_page, int qtype, u64 val) +{ + writeq(val, &db_page[qtype]); +} + +#endif /* _IONIC_REGS_H_ */ diff --git a/drivers/net/ionic/meson.build b/drivers/net/ionic/meson.build index 5534ad6c3..bd63e6136 100644 --- a/drivers/net/ionic/meson.build +++ b/drivers/net/ionic/meson.build @@ -4,6 +4,10 @@ version = 1 sources = files( + 'ionic_mac_api.c', + 'ionic_dev.c', + 'ionic_ethdev.c', + 'ionic_main.c', 'ionic_ethdev.c' ) -- 2.17.1