aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorYuval Mintz <Yuval.Mintz@qlogic.com>2014-08-18 15:36:23 -0400
committerDavid S. Miller <davem@davemloft.net>2014-08-21 20:54:43 -0400
commit7c3afd85dc1610bb2fc049644cd1b52c7af96f98 (patch)
treed741463badad3cd50fe32ccac568a8b2535e6311 /drivers/net
parent9a6d33c30790d9eb1143aae4e5d8bbe5fc5d8570 (diff)
bnx2x: Revert UNDI flushing mechanism
Commit 91ebb929b6f8 ("bnx2x: Add support for Multi-Function UNDI") [which was later supposedly fixed by de682941eef3 ("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>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c92
1 files changed, 17 insertions, 75 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index c13364b6cc19..900cab420810 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -10052,6 +10052,8 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
10052} 10052}
10053 10053
10054#define BNX2X_PREV_UNDI_PROD_ADDR(p) (BAR_TSTRORM_INTMEM + 0x1508 + ((p) << 4)) 10054#define BNX2X_PREV_UNDI_PROD_ADDR(p) (BAR_TSTRORM_INTMEM + 0x1508 + ((p) << 4))
10055#define BNX2X_PREV_UNDI_PROD_ADDR_H(f) (BAR_TSTRORM_INTMEM + \
10056 0x1848 + ((f) << 4))
10055#define BNX2X_PREV_UNDI_RCQ(val) ((val) & 0xffff) 10057#define BNX2X_PREV_UNDI_RCQ(val) ((val) & 0xffff)
10056#define BNX2X_PREV_UNDI_BD(val) ((val) >> 16 & 0xffff) 10058#define BNX2X_PREV_UNDI_BD(val) ((val) >> 16 & 0xffff)
10057#define BNX2X_PREV_UNDI_PROD(rcq, bd) ((bd) << 16 | (rcq)) 10059#define BNX2X_PREV_UNDI_PROD(rcq, bd) ((bd) << 16 | (rcq))
@@ -10059,8 +10061,6 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
10059#define BCM_5710_UNDI_FW_MF_MAJOR (0x07) 10061#define BCM_5710_UNDI_FW_MF_MAJOR (0x07)
10060#define BCM_5710_UNDI_FW_MF_MINOR (0x08) 10062#define BCM_5710_UNDI_FW_MF_MINOR (0x08)
10061#define BCM_5710_UNDI_FW_MF_VERS (0x05) 10063#define BCM_5710_UNDI_FW_MF_VERS (0x05)
10062#define BNX2X_PREV_UNDI_MF_PORT(p) (BAR_TSTRORM_INTMEM + 0x150c + ((p) << 4))
10063#define BNX2X_PREV_UNDI_MF_FUNC(f) (BAR_TSTRORM_INTMEM + 0x184c + ((f) << 4))
10064 10064
10065static bool bnx2x_prev_is_after_undi(struct bnx2x *bp) 10065static bool bnx2x_prev_is_after_undi(struct bnx2x *bp)
10066{ 10066{
@@ -10079,72 +10079,25 @@ static bool bnx2x_prev_is_after_undi(struct bnx2x *bp)
10079 return false; 10079 return false;
10080} 10080}
10081 10081
10082static bool bnx2x_prev_unload_undi_fw_supports_mf(struct bnx2x *bp) 10082static void bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 inc)
10083{
10084 u8 major, minor, version;
10085 u32 fw;
10086
10087 /* Must check that FW is loaded */
10088 if (!(REG_RD(bp, MISC_REG_RESET_REG_1) &
10089 MISC_REGISTERS_RESET_REG_1_RST_XSEM)) {
10090 BNX2X_DEV_INFO("XSEM is reset - UNDI MF FW is not loaded\n");
10091 return false;
10092 }
10093
10094 /* Read Currently loaded FW version */
10095 fw = REG_RD(bp, XSEM_REG_PRAM);
10096 major = fw & 0xff;
10097 minor = (fw >> 0x8) & 0xff;
10098 version = (fw >> 0x10) & 0xff;
10099 BNX2X_DEV_INFO("Loaded FW: 0x%08x: Major 0x%02x Minor 0x%02x Version 0x%02x\n",
10100 fw, major, minor, version);
10101
10102 if (major > BCM_5710_UNDI_FW_MF_MAJOR)
10103 return true;
10104
10105 if ((major == BCM_5710_UNDI_FW_MF_MAJOR) &&
10106 (minor > BCM_5710_UNDI_FW_MF_MINOR))
10107 return true;
10108
10109 if ((major == BCM_5710_UNDI_FW_MF_MAJOR) &&
10110 (minor == BCM_5710_UNDI_FW_MF_MINOR) &&
10111 (version >= BCM_5710_UNDI_FW_MF_VERS))
10112 return true;
10113
10114 return false;
10115}
10116
10117static void bnx2x_prev_unload_undi_mf(struct bnx2x *bp)
10118{
10119 int i;
10120
10121 /* Due to legacy (FW) code, the first function on each engine has a
10122 * different offset macro from the rest of the functions.
10123 * Setting this for all 8 functions is harmless regardless of whether
10124 * this is actually a multi-function device.
10125 */
10126 for (i = 0; i < 2; i++)
10127 REG_WR(bp, BNX2X_PREV_UNDI_MF_PORT(i), 1);
10128
10129 for (i = 2; i < 8; i++)
10130 REG_WR(bp, BNX2X_PREV_UNDI_MF_FUNC(i - 2), 1);
10131
10132 BNX2X_DEV_INFO("UNDI FW (MF) set to discard\n");
10133}
10134
10135static void bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port, u8 inc)
10136{ 10083{
10137 u16 rcq, bd; 10084 u16 rcq, bd;
10138 u32 tmp_reg = REG_RD(bp, BNX2X_PREV_UNDI_PROD_ADDR(port)); 10085 u32 addr, tmp_reg;
10139 10086
10087 if (BP_FUNC(bp) < 2)
10088 addr = BNX2X_PREV_UNDI_PROD_ADDR(BP_PORT(bp));
10089 else
10090 addr = BNX2X_PREV_UNDI_PROD_ADDR_H(BP_FUNC(bp) - 2);
10091
10092 tmp_reg = REG_RD(bp, addr);
10140 rcq = BNX2X_PREV_UNDI_RCQ(tmp_reg) + inc; 10093 rcq = BNX2X_PREV_UNDI_RCQ(tmp_reg) + inc;
10141 bd = BNX2X_PREV_UNDI_BD(tmp_reg) + inc; 10094 bd = BNX2X_PREV_UNDI_BD(tmp_reg) + inc;
10142 10095
10143 tmp_reg = BNX2X_PREV_UNDI_PROD(rcq, bd); 10096 tmp_reg = BNX2X_PREV_UNDI_PROD(rcq, bd);
10144 REG_WR(bp, BNX2X_PREV_UNDI_PROD_ADDR(port), tmp_reg); 10097 REG_WR(bp, addr, tmp_reg);
10145 10098
10146 BNX2X_DEV_INFO("UNDI producer [%d] rings bd -> 0x%04x, rcq -> 0x%04x\n", 10099 BNX2X_DEV_INFO("UNDI producer [%d/%d][%08x] rings bd -> 0x%04x, rcq -> 0x%04x\n",
10147 port, bd, rcq); 10100 BP_PORT(bp), BP_FUNC(bp), addr, bd, rcq);
10148} 10101}
10149 10102
10150static int bnx2x_prev_mcp_done(struct bnx2x *bp) 10103static int bnx2x_prev_mcp_done(struct bnx2x *bp)
@@ -10383,7 +10336,6 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
10383 /* Reset should be performed after BRB is emptied */ 10336 /* Reset should be performed after BRB is emptied */
10384 if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) { 10337 if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) {
10385 u32 timer_count = 1000; 10338 u32 timer_count = 1000;
10386 bool need_write = true;
10387 10339
10388 /* Close the MAC Rx to prevent BRB from filling up */ 10340 /* Close the MAC Rx to prevent BRB from filling up */
10389 bnx2x_prev_unload_close_mac(bp, &mac_vals); 10341 bnx2x_prev_unload_close_mac(bp, &mac_vals);
@@ -10420,20 +10372,10 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
10420 else 10372 else
10421 timer_count--; 10373 timer_count--;
10422 10374
10423 /* New UNDI FW supports MF and contains better 10375 /* If UNDI resides in memory, manually increment it */
10424 * cleaning methods - might be redundant but harmless. 10376 if (prev_undi)
10425 */ 10377 bnx2x_prev_unload_undi_inc(bp, 1);
10426 if (bnx2x_prev_unload_undi_fw_supports_mf(bp)) { 10378
10427 if (need_write) {
10428 bnx2x_prev_unload_undi_mf(bp);
10429 need_write = false;
10430 }
10431 } else if (prev_undi) {
10432 /* If UNDI resides in memory,
10433 * manually increment it
10434 */
10435 bnx2x_prev_unload_undi_inc(bp, BP_PORT(bp), 1);
10436 }
10437 udelay(10); 10379 udelay(10);
10438 } 10380 }
10439 10381