From patchwork Wed Oct 30 09:01:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Junlong Wang X-Patchwork-Id: 147727 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id BE21C45C13; Wed, 30 Oct 2024 10:06:34 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id A13CE433A4; Wed, 30 Oct 2024 10:06:22 +0100 (CET) Received: from mxhk.zte.com.cn (mxhk.zte.com.cn [63.216.63.40]) by mails.dpdk.org (Postfix) with ESMTP id 8A35B4338B for ; Wed, 30 Oct 2024 10:06:08 +0100 (CET) Received: from mxct.zte.com.cn (unknown [192.168.251.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mxhk.zte.com.cn (FangMail) with ESMTPS id 4Xdh7H5gBvz8RV6M for ; Wed, 30 Oct 2024 17:06:03 +0800 (CST) Received: from mse-fl2.zte.com.cn (unknown [10.5.228.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mxct.zte.com.cn (FangMail) with ESMTPS id 4Xdh7D0s4pz4x5p3 for ; Wed, 30 Oct 2024 17:06:00 +0800 (CST) Received: from szxlzmapp04.zte.com.cn ([10.5.231.166]) by mse-fl2.zte.com.cn with SMTP id 49U95dY8055400 for ; Wed, 30 Oct 2024 17:05:39 +0800 (+08) (envelope-from wang.junlong1@zte.com.cn) Received: from localhost.localdomain (unknown [192.168.6.15]) by smtp (Zmail) with SMTP; Wed, 30 Oct 2024 17:05:42 +0800 X-Zmail-TransId: 3e816721f6e6004-b8d38 From: Junlong Wang To: dev@dpdk.org Cc: wang.yong19@zte.com.cn, Junlong Wang Subject: [PATCH v8 1/9] net/zxdh: add zxdh ethdev pmd driver Date: Wed, 30 Oct 2024 17:01:08 +0800 Message-ID: <20241030090124.2540776-2-wang.junlong1@zte.com.cn> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241030090124.2540776-1-wang.junlong1@zte.com.cn> References: <20241022122042.2127065-2-wang.junlong1@zte.com.cn> <20241030090124.2540776-1-wang.junlong1@zte.com.cn> MIME-Version: 1.0 X-MAIL: mse-fl2.zte.com.cn 49U95dY8055400 X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 6721F6FB.000/4Xdh7H5gBvz8RV6M X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add basic zxdh ethdev init and register PCI probe functions Update doc files. Signed-off-by: Junlong Wang --- MAINTAINERS | 6 ++ doc/guides/nics/features/zxdh.ini | 9 +++ doc/guides/nics/index.rst | 1 + doc/guides/nics/zxdh.rst | 31 +++++++++ doc/guides/rel_notes/release_24_11.rst | 4 ++ drivers/net/meson.build | 1 + drivers/net/zxdh/meson.build | 18 +++++ drivers/net/zxdh/zxdh_ethdev.c | 92 ++++++++++++++++++++++++++ drivers/net/zxdh/zxdh_ethdev.h | 44 ++++++++++++ 9 files changed, 206 insertions(+) create mode 100644 doc/guides/nics/features/zxdh.ini create mode 100644 doc/guides/nics/zxdh.rst create mode 100644 drivers/net/zxdh/meson.build create mode 100644 drivers/net/zxdh/zxdh_ethdev.c create mode 100644 drivers/net/zxdh/zxdh_ethdev.h -- 2.27.0 diff --git a/MAINTAINERS b/MAINTAINERS index ab64230920..a998bf0fd5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1043,6 +1043,12 @@ F: drivers/net/virtio/ F: doc/guides/nics/virtio.rst F: doc/guides/nics/features/virtio*.ini +ZTE zxdh +M: Lijie Shan +F: drivers/net/zxdh/ +F: doc/guides/nics/zxdh.rst +F: doc/guides/nics/features/zxdh.ini + Wind River AVP M: Steven Webster M: Matt Peters diff --git a/doc/guides/nics/features/zxdh.ini b/doc/guides/nics/features/zxdh.ini new file mode 100644 index 0000000000..05c8091ed7 --- /dev/null +++ b/doc/guides/nics/features/zxdh.ini @@ -0,0 +1,9 @@ +; +; Supported features of the 'zxdh' network poll mode driver. +; +; Refer to default.ini for the full list of available PMD features. +; +[Features] +Linux = Y +x86-64 = Y +ARMv8 = Y diff --git a/doc/guides/nics/index.rst b/doc/guides/nics/index.rst index c14bc7988a..8e371ac4a5 100644 --- a/doc/guides/nics/index.rst +++ b/doc/guides/nics/index.rst @@ -69,3 +69,4 @@ Network Interface Controller Drivers vhost virtio vmxnet3 + zxdh diff --git a/doc/guides/nics/zxdh.rst b/doc/guides/nics/zxdh.rst new file mode 100644 index 0000000000..920ff5175e --- /dev/null +++ b/doc/guides/nics/zxdh.rst @@ -0,0 +1,31 @@ +.. SPDX-License-Identifier: BSD-3-Clause + Copyright(c) 2024 ZTE Corporation. + +ZXDH Poll Mode Driver +====================== + +The ZXDH PMD (**librte_net_zxdh**) provides poll mode driver support +for 25/100 Gbps ZXDH NX Series Ethernet Controller based on +the ZTE Ethernet Controller E310/E312. + +- Learn about ZXDH NX Series Ethernet Controller NICs using + ``_. + +Features +-------- + +Features of the ZXDH PMD are: + +- Multi arch support: x86_64, ARMv8. + + +Driver compilation and testing +------------------------------ + +Refer to the document :ref:`compiling and testing a PMD for a NIC ` +for details. + +Limitations or Known issues +--------------------------- + +X86-32, Power8, ARMv7, RISC-V, Windows and BSD are not supported yet. diff --git a/doc/guides/rel_notes/release_24_11.rst b/doc/guides/rel_notes/release_24_11.rst index fa4822d928..986a611e08 100644 --- a/doc/guides/rel_notes/release_24_11.rst +++ b/doc/guides/rel_notes/release_24_11.rst @@ -161,6 +161,10 @@ New Features * Added initialization of FPGA modules related to flow HW offload. * Added basic handling of the virtual queues. + * **Updated ZTE zxdh net driver.** + + * Added ethdev driver support for zxdh NX Series Ethernet Controller. + * **Added cryptodev queue pair reset support.** A new API ``rte_cryptodev_queue_pair_reset`` is added diff --git a/drivers/net/meson.build b/drivers/net/meson.build index fb6d34b782..0a12914534 100644 --- a/drivers/net/meson.build +++ b/drivers/net/meson.build @@ -62,6 +62,7 @@ drivers = [ 'vhost', 'virtio', 'vmxnet3', + 'zxdh', ] std_deps = ['ethdev', 'kvargs'] # 'ethdev' also pulls in mbuf, net, eal etc std_deps += ['bus_pci'] # very many PMDs depend on PCI, so make std diff --git a/drivers/net/zxdh/meson.build b/drivers/net/zxdh/meson.build new file mode 100644 index 0000000000..932fb1c835 --- /dev/null +++ b/drivers/net/zxdh/meson.build @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2024 ZTE Corporation + +if not is_linux + build = false + reason = 'only supported on Linux' + subdir_done() +endif + +if not dpdk_conf.has('RTE_ARCH_X86_64') or not dpdk_conf.get('RTE_ARCH_64') + build = false + reason = 'only supported on x86_64 and aarch64' + subdir_done() +endif + +sources = files( + 'zxdh_ethdev.c', +) diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c new file mode 100644 index 0000000000..5b6c9ec1bf --- /dev/null +++ b/drivers/net/zxdh/zxdh_ethdev.c @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 ZTE Corporation + */ + +#include +#include +#include + +#include "zxdh_ethdev.h" + +static int zxdh_eth_dev_init(struct rte_eth_dev *eth_dev) +{ + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); + struct zxdh_hw *hw = eth_dev->data->dev_private; + int ret = 0; + + eth_dev->dev_ops = NULL; + + /* Allocate memory for storing MAC addresses */ + eth_dev->data->mac_addrs = rte_zmalloc("zxdh_mac", + ZXDH_MAX_MAC_ADDRS * RTE_ETHER_ADDR_LEN, 0); + if (eth_dev->data->mac_addrs == NULL) + return -ENOMEM; + + memset(hw, 0, sizeof(*hw)); + hw->bar_addr[0] = (uint64_t)pci_dev->mem_resource[0].addr; + if (hw->bar_addr[0] == 0) + return -EIO; + + hw->device_id = pci_dev->id.device_id; + hw->port_id = eth_dev->data->port_id; + hw->eth_dev = eth_dev; + hw->speed = RTE_ETH_SPEED_NUM_UNKNOWN; + hw->duplex = RTE_ETH_LINK_FULL_DUPLEX; + hw->is_pf = 0; + + if (pci_dev->id.device_id == ZXDH_E310_PF_DEVICEID || + pci_dev->id.device_id == ZXDH_E312_PF_DEVICEID) { + hw->is_pf = 1; + } + + return ret; +} + +static int zxdh_eth_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, + struct rte_pci_device *pci_dev) +{ + return rte_eth_dev_pci_generic_probe(pci_dev, + sizeof(struct zxdh_hw), + zxdh_eth_dev_init); +} + +static int zxdh_dev_close(struct rte_eth_dev *dev __rte_unused) +{ + int ret = 0; + + return ret; +} + +static int zxdh_eth_dev_uninit(struct rte_eth_dev *eth_dev) +{ + int ret = 0; + + ret = zxdh_dev_close(eth_dev); + + return ret; +} + +static int zxdh_eth_pci_remove(struct rte_pci_device *pci_dev) +{ + int ret = rte_eth_dev_pci_generic_remove(pci_dev, zxdh_eth_dev_uninit); + + return ret; +} + +static const struct rte_pci_id pci_id_zxdh_map[] = { + {RTE_PCI_DEVICE(ZXDH_PCI_VENDOR_ID, ZXDH_E310_PF_DEVICEID)}, + {RTE_PCI_DEVICE(ZXDH_PCI_VENDOR_ID, ZXDH_E310_VF_DEVICEID)}, + {RTE_PCI_DEVICE(ZXDH_PCI_VENDOR_ID, ZXDH_E312_PF_DEVICEID)}, + {RTE_PCI_DEVICE(ZXDH_PCI_VENDOR_ID, ZXDH_E312_VF_DEVICEID)}, + {.vendor_id = 0, /* sentinel */ }, +}; +static struct rte_pci_driver zxdh_pmd = { + .id_table = pci_id_zxdh_map, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, + .probe = zxdh_eth_pci_probe, + .remove = zxdh_eth_pci_remove, +}; + +RTE_PMD_REGISTER_PCI(net_zxdh, zxdh_pmd); +RTE_PMD_REGISTER_PCI_TABLE(net_zxdh, pci_id_zxdh_map); +RTE_PMD_REGISTER_KMOD_DEP(net_zxdh, "* vfio-pci"); diff --git a/drivers/net/zxdh/zxdh_ethdev.h b/drivers/net/zxdh/zxdh_ethdev.h new file mode 100644 index 0000000000..93375aea11 --- /dev/null +++ b/drivers/net/zxdh/zxdh_ethdev.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 ZTE Corporation + */ + +#ifndef ZXDH_ETHDEV_H +#define ZXDH_ETHDEV_H + +#include "ethdev_driver.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ZXDH PCI vendor/device ID. */ +#define ZXDH_PCI_VENDOR_ID 0x1cf2 + +#define ZXDH_E310_PF_DEVICEID 0x8061 +#define ZXDH_E310_VF_DEVICEID 0x8062 +#define ZXDH_E312_PF_DEVICEID 0x8049 +#define ZXDH_E312_VF_DEVICEID 0x8060 + +#define ZXDH_MAX_UC_MAC_ADDRS 32 +#define ZXDH_MAX_MC_MAC_ADDRS 32 +#define ZXDH_MAX_MAC_ADDRS (ZXDH_MAX_UC_MAC_ADDRS + ZXDH_MAX_MC_MAC_ADDRS) + +#define ZXDH_NUM_BARS 2 + +struct zxdh_hw { + struct rte_eth_dev *eth_dev; + uint64_t bar_addr[ZXDH_NUM_BARS]; + + uint32_t speed; + uint16_t device_id; + uint16_t port_id; + + uint8_t duplex; + uint8_t is_pf; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* ZXDH_ETHDEV_H */ From patchwork Wed Oct 30 09:01:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Junlong Wang X-Patchwork-Id: 147724 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 3B5B045C13; Wed, 30 Oct 2024 10:06:09 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 4017A43375; Wed, 30 Oct 2024 10:06:08 +0100 (CET) Received: from mxhk.zte.com.cn (mxhk.zte.com.cn [63.216.63.40]) by mails.dpdk.org (Postfix) with ESMTP id AAA6443384 for ; Wed, 30 Oct 2024 10:06:05 +0100 (CET) Received: from mse-fl2.zte.com.cn (unknown [10.5.228.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mxhk.zte.com.cn (FangMail) with ESMTPS id 4Xdh7C4GtXz8RTZS for ; Wed, 30 Oct 2024 17:05:59 +0800 (CST) Received: from szxlzmapp01.zte.com.cn ([10.5.231.85]) by mse-fl2.zte.com.cn with SMTP id 49U95eGV055411 for ; Wed, 30 Oct 2024 17:05:40 +0800 (+08) (envelope-from wang.junlong1@zte.com.cn) Received: from localhost.localdomain (unknown [192.168.6.15]) by smtp (Zmail) with SMTP; Wed, 30 Oct 2024 17:05:43 +0800 X-Zmail-TransId: 3e816721f6e7004-b8d3b From: Junlong Wang To: dev@dpdk.org Cc: wang.yong19@zte.com.cn, Junlong Wang Subject: [PATCH v8 2/9] net/zxdh: add logging implementation Date: Wed, 30 Oct 2024 17:01:09 +0800 Message-ID: <20241030090124.2540776-3-wang.junlong1@zte.com.cn> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241030090124.2540776-1-wang.junlong1@zte.com.cn> References: <20241022122042.2127065-2-wang.junlong1@zte.com.cn> <20241030090124.2540776-1-wang.junlong1@zte.com.cn> MIME-Version: 1.0 X-MAIL: mse-fl2.zte.com.cn 49U95eGV055411 X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 6721F6F7.000/4Xdh7C4GtXz8RTZS X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add zxdh logging implementation. Signed-off-by: Junlong Wang --- drivers/net/zxdh/zxdh_ethdev.c | 15 +++++++++++-- drivers/net/zxdh/zxdh_logs.h | 40 ++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 drivers/net/zxdh/zxdh_logs.h -- 2.27.0 diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c index 5b6c9ec1bf..c911284423 100644 --- a/drivers/net/zxdh/zxdh_ethdev.c +++ b/drivers/net/zxdh/zxdh_ethdev.c @@ -7,6 +7,7 @@ #include #include "zxdh_ethdev.h" +#include "zxdh_logs.h" static int zxdh_eth_dev_init(struct rte_eth_dev *eth_dev) { @@ -19,13 +20,18 @@ static int zxdh_eth_dev_init(struct rte_eth_dev *eth_dev) /* Allocate memory for storing MAC addresses */ eth_dev->data->mac_addrs = rte_zmalloc("zxdh_mac", ZXDH_MAX_MAC_ADDRS * RTE_ETHER_ADDR_LEN, 0); - if (eth_dev->data->mac_addrs == NULL) + if (eth_dev->data->mac_addrs == NULL) { + PMD_INIT_LOG(ERR, "Failed to allocate %d bytes store MAC addresses", + ZXDH_MAX_MAC_ADDRS * RTE_ETHER_ADDR_LEN); return -ENOMEM; + } memset(hw, 0, sizeof(*hw)); hw->bar_addr[0] = (uint64_t)pci_dev->mem_resource[0].addr; - if (hw->bar_addr[0] == 0) + if (hw->bar_addr[0] == 0) { + PMD_INIT_LOG(ERR, "Bad mem resource."); return -EIO; + } hw->device_id = pci_dev->id.device_id; hw->port_id = eth_dev->data->port_id; @@ -90,3 +96,8 @@ static struct rte_pci_driver zxdh_pmd = { RTE_PMD_REGISTER_PCI(net_zxdh, zxdh_pmd); RTE_PMD_REGISTER_PCI_TABLE(net_zxdh, pci_id_zxdh_map); RTE_PMD_REGISTER_KMOD_DEP(net_zxdh, "* vfio-pci"); +RTE_LOG_REGISTER_SUFFIX(zxdh_logtype_init, init, NOTICE); +RTE_LOG_REGISTER_SUFFIX(zxdh_logtype_driver, driver, NOTICE); +RTE_LOG_REGISTER_SUFFIX(zxdh_logtype_rx, rx, NOTICE); +RTE_LOG_REGISTER_SUFFIX(zxdh_logtype_tx, tx, NOTICE); +RTE_LOG_REGISTER_SUFFIX(zxdh_logtype_msg, msg, NOTICE); diff --git a/drivers/net/zxdh/zxdh_logs.h b/drivers/net/zxdh/zxdh_logs.h new file mode 100644 index 0000000000..a8a6a3135b --- /dev/null +++ b/drivers/net/zxdh/zxdh_logs.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 ZTE Corporation + */ + +#ifndef ZXDH_LOGS_H +#define ZXDH_LOGS_H + +#include + +extern int zxdh_logtype_init; +#define RTE_LOGTYPE_ZXDH_INIT zxdh_logtype_init +#define PMD_INIT_LOG(level, ...) \ + RTE_LOG_LINE_PREFIX(level, ZXDH_INIT, "offload_zxdh %s(): ", \ + __func__, __VA_ARGS__) + +extern int zxdh_logtype_driver; +#define RTE_LOGTYPE_ZXDH_DRIVER zxdh_logtype_driver +#define PMD_DRV_LOG(level, ...) \ + RTE_LOG_LINE_PREFIX(level, ZXDH_DRIVER, "offload_zxdh %s(): ", \ + __func__, __VA_ARGS__) + +extern int zxdh_logtype_rx; +#define RTE_LOGTYPE_ZXDH_RX zxdh_logtype_rx +#define PMD_RX_LOG(level, ...) \ + RTE_LOG_LINE_PREFIX(level, ZXDH_RX, "offload_zxdh %s(): ", \ + __func__, __VA_ARGS__) + +extern int zxdh_logtype_tx; +#define RTE_LOGTYPE_ZXDH_TX zxdh_logtype_tx +#define PMD_TX_LOG(level, ...) \ + RTE_LOG_LINE_PREFIX(level, ZXDH_TX, "offload_zxdh %s(): ", \ + __func__, __VA_ARGS__) + +extern int zxdh_logtype_msg; +#define RTE_LOGTYPE_ZXDH_MSG zxdh_logtype_msg +#define PMD_MSG_LOG(level, ...) \ + RTE_LOG_LINE_PREFIX(level, ZXDH_MSG, "offload_zxdh %s(): ", \ + __func__, __VA_ARGS__) + +#endif /* ZXDH_LOGS_H */ From patchwork Wed Oct 30 09:01:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Junlong Wang X-Patchwork-Id: 147730 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 4548E45C13; Wed, 30 Oct 2024 10:06:57 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 5A061433B0; Wed, 30 Oct 2024 10:06:26 +0100 (CET) Received: from mxhk.zte.com.cn (mxhk.zte.com.cn [63.216.63.35]) by mails.dpdk.org (Postfix) with ESMTP id 2D74B4339A for ; Wed, 30 Oct 2024 10:06:12 +0100 (CET) Received: from mse-fl1.zte.com.cn (unknown [10.5.228.132]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mxhk.zte.com.cn (FangMail) with ESMTPS id 4Xdh7K5Whrz4xth9 for ; Wed, 30 Oct 2024 17:06:05 +0800 (CST) Received: from szxlzmapp01.zte.com.cn ([10.5.231.85]) by mse-fl1.zte.com.cn with SMTP id 49U95f0u007090 for ; Wed, 30 Oct 2024 17:05:41 +0800 (+08) (envelope-from wang.junlong1@zte.com.cn) Received: from localhost.localdomain (unknown [192.168.6.15]) by smtp (Zmail) with SMTP; Wed, 30 Oct 2024 17:05:44 +0800 X-Zmail-TransId: 3e816721f6e7004-b8d3f From: Junlong Wang To: dev@dpdk.org Cc: wang.yong19@zte.com.cn, Junlong Wang Subject: [PATCH v8 3/9] net/zxdh: add zxdh device pci init implementation Date: Wed, 30 Oct 2024 17:01:10 +0800 Message-ID: <20241030090124.2540776-4-wang.junlong1@zte.com.cn> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241030090124.2540776-1-wang.junlong1@zte.com.cn> References: <20241022122042.2127065-2-wang.junlong1@zte.com.cn> <20241030090124.2540776-1-wang.junlong1@zte.com.cn> MIME-Version: 1.0 X-MAIL: mse-fl1.zte.com.cn 49U95f0u007090 X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 6721F6FD.005/4Xdh7K5Whrz4xth9 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add device pci init implementation, to obtain PCI capability and read configuration, etc. Signed-off-by: Junlong Wang --- drivers/net/zxdh/meson.build | 1 + drivers/net/zxdh/zxdh_ethdev.c | 43 +++++ drivers/net/zxdh/zxdh_ethdev.h | 21 ++- drivers/net/zxdh/zxdh_pci.c | 285 +++++++++++++++++++++++++++++++++ drivers/net/zxdh/zxdh_pci.h | 151 +++++++++++++++++ drivers/net/zxdh/zxdh_queue.h | 105 ++++++++++++ drivers/net/zxdh/zxdh_rxtx.h | 51 ++++++ 7 files changed, 655 insertions(+), 2 deletions(-) create mode 100644 drivers/net/zxdh/zxdh_pci.c create mode 100644 drivers/net/zxdh/zxdh_pci.h create mode 100644 drivers/net/zxdh/zxdh_queue.h create mode 100644 drivers/net/zxdh/zxdh_rxtx.h -- 2.27.0 diff --git a/drivers/net/zxdh/meson.build b/drivers/net/zxdh/meson.build index 932fb1c835..7db4e7bc71 100644 --- a/drivers/net/zxdh/meson.build +++ b/drivers/net/zxdh/meson.build @@ -15,4 +15,5 @@ endif sources = files( 'zxdh_ethdev.c', + 'zxdh_pci.c', ) diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c index c911284423..8877855965 100644 --- a/drivers/net/zxdh/zxdh_ethdev.c +++ b/drivers/net/zxdh/zxdh_ethdev.c @@ -8,6 +8,40 @@ #include "zxdh_ethdev.h" #include "zxdh_logs.h" +#include "zxdh_pci.h" + +struct zxdh_hw_internal zxdh_hw_internal[RTE_MAX_ETHPORTS]; + +static int32_t zxdh_init_device(struct rte_eth_dev *eth_dev) +{ + struct zxdh_hw *hw = eth_dev->data->dev_private; + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); + int ret = 0; + + ret = zxdh_read_pci_caps(pci_dev, hw); + if (ret) { + PMD_INIT_LOG(ERR, "port 0x%x pci caps read failed .", hw->port_id); + goto err; + } + + zxdh_hw_internal[hw->port_id].zxdh_vtpci_ops = &zxdh_dev_pci_ops; + zxdh_vtpci_reset(hw); + zxdh_get_pci_dev_config(hw); + + rte_ether_addr_copy((struct rte_ether_addr *)hw->mac_addr, ð_dev->data->mac_addrs[0]); + + /* If host does not support both status and MSI-X then disable LSC */ + if (vtpci_with_feature(hw, ZXDH_NET_F_STATUS) && hw->use_msix != ZXDH_MSIX_NONE) + eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC; + else + eth_dev->data->dev_flags &= ~RTE_ETH_DEV_INTR_LSC; + + return 0; + +err: + PMD_INIT_LOG(ERR, "port %d init device failed", eth_dev->data->port_id); + return ret; +} static int zxdh_eth_dev_init(struct rte_eth_dev *eth_dev) { @@ -45,6 +79,15 @@ static int zxdh_eth_dev_init(struct rte_eth_dev *eth_dev) hw->is_pf = 1; } + ret = zxdh_init_device(eth_dev); + if (ret < 0) + goto err_zxdh_init; + + return ret; + +err_zxdh_init: + rte_free(eth_dev->data->mac_addrs); + eth_dev->data->mac_addrs = NULL; return ret; } diff --git a/drivers/net/zxdh/zxdh_ethdev.h b/drivers/net/zxdh/zxdh_ethdev.h index 93375aea11..8be5af6aeb 100644 --- a/drivers/net/zxdh/zxdh_ethdev.h +++ b/drivers/net/zxdh/zxdh_ethdev.h @@ -5,6 +5,8 @@ #ifndef ZXDH_ETHDEV_H #define ZXDH_ETHDEV_H +#include + #include "ethdev_driver.h" #ifdef __cplusplus @@ -24,15 +26,30 @@ extern "C" { #define ZXDH_MAX_MAC_ADDRS (ZXDH_MAX_UC_MAC_ADDRS + ZXDH_MAX_MC_MAC_ADDRS) #define ZXDH_NUM_BARS 2 +#define ZXDH_RX_QUEUES_MAX 128U +#define ZXDH_TX_QUEUES_MAX 128U struct zxdh_hw { struct rte_eth_dev *eth_dev; - uint64_t bar_addr[ZXDH_NUM_BARS]; + struct zxdh_pci_common_cfg *common_cfg; + struct zxdh_net_config *dev_cfg; - uint32_t speed; + uint64_t bar_addr[ZXDH_NUM_BARS]; + uint64_t host_features; + uint64_t guest_features; + uint32_t max_queue_pairs; + uint32_t speed; + uint32_t notify_off_multiplier; + uint16_t *notify_base; + uint16_t pcie_id; uint16_t device_id; uint16_t port_id; + uint8_t *isr; + uint8_t weak_barriers; + uint8_t use_msix; + uint8_t mac_addr[RTE_ETHER_ADDR_LEN]; + uint8_t duplex; uint8_t is_pf; }; diff --git a/drivers/net/zxdh/zxdh_pci.c b/drivers/net/zxdh/zxdh_pci.c new file mode 100644 index 0000000000..8fcab6e888 --- /dev/null +++ b/drivers/net/zxdh/zxdh_pci.c @@ -0,0 +1,285 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 ZTE Corporation + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "zxdh_ethdev.h" +#include "zxdh_pci.h" +#include "zxdh_logs.h" +#include "zxdh_queue.h" + +#define ZXDH_PMD_DEFAULT_GUEST_FEATURES \ + (1ULL << ZXDH_NET_F_MRG_RXBUF | \ + 1ULL << ZXDH_NET_F_STATUS | \ + 1ULL << ZXDH_NET_F_MQ | \ + 1ULL << ZXDH_F_ANY_LAYOUT | \ + 1ULL << ZXDH_F_VERSION_1 | \ + 1ULL << ZXDH_F_RING_PACKED | \ + 1ULL << ZXDH_F_IN_ORDER | \ + 1ULL << ZXDH_F_NOTIFICATION_DATA | \ + 1ULL << ZXDH_NET_F_MAC) + +static void zxdh_read_dev_config(struct zxdh_hw *hw, + size_t offset, + void *dst, + int32_t length) +{ + int32_t i = 0; + uint8_t *p = NULL; + uint8_t old_gen = 0; + uint8_t new_gen = 0; + + do { + old_gen = rte_read8(&hw->common_cfg->config_generation); + + p = dst; + for (i = 0; i < length; i++) + *p++ = rte_read8((uint8_t *)hw->dev_cfg + offset + i); + + new_gen = rte_read8(&hw->common_cfg->config_generation); + } while (old_gen != new_gen); +} + +static void zxdh_write_dev_config(struct zxdh_hw *hw, + size_t offset, + const void *src, + int32_t length) +{ + int32_t i = 0; + const uint8_t *p = src; + + for (i = 0; i < length; i++) + rte_write8((*p++), (((uint8_t *)hw->dev_cfg) + offset + i)); +} + +static uint8_t zxdh_get_status(struct zxdh_hw *hw) +{ + return rte_read8(&hw->common_cfg->device_status); +} + +static void zxdh_set_status(struct zxdh_hw *hw, uint8_t status) +{ + rte_write8(status, &hw->common_cfg->device_status); +} + +static uint64_t zxdh_get_features(struct zxdh_hw *hw) +{ + uint32_t features_lo = 0; + uint32_t features_hi = 0; + + rte_write32(0, &hw->common_cfg->device_feature_select); + features_lo = rte_read32(&hw->common_cfg->device_feature); + + rte_write32(1, &hw->common_cfg->device_feature_select); + features_hi = rte_read32(&hw->common_cfg->device_feature); + + return ((uint64_t)features_hi << 32) | features_lo; +} + +static void zxdh_set_features(struct zxdh_hw *hw, uint64_t features) +{ + rte_write32(0, &hw->common_cfg->guest_feature_select); + rte_write32(features & ((1ULL << 32) - 1), &hw->common_cfg->guest_feature); + rte_write32(1, &hw->common_cfg->guest_feature_select); + rte_write32(features >> 32, &hw->common_cfg->guest_feature); +} + +const struct zxdh_pci_ops zxdh_dev_pci_ops = { + .read_dev_cfg = zxdh_read_dev_config, + .write_dev_cfg = zxdh_write_dev_config, + .get_status = zxdh_get_status, + .set_status = zxdh_set_status, + .get_features = zxdh_get_features, + .set_features = zxdh_set_features, +}; + +uint16_t zxdh_vtpci_get_features(struct zxdh_hw *hw) +{ + return ZXDH_VTPCI_OPS(hw)->get_features(hw); +} + +void zxdh_vtpci_reset(struct zxdh_hw *hw) +{ + PMD_INIT_LOG(INFO, "port %u device start reset, just wait...", hw->port_id); + uint32_t retry = 0; + + ZXDH_VTPCI_OPS(hw)->set_status(hw, ZXDH_CONFIG_STATUS_RESET); + /* Flush status write and wait device ready max 3 seconds. */ + while (ZXDH_VTPCI_OPS(hw)->get_status(hw) != ZXDH_CONFIG_STATUS_RESET) { + ++retry; + rte_delay_ms(1); + } + PMD_INIT_LOG(INFO, "port %u device reset %u ms done", hw->port_id, retry); +} + +static void *get_cfg_addr(struct rte_pci_device *dev, struct zxdh_pci_cap *cap) +{ + uint8_t bar = cap->bar; + uint32_t length = cap->length; + uint32_t offset = cap->offset; + + if (bar >= PCI_MAX_RESOURCE) { + PMD_INIT_LOG(ERR, "invalid bar: %u", bar); + return NULL; + } + if (offset + length < offset) { + PMD_INIT_LOG(ERR, "offset(%u) + length(%u) overflows", offset, length); + return NULL; + } + if (offset + length > dev->mem_resource[bar].len) { + PMD_INIT_LOG(ERR, "invalid cap: overflows bar space"); + return NULL; + } + uint8_t *base = dev->mem_resource[bar].addr; + + if (base == NULL) { + PMD_INIT_LOG(ERR, "bar %u base addr is NULL", bar); + return NULL; + } + return base + offset; +} + +int32_t zxdh_read_pci_caps(struct rte_pci_device *dev, struct zxdh_hw *hw) +{ + uint8_t pos = 0; + int32_t ret = 0; + + if (dev->mem_resource[0].addr == NULL) { + PMD_INIT_LOG(ERR, "bar0 base addr is NULL"); + return -1; + } + + ret = rte_pci_read_config(dev, &pos, 1, ZXDH_PCI_CAPABILITY_LIST); + + if (ret != 1) { + PMD_INIT_LOG(DEBUG, "failed to read pci capability list, ret %d", ret); + return -1; + } + while (pos) { + struct zxdh_pci_cap cap; + + ret = rte_pci_read_config(dev, &cap, 2, pos); + if (ret != 2) { + PMD_INIT_LOG(DEBUG, "failed to read pci cap at pos: %x ret %d", pos, ret); + break; + } + if (cap.cap_vndr == ZXDH_PCI_CAP_ID_MSIX) { + /** + * Transitional devices would also have this capability, + * that's why we also check if msix is enabled. + * 1st byte is cap ID; 2nd byte is the position of next cap; + * next two bytes are the flags. + */ + uint16_t flags = 0; + + ret = rte_pci_read_config(dev, &flags, sizeof(flags), pos + 2); + if (ret != sizeof(flags)) { + PMD_INIT_LOG(ERR, "failed to read pci cap at pos: %x ret %d", + pos + 2, ret); + break; + } + hw->use_msix = (flags & ZXDH_PCI_MSIX_ENABLE) ? + ZXDH_MSIX_ENABLED : ZXDH_MSIX_DISABLED; + } + if (cap.cap_vndr != ZXDH_PCI_CAP_ID_VNDR) { + PMD_INIT_LOG(DEBUG, "[%2x] skipping non VNDR cap id: %02x", + pos, cap.cap_vndr); + goto next; + } + ret = rte_pci_read_config(dev, &cap, sizeof(cap), pos); + if (ret != sizeof(cap)) { + PMD_INIT_LOG(ERR, "failed to read pci cap at pos: %x ret %d", pos, ret); + break; + } + PMD_INIT_LOG(DEBUG, "[%2x] cfg type: %u, bar: %u, offset: %04x, len: %u", + pos, cap.cfg_type, cap.bar, cap.offset, cap.length); + switch (cap.cfg_type) { + case ZXDH_PCI_CAP_COMMON_CFG: + hw->common_cfg = get_cfg_addr(dev, &cap); + break; + case ZXDH_PCI_CAP_NOTIFY_CFG: { + ret = rte_pci_read_config(dev, &hw->notify_off_multiplier, + 4, pos + sizeof(cap)); + if (ret != 4) + PMD_INIT_LOG(ERR, + "failed to read notify_off_multiplier, ret %d", ret); + else + hw->notify_base = get_cfg_addr(dev, &cap); + break; + } + case ZXDH_PCI_CAP_DEVICE_CFG: + hw->dev_cfg = get_cfg_addr(dev, &cap); + break; + case ZXDH_PCI_CAP_ISR_CFG: + hw->isr = get_cfg_addr(dev, &cap); + break; + case ZXDH_PCI_CAP_PCI_CFG: { + hw->pcie_id = *(uint16_t *)&cap.padding[1]; + PMD_INIT_LOG(DEBUG, "get pcie id 0x%x", hw->pcie_id); + uint16_t pcie_id = hw->pcie_id; + + if ((pcie_id >> 11) & 0x1) /* PF */ { + PMD_INIT_LOG(DEBUG, "EP %u PF %u", + pcie_id >> 12, (pcie_id >> 8) & 0x7); + } else { /* VF */ + PMD_INIT_LOG(DEBUG, "EP %u PF %u VF %u", + pcie_id >> 12, (pcie_id >> 8) & 0x7, pcie_id & 0xff); + } + break; + } + } +next: + pos = cap.cap_next; + } + if (hw->common_cfg == NULL || hw->notify_base == NULL || + hw->dev_cfg == NULL || hw->isr == NULL) { + PMD_INIT_LOG(ERR, "no zxdh pci device found."); + return -1; + } + return 0; +} + +void zxdh_vtpci_read_dev_config(struct zxdh_hw *hw, size_t offset, void *dst, int32_t length) +{ + ZXDH_VTPCI_OPS(hw)->read_dev_cfg(hw, offset, dst, length); +} + +int32_t zxdh_get_pci_dev_config(struct zxdh_hw *hw) +{ + uint64_t guest_features = 0; + uint64_t nego_features = 0; + uint32_t max_queue_pairs = 0; + + hw->host_features = zxdh_vtpci_get_features(hw); + + guest_features = (uint64_t)ZXDH_PMD_DEFAULT_GUEST_FEATURES; + nego_features = guest_features & hw->host_features; + + hw->guest_features = nego_features; + + if (hw->guest_features & (1ULL << ZXDH_NET_F_MAC)) { + zxdh_vtpci_read_dev_config(hw, offsetof(struct zxdh_net_config, mac), + &hw->mac_addr, RTE_ETHER_ADDR_LEN); + } else { + rte_eth_random_addr(&hw->mac_addr[0]); + } + + zxdh_vtpci_read_dev_config(hw, offsetof(struct zxdh_net_config, max_virtqueue_pairs), + &max_queue_pairs, sizeof(max_queue_pairs)); + + if (max_queue_pairs == 0) + hw->max_queue_pairs = ZXDH_RX_QUEUES_MAX; + else + hw->max_queue_pairs = RTE_MIN(ZXDH_RX_QUEUES_MAX, max_queue_pairs); + PMD_INIT_LOG(DEBUG, "set max queue pairs %d", hw->max_queue_pairs); + + return 0; +} diff --git a/drivers/net/zxdh/zxdh_pci.h b/drivers/net/zxdh/zxdh_pci.h new file mode 100644 index 0000000000..bb5ae64ddf --- /dev/null +++ b/drivers/net/zxdh/zxdh_pci.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 ZTE Corporation + */ + +#ifndef ZXDH_PCI_H +#define ZXDH_PCI_H + +#include +#include + +#include + +#include "zxdh_ethdev.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum zxdh_msix_status { + ZXDH_MSIX_NONE = 0, + ZXDH_MSIX_DISABLED = 1, + ZXDH_MSIX_ENABLED = 2 +}; + +#define ZXDH_PCI_CAPABILITY_LIST 0x34 +#define ZXDH_PCI_CAP_ID_VNDR 0x09 +#define ZXDH_PCI_CAP_ID_MSIX 0x11 + +#define ZXDH_PCI_MSIX_ENABLE 0x8000 + +#define ZXDH_NET_F_MAC 5 /* Host has given MAC address. */ +#define ZXDH_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */ +#define ZXDH_NET_F_STATUS 16 /* zxdh_net_config.status available */ +#define ZXDH_NET_F_MQ 22 /* Device supports Receive Flow Steering */ +#define ZXDH_F_ANY_LAYOUT 27 /* Can the device handle any descriptor layout */ +#define ZXDH_F_VERSION_1 32 +#define ZXDH_F_RING_PACKED 34 +#define ZXDH_F_IN_ORDER 35 +#define ZXDH_F_NOTIFICATION_DATA 38 + +#define ZXDH_PCI_CAP_COMMON_CFG 1 /* Common configuration */ +#define ZXDH_PCI_CAP_NOTIFY_CFG 2 /* Notifications */ +#define ZXDH_PCI_CAP_ISR_CFG 3 /* ISR Status */ +#define ZXDH_PCI_CAP_DEVICE_CFG 4 /* Device specific configuration */ +#define ZXDH_PCI_CAP_PCI_CFG 5 /* PCI configuration access */ + +/* Status byte for guest to report progress. */ +#define ZXDH_CONFIG_STATUS_RESET 0x00 +#define ZXDH_CONFIG_STATUS_ACK 0x01 +#define ZXDH_CONFIG_STATUS_DRIVER 0x02 +#define ZXDH_CONFIG_STATUS_DRIVER_OK 0x04 +#define ZXDH_CONFIG_STATUS_FEATURES_OK 0x08 +#define ZXDH_CONFIG_STATUS_DEV_NEED_RESET 0x40 +#define ZXDH_CONFIG_STATUS_FAILED 0x80 + +struct zxdh_net_config { + /* The config defining mac address (if ZXDH_NET_F_MAC) */ + uint8_t mac[RTE_ETHER_ADDR_LEN]; + /* See ZXDH_NET_F_STATUS and ZXDH_NET_S_* above */ + uint16_t status; + uint16_t max_virtqueue_pairs; + uint16_t mtu; + /* + * speed, in units of 1Mb. All values 0 to INT_MAX are legal. + * Any other value stands for unknown. + */ + uint32_t speed; + /* 0x00 - half duplex + * 0x01 - full duplex + * Any other value stands for unknown. + */ + uint8_t duplex; +} __rte_packed; + +/* This is the PCI capability header: */ +struct zxdh_pci_cap { + uint8_t cap_vndr; /* Generic PCI field: PCI_CAP_ID_VNDR */ + uint8_t cap_next; /* Generic PCI field: next ptr. */ + uint8_t cap_len; /* Generic PCI field: capability length */ + uint8_t cfg_type; /* Identifies the structure. */ + uint8_t bar; /* Where to find it. */ + uint8_t padding[3]; /* Pad to full dword. */ + uint32_t offset; /* Offset within bar. */ + uint32_t length; /* Length of the structure, in bytes. */ +}; + +/* Fields in ZXDH_PCI_CAP_COMMON_CFG: */ +struct zxdh_pci_common_cfg { + /* About the whole device. */ + uint32_t device_feature_select; /* read-write */ + uint32_t device_feature; /* read-only */ + uint32_t guest_feature_select; /* read-write */ + uint32_t guest_feature; /* read-write */ + uint16_t msix_config; /* read-write */ + uint16_t num_queues; /* read-only */ + uint8_t device_status; /* read-write */ + uint8_t config_generation; /* read-only */ + + /* About a specific virtqueue. */ + uint16_t queue_select; /* read-write */ + uint16_t queue_size; /* read-write, power of 2. */ + uint16_t queue_msix_vector; /* read-write */ + uint16_t queue_enable; /* read-write */ + uint16_t queue_notify_off; /* read-only */ + uint32_t queue_desc_lo; /* read-write */ + uint32_t queue_desc_hi; /* read-write */ + uint32_t queue_avail_lo; /* read-write */ + uint32_t queue_avail_hi; /* read-write */ + uint32_t queue_used_lo; /* read-write */ + uint32_t queue_used_hi; /* read-write */ +}; + +static inline int32_t vtpci_with_feature(struct zxdh_hw *hw, uint64_t bit) +{ + return (hw->guest_features & (1ULL << bit)) != 0; +} + +struct zxdh_pci_ops { + void (*read_dev_cfg)(struct zxdh_hw *hw, size_t offset, void *dst, int32_t len); + void (*write_dev_cfg)(struct zxdh_hw *hw, size_t offset, const void *src, int32_t len); + + uint8_t (*get_status)(struct zxdh_hw *hw); + void (*set_status)(struct zxdh_hw *hw, uint8_t status); + + uint64_t (*get_features)(struct zxdh_hw *hw); + void (*set_features)(struct zxdh_hw *hw, uint64_t features); +}; + +struct zxdh_hw_internal { + const struct zxdh_pci_ops *zxdh_vtpci_ops; +}; + +#define ZXDH_VTPCI_OPS(hw) (zxdh_hw_internal[(hw)->port_id].zxdh_vtpci_ops) + +extern struct zxdh_hw_internal zxdh_hw_internal[RTE_MAX_ETHPORTS]; +extern const struct zxdh_pci_ops zxdh_dev_pci_ops; + +void zxdh_vtpci_reset(struct zxdh_hw *hw); +void zxdh_vtpci_read_dev_config(struct zxdh_hw *hw, size_t offset, + void *dst, int32_t length); + +int32_t zxdh_read_pci_caps(struct rte_pci_device *dev, struct zxdh_hw *hw); +int32_t zxdh_get_pci_dev_config(struct zxdh_hw *hw); + +uint16_t zxdh_vtpci_get_features(struct zxdh_hw *hw); + +#ifdef __cplusplus +} +#endif + +#endif /* ZXDH_PCI_H */ diff --git a/drivers/net/zxdh/zxdh_queue.h b/drivers/net/zxdh/zxdh_queue.h new file mode 100644 index 0000000000..fd73f14e2d --- /dev/null +++ b/drivers/net/zxdh/zxdh_queue.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 ZTE Corporation + */ + +#ifndef ZXDH_QUEUE_H +#define ZXDH_QUEUE_H + +#include + +#include + +#include "zxdh_ethdev.h" +#include "zxdh_rxtx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** ring descriptors: 16 bytes. + * These can chain together via "next". + **/ +struct zxdh_vring_desc { + uint64_t addr; /* Address (guest-physical). */ + uint32_t len; /* Length. */ + uint16_t flags; /* The flags as indicated above. */ + uint16_t next; /* We chain unused descriptors via this. */ +} __rte_packed; + +struct zxdh_vring_avail { + uint16_t flags; + uint16_t idx; + uint16_t ring[]; +} __rte_packed; + +struct zxdh_vring_packed_desc { + uint64_t addr; + uint32_t len; + uint16_t id; + uint16_t flags; +} __rte_packed; + +struct zxdh_vring_packed_desc_event { + uint16_t desc_event_off_wrap; + uint16_t desc_event_flags; +} __rte_packed; + +struct zxdh_vring_packed { + uint32_t num; + struct zxdh_vring_packed_desc *desc; + struct zxdh_vring_packed_desc_event *driver; + struct zxdh_vring_packed_desc_event *device; +} __rte_packed; + +struct zxdh_vq_desc_extra { + void *cookie; + uint16_t ndescs; + uint16_t next; +} __rte_packed; + +struct zxdh_virtqueue { + struct zxdh_hw *hw; /**< zxdh_hw structure pointer. */ + struct { + /**< vring keeping descs and events */ + struct zxdh_vring_packed ring; + uint8_t used_wrap_counter; + uint8_t rsv; + uint16_t cached_flags; /**< cached flags for descs */ + uint16_t event_flags_shadow; + uint16_t rsv1; + } __rte_packed vq_packed; + uint16_t vq_used_cons_idx; /**< last consumed descriptor */ + uint16_t vq_nentries; /**< vring desc numbers */ + uint16_t vq_free_cnt; /**< num of desc available */ + uint16_t vq_avail_idx; /**< sync until needed */ + uint16_t vq_free_thresh; /**< free threshold */ + uint16_t rsv2; + + void *vq_ring_virt_mem; /**< linear address of vring*/ + uint32_t vq_ring_size; + + union { + struct zxdh_virtnet_rx rxq; + struct zxdh_virtnet_tx txq; + }; + + /** < physical address of vring, + * or virtual address for virtio_user. + **/ + rte_iova_t vq_ring_mem; + + /** + * Head of the free chain in the descriptor table. If + * there are no free descriptors, this will be set to + * VQ_RING_DESC_CHAIN_END. + **/ + uint16_t vq_desc_head_idx; + uint16_t vq_desc_tail_idx; + uint16_t vq_queue_index; /**< PCI queue index */ + uint16_t offset; /**< relative offset to obtain addr in mbuf */ + uint16_t *notify_addr; + struct rte_mbuf **sw_ring; /**< RX software ring. */ + struct zxdh_vq_desc_extra vq_descx[]; +} __rte_packed; + +#endif /* ZXDH_QUEUE_H */ diff --git a/drivers/net/zxdh/zxdh_rxtx.h b/drivers/net/zxdh/zxdh_rxtx.h new file mode 100644 index 0000000000..ccac7e7834 --- /dev/null +++ b/drivers/net/zxdh/zxdh_rxtx.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 ZTE Corporation + */ + +#ifndef ZXDH_RXTX_H +#define ZXDH_RXTX_H + +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct zxdh_virtnet_stats { + uint64_t packets; + uint64_t bytes; + uint64_t errors; + uint64_t multicast; + uint64_t broadcast; + uint64_t truncated_err; + uint64_t size_bins[8]; +}; + +struct zxdh_virtnet_rx { + struct zxdh_virtqueue *vq; + + /* dummy mbuf, for wraparound when processing RX ring. */ + struct rte_mbuf fake_mbuf; + + uint64_t mbuf_initializer; /* value to init mbufs. */ + struct rte_mempool *mpool; /* mempool for mbuf allocation */ + uint16_t queue_id; /* DPDK queue index. */ + uint16_t port_id; /* Device port identifier. */ + struct zxdh_virtnet_stats stats; + const struct rte_memzone *mz; /* mem zone to populate RX ring. */ +} __rte_packed; + +struct zxdh_virtnet_tx { + struct zxdh_virtqueue *vq; + const struct rte_memzone *virtio_net_hdr_mz; /* memzone to populate hdr. */ + rte_iova_t virtio_net_hdr_mem; /* hdr for each xmit packet */ + uint16_t queue_id; /* DPDK queue index. */ + uint16_t port_id; /* Device port identifier. */ + struct zxdh_virtnet_stats stats; + const struct rte_memzone *mz; /* mem zone to populate TX ring. */ +} __rte_packed; + +#endif /* ZXDH_RXTX_H */ From patchwork Wed Oct 30 09:01:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Junlong Wang X-Patchwork-Id: 147725 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 7753345C13; Wed, 30 Oct 2024 10:06:20 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 6676243397; Wed, 30 Oct 2024 10:06:20 +0100 (CET) Received: from mxhk.zte.com.cn (mxhk.zte.com.cn [63.216.63.40]) by mails.dpdk.org (Postfix) with ESMTP id 0336143384 for ; Wed, 30 Oct 2024 10:06:07 +0100 (CET) Received: from mse-fl1.zte.com.cn (unknown [10.5.228.132]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mxhk.zte.com.cn (FangMail) with ESMTPS id 4Xdh7G2y9Kz8RV6X for ; Wed, 30 Oct 2024 17:06:02 +0800 (CST) Received: from szxlzmapp01.zte.com.cn ([10.5.231.85]) by mse-fl1.zte.com.cn with SMTP id 49U95fhT007091 for ; Wed, 30 Oct 2024 17:05:41 +0800 (+08) (envelope-from wang.junlong1@zte.com.cn) Received: from localhost.localdomain (unknown [192.168.6.15]) by smtp (Zmail) with SMTP; Wed, 30 Oct 2024 17:05:44 +0800 X-Zmail-TransId: 3e816721f6e8004-b8d4d From: Junlong Wang To: dev@dpdk.org Cc: wang.yong19@zte.com.cn, Junlong Wang Subject: [PATCH v8 4/9] net/zxdh: add msg chan and msg hwlock init Date: Wed, 30 Oct 2024 17:01:11 +0800 Message-ID: <20241030090124.2540776-5-wang.junlong1@zte.com.cn> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241030090124.2540776-1-wang.junlong1@zte.com.cn> References: <20241022122042.2127065-2-wang.junlong1@zte.com.cn> <20241030090124.2540776-1-wang.junlong1@zte.com.cn> MIME-Version: 1.0 X-MAIL: mse-fl1.zte.com.cn 49U95fhT007091 X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 6721F6FA.001/4Xdh7G2y9Kz8RV6X X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add msg channel and hwlock init implementation. Signed-off-by: Junlong Wang --- drivers/net/zxdh/meson.build | 1 + drivers/net/zxdh/zxdh_ethdev.c | 15 +++ drivers/net/zxdh/zxdh_ethdev.h | 1 + drivers/net/zxdh/zxdh_msg.c | 161 +++++++++++++++++++++++++++++++++ drivers/net/zxdh/zxdh_msg.h | 67 ++++++++++++++ 5 files changed, 245 insertions(+) create mode 100644 drivers/net/zxdh/zxdh_msg.c create mode 100644 drivers/net/zxdh/zxdh_msg.h -- 2.27.0 diff --git a/drivers/net/zxdh/meson.build b/drivers/net/zxdh/meson.build index 7db4e7bc71..2e0c8fddae 100644 --- a/drivers/net/zxdh/meson.build +++ b/drivers/net/zxdh/meson.build @@ -16,4 +16,5 @@ endif sources = files( 'zxdh_ethdev.c', 'zxdh_pci.c', + 'zxdh_msg.c', ) diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c index 8877855965..2dcf144fc9 100644 --- a/drivers/net/zxdh/zxdh_ethdev.c +++ b/drivers/net/zxdh/zxdh_ethdev.c @@ -9,6 +9,7 @@ #include "zxdh_ethdev.h" #include "zxdh_logs.h" #include "zxdh_pci.h" +#include "zxdh_msg.h" struct zxdh_hw_internal zxdh_hw_internal[RTE_MAX_ETHPORTS]; @@ -83,9 +84,23 @@ static int zxdh_eth_dev_init(struct rte_eth_dev *eth_dev) if (ret < 0) goto err_zxdh_init; + ret = zxdh_msg_chan_init(); + if (ret != 0) { + PMD_INIT_LOG(ERR, "Failed to init bar msg chan"); + goto err_zxdh_init; + } + hw->msg_chan_init = 1; + + ret = zxdh_msg_chan_hwlock_init(eth_dev); + if (ret != 0) { + PMD_INIT_LOG(ERR, "zxdh_msg_chan_hwlock_init failed ret %d", ret); + goto err_zxdh_init; + } + return ret; err_zxdh_init: + zxdh_bar_msg_chan_exit(); rte_free(eth_dev->data->mac_addrs); eth_dev->data->mac_addrs = NULL; return ret; diff --git a/drivers/net/zxdh/zxdh_ethdev.h b/drivers/net/zxdh/zxdh_ethdev.h index 8be5af6aeb..5902704923 100644 --- a/drivers/net/zxdh/zxdh_ethdev.h +++ b/drivers/net/zxdh/zxdh_ethdev.h @@ -52,6 +52,7 @@ struct zxdh_hw { uint8_t duplex; uint8_t is_pf; + uint8_t msg_chan_init; }; #ifdef __cplusplus diff --git a/drivers/net/zxdh/zxdh_msg.c b/drivers/net/zxdh/zxdh_msg.c new file mode 100644 index 0000000000..9dcf99f1f7 --- /dev/null +++ b/drivers/net/zxdh/zxdh_msg.c @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 ZTE Corporation + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "zxdh_ethdev.h" +#include "zxdh_logs.h" +#include "zxdh_msg.h" + +#define ZXDH_REPS_INFO_FLAG_USABLE 0x00 +#define ZXDH_BAR_SEQID_NUM_MAX 256 + +#define ZXDH_PCIEID_IS_PF_MASK (0x0800) +#define ZXDH_PCIEID_PF_IDX_MASK (0x0700) +#define ZXDH_PCIEID_VF_IDX_MASK (0x00ff) +#define ZXDH_PCIEID_EP_IDX_MASK (0x7000) +/* PCIEID bit field offset */ +#define ZXDH_PCIEID_PF_IDX_OFFSET (8) +#define ZXDH_PCIEID_EP_IDX_OFFSET (12) + +#define ZXDH_MULTIPLY_BY_8(x) ((x) << 3) +#define ZXDH_MULTIPLY_BY_32(x) ((x) << 5) +#define ZXDH_MULTIPLY_BY_256(x) ((x) << 8) + +#define ZXDH_MAX_EP_NUM (4) +#define ZXDH_MAX_HARD_SPINLOCK_NUM (511) + +#define ZXDH_BAR0_SPINLOCK_OFFSET (0x4000) +#define ZXDH_FW_SHRD_OFFSET (0x5000) +#define ZXDH_FW_SHRD_INNER_HW_LABEL_PAT (0x800) +#define ZXDH_HW_LABEL_OFFSET \ + (ZXDH_FW_SHRD_OFFSET + ZXDH_FW_SHRD_INNER_HW_LABEL_PAT) + +struct zxdh_dev_stat { + bool is_mpf_scanned; + bool is_res_init; + int16_t dev_cnt; /* probe cnt */ +}; +struct zxdh_dev_stat g_dev_stat = {0}; + +struct zxdh_seqid_item { + void *reps_addr; + uint16_t id; + uint16_t buffer_len; + uint16_t flag; +}; + +struct zxdh_seqid_ring { + uint16_t cur_id; + rte_spinlock_t lock; + struct zxdh_seqid_item reps_info_tbl[ZXDH_BAR_SEQID_NUM_MAX]; +}; +struct zxdh_seqid_ring g_seqid_ring = {0}; + +static uint16_t pcie_id_to_hard_lock(uint16_t src_pcieid, uint8_t dst) +{ + uint16_t lock_id = 0; + uint16_t pf_idx = (src_pcieid & ZXDH_PCIEID_PF_IDX_MASK) >> ZXDH_PCIEID_PF_IDX_OFFSET; + uint16_t ep_idx = (src_pcieid & ZXDH_PCIEID_EP_IDX_MASK) >> ZXDH_PCIEID_EP_IDX_OFFSET; + + switch (dst) { + /* msg to risc */ + case ZXDH_MSG_CHAN_END_RISC: + lock_id = ZXDH_MULTIPLY_BY_8(ep_idx) + pf_idx; + break; + /* msg to pf/vf */ + case ZXDH_MSG_CHAN_END_VF: + case ZXDH_MSG_CHAN_END_PF: + lock_id = ZXDH_MULTIPLY_BY_8(ep_idx) + pf_idx + + ZXDH_MULTIPLY_BY_8(1 + ZXDH_MAX_EP_NUM); + break; + default: + lock_id = 0; + break; + } + if (lock_id >= ZXDH_MAX_HARD_SPINLOCK_NUM) + lock_id = 0; + + return lock_id; +} + +static void label_write(uint64_t label_lock_addr, uint32_t lock_id, uint16_t value) +{ + *(volatile uint16_t *)(label_lock_addr + lock_id * 2) = value; +} + +static void spinlock_write(uint64_t virt_lock_addr, uint32_t lock_id, uint8_t data) +{ + *(volatile uint8_t *)((uint64_t)virt_lock_addr + (uint64_t)lock_id) = data; +} + +static int32_t zxdh_spinlock_unlock(uint32_t virt_lock_id, uint64_t virt_addr, uint64_t label_addr) +{ + label_write((uint64_t)label_addr, virt_lock_id, 0); + spinlock_write(virt_addr, virt_lock_id, 0); + return 0; +} + +/** + * Fun: PF init hard_spinlock addr + */ +static int bar_chan_pf_init_spinlock(uint16_t pcie_id, uint64_t bar_base_addr) +{ + int lock_id = pcie_id_to_hard_lock(pcie_id, ZXDH_MSG_CHAN_END_RISC); + + zxdh_spinlock_unlock(lock_id, bar_base_addr + ZXDH_BAR0_SPINLOCK_OFFSET, + bar_base_addr + ZXDH_HW_LABEL_OFFSET); + lock_id = pcie_id_to_hard_lock(pcie_id, ZXDH_MSG_CHAN_END_VF); + zxdh_spinlock_unlock(lock_id, bar_base_addr + ZXDH_BAR0_SPINLOCK_OFFSET, + bar_base_addr + ZXDH_HW_LABEL_OFFSET); + return 0; +} + +int zxdh_msg_chan_hwlock_init(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + + if (!hw->is_pf) + return 0; + return bar_chan_pf_init_spinlock(hw->pcie_id, (uint64_t)(hw->bar_addr[ZXDH_BAR0_INDEX])); +} + +static rte_spinlock_t chan_lock; +int zxdh_msg_chan_init(void) +{ + uint16_t seq_id = 0; + + g_dev_stat.dev_cnt++; + if (g_dev_stat.is_res_init) + return ZXDH_BAR_MSG_OK; + + rte_spinlock_init(&chan_lock); + g_seqid_ring.cur_id = 0; + rte_spinlock_init(&g_seqid_ring.lock); + + for (seq_id = 0; seq_id < ZXDH_BAR_SEQID_NUM_MAX; seq_id++) { + struct zxdh_seqid_item *reps_info = &g_seqid_ring.reps_info_tbl[seq_id]; + + reps_info->id = seq_id; + reps_info->flag = ZXDH_REPS_INFO_FLAG_USABLE; + } + g_dev_stat.is_res_init = true; + return ZXDH_BAR_MSG_OK; +} + +int zxdh_bar_msg_chan_exit(void) +{ + if (!g_dev_stat.is_res_init || (--g_dev_stat.dev_cnt > 0)) + return ZXDH_BAR_MSG_OK; + + g_dev_stat.is_res_init = false; + return ZXDH_BAR_MSG_OK; +} diff --git a/drivers/net/zxdh/zxdh_msg.h b/drivers/net/zxdh/zxdh_msg.h new file mode 100644 index 0000000000..a0b46c900a --- /dev/null +++ b/drivers/net/zxdh/zxdh_msg.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 ZTE Corporation + */ + +#ifndef ZXDH_MSG_H +#define ZXDH_MSG_H + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZXDH_BAR0_INDEX 0 + +enum ZXDH_DRIVER_TYPE { + ZXDH_MSG_CHAN_END_MPF = 0, + ZXDH_MSG_CHAN_END_PF, + ZXDH_MSG_CHAN_END_VF, + ZXDH_MSG_CHAN_END_RISC, +}; + +enum ZXDH_BAR_MSG_RTN { + ZXDH_BAR_MSG_OK = 0, + ZXDH_BAR_MSG_ERR_MSGID, + ZXDH_BAR_MSG_ERR_NULL, + ZXDH_BAR_MSG_ERR_TYPE, /* Message type exception */ + ZXDH_BAR_MSG_ERR_MODULE, /* Module ID exception */ + ZXDH_BAR_MSG_ERR_BODY_NULL, /* Message body exception */ + ZXDH_BAR_MSG_ERR_LEN, /* Message length exception */ + ZXDH_BAR_MSG_ERR_TIME_OUT, /* Message sending length too long */ + ZXDH_BAR_MSG_ERR_NOT_READY, /* Abnormal message sending conditions*/ + ZXDH_BAR_MEG_ERR_NULL_FUNC, /* Empty receive processing function pointer*/ + ZXDH_BAR_MSG_ERR_REPEAT_REGISTER, /* Module duplicate registration*/ + ZXDH_BAR_MSG_ERR_UNGISTER, /* Repeated deregistration*/ + /** + * The sending interface parameter boundary structure pointer is empty + */ + ZXDH_BAR_MSG_ERR_NULL_PARA, + ZXDH_BAR_MSG_ERR_REPSBUFF_LEN, /* The length of reps_buff is too short*/ + /** + * Unable to find the corresponding message processing function for this module + */ + ZXDH_BAR_MSG_ERR_MODULE_NOEXIST, + /** + * The virtual address in the parameters passed in by the sending interface is empty + */ + ZXDH_BAR_MSG_ERR_VIRTADDR_NULL, + ZXDH_BAR_MSG_ERR_REPLY, /* sync msg resp_error */ + ZXDH_BAR_MSG_ERR_MPF_NOT_SCANNED, + ZXDH_BAR_MSG_ERR_KERNEL_READY, + ZXDH_BAR_MSG_ERR_USR_RET_ERR, + ZXDH_BAR_MSG_ERR_ERR_PCIEID, + ZXDH_BAR_MSG_ERR_SOCKET, /* netlink sockte err */ +}; + +int zxdh_msg_chan_init(void); +int zxdh_bar_msg_chan_exit(void); +int zxdh_msg_chan_hwlock_init(struct rte_eth_dev *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* ZXDH_MSG_H */ From patchwork Wed Oct 30 09:01:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Junlong Wang X-Patchwork-Id: 147729 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 63D8A45C13; Wed, 30 Oct 2024 10:06:48 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 28EEC433B6; Wed, 30 Oct 2024 10:06:25 +0100 (CET) Received: from mxhk.zte.com.cn (mxhk.zte.com.cn [63.216.63.35]) by mails.dpdk.org (Postfix) with ESMTP id 2477A43399 for ; Wed, 30 Oct 2024 10:06:12 +0100 (CET) Received: from mse-fl1.zte.com.cn (unknown [10.5.228.132]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mxhk.zte.com.cn (FangMail) with ESMTPS id 4Xdh7L0nX6z4xthH for ; Wed, 30 Oct 2024 17:06:06 +0800 (CST) Received: from szxlzmapp04.zte.com.cn ([10.5.231.166]) by mse-fl1.zte.com.cn with SMTP id 49U95g8n007093 for ; Wed, 30 Oct 2024 17:05:42 +0800 (+08) (envelope-from wang.junlong1@zte.com.cn) Received: from localhost.localdomain (unknown [192.168.6.15]) by smtp (Zmail) with SMTP; Wed, 30 Oct 2024 17:05:45 +0800 X-Zmail-TransId: 3e816721f6e9004-b8d4f From: Junlong Wang To: dev@dpdk.org Cc: wang.yong19@zte.com.cn, Junlong Wang Subject: [PATCH v8 5/9] net/zxdh: add msg chan enable implementation Date: Wed, 30 Oct 2024 17:01:12 +0800 Message-ID: <20241030090124.2540776-6-wang.junlong1@zte.com.cn> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241030090124.2540776-1-wang.junlong1@zte.com.cn> References: <20241022122042.2127065-2-wang.junlong1@zte.com.cn> <20241030090124.2540776-1-wang.junlong1@zte.com.cn> MIME-Version: 1.0 X-MAIL: mse-fl1.zte.com.cn 49U95g8n007093 X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 6721F6FE.003/4Xdh7L0nX6z4xthH X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add msg chan enable implementation to support send msg to backend(device side) get infos. Signed-off-by: Junlong Wang --- drivers/net/zxdh/zxdh_ethdev.c | 6 + drivers/net/zxdh/zxdh_ethdev.h | 12 + drivers/net/zxdh/zxdh_msg.c | 641 ++++++++++++++++++++++++++++++++- drivers/net/zxdh/zxdh_msg.h | 129 +++++++ 4 files changed, 785 insertions(+), 3 deletions(-) -- 2.27.0 diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c index 2dcf144fc9..a729344288 100644 --- a/drivers/net/zxdh/zxdh_ethdev.c +++ b/drivers/net/zxdh/zxdh_ethdev.c @@ -97,6 +97,12 @@ static int zxdh_eth_dev_init(struct rte_eth_dev *eth_dev) goto err_zxdh_init; } + ret = zxdh_msg_chan_enable(eth_dev); + if (ret != 0) { + PMD_INIT_LOG(ERR, "zxdh_msg_bar_chan_enable failed ret %d", ret); + goto err_zxdh_init; + } + return ret; err_zxdh_init: diff --git a/drivers/net/zxdh/zxdh_ethdev.h b/drivers/net/zxdh/zxdh_ethdev.h index 5902704923..bed1334690 100644 --- a/drivers/net/zxdh/zxdh_ethdev.h +++ b/drivers/net/zxdh/zxdh_ethdev.h @@ -29,10 +29,22 @@ extern "C" { #define ZXDH_RX_QUEUES_MAX 128U #define ZXDH_TX_QUEUES_MAX 128U +union zxdh_virport_num { + uint16_t vport; + struct { + uint16_t vfid:8; + uint16_t pfid:3; + uint16_t vf_flag:1; + uint16_t epid:3; + uint16_t direct_flag:1; + }; +}; + struct zxdh_hw { struct rte_eth_dev *eth_dev; struct zxdh_pci_common_cfg *common_cfg; struct zxdh_net_config *dev_cfg; + union zxdh_virport_num vport; uint64_t bar_addr[ZXDH_NUM_BARS]; uint64_t host_features; diff --git a/drivers/net/zxdh/zxdh_msg.c b/drivers/net/zxdh/zxdh_msg.c index 9dcf99f1f7..1bf72a9b7c 100644 --- a/drivers/net/zxdh/zxdh_msg.c +++ b/drivers/net/zxdh/zxdh_msg.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include "zxdh_ethdev.h" @@ -17,6 +16,7 @@ #define ZXDH_REPS_INFO_FLAG_USABLE 0x00 #define ZXDH_BAR_SEQID_NUM_MAX 256 +#define ZXDH_REPS_INFO_FLAG_USED 0xa0 #define ZXDH_PCIEID_IS_PF_MASK (0x0800) #define ZXDH_PCIEID_PF_IDX_MASK (0x0700) @@ -33,15 +33,88 @@ #define ZXDH_MAX_EP_NUM (4) #define ZXDH_MAX_HARD_SPINLOCK_NUM (511) +#define LOCK_PRIMARY_ID_MASK (0x8000) +/* bar offset */ +#define ZXDH_BAR0_CHAN_RISC_OFFSET (0x2000) +#define ZXDH_BAR0_CHAN_PFVF_OFFSET (0x3000) #define ZXDH_BAR0_SPINLOCK_OFFSET (0x4000) #define ZXDH_FW_SHRD_OFFSET (0x5000) #define ZXDH_FW_SHRD_INNER_HW_LABEL_PAT (0x800) #define ZXDH_HW_LABEL_OFFSET \ (ZXDH_FW_SHRD_OFFSET + ZXDH_FW_SHRD_INNER_HW_LABEL_PAT) +#define ZXDH_CHAN_RISC_SPINLOCK_OFFSET \ + (ZXDH_BAR0_SPINLOCK_OFFSET - ZXDH_BAR0_CHAN_RISC_OFFSET) +#define ZXDH_CHAN_PFVF_SPINLOCK_OFFSET \ + (ZXDH_BAR0_SPINLOCK_OFFSET - ZXDH_BAR0_CHAN_PFVF_OFFSET) +#define ZXDH_CHAN_RISC_LABEL_OFFSET \ + (ZXDH_HW_LABEL_OFFSET - ZXDH_BAR0_CHAN_RISC_OFFSET) +#define ZXDH_CHAN_PFVF_LABEL_OFFSET \ + (ZXDH_HW_LABEL_OFFSET - ZXDH_BAR0_CHAN_PFVF_OFFSET) + +#define ZXDH_REPS_HEADER_LEN_OFFSET 1 +#define ZXDH_REPS_HEADER_PAYLOAD_OFFSET 4 +#define ZXDH_REPS_HEADER_REPLYED 0xff + +#define ZXDH_BAR_MSG_CHAN_USABLE 0 +#define ZXDH_BAR_MSG_CHAN_USED 1 + +#define ZXDH_BAR_MSG_POL_MASK (0x10) +#define ZXDH_BAR_MSG_POL_OFFSET (4) + +#define ZXDH_BAR_ALIGN_WORD_MASK 0xfffffffc +#define ZXDH_BAR_MSG_VALID_MASK 1 +#define ZXDH_BAR_MSG_VALID_OFFSET 0 + +#define ZXDH_BAR_PF_NUM 7 +#define ZXDH_BAR_VF_NUM 256 +#define ZXDH_BAR_INDEX_PF_TO_VF 0 +#define ZXDH_BAR_INDEX_MPF_TO_MPF 0xff +#define ZXDH_BAR_INDEX_MPF_TO_PFVF 0 +#define ZXDH_BAR_INDEX_PFVF_TO_MPF 0 + +#define ZXDH_MAX_HARD_SPINLOCK_ASK_TIMES (1000) +#define ZXDH_SPINLOCK_POLLING_SPAN_US (100) + +#define ZXDH_BAR_MSG_SRC_NUM 3 +#define ZXDH_BAR_MSG_SRC_MPF 0 +#define ZXDH_BAR_MSG_SRC_PF 1 +#define ZXDH_BAR_MSG_SRC_VF 2 +#define ZXDH_BAR_MSG_SRC_ERR 0xff +#define ZXDH_BAR_MSG_DST_NUM 3 +#define ZXDH_BAR_MSG_DST_RISC 0 +#define ZXDH_BAR_MSG_DST_MPF 2 +#define ZXDH_BAR_MSG_DST_PFVF 1 +#define ZXDH_BAR_MSG_DST_ERR 0xff + +#define ZXDH_LOCK_TYPE_HARD (1) +#define ZXDH_LOCK_TYPE_SOFT (0) +#define ZXDH_BAR_INDEX_TO_RISC 0 + +#define ZXDH_BAR_CHAN_INDEX_SEND 0 +#define ZXDH_BAR_CHAN_INDEX_RECV 1 + +uint8_t subchan_id_tbl[ZXDH_BAR_MSG_SRC_NUM][ZXDH_BAR_MSG_DST_NUM] = { + {ZXDH_BAR_CHAN_INDEX_SEND, ZXDH_BAR_CHAN_INDEX_SEND, ZXDH_BAR_CHAN_INDEX_SEND}, + {ZXDH_BAR_CHAN_INDEX_SEND, ZXDH_BAR_CHAN_INDEX_SEND, ZXDH_BAR_CHAN_INDEX_RECV}, + {ZXDH_BAR_CHAN_INDEX_SEND, ZXDH_BAR_CHAN_INDEX_RECV, ZXDH_BAR_CHAN_INDEX_RECV} +}; + +uint8_t chan_id_tbl[ZXDH_BAR_MSG_SRC_NUM][ZXDH_BAR_MSG_DST_NUM] = { + {ZXDH_BAR_INDEX_TO_RISC, ZXDH_BAR_INDEX_MPF_TO_PFVF, ZXDH_BAR_INDEX_MPF_TO_MPF}, + {ZXDH_BAR_INDEX_TO_RISC, ZXDH_BAR_INDEX_PF_TO_VF, ZXDH_BAR_INDEX_PFVF_TO_MPF}, + {ZXDH_BAR_INDEX_TO_RISC, ZXDH_BAR_INDEX_PF_TO_VF, ZXDH_BAR_INDEX_PFVF_TO_MPF} +}; + +uint8_t lock_type_tbl[ZXDH_BAR_MSG_SRC_NUM][ZXDH_BAR_MSG_DST_NUM] = { + {ZXDH_LOCK_TYPE_HARD, ZXDH_LOCK_TYPE_HARD, ZXDH_LOCK_TYPE_HARD}, + {ZXDH_LOCK_TYPE_SOFT, ZXDH_LOCK_TYPE_SOFT, ZXDH_LOCK_TYPE_HARD}, + {ZXDH_LOCK_TYPE_HARD, ZXDH_LOCK_TYPE_HARD, ZXDH_LOCK_TYPE_HARD} +}; + struct zxdh_dev_stat { - bool is_mpf_scanned; - bool is_res_init; + uint8_t is_mpf_scanned; + uint8_t is_res_init; int16_t dev_cnt; /* probe cnt */ }; struct zxdh_dev_stat g_dev_stat = {0}; @@ -97,6 +170,33 @@ static void spinlock_write(uint64_t virt_lock_addr, uint32_t lock_id, uint8_t da *(volatile uint8_t *)((uint64_t)virt_lock_addr + (uint64_t)lock_id) = data; } +static uint8_t spinlock_read(uint64_t virt_lock_addr, uint32_t lock_id) +{ + return *(volatile uint8_t *)((uint64_t)virt_lock_addr + (uint64_t)lock_id); +} + +static int32_t zxdh_spinlock_lock(uint32_t virt_lock_id, uint64_t virt_addr, + uint64_t label_addr, uint16_t primary_id) +{ + uint32_t lock_rd_cnt = 0; + + do { + /* read to lock */ + uint8_t spl_val = spinlock_read(virt_addr, virt_lock_id); + + if (spl_val == 0) { + label_write((uint64_t)label_addr, virt_lock_id, primary_id); + break; + } + rte_delay_us_block(ZXDH_SPINLOCK_POLLING_SPAN_US); + lock_rd_cnt++; + } while (lock_rd_cnt < ZXDH_MAX_HARD_SPINLOCK_ASK_TIMES); + if (lock_rd_cnt >= ZXDH_MAX_HARD_SPINLOCK_ASK_TIMES) + return -1; + + return 0; +} + static int32_t zxdh_spinlock_unlock(uint32_t virt_lock_id, uint64_t virt_addr, uint64_t label_addr) { label_write((uint64_t)label_addr, virt_lock_id, 0); @@ -159,3 +259,538 @@ int zxdh_bar_msg_chan_exit(void) g_dev_stat.is_res_init = false; return ZXDH_BAR_MSG_OK; } + +static int zxdh_bar_chan_msgid_allocate(uint16_t *msgid) +{ + struct zxdh_seqid_item *seqid_reps_info = NULL; + + rte_spinlock_lock(&g_seqid_ring.lock); + uint16_t g_id = g_seqid_ring.cur_id; + uint16_t count = 0; + int rc = 0; + + do { + count++; + ++g_id; + g_id %= ZXDH_BAR_SEQID_NUM_MAX; + seqid_reps_info = &g_seqid_ring.reps_info_tbl[g_id]; + } while ((seqid_reps_info->flag != ZXDH_REPS_INFO_FLAG_USABLE) && + (count < ZXDH_BAR_SEQID_NUM_MAX)); + + if (count >= ZXDH_BAR_SEQID_NUM_MAX) { + rc = -1; + goto out; + } + seqid_reps_info->flag = ZXDH_REPS_INFO_FLAG_USED; + g_seqid_ring.cur_id = g_id; + *msgid = g_id; + rc = ZXDH_BAR_MSG_OK; + +out: + rte_spinlock_unlock(&g_seqid_ring.lock); + return rc; +} + +static uint16_t zxdh_bar_chan_save_recv_info(struct zxdh_msg_recviver_mem *result, uint16_t *msg_id) +{ + int ret = zxdh_bar_chan_msgid_allocate(msg_id); + + if (ret != ZXDH_BAR_MSG_OK) + return ZXDH_BAR_MSG_ERR_MSGID; + + PMD_MSG_LOG(DEBUG, "allocate msg_id: %u", *msg_id); + struct zxdh_seqid_item *reps_info = &g_seqid_ring.reps_info_tbl[*msg_id]; + + reps_info->reps_addr = result->recv_buffer; + reps_info->buffer_len = result->buffer_len; + return ZXDH_BAR_MSG_OK; +} + +static uint8_t zxdh_bar_msg_src_index_trans(uint8_t src) +{ + uint8_t src_index = 0; + + switch (src) { + case ZXDH_MSG_CHAN_END_MPF: + src_index = ZXDH_BAR_MSG_SRC_MPF; + break; + case ZXDH_MSG_CHAN_END_PF: + src_index = ZXDH_BAR_MSG_SRC_PF; + break; + case ZXDH_MSG_CHAN_END_VF: + src_index = ZXDH_BAR_MSG_SRC_VF; + break; + default: + src_index = ZXDH_BAR_MSG_SRC_ERR; + break; + } + return src_index; +} + +static uint8_t zxdh_bar_msg_dst_index_trans(uint8_t dst) +{ + uint8_t dst_index = 0; + + switch (dst) { + case ZXDH_MSG_CHAN_END_MPF: + dst_index = ZXDH_BAR_MSG_DST_MPF; + break; + case ZXDH_MSG_CHAN_END_PF: + dst_index = ZXDH_BAR_MSG_DST_PFVF; + break; + case ZXDH_MSG_CHAN_END_VF: + dst_index = ZXDH_BAR_MSG_DST_PFVF; + break; + case ZXDH_MSG_CHAN_END_RISC: + dst_index = ZXDH_BAR_MSG_DST_RISC; + break; + default: + dst_index = ZXDH_BAR_MSG_SRC_ERR; + break; + } + return dst_index; +} + +static int zxdh_bar_chan_send_para_check(struct zxdh_pci_bar_msg *in, + struct zxdh_msg_recviver_mem *result) +{ + uint8_t src_index = 0; + uint8_t dst_index = 0; + + if (in == NULL || result == NULL) { + PMD_MSG_LOG(ERR, "send para ERR: null para."); + return ZXDH_BAR_MSG_ERR_NULL_PARA; + } + src_index = zxdh_bar_msg_src_index_trans(in->src); + dst_index = zxdh_bar_msg_dst_index_trans(in->dst); + + if (src_index == ZXDH_BAR_MSG_SRC_ERR || dst_index == ZXDH_BAR_MSG_DST_ERR) { + PMD_MSG_LOG(ERR, "send para ERR: chan doesn't exist."); + return ZXDH_BAR_MSG_ERR_TYPE; + } + if (in->module_id >= ZXDH_BAR_MSG_MODULE_NUM) { + PMD_MSG_LOG(ERR, "send para ERR: invalid module_id: %d.", in->module_id); + return ZXDH_BAR_MSG_ERR_MODULE; + } + if (in->payload_addr == NULL) { + PMD_MSG_LOG(ERR, "send para ERR: null message."); + return ZXDH_BAR_MSG_ERR_BODY_NULL; + } + if (in->payload_len > ZXDH_BAR_MSG_PAYLOAD_MAX_LEN) { + PMD_MSG_LOG(ERR, "send para ERR: len %d is too long.", in->payload_len); + return ZXDH_BAR_MSG_ERR_LEN; + } + if (in->virt_addr == 0 || result->recv_buffer == NULL) { + PMD_MSG_LOG(ERR, "send para ERR: virt_addr or recv_buffer is NULL."); + return ZXDH_BAR_MSG_ERR_VIRTADDR_NULL; + } + if (result->buffer_len < ZXDH_REPS_HEADER_PAYLOAD_OFFSET) + PMD_MSG_LOG(ERR, "recv buffer len is short than minimal 4 bytes"); + + return ZXDH_BAR_MSG_OK; +} + +static uint64_t zxdh_subchan_addr_cal(uint64_t virt_addr, uint8_t chan_id, uint8_t subchan_id) +{ + return virt_addr + (2 * chan_id + subchan_id) * ZXDH_BAR_MSG_ADDR_CHAN_INTERVAL; +} + +static uint16_t zxdh_bar_chan_subchan_addr_get(struct zxdh_pci_bar_msg *in, uint64_t *subchan_addr) +{ + uint8_t src_index = zxdh_bar_msg_src_index_trans(in->src); + uint8_t dst_index = zxdh_bar_msg_dst_index_trans(in->dst); + uint16_t chan_id = chan_id_tbl[src_index][dst_index]; + uint16_t subchan_id = subchan_id_tbl[src_index][dst_index]; + + *subchan_addr = zxdh_subchan_addr_cal(in->virt_addr, chan_id, subchan_id); + return ZXDH_BAR_MSG_OK; +} + +static int zxdh_bar_hard_lock(uint16_t src_pcieid, uint8_t dst, uint64_t virt_addr) +{ + int ret = 0; + uint16_t lockid = pcie_id_to_hard_lock(src_pcieid, dst); + + PMD_MSG_LOG(DEBUG, "dev pcieid: 0x%x lock, get hardlockid: %u", src_pcieid, lockid); + if (dst == ZXDH_MSG_CHAN_END_RISC) + ret = zxdh_spinlock_lock(lockid, virt_addr + ZXDH_CHAN_RISC_SPINLOCK_OFFSET, + virt_addr + ZXDH_CHAN_RISC_LABEL_OFFSET, + src_pcieid | LOCK_PRIMARY_ID_MASK); + else + ret = zxdh_spinlock_lock(lockid, virt_addr + ZXDH_CHAN_PFVF_SPINLOCK_OFFSET, + virt_addr + ZXDH_CHAN_PFVF_LABEL_OFFSET, + src_pcieid | LOCK_PRIMARY_ID_MASK); + + return ret; +} + +static void zxdh_bar_hard_unlock(uint16_t src_pcieid, uint8_t dst, uint64_t virt_addr) +{ + uint16_t lockid = pcie_id_to_hard_lock(src_pcieid, dst); + + PMD_MSG_LOG(DEBUG, "dev pcieid: 0x%x unlock, get hardlockid: %u", src_pcieid, lockid); + if (dst == ZXDH_MSG_CHAN_END_RISC) + zxdh_spinlock_unlock(lockid, virt_addr + ZXDH_CHAN_RISC_SPINLOCK_OFFSET, + virt_addr + ZXDH_CHAN_RISC_LABEL_OFFSET); + else + zxdh_spinlock_unlock(lockid, virt_addr + ZXDH_CHAN_PFVF_SPINLOCK_OFFSET, + virt_addr + ZXDH_CHAN_PFVF_LABEL_OFFSET); +} + +static int zxdh_bar_chan_lock(uint8_t src, uint8_t dst, uint16_t src_pcieid, uint64_t virt_addr) +{ + int ret = 0; + uint8_t src_index = zxdh_bar_msg_src_index_trans(src); + uint8_t dst_index = zxdh_bar_msg_dst_index_trans(dst); + + if (src_index == ZXDH_BAR_MSG_SRC_ERR || dst_index == ZXDH_BAR_MSG_DST_ERR) { + PMD_MSG_LOG(ERR, "lock ERR: chan doesn't exist."); + return ZXDH_BAR_MSG_ERR_TYPE; + } + + ret = zxdh_bar_hard_lock(src_pcieid, dst, virt_addr); + if (ret != 0) + PMD_MSG_LOG(ERR, "dev: 0x%x failed to lock.", src_pcieid); + + return ret; +} + +static int zxdh_bar_chan_unlock(uint8_t src, uint8_t dst, uint16_t src_pcieid, uint64_t virt_addr) +{ + uint8_t src_index = zxdh_bar_msg_src_index_trans(src); + uint8_t dst_index = zxdh_bar_msg_dst_index_trans(dst); + + if (src_index == ZXDH_BAR_MSG_SRC_ERR || dst_index == ZXDH_BAR_MSG_DST_ERR) { + PMD_MSG_LOG(ERR, "unlock ERR: chan doesn't exist."); + return ZXDH_BAR_MSG_ERR_TYPE; + } + + zxdh_bar_hard_unlock(src_pcieid, dst, virt_addr); + + return ZXDH_BAR_MSG_OK; +} + +static void zxdh_bar_chan_msgid_free(uint16_t msg_id) +{ + struct zxdh_seqid_item *seqid_reps_info = &g_seqid_ring.reps_info_tbl[msg_id]; + + rte_spinlock_lock(&g_seqid_ring.lock); + seqid_reps_info->flag = ZXDH_REPS_INFO_FLAG_USABLE; + PMD_MSG_LOG(DEBUG, "free msg_id: %u", msg_id); + rte_spinlock_unlock(&g_seqid_ring.lock); +} + +static int zxdh_bar_chan_reg_write(uint64_t subchan_addr, uint32_t offset, uint32_t data) +{ + uint32_t algin_offset = (offset & ZXDH_BAR_ALIGN_WORD_MASK); + + if (unlikely(algin_offset >= ZXDH_BAR_MSG_ADDR_CHAN_INTERVAL)) { + PMD_MSG_LOG(ERR, "algin_offset exceeds channel size!"); + return -1; + } + *(uint32_t *)(subchan_addr + algin_offset) = data; + return 0; +} + +static int zxdh_bar_chan_reg_read(uint64_t subchan_addr, uint32_t offset, uint32_t *pdata) +{ + uint32_t algin_offset = (offset & ZXDH_BAR_ALIGN_WORD_MASK); + + if (unlikely(algin_offset >= ZXDH_BAR_MSG_ADDR_CHAN_INTERVAL)) { + PMD_MSG_LOG(ERR, "algin_offset exceeds channel size!"); + return -1; + } + *pdata = *(uint32_t *)(subchan_addr + algin_offset); + return 0; +} + +static uint16_t zxdh_bar_chan_msg_header_set(uint64_t subchan_addr, + struct zxdh_bar_msg_header *msg_header) +{ + uint32_t *data = (uint32_t *)msg_header; + uint16_t idx; + + for (idx = 0; idx < (ZXDH_BAR_MSG_PLAYLOAD_OFFSET >> 2); idx++) + zxdh_bar_chan_reg_write(subchan_addr, idx * 4, *(data + idx)); + + return ZXDH_BAR_MSG_OK; +} + +static uint16_t zxdh_bar_chan_msg_header_get(uint64_t subchan_addr, + struct zxdh_bar_msg_header *msg_header) +{ + uint32_t *data = (uint32_t *)msg_header; + uint16_t idx; + + for (idx = 0; idx < (ZXDH_BAR_MSG_PLAYLOAD_OFFSET >> 2); idx++) + zxdh_bar_chan_reg_read(subchan_addr, idx * 4, data + idx); + + return ZXDH_BAR_MSG_OK; +} + +static uint16_t zxdh_bar_chan_msg_payload_set(uint64_t subchan_addr, uint8_t *msg, uint16_t len) +{ + uint32_t *data = (uint32_t *)msg; + uint32_t count = (len >> 2); + uint32_t ix; + + for (ix = 0; ix < count; ix++) + zxdh_bar_chan_reg_write(subchan_addr, 4 * ix + + ZXDH_BAR_MSG_PLAYLOAD_OFFSET, *(data + ix)); + + uint32_t remain = (len & 0x3); + + if (remain) { + uint32_t remain_data = 0; + + for (ix = 0; ix < remain; ix++) + remain_data |= *((uint8_t *)(msg + len - remain + ix)) << (8 * ix); + + zxdh_bar_chan_reg_write(subchan_addr, 4 * count + + ZXDH_BAR_MSG_PLAYLOAD_OFFSET, remain_data); + } + return ZXDH_BAR_MSG_OK; +} + +static uint16_t zxdh_bar_chan_msg_payload_get(uint64_t subchan_addr, uint8_t *msg, uint16_t len) +{ + uint32_t *data = (uint32_t *)msg; + uint32_t count = (len >> 2); + uint32_t ix; + + for (ix = 0; ix < count; ix++) + zxdh_bar_chan_reg_read(subchan_addr, 4 * ix + + ZXDH_BAR_MSG_PLAYLOAD_OFFSET, (data + ix)); + + uint32_t remain = (len & 0x3); + + if (remain) { + uint32_t remain_data = 0; + + zxdh_bar_chan_reg_read(subchan_addr, 4 * count + + ZXDH_BAR_MSG_PLAYLOAD_OFFSET, &remain_data); + for (ix = 0; ix < remain; ix++) + *((uint8_t *)(msg + (len - remain + ix))) = remain_data >> (8 * ix); + } + return ZXDH_BAR_MSG_OK; +} + +static uint16_t zxdh_bar_chan_msg_valid_set(uint64_t subchan_addr, uint8_t valid_label) +{ + uint32_t data; + + zxdh_bar_chan_reg_read(subchan_addr, ZXDH_BAR_MSG_VALID_OFFSET, &data); + data &= (~ZXDH_BAR_MSG_VALID_MASK); + data |= (uint32_t)valid_label; + zxdh_bar_chan_reg_write(subchan_addr, ZXDH_BAR_MSG_VALID_OFFSET, data); + return ZXDH_BAR_MSG_OK; +} + +static uint8_t temp_msg[ZXDH_BAR_MSG_ADDR_CHAN_INTERVAL]; +static uint16_t zxdh_bar_chan_msg_send(uint64_t subchan_addr, + void *payload_addr, + uint16_t payload_len, + struct zxdh_bar_msg_header *msg_header) +{ + uint16_t ret = 0; + ret = zxdh_bar_chan_msg_header_set(subchan_addr, msg_header); + + ret = zxdh_bar_chan_msg_header_get(subchan_addr, + (struct zxdh_bar_msg_header *)temp_msg); + + ret = zxdh_bar_chan_msg_payload_set(subchan_addr, + (uint8_t *)(payload_addr), payload_len); + + ret = zxdh_bar_chan_msg_payload_get(subchan_addr, + temp_msg, payload_len); + + ret = zxdh_bar_chan_msg_valid_set(subchan_addr, ZXDH_BAR_MSG_CHAN_USED); + return ret; +} + +static uint16_t zxdh_bar_msg_valid_stat_get(uint64_t subchan_addr) +{ + uint32_t data; + + zxdh_bar_chan_reg_read(subchan_addr, ZXDH_BAR_MSG_VALID_OFFSET, &data); + if (ZXDH_BAR_MSG_CHAN_USABLE == (data & ZXDH_BAR_MSG_VALID_MASK)) + return ZXDH_BAR_MSG_CHAN_USABLE; + + return ZXDH_BAR_MSG_CHAN_USED; +} + +static uint16_t zxdh_bar_chan_msg_poltag_set(uint64_t subchan_addr, uint8_t label) +{ + uint32_t data; + + zxdh_bar_chan_reg_read(subchan_addr, ZXDH_BAR_MSG_VALID_OFFSET, &data); + data &= (~(uint32_t)ZXDH_BAR_MSG_POL_MASK); + data |= ((uint32_t)label << ZXDH_BAR_MSG_POL_OFFSET); + zxdh_bar_chan_reg_write(subchan_addr, ZXDH_BAR_MSG_VALID_OFFSET, data); + return ZXDH_BAR_MSG_OK; +} + +static uint16_t zxdh_bar_chan_sync_msg_reps_get(uint64_t subchan_addr, + uint64_t recv_buffer, uint16_t buffer_len) +{ + struct zxdh_bar_msg_header msg_header = {0}; + uint16_t msg_id = 0; + uint16_t msg_len = 0; + + zxdh_bar_chan_msg_header_get(subchan_addr, &msg_header); + msg_id = msg_header.msg_id; + struct zxdh_seqid_item *reps_info = &g_seqid_ring.reps_info_tbl[msg_id]; + + if (reps_info->flag != ZXDH_REPS_INFO_FLAG_USED) { + PMD_MSG_LOG(ERR, "msg_id %u unused", msg_id); + return ZXDH_BAR_MSG_ERR_REPLY; + } + msg_len = msg_header.len; + + if (msg_len > buffer_len - 4) { + PMD_MSG_LOG(ERR, "recv buffer len is: %u, but reply msg len is: %u", + buffer_len, msg_len + 4); + return ZXDH_BAR_MSG_ERR_REPSBUFF_LEN; + } + uint8_t *recv_msg = (uint8_t *)recv_buffer; + + zxdh_bar_chan_msg_payload_get(subchan_addr, + recv_msg + ZXDH_REPS_HEADER_PAYLOAD_OFFSET, msg_len); + *(uint16_t *)(recv_msg + ZXDH_REPS_HEADER_LEN_OFFSET) = msg_len; + *recv_msg = ZXDH_REPS_HEADER_REPLYED; /* set reps's valid */ + return ZXDH_BAR_MSG_OK; +} + +int zxdh_bar_chan_sync_msg_send(struct zxdh_pci_bar_msg *in, struct zxdh_msg_recviver_mem *result) +{ + struct zxdh_bar_msg_header msg_header = {0}; + uint16_t seq_id = 0; + uint64_t subchan_addr = 0; + uint32_t time_out_cnt = 0; + uint16_t valid = 0; + int ret = 0; + + ret = zxdh_bar_chan_send_para_check(in, result); + if (ret != ZXDH_BAR_MSG_OK) + goto exit; + + ret = zxdh_bar_chan_save_recv_info(result, &seq_id); + if (ret != ZXDH_BAR_MSG_OK) + goto exit; + + zxdh_bar_chan_subchan_addr_get(in, &subchan_addr); + + msg_header.sync = ZXDH_BAR_CHAN_MSG_SYNC; + msg_header.emec = in->emec; + msg_header.usr = 0; + msg_header.rsv = 0; + msg_header.module_id = in->module_id; + msg_header.len = in->payload_len; + msg_header.msg_id = seq_id; + msg_header.src_pcieid = in->src_pcieid; + msg_header.dst_pcieid = in->dst_pcieid; + + ret = zxdh_bar_chan_lock(in->src, in->dst, in->src_pcieid, in->virt_addr); + if (ret != ZXDH_BAR_MSG_OK) { + zxdh_bar_chan_msgid_free(seq_id); + goto exit; + } + zxdh_bar_chan_msg_send(subchan_addr, in->payload_addr, in->payload_len, &msg_header); + + do { + rte_delay_us_block(ZXDH_BAR_MSG_POLLING_SPAN); + valid = zxdh_bar_msg_valid_stat_get(subchan_addr); + ++time_out_cnt; + } while ((time_out_cnt < ZXDH_BAR_MSG_TIMEOUT_TH) && (valid == ZXDH_BAR_MSG_CHAN_USED)); + + if (time_out_cnt == ZXDH_BAR_MSG_TIMEOUT_TH && valid != ZXDH_BAR_MSG_CHAN_USABLE) { + zxdh_bar_chan_msg_valid_set(subchan_addr, ZXDH_BAR_MSG_CHAN_USABLE); + zxdh_bar_chan_msg_poltag_set(subchan_addr, 0); + PMD_MSG_LOG(ERR, "BAR MSG ERR: chan type time out."); + ret = ZXDH_BAR_MSG_ERR_TIME_OUT; + } else { + ret = zxdh_bar_chan_sync_msg_reps_get(subchan_addr, + (uint64_t)result->recv_buffer, result->buffer_len); + } + zxdh_bar_chan_msgid_free(seq_id); + zxdh_bar_chan_unlock(in->src, in->dst, in->src_pcieid, in->virt_addr); + +exit: + return ret; +} + +static int bar_get_sum(uint8_t *ptr, uint8_t len) +{ + uint64_t sum = 0; + int idx; + + for (idx = 0; idx < len; idx++) + sum += *(ptr + idx); + + return (uint16_t)sum; +} + +static int zxdh_bar_chan_enable(struct zxdh_msix_para *para, uint16_t *vport) +{ + struct zxdh_bar_recv_msg recv_msg = {0}; + int ret = 0; + int check_token = 0; + int sum_res = 0; + + if (!para) + return ZXDH_BAR_MSG_ERR_NULL; + + struct zxdh_msix_msg msix_msg = { + .pcie_id = para->pcie_id, + .vector_risc = para->vector_risc, + .vector_pfvf = para->vector_pfvf, + .vector_mpf = para->vector_mpf, + }; + struct zxdh_pci_bar_msg in = { + .virt_addr = para->virt_addr, + .payload_addr = &msix_msg, + .payload_len = sizeof(msix_msg), + .emec = 0, + .src = para->driver_type, + .dst = ZXDH_MSG_CHAN_END_RISC, + .module_id = ZXDH_BAR_MODULE_MISX, + .src_pcieid = para->pcie_id, + .dst_pcieid = 0, + .usr = 0, + }; + + struct zxdh_msg_recviver_mem result = { + .recv_buffer = &recv_msg, + .buffer_len = sizeof(recv_msg), + }; + + ret = zxdh_bar_chan_sync_msg_send(&in, &result); + if (ret != ZXDH_BAR_MSG_OK) + return -ret; + + check_token = recv_msg.msix_reps.check; + sum_res = bar_get_sum((uint8_t *)&msix_msg, sizeof(msix_msg)); + + if (check_token != sum_res) { + PMD_MSG_LOG(ERR, "expect token: 0x%x, get token: 0x%x.", sum_res, check_token); + return ZXDH_BAR_MSG_ERR_REPLY; + } + *vport = recv_msg.msix_reps.vport; + PMD_MSG_LOG(DEBUG, "vport of pcieid: 0x%x get success.", para->pcie_id); + return ZXDH_BAR_MSG_OK; +} + +int zxdh_msg_chan_enable(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + struct zxdh_msix_para misx_info = { + .vector_risc = ZXDH_MSIX_FROM_RISCV, + .vector_pfvf = ZXDH_MSIX_FROM_PFVF, + .vector_mpf = ZXDH_MSIX_FROM_MPF, + .pcie_id = hw->pcie_id, + .driver_type = hw->is_pf ? ZXDH_MSG_CHAN_END_PF : ZXDH_MSG_CHAN_END_VF, + .virt_addr = (uint64_t)(hw->bar_addr[ZXDH_BAR0_INDEX] + ZXDH_CTRLCH_OFFSET), + }; + + return zxdh_bar_chan_enable(&misx_info, &hw->vport.vport); +} diff --git a/drivers/net/zxdh/zxdh_msg.h b/drivers/net/zxdh/zxdh_msg.h index a0b46c900a..7fbab4b214 100644 --- a/drivers/net/zxdh/zxdh_msg.h +++ b/drivers/net/zxdh/zxdh_msg.h @@ -14,6 +14,21 @@ extern "C" { #endif #define ZXDH_BAR0_INDEX 0 +#define ZXDH_CTRLCH_OFFSET (0x2000) + +#define ZXDH_MSIX_INTR_MSG_VEC_BASE 1 + +#define ZXDH_BAR_MSG_POLLING_SPAN 100 +#define ZXDH_BAR_MSG_POLL_CNT_PER_MS (1 * 1000 / ZXDH_BAR_MSG_POLLING_SPAN) +#define ZXDH_BAR_MSG_POLL_CNT_PER_S (1 * 1000 * 1000 / ZXDH_BAR_MSG_POLLING_SPAN) +#define ZXDH_BAR_MSG_TIMEOUT_TH (10 * 1000 * 1000 / ZXDH_BAR_MSG_POLLING_SPAN) + +#define ZXDH_BAR_CHAN_MSG_SYNC 0 + +#define ZXDH_BAR_MSG_ADDR_CHAN_INTERVAL (2 * 1024) /* channel size */ +#define ZXDH_BAR_MSG_PLAYLOAD_OFFSET (sizeof(struct zxdh_bar_msg_header)) +#define ZXDH_BAR_MSG_PAYLOAD_MAX_LEN \ + (ZXDH_BAR_MSG_ADDR_CHAN_INTERVAL - sizeof(struct zxdh_bar_msg_header)) enum ZXDH_DRIVER_TYPE { ZXDH_MSG_CHAN_END_MPF = 0, @@ -22,6 +37,13 @@ enum ZXDH_DRIVER_TYPE { ZXDH_MSG_CHAN_END_RISC, }; +enum ZXDH_MSG_VEC { + ZXDH_MSIX_FROM_PFVF = ZXDH_MSIX_INTR_MSG_VEC_BASE, + ZXDH_MSIX_FROM_MPF, + ZXDH_MSIX_FROM_RISCV, + ZXDH_MSG_VEC_NUM, +}; + enum ZXDH_BAR_MSG_RTN { ZXDH_BAR_MSG_OK = 0, ZXDH_BAR_MSG_ERR_MSGID, @@ -56,10 +78,117 @@ enum ZXDH_BAR_MSG_RTN { ZXDH_BAR_MSG_ERR_SOCKET, /* netlink sockte err */ }; +enum zxdh_bar_module_id { + ZXDH_BAR_MODULE_DBG = 0, /* 0: debug */ + ZXDH_BAR_MODULE_TBL, /* 1: resource table */ + ZXDH_BAR_MODULE_MISX, /* 2: config msix */ + ZXDH_BAR_MODULE_SDA, /* 3: */ + ZXDH_BAR_MODULE_RDMA, /* 4: */ + ZXDH_BAR_MODULE_DEMO, /* 5: channel test */ + ZXDH_BAR_MODULE_SMMU, /* 6: */ + ZXDH_BAR_MODULE_MAC, /* 7: mac rx/tx stats */ + ZXDH_BAR_MODULE_VDPA, /* 8: vdpa live migration */ + ZXDH_BAR_MODULE_VQM, /* 9: vqm live migration */ + ZXDH_BAR_MODULE_NP, /* 10: vf msg callback np */ + ZXDH_BAR_MODULE_VPORT, /* 11: get vport */ + ZXDH_BAR_MODULE_BDF, /* 12: get bdf */ + ZXDH_BAR_MODULE_RISC_READY, /* 13: */ + ZXDH_BAR_MODULE_REVERSE, /* 14: byte stream reverse */ + ZXDH_BAR_MDOULE_NVME, /* 15: */ + ZXDH_BAR_MDOULE_NPSDK, /* 16: */ + ZXDH_BAR_MODULE_NP_TODO, /* 17: */ + ZXDH_MODULE_BAR_MSG_TO_PF, /* 18: */ + ZXDH_MODULE_BAR_MSG_TO_VF, /* 19: */ + + ZXDH_MODULE_FLASH = 32, + ZXDH_BAR_MODULE_OFFSET_GET = 33, + ZXDH_BAR_EVENT_OVS_WITH_VCB = 36, + + ZXDH_BAR_MSG_MODULE_NUM = 100, +}; + +struct zxdh_msix_para { + uint16_t pcie_id; + uint16_t vector_risc; + uint16_t vector_pfvf; + uint16_t vector_mpf; + uint64_t virt_addr; + uint16_t driver_type; /* refer to DRIVER_TYPE */ +}; + +struct zxdh_msix_msg { + uint16_t pcie_id; + uint16_t vector_risc; + uint16_t vector_pfvf; + uint16_t vector_mpf; +}; + +struct zxdh_pci_bar_msg { + uint64_t virt_addr; /* bar addr */ + void *payload_addr; + uint16_t payload_len; + uint16_t emec; + uint16_t src; /* refer to BAR_DRIVER_TYPE */ + uint16_t dst; /* refer to BAR_DRIVER_TYPE */ + uint16_t module_id; + uint16_t src_pcieid; + uint16_t dst_pcieid; + uint16_t usr; +}; + +struct zxdh_bar_msix_reps { + uint16_t pcie_id; + uint16_t check; + uint16_t vport; + uint16_t rsv; +} __rte_packed; + +struct zxdh_bar_offset_reps { + uint16_t check; + uint16_t rsv; + uint32_t offset; + uint32_t length; +} __rte_packed; + +struct zxdh_bar_recv_msg { + uint8_t reps_ok; + uint16_t reps_len; + uint8_t rsv; + /* */ + union { + struct zxdh_bar_msix_reps msix_reps; + struct zxdh_bar_offset_reps offset_reps; + } __rte_packed; +} __rte_packed; + +struct zxdh_msg_recviver_mem { + void *recv_buffer; /* first 4B is head, followed by payload */ + uint64_t buffer_len; +}; + +struct zxdh_bar_msg_header { + uint8_t valid : 1; /* used by __bar_chan_msg_valid_set/get */ + uint8_t sync : 1; + uint8_t emec : 1; /* emergency */ + uint8_t ack : 1; /* ack msg */ + uint8_t poll : 1; + uint8_t usr : 1; + uint8_t rsv; + uint16_t module_id; + uint16_t len; + uint16_t msg_id; + uint16_t src_pcieid; + uint16_t dst_pcieid; /* used in PF-->VF */ +}; + int zxdh_msg_chan_init(void); int zxdh_bar_msg_chan_exit(void); int zxdh_msg_chan_hwlock_init(struct rte_eth_dev *dev); +int zxdh_msg_chan_enable(struct rte_eth_dev *dev); +int zxdh_bar_chan_sync_msg_send(struct zxdh_pci_bar_msg *in, + struct zxdh_msg_recviver_mem *result); + #ifdef __cplusplus } #endif From patchwork Wed Oct 30 09:01:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Junlong Wang X-Patchwork-Id: 147728 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id B647745C13; Wed, 30 Oct 2024 10:06:41 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id D9E39433AB; Wed, 30 Oct 2024 10:06:23 +0100 (CET) Received: from mxhk.zte.com.cn (mxhk.zte.com.cn [63.216.63.40]) by mails.dpdk.org (Postfix) with ESMTP id DD20242FB9 for ; Wed, 30 Oct 2024 10:06:10 +0100 (CET) Received: from mse-fl1.zte.com.cn (unknown [10.5.228.132]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mxhk.zte.com.cn (FangMail) with ESMTPS id 4Xdh7L2fcWz8RV6M for ; Wed, 30 Oct 2024 17:06:06 +0800 (CST) Received: from szxlzmapp04.zte.com.cn ([10.5.231.166]) by mse-fl1.zte.com.cn with SMTP id 49U95hBH007143 for ; Wed, 30 Oct 2024 17:05:43 +0800 (+08) (envelope-from wang.junlong1@zte.com.cn) Received: from localhost.localdomain (unknown [192.168.6.15]) by smtp (Zmail) with SMTP; Wed, 30 Oct 2024 17:05:46 +0800 X-Zmail-TransId: 3e816721f6ea004-b8d51 From: Junlong Wang To: dev@dpdk.org Cc: wang.yong19@zte.com.cn, Junlong Wang Subject: [PATCH v8 6/9] net/zxdh: add zxdh get device backend infos Date: Wed, 30 Oct 2024 17:01:13 +0800 Message-ID: <20241030090124.2540776-7-wang.junlong1@zte.com.cn> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241030090124.2540776-1-wang.junlong1@zte.com.cn> References: <20241022122042.2127065-2-wang.junlong1@zte.com.cn> <20241030090124.2540776-1-wang.junlong1@zte.com.cn> MIME-Version: 1.0 X-MAIL: mse-fl1.zte.com.cn 49U95hBH007143 X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 6721F6FE.002/4Xdh7L2fcWz8RV6M X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add zxdh get device backend infos, use msg chan to send msg get. Signed-off-by: Junlong Wang --- drivers/net/zxdh/meson.build | 1 + drivers/net/zxdh/zxdh_common.c | 250 +++++++++++++++++++++++++++++++++ drivers/net/zxdh/zxdh_common.h | 30 ++++ drivers/net/zxdh/zxdh_ethdev.c | 35 +++++ drivers/net/zxdh/zxdh_ethdev.h | 5 + drivers/net/zxdh/zxdh_msg.c | 17 +-- drivers/net/zxdh/zxdh_msg.h | 21 +++ drivers/net/zxdh/zxdh_queue.h | 4 + drivers/net/zxdh/zxdh_rxtx.h | 4 + 9 files changed, 359 insertions(+), 8 deletions(-) create mode 100644 drivers/net/zxdh/zxdh_common.c create mode 100644 drivers/net/zxdh/zxdh_common.h -- 2.27.0 diff --git a/drivers/net/zxdh/meson.build b/drivers/net/zxdh/meson.build index 2e0c8fddae..a16db47f89 100644 --- a/drivers/net/zxdh/meson.build +++ b/drivers/net/zxdh/meson.build @@ -17,4 +17,5 @@ sources = files( 'zxdh_ethdev.c', 'zxdh_pci.c', 'zxdh_msg.c', + 'zxdh_common.c', ) diff --git a/drivers/net/zxdh/zxdh_common.c b/drivers/net/zxdh/zxdh_common.c new file mode 100644 index 0000000000..0cb5380c5e --- /dev/null +++ b/drivers/net/zxdh/zxdh_common.c @@ -0,0 +1,250 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 ZTE Corporation + */ + +#include +#include + +#include +#include +#include + +#include "zxdh_ethdev.h" +#include "zxdh_logs.h" +#include "zxdh_msg.h" +#include "zxdh_common.h" + +#define ZXDH_MSG_RSP_SIZE_MAX 512 + +#define ZXDH_COMMON_TABLE_READ 0 +#define ZXDH_COMMON_TABLE_WRITE 1 + +#define ZXDH_COMMON_FIELD_PHYPORT 6 + +#define ZXDH_RSC_TBL_CONTENT_LEN_MAX (257 * 2) + +#define ZXDH_REPS_HEADER_OFFSET 4 +#define ZXDH_TBL_MSG_PRO_SUCCESS 0xaa + +struct zxdh_common_msg { + uint8_t type; /* 0:read table 1:write table */ + uint8_t field; + uint16_t pcie_id; + uint16_t slen; /* Data length for write table */ + uint16_t reserved; +} __rte_packed; + +struct zxdh_common_rsp_hdr { + uint8_t rsp_status; + uint16_t rsp_len; + uint8_t reserved; + uint8_t payload_status; + uint8_t rsv; + uint16_t payload_len; +} __rte_packed; + +struct zxdh_tbl_msg_header { + uint8_t type; /* r/w */ + uint8_t field; + uint16_t pcieid; + uint16_t slen; + uint16_t rsv; +}; +struct zxdh_tbl_msg_reps_header { + uint8_t check; + uint8_t rsv; + uint16_t len; +}; + +static int32_t zxdh_fill_common_msg(struct zxdh_hw *hw, + struct zxdh_pci_bar_msg *desc, + uint8_t type, + uint8_t field, + void *buff, + uint16_t buff_size) +{ + uint64_t msg_len = sizeof(struct zxdh_common_msg) + buff_size; + + desc->payload_addr = rte_zmalloc(NULL, msg_len, 0); + if (unlikely(desc->payload_addr == NULL)) { + PMD_DRV_LOG(ERR, "Failed to allocate msg_data"); + return -ENOMEM; + } + memset(desc->payload_addr, 0, msg_len); + desc->payload_len = msg_len; + struct zxdh_common_msg *msg_data = (struct zxdh_common_msg *)desc->payload_addr; + + msg_data->type = type; + msg_data->field = field; + msg_data->pcie_id = hw->pcie_id; + msg_data->slen = buff_size; + if (buff_size != 0) + rte_memcpy(msg_data + 1, buff, buff_size); + + return 0; +} + +static int32_t zxdh_send_command(struct zxdh_hw *hw, + struct zxdh_pci_bar_msg *desc, + enum zxdh_bar_module_id module_id, + struct zxdh_msg_recviver_mem *msg_rsp) +{ + desc->virt_addr = (uint64_t)(hw->bar_addr[ZXDH_BAR0_INDEX] + ZXDH_CTRLCH_OFFSET); + desc->src = hw->is_pf ? ZXDH_MSG_CHAN_END_PF : ZXDH_MSG_CHAN_END_VF; + desc->dst = ZXDH_MSG_CHAN_END_RISC; + desc->module_id = module_id; + desc->src_pcieid = hw->pcie_id; + + msg_rsp->buffer_len = ZXDH_MSG_RSP_SIZE_MAX; + msg_rsp->recv_buffer = rte_zmalloc(NULL, msg_rsp->buffer_len, 0); + if (unlikely(msg_rsp->recv_buffer == NULL)) { + PMD_DRV_LOG(ERR, "Failed to allocate messages response"); + return -ENOMEM; + } + + if (zxdh_bar_chan_sync_msg_send(desc, msg_rsp) != ZXDH_BAR_MSG_OK) { + PMD_DRV_LOG(ERR, "Failed to send sync messages or receive response"); + rte_free(msg_rsp->recv_buffer); + return -1; + } + + return 0; +} + +static int32_t zxdh_common_rsp_check(struct zxdh_msg_recviver_mem *msg_rsp, + void *buff, uint16_t len) +{ + struct zxdh_common_rsp_hdr *rsp_hdr = (struct zxdh_common_rsp_hdr *)msg_rsp->recv_buffer; + + if (rsp_hdr->payload_status != 0xaa || rsp_hdr->payload_len != len) { + PMD_DRV_LOG(ERR, "Common response is invalid, status:0x%x rsp_len:%d", + rsp_hdr->payload_status, rsp_hdr->payload_len); + return -1; + } + if (len != 0) + rte_memcpy(buff, rsp_hdr + 1, len); + + return 0; +} + +static int32_t zxdh_common_table_read(struct zxdh_hw *hw, uint8_t field, + void *buff, uint16_t buff_size) +{ + struct zxdh_msg_recviver_mem msg_rsp; + struct zxdh_pci_bar_msg desc; + int32_t ret = 0; + + if (!hw->msg_chan_init) { + PMD_DRV_LOG(ERR, "Bar messages channel not initialized"); + return -1; + } + + ret = zxdh_fill_common_msg(hw, &desc, ZXDH_COMMON_TABLE_READ, field, NULL, 0); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to fill common msg"); + return ret; + } + + ret = zxdh_send_command(hw, &desc, ZXDH_BAR_MODULE_TBL, &msg_rsp); + if (ret != 0) + goto free_msg_data; + + ret = zxdh_common_rsp_check(&msg_rsp, buff, buff_size); + if (ret != 0) + goto free_rsp_data; + +free_rsp_data: + rte_free(msg_rsp.recv_buffer); +free_msg_data: + rte_free(desc.payload_addr); + return ret; +} + +int32_t zxdh_phyport_get(struct rte_eth_dev *dev, uint8_t *phyport) +{ + struct zxdh_hw *hw = dev->data->dev_private; + + int32_t ret = zxdh_common_table_read(hw, ZXDH_COMMON_FIELD_PHYPORT, + (void *)phyport, sizeof(*phyport)); + return ret; +} + +static inline void zxdh_fill_res_para(struct rte_eth_dev *dev, struct zxdh_res_para *param) +{ + struct zxdh_hw *hw = dev->data->dev_private; + + param->pcie_id = hw->pcie_id; + param->virt_addr = hw->bar_addr[0] + ZXDH_CTRLCH_OFFSET; + param->src_type = ZXDH_BAR_MODULE_TBL; +} + +static int zxdh_get_res_info(struct zxdh_res_para *dev, uint8_t field, uint8_t *res, uint16_t *len) +{ + struct zxdh_pci_bar_msg in = {0}; + uint8_t recv_buf[ZXDH_RSC_TBL_CONTENT_LEN_MAX + 8] = {0}; + int ret = 0; + + if (!res || !dev) + return ZXDH_BAR_MSG_ERR_NULL; + + struct zxdh_tbl_msg_header tbl_msg = { + .type = ZXDH_TBL_TYPE_READ, + .field = field, + .pcieid = dev->pcie_id, + .slen = 0, + .rsv = 0, + }; + + in.virt_addr = dev->virt_addr; + in.payload_addr = &tbl_msg; + in.payload_len = sizeof(tbl_msg); + in.src = dev->src_type; + in.dst = ZXDH_MSG_CHAN_END_RISC; + in.module_id = ZXDH_BAR_MODULE_TBL; + in.src_pcieid = dev->pcie_id; + + struct zxdh_msg_recviver_mem result = { + .recv_buffer = recv_buf, + .buffer_len = sizeof(recv_buf), + }; + ret = zxdh_bar_chan_sync_msg_send(&in, &result); + + if (ret != ZXDH_BAR_MSG_OK) { + PMD_DRV_LOG(ERR, + "send sync_msg failed. pcieid: 0x%x, ret: %d.", dev->pcie_id, ret); + return ret; + } + struct zxdh_tbl_msg_reps_header *tbl_reps = + (struct zxdh_tbl_msg_reps_header *)(recv_buf + ZXDH_REPS_HEADER_OFFSET); + + if (tbl_reps->check != ZXDH_TBL_MSG_PRO_SUCCESS) { + PMD_DRV_LOG(ERR, + "get resource_field failed. pcieid: 0x%x, ret: %d.", dev->pcie_id, ret); + return ret; + } + *len = tbl_reps->len; + rte_memcpy(res, (recv_buf + ZXDH_REPS_HEADER_OFFSET + + sizeof(struct zxdh_tbl_msg_reps_header)), *len); + return ret; +} + +static int zxdh_get_res_panel_id(struct zxdh_res_para *in, uint8_t *panel_id) +{ + uint8_t reps = 0; + uint16_t reps_len = 0; + + if (zxdh_get_res_info(in, ZXDH_TBL_FIELD_PNLID, &reps, &reps_len) != ZXDH_BAR_MSG_OK) + return -1; + + *panel_id = reps; + return ZXDH_BAR_MSG_OK; +} + +int32_t zxdh_pannelid_get(struct rte_eth_dev *dev, uint8_t *pannelid) +{ + struct zxdh_res_para param; + + zxdh_fill_res_para(dev, ¶m); + int32_t ret = zxdh_get_res_panel_id(¶m, pannelid); + return ret; +} diff --git a/drivers/net/zxdh/zxdh_common.h b/drivers/net/zxdh/zxdh_common.h new file mode 100644 index 0000000000..f098ae4cf9 --- /dev/null +++ b/drivers/net/zxdh/zxdh_common.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 ZTE Corporation + */ + +#ifndef ZXDH_COMMON_H +#define ZXDH_COMMON_H + +#include +#include + +#include "zxdh_ethdev.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct zxdh_res_para { + uint64_t virt_addr; + uint16_t pcie_id; + uint16_t src_type; /* refer to BAR_DRIVER_TYPE */ +}; + +int32_t zxdh_phyport_get(struct rte_eth_dev *dev, uint8_t *phyport); +int32_t zxdh_pannelid_get(struct rte_eth_dev *dev, uint8_t *pannelid); + +#ifdef __cplusplus +} +#endif + +#endif /* ZXDH_COMMON_H */ diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c index a729344288..8d9df218ce 100644 --- a/drivers/net/zxdh/zxdh_ethdev.c +++ b/drivers/net/zxdh/zxdh_ethdev.c @@ -10,9 +10,21 @@ #include "zxdh_logs.h" #include "zxdh_pci.h" #include "zxdh_msg.h" +#include "zxdh_common.h" struct zxdh_hw_internal zxdh_hw_internal[RTE_MAX_ETHPORTS]; +uint16_t zxdh_vport_to_vfid(union zxdh_virport_num v) +{ + /* epid > 4 is local soft queue. return 1192 */ + if (v.epid > 4) + return 1192; + if (v.vf_flag) + return v.epid * 256 + v.vfid; + else + return (v.epid * 8 + v.pfid) + 1152; +} + static int32_t zxdh_init_device(struct rte_eth_dev *eth_dev) { struct zxdh_hw *hw = eth_dev->data->dev_private; @@ -44,6 +56,25 @@ static int32_t zxdh_init_device(struct rte_eth_dev *eth_dev) return ret; } +static int zxdh_agent_comm(struct rte_eth_dev *eth_dev, struct zxdh_hw *hw) +{ + if (zxdh_phyport_get(eth_dev, &hw->phyport) != 0) { + PMD_INIT_LOG(ERR, "Failed to get phyport"); + return -1; + } + PMD_INIT_LOG(INFO, "Get phyport success: 0x%x", hw->phyport); + + hw->vfid = zxdh_vport_to_vfid(hw->vport); + + if (zxdh_pannelid_get(eth_dev, &hw->panel_id) != 0) { + PMD_INIT_LOG(ERR, "Failed to get panel_id"); + return -1; + } + PMD_INIT_LOG(INFO, "Get panel id success: 0x%x", hw->panel_id); + + return 0; +} + static int zxdh_eth_dev_init(struct rte_eth_dev *eth_dev) { struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); @@ -103,6 +134,10 @@ static int zxdh_eth_dev_init(struct rte_eth_dev *eth_dev) goto err_zxdh_init; } + ret = zxdh_agent_comm(eth_dev, hw); + if (ret != 0) + goto err_zxdh_init; + return ret; err_zxdh_init: diff --git a/drivers/net/zxdh/zxdh_ethdev.h b/drivers/net/zxdh/zxdh_ethdev.h index bed1334690..1ee8dd744c 100644 --- a/drivers/net/zxdh/zxdh_ethdev.h +++ b/drivers/net/zxdh/zxdh_ethdev.h @@ -56,6 +56,7 @@ struct zxdh_hw { uint16_t pcie_id; uint16_t device_id; uint16_t port_id; + uint16_t vfid; uint8_t *isr; uint8_t weak_barriers; @@ -65,8 +66,12 @@ struct zxdh_hw { uint8_t duplex; uint8_t is_pf; uint8_t msg_chan_init; + uint8_t phyport; + uint8_t panel_id; }; +uint16_t zxdh_vport_to_vfid(union zxdh_virport_num v); + #ifdef __cplusplus } #endif diff --git a/drivers/net/zxdh/zxdh_msg.c b/drivers/net/zxdh/zxdh_msg.c index 1bf72a9b7c..4105daf5c6 100644 --- a/drivers/net/zxdh/zxdh_msg.c +++ b/drivers/net/zxdh/zxdh_msg.c @@ -133,7 +133,9 @@ struct zxdh_seqid_ring { }; struct zxdh_seqid_ring g_seqid_ring = {0}; -static uint16_t pcie_id_to_hard_lock(uint16_t src_pcieid, uint8_t dst) +static uint8_t tmp_msg_header[ZXDH_BAR_MSG_ADDR_CHAN_INTERVAL]; + +static uint16_t zxdh_pcie_id_to_hard_lock(uint16_t src_pcieid, uint8_t dst) { uint16_t lock_id = 0; uint16_t pf_idx = (src_pcieid & ZXDH_PCIEID_PF_IDX_MASK) >> ZXDH_PCIEID_PF_IDX_OFFSET; @@ -209,11 +211,11 @@ static int32_t zxdh_spinlock_unlock(uint32_t virt_lock_id, uint64_t virt_addr, u */ static int bar_chan_pf_init_spinlock(uint16_t pcie_id, uint64_t bar_base_addr) { - int lock_id = pcie_id_to_hard_lock(pcie_id, ZXDH_MSG_CHAN_END_RISC); + int lock_id = zxdh_pcie_id_to_hard_lock(pcie_id, ZXDH_MSG_CHAN_END_RISC); zxdh_spinlock_unlock(lock_id, bar_base_addr + ZXDH_BAR0_SPINLOCK_OFFSET, bar_base_addr + ZXDH_HW_LABEL_OFFSET); - lock_id = pcie_id_to_hard_lock(pcie_id, ZXDH_MSG_CHAN_END_VF); + lock_id = zxdh_pcie_id_to_hard_lock(pcie_id, ZXDH_MSG_CHAN_END_VF); zxdh_spinlock_unlock(lock_id, bar_base_addr + ZXDH_BAR0_SPINLOCK_OFFSET, bar_base_addr + ZXDH_HW_LABEL_OFFSET); return 0; @@ -409,7 +411,7 @@ static uint16_t zxdh_bar_chan_subchan_addr_get(struct zxdh_pci_bar_msg *in, uint static int zxdh_bar_hard_lock(uint16_t src_pcieid, uint8_t dst, uint64_t virt_addr) { int ret = 0; - uint16_t lockid = pcie_id_to_hard_lock(src_pcieid, dst); + uint16_t lockid = zxdh_pcie_id_to_hard_lock(src_pcieid, dst); PMD_MSG_LOG(DEBUG, "dev pcieid: 0x%x lock, get hardlockid: %u", src_pcieid, lockid); if (dst == ZXDH_MSG_CHAN_END_RISC) @@ -426,7 +428,7 @@ static int zxdh_bar_hard_lock(uint16_t src_pcieid, uint8_t dst, uint64_t virt_ad static void zxdh_bar_hard_unlock(uint16_t src_pcieid, uint8_t dst, uint64_t virt_addr) { - uint16_t lockid = pcie_id_to_hard_lock(src_pcieid, dst); + uint16_t lockid = zxdh_pcie_id_to_hard_lock(src_pcieid, dst); PMD_MSG_LOG(DEBUG, "dev pcieid: 0x%x unlock, get hardlockid: %u", src_pcieid, lockid); if (dst == ZXDH_MSG_CHAN_END_RISC) @@ -586,7 +588,6 @@ static uint16_t zxdh_bar_chan_msg_valid_set(uint64_t subchan_addr, uint8_t valid return ZXDH_BAR_MSG_OK; } -static uint8_t temp_msg[ZXDH_BAR_MSG_ADDR_CHAN_INTERVAL]; static uint16_t zxdh_bar_chan_msg_send(uint64_t subchan_addr, void *payload_addr, uint16_t payload_len, @@ -596,13 +597,13 @@ static uint16_t zxdh_bar_chan_msg_send(uint64_t subchan_addr, ret = zxdh_bar_chan_msg_header_set(subchan_addr, msg_header); ret = zxdh_bar_chan_msg_header_get(subchan_addr, - (struct zxdh_bar_msg_header *)temp_msg); + (struct zxdh_bar_msg_header *)tmp_msg_header); ret = zxdh_bar_chan_msg_payload_set(subchan_addr, (uint8_t *)(payload_addr), payload_len); ret = zxdh_bar_chan_msg_payload_get(subchan_addr, - temp_msg, payload_len); + tmp_msg_header, payload_len); ret = zxdh_bar_chan_msg_valid_set(subchan_addr, ZXDH_BAR_MSG_CHAN_USED); return ret; diff --git a/drivers/net/zxdh/zxdh_msg.h b/drivers/net/zxdh/zxdh_msg.h index 7fbab4b214..7da60ee189 100644 --- a/drivers/net/zxdh/zxdh_msg.h +++ b/drivers/net/zxdh/zxdh_msg.h @@ -107,6 +107,27 @@ enum zxdh_bar_module_id { ZXDH_BAR_MSG_MODULE_NUM = 100, }; +enum ZXDH_RES_TBL_FILED { + ZXDH_TBL_FIELD_PCIEID = 0, + ZXDH_TBL_FIELD_BDF = 1, + ZXDH_TBL_FIELD_MSGCH = 2, + ZXDH_TBL_FIELD_DATACH = 3, + ZXDH_TBL_FIELD_VPORT = 4, + ZXDH_TBL_FIELD_PNLID = 5, + ZXDH_TBL_FIELD_PHYPORT = 6, + ZXDH_TBL_FIELD_SERDES_NUM = 7, + ZXDH_TBL_FIELD_NP_PORT = 8, + ZXDH_TBL_FIELD_SPEED = 9, + ZXDH_TBL_FIELD_HASHID = 10, + ZXDH_TBL_FIELD_NON, +}; + +enum ZXDH_TBL_MSG_TYPE { + ZXDH_TBL_TYPE_READ, + ZXDH_TBL_TYPE_WRITE, + ZXDH_TBL_TYPE_NON, +}; + struct zxdh_msix_para { uint16_t pcie_id; uint16_t vector_risc; diff --git a/drivers/net/zxdh/zxdh_queue.h b/drivers/net/zxdh/zxdh_queue.h index fd73f14e2d..66f37ec612 100644 --- a/drivers/net/zxdh/zxdh_queue.h +++ b/drivers/net/zxdh/zxdh_queue.h @@ -102,4 +102,8 @@ struct zxdh_virtqueue { struct zxdh_vq_desc_extra vq_descx[]; } __rte_packed; +#ifdef __cplusplus +} +#endif + #endif /* ZXDH_QUEUE_H */ diff --git a/drivers/net/zxdh/zxdh_rxtx.h b/drivers/net/zxdh/zxdh_rxtx.h index ccac7e7834..31b1c8f0a5 100644 --- a/drivers/net/zxdh/zxdh_rxtx.h +++ b/drivers/net/zxdh/zxdh_rxtx.h @@ -48,4 +48,8 @@ struct zxdh_virtnet_tx { const struct rte_memzone *mz; /* mem zone to populate TX ring. */ } __rte_packed; +#ifdef __cplusplus +} +#endif + #endif /* ZXDH_RXTX_H */ From patchwork Wed Oct 30 09:01:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Junlong Wang X-Patchwork-Id: 147726 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 6029445C13; Wed, 30 Oct 2024 10:06:26 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 82026433A0; Wed, 30 Oct 2024 10:06:21 +0100 (CET) Received: from mxhk.zte.com.cn (mxhk.zte.com.cn [63.216.63.40]) by mails.dpdk.org (Postfix) with ESMTP id 19A4D43388 for ; Wed, 30 Oct 2024 10:06:07 +0100 (CET) Received: from mse-fl2.zte.com.cn (unknown [10.5.228.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mxhk.zte.com.cn (FangMail) with ESMTPS id 4Xdh7G1J1Sz8RV6W for ; Wed, 30 Oct 2024 17:06:02 +0800 (CST) Received: from szxlzmapp01.zte.com.cn ([10.5.231.85]) by mse-fl2.zte.com.cn with SMTP id 49U95iSS055481 for ; Wed, 30 Oct 2024 17:05:44 +0800 (+08) (envelope-from wang.junlong1@zte.com.cn) Received: from localhost.localdomain (unknown [192.168.6.15]) by smtp (Zmail) with SMTP; Wed, 30 Oct 2024 17:05:47 +0800 X-Zmail-TransId: 3e816721f6eb004-b8d53 From: Junlong Wang To: dev@dpdk.org Cc: wang.yong19@zte.com.cn, Junlong Wang Subject: [PATCH v8 7/9] net/zxdh: add configure zxdh intr implementation Date: Wed, 30 Oct 2024 17:01:14 +0800 Message-ID: <20241030090124.2540776-8-wang.junlong1@zte.com.cn> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241030090124.2540776-1-wang.junlong1@zte.com.cn> References: <20241022122042.2127065-2-wang.junlong1@zte.com.cn> <20241030090124.2540776-1-wang.junlong1@zte.com.cn> MIME-Version: 1.0 X-MAIL: mse-fl2.zte.com.cn 49U95iSS055481 X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 6721F6FA.000/4Xdh7G1J1Sz8RV6W X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org configure zxdh intr include risc,dtb. and release intr. Signed-off-by: Junlong Wang --- drivers/net/zxdh/zxdh_ethdev.c | 300 +++++++++++++++++++++++++++++++++ drivers/net/zxdh/zxdh_ethdev.h | 8 + drivers/net/zxdh/zxdh_msg.c | 188 +++++++++++++++++++++ drivers/net/zxdh/zxdh_msg.h | 13 ++ drivers/net/zxdh/zxdh_pci.c | 62 +++++++ drivers/net/zxdh/zxdh_pci.h | 12 ++ 6 files changed, 583 insertions(+) -- 2.27.0 diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c index 8d9df218ce..5963aed949 100644 --- a/drivers/net/zxdh/zxdh_ethdev.c +++ b/drivers/net/zxdh/zxdh_ethdev.c @@ -25,6 +25,301 @@ uint16_t zxdh_vport_to_vfid(union zxdh_virport_num v) return (v.epid * 8 + v.pfid) + 1152; } +static void zxdh_queues_unbind_intr(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + int32_t i; + + for (i = 0; i < dev->data->nb_rx_queues; ++i) { + ZXDH_VTPCI_OPS(hw)->set_queue_irq(hw, hw->vqs[i * 2], ZXDH_MSI_NO_VECTOR); + ZXDH_VTPCI_OPS(hw)->set_queue_irq(hw, hw->vqs[i * 2 + 1], ZXDH_MSI_NO_VECTOR); + } +} + + +static int32_t zxdh_intr_unmask(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + + if (rte_intr_ack(dev->intr_handle) < 0) + return -1; + + hw->use_msix = zxdh_vtpci_msix_detect(RTE_ETH_DEV_TO_PCI(dev)); + + return 0; +} + +static void zxdh_devconf_intr_handler(void *param) +{ + struct rte_eth_dev *dev = param; + + if (zxdh_intr_unmask(dev) < 0) + PMD_DRV_LOG(ERR, "interrupt enable failed"); +} + + +/* Interrupt handler triggered by NIC for handling specific interrupt. */ +static void zxdh_fromriscv_intr_handler(void *param) +{ + struct rte_eth_dev *dev = param; + struct zxdh_hw *hw = dev->data->dev_private; + uint64_t virt_addr = (uint64_t)(hw->bar_addr[ZXDH_BAR0_INDEX] + ZXDH_CTRLCH_OFFSET); + + if (hw->is_pf) { + PMD_INIT_LOG(DEBUG, "zxdh_risc2pf_intr_handler"); + zxdh_bar_irq_recv(ZXDH_MSG_CHAN_END_RISC, ZXDH_MSG_CHAN_END_PF, virt_addr, dev); + } else { + PMD_INIT_LOG(DEBUG, "zxdh_riscvf_intr_handler"); + zxdh_bar_irq_recv(ZXDH_MSG_CHAN_END_RISC, ZXDH_MSG_CHAN_END_VF, virt_addr, dev); + } +} + +/* Interrupt handler triggered by NIC for handling specific interrupt. */ +static void zxdh_frompfvf_intr_handler(void *param) +{ + struct rte_eth_dev *dev = param; + struct zxdh_hw *hw = dev->data->dev_private; + uint64_t virt_addr = (uint64_t)(hw->bar_addr[ZXDH_BAR0_INDEX] + + ZXDH_MSG_CHAN_PFVFSHARE_OFFSET); + + if (hw->is_pf) { + PMD_INIT_LOG(DEBUG, "zxdh_vf2pf_intr_handler"); + zxdh_bar_irq_recv(ZXDH_MSG_CHAN_END_VF, ZXDH_MSG_CHAN_END_PF, virt_addr, dev); + } else { + PMD_INIT_LOG(DEBUG, "zxdh_pf2vf_intr_handler"); + zxdh_bar_irq_recv(ZXDH_MSG_CHAN_END_PF, ZXDH_MSG_CHAN_END_VF, virt_addr, dev); + } +} + +static void zxdh_intr_cb_reg(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + + if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC) + rte_intr_callback_unregister(dev->intr_handle, zxdh_devconf_intr_handler, dev); + + /* register callback to update dev config intr */ + rte_intr_callback_register(dev->intr_handle, zxdh_devconf_intr_handler, dev); + /* Register rsic_v to pf interrupt callback */ + struct rte_intr_handle *tmp = hw->risc_intr + + (ZXDH_MSIX_FROM_PFVF - ZXDH_MSIX_INTR_MSG_VEC_BASE); + + rte_intr_callback_register(tmp, zxdh_frompfvf_intr_handler, dev); + + tmp = hw->risc_intr + (ZXDH_MSIX_FROM_RISCV - ZXDH_MSIX_INTR_MSG_VEC_BASE); + rte_intr_callback_register(tmp, zxdh_fromriscv_intr_handler, dev); +} + +static void zxdh_intr_cb_unreg(struct rte_eth_dev *dev) +{ + if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC) + rte_intr_callback_unregister(dev->intr_handle, zxdh_devconf_intr_handler, dev); + + struct zxdh_hw *hw = dev->data->dev_private; + + /* register callback to update dev config intr */ + rte_intr_callback_unregister(dev->intr_handle, zxdh_devconf_intr_handler, dev); + /* Register rsic_v to pf interrupt callback */ + struct rte_intr_handle *tmp = hw->risc_intr + + (ZXDH_MSIX_FROM_PFVF - ZXDH_MSIX_INTR_MSG_VEC_BASE); + + rte_intr_callback_unregister(tmp, zxdh_frompfvf_intr_handler, dev); + tmp = hw->risc_intr + (ZXDH_MSIX_FROM_RISCV - ZXDH_MSIX_INTR_MSG_VEC_BASE); + rte_intr_callback_unregister(tmp, zxdh_fromriscv_intr_handler, dev); +} + +static int32_t zxdh_intr_disable(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + + if (!hw->intr_enabled) + return 0; + + zxdh_intr_cb_unreg(dev); + if (rte_intr_disable(dev->intr_handle) < 0) + return -1; + + hw->intr_enabled = 0; + return 0; +} + +static int32_t zxdh_intr_enable(struct rte_eth_dev *dev) +{ + int ret = 0; + struct zxdh_hw *hw = dev->data->dev_private; + + if (!hw->intr_enabled) { + zxdh_intr_cb_reg(dev); + ret = rte_intr_enable(dev->intr_handle); + if (unlikely(ret)) + PMD_INIT_LOG(ERR, "Failed to enable %s intr", dev->data->name); + + hw->intr_enabled = 1; + } + return ret; +} + +static int32_t zxdh_intr_release(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + + if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC) + ZXDH_VTPCI_OPS(hw)->set_config_irq(hw, ZXDH_MSI_NO_VECTOR); + + zxdh_queues_unbind_intr(dev); + zxdh_intr_disable(dev); + + rte_intr_efd_disable(dev->intr_handle); + rte_intr_vec_list_free(dev->intr_handle); + rte_free(hw->risc_intr); + hw->risc_intr = NULL; + rte_free(hw->dtb_intr); + hw->dtb_intr = NULL; + return 0; +} + +static int32_t zxdh_setup_risc_interrupts(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + uint8_t i; + + if (!hw->risc_intr) { + PMD_INIT_LOG(ERR, " to allocate risc_intr"); + hw->risc_intr = rte_zmalloc("risc_intr", + ZXDH_MSIX_INTR_MSG_VEC_NUM * sizeof(struct rte_intr_handle), 0); + if (hw->risc_intr == NULL) { + PMD_INIT_LOG(ERR, "Failed to allocate risc_intr"); + return -ENOMEM; + } + } + + for (i = 0; i < ZXDH_MSIX_INTR_MSG_VEC_NUM; i++) { + if (dev->intr_handle->efds[i] < 0) { + PMD_INIT_LOG(ERR, "[%u]risc interrupt fd is invalid", i); + rte_free(hw->risc_intr); + hw->risc_intr = NULL; + return -1; + } + + struct rte_intr_handle *intr_handle = hw->risc_intr + i; + + intr_handle->fd = dev->intr_handle->efds[i]; + intr_handle->type = dev->intr_handle->type; + } + + return 0; +} + +static int32_t zxdh_setup_dtb_interrupts(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + + if (!hw->dtb_intr) { + hw->dtb_intr = rte_zmalloc("dtb_intr", sizeof(struct rte_intr_handle), 0); + if (hw->dtb_intr == NULL) { + PMD_INIT_LOG(ERR, "Failed to allocate dtb_intr"); + return -ENOMEM; + } + } + + if (dev->intr_handle->efds[ZXDH_MSIX_INTR_DTB_VEC - 1] < 0) { + PMD_INIT_LOG(ERR, "[%d]dtb interrupt fd is invalid", ZXDH_MSIX_INTR_DTB_VEC - 1); + rte_free(hw->dtb_intr); + hw->dtb_intr = NULL; + return -1; + } + hw->dtb_intr->fd = dev->intr_handle->efds[ZXDH_MSIX_INTR_DTB_VEC - 1]; + hw->dtb_intr->type = dev->intr_handle->type; + return 0; +} + +static int32_t zxdh_queues_bind_intr(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + int32_t i; + uint16_t vec; + + if (!dev->data->dev_conf.intr_conf.rxq) { + for (i = 0; i < dev->data->nb_rx_queues; ++i) { + vec = ZXDH_VTPCI_OPS(hw)->set_queue_irq(hw, + hw->vqs[i * 2], ZXDH_MSI_NO_VECTOR); + PMD_INIT_LOG(DEBUG, "vq%d irq set 0x%x, get 0x%x", + i * 2, ZXDH_MSI_NO_VECTOR, vec); + } + } else { + for (i = 0; i < dev->data->nb_rx_queues; ++i) { + vec = ZXDH_VTPCI_OPS(hw)->set_queue_irq(hw, + hw->vqs[i * 2], i + ZXDH_QUEUE_INTR_VEC_BASE); + PMD_INIT_LOG(DEBUG, "vq%d irq set %d, get %d", + i * 2, i + ZXDH_QUEUE_INTR_VEC_BASE, vec); + } + } + /* mask all txq intr */ + for (i = 0; i < dev->data->nb_tx_queues; ++i) { + vec = ZXDH_VTPCI_OPS(hw)->set_queue_irq(hw, + hw->vqs[(i * 2) + 1], ZXDH_MSI_NO_VECTOR); + PMD_INIT_LOG(DEBUG, "vq%d irq set 0x%x, get 0x%x", + (i * 2) + 1, ZXDH_MSI_NO_VECTOR, vec); + } + return 0; +} + +static int32_t zxdh_configure_intr(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + int32_t ret = 0; + + if (!rte_intr_cap_multiple(dev->intr_handle)) { + PMD_INIT_LOG(ERR, "Multiple intr vector not supported"); + return -ENOTSUP; + } + zxdh_intr_release(dev); + uint8_t nb_efd = ZXDH_MSIX_INTR_DTB_VEC_NUM + ZXDH_MSIX_INTR_MSG_VEC_NUM; + + if (dev->data->dev_conf.intr_conf.rxq) + nb_efd += dev->data->nb_rx_queues; + + if (rte_intr_efd_enable(dev->intr_handle, nb_efd)) { + PMD_INIT_LOG(ERR, "Fail to create eventfd"); + return -1; + } + + if (rte_intr_vec_list_alloc(dev->intr_handle, "intr_vec", + hw->max_queue_pairs + ZXDH_INTR_NONQUE_NUM)) { + PMD_INIT_LOG(ERR, "Failed to allocate %u rxq vectors", + hw->max_queue_pairs + ZXDH_INTR_NONQUE_NUM); + return -ENOMEM; + } + PMD_INIT_LOG(DEBUG, "allocate %u rxq vectors", dev->intr_handle->vec_list_size); + if (zxdh_setup_risc_interrupts(dev) != 0) { + PMD_INIT_LOG(ERR, "Error setting up rsic_v interrupts!"); + ret = -1; + goto free_intr_vec; + } + if (zxdh_setup_dtb_interrupts(dev) != 0) { + PMD_INIT_LOG(ERR, "Error setting up dtb interrupts!"); + ret = -1; + goto free_intr_vec; + } + + if (zxdh_queues_bind_intr(dev) < 0) { + PMD_INIT_LOG(ERR, "Failed to bind queue/interrupt"); + ret = -1; + goto free_intr_vec; + } + + if (zxdh_intr_enable(dev) < 0) { + PMD_DRV_LOG(ERR, "interrupt enable failed"); + ret = -1; + goto free_intr_vec; + } + return 0; + +free_intr_vec: + zxdh_intr_release(dev); + return ret; +} + static int32_t zxdh_init_device(struct rte_eth_dev *eth_dev) { struct zxdh_hw *hw = eth_dev->data->dev_private; @@ -138,9 +433,14 @@ static int zxdh_eth_dev_init(struct rte_eth_dev *eth_dev) if (ret != 0) goto err_zxdh_init; + ret = zxdh_configure_intr(eth_dev); + if (ret != 0) + goto err_zxdh_init; + return ret; err_zxdh_init: + zxdh_intr_release(eth_dev); zxdh_bar_msg_chan_exit(); rte_free(eth_dev->data->mac_addrs); eth_dev->data->mac_addrs = NULL; diff --git a/drivers/net/zxdh/zxdh_ethdev.h b/drivers/net/zxdh/zxdh_ethdev.h index 1ee8dd744c..0a7b574477 100644 --- a/drivers/net/zxdh/zxdh_ethdev.h +++ b/drivers/net/zxdh/zxdh_ethdev.h @@ -8,6 +8,10 @@ #include #include "ethdev_driver.h" +#include +#include + +#include "zxdh_queue.h" #ifdef __cplusplus extern "C" { @@ -44,6 +48,9 @@ struct zxdh_hw { struct rte_eth_dev *eth_dev; struct zxdh_pci_common_cfg *common_cfg; struct zxdh_net_config *dev_cfg; + struct rte_intr_handle *risc_intr; + struct rte_intr_handle *dtb_intr; + struct zxdh_virtqueue **vqs; union zxdh_virport_num vport; uint64_t bar_addr[ZXDH_NUM_BARS]; @@ -60,6 +67,7 @@ struct zxdh_hw { uint8_t *isr; uint8_t weak_barriers; + uint8_t intr_enabled; uint8_t use_msix; uint8_t mac_addr[RTE_ETHER_ADDR_LEN]; diff --git a/drivers/net/zxdh/zxdh_msg.c b/drivers/net/zxdh/zxdh_msg.c index 4105daf5c6..71c199ec2e 100644 --- a/drivers/net/zxdh/zxdh_msg.c +++ b/drivers/net/zxdh/zxdh_msg.c @@ -94,6 +94,12 @@ #define ZXDH_BAR_CHAN_INDEX_SEND 0 #define ZXDH_BAR_CHAN_INDEX_RECV 1 +#define ZXDH_BAR_CHAN_MSG_SYNC 0 +#define ZXDH_BAR_CHAN_MSG_NO_EMEC 0 +#define ZXDH_BAR_CHAN_MSG_EMEC 1 +#define ZXDH_BAR_CHAN_MSG_NO_ACK 0 +#define ZXDH_BAR_CHAN_MSG_ACK 1 + uint8_t subchan_id_tbl[ZXDH_BAR_MSG_SRC_NUM][ZXDH_BAR_MSG_DST_NUM] = { {ZXDH_BAR_CHAN_INDEX_SEND, ZXDH_BAR_CHAN_INDEX_SEND, ZXDH_BAR_CHAN_INDEX_SEND}, {ZXDH_BAR_CHAN_INDEX_SEND, ZXDH_BAR_CHAN_INDEX_SEND, ZXDH_BAR_CHAN_INDEX_RECV}, @@ -135,6 +141,36 @@ struct zxdh_seqid_ring g_seqid_ring = {0}; static uint8_t tmp_msg_header[ZXDH_BAR_MSG_ADDR_CHAN_INTERVAL]; +static inline const char *zxdh_module_id_name(int val) +{ + switch (val) { + case ZXDH_BAR_MODULE_DBG: return "ZXDH_BAR_MODULE_DBG"; + case ZXDH_BAR_MODULE_TBL: return "ZXDH_BAR_MODULE_TBL"; + case ZXDH_BAR_MODULE_MISX: return "ZXDH_BAR_MODULE_MISX"; + case ZXDH_BAR_MODULE_SDA: return "ZXDH_BAR_MODULE_SDA"; + case ZXDH_BAR_MODULE_RDMA: return "ZXDH_BAR_MODULE_RDMA"; + case ZXDH_BAR_MODULE_DEMO: return "ZXDH_BAR_MODULE_DEMO"; + case ZXDH_BAR_MODULE_SMMU: return "ZXDH_BAR_MODULE_SMMU"; + case ZXDH_BAR_MODULE_MAC: return "ZXDH_BAR_MODULE_MAC"; + case ZXDH_BAR_MODULE_VDPA: return "ZXDH_BAR_MODULE_VDPA"; + case ZXDH_BAR_MODULE_VQM: return "ZXDH_BAR_MODULE_VQM"; + case ZXDH_BAR_MODULE_NP: return "ZXDH_BAR_MODULE_NP"; + case ZXDH_BAR_MODULE_VPORT: return "ZXDH_BAR_MODULE_VPORT"; + case ZXDH_BAR_MODULE_BDF: return "ZXDH_BAR_MODULE_BDF"; + case ZXDH_BAR_MODULE_RISC_READY: return "ZXDH_BAR_MODULE_RISC_READY"; + case ZXDH_BAR_MODULE_REVERSE: return "ZXDH_BAR_MODULE_REVERSE"; + case ZXDH_BAR_MDOULE_NVME: return "ZXDH_BAR_MDOULE_NVME"; + case ZXDH_BAR_MDOULE_NPSDK: return "ZXDH_BAR_MDOULE_NPSDK"; + case ZXDH_BAR_MODULE_NP_TODO: return "ZXDH_BAR_MODULE_NP_TODO"; + case ZXDH_MODULE_BAR_MSG_TO_PF: return "ZXDH_MODULE_BAR_MSG_TO_PF"; + case ZXDH_MODULE_BAR_MSG_TO_VF: return "ZXDH_MODULE_BAR_MSG_TO_VF"; + case ZXDH_MODULE_FLASH: return "ZXDH_MODULE_FLASH"; + case ZXDH_BAR_MODULE_OFFSET_GET: return "ZXDH_BAR_MODULE_OFFSET_GET"; + case ZXDH_BAR_EVENT_OVS_WITH_VCB: return "ZXDH_BAR_EVENT_OVS_WITH_VCB"; + default: return "NA"; + } +} + static uint16_t zxdh_pcie_id_to_hard_lock(uint16_t src_pcieid, uint8_t dst) { uint16_t lock_id = 0; @@ -795,3 +831,155 @@ int zxdh_msg_chan_enable(struct rte_eth_dev *dev) return zxdh_bar_chan_enable(&misx_info, &hw->vport.vport); } + +static uint64_t zxdh_recv_addr_get(uint8_t src_type, uint8_t dst_type, uint64_t virt_addr) +{ + uint8_t src = zxdh_bar_msg_dst_index_trans(src_type); + uint8_t dst = zxdh_bar_msg_src_index_trans(dst_type); + + if (src == ZXDH_BAR_MSG_SRC_ERR || dst == ZXDH_BAR_MSG_DST_ERR) + return 0; + + uint8_t chan_id = chan_id_tbl[dst][src]; + uint8_t subchan_id = 1 - subchan_id_tbl[dst][src]; + + return zxdh_subchan_addr_cal(virt_addr, chan_id, subchan_id); +} + +static void zxdh_bar_msg_ack_async_msg_proc(struct zxdh_bar_msg_header *msg_header, + uint8_t *receiver_buff) +{ + struct zxdh_seqid_item *reps_info = &g_seqid_ring.reps_info_tbl[msg_header->msg_id]; + + if (reps_info->flag != ZXDH_REPS_INFO_FLAG_USED) { + PMD_MSG_LOG(ERR, "msg_id: %u is released", msg_header->msg_id); + return; + } + if (msg_header->len > reps_info->buffer_len - 4) { + PMD_MSG_LOG(ERR, "reps_buf_len is %u, but reps_msg_len is %u", + reps_info->buffer_len, msg_header->len + 4); + goto free_id; + } + uint8_t *reps_buffer = (uint8_t *)reps_info->reps_addr; + + rte_memcpy(reps_buffer + 4, receiver_buff, msg_header->len); + *(uint16_t *)(reps_buffer + 1) = msg_header->len; + *(uint8_t *)(reps_info->reps_addr) = ZXDH_REPS_HEADER_REPLYED; + +free_id: + zxdh_bar_chan_msgid_free(msg_header->msg_id); +} + +zxdh_bar_chan_msg_recv_callback msg_recv_func_tbl[ZXDH_BAR_MSG_MODULE_NUM]; +static void zxdh_bar_msg_sync_msg_proc(uint64_t reply_addr, + struct zxdh_bar_msg_header *msg_header, + uint8_t *receiver_buff, void *dev) +{ + uint8_t *reps_buffer = rte_malloc(NULL, ZXDH_BAR_MSG_PAYLOAD_MAX_LEN, 0); + + if (reps_buffer == NULL) + return; + + zxdh_bar_chan_msg_recv_callback recv_func = msg_recv_func_tbl[msg_header->module_id]; + uint16_t reps_len = 0; + + recv_func(receiver_buff, msg_header->len, reps_buffer, &reps_len, dev); + msg_header->ack = ZXDH_BAR_CHAN_MSG_ACK; + msg_header->len = reps_len; + zxdh_bar_chan_msg_header_set(reply_addr, msg_header); + zxdh_bar_chan_msg_payload_set(reply_addr, reps_buffer, reps_len); + zxdh_bar_chan_msg_valid_set(reply_addr, ZXDH_BAR_MSG_CHAN_USABLE); + rte_free(reps_buffer); +} + +static uint64_t zxdh_reply_addr_get(uint8_t sync, uint8_t src_type, + uint8_t dst_type, uint64_t virt_addr) +{ + uint8_t src = zxdh_bar_msg_dst_index_trans(src_type); + uint8_t dst = zxdh_bar_msg_src_index_trans(dst_type); + + if (src == ZXDH_BAR_MSG_SRC_ERR || dst == ZXDH_BAR_MSG_DST_ERR) + return 0; + + uint8_t chan_id = chan_id_tbl[dst][src]; + uint8_t subchan_id = 1 - subchan_id_tbl[dst][src]; + uint64_t recv_rep_addr; + + if (sync == ZXDH_BAR_CHAN_MSG_SYNC) + recv_rep_addr = zxdh_subchan_addr_cal(virt_addr, chan_id, subchan_id); + else + recv_rep_addr = zxdh_subchan_addr_cal(virt_addr, chan_id, 1 - subchan_id); + + return recv_rep_addr; +} + +static uint16_t zxdh_bar_chan_msg_header_check(struct zxdh_bar_msg_header *msg_header) +{ + if (msg_header->valid != ZXDH_BAR_MSG_CHAN_USED) { + PMD_MSG_LOG(ERR, "recv header ERR: valid label is not used."); + return ZXDH_BAR_MSG_ERR_MODULE; + } + uint8_t module_id = msg_header->module_id; + + if (module_id >= (uint8_t)ZXDH_BAR_MSG_MODULE_NUM) { + PMD_MSG_LOG(ERR, "recv header ERR: invalid module_id: %u.", module_id); + return ZXDH_BAR_MSG_ERR_MODULE; + } + uint16_t len = msg_header->len; + + if (len > ZXDH_BAR_MSG_PAYLOAD_MAX_LEN) { + PMD_MSG_LOG(ERR, "recv header ERR: invalid mesg len: %u.", len); + return ZXDH_BAR_MSG_ERR_LEN; + } + if (msg_recv_func_tbl[msg_header->module_id] == NULL) { + PMD_MSG_LOG(ERR, "recv header ERR: module:%s(%u) doesn't register", + zxdh_module_id_name(module_id), module_id); + return ZXDH_BAR_MSG_ERR_MODULE_NOEXIST; + } + return ZXDH_BAR_MSG_OK; +} + +int zxdh_bar_irq_recv(uint8_t src, uint8_t dst, uint64_t virt_addr, void *dev) +{ + struct zxdh_bar_msg_header msg_header = {0}; + uint64_t recv_addr = 0; + uint16_t ret = 0; + + recv_addr = zxdh_recv_addr_get(src, dst, virt_addr); + if (recv_addr == 0) { + PMD_MSG_LOG(ERR, "invalid driver type(src:%u, dst:%u).", src, dst); + return -1; + } + + zxdh_bar_chan_msg_header_get(recv_addr, &msg_header); + ret = zxdh_bar_chan_msg_header_check(&msg_header); + + if (ret != ZXDH_BAR_MSG_OK) { + PMD_MSG_LOG(ERR, "recv msg_head err, ret: %u.", ret); + return -1; + } + + uint8_t *recved_msg = rte_malloc(NULL, msg_header.len, 0); + if (recved_msg == NULL) { + PMD_MSG_LOG(ERR, "malloc temp buff failed."); + return -1; + } + zxdh_bar_chan_msg_payload_get(recv_addr, recved_msg, msg_header.len); + + uint64_t reps_addr = zxdh_reply_addr_get(msg_header.sync, src, dst, virt_addr); + + if (msg_header.sync == ZXDH_BAR_CHAN_MSG_SYNC) { + zxdh_bar_msg_sync_msg_proc(reps_addr, &msg_header, recved_msg, dev); + goto exit; + } + zxdh_bar_chan_msg_valid_set(recv_addr, ZXDH_BAR_MSG_CHAN_USABLE); + if (msg_header.ack == ZXDH_BAR_CHAN_MSG_ACK) { + zxdh_bar_msg_ack_async_msg_proc(&msg_header, recved_msg); + goto exit; + } + return 0; + +exit: + rte_free(recved_msg); + return ZXDH_BAR_MSG_OK; +} diff --git a/drivers/net/zxdh/zxdh_msg.h b/drivers/net/zxdh/zxdh_msg.h index 7da60ee189..691a847462 100644 --- a/drivers/net/zxdh/zxdh_msg.h +++ b/drivers/net/zxdh/zxdh_msg.h @@ -15,8 +15,15 @@ extern "C" { #define ZXDH_BAR0_INDEX 0 #define ZXDH_CTRLCH_OFFSET (0x2000) +#define ZXDH_MSG_CHAN_PFVFSHARE_OFFSET (ZXDH_CTRLCH_OFFSET + 0x1000) #define ZXDH_MSIX_INTR_MSG_VEC_BASE 1 +#define ZXDH_MSIX_INTR_MSG_VEC_NUM 3 +#define ZXDH_MSIX_INTR_DTB_VEC (ZXDH_MSIX_INTR_MSG_VEC_BASE + ZXDH_MSIX_INTR_MSG_VEC_NUM) +#define ZXDH_MSIX_INTR_DTB_VEC_NUM 1 +#define ZXDH_INTR_NONQUE_NUM (ZXDH_MSIX_INTR_MSG_VEC_NUM + ZXDH_MSIX_INTR_DTB_VEC_NUM + 1) +#define ZXDH_QUEUE_INTR_VEC_BASE (ZXDH_MSIX_INTR_DTB_VEC + ZXDH_MSIX_INTR_DTB_VEC_NUM) +#define ZXDH_QUEUE_INTR_VEC_NUM 256 #define ZXDH_BAR_MSG_POLLING_SPAN 100 #define ZXDH_BAR_MSG_POLL_CNT_PER_MS (1 * 1000 / ZXDH_BAR_MSG_POLLING_SPAN) @@ -202,6 +209,10 @@ struct zxdh_bar_msg_header { uint16_t dst_pcieid; /* used in PF-->VF */ }; +typedef int (*zxdh_bar_chan_msg_recv_callback)(void *pay_load, uint16_t len, + void *reps_buffer, uint16_t *reps_len, void *dev); + + int zxdh_msg_chan_init(void); int zxdh_bar_msg_chan_exit(void); int zxdh_msg_chan_hwlock_init(struct rte_eth_dev *dev); @@ -210,6 +221,8 @@ int zxdh_msg_chan_enable(struct rte_eth_dev *dev); int zxdh_bar_chan_sync_msg_send(struct zxdh_pci_bar_msg *in, struct zxdh_msg_recviver_mem *result); +int zxdh_bar_irq_recv(uint8_t src, uint8_t dst, uint64_t virt_addr, void *dev); + #ifdef __cplusplus } #endif diff --git a/drivers/net/zxdh/zxdh_pci.c b/drivers/net/zxdh/zxdh_pci.c index 8fcab6e888..5bd0df11da 100644 --- a/drivers/net/zxdh/zxdh_pci.c +++ b/drivers/net/zxdh/zxdh_pci.c @@ -92,6 +92,24 @@ static void zxdh_set_features(struct zxdh_hw *hw, uint64_t features) rte_write32(features >> 32, &hw->common_cfg->guest_feature); } +static uint16_t zxdh_set_config_irq(struct zxdh_hw *hw, uint16_t vec) +{ + rte_write16(vec, &hw->common_cfg->msix_config); + return rte_read16(&hw->common_cfg->msix_config); +} + +static uint16_t zxdh_set_queue_irq(struct zxdh_hw *hw, struct zxdh_virtqueue *vq, uint16_t vec) +{ + rte_write16(vq->vq_queue_index, &hw->common_cfg->queue_select); + rte_write16(vec, &hw->common_cfg->queue_msix_vector); + return rte_read16(&hw->common_cfg->queue_msix_vector); +} + +static uint8_t zxdh_get_isr(struct zxdh_hw *hw) +{ + return rte_read8(hw->isr); +} + const struct zxdh_pci_ops zxdh_dev_pci_ops = { .read_dev_cfg = zxdh_read_dev_config, .write_dev_cfg = zxdh_write_dev_config, @@ -99,8 +117,16 @@ const struct zxdh_pci_ops zxdh_dev_pci_ops = { .set_status = zxdh_set_status, .get_features = zxdh_get_features, .set_features = zxdh_set_features, + .set_queue_irq = zxdh_set_queue_irq, + .set_config_irq = zxdh_set_config_irq, + .get_isr = zxdh_get_isr, }; +uint8_t zxdh_vtpci_isr(struct zxdh_hw *hw) +{ + return ZXDH_VTPCI_OPS(hw)->get_isr(hw); +} + uint16_t zxdh_vtpci_get_features(struct zxdh_hw *hw) { return ZXDH_VTPCI_OPS(hw)->get_features(hw); @@ -283,3 +309,39 @@ int32_t zxdh_get_pci_dev_config(struct zxdh_hw *hw) return 0; } + +enum zxdh_msix_status zxdh_vtpci_msix_detect(struct rte_pci_device *dev) +{ + uint8_t pos = 0; + int32_t ret = rte_pci_read_config(dev, &pos, 1, ZXDH_PCI_CAPABILITY_LIST); + + if (ret != 1) { + PMD_INIT_LOG(ERR, "failed to read pci capability list, ret %d", ret); + return ZXDH_MSIX_NONE; + } + while (pos) { + uint8_t cap[2] = {0}; + + ret = rte_pci_read_config(dev, cap, sizeof(cap), pos); + if (ret != sizeof(cap)) { + PMD_INIT_LOG(ERR, "failed to read pci cap at pos: %x ret %d", pos, ret); + break; + } + if (cap[0] == ZXDH_PCI_CAP_ID_MSIX) { + uint16_t flags = 0; + + ret = rte_pci_read_config(dev, &flags, sizeof(flags), pos + sizeof(cap)); + if (ret != sizeof(flags)) { + PMD_INIT_LOG(ERR, + "failed to read pci cap at pos: %x ret %d", pos + 2, ret); + break; + } + if (flags & ZXDH_PCI_MSIX_ENABLE) + return ZXDH_MSIX_ENABLED; + else + return ZXDH_MSIX_DISABLED; + } + pos = cap[1]; + } + return ZXDH_MSIX_NONE; +} diff --git a/drivers/net/zxdh/zxdh_pci.h b/drivers/net/zxdh/zxdh_pci.h index bb5ae64ddf..55d8c5449c 100644 --- a/drivers/net/zxdh/zxdh_pci.h +++ b/drivers/net/zxdh/zxdh_pci.h @@ -22,6 +22,13 @@ enum zxdh_msix_status { ZXDH_MSIX_ENABLED = 2 }; +/* The bit of the ISR which indicates a device has an interrupt. */ +#define ZXDH_PCI_ISR_INTR 0x1 +/* The bit of the ISR which indicates a device configuration change. */ +#define ZXDH_PCI_ISR_CONFIG 0x2 +/* Vector value used to disable MSI for queue. */ +#define ZXDH_MSI_NO_VECTOR 0x7F + #define ZXDH_PCI_CAPABILITY_LIST 0x34 #define ZXDH_PCI_CAP_ID_VNDR 0x09 #define ZXDH_PCI_CAP_ID_MSIX 0x11 @@ -124,6 +131,9 @@ struct zxdh_pci_ops { uint64_t (*get_features)(struct zxdh_hw *hw); void (*set_features)(struct zxdh_hw *hw, uint64_t features); + uint16_t (*set_queue_irq)(struct zxdh_hw *hw, struct zxdh_virtqueue *vq, uint16_t vec); + uint16_t (*set_config_irq)(struct zxdh_hw *hw, uint16_t vec); + uint8_t (*get_isr)(struct zxdh_hw *hw); }; struct zxdh_hw_internal { @@ -143,6 +153,8 @@ int32_t zxdh_read_pci_caps(struct rte_pci_device *dev, struct zxdh_hw *hw); int32_t zxdh_get_pci_dev_config(struct zxdh_hw *hw); uint16_t zxdh_vtpci_get_features(struct zxdh_hw *hw); +uint8_t zxdh_vtpci_isr(struct zxdh_hw *hw); +enum zxdh_msix_status zxdh_vtpci_msix_detect(struct rte_pci_device *dev); #ifdef __cplusplus } From patchwork Wed Oct 30 09:01:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Junlong Wang X-Patchwork-Id: 147731 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id D844F45C13; Wed, 30 Oct 2024 10:07:06 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 8C8B1433A6; Wed, 30 Oct 2024 10:06:27 +0100 (CET) Received: from mxhk.zte.com.cn (mxhk.zte.com.cn [63.216.63.40]) by mails.dpdk.org (Postfix) with ESMTP id 120BE43397 for ; Wed, 30 Oct 2024 10:06:14 +0100 (CET) Received: from mxct.zte.com.cn (unknown [192.168.251.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mxhk.zte.com.cn (FangMail) with ESMTPS id 4Xdh7P476Tz8RV6M for ; Wed, 30 Oct 2024 17:06:09 +0800 (CST) Received: from mse-fl1.zte.com.cn (unknown [10.5.228.132]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mxct.zte.com.cn (FangMail) with ESMTPS id 4Xdh7M3fHcz51Sj8 for ; Wed, 30 Oct 2024 17:06:07 +0800 (CST) Received: from szxlzmapp04.zte.com.cn ([10.5.231.166]) by mse-fl1.zte.com.cn with SMTP id 49U95jJm007204 for ; Wed, 30 Oct 2024 17:05:45 +0800 (+08) (envelope-from wang.junlong1@zte.com.cn) Received: from localhost.localdomain (unknown [192.168.6.15]) by smtp (Zmail) with SMTP; Wed, 30 Oct 2024 17:05:48 +0800 X-Zmail-TransId: 3e816721f6ec004-b8d55 From: Junlong Wang To: dev@dpdk.org Cc: wang.yong19@zte.com.cn, Junlong Wang Subject: [PATCH v8 8/9] net/zxdh: add zxdh dev infos get ops Date: Wed, 30 Oct 2024 17:01:15 +0800 Message-ID: <20241030090124.2540776-9-wang.junlong1@zte.com.cn> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241030090124.2540776-1-wang.junlong1@zte.com.cn> References: <20241022122042.2127065-2-wang.junlong1@zte.com.cn> <20241030090124.2540776-1-wang.junlong1@zte.com.cn> MIME-Version: 1.0 X-MAIL: mse-fl1.zte.com.cn 49U95jJm007204 X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 6721F701.000/4Xdh7P476Tz8RV6M X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add support for zxdh infos get. Signed-off-by: Junlong Wang --- drivers/net/zxdh/zxdh_ethdev.c | 44 +++++++++++++++++++++++++++++++++- drivers/net/zxdh/zxdh_ethdev.h | 3 +++ 2 files changed, 46 insertions(+), 1 deletion(-) -- 2.27.0 diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c index 5963aed949..bf0d9b7b3a 100644 --- a/drivers/net/zxdh/zxdh_ethdev.c +++ b/drivers/net/zxdh/zxdh_ethdev.c @@ -25,6 +25,43 @@ uint16_t zxdh_vport_to_vfid(union zxdh_virport_num v) return (v.epid * 8 + v.pfid) + 1152; } +static int32_t zxdh_dev_infos_get(struct rte_eth_dev *dev, + struct rte_eth_dev_info *dev_info) +{ + struct zxdh_hw *hw = dev->data->dev_private; + + dev_info->speed_capa = rte_eth_speed_bitflag(hw->speed, RTE_ETH_LINK_FULL_DUPLEX); + dev_info->max_rx_queues = RTE_MIN(hw->max_queue_pairs, ZXDH_RX_QUEUES_MAX); + dev_info->max_tx_queues = RTE_MIN(hw->max_queue_pairs, ZXDH_TX_QUEUES_MAX); + dev_info->min_rx_bufsize = ZXDH_MIN_RX_BUFSIZE; + dev_info->max_rx_pktlen = ZXDH_MAX_RX_PKTLEN; + dev_info->max_mac_addrs = ZXDH_MAX_MAC_ADDRS; + dev_info->rx_offload_capa = (RTE_ETH_RX_OFFLOAD_VLAN_STRIP | + RTE_ETH_RX_OFFLOAD_VLAN_FILTER | + RTE_ETH_RX_OFFLOAD_QINQ_STRIP); + dev_info->rx_offload_capa |= (RTE_ETH_RX_OFFLOAD_IPV4_CKSUM | + RTE_ETH_RX_OFFLOAD_UDP_CKSUM | + RTE_ETH_RX_OFFLOAD_TCP_CKSUM | + RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM); + dev_info->rx_offload_capa |= (RTE_ETH_RX_OFFLOAD_SCATTER); + dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TCP_LRO; + dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_RSS_HASH; + + dev_info->tx_offload_capa = (RTE_ETH_TX_OFFLOAD_MULTI_SEGS); + dev_info->tx_offload_capa |= (RTE_ETH_TX_OFFLOAD_TCP_TSO | + RTE_ETH_TX_OFFLOAD_UDP_TSO); + dev_info->tx_offload_capa |= (RTE_ETH_TX_OFFLOAD_VLAN_INSERT | + RTE_ETH_TX_OFFLOAD_QINQ_INSERT | + RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO); + dev_info->tx_offload_capa |= (RTE_ETH_TX_OFFLOAD_IPV4_CKSUM | + RTE_ETH_TX_OFFLOAD_UDP_CKSUM | + RTE_ETH_TX_OFFLOAD_TCP_CKSUM | + RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM | + RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM); + + return 0; +} + static void zxdh_queues_unbind_intr(struct rte_eth_dev *dev) { struct zxdh_hw *hw = dev->data->dev_private; @@ -320,6 +357,11 @@ static int32_t zxdh_configure_intr(struct rte_eth_dev *dev) return ret; } +/* dev_ops for zxdh, bare necessities for basic operation */ +static const struct eth_dev_ops zxdh_eth_dev_ops = { + .dev_infos_get = zxdh_dev_infos_get, +}; + static int32_t zxdh_init_device(struct rte_eth_dev *eth_dev) { struct zxdh_hw *hw = eth_dev->data->dev_private; @@ -376,7 +418,7 @@ static int zxdh_eth_dev_init(struct rte_eth_dev *eth_dev) struct zxdh_hw *hw = eth_dev->data->dev_private; int ret = 0; - eth_dev->dev_ops = NULL; + eth_dev->dev_ops = &zxdh_eth_dev_ops; /* Allocate memory for storing MAC addresses */ eth_dev->data->mac_addrs = rte_zmalloc("zxdh_mac", diff --git a/drivers/net/zxdh/zxdh_ethdev.h b/drivers/net/zxdh/zxdh_ethdev.h index 0a7b574477..78f5ca6c00 100644 --- a/drivers/net/zxdh/zxdh_ethdev.h +++ b/drivers/net/zxdh/zxdh_ethdev.h @@ -33,6 +33,9 @@ extern "C" { #define ZXDH_RX_QUEUES_MAX 128U #define ZXDH_TX_QUEUES_MAX 128U +#define ZXDH_MIN_RX_BUFSIZE 64 +#define ZXDH_MAX_RX_PKTLEN 14000U + union zxdh_virport_num { uint16_t vport; struct { From patchwork Wed Oct 30 09:01:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Junlong Wang X-Patchwork-Id: 147732 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 1454645C13; Wed, 30 Oct 2024 10:07:15 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id AC3ED433BB; Wed, 30 Oct 2024 10:06:28 +0100 (CET) Received: from mxhk.zte.com.cn (mxhk.zte.com.cn [63.216.63.40]) by mails.dpdk.org (Postfix) with ESMTP id 943E243396 for ; Wed, 30 Oct 2024 10:06:13 +0100 (CET) Received: from mxct.zte.com.cn (unknown [192.168.251.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mxhk.zte.com.cn (FangMail) with ESMTPS id 4Xdh7N600Wz8RTZX for ; Wed, 30 Oct 2024 17:06:08 +0800 (CST) Received: from mse-fl1.zte.com.cn (unknown [10.5.228.132]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mxct.zte.com.cn (FangMail) with ESMTPS id 4Xdh7M3dqjz52SGj for ; Wed, 30 Oct 2024 17:06:07 +0800 (CST) Received: from szxlzmapp02.zte.com.cn ([10.5.231.79]) by mse-fl1.zte.com.cn with SMTP id 49U95jII007205 for ; Wed, 30 Oct 2024 17:05:45 +0800 (+08) (envelope-from wang.junlong1@zte.com.cn) Received: from localhost.localdomain (unknown [192.168.6.15]) by smtp (Zmail) with SMTP; Wed, 30 Oct 2024 17:05:49 +0800 X-Zmail-TransId: 3e816721f6ec004-b8d5b From: Junlong Wang To: dev@dpdk.org Cc: wang.yong19@zte.com.cn, Junlong Wang Subject: [PATCH v8 9/9] net/zxdh: add zxdh dev configure ops Date: Wed, 30 Oct 2024 17:01:16 +0800 Message-ID: <20241030090124.2540776-10-wang.junlong1@zte.com.cn> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241030090124.2540776-1-wang.junlong1@zte.com.cn> References: <20241022122042.2127065-2-wang.junlong1@zte.com.cn> <20241030090124.2540776-1-wang.junlong1@zte.com.cn> MIME-Version: 1.0 X-MAIL: mse-fl1.zte.com.cn 49U95jII007205 X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 6721F700.001/4Xdh7N600Wz8RTZX X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org provided zxdh dev configure ops for queue check,reset,alloc resources,etc. Signed-off-by: Junlong Wang --- drivers/net/zxdh/meson.build | 1 + drivers/net/zxdh/zxdh_common.c | 135 ++++++++++ drivers/net/zxdh/zxdh_common.h | 12 + drivers/net/zxdh/zxdh_ethdev.c | 450 +++++++++++++++++++++++++++++++++ drivers/net/zxdh/zxdh_ethdev.h | 34 ++- drivers/net/zxdh/zxdh_pci.c | 98 +++++++ drivers/net/zxdh/zxdh_pci.h | 37 ++- drivers/net/zxdh/zxdh_queue.c | 123 +++++++++ drivers/net/zxdh/zxdh_queue.h | 173 +++++++++++++ drivers/net/zxdh/zxdh_rxtx.h | 4 +- 10 files changed, 1051 insertions(+), 16 deletions(-) create mode 100644 drivers/net/zxdh/zxdh_queue.c -- 2.27.0 diff --git a/drivers/net/zxdh/meson.build b/drivers/net/zxdh/meson.build index a16db47f89..b96aa5a27e 100644 --- a/drivers/net/zxdh/meson.build +++ b/drivers/net/zxdh/meson.build @@ -18,4 +18,5 @@ sources = files( 'zxdh_pci.c', 'zxdh_msg.c', 'zxdh_common.c', + 'zxdh_queue.c', ) diff --git a/drivers/net/zxdh/zxdh_common.c b/drivers/net/zxdh/zxdh_common.c index 0cb5380c5e..5ff01c418e 100644 --- a/drivers/net/zxdh/zxdh_common.c +++ b/drivers/net/zxdh/zxdh_common.c @@ -20,6 +20,7 @@ #define ZXDH_COMMON_TABLE_WRITE 1 #define ZXDH_COMMON_FIELD_PHYPORT 6 +#define ZXDH_COMMON_FIELD_DATACH 3 #define ZXDH_RSC_TBL_CONTENT_LEN_MAX (257 * 2) @@ -248,3 +249,137 @@ int32_t zxdh_pannelid_get(struct rte_eth_dev *dev, uint8_t *pannelid) int32_t ret = zxdh_get_res_panel_id(¶m, pannelid); return ret; } + +uint32_t zxdh_read_bar_reg(struct rte_eth_dev *dev, uint32_t bar, uint32_t reg) +{ + struct zxdh_hw *hw = dev->data->dev_private; + uint64_t baseaddr = (uint64_t)(hw->bar_addr[bar]); + uint32_t val = *((volatile uint32_t *)(baseaddr + reg)); + return val; +} + +void zxdh_write_bar_reg(struct rte_eth_dev *dev, uint32_t bar, uint32_t reg, uint32_t val) +{ + struct zxdh_hw *hw = dev->data->dev_private; + uint64_t baseaddr = (uint64_t)(hw->bar_addr[bar]); + *((volatile uint32_t *)(baseaddr + reg)) = val; +} + +static bool zxdh_try_lock(struct zxdh_hw *hw) +{ + uint32_t var = zxdh_read_comm_reg((uint64_t)hw->common_cfg, ZXDH_VF_LOCK_REG); + + /* check whether lock is used */ + if (!(var & ZXDH_VF_LOCK_ENABLE_MASK)) + return false; + + return true; +} + +int32_t zxdh_timedlock(struct zxdh_hw *hw, uint32_t us) +{ + uint16_t timeout = 0; + + while ((timeout++) < ZXDH_ACQUIRE_CHANNEL_NUM_MAX) { + rte_delay_us_block(us); + /* acquire hw lock */ + if (!zxdh_try_lock(hw)) { + PMD_INIT_LOG(ERR, "Acquiring hw lock got failed, timeout: %d", timeout); + continue; + } + break; + } + if (timeout >= ZXDH_ACQUIRE_CHANNEL_NUM_MAX) { + PMD_INIT_LOG(ERR, "Failed to acquire channel"); + return -1; + } + return 0; +} + +void zxdh_release_lock(struct zxdh_hw *hw) +{ + uint32_t var = zxdh_read_comm_reg((uint64_t)hw->common_cfg, ZXDH_VF_LOCK_REG); + + if (var & ZXDH_VF_LOCK_ENABLE_MASK) { + var &= ~ZXDH_VF_LOCK_ENABLE_MASK; + zxdh_write_comm_reg((uint64_t)hw->common_cfg, ZXDH_VF_LOCK_REG, var); + } +} + +uint32_t zxdh_read_comm_reg(uint64_t pci_comm_cfg_baseaddr, uint32_t reg) +{ + uint32_t val = *((volatile uint32_t *)(pci_comm_cfg_baseaddr + reg)); + return val; +} + +void zxdh_write_comm_reg(uint64_t pci_comm_cfg_baseaddr, uint32_t reg, uint32_t val) +{ + *((volatile uint32_t *)(pci_comm_cfg_baseaddr + reg)) = val; +} + +static int32_t zxdh_common_table_write(struct zxdh_hw *hw, uint8_t field, + void *buff, uint16_t buff_size) +{ + struct zxdh_pci_bar_msg desc; + struct zxdh_msg_recviver_mem msg_rsp; + int32_t ret = 0; + + if (!hw->msg_chan_init) { + PMD_DRV_LOG(ERR, "Bar messages channel not initialized"); + return -1; + } + if (buff_size != 0 && buff == NULL) { + PMD_DRV_LOG(ERR, "Buff is invalid"); + return -1; + } + + ret = zxdh_fill_common_msg(hw, &desc, ZXDH_COMMON_TABLE_WRITE, + field, buff, buff_size); + + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to fill common msg"); + return ret; + } + + ret = zxdh_send_command(hw, &desc, ZXDH_BAR_MODULE_TBL, &msg_rsp); + if (ret != 0) + goto free_msg_data; + + ret = zxdh_common_rsp_check(&msg_rsp, NULL, 0); + if (ret != 0) + goto free_rsp_data; + +free_rsp_data: + rte_free(msg_rsp.recv_buffer); +free_msg_data: + rte_free(desc.payload_addr); + return ret; +} + +int32_t zxdh_datach_set(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + uint16_t buff_size = (hw->queue_num + 1) * 2; + void *buff = rte_zmalloc(NULL, buff_size, 0); + + if (unlikely(buff == NULL)) { + PMD_DRV_LOG(ERR, "Failed to allocate buff"); + return -ENOMEM; + } + memset(buff, 0, buff_size); + uint16_t *pdata = (uint16_t *)buff; + *pdata++ = hw->queue_num; + uint16_t i; + + for (i = 0; i < hw->queue_num; i++) + *(pdata + i) = hw->channel_context[i].ph_chno; + + int32_t ret = zxdh_common_table_write(hw, ZXDH_COMMON_FIELD_DATACH, + (void *)buff, buff_size); + + if (ret != 0) + PMD_DRV_LOG(ERR, "Failed to setup data channel of common table"); + + rte_free(buff); + return ret; +} diff --git a/drivers/net/zxdh/zxdh_common.h b/drivers/net/zxdh/zxdh_common.h index f098ae4cf9..a60e25b2e3 100644 --- a/drivers/net/zxdh/zxdh_common.h +++ b/drivers/net/zxdh/zxdh_common.h @@ -14,6 +14,10 @@ extern "C" { #endif +#define ZXDH_VF_LOCK_REG 0x90 +#define ZXDH_VF_LOCK_ENABLE_MASK 0x1 +#define ZXDH_ACQUIRE_CHANNEL_NUM_MAX 10 + struct zxdh_res_para { uint64_t virt_addr; uint16_t pcie_id; @@ -23,6 +27,14 @@ struct zxdh_res_para { int32_t zxdh_phyport_get(struct rte_eth_dev *dev, uint8_t *phyport); int32_t zxdh_pannelid_get(struct rte_eth_dev *dev, uint8_t *pannelid); +uint32_t zxdh_read_bar_reg(struct rte_eth_dev *dev, uint32_t bar, uint32_t reg); +void zxdh_write_bar_reg(struct rte_eth_dev *dev, uint32_t bar, uint32_t reg, uint32_t val); +void zxdh_release_lock(struct zxdh_hw *hw); +int32_t zxdh_timedlock(struct zxdh_hw *hw, uint32_t us); +uint32_t zxdh_read_comm_reg(uint64_t pci_comm_cfg_baseaddr, uint32_t reg); +void zxdh_write_comm_reg(uint64_t pci_comm_cfg_baseaddr, uint32_t reg, uint32_t val); +int32_t zxdh_datach_set(struct rte_eth_dev *dev); + #ifdef __cplusplus } #endif diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c index bf0d9b7b3a..ceaba444d4 100644 --- a/drivers/net/zxdh/zxdh_ethdev.c +++ b/drivers/net/zxdh/zxdh_ethdev.c @@ -11,6 +11,7 @@ #include "zxdh_pci.h" #include "zxdh_msg.h" #include "zxdh_common.h" +#include "zxdh_queue.h" struct zxdh_hw_internal zxdh_hw_internal[RTE_MAX_ETHPORTS]; @@ -357,8 +358,457 @@ static int32_t zxdh_configure_intr(struct rte_eth_dev *dev) return ret; } +static int32_t zxdh_features_update(struct zxdh_hw *hw, + const struct rte_eth_rxmode *rxmode, + const struct rte_eth_txmode *txmode) +{ + uint64_t rx_offloads = rxmode->offloads; + uint64_t tx_offloads = txmode->offloads; + uint64_t req_features = hw->guest_features; + + if (rx_offloads & (RTE_ETH_RX_OFFLOAD_UDP_CKSUM | RTE_ETH_RX_OFFLOAD_TCP_CKSUM)) + req_features |= (1ULL << ZXDH_NET_F_GUEST_CSUM); + + if (rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO) + req_features |= (1ULL << ZXDH_NET_F_GUEST_TSO4) | + (1ULL << ZXDH_NET_F_GUEST_TSO6); + + if (tx_offloads & (RTE_ETH_RX_OFFLOAD_UDP_CKSUM | RTE_ETH_RX_OFFLOAD_TCP_CKSUM)) + req_features |= (1ULL << ZXDH_NET_F_CSUM); + + if (tx_offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO) + req_features |= (1ULL << ZXDH_NET_F_HOST_TSO4) | + (1ULL << ZXDH_NET_F_HOST_TSO6); + + if (tx_offloads & RTE_ETH_TX_OFFLOAD_UDP_TSO) + req_features |= (1ULL << ZXDH_NET_F_HOST_UFO); + + req_features = req_features & hw->host_features; + hw->guest_features = req_features; + + ZXDH_VTPCI_OPS(hw)->set_features(hw, req_features); + + if ((rx_offloads & (RTE_ETH_TX_OFFLOAD_UDP_CKSUM | RTE_ETH_TX_OFFLOAD_TCP_CKSUM)) && + !vtpci_with_feature(hw, ZXDH_NET_F_GUEST_CSUM)) { + PMD_DRV_LOG(ERR, "rx checksum not available on this host"); + return -ENOTSUP; + } + + if ((rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO) && + (!vtpci_with_feature(hw, ZXDH_NET_F_GUEST_TSO4) || + !vtpci_with_feature(hw, ZXDH_NET_F_GUEST_TSO6))) { + PMD_DRV_LOG(ERR, "Large Receive Offload not available on this host"); + return -ENOTSUP; + } + return 0; +} + +static bool rx_offload_enabled(struct zxdh_hw *hw) +{ + return vtpci_with_feature(hw, ZXDH_NET_F_GUEST_CSUM) || + vtpci_with_feature(hw, ZXDH_NET_F_GUEST_TSO4) || + vtpci_with_feature(hw, ZXDH_NET_F_GUEST_TSO6); +} + +static bool tx_offload_enabled(struct zxdh_hw *hw) +{ + return vtpci_with_feature(hw, ZXDH_NET_F_CSUM) || + vtpci_with_feature(hw, ZXDH_NET_F_HOST_TSO4) || + vtpci_with_feature(hw, ZXDH_NET_F_HOST_TSO6) || + vtpci_with_feature(hw, ZXDH_NET_F_HOST_UFO); +} + +static void zxdh_dev_free_mbufs(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + uint16_t nr_vq = hw->queue_num; + uint32_t i = 0; + + const char *type = NULL; + struct zxdh_virtqueue *vq = NULL; + struct rte_mbuf *buf = NULL; + int32_t queue_type = 0; + + if (hw->vqs == NULL) + return; + + for (i = 0; i < nr_vq; i++) { + vq = hw->vqs[i]; + if (!vq) + continue; + + queue_type = zxdh_get_queue_type(i); + if (queue_type == ZXDH_VTNET_RQ) + type = "rxq"; + else if (queue_type == ZXDH_VTNET_TQ) + type = "txq"; + else + continue; + PMD_INIT_LOG(DEBUG, "Before freeing %s[%d] used and unused buf", type, i); + + while ((buf = zxdh_virtqueue_detach_unused(vq)) != NULL) + rte_pktmbuf_free(buf); + } +} + +static int32_t zxdh_get_available_channel(struct rte_eth_dev *dev, uint8_t queue_type) +{ + struct zxdh_hw *hw = dev->data->dev_private; + uint16_t base = (queue_type == ZXDH_VTNET_RQ) ? 0 : 1; + uint16_t i = 0; + uint16_t j = 0; + uint16_t done = 0; + int32_t ret = 0; + + ret = zxdh_timedlock(hw, 1000); + if (ret) { + PMD_INIT_LOG(ERR, "Acquiring hw lock got failed, timeout"); + return -1; + } + + /* Iterate COI table and find free channel */ + for (i = ZXDH_QUEUES_BASE / 32; i < ZXDH_TOTAL_QUEUES_NUM / 32; i++) { + uint32_t addr = ZXDH_QUERES_SHARE_BASE + (i * sizeof(uint32_t)); + uint32_t var = zxdh_read_bar_reg(dev, ZXDH_BAR0_INDEX, addr); + + for (j = base; j < 32; j += 2) { + /* Got the available channel & update COI table */ + if ((var & (1 << j)) == 0) { + var |= (1 << j); + zxdh_write_bar_reg(dev, ZXDH_BAR0_INDEX, addr, var); + done = 1; + break; + } + } + if (done) + break; + } + zxdh_release_lock(hw); + /* check for no channel condition */ + if (done != 1) { + PMD_INIT_LOG(ERR, "NO availd queues"); + return -1; + } + /* reruen available channel ID */ + return (i * 32) + j; +} + +static int32_t zxdh_acquire_channel(struct rte_eth_dev *dev, uint16_t lch) +{ + struct zxdh_hw *hw = dev->data->dev_private; + + if (hw->channel_context[lch].valid == 1) { + PMD_INIT_LOG(DEBUG, "Logic channel:%u already acquired Physics channel:%u", + lch, hw->channel_context[lch].ph_chno); + return hw->channel_context[lch].ph_chno; + } + int32_t pch = zxdh_get_available_channel(dev, zxdh_get_queue_type(lch)); + + if (pch < 0) { + PMD_INIT_LOG(ERR, "Failed to acquire channel"); + return -1; + } + hw->channel_context[lch].ph_chno = (uint16_t)pch; + hw->channel_context[lch].valid = 1; + PMD_INIT_LOG(DEBUG, "Acquire channel success lch:%u --> pch:%d", lch, pch); + return 0; +} + +static void zxdh_init_vring(struct zxdh_virtqueue *vq) +{ + int32_t size = vq->vq_nentries; + uint8_t *ring_mem = vq->vq_ring_virt_mem; + + memset(ring_mem, 0, vq->vq_ring_size); + + vq->vq_used_cons_idx = 0; + vq->vq_desc_head_idx = 0; + vq->vq_avail_idx = 0; + vq->vq_desc_tail_idx = (uint16_t)(vq->vq_nentries - 1); + vq->vq_free_cnt = vq->vq_nentries; + memset(vq->vq_descx, 0, sizeof(struct zxdh_vq_desc_extra) * vq->vq_nentries); + vring_init_packed(&vq->vq_packed.ring, ring_mem, ZXDH_PCI_VRING_ALIGN, size); + vring_desc_init_packed(vq, size); + virtqueue_disable_intr(vq); +} + +static int32_t zxdh_init_queue(struct rte_eth_dev *dev, uint16_t vtpci_logic_qidx) +{ + char vq_name[ZXDH_VIRTQUEUE_MAX_NAME_SZ] = {0}; + char vq_hdr_name[ZXDH_VIRTQUEUE_MAX_NAME_SZ] = {0}; + const struct rte_memzone *mz = NULL; + const struct rte_memzone *hdr_mz = NULL; + uint32_t size = 0; + struct zxdh_hw *hw = dev->data->dev_private; + struct zxdh_virtnet_rx *rxvq = NULL; + struct zxdh_virtnet_tx *txvq = NULL; + struct zxdh_virtqueue *vq = NULL; + size_t sz_hdr_mz = 0; + void *sw_ring = NULL; + int32_t queue_type = zxdh_get_queue_type(vtpci_logic_qidx); + int32_t numa_node = dev->device->numa_node; + uint16_t vtpci_phy_qidx = 0; + uint32_t vq_size = 0; + int32_t ret = 0; + + if (hw->channel_context[vtpci_logic_qidx].valid == 0) { + PMD_INIT_LOG(ERR, "lch %d is invalid", vtpci_logic_qidx); + return -EINVAL; + } + vtpci_phy_qidx = hw->channel_context[vtpci_logic_qidx].ph_chno; + + PMD_INIT_LOG(DEBUG, "vtpci_logic_qidx :%d setting up physical queue: %u on NUMA node %d", + vtpci_logic_qidx, vtpci_phy_qidx, numa_node); + + vq_size = ZXDH_QUEUE_DEPTH; + + if (ZXDH_VTPCI_OPS(hw)->set_queue_num != NULL) + ZXDH_VTPCI_OPS(hw)->set_queue_num(hw, vtpci_phy_qidx, vq_size); + + snprintf(vq_name, sizeof(vq_name), "port%d_vq%d", dev->data->port_id, vtpci_phy_qidx); + + size = RTE_ALIGN_CEIL(sizeof(*vq) + vq_size * sizeof(struct zxdh_vq_desc_extra), + RTE_CACHE_LINE_SIZE); + if (queue_type == ZXDH_VTNET_TQ) { + /* + * For each xmit packet, allocate a zxdh_net_hdr + * and indirect ring elements + */ + sz_hdr_mz = vq_size * sizeof(struct zxdh_tx_region); + } + + vq = rte_zmalloc_socket(vq_name, size, RTE_CACHE_LINE_SIZE, numa_node); + if (vq == NULL) { + PMD_INIT_LOG(ERR, "can not allocate vq"); + return -ENOMEM; + } + hw->vqs[vtpci_logic_qidx] = vq; + + vq->hw = hw; + vq->vq_queue_index = vtpci_phy_qidx; + vq->vq_nentries = vq_size; + + vq->vq_packed.used_wrap_counter = 1; + vq->vq_packed.cached_flags = ZXDH_VRING_PACKED_DESC_F_AVAIL; + vq->vq_packed.event_flags_shadow = 0; + if (queue_type == ZXDH_VTNET_RQ) + vq->vq_packed.cached_flags |= ZXDH_VRING_DESC_F_WRITE; + + /* + * Reserve a memzone for vring elements + */ + size = vring_size(hw, vq_size, ZXDH_PCI_VRING_ALIGN); + vq->vq_ring_size = RTE_ALIGN_CEIL(size, ZXDH_PCI_VRING_ALIGN); + PMD_INIT_LOG(DEBUG, "vring_size: %d, rounded_vring_size: %d", size, vq->vq_ring_size); + + mz = rte_memzone_reserve_aligned(vq_name, vq->vq_ring_size, + numa_node, RTE_MEMZONE_IOVA_CONTIG, + ZXDH_PCI_VRING_ALIGN); + if (mz == NULL) { + if (rte_errno == EEXIST) + mz = rte_memzone_lookup(vq_name); + if (mz == NULL) { + ret = -ENOMEM; + goto fail_q_alloc; + } + } + + memset(mz->addr, 0, mz->len); + + vq->vq_ring_mem = mz->iova; + vq->vq_ring_virt_mem = mz->addr; + + zxdh_init_vring(vq); + + if (sz_hdr_mz) { + snprintf(vq_hdr_name, sizeof(vq_hdr_name), "port%d_vq%d_hdr", + dev->data->port_id, vtpci_phy_qidx); + hdr_mz = rte_memzone_reserve_aligned(vq_hdr_name, sz_hdr_mz, + numa_node, RTE_MEMZONE_IOVA_CONTIG, + RTE_CACHE_LINE_SIZE); + if (hdr_mz == NULL) { + if (rte_errno == EEXIST) + hdr_mz = rte_memzone_lookup(vq_hdr_name); + if (hdr_mz == NULL) { + ret = -ENOMEM; + goto fail_q_alloc; + } + } + } + + if (queue_type == ZXDH_VTNET_RQ) { + size_t sz_sw = (ZXDH_MBUF_BURST_SZ + vq_size) * sizeof(vq->sw_ring[0]); + + sw_ring = rte_zmalloc_socket("sw_ring", sz_sw, RTE_CACHE_LINE_SIZE, numa_node); + if (!sw_ring) { + PMD_INIT_LOG(ERR, "can not allocate RX soft ring"); + ret = -ENOMEM; + goto fail_q_alloc; + } + + vq->sw_ring = sw_ring; + rxvq = &vq->rxq; + rxvq->vq = vq; + rxvq->port_id = dev->data->port_id; + rxvq->mz = mz; + } else { /* queue_type == VTNET_TQ */ + txvq = &vq->txq; + txvq->vq = vq; + txvq->port_id = dev->data->port_id; + txvq->mz = mz; + txvq->zxdh_net_hdr_mz = hdr_mz; + txvq->zxdh_net_hdr_mem = hdr_mz->iova; + } + + vq->offset = offsetof(struct rte_mbuf, buf_iova); + if (queue_type == ZXDH_VTNET_TQ) { + struct zxdh_tx_region *txr = hdr_mz->addr; + uint32_t i; + + memset(txr, 0, vq_size * sizeof(*txr)); + for (i = 0; i < vq_size; i++) { + /* first indirect descriptor is always the tx header */ + struct zxdh_vring_packed_desc *start_dp = txr[i].tx_packed_indir; + + vring_desc_init_indirect_packed(start_dp, RTE_DIM(txr[i].tx_packed_indir)); + start_dp->addr = txvq->zxdh_net_hdr_mem + i * sizeof(*txr) + + offsetof(struct zxdh_tx_region, tx_hdr); + /* length will be updated to actual pi hdr size when xmit pkt */ + start_dp->len = 0; + } + } + if (ZXDH_VTPCI_OPS(hw)->setup_queue(hw, vq) < 0) { + PMD_INIT_LOG(ERR, "setup_queue failed"); + return -EINVAL; + } + return 0; +fail_q_alloc: + rte_free(sw_ring); + rte_memzone_free(hdr_mz); + rte_memzone_free(mz); + rte_free(vq); + return ret; +} + +static int32_t zxdh_alloc_queues(struct rte_eth_dev *dev, uint16_t nr_vq) +{ + uint16_t lch; + struct zxdh_hw *hw = dev->data->dev_private; + + hw->vqs = rte_zmalloc(NULL, sizeof(struct zxdh_virtqueue *) * nr_vq, 0); + if (!hw->vqs) { + PMD_INIT_LOG(ERR, "Failed to allocate vqs"); + return -ENOMEM; + } + for (lch = 0; lch < nr_vq; lch++) { + if (zxdh_acquire_channel(dev, lch) < 0) { + PMD_INIT_LOG(ERR, "Failed to acquire the channels"); + zxdh_free_queues(dev); + return -1; + } + if (zxdh_init_queue(dev, lch) < 0) { + PMD_INIT_LOG(ERR, "Failed to alloc virtio queue"); + zxdh_free_queues(dev); + return -1; + } + } + return 0; +} + + +static int32_t zxdh_dev_configure(struct rte_eth_dev *dev) +{ + const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; + const struct rte_eth_txmode *txmode = &dev->data->dev_conf.txmode; + struct zxdh_hw *hw = dev->data->dev_private; + uint32_t nr_vq = 0; + int32_t ret = 0; + + if (dev->data->nb_rx_queues != dev->data->nb_tx_queues) { + PMD_INIT_LOG(ERR, "nb_rx_queues=%d and nb_tx_queues=%d not equal!", + dev->data->nb_rx_queues, dev->data->nb_tx_queues); + return -EINVAL; + } + if ((dev->data->nb_rx_queues + dev->data->nb_tx_queues) >= ZXDH_QUEUES_NUM_MAX) { + PMD_INIT_LOG(ERR, "nb_rx_queues=%d + nb_tx_queues=%d must < (%d)!", + dev->data->nb_rx_queues, dev->data->nb_tx_queues, + ZXDH_QUEUES_NUM_MAX); + return -EINVAL; + } + if (rxmode->mq_mode != RTE_ETH_MQ_RX_RSS && rxmode->mq_mode != RTE_ETH_MQ_RX_NONE) { + PMD_DRV_LOG(ERR, "Unsupported Rx multi queue mode %d", rxmode->mq_mode); + return -EINVAL; + } + + if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) { + PMD_DRV_LOG(ERR, "Unsupported Tx multi queue mode %d", txmode->mq_mode); + return -EINVAL; + } + if (rxmode->mq_mode != RTE_ETH_MQ_RX_RSS && rxmode->mq_mode != RTE_ETH_MQ_RX_NONE) { + PMD_DRV_LOG(ERR, "Unsupported Rx multi queue mode %d", rxmode->mq_mode); + return -EINVAL; + } + + if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) { + PMD_DRV_LOG(ERR, "Unsupported Tx multi queue mode %d", txmode->mq_mode); + return -EINVAL; + } + + ret = zxdh_features_update(hw, rxmode, txmode); + if (ret < 0) + return ret; + + /* check if lsc interrupt feature is enabled */ + if (dev->data->dev_conf.intr_conf.lsc) { + if (!(dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)) { + PMD_DRV_LOG(ERR, "link status not supported by host"); + return -ENOTSUP; + } + } + + hw->has_tx_offload = tx_offload_enabled(hw); + hw->has_rx_offload = rx_offload_enabled(hw); + + nr_vq = dev->data->nb_rx_queues + dev->data->nb_tx_queues; + if (nr_vq == hw->queue_num) + return 0; + + PMD_DRV_LOG(DEBUG, "queue changed need reset "); + /* Reset the device although not necessary at startup */ + zxdh_vtpci_reset(hw); + + /* Tell the host we've noticed this device. */ + zxdh_vtpci_set_status(hw, ZXDH_CONFIG_STATUS_ACK); + + /* Tell the host we've known how to drive the device. */ + zxdh_vtpci_set_status(hw, ZXDH_CONFIG_STATUS_DRIVER); + /* The queue needs to be released when reconfiguring*/ + if (hw->vqs != NULL) { + zxdh_dev_free_mbufs(dev); + zxdh_free_queues(dev); + } + + hw->queue_num = nr_vq; + ret = zxdh_alloc_queues(dev, nr_vq); + if (ret < 0) + return ret; + + zxdh_datach_set(dev); + + if (zxdh_configure_intr(dev) < 0) { + PMD_INIT_LOG(ERR, "Failed to configure interrupt"); + zxdh_free_queues(dev); + return -1; + } + + zxdh_vtpci_reinit_complete(hw); + + return ret; +} + /* dev_ops for zxdh, bare necessities for basic operation */ static const struct eth_dev_ops zxdh_eth_dev_ops = { + .dev_configure = zxdh_dev_configure, .dev_infos_get = zxdh_dev_infos_get, }; diff --git a/drivers/net/zxdh/zxdh_ethdev.h b/drivers/net/zxdh/zxdh_ethdev.h index 78f5ca6c00..49ddb505d8 100644 --- a/drivers/net/zxdh/zxdh_ethdev.h +++ b/drivers/net/zxdh/zxdh_ethdev.h @@ -11,8 +11,6 @@ #include #include -#include "zxdh_queue.h" - #ifdef __cplusplus extern "C" { #endif @@ -25,16 +23,23 @@ extern "C" { #define ZXDH_E312_PF_DEVICEID 0x8049 #define ZXDH_E312_VF_DEVICEID 0x8060 -#define ZXDH_MAX_UC_MAC_ADDRS 32 -#define ZXDH_MAX_MC_MAC_ADDRS 32 -#define ZXDH_MAX_MAC_ADDRS (ZXDH_MAX_UC_MAC_ADDRS + ZXDH_MAX_MC_MAC_ADDRS) +#define ZXDH_MAX_UC_MAC_ADDRS 32 +#define ZXDH_MAX_MC_MAC_ADDRS 32 +#define ZXDH_MAX_MAC_ADDRS (ZXDH_MAX_UC_MAC_ADDRS + ZXDH_MAX_MC_MAC_ADDRS) + +#define ZXDH_NUM_BARS 2 +#define ZXDH_RX_QUEUES_MAX 128U +#define ZXDH_TX_QUEUES_MAX 128U -#define ZXDH_NUM_BARS 2 -#define ZXDH_RX_QUEUES_MAX 128U -#define ZXDH_TX_QUEUES_MAX 128U +#define ZXDH_MIN_RX_BUFSIZE 64 +#define ZXDH_MAX_RX_PKTLEN 14000U +#define ZXDH_QUEUE_DEPTH 1024 +#define ZXDH_QUEUES_BASE 0 +#define ZXDH_TOTAL_QUEUES_NUM 4096 +#define ZXDH_QUEUES_NUM_MAX 256 +#define ZXDH_QUERES_SHARE_BASE (0x5000) -#define ZXDH_MIN_RX_BUFSIZE 64 -#define ZXDH_MAX_RX_PKTLEN 14000U +#define ZXDH_MBUF_BURST_SZ 64 union zxdh_virport_num { uint16_t vport; @@ -47,6 +52,11 @@ union zxdh_virport_num { }; }; +struct zxdh_chnl_context { + uint16_t valid; + uint16_t ph_chno; +}; + struct zxdh_hw { struct rte_eth_dev *eth_dev; struct zxdh_pci_common_cfg *common_cfg; @@ -54,6 +64,7 @@ struct zxdh_hw { struct rte_intr_handle *risc_intr; struct rte_intr_handle *dtb_intr; struct zxdh_virtqueue **vqs; + struct zxdh_chnl_context channel_context[ZXDH_QUEUES_NUM_MAX]; union zxdh_virport_num vport; uint64_t bar_addr[ZXDH_NUM_BARS]; @@ -67,6 +78,7 @@ struct zxdh_hw { uint16_t device_id; uint16_t port_id; uint16_t vfid; + uint16_t queue_num; uint8_t *isr; uint8_t weak_barriers; @@ -79,6 +91,8 @@ struct zxdh_hw { uint8_t msg_chan_init; uint8_t phyport; uint8_t panel_id; + uint8_t has_tx_offload; + uint8_t has_rx_offload; }; uint16_t zxdh_vport_to_vfid(union zxdh_virport_num v); diff --git a/drivers/net/zxdh/zxdh_pci.c b/drivers/net/zxdh/zxdh_pci.c index 5bd0df11da..f38de20baf 100644 --- a/drivers/net/zxdh/zxdh_pci.c +++ b/drivers/net/zxdh/zxdh_pci.c @@ -110,6 +110,87 @@ static uint8_t zxdh_get_isr(struct zxdh_hw *hw) return rte_read8(hw->isr); } +static uint16_t zxdh_get_queue_num(struct zxdh_hw *hw, uint16_t queue_id) +{ + rte_write16(queue_id, &hw->common_cfg->queue_select); + return rte_read16(&hw->common_cfg->queue_size); +} + +static void zxdh_set_queue_num(struct zxdh_hw *hw, uint16_t queue_id, uint16_t vq_size) +{ + rte_write16(queue_id, &hw->common_cfg->queue_select); + rte_write16(vq_size, &hw->common_cfg->queue_size); +} + +static int32_t check_vq_phys_addr_ok(struct zxdh_virtqueue *vq) +{ + if ((vq->vq_ring_mem + vq->vq_ring_size - 1) >> (ZXDH_PCI_QUEUE_ADDR_SHIFT + 32)) { + PMD_INIT_LOG(ERR, "vring address shouldn't be above 16TB!"); + return 0; + } + return 1; +} + +static inline void io_write64_twopart(uint64_t val, uint32_t *lo, uint32_t *hi) +{ + rte_write32(val & ((1ULL << 32) - 1), lo); + rte_write32(val >> 32, hi); +} + +static int32_t zxdh_setup_queue(struct zxdh_hw *hw, struct zxdh_virtqueue *vq) +{ + uint64_t desc_addr = 0; + uint64_t avail_addr = 0; + uint64_t used_addr = 0; + uint16_t notify_off = 0; + + if (!check_vq_phys_addr_ok(vq)) + return -1; + + desc_addr = vq->vq_ring_mem; + avail_addr = desc_addr + vq->vq_nentries * sizeof(struct zxdh_vring_desc); + if (vtpci_packed_queue(vq->hw)) { + used_addr = RTE_ALIGN_CEIL((avail_addr + + sizeof(struct zxdh_vring_packed_desc_event)), + ZXDH_PCI_VRING_ALIGN); + } else { + used_addr = RTE_ALIGN_CEIL(avail_addr + offsetof(struct zxdh_vring_avail, + ring[vq->vq_nentries]), ZXDH_PCI_VRING_ALIGN); + } + + rte_write16(vq->vq_queue_index, &hw->common_cfg->queue_select); + + io_write64_twopart(desc_addr, &hw->common_cfg->queue_desc_lo, + &hw->common_cfg->queue_desc_hi); + io_write64_twopart(avail_addr, &hw->common_cfg->queue_avail_lo, + &hw->common_cfg->queue_avail_hi); + io_write64_twopart(used_addr, &hw->common_cfg->queue_used_lo, + &hw->common_cfg->queue_used_hi); + + notify_off = rte_read16(&hw->common_cfg->queue_notify_off); /* default 0 */ + notify_off = 0; + vq->notify_addr = (void *)((uint8_t *)hw->notify_base + + notify_off * hw->notify_off_multiplier); + + rte_write16(1, &hw->common_cfg->queue_enable); + + return 0; +} + +static void zxdh_del_queue(struct zxdh_hw *hw, struct zxdh_virtqueue *vq) +{ + rte_write16(vq->vq_queue_index, &hw->common_cfg->queue_select); + + io_write64_twopart(0, &hw->common_cfg->queue_desc_lo, + &hw->common_cfg->queue_desc_hi); + io_write64_twopart(0, &hw->common_cfg->queue_avail_lo, + &hw->common_cfg->queue_avail_hi); + io_write64_twopart(0, &hw->common_cfg->queue_used_lo, + &hw->common_cfg->queue_used_hi); + + rte_write16(0, &hw->common_cfg->queue_enable); +} + const struct zxdh_pci_ops zxdh_dev_pci_ops = { .read_dev_cfg = zxdh_read_dev_config, .write_dev_cfg = zxdh_write_dev_config, @@ -120,6 +201,10 @@ const struct zxdh_pci_ops zxdh_dev_pci_ops = { .set_queue_irq = zxdh_set_queue_irq, .set_config_irq = zxdh_set_config_irq, .get_isr = zxdh_get_isr, + .get_queue_num = zxdh_get_queue_num, + .set_queue_num = zxdh_set_queue_num, + .setup_queue = zxdh_setup_queue, + .del_queue = zxdh_del_queue, }; uint8_t zxdh_vtpci_isr(struct zxdh_hw *hw) @@ -146,6 +231,19 @@ void zxdh_vtpci_reset(struct zxdh_hw *hw) PMD_INIT_LOG(INFO, "port %u device reset %u ms done", hw->port_id, retry); } +void zxdh_vtpci_reinit_complete(struct zxdh_hw *hw) +{ + zxdh_vtpci_set_status(hw, ZXDH_CONFIG_STATUS_DRIVER_OK); +} + +void zxdh_vtpci_set_status(struct zxdh_hw *hw, uint8_t status) +{ + if (status != ZXDH_CONFIG_STATUS_RESET) + status |= ZXDH_VTPCI_OPS(hw)->get_status(hw); + + ZXDH_VTPCI_OPS(hw)->set_status(hw, status); +} + static void *get_cfg_addr(struct rte_pci_device *dev, struct zxdh_pci_cap *cap) { uint8_t bar = cap->bar; diff --git a/drivers/net/zxdh/zxdh_pci.h b/drivers/net/zxdh/zxdh_pci.h index 55d8c5449c..231824f3c4 100644 --- a/drivers/net/zxdh/zxdh_pci.h +++ b/drivers/net/zxdh/zxdh_pci.h @@ -8,7 +8,9 @@ #include #include +#include #include +#include #include "zxdh_ethdev.h" @@ -29,13 +31,25 @@ enum zxdh_msix_status { /* Vector value used to disable MSI for queue. */ #define ZXDH_MSI_NO_VECTOR 0x7F -#define ZXDH_PCI_CAPABILITY_LIST 0x34 -#define ZXDH_PCI_CAP_ID_VNDR 0x09 -#define ZXDH_PCI_CAP_ID_MSIX 0x11 +#define ZXDH_PCI_CAPABILITY_LIST 0x34 +#define ZXDH_PCI_CAP_ID_VNDR 0x09 +#define ZXDH_PCI_CAP_ID_MSIX 0x11 -#define ZXDH_PCI_MSIX_ENABLE 0x8000 +#define ZXDH_PCI_MSIX_ENABLE 0x8000 +#define ZXDH_PCI_VRING_ALIGN 4096 +#define ZXDH_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */ +#define ZXDH_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */ +#define ZXDH_NET_F_MTU 3 /* Initial MTU advice. */ #define ZXDH_NET_F_MAC 5 /* Host has given MAC address. */ +#define ZXDH_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */ +#define ZXDH_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */ +#define ZXDH_NET_F_GUEST_ECN 9 /* Guest can handle TSO[6] w/ ECN in. */ +#define ZXDH_NET_F_GUEST_UFO 10 /* Guest can handle UFO in. */ + +#define ZXDH_NET_F_HOST_UFO 14 /* Host can handle UFO in. */ +#define ZXDH_NET_F_HOST_TSO4 11 /* Host can handle TSOv4 in. */ +#define ZXDH_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */ #define ZXDH_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */ #define ZXDH_NET_F_STATUS 16 /* zxdh_net_config.status available */ #define ZXDH_NET_F_MQ 22 /* Device supports Receive Flow Steering */ @@ -60,6 +74,8 @@ enum zxdh_msix_status { #define ZXDH_CONFIG_STATUS_DEV_NEED_RESET 0x40 #define ZXDH_CONFIG_STATUS_FAILED 0x80 +#define ZXDH_PCI_QUEUE_ADDR_SHIFT 12 + struct zxdh_net_config { /* The config defining mac address (if ZXDH_NET_F_MAC) */ uint8_t mac[RTE_ETHER_ADDR_LEN]; @@ -122,6 +138,11 @@ static inline int32_t vtpci_with_feature(struct zxdh_hw *hw, uint64_t bit) return (hw->guest_features & (1ULL << bit)) != 0; } +static inline int32_t vtpci_packed_queue(struct zxdh_hw *hw) +{ + return vtpci_with_feature(hw, ZXDH_F_RING_PACKED); +} + struct zxdh_pci_ops { void (*read_dev_cfg)(struct zxdh_hw *hw, size_t offset, void *dst, int32_t len); void (*write_dev_cfg)(struct zxdh_hw *hw, size_t offset, const void *src, int32_t len); @@ -134,6 +155,11 @@ struct zxdh_pci_ops { uint16_t (*set_queue_irq)(struct zxdh_hw *hw, struct zxdh_virtqueue *vq, uint16_t vec); uint16_t (*set_config_irq)(struct zxdh_hw *hw, uint16_t vec); uint8_t (*get_isr)(struct zxdh_hw *hw); + uint16_t (*get_queue_num)(struct zxdh_hw *hw, uint16_t queue_id); + void (*set_queue_num)(struct zxdh_hw *hw, uint16_t queue_id, uint16_t vq_size); + + int32_t (*setup_queue)(struct zxdh_hw *hw, struct zxdh_virtqueue *vq); + void (*del_queue)(struct zxdh_hw *hw, struct zxdh_virtqueue *vq); }; struct zxdh_hw_internal { @@ -156,6 +182,9 @@ uint16_t zxdh_vtpci_get_features(struct zxdh_hw *hw); uint8_t zxdh_vtpci_isr(struct zxdh_hw *hw); enum zxdh_msix_status zxdh_vtpci_msix_detect(struct rte_pci_device *dev); +void zxdh_vtpci_reinit_complete(struct zxdh_hw *hw); +void zxdh_vtpci_set_status(struct zxdh_hw *hw, uint8_t status); + #ifdef __cplusplus } #endif diff --git a/drivers/net/zxdh/zxdh_queue.c b/drivers/net/zxdh/zxdh_queue.c new file mode 100644 index 0000000000..2978a9f272 --- /dev/null +++ b/drivers/net/zxdh/zxdh_queue.c @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 ZTE Corporation + */ + +#include +#include +#include + +#include "zxdh_queue.h" +#include "zxdh_logs.h" +#include "zxdh_pci.h" +#include "zxdh_common.h" +#include "zxdh_msg.h" + +struct rte_mbuf *zxdh_virtqueue_detach_unused(struct zxdh_virtqueue *vq) +{ + struct rte_mbuf *cookie = NULL; + int32_t idx = 0; + + if (vq == NULL) + return NULL; + + for (idx = 0; idx < vq->vq_nentries; idx++) { + cookie = vq->vq_descx[idx].cookie; + if (cookie != NULL) { + vq->vq_descx[idx].cookie = NULL; + return cookie; + } + } + return NULL; +} + +static int32_t zxdh_release_channel(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + uint16_t nr_vq = hw->queue_num; + uint32_t var = 0; + uint32_t addr = 0; + uint32_t widx = 0; + uint32_t bidx = 0; + uint16_t pch = 0; + uint16_t lch = 0; + int32_t ret = 0; + + ret = zxdh_timedlock(hw, 1000); + if (ret) { + PMD_INIT_LOG(ERR, "Acquiring hw lock got failed, timeout"); + return -1; + } + + for (lch = 0; lch < nr_vq; lch++) { + if (hw->channel_context[lch].valid == 0) { + PMD_INIT_LOG(DEBUG, "Logic channel %d does not need to release", lch); + continue; + } + + pch = hw->channel_context[lch].ph_chno; + widx = pch / 32; + bidx = pch % 32; + + addr = ZXDH_QUERES_SHARE_BASE + (widx * sizeof(uint32_t)); + var = zxdh_read_bar_reg(dev, ZXDH_BAR0_INDEX, addr); + var &= ~(1 << bidx); + zxdh_write_bar_reg(dev, ZXDH_BAR0_INDEX, addr, var); + + hw->channel_context[lch].valid = 0; + hw->channel_context[lch].ph_chno = 0; + } + + zxdh_release_lock(hw); + + return 0; +} + +int32_t zxdh_get_queue_type(uint16_t vtpci_queue_idx) +{ + if (vtpci_queue_idx % 2 == 0) + return ZXDH_VTNET_RQ; + else + return ZXDH_VTNET_TQ; +} + +int32_t zxdh_free_queues(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + uint16_t nr_vq = hw->queue_num; + struct zxdh_virtqueue *vq = NULL; + int32_t queue_type = 0; + uint16_t i = 0; + + if (hw->vqs == NULL) + return 0; + + if (zxdh_release_channel(dev) < 0) { + PMD_INIT_LOG(ERR, "Failed to clear coi table"); + return -1; + } + + for (i = 0; i < nr_vq; i++) { + vq = hw->vqs[i]; + if (vq == NULL) + continue; + + ZXDH_VTPCI_OPS(hw)->del_queue(hw, vq); + queue_type = zxdh_get_queue_type(i); + if (queue_type == ZXDH_VTNET_RQ) { + rte_free(vq->sw_ring); + rte_memzone_free(vq->rxq.mz); + } else if (queue_type == ZXDH_VTNET_TQ) { + rte_memzone_free(vq->txq.mz); + rte_memzone_free(vq->txq.zxdh_net_hdr_mz); + } + + rte_free(vq); + hw->vqs[i] = NULL; + PMD_INIT_LOG(DEBUG, "Release to queue %d success!", i); + } + + rte_free(hw->vqs); + hw->vqs = NULL; + + return 0; +} diff --git a/drivers/net/zxdh/zxdh_queue.h b/drivers/net/zxdh/zxdh_queue.h index 66f37ec612..a9ba0be0d0 100644 --- a/drivers/net/zxdh/zxdh_queue.h +++ b/drivers/net/zxdh/zxdh_queue.h @@ -11,11 +11,30 @@ #include "zxdh_ethdev.h" #include "zxdh_rxtx.h" +#include "zxdh_pci.h" #ifdef __cplusplus extern "C" { #endif +enum { ZXDH_VTNET_RQ = 0, ZXDH_VTNET_TQ = 1 }; + +#define ZXDH_VIRTQUEUE_MAX_NAME_SZ 32 +#define ZXDH_RQ_QUEUE_IDX 0 +#define ZXDH_TQ_QUEUE_IDX 1 +#define ZXDH_MAX_TX_INDIRECT 8 + +/* This marks a buffer as write-only (otherwise read-only). */ +#define ZXDH_VRING_DESC_F_WRITE 2 +/* This flag means the descriptor was made available by the driver */ +#define ZXDH_VRING_PACKED_DESC_F_AVAIL (1 << (7)) + +#define ZXDH_RING_EVENT_FLAGS_ENABLE 0x0 +#define ZXDH_RING_EVENT_FLAGS_DISABLE 0x1 +#define ZXDH_RING_EVENT_FLAGS_DESC 0x2 + +#define ZXDH_VQ_RING_DESC_CHAIN_END 32768 + /** ring descriptors: 16 bytes. * These can chain together via "next". **/ @@ -26,6 +45,19 @@ struct zxdh_vring_desc { uint16_t next; /* We chain unused descriptors via this. */ } __rte_packed; +struct zxdh_vring_used_elem { + /* Index of start of used descriptor chain. */ + uint32_t id; + /* Total length of the descriptor chain which was written to. */ + uint32_t len; +}; + +struct zxdh_vring_used { + uint16_t flags; + uint16_t idx; + struct zxdh_vring_used_elem ring[]; +}; + struct zxdh_vring_avail { uint16_t flags; uint16_t idx; @@ -102,6 +134,147 @@ struct zxdh_virtqueue { struct zxdh_vq_desc_extra vq_descx[]; } __rte_packed; +struct zxdh_type_hdr { + uint8_t port; /* bit[0:1] 00-np 01-DRS 10-DTP */ + uint8_t pd_len; + uint8_t num_buffers; + uint8_t reserved; +} __rte_packed; /* 4B */ + +struct zxdh_pi_hdr { + uint8_t pi_len; + uint8_t pkt_type; + uint16_t vlan_id; + uint32_t ipv6_extend; + uint16_t l3_offset; + uint16_t l4_offset; + uint8_t phy_port; + uint8_t pkt_flag_hi8; + uint16_t pkt_flag_lw16; + union { + struct { + uint64_t sa_idx; + uint8_t reserved_8[8]; + } dl; + struct { + uint32_t lro_flag; + uint32_t lro_mss; + uint16_t err_code; + uint16_t pm_id; + uint16_t pkt_len; + uint8_t reserved[2]; + } ul; + }; +} __rte_packed; /* 32B */ + +struct zxdh_pd_hdr_dl { + uint32_t ol_flag; + uint8_t tag_idx; + uint8_t tag_data; + uint16_t dst_vfid; + uint32_t svlan_insert; + uint32_t cvlan_insert; +} __rte_packed; /* 16B */ + +struct zxdh_net_hdr_dl { + struct zxdh_type_hdr type_hdr; /* 4B */ + struct zxdh_pi_hdr pi_hdr; /* 32B */ + struct zxdh_pd_hdr_dl pd_hdr; /* 16B */ +} __rte_packed; + +struct zxdh_pd_hdr_ul { + uint32_t pkt_flag; + uint32_t rss_hash; + uint32_t fd; + uint32_t striped_vlan_tci; + /* ovs */ + uint8_t tag_idx; + uint8_t tag_data; + uint16_t src_vfid; + /* */ + uint16_t pkt_type_out; + uint16_t pkt_type_in; +} __rte_packed; /* 24B */ + +struct zxdh_net_hdr_ul { + struct zxdh_type_hdr type_hdr; /* 4B */ + struct zxdh_pi_hdr pi_hdr; /* 32B */ + struct zxdh_pd_hdr_ul pd_hdr; /* 24B */ +} __rte_packed; /* 60B */ + +struct zxdh_tx_region { + struct zxdh_net_hdr_dl tx_hdr; + union { + struct zxdh_vring_desc tx_indir[ZXDH_MAX_TX_INDIRECT]; + struct zxdh_vring_packed_desc tx_packed_indir[ZXDH_MAX_TX_INDIRECT]; + } __rte_packed; +}; + +static inline size_t vring_size(struct zxdh_hw *hw, uint32_t num, unsigned long align) +{ + size_t size; + + if (vtpci_packed_queue(hw)) { + size = num * sizeof(struct zxdh_vring_packed_desc); + size += sizeof(struct zxdh_vring_packed_desc_event); + size = RTE_ALIGN_CEIL(size, align); + size += sizeof(struct zxdh_vring_packed_desc_event); + return size; + } + + size = num * sizeof(struct zxdh_vring_desc); + size += sizeof(struct zxdh_vring_avail) + (num * sizeof(uint16_t)); + size = RTE_ALIGN_CEIL(size, align); + size += sizeof(struct zxdh_vring_used) + (num * sizeof(struct zxdh_vring_used_elem)); + return size; +} + +static inline void vring_init_packed(struct zxdh_vring_packed *vr, uint8_t *p, + unsigned long align, uint32_t num) +{ + vr->num = num; + vr->desc = (struct zxdh_vring_packed_desc *)p; + vr->driver = (struct zxdh_vring_packed_desc_event *)(p + + vr->num * sizeof(struct zxdh_vring_packed_desc)); + vr->device = (struct zxdh_vring_packed_desc_event *)RTE_ALIGN_CEIL(((uintptr_t)vr->driver + + sizeof(struct zxdh_vring_packed_desc_event)), align); +} + +static inline void vring_desc_init_packed(struct zxdh_virtqueue *vq, int32_t n) +{ + int32_t i = 0; + + for (i = 0; i < n - 1; i++) { + vq->vq_packed.ring.desc[i].id = i; + vq->vq_descx[i].next = i + 1; + } + vq->vq_packed.ring.desc[i].id = i; + vq->vq_descx[i].next = ZXDH_VQ_RING_DESC_CHAIN_END; +} + +static inline void vring_desc_init_indirect_packed(struct zxdh_vring_packed_desc *dp, int32_t n) +{ + int32_t i = 0; + + for (i = 0; i < n; i++) { + dp[i].id = (uint16_t)i; + dp[i].flags = ZXDH_VRING_DESC_F_WRITE; + } +} + +static inline void virtqueue_disable_intr(struct zxdh_virtqueue *vq) +{ + if (vq->vq_packed.event_flags_shadow != ZXDH_RING_EVENT_FLAGS_DISABLE) { + vq->vq_packed.event_flags_shadow = ZXDH_RING_EVENT_FLAGS_DISABLE; + vq->vq_packed.ring.driver->desc_event_flags = vq->vq_packed.event_flags_shadow; + } +} + +struct rte_mbuf *zxdh_virtqueue_detach_unused(struct zxdh_virtqueue *vq); +int32_t zxdh_free_queues(struct rte_eth_dev *dev); +int32_t zxdh_get_queue_type(uint16_t vtpci_queue_idx); + + #ifdef __cplusplus } #endif diff --git a/drivers/net/zxdh/zxdh_rxtx.h b/drivers/net/zxdh/zxdh_rxtx.h index 31b1c8f0a5..7d4b5481ec 100644 --- a/drivers/net/zxdh/zxdh_rxtx.h +++ b/drivers/net/zxdh/zxdh_rxtx.h @@ -40,8 +40,8 @@ struct zxdh_virtnet_rx { struct zxdh_virtnet_tx { struct zxdh_virtqueue *vq; - const struct rte_memzone *virtio_net_hdr_mz; /* memzone to populate hdr. */ - rte_iova_t virtio_net_hdr_mem; /* hdr for each xmit packet */ + const struct rte_memzone *zxdh_net_hdr_mz; /* memzone to populate hdr. */ + rte_iova_t zxdh_net_hdr_mem; /* hdr for each xmit packet */ uint16_t queue_id; /* DPDK queue index. */ uint16_t port_id; /* Device port identifier. */ struct zxdh_virtnet_stats stats;