提交 3d6b7253 编写于 作者: Y Yuval Mintz 提交者: David S. Miller

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: NYuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: NAriel Elior <Ariel.Elior@qlogic.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 2f302324
...@@ -129,8 +129,8 @@ struct bnx2x_mac_vals { ...@@ -129,8 +129,8 @@ struct bnx2x_mac_vals {
u32 xmac_val; u32 xmac_val;
u32 emac_addr; u32 emac_addr;
u32 emac_val; u32 emac_val;
u32 umac_addr; u32 umac_addr[2];
u32 umac_val; u32 umac_val[2];
u32 bmac_addr; u32 bmac_addr;
u32 bmac_val[2]; u32 bmac_val[2];
}; };
...@@ -10141,6 +10141,25 @@ static u32 bnx2x_get_pretend_reg(struct bnx2x *bp) ...@@ -10141,6 +10141,25 @@ static u32 bnx2x_get_pretend_reg(struct bnx2x *bp)
return base + (BP_ABS_FUNC(bp)) * stride; return base + (BP_ABS_FUNC(bp)) * stride;
} }
static bool bnx2x_prev_unload_close_umac(struct bnx2x *bp,
u8 port, u32 reset_reg,
struct bnx2x_mac_vals *vals)
{
u32 mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port;
u32 base_addr;
if (!(mask & reset_reg))
return false;
BNX2X_DEV_INFO("Disable umac Rx %02x\n", port);
base_addr = port ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
vals->umac_addr[port] = base_addr + UMAC_REG_COMMAND_CONFIG;
vals->umac_val[port] = REG_RD(bp, vals->umac_addr[port]);
REG_WR(bp, vals->umac_addr[port], 0);
return true;
}
static void bnx2x_prev_unload_close_mac(struct bnx2x *bp, static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
struct bnx2x_mac_vals *vals) struct bnx2x_mac_vals *vals)
{ {
...@@ -10149,10 +10168,7 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp, ...@@ -10149,10 +10168,7 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
u8 port = BP_PORT(bp); u8 port = BP_PORT(bp);
/* reset addresses as they also mark which values were changed */ /* reset addresses as they also mark which values were changed */
vals->bmac_addr = 0; memset(vals, 0, sizeof(*vals));
vals->umac_addr = 0;
vals->xmac_addr = 0;
vals->emac_addr = 0;
reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2); reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2);
...@@ -10201,15 +10217,11 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp, ...@@ -10201,15 +10217,11 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
REG_WR(bp, vals->xmac_addr, 0); REG_WR(bp, vals->xmac_addr, 0);
mac_stopped = true; mac_stopped = true;
} }
mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port;
if (mask & reset_reg) { mac_stopped |= bnx2x_prev_unload_close_umac(bp, 0,
BNX2X_DEV_INFO("Disable umac Rx\n"); reset_reg, vals);
base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0; mac_stopped |= bnx2x_prev_unload_close_umac(bp, 1,
vals->umac_addr = base_addr + UMAC_REG_COMMAND_CONFIG; reset_reg, vals);
vals->umac_val = REG_RD(bp, vals->umac_addr);
REG_WR(bp, vals->umac_addr, 0);
mac_stopped = true;
}
} }
if (mac_stopped) if (mac_stopped)
...@@ -10505,8 +10517,11 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) ...@@ -10505,8 +10517,11 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
/* 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, &mac_vals); bnx2x_prev_unload_close_mac(bp, &mac_vals);
/* close LLH filters towards the BRB */ /* close LLH filters for both ports towards the BRB */
bnx2x_set_rx_filter(&bp->link_params, 0);
bp->link_params.port ^= 1;
bnx2x_set_rx_filter(&bp->link_params, 0); bnx2x_set_rx_filter(&bp->link_params, 0);
bp->link_params.port ^= 1;
/* Check if the UNDI driver was previously loaded */ /* Check if the UNDI driver was previously loaded */
if (bnx2x_prev_is_after_undi(bp)) { if (bnx2x_prev_is_after_undi(bp)) {
...@@ -10553,8 +10568,10 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) ...@@ -10553,8 +10568,10 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
if (mac_vals.xmac_addr) if (mac_vals.xmac_addr)
REG_WR(bp, mac_vals.xmac_addr, mac_vals.xmac_val); REG_WR(bp, mac_vals.xmac_addr, mac_vals.xmac_val);
if (mac_vals.umac_addr) if (mac_vals.umac_addr[0])
REG_WR(bp, mac_vals.umac_addr, mac_vals.umac_val); REG_WR(bp, mac_vals.umac_addr[0], mac_vals.umac_val[0]);
if (mac_vals.umac_addr[1])
REG_WR(bp, mac_vals.umac_addr[1], mac_vals.umac_val[1]);
if (mac_vals.emac_addr) if (mac_vals.emac_addr)
REG_WR(bp, mac_vals.emac_addr, mac_vals.emac_val); REG_WR(bp, mac_vals.emac_addr, mac_vals.emac_val);
if (mac_vals.bmac_addr) { if (mac_vals.bmac_addr) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册