1 // SPDX-License-Identifier: GPL-2.0
3 * Async I/O region for vfio_ccw
5 * Copyright Red Hat, Inc. 2019
10 #include <linux/vfio.h>
11 #include <linux/mdev.h>
13 #include "vfio_ccw_private.h"
15 static ssize_t vfio_ccw_async_region_read(struct vfio_ccw_private *private,
16 char __user *buf, size_t count,
19 unsigned int i = VFIO_CCW_OFFSET_TO_INDEX(*ppos) - VFIO_CCW_NUM_REGIONS;
20 loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK;
21 struct ccw_cmd_region *region;
24 if (pos + count > sizeof(*region))
27 mutex_lock(&private->io_mutex);
28 region = private->region[i].data;
29 if (copy_to_user(buf, (void *)region + pos, count))
33 mutex_unlock(&private->io_mutex);
37 static ssize_t vfio_ccw_async_region_write(struct vfio_ccw_private *private,
38 const char __user *buf, size_t count,
41 unsigned int i = VFIO_CCW_OFFSET_TO_INDEX(*ppos) - VFIO_CCW_NUM_REGIONS;
42 loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK;
43 struct ccw_cmd_region *region;
46 if (pos + count > sizeof(*region))
49 if (!mutex_trylock(&private->io_mutex))
52 region = private->region[i].data;
53 if (copy_from_user((void *)region + pos, buf, count)) {
58 vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_ASYNC_REQ);
60 ret = region->ret_code ? region->ret_code : count;
63 mutex_unlock(&private->io_mutex);
67 static void vfio_ccw_async_region_release(struct vfio_ccw_private *private,
68 struct vfio_ccw_region *region)
73 static const struct vfio_ccw_regops vfio_ccw_async_region_ops = {
74 .read = vfio_ccw_async_region_read,
75 .write = vfio_ccw_async_region_write,
76 .release = vfio_ccw_async_region_release,
79 int vfio_ccw_register_async_dev_regions(struct vfio_ccw_private *private)
81 return vfio_ccw_register_dev_region(private,
82 VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD,
83 &vfio_ccw_async_region_ops,
84 sizeof(struct ccw_cmd_region),
85 VFIO_REGION_INFO_FLAG_READ |
86 VFIO_REGION_INFO_FLAG_WRITE,