From nobody Mon Jun 8 06:38:24 2026 Received: from mxhk.zte.com.cn (mxhk.zte.com.cn [160.30.148.34]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7B4F131F99C; Mon, 1 Jun 2026 06:30:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=160.30.148.34 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780295422; cv=none; b=t5os19XhZKARkIPZ9WOSN+JD7yVrDxzOcyVuZR9dlpABwQB0+RLzW1OgggCCAPr95OWLXW9iZNDyjaPcwCMTpxehFhkxFWZKOglzu7MThWbB1CezI618YkrISEJd1gWuWQyxJCm18NCq309JTvQH5XPntnfAdaQsBg2gKBKhlvU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780295422; c=relaxed/simple; bh=ktH8fqno6V7PfudIpcDsQz+OXBuwKkY2NAeq/YPtvF0=; h=Message-ID:In-Reply-To:References:Date:Mime-Version:From:To:Cc: Subject:Content-Type; b=Q0P5VsTdg2J0msi/TY1js3eN4ko3Sofhxb8XzGaKaP85SpdIo2J5nkjX8mM/zRBJltSSfW4806vfsjONNRrhU9wHxw8QZypbZXoUtgWPqJU/D8vIsYOBAz8JM5MIvIfrhCX8mnjlNnmprLkfSLyuOKj6vtOUgjSXv+S95Krtl8w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn; spf=pass smtp.mailfrom=zte.com.cn; arc=none smtp.client-ip=160.30.148.34 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zte.com.cn Received: from mse-fl2.zte.com.cn (unknown [10.5.228.133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mxhk.zte.com.cn (FangMail) with ESMTPS id 4gTPG86XQgz5B1Hf; Mon, 01 Jun 2026 14:30:08 +0800 (CST) Received: from njb2app06.zte.com.cn ([10.55.23.119]) by mse-fl2.zte.com.cn with SMTP id 6516U0Cx035756; Mon, 1 Jun 2026 14:30:00 +0800 (+08) (envelope-from han.junyang@zte.com.cn) Received: from mapi (njb2app06[null]) by mapi (Zmail) with MAPI id mid204; Mon, 1 Jun 2026 14:30:02 +0800 (CST) X-Zmail-TransId: 2afe6a1d26ea242-0bd68 X-Mailer: Zmail v1.0 Message-ID: <20260601143002051rSxzNiN9iKNj5gsdema0a@zte.com.cn> In-Reply-To: <20260601142440024x-1sx0cQucoMxTHjm7ps3@zte.com.cn> References: 20260601142440024x-1sx0cQucoMxTHjm7ps3@zte.com.cn Date: Mon, 1 Jun 2026 14:30:02 +0800 (CST) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 From: To: , , , , , Cc: , , , , , Subject: =?UTF-8?B?W1BBVENIIG5ldC1uZXh0IHY1IDEvMl0gZGluZ2hhaTogYWRkIFpURSBuZXR3b3JrIGRyaXZlciBzdXBwb3J0?= X-MAIL: mse-fl2.zte.com.cn 6516U0Cx035756 X-TLS: YES X-ENVELOPE-SENDER: han.junyang@zte.com.cn X-SOURCE-IP: 10.5.228.133 unknown Mon, 01 Jun 2026 14:30:08 +0800 X-CLEAN: YES X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 6A1D26F0.000/4gTPG86XQgz5B1Hf Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Junyang Han Add basic framework for ZTE DingHai ethernet PF driver, including Kconfig/Makefile build support and PCIe device probe/remove skeleton. Signed-off-by: Junyang Han --- MAINTAINERS | 6 + drivers/net/ethernet/Kconfig | 1 + drivers/net/ethernet/Makefile | 1 + drivers/net/ethernet/zte/Kconfig | 20 +++ drivers/net/ethernet/zte/Makefile | 6 + drivers/net/ethernet/zte/dinghai/Kconfig | 34 ++++ drivers/net/ethernet/zte/dinghai/Makefile | 10 ++ drivers/net/ethernet/zte/dinghai/en_pf.c | 189 ++++++++++++++++++++++ drivers/net/ethernet/zte/dinghai/en_pf.h | 66 ++++++++ 9 files changed, 333 insertions(+) create mode 100644 drivers/net/ethernet/zte/Kconfig create mode 100644 drivers/net/ethernet/zte/Makefile create mode 100644 drivers/net/ethernet/zte/dinghai/Kconfig create mode 100644 drivers/net/ethernet/zte/dinghai/Makefile create mode 100644 drivers/net/ethernet/zte/dinghai/en_pf.c create mode 100644 drivers/net/ethernet/zte/dinghai/en_pf.h diff --git a/MAINTAINERS b/MAINTAINERS index 2fb1c75afd16..73692b09bf7b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -29440,6 +29440,12 @@ S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git F: sound/hda/codecs/senarytech.c +ZTE DINGHAI ETHERNET DRIVER +M: Junyang Han +L: netdev@vger.kernel.org +S: Maintained +F: drivers/net/ethernet/zte/ + THE REST M: Linus Torvalds L: linux-kernel@vger.kernel.org diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index b8f70e2a1763..c2b6996b0cfe 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -188,5 +188,6 @@ source "drivers/net/ethernet/wangxun/Kconfig" source "drivers/net/ethernet/wiznet/Kconfig" source "drivers/net/ethernet/xilinx/Kconfig" source "drivers/net/ethernet/xircom/Kconfig" +source "drivers/net/ethernet/zte/Kconfig" endif # ETHERNET diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index 57344fec6ce0..a34bcbd4df4e 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -104,3 +104,4 @@ obj-$(CONFIG_NET_VENDOR_XIRCOM) +=3D xircom/ obj-$(CONFIG_NET_VENDOR_SYNOPSYS) +=3D synopsys/ obj-$(CONFIG_NET_VENDOR_PENSANDO) +=3D pensando/ obj-$(CONFIG_OA_TC6) +=3D oa_tc6.o +obj-$(CONFIG_NET_VENDOR_ZTE) +=3D zte/ diff --git a/drivers/net/ethernet/zte/Kconfig b/drivers/net/ethernet/zte/Kc= onfig new file mode 100644 index 000000000000..b95c2fc7db77 --- /dev/null +++ b/drivers/net/ethernet/zte/Kconfig @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# ZTE driver configuration +# + +config NET_VENDOR_ZTE + bool "ZTE devices" + default y + help + If you have a network (Ethernet) card belonging to this class, say Y. + Note that the answer to this question doesn't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about Zte cards. If you say Y, you will be asked + for your specific card in the following questions. + +if NET_VENDOR_ZTE + +source "drivers/net/ethernet/zte/dinghai/Kconfig" + +endif # NET_VENDOR_ZTE diff --git a/drivers/net/ethernet/zte/Makefile b/drivers/net/ethernet/zte/M= akefile new file mode 100644 index 000000000000..cd9929b61559 --- /dev/null +++ b/drivers/net/ethernet/zte/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Makefile for the ZTE device drivers +# + +obj-$(CONFIG_DINGHAI) +=3D dinghai/ diff --git a/drivers/net/ethernet/zte/dinghai/Kconfig b/drivers/net/etherne= t/zte/dinghai/Kconfig new file mode 100644 index 000000000000..94b5bd9b3c50 --- /dev/null +++ b/drivers/net/ethernet/zte/dinghai/Kconfig @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# ZTE DingHai Ethernet driver configuration +# + +config DINGHAI + bool "ZTE DingHai Ethernet driver" + depends on NET_VENDOR_ZTE && PCI + select NET_DEVLINK + help + This driver supports ZTE DingHai Ethernet devices. + + DingHai is a high-performance Ethernet controller that supports + multiple features including hardware offloading, SR-IOV, and + advanced virtualization capabilities. + + If you say Y here, you can select specific driver variants below. + + If unsure, say N. + +if DINGHAI + +config DINGHAI_PF + tristate "ZTE DingHai PF (Physical Function) driver" + help + This driver supports ZTE DingHai PCI Express Ethernet + adapters (PF). + + To compile this driver as a module, choose M here. The module + will be named dinghai10e. + + If unsure, say N. + +endif # DINGHAI diff --git a/drivers/net/ethernet/zte/dinghai/Makefile b/drivers/net/ethern= et/zte/dinghai/Makefile new file mode 100644 index 000000000000..f55a8de518be --- /dev/null +++ b/drivers/net/ethernet/zte/dinghai/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Makefile for ZTE DingHai Ethernet driver +# + +ccflags-y +=3D -I$(src) + +obj-$(CONFIG_DINGHAI_PF) +=3D dinghai10e.o +dinghai10e-y :=3D en_pf.o + diff --git a/drivers/net/ethernet/zte/dinghai/en_pf.c b/drivers/net/etherne= t/zte/dinghai/en_pf.c new file mode 100644 index 000000000000..6523bb7574b2 --- /dev/null +++ b/drivers/net/ethernet/zte/dinghai/en_pf.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * ZTE DingHai Ethernet driver + * Copyright (c) 2022-2026, ZTE Corporation. + */ + +#include +#include +#include +#include +#include "en_pf.h" + +MODULE_AUTHOR("Junyang Han "); +MODULE_DESCRIPTION("ZTE DingHai series Ethernet driver"); +MODULE_LICENSE("GPL"); + +static const struct devlink_ops dh_pf_devlink_ops =3D {}; + +static const struct pci_device_id dh_pf_pci_table[] =3D { + { PCI_DEVICE(ZXDH_PF_VENDOR_ID, ZXDH_PF_DEVICE_ID), 0 }, + { PCI_DEVICE(ZXDH_PF_VENDOR_ID, ZXDH_VF_DEVICE_ID), 0 }, + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, dh_pf_pci_table); + +static int dh_pf_pci_init(struct dh_core_dev *dev) +{ + struct zxdh_pf_device *pf_dev =3D dev->priv; + int ret; + + pci_set_drvdata(dev->pdev, dev); + + ret =3D pci_enable_device(dev->pdev); + if (ret) { + dev_err(dev->device, "pci_enable_device failed: %d\n", ret); + return ret; + } + + ret =3D dma_set_mask_and_coherent(dev->device, DMA_BIT_MASK(64)); + if (ret) { + ret =3D dma_set_mask_and_coherent(dev->device, DMA_BIT_MASK(32)); + if (ret) { + dev_err(dev->device, "dma_set_mask_and_coherent failed: %d\n", ret); + goto err_pci; + } + } + + ret =3D pci_request_selected_regions(dev->pdev, + pci_select_bars(dev->pdev, IORESOURCE_MEM), + "dh-pf"); + if (ret) { + dev_err(dev->device, "pci_request_selected_regions failed: %d\n", ret); + goto err_pci; + } + + pci_set_master(dev->pdev); + ret =3D pci_save_state(dev->pdev); + if (ret) { + dev_err(dev->device, "pci_save_state failed: %d\n", ret); + goto err_pci_save_state; + } + + pf_dev->pci_ioremap_addr[0] =3D + ioremap(pci_resource_start(dev->pdev, 0), + pci_resource_len(dev->pdev, 0)); + if (!pf_dev->pci_ioremap_addr[0]) { + ret =3D -ENOMEM; + dev_err(dev->device, "dh pf pci ioremap failed\n"); + goto err_pci_save_state; + } + + return 0; + +err_pci_save_state: + pci_release_selected_regions(dev->pdev, + pci_select_bars(dev->pdev, IORESOURCE_MEM)); +err_pci: + pci_disable_device(dev->pdev); + return ret; +} + +void dh_pf_pci_close(struct dh_core_dev *dev) +{ + struct zxdh_pf_device *pf_dev =3D dev->priv; + + iounmap(pf_dev->pci_ioremap_addr[0]); + pci_release_selected_regions(dev->pdev, + pci_select_bars(dev->pdev, IORESOURCE_MEM)); + pci_disable_device(dev->pdev); +} + +static int dh_pf_probe(struct pci_dev *pdev, const struct pci_device_id *i= d) +{ + struct zxdh_pf_device *pf_dev; + struct dh_core_dev *dh_dev; + struct devlink *devlink; + int ret; + + dev_info(&pdev->dev, "dh_pf probe start\n"); + devlink =3D devlink_alloc(&dh_pf_devlink_ops, sizeof(struct dh_core_dev), + &pdev->dev); + if (!devlink) { + dev_err(&pdev->dev, "dh_pf devlink alloc failed\n"); + return -ENOMEM; + } + + dh_dev =3D devlink_priv(devlink); + dh_dev->device =3D &pdev->dev; + dh_dev->pdev =3D pdev; + dh_dev->devlink =3D devlink; + + pf_dev =3D dh_core_alloc_priv(dh_dev, sizeof(*pf_dev)); + if (!pf_dev) { + dev_err(&pdev->dev, "dh_pf_dev alloc failed\n"); + goto err_pf_dev; + } + + pf_dev->bar_chan_valid =3D false; + pf_dev->vepa =3D false; + mutex_init(&dh_dev->lock); + mutex_init(&pf_dev->irq_lock); + + dh_dev->coredev_type =3D GET_COREDEV_TYPE(pdev); + + ret =3D dh_pf_pci_init(dh_dev); + if (ret) { + dev_err(&pdev->dev, "dh_pf_pci_init failed: %d\n", ret); + goto err_cfg_init; + } + + dev_info(&pdev->dev, "dh_pf probe completed\n"); + + return 0; + +err_cfg_init: + mutex_destroy(&pf_dev->irq_lock); + mutex_destroy(&dh_dev->lock); + dh_core_free_priv(dh_dev); +err_pf_dev: + devlink_free(devlink); + return -ENOMEM; +} + +static void dh_pf_remove(struct pci_dev *pdev) +{ + struct dh_core_dev *dh_dev =3D pci_get_drvdata(pdev); + struct devlink *devlink =3D priv_to_devlink(dh_dev); + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + + dev_info(&pdev->dev, "dh_pf remove start\n"); + + dh_pf_pci_close(dh_dev); + mutex_destroy(&pf_dev->irq_lock); + mutex_destroy(&dh_dev->lock); + dh_core_free_priv(dh_dev); + devlink_free(devlink); + pci_set_drvdata(pdev, NULL); + + dev_info(&pdev->dev, "dh_pf remove completed\n"); +} + +static void dh_pf_shutdown(struct pci_dev *pdev) +{ + struct dh_core_dev *dh_dev =3D pci_get_drvdata(pdev); + struct devlink *devlink =3D priv_to_devlink(dh_dev); + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + + dev_info(&pdev->dev, "dh_pf shutdown start\n"); + + dh_pf_pci_close(dh_dev); + mutex_destroy(&pf_dev->irq_lock); + mutex_destroy(&dh_dev->lock); + dh_core_free_priv(dh_dev); + devlink_free(devlink); + pci_set_drvdata(pdev, NULL); + + dev_info(&pdev->dev, "dh_pf shutdown completed\n"); +} + +static struct pci_driver dh_pf_driver =3D { + .name =3D "dinghai10e", + .id_table =3D dh_pf_pci_table, + .probe =3D dh_pf_probe, + .remove =3D dh_pf_remove, + .shutdown =3D dh_pf_shutdown, +}; + +module_pci_driver(dh_pf_driver); diff --git a/drivers/net/ethernet/zte/dinghai/en_pf.h b/drivers/net/etherne= t/zte/dinghai/en_pf.h new file mode 100644 index 000000000000..de46e8b275ca --- /dev/null +++ b/drivers/net/ethernet/zte/dinghai/en_pf.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * ZTE DingHai Ethernet driver - PF header + * Copyright (c) 2022-2026, ZTE Corporation. + */ + +#ifndef __ZXDH_EN_PF_H__ +#define __ZXDH_EN_PF_H__ + +#include +#include +#include +#include +#include + +#define ZXDH_PF_VENDOR_ID 0x1cf2 +#define ZXDH_PF_DEVICE_ID 0x8040 +#define ZXDH_VF_DEVICE_ID 0x8041 + +enum dh_coredev_type { + DH_COREDEV_PF, + DH_COREDEV_VF, + DH_COREDEV_SF, + DH_COREDEV_MPF +}; + +struct devlink; + +struct dh_core_dev { + struct device *device; + enum dh_coredev_type coredev_type; + struct pci_dev *pdev; + struct devlink *devlink; + struct mutex lock; /* Protects device configuration */ + void *priv; +}; + +struct zxdh_pf_device { + void __iomem *pci_ioremap_addr[6]; + bool bar_chan_valid; + bool vepa; + struct mutex irq_lock; /* Protects IRQ operations */ +}; + +static inline void *dh_core_alloc_priv(struct dh_core_dev *dh_dev, + size_t size) +{ + void *priv =3D kzalloc(size, GFP_KERNEL); + + if (priv) + dh_dev->priv =3D priv; + return priv; +} + +static inline void dh_core_free_priv(struct dh_core_dev *dh_dev) +{ + kfree(dh_dev->priv); + dh_dev->priv =3D NULL; +} + +#define GET_COREDEV_TYPE(pdev) \ + ((pdev)->device =3D=3D ZXDH_VF_DEVICE_ID ? DH_COREDEV_VF : DH_COREDEV_PF) + +void dh_pf_pci_close(struct dh_core_dev *dev); + +#endif /* __ZXDH_EN_PF_H__ */ --=20 2.27.0 From nobody Mon Jun 8 06:38:24 2026 Received: from mxhk.zte.com.cn (mxhk.zte.com.cn [160.30.148.34]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E91A729D26E; Mon, 1 Jun 2026 06:34:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=160.30.148.34 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780295692; cv=none; b=X1N0xQZo2qX6fVNCUH3CChC5b1WoaOLV6zD086T/lVDwBIBu4bcLYacpvi7sDojabRYfdfjME6XjXE6QgINCEV+f8vA13DbRnybcj51twRUjYLh3aXDmbnMc0SzuO2U3LOvLag/3UgU4ArbHQuM2cqS52AUFsQjhv6O8AITQe0w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780295692; c=relaxed/simple; bh=kvHdVfS6uPIlhOSxeAU8KMWDWTCGWi1e7XhKumJPvV0=; h=Message-ID:In-Reply-To:References:Date:Mime-Version:From:To:Cc: Subject:Content-Type; b=K9dfqN7cSV6Dfqa7GDSf/3ifoFlh/ea6dLkFG3iArmxLbn/aYp1Q0qqvKt2e0gtck7/JI+g2olBxeO0tO/HVNqMopfDmF1wvLaB5+hQvA/1WWhsfXMesPRHMyu1rKDd7fLLymfYzQ57iNNRo11WVvD0HMm9VaCSZqEFLo70DupY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn; spf=pass smtp.mailfrom=zte.com.cn; arc=none smtp.client-ip=160.30.148.34 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zte.com.cn Received: from mse-fl2.zte.com.cn (unknown [10.5.228.133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mxhk.zte.com.cn (FangMail) with ESMTPS id 4gTPMX1xZ8z5BNS0; Mon, 01 Jun 2026 14:34:48 +0800 (CST) Received: from njy2app04.zte.com.cn ([10.40.12.64]) by mse-fl2.zte.com.cn with SMTP id 6516YTfH041337; Mon, 1 Jun 2026 14:34:29 +0800 (+08) (envelope-from han.junyang@zte.com.cn) Received: from mapi (njy2app03[null]) by mapi (Zmail) with MAPI id mid204; Mon, 1 Jun 2026 14:34:30 +0800 (CST) X-Zmail-TransId: 2afb6a1d27f6302-2ee05 X-Mailer: Zmail v1.0 Message-ID: <20260601143430814hXl5cU6nTauRSLsxDwssK@zte.com.cn> In-Reply-To: <20260601142440024x-1sx0cQucoMxTHjm7ps3@zte.com.cn> References: 20260601142440024x-1sx0cQucoMxTHjm7ps3@zte.com.cn Date: Mon, 1 Jun 2026 14:34:30 +0800 (CST) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 From: To: , , , , , Cc: , , , , , Subject: =?UTF-8?B?W1BBVENIIG5ldC1uZXh0IHY1IDIvMl0gZGluZ2hhaTogYWRkIGhhcmR3YXJlIHJlZ2lzdGVyIGFjY2VzcyBhbmQgUENJCiBjYXBhYmlsaXR5IHNjYW5uaW5n?= X-MAIL: mse-fl2.zte.com.cn 6516YTfH041337 X-TLS: YES X-ENVELOPE-SENDER: han.junyang@zte.com.cn X-SOURCE-IP: 10.5.228.133 unknown Mon, 01 Jun 2026 14:34:48 +0800 X-CLEAN: YES X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 6A1D2808.000/4gTPMX1xZ8z5BNS0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Junyang Han Implement PCI configuration space access, BAR mapping, capability scanning (common/notify/device), and hardware queue register definitions for DingHai PF device. Signed-off-by: Junyang Han --- drivers/net/ethernet/zte/dinghai/dh_queue.h | 71 ++++ drivers/net/ethernet/zte/dinghai/en_pf.c | 440 ++++++++++++++++++++ drivers/net/ethernet/zte/dinghai/en_pf.h | 66 +++ 3 files changed, 577 insertions(+) create mode 100644 drivers/net/ethernet/zte/dinghai/dh_queue.h diff --git a/drivers/net/ethernet/zte/dinghai/dh_queue.h b/drivers/net/ethe= rnet/zte/dinghai/dh_queue.h new file mode 100644 index 000000000000..5067c73fed33 --- /dev/null +++ b/drivers/net/ethernet/zte/dinghai/dh_queue.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * ZTE DingHai Ethernet driver - PCI capability definitions + * Copyright (c) 2022-2026, ZTE Corporation. + */ + +#ifndef __DH_QUEUE_H__ +#define __DH_QUEUE_H__ + +/* Vector value used to disable MSI for queue */ +#define ZXDH_MSI_NO_VECTOR 0xff + +/* Status byte for guest to report progress, and synchronize features */ +/* We have seen device and processed generic fields */ +#define ZXDH_CONFIG_S_ACKNOWLEDGE 1 +/* We have found a driver for the device. */ +#define ZXDH_CONFIG_S_DRIVER 2 +/* Driver has used its parts of the config, and is happy */ +#define ZXDH_CONFIG_S_DRIVER_OK 4 +/* Driver has finished configuring features */ +#define ZXDH_CONFIG_S_FEATURES_OK 8 +/* Device entered invalid state, driver must reset it */ +#define ZXDH_CONFIG_S_NEEDS_RESET 0x40 +/* We've given up on this device */ +#define ZXDH_CONFIG_S_FAILED 0x80 + +/* This is the PCI capability header: */ +struct zxdh_pf_pci_cap { + __u8 cap_vndr; /* Generic PCI field: PCI_CAP_ID_VNDR */ + __u8 cap_next; /* Generic PCI field: next ptr. */ + __u8 cap_len; /* Generic PCI field: capability length */ + __u8 cfg_type; /* Identifies the structure. */ + __u8 bar; /* Where to find it. */ + __u8 id; /* Multiple capabilities of the same type */ + __u8 padding[2]; /* Pad to full dword. */ + __le32 offset; /* Offset within bar. */ + __le32 length; /* Length of the structure, in bytes. */ +}; + +/* Fields in ZXDH_PF_PCI_CAP_COMMON_CFG: */ +struct zxdh_pf_pci_common_cfg { + /* About the whole device. */ + __le32 device_feature_select; /* read-write */ + __le32 device_feature; /* read-only */ + __le32 guest_feature_select; /* read-write */ + __le32 guest_feature; /* read-write */ + __le16 msix_config; /* read-write */ + __le16 num_queues; /* read-only */ + __u8 device_status; /* read-write */ + __u8 config_generation; /* read-only */ + + /* About a specific virtqueue. */ + __le16 queue_select; /* read-write */ + __le16 queue_size; /* read-write, power of 2. */ + __le16 queue_msix_vector; /* read-write */ + __le16 queue_enable; /* read-write */ + __le16 queue_notify_off; /* read-only */ + __le32 queue_desc_lo; /* read-write */ + __le32 queue_desc_hi; /* read-write */ + __le32 queue_avail_lo; /* read-write */ + __le32 queue_avail_hi; /* read-write */ + __le32 queue_used_lo; /* read-write */ + __le32 queue_used_hi; /* read-write */ +}; + +struct zxdh_pf_pci_notify_cap { + struct zxdh_pf_pci_cap cap; + __le32 notify_off_multiplier; /* Multiplier for queue_notify_off. */ +}; + +#endif /* __DH_QUEUE_H__ */ diff --git a/drivers/net/ethernet/zte/dinghai/en_pf.c b/drivers/net/etherne= t/zte/dinghai/en_pf.c index 6523bb7574b2..02a47b99081f 100644 --- a/drivers/net/ethernet/zte/dinghai/en_pf.c +++ b/drivers/net/ethernet/zte/dinghai/en_pf.c @@ -9,6 +9,7 @@ #include #include #include "en_pf.h" +#include "dh_queue.h" MODULE_AUTHOR("Junyang Han "); MODULE_DESCRIPTION("ZTE DingHai series Ethernet driver"); @@ -90,6 +91,445 @@ void dh_pf_pci_close(struct dh_core_dev *dev) pci_disable_device(dev->pdev); } +int zxdh_pf_pci_find_capability(struct pci_dev *pdev, u8 cfg_type, + u32 ioresource_types, int *bars) +{ + int pos; + u8 type; + u8 bar; + + for (pos =3D pci_find_capability(pdev, PCI_CAP_ID_VNDR); pos > 0; + pos =3D pci_find_next_capability(pdev, pos, PCI_CAP_ID_VNDR)) { + pci_read_config_byte(pdev, + pos + offsetof(struct zxdh_pf_pci_cap, + cfg_type), &type); + pci_read_config_byte(pdev, + pos + offsetof(struct zxdh_pf_pci_cap, bar), &bar); + + /* ignore structures with reserved BAR values */ + if (bar > ZXDH_PF_MAX_BAR_VAL) + continue; + + if (type =3D=3D cfg_type) { + if (pci_resource_len(pdev, bar) && + pci_resource_flags(pdev, bar) & ioresource_types) { + *bars |=3D (1 << bar); + return pos; + } + } + } + + return 0; +} + +void __iomem *zxdh_pf_map_capability(struct dh_core_dev *dh_dev, int off, + size_t minlen, u32 align, + u32 start, u32 size, + size_t *len, resource_size_t *pa, + u32 *bar_off) +{ + struct pci_dev *pdev =3D dh_dev->pdev; + void __iomem *p; + u32 offset; + u32 length; + u8 bar; + + pci_read_config_byte(pdev, + off + offsetof(struct zxdh_pf_pci_cap, bar), &bar); + pci_read_config_dword(pdev, + off + offsetof(struct zxdh_pf_pci_cap, + offset), &offset); + pci_read_config_dword(pdev, + off + offsetof(struct zxdh_pf_pci_cap, + length), &length); + + if (bar_off) + *bar_off =3D offset; + + if (length <=3D start) { + dev_err(dh_dev->device, "bad capability len %u (>%u expected)\n", + length, start); + return NULL; + } + + if (length - start < minlen) { + dev_err(dh_dev->device, "bad capability len %u (>=3D%zu expected)\n", + length, minlen); + return NULL; + } + + length -=3D start; + if (start + offset < offset) { + dev_err(dh_dev->device, "map wrap-around %u+%u\n", start, offset); + return NULL; + } + + offset +=3D start; + if (offset & (align - 1)) { + dev_err(dh_dev->device, "offset %u not aligned to %u\n", offset, align); + return NULL; + } + + if (length > size) + length =3D size; + + if (len) + *len =3D length; + + if (minlen + offset < minlen || + minlen + offset > pci_resource_len(pdev, bar)) { + dev_err(dh_dev->device, + "map custom queue %zu@%u out of range on bar %i length %lu\n", + minlen, offset, bar, + (unsigned long)pci_resource_len(pdev, bar)); + return NULL; + } + + p =3D pci_iomap_range(pdev, bar, offset, length); + if (!p) { + dev_err(dh_dev->device, "unable to map custom queue %u@%u on bar %i\n", + length, offset, bar); + } else if (pa) { + *pa =3D pci_resource_start(pdev, bar) + offset; + } + + return p; +} + +int zxdh_pf_common_cfg_init(struct dh_core_dev *dh_dev) +{ + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + struct pci_dev *pdev =3D dh_dev->pdev; + int common; + + /* check for a common config: if not, use legacy mode (bar 0). */ + common =3D zxdh_pf_pci_find_capability(pdev, ZXDH_PCI_CAP_COMMON_CFG, + IORESOURCE_IO | IORESOURCE_MEM, + &pf_dev->modern_bars); + if (common =3D=3D 0) { + dev_err(dh_dev->device, + "missing capabilities %i, leaving for legacy driver\n", + common); + return -ENODEV; + } + + pf_dev->common =3D zxdh_pf_map_capability(dh_dev, common, + sizeof(struct zxdh_pf_pci_common_cfg), + ZXDH_PF_ALIGN4, 0, + sizeof(struct zxdh_pf_pci_common_cfg), + NULL, NULL, NULL); + if (!pf_dev->common) { + dev_err(dh_dev->device, "pf_dev->common is null\n"); + return -EINVAL; + } + + return 0; +} + +int zxdh_pf_notify_cfg_init(struct dh_core_dev *dh_dev) +{ + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + struct pci_dev *pdev =3D dh_dev->pdev; + u32 notify_length; + u32 notify_offset; + int notify; + + /* If common is there, these should be too... */ + notify =3D zxdh_pf_pci_find_capability(pdev, ZXDH_PCI_CAP_NOTIFY_CFG, + IORESOURCE_IO | IORESOURCE_MEM, + &pf_dev->modern_bars); + if (notify =3D=3D 0) { + dev_err(dh_dev->device, "missing capabilities %i\n", notify); + return -EINVAL; + } + + pci_read_config_dword(pdev, + notify + offsetof(struct zxdh_pf_pci_notify_cap, + notify_off_multiplier), + &pf_dev->notify_offset_multiplier); + pci_read_config_dword(pdev, + notify + offsetof(struct zxdh_pf_pci_notify_cap, + cap.length), ¬ify_length); + pci_read_config_dword(pdev, + notify + offsetof(struct zxdh_pf_pci_notify_cap, + cap.offset), ¬ify_offset); + + /* We don't know how many VQs we'll map, ahead of the time. + * If notify length is small, map it all now. Otherwise, + * map each VQ individually later. + */ + if (notify_length + (notify_offset % PAGE_SIZE) <=3D PAGE_SIZE) { + pf_dev->notify_base =3D zxdh_pf_map_capability(dh_dev, notify, + ZXDH_PF_MAP_MINLEN2, + ZXDH_PF_ALIGN2, 0, + notify_length, + &pf_dev->notify_len, + &pf_dev->notify_pa, NULL); + if (!pf_dev->notify_base) { + dev_err(dh_dev->device, "pf_dev->notify_base is null\n"); + return -EINVAL; + } + } else { + pf_dev->notify_map_cap =3D notify; + } + + return 0; +} + +int zxdh_pf_device_cfg_init(struct dh_core_dev *dh_dev) +{ + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + struct pci_dev *pdev =3D dh_dev->pdev; + int device; + + /* Device capability is only mandatory for + * devices that have device-specific configuration. + */ + device =3D zxdh_pf_pci_find_capability(pdev, ZXDH_PCI_CAP_DEVICE_CFG, + IORESOURCE_IO | IORESOURCE_MEM, + &pf_dev->modern_bars); + + /* we don't know how much we should map, + * but PAGE_SIZE is more than enough for all existing devices. + */ + if (device) { + pf_dev->device =3D zxdh_pf_map_capability(dh_dev, device, 0, + ZXDH_PF_ALIGN4, 0, PAGE_SIZE, + &pf_dev->device_len, NULL, + &pf_dev->dev_cfg_bar_off); + if (!pf_dev->device) { + dev_err(dh_dev->device, "pf_dev->device is null\n"); + return -EINVAL; + } + } + return 0; +} + +void zxdh_pf_modern_cfg_uninit(struct dh_core_dev *dh_dev) +{ + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + struct pci_dev *pdev =3D dh_dev->pdev; + + if (pf_dev->device) + pci_iounmap(pdev, pf_dev->device); + if (pf_dev->notify_base) + pci_iounmap(pdev, pf_dev->notify_base); + pci_iounmap(pdev, pf_dev->common); +} + +int zxdh_pf_modern_cfg_init(struct dh_core_dev *dh_dev) +{ + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + struct pci_dev *pdev =3D dh_dev->pdev; + int ret; + + ret =3D zxdh_pf_common_cfg_init(dh_dev); + if (ret) { + dev_err(dh_dev->device, "zxdh_pf_common_cfg_init failed: %d\n", ret); + return -EINVAL; + } + + ret =3D zxdh_pf_notify_cfg_init(dh_dev); + if (ret) { + dev_err(dh_dev->device, "zxdh_pf_notify_cfg_init failed: %d\n", ret); + goto err_map_notify; + } + + ret =3D zxdh_pf_device_cfg_init(dh_dev); + if (ret) { + dev_err(dh_dev->device, "zxdh_pf_device_cfg_init failed: %d\n", ret); + goto err_map_device; + } + + return 0; + +err_map_device: + if (pf_dev->notify_base) + pci_iounmap(pdev, pf_dev->notify_base); +err_map_notify: + pci_iounmap(pdev, pf_dev->common); + return -EINVAL; +} + +u16 zxdh_pf_get_queue_notify_off(struct dh_core_dev *dh_dev, + u16 phy_index, u16 index) +{ + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + + if (pf_dev->packed_status) + iowrite16(phy_index, &pf_dev->common->queue_select); + else + iowrite16(index, &pf_dev->common->queue_select); + + return ioread16(&pf_dev->common->queue_notify_off); +} + +void __iomem *zxdh_pf_map_vq_notify(struct dh_core_dev *dh_dev, + u16 phy_index, u16 index, + resource_size_t *pa) +{ + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + u16 off; + + off =3D zxdh_pf_get_queue_notify_off(dh_dev, phy_index, index); + + if (pf_dev->notify_base) { + /* offset should not wrap */ + if ((u64)off * + pf_dev->notify_offset_multiplier + 2 > pf_dev->notify_len) { + dev_err(dh_dev->device, + "bad notification offset %u (x %u) for queue %u > %zd", + off, pf_dev->notify_offset_multiplier, phy_index, + pf_dev->notify_len); + return NULL; + } + + if (pa) + *pa =3D pf_dev->notify_pa + off * pf_dev->notify_offset_multiplier; + + return pf_dev->notify_base + off * pf_dev->notify_offset_multiplier; + } else { + return zxdh_pf_map_capability(dh_dev, pf_dev->notify_map_cap, 2, 2, + off * pf_dev->notify_offset_multiplier, + 2, NULL, pa, NULL); + } +} + +void zxdh_pf_unmap_vq_notify(struct dh_core_dev *dh_dev, void __iomem *pri= v) +{ + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + + if (!pf_dev->notify_base) + pci_iounmap(dh_dev->pdev, priv); +} + +void zxdh_pf_set_status(struct dh_core_dev *dh_dev, u8 status) +{ + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + + iowrite8(status, &pf_dev->common->device_status); +} + +u8 zxdh_pf_get_status(struct dh_core_dev *dh_dev) +{ + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + + return ioread8(&pf_dev->common->device_status); +} + +u8 zxdh_pf_get_cfg_gen(struct dh_core_dev *dh_dev) +{ + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + u8 config_generation; + + config_generation =3D ioread8(&pf_dev->common->config_generation); + dev_info(dh_dev->device, "config_generation is %d\n", config_generation); + + return config_generation; +} + +void zxdh_pf_get_vf_mac(struct dh_core_dev *dh_dev, u8 *mac, int vf_id) +{ + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + u32 DEV_MAC_L; + u16 DEV_MAC_H; + + if (pf_dev->pf_sriov_cap_base) { + DEV_MAC_L =3D ioread32(pf_dev->pf_sriov_cap_base + + (pf_dev->sriov_bar_size) * vf_id + + pf_dev->dev_cfg_bar_off); + mac[0] =3D DEV_MAC_L & 0xff; + mac[1] =3D (DEV_MAC_L >> 8) & 0xff; + mac[2] =3D (DEV_MAC_L >> 16) & 0xff; + mac[3] =3D (DEV_MAC_L >> 24) & 0xff; + DEV_MAC_H =3D ioread16(pf_dev->pf_sriov_cap_base + + (pf_dev->sriov_bar_size) * vf_id + + pf_dev->dev_cfg_bar_off + + ZXDH_DEV_MAC_HIGH_OFFSET); + mac[4] =3D DEV_MAC_H & 0xff; + mac[5] =3D (DEV_MAC_H >> 8) & 0xff; + } +} + +void zxdh_pf_set_vf_mac_reg(struct zxdh_pf_device *pf_dev, + u8 *mac, int vf_id) +{ + u32 DEV_MAC_L; + u16 DEV_MAC_H; + + if (pf_dev->pf_sriov_cap_base) { + DEV_MAC_L =3D mac[0] | (mac[1] << 8) | + (mac[2] << 16) | (mac[3] << 24); + DEV_MAC_H =3D mac[4] | (mac[5] << 8); + iowrite32(DEV_MAC_L, (pf_dev->pf_sriov_cap_base + + (pf_dev->sriov_bar_size) * vf_id + + pf_dev->dev_cfg_bar_off)); + iowrite16(DEV_MAC_H, (pf_dev->pf_sriov_cap_base + + (pf_dev->sriov_bar_size) * vf_id + + pf_dev->dev_cfg_bar_off + + ZXDH_DEV_MAC_HIGH_OFFSET)); + } +} + +void zxdh_pf_set_vf_mac(struct dh_core_dev *dh_dev, u8 *mac, int vf_id) +{ + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + + zxdh_pf_set_vf_mac_reg(pf_dev, mac, vf_id); +} + +void zxdh_set_mac(struct dh_core_dev *dh_dev, u8 *mac) +{ + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + u32 DEV_MAC_L; + u16 DEV_MAC_H; + + DEV_MAC_L =3D mac[0] | (mac[1] << 8) | (mac[2] << 16) | (mac[3] << 24); + DEV_MAC_H =3D mac[4] | (mac[5] << 8); + iowrite32(DEV_MAC_L, pf_dev->device); + iowrite16(DEV_MAC_H, pf_dev->device + ZXDH_DEV_MAC_HIGH_OFFSET); +} + +void zxdh_get_mac(struct dh_core_dev *dh_dev, u8 *mac) +{ + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + u32 DEV_MAC_L; + u16 DEV_MAC_H; + + DEV_MAC_L =3D ioread32(pf_dev->device); + mac[0] =3D DEV_MAC_L & 0xff; + mac[1] =3D (DEV_MAC_L >> 8) & 0xff; + mac[2] =3D (DEV_MAC_L >> 16) & 0xff; + mac[3] =3D (DEV_MAC_L >> 24) & 0xff; + DEV_MAC_H =3D ioread16(pf_dev->device + ZXDH_DEV_MAC_HIGH_OFFSET); + mac[4] =3D DEV_MAC_H & 0xff; + mac[5] =3D (DEV_MAC_H >> 8) & 0xff; +} + +u64 zxdh_pf_get_features(struct dh_core_dev *dh_dev) +{ + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + u64 device_feature; + + iowrite32(0, &pf_dev->common->device_feature_select); + device_feature =3D ioread32(&pf_dev->common->device_feature); + iowrite32(1, &pf_dev->common->device_feature_select); + device_feature |=3D ((u64)ioread32(&pf_dev->common->device_feature) + << 32); + + return device_feature; +} + +void zxdh_pf_set_features(struct dh_core_dev *dh_dev, u64 features) +{ + struct zxdh_pf_device *pf_dev =3D dh_dev->priv; + + iowrite32(0, &pf_dev->common->guest_feature_select); + iowrite32((u32)features, &pf_dev->common->guest_feature); + iowrite32(1, &pf_dev->common->guest_feature_select); + iowrite32(features >> 32, &pf_dev->common->guest_feature); +} + static int dh_pf_probe(struct pci_dev *pdev, const struct pci_device_id *i= d) { struct zxdh_pf_device *pf_dev; diff --git a/drivers/net/ethernet/zte/dinghai/en_pf.h b/drivers/net/etherne= t/zte/dinghai/en_pf.h index de46e8b275ca..110d32d52728 100644 --- a/drivers/net/ethernet/zte/dinghai/en_pf.h +++ b/drivers/net/ethernet/zte/dinghai/en_pf.h @@ -17,6 +17,24 @@ #define ZXDH_PF_DEVICE_ID 0x8040 #define ZXDH_VF_DEVICE_ID 0x8041 +/* Common configuration */ +#define ZXDH_PCI_CAP_COMMON_CFG 1 +/* Notifications */ +#define ZXDH_PCI_CAP_NOTIFY_CFG 2 +/* ISR access */ +#define ZXDH_PCI_CAP_ISR_CFG 3 +/* Device specific configuration */ +#define ZXDH_PCI_CAP_DEVICE_CFG 4 +/* PCI configuration access */ +#define ZXDH_PCI_CAP_PCI_CFG 5 + +#define ZXDH_PF_MAX_BAR_VAL 0x5 +#define ZXDH_PF_ALIGN4 4 +#define ZXDH_PF_ALIGN2 2 +#define ZXDH_PF_MAP_MINLEN2 2 + +#define ZXDH_DEV_MAC_HIGH_OFFSET 4 + enum dh_coredev_type { DH_COREDEV_PF, DH_COREDEV_VF, @@ -36,7 +54,26 @@ struct dh_core_dev { }; struct zxdh_pf_device { + struct zxdh_pf_pci_common_cfg __iomem *common; + /* Device-specific data (non-legacy mode) */ + /* Base of vq notifications (non-legacy mode). */ + void __iomem *device; + void __iomem *notify_base; + void __iomem *pf_sriov_cap_base; + /* Physical base of vq notifications */ + resource_size_t notify_pa; + /* So we can sanity-check accesses. */ + size_t notify_len; + size_t device_len; + /* Capability for when we need to map notifications per-vq. */ + s32 notify_map_cap; + u32 notify_offset_multiplier; + /* Multiply queue_notify_off by this value. (non-legacy mode). */ + s32 modern_bars; void __iomem *pci_ioremap_addr[6]; + u64 sriov_bar_size; + u32 dev_cfg_bar_off; + bool packed_status; bool bar_chan_valid; bool vepa; struct mutex irq_lock; /* Protects IRQ operations */ @@ -62,5 +99,34 @@ static inline void dh_core_free_priv(struct dh_core_dev = *dh_dev) ((pdev)->device =3D=3D ZXDH_VF_DEVICE_ID ? DH_COREDEV_VF : DH_COREDEV_PF) void dh_pf_pci_close(struct dh_core_dev *dev); +int zxdh_pf_pci_find_capability(struct pci_dev *pdev, u8 cfg_type, + u32 ioresource_types, int *bars); +void __iomem *zxdh_pf_map_capability(struct dh_core_dev *dh_dev, int off, + size_t minlen, u32 align, + u32 start, u32 size, + size_t *len, resource_size_t *pa, + u32 *bar_off); +int zxdh_pf_common_cfg_init(struct dh_core_dev *dh_dev); +int zxdh_pf_notify_cfg_init(struct dh_core_dev *dh_dev); +int zxdh_pf_device_cfg_init(struct dh_core_dev *dh_dev); +void zxdh_pf_modern_cfg_uninit(struct dh_core_dev *dh_dev); +int zxdh_pf_modern_cfg_init(struct dh_core_dev *dh_dev); +u16 zxdh_pf_get_queue_notify_off(struct dh_core_dev *dh_dev, + u16 phy_index, u16 index); +void __iomem *zxdh_pf_map_vq_notify(struct dh_core_dev *dh_dev, + u16 phy_index, u16 index, + resource_size_t *pa); +void zxdh_pf_unmap_vq_notify(struct dh_core_dev *dh_dev, void __iomem *pri= v); +void zxdh_pf_set_status(struct dh_core_dev *dh_dev, u8 status); +u8 zxdh_pf_get_status(struct dh_core_dev *dh_dev); +u8 zxdh_pf_get_cfg_gen(struct dh_core_dev *dh_dev); +void zxdh_pf_get_vf_mac(struct dh_core_dev *dh_dev, u8 *mac, int vf_id); +void zxdh_pf_set_vf_mac_reg(struct zxdh_pf_device *pf_dev, + u8 *mac, int vf_id); +void zxdh_pf_set_vf_mac(struct dh_core_dev *dh_dev, u8 *mac, int vf_id); +void zxdh_set_mac(struct dh_core_dev *dh_dev, u8 *mac); +void zxdh_get_mac(struct dh_core_dev *dh_dev, u8 *mac); +u64 zxdh_pf_get_features(struct dh_core_dev *dh_dev); +void zxdh_pf_set_features(struct dh_core_dev *dh_dev, u64 features); #endif /* __ZXDH_EN_PF_H__ */ --=20 2.27.0