Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Channel path related status regions for vfio_ccw
0004  *
0005  * Copyright IBM Corp. 2020
0006  *
0007  * Author(s): Farhan Ali <alifm@linux.ibm.com>
0008  *            Eric Farman <farman@linux.ibm.com>
0009  */
0010 
0011 #include <linux/slab.h>
0012 #include <linux/vfio.h>
0013 #include "vfio_ccw_private.h"
0014 
0015 static ssize_t vfio_ccw_schib_region_read(struct vfio_ccw_private *private,
0016                       char __user *buf, size_t count,
0017                       loff_t *ppos)
0018 {
0019     unsigned int i = VFIO_CCW_OFFSET_TO_INDEX(*ppos) - VFIO_CCW_NUM_REGIONS;
0020     loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK;
0021     struct ccw_schib_region *region;
0022     int ret;
0023 
0024     if (pos + count > sizeof(*region))
0025         return -EINVAL;
0026 
0027     mutex_lock(&private->io_mutex);
0028     region = private->region[i].data;
0029 
0030     if (cio_update_schib(private->sch)) {
0031         ret = -ENODEV;
0032         goto out;
0033     }
0034 
0035     memcpy(region, &private->sch->schib, sizeof(*region));
0036 
0037     if (copy_to_user(buf, (void *)region + pos, count)) {
0038         ret = -EFAULT;
0039         goto out;
0040     }
0041 
0042     ret = count;
0043 
0044 out:
0045     mutex_unlock(&private->io_mutex);
0046     return ret;
0047 }
0048 
0049 static ssize_t vfio_ccw_schib_region_write(struct vfio_ccw_private *private,
0050                        const char __user *buf, size_t count,
0051                        loff_t *ppos)
0052 {
0053     return -EINVAL;
0054 }
0055 
0056 
0057 static void vfio_ccw_schib_region_release(struct vfio_ccw_private *private,
0058                       struct vfio_ccw_region *region)
0059 {
0060 
0061 }
0062 
0063 static const struct vfio_ccw_regops vfio_ccw_schib_region_ops = {
0064     .read = vfio_ccw_schib_region_read,
0065     .write = vfio_ccw_schib_region_write,
0066     .release = vfio_ccw_schib_region_release,
0067 };
0068 
0069 int vfio_ccw_register_schib_dev_regions(struct vfio_ccw_private *private)
0070 {
0071     return vfio_ccw_register_dev_region(private,
0072                         VFIO_REGION_SUBTYPE_CCW_SCHIB,
0073                         &vfio_ccw_schib_region_ops,
0074                         sizeof(struct ccw_schib_region),
0075                         VFIO_REGION_INFO_FLAG_READ,
0076                         private->schib_region);
0077 }
0078 
0079 static ssize_t vfio_ccw_crw_region_read(struct vfio_ccw_private *private,
0080                     char __user *buf, size_t count,
0081                     loff_t *ppos)
0082 {
0083     unsigned int i = VFIO_CCW_OFFSET_TO_INDEX(*ppos) - VFIO_CCW_NUM_REGIONS;
0084     loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK;
0085     struct ccw_crw_region *region;
0086     struct vfio_ccw_crw *crw;
0087     int ret;
0088 
0089     if (pos + count > sizeof(*region))
0090         return -EINVAL;
0091 
0092     crw = list_first_entry_or_null(&private->crw,
0093                        struct vfio_ccw_crw, next);
0094 
0095     if (crw)
0096         list_del(&crw->next);
0097 
0098     mutex_lock(&private->io_mutex);
0099     region = private->region[i].data;
0100 
0101     if (crw)
0102         memcpy(&region->crw, &crw->crw, sizeof(region->crw));
0103 
0104     if (copy_to_user(buf, (void *)region + pos, count))
0105         ret = -EFAULT;
0106     else
0107         ret = count;
0108 
0109     region->crw = 0;
0110 
0111     mutex_unlock(&private->io_mutex);
0112 
0113     kfree(crw);
0114 
0115     /* Notify the guest if more CRWs are on our queue */
0116     if (!list_empty(&private->crw) && private->crw_trigger)
0117         eventfd_signal(private->crw_trigger, 1);
0118 
0119     return ret;
0120 }
0121 
0122 static ssize_t vfio_ccw_crw_region_write(struct vfio_ccw_private *private,
0123                      const char __user *buf, size_t count,
0124                      loff_t *ppos)
0125 {
0126     return -EINVAL;
0127 }
0128 
0129 static void vfio_ccw_crw_region_release(struct vfio_ccw_private *private,
0130                     struct vfio_ccw_region *region)
0131 {
0132 
0133 }
0134 
0135 static const struct vfio_ccw_regops vfio_ccw_crw_region_ops = {
0136     .read = vfio_ccw_crw_region_read,
0137     .write = vfio_ccw_crw_region_write,
0138     .release = vfio_ccw_crw_region_release,
0139 };
0140 
0141 int vfio_ccw_register_crw_dev_regions(struct vfio_ccw_private *private)
0142 {
0143     return vfio_ccw_register_dev_region(private,
0144                         VFIO_REGION_SUBTYPE_CCW_CRW,
0145                         &vfio_ccw_crw_region_ops,
0146                         sizeof(struct ccw_crw_region),
0147                         VFIO_REGION_INFO_FLAG_READ,
0148                         private->crw_region);
0149 }