bnx2x: Revert UNDI flushing mechanism

Commit 91ebb929b6 ("bnx2x: Add support for Multi-Function UNDI") [which was
later supposedly fixed by de682941ee ("bnx2x: Fix UNDI driver unload")]
introduced a bug in which in some [yet-to-be-determined] scenarios the
alternative flushing mechanism which was to guarantee the Rx buffers are
empty before resetting them during device probe will fail.
If this happens, when device will be loaded once more a fatal attention will
occur; Since this most likely happens in boot from SAN scenarios, the machine
will fail to load.

Notice this may occur not only in the 'Multi-Function' scenario but in the
regular scenario as well, i.e., this introduced a regression in the driver's
ability to perform boot from SAN.

The patch reverts the mechanism and applies the old scheme to multi-function
devices as well as to single-function devices.

Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: Ariel Elior <Ariel.Elior@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Yuval Mintz 2014-08-18 22:36:23 +03:00 committed by David S. Miller
parent 9a6d33c307
commit 7c3afd85dc
1 changed files with 17 additions and 75 deletions

View File

@ -10052,6 +10052,8 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
}
#define BNX2X_PREV_UNDI_PROD_ADDR(p) (BAR_TSTRORM_INTMEM + 0x1508 + ((p) << 4))
#define BNX2X_PREV_UNDI_PROD_ADDR_H(f) (BAR_TSTRORM_INTMEM + \
0x1848 + ((f) << 4))
#define BNX2X_PREV_UNDI_RCQ(val) ((val) & 0xffff)
#define BNX2X_PREV_UNDI_BD(val) ((val) >> 16 & 0xffff)
#define BNX2X_PREV_UNDI_PROD(rcq, bd) ((bd) << 16 | (rcq))
@ -10059,8 +10061,6 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
#define BCM_5710_UNDI_FW_MF_MAJOR (0x07)
#define BCM_5710_UNDI_FW_MF_MINOR (0x08)
#define BCM_5710_UNDI_FW_MF_VERS (0x05)
#define BNX2X_PREV_UNDI_MF_PORT(p) (BAR_TSTRORM_INTMEM + 0x150c + ((p) << 4))
#define BNX2X_PREV_UNDI_MF_FUNC(f) (BAR_TSTRORM_INTMEM + 0x184c + ((f) << 4))
static bool bnx2x_prev_is_after_undi(struct bnx2x *bp)
{
@ -10079,72 +10079,25 @@ static bool bnx2x_prev_is_after_undi(struct bnx2x *bp)
return false;
}
static bool bnx2x_prev_unload_undi_fw_supports_mf(struct bnx2x *bp)
{
u8 major, minor, version;
u32 fw;
/* Must check that FW is loaded */
if (!(REG_RD(bp, MISC_REG_RESET_REG_1) &
MISC_REGISTERS_RESET_REG_1_RST_XSEM)) {
BNX2X_DEV_INFO("XSEM is reset - UNDI MF FW is not loaded\n");
return false;
}
/* Read Currently loaded FW version */
fw = REG_RD(bp, XSEM_REG_PRAM);
major = fw & 0xff;
minor = (fw >> 0x8) & 0xff;
version = (fw >> 0x10) & 0xff;
BNX2X_DEV_INFO("Loaded FW: 0x%08x: Major 0x%02x Minor 0x%02x Version 0x%02x\n",
fw, major, minor, version);
if (major > BCM_5710_UNDI_FW_MF_MAJOR)
return true;
if ((major == BCM_5710_UNDI_FW_MF_MAJOR) &&
(minor > BCM_5710_UNDI_FW_MF_MINOR))
return true;
if ((major == BCM_5710_UNDI_FW_MF_MAJOR) &&
(minor == BCM_5710_UNDI_FW_MF_MINOR) &&
(version >= BCM_5710_UNDI_FW_MF_VERS))
return true;
return false;
}
static void bnx2x_prev_unload_undi_mf(struct bnx2x *bp)
{
int i;
/* Due to legacy (FW) code, the first function on each engine has a
* different offset macro from the rest of the functions.
* Setting this for all 8 functions is harmless regardless of whether
* this is actually a multi-function device.
*/
for (i = 0; i < 2; i++)
REG_WR(bp, BNX2X_PREV_UNDI_MF_PORT(i), 1);
for (i = 2; i < 8; i++)
REG_WR(bp, BNX2X_PREV_UNDI_MF_FUNC(i - 2), 1);
BNX2X_DEV_INFO("UNDI FW (MF) set to discard\n");
}
static void bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port, u8 inc)
static void bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 inc)
{
u16 rcq, bd;
u32 tmp_reg = REG_RD(bp, BNX2X_PREV_UNDI_PROD_ADDR(port));
u32 addr, tmp_reg;
if (BP_FUNC(bp) < 2)
addr = BNX2X_PREV_UNDI_PROD_ADDR(BP_PORT(bp));
else
addr = BNX2X_PREV_UNDI_PROD_ADDR_H(BP_FUNC(bp) - 2);
tmp_reg = REG_RD(bp, addr);
rcq = BNX2X_PREV_UNDI_RCQ(tmp_reg) + inc;
bd = BNX2X_PREV_UNDI_BD(tmp_reg) + inc;
tmp_reg = BNX2X_PREV_UNDI_PROD(rcq, bd);
REG_WR(bp, BNX2X_PREV_UNDI_PROD_ADDR(port), tmp_reg);
REG_WR(bp, addr, tmp_reg);
BNX2X_DEV_INFO("UNDI producer [%d] rings bd -> 0x%04x, rcq -> 0x%04x\n",
port, bd, rcq);
BNX2X_DEV_INFO("UNDI producer [%d/%d][%08x] rings bd -> 0x%04x, rcq -> 0x%04x\n",
BP_PORT(bp), BP_FUNC(bp), addr, bd, rcq);
}
static int bnx2x_prev_mcp_done(struct bnx2x *bp)
@ -10383,7 +10336,6 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
/* Reset should be performed after BRB is emptied */
if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) {
u32 timer_count = 1000;
bool need_write = true;
/* Close the MAC Rx to prevent BRB from filling up */
bnx2x_prev_unload_close_mac(bp, &mac_vals);
@ -10420,20 +10372,10 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
else
timer_count--;
/* New UNDI FW supports MF and contains better
* cleaning methods - might be redundant but harmless.
*/
if (bnx2x_prev_unload_undi_fw_supports_mf(bp)) {
if (need_write) {
bnx2x_prev_unload_undi_mf(bp);
need_write = false;
}
} else if (prev_undi) {
/* If UNDI resides in memory,
* manually increment it
*/
bnx2x_prev_unload_undi_inc(bp, BP_PORT(bp), 1);
}
/* If UNDI resides in memory, manually increment it */
if (prev_undi)
bnx2x_prev_unload_undi_inc(bp, 1);
udelay(10);
}