]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bng_en: Add PCI interface
authorVikas Gupta <vikas.gupta@broadcom.com>
Tue, 1 Jul 2025 14:34:59 +0000 (14:34 +0000)
committerJakub Kicinski <kuba@kernel.org>
Tue, 8 Jul 2025 01:54:00 +0000 (18:54 -0700)
Add basic pci interface to the driver which supports
the BCM5770X NIC family.

Signed-off-by: Vikas Gupta <vikas.gupta@broadcom.com>
Reviewed-by: Bhargava Chenna Marreddy <bhargava.marreddy@broadcom.com>
Reviewed-by: Rajashekar Hudumula <rajashekar.hudumula@broadcom.com>
Link: https://patch.msgid.link/20250701143511.280702-2-vikas.gupta@broadcom.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
MAINTAINERS
drivers/net/ethernet/broadcom/Kconfig
drivers/net/ethernet/broadcom/Makefile
drivers/net/ethernet/broadcom/bnge/Makefile [new file with mode: 0644]
drivers/net/ethernet/broadcom/bnge/bnge.h [new file with mode: 0644]
drivers/net/ethernet/broadcom/bnge/bnge_core.c [new file with mode: 0644]

index 14196433aa871e2a4d5602b5cc30502908ba9b95..d1554f33d0ac5a84283202ea7cc2b63c54bfe0fe 100644 (file)
@@ -4858,6 +4858,12 @@ F:       drivers/firmware/broadcom/tee_bnxt_fw.c
 F:     drivers/net/ethernet/broadcom/bnxt/
 F:     include/linux/firmware/broadcom/tee_bnxt_fw.h
 
+BROADCOM BNG_EN 800 GIGABIT ETHERNET DRIVER
+M:     Vikas Gupta <vikas.gupta@broadcom.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/net/ethernet/broadcom/bnge/
+
 BROADCOM BRCM80211 IEEE802.11 WIRELESS DRIVERS
 M:     Arend van Spriel <arend.vanspriel@broadcom.com>
 L:     linux-wireless@vger.kernel.org
index 81a74e07464f301257ce07bbdb0a5534974cec82..e2c1ac91708e0308550dbad0998a4b807f39a74c 100644 (file)
@@ -253,6 +253,14 @@ config BNXT_HWMON
          Say Y if you want to expose the thermal sensor data on NetXtreme-C/E
          devices, via the hwmon sysfs interface.
 
+config BNGE
+       tristate "Broadcom Ethernet device support"
+       depends on PCI
+       help
+         This driver supports Broadcom 50/100/200/400/800 gigabit Ethernet cards.
+         The module will be called bng_en. To compile this driver as a module,
+         choose M here.
+
 config BCMASP
        tristate "Broadcom ASP 2.0 Ethernet support"
        depends on ARCH_BRCMSTB || COMPILE_TEST
index bac5cb6ad0cd209b6c74f86c102605e4f973ec8a..10cc1c92ecfc68272048a931bbe8449fa1245c4f 100644 (file)
@@ -18,3 +18,4 @@ obj-$(CONFIG_BGMAC_PLATFORM) += bgmac-platform.o
 obj-$(CONFIG_SYSTEMPORT) += bcmsysport.o
 obj-$(CONFIG_BNXT) += bnxt/
 obj-$(CONFIG_BCMASP) += asp2/
+obj-$(CONFIG_BNGE) += bnge/
diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethernet/broadcom/bnge/Makefile
new file mode 100644 (file)
index 0000000..0c3d632
--- /dev/null
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_BNGE) += bng_en.o
+
+bng_en-y := bnge_core.o
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
new file mode 100644 (file)
index 0000000..b49c51b
--- /dev/null
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2025 Broadcom */
+
+#ifndef _BNGE_H_
+#define _BNGE_H_
+
+#define DRV_NAME       "bng_en"
+#define DRV_SUMMARY    "Broadcom 800G Ethernet Linux Driver"
+
+extern char bnge_driver_name[];
+
+enum board_idx {
+       BCM57708,
+};
+
+#endif /* _BNGE_H_ */
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_core.c b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
new file mode 100644 (file)
index 0000000..5146025
--- /dev/null
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2025 Broadcom.
+
+#include <linux/init.h>
+#include <linux/crash_dump.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "bnge.h"
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRV_SUMMARY);
+
+char bnge_driver_name[] = DRV_NAME;
+
+static const struct {
+       char *name;
+} board_info[] = {
+       [BCM57708] = { "Broadcom BCM57708 50Gb/100Gb/200Gb/400Gb/800Gb Ethernet" },
+};
+
+static const struct pci_device_id bnge_pci_tbl[] = {
+       { PCI_VDEVICE(BROADCOM, 0x1780), .driver_data = BCM57708 },
+       /* Required last entry */
+       {0, }
+};
+MODULE_DEVICE_TABLE(pci, bnge_pci_tbl);
+
+static void bnge_print_device_info(struct pci_dev *pdev, enum board_idx idx)
+{
+       struct device *dev = &pdev->dev;
+
+       dev_info(dev, "%s found at mem %lx\n", board_info[idx].name,
+                (long)pci_resource_start(pdev, 0));
+
+       pcie_print_link_status(pdev);
+}
+
+static void bnge_pci_disable(struct pci_dev *pdev)
+{
+       pci_release_regions(pdev);
+       if (pci_is_enabled(pdev))
+               pci_disable_device(pdev);
+}
+
+static int bnge_pci_enable(struct pci_dev *pdev)
+{
+       int rc;
+
+       rc = pci_enable_device(pdev);
+       if (rc) {
+               dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n");
+               return rc;
+       }
+
+       if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+               dev_err(&pdev->dev,
+                       "Cannot find PCI device base address, aborting\n");
+               rc = -ENODEV;
+               goto err_pci_disable;
+       }
+
+       rc = pci_request_regions(pdev, bnge_driver_name);
+       if (rc) {
+               dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting\n");
+               goto err_pci_disable;
+       }
+
+       dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+
+       pci_set_master(pdev);
+
+       return 0;
+
+err_pci_disable:
+       pci_disable_device(pdev);
+       return rc;
+}
+
+static int bnge_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       int rc;
+
+       if (pci_is_bridge(pdev))
+               return -ENODEV;
+
+       if (!pdev->msix_cap) {
+               dev_err(&pdev->dev, "MSIX capability missing, aborting\n");
+               return -ENODEV;
+       }
+
+       if (is_kdump_kernel()) {
+               pci_clear_master(pdev);
+               pcie_flr(pdev);
+       }
+
+       rc = bnge_pci_enable(pdev);
+       if (rc)
+               return rc;
+
+       bnge_print_device_info(pdev, ent->driver_data);
+
+       pci_save_state(pdev);
+
+       return 0;
+}
+
+static void bnge_remove_one(struct pci_dev *pdev)
+{
+       bnge_pci_disable(pdev);
+}
+
+static void bnge_shutdown(struct pci_dev *pdev)
+{
+       pci_disable_device(pdev);
+
+       if (system_state == SYSTEM_POWER_OFF) {
+               pci_wake_from_d3(pdev, 0);
+               pci_set_power_state(pdev, PCI_D3hot);
+       }
+}
+
+static struct pci_driver bnge_driver = {
+       .name           = bnge_driver_name,
+       .id_table       = bnge_pci_tbl,
+       .probe          = bnge_probe_one,
+       .remove         = bnge_remove_one,
+       .shutdown       = bnge_shutdown,
+};
+
+static int __init bnge_init_module(void)
+{
+       return pci_register_driver(&bnge_driver);
+}
+module_init(bnge_init_module);
+
+static void __exit bnge_exit_module(void)
+{
+       pci_unregister_driver(&bnge_driver);
+}
+module_exit(bnge_exit_module);