Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 682704c4 authored by Antonios Motakis's avatar Antonios Motakis Committed by Alex Williamson
Browse files

vfio/platform: return IRQ info



Return information for the interrupts exposed by the device.
This patch extends VFIO_DEVICE_GET_INFO with the number of IRQs
and enables VFIO_DEVICE_GET_IRQ_INFO.

Signed-off-by: default avatarAntonios Motakis <a.motakis@virtualopensystems.com>
Signed-off-by: default avatarBaptiste Reynal <b.reynal@virtualopensystems.com>
Reviewed-by: default avatarEric Auger <eric.auger@linaro.org>
Tested-by: default avatarEric Auger <eric.auger@linaro.org>
Signed-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent fad4d5b1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line

vfio-platform-y := vfio_platform.o vfio_platform_common.o
vfio-platform-y := vfio_platform.o vfio_platform_common.o vfio_platform_irq.o

obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o

+27 −4
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ static void vfio_platform_release(void *device_data)

	if (!(--vdev->refcnt)) {
		vfio_platform_regions_cleanup(vdev);
		vfio_platform_irq_cleanup(vdev);
	}

	mutex_unlock(&driver_lock);
@@ -122,6 +123,10 @@ static int vfio_platform_open(void *device_data)
		ret = vfio_platform_regions_init(vdev);
		if (ret)
			goto err_reg;

		ret = vfio_platform_irq_init(vdev);
		if (ret)
			goto err_irq;
	}

	vdev->refcnt++;
@@ -129,6 +134,8 @@ static int vfio_platform_open(void *device_data)
	mutex_unlock(&driver_lock);
	return 0;

err_irq:
	vfio_platform_regions_cleanup(vdev);
err_reg:
	mutex_unlock(&driver_lock);
	module_put(THIS_MODULE);
@@ -154,7 +161,7 @@ static long vfio_platform_ioctl(void *device_data,

		info.flags = vdev->flags;
		info.num_regions = vdev->num_regions;
		info.num_irqs = 0;
		info.num_irqs = vdev->num_irqs;

		return copy_to_user((void __user *)arg, &info, minsz);

@@ -179,10 +186,26 @@ static long vfio_platform_ioctl(void *device_data,

		return copy_to_user((void __user *)arg, &info, minsz);

	} else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
	} else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) {
		struct vfio_irq_info info;

		minsz = offsetofend(struct vfio_irq_info, count);

		if (copy_from_user(&info, (void __user *)arg, minsz))
			return -EFAULT;

		if (info.argsz < minsz)
			return -EINVAL;

		if (info.index >= vdev->num_irqs)
			return -EINVAL;

	else if (cmd == VFIO_DEVICE_SET_IRQS)
		info.flags = vdev->irqs[info.index].flags;
		info.count = vdev->irqs[info.index].count;

		return copy_to_user((void __user *)arg, &info, minsz);

	} else if (cmd == VFIO_DEVICE_SET_IRQS)
		return -EINVAL;

	else if (cmd == VFIO_DEVICE_RESET)
+51 −0
Original line number Diff line number Diff line
/*
 * VFIO platform devices interrupt handling
 *
 * Copyright (C) 2013 - Virtual Open Systems
 * Author: Antonios Motakis <a.motakis@virtualopensystems.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2, as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/eventfd.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/vfio.h>
#include <linux/irq.h>

#include "vfio_platform_private.h"

int vfio_platform_irq_init(struct vfio_platform_device *vdev)
{
	int cnt = 0, i;

	while (vdev->get_irq(vdev, cnt) >= 0)
		cnt++;

	vdev->irqs = kcalloc(cnt, sizeof(struct vfio_platform_irq), GFP_KERNEL);
	if (!vdev->irqs)
		return -ENOMEM;

	for (i = 0; i < cnt; i++) {
		vdev->irqs[i].flags = 0;
		vdev->irqs[i].count = 1;
	}

	vdev->num_irqs = cnt;

	return 0;
}

void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev)
{
	vdev->num_irqs = 0;
	kfree(vdev->irqs);
}
+10 −0
Original line number Diff line number Diff line
@@ -27,6 +27,11 @@
#define VFIO_PLATFORM_INDEX_TO_OFFSET(index)	\
	((u64)(index) << VFIO_PLATFORM_OFFSET_SHIFT)

struct vfio_platform_irq {
	u32			flags;
	u32			count;
};

struct vfio_platform_region {
	u64			addr;
	resource_size_t		size;
@@ -40,6 +45,8 @@ struct vfio_platform_region {
struct vfio_platform_device {
	struct vfio_platform_region	*regions;
	u32				num_regions;
	struct vfio_platform_irq	*irqs;
	u32				num_irqs;
	int				refcnt;

	/*
@@ -59,4 +66,7 @@ extern int vfio_platform_probe_common(struct vfio_platform_device *vdev,
extern struct vfio_platform_device *vfio_platform_remove_common
				     (struct device *dev);

extern int vfio_platform_irq_init(struct vfio_platform_device *vdev);
extern void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev);

#endif /* VFIO_PLATFORM_PRIVATE_H */