Commit c63da990 authored by Barak Witkowski's avatar Barak Witkowski Committed by David S. Miller

bnx2x: Prevent link flaps when booting from SAN.

It is possible that the driver is configured to operate with a certain
link configuration which differs from the link's configuration during
boot from SAN - this would cause the driver to flap the link.

Said flap may be missed by specific switches, causing dcbx convergence
to be too long and boot sequence to fail. Convergence is longer because
switch ignores new dcbx packets due to counters mismatch, as only host
side reset the counters due to the link flap.

This patch causes the driver to ignore user's initial configuration during
boot from SAN, and continues with the existing link configuration.
Signed-off-by: default avatarBarak Witkowski <barak@broadcom.com>
Signed-off-by: default avatarYuval Mintz <yuvalmin@broadcom.com>
Signed-off-by: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6ded7cd6
...@@ -1186,6 +1186,7 @@ struct bnx2x_prev_path_list { ...@@ -1186,6 +1186,7 @@ struct bnx2x_prev_path_list {
u8 slot; u8 slot;
u8 path; u8 path;
struct list_head list; struct list_head list;
u8 undi;
}; };
struct bnx2x_sp_objs { struct bnx2x_sp_objs {
......
...@@ -2396,6 +2396,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) ...@@ -2396,6 +2396,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
if (bp->port.pmf) if (bp->port.pmf)
bnx2x_initial_phy_init(bp, load_mode); bnx2x_initial_phy_init(bp, load_mode);
bp->link_params.feature_config_flags &= ~FEATURE_CONFIG_BOOT_FROM_SAN;
/* Start fast path */ /* Start fast path */
......
...@@ -254,6 +254,12 @@ static int bnx2x_check_lfa(struct link_params *params) ...@@ -254,6 +254,12 @@ static int bnx2x_check_lfa(struct link_params *params)
if (!(link_status & LINK_STATUS_LINK_UP)) if (!(link_status & LINK_STATUS_LINK_UP))
return LFA_LINK_DOWN; return LFA_LINK_DOWN;
/* if loaded after BOOT from SAN, don't flap the link in any case and
* rely on link set by preboot driver
*/
if (params->feature_config_flags & FEATURE_CONFIG_BOOT_FROM_SAN)
return 0;
/* Verify that loopback mode is not set */ /* Verify that loopback mode is not set */
if (params->loopback_mode) if (params->loopback_mode)
return LFA_LOOPBACK_ENABLED; return LFA_LOOPBACK_ENABLED;
......
...@@ -267,6 +267,7 @@ struct link_params { ...@@ -267,6 +267,7 @@ struct link_params {
#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) #define FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET (1<<11)
#define FEATURE_CONFIG_MT_SUPPORT (1<<13) #define FEATURE_CONFIG_MT_SUPPORT (1<<13)
#define FEATURE_CONFIG_BOOT_FROM_SAN (1<<14)
/* Will be populated during common init */ /* Will be populated during common init */
struct bnx2x_phy phy[MAX_PHYS]; struct bnx2x_phy phy[MAX_PHYS];
......
...@@ -9515,6 +9515,20 @@ static int bnx2x_prev_mcp_done(struct bnx2x *bp) ...@@ -9515,6 +9515,20 @@ static int bnx2x_prev_mcp_done(struct bnx2x *bp)
return 0; return 0;
} }
static struct bnx2x_prev_path_list *
bnx2x_prev_path_get_entry(struct bnx2x *bp)
{
struct bnx2x_prev_path_list *tmp_list;
list_for_each_entry(tmp_list, &bnx2x_prev_list, list)
if (PCI_SLOT(bp->pdev->devfn) == tmp_list->slot &&
bp->pdev->bus->number == tmp_list->bus &&
BP_PATH(bp) == tmp_list->path)
return tmp_list;
return NULL;
}
static bool bnx2x_prev_is_path_marked(struct bnx2x *bp) static bool bnx2x_prev_is_path_marked(struct bnx2x *bp)
{ {
struct bnx2x_prev_path_list *tmp_list; struct bnx2x_prev_path_list *tmp_list;
...@@ -9539,7 +9553,7 @@ static bool bnx2x_prev_is_path_marked(struct bnx2x *bp) ...@@ -9539,7 +9553,7 @@ static bool bnx2x_prev_is_path_marked(struct bnx2x *bp)
return rc; return rc;
} }
static int bnx2x_prev_mark_path(struct bnx2x *bp) 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;
int rc; int rc;
...@@ -9553,6 +9567,7 @@ static int bnx2x_prev_mark_path(struct bnx2x *bp) ...@@ -9553,6 +9567,7 @@ static int bnx2x_prev_mark_path(struct bnx2x *bp)
tmp_list->bus = bp->pdev->bus->number; tmp_list->bus = bp->pdev->bus->number;
tmp_list->slot = PCI_SLOT(bp->pdev->devfn); tmp_list->slot = PCI_SLOT(bp->pdev->devfn);
tmp_list->path = BP_PATH(bp); tmp_list->path = BP_PATH(bp);
tmp_list->undi = after_undi ? (1 << BP_PORT(bp)) : 0;
rc = down_interruptible(&bnx2x_prev_sem); rc = down_interruptible(&bnx2x_prev_sem);
if (rc) { if (rc) {
...@@ -9649,6 +9664,7 @@ static int bnx2x_prev_unload_uncommon(struct bnx2x *bp) ...@@ -9649,6 +9664,7 @@ static int bnx2x_prev_unload_uncommon(struct bnx2x *bp)
static int bnx2x_prev_unload_common(struct bnx2x *bp) static int bnx2x_prev_unload_common(struct bnx2x *bp)
{ {
u32 reset_reg, tmp_reg = 0, rc; u32 reset_reg, tmp_reg = 0, rc;
bool prev_undi = false;
/* It is possible a previous function received 'common' answer, /* It is possible a previous function received 'common' answer,
* but hasn't loaded yet, therefore creating a scenario of * but hasn't loaded yet, therefore creating a scenario of
* multiple functions receiving 'common' on the same path. * multiple functions receiving 'common' on the same path.
...@@ -9663,7 +9679,6 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) ...@@ -9663,7 +9679,6 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
/* Reset should be performed after BRB is emptied */ /* Reset should be performed after BRB is emptied */
if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) { if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) {
u32 timer_count = 1000; u32 timer_count = 1000;
bool prev_undi = false;
/* Close the MAC Rx to prevent BRB from filling up */ /* Close the MAC Rx to prevent BRB from filling up */
bnx2x_prev_unload_close_mac(bp); bnx2x_prev_unload_close_mac(bp);
...@@ -9713,7 +9728,7 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) ...@@ -9713,7 +9728,7 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
/* No packets are in the pipeline, path is ready for reset */ /* No packets are in the pipeline, path is ready for reset */
bnx2x_reset_common(bp); bnx2x_reset_common(bp);
rc = bnx2x_prev_mark_path(bp); rc = bnx2x_prev_mark_path(bp, prev_undi);
if (rc) { if (rc) {
bnx2x_prev_mcp_done(bp); bnx2x_prev_mcp_done(bp);
return rc; return rc;
...@@ -9745,6 +9760,7 @@ static int bnx2x_prev_unload(struct bnx2x *bp) ...@@ -9745,6 +9760,7 @@ 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
...@@ -9803,6 +9819,12 @@ static int bnx2x_prev_unload(struct bnx2x *bp) ...@@ -9803,6 +9819,12 @@ static int bnx2x_prev_unload(struct bnx2x *bp)
rc = -EBUSY; rc = -EBUSY;
} }
/* Mark function if its port was used to boot from SAN */
prev_list = bnx2x_prev_path_get_entry(bp);
if (prev_list && (prev_list->undi & (1 << BP_PORT(bp))))
bp->link_params.feature_config_flags |=
FEATURE_CONFIG_BOOT_FROM_SAN;
BNX2X_DEV_INFO("Finished Previous Unload Flow [%d]\n", rc); BNX2X_DEV_INFO("Finished Previous Unload Flow [%d]\n", rc);
return rc; return rc;
......
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