提交 71e92a15 编写于 作者: C Chris Lalancette

Force FLR on for buggy SR-IOV devices.

Some buggy PCI devices actually support FLR, but
forget to advertise that fact in their PCI config space.
However, Virtual Functions on SR-IOV devices are
*required* to support FLR by the spec, so force has_flr
on if this is a virtual function.
Signed-off-by: NChris Lalancette <clalance@redhat.com>
上级 4018a026
...@@ -182,6 +182,16 @@ pciOpenConfig(pciDevice *dev) ...@@ -182,6 +182,16 @@ pciOpenConfig(pciDevice *dev)
return 0; return 0;
} }
static void
pciCloseConfig(pciDevice *dev)
{
if (!dev)
return;
if (dev->fd >= 0)
close(dev->fd);
}
static int static int
pciRead(pciDevice *dev, unsigned pos, uint8_t *buf, unsigned buflen) pciRead(pciDevice *dev, unsigned pos, uint8_t *buf, unsigned buflen)
{ {
...@@ -379,11 +389,16 @@ pciFindExtendedCapabilityOffset(pciDevice *dev, unsigned capability) ...@@ -379,11 +389,16 @@ pciFindExtendedCapabilityOffset(pciDevice *dev, unsigned capability)
return 0; return 0;
} }
static unsigned /* detects whether this device has FLR. Returns 0 if the device does
* not have FLR, 1 if it does, and -1 on error
*/
static int
pciDetectFunctionLevelReset(pciDevice *dev) pciDetectFunctionLevelReset(pciDevice *dev)
{ {
uint32_t caps; uint32_t caps;
uint8_t pos; uint8_t pos;
char *path;
int found;
/* The PCIe Function Level Reset capability allows /* The PCIe Function Level Reset capability allows
* individual device functions to be reset without * individual device functions to be reset without
...@@ -412,6 +427,25 @@ pciDetectFunctionLevelReset(pciDevice *dev) ...@@ -412,6 +427,25 @@ pciDetectFunctionLevelReset(pciDevice *dev)
} }
} }
/* there are some buggy devices that do support FLR, but forget to
* advertise that fact in their capabilities. However, FLR is *required*
* to be present for virtual functions (VFs), so if we see that this
* device is a VF, we just assume FLR works
*/
if (virAsprintf(&path, PCI_SYSFS "devices/%s/physfn", dev->name) < 0) {
virReportOOMError();
return -1;
}
found = virFileExists(path);
VIR_FREE(path);
if (found) {
VIR_DEBUG("%s %s: buggy device didn't advertise FLR, but is a VF; forcing flr on",
dev->id, dev->name);
return 1;
}
VIR_DEBUG("%s %s: no FLR capability found", dev->id, dev->name); VIR_DEBUG("%s %s: no FLR capability found", dev->id, dev->name);
return 0; return 0;
...@@ -626,6 +660,8 @@ pciTryPowerManagementReset(pciDevice *dev) ...@@ -626,6 +660,8 @@ pciTryPowerManagementReset(pciDevice *dev)
static int static int
pciInitDevice(pciDevice *dev) pciInitDevice(pciDevice *dev)
{ {
int flr;
if (pciOpenConfig(dev) < 0) { if (pciOpenConfig(dev) < 0) {
virReportSystemError(errno, virReportSystemError(errno,
_("Failed to open config space file '%s'"), _("Failed to open config space file '%s'"),
...@@ -635,7 +671,12 @@ pciInitDevice(pciDevice *dev) ...@@ -635,7 +671,12 @@ pciInitDevice(pciDevice *dev)
dev->pcie_cap_pos = pciFindCapabilityOffset(dev, PCI_CAP_ID_EXP); dev->pcie_cap_pos = pciFindCapabilityOffset(dev, PCI_CAP_ID_EXP);
dev->pci_pm_cap_pos = pciFindCapabilityOffset(dev, PCI_CAP_ID_PM); dev->pci_pm_cap_pos = pciFindCapabilityOffset(dev, PCI_CAP_ID_PM);
dev->has_flr = pciDetectFunctionLevelReset(dev); flr = pciDetectFunctionLevelReset(dev);
if (flr < 0) {
pciCloseConfig(dev);
return flr;
}
dev->has_flr = flr;
dev->has_pm_reset = pciDetectPowerManagementReset(dev); dev->has_pm_reset = pciDetectPowerManagementReset(dev);
dev->initted = 1; dev->initted = 1;
return 0; return 0;
...@@ -1099,8 +1140,7 @@ pciFreeDevice(pciDevice *dev) ...@@ -1099,8 +1140,7 @@ pciFreeDevice(pciDevice *dev)
if (!dev) if (!dev)
return; return;
VIR_DEBUG("%s %s: freeing", dev->id, dev->name); VIR_DEBUG("%s %s: freeing", dev->id, dev->name);
if (dev->fd >= 0) pciCloseConfig(dev);
close(dev->fd);
VIR_FREE(dev); VIR_FREE(dev);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册