mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 23:59:33 -04:00
dinghai: add ZTE network driver support
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> Link: https://patch.msgid.link/202608021621043761zZMwCny1e6y0TRFLQHxx@zte.com.cn Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
504ef04e86
commit
b8180f7977
@@ -29869,6 +29869,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
|
||||
|
||||
@@ -189,5 +189,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
|
||||
|
||||
@@ -105,3 +105,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/
|
||||
|
||||
20
drivers/net/ethernet/zte/Kconfig
Normal file
20
drivers/net/ethernet/zte/Kconfig
Normal file
@@ -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
|
||||
6
drivers/net/ethernet/zte/Makefile
Normal file
6
drivers/net/ethernet/zte/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Makefile for the ZTE device drivers
|
||||
#
|
||||
|
||||
obj-$(CONFIG_DINGHAI) += dinghai/
|
||||
34
drivers/net/ethernet/zte/dinghai/Kconfig
Normal file
34
drivers/net/ethernet/zte/dinghai/Kconfig
Normal file
@@ -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 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
|
||||
7
drivers/net/ethernet/zte/dinghai/Makefile
Normal file
7
drivers/net/ethernet/zte/dinghai/Makefile
Normal file
@@ -0,0 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Makefile for ZTE DingHai Ethernet driver
|
||||
#
|
||||
|
||||
obj-$(CONFIG_DINGHAI_PF) += dinghai10e.o
|
||||
dinghai10e-y := en_pf.o
|
||||
174
drivers/net/ethernet/zte/dinghai/en_pf.c
Normal file
174
drivers/net/ethernet/zte/dinghai/en_pf.c
Normal file
@@ -0,0 +1,174 @@
|
||||
// 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 <linux/dma-mapping.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 zxdh_pf_devlink_ops = {};
|
||||
|
||||
static const struct pci_device_id zxdh_pf_pci_table[] = {
|
||||
{ PCI_DEVICE(ZXDH_PF_VENDOR_ID, ZXDH_PF_DEVICE_ID) },
|
||||
{ PCI_DEVICE(ZXDH_PF_VENDOR_ID, ZXDH_VF_DEVICE_ID) },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, zxdh_pf_pci_table);
|
||||
|
||||
void *zxdh_core_alloc_priv(struct zxdh_core_dev *zxdh_dev, size_t size)
|
||||
{
|
||||
void *priv = kzalloc(size, GFP_KERNEL);
|
||||
|
||||
if (priv)
|
||||
zxdh_dev->priv = priv;
|
||||
return priv;
|
||||
}
|
||||
|
||||
void zxdh_core_free_priv(struct zxdh_core_dev *zxdh_dev)
|
||||
{
|
||||
kfree(zxdh_dev->priv);
|
||||
}
|
||||
|
||||
static int zxdh_pf_pci_init(struct zxdh_core_dev *zxdh_dev)
|
||||
{
|
||||
struct zxdh_pf_dev *pf_dev = zxdh_dev->priv;
|
||||
int ret;
|
||||
|
||||
pci_set_drvdata(zxdh_dev->pdev, zxdh_dev);
|
||||
|
||||
ret = pci_enable_device(zxdh_dev->pdev);
|
||||
if (ret) {
|
||||
dev_err(zxdh_dev->device, "pci_enable_device failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dma_set_mask_and_coherent(zxdh_dev->device, DMA_BIT_MASK(64));
|
||||
|
||||
ret = pci_request_selected_regions(zxdh_dev->pdev,
|
||||
pci_select_bars(zxdh_dev->pdev, IORESOURCE_MEM),
|
||||
"dh-pf");
|
||||
if (ret) {
|
||||
dev_err(zxdh_dev->device, "pci_request_selected_regions failed: %d\n", ret);
|
||||
goto err_pci;
|
||||
}
|
||||
|
||||
pci_set_master(zxdh_dev->pdev);
|
||||
ret = pci_save_state(zxdh_dev->pdev);
|
||||
if (ret) {
|
||||
dev_err(zxdh_dev->device, "pci_save_state failed: %d\n", ret);
|
||||
goto err_pci_save_state;
|
||||
}
|
||||
|
||||
if (!(pci_resource_flags(zxdh_dev->pdev, 0) & IORESOURCE_MEM)) {
|
||||
ret = -ENODEV;
|
||||
dev_err(zxdh_dev->device, "BAR 0 is not an MMIO resource\n");
|
||||
goto err_pci_save_state;
|
||||
}
|
||||
|
||||
pf_dev->pci_ioremap_addr[0] =
|
||||
ioremap(pci_resource_start(zxdh_dev->pdev, 0),
|
||||
pci_resource_len(zxdh_dev->pdev, 0));
|
||||
if (!pf_dev->pci_ioremap_addr[0]) {
|
||||
ret = -ENOMEM;
|
||||
dev_err(zxdh_dev->device, "dh pf pci ioremap failed\n");
|
||||
goto err_pci_save_state;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_pci_save_state:
|
||||
pci_release_selected_regions(zxdh_dev->pdev,
|
||||
pci_select_bars(zxdh_dev->pdev, IORESOURCE_MEM));
|
||||
err_pci:
|
||||
pci_disable_device(zxdh_dev->pdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void zxdh_pf_pci_close(struct zxdh_core_dev *zxdh_dev)
|
||||
{
|
||||
struct zxdh_pf_dev *pf_dev = zxdh_dev->priv;
|
||||
|
||||
iounmap(pf_dev->pci_ioremap_addr[0]);
|
||||
pci_release_selected_regions(zxdh_dev->pdev,
|
||||
pci_select_bars(zxdh_dev->pdev, IORESOURCE_MEM));
|
||||
pci_disable_device(zxdh_dev->pdev);
|
||||
}
|
||||
|
||||
static int zxdh_pf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
struct zxdh_core_dev *zxdh_dev;
|
||||
struct zxdh_pf_dev *pf_dev;
|
||||
struct devlink *devlink;
|
||||
int ret;
|
||||
|
||||
devlink = devlink_alloc(&zxdh_pf_devlink_ops, sizeof(struct zxdh_core_dev),
|
||||
&pdev->dev);
|
||||
if (!devlink)
|
||||
return -ENOMEM;
|
||||
|
||||
zxdh_dev = devlink_priv(devlink);
|
||||
zxdh_dev->device = &pdev->dev;
|
||||
zxdh_dev->pdev = pdev;
|
||||
zxdh_dev->devlink = devlink;
|
||||
|
||||
pf_dev = zxdh_core_alloc_priv(zxdh_dev, sizeof(*pf_dev));
|
||||
if (!pf_dev) {
|
||||
dev_err(&pdev->dev, "zxdh_pf_dev alloc failed\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_pf_dev;
|
||||
}
|
||||
|
||||
ret = zxdh_pf_pci_init(zxdh_dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "zxdh_pf_pci_init failed: %d\n", ret);
|
||||
goto err_pci_init;
|
||||
}
|
||||
|
||||
devlink_register(devlink);
|
||||
|
||||
return 0;
|
||||
|
||||
err_pci_init:
|
||||
zxdh_core_free_priv(zxdh_dev);
|
||||
err_pf_dev:
|
||||
devlink_free(devlink);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void zxdh_pf_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct zxdh_core_dev *zxdh_dev = pci_get_drvdata(pdev);
|
||||
struct devlink *devlink = priv_to_devlink(zxdh_dev);
|
||||
|
||||
devlink_unregister(devlink);
|
||||
zxdh_pf_pci_close(zxdh_dev);
|
||||
zxdh_core_free_priv(zxdh_dev);
|
||||
devlink_free(devlink);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
static void zxdh_pf_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
if (system_state == SYSTEM_POWER_OFF)
|
||||
pci_set_power_state(pdev, PCI_D3hot);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
static struct pci_driver zxdh_pf_driver = {
|
||||
.name = "dinghai10e",
|
||||
.id_table = zxdh_pf_pci_table,
|
||||
.probe = zxdh_pf_probe,
|
||||
.remove = zxdh_pf_remove,
|
||||
.shutdown = zxdh_pf_shutdown,
|
||||
};
|
||||
|
||||
module_pci_driver(zxdh_pf_driver);
|
||||
29
drivers/net/ethernet/zte/dinghai/en_pf.h
Normal file
29
drivers/net/ethernet/zte/dinghai/en_pf.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* 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__
|
||||
|
||||
#define ZXDH_PF_VENDOR_ID 0x1cf2
|
||||
#define ZXDH_PF_DEVICE_ID 0x8040
|
||||
#define ZXDH_VF_DEVICE_ID 0x8041
|
||||
|
||||
struct zxdh_core_dev {
|
||||
struct device *device;
|
||||
struct pci_dev *pdev;
|
||||
struct devlink *devlink;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct zxdh_pf_dev {
|
||||
void __iomem *pci_ioremap_addr[6];
|
||||
};
|
||||
|
||||
void *zxdh_core_alloc_priv(struct zxdh_core_dev *zxdh_dev, size_t size);
|
||||
void zxdh_core_free_priv(struct zxdh_core_dev *zxdh_dev);
|
||||
void zxdh_pf_pci_close(struct zxdh_core_dev *zxdh_dev);
|
||||
|
||||
#endif /* __ZXDH_EN_PF_H__ */
|
||||
Reference in New Issue
Block a user