Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bnx2x: Fix link problems for 1G SFP RJ45 module

When 1G SFP RJ45 module is detected, driver must reset the Tx laser
in order to prevent link issues. As part of change, the link_attr_sync
was relocated from vars to params.

Signed-off-by: Yaniv Rosner <Yaniv.Rosner@qlogic.com>
Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Yaniv Rosner and committed by
David S. Miller
6e9e5644 98ea232c

+50 -36
+6 -1
drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
··· 2233 2233 u32 reserved3; /* Offset 0x14C */ 2234 2234 u32 reserved4; /* Offset 0x150 */ 2235 2235 u32 link_attr_sync[PORT_MAX]; /* Offset 0x154 */ 2236 - #define LINK_ATTR_SYNC_KR2_ENABLE (1<<0) 2236 + #define LINK_ATTR_SYNC_KR2_ENABLE 0x00000001 2237 + #define LINK_SFP_EEPROM_COMP_CODE_MASK 0x0000ff00 2238 + #define LINK_SFP_EEPROM_COMP_CODE_SHIFT 8 2239 + #define LINK_SFP_EEPROM_COMP_CODE_SR 0x00001000 2240 + #define LINK_SFP_EEPROM_COMP_CODE_LR 0x00002000 2241 + #define LINK_SFP_EEPROM_COMP_CODE_LRM 0x00004000 2237 2242 2238 2243 u32 reserved5[2]; 2239 2244 u32 reserved6[PORT_MAX];
+41 -33
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
··· 154 154 LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE) 155 155 156 156 #define SFP_EEPROM_CON_TYPE_ADDR 0x2 157 + #define SFP_EEPROM_CON_TYPE_VAL_UNKNOWN 0x0 157 158 #define SFP_EEPROM_CON_TYPE_VAL_LC 0x7 158 159 #define SFP_EEPROM_CON_TYPE_VAL_COPPER 0x21 159 160 #define SFP_EEPROM_CON_TYPE_VAL_RJ45 0x22 160 161 161 162 162 - #define SFP_EEPROM_COMP_CODE_ADDR 0x3 163 - #define SFP_EEPROM_COMP_CODE_SR_MASK (1<<4) 164 - #define SFP_EEPROM_COMP_CODE_LR_MASK (1<<5) 165 - #define SFP_EEPROM_COMP_CODE_LRM_MASK (1<<6) 163 + #define SFP_EEPROM_10G_COMP_CODE_ADDR 0x3 164 + #define SFP_EEPROM_10G_COMP_CODE_SR_MASK (1<<4) 165 + #define SFP_EEPROM_10G_COMP_CODE_LR_MASK (1<<5) 166 + #define SFP_EEPROM_10G_COMP_CODE_LRM_MASK (1<<6) 167 + 168 + #define SFP_EEPROM_1G_COMP_CODE_ADDR 0x6 169 + #define SFP_EEPROM_1G_COMP_CODE_SX (1<<0) 170 + #define SFP_EEPROM_1G_COMP_CODE_LX (1<<1) 171 + #define SFP_EEPROM_1G_COMP_CODE_CX (1<<2) 172 + #define SFP_EEPROM_1G_COMP_CODE_BASE_T (1<<3) 166 173 167 174 #define SFP_EEPROM_FC_TX_TECH_ADDR 0x8 168 175 #define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE 0x4 ··· 3640 3633 reg_set[i].val); 3641 3634 3642 3635 /* Start KR2 work-around timer which handles BCM8073 link-parner */ 3643 - vars->link_attr_sync |= LINK_ATTR_SYNC_KR2_ENABLE; 3644 - bnx2x_update_link_attr(params, vars->link_attr_sync); 3636 + params->link_attr_sync |= LINK_ATTR_SYNC_KR2_ENABLE; 3637 + bnx2x_update_link_attr(params, params->link_attr_sync); 3645 3638 } 3646 3639 3647 3640 static void bnx2x_disable_kr2(struct link_params *params, ··· 3673 3666 for (i = 0; i < ARRAY_SIZE(reg_set); i++) 3674 3667 bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg, 3675 3668 reg_set[i].val); 3676 - vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE; 3677 - bnx2x_update_link_attr(params, vars->link_attr_sync); 3669 + params->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE; 3670 + bnx2x_update_link_attr(params, params->link_attr_sync); 3678 3671 3679 3672 vars->check_kr2_recovery_cnt = CHECK_KR2_RECOVERY_CNT; 3680 3673 } ··· 4817 4810 ~FEATURE_CONFIG_PFC_ENABLED; 4818 4811 4819 4812 if (SHMEM2_HAS(bp, link_attr_sync)) 4820 - vars->link_attr_sync = SHMEM2_RD(bp, 4813 + params->link_attr_sync = SHMEM2_RD(bp, 4821 4814 link_attr_sync[params->port]); 4822 4815 4823 4816 DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x int_mask 0x%x\n", ··· 8064 8057 { 8065 8058 struct bnx2x *bp = params->bp; 8066 8059 u32 sync_offset = 0, phy_idx, media_types; 8067 - u8 gport, val[2], check_limiting_mode = 0; 8060 + u8 val[SFP_EEPROM_FC_TX_TECH_ADDR + 1], check_limiting_mode = 0; 8068 8061 *edc_mode = EDC_MODE_LIMITING; 8069 8062 phy->media_type = ETH_PHY_UNSPECIFIED; 8070 8063 /* First check for copper cable */ 8071 8064 if (bnx2x_read_sfp_module_eeprom(phy, 8072 8065 params, 8073 8066 I2C_DEV_ADDR_A0, 8074 - SFP_EEPROM_CON_TYPE_ADDR, 8075 - 2, 8067 + 0, 8068 + SFP_EEPROM_FC_TX_TECH_ADDR + 1, 8076 8069 (u8 *)val) != 0) { 8077 8070 DP(NETIF_MSG_LINK, "Failed to read from SFP+ module EEPROM\n"); 8078 8071 return -EINVAL; 8079 8072 } 8080 - 8081 - switch (val[0]) { 8073 + params->link_attr_sync &= ~LINK_SFP_EEPROM_COMP_CODE_MASK; 8074 + params->link_attr_sync |= val[SFP_EEPROM_10G_COMP_CODE_ADDR] << 8075 + LINK_SFP_EEPROM_COMP_CODE_SHIFT; 8076 + bnx2x_update_link_attr(params, params->link_attr_sync); 8077 + switch (val[SFP_EEPROM_CON_TYPE_ADDR]) { 8082 8078 case SFP_EEPROM_CON_TYPE_VAL_COPPER: 8083 8079 { 8084 8080 u8 copper_module_type; ··· 8089 8079 /* Check if its active cable (includes SFP+ module) 8090 8080 * of passive cable 8091 8081 */ 8092 - if (bnx2x_read_sfp_module_eeprom(phy, 8093 - params, 8094 - I2C_DEV_ADDR_A0, 8095 - SFP_EEPROM_FC_TX_TECH_ADDR, 8096 - 1, 8097 - &copper_module_type) != 0) { 8098 - DP(NETIF_MSG_LINK, 8099 - "Failed to read copper-cable-type" 8100 - " from SFP+ EEPROM\n"); 8101 - return -EINVAL; 8102 - } 8082 + copper_module_type = val[SFP_EEPROM_FC_TX_TECH_ADDR]; 8103 8083 8104 8084 if (copper_module_type & 8105 8085 SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE) { ··· 8115 8115 } 8116 8116 break; 8117 8117 } 8118 + case SFP_EEPROM_CON_TYPE_VAL_UNKNOWN: 8118 8119 case SFP_EEPROM_CON_TYPE_VAL_LC: 8119 8120 case SFP_EEPROM_CON_TYPE_VAL_RJ45: 8120 8121 check_limiting_mode = 1; 8121 - if ((val[1] & (SFP_EEPROM_COMP_CODE_SR_MASK | 8122 - SFP_EEPROM_COMP_CODE_LR_MASK | 8123 - SFP_EEPROM_COMP_CODE_LRM_MASK)) == 0) { 8122 + if ((val[SFP_EEPROM_10G_COMP_CODE_ADDR] & 8123 + (SFP_EEPROM_10G_COMP_CODE_SR_MASK | 8124 + SFP_EEPROM_10G_COMP_CODE_LR_MASK | 8125 + SFP_EEPROM_10G_COMP_CODE_LRM_MASK)) == 0) { 8124 8126 DP(NETIF_MSG_LINK, "1G SFP module detected\n"); 8125 - gport = params->port; 8126 8127 phy->media_type = ETH_PHY_SFP_1G_FIBER; 8127 8128 if (phy->req_line_speed != SPEED_1000) { 8129 + u8 gport = params->port; 8128 8130 phy->req_line_speed = SPEED_1000; 8129 8131 if (!CHIP_IS_E1x(bp)) { 8130 8132 gport = BP_PATH(bp) + ··· 8135 8133 netdev_err(bp->dev, 8136 8134 "Warning: Link speed was forced to 1000Mbps. Current SFP module in port %d is not compliant with 10G Ethernet\n", 8137 8135 gport); 8136 + } 8137 + if (val[SFP_EEPROM_1G_COMP_CODE_ADDR] & 8138 + SFP_EEPROM_1G_COMP_CODE_BASE_T) { 8139 + bnx2x_sfp_set_transmitter(params, phy, 0); 8140 + msleep(40); 8141 + bnx2x_sfp_set_transmitter(params, phy, 1); 8138 8142 } 8139 8143 } else { 8140 8144 int idx, cfg_idx = 0; ··· 8157 8149 break; 8158 8150 default: 8159 8151 DP(NETIF_MSG_LINK, "Unable to determine module type 0x%x !!!\n", 8160 - val[0]); 8152 + val[SFP_EEPROM_CON_TYPE_ADDR]); 8161 8153 return -EINVAL; 8162 8154 } 8163 8155 sync_offset = params->shmem_base + ··· 13515 13507 13516 13508 sigdet = bnx2x_warpcore_get_sigdet(phy, params); 13517 13509 if (!sigdet) { 13518 - if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) { 13510 + if (!(params->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) { 13519 13511 bnx2x_kr2_recovery(params, vars, phy); 13520 13512 DP(NETIF_MSG_LINK, "No sigdet\n"); 13521 13513 } ··· 13533 13525 13534 13526 /* CL73 has not begun yet */ 13535 13527 if (base_page == 0) { 13536 - if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) { 13528 + if (!(params->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) { 13537 13529 bnx2x_kr2_recovery(params, vars, phy); 13538 13530 DP(NETIF_MSG_LINK, "No BP\n"); 13539 13531 } ··· 13549 13541 ((next_page & 0xe0) == 0x20)))); 13550 13542 13551 13543 /* In case KR2 is already disabled, check if we need to re-enable it */ 13552 - if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) { 13544 + if (!(params->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) { 13553 13545 if (!not_kr2_device) { 13554 13546 DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page, 13555 13547 next_page);
+3 -2
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
··· 323 323 #define LINK_FLAGS_INT_DISABLED (1<<0) 324 324 #define PHY_INITIALIZED (1<<1) 325 325 u32 lfa_base; 326 + 327 + /* The same definitions as the shmem2 parameter */ 328 + u32 link_attr_sync; 326 329 }; 327 330 328 331 /* Output parameters */ ··· 367 364 u8 rx_tx_asic_rst; 368 365 u8 turn_to_run_wc_rt; 369 366 u16 rsrv2; 370 - /* The same definitions as the shmem2 parameter */ 371 - u32 link_attr_sync; 372 367 }; 373 368 374 369 /***********************************************************/