diff options
Diffstat (limited to 'drivers/pci/quirks.c')
-rw-r--r-- | drivers/pci/quirks.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 51553179e967..7a451ff56ecc 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -3081,17 +3081,36 @@ static int reset_intel_generic_dev(struct pci_dev *dev, int probe) | |||
3081 | 3081 | ||
3082 | static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe) | 3082 | static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe) |
3083 | { | 3083 | { |
3084 | int pos; | 3084 | int i; |
3085 | u16 status; | ||
3085 | 3086 | ||
3086 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); | 3087 | /* |
3087 | if (!pos) | 3088 | * http://www.intel.com/content/dam/doc/datasheet/82599-10-gbe-controller-datasheet.pdf |
3088 | return -ENOTTY; | 3089 | * |
3090 | * The 82599 supports FLR on VFs, but FLR support is reported only | ||
3091 | * in the PF DEVCAP (sec 9.3.10.4), not in the VF DEVCAP (sec 9.5). | ||
3092 | * Therefore, we can't use pcie_flr(), which checks the VF DEVCAP. | ||
3093 | */ | ||
3089 | 3094 | ||
3090 | if (probe) | 3095 | if (probe) |
3091 | return 0; | 3096 | return 0; |
3092 | 3097 | ||
3093 | pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, | 3098 | /* Wait for Transaction Pending bit clean */ |
3094 | PCI_EXP_DEVCTL_BCR_FLR); | 3099 | for (i = 0; i < 4; i++) { |
3100 | if (i) | ||
3101 | msleep((1 << (i - 1)) * 100); | ||
3102 | |||
3103 | pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status); | ||
3104 | if (!(status & PCI_EXP_DEVSTA_TRPND)) | ||
3105 | goto clear; | ||
3106 | } | ||
3107 | |||
3108 | dev_err(&dev->dev, "transaction is not cleared; " | ||
3109 | "proceeding with reset anyway\n"); | ||
3110 | |||
3111 | clear: | ||
3112 | pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR); | ||
3113 | |||
3095 | msleep(100); | 3114 | msleep(100); |
3096 | 3115 | ||
3097 | return 0; | 3116 | return 0; |