Commit 186bfe44 authored by Gerd Bayer's avatar Gerd Bayer Committed by Alex Williamson
Browse files

vfio/pci: Extract duplicated code into macro



vfio_pci_core_do_io_rw() repeats the same code for multiple access
widths. Factor this out into a macro

Suggested-by: default avatarAlex Williamson <alex.williamson@redhat.com>
Signed-off-by: default avatarGerd Bayer <gbayer@linux.ibm.com>
Link: https://lore.kernel.org/r/20240619115847.1344875-2-gbayer@linux.ibm.com


Signed-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent 6ba59ff4
Loading
Loading
Loading
Loading
+46 −60
Original line number Diff line number Diff line
@@ -90,6 +90,40 @@ VFIO_IOREAD(8)
VFIO_IOREAD(16)
VFIO_IOREAD(32)

#define VFIO_IORDWR(size)						\
static int vfio_pci_iordwr##size(struct vfio_pci_core_device *vdev,\
				bool iswrite, bool test_mem,		\
				void __iomem *io, char __user *buf,	\
				loff_t off, size_t *filled)		\
{									\
	u##size val;							\
	int ret;							\
									\
	if (iswrite) {							\
		if (copy_from_user(&val, buf, sizeof(val)))		\
			return -EFAULT;					\
									\
		ret = vfio_pci_core_iowrite##size(vdev, test_mem,	\
						  val, io + off);	\
		if (ret)						\
			return ret;					\
	} else {							\
		ret = vfio_pci_core_ioread##size(vdev, test_mem,	\
						 &val, io + off);	\
		if (ret)						\
			return ret;					\
									\
		if (copy_to_user(buf, &val, sizeof(val)))		\
			return -EFAULT;					\
	}								\
									\
	*filled = sizeof(val);						\
	return 0;							\
}									\

VFIO_IORDWR(8)
VFIO_IORDWR(16)
VFIO_IORDWR(32)
/*
 * Read or write from an __iomem region (MMIO or I/O port) with an excluded
 * range which is inaccessible.  The excluded range drops writes and fills
@@ -115,71 +149,23 @@ ssize_t vfio_pci_core_do_io_rw(struct vfio_pci_core_device *vdev, bool test_mem,
			fillable = 0;

		if (fillable >= 4 && !(off % 4)) {
			u32 val;

			if (iswrite) {
				if (copy_from_user(&val, buf, 4))
					return -EFAULT;

				ret = vfio_pci_core_iowrite32(vdev, test_mem,
							      val, io + off);
			ret = vfio_pci_iordwr32(vdev, iswrite, test_mem,
						io, buf, off, &filled);
			if (ret)
				return ret;
			} else {
				ret = vfio_pci_core_ioread32(vdev, test_mem,
							     &val, io + off);
				if (ret)
					return ret;

				if (copy_to_user(buf, &val, 4))
					return -EFAULT;
			}

			filled = 4;
		} else if (fillable >= 2 && !(off % 2)) {
			u16 val;

			if (iswrite) {
				if (copy_from_user(&val, buf, 2))
					return -EFAULT;

				ret = vfio_pci_core_iowrite16(vdev, test_mem,
							      val, io + off);
			ret = vfio_pci_iordwr16(vdev, iswrite, test_mem,
						io, buf, off, &filled);
			if (ret)
				return ret;
			} else {
				ret = vfio_pci_core_ioread16(vdev, test_mem,
							     &val, io + off);
				if (ret)
					return ret;

				if (copy_to_user(buf, &val, 2))
					return -EFAULT;
			}

			filled = 2;
		} else if (fillable) {
			u8 val;

			if (iswrite) {
				if (copy_from_user(&val, buf, 1))
					return -EFAULT;

				ret = vfio_pci_core_iowrite8(vdev, test_mem,
							     val, io + off);
			ret = vfio_pci_iordwr8(vdev, iswrite, test_mem,
					       io, buf, off, &filled);
			if (ret)
				return ret;
			} else {
				ret = vfio_pci_core_ioread8(vdev, test_mem,
							    &val, io + off);
				if (ret)
					return ret;

				if (copy_to_user(buf, &val, 1))
					return -EFAULT;
			}

			filled = 1;
		} else {
			/* Fill reads with -1, drop writes */
			filled = min(count, (size_t)(x_end - off));