mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-24 14:45:24 +00:00
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: Chris Lalancette <clalance@redhat.com>
This commit is contained in:
parent
4018a026b2
commit
71e92a1575
@ -182,6 +182,16 @@ pciOpenConfig(pciDevice *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pciCloseConfig(pciDevice *dev)
|
||||
{
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
if (dev->fd >= 0)
|
||||
close(dev->fd);
|
||||
}
|
||||
|
||||
static int
|
||||
pciRead(pciDevice *dev, unsigned pos, uint8_t *buf, unsigned buflen)
|
||||
{
|
||||
@ -379,11 +389,16 @@ pciFindExtendedCapabilityOffset(pciDevice *dev, unsigned capability)
|
||||
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)
|
||||
{
|
||||
uint32_t caps;
|
||||
uint8_t pos;
|
||||
char *path;
|
||||
int found;
|
||||
|
||||
/* The PCIe Function Level Reset capability allows
|
||||
* individual device functions to be reset without
|
||||
@ -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);
|
||||
|
||||
return 0;
|
||||
@ -626,6 +660,8 @@ pciTryPowerManagementReset(pciDevice *dev)
|
||||
static int
|
||||
pciInitDevice(pciDevice *dev)
|
||||
{
|
||||
int flr;
|
||||
|
||||
if (pciOpenConfig(dev) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Failed to open config space file '%s'"),
|
||||
@ -635,7 +671,12 @@ pciInitDevice(pciDevice *dev)
|
||||
|
||||
dev->pcie_cap_pos = pciFindCapabilityOffset(dev, PCI_CAP_ID_EXP);
|
||||
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->initted = 1;
|
||||
return 0;
|
||||
@ -1099,8 +1140,7 @@ pciFreeDevice(pciDevice *dev)
|
||||
if (!dev)
|
||||
return;
|
||||
VIR_DEBUG("%s %s: freeing", dev->id, dev->name);
|
||||
if (dev->fd >= 0)
|
||||
close(dev->fd);
|
||||
pciCloseConfig(dev);
|
||||
VIR_FREE(dev);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user