1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2013 - Virtual Open Systems |
4 | * Author: Antonios Motakis <a.motakis@virtualopensystems.com> |
5 | */ |
6 | |
7 | #include <linux/module.h> |
8 | #include <linux/slab.h> |
9 | #include <linux/vfio.h> |
10 | #include <linux/pm_runtime.h> |
11 | #include <linux/platform_device.h> |
12 | |
13 | #include "vfio_platform_private.h" |
14 | |
15 | #define DRIVER_VERSION "0.10" |
16 | #define DRIVER_AUTHOR "Antonios Motakis <a.motakis@virtualopensystems.com>" |
17 | #define DRIVER_DESC "VFIO for platform devices - User Level meta-driver" |
18 | |
19 | static bool reset_required = true; |
20 | module_param(reset_required, bool, 0444); |
21 | MODULE_PARM_DESC(reset_required, "override reset requirement (default: 1)" ); |
22 | |
23 | /* probing devices from the linux platform bus */ |
24 | |
25 | static struct resource *get_platform_resource(struct vfio_platform_device *vdev, |
26 | int num) |
27 | { |
28 | struct platform_device *dev = (struct platform_device *) vdev->opaque; |
29 | |
30 | return platform_get_mem_or_io(dev, num); |
31 | } |
32 | |
33 | static int get_platform_irq(struct vfio_platform_device *vdev, int i) |
34 | { |
35 | struct platform_device *pdev = (struct platform_device *) vdev->opaque; |
36 | |
37 | return platform_get_irq_optional(pdev, i); |
38 | } |
39 | |
40 | static int vfio_platform_init_dev(struct vfio_device *core_vdev) |
41 | { |
42 | struct vfio_platform_device *vdev = |
43 | container_of(core_vdev, struct vfio_platform_device, vdev); |
44 | struct platform_device *pdev = to_platform_device(core_vdev->dev); |
45 | |
46 | vdev->opaque = (void *) pdev; |
47 | vdev->name = pdev->name; |
48 | vdev->flags = VFIO_DEVICE_FLAGS_PLATFORM; |
49 | vdev->get_resource = get_platform_resource; |
50 | vdev->get_irq = get_platform_irq; |
51 | vdev->reset_required = reset_required; |
52 | |
53 | return vfio_platform_init_common(vdev); |
54 | } |
55 | |
56 | static const struct vfio_device_ops vfio_platform_ops; |
57 | static int vfio_platform_probe(struct platform_device *pdev) |
58 | { |
59 | struct vfio_platform_device *vdev; |
60 | int ret; |
61 | |
62 | vdev = vfio_alloc_device(vfio_platform_device, vdev, &pdev->dev, |
63 | &vfio_platform_ops); |
64 | if (IS_ERR(ptr: vdev)) |
65 | return PTR_ERR(ptr: vdev); |
66 | |
67 | ret = vfio_register_group_dev(device: &vdev->vdev); |
68 | if (ret) |
69 | goto out_put_vdev; |
70 | |
71 | pm_runtime_enable(dev: &pdev->dev); |
72 | dev_set_drvdata(dev: &pdev->dev, data: vdev); |
73 | return 0; |
74 | |
75 | out_put_vdev: |
76 | vfio_put_device(device: &vdev->vdev); |
77 | return ret; |
78 | } |
79 | |
80 | static void vfio_platform_release_dev(struct vfio_device *core_vdev) |
81 | { |
82 | struct vfio_platform_device *vdev = |
83 | container_of(core_vdev, struct vfio_platform_device, vdev); |
84 | |
85 | vfio_platform_release_common(vdev); |
86 | } |
87 | |
88 | static void vfio_platform_remove(struct platform_device *pdev) |
89 | { |
90 | struct vfio_platform_device *vdev = dev_get_drvdata(dev: &pdev->dev); |
91 | |
92 | vfio_unregister_group_dev(device: &vdev->vdev); |
93 | pm_runtime_disable(dev: vdev->device); |
94 | vfio_put_device(device: &vdev->vdev); |
95 | } |
96 | |
97 | static const struct vfio_device_ops vfio_platform_ops = { |
98 | .name = "vfio-platform" , |
99 | .init = vfio_platform_init_dev, |
100 | .release = vfio_platform_release_dev, |
101 | .open_device = vfio_platform_open_device, |
102 | .close_device = vfio_platform_close_device, |
103 | .ioctl = vfio_platform_ioctl, |
104 | .read = vfio_platform_read, |
105 | .write = vfio_platform_write, |
106 | .mmap = vfio_platform_mmap, |
107 | .bind_iommufd = vfio_iommufd_physical_bind, |
108 | .unbind_iommufd = vfio_iommufd_physical_unbind, |
109 | .attach_ioas = vfio_iommufd_physical_attach_ioas, |
110 | .detach_ioas = vfio_iommufd_physical_detach_ioas, |
111 | }; |
112 | |
113 | static struct platform_driver vfio_platform_driver = { |
114 | .probe = vfio_platform_probe, |
115 | .remove_new = vfio_platform_remove, |
116 | .driver = { |
117 | .name = "vfio-platform" , |
118 | }, |
119 | .driver_managed_dma = true, |
120 | }; |
121 | |
122 | module_platform_driver(vfio_platform_driver); |
123 | |
124 | MODULE_VERSION(DRIVER_VERSION); |
125 | MODULE_LICENSE("GPL v2" ); |
126 | MODULE_AUTHOR(DRIVER_AUTHOR); |
127 | MODULE_DESCRIPTION(DRIVER_DESC); |
128 | |