diff options
author | Antonios Motakis <a.motakis@virtualopensystems.com> | 2015-03-16 16:08:48 -0400 |
---|---|---|
committer | Alex Williamson <alex.williamson@redhat.com> | 2015-03-16 16:08:48 -0400 |
commit | 682704c41e6d2238c1fb5c6ab83eedadd876fa0e (patch) | |
tree | a8a87b3d65f9f13115a4d2424ea78d8d8389e698 | |
parent | fad4d5b1f042a659e07ceba3a6d1744b30f8ff7c (diff) |
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: Antonios Motakis <a.motakis@virtualopensystems.com>
Signed-off-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
Reviewed-by: Eric Auger <eric.auger@linaro.org>
Tested-by: Eric Auger <eric.auger@linaro.org>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
-rw-r--r-- | drivers/vfio/platform/Makefile | 2 | ||||
-rw-r--r-- | drivers/vfio/platform/vfio_platform_common.c | 31 | ||||
-rw-r--r-- | drivers/vfio/platform/vfio_platform_irq.c | 51 | ||||
-rw-r--r-- | drivers/vfio/platform/vfio_platform_private.h | 10 |
4 files changed, 89 insertions, 5 deletions
diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile index 1957170ae429..81de144c0eaa 100644 --- a/drivers/vfio/platform/Makefile +++ b/drivers/vfio/platform/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | 1 | ||
2 | vfio-platform-y := vfio_platform.o vfio_platform_common.o | 2 | vfio-platform-y := vfio_platform.o vfio_platform_common.o vfio_platform_irq.o |
3 | 3 | ||
4 | obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o | 4 | obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o |
5 | 5 | ||
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c index d7fe2c71e8bc..908d5101e053 100644 --- a/drivers/vfio/platform/vfio_platform_common.c +++ b/drivers/vfio/platform/vfio_platform_common.c | |||
@@ -101,6 +101,7 @@ static void vfio_platform_release(void *device_data) | |||
101 | 101 | ||
102 | if (!(--vdev->refcnt)) { | 102 | if (!(--vdev->refcnt)) { |
103 | vfio_platform_regions_cleanup(vdev); | 103 | vfio_platform_regions_cleanup(vdev); |
104 | vfio_platform_irq_cleanup(vdev); | ||
104 | } | 105 | } |
105 | 106 | ||
106 | mutex_unlock(&driver_lock); | 107 | mutex_unlock(&driver_lock); |
@@ -122,6 +123,10 @@ static int vfio_platform_open(void *device_data) | |||
122 | ret = vfio_platform_regions_init(vdev); | 123 | ret = vfio_platform_regions_init(vdev); |
123 | if (ret) | 124 | if (ret) |
124 | goto err_reg; | 125 | goto err_reg; |
126 | |||
127 | ret = vfio_platform_irq_init(vdev); | ||
128 | if (ret) | ||
129 | goto err_irq; | ||
125 | } | 130 | } |
126 | 131 | ||
127 | vdev->refcnt++; | 132 | vdev->refcnt++; |
@@ -129,6 +134,8 @@ static int vfio_platform_open(void *device_data) | |||
129 | mutex_unlock(&driver_lock); | 134 | mutex_unlock(&driver_lock); |
130 | return 0; | 135 | return 0; |
131 | 136 | ||
137 | err_irq: | ||
138 | vfio_platform_regions_cleanup(vdev); | ||
132 | err_reg: | 139 | err_reg: |
133 | mutex_unlock(&driver_lock); | 140 | mutex_unlock(&driver_lock); |
134 | module_put(THIS_MODULE); | 141 | module_put(THIS_MODULE); |
@@ -154,7 +161,7 @@ static long vfio_platform_ioctl(void *device_data, | |||
154 | 161 | ||
155 | info.flags = vdev->flags; | 162 | info.flags = vdev->flags; |
156 | info.num_regions = vdev->num_regions; | 163 | info.num_regions = vdev->num_regions; |
157 | info.num_irqs = 0; | 164 | info.num_irqs = vdev->num_irqs; |
158 | 165 | ||
159 | return copy_to_user((void __user *)arg, &info, minsz); | 166 | return copy_to_user((void __user *)arg, &info, minsz); |
160 | 167 | ||
@@ -179,10 +186,26 @@ static long vfio_platform_ioctl(void *device_data, | |||
179 | 186 | ||
180 | return copy_to_user((void __user *)arg, &info, minsz); | 187 | return copy_to_user((void __user *)arg, &info, minsz); |
181 | 188 | ||
182 | } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) | 189 | } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) { |
183 | return -EINVAL; | 190 | struct vfio_irq_info info; |
191 | |||
192 | minsz = offsetofend(struct vfio_irq_info, count); | ||
193 | |||
194 | if (copy_from_user(&info, (void __user *)arg, minsz)) | ||
195 | return -EFAULT; | ||
196 | |||
197 | if (info.argsz < minsz) | ||
198 | return -EINVAL; | ||
199 | |||
200 | if (info.index >= vdev->num_irqs) | ||
201 | return -EINVAL; | ||
202 | |||
203 | info.flags = vdev->irqs[info.index].flags; | ||
204 | info.count = vdev->irqs[info.index].count; | ||
205 | |||
206 | return copy_to_user((void __user *)arg, &info, minsz); | ||
184 | 207 | ||
185 | else if (cmd == VFIO_DEVICE_SET_IRQS) | 208 | } else if (cmd == VFIO_DEVICE_SET_IRQS) |
186 | return -EINVAL; | 209 | return -EINVAL; |
187 | 210 | ||
188 | else if (cmd == VFIO_DEVICE_RESET) | 211 | else if (cmd == VFIO_DEVICE_RESET) |
diff --git a/drivers/vfio/platform/vfio_platform_irq.c b/drivers/vfio/platform/vfio_platform_irq.c new file mode 100644 index 000000000000..c6c3ec1b9f82 --- /dev/null +++ b/drivers/vfio/platform/vfio_platform_irq.c | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * VFIO platform devices interrupt handling | ||
3 | * | ||
4 | * Copyright (C) 2013 - Virtual Open Systems | ||
5 | * Author: Antonios Motakis <a.motakis@virtualopensystems.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License, version 2, as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/eventfd.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/vfio.h> | ||
22 | #include <linux/irq.h> | ||
23 | |||
24 | #include "vfio_platform_private.h" | ||
25 | |||
26 | int vfio_platform_irq_init(struct vfio_platform_device *vdev) | ||
27 | { | ||
28 | int cnt = 0, i; | ||
29 | |||
30 | while (vdev->get_irq(vdev, cnt) >= 0) | ||
31 | cnt++; | ||
32 | |||
33 | vdev->irqs = kcalloc(cnt, sizeof(struct vfio_platform_irq), GFP_KERNEL); | ||
34 | if (!vdev->irqs) | ||
35 | return -ENOMEM; | ||
36 | |||
37 | for (i = 0; i < cnt; i++) { | ||
38 | vdev->irqs[i].flags = 0; | ||
39 | vdev->irqs[i].count = 1; | ||
40 | } | ||
41 | |||
42 | vdev->num_irqs = cnt; | ||
43 | |||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev) | ||
48 | { | ||
49 | vdev->num_irqs = 0; | ||
50 | kfree(vdev->irqs); | ||
51 | } | ||
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h index 97c78f9791f1..a2e286ed1407 100644 --- a/drivers/vfio/platform/vfio_platform_private.h +++ b/drivers/vfio/platform/vfio_platform_private.h | |||
@@ -27,6 +27,11 @@ | |||
27 | #define VFIO_PLATFORM_INDEX_TO_OFFSET(index) \ | 27 | #define VFIO_PLATFORM_INDEX_TO_OFFSET(index) \ |
28 | ((u64)(index) << VFIO_PLATFORM_OFFSET_SHIFT) | 28 | ((u64)(index) << VFIO_PLATFORM_OFFSET_SHIFT) |
29 | 29 | ||
30 | struct vfio_platform_irq { | ||
31 | u32 flags; | ||
32 | u32 count; | ||
33 | }; | ||
34 | |||
30 | struct vfio_platform_region { | 35 | struct vfio_platform_region { |
31 | u64 addr; | 36 | u64 addr; |
32 | resource_size_t size; | 37 | resource_size_t size; |
@@ -40,6 +45,8 @@ struct vfio_platform_region { | |||
40 | struct vfio_platform_device { | 45 | struct vfio_platform_device { |
41 | struct vfio_platform_region *regions; | 46 | struct vfio_platform_region *regions; |
42 | u32 num_regions; | 47 | u32 num_regions; |
48 | struct vfio_platform_irq *irqs; | ||
49 | u32 num_irqs; | ||
43 | int refcnt; | 50 | int refcnt; |
44 | 51 | ||
45 | /* | 52 | /* |
@@ -59,4 +66,7 @@ extern int vfio_platform_probe_common(struct vfio_platform_device *vdev, | |||
59 | extern struct vfio_platform_device *vfio_platform_remove_common | 66 | extern struct vfio_platform_device *vfio_platform_remove_common |
60 | (struct device *dev); | 67 | (struct device *dev); |
61 | 68 | ||
69 | extern int vfio_platform_irq_init(struct vfio_platform_device *vdev); | ||
70 | extern void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev); | ||
71 | |||
62 | #endif /* VFIO_PLATFORM_PRIVATE_H */ | 72 | #endif /* VFIO_PLATFORM_PRIVATE_H */ |