Commit 178135c1 authored by Dmitry Kravkov's avatar Dmitry Kravkov Committed by David S. Miller

bnx2x: Link-flap avoidance in switch dependent mode

As part of the previous unload flow, probed devices will reset the chip
in order to clean the remains of the UNDI driver.
As a result, it's possible for the FW to toggle the link.

This toggling can prove fatal, as long periods without link can cause the
filesystem mount to fail as the storage protocol timeouts. This has been
observed against particular switches with long link re-establishment time.

This patch informs FW during the reset period that the link should not
be toggled - the FW will keep it alive until some interface will load and claim
the link as its own.
Signed-off-by: default avatarDmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: default avatarYuval Mintz <yuvalmin@broadcom.com>
Signed-off-by: default avatarAriel Elior <ariele@broadcom.com>
Signed-off-by: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3521b419
...@@ -1937,6 +1937,8 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, ...@@ -1937,6 +1937,8 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
void bnx2x_update_coalesce(struct bnx2x *bp); void bnx2x_update_coalesce(struct bnx2x *bp);
int bnx2x_get_cur_phy_idx(struct bnx2x *bp); int bnx2x_get_cur_phy_idx(struct bnx2x *bp);
bool bnx2x_port_after_undi(struct bnx2x *bp);
static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms, static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
int wait) int wait)
{ {
......
...@@ -2183,6 +2183,8 @@ static int bnx2x_alloc_fw_stats_mem(struct bnx2x *bp) ...@@ -2183,6 +2183,8 @@ static int bnx2x_alloc_fw_stats_mem(struct bnx2x *bp)
/* send load request to mcp and analyze response */ /* send load request to mcp and analyze response */
static int bnx2x_nic_load_request(struct bnx2x *bp, u32 *load_code) static int bnx2x_nic_load_request(struct bnx2x *bp, u32 *load_code)
{ {
u32 param;
/* init fw_seq */ /* init fw_seq */
bp->fw_seq = bp->fw_seq =
(SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) & (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
...@@ -2195,9 +2197,13 @@ static int bnx2x_nic_load_request(struct bnx2x *bp, u32 *load_code) ...@@ -2195,9 +2197,13 @@ static int bnx2x_nic_load_request(struct bnx2x *bp, u32 *load_code)
DRV_PULSE_SEQ_MASK); DRV_PULSE_SEQ_MASK);
BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq); BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
param = DRV_MSG_CODE_LOAD_REQ_WITH_LFA;
if (IS_MF_SD(bp) && bnx2x_port_after_undi(bp))
param |= DRV_MSG_CODE_LOAD_REQ_FORCE_LFA;
/* load request */ /* load request */
(*load_code) = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, (*load_code) = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, param);
DRV_MSG_CODE_LOAD_REQ_WITH_LFA);
/* if mcp fails to respond we must abort */ /* if mcp fails to respond we must abort */
if (!(*load_code)) { if (!(*load_code)) {
......
...@@ -1323,6 +1323,8 @@ struct drv_func_mb { ...@@ -1323,6 +1323,8 @@ struct drv_func_mb {
#define DRV_MSG_CODE_UNLOAD_SKIP_LINK_RESET 0x00000002 #define DRV_MSG_CODE_UNLOAD_SKIP_LINK_RESET 0x00000002
#define DRV_MSG_CODE_LOAD_REQ_WITH_LFA 0x0000100a #define DRV_MSG_CODE_LOAD_REQ_WITH_LFA 0x0000100a
#define DRV_MSG_CODE_LOAD_REQ_FORCE_LFA 0x00002000
u32 fw_mb_header; u32 fw_mb_header;
#define FW_MSG_CODE_MASK 0xffff0000 #define FW_MSG_CODE_MASK 0xffff0000
#define FW_MSG_CODE_DRV_LOAD_COMMON 0x10100000 #define FW_MSG_CODE_DRV_LOAD_COMMON 0x10100000
......
...@@ -9780,6 +9780,21 @@ static bool bnx2x_prev_is_path_marked(struct bnx2x *bp) ...@@ -9780,6 +9780,21 @@ static bool bnx2x_prev_is_path_marked(struct bnx2x *bp)
return rc; return rc;
} }
bool bnx2x_port_after_undi(struct bnx2x *bp)
{
struct bnx2x_prev_path_list *entry;
bool val;
down(&bnx2x_prev_sem);
entry = bnx2x_prev_path_get_entry(bp);
val = !!(entry && (entry->undi & (1 << BP_PORT(bp))));
up(&bnx2x_prev_sem);
return val;
}
static int bnx2x_prev_mark_path(struct bnx2x *bp, bool after_undi) static int bnx2x_prev_mark_path(struct bnx2x *bp, bool after_undi)
{ {
struct bnx2x_prev_path_list *tmp_list; struct bnx2x_prev_path_list *tmp_list;
...@@ -10036,7 +10051,6 @@ static int bnx2x_prev_unload(struct bnx2x *bp) ...@@ -10036,7 +10051,6 @@ static int bnx2x_prev_unload(struct bnx2x *bp)
{ {
int time_counter = 10; int time_counter = 10;
u32 rc, fw, hw_lock_reg, hw_lock_val; u32 rc, fw, hw_lock_reg, hw_lock_val;
struct bnx2x_prev_path_list *prev_list;
BNX2X_DEV_INFO("Entering Previous Unload Flow\n"); BNX2X_DEV_INFO("Entering Previous Unload Flow\n");
/* clear hw from errors which may have resulted from an interrupted /* clear hw from errors which may have resulted from an interrupted
...@@ -10107,8 +10121,7 @@ static int bnx2x_prev_unload(struct bnx2x *bp) ...@@ -10107,8 +10121,7 @@ static int bnx2x_prev_unload(struct bnx2x *bp)
} }
/* Mark function if its port was used to boot from SAN */ /* Mark function if its port was used to boot from SAN */
prev_list = bnx2x_prev_path_get_entry(bp); if (bnx2x_port_after_undi(bp))
if (prev_list && (prev_list->undi & (1 << BP_PORT(bp))))
bp->link_params.feature_config_flags |= bp->link_params.feature_config_flags |=
FEATURE_CONFIG_BOOT_FROM_SAN; FEATURE_CONFIG_BOOT_FROM_SAN;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment