Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
From 95190cc11737b35b62e92de37d7761370909d1b1 Mon Sep 17 00:00:00 2001
From: Christian Breunig <christian@breunig.cc>
Date: Thu, 25 Jun 2026 17:06:39 +0200
Subject: [PATCH] Kernel: T8914: add support for 2.5G pluggables on BCM57810S

Add the well-known JAMESMTL kernel module patch for bnx2x to advertise 2.5Gbit/s
capabilities on Broadcom NetXtreme2-X cards with BCM57810S chipset.

This is useful for ISP GPON access networks that use 2.5Gbit/s pluggables and
need the NIC to negotiate beyond 1000baseT/Full, avoiding the 940Mbit/s
practical cap on overprovisioned 1G services.

References:
* https://hack-gpon.org/broadcom-57810s/
* https://github.com/JAMESMTL/snippets/blob/dceb2fee74d80c66d/bnx2x/patches/bnx2x_warpcore_8727_2_5g_sgmii_txfault.patch
---
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 1 +
.../net/ethernet/broadcom/bnx2x/bnx2x_link.c | 54 +++++++++++++++++--
.../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 6 +++
.../net/ethernet/broadcom/bnx2x/bnx2x_reg.h | 3 +-
4 files changed, 58 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 9580ab83d387..e22a832936c3 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1593,6 +1593,7 @@ struct bnx2x {
uint num_ethernet_queues;
uint num_cnic_queues;
int disable_tpa;
+ int mask_tx_fault;
Comment thread
coderabbitai[bot] marked this conversation as resolved.

u32 rx_mode;
#define BNX2X_RX_MODE_NONE 0
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index ea310057fe3a..3fa0cf96da84 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -151,6 +151,7 @@ typedef int (*read_sfp_module_eeprom_func_p)(struct bnx2x_phy *phy,

#define SFP_EEPROM_CON_TYPE_ADDR 0x2
#define SFP_EEPROM_CON_TYPE_VAL_UNKNOWN 0x0
+ #define SFP_EEPROM_CON_TYPE_VAL_SC 0x1
#define SFP_EEPROM_CON_TYPE_VAL_LC 0x7
#define SFP_EEPROM_CON_TYPE_VAL_COPPER 0x21
#define SFP_EEPROM_CON_TYPE_VAL_RJ45 0x22
@@ -4210,6 +4211,16 @@ static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
0x1000);
DP(NETIF_MSG_LINK, "set SGMII AUTONEG\n");
} else {
+ /* Note that 2.5G works only when used with 1G advertisment */
+ if (fiber_mode && (phy->req_line_speed == SPEED_2500) &&
+ (phy->speed_cap_mask &
+ (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))) {
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_MISC1,
+ 0x6010);
+ }
Comment on lines +51 to +59

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Require the documented 1G + 2.5G capability combination.

Line 52 and Line 102 use speed_cap_mask & (1G | 2_5G), so either bit alone enables the 2.5G path. That contradicts Line 51’s “only when used with 1G advertisment” constraint and can configure 2.5G for an incomplete capability mask.

Proposed fix
-			(phy->speed_cap_mask &
-			 (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
-			  PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))) {
+			((phy->speed_cap_mask &
+			  (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
+			   PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)) ==
+			 (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
+			  PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))) {
-			(phy->speed_cap_mask &
-			(PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
-			 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))) {
+			((phy->speed_cap_mask &
+			  (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
+			   PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)) ==
+			 (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
+			  PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))) {

Also applies to: 102-117

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@scripts/package-build/linux-kernel/patches/kernel/0003-Kernel-T8914-add-support-for-2.5G-pluggables-on-BCM5.patch`
around lines 51 - 59, The 2.5G enablement check in the fiber-mode path is too
permissive because `speed_cap_mask & (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)` allows either capability alone to pass.
Update the condition in the `fiber_mode` / `phy->req_line_speed == SPEED_2500`
block (and the matching later path) so the 2.5G programming via
`bnx2x_cl45_write` only runs when both the 1G and 2.5G capability bits are
present, matching the “1G advertisment” requirement.

+
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
val16 &= 0xcebf;
@@ -4220,6 +4231,7 @@ static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
val16 |= 0x2000;
break;
case SPEED_1000:
+ case SPEED_2500:
val16 |= 0x0040;
break;
default:
@@ -8174,6 +8186,7 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
break;
}
case SFP_EEPROM_CON_TYPE_VAL_UNKNOWN:
+ case SFP_EEPROM_CON_TYPE_VAL_SC:
case SFP_EEPROM_CON_TYPE_VAL_LC:
case SFP_EEPROM_CON_TYPE_VAL_RJ45:
check_limiting_mode = 1;
@@ -8184,7 +8197,8 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
(val[SFP_EEPROM_1G_COMP_CODE_ADDR] != 0)) {
DP(NETIF_MSG_LINK, "1G SFP module detected\n");
phy->media_type = ETH_PHY_SFP_1G_FIBER;
- if (phy->req_line_speed != SPEED_1000) {
+ if ((phy->req_line_speed != SPEED_1000) &&
+ (phy->req_line_speed != SPEED_2500)) {
u8 gport = params->port;
phy->req_line_speed = SPEED_1000;
if (!CHIP_IS_E1x(bp)) {
@@ -9238,6 +9252,7 @@ static void bnx2x_8727_config_speed(struct bnx2x_phy *phy,
u16 tmp1, val;
/* Set option 1G speed */
if ((phy->req_line_speed == SPEED_1000) ||
+ (phy->req_line_speed == SPEED_2500) ||
(phy->media_type == ETH_PHY_SFP_1G_FIBER)) {
DP(NETIF_MSG_LINK, "Setting 1G force\n");
bnx2x_cl45_write(bp, phy,
@@ -9247,6 +9262,22 @@ static void bnx2x_8727_config_speed(struct bnx2x_phy *phy,
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, &tmp1);
DP(NETIF_MSG_LINK, "1.7 = 0x%x\n", tmp1);
+ if ((phy->req_line_speed == SPEED_2500) &&
+ (phy->speed_cap_mask &
+ (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))) {
+ bnx2x_cl45_read_and_write(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8727_MISC_CTRL2,
+ ~(1<<5));
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8727_MISC_CTRL1, 0x0010);
+ } else {
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8727_MISC_CTRL1, 0x001C);
+ }
/* Power down the XAUI until link is up in case of dual-media
* and 1G
*/
@@ -9268,7 +9299,7 @@ static void bnx2x_8727_config_speed(struct bnx2x_phy *phy,

DP(NETIF_MSG_LINK, "Setting 1G clause37\n");
bnx2x_cl45_write(bp, phy,
- MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL, 0);
+ MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL2, 0);
bnx2x_cl45_write(bp, phy,
MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1300);
} else {
@@ -9276,8 +9307,11 @@ static void bnx2x_8727_config_speed(struct bnx2x_phy *phy,
* registers although it is default
*/
bnx2x_cl45_write(bp, phy,
- MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL,
+ MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL2,
0x0020);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL1,
+ 0x001C);
bnx2x_cl45_write(bp, phy,
MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x0100);
bnx2x_cl45_write(bp, phy,
@@ -9567,6 +9601,11 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
vars->line_speed = SPEED_10000;
DP(NETIF_MSG_LINK, "port %x: External link up in 10G\n",
params->port);
+ } else if ((link_status & (1<<1)) && (!(link_status & (1<<14)))) {
+ link_up = 1;
+ vars->line_speed = SPEED_2500;
+ DP(NETIF_MSG_LINK, "port %x: External link up in 2.5G\n",
+ params->port);
} else if ((link_status & (1<<0)) && (!(link_status & (1<<13)))) {
link_up = 1;
vars->line_speed = SPEED_1000;
@@ -9598,7 +9637,8 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
}

if ((DUAL_MEDIA(params)) &&
- (phy->req_line_speed == SPEED_1000)) {
+ ((phy->req_line_speed == SPEED_1000) ||
+ (phy->req_line_speed == SPEED_2500))) {
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8727_PCS_GP, &val1);
@@ -11722,6 +11762,7 @@ static const struct bnx2x_phy phy_warpcore = {
SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Full |
SUPPORTED_1000baseKX_Full |
+ SUPPORTED_2500baseX_Full |
SUPPORTED_10000baseT_Full |
SUPPORTED_10000baseKR_Full |
SUPPORTED_20000baseKR2_Full |
@@ -11908,6 +11949,7 @@ static const struct bnx2x_phy phy_8727 = {
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
.supported = (SUPPORTED_10000baseT_Full |
+ SUPPORTED_2500baseX_Full |
SUPPORTED_1000baseT_Full |
SUPPORTED_FIBRE |
SUPPORTED_Pause |
@@ -12255,6 +12297,7 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
break;
case PORT_HW_CFG_NET_SERDES_IF_SFI:
phy->supported &= (SUPPORTED_1000baseT_Full |
+ SUPPORTED_2500baseX_Full |
SUPPORTED_10000baseT_Full |
SUPPORTED_FIBRE |
SUPPORTED_Pause |
@@ -13939,7 +13982,8 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
& PORT_HW_CFG_NET_SERDES_IF_MASK) ==
PORT_HW_CFG_NET_SERDES_IF_SFI) {
if (bnx2x_is_sfp_module_plugged(phy, params)) {
- bnx2x_sfp_tx_fault_detection(phy, params, vars);
+ if(!((params->port + 1) & bp->mask_tx_fault))
+ bnx2x_sfp_tx_fault_detection(phy, params, vars);
} else if (vars->link_status &
LINK_STATUS_SFP_TX_FAULT) {
/* Clean trail, interrupt corrects the leds */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 8e6eec828d48..767d4cd238e9 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -112,6 +112,10 @@ static int disable_tpa;
module_param(disable_tpa, int, 0444);
MODULE_PARM_DESC(disable_tpa, " Disable the TPA (LRO) feature");

+static int mask_tx_fault;
+module_param(mask_tx_fault, int, 0444);
+MODULE_PARM_DESC(mask_tx_fault, " Mask SFP TX fault detection");
+
static int int_mode;
module_param(int_mode, int, 0444);
MODULE_PARM_DESC(int_mode, " Force interrupt mode other than MSI-X "
@@ -12343,6 +12347,8 @@ static int bnx2x_init_bp(struct bnx2x *bp)
if (BP_NOMCP(bp) && (func == 0))
dev_err(&bp->pdev->dev, "MCP disabled, must load devices in order!\n");

+ bp->mask_tx_fault = mask_tx_fault;
+
bp->disable_tpa = disable_tpa;
bp->disable_tpa |= !!IS_MF_STORAGE_ONLY(bp);
/* Reduce memory usage in kdump environment by disabling TPA */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
index a018f251d198..b030b1cf9f93 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
@@ -7171,7 +7171,8 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_PMA_REG_8727_PCS_GP 0xc842
#define MDIO_PMA_REG_8727_OPT_CFG_REG 0xc8e4

-#define MDIO_AN_REG_8727_MISC_CTRL 0x8309
+#define MDIO_AN_REG_8727_MISC_CTRL1 0x8308
+#define MDIO_AN_REG_8727_MISC_CTRL2 0x8309

#define MDIO_PMA_REG_8073_CHIP_REV 0xc801
#define MDIO_PMA_REG_8073_SPEED_LINK_STATUS 0xc820
--
2.39.5

Loading