ixgbe/base: rework PCIe disabling
authorJijiang Liu <jijiang.liu@intel.com>
Wed, 18 Jun 2014 15:44:15 +0000 (17:44 +0200)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Wed, 18 Jun 2014 21:31:02 +0000 (23:31 +0200)
Signed-off-by: Jijiang Liu <jijiang.liu@intel.com>
Acked-by: Helin Zhang <helin.zhang@intel.com>
Tested-by: Waterman Cao <waterman.cao@intel.com>
[Thomas: split code drop]

lib/librte_pmd_ixgbe/ixgbe/ixgbe_common.c
lib/librte_pmd_ixgbe/ixgbe/ixgbe_common.h
lib/librte_pmd_ixgbe/ixgbe/ixgbe_osdep.h
lib/librte_pmd_ixgbe/ixgbe/ixgbe_type.h

index ec0c065..1cb6e4e 100644 (file)
@@ -2992,6 +2992,53 @@ out:
        }
 }
 
+/*
+ * ixgbe_pcie_timeout_poll - Return number of times to poll for completion
+ * @hw: pointer to hardware structure
+ *
+ * System-wide timeout range is encoded in PCIe Device Control2 register.
+ *
+ * Add 10% to specified maximum and return the number of times to poll for
+ * completion timeout, in units of 100 microsec.  Never return less than
+ * 800 = 80 millisec.
+ */
+STATIC u32 ixgbe_pcie_timeout_poll(struct ixgbe_hw *hw)
+{
+       s16 devctl2;
+       u32 pollcnt;
+
+       devctl2 = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2);
+       devctl2 &= IXGBE_PCIDEVCTRL2_TIMEO_MASK;
+
+       switch (devctl2) {
+       case IXGBE_PCIDEVCTRL2_65_130ms:
+               pollcnt = 1300;         /* 130 millisec */
+               break;
+       case IXGBE_PCIDEVCTRL2_260_520ms:
+               pollcnt = 5200;         /* 520 millisec */
+               break;
+       case IXGBE_PCIDEVCTRL2_1_2s:
+               pollcnt = 20000;        /* 2 sec */
+               break;
+       case IXGBE_PCIDEVCTRL2_4_8s:
+               pollcnt = 80000;        /* 8 sec */
+               break;
+       case IXGBE_PCIDEVCTRL2_17_34s:
+               pollcnt = 34000;        /* 34 sec */
+               break;
+       case IXGBE_PCIDEVCTRL2_50_100us:        /* 100 microsecs */
+       case IXGBE_PCIDEVCTRL2_1_2ms:           /* 2 millisecs */
+       case IXGBE_PCIDEVCTRL2_16_32ms:         /* 32 millisec */
+       case IXGBE_PCIDEVCTRL2_16_32ms_def:     /* 32 millisec default */
+       default:
+               pollcnt = 800;          /* 80 millisec minimum */
+               break;
+       }
+
+       /* add 10% to spec maximum */
+       return (pollcnt * 11) / 10;
+}
+
 /**
  *  ixgbe_disable_pcie_master - Disable PCI-express master access
  *  @hw: pointer to hardware structure
@@ -3004,15 +3051,17 @@ out:
 s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
 {
        s32 status = IXGBE_SUCCESS;
-       u32 i;
+       u32 i, poll;
+       u16 value;
 
        DEBUGFUNC("ixgbe_disable_pcie_master");
 
        /* Always set this bit to ensure any future transactions are blocked */
        IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS);
 
-       /* Exit if master requets are blocked */
-       if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
+       /* Exit if master requests are blocked */
+       if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) ||
+           IXGBE_REMOVED(hw->hw_addr))
                goto out;
 
        /* Poll for master request bit to clear */
@@ -3037,10 +3086,13 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
         * Before proceeding, make sure that the PCIe block does not have
         * transactions pending.
         */
-       for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
+       poll = ixgbe_pcie_timeout_poll(hw);
+       for (i = 0; i < poll; i++) {
                usec_delay(100);
-               if (!(IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS) &
-                   IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
+               value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS);
+               if (IXGBE_REMOVED(hw->hw_addr))
+                       goto out;
+               if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
                        goto out;
        }
 
@@ -3456,6 +3508,8 @@ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
 
        DEBUGFUNC("ixgbe_get_pcie_msix_count_generic");
        msix_count = IXGBE_READ_PCIE_WORD(hw, pcie_offset);
+       if (IXGBE_REMOVED(hw->hw_addr))
+               msix_count = 0;
        msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK;
 
        /* MSI-X count is zero-based in HW */
@@ -3559,6 +3613,9 @@ s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
        mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
        mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
 
+       if (IXGBE_REMOVED(hw->hw_addr))
+               goto done;
+
        if (!mpsar_lo && !mpsar_hi)
                goto done;
 
index dc4d484..6c70ca7 100644 (file)
@@ -41,6 +41,9 @@ POSSIBILITY OF SUCH DAMAGE.
                IXGBE_WRITE_REG(hw, reg, (u32) value); \
                IXGBE_WRITE_REG(hw, reg + 4, (u32) (value >> 32)); \
        } while (0)
+#ifndef IXGBE_REMOVED
+#define IXGBE_REMOVED(a) (0)
+#endif /* IXGBE_REMOVED */
 struct ixgbe_pba {
        u16 word[2];
        u16 *pba_block;
index 4a3018d..d602cbc 100644 (file)
@@ -91,6 +91,7 @@
 typedef uint8_t                u8;
 typedef int8_t         s8;
 typedef uint16_t       u16;
+typedef int16_t        s16; 
 typedef uint32_t       u32;
 typedef int32_t                s32;
 typedef uint64_t       u64;
index 040983a..61e2054 100644 (file)
@@ -1951,6 +1951,17 @@ enum {
 #define IXGBE_PCI_HEADER_TYPE_MULTIFUNC        0x80
 #define IXGBE_PCI_DEVICE_CONTROL2_16ms 0x0005
 
+#define IXGBE_PCIDEVCTRL2_TIMEO_MASK   0xf
+#define IXGBE_PCIDEVCTRL2_16_32ms_def  0x0
+#define IXGBE_PCIDEVCTRL2_50_100us     0x1
+#define IXGBE_PCIDEVCTRL2_1_2ms                0x2
+#define IXGBE_PCIDEVCTRL2_16_32ms      0x5
+#define IXGBE_PCIDEVCTRL2_65_130ms     0x6
+#define IXGBE_PCIDEVCTRL2_260_520ms    0x9
+#define IXGBE_PCIDEVCTRL2_1_2s         0xa
+#define IXGBE_PCIDEVCTRL2_4_8s         0xd
+#define IXGBE_PCIDEVCTRL2_17_34s       0xe
+
 /* Number of 100 microseconds we wait for PCI Express master disable */
 #define IXGBE_PCI_MASTER_DISABLE_TIMEOUT       800