bnx2x: Add remote-fault link detection
Restore remote-faule detection, which periodically checks for remote-fault on the MAC layer. In case physical link appear to be up but fault is set, it will provide a link down indication, and when the fault is cleared, it will indicate link up again. Signed-off-by: Yaniv Rosner <yaniv.rosner@broadcom.com> Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
30a5de7723
commit
55098c5c61
|
@ -6439,7 +6439,6 @@ static int bnx2x_link_initialize(struct link_params *params,
|
||||||
NIG_STATUS_XGXS0_LINK_STATUS |
|
NIG_STATUS_XGXS0_LINK_STATUS |
|
||||||
NIG_STATUS_SERDES0_LINK_STATUS |
|
NIG_STATUS_SERDES0_LINK_STATUS |
|
||||||
NIG_MASK_MI_INT));
|
NIG_MASK_MI_INT));
|
||||||
bnx2x_update_mng(params, vars->link_status);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6524,7 +6523,7 @@ static int bnx2x_update_link_up(struct link_params *params,
|
||||||
u8 link_10g)
|
u8 link_10g)
|
||||||
{
|
{
|
||||||
struct bnx2x *bp = params->bp;
|
struct bnx2x *bp = params->bp;
|
||||||
u8 port = params->port;
|
u8 phy_idx, port = params->port;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
vars->link_status |= (LINK_STATUS_LINK_UP |
|
vars->link_status |= (LINK_STATUS_LINK_UP |
|
||||||
|
@ -6588,6 +6587,14 @@ static int bnx2x_update_link_up(struct link_params *params,
|
||||||
|
|
||||||
/* update shared memory */
|
/* update shared memory */
|
||||||
bnx2x_update_mng(params, vars->link_status);
|
bnx2x_update_mng(params, vars->link_status);
|
||||||
|
|
||||||
|
/* Check remote fault */
|
||||||
|
for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
|
||||||
|
if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) {
|
||||||
|
bnx2x_check_half_open_conn(params, vars, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
msleep(20);
|
msleep(20);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -11027,7 +11034,8 @@ static struct bnx2x_phy phy_warpcore = {
|
||||||
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
|
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
|
||||||
.addr = 0xff,
|
.addr = 0xff,
|
||||||
.def_md_devad = 0,
|
.def_md_devad = 0,
|
||||||
.flags = FLAGS_HW_LOCK_REQUIRED,
|
.flags = (FLAGS_HW_LOCK_REQUIRED |
|
||||||
|
FLAGS_TX_ERROR_CHECK),
|
||||||
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
||||||
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
||||||
.mdio_ctrl = 0,
|
.mdio_ctrl = 0,
|
||||||
|
@ -11184,7 +11192,8 @@ static struct bnx2x_phy phy_8726 = {
|
||||||
.addr = 0xff,
|
.addr = 0xff,
|
||||||
.def_md_devad = 0,
|
.def_md_devad = 0,
|
||||||
.flags = (FLAGS_HW_LOCK_REQUIRED |
|
.flags = (FLAGS_HW_LOCK_REQUIRED |
|
||||||
FLAGS_INIT_XGXS_FIRST),
|
FLAGS_INIT_XGXS_FIRST |
|
||||||
|
FLAGS_TX_ERROR_CHECK),
|
||||||
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
||||||
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
||||||
.mdio_ctrl = 0,
|
.mdio_ctrl = 0,
|
||||||
|
@ -11215,7 +11224,8 @@ static struct bnx2x_phy phy_8727 = {
|
||||||
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
|
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
|
||||||
.addr = 0xff,
|
.addr = 0xff,
|
||||||
.def_md_devad = 0,
|
.def_md_devad = 0,
|
||||||
.flags = FLAGS_FAN_FAILURE_DET_REQ,
|
.flags = (FLAGS_FAN_FAILURE_DET_REQ |
|
||||||
|
FLAGS_TX_ERROR_CHECK),
|
||||||
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
||||||
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
||||||
.mdio_ctrl = 0,
|
.mdio_ctrl = 0,
|
||||||
|
@ -11280,8 +11290,9 @@ static struct bnx2x_phy phy_84823 = {
|
||||||
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
|
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
|
||||||
.addr = 0xff,
|
.addr = 0xff,
|
||||||
.def_md_devad = 0,
|
.def_md_devad = 0,
|
||||||
.flags = FLAGS_FAN_FAILURE_DET_REQ |
|
.flags = (FLAGS_FAN_FAILURE_DET_REQ |
|
||||||
FLAGS_REARM_LATCH_SIGNAL,
|
FLAGS_REARM_LATCH_SIGNAL |
|
||||||
|
FLAGS_TX_ERROR_CHECK),
|
||||||
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
||||||
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
||||||
.mdio_ctrl = 0,
|
.mdio_ctrl = 0,
|
||||||
|
@ -11316,8 +11327,9 @@ static struct bnx2x_phy phy_84833 = {
|
||||||
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833,
|
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833,
|
||||||
.addr = 0xff,
|
.addr = 0xff,
|
||||||
.def_md_devad = 0,
|
.def_md_devad = 0,
|
||||||
.flags = FLAGS_FAN_FAILURE_DET_REQ |
|
.flags = (FLAGS_FAN_FAILURE_DET_REQ |
|
||||||
FLAGS_REARM_LATCH_SIGNAL,
|
FLAGS_REARM_LATCH_SIGNAL |
|
||||||
|
FLAGS_TX_ERROR_CHECK),
|
||||||
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
||||||
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
||||||
.mdio_ctrl = 0,
|
.mdio_ctrl = 0,
|
||||||
|
@ -11862,6 +11874,10 @@ int bnx2x_phy_probe(struct link_params *params)
|
||||||
if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)
|
if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (params->feature_config_flags &
|
||||||
|
FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET)
|
||||||
|
phy->flags &= ~FLAGS_TX_ERROR_CHECK;
|
||||||
|
|
||||||
sync_offset = params->shmem_base +
|
sync_offset = params->shmem_base +
|
||||||
offsetof(struct shmem_region,
|
offsetof(struct shmem_region,
|
||||||
dev_info.port_hw_config[params->port].media_type);
|
dev_info.port_hw_config[params->port].media_type);
|
||||||
|
@ -12085,6 +12101,7 @@ int bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
|
||||||
bnx2x_link_int_enable(params);
|
bnx2x_link_int_enable(params);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
bnx2x_update_mng(params, vars->link_status);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12702,7 +12719,8 @@ static void bnx2x_check_over_curr(struct link_params *params,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bnx2x_analyze_link_error(struct link_params *params,
|
static void bnx2x_analyze_link_error(struct link_params *params,
|
||||||
struct link_vars *vars, u32 lss_status)
|
struct link_vars *vars, u32 lss_status,
|
||||||
|
u8 notify)
|
||||||
{
|
{
|
||||||
struct bnx2x *bp = params->bp;
|
struct bnx2x *bp = params->bp;
|
||||||
/* Compare new value with previous value */
|
/* Compare new value with previous value */
|
||||||
|
@ -12725,6 +12743,9 @@ static void bnx2x_analyze_link_error(struct link_params *params,
|
||||||
vars->link_status &= ~LINK_STATUS_LINK_UP;
|
vars->link_status &= ~LINK_STATUS_LINK_UP;
|
||||||
vars->link_up = 0;
|
vars->link_up = 0;
|
||||||
vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
|
vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
|
||||||
|
|
||||||
|
/* activate nig drain */
|
||||||
|
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 1);
|
||||||
/*
|
/*
|
||||||
* Set LED mode to off since the PHY doesn't know about these
|
* Set LED mode to off since the PHY doesn't know about these
|
||||||
* errors
|
* errors
|
||||||
|
@ -12736,7 +12757,11 @@ static void bnx2x_analyze_link_error(struct link_params *params,
|
||||||
vars->link_up = 1;
|
vars->link_up = 1;
|
||||||
vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
|
vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
|
||||||
led_mode = LED_MODE_OPER;
|
led_mode = LED_MODE_OPER;
|
||||||
|
|
||||||
|
/* Clear nig drain */
|
||||||
|
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
|
||||||
}
|
}
|
||||||
|
bnx2x_sync_link(params, vars);
|
||||||
/* Update the LED according to the link state */
|
/* Update the LED according to the link state */
|
||||||
bnx2x_set_led(params, vars, led_mode, SPEED_10000);
|
bnx2x_set_led(params, vars, led_mode, SPEED_10000);
|
||||||
|
|
||||||
|
@ -12745,7 +12770,8 @@ static void bnx2x_analyze_link_error(struct link_params *params,
|
||||||
|
|
||||||
/* C. Trigger General Attention */
|
/* C. Trigger General Attention */
|
||||||
vars->periodic_flags |= PERIODIC_FLAGS_LINK_EVENT;
|
vars->periodic_flags |= PERIODIC_FLAGS_LINK_EVENT;
|
||||||
bnx2x_notify_link_changed(bp);
|
if (notify)
|
||||||
|
bnx2x_notify_link_changed(bp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
@ -12757,15 +12783,17 @@ static void bnx2x_analyze_link_error(struct link_params *params,
|
||||||
* a fault, for example, due to break in the TX side of fiber.
|
* a fault, for example, due to break in the TX side of fiber.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
static void bnx2x_check_half_open_conn(struct link_params *params,
|
int bnx2x_check_half_open_conn(struct link_params *params,
|
||||||
struct link_vars *vars)
|
struct link_vars *vars,
|
||||||
|
u8 notify)
|
||||||
{
|
{
|
||||||
struct bnx2x *bp = params->bp;
|
struct bnx2x *bp = params->bp;
|
||||||
u32 lss_status = 0;
|
u32 lss_status = 0;
|
||||||
u32 mac_base;
|
u32 mac_base;
|
||||||
/* In case link status is physically up @ 10G do */
|
/* In case link status is physically up @ 10G do */
|
||||||
if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0)
|
if (((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0) ||
|
||||||
return;
|
(REG_RD(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (CHIP_IS_E3(bp) &&
|
if (CHIP_IS_E3(bp) &&
|
||||||
(REG_RD(bp, MISC_REG_RESET_REG_2) &
|
(REG_RD(bp, MISC_REG_RESET_REG_2) &
|
||||||
|
@ -12786,7 +12814,7 @@ static void bnx2x_check_half_open_conn(struct link_params *params,
|
||||||
if (REG_RD(bp, mac_base + XMAC_REG_RX_LSS_STATUS))
|
if (REG_RD(bp, mac_base + XMAC_REG_RX_LSS_STATUS))
|
||||||
lss_status = 1;
|
lss_status = 1;
|
||||||
|
|
||||||
bnx2x_analyze_link_error(params, vars, lss_status);
|
bnx2x_analyze_link_error(params, vars, lss_status, notify);
|
||||||
} else if (REG_RD(bp, MISC_REG_RESET_REG_2) &
|
} else if (REG_RD(bp, MISC_REG_RESET_REG_2) &
|
||||||
(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) {
|
(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) {
|
||||||
/* Check E1X / E2 BMAC */
|
/* Check E1X / E2 BMAC */
|
||||||
|
@ -12803,18 +12831,21 @@ static void bnx2x_check_half_open_conn(struct link_params *params,
|
||||||
REG_RD_DMAE(bp, mac_base + lss_status_reg, wb_data, 2);
|
REG_RD_DMAE(bp, mac_base + lss_status_reg, wb_data, 2);
|
||||||
lss_status = (wb_data[0] > 0);
|
lss_status = (wb_data[0] > 0);
|
||||||
|
|
||||||
bnx2x_analyze_link_error(params, vars, lss_status);
|
bnx2x_analyze_link_error(params, vars, lss_status, notify);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
|
void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
|
||||||
{
|
{
|
||||||
struct bnx2x *bp = params->bp;
|
|
||||||
u16 phy_idx;
|
u16 phy_idx;
|
||||||
|
struct bnx2x *bp = params->bp;
|
||||||
for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
|
for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
|
||||||
if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) {
|
if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) {
|
||||||
bnx2x_set_aer_mmd(params, ¶ms->phy[phy_idx]);
|
bnx2x_set_aer_mmd(params, ¶ms->phy[phy_idx]);
|
||||||
bnx2x_check_half_open_conn(params, vars);
|
if (bnx2x_check_half_open_conn(params, vars, 1) !=
|
||||||
|
0)
|
||||||
|
DP(NETIF_MSG_LINK, "Fault detection failed\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,6 +256,7 @@ struct link_params {
|
||||||
#define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY (1<<3)
|
#define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY (1<<3)
|
||||||
#define FEATURE_CONFIG_AUTOGREEEN_ENABLED (1<<9)
|
#define FEATURE_CONFIG_AUTOGREEEN_ENABLED (1<<9)
|
||||||
#define FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED (1<<10)
|
#define FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED (1<<10)
|
||||||
|
#define FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET (1<<11)
|
||||||
/* Will be populated during common init */
|
/* Will be populated during common init */
|
||||||
struct bnx2x_phy phy[MAX_PHYS];
|
struct bnx2x_phy phy[MAX_PHYS];
|
||||||
|
|
||||||
|
@ -495,4 +496,6 @@ int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
|
||||||
|
|
||||||
void bnx2x_period_func(struct link_params *params, struct link_vars *vars);
|
void bnx2x_period_func(struct link_params *params, struct link_vars *vars);
|
||||||
|
|
||||||
|
int bnx2x_check_half_open_conn(struct link_params *params,
|
||||||
|
struct link_vars *vars, u8 notify);
|
||||||
#endif /* BNX2X_LINK_H */
|
#endif /* BNX2X_LINK_H */
|
||||||
|
|
Loading…
Reference in New Issue