|
| 1 | +From 95190cc11737b35b62e92de37d7761370909d1b1 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Christian Breunig <christian@breunig.cc> |
| 3 | +Date: Thu, 25 Jun 2026 17:06:39 +0200 |
| 4 | +Subject: [PATCH] Kernel: T8914: add support for 2.5G pluggables on BCM57810S |
| 5 | + |
| 6 | +Add the well-known JAMESMTL kernel module patch for bnx2x to advertise 2.5Gbit/s |
| 7 | +capabilities on Broadcom NetXtreme2-X cards with BCM57810S chipset. |
| 8 | + |
| 9 | +This is useful for ISP GPON access networks that use 2.5Gbit/s pluggables and |
| 10 | +need the NIC to negotiate beyond 1000baseT/Full, avoiding the 940Mbit/s |
| 11 | +practical cap on overprovisioned 1G services. |
| 12 | + |
| 13 | +References: |
| 14 | +* https://hack-gpon.org/broadcom-57810s/ |
| 15 | +* https://github.com/JAMESMTL/snippets/blob/dceb2fee74d80c66d/bnx2x/patches/bnx2x_warpcore_8727_2_5g_sgmii_txfault.patch |
| 16 | +--- |
| 17 | + drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 1 + |
| 18 | + .../net/ethernet/broadcom/bnx2x/bnx2x_link.c | 54 +++++++++++++++++-- |
| 19 | + .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 6 +++ |
| 20 | + .../net/ethernet/broadcom/bnx2x/bnx2x_reg.h | 3 +- |
| 21 | + 4 files changed, 58 insertions(+), 6 deletions(-) |
| 22 | + |
| 23 | +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h |
| 24 | +index 9580ab83d387..e22a832936c3 100644 |
| 25 | +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h |
| 26 | ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h |
| 27 | +@@ -1593,6 +1593,7 @@ struct bnx2x { |
| 28 | + uint num_ethernet_queues; |
| 29 | + uint num_cnic_queues; |
| 30 | + int disable_tpa; |
| 31 | ++ int mask_tx_fault; |
| 32 | + |
| 33 | + u32 rx_mode; |
| 34 | + #define BNX2X_RX_MODE_NONE 0 |
| 35 | +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c |
| 36 | +index ea310057fe3a..3fa0cf96da84 100644 |
| 37 | +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c |
| 38 | ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c |
| 39 | +@@ -151,6 +151,7 @@ typedef int (*read_sfp_module_eeprom_func_p)(struct bnx2x_phy *phy, |
| 40 | + |
| 41 | + #define SFP_EEPROM_CON_TYPE_ADDR 0x2 |
| 42 | + #define SFP_EEPROM_CON_TYPE_VAL_UNKNOWN 0x0 |
| 43 | ++ #define SFP_EEPROM_CON_TYPE_VAL_SC 0x1 |
| 44 | + #define SFP_EEPROM_CON_TYPE_VAL_LC 0x7 |
| 45 | + #define SFP_EEPROM_CON_TYPE_VAL_COPPER 0x21 |
| 46 | + #define SFP_EEPROM_CON_TYPE_VAL_RJ45 0x22 |
| 47 | +@@ -4210,6 +4211,16 @@ static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy, |
| 48 | + 0x1000); |
| 49 | + DP(NETIF_MSG_LINK, "set SGMII AUTONEG\n"); |
| 50 | + } else { |
| 51 | ++ /* Note that 2.5G works only when used with 1G advertisment */ |
| 52 | ++ if (fiber_mode && (phy->req_line_speed == SPEED_2500) && |
| 53 | ++ (phy->speed_cap_mask & |
| 54 | ++ (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G | |
| 55 | ++ PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))) { |
| 56 | ++ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, |
| 57 | ++ MDIO_WC_REG_SERDESDIGITAL_MISC1, |
| 58 | ++ 0x6010); |
| 59 | ++ } |
| 60 | ++ |
| 61 | + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, |
| 62 | + MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16); |
| 63 | + val16 &= 0xcebf; |
| 64 | +@@ -4220,6 +4231,7 @@ static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy, |
| 65 | + val16 |= 0x2000; |
| 66 | + break; |
| 67 | + case SPEED_1000: |
| 68 | ++ case SPEED_2500: |
| 69 | + val16 |= 0x0040; |
| 70 | + break; |
| 71 | + default: |
| 72 | +@@ -8174,6 +8186,7 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy, |
| 73 | + break; |
| 74 | + } |
| 75 | + case SFP_EEPROM_CON_TYPE_VAL_UNKNOWN: |
| 76 | ++ case SFP_EEPROM_CON_TYPE_VAL_SC: |
| 77 | + case SFP_EEPROM_CON_TYPE_VAL_LC: |
| 78 | + case SFP_EEPROM_CON_TYPE_VAL_RJ45: |
| 79 | + check_limiting_mode = 1; |
| 80 | +@@ -8184,7 +8197,8 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy, |
| 81 | + (val[SFP_EEPROM_1G_COMP_CODE_ADDR] != 0)) { |
| 82 | + DP(NETIF_MSG_LINK, "1G SFP module detected\n"); |
| 83 | + phy->media_type = ETH_PHY_SFP_1G_FIBER; |
| 84 | +- if (phy->req_line_speed != SPEED_1000) { |
| 85 | ++ if ((phy->req_line_speed != SPEED_1000) && |
| 86 | ++ (phy->req_line_speed != SPEED_2500)) { |
| 87 | + u8 gport = params->port; |
| 88 | + phy->req_line_speed = SPEED_1000; |
| 89 | + if (!CHIP_IS_E1x(bp)) { |
| 90 | +@@ -9238,6 +9252,7 @@ static void bnx2x_8727_config_speed(struct bnx2x_phy *phy, |
| 91 | + u16 tmp1, val; |
| 92 | + /* Set option 1G speed */ |
| 93 | + if ((phy->req_line_speed == SPEED_1000) || |
| 94 | ++ (phy->req_line_speed == SPEED_2500) || |
| 95 | + (phy->media_type == ETH_PHY_SFP_1G_FIBER)) { |
| 96 | + DP(NETIF_MSG_LINK, "Setting 1G force\n"); |
| 97 | + bnx2x_cl45_write(bp, phy, |
| 98 | +@@ -9247,6 +9262,22 @@ static void bnx2x_8727_config_speed(struct bnx2x_phy *phy, |
| 99 | + bnx2x_cl45_read(bp, phy, |
| 100 | + MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, &tmp1); |
| 101 | + DP(NETIF_MSG_LINK, "1.7 = 0x%x\n", tmp1); |
| 102 | ++ if ((phy->req_line_speed == SPEED_2500) && |
| 103 | ++ (phy->speed_cap_mask & |
| 104 | ++ (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G | |
| 105 | ++ PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))) { |
| 106 | ++ bnx2x_cl45_read_and_write(bp, phy, |
| 107 | ++ MDIO_AN_DEVAD, |
| 108 | ++ MDIO_AN_REG_8727_MISC_CTRL2, |
| 109 | ++ ~(1<<5)); |
| 110 | ++ bnx2x_cl45_write(bp, phy, |
| 111 | ++ MDIO_AN_DEVAD, |
| 112 | ++ MDIO_AN_REG_8727_MISC_CTRL1, 0x0010); |
| 113 | ++ } else { |
| 114 | ++ bnx2x_cl45_write(bp, phy, |
| 115 | ++ MDIO_AN_DEVAD, |
| 116 | ++ MDIO_AN_REG_8727_MISC_CTRL1, 0x001C); |
| 117 | ++ } |
| 118 | + /* Power down the XAUI until link is up in case of dual-media |
| 119 | + * and 1G |
| 120 | + */ |
| 121 | +@@ -9268,7 +9299,7 @@ static void bnx2x_8727_config_speed(struct bnx2x_phy *phy, |
| 122 | + |
| 123 | + DP(NETIF_MSG_LINK, "Setting 1G clause37\n"); |
| 124 | + bnx2x_cl45_write(bp, phy, |
| 125 | +- MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL, 0); |
| 126 | ++ MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL2, 0); |
| 127 | + bnx2x_cl45_write(bp, phy, |
| 128 | + MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1300); |
| 129 | + } else { |
| 130 | +@@ -9276,8 +9307,11 @@ static void bnx2x_8727_config_speed(struct bnx2x_phy *phy, |
| 131 | + * registers although it is default |
| 132 | + */ |
| 133 | + bnx2x_cl45_write(bp, phy, |
| 134 | +- MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL, |
| 135 | ++ MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL2, |
| 136 | + 0x0020); |
| 137 | ++ bnx2x_cl45_write(bp, phy, |
| 138 | ++ MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL1, |
| 139 | ++ 0x001C); |
| 140 | + bnx2x_cl45_write(bp, phy, |
| 141 | + MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x0100); |
| 142 | + bnx2x_cl45_write(bp, phy, |
| 143 | +@@ -9567,6 +9601,11 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy, |
| 144 | + vars->line_speed = SPEED_10000; |
| 145 | + DP(NETIF_MSG_LINK, "port %x: External link up in 10G\n", |
| 146 | + params->port); |
| 147 | ++ } else if ((link_status & (1<<1)) && (!(link_status & (1<<14)))) { |
| 148 | ++ link_up = 1; |
| 149 | ++ vars->line_speed = SPEED_2500; |
| 150 | ++ DP(NETIF_MSG_LINK, "port %x: External link up in 2.5G\n", |
| 151 | ++ params->port); |
| 152 | + } else if ((link_status & (1<<0)) && (!(link_status & (1<<13)))) { |
| 153 | + link_up = 1; |
| 154 | + vars->line_speed = SPEED_1000; |
| 155 | +@@ -9598,7 +9637,8 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy, |
| 156 | + } |
| 157 | + |
| 158 | + if ((DUAL_MEDIA(params)) && |
| 159 | +- (phy->req_line_speed == SPEED_1000)) { |
| 160 | ++ ((phy->req_line_speed == SPEED_1000) || |
| 161 | ++ (phy->req_line_speed == SPEED_2500))) { |
| 162 | + bnx2x_cl45_read(bp, phy, |
| 163 | + MDIO_PMA_DEVAD, |
| 164 | + MDIO_PMA_REG_8727_PCS_GP, &val1); |
| 165 | +@@ -11722,6 +11762,7 @@ static const struct bnx2x_phy phy_warpcore = { |
| 166 | + SUPPORTED_100baseT_Full | |
| 167 | + SUPPORTED_1000baseT_Full | |
| 168 | + SUPPORTED_1000baseKX_Full | |
| 169 | ++ SUPPORTED_2500baseX_Full | |
| 170 | + SUPPORTED_10000baseT_Full | |
| 171 | + SUPPORTED_10000baseKR_Full | |
| 172 | + SUPPORTED_20000baseKR2_Full | |
| 173 | +@@ -11908,6 +11949,7 @@ static const struct bnx2x_phy phy_8727 = { |
| 174 | + .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, |
| 175 | + .mdio_ctrl = 0, |
| 176 | + .supported = (SUPPORTED_10000baseT_Full | |
| 177 | ++ SUPPORTED_2500baseX_Full | |
| 178 | + SUPPORTED_1000baseT_Full | |
| 179 | + SUPPORTED_FIBRE | |
| 180 | + SUPPORTED_Pause | |
| 181 | +@@ -12255,6 +12297,7 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port, |
| 182 | + break; |
| 183 | + case PORT_HW_CFG_NET_SERDES_IF_SFI: |
| 184 | + phy->supported &= (SUPPORTED_1000baseT_Full | |
| 185 | ++ SUPPORTED_2500baseX_Full | |
| 186 | + SUPPORTED_10000baseT_Full | |
| 187 | + SUPPORTED_FIBRE | |
| 188 | + SUPPORTED_Pause | |
| 189 | +@@ -13939,7 +13982,8 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars) |
| 190 | + & PORT_HW_CFG_NET_SERDES_IF_MASK) == |
| 191 | + PORT_HW_CFG_NET_SERDES_IF_SFI) { |
| 192 | + if (bnx2x_is_sfp_module_plugged(phy, params)) { |
| 193 | +- bnx2x_sfp_tx_fault_detection(phy, params, vars); |
| 194 | ++ if(!((params->port + 1) & bp->mask_tx_fault)) |
| 195 | ++ bnx2x_sfp_tx_fault_detection(phy, params, vars); |
| 196 | + } else if (vars->link_status & |
| 197 | + LINK_STATUS_SFP_TX_FAULT) { |
| 198 | + /* Clean trail, interrupt corrects the leds */ |
| 199 | +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c |
| 200 | +index 8e6eec828d48..767d4cd238e9 100644 |
| 201 | +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c |
| 202 | ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c |
| 203 | +@@ -112,6 +112,10 @@ static int disable_tpa; |
| 204 | + module_param(disable_tpa, int, 0444); |
| 205 | + MODULE_PARM_DESC(disable_tpa, " Disable the TPA (LRO) feature"); |
| 206 | + |
| 207 | ++static int mask_tx_fault; |
| 208 | ++module_param(mask_tx_fault, int, 0444); |
| 209 | ++MODULE_PARM_DESC(mask_tx_fault, " Mask SFP TX fault detection"); |
| 210 | ++ |
| 211 | + static int int_mode; |
| 212 | + module_param(int_mode, int, 0444); |
| 213 | + MODULE_PARM_DESC(int_mode, " Force interrupt mode other than MSI-X " |
| 214 | +@@ -12343,6 +12347,8 @@ static int bnx2x_init_bp(struct bnx2x *bp) |
| 215 | + if (BP_NOMCP(bp) && (func == 0)) |
| 216 | + dev_err(&bp->pdev->dev, "MCP disabled, must load devices in order!\n"); |
| 217 | + |
| 218 | ++ bp->mask_tx_fault = mask_tx_fault; |
| 219 | ++ |
| 220 | + bp->disable_tpa = disable_tpa; |
| 221 | + bp->disable_tpa |= !!IS_MF_STORAGE_ONLY(bp); |
| 222 | + /* Reduce memory usage in kdump environment by disabling TPA */ |
| 223 | +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h |
| 224 | +index a018f251d198..b030b1cf9f93 100644 |
| 225 | +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h |
| 226 | ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h |
| 227 | +@@ -7171,7 +7171,8 @@ Theotherbitsarereservedandshouldbezero*/ |
| 228 | + #define MDIO_PMA_REG_8727_PCS_GP 0xc842 |
| 229 | + #define MDIO_PMA_REG_8727_OPT_CFG_REG 0xc8e4 |
| 230 | + |
| 231 | +-#define MDIO_AN_REG_8727_MISC_CTRL 0x8309 |
| 232 | ++#define MDIO_AN_REG_8727_MISC_CTRL1 0x8308 |
| 233 | ++#define MDIO_AN_REG_8727_MISC_CTRL2 0x8309 |
| 234 | + |
| 235 | + #define MDIO_PMA_REG_8073_CHIP_REV 0xc801 |
| 236 | + #define MDIO_PMA_REG_8073_SPEED_LINK_STATUS 0xc820 |
| 237 | +-- |
| 238 | +2.39.5 |
| 239 | + |
0 commit comments