aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorYuval Mintz <Yuval.Mintz@qlogic.com>2015-04-01 03:02:19 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-01 12:30:38 -0400
commit3d6b72534a109be4353b161a09a5683b441d0941 (patch)
tree3d56a6519b1e1d8a23a782109c0d36cf89458d79 /drivers/net/ethernet
parent2f30232481ef39aa1657ac76b16c47d0c0241a69 (diff)
bnx2x: Fix kdump on 4-port device
When running in a kdump kernel, it's very likely that due to sync. loss with management firmware the first PCI function to probe and reach the previous unload flow would decide it can reset the chip and continue onward. While doing so, it will only close its own Rx port. On a 4-port device where 2nd port on engine is a 1g-port, the 2nd port would allow ingress traffic after the chip is reset [assuming it was active on the first kernel]. This would later cause a HW attention. This changes driver flow to close both ports' 1g capabilities during the previous driver unload flow prior to the chip reset. 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/ethernet')
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c53
1 files changed, 35 insertions, 18 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index ae571a199f2f..e6dec47fec68 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -129,8 +129,8 @@ struct bnx2x_mac_vals {
129 u32 xmac_val; 129 u32 xmac_val;
130 u32 emac_addr; 130 u32 emac_addr;
131 u32 emac_val; 131 u32 emac_val;
132 u32 umac_addr; 132 u32 umac_addr[2];
133 u32 umac_val; 133 u32 umac_val[2];
134 u32 bmac_addr; 134 u32 bmac_addr;
135 u32 bmac_val[2]; 135 u32 bmac_val[2];
136}; 136};
@@ -10141,6 +10141,25 @@ static u32 bnx2x_get_pretend_reg(struct bnx2x *bp)
10141 return base + (BP_ABS_FUNC(bp)) * stride; 10141 return base + (BP_ABS_FUNC(bp)) * stride;
10142} 10142}
10143 10143
10144static bool bnx2x_prev_unload_close_umac(struct bnx2x *bp,
10145 u8 port, u32 reset_reg,
10146 struct bnx2x_mac_vals *vals)
10147{
10148 u32 mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port;
10149 u32 base_addr;
10150
10151 if (!(mask & reset_reg))
10152 return false;
10153
10154 BNX2X_DEV_INFO("Disable umac Rx %02x\n", port);
10155 base_addr = port ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
10156 vals->umac_addr[port] = base_addr + UMAC_REG_COMMAND_CONFIG;
10157 vals->umac_val[port] = REG_RD(bp, vals->umac_addr[port]);
10158 REG_WR(bp, vals->umac_addr[port], 0);
10159
10160 return true;
10161}
10162
10144static void bnx2x_prev_unload_close_mac(struct bnx2x *bp, 10163static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
10145 struct bnx2x_mac_vals *vals) 10164 struct bnx2x_mac_vals *vals)
10146{ 10165{
@@ -10149,10 +10168,7 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
10149 u8 port = BP_PORT(bp); 10168 u8 port = BP_PORT(bp);
10150 10169
10151 /* reset addresses as they also mark which values were changed */ 10170 /* reset addresses as they also mark which values were changed */
10152 vals->bmac_addr = 0; 10171 memset(vals, 0, sizeof(*vals));
10153 vals->umac_addr = 0;
10154 vals->xmac_addr = 0;
10155 vals->emac_addr = 0;
10156 10172
10157 reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2); 10173 reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2);
10158 10174
@@ -10201,15 +10217,11 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
10201 REG_WR(bp, vals->xmac_addr, 0); 10217 REG_WR(bp, vals->xmac_addr, 0);
10202 mac_stopped = true; 10218 mac_stopped = true;
10203 } 10219 }
10204 mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port; 10220
10205 if (mask & reset_reg) { 10221 mac_stopped |= bnx2x_prev_unload_close_umac(bp, 0,
10206 BNX2X_DEV_INFO("Disable umac Rx\n"); 10222 reset_reg, vals);
10207 base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0; 10223 mac_stopped |= bnx2x_prev_unload_close_umac(bp, 1,
10208 vals->umac_addr = base_addr + UMAC_REG_COMMAND_CONFIG; 10224 reset_reg, vals);
10209 vals->umac_val = REG_RD(bp, vals->umac_addr);
10210 REG_WR(bp, vals->umac_addr, 0);
10211 mac_stopped = true;
10212 }
10213 } 10225 }
10214 10226
10215 if (mac_stopped) 10227 if (mac_stopped)
@@ -10505,8 +10517,11 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
10505 /* Close the MAC Rx to prevent BRB from filling up */ 10517 /* Close the MAC Rx to prevent BRB from filling up */
10506 bnx2x_prev_unload_close_mac(bp, &mac_vals); 10518 bnx2x_prev_unload_close_mac(bp, &mac_vals);
10507 10519
10508 /* close LLH filters towards the BRB */ 10520 /* close LLH filters for both ports towards the BRB */
10521 bnx2x_set_rx_filter(&bp->link_params, 0);
10522 bp->link_params.port ^= 1;
10509 bnx2x_set_rx_filter(&bp->link_params, 0); 10523 bnx2x_set_rx_filter(&bp->link_params, 0);
10524 bp->link_params.port ^= 1;
10510 10525
10511 /* Check if the UNDI driver was previously loaded */ 10526 /* Check if the UNDI driver was previously loaded */
10512 if (bnx2x_prev_is_after_undi(bp)) { 10527 if (bnx2x_prev_is_after_undi(bp)) {
@@ -10553,8 +10568,10 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
10553 10568
10554 if (mac_vals.xmac_addr) 10569 if (mac_vals.xmac_addr)
10555 REG_WR(bp, mac_vals.xmac_addr, mac_vals.xmac_val); 10570 REG_WR(bp, mac_vals.xmac_addr, mac_vals.xmac_val);
10556 if (mac_vals.umac_addr) 10571 if (mac_vals.umac_addr[0])
10557 REG_WR(bp, mac_vals.umac_addr, mac_vals.umac_val); 10572 REG_WR(bp, mac_vals.umac_addr[0], mac_vals.umac_val[0]);
10573 if (mac_vals.umac_addr[1])
10574 REG_WR(bp, mac_vals.umac_addr[1], mac_vals.umac_val[1]);
10558 if (mac_vals.emac_addr) 10575 if (mac_vals.emac_addr)
10559 REG_WR(bp, mac_vals.emac_addr, mac_vals.emac_val); 10576 REG_WR(bp, mac_vals.emac_addr, mac_vals.emac_val);
10560 if (mac_vals.bmac_addr) { 10577 if (mac_vals.bmac_addr) {