[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v4 6/6] vfio-ccw: Add support for the CRW region and IRQ
From: |
Eric Farman |
Subject: |
[PATCH v4 6/6] vfio-ccw: Add support for the CRW region and IRQ |
Date: |
Tue, 5 May 2020 14:57:57 +0200 |
From: Farhan Ali <address@hidden>
The crw region can be used to obtain information about
Channel Report Words (CRW) from vfio-ccw driver.
Currently only channel-path related CRWs are passed to
QEMU from vfio-ccw driver.
Signed-off-by: Farhan Ali <address@hidden>
Signed-off-by: Eric Farman <address@hidden>
---
Notes:
v3->v4:
- Merge region patch into IRQ patch [CH]
- Rework the testing/clearing notifier and reading region [CH]
v2->v3:
- Remove "size==0" check in CRW notifier [CH]
- Remove intermediate rsc/erc variables, use css_queue_crw_cont() [CH]
- s/crw0/crw/ [CH]
v1->v2:
- Add a loop to continually read region while data is
present, queueing CRWs as found [CH]
v0->v1: [EF]
- Fixed copy/paste error in error message (s/schib/CRW)
- 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 | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 73 insertions(+)
diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index 3ca2d83a30..5b620f97c3 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -44,7 +44,11 @@ struct VFIOCCWDevice {
uint64_t schib_region_size;
uint64_t schib_region_offset;
struct ccw_schib_region *schib_region;
+ uint64_t crw_region_size;
+ 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;
};
@@ -261,6 +265,44 @@ static void vfio_ccw_reset(DeviceState *dev)
ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET);
}
+static void vfio_ccw_crw_read(VFIOCCWDevice *vcdev)
+{
+ struct ccw_crw_region *region = vcdev->crw_region;
+ CRW crw;
+ int size;
+
+ /* Keep reading CRWs as long as data is returned */
+ do {
+ 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);
+ break;
+ }
+
+ if (region->crw == 0) {
+ /* No more CRWs to queue */
+ break;
+ }
+
+ memcpy(&crw, ®ion->crw, sizeof(CRW));
+
+ css_crw_add_to_queue(crw);
+ } while (1);
+}
+
+static void vfio_ccw_crw_notifier_handler(void *opaque)
+{
+ VFIOCCWDevice *vcdev = opaque;
+
+ while (event_notifier_test_and_clear(&vcdev->crw_notifier)) {
+ vfio_ccw_crw_read(vcdev);
+ }
+}
+
static void vfio_ccw_io_notifier_handler(void *opaque)
{
VFIOCCWDevice *vcdev = opaque;
@@ -347,6 +389,10 @@ static void vfio_ccw_register_irq_notifier(VFIOCCWDevice
*vcdev,
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)", irq);
return;
@@ -398,6 +444,9 @@ static void vfio_ccw_unregister_irq_notifier(VFIOCCWDevice
*vcdev,
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)", irq);
return;
@@ -475,10 +524,24 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev,
Error **errp)
vcdev->schib_region = g_malloc(info->size);
}
+ ret = vfio_get_dev_region_info(vdev, VFIO_REGION_TYPE_CCW,
+ VFIO_REGION_SUBTYPE_CCW_CRW, &info);
+
+ if (!ret) {
+ vcdev->crw_region_size = info->size;
+ if (sizeof(*vcdev->crw_region) != vcdev->crw_region_size) {
+ error_setg(errp, "vfio: Unexpected size of the CRW region");
+ goto out_err;
+ }
+ vcdev->crw_region_offset = info->offset;
+ vcdev->crw_region = g_malloc(info->size);
+ }
+
g_free(info);
return;
out_err:
+ g_free(vcdev->crw_region);
g_free(vcdev->schib_region);
g_free(vcdev->async_cmd_region);
g_free(vcdev->io_region);
@@ -488,6 +551,7 @@ out_err:
static void vfio_ccw_put_region(VFIOCCWDevice *vcdev)
{
+ g_free(vcdev->crw_region);
g_free(vcdev->schib_region);
g_free(vcdev->async_cmd_region);
g_free(vcdev->io_region);
@@ -603,6 +667,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:
@@ -627,6 +699,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
- [PATCH v4 0/6] s390x/vfio-ccw: Channel Path Handling [QEMU], Eric Farman, 2020/05/05
- [PATCH v4 4/6] vfio-ccw: Refactor ccw irq handler, Eric Farman, 2020/05/05
- [PATCH v4 3/6] vfio-ccw: Add support for the schib region, Eric Farman, 2020/05/05
- [PATCH v4 5/6] s390x/css: Refactor the css_queue_crw() routine, Eric Farman, 2020/05/05
- [PATCH v4 1/6] linux-headers: update, Eric Farman, 2020/05/05
- [PATCH v4 6/6] vfio-ccw: Add support for the CRW region and IRQ,
Eric Farman <=
- [PATCH v4 2/6] vfio-ccw: Refactor cleanup of regions, Eric Farman, 2020/05/05
- Re: [PATCH v4 0/6] s390x/vfio-ccw: Channel Path Handling [QEMU], Cornelia Huck, 2020/05/06