diff --git a/devicemodel/hw/pci/passthrough.c b/devicemodel/hw/pci/passthrough.c index c10206954..27f1c4101 100644 --- a/devicemodel/hw/pci/passthrough.c +++ b/devicemodel/hw/pci/passthrough.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include "iodev.h" #include "vmmapi.h" @@ -815,7 +817,7 @@ cfginit(struct vmctx *ctx, struct passthru_dev *ptdev, int bus, { int irq_type = IRQ_MSI; char reset_path[60]; - FILE *f; + int fd; bzero(&ptdev->sel, sizeof(struct pcisel)); ptdev->sel.bus = bus; @@ -835,25 +837,28 @@ cfginit(struct vmctx *ctx, struct passthru_dev *ptdev, int bus, irq_type = IRQ_INTX; } - /* Check reset method for PCIe dev. If SOS kernel provides 'reset' - * entry in sysfs, related dev has some reset capability, e.g. FLR, or - * secondary bus reset. PCIe dev without any reset capability is - * refused for passthrough. + /* If SOS kernel provides 'reset' entry in sysfs, related dev has some + * reset capability, e.g. FLR, or secondary bus reset. We do 2 things: + * - reset each dev before passthrough to achieve valid dev state after + * UOS reboot + * - refuse to passthrough PCIe dev without any reset capability */ - if (ptdev->pcie_cap) { - snprintf(reset_path, 40, - "/sys/bus/pci/devices/0000:%02x:%02x.%x/reset", - bus, slot, func); + snprintf(reset_path, 40, + "/sys/bus/pci/devices/0000:%02x:%02x.%x/reset", + bus, slot, func); - if ((f = fopen(reset_path, "r"))) - fclose(f); - else if (errno == ENOENT) { - warnx("No reset capability for PCIe %x/%x/%x, " - "remove it from ptdev list!!\n", - bus, slot, func); - if (!no_reset) - return -1; - } + fd = open(reset_path, O_WRONLY); + if (fd >= 0) { + if (write(fd, "1", 1) < 0) + warnx("reset dev %x/%x/%x failed!\n", + bus, slot, func); + close(fd); + } else if (errno == ENOENT && ptdev->pcie_cap) { + warnx("No reset capability for PCIe %x/%x/%x, " + "remove it from ptdev list!!\n", + bus, slot, func); + if (!no_reset) + return -1; } if (cfginitbar(ctx, ptdev) != 0) {