diff options
author | Antonios Motakis <a.motakis@virtualopensystems.com> | 2015-03-16 16:08:49 -0400 |
---|---|---|
committer | Alex Williamson <alex.williamson@redhat.com> | 2015-03-16 16:08:49 -0400 |
commit | 9a36321c8d3350c4f7befa02adf3ce4583287ad9 (patch) | |
tree | 7297fc06e32c1fd44a5abb893e8095cae3cb7e14 /drivers/vfio | |
parent | 682704c41e6d2238c1fb5c6ab83eedadd876fa0e (diff) |
vfio/platform: initial interrupts support code
This patch is a skeleton for the VFIO_DEVICE_SET_IRQS IOCTL, around which
most IRQ functionality is implemented in VFIO.
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>
Diffstat (limited to 'drivers/vfio')
-rw-r--r-- | drivers/vfio/platform/vfio_platform_common.c | 52 | ||||
-rw-r--r-- | drivers/vfio/platform/vfio_platform_irq.c | 59 | ||||
-rw-r--r-- | drivers/vfio/platform/vfio_platform_private.h | 7 |
3 files changed, 115 insertions, 3 deletions
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c index 908d5101e053..abcff7a1aa66 100644 --- a/drivers/vfio/platform/vfio_platform_common.c +++ b/drivers/vfio/platform/vfio_platform_common.c | |||
@@ -205,10 +205,54 @@ static long vfio_platform_ioctl(void *device_data, | |||
205 | 205 | ||
206 | return copy_to_user((void __user *)arg, &info, minsz); | 206 | return copy_to_user((void __user *)arg, &info, minsz); |
207 | 207 | ||
208 | } else if (cmd == VFIO_DEVICE_SET_IRQS) | 208 | } else if (cmd == VFIO_DEVICE_SET_IRQS) { |
209 | return -EINVAL; | 209 | struct vfio_irq_set hdr; |
210 | u8 *data = NULL; | ||
211 | int ret = 0; | ||
212 | |||
213 | minsz = offsetofend(struct vfio_irq_set, count); | ||
214 | |||
215 | if (copy_from_user(&hdr, (void __user *)arg, minsz)) | ||
216 | return -EFAULT; | ||
217 | |||
218 | if (hdr.argsz < minsz) | ||
219 | return -EINVAL; | ||
220 | |||
221 | if (hdr.index >= vdev->num_irqs) | ||
222 | return -EINVAL; | ||
223 | |||
224 | if (hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK | | ||
225 | VFIO_IRQ_SET_ACTION_TYPE_MASK)) | ||
226 | return -EINVAL; | ||
210 | 227 | ||
211 | else if (cmd == VFIO_DEVICE_RESET) | 228 | if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) { |
229 | size_t size; | ||
230 | |||
231 | if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL) | ||
232 | size = sizeof(uint8_t); | ||
233 | else if (hdr.flags & VFIO_IRQ_SET_DATA_EVENTFD) | ||
234 | size = sizeof(int32_t); | ||
235 | else | ||
236 | return -EINVAL; | ||
237 | |||
238 | if (hdr.argsz - minsz < size) | ||
239 | return -EINVAL; | ||
240 | |||
241 | data = memdup_user((void __user *)(arg + minsz), size); | ||
242 | if (IS_ERR(data)) | ||
243 | return PTR_ERR(data); | ||
244 | } | ||
245 | |||
246 | mutex_lock(&vdev->igate); | ||
247 | |||
248 | ret = vfio_platform_set_irqs_ioctl(vdev, hdr.flags, hdr.index, | ||
249 | hdr.start, hdr.count, data); | ||
250 | mutex_unlock(&vdev->igate); | ||
251 | kfree(data); | ||
252 | |||
253 | return ret; | ||
254 | |||
255 | } else if (cmd == VFIO_DEVICE_RESET) | ||
212 | return -EINVAL; | 256 | return -EINVAL; |
213 | 257 | ||
214 | return -ENOTTY; | 258 | return -ENOTTY; |
@@ -458,6 +502,8 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev, | |||
458 | return ret; | 502 | return ret; |
459 | } | 503 | } |
460 | 504 | ||
505 | mutex_init(&vdev->igate); | ||
506 | |||
461 | return 0; | 507 | return 0; |
462 | } | 508 | } |
463 | EXPORT_SYMBOL_GPL(vfio_platform_probe_common); | 509 | EXPORT_SYMBOL_GPL(vfio_platform_probe_common); |
diff --git a/drivers/vfio/platform/vfio_platform_irq.c b/drivers/vfio/platform/vfio_platform_irq.c index c6c3ec1b9f82..df5c91936a68 100644 --- a/drivers/vfio/platform/vfio_platform_irq.c +++ b/drivers/vfio/platform/vfio_platform_irq.c | |||
@@ -23,6 +23,56 @@ | |||
23 | 23 | ||
24 | #include "vfio_platform_private.h" | 24 | #include "vfio_platform_private.h" |
25 | 25 | ||
26 | static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev, | ||
27 | unsigned index, unsigned start, | ||
28 | unsigned count, uint32_t flags, | ||
29 | void *data) | ||
30 | { | ||
31 | return -EINVAL; | ||
32 | } | ||
33 | |||
34 | static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev, | ||
35 | unsigned index, unsigned start, | ||
36 | unsigned count, uint32_t flags, | ||
37 | void *data) | ||
38 | { | ||
39 | return -EINVAL; | ||
40 | } | ||
41 | |||
42 | static int vfio_platform_set_irq_trigger(struct vfio_platform_device *vdev, | ||
43 | unsigned index, unsigned start, | ||
44 | unsigned count, uint32_t flags, | ||
45 | void *data) | ||
46 | { | ||
47 | return -EINVAL; | ||
48 | } | ||
49 | |||
50 | int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev, | ||
51 | uint32_t flags, unsigned index, unsigned start, | ||
52 | unsigned count, void *data) | ||
53 | { | ||
54 | int (*func)(struct vfio_platform_device *vdev, unsigned index, | ||
55 | unsigned start, unsigned count, uint32_t flags, | ||
56 | void *data) = NULL; | ||
57 | |||
58 | switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) { | ||
59 | case VFIO_IRQ_SET_ACTION_MASK: | ||
60 | func = vfio_platform_set_irq_mask; | ||
61 | break; | ||
62 | case VFIO_IRQ_SET_ACTION_UNMASK: | ||
63 | func = vfio_platform_set_irq_unmask; | ||
64 | break; | ||
65 | case VFIO_IRQ_SET_ACTION_TRIGGER: | ||
66 | func = vfio_platform_set_irq_trigger; | ||
67 | break; | ||
68 | } | ||
69 | |||
70 | if (!func) | ||
71 | return -ENOTTY; | ||
72 | |||
73 | return func(vdev, index, start, count, flags, data); | ||
74 | } | ||
75 | |||
26 | int vfio_platform_irq_init(struct vfio_platform_device *vdev) | 76 | int vfio_platform_irq_init(struct vfio_platform_device *vdev) |
27 | { | 77 | { |
28 | int cnt = 0, i; | 78 | int cnt = 0, i; |
@@ -35,13 +85,22 @@ int vfio_platform_irq_init(struct vfio_platform_device *vdev) | |||
35 | return -ENOMEM; | 85 | return -ENOMEM; |
36 | 86 | ||
37 | for (i = 0; i < cnt; i++) { | 87 | for (i = 0; i < cnt; i++) { |
88 | int hwirq = vdev->get_irq(vdev, i); | ||
89 | |||
90 | if (hwirq < 0) | ||
91 | goto err; | ||
92 | |||
38 | vdev->irqs[i].flags = 0; | 93 | vdev->irqs[i].flags = 0; |
39 | vdev->irqs[i].count = 1; | 94 | vdev->irqs[i].count = 1; |
95 | vdev->irqs[i].hwirq = hwirq; | ||
40 | } | 96 | } |
41 | 97 | ||
42 | vdev->num_irqs = cnt; | 98 | vdev->num_irqs = cnt; |
43 | 99 | ||
44 | return 0; | 100 | return 0; |
101 | err: | ||
102 | kfree(vdev->irqs); | ||
103 | return -EINVAL; | ||
45 | } | 104 | } |
46 | 105 | ||
47 | void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev) | 106 | void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev) |
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h index a2e286ed1407..b119a6c5ac23 100644 --- a/drivers/vfio/platform/vfio_platform_private.h +++ b/drivers/vfio/platform/vfio_platform_private.h | |||
@@ -30,6 +30,7 @@ | |||
30 | struct vfio_platform_irq { | 30 | struct vfio_platform_irq { |
31 | u32 flags; | 31 | u32 flags; |
32 | u32 count; | 32 | u32 count; |
33 | int hwirq; | ||
33 | }; | 34 | }; |
34 | 35 | ||
35 | struct vfio_platform_region { | 36 | struct vfio_platform_region { |
@@ -48,6 +49,7 @@ struct vfio_platform_device { | |||
48 | struct vfio_platform_irq *irqs; | 49 | struct vfio_platform_irq *irqs; |
49 | u32 num_irqs; | 50 | u32 num_irqs; |
50 | int refcnt; | 51 | int refcnt; |
52 | struct mutex igate; | ||
51 | 53 | ||
52 | /* | 54 | /* |
53 | * These fields should be filled by the bus specific binder | 55 | * These fields should be filled by the bus specific binder |
@@ -69,4 +71,9 @@ extern struct vfio_platform_device *vfio_platform_remove_common | |||
69 | extern int vfio_platform_irq_init(struct vfio_platform_device *vdev); | 71 | extern int vfio_platform_irq_init(struct vfio_platform_device *vdev); |
70 | extern void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev); | 72 | extern void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev); |
71 | 73 | ||
74 | extern int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev, | ||
75 | uint32_t flags, unsigned index, | ||
76 | unsigned start, unsigned count, | ||
77 | void *data); | ||
78 | |||
72 | #endif /* VFIO_PLATFORM_PRIVATE_H */ | 79 | #endif /* VFIO_PLATFORM_PRIVATE_H */ |