Commit 009bc06e authored by Alexander Duyck's avatar Alexander Duyck Committed by David S. Miller

igb: add completion timeout workaround for 82575/82576

The 82575 and 82576 hardware can both experience data corruption issues if
a pci-e completion arrives after the timeout value.  In order to avoid this
we need to increase the timeout value while pci-e master is disabled.
Signed-off-by: default avatarAlexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 12645a19
...@@ -61,6 +61,7 @@ static void igb_release_swfw_sync_82575(struct e1000_hw *, u16); ...@@ -61,6 +61,7 @@ static void igb_release_swfw_sync_82575(struct e1000_hw *, u16);
static bool igb_sgmii_active_82575(struct e1000_hw *); static bool igb_sgmii_active_82575(struct e1000_hw *);
static s32 igb_reset_init_script_82575(struct e1000_hw *); static s32 igb_reset_init_script_82575(struct e1000_hw *);
static s32 igb_read_mac_addr_82575(struct e1000_hw *); static s32 igb_read_mac_addr_82575(struct e1000_hw *);
static s32 igb_set_pcie_completion_timeout(struct e1000_hw *hw);
static s32 igb_get_invariants_82575(struct e1000_hw *hw) static s32 igb_get_invariants_82575(struct e1000_hw *hw)
{ {
...@@ -909,6 +910,12 @@ static s32 igb_reset_hw_82575(struct e1000_hw *hw) ...@@ -909,6 +910,12 @@ static s32 igb_reset_hw_82575(struct e1000_hw *hw)
if (ret_val) if (ret_val)
hw_dbg("PCI-E Master disable polling has failed.\n"); hw_dbg("PCI-E Master disable polling has failed.\n");
/* set the completion timeout for interface */
ret_val = igb_set_pcie_completion_timeout(hw);
if (ret_val) {
hw_dbg("PCI-E Set completion timeout has failed.\n");
}
hw_dbg("Masking off all interrupts\n"); hw_dbg("Masking off all interrupts\n");
wr32(E1000_IMC, 0xffffffff); wr32(E1000_IMC, 0xffffffff);
...@@ -1407,6 +1414,57 @@ void igb_rx_fifo_flush_82575(struct e1000_hw *hw) ...@@ -1407,6 +1414,57 @@ void igb_rx_fifo_flush_82575(struct e1000_hw *hw)
rd32(E1000_MPC); rd32(E1000_MPC);
} }
/**
* igb_set_pcie_completion_timeout - set pci-e completion timeout
* @hw: pointer to the HW structure
*
* The defaults for 82575 and 82576 should be in the range of 50us to 50ms,
* however the hardware default for these parts is 500us to 1ms which is less
* than the 10ms recommended by the pci-e spec. To address this we need to
* increase the value to either 10ms to 200ms for capability version 1 config,
* or 16ms to 55ms for version 2.
**/
static s32 igb_set_pcie_completion_timeout(struct e1000_hw *hw)
{
u32 gcr = rd32(E1000_GCR);
s32 ret_val = 0;
u16 pcie_devctl2;
/* only take action if timeout value is defaulted to 0 */
if (gcr & E1000_GCR_CMPL_TMOUT_MASK)
goto out;
/*
* if capababilities version is type 1 we can write the
* timeout of 10ms to 200ms through the GCR register
*/
if (!(gcr & E1000_GCR_CAP_VER2)) {
gcr |= E1000_GCR_CMPL_TMOUT_10ms;
goto out;
}
/*
* for version 2 capabilities we need to write the config space
* directly in order to set the completion timeout value for
* 16ms to 55ms
*/
ret_val = igb_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
&pcie_devctl2);
if (ret_val)
goto out;
pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms;
ret_val = igb_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
&pcie_devctl2);
out:
/* disable completion timeout resend */
gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND;
wr32(E1000_GCR, gcr);
return ret_val;
}
/** /**
* igb_vmdq_set_loopback_pf - enable or disable vmdq loopback * igb_vmdq_set_loopback_pf - enable or disable vmdq loopback
* @hw: pointer to the hardware struct * @hw: pointer to the hardware struct
......
...@@ -435,6 +435,12 @@ ...@@ -435,6 +435,12 @@
/* Flow Control */ /* Flow Control */
#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */ #define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */
/* PCI Express Control */
#define E1000_GCR_CMPL_TMOUT_MASK 0x0000F000
#define E1000_GCR_CMPL_TMOUT_10ms 0x00001000
#define E1000_GCR_CMPL_TMOUT_RESEND 0x00010000
#define E1000_GCR_CAP_VER2 0x00040000
/* PHY Control Register */ /* PHY Control Register */
#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ #define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ #define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
...@@ -569,9 +575,11 @@ ...@@ -569,9 +575,11 @@
/* PCI/PCI-X/PCI-EX Config space */ /* PCI/PCI-X/PCI-EX Config space */
#define PCIE_LINK_STATUS 0x12 #define PCIE_LINK_STATUS 0x12
#define PCIE_DEVICE_CONTROL2 0x28
#define PCIE_LINK_WIDTH_MASK 0x3F0 #define PCIE_LINK_WIDTH_MASK 0x3F0
#define PCIE_LINK_WIDTH_SHIFT 4 #define PCIE_LINK_WIDTH_SHIFT 4
#define PCIE_DEVICE_CONTROL2_16ms 0x0005
#define PHY_REVISION_MASK 0xFFFFFFF0 #define PHY_REVISION_MASK 0xFFFFFFF0
#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ #define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
......
...@@ -494,5 +494,7 @@ extern char *igb_get_hw_dev_name(struct e1000_hw *hw); ...@@ -494,5 +494,7 @@ extern char *igb_get_hw_dev_name(struct e1000_hw *hw);
#else #else
#define hw_dbg(format, arg...) #define hw_dbg(format, arg...)
#endif #endif
#endif #endif
/* These functions must be implemented by drivers */
s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
...@@ -37,20 +37,6 @@ ...@@ -37,20 +37,6 @@
static s32 igb_set_default_fc(struct e1000_hw *hw); static s32 igb_set_default_fc(struct e1000_hw *hw);
static s32 igb_set_fc_watermarks(struct e1000_hw *hw); static s32 igb_set_fc_watermarks(struct e1000_hw *hw);
static s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
{
struct igb_adapter *adapter = hw->back;
u16 cap_offset;
cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
if (!cap_offset)
return -E1000_ERR_CONFIG;
pci_read_config_word(adapter->pdev, cap_offset + reg, value);
return 0;
}
/** /**
* igb_get_bus_info_pcie - Get PCIe bus information * igb_get_bus_info_pcie - Get PCIe bus information
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
......
...@@ -305,6 +305,7 @@ enum { ...@@ -305,6 +305,7 @@ enum {
#define E1000_CCMCTL 0x05B48 /* CCM Control Register */ #define E1000_CCMCTL 0x05B48 /* CCM Control Register */
#define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */ #define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */
#define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */ #define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */
#define E1000_GCR 0x05B00 /* PCI-Ex Control */
#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */ #define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */
#define E1000_SWSM 0x05B50 /* SW Semaphore */ #define E1000_SWSM 0x05B50 /* SW Semaphore */
#define E1000_FWSM 0x05B54 /* FW Semaphore */ #define E1000_FWSM 0x05B54 /* FW Semaphore */
......
...@@ -5029,6 +5029,34 @@ static int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) ...@@ -5029,6 +5029,34 @@ static int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
} }
} }
s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
{
struct igb_adapter *adapter = hw->back;
u16 cap_offset;
cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
if (!cap_offset)
return -E1000_ERR_CONFIG;
pci_read_config_word(adapter->pdev, cap_offset + reg, value);
return 0;
}
s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
{
struct igb_adapter *adapter = hw->back;
u16 cap_offset;
cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
if (!cap_offset)
return -E1000_ERR_CONFIG;
pci_write_config_word(adapter->pdev, cap_offset + reg, *value);
return 0;
}
static void igb_vlan_rx_register(struct net_device *netdev, static void igb_vlan_rx_register(struct net_device *netdev,
struct vlan_group *grp) struct vlan_group *grp)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment