mirror of https://gitee.com/openkylin/linux.git
bnx2x: improve stop-on-error
Get better control over interrupts during panic, and allow FW to test outgoing Tx packets when stop-on-error is allowed. Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com> Signed-off-by: Ariel Elior <ariele@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
07ba6af465
commit
823e1d9079
|
@ -123,20 +123,18 @@ do { \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#ifdef BNX2X_STOP_ON_ERROR
|
#ifdef BNX2X_STOP_ON_ERROR
|
||||||
void bnx2x_int_disable(struct bnx2x *bp);
|
|
||||||
#define bnx2x_panic() \
|
#define bnx2x_panic() \
|
||||||
do { \
|
do { \
|
||||||
bp->panic = 1; \
|
bp->panic = 1; \
|
||||||
BNX2X_ERR("driver assert\n"); \
|
BNX2X_ERR("driver assert\n"); \
|
||||||
bnx2x_int_disable(bp); \
|
bnx2x_panic_dump(bp, true); \
|
||||||
bnx2x_panic_dump(bp); \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
#else
|
#else
|
||||||
#define bnx2x_panic() \
|
#define bnx2x_panic() \
|
||||||
do { \
|
do { \
|
||||||
bp->panic = 1; \
|
bp->panic = 1; \
|
||||||
BNX2X_ERR("driver assert\n"); \
|
BNX2X_ERR("driver assert\n"); \
|
||||||
bnx2x_panic_dump(bp); \
|
bnx2x_panic_dump(bp, false); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -3535,13 +3535,17 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
/* when transmitting in a vf, start bd must hold the ethertype
|
/* when transmitting in a vf, start bd must hold the ethertype
|
||||||
* for fw to enforce it
|
* for fw to enforce it
|
||||||
*/
|
*/
|
||||||
|
#ifndef BNX2X_STOP_ON_ERROR
|
||||||
if (IS_VF(bp)) {
|
if (IS_VF(bp)) {
|
||||||
|
#endif
|
||||||
tx_start_bd->vlan_or_ethertype =
|
tx_start_bd->vlan_or_ethertype =
|
||||||
cpu_to_le16(ntohs(eth->h_proto));
|
cpu_to_le16(ntohs(eth->h_proto));
|
||||||
|
#ifndef BNX2X_STOP_ON_ERROR
|
||||||
} else {
|
} else {
|
||||||
/* used by FW for packet accounting */
|
/* used by FW for packet accounting */
|
||||||
tx_start_bd->vlan_or_ethertype = cpu_to_le16(pkt_prod);
|
tx_start_bd->vlan_or_ethertype = cpu_to_le16(pkt_prod);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* turn on parsing and get a BD */
|
/* turn on parsing and get a BD */
|
||||||
|
|
|
@ -479,7 +479,7 @@ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state);
|
||||||
*/
|
*/
|
||||||
void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value);
|
void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value);
|
||||||
/* Error handling */
|
/* Error handling */
|
||||||
void bnx2x_panic_dump(struct bnx2x *bp);
|
void bnx2x_panic_dump(struct bnx2x *bp, bool disable_int);
|
||||||
|
|
||||||
void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl);
|
void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl);
|
||||||
|
|
||||||
|
|
|
@ -2720,10 +2720,6 @@ static void bnx2x_self_test(struct net_device *dev,
|
||||||
buf[2] = 1;
|
buf[2] = 1;
|
||||||
etest->flags |= ETH_TEST_FL_FAILED;
|
etest->flags |= ETH_TEST_FL_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BNX2X_EXTRA_DEBUG
|
|
||||||
bnx2x_panic_dump(bp);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IS_PORT_STAT(i) \
|
#define IS_PORT_STAT(i) \
|
||||||
|
|
|
@ -802,7 +802,71 @@ static void bnx2x_fw_dump(struct bnx2x *bp)
|
||||||
bnx2x_fw_dump_lvl(bp, KERN_ERR);
|
bnx2x_fw_dump_lvl(bp, KERN_ERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bnx2x_panic_dump(struct bnx2x *bp)
|
static void bnx2x_hc_int_disable(struct bnx2x *bp)
|
||||||
|
{
|
||||||
|
int port = BP_PORT(bp);
|
||||||
|
u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
|
||||||
|
u32 val = REG_RD(bp, addr);
|
||||||
|
|
||||||
|
/* in E1 we must use only PCI configuration space to disable
|
||||||
|
* MSI/MSIX capablility
|
||||||
|
* It's forbitten to disable IGU_PF_CONF_MSI_MSIX_EN in HC block
|
||||||
|
*/
|
||||||
|
if (CHIP_IS_E1(bp)) {
|
||||||
|
/* Since IGU_PF_CONF_MSI_MSIX_EN still always on
|
||||||
|
* Use mask register to prevent from HC sending interrupts
|
||||||
|
* after we exit the function
|
||||||
|
*/
|
||||||
|
REG_WR(bp, HC_REG_INT_MASK + port*4, 0);
|
||||||
|
|
||||||
|
val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
|
||||||
|
HC_CONFIG_0_REG_INT_LINE_EN_0 |
|
||||||
|
HC_CONFIG_0_REG_ATTN_BIT_EN_0);
|
||||||
|
} else
|
||||||
|
val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
|
||||||
|
HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 |
|
||||||
|
HC_CONFIG_0_REG_INT_LINE_EN_0 |
|
||||||
|
HC_CONFIG_0_REG_ATTN_BIT_EN_0);
|
||||||
|
|
||||||
|
DP(NETIF_MSG_IFDOWN,
|
||||||
|
"write %x to HC %d (addr 0x%x)\n",
|
||||||
|
val, port, addr);
|
||||||
|
|
||||||
|
/* flush all outstanding writes */
|
||||||
|
mmiowb();
|
||||||
|
|
||||||
|
REG_WR(bp, addr, val);
|
||||||
|
if (REG_RD(bp, addr) != val)
|
||||||
|
BNX2X_ERR("BUG! proper val not read from IGU!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bnx2x_igu_int_disable(struct bnx2x *bp)
|
||||||
|
{
|
||||||
|
u32 val = REG_RD(bp, IGU_REG_PF_CONFIGURATION);
|
||||||
|
|
||||||
|
val &= ~(IGU_PF_CONF_MSI_MSIX_EN |
|
||||||
|
IGU_PF_CONF_INT_LINE_EN |
|
||||||
|
IGU_PF_CONF_ATTN_BIT_EN);
|
||||||
|
|
||||||
|
DP(NETIF_MSG_IFDOWN, "write %x to IGU\n", val);
|
||||||
|
|
||||||
|
/* flush all outstanding writes */
|
||||||
|
mmiowb();
|
||||||
|
|
||||||
|
REG_WR(bp, IGU_REG_PF_CONFIGURATION, val);
|
||||||
|
if (REG_RD(bp, IGU_REG_PF_CONFIGURATION) != val)
|
||||||
|
BNX2X_ERR("BUG! proper val not read from IGU!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bnx2x_int_disable(struct bnx2x *bp)
|
||||||
|
{
|
||||||
|
if (bp->common.int_block == INT_BLOCK_HC)
|
||||||
|
bnx2x_hc_int_disable(bp);
|
||||||
|
else
|
||||||
|
bnx2x_igu_int_disable(bp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bnx2x_panic_dump(struct bnx2x *bp, bool disable_int)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
u16 j;
|
u16 j;
|
||||||
|
@ -812,6 +876,8 @@ void bnx2x_panic_dump(struct bnx2x *bp)
|
||||||
u16 start = 0, end = 0;
|
u16 start = 0, end = 0;
|
||||||
u8 cos;
|
u8 cos;
|
||||||
#endif
|
#endif
|
||||||
|
if (disable_int)
|
||||||
|
bnx2x_int_disable(bp);
|
||||||
|
|
||||||
bp->stats_state = STATS_STATE_DISABLED;
|
bp->stats_state = STATS_STATE_DISABLED;
|
||||||
bp->eth_stats.unrecoverable_error++;
|
bp->eth_stats.unrecoverable_error++;
|
||||||
|
@ -1527,71 +1593,6 @@ void bnx2x_int_enable(struct bnx2x *bp)
|
||||||
bnx2x_igu_int_enable(bp);
|
bnx2x_igu_int_enable(bp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bnx2x_hc_int_disable(struct bnx2x *bp)
|
|
||||||
{
|
|
||||||
int port = BP_PORT(bp);
|
|
||||||
u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
|
|
||||||
u32 val = REG_RD(bp, addr);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* in E1 we must use only PCI configuration space to disable
|
|
||||||
* MSI/MSIX capablility
|
|
||||||
* It's forbitten to disable IGU_PF_CONF_MSI_MSIX_EN in HC block
|
|
||||||
*/
|
|
||||||
if (CHIP_IS_E1(bp)) {
|
|
||||||
/* Since IGU_PF_CONF_MSI_MSIX_EN still always on
|
|
||||||
* Use mask register to prevent from HC sending interrupts
|
|
||||||
* after we exit the function
|
|
||||||
*/
|
|
||||||
REG_WR(bp, HC_REG_INT_MASK + port*4, 0);
|
|
||||||
|
|
||||||
val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
|
|
||||||
HC_CONFIG_0_REG_INT_LINE_EN_0 |
|
|
||||||
HC_CONFIG_0_REG_ATTN_BIT_EN_0);
|
|
||||||
} else
|
|
||||||
val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
|
|
||||||
HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 |
|
|
||||||
HC_CONFIG_0_REG_INT_LINE_EN_0 |
|
|
||||||
HC_CONFIG_0_REG_ATTN_BIT_EN_0);
|
|
||||||
|
|
||||||
DP(NETIF_MSG_IFDOWN,
|
|
||||||
"write %x to HC %d (addr 0x%x)\n",
|
|
||||||
val, port, addr);
|
|
||||||
|
|
||||||
/* flush all outstanding writes */
|
|
||||||
mmiowb();
|
|
||||||
|
|
||||||
REG_WR(bp, addr, val);
|
|
||||||
if (REG_RD(bp, addr) != val)
|
|
||||||
BNX2X_ERR("BUG! proper val not read from IGU!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bnx2x_igu_int_disable(struct bnx2x *bp)
|
|
||||||
{
|
|
||||||
u32 val = REG_RD(bp, IGU_REG_PF_CONFIGURATION);
|
|
||||||
|
|
||||||
val &= ~(IGU_PF_CONF_MSI_MSIX_EN |
|
|
||||||
IGU_PF_CONF_INT_LINE_EN |
|
|
||||||
IGU_PF_CONF_ATTN_BIT_EN);
|
|
||||||
|
|
||||||
DP(NETIF_MSG_IFDOWN, "write %x to IGU\n", val);
|
|
||||||
|
|
||||||
/* flush all outstanding writes */
|
|
||||||
mmiowb();
|
|
||||||
|
|
||||||
REG_WR(bp, IGU_REG_PF_CONFIGURATION, val);
|
|
||||||
if (REG_RD(bp, IGU_REG_PF_CONFIGURATION) != val)
|
|
||||||
BNX2X_ERR("BUG! proper val not read from IGU!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bnx2x_int_disable(struct bnx2x *bp)
|
|
||||||
{
|
|
||||||
if (bp->common.int_block == INT_BLOCK_HC)
|
|
||||||
bnx2x_hc_int_disable(bp);
|
|
||||||
else
|
|
||||||
bnx2x_igu_int_disable(bp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
|
void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
|
||||||
{
|
{
|
||||||
int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
|
int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
|
||||||
|
@ -2945,6 +2946,10 @@ static unsigned long bnx2x_get_common_flags(struct bnx2x *bp,
|
||||||
__set_bit(BNX2X_Q_FLG_ZERO_STATS, &flags);
|
__set_bit(BNX2X_Q_FLG_ZERO_STATS, &flags);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef BNX2X_STOP_ON_ERROR
|
||||||
|
__set_bit(BNX2X_Q_FLG_TX_SEC, &flags);
|
||||||
|
#endif
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4765,7 +4770,7 @@ static int bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid,
|
||||||
|
|
||||||
BNX2X_ERR("got delete ramrod for CNIC CID %d with error!\n",
|
BNX2X_ERR("got delete ramrod for CNIC CID %d with error!\n",
|
||||||
cid);
|
cid);
|
||||||
bnx2x_panic_dump(bp);
|
bnx2x_panic_dump(bp, false);
|
||||||
}
|
}
|
||||||
bnx2x_cnic_cfc_comp(bp, cid, err);
|
bnx2x_cnic_cfc_comp(bp, cid, err);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue