vfio-ccw: Wire in the request callback

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>
This commit is contained in:
Eric Farman
2020-12-03 22:35:12 +01:00
committed by Alex Williamson
parent a15ac665b9
commit bccce80bbd
3 changed files with 31 additions and 0 deletions

View File

@@ -394,6 +394,7 @@ static int vfio_ccw_mdev_get_irq_info(struct vfio_irq_info *info)
switch (info->index) { switch (info->index) {
case VFIO_CCW_IO_IRQ_INDEX: case VFIO_CCW_IO_IRQ_INDEX:
case VFIO_CCW_CRW_IRQ_INDEX: case VFIO_CCW_CRW_IRQ_INDEX:
case VFIO_CCW_REQ_IRQ_INDEX:
info->count = 1; info->count = 1;
info->flags = VFIO_IRQ_INFO_EVENTFD; info->flags = VFIO_IRQ_INFO_EVENTFD;
break; break;
@@ -424,6 +425,9 @@ static int vfio_ccw_mdev_set_irqs(struct mdev_device *mdev,
case VFIO_CCW_CRW_IRQ_INDEX: case VFIO_CCW_CRW_IRQ_INDEX:
ctx = &private->crw_trigger; ctx = &private->crw_trigger;
break; break;
case VFIO_CCW_REQ_IRQ_INDEX:
ctx = &private->req_trigger;
break;
default: default:
return -EINVAL; return -EINVAL;
} }
@@ -607,6 +611,27 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev,
} }
} }
/* 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");
}
}
static const struct mdev_parent_ops vfio_ccw_mdev_ops = { static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.supported_type_groups = mdev_type_groups, .supported_type_groups = mdev_type_groups,
@@ -617,6 +642,7 @@ static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
.read = vfio_ccw_mdev_read, .read = vfio_ccw_mdev_read,
.write = vfio_ccw_mdev_write, .write = vfio_ccw_mdev_write,
.ioctl = vfio_ccw_mdev_ioctl, .ioctl = vfio_ccw_mdev_ioctl,
.request = vfio_ccw_mdev_request,
}; };
int vfio_ccw_mdev_reg(struct subchannel *sch) int vfio_ccw_mdev_reg(struct subchannel *sch)

View File

@@ -84,7 +84,10 @@ struct vfio_ccw_crw {
* @irb: irb info received from interrupt * @irb: irb info received from interrupt
* @scsw: scsw info * @scsw: scsw info
* @io_trigger: eventfd ctx for signaling userspace I/O results * @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 * @io_work: work for deferral process of I/O handling
* @crw_work: work for deferral process of CRW handling
*/ */
struct vfio_ccw_private { struct vfio_ccw_private {
struct subchannel *sch; struct subchannel *sch;
@@ -108,6 +111,7 @@ struct vfio_ccw_private {
struct eventfd_ctx *io_trigger; struct eventfd_ctx *io_trigger;
struct eventfd_ctx *crw_trigger; struct eventfd_ctx *crw_trigger;
struct eventfd_ctx *req_trigger;
struct work_struct io_work; struct work_struct io_work;
struct work_struct crw_work; struct work_struct crw_work;
} __aligned(8); } __aligned(8);

View File

@@ -820,6 +820,7 @@ enum {
enum { enum {
VFIO_CCW_IO_IRQ_INDEX, VFIO_CCW_IO_IRQ_INDEX,
VFIO_CCW_CRW_IRQ_INDEX, VFIO_CCW_CRW_IRQ_INDEX,
VFIO_CCW_REQ_IRQ_INDEX,
VFIO_CCW_NUM_IRQS VFIO_CCW_NUM_IRQS
}; };