88 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Async I/O region for vfio_ccw4 *5 * Copyright Red Hat, Inc. 20196 *7 * Author(s): Cornelia Huck <cohuck@redhat.com>8 */9 10#include <linux/vfio.h>11 12#include "vfio_ccw_private.h"13 14static ssize_t vfio_ccw_async_region_read(struct vfio_ccw_private *private,15 char __user *buf, size_t count,16 loff_t *ppos)17{18 unsigned int i = VFIO_CCW_OFFSET_TO_INDEX(*ppos) - VFIO_CCW_NUM_REGIONS;19 loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK;20 struct ccw_cmd_region *region;21 int ret;22 23 if (pos + count > sizeof(*region))24 return -EINVAL;25 26 mutex_lock(&private->io_mutex);27 region = private->region[i].data;28 if (copy_to_user(buf, (void *)region + pos, count))29 ret = -EFAULT;30 else31 ret = count;32 mutex_unlock(&private->io_mutex);33 return ret;34}35 36static ssize_t vfio_ccw_async_region_write(struct vfio_ccw_private *private,37 const char __user *buf, size_t count,38 loff_t *ppos)39{40 unsigned int i = VFIO_CCW_OFFSET_TO_INDEX(*ppos) - VFIO_CCW_NUM_REGIONS;41 loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK;42 struct ccw_cmd_region *region;43 int ret;44 45 if (pos + count > sizeof(*region))46 return -EINVAL;47 48 if (!mutex_trylock(&private->io_mutex))49 return -EAGAIN;50 51 region = private->region[i].data;52 if (copy_from_user((void *)region + pos, buf, count)) {53 ret = -EFAULT;54 goto out_unlock;55 }56 57 vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_ASYNC_REQ);58 59 ret = region->ret_code ? region->ret_code : count;60 61out_unlock:62 mutex_unlock(&private->io_mutex);63 return ret;64}65 66static void vfio_ccw_async_region_release(struct vfio_ccw_private *private,67 struct vfio_ccw_region *region)68{69 70}71 72static const struct vfio_ccw_regops vfio_ccw_async_region_ops = {73 .read = vfio_ccw_async_region_read,74 .write = vfio_ccw_async_region_write,75 .release = vfio_ccw_async_region_release,76};77 78int vfio_ccw_register_async_dev_regions(struct vfio_ccw_private *private)79{80 return vfio_ccw_register_dev_region(private,81 VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD,82 &vfio_ccw_async_region_ops,83 sizeof(struct ccw_cmd_region),84 VFIO_REGION_INFO_FLAG_READ |85 VFIO_REGION_INFO_FLAG_WRITE,86 private->cmd_region);87}88