* [PATCH net-next v3 0/3] Add ZTE DingHai Ethernet PF driver
@ 2026-04-30 15:11 Junyang Han
2026-04-30 15:11 ` [PATCH net-next v3 1/3] net/ethernet: add ZTE network driver support Junyang Han
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Junyang Han @ 2026-04-30 15:11 UTC (permalink / raw)
To: andrew+netdev
Cc: netdev, vadim.fedorenko, davem, edumazet, kuba, pabeni,
han.junyang, ran.ming, han.chengfei, zhang.yanze
[-- Attachment #1.1.1: Type: text/plain, Size: 2851 bytes --]
This series adds initial support for the ZTE DingHai Ethernet controller,
a high-performance PCIe Ethernet device supporting SR-IOV, hardware
offloading, and advanced virtualization features.
Changes from v2:
- Address maintainer feedback from v2 review:
* Remove meaningless initialization
* Change dh_pf_pci_table to static const for better encapsulation
* Simplify MODULE_DESCRIPTION for brevity
- Coding style improvements:
* Ensure all lines are within 80-column limit
* Use kernel types (u32/u8) consistently throughout
* Improve code readability with better formatting
Changes from v1 (addressing feedback from AndrewLunn):
- Update copyright years to 2022-2026
- Remove DRV_VERSION, MODULE_VERSION and related boilerplate
- Fix MODULE_AUTHOR to use person with email address
- Use module_pci_driver() instead of manual init/exit
- Remove empty suspend/resume callbacks
- Replace char priv[] flexible array with void *priv + kzalloc
- Switch logging from printk wrappers to dev_*() based macros
- Remove dh_helper.h and dh_log.c, simplify to dh_log.h only
- Fix variable declaration ordering (reverse Christmas tree)
- Remove unnecessary NULL check in remove and pf_dev=NULL in probe
- Fix indentation and remove unnecessary type casts
- Use kernel idiomatic "if (ret)" style
This is the initial submission and only includes the PF (Physical Function)
driver. The VF (Virtual Function) driver will be submitted separately.
Junyang Han (3):
net/ethernet: add ZTE network driver support
net/ethernet/zte/dinghai: add logging infrastructure
net/ethernet/zte/dinghai: add hardware register access and PCI
capability scanning
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/dh_log.h | 64 ++
drivers/net/ethernet/zte/dinghai/dh_queue.h | 71 +++
drivers/net/ethernet/zte/dinghai/en_pf.c | 637 ++++++++++++++++++++
drivers/net/ethernet/zte/dinghai/en_pf.h | 102 ++++
11 files changed, 952 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/dh_log.h
create mode 100644 drivers/net/ethernet/zte/dinghai/dh_queue.h
create mode 100644 drivers/net/ethernet/zte/dinghai/en_pf.c
create mode 100644 drivers/net/ethernet/zte/dinghai/en_pf.h
--
2.27.0
[-- Attachment #1.1.2: Type: text/html , Size: 5150 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH net-next v3 1/3] net/ethernet: add ZTE network driver support
2026-04-30 15:11 [PATCH net-next v3 0/3] Add ZTE DingHai Ethernet PF driver Junyang Han
@ 2026-04-30 15:11 ` Junyang Han
2026-04-30 19:34 ` Andrew Lunn
2026-04-30 15:11 ` [PATCH net-next v3 2/3] net/ethernet/zte/dinghai: add logging infrastructure Junyang Han
2026-04-30 15:11 ` [PATCH net-next v3 3/3] net/ethernet/zte/dinghai: add hardware register access and PCI capability scanning Junyang Han
2 siblings, 1 reply; 6+ messages in thread
From: Junyang Han @ 2026-04-30 15:11 UTC (permalink / raw)
To: andrew+netdev
Cc: netdev, vadim.fedorenko, davem, edumazet, kuba, pabeni,
han.junyang, ran.ming, han.chengfei, zhang.yanze
[-- Attachment #1.1.1: Type: text/plain, Size: 11300 bytes --]
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 <han.junyang@zte.com.cn>
---
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 | 164 ++++++++++++++++++++++
drivers/net/ethernet/zte/dinghai/en_pf.h | 64 +++++++++
9 files changed, 306 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 <han.junyang@zte.com.cn>
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/ethernet/zte/
+
THE REST
M: Linus Torvalds <torvalds@linux-foundation.org>
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) += xircom/
obj-$(CONFIG_NET_VENDOR_SYNOPSYS) += synopsys/
obj-$(CONFIG_NET_VENDOR_PENSANDO) += pensando/
obj-$(CONFIG_OA_TC6) += oa_tc6.o
+obj-$(CONFIG_NET_VENDOR_ZTE) += zte/
diff --git a/drivers/net/ethernet/zte/Kconfig b/drivers/net/ethernet/zte/Kconfig
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/Makefile
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) += dinghai/
diff --git a/drivers/net/ethernet/zte/dinghai/Kconfig b/drivers/net/ethernet/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/ethernet/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 += -I$(src)
+
+obj-$(CONFIG_DINGHAI_PF) += dinghai10e.o
+dinghai10e-y := en_pf.o
+
diff --git a/drivers/net/ethernet/zte/dinghai/en_pf.c b/drivers/net/ethernet/zte/dinghai/en_pf.c
new file mode 100644
index 000000000000..d56bd4ea3259
--- /dev/null
+++ b/drivers/net/ethernet/zte/dinghai/en_pf.c
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * ZTE DingHai Ethernet driver
+ * Copyright (c) 2022-2026, ZTE Corporation.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <net/devlink.h>
+#include "en_pf.h"
+
+MODULE_AUTHOR("Junyang Han <han.junyang@zte.com.cn>");
+MODULE_DESCRIPTION("ZTE DingHai series Ethernet driver");
+MODULE_LICENSE("GPL");
+
+static const struct devlink_ops dh_pf_devlink_ops = {};
+
+static const struct pci_device_id dh_pf_pci_table[] = {
+ { 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 = NULL;
+ int ret;
+
+ pci_set_drvdata(dev->pdev, dev);
+
+ ret = pci_enable_device(dev->pdev);
+ if (ret)
+ return -ENOMEM;
+
+ ret = dma_set_mask_and_coherent(dev->device, DMA_BIT_MASK(64));
+ if (ret) {
+ ret = dma_set_mask_and_coherent(dev->device, DMA_BIT_MASK(32));
+ if (ret)
+ goto err_pci;
+ }
+
+ ret = pci_request_selected_regions(dev->pdev,
+ pci_select_bars(dev->pdev, IORESOURCE_MEM),
+ "dh-pf");
+ if (ret)
+ goto err_pci;
+
+ pci_set_master(dev->pdev);
+ ret = pci_save_state(dev->pdev);
+ if (ret)
+ goto err_pci_save_state;
+
+ pf_dev = dev->priv;
+ pf_dev->pci_ioremap_addr[0] =
+ ioremap(pci_resource_start(dev->pdev, 0),
+ pci_resource_len(dev->pdev, 0));
+ if (!pf_dev->pci_ioremap_addr[0]) {
+ ret = -ENOMEM;
+ 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 = NULL;
+
+ pf_dev = 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 *id)
+{
+ struct dh_core_dev *dh_dev;
+ struct zxdh_pf_device *pf_dev;
+ struct devlink *devlink;
+ int ret;
+
+ devlink = devlink_alloc(&dh_pf_devlink_ops, sizeof(struct dh_core_dev),
+ &pdev->dev);
+ if (!devlink)
+ return -ENOMEM;
+
+ dh_dev = devlink_priv(devlink);
+ dh_dev->device = &pdev->dev;
+ dh_dev->pdev = pdev;
+ dh_dev->devlink = devlink;
+
+ pf_dev = dh_core_alloc_priv(dh_dev, sizeof(*pf_dev));
+ if (!pf_dev)
+ return -ENOMEM;
+
+ pf_dev->bar_chan_valid = false;
+ pf_dev->vepa = false;
+ mutex_init(&dh_dev->lock);
+ mutex_init(&pf_dev->irq_lock);
+
+ dh_dev->coredev_type = GET_COREDEV_TYPE(pdev);
+
+ ret = dh_pf_pci_init(dh_dev);
+ if (ret)
+ goto err_cfg_init;
+
+ return 0;
+
+err_cfg_init:
+ mutex_destroy(&pf_dev->irq_lock);
+ mutex_destroy(&dh_dev->lock);
+ dh_core_free_priv(dh_dev);
+ devlink_free(devlink);
+ return -EPERM;
+}
+
+static void dh_pf_remove(struct pci_dev *pdev)
+{
+ struct dh_core_dev *dh_dev = pci_get_drvdata(pdev);
+ struct devlink *devlink = priv_to_devlink(dh_dev);
+ struct zxdh_pf_device *pf_dev = dh_dev->priv;
+
+ 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);
+}
+
+static void dh_pf_shutdown(struct pci_dev *pdev)
+{
+ struct dh_core_dev *dh_dev = pci_get_drvdata(pdev);
+ struct devlink *devlink = priv_to_devlink(dh_dev);
+ struct zxdh_pf_device *pf_dev = dh_dev->priv;
+
+ 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);
+}
+
+static struct pci_driver dh_pf_driver = {
+ .name = "dinghai10e",
+ .id_table = dh_pf_pci_table,
+ .probe = dh_pf_probe,
+ .remove = dh_pf_remove,
+ .shutdown = dh_pf_shutdown,
+};
+
+module_pci_driver(dh_pf_driver);
diff --git a/drivers/net/ethernet/zte/dinghai/en_pf.h b/drivers/net/ethernet/zte/dinghai/en_pf.h
new file mode 100644
index 000000000000..0c47f3a38a9d
--- /dev/null
+++ b/drivers/net/ethernet/zte/dinghai/en_pf.h
@@ -0,0 +1,64 @@
+/* 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 <linux/types.h>
+#include <linux/pci.h>
+#include <linux/mutex.h>
+
+#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 = kzalloc(size, GFP_KERNEL);
+
+ if (priv)
+ dh_dev->priv = priv;
+ return priv;
+}
+
+static inline void dh_core_free_priv(struct dh_core_dev *dh_dev)
+{
+ kfree(dh_dev->priv);
+ dh_dev->priv = NULL;
+}
+
+#define GET_COREDEV_TYPE(pdev) \
+ ((pdev)->device == ZXDH_VF_DEVICE_ID ? DH_COREDEV_VF : DH_COREDEV_PF)
+
+#endif
+
+void dh_pf_pci_close(struct dh_core_dev *dev);
--
2.27.0
[-- Attachment #1.1.2: Type: text/html , Size: 21753 bytes --]
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net-next v3 2/3] net/ethernet/zte/dinghai: add logging infrastructure
2026-04-30 15:11 [PATCH net-next v3 0/3] Add ZTE DingHai Ethernet PF driver Junyang Han
2026-04-30 15:11 ` [PATCH net-next v3 1/3] net/ethernet: add ZTE network driver support Junyang Han
@ 2026-04-30 15:11 ` Junyang Han
2026-04-30 19:36 ` Andrew Lunn
2026-04-30 15:11 ` [PATCH net-next v3 3/3] net/ethernet/zte/dinghai: add hardware register access and PCI capability scanning Junyang Han
2 siblings, 1 reply; 6+ messages in thread
From: Junyang Han @ 2026-04-30 15:11 UTC (permalink / raw)
To: andrew+netdev
Cc: netdev, vadim.fedorenko, davem, edumazet, kuba, pabeni,
han.junyang, ran.ming, han.chengfei, zhang.yanze
[-- Attachment #1.1.1: Type: text/plain, Size: 7371 bytes --]
Introduce logging macros (DH_LOG_EMERG/ALERT/CRIT/ERR/WARN/INFO/DBG)
and helper definitions for ZTE DingHai driver debugging.
Signed-off-by: Junyang Han <han.junyang@zte.com.cn>
---
drivers/net/ethernet/zte/dinghai/dh_log.h | 64 +++++++++++++++++++++++
drivers/net/ethernet/zte/dinghai/en_pf.c | 49 ++++++++++++++---
2 files changed, 105 insertions(+), 8 deletions(-)
create mode 100644 drivers/net/ethernet/zte/dinghai/dh_log.h
diff --git a/drivers/net/ethernet/zte/dinghai/dh_log.h b/drivers/net/ethernet/zte/dinghai/dh_log.h
new file mode 100644
index 000000000000..ae93596bcaef
--- /dev/null
+++ b/drivers/net/ethernet/zte/dinghai/dh_log.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * ZTE DingHai Ethernet driver - logging infrastructure
+ * Copyright (c) 2022-2026, ZTE Corporation.
+ */
+
+#ifndef __DH_LOG_H__
+#define __DH_LOG_H__
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/printk.h>
+
+#define MODULE_CMD "zxdh_cmd"
+#define MODULE_NP "zxdh_np"
+#define MODULE_PF "zxdh_pf"
+#define MODULE_PTP "zxdh_ptp"
+#define MODULE_TSN "zxdh_tsn"
+#define MODULE_LAG "zxdh_lag"
+#define MODULE_DHTOOLS "zxdh_tool"
+#define MODULE_SEC "zxdh_sec"
+#define MODULE_MPF "zxdh_mpf"
+#define MODULE_FUC_HP "zxdh_func_hp"
+#define MODULE_UACCE "zxdh_uacce"
+#define MODULE_HEAL "zxdh_health"
+
+#define DH_LOG_EMERG(module, __dev, fmt, arg...) \
+ dev_emerg((__dev)->device, "[%s][%s][%d] " fmt, \
+ module, __func__, __LINE__, ##arg)
+
+#define DH_LOG_ALERT(module, __dev, fmt, arg...) \
+ dev_alert((__dev)->device, "[%s][%s][%d] " fmt, \
+ module, __func__, __LINE__, ##arg)
+
+#define DH_LOG_CRIT(module, __dev, fmt, arg...) \
+ dev_crit((__dev)->device, "[%s][%s][%d] " fmt, \
+ module, __func__, __LINE__, ##arg)
+
+#define DH_LOG_ERR(module, __dev, fmt, arg...) \
+ dev_err((__dev)->device, "[%s][%s][%d] " fmt, \
+ module, __func__, __LINE__, ##arg)
+
+#define DH_LOG_WARNING(module, __dev, fmt, arg...) \
+ dev_warn((__dev)->device, "[%s][%s][%d] " fmt, \
+ module, __func__, __LINE__, ##arg)
+
+#define DH_LOG_INFO(module, __dev, fmt, arg...) \
+ dev_info((__dev)->device, "[%s][%s][%d] " fmt, \
+ module, __func__, __LINE__, ##arg)
+
+#define DH_LOG_DEBUG(module, __dev, fmt, arg...) \
+ dev_dbg((__dev)->device, "[%s][%s][%d] " fmt, \
+ module, __func__, __LINE__, ##arg)
+
+#define LOG_ERR(__dev, fmt, arg...) \
+ DH_LOG_ERR(MODULE_PF, __dev, fmt, ##arg)
+#define LOG_INFO(__dev, fmt, arg...) \
+ DH_LOG_INFO(MODULE_PF, __dev, fmt, ##arg)
+#define LOG_DEBUG(__dev, fmt, arg...) \
+ DH_LOG_DEBUG(MODULE_PF, __dev, fmt, ##arg)
+#define LOG_WARN(__dev, fmt, arg...) \
+ DH_LOG_WARNING(MODULE_PF, __dev, fmt, ##arg)
+
+#endif /* __DH_LOG_H__ */
diff --git a/drivers/net/ethernet/zte/dinghai/en_pf.c b/drivers/net/ethernet/zte/dinghai/en_pf.c
index d56bd4ea3259..f4a923b76037 100644
--- a/drivers/net/ethernet/zte/dinghai/en_pf.c
+++ b/drivers/net/ethernet/zte/dinghai/en_pf.c
@@ -8,6 +8,7 @@
#include <linux/pci.h>
#include <net/devlink.h>
#include "en_pf.h"
+#include "dh_log.h"
MODULE_AUTHOR("Junyang Han <han.junyang@zte.com.cn>");
MODULE_DESCRIPTION("ZTE DingHai series Ethernet driver");
@@ -31,26 +32,34 @@ static int dh_pf_pci_init(struct dh_core_dev *dev)
pci_set_drvdata(dev->pdev, dev);
ret = pci_enable_device(dev->pdev);
- if (ret)
+ if (ret) {
+ LOG_ERR(dev, "pci_enable_device failed: %d\n", ret);
return -ENOMEM;
+ }
ret = dma_set_mask_and_coherent(dev->device, DMA_BIT_MASK(64));
if (ret) {
ret = dma_set_mask_and_coherent(dev->device, DMA_BIT_MASK(32));
- if (ret)
+ if (ret) {
+ LOG_ERR(dev, "dma_set_mask_and_coherent failed: %d\n", ret);
goto err_pci;
+ }
}
ret = pci_request_selected_regions(dev->pdev,
pci_select_bars(dev->pdev, IORESOURCE_MEM),
"dh-pf");
- if (ret)
+ if (ret) {
+ LOG_ERR(dev, "pci_request_selected_regions failed: %d\n", ret);
goto err_pci;
+ }
pci_set_master(dev->pdev);
ret = pci_save_state(dev->pdev);
- if (ret)
+ if (ret) {
+ LOG_ERR(dev, "pci_save_state failed: %d\n", ret);
goto err_pci_save_state;
+ }
pf_dev = dev->priv;
pf_dev->pci_ioremap_addr[0] =
@@ -58,6 +67,9 @@ static int dh_pf_pci_init(struct dh_core_dev *dev)
pci_resource_len(dev->pdev, 0));
if (!pf_dev->pci_ioremap_addr[0]) {
ret = -ENOMEM;
+ LOG_ERR(dev, "ioremap(0x%llx, 0x%llx) failed\n",
+ pci_resource_start(dev->pdev, 0),
+ pci_resource_len(dev->pdev, 0));
goto err_pci_save_state;
}
@@ -89,10 +101,13 @@ static int dh_pf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct devlink *devlink;
int ret;
+ dev_info(&pdev->dev, "pf level start\n");
devlink = devlink_alloc(&dh_pf_devlink_ops, sizeof(struct dh_core_dev),
&pdev->dev);
- if (!devlink)
+ if (!devlink) {
+ dev_err(&pdev->dev, "devlink alloc failed\n");
return -ENOMEM;
+ }
dh_dev = devlink_priv(devlink);
dh_dev->device = &pdev->dev;
@@ -100,8 +115,10 @@ static int dh_pf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dh_dev->devlink = devlink;
pf_dev = dh_core_alloc_priv(dh_dev, sizeof(*pf_dev));
- if (!pf_dev)
- return -ENOMEM;
+ if (!pf_dev) {
+ LOG_ERR(dh_dev, "zxdh_pf_dev alloc failed\n");
+ goto err_pf_dev;
+ }
pf_dev->bar_chan_valid = false;
pf_dev->vepa = false;
@@ -109,10 +126,17 @@ static int dh_pf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mutex_init(&pf_dev->irq_lock);
dh_dev->coredev_type = GET_COREDEV_TYPE(pdev);
+ LOG_DEBUG(dh_dev, "%s device: %s\n",
+ (dh_dev->coredev_type == DH_COREDEV_PF) ? "PF" : "VF",
+ pci_name(pdev));
ret = dh_pf_pci_init(dh_dev);
- if (ret)
+ if (ret) {
+ LOG_ERR(dh_dev, "dh_pf_pci_init failed: %d\n", ret);
goto err_cfg_init;
+ }
+
+ LOG_INFO(dh_dev, "pf level completed\n");
return 0;
@@ -120,6 +144,7 @@ static int dh_pf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mutex_destroy(&pf_dev->irq_lock);
mutex_destroy(&dh_dev->lock);
dh_core_free_priv(dh_dev);
+err_pf_dev:
devlink_free(devlink);
return -EPERM;
}
@@ -130,12 +155,16 @@ static void dh_pf_remove(struct pci_dev *pdev)
struct devlink *devlink = priv_to_devlink(dh_dev);
struct zxdh_pf_device *pf_dev = dh_dev->priv;
+ LOG_INFO(dh_dev, "pf level 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);
+
+ LOG_INFO(dh_dev, "pf level completed\n");
}
static void dh_pf_shutdown(struct pci_dev *pdev)
@@ -144,6 +173,8 @@ static void dh_pf_shutdown(struct pci_dev *pdev)
struct devlink *devlink = priv_to_devlink(dh_dev);
struct zxdh_pf_device *pf_dev = dh_dev->priv;
+ LOG_INFO(dh_dev, "pf level start\n");
+
dh_pf_pci_close(dh_dev);
mutex_destroy(&pf_dev->irq_lock);
mutex_destroy(&dh_dev->lock);
@@ -151,6 +182,8 @@ static void dh_pf_shutdown(struct pci_dev *pdev)
devlink_free(devlink);
pci_set_drvdata(pdev, NULL);
+
+ LOG_INFO(dh_dev, "pf level completed\n");
}
static struct pci_driver dh_pf_driver = {
--
2.27.0
[-- Attachment #1.1.2: Type: text/html , Size: 17344 bytes --]
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net-next v3 3/3] net/ethernet/zte/dinghai: add hardware register access and PCI capability scanning
2026-04-30 15:11 [PATCH net-next v3 0/3] Add ZTE DingHai Ethernet PF driver Junyang Han
2026-04-30 15:11 ` [PATCH net-next v3 1/3] net/ethernet: add ZTE network driver support Junyang Han
2026-04-30 15:11 ` [PATCH net-next v3 2/3] net/ethernet/zte/dinghai: add logging infrastructure Junyang Han
@ 2026-04-30 15:11 ` Junyang Han
2 siblings, 0 replies; 6+ messages in thread
From: Junyang Han @ 2026-04-30 15:11 UTC (permalink / raw)
To: andrew+netdev
Cc: netdev, vadim.fedorenko, davem, edumazet, kuba, pabeni,
han.junyang, ran.ming, han.chengfei, zhang.yanze
[-- Attachment #1.1.1: Type: text/plain, Size: 19448 bytes --]
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 <han.junyang@zte.com.cn>
---
drivers/net/ethernet/zte/dinghai/dh_queue.h | 71 ++++
drivers/net/ethernet/zte/dinghai/en_pf.c | 446 +++++++++++++++++++-
drivers/net/ethernet/zte/dinghai/en_pf.h | 38 ++
3 files changed, 552 insertions(+), 3 deletions(-)
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/ethernet/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/ethernet/zte/dinghai/en_pf.c
index f4a923b76037..211893b2f8e3 100644
--- a/drivers/net/ethernet/zte/dinghai/en_pf.c
+++ b/drivers/net/ethernet/zte/dinghai/en_pf.c
@@ -9,6 +9,7 @@
#include <net/devlink.h>
#include "en_pf.h"
#include "dh_log.h"
+#include "dh_queue.h"
MODULE_AUTHOR("Junyang Han <han.junyang@zte.com.cn>");
MODULE_DESCRIPTION("ZTE DingHai series Ethernet driver");
@@ -64,7 +65,7 @@ static int dh_pf_pci_init(struct dh_core_dev *dev)
pf_dev = dev->priv;
pf_dev->pci_ioremap_addr[0] =
ioremap(pci_resource_start(dev->pdev, 0),
- pci_resource_len(dev->pdev, 0));
+ pci_resource_len(dev->pdev, 0));
if (!pf_dev->pci_ioremap_addr[0]) {
ret = -ENOMEM;
LOG_ERR(dev, "ioremap(0x%llx, 0x%llx) failed\n",
@@ -77,7 +78,7 @@ static int dh_pf_pci_init(struct dh_core_dev *dev)
err_pci_save_state:
pci_release_selected_regions(dev->pdev,
- pci_select_bars(dev->pdev, IORESOURCE_MEM));
+ pci_select_bars(dev->pdev, IORESOURCE_MEM));
err_pci:
pci_disable_device(dev->pdev);
return ret;
@@ -90,10 +91,449 @@ void dh_pf_pci_close(struct dh_core_dev *dev)
pf_dev = dev->priv;
iounmap(pf_dev->pci_ioremap_addr[0]);
pci_release_selected_regions(dev->pdev,
- pci_select_bars(dev->pdev, IORESOURCE_MEM));
+ pci_select_bars(dev->pdev, IORESOURCE_MEM));
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 = pci_find_capability(pdev, PCI_CAP_ID_VNDR); pos > 0;
+ pos = 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 == cfg_type) {
+ if (pci_resource_len(pdev, bar) &&
+ pci_resource_flags(pdev, bar) & ioresource_types) {
+ *bars |= (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 = 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 = offset;
+
+ if (length <= start) {
+ LOG_ERR(dh_dev, "bad capability len %u (>%u expected)\n",
+ length, start);
+ return NULL;
+ }
+
+ if (length - start < minlen) {
+ LOG_ERR(dh_dev, "bad capability len %u (>=%zu expected)\n",
+ length, minlen);
+ return NULL;
+ }
+
+ length -= start;
+ if (start + offset < offset) {
+ LOG_ERR(dh_dev, "map wrap-around %u+%u\n", start, offset);
+ return NULL;
+ }
+
+ offset += start;
+ if (offset & (align - 1)) {
+ LOG_ERR(dh_dev, "offset %u not aligned to %u\n", offset, align);
+ return NULL;
+ }
+
+ if (length > size)
+ length = size;
+
+ if (len)
+ *len = length;
+
+ if (minlen + offset < minlen ||
+ minlen + offset > pci_resource_len(pdev, bar)) {
+ LOG_ERR(dh_dev,
+ "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 = pci_iomap_range(pdev, bar, offset, length);
+ if (!p) {
+ LOG_ERR(dh_dev, "unable to map custom queue %u@%u on bar %i\n",
+ length, offset, bar);
+ } else if (pa) {
+ *pa = 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 = dh_core_priv(dh_dev);
+ struct pci_dev *pdev = dh_dev->pdev;
+ int common;
+
+ /* check for a common config: if not, use legacy mode (bar 0). */
+ common = zxdh_pf_pci_find_capability(pdev, ZXDH_PCI_CAP_COMMON_CFG,
+ IORESOURCE_IO | IORESOURCE_MEM,
+ &pf_dev->modern_bars);
+ if (common == 0) {
+ LOG_ERR(dh_dev,
+ "missing capabilities %i, leaving for legacy driver\n",
+ common);
+ return -ENODEV;
+ }
+
+ pf_dev->common = 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) {
+ LOG_ERR(dh_dev, "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 = dh_core_priv(dh_dev);
+ struct pci_dev *pdev = dh_dev->pdev;
+ size_t notify_length;
+ size_t notify_offset;
+ int notify;
+
+ /* If common is there, these should be too... */
+ notify = zxdh_pf_pci_find_capability(pdev, ZXDH_PCI_CAP_NOTIFY_CFG,
+ IORESOURCE_IO | IORESOURCE_MEM,
+ &pf_dev->modern_bars);
+ if (notify == 0) {
+ LOG_ERR(dh_dev, "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) <= PAGE_SIZE) {
+ pf_dev->notify_base = 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) {
+ LOG_ERR(dh_dev, "pf_dev->notify_base is null\n");
+ return -EINVAL;
+ }
+ } else {
+ pf_dev->notify_map_cap = notify;
+ }
+
+ return 0;
+}
+
+int zxdh_pf_device_cfg_init(struct dh_core_dev *dh_dev)
+{
+ struct zxdh_pf_device *pf_dev = dh_core_priv(dh_dev);
+ struct pci_dev *pdev = dh_dev->pdev;
+ int device;
+
+ /* Device capability is only mandatory for
+ * devices that have device-specific configuration.
+ */
+ device = 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 = 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) {
+ LOG_ERR(dh_dev, "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 = dh_core_priv(dh_dev);
+ struct pci_dev *pdev = 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 = dh_core_priv(dh_dev);
+ struct pci_dev *pdev = dh_dev->pdev;
+ int ret;
+
+ ret = zxdh_pf_common_cfg_init(dh_dev);
+ if (ret) {
+ LOG_ERR(dh_dev, "zxdh_pf_common_cfg_init failed: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = zxdh_pf_notify_cfg_init(dh_dev);
+ if (ret) {
+ LOG_ERR(dh_dev, "zxdh_pf_notify_cfg_init failed: %d\n", ret);
+ goto err_map_notify;
+ }
+
+ ret = zxdh_pf_device_cfg_init(dh_dev);
+ if (ret) {
+ LOG_ERR(dh_dev, "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 = dh_core_priv(dh_dev);
+
+ 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 = dh_core_priv(dh_dev);
+ u16 off;
+
+ off = 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) {
+ LOG_ERR(dh_dev,
+ "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 = 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 *priv)
+{
+ struct zxdh_pf_device *pf_dev = dh_core_priv(dh_dev);
+
+ 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 = dh_core_priv(dh_dev);
+
+ iowrite8(status, &pf_dev->common->device_status);
+}
+
+u8 zxdh_pf_get_status(struct dh_core_dev *dh_dev)
+{
+ struct zxdh_pf_device *pf_dev = dh_core_priv(dh_dev);
+
+ return ioread8(&pf_dev->common->device_status);
+}
+
+static u8 zxdh_pf_get_cfg_gen(struct dh_core_dev *dh_dev)
+{
+ struct zxdh_pf_device *pf_dev = dh_core_priv(dh_dev);
+ u8 config_generation;
+
+ config_generation = ioread8(&pf_dev->common->config_generation);
+ LOG_INFO(dh_dev, "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 = dh_core_priv(dh_dev);
+ u32 DEV_MAC_L;
+ u16 DEV_MAC_H;
+
+ if (pf_dev->pf_sriov_cap_base) {
+ DEV_MAC_L = ioread32(pf_dev->pf_sriov_cap_base +
+ (pf_dev->sriov_bar_size) * vf_id +
+ pf_dev->dev_cfg_bar_off);
+ mac[0] = DEV_MAC_L & 0xff;
+ mac[1] = (DEV_MAC_L >> 8) & 0xff;
+ mac[2] = (DEV_MAC_L >> 16) & 0xff;
+ mac[3] = (DEV_MAC_L >> 24) & 0xff;
+ DEV_MAC_H = 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] = DEV_MAC_H & 0xff;
+ mac[5] = (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 = mac[0] | (mac[1] << 8) |
+ (mac[2] << 16) | (mac[3] << 24);
+ DEV_MAC_H = 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 = dh_core_priv(dh_dev);
+
+ 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 = dh_core_priv(dh_dev);
+ u32 DEV_MAC_L;
+ u16 DEV_MAC_H;
+
+ DEV_MAC_L = mac[0] | (mac[1] << 8) | (mac[2] << 16) | (mac[3] << 24);
+ DEV_MAC_H = 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 = dh_core_priv(dh_dev);
+ u32 DEV_MAC_L;
+ u16 DEV_MAC_H;
+
+ DEV_MAC_L = ioread32(pf_dev->device);
+ mac[0] = DEV_MAC_L & 0xff;
+ mac[1] = (DEV_MAC_L >> 8) & 0xff;
+ mac[2] = (DEV_MAC_L >> 16) & 0xff;
+ mac[3] = (DEV_MAC_L >> 24) & 0xff;
+ DEV_MAC_H = ioread16(pf_dev->device + ZXDH_DEV_MAC_HIGH_OFFSET);
+ mac[4] = DEV_MAC_H & 0xff;
+ mac[5] = (DEV_MAC_H >> 8) & 0xff;
+}
+
+u64 zxdh_pf_get_features(struct dh_core_dev *dh_dev)
+{
+ struct zxdh_pf_device *pf_dev = dh_core_priv(dh_dev);
+ u64 device_feature;
+
+ iowrite32(0, &pf_dev->common->device_feature_select);
+ device_feature = ioread32(&pf_dev->common->device_feature);
+ iowrite32(1, &pf_dev->common->device_feature_select);
+ device_feature |= ((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 = dh_core_priv(dh_dev);
+
+ 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 *id)
{
struct dh_core_dev *dh_dev;
diff --git a/drivers/net/ethernet/zte/dinghai/en_pf.h b/drivers/net/ethernet/zte/dinghai/en_pf.h
index 0c47f3a38a9d..33e3c957e3a3 100644
--- a/drivers/net/ethernet/zte/dinghai/en_pf.h
+++ b/drivers/net/ethernet/zte/dinghai/en_pf.h
@@ -15,6 +15,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,
@@ -34,7 +52,27 @@ 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 */
--
2.27.0
[-- Attachment #1.1.2: Type: text/html , Size: 49437 bytes --]
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH net-next v3 1/3] net/ethernet: add ZTE network driver support
2026-04-30 15:11 ` [PATCH net-next v3 1/3] net/ethernet: add ZTE network driver support Junyang Han
@ 2026-04-30 19:34 ` Andrew Lunn
0 siblings, 0 replies; 6+ messages in thread
From: Andrew Lunn @ 2026-04-30 19:34 UTC (permalink / raw)
To: Junyang Han
Cc: andrew+netdev, netdev, vadim.fedorenko, davem, edumazet, kuba,
pabeni, ran.ming, han.chengfei, zhang.yanze
> + struct zxdh_pf_device *pf_dev = NULL;
Please don't initialise variables, unless they actual do need
initialising. It mask used before set warnings the compiler will
issue.
> +void dh_pf_pci_close(struct dh_core_dev *dev)
> +{
> + struct zxdh_pf_device *pf_dev = NULL;
Looks like you can just set it so dev->priv.
> +static int dh_pf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> +{
> + struct dh_core_dev *dh_dev;
> + struct zxdh_pf_device *pf_dev;
Reverse Christmas tree.
> + struct devlink *devlink;
> + int ret;
> +
> + devlink = devlink_alloc(&dh_pf_devlink_ops, sizeof(struct dh_core_dev),
> + &pdev->dev);
Wrong indentation. In fact, this seems to have spaces not tabs. What
does checkpatch say about these files? Or is you email still broken?
No point reviewing further if the basic are wrong.
Andrew
---
pw-bot: cr
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net-next v3 2/3] net/ethernet/zte/dinghai: add logging infrastructure
2026-04-30 15:11 ` [PATCH net-next v3 2/3] net/ethernet/zte/dinghai: add logging infrastructure Junyang Han
@ 2026-04-30 19:36 ` Andrew Lunn
0 siblings, 0 replies; 6+ messages in thread
From: Andrew Lunn @ 2026-04-30 19:36 UTC (permalink / raw)
To: Junyang Han
Cc: andrew+netdev, netdev, vadim.fedorenko, davem, edumazet, kuba,
pabeni, ran.ming, han.chengfei, zhang.yanze
> ret = pci_enable_device(dev->pdev);
> - if (ret)
> + if (ret) {
> + LOG_ERR(dev, "pci_enable_device failed: %d\n", ret);
I asked that your use dev_err().
Andrew
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-04-30 19:36 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-30 15:11 [PATCH net-next v3 0/3] Add ZTE DingHai Ethernet PF driver Junyang Han
2026-04-30 15:11 ` [PATCH net-next v3 1/3] net/ethernet: add ZTE network driver support Junyang Han
2026-04-30 19:34 ` Andrew Lunn
2026-04-30 15:11 ` [PATCH net-next v3 2/3] net/ethernet/zte/dinghai: add logging infrastructure Junyang Han
2026-04-30 19:36 ` Andrew Lunn
2026-04-30 15:11 ` [PATCH net-next v3 3/3] net/ethernet/zte/dinghai: add hardware register access and PCI capability scanning Junyang Han
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox