From patchwork Wed Jun 2 09:40:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93763 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 06B6EA0524; Wed, 2 Jun 2021 11:39:46 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 6188D410E2; Wed, 2 Jun 2021 11:39:42 +0200 (CEST) Received: from smtpbg501.qq.com (smtpbg501.qq.com [203.205.250.101]) by mails.dpdk.org (Postfix) with ESMTP id 98863410D7 for ; Wed, 2 Jun 2021 11:39:38 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626771twy4yw5l Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:31 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: CPznDyfYuPcVDuN/T+4/YExe7yjZ28tGFhaMIjrRi2jhB16hWbhEeABX6tFD4 MSyFDI6OBlKK1I5B9lZ2DBDRv2BfF22Yi7sKhCe78tPpQIcc7P+8fBglnz94M0YLJ/HHy17 K1cBiu6egcyLLhVrneC7msl/TZkcqPQsW85OJ4u9ZAubYsaAedAVwCN8yIeed28mkm/HIfx Ap80dPrWOlgPU0e+WSM2bphl+yJu0e4Jn90ZCQhTwanmc97GUovzHk/uu52chJWeDyjqlHP BdF+aBLv7jUEsYGo0nyfHwWy9KQz/48VXhLLbctsTfHanMDaDIOiqi1tt4VtmZL+pGednNg W3gtsKSQ6hX8jrqssbd1wB07f6IhZddUJi5PiX3 X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:40:45 +0800 Message-Id: <20210602094108.1575640-2-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign7 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 01/24] net/ngbe: add build and doc infrastructure 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 Sender: "dev" Adding bare minimum PMD library and doc build infrastructure and claim the maintainership for ngbe PMD. Signed-off-by: Jiawen Wu --- MAINTAINERS | 6 ++++++ doc/guides/nics/features/ngbe.ini | 10 +++++++++ doc/guides/nics/index.rst | 1 + doc/guides/nics/ngbe.rst | 28 ++++++++++++++++++++++++++ doc/guides/rel_notes/release_21_08.rst | 6 ++++++ drivers/net/meson.build | 1 + drivers/net/ngbe/meson.build | 12 +++++++++++ drivers/net/ngbe/ngbe_ethdev.c | 5 +++++ drivers/net/ngbe/ngbe_ethdev.h | 5 +++++ drivers/net/ngbe/version.map | 3 +++ 10 files changed, 77 insertions(+) create mode 100644 doc/guides/nics/features/ngbe.ini create mode 100644 doc/guides/nics/ngbe.rst create mode 100644 drivers/net/ngbe/meson.build create mode 100644 drivers/net/ngbe/ngbe_ethdev.c create mode 100644 drivers/net/ngbe/ngbe_ethdev.h create mode 100644 drivers/net/ngbe/version.map diff --git a/MAINTAINERS b/MAINTAINERS index 5877a16971..04672f6eaa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -903,6 +903,12 @@ F: drivers/net/txgbe/ F: doc/guides/nics/txgbe.rst F: doc/guides/nics/features/txgbe.ini +Wangxun ngbe +M: Jiawen Wu +F: drivers/net/ngbe/ +F: doc/guides/nics/ngbe.rst +F: doc/guides/nics/features/ngbe.ini + VMware vmxnet3 M: Yong Wang F: drivers/net/vmxnet3/ diff --git a/doc/guides/nics/features/ngbe.ini b/doc/guides/nics/features/ngbe.ini new file mode 100644 index 0000000000..a7a524defc --- /dev/null +++ b/doc/guides/nics/features/ngbe.ini @@ -0,0 +1,10 @@ +; +; Supported features of the 'ngbe' network poll mode driver. +; +; Refer to default.ini for the full list of available PMD features. +; +[Features] +Linux = Y +ARMv8 = Y +x86-32 = Y +x86-64 = Y diff --git a/doc/guides/nics/index.rst b/doc/guides/nics/index.rst index 799697caf0..31a3e6bcdc 100644 --- a/doc/guides/nics/index.rst +++ b/doc/guides/nics/index.rst @@ -47,6 +47,7 @@ Network Interface Controller Drivers netvsc nfb nfp + ngbe null octeontx octeontx2 diff --git a/doc/guides/nics/ngbe.rst b/doc/guides/nics/ngbe.rst new file mode 100644 index 0000000000..4ec2623a05 --- /dev/null +++ b/doc/guides/nics/ngbe.rst @@ -0,0 +1,28 @@ +.. SPDX-License-Identifier: BSD-3-Clause + Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + +NGBE Poll Mode Driver +====================== + +The NGBE PMD (librte_pmd_ngbe) provides poll mode driver support +for Wangxun 1 Gigabit Ethernet NICs. + +Prerequisites +------------- + +- Learning about Wangxun 1 Gigabit Ethernet NICs using + ``_. + +- Follow the DPDK :ref:`Getting Started Guide for Linux ` to setup the basic DPDK environment. + +Driver compilation and testing +------------------------------ + +Refer to the document :ref:`compiling and testing a PMD for a NIC ` +for details. + +Limitations or Known issues +--------------------------- + +Build with ICC is not supported yet. +Power8, ARMv7 and BSD are not supported yet. diff --git a/doc/guides/rel_notes/release_21_08.rst b/doc/guides/rel_notes/release_21_08.rst index a6ecfdf3ce..2deac4f398 100644 --- a/doc/guides/rel_notes/release_21_08.rst +++ b/doc/guides/rel_notes/release_21_08.rst @@ -55,6 +55,12 @@ New Features Also, make sure to start the actual text at the margin. ======================================================= +* **Added Wangxun ngbe PMD.** + + Added a new PMD driver for Wangxun 1 Gigabit Ethernet NICs. + + See the :doc:`../nics/ngbe` for more details. + Removed Items ------------- diff --git a/drivers/net/meson.build b/drivers/net/meson.build index c8b5ce2980..d6c1751540 100644 --- a/drivers/net/meson.build +++ b/drivers/net/meson.build @@ -40,6 +40,7 @@ drivers = [ 'netvsc', 'nfb', 'nfp', + 'ngbe', 'null', 'octeontx', 'octeontx2', diff --git a/drivers/net/ngbe/meson.build b/drivers/net/ngbe/meson.build new file mode 100644 index 0000000000..de2d7be716 --- /dev/null +++ b/drivers/net/ngbe/meson.build @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + +if is_windows + build = false + reason = 'not supported on Windows' + subdir_done() +endif + +sources = files( + 'ngbe_ethdev.c', +) diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c new file mode 100644 index 0000000000..e424ff11a2 --- /dev/null +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h new file mode 100644 index 0000000000..e424ff11a2 --- /dev/null +++ b/drivers/net/ngbe/ngbe_ethdev.h @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + diff --git a/drivers/net/ngbe/version.map b/drivers/net/ngbe/version.map new file mode 100644 index 0000000000..4a76d1d52d --- /dev/null +++ b/drivers/net/ngbe/version.map @@ -0,0 +1,3 @@ +DPDK_21 { + local: *; +}; From patchwork Wed Jun 2 09:40:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93764 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 6B906A0524; Wed, 2 Jun 2021 11:39:53 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7F1EE410E8; Wed, 2 Jun 2021 11:39:43 +0200 (CEST) Received: from smtpbgbr2.qq.com (smtpbgbr2.qq.com [54.207.22.56]) by mails.dpdk.org (Postfix) with ESMTP id 00A8A410DF for ; Wed, 2 Jun 2021 11:39:39 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626773th1cpgd4 Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:32 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: vZzaA5K0aJ6w43YXJBQpdguRR+jVvsqAX+VAYDeosDl6UyiW0/Pd/9rZyucI6 sBomsVTOOkVG8QKmxuQnxqEPZvC0SDNnWaSO3ukoRTYaFUsHV202yn5HK2bC9ChtYSp5/sR DmtMT/S+n5r6HAYIbFYPvZLxV5Qm8staxOC/HhzGC2sfR0Gn9Zkwg+eqAMPxPd5GiKcYaI2 oSdB5eOg8JcOezAXPOqBhyZvrAo1OWhjxv3jyptrHmqjmrpCjaJseZ0aVCNxZsE6T23bXvm le+h9z7EtjxSAvaNC2xeLrc0KznlUO+KajAhwFWLvLHg3f+EJg9zFp2rrb06N0GXpzkUbyS 3MpVXAUPIzI5vAo/tdmti+lVNPK1A== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:40:46 +0800 Message-Id: <20210602094108.1575640-3-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign7 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 02/24] net/ngbe: add device IDs 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 Sender: "dev" Add device IDs for Wangxun 1Gb NICs, and register rte_ngbe_pmd. Signed-off-by: Jiawen Wu --- drivers/net/ngbe/base/meson.build | 18 +++++++ drivers/net/ngbe/base/ngbe_devids.h | 84 +++++++++++++++++++++++++++++ drivers/net/ngbe/meson.build | 6 +++ drivers/net/ngbe/ngbe_ethdev.c | 51 ++++++++++++++++++ 4 files changed, 159 insertions(+) create mode 100644 drivers/net/ngbe/base/meson.build create mode 100644 drivers/net/ngbe/base/ngbe_devids.h diff --git a/drivers/net/ngbe/base/meson.build b/drivers/net/ngbe/base/meson.build new file mode 100644 index 0000000000..c5f6467743 --- /dev/null +++ b/drivers/net/ngbe/base/meson.build @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + +sources = [] + +error_cflags = [] + +c_args = cflags +foreach flag: error_cflags + if cc.has_argument(flag) + c_args += flag + endif +endforeach + +base_lib = static_library('ngbe_base', sources, + dependencies: [static_rte_eal, static_rte_ethdev, static_rte_bus_pci], + c_args: c_args) +base_objs = base_lib.extract_all_objects() diff --git a/drivers/net/ngbe/base/ngbe_devids.h b/drivers/net/ngbe/base/ngbe_devids.h new file mode 100644 index 0000000000..81671f71da --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_devids.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#ifndef _NGBE_DEVIDS_H_ +#define _NGBE_DEVIDS_H_ + +/* + * Vendor ID + */ +#ifndef PCI_VENDOR_ID_WANGXUN +#define PCI_VENDOR_ID_WANGXUN 0x8088 +#endif + +/* + * Device IDs + */ +#define NGBE_DEV_ID_EM_VF 0x0110 +#define NGBE_SUB_DEV_ID_EM_VF 0x0110 +#define NGBE_DEV_ID_EM 0x0100 +#define NGBE_SUB_DEV_ID_EM_MVL_RGMII 0x0200 +#define NGBE_SUB_DEV_ID_EM_MVL_SFP 0x0403 +#define NGBE_SUB_DEV_ID_EM_RTL_SGMII 0x0410 +#define NGBE_SUB_DEV_ID_EM_YT8521S_SFP 0x0460 + +#define NGBE_DEV_ID_EM_WX1860AL_W 0x0100 +#define NGBE_DEV_ID_EM_WX1860AL_W_VF 0x0110 +#define NGBE_DEV_ID_EM_WX1860A2 0x0101 +#define NGBE_DEV_ID_EM_WX1860A2_VF 0x0111 +#define NGBE_DEV_ID_EM_WX1860A2S 0x0102 +#define NGBE_DEV_ID_EM_WX1860A2S_VF 0x0112 +#define NGBE_DEV_ID_EM_WX1860A4 0x0103 +#define NGBE_DEV_ID_EM_WX1860A4_VF 0x0113 +#define NGBE_DEV_ID_EM_WX1860A4S 0x0104 +#define NGBE_DEV_ID_EM_WX1860A4S_VF 0x0114 +#define NGBE_DEV_ID_EM_WX1860AL2 0x0105 +#define NGBE_DEV_ID_EM_WX1860AL2_VF 0x0115 +#define NGBE_DEV_ID_EM_WX1860AL2S 0x0106 +#define NGBE_DEV_ID_EM_WX1860AL2S_VF 0x0116 +#define NGBE_DEV_ID_EM_WX1860AL4 0x0107 +#define NGBE_DEV_ID_EM_WX1860AL4_VF 0x0117 +#define NGBE_DEV_ID_EM_WX1860AL4S 0x0108 +#define NGBE_DEV_ID_EM_WX1860AL4S_VF 0x0118 +#define NGBE_DEV_ID_EM_WX1860NCSI 0x0109 +#define NGBE_DEV_ID_EM_WX1860NCSI_VF 0x0119 +#define NGBE_DEV_ID_EM_WX1860A1 0x010A +#define NGBE_DEV_ID_EM_WX1860A1_VF 0x011A +#define NGBE_DEV_ID_EM_WX1860A1L 0x010B +#define NGBE_DEV_ID_EM_WX1860A1L_VF 0x011B +#define NGBE_SUB_DEV_ID_EM_ZTE5201_RJ45 0x0100 +#define NGBE_SUB_DEV_ID_EM_SF100F_LP 0x0103 +#define NGBE_SUB_DEV_ID_EM_M88E1512_RJ45 0x0200 +#define NGBE_SUB_DEV_ID_EM_SF100HT 0x0102 +#define NGBE_SUB_DEV_ID_EM_SF200T 0x0201 +#define NGBE_SUB_DEV_ID_EM_SF200HT 0x0202 +#define NGBE_SUB_DEV_ID_EM_SF200T_S 0x0210 +#define NGBE_SUB_DEV_ID_EM_SF200HT_S 0x0220 +#define NGBE_SUB_DEV_ID_EM_SF200HXT 0x0230 +#define NGBE_SUB_DEV_ID_EM_SF400T 0x0401 +#define NGBE_SUB_DEV_ID_EM_SF400HT 0x0402 +#define NGBE_SUB_DEV_ID_EM_M88E1512_SFP 0x0403 +#define NGBE_SUB_DEV_ID_EM_SF400T_S 0x0410 +#define NGBE_SUB_DEV_ID_EM_SF400HT_S 0x0420 +#define NGBE_SUB_DEV_ID_EM_SF400HXT 0x0430 +#define NGBE_SUB_DEV_ID_EM_SF400_OCP 0x0440 +#define NGBE_SUB_DEV_ID_EM_SF400_LY 0x0450 +#define NGBE_SUB_DEV_ID_EM_SF400_LY_YT 0x0470 + +/* Assign excessive id with masks */ +#define NGBE_INTERNAL_MASK 0x000F +#define NGBE_OEM_MASK 0x00F0 +#define NGBE_WOL_SUP_MASK 0x4000 +#define NGBE_NCSI_SUP_MASK 0x8000 + +#define NGBE_INTERNAL_SFP 0x0003 +#define NGBE_OCP_CARD 0x0040 +#define NGBE_LY_M88E1512_SFP 0x0050 +#define NGBE_YT8521S_SFP 0x0060 +#define NGBE_LY_YT8521S_SFP 0x0070 +#define NGBE_WOL_SUP 0x4000 +#define NGBE_NCSI_SUP 0x8000 + +#endif /* _NGBE_DEVIDS_H_ */ diff --git a/drivers/net/ngbe/meson.build b/drivers/net/ngbe/meson.build index de2d7be716..81173fa7f0 100644 --- a/drivers/net/ngbe/meson.build +++ b/drivers/net/ngbe/meson.build @@ -7,6 +7,12 @@ if is_windows subdir_done() endif +subdir('base') +objs = [base_objs] + sources = files( 'ngbe_ethdev.c', ) + +includes += include_directories('base') + diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index e424ff11a2..0f1fa86fe6 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -3,3 +3,54 @@ * Copyright(c) 2010-2017 Intel Corporation */ +#include + +#include + +/* + * The set of PCI devices this driver supports + */ +static const struct rte_pci_id pci_id_ngbe_map[] = { + { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A2) }, + { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A2S) }, + { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A4) }, + { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A4S) }, + { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL2) }, + { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL2S) }, + { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL4) }, + { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL4S) }, + { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860NCSI) }, + { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A1) }, + { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A1L) }, + { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL_W) }, + { .vendor_id = 0, /* sentinel */ }, +}; + +static int +eth_ngbe_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, + struct rte_pci_device *pci_dev) +{ + RTE_SET_USED(pci_dev); + + return 0; +} + +static int eth_ngbe_pci_remove(struct rte_pci_device *pci_dev) +{ + RTE_SET_USED(pci_dev); + + return 0; +} + +static struct rte_pci_driver rte_ngbe_pmd = { + .id_table = pci_id_ngbe_map, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | + RTE_PCI_DRV_INTR_LSC, + .probe = eth_ngbe_pci_probe, + .remove = eth_ngbe_pci_remove, +}; + +RTE_PMD_REGISTER_PCI(net_ngbe, rte_ngbe_pmd); +RTE_PMD_REGISTER_PCI_TABLE(net_ngbe, pci_id_ngbe_map); +RTE_PMD_REGISTER_KMOD_DEP(net_ngbe, "* igb_uio | uio_pci_generic | vfio-pci"); + From patchwork Wed Jun 2 09:40:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93766 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 AACA8A0524; Wed, 2 Jun 2021 11:40:07 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id CC72E410FB; Wed, 2 Jun 2021 11:39:45 +0200 (CEST) Received: from smtpbg511.qq.com (smtpbg511.qq.com [203.205.250.109]) by mails.dpdk.org (Postfix) with ESMTP id BA397410D7 for ; Wed, 2 Jun 2021 11:39:41 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626774tvv4n847 Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:34 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: sHM4pNkI5yT4zdy8QjEprIcJ+428Usbmz1kZ9iWhhhMZGdKd9pgPkAaOsDskB 5DXy3qcUz6pC9W4yCj+oriJkOpkLmCfOf2Kkt8GWzuz7X76bZXd52heM6bkFyROVSBBeTn2 VnLUh2gIsGt0QVFg6CvLozAywLb4Ih8gK+nrYNRbR7+wGBhjMu5BEyMPbdau6pkX2XVcUn/ cw6aF2NJN3pCAREBKP6yaoEcLSIw1z+3aNpmhi2B5CjNZfBmM/zwaYJYXncQCx8U37jzSGN B/QvJNyjBRkRcxvTchUN+Gqpx8XbUxjno0ugZdm+/sBRWBuAOIvoGqC8DVxlpiy3W5U6UJw RO/fF3lI0Yt5hE5v4HJUOG+vLuDow== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:40:47 +0800 Message-Id: <20210602094108.1575640-4-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign1 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 03/24] net/ngbe: support probe and remove 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 Sender: "dev" Add basic PCIe ethdev probe and remove. Signed-off-by: Jiawen Wu --- doc/guides/nics/features/ngbe.ini | 1 + drivers/net/ngbe/ngbe_ethdev.c | 44 ++++++++++++++++++++++++++++--- drivers/net/ngbe/ngbe_ethdev.h | 10 +++++++ 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/doc/guides/nics/features/ngbe.ini b/doc/guides/nics/features/ngbe.ini index a7a524defc..977286ac04 100644 --- a/doc/guides/nics/features/ngbe.ini +++ b/doc/guides/nics/features/ngbe.ini @@ -4,6 +4,7 @@ ; Refer to default.ini for the full list of available PMD features. ; [Features] +Multiprocess aware = Y Linux = Y ARMv8 = Y x86-32 = Y diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 0f1fa86fe6..83af1a6bc7 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -3,9 +3,11 @@ * Copyright(c) 2010-2017 Intel Corporation */ +#include #include #include +#include "ngbe_ethdev.h" /* * The set of PCI devices this driver supports @@ -26,20 +28,56 @@ static const struct rte_pci_id pci_id_ngbe_map[] = { { .vendor_id = 0, /* sentinel */ }, }; +static int +eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) +{ + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return 0; + + rte_eth_copy_pci_info(eth_dev, pci_dev); + + return 0; +} + +static int +eth_ngbe_dev_uninit(struct rte_eth_dev *eth_dev) +{ + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return 0; + + RTE_SET_USED(eth_dev); + + return 0; +} + static int eth_ngbe_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, struct rte_pci_device *pci_dev) { - RTE_SET_USED(pci_dev); + int retval; + + retval = rte_eth_dev_create(&pci_dev->device, pci_dev->device.name, + sizeof(struct ngbe_adapter), + eth_dev_pci_specific_init, pci_dev, + eth_ngbe_dev_init, NULL); + + if (retval) + return retval; return 0; } static int eth_ngbe_pci_remove(struct rte_pci_device *pci_dev) { - RTE_SET_USED(pci_dev); + struct rte_eth_dev *ethdev; - return 0; + ethdev = rte_eth_dev_allocated(pci_dev->device.name); + if (!ethdev) + return 0; + + return rte_eth_dev_destroy(ethdev, eth_ngbe_dev_uninit); } static struct rte_pci_driver rte_ngbe_pmd = { diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h index e424ff11a2..b79570dc51 100644 --- a/drivers/net/ngbe/ngbe_ethdev.h +++ b/drivers/net/ngbe/ngbe_ethdev.h @@ -3,3 +3,13 @@ * Copyright(c) 2010-2017 Intel Corporation */ +#ifndef _NGBE_ETHDEV_H_ +#define _NGBE_ETHDEV_H_ + +/* + * Structure to store private data for each driver instance (for each port). + */ +struct ngbe_adapter { +}; + +#endif /* _NGBE_ETHDEV_H_ */ From patchwork Wed Jun 2 09:40:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93765 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 21C57A0524; Wed, 2 Jun 2021 11:40:00 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id C3FFF410F0; Wed, 2 Jun 2021 11:39:44 +0200 (CEST) Received: from smtpbgeu1.qq.com (smtpbgeu1.qq.com [52.59.177.22]) by mails.dpdk.org (Postfix) with ESMTP id 1DB14410DF for ; Wed, 2 Jun 2021 11:39:42 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626776tkexfx30 Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:35 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: tSE3IANCkAu219r2i8BFISrx3LVhO0VsSarOkICzoXCjn6xiPuzDbBJSU6TJ+ dVXM8v4sGqI/rebGNNxOJfD6kx3V7e6l2VjWojafTDJ4jxvpphsB4Q1cfIk9Juj/SYqtlWv bHfIEM0k4DWzj2ihffCPmFHwAhYAwn0PJgsl/CfJ4KnUarCCWu+gDq/TWuA2m/Wdutkg/Nh j9LIrfK0Ka4NyrKIwdW7z06SYRWaxquwEa3s1lerCu5nPNtOqs/0KW8YXklrg/FOz6ciGRP ULW7IIZ50xtThy3909vSywBMlLff6TlS+gYZjCXgWUJEh0RhXuRol8XhJ9gQosmOKPhbm1t Cc39OVbgWF4YPon7PBrPlFaOhfFyz9wwpF8iQzU X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:40:48 +0800 Message-Id: <20210602094108.1575640-5-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign7 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 04/24] net/ngbe: add device init and uninit 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 Sender: "dev" Add basic init and uninit function. Map device IDs and subsystem IDs to single ID for easy operation. Signed-off-by: Jiawen Wu --- drivers/net/ngbe/base/meson.build | 4 +- drivers/net/ngbe/base/ngbe.h | 11 ++ drivers/net/ngbe/base/ngbe_hw.c | 60 ++++++++++ drivers/net/ngbe/base/ngbe_hw.h | 13 +++ drivers/net/ngbe/base/ngbe_osdep.h | 175 +++++++++++++++++++++++++++++ drivers/net/ngbe/base/ngbe_type.h | 28 +++++ drivers/net/ngbe/ngbe_ethdev.c | 36 +++++- drivers/net/ngbe/ngbe_ethdev.h | 7 ++ 8 files changed, 331 insertions(+), 3 deletions(-) create mode 100644 drivers/net/ngbe/base/ngbe.h create mode 100644 drivers/net/ngbe/base/ngbe_hw.c create mode 100644 drivers/net/ngbe/base/ngbe_hw.h create mode 100644 drivers/net/ngbe/base/ngbe_osdep.h create mode 100644 drivers/net/ngbe/base/ngbe_type.h diff --git a/drivers/net/ngbe/base/meson.build b/drivers/net/ngbe/base/meson.build index c5f6467743..fdbfa99916 100644 --- a/drivers/net/ngbe/base/meson.build +++ b/drivers/net/ngbe/base/meson.build @@ -1,7 +1,9 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. -sources = [] +sources = [ + 'ngbe_hw.c', +] error_cflags = [] diff --git a/drivers/net/ngbe/base/ngbe.h b/drivers/net/ngbe/base/ngbe.h new file mode 100644 index 0000000000..63fad12ad3 --- /dev/null +++ b/drivers/net/ngbe/base/ngbe.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + */ + +#ifndef _NGBE_H_ +#define _NGBE_H_ + +#include "ngbe_type.h" +#include "ngbe_hw.h" + +#endif /* _NGBE_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c new file mode 100644 index 0000000000..0fab47f272 --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_hw.c @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#include "ngbe_hw.h" + +void ngbe_map_device_id(struct ngbe_hw *hw) +{ + u16 oem = hw->sub_system_id & NGBE_OEM_MASK; + u16 internal = hw->sub_system_id & NGBE_INTERNAL_MASK; + hw->is_pf = true; + + /* move subsystem_device_id to device_id */ + switch (hw->device_id) { + case NGBE_DEV_ID_EM_WX1860AL_W_VF: + case NGBE_DEV_ID_EM_WX1860A2_VF: + case NGBE_DEV_ID_EM_WX1860A2S_VF: + case NGBE_DEV_ID_EM_WX1860A4_VF: + case NGBE_DEV_ID_EM_WX1860A4S_VF: + case NGBE_DEV_ID_EM_WX1860AL2_VF: + case NGBE_DEV_ID_EM_WX1860AL2S_VF: + case NGBE_DEV_ID_EM_WX1860AL4_VF: + case NGBE_DEV_ID_EM_WX1860AL4S_VF: + case NGBE_DEV_ID_EM_WX1860NCSI_VF: + case NGBE_DEV_ID_EM_WX1860A1_VF: + case NGBE_DEV_ID_EM_WX1860A1L_VF: + hw->device_id = NGBE_DEV_ID_EM_VF; + hw->sub_device_id = NGBE_SUB_DEV_ID_EM_VF; + hw->is_pf = false; + break; + case NGBE_DEV_ID_EM_WX1860AL_W: + case NGBE_DEV_ID_EM_WX1860A2: + case NGBE_DEV_ID_EM_WX1860A2S: + case NGBE_DEV_ID_EM_WX1860A4: + case NGBE_DEV_ID_EM_WX1860A4S: + case NGBE_DEV_ID_EM_WX1860AL2: + case NGBE_DEV_ID_EM_WX1860AL2S: + case NGBE_DEV_ID_EM_WX1860AL4: + case NGBE_DEV_ID_EM_WX1860AL4S: + case NGBE_DEV_ID_EM_WX1860NCSI: + case NGBE_DEV_ID_EM_WX1860A1: + case NGBE_DEV_ID_EM_WX1860A1L: + hw->device_id = NGBE_DEV_ID_EM; + if (oem == NGBE_LY_M88E1512_SFP || + internal == NGBE_INTERNAL_SFP) + hw->sub_device_id = NGBE_SUB_DEV_ID_EM_MVL_SFP; + else if (hw->sub_system_id == NGBE_SUB_DEV_ID_EM_M88E1512_RJ45) + hw->sub_device_id = NGBE_SUB_DEV_ID_EM_MVL_RGMII; + else if (oem == NGBE_YT8521S_SFP || + oem == NGBE_LY_YT8521S_SFP) + hw->sub_device_id = NGBE_SUB_DEV_ID_EM_YT8521S_SFP; + else + hw->sub_device_id = NGBE_SUB_DEV_ID_EM_RTL_SGMII; + break; + default: + break; + } +} + diff --git a/drivers/net/ngbe/base/ngbe_hw.h b/drivers/net/ngbe/base/ngbe_hw.h new file mode 100644 index 0000000000..b320d126ec --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_hw.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#ifndef _NGBE_HW_H_ +#define _NGBE_HW_H_ + +#include "ngbe_type.h" + +void ngbe_map_device_id(struct ngbe_hw *hw); + +#endif /* _NGBE_HW_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_osdep.h b/drivers/net/ngbe/base/ngbe_osdep.h new file mode 100644 index 0000000000..ef3d3d9180 --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_osdep.h @@ -0,0 +1,175 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#ifndef _NGBE_OS_H_ +#define _NGBE_OS_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RTE_LIBRTE_NGBE_TM DCPV(1, 0) +#define TMZ_PADDR(mz) ((mz)->iova) +#define TMZ_VADDR(mz) ((mz)->addr) +#define TDEV_NAME(eth_dev) ((eth_dev)->device->name) + +#define ngbe_unused __rte_unused + +#define usec_delay(x) rte_delay_us(x) +#define msec_delay(x) rte_delay_ms(x) +#define usleep(x) rte_delay_us(x) +#define msleep(x) rte_delay_ms(x) + +#define FALSE 0 +#define TRUE 1 + +#ifndef false +#define false 0 +#endif +#ifndef true +#define true 1 +#endif +#define min(a, b) RTE_MIN(a, b) +#define max(a, b) RTE_MAX(a, b) + +/* Bunch of defines for shared code bogosity */ + +static inline void UNREFERENCED(const char *a __rte_unused, ...) {} +#define UNREFERENCED_PARAMETER(args...) UNREFERENCED("", ##args) + +#define STATIC static + +typedef uint8_t u8; +typedef int8_t s8; +typedef uint16_t u16; +typedef int16_t s16; +typedef uint32_t u32; +typedef int32_t s32; +typedef uint64_t u64; +typedef int64_t s64; + +/* Little Endian defines */ +#ifndef __le16 +#define __le16 u16 +#define __le32 u32 +#define __le64 u64 +#endif +#ifndef __be16 +#define __be16 u16 +#define __be32 u32 +#define __be64 u64 +#endif + +/* Bit shift and mask */ +#define BIT_MASK4 (0x0000000FU) +#define BIT_MASK8 (0x000000FFU) +#define BIT_MASK16 (0x0000FFFFU) +#define BIT_MASK32 (0xFFFFFFFFU) +#define BIT_MASK64 (0xFFFFFFFFFFFFFFFFUL) + +#ifndef cpu_to_le32 +#define cpu_to_le16(v) rte_cpu_to_le_16((u16)(v)) +#define cpu_to_le32(v) rte_cpu_to_le_32((u32)(v)) +#define cpu_to_le64(v) rte_cpu_to_le_64((u64)(v)) +#define le_to_cpu16(v) rte_le_to_cpu_16((u16)(v)) +#define le_to_cpu32(v) rte_le_to_cpu_32((u32)(v)) +#define le_to_cpu64(v) rte_le_to_cpu_64((u64)(v)) + +#define cpu_to_be16(v) rte_cpu_to_be_16((u16)(v)) +#define cpu_to_be32(v) rte_cpu_to_be_32((u32)(v)) +#define cpu_to_be64(v) rte_cpu_to_be_64((u64)(v)) +#define be_to_cpu16(v) rte_be_to_cpu_16((u16)(v)) +#define be_to_cpu32(v) rte_be_to_cpu_32((u32)(v)) +#define be_to_cpu64(v) rte_be_to_cpu_64((u64)(v)) + +#define le_to_be16(v) rte_bswap16((u16)(v)) +#define le_to_be32(v) rte_bswap32((u32)(v)) +#define le_to_be64(v) rte_bswap64((u64)(v)) +#define be_to_le16(v) rte_bswap16((u16)(v)) +#define be_to_le32(v) rte_bswap32((u32)(v)) +#define be_to_le64(v) rte_bswap64((u64)(v)) + +#define npu_to_le16(v) (v) +#define npu_to_le32(v) (v) +#define npu_to_le64(v) (v) +#define le_to_npu16(v) (v) +#define le_to_npu32(v) (v) +#define le_to_npu64(v) (v) + +#define npu_to_be16(v) le_to_be16((u16)(v)) +#define npu_to_be32(v) le_to_be32((u32)(v)) +#define npu_to_be64(v) le_to_be64((u64)(v)) +#define be_to_npu16(v) be_to_le16((u16)(v)) +#define be_to_npu32(v) be_to_le32((u32)(v)) +#define be_to_npu64(v) be_to_le64((u64)(v)) +#endif /* !cpu_to_le32 */ + +static inline u16 REVERT_BIT_MASK16(u16 mask) +{ + mask = ((mask & 0x5555) << 1) | ((mask & 0xAAAA) >> 1); + mask = ((mask & 0x3333) << 2) | ((mask & 0xCCCC) >> 2); + mask = ((mask & 0x0F0F) << 4) | ((mask & 0xF0F0) >> 4); + return ((mask & 0x00FF) << 8) | ((mask & 0xFF00) >> 8); +} + +static inline u32 REVERT_BIT_MASK32(u32 mask) +{ + mask = ((mask & 0x55555555) << 1) | ((mask & 0xAAAAAAAA) >> 1); + mask = ((mask & 0x33333333) << 2) | ((mask & 0xCCCCCCCC) >> 2); + mask = ((mask & 0x0F0F0F0F) << 4) | ((mask & 0xF0F0F0F0) >> 4); + mask = ((mask & 0x00FF00FF) << 8) | ((mask & 0xFF00FF00) >> 8); + return ((mask & 0x0000FFFF) << 16) | ((mask & 0xFFFF0000) >> 16); +} + +static inline u64 REVERT_BIT_MASK64(u64 mask) +{ + mask = ((mask & 0x5555555555555555) << 1) | + ((mask & 0xAAAAAAAAAAAAAAAA) >> 1); + mask = ((mask & 0x3333333333333333) << 2) | + ((mask & 0xCCCCCCCCCCCCCCCC) >> 2); + mask = ((mask & 0x0F0F0F0F0F0F0F0F) << 4) | + ((mask & 0xF0F0F0F0F0F0F0F0) >> 4); + mask = ((mask & 0x00FF00FF00FF00FF) << 8) | + ((mask & 0xFF00FF00FF00FF00) >> 8); + mask = ((mask & 0x0000FFFF0000FFFF) << 16) | + ((mask & 0xFFFF0000FFFF0000) >> 16); + return ((mask & 0x00000000FFFFFFFF) << 32) | + ((mask & 0xFFFFFFFF00000000) >> 32); +} + +#define IOMEM + +#define prefetch(x) rte_prefetch0(x) + +#define ARRAY_SIZE(x) ((int32_t)RTE_DIM(x)) + +#ifndef MAX_UDELAY_MS +#define MAX_UDELAY_MS 5 +#endif + +#define ETH_ADDR_LEN 6 +#define ETH_FCS_LEN 4 + +/* Check whether address is multicast. This is little-endian specific check.*/ +#define NGBE_IS_MULTICAST(address) \ + rte_is_multicast_ether_addr(address) + +/* Check whether an address is broadcast. */ +#define NGBE_IS_BROADCAST(address) \ + rte_is_broadcast_ether_addr(address) + +#define ETH_P_8021Q 0x8100 +#define ETH_P_8021AD 0x88A8 + +#endif /* _NGBE_OS_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h new file mode 100644 index 0000000000..b6bde11dcd --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_type.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#ifndef _NGBE_TYPE_H_ +#define _NGBE_TYPE_H_ + +#define NGBE_ALIGN 128 /* as intel did */ + +#include "ngbe_osdep.h" +#include "ngbe_devids.h" + +struct ngbe_hw { + void IOMEM *hw_addr; + u16 device_id; + u16 vendor_id; + u16 sub_device_id; + u16 sub_system_id; + bool allow_unsupported_sfp; + + uint64_t isb_dma; + void IOMEM *isb_mem; + + bool is_pf; +}; + +#endif /* _NGBE_TYPE_H_ */ diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 83af1a6bc7..3431a9a9a7 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -6,9 +6,11 @@ #include #include -#include +#include "base/ngbe.h" #include "ngbe_ethdev.h" +static int ngbe_dev_close(struct rte_eth_dev *dev); + /* * The set of PCI devices this driver supports */ @@ -32,12 +34,31 @@ static int eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) { struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); + struct ngbe_hw *hw = NGBE_DEV_HW(eth_dev); + const struct rte_memzone *mz; if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; rte_eth_copy_pci_info(eth_dev, pci_dev); + /* Vendor and Device ID need to be set before init of shared code */ + hw->device_id = pci_dev->id.device_id; + hw->vendor_id = pci_dev->id.vendor_id; + hw->sub_system_id = pci_dev->id.subsystem_device_id; + ngbe_map_device_id(hw); + hw->hw_addr = (void *)pci_dev->mem_resource[0].addr; + hw->allow_unsupported_sfp = 1; + + /* Reserve memory for interrupt status block */ + mz = rte_eth_dma_zone_reserve(eth_dev, "ngbe_driver", -1, + 16, NGBE_ALIGN, SOCKET_ID_ANY); + if (mz == NULL) + return -ENOMEM; + + hw->isb_dma = TMZ_PADDR(mz); + hw->isb_mem = TMZ_VADDR(mz); + return 0; } @@ -47,7 +68,7 @@ eth_ngbe_dev_uninit(struct rte_eth_dev *eth_dev) if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; - RTE_SET_USED(eth_dev); + ngbe_dev_close(eth_dev); return 0; } @@ -88,6 +109,17 @@ static struct rte_pci_driver rte_ngbe_pmd = { .remove = eth_ngbe_pci_remove, }; +/* + * Reset and stop device. + */ +static int +ngbe_dev_close(struct rte_eth_dev *dev) +{ + RTE_SET_USED(dev); + + return 0; +} + RTE_PMD_REGISTER_PCI(net_ngbe, rte_ngbe_pmd); RTE_PMD_REGISTER_PCI_TABLE(net_ngbe, pci_id_ngbe_map); RTE_PMD_REGISTER_KMOD_DEP(net_ngbe, "* igb_uio | uio_pci_generic | vfio-pci"); diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h index b79570dc51..f6cee4a4a9 100644 --- a/drivers/net/ngbe/ngbe_ethdev.h +++ b/drivers/net/ngbe/ngbe_ethdev.h @@ -10,6 +10,13 @@ * Structure to store private data for each driver instance (for each port). */ struct ngbe_adapter { + struct ngbe_hw hw; }; +#define NGBE_DEV_ADAPTER(dev) \ + ((struct ngbe_adapter *)(dev)->data->dev_private) + +#define NGBE_DEV_HW(dev) \ + (&((struct ngbe_adapter *)(dev)->data->dev_private)->hw) + #endif /* _NGBE_ETHDEV_H_ */ From patchwork Wed Jun 2 09:40:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93767 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 11C67A0524; Wed, 2 Jun 2021 11:40:17 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 65E384111B; Wed, 2 Jun 2021 11:39:47 +0200 (CEST) Received: from smtpproxy21.qq.com (smtpbg704.qq.com [203.205.195.105]) by mails.dpdk.org (Postfix) with ESMTP id E8ECD410DF for ; Wed, 2 Jun 2021 11:39:42 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626777tm4ogqo8 Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:37 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: Ip9gq/n0Aa7D3NRyXJrTXD0DD9RnKbpvLggcVnI0I5+mt7zdFqNXzUd6D8SBi N40yxByx7n2L+jZZJhL2/31gobXKFnmjAcasZsstlZAGAm+17HNCgeLaG292a6KeBuc6lY/ TSuurEuwEzrhDRrn9ESo8wCe+155knx99v5g7MN+IwPDYGvsvm3yMF7JlrP0sOJp/Ivy9Yw 79OGC1UHv+NssMMtdZvFv00iJdB9FH1/bmH8h2zQGD0SqqxBnw0m05r3nhurvVrPvniaWZi hGu3JP2UmaULo0Iq7HWH+71ycEDwNiquKjwIgrTUU9HHtiy/F5754gnGVmR2DNJs0/gy5ya GbVeGwt9uqJBRAUxupanreRKY6oWQ== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:40:49 +0800 Message-Id: <20210602094108.1575640-6-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign7 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 05/24] net/ngbe: add log type and error type 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 Sender: "dev" Add log type and error type to trace functions. Signed-off-by: Jiawen Wu --- doc/guides/nics/ngbe.rst | 20 +++++ drivers/net/ngbe/base/ngbe_status.h | 125 ++++++++++++++++++++++++++++ drivers/net/ngbe/base/ngbe_type.h | 1 + drivers/net/ngbe/ngbe_ethdev.c | 16 ++++ drivers/net/ngbe/ngbe_logs.h | 46 ++++++++++ 5 files changed, 208 insertions(+) create mode 100644 drivers/net/ngbe/base/ngbe_status.h create mode 100644 drivers/net/ngbe/ngbe_logs.h diff --git a/doc/guides/nics/ngbe.rst b/doc/guides/nics/ngbe.rst index 4ec2623a05..c274a15aab 100644 --- a/doc/guides/nics/ngbe.rst +++ b/doc/guides/nics/ngbe.rst @@ -15,6 +15,26 @@ Prerequisites - Follow the DPDK :ref:`Getting Started Guide for Linux ` to setup the basic DPDK environment. +Pre-Installation Configuration +------------------------------ + +Dynamic Logging Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +One may leverage EAL option "--log-level" to change default levels +for the log types supported by the driver. The option is used with +an argument typically consisting of two parts separated by a colon. + +NGBE PMD provides the following log types available for control: + +- ``pmd.net.ngbe.driver`` (default level is **notice**) + + Affects driver-wide messages unrelated to any particular devices. + +- ``pmd.net.ngbe.init`` (default level is **notice**) + + Extra logging of the messages during PMD initialization. + Driver compilation and testing ------------------------------ diff --git a/drivers/net/ngbe/base/ngbe_status.h b/drivers/net/ngbe/base/ngbe_status.h new file mode 100644 index 0000000000..b1836c6479 --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_status.h @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#ifndef _NGBE_STATUS_H_ +#define _NGBE_STATUS_H_ + +/* Error Codes: + * common error + * module error(simple) + * module error(detailed) + * + * (-256, 256): reserved for non-ngbe defined error code + */ +#define TERR_BASE (0x100) +enum ngbe_error { + TERR_NULL = TERR_BASE, + TERR_ANY, + TERR_NOSUPP, + TERR_NOIMPL, + TERR_NOMEM, + TERR_NOSPACE, + TERR_NOENTRY, + TERR_CONFIG, + TERR_ARGS, + TERR_PARAM, + TERR_INVALID, + TERR_TIMEOUT, + TERR_VERSION, + TERR_REGISTER, + TERR_FEATURE, + TERR_RESET, + TERR_AUTONEG, + TERR_MBX, + TERR_I2C, + TERR_FC, + TERR_FLASH, + TERR_DEVICE, + TERR_HOSTIF, + TERR_SRAM, + TERR_EEPROM, + TERR_EEPROM_CHECKSUM, + TERR_EEPROM_PROTECT, + TERR_EEPROM_VERSION, + TERR_MAC, + TERR_MAC_ADDR, + TERR_SFP, + TERR_SFP_INITSEQ, + TERR_SFP_PRESENT, + TERR_SFP_SUPPORT, + TERR_SFP_SETUP, + TERR_PHY, + TERR_PHY_ADDR, + TERR_PHY_INIT, + TERR_FDIR_CMD, + TERR_FDIR_REINIT, + TERR_SWFW_SYNC, + TERR_SWFW_COMMAND, + TERR_FC_CFG, + TERR_FC_NEGO, + TERR_LINK_SETUP, + TERR_PCIE_PENDING, + TERR_PBA_SECTION, + TERR_OVERTEMP, + TERR_UNDERTEMP, + TERR_XPCS_POWERUP, +}; + +/* WARNING: just for legacy compatibility */ +#define NGBE_NOT_IMPLEMENTED 0x7FFFFFFF +#define NGBE_ERR_OPS_DUMMY 0x3FFFFFFF + +/* Error Codes */ +#define NGBE_ERR_EEPROM -(TERR_BASE + 1) +#define NGBE_ERR_EEPROM_CHECKSUM -(TERR_BASE + 2) +#define NGBE_ERR_PHY -(TERR_BASE + 3) +#define NGBE_ERR_CONFIG -(TERR_BASE + 4) +#define NGBE_ERR_PARAM -(TERR_BASE + 5) +#define NGBE_ERR_MAC_TYPE -(TERR_BASE + 6) +#define NGBE_ERR_UNKNOWN_PHY -(TERR_BASE + 7) +#define NGBE_ERR_LINK_SETUP -(TERR_BASE + 8) +#define NGBE_ERR_ADAPTER_STOPPED -(TERR_BASE + 9) +#define NGBE_ERR_INVALID_MAC_ADDR -(TERR_BASE + 10) +#define NGBE_ERR_DEVICE_NOT_SUPPORTED -(TERR_BASE + 11) +#define NGBE_ERR_MASTER_REQUESTS_PENDING -(TERR_BASE + 12) +#define NGBE_ERR_INVALID_LINK_SETTINGS -(TERR_BASE + 13) +#define NGBE_ERR_AUTONEG_NOT_COMPLETE -(TERR_BASE + 14) +#define NGBE_ERR_RESET_FAILED -(TERR_BASE + 15) +#define NGBE_ERR_SWFW_SYNC -(TERR_BASE + 16) +#define NGBE_ERR_PHY_ADDR_INVALID -(TERR_BASE + 17) +#define NGBE_ERR_I2C -(TERR_BASE + 18) +#define NGBE_ERR_SFP_NOT_SUPPORTED -(TERR_BASE + 19) +#define NGBE_ERR_SFP_NOT_PRESENT -(TERR_BASE + 20) +#define NGBE_ERR_SFP_NO_INIT_SEQ_PRESENT -(TERR_BASE + 21) +#define NGBE_ERR_NO_SAN_ADDR_PTR -(TERR_BASE + 22) +#define NGBE_ERR_FDIR_REINIT_FAILED -(TERR_BASE + 23) +#define NGBE_ERR_EEPROM_VERSION -(TERR_BASE + 24) +#define NGBE_ERR_NO_SPACE -(TERR_BASE + 25) +#define NGBE_ERR_OVERTEMP -(TERR_BASE + 26) +#define NGBE_ERR_FC_NOT_NEGOTIATED -(TERR_BASE + 27) +#define NGBE_ERR_FC_NOT_SUPPORTED -(TERR_BASE + 28) +#define NGBE_ERR_SFP_SETUP_NOT_COMPLETE -(TERR_BASE + 30) +#define NGBE_ERR_PBA_SECTION -(TERR_BASE + 31) +#define NGBE_ERR_INVALID_ARGUMENT -(TERR_BASE + 32) +#define NGBE_ERR_HOST_INTERFACE_COMMAND -(TERR_BASE + 33) +#define NGBE_ERR_OUT_OF_MEM -(TERR_BASE + 34) +#define NGBE_ERR_FEATURE_NOT_SUPPORTED -(TERR_BASE + 36) +#define NGBE_ERR_EEPROM_PROTECTED_REGION -(TERR_BASE + 37) +#define NGBE_ERR_FDIR_CMD_INCOMPLETE -(TERR_BASE + 38) +#define NGBE_ERR_FW_RESP_INVALID -(TERR_BASE + 39) +#define NGBE_ERR_TOKEN_RETRY -(TERR_BASE + 40) +#define NGBE_ERR_FLASH_LOADING_FAILED -(TERR_BASE + 41) + +#define NGBE_ERR_NOSUPP -(TERR_BASE + 42) +#define NGBE_ERR_UNDERTEMP -(TERR_BASE + 43) +#define NGBE_ERR_XPCS_POWER_UP_FAILED -(TERR_BASE + 44) +#define NGBE_ERR_PHY_INIT_NOT_DONE -(TERR_BASE + 45) +#define NGBE_ERR_TIMEOUT -(TERR_BASE + 46) +#define NGBE_ERR_REGISTER -(TERR_BASE + 47) +#define NGBE_ERR_MNG_ACCESS_FAILED -(TERR_BASE + 49) +#define NGBE_ERR_PHY_TYPE -(TERR_BASE + 50) +#define NGBE_ERR_PHY_TIMEOUT -(TERR_BASE + 51) + +#endif /* _NGBE_STATUS_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h index b6bde11dcd..bcc9f74216 100644 --- a/drivers/net/ngbe/base/ngbe_type.h +++ b/drivers/net/ngbe/base/ngbe_type.h @@ -8,6 +8,7 @@ #define NGBE_ALIGN 128 /* as intel did */ +#include "ngbe_status.h" #include "ngbe_osdep.h" #include "ngbe_devids.h" diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 3431a9a9a7..f24c3e173e 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -6,6 +6,7 @@ #include #include +#include "ngbe_logs.h" #include "base/ngbe.h" #include "ngbe_ethdev.h" @@ -37,6 +38,8 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) struct ngbe_hw *hw = NGBE_DEV_HW(eth_dev); const struct rte_memzone *mz; + PMD_INIT_FUNC_TRACE(); + if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; @@ -65,6 +68,8 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) static int eth_ngbe_dev_uninit(struct rte_eth_dev *eth_dev) { + PMD_INIT_FUNC_TRACE(); + if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; @@ -115,6 +120,8 @@ static struct rte_pci_driver rte_ngbe_pmd = { static int ngbe_dev_close(struct rte_eth_dev *dev) { + PMD_INIT_FUNC_TRACE(); + RTE_SET_USED(dev); return 0; @@ -124,3 +131,12 @@ RTE_PMD_REGISTER_PCI(net_ngbe, rte_ngbe_pmd); RTE_PMD_REGISTER_PCI_TABLE(net_ngbe, pci_id_ngbe_map); RTE_PMD_REGISTER_KMOD_DEP(net_ngbe, "* igb_uio | uio_pci_generic | vfio-pci"); +RTE_LOG_REGISTER(ngbe_logtype_init, pmd.net.ngbe.init, NOTICE); +RTE_LOG_REGISTER(ngbe_logtype_driver, pmd.net.ngbe.driver, NOTICE); + +#ifdef RTE_ETHDEV_DEBUG_RX + RTE_LOG_REGISTER(ngbe_logtype_rx, pmd.net.ngbe.rx, DEBUG); +#endif +#ifdef RTE_ETHDEV_DEBUG_TX + RTE_LOG_REGISTER(ngbe_logtype_tx, pmd.net.ngbe.tx, DEBUG); +#endif diff --git a/drivers/net/ngbe/ngbe_logs.h b/drivers/net/ngbe/ngbe_logs.h new file mode 100644 index 0000000000..c5d1ab0930 --- /dev/null +++ b/drivers/net/ngbe/ngbe_logs.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#ifndef _NGBE_LOGS_H_ +#define _NGBE_LOGS_H_ + +/* + * PMD_USER_LOG: for user + */ +extern int ngbe_logtype_init; +#define PMD_INIT_LOG(level, fmt, args...) \ + rte_log(RTE_LOG_ ## level, ngbe_logtype_init, \ + "%s(): " fmt "\n", __func__, ##args) + +extern int ngbe_logtype_driver; +#define PMD_DRV_LOG(level, fmt, args...) \ + rte_log(RTE_LOG_ ## level, ngbe_logtype_driver, \ + "%s(): " fmt "\n", __func__, ##args) + +#ifdef RTE_ETHDEV_DEBUG_RX +extern int ngbe_logtype_rx; +#define PMD_RX_LOG(level, fmt, args...) \ + rte_log(RTE_LOG_ ## level, ngbe_logtype_rx, \ + "%s(): " fmt "\n", __func__, ##args) +#else +#define PMD_RX_LOG(level, fmt, args...) do { } while (0) +#endif + +#ifdef RTE_ETHDEV_DEBUG_TX +extern int ngbe_logtype_tx; +#define PMD_TX_LOG(level, fmt, args...) \ + rte_log(RTE_LOG_ ## level, ngbe_logtype_tx, \ + "%s(): " fmt "\n", __func__, ##args) +#else +#define PMD_TX_LOG(level, fmt, args...) do { } while (0) +#endif + +#define TLOG_DEBUG(fmt, args...) PMD_DRV_LOG(DEBUG, fmt, ##args) + +#define DEBUGOUT(fmt, args...) TLOG_DEBUG(fmt, ##args) +#define PMD_INIT_FUNC_TRACE() TLOG_DEBUG(" >>") +#define DEBUGFUNC(fmt) TLOG_DEBUG(fmt) + +#endif /* _NGBE_LOGS_H_ */ From patchwork Wed Jun 2 09:40:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93769 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 25C73A0524; Wed, 2 Jun 2021 11:40:30 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 920D641123; Wed, 2 Jun 2021 11:39:49 +0200 (CEST) Received: from smtpbgau1.qq.com (smtpbgau1.qq.com [54.206.16.166]) by mails.dpdk.org (Postfix) with ESMTP id 4C50D410F5 for ; Wed, 2 Jun 2021 11:39:45 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626779tevjrr1d Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:38 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: tc6S58rF1JCuo5PRQwRQEWLeBTUEdnQPsfUThlJD1+kPmaiaLKGydPEo/I8fB elxaKbHVxZqYv2yXinIknS9k3/pMTZKs/Q+KJZB8WkRH59MNoD+eCpXzotzY9QbbdAQczva kp9S9ntjaxrZSHori2wqsTrpP5Q1abFC8l5icYxIMZefbn9NdQMBeprjI5PrAa3EuwcL96a wA7YuA5wwBIH1F2v8J+MOqOJ4uHR173ozYj1TB6j1O0hV8Xk5tuiy+I9VBqE2ljXtkjO/y8 U/99fdjzssaEBJI0x0U7TYMY6HdXe4pW/aoaf9zt9veAcFLqpKCPq3kkfJ6OvucrgHg1ok8 lP0AGNVuamo+1tsfSs= X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:40:50 +0800 Message-Id: <20210602094108.1575640-7-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign5 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 06/24] net/ngbe: define registers 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 Sender: "dev" Define all registers that will be used. Signed-off-by: Jiawen Wu --- drivers/net/ngbe/base/ngbe_regs.h | 1490 +++++++++++++++++++++++++++++ drivers/net/ngbe/base/ngbe_type.h | 2 + 2 files changed, 1492 insertions(+) create mode 100644 drivers/net/ngbe/base/ngbe_regs.h diff --git a/drivers/net/ngbe/base/ngbe_regs.h b/drivers/net/ngbe/base/ngbe_regs.h new file mode 100644 index 0000000000..737bd796a1 --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_regs.h @@ -0,0 +1,1490 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#ifndef _NGBE_REGS_H_ +#define _NGBE_REGS_H_ + +#define NGBE_PVMBX_QSIZE (16) /* 16*4B */ +#define NGBE_PVMBX_BSIZE (NGBE_PVMBX_QSIZE * 4) + +#define NGBE_REMOVED(a) (0) + +#define NGBE_REG_DUMMY 0xFFFFFF + +#define MS8(shift, mask) (((u8)(mask)) << (shift)) +#define LS8(val, shift, mask) (((u8)(val) & (u8)(mask)) << (shift)) +#define RS8(reg, shift, mask) (((u8)(reg) >> (shift)) & (u8)(mask)) + +#define MS16(shift, mask) (((u16)(mask)) << (shift)) +#define LS16(val, shift, mask) (((u16)(val) & (u16)(mask)) << (shift)) +#define RS16(reg, shift, mask) (((u16)(reg) >> (shift)) & (u16)(mask)) + +#define MS32(shift, mask) (((u32)(mask)) << (shift)) +#define LS32(val, shift, mask) (((u32)(val) & (u32)(mask)) << (shift)) +#define RS32(reg, shift, mask) (((u32)(reg) >> (shift)) & (u32)(mask)) + +#define MS64(shift, mask) (((u64)(mask)) << (shift)) +#define LS64(val, shift, mask) (((u64)(val) & (u64)(mask)) << (shift)) +#define RS64(reg, shift, mask) (((u64)(reg) >> (shift)) & (u64)(mask)) + +#define MS(shift, mask) MS32(shift, mask) +#define LS(val, shift, mask) LS32(val, shift, mask) +#define RS(reg, shift, mask) RS32(reg, shift, mask) + +#define ROUND_UP(x, y) (((x) + (y) - 1) / (y) * (y)) +#define ROUND_DOWN(x, y) ((x) / (y) * (y)) +#define ROUND_OVER(x, maxbits, unitbits) \ + ((x) >= 1 << (maxbits) ? 0 : (x) >> (unitbits)) + +/* autoc bits definition */ +#define NGBE_AUTOC NGBE_REG_DUMMY +#define NGBE_AUTOC_FLU MS64(0, 0x1) +#define NGBE_AUTOC_10G_PMA_PMD_MASK MS64(7, 0x3) /* parallel */ +#define NGBE_AUTOC_10G_XAUI LS64(0, 7, 0x3) +#define NGBE_AUTOC_10G_KX4 LS64(1, 7, 0x3) +#define NGBE_AUTOC_10G_CX4 LS64(2, 7, 0x3) +#define NGBE_AUTOC_10G_KR LS64(3, 7, 0x3) /* fixme */ +#define NGBE_AUTOC_1G_PMA_PMD_MASK MS64(9, 0x7) +#define NGBE_AUTOC_1G_BX LS64(0, 9, 0x7) +#define NGBE_AUTOC_1G_KX LS64(1, 9, 0x7) +#define NGBE_AUTOC_1G_SFI LS64(0, 9, 0x7) +#define NGBE_AUTOC_1G_KX_BX LS64(1, 9, 0x7) +#define NGBE_AUTOC_AN_RESTART MS64(12, 0x1) +#define NGBE_AUTOC_LMS_MASK MS64(13, 0x7) +#define NGBE_AUTOC_LMS_10G LS64(3, 13, 0x7) +#define NGBE_AUTOC_LMS_KX4_KX_KR LS64(4, 13, 0x7) +#define NGBE_AUTOC_LMS_SGMII_1G_100M LS64(5, 13, 0x7) +#define NGBE_AUTOC_LMS_KX4_KX_KR_1G_AN LS64(6, 13, 0x7) +#define NGBE_AUTOC_LMS_KX4_KX_KR_SGMII LS64(7, 13, 0x7) +#define NGBE_AUTOC_LMS_1G_LINK_NO_AN LS64(0, 13, 0x7) +#define NGBE_AUTOC_LMS_10G_LINK_NO_AN LS64(1, 13, 0x7) +#define NGBE_AUTOC_LMS_1G_AN LS64(2, 13, 0x7) +#define NGBE_AUTOC_LMS_KX4_AN LS64(4, 13, 0x7) +#define NGBE_AUTOC_LMS_KX4_AN_1G_AN LS64(6, 13, 0x7) +#define NGBE_AUTOC_LMS_ATTACH_TYPE LS64(7, 13, 0x7) +#define NGBE_AUTOC_LMS_AN MS64(15, 0x7) + +#define NGBE_AUTOC_KR_SUPP MS64(16, 0x1) +#define NGBE_AUTOC_FECR MS64(17, 0x1) +#define NGBE_AUTOC_FECA MS64(18, 0x1) +#define NGBE_AUTOC_AN_RX_ALIGN MS64(18, 0x1F) /* fixme */ +#define NGBE_AUTOC_AN_RX_DRIFT MS64(23, 0x3) +#define NGBE_AUTOC_AN_RX_LOOSE MS64(24, 0x3) +#define NGBE_AUTOC_PD_TMR MS64(25, 0x3) +#define NGBE_AUTOC_RF MS64(27, 0x1) +#define NGBE_AUTOC_ASM_PAUSE MS64(29, 0x1) +#define NGBE_AUTOC_SYM_PAUSE MS64(28, 0x1) +#define NGBE_AUTOC_PAUSE MS64(28, 0x3) +#define NGBE_AUTOC_KX_SUPP MS64(30, 0x1) +#define NGBE_AUTOC_KX4_SUPP MS64(31, 0x1) + +#define NGBE_AUTOC_10GS_PMA_PMD_MASK MS64(48, 0x3) /* serial */ +#define NGBE_AUTOC_10GS_KR LS64(0, 48, 0x3) +#define NGBE_AUTOC_10GS_XFI LS64(1, 48, 0x3) +#define NGBE_AUTOC_10GS_SFI LS64(2, 48, 0x3) +#define NGBE_AUTOC_LINK_DIA_MASK MS64(60, 0x7) +#define NGBE_AUTOC_LINK_DIA_D3_MASK LS64(5, 60, 0x7) + +#define NGBE_AUTOC_SPEED_MASK MS64(32, 0xFFFF) +#define NGBD_AUTOC_SPEED(r) RS64(r, 32, 0xFFFF) +#define NGBE_AUTOC_SPEED(v) LS64(v, 32, 0xFFFF) +#define NGBE_LINK_SPEED_UNKNOWN 0 +#define NGBE_LINK_SPEED_10M_FULL 0x0002 +#define NGBE_LINK_SPEED_100M_FULL 0x0008 +#define NGBE_LINK_SPEED_1GB_FULL 0x0020 +#define NGBE_LINK_SPEED_2_5GB_FULL 0x0400 +#define NGBE_LINK_SPEED_5GB_FULL 0x0800 +#define NGBE_LINK_SPEED_10GB_FULL 0x0080 +#define NGBE_LINK_SPEED_40GB_FULL 0x0100 +#define NGBE_AUTOC_AUTONEG MS64(63, 0x1) + + + +/* Hardware Datapath: + * RX: / Queue <- Filter \ + * Host | TC <=> SEC <=> MAC <=> PHY + * TX: \ Queue -> Filter / + * + * Packet Filter: + * RX: RSS < FDIR < Filter < Encrypt + * + * Macro Argument Naming: + * rp = ring pair [0,127] + * tc = traffic class [0,7] + * up = user priority [0,7] + * pi = pool index [0,63] + * r = register + * v = value + * s = shift + * m = mask + * i,j,k = array index + * H,L = high/low bits + * HI,LO = high/low state + */ + +#define NGBE_ETHPHYIF NGBE_REG_DUMMY +#define NGBE_ETHPHYIF_MDIO_ACT MS(1, 0x1) +#define NGBE_ETHPHYIF_MDIO_MODE MS(2, 0x1) +#define NGBE_ETHPHYIF_MDIO_BASE(r) RS(r, 3, 0x1F) +#define NGBE_ETHPHYIF_MDIO_SHARED MS(13, 0x1) +#define NGBE_ETHPHYIF_SPEED_10M MS(17, 0x1) +#define NGBE_ETHPHYIF_SPEED_100M MS(18, 0x1) +#define NGBE_ETHPHYIF_SPEED_1G MS(19, 0x1) +#define NGBE_ETHPHYIF_SPEED_2_5G MS(20, 0x1) +#define NGBE_ETHPHYIF_SPEED_10G MS(21, 0x1) +#define NGBE_ETHPHYIF_SGMII_ENABLE MS(25, 0x1) +#define NGBE_ETHPHYIF_INT_PHY_MODE MS(24, 0x1) +#define NGBE_ETHPHYIF_IO_XPCS MS(30, 0x1) +#define NGBE_ETHPHYIF_IO_EPHY MS(31, 0x1) + +/****************************************************************************** + * Chip Registers + ******************************************************************************/ +/** + * Chip Status + **/ +#define NGBE_PWR 0x010000 +#define NGBE_PWR_LAN(r) RS(r, 28, 0xC) +#define NGBE_PWR_LAN_0 (1) +#define NGBE_PWR_LAN_1 (2) +#define NGBE_PWR_LAN_2 (3) +#define NGBE_PWR_LAN_3 (4) +#define NGBE_CTL 0x010004 +#define NGBE_LOCKPF 0x010008 +#define NGBE_RST 0x01000C +#define NGBE_RST_SW MS(0, 0x1) +#define NGBE_RST_LAN(i) MS(((i) + 1), 0x1) +#define NGBE_RST_FW MS(5, 0x1) +#define NGBE_RST_ETH(i) MS(((i) + 29), 0x1) +#define NGBE_RST_GLB MS(31, 0x1) +#define NGBE_RST_DEFAULT (NGBE_RST_SW | \ + NGBE_RST_LAN(0) | \ + NGBE_RST_LAN(1) | \ + NGBE_RST_LAN(2) | \ + NGBE_RST_LAN(3)) +#define NGBE_PROB 0x010010 +#define NGBE_IODRV 0x010024 +#define NGBE_STAT 0x010028 +#define NGBE_STAT_MNGINIT MS(0, 0x1) +#define NGBE_STAT_MNGVETO MS(8, 0x1) +#define NGBE_STAT_ECCLAN0 MS(16, 0x1) +#define NGBE_STAT_ECCLAN1 MS(17, 0x1) +#define NGBE_STAT_ECCLAN2 MS(18, 0x1) +#define NGBE_STAT_ECCLAN3 MS(19, 0x1) +#define NGBE_STAT_ECCMNG MS(20, 0x1) +#define NGBE_STAT_ECCPCORE MS(21, 0X1) +#define NGBE_STAT_ECCPCIW MS(22, 0x1) +#define NGBE_STAT_ECCPCIEPHY MS(23, 0x1) +#define NGBE_STAT_ECCFMGR MS(24, 0x1) +#define NGBE_STAT_GPHY_IN_RST(i) MS(((i) + 9), 0x1) +#define NGBE_RSTSTAT 0x010030 +#define NGBE_RSTSTAT_PROG MS(20, 0x1) +#define NGBE_RSTSTAT_PREP MS(19, 0x1) +#define NGBE_RSTSTAT_TYPE_MASK MS(16, 0x7) +#define NGBE_RSTSTAT_TYPE(r) RS(r, 16, 0x7) +#define NGBE_RSTSTAT_TYPE_PE LS(0, 16, 0x7) +#define NGBE_RSTSTAT_TYPE_PWR LS(1, 16, 0x7) +#define NGBE_RSTSTAT_TYPE_HOT LS(2, 16, 0x7) +#define NGBE_RSTSTAT_TYPE_SW LS(3, 16, 0x7) +#define NGBE_RSTSTAT_TYPE_FW LS(4, 16, 0x7) +#define NGBE_RSTSTAT_TMRINIT_MASK MS(8, 0xFF) +#define NGBE_RSTSTAT_TMRINIT(v) LS(v, 8, 0xFF) +#define NGBE_RSTSTAT_TMRCNT_MASK MS(0, 0xFF) +#define NGBE_RSTSTAT_TMRCNT(v) LS(v, 0, 0xFF) +#define NGBE_PWRTMR 0x010034 + +/** + * SPI(Flash) + **/ +#define NGBE_SPICMD 0x010104 +#define NGBE_SPICMD_ADDR(v) LS(v, 0, 0xFFFFFF) +#define NGBE_SPICMD_CLK(v) LS(v, 25, 0x7) +#define NGBE_SPICMD_CMD(v) LS(v, 28, 0x7) +#define NGBE_SPIDAT 0x010108 +#define NGBE_SPIDAT_BYPASS MS(31, 0x1) +#define NGBE_SPIDAT_STATUS(v) LS(v, 16, 0xFF) +#define NGBE_SPIDAT_OPDONE MS(0, 0x1) +#define NGBE_SPISTAT 0x01010C +#define NGBE_SPISTAT_OPDONE MS(0, 0x1) +#define NGBE_SPISTAT_BPFLASH MS(31, 0x1) +#define NGBE_SPIUSRCMD 0x010110 +#define NGBE_SPICFG0 0x010114 +#define NGBE_SPICFG1 0x010118 + +/* FMGR Registers */ +#define NGBE_ILDRSTAT 0x010120 +#define NGBE_ILDRSTAT_PCIRST MS(0, 0x1) +#define NGBE_ILDRSTAT_PWRRST MS(1, 0x1) +#define NGBE_ILDRSTAT_SWRST MS(11, 0x1) +#define NGBE_ILDRSTAT_SWRST_LAN0 MS(13, 0x1) +#define NGBE_ILDRSTAT_SWRST_LAN1 MS(14, 0x1) +#define NGBE_ILDRSTAT_SWRST_LAN2 MS(15, 0x1) +#define NGBE_ILDRSTAT_SWRST_LAN3 MS(16, 0x1) + +#define NGBE_SRAM 0x010124 +#define NGBE_SRAM_SZ(v) LS(v, 28, 0x7) +#define NGBE_SRAMCTLECC 0x010130 +#define NGBE_SRAMINJECC 0x010134 +#define NGBE_SRAMECC 0x010138 + +/* Sensors for PVT(Process Voltage Temperature) */ +#define NGBE_TSCTRL 0x010300 +#define NGBE_TSCTRL_EVALMD MS(31, 0x1) +#define NGBE_TSEN 0x010304 +#define NGBE_TSEN_ENA MS(0, 0x1) +#define NGBE_TSSTAT 0x010308 +#define NGBE_TSSTAT_VLD MS(16, 0x1) +#define NGBE_TSSTAT_DATA(r) RS(r, 0, 0x3FF) +#define NGBE_TSATHRE 0x01030C +#define NGBE_TSDTHRE 0x010310 +#define NGBE_TSINTR 0x010314 +#define NGBE_TSINTR_AEN MS(0, 0x1) +#define NGBE_TSINTR_DEN MS(1, 0x1) +#define NGBE_TSALM 0x010318 +#define NGBE_TSALM_LO MS(0, 0x1) +#define NGBE_TSALM_HI MS(1, 0x1) + +#define NGBE_EFUSE_WDATA0 0x010320 +#define NGBE_EFUSE_WDATA1 0x010324 +#define NGBE_EFUSE_RDATA0 0x010328 +#define NGBE_EFUSE_RDATA1 0x01032C +#define NGBE_EFUSE_STATUS 0x010330 + +/****************************************************************************** + * Port Registers + ******************************************************************************/ +/* Internal PHY reg_offset [0,31] */ +#define NGBE_PHY_CONFIG(reg_offset) (0x014000 + (reg_offset) * 4) + +/* Port Control */ +#define NGBE_PORTCTL 0x014400 +#define NGBE_PORTCTL_VLANEXT MS(0, 0x1) +#define NGBE_PORTCTL_ETAG MS(1, 0x1) +#define NGBE_PORTCTL_QINQ MS(2, 0x1) +#define NGBE_PORTCTL_DRVLOAD MS(3, 0x1) +#define NGBE_PORTCTL_NUMVT_MASK MS(12, 0x1) +#define NGBE_PORTCTL_NUMVT_8 LS(1, 12, 0x1) +#define NGBE_PORTCTL_RSTDONE MS(14, 0x1) +#define NGBE_PORTCTL_TEREDODIA MS(27, 0x1) +#define NGBE_PORTCTL_GENEVEDIA MS(28, 0x1) +#define NGBE_PORTCTL_VXLANGPEDIA MS(30, 0x1) +#define NGBE_PORTCTL_VXLANDIA MS(31, 0x1) + +/* Port Status */ +#define NGBE_PORTSTAT 0x014404 +#define NGBE_PORTSTAT_BW_MASK MS(1, 0x7) +#define NGBE_PORTSTAT_BW_1G MS(1, 0x1) +#define NGBE_PORTSTAT_BW_100M MS(2, 0x1) +#define NGBE_PORTSTAT_BW_10M MS(3, 0x1) +#define NGBE_PORTSTAT_ID(r) RS(r, 8, 0x3) + +#define NGBE_EXTAG 0x014408 +#define NGBE_EXTAG_ETAG_MASK MS(0, 0xFFFF) +#define NGBE_EXTAG_ETAG(v) LS(v, 0, 0xFFFF) +#define NGBE_EXTAG_VLAN_MASK MS(16, 0xFFFF) +#define NGBE_EXTAG_VLAN(v) LS(v, 16, 0xFFFF) + +#define NGBE_TCPTIME 0x014420 + +#define NGBE_LEDCTL 0x014424 +#define NGBE_LEDCTL_SEL(s) MS((s), 0x1) +#define NGBE_LEDCTL_OD(s) MS(((s) + 16), 0x1) + /* s=1G(1),100M(2),10M(3) */ +#define NGBE_LEDCTL_100M (NGBE_LEDCTL_SEL(2) | NGBE_LEDCTL_OD(2)) + +#define NGBE_TAGTPID(i) (0x014430 + (i) * 4) /*0-3*/ +#define NGBE_TAGTPID_LSB_MASK MS(0, 0xFFFF) +#define NGBE_TAGTPID_LSB(v) LS(v, 0, 0xFFFF) +#define NGBE_TAGTPID_MSB_MASK MS(16, 0xFFFF) +#define NGBE_TAGTPID_MSB(v) LS(v, 16, 0xFFFF) + +#define NGBE_LAN_SPEED 0x014440 +#define NGBE_LAN_SPEED_MASK MS(0, 0x3) + +/* GPIO Registers */ +#define NGBE_GPIODATA 0x014800 +#define NGBE_GPIOBIT_0 MS(0, 0x1) /* O:tx fault */ +#define NGBE_GPIOBIT_1 MS(1, 0x1) /* O:tx disabled */ +#define NGBE_GPIOBIT_2 MS(2, 0x1) /* I:sfp module absent */ +#define NGBE_GPIOBIT_3 MS(3, 0x1) /* I:rx signal lost */ +#define NGBE_GPIOBIT_4 MS(4, 0x1) /* O:rate select, 1G(0) 10G(1) */ +#define NGBE_GPIOBIT_5 MS(5, 0x1) /* O:rate select, 1G(0) 10G(1) */ +#define NGBE_GPIOBIT_6 MS(6, 0x1) /* I:ext phy interrupt */ +#define NGBE_GPIOBIT_7 MS(7, 0x1) /* I:fan speed alarm */ +#define NGBE_GPIODIR 0x014804 +#define NGBE_GPIODIR_DDR(v) LS(v, 0, 0x3) +#define NGBE_GPIOCTL 0x014808 +#define NGBE_GPIOINTEN 0x014830 +#define NGBE_GPIOINTEN_INT(v) LS(v, 0, 0x3) +#define NGBE_GPIOINTMASK 0x014834 +#define NGBE_GPIOINTTYPE 0x014838 +#define NGBE_GPIOINTTYPE_LEVEL(v) LS(v, 0, 0x3) +#define NGBE_GPIOINTPOL 0x01483C +#define NGBE_GPIOINTPOL_ACT(v) LS(v, 0, 0x3) +#define NGBE_GPIOINTSTAT 0x014840 +#define NGBE_GPIOINTDB 0x014848 +#define NGBE_GPIOEOI 0x01484C +#define NGBE_GPIODAT 0x014850 + +/* TPH */ +#define NGBE_TPHCFG 0x014F00 + +/****************************************************************************** + * Transmit DMA Registers + ******************************************************************************/ +/* TDMA Control */ +#define NGBE_DMATXCTRL 0x018000 +#define NGBE_DMATXCTRL_ENA MS(0, 0x1) +#define NGBE_DMATXCTRL_TPID_MASK MS(16, 0xFFFF) +#define NGBE_DMATXCTRL_TPID(v) LS(v, 16, 0xFFFF) +#define NGBE_POOLTXENA(i) (0x018004 + (i) * 4) /*0*/ +#define NGBE_PRBTXDMACTL 0x018010 +#define NGBE_ECCTXDMACTL 0x018014 +#define NGBE_ECCTXDMAINJ 0x018018 +#define NGBE_ECCTXDMA 0x01801C +#define NGBE_PBTXDMATH 0x018020 +#define NGBE_QPTXLLI 0x018040 +#define NGBE_POOLTXLBET 0x018050 +#define NGBE_POOLTXASET 0x018058 +#define NGBE_POOLTXASMAC 0x018060 +#define NGBE_POOLTXASVLAN 0x018070 +#define NGBE_POOLTXDSA 0x0180A0 +#define NGBE_POOLTAG(pl) (0x018100 + (pl) * 4) /*0-7*/ +#define NGBE_POOLTAG_VTAG(v) LS(v, 0, 0xFFFF) +#define NGBE_POOLTAG_VTAG_MASK MS(0, 0xFFFF) +#define TXGBD_POOLTAG_VTAG_UP(r) RS(r, 13, 0x7) +#define NGBE_POOLTAG_TPIDSEL(v) LS(v, 24, 0x7) +#define NGBE_POOLTAG_ETAG_MASK MS(27, 0x3) +#define NGBE_POOLTAG_ETAG LS(2, 27, 0x3) +#define NGBE_POOLTAG_ACT_MASK MS(30, 0x3) +#define NGBE_POOLTAG_ACT_ALWAYS LS(1, 30, 0x3) +#define NGBE_POOLTAG_ACT_NEVER LS(2, 30, 0x3) + +/* Queue Arbiter(QoS) */ +#define NGBE_QARBTXCTL 0x018200 +#define NGBE_QARBTXCTL_DA MS(6, 0x1) +#define NGBE_QARBTXRATE 0x018404 +#define NGBE_QARBTXRATE_MIN(v) LS(v, 0, 0x3FFF) +#define NGBE_QARBTXRATE_MAX(v) LS(v, 16, 0x3FFF) + +/* ETAG */ +#define NGBE_POOLETAG(pl) (0x018700 + (pl) * 4) + +/****************************************************************************** + * Receive DMA Registers + ******************************************************************************/ +/* Receive Control */ +#define NGBE_ARBRXCTL 0x012000 +#define NGBE_ARBRXCTL_DIA MS(6, 0x1) +#define NGBE_POOLRXENA(i) (0x012004 + (i) * 4) /*0*/ +#define NGBE_PRBRDMA 0x012010 +#define NGBE_ECCRXDMACTL 0x012014 +#define NGBE_ECCRXDMAINJ 0x012018 +#define NGBE_ECCRXDMA 0x01201C +#define NGBE_POOLRXDNA 0x0120A0 +#define NGBE_QPRXDROP 0x012080 +#define NGBE_QPRXSTRPVLAN 0x012090 + +/****************************************************************************** + * Packet Buffer + ******************************************************************************/ +/* Flow Control */ +#define NGBE_FCXOFFTM 0x019200 +#define NGBE_FCWTRLO 0x019220 +#define NGBE_FCWTRLO_TH(v) LS(v, 10, 0x1FF) /*KB*/ +#define NGBE_FCWTRLO_XON MS(31, 0x1) +#define NGBE_FCWTRHI 0x019260 +#define NGBE_FCWTRHI_TH(v) LS(v, 10, 0x1FF) /*KB*/ +#define NGBE_FCWTRHI_XOFF MS(31, 0x1) +#define NGBE_RXFCRFSH 0x0192A0 +#define NGBE_RXFCFSH_TIME(v) LS(v, 0, 0xFFFF) +#define NGBE_FCSTAT 0x01CE00 +#define NGBE_FCSTAT_DLNK MS(0, 0x1) +#define NGBE_FCSTAT_ULNK MS(8, 0x1) + +#define NGBE_RXFCCFG 0x011090 +#define NGBE_RXFCCFG_FC MS(0, 0x1) +#define NGBE_TXFCCFG 0x0192A4 +#define NGBE_TXFCCFG_FC MS(3, 0x1) + +/* Data Buffer */ +#define NGBE_PBRXCTL 0x019000 +#define NGBE_PBRXCTL_ST MS(0, 0x1) +#define NGBE_PBRXCTL_ENA MS(31, 0x1) +#define NGBE_PBRXSTAT 0x019004 +#define NGBE_PBRXSIZE 0x019020 +#define NGBE_PBRXSIZE_KB(v) LS(v, 10, 0x3F) + +#define NGBE_PBRXOFTMR 0x019094 +#define NGBE_PBRXDBGCMD 0x019090 +#define NGBE_PBRXDBGDAT 0x0190A0 + +#define NGBE_PBTXSIZE 0x01CC00 + +/* LLI */ +#define NGBE_PBRXLLI 0x19080 +#define NGBE_PBRXLLI_SZLT(v) LS(v, 0, 0xFFF) +#define NGBE_PBRXLLI_UPLT(v) LS(v, 16, 0x7) +#define NGBE_PBRXLLI_UPEA MS(19, 0x1) + +/* Port Arbiter(QoS) */ +#define NGBE_PARBTXCTL 0x01CD00 +#define NGBE_PARBTXCTL_DA MS(6, 0x1) + +/****************************************************************************** + * Packet Filter (L2-7) + ******************************************************************************/ +/** + * Receive Scaling + **/ +#define NGBE_POOLRSS(pl) (0x019300 + (pl) * 4) /*0-7*/ +#define NGBE_POOLRSS_L4HDR MS(1, 0x1) +#define NGBE_POOLRSS_L3HDR MS(2, 0x1) +#define NGBE_POOLRSS_L2HDR MS(3, 0x1) +#define NGBE_POOLRSS_L2TUN MS(4, 0x1) +#define NGBE_POOLRSS_TUNHDR MS(5, 0x1) +#define NGBE_RSSTBL(i) (0x019400 + (i) * 4) /*32*/ +#define NGBE_RSSKEY(i) (0x019480 + (i) * 4) /*10*/ +#define NGBE_RACTL 0x0194F4 +#define NGBE_RACTL_RSSENA MS(2, 0x1) +#define NGBE_RACTL_RSSMASK MS(16, 0xFFFF) +#define NGBE_RACTL_RSSIPV4TCP MS(16, 0x1) +#define NGBE_RACTL_RSSIPV4 MS(17, 0x1) +#define NGBE_RACTL_RSSIPV6 MS(20, 0x1) +#define NGBE_RACTL_RSSIPV6TCP MS(21, 0x1) +#define NGBE_RACTL_RSSIPV4UDP MS(22, 0x1) +#define NGBE_RACTL_RSSIPV6UDP MS(23, 0x1) + +/** + * Flow Director + **/ +#define PERFECT_BUCKET_64KB_HASH_MASK 0x07FF /* 11 bits */ +#define PERFECT_BUCKET_128KB_HASH_MASK 0x0FFF /* 12 bits */ +#define PERFECT_BUCKET_256KB_HASH_MASK 0x1FFF /* 13 bits */ +#define SIG_BUCKET_64KB_HASH_MASK 0x1FFF /* 13 bits */ +#define SIG_BUCKET_128KB_HASH_MASK 0x3FFF /* 14 bits */ +#define SIG_BUCKET_256KB_HASH_MASK 0x7FFF /* 15 bits */ + +/** + * 5-tuple Filter + **/ +#define NGBE_5TFPORT(i) (0x019A00 + (i) * 4) /*0-7*/ +#define NGBE_5TFPORT_SRC(v) LS(v, 0, 0xFFFF) +#define NGBE_5TFPORT_DST(v) LS(v, 16, 0xFFFF) +#define NGBE_5TFCTL0(i) (0x019C00 + (i) * 4) /*0-7*/ +#define NGBE_5TFCTL0_PROTO(v) LS(v, 0, 0x3) +enum ngbe_5tuple_protocol { + NGBE_5TF_PROT_TCP = 0, + NGBE_5TF_PROT_UDP, + NGBE_5TF_PROT_SCTP, + NGBE_5TF_PROT_NONE, +}; +#define NGBE_5TFCTL0_PRI(v) LS(v, 2, 0x7) +#define NGBE_5TFCTL0_POOL(v) LS(v, 8, 0x7) +#define NGBE_5TFCTL0_MASK MS(27, 0xF) +#define NGBE_5TFCTL0_MSPORT MS(27, 0x1) +#define NGBE_5TFCTL0_MDPORT MS(28, 0x1) +#define NGBE_5TFCTL0_MPROTO MS(29, 0x1) +#define NGBE_5TFCTL0_MPOOL MS(30, 0x1) +#define NGBE_5TFCTL0_ENA MS(31, 0x1) +#define NGBE_5TFCTL1(i) (0x019E00 + (i) * 4) /*0-7*/ +#define NGBE_5TFCTL1_CHKSZ MS(12, 0x1) +#define NGBE_5TFCTL1_LLI MS(20, 0x1) +#define NGBE_5TFCTL1_QP(v) LS(v, 21, 0x7) + +/** + * Storm Control + **/ +#define NGBE_STRMCTL 0x015004 +#define NGBE_STRMCTL_MCPNSH MS(0, 0x1) +#define NGBE_STRMCTL_MCDROP MS(1, 0x1) +#define NGBE_STRMCTL_BCPNSH MS(2, 0x1) +#define NGBE_STRMCTL_BCDROP MS(3, 0x1) +#define NGBE_STRMCTL_DFTPOOL MS(4, 0x1) +#define NGBE_STRMCTL_ITVL(v) LS(v, 8, 0x3FF) +#define NGBE_STRMTH 0x015008 +#define NGBE_STRMTH_MC(v) LS(v, 0, 0xFFFF) +#define NGBE_STRMTH_BC(v) LS(v, 16, 0xFFFF) + +/****************************************************************************** + * Ether Flow + ******************************************************************************/ +#define NGBE_PSRCTL 0x015000 +#define NGBE_PSRCTL_TPE MS(4, 0x1) +#define NGBE_PSRCTL_ADHF12_MASK MS(5, 0x3) +#define NGBE_PSRCTL_ADHF12(v) LS(v, 5, 0x3) +#define NGBE_PSRCTL_UCHFENA MS(7, 0x1) +#define NGBE_PSRCTL_MCHFENA MS(7, 0x1) +#define NGBE_PSRCTL_MCP MS(8, 0x1) +#define NGBE_PSRCTL_UCP MS(9, 0x1) +#define NGBE_PSRCTL_BCA MS(10, 0x1) +#define NGBE_PSRCTL_L4CSUM MS(12, 0x1) +#define NGBE_PSRCTL_PCSD MS(13, 0x1) +#define NGBE_PSRCTL_LBENA MS(18, 0x1) +#define NGBE_FRMSZ 0x015020 +#define NGBE_FRMSZ_MAX_MASK MS(0, 0xFFFF) +#define NGBE_FRMSZ_MAX(v) LS(v, 0, 0xFFFF) +#define NGBE_VLANCTL 0x015088 +#define NGBE_VLANCTL_TPID_MASK MS(0, 0xFFFF) +#define NGBE_VLANCTL_TPID(v) LS(v, 0, 0xFFFF) +#define NGBE_VLANCTL_CFI MS(28, 0x1) +#define NGBE_VLANCTL_CFIENA MS(29, 0x1) +#define NGBE_VLANCTL_VFE MS(30, 0x1) +#define NGBE_POOLCTL 0x0151B0 +#define NGBE_POOLCTL_DEFDSA MS(29, 0x1) +#define NGBE_POOLCTL_RPLEN MS(30, 0x1) +#define NGBE_POOLCTL_MODE_MASK MS(16, 0x3) +#define NGBE_PSRPOOL_MODE_MAC LS(0, 16, 0x3) +#define NGBE_PSRPOOL_MODE_ETAG LS(1, 16, 0x3) +#define NGBE_POOLCTL_DEFPL(v) LS(v, 7, 0x7) +#define NGBE_POOLCTL_DEFPL_MASK MS(7, 0x7) + +#define NGBE_ETFLT(i) (0x015128 + (i) * 4) /*0-7*/ +#define NGBE_ETFLT_ETID(v) LS(v, 0, 0xFFFF) +#define NGBE_ETFLT_ETID_MASK MS(0, 0xFFFF) +#define NGBE_ETFLT_POOL(v) LS(v, 20, 0x7) +#define NGBE_ETFLT_POOLENA MS(26, 0x1) +#define NGBE_ETFLT_TXAS MS(29, 0x1) +#define NGBE_ETFLT_1588 MS(30, 0x1) +#define NGBE_ETFLT_ENA MS(31, 0x1) +#define NGBE_ETCLS(i) (0x019100 + (i) * 4) /*0-7*/ +#define NGBE_ETCLS_QPID(v) LS(v, 16, 0x7) +#define NGBD_ETCLS_QPID(r) RS(r, 16, 0x7) +#define NGBE_ETCLS_LLI MS(29, 0x1) +#define NGBE_ETCLS_QENA MS(31, 0x1) +#define NGBE_SYNCLS 0x019130 +#define NGBE_SYNCLS_ENA MS(0, 0x1) +#define NGBE_SYNCLS_QPID(v) LS(v, 1, 0x7) +#define NGBD_SYNCLS_QPID(r) RS(r, 1, 0x7) +#define NGBE_SYNCLS_QPID_MASK MS(1, 0x7) +#define NGBE_SYNCLS_HIPRIO MS(31, 0x1) + +/* MAC & VLAN & NVE */ +#define NGBE_PSRVLANIDX 0x016230 /*0-31*/ +#define NGBE_PSRVLAN 0x016220 +#define NGBE_PSRVLAN_VID(v) LS(v, 0, 0xFFF) +#define NGBE_PSRVLAN_EA MS(31, 0x1) +#define NGBE_PSRVLANPLM(i) (0x016224 + (i) * 4) /*0-1*/ + +/** + * Mirror Rules + **/ +#define NGBE_MIRRCTL(i) (0x015B00 + (i) * 4) +#define NGBE_MIRRCTL_POOL MS(0, 0x1) +#define NGBE_MIRRCTL_UPLINK MS(1, 0x1) +#define NGBE_MIRRCTL_DNLINK MS(2, 0x1) +#define NGBE_MIRRCTL_VLAN MS(3, 0x1) +#define NGBE_MIRRCTL_DESTP(v) LS(v, 8, 0x7) +#define NGBE_MIRRVLANL(i) (0x015B10 + (i) * 8) +#define NGBE_MIRRPOOLL(i) (0x015B30 + (i) * 8) + +/** + * Time Stamp + **/ +#define NGBE_TSRXCTL 0x015188 +#define NGBE_TSRXCTL_VLD MS(0, 0x1) +#define NGBE_TSRXCTL_TYPE(v) LS(v, 1, 0x7) +#define NGBE_TSRXCTL_TYPE_V2L2 (0) +#define NGBE_TSRXCTL_TYPE_V1L4 (1) +#define NGBE_TSRXCTL_TYPE_V2L24 (2) +#define NGBE_TSRXCTL_TYPE_V2EVENT (5) +#define NGBE_TSRXCTL_ENA MS(4, 0x1) +#define NGBE_TSRXSTMPL 0x0151E8 +#define NGBE_TSRXSTMPH 0x0151A4 +#define NGBE_TSTXCTL 0x011F00 +#define NGBE_TSTXCTL_VLD MS(0, 0x1) +#define NGBE_TSTXCTL_ENA MS(4, 0x1) +#define NGBE_TSTXSTMPL 0x011F04 +#define NGBE_TSTXSTMPH 0x011F08 +#define NGBE_TSTIMEL 0x011F0C +#define NGBE_TSTIMEH 0x011F10 +#define NGBE_TSTIMEINC 0x011F14 +#define NGBE_TSTIMEINC_IV(v) LS(v, 0, 0x7FFFFFF) + +/** + * Wake on Lan + **/ +#define NGBE_WOLCTL 0x015B80 +#define NGBE_WOLIPCTL 0x015B84 +#define NGBE_WOLIP4(i) (0x015BC0 + (i) * 4) /* 0-3 */ +#define NGBE_WOLIP6(i) (0x015BE0 + (i) * 4) /* 0-3 */ + +#define NGBE_WOLFLEXCTL 0x015CFC +#define NGBE_WOLFLEXI 0x015B8C +#define NGBE_WOLFLEXDAT(i) (0x015C00 + (i) * 16) /* 0-15 */ +#define NGBE_WOLFLEXMSK(i) (0x015C08 + (i) * 16) /* 0-15 */ + +/****************************************************************************** + * Security Registers + ******************************************************************************/ +#define NGBE_SECRXCTL 0x017000 +#define NGBE_SECRXCTL_ODSA MS(0, 0x1) +#define NGBE_SECRXCTL_XDSA MS(1, 0x1) +#define NGBE_SECRXCTL_CRCSTRIP MS(2, 0x1) +#define NGBE_SECRXCTL_SAVEBAD MS(6, 0x1) +#define NGBE_SECRXSTAT 0x017004 +#define NGBE_SECRXSTAT_RDY MS(0, 0x1) +#define NGBE_SECRXSTAT_ECC MS(1, 0x1) + +#define NGBE_SECTXCTL 0x01D000 +#define NGBE_SECTXCTL_ODSA MS(0, 0x1) +#define NGBE_SECTXCTL_XDSA MS(1, 0x1) +#define NGBE_SECTXCTL_STFWD MS(2, 0x1) +#define NGBE_SECTXCTL_MSKIV MS(3, 0x1) +#define NGBE_SECTXSTAT 0x01D004 +#define NGBE_SECTXSTAT_RDY MS(0, 0x1) +#define NGBE_SECTXSTAT_ECC MS(1, 0x1) +#define NGBE_SECTXBUFAF 0x01D008 +#define NGBE_SECTXBUFAE 0x01D00C +#define NGBE_SECTXIFG 0x01D020 +#define NGBE_SECTXIFG_MIN(v) LS(v, 0, 0xF) +#define NGBE_SECTXIFG_MIN_MASK MS(0, 0xF) + +/** + * LinkSec + **/ +#define NGBE_LSECRXCAP 0x017200 +#define NGBE_LSECRXCTL 0x017204 + /* disabled(0),check(1),strict(2),drop(3) */ +#define NGBE_LSECRXCTL_MODE_MASK MS(2, 0x3) +#define NGBE_LSECRXCTL_MODE_STRICT LS(2, 2, 0x3) +#define NGBE_LSECRXCTL_POSTHDR MS(6, 0x1) +#define NGBE_LSECRXCTL_REPLAY MS(7, 0x1) +#define NGBE_LSECRXSCIL 0x017208 +#define NGBE_LSECRXSCIH 0x01720C +#define NGBE_LSECRXSA(i) (0x017210 + (i) * 4) /* 0-1 */ +#define NGBE_LSECRXPN(i) (0x017218 + (i) * 4) /* 0-1 */ +#define NGBE_LSECRXKEY(n, i) (0x017220 + 0x10 * (n) + 4 * (i)) /*0-3*/ +#define NGBE_LSECTXCAP 0x01D200 +#define NGBE_LSECTXCTL 0x01D204 + /* disabled(0), auth(1), auth+encrypt(2) */ +#define NGBE_LSECTXCTL_MODE_MASK MS(0, 0x3) +#define NGBE_LSECTXCTL_MODE_AUTH LS(1, 0, 0x3) +#define NGBE_LSECTXCTL_MODE_AENC LS(2, 0, 0x3) +#define NGBE_LSECTXCTL_PNTRH_MASK MS(8, 0xFFFFFF) +#define NGBE_LSECTXCTL_PNTRH(v) LS(v, 8, 0xFFFFFF) +#define NGBE_LSECTXSCIL 0x01D208 +#define NGBE_LSECTXSCIH 0x01D20C +#define NGBE_LSECTXSA 0x01D210 +#define NGBE_LSECTXPN0 0x01D214 +#define NGBE_LSECTXPN1 0x01D218 +#define NGBE_LSECTXKEY0(i) (0x01D21C + (i) * 4) /* 0-3 */ +#define NGBE_LSECTXKEY1(i) (0x01D22C + (i) * 4) /* 0-3 */ + +#define NGBE_LSECRX_UTPKT 0x017240 +#define NGBE_LSECRX_DECOCT 0x017244 +#define NGBE_LSECRX_VLDOCT 0x017248 +#define NGBE_LSECRX_BTPKT 0x01724C +#define NGBE_LSECRX_NOSCIPKT 0x017250 +#define NGBE_LSECRX_UNSCIPKT 0x017254 +#define NGBE_LSECRX_UNCHKPKT 0x017258 +#define NGBE_LSECRX_DLYPKT 0x01725C +#define NGBE_LSECRX_LATEPKT 0x017260 +#define NGBE_LSECRX_OKPKT(i) (0x017264 + (i) * 4) /* 0-1 */ +#define NGBE_LSECRX_BADPKT(i) (0x01726C + (i) * 4) /* 0-1 */ +#define NGBE_LSECRX_INVPKT(i) (0x017274 + (i) * 4) /* 0-1 */ +#define NGBE_LSECRX_BADSAPKT(i) (0x01727C + (i) * 8) /* 0-3 */ +#define NGBE_LSECRX_INVSAPKT(i) (0x017280 + (i) * 8) /* 0-3 */ +#define NGBE_LSECTX_UTPKT 0x01D23C +#define NGBE_LSECTX_ENCPKT 0x01D240 +#define NGBE_LSECTX_PROTPKT 0x01D244 +#define NGBE_LSECTX_ENCOCT 0x01D248 +#define NGBE_LSECTX_PROTOCT 0x01D24C + +/****************************************************************************** + * MAC Registers + ******************************************************************************/ +#define NGBE_MACRXCFG 0x011004 +#define NGBE_MACRXCFG_ENA MS(0, 0x1) +#define NGBE_MACRXCFG_JUMBO MS(8, 0x1) +#define NGBE_MACRXCFG_LB MS(10, 0x1) +#define NGBE_MACCNTCTL 0x011800 +#define NGBE_MACCNTCTL_RC MS(2, 0x1) + +#define NGBE_MACRXFLT 0x011008 +#define NGBE_MACRXFLT_PROMISC MS(0, 0x1) +#define NGBE_MACRXFLT_CTL_MASK MS(6, 0x3) +#define NGBE_MACRXFLT_CTL_DROP LS(0, 6, 0x3) +#define NGBE_MACRXFLT_CTL_NOPS LS(1, 6, 0x3) +#define NGBE_MACRXFLT_CTL_NOFT LS(2, 6, 0x3) +#define NGBE_MACRXFLT_CTL_PASS LS(3, 6, 0x3) +#define NGBE_MACRXFLT_RXALL MS(31, 0x1) + +/****************************************************************************** + * Statistic Registers + ******************************************************************************/ +/* Ring Counter */ +#define NGBE_QPRXPKT(rp) (0x001014 + 0x40 * (rp)) +#define NGBE_QPRXOCTL(rp) (0x001018 + 0x40 * (rp)) +#define NGBE_QPRXOCTH(rp) (0x00101C + 0x40 * (rp)) +#define NGBE_QPRXMPKT(rp) (0x001020 + 0x40 * (rp)) +#define NGBE_QPRXBPKT(rp) (0x001024 + 0x40 * (rp)) +#define NGBE_QPTXPKT(rp) (0x003014 + 0x40 * (rp)) +#define NGBE_QPTXOCTL(rp) (0x003018 + 0x40 * (rp)) +#define NGBE_QPTXOCTH(rp) (0x00301C + 0x40 * (rp)) +#define NGBE_QPTXMPKT(rp) (0x003020 + 0x40 * (rp)) +#define NGBE_QPTXBPKT(rp) (0x003024 + 0x40 * (rp)) + +/* TDMA Counter */ +#define NGBE_DMATXDROP 0x018300 +#define NGBE_DMATXSECDROP 0x018304 +#define NGBE_DMATXPKT 0x018308 +#define NGBE_DMATXOCTL 0x01830C +#define NGBE_DMATXOCTH 0x018310 +#define NGBE_DMATXMNG 0x018314 + +/* RDMA Counter */ +#define NGBE_DMARXDROP 0x012500 +#define NGBE_DMARXPKT 0x012504 +#define NGBE_DMARXOCTL 0x012508 +#define NGBE_DMARXOCTH 0x01250C +#define NGBE_DMARXMNG 0x012510 + +/* Packet Buffer Counter */ +#define NGBE_PBRXMISS 0x019040 +#define NGBE_PBRXPKT 0x019060 +#define NGBE_PBRXREP 0x019064 +#define NGBE_PBRXDROP 0x019068 +#define NGBE_PBLBSTAT 0x01906C +#define NGBE_PBLBSTAT_FREE(r) RS(r, 0, 0x3FF) +#define NGBE_PBLBSTAT_FULL MS(11, 0x1) +#define NGBE_PBRXWRPTR 0x019180 +#define NGBE_PBRXWRPTR_HEAD(r) RS(r, 0, 0xFFFF) +#define NGBE_PBRXWRPTR_TAIL(r) RS(r, 16, 0xFFFF) +#define NGBE_PBRXRDPTR 0x0191A0 +#define NGBE_PBRXRDPTR_HEAD(r) RS(r, 0, 0xFFFF) +#define NGBE_PBRXRDPTR_TAIL(r) RS(r, 16, 0xFFFF) +#define NGBE_PBRXDATA 0x0191C0 +#define NGBE_PBRXDATA_RDPTR(r) RS(r, 0, 0xFFFF) +#define NGBE_PBRXDATA_WRPTR(r) RS(r, 16, 0xFFFF) +#define NGBE_PBRX_USDSP 0x0191E0 +#define NGBE_RXPBPFCDMACL 0x019210 +#define NGBE_RXPBPFCDMACH 0x019214 +#define NGBE_PBTXLNKXOFF 0x019218 +#define NGBE_PBTXLNKXON 0x01921C + +#define NGBE_PBTXSTAT 0x01C004 +#define NGBE_PBTXSTAT_EMPT(tc, r) ((1 << (tc) & (r)) >> (tc)) + +#define NGBE_PBRXLNKXOFF 0x011988 +#define NGBE_PBRXLNKXON 0x011E0C + +#define NGBE_PBLPBK 0x01CF08 + +/* Ether Flow Counter */ +#define NGBE_LANPKTDROP 0x0151C0 +#define NGBE_MNGPKTDROP 0x0151C4 + +#define NGBE_PSRLANPKTCNT 0x0151B8 +#define NGBE_PSRMNGPKTCNT 0x0151BC + +/* MAC Counter */ +#define NGBE_MACRXERRCRCL 0x011928 +#define NGBE_MACRXERRCRCH 0x01192C +#define NGBE_MACRXERRLENL 0x011978 +#define NGBE_MACRXERRLENH 0x01197C +#define NGBE_MACRX1TO64L 0x001940 +#define NGBE_MACRX1TO64H 0x001944 +#define NGBE_MACRX65TO127L 0x001948 +#define NGBE_MACRX65TO127H 0x00194C +#define NGBE_MACRX128TO255L 0x001950 +#define NGBE_MACRX128TO255H 0x001954 +#define NGBE_MACRX256TO511L 0x001958 +#define NGBE_MACRX256TO511H 0x00195C +#define NGBE_MACRX512TO1023L 0x001960 +#define NGBE_MACRX512TO1023H 0x001964 +#define NGBE_MACRX1024TOMAXL 0x001968 +#define NGBE_MACRX1024TOMAXH 0x00196C +#define NGBE_MACTX1TO64L 0x001834 +#define NGBE_MACTX1TO64H 0x001838 +#define NGBE_MACTX65TO127L 0x00183C +#define NGBE_MACTX65TO127H 0x001840 +#define NGBE_MACTX128TO255L 0x001844 +#define NGBE_MACTX128TO255H 0x001848 +#define NGBE_MACTX256TO511L 0x00184C +#define NGBE_MACTX256TO511H 0x001850 +#define NGBE_MACTX512TO1023L 0x001854 +#define NGBE_MACTX512TO1023H 0x001858 +#define NGBE_MACTX1024TOMAXL 0x00185C +#define NGBE_MACTX1024TOMAXH 0x001860 + +#define NGBE_MACRXUNDERSIZE 0x011938 +#define NGBE_MACRXOVERSIZE 0x01193C +#define NGBE_MACRXJABBER 0x011934 + +#define NGBE_MACRXPKTL 0x011900 +#define NGBE_MACRXPKTH 0x011904 +#define NGBE_MACTXPKTL 0x01181C +#define NGBE_MACTXPKTH 0x011820 +#define NGBE_MACRXGBOCTL 0x011908 +#define NGBE_MACRXGBOCTH 0x01190C +#define NGBE_MACTXGBOCTL 0x011814 +#define NGBE_MACTXGBOCTH 0x011818 + +#define NGBE_MACRXOCTL 0x011918 +#define NGBE_MACRXOCTH 0x01191C +#define NGBE_MACRXMPKTL 0x011920 +#define NGBE_MACRXMPKTH 0x011924 +#define NGBE_MACTXOCTL 0x011824 +#define NGBE_MACTXOCTH 0x011828 +#define NGBE_MACTXMPKTL 0x01182C +#define NGBE_MACTXMPKTH 0x011830 + +/* Management Counter */ +#define NGBE_MNGOUT 0x01CF00 +#define NGBE_MNGIN 0x01CF04 +#define NGBE_MNGDROP 0x01CF0C + +/* MAC SEC Counter */ +#define NGBE_LSECRXUNTAG 0x017240 +#define NGBE_LSECRXDECOCT 0x017244 +#define NGBE_LSECRXVLDOCT 0x017248 +#define NGBE_LSECRXBADTAG 0x01724C +#define NGBE_LSECRXNOSCI 0x017250 +#define NGBE_LSECRXUKSCI 0x017254 +#define NGBE_LSECRXUNCHK 0x017258 +#define NGBE_LSECRXDLY 0x01725C +#define NGBE_LSECRXLATE 0x017260 +#define NGBE_LSECRXGOOD 0x017264 +#define NGBE_LSECRXBAD 0x01726C +#define NGBE_LSECRXUK 0x017274 +#define NGBE_LSECRXBADSA 0x01727C +#define NGBE_LSECRXUKSA 0x017280 +#define NGBE_LSECTXUNTAG 0x01D23C +#define NGBE_LSECTXENC 0x01D240 +#define NGBE_LSECTXPTT 0x01D244 +#define NGBE_LSECTXENCOCT 0x01D248 +#define NGBE_LSECTXPTTOCT 0x01D24C + +/* Management Counter */ +#define NGBE_MNGOS2BMC 0x01E094 +#define NGBE_MNGBMC2OS 0x01E090 + +/****************************************************************************** + * PF(Physical Function) Registers + ******************************************************************************/ +/* Interrupt */ +#define NGBE_ICRMISC 0x000100 +#define NGBE_ICRMISC_MASK MS(8, 0xFFFFFF) +#define NGBE_ICRMISC_RST MS(10, 0x1) /* device reset event */ +#define NGBE_ICRMISC_TS MS(11, 0x1) /* time sync */ +#define NGBE_ICRMISC_STALL MS(12, 0x1) /* trans or recv path is stalled */ +#define NGBE_ICRMISC_LNKSEC MS(13, 0x1) /* Tx LinkSec require key exchange*/ +#define NGBE_ICRMISC_ERRBUF MS(14, 0x1) /* Packet Buffer Overrun */ +#define NGBE_ICRMISC_ERRMAC MS(17, 0x1) /* err reported by MAC */ +#define NGBE_ICRMISC_PHY MS(18, 0x1) /* interrupt reported by eth phy */ +#define NGBE_ICRMISC_ERRIG MS(20, 0x1) /* integrity error */ +#define NGBE_ICRMISC_SPI MS(21, 0x1) /* SPI interface */ +#define NGBE_ICRMISC_VFMBX MS(23, 0x1) /* VF-PF message box */ +#define NGBE_ICRMISC_GPIO MS(26, 0x1) /* GPIO interrupt */ +#define NGBE_ICRMISC_ERRPCI MS(27, 0x1) /* pcie request error */ +#define NGBE_ICRMISC_HEAT MS(28, 0x1) /* overheat detection */ +#define NGBE_ICRMISC_PROBE MS(29, 0x1) /* probe match */ +#define NGBE_ICRMISC_MNGMBX MS(30, 0x1) /* mng mailbox */ +#define NGBE_ICRMISC_TIMER MS(31, 0x1) /* tcp timer */ +#define NGBE_ICRMISC_DEFAULT ( \ + NGBE_ICRMISC_RST | \ + NGBE_ICRMISC_ERRMAC | \ + NGBE_ICRMISC_PHY | \ + NGBE_ICRMISC_ERRIG | \ + NGBE_ICRMISC_GPIO | \ + NGBE_ICRMISC_VFMBX | \ + NGBE_ICRMISC_MNGMBX | \ + NGBE_ICRMISC_STALL | \ + NGBE_ICRMISC_TIMER) +#define NGBE_ICSMISC 0x000104 +#define NGBE_IENMISC 0x000108 +#define NGBE_IVARMISC 0x0004FC +#define NGBE_IVARMISC_VEC(v) LS(v, 0, 0x7) +#define NGBE_IVARMISC_VLD MS(7, 0x1) +#define NGBE_ICR(i) (0x000120 + (i) * 4) /*0*/ +#define NGBE_ICR_MASK MS(0, 0x1FF) +#define NGBE_ICS(i) (0x000130 + (i) * 4) /*0*/ +#define NGBE_ICS_MASK NGBE_ICR_MASK +#define NGBE_IMS(i) (0x000140 + (i) * 4) /*0*/ +#define NGBE_IMS_MASK NGBE_ICR_MASK +#define NGBE_IMC(i) (0x000150 + (i) * 4) /*0*/ +#define NGBE_IMC_MASK NGBE_ICR_MASK +#define NGBE_IVAR(i) (0x000500 + (i) * 4) /*0-3*/ +#define NGBE_IVAR_VEC(v) LS(v, 0, 0x7) +#define NGBE_IVAR_VLD MS(7, 0x1) +#define NGBE_TCPTMR 0x000170 +#define NGBE_ITRSEL 0x000180 + +/* P2V Mailbox */ +#define NGBE_MBMEM(i) (0x005000 + 0x40 * (i)) /*0-7*/ +#define NGBE_MBCTL(i) (0x000600 + 4 * (i)) /*0-7*/ +#define NGBE_MBCTL_STS MS(0, 0x1) /* Initiate message send to VF */ +#define NGBE_MBCTL_ACK MS(1, 0x1) /* Ack message recv'd from VF */ +#define NGBE_MBCTL_VFU MS(2, 0x1) /* VF owns the mailbox buffer */ +#define NGBE_MBCTL_PFU MS(3, 0x1) /* PF owns the mailbox buffer */ +#define NGBE_MBCTL_RVFU MS(4, 0x1) /* Reset VFU - used when VF stuck */ +#define NGBE_MBVFICR 0x000480 +#define NGBE_MBVFICR_INDEX(vf) ((vf) >> 4) +#define NGBE_MBVFICR_VFREQ_MASK (0x0000FFFF) /* bits for VF messages */ +#define NGBE_MBVFICR_VFREQ_VF1 (0x00000001) /* bit for VF 1 message */ +#define NGBE_MBVFICR_VFACK_MASK (0xFFFF0000) /* bits for VF acks */ +#define NGBE_MBVFICR_VFACK_VF1 (0x00010000) /* bit for VF 1 ack */ +#define NGBE_FLRVFP 0x000490 +#define NGBE_FLRVFE 0x0004A0 +#define NGBE_FLRVFEC 0x0004A8 + +/****************************************************************************** + * VF(Virtual Function) Registers + ******************************************************************************/ +#define NGBE_VFPBWRAP 0x000000 +#define NGBE_VFPBWRAP_WRAP MS(0, 0x7) +#define NGBE_VFPBWRAP_EMPT MS(3, 0x1) +#define NGBE_VFSTATUS 0x000004 +#define NGBE_VFSTATUS_UP MS(0, 0x1) +#define NGBE_VFSTATUS_BW_MASK MS(1, 0x7) +#define NGBE_VFSTATUS_BW_1G LS(0x1, 1, 0x7) +#define NGBE_VFSTATUS_BW_100M LS(0x2, 1, 0x7) +#define NGBE_VFSTATUS_BW_10M LS(0x4, 1, 0x7) +#define NGBE_VFSTATUS_BUSY MS(4, 0x1) +#define NGBE_VFSTATUS_LANID MS(8, 0x3) +#define NGBE_VFRST 0x000008 +#define NGBE_VFRST_SET MS(0, 0x1) +#define NGBE_VFMSIXECC 0x00000C +#define NGBE_VFPLCFG 0x000078 +#define NGBE_VFPLCFG_RSV MS(0, 0x1) +#define NGBE_VFPLCFG_PSR(v) LS(v, 1, 0x1F) +#define NGBE_VFPLCFG_PSRL4HDR (0x1) +#define NGBE_VFPLCFG_PSRL3HDR (0x2) +#define NGBE_VFPLCFG_PSRL2HDR (0x4) +#define NGBE_VFPLCFG_PSRTUNHDR (0x8) +#define NGBE_VFPLCFG_PSRTUNMAC (0x10) +#define NGBE_VFICR 0x000100 +#define NGBE_VFICR_MASK LS(3, 0, 0x3) +#define NGBE_VFICR_MBX MS(1, 0x1) +#define NGBE_VFICR_DONE1 MS(0, 0x1) +#define NGBE_VFICS 0x000104 +#define NGBE_VFICS_MASK NGBE_VFICR_MASK +#define NGBE_VFIMS 0x000108 +#define NGBE_VFIMS_MASK NGBE_VFICR_MASK +#define NGBE_VFIMC 0x00010C +#define NGBE_VFIMC_MASK NGBE_VFICR_MASK +#define NGBE_VFGPIE 0x000118 +#define NGBE_VFIVAR(i) (0x000240 + 4 * (i)) /*0-1*/ +#define NGBE_VFIVARMISC 0x000260 +#define NGBE_VFIVAR_ALLOC(v) LS(v, 0, 0x1) +#define NGBE_VFIVAR_VLD MS(7, 0x1) + +#define NGBE_VFMBCTL 0x000600 +#define NGBE_VFMBCTL_REQ MS(0, 0x1) /* Request for PF Ready bit */ +#define NGBE_VFMBCTL_ACK MS(1, 0x1) /* Ack PF message received */ +#define NGBE_VFMBCTL_VFU MS(2, 0x1) /* VF owns the mailbox buffer */ +#define NGBE_VFMBCTL_PFU MS(3, 0x1) /* PF owns the mailbox buffer */ +#define NGBE_VFMBCTL_PFSTS MS(4, 0x1) /* PF wrote a message in the MB */ +#define NGBE_VFMBCTL_PFACK MS(5, 0x1) /* PF ack the previous VF msg */ +#define NGBE_VFMBCTL_RSTI MS(6, 0x1) /* PF has reset indication */ +#define NGBE_VFMBCTL_RSTD MS(7, 0x1) /* PF has indicated reset done */ +#define NGBE_VFMBCTL_R2C_BITS (NGBE_VFMBCTL_RSTD | \ + NGBE_VFMBCTL_PFSTS | \ + NGBE_VFMBCTL_PFACK) +#define NGBE_VFMBX 0x000C00 /*0-15*/ +#define NGBE_VFTPHCTL(i) 0x000D00 + +/****************************************************************************** + * PF&VF TxRx Interface + ******************************************************************************/ +#define RNGLEN(v) ROUND_OVER(v, 13, 7) +#define HDRLEN(v) ROUND_OVER(v, 10, 6) +#define PKTLEN(v) ROUND_OVER(v, 14, 10) +#define INTTHR(v) ROUND_OVER(v, 4, 0) + +#define NGBE_RING_DESC_ALIGN 128 +#define NGBE_RING_DESC_MIN 128 +#define NGBE_RING_DESC_MAX 8192 +#define NGBE_RXD_ALIGN NGBE_RING_DESC_ALIGN +#define NGBE_TXD_ALIGN NGBE_RING_DESC_ALIGN + +/* receive ring */ +#define NGBE_RXBAL(rp) (0x001000 + 0x40 * (rp)) +#define NGBE_RXBAH(rp) (0x001004 + 0x40 * (rp)) +#define NGBE_RXRP(rp) (0x00100C + 0x40 * (rp)) +#define NGBE_RXWP(rp) (0x001008 + 0x40 * (rp)) +#define NGBE_RXCFG(rp) (0x001010 + 0x40 * (rp)) +#define NGBE_RXCFG_ENA MS(0, 0x1) +#define NGBE_RXCFG_RNGLEN(v) LS(RNGLEN(v), 1, 0x3F) +#define NGBE_RXCFG_PKTLEN(v) LS(PKTLEN(v), 8, 0xF) +#define NGBE_RXCFG_PKTLEN_MASK MS(8, 0xF) +#define NGBE_RXCFG_HDRLEN(v) LS(HDRLEN(v), 12, 0xF) +#define NGBE_RXCFG_HDRLEN_MASK MS(12, 0xF) +#define NGBE_RXCFG_WTHRESH(v) LS(v, 16, 0x7) +#define NGBE_RXCFG_ETAG MS(22, 0x1) +#define NGBE_RXCFG_SPLIT MS(26, 0x1) +#define NGBE_RXCFG_CNTAG MS(28, 0x1) +#define NGBE_RXCFG_DROP MS(30, 0x1) +#define NGBE_RXCFG_VLAN MS(31, 0x1) + +/* transmit ring */ +#define NGBE_TXBAL(rp) (0x003000 + 0x40 * (rp)) /*0-7*/ +#define NGBE_TXBAH(rp) (0x003004 + 0x40 * (rp)) +#define NGBE_TXWP(rp) (0x003008 + 0x40 * (rp)) +#define NGBE_TXRP(rp) (0x00300C + 0x40 * (rp)) +#define NGBE_TXCFG(rp) (0x003010 + 0x40 * (rp)) +#define NGBE_TXCFG_ENA MS(0, 0x1) +#define NGBE_TXCFG_BUFLEN_MASK MS(1, 0x3F) +#define NGBE_TXCFG_BUFLEN(v) LS(RNGLEN(v), 1, 0x3F) +#define NGBE_TXCFG_HTHRESH_MASK MS(8, 0xF) +#define NGBE_TXCFG_HTHRESH(v) LS(v, 8, 0xF) +#define NGBE_TXCFG_WTHRESH_MASK MS(16, 0x7F) +#define NGBE_TXCFG_WTHRESH(v) LS(v, 16, 0x7F) +#define NGBE_TXCFG_FLUSH MS(26, 0x1) + +/* interrupt registers */ +#define NGBE_BMEPEND 0x000168 +#define NGBE_BMEPEND_ST MS(0, 0x1) +#define NGBE_ITRI 0x000180 +#define NGBE_ITR(i) (0x000200 + 4 * (i)) +#define NGBE_ITR_IVAL_MASK MS(2, 0x1FFF) /* 1ns/10G, 10ns/REST */ +#define NGBE_ITR_IVAL(v) LS(v, 2, 0x1FFF) /*1ns/10G, 10ns/REST*/ +#define NGBE_ITR_IVAL_1G(us) NGBE_ITR_IVAL((us) / 2) +#define NGBE_ITR_IVAL_10G(us) NGBE_ITR_IVAL((us) / 20) +#define NGBE_ITR_LLIEA MS(15, 0x1) +#define NGBE_ITR_LLICREDIT(v) LS(v, 16, 0x1F) +#define NGBE_ITR_CNT(v) LS(v, 21, 0x3FF) +#define NGBE_ITR_WRDSA MS(31, 0x1) +#define NGBE_GPIE 0x000118 +#define NGBE_GPIE_MSIX MS(0, 0x1) +#define NGBE_GPIE_LLIEA MS(1, 0x1) +#define NGBE_GPIE_LLIVAL(v) LS(v, 3, 0x1F) +#define NGBE_GPIE_LLIVAL_H(v) LS(v, 16, 0x7FF) + +/****************************************************************************** + * Debug Registers + ******************************************************************************/ +/** + * Probe + **/ +#define NGBE_PRBCTL 0x010200 +#define NGBE_PRBSTA 0x010204 +#define NGBE_PRBDAT 0x010220 +#define NGBE_PRBCNT 0x010228 + +#define NGBE_PRBPCI 0x01F010 +#define NGBE_PRBPSR 0x015010 +#define NGBE_PRBRDB 0x019010 +#define NGBE_PRBTDB 0x01C010 +#define NGBE_PRBRSEC 0x017010 +#define NGBE_PRBTSEC 0x01D010 +#define NGBE_PRBMNG 0x01E010 +#define NGBE_PRBRMAC 0x011014 +#define NGBE_PRBTMAC 0x011010 +#define NGBE_PRBREMAC 0x011E04 +#define NGBE_PRBTEMAC 0x011E00 + +/** + * ECC + **/ +#define NGBE_ECCRXPBCTL 0x019014 +#define NGBE_ECCRXPBINJ 0x019018 +#define NGBE_ECCRXPB 0x01901C +#define NGBE_ECCTXPBCTL 0x01C014 +#define NGBE_ECCTXPBINJ 0x01C018 +#define NGBE_ECCTXPB 0x01C01C + +#define NGBE_ECCRXETHCTL 0x015014 +#define NGBE_ECCRXETHINJ 0x015018 +#define NGBE_ECCRXETH 0x01401C + +#define NGBE_ECCRXSECCTL 0x017014 +#define NGBE_ECCRXSECINJ 0x017018 +#define NGBE_ECCRXSEC 0x01701C +#define NGBE_ECCTXSECCTL 0x01D014 +#define NGBE_ECCTXSECINJ 0x01D018 +#define NGBE_ECCTXSEC 0x01D01C + +#define NGBE_P2VMBX_SIZE (16) /* 16*4B */ +#define NGBE_P2MMBX_SIZE (64) /* 64*4B */ + +/**************** Global Registers ****************************/ +#define NGBE_POOLETHCTL(pl) (0x015600 + (pl) * 4) +#define NGBE_POOLETHCTL_LBDIA MS(0, 0x1) +#define NGBE_POOLETHCTL_LLBDIA MS(1, 0x1) +#define NGBE_POOLETHCTL_LLB MS(2, 0x1) +#define NGBE_POOLETHCTL_UCP MS(4, 0x1) +#define NGBE_POOLETHCTL_ETP MS(5, 0x1) +#define NGBE_POOLETHCTL_VLA MS(6, 0x1) +#define NGBE_POOLETHCTL_VLP MS(7, 0x1) +#define NGBE_POOLETHCTL_UTA MS(8, 0x1) +#define NGBE_POOLETHCTL_MCHA MS(9, 0x1) +#define NGBE_POOLETHCTL_UCHA MS(10, 0x1) +#define NGBE_POOLETHCTL_BCA MS(11, 0x1) +#define NGBE_POOLETHCTL_MCP MS(12, 0x1) +#define NGBE_POOLDROPSWBK(i) (0x0151C8 + (i) * 4) /*0-1*/ + +/**************************** Receive DMA registers **************************/ + +#define NGBE_RPUP2TC 0x019008 +#define NGBE_RPUP2TC_UP_SHIFT 3 +#define NGBE_RPUP2TC_UP_MASK 0x7 + +/* mac switcher */ +#define NGBE_ETHADDRL 0x016200 +#define NGBE_ETHADDRL_AD0(v) LS(v, 0, 0xFF) +#define NGBE_ETHADDRL_AD1(v) LS(v, 8, 0xFF) +#define NGBE_ETHADDRL_AD2(v) LS(v, 16, 0xFF) +#define NGBE_ETHADDRL_AD3(v) LS(v, 24, 0xFF) +#define NGBE_ETHADDRL_ETAG(r) RS(r, 0, 0x3FFF) +#define NGBE_ETHADDRH 0x016204 +#define NGBE_ETHADDRH_AD4(v) LS(v, 0, 0xFF) +#define NGBE_ETHADDRH_AD5(v) LS(v, 8, 0xFF) +#define NGBE_ETHADDRH_AD_MASK MS(0, 0xFFFF) +#define NGBE_ETHADDRH_ETAG MS(30, 0x1) +#define NGBE_ETHADDRH_VLD MS(31, 0x1) +#define NGBE_ETHADDRASS 0x016208 +#define NGBE_ETHADDRIDX 0x016210 + +/* Outmost Barrier Filters */ +#define NGBE_MCADDRTBL(i) (0x015200 + (i) * 4) /*0-127*/ +#define NGBE_UCADDRTBL(i) (0x015400 + (i) * 4) /*0-127*/ +#define NGBE_VLANTBL(i) (0x016000 + (i) * 4) /*0-127*/ + +#define NGBE_MNGFLEXSEL 0x1582C +#define NGBE_MNGFLEXDWL(i) (0x15A00 + ((i) * 16)) +#define NGBE_MNGFLEXDWH(i) (0x15A04 + ((i) * 16)) +#define NGBE_MNGFLEXMSK(i) (0x15A08 + ((i) * 16)) + +#define NGBE_LANFLEXSEL 0x15B8C +#define NGBE_LANFLEXDWL(i) (0x15C00 + ((i) * 16)) +#define NGBE_LANFLEXDWH(i) (0x15C04 + ((i) * 16)) +#define NGBE_LANFLEXMSK(i) (0x15C08 + ((i) * 16)) +#define NGBE_LANFLEXCTL 0x15CFC + +/* ipsec */ +#define NGBE_IPSRXIDX 0x017100 +#define NGBE_IPSRXIDX_ENA MS(0, 0x1) +#define NGBE_IPSRXIDX_TB_MASK MS(1, 0x3) +#define NGBE_IPSRXIDX_TB_IP LS(1, 1, 0x3) +#define NGBE_IPSRXIDX_TB_SPI LS(2, 1, 0x3) +#define NGBE_IPSRXIDX_TB_KEY LS(3, 1, 0x3) +#define NGBE_IPSRXIDX_TBIDX(v) LS(v, 3, 0xF) +#define NGBE_IPSRXIDX_READ MS(30, 0x1) +#define NGBE_IPSRXIDX_WRITE MS(31, 0x1) +#define NGBE_IPSRXADDR(i) (0x017104 + (i) * 4) + +#define NGBE_IPSRXSPI 0x017114 +#define NGBE_IPSRXADDRIDX 0x017118 +#define NGBE_IPSRXKEY(i) (0x01711C + (i) * 4) +#define NGBE_IPSRXSALT 0x01712C +#define NGBE_IPSRXMODE 0x017130 +#define NGBE_IPSRXMODE_IPV6 0x00000010 +#define NGBE_IPSRXMODE_DEC 0x00000008 +#define NGBE_IPSRXMODE_ESP 0x00000004 +#define NGBE_IPSRXMODE_AH 0x00000002 +#define NGBE_IPSRXMODE_VLD 0x00000001 +#define NGBE_IPSTXIDX 0x01D100 +#define NGBE_IPSTXIDX_ENA MS(0, 0x1) +#define NGBE_IPSTXIDX_SAIDX(v) LS(v, 3, 0x3FF) +#define NGBE_IPSTXIDX_READ MS(30, 0x1) +#define NGBE_IPSTXIDX_WRITE MS(31, 0x1) +#define NGBE_IPSTXSALT 0x01D104 +#define NGBE_IPSTXKEY(i) (0x01D108 + (i) * 4) + +#define NGBE_MACTXCFG 0x011000 +#define NGBE_MACTXCFG_TE MS(0, 0x1) +#define NGBE_MACTXCFG_SPEED_MASK MS(29, 0x3) +#define NGBE_MACTXCFG_SPEED(v) LS(v, 29, 0x3) +#define NGBE_MACTXCFG_SPEED_10G LS(0, 29, 0x3) +#define NGBE_MACTXCFG_SPEED_1G LS(3, 29, 0x3) + +#define NGBE_ISBADDRL 0x000160 +#define NGBE_ISBADDRH 0x000164 + +#define NGBE_ARBPOOLIDX 0x01820C +#define NGBE_ARBTXRATE 0x018404 +#define NGBE_ARBTXRATE_MIN(v) LS(v, 0, 0x3FFF) +#define NGBE_ARBTXRATE_MAX(v) LS(v, 16, 0x3FFF) + +/* qos */ +#define NGBE_ARBTXCTL 0x018200 +#define NGBE_ARBTXCTL_RRM MS(1, 0x1) +#define NGBE_ARBTXCTL_WSP MS(2, 0x1) +#define NGBE_ARBTXCTL_DIA MS(6, 0x1) +#define NGBE_ARBTXMMW 0x018208 + +/* Management */ +#define NGBE_MNGFWSYNC 0x01E000 +#define NGBE_MNGFWSYNC_REQ MS(0, 0x1) +#define NGBE_MNGSWSYNC 0x01E004 +#define NGBE_MNGSWSYNC_REQ MS(0, 0x1) +#define NGBE_SWSEM 0x01002C +#define NGBE_SWSEM_PF MS(0, 0x1) +#define NGBE_MNGSEM 0x01E008 +#define NGBE_MNGSEM_SW(v) LS(v, 0, 0xFFFF) +#define NGBE_MNGSEM_SWPHY MS(0, 0x1) +#define NGBE_MNGSEM_SWMBX MS(2, 0x1) +#define NGBE_MNGSEM_SWFLASH MS(3, 0x1) +#define NGBE_MNGSEM_FW(v) LS(v, 16, 0xFFFF) +#define NGBE_MNGSEM_FWPHY MS(16, 0x1) +#define NGBE_MNGSEM_FWMBX MS(18, 0x1) +#define NGBE_MNGSEM_FWFLASH MS(19, 0x1) +#define NGBE_MNGMBXCTL 0x01E044 +#define NGBE_MNGMBXCTL_SWRDY MS(0, 0x1) +#define NGBE_MNGMBXCTL_SWACK MS(1, 0x1) +#define NGBE_MNGMBXCTL_FWRDY MS(2, 0x1) +#define NGBE_MNGMBXCTL_FWACK MS(3, 0x1) +#define NGBE_MNGMBX 0x01E100 + +/** + * MDIO(PHY) + **/ +#define NGBE_MDIOSCA 0x011200 +#define NGBE_MDIOSCA_REG(v) LS(v, 0, 0xFFFF) +#define NGBE_MDIOSCA_PORT(v) LS(v, 16, 0x1F) +#define NGBE_MDIOSCA_DEV(v) LS(v, 21, 0x1F) +#define NGBE_MDIOSCD 0x011204 +#define NGBE_MDIOSCD_DAT_R(r) RS(r, 0, 0xFFFF) +#define NGBE_MDIOSCD_DAT(v) LS(v, 0, 0xFFFF) +#define NGBE_MDIOSCD_CMD_PREAD LS(2, 16, 0x3) +#define NGBE_MDIOSCD_CMD_WRITE LS(1, 16, 0x3) +#define NGBE_MDIOSCD_CMD_READ LS(3, 16, 0x3) +#define NGBE_MDIOSCD_SADDR MS(18, 0x1) +#define NGBE_MDIOSCD_CLOCK(v) LS(v, 19, 0x7) +#define NGBE_MDIOSCD_BUSY MS(22, 0x1) + +#define NGBE_MDIOMODE 0x011220 +#define NGBE_MDIOMODE_MASK MS(0, 0xF) +#define NGBE_MDIOMODE_PRT3CL22 MS(3, 0x1) +#define NGBE_MDIOMODE_PRT2CL22 MS(2, 0x1) +#define NGBE_MDIOMODE_PRT1CL22 MS(1, 0x1) +#define NGBE_MDIOMODE_PRT0CL22 MS(0, 0x1) + +#define NVM_OROM_OFFSET 0x17 +#define NVM_OROM_BLK_LOW 0x83 +#define NVM_OROM_BLK_HI 0x84 +#define NVM_OROM_PATCH_MASK 0xFF +#define NVM_OROM_SHIFT 8 +#define NVM_VER_MASK 0x00FF /* version mask */ +#define NVM_VER_SHIFT 8 /* version bit shift */ +#define NVM_OEM_PROD_VER_PTR 0x1B /* OEM Product version block pointer */ +#define NVM_OEM_PROD_VER_CAP_OFF 0x1 /* OEM Product version format offset */ +#define NVM_OEM_PROD_VER_OFF_L 0x2 /* OEM Product version offset low */ +#define NVM_OEM_PROD_VER_OFF_H 0x3 /* OEM Product version offset high */ +#define NVM_OEM_PROD_VER_CAP_MASK 0xF /* OEM Product version cap mask */ +#define NVM_OEM_PROD_VER_MOD_LEN 0x3 /* OEM Product version module length */ +#define NVM_ETK_OFF_LOW 0x2D /* version low order word */ +#define NVM_ETK_OFF_HI 0x2E /* version high order word */ +#define NVM_ETK_SHIFT 16 /* high version word shift */ +#define NVM_VER_INVALID 0xFFFF +#define NVM_ETK_VALID 0x8000 +#define NVM_INVALID_PTR 0xFFFF +#define NVM_VER_SIZE 32 /* version string size */ + +#define NGBE_REG_RSSTBL NGBE_RSSTBL(0) +#define NGBE_REG_RSSKEY NGBE_RSSKEY(0) + +/* + * read non-rc counters + */ +#define NGBE_UPDCNT32(reg, last, cur) \ +do { \ + uint32_t latest = rd32(hw, reg); \ + if (hw->offset_loaded || hw->rx_loaded) \ + last = 0; \ + cur += (latest - last) & UINT_MAX; \ + last = latest; \ +} while (0) + +#define NGBE_UPDCNT36(regl, last, cur) \ +do { \ + uint64_t new_lsb = rd32(hw, regl); \ + uint64_t new_msb = rd32(hw, regl + 4); \ + uint64_t latest = ((new_msb << 32) | new_lsb); \ + if (hw->offset_loaded || hw->rx_loaded) \ + last = 0; \ + cur += (0x1000000000LL + latest - last) & 0xFFFFFFFFFLL; \ + last = latest; \ +} while (0) + +/** + * register operations + **/ +#define NGBE_REG_READ32(addr) rte_read32(addr) +#define NGBE_REG_READ32_RELAXED(addr) rte_read32_relaxed(addr) +#define NGBE_REG_WRITE32(addr, val) rte_write32(val, addr) +#define NGBE_REG_WRITE32_RELAXED(addr, val) rte_write32_relaxed(val, addr) + +#define NGBE_DEAD_READ_REG 0xdeadbeefU +#define NGBE_FAILED_READ_REG 0xffffffffU +#define NGBE_REG_ADDR(hw, reg) \ + ((volatile u32 *)((char *)(hw)->hw_addr + (reg))) + +static inline u32 +ngbe_get32(volatile u32 *addr) +{ + u32 val = NGBE_REG_READ32(addr); + return rte_le_to_cpu_32(val); +} + +static inline void +ngbe_set32(volatile u32 *addr, u32 val) +{ + val = rte_cpu_to_le_32(val); + NGBE_REG_WRITE32(addr, val); +} + +static inline u32 +ngbe_get32_masked(volatile u32 *addr, u32 mask) +{ + u32 val = ngbe_get32(addr); + val &= mask; + return val; +} + +static inline void +ngbe_set32_masked(volatile u32 *addr, u32 mask, u32 field) +{ + u32 val = ngbe_get32(addr); + val = ((val & ~mask) | (field & mask)); + ngbe_set32(addr, val); +} + +static inline u32 +ngbe_get32_relaxed(volatile u32 *addr) +{ + u32 val = NGBE_REG_READ32_RELAXED(addr); + return rte_le_to_cpu_32(val); +} + +static inline void +ngbe_set32_relaxed(volatile u32 *addr, u32 val) +{ + val = rte_cpu_to_le_32(val); + NGBE_REG_WRITE32_RELAXED(addr, val); +} + +static inline u32 +rd32(struct ngbe_hw *hw, u32 reg) +{ + if (reg == NGBE_REG_DUMMY) + return 0; + return ngbe_get32(NGBE_REG_ADDR(hw, reg)); +} + +static inline void +wr32(struct ngbe_hw *hw, u32 reg, u32 val) +{ + if (reg == NGBE_REG_DUMMY) + return; + ngbe_set32(NGBE_REG_ADDR(hw, reg), val); +} + +static inline u32 +rd32m(struct ngbe_hw *hw, u32 reg, u32 mask) +{ + u32 val = rd32(hw, reg); + val &= mask; + return val; +} + +static inline void +wr32m(struct ngbe_hw *hw, u32 reg, u32 mask, u32 field) +{ + u32 val = rd32(hw, reg); + val = ((val & ~mask) | (field & mask)); + wr32(hw, reg, val); +} + +static inline u64 +rd64(struct ngbe_hw *hw, u32 reg) +{ + u64 lsb = rd32(hw, reg); + u64 msb = rd32(hw, reg + 4); + return (lsb | msb << 32); +} + +static inline void +wr64(struct ngbe_hw *hw, u32 reg, u64 val) +{ + wr32(hw, reg, (u32)val); + wr32(hw, reg + 4, (u32)(val >> 32)); +} + +/* poll register */ +static inline u32 +po32m(struct ngbe_hw *hw, u32 reg, u32 mask, u32 expect, u32 *actual, + u32 loop, u32 slice) +{ + bool usec = true; + u32 value = 0, all = 0; + + if (slice > 1000 * MAX_UDELAY_MS) { + usec = false; + slice = (slice + 500) / 1000; + } + + do { + all |= rd32(hw, reg); + value |= mask & all; + if (value == expect) + break; + + usec ? usec_delay(slice) : msec_delay(slice); + } while (--loop > 0); + + if (actual) + *actual = all; + + return loop; +} + +/* flush all write operations */ +#define ngbe_flush(hw) rd32(hw, 0x00100C) + +#define rd32a(hw, reg, idx) ( \ + rd32((hw), (reg) + ((idx) << 2))) +#define wr32a(hw, reg, idx, val) \ + wr32((hw), (reg) + ((idx) << 2), (val)) + +#define rd32w(hw, reg, mask, slice) do { \ + rd32((hw), reg); \ + po32m((hw), reg, mask, mask, NULL, 5, slice); \ +} while (0) + +#define wr32w(hw, reg, val, mask, slice) do { \ + wr32((hw), reg, val); \ + po32m((hw), reg, mask, mask, NULL, 5, slice); \ +} while (0) + +#define NGBE_XPCS_IDAADDR 0x13000 +#define NGBE_XPCS_IDADATA 0x13004 +#define NGBE_EPHY_IDAADDR 0x13008 +#define NGBE_EPHY_IDADATA 0x1300C +static inline u32 +rd32_epcs(struct ngbe_hw *hw, u32 addr) +{ + u32 data; + wr32(hw, NGBE_XPCS_IDAADDR, addr); + data = rd32(hw, NGBE_XPCS_IDADATA); + return data; +} + +static inline void +wr32_epcs(struct ngbe_hw *hw, u32 addr, u32 data) +{ + wr32(hw, NGBE_XPCS_IDAADDR, addr); + wr32(hw, NGBE_XPCS_IDADATA, data); +} + +static inline u32 +rd32_ephy(struct ngbe_hw *hw, u32 addr) +{ + u32 data; + wr32(hw, NGBE_EPHY_IDAADDR, addr); + data = rd32(hw, NGBE_EPHY_IDADATA); + return data; +} + +static inline void +wr32_ephy(struct ngbe_hw *hw, u32 addr, u32 data) +{ + wr32(hw, NGBE_EPHY_IDAADDR, addr); + wr32(hw, NGBE_EPHY_IDADATA, data); +} + +#endif /* _NGBE_REGS_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h index bcc9f74216..4243e04eef 100644 --- a/drivers/net/ngbe/base/ngbe_type.h +++ b/drivers/net/ngbe/base/ngbe_type.h @@ -26,4 +26,6 @@ struct ngbe_hw { bool is_pf; }; +#include "ngbe_regs.h" + #endif /* _NGBE_TYPE_H_ */ From patchwork Wed Jun 2 09:40:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93768 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 E6B37A0524; Wed, 2 Jun 2021 11:40:23 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 849764111E; Wed, 2 Jun 2021 11:39:48 +0200 (CEST) Received: from smtpbguseast2.qq.com (smtpbguseast2.qq.com [54.204.34.130]) by mails.dpdk.org (Postfix) with ESMTP id 88F60410F8 for ; Wed, 2 Jun 2021 11:39:45 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626780tfzrzl5s Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:40 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: xmzaef4TE3dtr6ROoWXKmX+7VQGoOm7fTlP2xxQkQReMnTWne7UJMzylUM/ur MtzKdMndpp8lS1EPuSkAlEazIKhrZbX7URQprkm6TqEqtnHjkblooLMZYgRShMhUso7beBq CQe0qyJsq/luBWADtEwzvZYlbMdCNTJeVsXvRn8Jq9j8i5CGKQt8LDTagC39+jKReaEwXHL gRLRQrWK32iK3cUpgqI7jcvyCv7nU/6hUJgRyffSTjirw5l+ukRpOzsgWGuzZwGwbcNVGZV aJCyGdz9qTJdmAJKjCC8SmCajb1uBgxAdbOzJ0BOKubbZCE4jyWRCeVM/pO7I4Yl8MArK5I KRG5/PIPy+D7N3o38GIS/sg7YAu6g== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:40:51 +0800 Message-Id: <20210602094108.1575640-8-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign5 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 07/24] net/ngbe: set MAC type and LAN id 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 Sender: "dev" Initialize the shared code. Signed-off-by: Jiawen Wu --- drivers/net/ngbe/base/ngbe_dummy.h | 37 +++++++++ drivers/net/ngbe/base/ngbe_hw.c | 122 +++++++++++++++++++++++++++++ drivers/net/ngbe/base/ngbe_hw.h | 5 ++ drivers/net/ngbe/base/ngbe_osdep.h | 2 + drivers/net/ngbe/base/ngbe_type.h | 53 +++++++++++++ drivers/net/ngbe/ngbe_ethdev.c | 8 ++ 6 files changed, 227 insertions(+) create mode 100644 drivers/net/ngbe/base/ngbe_dummy.h diff --git a/drivers/net/ngbe/base/ngbe_dummy.h b/drivers/net/ngbe/base/ngbe_dummy.h new file mode 100644 index 0000000000..75b4e50bca --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_dummy.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + */ + +#ifndef _NGBE_TYPE_DUMMY_H_ +#define _NGBE_TYPE_DUMMY_H_ + +#ifdef TUP +#elif defined(__GNUC__) +#define TUP(x) x##_unused ngbe_unused +#elif defined(__LCLINT__) +#define TUP(x) x /*@unused@*/ +#else +#define TUP(x) x +#endif /*TUP*/ +#define TUP0 TUP(p0) +#define TUP1 TUP(p1) +#define TUP2 TUP(p2) +#define TUP3 TUP(p3) +#define TUP4 TUP(p4) +#define TUP5 TUP(p5) +#define TUP6 TUP(p6) +#define TUP7 TUP(p7) +#define TUP8 TUP(p8) +#define TUP9 TUP(p9) + +/* struct ngbe_bus_operations */ +static inline void ngbe_bus_set_lan_id_dummy(struct ngbe_hw *TUP0) +{ +} +static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw) +{ + hw->bus.set_lan_id = ngbe_bus_set_lan_id_dummy; +} + +#endif /* _NGBE_TYPE_DUMMY_H_ */ + diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c index 0fab47f272..014bb0faee 100644 --- a/drivers/net/ngbe/base/ngbe_hw.c +++ b/drivers/net/ngbe/base/ngbe_hw.c @@ -3,8 +3,74 @@ * Copyright(c) 2010-2017 Intel Corporation */ +#include "ngbe_type.h" #include "ngbe_hw.h" +/** + * ngbe_set_lan_id_multi_port - Set LAN id for PCIe multiple port devices + * @hw: pointer to the HW structure + * + * Determines the LAN function id by reading memory-mapped registers and swaps + * the port value if requested, and set MAC instance for devices. + **/ +void ngbe_set_lan_id_multi_port(struct ngbe_hw *hw) +{ + struct ngbe_bus_info *bus = &hw->bus; + u32 reg = 0; + + DEBUGFUNC("ngbe_set_lan_id_multi_port"); + + reg = rd32(hw, NGBE_PORTSTAT); + bus->lan_id = NGBE_PORTSTAT_ID(reg); + bus->func = bus->lan_id; +} + +/** + * ngbe_set_mac_type - Sets MAC type + * @hw: pointer to the HW structure + * + * This function sets the mac type of the adapter based on the + * vendor ID and device ID stored in the hw structure. + **/ +s32 ngbe_set_mac_type(struct ngbe_hw *hw) +{ + s32 err = 0; + + DEBUGFUNC("ngbe_set_mac_type"); + + if (hw->vendor_id != PCI_VENDOR_ID_WANGXUN) { + DEBUGOUT("Unsupported vendor id: %x", hw->vendor_id); + return NGBE_ERR_DEVICE_NOT_SUPPORTED; + } + + switch (hw->sub_device_id) { + case NGBE_SUB_DEV_ID_EM_RTL_SGMII: + case NGBE_SUB_DEV_ID_EM_MVL_RGMII: + hw->phy.media_type = ngbe_media_type_copper; + hw->mac.type = ngbe_mac_em; + break; + case NGBE_SUB_DEV_ID_EM_MVL_SFP: + case NGBE_SUB_DEV_ID_EM_YT8521S_SFP: + hw->phy.media_type = ngbe_media_type_fiber; + hw->mac.type = ngbe_mac_em; + break; + case NGBE_SUB_DEV_ID_EM_VF: + hw->phy.media_type = ngbe_media_type_virtual; + hw->mac.type = ngbe_mac_em_vf; + break; + default: + err = NGBE_ERR_DEVICE_NOT_SUPPORTED; + hw->phy.media_type = ngbe_media_type_unknown; + hw->mac.type = ngbe_mac_unknown; + DEBUGOUT("Unsupported device id: %x", hw->device_id); + break; + } + + DEBUGOUT("found mac: %d media: %d, returns: %d\n", + hw->mac.type, hw->phy.media_type, err); + return err; +} + void ngbe_map_device_id(struct ngbe_hw *hw) { u16 oem = hw->sub_system_id & NGBE_OEM_MASK; @@ -58,3 +124,59 @@ void ngbe_map_device_id(struct ngbe_hw *hw) } } +/** + * ngbe_init_ops_pf - Inits func ptrs and MAC type + * @hw: pointer to hardware structure + * + * Initialize the function pointers and assign the MAC type. + * Does not touch the hardware. + **/ +s32 ngbe_init_ops_pf(struct ngbe_hw *hw) +{ + struct ngbe_bus_info *bus = &hw->bus; + + DEBUGFUNC("ngbe_init_ops_pf"); + + /* BUS */ + bus->set_lan_id = ngbe_set_lan_id_multi_port; + + return 0; +} + +/** + * ngbe_init_shared_code - Initialize the shared code + * @hw: pointer to hardware structure + * + * This will assign function pointers and assign the MAC type and PHY code. + * Does not touch the hardware. This function must be called prior to any + * other function in the shared code. The ngbe_hw structure should be + * memset to 0 prior to calling this function. The following fields in + * hw structure should be filled in prior to calling this function: + * hw_addr, back, device_id, vendor_id, subsystem_device_id + **/ +s32 ngbe_init_shared_code(struct ngbe_hw *hw) +{ + s32 status = 0; + + DEBUGFUNC("ngbe_init_shared_code"); + + /* + * Set the mac type + */ + ngbe_set_mac_type(hw); + + ngbe_init_ops_dummy(hw); + switch (hw->mac.type) { + case ngbe_mac_em: + ngbe_init_ops_pf(hw); + break; + default: + status = NGBE_ERR_DEVICE_NOT_SUPPORTED; + break; + } + + hw->bus.set_lan_id(hw); + + return status; +} + diff --git a/drivers/net/ngbe/base/ngbe_hw.h b/drivers/net/ngbe/base/ngbe_hw.h index b320d126ec..7d5de49248 100644 --- a/drivers/net/ngbe/base/ngbe_hw.h +++ b/drivers/net/ngbe/base/ngbe_hw.h @@ -8,6 +8,11 @@ #include "ngbe_type.h" +void ngbe_set_lan_id_multi_port(struct ngbe_hw *hw); + +s32 ngbe_init_shared_code(struct ngbe_hw *hw); +s32 ngbe_set_mac_type(struct ngbe_hw *hw); +s32 ngbe_init_ops_pf(struct ngbe_hw *hw); void ngbe_map_device_id(struct ngbe_hw *hw); #endif /* _NGBE_HW_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_osdep.h b/drivers/net/ngbe/base/ngbe_osdep.h index ef3d3d9180..94cc10315e 100644 --- a/drivers/net/ngbe/base/ngbe_osdep.h +++ b/drivers/net/ngbe/base/ngbe_osdep.h @@ -19,6 +19,8 @@ #include #include +#include "../ngbe_logs.h" + #define RTE_LIBRTE_NGBE_TM DCPV(1, 0) #define TMZ_PADDR(mz) ((mz)->iova) #define TMZ_VADDR(mz) ((mz)->addr) diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h index 4243e04eef..15f1778d6a 100644 --- a/drivers/net/ngbe/base/ngbe_type.h +++ b/drivers/net/ngbe/base/ngbe_type.h @@ -12,8 +12,60 @@ #include "ngbe_osdep.h" #include "ngbe_devids.h" +enum ngbe_mac_type { + ngbe_mac_unknown = 0, + ngbe_mac_em, + ngbe_mac_em_vf, + ngbe_num_macs +}; + +enum ngbe_phy_type { + ngbe_phy_unknown = 0, + ngbe_phy_none, + ngbe_phy_rtl, + ngbe_phy_mvl, + ngbe_phy_mvl_sfi, + ngbe_phy_yt8521s, + ngbe_phy_yt8521s_sfi, + ngbe_phy_zte, + ngbe_phy_cu_mtd, +}; + +enum ngbe_media_type { + ngbe_media_type_unknown = 0, + ngbe_media_type_fiber, + ngbe_media_type_fiber_qsfp, + ngbe_media_type_copper, + ngbe_media_type_backplane, + ngbe_media_type_cx4, + ngbe_media_type_virtual +}; + +struct ngbe_hw; + +/* Bus parameters */ +struct ngbe_bus_info { + void (*set_lan_id)(struct ngbe_hw *hw); + + u16 func; + u8 lan_id; +}; + +struct ngbe_mac_info { + enum ngbe_mac_type type; +}; + +struct ngbe_phy_info { + enum ngbe_media_type media_type; + enum ngbe_phy_type type; +}; + struct ngbe_hw { void IOMEM *hw_addr; + void *back; + struct ngbe_mac_info mac; + struct ngbe_phy_info phy; + struct ngbe_bus_info bus; u16 device_id; u16 vendor_id; u16 sub_device_id; @@ -27,5 +79,6 @@ struct ngbe_hw { }; #include "ngbe_regs.h" +#include "ngbe_dummy.h" #endif /* _NGBE_TYPE_H_ */ diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index f24c3e173e..12b80ec695 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -37,6 +37,7 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); struct ngbe_hw *hw = NGBE_DEV_HW(eth_dev); const struct rte_memzone *mz; + int err; PMD_INIT_FUNC_TRACE(); @@ -62,6 +63,13 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) hw->isb_dma = TMZ_PADDR(mz); hw->isb_mem = TMZ_VADDR(mz); + /* Initialize the shared code (base driver) */ + err = ngbe_init_shared_code(hw); + if (err != 0) { + PMD_INIT_LOG(ERR, "Shared code init failed: %d", err); + return -EIO; + } + return 0; } From patchwork Wed Jun 2 09:40:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93770 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 AE0F5A0524; Wed, 2 Jun 2021 11:40:37 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id B64F141137; Wed, 2 Jun 2021 11:39:50 +0200 (CEST) Received: from smtpbgbr2.qq.com (smtpbgbr2.qq.com [54.207.22.56]) by mails.dpdk.org (Postfix) with ESMTP id 3EEAA410FE for ; Wed, 2 Jun 2021 11:39:46 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626782t7yczoo1 Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:41 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: O9RHVi+JMbKjKUGxkfl8gQzFsaHFKSEpEMiO3AYX3KpGQokh0gRg7cFFXkxH/ k8IV3lLe3LcaE5ov4YJ+PA5iYGf8kEFyFAfQ+XdmtNRrt5Er6yTmqcpFJ0ctj7/pczDyrID ddyoOCyzH2ZBYqP9U5CGqc7yzShxtDV8gH3vtbiVVFrcarI3n8onfEQZlRIjTF8/n6h5pG1 bMf3iMuGcgu+u+8fCOy+BbzV0God7/vOuhA2Lv1zAixR4p/H64sWMgSQzc4CJ2HO1bBbJq6 DiSAAw7twGPQv5Aeby+susaRcb73lIgd8687unU/G8Pu0Z608CF8Z0s2AH64nuUVeonEYXq 0+7wQzMHIBUz//cR5wzlwvKlIFfOQ== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:40:52 +0800 Message-Id: <20210602094108.1575640-9-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign6 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 08/24] net/ngbe: init and validate EEPROM 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 Sender: "dev" Reset swfw lock before NVM access, init EEPROM and validate the checksum. Signed-off-by: Jiawen Wu --- drivers/net/ngbe/base/meson.build | 2 + drivers/net/ngbe/base/ngbe_dummy.h | 23 ++++ drivers/net/ngbe/base/ngbe_eeprom.c | 203 ++++++++++++++++++++++++++++ drivers/net/ngbe/base/ngbe_eeprom.h | 17 +++ drivers/net/ngbe/base/ngbe_hw.c | 83 ++++++++++++ drivers/net/ngbe/base/ngbe_hw.h | 3 + drivers/net/ngbe/base/ngbe_mng.c | 198 +++++++++++++++++++++++++++ drivers/net/ngbe/base/ngbe_mng.h | 65 +++++++++ drivers/net/ngbe/base/ngbe_type.h | 24 ++++ drivers/net/ngbe/ngbe_ethdev.c | 39 ++++++ 10 files changed, 657 insertions(+) create mode 100644 drivers/net/ngbe/base/ngbe_eeprom.c create mode 100644 drivers/net/ngbe/base/ngbe_eeprom.h create mode 100644 drivers/net/ngbe/base/ngbe_mng.c create mode 100644 drivers/net/ngbe/base/ngbe_mng.h diff --git a/drivers/net/ngbe/base/meson.build b/drivers/net/ngbe/base/meson.build index fdbfa99916..ddd122ec45 100644 --- a/drivers/net/ngbe/base/meson.build +++ b/drivers/net/ngbe/base/meson.build @@ -2,7 +2,9 @@ # Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. sources = [ + 'ngbe_eeprom.c', 'ngbe_hw.c', + 'ngbe_mng.c', ] error_cflags = [] diff --git a/drivers/net/ngbe/base/ngbe_dummy.h b/drivers/net/ngbe/base/ngbe_dummy.h index 75b4e50bca..ade03eae81 100644 --- a/drivers/net/ngbe/base/ngbe_dummy.h +++ b/drivers/net/ngbe/base/ngbe_dummy.h @@ -28,9 +28,32 @@ static inline void ngbe_bus_set_lan_id_dummy(struct ngbe_hw *TUP0) { } +/* struct ngbe_rom_operations */ +static inline s32 ngbe_rom_init_params_dummy(struct ngbe_hw *TUP0) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_rom_validate_checksum_dummy(struct ngbe_hw *TUP0, + u16 *TUP1) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_mac_acquire_swfw_sync_dummy(struct ngbe_hw *TUP0, + u32 TUP1) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline void ngbe_mac_release_swfw_sync_dummy(struct ngbe_hw *TUP0, + u32 TUP1) +{ +} static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw) { hw->bus.set_lan_id = ngbe_bus_set_lan_id_dummy; + hw->rom.init_params = ngbe_rom_init_params_dummy; + hw->rom.validate_checksum = ngbe_rom_validate_checksum_dummy; + hw->mac.acquire_swfw_sync = ngbe_mac_acquire_swfw_sync_dummy; + hw->mac.release_swfw_sync = ngbe_mac_release_swfw_sync_dummy; } #endif /* _NGBE_TYPE_DUMMY_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_eeprom.c b/drivers/net/ngbe/base/ngbe_eeprom.c new file mode 100644 index 0000000000..0ebbb7a29e --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_eeprom.c @@ -0,0 +1,203 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#include "ngbe_hw.h" +#include "ngbe_mng.h" +#include "ngbe_eeprom.h" + +/** + * ngbe_init_eeprom_params - Initialize EEPROM params + * @hw: pointer to hardware structure + * + * Initializes the EEPROM parameters ngbe_rom_info within the + * ngbe_hw struct in order to set up EEPROM access. + **/ +s32 ngbe_init_eeprom_params(struct ngbe_hw *hw) +{ + struct ngbe_rom_info *eeprom = &hw->rom; + u32 eec; + u16 eeprom_size; + + DEBUGFUNC("ngbe_init_eeprom_params"); + + if (eeprom->type != ngbe_eeprom_unknown) + return 0; + + eeprom->type = ngbe_eeprom_none; + /* Set default semaphore delay to 10ms which is a well + * tested value + */ + eeprom->semaphore_delay = 10; /*ms*/ + /* Clear EEPROM page size, it will be initialized as needed */ + eeprom->word_page_size = 0; + + /* + * Check for EEPROM present first. + * If not present leave as none + */ + eec = rd32(hw, NGBE_SPISTAT); + if (!(eec & NGBE_SPISTAT_BPFLASH)) { + eeprom->type = ngbe_eeprom_flash; + + /* + * SPI EEPROM is assumed here. This code would need to + * change if a future EEPROM is not SPI. + */ + eeprom_size = 4096; + eeprom->word_size = eeprom_size >> 1; + } + + eeprom->address_bits = 16; + eeprom->sw_addr = 0x80; + + DEBUGOUT("eeprom params: type = %d, size = %d, address bits: " + "%d %d\n", eeprom->type, eeprom->word_size, + eeprom->address_bits, eeprom->sw_addr); + + return 0; +} + +/** + * ngbe_get_eeprom_semaphore - Get hardware semaphore + * @hw: pointer to hardware structure + * + * Sets the hardware semaphores so EEPROM access can occur for bit-bang method + **/ +s32 ngbe_get_eeprom_semaphore(struct ngbe_hw *hw) +{ + s32 status = NGBE_ERR_EEPROM; + u32 timeout = 2000; + u32 i; + u32 swsm; + + DEBUGFUNC("ngbe_get_eeprom_semaphore"); + + + /* Get SMBI software semaphore between device drivers first */ + for (i = 0; i < timeout; i++) { + /* + * If the SMBI bit is 0 when we read it, then the bit will be + * set and we have the semaphore + */ + swsm = rd32(hw, NGBE_SWSEM); + if (!(swsm & NGBE_SWSEM_PF)) { + status = 0; + break; + } + usec_delay(50); + } + + if (i == timeout) { + DEBUGOUT("Driver can't access the eeprom - SMBI Semaphore " + "not granted.\n"); + /* + * this release is particularly important because our attempts + * above to get the semaphore may have succeeded, and if there + * was a timeout, we should unconditionally clear the semaphore + * bits to free the driver to make progress + */ + ngbe_release_eeprom_semaphore(hw); + + usec_delay(50); + /* + * one last try + * If the SMBI bit is 0 when we read it, then the bit will be + * set and we have the semaphore + */ + swsm = rd32(hw, NGBE_SWSEM); + if (!(swsm & NGBE_SWSEM_PF)) + status = 0; + } + + /* Now get the semaphore between SW/FW through the SWESMBI bit */ + if (status == 0) { + for (i = 0; i < timeout; i++) { + /* Set the SW EEPROM semaphore bit to request access */ + wr32m(hw, NGBE_MNGSWSYNC, + NGBE_MNGSWSYNC_REQ, NGBE_MNGSWSYNC_REQ); + + /* + * If we set the bit successfully then we got the + * semaphore. + */ + swsm = rd32(hw, NGBE_MNGSWSYNC); + if (swsm & NGBE_MNGSWSYNC_REQ) + break; + + usec_delay(50); + } + + /* + * Release semaphores and return error if SW EEPROM semaphore + * was not granted because we don't have access to the EEPROM + */ + if (i >= timeout) { + DEBUGOUT("SWESMBI Software EEPROM semaphore not granted.\n"); + ngbe_release_eeprom_semaphore(hw); + status = NGBE_ERR_EEPROM; + } + } else { + DEBUGOUT("Software semaphore SMBI between device drivers " + "not granted.\n"); + } + + return status; +} + +/** + * ngbe_release_eeprom_semaphore - Release hardware semaphore + * @hw: pointer to hardware structure + * + * This function clears hardware semaphore bits. + **/ +void ngbe_release_eeprom_semaphore(struct ngbe_hw *hw) +{ + DEBUGFUNC("ngbe_release_eeprom_semaphore"); + + wr32m(hw, NGBE_MNGSWSYNC, NGBE_MNGSWSYNC_REQ, 0); + wr32m(hw, NGBE_SWSEM, NGBE_SWSEM_PF, 0); + ngbe_flush(hw); +} + +/** + * ngbe_validate_eeprom_checksum_em - Validate EEPROM checksum + * @hw: pointer to hardware structure + * @checksum_val: calculated checksum + * + * Performs checksum calculation and validates the EEPROM checksum. If the + * caller does not need checksum_val, the value can be NULL. + **/ +s32 ngbe_validate_eeprom_checksum_em(struct ngbe_hw *hw, + u16 *checksum_val) +{ + u32 eeprom_cksum_devcap = 0; + int err = 0; + + DEBUGFUNC("ngbe_validate_eeprom_checksum_em"); + UNREFERENCED_PARAMETER(checksum_val); + + /* Check EEPROM only once */ + if (hw->bus.lan_id == 0) { + wr32(hw, NGBE_CALSUM_CAP_STATUS, 0x0); + wr32(hw, NGBE_EEPROM_VERSION_STORE_REG, 0x0); + } else { + eeprom_cksum_devcap = rd32(hw, NGBE_CALSUM_CAP_STATUS); + hw->rom.saved_version = rd32(hw, NGBE_EEPROM_VERSION_STORE_REG); + } + + if (hw->bus.lan_id == 0 || eeprom_cksum_devcap == 0) { + err = ngbe_hic_check_cap(hw); + if (err != 0) { + PMD_INIT_LOG(ERR, + "The EEPROM checksum is not valid: %d", err); + return -EIO; + } + } + + hw->rom.cksum_devcap = eeprom_cksum_devcap & 0xffff; + + return err; +} + diff --git a/drivers/net/ngbe/base/ngbe_eeprom.h b/drivers/net/ngbe/base/ngbe_eeprom.h new file mode 100644 index 0000000000..0c2819df4a --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_eeprom.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#ifndef _NGBE_EEPROM_H_ +#define _NGBE_EEPROM_H_ + +#define NGBE_CALSUM_CAP_STATUS 0x10224 +#define NGBE_EEPROM_VERSION_STORE_REG 0x1022C + +s32 ngbe_init_eeprom_params(struct ngbe_hw *hw); +s32 ngbe_validate_eeprom_checksum_em(struct ngbe_hw *hw, u16 *checksum_val); +s32 ngbe_get_eeprom_semaphore(struct ngbe_hw *hw); +void ngbe_release_eeprom_semaphore(struct ngbe_hw *hw); + +#endif /* _NGBE_EEPROM_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c index 014bb0faee..de6b75e1c0 100644 --- a/drivers/net/ngbe/base/ngbe_hw.c +++ b/drivers/net/ngbe/base/ngbe_hw.c @@ -4,6 +4,8 @@ */ #include "ngbe_type.h" +#include "ngbe_eeprom.h" +#include "ngbe_mng.h" #include "ngbe_hw.h" /** @@ -25,6 +27,77 @@ void ngbe_set_lan_id_multi_port(struct ngbe_hw *hw) bus->func = bus->lan_id; } +/** + * ngbe_acquire_swfw_sync - Acquire SWFW semaphore + * @hw: pointer to hardware structure + * @mask: Mask to specify which semaphore to acquire + * + * Acquires the SWFW semaphore through the MNGSEM register for the specified + * function (CSR, PHY0, PHY1, EEPROM, Flash) + **/ +s32 ngbe_acquire_swfw_sync(struct ngbe_hw *hw, u32 mask) +{ + u32 mngsem = 0; + u32 swmask = NGBE_MNGSEM_SW(mask); + u32 fwmask = NGBE_MNGSEM_FW(mask); + u32 timeout = 200; + u32 i; + + DEBUGFUNC("ngbe_acquire_swfw_sync"); + + for (i = 0; i < timeout; i++) { + /* + * SW NVM semaphore bit is used for access to all + * SW_FW_SYNC bits (not just NVM) + */ + if (ngbe_get_eeprom_semaphore(hw)) + return NGBE_ERR_SWFW_SYNC; + + mngsem = rd32(hw, NGBE_MNGSEM); + if (mngsem & (fwmask | swmask)) { + /* Resource is currently in use by FW or SW */ + ngbe_release_eeprom_semaphore(hw); + msec_delay(5); + } else { + mngsem |= swmask; + wr32(hw, NGBE_MNGSEM, mngsem); + ngbe_release_eeprom_semaphore(hw); + return 0; + } + } + + /* If time expired clear the bits holding the lock and retry */ + if (mngsem & (fwmask | swmask)) + ngbe_release_swfw_sync(hw, mngsem & (fwmask | swmask)); + + msec_delay(5); + return NGBE_ERR_SWFW_SYNC; +} + +/** + * ngbe_release_swfw_sync - Release SWFW semaphore + * @hw: pointer to hardware structure + * @mask: Mask to specify which semaphore to release + * + * Releases the SWFW semaphore through the MNGSEM register for the specified + * function (CSR, PHY0, PHY1, EEPROM, Flash) + **/ +void ngbe_release_swfw_sync(struct ngbe_hw *hw, u32 mask) +{ + u32 mngsem; + u32 swmask = mask; + + DEBUGFUNC("ngbe_release_swfw_sync"); + + ngbe_get_eeprom_semaphore(hw); + + mngsem = rd32(hw, NGBE_MNGSEM); + mngsem &= ~swmask; + wr32(hw, NGBE_MNGSEM, mngsem); + + ngbe_release_eeprom_semaphore(hw); +} + /** * ngbe_set_mac_type - Sets MAC type * @hw: pointer to the HW structure @@ -134,12 +207,22 @@ void ngbe_map_device_id(struct ngbe_hw *hw) s32 ngbe_init_ops_pf(struct ngbe_hw *hw) { struct ngbe_bus_info *bus = &hw->bus; + struct ngbe_mac_info *mac = &hw->mac; + struct ngbe_rom_info *rom = &hw->rom; DEBUGFUNC("ngbe_init_ops_pf"); /* BUS */ bus->set_lan_id = ngbe_set_lan_id_multi_port; + /* MAC */ + mac->acquire_swfw_sync = ngbe_acquire_swfw_sync; + mac->release_swfw_sync = ngbe_release_swfw_sync; + + /* EEPROM */ + rom->init_params = ngbe_init_eeprom_params; + rom->validate_checksum = ngbe_validate_eeprom_checksum_em; + return 0; } diff --git a/drivers/net/ngbe/base/ngbe_hw.h b/drivers/net/ngbe/base/ngbe_hw.h index 7d5de49248..5e508fb67f 100644 --- a/drivers/net/ngbe/base/ngbe_hw.h +++ b/drivers/net/ngbe/base/ngbe_hw.h @@ -10,6 +10,9 @@ void ngbe_set_lan_id_multi_port(struct ngbe_hw *hw); +s32 ngbe_acquire_swfw_sync(struct ngbe_hw *hw, u32 mask); +void ngbe_release_swfw_sync(struct ngbe_hw *hw, u32 mask); + s32 ngbe_init_shared_code(struct ngbe_hw *hw); s32 ngbe_set_mac_type(struct ngbe_hw *hw); s32 ngbe_init_ops_pf(struct ngbe_hw *hw); diff --git a/drivers/net/ngbe/base/ngbe_mng.c b/drivers/net/ngbe/base/ngbe_mng.c new file mode 100644 index 0000000000..87891a91e1 --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_mng.c @@ -0,0 +1,198 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#include "ngbe_type.h" +#include "ngbe_mng.h" + +/** + * ngbe_hic_unlocked - Issue command to manageability block unlocked + * @hw: pointer to the HW structure + * @buffer: command to write and where the return status will be placed + * @length: length of buffer, must be multiple of 4 bytes + * @timeout: time in ms to wait for command completion + * + * Communicates with the manageability block. On success return 0 + * else returns semaphore error when encountering an error acquiring + * semaphore or NGBE_ERR_HOST_INTERFACE_COMMAND when command fails. + * + * This function assumes that the NGBE_MNGSEM_SWMBX semaphore is held + * by the caller. + **/ +static s32 +ngbe_hic_unlocked(struct ngbe_hw *hw, u32 *buffer, u32 length, u32 timeout) +{ + u32 value, loop; + u16 i, dword_len; + + DEBUGFUNC("ngbe_hic_unlocked"); + + if (!length || length > NGBE_PMMBX_BSIZE) { + DEBUGOUT("Buffer length failure buffersize=%d.\n", length); + return NGBE_ERR_HOST_INTERFACE_COMMAND; + } + + /* Calculate length in DWORDs. We must be DWORD aligned */ + if (length % sizeof(u32)) { + DEBUGOUT("Buffer length failure, not aligned to dword"); + return NGBE_ERR_INVALID_ARGUMENT; + } + + dword_len = length >> 2; + + /* The device driver writes the relevant command block + * into the ram area. + */ + for (i = 0; i < dword_len; i++) { + wr32a(hw, NGBE_MNGMBX, i, cpu_to_le32(buffer[i])); + buffer[i] = rd32a(hw, NGBE_MNGMBX, i); + } + ngbe_flush(hw); + + /* Setting this bit tells the ARC that a new command is pending. */ + wr32m(hw, NGBE_MNGMBXCTL, + NGBE_MNGMBXCTL_SWRDY, NGBE_MNGMBXCTL_SWRDY); + + /* Check command completion */ + loop = po32m(hw, NGBE_MNGMBXCTL, + NGBE_MNGMBXCTL_FWRDY, NGBE_MNGMBXCTL_FWRDY, + &value, timeout, 1000); + if (!loop || !(value & NGBE_MNGMBXCTL_FWACK)) { + DEBUGOUT("Command has failed with no status valid.\n"); + return NGBE_ERR_HOST_INTERFACE_COMMAND; + } + + return 0; +} + +/** + * ngbe_host_interface_command - Issue command to manageability block + * @hw: pointer to the HW structure + * @buffer: contains the command to write and where the return status will + * be placed + * @length: length of buffer, must be multiple of 4 bytes + * @timeout: time in ms to wait for command completion + * @return_data: read and return data from the buffer (true) or not (false) + * Needed because FW structures are big endian and decoding of + * these fields can be 8 bit or 16 bit based on command. Decoding + * is not easily understood without making a table of commands. + * So we will leave this up to the caller to read back the data + * in these cases. + * + * Communicates with the manageability block. On success return 0 + * else returns semaphore error when encountering an error acquiring + * semaphore or NGBE_ERR_HOST_INTERFACE_COMMAND when command fails. + **/ +static s32 +ngbe_host_interface_command(struct ngbe_hw *hw, u32 *buffer, + u32 length, u32 timeout, bool return_data) +{ + u32 hdr_size = sizeof(struct ngbe_hic_hdr); + struct ngbe_hic_hdr *resp = (struct ngbe_hic_hdr *)buffer; + u16 buf_len; + s32 err; + u32 bi; + u32 dword_len; + + DEBUGFUNC("ngbe_host_interface_command"); + + if (length == 0 || length > NGBE_PMMBX_BSIZE) { + DEBUGOUT("Buffer length failure buffersize=%d.\n", length); + return NGBE_ERR_HOST_INTERFACE_COMMAND; + } + + /* Take management host interface semaphore */ + err = hw->mac.acquire_swfw_sync(hw, NGBE_MNGSEM_SWMBX); + if (err) + return err; + + err = ngbe_hic_unlocked(hw, buffer, length, timeout); + if (err) + goto rel_out; + + if (!return_data) + goto rel_out; + + /* Calculate length in DWORDs */ + dword_len = hdr_size >> 2; + + /* first pull in the header so we know the buffer length */ + for (bi = 0; bi < dword_len; bi++) + buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi); + + /* + * If there is any thing in data position pull it in + * Read Flash command requires reading buffer length from + * two byes instead of one byte + */ + if (resp->cmd == 0x30) { + for (; bi < dword_len + 2; bi++) + buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi); + + buf_len = (((u16)(resp->cmd_or_resp.ret_status) << 3) + & 0xF00) | resp->buf_len; + hdr_size += (2 << 2); + } else { + buf_len = resp->buf_len; + } + if (!buf_len) + goto rel_out; + + if (length < buf_len + hdr_size) { + DEBUGOUT("Buffer not large enough for reply message.\n"); + err = NGBE_ERR_HOST_INTERFACE_COMMAND; + goto rel_out; + } + + /* Calculate length in DWORDs, add 3 for odd lengths */ + dword_len = (buf_len + 3) >> 2; + + /* Pull in the rest of the buffer (bi is where we left off) */ + for (; bi <= dword_len; bi++) + buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi); + +rel_out: + hw->mac.release_swfw_sync(hw, NGBE_MNGSEM_SWMBX); + + return err; +} + +s32 ngbe_hic_check_cap(struct ngbe_hw *hw) +{ + struct ngbe_hic_read_shadow_ram command; + s32 err; + int i; + + DEBUGFUNC("\n"); + + command.hdr.req.cmd = FW_EEPROM_CHECK_STATUS; + command.hdr.req.buf_lenh = 0; + command.hdr.req.buf_lenl = 0; + command.hdr.req.checksum = FW_DEFAULT_CHECKSUM; + + /* convert offset from words to bytes */ + command.address = 0; + /* one word */ + command.length = 0; + + for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { + err = ngbe_host_interface_command(hw, (u32 *)&command, + sizeof(command), + NGBE_HI_COMMAND_TIMEOUT, true); + if (err) + continue; + + command.hdr.rsp.ret_status &= 0x1F; + if (command.hdr.rsp.ret_status != + FW_CEM_RESP_STATUS_SUCCESS) + err = NGBE_ERR_HOST_INTERFACE_COMMAND; + + break; + } + + if (!err && command.address != FW_CHECKSUM_CAP_ST_PASS) + err = NGBE_ERR_EEPROM_CHECKSUM; + + return err; +} diff --git a/drivers/net/ngbe/base/ngbe_mng.h b/drivers/net/ngbe/base/ngbe_mng.h new file mode 100644 index 0000000000..383e0dc0d1 --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_mng.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#ifndef _NGBE_MNG_H_ +#define _NGBE_MNG_H_ + +#include "ngbe_type.h" + +#define NGBE_PMMBX_QSIZE 64 /* Num of dwords in range */ +#define NGBE_PMMBX_BSIZE (NGBE_PMMBX_QSIZE * 4) +#define NGBE_HI_COMMAND_TIMEOUT 5000 /* Process HI command limit */ + +/* CEM Support */ +#define FW_CEM_MAX_RETRIES 3 +#define FW_CEM_RESP_STATUS_SUCCESS 0x1 +#define FW_DEFAULT_CHECKSUM 0xFF /* checksum always 0xFF */ +#define FW_EEPROM_CHECK_STATUS 0xE9 + +#define FW_CHECKSUM_CAP_ST_PASS 0x80658383 +#define FW_CHECKSUM_CAP_ST_FAIL 0x70657376 + +/* Host Interface Command Structures */ +struct ngbe_hic_hdr { + u8 cmd; + u8 buf_len; + union { + u8 cmd_resv; + u8 ret_status; + } cmd_or_resp; + u8 checksum; +}; + +struct ngbe_hic_hdr2_req { + u8 cmd; + u8 buf_lenh; + u8 buf_lenl; + u8 checksum; +}; + +struct ngbe_hic_hdr2_rsp { + u8 cmd; + u8 buf_lenl; + u8 ret_status; /* 7-5: high bits of buf_len, 4-0: status */ + u8 checksum; +}; + +union ngbe_hic_hdr2 { + struct ngbe_hic_hdr2_req req; + struct ngbe_hic_hdr2_rsp rsp; +}; + +/* These need to be dword aligned */ +struct ngbe_hic_read_shadow_ram { + union ngbe_hic_hdr2 hdr; + u32 address; + u16 length; + u16 pad2; + u16 data; + u16 pad3; +}; + +s32 ngbe_hic_check_cap(struct ngbe_hw *hw); +#endif /* _NGBE_MNG_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h index 15f1778d6a..28b15cfb5a 100644 --- a/drivers/net/ngbe/base/ngbe_type.h +++ b/drivers/net/ngbe/base/ngbe_type.h @@ -12,6 +12,13 @@ #include "ngbe_osdep.h" #include "ngbe_devids.h" +enum ngbe_eeprom_type { + ngbe_eeprom_unknown = 0, + ngbe_eeprom_spi, + ngbe_eeprom_flash, + ngbe_eeprom_none /* No NVM support */ +}; + enum ngbe_mac_type { ngbe_mac_unknown = 0, ngbe_mac_em, @@ -51,7 +58,23 @@ struct ngbe_bus_info { u8 lan_id; }; +struct ngbe_rom_info { + s32 (*init_params)(struct ngbe_hw *hw); + s32 (*validate_checksum)(struct ngbe_hw *hw, u16 *checksum_val); + + enum ngbe_eeprom_type type; + u32 semaphore_delay; + u16 word_size; + u16 address_bits; + u16 word_page_size; + u32 sw_addr; + u32 saved_version; + u16 cksum_devcap; +}; + struct ngbe_mac_info { + s32 (*acquire_swfw_sync)(struct ngbe_hw *hw, u32 mask); + void (*release_swfw_sync)(struct ngbe_hw *hw, u32 mask); enum ngbe_mac_type type; }; @@ -65,6 +88,7 @@ struct ngbe_hw { void *back; struct ngbe_mac_info mac; struct ngbe_phy_info phy; + struct ngbe_rom_info rom; struct ngbe_bus_info bus; u16 device_id; u16 vendor_id; diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 12b80ec695..c2f92a8437 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -31,6 +31,29 @@ static const struct rte_pci_id pci_id_ngbe_map[] = { { .vendor_id = 0, /* sentinel */ }, }; +/* + * Ensure that all locks are released before first NVM or PHY access + */ +static void +ngbe_swfw_lock_reset(struct ngbe_hw *hw) +{ + uint16_t mask; + + /* + * These ones are more tricky since they are common to all ports; but + * swfw_sync retries last long enough (1s) to be almost sure that if + * lock can not be taken it is due to an improper lock of the + * semaphore. + */ + mask = NGBE_MNGSEM_SWPHY | + NGBE_MNGSEM_SWMBX | + NGBE_MNGSEM_SWFLASH; + if (hw->mac.acquire_swfw_sync(hw, mask) < 0) + PMD_DRV_LOG(DEBUG, "SWFW common locks released"); + + hw->mac.release_swfw_sync(hw, mask); +} + static int eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) { @@ -70,6 +93,22 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + /* Unlock any pending hardware semaphore */ + ngbe_swfw_lock_reset(hw); + + err = hw->rom.init_params(hw); + if (err != 0) { + PMD_INIT_LOG(ERR, "The EEPROM init failed: %d", err); + return -EIO; + } + + /* Make sure we have a good EEPROM before we read from it */ + err = hw->rom.validate_checksum(hw, NULL); + if (err != 0) { + PMD_INIT_LOG(ERR, "The EEPROM checksum is not valid: %d", err); + return -EIO; + } + return 0; } From patchwork Wed Jun 2 09:40:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93771 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 EA60CA0524; Wed, 2 Jun 2021 11:40:47 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 4EBBB41147; Wed, 2 Jun 2021 11:39:52 +0200 (CEST) Received: from smtpbgeu1.qq.com (smtpbgeu1.qq.com [52.59.177.22]) by mails.dpdk.org (Postfix) with ESMTP id 30574410F5 for ; Wed, 2 Jun 2021 11:39:47 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626783tb3he0qv Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:43 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: O0I776c7Orzifd5BgCTAsdsC2+563oUh3H8yPOXtDV9ulcGFp7aUARHcuMsed CF4b9jaxDLekGTQ3B9Ab3ozlmqy7B4o6y5M+XyRd5hvAXzVJoLcXjc08qOzu/weXJkirxyx GTexQODdsWsilWhVRjFD75p6eEmDn+EGOn+j9TyFq2gqN477BYK0pErOTjMWfCsun30W62R HwmpT7WOzVlLZAO5CBym7XwtyXa2VhKC+U51rw8LaAclRx5PBrLbAHfH2TDoJLTVgIa8tA8 xhQCTfmpZ7e3yUY/u/MKlRWD51nS4UjqAk1X6v9rhJk7rWMrSK/rcUe5gDSIt00ZIMI+BE7 CfBPbL8dnmdmyLSOds1yYb6lpKUvQ== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:40:53 +0800 Message-Id: <20210602094108.1575640-10-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign5 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 09/24] net/ngbe: add HW initialization 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 Sender: "dev" Initialize the hardware by resetting the hardware in base code. Signed-off-by: Jiawen Wu --- drivers/net/ngbe/base/ngbe_dummy.h | 21 +++ drivers/net/ngbe/base/ngbe_hw.c | 235 +++++++++++++++++++++++++++++ drivers/net/ngbe/base/ngbe_hw.h | 9 ++ drivers/net/ngbe/base/ngbe_type.h | 24 +++ drivers/net/ngbe/ngbe_ethdev.c | 7 + 5 files changed, 296 insertions(+) diff --git a/drivers/net/ngbe/base/ngbe_dummy.h b/drivers/net/ngbe/base/ngbe_dummy.h index ade03eae81..d0081acc2b 100644 --- a/drivers/net/ngbe/base/ngbe_dummy.h +++ b/drivers/net/ngbe/base/ngbe_dummy.h @@ -38,6 +38,19 @@ static inline s32 ngbe_rom_validate_checksum_dummy(struct ngbe_hw *TUP0, { return NGBE_ERR_OPS_DUMMY; } +/* struct ngbe_mac_operations */ +static inline s32 ngbe_mac_init_hw_dummy(struct ngbe_hw *TUP0) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_mac_reset_hw_dummy(struct ngbe_hw *TUP0) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_mac_stop_hw_dummy(struct ngbe_hw *TUP0) +{ + return NGBE_ERR_OPS_DUMMY; +} static inline s32 ngbe_mac_acquire_swfw_sync_dummy(struct ngbe_hw *TUP0, u32 TUP1) { @@ -47,13 +60,21 @@ static inline void ngbe_mac_release_swfw_sync_dummy(struct ngbe_hw *TUP0, u32 TUP1) { } +static inline s32 ngbe_mac_init_thermal_ssth_dummy(struct ngbe_hw *TUP0) +{ + return NGBE_ERR_OPS_DUMMY; +} static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw) { hw->bus.set_lan_id = ngbe_bus_set_lan_id_dummy; hw->rom.init_params = ngbe_rom_init_params_dummy; hw->rom.validate_checksum = ngbe_rom_validate_checksum_dummy; + hw->mac.init_hw = ngbe_mac_init_hw_dummy; + hw->mac.reset_hw = ngbe_mac_reset_hw_dummy; + hw->mac.stop_hw = ngbe_mac_stop_hw_dummy; hw->mac.acquire_swfw_sync = ngbe_mac_acquire_swfw_sync_dummy; hw->mac.release_swfw_sync = ngbe_mac_release_swfw_sync_dummy; + hw->mac.init_thermal_sensor_thresh = ngbe_mac_init_thermal_ssth_dummy; } #endif /* _NGBE_TYPE_DUMMY_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c index de6b75e1c0..9fa40f7de1 100644 --- a/drivers/net/ngbe/base/ngbe_hw.c +++ b/drivers/net/ngbe/base/ngbe_hw.c @@ -8,6 +8,133 @@ #include "ngbe_mng.h" #include "ngbe_hw.h" +/** + * ngbe_init_hw - Generic hardware initialization + * @hw: pointer to hardware structure + * + * Initialize the hardware by resetting the hardware, filling the bus info + * structure and media type, clears all on chip counters, initializes receive + * address registers, multicast table, VLAN filter table, calls routine to set + * up link and flow control settings, and leaves transmit and receive units + * disabled and uninitialized + **/ +s32 ngbe_init_hw(struct ngbe_hw *hw) +{ + s32 status; + + DEBUGFUNC("ngbe_init_hw"); + + /* Reset the hardware */ + status = hw->mac.reset_hw(hw); + + if (status != 0) + DEBUGOUT("Failed to initialize HW, STATUS = %d\n", status); + + return status; +} + +static void +ngbe_reset_misc_em(struct ngbe_hw *hw) +{ + int i; + + wr32(hw, NGBE_ISBADDRL, hw->isb_dma & 0xFFFFFFFF); + wr32(hw, NGBE_ISBADDRH, hw->isb_dma >> 32); + + /* receive packets that size > 2048 */ + wr32m(hw, NGBE_MACRXCFG, + NGBE_MACRXCFG_JUMBO, NGBE_MACRXCFG_JUMBO); + + wr32m(hw, NGBE_FRMSZ, NGBE_FRMSZ_MAX_MASK, + NGBE_FRMSZ_MAX(NGBE_FRAME_SIZE_DFT)); + + /* clear counters on read */ + wr32m(hw, NGBE_MACCNTCTL, + NGBE_MACCNTCTL_RC, NGBE_MACCNTCTL_RC); + + wr32m(hw, NGBE_RXFCCFG, + NGBE_RXFCCFG_FC, NGBE_RXFCCFG_FC); + wr32m(hw, NGBE_TXFCCFG, + NGBE_TXFCCFG_FC, NGBE_TXFCCFG_FC); + + wr32m(hw, NGBE_MACRXFLT, + NGBE_MACRXFLT_PROMISC, NGBE_MACRXFLT_PROMISC); + + wr32m(hw, NGBE_RSTSTAT, + NGBE_RSTSTAT_TMRINIT_MASK, NGBE_RSTSTAT_TMRINIT(30)); + + /* errata 4: initialize mng flex tbl and wakeup flex tbl*/ + wr32(hw, NGBE_MNGFLEXSEL, 0); + for (i = 0; i < 16; i++) { + wr32(hw, NGBE_MNGFLEXDWL(i), 0); + wr32(hw, NGBE_MNGFLEXDWH(i), 0); + wr32(hw, NGBE_MNGFLEXMSK(i), 0); + } + wr32(hw, NGBE_LANFLEXSEL, 0); + for (i = 0; i < 16; i++) { + wr32(hw, NGBE_LANFLEXDWL(i), 0); + wr32(hw, NGBE_LANFLEXDWH(i), 0); + wr32(hw, NGBE_LANFLEXMSK(i), 0); + } + + /* set pause frame dst mac addr */ + wr32(hw, NGBE_RXPBPFCDMACL, 0xC2000001); + wr32(hw, NGBE_RXPBPFCDMACH, 0x0180); + + wr32(hw, NGBE_MDIOMODE, 0xF); + + wr32m(hw, NGBE_GPIE, NGBE_GPIE_MSIX, NGBE_GPIE_MSIX); + + if ((hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_M88E1512_SFP || + (hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_YT8521S_SFP) { + /* gpio0 is used to power on/off control*/ + wr32(hw, NGBE_GPIODIR, NGBE_GPIODIR_DDR(1)); + wr32(hw, NGBE_GPIODATA, NGBE_GPIOBIT_0); + } + + hw->mac.init_thermal_sensor_thresh(hw); + + /* enable mac transmiter */ + wr32m(hw, NGBE_MACTXCFG, NGBE_MACTXCFG_TE, NGBE_MACTXCFG_TE); + + /* sellect GMII */ + wr32m(hw, NGBE_MACTXCFG, + NGBE_MACTXCFG_SPEED_MASK, NGBE_MACTXCFG_SPEED_1G); + + for (i = 0; i < 4; i++) + wr32m(hw, NGBE_IVAR(i), 0x80808080, 0); +} + +/** + * ngbe_reset_hw_em - Perform hardware reset + * @hw: pointer to hardware structure + * + * Resets the hardware by resetting the transmit and receive units, masks + * and clears all interrupts, perform a PHY reset, and perform a link (MAC) + * reset. + **/ +s32 ngbe_reset_hw_em(struct ngbe_hw *hw) +{ + s32 status; + + DEBUGFUNC("ngbe_reset_hw_em"); + + /* Call adapter stop to disable tx/rx and clear interrupts */ + status = hw->mac.stop_hw(hw); + if (status != 0) + return status; + + wr32(hw, NGBE_RST, NGBE_RST_LAN(hw->bus.lan_id)); + ngbe_flush(hw); + msec_delay(50); + + ngbe_reset_misc_em(hw); + + msec_delay(50); + + return status; +} + /** * ngbe_set_lan_id_multi_port - Set LAN id for PCIe multiple port devices * @hw: pointer to the HW structure @@ -27,6 +154,57 @@ void ngbe_set_lan_id_multi_port(struct ngbe_hw *hw) bus->func = bus->lan_id; } +/** + * ngbe_stop_hw - Generic stop Tx/Rx units + * @hw: pointer to hardware structure + * + * Sets the adapter_stopped flag within ngbe_hw struct. Clears interrupts, + * disables transmit and receive units. The adapter_stopped flag is used by + * the shared code and drivers to determine if the adapter is in a stopped + * state and should not touch the hardware. + **/ +s32 ngbe_stop_hw(struct ngbe_hw *hw) +{ + u32 reg_val; + u16 i; + + DEBUGFUNC("ngbe_stop_hw"); + + /* + * Set the adapter_stopped flag so other driver functions stop touching + * the hardware + */ + hw->adapter_stopped = true; + + /* Disable the receive unit */ + ngbe_disable_rx(hw); + + /* Clear interrupt mask to stop interrupts from being generated */ + wr32(hw, NGBE_IENMISC, 0); + wr32(hw, NGBE_IMS(0), NGBE_IMS_MASK); + + /* Clear any pending interrupts, flush previous writes */ + wr32(hw, NGBE_ICRMISC, NGBE_ICRMISC_MASK); + wr32(hw, NGBE_ICR(0), NGBE_ICR_MASK); + + /* Disable the transmit unit. Each queue must be disabled. */ + for (i = 0; i < hw->mac.max_tx_queues; i++) + wr32(hw, NGBE_TXCFG(i), NGBE_TXCFG_FLUSH); + + /* Disable the receive unit by stopping each queue */ + for (i = 0; i < hw->mac.max_rx_queues; i++) { + reg_val = rd32(hw, NGBE_RXCFG(i)); + reg_val &= ~NGBE_RXCFG_ENA; + wr32(hw, NGBE_RXCFG(i), reg_val); + } + + /* flush all queues disables */ + ngbe_flush(hw); + msec_delay(2); + + return 0; +} + /** * ngbe_acquire_swfw_sync - Acquire SWFW semaphore * @hw: pointer to hardware structure @@ -98,6 +276,54 @@ void ngbe_release_swfw_sync(struct ngbe_hw *hw, u32 mask) ngbe_release_eeprom_semaphore(hw); } +/** + * ngbe_init_thermal_sensor_thresh - Inits thermal sensor thresholds + * @hw: pointer to hardware structure + * + * Inits the thermal sensor thresholds according to the NVM map + * and save off the threshold and location values into mac.thermal_sensor_data + **/ +s32 ngbe_init_thermal_sensor_thresh(struct ngbe_hw *hw) +{ + struct ngbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data; + + DEBUGFUNC("ngbe_init_thermal_sensor_thresh"); + + memset(data, 0, sizeof(struct ngbe_thermal_sensor_data)); + + if (hw->bus.lan_id != 0) + return NGBE_NOT_IMPLEMENTED; + + wr32(hw, NGBE_TSINTR, + NGBE_TSINTR_AEN | NGBE_TSINTR_DEN); + wr32(hw, NGBE_TSEN, NGBE_TSEN_ENA); + + + data->sensor[0].alarm_thresh = 115; + wr32(hw, NGBE_TSATHRE, 0x344); + data->sensor[0].dalarm_thresh = 110; + wr32(hw, NGBE_TSDTHRE, 0x330); + + return 0; +} + +void ngbe_disable_rx(struct ngbe_hw *hw) +{ + u32 pfdtxgswc; + + pfdtxgswc = rd32(hw, NGBE_PSRCTL); + if (pfdtxgswc & NGBE_PSRCTL_LBENA) { + pfdtxgswc &= ~NGBE_PSRCTL_LBENA; + wr32(hw, NGBE_PSRCTL, pfdtxgswc); + hw->mac.set_lben = true; + } else { + hw->mac.set_lben = false; + } + + wr32m(hw, NGBE_PBRXCTL, NGBE_PBRXCTL_ENA, 0); + wr32m(hw, NGBE_MACRXCFG, NGBE_MACRXCFG_ENA, 0); +} + /** * ngbe_set_mac_type - Sets MAC type * @hw: pointer to the HW structure @@ -216,13 +442,22 @@ s32 ngbe_init_ops_pf(struct ngbe_hw *hw) bus->set_lan_id = ngbe_set_lan_id_multi_port; /* MAC */ + mac->init_hw = ngbe_init_hw; + mac->reset_hw = ngbe_reset_hw_em; + mac->stop_hw = ngbe_stop_hw; mac->acquire_swfw_sync = ngbe_acquire_swfw_sync; mac->release_swfw_sync = ngbe_release_swfw_sync; + /* Manageability interface */ + mac->init_thermal_sensor_thresh = ngbe_init_thermal_sensor_thresh; + /* EEPROM */ rom->init_params = ngbe_init_eeprom_params; rom->validate_checksum = ngbe_validate_eeprom_checksum_em; + mac->max_rx_queues = NGBE_EM_MAX_RX_QUEUES; + mac->max_tx_queues = NGBE_EM_MAX_TX_QUEUES; + return 0; } diff --git a/drivers/net/ngbe/base/ngbe_hw.h b/drivers/net/ngbe/base/ngbe_hw.h index 5e508fb67f..39b2fe696b 100644 --- a/drivers/net/ngbe/base/ngbe_hw.h +++ b/drivers/net/ngbe/base/ngbe_hw.h @@ -8,11 +8,20 @@ #include "ngbe_type.h" +#define NGBE_EM_MAX_TX_QUEUES 8 +#define NGBE_EM_MAX_RX_QUEUES 8 + +s32 ngbe_init_hw(struct ngbe_hw *hw); +s32 ngbe_reset_hw_em(struct ngbe_hw *hw); +s32 ngbe_stop_hw(struct ngbe_hw *hw); + void ngbe_set_lan_id_multi_port(struct ngbe_hw *hw); s32 ngbe_acquire_swfw_sync(struct ngbe_hw *hw, u32 mask); void ngbe_release_swfw_sync(struct ngbe_hw *hw, u32 mask); +s32 ngbe_init_thermal_sensor_thresh(struct ngbe_hw *hw); +void ngbe_disable_rx(struct ngbe_hw *hw); s32 ngbe_init_shared_code(struct ngbe_hw *hw); s32 ngbe_set_mac_type(struct ngbe_hw *hw); s32 ngbe_init_ops_pf(struct ngbe_hw *hw); diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h index 28b15cfb5a..21756c4690 100644 --- a/drivers/net/ngbe/base/ngbe_type.h +++ b/drivers/net/ngbe/base/ngbe_type.h @@ -6,12 +6,24 @@ #ifndef _NGBE_TYPE_H_ #define _NGBE_TYPE_H_ +#define NGBE_FRAME_SIZE_DFT (1522) /* Default frame size, +FCS */ + #define NGBE_ALIGN 128 /* as intel did */ #include "ngbe_status.h" #include "ngbe_osdep.h" #include "ngbe_devids.h" +struct ngbe_thermal_diode_data { + s16 temp; + s16 alarm_thresh; + s16 dalarm_thresh; +}; + +struct ngbe_thermal_sensor_data { + struct ngbe_thermal_diode_data sensor[1]; +}; + enum ngbe_eeprom_type { ngbe_eeprom_unknown = 0, ngbe_eeprom_spi, @@ -73,9 +85,20 @@ struct ngbe_rom_info { }; struct ngbe_mac_info { + s32 (*init_hw)(struct ngbe_hw *hw); + s32 (*reset_hw)(struct ngbe_hw *hw); + s32 (*stop_hw)(struct ngbe_hw *hw); s32 (*acquire_swfw_sync)(struct ngbe_hw *hw, u32 mask); void (*release_swfw_sync)(struct ngbe_hw *hw, u32 mask); + + /* Manageability interface */ + s32 (*init_thermal_sensor_thresh)(struct ngbe_hw *hw); + enum ngbe_mac_type type; + u32 max_tx_queues; + u32 max_rx_queues; + struct ngbe_thermal_sensor_data thermal_sensor_data; + bool set_lben; }; struct ngbe_phy_info { @@ -94,6 +117,7 @@ struct ngbe_hw { u16 vendor_id; u16 sub_device_id; u16 sub_system_id; + bool adapter_stopped; bool allow_unsupported_sfp; uint64_t isb_dma; diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index c2f92a8437..bb5923c485 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -109,6 +109,13 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + err = hw->mac.init_hw(hw); + + if (err) { + PMD_INIT_LOG(ERR, "Hardware Initialization Failure: %d", err); + return -EIO; + } + return 0; } From patchwork Wed Jun 2 09:40:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93772 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 13CBFA0524; Wed, 2 Jun 2021 11:40:57 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id B558941151; Wed, 2 Jun 2021 11:39:53 +0200 (CEST) Received: from smtpbgbr2.qq.com (smtpbgbr2.qq.com [54.207.22.56]) by mails.dpdk.org (Postfix) with ESMTP id B9A4141139 for ; Wed, 2 Jun 2021 11:39:50 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626784tbe2qsyf Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:44 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: g9nl15ZGxliA1H8dgkYoNksH5J5ZiAhTeMlt9GMUq0WVH0KHpr37nbmHY4bja +9P3KJc7G6cORS15CJh0UaQOQhr7uLaagDsBNVTuKXqn2A7w8OBuH/pf1I427MgTZCdaH1d +KiLrcJzi3rrOk/HDI5yqxui1qIS0KDe82QbwtRkngA8SuckrZNwj1z2UAfDJJY1PNQ3sgh GM/X4l+I9K31le7YWh1T998E599sFuiMy2TOT35tI41s5Wmjrz6tj2imaLaosR9R/PcJipb TZMENOegXIiL27+n39GbwQ/5eOaF35XSz5MOsDSFSkyIBkv4oJDtvmlxHUDr2GSWlXqRLUx DOEGmffQG7vOV6go+w= X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:40:54 +0800 Message-Id: <20210602094108.1575640-11-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign6 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 10/24] net/ngbe: identify PHY and reset PHY 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 Sender: "dev" Identify PHY to get the PHY type, and perform a PHY reset. Signed-off-by: Jiawen Wu --- drivers/net/ngbe/base/meson.build | 4 + drivers/net/ngbe/base/ngbe_dummy.h | 40 +++ drivers/net/ngbe/base/ngbe_hw.c | 38 +++ drivers/net/ngbe/base/ngbe_hw.h | 2 + drivers/net/ngbe/base/ngbe_phy.c | 426 +++++++++++++++++++++++++++ drivers/net/ngbe/base/ngbe_phy.h | 60 ++++ drivers/net/ngbe/base/ngbe_phy_mvl.c | 89 ++++++ drivers/net/ngbe/base/ngbe_phy_mvl.h | 92 ++++++ drivers/net/ngbe/base/ngbe_phy_rtl.c | 44 +++ drivers/net/ngbe/base/ngbe_phy_rtl.h | 83 ++++++ drivers/net/ngbe/base/ngbe_phy_yt.c | 112 +++++++ drivers/net/ngbe/base/ngbe_phy_yt.h | 66 +++++ drivers/net/ngbe/base/ngbe_type.h | 17 ++ 13 files changed, 1073 insertions(+) create mode 100644 drivers/net/ngbe/base/ngbe_phy.c create mode 100644 drivers/net/ngbe/base/ngbe_phy.h create mode 100644 drivers/net/ngbe/base/ngbe_phy_mvl.c create mode 100644 drivers/net/ngbe/base/ngbe_phy_mvl.h create mode 100644 drivers/net/ngbe/base/ngbe_phy_rtl.c create mode 100644 drivers/net/ngbe/base/ngbe_phy_rtl.h create mode 100644 drivers/net/ngbe/base/ngbe_phy_yt.c create mode 100644 drivers/net/ngbe/base/ngbe_phy_yt.h diff --git a/drivers/net/ngbe/base/meson.build b/drivers/net/ngbe/base/meson.build index ddd122ec45..146134f671 100644 --- a/drivers/net/ngbe/base/meson.build +++ b/drivers/net/ngbe/base/meson.build @@ -5,6 +5,10 @@ sources = [ 'ngbe_eeprom.c', 'ngbe_hw.c', 'ngbe_mng.c', + 'ngbe_phy.c', + 'ngbe_phy_rtl.c', + 'ngbe_phy_mvl.c', + 'ngbe_phy_yt.c', ] error_cflags = [] diff --git a/drivers/net/ngbe/base/ngbe_dummy.h b/drivers/net/ngbe/base/ngbe_dummy.h index d0081acc2b..15017cfd82 100644 --- a/drivers/net/ngbe/base/ngbe_dummy.h +++ b/drivers/net/ngbe/base/ngbe_dummy.h @@ -64,6 +64,39 @@ static inline s32 ngbe_mac_init_thermal_ssth_dummy(struct ngbe_hw *TUP0) { return NGBE_ERR_OPS_DUMMY; } +static inline s32 ngbe_mac_check_overtemp_dummy(struct ngbe_hw *TUP0) +{ + return NGBE_ERR_OPS_DUMMY; +} +/* struct ngbe_phy_operations */ +static inline s32 ngbe_phy_identify_dummy(struct ngbe_hw *TUP0) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_phy_reset_hw_dummy(struct ngbe_hw *TUP0) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_phy_read_reg_dummy(struct ngbe_hw *TUP0, u32 TUP1, + u32 TUP2, u16 *TUP3) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_phy_write_reg_dummy(struct ngbe_hw *TUP0, u32 TUP1, + u32 TUP2, u16 TUP3) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_phy_read_reg_unlocked_dummy(struct ngbe_hw *TUP0, + u32 TUP1, u32 TUP2, u16 *TUP3) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_phy_write_reg_unlocked_dummy(struct ngbe_hw *TUP0, + u32 TUP1, u32 TUP2, u16 TUP3) +{ + return NGBE_ERR_OPS_DUMMY; +} static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw) { hw->bus.set_lan_id = ngbe_bus_set_lan_id_dummy; @@ -75,6 +108,13 @@ static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw) hw->mac.acquire_swfw_sync = ngbe_mac_acquire_swfw_sync_dummy; hw->mac.release_swfw_sync = ngbe_mac_release_swfw_sync_dummy; hw->mac.init_thermal_sensor_thresh = ngbe_mac_init_thermal_ssth_dummy; + hw->mac.check_overtemp = ngbe_mac_check_overtemp_dummy; + hw->phy.identify = ngbe_phy_identify_dummy; + hw->phy.reset_hw = ngbe_phy_reset_hw_dummy; + hw->phy.read_reg = ngbe_phy_read_reg_dummy; + hw->phy.write_reg = ngbe_phy_write_reg_dummy; + hw->phy.read_reg_unlocked = ngbe_phy_read_reg_unlocked_dummy; + hw->phy.write_reg_unlocked = ngbe_phy_write_reg_unlocked_dummy; } #endif /* _NGBE_TYPE_DUMMY_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c index 9fa40f7de1..ebd163d9e6 100644 --- a/drivers/net/ngbe/base/ngbe_hw.c +++ b/drivers/net/ngbe/base/ngbe_hw.c @@ -4,6 +4,7 @@ */ #include "ngbe_type.h" +#include "ngbe_phy.h" #include "ngbe_eeprom.h" #include "ngbe_mng.h" #include "ngbe_hw.h" @@ -124,6 +125,15 @@ s32 ngbe_reset_hw_em(struct ngbe_hw *hw) if (status != 0) return status; + /* Identify PHY and related function pointers */ + status = ngbe_init_phy(hw); + if (status) + return status; + + /* Reset PHY */ + if (!hw->phy.reset_disable) + hw->phy.reset_hw(hw); + wr32(hw, NGBE_RST, NGBE_RST_LAN(hw->bus.lan_id)); ngbe_flush(hw); msec_delay(50); @@ -307,6 +317,24 @@ s32 ngbe_init_thermal_sensor_thresh(struct ngbe_hw *hw) return 0; } +s32 ngbe_mac_check_overtemp(struct ngbe_hw *hw) +{ + s32 status = 0; + u32 ts_state; + + DEBUGFUNC("ngbe_mac_check_overtemp"); + + /* Check that the LASI temp alarm status was triggered */ + ts_state = rd32(hw, NGBE_TSALM); + + if (ts_state & NGBE_TSALM_HI) + status = NGBE_ERR_UNDERTEMP; + else if (ts_state & NGBE_TSALM_LO) + status = NGBE_ERR_OVERTEMP; + + return status; +} + void ngbe_disable_rx(struct ngbe_hw *hw) { u32 pfdtxgswc; @@ -434,6 +462,7 @@ s32 ngbe_init_ops_pf(struct ngbe_hw *hw) { struct ngbe_bus_info *bus = &hw->bus; struct ngbe_mac_info *mac = &hw->mac; + struct ngbe_phy_info *phy = &hw->phy; struct ngbe_rom_info *rom = &hw->rom; DEBUGFUNC("ngbe_init_ops_pf"); @@ -441,6 +470,14 @@ s32 ngbe_init_ops_pf(struct ngbe_hw *hw) /* BUS */ bus->set_lan_id = ngbe_set_lan_id_multi_port; + /* PHY */ + phy->identify = ngbe_identify_phy; + phy->read_reg = ngbe_read_phy_reg; + phy->write_reg = ngbe_write_phy_reg; + phy->read_reg_unlocked = ngbe_read_phy_reg_mdi; + phy->write_reg_unlocked = ngbe_write_phy_reg_mdi; + phy->reset_hw = ngbe_reset_phy; + /* MAC */ mac->init_hw = ngbe_init_hw; mac->reset_hw = ngbe_reset_hw_em; @@ -450,6 +487,7 @@ s32 ngbe_init_ops_pf(struct ngbe_hw *hw) /* Manageability interface */ mac->init_thermal_sensor_thresh = ngbe_init_thermal_sensor_thresh; + mac->check_overtemp = ngbe_mac_check_overtemp; /* EEPROM */ rom->init_params = ngbe_init_eeprom_params; diff --git a/drivers/net/ngbe/base/ngbe_hw.h b/drivers/net/ngbe/base/ngbe_hw.h index 39b2fe696b..3c8e646bb7 100644 --- a/drivers/net/ngbe/base/ngbe_hw.h +++ b/drivers/net/ngbe/base/ngbe_hw.h @@ -21,10 +21,12 @@ s32 ngbe_acquire_swfw_sync(struct ngbe_hw *hw, u32 mask); void ngbe_release_swfw_sync(struct ngbe_hw *hw, u32 mask); s32 ngbe_init_thermal_sensor_thresh(struct ngbe_hw *hw); +s32 ngbe_mac_check_overtemp(struct ngbe_hw *hw); void ngbe_disable_rx(struct ngbe_hw *hw); s32 ngbe_init_shared_code(struct ngbe_hw *hw); s32 ngbe_set_mac_type(struct ngbe_hw *hw); s32 ngbe_init_ops_pf(struct ngbe_hw *hw); +s32 ngbe_init_phy(struct ngbe_hw *hw); void ngbe_map_device_id(struct ngbe_hw *hw); #endif /* _NGBE_HW_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_phy.c b/drivers/net/ngbe/base/ngbe_phy.c new file mode 100644 index 0000000000..d1b4cc9e5f --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_phy.c @@ -0,0 +1,426 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#include "ngbe_hw.h" +#include "ngbe_phy.h" + +s32 ngbe_mdi_map_register(mdi_reg_t *reg, mdi_reg_22_t *reg22) +{ + bool match = 1; + switch (reg->device_type) { + case NGBE_MD_DEV_PMA_PMD: + switch (reg->addr) { + case NGBE_MD_PHY_ID_HIGH: + case NGBE_MD_PHY_ID_LOW: + reg22->page = 0; + reg22->addr = reg->addr; + reg22->device_type = 0; + break; + default: + match = 0; + } + break; + default: + match = 0; + break; + } + + if (!match) { + reg22->page = reg->device_type; + reg22->device_type = reg->device_type; + reg22->addr = reg->addr; + } + + return 0; +} + +/** + * ngbe_probe_phy - Identify a single address for a PHY + * @hw: pointer to hardware structure + * @phy_addr: PHY address to probe + * + * Returns true if PHY found + */ +static bool ngbe_probe_phy(struct ngbe_hw *hw, u16 phy_addr) +{ + if (!ngbe_validate_phy_addr(hw, phy_addr)) { + DEBUGOUT("Unable to validate PHY address 0x%04X\n", + phy_addr); + return false; + } + + if (ngbe_get_phy_id(hw)) + return false; + + hw->phy.type = ngbe_get_phy_type_from_id(hw); + if (hw->phy.type == ngbe_phy_unknown) + return false; + + return true; +} + +/** + * ngbe_identify_phy - Get physical layer module + * @hw: pointer to hardware structure + * + * Determines the physical layer module found on the current adapter. + **/ +s32 ngbe_identify_phy(struct ngbe_hw *hw) +{ + s32 err = NGBE_ERR_PHY_ADDR_INVALID; + u16 phy_addr; + + DEBUGFUNC("ngbe_identify_phy"); + + if (hw->phy.type != ngbe_phy_unknown) + return 0; + + /* select claus22 */ + wr32(hw, NGBE_MDIOMODE, NGBE_MDIOMODE_MASK); + + for (phy_addr = 0; phy_addr < NGBE_MAX_PHY_ADDR; phy_addr++) { + if (ngbe_probe_phy(hw, phy_addr)) { + err = 0; + break; + } + } + + return err; +} + +/** + * ngbe_check_reset_blocked - check status of MNG FW veto bit + * @hw: pointer to the hardware structure + * + * This function checks the STAT.MNGVETO bit to see if there are + * any constraints on link from manageability. For MAC's that don't + * have this bit just return faluse since the link can not be blocked + * via this method. + **/ +s32 ngbe_check_reset_blocked(struct ngbe_hw *hw) +{ + u32 mmngc; + + DEBUGFUNC("ngbe_check_reset_blocked"); + + mmngc = rd32(hw, NGBE_STAT); + if (mmngc & NGBE_STAT_MNGVETO) { + DEBUGOUT("MNG_VETO bit detected.\n"); + return true; + } + + return false; +} + +/** + * ngbe_validate_phy_addr - Determines phy address is valid + * @hw: pointer to hardware structure + * @phy_addr: PHY address + * + **/ +bool ngbe_validate_phy_addr(struct ngbe_hw *hw, u32 phy_addr) +{ + u16 phy_id = 0; + bool valid = false; + + DEBUGFUNC("ngbe_validate_phy_addr"); + + if (hw->sub_device_id == NGBE_SUB_DEV_ID_EM_YT8521S_SFP) + return true; + + hw->phy.addr = phy_addr; + hw->phy.read_reg(hw, NGBE_MD_PHY_ID_HIGH, + NGBE_MD_DEV_PMA_PMD, &phy_id); + + if (phy_id != 0xFFFF && phy_id != 0x0) + valid = true; + + DEBUGOUT("PHY ID HIGH is 0x%04X\n", phy_id); + + return valid; +} + +/** + * ngbe_get_phy_id - Get the phy ID + * @hw: pointer to hardware structure + * + **/ +s32 ngbe_get_phy_id(struct ngbe_hw *hw) +{ + u32 err; + u16 phy_id_high = 0; + u16 phy_id_low = 0; + + DEBUGFUNC("ngbe_get_phy_id"); + + err = hw->phy.read_reg(hw, NGBE_MD_PHY_ID_HIGH, + NGBE_MD_DEV_PMA_PMD, + &phy_id_high); + hw->phy.id = (u32)(phy_id_high << 16); + + err = hw->phy.read_reg(hw, NGBE_MD_PHY_ID_LOW, + NGBE_MD_DEV_PMA_PMD, + &phy_id_low); + hw->phy.id |= (u32)(phy_id_low & NGBE_PHY_REVISION_MASK); + hw->phy.revision = (u32)(phy_id_low & ~NGBE_PHY_REVISION_MASK); + + DEBUGOUT("PHY_ID_HIGH 0x%04X, PHY_ID_LOW 0x%04X\n", + phy_id_high, phy_id_low); + + return err; +} + +/** + * ngbe_get_phy_type_from_id - Get the phy type + * @phy_id: PHY ID information + * + **/ +enum ngbe_phy_type ngbe_get_phy_type_from_id(struct ngbe_hw *hw) +{ + enum ngbe_phy_type phy_type; + + DEBUGFUNC("ngbe_get_phy_type_from_id"); + + switch (hw->phy.id) { + case NGBE_PHYID_RTL: + phy_type = ngbe_phy_rtl; + break; + case NGBE_PHYID_MVL: + if (hw->phy.media_type == ngbe_media_type_fiber) + phy_type = ngbe_phy_mvl_sfi; + else + phy_type = ngbe_phy_mvl; + break; + case NGBE_PHYID_YT: + if (hw->phy.media_type == ngbe_media_type_fiber) + phy_type = ngbe_phy_yt8521s_sfi; + else + phy_type = ngbe_phy_yt8521s; + break; + default: + phy_type = ngbe_phy_unknown; + break; + } + + return phy_type; +} + +/** + * ngbe_reset_phy - Performs a PHY reset + * @hw: pointer to hardware structure + **/ +s32 ngbe_reset_phy(struct ngbe_hw *hw) +{ + s32 err = 0; + + DEBUGFUNC("ngbe_reset_phy"); + + if (hw->phy.type == ngbe_phy_unknown) + err = ngbe_identify_phy(hw); + + if (err != 0 || hw->phy.type == ngbe_phy_none) + return err; + + /* Don't reset PHY if it's shut down due to overtemp. */ + if (hw->mac.check_overtemp(hw) == NGBE_ERR_OVERTEMP) + return err; + + /* Blocked by MNG FW so bail */ + if (ngbe_check_reset_blocked(hw)) + return err; + + switch (hw->phy.type) { + case ngbe_phy_rtl: + err = ngbe_reset_phy_rtl(hw); + break; + case ngbe_phy_mvl: + case ngbe_phy_mvl_sfi: + err = ngbe_reset_phy_mvl(hw); + break; + case ngbe_phy_yt8521s: + case ngbe_phy_yt8521s_sfi: + err = ngbe_reset_phy_yt(hw); + break; + default: + break; + } + + return err; +} + +/** + * ngbe_read_phy_mdi - Reads a value from a specified PHY register without + * the SWFW lock + * @hw: pointer to hardware structure + * @reg_addr: 32 bit address of PHY register to read + * @device_type: 5 bit device type + * @phy_data: Pointer to read data from PHY register + **/ +s32 ngbe_read_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, + u16 *phy_data) +{ + u32 command, data; + + /* Setup and write the address cycle command */ + command = NGBE_MDIOSCA_REG(reg_addr) | + NGBE_MDIOSCA_DEV(device_type) | + NGBE_MDIOSCA_PORT(hw->phy.addr); + wr32(hw, NGBE_MDIOSCA, command); + + command = NGBE_MDIOSCD_CMD_READ | + NGBE_MDIOSCD_BUSY | + NGBE_MDIOSCD_CLOCK(6); + wr32(hw, NGBE_MDIOSCD, command); + + /* + * Check every 10 usec to see if the address cycle completed. + * The MDI Command bit will clear when the operation is + * complete + */ + if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY, + 0, NULL, 100, 100)) { + DEBUGOUT("PHY address command did not complete\n"); + return NGBE_ERR_PHY; + } + + data = rd32(hw, NGBE_MDIOSCD); + *phy_data = (u16)NGBE_MDIOSCD_DAT_R(data); + + return 0; +} + +/** + * ngbe_read_phy_reg - Reads a value from a specified PHY register + * using the SWFW lock - this function is needed in most cases + * @hw: pointer to hardware structure + * @reg_addr: 32 bit address of PHY register to read + * @device_type: 5 bit device type + * @phy_data: Pointer to read data from PHY register + **/ +s32 ngbe_read_phy_reg(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 *phy_data) +{ + s32 err; + u32 gssr = hw->phy.phy_semaphore_mask; + + DEBUGFUNC("ngbe_read_phy_reg"); + + if (hw->mac.acquire_swfw_sync(hw, gssr)) + return NGBE_ERR_SWFW_SYNC; + + err = hw->phy.read_reg_unlocked(hw, reg_addr, device_type, + phy_data); + + hw->mac.release_swfw_sync(hw, gssr); + + return err; +} + +/** + * ngbe_write_phy_reg_mdi - Writes a value to specified PHY register + * without SWFW lock + * @hw: pointer to hardware structure + * @reg_addr: 32 bit PHY register to write + * @device_type: 5 bit device type + * @phy_data: Data to write to the PHY register + **/ +s32 ngbe_write_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 phy_data) +{ + u32 command; + + /* write command */ + command = NGBE_MDIOSCA_REG(reg_addr) | + NGBE_MDIOSCA_DEV(device_type) | + NGBE_MDIOSCA_PORT(hw->phy.addr); + wr32(hw, NGBE_MDIOSCA, command); + + command = NGBE_MDIOSCD_CMD_WRITE | + NGBE_MDIOSCD_DAT(phy_data) | + NGBE_MDIOSCD_BUSY | + NGBE_MDIOSCD_CLOCK(6); + wr32(hw, NGBE_MDIOSCD, command); + + /* wait for completion */ + if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY, + 0, NULL, 100, 100)) { + TLOG_DEBUG("PHY write cmd didn't complete\n"); + return -TERR_PHY; + } + + return 0; +} + +/** + * ngbe_write_phy_reg - Writes a value to specified PHY register + * using SWFW lock- this function is needed in most cases + * @hw: pointer to hardware structure + * @reg_addr: 32 bit PHY register to write + * @device_type: 5 bit device type + * @phy_data: Data to write to the PHY register + **/ +s32 ngbe_write_phy_reg(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 phy_data) +{ + s32 err; + u32 gssr = hw->phy.phy_semaphore_mask; + + DEBUGFUNC("ngbe_write_phy_reg"); + + if (hw->mac.acquire_swfw_sync(hw, gssr)) + err = NGBE_ERR_SWFW_SYNC; + + err = hw->phy.write_reg_unlocked(hw, reg_addr, device_type, + phy_data); + + hw->mac.release_swfw_sync(hw, gssr); + + return err; +} + +/** + * ngbe_init_phy - PHY specific init + * @hw: pointer to hardware structure + * + * Initialize any function pointers that were not able to be + * set during init_shared_code because the PHY type was + * not known. + * + **/ +s32 ngbe_init_phy(struct ngbe_hw *hw) +{ + struct ngbe_phy_info *phy = &hw->phy; + s32 err = 0; + + DEBUGFUNC("ngbe_init_phy"); + + hw->phy.addr = 0; + + switch (hw->sub_device_id) { + case NGBE_SUB_DEV_ID_EM_RTL_SGMII: + hw->phy.read_reg_unlocked = ngbe_read_phy_reg_rtl; + hw->phy.write_reg_unlocked = ngbe_write_phy_reg_rtl; + break; + case NGBE_SUB_DEV_ID_EM_MVL_RGMII: + case NGBE_SUB_DEV_ID_EM_MVL_SFP: + hw->phy.read_reg_unlocked = ngbe_read_phy_reg_mvl; + hw->phy.write_reg_unlocked = ngbe_write_phy_reg_mvl; + break; + case NGBE_SUB_DEV_ID_EM_YT8521S_SFP: + hw->phy.read_reg_unlocked = ngbe_read_phy_reg_yt; + hw->phy.write_reg_unlocked = ngbe_write_phy_reg_yt; + break; + default: + break; + } + + hw->phy.phy_semaphore_mask = NGBE_MNGSEM_SWPHY; + + /* Identify the PHY */ + err = phy->identify(hw); + + return err; +} + diff --git a/drivers/net/ngbe/base/ngbe_phy.h b/drivers/net/ngbe/base/ngbe_phy.h new file mode 100644 index 0000000000..59d9efe025 --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_phy.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#ifndef _NGBE_PHY_H_ +#define _NGBE_PHY_H_ + +#include "ngbe_type.h" +#include "ngbe_phy_rtl.h" +#include "ngbe_phy_mvl.h" +#include "ngbe_phy_yt.h" + +/****************************************************************************** + * PHY MDIO Registers: + ******************************************************************************/ +#define NGBE_MAX_PHY_ADDR 32 + +/* (dev_type = 1) */ +#define NGBE_MD_DEV_PMA_PMD 0x1 +#define NGBE_MD_PHY_ID_HIGH 0x2 /* PHY ID High Reg*/ +#define NGBE_MD_PHY_ID_LOW 0x3 /* PHY ID Low Reg*/ +#define NGBE_PHY_REVISION_MASK 0xFFFFFFF0 + +/* IEEE 802.3 Clause 22 */ +struct mdi_reg_22 { + u16 page; + u16 addr; + u16 device_type; +}; +typedef struct mdi_reg_22 mdi_reg_22_t; + +/* IEEE 802.3ae Clause 45 */ +struct mdi_reg { + u16 device_type; + u16 addr; +}; +typedef struct mdi_reg mdi_reg_t; + +#define NGBE_MD22_PHY_ID_HIGH 0x2 /* PHY ID High Reg*/ +#define NGBE_MD22_PHY_ID_LOW 0x3 /* PHY ID Low Reg*/ + +s32 ngbe_mdi_map_register(mdi_reg_t *reg, mdi_reg_22_t *reg22); + +bool ngbe_validate_phy_addr(struct ngbe_hw *hw, u32 phy_addr); +enum ngbe_phy_type ngbe_get_phy_type_from_id(struct ngbe_hw *hw); +s32 ngbe_get_phy_id(struct ngbe_hw *hw); +s32 ngbe_identify_phy(struct ngbe_hw *hw); +s32 ngbe_reset_phy(struct ngbe_hw *hw); +s32 ngbe_read_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, + u16 *phy_data); +s32 ngbe_write_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, + u16 phy_data); +s32 ngbe_read_phy_reg(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 *phy_data); +s32 ngbe_write_phy_reg(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 phy_data); +s32 ngbe_check_reset_blocked(struct ngbe_hw *hw); + +#endif /* _NGBE_PHY_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_phy_mvl.c b/drivers/net/ngbe/base/ngbe_phy_mvl.c new file mode 100644 index 0000000000..40419a61f6 --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_phy_mvl.c @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + */ + +#include "ngbe_phy_mvl.h" + +#define MVL_PHY_RST_WAIT_PERIOD 5 + +s32 ngbe_read_phy_reg_mvl(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 *phy_data) +{ + mdi_reg_t reg; + mdi_reg_22_t reg22; + + reg.device_type = device_type; + reg.addr = reg_addr; + + if (hw->phy.media_type == ngbe_media_type_fiber) + ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 1); + else + ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 0); + + ngbe_mdi_map_register(®, ®22); + + ngbe_read_phy_reg_mdi(hw, reg22.addr, reg22.device_type, phy_data); + + return 0; +} + +s32 ngbe_write_phy_reg_mvl(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 phy_data) +{ + mdi_reg_t reg; + mdi_reg_22_t reg22; + + reg.device_type = device_type; + reg.addr = reg_addr; + + if (hw->phy.media_type == ngbe_media_type_fiber) + ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 1); + else + ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 0); + + ngbe_mdi_map_register(®, ®22); + + ngbe_write_phy_reg_mdi(hw, reg22.addr, reg22.device_type, phy_data); + + return 0; +} + +s32 ngbe_reset_phy_mvl(struct ngbe_hw *hw) +{ + u32 i; + u16 ctrl = 0; + s32 status = 0; + + DEBUGFUNC("ngbe_reset_phy_mvl"); + + if (hw->phy.type != ngbe_phy_mvl && hw->phy.type != ngbe_phy_mvl_sfi) + return NGBE_ERR_PHY_TYPE; + + /* select page 18 reg 20 */ + status = ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 18); + + /* mode select to RGMII-to-copper or RGMII-to-sfi*/ + if (hw->phy.type == ngbe_phy_mvl) + ctrl = MVL_GEN_CTL_MODE_COPPER; + else + ctrl = MVL_GEN_CTL_MODE_FIBER; + status = ngbe_write_phy_reg_mdi(hw, MVL_GEN_CTL, 0, ctrl); + /* mode reset */ + ctrl |= MVL_GEN_CTL_RESET; + status = ngbe_write_phy_reg_mdi(hw, MVL_GEN_CTL, 0, ctrl); + + for (i = 0; i < MVL_PHY_RST_WAIT_PERIOD; i++) { + status = ngbe_read_phy_reg_mdi(hw, MVL_GEN_CTL, 0, &ctrl); + if (!(ctrl & MVL_GEN_CTL_RESET)) + break; + msleep(1); + } + + if (i == MVL_PHY_RST_WAIT_PERIOD) { + DEBUGOUT("PHY reset polling failed to complete.\n"); + return NGBE_ERR_RESET_FAILED; + } + + return status; +} + diff --git a/drivers/net/ngbe/base/ngbe_phy_mvl.h b/drivers/net/ngbe/base/ngbe_phy_mvl.h new file mode 100644 index 0000000000..a88ace9ec1 --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_phy_mvl.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + */ + +#include "ngbe_phy.h" + +#ifndef _NGBE_PHY_MVL_H_ +#define _NGBE_PHY_MVL_H_ + +#define NGBE_PHYID_MVL 0x01410DD0U + +/* Page 0 for Copper, Page 1 for Fiber */ +#define MVL_CTRL 0x0 +#define MVL_CTRL_RESET MS16(15, 0x1) +#define MVL_CTRL_ANE MS16(12, 0x1) +#define MVL_CTRL_RESTART_AN MS16(9, 0x1) +#define MVL_ANA 0x4 +/* copper */ +#define MVL_CANA_ASM_PAUSE MS16(11, 0x1) +#define MVL_CANA_PAUSE MS16(10, 0x1) +#define MVL_PHY_100BASET_FULL MS16(8, 0x1) +#define MVL_PHY_100BASET_HALF MS16(7, 0x1) +#define MVL_PHY_10BASET_FULL MS16(6, 0x1) +#define MVL_PHY_10BASET_HALF MS16(5, 0x1) +/* fiber */ +#define MVL_FANA_PAUSE_MASK MS16(7, 0x3) +#define MVL_FANA_SYM_PAUSE LS16(1, 7, 0x3) +#define MVL_FANA_ASM_PAUSE LS16(2, 7, 0x3) +#define MVL_PHY_1000BASEX_HALF MS16(6, 0x1) +#define MVL_PHY_1000BASEX_FULL MS16(5, 0x1) +#define MVL_LPAR 0x5 +#define MVL_CLPAR_ASM_PAUSE MS(11, 0x1) +#define MVL_CLPAR_PAUSE MS(10, 0x1) +#define MVL_FLPAR_PAUSE_MASK MS(7, 0x3) +#define MVL_PHY_1000BASET 0x9 +#define MVL_PHY_1000BASET_FULL MS16(9, 0x1) +#define MVL_PHY_1000BASET_HALF MS16(8, 0x1) +#define MVL_CTRL1 0x10 +#define MVL_CTRL1_INTR_POL MS16(2, 0x1) +#define MVL_PHYSR 0x11 +#define MVL_PHYSR_SPEED_MASK MS16(14, 0x3) +#define MVL_PHYSR_SPEED_1000M LS16(2, 14, 0x3) +#define MVL_PHYSR_SPEED_100M LS16(1, 14, 0x3) +#define MVL_PHYSR_SPEED_10M LS16(0, 14, 0x3) +#define MVL_PHYSR_LINK MS16(10, 0x1) +#define MVL_INTR_EN 0x12 +#define MVL_INTR_EN_ANC MS16(11, 0x1) +#define MVL_INTR_EN_LSC MS16(10, 0x1) +#define MVL_INTR 0x13 +#define MVL_INTR_ANC MS16(11, 0x1) +#define MVL_INTR_LSC MS16(10, 0x1) + +/* Page 2 */ +#define MVL_RGM_CTL2 0x15 +#define MVL_RGM_CTL2_TTC MS16(4, 0x1) +#define MVL_RGM_CTL2_RTC MS16(5, 0x1) +/* Page 3 */ +#define MVL_LEDFCR 0x10 +#define MVL_LEDFCR_CTL1 MS16(4, 0xF) +#define MVL_LEDFCR_CTL1_CONF LS16(6, 4, 0xF) +#define MVL_LEDFCR_CTL0 MS16(0, 0xF) +#define MVL_LEDFCR_CTL0_CONF LS16(1, 0, 0xF) +#define MVL_LEDPCR 0x11 +#define MVL_LEDPCR_CTL1 MS16(2, 0x3) +#define MVL_LEDPCR_CTL1_CONF LS16(1, 2, 0x3) +#define MVL_LEDPCR_CTL0 MS16(0, 0x3) +#define MVL_LEDPCR_CTL0_CONF LS16(1, 0, 0x3) +#define MVL_LEDTCR 0x12 +#define MVL_LEDTCR_INTR_POL MS16(11, 0x1) +#define MVL_LEDTCR_INTR_EN MS16(7, 0x1) +/* Page 18 */ +#define MVL_GEN_CTL 0x14 +#define MVL_GEN_CTL_RESET MS16(15, 0x1) +#define MVL_GEN_CTL_MODE(v) LS16(v, 0, 0x7) +#define MVL_GEN_CTL_MODE_COPPER LS16(0, 0, 0x7) +#define MVL_GEN_CTL_MODE_FIBER LS16(2, 0, 0x7) + +/* reg 22 */ +#define MVL_PAGE_SEL 22 + +/* reg 19_0 INT status*/ +#define MVL_PHY_ANC 0x0800 +#define MVL_PHY_LSC 0x0400 + +s32 ngbe_read_phy_reg_mvl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, + u16 *phy_data); +s32 ngbe_write_phy_reg_mvl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, + u16 phy_data); + +s32 ngbe_reset_phy_mvl(struct ngbe_hw *hw); + +#endif /* _NGBE_PHY_MVL_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_phy_rtl.c b/drivers/net/ngbe/base/ngbe_phy_rtl.c new file mode 100644 index 0000000000..9c98a8ecaf --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_phy_rtl.c @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + */ + +#include "ngbe_phy_rtl.h" + +s32 ngbe_read_phy_reg_rtl(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 *phy_data) +{ + mdi_reg_t reg; + mdi_reg_22_t reg22; + + reg.device_type = device_type; + reg.addr = reg_addr; + ngbe_mdi_map_register(®, ®22); + + wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page); + *phy_data = 0xFFFF & rd32(hw, NGBE_PHY_CONFIG(reg22.addr)); + + return 0; +} + +s32 ngbe_write_phy_reg_rtl(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 phy_data) +{ + mdi_reg_t reg; + mdi_reg_22_t reg22; + + reg.device_type = device_type; + reg.addr = reg_addr; + ngbe_mdi_map_register(®, ®22); + + wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page); + wr32(hw, NGBE_PHY_CONFIG(reg22.addr), phy_data); + + return 0; +} + +s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw) +{ + UNREFERENCED_PARAMETER(hw); + return 0; +} + diff --git a/drivers/net/ngbe/base/ngbe_phy_rtl.h b/drivers/net/ngbe/base/ngbe_phy_rtl.h new file mode 100644 index 0000000000..ecb60b0ddd --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_phy_rtl.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + */ + +#include "ngbe_phy.h" + +#ifndef _NGBE_PHY_RTL_H_ +#define _NGBE_PHY_RTL_H_ + +#define NGBE_PHYID_RTL 0x001CC800U + +/* Page 0 */ +#define RTL_DEV_ZERO 0 +#define RTL_BMCR 0x0 +#define RTL_BMCR_RESET MS16(15, 0x1) +#define RTL_BMCR_SPEED_SELECT0 MS16(13, 0x1) +#define RTL_BMCR_ANE MS16(12, 0x1) +#define RTL_BMCR_RESTART_AN MS16(9, 0x1) +#define RTL_BMCR_DUPLEX MS16(8, 0x1) +#define RTL_BMCR_SPEED_SELECT1 MS16(6, 0x1) +#define RTL_BMSR 0x1 +#define RTL_BMSR_ANC MS16(5, 0x1) +#define RTL_ID1_OFFSET 0x2 +#define RTL_ID2_OFFSET 0x3 +#define RTL_ID_MASK 0xFFFFFC00U +#define RTL_ANAR 0x4 +#define RTL_ANAR_APAUSE MS16(11, 0x1) +#define RTL_ANAR_PAUSE MS16(10, 0x1) +#define RTL_ANAR_100F MS16(8, 0x1) +#define RTL_ANAR_100H MS16(7, 0x1) +#define RTL_ANAR_10F MS16(6, 0x1) +#define RTL_ANAR_10H MS16(5, 0x1) +#define RTL_ANLPAR 0x5 +#define RTL_ANLPAR_LP MS16(10, 0x3) +#define RTL_GBCR 0x9 +#define RTL_GBCR_1000F MS16(9, 0x1) +/* Page 0xa42*/ +#define RTL_GSR 0x10 +#define RTL_GSR_ST MS16(0, 0x7) +#define RTL_GSR_ST_LANON MS16(0, 0x3) +#define RTL_INER 0x12 +#define RTL_INER_LSC MS16(4, 0x1) +#define RTL_INER_ANC MS16(3, 0x1) +/* Page 0xa43*/ +#define RTL_PHYSR 0x1A +#define RTL_PHYSR_SPEED_MASK MS16(4, 0x3) +#define RTL_PHYSR_SPEED_RES LS16(3, 4, 0x3) +#define RTL_PHYSR_SPEED_1000M LS16(2, 4, 0x3) +#define RTL_PHYSR_SPEED_100M LS16(1, 4, 0x3) +#define RTL_PHYSR_SPEED_10M LS16(0, 4, 0x3) +#define RTL_PHYSR_DP MS16(3, 0x1) +#define RTL_PHYSR_RTLS MS16(2, 0x1) +#define RTL_INSR 0x1D +#define RTL_INSR_ACCESS MS16(5, 0x1) +#define RTL_INSR_LSC MS16(4, 0x1) +#define RTL_INSR_ANC MS16(3, 0x1) +/* Page 0xa46*/ +#define RTL_SCR 0x14 +#define RTL_SCR_EXTINI MS16(1, 0x1) +#define RTL_SCR_EFUSE MS16(0, 0x1) +/* Page 0xa47*/ +/* Page 0xd04*/ +#define RTL_LCR 0x10 +#define RTL_EEELCR 0x11 +#define RTL_LPCR 0x12 + +/* INTERNAL PHY CONTROL */ +#define RTL_PAGE_SELECT 31 +#define NGBE_INTERNAL_PHY_OFFSET_MAX 32 +#define NGBE_INTERNAL_PHY_ID 0x000732 + +#define NGBE_INTPHY_LED0 0x0010 +#define NGBE_INTPHY_LED1 0x0040 +#define NGBE_INTPHY_LED2 0x2000 + +s32 ngbe_read_phy_reg_rtl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, + u16 *phy_data); +s32 ngbe_write_phy_reg_rtl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, + u16 phy_data); + +s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw); + +#endif /* _NGBE_PHY_RTL_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.c b/drivers/net/ngbe/base/ngbe_phy_yt.c new file mode 100644 index 0000000000..84b20de45c --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_phy_yt.c @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + */ + +#include "ngbe_phy_yt.h" + +#define YT_PHY_RST_WAIT_PERIOD 5 + +s32 ngbe_read_phy_reg_yt(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 *phy_data) +{ + mdi_reg_t reg; + mdi_reg_22_t reg22; + + reg.device_type = device_type; + reg.addr = reg_addr; + + ngbe_mdi_map_register(®, ®22); + + /* Read MII reg according to media type */ + if (hw->phy.media_type == ngbe_media_type_fiber) { + ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, + reg22.device_type, YT_SMI_PHY_SDS); + ngbe_read_phy_reg_mdi(hw, reg22.addr, + reg22.device_type, phy_data); + ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, + reg22.device_type, 0); + } else { + ngbe_read_phy_reg_mdi(hw, reg22.addr, + reg22.device_type, phy_data); + } + + return 0; +} + +s32 ngbe_write_phy_reg_yt(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 phy_data) +{ + mdi_reg_t reg; + mdi_reg_22_t reg22; + + reg.device_type = device_type; + reg.addr = reg_addr; + + ngbe_mdi_map_register(®, ®22); + + /* Write MII reg according to media type */ + if (hw->phy.media_type == ngbe_media_type_fiber) { + ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, + reg22.device_type, YT_SMI_PHY_SDS); + ngbe_write_phy_reg_mdi(hw, reg22.addr, + reg22.device_type, phy_data); + ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, + reg22.device_type, 0); + } else { + ngbe_write_phy_reg_mdi(hw, reg22.addr, + reg22.device_type, phy_data); + } + + return 0; +} + +s32 ngbe_read_phy_reg_ext_yt(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 *phy_data) +{ + ngbe_write_phy_reg_mdi(hw, 0x1E, device_type, reg_addr); + ngbe_read_phy_reg_mdi(hw, 0x1F, device_type, phy_data); + + return 0; +} + +s32 ngbe_write_phy_reg_ext_yt(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 phy_data) +{ + ngbe_write_phy_reg_mdi(hw, 0x1E, device_type, reg_addr); + ngbe_write_phy_reg_mdi(hw, 0x1F, device_type, phy_data); + + return 0; +} + +s32 ngbe_reset_phy_yt(struct ngbe_hw *hw) +{ + u32 i; + u16 ctrl = 0; + s32 status = 0; + + DEBUGFUNC("ngbe_reset_phy_yt"); + + if (hw->phy.type != ngbe_phy_yt8521s && + hw->phy.type != ngbe_phy_yt8521s_sfi) + return NGBE_ERR_PHY_TYPE; + + status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl); + /* sds software reset */ + ctrl |= YT_BCR_RESET; + status = hw->phy.write_reg(hw, YT_BCR, 0, ctrl); + + for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) { + status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl); + if (!(ctrl & YT_BCR_RESET)) + break; + msleep(1); + } + + if (i == YT_PHY_RST_WAIT_PERIOD) { + DEBUGOUT("PHY reset polling failed to complete.\n"); + return NGBE_ERR_RESET_FAILED; + } + + return status; +} + diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.h b/drivers/net/ngbe/base/ngbe_phy_yt.h new file mode 100644 index 0000000000..03b53ece86 --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_phy_yt.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + */ + +#include "ngbe_phy.h" + +#ifndef _NGBE_PHY_YT_H_ +#define _NGBE_PHY_YT_H_ + +#define NGBE_PHYID_YT 0x00000110U + +/* Common EXT */ +#define YT_SMI_PHY 0xA000 +#define YT_SMI_PHY_SDS MS16(1, 0x1) /* 0 for UTP */ +#define YT_CHIP 0xA001 +#define YT_CHIP_SW_RST MS16(15, 0x1) +#define YT_CHIP_SW_LDO_EN MS16(6, 0x1) +#define YT_CHIP_MODE_SEL(v) LS16(v, 0, 0x7) +#define YT_RGMII_CONF1 0xA003 +#define YT_RGMII_CONF1_RXDELAY MS16(10, 0xF) +#define YT_RGMII_CONF1_TXDELAY_FE MS16(4, 0xF) +#define YT_RGMII_CONF1_TXDELAY MS16(0, 0x1) +#define YT_MISC 0xA006 +#define YT_MISC_FIBER_PRIO MS16(8, 0x1) /* 0 for UTP */ + +/* MII common registers in UTP and SDS */ +#define YT_BCR 0x0 +#define YT_BCR_RESET MS16(15, 0x1) +#define YT_ANA 0x4 +/* copper */ +#define YT_ANA_100BASET_FULL MS16(8, 0x1) +#define YT_ANA_10BASET_FULL MS16(6, 0x1) +/* fiber */ +#define YT_FANA_PAUSE_MASK MS16(7, 0x3) + +#define YT_LPAR 0x5 +#define YT_CLPAR_ASM_PAUSE MS(11, 0x1) +#define YT_CLPAR_PAUSE MS(10, 0x1) +#define YT_FLPAR_PAUSE_MASK MS(7, 0x3) + +#define YT_MS_CTRL 0x9 +#define YT_MS_1000BASET_FULL MS16(9, 0x1) +#define YT_SPST 0x11 +#define YT_SPST_SPEED_MASK MS16(14, 0x3) +#define YT_SPST_SPEED_1000M LS16(2, 14, 0x3) +#define YT_SPST_SPEED_100M LS16(1, 14, 0x3) +#define YT_SPST_SPEED_10M LS16(0, 14, 0x3) +#define YT_SPST_LINK MS16(10, 0x1) + +/* UTP only */ +#define YT_INTR 0x12 +#define YT_INTR_ENA_MASK MS16(2, 0x3) +#define YT_INTR_STATUS 0x13 + +s32 ngbe_read_phy_reg_yt(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, + u16 *phy_data); +s32 ngbe_write_phy_reg_yt(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, + u16 phy_data); +s32 ngbe_read_phy_reg_ext_yt(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 *phy_data); +s32 ngbe_write_phy_reg_ext_yt(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 phy_data); + +s32 ngbe_reset_phy_yt(struct ngbe_hw *hw); + +#endif /* _NGBE_PHY_YT_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h index 21756c4690..b5c05e0f2f 100644 --- a/drivers/net/ngbe/base/ngbe_type.h +++ b/drivers/net/ngbe/base/ngbe_type.h @@ -93,6 +93,7 @@ struct ngbe_mac_info { /* Manageability interface */ s32 (*init_thermal_sensor_thresh)(struct ngbe_hw *hw); + s32 (*check_overtemp)(struct ngbe_hw *hw); enum ngbe_mac_type type; u32 max_tx_queues; @@ -102,8 +103,24 @@ struct ngbe_mac_info { }; struct ngbe_phy_info { + s32 (*identify)(struct ngbe_hw *hw); + s32 (*reset_hw)(struct ngbe_hw *hw); + s32 (*read_reg)(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 *phy_data); + s32 (*write_reg)(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 phy_data); + s32 (*read_reg_unlocked)(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 *phy_data); + s32 (*write_reg_unlocked)(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 phy_data); + enum ngbe_media_type media_type; enum ngbe_phy_type type; + u32 addr; + u32 id; + u32 revision; + u32 phy_semaphore_mask; + bool reset_disable; }; struct ngbe_hw { From patchwork Wed Jun 2 09:40:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93773 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 6E61DA0524; Wed, 2 Jun 2021 11:41:04 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id C491041140; Wed, 2 Jun 2021 11:39:54 +0200 (CEST) Received: from smtpproxy21.qq.com (smtpbg704.qq.com [203.205.195.105]) by mails.dpdk.org (Postfix) with ESMTP id B702E4113E for ; Wed, 2 Jun 2021 11:39:51 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626787tk6fl18c Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:47 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: O0I776c7OryrqG1XOAsEngpkc/zapSzTAckDbQkrBxtKKnsbBbWB/orVEspXR JYO1+T9NjsOFjqyKL1P0ZHX4zKJXeRbDUXU8X+qoclFht2QFe0JkWaeavSLG5QoR0Ul9Is1 OuasVO5YN/iz7718EWNzz0ZQbE97XOZK3bx8Q8t9lHysLPuHErZizx1jzrkcmGhj9IuTnUm cyoagH6PM8qrx2DUjFewzuGGydqBa3QdoN7xBTL1JICuIjU+3MIyl/v3Oehhz2VuXTZbkcc JszhVWilMA6EVzQEPKTV4cBl4X6xe+ESc9U7qDXMAamMMEajft0XG7y6dnkJEDZ7ns1WBJM kIXFD1mVqKTGji5hy3aE3vUuw0voVtecEXubJP4 X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:40:55 +0800 Message-Id: <20210602094108.1575640-12-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign2 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 11/24] net/ngbe: store MAC address 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 Sender: "dev" Store MAC addresses and init receive address filters. Signed-off-by: Jiawen Wu --- drivers/net/ngbe/base/ngbe_dummy.h | 33 +++ drivers/net/ngbe/base/ngbe_hw.c | 323 +++++++++++++++++++++++++++++ drivers/net/ngbe/base/ngbe_hw.h | 13 ++ drivers/net/ngbe/base/ngbe_osdep.h | 1 + drivers/net/ngbe/base/ngbe_type.h | 19 ++ drivers/net/ngbe/ngbe_ethdev.c | 25 +++ drivers/net/ngbe/ngbe_ethdev.h | 2 + 7 files changed, 416 insertions(+) diff --git a/drivers/net/ngbe/base/ngbe_dummy.h b/drivers/net/ngbe/base/ngbe_dummy.h index 15017cfd82..8462d6d1cb 100644 --- a/drivers/net/ngbe/base/ngbe_dummy.h +++ b/drivers/net/ngbe/base/ngbe_dummy.h @@ -51,6 +51,10 @@ static inline s32 ngbe_mac_stop_hw_dummy(struct ngbe_hw *TUP0) { return NGBE_ERR_OPS_DUMMY; } +static inline s32 ngbe_mac_get_mac_addr_dummy(struct ngbe_hw *TUP0, u8 *TUP1) +{ + return NGBE_ERR_OPS_DUMMY; +} static inline s32 ngbe_mac_acquire_swfw_sync_dummy(struct ngbe_hw *TUP0, u32 TUP1) { @@ -60,6 +64,29 @@ static inline void ngbe_mac_release_swfw_sync_dummy(struct ngbe_hw *TUP0, u32 TUP1) { } +static inline s32 ngbe_mac_set_rar_dummy(struct ngbe_hw *TUP0, u32 TUP1, + u8 *TUP2, u32 TUP3, u32 TUP4) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_mac_clear_rar_dummy(struct ngbe_hw *TUP0, u32 TUP1) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_mac_set_vmdq_dummy(struct ngbe_hw *TUP0, u32 TUP1, + u32 TUP2) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_mac_clear_vmdq_dummy(struct ngbe_hw *TUP0, u32 TUP1, + u32 TUP2) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_mac_init_rx_addrs_dummy(struct ngbe_hw *TUP0) +{ + return NGBE_ERR_OPS_DUMMY; +} static inline s32 ngbe_mac_init_thermal_ssth_dummy(struct ngbe_hw *TUP0) { return NGBE_ERR_OPS_DUMMY; @@ -105,8 +132,14 @@ static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw) hw->mac.init_hw = ngbe_mac_init_hw_dummy; hw->mac.reset_hw = ngbe_mac_reset_hw_dummy; hw->mac.stop_hw = ngbe_mac_stop_hw_dummy; + hw->mac.get_mac_addr = ngbe_mac_get_mac_addr_dummy; hw->mac.acquire_swfw_sync = ngbe_mac_acquire_swfw_sync_dummy; hw->mac.release_swfw_sync = ngbe_mac_release_swfw_sync_dummy; + hw->mac.set_rar = ngbe_mac_set_rar_dummy; + hw->mac.clear_rar = ngbe_mac_clear_rar_dummy; + hw->mac.set_vmdq = ngbe_mac_set_vmdq_dummy; + hw->mac.clear_vmdq = ngbe_mac_clear_vmdq_dummy; + hw->mac.init_rx_addrs = ngbe_mac_init_rx_addrs_dummy; hw->mac.init_thermal_sensor_thresh = ngbe_mac_init_thermal_ssth_dummy; hw->mac.check_overtemp = ngbe_mac_check_overtemp_dummy; hw->phy.identify = ngbe_phy_identify_dummy; diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c index ebd163d9e6..386557f468 100644 --- a/drivers/net/ngbe/base/ngbe_hw.c +++ b/drivers/net/ngbe/base/ngbe_hw.c @@ -142,9 +142,49 @@ s32 ngbe_reset_hw_em(struct ngbe_hw *hw) msec_delay(50); + /* Store the permanent mac address */ + hw->mac.get_mac_addr(hw, hw->mac.perm_addr); + + /* + * Store MAC address from RAR0, clear receive address registers, and + * clear the multicast table. + */ + hw->mac.num_rar_entries = NGBE_EM_RAR_ENTRIES; + hw->mac.init_rx_addrs(hw); + return status; } +/** + * ngbe_get_mac_addr - Generic get MAC address + * @hw: pointer to hardware structure + * @mac_addr: Adapter MAC address + * + * Reads the adapter's MAC address from first Receive Address Register (RAR0) + * A reset of the adapter must be performed prior to calling this function + * in order for the MAC address to have been loaded from the EEPROM into RAR0 + **/ +s32 ngbe_get_mac_addr(struct ngbe_hw *hw, u8 *mac_addr) +{ + u32 rar_high; + u32 rar_low; + u16 i; + + DEBUGFUNC("ngbe_get_mac_addr"); + + wr32(hw, NGBE_ETHADDRIDX, 0); + rar_high = rd32(hw, NGBE_ETHADDRH); + rar_low = rd32(hw, NGBE_ETHADDRL); + + for (i = 0; i < 2; i++) + mac_addr[i] = (u8)(rar_high >> (1 - i) * 8); + + for (i = 0; i < 4; i++) + mac_addr[i + 2] = (u8)(rar_low >> (3 - i) * 8); + + return 0; +} + /** * ngbe_set_lan_id_multi_port - Set LAN id for PCIe multiple port devices * @hw: pointer to the HW structure @@ -215,6 +255,196 @@ s32 ngbe_stop_hw(struct ngbe_hw *hw) return 0; } +/** + * ngbe_validate_mac_addr - Validate MAC address + * @mac_addr: pointer to MAC address. + * + * Tests a MAC address to ensure it is a valid Individual Address. + **/ +s32 ngbe_validate_mac_addr(u8 *mac_addr) +{ + s32 status = 0; + + DEBUGFUNC("ngbe_validate_mac_addr"); + + /* Make sure it is not a multicast address */ + if (NGBE_IS_MULTICAST((struct rte_ether_addr *)mac_addr)) { + status = NGBE_ERR_INVALID_MAC_ADDR; + /* Not a broadcast address */ + } else if (NGBE_IS_BROADCAST((struct rte_ether_addr *)mac_addr)) { + status = NGBE_ERR_INVALID_MAC_ADDR; + /* Reject the zero address */ + } else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && + mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) { + status = NGBE_ERR_INVALID_MAC_ADDR; + } + return status; +} + +/** + * ngbe_set_rar - Set Rx address register + * @hw: pointer to hardware structure + * @index: Receive address register to write + * @addr: Address to put into receive address register + * @vmdq: VMDq "set" or "pool" index + * @enable_addr: set flag that address is active + * + * Puts an ethernet address into a receive address register. + **/ +s32 ngbe_set_rar(struct ngbe_hw *hw, u32 index, u8 *addr, u32 vmdq, + u32 enable_addr) +{ + u32 rar_low, rar_high; + u32 rar_entries = hw->mac.num_rar_entries; + + DEBUGFUNC("ngbe_set_rar"); + + /* Make sure we are using a valid rar index range */ + if (index >= rar_entries) { + DEBUGOUT("RAR index %d is out of range.\n", index); + return NGBE_ERR_INVALID_ARGUMENT; + } + + /* setup VMDq pool selection before this RAR gets enabled */ + hw->mac.set_vmdq(hw, index, vmdq); + + /* + * HW expects these in little endian so we reverse the byte + * order from network order (big endian) to little endian + */ + rar_low = NGBE_ETHADDRL_AD0(addr[5]) | + NGBE_ETHADDRL_AD1(addr[4]) | + NGBE_ETHADDRL_AD2(addr[3]) | + NGBE_ETHADDRL_AD3(addr[2]); + /* + * Some parts put the VMDq setting in the extra RAH bits, + * so save everything except the lower 16 bits that hold part + * of the address and the address valid bit. + */ + rar_high = rd32(hw, NGBE_ETHADDRH); + rar_high &= ~NGBE_ETHADDRH_AD_MASK; + rar_high |= (NGBE_ETHADDRH_AD4(addr[1]) | + NGBE_ETHADDRH_AD5(addr[0])); + + rar_high &= ~NGBE_ETHADDRH_VLD; + if (enable_addr != 0) + rar_high |= NGBE_ETHADDRH_VLD; + + wr32(hw, NGBE_ETHADDRIDX, index); + wr32(hw, NGBE_ETHADDRL, rar_low); + wr32(hw, NGBE_ETHADDRH, rar_high); + + return 0; +} + +/** + * ngbe_clear_rar - Remove Rx address register + * @hw: pointer to hardware structure + * @index: Receive address register to write + * + * Clears an ethernet address from a receive address register. + **/ +s32 ngbe_clear_rar(struct ngbe_hw *hw, u32 index) +{ + u32 rar_high; + u32 rar_entries = hw->mac.num_rar_entries; + + DEBUGFUNC("ngbe_clear_rar"); + + /* Make sure we are using a valid rar index range */ + if (index >= rar_entries) { + DEBUGOUT("RAR index %d is out of range.\n", index); + return NGBE_ERR_INVALID_ARGUMENT; + } + + /* + * Some parts put the VMDq setting in the extra RAH bits, + * so save everything except the lower 16 bits that hold part + * of the address and the address valid bit. + */ + wr32(hw, NGBE_ETHADDRIDX, index); + rar_high = rd32(hw, NGBE_ETHADDRH); + rar_high &= ~(NGBE_ETHADDRH_AD_MASK | NGBE_ETHADDRH_VLD); + + wr32(hw, NGBE_ETHADDRL, 0); + wr32(hw, NGBE_ETHADDRH, rar_high); + + /* clear VMDq pool/queue selection for this RAR */ + hw->mac.clear_vmdq(hw, index, BIT_MASK32); + + return 0; +} + +/** + * ngbe_init_rx_addrs - Initializes receive address filters. + * @hw: pointer to hardware structure + * + * Places the MAC address in receive address register 0 and clears the rest + * of the receive address registers. Clears the multicast table. Assumes + * the receiver is in reset when the routine is called. + **/ +s32 ngbe_init_rx_addrs(struct ngbe_hw *hw) +{ + u32 i; + u32 psrctl; + u32 rar_entries = hw->mac.num_rar_entries; + + DEBUGFUNC("ngbe_init_rx_addrs"); + + /* + * If the current mac address is valid, assume it is a software override + * to the permanent address. + * Otherwise, use the permanent address from the eeprom. + */ + if (ngbe_validate_mac_addr(hw->mac.addr) == + NGBE_ERR_INVALID_MAC_ADDR) { + /* Get the MAC address from the RAR0 for later reference */ + hw->mac.get_mac_addr(hw, hw->mac.addr); + + DEBUGOUT(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ", + hw->mac.addr[0], hw->mac.addr[1], + hw->mac.addr[2]); + DEBUGOUT("%.2X %.2X %.2X\n", hw->mac.addr[3], + hw->mac.addr[4], hw->mac.addr[5]); + } else { + /* Setup the receive address. */ + DEBUGOUT("Overriding MAC Address in RAR[0]\n"); + DEBUGOUT(" New MAC Addr =%.2X %.2X %.2X ", + hw->mac.addr[0], hw->mac.addr[1], + hw->mac.addr[2]); + DEBUGOUT("%.2X %.2X %.2X\n", hw->mac.addr[3], + hw->mac.addr[4], hw->mac.addr[5]); + + hw->mac.set_rar(hw, 0, hw->mac.addr, 0, true); + } + + /* clear VMDq pool/queue selection for RAR 0 */ + hw->mac.clear_vmdq(hw, 0, BIT_MASK32); + + /* Zero out the other receive addresses. */ + DEBUGOUT("Clearing RAR[1-%d]\n", rar_entries - 1); + for (i = 1; i < rar_entries; i++) { + wr32(hw, NGBE_ETHADDRIDX, i); + wr32(hw, NGBE_ETHADDRL, 0); + wr32(hw, NGBE_ETHADDRH, 0); + } + + /* Clear the MTA */ + hw->addr_ctrl.mta_in_use = 0; + psrctl = rd32(hw, NGBE_PSRCTL); + psrctl &= ~(NGBE_PSRCTL_ADHF12_MASK | NGBE_PSRCTL_MCHFENA); + psrctl |= NGBE_PSRCTL_ADHF12(hw->mac.mc_filter_type); + wr32(hw, NGBE_PSRCTL, psrctl); + + DEBUGOUT(" Clearing MTA\n"); + for (i = 0; i < hw->mac.mcft_size; i++) + wr32(hw, NGBE_MCADDRTBL(i), 0); + + ngbe_init_uta_tables(hw); + + return 0; +} + /** * ngbe_acquire_swfw_sync - Acquire SWFW semaphore * @hw: pointer to hardware structure @@ -286,6 +516,89 @@ void ngbe_release_swfw_sync(struct ngbe_hw *hw, u32 mask) ngbe_release_eeprom_semaphore(hw); } +/** + * ngbe_clear_vmdq - Disassociate a VMDq pool index from a rx address + * @hw: pointer to hardware struct + * @rar: receive address register index to disassociate + * @vmdq: VMDq pool index to remove from the rar + **/ +s32 ngbe_clear_vmdq(struct ngbe_hw *hw, u32 rar, u32 vmdq) +{ + u32 mpsar; + u32 rar_entries = hw->mac.num_rar_entries; + + DEBUGFUNC("ngbe_clear_vmdq"); + + /* Make sure we are using a valid rar index range */ + if (rar >= rar_entries) { + DEBUGOUT("RAR index %d is out of range.\n", rar); + return NGBE_ERR_INVALID_ARGUMENT; + } + + wr32(hw, NGBE_ETHADDRIDX, rar); + mpsar = rd32(hw, NGBE_ETHADDRASS); + + if (NGBE_REMOVED(hw->hw_addr)) + goto done; + + if (!mpsar) + goto done; + + mpsar &= ~(1 << vmdq); + wr32(hw, NGBE_ETHADDRASS, mpsar); + + /* was that the last pool using this rar? */ + if (mpsar == 0 && rar != 0) + hw->mac.clear_rar(hw, rar); +done: + return 0; +} + +/** + * ngbe_set_vmdq - Associate a VMDq pool index with a rx address + * @hw: pointer to hardware struct + * @rar: receive address register index to associate with a VMDq index + * @vmdq: VMDq pool index + **/ +s32 ngbe_set_vmdq(struct ngbe_hw *hw, u32 rar, u32 vmdq) +{ + u32 mpsar; + u32 rar_entries = hw->mac.num_rar_entries; + + DEBUGFUNC("ngbe_set_vmdq"); + + /* Make sure we are using a valid rar index range */ + if (rar >= rar_entries) { + DEBUGOUT("RAR index %d is out of range.\n", rar); + return NGBE_ERR_INVALID_ARGUMENT; + } + + wr32(hw, NGBE_ETHADDRIDX, rar); + + mpsar = rd32(hw, NGBE_ETHADDRASS); + mpsar |= 1 << vmdq; + wr32(hw, NGBE_ETHADDRASS, mpsar); + + return 0; +} + +/** + * ngbe_init_uta_tables - Initialize the Unicast Table Array + * @hw: pointer to hardware structure + **/ +s32 ngbe_init_uta_tables(struct ngbe_hw *hw) +{ + int i; + + DEBUGFUNC("ngbe_init_uta_tables"); + DEBUGOUT(" Clearing UTA\n"); + + for (i = 0; i < 128; i++) + wr32(hw, NGBE_UCADDRTBL(i), 0); + + return 0; +} + /** * ngbe_init_thermal_sensor_thresh - Inits thermal sensor thresholds * @hw: pointer to hardware structure @@ -481,10 +794,18 @@ s32 ngbe_init_ops_pf(struct ngbe_hw *hw) /* MAC */ mac->init_hw = ngbe_init_hw; mac->reset_hw = ngbe_reset_hw_em; + mac->get_mac_addr = ngbe_get_mac_addr; mac->stop_hw = ngbe_stop_hw; mac->acquire_swfw_sync = ngbe_acquire_swfw_sync; mac->release_swfw_sync = ngbe_release_swfw_sync; + /* RAR */ + mac->set_rar = ngbe_set_rar; + mac->clear_rar = ngbe_clear_rar; + mac->init_rx_addrs = ngbe_init_rx_addrs; + mac->set_vmdq = ngbe_set_vmdq; + mac->clear_vmdq = ngbe_clear_vmdq; + /* Manageability interface */ mac->init_thermal_sensor_thresh = ngbe_init_thermal_sensor_thresh; mac->check_overtemp = ngbe_mac_check_overtemp; @@ -493,6 +814,8 @@ s32 ngbe_init_ops_pf(struct ngbe_hw *hw) rom->init_params = ngbe_init_eeprom_params; rom->validate_checksum = ngbe_validate_eeprom_checksum_em; + mac->mcft_size = NGBE_EM_MC_TBL_SIZE; + mac->num_rar_entries = NGBE_EM_RAR_ENTRIES; mac->max_rx_queues = NGBE_EM_MAX_RX_QUEUES; mac->max_tx_queues = NGBE_EM_MAX_TX_QUEUES; diff --git a/drivers/net/ngbe/base/ngbe_hw.h b/drivers/net/ngbe/base/ngbe_hw.h index 3c8e646bb7..0b3d60ae29 100644 --- a/drivers/net/ngbe/base/ngbe_hw.h +++ b/drivers/net/ngbe/base/ngbe_hw.h @@ -10,16 +10,29 @@ #define NGBE_EM_MAX_TX_QUEUES 8 #define NGBE_EM_MAX_RX_QUEUES 8 +#define NGBE_EM_RAR_ENTRIES 32 +#define NGBE_EM_MC_TBL_SIZE 32 s32 ngbe_init_hw(struct ngbe_hw *hw); s32 ngbe_reset_hw_em(struct ngbe_hw *hw); s32 ngbe_stop_hw(struct ngbe_hw *hw); +s32 ngbe_get_mac_addr(struct ngbe_hw *hw, u8 *mac_addr); void ngbe_set_lan_id_multi_port(struct ngbe_hw *hw); +s32 ngbe_set_rar(struct ngbe_hw *hw, u32 index, u8 *addr, u32 vmdq, + u32 enable_addr); +s32 ngbe_clear_rar(struct ngbe_hw *hw, u32 index); +s32 ngbe_init_rx_addrs(struct ngbe_hw *hw); + +s32 ngbe_validate_mac_addr(u8 *mac_addr); s32 ngbe_acquire_swfw_sync(struct ngbe_hw *hw, u32 mask); void ngbe_release_swfw_sync(struct ngbe_hw *hw, u32 mask); +s32 ngbe_set_vmdq(struct ngbe_hw *hw, u32 rar, u32 vmdq); +s32 ngbe_clear_vmdq(struct ngbe_hw *hw, u32 rar, u32 vmdq); +s32 ngbe_init_uta_tables(struct ngbe_hw *hw); + s32 ngbe_init_thermal_sensor_thresh(struct ngbe_hw *hw); s32 ngbe_mac_check_overtemp(struct ngbe_hw *hw); void ngbe_disable_rx(struct ngbe_hw *hw); diff --git a/drivers/net/ngbe/base/ngbe_osdep.h b/drivers/net/ngbe/base/ngbe_osdep.h index 94cc10315e..8c2a1271cb 100644 --- a/drivers/net/ngbe/base/ngbe_osdep.h +++ b/drivers/net/ngbe/base/ngbe_osdep.h @@ -18,6 +18,7 @@ #include #include #include +#include #include "../ngbe_logs.h" diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h index b5c05e0f2f..5add9ec2a3 100644 --- a/drivers/net/ngbe/base/ngbe_type.h +++ b/drivers/net/ngbe/base/ngbe_type.h @@ -62,6 +62,10 @@ enum ngbe_media_type { struct ngbe_hw; +struct ngbe_addr_filter_info { + u32 mta_in_use; +}; + /* Bus parameters */ struct ngbe_bus_info { void (*set_lan_id)(struct ngbe_hw *hw); @@ -88,14 +92,28 @@ struct ngbe_mac_info { s32 (*init_hw)(struct ngbe_hw *hw); s32 (*reset_hw)(struct ngbe_hw *hw); s32 (*stop_hw)(struct ngbe_hw *hw); + s32 (*get_mac_addr)(struct ngbe_hw *hw, u8 *mac_addr); s32 (*acquire_swfw_sync)(struct ngbe_hw *hw, u32 mask); void (*release_swfw_sync)(struct ngbe_hw *hw, u32 mask); + /* RAR */ + s32 (*set_rar)(struct ngbe_hw *hw, u32 index, u8 *addr, u32 vmdq, + u32 enable_addr); + s32 (*clear_rar)(struct ngbe_hw *hw, u32 index); + s32 (*set_vmdq)(struct ngbe_hw *hw, u32 rar, u32 vmdq); + s32 (*clear_vmdq)(struct ngbe_hw *hw, u32 rar, u32 vmdq); + s32 (*init_rx_addrs)(struct ngbe_hw *hw); + /* Manageability interface */ s32 (*init_thermal_sensor_thresh)(struct ngbe_hw *hw); s32 (*check_overtemp)(struct ngbe_hw *hw); enum ngbe_mac_type type; + u8 addr[ETH_ADDR_LEN]; + u8 perm_addr[ETH_ADDR_LEN]; + s32 mc_filter_type; + u32 mcft_size; + u32 num_rar_entries; u32 max_tx_queues; u32 max_rx_queues; struct ngbe_thermal_sensor_data thermal_sensor_data; @@ -127,6 +145,7 @@ struct ngbe_hw { void IOMEM *hw_addr; void *back; struct ngbe_mac_info mac; + struct ngbe_addr_filter_info addr_ctrl; struct ngbe_phy_info phy; struct ngbe_rom_info rom; struct ngbe_bus_info bus; diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index bb5923c485..e9ddbe9753 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -116,6 +116,31 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + /* Allocate memory for storing MAC addresses */ + eth_dev->data->mac_addrs = rte_zmalloc("ngbe", RTE_ETHER_ADDR_LEN * + hw->mac.num_rar_entries, 0); + if (eth_dev->data->mac_addrs == NULL) { + PMD_INIT_LOG(ERR, + "Failed to allocate %u bytes needed to store " + "MAC addresses", + RTE_ETHER_ADDR_LEN * hw->mac.num_rar_entries); + return -ENOMEM; + } + + /* Copy the permanent MAC address */ + rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.perm_addr, + ð_dev->data->mac_addrs[0]); + + /* Allocate memory for storing hash filter MAC addresses */ + eth_dev->data->hash_mac_addrs = rte_zmalloc("ngbe", + RTE_ETHER_ADDR_LEN * NGBE_VMDQ_NUM_UC_MAC, 0); + if (eth_dev->data->hash_mac_addrs == NULL) { + PMD_INIT_LOG(ERR, + "Failed to allocate %d bytes needed to store MAC addresses", + RTE_ETHER_ADDR_LEN * NGBE_VMDQ_NUM_UC_MAC); + return -ENOMEM; + } + return 0; } diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h index f6cee4a4a9..5917ff02aa 100644 --- a/drivers/net/ngbe/ngbe_ethdev.h +++ b/drivers/net/ngbe/ngbe_ethdev.h @@ -19,4 +19,6 @@ struct ngbe_adapter { #define NGBE_DEV_HW(dev) \ (&((struct ngbe_adapter *)(dev)->data->dev_private)->hw) +#define NGBE_VMDQ_NUM_UC_MAC 4096 /* Maximum nb. of UC MAC addr. */ + #endif /* _NGBE_ETHDEV_H_ */ From patchwork Wed Jun 2 09:40:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93774 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 504ABA0524; Wed, 2 Jun 2021 11:41:13 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 4D2774115B; Wed, 2 Jun 2021 11:39:56 +0200 (CEST) Received: from smtpbgeu1.qq.com (smtpbgeu1.qq.com [52.59.177.22]) by mails.dpdk.org (Postfix) with ESMTP id 4153A4113D for ; Wed, 2 Jun 2021 11:39:53 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626789tu0g9ruh Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:49 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: YMCyK+F2Wl8kaUDYDcdaZ9Rss3Hbq3yLgBFOS9IWwUxyQatM+IYvyMD8edhjC N31h61jtJiH/25Z3wOv9q0R0qrZjfQQwGIATEtR8Yr3rVZJwCSOBbeQUkBQuXWU18skCyCw kB57n4ZzZlL0T2vkJFSZbHkct0j2IglwXa7OhJZzDE9uqVdv+1Y2hXXAxBMWOvcdDvPePUJ YxYS5v5V0f/xhMX7pL47O+p983IQT3m80uN+eewXEFCjpx9rbRlfaYexf0wXo7GJFAwc0VK sQ7R5AKlqHlED+u2x4GnPzJ6AY+DEtt2MA3tBkQSM1FkprII9Rag61Sijtu6C9KUmWHyyal fQYtG6ezI/XVgAW2C4dikRpJ+NpHQ== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:40:56 +0800 Message-Id: <20210602094108.1575640-13-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign2 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 12/24] net/ngbe: add info get operation 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 Sender: "dev" Add device information get operation. Signed-off-by: Jiawen Wu --- doc/guides/nics/features/ngbe.ini | 1 + drivers/net/ngbe/meson.build | 1 + drivers/net/ngbe/ngbe_ethdev.c | 86 +++++++++++++++++++++++++++++++ drivers/net/ngbe/ngbe_ethdev.h | 26 ++++++++++ drivers/net/ngbe/ngbe_rxtx.c | 67 ++++++++++++++++++++++++ drivers/net/ngbe/ngbe_rxtx.h | 15 ++++++ 6 files changed, 196 insertions(+) create mode 100644 drivers/net/ngbe/ngbe_rxtx.c create mode 100644 drivers/net/ngbe/ngbe_rxtx.h diff --git a/doc/guides/nics/features/ngbe.ini b/doc/guides/nics/features/ngbe.ini index 977286ac04..ca03a255de 100644 --- a/doc/guides/nics/features/ngbe.ini +++ b/doc/guides/nics/features/ngbe.ini @@ -4,6 +4,7 @@ ; Refer to default.ini for the full list of available PMD features. ; [Features] +Speed capabilities = Y Multiprocess aware = Y Linux = Y ARMv8 = Y diff --git a/drivers/net/ngbe/meson.build b/drivers/net/ngbe/meson.build index 81173fa7f0..9e75b82f1c 100644 --- a/drivers/net/ngbe/meson.build +++ b/drivers/net/ngbe/meson.build @@ -12,6 +12,7 @@ objs = [base_objs] sources = files( 'ngbe_ethdev.c', + 'ngbe_rxtx.c', ) includes += include_directories('base') diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index e9ddbe9753..07df677b64 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -9,6 +9,7 @@ #include "ngbe_logs.h" #include "base/ngbe.h" #include "ngbe_ethdev.h" +#include "ngbe_rxtx.h" static int ngbe_dev_close(struct rte_eth_dev *dev); @@ -31,6 +32,22 @@ static const struct rte_pci_id pci_id_ngbe_map[] = { { .vendor_id = 0, /* sentinel */ }, }; +static const struct rte_eth_desc_lim rx_desc_lim = { + .nb_max = NGBE_RING_DESC_MAX, + .nb_min = NGBE_RING_DESC_MIN, + .nb_align = NGBE_RXD_ALIGN, +}; + +static const struct rte_eth_desc_lim tx_desc_lim = { + .nb_max = NGBE_RING_DESC_MAX, + .nb_min = NGBE_RING_DESC_MIN, + .nb_align = NGBE_TXD_ALIGN, + .nb_seg_max = NGBE_TX_MAX_SEG, + .nb_mtu_seg_max = NGBE_TX_MAX_SEG, +}; + +static const struct eth_dev_ops ngbe_eth_dev_ops; + /* * Ensure that all locks are released before first NVM or PHY access */ @@ -64,6 +81,8 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) PMD_INIT_FUNC_TRACE(); + eth_dev->dev_ops = &ngbe_eth_dev_ops; + if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; @@ -206,6 +225,73 @@ ngbe_dev_close(struct rte_eth_dev *dev) return 0; } +static int +ngbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) +{ + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct ngbe_hw *hw = NGBE_DEV_HW(dev); + + dev_info->max_rx_queues = (uint16_t)hw->mac.max_rx_queues; + dev_info->max_tx_queues = (uint16_t)hw->mac.max_tx_queues; + dev_info->min_rx_bufsize = 1024; + dev_info->max_rx_pktlen = 15872; + dev_info->max_mac_addrs = hw->mac.num_rar_entries; + dev_info->max_hash_mac_addrs = NGBE_VMDQ_NUM_UC_MAC; + dev_info->max_vfs = pci_dev->max_vfs; + dev_info->max_vmdq_pools = ETH_64_POOLS; + dev_info->vmdq_queue_num = dev_info->max_rx_queues; + dev_info->rx_queue_offload_capa = ngbe_get_rx_queue_offloads(dev); + dev_info->rx_offload_capa = (ngbe_get_rx_port_offloads(dev) | + dev_info->rx_queue_offload_capa); + dev_info->tx_queue_offload_capa = 0; + dev_info->tx_offload_capa = ngbe_get_tx_port_offloads(dev); + + dev_info->default_rxconf = (struct rte_eth_rxconf) { + .rx_thresh = { + .pthresh = NGBE_DEFAULT_RX_PTHRESH, + .hthresh = NGBE_DEFAULT_RX_HTHRESH, + .wthresh = NGBE_DEFAULT_RX_WTHRESH, + }, + .rx_free_thresh = NGBE_DEFAULT_RX_FREE_THRESH, + .rx_drop_en = 0, + .offloads = 0, + }; + + dev_info->default_txconf = (struct rte_eth_txconf) { + .tx_thresh = { + .pthresh = NGBE_DEFAULT_TX_PTHRESH, + .hthresh = NGBE_DEFAULT_TX_HTHRESH, + .wthresh = NGBE_DEFAULT_TX_WTHRESH, + }, + .tx_free_thresh = NGBE_DEFAULT_TX_FREE_THRESH, + .offloads = 0, + }; + + dev_info->rx_desc_lim = rx_desc_lim; + dev_info->tx_desc_lim = tx_desc_lim; + + dev_info->hash_key_size = NGBE_HKEY_MAX_INDEX * sizeof(uint32_t); + dev_info->reta_size = ETH_RSS_RETA_SIZE_128; + dev_info->flow_type_rss_offloads = NGBE_RSS_OFFLOAD_ALL; + + dev_info->speed_capa = ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G; + dev_info->speed_capa |= ETH_LINK_SPEED_100M; + + /* Driver-preferred Rx/Tx parameters */ + dev_info->default_rxportconf.burst_size = 32; + dev_info->default_txportconf.burst_size = 32; + dev_info->default_rxportconf.nb_queues = 1; + dev_info->default_txportconf.nb_queues = 1; + dev_info->default_rxportconf.ring_size = 256; + dev_info->default_txportconf.ring_size = 256; + + return 0; +} + +static const struct eth_dev_ops ngbe_eth_dev_ops = { + .dev_infos_get = ngbe_dev_info_get, +}; + RTE_PMD_REGISTER_PCI(net_ngbe, rte_ngbe_pmd); RTE_PMD_REGISTER_PCI_TABLE(net_ngbe, pci_id_ngbe_map); RTE_PMD_REGISTER_KMOD_DEP(net_ngbe, "* igb_uio | uio_pci_generic | vfio-pci"); diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h index 5917ff02aa..b4e2000dd3 100644 --- a/drivers/net/ngbe/ngbe_ethdev.h +++ b/drivers/net/ngbe/ngbe_ethdev.h @@ -6,6 +6,19 @@ #ifndef _NGBE_ETHDEV_H_ #define _NGBE_ETHDEV_H_ +#define NGBE_HKEY_MAX_INDEX 10 + +#define NGBE_RSS_OFFLOAD_ALL ( \ + ETH_RSS_IPV4 | \ + ETH_RSS_NONFRAG_IPV4_TCP | \ + ETH_RSS_NONFRAG_IPV4_UDP | \ + ETH_RSS_IPV6 | \ + ETH_RSS_NONFRAG_IPV6_TCP | \ + ETH_RSS_NONFRAG_IPV6_UDP | \ + ETH_RSS_IPV6_EX | \ + ETH_RSS_IPV6_TCP_EX | \ + ETH_RSS_IPV6_UDP_EX) + /* * Structure to store private data for each driver instance (for each port). */ @@ -21,4 +34,17 @@ struct ngbe_adapter { #define NGBE_VMDQ_NUM_UC_MAC 4096 /* Maximum nb. of UC MAC addr. */ +/* + * Default values for RX/TX configuration + */ +#define NGBE_DEFAULT_RX_FREE_THRESH 32 +#define NGBE_DEFAULT_RX_PTHRESH 8 +#define NGBE_DEFAULT_RX_HTHRESH 8 +#define NGBE_DEFAULT_RX_WTHRESH 0 + +#define NGBE_DEFAULT_TX_FREE_THRESH 32 +#define NGBE_DEFAULT_TX_PTHRESH 32 +#define NGBE_DEFAULT_TX_HTHRESH 0 +#define NGBE_DEFAULT_TX_WTHRESH 0 + #endif /* _NGBE_ETHDEV_H_ */ diff --git a/drivers/net/ngbe/ngbe_rxtx.c b/drivers/net/ngbe/ngbe_rxtx.c new file mode 100644 index 0000000000..ae24367b18 --- /dev/null +++ b/drivers/net/ngbe/ngbe_rxtx.c @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#include +#include + +#include "base/ngbe.h" +#include "ngbe_ethdev.h" +#include "ngbe_rxtx.h" + +uint64_t +ngbe_get_tx_port_offloads(struct rte_eth_dev *dev) +{ + uint64_t tx_offload_capa; + struct ngbe_hw *hw = NGBE_DEV_HW(dev); + + tx_offload_capa = + DEV_TX_OFFLOAD_VLAN_INSERT | + DEV_TX_OFFLOAD_IPV4_CKSUM | + DEV_TX_OFFLOAD_UDP_CKSUM | + DEV_TX_OFFLOAD_TCP_CKSUM | + DEV_TX_OFFLOAD_SCTP_CKSUM | + DEV_TX_OFFLOAD_TCP_TSO | + DEV_TX_OFFLOAD_UDP_TSO | + DEV_TX_OFFLOAD_UDP_TNL_TSO | + DEV_TX_OFFLOAD_IP_TNL_TSO | + DEV_TX_OFFLOAD_IPIP_TNL_TSO | + DEV_TX_OFFLOAD_MULTI_SEGS; + + if (hw->is_pf) + tx_offload_capa |= DEV_TX_OFFLOAD_QINQ_INSERT; + + tx_offload_capa |= DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM; + + return tx_offload_capa; +} + +uint64_t +ngbe_get_rx_queue_offloads(struct rte_eth_dev *dev __rte_unused) +{ + return DEV_RX_OFFLOAD_VLAN_STRIP; +} + +uint64_t +ngbe_get_rx_port_offloads(struct rte_eth_dev *dev) +{ + uint64_t offloads; + struct ngbe_hw *hw = NGBE_DEV_HW(dev); + + offloads = DEV_RX_OFFLOAD_IPV4_CKSUM | + DEV_RX_OFFLOAD_UDP_CKSUM | + DEV_RX_OFFLOAD_TCP_CKSUM | + DEV_RX_OFFLOAD_KEEP_CRC | + DEV_RX_OFFLOAD_JUMBO_FRAME | + DEV_RX_OFFLOAD_VLAN_FILTER | + DEV_RX_OFFLOAD_SCATTER; + + if (hw->is_pf) + offloads |= (DEV_RX_OFFLOAD_VLAN_FILTER | + DEV_RX_OFFLOAD_QINQ_STRIP | + DEV_RX_OFFLOAD_VLAN_EXTEND); + + return offloads; +} + diff --git a/drivers/net/ngbe/ngbe_rxtx.h b/drivers/net/ngbe/ngbe_rxtx.h new file mode 100644 index 0000000000..39011ee286 --- /dev/null +++ b/drivers/net/ngbe/ngbe_rxtx.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#ifndef _NGBE_RXTX_H_ +#define _NGBE_RXTX_H_ + +#define NGBE_TX_MAX_SEG 40 + +uint64_t ngbe_get_tx_port_offloads(struct rte_eth_dev *dev); +uint64_t ngbe_get_rx_queue_offloads(struct rte_eth_dev *dev); +uint64_t ngbe_get_rx_port_offloads(struct rte_eth_dev *dev); + +#endif /* _NGBE_RXTX_H_ */ From patchwork Wed Jun 2 09:40:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93775 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 36245A0A02; Wed, 2 Jun 2021 11:41:21 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id C9CCA41166; Wed, 2 Jun 2021 11:39:57 +0200 (CEST) Received: from smtpbg501.qq.com (smtpbg501.qq.com [203.205.250.101]) by mails.dpdk.org (Postfix) with ESMTP id A9F0E4114F for ; Wed, 2 Jun 2021 11:39:53 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626791tmg4ikv4 Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:50 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: xeo957adDlZEmZPzW1uACs37kd/ZgwISjrfyR0XHP8urw8Je7LaakNwCh7DZ9 BVR9Bt+mJUgzifQR8sIYUAF0+EPdfaCXtAv+aTqwVId4V1kJ4PRgo/bQRqE3SeDQKna7Ndo nTpTY6zmrkhLK+8lafJmqCvzwQjUhrv1pIQh7awFss2iAogbyGBTIxakOwJZuZisjeANltt wrgDjLKf+uI0HBR0nDZEQ3TPh0wSCirg8zp4R6eWoBvDqf3uL9PeE+JDkwuE59jH58NmTAq brfahiK/mF8OEzw+kwYeFz7bQ9Sis3GjfgWDidah6uDfE0h7+TgqzWe8GFpgHXAgVY46UNH HlPZqgvL4JjMupVsMrMCxCdc8r7gw== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:40:57 +0800 Message-Id: <20210602094108.1575640-14-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign6 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 13/24] net/ngbe: support link update 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 Sender: "dev" Register to handle device interrupt. Signed-off-by: Jiawen Wu --- doc/guides/nics/features/ngbe.ini | 2 + doc/guides/nics/ngbe.rst | 5 + drivers/net/ngbe/base/ngbe_dummy.h | 6 + drivers/net/ngbe/base/ngbe_type.h | 11 + drivers/net/ngbe/ngbe_ethdev.c | 364 +++++++++++++++++++++++++++++ drivers/net/ngbe/ngbe_ethdev.h | 28 +++ 6 files changed, 416 insertions(+) diff --git a/doc/guides/nics/features/ngbe.ini b/doc/guides/nics/features/ngbe.ini index ca03a255de..291a542a42 100644 --- a/doc/guides/nics/features/ngbe.ini +++ b/doc/guides/nics/features/ngbe.ini @@ -5,6 +5,8 @@ ; [Features] Speed capabilities = Y +Link status = Y +Link status event = Y Multiprocess aware = Y Linux = Y ARMv8 = Y diff --git a/doc/guides/nics/ngbe.rst b/doc/guides/nics/ngbe.rst index c274a15aab..de2ef65664 100644 --- a/doc/guides/nics/ngbe.rst +++ b/doc/guides/nics/ngbe.rst @@ -7,6 +7,11 @@ NGBE Poll Mode Driver The NGBE PMD (librte_pmd_ngbe) provides poll mode driver support for Wangxun 1 Gigabit Ethernet NICs. +Features +-------- + +- Link state information + Prerequisites ------------- diff --git a/drivers/net/ngbe/base/ngbe_dummy.h b/drivers/net/ngbe/base/ngbe_dummy.h index 8462d6d1cb..4273e5af36 100644 --- a/drivers/net/ngbe/base/ngbe_dummy.h +++ b/drivers/net/ngbe/base/ngbe_dummy.h @@ -64,6 +64,11 @@ static inline void ngbe_mac_release_swfw_sync_dummy(struct ngbe_hw *TUP0, u32 TUP1) { } +static inline s32 ngbe_mac_check_link_dummy(struct ngbe_hw *TUP0, u32 *TUP1, + bool *TUP3, bool TUP4) +{ + return NGBE_ERR_OPS_DUMMY; +} static inline s32 ngbe_mac_set_rar_dummy(struct ngbe_hw *TUP0, u32 TUP1, u8 *TUP2, u32 TUP3, u32 TUP4) { @@ -135,6 +140,7 @@ static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw) hw->mac.get_mac_addr = ngbe_mac_get_mac_addr_dummy; hw->mac.acquire_swfw_sync = ngbe_mac_acquire_swfw_sync_dummy; hw->mac.release_swfw_sync = ngbe_mac_release_swfw_sync_dummy; + hw->mac.check_link = ngbe_mac_check_link_dummy; hw->mac.set_rar = ngbe_mac_set_rar_dummy; hw->mac.clear_rar = ngbe_mac_clear_rar_dummy; hw->mac.set_vmdq = ngbe_mac_set_vmdq_dummy; diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h index 5add9ec2a3..d05d2ff28a 100644 --- a/drivers/net/ngbe/base/ngbe_type.h +++ b/drivers/net/ngbe/base/ngbe_type.h @@ -96,6 +96,8 @@ struct ngbe_mac_info { s32 (*acquire_swfw_sync)(struct ngbe_hw *hw, u32 mask); void (*release_swfw_sync)(struct ngbe_hw *hw, u32 mask); + s32 (*check_link)(struct ngbe_hw *hw, u32 *speed, + bool *link_up, bool link_up_wait_to_complete); /* RAR */ s32 (*set_rar)(struct ngbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr); @@ -116,6 +118,7 @@ struct ngbe_mac_info { u32 num_rar_entries; u32 max_tx_queues; u32 max_rx_queues; + bool get_link_status; struct ngbe_thermal_sensor_data thermal_sensor_data; bool set_lben; }; @@ -141,6 +144,14 @@ struct ngbe_phy_info { bool reset_disable; }; +enum ngbe_isb_idx { + NGBE_ISB_HEADER, + NGBE_ISB_MISC, + NGBE_ISB_VEC0, + NGBE_ISB_VEC1, + NGBE_ISB_MAX +}; + struct ngbe_hw { void IOMEM *hw_addr; void *back; diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 07df677b64..97b6de3aa4 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -6,6 +6,8 @@ #include #include +#include + #include "ngbe_logs.h" #include "base/ngbe.h" #include "ngbe_ethdev.h" @@ -13,6 +15,9 @@ static int ngbe_dev_close(struct rte_eth_dev *dev); +static void ngbe_dev_interrupt_handler(void *param); +static void ngbe_dev_interrupt_delayed_handler(void *param); + /* * The set of PCI devices this driver supports */ @@ -47,6 +52,26 @@ static const struct rte_eth_desc_lim tx_desc_lim = { }; static const struct eth_dev_ops ngbe_eth_dev_ops; +static inline void +ngbe_enable_intr(struct rte_eth_dev *dev) +{ + struct ngbe_interrupt *intr = NGBE_DEV_INTR(dev); + struct ngbe_hw *hw = NGBE_DEV_HW(dev); + + wr32(hw, NGBE_IENMISC, intr->mask_misc); + wr32(hw, NGBE_IMC(0), intr->mask & BIT_MASK32); + ngbe_flush(hw); +} + +static void +ngbe_disable_intr(struct ngbe_hw *hw) +{ + PMD_INIT_FUNC_TRACE(); + + wr32(hw, NGBE_IMS(0), NGBE_IMS_MASK); + ngbe_flush(hw); +} + /* * Ensure that all locks are released before first NVM or PHY access @@ -76,7 +101,9 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) { struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); struct ngbe_hw *hw = NGBE_DEV_HW(eth_dev); + struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; const struct rte_memzone *mz; + uint32_t ctrl_ext; int err; PMD_INIT_FUNC_TRACE(); @@ -135,6 +162,9 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + /* disable interrupt */ + ngbe_disable_intr(hw); + /* Allocate memory for storing MAC addresses */ eth_dev->data->mac_addrs = rte_zmalloc("ngbe", RTE_ETHER_ADDR_LEN * hw->mac.num_rar_entries, 0); @@ -160,6 +190,22 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -ENOMEM; } + ctrl_ext = rd32(hw, NGBE_PORTCTL); + /* let hardware know driver is loaded */ + ctrl_ext |= NGBE_PORTCTL_DRVLOAD; + wr32(hw, NGBE_PORTCTL, ctrl_ext); + ngbe_flush(hw); + + rte_intr_callback_register(intr_handle, + ngbe_dev_interrupt_handler, eth_dev); + + /* enable uio/vfio intr/eventfd mapping */ + rte_intr_enable(intr_handle); + + /* enable support intr */ + ngbe_enable_intr(eth_dev); + + return 0; } @@ -212,6 +258,19 @@ static struct rte_pci_driver rte_ngbe_pmd = { .remove = eth_ngbe_pci_remove, }; +static int +ngbe_dev_configure(struct rte_eth_dev *dev) +{ + struct ngbe_interrupt *intr = NGBE_DEV_INTR(dev); + + PMD_INIT_FUNC_TRACE(); + + /* set flag to update link status after init */ + intr->flags |= NGBE_FLAG_NEED_LINK_UPDATE; + + return 0; +} + /* * Reset and stop device. */ @@ -288,8 +347,313 @@ ngbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) return 0; } +/* return 0 means link status changed, -1 means not changed */ +int +ngbe_dev_link_update_share(struct rte_eth_dev *dev, + int wait_to_complete) +{ + struct ngbe_hw *hw = NGBE_DEV_HW(dev); + struct rte_eth_link link; + u32 link_speed = NGBE_LINK_SPEED_UNKNOWN; + u32 lan_speed = 0; + struct ngbe_interrupt *intr = NGBE_DEV_INTR(dev); + bool link_up; + int err; + int wait = 1; + + memset(&link, 0, sizeof(link)); + link.link_status = ETH_LINK_DOWN; + link.link_speed = ETH_SPEED_NUM_NONE; + link.link_duplex = ETH_LINK_HALF_DUPLEX; + link.link_autoneg = ETH_LINK_AUTONEG; + + hw->mac.get_link_status = true; + + if (intr->flags & NGBE_FLAG_NEED_LINK_CONFIG) + return rte_eth_linkstatus_set(dev, &link); + + /* check if it needs to wait to complete, if lsc interrupt is enabled */ + if (wait_to_complete == 0 || dev->data->dev_conf.intr_conf.lsc != 0) + wait = 0; + + err = hw->mac.check_link(hw, &link_speed, &link_up, wait); + + if (err != 0) { + link.link_speed = ETH_SPEED_NUM_100M; + link.link_duplex = ETH_LINK_FULL_DUPLEX; + return rte_eth_linkstatus_set(dev, &link); + } + + if (link_up == 0) + return rte_eth_linkstatus_set(dev, &link); + + intr->flags &= ~NGBE_FLAG_NEED_LINK_CONFIG; + link.link_status = ETH_LINK_UP; + link.link_duplex = ETH_LINK_FULL_DUPLEX; + + switch (link_speed) { + default: + case NGBE_LINK_SPEED_UNKNOWN: + link.link_duplex = ETH_LINK_FULL_DUPLEX; + link.link_speed = ETH_SPEED_NUM_100M; + break; + + case NGBE_LINK_SPEED_10M_FULL: + link.link_speed = ETH_SPEED_NUM_10M; + lan_speed = 0; + break; + + case NGBE_LINK_SPEED_100M_FULL: + link.link_speed = ETH_SPEED_NUM_100M; + lan_speed = 1; + break; + + case NGBE_LINK_SPEED_1GB_FULL: + link.link_speed = ETH_SPEED_NUM_1G; + lan_speed = 2; + break; + + case NGBE_LINK_SPEED_2_5GB_FULL: + link.link_speed = ETH_SPEED_NUM_2_5G; + break; + + case NGBE_LINK_SPEED_5GB_FULL: + link.link_speed = ETH_SPEED_NUM_5G; + break; + + case NGBE_LINK_SPEED_10GB_FULL: + link.link_speed = ETH_SPEED_NUM_10G; + break; + } + + if (hw->is_pf) { + wr32m(hw, NGBE_LAN_SPEED, NGBE_LAN_SPEED_MASK, lan_speed); + if (link_speed & (NGBE_LINK_SPEED_1GB_FULL | + NGBE_LINK_SPEED_100M_FULL | NGBE_LINK_SPEED_10M_FULL)) { + wr32m(hw, NGBE_MACTXCFG, NGBE_MACTXCFG_SPEED_MASK, + NGBE_MACTXCFG_SPEED_1G | NGBE_MACTXCFG_TE); + } + } + + return rte_eth_linkstatus_set(dev, &link); +} + +static int +ngbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete) +{ + return ngbe_dev_link_update_share(dev, wait_to_complete); +} + +/* + * It reads ICR and sets flag for the link_update. + * + * @param dev + * Pointer to struct rte_eth_dev. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ngbe_dev_interrupt_get_status(struct rte_eth_dev *dev) +{ + uint32_t eicr; + struct ngbe_hw *hw = NGBE_DEV_HW(dev); + struct ngbe_interrupt *intr = NGBE_DEV_INTR(dev); + + /* clear all cause mask */ + ngbe_disable_intr(hw); + + /* read-on-clear nic registers here */ + eicr = ((u32 *)hw->isb_mem)[NGBE_ISB_MISC]; + PMD_DRV_LOG(DEBUG, "eicr %x", eicr); + + intr->flags = 0; + + /* set flag for async link update */ + if (eicr & NGBE_ICRMISC_PHY) + intr->flags |= NGBE_FLAG_NEED_LINK_UPDATE; + + if (eicr & NGBE_ICRMISC_VFMBX) + intr->flags |= NGBE_FLAG_MAILBOX; + + if (eicr & NGBE_ICRMISC_LNKSEC) + intr->flags |= NGBE_FLAG_MACSEC; + + if (eicr & NGBE_ICRMISC_GPIO) + intr->flags |= NGBE_FLAG_NEED_LINK_UPDATE; + + return 0; +} + +/** + * It gets and then prints the link status. + * + * @param dev + * Pointer to struct rte_eth_dev. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static void +ngbe_dev_link_status_print(struct rte_eth_dev *dev) +{ + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_eth_link link; + + rte_eth_linkstatus_get(dev, &link); + + if (link.link_status) { + PMD_INIT_LOG(INFO, "Port %d: Link Up - speed %u Mbps - %s", + (int)(dev->data->port_id), + (unsigned int)link.link_speed, + link.link_duplex == ETH_LINK_FULL_DUPLEX ? + "full-duplex" : "half-duplex"); + } else { + PMD_INIT_LOG(INFO, " Port %d: Link Down", + (int)(dev->data->port_id)); + } + PMD_INIT_LOG(DEBUG, "PCI Address: " PCI_PRI_FMT, + pci_dev->addr.domain, + pci_dev->addr.bus, + pci_dev->addr.devid, + pci_dev->addr.function); +} + +/* + * It executes link_update after knowing an interrupt occurred. + * + * @param dev + * Pointer to struct rte_eth_dev. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ngbe_dev_interrupt_action(struct rte_eth_dev *dev) +{ + struct ngbe_interrupt *intr = NGBE_DEV_INTR(dev); + int64_t timeout; + + PMD_DRV_LOG(DEBUG, "intr action type %d", intr->flags); + + if (intr->flags & NGBE_FLAG_NEED_LINK_UPDATE) { + struct rte_eth_link link; + + /*get the link status before link update, for predicting later*/ + rte_eth_linkstatus_get(dev, &link); + + ngbe_dev_link_update(dev, 0); + + /* likely to up */ + if (!link.link_status) + /* handle it 1 sec later, wait it being stable */ + timeout = NGBE_LINK_UP_CHECK_TIMEOUT; + /* likely to down */ + else + /* handle it 4 sec later, wait it being stable */ + timeout = NGBE_LINK_DOWN_CHECK_TIMEOUT; + + ngbe_dev_link_status_print(dev); + if (rte_eal_alarm_set(timeout * 1000, + ngbe_dev_interrupt_delayed_handler, + (void *)dev) < 0) { + PMD_DRV_LOG(ERR, "Error setting alarm"); + } else { + /* remember original mask */ + intr->mask_misc_orig = intr->mask_misc; + /* only disable lsc interrupt */ + intr->mask_misc &= ~NGBE_ICRMISC_PHY; + + intr->mask_orig = intr->mask; + /* only disable all misc interrupts */ + intr->mask &= ~(1ULL << NGBE_MISC_VEC_ID); + } + } + + PMD_DRV_LOG(DEBUG, "enable intr immediately"); + ngbe_enable_intr(dev); + + return 0; +} + +/** + * Interrupt handler which shall be registered for alarm callback for delayed + * handling specific interrupt to wait for the stable nic state. As the + * NIC interrupt state is not stable for ngbe after link is just down, + * it needs to wait 4 seconds to get the stable status. + * + * @param handle + * Pointer to interrupt handle. + * @param param + * The address of parameter (struct rte_eth_dev *) registered before. + * + * @return + * void + */ +static void +ngbe_dev_interrupt_delayed_handler(void *param) +{ + struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct ngbe_interrupt *intr = NGBE_DEV_INTR(dev); + struct ngbe_hw *hw = NGBE_DEV_HW(dev); + uint32_t eicr; + + ngbe_disable_intr(hw); + + eicr = ((u32 *)hw->isb_mem)[NGBE_ISB_MISC]; + + if (intr->flags & NGBE_FLAG_NEED_LINK_UPDATE) { + ngbe_dev_link_update(dev, 0); + intr->flags &= ~NGBE_FLAG_NEED_LINK_UPDATE; + ngbe_dev_link_status_print(dev); + rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, + NULL); + } + + if (intr->flags & NGBE_FLAG_MACSEC) { + rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_MACSEC, + NULL); + intr->flags &= ~NGBE_FLAG_MACSEC; + } + + /* restore original mask */ + intr->mask_misc = intr->mask_misc_orig; + intr->mask_misc_orig = 0; + intr->mask = intr->mask_orig; + intr->mask_orig = 0; + + PMD_DRV_LOG(DEBUG, "enable intr in delayed handler S[%08x]", eicr); + ngbe_enable_intr(dev); +} + +/** + * Interrupt handler triggered by NIC for handling + * specific interrupt. + * + * @param handle + * Pointer to interrupt handle. + * @param param + * The address of parameter (struct rte_eth_dev *) registered before. + * + * @return + * void + */ +static void +ngbe_dev_interrupt_handler(void *param) +{ + struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + + ngbe_dev_interrupt_get_status(dev); + ngbe_dev_interrupt_action(dev); +} + static const struct eth_dev_ops ngbe_eth_dev_ops = { + .dev_configure = ngbe_dev_configure, .dev_infos_get = ngbe_dev_info_get, + .link_update = ngbe_dev_link_update, }; RTE_PMD_REGISTER_PCI(net_ngbe, rte_ngbe_pmd); diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h index b4e2000dd3..10c23c41d1 100644 --- a/drivers/net/ngbe/ngbe_ethdev.h +++ b/drivers/net/ngbe/ngbe_ethdev.h @@ -6,6 +6,13 @@ #ifndef _NGBE_ETHDEV_H_ #define _NGBE_ETHDEV_H_ +/* need update link, bit flag */ +#define NGBE_FLAG_NEED_LINK_UPDATE (uint32_t)(1 << 0) +#define NGBE_FLAG_MAILBOX (uint32_t)(1 << 1) +#define NGBE_FLAG_PHY_INTERRUPT (uint32_t)(1 << 2) +#define NGBE_FLAG_MACSEC (uint32_t)(1 << 3) +#define NGBE_FLAG_NEED_LINK_CONFIG (uint32_t)(1 << 4) + #define NGBE_HKEY_MAX_INDEX 10 #define NGBE_RSS_OFFLOAD_ALL ( \ @@ -19,11 +26,23 @@ ETH_RSS_IPV6_TCP_EX | \ ETH_RSS_IPV6_UDP_EX) +#define NGBE_MISC_VEC_ID RTE_INTR_VEC_ZERO_OFFSET + +/* structure for interrupt relative data */ +struct ngbe_interrupt { + uint32_t flags; + uint32_t mask_misc; + uint32_t mask_misc_orig; /* save mask during delayed handler */ + uint64_t mask; + uint64_t mask_orig; /* save mask during delayed handler */ +}; + /* * Structure to store private data for each driver instance (for each port). */ struct ngbe_adapter { struct ngbe_hw hw; + struct ngbe_interrupt intr; }; #define NGBE_DEV_ADAPTER(dev) \ @@ -32,6 +51,15 @@ struct ngbe_adapter { #define NGBE_DEV_HW(dev) \ (&((struct ngbe_adapter *)(dev)->data->dev_private)->hw) +#define NGBE_DEV_INTR(dev) \ + (&((struct ngbe_adapter *)(dev)->data->dev_private)->intr) + +int +ngbe_dev_link_update_share(struct rte_eth_dev *dev, + int wait_to_complete); + +#define NGBE_LINK_DOWN_CHECK_TIMEOUT 4000 /* ms */ +#define NGBE_LINK_UP_CHECK_TIMEOUT 1000 /* ms */ #define NGBE_VMDQ_NUM_UC_MAC 4096 /* Maximum nb. of UC MAC addr. */ /* From patchwork Wed Jun 2 09:40:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93777 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 5B88DA0524; Wed, 2 Jun 2021 11:41:35 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 4703541171; Wed, 2 Jun 2021 11:40:00 +0200 (CEST) Received: from smtpbgau2.qq.com (smtpbgau2.qq.com [54.206.34.216]) by mails.dpdk.org (Postfix) with ESMTP id A567341163 for ; Wed, 2 Jun 2021 11:39:57 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626792tamqw9ri Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:51 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: WGeG4oi7p4Q97T3KTibR/vCEvsYQWs2JjLGFF4qhX/m1AaCVI9LkXzCeFI7iu OjkYBz4lfHoWBb353zuCkCrvQo6wxBrrN7yjnH/8xIN5/3ouopwpVIDNtcNP5asEY2Cc3RB K8b3k0nCupcdcxjWLfOoc663Ohq0JRy/uQ7fbNZmAzZQNcHi84i7cSqqZmrmUgUKPjUEJ3F +Vvo2YEA49aNGkpl1tRDomEq11vxT0EeHo0+6zNXlBqHUjcdVGIXhqjctfwFTW5vuzzqxz3 ub+DRPBlBJPpBFcVL8uUWILag6OFdGG/6d/hgDLkWItLLnxKHXrdNIR7RAf+WqaOOKiC0ik D3RC3nGff4omd3ICNBXU6kbSbDNdg== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:40:58 +0800 Message-Id: <20210602094108.1575640-15-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign1 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 14/24] net/ngbe: setup the check PHY link 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 Sender: "dev" Setup PHY, determine link and speed status from PHY. Signed-off-by: Jiawen Wu --- drivers/net/ngbe/base/ngbe_dummy.h | 18 ++++ drivers/net/ngbe/base/ngbe_hw.c | 53 ++++++++++ drivers/net/ngbe/base/ngbe_hw.h | 6 ++ drivers/net/ngbe/base/ngbe_phy.c | 22 +++++ drivers/net/ngbe/base/ngbe_phy.h | 2 + drivers/net/ngbe/base/ngbe_phy_mvl.c | 98 +++++++++++++++++++ drivers/net/ngbe/base/ngbe_phy_mvl.h | 4 + drivers/net/ngbe/base/ngbe_phy_rtl.c | 138 +++++++++++++++++++++++++++ drivers/net/ngbe/base/ngbe_phy_rtl.h | 4 + drivers/net/ngbe/base/ngbe_phy_yt.c | 134 ++++++++++++++++++++++++++ drivers/net/ngbe/base/ngbe_phy_yt.h | 9 ++ drivers/net/ngbe/base/ngbe_type.h | 9 ++ 12 files changed, 497 insertions(+) diff --git a/drivers/net/ngbe/base/ngbe_dummy.h b/drivers/net/ngbe/base/ngbe_dummy.h index 4273e5af36..709e01659c 100644 --- a/drivers/net/ngbe/base/ngbe_dummy.h +++ b/drivers/net/ngbe/base/ngbe_dummy.h @@ -64,6 +64,11 @@ static inline void ngbe_mac_release_swfw_sync_dummy(struct ngbe_hw *TUP0, u32 TUP1) { } +static inline s32 ngbe_mac_setup_link_dummy(struct ngbe_hw *TUP0, u32 TUP1, + bool TUP2) +{ + return NGBE_ERR_OPS_DUMMY; +} static inline s32 ngbe_mac_check_link_dummy(struct ngbe_hw *TUP0, u32 *TUP1, bool *TUP3, bool TUP4) { @@ -129,6 +134,16 @@ static inline s32 ngbe_phy_write_reg_unlocked_dummy(struct ngbe_hw *TUP0, { return NGBE_ERR_OPS_DUMMY; } +static inline s32 ngbe_phy_setup_link_dummy(struct ngbe_hw *TUP0, + u32 TUP1, bool TUP2) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_phy_check_link_dummy(struct ngbe_hw *TUP0, u32 *TUP1, + bool *TUP2) +{ + return NGBE_ERR_OPS_DUMMY; +} static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw) { hw->bus.set_lan_id = ngbe_bus_set_lan_id_dummy; @@ -140,6 +155,7 @@ static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw) hw->mac.get_mac_addr = ngbe_mac_get_mac_addr_dummy; hw->mac.acquire_swfw_sync = ngbe_mac_acquire_swfw_sync_dummy; hw->mac.release_swfw_sync = ngbe_mac_release_swfw_sync_dummy; + hw->mac.setup_link = ngbe_mac_setup_link_dummy; hw->mac.check_link = ngbe_mac_check_link_dummy; hw->mac.set_rar = ngbe_mac_set_rar_dummy; hw->mac.clear_rar = ngbe_mac_clear_rar_dummy; @@ -154,6 +170,8 @@ static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw) hw->phy.write_reg = ngbe_phy_write_reg_dummy; hw->phy.read_reg_unlocked = ngbe_phy_read_reg_unlocked_dummy; hw->phy.write_reg_unlocked = ngbe_phy_write_reg_unlocked_dummy; + hw->phy.setup_link = ngbe_phy_setup_link_dummy; + hw->phy.check_link = ngbe_phy_check_link_dummy; } #endif /* _NGBE_TYPE_DUMMY_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c index 386557f468..00ac4ce838 100644 --- a/drivers/net/ngbe/base/ngbe_hw.c +++ b/drivers/net/ngbe/base/ngbe_hw.c @@ -599,6 +599,54 @@ s32 ngbe_init_uta_tables(struct ngbe_hw *hw) return 0; } +/** + * ngbe_check_mac_link_em - Determine link and speed status + * @hw: pointer to hardware structure + * @speed: pointer to link speed + * @link_up: true when link is up + * @link_up_wait_to_complete: bool used to wait for link up or not + * + * Reads the links register to determine if link is up and the current speed + **/ +s32 ngbe_check_mac_link_em(struct ngbe_hw *hw, u32 *speed, + bool *link_up, bool link_up_wait_to_complete) +{ + u32 i, reg; + s32 status = 0; + + DEBUGFUNC("ngbe_check_mac_link_em"); + + reg = rd32(hw, NGBE_GPIOINTSTAT); + wr32(hw, NGBE_GPIOEOI, reg); + + if (link_up_wait_to_complete) { + for (i = 0; i < hw->mac.max_link_up_time; i++) { + status = hw->phy.check_link(hw, speed, link_up); + if (*link_up) + break; + msec_delay(100); + } + } else { + status = hw->phy.check_link(hw, speed, link_up); + } + + return status; +} + +s32 ngbe_setup_mac_link_em(struct ngbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete) +{ + s32 status; + + DEBUGFUNC("\n"); + + /* Setup the PHY according to input speed */ + status = hw->phy.setup_link(hw, speed, autoneg_wait_to_complete); + + return status; +} + /** * ngbe_init_thermal_sensor_thresh - Inits thermal sensor thresholds * @hw: pointer to hardware structure @@ -806,6 +854,10 @@ s32 ngbe_init_ops_pf(struct ngbe_hw *hw) mac->set_vmdq = ngbe_set_vmdq; mac->clear_vmdq = ngbe_clear_vmdq; + /* Link */ + mac->check_link = ngbe_check_mac_link_em; + mac->setup_link = ngbe_setup_mac_link_em; + /* Manageability interface */ mac->init_thermal_sensor_thresh = ngbe_init_thermal_sensor_thresh; mac->check_overtemp = ngbe_mac_check_overtemp; @@ -853,6 +905,7 @@ s32 ngbe_init_shared_code(struct ngbe_hw *hw) status = NGBE_ERR_DEVICE_NOT_SUPPORTED; break; } + hw->mac.max_link_up_time = NGBE_LINK_UP_TIME; hw->bus.set_lan_id(hw); diff --git a/drivers/net/ngbe/base/ngbe_hw.h b/drivers/net/ngbe/base/ngbe_hw.h index 0b3d60ae29..1689223168 100644 --- a/drivers/net/ngbe/base/ngbe_hw.h +++ b/drivers/net/ngbe/base/ngbe_hw.h @@ -20,6 +20,12 @@ s32 ngbe_get_mac_addr(struct ngbe_hw *hw, u8 *mac_addr); void ngbe_set_lan_id_multi_port(struct ngbe_hw *hw); +s32 ngbe_check_mac_link_em(struct ngbe_hw *hw, u32 *speed, + bool *link_up, bool link_up_wait_to_complete); +s32 ngbe_setup_mac_link_em(struct ngbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete); + s32 ngbe_set_rar(struct ngbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr); s32 ngbe_clear_rar(struct ngbe_hw *hw, u32 index); diff --git a/drivers/net/ngbe/base/ngbe_phy.c b/drivers/net/ngbe/base/ngbe_phy.c index d1b4cc9e5f..7a9baada81 100644 --- a/drivers/net/ngbe/base/ngbe_phy.c +++ b/drivers/net/ngbe/base/ngbe_phy.c @@ -420,7 +420,29 @@ s32 ngbe_init_phy(struct ngbe_hw *hw) /* Identify the PHY */ err = phy->identify(hw); + if (err == NGBE_ERR_PHY_ADDR_INVALID) + goto init_phy_ops_out; + /* Set necessary function pointers based on PHY type */ + switch (hw->phy.type) { + case ngbe_phy_rtl: + hw->phy.check_link = ngbe_check_phy_link_rtl; + hw->phy.setup_link = ngbe_setup_phy_link_rtl; + break; + case ngbe_phy_mvl: + case ngbe_phy_mvl_sfi: + hw->phy.check_link = ngbe_check_phy_link_mvl; + hw->phy.setup_link = ngbe_setup_phy_link_mvl; + break; + case ngbe_phy_yt8521s: + case ngbe_phy_yt8521s_sfi: + hw->phy.check_link = ngbe_check_phy_link_yt; + hw->phy.setup_link = ngbe_setup_phy_link_yt; + default: + break; + } + +init_phy_ops_out: return err; } diff --git a/drivers/net/ngbe/base/ngbe_phy.h b/drivers/net/ngbe/base/ngbe_phy.h index 59d9efe025..96e47b5bb9 100644 --- a/drivers/net/ngbe/base/ngbe_phy.h +++ b/drivers/net/ngbe/base/ngbe_phy.h @@ -22,6 +22,8 @@ #define NGBE_MD_PHY_ID_LOW 0x3 /* PHY ID Low Reg*/ #define NGBE_PHY_REVISION_MASK 0xFFFFFFF0 +#define NGBE_MII_AUTONEG_REG 0x0 + /* IEEE 802.3 Clause 22 */ struct mdi_reg_22 { u16 page; diff --git a/drivers/net/ngbe/base/ngbe_phy_mvl.c b/drivers/net/ngbe/base/ngbe_phy_mvl.c index 40419a61f6..a1c055e238 100644 --- a/drivers/net/ngbe/base/ngbe_phy_mvl.c +++ b/drivers/net/ngbe/base/ngbe_phy_mvl.c @@ -48,6 +48,64 @@ s32 ngbe_write_phy_reg_mvl(struct ngbe_hw *hw, return 0; } +s32 ngbe_setup_phy_link_mvl(struct ngbe_hw *hw, u32 speed, + bool autoneg_wait_to_complete) +{ + u16 value_r4 = 0; + u16 value_r9 = 0; + u16 value; + + DEBUGFUNC("ngbe_setup_phy_link_mvl"); + UNREFERENCED_PARAMETER(autoneg_wait_to_complete); + + hw->phy.autoneg_advertised = 0; + + if (hw->phy.type == ngbe_phy_mvl) { + if (speed & NGBE_LINK_SPEED_1GB_FULL) { + value_r9 |= MVL_PHY_1000BASET_FULL; + hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL; + } + + if (speed & NGBE_LINK_SPEED_100M_FULL) { + value_r4 |= MVL_PHY_100BASET_FULL; + hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL; + } + + if (speed & NGBE_LINK_SPEED_10M_FULL) { + value_r4 |= MVL_PHY_10BASET_FULL; + hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL; + } + + hw->phy.read_reg(hw, MVL_ANA, 0, &value); + value &= ~(MVL_PHY_100BASET_FULL | + MVL_PHY_100BASET_HALF | + MVL_PHY_10BASET_FULL | + MVL_PHY_10BASET_HALF); + value_r4 |= value; + hw->phy.write_reg(hw, MVL_ANA, 0, value_r4); + + hw->phy.read_reg(hw, MVL_PHY_1000BASET, 0, &value); + value &= ~(MVL_PHY_1000BASET_FULL | + MVL_PHY_1000BASET_HALF); + value_r9 |= value; + hw->phy.write_reg(hw, MVL_PHY_1000BASET, 0, value_r9); + } else { + hw->phy.autoneg_advertised = 1; + + hw->phy.read_reg(hw, MVL_ANA, 0, &value); + value &= ~(MVL_PHY_1000BASEX_HALF | MVL_PHY_1000BASEX_FULL); + value |= MVL_PHY_1000BASEX_FULL; + hw->phy.write_reg(hw, MVL_ANA, 0, value); + } + + value = MVL_CTRL_RESTART_AN | MVL_CTRL_ANE; + ngbe_write_phy_reg_mdi(hw, MVL_CTRL, 0, value); + + hw->phy.read_reg(hw, MVL_INTR, 0, &value); + + return 0; +} + s32 ngbe_reset_phy_mvl(struct ngbe_hw *hw) { u32 i; @@ -87,3 +145,43 @@ s32 ngbe_reset_phy_mvl(struct ngbe_hw *hw) return status; } +s32 ngbe_check_phy_link_mvl(struct ngbe_hw *hw, + u32 *speed, bool *link_up) +{ + s32 status = 0; + u16 phy_link = 0; + u16 phy_speed = 0; + u16 phy_data = 0; + u16 insr = 0; + + DEBUGFUNC("ngbe_check_phy_link_mvl"); + + /* Initialize speed and link to default case */ + *link_up = false; + *speed = NGBE_LINK_SPEED_UNKNOWN; + + hw->phy.read_reg(hw, MVL_INTR, 0, &insr); + + /* + * Check current speed and link status of the PHY register. + * This is a vendor specific register and may have to + * be changed for other copper PHYs. + */ + status = hw->phy.read_reg(hw, MVL_PHYSR, 0, &phy_data); + phy_link = phy_data & MVL_PHYSR_LINK; + phy_speed = phy_data & MVL_PHYSR_SPEED_MASK; + + if (phy_link == MVL_PHYSR_LINK) { + *link_up = true; + + if (phy_speed == MVL_PHYSR_SPEED_1000M) + *speed = NGBE_LINK_SPEED_1GB_FULL; + else if (phy_speed == MVL_PHYSR_SPEED_100M) + *speed = NGBE_LINK_SPEED_100M_FULL; + else if (phy_speed == MVL_PHYSR_SPEED_10M) + *speed = NGBE_LINK_SPEED_10M_FULL; + } + + return status; +} + diff --git a/drivers/net/ngbe/base/ngbe_phy_mvl.h b/drivers/net/ngbe/base/ngbe_phy_mvl.h index a88ace9ec1..a663a429dd 100644 --- a/drivers/net/ngbe/base/ngbe_phy_mvl.h +++ b/drivers/net/ngbe/base/ngbe_phy_mvl.h @@ -89,4 +89,8 @@ s32 ngbe_write_phy_reg_mvl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, s32 ngbe_reset_phy_mvl(struct ngbe_hw *hw); +s32 ngbe_check_phy_link_mvl(struct ngbe_hw *hw, + u32 *speed, bool *link_up); +s32 ngbe_setup_phy_link_mvl(struct ngbe_hw *hw, + u32 speed, bool autoneg_wait_to_complete); #endif /* _NGBE_PHY_MVL_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_phy_rtl.c b/drivers/net/ngbe/base/ngbe_phy_rtl.c index 9c98a8ecaf..5214ce5a8a 100644 --- a/drivers/net/ngbe/base/ngbe_phy_rtl.c +++ b/drivers/net/ngbe/base/ngbe_phy_rtl.c @@ -36,9 +36,147 @@ s32 ngbe_write_phy_reg_rtl(struct ngbe_hw *hw, return 0; } +/** + * ngbe_setup_phy_link_rtl - Set and restart auto-neg + * @hw: pointer to hardware structure + * + * Restart auto-negotiation and PHY and waits for completion. + **/ +s32 ngbe_setup_phy_link_rtl(struct ngbe_hw *hw, + u32 speed, bool autoneg_wait_to_complete) +{ + u16 autoneg_reg = NGBE_MII_AUTONEG_REG; + + DEBUGFUNC("ngbe_setup_phy_link_rtl"); + + UNREFERENCED_PARAMETER(autoneg_wait_to_complete); + + hw->phy.read_reg(hw, RTL_INSR, 0xa43, &autoneg_reg); + + /* + * Clear autoneg_advertised and set new values based on input link + * speed. + */ + if (speed) { + hw->phy.autoneg_advertised = 0; + + if (speed & NGBE_LINK_SPEED_1GB_FULL) + hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL; + + if (speed & NGBE_LINK_SPEED_100M_FULL) + hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL; + + if (speed & NGBE_LINK_SPEED_10M_FULL) + hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL; + } + + /* disable 10/100M Half Duplex */ + hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &autoneg_reg); + autoneg_reg &= 0xFF5F; + hw->phy.write_reg(hw, RTL_ANAR, RTL_DEV_ZERO, autoneg_reg); + + /* set advertise enable according to input speed */ + if (!(speed & NGBE_LINK_SPEED_1GB_FULL)) { + hw->phy.read_reg(hw, RTL_GBCR, + RTL_DEV_ZERO, &autoneg_reg); + autoneg_reg &= ~RTL_GBCR_1000F; + hw->phy.write_reg(hw, RTL_GBCR, + RTL_DEV_ZERO, autoneg_reg); + } else { + hw->phy.read_reg(hw, RTL_GBCR, + RTL_DEV_ZERO, &autoneg_reg); + autoneg_reg |= RTL_GBCR_1000F; + hw->phy.write_reg(hw, RTL_GBCR, + RTL_DEV_ZERO, autoneg_reg); + } + + if (!(speed & NGBE_LINK_SPEED_100M_FULL)) { + hw->phy.read_reg(hw, RTL_ANAR, + RTL_DEV_ZERO, &autoneg_reg); + autoneg_reg &= ~RTL_ANAR_100F; + autoneg_reg &= ~RTL_ANAR_100H; + hw->phy.write_reg(hw, RTL_ANAR, + RTL_DEV_ZERO, autoneg_reg); + } else { + hw->phy.read_reg(hw, RTL_ANAR, + RTL_DEV_ZERO, &autoneg_reg); + autoneg_reg |= RTL_ANAR_100F; + hw->phy.write_reg(hw, RTL_ANAR, + RTL_DEV_ZERO, autoneg_reg); + } + + if (!(speed & NGBE_LINK_SPEED_10M_FULL)) { + hw->phy.read_reg(hw, RTL_ANAR, + RTL_DEV_ZERO, &autoneg_reg); + autoneg_reg &= ~RTL_ANAR_10F; + autoneg_reg &= ~RTL_ANAR_10H; + hw->phy.write_reg(hw, RTL_ANAR, + RTL_DEV_ZERO, autoneg_reg); + } else { + hw->phy.read_reg(hw, RTL_ANAR, + RTL_DEV_ZERO, &autoneg_reg); + autoneg_reg |= RTL_ANAR_10F; + hw->phy.write_reg(hw, RTL_ANAR, + RTL_DEV_ZERO, autoneg_reg); + } + + /* restart AN and wait AN done interrupt */ + autoneg_reg = RTL_BMCR_RESTART_AN | RTL_BMCR_ANE; + hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, autoneg_reg); + + autoneg_reg = 0x205B; + hw->phy.write_reg(hw, RTL_LCR, 0xd04, autoneg_reg); + hw->phy.write_reg(hw, RTL_EEELCR, 0xd04, 0); + + hw->phy.read_reg(hw, RTL_LPCR, 0xd04, &autoneg_reg); + autoneg_reg = autoneg_reg & 0xFFFC; + autoneg_reg |= 0x2; + hw->phy.write_reg(hw, RTL_LPCR, 0xd04, autoneg_reg); + + return 0; +} + s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw) { UNREFERENCED_PARAMETER(hw); return 0; } +s32 ngbe_check_phy_link_rtl(struct ngbe_hw *hw, u32 *speed, bool *link_up) +{ + s32 status = 0; + u16 phy_link = 0; + u16 phy_speed = 0; + u16 phy_data = 0; + u16 insr = 0; + + DEBUGFUNC("ngbe_check_phy_link_rtl"); + + hw->phy.read_reg(hw, RTL_INSR, 0xa43, &insr); + + /* Initialize speed and link to default case */ + *link_up = false; + *speed = NGBE_LINK_SPEED_UNKNOWN; + + /* + * Check current speed and link status of the PHY register. + * This is a vendor specific register and may have to + * be changed for other copper PHYs. + */ + status = hw->phy.read_reg(hw, RTL_PHYSR, 0xa43, &phy_data); + phy_link = phy_data & RTL_PHYSR_RTLS; + phy_speed = phy_data & (RTL_PHYSR_SPEED_MASK | RTL_PHYSR_DP); + if (phy_link == RTL_PHYSR_RTLS) { + *link_up = true; + + if (phy_speed == (RTL_PHYSR_SPEED_1000M | RTL_PHYSR_DP)) + *speed = NGBE_LINK_SPEED_1GB_FULL; + else if (phy_speed == (RTL_PHYSR_SPEED_100M | RTL_PHYSR_DP)) + *speed = NGBE_LINK_SPEED_100M_FULL; + else if (phy_speed == (RTL_PHYSR_SPEED_10M | RTL_PHYSR_DP)) + *speed = NGBE_LINK_SPEED_10M_FULL; + } + + return status; +} + diff --git a/drivers/net/ngbe/base/ngbe_phy_rtl.h b/drivers/net/ngbe/base/ngbe_phy_rtl.h index ecb60b0ddd..e8bc4a1bd7 100644 --- a/drivers/net/ngbe/base/ngbe_phy_rtl.h +++ b/drivers/net/ngbe/base/ngbe_phy_rtl.h @@ -78,6 +78,10 @@ s32 ngbe_read_phy_reg_rtl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, s32 ngbe_write_phy_reg_rtl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data); +s32 ngbe_setup_phy_link_rtl(struct ngbe_hw *hw, + u32 speed, bool autoneg_wait_to_complete); s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw); +s32 ngbe_check_phy_link_rtl(struct ngbe_hw *hw, + u32 *speed, bool *link_up); #endif /* _NGBE_PHY_RTL_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.c b/drivers/net/ngbe/base/ngbe_phy_yt.c index 84b20de45c..f518dc0af6 100644 --- a/drivers/net/ngbe/base/ngbe_phy_yt.c +++ b/drivers/net/ngbe/base/ngbe_phy_yt.c @@ -78,6 +78,104 @@ s32 ngbe_write_phy_reg_ext_yt(struct ngbe_hw *hw, return 0; } +s32 ngbe_read_phy_reg_sds_ext_yt(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 *phy_data) +{ + ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, YT_SMI_PHY_SDS); + ngbe_read_phy_reg_ext_yt(hw, reg_addr, device_type, phy_data); + ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, 0); + + return 0; +} + +s32 ngbe_write_phy_reg_sds_ext_yt(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 phy_data) +{ + ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, YT_SMI_PHY_SDS); + ngbe_write_phy_reg_ext_yt(hw, reg_addr, device_type, phy_data); + ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, 0); + + return 0; +} + +s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed, + bool autoneg_wait_to_complete) +{ + u16 value_r4 = 0; + u16 value_r9 = 0; + u16 value; + + DEBUGFUNC("ngbe_setup_phy_link_yt"); + UNREFERENCED_PARAMETER(autoneg_wait_to_complete); + + hw->phy.autoneg_advertised = 0; + + if (hw->phy.type == ngbe_phy_yt8521s) { + /*disable 100/10base-T Self-negotiation ability*/ + hw->phy.read_reg(hw, YT_ANA, 0, &value); + value &= ~(YT_ANA_100BASET_FULL | YT_ANA_10BASET_FULL); + hw->phy.write_reg(hw, YT_ANA, 0, value); + + /*disable 1000base-T Self-negotiation ability*/ + hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value); + value &= ~YT_MS_1000BASET_FULL; + hw->phy.write_reg(hw, YT_MS_CTRL, 0, value); + + if (speed & NGBE_LINK_SPEED_1GB_FULL) { + hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL; + value_r9 |= YT_MS_1000BASET_FULL; + } + if (speed & NGBE_LINK_SPEED_100M_FULL) { + hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL; + value_r4 |= YT_ANA_100BASET_FULL; + } + if (speed & NGBE_LINK_SPEED_10M_FULL) { + hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL; + value_r4 |= YT_ANA_10BASET_FULL; + } + + /* enable 1000base-T Self-negotiation ability */ + hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value); + value |= value_r9; + hw->phy.write_reg(hw, YT_MS_CTRL, 0, value); + + /* enable 100/10base-T Self-negotiation ability */ + hw->phy.read_reg(hw, YT_ANA, 0, &value); + value |= value_r4; + hw->phy.write_reg(hw, YT_ANA, 0, value); + + /* software reset to make the above configuration take effect*/ + hw->phy.read_reg(hw, YT_BCR, 0, &value); + value |= YT_BCR_RESET; + hw->phy.write_reg(hw, YT_BCR, 0, value); + } else { + hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL; + + /* RGMII_Config1 : Config rx and tx training delay */ + value = YT_RGMII_CONF1_RXDELAY | + YT_RGMII_CONF1_TXDELAY_FE | + YT_RGMII_CONF1_TXDELAY; + ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value); + value = YT_CHIP_MODE_SEL(1) | + YT_CHIP_SW_LDO_EN | + YT_CHIP_SW_RST; + ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value); + + /* software reset */ + ngbe_write_phy_reg_sds_ext_yt(hw, 0x0, 0, 0x9140); + + /* power on phy */ + hw->phy.read_reg(hw, YT_BCR, 0, &value); + value &= ~YT_BCR_PWDN; + hw->phy.write_reg(hw, YT_BCR, 0, value); + } + + ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0); + ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &value); + + return 0; +} + s32 ngbe_reset_phy_yt(struct ngbe_hw *hw) { u32 i; @@ -110,3 +208,39 @@ s32 ngbe_reset_phy_yt(struct ngbe_hw *hw) return status; } +s32 ngbe_check_phy_link_yt(struct ngbe_hw *hw, + u32 *speed, bool *link_up) +{ + s32 status = 0; + u16 phy_link = 0; + u16 phy_speed = 0; + u16 phy_data = 0; + u16 insr = 0; + + DEBUGFUNC("ngbe_check_phy_link_yt"); + + /* Initialize speed and link to default case */ + *link_up = false; + *speed = NGBE_LINK_SPEED_UNKNOWN; + + ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0); + ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &insr); + + status = hw->phy.read_reg(hw, YT_SPST, 0, &phy_data); + phy_link = phy_data & YT_SPST_LINK; + phy_speed = phy_data & YT_SPST_SPEED_MASK; + + if (phy_link) { + *link_up = true; + + if (phy_speed == YT_SPST_SPEED_1000M) + *speed = NGBE_LINK_SPEED_1GB_FULL; + else if (phy_speed == YT_SPST_SPEED_100M) + *speed = NGBE_LINK_SPEED_100M_FULL; + else if (phy_speed == YT_SPST_SPEED_10M) + *speed = NGBE_LINK_SPEED_10M_FULL; + } + + return status; +} + diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.h b/drivers/net/ngbe/base/ngbe_phy_yt.h index 03b53ece86..26820ecb92 100644 --- a/drivers/net/ngbe/base/ngbe_phy_yt.h +++ b/drivers/net/ngbe/base/ngbe_phy_yt.h @@ -26,6 +26,7 @@ /* MII common registers in UTP and SDS */ #define YT_BCR 0x0 #define YT_BCR_RESET MS16(15, 0x1) +#define YT_BCR_PWDN MS16(11, 0x1) #define YT_ANA 0x4 /* copper */ #define YT_ANA_100BASET_FULL MS16(8, 0x1) @@ -60,7 +61,15 @@ s32 ngbe_read_phy_reg_ext_yt(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, u16 *phy_data); s32 ngbe_write_phy_reg_ext_yt(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data); +s32 ngbe_read_phy_reg_sds_ext_yt(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 *phy_data); +s32 ngbe_write_phy_reg_sds_ext_yt(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 phy_data); s32 ngbe_reset_phy_yt(struct ngbe_hw *hw); +s32 ngbe_check_phy_link_yt(struct ngbe_hw *hw, + u32 *speed, bool *link_up); +s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, + u32 speed, bool autoneg_wait_to_complete); #endif /* _NGBE_PHY_YT_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h index d05d2ff28a..bc99d9c3db 100644 --- a/drivers/net/ngbe/base/ngbe_type.h +++ b/drivers/net/ngbe/base/ngbe_type.h @@ -6,6 +6,8 @@ #ifndef _NGBE_TYPE_H_ #define _NGBE_TYPE_H_ +#define NGBE_LINK_UP_TIME 90 /* 9.0 Seconds */ + #define NGBE_FRAME_SIZE_DFT (1522) /* Default frame size, +FCS */ #define NGBE_ALIGN 128 /* as intel did */ @@ -96,6 +98,8 @@ struct ngbe_mac_info { s32 (*acquire_swfw_sync)(struct ngbe_hw *hw, u32 mask); void (*release_swfw_sync)(struct ngbe_hw *hw, u32 mask); + s32 (*setup_link)(struct ngbe_hw *hw, u32 speed, + bool autoneg_wait_to_complete); s32 (*check_link)(struct ngbe_hw *hw, u32 *speed, bool *link_up, bool link_up_wait_to_complete); /* RAR */ @@ -121,6 +125,7 @@ struct ngbe_mac_info { bool get_link_status; struct ngbe_thermal_sensor_data thermal_sensor_data; bool set_lben; + u32 max_link_up_time; }; struct ngbe_phy_info { @@ -134,6 +139,9 @@ struct ngbe_phy_info { u32 device_type, u16 *phy_data); s32 (*write_reg_unlocked)(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data); + s32 (*setup_link)(struct ngbe_hw *hw, u32 speed, + bool autoneg_wait_to_complete); + s32 (*check_link)(struct ngbe_hw *hw, u32 *speed, bool *link_up); enum ngbe_media_type media_type; enum ngbe_phy_type type; @@ -142,6 +150,7 @@ struct ngbe_phy_info { u32 revision; u32 phy_semaphore_mask; bool reset_disable; + u32 autoneg_advertised; }; enum ngbe_isb_idx { From patchwork Wed Jun 2 09:40:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93776 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 89BF2A0524; Wed, 2 Jun 2021 11:41:27 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E88914115E; Wed, 2 Jun 2021 11:39:58 +0200 (CEST) Received: from smtpproxy21.qq.com (smtpbg704.qq.com [203.205.195.105]) by mails.dpdk.org (Postfix) with ESMTP id 6D54D4114F for ; Wed, 2 Jun 2021 11:39:57 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626793tuf91une Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:53 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: mJG+EqVdzGCmdd4hlPiR1rCmce81bDM0XFlJnEJFe1oeRxrvMMvIKo+SMM6R3 EwirAS82e+tOE9ufHDnDHjEMM/+f+pfDTN2VdoVZN1QwAEpFXpUVAwF8knKBHTXqroe1tjC oVzuA6xZnJnkq4RiwUtBrReon8ioo4KzQ/pMQ0DW/A1PjejVGm928HrNc8vqpC43tolgdGj fZgGJYJPa2Nm2sqruW3xhPuey/BiBjqr9+IrV7pZ/Pxjt0vemOhqhqlWf0z/aiGt2kc9X// 9s3Dh5wX20ITJ/mKg5vTgw27VX0E8kZBXiaBPr0nwZc6GwXJk61AE/wevO3lt6UxgSzftak WzlDN6+RymhP/XsEXqvPqqoL1ob1g== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:40:59 +0800 Message-Id: <20210602094108.1575640-16-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign7 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 15/24] net/ngbe: add Rx queue setup and release 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 Sender: "dev" Setup device Rx queue and release Rx queue. Signed-off-by: Jiawen Wu --- drivers/net/ngbe/ngbe_ethdev.c | 9 + drivers/net/ngbe/ngbe_ethdev.h | 8 + drivers/net/ngbe/ngbe_rxtx.c | 305 +++++++++++++++++++++++++++++++++ drivers/net/ngbe/ngbe_rxtx.h | 90 ++++++++++ 4 files changed, 412 insertions(+) diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 97b6de3aa4..8eb41a7a2b 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -262,12 +262,19 @@ static int ngbe_dev_configure(struct rte_eth_dev *dev) { struct ngbe_interrupt *intr = NGBE_DEV_INTR(dev); + struct ngbe_adapter *adapter = NGBE_DEV_ADAPTER(dev); PMD_INIT_FUNC_TRACE(); /* set flag to update link status after init */ intr->flags |= NGBE_FLAG_NEED_LINK_UPDATE; + /* + * Initialize to TRUE. If any of Rx queues doesn't meet the bulk + * allocation Rx preconditions we will reset it. + */ + adapter->rx_bulk_alloc_allowed = true; + return 0; } @@ -654,6 +661,8 @@ static const struct eth_dev_ops ngbe_eth_dev_ops = { .dev_configure = ngbe_dev_configure, .dev_infos_get = ngbe_dev_info_get, .link_update = ngbe_dev_link_update, + .rx_queue_setup = ngbe_dev_rx_queue_setup, + .rx_queue_release = ngbe_dev_rx_queue_release, }; RTE_PMD_REGISTER_PCI(net_ngbe, rte_ngbe_pmd); diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h index 10c23c41d1..c324ca7e0f 100644 --- a/drivers/net/ngbe/ngbe_ethdev.h +++ b/drivers/net/ngbe/ngbe_ethdev.h @@ -43,6 +43,7 @@ struct ngbe_interrupt { struct ngbe_adapter { struct ngbe_hw hw; struct ngbe_interrupt intr; + bool rx_bulk_alloc_allowed; }; #define NGBE_DEV_ADAPTER(dev) \ @@ -54,6 +55,13 @@ struct ngbe_adapter { #define NGBE_DEV_INTR(dev) \ (&((struct ngbe_adapter *)(dev)->data->dev_private)->intr) +void ngbe_dev_rx_queue_release(void *rxq); + +int ngbe_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, + uint16_t nb_rx_desc, unsigned int socket_id, + const struct rte_eth_rxconf *rx_conf, + struct rte_mempool *mb_pool); + int ngbe_dev_link_update_share(struct rte_eth_dev *dev, int wait_to_complete); diff --git a/drivers/net/ngbe/ngbe_rxtx.c b/drivers/net/ngbe/ngbe_rxtx.c index ae24367b18..9992983bef 100644 --- a/drivers/net/ngbe/ngbe_rxtx.c +++ b/drivers/net/ngbe/ngbe_rxtx.c @@ -3,9 +3,14 @@ * Copyright(c) 2010-2017 Intel Corporation */ +#include + #include #include +#include +#include +#include "ngbe_logs.h" #include "base/ngbe.h" #include "ngbe_ethdev.h" #include "ngbe_rxtx.h" @@ -37,6 +42,166 @@ ngbe_get_tx_port_offloads(struct rte_eth_dev *dev) return tx_offload_capa; } +/** + * ngbe_free_sc_cluster - free the not-yet-completed scattered cluster + * + * The "next" pointer of the last segment of (not-yet-completed) RSC clusters + * in the sw_rsc_ring is not set to NULL but rather points to the next + * mbuf of this RSC aggregation (that has not been completed yet and still + * resides on the HW ring). So, instead of calling for rte_pktmbuf_free() we + * will just free first "nb_segs" segments of the cluster explicitly by calling + * an rte_pktmbuf_free_seg(). + * + * @m scattered cluster head + */ +static void __rte_cold +ngbe_free_sc_cluster(struct rte_mbuf *m) +{ + uint16_t i, nb_segs = m->nb_segs; + struct rte_mbuf *next_seg; + + for (i = 0; i < nb_segs; i++) { + next_seg = m->next; + rte_pktmbuf_free_seg(m); + m = next_seg; + } +} + +static void __rte_cold +ngbe_rx_queue_release_mbufs(struct ngbe_rx_queue *rxq) +{ + unsigned int i; + + if (rxq->sw_ring != NULL) { + for (i = 0; i < rxq->nb_rx_desc; i++) { + if (rxq->sw_ring[i].mbuf != NULL) { + rte_pktmbuf_free_seg(rxq->sw_ring[i].mbuf); + rxq->sw_ring[i].mbuf = NULL; + } + } + if (rxq->rx_nb_avail) { + for (i = 0; i < rxq->rx_nb_avail; ++i) { + struct rte_mbuf *mb; + + mb = rxq->rx_stage[rxq->rx_next_avail + i]; + rte_pktmbuf_free_seg(mb); + } + rxq->rx_nb_avail = 0; + } + } + + if (rxq->sw_sc_ring) + for (i = 0; i < rxq->nb_rx_desc; i++) + if (rxq->sw_sc_ring[i].fbuf) { + ngbe_free_sc_cluster(rxq->sw_sc_ring[i].fbuf); + rxq->sw_sc_ring[i].fbuf = NULL; + } +} + +static void __rte_cold +ngbe_rx_queue_release(struct ngbe_rx_queue *rxq) +{ + if (rxq != NULL) { + ngbe_rx_queue_release_mbufs(rxq); + rte_free(rxq->sw_ring); + rte_free(rxq->sw_sc_ring); + rte_free(rxq); + } +} + +void __rte_cold +ngbe_dev_rx_queue_release(void *rxq) +{ + ngbe_rx_queue_release(rxq); +} + +/* + * Check if Rx Burst Bulk Alloc function can be used. + * Return + * 0: the preconditions are satisfied and the bulk allocation function + * can be used. + * -EINVAL: the preconditions are NOT satisfied and the default Rx burst + * function must be used. + */ +static inline int __rte_cold +check_rx_burst_bulk_alloc_preconditions(struct ngbe_rx_queue *rxq) +{ + int ret = 0; + + /* + * Make sure the following pre-conditions are satisfied: + * rxq->rx_free_thresh >= RTE_PMD_NGBE_RX_MAX_BURST + * rxq->rx_free_thresh < rxq->nb_rx_desc + * (rxq->nb_rx_desc % rxq->rx_free_thresh) == 0 + * Scattered packets are not supported. This should be checked + * outside of this function. + */ + if (!(rxq->rx_free_thresh >= RTE_PMD_NGBE_RX_MAX_BURST)) { + PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions: " + "rxq->rx_free_thresh=%d, " + "RTE_PMD_NGBE_RX_MAX_BURST=%d", + rxq->rx_free_thresh, RTE_PMD_NGBE_RX_MAX_BURST); + ret = -EINVAL; + } else if (!(rxq->rx_free_thresh < rxq->nb_rx_desc)) { + PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions: " + "rxq->rx_free_thresh=%d, " + "rxq->nb_rx_desc=%d", + rxq->rx_free_thresh, rxq->nb_rx_desc); + ret = -EINVAL; + } else if (!((rxq->nb_rx_desc % rxq->rx_free_thresh) == 0)) { + PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions: " + "rxq->nb_rx_desc=%d, " + "rxq->rx_free_thresh=%d", + rxq->nb_rx_desc, rxq->rx_free_thresh); + ret = -EINVAL; + } + + return ret; +} + +/* Reset dynamic ngbe_rx_queue fields back to defaults */ +static void __rte_cold +ngbe_reset_rx_queue(struct ngbe_adapter *adapter, struct ngbe_rx_queue *rxq) +{ + static const struct ngbe_rx_desc zeroed_desc = { + {{0}, {0} }, {{0}, {0} } }; + unsigned int i; + uint16_t len = rxq->nb_rx_desc; + + /* + * By default, the Rx queue setup function allocates enough memory for + * NGBE_RING_DESC_MAX. The Rx Burst bulk allocation function requires + * extra memory at the end of the descriptor ring to be zero'd out. + */ + if (adapter->rx_bulk_alloc_allowed) + /* zero out extra memory */ + len += RTE_PMD_NGBE_RX_MAX_BURST; + + /* + * Zero out HW ring memory. Zero out extra memory at the end of + * the H/W ring so look-ahead logic in Rx Burst bulk alloc function + * reads extra memory as zeros. + */ + for (i = 0; i < len; i++) + rxq->rx_ring[i] = zeroed_desc; + + /* + * initialize extra software ring entries. Space for these extra + * entries is always allocated + */ + memset(&rxq->fake_mbuf, 0x0, sizeof(rxq->fake_mbuf)); + for (i = rxq->nb_rx_desc; i < len; ++i) + rxq->sw_ring[i].mbuf = &rxq->fake_mbuf; + + rxq->rx_nb_avail = 0; + rxq->rx_next_avail = 0; + rxq->rx_free_trigger = (uint16_t)(rxq->rx_free_thresh - 1); + rxq->rx_tail = 0; + rxq->nb_rx_hold = 0; + rxq->pkt_first_seg = NULL; + rxq->pkt_last_seg = NULL; +} + uint64_t ngbe_get_rx_queue_offloads(struct rte_eth_dev *dev __rte_unused) { @@ -65,3 +230,143 @@ ngbe_get_rx_port_offloads(struct rte_eth_dev *dev) return offloads; } +int __rte_cold +ngbe_dev_rx_queue_setup(struct rte_eth_dev *dev, + uint16_t queue_idx, + uint16_t nb_desc, + unsigned int socket_id, + const struct rte_eth_rxconf *rx_conf, + struct rte_mempool *mp) +{ + const struct rte_memzone *rz; + struct ngbe_rx_queue *rxq; + struct ngbe_hw *hw; + uint16_t len; + struct ngbe_adapter *adapter = NGBE_DEV_ADAPTER(dev); + uint64_t offloads; + + PMD_INIT_FUNC_TRACE(); + hw = NGBE_DEV_HW(dev); + + offloads = rx_conf->offloads | dev->data->dev_conf.rxmode.offloads; + + /* + * Validate number of receive descriptors. + * It must not exceed hardware maximum, and must be multiple + * of NGBE_ALIGN. + */ + if (nb_desc % NGBE_RXD_ALIGN != 0 || + nb_desc > NGBE_RING_DESC_MAX || + nb_desc < NGBE_RING_DESC_MIN) { + return -EINVAL; + } + + /* Free memory prior to re-allocation if needed... */ + if (dev->data->rx_queues[queue_idx] != NULL) { + ngbe_rx_queue_release(dev->data->rx_queues[queue_idx]); + dev->data->rx_queues[queue_idx] = NULL; + } + + /* First allocate the rx queue data structure */ + rxq = rte_zmalloc_socket("ethdev RX queue", + sizeof(struct ngbe_rx_queue), + RTE_CACHE_LINE_SIZE, socket_id); + if (rxq == NULL) + return -ENOMEM; + rxq->mb_pool = mp; + rxq->nb_rx_desc = nb_desc; + rxq->rx_free_thresh = rx_conf->rx_free_thresh; + rxq->queue_id = queue_idx; + rxq->reg_idx = queue_idx; + rxq->port_id = dev->data->port_id; + if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_KEEP_CRC) + rxq->crc_len = RTE_ETHER_CRC_LEN; + else + rxq->crc_len = 0; + rxq->drop_en = rx_conf->rx_drop_en; + rxq->rx_deferred_start = rx_conf->rx_deferred_start; + rxq->offloads = offloads; + rxq->pkt_type_mask = NGBE_PTID_MASK; + + /* + * Allocate RX ring hardware descriptors. A memzone large enough to + * handle the maximum ring size is allocated in order to allow for + * resizing in later calls to the queue setup function. + */ + rz = rte_eth_dma_zone_reserve(dev, "rx_ring", queue_idx, + RX_RING_SZ, NGBE_ALIGN, socket_id); + if (rz == NULL) { + ngbe_rx_queue_release(rxq); + return -ENOMEM; + } + + /* + * Zero init all the descriptors in the ring. + */ + memset(rz->addr, 0, RX_RING_SZ); + + rxq->rdt_reg_addr = NGBE_REG_ADDR(hw, NGBE_RXWP(rxq->reg_idx)); + rxq->rdh_reg_addr = NGBE_REG_ADDR(hw, NGBE_RXRP(rxq->reg_idx)); + + rxq->rx_ring_phys_addr = TMZ_PADDR(rz); + rxq->rx_ring = (struct ngbe_rx_desc *)TMZ_VADDR(rz); + + /* + * Certain constraints must be met in order to use the bulk buffer + * allocation Rx burst function. If any of Rx queues doesn't meet them + * the feature should be disabled for the whole port. + */ + if (check_rx_burst_bulk_alloc_preconditions(rxq)) { + PMD_INIT_LOG(DEBUG, "queue[%d] doesn't meet Rx Bulk Alloc " + "preconditions - canceling the feature for " + "the whole port[%d]", + rxq->queue_id, rxq->port_id); + adapter->rx_bulk_alloc_allowed = false; + } + + /* + * Allocate software ring. Allow for space at the end of the + * S/W ring to make sure look-ahead logic in bulk alloc Rx burst + * function does not access an invalid memory region. + */ + len = nb_desc; + if (adapter->rx_bulk_alloc_allowed) + len += RTE_PMD_NGBE_RX_MAX_BURST; + + rxq->sw_ring = rte_zmalloc_socket("rxq->sw_ring", + sizeof(struct ngbe_rx_entry) * len, + RTE_CACHE_LINE_SIZE, socket_id); + if (!rxq->sw_ring) { + ngbe_rx_queue_release(rxq); + return -ENOMEM; + } + + /* + * Always allocate even if it's not going to be needed in order to + * simplify the code. + * + * This ring is used in Scattered Rx cases and Scattered Rx may + * be requested in ngbe_dev_rx_init(), which is called later from + * dev_start() flow. + */ + rxq->sw_sc_ring = + rte_zmalloc_socket("rxq->sw_sc_ring", + sizeof(struct ngbe_scattered_rx_entry) * len, + RTE_CACHE_LINE_SIZE, socket_id); + if (!rxq->sw_sc_ring) { + ngbe_rx_queue_release(rxq); + return -ENOMEM; + } + + PMD_INIT_LOG(DEBUG, "sw_ring=%p sw_sc_ring=%p hw_ring=%p " + "dma_addr=0x%" PRIx64, + rxq->sw_ring, rxq->sw_sc_ring, rxq->rx_ring, + rxq->rx_ring_phys_addr); + + dev->data->rx_queues[queue_idx] = rxq; + + ngbe_reset_rx_queue(adapter, rxq); + + return 0; +} + diff --git a/drivers/net/ngbe/ngbe_rxtx.h b/drivers/net/ngbe/ngbe_rxtx.h index 39011ee286..e1676a53b4 100644 --- a/drivers/net/ngbe/ngbe_rxtx.h +++ b/drivers/net/ngbe/ngbe_rxtx.h @@ -6,7 +6,97 @@ #ifndef _NGBE_RXTX_H_ #define _NGBE_RXTX_H_ +/***************************************************************************** + * Receive Descriptor + *****************************************************************************/ +struct ngbe_rx_desc { + struct { + union { + __le32 dw0; + struct { + __le16 pkt; + __le16 hdr; + } lo; + }; + union { + __le32 dw1; + struct { + __le16 ipid; + __le16 csum; + } hi; + }; + } qw0; /* also as r.pkt_addr */ + struct { + union { + __le32 dw2; + struct { + __le32 status; + } lo; + }; + union { + __le32 dw3; + struct { + __le16 len; + __le16 tag; + } hi; + }; + } qw1; /* also as r.hdr_addr */ +}; + +#define RTE_PMD_NGBE_RX_MAX_BURST 32 + +#define RX_RING_SZ ((NGBE_RING_DESC_MAX + RTE_PMD_NGBE_RX_MAX_BURST) * \ + sizeof(struct ngbe_rx_desc)) + #define NGBE_TX_MAX_SEG 40 +#define NGBE_PTID_MASK 0xFF + +/** + * Structure associated with each descriptor of the RX ring of a RX queue. + */ +struct ngbe_rx_entry { + struct rte_mbuf *mbuf; /**< mbuf associated with RX descriptor. */ +}; + +struct ngbe_scattered_rx_entry { + struct rte_mbuf *fbuf; /**< First segment of the fragmented packet. */ +}; + +/** + * Structure associated with each RX queue. + */ +struct ngbe_rx_queue { + struct rte_mempool *mb_pool; /**< mbuf pool to populate RX ring. */ + volatile struct ngbe_rx_desc *rx_ring; /**< RX ring virtual address. */ + uint64_t rx_ring_phys_addr; /**< RX ring DMA address. */ + volatile uint32_t *rdt_reg_addr; /**< RDT register address. */ + volatile uint32_t *rdh_reg_addr; /**< RDH register address. */ + struct ngbe_rx_entry *sw_ring; /**< address of RX software ring. */ + /**< address of scattered Rx software ring. */ + struct ngbe_scattered_rx_entry *sw_sc_ring; + struct rte_mbuf *pkt_first_seg; /**< First segment of current packet. */ + struct rte_mbuf *pkt_last_seg; /**< Last segment of current packet. */ + uint16_t nb_rx_desc; /**< number of RX descriptors. */ + uint16_t rx_tail; /**< current value of RDT register. */ + uint16_t nb_rx_hold; /**< number of held free RX desc. */ + uint16_t rx_nb_avail; /**< nr of staged pkts ready to ret to app */ + uint16_t rx_next_avail; /**< idx of next staged pkt to ret to app */ + uint16_t rx_free_trigger; /**< triggers rx buffer allocation */ + uint16_t rx_free_thresh; /**< max free RX desc to hold. */ + uint16_t queue_id; /**< RX queue index. */ + uint16_t reg_idx; /**< RX queue register index. */ + /**< Packet type mask for different NICs. */ + uint16_t pkt_type_mask; + uint16_t port_id; /**< Device port identifier. */ + uint8_t crc_len; /**< 0 if CRC stripped, 4 otherwise. */ + uint8_t drop_en; /**< If not 0, set SRRCTL.Drop_En. */ + uint8_t rx_deferred_start; /**< not in global dev start. */ + uint64_t offloads; /**< Rx offloads with DEV_RX_OFFLOAD_* */ + /** need to alloc dummy mbuf, for wraparound when scanning hw ring */ + struct rte_mbuf fake_mbuf; + /** hold packets to return to application */ + struct rte_mbuf *rx_stage[RTE_PMD_NGBE_RX_MAX_BURST * 2]; +}; uint64_t ngbe_get_tx_port_offloads(struct rte_eth_dev *dev); uint64_t ngbe_get_rx_queue_offloads(struct rte_eth_dev *dev); From patchwork Wed Jun 2 09:41:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93778 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 A0CBDA0524; Wed, 2 Jun 2021 11:41:41 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 657E141174; Wed, 2 Jun 2021 11:40:02 +0200 (CEST) Received: from smtpbgsg2.qq.com (smtpbgsg2.qq.com [54.254.200.128]) by mails.dpdk.org (Postfix) with ESMTP id 8A1A341173 for ; Wed, 2 Jun 2021 11:40:00 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626795tds8cmin Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:55 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: i7ScvpL4pspgpo887IbfI/j7KPm/myJgSz//zQi3pcgD/fUpcBA21klQ5p7Ax KVBVQsKg2XnKWbF7fTN8+SmD31R1iKRcfRFu062fhrd9sOY1lGQCC+JD62+LmkSMvBIUCaA y8F7de7L9zKlq8Xpe8ZfZF2AesGogWvA+lZayjVmC6TmCPCwAjKfgE0eq3BcwTKbkeNcnof SHOOhqG9TF8EPjomRbJs2od8EK5kHvEHelvYeSvvRdYaE0u7/uFzCHiWImR7d2sEaykkRua vKWhKVWyDh45IA5HsZQH869qWPZaytLpR1R/LBsSVnVqBVPAMaNxnCtNIqqaUKniEAALZsl x0K//5DIPFovYmJgQYR5QT+TBZn3w== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:41:00 +0800 Message-Id: <20210602094108.1575640-17-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign6 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 16/24] net/ngbe: add Tx queue setup and release 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 Sender: "dev" Setup device Tx queue and release Tx queue. Signed-off-by: Jiawen Wu --- drivers/net/ngbe/ngbe_ethdev.c | 2 + drivers/net/ngbe/ngbe_ethdev.h | 6 + drivers/net/ngbe/ngbe_rxtx.c | 212 +++++++++++++++++++++++++++++++++ drivers/net/ngbe/ngbe_rxtx.h | 91 ++++++++++++++ 4 files changed, 311 insertions(+) diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 8eb41a7a2b..2f8ac48f33 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -663,6 +663,8 @@ static const struct eth_dev_ops ngbe_eth_dev_ops = { .link_update = ngbe_dev_link_update, .rx_queue_setup = ngbe_dev_rx_queue_setup, .rx_queue_release = ngbe_dev_rx_queue_release, + .tx_queue_setup = ngbe_dev_tx_queue_setup, + .tx_queue_release = ngbe_dev_tx_queue_release, }; RTE_PMD_REGISTER_PCI(net_ngbe, rte_ngbe_pmd); diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h index c324ca7e0f..f52d813a47 100644 --- a/drivers/net/ngbe/ngbe_ethdev.h +++ b/drivers/net/ngbe/ngbe_ethdev.h @@ -57,11 +57,17 @@ struct ngbe_adapter { void ngbe_dev_rx_queue_release(void *rxq); +void ngbe_dev_tx_queue_release(void *txq); + int ngbe_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, uint16_t nb_rx_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool); +int ngbe_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, + uint16_t nb_tx_desc, unsigned int socket_id, + const struct rte_eth_txconf *tx_conf); + int ngbe_dev_link_update_share(struct rte_eth_dev *dev, int wait_to_complete); diff --git a/drivers/net/ngbe/ngbe_rxtx.c b/drivers/net/ngbe/ngbe_rxtx.c index 9992983bef..2d8db3245f 100644 --- a/drivers/net/ngbe/ngbe_rxtx.c +++ b/drivers/net/ngbe/ngbe_rxtx.c @@ -15,6 +15,99 @@ #include "ngbe_ethdev.h" #include "ngbe_rxtx.h" +#ifndef DEFAULT_TX_FREE_THRESH +#define DEFAULT_TX_FREE_THRESH 32 +#endif + +/********************************************************************* + * + * Queue management functions + * + **********************************************************************/ + +static void __rte_cold +ngbe_tx_queue_release_mbufs(struct ngbe_tx_queue *txq) +{ + unsigned int i; + + if (txq->sw_ring != NULL) { + for (i = 0; i < txq->nb_tx_desc; i++) { + if (txq->sw_ring[i].mbuf != NULL) { + rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf); + txq->sw_ring[i].mbuf = NULL; + } + } + } +} + +static void __rte_cold +ngbe_tx_free_swring(struct ngbe_tx_queue *txq) +{ + if (txq != NULL && + txq->sw_ring != NULL) + rte_free(txq->sw_ring); +} + +static void __rte_cold +ngbe_tx_queue_release(struct ngbe_tx_queue *txq) +{ + if (txq != NULL && txq->ops != NULL) { + txq->ops->release_mbufs(txq); + txq->ops->free_swring(txq); + rte_free(txq); + } +} + +void __rte_cold +ngbe_dev_tx_queue_release(void *txq) +{ + ngbe_tx_queue_release(txq); +} + +/* (Re)set dynamic ngbe_tx_queue fields to defaults */ +static void __rte_cold +ngbe_reset_tx_queue(struct ngbe_tx_queue *txq) +{ + static const struct ngbe_tx_desc zeroed_desc = {0}; + struct ngbe_tx_entry *txe = txq->sw_ring; + uint16_t prev, i; + + /* Zero out HW ring memory */ + for (i = 0; i < txq->nb_tx_desc; i++) + txq->tx_ring[i] = zeroed_desc; + + /* Initialize SW ring entries */ + prev = (uint16_t)(txq->nb_tx_desc - 1); + for (i = 0; i < txq->nb_tx_desc; i++) { + volatile struct ngbe_tx_desc *txd = &txq->tx_ring[i]; + + txd->dw3 = rte_cpu_to_le_32(NGBE_TXD_DD); + txe[i].mbuf = NULL; + txe[i].last_id = i; + txe[prev].next_id = i; + prev = i; + } + + txq->tx_next_dd = (uint16_t)(txq->tx_free_thresh - 1); + txq->tx_tail = 0; + + /* + * Always allow 1 descriptor to be un-allocated to avoid + * a H/W race condition + */ + txq->last_desc_cleaned = (uint16_t)(txq->nb_tx_desc - 1); + txq->nb_tx_free = (uint16_t)(txq->nb_tx_desc - 1); + txq->ctx_curr = 0; + memset((void *)&txq->ctx_cache, 0, + NGBE_CTX_NUM * sizeof(struct ngbe_ctx_info)); +} + +static const struct ngbe_txq_ops def_txq_ops = { + .release_mbufs = ngbe_tx_queue_release_mbufs, + .free_swring = ngbe_tx_free_swring, + .reset = ngbe_reset_tx_queue, +}; + uint64_t ngbe_get_tx_port_offloads(struct rte_eth_dev *dev) { @@ -42,6 +135,125 @@ ngbe_get_tx_port_offloads(struct rte_eth_dev *dev) return tx_offload_capa; } +int __rte_cold +ngbe_dev_tx_queue_setup(struct rte_eth_dev *dev, + uint16_t queue_idx, + uint16_t nb_desc, + unsigned int socket_id, + const struct rte_eth_txconf *tx_conf) +{ + const struct rte_memzone *tz; + struct ngbe_tx_queue *txq; + struct ngbe_hw *hw; + uint16_t tx_free_thresh; + uint64_t offloads; + + PMD_INIT_FUNC_TRACE(); + hw = NGBE_DEV_HW(dev); + + offloads = tx_conf->offloads | dev->data->dev_conf.txmode.offloads; + + /* + * Validate number of transmit descriptors. + * It must not exceed hardware maximum, and must be multiple + * of NGBE_ALIGN. + */ + if (nb_desc % NGBE_TXD_ALIGN != 0 || + nb_desc > NGBE_RING_DESC_MAX || + nb_desc < NGBE_RING_DESC_MIN) { + return -EINVAL; + } + + /* + * The TX descriptor ring will be cleaned after txq->tx_free_thresh + * descriptors are used or if the number of descriptors required + * to transmit a packet is greater than the number of free TX + * descriptors. + * One descriptor in the TX ring is used as a sentinel to avoid a + * H/W race condition, hence the maximum threshold constraints. + * When set to zero use default values. + */ + tx_free_thresh = (uint16_t)((tx_conf->tx_free_thresh) ? + tx_conf->tx_free_thresh : DEFAULT_TX_FREE_THRESH); + if (tx_free_thresh >= (nb_desc - 3)) { + PMD_INIT_LOG(ERR, "tx_free_thresh must be less than the number of " + "TX descriptors minus 3. (tx_free_thresh=%u " + "port=%d queue=%d)", + (unsigned int)tx_free_thresh, + (int)dev->data->port_id, (int)queue_idx); + return -(EINVAL); + } + + if ((nb_desc % tx_free_thresh) != 0) { + PMD_INIT_LOG(ERR, "tx_free_thresh must be a divisor of the " + "number of TX descriptors. (tx_free_thresh=%u " + "port=%d queue=%d)", (unsigned int)tx_free_thresh, + (int)dev->data->port_id, (int)queue_idx); + return -(EINVAL); + } + + /* Free memory prior to re-allocation if needed... */ + if (dev->data->tx_queues[queue_idx] != NULL) { + ngbe_tx_queue_release(dev->data->tx_queues[queue_idx]); + dev->data->tx_queues[queue_idx] = NULL; + } + + /* First allocate the tx queue data structure */ + txq = rte_zmalloc_socket("ethdev TX queue", + sizeof(struct ngbe_tx_queue), + RTE_CACHE_LINE_SIZE, socket_id); + if (txq == NULL) + return -ENOMEM; + + /* + * Allocate TX ring hardware descriptors. A memzone large enough to + * handle the maximum ring size is allocated in order to allow for + * resizing in later calls to the queue setup function. + */ + tz = rte_eth_dma_zone_reserve(dev, "tx_ring", queue_idx, + sizeof(struct ngbe_tx_desc) * NGBE_RING_DESC_MAX, + NGBE_ALIGN, socket_id); + if (tz == NULL) { + ngbe_tx_queue_release(txq); + return -ENOMEM; + } + + txq->nb_tx_desc = nb_desc; + txq->tx_free_thresh = tx_free_thresh; + txq->pthresh = tx_conf->tx_thresh.pthresh; + txq->hthresh = tx_conf->tx_thresh.hthresh; + txq->wthresh = tx_conf->tx_thresh.wthresh; + txq->queue_id = queue_idx; + txq->reg_idx = queue_idx; + txq->port_id = dev->data->port_id; + txq->offloads = offloads; + txq->ops = &def_txq_ops; + txq->tx_deferred_start = tx_conf->tx_deferred_start; + + txq->tdt_reg_addr = NGBE_REG_ADDR(hw, NGBE_TXWP(txq->reg_idx)); + txq->tdc_reg_addr = NGBE_REG_ADDR(hw, NGBE_TXCFG(txq->reg_idx)); + + txq->tx_ring_phys_addr = TMZ_PADDR(tz); + txq->tx_ring = (struct ngbe_tx_desc *)TMZ_VADDR(tz); + + /* Allocate software ring */ + txq->sw_ring = rte_zmalloc_socket("txq->sw_ring", + sizeof(struct ngbe_tx_entry) * nb_desc, + RTE_CACHE_LINE_SIZE, socket_id); + if (txq->sw_ring == NULL) { + ngbe_tx_queue_release(txq); + return -ENOMEM; + } + PMD_INIT_LOG(DEBUG, "sw_ring=%p hw_ring=%p dma_addr=0x%" PRIx64, + txq->sw_ring, txq->tx_ring, txq->tx_ring_phys_addr); + + txq->ops->reset(txq); + + dev->data->tx_queues[queue_idx] = txq; + + return 0; +} + /** * ngbe_free_sc_cluster - free the not-yet-completed scattered cluster * diff --git a/drivers/net/ngbe/ngbe_rxtx.h b/drivers/net/ngbe/ngbe_rxtx.h index e1676a53b4..2db5cc3f2a 100644 --- a/drivers/net/ngbe/ngbe_rxtx.h +++ b/drivers/net/ngbe/ngbe_rxtx.h @@ -43,6 +43,31 @@ struct ngbe_rx_desc { } qw1; /* also as r.hdr_addr */ }; +/***************************************************************************** + * Transmit Descriptor + *****************************************************************************/ +/** + * Transmit Context Descriptor (NGBE_TXD_TYP=CTXT) + **/ +struct ngbe_tx_ctx_desc { + __le32 dw0; /* w.vlan_macip_lens */ + __le32 dw1; /* w.seqnum_seed */ + __le32 dw2; /* w.type_tucmd_mlhl */ + __le32 dw3; /* w.mss_l4len_idx */ +}; + +/* @ngbe_tx_ctx_desc.dw3 */ +#define NGBE_TXD_DD MS(0, 0x1) /* descriptor done */ + +/** + * Transmit Data Descriptor (NGBE_TXD_TYP=DATA) + **/ +struct ngbe_tx_desc { + __le64 qw0; /* r.buffer_addr , w.reserved */ + __le32 dw2; /* r.cmd_type_len, w.nxtseq_seed */ + __le32 dw3; /* r.olinfo_status, w.status */ +}; + #define RTE_PMD_NGBE_RX_MAX_BURST 32 #define RX_RING_SZ ((NGBE_RING_DESC_MAX + RTE_PMD_NGBE_RX_MAX_BURST) * \ @@ -62,6 +87,15 @@ struct ngbe_scattered_rx_entry { struct rte_mbuf *fbuf; /**< First segment of the fragmented packet. */ }; +/** + * Structure associated with each descriptor of the TX ring of a TX queue. + */ +struct ngbe_tx_entry { + struct rte_mbuf *mbuf; /**< mbuf associated with TX desc, if any. */ + uint16_t next_id; /**< Index of next descriptor in ring. */ + uint16_t last_id; /**< Index of last scattered descriptor. */ +}; + /** * Structure associated with each RX queue. */ @@ -98,6 +132,63 @@ struct ngbe_rx_queue { struct rte_mbuf *rx_stage[RTE_PMD_NGBE_RX_MAX_BURST * 2]; }; +/** + * NGBE CTX Constants + */ +enum ngbe_ctx_num { + NGBE_CTX_0 = 0, /**< CTX0 */ + NGBE_CTX_1 = 1, /**< CTX1 */ + NGBE_CTX_NUM = 2, /**< CTX NUMBER */ +}; + +/** + * Structure to check if new context need be built + */ +struct ngbe_ctx_info { + uint64_t flags; /**< ol_flags for context build. */ +}; + +/** + * Structure associated with each TX queue. + */ +struct ngbe_tx_queue { + /** TX ring virtual address. */ + volatile struct ngbe_tx_desc *tx_ring; + uint64_t tx_ring_phys_addr; /**< TX ring DMA address. */ + struct ngbe_tx_entry *sw_ring; /**< address of SW ring for scalar PMD.*/ + volatile uint32_t *tdt_reg_addr; /**< Address of TDT register. */ + volatile uint32_t *tdc_reg_addr; /**< Address of TDC register. */ + uint16_t nb_tx_desc; /**< number of TX descriptors. */ + uint16_t tx_tail; /**< current value of TDT reg. */ + /**< Start freeing TX buffers if there are less free descriptors than + * this value. + */ + uint16_t tx_free_thresh; + /** Index to last TX descriptor to have been cleaned. */ + uint16_t last_desc_cleaned; + /** Total number of TX descriptors ready to be allocated. */ + uint16_t nb_tx_free; + uint16_t tx_next_dd; /**< next desc to scan for DD bit */ + uint16_t queue_id; /**< TX queue index. */ + uint16_t reg_idx; /**< TX queue register index. */ + uint16_t port_id; /**< Device port identifier. */ + uint8_t pthresh; /**< Prefetch threshold register. */ + uint8_t hthresh; /**< Host threshold register. */ + uint8_t wthresh; /**< Write-back threshold reg. */ + uint64_t offloads; /* Tx offload flags of DEV_TX_OFFLOAD_* */ + uint32_t ctx_curr; /**< Hardware context states. */ + /** Hardware context0 history. */ + struct ngbe_ctx_info ctx_cache[NGBE_CTX_NUM]; + const struct ngbe_txq_ops *ops; /**< txq ops */ + uint8_t tx_deferred_start; /**< not in global dev start. */ +}; + +struct ngbe_txq_ops { + void (*release_mbufs)(struct ngbe_tx_queue *txq); + void (*free_swring)(struct ngbe_tx_queue *txq); + void (*reset)(struct ngbe_tx_queue *txq); +}; + uint64_t ngbe_get_tx_port_offloads(struct rte_eth_dev *dev); uint64_t ngbe_get_rx_queue_offloads(struct rte_eth_dev *dev); uint64_t ngbe_get_rx_port_offloads(struct rte_eth_dev *dev); From patchwork Wed Jun 2 09:41:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93780 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 ABC81A0524; Wed, 2 Jun 2021 11:41:56 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id D34E841183; Wed, 2 Jun 2021 11:40:05 +0200 (CEST) Received: from smtpbgsg2.qq.com (smtpbgsg2.qq.com [54.254.200.128]) by mails.dpdk.org (Postfix) with ESMTP id 41E3B41169 for ; Wed, 2 Jun 2021 11:40:01 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626796tbx1xsxb Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:56 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: sgsrYKOS1bSZERsRFR85pLT1Z9y6rAtNT86hPjObUh6aa0Xhzp2Jf3VefAB3f y18NXNKYWNJmLVm4fflWp4FuKUJQCFT8iaZ62PXP/kL6M1XNKhMYySH/u3lpfilhKtX6aMn 7aupOBhUkYEmtGd2ONCk+PH+8cm8ejwwE42VvFEb/qX0hfey3igea7qpm8QgpKa1btLb+fZ E2j+hFFzWMfL8MPyY8fXpz0ce4PbGblZIbKCrQhQbZOAxsaPqB9SbHlvrVD0Fe7KSPp/+0W ZSCr25B032RIuV6ETtC74aU4Gzu0i2ttXk0OXh2DnVWidzxDa2Mo7lNatAKXGq7ET+7nIrV xkTpzpZTgfS8DnGvYzQ0cD4cW+TRYCgh3/0bs7m X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:41:01 +0800 Message-Id: <20210602094108.1575640-18-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign1 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 17/24] net/ngbe: add Rx and Tx init 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 Sender: "dev" Initializes receive unit and transmit unit. Signed-off-by: Jiawen Wu --- doc/guides/nics/features/ngbe.ini | 6 + doc/guides/nics/ngbe.rst | 2 + drivers/net/ngbe/ngbe_ethdev.h | 5 + drivers/net/ngbe/ngbe_rxtx.c | 187 ++++++++++++++++++++++++++++++ 4 files changed, 200 insertions(+) diff --git a/doc/guides/nics/features/ngbe.ini b/doc/guides/nics/features/ngbe.ini index 291a542a42..abde1e2a67 100644 --- a/doc/guides/nics/features/ngbe.ini +++ b/doc/guides/nics/features/ngbe.ini @@ -7,6 +7,12 @@ Speed capabilities = Y Link status = Y Link status event = Y +Jumbo frame = Y +Scattered Rx = Y +CRC offload = P +VLAN offload = P +L3 checksum offload = P +L4 checksum offload = P Multiprocess aware = Y Linux = Y ARMv8 = Y diff --git a/doc/guides/nics/ngbe.rst b/doc/guides/nics/ngbe.rst index de2ef65664..e56baf26b4 100644 --- a/doc/guides/nics/ngbe.rst +++ b/doc/guides/nics/ngbe.rst @@ -10,6 +10,8 @@ for Wangxun 1 Gigabit Ethernet NICs. Features -------- +- Checksum offload +- Jumbo frames - Link state information Prerequisites diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h index f52d813a47..a9482f3001 100644 --- a/drivers/net/ngbe/ngbe_ethdev.h +++ b/drivers/net/ngbe/ngbe_ethdev.h @@ -13,6 +13,7 @@ #define NGBE_FLAG_MACSEC (uint32_t)(1 << 3) #define NGBE_FLAG_NEED_LINK_CONFIG (uint32_t)(1 << 4) +#define NGBE_VLAN_TAG_SIZE 4 #define NGBE_HKEY_MAX_INDEX 10 #define NGBE_RSS_OFFLOAD_ALL ( \ @@ -68,6 +69,10 @@ int ngbe_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf); +int ngbe_dev_rx_init(struct rte_eth_dev *dev); + +void ngbe_dev_tx_init(struct rte_eth_dev *dev); + int ngbe_dev_link_update_share(struct rte_eth_dev *dev, int wait_to_complete); diff --git a/drivers/net/ngbe/ngbe_rxtx.c b/drivers/net/ngbe/ngbe_rxtx.c index 2d8db3245f..68d7e651af 100644 --- a/drivers/net/ngbe/ngbe_rxtx.c +++ b/drivers/net/ngbe/ngbe_rxtx.c @@ -582,3 +582,190 @@ ngbe_dev_rx_queue_setup(struct rte_eth_dev *dev, return 0; } +/* + * Initializes Receive Unit. + */ +int __rte_cold +ngbe_dev_rx_init(struct rte_eth_dev *dev) +{ + struct ngbe_hw *hw; + struct ngbe_rx_queue *rxq; + uint64_t bus_addr; + uint32_t fctrl; + uint32_t hlreg0; + uint32_t srrctl; + uint32_t rdrxctl; + uint32_t rxcsum; + uint16_t buf_size; + uint16_t i; + struct rte_eth_rxmode *rx_conf = &dev->data->dev_conf.rxmode; + + PMD_INIT_FUNC_TRACE(); + hw = NGBE_DEV_HW(dev); + + /* + * Make sure receives are disabled while setting + * up the RX context (registers, descriptor rings, etc.). + */ + wr32m(hw, NGBE_MACRXCFG, NGBE_MACRXCFG_ENA, 0); + wr32m(hw, NGBE_PBRXCTL, NGBE_PBRXCTL_ENA, 0); + + /* Enable receipt of broadcasted frames */ + fctrl = rd32(hw, NGBE_PSRCTL); + fctrl |= NGBE_PSRCTL_BCA; + wr32(hw, NGBE_PSRCTL, fctrl); + + /* + * Configure CRC stripping, if any. + */ + hlreg0 = rd32(hw, NGBE_SECRXCTL); + if (rx_conf->offloads & DEV_RX_OFFLOAD_KEEP_CRC) + hlreg0 &= ~NGBE_SECRXCTL_CRCSTRIP; + else + hlreg0 |= NGBE_SECRXCTL_CRCSTRIP; + hlreg0 &= ~NGBE_SECRXCTL_XDSA; + wr32(hw, NGBE_SECRXCTL, hlreg0); + + /* + * Configure jumbo frame support, if any. + */ + if (rx_conf->offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) { + wr32m(hw, NGBE_FRMSZ, NGBE_FRMSZ_MAX_MASK, + NGBE_FRMSZ_MAX(rx_conf->max_rx_pkt_len)); + } else { + wr32m(hw, NGBE_FRMSZ, NGBE_FRMSZ_MAX_MASK, + NGBE_FRMSZ_MAX(NGBE_FRAME_SIZE_DFT)); + } + + /* + * If loopback mode is configured, set LPBK bit. + */ + hlreg0 = rd32(hw, NGBE_PSRCTL); + if (hw->is_pf && dev->data->dev_conf.lpbk_mode) + hlreg0 |= NGBE_PSRCTL_LBENA; + else + hlreg0 &= ~NGBE_PSRCTL_LBENA; + + wr32(hw, NGBE_PSRCTL, hlreg0); + + /* + * Assume no header split and no VLAN strip support + * on any Rx queue first . + */ + rx_conf->offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP; + + /* Setup RX queues */ + for (i = 0; i < dev->data->nb_rx_queues; i++) { + rxq = dev->data->rx_queues[i]; + + /* + * Reset crc_len in case it was changed after queue setup by a + * call to configure. + */ + if (rx_conf->offloads & DEV_RX_OFFLOAD_KEEP_CRC) + rxq->crc_len = RTE_ETHER_CRC_LEN; + else + rxq->crc_len = 0; + + /* Setup the Base and Length of the Rx Descriptor Rings */ + bus_addr = rxq->rx_ring_phys_addr; + wr32(hw, NGBE_RXBAL(rxq->reg_idx), + (uint32_t)(bus_addr & BIT_MASK32)); + wr32(hw, NGBE_RXBAH(rxq->reg_idx), + (uint32_t)(bus_addr >> 32)); + wr32(hw, NGBE_RXRP(rxq->reg_idx), 0); + wr32(hw, NGBE_RXWP(rxq->reg_idx), 0); + + srrctl = NGBE_RXCFG_RNGLEN(rxq->nb_rx_desc); + + /* Set if packets are dropped when no descriptors available */ + if (rxq->drop_en) + srrctl |= NGBE_RXCFG_DROP; + + /* + * Configure the RX buffer size in the PKTLEN field of + * the RXCFG register of the queue. + * The value is in 1 KB resolution. Valid values can be from + * 1 KB to 16 KB. + */ + buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rxq->mb_pool) - + RTE_PKTMBUF_HEADROOM); + buf_size = ROUND_DOWN(buf_size, 0x1 << 10); + srrctl |= NGBE_RXCFG_PKTLEN(buf_size); + + wr32(hw, NGBE_RXCFG(rxq->reg_idx), srrctl); + + /* It adds dual VLAN length for supporting dual VLAN */ + if (dev->data->dev_conf.rxmode.max_rx_pkt_len + + 2 * NGBE_VLAN_TAG_SIZE > buf_size) + dev->data->scattered_rx = 1; + if (rxq->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) + rx_conf->offloads |= DEV_RX_OFFLOAD_VLAN_STRIP; + } + + if (rx_conf->offloads & DEV_RX_OFFLOAD_SCATTER) + dev->data->scattered_rx = 1; + + /* + * Setup the Checksum Register. + * Disable Full-Packet Checksum which is mutually exclusive with RSS. + * Enable IP/L4 checksum computation by hardware if requested to do so. + */ + rxcsum = rd32(hw, NGBE_PSRCTL); + rxcsum |= NGBE_PSRCTL_PCSD; + if (rx_conf->offloads & DEV_RX_OFFLOAD_CHECKSUM) + rxcsum |= NGBE_PSRCTL_L4CSUM; + else + rxcsum &= ~NGBE_PSRCTL_L4CSUM; + + wr32(hw, NGBE_PSRCTL, rxcsum); + + if (hw->is_pf) { + rdrxctl = rd32(hw, NGBE_SECRXCTL); + if (rx_conf->offloads & DEV_RX_OFFLOAD_KEEP_CRC) + rdrxctl &= ~NGBE_SECRXCTL_CRCSTRIP; + else + rdrxctl |= NGBE_SECRXCTL_CRCSTRIP; + wr32(hw, NGBE_SECRXCTL, rdrxctl); + } + + return 0; +} + +/* + * Initializes Transmit Unit. + */ +void __rte_cold +ngbe_dev_tx_init(struct rte_eth_dev *dev) +{ + struct ngbe_hw *hw; + struct ngbe_tx_queue *txq; + uint64_t bus_addr; + uint16_t i; + + PMD_INIT_FUNC_TRACE(); + hw = NGBE_DEV_HW(dev); + + /* Enable TX CRC (checksum offload requirement) and hw padding + * (TSO requirement) + */ + wr32m(hw, NGBE_SECTXCTL, NGBE_SECTXCTL_ODSA, NGBE_SECTXCTL_ODSA); + wr32m(hw, NGBE_SECTXCTL, NGBE_SECTXCTL_XDSA, 0); + + /* Setup the Base and Length of the Tx Descriptor Rings */ + for (i = 0; i < dev->data->nb_tx_queues; i++) { + txq = dev->data->tx_queues[i]; + + bus_addr = txq->tx_ring_phys_addr; + wr32(hw, NGBE_TXBAL(txq->reg_idx), + (uint32_t)(bus_addr & BIT_MASK32)); + wr32(hw, NGBE_TXBAH(txq->reg_idx), + (uint32_t)(bus_addr >> 32)); + wr32m(hw, NGBE_TXCFG(txq->reg_idx), NGBE_TXCFG_BUFLEN_MASK, + NGBE_TXCFG_BUFLEN(txq->nb_tx_desc)); + /* Setup the HW Tx Head and TX Tail descriptor pointers */ + wr32(hw, NGBE_TXRP(txq->reg_idx), 0); + wr32(hw, NGBE_TXWP(txq->reg_idx), 0); + } +} + From patchwork Wed Jun 2 09:41:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93779 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 B560DA0524; Wed, 2 Jun 2021 11:41:49 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id D48B64117F; Wed, 2 Jun 2021 11:40:04 +0200 (CEST) Received: from smtpbguseast2.qq.com (smtpbguseast2.qq.com [54.204.34.130]) by mails.dpdk.org (Postfix) with ESMTP id 5B24041174 for ; Wed, 2 Jun 2021 11:40:01 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626797tekmpia2 Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:57 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: bQJt8icoRZOLwd9cc2YdT4Pc/h8f5R2eKRQ+MphjdneH3a54Vwlw64U+L8IWb SkduKX+qp1NHUV7PpjGacWZFlZkkPN9pHR1qZnzkNLm6KcVBJvMBgsCE+CPgb37+LJt1qXi KScpq8g/sNJcJJLinpdb7YDh+xj21htGlOGZg6Ije+6Zu9zFigvcfkzw+f6C1nL8arb53f4 wMgbmcWA2h5xuTiQQ2xOwZlg6h0wzin4rXSW6xh3VWk4UtMjyOdEiY5Ct2L+b26FnsRhwpS pHkzvYKmejmZY4R/5TILR1EVFUfGBpKctt/vLtzqDZFU+/eQHhEFmUCZ0UX3FdJN5FtZgik FGHmy9IAb8uj6noW4hBSlpvW5GnHDDW/32+HJJh X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:41:02 +0800 Message-Id: <20210602094108.1575640-19-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign1 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 18/24] net/ngbe: add packet type 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 Sender: "dev" Add packet type marco definition and convert ptype to ptid. Signed-off-by: Jiawen Wu --- doc/guides/nics/features/ngbe.ini | 1 + doc/guides/nics/ngbe.rst | 1 + drivers/net/ngbe/meson.build | 1 + drivers/net/ngbe/ngbe_ethdev.c | 8 + drivers/net/ngbe/ngbe_ethdev.h | 4 + drivers/net/ngbe/ngbe_ptypes.c | 640 ++++++++++++++++++++++++++++++ drivers/net/ngbe/ngbe_ptypes.h | 351 ++++++++++++++++ drivers/net/ngbe/ngbe_rxtx.h | 1 - 8 files changed, 1006 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ngbe/ngbe_ptypes.c create mode 100644 drivers/net/ngbe/ngbe_ptypes.h diff --git a/doc/guides/nics/features/ngbe.ini b/doc/guides/nics/features/ngbe.ini index abde1e2a67..e24d8d0b55 100644 --- a/doc/guides/nics/features/ngbe.ini +++ b/doc/guides/nics/features/ngbe.ini @@ -13,6 +13,7 @@ CRC offload = P VLAN offload = P L3 checksum offload = P L4 checksum offload = P +Packet type parsing = Y Multiprocess aware = Y Linux = Y ARMv8 = Y diff --git a/doc/guides/nics/ngbe.rst b/doc/guides/nics/ngbe.rst index e56baf26b4..04fa3e90a8 100644 --- a/doc/guides/nics/ngbe.rst +++ b/doc/guides/nics/ngbe.rst @@ -10,6 +10,7 @@ for Wangxun 1 Gigabit Ethernet NICs. Features -------- +- Packet type information - Checksum offload - Jumbo frames - Link state information diff --git a/drivers/net/ngbe/meson.build b/drivers/net/ngbe/meson.build index 9e75b82f1c..fd571399b3 100644 --- a/drivers/net/ngbe/meson.build +++ b/drivers/net/ngbe/meson.build @@ -12,6 +12,7 @@ objs = [base_objs] sources = files( 'ngbe_ethdev.c', + 'ngbe_ptypes.c', 'ngbe_rxtx.c', ) diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 2f8ac48f33..672db88133 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -354,6 +354,13 @@ ngbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) return 0; } +const uint32_t * +ngbe_dev_supported_ptypes_get(struct rte_eth_dev *dev) +{ + RTE_SET_USED(dev); + return ngbe_get_supported_ptypes(); +} + /* return 0 means link status changed, -1 means not changed */ int ngbe_dev_link_update_share(struct rte_eth_dev *dev, @@ -661,6 +668,7 @@ static const struct eth_dev_ops ngbe_eth_dev_ops = { .dev_configure = ngbe_dev_configure, .dev_infos_get = ngbe_dev_info_get, .link_update = ngbe_dev_link_update, + .dev_supported_ptypes_get = ngbe_dev_supported_ptypes_get, .rx_queue_setup = ngbe_dev_rx_queue_setup, .rx_queue_release = ngbe_dev_rx_queue_release, .tx_queue_setup = ngbe_dev_tx_queue_setup, diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h index a9482f3001..6881351252 100644 --- a/drivers/net/ngbe/ngbe_ethdev.h +++ b/drivers/net/ngbe/ngbe_ethdev.h @@ -6,6 +6,8 @@ #ifndef _NGBE_ETHDEV_H_ #define _NGBE_ETHDEV_H_ +#include "ngbe_ptypes.h" + /* need update link, bit flag */ #define NGBE_FLAG_NEED_LINK_UPDATE (uint32_t)(1 << 0) #define NGBE_FLAG_MAILBOX (uint32_t)(1 << 1) @@ -94,4 +96,6 @@ ngbe_dev_link_update_share(struct rte_eth_dev *dev, #define NGBE_DEFAULT_TX_HTHRESH 0 #define NGBE_DEFAULT_TX_WTHRESH 0 +const uint32_t *ngbe_dev_supported_ptypes_get(struct rte_eth_dev *dev); + #endif /* _NGBE_ETHDEV_H_ */ diff --git a/drivers/net/ngbe/ngbe_ptypes.c b/drivers/net/ngbe/ngbe_ptypes.c new file mode 100644 index 0000000000..4b6cd374f6 --- /dev/null +++ b/drivers/net/ngbe/ngbe_ptypes.c @@ -0,0 +1,640 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + */ + +#include +#include + +#include "base/ngbe_type.h" +#include "ngbe_ptypes.h" + +/* The ngbe_ptype_lookup is used to convert from the 8-bit ptid in the + * hardware to a bit-field that can be used by SW to more easily determine the + * packet type. + * + * Macros are used to shorten the table lines and make this table human + * readable. + * + * We store the PTYPE in the top byte of the bit field - this is just so that + * we can check that the table doesn't have a row missing, as the index into + * the table should be the PTYPE. + */ +#define TPTE(ptid, l2, l3, l4, tun, el2, el3, el4) \ + [ptid] = (RTE_PTYPE_L2_##l2 | \ + RTE_PTYPE_L3_##l3 | \ + RTE_PTYPE_L4_##l4 | \ + RTE_PTYPE_TUNNEL_##tun | \ + RTE_PTYPE_INNER_L2_##el2 | \ + RTE_PTYPE_INNER_L3_##el3 | \ + RTE_PTYPE_INNER_L4_##el4) + +#define RTE_PTYPE_L2_NONE 0 +#define RTE_PTYPE_L3_NONE 0 +#define RTE_PTYPE_L4_NONE 0 +#define RTE_PTYPE_TUNNEL_NONE 0 +#define RTE_PTYPE_INNER_L2_NONE 0 +#define RTE_PTYPE_INNER_L3_NONE 0 +#define RTE_PTYPE_INNER_L4_NONE 0 + +static u32 ngbe_ptype_lookup[NGBE_PTID_MAX] __rte_cache_aligned = { + /* L2:0-3 L3:4-7 L4:8-11 TUN:12-15 EL2:16-19 EL3:20-23 EL2:24-27 */ + /* L2: ETH */ + TPTE(0x10, ETHER, NONE, NONE, NONE, NONE, NONE, NONE), + TPTE(0x11, ETHER, NONE, NONE, NONE, NONE, NONE, NONE), + TPTE(0x12, ETHER_TIMESYNC, NONE, NONE, NONE, NONE, NONE, NONE), + TPTE(0x13, ETHER_FIP, NONE, NONE, NONE, NONE, NONE, NONE), + TPTE(0x14, ETHER_LLDP, NONE, NONE, NONE, NONE, NONE, NONE), + TPTE(0x15, ETHER_CNM, NONE, NONE, NONE, NONE, NONE, NONE), + TPTE(0x16, ETHER_EAPOL, NONE, NONE, NONE, NONE, NONE, NONE), + TPTE(0x17, ETHER_ARP, NONE, NONE, NONE, NONE, NONE, NONE), + /* L2: Ethertype Filter */ + TPTE(0x18, ETHER_FILTER, NONE, NONE, NONE, NONE, NONE, NONE), + TPTE(0x19, ETHER_FILTER, NONE, NONE, NONE, NONE, NONE, NONE), + TPTE(0x1A, ETHER_FILTER, NONE, NONE, NONE, NONE, NONE, NONE), + TPTE(0x1B, ETHER_FILTER, NONE, NONE, NONE, NONE, NONE, NONE), + TPTE(0x1C, ETHER_FILTER, NONE, NONE, NONE, NONE, NONE, NONE), + TPTE(0x1D, ETHER_FILTER, NONE, NONE, NONE, NONE, NONE, NONE), + TPTE(0x1E, ETHER_FILTER, NONE, NONE, NONE, NONE, NONE, NONE), + TPTE(0x1F, ETHER_FILTER, NONE, NONE, NONE, NONE, NONE, NONE), + /* L3: IP */ + TPTE(0x20, ETHER, IPV4, NONFRAG, NONE, NONE, NONE, NONE), + TPTE(0x21, ETHER, IPV4, FRAG, NONE, NONE, NONE, NONE), + TPTE(0x22, ETHER, IPV4, NONFRAG, NONE, NONE, NONE, NONE), + TPTE(0x23, ETHER, IPV4, UDP, NONE, NONE, NONE, NONE), + TPTE(0x24, ETHER, IPV4, TCP, NONE, NONE, NONE, NONE), + TPTE(0x25, ETHER, IPV4, SCTP, NONE, NONE, NONE, NONE), + TPTE(0x29, ETHER, IPV6, FRAG, NONE, NONE, NONE, NONE), + TPTE(0x2A, ETHER, IPV6, NONFRAG, NONE, NONE, NONE, NONE), + TPTE(0x2B, ETHER, IPV6, UDP, NONE, NONE, NONE, NONE), + TPTE(0x2C, ETHER, IPV6, TCP, NONE, NONE, NONE, NONE), + TPTE(0x2D, ETHER, IPV6, SCTP, NONE, NONE, NONE, NONE), + /* IPv4 -> IPv4/IPv6 */ + TPTE(0x81, ETHER, IPV4, NONE, IP, NONE, IPV4, FRAG), + TPTE(0x82, ETHER, IPV4, NONE, IP, NONE, IPV4, NONFRAG), + TPTE(0x83, ETHER, IPV4, NONE, IP, NONE, IPV4, UDP), + TPTE(0x84, ETHER, IPV4, NONE, IP, NONE, IPV4, TCP), + TPTE(0x85, ETHER, IPV4, NONE, IP, NONE, IPV4, SCTP), + TPTE(0x89, ETHER, IPV4, NONE, IP, NONE, IPV6, FRAG), + TPTE(0x8A, ETHER, IPV4, NONE, IP, NONE, IPV6, NONFRAG), + TPTE(0x8B, ETHER, IPV4, NONE, IP, NONE, IPV6, UDP), + TPTE(0x8C, ETHER, IPV4, NONE, IP, NONE, IPV6, TCP), + TPTE(0x8D, ETHER, IPV4, NONE, IP, NONE, IPV6, SCTP), + /* IPv4 -> GRE/Teredo/VXLAN -> NONE/IPv4/IPv6 */ + TPTE(0x90, ETHER, IPV4, NONE, VXLAN_GPE, NONE, NONE, NONE), + TPTE(0x91, ETHER, IPV4, NONE, VXLAN_GPE, NONE, IPV4, FRAG), + TPTE(0x92, ETHER, IPV4, NONE, VXLAN_GPE, NONE, IPV4, NONFRAG), + TPTE(0x93, ETHER, IPV4, NONE, VXLAN_GPE, NONE, IPV4, UDP), + TPTE(0x94, ETHER, IPV4, NONE, VXLAN_GPE, NONE, IPV4, TCP), + TPTE(0x95, ETHER, IPV4, NONE, VXLAN_GPE, NONE, IPV4, SCTP), + TPTE(0x99, ETHER, IPV4, NONE, VXLAN_GPE, NONE, IPV6, FRAG), + TPTE(0x9A, ETHER, IPV4, NONE, VXLAN_GPE, NONE, IPV6, NONFRAG), + TPTE(0x9B, ETHER, IPV4, NONE, VXLAN_GPE, NONE, IPV6, UDP), + TPTE(0x9C, ETHER, IPV4, NONE, VXLAN_GPE, NONE, IPV6, TCP), + TPTE(0x9D, ETHER, IPV4, NONE, VXLAN_GPE, NONE, IPV6, SCTP), + /* IPv4 -> GRE/Teredo/VXLAN -> MAC -> NONE/IPv4/IPv6 */ + TPTE(0xA0, ETHER, IPV4, NONE, GRENAT, ETHER, NONE, NONE), + TPTE(0xA1, ETHER, IPV4, NONE, GRENAT, ETHER, IPV4, FRAG), + TPTE(0xA2, ETHER, IPV4, NONE, GRENAT, ETHER, IPV4, NONFRAG), + TPTE(0xA3, ETHER, IPV4, NONE, GRENAT, ETHER, IPV4, UDP), + TPTE(0xA4, ETHER, IPV4, NONE, GRENAT, ETHER, IPV4, TCP), + TPTE(0xA5, ETHER, IPV4, NONE, GRENAT, ETHER, IPV4, SCTP), + TPTE(0xA9, ETHER, IPV4, NONE, GRENAT, ETHER, IPV6, FRAG), + TPTE(0xAA, ETHER, IPV4, NONE, GRENAT, ETHER, IPV6, NONFRAG), + TPTE(0xAB, ETHER, IPV4, NONE, GRENAT, ETHER, IPV6, UDP), + TPTE(0xAC, ETHER, IPV4, NONE, GRENAT, ETHER, IPV6, TCP), + TPTE(0xAD, ETHER, IPV4, NONE, GRENAT, ETHER, IPV6, SCTP), + /* IPv4 -> GRE/Teredo/VXLAN -> MAC+VLAN -> NONE/IPv4/IPv6 */ + TPTE(0xB0, ETHER, IPV4, NONE, GRENAT, ETHER_VLAN, NONE, NONE), + TPTE(0xB1, ETHER, IPV4, NONE, GRENAT, ETHER_VLAN, IPV4, FRAG), + TPTE(0xB2, ETHER, IPV4, NONE, GRENAT, ETHER_VLAN, IPV4, NONFRAG), + TPTE(0xB3, ETHER, IPV4, NONE, GRENAT, ETHER_VLAN, IPV4, UDP), + TPTE(0xB4, ETHER, IPV4, NONE, GRENAT, ETHER_VLAN, IPV4, TCP), + TPTE(0xB5, ETHER, IPV4, NONE, GRENAT, ETHER_VLAN, IPV4, SCTP), + TPTE(0xB9, ETHER, IPV4, NONE, GRENAT, ETHER_VLAN, IPV6, FRAG), + TPTE(0xBA, ETHER, IPV4, NONE, GRENAT, ETHER_VLAN, IPV6, NONFRAG), + TPTE(0xBB, ETHER, IPV4, NONE, GRENAT, ETHER_VLAN, IPV6, UDP), + TPTE(0xBC, ETHER, IPV4, NONE, GRENAT, ETHER_VLAN, IPV6, TCP), + TPTE(0xBD, ETHER, IPV4, NONE, GRENAT, ETHER_VLAN, IPV6, SCTP), + /* IPv6 -> IPv4/IPv6 */ + TPTE(0xC1, ETHER, IPV6, NONE, IP, NONE, IPV4, FRAG), + TPTE(0xC2, ETHER, IPV6, NONE, IP, NONE, IPV4, NONFRAG), + TPTE(0xC3, ETHER, IPV6, NONE, IP, NONE, IPV4, UDP), + TPTE(0xC4, ETHER, IPV6, NONE, IP, NONE, IPV4, TCP), + TPTE(0xC5, ETHER, IPV6, NONE, IP, NONE, IPV4, SCTP), + TPTE(0xC9, ETHER, IPV6, NONE, IP, NONE, IPV6, FRAG), + TPTE(0xCA, ETHER, IPV6, NONE, IP, NONE, IPV6, NONFRAG), + TPTE(0xCB, ETHER, IPV6, NONE, IP, NONE, IPV6, UDP), + TPTE(0xCC, ETHER, IPV6, NONE, IP, NONE, IPV6, TCP), + TPTE(0xCD, ETHER, IPV6, NONE, IP, NONE, IPV6, SCTP), + /* IPv6 -> GRE/Teredo/VXLAN -> NONE/IPv4/IPv6 */ + TPTE(0xD0, ETHER, IPV6, NONE, GRENAT, NONE, NONE, NONE), + TPTE(0xD1, ETHER, IPV6, NONE, GRENAT, NONE, IPV4, FRAG), + TPTE(0xD2, ETHER, IPV6, NONE, GRENAT, NONE, IPV4, NONFRAG), + TPTE(0xD3, ETHER, IPV6, NONE, GRENAT, NONE, IPV4, UDP), + TPTE(0xD4, ETHER, IPV6, NONE, GRENAT, NONE, IPV4, TCP), + TPTE(0xD5, ETHER, IPV6, NONE, GRENAT, NONE, IPV4, SCTP), + TPTE(0xD9, ETHER, IPV6, NONE, GRENAT, NONE, IPV6, FRAG), + TPTE(0xDA, ETHER, IPV6, NONE, GRENAT, NONE, IPV6, NONFRAG), + TPTE(0xDB, ETHER, IPV6, NONE, GRENAT, NONE, IPV6, UDP), + TPTE(0xDC, ETHER, IPV6, NONE, GRENAT, NONE, IPV6, TCP), + TPTE(0xDD, ETHER, IPV6, NONE, GRENAT, NONE, IPV6, SCTP), + /* IPv6 -> GRE/Teredo/VXLAN -> MAC -> NONE/IPv4/IPv6 */ + TPTE(0xE0, ETHER, IPV6, NONE, GRENAT, ETHER, NONE, NONE), + TPTE(0xE1, ETHER, IPV6, NONE, GRENAT, ETHER, IPV4, FRAG), + TPTE(0xE2, ETHER, IPV6, NONE, GRENAT, ETHER, IPV4, NONFRAG), + TPTE(0xE3, ETHER, IPV6, NONE, GRENAT, ETHER, IPV4, UDP), + TPTE(0xE4, ETHER, IPV6, NONE, GRENAT, ETHER, IPV4, TCP), + TPTE(0xE5, ETHER, IPV6, NONE, GRENAT, ETHER, IPV4, SCTP), + TPTE(0xE9, ETHER, IPV6, NONE, GRENAT, ETHER, IPV6, FRAG), + TPTE(0xEA, ETHER, IPV6, NONE, GRENAT, ETHER, IPV6, NONFRAG), + TPTE(0xEB, ETHER, IPV6, NONE, GRENAT, ETHER, IPV6, UDP), + TPTE(0xEC, ETHER, IPV6, NONE, GRENAT, ETHER, IPV6, TCP), + TPTE(0xED, ETHER, IPV6, NONE, GRENAT, ETHER, IPV6, SCTP), + /* IPv6 -> GRE/Teredo/VXLAN -> MAC+VLAN -> NONE/IPv4/IPv6 */ + TPTE(0xF0, ETHER, IPV6, NONE, GRENAT, ETHER_VLAN, NONE, NONE), + TPTE(0xF1, ETHER, IPV6, NONE, GRENAT, ETHER_VLAN, IPV4, FRAG), + TPTE(0xF2, ETHER, IPV6, NONE, GRENAT, ETHER_VLAN, IPV4, NONFRAG), + TPTE(0xF3, ETHER, IPV6, NONE, GRENAT, ETHER_VLAN, IPV4, UDP), + TPTE(0xF4, ETHER, IPV6, NONE, GRENAT, ETHER_VLAN, IPV4, TCP), + TPTE(0xF5, ETHER, IPV6, NONE, GRENAT, ETHER_VLAN, IPV4, SCTP), + TPTE(0xF9, ETHER, IPV6, NONE, GRENAT, ETHER_VLAN, IPV6, FRAG), + TPTE(0xFA, ETHER, IPV6, NONE, GRENAT, ETHER_VLAN, IPV6, NONFRAG), + TPTE(0xFB, ETHER, IPV6, NONE, GRENAT, ETHER_VLAN, IPV6, UDP), + TPTE(0xFC, ETHER, IPV6, NONE, GRENAT, ETHER_VLAN, IPV6, TCP), + TPTE(0xFD, ETHER, IPV6, NONE, GRENAT, ETHER_VLAN, IPV6, SCTP), +}; + +u32 *ngbe_get_supported_ptypes(void) +{ + static u32 ptypes[] = { + /* For non-vec functions, + * refers to ngbe_rxd_pkt_info_to_pkt_type(); + */ + RTE_PTYPE_L2_ETHER, + RTE_PTYPE_L3_IPV4, + RTE_PTYPE_L3_IPV4_EXT, + RTE_PTYPE_L3_IPV6, + RTE_PTYPE_L3_IPV6_EXT, + RTE_PTYPE_L4_SCTP, + RTE_PTYPE_L4_TCP, + RTE_PTYPE_L4_UDP, + RTE_PTYPE_TUNNEL_IP, + RTE_PTYPE_INNER_L3_IPV6, + RTE_PTYPE_INNER_L3_IPV6_EXT, + RTE_PTYPE_INNER_L4_TCP, + RTE_PTYPE_INNER_L4_UDP, + RTE_PTYPE_UNKNOWN + }; + + return ptypes; +} + +static inline u8 +ngbe_encode_ptype_mac(u32 ptype) +{ + u8 ptid; + + ptid = NGBE_PTID_PKT_MAC; + + switch (ptype & RTE_PTYPE_L2_MASK) { + case RTE_PTYPE_UNKNOWN: + break; + case RTE_PTYPE_L2_ETHER_TIMESYNC: + ptid |= NGBE_PTID_TYP_TS; + break; + case RTE_PTYPE_L2_ETHER_ARP: + ptid |= NGBE_PTID_TYP_ARP; + break; + case RTE_PTYPE_L2_ETHER_LLDP: + ptid |= NGBE_PTID_TYP_LLDP; + break; + default: + ptid |= NGBE_PTID_TYP_MAC; + break; + } + + return ptid; +} + +static inline u8 +ngbe_encode_ptype_ip(u32 ptype) +{ + u8 ptid; + + ptid = NGBE_PTID_PKT_IP; + + switch (ptype & RTE_PTYPE_L3_MASK) { + case RTE_PTYPE_L3_IPV4: + case RTE_PTYPE_L3_IPV4_EXT: + case RTE_PTYPE_L3_IPV4_EXT_UNKNOWN: + break; + case RTE_PTYPE_L3_IPV6: + case RTE_PTYPE_L3_IPV6_EXT: + case RTE_PTYPE_L3_IPV6_EXT_UNKNOWN: + ptid |= NGBE_PTID_PKT_IPV6; + break; + default: + return ngbe_encode_ptype_mac(ptype); + } + + switch (ptype & RTE_PTYPE_L4_MASK) { + case RTE_PTYPE_L4_TCP: + ptid |= NGBE_PTID_TYP_TCP; + break; + case RTE_PTYPE_L4_UDP: + ptid |= NGBE_PTID_TYP_UDP; + break; + case RTE_PTYPE_L4_SCTP: + ptid |= NGBE_PTID_TYP_SCTP; + break; + case RTE_PTYPE_L4_FRAG: + ptid |= NGBE_PTID_TYP_IPFRAG; + break; + default: + ptid |= NGBE_PTID_TYP_IPDATA; + break; + } + + return ptid; +} + +static inline u8 +ngbe_encode_ptype_tunnel(u32 ptype) +{ + u8 ptid; + + ptid = NGBE_PTID_PKT_TUN; + + switch (ptype & RTE_PTYPE_L3_MASK) { + case RTE_PTYPE_L3_IPV4: + case RTE_PTYPE_L3_IPV4_EXT: + case RTE_PTYPE_L3_IPV4_EXT_UNKNOWN: + break; + case RTE_PTYPE_L3_IPV6: + case RTE_PTYPE_L3_IPV6_EXT: + case RTE_PTYPE_L3_IPV6_EXT_UNKNOWN: + ptid |= NGBE_PTID_TUN_IPV6; + break; + default: + return ngbe_encode_ptype_ip(ptype); + } + + /* VXLAN/GRE/Teredo/VXLAN-GPE are not supported in EM */ + switch (ptype & RTE_PTYPE_TUNNEL_MASK) { + case RTE_PTYPE_TUNNEL_IP: + ptid |= NGBE_PTID_TUN_EI; + break; + case RTE_PTYPE_TUNNEL_GRE: + case RTE_PTYPE_TUNNEL_VXLAN_GPE: + ptid |= NGBE_PTID_TUN_EIG; + break; + case RTE_PTYPE_TUNNEL_VXLAN: + case RTE_PTYPE_TUNNEL_NVGRE: + case RTE_PTYPE_TUNNEL_GENEVE: + case RTE_PTYPE_TUNNEL_GRENAT: + break; + default: + return ptid; + } + + switch (ptype & RTE_PTYPE_INNER_L2_MASK) { + case RTE_PTYPE_INNER_L2_ETHER: + ptid |= NGBE_PTID_TUN_EIGM; + break; + case RTE_PTYPE_INNER_L2_ETHER_VLAN: + ptid |= NGBE_PTID_TUN_EIGMV; + break; + case RTE_PTYPE_INNER_L2_ETHER_QINQ: + ptid |= NGBE_PTID_TUN_EIGMV; + break; + default: + break; + } + + switch (ptype & RTE_PTYPE_INNER_L3_MASK) { + case RTE_PTYPE_INNER_L3_IPV4: + case RTE_PTYPE_INNER_L3_IPV4_EXT: + case RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN: + break; + case RTE_PTYPE_INNER_L3_IPV6: + case RTE_PTYPE_INNER_L3_IPV6_EXT: + case RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN: + ptid |= NGBE_PTID_PKT_IPV6; + break; + default: + return ptid; + } + + switch (ptype & RTE_PTYPE_INNER_L4_MASK) { + case RTE_PTYPE_INNER_L4_TCP: + ptid |= NGBE_PTID_TYP_TCP; + break; + case RTE_PTYPE_INNER_L4_UDP: + ptid |= NGBE_PTID_TYP_UDP; + break; + case RTE_PTYPE_INNER_L4_SCTP: + ptid |= NGBE_PTID_TYP_SCTP; + break; + case RTE_PTYPE_INNER_L4_FRAG: + ptid |= NGBE_PTID_TYP_IPFRAG; + break; + default: + ptid |= NGBE_PTID_TYP_IPDATA; + break; + } + + return ptid; +} + +u32 ngbe_decode_ptype(u8 ptid) +{ + if (-1 != ngbe_etflt_id(ptid)) + return RTE_PTYPE_UNKNOWN; + + return ngbe_ptype_lookup[ptid]; +} + +u8 ngbe_encode_ptype(u32 ptype) +{ + u8 ptid = 0; + + if (ptype & RTE_PTYPE_TUNNEL_MASK) + ptid = ngbe_encode_ptype_tunnel(ptype); + else if (ptype & RTE_PTYPE_L3_MASK) + ptid = ngbe_encode_ptype_ip(ptype); + else if (ptype & RTE_PTYPE_L2_MASK) + ptid = ngbe_encode_ptype_mac(ptype); + else + ptid = NGBE_PTID_NULL; + + return ptid; +} + +/** + * Use 2 different table for normal packet and tunnel packet + * to save the space. + */ +const u32 +ngbe_ptype_table[NGBE_PTID_MAX] __rte_cache_aligned = { + [NGBE_PT_ETHER] = RTE_PTYPE_L2_ETHER, + [NGBE_PT_IPV4] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4, + [NGBE_PT_IPV4_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP, + [NGBE_PT_IPV4_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP, + [NGBE_PT_IPV4_SCTP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP, + [NGBE_PT_IPV4_EXT] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT, + [NGBE_PT_IPV4_EXT_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L4_TCP, + [NGBE_PT_IPV4_EXT_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L4_UDP, + [NGBE_PT_IPV4_EXT_SCTP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L4_SCTP, + [NGBE_PT_IPV6] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6, + [NGBE_PT_IPV6_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP, + [NGBE_PT_IPV6_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP, + [NGBE_PT_IPV6_SCTP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_SCTP, + [NGBE_PT_IPV6_EXT] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6_EXT, + [NGBE_PT_IPV6_EXT_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_TCP, + [NGBE_PT_IPV6_EXT_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_UDP, + [NGBE_PT_IPV6_EXT_SCTP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_SCTP, + [NGBE_PT_IPV4_IPV6] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | + RTE_PTYPE_INNER_L3_IPV6, + [NGBE_PT_IPV4_IPV6_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | + RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_TCP, + [NGBE_PT_IPV4_IPV6_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | + RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_UDP, + [NGBE_PT_IPV4_IPV6_SCTP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | + RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_SCTP, + [NGBE_PT_IPV4_EXT_IPV6] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_TUNNEL_IP | + RTE_PTYPE_INNER_L3_IPV6, + [NGBE_PT_IPV4_EXT_IPV6_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_TUNNEL_IP | + RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_TCP, + [NGBE_PT_IPV4_EXT_IPV6_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_TUNNEL_IP | + RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_UDP, + [NGBE_PT_IPV4_EXT_IPV6_SCTP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_TUNNEL_IP | + RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_SCTP, + [NGBE_PT_IPV4_IPV6_EXT] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | + RTE_PTYPE_INNER_L3_IPV6_EXT, + [NGBE_PT_IPV4_IPV6_EXT_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | + RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_TCP, + [NGBE_PT_IPV4_IPV6_EXT_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | + RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_UDP, + [NGBE_PT_IPV4_IPV6_EXT_SCTP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | + RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_SCTP, + [NGBE_PT_IPV4_EXT_IPV6_EXT] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_TUNNEL_IP | + RTE_PTYPE_INNER_L3_IPV6_EXT, + [NGBE_PT_IPV4_EXT_IPV6_EXT_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_TUNNEL_IP | + RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_TCP, + [NGBE_PT_IPV4_EXT_IPV6_EXT_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_TUNNEL_IP | + RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_UDP, + [NGBE_PT_IPV4_EXT_IPV6_EXT_SCTP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_TUNNEL_IP | + RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_SCTP, +}; + +const u32 +ngbe_ptype_table_tn[NGBE_PTID_MAX] __rte_cache_aligned = { + [NGBE_PT_NVGRE] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER, + [NGBE_PT_NVGRE_IPV4] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4, + [NGBE_PT_NVGRE_IPV4_EXT] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4_EXT, + [NGBE_PT_NVGRE_IPV6] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6, + [NGBE_PT_NVGRE_IPV4_IPV6] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4, + [NGBE_PT_NVGRE_IPV6_EXT] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6_EXT, + [NGBE_PT_NVGRE_IPV4_IPV6_EXT] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4, + [NGBE_PT_NVGRE_IPV4_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4 | + RTE_PTYPE_INNER_L4_TCP, + [NGBE_PT_NVGRE_IPV6_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6 | + RTE_PTYPE_INNER_L4_TCP, + [NGBE_PT_NVGRE_IPV4_IPV6_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4, + [NGBE_PT_NVGRE_IPV6_EXT_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6_EXT | + RTE_PTYPE_INNER_L4_TCP, + [NGBE_PT_NVGRE_IPV4_IPV6_EXT_TCP] = + RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRE | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4, + [NGBE_PT_NVGRE_IPV4_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4 | + RTE_PTYPE_INNER_L4_UDP, + [NGBE_PT_NVGRE_IPV6_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6 | + RTE_PTYPE_INNER_L4_UDP, + [NGBE_PT_NVGRE_IPV6_SCTP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6 | + RTE_PTYPE_INNER_L4_SCTP, + [NGBE_PT_NVGRE_IPV4_IPV6_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4, + [NGBE_PT_NVGRE_IPV6_EXT_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6_EXT | + RTE_PTYPE_INNER_L4_UDP, + [NGBE_PT_NVGRE_IPV6_EXT_SCTP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6_EXT | + RTE_PTYPE_INNER_L4_SCTP, + [NGBE_PT_NVGRE_IPV4_IPV6_EXT_UDP] = + RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRE | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4, + [NGBE_PT_NVGRE_IPV4_SCTP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4 | + RTE_PTYPE_INNER_L4_SCTP, + [NGBE_PT_NVGRE_IPV4_EXT_SCTP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4_EXT | + RTE_PTYPE_INNER_L4_SCTP, + [NGBE_PT_NVGRE_IPV4_EXT_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4_EXT | + RTE_PTYPE_INNER_L4_TCP, + [NGBE_PT_NVGRE_IPV4_EXT_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRE | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4_EXT | + RTE_PTYPE_INNER_L4_UDP, + + [NGBE_PT_VXLAN] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER, + [NGBE_PT_VXLAN_IPV4] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4, + [NGBE_PT_VXLAN_IPV4_EXT] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT, + [NGBE_PT_VXLAN_IPV6] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6, + [NGBE_PT_VXLAN_IPV4_IPV6] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4, + [NGBE_PT_VXLAN_IPV6_EXT] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT, + [NGBE_PT_VXLAN_IPV4_IPV6_EXT] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4, + [NGBE_PT_VXLAN_IPV4_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4 | RTE_PTYPE_INNER_L4_TCP, + [NGBE_PT_VXLAN_IPV6_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_TCP, + [NGBE_PT_VXLAN_IPV4_IPV6_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4, + [NGBE_PT_VXLAN_IPV6_EXT_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_TCP, + [NGBE_PT_VXLAN_IPV4_IPV6_EXT_TCP] = + RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_VXLAN | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4, + [NGBE_PT_VXLAN_IPV4_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4 | RTE_PTYPE_INNER_L4_UDP, + [NGBE_PT_VXLAN_IPV6_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_UDP, + [NGBE_PT_VXLAN_IPV6_SCTP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_SCTP, + [NGBE_PT_VXLAN_IPV4_IPV6_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4, + [NGBE_PT_VXLAN_IPV6_EXT_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_UDP, + [NGBE_PT_VXLAN_IPV6_EXT_SCTP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_SCTP, + [NGBE_PT_VXLAN_IPV4_IPV6_EXT_UDP] = + RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_VXLAN | + RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4, + [NGBE_PT_VXLAN_IPV4_SCTP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4 | RTE_PTYPE_INNER_L4_SCTP, + [NGBE_PT_VXLAN_IPV4_EXT_SCTP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT | RTE_PTYPE_INNER_L4_SCTP, + [NGBE_PT_VXLAN_IPV4_EXT_TCP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT | RTE_PTYPE_INNER_L4_TCP, + [NGBE_PT_VXLAN_IPV4_EXT_UDP] = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT | RTE_PTYPE_INNER_L4_UDP, +}; + diff --git a/drivers/net/ngbe/ngbe_ptypes.h b/drivers/net/ngbe/ngbe_ptypes.h new file mode 100644 index 0000000000..1b965c02d8 --- /dev/null +++ b/drivers/net/ngbe/ngbe_ptypes.h @@ -0,0 +1,351 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + */ + +#ifndef _NGBE_PTYPE_H_ +#define _NGBE_PTYPE_H_ + +/** + * PTID(Packet Type Identifier, 8bits) + * - Bit 3:0 detailed types. + * - Bit 5:4 basic types. + * - Bit 7:6 tunnel types. + **/ +#define NGBE_PTID_NULL 0 +#define NGBE_PTID_MAX 256 +#define NGBE_PTID_MASK 0xFF +#define NGBE_PTID_MASK_TUNNEL 0x7F + +/* TUN */ +#define NGBE_PTID_TUN_IPV6 0x40 +#define NGBE_PTID_TUN_EI 0x00 /* IP */ +#define NGBE_PTID_TUN_EIG 0x10 /* IP+GRE */ +#define NGBE_PTID_TUN_EIGM 0x20 /* IP+GRE+MAC */ +#define NGBE_PTID_TUN_EIGMV 0x30 /* IP+GRE+MAC+VLAN */ + +/* PKT for !TUN */ +#define NGBE_PTID_PKT_TUN (0x80) +#define NGBE_PTID_PKT_MAC (0x10) +#define NGBE_PTID_PKT_IP (0x20) +#define NGBE_PTID_PKT_FCOE (0x30) + +/* TYP for PKT=mac */ +#define NGBE_PTID_TYP_MAC (0x01) +#define NGBE_PTID_TYP_TS (0x02) /* time sync */ +#define NGBE_PTID_TYP_FIP (0x03) +#define NGBE_PTID_TYP_LLDP (0x04) +#define NGBE_PTID_TYP_CNM (0x05) +#define NGBE_PTID_TYP_EAPOL (0x06) +#define NGBE_PTID_TYP_ARP (0x07) +#define NGBE_PTID_TYP_ETF (0x08) + +/* TYP for PKT=ip */ +#define NGBE_PTID_PKT_IPV6 (0x08) +#define NGBE_PTID_TYP_IPFRAG (0x01) +#define NGBE_PTID_TYP_IPDATA (0x02) +#define NGBE_PTID_TYP_UDP (0x03) +#define NGBE_PTID_TYP_TCP (0x04) +#define NGBE_PTID_TYP_SCTP (0x05) + +/* TYP for PKT=fcoe */ +#define NGBE_PTID_PKT_VFT (0x08) +#define NGBE_PTID_TYP_FCOE (0x00) +#define NGBE_PTID_TYP_FCDATA (0x01) +#define NGBE_PTID_TYP_FCRDY (0x02) +#define NGBE_PTID_TYP_FCRSP (0x03) +#define NGBE_PTID_TYP_FCOTHER (0x04) + +/* packet type non-ip values */ +enum ngbe_l2_ptids { + NGBE_PTID_L2_ABORTED = (NGBE_PTID_PKT_MAC), + NGBE_PTID_L2_MAC = (NGBE_PTID_PKT_MAC | NGBE_PTID_TYP_MAC), + NGBE_PTID_L2_TMST = (NGBE_PTID_PKT_MAC | NGBE_PTID_TYP_TS), + NGBE_PTID_L2_FIP = (NGBE_PTID_PKT_MAC | NGBE_PTID_TYP_FIP), + NGBE_PTID_L2_LLDP = (NGBE_PTID_PKT_MAC | NGBE_PTID_TYP_LLDP), + NGBE_PTID_L2_CNM = (NGBE_PTID_PKT_MAC | NGBE_PTID_TYP_CNM), + NGBE_PTID_L2_EAPOL = (NGBE_PTID_PKT_MAC | NGBE_PTID_TYP_EAPOL), + NGBE_PTID_L2_ARP = (NGBE_PTID_PKT_MAC | NGBE_PTID_TYP_ARP), + + NGBE_PTID_L2_IPV4_FRAG = (NGBE_PTID_PKT_IP | NGBE_PTID_TYP_IPFRAG), + NGBE_PTID_L2_IPV4 = (NGBE_PTID_PKT_IP | NGBE_PTID_TYP_IPDATA), + NGBE_PTID_L2_IPV4_UDP = (NGBE_PTID_PKT_IP | NGBE_PTID_TYP_UDP), + NGBE_PTID_L2_IPV4_TCP = (NGBE_PTID_PKT_IP | NGBE_PTID_TYP_TCP), + NGBE_PTID_L2_IPV4_SCTP = (NGBE_PTID_PKT_IP | NGBE_PTID_TYP_SCTP), + NGBE_PTID_L2_IPV6_FRAG = (NGBE_PTID_PKT_IP | NGBE_PTID_PKT_IPV6 | + NGBE_PTID_TYP_IPFRAG), + NGBE_PTID_L2_IPV6 = (NGBE_PTID_PKT_IP | NGBE_PTID_PKT_IPV6 | + NGBE_PTID_TYP_IPDATA), + NGBE_PTID_L2_IPV6_UDP = (NGBE_PTID_PKT_IP | NGBE_PTID_PKT_IPV6 | + NGBE_PTID_TYP_UDP), + NGBE_PTID_L2_IPV6_TCP = (NGBE_PTID_PKT_IP | NGBE_PTID_PKT_IPV6 | + NGBE_PTID_TYP_TCP), + NGBE_PTID_L2_IPV6_SCTP = (NGBE_PTID_PKT_IP | NGBE_PTID_PKT_IPV6 | + NGBE_PTID_TYP_SCTP), + + NGBE_PTID_L2_FCOE = (NGBE_PTID_PKT_FCOE | + NGBE_PTID_TYP_FCOE), + NGBE_PTID_L2_FCOE_FCDATA = (NGBE_PTID_PKT_FCOE | + NGBE_PTID_TYP_FCDATA), + NGBE_PTID_L2_FCOE_FCRDY = (NGBE_PTID_PKT_FCOE | + NGBE_PTID_TYP_FCRDY), + NGBE_PTID_L2_FCOE_FCRSP = (NGBE_PTID_PKT_FCOE | + NGBE_PTID_TYP_FCRSP), + NGBE_PTID_L2_FCOE_FCOTHER = (NGBE_PTID_PKT_FCOE | + NGBE_PTID_TYP_FCOTHER), + NGBE_PTID_L2_FCOE_VFT = (NGBE_PTID_PKT_FCOE | + NGBE_PTID_PKT_VFT), + NGBE_PTID_L2_FCOE_VFT_FCDATA = (NGBE_PTID_PKT_FCOE | + NGBE_PTID_PKT_VFT | NGBE_PTID_TYP_FCDATA), + NGBE_PTID_L2_FCOE_VFT_FCRDY = (NGBE_PTID_PKT_FCOE | + NGBE_PTID_PKT_VFT | NGBE_PTID_TYP_FCRDY), + NGBE_PTID_L2_FCOE_VFT_FCRSP = (NGBE_PTID_PKT_FCOE | + NGBE_PTID_PKT_VFT | NGBE_PTID_TYP_FCRSP), + NGBE_PTID_L2_FCOE_VFT_FCOTHER = (NGBE_PTID_PKT_FCOE | + NGBE_PTID_PKT_VFT | NGBE_PTID_TYP_FCOTHER), + + NGBE_PTID_L2_TUN4_MAC = (NGBE_PTID_PKT_TUN | + NGBE_PTID_TUN_EIGM), + NGBE_PTID_L2_TUN6_MAC = (NGBE_PTID_PKT_TUN | + NGBE_PTID_TUN_IPV6 | NGBE_PTID_TUN_EIGM), +}; + + +/* + * PTYPE(Packet Type, 32bits) + * - Bit 3:0 is for L2 types. + * - Bit 7:4 is for L3 or outer L3 (for tunneling case) types. + * - Bit 11:8 is for L4 or outer L4 (for tunneling case) types. + * - Bit 15:12 is for tunnel types. + * - Bit 19:16 is for inner L2 types. + * - Bit 23:20 is for inner L3 types. + * - Bit 27:24 is for inner L4 types. + * - Bit 31:28 is reserved. + * please ref to rte_mbuf.h: rte_mbuf.packet_type + */ +struct rte_ngbe_ptype { + u32 l2:4; /* outer mac */ + u32 l3:4; /* outer internet protocol */ + u32 l4:4; /* outer transport protocol */ + u32 tun:4; /* tunnel protocol */ + + u32 el2:4; /* inner mac */ + u32 el3:4; /* inner internet protocol */ + u32 el4:4; /* inner transport protocol */ + u32 rsv:3; + u32 known:1; +}; + +#ifndef RTE_PTYPE_UNKNOWN +#define RTE_PTYPE_UNKNOWN 0x00000000 +#define RTE_PTYPE_L2_ETHER 0x00000001 +#define RTE_PTYPE_L2_ETHER_TIMESYNC 0x00000002 +#define RTE_PTYPE_L2_ETHER_ARP 0x00000003 +#define RTE_PTYPE_L2_ETHER_LLDP 0x00000004 +#define RTE_PTYPE_L2_ETHER_NSH 0x00000005 +#define RTE_PTYPE_L2_ETHER_FCOE 0x00000009 +#define RTE_PTYPE_L3_IPV4 0x00000010 +#define RTE_PTYPE_L3_IPV4_EXT 0x00000030 +#define RTE_PTYPE_L3_IPV6 0x00000040 +#define RTE_PTYPE_L3_IPV4_EXT_UNKNOWN 0x00000090 +#define RTE_PTYPE_L3_IPV6_EXT 0x000000c0 +#define RTE_PTYPE_L3_IPV6_EXT_UNKNOWN 0x000000e0 +#define RTE_PTYPE_L4_TCP 0x00000100 +#define RTE_PTYPE_L4_UDP 0x00000200 +#define RTE_PTYPE_L4_FRAG 0x00000300 +#define RTE_PTYPE_L4_SCTP 0x00000400 +#define RTE_PTYPE_L4_ICMP 0x00000500 +#define RTE_PTYPE_L4_NONFRAG 0x00000600 +#define RTE_PTYPE_TUNNEL_IP 0x00001000 +#define RTE_PTYPE_TUNNEL_GRE 0x00002000 +#define RTE_PTYPE_TUNNEL_VXLAN 0x00003000 +#define RTE_PTYPE_TUNNEL_NVGRE 0x00004000 +#define RTE_PTYPE_TUNNEL_GENEVE 0x00005000 +#define RTE_PTYPE_TUNNEL_GRENAT 0x00006000 +#define RTE_PTYPE_INNER_L2_ETHER 0x00010000 +#define RTE_PTYPE_INNER_L2_ETHER_VLAN 0x00020000 +#define RTE_PTYPE_INNER_L3_IPV4 0x00100000 +#define RTE_PTYPE_INNER_L3_IPV4_EXT 0x00200000 +#define RTE_PTYPE_INNER_L3_IPV6 0x00300000 +#define RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN 0x00400000 +#define RTE_PTYPE_INNER_L3_IPV6_EXT 0x00500000 +#define RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN 0x00600000 +#define RTE_PTYPE_INNER_L4_TCP 0x01000000 +#define RTE_PTYPE_INNER_L4_UDP 0x02000000 +#define RTE_PTYPE_INNER_L4_FRAG 0x03000000 +#define RTE_PTYPE_INNER_L4_SCTP 0x04000000 +#define RTE_PTYPE_INNER_L4_ICMP 0x05000000 +#define RTE_PTYPE_INNER_L4_NONFRAG 0x06000000 +#endif /* !RTE_PTYPE_UNKNOWN */ +#define RTE_PTYPE_L3_IPV4u RTE_PTYPE_L3_IPV4_EXT_UNKNOWN +#define RTE_PTYPE_L3_IPV6u RTE_PTYPE_L3_IPV6_EXT_UNKNOWN +#define RTE_PTYPE_INNER_L3_IPV4u RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN +#define RTE_PTYPE_INNER_L3_IPV6u RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN +#define RTE_PTYPE_L2_ETHER_FIP RTE_PTYPE_L2_ETHER +#define RTE_PTYPE_L2_ETHER_CNM RTE_PTYPE_L2_ETHER +#define RTE_PTYPE_L2_ETHER_EAPOL RTE_PTYPE_L2_ETHER +#define RTE_PTYPE_L2_ETHER_FILTER RTE_PTYPE_L2_ETHER + +u32 *ngbe_get_supported_ptypes(void); +u32 ngbe_decode_ptype(u8 ptid); +u8 ngbe_encode_ptype(u32 ptype); + +/** + * PT(Packet Type, 32bits) + * - Bit 3:0 is for L2 types. + * - Bit 7:4 is for L3 or outer L3 (for tunneling case) types. + * - Bit 11:8 is for L4 or outer L4 (for tunneling case) types. + * - Bit 15:12 is for tunnel types. + * - Bit 19:16 is for inner L2 types. + * - Bit 23:20 is for inner L3 types. + * - Bit 27:24 is for inner L4 types. + * - Bit 31:28 is reserved. + * PT is a more accurate version of PTYPE + **/ +#define NGBE_PT_ETHER 0x00 +#define NGBE_PT_IPV4 0x01 +#define NGBE_PT_IPV4_TCP 0x11 +#define NGBE_PT_IPV4_UDP 0x21 +#define NGBE_PT_IPV4_SCTP 0x41 +#define NGBE_PT_IPV4_EXT 0x03 +#define NGBE_PT_IPV4_EXT_TCP 0x13 +#define NGBE_PT_IPV4_EXT_UDP 0x23 +#define NGBE_PT_IPV4_EXT_SCTP 0x43 +#define NGBE_PT_IPV6 0x04 +#define NGBE_PT_IPV6_TCP 0x14 +#define NGBE_PT_IPV6_UDP 0x24 +#define NGBE_PT_IPV6_SCTP 0x44 +#define NGBE_PT_IPV6_EXT 0x0C +#define NGBE_PT_IPV6_EXT_TCP 0x1C +#define NGBE_PT_IPV6_EXT_UDP 0x2C +#define NGBE_PT_IPV6_EXT_SCTP 0x4C +#define NGBE_PT_IPV4_IPV6 0x05 +#define NGBE_PT_IPV4_IPV6_TCP 0x15 +#define NGBE_PT_IPV4_IPV6_UDP 0x25 +#define NGBE_PT_IPV4_IPV6_SCTP 0x45 +#define NGBE_PT_IPV4_EXT_IPV6 0x07 +#define NGBE_PT_IPV4_EXT_IPV6_TCP 0x17 +#define NGBE_PT_IPV4_EXT_IPV6_UDP 0x27 +#define NGBE_PT_IPV4_EXT_IPV6_SCTP 0x47 +#define NGBE_PT_IPV4_IPV6_EXT 0x0D +#define NGBE_PT_IPV4_IPV6_EXT_TCP 0x1D +#define NGBE_PT_IPV4_IPV6_EXT_UDP 0x2D +#define NGBE_PT_IPV4_IPV6_EXT_SCTP 0x4D +#define NGBE_PT_IPV4_EXT_IPV6_EXT 0x0F +#define NGBE_PT_IPV4_EXT_IPV6_EXT_TCP 0x1F +#define NGBE_PT_IPV4_EXT_IPV6_EXT_UDP 0x2F +#define NGBE_PT_IPV4_EXT_IPV6_EXT_SCTP 0x4F + +#define NGBE_PT_NVGRE 0x00 +#define NGBE_PT_NVGRE_IPV4 0x01 +#define NGBE_PT_NVGRE_IPV4_TCP 0x11 +#define NGBE_PT_NVGRE_IPV4_UDP 0x21 +#define NGBE_PT_NVGRE_IPV4_SCTP 0x41 +#define NGBE_PT_NVGRE_IPV4_EXT 0x03 +#define NGBE_PT_NVGRE_IPV4_EXT_TCP 0x13 +#define NGBE_PT_NVGRE_IPV4_EXT_UDP 0x23 +#define NGBE_PT_NVGRE_IPV4_EXT_SCTP 0x43 +#define NGBE_PT_NVGRE_IPV6 0x04 +#define NGBE_PT_NVGRE_IPV6_TCP 0x14 +#define NGBE_PT_NVGRE_IPV6_UDP 0x24 +#define NGBE_PT_NVGRE_IPV6_SCTP 0x44 +#define NGBE_PT_NVGRE_IPV6_EXT 0x0C +#define NGBE_PT_NVGRE_IPV6_EXT_TCP 0x1C +#define NGBE_PT_NVGRE_IPV6_EXT_UDP 0x2C +#define NGBE_PT_NVGRE_IPV6_EXT_SCTP 0x4C +#define NGBE_PT_NVGRE_IPV4_IPV6 0x05 +#define NGBE_PT_NVGRE_IPV4_IPV6_TCP 0x15 +#define NGBE_PT_NVGRE_IPV4_IPV6_UDP 0x25 +#define NGBE_PT_NVGRE_IPV4_IPV6_EXT 0x0D +#define NGBE_PT_NVGRE_IPV4_IPV6_EXT_TCP 0x1D +#define NGBE_PT_NVGRE_IPV4_IPV6_EXT_UDP 0x2D + +#define NGBE_PT_VXLAN 0x80 +#define NGBE_PT_VXLAN_IPV4 0x81 +#define NGBE_PT_VXLAN_IPV4_TCP 0x91 +#define NGBE_PT_VXLAN_IPV4_UDP 0xA1 +#define NGBE_PT_VXLAN_IPV4_SCTP 0xC1 +#define NGBE_PT_VXLAN_IPV4_EXT 0x83 +#define NGBE_PT_VXLAN_IPV4_EXT_TCP 0x93 +#define NGBE_PT_VXLAN_IPV4_EXT_UDP 0xA3 +#define NGBE_PT_VXLAN_IPV4_EXT_SCTP 0xC3 +#define NGBE_PT_VXLAN_IPV6 0x84 +#define NGBE_PT_VXLAN_IPV6_TCP 0x94 +#define NGBE_PT_VXLAN_IPV6_UDP 0xA4 +#define NGBE_PT_VXLAN_IPV6_SCTP 0xC4 +#define NGBE_PT_VXLAN_IPV6_EXT 0x8C +#define NGBE_PT_VXLAN_IPV6_EXT_TCP 0x9C +#define NGBE_PT_VXLAN_IPV6_EXT_UDP 0xAC +#define NGBE_PT_VXLAN_IPV6_EXT_SCTP 0xCC +#define NGBE_PT_VXLAN_IPV4_IPV6 0x85 +#define NGBE_PT_VXLAN_IPV4_IPV6_TCP 0x95 +#define NGBE_PT_VXLAN_IPV4_IPV6_UDP 0xA5 +#define NGBE_PT_VXLAN_IPV4_IPV6_EXT 0x8D +#define NGBE_PT_VXLAN_IPV4_IPV6_EXT_TCP 0x9D +#define NGBE_PT_VXLAN_IPV4_IPV6_EXT_UDP 0xAD + +#define NGBE_PT_MAX 256 +extern const u32 ngbe_ptype_table[NGBE_PT_MAX]; +extern const u32 ngbe_ptype_table_tn[NGBE_PT_MAX]; + + +/* ether type filter list: one static filter per filter consumer. This is + * to avoid filter collisions later. Add new filters + * here!! + * EAPOL 802.1x (0x888e): Filter 0 + * FCoE (0x8906): Filter 2 + * 1588 (0x88f7): Filter 3 + * FIP (0x8914): Filter 4 + * LLDP (0x88CC): Filter 5 + * LACP (0x8809): Filter 6 + * FC (0x8808): Filter 7 + */ +#define NGBE_ETF_ID_EAPOL 0 +#define NGBE_ETF_ID_FCOE 2 +#define NGBE_ETF_ID_1588 3 +#define NGBE_ETF_ID_FIP 4 +#define NGBE_ETF_ID_LLDP 5 +#define NGBE_ETF_ID_LACP 6 +#define NGBE_ETF_ID_FC 7 +#define NGBE_ETF_ID_MAX 8 + +#define NGBE_PTID_ETF_MIN 0x18 +#define NGBE_PTID_ETF_MAX 0x1F +static inline int ngbe_etflt_id(u8 ptid) +{ + if (ptid >= NGBE_PTID_ETF_MIN && ptid <= NGBE_PTID_ETF_MAX) + return ptid - NGBE_PTID_ETF_MIN; + else + return -1; +} + +struct ngbe_udphdr { + __be16 source; + __be16 dest; + __be16 len; + __be16 check; +}; + +struct ngbe_vxlanhdr { + __be32 vx_flags; + __be32 vx_vni; +}; + +struct ngbe_genevehdr { + u8 opt_len:6; + u8 ver:2; + u8 rsvd1:6; + u8 critical:1; + u8 oam:1; + __be16 proto_type; + + u8 vni[3]; + u8 rsvd2; +}; + +struct ngbe_nvgrehdr { + __be16 flags; + __be16 proto; + __be32 tni; +}; + +#endif /* _NGBE_PTYPE_H_ */ diff --git a/drivers/net/ngbe/ngbe_rxtx.h b/drivers/net/ngbe/ngbe_rxtx.h index 2db5cc3f2a..f30da10ae3 100644 --- a/drivers/net/ngbe/ngbe_rxtx.h +++ b/drivers/net/ngbe/ngbe_rxtx.h @@ -74,7 +74,6 @@ struct ngbe_tx_desc { sizeof(struct ngbe_rx_desc)) #define NGBE_TX_MAX_SEG 40 -#define NGBE_PTID_MASK 0xFF /** * Structure associated with each descriptor of the RX ring of a RX queue. From patchwork Wed Jun 2 09:41:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93781 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 39880A0524; Wed, 2 Jun 2021 11:42:04 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 854884118B; Wed, 2 Jun 2021 11:40:07 +0200 (CEST) Received: from smtpbg516.qq.com (smtpbg516.qq.com [203.205.250.54]) by mails.dpdk.org (Postfix) with ESMTP id 5A19D41160 for ; Wed, 2 Jun 2021 11:40:04 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626799tydzhdpe Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:39:59 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: fYJ0eR3mMJ2wnM3AwD7cupw1bWK9QObFCqtitNkppWnRwulZhGy9EiTOpkSA3 pIWz9xSt2t0lhsKuidmtkDCI2RVL8bpQCw7n48t6iQOaflnlrJubZ/WSb66Z+4iihSV1YSe i7g+4KSlJ6u+NcxlGJdnz3L2feidSReSxthSfvxgRi2p7wjs2Ps8To0JNXZ22kbMwabfR95 2txkV1eI9QBCkqf/GODJYlzwYVy84U9W3iW9b2+pLggFCBisddwwXNOWOQLHoMhx4fyX6Jh ei/e7aEt3m//wtq0mTZpQnGdiJvcbCK0qNAqAcZBkvcOFsF4iOAVCKGjF4BzGrQcd5jfHjw mUEP1lOWuXvloVxLqauG6NP5K6big== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:41:03 +0800 Message-Id: <20210602094108.1575640-20-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign1 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 19/24] net/ngbe: add simple Rx and Tx flow 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 Sender: "dev" Initialize device with the simplest receive and transmit functions. Signed-off-by: Jiawen Wu --- drivers/net/ngbe/ngbe_ethdev.c | 8 +- drivers/net/ngbe/ngbe_ethdev.h | 6 + drivers/net/ngbe/ngbe_rxtx.c | 482 +++++++++++++++++++++++++++++++++ drivers/net/ngbe/ngbe_rxtx.h | 110 ++++++++ 4 files changed, 604 insertions(+), 2 deletions(-) diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 672db88133..4dab920caa 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -109,6 +109,8 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) PMD_INIT_FUNC_TRACE(); eth_dev->dev_ops = &ngbe_eth_dev_ops; + eth_dev->rx_pkt_burst = &ngbe_recv_pkts; + eth_dev->tx_pkt_burst = &ngbe_xmit_pkts_simple; if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; @@ -357,8 +359,10 @@ ngbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) const uint32_t * ngbe_dev_supported_ptypes_get(struct rte_eth_dev *dev) { - RTE_SET_USED(dev); - return ngbe_get_supported_ptypes(); + if (dev->rx_pkt_burst == ngbe_recv_pkts) + return ngbe_get_supported_ptypes(); + + return NULL; } /* return 0 means link status changed, -1 means not changed */ diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h index 6881351252..c0f8483eca 100644 --- a/drivers/net/ngbe/ngbe_ethdev.h +++ b/drivers/net/ngbe/ngbe_ethdev.h @@ -75,6 +75,12 @@ int ngbe_dev_rx_init(struct rte_eth_dev *dev); void ngbe_dev_tx_init(struct rte_eth_dev *dev); +uint16_t ngbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, + uint16_t nb_pkts); + +uint16_t ngbe_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, + uint16_t nb_pkts); + int ngbe_dev_link_update_share(struct rte_eth_dev *dev, int wait_to_complete); diff --git a/drivers/net/ngbe/ngbe_rxtx.c b/drivers/net/ngbe/ngbe_rxtx.c index 68d7e651af..9462da5b7a 100644 --- a/drivers/net/ngbe/ngbe_rxtx.c +++ b/drivers/net/ngbe/ngbe_rxtx.c @@ -15,10 +15,492 @@ #include "ngbe_ethdev.h" #include "ngbe_rxtx.h" +/* + * Prefetch a cache line into all cache levels. + */ +#define rte_ngbe_prefetch(p) rte_prefetch0(p) + +/********************************************************************* + * + * TX functions + * + **********************************************************************/ + +/* + * Check for descriptors with their DD bit set and free mbufs. + * Return the total number of buffers freed. + */ +static __rte_always_inline int +ngbe_tx_free_bufs(struct ngbe_tx_queue *txq) +{ + struct ngbe_tx_entry *txep; + uint32_t status; + int i, nb_free = 0; + struct rte_mbuf *m, *free[RTE_NGBE_TX_MAX_FREE_BUF_SZ]; + + /* check DD bit on threshold descriptor */ + status = txq->tx_ring[txq->tx_next_dd].dw3; + if (!(status & rte_cpu_to_le_32(NGBE_TXD_DD))) { + if (txq->nb_tx_free >> 1 < txq->tx_free_thresh) + ngbe_set32_masked(txq->tdc_reg_addr, + NGBE_TXCFG_FLUSH, NGBE_TXCFG_FLUSH); + return 0; + } + + /* + * first buffer to free from S/W ring is at index + * tx_next_dd - (tx_free_thresh-1) + */ + txep = &txq->sw_ring[txq->tx_next_dd - (txq->tx_free_thresh - 1)]; + for (i = 0; i < txq->tx_free_thresh; ++i, ++txep) { + /* free buffers one at a time */ + m = rte_pktmbuf_prefree_seg(txep->mbuf); + txep->mbuf = NULL; + + if (unlikely(m == NULL)) + continue; + + if (nb_free >= RTE_NGBE_TX_MAX_FREE_BUF_SZ || + (nb_free > 0 && m->pool != free[0]->pool)) { + rte_mempool_put_bulk(free[0]->pool, + (void **)free, nb_free); + nb_free = 0; + } + + free[nb_free++] = m; + } + + if (nb_free > 0) + rte_mempool_put_bulk(free[0]->pool, (void **)free, nb_free); + + /* buffers were freed, update counters */ + txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + txq->tx_free_thresh); + txq->tx_next_dd = (uint16_t)(txq->tx_next_dd + txq->tx_free_thresh); + if (txq->tx_next_dd >= txq->nb_tx_desc) + txq->tx_next_dd = (uint16_t)(txq->tx_free_thresh - 1); + + return txq->tx_free_thresh; +} + +/* Populate 4 descriptors with data from 4 mbufs */ +static inline void +tx4(volatile struct ngbe_tx_desc *txdp, struct rte_mbuf **pkts) +{ + uint64_t buf_dma_addr; + uint32_t pkt_len; + int i; + + for (i = 0; i < 4; ++i, ++txdp, ++pkts) { + buf_dma_addr = rte_mbuf_data_iova(*pkts); + pkt_len = (*pkts)->data_len; + + /* write data to descriptor */ + txdp->qw0 = rte_cpu_to_le_64(buf_dma_addr); + txdp->dw2 = cpu_to_le32(NGBE_TXD_FLAGS | + NGBE_TXD_DATLEN(pkt_len)); + txdp->dw3 = cpu_to_le32(NGBE_TXD_PAYLEN(pkt_len)); + + rte_prefetch0(&(*pkts)->pool); + } +} + +/* Populate 1 descriptor with data from 1 mbuf */ +static inline void +tx1(volatile struct ngbe_tx_desc *txdp, struct rte_mbuf **pkts) +{ + uint64_t buf_dma_addr; + uint32_t pkt_len; + + buf_dma_addr = rte_mbuf_data_iova(*pkts); + pkt_len = (*pkts)->data_len; + + /* write data to descriptor */ + txdp->qw0 = cpu_to_le64(buf_dma_addr); + txdp->dw2 = cpu_to_le32(NGBE_TXD_FLAGS | + NGBE_TXD_DATLEN(pkt_len)); + txdp->dw3 = cpu_to_le32(NGBE_TXD_PAYLEN(pkt_len)); + + rte_prefetch0(&(*pkts)->pool); +} + +/* + * Fill H/W descriptor ring with mbuf data. + * Copy mbuf pointers to the S/W ring. + */ +static inline void +ngbe_tx_fill_hw_ring(struct ngbe_tx_queue *txq, struct rte_mbuf **pkts, + uint16_t nb_pkts) +{ + volatile struct ngbe_tx_desc *txdp = &txq->tx_ring[txq->tx_tail]; + struct ngbe_tx_entry *txep = &txq->sw_ring[txq->tx_tail]; + const int N_PER_LOOP = 4; + const int N_PER_LOOP_MASK = N_PER_LOOP - 1; + int mainpart, leftover; + int i, j; + + /* + * Process most of the packets in chunks of N pkts. Any + * leftover packets will get processed one at a time. + */ + mainpart = (nb_pkts & ((uint32_t)~N_PER_LOOP_MASK)); + leftover = (nb_pkts & ((uint32_t)N_PER_LOOP_MASK)); + for (i = 0; i < mainpart; i += N_PER_LOOP) { + /* Copy N mbuf pointers to the S/W ring */ + for (j = 0; j < N_PER_LOOP; ++j) + (txep + i + j)->mbuf = *(pkts + i + j); + tx4(txdp + i, pkts + i); + } + + if (unlikely(leftover > 0)) { + for (i = 0; i < leftover; ++i) { + (txep + mainpart + i)->mbuf = *(pkts + mainpart + i); + tx1(txdp + mainpart + i, pkts + mainpart + i); + } + } +} + +static inline uint16_t +tx_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, + uint16_t nb_pkts) +{ + struct ngbe_tx_queue *txq = (struct ngbe_tx_queue *)tx_queue; + uint16_t n = 0; + + /* + * Begin scanning the H/W ring for done descriptors when the + * number of available descriptors drops below tx_free_thresh. For + * each done descriptor, free the associated buffer. + */ + if (txq->nb_tx_free < txq->tx_free_thresh) + ngbe_tx_free_bufs(txq); + + /* Only use descriptors that are available */ + nb_pkts = (uint16_t)RTE_MIN(txq->nb_tx_free, nb_pkts); + if (unlikely(nb_pkts == 0)) + return 0; + + /* Use exactly nb_pkts descriptors */ + txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_pkts); + + /* + * At this point, we know there are enough descriptors in the + * ring to transmit all the packets. This assumes that each + * mbuf contains a single segment, and that no new offloads + * are expected, which would require a new context descriptor. + */ + + /* + * See if we're going to wrap-around. If so, handle the top + * of the descriptor ring first, then do the bottom. If not, + * the processing looks just like the "bottom" part anyway... + */ + if ((txq->tx_tail + nb_pkts) > txq->nb_tx_desc) { + n = (uint16_t)(txq->nb_tx_desc - txq->tx_tail); + ngbe_tx_fill_hw_ring(txq, tx_pkts, n); + txq->tx_tail = 0; + } + + /* Fill H/W descriptor ring with mbuf data */ + ngbe_tx_fill_hw_ring(txq, tx_pkts + n, (uint16_t)(nb_pkts - n)); + txq->tx_tail = (uint16_t)(txq->tx_tail + (nb_pkts - n)); + + /* + * Check for wrap-around. This would only happen if we used + * up to the last descriptor in the ring, no more, no less. + */ + if (txq->tx_tail >= txq->nb_tx_desc) + txq->tx_tail = 0; + + PMD_TX_LOG(DEBUG, "port_id=%u queue_id=%u tx_tail=%u nb_tx=%u", + (uint16_t)txq->port_id, (uint16_t)txq->queue_id, + (uint16_t)txq->tx_tail, (uint16_t)nb_pkts); + + /* update tail pointer */ + rte_wmb(); + ngbe_set32_relaxed(txq->tdt_reg_addr, txq->tx_tail); + + return nb_pkts; +} + +uint16_t +ngbe_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, + uint16_t nb_pkts) +{ + uint16_t nb_tx; + + /* Try to transmit at least chunks of TX_MAX_BURST pkts */ + if (likely(nb_pkts <= RTE_PMD_NGBE_TX_MAX_BURST)) + return tx_xmit_pkts(tx_queue, tx_pkts, nb_pkts); + + /* transmit more than the max burst, in chunks of TX_MAX_BURST */ + nb_tx = 0; + while (nb_pkts) { + uint16_t ret, n; + + n = (uint16_t)RTE_MIN(nb_pkts, RTE_PMD_NGBE_TX_MAX_BURST); + ret = tx_xmit_pkts(tx_queue, &tx_pkts[nb_tx], n); + nb_tx = (uint16_t)(nb_tx + ret); + nb_pkts = (uint16_t)(nb_pkts - ret); + if (ret < n) + break; + } + + return nb_tx; +} + #ifndef DEFAULT_TX_FREE_THRESH #define DEFAULT_TX_FREE_THRESH 32 #endif +/********************************************************************* + * + * RX functions + * + **********************************************************************/ +static inline uint32_t +ngbe_rxd_pkt_info_to_pkt_type(uint32_t pkt_info, uint16_t ptid_mask) +{ + uint16_t ptid = NGBE_RXD_PTID(pkt_info); + + ptid &= ptid_mask; + + return ngbe_decode_ptype(ptid); +} + +static inline uint64_t +ngbe_rxd_pkt_info_to_pkt_flags(uint32_t pkt_info) +{ + static uint64_t ip_rss_types_map[16] __rte_cache_aligned = { + 0, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, + 0, PKT_RX_RSS_HASH, 0, PKT_RX_RSS_HASH, + PKT_RX_RSS_HASH, 0, 0, 0, + 0, 0, 0, PKT_RX_FDIR, + }; + return ip_rss_types_map[NGBE_RXD_RSSTYPE(pkt_info)]; +} + +static inline uint64_t +rx_desc_status_to_pkt_flags(uint32_t rx_status, uint64_t vlan_flags) +{ + uint64_t pkt_flags; + + /* + * Check if VLAN present only. + * Do not check whether L3/L4 rx checksum done by NIC or not, + * That can be found from rte_eth_rxmode.offloads flag + */ + pkt_flags = (rx_status & NGBE_RXD_STAT_VLAN && + vlan_flags & PKT_RX_VLAN_STRIPPED) + ? vlan_flags : 0; + + return pkt_flags; +} + +static inline uint64_t +rx_desc_error_to_pkt_flags(uint32_t rx_status) +{ + uint64_t pkt_flags = 0; + + /* checksum offload can't be disabled */ + if (rx_status & NGBE_RXD_STAT_IPCS) { + pkt_flags |= (rx_status & NGBE_RXD_ERR_IPCS + ? PKT_RX_IP_CKSUM_BAD : PKT_RX_IP_CKSUM_GOOD); + } + + if (rx_status & NGBE_RXD_STAT_L4CS) { + pkt_flags |= (rx_status & NGBE_RXD_ERR_L4CS + ? PKT_RX_L4_CKSUM_BAD : PKT_RX_L4_CKSUM_GOOD); + } + + if (rx_status & NGBE_RXD_STAT_EIPCS && + rx_status & NGBE_RXD_ERR_EIPCS) { + pkt_flags |= PKT_RX_OUTER_IP_CKSUM_BAD; + } + + + return pkt_flags; +} + +uint16_t +ngbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, + uint16_t nb_pkts) +{ + struct ngbe_rx_queue *rxq; + volatile struct ngbe_rx_desc *rx_ring; + volatile struct ngbe_rx_desc *rxdp; + struct ngbe_rx_entry *sw_ring; + struct ngbe_rx_entry *rxe; + struct rte_mbuf *rxm; + struct rte_mbuf *nmb; + struct ngbe_rx_desc rxd; + uint64_t dma_addr; + uint32_t staterr; + uint32_t pkt_info; + uint16_t pkt_len; + uint16_t rx_id; + uint16_t nb_rx; + uint16_t nb_hold; + uint64_t pkt_flags; + + nb_rx = 0; + nb_hold = 0; + rxq = rx_queue; + rx_id = rxq->rx_tail; + rx_ring = rxq->rx_ring; + sw_ring = rxq->sw_ring; + struct rte_eth_dev *dev = &rte_eth_devices[rxq->port_id]; + while (nb_rx < nb_pkts) { + /* + * The order of operations here is important as the DD status + * bit must not be read after any other descriptor fields. + * rx_ring and rxdp are pointing to volatile data so the order + * of accesses cannot be reordered by the compiler. If they were + * not volatile, they could be reordered which could lead to + * using invalid descriptor fields when read from rxd. + */ + rxdp = &rx_ring[rx_id]; + staterr = rxdp->qw1.lo.status; + if (!(staterr & rte_cpu_to_le_32(NGBE_RXD_STAT_DD))) + break; + rxd = *rxdp; + + /* + * End of packet. + * + * If the NGBE_RXD_STAT_EOP flag is not set, the RX packet + * is likely to be invalid and to be dropped by the various + * validation checks performed by the network stack. + * + * Allocate a new mbuf to replenish the RX ring descriptor. + * If the allocation fails: + * - arrange for that RX descriptor to be the first one + * being parsed the next time the receive function is + * invoked [on the same queue]. + * + * - Stop parsing the RX ring and return immediately. + * + * This policy do not drop the packet received in the RX + * descriptor for which the allocation of a new mbuf failed. + * Thus, it allows that packet to be later retrieved if + * mbuf have been freed in the mean time. + * As a side effect, holding RX descriptors instead of + * systematically giving them back to the NIC may lead to + * RX ring exhaustion situations. + * However, the NIC can gracefully prevent such situations + * to happen by sending specific "back-pressure" flow control + * frames to its peer(s). + */ + PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_id=%u " + "ext_err_stat=0x%08x pkt_len=%u", + (uint16_t)rxq->port_id, (uint16_t)rxq->queue_id, + (uint16_t)rx_id, (uint32_t)staterr, + (uint16_t)rte_le_to_cpu_16(rxd.qw1.hi.len)); + + nmb = rte_mbuf_raw_alloc(rxq->mb_pool); + if (nmb == NULL) { + PMD_RX_LOG(DEBUG, "RX mbuf alloc failed port_id=%u " + "queue_id=%u", (uint16_t)rxq->port_id, + (uint16_t)rxq->queue_id); + dev->data->rx_mbuf_alloc_failed++; + break; + } + + nb_hold++; + rxe = &sw_ring[rx_id]; + rx_id++; + if (rx_id == rxq->nb_rx_desc) + rx_id = 0; + + /* Prefetch next mbuf while processing current one. */ + rte_ngbe_prefetch(sw_ring[rx_id].mbuf); + + /* + * When next RX descriptor is on a cache-line boundary, + * prefetch the next 4 RX descriptors and the next 8 pointers + * to mbufs. + */ + if ((rx_id & 0x3) == 0) { + rte_ngbe_prefetch(&rx_ring[rx_id]); + rte_ngbe_prefetch(&sw_ring[rx_id]); + } + + rxm = rxe->mbuf; + rxe->mbuf = nmb; + dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(nmb)); + NGBE_RXD_HDRADDR(rxdp, 0); + NGBE_RXD_PKTADDR(rxdp, dma_addr); + + /* + * Initialize the returned mbuf. + * 1) setup generic mbuf fields: + * - number of segments, + * - next segment, + * - packet length, + * - RX port identifier. + * 2) integrate hardware offload data, if any: + * - RSS flag & hash, + * - IP checksum flag, + * - VLAN TCI, if any, + * - error flags. + */ + pkt_len = (uint16_t)(rte_le_to_cpu_16(rxd.qw1.hi.len) - + rxq->crc_len); + rxm->data_off = RTE_PKTMBUF_HEADROOM; + rte_packet_prefetch((char *)rxm->buf_addr + rxm->data_off); + rxm->nb_segs = 1; + rxm->next = NULL; + rxm->pkt_len = pkt_len; + rxm->data_len = pkt_len; + rxm->port = rxq->port_id; + + pkt_info = rte_le_to_cpu_32(rxd.qw0.dw0); + /* Only valid if PKT_RX_VLAN set in pkt_flags */ + rxm->vlan_tci = rte_le_to_cpu_16(rxd.qw1.hi.tag); + + pkt_flags = rx_desc_status_to_pkt_flags(staterr, + rxq->vlan_flags); + pkt_flags |= rx_desc_error_to_pkt_flags(staterr); + pkt_flags |= ngbe_rxd_pkt_info_to_pkt_flags(pkt_info); + rxm->ol_flags = pkt_flags; + rxm->packet_type = ngbe_rxd_pkt_info_to_pkt_type(pkt_info, + rxq->pkt_type_mask); + + if (likely(pkt_flags & PKT_RX_RSS_HASH)) + rxm->hash.rss = rte_le_to_cpu_32(rxd.qw0.dw1); + + /* + * Store the mbuf address into the next entry of the array + * of returned packets. + */ + rx_pkts[nb_rx++] = rxm; + } + rxq->rx_tail = rx_id; + + /* + * If the number of free RX descriptors is greater than the RX free + * threshold of the queue, advance the Receive Descriptor Tail (RDT) + * register. + * Update the RDT with the value of the last processed RX descriptor + * minus 1, to guarantee that the RDT register is never equal to the + * RDH register, which creates a "full" ring situation from the + * hardware point of view... + */ + nb_hold = (uint16_t)(nb_hold + rxq->nb_rx_hold); + if (nb_hold > rxq->rx_free_thresh) { + PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_tail=%u " + "nb_hold=%u nb_rx=%u", + (uint16_t)rxq->port_id, (uint16_t)rxq->queue_id, + (uint16_t)rx_id, (uint16_t)nb_hold, + (uint16_t)nb_rx); + rx_id = (uint16_t)((rx_id == 0) ? + (rxq->nb_rx_desc - 1) : (rx_id - 1)); + ngbe_set32(rxq->rdt_reg_addr, rx_id); + nb_hold = 0; + } + rxq->nb_rx_hold = nb_hold; + return nb_rx; +} + /********************************************************************* * * Queue management functions diff --git a/drivers/net/ngbe/ngbe_rxtx.h b/drivers/net/ngbe/ngbe_rxtx.h index f30da10ae3..d6b9127cb4 100644 --- a/drivers/net/ngbe/ngbe_rxtx.h +++ b/drivers/net/ngbe/ngbe_rxtx.h @@ -43,6 +43,85 @@ struct ngbe_rx_desc { } qw1; /* also as r.hdr_addr */ }; +/* @ngbe_rx_desc.qw0 */ +#define NGBE_RXD_PKTADDR(rxd, v) \ + (((volatile __le64 *)(rxd))[0] = cpu_to_le64(v)) + +/* @ngbe_rx_desc.qw1 */ +#define NGBE_RXD_HDRADDR(rxd, v) \ + (((volatile __le64 *)(rxd))[1] = cpu_to_le64(v)) + +/* @ngbe_rx_desc.dw0 */ +#define NGBE_RXD_RSSTYPE(dw) RS(dw, 0, 0xF) +#define NGBE_RSSTYPE_NONE 0 +#define NGBE_RSSTYPE_IPV4TCP 1 +#define NGBE_RSSTYPE_IPV4 2 +#define NGBE_RSSTYPE_IPV6TCP 3 +#define NGBE_RSSTYPE_IPV4SCTP 4 +#define NGBE_RSSTYPE_IPV6 5 +#define NGBE_RSSTYPE_IPV6SCTP 6 +#define NGBE_RSSTYPE_IPV4UDP 7 +#define NGBE_RSSTYPE_IPV6UDP 8 +#define NGBE_RSSTYPE_FDIR 15 +#define NGBE_RXD_SECTYPE(dw) RS(dw, 4, 0x3) +#define NGBE_RXD_SECTYPE_NONE LS(0, 4, 0x3) +#define NGBE_RXD_SECTYPE_IPSECESP LS(2, 4, 0x3) +#define NGBE_RXD_SECTYPE_IPSECAH LS(3, 4, 0x3) +#define NGBE_RXD_TPIDSEL(dw) RS(dw, 6, 0x7) +#define NGBE_RXD_PTID(dw) RS(dw, 9, 0xFF) +#define NGBE_RXD_RSCCNT(dw) RS(dw, 17, 0xF) +#define NGBE_RXD_HDRLEN(dw) RS(dw, 21, 0x3FF) +#define NGBE_RXD_SPH MS(31, 0x1) + +/* @ngbe_rx_desc.dw1 */ +/** bit 0-31, as rss hash when **/ +#define NGBE_RXD_RSSHASH(rxd) ((rxd)->qw0.dw1) + +/** bit 0-31, as ip csum when **/ +#define NGBE_RXD_IPID(rxd) ((rxd)->qw0.hi.ipid) +#define NGBE_RXD_CSUM(rxd) ((rxd)->qw0.hi.csum) + +/* @ngbe_rx_desc.dw2 */ +#define NGBE_RXD_STATUS(rxd) ((rxd)->qw1.lo.status) +/** bit 0-1 **/ +#define NGBE_RXD_STAT_DD MS(0, 0x1) /* Descriptor Done */ +#define NGBE_RXD_STAT_EOP MS(1, 0x1) /* End of Packet */ +/** bit 2-31, when EOP=0 **/ +#define NGBE_RXD_NEXTP_RESV(v) LS(v, 2, 0x3) +#define NGBE_RXD_NEXTP(dw) RS(dw, 4, 0xFFFF) /* Next Descriptor */ +/** bit 2-31, when EOP=1 **/ +#define NGBE_RXD_PKT_CLS_MASK MS(2, 0x7) /* Packet Class */ +#define NGBE_RXD_PKT_CLS_TC_RSS LS(0, 2, 0x7) /* RSS Hash */ +#define NGBE_RXD_PKT_CLS_FLM LS(1, 2, 0x7) /* FDir Match */ +#define NGBE_RXD_PKT_CLS_SYN LS(2, 2, 0x7) /* TCP Sync */ +#define NGBE_RXD_PKT_CLS_5TUPLE LS(3, 2, 0x7) /* 5 Tuple */ +#define NGBE_RXD_PKT_CLS_ETF LS(4, 2, 0x7) /* Ethertype Filter */ +#define NGBE_RXD_STAT_VLAN MS(5, 0x1) /* IEEE VLAN Packet */ +#define NGBE_RXD_STAT_UDPCS MS(6, 0x1) /* UDP xsum calculated */ +#define NGBE_RXD_STAT_L4CS MS(7, 0x1) /* L4 xsum calculated */ +#define NGBE_RXD_STAT_IPCS MS(8, 0x1) /* IP xsum calculated */ +#define NGBE_RXD_STAT_PIF MS(9, 0x1) /* Non-unicast address */ +#define NGBE_RXD_STAT_EIPCS MS(10, 0x1) /* Encap IP xsum calculated */ +#define NGBE_RXD_STAT_VEXT MS(11, 0x1) /* Multi-VLAN */ +#define NGBE_RXD_STAT_IPV6EX MS(12, 0x1) /* IPv6 with option header */ +#define NGBE_RXD_STAT_LLINT MS(13, 0x1) /* Pkt caused LLI */ +#define NGBE_RXD_STAT_1588 MS(14, 0x1) /* IEEE1588 Time Stamp */ +#define NGBE_RXD_STAT_SECP MS(15, 0x1) /* Security Processing */ +#define NGBE_RXD_STAT_LB MS(16, 0x1) /* Loopback Status */ +/*** bit 17-30, when PTYPE=IP ***/ +#define NGBE_RXD_STAT_BMC MS(17, 0x1) /* PTYPE=IP, BMC status */ +#define NGBE_RXD_ERR_HBO MS(23, 0x1) /* Header Buffer Overflow */ +#define NGBE_RXD_ERR_EIPCS MS(26, 0x1) /* Encap IP header error */ +#define NGBE_RXD_ERR_SECERR MS(27, 0x1) /* macsec or ipsec error */ +#define NGBE_RXD_ERR_RXE MS(29, 0x1) /* Any MAC Error */ +#define NGBE_RXD_ERR_L4CS MS(30, 0x1) /* TCP/UDP xsum error */ +#define NGBE_RXD_ERR_IPCS MS(31, 0x1) /* IP xsum error */ +#define NGBE_RXD_ERR_CSUM(dw) RS(dw, 30, 0x3) + +/* @ngbe_rx_desc.dw3 */ +#define NGBE_RXD_LENGTH(rxd) ((rxd)->qw1.hi.len) +#define NGBE_RXD_VLAN(rxd) ((rxd)->qw1.hi.tag) + /***************************************************************************** * Transmit Descriptor *****************************************************************************/ @@ -68,11 +147,40 @@ struct ngbe_tx_desc { __le32 dw3; /* r.olinfo_status, w.status */ }; +/* @ngbe_tx_desc.dw2 */ +#define NGBE_TXD_DATLEN(v) ((0xFFFF & (v))) /* data buffer length */ +#define NGBE_TXD_1588 ((0x1) << 19) /* IEEE1588 time stamp */ +#define NGBE_TXD_DATA ((0x0) << 20) /* data descriptor */ +#define NGBE_TXD_EOP ((0x1) << 24) /* End of Packet */ +#define NGBE_TXD_FCS ((0x1) << 25) /* Insert FCS */ +#define NGBE_TXD_LINKSEC ((0x1) << 26) /* Insert LinkSec */ +#define NGBE_TXD_ECU ((0x1) << 28) /* forward to ECU */ +#define NGBE_TXD_CNTAG ((0x1) << 29) /* insert CN tag */ +#define NGBE_TXD_VLE ((0x1) << 30) /* insert VLAN tag */ +#define NGBE_TXD_TSE ((0x1) << 31) /* transmit segmentation */ + +#define NGBE_TXD_FLAGS (NGBE_TXD_FCS | NGBE_TXD_EOP) + +/* @ngbe_tx_desc.dw3 */ +#define NGBE_TXD_DD_UNUSED NGBE_TXD_DD +#define NGBE_TXD_IDX_UNUSED(v) NGBE_TXD_IDX(v) +#define NGBE_TXD_CC ((0x1) << 7) /* check context */ +#define NGBE_TXD_IPSEC ((0x1) << 8) /* request ipsec offload */ +#define NGBE_TXD_L4CS ((0x1) << 9) /* insert TCP/UDP/SCTP csum */ +#define NGBE_TXD_IPCS ((0x1) << 10) /* insert IPv4 csum */ +#define NGBE_TXD_EIPCS ((0x1) << 11) /* insert outer IP csum */ +#define NGBE_TXD_MNGFLT ((0x1) << 12) /* enable management filter */ +#define NGBE_TXD_PAYLEN(v) ((0x7FFFF & (v)) << 13) /* payload length */ + +#define RTE_PMD_NGBE_TX_MAX_BURST 32 #define RTE_PMD_NGBE_RX_MAX_BURST 32 +#define RTE_NGBE_TX_MAX_FREE_BUF_SZ 64 #define RX_RING_SZ ((NGBE_RING_DESC_MAX + RTE_PMD_NGBE_RX_MAX_BURST) * \ sizeof(struct ngbe_rx_desc)) +#define rte_packet_prefetch(p) rte_prefetch1(p) + #define NGBE_TX_MAX_SEG 40 /** @@ -124,6 +232,8 @@ struct ngbe_rx_queue { uint8_t crc_len; /**< 0 if CRC stripped, 4 otherwise. */ uint8_t drop_en; /**< If not 0, set SRRCTL.Drop_En. */ uint8_t rx_deferred_start; /**< not in global dev start. */ + /** flags to set in mbuf when a vlan is detected. */ + uint64_t vlan_flags; uint64_t offloads; /**< Rx offloads with DEV_RX_OFFLOAD_* */ /** need to alloc dummy mbuf, for wraparound when scanning hw ring */ struct rte_mbuf fake_mbuf; From patchwork Wed Jun 2 09:41:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93782 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 B8354A0524; Wed, 2 Jun 2021 11:42:11 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id CD4A141194; Wed, 2 Jun 2021 11:40:08 +0200 (CEST) Received: from smtpbg501.qq.com (smtpbg501.qq.com [203.205.250.101]) by mails.dpdk.org (Postfix) with ESMTP id 1506241185 for ; Wed, 2 Jun 2021 11:40:05 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626801th03bcpr Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:40:00 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: RAPFXLVIdyDg+a9BdxPQofPaRE/P2v1BdPQkNJs38eSQtEiGG5IfOLcEzmiBU zCaPJCW38HbhZwu2WfTlcJHUgUy8SYpTO3p4vnhSesDhS+Lf5IJYMsf0+SVy/QPCu7v6nKN VErld5mLbI08fUAQSXblZWTB4PWTSo1aumVLVd0IqpSGoHRyJwkD6TvB1PPDUAm+RK0Hgbm N4Dx9NtYE/+4WhnHyWRXdGivQrzKaVoT/I3MuAf0HvRsePkUspaOrEkCjWH6VlbQA4/hXOq QF9btSEqBjT7rKVdTw/Ve3RPXNbUWFWqRtq/wINn7jzQthBDbU6/RFifpeeYgtO3Sxd6NhQ +8X9bxA6NXLU0ZvpyyCUj5w8EhgFw== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:41:04 +0800 Message-Id: <20210602094108.1575640-21-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign7 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 20/24] net/ngbe: support bulk and scatter Rx 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 Sender: "dev" Add bulk allocation receive function, and support scattered Rx rely on Rx offload. Signed-off-by: Jiawen Wu --- doc/guides/nics/ngbe.rst | 1 + drivers/net/ngbe/ngbe_ethdev.c | 15 +- drivers/net/ngbe/ngbe_ethdev.h | 8 + drivers/net/ngbe/ngbe_rxtx.c | 583 +++++++++++++++++++++++++++++++++ drivers/net/ngbe/ngbe_rxtx.h | 2 + 5 files changed, 607 insertions(+), 2 deletions(-) diff --git a/doc/guides/nics/ngbe.rst b/doc/guides/nics/ngbe.rst index 04fa3e90a8..e999e0b580 100644 --- a/doc/guides/nics/ngbe.rst +++ b/doc/guides/nics/ngbe.rst @@ -14,6 +14,7 @@ Features - Checksum offload - Jumbo frames - Link state information +- Scattered and gather for RX Prerequisites ------------- diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 4dab920caa..260bca0e4f 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -112,8 +112,16 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) eth_dev->rx_pkt_burst = &ngbe_recv_pkts; eth_dev->tx_pkt_burst = &ngbe_xmit_pkts_simple; - if (rte_eal_process_type() != RTE_PROC_PRIMARY) + /* + * For secondary processes, we don't initialise any further as primary + * has already done this work. Only check we don't need a different + * RX and TX function. + */ + if (rte_eal_process_type() != RTE_PROC_PRIMARY) { + ngbe_set_rx_function(eth_dev); + return 0; + } rte_eth_copy_pci_info(eth_dev, pci_dev); @@ -359,7 +367,10 @@ ngbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) const uint32_t * ngbe_dev_supported_ptypes_get(struct rte_eth_dev *dev) { - if (dev->rx_pkt_burst == ngbe_recv_pkts) + if (dev->rx_pkt_burst == ngbe_recv_pkts || + dev->rx_pkt_burst == ngbe_recv_pkts_sc_single_alloc || + dev->rx_pkt_burst == ngbe_recv_pkts_sc_bulk_alloc || + dev->rx_pkt_burst == ngbe_recv_pkts_bulk_alloc) return ngbe_get_supported_ptypes(); return NULL; diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h index c0f8483eca..1e21db5e25 100644 --- a/drivers/net/ngbe/ngbe_ethdev.h +++ b/drivers/net/ngbe/ngbe_ethdev.h @@ -78,6 +78,14 @@ void ngbe_dev_tx_init(struct rte_eth_dev *dev); uint16_t ngbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); +uint16_t ngbe_recv_pkts_bulk_alloc(void *rx_queue, struct rte_mbuf **rx_pkts, + uint16_t nb_pkts); + +uint16_t ngbe_recv_pkts_sc_single_alloc(void *rx_queue, + struct rte_mbuf **rx_pkts, uint16_t nb_pkts); +uint16_t ngbe_recv_pkts_sc_bulk_alloc(void *rx_queue, + struct rte_mbuf **rx_pkts, uint16_t nb_pkts); + uint16_t ngbe_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); diff --git a/drivers/net/ngbe/ngbe_rxtx.c b/drivers/net/ngbe/ngbe_rxtx.c index 9462da5b7a..f633718237 100644 --- a/drivers/net/ngbe/ngbe_rxtx.c +++ b/drivers/net/ngbe/ngbe_rxtx.c @@ -321,6 +321,257 @@ rx_desc_error_to_pkt_flags(uint32_t rx_status) return pkt_flags; } +/* + * LOOK_AHEAD defines how many desc statuses to check beyond the + * current descriptor. + * It must be a pound define for optimal performance. + * Do not change the value of LOOK_AHEAD, as the ngbe_rx_scan_hw_ring + * function only works with LOOK_AHEAD=8. + */ +#define LOOK_AHEAD 8 +#if (LOOK_AHEAD != 8) +#error "PMD NGBE: LOOK_AHEAD must be 8\n" +#endif +static inline int +ngbe_rx_scan_hw_ring(struct ngbe_rx_queue *rxq) +{ + volatile struct ngbe_rx_desc *rxdp; + struct ngbe_rx_entry *rxep; + struct rte_mbuf *mb; + uint16_t pkt_len; + uint64_t pkt_flags; + int nb_dd; + uint32_t s[LOOK_AHEAD]; + uint32_t pkt_info[LOOK_AHEAD]; + int i, j, nb_rx = 0; + uint32_t status; + + /* get references to current descriptor and S/W ring entry */ + rxdp = &rxq->rx_ring[rxq->rx_tail]; + rxep = &rxq->sw_ring[rxq->rx_tail]; + + status = rxdp->qw1.lo.status; + /* check to make sure there is at least 1 packet to receive */ + if (!(status & rte_cpu_to_le_32(NGBE_RXD_STAT_DD))) + return 0; + + /* + * Scan LOOK_AHEAD descriptors at a time to determine which descriptors + * reference packets that are ready to be received. + */ + for (i = 0; i < RTE_PMD_NGBE_RX_MAX_BURST; + i += LOOK_AHEAD, rxdp += LOOK_AHEAD, rxep += LOOK_AHEAD) { + /* Read desc statuses backwards to avoid race condition */ + for (j = 0; j < LOOK_AHEAD; j++) + s[j] = rte_le_to_cpu_32(rxdp[j].qw1.lo.status); + + rte_atomic_thread_fence(__ATOMIC_ACQUIRE); + + /* Compute how many status bits were set */ + for (nb_dd = 0; nb_dd < LOOK_AHEAD && + (s[nb_dd] & NGBE_RXD_STAT_DD); nb_dd++) + ; + + for (j = 0; j < nb_dd; j++) + pkt_info[j] = rte_le_to_cpu_32(rxdp[j].qw0.dw0); + + nb_rx += nb_dd; + + /* Translate descriptor info to mbuf format */ + for (j = 0; j < nb_dd; ++j) { + mb = rxep[j].mbuf; + pkt_len = rte_le_to_cpu_16(rxdp[j].qw1.hi.len) - + rxq->crc_len; + mb->data_len = pkt_len; + mb->pkt_len = pkt_len; + mb->vlan_tci = rte_le_to_cpu_16(rxdp[j].qw1.hi.tag); + + /* convert descriptor fields to rte mbuf flags */ + pkt_flags = rx_desc_status_to_pkt_flags(s[j], + rxq->vlan_flags); + pkt_flags |= rx_desc_error_to_pkt_flags(s[j]); + pkt_flags |= + ngbe_rxd_pkt_info_to_pkt_flags(pkt_info[j]); + mb->ol_flags = pkt_flags; + mb->packet_type = + ngbe_rxd_pkt_info_to_pkt_type(pkt_info[j], + rxq->pkt_type_mask); + + if (likely(pkt_flags & PKT_RX_RSS_HASH)) + mb->hash.rss = + rte_le_to_cpu_32(rxdp[j].qw0.dw1); + } + + /* Move mbuf pointers from the S/W ring to the stage */ + for (j = 0; j < LOOK_AHEAD; ++j) + rxq->rx_stage[i + j] = rxep[j].mbuf; + + /* stop if all requested packets could not be received */ + if (nb_dd != LOOK_AHEAD) + break; + } + + /* clear software ring entries so we can cleanup correctly */ + for (i = 0; i < nb_rx; ++i) + rxq->sw_ring[rxq->rx_tail + i].mbuf = NULL; + + return nb_rx; +} + +static inline int +ngbe_rx_alloc_bufs(struct ngbe_rx_queue *rxq, bool reset_mbuf) +{ + volatile struct ngbe_rx_desc *rxdp; + struct ngbe_rx_entry *rxep; + struct rte_mbuf *mb; + uint16_t alloc_idx; + __le64 dma_addr; + int diag, i; + + /* allocate buffers in bulk directly into the S/W ring */ + alloc_idx = rxq->rx_free_trigger - (rxq->rx_free_thresh - 1); + rxep = &rxq->sw_ring[alloc_idx]; + diag = rte_mempool_get_bulk(rxq->mb_pool, (void *)rxep, + rxq->rx_free_thresh); + if (unlikely(diag != 0)) + return -ENOMEM; + + rxdp = &rxq->rx_ring[alloc_idx]; + for (i = 0; i < rxq->rx_free_thresh; ++i) { + /* populate the static rte mbuf fields */ + mb = rxep[i].mbuf; + if (reset_mbuf) + mb->port = rxq->port_id; + + rte_mbuf_refcnt_set(mb, 1); + mb->data_off = RTE_PKTMBUF_HEADROOM; + + /* populate the descriptors */ + dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(mb)); + NGBE_RXD_HDRADDR(&rxdp[i], 0); + NGBE_RXD_PKTADDR(&rxdp[i], dma_addr); + } + + /* update state of internal queue structure */ + rxq->rx_free_trigger = rxq->rx_free_trigger + rxq->rx_free_thresh; + if (rxq->rx_free_trigger >= rxq->nb_rx_desc) + rxq->rx_free_trigger = rxq->rx_free_thresh - 1; + + /* no errors */ + return 0; +} + +static inline uint16_t +ngbe_rx_fill_from_stage(struct ngbe_rx_queue *rxq, struct rte_mbuf **rx_pkts, + uint16_t nb_pkts) +{ + struct rte_mbuf **stage = &rxq->rx_stage[rxq->rx_next_avail]; + int i; + + /* how many packets are ready to return? */ + nb_pkts = (uint16_t)RTE_MIN(nb_pkts, rxq->rx_nb_avail); + + /* copy mbuf pointers to the application's packet list */ + for (i = 0; i < nb_pkts; ++i) + rx_pkts[i] = stage[i]; + + /* update internal queue state */ + rxq->rx_nb_avail = (uint16_t)(rxq->rx_nb_avail - nb_pkts); + rxq->rx_next_avail = (uint16_t)(rxq->rx_next_avail + nb_pkts); + + return nb_pkts; +} + +static inline uint16_t +ngbe_rx_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, + uint16_t nb_pkts) +{ + struct ngbe_rx_queue *rxq = (struct ngbe_rx_queue *)rx_queue; + struct rte_eth_dev *dev = &rte_eth_devices[rxq->port_id]; + uint16_t nb_rx = 0; + + /* Any previously recv'd pkts will be returned from the Rx stage */ + if (rxq->rx_nb_avail) + return ngbe_rx_fill_from_stage(rxq, rx_pkts, nb_pkts); + + /* Scan the H/W ring for packets to receive */ + nb_rx = (uint16_t)ngbe_rx_scan_hw_ring(rxq); + + /* update internal queue state */ + rxq->rx_next_avail = 0; + rxq->rx_nb_avail = nb_rx; + rxq->rx_tail = (uint16_t)(rxq->rx_tail + nb_rx); + + /* if required, allocate new buffers to replenish descriptors */ + if (rxq->rx_tail > rxq->rx_free_trigger) { + uint16_t cur_free_trigger = rxq->rx_free_trigger; + + if (ngbe_rx_alloc_bufs(rxq, true) != 0) { + int i, j; + + PMD_RX_LOG(DEBUG, "RX mbuf alloc failed port_id=%u " + "queue_id=%u", (uint16_t)rxq->port_id, + (uint16_t)rxq->queue_id); + + dev->data->rx_mbuf_alloc_failed += + rxq->rx_free_thresh; + + /* + * Need to rewind any previous receives if we cannot + * allocate new buffers to replenish the old ones. + */ + rxq->rx_nb_avail = 0; + rxq->rx_tail = (uint16_t)(rxq->rx_tail - nb_rx); + for (i = 0, j = rxq->rx_tail; i < nb_rx; ++i, ++j) + rxq->sw_ring[j].mbuf = rxq->rx_stage[i]; + + return 0; + } + + /* update tail pointer */ + rte_wmb(); + ngbe_set32_relaxed(rxq->rdt_reg_addr, cur_free_trigger); + } + + if (rxq->rx_tail >= rxq->nb_rx_desc) + rxq->rx_tail = 0; + + /* received any packets this loop? */ + if (rxq->rx_nb_avail) + return ngbe_rx_fill_from_stage(rxq, rx_pkts, nb_pkts); + + return 0; +} + +/* split requests into chunks of size RTE_PMD_NGBE_RX_MAX_BURST */ +uint16_t +ngbe_recv_pkts_bulk_alloc(void *rx_queue, struct rte_mbuf **rx_pkts, + uint16_t nb_pkts) +{ + uint16_t nb_rx; + + if (unlikely(nb_pkts == 0)) + return 0; + + if (likely(nb_pkts <= RTE_PMD_NGBE_RX_MAX_BURST)) + return ngbe_rx_recv_pkts(rx_queue, rx_pkts, nb_pkts); + + /* request is relatively large, chunk it up */ + nb_rx = 0; + while (nb_pkts) { + uint16_t ret, n; + + n = (uint16_t)RTE_MIN(nb_pkts, RTE_PMD_NGBE_RX_MAX_BURST); + ret = ngbe_rx_recv_pkts(rx_queue, &rx_pkts[nb_rx], n); + nb_rx = (uint16_t)(nb_rx + ret); + nb_pkts = (uint16_t)(nb_pkts - ret); + if (ret < n) + break; + } + + return nb_rx; +} + uint16_t ngbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) @@ -501,6 +752,288 @@ ngbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, return nb_rx; } +/** + * ngbe_fill_cluster_head_buf - fill the first mbuf of the returned packet + * + * Fill the following info in the HEAD buffer of the Rx cluster: + * - RX port identifier + * - hardware offload data, if any: + * - RSS flag & hash + * - IP checksum flag + * - VLAN TCI, if any + * - error flags + * @head HEAD of the packet cluster + * @desc HW descriptor to get data from + * @rxq Pointer to the Rx queue + */ +static inline void +ngbe_fill_cluster_head_buf(struct rte_mbuf *head, struct ngbe_rx_desc *desc, + struct ngbe_rx_queue *rxq, uint32_t staterr) +{ + uint32_t pkt_info; + uint64_t pkt_flags; + + head->port = rxq->port_id; + + /* The vlan_tci field is only valid when PKT_RX_VLAN is + * set in the pkt_flags field. + */ + head->vlan_tci = rte_le_to_cpu_16(desc->qw1.hi.tag); + pkt_info = rte_le_to_cpu_32(desc->qw0.dw0); + pkt_flags = rx_desc_status_to_pkt_flags(staterr, rxq->vlan_flags); + pkt_flags |= rx_desc_error_to_pkt_flags(staterr); + pkt_flags |= ngbe_rxd_pkt_info_to_pkt_flags(pkt_info); + head->ol_flags = pkt_flags; + head->packet_type = ngbe_rxd_pkt_info_to_pkt_type(pkt_info, + rxq->pkt_type_mask); + + if (likely(pkt_flags & PKT_RX_RSS_HASH)) + head->hash.rss = rte_le_to_cpu_32(desc->qw0.dw1); +} + +/** + * ngbe_recv_pkts_sc - receive handler for scatter case. + * + * @rx_queue Rx queue handle + * @rx_pkts table of received packets + * @nb_pkts size of rx_pkts table + * @bulk_alloc if TRUE bulk allocation is used for a HW ring refilling + * + * Returns the number of received packets/clusters (according to the "bulk + * receive" interface). + */ +static inline uint16_t +ngbe_recv_pkts_sc(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts, + bool bulk_alloc) +{ + struct ngbe_rx_queue *rxq = rx_queue; + struct rte_eth_dev *dev = &rte_eth_devices[rxq->port_id]; + volatile struct ngbe_rx_desc *rx_ring = rxq->rx_ring; + struct ngbe_rx_entry *sw_ring = rxq->sw_ring; + struct ngbe_scattered_rx_entry *sw_sc_ring = rxq->sw_sc_ring; + uint16_t rx_id = rxq->rx_tail; + uint16_t nb_rx = 0; + uint16_t nb_hold = rxq->nb_rx_hold; + uint16_t prev_id = rxq->rx_tail; + + while (nb_rx < nb_pkts) { + bool eop; + struct ngbe_rx_entry *rxe; + struct ngbe_scattered_rx_entry *sc_entry; + struct ngbe_scattered_rx_entry *next_sc_entry = NULL; + struct ngbe_rx_entry *next_rxe = NULL; + struct rte_mbuf *first_seg; + struct rte_mbuf *rxm; + struct rte_mbuf *nmb = NULL; + struct ngbe_rx_desc rxd; + uint16_t data_len; + uint16_t next_id; + volatile struct ngbe_rx_desc *rxdp; + uint32_t staterr; + +next_desc: + rxdp = &rx_ring[rx_id]; + staterr = rte_le_to_cpu_32(rxdp->qw1.lo.status); + + if (!(staterr & NGBE_RXD_STAT_DD)) + break; + + rxd = *rxdp; + + PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_id=%u " + "staterr=0x%x data_len=%u", + rxq->port_id, rxq->queue_id, rx_id, staterr, + rte_le_to_cpu_16(rxd.qw1.hi.len)); + + if (!bulk_alloc) { + nmb = rte_mbuf_raw_alloc(rxq->mb_pool); + if (nmb == NULL) { + PMD_RX_LOG(DEBUG, "RX mbuf alloc failed " + "port_id=%u queue_id=%u", + rxq->port_id, rxq->queue_id); + + dev->data->rx_mbuf_alloc_failed++; + break; + } + } else if (nb_hold > rxq->rx_free_thresh) { + uint16_t next_rdt = rxq->rx_free_trigger; + + if (!ngbe_rx_alloc_bufs(rxq, false)) { + rte_wmb(); + ngbe_set32_relaxed(rxq->rdt_reg_addr, + next_rdt); + nb_hold -= rxq->rx_free_thresh; + } else { + PMD_RX_LOG(DEBUG, "RX bulk alloc failed " + "port_id=%u queue_id=%u", + rxq->port_id, rxq->queue_id); + + dev->data->rx_mbuf_alloc_failed++; + break; + } + } + + nb_hold++; + rxe = &sw_ring[rx_id]; + eop = staterr & NGBE_RXD_STAT_EOP; + + next_id = rx_id + 1; + if (next_id == rxq->nb_rx_desc) + next_id = 0; + + /* Prefetch next mbuf while processing current one. */ + rte_ngbe_prefetch(sw_ring[next_id].mbuf); + + /* + * When next RX descriptor is on a cache-line boundary, + * prefetch the next 4 RX descriptors and the next 4 pointers + * to mbufs. + */ + if ((next_id & 0x3) == 0) { + rte_ngbe_prefetch(&rx_ring[next_id]); + rte_ngbe_prefetch(&sw_ring[next_id]); + } + + rxm = rxe->mbuf; + + if (!bulk_alloc) { + __le64 dma = + rte_cpu_to_le_64(rte_mbuf_data_iova_default(nmb)); + /* + * Update RX descriptor with the physical address of the + * new data buffer of the new allocated mbuf. + */ + rxe->mbuf = nmb; + + rxm->data_off = RTE_PKTMBUF_HEADROOM; + NGBE_RXD_HDRADDR(rxdp, 0); + NGBE_RXD_PKTADDR(rxdp, dma); + } else { + rxe->mbuf = NULL; + } + + /* + * Set data length & data buffer address of mbuf. + */ + data_len = rte_le_to_cpu_16(rxd.qw1.hi.len); + rxm->data_len = data_len; + + if (!eop) { + uint16_t nextp_id; + + nextp_id = next_id; + next_sc_entry = &sw_sc_ring[nextp_id]; + next_rxe = &sw_ring[nextp_id]; + rte_ngbe_prefetch(next_rxe); + } + + sc_entry = &sw_sc_ring[rx_id]; + first_seg = sc_entry->fbuf; + sc_entry->fbuf = NULL; + + /* + * If this is the first buffer of the received packet, + * set the pointer to the first mbuf of the packet and + * initialize its context. + * Otherwise, update the total length and the number of segments + * of the current scattered packet, and update the pointer to + * the last mbuf of the current packet. + */ + if (first_seg == NULL) { + first_seg = rxm; + first_seg->pkt_len = data_len; + first_seg->nb_segs = 1; + } else { + first_seg->pkt_len += data_len; + first_seg->nb_segs++; + } + + prev_id = rx_id; + rx_id = next_id; + + /* + * If this is not the last buffer of the received packet, update + * the pointer to the first mbuf at the NEXTP entry in the + * sw_sc_ring and continue to parse the RX ring. + */ + if (!eop && next_rxe) { + rxm->next = next_rxe->mbuf; + next_sc_entry->fbuf = first_seg; + goto next_desc; + } + + /* Initialize the first mbuf of the returned packet */ + ngbe_fill_cluster_head_buf(first_seg, &rxd, rxq, staterr); + + /* Deal with the case, when HW CRC srip is disabled. */ + first_seg->pkt_len -= rxq->crc_len; + if (unlikely(rxm->data_len <= rxq->crc_len)) { + struct rte_mbuf *lp; + + for (lp = first_seg; lp->next != rxm; lp = lp->next) + ; + + first_seg->nb_segs--; + lp->data_len -= rxq->crc_len - rxm->data_len; + lp->next = NULL; + rte_pktmbuf_free_seg(rxm); + } else { + rxm->data_len -= rxq->crc_len; + } + + /* Prefetch data of first segment, if configured to do so. */ + rte_packet_prefetch((char *)first_seg->buf_addr + + first_seg->data_off); + + /* + * Store the mbuf address into the next entry of the array + * of returned packets. + */ + rx_pkts[nb_rx++] = first_seg; + } + + /* + * Record index of the next RX descriptor to probe. + */ + rxq->rx_tail = rx_id; + + /* + * If the number of free RX descriptors is greater than the RX free + * threshold of the queue, advance the Receive Descriptor Tail (RDT) + * register. + * Update the RDT with the value of the last processed RX descriptor + * minus 1, to guarantee that the RDT register is never equal to the + * RDH register, which creates a "full" ring situation from the + * hardware point of view... + */ + if (!bulk_alloc && nb_hold > rxq->rx_free_thresh) { + PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_tail=%u " + "nb_hold=%u nb_rx=%u", + rxq->port_id, rxq->queue_id, rx_id, nb_hold, nb_rx); + + rte_wmb(); + ngbe_set32_relaxed(rxq->rdt_reg_addr, prev_id); + nb_hold = 0; + } + + rxq->nb_rx_hold = nb_hold; + return nb_rx; +} + +uint16_t +ngbe_recv_pkts_sc_single_alloc(void *rx_queue, struct rte_mbuf **rx_pkts, + uint16_t nb_pkts) +{ + return ngbe_recv_pkts_sc(rx_queue, rx_pkts, nb_pkts, false); +} + +uint16_t +ngbe_recv_pkts_sc_bulk_alloc(void *rx_queue, struct rte_mbuf **rx_pkts, + uint16_t nb_pkts) +{ + return ngbe_recv_pkts_sc(rx_queue, rx_pkts, nb_pkts, true); +} + /********************************************************************* * * Queue management functions @@ -1064,6 +1597,54 @@ ngbe_dev_rx_queue_setup(struct rte_eth_dev *dev, return 0; } +void __rte_cold +ngbe_set_rx_function(struct rte_eth_dev *dev) +{ + struct ngbe_adapter *adapter = NGBE_DEV_ADAPTER(dev); + + if (dev->data->scattered_rx) { + /* + * Set the scattered callback: there are bulk and + * single allocation versions. + */ + if (adapter->rx_bulk_alloc_allowed) { + PMD_INIT_LOG(DEBUG, "Using a Scattered with bulk " + "allocation callback (port=%d).", + dev->data->port_id); + dev->rx_pkt_burst = ngbe_recv_pkts_sc_bulk_alloc; + } else { + PMD_INIT_LOG(DEBUG, "Using Regular (non-vector, " + "single allocation) " + "Scattered Rx callback " + "(port=%d).", + dev->data->port_id); + + dev->rx_pkt_burst = ngbe_recv_pkts_sc_single_alloc; + } + /* + * Below we set "simple" callbacks according to port/queues parameters. + * If parameters allow we are going to choose between the following + * callbacks: + * - Bulk Allocation + * - Single buffer allocation (the simplest one) + */ + } else if (adapter->rx_bulk_alloc_allowed) { + PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions are " + "satisfied. Rx Burst Bulk Alloc function " + "will be used on port=%d.", + dev->data->port_id); + + dev->rx_pkt_burst = ngbe_recv_pkts_bulk_alloc; + } else { + PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions are not " + "satisfied, or Scattered Rx is requested " + "(port=%d).", + dev->data->port_id); + + dev->rx_pkt_burst = ngbe_recv_pkts; + } +} + /* * Initializes Receive Unit. */ @@ -1211,6 +1792,8 @@ ngbe_dev_rx_init(struct rte_eth_dev *dev) wr32(hw, NGBE_SECRXCTL, rdrxctl); } + ngbe_set_rx_function(dev); + return 0; } diff --git a/drivers/net/ngbe/ngbe_rxtx.h b/drivers/net/ngbe/ngbe_rxtx.h index d6b9127cb4..4b8596b24a 100644 --- a/drivers/net/ngbe/ngbe_rxtx.h +++ b/drivers/net/ngbe/ngbe_rxtx.h @@ -298,6 +298,8 @@ struct ngbe_txq_ops { void (*reset)(struct ngbe_tx_queue *txq); }; +void ngbe_set_rx_function(struct rte_eth_dev *dev); + uint64_t ngbe_get_tx_port_offloads(struct rte_eth_dev *dev); uint64_t ngbe_get_rx_queue_offloads(struct rte_eth_dev *dev); uint64_t ngbe_get_rx_port_offloads(struct rte_eth_dev *dev); From patchwork Wed Jun 2 09:41:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93783 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 5B6C1A0A02; Wed, 2 Jun 2021 11:42:17 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 1F3C641197; Wed, 2 Jun 2021 11:40:10 +0200 (CEST) Received: from smtpbgbr2.qq.com (smtpbgbr2.qq.com [54.207.22.56]) by mails.dpdk.org (Postfix) with ESMTP id DAA0D41185 for ; Wed, 2 Jun 2021 11:40:07 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626803ty3uzoib Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:40:02 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: 6s0TUQ0M+4gpMLA7DRGKqa1Nq0jujuuccJAPrSiZYUEf1HtrrWhILS3j/j64E /K7eEzfRtrIlcbooDk3ilB4+kPOusTwwgfJmGcw/9DiEIyGgj/s+sqxBdzvIxyoyAaGAOdQ hZQ1sWLOfw2z91JXwwqV2TQ80ewQ5im6oEl8ynSW+52wksI+91+mYk762r/8Yr2CcDAnpv8 K9xTlGHuJclX6U4PNX5XvNn3WgDv9IwKutEBrVXEdHMLytUicjnBuFJTzKq9YxTvFogC1wo mWkhhSw3vXptWyta7fo17D8VzYppkIICI9wB9EAyuCNEdHNrioXBd8f5R6m7SnWIhdTOQFx n/1c3Qpc/DQqxomKVU6hpNJZYy7Yw== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:41:05 +0800 Message-Id: <20210602094108.1575640-22-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign2 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 21/24] net/ngbe: support full-featured Tx path 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 Sender: "dev" Add the full-featured transmit function, which supports checksum, TSO, tunnel parse, etc. Signed-off-by: Jiawen Wu --- doc/guides/nics/features/ngbe.ini | 3 + doc/guides/nics/ngbe.rst | 3 +- drivers/net/ngbe/meson.build | 2 + drivers/net/ngbe/ngbe_ethdev.c | 16 +- drivers/net/ngbe/ngbe_ethdev.h | 3 + drivers/net/ngbe/ngbe_rxtx.c | 639 ++++++++++++++++++++++++++++++ drivers/net/ngbe/ngbe_rxtx.h | 56 +++ 7 files changed, 720 insertions(+), 2 deletions(-) diff --git a/doc/guides/nics/features/ngbe.ini b/doc/guides/nics/features/ngbe.ini index e24d8d0b55..443c6691a3 100644 --- a/doc/guides/nics/features/ngbe.ini +++ b/doc/guides/nics/features/ngbe.ini @@ -9,10 +9,13 @@ Link status = Y Link status event = Y Jumbo frame = Y Scattered Rx = Y +TSO = Y CRC offload = P VLAN offload = P L3 checksum offload = P L4 checksum offload = P +Inner L3 checksum = P +Inner L4 checksum = P Packet type parsing = Y Multiprocess aware = Y Linux = Y diff --git a/doc/guides/nics/ngbe.rst b/doc/guides/nics/ngbe.rst index e999e0b580..cf3fafabd8 100644 --- a/doc/guides/nics/ngbe.rst +++ b/doc/guides/nics/ngbe.rst @@ -12,9 +12,10 @@ Features - Packet type information - Checksum offload +- TSO offload - Jumbo frames - Link state information -- Scattered and gather for RX +- Scattered and gather for TX and RX Prerequisites ------------- diff --git a/drivers/net/ngbe/meson.build b/drivers/net/ngbe/meson.build index fd571399b3..069e648a36 100644 --- a/drivers/net/ngbe/meson.build +++ b/drivers/net/ngbe/meson.build @@ -16,5 +16,7 @@ sources = files( 'ngbe_rxtx.c', ) +deps += ['security'] + includes += include_directories('base') diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 260bca0e4f..1a6419e5a4 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -110,7 +110,7 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) eth_dev->dev_ops = &ngbe_eth_dev_ops; eth_dev->rx_pkt_burst = &ngbe_recv_pkts; - eth_dev->tx_pkt_burst = &ngbe_xmit_pkts_simple; + eth_dev->tx_pkt_burst = &ngbe_xmit_pkts; /* * For secondary processes, we don't initialise any further as primary @@ -118,6 +118,20 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) * RX and TX function. */ if (rte_eal_process_type() != RTE_PROC_PRIMARY) { + struct ngbe_tx_queue *txq; + /* TX queue function in primary, set by last queue initialized + * Tx queue may not initialized by primary process + */ + if (eth_dev->data->tx_queues) { + uint16_t nb_tx_queues = eth_dev->data->nb_tx_queues; + txq = eth_dev->data->tx_queues[nb_tx_queues - 1]; + ngbe_set_tx_function(eth_dev, txq); + } else { + /* Use default TX function if we get here */ + PMD_INIT_LOG(NOTICE, "No TX queues configured yet. " + "Using default TX function."); + } + ngbe_set_rx_function(eth_dev); return 0; diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h index 1e21db5e25..035b1ad5c8 100644 --- a/drivers/net/ngbe/ngbe_ethdev.h +++ b/drivers/net/ngbe/ngbe_ethdev.h @@ -86,6 +86,9 @@ uint16_t ngbe_recv_pkts_sc_single_alloc(void *rx_queue, uint16_t ngbe_recv_pkts_sc_bulk_alloc(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); +uint16_t ngbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, + uint16_t nb_pkts); + uint16_t ngbe_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); diff --git a/drivers/net/ngbe/ngbe_rxtx.c b/drivers/net/ngbe/ngbe_rxtx.c index f633718237..3f3f2cab06 100644 --- a/drivers/net/ngbe/ngbe_rxtx.c +++ b/drivers/net/ngbe/ngbe_rxtx.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "ngbe_logs.h" @@ -15,6 +16,18 @@ #include "ngbe_ethdev.h" #include "ngbe_rxtx.h" +/* Bit Mask to indicate what bits required for building TX context */ +static const u64 NGBE_TX_OFFLOAD_MASK = (PKT_TX_IP_CKSUM | + PKT_TX_OUTER_IPV6 | + PKT_TX_OUTER_IPV4 | + PKT_TX_IPV6 | + PKT_TX_IPV4 | + PKT_TX_VLAN_PKT | + PKT_TX_L4_MASK | + PKT_TX_TCP_SEG | + PKT_TX_TUNNEL_MASK | + PKT_TX_OUTER_IP_CKSUM); + /* * Prefetch a cache line into all cache levels. */ @@ -248,10 +261,608 @@ ngbe_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, return nb_tx; } +static inline void +ngbe_set_xmit_ctx(struct ngbe_tx_queue *txq, + volatile struct ngbe_tx_ctx_desc *ctx_txd, + uint64_t ol_flags, union ngbe_tx_offload tx_offload, + __rte_unused uint64_t *mdata) +{ + union ngbe_tx_offload tx_offload_mask; + uint32_t type_tucmd_mlhl; + uint32_t mss_l4len_idx; + uint32_t ctx_idx; + uint32_t vlan_macip_lens; + uint32_t tunnel_seed; + + ctx_idx = txq->ctx_curr; + tx_offload_mask.data[0] = 0; + tx_offload_mask.data[1] = 0; + + /* Specify which HW CTX to upload. */ + mss_l4len_idx = NGBE_TXD_IDX(ctx_idx); + type_tucmd_mlhl = NGBE_TXD_CTXT; + + tx_offload_mask.ptid |= ~0; + type_tucmd_mlhl |= NGBE_TXD_PTID(tx_offload.ptid); + + /* check if TCP segmentation required for this packet */ + if (ol_flags & PKT_TX_TCP_SEG) { + tx_offload_mask.l2_len |= ~0; + tx_offload_mask.l3_len |= ~0; + tx_offload_mask.l4_len |= ~0; + tx_offload_mask.tso_segsz |= ~0; + mss_l4len_idx |= NGBE_TXD_MSS(tx_offload.tso_segsz); + mss_l4len_idx |= NGBE_TXD_L4LEN(tx_offload.l4_len); + } else { /* no TSO, check if hardware checksum is needed */ + if (ol_flags & PKT_TX_IP_CKSUM) { + tx_offload_mask.l2_len |= ~0; + tx_offload_mask.l3_len |= ~0; + } + + switch (ol_flags & PKT_TX_L4_MASK) { + case PKT_TX_UDP_CKSUM: + mss_l4len_idx |= + NGBE_TXD_L4LEN(sizeof(struct rte_udp_hdr)); + tx_offload_mask.l2_len |= ~0; + tx_offload_mask.l3_len |= ~0; + break; + case PKT_TX_TCP_CKSUM: + mss_l4len_idx |= + NGBE_TXD_L4LEN(sizeof(struct rte_tcp_hdr)); + tx_offload_mask.l2_len |= ~0; + tx_offload_mask.l3_len |= ~0; + break; + case PKT_TX_SCTP_CKSUM: + mss_l4len_idx |= + NGBE_TXD_L4LEN(sizeof(struct rte_sctp_hdr)); + tx_offload_mask.l2_len |= ~0; + tx_offload_mask.l3_len |= ~0; + break; + default: + break; + } + } + + vlan_macip_lens = NGBE_TXD_IPLEN(tx_offload.l3_len >> 1); + + if (ol_flags & PKT_TX_TUNNEL_MASK) { + tx_offload_mask.outer_tun_len |= ~0; + tx_offload_mask.outer_l2_len |= ~0; + tx_offload_mask.outer_l3_len |= ~0; + tx_offload_mask.l2_len |= ~0; + tunnel_seed = NGBE_TXD_ETUNLEN(tx_offload.outer_tun_len >> 1); + tunnel_seed |= NGBE_TXD_EIPLEN(tx_offload.outer_l3_len >> 2); + + switch (ol_flags & PKT_TX_TUNNEL_MASK) { + case PKT_TX_TUNNEL_IPIP: + /* for non UDP / GRE tunneling, set to 0b */ + break; + default: + PMD_TX_LOG(ERR, "Tunnel type not supported"); + return; + } + vlan_macip_lens |= NGBE_TXD_MACLEN(tx_offload.outer_l2_len); + } else { + tunnel_seed = 0; + vlan_macip_lens |= NGBE_TXD_MACLEN(tx_offload.l2_len); + } + + if (ol_flags & PKT_TX_VLAN_PKT) { + tx_offload_mask.vlan_tci |= ~0; + vlan_macip_lens |= NGBE_TXD_VLAN(tx_offload.vlan_tci); + } + + txq->ctx_cache[ctx_idx].flags = ol_flags; + txq->ctx_cache[ctx_idx].tx_offload.data[0] = + tx_offload_mask.data[0] & tx_offload.data[0]; + txq->ctx_cache[ctx_idx].tx_offload.data[1] = + tx_offload_mask.data[1] & tx_offload.data[1]; + txq->ctx_cache[ctx_idx].tx_offload_mask = tx_offload_mask; + + ctx_txd->dw0 = rte_cpu_to_le_32(vlan_macip_lens); + ctx_txd->dw1 = rte_cpu_to_le_32(tunnel_seed); + ctx_txd->dw2 = rte_cpu_to_le_32(type_tucmd_mlhl); + ctx_txd->dw3 = rte_cpu_to_le_32(mss_l4len_idx); +} + +/* + * Check which hardware context can be used. Use the existing match + * or create a new context descriptor. + */ +static inline uint32_t +what_ctx_update(struct ngbe_tx_queue *txq, uint64_t flags, + union ngbe_tx_offload tx_offload) +{ + /* If match with the current used context */ + if (likely(txq->ctx_cache[txq->ctx_curr].flags == flags && + (txq->ctx_cache[txq->ctx_curr].tx_offload.data[0] == + (txq->ctx_cache[txq->ctx_curr].tx_offload_mask.data[0] + & tx_offload.data[0])) && + (txq->ctx_cache[txq->ctx_curr].tx_offload.data[1] == + (txq->ctx_cache[txq->ctx_curr].tx_offload_mask.data[1] + & tx_offload.data[1])))) + return txq->ctx_curr; + + /* What if match with the next context */ + txq->ctx_curr ^= 1; + if (likely(txq->ctx_cache[txq->ctx_curr].flags == flags && + (txq->ctx_cache[txq->ctx_curr].tx_offload.data[0] == + (txq->ctx_cache[txq->ctx_curr].tx_offload_mask.data[0] + & tx_offload.data[0])) && + (txq->ctx_cache[txq->ctx_curr].tx_offload.data[1] == + (txq->ctx_cache[txq->ctx_curr].tx_offload_mask.data[1] + & tx_offload.data[1])))) + return txq->ctx_curr; + + /* Mismatch, use the previous context */ + return NGBE_CTX_NUM; +} + +static inline uint32_t +tx_desc_cksum_flags_to_olinfo(uint64_t ol_flags) +{ + uint32_t tmp = 0; + + if ((ol_flags & PKT_TX_L4_MASK) != PKT_TX_L4_NO_CKSUM) { + tmp |= NGBE_TXD_CC; + tmp |= NGBE_TXD_L4CS; + } + if (ol_flags & PKT_TX_IP_CKSUM) { + tmp |= NGBE_TXD_CC; + tmp |= NGBE_TXD_IPCS; + } + if (ol_flags & PKT_TX_OUTER_IP_CKSUM) { + tmp |= NGBE_TXD_CC; + tmp |= NGBE_TXD_EIPCS; + } + if (ol_flags & PKT_TX_TCP_SEG) { + tmp |= NGBE_TXD_CC; + /* implies IPv4 cksum */ + if (ol_flags & PKT_TX_IPV4) + tmp |= NGBE_TXD_IPCS; + tmp |= NGBE_TXD_L4CS; + } + if (ol_flags & PKT_TX_VLAN_PKT) + tmp |= NGBE_TXD_CC; + + return tmp; +} + +static inline uint32_t +tx_desc_ol_flags_to_cmdtype(uint64_t ol_flags) +{ + uint32_t cmdtype = 0; + + if (ol_flags & PKT_TX_VLAN_PKT) + cmdtype |= NGBE_TXD_VLE; + if (ol_flags & PKT_TX_TCP_SEG) + cmdtype |= NGBE_TXD_TSE; + if (ol_flags & PKT_TX_MACSEC) + cmdtype |= NGBE_TXD_LINKSEC; + return cmdtype; +} + +static inline uint8_t +tx_desc_ol_flags_to_ptid(uint64_t oflags, uint32_t ptype) +{ + bool tun; + + if (ptype) + return ngbe_encode_ptype(ptype); + + /* Only support flags in NGBE_TX_OFFLOAD_MASK */ + tun = !!(oflags & PKT_TX_TUNNEL_MASK); + + /* L2 level */ + ptype = RTE_PTYPE_L2_ETHER; + if (oflags & PKT_TX_VLAN) + ptype |= RTE_PTYPE_L2_ETHER_VLAN; + + /* L3 level */ + if (oflags & (PKT_TX_OUTER_IPV4 | PKT_TX_OUTER_IP_CKSUM)) + ptype |= RTE_PTYPE_L3_IPV4; + else if (oflags & (PKT_TX_OUTER_IPV6)) + ptype |= RTE_PTYPE_L3_IPV6; + + if (oflags & (PKT_TX_IPV4 | PKT_TX_IP_CKSUM)) + ptype |= (tun ? RTE_PTYPE_INNER_L3_IPV4 : RTE_PTYPE_L3_IPV4); + else if (oflags & (PKT_TX_IPV6)) + ptype |= (tun ? RTE_PTYPE_INNER_L3_IPV6 : RTE_PTYPE_L3_IPV6); + + /* L4 level */ + switch (oflags & (PKT_TX_L4_MASK)) { + case PKT_TX_TCP_CKSUM: + ptype |= (tun ? RTE_PTYPE_INNER_L4_TCP : RTE_PTYPE_L4_TCP); + break; + case PKT_TX_UDP_CKSUM: + ptype |= (tun ? RTE_PTYPE_INNER_L4_UDP : RTE_PTYPE_L4_UDP); + break; + case PKT_TX_SCTP_CKSUM: + ptype |= (tun ? RTE_PTYPE_INNER_L4_SCTP : RTE_PTYPE_L4_SCTP); + break; + } + + if (oflags & PKT_TX_TCP_SEG) + ptype |= (tun ? RTE_PTYPE_INNER_L4_TCP : RTE_PTYPE_L4_TCP); + + /* Tunnel */ + switch (oflags & PKT_TX_TUNNEL_MASK) { + case PKT_TX_TUNNEL_VXLAN: + ptype |= RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | + RTE_PTYPE_TUNNEL_VXLAN; + ptype |= RTE_PTYPE_INNER_L2_ETHER; + break; + case PKT_TX_TUNNEL_GRE: + ptype |= RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | + RTE_PTYPE_TUNNEL_GRE; + ptype |= RTE_PTYPE_INNER_L2_ETHER; + break; + case PKT_TX_TUNNEL_GENEVE: + ptype |= RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | + RTE_PTYPE_TUNNEL_GENEVE; + ptype |= RTE_PTYPE_INNER_L2_ETHER; + break; + case PKT_TX_TUNNEL_VXLAN_GPE: + ptype |= RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | + RTE_PTYPE_TUNNEL_VXLAN_GPE; + break; + case PKT_TX_TUNNEL_IPIP: + case PKT_TX_TUNNEL_IP: + ptype |= RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | + RTE_PTYPE_TUNNEL_IP; + break; + } + + return ngbe_encode_ptype(ptype); +} + #ifndef DEFAULT_TX_FREE_THRESH #define DEFAULT_TX_FREE_THRESH 32 #endif +/* Reset transmit descriptors after they have been used */ +static inline int +ngbe_xmit_cleanup(struct ngbe_tx_queue *txq) +{ + struct ngbe_tx_entry *sw_ring = txq->sw_ring; + volatile struct ngbe_tx_desc *txr = txq->tx_ring; + uint16_t last_desc_cleaned = txq->last_desc_cleaned; + uint16_t nb_tx_desc = txq->nb_tx_desc; + uint16_t desc_to_clean_to; + uint16_t nb_tx_to_clean; + uint32_t status; + + /* Determine the last descriptor needing to be cleaned */ + desc_to_clean_to = (uint16_t)(last_desc_cleaned + txq->tx_free_thresh); + if (desc_to_clean_to >= nb_tx_desc) + desc_to_clean_to = (uint16_t)(desc_to_clean_to - nb_tx_desc); + + /* Check to make sure the last descriptor to clean is done */ + desc_to_clean_to = sw_ring[desc_to_clean_to].last_id; + status = txr[desc_to_clean_to].dw3; + if (!(status & rte_cpu_to_le_32(NGBE_TXD_DD))) { + PMD_TX_LOG(DEBUG, + "TX descriptor %4u is not done" + "(port=%d queue=%d)", + desc_to_clean_to, + txq->port_id, txq->queue_id); + if (txq->nb_tx_free >> 1 < txq->tx_free_thresh) + ngbe_set32_masked(txq->tdc_reg_addr, + NGBE_TXCFG_FLUSH, NGBE_TXCFG_FLUSH); + /* Failed to clean any descriptors, better luck next time */ + return -(1); + } + + /* Figure out how many descriptors will be cleaned */ + if (last_desc_cleaned > desc_to_clean_to) + nb_tx_to_clean = (uint16_t)((nb_tx_desc - last_desc_cleaned) + + desc_to_clean_to); + else + nb_tx_to_clean = (uint16_t)(desc_to_clean_to - + last_desc_cleaned); + + PMD_TX_LOG(DEBUG, + "Cleaning %4u TX descriptors: %4u to %4u " + "(port=%d queue=%d)", + nb_tx_to_clean, last_desc_cleaned, desc_to_clean_to, + txq->port_id, txq->queue_id); + + /* + * The last descriptor to clean is done, so that means all the + * descriptors from the last descriptor that was cleaned + * up to the last descriptor with the RS bit set + * are done. Only reset the threshold descriptor. + */ + txr[desc_to_clean_to].dw3 = 0; + + /* Update the txq to reflect the last descriptor that was cleaned */ + txq->last_desc_cleaned = desc_to_clean_to; + txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + nb_tx_to_clean); + + /* No Error */ + return 0; +} + +uint16_t +ngbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, + uint16_t nb_pkts) +{ + struct ngbe_tx_queue *txq; + struct ngbe_tx_entry *sw_ring; + struct ngbe_tx_entry *txe, *txn; + volatile struct ngbe_tx_desc *txr; + volatile struct ngbe_tx_desc *txd; + struct rte_mbuf *tx_pkt; + struct rte_mbuf *m_seg; + uint64_t buf_dma_addr; + uint32_t olinfo_status; + uint32_t cmd_type_len; + uint32_t pkt_len; + uint16_t slen; + uint64_t ol_flags; + uint16_t tx_id; + uint16_t tx_last; + uint16_t nb_tx; + uint16_t nb_used; + uint64_t tx_ol_req; + uint32_t ctx = 0; + uint32_t new_ctx; + union ngbe_tx_offload tx_offload; + + tx_offload.data[0] = 0; + tx_offload.data[1] = 0; + txq = tx_queue; + sw_ring = txq->sw_ring; + txr = txq->tx_ring; + tx_id = txq->tx_tail; + txe = &sw_ring[tx_id]; + + /* Determine if the descriptor ring needs to be cleaned. */ + if (txq->nb_tx_free < txq->tx_free_thresh) + ngbe_xmit_cleanup(txq); + + rte_prefetch0(&txe->mbuf->pool); + + /* TX loop */ + for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) { + new_ctx = 0; + tx_pkt = *tx_pkts++; + pkt_len = tx_pkt->pkt_len; + + /* + * Determine how many (if any) context descriptors + * are needed for offload functionality. + */ + ol_flags = tx_pkt->ol_flags; + + /* If hardware offload required */ + tx_ol_req = ol_flags & NGBE_TX_OFFLOAD_MASK; + if (tx_ol_req) { + tx_offload.ptid = tx_desc_ol_flags_to_ptid(tx_ol_req, + tx_pkt->packet_type); + tx_offload.l2_len = tx_pkt->l2_len; + tx_offload.l3_len = tx_pkt->l3_len; + tx_offload.l4_len = tx_pkt->l4_len; + tx_offload.vlan_tci = tx_pkt->vlan_tci; + tx_offload.tso_segsz = tx_pkt->tso_segsz; + tx_offload.outer_l2_len = tx_pkt->outer_l2_len; + tx_offload.outer_l3_len = tx_pkt->outer_l3_len; + tx_offload.outer_tun_len = 0; + + + /* If new context need be built or reuse the exist ctx*/ + ctx = what_ctx_update(txq, tx_ol_req, tx_offload); + /* Only allocate context descriptor if required */ + new_ctx = (ctx == NGBE_CTX_NUM); + ctx = txq->ctx_curr; + } + + /* + * Keep track of how many descriptors are used this loop + * This will always be the number of segments + the number of + * Context descriptors required to transmit the packet + */ + nb_used = (uint16_t)(tx_pkt->nb_segs + new_ctx); + + /* + * The number of descriptors that must be allocated for a + * packet is the number of segments of that packet, plus 1 + * Context Descriptor for the hardware offload, if any. + * Determine the last TX descriptor to allocate in the TX ring + * for the packet, starting from the current position (tx_id) + * in the ring. + */ + tx_last = (uint16_t)(tx_id + nb_used - 1); + + /* Circular ring */ + if (tx_last >= txq->nb_tx_desc) + tx_last = (uint16_t)(tx_last - txq->nb_tx_desc); + + PMD_TX_LOG(DEBUG, "port_id=%u queue_id=%u pktlen=%u" + " tx_first=%u tx_last=%u", + (uint16_t)txq->port_id, + (uint16_t)txq->queue_id, + (uint32_t)pkt_len, + (uint16_t)tx_id, + (uint16_t)tx_last); + + /* + * Make sure there are enough TX descriptors available to + * transmit the entire packet. + * nb_used better be less than or equal to txq->tx_free_thresh + */ + if (nb_used > txq->nb_tx_free) { + PMD_TX_LOG(DEBUG, + "Not enough free TX descriptors " + "nb_used=%4u nb_free=%4u " + "(port=%d queue=%d)", + nb_used, txq->nb_tx_free, + txq->port_id, txq->queue_id); + + if (ngbe_xmit_cleanup(txq) != 0) { + /* Could not clean any descriptors */ + if (nb_tx == 0) + return 0; + goto end_of_tx; + } + + /* nb_used better be <= txq->tx_free_thresh */ + if (unlikely(nb_used > txq->tx_free_thresh)) { + PMD_TX_LOG(DEBUG, + "The number of descriptors needed to " + "transmit the packet exceeds the " + "RS bit threshold. This will impact " + "performance." + "nb_used=%4u nb_free=%4u " + "tx_free_thresh=%4u. " + "(port=%d queue=%d)", + nb_used, txq->nb_tx_free, + txq->tx_free_thresh, + txq->port_id, txq->queue_id); + /* + * Loop here until there are enough TX + * descriptors or until the ring cannot be + * cleaned. + */ + while (nb_used > txq->nb_tx_free) { + if (ngbe_xmit_cleanup(txq) != 0) { + /* + * Could not clean any + * descriptors + */ + if (nb_tx == 0) + return 0; + goto end_of_tx; + } + } + } + } + + /* + * By now there are enough free TX descriptors to transmit + * the packet. + */ + + /* + * Set common flags of all TX Data Descriptors. + * + * The following bits must be set in the first Data Descriptor + * and are ignored in the other ones: + * - NGBE_TXD_FCS + * + * The following bits must only be set in the last Data + * Descriptor: + * - NGBE_TXD_EOP + */ + cmd_type_len = NGBE_TXD_FCS; + + olinfo_status = 0; + if (tx_ol_req) { + if (ol_flags & PKT_TX_TCP_SEG) { + /* when TSO is on, paylen in descriptor is the + * not the packet len but the tcp payload len + */ + pkt_len -= (tx_offload.l2_len + + tx_offload.l3_len + tx_offload.l4_len); + pkt_len -= + (tx_pkt->ol_flags & PKT_TX_TUNNEL_MASK) + ? tx_offload.outer_l2_len + + tx_offload.outer_l3_len : 0; + } + + /* + * Setup the TX Advanced Context Descriptor if required + */ + if (new_ctx) { + volatile struct ngbe_tx_ctx_desc *ctx_txd; + + ctx_txd = (volatile struct ngbe_tx_ctx_desc *) + &txr[tx_id]; + + txn = &sw_ring[txe->next_id]; + rte_prefetch0(&txn->mbuf->pool); + + if (txe->mbuf != NULL) { + rte_pktmbuf_free_seg(txe->mbuf); + txe->mbuf = NULL; + } + + ngbe_set_xmit_ctx(txq, ctx_txd, tx_ol_req, + tx_offload, + rte_security_dynfield(tx_pkt)); + + txe->last_id = tx_last; + tx_id = txe->next_id; + txe = txn; + } + + /* + * Setup the TX Advanced Data Descriptor, + * This path will go through + * whatever new/reuse the context descriptor + */ + cmd_type_len |= tx_desc_ol_flags_to_cmdtype(ol_flags); + olinfo_status |= + tx_desc_cksum_flags_to_olinfo(ol_flags); + olinfo_status |= NGBE_TXD_IDX(ctx); + } + + olinfo_status |= NGBE_TXD_PAYLEN(pkt_len); + + m_seg = tx_pkt; + do { + txd = &txr[tx_id]; + txn = &sw_ring[txe->next_id]; + rte_prefetch0(&txn->mbuf->pool); + + if (txe->mbuf != NULL) + rte_pktmbuf_free_seg(txe->mbuf); + txe->mbuf = m_seg; + + /* + * Set up Transmit Data Descriptor. + */ + slen = m_seg->data_len; + buf_dma_addr = rte_mbuf_data_iova(m_seg); + txd->qw0 = rte_cpu_to_le_64(buf_dma_addr); + txd->dw2 = rte_cpu_to_le_32(cmd_type_len | slen); + txd->dw3 = rte_cpu_to_le_32(olinfo_status); + txe->last_id = tx_last; + tx_id = txe->next_id; + txe = txn; + m_seg = m_seg->next; + } while (m_seg != NULL); + + /* + * The last packet data descriptor needs End Of Packet (EOP) + */ + cmd_type_len |= NGBE_TXD_EOP; + txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_used); + + txd->dw2 |= rte_cpu_to_le_32(cmd_type_len); + } + +end_of_tx: + + rte_wmb(); + + /* + * Set the Transmit Descriptor Tail (TDT) + */ + PMD_TX_LOG(DEBUG, "port_id=%u queue_id=%u tx_tail=%u nb_tx=%u", + (uint16_t)txq->port_id, (uint16_t)txq->queue_id, + (uint16_t)tx_id, (uint16_t)nb_tx); + ngbe_set32_relaxed(txq->tdt_reg_addr, tx_id); + txq->tx_tail = tx_id; + + return nb_tx; +} + /********************************************************************* * * RX functions @@ -1123,6 +1734,31 @@ static const struct ngbe_txq_ops def_txq_ops = { .reset = ngbe_reset_tx_queue, }; +/* Takes an ethdev and a queue and sets up the tx function to be used based on + * the queue parameters. Used in tx_queue_setup by primary process and then + * in dev_init by secondary process when attaching to an existing ethdev. + */ +void __rte_cold +ngbe_set_tx_function(struct rte_eth_dev *dev, struct ngbe_tx_queue *txq) +{ + /* Use a simple Tx queue (no offloads, no multi segs) if possible */ + if (txq->offloads == 0 && + txq->tx_free_thresh >= RTE_PMD_NGBE_TX_MAX_BURST) { + PMD_INIT_LOG(DEBUG, "Using simple tx code path"); + dev->tx_pkt_burst = ngbe_xmit_pkts_simple; + } else { + PMD_INIT_LOG(DEBUG, "Using full-featured tx code path"); + PMD_INIT_LOG(DEBUG, + " - offloads = 0x%" PRIx64, + txq->offloads); + PMD_INIT_LOG(DEBUG, + " - tx_free_thresh = %lu [RTE_PMD_NGBE_TX_MAX_BURST=%lu]", + (unsigned long)txq->tx_free_thresh, + (unsigned long)RTE_PMD_NGBE_TX_MAX_BURST); + dev->tx_pkt_burst = ngbe_xmit_pkts; + } +} + uint64_t ngbe_get_tx_port_offloads(struct rte_eth_dev *dev) { @@ -1262,6 +1898,9 @@ ngbe_dev_tx_queue_setup(struct rte_eth_dev *dev, PMD_INIT_LOG(DEBUG, "sw_ring=%p hw_ring=%p dma_addr=0x%" PRIx64, txq->sw_ring, txq->tx_ring, txq->tx_ring_phys_addr); + /* set up scalar TX function as appropriate */ + ngbe_set_tx_function(dev, txq); + txq->ops->reset(txq); dev->data->tx_queues[queue_idx] = txq; diff --git a/drivers/net/ngbe/ngbe_rxtx.h b/drivers/net/ngbe/ngbe_rxtx.h index 4b8596b24a..2cb98e2497 100644 --- a/drivers/net/ngbe/ngbe_rxtx.h +++ b/drivers/net/ngbe/ngbe_rxtx.h @@ -135,8 +135,35 @@ struct ngbe_tx_ctx_desc { __le32 dw3; /* w.mss_l4len_idx */ }; +/* @ngbe_tx_ctx_desc.dw0 */ +#define NGBE_TXD_IPLEN(v) LS(v, 0, 0x1FF) /* ip/fcoe header end */ +#define NGBE_TXD_MACLEN(v) LS(v, 9, 0x7F) /* desc mac len */ +#define NGBE_TXD_VLAN(v) LS(v, 16, 0xFFFF) /* vlan tag */ + +/* @ngbe_tx_ctx_desc.dw1 */ +/*** bit 0-31, when NGBE_TXD_DTYP_FCOE=0 ***/ +#define NGBE_TXD_IPSEC_SAIDX(v) LS(v, 0, 0x3FF) /* ipsec SA index */ +#define NGBE_TXD_ETYPE(v) LS(v, 11, 0x1) /* tunnel type */ +#define NGBE_TXD_ETYPE_UDP LS(0, 11, 0x1) +#define NGBE_TXD_ETYPE_GRE LS(1, 11, 0x1) +#define NGBE_TXD_EIPLEN(v) LS(v, 12, 0x7F) /* tunnel ip header */ +#define NGBE_TXD_DTYP_FCOE MS(16, 0x1) /* FCoE/IP descriptor */ +#define NGBE_TXD_ETUNLEN(v) LS(v, 21, 0xFF) /* tunnel header */ +#define NGBE_TXD_DECTTL(v) LS(v, 29, 0xF) /* decrease ip TTL */ + +/* @ngbe_tx_ctx_desc.dw2 */ +#define NGBE_TXD_IPSEC_ESPLEN(v) LS(v, 1, 0x1FF) /* ipsec ESP length */ +#define NGBE_TXD_SNAP MS(10, 0x1) /* SNAP indication */ +#define NGBE_TXD_TPID_SEL(v) LS(v, 11, 0x7) /* vlan tag index */ +#define NGBE_TXD_IPSEC_ESP MS(14, 0x1) /* ipsec type: esp=1 ah=0 */ +#define NGBE_TXD_IPSEC_ESPENC MS(15, 0x1) /* ESP encrypt */ +#define NGBE_TXD_CTXT MS(20, 0x1) /* context descriptor */ +#define NGBE_TXD_PTID(v) LS(v, 24, 0xFF) /* packet type */ /* @ngbe_tx_ctx_desc.dw3 */ #define NGBE_TXD_DD MS(0, 0x1) /* descriptor done */ +#define NGBE_TXD_IDX(v) LS(v, 4, 0x1) /* ctxt desc index */ +#define NGBE_TXD_L4LEN(v) LS(v, 8, 0xFF) /* l4 header length */ +#define NGBE_TXD_MSS(v) LS(v, 16, 0xFFFF) /* l4 MSS */ /** * Transmit Data Descriptor (NGBE_TXD_TYP=DATA) @@ -250,11 +277,34 @@ enum ngbe_ctx_num { NGBE_CTX_NUM = 2, /**< CTX NUMBER */ }; +/** Offload features */ +union ngbe_tx_offload { + uint64_t data[2]; + struct { + uint64_t ptid:8; /**< Packet Type Identifier. */ + uint64_t l2_len:7; /**< L2 (MAC) Header Length. */ + uint64_t l3_len:9; /**< L3 (IP) Header Length. */ + uint64_t l4_len:8; /**< L4 (TCP/UDP) Header Length. */ + uint64_t tso_segsz:16; /**< TCP TSO segment size */ + uint64_t vlan_tci:16; + /**< VLAN Tag Control Identifier (CPU order). */ + + /* fields for TX offloading of tunnels */ + uint64_t outer_tun_len:8; /**< Outer TUN (Tunnel) Hdr Length. */ + uint64_t outer_l2_len:8; /**< Outer L2 (MAC) Hdr Length. */ + uint64_t outer_l3_len:16; /**< Outer L3 (IP) Hdr Length. */ + }; +}; + /** * Structure to check if new context need be built */ struct ngbe_ctx_info { uint64_t flags; /**< ol_flags for context build. */ + /**< tx offload: vlan, tso, l2-l3-l4 lengths. */ + union ngbe_tx_offload tx_offload; + /** compare mask for tx offload. */ + union ngbe_tx_offload tx_offload_mask; }; /** @@ -298,6 +348,12 @@ struct ngbe_txq_ops { void (*reset)(struct ngbe_tx_queue *txq); }; +/* Takes an ethdev and a queue and sets up the tx function to be used based on + * the queue parameters. Used in tx_queue_setup by primary process and then + * in dev_init by secondary process when attaching to an existing ethdev. + */ +void ngbe_set_tx_function(struct rte_eth_dev *dev, struct ngbe_tx_queue *txq); + void ngbe_set_rx_function(struct rte_eth_dev *dev); uint64_t ngbe_get_tx_port_offloads(struct rte_eth_dev *dev); From patchwork Wed Jun 2 09:41:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93784 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 06321A0524; Wed, 2 Jun 2021 11:42:25 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7B398411A2; Wed, 2 Jun 2021 11:40:11 +0200 (CEST) Received: from smtpbg511.qq.com (smtpbg511.qq.com [203.205.250.109]) by mails.dpdk.org (Postfix) with ESMTP id 03B2941196 for ; Wed, 2 Jun 2021 11:40:08 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626804t1fgulnk Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:40:04 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: PAtBXkQ2bGB+QzB5GJemzIIQJ1JE/ih3EHc2jSRt1I8m7O4rgERJxt8d+ZQX1 1aY2evian7ikhYazhKNAY41vzGx0VZFr4RDJ3n4XnQ2tDCL8yI3JVkuupQ/kNL1IkKXhG7m LSJDpbqPIXlEVHWBfzGuiMcAUkL72OkxOhKL2dVu+APj2hKziZ8M1SPiGpj5rydTym2qzq6 DCmozD8YfqNte4uG5RK8jv3MxBMqGctQ+geI/Ov70+zr2y4WwPXFa5hy6KuKQ7EjPGcNmwJ zD6aXC46bIiMMHIjpGxIbaJSf8YxRtb/b8WEwQZn8yIQ2zL8BnLoU9D1fBc06WxAOqdXLZe UTx4vIIgnDYDMUBnG0acJN3z/Z1zw== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:41:06 +0800 Message-Id: <20210602094108.1575640-23-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign7 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 22/24] net/ngbe: add device start operation 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 Sender: "dev" Setup misx interrupt, complete PHY configuration and set device link speed, to start device. Signed-off-by: Jiawen Wu --- drivers/net/ngbe/base/ngbe_dummy.h | 16 + drivers/net/ngbe/base/ngbe_hw.c | 50 ++++ drivers/net/ngbe/base/ngbe_hw.h | 4 + drivers/net/ngbe/base/ngbe_phy.c | 3 + drivers/net/ngbe/base/ngbe_phy_mvl.c | 64 ++++ drivers/net/ngbe/base/ngbe_phy_mvl.h | 1 + drivers/net/ngbe/base/ngbe_phy_rtl.c | 58 ++++ drivers/net/ngbe/base/ngbe_phy_rtl.h | 2 + drivers/net/ngbe/base/ngbe_phy_yt.c | 26 ++ drivers/net/ngbe/base/ngbe_phy_yt.h | 1 + drivers/net/ngbe/base/ngbe_type.h | 17 ++ drivers/net/ngbe/ngbe_ethdev.c | 420 ++++++++++++++++++++++++++- drivers/net/ngbe/ngbe_ethdev.h | 6 + 13 files changed, 667 insertions(+), 1 deletion(-) diff --git a/drivers/net/ngbe/base/ngbe_dummy.h b/drivers/net/ngbe/base/ngbe_dummy.h index 709e01659c..dfc7b13192 100644 --- a/drivers/net/ngbe/base/ngbe_dummy.h +++ b/drivers/net/ngbe/base/ngbe_dummy.h @@ -47,6 +47,10 @@ static inline s32 ngbe_mac_reset_hw_dummy(struct ngbe_hw *TUP0) { return NGBE_ERR_OPS_DUMMY; } +static inline s32 ngbe_mac_start_hw_dummy(struct ngbe_hw *TUP0) +{ + return NGBE_ERR_OPS_DUMMY; +} static inline s32 ngbe_mac_stop_hw_dummy(struct ngbe_hw *TUP0) { return NGBE_ERR_OPS_DUMMY; @@ -74,6 +78,11 @@ static inline s32 ngbe_mac_check_link_dummy(struct ngbe_hw *TUP0, u32 *TUP1, { return NGBE_ERR_OPS_DUMMY; } +static inline s32 ngbe_mac_get_link_capabilities_dummy(struct ngbe_hw *TUP0, + u32 *TUP1, bool *TUP2) +{ + return NGBE_ERR_OPS_DUMMY; +} static inline s32 ngbe_mac_set_rar_dummy(struct ngbe_hw *TUP0, u32 TUP1, u8 *TUP2, u32 TUP3, u32 TUP4) { @@ -110,6 +119,10 @@ static inline s32 ngbe_phy_identify_dummy(struct ngbe_hw *TUP0) { return NGBE_ERR_OPS_DUMMY; } +static inline s32 ngbe_phy_init_hw_dummy(struct ngbe_hw *TUP0) +{ + return NGBE_ERR_OPS_DUMMY; +} static inline s32 ngbe_phy_reset_hw_dummy(struct ngbe_hw *TUP0) { return NGBE_ERR_OPS_DUMMY; @@ -151,12 +164,14 @@ static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw) hw->rom.validate_checksum = ngbe_rom_validate_checksum_dummy; hw->mac.init_hw = ngbe_mac_init_hw_dummy; hw->mac.reset_hw = ngbe_mac_reset_hw_dummy; + hw->mac.start_hw = ngbe_mac_start_hw_dummy; hw->mac.stop_hw = ngbe_mac_stop_hw_dummy; hw->mac.get_mac_addr = ngbe_mac_get_mac_addr_dummy; hw->mac.acquire_swfw_sync = ngbe_mac_acquire_swfw_sync_dummy; hw->mac.release_swfw_sync = ngbe_mac_release_swfw_sync_dummy; hw->mac.setup_link = ngbe_mac_setup_link_dummy; hw->mac.check_link = ngbe_mac_check_link_dummy; + hw->mac.get_link_capabilities = ngbe_mac_get_link_capabilities_dummy; hw->mac.set_rar = ngbe_mac_set_rar_dummy; hw->mac.clear_rar = ngbe_mac_clear_rar_dummy; hw->mac.set_vmdq = ngbe_mac_set_vmdq_dummy; @@ -165,6 +180,7 @@ static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw) hw->mac.init_thermal_sensor_thresh = ngbe_mac_init_thermal_ssth_dummy; hw->mac.check_overtemp = ngbe_mac_check_overtemp_dummy; hw->phy.identify = ngbe_phy_identify_dummy; + hw->phy.init_hw = ngbe_phy_init_hw_dummy; hw->phy.reset_hw = ngbe_phy_reset_hw_dummy; hw->phy.read_reg = ngbe_phy_read_reg_dummy; hw->phy.write_reg = ngbe_phy_write_reg_dummy; diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c index 00ac4ce838..b0bc714741 100644 --- a/drivers/net/ngbe/base/ngbe_hw.c +++ b/drivers/net/ngbe/base/ngbe_hw.c @@ -9,6 +9,22 @@ #include "ngbe_mng.h" #include "ngbe_hw.h" +/** + * ngbe_start_hw - Prepare hardware for Tx/Rx + * @hw: pointer to hardware structure + * + * Starts the hardware. + **/ +s32 ngbe_start_hw(struct ngbe_hw *hw) +{ + DEBUGFUNC("ngbe_start_hw"); + + /* Clear adapter stopped flag */ + hw->adapter_stopped = false; + + return 0; +} + /** * ngbe_init_hw - Generic hardware initialization * @hw: pointer to hardware structure @@ -27,6 +43,10 @@ s32 ngbe_init_hw(struct ngbe_hw *hw) /* Reset the hardware */ status = hw->mac.reset_hw(hw); + if (status == 0) { + /* Start the HW */ + status = hw->mac.start_hw(hw); + } if (status != 0) DEBUGOUT("Failed to initialize HW, STATUS = %d\n", status); @@ -633,6 +653,30 @@ s32 ngbe_check_mac_link_em(struct ngbe_hw *hw, u32 *speed, return status; } +s32 ngbe_get_link_capabilities_em(struct ngbe_hw *hw, + u32 *speed, + bool *autoneg) +{ + s32 status = 0; + + DEBUGFUNC("\n"); + + switch (hw->sub_device_id) { + case NGBE_SUB_DEV_ID_EM_RTL_SGMII: + *speed = NGBE_LINK_SPEED_1GB_FULL | + NGBE_LINK_SPEED_100M_FULL | + NGBE_LINK_SPEED_10M_FULL; + *autoneg = false; + hw->phy.link_mode = NGBE_PHYSICAL_LAYER_1000BASE_T | + NGBE_PHYSICAL_LAYER_100BASE_TX; + break; + default: + break; + } + + return status; +} + s32 ngbe_setup_mac_link_em(struct ngbe_hw *hw, u32 speed, bool autoneg_wait_to_complete) @@ -842,6 +886,7 @@ s32 ngbe_init_ops_pf(struct ngbe_hw *hw) /* MAC */ mac->init_hw = ngbe_init_hw; mac->reset_hw = ngbe_reset_hw_em; + mac->start_hw = ngbe_start_hw; mac->get_mac_addr = ngbe_get_mac_addr; mac->stop_hw = ngbe_stop_hw; mac->acquire_swfw_sync = ngbe_acquire_swfw_sync; @@ -855,6 +900,7 @@ s32 ngbe_init_ops_pf(struct ngbe_hw *hw) mac->clear_vmdq = ngbe_clear_vmdq; /* Link */ + mac->get_link_capabilities = ngbe_get_link_capabilities_em; mac->check_link = ngbe_check_mac_link_em; mac->setup_link = ngbe_setup_mac_link_em; @@ -871,6 +917,10 @@ s32 ngbe_init_ops_pf(struct ngbe_hw *hw) mac->max_rx_queues = NGBE_EM_MAX_RX_QUEUES; mac->max_tx_queues = NGBE_EM_MAX_TX_QUEUES; + mac->default_speeds = NGBE_LINK_SPEED_10M_FULL | + NGBE_LINK_SPEED_100M_FULL | + NGBE_LINK_SPEED_1GB_FULL; + return 0; } diff --git a/drivers/net/ngbe/base/ngbe_hw.h b/drivers/net/ngbe/base/ngbe_hw.h index 1689223168..4fee5735ac 100644 --- a/drivers/net/ngbe/base/ngbe_hw.h +++ b/drivers/net/ngbe/base/ngbe_hw.h @@ -14,6 +14,7 @@ #define NGBE_EM_MC_TBL_SIZE 32 s32 ngbe_init_hw(struct ngbe_hw *hw); +s32 ngbe_start_hw(struct ngbe_hw *hw); s32 ngbe_reset_hw_em(struct ngbe_hw *hw); s32 ngbe_stop_hw(struct ngbe_hw *hw); s32 ngbe_get_mac_addr(struct ngbe_hw *hw, u8 *mac_addr); @@ -22,6 +23,9 @@ void ngbe_set_lan_id_multi_port(struct ngbe_hw *hw); s32 ngbe_check_mac_link_em(struct ngbe_hw *hw, u32 *speed, bool *link_up, bool link_up_wait_to_complete); +s32 ngbe_get_link_capabilities_em(struct ngbe_hw *hw, + u32 *speed, + bool *autoneg); s32 ngbe_setup_mac_link_em(struct ngbe_hw *hw, u32 speed, bool autoneg_wait_to_complete); diff --git a/drivers/net/ngbe/base/ngbe_phy.c b/drivers/net/ngbe/base/ngbe_phy.c index 7a9baada81..47a5687b48 100644 --- a/drivers/net/ngbe/base/ngbe_phy.c +++ b/drivers/net/ngbe/base/ngbe_phy.c @@ -426,16 +426,19 @@ s32 ngbe_init_phy(struct ngbe_hw *hw) /* Set necessary function pointers based on PHY type */ switch (hw->phy.type) { case ngbe_phy_rtl: + hw->phy.init_hw = ngbe_init_phy_rtl; hw->phy.check_link = ngbe_check_phy_link_rtl; hw->phy.setup_link = ngbe_setup_phy_link_rtl; break; case ngbe_phy_mvl: case ngbe_phy_mvl_sfi: + hw->phy.init_hw = ngbe_init_phy_mvl; hw->phy.check_link = ngbe_check_phy_link_mvl; hw->phy.setup_link = ngbe_setup_phy_link_mvl; break; case ngbe_phy_yt8521s: case ngbe_phy_yt8521s_sfi: + hw->phy.init_hw = ngbe_init_phy_yt; hw->phy.check_link = ngbe_check_phy_link_yt; hw->phy.setup_link = ngbe_setup_phy_link_yt; default: diff --git a/drivers/net/ngbe/base/ngbe_phy_mvl.c b/drivers/net/ngbe/base/ngbe_phy_mvl.c index a1c055e238..33d21edfce 100644 --- a/drivers/net/ngbe/base/ngbe_phy_mvl.c +++ b/drivers/net/ngbe/base/ngbe_phy_mvl.c @@ -48,6 +48,70 @@ s32 ngbe_write_phy_reg_mvl(struct ngbe_hw *hw, return 0; } +s32 ngbe_init_phy_mvl(struct ngbe_hw *hw) +{ + s32 ret_val = 0; + u16 value = 0; + int i; + + DEBUGFUNC("ngbe_init_phy_mvl"); + + /* enable interrupts, only link status change and an done is allowed */ + ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 2); + ngbe_read_phy_reg_mdi(hw, MVL_RGM_CTL2, 0, &value); + value &= ~MVL_RGM_CTL2_TTC; + value |= MVL_RGM_CTL2_RTC; + ngbe_write_phy_reg_mdi(hw, MVL_RGM_CTL2, 0, value); + + hw->phy.write_reg(hw, MVL_CTRL, 0, MVL_CTRL_RESET); + for (i = 0; i < 15; i++) { + ngbe_read_phy_reg_mdi(hw, MVL_CTRL, 0, &value); + if (value & MVL_CTRL_RESET) + msleep(1); + else + break; + } + + if (i == 15) { + DEBUGOUT("phy reset exceeds maximum waiting period.\n"); + return NGBE_ERR_TIMEOUT; + } + + ret_val = hw->phy.reset_hw(hw); + if (ret_val) + return ret_val; + + /* set LED2 to interrupt output and INTn active low */ + ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 3); + ngbe_read_phy_reg_mdi(hw, MVL_LEDTCR, 0, &value); + value |= MVL_LEDTCR_INTR_EN; + value &= ~(MVL_LEDTCR_INTR_POL); + ngbe_write_phy_reg_mdi(hw, MVL_LEDTCR, 0, value); + + if (hw->phy.type == ngbe_phy_mvl_sfi) { + hw->phy.read_reg(hw, MVL_CTRL1, 0, &value); + value &= ~MVL_CTRL1_INTR_POL; + ngbe_write_phy_reg_mdi(hw, MVL_CTRL1, 0, value); + } + + /* enable link status change and AN complete interrupts */ + value = MVL_INTR_EN_ANC | MVL_INTR_EN_LSC; + hw->phy.write_reg(hw, MVL_INTR_EN, 0, value); + + /* LED control */ + ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 3); + ngbe_read_phy_reg_mdi(hw, MVL_LEDFCR, 0, &value); + value &= ~(MVL_LEDFCR_CTL0 | MVL_LEDFCR_CTL1); + value |= MVL_LEDFCR_CTL0_CONF | MVL_LEDFCR_CTL1_CONF; + ngbe_write_phy_reg_mdi(hw, MVL_LEDFCR, 0, value); + ngbe_read_phy_reg_mdi(hw, MVL_LEDPCR, 0, &value); + value &= ~(MVL_LEDPCR_CTL0 | MVL_LEDPCR_CTL1); + value |= MVL_LEDPCR_CTL0_CONF | MVL_LEDPCR_CTL1_CONF; + ngbe_write_phy_reg_mdi(hw, MVL_LEDPCR, 0, value); + + return ret_val; +} + s32 ngbe_setup_phy_link_mvl(struct ngbe_hw *hw, u32 speed, bool autoneg_wait_to_complete) { diff --git a/drivers/net/ngbe/base/ngbe_phy_mvl.h b/drivers/net/ngbe/base/ngbe_phy_mvl.h index a663a429dd..34cb1e838a 100644 --- a/drivers/net/ngbe/base/ngbe_phy_mvl.h +++ b/drivers/net/ngbe/base/ngbe_phy_mvl.h @@ -86,6 +86,7 @@ s32 ngbe_read_phy_reg_mvl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, u16 *phy_data); s32 ngbe_write_phy_reg_mvl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data); +s32 ngbe_init_phy_mvl(struct ngbe_hw *hw); s32 ngbe_reset_phy_mvl(struct ngbe_hw *hw); diff --git a/drivers/net/ngbe/base/ngbe_phy_rtl.c b/drivers/net/ngbe/base/ngbe_phy_rtl.c index 5214ce5a8a..535259d8fd 100644 --- a/drivers/net/ngbe/base/ngbe_phy_rtl.c +++ b/drivers/net/ngbe/base/ngbe_phy_rtl.c @@ -36,6 +36,64 @@ s32 ngbe_write_phy_reg_rtl(struct ngbe_hw *hw, return 0; } +s32 ngbe_init_phy_rtl(struct ngbe_hw *hw) +{ + int i; + u16 value = 0; + + /* enable interrupts, only link status change and an done is allowed */ + value = RTL_INER_LSC | RTL_INER_ANC; + hw->phy.write_reg(hw, RTL_INER, 0xa42, value); + + hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value); + + for (i = 0; i < 15; i++) { + if (!rd32m(hw, NGBE_STAT, + NGBE_STAT_GPHY_IN_RST(hw->bus.lan_id))) + break; + + msec_delay(10); + } + if (i == 15) { + DEBUGOUT("GPhy reset exceeds maximum times.\n"); + return NGBE_ERR_PHY_TIMEOUT; + } + + for (i = 0; i < 1000; i++) { + hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value); + if (value & RTL_INSR_ACCESS) + break; + } + + hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EFUSE); + for (i = 0; i < 1000; i++) { + hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value); + if (value & RTL_INSR_ACCESS) + break; + } + if (i == 1000) + return NGBE_ERR_PHY_TIMEOUT; + + hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EXTINI); + for (i = 0; i < 1000; i++) { + hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value); + if (value & RTL_INSR_ACCESS) + break; + } + if (i == 1000) + return NGBE_ERR_PHY_TIMEOUT; + + for (i = 0; i < 1000; i++) { + hw->phy.read_reg(hw, RTL_GSR, 0xa42, &value); + if ((value & RTL_GSR_ST) == RTL_GSR_ST_LANON) + break; + } + if (i == 1000) + return NGBE_ERR_PHY_TIMEOUT; + + return 0; +} + /** * ngbe_setup_phy_link_rtl - Set and restart auto-neg * @hw: pointer to hardware structure diff --git a/drivers/net/ngbe/base/ngbe_phy_rtl.h b/drivers/net/ngbe/base/ngbe_phy_rtl.h index e8bc4a1bd7..e6e7df5254 100644 --- a/drivers/net/ngbe/base/ngbe_phy_rtl.h +++ b/drivers/net/ngbe/base/ngbe_phy_rtl.h @@ -80,6 +80,8 @@ s32 ngbe_write_phy_reg_rtl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, s32 ngbe_setup_phy_link_rtl(struct ngbe_hw *hw, u32 speed, bool autoneg_wait_to_complete); + +s32 ngbe_init_phy_rtl(struct ngbe_hw *hw); s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw); s32 ngbe_check_phy_link_rtl(struct ngbe_hw *hw, u32 *speed, bool *link_up); diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.c b/drivers/net/ngbe/base/ngbe_phy_yt.c index f518dc0af6..94d3430fa4 100644 --- a/drivers/net/ngbe/base/ngbe_phy_yt.c +++ b/drivers/net/ngbe/base/ngbe_phy_yt.c @@ -98,6 +98,32 @@ s32 ngbe_write_phy_reg_sds_ext_yt(struct ngbe_hw *hw, return 0; } +s32 ngbe_init_phy_yt(struct ngbe_hw *hw) +{ + u16 value = 0; + + DEBUGFUNC("ngbe_init_phy_yt"); + + if (hw->phy.type != ngbe_phy_yt8521s_sfi) + return 0; + + /* select sds area register */ + ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0); + /* enable interrupts */ + ngbe_write_phy_reg_mdi(hw, YT_INTR, 0, YT_INTR_ENA_MASK); + + /* select fiber_to_rgmii first in multiplex */ + ngbe_read_phy_reg_ext_yt(hw, YT_MISC, 0, &value); + value |= YT_MISC_FIBER_PRIO; + ngbe_write_phy_reg_ext_yt(hw, YT_MISC, 0, value); + + hw->phy.read_reg(hw, YT_BCR, 0, &value); + value |= YT_BCR_PWDN; + hw->phy.write_reg(hw, YT_BCR, 0, value); + + return 0; +} + s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed, bool autoneg_wait_to_complete) { diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.h b/drivers/net/ngbe/base/ngbe_phy_yt.h index 26820ecb92..5babd841c1 100644 --- a/drivers/net/ngbe/base/ngbe_phy_yt.h +++ b/drivers/net/ngbe/base/ngbe_phy_yt.h @@ -65,6 +65,7 @@ s32 ngbe_read_phy_reg_sds_ext_yt(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, u16 *phy_data); s32 ngbe_write_phy_reg_sds_ext_yt(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data); +s32 ngbe_init_phy_yt(struct ngbe_hw *hw); s32 ngbe_reset_phy_yt(struct ngbe_hw *hw); diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h index bc99d9c3db..601fb85b91 100644 --- a/drivers/net/ngbe/base/ngbe_type.h +++ b/drivers/net/ngbe/base/ngbe_type.h @@ -26,6 +26,12 @@ struct ngbe_thermal_sensor_data { struct ngbe_thermal_diode_data sensor[1]; }; +/* Physical layer type */ +#define NGBE_PHYSICAL_LAYER_UNKNOWN 0 +#define NGBE_PHYSICAL_LAYER_10GBASE_T 0x00001 +#define NGBE_PHYSICAL_LAYER_1000BASE_T 0x00002 +#define NGBE_PHYSICAL_LAYER_100BASE_TX 0x00004 + enum ngbe_eeprom_type { ngbe_eeprom_unknown = 0, ngbe_eeprom_spi, @@ -93,15 +99,20 @@ struct ngbe_rom_info { struct ngbe_mac_info { s32 (*init_hw)(struct ngbe_hw *hw); s32 (*reset_hw)(struct ngbe_hw *hw); + s32 (*start_hw)(struct ngbe_hw *hw); s32 (*stop_hw)(struct ngbe_hw *hw); s32 (*get_mac_addr)(struct ngbe_hw *hw, u8 *mac_addr); s32 (*acquire_swfw_sync)(struct ngbe_hw *hw, u32 mask); void (*release_swfw_sync)(struct ngbe_hw *hw, u32 mask); + /* Link */ s32 (*setup_link)(struct ngbe_hw *hw, u32 speed, bool autoneg_wait_to_complete); s32 (*check_link)(struct ngbe_hw *hw, u32 *speed, bool *link_up, bool link_up_wait_to_complete); + s32 (*get_link_capabilities)(struct ngbe_hw *hw, + u32 *speed, bool *autoneg); + /* RAR */ s32 (*set_rar)(struct ngbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr); @@ -126,10 +137,13 @@ struct ngbe_mac_info { struct ngbe_thermal_sensor_data thermal_sensor_data; bool set_lben; u32 max_link_up_time; + + u32 default_speeds; }; struct ngbe_phy_info { s32 (*identify)(struct ngbe_hw *hw); + s32 (*init_hw)(struct ngbe_hw *hw); s32 (*reset_hw)(struct ngbe_hw *hw); s32 (*read_reg)(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, u16 *phy_data); @@ -151,6 +165,7 @@ struct ngbe_phy_info { u32 phy_semaphore_mask; bool reset_disable; u32 autoneg_advertised; + u32 link_mode; }; enum ngbe_isb_idx { @@ -178,6 +193,8 @@ struct ngbe_hw { uint64_t isb_dma; void IOMEM *isb_mem; + u16 nb_rx_queues; + u16 nb_tx_queues; bool is_pf; }; diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 1a6419e5a4..3812663591 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -14,9 +14,17 @@ #include "ngbe_rxtx.h" static int ngbe_dev_close(struct rte_eth_dev *dev); - +static int ngbe_dev_link_update(struct rte_eth_dev *dev, + int wait_to_complete); + +static void ngbe_dev_link_status_print(struct rte_eth_dev *dev); +static int ngbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev, uint8_t on); +static int ngbe_dev_macsec_interrupt_setup(struct rte_eth_dev *dev); +static int ngbe_dev_misc_interrupt_setup(struct rte_eth_dev *dev); +static int ngbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev); static void ngbe_dev_interrupt_handler(void *param); static void ngbe_dev_interrupt_delayed_handler(void *param); +static void ngbe_configure_msix(struct rte_eth_dev *dev); /* * The set of PCI devices this driver supports @@ -52,6 +60,25 @@ static const struct rte_eth_desc_lim tx_desc_lim = { }; static const struct eth_dev_ops ngbe_eth_dev_ops; +static inline int32_t +ngbe_pf_reset_hw(struct ngbe_hw *hw) +{ + uint32_t ctrl_ext; + int32_t status; + + status = hw->mac.reset_hw(hw); + + ctrl_ext = rd32(hw, NGBE_PORTCTL); + /* Set PF Reset Done bit so PF/VF Mail Ops can work */ + ctrl_ext |= NGBE_PORTCTL_RSTDONE; + wr32(hw, NGBE_PORTCTL, ctrl_ext); + ngbe_flush(hw); + + if (status == NGBE_ERR_SFP_NOT_PRESENT) + status = 0; + return status; +} + static inline void ngbe_enable_intr(struct rte_eth_dev *dev) { @@ -217,9 +244,18 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) ctrl_ext = rd32(hw, NGBE_PORTCTL); /* let hardware know driver is loaded */ ctrl_ext |= NGBE_PORTCTL_DRVLOAD; + /* Set PF Reset Done bit so PF/VF Mail Ops can work */ + ctrl_ext |= NGBE_PORTCTL_RSTDONE; wr32(hw, NGBE_PORTCTL, ctrl_ext); ngbe_flush(hw); + PMD_INIT_LOG(DEBUG, "MAC: %d, PHY: %d", + (int)hw->mac.type, (int)hw->phy.type); + + PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x", + eth_dev->data->port_id, pci_dev->id.vendor_id, + pci_dev->id.device_id); + rte_intr_callback_register(intr_handle, ngbe_dev_interrupt_handler, eth_dev); @@ -302,6 +338,196 @@ ngbe_dev_configure(struct rte_eth_dev *dev) return 0; } +static void +ngbe_dev_phy_intr_setup(struct rte_eth_dev *dev) +{ + struct ngbe_hw *hw = NGBE_DEV_HW(dev); + struct ngbe_interrupt *intr = NGBE_DEV_INTR(dev); + + wr32(hw, NGBE_GPIODIR, NGBE_GPIODIR_DDR(1)); + wr32(hw, NGBE_GPIOINTEN, NGBE_GPIOINTEN_INT(3)); + wr32(hw, NGBE_GPIOINTTYPE, NGBE_GPIOINTTYPE_LEVEL(0)); + if (hw->phy.type == ngbe_phy_yt8521s_sfi) + wr32(hw, NGBE_GPIOINTPOL, NGBE_GPIOINTPOL_ACT(0)); + else + wr32(hw, NGBE_GPIOINTPOL, NGBE_GPIOINTPOL_ACT(3)); + + intr->mask_misc |= NGBE_ICRMISC_GPIO; +} + +/* + * Configure device link speed and setup link. + * It returns 0 on success. + */ +static int +ngbe_dev_start(struct rte_eth_dev *dev) +{ + struct ngbe_hw *hw = NGBE_DEV_HW(dev); + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; + uint32_t intr_vector = 0; + int err; + bool link_up = false, negotiate = 0; + uint32_t speed = 0; + uint32_t allowed_speeds = 0; + int status; + uint32_t *link_speeds; + + PMD_INIT_FUNC_TRACE(); + + if (dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_FIXED) { + PMD_INIT_LOG(ERR, + "Invalid link_speeds for port %u, fix speed not supported", + dev->data->port_id); + return -EINVAL; + } + + /* disable uio/vfio intr/eventfd mapping */ + rte_intr_disable(intr_handle); + + /* stop adapter */ + hw->adapter_stopped = 0; + ngbe_stop_hw(hw); + + /* reinitialize adapter + * this calls reset and start + */ + hw->nb_rx_queues = dev->data->nb_rx_queues; + hw->nb_tx_queues = dev->data->nb_tx_queues; + status = ngbe_pf_reset_hw(hw); + if (status != 0) + return -1; + hw->mac.start_hw(hw); + hw->mac.get_link_status = true; + + ngbe_dev_phy_intr_setup(dev); + + /* check and configure queue intr-vector mapping */ + if ((rte_intr_cap_multiple(intr_handle) || + !RTE_ETH_DEV_SRIOV(dev).active) && + dev->data->dev_conf.intr_conf.rxq != 0) { + intr_vector = dev->data->nb_rx_queues; + if (rte_intr_efd_enable(intr_handle, intr_vector)) + return -1; + } + + if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) { + intr_handle->intr_vec = + rte_zmalloc("intr_vec", + dev->data->nb_rx_queues * sizeof(int), 0); + if (intr_handle->intr_vec == NULL) { + PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues" + " intr_vec", dev->data->nb_rx_queues); + return -ENOMEM; + } + } + + /* confiugre msix for sleep until rx interrupt */ + ngbe_configure_msix(dev); + + /* initialize transmission unit */ + ngbe_dev_tx_init(dev); + + /* This can fail when allocating mbufs for descriptor rings */ + err = ngbe_dev_rx_init(dev); + if (err) { + PMD_INIT_LOG(ERR, "Unable to initialize RX hardware"); + goto error; + } + + /* Skip link setup if loopback mode is enabled. */ + if (hw->is_pf && dev->data->dev_conf.lpbk_mode) + goto skip_link_setup; + + err = hw->mac.check_link(hw, &speed, &link_up, 0); + if (err) + goto error; + dev->data->dev_link.link_status = link_up; + + err = hw->mac.get_link_capabilities(hw, &speed, &negotiate); + if (err) + goto error; + + allowed_speeds = 0; + if (hw->mac.default_speeds & NGBE_LINK_SPEED_1GB_FULL) + allowed_speeds |= ETH_LINK_SPEED_1G; + if (hw->mac.default_speeds & NGBE_LINK_SPEED_100M_FULL) + allowed_speeds |= ETH_LINK_SPEED_100M; + if (hw->mac.default_speeds & NGBE_LINK_SPEED_10M_FULL) + allowed_speeds |= ETH_LINK_SPEED_10M; + + link_speeds = &dev->data->dev_conf.link_speeds; + if (*link_speeds & ~allowed_speeds) { + PMD_INIT_LOG(ERR, "Invalid link setting"); + goto error; + } + + speed = 0x0; + if (*link_speeds == ETH_LINK_SPEED_AUTONEG) { + speed = hw->mac.default_speeds; + } else { + if (*link_speeds & ETH_LINK_SPEED_1G) + speed |= NGBE_LINK_SPEED_1GB_FULL; + if (*link_speeds & ETH_LINK_SPEED_100M) + speed |= NGBE_LINK_SPEED_100M_FULL; + if (*link_speeds & ETH_LINK_SPEED_10M) + speed |= NGBE_LINK_SPEED_10M_FULL; + } + + hw->phy.init_hw(hw); + err = hw->mac.setup_link(hw, speed, link_up); + if (err) + goto error; + +skip_link_setup: + + if (rte_intr_allow_others(intr_handle)) { + ngbe_dev_misc_interrupt_setup(dev); + /* check if lsc interrupt is enabled */ + if (dev->data->dev_conf.intr_conf.lsc != 0) + ngbe_dev_lsc_interrupt_setup(dev, TRUE); + else + ngbe_dev_lsc_interrupt_setup(dev, FALSE); + ngbe_dev_macsec_interrupt_setup(dev); + ngbe_set_ivar_map(hw, -1, 1, NGBE_MISC_VEC_ID); + } else { + rte_intr_callback_unregister(intr_handle, + ngbe_dev_interrupt_handler, dev); + if (dev->data->dev_conf.intr_conf.lsc != 0) + PMD_INIT_LOG(INFO, "lsc won't enable because of" + " no intr multiplex"); + } + + /* check if rxq interrupt is enabled */ + if (dev->data->dev_conf.intr_conf.rxq != 0 && + rte_intr_dp_is_en(intr_handle)) + ngbe_dev_rxq_interrupt_setup(dev); + + /* enable uio/vfio intr/eventfd mapping */ + rte_intr_enable(intr_handle); + + /* resume enabled intr since hw reset */ + ngbe_enable_intr(dev); + + if ((hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_M88E1512_SFP || + (hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_YT8521S_SFP) { + /* gpio0 is used to power on/off control*/ + wr32(hw, NGBE_GPIODATA, 0); + } + + /* + * Update link status right before return, because it may + * start link configuration process in a separate thread. + */ + ngbe_dev_link_update(dev, 0); + + return 0; + +error: + PMD_INIT_LOG(ERR, "failure in dev start: %d", err); + return -EIO; +} + /* * Reset and stop device. */ @@ -487,6 +713,106 @@ ngbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete) return ngbe_dev_link_update_share(dev, wait_to_complete); } +/** + * It clears the interrupt causes and enables the interrupt. + * It will be called once only during nic initialized. + * + * @param dev + * Pointer to struct rte_eth_dev. + * @param on + * Enable or Disable. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ngbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev, uint8_t on) +{ + struct ngbe_interrupt *intr = NGBE_DEV_INTR(dev); + + ngbe_dev_link_status_print(dev); + if (on) { + intr->mask_misc |= NGBE_ICRMISC_PHY; + intr->mask_misc |= NGBE_ICRMISC_GPIO; + } else { + intr->mask_misc &= ~NGBE_ICRMISC_PHY; + intr->mask_misc &= ~NGBE_ICRMISC_GPIO; + } + + return 0; +} + +/** + * It clears the interrupt causes and enables the interrupt. + * It will be called once only during nic initialized. + * + * @param dev + * Pointer to struct rte_eth_dev. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ngbe_dev_misc_interrupt_setup(struct rte_eth_dev *dev) +{ + struct ngbe_interrupt *intr = NGBE_DEV_INTR(dev); + u64 mask; + + mask = NGBE_ICR_MASK; + mask &= (1ULL << NGBE_MISC_VEC_ID); + intr->mask |= mask; + intr->mask_misc |= NGBE_ICRMISC_GPIO; + + return 0; +} + +/** + * It clears the interrupt causes and enables the interrupt. + * It will be called once only during nic initialized. + * + * @param dev + * Pointer to struct rte_eth_dev. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ngbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev) +{ + struct ngbe_interrupt *intr = NGBE_DEV_INTR(dev); + u64 mask; + + mask = NGBE_ICR_MASK; + mask &= ~((1ULL << NGBE_RX_VEC_START) - 1); + intr->mask |= mask; + + return 0; +} + +/** + * It clears the interrupt causes and enables the interrupt. + * It will be called once only during nic initialized. + * + * @param dev + * Pointer to struct rte_eth_dev. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ngbe_dev_macsec_interrupt_setup(struct rte_eth_dev *dev) +{ + struct ngbe_interrupt *intr = NGBE_DEV_INTR(dev); + + intr->mask_misc |= NGBE_ICRMISC_LNKSEC; + + return 0; +} + /* * It reads ICR and sets flag for the link_update. * @@ -693,9 +1019,101 @@ ngbe_dev_interrupt_handler(void *param) ngbe_dev_interrupt_action(dev); } +/** + * set the IVAR registers, mapping interrupt causes to vectors + * @param hw + * pointer to ngbe_hw struct + * @direction + * 0 for Rx, 1 for Tx, -1 for other causes + * @queue + * queue to map the corresponding interrupt to + * @msix_vector + * the vector to map to the corresponding queue + */ +void +ngbe_set_ivar_map(struct ngbe_hw *hw, int8_t direction, + uint8_t queue, uint8_t msix_vector) +{ + uint32_t tmp, idx; + + if (direction == -1) { + /* other causes */ + msix_vector |= NGBE_IVARMISC_VLD; + idx = 0; + tmp = rd32(hw, NGBE_IVARMISC); + tmp &= ~(0xFF << idx); + tmp |= (msix_vector << idx); + wr32(hw, NGBE_IVARMISC, tmp); + } else { + /* rx or tx causes */ + /* Workround for ICR lost */ + idx = ((16 * (queue & 1)) + (8 * direction)); + tmp = rd32(hw, NGBE_IVAR(queue >> 1)); + tmp &= ~(0xFF << idx); + tmp |= (msix_vector << idx); + wr32(hw, NGBE_IVAR(queue >> 1), tmp); + } +} + +/** + * Sets up the hardware to properly generate MSI-X interrupts + * @hw + * board private structure + */ +static void +ngbe_configure_msix(struct rte_eth_dev *dev) +{ + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; + struct ngbe_hw *hw = NGBE_DEV_HW(dev); + uint32_t queue_id, base = NGBE_MISC_VEC_ID; + uint32_t vec = NGBE_MISC_VEC_ID; + uint32_t gpie; + + /* won't configure msix register if no mapping is done + * between intr vector and event fd + * but if misx has been enabled already, need to configure + * auto clean, auto mask and throttling. + */ + gpie = rd32(hw, NGBE_GPIE); + if (!rte_intr_dp_is_en(intr_handle) && + !(gpie & NGBE_GPIE_MSIX)) + return; + + if (rte_intr_allow_others(intr_handle)) { + base = NGBE_RX_VEC_START; + vec = base; + } + + /* setup GPIE for MSI-x mode */ + gpie = rd32(hw, NGBE_GPIE); + gpie |= NGBE_GPIE_MSIX; + wr32(hw, NGBE_GPIE, gpie); + + /* Populate the IVAR table and set the ITR values to the + * corresponding register. + */ + if (rte_intr_dp_is_en(intr_handle)) { + for (queue_id = 0; queue_id < dev->data->nb_rx_queues; + queue_id++) { + /* by default, 1:1 mapping */ + ngbe_set_ivar_map(hw, 0, queue_id, vec); + intr_handle->intr_vec[queue_id] = vec; + if (vec < base + intr_handle->nb_efd - 1) + vec++; + } + + ngbe_set_ivar_map(hw, -1, 1, NGBE_MISC_VEC_ID); + } + wr32(hw, NGBE_ITR(NGBE_MISC_VEC_ID), + NGBE_ITR_IVAL_1G(NGBE_QUEUE_ITR_INTERVAL_DEFAULT) + | NGBE_ITR_WRDSA); +} + static const struct eth_dev_ops ngbe_eth_dev_ops = { .dev_configure = ngbe_dev_configure, .dev_infos_get = ngbe_dev_info_get, + .dev_start = ngbe_dev_start, .link_update = ngbe_dev_link_update, .dev_supported_ptypes_get = ngbe_dev_supported_ptypes_get, .rx_queue_setup = ngbe_dev_rx_queue_setup, diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h index 035b1ad5c8..0b8dba571b 100644 --- a/drivers/net/ngbe/ngbe_ethdev.h +++ b/drivers/net/ngbe/ngbe_ethdev.h @@ -18,6 +18,8 @@ #define NGBE_VLAN_TAG_SIZE 4 #define NGBE_HKEY_MAX_INDEX 10 +#define NGBE_QUEUE_ITR_INTERVAL_DEFAULT 500 /* 500us */ + #define NGBE_RSS_OFFLOAD_ALL ( \ ETH_RSS_IPV4 | \ ETH_RSS_NONFRAG_IPV4_TCP | \ @@ -30,6 +32,7 @@ ETH_RSS_IPV6_UDP_EX) #define NGBE_MISC_VEC_ID RTE_INTR_VEC_ZERO_OFFSET +#define NGBE_RX_VEC_START RTE_INTR_VEC_RXTX_OFFSET /* structure for interrupt relative data */ struct ngbe_interrupt { @@ -92,6 +95,9 @@ uint16_t ngbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t ngbe_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); +void ngbe_set_ivar_map(struct ngbe_hw *hw, int8_t direction, + uint8_t queue, uint8_t msix_vector); + int ngbe_dev_link_update_share(struct rte_eth_dev *dev, int wait_to_complete); From patchwork Wed Jun 2 09:41:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93785 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 CF08DA0524; Wed, 2 Jun 2021 11:42:32 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E1556411AA; Wed, 2 Jun 2021 11:40:13 +0200 (CEST) Received: from smtpbgbr2.qq.com (smtpbgbr2.qq.com [54.207.22.56]) by mails.dpdk.org (Postfix) with ESMTP id 0BD8A4119B for ; Wed, 2 Jun 2021 11:40:10 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626806tuyx1x7s Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:40:06 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: aiXUkxla6RCaCzrYa9Ud8uLfQV0epSu0L+PBLQKjiy2kwggG6mwOKWf84zM5R 4TwgJ27WLNAlz4eM9sP46P3Q9BPLb9z3G3V9rDxuILTenQAGNIl4EAPLOex6b7sTtDqAOxs +x2bEn0rFO2KWCQuA5oS+Rk7AefkyfjSwUs4XJ29FPfQRdxLZSnVsYiqypNsT1Sube8sHKs GOh+9+HpZm4ftUtBq/WSR64tAKL3jJ19dxVIEqPx9HrNpsDBgWHAnECifxEvOl6B14lv59y tDtKiX47w0f8iOgkpT7NpMgo+RETqrON90Q+BgWCRutb6TrwCI1+vtk6JelIeOq2tY1fvBj bwY/5hS+dsBvVwwI9/2GWk9SIaApA== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:41:07 +0800 Message-Id: <20210602094108.1575640-24-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign7 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 23/24] net/ngbe: start and stop RxTx 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 Sender: "dev" Support to start and stop receive and transmit unit for specified queues. Signed-off-by: Jiawen Wu --- doc/guides/nics/features/ngbe.ini | 1 + drivers/net/ngbe/base/ngbe_dummy.h | 15 ++ drivers/net/ngbe/base/ngbe_hw.c | 105 ++++++++++ drivers/net/ngbe/base/ngbe_hw.h | 4 + drivers/net/ngbe/base/ngbe_type.h | 5 + drivers/net/ngbe/ngbe_ethdev.c | 10 + drivers/net/ngbe/ngbe_ethdev.h | 15 ++ drivers/net/ngbe/ngbe_rxtx.c | 307 +++++++++++++++++++++++++++++ drivers/net/ngbe/ngbe_rxtx.h | 3 + 9 files changed, 465 insertions(+) diff --git a/doc/guides/nics/features/ngbe.ini b/doc/guides/nics/features/ngbe.ini index 443c6691a3..43b6b2c2c7 100644 --- a/doc/guides/nics/features/ngbe.ini +++ b/doc/guides/nics/features/ngbe.ini @@ -7,6 +7,7 @@ Speed capabilities = Y Link status = Y Link status event = Y +Queue start/stop = Y Jumbo frame = Y Scattered Rx = Y TSO = Y diff --git a/drivers/net/ngbe/base/ngbe_dummy.h b/drivers/net/ngbe/base/ngbe_dummy.h index dfc7b13192..384631b4f1 100644 --- a/drivers/net/ngbe/base/ngbe_dummy.h +++ b/drivers/net/ngbe/base/ngbe_dummy.h @@ -59,6 +59,18 @@ static inline s32 ngbe_mac_get_mac_addr_dummy(struct ngbe_hw *TUP0, u8 *TUP1) { return NGBE_ERR_OPS_DUMMY; } +static inline s32 ngbe_mac_enable_rx_dma_dummy(struct ngbe_hw *TUP0, u32 TUP1) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_mac_disable_sec_rx_path_dummy(struct ngbe_hw *TUP0) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_mac_enable_sec_rx_path_dummy(struct ngbe_hw *TUP0) +{ + return NGBE_ERR_OPS_DUMMY; +} static inline s32 ngbe_mac_acquire_swfw_sync_dummy(struct ngbe_hw *TUP0, u32 TUP1) { @@ -167,6 +179,9 @@ static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw) hw->mac.start_hw = ngbe_mac_start_hw_dummy; hw->mac.stop_hw = ngbe_mac_stop_hw_dummy; hw->mac.get_mac_addr = ngbe_mac_get_mac_addr_dummy; + hw->mac.enable_rx_dma = ngbe_mac_enable_rx_dma_dummy; + hw->mac.disable_sec_rx_path = ngbe_mac_disable_sec_rx_path_dummy; + hw->mac.enable_sec_rx_path = ngbe_mac_enable_sec_rx_path_dummy; hw->mac.acquire_swfw_sync = ngbe_mac_acquire_swfw_sync_dummy; hw->mac.release_swfw_sync = ngbe_mac_release_swfw_sync_dummy; hw->mac.setup_link = ngbe_mac_setup_link_dummy; diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c index b0bc714741..030068f3f7 100644 --- a/drivers/net/ngbe/base/ngbe_hw.c +++ b/drivers/net/ngbe/base/ngbe_hw.c @@ -536,6 +536,63 @@ void ngbe_release_swfw_sync(struct ngbe_hw *hw, u32 mask) ngbe_release_eeprom_semaphore(hw); } +/** + * ngbe_disable_sec_rx_path - Stops the receive data path + * @hw: pointer to hardware structure + * + * Stops the receive data path and waits for the HW to internally empty + * the Rx security block + **/ +s32 ngbe_disable_sec_rx_path(struct ngbe_hw *hw) +{ +#define NGBE_MAX_SECRX_POLL 4000 + + int i; + u32 secrxreg; + + DEBUGFUNC("ngbe_disable_sec_rx_path"); + + + secrxreg = rd32(hw, NGBE_SECRXCTL); + secrxreg |= NGBE_SECRXCTL_XDSA; + wr32(hw, NGBE_SECRXCTL, secrxreg); + for (i = 0; i < NGBE_MAX_SECRX_POLL; i++) { + secrxreg = rd32(hw, NGBE_SECRXSTAT); + if (!(secrxreg & NGBE_SECRXSTAT_RDY)) + /* Use interrupt-safe sleep just in case */ + usec_delay(10); + else + break; + } + + /* For informational purposes only */ + if (i >= NGBE_MAX_SECRX_POLL) + DEBUGOUT("Rx unit being enabled before security " + "path fully disabled. Continuing with init.\n"); + + return 0; +} + +/** + * ngbe_enable_sec_rx_path - Enables the receive data path + * @hw: pointer to hardware structure + * + * Enables the receive data path. + **/ +s32 ngbe_enable_sec_rx_path(struct ngbe_hw *hw) +{ + u32 secrxreg; + + DEBUGFUNC("ngbe_enable_sec_rx_path"); + + secrxreg = rd32(hw, NGBE_SECRXCTL); + secrxreg &= ~NGBE_SECRXCTL_XDSA; + wr32(hw, NGBE_SECRXCTL, secrxreg); + ngbe_flush(hw); + + return 0; +} + /** * ngbe_clear_vmdq - Disassociate a VMDq pool index from a rx address * @hw: pointer to hardware struct @@ -757,6 +814,21 @@ void ngbe_disable_rx(struct ngbe_hw *hw) wr32m(hw, NGBE_MACRXCFG, NGBE_MACRXCFG_ENA, 0); } +void ngbe_enable_rx(struct ngbe_hw *hw) +{ + u32 pfdtxgswc; + + wr32m(hw, NGBE_MACRXCFG, NGBE_MACRXCFG_ENA, NGBE_MACRXCFG_ENA); + wr32m(hw, NGBE_PBRXCTL, NGBE_PBRXCTL_ENA, NGBE_PBRXCTL_ENA); + + if (hw->mac.set_lben) { + pfdtxgswc = rd32(hw, NGBE_PSRCTL); + pfdtxgswc |= NGBE_PSRCTL_LBENA; + wr32(hw, NGBE_PSRCTL, pfdtxgswc); + hw->mac.set_lben = false; + } +} + /** * ngbe_set_mac_type - Sets MAC type * @hw: pointer to the HW structure @@ -803,6 +875,36 @@ s32 ngbe_set_mac_type(struct ngbe_hw *hw) return err; } +/** + * ngbe_enable_rx_dma - Enable the Rx DMA unit + * @hw: pointer to hardware structure + * @regval: register value to write to RXCTRL + * + * Enables the Rx DMA unit + **/ +s32 ngbe_enable_rx_dma(struct ngbe_hw *hw, u32 regval) +{ + DEBUGFUNC("ngbe_enable_rx_dma"); + + /* + * Workaround silicon errata when enabling the Rx datapath. + * If traffic is incoming before we enable the Rx unit, it could hang + * the Rx DMA unit. Therefore, make sure the security engine is + * completely disabled prior to enabling the Rx unit. + */ + + hw->mac.disable_sec_rx_path(hw); + + if (regval & NGBE_PBRXCTL_ENA) + ngbe_enable_rx(hw); + else + ngbe_disable_rx(hw); + + hw->mac.enable_sec_rx_path(hw); + + return 0; +} + void ngbe_map_device_id(struct ngbe_hw *hw) { u16 oem = hw->sub_system_id & NGBE_OEM_MASK; @@ -887,11 +989,14 @@ s32 ngbe_init_ops_pf(struct ngbe_hw *hw) mac->init_hw = ngbe_init_hw; mac->reset_hw = ngbe_reset_hw_em; mac->start_hw = ngbe_start_hw; + mac->enable_rx_dma = ngbe_enable_rx_dma; mac->get_mac_addr = ngbe_get_mac_addr; mac->stop_hw = ngbe_stop_hw; mac->acquire_swfw_sync = ngbe_acquire_swfw_sync; mac->release_swfw_sync = ngbe_release_swfw_sync; + mac->disable_sec_rx_path = ngbe_disable_sec_rx_path; + mac->enable_sec_rx_path = ngbe_enable_sec_rx_path; /* RAR */ mac->set_rar = ngbe_set_rar; mac->clear_rar = ngbe_clear_rar; diff --git a/drivers/net/ngbe/base/ngbe_hw.h b/drivers/net/ngbe/base/ngbe_hw.h index 4fee5735ac..01f41fe9b3 100644 --- a/drivers/net/ngbe/base/ngbe_hw.h +++ b/drivers/net/ngbe/base/ngbe_hw.h @@ -34,6 +34,8 @@ s32 ngbe_set_rar(struct ngbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr); s32 ngbe_clear_rar(struct ngbe_hw *hw, u32 index); s32 ngbe_init_rx_addrs(struct ngbe_hw *hw); +s32 ngbe_disable_sec_rx_path(struct ngbe_hw *hw); +s32 ngbe_enable_sec_rx_path(struct ngbe_hw *hw); s32 ngbe_validate_mac_addr(u8 *mac_addr); s32 ngbe_acquire_swfw_sync(struct ngbe_hw *hw, u32 mask); @@ -46,10 +48,12 @@ s32 ngbe_init_uta_tables(struct ngbe_hw *hw); s32 ngbe_init_thermal_sensor_thresh(struct ngbe_hw *hw); s32 ngbe_mac_check_overtemp(struct ngbe_hw *hw); void ngbe_disable_rx(struct ngbe_hw *hw); +void ngbe_enable_rx(struct ngbe_hw *hw); s32 ngbe_init_shared_code(struct ngbe_hw *hw); s32 ngbe_set_mac_type(struct ngbe_hw *hw); s32 ngbe_init_ops_pf(struct ngbe_hw *hw); s32 ngbe_init_phy(struct ngbe_hw *hw); +s32 ngbe_enable_rx_dma(struct ngbe_hw *hw, u32 regval); void ngbe_map_device_id(struct ngbe_hw *hw); #endif /* _NGBE_HW_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h index 601fb85b91..134d2019e1 100644 --- a/drivers/net/ngbe/base/ngbe_type.h +++ b/drivers/net/ngbe/base/ngbe_type.h @@ -102,6 +102,9 @@ struct ngbe_mac_info { s32 (*start_hw)(struct ngbe_hw *hw); s32 (*stop_hw)(struct ngbe_hw *hw); s32 (*get_mac_addr)(struct ngbe_hw *hw, u8 *mac_addr); + s32 (*enable_rx_dma)(struct ngbe_hw *hw, u32 regval); + s32 (*disable_sec_rx_path)(struct ngbe_hw *hw); + s32 (*enable_sec_rx_path)(struct ngbe_hw *hw); s32 (*acquire_swfw_sync)(struct ngbe_hw *hw, u32 mask); void (*release_swfw_sync)(struct ngbe_hw *hw, u32 mask); @@ -196,6 +199,8 @@ struct ngbe_hw { u16 nb_rx_queues; u16 nb_tx_queues; + u32 q_rx_regs[8 * 4]; + u32 q_tx_regs[8 * 4]; bool is_pf; }; diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 3812663591..2b551c00c7 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -435,6 +435,12 @@ ngbe_dev_start(struct rte_eth_dev *dev) goto error; } + err = ngbe_dev_rxtx_start(dev); + if (err < 0) { + PMD_INIT_LOG(ERR, "Unable to start rxtx queues"); + goto error; + } + /* Skip link setup if loopback mode is enabled. */ if (hw->is_pf && dev->data->dev_conf.lpbk_mode) goto skip_link_setup; @@ -1116,6 +1122,10 @@ static const struct eth_dev_ops ngbe_eth_dev_ops = { .dev_start = ngbe_dev_start, .link_update = ngbe_dev_link_update, .dev_supported_ptypes_get = ngbe_dev_supported_ptypes_get, + .rx_queue_start = ngbe_dev_rx_queue_start, + .rx_queue_stop = ngbe_dev_rx_queue_stop, + .tx_queue_start = ngbe_dev_tx_queue_start, + .tx_queue_stop = ngbe_dev_tx_queue_stop, .rx_queue_setup = ngbe_dev_rx_queue_setup, .rx_queue_release = ngbe_dev_rx_queue_release, .tx_queue_setup = ngbe_dev_tx_queue_setup, diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h index 0b8dba571b..97ced40e4b 100644 --- a/drivers/net/ngbe/ngbe_ethdev.h +++ b/drivers/net/ngbe/ngbe_ethdev.h @@ -78,6 +78,21 @@ int ngbe_dev_rx_init(struct rte_eth_dev *dev); void ngbe_dev_tx_init(struct rte_eth_dev *dev); +int ngbe_dev_rxtx_start(struct rte_eth_dev *dev); + +void ngbe_dev_save_rx_queue(struct ngbe_hw *hw, uint16_t rx_queue_id); +void ngbe_dev_store_rx_queue(struct ngbe_hw *hw, uint16_t rx_queue_id); +void ngbe_dev_save_tx_queue(struct ngbe_hw *hw, uint16_t tx_queue_id); +void ngbe_dev_store_tx_queue(struct ngbe_hw *hw, uint16_t tx_queue_id); + +int ngbe_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id); + +int ngbe_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id); + +int ngbe_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id); + +int ngbe_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id); + uint16_t ngbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); diff --git a/drivers/net/ngbe/ngbe_rxtx.c b/drivers/net/ngbe/ngbe_rxtx.c index 3f3f2cab06..daa2d7ae4d 100644 --- a/drivers/net/ngbe/ngbe_rxtx.c +++ b/drivers/net/ngbe/ngbe_rxtx.c @@ -2236,6 +2236,38 @@ ngbe_dev_rx_queue_setup(struct rte_eth_dev *dev, return 0; } +static int __rte_cold +ngbe_alloc_rx_queue_mbufs(struct ngbe_rx_queue *rxq) +{ + struct ngbe_rx_entry *rxe = rxq->sw_ring; + uint64_t dma_addr; + unsigned int i; + + /* Initialize software ring entries */ + for (i = 0; i < rxq->nb_rx_desc; i++) { + volatile struct ngbe_rx_desc *rxd; + struct rte_mbuf *mbuf = rte_mbuf_raw_alloc(rxq->mb_pool); + + if (mbuf == NULL) { + PMD_INIT_LOG(ERR, "RX mbuf alloc failed queue_id=%u", + (unsigned int)rxq->queue_id); + return -ENOMEM; + } + + mbuf->data_off = RTE_PKTMBUF_HEADROOM; + mbuf->port = rxq->port_id; + + dma_addr = + rte_cpu_to_le_64(rte_mbuf_data_iova_default(mbuf)); + rxd = &rxq->rx_ring[i]; + NGBE_RXD_HDRADDR(rxd, 0); + NGBE_RXD_PKTADDR(rxd, dma_addr); + rxe[i].mbuf = mbuf; + } + + return 0; +} + void __rte_cold ngbe_set_rx_function(struct rte_eth_dev *dev) { @@ -2473,3 +2505,278 @@ ngbe_dev_tx_init(struct rte_eth_dev *dev) } } +/* + * Set up link loopback mode Tx->Rx. + */ +static inline void __rte_cold +ngbe_setup_loopback_link(struct ngbe_hw *hw) +{ + PMD_INIT_FUNC_TRACE(); + + wr32m(hw, NGBE_MACRXCFG, NGBE_MACRXCFG_LB, NGBE_MACRXCFG_LB); + + msec_delay(50); +} + +/* + * Start Transmit and Receive Units. + */ +int __rte_cold +ngbe_dev_rxtx_start(struct rte_eth_dev *dev) +{ + struct ngbe_hw *hw; + struct ngbe_tx_queue *txq; + struct ngbe_rx_queue *rxq; + uint32_t dmatxctl; + uint32_t rxctrl; + uint16_t i; + int ret = 0; + + PMD_INIT_FUNC_TRACE(); + hw = NGBE_DEV_HW(dev); + + for (i = 0; i < dev->data->nb_tx_queues; i++) { + txq = dev->data->tx_queues[i]; + /* Setup Transmit Threshold Registers */ + wr32m(hw, NGBE_TXCFG(txq->reg_idx), + NGBE_TXCFG_HTHRESH_MASK | + NGBE_TXCFG_WTHRESH_MASK, + NGBE_TXCFG_HTHRESH(txq->hthresh) | + NGBE_TXCFG_WTHRESH(txq->wthresh)); + } + + dmatxctl = rd32(hw, NGBE_DMATXCTRL); + dmatxctl |= NGBE_DMATXCTRL_ENA; + wr32(hw, NGBE_DMATXCTRL, dmatxctl); + + for (i = 0; i < dev->data->nb_tx_queues; i++) { + txq = dev->data->tx_queues[i]; + if (!txq->tx_deferred_start) { + ret = ngbe_dev_tx_queue_start(dev, i); + if (ret < 0) + return ret; + } + } + + for (i = 0; i < dev->data->nb_rx_queues; i++) { + rxq = dev->data->rx_queues[i]; + if (!rxq->rx_deferred_start) { + ret = ngbe_dev_rx_queue_start(dev, i); + if (ret < 0) + return ret; + } + } + + /* Enable Receive engine */ + rxctrl = rd32(hw, NGBE_PBRXCTL); + rxctrl |= NGBE_PBRXCTL_ENA; + hw->mac.enable_rx_dma(hw, rxctrl); + + /* If loopback mode is enabled, set up the link accordingly */ + if (hw->is_pf && dev->data->dev_conf.lpbk_mode) + ngbe_setup_loopback_link(hw); + + return 0; +} + +void +ngbe_dev_save_rx_queue(struct ngbe_hw *hw, uint16_t rx_queue_id) +{ + u32 *reg = &hw->q_rx_regs[rx_queue_id * 8]; + *(reg++) = rd32(hw, NGBE_RXBAL(rx_queue_id)); + *(reg++) = rd32(hw, NGBE_RXBAH(rx_queue_id)); + *(reg++) = rd32(hw, NGBE_RXCFG(rx_queue_id)); +} + +void +ngbe_dev_store_rx_queue(struct ngbe_hw *hw, uint16_t rx_queue_id) +{ + u32 *reg = &hw->q_rx_regs[rx_queue_id * 8]; + wr32(hw, NGBE_RXBAL(rx_queue_id), *(reg++)); + wr32(hw, NGBE_RXBAH(rx_queue_id), *(reg++)); + wr32(hw, NGBE_RXCFG(rx_queue_id), *(reg++) & ~NGBE_RXCFG_ENA); +} + +void +ngbe_dev_save_tx_queue(struct ngbe_hw *hw, uint16_t tx_queue_id) +{ + u32 *reg = &hw->q_tx_regs[tx_queue_id * 8]; + *(reg++) = rd32(hw, NGBE_TXBAL(tx_queue_id)); + *(reg++) = rd32(hw, NGBE_TXBAH(tx_queue_id)); + *(reg++) = rd32(hw, NGBE_TXCFG(tx_queue_id)); +} + +void +ngbe_dev_store_tx_queue(struct ngbe_hw *hw, uint16_t tx_queue_id) +{ + u32 *reg = &hw->q_tx_regs[tx_queue_id * 8]; + wr32(hw, NGBE_TXBAL(tx_queue_id), *(reg++)); + wr32(hw, NGBE_TXBAH(tx_queue_id), *(reg++)); + wr32(hw, NGBE_TXCFG(tx_queue_id), *(reg++) & ~NGBE_TXCFG_ENA); +} + +/* + * Start Receive Units for specified queue. + */ +int __rte_cold +ngbe_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id) +{ + struct ngbe_hw *hw = NGBE_DEV_HW(dev); + struct ngbe_rx_queue *rxq; + uint32_t rxdctl; + int poll_ms; + + PMD_INIT_FUNC_TRACE(); + + rxq = dev->data->rx_queues[rx_queue_id]; + + /* Allocate buffers for descriptor rings */ + if (ngbe_alloc_rx_queue_mbufs(rxq) != 0) { + PMD_INIT_LOG(ERR, "Could not alloc mbuf for queue:%d", + rx_queue_id); + return -1; + } + rxdctl = rd32(hw, NGBE_RXCFG(rxq->reg_idx)); + rxdctl |= NGBE_RXCFG_ENA; + wr32(hw, NGBE_RXCFG(rxq->reg_idx), rxdctl); + + /* Wait until RX Enable ready */ + poll_ms = RTE_NGBE_REGISTER_POLL_WAIT_10_MS; + do { + rte_delay_ms(1); + rxdctl = rd32(hw, NGBE_RXCFG(rxq->reg_idx)); + } while (--poll_ms && !(rxdctl & NGBE_RXCFG_ENA)); + if (!poll_ms) + PMD_INIT_LOG(ERR, "Could not enable Rx Queue %d", rx_queue_id); + rte_wmb(); + wr32(hw, NGBE_RXRP(rxq->reg_idx), 0); + wr32(hw, NGBE_RXWP(rxq->reg_idx), rxq->nb_rx_desc - 1); + dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED; + + return 0; +} + +/* + * Stop Receive Units for specified queue. + */ +int __rte_cold +ngbe_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id) +{ + struct ngbe_hw *hw = NGBE_DEV_HW(dev); + struct ngbe_adapter *adapter = NGBE_DEV_ADAPTER(dev); + struct ngbe_rx_queue *rxq; + uint32_t rxdctl; + int poll_ms; + + PMD_INIT_FUNC_TRACE(); + + rxq = dev->data->rx_queues[rx_queue_id]; + + ngbe_dev_save_rx_queue(hw, rxq->reg_idx); + wr32m(hw, NGBE_RXCFG(rxq->reg_idx), NGBE_RXCFG_ENA, 0); + + /* Wait until RX Enable bit clear */ + poll_ms = RTE_NGBE_REGISTER_POLL_WAIT_10_MS; + do { + rte_delay_ms(1); + rxdctl = rd32(hw, NGBE_RXCFG(rxq->reg_idx)); + } while (--poll_ms && (rxdctl & NGBE_RXCFG_ENA)); + if (!poll_ms) + PMD_INIT_LOG(ERR, "Could not disable Rx Queue %d", rx_queue_id); + + rte_delay_us(RTE_NGBE_WAIT_100_US); + ngbe_dev_store_rx_queue(hw, rxq->reg_idx); + + ngbe_rx_queue_release_mbufs(rxq); + ngbe_reset_rx_queue(adapter, rxq); + dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED; + + return 0; +} + +/* + * Start Transmit Units for specified queue. + */ +int __rte_cold +ngbe_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id) +{ + struct ngbe_hw *hw = NGBE_DEV_HW(dev); + struct ngbe_tx_queue *txq; + uint32_t txdctl; + int poll_ms; + + PMD_INIT_FUNC_TRACE(); + + txq = dev->data->tx_queues[tx_queue_id]; + wr32m(hw, NGBE_TXCFG(txq->reg_idx), NGBE_TXCFG_ENA, NGBE_TXCFG_ENA); + + /* Wait until TX Enable ready */ + poll_ms = RTE_NGBE_REGISTER_POLL_WAIT_10_MS; + do { + rte_delay_ms(1); + txdctl = rd32(hw, NGBE_TXCFG(txq->reg_idx)); + } while (--poll_ms && !(txdctl & NGBE_TXCFG_ENA)); + if (!poll_ms) + PMD_INIT_LOG(ERR, "Could not enable " + "Tx Queue %d", tx_queue_id); + + rte_wmb(); + wr32(hw, NGBE_TXWP(txq->reg_idx), txq->tx_tail); + dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED; + + return 0; +} + +/* + * Stop Transmit Units for specified queue. + */ +int __rte_cold +ngbe_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id) +{ + struct ngbe_hw *hw = NGBE_DEV_HW(dev); + struct ngbe_tx_queue *txq; + uint32_t txdctl; + uint32_t txtdh, txtdt; + int poll_ms; + + PMD_INIT_FUNC_TRACE(); + + txq = dev->data->tx_queues[tx_queue_id]; + + /* Wait until TX queue is empty */ + poll_ms = RTE_NGBE_REGISTER_POLL_WAIT_10_MS; + do { + rte_delay_us(RTE_NGBE_WAIT_100_US); + txtdh = rd32(hw, NGBE_TXRP(txq->reg_idx)); + txtdt = rd32(hw, NGBE_TXWP(txq->reg_idx)); + } while (--poll_ms && (txtdh != txtdt)); + if (!poll_ms) + PMD_INIT_LOG(ERR, + "Tx Queue %d is not empty when stopping.", + tx_queue_id); + + ngbe_dev_save_tx_queue(hw, txq->reg_idx); + wr32m(hw, NGBE_TXCFG(txq->reg_idx), NGBE_TXCFG_ENA, 0); + + /* Wait until TX Enable bit clear */ + poll_ms = RTE_NGBE_REGISTER_POLL_WAIT_10_MS; + do { + rte_delay_ms(1); + txdctl = rd32(hw, NGBE_TXCFG(txq->reg_idx)); + } while (--poll_ms && (txdctl & NGBE_TXCFG_ENA)); + if (!poll_ms) + PMD_INIT_LOG(ERR, "Could not disable Tx Queue %d", + tx_queue_id); + + rte_delay_us(RTE_NGBE_WAIT_100_US); + ngbe_dev_store_tx_queue(hw, txq->reg_idx); + + if (txq->ops != NULL) { + txq->ops->release_mbufs(txq); + txq->ops->reset(txq); + } + dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED; + + return 0; +} + diff --git a/drivers/net/ngbe/ngbe_rxtx.h b/drivers/net/ngbe/ngbe_rxtx.h index 2cb98e2497..48241bd634 100644 --- a/drivers/net/ngbe/ngbe_rxtx.h +++ b/drivers/net/ngbe/ngbe_rxtx.h @@ -208,6 +208,9 @@ struct ngbe_tx_desc { #define rte_packet_prefetch(p) rte_prefetch1(p) +#define RTE_NGBE_REGISTER_POLL_WAIT_10_MS 10 +#define RTE_NGBE_WAIT_100_US 100 + #define NGBE_TX_MAX_SEG 40 /** From patchwork Wed Jun 2 09:41:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 93786 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru 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 7D81DA0524; Wed, 2 Jun 2021 11:42:38 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id EBD6A411AC; Wed, 2 Jun 2021 11:40:14 +0200 (CEST) Received: from smtpbgbr2.qq.com (smtpbgbr2.qq.com [54.207.22.56]) by mails.dpdk.org (Postfix) with ESMTP id BF146411A5 for ; Wed, 2 Jun 2021 11:40:12 +0200 (CEST) X-QQ-mid: bizesmtp32t1622626807t4hquvcm Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Wed, 02 Jun 2021 17:40:07 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: CBgi6aaeY4fybGPRZ6bVBtL+Mh+6FDjrm1/sBfkGlHOL4DZDX3LAPIZI41sxs WwcM0RguuBrRO2b+2iXU/lwCtcqdBYA0Ab3VrMrq8fDc10sWAdboIo99Z5SFksikk4b61G/ iF1vGv5+DJPGLXUqj8O5/WQAeEcS39GT+LjGnbG9ahk95XirFlz6R+CQ7euGsRPwufkRBZa 23yV/FEHHsvEboMJtW/M05ppyAeHtr7flC37YGb9ZiPp/5NTf+fuBn+8d9UPZpS4AOTtoP6 pGKMC/vmLAtNDxPtN3BAtS1oaw8LstnvYYEN7Mb+vWtmZuCzu1gjfW+9ygNtqFUvCQkqQZI l1lFxx561PAqNklKHgetxzP9iZLkQNL3FXtATQ8 X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Wed, 2 Jun 2021 17:41:08 +0800 Message-Id: <20210602094108.1575640-25-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210602094108.1575640-1-jiawenwu@trustnetic.com> References: <20210602094108.1575640-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign6 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v5 24/24] net/ngbe: add device stop operation 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 Sender: "dev" Support to stop, close and reset device. Signed-off-by: Jiawen Wu --- drivers/net/ngbe/ngbe_ethdev.c | 123 ++++++++++++++++++++++++++++++++- drivers/net/ngbe/ngbe_ethdev.h | 7 ++ drivers/net/ngbe/ngbe_rxtx.c | 47 +++++++++++++ 3 files changed, 175 insertions(+), 2 deletions(-) diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 2b551c00c7..d6ea621b86 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -531,20 +531,136 @@ ngbe_dev_start(struct rte_eth_dev *dev) error: PMD_INIT_LOG(ERR, "failure in dev start: %d", err); + ngbe_dev_clear_queues(dev); return -EIO; } +/* + * Stop device: disable rx and tx functions to allow for reconfiguring. + */ +static int +ngbe_dev_stop(struct rte_eth_dev *dev) +{ + struct rte_eth_link link; + struct ngbe_hw *hw = NGBE_DEV_HW(dev); + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; + + if (hw->adapter_stopped) + return 0; + + PMD_INIT_FUNC_TRACE(); + + if ((hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_M88E1512_SFP || + (hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_YT8521S_SFP) { + /* gpio0 is used to power on/off control*/ + wr32(hw, NGBE_GPIODATA, NGBE_GPIOBIT_0); + } + + /* disable interrupts */ + ngbe_disable_intr(hw); + + /* reset the NIC */ + ngbe_pf_reset_hw(hw); + hw->adapter_stopped = 0; + + /* stop adapter */ + ngbe_stop_hw(hw); + + ngbe_dev_clear_queues(dev); + + /* Clear stored conf */ + dev->data->scattered_rx = 0; + + /* Clear recorded link status */ + memset(&link, 0, sizeof(link)); + rte_eth_linkstatus_set(dev, &link); + + if (!rte_intr_allow_others(intr_handle)) + /* resume to the default handler */ + rte_intr_callback_register(intr_handle, + ngbe_dev_interrupt_handler, + (void *)dev); + + /* Clean datapath event and queue/vec mapping */ + rte_intr_efd_disable(intr_handle); + if (intr_handle->intr_vec != NULL) { + rte_free(intr_handle->intr_vec); + intr_handle->intr_vec = NULL; + } + + hw->adapter_stopped = true; + dev->data->dev_started = 0; + + return 0; +} + /* * Reset and stop device. */ static int ngbe_dev_close(struct rte_eth_dev *dev) { + struct ngbe_hw *hw = NGBE_DEV_HW(dev); + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; + int retries = 0; + int ret; + PMD_INIT_FUNC_TRACE(); - RTE_SET_USED(dev); + ngbe_pf_reset_hw(hw); - return 0; + ret = ngbe_dev_stop(dev); + + ngbe_dev_free_queues(dev); + + /* reprogram the RAR[0] in case user changed it. */ + ngbe_set_rar(hw, 0, hw->mac.addr, 0, true); + + /* Unlock any pending hardware semaphore */ + ngbe_swfw_lock_reset(hw); + + /* disable uio intr before callback unregister */ + rte_intr_disable(intr_handle); + + do { + ret = rte_intr_callback_unregister(intr_handle, + ngbe_dev_interrupt_handler, dev); + if (ret >= 0 || ret == -ENOENT) { + break; + } else if (ret != -EAGAIN) { + PMD_INIT_LOG(ERR, + "intr callback unregister failed: %d", + ret); + } + rte_delay_ms(100); + } while (retries++ < (10 + NGBE_LINK_UP_TIME)); + + rte_free(dev->data->mac_addrs); + dev->data->mac_addrs = NULL; + + rte_free(dev->data->hash_mac_addrs); + dev->data->hash_mac_addrs = NULL; + + return ret; +} + +/* + * Reset PF device. + */ +static int +ngbe_dev_reset(struct rte_eth_dev *dev) +{ + int ret; + + ret = eth_ngbe_dev_uninit(dev); + if (ret) + return ret; + + ret = eth_ngbe_dev_init(dev, NULL); + + return ret; } static int @@ -1120,6 +1236,9 @@ static const struct eth_dev_ops ngbe_eth_dev_ops = { .dev_configure = ngbe_dev_configure, .dev_infos_get = ngbe_dev_info_get, .dev_start = ngbe_dev_start, + .dev_stop = ngbe_dev_stop, + .dev_close = ngbe_dev_close, + .dev_reset = ngbe_dev_reset, .link_update = ngbe_dev_link_update, .dev_supported_ptypes_get = ngbe_dev_supported_ptypes_get, .rx_queue_start = ngbe_dev_rx_queue_start, diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h index 97ced40e4b..7ca3ebbda3 100644 --- a/drivers/net/ngbe/ngbe_ethdev.h +++ b/drivers/net/ngbe/ngbe_ethdev.h @@ -61,6 +61,13 @@ struct ngbe_adapter { #define NGBE_DEV_INTR(dev) \ (&((struct ngbe_adapter *)(dev)->data->dev_private)->intr) +/* + * RX/TX function prototypes + */ +void ngbe_dev_clear_queues(struct rte_eth_dev *dev); + +void ngbe_dev_free_queues(struct rte_eth_dev *dev); + void ngbe_dev_rx_queue_release(void *rxq); void ngbe_dev_tx_queue_release(void *txq); diff --git a/drivers/net/ngbe/ngbe_rxtx.c b/drivers/net/ngbe/ngbe_rxtx.c index daa2d7ae4d..a76b9d50a1 100644 --- a/drivers/net/ngbe/ngbe_rxtx.c +++ b/drivers/net/ngbe/ngbe_rxtx.c @@ -2236,6 +2236,53 @@ ngbe_dev_rx_queue_setup(struct rte_eth_dev *dev, return 0; } +void __rte_cold +ngbe_dev_clear_queues(struct rte_eth_dev *dev) +{ + unsigned int i; + struct ngbe_adapter *adapter = NGBE_DEV_ADAPTER(dev); + + PMD_INIT_FUNC_TRACE(); + + for (i = 0; i < dev->data->nb_tx_queues; i++) { + struct ngbe_tx_queue *txq = dev->data->tx_queues[i]; + + if (txq != NULL) { + txq->ops->release_mbufs(txq); + txq->ops->reset(txq); + } + } + + for (i = 0; i < dev->data->nb_rx_queues; i++) { + struct ngbe_rx_queue *rxq = dev->data->rx_queues[i]; + + if (rxq != NULL) { + ngbe_rx_queue_release_mbufs(rxq); + ngbe_reset_rx_queue(adapter, rxq); + } + } +} + +void +ngbe_dev_free_queues(struct rte_eth_dev *dev) +{ + unsigned int i; + + PMD_INIT_FUNC_TRACE(); + + for (i = 0; i < dev->data->nb_rx_queues; i++) { + ngbe_dev_rx_queue_release(dev->data->rx_queues[i]); + dev->data->rx_queues[i] = NULL; + } + dev->data->nb_rx_queues = 0; + + for (i = 0; i < dev->data->nb_tx_queues; i++) { + ngbe_dev_tx_queue_release(dev->data->tx_queues[i]); + dev->data->tx_queues[i] = NULL; + } + dev->data->nb_tx_queues = 0; +} + static int __rte_cold ngbe_alloc_rx_queue_mbufs(struct ngbe_rx_queue *rxq) {