netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [net-next, 00/10] Introducing Broadcom BNGE Ethernet Driver
@ 2025-06-18 14:47 Vikas Gupta
  2025-06-18 14:47 ` [net-next, 01/10] bng_en: Add PCI interface Vikas Gupta
                   ` (9 more replies)
  0 siblings, 10 replies; 37+ messages in thread
From: Vikas Gupta @ 2025-06-18 14:47 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta

Hi,

This patch series introduces the Ethernet driver for Broadcom’s
BCM5770X chip family, which supports 50/100/200/400/800 Gbps
link speeds. The driver is built as the bng_en.ko kernel module.

To keep the series within a reviewable size (~5K lines of code), this initial
submission focuses on the core infrastructure and initialization, including:
1) PCIe support (device IDs, probe/remove)
2) Devlink support
3) Firmware communication mechanism
4) Creation of network device
5) PF Resource management (rings, IRQs, etc. for netdev & aux dev)

Support for Tx/Rx datapaths, link management, ethtool/devlink operations and
additional features will be introduced in the subsequent patch series.

The bng_en driver shares the bnxt_hsi.h file with the bnxt_en driver, as the bng_en
driver leverages the hardware communication protocol used by the bnxt_en driver.

Thanks,
Vikas


Vikas Gupta (10):
  bng_en: Add PCI interface
  bng_en: Add devlink interface
  bng_en: Add firmware communication mechanism
  bng_en: Add initial interaction with firmware
  bng_en: Add ring memory allocation support
  bng_en: Add backing store support
  bng_en: Add resource management support
  bng_en: Add irq allocation support
  bng_en: Initialize default configuration
  bng_en: Add a network device

 MAINTAINERS                                   |   6 +
 drivers/net/ethernet/broadcom/Kconfig         |   9 +
 drivers/net/ethernet/broadcom/Makefile        |   1 +
 drivers/net/ethernet/broadcom/bnge/Makefile   |  12 +
 drivers/net/ethernet/broadcom/bnge/bnge.h     | 218 ++++++
 .../net/ethernet/broadcom/bnge/bnge_core.c    | 395 ++++++++++
 .../net/ethernet/broadcom/bnge/bnge_devlink.c | 267 +++++++
 .../net/ethernet/broadcom/bnge/bnge_devlink.h |  18 +
 .../net/ethernet/broadcom/bnge/bnge_ethtool.c |  33 +
 .../net/ethernet/broadcom/bnge/bnge_ethtool.h |   9 +
 .../net/ethernet/broadcom/bnge/bnge_hwrm.c    | 503 +++++++++++++
 .../net/ethernet/broadcom/bnge/bnge_hwrm.h    | 117 +++
 .../ethernet/broadcom/bnge/bnge_hwrm_lib.c    | 703 ++++++++++++++++++
 .../ethernet/broadcom/bnge/bnge_hwrm_lib.h    |  27 +
 .../net/ethernet/broadcom/bnge/bnge_netdev.c  | 266 +++++++
 .../net/ethernet/broadcom/bnge/bnge_netdev.h  | 206 +++++
 .../net/ethernet/broadcom/bnge/bnge_resc.c    | 604 +++++++++++++++
 .../net/ethernet/broadcom/bnge/bnge_resc.h    |  94 +++
 .../net/ethernet/broadcom/bnge/bnge_rmem.c    | 438 +++++++++++
 .../net/ethernet/broadcom/bnge/bnge_rmem.h    | 188 +++++
 20 files changed, 4114 insertions(+)
 create mode 100644 drivers/net/ethernet/broadcom/bnge/Makefile
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge.h
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_core.c
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_devlink.h
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_ethtool.h
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm.c
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_netdev.h
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_resc.c
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_resc.h
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_rmem.c
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_rmem.h

-- 
2.47.1


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [net-next, 01/10] bng_en: Add PCI interface
  2025-06-18 14:47 [net-next, 00/10] Introducing Broadcom BNGE Ethernet Driver Vikas Gupta
@ 2025-06-18 14:47 ` Vikas Gupta
  2025-06-19 12:25   ` Vadim Fedorenko
  2025-06-18 14:47 ` [net-next, 02/10] bng_en: Add devlink interface Vikas Gupta
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 37+ messages in thread
From: Vikas Gupta @ 2025-06-18 14:47 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

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>
---
 MAINTAINERS                                   |   6 +
 drivers/net/ethernet/broadcom/Kconfig         |   8 +
 drivers/net/ethernet/broadcom/Makefile        |   1 +
 drivers/net/ethernet/broadcom/bnge/Makefile   |   5 +
 drivers/net/ethernet/broadcom/bnge/bnge.h     |  16 ++
 .../net/ethernet/broadcom/bnge/bnge_core.c    | 149 ++++++++++++++++++
 6 files changed, 185 insertions(+)
 create mode 100644 drivers/net/ethernet/broadcom/bnge/Makefile
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge.h
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_core.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 507c5ff6f620..af349b77a92e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4854,6 +4854,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
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index 81a74e07464f..e2c1ac91708e 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -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
diff --git a/drivers/net/ethernet/broadcom/Makefile b/drivers/net/ethernet/broadcom/Makefile
index bac5cb6ad0cd..10cc1c92ecfc 100644
--- a/drivers/net/ethernet/broadcom/Makefile
+++ b/drivers/net/ethernet/broadcom/Makefile
@@ -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
index 000000000000..0c3d632805d1
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnge/Makefile
@@ -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
index 000000000000..b49c51b44473
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
@@ -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
index 000000000000..3778210da98d
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
@@ -0,0 +1,149 @@
+// 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;
+	}
+
+	if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) != 0 &&
+	    dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)) != 0) {
+		dev_err(&pdev->dev, "System does not support DMA, aborting\n");
+		rc = -EIO;
+		goto err_pci_release;
+	}
+
+	pci_set_master(pdev);
+
+	return 0;
+
+err_pci_release:
+	pci_release_regions(pdev);
+
+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);
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [net-next, 02/10] bng_en: Add devlink interface
  2025-06-18 14:47 [net-next, 00/10] Introducing Broadcom BNGE Ethernet Driver Vikas Gupta
  2025-06-18 14:47 ` [net-next, 01/10] bng_en: Add PCI interface Vikas Gupta
@ 2025-06-18 14:47 ` Vikas Gupta
  2025-06-19 12:34   ` Vadim Fedorenko
  2025-06-18 14:47 ` [net-next, 03/10] bng_en: Add firmware communication mechanism Vikas Gupta
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 37+ messages in thread
From: Vikas Gupta @ 2025-06-18 14:47 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Allocate a base device and devlink interface with minimal
devlink ops.
Add dsn and board related information.
Map PCIe BAR (bar0), which helps to communicate with the
firmware.

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>
---
 drivers/net/ethernet/broadcom/Kconfig         |   1 +
 drivers/net/ethernet/broadcom/bnge/Makefile   |   3 +-
 drivers/net/ethernet/broadcom/bnge/bnge.h     |  11 ++
 .../net/ethernet/broadcom/bnge/bnge_core.c    |  43 +++++
 .../net/ethernet/broadcom/bnge/bnge_devlink.c | 147 ++++++++++++++++++
 .../net/ethernet/broadcom/bnge/bnge_devlink.h |  18 +++
 6 files changed, 222 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_devlink.h

diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index e2c1ac91708e..0fc10e6c6902 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -256,6 +256,7 @@ config BNXT_HWMON
 config BNGE
 	tristate "Broadcom Ethernet device support"
 	depends on PCI
+	select NET_DEVLINK
 	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,
diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethernet/broadcom/bnge/Makefile
index 0c3d632805d1..e021a14d2fa0 100644
--- a/drivers/net/ethernet/broadcom/bnge/Makefile
+++ b/drivers/net/ethernet/broadcom/bnge/Makefile
@@ -2,4 +2,5 @@
 
 obj-$(CONFIG_BNGE) += bng_en.o
 
-bng_en-y := bnge_core.o
+bng_en-y := bnge_core.o \
+	    bnge_devlink.o
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
index b49c51b44473..19d85aabab4e 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
@@ -13,4 +13,15 @@ enum board_idx {
 	BCM57708,
 };
 
+struct bnge_dev {
+	struct device	*dev;
+	struct pci_dev	*pdev;
+	u64	dsn;
+#define BNGE_VPD_FLD_LEN	32
+	char		board_partno[BNGE_VPD_FLD_LEN];
+	char		board_serialno[BNGE_VPD_FLD_LEN];
+
+	void __iomem	*bar0;
+};
+
 #endif /* _BNGE_H_ */
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_core.c b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
index 3778210da98d..1a46c7663012 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_core.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
@@ -7,6 +7,7 @@
 #include <linux/pci.h>
 
 #include "bnge.h"
+#include "bnge_devlink.h"
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION(DRV_SUMMARY);
@@ -85,8 +86,19 @@ static int bnge_pci_enable(struct pci_dev *pdev)
 	return rc;
 }
 
+static void bnge_unmap_bars(struct pci_dev *pdev)
+{
+	struct bnge_dev *bd = pci_get_drvdata(pdev);
+
+	if (bd->bar0) {
+		pci_iounmap(pdev, bd->bar0);
+		bd->bar0 = NULL;
+	}
+}
+
 static int bnge_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
+	struct bnge_dev *bd;
 	int rc;
 
 	if (pci_is_bridge(pdev))
@@ -108,13 +120,44 @@ static int bnge_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	bnge_print_device_info(pdev, ent->driver_data);
 
+	bd = bnge_devlink_alloc(pdev);
+	if (!bd) {
+		dev_err(&pdev->dev, "Devlink allocation failed\n");
+		rc = -ENOMEM;
+		goto err_pci_disable;
+	}
+
+	bnge_devlink_register(bd);
+
+	bd->bar0 = pci_ioremap_bar(pdev, 0);
+	if (!bd->bar0) {
+		dev_err(&pdev->dev, "Failed mapping BAR-0, aborting\n");
+		rc = -ENOMEM;
+		goto err_devl_unreg;
+	}
+
 	pci_save_state(pdev);
 
 	return 0;
+
+err_devl_unreg:
+	bnge_devlink_unregister(bd);
+	bnge_devlink_free(bd);
+
+err_pci_disable:
+	bnge_pci_disable(pdev);
+	return rc;
 }
 
 static void bnge_remove_one(struct pci_dev *pdev)
 {
+	struct bnge_dev *bd = pci_get_drvdata(pdev);
+
+	bnge_unmap_bars(pdev);
+
+	bnge_devlink_unregister(bd);
+	bnge_devlink_free(bd);
+
 	bnge_pci_disable(pdev);
 }
 
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
new file mode 100644
index 000000000000..d406338da130
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2025 Broadcom.
+
+#include <linux/unaligned.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <net/devlink.h>
+
+#include "bnge.h"
+#include "bnge_devlink.h"
+
+static int bnge_dl_info_put(struct bnge_dev *bd, struct devlink_info_req *req,
+			    enum bnge_dl_version_type type, const char *key,
+			    char *buf)
+{
+	if (!strlen(buf))
+		return 0;
+
+	switch (type) {
+	case BNGE_VERSION_FIXED:
+		return devlink_info_version_fixed_put(req, key, buf);
+	case BNGE_VERSION_RUNNING:
+		return devlink_info_version_running_put(req, key, buf);
+	case BNGE_VERSION_STORED:
+		return devlink_info_version_stored_put(req, key, buf);
+	}
+
+	return 0;
+}
+
+static void bnge_vpd_read_info(struct bnge_dev *bd)
+{
+	struct pci_dev *pdev = bd->pdev;
+	unsigned int vpd_size, kw_len;
+	int pos, size;
+	u8 *vpd_data;
+
+	vpd_data = pci_vpd_alloc(pdev, &vpd_size);
+	if (IS_ERR(vpd_data)) {
+		pci_warn(pdev, "Unable to read VPD\n");
+		return;
+	}
+
+	pos = pci_vpd_find_ro_info_keyword(vpd_data, vpd_size,
+					   PCI_VPD_RO_KEYWORD_PARTNO, &kw_len);
+	if (pos < 0)
+		goto read_sn;
+
+	size = min_t(int, kw_len, BNGE_VPD_FLD_LEN - 1);
+	memcpy(bd->board_partno, &vpd_data[pos], size);
+
+read_sn:
+	pos = pci_vpd_find_ro_info_keyword(vpd_data, vpd_size,
+					   PCI_VPD_RO_KEYWORD_SERIALNO,
+					   &kw_len);
+	if (pos < 0)
+		goto exit;
+
+	size = min_t(int, kw_len, BNGE_VPD_FLD_LEN - 1);
+	memcpy(bd->board_serialno, &vpd_data[pos], size);
+
+exit:
+	kfree(vpd_data);
+}
+
+static int bnge_devlink_info_get(struct devlink *devlink,
+				 struct devlink_info_req *req,
+				 struct netlink_ext_ack *extack)
+{
+	struct bnge_dev *bd = devlink_priv(devlink);
+	int rc;
+
+	if (bd->dsn) {
+		char buf[32];
+		u8 dsn[8];
+		int rc;
+
+		put_unaligned_le64(bd->dsn, dsn);
+		sprintf(buf, "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",
+			dsn[7], dsn[6], dsn[5], dsn[4],
+			dsn[3], dsn[2], dsn[1], dsn[0]);
+		rc = devlink_info_serial_number_put(req, buf);
+		if (rc)
+			return rc;
+	}
+
+	if (strlen(bd->board_serialno)) {
+		rc = devlink_info_board_serial_number_put(req,
+							  bd->board_serialno);
+		if (rc)
+			return rc;
+	}
+
+	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_FIXED,
+			      DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
+			      bd->board_partno);
+
+	return rc;
+}
+
+static const struct devlink_ops bnge_devlink_ops = {
+	.info_get = bnge_devlink_info_get,
+};
+
+void bnge_devlink_free(struct bnge_dev *bd)
+{
+	struct devlink *devlink = priv_to_devlink(bd);
+
+	devlink_free(devlink);
+}
+
+struct bnge_dev *bnge_devlink_alloc(struct pci_dev *pdev)
+{
+	struct devlink *devlink;
+	struct bnge_dev *bd;
+
+	devlink = devlink_alloc(&bnge_devlink_ops, sizeof(*bd), &pdev->dev);
+	if (!devlink)
+		return NULL;
+
+	bd = devlink_priv(devlink);
+	pci_set_drvdata(pdev, bd);
+	bd->dev = &pdev->dev;
+	bd->pdev = pdev;
+
+	bd->dsn = pci_get_dsn(pdev);
+	if (!bd->dsn)
+		pci_warn(pdev, "Failed to get DSN\n");
+
+	bnge_vpd_read_info(bd);
+
+	return bd;
+}
+
+void bnge_devlink_register(struct bnge_dev *bd)
+{
+	struct devlink *devlink = priv_to_devlink(bd);
+
+	devlink_register(devlink);
+}
+
+void bnge_devlink_unregister(struct bnge_dev *bd)
+{
+	struct devlink *devlink = priv_to_devlink(bd);
+
+	devlink_unregister(devlink);
+}
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_devlink.h b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.h
new file mode 100644
index 000000000000..c6575255e650
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2025 Broadcom */
+
+#ifndef _BNGE_DEVLINK_H_
+#define _BNGE_DEVLINK_H_
+
+enum bnge_dl_version_type {
+	BNGE_VERSION_FIXED,
+	BNGE_VERSION_RUNNING,
+	BNGE_VERSION_STORED,
+};
+
+void bnge_devlink_free(struct bnge_dev *bd);
+struct bnge_dev *bnge_devlink_alloc(struct pci_dev *pdev);
+void bnge_devlink_register(struct bnge_dev *bd);
+void bnge_devlink_unregister(struct bnge_dev *bd);
+
+#endif /* _BNGE_DEVLINK_H_ */
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [net-next, 03/10] bng_en: Add firmware communication mechanism
  2025-06-18 14:47 [net-next, 00/10] Introducing Broadcom BNGE Ethernet Driver Vikas Gupta
  2025-06-18 14:47 ` [net-next, 01/10] bng_en: Add PCI interface Vikas Gupta
  2025-06-18 14:47 ` [net-next, 02/10] bng_en: Add devlink interface Vikas Gupta
@ 2025-06-18 14:47 ` Vikas Gupta
  2025-06-19  9:46   ` kernel test robot
  2025-06-19 12:43   ` Vadim Fedorenko
  2025-06-18 14:47 ` [net-next, 04/10] bng_en: Add initial interaction with firmware Vikas Gupta
                   ` (6 subsequent siblings)
  9 siblings, 2 replies; 37+ messages in thread
From: Vikas Gupta @ 2025-06-18 14:47 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Add support to communicate with the firmware.
Future patches will use these functions to send the
messages to the firmware.
Functions support allocating request/response buffers
to send a particular command. Each command has certain
timeout value to which the driver waits for response from
the firmware. In error case, commands may be either timed
out waiting on response from the firmware or may return
a specific error code.

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>
---
 drivers/net/ethernet/broadcom/bnge/Makefile   |   3 +-
 drivers/net/ethernet/broadcom/bnge/bnge.h     |  13 +
 .../net/ethernet/broadcom/bnge/bnge_hwrm.c    | 503 ++++++++++++++++++
 .../net/ethernet/broadcom/bnge/bnge_hwrm.h    | 107 ++++
 4 files changed, 625 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm.c
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h

diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethernet/broadcom/bnge/Makefile
index e021a14d2fa0..b296d7de56ce 100644
--- a/drivers/net/ethernet/broadcom/bnge/Makefile
+++ b/drivers/net/ethernet/broadcom/bnge/Makefile
@@ -3,4 +3,5 @@
 obj-$(CONFIG_BNGE) += bng_en.o
 
 bng_en-y := bnge_core.o \
-	    bnge_devlink.o
+	    bnge_devlink.o \
+	    bnge_hwrm.o
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
index 19d85aabab4e..8f2a562d9ae2 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
@@ -13,6 +13,8 @@ enum board_idx {
 	BCM57708,
 };
 
+#define INVALID_HW_RING_ID      ((u16)-1)
+
 struct bnge_dev {
 	struct device	*dev;
 	struct pci_dev	*pdev;
@@ -22,6 +24,17 @@ struct bnge_dev {
 	char		board_serialno[BNGE_VPD_FLD_LEN];
 
 	void __iomem	*bar0;
+
+	/* HWRM members */
+	u16			hwrm_cmd_seq;
+	u16			hwrm_cmd_kong_seq;
+	struct dma_pool		*hwrm_dma_pool;
+	struct hlist_head	hwrm_pending_list;
+	u16			hwrm_max_req_len;
+	u16			hwrm_max_ext_req_len;
+	unsigned int		hwrm_cmd_timeout;
+	unsigned int		hwrm_cmd_max_timeout;
+	struct mutex		hwrm_cmd_lock;	/* serialize hwrm messages */
 };
 
 #endif /* _BNGE_H_ */
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.c b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.c
new file mode 100644
index 000000000000..803a1951b736
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.c
@@ -0,0 +1,503 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2025 Broadcom.
+
+#include <asm/byteorder.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+
+#include "bnge.h"
+#include "bnge_hwrm.h"
+
+static u64 hwrm_calc_sentinel(struct bnge_hwrm_ctx *ctx, u16 req_type)
+{
+	return (((uintptr_t)ctx) + req_type) ^ BNGE_HWRM_SENTINEL;
+}
+
+int __hwrm_req_init(struct bnge_dev *bd, void **req, u16 req_type, u32 req_len)
+{
+	struct bnge_hwrm_ctx *ctx;
+	dma_addr_t dma_handle;
+	u8 *req_addr;
+
+	if (req_len > BNGE_HWRM_CTX_OFFSET)
+		return -E2BIG;
+
+	req_addr = dma_pool_alloc(bd->hwrm_dma_pool, GFP_KERNEL | __GFP_ZERO,
+				  &dma_handle);
+	if (!req_addr)
+		return -ENOMEM;
+
+	ctx = (struct bnge_hwrm_ctx *)(req_addr + BNGE_HWRM_CTX_OFFSET);
+	/* safety first, sentinel used to check for invalid requests */
+	ctx->sentinel = hwrm_calc_sentinel(ctx, req_type);
+	ctx->req_len = req_len;
+	ctx->req = (struct input *)req_addr;
+	ctx->resp = (struct output *)(req_addr + BNGE_HWRM_RESP_OFFSET);
+	ctx->dma_handle = dma_handle;
+	ctx->flags = 0; /* __GFP_ZERO, but be explicit regarding ownership */
+	ctx->timeout = bd->hwrm_cmd_timeout ?: DFLT_HWRM_CMD_TIMEOUT;
+	ctx->allocated = BNGE_HWRM_DMA_SIZE - BNGE_HWRM_CTX_OFFSET;
+	ctx->gfp = GFP_KERNEL;
+	ctx->slice_addr = NULL;
+
+	/* initialize common request fields */
+	ctx->req->req_type = cpu_to_le16(req_type);
+	ctx->req->resp_addr = cpu_to_le64(dma_handle + BNGE_HWRM_RESP_OFFSET);
+	ctx->req->cmpl_ring = cpu_to_le16(BNGE_HWRM_NO_CMPL_RING);
+	ctx->req->target_id = cpu_to_le16(BNGE_HWRM_TARGET);
+	*req = ctx->req;
+
+	return 0;
+}
+
+static struct bnge_hwrm_ctx *__hwrm_ctx(struct bnge_dev *bd, u8 *req_addr)
+{
+	void *ctx_addr = req_addr + BNGE_HWRM_CTX_OFFSET;
+	struct input *req = (struct input *)req_addr;
+	struct bnge_hwrm_ctx *ctx = ctx_addr;
+	u64 sentinel;
+
+	if (!req) {
+		dev_err(bd->dev, "null HWRM request");
+		dump_stack();
+		return NULL;
+	}
+
+	/* HWRM API has no type safety, verify sentinel to validate address */
+	sentinel = hwrm_calc_sentinel(ctx, le16_to_cpu(req->req_type));
+	if (ctx->sentinel != sentinel) {
+		dev_err(bd->dev, "HWRM sentinel mismatch, req_type = %u\n",
+			(u32)le16_to_cpu(req->req_type));
+		dump_stack();
+		return NULL;
+	}
+
+	return ctx;
+}
+
+void hwrm_req_timeout(struct bnge_dev *bd, void *req, unsigned int timeout)
+{
+	struct bnge_hwrm_ctx *ctx = __hwrm_ctx(bd, req);
+
+	if (ctx)
+		ctx->timeout = timeout;
+}
+
+void hwrm_req_alloc_flags(struct bnge_dev *bd, void *req, gfp_t gfp)
+{
+	struct bnge_hwrm_ctx *ctx = __hwrm_ctx(bd, req);
+
+	if (ctx)
+		ctx->gfp = gfp;
+}
+
+void hwrm_req_flags(struct bnge_dev *bd, void *req,
+		    enum bnge_hwrm_ctx_flags flags)
+{
+	struct bnge_hwrm_ctx *ctx = __hwrm_ctx(bd, req);
+
+	if (ctx)
+		ctx->flags |= (flags & HWRM_API_FLAGS);
+}
+
+void *hwrm_req_hold(struct bnge_dev *bd, void *req)
+{
+	struct bnge_hwrm_ctx *ctx = __hwrm_ctx(bd, req);
+	struct input *input = (struct input *)req;
+
+	if (!ctx)
+		return NULL;
+
+	if (ctx->flags & BNGE_HWRM_INTERNAL_CTX_OWNED) {
+		dev_err(bd->dev, "HWRM context already owned, req_type = %u\n",
+			(u32)le16_to_cpu(input->req_type));
+		dump_stack();
+		return NULL;
+	}
+
+	ctx->flags |= BNGE_HWRM_INTERNAL_CTX_OWNED;
+	return ((u8 *)req) + BNGE_HWRM_RESP_OFFSET;
+}
+
+static void __hwrm_ctx_drop(struct bnge_dev *bd, struct bnge_hwrm_ctx *ctx)
+{
+	void *addr = ((u8 *)ctx) - BNGE_HWRM_CTX_OFFSET;
+	dma_addr_t dma_handle = ctx->dma_handle; /* save before invalidate */
+
+	/* unmap any auxiliary DMA slice */
+	if (ctx->slice_addr)
+		dma_free_coherent(bd->dev, ctx->slice_size,
+				  ctx->slice_addr, ctx->slice_handle);
+
+	/* invalidate, ensure ownership, sentinel and dma_handle are cleared */
+	memset(ctx, 0, sizeof(struct bnge_hwrm_ctx));
+
+	/* return the buffer to the DMA pool */
+	if (dma_handle)
+		dma_pool_free(bd->hwrm_dma_pool, addr, dma_handle);
+}
+
+void hwrm_req_drop(struct bnge_dev *bd, void *req)
+{
+	struct bnge_hwrm_ctx *ctx = __hwrm_ctx(bd, req);
+
+	if (ctx)
+		__hwrm_ctx_drop(bd, ctx);
+}
+
+static int __hwrm_to_stderr(u32 hwrm_err)
+{
+	switch (hwrm_err) {
+	case HWRM_ERR_CODE_SUCCESS:
+		return 0;
+	case HWRM_ERR_CODE_RESOURCE_LOCKED:
+		return -EROFS;
+	case HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED:
+		return -EACCES;
+	case HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR:
+		return -ENOSPC;
+	case HWRM_ERR_CODE_INVALID_PARAMS:
+	case HWRM_ERR_CODE_INVALID_FLAGS:
+	case HWRM_ERR_CODE_INVALID_ENABLES:
+	case HWRM_ERR_CODE_UNSUPPORTED_TLV:
+	case HWRM_ERR_CODE_UNSUPPORTED_OPTION_ERR:
+		return -EINVAL;
+	case HWRM_ERR_CODE_NO_BUFFER:
+		return -ENOMEM;
+	case HWRM_ERR_CODE_HOT_RESET_PROGRESS:
+	case HWRM_ERR_CODE_BUSY:
+		return -EAGAIN;
+	case HWRM_ERR_CODE_CMD_NOT_SUPPORTED:
+		return -EOPNOTSUPP;
+	case HWRM_ERR_CODE_PF_UNAVAILABLE:
+		return -ENODEV;
+	default:
+		return -EIO;
+	}
+}
+
+static struct bnge_hwrm_wait_token *
+__hwrm_acquire_token(struct bnge_dev *bd, enum bnge_hwrm_chnl dst)
+{
+	struct bnge_hwrm_wait_token *token;
+
+	token = kzalloc(sizeof(*token), GFP_KERNEL);
+	if (!token)
+		return NULL;
+
+	mutex_lock(&bd->hwrm_cmd_lock);
+
+	token->dst = dst;
+	token->state = BNGE_HWRM_PENDING;
+	if (dst == BNGE_HWRM_CHNL_CHIMP) {
+		token->seq_id = bd->hwrm_cmd_seq++;
+		hlist_add_head_rcu(&token->node, &bd->hwrm_pending_list);
+	} else {
+		token->seq_id = bd->hwrm_cmd_kong_seq++;
+	}
+
+	return token;
+}
+
+static void
+__hwrm_release_token(struct bnge_dev *bd, struct bnge_hwrm_wait_token *token)
+{
+	if (token->dst == BNGE_HWRM_CHNL_CHIMP) {
+		hlist_del_rcu(&token->node);
+		kfree_rcu(token, rcu);
+	} else {
+		kfree(token);
+	}
+	mutex_unlock(&bd->hwrm_cmd_lock);
+}
+
+static void hwrm_req_dbg(struct bnge_dev *bd, struct input *req)
+{
+	u32 ring = le16_to_cpu(req->cmpl_ring);
+	u32 type = le16_to_cpu(req->req_type);
+	u32 tgt = le16_to_cpu(req->target_id);
+	u32 seq = le16_to_cpu(req->seq_id);
+	char opt[32] = "\n";
+
+	if (unlikely(ring != (u16)BNGE_HWRM_NO_CMPL_RING))
+		snprintf(opt, 16, " ring %d\n", ring);
+
+	if (unlikely(tgt != BNGE_HWRM_TARGET))
+		snprintf(opt + strlen(opt) - 1, 16, " tgt 0x%x\n", tgt);
+
+	dev_dbg(bd->dev, "sent hwrm req_type 0x%x seq id 0x%x%s",
+		type, seq, opt);
+}
+
+#define hwrm_err(bd, ctx, fmt, ...)				       \
+	do {							       \
+		if ((ctx)->flags & BNGE_HWRM_CTX_SILENT)	       \
+			dev_dbg((bd)->dev, fmt, __VA_ARGS__);       \
+		else						       \
+			dev_err((bd)->dev, fmt, __VA_ARGS__);       \
+	} while (0)
+
+static int __hwrm_send(struct bnge_dev *bd, struct bnge_hwrm_ctx *ctx)
+{
+	u32 doorbell_offset = BNGE_GRCPF_REG_CHIMP_COMM_TRIGGER;
+	enum bnge_hwrm_chnl dst = BNGE_HWRM_CHNL_CHIMP;
+	u32 bar_offset = BNGE_GRCPF_REG_CHIMP_COMM;
+	struct bnge_hwrm_wait_token *token = NULL;
+	u16 max_req_len = BNGE_HWRM_MAX_REQ_LEN;
+	unsigned int i, timeout, tmo_count;
+	u32 *data = (u32 *)ctx->req;
+	u32 msg_len = ctx->req_len;
+	int rc = -EBUSY;
+	u32 req_type;
+	u16 len = 0;
+	u8 *valid;
+
+	if (ctx->flags & BNGE_HWRM_INTERNAL_RESP_DIRTY)
+		memset(ctx->resp, 0, PAGE_SIZE);
+
+	req_type = le16_to_cpu(ctx->req->req_type);
+
+	if (msg_len > BNGE_HWRM_MAX_REQ_LEN &&
+	    msg_len > bd->hwrm_max_ext_req_len) {
+		dev_warn(bd->dev, "oversized hwrm request, req_type 0x%x",
+			 req_type);
+		rc = -E2BIG;
+		goto exit;
+	}
+
+	token = __hwrm_acquire_token(bd, dst);
+	if (!token) {
+		rc = -ENOMEM;
+		goto exit;
+	}
+	ctx->req->seq_id = cpu_to_le16(token->seq_id);
+
+	/* Ensure any associated DMA buffers are written before doorbell */
+	wmb();
+
+	/* Write request msg to hwrm channel */
+	__iowrite32_copy(bd->bar0 + bar_offset, data, msg_len / 4);
+
+	for (i = msg_len; i < max_req_len; i += 4)
+		writel(0, bd->bar0 + bar_offset + i);
+
+	/* Ring channel doorbell */
+	writel(1, bd->bar0 + doorbell_offset);
+
+	hwrm_req_dbg(bd, ctx->req);
+
+	/* Limit timeout to an upper limit */
+	timeout = min(ctx->timeout,
+		      bd->hwrm_cmd_max_timeout ?: HWRM_CMD_MAX_TIMEOUT);
+	/* convert timeout to usec */
+	timeout *= 1000;
+
+	i = 0;
+	/* Short timeout for the first few iterations:
+	 * number of loops = number of loops for short timeout +
+	 * number of loops for standard timeout.
+	 */
+	tmo_count = HWRM_SHORT_TIMEOUT_COUNTER;
+	timeout = timeout - HWRM_SHORT_MIN_TIMEOUT * HWRM_SHORT_TIMEOUT_COUNTER;
+	tmo_count += DIV_ROUND_UP(timeout, HWRM_MIN_TIMEOUT);
+
+	if (le16_to_cpu(ctx->req->cmpl_ring) != INVALID_HW_RING_ID) {
+		/* Wait until hwrm response cmpl interrupt is processed */
+		while (READ_ONCE(token->state) < BNGE_HWRM_COMPLETE &&
+		       i++ < tmo_count) {
+			/* on first few passes, just barely sleep */
+			if (i < HWRM_SHORT_TIMEOUT_COUNTER) {
+				usleep_range(HWRM_SHORT_MIN_TIMEOUT,
+					     HWRM_SHORT_MAX_TIMEOUT);
+			} else {
+				usleep_range(HWRM_MIN_TIMEOUT,
+					     HWRM_MAX_TIMEOUT);
+			}
+		}
+
+		if (READ_ONCE(token->state) != BNGE_HWRM_COMPLETE) {
+			hwrm_err(bd, ctx, "Resp cmpl intr err msg: 0x%x\n",
+				 req_type);
+			goto exit;
+		}
+		len = le16_to_cpu(READ_ONCE(ctx->resp->resp_len));
+		valid = ((u8 *)ctx->resp) + len - 1;
+	} else {
+		__le16 seen_out_of_seq = ctx->req->seq_id; /* will never see */
+		int j;
+
+		/* Check if response len is updated */
+		for (i = 0; i < tmo_count; i++) {
+			if (token &&
+			    READ_ONCE(token->state) == BNGE_HWRM_DEFERRED) {
+				__hwrm_release_token(bd, token);
+				token = NULL;
+			}
+
+			len = le16_to_cpu(READ_ONCE(ctx->resp->resp_len));
+			if (len) {
+				__le16 resp_seq = READ_ONCE(ctx->resp->seq_id);
+
+				if (resp_seq == ctx->req->seq_id)
+					break;
+				if (resp_seq != seen_out_of_seq) {
+					dev_warn(bd->dev, "Discarding out of seq response: 0x%x for msg {0x%x 0x%x}\n",
+						 le16_to_cpu(resp_seq), req_type, le16_to_cpu(ctx->req->seq_id));
+					seen_out_of_seq = resp_seq;
+				}
+			}
+
+			/* on first few passes, just barely sleep */
+			if (i < HWRM_SHORT_TIMEOUT_COUNTER) {
+				usleep_range(HWRM_SHORT_MIN_TIMEOUT,
+					     HWRM_SHORT_MAX_TIMEOUT);
+			} else {
+				usleep_range(HWRM_MIN_TIMEOUT,
+					     HWRM_MAX_TIMEOUT);
+			}
+		}
+
+		if (i >= tmo_count) {
+			hwrm_err(bd, ctx, "Error (timeout: %u) msg {0x%x 0x%x} len:%d\n",
+				 hwrm_total_timeout(i), req_type,
+				 le16_to_cpu(ctx->req->seq_id), len);
+			goto exit;
+		}
+
+		/* Last byte of resp contains valid bit */
+		valid = ((u8 *)ctx->resp) + len - 1;
+		for (j = 0; j < HWRM_VALID_BIT_DELAY_USEC; ) {
+			/* make sure we read from updated DMA memory */
+			dma_rmb();
+			if (*valid)
+				break;
+			if (j < 10) {
+				udelay(1);
+				j++;
+			} else {
+				usleep_range(20, 30);
+				j += 20;
+			}
+		}
+
+		if (j >= HWRM_VALID_BIT_DELAY_USEC) {
+			hwrm_err(bd, ctx, "Error (timeout: %u) msg {0x%x 0x%x} len:%d v:%d\n",
+				 hwrm_total_timeout(i) + j, req_type,
+				 le16_to_cpu(ctx->req->seq_id), len, *valid);
+			goto exit;
+		}
+	}
+
+	/* Zero valid bit for compatibility.  Valid bit in an older spec
+	 * may become a new field in a newer spec.  We must make sure that
+	 * a new field not implemented by old spec will read zero.
+	 */
+	*valid = 0;
+	rc = le16_to_cpu(ctx->resp->error_code);
+	if (rc == HWRM_ERR_CODE_BUSY && !(ctx->flags & BNGE_HWRM_CTX_SILENT))
+		dev_warn(bd->dev, "FW returned busy, hwrm req_type 0x%x\n",
+			 req_type);
+	else if (rc && rc != HWRM_ERR_CODE_PF_UNAVAILABLE)
+		hwrm_err(bd, ctx, "hwrm req_type 0x%x seq id 0x%x error %d\n",
+			 req_type, le16_to_cpu(ctx->req->seq_id), rc);
+	rc = __hwrm_to_stderr(rc);
+
+exit:
+	if (token)
+		__hwrm_release_token(bd, token);
+	if (ctx->flags & BNGE_HWRM_INTERNAL_CTX_OWNED)
+		ctx->flags |= BNGE_HWRM_INTERNAL_RESP_DIRTY;
+	else
+		__hwrm_ctx_drop(bd, ctx);
+	return rc;
+}
+
+int hwrm_req_send(struct bnge_dev *bd, void *req)
+{
+	struct bnge_hwrm_ctx *ctx = __hwrm_ctx(bd, req);
+
+	if (!ctx)
+		return -EINVAL;
+
+	return __hwrm_send(bd, ctx);
+}
+
+int hwrm_req_send_silent(struct bnge_dev *bd, void *req)
+{
+	hwrm_req_flags(bd, req, BNGE_HWRM_CTX_SILENT);
+	return hwrm_req_send(bd, req);
+}
+
+void *
+hwrm_req_dma_slice(struct bnge_dev *bd, void *req, u32 size,
+		   dma_addr_t *dma_handle)
+{
+	struct bnge_hwrm_ctx *ctx = __hwrm_ctx(bd, req);
+	u8 *end = ((u8 *)req) + BNGE_HWRM_DMA_SIZE;
+	struct input *input = req;
+	u8 *addr, *req_addr = req;
+	u32 max_offset, offset;
+
+	if (!ctx)
+		return NULL;
+
+	max_offset = BNGE_HWRM_DMA_SIZE - ctx->allocated;
+	offset = max_offset - size;
+	offset = ALIGN_DOWN(offset, BNGE_HWRM_DMA_ALIGN);
+	addr = req_addr + offset;
+
+	if (addr < req_addr + max_offset && req_addr + ctx->req_len <= addr) {
+		ctx->allocated = end - addr;
+		*dma_handle = ctx->dma_handle + offset;
+		return addr;
+	}
+
+	if (ctx->slice_addr) {
+		dev_err(bd->dev, "HWRM refusing to reallocate DMA slice, req_type = %u\n",
+			(u32)le16_to_cpu(input->req_type));
+		dump_stack();
+		return NULL;
+	}
+
+	addr = dma_alloc_coherent(bd->dev, size, dma_handle, ctx->gfp);
+	if (!addr)
+		return NULL;
+
+	ctx->slice_addr = addr;
+	ctx->slice_size = size;
+	ctx->slice_handle = *dma_handle;
+
+	return addr;
+}
+
+void bnge_cleanup_hwrm_resources(struct bnge_dev *bd)
+{
+	struct bnge_hwrm_wait_token *token;
+
+	dma_pool_destroy(bd->hwrm_dma_pool);
+	bd->hwrm_dma_pool = NULL;
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(token, &bd->hwrm_pending_list, node)
+		WRITE_ONCE(token->state, BNGE_HWRM_CANCELLED);
+	rcu_read_unlock();
+}
+
+int bnge_init_hwrm_resources(struct bnge_dev *bd)
+{
+	bd->hwrm_dma_pool = dma_pool_create("bnge_hwrm", bd->dev,
+					    BNGE_HWRM_DMA_SIZE,
+					    BNGE_HWRM_DMA_ALIGN, 0);
+	if (!bd->hwrm_dma_pool)
+		return -ENOMEM;
+
+	INIT_HLIST_HEAD(&bd->hwrm_pending_list);
+	mutex_init(&bd->hwrm_cmd_lock);
+
+	return 0;
+}
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h
new file mode 100644
index 000000000000..c14f03daab4b
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h
@@ -0,0 +1,107 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2025 Broadcom */
+
+#ifndef _BNGE_HWRM_H_
+#define _BNGE_HWRM_H_
+
+#include "../bnxt/bnxt_hsi.h"
+
+enum bnge_hwrm_ctx_flags {
+	BNGE_HWRM_INTERNAL_CTX_OWNED	= BIT(0),
+	BNGE_HWRM_INTERNAL_RESP_DIRTY	= BIT(1),
+	BNGE_HWRM_CTX_SILENT		= BIT(2),
+	BNGE_HWRM_FULL_WAIT		= BIT(3),
+};
+
+#define HWRM_API_FLAGS (BNGE_HWRM_CTX_SILENT | BNGE_HWRM_FULL_WAIT)
+
+struct bnge_hwrm_ctx {
+	u64 sentinel;
+	dma_addr_t dma_handle;
+	struct output *resp;
+	struct input *req;
+	dma_addr_t slice_handle;
+	void *slice_addr;
+	u32 slice_size;
+	u32 req_len;
+	enum bnge_hwrm_ctx_flags flags;
+	unsigned int timeout;
+	u32 allocated;
+	gfp_t gfp;
+};
+
+enum bnge_hwrm_wait_state {
+	BNGE_HWRM_PENDING,
+	BNGE_HWRM_DEFERRED,
+	BNGE_HWRM_COMPLETE,
+	BNGE_HWRM_CANCELLED,
+};
+
+enum bnge_hwrm_chnl { BNGE_HWRM_CHNL_CHIMP, BNGE_HWRM_CHNL_KONG };
+
+struct bnge_hwrm_wait_token {
+	struct rcu_head rcu;
+	struct hlist_node node;
+	enum bnge_hwrm_wait_state state;
+	enum bnge_hwrm_chnl dst;
+	u16 seq_id;
+};
+
+#define DFLT_HWRM_CMD_TIMEOUT		500
+
+#define BNGE_GRCPF_REG_CHIMP_COMM		0x0
+#define BNGE_GRCPF_REG_CHIMP_COMM_TRIGGER	0x100
+
+#define BNGE_HWRM_MAX_REQ_LEN		(bd->hwrm_max_req_len)
+#define BNGE_HWRM_SHORT_REQ_LEN		sizeof(struct hwrm_short_input)
+#define HWRM_CMD_MAX_TIMEOUT		40000U
+#define SHORT_HWRM_CMD_TIMEOUT		20
+#define HWRM_CMD_TIMEOUT		(bd->hwrm_cmd_timeout)
+#define HWRM_RESET_TIMEOUT		((HWRM_CMD_TIMEOUT) * 4)
+#define BNGE_HWRM_TARGET		0xffff
+#define BNGE_HWRM_NO_CMPL_RING		-1
+#define BNGE_HWRM_REQ_MAX_SIZE		128
+#define BNGE_HWRM_DMA_SIZE		(2 * PAGE_SIZE) /* space for req+resp */
+#define BNGE_HWRM_RESP_RESERVED		PAGE_SIZE
+#define BNGE_HWRM_RESP_OFFSET		(BNGE_HWRM_DMA_SIZE -		\
+					 BNGE_HWRM_RESP_RESERVED)
+#define BNGE_HWRM_CTX_OFFSET		(BNGE_HWRM_RESP_OFFSET -	\
+					 sizeof(struct bnge_hwrm_ctx))
+#define BNGE_HWRM_DMA_ALIGN		16
+#define BNGE_HWRM_SENTINEL		0xb6e1f68a12e9a7eb /* arbitrary value */
+#define BNGE_HWRM_REQS_PER_PAGE	(BNGE_PAGE_SIZE /	\
+					 BNGE_HWRM_REQ_MAX_SIZE)
+#define HWRM_SHORT_MIN_TIMEOUT		3
+#define HWRM_SHORT_MAX_TIMEOUT		10
+#define HWRM_SHORT_TIMEOUT_COUNTER	5
+
+#define HWRM_MIN_TIMEOUT		25
+#define HWRM_MAX_TIMEOUT		40
+
+static inline unsigned int hwrm_total_timeout(unsigned int n)
+{
+	return n <= HWRM_SHORT_TIMEOUT_COUNTER ? n * HWRM_SHORT_MIN_TIMEOUT :
+		HWRM_SHORT_TIMEOUT_COUNTER * HWRM_SHORT_MIN_TIMEOUT +
+		(n - HWRM_SHORT_TIMEOUT_COUNTER) * HWRM_MIN_TIMEOUT;
+}
+
+#define HWRM_VALID_BIT_DELAY_USEC	50000
+
+void bnge_cleanup_hwrm_resources(struct bnge_dev *bd);
+int bnge_init_hwrm_resources(struct bnge_dev *bd);
+
+int __hwrm_req_init(struct bnge_dev *bd, void **req, u16 req_type, u32 req_len);
+#define hwrm_req_init(bd, req, req_type) \
+	__hwrm_req_init((bd), (void **)&(req), (req_type), sizeof(*(req)))
+void *hwrm_req_hold(struct bnge_dev *bd, void *req);
+void hwrm_req_drop(struct bnge_dev *bd, void *req);
+void hwrm_req_flags(struct bnge_dev *bd, void *req,
+		    enum bnge_hwrm_ctx_flags flags);
+void hwrm_req_timeout(struct bnge_dev *bd, void *req, unsigned int timeout);
+int hwrm_req_send(struct bnge_dev *bd, void *req);
+int hwrm_req_send_silent(struct bnge_dev *bd, void *req);
+void hwrm_req_alloc_flags(struct bnge_dev *bd, void *req, gfp_t flags);
+void *hwrm_req_dma_slice(struct bnge_dev *bd, void *req, u32 size,
+			 dma_addr_t *dma);
+
+#endif /* _BNGE_HWRM_H_ */
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [net-next, 04/10] bng_en: Add initial interaction with firmware
  2025-06-18 14:47 [net-next, 00/10] Introducing Broadcom BNGE Ethernet Driver Vikas Gupta
                   ` (2 preceding siblings ...)
  2025-06-18 14:47 ` [net-next, 03/10] bng_en: Add firmware communication mechanism Vikas Gupta
@ 2025-06-18 14:47 ` Vikas Gupta
  2025-06-19 12:53   ` Vadim Fedorenko
  2025-06-18 14:47 ` [net-next, 05/10] bng_en: Add ring memory allocation support Vikas Gupta
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 37+ messages in thread
From: Vikas Gupta @ 2025-06-18 14:47 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Query firmware with the help of basic firmware commands and
cache the capabilities. With the help of basic commands
start the initialization process of the driver with the
firmware.
Since basic information is available from the firmware,
add that information to the devlink info get command.

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>
---
 drivers/net/ethernet/broadcom/bnge/Makefile   |   3 +-
 drivers/net/ethernet/broadcom/bnge/bnge.h     |  54 +++++
 .../net/ethernet/broadcom/bnge/bnge_core.c    |  67 ++++++
 .../net/ethernet/broadcom/bnge/bnge_devlink.c | 120 ++++++++++
 .../ethernet/broadcom/bnge/bnge_hwrm_lib.c    | 213 ++++++++++++++++++
 .../ethernet/broadcom/bnge/bnge_hwrm_lib.h    |  16 ++
 6 files changed, 472 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h

diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethernet/broadcom/bnge/Makefile
index b296d7de56ce..b8dbbc2d5972 100644
--- a/drivers/net/ethernet/broadcom/bnge/Makefile
+++ b/drivers/net/ethernet/broadcom/bnge/Makefile
@@ -4,4 +4,5 @@ obj-$(CONFIG_BNGE) += bng_en.o
 
 bng_en-y := bnge_core.o \
 	    bnge_devlink.o \
-	    bnge_hwrm.o
+	    bnge_hwrm.o \
+	    bnge_hwrm_lib.o
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
index 8f2a562d9ae2..60af0517c45e 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
@@ -7,6 +7,13 @@
 #define DRV_NAME	"bng_en"
 #define DRV_SUMMARY	"Broadcom 800G Ethernet Linux Driver"
 
+#include <linux/etherdevice.h>
+#include "../bnxt/bnxt_hsi.h"
+
+#define DRV_VER_MAJ	1
+#define DRV_VER_MIN	15
+#define DRV_VER_UPD	1
+
 extern char bnge_driver_name[];
 
 enum board_idx {
@@ -15,6 +22,36 @@ enum board_idx {
 
 #define INVALID_HW_RING_ID      ((u16)-1)
 
+enum {
+	BNGE_FW_CAP_SHORT_CMD				= BIT_ULL(0),
+	BNGE_FW_CAP_LLDP_AGENT				= BIT_ULL(1),
+	BNGE_FW_CAP_DCBX_AGENT				= BIT_ULL(2),
+	BNGE_FW_CAP_IF_CHANGE				= BIT_ULL(3),
+	BNGE_FW_CAP_KONG_MB_CHNL			= BIT_ULL(4),
+	BNGE_FW_CAP_ERROR_RECOVERY			= BIT_ULL(5),
+	BNGE_FW_CAP_PKG_VER				= BIT_ULL(6),
+	BNGE_FW_CAP_CFA_ADV_FLOW			= BIT_ULL(7),
+	BNGE_FW_CAP_CFA_RFS_RING_TBL_IDX_V2		= BIT_ULL(8),
+	BNGE_FW_CAP_PCIE_STATS_SUPPORTED		= BIT_ULL(9),
+	BNGE_FW_CAP_EXT_STATS_SUPPORTED			= BIT_ULL(10),
+	BNGE_FW_CAP_ERR_RECOVER_RELOAD			= BIT_ULL(11),
+	BNGE_FW_CAP_HOT_RESET				= BIT_ULL(12),
+	BNGE_FW_CAP_RX_ALL_PKT_TS			= BIT_ULL(13),
+	BNGE_FW_CAP_VLAN_RX_STRIP			= BIT_ULL(14),
+	BNGE_FW_CAP_VLAN_TX_INSERT			= BIT_ULL(15),
+	BNGE_FW_CAP_EXT_HW_STATS_SUPPORTED		= BIT_ULL(16),
+	BNGE_FW_CAP_LIVEPATCH				= BIT_ULL(17),
+	BNGE_FW_CAP_HOT_RESET_IF			= BIT_ULL(18),
+	BNGE_FW_CAP_RING_MONITOR			= BIT_ULL(19),
+	BNGE_FW_CAP_DBG_QCAPS				= BIT_ULL(20),
+	BNGE_FW_CAP_THRESHOLD_TEMP_SUPPORTED		= BIT_ULL(21),
+	BNGE_FW_CAP_DFLT_VLAN_TPID_PCP			= BIT_ULL(22),
+	BNGE_FW_CAP_VNIC_TUNNEL_TPA			= BIT_ULL(23),
+	BNGE_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO		= BIT_ULL(24),
+	BNGE_FW_CAP_CFA_RFS_RING_TBL_IDX_V3		= BIT_ULL(25),
+	BNGE_FW_CAP_VNIC_RE_FLUSH			= BIT_ULL(26),
+};
+
 struct bnge_dev {
 	struct device	*dev;
 	struct pci_dev	*pdev;
@@ -25,6 +62,9 @@ struct bnge_dev {
 
 	void __iomem	*bar0;
 
+	u16		chip_num;
+	u8		chip_rev;
+
 	/* HWRM members */
 	u16			hwrm_cmd_seq;
 	u16			hwrm_cmd_kong_seq;
@@ -35,6 +75,20 @@ struct bnge_dev {
 	unsigned int		hwrm_cmd_timeout;
 	unsigned int		hwrm_cmd_max_timeout;
 	struct mutex		hwrm_cmd_lock;	/* serialize hwrm messages */
+
+	struct hwrm_ver_get_output	ver_resp;
+#define FW_VER_STR_LEN		32
+	char			fw_ver_str[FW_VER_STR_LEN];
+	char			hwrm_ver_supp[FW_VER_STR_LEN];
+	char			nvm_cfg_ver[FW_VER_STR_LEN];
+	u64			fw_ver_code;
+#define BNGE_FW_VER_CODE(maj, min, bld, rsv)			\
+	((u64)(maj) << 48 | (u64)(min) << 32 | (u64)(bld) << 16 | (rsv))
+
+	unsigned long           state;
+#define BNGE_STATE_DRV_REGISTERED      0
+
+	u64			fw_cap;
 };
 
 #endif /* _BNGE_H_ */
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_core.c b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
index 1a46c7663012..5e23eb14f60e 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_core.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
@@ -8,6 +8,8 @@
 
 #include "bnge.h"
 #include "bnge_devlink.h"
+#include "bnge_hwrm.h"
+#include "bnge_hwrm_lib.h"
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION(DRV_SUMMARY);
@@ -37,6 +39,51 @@ static void bnge_print_device_info(struct pci_dev *pdev, enum board_idx idx)
 	pcie_print_link_status(pdev);
 }
 
+static void bnge_nvm_cfg_ver_get(struct bnge_dev *bd)
+{
+	struct hwrm_nvm_get_dev_info_output nvm_info;
+
+	if (!bnge_hwrm_nvm_dev_info(bd, &nvm_info))
+		snprintf(bd->nvm_cfg_ver, FW_VER_STR_LEN, "%d.%d.%d",
+			 nvm_info.nvm_cfg_ver_maj, nvm_info.nvm_cfg_ver_min,
+			 nvm_info.nvm_cfg_ver_upd);
+}
+
+static void bnge_fw_unregister_dev(struct bnge_dev *bd)
+{
+	bnge_hwrm_func_drv_unrgtr(bd);
+}
+
+static int bnge_fw_register_dev(struct bnge_dev *bd)
+{
+	int rc;
+
+	bd->fw_cap = 0;
+	rc = bnge_hwrm_ver_get(bd);
+	if (rc) {
+		dev_err(bd->dev, "Get Version command failed rc: %d\n", rc);
+		return rc;
+	}
+
+	bnge_nvm_cfg_ver_get(bd);
+
+	rc = bnge_hwrm_func_reset(bd);
+	if (rc) {
+		dev_err(bd->dev, "Failed to reset function rc: %d\n", rc);
+		return rc;
+	}
+
+	bnge_hwrm_fw_set_time(bd);
+
+	rc =  bnge_hwrm_func_drv_rgtr(bd);
+	if (rc) {
+		dev_err(bd->dev, "Failed to rgtr with firmware rc: %d\n", rc);
+		return rc;
+	}
+
+	return 0;
+}
+
 static void bnge_pci_disable(struct pci_dev *pdev)
 {
 	pci_release_regions(pdev);
@@ -136,10 +183,26 @@ static int bnge_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_devl_unreg;
 	}
 
+	rc = bnge_init_hwrm_resources(bd);
+	if (rc)
+		goto err_bar_unmap;
+
+	rc = bnge_fw_register_dev(bd);
+	if (rc) {
+		dev_err(&pdev->dev, "Failed to register with firmware rc = %d\n", rc);
+		goto err_hwrm_cleanup;
+	}
+
 	pci_save_state(pdev);
 
 	return 0;
 
+err_hwrm_cleanup:
+	bnge_cleanup_hwrm_resources(bd);
+
+err_bar_unmap:
+	bnge_unmap_bars(pdev);
+
 err_devl_unreg:
 	bnge_devlink_unregister(bd);
 	bnge_devlink_free(bd);
@@ -153,6 +216,10 @@ static void bnge_remove_one(struct pci_dev *pdev)
 {
 	struct bnge_dev *bd = pci_get_drvdata(pdev);
 
+	bnge_fw_unregister_dev(bd);
+
+	bnge_cleanup_hwrm_resources(bd);
+
 	bnge_unmap_bars(pdev);
 
 	bnge_devlink_unregister(bd);
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
index d406338da130..f987d35beea2 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
@@ -8,6 +8,7 @@
 
 #include "bnge.h"
 #include "bnge_devlink.h"
+#include "bnge_hwrm_lib.h"
 
 static int bnge_dl_info_put(struct bnge_dev *bd, struct devlink_info_req *req,
 			    enum bnge_dl_version_type type, const char *key,
@@ -16,6 +17,10 @@ static int bnge_dl_info_put(struct bnge_dev *bd, struct devlink_info_req *req,
 	if (!strlen(buf))
 		return 0;
 
+	if (!strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_NCSI) ||
+	    !strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_ROCE))
+		return 0;
+
 	switch (type) {
 	case BNGE_VERSION_FIXED:
 		return devlink_info_version_fixed_put(req, key, buf);
@@ -63,11 +68,20 @@ static void bnge_vpd_read_info(struct bnge_dev *bd)
 	kfree(vpd_data);
 }
 
+#define HWRM_FW_VER_STR_LEN	16
+
 static int bnge_devlink_info_get(struct devlink *devlink,
 				 struct devlink_info_req *req,
 				 struct netlink_ext_ack *extack)
 {
+	struct hwrm_nvm_get_dev_info_output nvm_dev_info;
 	struct bnge_dev *bd = devlink_priv(devlink);
+	struct hwrm_ver_get_output *ver_resp;
+	char mgmt_ver[FW_VER_STR_LEN];
+	char roce_ver[FW_VER_STR_LEN];
+	char ncsi_ver[FW_VER_STR_LEN];
+	char buf[32];
+
 	int rc;
 
 	if (bd->dsn) {
@@ -95,6 +109,112 @@ static int bnge_devlink_info_get(struct devlink *devlink,
 			      DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
 			      bd->board_partno);
 
+	/* More information from HWRM ver get command */
+	sprintf(buf, "%X", bd->chip_num);
+	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_FIXED,
+			      DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, buf);
+	if (rc)
+		return rc;
+
+	ver_resp = &bd->ver_resp;
+	sprintf(buf, "%c%d", 'A' + ver_resp->chip_rev, ver_resp->chip_metal);
+	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_FIXED,
+			      DEVLINK_INFO_VERSION_GENERIC_ASIC_REV, buf);
+	if (rc)
+		return rc;
+
+	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
+			      DEVLINK_INFO_VERSION_GENERIC_FW_PSID,
+			      bd->nvm_cfg_ver);
+	if (rc)
+		return rc;
+
+	buf[0] = 0;
+	strncat(buf, ver_resp->active_pkg_name, HWRM_FW_VER_STR_LEN);
+	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
+			      DEVLINK_INFO_VERSION_GENERIC_FW, buf);
+	if (rc)
+		return rc;
+
+	if (ver_resp->flags & VER_GET_RESP_FLAGS_EXT_VER_AVAIL) {
+		snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+			 ver_resp->hwrm_fw_major, ver_resp->hwrm_fw_minor,
+			 ver_resp->hwrm_fw_build, ver_resp->hwrm_fw_patch);
+
+		snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+			 ver_resp->mgmt_fw_major, ver_resp->mgmt_fw_minor,
+			 ver_resp->mgmt_fw_build, ver_resp->mgmt_fw_patch);
+
+		snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+			 ver_resp->roce_fw_major, ver_resp->roce_fw_minor,
+			 ver_resp->roce_fw_build, ver_resp->roce_fw_patch);
+	} else {
+		snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+			 ver_resp->hwrm_fw_maj_8b, ver_resp->hwrm_fw_min_8b,
+			 ver_resp->hwrm_fw_bld_8b, ver_resp->hwrm_fw_rsvd_8b);
+
+		snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+			 ver_resp->mgmt_fw_maj_8b, ver_resp->mgmt_fw_min_8b,
+			 ver_resp->mgmt_fw_bld_8b, ver_resp->mgmt_fw_rsvd_8b);
+
+		snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+			 ver_resp->roce_fw_maj_8b, ver_resp->roce_fw_min_8b,
+			 ver_resp->roce_fw_bld_8b, ver_resp->roce_fw_rsvd_8b);
+	}
+	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
+			      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
+	if (rc)
+		return rc;
+
+	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
+			      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API,
+			      bd->hwrm_ver_supp);
+	if (rc)
+		return rc;
+
+	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
+			      DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver);
+	if (rc)
+		return rc;
+
+	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
+			      DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver);
+	if (rc)
+		return rc;
+
+	rc = bnge_hwrm_nvm_dev_info(bd, &nvm_dev_info);
+	if (!(nvm_dev_info.flags & NVM_GET_DEV_INFO_RESP_FLAGS_FW_VER_VALID))
+		return 0;
+
+	buf[0] = 0;
+	strncat(buf, nvm_dev_info.pkg_name, HWRM_FW_VER_STR_LEN);
+	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
+			      DEVLINK_INFO_VERSION_GENERIC_FW, buf);
+	if (rc)
+		return rc;
+
+	snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+		 nvm_dev_info.hwrm_fw_major, nvm_dev_info.hwrm_fw_minor,
+		 nvm_dev_info.hwrm_fw_build, nvm_dev_info.hwrm_fw_patch);
+	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
+			      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
+	if (rc)
+		return rc;
+
+	snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+		 nvm_dev_info.mgmt_fw_major, nvm_dev_info.mgmt_fw_minor,
+		 nvm_dev_info.mgmt_fw_build, nvm_dev_info.mgmt_fw_patch);
+	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
+			      DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver);
+	if (rc)
+		return rc;
+
+	snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+		 nvm_dev_info.roce_fw_major, nvm_dev_info.roce_fw_minor,
+		 nvm_dev_info.roce_fw_build, nvm_dev_info.roce_fw_patch);
+	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
+			      DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver);
+
 	return rc;
 }
 
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
new file mode 100644
index 000000000000..567376a407df
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2025 Broadcom.
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+
+#include "bnge.h"
+#include "../bnxt/bnxt_hsi.h"
+#include "bnge_hwrm.h"
+#include "bnge_hwrm_lib.h"
+
+int bnge_hwrm_ver_get(struct bnge_dev *bd)
+{
+	u32 dev_caps_cfg, hwrm_ver, hwrm_spec_code;
+	u16 fw_maj, fw_min, fw_bld, fw_rsv;
+	struct hwrm_ver_get_output *resp;
+	struct hwrm_ver_get_input *req;
+	int rc;
+
+	rc = hwrm_req_init(bd, req, HWRM_VER_GET);
+	if (rc)
+		return rc;
+
+	hwrm_req_flags(bd, req, BNGE_HWRM_FULL_WAIT);
+	bd->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
+	req->hwrm_intf_maj = HWRM_VERSION_MAJOR;
+	req->hwrm_intf_min = HWRM_VERSION_MINOR;
+	req->hwrm_intf_upd = HWRM_VERSION_UPDATE;
+
+	resp = hwrm_req_hold(bd, req);
+	rc = hwrm_req_send(bd, req);
+	if (rc)
+		goto hwrm_ver_get_exit;
+
+	memcpy(&bd->ver_resp, resp, sizeof(struct hwrm_ver_get_output));
+
+	hwrm_spec_code = resp->hwrm_intf_maj_8b << 16 |
+			 resp->hwrm_intf_min_8b << 8 |
+			 resp->hwrm_intf_upd_8b;
+	hwrm_ver = HWRM_VERSION_MAJOR << 16 | HWRM_VERSION_MINOR << 8 |
+			HWRM_VERSION_UPDATE;
+
+	if (hwrm_spec_code > hwrm_ver)
+		snprintf(bd->hwrm_ver_supp, FW_VER_STR_LEN, "%d.%d.%d",
+			 HWRM_VERSION_MAJOR, HWRM_VERSION_MINOR,
+			 HWRM_VERSION_UPDATE);
+	else
+		snprintf(bd->hwrm_ver_supp, FW_VER_STR_LEN, "%d.%d.%d",
+			 resp->hwrm_intf_maj_8b, resp->hwrm_intf_min_8b,
+			 resp->hwrm_intf_upd_8b);
+
+	fw_maj = le16_to_cpu(resp->hwrm_fw_major);
+	fw_min = le16_to_cpu(resp->hwrm_fw_minor);
+	fw_bld = le16_to_cpu(resp->hwrm_fw_build);
+	fw_rsv = le16_to_cpu(resp->hwrm_fw_patch);
+
+	bd->fw_ver_code = BNGE_FW_VER_CODE(fw_maj, fw_min, fw_bld, fw_rsv);
+	snprintf(bd->fw_ver_str, FW_VER_STR_LEN, "%d.%d.%d.%d",
+		 fw_maj, fw_min, fw_bld, fw_rsv);
+
+	if (strlen(resp->active_pkg_name)) {
+		int fw_ver_len = strlen(bd->fw_ver_str);
+
+		snprintf(bd->fw_ver_str + fw_ver_len,
+			 FW_VER_STR_LEN - fw_ver_len - 1, "/pkg %s",
+			 resp->active_pkg_name);
+		bd->fw_cap |= BNGE_FW_CAP_PKG_VER;
+	}
+
+	bd->hwrm_cmd_timeout = le16_to_cpu(resp->def_req_timeout);
+	if (!bd->hwrm_cmd_timeout)
+		bd->hwrm_cmd_timeout = DFLT_HWRM_CMD_TIMEOUT;
+	bd->hwrm_cmd_max_timeout = le16_to_cpu(resp->max_req_timeout) * 1000;
+	if (!bd->hwrm_cmd_max_timeout)
+		bd->hwrm_cmd_max_timeout = HWRM_CMD_MAX_TIMEOUT;
+	else if (bd->hwrm_cmd_max_timeout > HWRM_CMD_MAX_TIMEOUT)
+			dev_warn(bd->dev, "Default HWRM commands max timeout increased to %d seconds\n",
+				 bd->hwrm_cmd_max_timeout / 1000);
+
+	bd->hwrm_max_req_len = le16_to_cpu(resp->max_req_win_len);
+	bd->hwrm_max_ext_req_len = le16_to_cpu(resp->max_ext_req_len);
+
+	if (bd->hwrm_max_ext_req_len < HWRM_MAX_REQ_LEN)
+		bd->hwrm_max_ext_req_len = HWRM_MAX_REQ_LEN;
+
+	bd->chip_num = le16_to_cpu(resp->chip_num);
+	bd->chip_rev = resp->chip_rev;
+
+	dev_caps_cfg = le32_to_cpu(resp->dev_caps_cfg);
+	if ((dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
+	    (dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
+		bd->fw_cap |= BNGE_FW_CAP_SHORT_CMD;
+
+	if (dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_KONG_MB_CHNL_SUPPORTED)
+		bd->fw_cap |= BNGE_FW_CAP_KONG_MB_CHNL;
+
+	if (dev_caps_cfg &
+	    VER_GET_RESP_DEV_CAPS_CFG_CFA_ADV_FLOW_MGNT_SUPPORTED)
+		bd->fw_cap |= BNGE_FW_CAP_CFA_ADV_FLOW;
+
+hwrm_ver_get_exit:
+	hwrm_req_drop(bd, req);
+	return rc;
+}
+
+int
+bnge_hwrm_nvm_dev_info(struct bnge_dev *bd,
+		       struct hwrm_nvm_get_dev_info_output *nvm_info)
+{
+	struct hwrm_nvm_get_dev_info_output *resp;
+	struct hwrm_nvm_get_dev_info_input *req;
+	int rc;
+
+	rc = hwrm_req_init(bd, req, HWRM_NVM_GET_DEV_INFO);
+	if (rc)
+		return rc;
+
+	resp = hwrm_req_hold(bd, req);
+	rc = hwrm_req_send(bd, req);
+	if (!rc)
+		memcpy(nvm_info, resp, sizeof(*resp));
+	hwrm_req_drop(bd, req);
+	return rc;
+}
+
+int bnge_hwrm_func_reset(struct bnge_dev *bd)
+{
+	struct hwrm_func_reset_input *req;
+	int rc;
+
+	rc = hwrm_req_init(bd, req, HWRM_FUNC_RESET);
+	if (rc)
+		return rc;
+
+	req->enables = 0;
+	hwrm_req_timeout(bd, req, HWRM_RESET_TIMEOUT);
+	return hwrm_req_send(bd, req);
+}
+
+int bnge_hwrm_fw_set_time(struct bnge_dev *bd)
+{
+	struct hwrm_fw_set_time_input *req;
+	struct tm tm;
+	time64_t now = ktime_get_real_seconds();
+	int rc;
+
+	time64_to_tm(now, 0, &tm);
+	rc = hwrm_req_init(bd, req, HWRM_FW_SET_TIME);
+	if (rc)
+		return rc;
+
+	req->year = cpu_to_le16(1900 + tm.tm_year);
+	req->month = 1 + tm.tm_mon;
+	req->day = tm.tm_mday;
+	req->hour = tm.tm_hour;
+	req->minute = tm.tm_min;
+	req->second = tm.tm_sec;
+	return hwrm_req_send(bd, req);
+}
+
+int bnge_hwrm_func_drv_rgtr(struct bnge_dev *bd)
+{
+	struct hwrm_func_drv_rgtr_output *resp;
+	struct hwrm_func_drv_rgtr_input *req;
+	u32 flags;
+	int rc;
+
+	rc = hwrm_req_init(bd, req, HWRM_FUNC_DRV_RGTR);
+	if (rc)
+		return rc;
+
+	req->enables = cpu_to_le32(FUNC_DRV_RGTR_REQ_ENABLES_OS_TYPE |
+				   FUNC_DRV_RGTR_REQ_ENABLES_VER |
+				   FUNC_DRV_RGTR_REQ_ENABLES_ASYNC_EVENT_FWD);
+
+	req->os_type = cpu_to_le16(FUNC_DRV_RGTR_REQ_OS_TYPE_LINUX);
+	flags = FUNC_DRV_RGTR_REQ_FLAGS_16BIT_VER_MODE;
+
+	req->flags = cpu_to_le32(flags);
+	req->ver_maj_8b = DRV_VER_MAJ;
+	req->ver_min_8b = DRV_VER_MIN;
+	req->ver_upd_8b = DRV_VER_UPD;
+	req->ver_maj = cpu_to_le16(DRV_VER_MAJ);
+	req->ver_min = cpu_to_le16(DRV_VER_MIN);
+	req->ver_upd = cpu_to_le16(DRV_VER_UPD);
+
+	resp = hwrm_req_hold(bd, req);
+	rc = hwrm_req_send(bd, req);
+	if (!rc) {
+		set_bit(BNGE_STATE_DRV_REGISTERED, &bd->state);
+		if (resp->flags &
+		    cpu_to_le32(FUNC_DRV_RGTR_RESP_FLAGS_IF_CHANGE_SUPPORTED))
+			bd->fw_cap |= BNGE_FW_CAP_IF_CHANGE;
+	}
+	hwrm_req_drop(bd, req);
+	return rc;
+}
+
+int bnge_hwrm_func_drv_unrgtr(struct bnge_dev *bd)
+{
+	struct hwrm_func_drv_unrgtr_input *req;
+	int rc;
+
+	if (!test_and_clear_bit(BNGE_STATE_DRV_REGISTERED, &bd->state))
+		return 0;
+
+	rc = hwrm_req_init(bd, req, HWRM_FUNC_DRV_UNRGTR);
+	if (rc)
+		return rc;
+	return hwrm_req_send(bd, req);
+}
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
new file mode 100644
index 000000000000..9308d4fe64d2
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2025 Broadcom */
+
+#ifndef _BNGE_HWRM_LIB_H_
+#define _BNGE_HWRM_LIB_H_
+
+int bnge_hwrm_ver_get(struct bnge_dev *bd);
+int bnge_hwrm_func_reset(struct bnge_dev *bd);
+int bnge_hwrm_fw_set_time(struct bnge_dev *bd);
+int bnge_hwrm_func_drv_rgtr(struct bnge_dev *bd);
+int bnge_hwrm_func_drv_unrgtr(struct bnge_dev *bd);
+int bnge_hwrm_vnic_qcaps(struct bnge_dev *bd);
+int bnge_hwrm_nvm_dev_info(struct bnge_dev *bd,
+			   struct hwrm_nvm_get_dev_info_output *nvm_dev_info);
+
+#endif /* _BNGE_HWRM_LIB_H_ */
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [net-next, 05/10] bng_en: Add ring memory allocation support
  2025-06-18 14:47 [net-next, 00/10] Introducing Broadcom BNGE Ethernet Driver Vikas Gupta
                   ` (3 preceding siblings ...)
  2025-06-18 14:47 ` [net-next, 04/10] bng_en: Add initial interaction with firmware Vikas Gupta
@ 2025-06-18 14:47 ` Vikas Gupta
  2025-06-18 14:47 ` [net-next, 06/10] bng_en: Add backing store support Vikas Gupta
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 37+ messages in thread
From: Vikas Gupta @ 2025-06-18 14:47 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Add ring allocation/free mechanism which help
to allocate rings (TX/RX/Completion) and backing
stores memory on the host for the device.
Future patches will use these functions.

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>
---
 drivers/net/ethernet/broadcom/bnge/Makefile   |   3 +-
 .../net/ethernet/broadcom/bnge/bnge_rmem.c    | 101 ++++++++++++++++++
 .../net/ethernet/broadcom/bnge/bnge_rmem.h    |  35 ++++++
 3 files changed, 138 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_rmem.c
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_rmem.h

diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethernet/broadcom/bnge/Makefile
index b8dbbc2d5972..1144594fc3f6 100644
--- a/drivers/net/ethernet/broadcom/bnge/Makefile
+++ b/drivers/net/ethernet/broadcom/bnge/Makefile
@@ -5,4 +5,5 @@ obj-$(CONFIG_BNGE) += bng_en.o
 bng_en-y := bnge_core.o \
 	    bnge_devlink.o \
 	    bnge_hwrm.o \
-	    bnge_hwrm_lib.o
+	    bnge_hwrm_lib.o \
+	    bnge_rmem.o
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_rmem.c b/drivers/net/ethernet/broadcom/bnge/bnge_rmem.c
new file mode 100644
index 000000000000..ef232c4217bc
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_rmem.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2025 Broadcom.
+
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/crash_dump.h>
+
+#include "bnge.h"
+#include "../bnxt/bnxt_hsi.h"
+#include "bnge_hwrm_lib.h"
+#include "bnge_rmem.h"
+
+void bnge_free_ring(struct bnge_dev *bd, struct bnge_ring_mem_info *rmem)
+{
+	struct pci_dev *pdev = bd->pdev;
+	int i;
+
+	if (!rmem->pg_arr)
+		goto skip_pages;
+
+	for (i = 0; i < rmem->nr_pages; i++) {
+		if (!rmem->pg_arr[i])
+			continue;
+
+		dma_free_coherent(&pdev->dev, rmem->page_size,
+				  rmem->pg_arr[i], rmem->dma_arr[i]);
+
+		rmem->pg_arr[i] = NULL;
+	}
+skip_pages:
+	if (rmem->pg_tbl) {
+		size_t pg_tbl_size = rmem->nr_pages * 8;
+
+		if (rmem->flags & BNGE_RMEM_USE_FULL_PAGE_FLAG)
+			pg_tbl_size = rmem->page_size;
+		dma_free_coherent(&pdev->dev, pg_tbl_size,
+				  rmem->pg_tbl, rmem->dma_pg_tbl);
+		rmem->pg_tbl = NULL;
+	}
+	if (rmem->vmem_size && *rmem->vmem) {
+		vfree(*rmem->vmem);
+		*rmem->vmem = NULL;
+	}
+}
+
+int bnge_alloc_ring(struct bnge_dev *bd, struct bnge_ring_mem_info *rmem)
+{
+	struct pci_dev *pdev = bd->pdev;
+	u64 valid_bit = 0;
+	int i;
+
+	if (rmem->flags & (BNGE_RMEM_VALID_PTE_FLAG | BNGE_RMEM_RING_PTE_FLAG))
+		valid_bit = PTU_PTE_VALID;
+
+	if ((rmem->nr_pages > 1 || rmem->depth > 0) && !rmem->pg_tbl) {
+		size_t pg_tbl_size = rmem->nr_pages * 8;
+
+		if (rmem->flags & BNGE_RMEM_USE_FULL_PAGE_FLAG)
+			pg_tbl_size = rmem->page_size;
+		rmem->pg_tbl = dma_alloc_coherent(&pdev->dev, pg_tbl_size,
+						  &rmem->dma_pg_tbl,
+						  GFP_KERNEL);
+		if (!rmem->pg_tbl)
+			return -ENOMEM;
+	}
+
+	for (i = 0; i < rmem->nr_pages; i++) {
+		u64 extra_bits = valid_bit;
+
+		rmem->pg_arr[i] = dma_alloc_coherent(&pdev->dev,
+						     rmem->page_size,
+						     &rmem->dma_arr[i],
+						     GFP_KERNEL);
+		if (!rmem->pg_arr[i])
+			return -ENOMEM;
+
+		if (rmem->nr_pages > 1 || rmem->depth > 0) {
+			if (i == rmem->nr_pages - 2 &&
+			    (rmem->flags & BNGE_RMEM_RING_PTE_FLAG))
+				extra_bits |= PTU_PTE_NEXT_TO_LAST;
+			else if (i == rmem->nr_pages - 1 &&
+				 (rmem->flags & BNGE_RMEM_RING_PTE_FLAG))
+				extra_bits |= PTU_PTE_LAST;
+			rmem->pg_tbl[i] =
+				cpu_to_le64(rmem->dma_arr[i] | extra_bits);
+		}
+	}
+
+	if (rmem->vmem_size) {
+		*rmem->vmem = vzalloc(rmem->vmem_size);
+		if (!(*rmem->vmem))
+			return -ENOMEM;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_rmem.h b/drivers/net/ethernet/broadcom/bnge/bnge_rmem.h
new file mode 100644
index 000000000000..56de31ed6613
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_rmem.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2025 Broadcom */
+
+#ifndef _BNGE_RMEM_H_
+#define _BNGE_RMEM_H_
+
+#define PTU_PTE_VALID             0x1UL
+#define PTU_PTE_LAST              0x2UL
+#define PTU_PTE_NEXT_TO_LAST      0x4UL
+
+struct bnge_ring_mem_info {
+	/* Number of pages to next level */
+	int			nr_pages;
+	int			page_size;
+	u16			flags;
+#define BNGE_RMEM_VALID_PTE_FLAG	1
+#define BNGE_RMEM_RING_PTE_FLAG		2
+#define BNGE_RMEM_USE_FULL_PAGE_FLAG	4
+
+	u16			depth;
+
+	void			**pg_arr;
+	dma_addr_t		*dma_arr;
+
+	__le64			*pg_tbl;
+	dma_addr_t		dma_pg_tbl;
+
+	int			vmem_size;
+	void			**vmem;
+};
+
+int bnge_alloc_ring(struct bnge_dev *bd, struct bnge_ring_mem_info *rmem);
+void bnge_free_ring(struct bnge_dev *bd, struct bnge_ring_mem_info *rmem);
+
+#endif /* _BNGE_RMEM_H_ */
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [net-next, 06/10] bng_en: Add backing store support
  2025-06-18 14:47 [net-next, 00/10] Introducing Broadcom BNGE Ethernet Driver Vikas Gupta
                   ` (4 preceding siblings ...)
  2025-06-18 14:47 ` [net-next, 05/10] bng_en: Add ring memory allocation support Vikas Gupta
@ 2025-06-18 14:47 ` Vikas Gupta
  2025-06-19 13:02   ` Vadim Fedorenko
  2025-06-18 14:47 ` [net-next, 07/10] bng_en: Add resource management support Vikas Gupta
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 37+ messages in thread
From: Vikas Gupta @ 2025-06-18 14:47 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Backing store or context memory on the host helps the
device to manage rings, stats and other resources.
Context memory is allocated with the help of ring
alloc/free functions.

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>
---
 drivers/net/ethernet/broadcom/bnge/bnge.h     |  18 +
 .../ethernet/broadcom/bnge/bnge_hwrm_lib.c    | 168 +++++++++
 .../ethernet/broadcom/bnge/bnge_hwrm_lib.h    |   4 +
 .../net/ethernet/broadcom/bnge/bnge_rmem.c    | 337 ++++++++++++++++++
 .../net/ethernet/broadcom/bnge/bnge_rmem.h    | 153 ++++++++
 5 files changed, 680 insertions(+)

diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
index 60af0517c45e..01f64a10729c 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
@@ -9,6 +9,7 @@
 
 #include <linux/etherdevice.h>
 #include "../bnxt/bnxt_hsi.h"
+#include "bnge_rmem.h"
 
 #define DRV_VER_MAJ	1
 #define DRV_VER_MIN	15
@@ -52,6 +53,13 @@ enum {
 	BNGE_FW_CAP_VNIC_RE_FLUSH			= BIT_ULL(26),
 };
 
+enum {
+	BNGE_EN_ROCE_V1					= BIT_ULL(0),
+	BNGE_EN_ROCE_V2					= BIT_ULL(1),
+};
+
+#define BNGE_EN_ROCE		(BNGE_EN_ROCE_V1 | BNGE_EN_ROCE_V2)
+
 struct bnge_dev {
 	struct device	*dev;
 	struct pci_dev	*pdev;
@@ -89,6 +97,16 @@ struct bnge_dev {
 #define BNGE_STATE_DRV_REGISTERED      0
 
 	u64			fw_cap;
+
+	/* Backing stores */
+	struct bnge_ctx_mem_info	*ctx;
+
+	u64			flags;
 };
 
+static inline bool bnge_is_roce_en(struct bnge_dev *bd)
+{
+	return bd->flags & BNGE_EN_ROCE;
+}
+
 #endif /* _BNGE_H_ */
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
index 567376a407df..e5f32ac8a69f 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
@@ -10,6 +10,7 @@
 #include "../bnxt/bnxt_hsi.h"
 #include "bnge_hwrm.h"
 #include "bnge_hwrm_lib.h"
+#include "bnge_rmem.h"
 
 int bnge_hwrm_ver_get(struct bnge_dev *bd)
 {
@@ -211,3 +212,170 @@ int bnge_hwrm_func_drv_unrgtr(struct bnge_dev *bd)
 		return rc;
 	return hwrm_req_send(bd, req);
 }
+
+static void bnge_init_ctx_initializer(struct bnge_ctx_mem_type *ctxm,
+				      u8 init_val, u8 init_offset,
+				      bool init_mask_set)
+{
+	ctxm->init_value = init_val;
+	ctxm->init_offset = BNGE_CTX_INIT_INVALID_OFFSET;
+	if (init_mask_set)
+		ctxm->init_offset = init_offset * 4;
+	else
+		ctxm->init_value = 0;
+}
+
+static int bnge_alloc_all_ctx_pg_info(struct bnge_dev *bd, int ctx_max)
+{
+	struct bnge_ctx_mem_info *ctx = bd->ctx;
+	u16 type;
+
+	for (type = 0; type < ctx_max; type++) {
+		struct bnge_ctx_mem_type *ctxm = &ctx->ctx_arr[type];
+		int n = 1;
+
+		if (!ctxm->max_entries)
+			continue;
+
+		if (ctxm->instance_bmap)
+			n = hweight32(ctxm->instance_bmap);
+		ctxm->pg_info = kcalloc(n, sizeof(*ctxm->pg_info), GFP_KERNEL);
+		if (!ctxm->pg_info)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+
+#define BNGE_CTX_INIT_VALID(flags)	\
+	(!!((flags) &			\
+	    FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_ENABLE_CTX_KIND_INIT))
+
+int bnge_hwrm_func_backing_store_qcaps(struct bnge_dev *bd)
+{
+	struct hwrm_func_backing_store_qcaps_v2_output *resp;
+	struct hwrm_func_backing_store_qcaps_v2_input *req;
+	struct bnge_ctx_mem_info *ctx;
+	u16 type;
+	int rc;
+
+	if (bd->ctx)
+		return 0;
+
+	rc = hwrm_req_init(bd, req, HWRM_FUNC_BACKING_STORE_QCAPS_V2);
+	if (rc)
+		return rc;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+	bd->ctx = ctx;
+
+	resp = hwrm_req_hold(bd, req);
+
+	for (type = 0; type < BNGE_CTX_V2_MAX; ) {
+		struct bnge_ctx_mem_type *ctxm = &ctx->ctx_arr[type];
+		u8 init_val, init_off, i;
+		__le32 *p;
+		u32 flags;
+
+		req->type = cpu_to_le16(type);
+		rc = hwrm_req_send(bd, req);
+		if (rc)
+			goto ctx_done;
+		flags = le32_to_cpu(resp->flags);
+		type = le16_to_cpu(resp->next_valid_type);
+		if (!(flags &
+		      FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_TYPE_VALID))
+			continue;
+
+		ctxm->type = le16_to_cpu(resp->type);
+		ctxm->entry_size = le16_to_cpu(resp->entry_size);
+		ctxm->flags = flags;
+		ctxm->instance_bmap = le32_to_cpu(resp->instance_bit_map);
+		ctxm->entry_multiple = resp->entry_multiple;
+		ctxm->max_entries = le32_to_cpu(resp->max_num_entries);
+		ctxm->min_entries = le32_to_cpu(resp->min_num_entries);
+		init_val = resp->ctx_init_value;
+		init_off = resp->ctx_init_offset;
+		bnge_init_ctx_initializer(ctxm, init_val, init_off,
+					  BNGE_CTX_INIT_VALID(flags));
+		ctxm->split_entry_cnt = min_t(u8, resp->subtype_valid_cnt,
+					      BNGE_MAX_SPLIT_ENTRY);
+		for (i = 0, p = &resp->split_entry_0; i < ctxm->split_entry_cnt;
+		     i++, p++)
+			ctxm->split[i] = le32_to_cpu(*p);
+	}
+	rc = bnge_alloc_all_ctx_pg_info(bd, BNGE_CTX_V2_MAX);
+
+ctx_done:
+	hwrm_req_drop(bd, req);
+	return rc;
+}
+
+static void bnge_hwrm_set_pg_attr(struct bnge_ring_mem_info *rmem, u8 *pg_attr,
+				  __le64 *pg_dir)
+{
+	if (!rmem->nr_pages)
+		return;
+
+	BNGE_SET_CTX_PAGE_ATTR(*pg_attr);
+	if (rmem->depth >= 1) {
+		if (rmem->depth == 2)
+			*pg_attr |= 2;
+		else
+			*pg_attr |= 1;
+		*pg_dir = cpu_to_le64(rmem->dma_pg_tbl);
+	} else {
+		*pg_dir = cpu_to_le64(rmem->dma_arr[0]);
+	}
+}
+
+int bnge_hwrm_func_backing_store(struct bnge_dev *bd,
+				 struct bnge_ctx_mem_type *ctxm,
+				 bool last)
+{
+	struct hwrm_func_backing_store_cfg_v2_input *req;
+	u32 instance_bmap = ctxm->instance_bmap;
+	int i, j, rc = 0, n = 1;
+	__le32 *p;
+
+	if (!(ctxm->flags & BNGE_CTX_MEM_TYPE_VALID) || !ctxm->pg_info)
+		return 0;
+
+	if (instance_bmap)
+		n = hweight32(ctxm->instance_bmap);
+	else
+		instance_bmap = 1;
+
+	rc = hwrm_req_init(bd, req, HWRM_FUNC_BACKING_STORE_CFG_V2);
+	if (rc)
+		return rc;
+	hwrm_req_hold(bd, req);
+	req->type = cpu_to_le16(ctxm->type);
+	req->entry_size = cpu_to_le16(ctxm->entry_size);
+	req->subtype_valid_cnt = ctxm->split_entry_cnt;
+	for (i = 0, p = &req->split_entry_0; i < ctxm->split_entry_cnt; i++)
+		p[i] = cpu_to_le32(ctxm->split[i]);
+	for (i = 0, j = 0; j < n && !rc; i++) {
+		struct bnge_ctx_pg_info *ctx_pg;
+
+		if (!(instance_bmap & (1 << i)))
+			continue;
+		req->instance = cpu_to_le16(i);
+		ctx_pg = &ctxm->pg_info[j++];
+		if (!ctx_pg->entries)
+			continue;
+		req->num_entries = cpu_to_le32(ctx_pg->entries);
+		bnge_hwrm_set_pg_attr(&ctx_pg->ring_mem,
+				      &req->page_size_pbl_level,
+				      &req->page_dir);
+		if (last && j == n)
+			req->flags =
+				cpu_to_le32(BNGE_BS_CFG_ALL_DONE);
+		rc = hwrm_req_send(bd, req);
+	}
+	hwrm_req_drop(bd, req);
+
+	return rc;
+}
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
index 9308d4fe64d2..c04291d74bf0 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
@@ -12,5 +12,9 @@ int bnge_hwrm_func_drv_unrgtr(struct bnge_dev *bd);
 int bnge_hwrm_vnic_qcaps(struct bnge_dev *bd);
 int bnge_hwrm_nvm_dev_info(struct bnge_dev *bd,
 			   struct hwrm_nvm_get_dev_info_output *nvm_dev_info);
+int bnge_hwrm_func_backing_store(struct bnge_dev *bd,
+				 struct bnge_ctx_mem_type *ctxm,
+				 bool last);
+int bnge_hwrm_func_backing_store_qcaps(struct bnge_dev *bd);
 
 #endif /* _BNGE_HWRM_LIB_H_ */
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_rmem.c b/drivers/net/ethernet/broadcom/bnge/bnge_rmem.c
index ef232c4217bc..0e935cc46da6 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_rmem.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_rmem.c
@@ -15,6 +15,24 @@
 #include "bnge_hwrm_lib.h"
 #include "bnge_rmem.h"
 
+static void bnge_init_ctx_mem(struct bnge_ctx_mem_type *ctxm,
+			      void *p, int len)
+{
+	u8 init_val = ctxm->init_value;
+	u16 offset = ctxm->init_offset;
+	u8 *p2 = p;
+	int i;
+
+	if (!init_val)
+		return;
+	if (offset == BNGE_CTX_INIT_INVALID_OFFSET) {
+		memset(p, init_val, len);
+		return;
+	}
+	for (i = 0; i < len; i += ctxm->entry_size)
+		*(p2 + i + offset) = init_val;
+}
+
 void bnge_free_ring(struct bnge_dev *bd, struct bnge_ring_mem_info *rmem)
 {
 	struct pci_dev *pdev = bd->pdev;
@@ -79,6 +97,10 @@ int bnge_alloc_ring(struct bnge_dev *bd, struct bnge_ring_mem_info *rmem)
 		if (!rmem->pg_arr[i])
 			return -ENOMEM;
 
+		if (rmem->ctx_mem)
+			bnge_init_ctx_mem(rmem->ctx_mem, rmem->pg_arr[i],
+					  rmem->page_size);
+
 		if (rmem->nr_pages > 1 || rmem->depth > 0) {
 			if (i == rmem->nr_pages - 2 &&
 			    (rmem->flags & BNGE_RMEM_RING_PTE_FLAG))
@@ -99,3 +121,318 @@ int bnge_alloc_ring(struct bnge_dev *bd, struct bnge_ring_mem_info *rmem)
 
 	return 0;
 }
+
+static int bnge_alloc_ctx_one_lvl(struct bnge_dev *bd,
+				  struct bnge_ctx_pg_info *ctx_pg)
+{
+	struct bnge_ring_mem_info *rmem = &ctx_pg->ring_mem;
+
+	rmem->page_size = BNGE_PAGE_SIZE;
+	rmem->pg_arr = ctx_pg->ctx_pg_arr;
+	rmem->dma_arr = ctx_pg->ctx_dma_arr;
+	rmem->flags = BNGE_RMEM_VALID_PTE_FLAG;
+	if (rmem->depth >= 1)
+		rmem->flags |= BNGE_RMEM_USE_FULL_PAGE_FLAG;
+	return bnge_alloc_ring(bd, rmem);
+}
+
+static int bnge_alloc_ctx_pg_tbls(struct bnge_dev *bd,
+				  struct bnge_ctx_pg_info *ctx_pg, u32 mem_size,
+				  u8 depth, struct bnge_ctx_mem_type *ctxm)
+{
+	struct bnge_ring_mem_info *rmem = &ctx_pg->ring_mem;
+	int rc;
+
+	if (!mem_size)
+		return -EINVAL;
+
+	ctx_pg->nr_pages = DIV_ROUND_UP(mem_size, BNGE_PAGE_SIZE);
+	if (ctx_pg->nr_pages > MAX_CTX_TOTAL_PAGES) {
+		ctx_pg->nr_pages = 0;
+		return -EINVAL;
+	}
+	if (ctx_pg->nr_pages > MAX_CTX_PAGES || depth > 1) {
+		int nr_tbls, i;
+
+		rmem->depth = 2;
+		ctx_pg->ctx_pg_tbl = kcalloc(MAX_CTX_PAGES, sizeof(ctx_pg),
+					     GFP_KERNEL);
+		if (!ctx_pg->ctx_pg_tbl)
+			return -ENOMEM;
+		nr_tbls = DIV_ROUND_UP(ctx_pg->nr_pages, MAX_CTX_PAGES);
+		rmem->nr_pages = nr_tbls;
+		rc = bnge_alloc_ctx_one_lvl(bd, ctx_pg);
+		if (rc)
+			return rc;
+		for (i = 0; i < nr_tbls; i++) {
+			struct bnge_ctx_pg_info *pg_tbl;
+
+			pg_tbl = kzalloc(sizeof(*pg_tbl), GFP_KERNEL);
+			if (!pg_tbl)
+				return -ENOMEM;
+			ctx_pg->ctx_pg_tbl[i] = pg_tbl;
+			rmem = &pg_tbl->ring_mem;
+			rmem->pg_tbl = ctx_pg->ctx_pg_arr[i];
+			rmem->dma_pg_tbl = ctx_pg->ctx_dma_arr[i];
+			rmem->depth = 1;
+			rmem->nr_pages = MAX_CTX_PAGES;
+			rmem->ctx_mem = ctxm;
+			if (i == (nr_tbls - 1)) {
+				int rem = ctx_pg->nr_pages % MAX_CTX_PAGES;
+
+				if (rem)
+					rmem->nr_pages = rem;
+			}
+			rc = bnge_alloc_ctx_one_lvl(bd, pg_tbl);
+			if (rc)
+				break;
+		}
+	} else {
+		rmem->nr_pages = DIV_ROUND_UP(mem_size, BNGE_PAGE_SIZE);
+		if (rmem->nr_pages > 1 || depth)
+			rmem->depth = 1;
+		rmem->ctx_mem = ctxm;
+		rc = bnge_alloc_ctx_one_lvl(bd, ctx_pg);
+	}
+
+	return rc;
+}
+
+static void bnge_free_ctx_pg_tbls(struct bnge_dev *bd,
+				  struct bnge_ctx_pg_info *ctx_pg)
+{
+	struct bnge_ring_mem_info *rmem = &ctx_pg->ring_mem;
+
+	if (rmem->depth > 1 || ctx_pg->nr_pages > MAX_CTX_PAGES ||
+	    ctx_pg->ctx_pg_tbl) {
+		int i, nr_tbls = rmem->nr_pages;
+
+		for (i = 0; i < nr_tbls; i++) {
+			struct bnge_ctx_pg_info *pg_tbl;
+			struct bnge_ring_mem_info *rmem2;
+
+			pg_tbl = ctx_pg->ctx_pg_tbl[i];
+			if (!pg_tbl)
+				continue;
+			rmem2 = &pg_tbl->ring_mem;
+			bnge_free_ring(bd, rmem2);
+			ctx_pg->ctx_pg_arr[i] = NULL;
+			kfree(pg_tbl);
+			ctx_pg->ctx_pg_tbl[i] = NULL;
+		}
+		kfree(ctx_pg->ctx_pg_tbl);
+		ctx_pg->ctx_pg_tbl = NULL;
+	}
+	bnge_free_ring(bd, rmem);
+	ctx_pg->nr_pages = 0;
+}
+
+static int bnge_setup_ctxm_pg_tbls(struct bnge_dev *bd,
+				   struct bnge_ctx_mem_type *ctxm, u32 entries,
+				   u8 pg_lvl)
+{
+	struct bnge_ctx_pg_info *ctx_pg = ctxm->pg_info;
+	int i, rc = 0, n = 1;
+	u32 mem_size;
+
+	if (!ctxm->entry_size || !ctx_pg)
+		return -EINVAL;
+	if (ctxm->instance_bmap)
+		n = hweight32(ctxm->instance_bmap);
+	if (ctxm->entry_multiple)
+		entries = roundup(entries, ctxm->entry_multiple);
+	entries = clamp_t(u32, entries, ctxm->min_entries, ctxm->max_entries);
+	mem_size = entries * ctxm->entry_size;
+	for (i = 0; i < n && !rc; i++) {
+		ctx_pg[i].entries = entries;
+		rc = bnge_alloc_ctx_pg_tbls(bd, &ctx_pg[i], mem_size, pg_lvl,
+					    ctxm->init_value ? ctxm : NULL);
+	}
+
+	return rc;
+}
+
+static int bnge_backing_store_cfg(struct bnge_dev *bd, u32 ena)
+{
+	struct bnge_ctx_mem_info *ctx = bd->ctx;
+	struct bnge_ctx_mem_type *ctxm;
+	u16 last_type;
+	int rc = 0;
+	u16 type;
+
+	if (!ena)
+		return 0;
+	else if (ena & FUNC_BACKING_STORE_CFG_REQ_ENABLES_TIM)
+		last_type = BNGE_CTX_MAX - 1;
+	else
+		last_type = BNGE_CTX_L2_MAX - 1;
+	ctx->ctx_arr[last_type].last = 1;
+
+	for (type = 0 ; type < BNGE_CTX_V2_MAX; type++) {
+		ctxm = &ctx->ctx_arr[type];
+
+		rc = bnge_hwrm_func_backing_store(bd, ctxm, ctxm->last);
+		if (rc)
+			return rc;
+	}
+
+	return 0;
+}
+
+void bnge_free_ctx_mem(struct bnge_dev *bd)
+{
+	struct bnge_ctx_mem_info *ctx = bd->ctx;
+	u16 type;
+
+	if (!ctx)
+		return;
+
+	for (type = 0; type < BNGE_CTX_V2_MAX; type++) {
+		struct bnge_ctx_mem_type *ctxm = &ctx->ctx_arr[type];
+		struct bnge_ctx_pg_info *ctx_pg = ctxm->pg_info;
+		int i, n = 1;
+
+		if (!ctx_pg)
+			continue;
+		if (ctxm->instance_bmap)
+			n = hweight32(ctxm->instance_bmap);
+		for (i = 0; i < n; i++)
+			bnge_free_ctx_pg_tbls(bd, &ctx_pg[i]);
+
+		kfree(ctx_pg);
+		ctxm->pg_info = NULL;
+	}
+
+	ctx->flags &= ~BNGE_CTX_FLAG_INITED;
+	kfree(ctx);
+	bd->ctx = NULL;
+}
+
+#define FUNC_BACKING_STORE_CFG_REQ_DFLT_ENABLES			\
+	(FUNC_BACKING_STORE_CFG_REQ_ENABLES_QP |		\
+	 FUNC_BACKING_STORE_CFG_REQ_ENABLES_SRQ |		\
+	 FUNC_BACKING_STORE_CFG_REQ_ENABLES_CQ |		\
+	 FUNC_BACKING_STORE_CFG_REQ_ENABLES_VNIC |		\
+	 FUNC_BACKING_STORE_CFG_REQ_ENABLES_STAT)
+
+int bnge_alloc_ctx_mem(struct bnge_dev *bd)
+{
+	struct bnge_ctx_mem_type *ctxm;
+	struct bnge_ctx_mem_info *ctx;
+	u32 l2_qps, qp1_qps, max_qps;
+	u32 ena, entries_sp, entries;
+	u32 srqs, max_srqs, min;
+	u32 num_mr, num_ah;
+	u32 extra_srqs = 0;
+	u32 extra_qps = 0;
+	u32 fast_qpmd_qps;
+	u8 pg_lvl = 1;
+	int i, rc;
+
+	rc = bnge_hwrm_func_backing_store_qcaps(bd);
+	if (rc) {
+		dev_err(bd->dev, "Failed querying ctx mem caps, rc: %d\n", rc);
+		return rc;
+	}
+
+	ctx = bd->ctx;
+	if (!ctx || (ctx->flags & BNGE_CTX_FLAG_INITED))
+		return 0;
+
+	ctxm = &ctx->ctx_arr[BNGE_CTX_QP];
+	l2_qps = ctxm->qp_l2_entries;
+	qp1_qps = ctxm->qp_qp1_entries;
+	fast_qpmd_qps = ctxm->qp_fast_qpmd_entries;
+	max_qps = ctxm->max_entries;
+	ctxm = &ctx->ctx_arr[BNGE_CTX_SRQ];
+	srqs = ctxm->srq_l2_entries;
+	max_srqs = ctxm->max_entries;
+	ena = 0;
+	if (bnge_is_roce_en(bd) && !is_kdump_kernel()) {
+		pg_lvl = 2;
+		extra_qps = min_t(u32, 65536, max_qps - l2_qps - qp1_qps);
+		/* allocate extra qps if fast qp destroy feature enabled */
+		extra_qps += fast_qpmd_qps;
+		extra_srqs = min_t(u32, 8192, max_srqs - srqs);
+		if (fast_qpmd_qps)
+			ena |= FUNC_BACKING_STORE_CFG_REQ_ENABLES_QP_FAST_QPMD;
+	}
+
+	ctxm = &ctx->ctx_arr[BNGE_CTX_QP];
+	rc = bnge_setup_ctxm_pg_tbls(bd, ctxm, l2_qps + qp1_qps + extra_qps,
+				     pg_lvl);
+	if (rc)
+		return rc;
+
+	ctxm = &ctx->ctx_arr[BNGE_CTX_SRQ];
+	rc = bnge_setup_ctxm_pg_tbls(bd, ctxm, srqs + extra_srqs, pg_lvl);
+	if (rc)
+		return rc;
+
+	ctxm = &ctx->ctx_arr[BNGE_CTX_CQ];
+	rc = bnge_setup_ctxm_pg_tbls(bd, ctxm, ctxm->cq_l2_entries +
+				     extra_qps * 2, pg_lvl);
+	if (rc)
+		return rc;
+
+	ctxm = &ctx->ctx_arr[BNGE_CTX_VNIC];
+	rc = bnge_setup_ctxm_pg_tbls(bd, ctxm, ctxm->max_entries, 1);
+	if (rc)
+		return rc;
+
+	ctxm = &ctx->ctx_arr[BNGE_CTX_STAT];
+	rc = bnge_setup_ctxm_pg_tbls(bd, ctxm, ctxm->max_entries, 1);
+	if (rc)
+		return rc;
+
+	if (!bnge_is_roce_en(bd))
+		goto skip_rdma;
+
+	ctxm = &ctx->ctx_arr[BNGE_CTX_MRAV];
+	/* 128K extra is needed to accommodate static AH context
+	 * allocation by f/w.
+	 */
+	num_mr = min_t(u32, ctxm->max_entries / 2, 1024 * 256);
+	num_ah = min_t(u32, num_mr, 1024 * 128);
+	ctxm->split_entry_cnt = BNGE_CTX_MRAV_AV_SPLIT_ENTRY + 1;
+	if (!ctxm->mrav_av_entries || ctxm->mrav_av_entries > num_ah)
+		ctxm->mrav_av_entries = num_ah;
+
+	rc = bnge_setup_ctxm_pg_tbls(bd, ctxm, num_mr + num_ah, 2);
+	if (rc)
+		return rc;
+	ena |= FUNC_BACKING_STORE_CFG_REQ_ENABLES_MRAV;
+
+	ctxm = &ctx->ctx_arr[BNGE_CTX_TIM];
+	rc = bnge_setup_ctxm_pg_tbls(bd, ctxm, l2_qps + qp1_qps + extra_qps, 1);
+	if (rc)
+		return rc;
+	ena |= FUNC_BACKING_STORE_CFG_REQ_ENABLES_TIM;
+
+skip_rdma:
+	ctxm = &ctx->ctx_arr[BNGE_CTX_STQM];
+	min = ctxm->min_entries;
+	entries_sp = ctx->ctx_arr[BNGE_CTX_VNIC].vnic_entries + l2_qps +
+		     2 * (extra_qps + qp1_qps) + min;
+	rc = bnge_setup_ctxm_pg_tbls(bd, ctxm, entries_sp, 2);
+	if (rc)
+		return rc;
+
+	ctxm = &ctx->ctx_arr[BNGE_CTX_FTQM];
+	entries = l2_qps + 2 * (extra_qps + qp1_qps);
+	rc = bnge_setup_ctxm_pg_tbls(bd, ctxm, entries, 2);
+	if (rc)
+		return rc;
+	for (i = 0; i < ctx->tqm_fp_rings_count + 1; i++)
+		ena |= FUNC_BACKING_STORE_CFG_REQ_ENABLES_TQM_SP << i;
+	ena |= FUNC_BACKING_STORE_CFG_REQ_DFLT_ENABLES;
+
+	rc = bnge_backing_store_cfg(bd, ena);
+	if (rc) {
+		dev_err(bd->dev, "Failed configuring ctx mem, rc: %d\n", rc);
+		return rc;
+	}
+	ctx->flags |= BNGE_CTX_FLAG_INITED;
+
+	return 0;
+}
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_rmem.h b/drivers/net/ethernet/broadcom/bnge/bnge_rmem.h
index 56de31ed6613..300f1d8268ef 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_rmem.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_rmem.h
@@ -4,6 +4,9 @@
 #ifndef _BNGE_RMEM_H_
 #define _BNGE_RMEM_H_
 
+struct bnge_ctx_mem_type;
+struct bnge_dev;
+
 #define PTU_PTE_VALID             0x1UL
 #define PTU_PTE_LAST              0x2UL
 #define PTU_PTE_NEXT_TO_LAST      0x4UL
@@ -27,9 +30,159 @@ struct bnge_ring_mem_info {
 
 	int			vmem_size;
 	void			**vmem;
+
+	struct bnge_ctx_mem_type	*ctx_mem;
+};
+
+/* The hardware supports certain page sizes.
+ * Use the supported page sizes to allocate the rings.
+ */
+#if (PAGE_SHIFT < 12)
+#define BNGE_PAGE_SHIFT	12
+#elif (PAGE_SHIFT <= 13)
+#define BNGE_PAGE_SHIFT	PAGE_SHIFT
+#elif (PAGE_SHIFT < 16)
+#define BNGE_PAGE_SHIFT	13
+#else
+#define BNGE_PAGE_SHIFT	16
+#endif
+#define BNGE_PAGE_SIZE	(1 << BNGE_PAGE_SHIFT)
+/* The RXBD length is 16-bit so we can only support page sizes < 64K */
+#if (PAGE_SHIFT > 15)
+#define BNGE_RX_PAGE_SHIFT 15
+#else
+#define BNGE_RX_PAGE_SHIFT PAGE_SHIFT
+#endif
+#define MAX_CTX_PAGES	(BNGE_PAGE_SIZE / 8)
+#define MAX_CTX_TOTAL_PAGES	(MAX_CTX_PAGES * MAX_CTX_PAGES)
+
+struct bnge_ctx_pg_info {
+	u32		entries;
+	u32		nr_pages;
+	void		*ctx_pg_arr[MAX_CTX_PAGES];
+	dma_addr_t	ctx_dma_arr[MAX_CTX_PAGES];
+	struct bnge_ring_mem_info ring_mem;
+	struct bnge_ctx_pg_info **ctx_pg_tbl;
+};
+
+#define BNGE_MAX_TQM_SP_RINGS		1
+#define BNGE_MAX_TQM_FP_RINGS		8
+#define BNGE_MAX_TQM_RINGS		\
+	(BNGE_MAX_TQM_SP_RINGS + BNGE_MAX_TQM_FP_RINGS)
+#define BNGE_BACKING_STORE_CFG_LEGACY_LEN	256
+#define BNGE_SET_CTX_PAGE_ATTR(attr)					\
+do {									\
+	if (BNGE_PAGE_SIZE == 0x2000)					\
+		attr = FUNC_BACKING_STORE_CFG_REQ_SRQ_PG_SIZE_PG_8K;	\
+	else if (BNGE_PAGE_SIZE == 0x10000)				\
+		attr = FUNC_BACKING_STORE_CFG_REQ_QPC_PG_SIZE_PG_64K;	\
+	else								\
+		attr = FUNC_BACKING_STORE_CFG_REQ_QPC_PG_SIZE_PG_4K;	\
+} while (0)
+
+#define BNGE_CTX_MRAV_AV_SPLIT_ENTRY	0
+
+#define BNGE_CTX_QP	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_QP
+#define BNGE_CTX_SRQ	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_SRQ
+#define BNGE_CTX_CQ	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CQ
+#define BNGE_CTX_VNIC	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_VNIC
+#define BNGE_CTX_STAT	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_STAT
+#define BNGE_CTX_STQM	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_SP_TQM_RING
+#define BNGE_CTX_FTQM	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_FP_TQM_RING
+#define BNGE_CTX_MRAV	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_MRAV
+#define BNGE_CTX_TIM	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_TIM
+#define BNGE_CTX_TCK	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_TX_CK
+#define BNGE_CTX_RCK	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_RX_CK
+#define BNGE_CTX_MTQM	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_MP_TQM_RING
+#define BNGE_CTX_SQDBS	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_SQ_DB_SHADOW
+#define BNGE_CTX_RQDBS	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_RQ_DB_SHADOW
+#define BNGE_CTX_SRQDBS	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_SRQ_DB_SHADOW
+#define BNGE_CTX_CQDBS	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CQ_DB_SHADOW
+#define BNGE_CTX_SRT_TRACE	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_SRT_TRACE
+#define BNGE_CTX_SRT2_TRACE	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_SRT2_TRACE
+#define BNGE_CTX_CRT_TRACE	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CRT_TRACE
+#define BNGE_CTX_CRT2_TRACE	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CRT2_TRACE
+#define BNGE_CTX_RIGP0_TRACE	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_RIGP0_TRACE
+#define BNGE_CTX_L2_HWRM_TRACE	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_L2_HWRM_TRACE
+#define BNGE_CTX_ROCE_HWRM_TRACE	\
+	FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_ROCE_HWRM_TRACE
+
+#define BNGE_CTX_MAX		(BNGE_CTX_TIM + 1)
+#define BNGE_CTX_L2_MAX		(BNGE_CTX_FTQM + 1)
+#define BNGE_CTX_INV		((u16)-1)
+
+#define BNGE_CTX_V2_MAX	\
+	(FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_ROCE_HWRM_TRACE + 1)
+
+#define BNGE_BS_CFG_ALL_DONE	\
+	FUNC_BACKING_STORE_CFG_V2_REQ_FLAGS_BS_CFG_ALL_DONE
+
+struct bnge_ctx_mem_type {
+	u16	type;
+	u16	entry_size;
+	u32	flags;
+#define BNGE_CTX_MEM_TYPE_VALID	\
+	FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_TYPE_VALID
+	u32	instance_bmap;
+	u8	init_value;
+	u8	entry_multiple;
+	u16	init_offset;
+#define	BNGE_CTX_INIT_INVALID_OFFSET	0xffff
+	u32	max_entries;
+	u32	min_entries;
+	u8	last:1;
+	u8	split_entry_cnt;
+#define BNGE_MAX_SPLIT_ENTRY	4
+	union {
+		struct {
+			u32	qp_l2_entries;
+			u32	qp_qp1_entries;
+			u32	qp_fast_qpmd_entries;
+		};
+		u32	srq_l2_entries;
+		u32	cq_l2_entries;
+		u32	vnic_entries;
+		struct {
+			u32	mrav_av_entries;
+			u32	mrav_num_entries_units;
+		};
+		u32	split[BNGE_MAX_SPLIT_ENTRY];
+	};
+	struct bnge_ctx_pg_info	*pg_info;
+};
+
+struct bnge_ctx_mem_info {
+	u8	tqm_fp_rings_count;
+	u32	flags;
+#define BNGE_CTX_FLAG_INITED	0x01
+	struct bnge_ctx_mem_type	ctx_arr[BNGE_CTX_V2_MAX];
 };
 
 int bnge_alloc_ring(struct bnge_dev *bd, struct bnge_ring_mem_info *rmem);
 void bnge_free_ring(struct bnge_dev *bd, struct bnge_ring_mem_info *rmem);
+int bnge_alloc_ctx_mem(struct bnge_dev *bd);
+void bnge_free_ctx_mem(struct bnge_dev *bd);
 
 #endif /* _BNGE_RMEM_H_ */
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [net-next, 07/10] bng_en: Add resource management support
  2025-06-18 14:47 [net-next, 00/10] Introducing Broadcom BNGE Ethernet Driver Vikas Gupta
                   ` (5 preceding siblings ...)
  2025-06-18 14:47 ` [net-next, 06/10] bng_en: Add backing store support Vikas Gupta
@ 2025-06-18 14:47 ` Vikas Gupta
  2025-06-19 13:39   ` Vadim Fedorenko
  2025-06-18 14:47 ` [net-next, 08/10] bng_en: Add irq allocation support Vikas Gupta
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 37+ messages in thread
From: Vikas Gupta @ 2025-06-18 14:47 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Get the resources and capabilities from the firmware.
Add functions to manage the resources with the firmware.
These functions will help netdev reserve the resources
with the firmware before registering the device in future
patches. The resources and their information, such as
the maximum available and reserved, are part of the members
present in the bnge_hw_resc struct.
The bnge_reserve_rings() function also populates
the RSS table entries once the RX rings are reserved with
the firmware.

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>
---
 drivers/net/ethernet/broadcom/bnge/Makefile   |   3 +-
 drivers/net/ethernet/broadcom/bnge/bnge.h     |  77 ++++
 .../net/ethernet/broadcom/bnge/bnge_core.c    |   5 +
 .../net/ethernet/broadcom/bnge/bnge_hwrm.h    |  10 +
 .../ethernet/broadcom/bnge/bnge_hwrm_lib.c    | 268 ++++++++++++++
 .../ethernet/broadcom/bnge/bnge_hwrm_lib.h    |   6 +
 .../net/ethernet/broadcom/bnge/bnge_resc.c    | 328 ++++++++++++++++++
 .../net/ethernet/broadcom/bnge/bnge_resc.h    |  75 ++++
 8 files changed, 771 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_resc.c
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_resc.h

diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethernet/broadcom/bnge/Makefile
index 1144594fc3f6..10df05b6695e 100644
--- a/drivers/net/ethernet/broadcom/bnge/Makefile
+++ b/drivers/net/ethernet/broadcom/bnge/Makefile
@@ -6,4 +6,5 @@ bng_en-y := bnge_core.o \
 	    bnge_devlink.o \
 	    bnge_hwrm.o \
 	    bnge_hwrm_lib.o \
-	    bnge_rmem.o
+	    bnge_rmem.o \
+	    bnge_resc.o
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
index 01f64a10729c..b58d8fc6f258 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
@@ -10,6 +10,7 @@
 #include <linux/etherdevice.h>
 #include "../bnxt/bnxt_hsi.h"
 #include "bnge_rmem.h"
+#include "bnge_resc.h"
 
 #define DRV_VER_MAJ	1
 #define DRV_VER_MIN	15
@@ -21,6 +22,12 @@ enum board_idx {
 	BCM57708,
 };
 
+struct bnge_pf_info {
+	u16	fw_fid;
+	u16	port_id;
+	u8	mac_addr[ETH_ALEN];
+};
+
 #define INVALID_HW_RING_ID      ((u16)-1)
 
 enum {
@@ -56,10 +63,23 @@ enum {
 enum {
 	BNGE_EN_ROCE_V1					= BIT_ULL(0),
 	BNGE_EN_ROCE_V2					= BIT_ULL(1),
+	BNGE_EN_STRIP_VLAN				= BIT_ULL(2),
+	BNGE_EN_SHARED_CHNL				= BIT_ULL(3),
 };
 
 #define BNGE_EN_ROCE		(BNGE_EN_ROCE_V1 | BNGE_EN_ROCE_V2)
 
+enum {
+	BNGE_RSS_CAP_RSS_HASH_TYPE_DELTA		= BIT(0),
+	BNGE_RSS_CAP_UDP_RSS_CAP			= BIT(1),
+	BNGE_RSS_CAP_NEW_RSS_CAP			= BIT(2),
+	BNGE_RSS_CAP_RSS_TCAM				= BIT(3),
+	BNGE_RSS_CAP_AH_V4_RSS_CAP			= BIT(4),
+	BNGE_RSS_CAP_AH_V6_RSS_CAP			= BIT(5),
+	BNGE_RSS_CAP_ESP_V4_RSS_CAP			= BIT(6),
+	BNGE_RSS_CAP_ESP_V6_RSS_CAP			= BIT(7),
+};
+
 struct bnge_dev {
 	struct device	*dev;
 	struct pci_dev	*pdev;
@@ -73,6 +93,9 @@ struct bnge_dev {
 	u16		chip_num;
 	u8		chip_rev;
 
+	int		db_offset; /* db_offset within db_size */
+	int		db_size;
+
 	/* HWRM members */
 	u16			hwrm_cmd_seq;
 	u16			hwrm_cmd_kong_seq;
@@ -93,6 +116,8 @@ struct bnge_dev {
 #define BNGE_FW_VER_CODE(maj, min, bld, rsv)			\
 	((u64)(maj) << 48 | (u64)(min) << 32 | (u64)(bld) << 16 | (rsv))
 
+	struct bnge_pf_info	pf;
+
 	unsigned long           state;
 #define BNGE_STATE_DRV_REGISTERED      0
 
@@ -102,6 +127,51 @@ struct bnge_dev {
 	struct bnge_ctx_mem_info	*ctx;
 
 	u64			flags;
+
+	struct bnge_hw_resc	hw_resc;
+
+	u16			tso_max_segs;
+
+	int			max_fltr;
+#define BNGE_L2_FLTR_MAX_FLTR	1024
+
+	u32			*rss_indir_tbl;
+#define BNGE_RSS_TABLE_ENTRIES	64
+#define BNGE_RSS_TABLE_SIZE		(BNGE_RSS_TABLE_ENTRIES * 4)
+#define BNGE_RSS_TABLE_MAX_TBL	8
+#define BNGE_MAX_RSS_TABLE_SIZE				\
+	(BNGE_RSS_TABLE_SIZE * BNGE_RSS_TABLE_MAX_TBL)
+#define BNGE_MAX_RSS_TABLE_ENTRIES				\
+	(BNGE_RSS_TABLE_ENTRIES * BNGE_RSS_TABLE_MAX_TBL)
+	u16			rss_indir_tbl_entries;
+
+	u32			rss_cap;
+
+	u16			rx_nr_rings;
+	u16			tx_nr_rings;
+	u16			tx_nr_rings_per_tc;
+	/* Number of NQs */
+	u16			nq_nr_rings;
+
+	/* Aux device resources */
+	u16			aux_num_msix;
+	u16			aux_num_stat_ctxs;
+
+	u16			max_mtu;
+#define BNGE_MAX_MTU		9500
+
+	u16			hw_ring_stats_size;
+#define BNGE_NUM_RX_RING_STATS			8
+#define BNGE_NUM_TX_RING_STATS			8
+#define BNGE_NUM_TPA_RING_STATS			6
+#define BNGE_RING_STATS_SIZE					\
+	((BNGE_NUM_RX_RING_STATS + BNGE_NUM_TX_RING_STATS +	\
+	  BNGE_NUM_TPA_RING_STATS) * 8)
+
+	u16			max_tpa_v2;
+#define BNGE_SUPPORTS_TPA(bd)	((bd)->max_tpa_v2)
+
+	u8                      num_tc;
 };
 
 static inline bool bnge_is_roce_en(struct bnge_dev *bd)
@@ -109,4 +179,11 @@ static inline bool bnge_is_roce_en(struct bnge_dev *bd)
 	return bd->flags & BNGE_EN_ROCE;
 }
 
+static inline bool bnge_is_agg_reqd(struct bnge_dev *bd)
+{
+	return true;
+}
+
+bool bnge_aux_registered(struct bnge_dev *bd);
+
 #endif /* _BNGE_H_ */
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_core.c b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
index 5e23eb14f60e..cef68c4b6343 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_core.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
@@ -39,6 +39,11 @@ static void bnge_print_device_info(struct pci_dev *pdev, enum board_idx idx)
 	pcie_print_link_status(pdev);
 }
 
+bool bnge_aux_registered(struct bnge_dev *bd)
+{
+	return false;
+}
+
 static void bnge_nvm_cfg_ver_get(struct bnge_dev *bd)
 {
 	struct hwrm_nvm_get_dev_info_output nvm_info;
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h
index c14f03daab4b..9dd13c5219a5 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h
@@ -104,4 +104,14 @@ void hwrm_req_alloc_flags(struct bnge_dev *bd, void *req, gfp_t flags);
 void *hwrm_req_dma_slice(struct bnge_dev *bd, void *req, u32 size,
 			 dma_addr_t *dma);
 
+static inline int
+bnge_hwrm_func_cfg_short_req_init(struct bnge_dev *bdev,
+				  struct hwrm_func_cfg_input **req)
+{
+	u32 req_len;
+
+	req_len = min_t(u32, sizeof(**req), bdev->hwrm_max_ext_req_len);
+	return __hwrm_req_init(bdev, (void **)req, HWRM_FUNC_CFG, req_len);
+}
+
 #endif /* _BNGE_HWRM_H_ */
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
index e5f32ac8a69f..577ac5dcdd9b 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
@@ -11,6 +11,7 @@
 #include "bnge_hwrm.h"
 #include "bnge_hwrm_lib.h"
 #include "bnge_rmem.h"
+#include "bnge_resc.h"
 
 int bnge_hwrm_ver_get(struct bnge_dev *bd)
 {
@@ -379,3 +380,270 @@ int bnge_hwrm_func_backing_store(struct bnge_dev *bd,
 
 	return rc;
 }
+
+static int bnge_hwrm_get_rings(struct bnge_dev *bd)
+{
+	struct bnge_hw_resc *hw_resc = &bd->hw_resc;
+	struct hwrm_func_qcfg_output *resp;
+	struct hwrm_func_qcfg_input *req;
+	u16 cp, stats;
+	u16 rx, tx;
+	int rc;
+
+	rc = hwrm_req_init(bd, req, HWRM_FUNC_QCFG);
+	if (rc)
+		return rc;
+
+	req->fid = cpu_to_le16(0xffff);
+	resp = hwrm_req_hold(bd, req);
+	rc = hwrm_req_send(bd, req);
+	if (rc) {
+		hwrm_req_drop(bd, req);
+		return rc;
+	}
+
+	hw_resc->resv_tx_rings = le16_to_cpu(resp->alloc_tx_rings);
+	hw_resc->resv_rx_rings = le16_to_cpu(resp->alloc_rx_rings);
+	hw_resc->resv_hw_ring_grps =
+		le32_to_cpu(resp->alloc_hw_ring_grps);
+	hw_resc->resv_vnics = le16_to_cpu(resp->alloc_vnics);
+	hw_resc->resv_rsscos_ctxs = le16_to_cpu(resp->alloc_rsscos_ctx);
+	cp = le16_to_cpu(resp->alloc_cmpl_rings);
+	stats = le16_to_cpu(resp->alloc_stat_ctx);
+	hw_resc->resv_irqs = cp;
+	rx = hw_resc->resv_rx_rings;
+	tx = hw_resc->resv_tx_rings;
+	if (bnge_is_agg_reqd(bd))
+		rx >>= 1;
+	if (cp < (rx + tx)) {
+		rc = bnge_fix_rings_count(&rx, &tx, cp, false);
+		if (rc)
+			goto get_rings_exit;
+		if (bnge_is_agg_reqd(bd))
+			rx <<= 1;
+		hw_resc->resv_rx_rings = rx;
+		hw_resc->resv_tx_rings = tx;
+	}
+	hw_resc->resv_irqs = le16_to_cpu(resp->alloc_msix);
+	hw_resc->resv_hw_ring_grps = rx;
+	hw_resc->resv_cp_rings = cp;
+	hw_resc->resv_stat_ctxs = stats;
+
+get_rings_exit:
+	hwrm_req_drop(bd, req);
+	return rc;
+}
+
+static struct hwrm_func_cfg_input *
+__bnge_hwrm_reserve_pf_rings(struct bnge_dev *bd, struct bnge_hw_rings *hwr)
+{
+	struct hwrm_func_cfg_input *req;
+	u32 enables = 0;
+
+	if (bnge_hwrm_func_cfg_short_req_init(bd, &req))
+		return NULL;
+
+	req->fid = cpu_to_le16(0xffff);
+	enables |= hwr->tx ? FUNC_CFG_REQ_ENABLES_NUM_TX_RINGS : 0;
+	req->num_tx_rings = cpu_to_le16(hwr->tx);
+
+	enables |= hwr->rx ? FUNC_CFG_REQ_ENABLES_NUM_RX_RINGS : 0;
+	enables |= hwr->stat ? FUNC_CFG_REQ_ENABLES_NUM_STAT_CTXS : 0;
+	enables |= hwr->nq ? FUNC_CFG_REQ_ENABLES_NUM_MSIX : 0;
+	enables |= hwr->cmpl ? FUNC_CFG_REQ_ENABLES_NUM_CMPL_RINGS : 0;
+	enables |= hwr->vnic ? FUNC_CFG_REQ_ENABLES_NUM_VNICS : 0;
+	enables |= hwr->rss_ctx ? FUNC_CFG_REQ_ENABLES_NUM_RSSCOS_CTXS : 0;
+
+	req->num_rx_rings = cpu_to_le16(hwr->rx);
+	req->num_rsscos_ctxs = cpu_to_le16(hwr->rss_ctx);
+	req->num_cmpl_rings = cpu_to_le16(hwr->cmpl);
+	req->num_msix = cpu_to_le16(hwr->nq);
+	req->num_stat_ctxs = cpu_to_le16(hwr->stat);
+	req->num_vnics = cpu_to_le16(hwr->vnic);
+	req->enables = cpu_to_le32(enables);
+
+	return req;
+}
+
+static int
+bnge_hwrm_reserve_pf_rings(struct bnge_dev *bd, struct bnge_hw_rings *hwr)
+{
+	struct hwrm_func_cfg_input *req;
+	int rc;
+
+	req = __bnge_hwrm_reserve_pf_rings(bd, hwr);
+	if (!req)
+		return -ENOMEM;
+
+	if (!req->enables) {
+		hwrm_req_drop(bd, req);
+		return 0;
+	}
+
+	rc = hwrm_req_send(bd, req);
+	if (rc)
+		return rc;
+
+	return bnge_hwrm_get_rings(bd);
+}
+
+int bnge_hwrm_reserve_rings(struct bnge_dev *bd, struct bnge_hw_rings *hwr)
+{
+	return bnge_hwrm_reserve_pf_rings(bd, hwr);
+}
+
+int bnge_hwrm_func_qcfg(struct bnge_dev *bd)
+{
+	struct hwrm_func_qcfg_output *resp;
+	struct hwrm_func_qcfg_input *req;
+	int rc;
+
+	rc = hwrm_req_init(bd, req, HWRM_FUNC_QCFG);
+	if (rc)
+		return rc;
+
+	req->fid = cpu_to_le16(0xffff);
+	resp = hwrm_req_hold(bd, req);
+	rc = hwrm_req_send(bd, req);
+	if (rc)
+		goto func_qcfg_exit;
+
+	bd->max_mtu = le16_to_cpu(resp->max_mtu_configured);
+	if (!bd->max_mtu)
+		bd->max_mtu = BNGE_MAX_MTU;
+
+	if (bd->db_size)
+		goto func_qcfg_exit;
+
+	bd->db_offset = le16_to_cpu(resp->legacy_l2_db_size_kb) * 1024;
+	bd->db_size = PAGE_ALIGN(le16_to_cpu(resp->l2_doorbell_bar_size_kb) *
+			1024);
+	if (!bd->db_size || bd->db_size > pci_resource_len(bd->pdev, 2) ||
+	    bd->db_size <= bd->db_offset)
+		bd->db_size = pci_resource_len(bd->pdev, 2);
+
+func_qcfg_exit:
+	hwrm_req_drop(bd, req);
+	return rc;
+}
+
+int bnge_hwrm_func_resc_qcaps(struct bnge_dev *bd)
+{
+	struct hwrm_func_resource_qcaps_output *resp;
+	struct bnge_hw_resc *hw_resc = &bd->hw_resc;
+	struct hwrm_func_resource_qcaps_input *req;
+	int rc;
+
+	rc = hwrm_req_init(bd, req, HWRM_FUNC_RESOURCE_QCAPS);
+	if (rc)
+		return rc;
+
+	req->fid = cpu_to_le16(0xffff);
+	resp = hwrm_req_hold(bd, req);
+	rc = hwrm_req_send_silent(bd, req);
+	if (rc)
+		goto hwrm_func_resc_qcaps_exit;
+
+	hw_resc->max_tx_sch_inputs = le16_to_cpu(resp->max_tx_scheduler_inputs);
+	hw_resc->min_rsscos_ctxs = le16_to_cpu(resp->min_rsscos_ctx);
+	hw_resc->max_rsscos_ctxs = le16_to_cpu(resp->max_rsscos_ctx);
+	hw_resc->min_cp_rings = le16_to_cpu(resp->min_cmpl_rings);
+	hw_resc->max_cp_rings = le16_to_cpu(resp->max_cmpl_rings);
+	hw_resc->min_tx_rings = le16_to_cpu(resp->min_tx_rings);
+	hw_resc->max_tx_rings = le16_to_cpu(resp->max_tx_rings);
+	hw_resc->min_rx_rings = le16_to_cpu(resp->min_rx_rings);
+	hw_resc->max_rx_rings = le16_to_cpu(resp->max_rx_rings);
+	hw_resc->min_hw_ring_grps = le16_to_cpu(resp->min_hw_ring_grps);
+	hw_resc->max_hw_ring_grps = le16_to_cpu(resp->max_hw_ring_grps);
+	hw_resc->min_l2_ctxs = le16_to_cpu(resp->min_l2_ctxs);
+	hw_resc->max_l2_ctxs = le16_to_cpu(resp->max_l2_ctxs);
+	hw_resc->min_vnics = le16_to_cpu(resp->min_vnics);
+	hw_resc->max_vnics = le16_to_cpu(resp->max_vnics);
+	hw_resc->min_stat_ctxs = le16_to_cpu(resp->min_stat_ctx);
+	hw_resc->max_stat_ctxs = le16_to_cpu(resp->max_stat_ctx);
+
+	hw_resc->max_nqs = le16_to_cpu(resp->max_msix);
+	hw_resc->max_hw_ring_grps = hw_resc->max_rx_rings;
+
+hwrm_func_resc_qcaps_exit:
+	hwrm_req_drop(bd, req);
+	return rc;
+}
+
+int bnge_hwrm_func_qcaps(struct bnge_dev *bd)
+{
+	struct hwrm_func_qcaps_output *resp;
+	struct hwrm_func_qcaps_input *req;
+	struct bnge_pf_info *pf = &bd->pf;
+	u32 flags;
+	int rc;
+
+	rc = hwrm_req_init(bd, req, HWRM_FUNC_QCAPS);
+	if (rc)
+		return rc;
+
+	req->fid = cpu_to_le16(0xffff);
+	resp = hwrm_req_hold(bd, req);
+	rc = hwrm_req_send(bd, req);
+	if (rc)
+		goto hwrm_func_qcaps_exit;
+
+	flags = le32_to_cpu(resp->flags);
+	if (flags & FUNC_QCAPS_RESP_FLAGS_ROCE_V1_SUPPORTED)
+		bd->flags |= BNGE_EN_ROCE_V1;
+	if (flags & FUNC_QCAPS_RESP_FLAGS_ROCE_V2_SUPPORTED)
+		bd->flags |= BNGE_EN_ROCE_V2;
+
+	pf->fw_fid = le16_to_cpu(resp->fid);
+	pf->port_id = le16_to_cpu(resp->port_id);
+	memcpy(pf->mac_addr, resp->mac_address, ETH_ALEN);
+
+	bd->tso_max_segs = le16_to_cpu(resp->max_tso_segs);
+
+hwrm_func_qcaps_exit:
+	hwrm_req_drop(bd, req);
+	return rc;
+}
+
+int bnge_hwrm_vnic_qcaps(struct bnge_dev *bd)
+{
+	struct hwrm_vnic_qcaps_output *resp;
+	struct hwrm_vnic_qcaps_input *req;
+	int rc;
+
+	bd->hw_ring_stats_size = sizeof(struct ctx_hw_stats);
+	bd->rss_cap &= ~BNGE_RSS_CAP_NEW_RSS_CAP;
+
+	rc = hwrm_req_init(bd, req, HWRM_VNIC_QCAPS);
+	if (rc)
+		return rc;
+
+	resp = hwrm_req_hold(bd, req);
+	rc = hwrm_req_send(bd, req);
+	if (!rc) {
+		u32 flags = le32_to_cpu(resp->flags);
+
+		if (flags & VNIC_QCAPS_RESP_FLAGS_VLAN_STRIP_CAP)
+			bd->fw_cap |= BNGE_FW_CAP_VLAN_RX_STRIP;
+		if (flags & VNIC_QCAPS_RESP_FLAGS_RSS_HASH_TYPE_DELTA_CAP)
+			bd->rss_cap |= BNGE_RSS_CAP_RSS_HASH_TYPE_DELTA;
+		if (flags & VNIC_QCAPS_RESP_FLAGS_RSS_PROF_TCAM_MODE_ENABLED)
+			bd->rss_cap |= BNGE_RSS_CAP_RSS_TCAM;
+		bd->max_tpa_v2 = le16_to_cpu(resp->max_aggs_supported);
+		if (bd->max_tpa_v2)
+			bd->hw_ring_stats_size = BNGE_RING_STATS_SIZE;
+		if (flags & VNIC_QCAPS_RESP_FLAGS_HW_TUNNEL_TPA_CAP)
+			bd->fw_cap |= BNGE_FW_CAP_VNIC_TUNNEL_TPA;
+		if (flags & VNIC_QCAPS_RESP_FLAGS_RSS_IPSEC_AH_SPI_IPV4_CAP)
+			bd->rss_cap |= BNGE_RSS_CAP_AH_V4_RSS_CAP;
+		if (flags & VNIC_QCAPS_RESP_FLAGS_RSS_IPSEC_AH_SPI_IPV6_CAP)
+			bd->rss_cap |= BNGE_RSS_CAP_AH_V6_RSS_CAP;
+		if (flags & VNIC_QCAPS_RESP_FLAGS_RSS_IPSEC_ESP_SPI_IPV4_CAP)
+			bd->rss_cap |= BNGE_RSS_CAP_ESP_V4_RSS_CAP;
+		if (flags & VNIC_QCAPS_RESP_FLAGS_RSS_IPSEC_ESP_SPI_IPV6_CAP)
+			bd->rss_cap |= BNGE_RSS_CAP_ESP_V6_RSS_CAP;
+	}
+	hwrm_req_drop(bd, req);
+
+	return rc;
+}
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
index c04291d74bf0..59ec1899879a 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
@@ -16,5 +16,11 @@ int bnge_hwrm_func_backing_store(struct bnge_dev *bd,
 				 struct bnge_ctx_mem_type *ctxm,
 				 bool last);
 int bnge_hwrm_func_backing_store_qcaps(struct bnge_dev *bd);
+int bnge_hwrm_reserve_rings(struct bnge_dev *bd,
+			    struct bnge_hw_rings *hwr);
+int bnge_hwrm_func_qcaps(struct bnge_dev *bd);
+int bnge_hwrm_vnic_qcaps(struct bnge_dev *bd);
+int bnge_hwrm_func_qcfg(struct bnge_dev *bd);
+int bnge_hwrm_func_resc_qcaps(struct bnge_dev *bd);
 
 #endif /* _BNGE_HWRM_LIB_H_ */
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_resc.c b/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
new file mode 100644
index 000000000000..68e094474822
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
@@ -0,0 +1,328 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2025 Broadcom.
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/ethtool.h>
+
+#include "bnge.h"
+#include "bnge_hwrm.h"
+#include "bnge_hwrm_lib.h"
+#include "bnge_resc.h"
+
+static u16 bnge_num_tx_to_cp(struct bnge_dev *bd, u16 tx)
+{
+	u16 tcs = bd->num_tc;
+
+	if (!tcs)
+		tcs = 1;
+
+	return tx / tcs;
+}
+
+static u16 bnge_get_max_func_irqs(struct bnge_dev *bd)
+{
+	struct bnge_hw_resc *hw_resc = &bd->hw_resc;
+
+	return min_t(u16, hw_resc->max_irqs, hw_resc->max_nqs);
+}
+
+static int bnge_aux_get_dflt_msix(struct bnge_dev *bd)
+{
+	int roce_msix = BNGE_MAX_ROCE_MSIX;
+
+	return min_t(int, roce_msix, num_online_cpus() + 1);
+}
+
+static u16 bnge_aux_get_msix(struct bnge_dev *bd)
+{
+	if (bnge_is_roce_en(bd))
+		return bd->aux_num_msix;
+
+	return 0;
+}
+
+static void bnge_aux_set_msix_num(struct bnge_dev *bd, u16 num)
+{
+	if (bnge_is_roce_en(bd))
+		bd->aux_num_msix = num;
+}
+
+static u16 bnge_aux_get_stat_ctxs(struct bnge_dev *bd)
+{
+	if (bnge_is_roce_en(bd))
+		return bd->aux_num_stat_ctxs;
+
+	return 0;
+}
+
+static void bnge_aux_set_stat_ctxs(struct bnge_dev *bd, u16 num_aux_ctx)
+{
+	if (bnge_is_roce_en(bd))
+		bd->aux_num_stat_ctxs = num_aux_ctx;
+}
+
+static u16 bnge_func_stat_ctxs_demand(struct bnge_dev *bd)
+{
+	return bd->nq_nr_rings + bnge_aux_get_stat_ctxs(bd);
+}
+
+static u16 bnge_nqs_demand(struct bnge_dev *bd)
+{
+	return bd->nq_nr_rings + bnge_aux_get_msix(bd);
+}
+
+static u16 bnge_cprs_demand(struct bnge_dev *bd)
+{
+	return bd->tx_nr_rings + bd->rx_nr_rings;
+}
+
+static u16 bnge_get_avail_msix(struct bnge_dev *bd, int num)
+{
+	u16 max_irq = bnge_get_max_func_irqs(bd);
+	u16 total_demand = bd->nq_nr_rings + num;
+
+	if (max_irq < total_demand) {
+		num = max_irq - bd->nq_nr_rings;
+		if (num <= 0)
+			return 0;
+	}
+
+	return num;
+}
+
+static u16 bnge_num_cp_to_tx(struct bnge_dev *bd, u16 tx_chunks)
+{
+	return tx_chunks * bd->num_tc;
+}
+
+int bnge_fix_rings_count(u16 *rx, u16 *tx, u16 max, bool shared)
+{
+	u16 _rx = *rx, _tx = *tx;
+
+	if (shared) {
+		*rx = min_t(u16, _rx, max);
+		*tx = min_t(u16, _tx, max);
+	} else {
+		if (max < 2)
+			return -ENOMEM;
+		while (_rx + _tx > max) {
+			if (_rx > _tx && _rx > 1)
+				_rx--;
+			else if (_tx > 1)
+				_tx--;
+		}
+		*rx = _rx;
+		*tx = _tx;
+	}
+
+	return 0;
+}
+
+static int bnge_adjust_rings(struct bnge_dev *bd, u16 *rx,
+			     u16 *tx, u16 max_nq, bool sh)
+{
+	u16 tx_chunks = bnge_num_tx_to_cp(bd, *tx);
+
+	if (tx_chunks != *tx) {
+		u16 tx_saved = tx_chunks, rc;
+
+		rc = bnge_fix_rings_count(rx, &tx_chunks, max_nq, sh);
+		if (rc)
+			return rc;
+		if (tx_chunks != tx_saved)
+			*tx = bnge_num_cp_to_tx(bd, tx_chunks);
+		return 0;
+	}
+
+	return bnge_fix_rings_count(rx, tx, max_nq, sh);
+}
+
+static int bnge_cal_nr_rss_ctxs(u16 rx_rings)
+{
+	if (!rx_rings)
+		return 0;
+
+	return bnge_adjust_pow_two(rx_rings - 1,
+				   BNGE_RSS_TABLE_ENTRIES);
+}
+
+static u16 bnge_rss_ctxs_in_use(struct bnge_dev *bd,
+				struct bnge_hw_rings *hwr)
+{
+	return bnge_cal_nr_rss_ctxs(hwr->grp);
+}
+
+static u16 bnge_get_total_vnics(struct bnge_dev *bd, u16 rx_rings)
+{
+	return 1;
+}
+
+static u32 bnge_get_rxfh_indir_size(struct bnge_dev *bd)
+{
+	return bnge_cal_nr_rss_ctxs(bd->rx_nr_rings) *
+	       BNGE_RSS_TABLE_ENTRIES;
+}
+
+static void bnge_set_dflt_rss_indir_tbl(struct bnge_dev *bd)
+{
+	u16 max_entries, pad;
+	u32 *rss_indir_tbl;
+	int i;
+
+	max_entries = bnge_get_rxfh_indir_size(bd);
+	rss_indir_tbl = &bd->rss_indir_tbl[0];
+
+	for (i = 0; i < max_entries; i++)
+		rss_indir_tbl[i] = ethtool_rxfh_indir_default(i,
+							      bd->rx_nr_rings);
+
+	pad = bd->rss_indir_tbl_entries - max_entries;
+	if (pad)
+		memset(&rss_indir_tbl[i], 0, pad * sizeof(*rss_indir_tbl));
+}
+
+static void bnge_copy_reserved_rings(struct bnge_dev *bd,
+				     struct bnge_hw_rings *hwr)
+{
+	struct bnge_hw_resc *hw_resc = &bd->hw_resc;
+
+	hwr->tx = hw_resc->resv_tx_rings;
+	hwr->rx = hw_resc->resv_rx_rings;
+	hwr->nq = hw_resc->resv_irqs;
+	hwr->cmpl = hw_resc->resv_cp_rings;
+	hwr->grp = hw_resc->resv_hw_ring_grps;
+	hwr->vnic = hw_resc->resv_vnics;
+	hwr->stat = hw_resc->resv_stat_ctxs;
+	hwr->rss_ctx = hw_resc->resv_rsscos_ctxs;
+}
+
+static bool bnge_rings_ok(struct bnge_hw_rings *hwr)
+{
+	return hwr->tx && hwr->rx && hwr->nq && hwr->grp && hwr->vnic &&
+	       hwr->stat && hwr->cmpl;
+}
+
+static bool bnge_need_reserve_rings(struct bnge_dev *bd)
+{
+	struct bnge_hw_resc *hw_resc = &bd->hw_resc;
+	u16 cprs = bnge_cprs_demand(bd);
+	u16 rx = bd->rx_nr_rings, stat;
+	u16 nqs = bnge_nqs_demand(bd);
+	u16 vnic;
+
+	if (hw_resc->resv_tx_rings != bd->tx_nr_rings)
+		return true;
+
+	vnic = bnge_get_total_vnics(bd, rx);
+
+	if (bnge_is_agg_reqd(bd))
+		rx <<= 1;
+	stat = bnge_func_stat_ctxs_demand(bd);
+	if (hw_resc->resv_rx_rings != rx || hw_resc->resv_cp_rings != cprs ||
+	    hw_resc->resv_vnics != vnic || hw_resc->resv_stat_ctxs != stat)
+		return true;
+	if (hw_resc->resv_irqs != nqs)
+		return true;
+
+	return false;
+}
+
+int bnge_reserve_rings(struct bnge_dev *bd)
+{
+	u16 aux_dflt_msix = bnge_aux_get_dflt_msix(bd);
+	struct bnge_hw_rings hwr = {0};
+	u16 rx_rings, old_rx_rings;
+	u16 nq = bd->nq_nr_rings;
+	u16 aux_msix = 0;
+	bool sh = false;
+	u16 tx_cp;
+	int rc;
+
+	if (!bnge_need_reserve_rings(bd))
+		return 0;
+
+	if (!bnge_aux_registered(bd)) {
+		aux_msix = bnge_get_avail_msix(bd, aux_dflt_msix);
+		if (!aux_msix)
+			bnge_aux_set_stat_ctxs(bd, 0);
+
+		if (aux_msix > aux_dflt_msix)
+			aux_msix = aux_dflt_msix;
+		hwr.nq = nq + aux_msix;
+	} else {
+		hwr.nq = bnge_nqs_demand(bd);
+	}
+
+	hwr.tx = bd->tx_nr_rings;
+	hwr.rx = bd->rx_nr_rings;
+	if (bd->flags & BNGE_EN_SHARED_CHNL)
+		sh = true;
+	hwr.cmpl = hwr.rx + hwr.tx;
+
+	hwr.vnic = bnge_get_total_vnics(bd, hwr.rx);
+
+	if (bnge_is_agg_reqd(bd))
+		hwr.rx <<= 1;
+	hwr.grp = bd->rx_nr_rings;
+	hwr.rss_ctx = bnge_rss_ctxs_in_use(bd, &hwr);
+	hwr.stat = bnge_func_stat_ctxs_demand(bd);
+	old_rx_rings = bd->hw_resc.resv_rx_rings;
+
+	rc = bnge_hwrm_reserve_rings(bd, &hwr);
+	if (rc)
+		return rc;
+
+	bnge_copy_reserved_rings(bd, &hwr);
+
+	rx_rings = hwr.rx;
+	if (bnge_is_agg_reqd(bd)) {
+		if (hwr.rx >= 2)
+			rx_rings = hwr.rx >> 1;
+		else
+			return -ENOMEM;
+	}
+
+	rx_rings = min_t(u16, rx_rings, hwr.grp);
+	hwr.nq = min_t(u16, hwr.nq, bd->nq_nr_rings);
+	if (hwr.stat > bnge_aux_get_stat_ctxs(bd))
+		hwr.stat -= bnge_aux_get_stat_ctxs(bd);
+	hwr.nq = min_t(u16, hwr.nq, hwr.stat);
+
+	/* Adjust the rings */
+	rc = bnge_adjust_rings(bd, &rx_rings, &hwr.tx, hwr.nq, sh);
+	if (bnge_is_agg_reqd(bd))
+		hwr.rx = rx_rings << 1;
+	tx_cp = hwr.tx;
+	hwr.nq = sh ? max_t(u16, tx_cp, rx_rings) : tx_cp + rx_rings;
+	bd->tx_nr_rings = hwr.tx;
+
+	if (rx_rings != bd->rx_nr_rings)
+		dev_warn(bd->dev, "RX rings resv reduced to %d than earlier %d requested\n",
+			 rx_rings, bd->rx_nr_rings);
+
+	bd->rx_nr_rings = rx_rings;
+	bd->nq_nr_rings = hwr.nq;
+
+	if (!bnge_rings_ok(&hwr))
+		return -ENOMEM;
+
+	if (old_rx_rings != bd->hw_resc.resv_rx_rings)
+		bnge_set_dflt_rss_indir_tbl(bd);
+
+	if (!bnge_aux_registered(bd)) {
+		u16 resv_msix, resv_ctx, aux_ctxs;
+		struct bnge_hw_resc *hw_resc;
+
+		hw_resc = &bd->hw_resc;
+		resv_msix = hw_resc->resv_irqs - bd->nq_nr_rings;
+		aux_msix = min_t(u16, resv_msix, aux_msix);
+		bnge_aux_set_msix_num(bd, aux_msix);
+		resv_ctx = hw_resc->resv_stat_ctxs  - bd->nq_nr_rings;
+		aux_ctxs = min(resv_ctx, bnge_aux_get_stat_ctxs(bd));
+		bnge_aux_set_stat_ctxs(bd, aux_ctxs);
+	}
+
+	return rc;
+}
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_resc.h b/drivers/net/ethernet/broadcom/bnge/bnge_resc.h
new file mode 100644
index 000000000000..c6cef514588f
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_resc.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2025 Broadcom */
+
+#ifndef _BNGE_RESC_H_
+#define _BNGE_RESC_H_
+
+struct bnge_hw_resc {
+	u16	min_rsscos_ctxs;
+	u16	max_rsscos_ctxs;
+	u16	resv_rsscos_ctxs;
+	u16	min_cp_rings;
+	u16	max_cp_rings;
+	u16	resv_cp_rings;
+	u16	min_tx_rings;
+	u16	max_tx_rings;
+	u16	resv_tx_rings;
+	u16	max_tx_sch_inputs;
+	u16	min_rx_rings;
+	u16	max_rx_rings;
+	u16	resv_rx_rings;
+	u16	min_hw_ring_grps;
+	u16	max_hw_ring_grps;
+	u16	resv_hw_ring_grps;
+	u16	min_l2_ctxs;
+	u16	max_l2_ctxs;
+	u16	min_vnics;
+	u16	max_vnics;
+	u16	resv_vnics;
+	u16	min_stat_ctxs;
+	u16	max_stat_ctxs;
+	u16	resv_stat_ctxs;
+	u16	max_nqs;
+	u16	max_irqs;
+	u16	resv_irqs;
+	u32	max_encap_records;
+	u32	max_decap_records;
+	u32	max_tx_em_flows;
+	u32	max_tx_wm_flows;
+	u32	max_rx_em_flows;
+	u32	max_rx_wm_flows;
+};
+
+struct bnge_hw_rings {
+	u16 tx;
+	u16 rx;
+	u16 grp;
+	u16 nq;
+	u16 cmpl;
+	u16 stat;
+	u16 vnic;
+	u16 rss_ctx;
+};
+
+int bnge_reserve_rings(struct bnge_dev *bd);
+int bnge_fix_rings_count(u16 *rx, u16 *tx, u16 max, bool shared);
+
+static inline u32
+bnge_adjust_pow_two(u32 total_ent, u16 ent_per_blk)
+{
+	u32 blks = total_ent / ent_per_blk;
+
+	if (blks == 0 || blks == 1)
+		return ++blks;
+
+	if (!is_power_of_2(blks))
+		blks = roundup_pow_of_two(blks);
+
+	return blks;
+}
+
+#define BNGE_MAX_ROCE_MSIX		64
+#define BNGE_MIN_ROCE_CP_RINGS		2
+#define BNGE_MIN_ROCE_STAT_CTXS		1
+
+#endif /* _BNGE_RESC_H_ */
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [net-next, 08/10] bng_en: Add irq allocation support
  2025-06-18 14:47 [net-next, 00/10] Introducing Broadcom BNGE Ethernet Driver Vikas Gupta
                   ` (6 preceding siblings ...)
  2025-06-18 14:47 ` [net-next, 07/10] bng_en: Add resource management support Vikas Gupta
@ 2025-06-18 14:47 ` Vikas Gupta
  2025-06-19 13:52   ` Vadim Fedorenko
                     ` (4 more replies)
  2025-06-18 14:47 ` [net-next, 09/10] bng_en: Initialize default configuration Vikas Gupta
  2025-06-18 14:47 ` [net-next, 10/10] bng_en: Add a network device Vikas Gupta
  9 siblings, 5 replies; 37+ messages in thread
From: Vikas Gupta @ 2025-06-18 14:47 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Add irq allocation functions. This will help
to allocate IRQs to both netdev and RoCE aux devices.

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>
---
 drivers/net/ethernet/broadcom/bnge/bnge.h     |  3 +
 .../net/ethernet/broadcom/bnge/bnge_resc.c    | 69 +++++++++++++++++++
 .../net/ethernet/broadcom/bnge/bnge_resc.h    | 13 ++++
 3 files changed, 85 insertions(+)

diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
index b58d8fc6f258..3c161b1a9b62 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
@@ -172,6 +172,9 @@ struct bnge_dev {
 #define BNGE_SUPPORTS_TPA(bd)	((bd)->max_tpa_v2)
 
 	u8                      num_tc;
+
+	struct bnge_irq		*irq_tbl;
+	u16			irqs_acquired;
 };
 
 static inline bool bnge_is_roce_en(struct bnge_dev *bd)
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_resc.c b/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
index 68e094474822..84f91e05a2b0 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
@@ -326,3 +326,72 @@ int bnge_reserve_rings(struct bnge_dev *bd)
 
 	return rc;
 }
+
+int bnge_alloc_irqs(struct bnge_dev *bd)
+{
+	u16 aux_msix, tx_cp, num_entries;
+	u16 irqs_demand, max, min = 1;
+	int i, rc = 0;
+
+	irqs_demand = bnge_nqs_demand(bd);
+	max = bnge_get_max_func_irqs(bd);
+	if (irqs_demand > max)
+		irqs_demand = max;
+
+	if (!(bd->flags & BNGE_EN_SHARED_CHNL))
+		min = 2;
+
+	irqs_demand = pci_alloc_irq_vectors(bd->pdev, min, irqs_demand,
+					    PCI_IRQ_MSIX);
+	aux_msix = bnge_aux_get_msix(bd);
+	if (irqs_demand < 0 || irqs_demand < aux_msix) {
+		rc = -ENODEV;
+		goto err_free_irqs;
+	}
+
+	num_entries = irqs_demand;
+	if (pci_msix_can_alloc_dyn(bd->pdev))
+		num_entries = max;
+	bd->irq_tbl = kcalloc(num_entries, sizeof(*bd->irq_tbl), GFP_KERNEL);
+	if (!bd->irq_tbl) {
+		rc = -ENOMEM;
+		goto err_free_irqs;
+	}
+
+	for (i = 0; i < irqs_demand; i++)
+		bd->irq_tbl[i].vector = pci_irq_vector(bd->pdev, i);
+
+	bd->irqs_acquired = irqs_demand;
+	/* Reduce rings based upon num of vectors allocated.
+	 * We dont need to consider NQs as they have been calculated
+	 * and must be more than irqs_demand.
+	 */
+	rc = bnge_adjust_rings(bd, &bd->rx_nr_rings,
+			       &bd->tx_nr_rings,
+			       irqs_demand - aux_msix, min == 1);
+	if (rc)
+		goto err_free_irqs;
+
+	tx_cp = bnge_num_tx_to_cp(bd, bd->tx_nr_rings);
+	bd->nq_nr_rings = (min == 1) ?
+		max_t(u16, tx_cp, bd->rx_nr_rings) :
+		tx_cp + bd->rx_nr_rings;
+
+	/* Readjust tx_nr_rings_per_tc */
+	if (!bd->num_tc)
+		bd->tx_nr_rings_per_tc = bd->tx_nr_rings;
+
+	return 0;
+
+err_free_irqs:
+	dev_err(bd->dev, "Failed to allocate IRQs err = %d\n", rc);
+	bnge_free_irqs(bd);
+	return rc;
+}
+
+void bnge_free_irqs(struct bnge_dev *bd)
+{
+	pci_free_irq_vectors(bd->pdev);
+	kfree(bd->irq_tbl);
+	bd->irq_tbl = NULL;
+}
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_resc.h b/drivers/net/ethernet/broadcom/bnge/bnge_resc.h
index c6cef514588f..23db93e03787 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_resc.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_resc.h
@@ -51,8 +51,21 @@ struct bnge_hw_rings {
 	u16 rss_ctx;
 };
 
+/* "TXRX", 2 hypens, plus maximum integer */
+#define BNGE_IRQ_NAME_EXTRA	17
+struct bnge_irq {
+	irq_handler_t	handler;
+	unsigned int	vector;
+	u8		requested:1;
+	u8		have_cpumask:1;
+	char		name[IFNAMSIZ + BNGE_IRQ_NAME_EXTRA];
+	cpumask_var_t	cpu_mask;
+};
+
 int bnge_reserve_rings(struct bnge_dev *bd);
 int bnge_fix_rings_count(u16 *rx, u16 *tx, u16 max, bool shared);
+int bnge_alloc_irqs(struct bnge_dev *bd);
+void bnge_free_irqs(struct bnge_dev *bd);
 
 static inline u32
 bnge_adjust_pow_two(u32 total_ent, u16 ent_per_blk)
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [net-next, 09/10] bng_en: Initialize default configuration
  2025-06-18 14:47 [net-next, 00/10] Introducing Broadcom BNGE Ethernet Driver Vikas Gupta
                   ` (7 preceding siblings ...)
  2025-06-18 14:47 ` [net-next, 08/10] bng_en: Add irq allocation support Vikas Gupta
@ 2025-06-18 14:47 ` Vikas Gupta
  2025-06-18 20:16   ` kernel test robot
                     ` (4 more replies)
  2025-06-18 14:47 ` [net-next, 10/10] bng_en: Add a network device Vikas Gupta
  9 siblings, 5 replies; 37+ messages in thread
From: Vikas Gupta @ 2025-06-18 14:47 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Query resources from the firmware and, based on the
availability of resources, initialize the default
settings. The default settings include:
1. Rings and other resource reservations with the
firmware. This ensures that resources are reserved
before network and auxiliary devices are created.
2. Mapping the BAR, which helps access doorbells since
its size is known after querying the firmware.
3. Retrieving the TCs and hardware CoS queue mappings.

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>
---
 drivers/net/ethernet/broadcom/bnge/bnge.h     |  14 ++
 .../net/ethernet/broadcom/bnge/bnge_core.c    | 122 +++++++++++
 .../ethernet/broadcom/bnge/bnge_hwrm_lib.c    |  54 +++++
 .../ethernet/broadcom/bnge/bnge_hwrm_lib.h    |   1 +
 .../net/ethernet/broadcom/bnge/bnge_resc.c    | 207 ++++++++++++++++++
 .../net/ethernet/broadcom/bnge/bnge_resc.h    |   3 +
 6 files changed, 401 insertions(+)

diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
index 3c161b1a9b62..06465b318f5c 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
@@ -80,6 +80,12 @@ enum {
 	BNGE_RSS_CAP_ESP_V6_RSS_CAP			= BIT(7),
 };
 
+#define BNGE_MAX_QUEUE		8
+struct bnge_queue_info {
+	u8      queue_id;
+	u8      queue_profile;
+};
+
 struct bnge_dev {
 	struct device	*dev;
 	struct pci_dev	*pdev;
@@ -89,6 +95,7 @@ struct bnge_dev {
 	char		board_serialno[BNGE_VPD_FLD_LEN];
 
 	void __iomem	*bar0;
+	void __iomem 	*bar1;
 
 	u16		chip_num;
 	u8		chip_rev;
@@ -172,6 +179,13 @@ struct bnge_dev {
 #define BNGE_SUPPORTS_TPA(bd)	((bd)->max_tpa_v2)
 
 	u8                      num_tc;
+	u8			max_tc;
+	u8			max_lltc;	/* lossless TCs */
+	struct bnge_queue_info	q_info[BNGE_MAX_QUEUE];
+	u8			tc_to_qidx[BNGE_MAX_QUEUE];
+	u8			q_ids[BNGE_MAX_QUEUE];
+	u8			max_q;
+	u8			port_count;
 
 	struct bnge_irq		*irq_tbl;
 	u16			irqs_acquired;
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_core.c b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
index cef68c4b6343..bad77973f100 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_core.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
@@ -54,9 +54,46 @@ static void bnge_nvm_cfg_ver_get(struct bnge_dev *bd)
 			 nvm_info.nvm_cfg_ver_upd);
 }
 
+static int bnge_func_qcaps(struct bnge_dev *bd)
+{
+	int rc;
+
+	rc = bnge_hwrm_func_qcaps(bd);
+	if (rc)
+		return rc;
+
+	rc = bnge_hwrm_queue_qportcfg(bd);
+	if (rc) {
+		dev_err(bd->dev, "query qportcfg failure rc: %d\n", rc);
+		return rc;
+	}
+
+	rc = bnge_hwrm_func_resc_qcaps(bd);
+	if (rc) {
+		dev_err(bd->dev, "query resc caps failure rc: %d\n", rc);
+		return rc;
+	}
+
+	rc = bnge_hwrm_func_qcfg(bd);
+	if (rc) {
+		dev_err(bd->dev, "query config failure rc: %d\n", rc);
+		return rc;
+	}
+
+	rc = bnge_hwrm_vnic_qcaps(bd);
+	if (rc) {
+		dev_err(bd->dev, "vnic caps failure rc: %d\n", rc);
+		return rc;
+	}
+
+	return 0;
+}
+
 static void bnge_fw_unregister_dev(struct bnge_dev *bd)
 {
+	/* ctx mem free after unrgtr only */
 	bnge_hwrm_func_drv_unrgtr(bd);
+	bnge_free_ctx_mem(bd);
 }
 
 static int bnge_fw_register_dev(struct bnge_dev *bd)
@@ -86,7 +123,25 @@ static int bnge_fw_register_dev(struct bnge_dev *bd)
 		return rc;
 	}
 
+	rc = bnge_alloc_ctx_mem(bd);
+	if (rc) {
+		dev_err(bd->dev, "Failed to allocate ctx mem rc: %d\n", rc);
+		goto err_func_unrgtr;
+	}
+
+	/* Get the resources and configuration from firmware */
+	rc = bnge_func_qcaps(bd);
+	if (rc) {
+		dev_err(bd->dev, "Failed initial configuration rc: %d\n", rc);
+		rc = -ENODEV;
+		goto err_func_unrgtr;
+	}
+
 	return 0;
+
+err_func_unrgtr:
+	bnge_fw_unregister_dev(bd);
+	return rc;
 }
 
 static void bnge_pci_disable(struct pci_dev *pdev)
@@ -142,14 +197,46 @@ static void bnge_unmap_bars(struct pci_dev *pdev)
 {
 	struct bnge_dev *bd = pci_get_drvdata(pdev);
 
+	if (bd->bar1) {
+		pci_iounmap(pdev, bd->bar1);
+		bd->bar1 = NULL;
+	}
+
 	if (bd->bar0) {
 		pci_iounmap(pdev, bd->bar0);
 		bd->bar0 = NULL;
 	}
 }
 
+static void bnge_set_max_func_irqs(struct bnge_dev *bd,
+				   unsigned int max_irqs)
+{
+	bd->hw_resc.max_irqs = max_irqs;
+}
+
+static int bnge_get_max_irq(struct pci_dev *pdev)
+{
+	u16 ctrl;
+
+	pci_read_config_word(pdev, pdev->msix_cap + PCI_MSIX_FLAGS, &ctrl);
+	return (ctrl & PCI_MSIX_FLAGS_QSIZE) + 1;
+}
+
+static int bnge_map_db_bar(struct bnge_dev *bd)
+{
+	if (!bd->db_size)
+		return -ENODEV;
+
+	bd->bar1 = pci_iomap(bd->pdev, 2, bd->db_size);
+	if (!bd->bar1)
+		return -ENOMEM;
+
+	return 0;
+}
+
 static int bnge_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
+	unsigned int max_irqs;
 	struct bnge_dev *bd;
 	int rc;
 
@@ -198,10 +285,41 @@ static int bnge_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_hwrm_cleanup;
 	}
 
+	max_irqs = bnge_get_max_irq(pdev);
+	bnge_set_max_func_irqs(bd, max_irqs);
+
+	bnge_aux_init_dflt_config(bd);
+
+	rc = bnge_net_init_dflt_config(bd);
+	if (rc) {
+		dev_err(&pdev->dev, "Error setting up default cfg to netdev rc = %d\n",
+			rc);
+		goto err_fw_reg;
+	}
+
+	rc = bnge_map_db_bar(bd);
+	if (rc) {
+		dev_err(&pdev->dev, "Failed mapping doorbell BAR rc = %d, aborting\n",
+			rc);
+		goto err_config_uninit;
+	}
+
+	rc = bnge_alloc_irqs(bd);
+	if (rc) {
+		dev_err(&pdev->dev, "Error IRQ allocation rc = %d\n", rc);
+		goto err_config_uninit;
+	}
+
 	pci_save_state(pdev);
 
 	return 0;
 
+err_config_uninit:
+	bnge_net_uninit_dflt_config(bd);
+
+err_fw_reg:
+	bnge_fw_unregister_dev(bd);
+
 err_hwrm_cleanup:
 	bnge_cleanup_hwrm_resources(bd);
 
@@ -221,6 +339,10 @@ static void bnge_remove_one(struct pci_dev *pdev)
 {
 	struct bnge_dev *bd = pci_get_drvdata(pdev);
 
+	bnge_free_irqs(bd);
+
+	bnge_net_uninit_dflt_config(bd);
+
 	bnge_fw_unregister_dev(bd);
 
 	bnge_cleanup_hwrm_resources(bd);
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
index 577ac5dcdd9b..ffdec285948e 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
@@ -647,3 +647,57 @@ int bnge_hwrm_vnic_qcaps(struct bnge_dev *bd)
 
 	return rc;
 }
+
+#define BNGE_CNPQ(q_profile)	\
+		((q_profile) ==	\
+		 QUEUE_QPORTCFG_RESP_QUEUE_ID0_SERVICE_PROFILE_LOSSY_ROCE_CNP)
+
+int bnge_hwrm_queue_qportcfg(struct bnge_dev *bd)
+{
+	struct hwrm_queue_qportcfg_output *resp;
+	struct hwrm_queue_qportcfg_input *req;
+	u8 i, j, *qptr;
+	bool no_rdma;
+	int rc = 0;
+
+	rc = hwrm_req_init(bd, req, HWRM_QUEUE_QPORTCFG);
+	if (rc)
+		return rc;
+
+	resp = hwrm_req_hold(bd, req);
+	rc = hwrm_req_send(bd, req);
+	if (rc)
+		goto qportcfg_exit;
+
+	if (!resp->max_configurable_queues) {
+		rc = -EINVAL;
+		goto qportcfg_exit;
+	}
+	bd->max_tc = resp->max_configurable_queues;
+	bd->max_lltc = resp->max_configurable_lossless_queues;
+	if (bd->max_tc > BNGE_MAX_QUEUE)
+		bd->max_tc = BNGE_MAX_QUEUE;
+
+	no_rdma = !bnge_is_roce_en(bd);
+	qptr = &resp->queue_id0;
+	for (i = 0, j = 0; i < bd->max_tc; i++) {
+		bd->q_info[j].queue_id = *qptr;
+		bd->q_ids[i] = *qptr++;
+		bd->q_info[j].queue_profile = *qptr++;
+		bd->tc_to_qidx[j] = j;
+		if (!BNGE_CNPQ(bd->q_info[j].queue_profile) || no_rdma)
+			j++;
+	}
+	bd->max_q = bd->max_tc;
+	bd->max_tc = max_t(u8, j, 1);
+
+	if (resp->queue_cfg_info & QUEUE_QPORTCFG_RESP_QUEUE_CFG_INFO_ASYM_CFG)
+		bd->max_tc = 1;
+
+	if (bd->max_lltc > bd->max_tc)
+		bd->max_lltc = bd->max_tc;
+
+qportcfg_exit:
+	hwrm_req_drop(bd, req);
+	return rc;
+}
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
index 59ec1899879a..6c03923eb559 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
@@ -22,5 +22,6 @@ int bnge_hwrm_func_qcaps(struct bnge_dev *bd);
 int bnge_hwrm_vnic_qcaps(struct bnge_dev *bd);
 int bnge_hwrm_func_qcfg(struct bnge_dev *bd);
 int bnge_hwrm_func_resc_qcaps(struct bnge_dev *bd);
+int bnge_hwrm_queue_qportcfg(struct bnge_dev *bd);
 
 #endif /* _BNGE_HWRM_LIB_H_ */
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_resc.c b/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
index 84f91e05a2b0..d98f8f9216e9 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
@@ -5,6 +5,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/ethtool.h>
+#include <linux/netdevice.h>
 
 #include "bnge.h"
 #include "bnge_hwrm.h"
@@ -28,6 +29,16 @@ static u16 bnge_get_max_func_irqs(struct bnge_dev *bd)
 	return min_t(u16, hw_resc->max_irqs, hw_resc->max_nqs);
 }
 
+static unsigned int bnge_get_max_func_stat_ctxs(struct bnge_dev *bd)
+{
+	return bd->hw_resc.max_stat_ctxs;
+}
+
+static unsigned int bnge_get_max_func_cp_rings(struct bnge_dev *bd)
+{
+	return bd->hw_resc.max_cp_rings;
+}
+
 static int bnge_aux_get_dflt_msix(struct bnge_dev *bd)
 {
 	int roce_msix = BNGE_MAX_ROCE_MSIX;
@@ -68,6 +79,20 @@ static u16 bnge_func_stat_ctxs_demand(struct bnge_dev *bd)
 	return bd->nq_nr_rings + bnge_aux_get_stat_ctxs(bd);
 }
 
+static int bnge_get_dflt_aux_stat_ctxs(struct bnge_dev *bd)
+{
+	int stat_ctx = 0;
+
+	if (bnge_is_roce_en(bd)) {
+		stat_ctx = BNGE_MIN_ROCE_STAT_CTXS;
+
+		if (!bd->pf.port_id && bd->port_count > 1)
+			stat_ctx++;
+	}
+
+	return stat_ctx;
+}
+
 static u16 bnge_nqs_demand(struct bnge_dev *bd)
 {
 	return bd->nq_nr_rings + bnge_aux_get_msix(bd);
@@ -395,3 +420,185 @@ void bnge_free_irqs(struct bnge_dev *bd)
 	kfree(bd->irq_tbl);
 	bd->irq_tbl = NULL;
 }
+
+static void _bnge_get_max_rings(struct bnge_dev *bd, u16 *max_rx,
+				u16 *max_tx, u16 *max_nq)
+{
+	struct bnge_hw_resc *hw_resc = &bd->hw_resc;
+	u16 max_ring_grps = 0, max_cp;
+	int rc;
+
+	*max_tx = hw_resc->max_tx_rings;
+	*max_rx = hw_resc->max_rx_rings;
+	*max_nq = min_t(int, bnge_get_max_func_irqs(bd),
+			hw_resc->max_stat_ctxs);
+	max_ring_grps = hw_resc->max_hw_ring_grps;
+	if (bnge_is_agg_reqd(bd))
+		*max_rx >>= 1;
+
+	max_cp = bnge_get_max_func_cp_rings(bd);
+
+	/* Fix RX and TX rings according to number of CPs available */
+	rc = bnge_fix_rings_count(max_rx, max_tx, max_cp, false);
+	if (rc) {
+		*max_rx = 0;
+		*max_tx = 0;
+	}
+
+	*max_rx = min_t(int, *max_rx, max_ring_grps);
+}
+
+static int bnge_get_max_rings(struct bnge_dev *bd, u16 *max_rx,
+			      u16 *max_tx, bool shared)
+{
+	u16 rx, tx, nq;
+
+	_bnge_get_max_rings(bd, &rx, &tx, &nq);
+	*max_rx = rx;
+	*max_tx = tx;
+	if (!rx || !tx || !nq)
+		return -ENOMEM;
+
+	return bnge_fix_rings_count(max_rx, max_tx, nq, shared);
+}
+
+static int bnge_get_dflt_rings(struct bnge_dev *bd, u16 *max_rx, u16 *max_tx,
+			       bool shared)
+{
+	int rc;
+
+	rc = bnge_get_max_rings(bd, max_rx, max_tx, shared);
+	if (rc) {
+		dev_info(bd->dev, "Not enough rings available\n");
+		return rc;
+	}
+
+	if (bnge_is_roce_en(bd)) {
+		int max_cp, max_stat, max_irq;
+
+		/* Reserve minimum resources for RoCE */
+		max_cp = bnge_get_max_func_cp_rings(bd);
+		max_stat = bnge_get_max_func_stat_ctxs(bd);
+		max_irq = bnge_get_max_func_irqs(bd);
+		if (max_cp <= BNGE_MIN_ROCE_CP_RINGS ||
+		    max_irq <= BNGE_MIN_ROCE_CP_RINGS ||
+		    max_stat <= BNGE_MIN_ROCE_STAT_CTXS)
+			return 0;
+
+		max_cp -= BNGE_MIN_ROCE_CP_RINGS;
+		max_irq -= BNGE_MIN_ROCE_CP_RINGS;
+		max_stat -= BNGE_MIN_ROCE_STAT_CTXS;
+		max_cp = min_t(u16, max_cp, max_irq);
+		max_cp = min_t(u16, max_cp, max_stat);
+		rc = bnge_adjust_rings(bd, max_rx, max_tx, max_cp, shared);
+		if (rc)
+			rc = 0;
+	}
+
+	return rc;
+}
+
+/* In initial default shared ring setting, each shared ring must have a
+ * RX/TX ring pair.
+ */
+static void bnge_trim_dflt_sh_rings(struct bnge_dev *bd)
+{
+	bd->nq_nr_rings = min_t(u16, bd->tx_nr_rings_per_tc, bd->rx_nr_rings);
+	bd->rx_nr_rings = bd->nq_nr_rings;
+	bd->tx_nr_rings_per_tc = bd->nq_nr_rings;
+	bd->tx_nr_rings = bd->tx_nr_rings_per_tc;
+}
+
+static int bnge_net_init_dflt_rings(struct bnge_dev *bd, bool sh)
+{
+	u16 dflt_rings, max_rx_rings, max_tx_rings, rc;
+
+	if (sh)
+		bd->flags |= BNGE_EN_SHARED_CHNL;
+
+	dflt_rings = netif_get_num_default_rss_queues();
+
+	rc = bnge_get_dflt_rings(bd, &max_rx_rings, &max_tx_rings, sh);
+	if (rc)
+		return rc;
+	bd->rx_nr_rings = min_t(u16, dflt_rings, max_rx_rings);
+	bd->tx_nr_rings_per_tc = min_t(u16, dflt_rings, max_tx_rings);
+	if (sh)
+		bnge_trim_dflt_sh_rings(bd);
+	else
+		bd->nq_nr_rings = bd->tx_nr_rings_per_tc + bd->rx_nr_rings;
+	bd->tx_nr_rings = bd->tx_nr_rings_per_tc;
+
+	rc = bnge_reserve_rings(bd);
+	if (rc && rc != -ENODEV)
+		dev_warn(bd->dev, "Unable to reserve tx rings\n");
+	bd->tx_nr_rings_per_tc = bd->tx_nr_rings;
+	if (sh)
+		bnge_trim_dflt_sh_rings(bd);
+
+	/* Rings may have been reduced, re-reserve them again */
+	if (bnge_need_reserve_rings(bd)) {
+		rc = bnge_reserve_rings(bd);
+		if (rc && rc != -ENODEV)
+			dev_warn(bd->dev, "Fewer rings reservation failed\n");
+		bd->tx_nr_rings_per_tc = bd->tx_nr_rings;
+	}
+	if (rc) {
+		bd->tx_nr_rings = 0;
+		bd->rx_nr_rings = 0;
+	}
+
+	return rc;
+}
+
+static int bnge_alloc_rss_indir_tbl(struct bnge_dev *bd)
+{
+	u16 entries;
+
+	entries = BNGE_MAX_RSS_TABLE_ENTRIES;
+
+	bd->rss_indir_tbl_entries = entries;
+	bd->rss_indir_tbl =
+		kmalloc_array(entries, sizeof(*bd->rss_indir_tbl), GFP_KERNEL);
+	if (!bd->rss_indir_tbl)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int bnge_net_init_dflt_config(struct bnge_dev *bd)
+{
+	struct bnge_hw_resc *hw_resc;
+	int rc;
+
+	rc = bnge_alloc_rss_indir_tbl(bd);
+	if (rc)
+		return rc;
+
+	rc = bnge_net_init_dflt_rings(bd, true);
+	if (rc)
+		goto err_free_tbl;
+
+	hw_resc = &bd->hw_resc;
+	bd->max_fltr = hw_resc->max_rx_em_flows + hw_resc->max_rx_wm_flows +
+		       BNGE_L2_FLTR_MAX_FLTR;
+
+	return 0;
+
+err_free_tbl:
+	kfree(bd->rss_indir_tbl);
+	bd->rss_indir_tbl = NULL;
+	return rc;
+}
+
+void bnge_net_uninit_dflt_config(struct bnge_dev *bd)
+{
+	kfree(bd->rss_indir_tbl);
+	bd->rss_indir_tbl = NULL;
+}
+
+void bnge_aux_init_dflt_config(struct bnge_dev *bd)
+{
+	bd->aux_num_msix = bnge_aux_get_dflt_msix(bd);
+	bd->aux_num_stat_ctxs = bnge_get_dflt_aux_stat_ctxs(bd);
+}
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_resc.h b/drivers/net/ethernet/broadcom/bnge/bnge_resc.h
index 23db93e03787..b39fd1a7a81b 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_resc.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_resc.h
@@ -66,6 +66,9 @@ int bnge_reserve_rings(struct bnge_dev *bd);
 int bnge_fix_rings_count(u16 *rx, u16 *tx, u16 max, bool shared);
 int bnge_alloc_irqs(struct bnge_dev *bd);
 void bnge_free_irqs(struct bnge_dev *bd);
+int bnge_net_init_dflt_config(struct bnge_dev *bd);
+void bnge_net_uninit_dflt_config(struct bnge_dev *bd);
+void bnge_aux_init_dflt_config(struct bnge_dev *bd);
 
 static inline u32
 bnge_adjust_pow_two(u32 total_ent, u16 ent_per_blk)
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [net-next, 10/10] bng_en: Add a network device
  2025-06-18 14:47 [net-next, 00/10] Introducing Broadcom BNGE Ethernet Driver Vikas Gupta
                   ` (8 preceding siblings ...)
  2025-06-18 14:47 ` [net-next, 09/10] bng_en: Initialize default configuration Vikas Gupta
@ 2025-06-18 14:47 ` Vikas Gupta
  2025-06-24  0:42   ` kernel test robot
  9 siblings, 1 reply; 37+ messages in thread
From: Vikas Gupta @ 2025-06-18 14:47 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Add a network device with netdev features enabled.
Some features are enabled based on the capabilities
advertised by the firmware. Add the skeleton of minimal
netdev operations. Additionally, initialize the parameters
for rings (TX/RX/Completion).

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>
---
 drivers/net/ethernet/broadcom/bnge/Makefile   |   4 +-
 drivers/net/ethernet/broadcom/bnge/bnge.h     |  12 +
 .../net/ethernet/broadcom/bnge/bnge_core.c    |   9 +
 .../net/ethernet/broadcom/bnge/bnge_ethtool.c |  33 +++
 .../net/ethernet/broadcom/bnge/bnge_ethtool.h |   9 +
 .../net/ethernet/broadcom/bnge/bnge_netdev.c  | 266 ++++++++++++++++++
 .../net/ethernet/broadcom/bnge/bnge_netdev.h  | 206 ++++++++++++++
 .../net/ethernet/broadcom/bnge/bnge_resc.h    |   3 +
 8 files changed, 541 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_ethtool.h
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
 create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_netdev.h

diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethernet/broadcom/bnge/Makefile
index 10df05b6695e..6142d9c57f49 100644
--- a/drivers/net/ethernet/broadcom/bnge/Makefile
+++ b/drivers/net/ethernet/broadcom/bnge/Makefile
@@ -7,4 +7,6 @@ bng_en-y := bnge_core.o \
 	    bnge_hwrm.o \
 	    bnge_hwrm_lib.o \
 	    bnge_rmem.o \
-	    bnge_resc.o
+	    bnge_resc.o \
+	    bnge_netdev.o \
+	    bnge_ethtool.o
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
index 06465b318f5c..7cdf99b40806 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
@@ -65,6 +65,7 @@ enum {
 	BNGE_EN_ROCE_V2					= BIT_ULL(1),
 	BNGE_EN_STRIP_VLAN				= BIT_ULL(2),
 	BNGE_EN_SHARED_CHNL				= BIT_ULL(3),
+	BNGE_EN_UDP_GSO_SUPP				= BIT_ULL(4),
 };
 
 #define BNGE_EN_ROCE		(BNGE_EN_ROCE_V1 | BNGE_EN_ROCE_V2)
@@ -89,6 +90,7 @@ struct bnge_queue_info {
 struct bnge_dev {
 	struct device	*dev;
 	struct pci_dev	*pdev;
+	struct net_device	*netdev;
 	u64	dsn;
 #define BNGE_VPD_FLD_LEN	32
 	char		board_partno[BNGE_VPD_FLD_LEN];
@@ -198,6 +200,16 @@ static inline bool bnge_is_roce_en(struct bnge_dev *bd)
 
 static inline bool bnge_is_agg_reqd(struct bnge_dev *bd)
 {
+	if (bd->netdev) {
+		struct bnge_net *bn = netdev_priv(bd->netdev);
+
+		if (bn->priv_flags & BNGE_NET_EN_TPA ||
+		    bn->priv_flags & BNGE_NET_EN_JUMBO)
+			return true;
+		else
+			return false;
+	}
+
 	return true;
 }
 
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_core.c b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
index bad77973f100..dc7a33c6024d 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_core.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
@@ -310,10 +310,17 @@ static int bnge_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_config_uninit;
 	}
 
+	rc = bnge_netdev_alloc(bd, max_irqs);
+	if (rc)
+		goto err_free_irq;
+
 	pci_save_state(pdev);
 
 	return 0;
 
+err_free_irq:
+	bnge_free_irqs(bd);
+
 err_config_uninit:
 	bnge_net_uninit_dflt_config(bd);
 
@@ -339,6 +346,8 @@ static void bnge_remove_one(struct pci_dev *pdev)
 {
 	struct bnge_dev *bd = pci_get_drvdata(pdev);
 
+	bnge_netdev_free(bd);
+
 	bnge_free_irqs(bd);
 
 	bnge_net_uninit_dflt_config(bd);
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c b/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c
new file mode 100644
index 000000000000..5cf0ca1d7014
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2025 Broadcom.
+
+#include <linux/unaligned.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <net/devlink.h>
+#include <linux/ethtool.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool_netlink.h>
+
+#include "bnge.h"
+#include "bnge_ethtool.h"
+
+static void bnge_get_drvinfo(struct net_device *dev,
+			     struct ethtool_drvinfo *info)
+{
+	struct bnge_net *bn = netdev_priv(dev);
+	struct bnge_dev *bd = bn->bd;
+
+	strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+	strscpy(info->fw_version, bd->fw_ver_str, sizeof(info->fw_version));
+	strscpy(info->bus_info, pci_name(bd->pdev), sizeof(info->bus_info));
+}
+
+const struct ethtool_ops bnge_ethtool_ops = {
+	.get_drvinfo		= bnge_get_drvinfo,
+};
+
+void bnge_set_ethtool_ops(struct net_device *dev)
+{
+	dev->ethtool_ops = &bnge_ethtool_ops;
+}
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.h b/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.h
new file mode 100644
index 000000000000..21e96a0976d5
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2025 Broadcom */
+
+#ifndef _BNGE_ETHTOOL_H_
+#define _BNGE_ETHTOOL_H_
+
+void bnge_set_ethtool_ops(struct net_device *dev);
+
+#endif /* _BNGE_ETHTOOL_H_ */
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
new file mode 100644
index 000000000000..f71418e8fa09
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2025 Broadcom.
+
+#include <asm/byteorder.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if.h>
+#include <net/ip.h>
+#include <linux/skbuff.h>
+
+#include "bnge.h"
+#include "bnge_hwrm_lib.h"
+#include "bnge_ethtool.h"
+
+static netdev_tx_t bnge_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	return NETDEV_TX_OK;
+}
+
+static int bnge_open(struct net_device *dev)
+{
+	return 0;
+}
+
+static int bnge_close(struct net_device *dev)
+{
+	return 0;
+}
+
+static const struct net_device_ops bnge_netdev_ops = {
+	.ndo_open		= bnge_open,
+	.ndo_stop		= bnge_close,
+	.ndo_start_xmit		= bnge_start_xmit,
+};
+
+static void bnge_init_mac_addr(struct bnge_dev *bd)
+{
+	eth_hw_addr_set(bd->netdev, bd->pf.mac_addr);
+}
+
+static void bnge_set_tpa_flags(struct bnge_dev *bd)
+{
+	struct bnge_net *bn = netdev_priv(bd->netdev);
+
+	bn->priv_flags &= ~BNGE_NET_EN_TPA;
+
+	if (bd->netdev->features & NETIF_F_LRO)
+		bn->priv_flags |= BNGE_NET_EN_LRO;
+	else if (bd->netdev->features & NETIF_F_GRO_HW)
+		bn->priv_flags |= BNGE_NET_EN_GRO;
+}
+
+static void bnge_init_l2_fltr_tbl(struct bnge_net *bn)
+{
+	int i;
+
+	for (i = 0; i < BNGE_L2_FLTR_HASH_SIZE; i++)
+		INIT_HLIST_HEAD(&bn->l2_fltr_hash_tbl[i]);
+	get_random_bytes(&bn->hash_seed, sizeof(bn->hash_seed));
+}
+
+void bnge_set_ring_params(struct bnge_dev *bd)
+{
+	struct bnge_net *bn = netdev_priv(bd->netdev);
+	u32 ring_size, rx_size, rx_space, max_rx_cmpl;
+	u32 agg_factor = 0, agg_ring_size = 0;
+
+	/* 8 for CRC and VLAN */
+	rx_size = SKB_DATA_ALIGN(bn->netdev->mtu + ETH_HLEN + NET_IP_ALIGN + 8);
+
+	rx_space = rx_size + ALIGN(NET_SKB_PAD, 8) +
+		SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
+	bn->rx_copy_thresh = BNGE_RX_COPY_THRESH;
+	ring_size = bn->rx_ring_size;
+	bn->rx_agg_ring_size = 0;
+	bn->rx_agg_nr_pages = 0;
+
+	if (bn->priv_flags & BNGE_NET_EN_TPA)
+		agg_factor = min_t(u32, 4, 65536 / BNGE_RX_PAGE_SIZE);
+
+	bn->priv_flags &= ~BNGE_NET_EN_JUMBO;
+	if (rx_space > PAGE_SIZE) {
+		u32 jumbo_factor;
+
+		bn->priv_flags |= BNGE_NET_EN_JUMBO;
+		jumbo_factor = PAGE_ALIGN(bn->netdev->mtu - 40) >> PAGE_SHIFT;
+		if (jumbo_factor > agg_factor)
+			agg_factor = jumbo_factor;
+	}
+	if (agg_factor) {
+		if (ring_size > BNGE_MAX_RX_DESC_CNT_JUM_ENA) {
+			ring_size = BNGE_MAX_RX_DESC_CNT_JUM_ENA;
+			netdev_warn(bn->netdev, "RX ring size reduced from %d to %d due to jumbo ring\n",
+				    bn->rx_ring_size, ring_size);
+			bn->rx_ring_size = ring_size;
+		}
+		agg_ring_size = ring_size * agg_factor;
+
+		bn->rx_agg_nr_pages = bnge_adjust_pow_two(agg_ring_size,
+							  RX_DESC_CNT);
+		if (bn->rx_agg_nr_pages > MAX_RX_AGG_PAGES) {
+			u32 tmp = agg_ring_size;
+
+			bn->rx_agg_nr_pages = MAX_RX_AGG_PAGES;
+			agg_ring_size = MAX_RX_AGG_PAGES * RX_DESC_CNT - 1;
+			netdev_warn(bn->netdev, "RX agg ring size %d reduced to %d.\n",
+				    tmp, agg_ring_size);
+		}
+		bn->rx_agg_ring_size = agg_ring_size;
+		bn->rx_agg_ring_mask = (bn->rx_agg_nr_pages * RX_DESC_CNT) - 1;
+
+		rx_size = SKB_DATA_ALIGN(BNGE_RX_COPY_THRESH + NET_IP_ALIGN);
+		rx_space = rx_size + NET_SKB_PAD +
+			SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+	}
+
+	bn->rx_buf_use_size = rx_size;
+	bn->rx_buf_size = rx_space;
+
+	bn->rx_nr_pages = bnge_adjust_pow_two(ring_size, RX_DESC_CNT);
+	bn->rx_ring_mask = (bn->rx_nr_pages * RX_DESC_CNT) - 1;
+
+	ring_size = bn->tx_ring_size;
+	bn->tx_nr_pages = bnge_adjust_pow_two(ring_size, TX_DESC_CNT);
+	bn->tx_ring_mask = (bn->tx_nr_pages * TX_DESC_CNT) - 1;
+
+	max_rx_cmpl = bn->rx_ring_size;
+
+	if (bn->priv_flags & BNGE_NET_EN_TPA)
+		max_rx_cmpl += bd->max_tpa_v2;
+	ring_size = max_rx_cmpl * 2 + agg_ring_size + bn->tx_ring_size;
+	bn->cp_ring_size = ring_size;
+
+	bn->cp_nr_pages = bnge_adjust_pow_two(ring_size, CP_DESC_CNT);
+	if (bn->cp_nr_pages > MAX_CP_PAGES) {
+		bn->cp_nr_pages = MAX_CP_PAGES;
+		bn->cp_ring_size = MAX_CP_PAGES * CP_DESC_CNT - 1;
+		netdev_warn(bn->netdev, "completion ring size %d reduced to %d.\n",
+			    ring_size, bn->cp_ring_size);
+	}
+	bn->cp_bit = bn->cp_nr_pages * CP_DESC_CNT;
+	bn->cp_ring_mask = bn->cp_bit - 1;
+}
+
+int bnge_netdev_alloc(struct bnge_dev *bd, int max_irqs)
+{
+	struct net_device *netdev;
+	struct bnge_net *bn;
+	int rc;
+
+	netdev = alloc_etherdev_mqs(sizeof(*bn), max_irqs * BNGE_MAX_QUEUE,
+				    max_irqs);
+	if (!netdev)
+		return -ENOMEM;
+
+	SET_NETDEV_DEV(netdev, bd->dev);
+	bd->netdev = netdev;
+
+	netdev->netdev_ops = &bnge_netdev_ops;
+
+	bnge_set_ethtool_ops(netdev);
+
+	bn = netdev_priv(netdev);
+	bn->netdev = netdev;
+	bn->bd = bd;
+
+	netdev->min_mtu = ETH_ZLEN;
+	netdev->max_mtu = bd->max_mtu;
+
+	netdev->hw_features = NETIF_F_IP_CSUM |
+			      NETIF_F_IPV6_CSUM |
+			      NETIF_F_SG |
+			      NETIF_F_TSO |
+			      NETIF_F_TSO6 |
+			      NETIF_F_GSO_UDP_TUNNEL |
+			      NETIF_F_GSO_GRE |
+			      NETIF_F_GSO_IPXIP4 |
+			      NETIF_F_GSO_UDP_TUNNEL_CSUM |
+			      NETIF_F_GSO_GRE_CSUM |
+			      NETIF_F_GSO_PARTIAL |
+			      NETIF_F_RXHASH |
+			      NETIF_F_RXCSUM |
+			      NETIF_F_GRO;
+
+	if (bd->flags & BNGE_EN_UDP_GSO_SUPP)
+		netdev->hw_features |= NETIF_F_GSO_UDP_L4;
+
+	if (BNGE_SUPPORTS_TPA(bd))
+		netdev->hw_features |= NETIF_F_LRO;
+
+	netdev->hw_enc_features = NETIF_F_IP_CSUM |
+				  NETIF_F_IPV6_CSUM |
+				  NETIF_F_SG |
+				  NETIF_F_TSO |
+				  NETIF_F_TSO6 |
+				  NETIF_F_GSO_UDP_TUNNEL |
+				  NETIF_F_GSO_GRE |
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM |
+				  NETIF_F_GSO_GRE_CSUM |
+				  NETIF_F_GSO_IPXIP4 |
+				  NETIF_F_GSO_PARTIAL;
+
+	if (bd->flags & BNGE_EN_UDP_GSO_SUPP)
+		netdev->hw_enc_features |= NETIF_F_GSO_UDP_L4;
+
+	netdev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM |
+				       NETIF_F_GSO_GRE_CSUM;
+
+	netdev->vlan_features = netdev->hw_features | NETIF_F_HIGHDMA;
+	if (bd->fw_cap & BNGE_FW_CAP_VLAN_RX_STRIP)
+		netdev->hw_features |= BNGE_HW_FEATURE_VLAN_ALL_RX;
+	if (bd->fw_cap & BNGE_FW_CAP_VLAN_TX_INSERT)
+		netdev->hw_features |= BNGE_HW_FEATURE_VLAN_ALL_TX;
+
+	if (BNGE_SUPPORTS_TPA(bd))
+		netdev->hw_features |= NETIF_F_GRO_HW;
+
+	netdev->features |= netdev->hw_features | NETIF_F_HIGHDMA;
+
+	if (netdev->features & NETIF_F_GRO_HW)
+		netdev->features &= ~NETIF_F_LRO;
+
+	netdev->priv_flags |= IFF_UNICAST_FLT;
+
+	netif_set_tso_max_size(netdev, GSO_MAX_SIZE);
+	if (bd->tso_max_segs)
+		netif_set_tso_max_segs(netdev, bd->tso_max_segs);
+
+	bn->rx_ring_size = BNGE_DEFAULT_RX_RING_SIZE;
+	bn->tx_ring_size = BNGE_DEFAULT_TX_RING_SIZE;
+
+	bnge_set_tpa_flags(bd);
+	bnge_set_ring_params(bd);
+
+	bnge_init_l2_fltr_tbl(bn);
+	bnge_init_mac_addr(bd);
+
+	rc = register_netdev(netdev);
+	if (rc) {
+		dev_err(bd->dev, "Register netdev failed rc: %d\n", rc);
+		goto err_netdev;
+	}
+
+	return 0;
+
+err_netdev:
+	free_netdev(netdev);
+	return rc;
+}
+
+void bnge_netdev_free(struct bnge_dev *bd)
+{
+	struct net_device *netdev = bd->netdev;
+
+	unregister_netdev(netdev);
+	free_netdev(netdev);
+	bd->netdev = NULL;
+}
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h
new file mode 100644
index 000000000000..e8eb6074a83c
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h
@@ -0,0 +1,206 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2025 Broadcom */
+
+#ifndef _BNGE_NETDEV_H_
+#define _BNGE_NETDEV_H_
+
+#include "../bnxt/bnxt_hsi.h"
+
+struct tx_bd {
+	__le32 tx_bd_len_flags_type;
+	#define TX_BD_TYPE					(0x3f << 0)
+	#define TX_BD_TYPE_SHORT_TX_BD				(0x00 << 0)
+	#define TX_BD_TYPE_LONG_TX_BD				(0x10 << 0)
+	#define TX_BD_FLAGS_PACKET_END				(1 << 6)
+	#define TX_BD_FLAGS_NO_CMPL				(1 << 7)
+	#define TX_BD_FLAGS_BD_CNT				(0x1f << 8)
+	#define TX_BD_FLAGS_BD_CNT_SHIFT			8
+	#define TX_BD_FLAGS_LHINT				(3 << 13)
+	#define TX_BD_FLAGS_LHINT_SHIFT				13
+	#define TX_BD_FLAGS_LHINT_512_AND_SMALLER		(0 << 13)
+	#define TX_BD_FLAGS_LHINT_512_TO_1023			(1 << 13)
+	#define TX_BD_FLAGS_LHINT_1024_TO_2047			(2 << 13)
+	#define TX_BD_FLAGS_LHINT_2048_AND_LARGER		(3 << 13)
+	#define TX_BD_FLAGS_COAL_NOW				(1 << 15)
+	#define TX_BD_LEN					(0xffff << 16)
+	#define TX_BD_LEN_SHIFT					16
+	u32 tx_bd_opaque;
+	__le64 tx_bd_haddr;
+} __packed;
+
+struct rx_bd {
+	__le32 rx_bd_len_flags_type;
+	#define RX_BD_TYPE					(0x3f << 0)
+	#define RX_BD_TYPE_RX_PACKET_BD				0x4
+	#define RX_BD_TYPE_RX_BUFFER_BD				0x5
+	#define RX_BD_TYPE_RX_AGG_BD				0x6
+	#define RX_BD_TYPE_16B_BD_SIZE				(0 << 4)
+	#define RX_BD_TYPE_32B_BD_SIZE				(1 << 4)
+	#define RX_BD_TYPE_48B_BD_SIZE				(2 << 4)
+	#define RX_BD_TYPE_64B_BD_SIZE				(3 << 4)
+	#define RX_BD_FLAGS_SOP					(1 << 6)
+	#define RX_BD_FLAGS_EOP					(1 << 7)
+	#define RX_BD_FLAGS_BUFFERS				(3 << 8)
+	#define RX_BD_FLAGS_1_BUFFER_PACKET			(0 << 8)
+	#define RX_BD_FLAGS_2_BUFFER_PACKET			(1 << 8)
+	#define RX_BD_FLAGS_3_BUFFER_PACKET			(2 << 8)
+	#define RX_BD_FLAGS_4_BUFFER_PACKET			(3 << 8)
+	#define RX_BD_LEN					(0xffff << 16)
+	#define RX_BD_LEN_SHIFT					16
+	u32 rx_bd_opaque;
+	__le64 rx_bd_haddr;
+};
+
+struct tx_cmp {
+	__le32 tx_cmp_flags_type;
+	#define CMP_TYPE					(0x3f << 0)
+	#define CMP_TYPE_TX_L2_CMP				0
+	#define CMP_TYPE_TX_L2_COAL_CMP				2
+	#define CMP_TYPE_TX_L2_PKT_TS_CMP			4
+	#define CMP_TYPE_RX_L2_CMP				17
+	#define CMP_TYPE_RX_AGG_CMP				18
+	#define CMP_TYPE_RX_L2_TPA_START_CMP			19
+	#define CMP_TYPE_RX_L2_TPA_END_CMP			21
+	#define CMP_TYPE_RX_TPA_AGG_CMP				22
+	#define CMP_TYPE_RX_L2_V3_CMP				23
+	#define CMP_TYPE_RX_L2_TPA_START_V3_CMP			25
+	#define CMP_TYPE_STATUS_CMP				32
+	#define CMP_TYPE_REMOTE_DRIVER_REQ			34
+	#define CMP_TYPE_REMOTE_DRIVER_RESP			36
+	#define CMP_TYPE_ERROR_STATUS				48
+	#define CMPL_BASE_TYPE_STAT_EJECT			0x1aUL
+	#define CMPL_BASE_TYPE_HWRM_DONE			0x20UL
+	#define CMPL_BASE_TYPE_HWRM_FWD_REQ			0x22UL
+	#define CMPL_BASE_TYPE_HWRM_FWD_RESP			0x24UL
+	#define CMPL_BASE_TYPE_HWRM_ASYNC_EVENT			0x2eUL
+	#define TX_CMP_FLAGS_ERROR				(1 << 6)
+	#define TX_CMP_FLAGS_PUSH				(1 << 7)
+	u32 tx_cmp_opaque;
+	__le32 tx_cmp_errors_v;
+	#define TX_CMP_V					(1 << 0)
+	#define TX_CMP_ERRORS_BUFFER_ERROR			(7 << 1)
+	#define TX_CMP_ERRORS_BUFFER_ERROR_NO_ERROR		0
+	#define TX_CMP_ERRORS_BUFFER_ERROR_BAD_FORMAT		2
+	#define TX_CMP_ERRORS_BUFFER_ERROR_INVALID_STAG		4
+	#define TX_CMP_ERRORS_BUFFER_ERROR_STAG_BOUNDS		5
+	#define TX_CMP_ERRORS_ZERO_LENGTH_PKT			(1 << 4)
+	#define TX_CMP_ERRORS_EXCESSIVE_BD_LEN			(1 << 5)
+	#define TX_CMP_ERRORS_DMA_ERROR				(1 << 6)
+	#define TX_CMP_ERRORS_HINT_TOO_SHORT			(1 << 7)
+	__le32 sq_cons_idx;
+	#define TX_CMP_SQ_CONS_IDX_MASK				0x00ffffff
+};
+
+struct bnge_sw_tx_bd {
+	struct sk_buff		*skb;
+	DEFINE_DMA_UNMAP_ADDR(mapping);
+	DEFINE_DMA_UNMAP_LEN(len);
+	struct page		*page;
+	u8			is_ts_pkt;
+	u8			is_push;
+	u8			action;
+	unsigned short		nr_frags;
+	union {
+		u16		rx_prod;
+		u16		txts_prod;
+	};
+};
+
+struct bnge_sw_rx_bd {
+	void			*data;
+	u8			*data_ptr;
+	dma_addr_t		mapping;
+};
+
+struct bnge_sw_rx_agg_bd {
+	struct page		*page;
+	unsigned int		offset;
+	dma_addr_t		mapping;
+};
+
+#define BNGE_RX_COPY_THRESH     256
+
+#define BNGE_HW_FEATURE_VLAN_ALL_RX	\
+		(NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)
+#define BNGE_HW_FEATURE_VLAN_ALL_TX	\
+		(NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX)
+
+enum {
+	BNGE_NET_EN_GRO		= BIT(0),
+	BNGE_NET_EN_LRO		= BIT(1),
+	BNGE_NET_EN_JUMBO	= BIT(2),
+};
+
+#define BNGE_NET_EN_TPA		(BNGE_NET_EN_GRO | BNGE_NET_EN_LRO)
+
+struct bnge_net {
+	struct bnge_dev		*bd;
+	struct net_device	*netdev;
+
+	u32			priv_flags;
+
+	u32			rx_ring_size;
+	u32			rx_buf_size;
+	u32			rx_buf_use_size; /* useable size */
+	u32			rx_agg_ring_size;
+	u32			rx_copy_thresh;
+	u32			rx_ring_mask;
+	u32			rx_agg_ring_mask;
+	u16			rx_nr_pages;
+	u16			rx_agg_nr_pages;
+
+	u32			tx_ring_size;
+	u32			tx_ring_mask;
+	u16			tx_nr_pages;
+
+	/* NQs and Completion rings */
+	u32			cp_ring_size;
+	u32			cp_ring_mask;
+	u32			cp_bit;
+	u16			cp_nr_pages;
+
+#define BNGE_L2_FLTR_HASH_SIZE	32
+#define BNGE_L2_FLTR_HASH_MASK	(BNGE_L2_FLTR_HASH_SIZE - 1)
+	struct hlist_head	l2_fltr_hash_tbl[BNGE_L2_FLTR_HASH_SIZE];
+	u32			hash_seed;
+	u64			toeplitz_prefix;
+};
+
+#define BNGE_DEFAULT_RX_RING_SIZE	511
+#define BNGE_DEFAULT_TX_RING_SIZE	511
+
+int bnge_netdev_alloc(struct bnge_dev *bd, int max_irqs);
+void bnge_netdev_free(struct bnge_dev *bd);
+void bnge_set_ring_params(struct bnge_dev *bd);
+
+#if (BNGE_PAGE_SHIFT == 16)
+#define MAX_RX_PAGES_AGG_ENA	1
+#define MAX_RX_PAGES		4
+#define MAX_RX_AGG_PAGES	4
+#define MAX_TX_PAGES		1
+#define MAX_CP_PAGES		16
+#else
+#define MAX_RX_PAGES_AGG_ENA	8
+#define MAX_RX_PAGES		32
+#define MAX_RX_AGG_PAGES	32
+#define MAX_TX_PAGES		8
+#define MAX_CP_PAGES		128
+#endif
+
+#define BNGE_RX_PAGE_SIZE		(1 << BNGE_RX_PAGE_SHIFT)
+
+#define RX_DESC_CNT			(BNGE_PAGE_SIZE / sizeof(struct rx_bd))
+#define TX_DESC_CNT			(BNGE_PAGE_SIZE / sizeof(struct tx_bd))
+#define CP_DESC_CNT			(BNGE_PAGE_SIZE / sizeof(struct tx_cmp))
+#define SW_RXBD_RING_SIZE		(sizeof(struct bnge_sw_rx_bd) * RX_DESC_CNT)
+#define HW_RXBD_RING_SIZE		(sizeof(struct rx_bd) * RX_DESC_CNT)
+#define SW_RXBD_AGG_RING_SIZE		(sizeof(struct bnge_sw_rx_agg_bd) * RX_DESC_CNT)
+#define SW_TXBD_RING_SIZE		(sizeof(struct bnge_sw_tx_bd) * TX_DESC_CNT)
+#define HW_TXBD_RING_SIZE		(sizeof(struct tx_bd) * TX_DESC_CNT)
+#define HW_CMPD_RING_SIZE		(sizeof(struct tx_cmp) * CP_DESC_CNT)
+#define BNGE_MAX_RX_DESC_CNT		(RX_DESC_CNT * MAX_RX_PAGES - 1)
+#define BNGE_MAX_RX_DESC_CNT_JUM_ENA	(RX_DESC_CNT * MAX_RX_PAGES_AGG_ENA - 1)
+#define BNGE_MAX_RX_JUM_DESC_CNT	(RX_DESC_CNT * MAX_RX_AGG_PAGES - 1)
+#define BNGE_MAX_TX_DESC_CNT		(TX_DESC_CNT * MAX_TX_PAGES - 1)
+
+#endif /* _BNGE_NETDEV_H_ */
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_resc.h b/drivers/net/ethernet/broadcom/bnge/bnge_resc.h
index b39fd1a7a81b..54ef1c7d8822 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_resc.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_resc.h
@@ -4,6 +4,9 @@
 #ifndef _BNGE_RESC_H_
 #define _BNGE_RESC_H_
 
+#include "bnge_netdev.h"
+#include "bnge_rmem.h"
+
 struct bnge_hw_resc {
 	u16	min_rsscos_ctxs;
 	u16	max_rsscos_ctxs;
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [net-next, 09/10] bng_en: Initialize default configuration
  2025-06-18 14:47 ` [net-next, 09/10] bng_en: Initialize default configuration Vikas Gupta
@ 2025-06-18 20:16   ` kernel test robot
  2025-06-19 13:57   ` Vadim Fedorenko
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 37+ messages in thread
From: kernel test robot @ 2025-06-18 20:16 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: llvm, oe-kbuild-all, netdev, linux-kernel, michael.chan,
	pavan.chebbi, vsrama-krishna.nemani, Vikas Gupta,
	Bhargava Chenna Marreddy, Rajashekar Hudumula

Hi Vikas,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.16-rc2 next-20250618]
[cannot apply to horms-ipvs/master]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Vikas-Gupta/bng_en-Add-PCI-interface/20250618-173130
base:   linus/master
patch link:    https://lore.kernel.org/r/20250618144743.843815-10-vikas.gupta%40broadcom.com
patch subject: [net-next, 09/10] bng_en: Initialize default configuration
config: i386-randconfig-012-20250619 (https://download.01.org/0day-ci/archive/20250619/202506190321.0HgmyniP-lkp@intel.com/config)
compiler: clang version 20.1.2 (https://github.com/llvm/llvm-project 58df0ef89dd64126512e4ee27b4ac3fd8ddf6247)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250619/202506190321.0HgmyniP-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506190321.0HgmyniP-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/net/ethernet/broadcom/bnge/bnge_resc.c:533:15: warning: result of comparison of constant -19 with expression of type 'u16' (aka 'unsigned short') is always true [-Wtautological-constant-out-of-range-compare]
     533 |         if (rc && rc != -ENODEV)
         |                   ~~ ^  ~~~~~~~
   drivers/net/ethernet/broadcom/bnge/bnge_resc.c:542:16: warning: result of comparison of constant -19 with expression of type 'u16' (aka 'unsigned short') is always true [-Wtautological-constant-out-of-range-compare]
     542 |                 if (rc && rc != -ENODEV)
         |                           ~~ ^  ~~~~~~~
   2 warnings generated.


vim +533 drivers/net/ethernet/broadcom/bnge/bnge_resc.c

   511	
   512	static int bnge_net_init_dflt_rings(struct bnge_dev *bd, bool sh)
   513	{
   514		u16 dflt_rings, max_rx_rings, max_tx_rings, rc;
   515	
   516		if (sh)
   517			bd->flags |= BNGE_EN_SHARED_CHNL;
   518	
   519		dflt_rings = netif_get_num_default_rss_queues();
   520	
   521		rc = bnge_get_dflt_rings(bd, &max_rx_rings, &max_tx_rings, sh);
   522		if (rc)
   523			return rc;
   524		bd->rx_nr_rings = min_t(u16, dflt_rings, max_rx_rings);
   525		bd->tx_nr_rings_per_tc = min_t(u16, dflt_rings, max_tx_rings);
   526		if (sh)
   527			bnge_trim_dflt_sh_rings(bd);
   528		else
   529			bd->nq_nr_rings = bd->tx_nr_rings_per_tc + bd->rx_nr_rings;
   530		bd->tx_nr_rings = bd->tx_nr_rings_per_tc;
   531	
   532		rc = bnge_reserve_rings(bd);
 > 533		if (rc && rc != -ENODEV)
   534			dev_warn(bd->dev, "Unable to reserve tx rings\n");
   535		bd->tx_nr_rings_per_tc = bd->tx_nr_rings;
   536		if (sh)
   537			bnge_trim_dflt_sh_rings(bd);
   538	
   539		/* Rings may have been reduced, re-reserve them again */
   540		if (bnge_need_reserve_rings(bd)) {
   541			rc = bnge_reserve_rings(bd);
   542			if (rc && rc != -ENODEV)
   543				dev_warn(bd->dev, "Fewer rings reservation failed\n");
   544			bd->tx_nr_rings_per_tc = bd->tx_nr_rings;
   545		}
   546		if (rc) {
   547			bd->tx_nr_rings = 0;
   548			bd->rx_nr_rings = 0;
   549		}
   550	
   551		return rc;
   552	}
   553	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 03/10] bng_en: Add firmware communication mechanism
  2025-06-18 14:47 ` [net-next, 03/10] bng_en: Add firmware communication mechanism Vikas Gupta
@ 2025-06-19  9:46   ` kernel test robot
  2025-06-19 12:43   ` Vadim Fedorenko
  1 sibling, 0 replies; 37+ messages in thread
From: kernel test robot @ 2025-06-19  9:46 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: oe-kbuild-all, netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Hi Vikas,

kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on v6.16-rc2 next-20250618]
[cannot apply to horms-ipvs/master]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Vikas-Gupta/bng_en-Add-PCI-interface/20250618-173130
base:   linus/master
patch link:    https://lore.kernel.org/r/20250618144743.843815-4-vikas.gupta%40broadcom.com
patch subject: [net-next, 03/10] bng_en: Add firmware communication mechanism
config: parisc-randconfig-r073-20250619 (https://download.01.org/0day-ci/archive/20250619/202506191741.1C9E7i3x-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 8.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250619/202506191741.1C9E7i3x-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506191741.1C9E7i3x-lkp@intel.com/

All errors (new ones prefixed by >>):

   hppa-linux-ld: hppa-linux-ld: DWARF error: could not find abbrev number 1754059
   drivers/net/ethernet/broadcom/bnge/bnge_hwrm.o: in function `__hwrm_req_init':
>> bnge_hwrm.c:(.text+0x96c): multiple definition of `__hwrm_req_init'; hppa-linux-ld: DWARF error: could not find abbrev number 179644068
   drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.o:bnxt_hwrm.c:(.text+0xccc): first defined here
   hppa-linux-ld: drivers/net/ethernet/broadcom/bnge/bnge_hwrm.o: in function `hwrm_req_timeout':
>> bnge_hwrm.c:(.text+0xa90): multiple definition of `hwrm_req_timeout'; drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.o:bnxt_hwrm.c:(.text+0xdf0): first defined here
   hppa-linux-ld: drivers/net/ethernet/broadcom/bnge/bnge_hwrm.o: in function `hwrm_req_alloc_flags':
>> bnge_hwrm.c:(.text+0xac8): multiple definition of `hwrm_req_alloc_flags'; drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.o:bnxt_hwrm.c:(.text+0xe28): first defined here
   hppa-linux-ld: drivers/net/ethernet/broadcom/bnge/bnge_hwrm.o: in function `hwrm_req_flags':
>> bnge_hwrm.c:(.text+0xb00): multiple definition of `hwrm_req_flags'; drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.o:bnxt_hwrm.c:(.text+0xf9c): first defined here
   hppa-linux-ld: drivers/net/ethernet/broadcom/bnge/bnge_hwrm.o: in function `hwrm_req_hold':
>> bnge_hwrm.c:(.text+0xb48): multiple definition of `hwrm_req_hold'; drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.o:bnxt_hwrm.c:(.text+0xfe4): first defined here
   hppa-linux-ld: drivers/net/ethernet/broadcom/bnge/bnge_hwrm.o: in function `hwrm_req_drop':
>> bnge_hwrm.c:(.text+0xbd0): multiple definition of `hwrm_req_drop'; drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.o:bnxt_hwrm.c:(.text+0x106c): first defined here
   hppa-linux-ld: drivers/net/ethernet/broadcom/bnge/bnge_hwrm.o: in function `hwrm_req_send':
>> bnge_hwrm.c:(.text+0xc10): multiple definition of `hwrm_req_send'; drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.o:bnxt_hwrm.c:(.text+0x12f0): first defined here
   hppa-linux-ld: drivers/net/ethernet/broadcom/bnge/bnge_hwrm.o: in function `hwrm_req_send_silent':
>> bnge_hwrm.c:(.text+0xc50): multiple definition of `hwrm_req_send_silent'; drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.o:bnxt_hwrm.c:(.text+0x1330): first defined here
   hppa-linux-ld: drivers/net/ethernet/broadcom/bnge/bnge_hwrm.o: in function `hwrm_req_dma_slice':
>> bnge_hwrm.c:(.text+0xca8): multiple definition of `hwrm_req_dma_slice'; drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.o:bnxt_hwrm.c:(.text+0x1388): first defined here

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 01/10] bng_en: Add PCI interface
  2025-06-18 14:47 ` [net-next, 01/10] bng_en: Add PCI interface Vikas Gupta
@ 2025-06-19 12:25   ` Vadim Fedorenko
  0 siblings, 0 replies; 37+ messages in thread
From: Vadim Fedorenko @ 2025-06-19 12:25 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

On 18/06/2025 15:47, Vikas Gupta wrote:
> 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>
> ---
>   MAINTAINERS                                   |   6 +
>   drivers/net/ethernet/broadcom/Kconfig         |   8 +
>   drivers/net/ethernet/broadcom/Makefile        |   1 +
>   drivers/net/ethernet/broadcom/bnge/Makefile   |   5 +
>   drivers/net/ethernet/broadcom/bnge/bnge.h     |  16 ++
>   .../net/ethernet/broadcom/bnge/bnge_core.c    | 149 ++++++++++++++++++
>   6 files changed, 185 insertions(+)
>   create mode 100644 drivers/net/ethernet/broadcom/bnge/Makefile
>   create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge.h
>   create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_core.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 507c5ff6f620..af349b77a92e 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -4854,6 +4854,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
> diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
> index 81a74e07464f..e2c1ac91708e 100644
> --- a/drivers/net/ethernet/broadcom/Kconfig
> +++ b/drivers/net/ethernet/broadcom/Kconfig
> @@ -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
> diff --git a/drivers/net/ethernet/broadcom/Makefile b/drivers/net/ethernet/broadcom/Makefile
> index bac5cb6ad0cd..10cc1c92ecfc 100644
> --- a/drivers/net/ethernet/broadcom/Makefile
> +++ b/drivers/net/ethernet/broadcom/Makefile
> @@ -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
> index 000000000000..0c3d632805d1
> --- /dev/null
> +++ b/drivers/net/ethernet/broadcom/bnge/Makefile
> @@ -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
> index 000000000000..b49c51b44473
> --- /dev/null
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
> @@ -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
> index 000000000000..3778210da98d
> --- /dev/null
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
> @@ -0,0 +1,149 @@
> +// 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;
> +	}
> +
> +	if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) != 0 &&
> +	    dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)) != 0) {
> +		dev_err(&pdev->dev, "System does not support DMA, aborting\n");
> +		rc = -EIO;
> +		goto err_pci_release;
> +	}

According to https://docs.kernel.org/core-api/dma-api-howto.html the
code above is not correct. dma_set_mask_and_coherent() will never return
fail when DMA_BIT_MASK(64).


> +
> +	pci_set_master(pdev);
> +
> +	return 0;
> +
> +err_pci_release:
> +	pci_release_regions(pdev);
> +
> +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);


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 02/10] bng_en: Add devlink interface
  2025-06-18 14:47 ` [net-next, 02/10] bng_en: Add devlink interface Vikas Gupta
@ 2025-06-19 12:34   ` Vadim Fedorenko
  0 siblings, 0 replies; 37+ messages in thread
From: Vadim Fedorenko @ 2025-06-19 12:34 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

On 18/06/2025 15:47, Vikas Gupta wrote:
> Allocate a base device and devlink interface with minimal
> devlink ops.
> Add dsn and board related information.
> Map PCIe BAR (bar0), which helps to communicate with the
> firmware.
> 
> 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>
> ---
>   drivers/net/ethernet/broadcom/Kconfig         |   1 +
>   drivers/net/ethernet/broadcom/bnge/Makefile   |   3 +-
>   drivers/net/ethernet/broadcom/bnge/bnge.h     |  11 ++
>   .../net/ethernet/broadcom/bnge/bnge_core.c    |  43 +++++
>   .../net/ethernet/broadcom/bnge/bnge_devlink.c | 147 ++++++++++++++++++
>   .../net/ethernet/broadcom/bnge/bnge_devlink.h |  18 +++
>   6 files changed, 222 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
>   create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_devlink.h
> 
> diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
> index e2c1ac91708e..0fc10e6c6902 100644
> --- a/drivers/net/ethernet/broadcom/Kconfig
> +++ b/drivers/net/ethernet/broadcom/Kconfig
> @@ -256,6 +256,7 @@ config BNXT_HWMON
>   config BNGE
>   	tristate "Broadcom Ethernet device support"
>   	depends on PCI
> +	select NET_DEVLINK
>   	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,
> diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethernet/broadcom/bnge/Makefile
> index 0c3d632805d1..e021a14d2fa0 100644
> --- a/drivers/net/ethernet/broadcom/bnge/Makefile
> +++ b/drivers/net/ethernet/broadcom/bnge/Makefile
> @@ -2,4 +2,5 @@
>   
>   obj-$(CONFIG_BNGE) += bng_en.o
>   
> -bng_en-y := bnge_core.o
> +bng_en-y := bnge_core.o \
> +	    bnge_devlink.o
> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
> index b49c51b44473..19d85aabab4e 100644
> --- a/drivers/net/ethernet/broadcom/bnge/bnge.h
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
> @@ -13,4 +13,15 @@ enum board_idx {
>   	BCM57708,
>   };
>   
> +struct bnge_dev {
> +	struct device	*dev;
> +	struct pci_dev	*pdev;
> +	u64	dsn;
> +#define BNGE_VPD_FLD_LEN	32
> +	char		board_partno[BNGE_VPD_FLD_LEN];
> +	char		board_serialno[BNGE_VPD_FLD_LEN];
> +
> +	void __iomem	*bar0;
> +};
> +
>   #endif /* _BNGE_H_ */
> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_core.c b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
> index 3778210da98d..1a46c7663012 100644
> --- a/drivers/net/ethernet/broadcom/bnge/bnge_core.c
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
> @@ -7,6 +7,7 @@
>   #include <linux/pci.h>
>   
>   #include "bnge.h"
> +#include "bnge_devlink.h"
>   
>   MODULE_LICENSE("GPL");
>   MODULE_DESCRIPTION(DRV_SUMMARY);
> @@ -85,8 +86,19 @@ static int bnge_pci_enable(struct pci_dev *pdev)
>   	return rc;
>   }
>   
> +static void bnge_unmap_bars(struct pci_dev *pdev)
> +{
> +	struct bnge_dev *bd = pci_get_drvdata(pdev);
> +
> +	if (bd->bar0) {
> +		pci_iounmap(pdev, bd->bar0);
> +		bd->bar0 = NULL;
> +	}
> +}
> +
>   static int bnge_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>   {
> +	struct bnge_dev *bd;
>   	int rc;
>   
>   	if (pci_is_bridge(pdev))
> @@ -108,13 +120,44 @@ static int bnge_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>   
>   	bnge_print_device_info(pdev, ent->driver_data);
>   
> +	bd = bnge_devlink_alloc(pdev);
> +	if (!bd) {
> +		dev_err(&pdev->dev, "Devlink allocation failed\n");
> +		rc = -ENOMEM;
> +		goto err_pci_disable;
> +	}
> +
> +	bnge_devlink_register(bd);
> +
> +	bd->bar0 = pci_ioremap_bar(pdev, 0);
> +	if (!bd->bar0) {
> +		dev_err(&pdev->dev, "Failed mapping BAR-0, aborting\n");
> +		rc = -ENOMEM;
> +		goto err_devl_unreg;
> +	}
> +
>   	pci_save_state(pdev);
>   
>   	return 0;
> +
> +err_devl_unreg:
> +	bnge_devlink_unregister(bd);
> +	bnge_devlink_free(bd);
> +
> +err_pci_disable:
> +	bnge_pci_disable(pdev);
> +	return rc;
>   }
>   
>   static void bnge_remove_one(struct pci_dev *pdev)
>   {
> +	struct bnge_dev *bd = pci_get_drvdata(pdev);
> +
> +	bnge_unmap_bars(pdev);
> +
> +	bnge_devlink_unregister(bd);
> +	bnge_devlink_free(bd);
> +
>   	bnge_pci_disable(pdev);
>   }
>   
> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
> new file mode 100644
> index 000000000000..d406338da130
> --- /dev/null
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
> @@ -0,0 +1,147 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (c) 2025 Broadcom.
> +
> +#include <linux/unaligned.h>
> +#include <linux/pci.h>
> +#include <linux/types.h>
> +#include <net/devlink.h>
> +
> +#include "bnge.h"
> +#include "bnge_devlink.h"
> +
> +static int bnge_dl_info_put(struct bnge_dev *bd, struct devlink_info_req *req,
> +			    enum bnge_dl_version_type type, const char *key,
> +			    char *buf)
> +{
> +	if (!strlen(buf))
> +		return 0;
> +
> +	switch (type) {
> +	case BNGE_VERSION_FIXED:
> +		return devlink_info_version_fixed_put(req, key, buf);
> +	case BNGE_VERSION_RUNNING:
> +		return devlink_info_version_running_put(req, key, buf);
> +	case BNGE_VERSION_STORED:
> +		return devlink_info_version_stored_put(req, key, buf);
> +	}
> +
> +	return 0;
> +}
> +
> +static void bnge_vpd_read_info(struct bnge_dev *bd)
> +{
> +	struct pci_dev *pdev = bd->pdev;
> +	unsigned int vpd_size, kw_len;
> +	int pos, size;
> +	u8 *vpd_data;
> +
> +	vpd_data = pci_vpd_alloc(pdev, &vpd_size);
> +	if (IS_ERR(vpd_data)) {
> +		pci_warn(pdev, "Unable to read VPD\n");
> +		return;
> +	}
> +
> +	pos = pci_vpd_find_ro_info_keyword(vpd_data, vpd_size,
> +					   PCI_VPD_RO_KEYWORD_PARTNO, &kw_len);
> +	if (pos < 0)
> +		goto read_sn;
> +
> +	size = min_t(int, kw_len, BNGE_VPD_FLD_LEN - 1);
> +	memcpy(bd->board_partno, &vpd_data[pos], size);
> +
> +read_sn:
> +	pos = pci_vpd_find_ro_info_keyword(vpd_data, vpd_size,
> +					   PCI_VPD_RO_KEYWORD_SERIALNO,
> +					   &kw_len);
> +	if (pos < 0)
> +		goto exit;
> +
> +	size = min_t(int, kw_len, BNGE_VPD_FLD_LEN - 1);
> +	memcpy(bd->board_serialno, &vpd_data[pos], size);
> +
> +exit:
> +	kfree(vpd_data);
> +}
> +
> +static int bnge_devlink_info_get(struct devlink *devlink,
> +				 struct devlink_info_req *req,
> +				 struct netlink_ext_ack *extack)
> +{
> +	struct bnge_dev *bd = devlink_priv(devlink);
> +	int rc;
> +
> +	if (bd->dsn) {
> +		char buf[32];
> +		u8 dsn[8];
> +		int rc;
> +
> +		put_unaligned_le64(bd->dsn, dsn);
> +		sprintf(buf, "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",
> +			dsn[7], dsn[6], dsn[5], dsn[4],
> +			dsn[3], dsn[2], dsn[1], dsn[0]);
> +		rc = devlink_info_serial_number_put(req, buf);
> +		if (rc)
> +			return rc;
> +	}
> +
> +	if (strlen(bd->board_serialno)) {
> +		rc = devlink_info_board_serial_number_put(req,
> +							  bd->board_serialno);
> +		if (rc)
> +			return rc;
> +	}
> +
> +	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_FIXED,
> +			      DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
> +			      bd->board_partno);
> +
> +	return rc;

As extack is available, it may be a good idea to put a bit of readable
description into extack in error cases

> +}
> +
> +static const struct devlink_ops bnge_devlink_ops = {
> +	.info_get = bnge_devlink_info_get,
> +};
> +
> +void bnge_devlink_free(struct bnge_dev *bd)
> +{
> +	struct devlink *devlink = priv_to_devlink(bd);
> +
> +	devlink_free(devlink);
> +}
> +
> +struct bnge_dev *bnge_devlink_alloc(struct pci_dev *pdev)
> +{
> +	struct devlink *devlink;
> +	struct bnge_dev *bd;
> +
> +	devlink = devlink_alloc(&bnge_devlink_ops, sizeof(*bd), &pdev->dev);
> +	if (!devlink)
> +		return NULL;
> +
> +	bd = devlink_priv(devlink);
> +	pci_set_drvdata(pdev, bd);
> +	bd->dev = &pdev->dev;
> +	bd->pdev = pdev;
> +
> +	bd->dsn = pci_get_dsn(pdev);
> +	if (!bd->dsn)
> +		pci_warn(pdev, "Failed to get DSN\n");
> +
> +	bnge_vpd_read_info(bd);
> +
> +	return bd;
> +}
> +
> +void bnge_devlink_register(struct bnge_dev *bd)
> +{
> +	struct devlink *devlink = priv_to_devlink(bd);
> +
> +	devlink_register(devlink);
> +}
> +
> +void bnge_devlink_unregister(struct bnge_dev *bd)
> +{
> +	struct devlink *devlink = priv_to_devlink(bd);
> +
> +	devlink_unregister(devlink);
> +}
> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_devlink.h b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.h
> new file mode 100644
> index 000000000000..c6575255e650
> --- /dev/null
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.h
> @@ -0,0 +1,18 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (c) 2025 Broadcom */
> +
> +#ifndef _BNGE_DEVLINK_H_
> +#define _BNGE_DEVLINK_H_
> +
> +enum bnge_dl_version_type {
> +	BNGE_VERSION_FIXED,
> +	BNGE_VERSION_RUNNING,
> +	BNGE_VERSION_STORED,
> +};
> +
> +void bnge_devlink_free(struct bnge_dev *bd);
> +struct bnge_dev *bnge_devlink_alloc(struct pci_dev *pdev);
> +void bnge_devlink_register(struct bnge_dev *bd);
> +void bnge_devlink_unregister(struct bnge_dev *bd);
> +
> +#endif /* _BNGE_DEVLINK_H_ */


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 03/10] bng_en: Add firmware communication mechanism
  2025-06-18 14:47 ` [net-next, 03/10] bng_en: Add firmware communication mechanism Vikas Gupta
  2025-06-19  9:46   ` kernel test robot
@ 2025-06-19 12:43   ` Vadim Fedorenko
  2025-06-24 10:23     ` Vikas Gupta
  1 sibling, 1 reply; 37+ messages in thread
From: Vadim Fedorenko @ 2025-06-19 12:43 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

On 18/06/2025 15:47, Vikas Gupta wrote:
> Add support to communicate with the firmware.
> Future patches will use these functions to send the
> messages to the firmware.
> Functions support allocating request/response buffers
> to send a particular command. Each command has certain
> timeout value to which the driver waits for response from
> the firmware. In error case, commands may be either timed
> out waiting on response from the firmware or may return
> a specific error code.
> 
> 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>
> ---
>   drivers/net/ethernet/broadcom/bnge/Makefile   |   3 +-
>   drivers/net/ethernet/broadcom/bnge/bnge.h     |  13 +
>   .../net/ethernet/broadcom/bnge/bnge_hwrm.c    | 503 ++++++++++++++++++
>   .../net/ethernet/broadcom/bnge/bnge_hwrm.h    | 107 ++++
>   4 files changed, 625 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm.c
>   create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h
> 
> diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethernet/broadcom/bnge/Makefile
> index e021a14d2fa0..b296d7de56ce 100644
> --- a/drivers/net/ethernet/broadcom/bnge/Makefile
> +++ b/drivers/net/ethernet/broadcom/bnge/Makefile
> @@ -3,4 +3,5 @@
>   obj-$(CONFIG_BNGE) += bng_en.o
>   
>   bng_en-y := bnge_core.o \
> -	    bnge_devlink.o
> +	    bnge_devlink.o \
> +	    bnge_hwrm.o
> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
> index 19d85aabab4e..8f2a562d9ae2 100644
> --- a/drivers/net/ethernet/broadcom/bnge/bnge.h
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
> @@ -13,6 +13,8 @@ enum board_idx {
>   	BCM57708,
>   };
>   
> +#define INVALID_HW_RING_ID      ((u16)-1)
> +
>   struct bnge_dev {
>   	struct device	*dev;
>   	struct pci_dev	*pdev;
> @@ -22,6 +24,17 @@ struct bnge_dev {
>   	char		board_serialno[BNGE_VPD_FLD_LEN];
>   
>   	void __iomem	*bar0;
> +
> +	/* HWRM members */
> +	u16			hwrm_cmd_seq;
> +	u16			hwrm_cmd_kong_seq;
> +	struct dma_pool		*hwrm_dma_pool;
> +	struct hlist_head	hwrm_pending_list;
> +	u16			hwrm_max_req_len;
> +	u16			hwrm_max_ext_req_len;
> +	unsigned int		hwrm_cmd_timeout;
> +	unsigned int		hwrm_cmd_max_timeout;
> +	struct mutex		hwrm_cmd_lock;	/* serialize hwrm messages */
>   };

It's all looks pretty similar to what is used in bnxt driver. Why do you
duplicate the code rather then reusing (and improving) the existing one?

I didn't look carefully, but in case it's impossible to merge hwrm code
from bnxt, you have to make function names prepended with bnge prefix...




^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 04/10] bng_en: Add initial interaction with firmware
  2025-06-18 14:47 ` [net-next, 04/10] bng_en: Add initial interaction with firmware Vikas Gupta
@ 2025-06-19 12:53   ` Vadim Fedorenko
  2025-06-24 10:26     ` Vikas Gupta
  0 siblings, 1 reply; 37+ messages in thread
From: Vadim Fedorenko @ 2025-06-19 12:53 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

On 18/06/2025 15:47, Vikas Gupta wrote:
> Query firmware with the help of basic firmware commands and
> cache the capabilities. With the help of basic commands
> start the initialization process of the driver with the
> firmware.
> Since basic information is available from the firmware,
> add that information to the devlink info get command.
> 
> 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>
> ---
>   drivers/net/ethernet/broadcom/bnge/Makefile   |   3 +-
>   drivers/net/ethernet/broadcom/bnge/bnge.h     |  54 +++++
>   .../net/ethernet/broadcom/bnge/bnge_core.c    |  67 ++++++
>   .../net/ethernet/broadcom/bnge/bnge_devlink.c | 120 ++++++++++
>   .../ethernet/broadcom/bnge/bnge_hwrm_lib.c    | 213 ++++++++++++++++++
>   .../ethernet/broadcom/bnge/bnge_hwrm_lib.h    |  16 ++
>   6 files changed, 472 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
>   create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
> 
> diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethernet/broadcom/bnge/Makefile
> index b296d7de56ce..b8dbbc2d5972 100644
> --- a/drivers/net/ethernet/broadcom/bnge/Makefile
> +++ b/drivers/net/ethernet/broadcom/bnge/Makefile
> @@ -4,4 +4,5 @@ obj-$(CONFIG_BNGE) += bng_en.o
>   
>   bng_en-y := bnge_core.o \
>   	    bnge_devlink.o \
> -	    bnge_hwrm.o
> +	    bnge_hwrm.o \
> +	    bnge_hwrm_lib.o
> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
> index 8f2a562d9ae2..60af0517c45e 100644
> --- a/drivers/net/ethernet/broadcom/bnge/bnge.h
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
> @@ -7,6 +7,13 @@
>   #define DRV_NAME	"bng_en"
>   #define DRV_SUMMARY	"Broadcom 800G Ethernet Linux Driver"
>   
> +#include <linux/etherdevice.h>
> +#include "../bnxt/bnxt_hsi.h"
> +
> +#define DRV_VER_MAJ	1
> +#define DRV_VER_MIN	15
> +#define DRV_VER_UPD	1
> +
>   extern char bnge_driver_name[];
>   
>   enum board_idx {
> @@ -15,6 +22,36 @@ enum board_idx {
>   
>   #define INVALID_HW_RING_ID      ((u16)-1)
>   
> +enum {
> +	BNGE_FW_CAP_SHORT_CMD				= BIT_ULL(0),
> +	BNGE_FW_CAP_LLDP_AGENT				= BIT_ULL(1),
> +	BNGE_FW_CAP_DCBX_AGENT				= BIT_ULL(2),
> +	BNGE_FW_CAP_IF_CHANGE				= BIT_ULL(3),
> +	BNGE_FW_CAP_KONG_MB_CHNL			= BIT_ULL(4),
> +	BNGE_FW_CAP_ERROR_RECOVERY			= BIT_ULL(5),
> +	BNGE_FW_CAP_PKG_VER				= BIT_ULL(6),
> +	BNGE_FW_CAP_CFA_ADV_FLOW			= BIT_ULL(7),
> +	BNGE_FW_CAP_CFA_RFS_RING_TBL_IDX_V2		= BIT_ULL(8),
> +	BNGE_FW_CAP_PCIE_STATS_SUPPORTED		= BIT_ULL(9),
> +	BNGE_FW_CAP_EXT_STATS_SUPPORTED			= BIT_ULL(10),
> +	BNGE_FW_CAP_ERR_RECOVER_RELOAD			= BIT_ULL(11),
> +	BNGE_FW_CAP_HOT_RESET				= BIT_ULL(12),
> +	BNGE_FW_CAP_RX_ALL_PKT_TS			= BIT_ULL(13),
> +	BNGE_FW_CAP_VLAN_RX_STRIP			= BIT_ULL(14),
> +	BNGE_FW_CAP_VLAN_TX_INSERT			= BIT_ULL(15),
> +	BNGE_FW_CAP_EXT_HW_STATS_SUPPORTED		= BIT_ULL(16),
> +	BNGE_FW_CAP_LIVEPATCH				= BIT_ULL(17),
> +	BNGE_FW_CAP_HOT_RESET_IF			= BIT_ULL(18),
> +	BNGE_FW_CAP_RING_MONITOR			= BIT_ULL(19),
> +	BNGE_FW_CAP_DBG_QCAPS				= BIT_ULL(20),
> +	BNGE_FW_CAP_THRESHOLD_TEMP_SUPPORTED		= BIT_ULL(21),
> +	BNGE_FW_CAP_DFLT_VLAN_TPID_PCP			= BIT_ULL(22),
> +	BNGE_FW_CAP_VNIC_TUNNEL_TPA			= BIT_ULL(23),
> +	BNGE_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO		= BIT_ULL(24),
> +	BNGE_FW_CAP_CFA_RFS_RING_TBL_IDX_V3		= BIT_ULL(25),
> +	BNGE_FW_CAP_VNIC_RE_FLUSH			= BIT_ULL(26),
> +};
> +
>   struct bnge_dev {
>   	struct device	*dev;
>   	struct pci_dev	*pdev;
> @@ -25,6 +62,9 @@ struct bnge_dev {
>   
>   	void __iomem	*bar0;
>   
> +	u16		chip_num;
> +	u8		chip_rev;
> +
>   	/* HWRM members */
>   	u16			hwrm_cmd_seq;
>   	u16			hwrm_cmd_kong_seq;
> @@ -35,6 +75,20 @@ struct bnge_dev {
>   	unsigned int		hwrm_cmd_timeout;
>   	unsigned int		hwrm_cmd_max_timeout;
>   	struct mutex		hwrm_cmd_lock;	/* serialize hwrm messages */
> +
> +	struct hwrm_ver_get_output	ver_resp;
> +#define FW_VER_STR_LEN		32
> +	char			fw_ver_str[FW_VER_STR_LEN];
> +	char			hwrm_ver_supp[FW_VER_STR_LEN];
> +	char			nvm_cfg_ver[FW_VER_STR_LEN];
> +	u64			fw_ver_code;
> +#define BNGE_FW_VER_CODE(maj, min, bld, rsv)			\
> +	((u64)(maj) << 48 | (u64)(min) << 32 | (u64)(bld) << 16 | (rsv))
> +
> +	unsigned long           state;
> +#define BNGE_STATE_DRV_REGISTERED      0
> +
> +	u64			fw_cap;
>   };
>   
>   #endif /* _BNGE_H_ */
> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_core.c b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
> index 1a46c7663012..5e23eb14f60e 100644
> --- a/drivers/net/ethernet/broadcom/bnge/bnge_core.c
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
> @@ -8,6 +8,8 @@
>   
>   #include "bnge.h"
>   #include "bnge_devlink.h"
> +#include "bnge_hwrm.h"
> +#include "bnge_hwrm_lib.h"
>   
>   MODULE_LICENSE("GPL");
>   MODULE_DESCRIPTION(DRV_SUMMARY);
> @@ -37,6 +39,51 @@ static void bnge_print_device_info(struct pci_dev *pdev, enum board_idx idx)
>   	pcie_print_link_status(pdev);
>   }
>   
> +static void bnge_nvm_cfg_ver_get(struct bnge_dev *bd)
> +{
> +	struct hwrm_nvm_get_dev_info_output nvm_info;
> +
> +	if (!bnge_hwrm_nvm_dev_info(bd, &nvm_info))
> +		snprintf(bd->nvm_cfg_ver, FW_VER_STR_LEN, "%d.%d.%d",
> +			 nvm_info.nvm_cfg_ver_maj, nvm_info.nvm_cfg_ver_min,
> +			 nvm_info.nvm_cfg_ver_upd);
> +}
> +
> +static void bnge_fw_unregister_dev(struct bnge_dev *bd)
> +{
> +	bnge_hwrm_func_drv_unrgtr(bd);
> +}
> +
> +static int bnge_fw_register_dev(struct bnge_dev *bd)
> +{
> +	int rc;
> +
> +	bd->fw_cap = 0;
> +	rc = bnge_hwrm_ver_get(bd);
> +	if (rc) {
> +		dev_err(bd->dev, "Get Version command failed rc: %d\n", rc);
> +		return rc;
> +	}
> +
> +	bnge_nvm_cfg_ver_get(bd);
> +
> +	rc = bnge_hwrm_func_reset(bd);
> +	if (rc) {
> +		dev_err(bd->dev, "Failed to reset function rc: %d\n", rc);
> +		return rc;
> +	}
> +
> +	bnge_hwrm_fw_set_time(bd);
> +
> +	rc =  bnge_hwrm_func_drv_rgtr(bd);
> +	if (rc) {
> +		dev_err(bd->dev, "Failed to rgtr with firmware rc: %d\n", rc);
> +		return rc;
> +	}
> +
> +	return 0;
> +}
> +
>   static void bnge_pci_disable(struct pci_dev *pdev)
>   {
>   	pci_release_regions(pdev);
> @@ -136,10 +183,26 @@ static int bnge_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>   		goto err_devl_unreg;
>   	}
>   
> +	rc = bnge_init_hwrm_resources(bd);
> +	if (rc)
> +		goto err_bar_unmap;
> +
> +	rc = bnge_fw_register_dev(bd);
> +	if (rc) {
> +		dev_err(&pdev->dev, "Failed to register with firmware rc = %d\n", rc);
> +		goto err_hwrm_cleanup;
> +	}
> +
>   	pci_save_state(pdev);
>   
>   	return 0;
>   
> +err_hwrm_cleanup:
> +	bnge_cleanup_hwrm_resources(bd);
> +
> +err_bar_unmap:
> +	bnge_unmap_bars(pdev);
> +
>   err_devl_unreg:
>   	bnge_devlink_unregister(bd);
>   	bnge_devlink_free(bd);
> @@ -153,6 +216,10 @@ static void bnge_remove_one(struct pci_dev *pdev)
>   {
>   	struct bnge_dev *bd = pci_get_drvdata(pdev);
>   
> +	bnge_fw_unregister_dev(bd);
> +
> +	bnge_cleanup_hwrm_resources(bd);
> +
>   	bnge_unmap_bars(pdev);
>   
>   	bnge_devlink_unregister(bd);
> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
> index d406338da130..f987d35beea2 100644
> --- a/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
> @@ -8,6 +8,7 @@
>   
>   #include "bnge.h"
>   #include "bnge_devlink.h"
> +#include "bnge_hwrm_lib.h"
>   
>   static int bnge_dl_info_put(struct bnge_dev *bd, struct devlink_info_req *req,
>   			    enum bnge_dl_version_type type, const char *key,
> @@ -16,6 +17,10 @@ static int bnge_dl_info_put(struct bnge_dev *bd, struct devlink_info_req *req,
>   	if (!strlen(buf))
>   		return 0;
>   
> +	if (!strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_NCSI) ||
> +	    !strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_ROCE))
> +		return 0;
> +
>   	switch (type) {
>   	case BNGE_VERSION_FIXED:
>   		return devlink_info_version_fixed_put(req, key, buf);
> @@ -63,11 +68,20 @@ static void bnge_vpd_read_info(struct bnge_dev *bd)
>   	kfree(vpd_data);
>   }
>   
> +#define HWRM_FW_VER_STR_LEN	16
> +
>   static int bnge_devlink_info_get(struct devlink *devlink,
>   				 struct devlink_info_req *req,
>   				 struct netlink_ext_ack *extack)
>   {
> +	struct hwrm_nvm_get_dev_info_output nvm_dev_info;
>   	struct bnge_dev *bd = devlink_priv(devlink);
> +	struct hwrm_ver_get_output *ver_resp;
> +	char mgmt_ver[FW_VER_STR_LEN];
> +	char roce_ver[FW_VER_STR_LEN];
> +	char ncsi_ver[FW_VER_STR_LEN];
> +	char buf[32];
> +
>   	int rc;
>   
>   	if (bd->dsn) {
> @@ -95,6 +109,112 @@ static int bnge_devlink_info_get(struct devlink *devlink,
>   			      DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
>   			      bd->board_partno);
>   
> +	/* More information from HWRM ver get command */
> +	sprintf(buf, "%X", bd->chip_num);
> +	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_FIXED,
> +			      DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, buf);
> +	if (rc)
> +		return rc;
> +
> +	ver_resp = &bd->ver_resp;
> +	sprintf(buf, "%c%d", 'A' + ver_resp->chip_rev, ver_resp->chip_metal);
> +	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_FIXED,
> +			      DEVLINK_INFO_VERSION_GENERIC_ASIC_REV, buf);
> +	if (rc)
> +		return rc;
> +
> +	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
> +			      DEVLINK_INFO_VERSION_GENERIC_FW_PSID,
> +			      bd->nvm_cfg_ver);
> +	if (rc)
> +		return rc;
> +
> +	buf[0] = 0;
> +	strncat(buf, ver_resp->active_pkg_name, HWRM_FW_VER_STR_LEN);
> +	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
> +			      DEVLINK_INFO_VERSION_GENERIC_FW, buf);
> +	if (rc)
> +		return rc;
> +
> +	if (ver_resp->flags & VER_GET_RESP_FLAGS_EXT_VER_AVAIL) {
> +		snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> +			 ver_resp->hwrm_fw_major, ver_resp->hwrm_fw_minor,
> +			 ver_resp->hwrm_fw_build, ver_resp->hwrm_fw_patch);
> +
> +		snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> +			 ver_resp->mgmt_fw_major, ver_resp->mgmt_fw_minor,
> +			 ver_resp->mgmt_fw_build, ver_resp->mgmt_fw_patch);
> +
> +		snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> +			 ver_resp->roce_fw_major, ver_resp->roce_fw_minor,
> +			 ver_resp->roce_fw_build, ver_resp->roce_fw_patch);
> +	} else {
> +		snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> +			 ver_resp->hwrm_fw_maj_8b, ver_resp->hwrm_fw_min_8b,
> +			 ver_resp->hwrm_fw_bld_8b, ver_resp->hwrm_fw_rsvd_8b);
> +
> +		snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> +			 ver_resp->mgmt_fw_maj_8b, ver_resp->mgmt_fw_min_8b,
> +			 ver_resp->mgmt_fw_bld_8b, ver_resp->mgmt_fw_rsvd_8b);
> +
> +		snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> +			 ver_resp->roce_fw_maj_8b, ver_resp->roce_fw_min_8b,
> +			 ver_resp->roce_fw_bld_8b, ver_resp->roce_fw_rsvd_8b);
> +	}
> +	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
> +			      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
> +	if (rc)
> +		return rc;
> +
> +	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
> +			      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API,
> +			      bd->hwrm_ver_supp);
> +	if (rc)
> +		return rc;
> +
> +	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
> +			      DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver);
> +	if (rc)
> +		return rc;
> +
> +	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
> +			      DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver);
> +	if (rc)
> +		return rc;
> +
> +	rc = bnge_hwrm_nvm_dev_info(bd, &nvm_dev_info);
> +	if (!(nvm_dev_info.flags & NVM_GET_DEV_INFO_RESP_FLAGS_FW_VER_VALID))
> +		return 0;
> +
> +	buf[0] = 0;
> +	strncat(buf, nvm_dev_info.pkg_name, HWRM_FW_VER_STR_LEN);
> +	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
> +			      DEVLINK_INFO_VERSION_GENERIC_FW, buf);
> +	if (rc)
> +		return rc;
> +
> +	snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> +		 nvm_dev_info.hwrm_fw_major, nvm_dev_info.hwrm_fw_minor,
> +		 nvm_dev_info.hwrm_fw_build, nvm_dev_info.hwrm_fw_patch);
> +	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
> +			      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
> +	if (rc)
> +		return rc;
> +
> +	snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> +		 nvm_dev_info.mgmt_fw_major, nvm_dev_info.mgmt_fw_minor,
> +		 nvm_dev_info.mgmt_fw_build, nvm_dev_info.mgmt_fw_patch);
> +	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
> +			      DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver);
> +	if (rc)
> +		return rc;
> +
> +	snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> +		 nvm_dev_info.roce_fw_major, nvm_dev_info.roce_fw_minor,
> +		 nvm_dev_info.roce_fw_build, nvm_dev_info.roce_fw_patch);
> +	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
> +			      DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver);
> +
>   	return rc;
>   }
>   
> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
> new file mode 100644
> index 000000000000..567376a407df
> --- /dev/null
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
> @@ -0,0 +1,213 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (c) 2025 Broadcom.
> +
> +#include <linux/errno.h>
> +#include <linux/kernel.h>
> +#include <linux/mm.h>
> +#include <linux/pci.h>
> +
> +#include "bnge.h"
> +#include "../bnxt/bnxt_hsi.h"
> +#include "bnge_hwrm.h"
> +#include "bnge_hwrm_lib.h"
> +
> +int bnge_hwrm_ver_get(struct bnge_dev *bd)
> +{
> +	u32 dev_caps_cfg, hwrm_ver, hwrm_spec_code;
> +	u16 fw_maj, fw_min, fw_bld, fw_rsv;
> +	struct hwrm_ver_get_output *resp;
> +	struct hwrm_ver_get_input *req;
> +	int rc;
> +
> +	rc = hwrm_req_init(bd, req, HWRM_VER_GET);
> +	if (rc)
> +		return rc;
> +
> +	hwrm_req_flags(bd, req, BNGE_HWRM_FULL_WAIT);
> +	bd->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
> +	req->hwrm_intf_maj = HWRM_VERSION_MAJOR;
> +	req->hwrm_intf_min = HWRM_VERSION_MINOR;
> +	req->hwrm_intf_upd = HWRM_VERSION_UPDATE;
> +
> +	resp = hwrm_req_hold(bd, req);
> +	rc = hwrm_req_send(bd, req);
> +	if (rc)
> +		goto hwrm_ver_get_exit;
> +
> +	memcpy(&bd->ver_resp, resp, sizeof(struct hwrm_ver_get_output));
> +
> +	hwrm_spec_code = resp->hwrm_intf_maj_8b << 16 |
> +			 resp->hwrm_intf_min_8b << 8 |
> +			 resp->hwrm_intf_upd_8b;
> +	hwrm_ver = HWRM_VERSION_MAJOR << 16 | HWRM_VERSION_MINOR << 8 |
> +			HWRM_VERSION_UPDATE;
> +
> +	if (hwrm_spec_code > hwrm_ver)
> +		snprintf(bd->hwrm_ver_supp, FW_VER_STR_LEN, "%d.%d.%d",
> +			 HWRM_VERSION_MAJOR, HWRM_VERSION_MINOR,
> +			 HWRM_VERSION_UPDATE);
> +	else
> +		snprintf(bd->hwrm_ver_supp, FW_VER_STR_LEN, "%d.%d.%d",
> +			 resp->hwrm_intf_maj_8b, resp->hwrm_intf_min_8b,
> +			 resp->hwrm_intf_upd_8b);
> +
> +	fw_maj = le16_to_cpu(resp->hwrm_fw_major);
> +	fw_min = le16_to_cpu(resp->hwrm_fw_minor);
> +	fw_bld = le16_to_cpu(resp->hwrm_fw_build);
> +	fw_rsv = le16_to_cpu(resp->hwrm_fw_patch);
> +
> +	bd->fw_ver_code = BNGE_FW_VER_CODE(fw_maj, fw_min, fw_bld, fw_rsv);
> +	snprintf(bd->fw_ver_str, FW_VER_STR_LEN, "%d.%d.%d.%d",
> +		 fw_maj, fw_min, fw_bld, fw_rsv);
> +
> +	if (strlen(resp->active_pkg_name)) {
> +		int fw_ver_len = strlen(bd->fw_ver_str);
> +
> +		snprintf(bd->fw_ver_str + fw_ver_len,
> +			 FW_VER_STR_LEN - fw_ver_len - 1, "/pkg %s",
> +			 resp->active_pkg_name);
> +		bd->fw_cap |= BNGE_FW_CAP_PKG_VER;
> +	}
> +
> +	bd->hwrm_cmd_timeout = le16_to_cpu(resp->def_req_timeout);
> +	if (!bd->hwrm_cmd_timeout)
> +		bd->hwrm_cmd_timeout = DFLT_HWRM_CMD_TIMEOUT;
> +	bd->hwrm_cmd_max_timeout = le16_to_cpu(resp->max_req_timeout) * 1000;
> +	if (!bd->hwrm_cmd_max_timeout)
> +		bd->hwrm_cmd_max_timeout = HWRM_CMD_MAX_TIMEOUT;
> +	else if (bd->hwrm_cmd_max_timeout > HWRM_CMD_MAX_TIMEOUT)
> +			dev_warn(bd->dev, "Default HWRM commands max timeout increased to %d seconds\n",
> +				 bd->hwrm_cmd_max_timeout / 1000);
> +
> +	bd->hwrm_max_req_len = le16_to_cpu(resp->max_req_win_len);
> +	bd->hwrm_max_ext_req_len = le16_to_cpu(resp->max_ext_req_len);
> +
> +	if (bd->hwrm_max_ext_req_len < HWRM_MAX_REQ_LEN)
> +		bd->hwrm_max_ext_req_len = HWRM_MAX_REQ_LEN;
> +
> +	bd->chip_num = le16_to_cpu(resp->chip_num);
> +	bd->chip_rev = resp->chip_rev;
> +
> +	dev_caps_cfg = le32_to_cpu(resp->dev_caps_cfg);
> +	if ((dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
> +	    (dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
> +		bd->fw_cap |= BNGE_FW_CAP_SHORT_CMD;
> +
> +	if (dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_KONG_MB_CHNL_SUPPORTED)
> +		bd->fw_cap |= BNGE_FW_CAP_KONG_MB_CHNL;
> +
> +	if (dev_caps_cfg &
> +	    VER_GET_RESP_DEV_CAPS_CFG_CFA_ADV_FLOW_MGNT_SUPPORTED)
> +		bd->fw_cap |= BNGE_FW_CAP_CFA_ADV_FLOW;
> +
> +hwrm_ver_get_exit:
> +	hwrm_req_drop(bd, req);
> +	return rc;
> +}
> +
> +int
> +bnge_hwrm_nvm_dev_info(struct bnge_dev *bd,
> +		       struct hwrm_nvm_get_dev_info_output *nvm_info)
> +{
> +	struct hwrm_nvm_get_dev_info_output *resp;
> +	struct hwrm_nvm_get_dev_info_input *req;
> +	int rc;
> +
> +	rc = hwrm_req_init(bd, req, HWRM_NVM_GET_DEV_INFO);
> +	if (rc)
> +		return rc;
> +
> +	resp = hwrm_req_hold(bd, req);
> +	rc = hwrm_req_send(bd, req);
> +	if (!rc)
> +		memcpy(nvm_info, resp, sizeof(*resp));
> +	hwrm_req_drop(bd, req);
> +	return rc;
> +}
> +
> +int bnge_hwrm_func_reset(struct bnge_dev *bd)
> +{
> +	struct hwrm_func_reset_input *req;
> +	int rc;
> +
> +	rc = hwrm_req_init(bd, req, HWRM_FUNC_RESET);
> +	if (rc)
> +		return rc;
> +
> +	req->enables = 0;
> +	hwrm_req_timeout(bd, req, HWRM_RESET_TIMEOUT);
> +	return hwrm_req_send(bd, req);
> +}
> +
> +int bnge_hwrm_fw_set_time(struct bnge_dev *bd)
> +{
> +	struct hwrm_fw_set_time_input *req;
> +	struct tm tm;
> +	time64_t now = ktime_get_real_seconds();
> +	int rc;

Reverse xmass tree, please. Not quite sure you need this 'now'
variable at all. You can use ktime_get_real_seconds() directly
in time64_to_tm() - there are examples of such code in the kernel.

> +
> +	time64_to_tm(now, 0, &tm);
> +	rc = hwrm_req_init(bd, req, HWRM_FW_SET_TIME);
> +	if (rc)
> +		return rc;
> +
> +	req->year = cpu_to_le16(1900 + tm.tm_year);
> +	req->month = 1 + tm.tm_mon;
> +	req->day = tm.tm_mday;
> +	req->hour = tm.tm_hour;
> +	req->minute = tm.tm_min;
> +	req->second = tm.tm_sec;
> +	return hwrm_req_send(bd, req);
> +}

This whole function looks like copy-paste from bnxt, did you consider
merging these parts?


> +
> +int bnge_hwrm_func_drv_rgtr(struct bnge_dev *bd)
> +{
> +	struct hwrm_func_drv_rgtr_output *resp;
> +	struct hwrm_func_drv_rgtr_input *req;
> +	u32 flags;
> +	int rc;
> +
> +	rc = hwrm_req_init(bd, req, HWRM_FUNC_DRV_RGTR);
> +	if (rc)
> +		return rc;
> +
> +	req->enables = cpu_to_le32(FUNC_DRV_RGTR_REQ_ENABLES_OS_TYPE |
> +				   FUNC_DRV_RGTR_REQ_ENABLES_VER |
> +				   FUNC_DRV_RGTR_REQ_ENABLES_ASYNC_EVENT_FWD);
> +
> +	req->os_type = cpu_to_le16(FUNC_DRV_RGTR_REQ_OS_TYPE_LINUX);
> +	flags = FUNC_DRV_RGTR_REQ_FLAGS_16BIT_VER_MODE;
> +
> +	req->flags = cpu_to_le32(flags);
> +	req->ver_maj_8b = DRV_VER_MAJ;
> +	req->ver_min_8b = DRV_VER_MIN;
> +	req->ver_upd_8b = DRV_VER_UPD;
> +	req->ver_maj = cpu_to_le16(DRV_VER_MAJ);
> +	req->ver_min = cpu_to_le16(DRV_VER_MIN);
> +	req->ver_upd = cpu_to_le16(DRV_VER_UPD);
> +
> +	resp = hwrm_req_hold(bd, req);
> +	rc = hwrm_req_send(bd, req);
> +	if (!rc) {
> +		set_bit(BNGE_STATE_DRV_REGISTERED, &bd->state);
> +		if (resp->flags &
> +		    cpu_to_le32(FUNC_DRV_RGTR_RESP_FLAGS_IF_CHANGE_SUPPORTED))
> +			bd->fw_cap |= BNGE_FW_CAP_IF_CHANGE;
> +	}
> +	hwrm_req_drop(bd, req);
> +	return rc;
> +}
> +
> +int bnge_hwrm_func_drv_unrgtr(struct bnge_dev *bd)
> +{
> +	struct hwrm_func_drv_unrgtr_input *req;
> +	int rc;
> +
> +	if (!test_and_clear_bit(BNGE_STATE_DRV_REGISTERED, &bd->state))
> +		return 0;
> +
> +	rc = hwrm_req_init(bd, req, HWRM_FUNC_DRV_UNRGTR);
> +	if (rc)
> +		return rc;
> +	return hwrm_req_send(bd, req);
> +}
> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
> new file mode 100644
> index 000000000000..9308d4fe64d2
> --- /dev/null
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
> @@ -0,0 +1,16 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (c) 2025 Broadcom */
> +
> +#ifndef _BNGE_HWRM_LIB_H_
> +#define _BNGE_HWRM_LIB_H_
> +
> +int bnge_hwrm_ver_get(struct bnge_dev *bd);
> +int bnge_hwrm_func_reset(struct bnge_dev *bd);
> +int bnge_hwrm_fw_set_time(struct bnge_dev *bd);
> +int bnge_hwrm_func_drv_rgtr(struct bnge_dev *bd);
> +int bnge_hwrm_func_drv_unrgtr(struct bnge_dev *bd);
> +int bnge_hwrm_vnic_qcaps(struct bnge_dev *bd);
> +int bnge_hwrm_nvm_dev_info(struct bnge_dev *bd,
> +			   struct hwrm_nvm_get_dev_info_output *nvm_dev_info);
> +
> +#endif /* _BNGE_HWRM_LIB_H_ */


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 06/10] bng_en: Add backing store support
  2025-06-18 14:47 ` [net-next, 06/10] bng_en: Add backing store support Vikas Gupta
@ 2025-06-19 13:02   ` Vadim Fedorenko
  2025-06-24 10:29     ` Vikas Gupta
  0 siblings, 1 reply; 37+ messages in thread
From: Vadim Fedorenko @ 2025-06-19 13:02 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

On 18/06/2025 15:47, Vikas Gupta wrote:
> Backing store or context memory on the host helps the
> device to manage rings, stats and other resources.
> Context memory is allocated with the help of ring
> alloc/free functions.
> 
> 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>
> ---
>   drivers/net/ethernet/broadcom/bnge/bnge.h     |  18 +
>   .../ethernet/broadcom/bnge/bnge_hwrm_lib.c    | 168 +++++++++
>   .../ethernet/broadcom/bnge/bnge_hwrm_lib.h    |   4 +
>   .../net/ethernet/broadcom/bnge/bnge_rmem.c    | 337 ++++++++++++++++++
>   .../net/ethernet/broadcom/bnge/bnge_rmem.h    | 153 ++++++++
>   5 files changed, 680 insertions(+)
> 
> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
> index 60af0517c45e..01f64a10729c 100644
> --- a/drivers/net/ethernet/broadcom/bnge/bnge.h
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
> @@ -9,6 +9,7 @@
>   
>   #include <linux/etherdevice.h>
>   #include "../bnxt/bnxt_hsi.h"
> +#include "bnge_rmem.h"
>   
>   #define DRV_VER_MAJ	1
>   #define DRV_VER_MIN	15
> @@ -52,6 +53,13 @@ enum {
>   	BNGE_FW_CAP_VNIC_RE_FLUSH			= BIT_ULL(26),
>   };
>   
> +enum {
> +	BNGE_EN_ROCE_V1					= BIT_ULL(0),
> +	BNGE_EN_ROCE_V2					= BIT_ULL(1),
> +};
> +
> +#define BNGE_EN_ROCE		(BNGE_EN_ROCE_V1 | BNGE_EN_ROCE_V2)
> +
>   struct bnge_dev {
>   	struct device	*dev;
>   	struct pci_dev	*pdev;
> @@ -89,6 +97,16 @@ struct bnge_dev {
>   #define BNGE_STATE_DRV_REGISTERED      0
>   
>   	u64			fw_cap;
> +
> +	/* Backing stores */
> +	struct bnge_ctx_mem_info	*ctx;
> +
> +	u64			flags;
>   };
>   
> +static inline bool bnge_is_roce_en(struct bnge_dev *bd)
> +{
> +	return bd->flags & BNGE_EN_ROCE;
> +}
> +
>   #endif /* _BNGE_H_ */
> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
> index 567376a407df..e5f32ac8a69f 100644
> --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
> @@ -10,6 +10,7 @@
>   #include "../bnxt/bnxt_hsi.h"
>   #include "bnge_hwrm.h"
>   #include "bnge_hwrm_lib.h"
> +#include "bnge_rmem.h"
>   
>   int bnge_hwrm_ver_get(struct bnge_dev *bd)
>   {
> @@ -211,3 +212,170 @@ int bnge_hwrm_func_drv_unrgtr(struct bnge_dev *bd)
>   		return rc;
>   	return hwrm_req_send(bd, req);
>   }
> +
> +static void bnge_init_ctx_initializer(struct bnge_ctx_mem_type *ctxm,
> +				      u8 init_val, u8 init_offset,
> +				      bool init_mask_set)
> +{
> +	ctxm->init_value = init_val;
> +	ctxm->init_offset = BNGE_CTX_INIT_INVALID_OFFSET;
> +	if (init_mask_set)
> +		ctxm->init_offset = init_offset * 4;
> +	else
> +		ctxm->init_value = 0;
> +}
> +
> +static int bnge_alloc_all_ctx_pg_info(struct bnge_dev *bd, int ctx_max)
> +{
> +	struct bnge_ctx_mem_info *ctx = bd->ctx;
> +	u16 type;
> +
> +	for (type = 0; type < ctx_max; type++) {
> +		struct bnge_ctx_mem_type *ctxm = &ctx->ctx_arr[type];
> +		int n = 1;
> +
> +		if (!ctxm->max_entries)
> +			continue;
> +
> +		if (ctxm->instance_bmap)
> +			n = hweight32(ctxm->instance_bmap);
> +		ctxm->pg_info = kcalloc(n, sizeof(*ctxm->pg_info), GFP_KERNEL);
> +		if (!ctxm->pg_info)
> +			return -ENOMEM;

It's a bit hard to be absolutely sure without full chain of calls, but
it looks like some of the memory can be leaked in case of allocation
fail. Direct callers do not clear allocated contextes in the error path.

> +	}
> +
> +	return 0;
> +}
> +

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 07/10] bng_en: Add resource management support
  2025-06-18 14:47 ` [net-next, 07/10] bng_en: Add resource management support Vikas Gupta
@ 2025-06-19 13:39   ` Vadim Fedorenko
  2025-06-24 10:31     ` Vikas Gupta
  0 siblings, 1 reply; 37+ messages in thread
From: Vadim Fedorenko @ 2025-06-19 13:39 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

On 18/06/2025 15:47, Vikas Gupta wrote:
> Get the resources and capabilities from the firmware.
> Add functions to manage the resources with the firmware.
> These functions will help netdev reserve the resources
> with the firmware before registering the device in future
> patches. The resources and their information, such as
> the maximum available and reserved, are part of the members
> present in the bnge_hw_resc struct.
> The bnge_reserve_rings() function also populates
> the RSS table entries once the RX rings are reserved with
> the firmware.
> 

[...]

> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h
> index c14f03daab4b..9dd13c5219a5 100644
> --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h
> @@ -104,4 +104,14 @@ void hwrm_req_alloc_flags(struct bnge_dev *bd, void *req, gfp_t flags);
>   void *hwrm_req_dma_slice(struct bnge_dev *bd, void *req, u32 size,
>   			 dma_addr_t *dma);
>   
> +static inline int
> +bnge_hwrm_func_cfg_short_req_init(struct bnge_dev *bdev,
> +				  struct hwrm_func_cfg_input **req)
> +{
> +	u32 req_len;
> +
> +	req_len = min_t(u32, sizeof(**req), bdev->hwrm_max_ext_req_len);
> +	return __hwrm_req_init(bdev, (void **)req, HWRM_FUNC_CFG, req_len);
> +}
> +

Could you please explain how does this suppose to work? If the size of
request will be bigger than the max request length, the HWRM request
will be prepared with smaller size and then partially transferred to FW?

[...]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 08/10] bng_en: Add irq allocation support
  2025-06-18 14:47 ` [net-next, 08/10] bng_en: Add irq allocation support Vikas Gupta
@ 2025-06-19 13:52   ` Vadim Fedorenko
  2025-06-19 21:25   ` kernel test robot
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 37+ messages in thread
From: Vadim Fedorenko @ 2025-06-19 13:52 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

On 18/06/2025 15:47, Vikas Gupta wrote:
> Add irq allocation functions. This will help
> to allocate IRQs to both netdev and RoCE aux devices.
> 
> 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>
> ---
>   drivers/net/ethernet/broadcom/bnge/bnge.h     |  3 +
>   .../net/ethernet/broadcom/bnge/bnge_resc.c    | 69 +++++++++++++++++++
>   .../net/ethernet/broadcom/bnge/bnge_resc.h    | 13 ++++
>   3 files changed, 85 insertions(+)
> 
> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
> index b58d8fc6f258..3c161b1a9b62 100644
> --- a/drivers/net/ethernet/broadcom/bnge/bnge.h
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
> @@ -172,6 +172,9 @@ struct bnge_dev {
>   #define BNGE_SUPPORTS_TPA(bd)	((bd)->max_tpa_v2)
>   
>   	u8                      num_tc;
> +
> +	struct bnge_irq		*irq_tbl;
> +	u16			irqs_acquired;
>   };
>   
>   static inline bool bnge_is_roce_en(struct bnge_dev *bd)
> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_resc.c b/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
> index 68e094474822..84f91e05a2b0 100644
> --- a/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
> @@ -326,3 +326,72 @@ int bnge_reserve_rings(struct bnge_dev *bd)
>   
>   	return rc;
>   }
> +
> +int bnge_alloc_irqs(struct bnge_dev *bd)
> +{
> +	u16 aux_msix, tx_cp, num_entries;
> +	u16 irqs_demand, max, min = 1;
> +	int i, rc = 0;

This assignment is not needed. Error paths re-assign proper error code
while normal flow re-assigns rc to the return value of
bnge_adjust_rings()

> +
> +	irqs_demand = bnge_nqs_demand(bd);
> +	max = bnge_get_max_func_irqs(bd);
> +	if (irqs_demand > max)
> +		irqs_demand = max;
> +
> +	if (!(bd->flags & BNGE_EN_SHARED_CHNL))
> +		min = 2;
> +
> +	irqs_demand = pci_alloc_irq_vectors(bd->pdev, min, irqs_demand,
> +					    PCI_IRQ_MSIX);
> +	aux_msix = bnge_aux_get_msix(bd);
> +	if (irqs_demand < 0 || irqs_demand < aux_msix) {
> +		rc = -ENODEV;
> +		goto err_free_irqs;
> +	}
> +
> +	num_entries = irqs_demand;
> +	if (pci_msix_can_alloc_dyn(bd->pdev))
> +		num_entries = max;
> +	bd->irq_tbl = kcalloc(num_entries, sizeof(*bd->irq_tbl), GFP_KERNEL);
> +	if (!bd->irq_tbl) {
> +		rc = -ENOMEM;
> +		goto err_free_irqs;
> +	}
> +
> +	for (i = 0; i < irqs_demand; i++)
> +		bd->irq_tbl[i].vector = pci_irq_vector(bd->pdev, i);
> +
> +	bd->irqs_acquired = irqs_demand;
> +	/* Reduce rings based upon num of vectors allocated.
> +	 * We dont need to consider NQs as they have been calculated
> +	 * and must be more than irqs_demand.
> +	 */
> +	rc = bnge_adjust_rings(bd, &bd->rx_nr_rings,
> +			       &bd->tx_nr_rings,
> +			       irqs_demand - aux_msix, min == 1);
> +	if (rc)
> +		goto err_free_irqs;
> +
> +	tx_cp = bnge_num_tx_to_cp(bd, bd->tx_nr_rings);
> +	bd->nq_nr_rings = (min == 1) ?
> +		max_t(u16, tx_cp, bd->rx_nr_rings) :
> +		tx_cp + bd->rx_nr_rings;
> +
> +	/* Readjust tx_nr_rings_per_tc */
> +	if (!bd->num_tc)
> +		bd->tx_nr_rings_per_tc = bd->tx_nr_rings;
> +
> +	return 0;
> +
> +err_free_irqs:
> +	dev_err(bd->dev, "Failed to allocate IRQs err = %d\n", rc);
> +	bnge_free_irqs(bd);
> +	return rc;
> +}

[...]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 09/10] bng_en: Initialize default configuration
  2025-06-18 14:47 ` [net-next, 09/10] bng_en: Initialize default configuration Vikas Gupta
  2025-06-18 20:16   ` kernel test robot
@ 2025-06-19 13:57   ` Vadim Fedorenko
  2025-06-20  9:08   ` kernel test robot
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 37+ messages in thread
From: Vadim Fedorenko @ 2025-06-19 13:57 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

On 18/06/2025 15:47, Vikas Gupta wrote:
> Query resources from the firmware and, based on the
> availability of resources, initialize the default
> settings. The default settings include:
> 1. Rings and other resource reservations with the
> firmware. This ensures that resources are reserved
> before network and auxiliary devices are created.
> 2. Mapping the BAR, which helps access doorbells since
> its size is known after querying the firmware.
> 3. Retrieving the TCs and hardware CoS queue mappings.
> 
> 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>
> ---

[...]

> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
> index 577ac5dcdd9b..ffdec285948e 100644
> --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
> +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
> @@ -647,3 +647,57 @@ int bnge_hwrm_vnic_qcaps(struct bnge_dev *bd)
>   
>   	return rc;
>   }
> +
> +#define BNGE_CNPQ(q_profile)	\
> +		((q_profile) ==	\
> +		 QUEUE_QPORTCFG_RESP_QUEUE_ID0_SERVICE_PROFILE_LOSSY_ROCE_CNP)
> +
> +int bnge_hwrm_queue_qportcfg(struct bnge_dev *bd)
> +{
> +	struct hwrm_queue_qportcfg_output *resp;
> +	struct hwrm_queue_qportcfg_input *req;
> +	u8 i, j, *qptr;
> +	bool no_rdma;
> +	int rc = 0;

The initialization is not needed. The very next line re-assigns the
value of rc.

> +
> +	rc = hwrm_req_init(bd, req, HWRM_QUEUE_QPORTCFG);
> +	if (rc)
> +		return rc;
> +
> +	resp = hwrm_req_hold(bd, req);
> +	rc = hwrm_req_send(bd, req);
> +	if (rc)
> +		goto qportcfg_exit;
> +
> +	if (!resp->max_configurable_queues) {
> +		rc = -EINVAL;
> +		goto qportcfg_exit;
> +	}
> +	bd->max_tc = resp->max_configurable_queues;
> +	bd->max_lltc = resp->max_configurable_lossless_queues;
> +	if (bd->max_tc > BNGE_MAX_QUEUE)
> +		bd->max_tc = BNGE_MAX_QUEUE;
> +
> +	no_rdma = !bnge_is_roce_en(bd);
> +	qptr = &resp->queue_id0;
> +	for (i = 0, j = 0; i < bd->max_tc; i++) {
> +		bd->q_info[j].queue_id = *qptr;
> +		bd->q_ids[i] = *qptr++;
> +		bd->q_info[j].queue_profile = *qptr++;
> +		bd->tc_to_qidx[j] = j;
> +		if (!BNGE_CNPQ(bd->q_info[j].queue_profile) || no_rdma)
> +			j++;
> +	}
> +	bd->max_q = bd->max_tc;
> +	bd->max_tc = max_t(u8, j, 1);
> +
> +	if (resp->queue_cfg_info & QUEUE_QPORTCFG_RESP_QUEUE_CFG_INFO_ASYM_CFG)
> +		bd->max_tc = 1;
> +
> +	if (bd->max_lltc > bd->max_tc)
> +		bd->max_lltc = bd->max_tc;
> +
> +qportcfg_exit:
> +	hwrm_req_drop(bd, req);
> +	return rc;
> +}

[...]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 08/10] bng_en: Add irq allocation support
  2025-06-18 14:47 ` [net-next, 08/10] bng_en: Add irq allocation support Vikas Gupta
  2025-06-19 13:52   ` Vadim Fedorenko
@ 2025-06-19 21:25   ` kernel test robot
  2025-06-22  5:21   ` kernel test robot
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 37+ messages in thread
From: kernel test robot @ 2025-06-19 21:25 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: oe-kbuild-all, netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Hi Vikas,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.16-rc2 next-20250619]
[cannot apply to horms-ipvs/master]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Vikas-Gupta/bng_en-Add-PCI-interface/20250618-173130
base:   linus/master
patch link:    https://lore.kernel.org/r/20250618144743.843815-9-vikas.gupta%40broadcom.com
patch subject: [net-next, 08/10] bng_en: Add irq allocation support
config: parisc-randconfig-r073-20250619 (https://download.01.org/0day-ci/archive/20250620/202506200530.jiD9Txum-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 8.5.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506200530.jiD9Txum-lkp@intel.com/

smatch warnings:
drivers/net/ethernet/broadcom/bnge/bnge_resc.c:347 bnge_alloc_irqs() warn: unsigned 'irqs_demand' is never less than zero.

vim +/irqs_demand +347 drivers/net/ethernet/broadcom/bnge/bnge_resc.c

   329	
   330	int bnge_alloc_irqs(struct bnge_dev *bd)
   331	{
   332		u16 aux_msix, tx_cp, num_entries;
   333		u16 irqs_demand, max, min = 1;
   334		int i, rc = 0;
   335	
   336		irqs_demand = bnge_nqs_demand(bd);
   337		max = bnge_get_max_func_irqs(bd);
   338		if (irqs_demand > max)
   339			irqs_demand = max;
   340	
   341		if (!(bd->flags & BNGE_EN_SHARED_CHNL))
   342			min = 2;
   343	
   344		irqs_demand = pci_alloc_irq_vectors(bd->pdev, min, irqs_demand,
   345						    PCI_IRQ_MSIX);
   346		aux_msix = bnge_aux_get_msix(bd);
 > 347		if (irqs_demand < 0 || irqs_demand < aux_msix) {
   348			rc = -ENODEV;
   349			goto err_free_irqs;
   350		}
   351	
   352		num_entries = irqs_demand;
   353		if (pci_msix_can_alloc_dyn(bd->pdev))
   354			num_entries = max;
   355		bd->irq_tbl = kcalloc(num_entries, sizeof(*bd->irq_tbl), GFP_KERNEL);
   356		if (!bd->irq_tbl) {
   357			rc = -ENOMEM;
   358			goto err_free_irqs;
   359		}
   360	
   361		for (i = 0; i < irqs_demand; i++)
   362			bd->irq_tbl[i].vector = pci_irq_vector(bd->pdev, i);
   363	
   364		bd->irqs_acquired = irqs_demand;
   365		/* Reduce rings based upon num of vectors allocated.
   366		 * We dont need to consider NQs as they have been calculated
   367		 * and must be more than irqs_demand.
   368		 */
   369		rc = bnge_adjust_rings(bd, &bd->rx_nr_rings,
   370				       &bd->tx_nr_rings,
   371				       irqs_demand - aux_msix, min == 1);
   372		if (rc)
   373			goto err_free_irqs;
   374	
   375		tx_cp = bnge_num_tx_to_cp(bd, bd->tx_nr_rings);
   376		bd->nq_nr_rings = (min == 1) ?
   377			max_t(u16, tx_cp, bd->rx_nr_rings) :
   378			tx_cp + bd->rx_nr_rings;
   379	
   380		/* Readjust tx_nr_rings_per_tc */
   381		if (!bd->num_tc)
   382			bd->tx_nr_rings_per_tc = bd->tx_nr_rings;
   383	
   384		return 0;
   385	
   386	err_free_irqs:
   387		dev_err(bd->dev, "Failed to allocate IRQs err = %d\n", rc);
   388		bnge_free_irqs(bd);
   389		return rc;
   390	}
   391	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 09/10] bng_en: Initialize default configuration
  2025-06-18 14:47 ` [net-next, 09/10] bng_en: Initialize default configuration Vikas Gupta
  2025-06-18 20:16   ` kernel test robot
  2025-06-19 13:57   ` Vadim Fedorenko
@ 2025-06-20  9:08   ` kernel test robot
  2025-06-22 12:39   ` kernel test robot
  2025-06-26  8:47   ` kernel test robot
  4 siblings, 0 replies; 37+ messages in thread
From: kernel test robot @ 2025-06-20  9:08 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: oe-kbuild-all, netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Hi Vikas,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.16-rc2 next-20250619]
[cannot apply to horms-ipvs/master]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Vikas-Gupta/bng_en-Add-PCI-interface/20250618-173130
base:   linus/master
patch link:    https://lore.kernel.org/r/20250618144743.843815-10-vikas.gupta%40broadcom.com
patch subject: [net-next, 09/10] bng_en: Initialize default configuration
config: parisc-randconfig-r073-20250619 (https://download.01.org/0day-ci/archive/20250620/202506201622.Cn1MMNfm-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 8.5.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506201622.Cn1MMNfm-lkp@intel.com/

New smatch warnings:
drivers/net/ethernet/broadcom/bnge/bnge_resc.c:533 bnge_net_init_dflt_rings() warn: always true condition '(rc != -19) => (0-u16max != (-19))'

Old smatch warnings:
drivers/net/ethernet/broadcom/bnge/bnge_resc.c:372 bnge_alloc_irqs() warn: unsigned 'irqs_demand' is never less than zero.
drivers/net/ethernet/broadcom/bnge/bnge_resc.c:542 bnge_net_init_dflt_rings() warn: always true condition '(rc != -19) => (0-u16max != (-19))'

vim +533 drivers/net/ethernet/broadcom/bnge/bnge_resc.c

   511	
   512	static int bnge_net_init_dflt_rings(struct bnge_dev *bd, bool sh)
   513	{
   514		u16 dflt_rings, max_rx_rings, max_tx_rings, rc;
   515	
   516		if (sh)
   517			bd->flags |= BNGE_EN_SHARED_CHNL;
   518	
   519		dflt_rings = netif_get_num_default_rss_queues();
   520	
   521		rc = bnge_get_dflt_rings(bd, &max_rx_rings, &max_tx_rings, sh);
   522		if (rc)
   523			return rc;
   524		bd->rx_nr_rings = min_t(u16, dflt_rings, max_rx_rings);
   525		bd->tx_nr_rings_per_tc = min_t(u16, dflt_rings, max_tx_rings);
   526		if (sh)
   527			bnge_trim_dflt_sh_rings(bd);
   528		else
   529			bd->nq_nr_rings = bd->tx_nr_rings_per_tc + bd->rx_nr_rings;
   530		bd->tx_nr_rings = bd->tx_nr_rings_per_tc;
   531	
   532		rc = bnge_reserve_rings(bd);
 > 533		if (rc && rc != -ENODEV)
   534			dev_warn(bd->dev, "Unable to reserve tx rings\n");
   535		bd->tx_nr_rings_per_tc = bd->tx_nr_rings;
   536		if (sh)
   537			bnge_trim_dflt_sh_rings(bd);
   538	
   539		/* Rings may have been reduced, re-reserve them again */
   540		if (bnge_need_reserve_rings(bd)) {
   541			rc = bnge_reserve_rings(bd);
   542			if (rc && rc != -ENODEV)
   543				dev_warn(bd->dev, "Fewer rings reservation failed\n");
   544			bd->tx_nr_rings_per_tc = bd->tx_nr_rings;
   545		}
   546		if (rc) {
   547			bd->tx_nr_rings = 0;
   548			bd->rx_nr_rings = 0;
   549		}
   550	
   551		return rc;
   552	}
   553	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 08/10] bng_en: Add irq allocation support
  2025-06-18 14:47 ` [net-next, 08/10] bng_en: Add irq allocation support Vikas Gupta
  2025-06-19 13:52   ` Vadim Fedorenko
  2025-06-19 21:25   ` kernel test robot
@ 2025-06-22  5:21   ` kernel test robot
  2025-06-23  6:11   ` kernel test robot
  2025-06-25  9:17   ` kernel test robot
  4 siblings, 0 replies; 37+ messages in thread
From: kernel test robot @ 2025-06-22  5:21 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: oe-kbuild-all, netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Hi Vikas,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.16-rc2 next-20250620]
[cannot apply to horms-ipvs/master]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Vikas-Gupta/bng_en-Add-PCI-interface/20250618-173130
base:   linus/master
patch link:    https://lore.kernel.org/r/20250618144743.843815-9-vikas.gupta%40broadcom.com
patch subject: [net-next, 08/10] bng_en: Add irq allocation support
config: parisc-randconfig-r073-20250619 (https://download.01.org/0day-ci/archive/20250622/202506221311.dmMiJyFp-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 8.5.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506221311.dmMiJyFp-lkp@intel.com/

smatch warnings:
drivers/net/ethernet/broadcom/bnge/bnge_resc.c:347 bnge_alloc_irqs() warn: unsigned 'irqs_demand' is never less than zero.

vim +/irqs_demand +347 drivers/net/ethernet/broadcom/bnge/bnge_resc.c

   329	
   330	int bnge_alloc_irqs(struct bnge_dev *bd)
   331	{
   332		u16 aux_msix, tx_cp, num_entries;
   333		u16 irqs_demand, max, min = 1;
   334		int i, rc = 0;
   335	
   336		irqs_demand = bnge_nqs_demand(bd);
   337		max = bnge_get_max_func_irqs(bd);
   338		if (irqs_demand > max)
   339			irqs_demand = max;
   340	
   341		if (!(bd->flags & BNGE_EN_SHARED_CHNL))
   342			min = 2;
   343	
   344		irqs_demand = pci_alloc_irq_vectors(bd->pdev, min, irqs_demand,
   345						    PCI_IRQ_MSIX);
   346		aux_msix = bnge_aux_get_msix(bd);
 > 347		if (irqs_demand < 0 || irqs_demand < aux_msix) {
   348			rc = -ENODEV;
   349			goto err_free_irqs;
   350		}
   351	
   352		num_entries = irqs_demand;
   353		if (pci_msix_can_alloc_dyn(bd->pdev))
   354			num_entries = max;
   355		bd->irq_tbl = kcalloc(num_entries, sizeof(*bd->irq_tbl), GFP_KERNEL);
   356		if (!bd->irq_tbl) {
   357			rc = -ENOMEM;
   358			goto err_free_irqs;
   359		}
   360	
   361		for (i = 0; i < irqs_demand; i++)
   362			bd->irq_tbl[i].vector = pci_irq_vector(bd->pdev, i);
   363	
   364		bd->irqs_acquired = irqs_demand;
   365		/* Reduce rings based upon num of vectors allocated.
   366		 * We dont need to consider NQs as they have been calculated
   367		 * and must be more than irqs_demand.
   368		 */
   369		rc = bnge_adjust_rings(bd, &bd->rx_nr_rings,
   370				       &bd->tx_nr_rings,
   371				       irqs_demand - aux_msix, min == 1);
   372		if (rc)
   373			goto err_free_irqs;
   374	
   375		tx_cp = bnge_num_tx_to_cp(bd, bd->tx_nr_rings);
   376		bd->nq_nr_rings = (min == 1) ?
   377			max_t(u16, tx_cp, bd->rx_nr_rings) :
   378			tx_cp + bd->rx_nr_rings;
   379	
   380		/* Readjust tx_nr_rings_per_tc */
   381		if (!bd->num_tc)
   382			bd->tx_nr_rings_per_tc = bd->tx_nr_rings;
   383	
   384		return 0;
   385	
   386	err_free_irqs:
   387		dev_err(bd->dev, "Failed to allocate IRQs err = %d\n", rc);
   388		bnge_free_irqs(bd);
   389		return rc;
   390	}
   391	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 09/10] bng_en: Initialize default configuration
  2025-06-18 14:47 ` [net-next, 09/10] bng_en: Initialize default configuration Vikas Gupta
                     ` (2 preceding siblings ...)
  2025-06-20  9:08   ` kernel test robot
@ 2025-06-22 12:39   ` kernel test robot
  2025-06-26  8:47   ` kernel test robot
  4 siblings, 0 replies; 37+ messages in thread
From: kernel test robot @ 2025-06-22 12:39 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: oe-kbuild-all, netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Hi Vikas,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.16-rc2 next-20250620]
[cannot apply to horms-ipvs/master]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Vikas-Gupta/bng_en-Add-PCI-interface/20250618-173130
base:   linus/master
patch link:    https://lore.kernel.org/r/20250618144743.843815-10-vikas.gupta%40broadcom.com
patch subject: [net-next, 09/10] bng_en: Initialize default configuration
config: parisc-randconfig-r073-20250619 (https://download.01.org/0day-ci/archive/20250622/202506222025.zd9UxyF7-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 8.5.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506222025.zd9UxyF7-lkp@intel.com/

New smatch warnings:
drivers/net/ethernet/broadcom/bnge/bnge_resc.c:533 bnge_net_init_dflt_rings() warn: always true condition '(rc != -19) => (0-u16max != (-19))'

Old smatch warnings:
drivers/net/ethernet/broadcom/bnge/bnge_resc.c:372 bnge_alloc_irqs() warn: unsigned 'irqs_demand' is never less than zero.
drivers/net/ethernet/broadcom/bnge/bnge_resc.c:542 bnge_net_init_dflt_rings() warn: always true condition '(rc != -19) => (0-u16max != (-19))'

vim +533 drivers/net/ethernet/broadcom/bnge/bnge_resc.c

   511	
   512	static int bnge_net_init_dflt_rings(struct bnge_dev *bd, bool sh)
   513	{
   514		u16 dflt_rings, max_rx_rings, max_tx_rings, rc;
   515	
   516		if (sh)
   517			bd->flags |= BNGE_EN_SHARED_CHNL;
   518	
   519		dflt_rings = netif_get_num_default_rss_queues();
   520	
   521		rc = bnge_get_dflt_rings(bd, &max_rx_rings, &max_tx_rings, sh);
   522		if (rc)
   523			return rc;
   524		bd->rx_nr_rings = min_t(u16, dflt_rings, max_rx_rings);
   525		bd->tx_nr_rings_per_tc = min_t(u16, dflt_rings, max_tx_rings);
   526		if (sh)
   527			bnge_trim_dflt_sh_rings(bd);
   528		else
   529			bd->nq_nr_rings = bd->tx_nr_rings_per_tc + bd->rx_nr_rings;
   530		bd->tx_nr_rings = bd->tx_nr_rings_per_tc;
   531	
   532		rc = bnge_reserve_rings(bd);
 > 533		if (rc && rc != -ENODEV)
   534			dev_warn(bd->dev, "Unable to reserve tx rings\n");
   535		bd->tx_nr_rings_per_tc = bd->tx_nr_rings;
   536		if (sh)
   537			bnge_trim_dflt_sh_rings(bd);
   538	
   539		/* Rings may have been reduced, re-reserve them again */
   540		if (bnge_need_reserve_rings(bd)) {
   541			rc = bnge_reserve_rings(bd);
   542			if (rc && rc != -ENODEV)
   543				dev_warn(bd->dev, "Fewer rings reservation failed\n");
   544			bd->tx_nr_rings_per_tc = bd->tx_nr_rings;
   545		}
   546		if (rc) {
   547			bd->tx_nr_rings = 0;
   548			bd->rx_nr_rings = 0;
   549		}
   550	
   551		return rc;
   552	}
   553	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 08/10] bng_en: Add irq allocation support
  2025-06-18 14:47 ` [net-next, 08/10] bng_en: Add irq allocation support Vikas Gupta
                     ` (2 preceding siblings ...)
  2025-06-22  5:21   ` kernel test robot
@ 2025-06-23  6:11   ` kernel test robot
  2025-06-25  9:17   ` kernel test robot
  4 siblings, 0 replies; 37+ messages in thread
From: kernel test robot @ 2025-06-23  6:11 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: oe-kbuild-all, netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Hi Vikas,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.16-rc3 next-20250620]
[cannot apply to horms-ipvs/master]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Vikas-Gupta/bng_en-Add-PCI-interface/20250618-173130
base:   linus/master
patch link:    https://lore.kernel.org/r/20250618144743.843815-9-vikas.gupta%40broadcom.com
patch subject: [net-next, 08/10] bng_en: Add irq allocation support
config: parisc-randconfig-r073-20250619 (https://download.01.org/0day-ci/archive/20250623/202506231320.YMpashmK-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 8.5.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506231320.YMpashmK-lkp@intel.com/

smatch warnings:
drivers/net/ethernet/broadcom/bnge/bnge_resc.c:347 bnge_alloc_irqs() warn: unsigned 'irqs_demand' is never less than zero.

vim +/irqs_demand +347 drivers/net/ethernet/broadcom/bnge/bnge_resc.c

   329	
   330	int bnge_alloc_irqs(struct bnge_dev *bd)
   331	{
   332		u16 aux_msix, tx_cp, num_entries;
   333		u16 irqs_demand, max, min = 1;
   334		int i, rc = 0;
   335	
   336		irqs_demand = bnge_nqs_demand(bd);
   337		max = bnge_get_max_func_irqs(bd);
   338		if (irqs_demand > max)
   339			irqs_demand = max;
   340	
   341		if (!(bd->flags & BNGE_EN_SHARED_CHNL))
   342			min = 2;
   343	
   344		irqs_demand = pci_alloc_irq_vectors(bd->pdev, min, irqs_demand,
   345						    PCI_IRQ_MSIX);
   346		aux_msix = bnge_aux_get_msix(bd);
 > 347		if (irqs_demand < 0 || irqs_demand < aux_msix) {
   348			rc = -ENODEV;
   349			goto err_free_irqs;
   350		}
   351	
   352		num_entries = irqs_demand;
   353		if (pci_msix_can_alloc_dyn(bd->pdev))
   354			num_entries = max;
   355		bd->irq_tbl = kcalloc(num_entries, sizeof(*bd->irq_tbl), GFP_KERNEL);
   356		if (!bd->irq_tbl) {
   357			rc = -ENOMEM;
   358			goto err_free_irqs;
   359		}
   360	
   361		for (i = 0; i < irqs_demand; i++)
   362			bd->irq_tbl[i].vector = pci_irq_vector(bd->pdev, i);
   363	
   364		bd->irqs_acquired = irqs_demand;
   365		/* Reduce rings based upon num of vectors allocated.
   366		 * We dont need to consider NQs as they have been calculated
   367		 * and must be more than irqs_demand.
   368		 */
   369		rc = bnge_adjust_rings(bd, &bd->rx_nr_rings,
   370				       &bd->tx_nr_rings,
   371				       irqs_demand - aux_msix, min == 1);
   372		if (rc)
   373			goto err_free_irqs;
   374	
   375		tx_cp = bnge_num_tx_to_cp(bd, bd->tx_nr_rings);
   376		bd->nq_nr_rings = (min == 1) ?
   377			max_t(u16, tx_cp, bd->rx_nr_rings) :
   378			tx_cp + bd->rx_nr_rings;
   379	
   380		/* Readjust tx_nr_rings_per_tc */
   381		if (!bd->num_tc)
   382			bd->tx_nr_rings_per_tc = bd->tx_nr_rings;
   383	
   384		return 0;
   385	
   386	err_free_irqs:
   387		dev_err(bd->dev, "Failed to allocate IRQs err = %d\n", rc);
   388		bnge_free_irqs(bd);
   389		return rc;
   390	}
   391	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 10/10] bng_en: Add a network device
  2025-06-18 14:47 ` [net-next, 10/10] bng_en: Add a network device Vikas Gupta
@ 2025-06-24  0:42   ` kernel test robot
  0 siblings, 0 replies; 37+ messages in thread
From: kernel test robot @ 2025-06-24  0:42 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: oe-kbuild-all, netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Hi Vikas,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.16-rc3 next-20250623]
[cannot apply to horms-ipvs/master]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Vikas-Gupta/bng_en-Add-PCI-interface/20250618-173130
base:   linus/master
patch link:    https://lore.kernel.org/r/20250618144743.843815-11-vikas.gupta%40broadcom.com
patch subject: [net-next, 10/10] bng_en: Add a network device
config: i386-randconfig-061-20250621 (https://download.01.org/0day-ci/archive/20250624/202506240834.02LQ6IMr-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250624/202506240834.02LQ6IMr-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506240834.02LQ6IMr-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c:26:26: sparse: sparse: symbol 'bnge_ethtool_ops' was not declared. Should it be static?

vim +/bnge_ethtool_ops +26 drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c

    25	
  > 26	const struct ethtool_ops bnge_ethtool_ops = {
    27		.get_drvinfo		= bnge_get_drvinfo,
    28	};
    29	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 03/10] bng_en: Add firmware communication mechanism
  2025-06-19 12:43   ` Vadim Fedorenko
@ 2025-06-24 10:23     ` Vikas Gupta
  0 siblings, 0 replies; 37+ messages in thread
From: Vikas Gupta @ 2025-06-24 10:23 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: davem, edumazet, kuba, pabeni, andrew+netdev, horms, netdev,
	linux-kernel, michael.chan, pavan.chebbi, vsrama-krishna.nemani,
	Bhargava Chenna Marreddy, Rajashekar Hudumula

[-- Attachment #1: Type: text/plain, Size: 3445 bytes --]

Hi Vadim,

On Thu, Jun 19, 2025 at 6:13 PM Vadim Fedorenko
<vadim.fedorenko@linux.dev> wrote:
>
> On 18/06/2025 15:47, Vikas Gupta wrote:
> > Add support to communicate with the firmware.
> > Future patches will use these functions to send the
> > messages to the firmware.
> > Functions support allocating request/response buffers
> > to send a particular command. Each command has certain
> > timeout value to which the driver waits for response from
> > the firmware. In error case, commands may be either timed
> > out waiting on response from the firmware or may return
> > a specific error code.
> >
> > 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>
> > ---
> >   drivers/net/ethernet/broadcom/bnge/Makefile   |   3 +-
> >   drivers/net/ethernet/broadcom/bnge/bnge.h     |  13 +
> >   .../net/ethernet/broadcom/bnge/bnge_hwrm.c    | 503 ++++++++++++++++++
> >   .../net/ethernet/broadcom/bnge/bnge_hwrm.h    | 107 ++++
> >   4 files changed, 625 insertions(+), 1 deletion(-)
> >   create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm.c
> >   create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h
> >
> > diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethernet/broadcom/bnge/Makefile
> > index e021a14d2fa0..b296d7de56ce 100644
> > --- a/drivers/net/ethernet/broadcom/bnge/Makefile
> > +++ b/drivers/net/ethernet/broadcom/bnge/Makefile
> > @@ -3,4 +3,5 @@
> >   obj-$(CONFIG_BNGE) += bng_en.o
> >
> >   bng_en-y := bnge_core.o \
> > -         bnge_devlink.o
> > +         bnge_devlink.o \
> > +         bnge_hwrm.o
> > diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
> > index 19d85aabab4e..8f2a562d9ae2 100644
> > --- a/drivers/net/ethernet/broadcom/bnge/bnge.h
> > +++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
> > @@ -13,6 +13,8 @@ enum board_idx {
> >       BCM57708,
> >   };
> >
> > +#define INVALID_HW_RING_ID      ((u16)-1)
> > +
> >   struct bnge_dev {
> >       struct device   *dev;
> >       struct pci_dev  *pdev;
> > @@ -22,6 +24,17 @@ struct bnge_dev {
> >       char            board_serialno[BNGE_VPD_FLD_LEN];
> >
> >       void __iomem    *bar0;
> > +
> > +     /* HWRM members */
> > +     u16                     hwrm_cmd_seq;
> > +     u16                     hwrm_cmd_kong_seq;
> > +     struct dma_pool         *hwrm_dma_pool;
> > +     struct hlist_head       hwrm_pending_list;
> > +     u16                     hwrm_max_req_len;
> > +     u16                     hwrm_max_ext_req_len;
> > +     unsigned int            hwrm_cmd_timeout;
> > +     unsigned int            hwrm_cmd_max_timeout;
> > +     struct mutex            hwrm_cmd_lock;  /* serialize hwrm messages */
> >   };
>
> It's all looks pretty similar to what is used in bnxt driver. Why do you
> duplicate the code rather then reusing (and improving) the existing one?
>
> I didn't look carefully, but in case it's impossible to merge hwrm code
> from bnxt, you have to make function names prepended with bnge prefix...

 Both the bnxt and bnge drivers follow the same protocol to send the
requests with the firmware,
so the HWRM mechanism is similar. I'll consider renaming the function
names in v2.

>
>
>

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4193 bytes --]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 04/10] bng_en: Add initial interaction with firmware
  2025-06-19 12:53   ` Vadim Fedorenko
@ 2025-06-24 10:26     ` Vikas Gupta
  2025-06-24 12:11       ` Vadim Fedorenko
  0 siblings, 1 reply; 37+ messages in thread
From: Vikas Gupta @ 2025-06-24 10:26 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: davem, edumazet, kuba, pabeni, andrew+netdev, horms, netdev,
	linux-kernel, michael.chan, pavan.chebbi, vsrama-krishna.nemani,
	Bhargava Chenna Marreddy, Rajashekar Hudumula

[-- Attachment #1: Type: text/plain, Size: 26111 bytes --]

On Thu, Jun 19, 2025 at 6:23 PM Vadim Fedorenko
<vadim.fedorenko@linux.dev> wrote:
>
> On 18/06/2025 15:47, Vikas Gupta wrote:
> > Query firmware with the help of basic firmware commands and
> > cache the capabilities. With the help of basic commands
> > start the initialization process of the driver with the
> > firmware.
> > Since basic information is available from the firmware,
> > add that information to the devlink info get command.
> >
> > 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>
> > ---
> >   drivers/net/ethernet/broadcom/bnge/Makefile   |   3 +-
> >   drivers/net/ethernet/broadcom/bnge/bnge.h     |  54 +++++
> >   .../net/ethernet/broadcom/bnge/bnge_core.c    |  67 ++++++
> >   .../net/ethernet/broadcom/bnge/bnge_devlink.c | 120 ++++++++++
> >   .../ethernet/broadcom/bnge/bnge_hwrm_lib.c    | 213 ++++++++++++++++++
> >   .../ethernet/broadcom/bnge/bnge_hwrm_lib.h    |  16 ++
> >   6 files changed, 472 insertions(+), 1 deletion(-)
> >   create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
> >   create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
> >
> > diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethernet/broadcom/bnge/Makefile
> > index b296d7de56ce..b8dbbc2d5972 100644
> > --- a/drivers/net/ethernet/broadcom/bnge/Makefile
> > +++ b/drivers/net/ethernet/broadcom/bnge/Makefile
> > @@ -4,4 +4,5 @@ obj-$(CONFIG_BNGE) += bng_en.o
> >
> >   bng_en-y := bnge_core.o \
> >           bnge_devlink.o \
> > -         bnge_hwrm.o
> > +         bnge_hwrm.o \
> > +         bnge_hwrm_lib.o
> > diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
> > index 8f2a562d9ae2..60af0517c45e 100644
> > --- a/drivers/net/ethernet/broadcom/bnge/bnge.h
> > +++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
> > @@ -7,6 +7,13 @@
> >   #define DRV_NAME    "bng_en"
> >   #define DRV_SUMMARY "Broadcom 800G Ethernet Linux Driver"
> >
> > +#include <linux/etherdevice.h>
> > +#include "../bnxt/bnxt_hsi.h"
> > +
> > +#define DRV_VER_MAJ  1
> > +#define DRV_VER_MIN  15
> > +#define DRV_VER_UPD  1
> > +
> >   extern char bnge_driver_name[];
> >
> >   enum board_idx {
> > @@ -15,6 +22,36 @@ enum board_idx {
> >
> >   #define INVALID_HW_RING_ID      ((u16)-1)
> >
> > +enum {
> > +     BNGE_FW_CAP_SHORT_CMD                           = BIT_ULL(0),
> > +     BNGE_FW_CAP_LLDP_AGENT                          = BIT_ULL(1),
> > +     BNGE_FW_CAP_DCBX_AGENT                          = BIT_ULL(2),
> > +     BNGE_FW_CAP_IF_CHANGE                           = BIT_ULL(3),
> > +     BNGE_FW_CAP_KONG_MB_CHNL                        = BIT_ULL(4),
> > +     BNGE_FW_CAP_ERROR_RECOVERY                      = BIT_ULL(5),
> > +     BNGE_FW_CAP_PKG_VER                             = BIT_ULL(6),
> > +     BNGE_FW_CAP_CFA_ADV_FLOW                        = BIT_ULL(7),
> > +     BNGE_FW_CAP_CFA_RFS_RING_TBL_IDX_V2             = BIT_ULL(8),
> > +     BNGE_FW_CAP_PCIE_STATS_SUPPORTED                = BIT_ULL(9),
> > +     BNGE_FW_CAP_EXT_STATS_SUPPORTED                 = BIT_ULL(10),
> > +     BNGE_FW_CAP_ERR_RECOVER_RELOAD                  = BIT_ULL(11),
> > +     BNGE_FW_CAP_HOT_RESET                           = BIT_ULL(12),
> > +     BNGE_FW_CAP_RX_ALL_PKT_TS                       = BIT_ULL(13),
> > +     BNGE_FW_CAP_VLAN_RX_STRIP                       = BIT_ULL(14),
> > +     BNGE_FW_CAP_VLAN_TX_INSERT                      = BIT_ULL(15),
> > +     BNGE_FW_CAP_EXT_HW_STATS_SUPPORTED              = BIT_ULL(16),
> > +     BNGE_FW_CAP_LIVEPATCH                           = BIT_ULL(17),
> > +     BNGE_FW_CAP_HOT_RESET_IF                        = BIT_ULL(18),
> > +     BNGE_FW_CAP_RING_MONITOR                        = BIT_ULL(19),
> > +     BNGE_FW_CAP_DBG_QCAPS                           = BIT_ULL(20),
> > +     BNGE_FW_CAP_THRESHOLD_TEMP_SUPPORTED            = BIT_ULL(21),
> > +     BNGE_FW_CAP_DFLT_VLAN_TPID_PCP                  = BIT_ULL(22),
> > +     BNGE_FW_CAP_VNIC_TUNNEL_TPA                     = BIT_ULL(23),
> > +     BNGE_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO          = BIT_ULL(24),
> > +     BNGE_FW_CAP_CFA_RFS_RING_TBL_IDX_V3             = BIT_ULL(25),
> > +     BNGE_FW_CAP_VNIC_RE_FLUSH                       = BIT_ULL(26),
> > +};
> > +
> >   struct bnge_dev {
> >       struct device   *dev;
> >       struct pci_dev  *pdev;
> > @@ -25,6 +62,9 @@ struct bnge_dev {
> >
> >       void __iomem    *bar0;
> >
> > +     u16             chip_num;
> > +     u8              chip_rev;
> > +
> >       /* HWRM members */
> >       u16                     hwrm_cmd_seq;
> >       u16                     hwrm_cmd_kong_seq;
> > @@ -35,6 +75,20 @@ struct bnge_dev {
> >       unsigned int            hwrm_cmd_timeout;
> >       unsigned int            hwrm_cmd_max_timeout;
> >       struct mutex            hwrm_cmd_lock;  /* serialize hwrm messages */
> > +
> > +     struct hwrm_ver_get_output      ver_resp;
> > +#define FW_VER_STR_LEN               32
> > +     char                    fw_ver_str[FW_VER_STR_LEN];
> > +     char                    hwrm_ver_supp[FW_VER_STR_LEN];
> > +     char                    nvm_cfg_ver[FW_VER_STR_LEN];
> > +     u64                     fw_ver_code;
> > +#define BNGE_FW_VER_CODE(maj, min, bld, rsv)                 \
> > +     ((u64)(maj) << 48 | (u64)(min) << 32 | (u64)(bld) << 16 | (rsv))
> > +
> > +     unsigned long           state;
> > +#define BNGE_STATE_DRV_REGISTERED      0
> > +
> > +     u64                     fw_cap;
> >   };
> >
> >   #endif /* _BNGE_H_ */
> > diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_core.c b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
> > index 1a46c7663012..5e23eb14f60e 100644
> > --- a/drivers/net/ethernet/broadcom/bnge/bnge_core.c
> > +++ b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
> > @@ -8,6 +8,8 @@
> >
> >   #include "bnge.h"
> >   #include "bnge_devlink.h"
> > +#include "bnge_hwrm.h"
> > +#include "bnge_hwrm_lib.h"
> >
> >   MODULE_LICENSE("GPL");
> >   MODULE_DESCRIPTION(DRV_SUMMARY);
> > @@ -37,6 +39,51 @@ static void bnge_print_device_info(struct pci_dev *pdev, enum board_idx idx)
> >       pcie_print_link_status(pdev);
> >   }
> >
> > +static void bnge_nvm_cfg_ver_get(struct bnge_dev *bd)
> > +{
> > +     struct hwrm_nvm_get_dev_info_output nvm_info;
> > +
> > +     if (!bnge_hwrm_nvm_dev_info(bd, &nvm_info))
> > +             snprintf(bd->nvm_cfg_ver, FW_VER_STR_LEN, "%d.%d.%d",
> > +                      nvm_info.nvm_cfg_ver_maj, nvm_info.nvm_cfg_ver_min,
> > +                      nvm_info.nvm_cfg_ver_upd);
> > +}
> > +
> > +static void bnge_fw_unregister_dev(struct bnge_dev *bd)
> > +{
> > +     bnge_hwrm_func_drv_unrgtr(bd);
> > +}
> > +
> > +static int bnge_fw_register_dev(struct bnge_dev *bd)
> > +{
> > +     int rc;
> > +
> > +     bd->fw_cap = 0;
> > +     rc = bnge_hwrm_ver_get(bd);
> > +     if (rc) {
> > +             dev_err(bd->dev, "Get Version command failed rc: %d\n", rc);
> > +             return rc;
> > +     }
> > +
> > +     bnge_nvm_cfg_ver_get(bd);
> > +
> > +     rc = bnge_hwrm_func_reset(bd);
> > +     if (rc) {
> > +             dev_err(bd->dev, "Failed to reset function rc: %d\n", rc);
> > +             return rc;
> > +     }
> > +
> > +     bnge_hwrm_fw_set_time(bd);
> > +
> > +     rc =  bnge_hwrm_func_drv_rgtr(bd);
> > +     if (rc) {
> > +             dev_err(bd->dev, "Failed to rgtr with firmware rc: %d\n", rc);
> > +             return rc;
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> >   static void bnge_pci_disable(struct pci_dev *pdev)
> >   {
> >       pci_release_regions(pdev);
> > @@ -136,10 +183,26 @@ static int bnge_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
> >               goto err_devl_unreg;
> >       }
> >
> > +     rc = bnge_init_hwrm_resources(bd);
> > +     if (rc)
> > +             goto err_bar_unmap;
> > +
> > +     rc = bnge_fw_register_dev(bd);
> > +     if (rc) {
> > +             dev_err(&pdev->dev, "Failed to register with firmware rc = %d\n", rc);
> > +             goto err_hwrm_cleanup;
> > +     }
> > +
> >       pci_save_state(pdev);
> >
> >       return 0;
> >
> > +err_hwrm_cleanup:
> > +     bnge_cleanup_hwrm_resources(bd);
> > +
> > +err_bar_unmap:
> > +     bnge_unmap_bars(pdev);
> > +
> >   err_devl_unreg:
> >       bnge_devlink_unregister(bd);
> >       bnge_devlink_free(bd);
> > @@ -153,6 +216,10 @@ static void bnge_remove_one(struct pci_dev *pdev)
> >   {
> >       struct bnge_dev *bd = pci_get_drvdata(pdev);
> >
> > +     bnge_fw_unregister_dev(bd);
> > +
> > +     bnge_cleanup_hwrm_resources(bd);
> > +
> >       bnge_unmap_bars(pdev);
> >
> >       bnge_devlink_unregister(bd);
> > diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
> > index d406338da130..f987d35beea2 100644
> > --- a/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
> > +++ b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
> > @@ -8,6 +8,7 @@
> >
> >   #include "bnge.h"
> >   #include "bnge_devlink.h"
> > +#include "bnge_hwrm_lib.h"
> >
> >   static int bnge_dl_info_put(struct bnge_dev *bd, struct devlink_info_req *req,
> >                           enum bnge_dl_version_type type, const char *key,
> > @@ -16,6 +17,10 @@ static int bnge_dl_info_put(struct bnge_dev *bd, struct devlink_info_req *req,
> >       if (!strlen(buf))
> >               return 0;
> >
> > +     if (!strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_NCSI) ||
> > +         !strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_ROCE))
> > +             return 0;
> > +
> >       switch (type) {
> >       case BNGE_VERSION_FIXED:
> >               return devlink_info_version_fixed_put(req, key, buf);
> > @@ -63,11 +68,20 @@ static void bnge_vpd_read_info(struct bnge_dev *bd)
> >       kfree(vpd_data);
> >   }
> >
> > +#define HWRM_FW_VER_STR_LEN  16
> > +
> >   static int bnge_devlink_info_get(struct devlink *devlink,
> >                                struct devlink_info_req *req,
> >                                struct netlink_ext_ack *extack)
> >   {
> > +     struct hwrm_nvm_get_dev_info_output nvm_dev_info;
> >       struct bnge_dev *bd = devlink_priv(devlink);
> > +     struct hwrm_ver_get_output *ver_resp;
> > +     char mgmt_ver[FW_VER_STR_LEN];
> > +     char roce_ver[FW_VER_STR_LEN];
> > +     char ncsi_ver[FW_VER_STR_LEN];
> > +     char buf[32];
> > +
> >       int rc;
> >
> >       if (bd->dsn) {
> > @@ -95,6 +109,112 @@ static int bnge_devlink_info_get(struct devlink *devlink,
> >                             DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
> >                             bd->board_partno);
> >
> > +     /* More information from HWRM ver get command */
> > +     sprintf(buf, "%X", bd->chip_num);
> > +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_FIXED,
> > +                           DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, buf);
> > +     if (rc)
> > +             return rc;
> > +
> > +     ver_resp = &bd->ver_resp;
> > +     sprintf(buf, "%c%d", 'A' + ver_resp->chip_rev, ver_resp->chip_metal);
> > +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_FIXED,
> > +                           DEVLINK_INFO_VERSION_GENERIC_ASIC_REV, buf);
> > +     if (rc)
> > +             return rc;
> > +
> > +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
> > +                           DEVLINK_INFO_VERSION_GENERIC_FW_PSID,
> > +                           bd->nvm_cfg_ver);
> > +     if (rc)
> > +             return rc;
> > +
> > +     buf[0] = 0;
> > +     strncat(buf, ver_resp->active_pkg_name, HWRM_FW_VER_STR_LEN);
> > +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
> > +                           DEVLINK_INFO_VERSION_GENERIC_FW, buf);
> > +     if (rc)
> > +             return rc;
> > +
> > +     if (ver_resp->flags & VER_GET_RESP_FLAGS_EXT_VER_AVAIL) {
> > +             snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> > +                      ver_resp->hwrm_fw_major, ver_resp->hwrm_fw_minor,
> > +                      ver_resp->hwrm_fw_build, ver_resp->hwrm_fw_patch);
> > +
> > +             snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> > +                      ver_resp->mgmt_fw_major, ver_resp->mgmt_fw_minor,
> > +                      ver_resp->mgmt_fw_build, ver_resp->mgmt_fw_patch);
> > +
> > +             snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> > +                      ver_resp->roce_fw_major, ver_resp->roce_fw_minor,
> > +                      ver_resp->roce_fw_build, ver_resp->roce_fw_patch);
> > +     } else {
> > +             snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> > +                      ver_resp->hwrm_fw_maj_8b, ver_resp->hwrm_fw_min_8b,
> > +                      ver_resp->hwrm_fw_bld_8b, ver_resp->hwrm_fw_rsvd_8b);
> > +
> > +             snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> > +                      ver_resp->mgmt_fw_maj_8b, ver_resp->mgmt_fw_min_8b,
> > +                      ver_resp->mgmt_fw_bld_8b, ver_resp->mgmt_fw_rsvd_8b);
> > +
> > +             snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> > +                      ver_resp->roce_fw_maj_8b, ver_resp->roce_fw_min_8b,
> > +                      ver_resp->roce_fw_bld_8b, ver_resp->roce_fw_rsvd_8b);
> > +     }
> > +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
> > +                           DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
> > +     if (rc)
> > +             return rc;
> > +
> > +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
> > +                           DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API,
> > +                           bd->hwrm_ver_supp);
> > +     if (rc)
> > +             return rc;
> > +
> > +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
> > +                           DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver);
> > +     if (rc)
> > +             return rc;
> > +
> > +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
> > +                           DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver);
> > +     if (rc)
> > +             return rc;
> > +
> > +     rc = bnge_hwrm_nvm_dev_info(bd, &nvm_dev_info);
> > +     if (!(nvm_dev_info.flags & NVM_GET_DEV_INFO_RESP_FLAGS_FW_VER_VALID))
> > +             return 0;
> > +
> > +     buf[0] = 0;
> > +     strncat(buf, nvm_dev_info.pkg_name, HWRM_FW_VER_STR_LEN);
> > +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
> > +                           DEVLINK_INFO_VERSION_GENERIC_FW, buf);
> > +     if (rc)
> > +             return rc;
> > +
> > +     snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> > +              nvm_dev_info.hwrm_fw_major, nvm_dev_info.hwrm_fw_minor,
> > +              nvm_dev_info.hwrm_fw_build, nvm_dev_info.hwrm_fw_patch);
> > +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
> > +                           DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
> > +     if (rc)
> > +             return rc;
> > +
> > +     snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> > +              nvm_dev_info.mgmt_fw_major, nvm_dev_info.mgmt_fw_minor,
> > +              nvm_dev_info.mgmt_fw_build, nvm_dev_info.mgmt_fw_patch);
> > +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
> > +                           DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver);
> > +     if (rc)
> > +             return rc;
> > +
> > +     snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
> > +              nvm_dev_info.roce_fw_major, nvm_dev_info.roce_fw_minor,
> > +              nvm_dev_info.roce_fw_build, nvm_dev_info.roce_fw_patch);
> > +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
> > +                           DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver);
> > +
> >       return rc;
> >   }
> >
> > diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
> > new file mode 100644
> > index 000000000000..567376a407df
> > --- /dev/null
> > +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
> > @@ -0,0 +1,213 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +// Copyright (c) 2025 Broadcom.
> > +
> > +#include <linux/errno.h>
> > +#include <linux/kernel.h>
> > +#include <linux/mm.h>
> > +#include <linux/pci.h>
> > +
> > +#include "bnge.h"
> > +#include "../bnxt/bnxt_hsi.h"
> > +#include "bnge_hwrm.h"
> > +#include "bnge_hwrm_lib.h"
> > +
> > +int bnge_hwrm_ver_get(struct bnge_dev *bd)
> > +{
> > +     u32 dev_caps_cfg, hwrm_ver, hwrm_spec_code;
> > +     u16 fw_maj, fw_min, fw_bld, fw_rsv;
> > +     struct hwrm_ver_get_output *resp;
> > +     struct hwrm_ver_get_input *req;
> > +     int rc;
> > +
> > +     rc = hwrm_req_init(bd, req, HWRM_VER_GET);
> > +     if (rc)
> > +             return rc;
> > +
> > +     hwrm_req_flags(bd, req, BNGE_HWRM_FULL_WAIT);
> > +     bd->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
> > +     req->hwrm_intf_maj = HWRM_VERSION_MAJOR;
> > +     req->hwrm_intf_min = HWRM_VERSION_MINOR;
> > +     req->hwrm_intf_upd = HWRM_VERSION_UPDATE;
> > +
> > +     resp = hwrm_req_hold(bd, req);
> > +     rc = hwrm_req_send(bd, req);
> > +     if (rc)
> > +             goto hwrm_ver_get_exit;
> > +
> > +     memcpy(&bd->ver_resp, resp, sizeof(struct hwrm_ver_get_output));
> > +
> > +     hwrm_spec_code = resp->hwrm_intf_maj_8b << 16 |
> > +                      resp->hwrm_intf_min_8b << 8 |
> > +                      resp->hwrm_intf_upd_8b;
> > +     hwrm_ver = HWRM_VERSION_MAJOR << 16 | HWRM_VERSION_MINOR << 8 |
> > +                     HWRM_VERSION_UPDATE;
> > +
> > +     if (hwrm_spec_code > hwrm_ver)
> > +             snprintf(bd->hwrm_ver_supp, FW_VER_STR_LEN, "%d.%d.%d",
> > +                      HWRM_VERSION_MAJOR, HWRM_VERSION_MINOR,
> > +                      HWRM_VERSION_UPDATE);
> > +     else
> > +             snprintf(bd->hwrm_ver_supp, FW_VER_STR_LEN, "%d.%d.%d",
> > +                      resp->hwrm_intf_maj_8b, resp->hwrm_intf_min_8b,
> > +                      resp->hwrm_intf_upd_8b);
> > +
> > +     fw_maj = le16_to_cpu(resp->hwrm_fw_major);
> > +     fw_min = le16_to_cpu(resp->hwrm_fw_minor);
> > +     fw_bld = le16_to_cpu(resp->hwrm_fw_build);
> > +     fw_rsv = le16_to_cpu(resp->hwrm_fw_patch);
> > +
> > +     bd->fw_ver_code = BNGE_FW_VER_CODE(fw_maj, fw_min, fw_bld, fw_rsv);
> > +     snprintf(bd->fw_ver_str, FW_VER_STR_LEN, "%d.%d.%d.%d",
> > +              fw_maj, fw_min, fw_bld, fw_rsv);
> > +
> > +     if (strlen(resp->active_pkg_name)) {
> > +             int fw_ver_len = strlen(bd->fw_ver_str);
> > +
> > +             snprintf(bd->fw_ver_str + fw_ver_len,
> > +                      FW_VER_STR_LEN - fw_ver_len - 1, "/pkg %s",
> > +                      resp->active_pkg_name);
> > +             bd->fw_cap |= BNGE_FW_CAP_PKG_VER;
> > +     }
> > +
> > +     bd->hwrm_cmd_timeout = le16_to_cpu(resp->def_req_timeout);
> > +     if (!bd->hwrm_cmd_timeout)
> > +             bd->hwrm_cmd_timeout = DFLT_HWRM_CMD_TIMEOUT;
> > +     bd->hwrm_cmd_max_timeout = le16_to_cpu(resp->max_req_timeout) * 1000;
> > +     if (!bd->hwrm_cmd_max_timeout)
> > +             bd->hwrm_cmd_max_timeout = HWRM_CMD_MAX_TIMEOUT;
> > +     else if (bd->hwrm_cmd_max_timeout > HWRM_CMD_MAX_TIMEOUT)
> > +                     dev_warn(bd->dev, "Default HWRM commands max timeout increased to %d seconds\n",
> > +                              bd->hwrm_cmd_max_timeout / 1000);
> > +
> > +     bd->hwrm_max_req_len = le16_to_cpu(resp->max_req_win_len);
> > +     bd->hwrm_max_ext_req_len = le16_to_cpu(resp->max_ext_req_len);
> > +
> > +     if (bd->hwrm_max_ext_req_len < HWRM_MAX_REQ_LEN)
> > +             bd->hwrm_max_ext_req_len = HWRM_MAX_REQ_LEN;
> > +
> > +     bd->chip_num = le16_to_cpu(resp->chip_num);
> > +     bd->chip_rev = resp->chip_rev;
> > +
> > +     dev_caps_cfg = le32_to_cpu(resp->dev_caps_cfg);
> > +     if ((dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
> > +         (dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
> > +             bd->fw_cap |= BNGE_FW_CAP_SHORT_CMD;
> > +
> > +     if (dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_KONG_MB_CHNL_SUPPORTED)
> > +             bd->fw_cap |= BNGE_FW_CAP_KONG_MB_CHNL;
> > +
> > +     if (dev_caps_cfg &
> > +         VER_GET_RESP_DEV_CAPS_CFG_CFA_ADV_FLOW_MGNT_SUPPORTED)
> > +             bd->fw_cap |= BNGE_FW_CAP_CFA_ADV_FLOW;
> > +
> > +hwrm_ver_get_exit:
> > +     hwrm_req_drop(bd, req);
> > +     return rc;
> > +}
> > +
> > +int
> > +bnge_hwrm_nvm_dev_info(struct bnge_dev *bd,
> > +                    struct hwrm_nvm_get_dev_info_output *nvm_info)
> > +{
> > +     struct hwrm_nvm_get_dev_info_output *resp;
> > +     struct hwrm_nvm_get_dev_info_input *req;
> > +     int rc;
> > +
> > +     rc = hwrm_req_init(bd, req, HWRM_NVM_GET_DEV_INFO);
> > +     if (rc)
> > +             return rc;
> > +
> > +     resp = hwrm_req_hold(bd, req);
> > +     rc = hwrm_req_send(bd, req);
> > +     if (!rc)
> > +             memcpy(nvm_info, resp, sizeof(*resp));
> > +     hwrm_req_drop(bd, req);
> > +     return rc;
> > +}
> > +
> > +int bnge_hwrm_func_reset(struct bnge_dev *bd)
> > +{
> > +     struct hwrm_func_reset_input *req;
> > +     int rc;
> > +
> > +     rc = hwrm_req_init(bd, req, HWRM_FUNC_RESET);
> > +     if (rc)
> > +             return rc;
> > +
> > +     req->enables = 0;
> > +     hwrm_req_timeout(bd, req, HWRM_RESET_TIMEOUT);
> > +     return hwrm_req_send(bd, req);
> > +}
> > +
> > +int bnge_hwrm_fw_set_time(struct bnge_dev *bd)
> > +{
> > +     struct hwrm_fw_set_time_input *req;
> > +     struct tm tm;
> > +     time64_t now = ktime_get_real_seconds();
> > +     int rc;
>
> Reverse xmass tree, please. Not quite sure you need this 'now'
> variable at all. You can use ktime_get_real_seconds() directly
> in time64_to_tm() - there are examples of such code in the kernel.

 Will fix it in v2.

>
> > +
> > +     time64_to_tm(now, 0, &tm);
> > +     rc = hwrm_req_init(bd, req, HWRM_FW_SET_TIME);
> > +     if (rc)
> > +             return rc;
> > +
> > +     req->year = cpu_to_le16(1900 + tm.tm_year);
> > +     req->month = 1 + tm.tm_mon;
> > +     req->day = tm.tm_mday;
> > +     req->hour = tm.tm_hour;
> > +     req->minute = tm.tm_min;
> > +     req->second = tm.tm_sec;
> > +     return hwrm_req_send(bd, req);
> > +}
>
> This whole function looks like copy-paste from bnxt, did you consider
> merging these parts?

Both the bnxt and bnge drivers follow the same protocol to send the
requests to  the firmware,
so some functions may appear similar. However, we do not plan to share
the code, as certain
 fundamental data structures will differ.

>
>
> > +
> > +int bnge_hwrm_func_drv_rgtr(struct bnge_dev *bd)
> > +{
> > +     struct hwrm_func_drv_rgtr_output *resp;
> > +     struct hwrm_func_drv_rgtr_input *req;
> > +     u32 flags;
> > +     int rc;
> > +
> > +     rc = hwrm_req_init(bd, req, HWRM_FUNC_DRV_RGTR);
> > +     if (rc)
> > +             return rc;
> > +
> > +     req->enables = cpu_to_le32(FUNC_DRV_RGTR_REQ_ENABLES_OS_TYPE |
> > +                                FUNC_DRV_RGTR_REQ_ENABLES_VER |
> > +                                FUNC_DRV_RGTR_REQ_ENABLES_ASYNC_EVENT_FWD);
> > +
> > +     req->os_type = cpu_to_le16(FUNC_DRV_RGTR_REQ_OS_TYPE_LINUX);
> > +     flags = FUNC_DRV_RGTR_REQ_FLAGS_16BIT_VER_MODE;
> > +
> > +     req->flags = cpu_to_le32(flags);
> > +     req->ver_maj_8b = DRV_VER_MAJ;
> > +     req->ver_min_8b = DRV_VER_MIN;
> > +     req->ver_upd_8b = DRV_VER_UPD;
> > +     req->ver_maj = cpu_to_le16(DRV_VER_MAJ);
> > +     req->ver_min = cpu_to_le16(DRV_VER_MIN);
> > +     req->ver_upd = cpu_to_le16(DRV_VER_UPD);
> > +
> > +     resp = hwrm_req_hold(bd, req);
> > +     rc = hwrm_req_send(bd, req);
> > +     if (!rc) {
> > +             set_bit(BNGE_STATE_DRV_REGISTERED, &bd->state);
> > +             if (resp->flags &
> > +                 cpu_to_le32(FUNC_DRV_RGTR_RESP_FLAGS_IF_CHANGE_SUPPORTED))
> > +                     bd->fw_cap |= BNGE_FW_CAP_IF_CHANGE;
> > +     }
> > +     hwrm_req_drop(bd, req);
> > +     return rc;
> > +}
> > +
> > +int bnge_hwrm_func_drv_unrgtr(struct bnge_dev *bd)
> > +{
> > +     struct hwrm_func_drv_unrgtr_input *req;
> > +     int rc;
> > +
> > +     if (!test_and_clear_bit(BNGE_STATE_DRV_REGISTERED, &bd->state))
> > +             return 0;
> > +
> > +     rc = hwrm_req_init(bd, req, HWRM_FUNC_DRV_UNRGTR);
> > +     if (rc)
> > +             return rc;
> > +     return hwrm_req_send(bd, req);
> > +}
> > diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
> > new file mode 100644
> > index 000000000000..9308d4fe64d2
> > --- /dev/null
> > +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
> > @@ -0,0 +1,16 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/* Copyright (c) 2025 Broadcom */
> > +
> > +#ifndef _BNGE_HWRM_LIB_H_
> > +#define _BNGE_HWRM_LIB_H_
> > +
> > +int bnge_hwrm_ver_get(struct bnge_dev *bd);
> > +int bnge_hwrm_func_reset(struct bnge_dev *bd);
> > +int bnge_hwrm_fw_set_time(struct bnge_dev *bd);
> > +int bnge_hwrm_func_drv_rgtr(struct bnge_dev *bd);
> > +int bnge_hwrm_func_drv_unrgtr(struct bnge_dev *bd);
> > +int bnge_hwrm_vnic_qcaps(struct bnge_dev *bd);
> > +int bnge_hwrm_nvm_dev_info(struct bnge_dev *bd,
> > +                        struct hwrm_nvm_get_dev_info_output *nvm_dev_info);
> > +
> > +#endif /* _BNGE_HWRM_LIB_H_ */
>

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4193 bytes --]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 06/10] bng_en: Add backing store support
  2025-06-19 13:02   ` Vadim Fedorenko
@ 2025-06-24 10:29     ` Vikas Gupta
  2025-06-24 12:12       ` Vadim Fedorenko
  0 siblings, 1 reply; 37+ messages in thread
From: Vikas Gupta @ 2025-06-24 10:29 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: davem, edumazet, kuba, pabeni, andrew+netdev, horms, netdev,
	linux-kernel, michael.chan, pavan.chebbi, vsrama-krishna.nemani,
	Bhargava Chenna Marreddy, Rajashekar Hudumula

[-- Attachment #1: Type: text/plain, Size: 4741 bytes --]

On Thu, Jun 19, 2025 at 6:32 PM Vadim Fedorenko
<vadim.fedorenko@linux.dev> wrote:
>
> On 18/06/2025 15:47, Vikas Gupta wrote:
> > Backing store or context memory on the host helps the
> > device to manage rings, stats and other resources.
> > Context memory is allocated with the help of ring
> > alloc/free functions.
> >
> > 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>
> > ---
> >   drivers/net/ethernet/broadcom/bnge/bnge.h     |  18 +
> >   .../ethernet/broadcom/bnge/bnge_hwrm_lib.c    | 168 +++++++++
> >   .../ethernet/broadcom/bnge/bnge_hwrm_lib.h    |   4 +
> >   .../net/ethernet/broadcom/bnge/bnge_rmem.c    | 337 ++++++++++++++++++
> >   .../net/ethernet/broadcom/bnge/bnge_rmem.h    | 153 ++++++++
> >   5 files changed, 680 insertions(+)
> >
> > diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
> > index 60af0517c45e..01f64a10729c 100644
> > --- a/drivers/net/ethernet/broadcom/bnge/bnge.h
> > +++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
> > @@ -9,6 +9,7 @@
> >
> >   #include <linux/etherdevice.h>
> >   #include "../bnxt/bnxt_hsi.h"
> > +#include "bnge_rmem.h"
> >
> >   #define DRV_VER_MAJ 1
> >   #define DRV_VER_MIN 15
> > @@ -52,6 +53,13 @@ enum {
> >       BNGE_FW_CAP_VNIC_RE_FLUSH                       = BIT_ULL(26),
> >   };
> >
> > +enum {
> > +     BNGE_EN_ROCE_V1                                 = BIT_ULL(0),
> > +     BNGE_EN_ROCE_V2                                 = BIT_ULL(1),
> > +};
> > +
> > +#define BNGE_EN_ROCE         (BNGE_EN_ROCE_V1 | BNGE_EN_ROCE_V2)
> > +
> >   struct bnge_dev {
> >       struct device   *dev;
> >       struct pci_dev  *pdev;
> > @@ -89,6 +97,16 @@ struct bnge_dev {
> >   #define BNGE_STATE_DRV_REGISTERED      0
> >
> >       u64                     fw_cap;
> > +
> > +     /* Backing stores */
> > +     struct bnge_ctx_mem_info        *ctx;
> > +
> > +     u64                     flags;
> >   };
> >
> > +static inline bool bnge_is_roce_en(struct bnge_dev *bd)
> > +{
> > +     return bd->flags & BNGE_EN_ROCE;
> > +}
> > +
> >   #endif /* _BNGE_H_ */
> > diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
> > index 567376a407df..e5f32ac8a69f 100644
> > --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
> > +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
> > @@ -10,6 +10,7 @@
> >   #include "../bnxt/bnxt_hsi.h"
> >   #include "bnge_hwrm.h"
> >   #include "bnge_hwrm_lib.h"
> > +#include "bnge_rmem.h"
> >
> >   int bnge_hwrm_ver_get(struct bnge_dev *bd)
> >   {
> > @@ -211,3 +212,170 @@ int bnge_hwrm_func_drv_unrgtr(struct bnge_dev *bd)
> >               return rc;
> >       return hwrm_req_send(bd, req);
> >   }
> > +
> > +static void bnge_init_ctx_initializer(struct bnge_ctx_mem_type *ctxm,
> > +                                   u8 init_val, u8 init_offset,
> > +                                   bool init_mask_set)
> > +{
> > +     ctxm->init_value = init_val;
> > +     ctxm->init_offset = BNGE_CTX_INIT_INVALID_OFFSET;
> > +     if (init_mask_set)
> > +             ctxm->init_offset = init_offset * 4;
> > +     else
> > +             ctxm->init_value = 0;
> > +}
> > +
> > +static int bnge_alloc_all_ctx_pg_info(struct bnge_dev *bd, int ctx_max)
> > +{
> > +     struct bnge_ctx_mem_info *ctx = bd->ctx;
> > +     u16 type;
> > +
> > +     for (type = 0; type < ctx_max; type++) {
> > +             struct bnge_ctx_mem_type *ctxm = &ctx->ctx_arr[type];
> > +             int n = 1;
> > +
> > +             if (!ctxm->max_entries)
> > +                     continue;
> > +
> > +             if (ctxm->instance_bmap)
> > +                     n = hweight32(ctxm->instance_bmap);
> > +             ctxm->pg_info = kcalloc(n, sizeof(*ctxm->pg_info), GFP_KERNEL);
> > +             if (!ctxm->pg_info)
> > +                     return -ENOMEM;
>
> It's a bit hard to be absolutely sure without full chain of calls, but
> it looks like some of the memory can be leaked in case of allocation
> fail. Direct callers do not clear allocated contextes in the error path.

After the allocation of context memory, it could be in use by the
hardware, so it is always safer
to clean it up when we finally deregister from the firmware. The
bnge_fw_unregister_dev() function
handles memory freeing via bnge_free_ctx_mem(), instead of freeing up by caller.
I hope this clarifies your concern.

>
> > +     }
> > +
> > +     return 0;
> > +}
> > +

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4193 bytes --]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 07/10] bng_en: Add resource management support
  2025-06-19 13:39   ` Vadim Fedorenko
@ 2025-06-24 10:31     ` Vikas Gupta
  0 siblings, 0 replies; 37+ messages in thread
From: Vikas Gupta @ 2025-06-24 10:31 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: davem, edumazet, kuba, pabeni, andrew+netdev, horms, netdev,
	linux-kernel, michael.chan, pavan.chebbi, vsrama-krishna.nemani,
	Bhargava Chenna Marreddy, Rajashekar Hudumula

[-- Attachment #1: Type: text/plain, Size: 2208 bytes --]

On Thu, Jun 19, 2025 at 7:09 PM Vadim Fedorenko
<vadim.fedorenko@linux.dev> wrote:
>
> On 18/06/2025 15:47, Vikas Gupta wrote:
> > Get the resources and capabilities from the firmware.
> > Add functions to manage the resources with the firmware.
> > These functions will help netdev reserve the resources
> > with the firmware before registering the device in future
> > patches. The resources and their information, such as
> > the maximum available and reserved, are part of the members
> > present in the bnge_hw_resc struct.
> > The bnge_reserve_rings() function also populates
> > the RSS table entries once the RX rings are reserved with
> > the firmware.
> >
>
> [...]
>
> > diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h
> > index c14f03daab4b..9dd13c5219a5 100644
> > --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h
> > +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h
> > @@ -104,4 +104,14 @@ void hwrm_req_alloc_flags(struct bnge_dev *bd, void *req, gfp_t flags);
> >   void *hwrm_req_dma_slice(struct bnge_dev *bd, void *req, u32 size,
> >                        dma_addr_t *dma);
> >
> > +static inline int
> > +bnge_hwrm_func_cfg_short_req_init(struct bnge_dev *bdev,
> > +                               struct hwrm_func_cfg_input **req)
> > +{
> > +     u32 req_len;
> > +
> > +     req_len = min_t(u32, sizeof(**req), bdev->hwrm_max_ext_req_len);
> > +     return __hwrm_req_init(bdev, (void **)req, HWRM_FUNC_CFG, req_len);
> > +}
> > +
>
> Could you please explain how does this suppose to work? If the size of
> request will be bigger than the max request length, the HWRM request
> will be prepared with smaller size and then partially transferred to FW?

Thanks for pointing that out. After checking the firmware code, I
understand that
 bnge_hwrm_func_cfg_short_req_init() is not required. I’ll consider
removing this function in v2.
However, to explain your comment, this was aligned with the firmware's
behaviour.
if hwrm_max_ext_req_len is less than the command length, then only a few members
 are accessed by the firmware.


Thanks,
Vikas

>
> [...]

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4193 bytes --]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 04/10] bng_en: Add initial interaction with firmware
  2025-06-24 10:26     ` Vikas Gupta
@ 2025-06-24 12:11       ` Vadim Fedorenko
  2025-06-25  9:29         ` Vikas Gupta
  0 siblings, 1 reply; 37+ messages in thread
From: Vadim Fedorenko @ 2025-06-24 12:11 UTC (permalink / raw)
  To: Vikas Gupta
  Cc: davem, edumazet, kuba, pabeni, andrew+netdev, horms, netdev,
	linux-kernel, michael.chan, pavan.chebbi, vsrama-krishna.nemani,
	Bhargava Chenna Marreddy, Rajashekar Hudumula

On 24/06/2025 11:26, Vikas Gupta wrote:
> On Thu, Jun 19, 2025 at 6:23 PM Vadim Fedorenko
> <vadim.fedorenko@linux.dev> wrote:
>>
>> On 18/06/2025 15:47, Vikas Gupta wrote:
>>> Query firmware with the help of basic firmware commands and
>>> cache the capabilities. With the help of basic commands
>>> start the initialization process of the driver with the
>>> firmware.
>>> Since basic information is available from the firmware,
>>> add that information to the devlink info get command.
>>>
>>> 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>
>>> ---
>>>    drivers/net/ethernet/broadcom/bnge/Makefile   |   3 +-
>>>    drivers/net/ethernet/broadcom/bnge/bnge.h     |  54 +++++
>>>    .../net/ethernet/broadcom/bnge/bnge_core.c    |  67 ++++++
>>>    .../net/ethernet/broadcom/bnge/bnge_devlink.c | 120 ++++++++++
>>>    .../ethernet/broadcom/bnge/bnge_hwrm_lib.c    | 213 ++++++++++++++++++
>>>    .../ethernet/broadcom/bnge/bnge_hwrm_lib.h    |  16 ++
>>>    6 files changed, 472 insertions(+), 1 deletion(-)
>>>    create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
>>>    create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
>>>
>>> diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethernet/broadcom/bnge/Makefile
>>> index b296d7de56ce..b8dbbc2d5972 100644
>>> --- a/drivers/net/ethernet/broadcom/bnge/Makefile
>>> +++ b/drivers/net/ethernet/broadcom/bnge/Makefile
>>> @@ -4,4 +4,5 @@ obj-$(CONFIG_BNGE) += bng_en.o
>>>
>>>    bng_en-y := bnge_core.o \
>>>            bnge_devlink.o \
>>> -         bnge_hwrm.o
>>> +         bnge_hwrm.o \
>>> +         bnge_hwrm_lib.o
>>> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
>>> index 8f2a562d9ae2..60af0517c45e 100644
>>> --- a/drivers/net/ethernet/broadcom/bnge/bnge.h
>>> +++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
>>> @@ -7,6 +7,13 @@
>>>    #define DRV_NAME    "bng_en"
>>>    #define DRV_SUMMARY "Broadcom 800G Ethernet Linux Driver"
>>>
>>> +#include <linux/etherdevice.h>
>>> +#include "../bnxt/bnxt_hsi.h"
>>> +
>>> +#define DRV_VER_MAJ  1
>>> +#define DRV_VER_MIN  15
>>> +#define DRV_VER_UPD  1
>>> +
>>>    extern char bnge_driver_name[];
>>>
>>>    enum board_idx {
>>> @@ -15,6 +22,36 @@ enum board_idx {
>>>
>>>    #define INVALID_HW_RING_ID      ((u16)-1)
>>>
>>> +enum {
>>> +     BNGE_FW_CAP_SHORT_CMD                           = BIT_ULL(0),
>>> +     BNGE_FW_CAP_LLDP_AGENT                          = BIT_ULL(1),
>>> +     BNGE_FW_CAP_DCBX_AGENT                          = BIT_ULL(2),
>>> +     BNGE_FW_CAP_IF_CHANGE                           = BIT_ULL(3),
>>> +     BNGE_FW_CAP_KONG_MB_CHNL                        = BIT_ULL(4),
>>> +     BNGE_FW_CAP_ERROR_RECOVERY                      = BIT_ULL(5),
>>> +     BNGE_FW_CAP_PKG_VER                             = BIT_ULL(6),
>>> +     BNGE_FW_CAP_CFA_ADV_FLOW                        = BIT_ULL(7),
>>> +     BNGE_FW_CAP_CFA_RFS_RING_TBL_IDX_V2             = BIT_ULL(8),
>>> +     BNGE_FW_CAP_PCIE_STATS_SUPPORTED                = BIT_ULL(9),
>>> +     BNGE_FW_CAP_EXT_STATS_SUPPORTED                 = BIT_ULL(10),
>>> +     BNGE_FW_CAP_ERR_RECOVER_RELOAD                  = BIT_ULL(11),
>>> +     BNGE_FW_CAP_HOT_RESET                           = BIT_ULL(12),
>>> +     BNGE_FW_CAP_RX_ALL_PKT_TS                       = BIT_ULL(13),
>>> +     BNGE_FW_CAP_VLAN_RX_STRIP                       = BIT_ULL(14),
>>> +     BNGE_FW_CAP_VLAN_TX_INSERT                      = BIT_ULL(15),
>>> +     BNGE_FW_CAP_EXT_HW_STATS_SUPPORTED              = BIT_ULL(16),
>>> +     BNGE_FW_CAP_LIVEPATCH                           = BIT_ULL(17),
>>> +     BNGE_FW_CAP_HOT_RESET_IF                        = BIT_ULL(18),
>>> +     BNGE_FW_CAP_RING_MONITOR                        = BIT_ULL(19),
>>> +     BNGE_FW_CAP_DBG_QCAPS                           = BIT_ULL(20),
>>> +     BNGE_FW_CAP_THRESHOLD_TEMP_SUPPORTED            = BIT_ULL(21),
>>> +     BNGE_FW_CAP_DFLT_VLAN_TPID_PCP                  = BIT_ULL(22),
>>> +     BNGE_FW_CAP_VNIC_TUNNEL_TPA                     = BIT_ULL(23),
>>> +     BNGE_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO          = BIT_ULL(24),
>>> +     BNGE_FW_CAP_CFA_RFS_RING_TBL_IDX_V3             = BIT_ULL(25),
>>> +     BNGE_FW_CAP_VNIC_RE_FLUSH                       = BIT_ULL(26),
>>> +};
>>> +
>>>    struct bnge_dev {
>>>        struct device   *dev;
>>>        struct pci_dev  *pdev;
>>> @@ -25,6 +62,9 @@ struct bnge_dev {
>>>
>>>        void __iomem    *bar0;
>>>
>>> +     u16             chip_num;
>>> +     u8              chip_rev;
>>> +
>>>        /* HWRM members */
>>>        u16                     hwrm_cmd_seq;
>>>        u16                     hwrm_cmd_kong_seq;
>>> @@ -35,6 +75,20 @@ struct bnge_dev {
>>>        unsigned int            hwrm_cmd_timeout;
>>>        unsigned int            hwrm_cmd_max_timeout;
>>>        struct mutex            hwrm_cmd_lock;  /* serialize hwrm messages */
>>> +
>>> +     struct hwrm_ver_get_output      ver_resp;
>>> +#define FW_VER_STR_LEN               32
>>> +     char                    fw_ver_str[FW_VER_STR_LEN];
>>> +     char                    hwrm_ver_supp[FW_VER_STR_LEN];
>>> +     char                    nvm_cfg_ver[FW_VER_STR_LEN];
>>> +     u64                     fw_ver_code;
>>> +#define BNGE_FW_VER_CODE(maj, min, bld, rsv)                 \
>>> +     ((u64)(maj) << 48 | (u64)(min) << 32 | (u64)(bld) << 16 | (rsv))
>>> +
>>> +     unsigned long           state;
>>> +#define BNGE_STATE_DRV_REGISTERED      0
>>> +
>>> +     u64                     fw_cap;
>>>    };
>>>
>>>    #endif /* _BNGE_H_ */
>>> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_core.c b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
>>> index 1a46c7663012..5e23eb14f60e 100644
>>> --- a/drivers/net/ethernet/broadcom/bnge/bnge_core.c
>>> +++ b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
>>> @@ -8,6 +8,8 @@
>>>
>>>    #include "bnge.h"
>>>    #include "bnge_devlink.h"
>>> +#include "bnge_hwrm.h"
>>> +#include "bnge_hwrm_lib.h"
>>>
>>>    MODULE_LICENSE("GPL");
>>>    MODULE_DESCRIPTION(DRV_SUMMARY);
>>> @@ -37,6 +39,51 @@ static void bnge_print_device_info(struct pci_dev *pdev, enum board_idx idx)
>>>        pcie_print_link_status(pdev);
>>>    }
>>>
>>> +static void bnge_nvm_cfg_ver_get(struct bnge_dev *bd)
>>> +{
>>> +     struct hwrm_nvm_get_dev_info_output nvm_info;
>>> +
>>> +     if (!bnge_hwrm_nvm_dev_info(bd, &nvm_info))
>>> +             snprintf(bd->nvm_cfg_ver, FW_VER_STR_LEN, "%d.%d.%d",
>>> +                      nvm_info.nvm_cfg_ver_maj, nvm_info.nvm_cfg_ver_min,
>>> +                      nvm_info.nvm_cfg_ver_upd);
>>> +}
>>> +
>>> +static void bnge_fw_unregister_dev(struct bnge_dev *bd)
>>> +{
>>> +     bnge_hwrm_func_drv_unrgtr(bd);
>>> +}
>>> +
>>> +static int bnge_fw_register_dev(struct bnge_dev *bd)
>>> +{
>>> +     int rc;
>>> +
>>> +     bd->fw_cap = 0;
>>> +     rc = bnge_hwrm_ver_get(bd);
>>> +     if (rc) {
>>> +             dev_err(bd->dev, "Get Version command failed rc: %d\n", rc);
>>> +             return rc;
>>> +     }
>>> +
>>> +     bnge_nvm_cfg_ver_get(bd);
>>> +
>>> +     rc = bnge_hwrm_func_reset(bd);
>>> +     if (rc) {
>>> +             dev_err(bd->dev, "Failed to reset function rc: %d\n", rc);
>>> +             return rc;
>>> +     }
>>> +
>>> +     bnge_hwrm_fw_set_time(bd);
>>> +
>>> +     rc =  bnge_hwrm_func_drv_rgtr(bd);
>>> +     if (rc) {
>>> +             dev_err(bd->dev, "Failed to rgtr with firmware rc: %d\n", rc);
>>> +             return rc;
>>> +     }
>>> +
>>> +     return 0;
>>> +}
>>> +
>>>    static void bnge_pci_disable(struct pci_dev *pdev)
>>>    {
>>>        pci_release_regions(pdev);
>>> @@ -136,10 +183,26 @@ static int bnge_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>>>                goto err_devl_unreg;
>>>        }
>>>
>>> +     rc = bnge_init_hwrm_resources(bd);
>>> +     if (rc)
>>> +             goto err_bar_unmap;
>>> +
>>> +     rc = bnge_fw_register_dev(bd);
>>> +     if (rc) {
>>> +             dev_err(&pdev->dev, "Failed to register with firmware rc = %d\n", rc);
>>> +             goto err_hwrm_cleanup;
>>> +     }
>>> +
>>>        pci_save_state(pdev);
>>>
>>>        return 0;
>>>
>>> +err_hwrm_cleanup:
>>> +     bnge_cleanup_hwrm_resources(bd);
>>> +
>>> +err_bar_unmap:
>>> +     bnge_unmap_bars(pdev);
>>> +
>>>    err_devl_unreg:
>>>        bnge_devlink_unregister(bd);
>>>        bnge_devlink_free(bd);
>>> @@ -153,6 +216,10 @@ static void bnge_remove_one(struct pci_dev *pdev)
>>>    {
>>>        struct bnge_dev *bd = pci_get_drvdata(pdev);
>>>
>>> +     bnge_fw_unregister_dev(bd);
>>> +
>>> +     bnge_cleanup_hwrm_resources(bd);
>>> +
>>>        bnge_unmap_bars(pdev);
>>>
>>>        bnge_devlink_unregister(bd);
>>> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
>>> index d406338da130..f987d35beea2 100644
>>> --- a/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
>>> +++ b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c
>>> @@ -8,6 +8,7 @@
>>>
>>>    #include "bnge.h"
>>>    #include "bnge_devlink.h"
>>> +#include "bnge_hwrm_lib.h"
>>>
>>>    static int bnge_dl_info_put(struct bnge_dev *bd, struct devlink_info_req *req,
>>>                            enum bnge_dl_version_type type, const char *key,
>>> @@ -16,6 +17,10 @@ static int bnge_dl_info_put(struct bnge_dev *bd, struct devlink_info_req *req,
>>>        if (!strlen(buf))
>>>                return 0;
>>>
>>> +     if (!strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_NCSI) ||
>>> +         !strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_ROCE))
>>> +             return 0;
>>> +
>>>        switch (type) {
>>>        case BNGE_VERSION_FIXED:
>>>                return devlink_info_version_fixed_put(req, key, buf);
>>> @@ -63,11 +68,20 @@ static void bnge_vpd_read_info(struct bnge_dev *bd)
>>>        kfree(vpd_data);
>>>    }
>>>
>>> +#define HWRM_FW_VER_STR_LEN  16
>>> +
>>>    static int bnge_devlink_info_get(struct devlink *devlink,
>>>                                 struct devlink_info_req *req,
>>>                                 struct netlink_ext_ack *extack)
>>>    {
>>> +     struct hwrm_nvm_get_dev_info_output nvm_dev_info;
>>>        struct bnge_dev *bd = devlink_priv(devlink);
>>> +     struct hwrm_ver_get_output *ver_resp;
>>> +     char mgmt_ver[FW_VER_STR_LEN];
>>> +     char roce_ver[FW_VER_STR_LEN];
>>> +     char ncsi_ver[FW_VER_STR_LEN];
>>> +     char buf[32];
>>> +
>>>        int rc;
>>>
>>>        if (bd->dsn) {
>>> @@ -95,6 +109,112 @@ static int bnge_devlink_info_get(struct devlink *devlink,
>>>                              DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
>>>                              bd->board_partno);
>>>
>>> +     /* More information from HWRM ver get command */
>>> +     sprintf(buf, "%X", bd->chip_num);
>>> +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_FIXED,
>>> +                           DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, buf);
>>> +     if (rc)
>>> +             return rc;
>>> +
>>> +     ver_resp = &bd->ver_resp;
>>> +     sprintf(buf, "%c%d", 'A' + ver_resp->chip_rev, ver_resp->chip_metal);
>>> +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_FIXED,
>>> +                           DEVLINK_INFO_VERSION_GENERIC_ASIC_REV, buf);
>>> +     if (rc)
>>> +             return rc;
>>> +
>>> +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
>>> +                           DEVLINK_INFO_VERSION_GENERIC_FW_PSID,
>>> +                           bd->nvm_cfg_ver);
>>> +     if (rc)
>>> +             return rc;
>>> +
>>> +     buf[0] = 0;
>>> +     strncat(buf, ver_resp->active_pkg_name, HWRM_FW_VER_STR_LEN);
>>> +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
>>> +                           DEVLINK_INFO_VERSION_GENERIC_FW, buf);
>>> +     if (rc)
>>> +             return rc;
>>> +
>>> +     if (ver_resp->flags & VER_GET_RESP_FLAGS_EXT_VER_AVAIL) {
>>> +             snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
>>> +                      ver_resp->hwrm_fw_major, ver_resp->hwrm_fw_minor,
>>> +                      ver_resp->hwrm_fw_build, ver_resp->hwrm_fw_patch);
>>> +
>>> +             snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
>>> +                      ver_resp->mgmt_fw_major, ver_resp->mgmt_fw_minor,
>>> +                      ver_resp->mgmt_fw_build, ver_resp->mgmt_fw_patch);
>>> +
>>> +             snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
>>> +                      ver_resp->roce_fw_major, ver_resp->roce_fw_minor,
>>> +                      ver_resp->roce_fw_build, ver_resp->roce_fw_patch);
>>> +     } else {
>>> +             snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
>>> +                      ver_resp->hwrm_fw_maj_8b, ver_resp->hwrm_fw_min_8b,
>>> +                      ver_resp->hwrm_fw_bld_8b, ver_resp->hwrm_fw_rsvd_8b);
>>> +
>>> +             snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
>>> +                      ver_resp->mgmt_fw_maj_8b, ver_resp->mgmt_fw_min_8b,
>>> +                      ver_resp->mgmt_fw_bld_8b, ver_resp->mgmt_fw_rsvd_8b);
>>> +
>>> +             snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
>>> +                      ver_resp->roce_fw_maj_8b, ver_resp->roce_fw_min_8b,
>>> +                      ver_resp->roce_fw_bld_8b, ver_resp->roce_fw_rsvd_8b);
>>> +     }
>>> +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
>>> +                           DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
>>> +     if (rc)
>>> +             return rc;
>>> +
>>> +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
>>> +                           DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API,
>>> +                           bd->hwrm_ver_supp);
>>> +     if (rc)
>>> +             return rc;
>>> +
>>> +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
>>> +                           DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver);
>>> +     if (rc)
>>> +             return rc;
>>> +
>>> +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
>>> +                           DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver);
>>> +     if (rc)
>>> +             return rc;
>>> +
>>> +     rc = bnge_hwrm_nvm_dev_info(bd, &nvm_dev_info);
>>> +     if (!(nvm_dev_info.flags & NVM_GET_DEV_INFO_RESP_FLAGS_FW_VER_VALID))
>>> +             return 0;
>>> +
>>> +     buf[0] = 0;
>>> +     strncat(buf, nvm_dev_info.pkg_name, HWRM_FW_VER_STR_LEN);
>>> +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
>>> +                           DEVLINK_INFO_VERSION_GENERIC_FW, buf);
>>> +     if (rc)
>>> +             return rc;
>>> +
>>> +     snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
>>> +              nvm_dev_info.hwrm_fw_major, nvm_dev_info.hwrm_fw_minor,
>>> +              nvm_dev_info.hwrm_fw_build, nvm_dev_info.hwrm_fw_patch);
>>> +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
>>> +                           DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
>>> +     if (rc)
>>> +             return rc;
>>> +
>>> +     snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
>>> +              nvm_dev_info.mgmt_fw_major, nvm_dev_info.mgmt_fw_minor,
>>> +              nvm_dev_info.mgmt_fw_build, nvm_dev_info.mgmt_fw_patch);
>>> +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
>>> +                           DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver);
>>> +     if (rc)
>>> +             return rc;
>>> +
>>> +     snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
>>> +              nvm_dev_info.roce_fw_major, nvm_dev_info.roce_fw_minor,
>>> +              nvm_dev_info.roce_fw_build, nvm_dev_info.roce_fw_patch);
>>> +     rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
>>> +                           DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver);
>>> +
>>>        return rc;
>>>    }
>>>
>>> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
>>> new file mode 100644
>>> index 000000000000..567376a407df
>>> --- /dev/null
>>> +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
>>> @@ -0,0 +1,213 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +// Copyright (c) 2025 Broadcom.
>>> +
>>> +#include <linux/errno.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/mm.h>
>>> +#include <linux/pci.h>
>>> +
>>> +#include "bnge.h"
>>> +#include "../bnxt/bnxt_hsi.h"
>>> +#include "bnge_hwrm.h"
>>> +#include "bnge_hwrm_lib.h"
>>> +
>>> +int bnge_hwrm_ver_get(struct bnge_dev *bd)
>>> +{
>>> +     u32 dev_caps_cfg, hwrm_ver, hwrm_spec_code;
>>> +     u16 fw_maj, fw_min, fw_bld, fw_rsv;
>>> +     struct hwrm_ver_get_output *resp;
>>> +     struct hwrm_ver_get_input *req;
>>> +     int rc;
>>> +
>>> +     rc = hwrm_req_init(bd, req, HWRM_VER_GET);
>>> +     if (rc)
>>> +             return rc;
>>> +
>>> +     hwrm_req_flags(bd, req, BNGE_HWRM_FULL_WAIT);
>>> +     bd->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
>>> +     req->hwrm_intf_maj = HWRM_VERSION_MAJOR;
>>> +     req->hwrm_intf_min = HWRM_VERSION_MINOR;
>>> +     req->hwrm_intf_upd = HWRM_VERSION_UPDATE;
>>> +
>>> +     resp = hwrm_req_hold(bd, req);
>>> +     rc = hwrm_req_send(bd, req);
>>> +     if (rc)
>>> +             goto hwrm_ver_get_exit;
>>> +
>>> +     memcpy(&bd->ver_resp, resp, sizeof(struct hwrm_ver_get_output));
>>> +
>>> +     hwrm_spec_code = resp->hwrm_intf_maj_8b << 16 |
>>> +                      resp->hwrm_intf_min_8b << 8 |
>>> +                      resp->hwrm_intf_upd_8b;
>>> +     hwrm_ver = HWRM_VERSION_MAJOR << 16 | HWRM_VERSION_MINOR << 8 |
>>> +                     HWRM_VERSION_UPDATE;
>>> +
>>> +     if (hwrm_spec_code > hwrm_ver)
>>> +             snprintf(bd->hwrm_ver_supp, FW_VER_STR_LEN, "%d.%d.%d",
>>> +                      HWRM_VERSION_MAJOR, HWRM_VERSION_MINOR,
>>> +                      HWRM_VERSION_UPDATE);
>>> +     else
>>> +             snprintf(bd->hwrm_ver_supp, FW_VER_STR_LEN, "%d.%d.%d",
>>> +                      resp->hwrm_intf_maj_8b, resp->hwrm_intf_min_8b,
>>> +                      resp->hwrm_intf_upd_8b);
>>> +
>>> +     fw_maj = le16_to_cpu(resp->hwrm_fw_major);
>>> +     fw_min = le16_to_cpu(resp->hwrm_fw_minor);
>>> +     fw_bld = le16_to_cpu(resp->hwrm_fw_build);
>>> +     fw_rsv = le16_to_cpu(resp->hwrm_fw_patch);
>>> +
>>> +     bd->fw_ver_code = BNGE_FW_VER_CODE(fw_maj, fw_min, fw_bld, fw_rsv);
>>> +     snprintf(bd->fw_ver_str, FW_VER_STR_LEN, "%d.%d.%d.%d",
>>> +              fw_maj, fw_min, fw_bld, fw_rsv);
>>> +
>>> +     if (strlen(resp->active_pkg_name)) {
>>> +             int fw_ver_len = strlen(bd->fw_ver_str);
>>> +
>>> +             snprintf(bd->fw_ver_str + fw_ver_len,
>>> +                      FW_VER_STR_LEN - fw_ver_len - 1, "/pkg %s",
>>> +                      resp->active_pkg_name);
>>> +             bd->fw_cap |= BNGE_FW_CAP_PKG_VER;
>>> +     }
>>> +
>>> +     bd->hwrm_cmd_timeout = le16_to_cpu(resp->def_req_timeout);
>>> +     if (!bd->hwrm_cmd_timeout)
>>> +             bd->hwrm_cmd_timeout = DFLT_HWRM_CMD_TIMEOUT;
>>> +     bd->hwrm_cmd_max_timeout = le16_to_cpu(resp->max_req_timeout) * 1000;
>>> +     if (!bd->hwrm_cmd_max_timeout)
>>> +             bd->hwrm_cmd_max_timeout = HWRM_CMD_MAX_TIMEOUT;
>>> +     else if (bd->hwrm_cmd_max_timeout > HWRM_CMD_MAX_TIMEOUT)
>>> +                     dev_warn(bd->dev, "Default HWRM commands max timeout increased to %d seconds\n",
>>> +                              bd->hwrm_cmd_max_timeout / 1000);
>>> +
>>> +     bd->hwrm_max_req_len = le16_to_cpu(resp->max_req_win_len);
>>> +     bd->hwrm_max_ext_req_len = le16_to_cpu(resp->max_ext_req_len);
>>> +
>>> +     if (bd->hwrm_max_ext_req_len < HWRM_MAX_REQ_LEN)
>>> +             bd->hwrm_max_ext_req_len = HWRM_MAX_REQ_LEN;
>>> +
>>> +     bd->chip_num = le16_to_cpu(resp->chip_num);
>>> +     bd->chip_rev = resp->chip_rev;
>>> +
>>> +     dev_caps_cfg = le32_to_cpu(resp->dev_caps_cfg);
>>> +     if ((dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
>>> +         (dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
>>> +             bd->fw_cap |= BNGE_FW_CAP_SHORT_CMD;
>>> +
>>> +     if (dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_KONG_MB_CHNL_SUPPORTED)
>>> +             bd->fw_cap |= BNGE_FW_CAP_KONG_MB_CHNL;
>>> +
>>> +     if (dev_caps_cfg &
>>> +         VER_GET_RESP_DEV_CAPS_CFG_CFA_ADV_FLOW_MGNT_SUPPORTED)
>>> +             bd->fw_cap |= BNGE_FW_CAP_CFA_ADV_FLOW;
>>> +
>>> +hwrm_ver_get_exit:
>>> +     hwrm_req_drop(bd, req);
>>> +     return rc;
>>> +}
>>> +
>>> +int
>>> +bnge_hwrm_nvm_dev_info(struct bnge_dev *bd,
>>> +                    struct hwrm_nvm_get_dev_info_output *nvm_info)
>>> +{
>>> +     struct hwrm_nvm_get_dev_info_output *resp;
>>> +     struct hwrm_nvm_get_dev_info_input *req;
>>> +     int rc;
>>> +
>>> +     rc = hwrm_req_init(bd, req, HWRM_NVM_GET_DEV_INFO);
>>> +     if (rc)
>>> +             return rc;
>>> +
>>> +     resp = hwrm_req_hold(bd, req);
>>> +     rc = hwrm_req_send(bd, req);
>>> +     if (!rc)
>>> +             memcpy(nvm_info, resp, sizeof(*resp));
>>> +     hwrm_req_drop(bd, req);
>>> +     return rc;
>>> +}
>>> +
>>> +int bnge_hwrm_func_reset(struct bnge_dev *bd)
>>> +{
>>> +     struct hwrm_func_reset_input *req;
>>> +     int rc;
>>> +
>>> +     rc = hwrm_req_init(bd, req, HWRM_FUNC_RESET);
>>> +     if (rc)
>>> +             return rc;
>>> +
>>> +     req->enables = 0;
>>> +     hwrm_req_timeout(bd, req, HWRM_RESET_TIMEOUT);
>>> +     return hwrm_req_send(bd, req);
>>> +}
>>> +
>>> +int bnge_hwrm_fw_set_time(struct bnge_dev *bd)
>>> +{
>>> +     struct hwrm_fw_set_time_input *req;
>>> +     struct tm tm;
>>> +     time64_t now = ktime_get_real_seconds();
>>> +     int rc;
>>
>> Reverse xmass tree, please. Not quite sure you need this 'now'
>> variable at all. You can use ktime_get_real_seconds() directly
>> in time64_to_tm() - there are examples of such code in the kernel.
> 
>   Will fix it in v2.
> 
>>
>>> +
>>> +     time64_to_tm(now, 0, &tm);
>>> +     rc = hwrm_req_init(bd, req, HWRM_FW_SET_TIME);
>>> +     if (rc)
>>> +             return rc;
>>> +
>>> +     req->year = cpu_to_le16(1900 + tm.tm_year);
>>> +     req->month = 1 + tm.tm_mon;
>>> +     req->day = tm.tm_mday;
>>> +     req->hour = tm.tm_hour;
>>> +     req->minute = tm.tm_min;
>>> +     req->second = tm.tm_sec;
>>> +     return hwrm_req_send(bd, req);
>>> +}
>>
>> This whole function looks like copy-paste from bnxt, did you consider
>> merging these parts?
> 
> Both the bnxt and bnge drivers follow the same protocol to send the
> requests to  the firmware,
> so some functions may appear similar. However, we do not plan to share
> the code, as certain
>   fundamental data structures will differ.

But at the same time some data structures are completely the same. Why
do you think code duplication will work better on long run?

> 
>>
>>
>>> +
>>> +int bnge_hwrm_func_drv_rgtr(struct bnge_dev *bd)
>>> +{
>>> +     struct hwrm_func_drv_rgtr_output *resp;
>>> +     struct hwrm_func_drv_rgtr_input *req;
>>> +     u32 flags;
>>> +     int rc;
>>> +
>>> +     rc = hwrm_req_init(bd, req, HWRM_FUNC_DRV_RGTR);
>>> +     if (rc)
>>> +             return rc;
>>> +
>>> +     req->enables = cpu_to_le32(FUNC_DRV_RGTR_REQ_ENABLES_OS_TYPE |
>>> +                                FUNC_DRV_RGTR_REQ_ENABLES_VER |
>>> +                                FUNC_DRV_RGTR_REQ_ENABLES_ASYNC_EVENT_FWD);
>>> +
>>> +     req->os_type = cpu_to_le16(FUNC_DRV_RGTR_REQ_OS_TYPE_LINUX);
>>> +     flags = FUNC_DRV_RGTR_REQ_FLAGS_16BIT_VER_MODE;
>>> +
>>> +     req->flags = cpu_to_le32(flags);
>>> +     req->ver_maj_8b = DRV_VER_MAJ;
>>> +     req->ver_min_8b = DRV_VER_MIN;
>>> +     req->ver_upd_8b = DRV_VER_UPD;
>>> +     req->ver_maj = cpu_to_le16(DRV_VER_MAJ);
>>> +     req->ver_min = cpu_to_le16(DRV_VER_MIN);
>>> +     req->ver_upd = cpu_to_le16(DRV_VER_UPD);
>>> +
>>> +     resp = hwrm_req_hold(bd, req);
>>> +     rc = hwrm_req_send(bd, req);
>>> +     if (!rc) {
>>> +             set_bit(BNGE_STATE_DRV_REGISTERED, &bd->state);
>>> +             if (resp->flags &
>>> +                 cpu_to_le32(FUNC_DRV_RGTR_RESP_FLAGS_IF_CHANGE_SUPPORTED))
>>> +                     bd->fw_cap |= BNGE_FW_CAP_IF_CHANGE;
>>> +     }
>>> +     hwrm_req_drop(bd, req);
>>> +     return rc;
>>> +}
>>> +
>>> +int bnge_hwrm_func_drv_unrgtr(struct bnge_dev *bd)
>>> +{
>>> +     struct hwrm_func_drv_unrgtr_input *req;
>>> +     int rc;
>>> +
>>> +     if (!test_and_clear_bit(BNGE_STATE_DRV_REGISTERED, &bd->state))
>>> +             return 0;
>>> +
>>> +     rc = hwrm_req_init(bd, req, HWRM_FUNC_DRV_UNRGTR);
>>> +     if (rc)
>>> +             return rc;
>>> +     return hwrm_req_send(bd, req);
>>> +}
>>> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
>>> new file mode 100644
>>> index 000000000000..9308d4fe64d2
>>> --- /dev/null
>>> +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
>>> @@ -0,0 +1,16 @@
>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>> +/* Copyright (c) 2025 Broadcom */
>>> +
>>> +#ifndef _BNGE_HWRM_LIB_H_
>>> +#define _BNGE_HWRM_LIB_H_
>>> +
>>> +int bnge_hwrm_ver_get(struct bnge_dev *bd);
>>> +int bnge_hwrm_func_reset(struct bnge_dev *bd);
>>> +int bnge_hwrm_fw_set_time(struct bnge_dev *bd);
>>> +int bnge_hwrm_func_drv_rgtr(struct bnge_dev *bd);
>>> +int bnge_hwrm_func_drv_unrgtr(struct bnge_dev *bd);
>>> +int bnge_hwrm_vnic_qcaps(struct bnge_dev *bd);
>>> +int bnge_hwrm_nvm_dev_info(struct bnge_dev *bd,
>>> +                        struct hwrm_nvm_get_dev_info_output *nvm_dev_info);
>>> +
>>> +#endif /* _BNGE_HWRM_LIB_H_ */
>>


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 06/10] bng_en: Add backing store support
  2025-06-24 10:29     ` Vikas Gupta
@ 2025-06-24 12:12       ` Vadim Fedorenko
  0 siblings, 0 replies; 37+ messages in thread
From: Vadim Fedorenko @ 2025-06-24 12:12 UTC (permalink / raw)
  To: Vikas Gupta
  Cc: davem, edumazet, kuba, pabeni, andrew+netdev, horms, netdev,
	linux-kernel, michael.chan, pavan.chebbi, vsrama-krishna.nemani,
	Bhargava Chenna Marreddy, Rajashekar Hudumula

On 24/06/2025 11:29, Vikas Gupta wrote:
> On Thu, Jun 19, 2025 at 6:32 PM Vadim Fedorenko
> <vadim.fedorenko@linux.dev> wrote:
>>
>> On 18/06/2025 15:47, Vikas Gupta wrote:
>>> Backing store or context memory on the host helps the
>>> device to manage rings, stats and other resources.
>>> Context memory is allocated with the help of ring
>>> alloc/free functions.
>>>
>>> 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>
>>> ---
>>>    drivers/net/ethernet/broadcom/bnge/bnge.h     |  18 +
>>>    .../ethernet/broadcom/bnge/bnge_hwrm_lib.c    | 168 +++++++++
>>>    .../ethernet/broadcom/bnge/bnge_hwrm_lib.h    |   4 +
>>>    .../net/ethernet/broadcom/bnge/bnge_rmem.c    | 337 ++++++++++++++++++
>>>    .../net/ethernet/broadcom/bnge/bnge_rmem.h    | 153 ++++++++
>>>    5 files changed, 680 insertions(+)
>>>
>>> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
>>> index 60af0517c45e..01f64a10729c 100644
>>> --- a/drivers/net/ethernet/broadcom/bnge/bnge.h
>>> +++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
>>> @@ -9,6 +9,7 @@
>>>
>>>    #include <linux/etherdevice.h>
>>>    #include "../bnxt/bnxt_hsi.h"
>>> +#include "bnge_rmem.h"
>>>
>>>    #define DRV_VER_MAJ 1
>>>    #define DRV_VER_MIN 15
>>> @@ -52,6 +53,13 @@ enum {
>>>        BNGE_FW_CAP_VNIC_RE_FLUSH                       = BIT_ULL(26),
>>>    };
>>>
>>> +enum {
>>> +     BNGE_EN_ROCE_V1                                 = BIT_ULL(0),
>>> +     BNGE_EN_ROCE_V2                                 = BIT_ULL(1),
>>> +};
>>> +
>>> +#define BNGE_EN_ROCE         (BNGE_EN_ROCE_V1 | BNGE_EN_ROCE_V2)
>>> +
>>>    struct bnge_dev {
>>>        struct device   *dev;
>>>        struct pci_dev  *pdev;
>>> @@ -89,6 +97,16 @@ struct bnge_dev {
>>>    #define BNGE_STATE_DRV_REGISTERED      0
>>>
>>>        u64                     fw_cap;
>>> +
>>> +     /* Backing stores */
>>> +     struct bnge_ctx_mem_info        *ctx;
>>> +
>>> +     u64                     flags;
>>>    };
>>>
>>> +static inline bool bnge_is_roce_en(struct bnge_dev *bd)
>>> +{
>>> +     return bd->flags & BNGE_EN_ROCE;
>>> +}
>>> +
>>>    #endif /* _BNGE_H_ */
>>> diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
>>> index 567376a407df..e5f32ac8a69f 100644
>>> --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
>>> +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
>>> @@ -10,6 +10,7 @@
>>>    #include "../bnxt/bnxt_hsi.h"
>>>    #include "bnge_hwrm.h"
>>>    #include "bnge_hwrm_lib.h"
>>> +#include "bnge_rmem.h"
>>>
>>>    int bnge_hwrm_ver_get(struct bnge_dev *bd)
>>>    {
>>> @@ -211,3 +212,170 @@ int bnge_hwrm_func_drv_unrgtr(struct bnge_dev *bd)
>>>                return rc;
>>>        return hwrm_req_send(bd, req);
>>>    }
>>> +
>>> +static void bnge_init_ctx_initializer(struct bnge_ctx_mem_type *ctxm,
>>> +                                   u8 init_val, u8 init_offset,
>>> +                                   bool init_mask_set)
>>> +{
>>> +     ctxm->init_value = init_val;
>>> +     ctxm->init_offset = BNGE_CTX_INIT_INVALID_OFFSET;
>>> +     if (init_mask_set)
>>> +             ctxm->init_offset = init_offset * 4;
>>> +     else
>>> +             ctxm->init_value = 0;
>>> +}
>>> +
>>> +static int bnge_alloc_all_ctx_pg_info(struct bnge_dev *bd, int ctx_max)
>>> +{
>>> +     struct bnge_ctx_mem_info *ctx = bd->ctx;
>>> +     u16 type;
>>> +
>>> +     for (type = 0; type < ctx_max; type++) {
>>> +             struct bnge_ctx_mem_type *ctxm = &ctx->ctx_arr[type];
>>> +             int n = 1;
>>> +
>>> +             if (!ctxm->max_entries)
>>> +                     continue;
>>> +
>>> +             if (ctxm->instance_bmap)
>>> +                     n = hweight32(ctxm->instance_bmap);
>>> +             ctxm->pg_info = kcalloc(n, sizeof(*ctxm->pg_info), GFP_KERNEL);
>>> +             if (!ctxm->pg_info)
>>> +                     return -ENOMEM;
>>
>> It's a bit hard to be absolutely sure without full chain of calls, but
>> it looks like some of the memory can be leaked in case of allocation
>> fail. Direct callers do not clear allocated contextes in the error path.
> 
> After the allocation of context memory, it could be in use by the
> hardware, so it is always safer
> to clean it up when we finally deregister from the firmware. The
> bnge_fw_unregister_dev() function
> handles memory freeing via bnge_free_ctx_mem(), instead of freeing up by caller.
> I hope this clarifies your concern.

Yeah, I have found cleaning calls in the other patches, thanks

> 
>>
>>> +     }
>>> +
>>> +     return 0;
>>> +}
>>> +


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 08/10] bng_en: Add irq allocation support
  2025-06-18 14:47 ` [net-next, 08/10] bng_en: Add irq allocation support Vikas Gupta
                     ` (3 preceding siblings ...)
  2025-06-23  6:11   ` kernel test robot
@ 2025-06-25  9:17   ` kernel test robot
  4 siblings, 0 replies; 37+ messages in thread
From: kernel test robot @ 2025-06-25  9:17 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: oe-kbuild-all, netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Hi Vikas,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.16-rc3 next-20250624]
[cannot apply to horms-ipvs/master]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Vikas-Gupta/bng_en-Add-PCI-interface/20250618-173130
base:   linus/master
patch link:    https://lore.kernel.org/r/20250618144743.843815-9-vikas.gupta%40broadcom.com
patch subject: [net-next, 08/10] bng_en: Add irq allocation support
config: parisc-randconfig-r073-20250619 (https://download.01.org/0day-ci/archive/20250625/202506251636.aTzmB45K-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 8.5.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506251636.aTzmB45K-lkp@intel.com/

smatch warnings:
drivers/net/ethernet/broadcom/bnge/bnge_resc.c:347 bnge_alloc_irqs() warn: unsigned 'irqs_demand' is never less than zero.

vim +/irqs_demand +347 drivers/net/ethernet/broadcom/bnge/bnge_resc.c

   329	
   330	int bnge_alloc_irqs(struct bnge_dev *bd)
   331	{
   332		u16 aux_msix, tx_cp, num_entries;
   333		u16 irqs_demand, max, min = 1;
   334		int i, rc = 0;
   335	
   336		irqs_demand = bnge_nqs_demand(bd);
   337		max = bnge_get_max_func_irqs(bd);
   338		if (irqs_demand > max)
   339			irqs_demand = max;
   340	
   341		if (!(bd->flags & BNGE_EN_SHARED_CHNL))
   342			min = 2;
   343	
   344		irqs_demand = pci_alloc_irq_vectors(bd->pdev, min, irqs_demand,
   345						    PCI_IRQ_MSIX);
   346		aux_msix = bnge_aux_get_msix(bd);
 > 347		if (irqs_demand < 0 || irqs_demand < aux_msix) {
   348			rc = -ENODEV;
   349			goto err_free_irqs;
   350		}
   351	
   352		num_entries = irqs_demand;
   353		if (pci_msix_can_alloc_dyn(bd->pdev))
   354			num_entries = max;
   355		bd->irq_tbl = kcalloc(num_entries, sizeof(*bd->irq_tbl), GFP_KERNEL);
   356		if (!bd->irq_tbl) {
   357			rc = -ENOMEM;
   358			goto err_free_irqs;
   359		}
   360	
   361		for (i = 0; i < irqs_demand; i++)
   362			bd->irq_tbl[i].vector = pci_irq_vector(bd->pdev, i);
   363	
   364		bd->irqs_acquired = irqs_demand;
   365		/* Reduce rings based upon num of vectors allocated.
   366		 * We dont need to consider NQs as they have been calculated
   367		 * and must be more than irqs_demand.
   368		 */
   369		rc = bnge_adjust_rings(bd, &bd->rx_nr_rings,
   370				       &bd->tx_nr_rings,
   371				       irqs_demand - aux_msix, min == 1);
   372		if (rc)
   373			goto err_free_irqs;
   374	
   375		tx_cp = bnge_num_tx_to_cp(bd, bd->tx_nr_rings);
   376		bd->nq_nr_rings = (min == 1) ?
   377			max_t(u16, tx_cp, bd->rx_nr_rings) :
   378			tx_cp + bd->rx_nr_rings;
   379	
   380		/* Readjust tx_nr_rings_per_tc */
   381		if (!bd->num_tc)
   382			bd->tx_nr_rings_per_tc = bd->tx_nr_rings;
   383	
   384		return 0;
   385	
   386	err_free_irqs:
   387		dev_err(bd->dev, "Failed to allocate IRQs err = %d\n", rc);
   388		bnge_free_irqs(bd);
   389		return rc;
   390	}
   391	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 04/10] bng_en: Add initial interaction with firmware
  2025-06-24 12:11       ` Vadim Fedorenko
@ 2025-06-25  9:29         ` Vikas Gupta
  2025-06-25 10:24           ` Vadim Fedorenko
  0 siblings, 1 reply; 37+ messages in thread
From: Vikas Gupta @ 2025-06-25  9:29 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: davem, edumazet, kuba, pabeni, andrew+netdev, horms, netdev,
	linux-kernel, michael.chan, pavan.chebbi, vsrama-krishna.nemani,
	Bhargava Chenna Marreddy, Rajashekar Hudumula

[-- Attachment #1: Type: text/plain, Size: 1446 bytes --]

Hi Vadim,

> >>> +     req->year = cpu_to_le16(1900 + tm.tm_year);
> >>> +     req->month = 1 + tm.tm_mon;
> >>> +     req->day = tm.tm_mday;
> >>> +     req->hour = tm.tm_hour;
> >>> +     req->minute = tm.tm_min;
> >>> +     req->second = tm.tm_sec;
> >>> +     return hwrm_req_send(bd, req);
> >>> +}
> >>
> >> This whole function looks like copy-paste from bnxt, did you consider
> >> merging these parts?
> >
> > Both the bnxt and bnge drivers follow the same protocol to send the
> > requests to  the firmware,
> > so some functions may appear similar. However, we do not plan to share
> > the code, as certain
> >   fundamental data structures will differ.
>
> But at the same time some data structures are completely the same. Why
> do you think code duplication will work better on long run?

In the long run, maintaining this driver for future hardware is more practical
for us than integrating code into the BNXT driver.
Nevertheless, we are making a concerted effort to minimize duplication
wherever feasible.
So currently, we share the HSI (bnxt_hsi.h) as the driver to firmware
protocol remains largely unchanged.
While data structures are currently identical, but not all, we
recognize this is due to the fundamental
architectural similarities between the new and previous chip generations.
Newer chip features will definitely change the data structures and
related implementations.

Does this clarify your concern?

Thanks,
Vikas

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4193 bytes --]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 04/10] bng_en: Add initial interaction with firmware
  2025-06-25  9:29         ` Vikas Gupta
@ 2025-06-25 10:24           ` Vadim Fedorenko
  0 siblings, 0 replies; 37+ messages in thread
From: Vadim Fedorenko @ 2025-06-25 10:24 UTC (permalink / raw)
  To: Vikas Gupta
  Cc: davem, edumazet, kuba, pabeni, andrew+netdev, horms, netdev,
	linux-kernel, michael.chan, pavan.chebbi, vsrama-krishna.nemani,
	Bhargava Chenna Marreddy, Rajashekar Hudumula

On 25/06/2025 10:29, Vikas Gupta wrote:
> Hi Vadim,
> 
>>>>> +     req->year = cpu_to_le16(1900 + tm.tm_year);
>>>>> +     req->month = 1 + tm.tm_mon;
>>>>> +     req->day = tm.tm_mday;
>>>>> +     req->hour = tm.tm_hour;
>>>>> +     req->minute = tm.tm_min;
>>>>> +     req->second = tm.tm_sec;
>>>>> +     return hwrm_req_send(bd, req);
>>>>> +}
>>>>
>>>> This whole function looks like copy-paste from bnxt, did you consider
>>>> merging these parts?
>>>
>>> Both the bnxt and bnge drivers follow the same protocol to send the
>>> requests to  the firmware,
>>> so some functions may appear similar. However, we do not plan to share
>>> the code, as certain
>>>    fundamental data structures will differ.
>>
>> But at the same time some data structures are completely the same. Why
>> do you think code duplication will work better on long run?
> 
> In the long run, maintaining this driver for future hardware is more practical
> for us than integrating code into the BNXT driver.

I got it, my point was not in integrating it into BNXT, I totally agree
that it's more practical to have separate drivers for different
generations.

> Nevertheless, we are making a concerted effort to minimize duplication
> wherever feasible.
> So currently, we share the HSI (bnxt_hsi.h) as the driver to firmware
> protocol remains largely unchanged.
> While data structures are currently identical, but not all, we
> recognize this is due to the fundamental
> architectural similarities between the new and previous chip generations.
> Newer chip features will definitely change the data structures and
> related implementations.
> 
> Does this clarify your concern?

I was thinking of maybe creating a library with shared functions. But if
you say that data structures will change, I'm ok to have them
separately. Just be sure not to keep hacks for the really old HW.

Thanks,
Vadim

> 
> Thanks,
> Vikas


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [net-next, 09/10] bng_en: Initialize default configuration
  2025-06-18 14:47 ` [net-next, 09/10] bng_en: Initialize default configuration Vikas Gupta
                     ` (3 preceding siblings ...)
  2025-06-22 12:39   ` kernel test robot
@ 2025-06-26  8:47   ` kernel test robot
  4 siblings, 0 replies; 37+ messages in thread
From: kernel test robot @ 2025-06-26  8:47 UTC (permalink / raw)
  To: Vikas Gupta, davem, edumazet, kuba, pabeni, andrew+netdev, horms
  Cc: oe-kbuild-all, netdev, linux-kernel, michael.chan, pavan.chebbi,
	vsrama-krishna.nemani, Vikas Gupta, Bhargava Chenna Marreddy,
	Rajashekar Hudumula

Hi Vikas,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.16-rc3 next-20250625]
[cannot apply to horms-ipvs/master]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Vikas-Gupta/bng_en-Add-PCI-interface/20250618-173130
base:   linus/master
patch link:    https://lore.kernel.org/r/20250618144743.843815-10-vikas.gupta%40broadcom.com
patch subject: [net-next, 09/10] bng_en: Initialize default configuration
config: parisc-randconfig-r073-20250619 (https://download.01.org/0day-ci/archive/20250626/202506261600.oLXe1N0I-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 8.5.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506261600.oLXe1N0I-lkp@intel.com/

New smatch warnings:
drivers/net/ethernet/broadcom/bnge/bnge_resc.c:533 bnge_net_init_dflt_rings() warn: always true condition '(rc != -19) => (0-u16max != (-19))'

Old smatch warnings:
drivers/net/ethernet/broadcom/bnge/bnge_resc.c:372 bnge_alloc_irqs() warn: unsigned 'irqs_demand' is never less than zero.
drivers/net/ethernet/broadcom/bnge/bnge_resc.c:542 bnge_net_init_dflt_rings() warn: always true condition '(rc != -19) => (0-u16max != (-19))'

vim +533 drivers/net/ethernet/broadcom/bnge/bnge_resc.c

   511	
   512	static int bnge_net_init_dflt_rings(struct bnge_dev *bd, bool sh)
   513	{
   514		u16 dflt_rings, max_rx_rings, max_tx_rings, rc;
   515	
   516		if (sh)
   517			bd->flags |= BNGE_EN_SHARED_CHNL;
   518	
   519		dflt_rings = netif_get_num_default_rss_queues();
   520	
   521		rc = bnge_get_dflt_rings(bd, &max_rx_rings, &max_tx_rings, sh);
   522		if (rc)
   523			return rc;
   524		bd->rx_nr_rings = min_t(u16, dflt_rings, max_rx_rings);
   525		bd->tx_nr_rings_per_tc = min_t(u16, dflt_rings, max_tx_rings);
   526		if (sh)
   527			bnge_trim_dflt_sh_rings(bd);
   528		else
   529			bd->nq_nr_rings = bd->tx_nr_rings_per_tc + bd->rx_nr_rings;
   530		bd->tx_nr_rings = bd->tx_nr_rings_per_tc;
   531	
   532		rc = bnge_reserve_rings(bd);
 > 533		if (rc && rc != -ENODEV)
   534			dev_warn(bd->dev, "Unable to reserve tx rings\n");
   535		bd->tx_nr_rings_per_tc = bd->tx_nr_rings;
   536		if (sh)
   537			bnge_trim_dflt_sh_rings(bd);
   538	
   539		/* Rings may have been reduced, re-reserve them again */
   540		if (bnge_need_reserve_rings(bd)) {
   541			rc = bnge_reserve_rings(bd);
   542			if (rc && rc != -ENODEV)
   543				dev_warn(bd->dev, "Fewer rings reservation failed\n");
   544			bd->tx_nr_rings_per_tc = bd->tx_nr_rings;
   545		}
   546		if (rc) {
   547			bd->tx_nr_rings = 0;
   548			bd->rx_nr_rings = 0;
   549		}
   550	
   551		return rc;
   552	}
   553	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2025-06-26  8:47 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-18 14:47 [net-next, 00/10] Introducing Broadcom BNGE Ethernet Driver Vikas Gupta
2025-06-18 14:47 ` [net-next, 01/10] bng_en: Add PCI interface Vikas Gupta
2025-06-19 12:25   ` Vadim Fedorenko
2025-06-18 14:47 ` [net-next, 02/10] bng_en: Add devlink interface Vikas Gupta
2025-06-19 12:34   ` Vadim Fedorenko
2025-06-18 14:47 ` [net-next, 03/10] bng_en: Add firmware communication mechanism Vikas Gupta
2025-06-19  9:46   ` kernel test robot
2025-06-19 12:43   ` Vadim Fedorenko
2025-06-24 10:23     ` Vikas Gupta
2025-06-18 14:47 ` [net-next, 04/10] bng_en: Add initial interaction with firmware Vikas Gupta
2025-06-19 12:53   ` Vadim Fedorenko
2025-06-24 10:26     ` Vikas Gupta
2025-06-24 12:11       ` Vadim Fedorenko
2025-06-25  9:29         ` Vikas Gupta
2025-06-25 10:24           ` Vadim Fedorenko
2025-06-18 14:47 ` [net-next, 05/10] bng_en: Add ring memory allocation support Vikas Gupta
2025-06-18 14:47 ` [net-next, 06/10] bng_en: Add backing store support Vikas Gupta
2025-06-19 13:02   ` Vadim Fedorenko
2025-06-24 10:29     ` Vikas Gupta
2025-06-24 12:12       ` Vadim Fedorenko
2025-06-18 14:47 ` [net-next, 07/10] bng_en: Add resource management support Vikas Gupta
2025-06-19 13:39   ` Vadim Fedorenko
2025-06-24 10:31     ` Vikas Gupta
2025-06-18 14:47 ` [net-next, 08/10] bng_en: Add irq allocation support Vikas Gupta
2025-06-19 13:52   ` Vadim Fedorenko
2025-06-19 21:25   ` kernel test robot
2025-06-22  5:21   ` kernel test robot
2025-06-23  6:11   ` kernel test robot
2025-06-25  9:17   ` kernel test robot
2025-06-18 14:47 ` [net-next, 09/10] bng_en: Initialize default configuration Vikas Gupta
2025-06-18 20:16   ` kernel test robot
2025-06-19 13:57   ` Vadim Fedorenko
2025-06-20  9:08   ` kernel test robot
2025-06-22 12:39   ` kernel test robot
2025-06-26  8:47   ` kernel test robot
2025-06-18 14:47 ` [net-next, 10/10] bng_en: Add a network device Vikas Gupta
2025-06-24  0:42   ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).