diff options
| author | Vikas Gupta <vikas.gupta@broadcom.com> | 2025-07-01 14:35:00 +0000 | 
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2025-07-07 18:54:00 -0700 | 
| commit | 9099bfa1158a119b1cfd38b4de3ab16d24f841fe (patch) | |
| tree | fecadd0fce2ec0130558a39392e7cb9eb93cb17a | |
| parent | 74715c4ab0fa0c0911ba78cb639db6b8da88b085 (diff) | |
bng_en: Add devlink interface
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>
Link: https://patch.msgid.link/20250701143511.280702-3-vikas.gupta@broadcom.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
| -rw-r--r-- | drivers/net/ethernet/broadcom/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnge/Makefile | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnge/bnge.h | 11 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnge/bnge_core.c | 39 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnge/bnge_devlink.c | 142 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnge/bnge_devlink.h | 16 | 
6 files changed, 211 insertions, 1 deletions
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 514602555cd1..2596215f0639 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); @@ -77,8 +78,19 @@ err_pci_disable:  	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)) @@ -100,13 +112,40 @@ 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; +	} + +	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_free; +	} +  	pci_save_state(pdev);  	return 0; + +err_devl_free: +	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_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..d01cc32ce241 --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.c @@ -0,0 +1,142 @@ +// 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) { +			NL_SET_ERR_MSG_MOD(extack, "Failed to set dsn"); +			return rc; +		} +	} + +	if (strlen(bd->board_serialno)) { +		rc = devlink_info_board_serial_number_put(req, +							  bd->board_serialno); +		if (rc) { +			NL_SET_ERR_MSG_MOD(extack, +					   "Failed to set board serial number"); +			return rc; +		} +	} + +	rc = bnge_dl_info_put(bd, req, BNGE_VERSION_FIXED, +			      DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, +			      bd->board_partno); +	if (rc) { +		NL_SET_ERR_MSG_MOD(extack, "Failed to set board part number"); +		return rc; +	} + +	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; +} 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..497543918741 --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnge/bnge_devlink.h @@ -0,0 +1,16 @@ +/* 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); + +#endif /* _BNGE_DEVLINK_H_ */  | 
