From: Farhan Ali <al...@linux.ibm.com> The CRW irq will be used by vfio-ccw to notify the userspace about any CRWs the userspace needs to handle. Let's add support for it.
Signed-off-by: Farhan Ali <al...@linux.ibm.com> Signed-off-by: Eric Farman <far...@linux.ibm.com> --- Notes: v0->v1: [EF] - Check vcdev->crw_region before registering the irq, in case host kernel does not have matching support - Split the refactoring changes to an earlier (new) patch (and don't remove the "num_irqs" check in the register routine, but adjust it to the check the input variable) - Don't revert the cool vfio_set_irq_signaling() stuff - Unregister CRW IRQ before IO IRQ in unrealize - s/crw1/crw0/ hw/vfio/ccw.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index b16526d5de..b3f4120118 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -48,6 +48,7 @@ struct VFIOCCWDevice { uint64_t crw_region_offset; struct ccw_crw_region *crw_region; EventNotifier io_notifier; + EventNotifier crw_notifier; bool force_orb_pfch; bool warned_orb_pfch; }; @@ -259,6 +260,34 @@ static void vfio_ccw_reset(DeviceState *dev) ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET); } +static void vfio_ccw_crw_notifier_handler(void *opaque) +{ + VFIOCCWDevice *vcdev = opaque; + struct ccw_crw_region *region = vcdev->crw_region; + CRW crw; + int size; + uint8_t erc; + uint16_t rsid; + + if (!event_notifier_test_and_clear(&vcdev->crw_notifier)) { + return; + } + + memset(region, 0, sizeof(*region)); + size = pread(vcdev->vdev.fd, region, vcdev->crw_region_size, + vcdev->crw_region_offset); + + if (size == -1) { + error_report("vfio-ccw: Read crw region failed with errno=%d", errno); + return; + } + + memcpy(&crw, ®ion->crw0, sizeof(CRW)); + erc = crw.flags & 0x003f; + rsid = crw.rsid; + css_queue_crw(CRW_RSC_CHP, erc, 0, 0, rsid); +} + static void vfio_ccw_io_notifier_handler(void *opaque) { VFIOCCWDevice *vcdev = opaque; @@ -349,6 +378,10 @@ static void vfio_ccw_register_irq_notifier(VFIOCCWDevice *vcdev, int irq, notifier = &vcdev->io_notifier; fd_read = vfio_ccw_io_notifier_handler; break; + case VFIO_CCW_CRW_IRQ_INDEX: + notifier = &vcdev->crw_notifier; + fd_read = vfio_ccw_crw_notifier_handler; + break; default: error_setg(errp, "vfio: Unsupported device irq(%d) fd: %m", irq); return; @@ -398,6 +431,9 @@ static void vfio_ccw_unregister_irq_notifier(VFIOCCWDevice *vcdev, int irq) case VFIO_CCW_IO_IRQ_INDEX: notifier = &vcdev->io_notifier; break; + case VFIO_CCW_CRW_IRQ_INDEX: + notifier = &vcdev->crw_notifier; + break; default: error_report("vfio: Unsupported device irq(%d) fd: %m", irq); return; @@ -618,6 +654,14 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) goto out_notifier_err; } + if (vcdev->crw_region) { + vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_CRW_IRQ_INDEX, &err); + if (err) { + vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX); + goto out_notifier_err; + } + } + return; out_notifier_err: @@ -642,6 +686,7 @@ static void vfio_ccw_unrealize(DeviceState *dev, Error **errp) S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev); VFIOGroup *group = vcdev->vdev.group; + vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_CRW_IRQ_INDEX); vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX); vfio_ccw_put_region(vcdev); vfio_ccw_put_device(vcdev); -- 2.17.1