124c98674SFarhan Ali // SPDX-License-Identifier: GPL-2.0 224c98674SFarhan Ali /* 324c98674SFarhan Ali * Channel path related status regions for vfio_ccw 424c98674SFarhan Ali * 524c98674SFarhan Ali * Copyright IBM Corp. 2020 624c98674SFarhan Ali * 724c98674SFarhan Ali * Author(s): Farhan Ali <alifm@linux.ibm.com> 824c98674SFarhan Ali * Eric Farman <farman@linux.ibm.com> 924c98674SFarhan Ali */ 1024c98674SFarhan Ali 1124c98674SFarhan Ali #include <linux/vfio.h> 1224c98674SFarhan Ali #include "vfio_ccw_private.h" 1324c98674SFarhan Ali 1424c98674SFarhan Ali static ssize_t vfio_ccw_schib_region_read(struct vfio_ccw_private *private, 1524c98674SFarhan Ali char __user *buf, size_t count, 1624c98674SFarhan Ali loff_t *ppos) 1724c98674SFarhan Ali { 1824c98674SFarhan Ali unsigned int i = VFIO_CCW_OFFSET_TO_INDEX(*ppos) - VFIO_CCW_NUM_REGIONS; 1924c98674SFarhan Ali loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK; 2024c98674SFarhan Ali struct ccw_schib_region *region; 2124c98674SFarhan Ali int ret; 2224c98674SFarhan Ali 2324c98674SFarhan Ali if (pos + count > sizeof(*region)) 2424c98674SFarhan Ali return -EINVAL; 2524c98674SFarhan Ali 2624c98674SFarhan Ali mutex_lock(&private->io_mutex); 2724c98674SFarhan Ali region = private->region[i].data; 2824c98674SFarhan Ali 2924c98674SFarhan Ali if (cio_update_schib(private->sch)) { 3024c98674SFarhan Ali ret = -ENODEV; 3124c98674SFarhan Ali goto out; 3224c98674SFarhan Ali } 3324c98674SFarhan Ali 3424c98674SFarhan Ali memcpy(region, &private->sch->schib, sizeof(*region)); 3524c98674SFarhan Ali 3624c98674SFarhan Ali if (copy_to_user(buf, (void *)region + pos, count)) { 3724c98674SFarhan Ali ret = -EFAULT; 3824c98674SFarhan Ali goto out; 3924c98674SFarhan Ali } 4024c98674SFarhan Ali 4124c98674SFarhan Ali ret = count; 4224c98674SFarhan Ali 4324c98674SFarhan Ali out: 4424c98674SFarhan Ali mutex_unlock(&private->io_mutex); 4524c98674SFarhan Ali return ret; 4624c98674SFarhan Ali } 4724c98674SFarhan Ali 4824c98674SFarhan Ali static ssize_t vfio_ccw_schib_region_write(struct vfio_ccw_private *private, 4924c98674SFarhan Ali const char __user *buf, size_t count, 5024c98674SFarhan Ali loff_t *ppos) 5124c98674SFarhan Ali { 5224c98674SFarhan Ali return -EINVAL; 5324c98674SFarhan Ali } 5424c98674SFarhan Ali 5524c98674SFarhan Ali 5624c98674SFarhan Ali static void vfio_ccw_schib_region_release(struct vfio_ccw_private *private, 5724c98674SFarhan Ali struct vfio_ccw_region *region) 5824c98674SFarhan Ali { 5924c98674SFarhan Ali 6024c98674SFarhan Ali } 6124c98674SFarhan Ali 6224c98674SFarhan Ali const struct vfio_ccw_regops vfio_ccw_schib_region_ops = { 6324c98674SFarhan Ali .read = vfio_ccw_schib_region_read, 6424c98674SFarhan Ali .write = vfio_ccw_schib_region_write, 6524c98674SFarhan Ali .release = vfio_ccw_schib_region_release, 6624c98674SFarhan Ali }; 6724c98674SFarhan Ali 6824c98674SFarhan Ali int vfio_ccw_register_schib_dev_regions(struct vfio_ccw_private *private) 6924c98674SFarhan Ali { 7024c98674SFarhan Ali return vfio_ccw_register_dev_region(private, 7124c98674SFarhan Ali VFIO_REGION_SUBTYPE_CCW_SCHIB, 7224c98674SFarhan Ali &vfio_ccw_schib_region_ops, 7324c98674SFarhan Ali sizeof(struct ccw_schib_region), 7424c98674SFarhan Ali VFIO_REGION_INFO_FLAG_READ, 7524c98674SFarhan Ali private->schib_region); 7624c98674SFarhan Ali } 77d8cac29bSFarhan Ali 78d8cac29bSFarhan Ali static ssize_t vfio_ccw_crw_region_read(struct vfio_ccw_private *private, 79d8cac29bSFarhan Ali char __user *buf, size_t count, 80d8cac29bSFarhan Ali loff_t *ppos) 81d8cac29bSFarhan Ali { 82d8cac29bSFarhan Ali unsigned int i = VFIO_CCW_OFFSET_TO_INDEX(*ppos) - VFIO_CCW_NUM_REGIONS; 83d8cac29bSFarhan Ali loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK; 84d8cac29bSFarhan Ali struct ccw_crw_region *region; 85d8cac29bSFarhan Ali int ret; 86d8cac29bSFarhan Ali 87d8cac29bSFarhan Ali if (pos + count > sizeof(*region)) 88d8cac29bSFarhan Ali return -EINVAL; 89d8cac29bSFarhan Ali 90d8cac29bSFarhan Ali mutex_lock(&private->io_mutex); 91d8cac29bSFarhan Ali region = private->region[i].data; 92d8cac29bSFarhan Ali 93d8cac29bSFarhan Ali if (copy_to_user(buf, (void *)region + pos, count)) 94d8cac29bSFarhan Ali ret = -EFAULT; 95d8cac29bSFarhan Ali else 96d8cac29bSFarhan Ali ret = count; 97d8cac29bSFarhan Ali 98d8cac29bSFarhan Ali region->crw = 0; 99d8cac29bSFarhan Ali 100d8cac29bSFarhan Ali mutex_unlock(&private->io_mutex); 101d8cac29bSFarhan Ali return ret; 102d8cac29bSFarhan Ali } 103d8cac29bSFarhan Ali 104d8cac29bSFarhan Ali static ssize_t vfio_ccw_crw_region_write(struct vfio_ccw_private *private, 105d8cac29bSFarhan Ali const char __user *buf, size_t count, 106d8cac29bSFarhan Ali loff_t *ppos) 107d8cac29bSFarhan Ali { 108d8cac29bSFarhan Ali return -EINVAL; 109d8cac29bSFarhan Ali } 110d8cac29bSFarhan Ali 111d8cac29bSFarhan Ali static void vfio_ccw_crw_region_release(struct vfio_ccw_private *private, 112d8cac29bSFarhan Ali struct vfio_ccw_region *region) 113d8cac29bSFarhan Ali { 114d8cac29bSFarhan Ali 115d8cac29bSFarhan Ali } 116d8cac29bSFarhan Ali 117d8cac29bSFarhan Ali const struct vfio_ccw_regops vfio_ccw_crw_region_ops = { 118d8cac29bSFarhan Ali .read = vfio_ccw_crw_region_read, 119d8cac29bSFarhan Ali .write = vfio_ccw_crw_region_write, 120d8cac29bSFarhan Ali .release = vfio_ccw_crw_region_release, 121d8cac29bSFarhan Ali }; 122d8cac29bSFarhan Ali 123d8cac29bSFarhan Ali int vfio_ccw_register_crw_dev_regions(struct vfio_ccw_private *private) 124d8cac29bSFarhan Ali { 125d8cac29bSFarhan Ali return vfio_ccw_register_dev_region(private, 126d8cac29bSFarhan Ali VFIO_REGION_SUBTYPE_CCW_CRW, 127d8cac29bSFarhan Ali &vfio_ccw_crw_region_ops, 128d8cac29bSFarhan Ali sizeof(struct ccw_crw_region), 129d8cac29bSFarhan Ali VFIO_REGION_INFO_FLAG_READ, 130d8cac29bSFarhan Ali private->crw_region); 131d8cac29bSFarhan Ali } 132