[PATCH v2 4/4] s390x/pci: Reset a device in error state

Farhan Ali posted 4 patches 2 months, 3 weeks ago
Maintainers: Matthew Rosato <mjrosato@linux.ibm.com>, Eric Farman <farman@linux.ibm.com>, Thomas Huth <thuth@redhat.com>, Richard Henderson <richard.henderson@linaro.org>, David Hildenbrand <david@redhat.com>, Ilya Leoshkevich <iii@linux.ibm.com>, Halil Pasic <pasic@linux.ibm.com>, Christian Borntraeger <borntraeger@linux.ibm.com>, Alex Williamson <alex.williamson@redhat.com>, "Cédric Le Goater" <clg@redhat.com>, "Michael S. Tsirkin" <mst@redhat.com>, Cornelia Huck <cohuck@redhat.com>, Paolo Bonzini <pbonzini@redhat.com>
There is a newer version of this series
[PATCH v2 4/4] s390x/pci: Reset a device in error state
Posted by Farhan Ali 2 months, 3 weeks ago
For passthrough devices in error state, for a guest driven reset of the
device we can attempt a reset to recover the device. A 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 <alifm@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 87ecd06a81..a11ec770a7 100644
--- a/hw/s390x/s390-pci-vfio.c
+++ b/hw/s390x/s390-pci-vfio.c
@@ -158,6 +158,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
Re: [PATCH v2 4/4] s390x/pci: Reset a device in error state
Posted by Cédric Le Goater 2 months, 2 weeks ago
On 8/25/25 23:24, Farhan Ali wrote:
> For passthrough devices in error state, for a guest driven reset of the
> device we can attempt a reset to recover the device. A 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 <alifm@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 87ecd06a81..a11ec770a7 100644
> --- a/hw/s390x/s390-pci-vfio.c
> +++ b/hw/s390x/s390-pci-vfio.c
> @@ -158,6 +158,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) { }

static inline void ... ^


Thanks,

C.



>   #endif
>   
>   #endif
Re: [PATCH v2 4/4] s390x/pci: Reset a device in error state
Posted by Farhan Ali 2 months, 1 week ago
On 9/1/2025 4:17 AM, Cédric Le Goater wrote:
> On 8/25/25 23:24, Farhan Ali wrote:
>> For passthrough devices in error state, for a guest driven reset of the
>> device we can attempt a reset to recover the device. A 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 <alifm@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 87ecd06a81..a11ec770a7 100644
>> --- a/hw/s390x/s390-pci-vfio.c
>> +++ b/hw/s390x/s390-pci-vfio.c
>> @@ -158,6 +158,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) { }
>
> static inline void ... ^
>
>
> Thanks,
>
> C.

Ack, will change.

Thanks

Farhan


>
>
>
>>   #endif
>>     #endif
>
>