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 struct subchannel
*sch
= to_subchannel(private->vdev
.dev
->parent
);
20 unsigned int i
= VFIO_CCW_OFFSET_TO_INDEX(*ppos
) - VFIO_CCW_NUM_REGIONS
;
21 loff_t pos
= *ppos
& VFIO_CCW_OFFSET_MASK
;
22 struct ccw_schib_region
*region
;
25 if (pos
+ count
> sizeof(*region
))
28 mutex_lock(&private->io_mutex
);
29 region
= private->region
[i
].data
;
31 if (cio_update_schib(sch
)) {
36 memcpy(region
, &sch
->schib
, sizeof(*region
));
38 if (copy_to_user(buf
, (void *)region
+ pos
, count
)) {
46 mutex_unlock(&private->io_mutex
);
50 static ssize_t
vfio_ccw_schib_region_write(struct vfio_ccw_private
*private,
51 const char __user
*buf
, size_t count
,
58 static void vfio_ccw_schib_region_release(struct vfio_ccw_private
*private,
59 struct vfio_ccw_region
*region
)
64 static const struct vfio_ccw_regops vfio_ccw_schib_region_ops
= {
65 .read
= vfio_ccw_schib_region_read
,
66 .write
= vfio_ccw_schib_region_write
,
67 .release
= vfio_ccw_schib_region_release
,
70 int vfio_ccw_register_schib_dev_regions(struct vfio_ccw_private
*private)
72 return vfio_ccw_register_dev_region(private,
73 VFIO_REGION_SUBTYPE_CCW_SCHIB
,
74 &vfio_ccw_schib_region_ops
,
75 sizeof(struct ccw_schib_region
),
76 VFIO_REGION_INFO_FLAG_READ
,
77 private->schib_region
);
80 static ssize_t
vfio_ccw_crw_region_read(struct vfio_ccw_private
*private,
81 char __user
*buf
, size_t count
,
84 unsigned int i
= VFIO_CCW_OFFSET_TO_INDEX(*ppos
) - VFIO_CCW_NUM_REGIONS
;
85 loff_t pos
= *ppos
& VFIO_CCW_OFFSET_MASK
;
86 struct ccw_crw_region
*region
;
87 struct vfio_ccw_crw
*crw
;
90 if (pos
+ count
> sizeof(*region
))
93 crw
= list_first_entry_or_null(&private->crw
,
94 struct vfio_ccw_crw
, next
);
99 mutex_lock(&private->io_mutex
);
100 region
= private->region
[i
].data
;
103 memcpy(®ion
->crw
, &crw
->crw
, sizeof(region
->crw
));
105 if (copy_to_user(buf
, (void *)region
+ pos
, count
))
112 mutex_unlock(&private->io_mutex
);
116 /* Notify the guest if more CRWs are on our queue */
117 if (!list_empty(&private->crw
) && private->crw_trigger
)
118 eventfd_signal(private->crw_trigger
);
123 static ssize_t
vfio_ccw_crw_region_write(struct vfio_ccw_private
*private,
124 const char __user
*buf
, size_t count
,
130 static void vfio_ccw_crw_region_release(struct vfio_ccw_private
*private,
131 struct vfio_ccw_region
*region
)
136 static const struct vfio_ccw_regops vfio_ccw_crw_region_ops
= {
137 .read
= vfio_ccw_crw_region_read
,
138 .write
= vfio_ccw_crw_region_write
,
139 .release
= vfio_ccw_crw_region_release
,
142 int vfio_ccw_register_crw_dev_regions(struct vfio_ccw_private
*private)
144 return vfio_ccw_register_dev_region(private,
145 VFIO_REGION_SUBTYPE_CCW_CRW
,
146 &vfio_ccw_crw_region_ops
,
147 sizeof(struct ccw_crw_region
),
148 VFIO_REGION_INFO_FLAG_READ
,
149 private->crw_region
);