From 1f86c983bebbb226b69f986bdc7b8b4299a2004c Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Thu, 27 Feb 2014 20:32:40 -0800 Subject: [PATCH] ixgbe: fix to use correct timeout interval for memory read completion Currently we were just always polling for a hard coded 80 ms and not respecting the system-wide timeout interval. Since up until now all devices have been tested with this 80ms value we continue to use this value as a hard minimum. Signed-off-by: Don Skidmore Tested-by: Phil Schmitt Signed-off-by: Aaron Brown Signed-off-by: David S. Miller --- .../net/ethernet/intel/ixgbe/ixgbe_common.c | 54 ++++++++++++++++++- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 13 ++++- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index b5c434b617b1..2e84ee8a1071 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -2436,6 +2436,55 @@ void ixgbe_fc_autoneg(struct ixgbe_hw *hw) } } +/** + * 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) +{ + struct ixgbe_adapter *adapter = hw->back; + s16 devctl2; + u32 pollcnt; + + pci_read_config_word(adapter->pdev, IXGBE_PCI_DEVICE_CONTROL2, + &devctl2); + 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 @@ -2449,7 +2498,7 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) { struct ixgbe_adapter *adapter = hw->back; s32 status = 0; - u32 i; + u32 i, poll; u16 value; /* Always set this bit to ensure any future transactions are blocked */ @@ -2481,7 +2530,8 @@ static 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++) { udelay(100); pci_read_config_word(adapter->pdev, IXGBE_PCI_DEVICE_STATUS, &value); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 9283cffd1b57..245819d7ec15 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -1854,8 +1854,19 @@ 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 +#define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800 /* RAH */ #define IXGBE_RAH_VIND_MASK 0x003C0000 -- GitLab