diff options
author | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2016-11-21 17:08:57 +0000 |
---|---|---|
committer | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2016-11-21 17:08:57 +0000 |
commit | 3d02ff6ebaec39bbbaf3074fac77687ec2241bc6 (patch) | |
tree | d6c15974927b87518e2290ba4db8311b0eac5c1e /sys/dev | |
parent | 0a79c9d3a0b3b923793d10f9265a8bd6484bcfbc (diff) |
Fixup a PCIe transaction completion timeout issue
Mirrors the change 71bde60191a9fa44d33b582c5e3713ffe99b0fef in Linux;
taken as a part of the 280182 commit to FreeBSD.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/ixgbe.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/sys/dev/pci/ixgbe.c b/sys/dev/pci/ixgbe.c index b2913205040..6405f20078b 100644 --- a/sys/dev/pci/ixgbe.c +++ b/sys/dev/pci/ixgbe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ixgbe.c,v 1.20 2016/11/21 12:37:35 mikeb Exp $ */ +/* $OpenBSD: ixgbe.c,v 1.21 2016/11/21 17:08:56 mikeb Exp $ */ /****************************************************************************** @@ -3570,7 +3570,8 @@ int32_t ixgbe_host_interface_command(struct ixgbe_hw *hw, uint32_t *buffer, **/ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw) { - uint32_t gcr_ext, hlreg0; + uint32_t gcr_ext, hlreg0, i, poll; + uint16_t value; /* * If double reset is not requested then all transactions should @@ -3587,6 +3588,23 @@ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw) hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK); + /* Wait for a last completion before clearing buffers */ + IXGBE_WRITE_FLUSH(hw); + msec_delay(3); + + /* + * Before proceeding, make sure that the PCIe block does not have + * transactions pending. + */ + poll = ixgbe_pcie_timeout_poll(hw); + for (i = 0; i < poll; i++) { + usec_delay(100); + value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS); + if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) + goto out; + } + +out: /* initiate cleaning flow for buffers in the PCIe transaction layer */ gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, |