From fe34e6d79969bc4d442f5eacf242d6939f0d1c56 Mon Sep 17 00:00:00 2001 From: Jijiang Liu Date: Wed, 18 Jun 2014 17:44:15 +0200 Subject: [PATCH] ixgbe/base: rework PCIe disabling Signed-off-by: Jijiang Liu Acked-by: Helin Zhang Tested-by: Waterman Cao [Thomas: split code drop] --- lib/librte_pmd_ixgbe/ixgbe/ixgbe_common.c | 69 +++++++++++++++++++++-- lib/librte_pmd_ixgbe/ixgbe/ixgbe_common.h | 3 + lib/librte_pmd_ixgbe/ixgbe/ixgbe_osdep.h | 1 + lib/librte_pmd_ixgbe/ixgbe/ixgbe_type.h | 11 ++++ 4 files changed, 78 insertions(+), 6 deletions(-) diff --git a/lib/librte_pmd_ixgbe/ixgbe/ixgbe_common.c b/lib/librte_pmd_ixgbe/ixgbe/ixgbe_common.c index ec0c0656f6..1cb6e4ece0 100644 --- a/lib/librte_pmd_ixgbe/ixgbe/ixgbe_common.c +++ b/lib/librte_pmd_ixgbe/ixgbe/ixgbe_common.c @@ -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; diff --git a/lib/librte_pmd_ixgbe/ixgbe/ixgbe_common.h b/lib/librte_pmd_ixgbe/ixgbe/ixgbe_common.h index dc4d484059..6c70ca7bcf 100644 --- a/lib/librte_pmd_ixgbe/ixgbe/ixgbe_common.h +++ b/lib/librte_pmd_ixgbe/ixgbe/ixgbe_common.h @@ -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; diff --git a/lib/librte_pmd_ixgbe/ixgbe/ixgbe_osdep.h b/lib/librte_pmd_ixgbe/ixgbe/ixgbe_osdep.h index 4a3018d3bb..d602cbc351 100644 --- a/lib/librte_pmd_ixgbe/ixgbe/ixgbe_osdep.h +++ b/lib/librte_pmd_ixgbe/ixgbe/ixgbe_osdep.h @@ -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; diff --git a/lib/librte_pmd_ixgbe/ixgbe/ixgbe_type.h b/lib/librte_pmd_ixgbe/ixgbe/ixgbe_type.h index 040983ab4a..61e2054f2c 100644 --- a/lib/librte_pmd_ixgbe/ixgbe/ixgbe_type.h +++ b/lib/librte_pmd_ixgbe/ixgbe/ixgbe_type.h @@ -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 -- 2.20.1