bnx2: Fix reset bug on 5709
authorEddie Wai <waie@broadcom.com>
Wed, 24 Nov 2010 13:48:54 +0000 (13:48 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sun, 28 Nov 2010 18:47:19 +0000 (10:47 -0800)
The 5709 chip requires the BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE bit to be
cleared and polling for pending DMAs to complete before chip reset.
Without this step, we've seen NMIs during repeated resets of the chip.

Signed-off-by: Eddie Wai <waie@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/bnx2.c
drivers/net/bnx2.h

index 0de196da4d4a4d5f3906b24c61abe910ba1040e5..78f91ef44969ab9db8cf8d8c112c2ac7c9ece7c5 100644 (file)
@@ -4640,13 +4640,28 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
 
        /* Wait for the current PCI transaction to complete before
         * issuing a reset. */
-       REG_WR(bp, BNX2_MISC_ENABLE_CLR_BITS,
-              BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
-              BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
-              BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
-              BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
-       val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS);
-       udelay(5);
+       if ((CHIP_NUM(bp) == CHIP_NUM_5706) ||
+           (CHIP_NUM(bp) == CHIP_NUM_5708)) {
+               REG_WR(bp, BNX2_MISC_ENABLE_CLR_BITS,
+                      BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
+                      BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
+                      BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
+                      BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
+               val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS);
+               udelay(5);
+       } else {  /* 5709 */
+               val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
+               val &= ~BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE;
+               REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
+               val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
+
+               for (i = 0; i < 100; i++) {
+                       msleep(1);
+                       val = REG_RD(bp, BNX2_PCICFG_DEVICE_CONTROL);
+                       if (!(val & BNX2_PCICFG_DEVICE_STATUS_NO_PEND))
+                               break;
+               }
+       }
 
        /* Wait for the firmware to tell us it is ok to issue a reset. */
        bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code, 1, 1);
index bf4c3421067d2078b56c6da7818f25c979717185..5488a2e82fe93a445dd9e38f695d7035703c39a3 100644 (file)
@@ -461,6 +461,8 @@ struct l2_fhdr {
 #define BNX2_PCICFG_MAILBOX_QUEUE_ADDR                 0x00000090
 #define BNX2_PCICFG_MAILBOX_QUEUE_DATA                 0x00000094
 
+#define BNX2_PCICFG_DEVICE_CONTROL                     0x000000b4
+#define BNX2_PCICFG_DEVICE_STATUS_NO_PEND               ((1L<<5)<<16)
 
 /*
  *  pci_reg definition