For passthrough devices in error state, for a guest driven reset of the device we can attempt a hot reset to recover the device. A hot reset of the device will trigger a CLP disable/enable cycle on the host to bring the device into a recovered state.
Signed-off-by: Farhan Ali <al...@linux.ibm.com> --- hw/s390x/s390-pci-bus.c | 7 +++++++ hw/s390x/s390-pci-vfio.c | 6 ++++++ include/hw/s390x/s390-pci-vfio.h | 2 ++ 3 files changed, 15 insertions(+) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index af42eb9938..c9c2d775f0 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -1493,6 +1493,8 @@ static void s390_pci_device_reset(DeviceState *dev) return; case ZPCI_FS_STANDBY: break; + case ZPCI_FS_ERROR: + break; default: pbdev->fh &= ~FH_MASK_ENABLE; pbdev->state = ZPCI_FS_DISABLED; @@ -1505,6 +1507,11 @@ static void s390_pci_device_reset(DeviceState *dev) } else if (pbdev->summary_ind) { pci_dereg_irqs(pbdev); } + + if (pbdev->state == ZPCI_FS_ERROR) { + s390_pci_reset(pbdev); + } + if (pbdev->iommu->enabled) { pci_dereg_ioat(pbdev->iommu); } diff --git a/hw/s390x/s390-pci-vfio.c b/hw/s390x/s390-pci-vfio.c index ceee342f4a..4ec5e2cd95 100644 --- a/hw/s390x/s390-pci-vfio.c +++ b/hw/s390x/s390-pci-vfio.c @@ -168,6 +168,12 @@ static void s390_pci_err_handler(VFIOPCIDevice *vfio_pci) return; } +void s390_pci_reset(S390PCIBusDevice *pbdev) +{ + VFIOPCIDevice *vfio_pci = container_of(pbdev->pdev, VFIOPCIDevice, pdev); + ioctl(vfio_pci->vbasedev.fd, VFIO_DEVICE_RESET); +} + static void s390_pci_read_base(S390PCIBusDevice *pbdev, struct vfio_device_info *info) { diff --git a/include/hw/s390x/s390-pci-vfio.h b/include/hw/s390x/s390-pci-vfio.h index 66b274293c..c28dafeed8 100644 --- a/include/hw/s390x/s390-pci-vfio.h +++ b/include/hw/s390x/s390-pci-vfio.h @@ -23,6 +23,7 @@ void s390_pci_end_dma_count(S390pciState *s, S390PCIDMACount *cnt); bool s390_pci_get_host_fh(S390PCIBusDevice *pbdev, uint32_t *fh); void s390_pci_get_clp_info(S390PCIBusDevice *pbdev); void s390_pci_setup_err_handler(S390PCIBusDevice *pbdev); +void s390_pci_reset(S390PCIBusDevice *pbdev); #else static inline bool s390_pci_update_dma_avail(int fd, unsigned int *avail) { @@ -41,6 +42,7 @@ static inline bool s390_pci_get_host_fh(S390PCIBusDevice *pbdev, uint32_t *fh) } static inline void s390_pci_get_clp_info(S390PCIBusDevice *pbdev) { } static inline void s390_pci_setup_err_handler(S390PCIBusDevice *pbdev) { } +void s390_pci_reset(S390PCIBusDevice *pbdev) { } #endif #endif -- 2.43.0