1 // SPDX-License-Identifier: GPL-2.0
3 * Channel path related status regions for vfio_ccw
5 * Copyright IBM Corp. 2020
7 * Author(s): Farhan Ali <alifm@linux.ibm.com>
8 * Eric Farman <farman@linux.ibm.com>
11 #include <linux/slab.h>
12 #include <linux/vfio.h>
13 #include "vfio_ccw_private.h"
15 static ssize_t
vfio_ccw_schib_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_schib_region
*region
;
24 if (pos
+ count
> sizeof(*region
))
27 mutex_lock(&private->io_mutex
);
28 region
= private->region
[i
].data
;
30 if (cio_update_schib(private->sch
)) {
35 memcpy(region
, &private->sch
->schib
, sizeof(*region
));
37 if (copy_to_user(buf
, (void *)region
+ pos
, count
)) {
45 mutex_unlock(&private->io_mutex
);
49 static ssize_t
vfio_ccw_schib_region_write(struct vfio_ccw_private
*private,
50 const char __user
*buf
, size_t count
,
57 static void vfio_ccw_schib_region_release(struct vfio_ccw_private
*private,
58 struct vfio_ccw_region
*region
)
63 static const struct vfio_ccw_regops vfio_ccw_schib_region_ops
= {
64 .read
= vfio_ccw_schib_region_read
,
65 .write
= vfio_ccw_schib_region_write
,
66 .release
= vfio_ccw_schib_region_release
,
69 int vfio_ccw_register_schib_dev_regions(struct vfio_ccw_private
*private)
71 return vfio_ccw_register_dev_region(private,
72 VFIO_REGION_SUBTYPE_CCW_SCHIB
,
73 &vfio_ccw_schib_region_ops
,
74 sizeof(struct ccw_schib_region
),
75 VFIO_REGION_INFO_FLAG_READ
,
76 private->schib_region
);
79 static ssize_t
vfio_ccw_crw_region_read(struct vfio_ccw_private
*private,
80 char __user
*buf
, size_t count
,
83 unsigned int i
= VFIO_CCW_OFFSET_TO_INDEX(*ppos
) - VFIO_CCW_NUM_REGIONS
;
84 loff_t pos
= *ppos
& VFIO_CCW_OFFSET_MASK
;
85 struct ccw_crw_region
*region
;
86 struct vfio_ccw_crw
*crw
;
89 if (pos
+ count
> sizeof(*region
))
92 crw
= list_first_entry_or_null(&private->crw
,
93 struct vfio_ccw_crw
, next
);
98 mutex_lock(&private->io_mutex
);
99 region
= private->region
[i
].data
;
102 memcpy(®ion
->crw
, &crw
->crw
, sizeof(region
->crw
));
104 if (copy_to_user(buf
, (void *)region
+ pos
, count
))
111 mutex_unlock(&private->io_mutex
);
115 /* Notify the guest if more CRWs are on our queue */
116 if (!list_empty(&private->crw
) && private->crw_trigger
)
117 eventfd_signal(private->crw_trigger
, 1);
122 static ssize_t
vfio_ccw_crw_region_write(struct vfio_ccw_private
*private,
123 const char __user
*buf
, size_t count
,
129 static void vfio_ccw_crw_region_release(struct vfio_ccw_private
*private,
130 struct vfio_ccw_region
*region
)
135 static const struct vfio_ccw_regops vfio_ccw_crw_region_ops
= {
136 .read
= vfio_ccw_crw_region_read
,
137 .write
= vfio_ccw_crw_region_write
,
138 .release
= vfio_ccw_crw_region_release
,
141 int vfio_ccw_register_crw_dev_regions(struct vfio_ccw_private
*private)
143 return vfio_ccw_register_dev_region(private,
144 VFIO_REGION_SUBTYPE_CCW_CRW
,
145 &vfio_ccw_crw_region_ops
,
146 sizeof(struct ccw_crw_region
),
147 VFIO_REGION_INFO_FLAG_READ
,
148 private->crw_region
);