From: Eric Farman <farman@linux.ibm.com>
Date: Thu, 3 Dec 2020 22:35:12 +0100
Subject: [PATCH] vfio-ccw: Wire in the request callback
Patch-mainline: v5.11-rc1
Git-commit: bccce80bbd44ab50bbec761a51c6293c1ce47e34
References: bsc#1183225
The device is being unplugged, so pass the request to userspace to
ask for a graceful cleanup. This should free up the thread that
would otherwise loop waiting for the device to be fully released.
Signed-off-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Acked-by: Cho, Yu-Chen <acho@suse.com>
---
drivers/s390/cio/vfio_ccw_ops.c | 34 ++++++++++++++++++++++++++++++++++
drivers/s390/cio/vfio_ccw_private.h | 6 ++++++
include/uapi/linux/vfio.h | 3 +++
3 files changed, 43 insertions(+)
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -394,6 +394,9 @@ static int vfio_ccw_mdev_get_irq_info(st
switch (info->index) {
case VFIO_CCW_IO_IRQ_INDEX:
case VFIO_CCW_CRW_IRQ_INDEX:
+#ifndef __GENKSYMS__
+ case VFIO_CCW_REQ_IRQ_INDEX:
+#endif
info->count = 1;
info->flags = VFIO_IRQ_INFO_EVENTFD;
break;
@@ -424,6 +427,11 @@ static int vfio_ccw_mdev_set_irqs(struct
case VFIO_CCW_CRW_IRQ_INDEX:
ctx = &private->crw_trigger;
break;
+#ifndef __GENKSYMS__
+ case VFIO_CCW_REQ_IRQ_INDEX:
+ ctx = &private->req_trigger;
+ break;
+#endif
default:
return -EINVAL;
}
@@ -607,6 +615,29 @@ static ssize_t vfio_ccw_mdev_ioctl(struc
}
}
+#ifndef __GENKSYMS__
+/* Request removal of the device*/
+static void vfio_ccw_mdev_request(struct mdev_device *mdev, unsigned int count)
+{
+ struct vfio_ccw_private *private = dev_get_drvdata(mdev_parent_dev(mdev));
+
+ if (!private)
+ return;
+
+ if (private->req_trigger) {
+ if (!(count % 10))
+ dev_notice_ratelimited(mdev_dev(private->mdev),
+ "Relaying device request to user (#%u)\n",
+ count);
+
+ eventfd_signal(private->req_trigger, 1);
+ } else if (count == 0) {
+ dev_notice(mdev_dev(private->mdev),
+ "No device request channel registered, blocked until released by user\n");
+ }
+}
+#endif
+
static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
.owner = THIS_MODULE,
.supported_type_groups = mdev_type_groups,
@@ -617,6 +648,9 @@ static const struct mdev_parent_ops vfio
.read = vfio_ccw_mdev_read,
.write = vfio_ccw_mdev_write,
.ioctl = vfio_ccw_mdev_ioctl,
+#ifndef __GENKSYMS__
+ .request = vfio_ccw_mdev_request,
+#endif
};
int vfio_ccw_mdev_reg(struct subchannel *sch)
--- a/drivers/s390/cio/vfio_ccw_private.h
+++ b/drivers/s390/cio/vfio_ccw_private.h
@@ -84,7 +84,10 @@ struct vfio_ccw_crw {
* @irb: irb info received from interrupt
* @scsw: scsw info
* @io_trigger: eventfd ctx for signaling userspace I/O results
+ * @crw_trigger: eventfd ctx for signaling userspace CRW information
+ * @req_trigger: eventfd ctx for signaling userspace to return device
* @io_work: work for deferral process of I/O handling
+ * @crw_work: work for deferral process of CRW handling
*/
struct vfio_ccw_private {
struct subchannel *sch;
@@ -108,6 +111,9 @@ struct vfio_ccw_private {
struct eventfd_ctx *io_trigger;
struct eventfd_ctx *crw_trigger;
+#ifndef __GENKSYMS__
+ struct eventfd_ctx *req_trigger;
+#endif
struct work_struct io_work;
struct work_struct crw_work;
} __aligned(8);
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -819,6 +819,9 @@ enum {
enum {
VFIO_CCW_IO_IRQ_INDEX,
VFIO_CCW_CRW_IRQ_INDEX,
+#ifndef __GENKSYMS__
+ VFIO_CCW_REQ_IRQ_INDEX,
+#endif
VFIO_CCW_NUM_IRQS
};