bnx2x: improve stop-on-error
authorYuval Mintz <yuvalmin@broadcom.com>
Mon, 14 Jan 2013 05:11:47 +0000 (05:11 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 15 Jan 2013 20:07:59 +0000 (15:07 -0500)
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>
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c

index 309bbb70cf7fa8c65c82ad2c7f5963ca55457313..757fe2c843d81dd8eb3224ad1c5ef9871a72b781 100644 (file)
@@ -123,20 +123,18 @@ do {                                                               \
 } while (0)
 
 #ifdef BNX2X_STOP_ON_ERROR
-void bnx2x_int_disable(struct bnx2x *bp);
 #define bnx2x_panic()                          \
 do {                                           \
        bp->panic = 1;                          \
        BNX2X_ERR("driver assert\n");           \
-       bnx2x_int_disable(bp);                  \
-       bnx2x_panic_dump(bp);                   \
+       bnx2x_panic_dump(bp, true);             \
 } while (0)
 #else
 #define bnx2x_panic()                          \
 do {                                           \
        bp->panic = 1;                          \
        BNX2X_ERR("driver assert\n");           \
-       bnx2x_panic_dump(bp);                   \
+       bnx2x_panic_dump(bp, false);            \
 } while (0)
 #endif
 
index 6312e636e37bdd1ea544ccb4650b0701907bd597..5409b303a69b5bb1205dc345574a6d036621aeb4 100644 (file)
@@ -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
                 * for fw to enforce it
                 */
+#ifndef BNX2X_STOP_ON_ERROR
                if (IS_VF(bp)) {
+#endif
                        tx_start_bd->vlan_or_ethertype =
                                cpu_to_le16(ntohs(eth->h_proto));
+#ifndef BNX2X_STOP_ON_ERROR
                } else {
                        /* used by FW for packet accounting */
                        tx_start_bd->vlan_or_ethertype = cpu_to_le16(pkt_prod);
                }
+#endif
        }
 
        /* turn on parsing and get a BD */
index a2583f2c935dd58e05e2adb9407ba8c869d88b42..8104b986037be5d8981c1fe1ee476b2f9308c988 100644 (file)
@@ -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);
 /* 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);
 
index 9c9fe0e491179d44795e7b420b973beac3428092..d3b0429d62a029fd9406c94399a1ef0f2e238da0 100644 (file)
@@ -2720,10 +2720,6 @@ static void bnx2x_self_test(struct net_device *dev,
                        buf[2] = 1;
                etest->flags |= ETH_TEST_FL_FAILED;
        }
-
-#ifdef BNX2X_EXTRA_DEBUG
-       bnx2x_panic_dump(bp);
-#endif
 }
 
 #define IS_PORT_STAT(i) \
index f4d4896d71f33e60fc5fcff719bd80af9b47f99c..b4838510f3da7e04a9d895592ecf9a675193333d 100644 (file)
@@ -802,7 +802,71 @@ static void bnx2x_fw_dump(struct bnx2x *bp)
        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;
        u16 j;
@@ -812,6 +876,8 @@ void bnx2x_panic_dump(struct bnx2x *bp)
        u16 start = 0, end = 0;
        u8 cos;
 #endif
+       if (disable_int)
+               bnx2x_int_disable(bp);
 
        bp->stats_state = STATS_STATE_DISABLED;
        bp->eth_stats.unrecoverable_error++;
@@ -1527,71 +1593,6 @@ void bnx2x_int_enable(struct bnx2x *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)
 {
        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);
 
 
+#ifdef BNX2X_STOP_ON_ERROR
+       __set_bit(BNX2X_Q_FLG_TX_SEC, &flags);
+#endif
+
        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",
                          cid);
-               bnx2x_panic_dump(bp);
+               bnx2x_panic_dump(bp, false);
        }
        bnx2x_cnic_cfc_comp(bp, cid, err);
        return 0;