diff options
Diffstat (limited to 'drivers/s390/cio/vfio_ccw_ops.c')
-rw-r--r-- | drivers/s390/cio/vfio_ccw_ops.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c index b8a2fed..6c06805 100644 --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -127,6 +127,51 @@ void vfio_ccw_mdev_release(struct mdev_device *mdev) &private->nb); } +static ssize_t vfio_ccw_mdev_read(struct mdev_device *mdev, + char __user *buf, + size_t count, + loff_t *ppos) +{ + struct vfio_ccw_private *private; + struct ccw_io_region *region; + + if (*ppos + count > sizeof(*region)) + return -EINVAL; + + private = dev_get_drvdata(mdev_parent_dev(mdev)); + if (!private) + return -ENODEV; + + region = &private->io_region; + if (copy_to_user(buf, (void *)region + *ppos, count)) + return -EFAULT; + + return count; +} + +static ssize_t vfio_ccw_mdev_write(struct mdev_device *mdev, + const char __user *buf, + size_t count, + loff_t *ppos) +{ + struct vfio_ccw_private *private; + struct ccw_io_region *region; + + if (*ppos + count > sizeof(*region)) + return -EINVAL; + + private = dev_get_drvdata(mdev_parent_dev(mdev)); + if (!private) + return -ENODEV; + + region = &private->io_region; + if (copy_from_user((void *)region + *ppos, buf, count)) + return -EFAULT; + region->ret_code = 0; + + return count; +} + static const struct mdev_parent_ops vfio_ccw_mdev_ops = { .owner = THIS_MODULE, .supported_type_groups = mdev_type_groups, @@ -134,6 +179,8 @@ static const struct mdev_parent_ops vfio_ccw_mdev_ops = { .remove = vfio_ccw_mdev_remove, .open = vfio_ccw_mdev_open, .release = vfio_ccw_mdev_release, + .read = vfio_ccw_mdev_read, + .write = vfio_ccw_mdev_write, }; int vfio_ccw_mdev_reg(struct subchannel *sch) |