1
2
3
4
5
6
7
8
9
10#include <linux/vfio.h>
11#include <linux/mdev.h>
12
13#include "vfio_ccw_private.h"
14
15static ssize_t vfio_ccw_async_region_read(struct vfio_ccw_private *private,
16 char __user *buf, size_t count,
17 loff_t *ppos)
18{
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;
22 int ret;
23
24 if (pos + count > sizeof(*region))
25 return -EINVAL;
26
27 mutex_lock(&private->io_mutex);
28 region = private->region[i].data;
29 if (copy_to_user(buf, (void *)region + pos, count))
30 ret = -EFAULT;
31 else
32 ret = count;
33 mutex_unlock(&private->io_mutex);
34 return ret;
35}
36
37static ssize_t vfio_ccw_async_region_write(struct vfio_ccw_private *private,
38 const char __user *buf, size_t count,
39 loff_t *ppos)
40{
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;
44 int ret;
45
46 if (pos + count > sizeof(*region))
47 return -EINVAL;
48
49 if (!mutex_trylock(&private->io_mutex))
50 return -EAGAIN;
51
52 region = private->region[i].data;
53 if (copy_from_user((void *)region + pos, buf, count)) {
54 ret = -EFAULT;
55 goto out_unlock;
56 }
57
58 vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_ASYNC_REQ);
59
60 ret = region->ret_code ? region->ret_code : count;
61
62out_unlock:
63 mutex_unlock(&private->io_mutex);
64 return ret;
65}
66
67static void vfio_ccw_async_region_release(struct vfio_ccw_private *private,
68 struct vfio_ccw_region *region)
69{
70
71}
72
73static 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,
77};
78
79int vfio_ccw_register_async_dev_regions(struct vfio_ccw_private *private)
80{
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,
87 private->cmd_region);
88}
89