diff options
| author | Bjorn Helgaas <bhelgaas@google.com> | 2012-08-22 09:41:27 -0600 | 
|---|---|---|
| committer | Bjorn Helgaas <bhelgaas@google.com> | 2012-08-23 10:11:11 -0600 | 
| commit | 76b57c6700e56d146938ca9dc1d553557e940d9f (patch) | |
| tree | c7bc8610faf614c6d707912cd666ac7beee2ed8b /drivers/pci/quirks.c | |
| parent | 59875ae489609b2267548dc85160c5f0f0c6f9d4 (diff) | |
| download | olio-linux-3.10-76b57c6700e56d146938ca9dc1d553557e940d9f.tar.xz olio-linux-3.10-76b57c6700e56d146938ca9dc1d553557e940d9f.zip  | |
PCI: Wait for pending transactions to complete before 82599 FLR
Before initiating an FLR, we should wait for completion of any outstanding
non-posted requests.  See PCIe spec r3.0, sec 6.6.2.
This makes reset_intel_82599_sfp_virtfn() very similar to the generic
pcie_flr().  The only difference is that the 82599 doesn't report FLR
support in the VF Device Capability register.
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/quirks.c')
| -rw-r--r-- | drivers/pci/quirks.c | 28 | 
1 files changed, 27 insertions, 1 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index aa77538c50c..7a451ff56ec 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3081,10 +3081,36 @@ static int reset_intel_generic_dev(struct pci_dev *dev, int probe)  static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe)  { +	int i; +	u16 status; + +	/* +	 * http://www.intel.com/content/dam/doc/datasheet/82599-10-gbe-controller-datasheet.pdf +	 * +	 * The 82599 supports FLR on VFs, but FLR support is reported only +	 * in the PF DEVCAP (sec 9.3.10.4), not in the VF DEVCAP (sec 9.5). +	 * Therefore, we can't use pcie_flr(), which checks the VF DEVCAP. +	 */ +  	if (probe)  		return 0; -	pcie_capability_write_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR); +	/* Wait for Transaction Pending bit clean */ +	for (i = 0; i < 4; i++) { +		if (i) +			msleep((1 << (i - 1)) * 100); + +		pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status); +		if (!(status & PCI_EXP_DEVSTA_TRPND)) +			goto clear; +	} + +	dev_err(&dev->dev, "transaction is not cleared; " +			"proceeding with reset anyway\n"); + +clear: +	pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR); +  	msleep(100);  	return 0;  |