Skip to content

Commit

Permalink
bnx2x: Fix link problems for 1G SFP RJ45 module
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Yaniv Rosner authored and David S. Miller committed Sep 6, 2014
1 parent 98ea232 commit 6e9e564
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 36 deletions.
7 changes: 6 additions & 1 deletion drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -2233,7 +2233,12 @@ struct shmem2_region {
u32 reserved3; /* Offset 0x14C */
u32 reserved4; /* Offset 0x150 */
u32 link_attr_sync[PORT_MAX]; /* Offset 0x154 */
#define LINK_ATTR_SYNC_KR2_ENABLE (1<<0)
#define LINK_ATTR_SYNC_KR2_ENABLE 0x00000001
#define LINK_SFP_EEPROM_COMP_CODE_MASK 0x0000ff00
#define LINK_SFP_EEPROM_COMP_CODE_SHIFT 8
#define LINK_SFP_EEPROM_COMP_CODE_SR 0x00001000
#define LINK_SFP_EEPROM_COMP_CODE_LR 0x00002000
#define LINK_SFP_EEPROM_COMP_CODE_LRM 0x00004000

u32 reserved5[2];
u32 reserved6[PORT_MAX];
Expand Down
74 changes: 41 additions & 33 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,22 @@ typedef int (*read_sfp_module_eeprom_func_p)(struct bnx2x_phy *phy,
LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE)

#define SFP_EEPROM_CON_TYPE_ADDR 0x2
#define SFP_EEPROM_CON_TYPE_VAL_UNKNOWN 0x0
#define SFP_EEPROM_CON_TYPE_VAL_LC 0x7
#define SFP_EEPROM_CON_TYPE_VAL_COPPER 0x21
#define SFP_EEPROM_CON_TYPE_VAL_RJ45 0x22


#define SFP_EEPROM_COMP_CODE_ADDR 0x3
#define SFP_EEPROM_COMP_CODE_SR_MASK (1<<4)
#define SFP_EEPROM_COMP_CODE_LR_MASK (1<<5)
#define SFP_EEPROM_COMP_CODE_LRM_MASK (1<<6)
#define SFP_EEPROM_10G_COMP_CODE_ADDR 0x3
#define SFP_EEPROM_10G_COMP_CODE_SR_MASK (1<<4)
#define SFP_EEPROM_10G_COMP_CODE_LR_MASK (1<<5)
#define SFP_EEPROM_10G_COMP_CODE_LRM_MASK (1<<6)

#define SFP_EEPROM_1G_COMP_CODE_ADDR 0x6
#define SFP_EEPROM_1G_COMP_CODE_SX (1<<0)
#define SFP_EEPROM_1G_COMP_CODE_LX (1<<1)
#define SFP_EEPROM_1G_COMP_CODE_CX (1<<2)
#define SFP_EEPROM_1G_COMP_CODE_BASE_T (1<<3)

#define SFP_EEPROM_FC_TX_TECH_ADDR 0x8
#define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE 0x4
Expand Down Expand Up @@ -3633,8 +3640,8 @@ static void bnx2x_warpcore_enable_AN_KR2(struct bnx2x_phy *phy,
reg_set[i].val);

/* Start KR2 work-around timer which handles BCM8073 link-parner */
vars->link_attr_sync |= LINK_ATTR_SYNC_KR2_ENABLE;
bnx2x_update_link_attr(params, vars->link_attr_sync);
params->link_attr_sync |= LINK_ATTR_SYNC_KR2_ENABLE;
bnx2x_update_link_attr(params, params->link_attr_sync);
}

static void bnx2x_disable_kr2(struct link_params *params,
Expand Down Expand Up @@ -3666,8 +3673,8 @@ static void bnx2x_disable_kr2(struct link_params *params,
for (i = 0; i < ARRAY_SIZE(reg_set); i++)
bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
reg_set[i].val);
vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
bnx2x_update_link_attr(params, vars->link_attr_sync);
params->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
bnx2x_update_link_attr(params, params->link_attr_sync);

vars->check_kr2_recovery_cnt = CHECK_KR2_RECOVERY_CNT;
}
Expand Down Expand Up @@ -4810,7 +4817,7 @@ void bnx2x_link_status_update(struct link_params *params,
~FEATURE_CONFIG_PFC_ENABLED;

if (SHMEM2_HAS(bp, link_attr_sync))
vars->link_attr_sync = SHMEM2_RD(bp,
params->link_attr_sync = SHMEM2_RD(bp,
link_attr_sync[params->port]);

DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x int_mask 0x%x\n",
Expand Down Expand Up @@ -8057,39 +8064,32 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
{
struct bnx2x *bp = params->bp;
u32 sync_offset = 0, phy_idx, media_types;
u8 gport, val[2], check_limiting_mode = 0;
u8 val[SFP_EEPROM_FC_TX_TECH_ADDR + 1], check_limiting_mode = 0;
*edc_mode = EDC_MODE_LIMITING;
phy->media_type = ETH_PHY_UNSPECIFIED;
/* First check for copper cable */
if (bnx2x_read_sfp_module_eeprom(phy,
params,
I2C_DEV_ADDR_A0,
SFP_EEPROM_CON_TYPE_ADDR,
2,
0,
SFP_EEPROM_FC_TX_TECH_ADDR + 1,
(u8 *)val) != 0) {
DP(NETIF_MSG_LINK, "Failed to read from SFP+ module EEPROM\n");
return -EINVAL;
}

switch (val[0]) {
params->link_attr_sync &= ~LINK_SFP_EEPROM_COMP_CODE_MASK;
params->link_attr_sync |= val[SFP_EEPROM_10G_COMP_CODE_ADDR] <<
LINK_SFP_EEPROM_COMP_CODE_SHIFT;
bnx2x_update_link_attr(params, params->link_attr_sync);
switch (val[SFP_EEPROM_CON_TYPE_ADDR]) {
case SFP_EEPROM_CON_TYPE_VAL_COPPER:
{
u8 copper_module_type;
phy->media_type = ETH_PHY_DA_TWINAX;
/* Check if its active cable (includes SFP+ module)
* of passive cable
*/
if (bnx2x_read_sfp_module_eeprom(phy,
params,
I2C_DEV_ADDR_A0,
SFP_EEPROM_FC_TX_TECH_ADDR,
1,
&copper_module_type) != 0) {
DP(NETIF_MSG_LINK,
"Failed to read copper-cable-type"
" from SFP+ EEPROM\n");
return -EINVAL;
}
copper_module_type = val[SFP_EEPROM_FC_TX_TECH_ADDR];

if (copper_module_type &
SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE) {
Expand All @@ -8115,16 +8115,18 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
}
break;
}
case SFP_EEPROM_CON_TYPE_VAL_UNKNOWN:
case SFP_EEPROM_CON_TYPE_VAL_LC:
case SFP_EEPROM_CON_TYPE_VAL_RJ45:
check_limiting_mode = 1;
if ((val[1] & (SFP_EEPROM_COMP_CODE_SR_MASK |
SFP_EEPROM_COMP_CODE_LR_MASK |
SFP_EEPROM_COMP_CODE_LRM_MASK)) == 0) {
if ((val[SFP_EEPROM_10G_COMP_CODE_ADDR] &
(SFP_EEPROM_10G_COMP_CODE_SR_MASK |
SFP_EEPROM_10G_COMP_CODE_LR_MASK |
SFP_EEPROM_10G_COMP_CODE_LRM_MASK)) == 0) {
DP(NETIF_MSG_LINK, "1G SFP module detected\n");
gport = params->port;
phy->media_type = ETH_PHY_SFP_1G_FIBER;
if (phy->req_line_speed != SPEED_1000) {
u8 gport = params->port;
phy->req_line_speed = SPEED_1000;
if (!CHIP_IS_E1x(bp)) {
gport = BP_PATH(bp) +
Expand All @@ -8134,6 +8136,12 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
"Warning: Link speed was forced to 1000Mbps. Current SFP module in port %d is not compliant with 10G Ethernet\n",
gport);
}
if (val[SFP_EEPROM_1G_COMP_CODE_ADDR] &
SFP_EEPROM_1G_COMP_CODE_BASE_T) {
bnx2x_sfp_set_transmitter(params, phy, 0);
msleep(40);
bnx2x_sfp_set_transmitter(params, phy, 1);
}
} else {
int idx, cfg_idx = 0;
DP(NETIF_MSG_LINK, "10G Optic module detected\n");
Expand All @@ -8149,7 +8157,7 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
break;
default:
DP(NETIF_MSG_LINK, "Unable to determine module type 0x%x !!!\n",
val[0]);
val[SFP_EEPROM_CON_TYPE_ADDR]);
return -EINVAL;
}
sync_offset = params->shmem_base +
Expand Down Expand Up @@ -13507,7 +13515,7 @@ static void bnx2x_check_kr2_wa(struct link_params *params,

sigdet = bnx2x_warpcore_get_sigdet(phy, params);
if (!sigdet) {
if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
if (!(params->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
bnx2x_kr2_recovery(params, vars, phy);
DP(NETIF_MSG_LINK, "No sigdet\n");
}
Expand All @@ -13525,7 +13533,7 @@ static void bnx2x_check_kr2_wa(struct link_params *params,

/* CL73 has not begun yet */
if (base_page == 0) {
if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
if (!(params->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
bnx2x_kr2_recovery(params, vars, phy);
DP(NETIF_MSG_LINK, "No BP\n");
}
Expand All @@ -13541,7 +13549,7 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
((next_page & 0xe0) == 0x20))));

/* In case KR2 is already disabled, check if we need to re-enable it */
if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
if (!(params->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
if (!not_kr2_device) {
DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page,
next_page);
Expand Down
5 changes: 3 additions & 2 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@ struct link_params {
#define LINK_FLAGS_INT_DISABLED (1<<0)
#define PHY_INITIALIZED (1<<1)
u32 lfa_base;

/* The same definitions as the shmem2 parameter */
u32 link_attr_sync;
};

/* Output parameters */
Expand Down Expand Up @@ -364,8 +367,6 @@ struct link_vars {
u8 rx_tx_asic_rst;
u8 turn_to_run_wc_rt;
u16 rsrv2;
/* The same definitions as the shmem2 parameter */
u32 link_attr_sync;
};

/***********************************************************/
Expand Down

0 comments on commit 6e9e564

Please sign in to comment.