ath79/mikrotik: use routerbootpart partitions
[oweals/openwrt.git] / target / linux / layerscape / patches-5.4 / 821-vfio-0004-vfio-fsl-mc-Implement-VFIO_DEVICE_GET_REGION_INFO-io.patch
1 From 10abb46294d1569826854f77bcdb5d38d8db8e79 Mon Sep 17 00:00:00 2001
2 From: Diana Craciun <diana.craciun@nxp.com>
3 Date: Thu, 26 Sep 2019 15:13:24 +0300
4 Subject: [PATCH] vfio/fsl-mc: Implement VFIO_DEVICE_GET_REGION_INFO ioctl call
5
6 Expose to userspace information about the memory regions.
7
8 Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com>
9 Signed-off-by: Diana Craciun <diana.craciun@nxp.com>
10 ---
11  drivers/vfio/fsl-mc/vfio_fsl_mc.c         | 76 ++++++++++++++++++++++++++++++-
12  drivers/vfio/fsl-mc/vfio_fsl_mc_private.h | 19 ++++++++
13  2 files changed, 94 insertions(+), 1 deletion(-)
14
15 --- a/drivers/vfio/fsl-mc/vfio_fsl_mc.c
16 +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c
17 @@ -16,16 +16,70 @@
18  #include "vfio_fsl_mc_private.h"
19  
20  
21 +static int vfio_fsl_mc_regions_init(struct vfio_fsl_mc_device *vdev)
22 +{
23 +       struct fsl_mc_device *mc_dev = vdev->mc_dev;
24 +       int count = mc_dev->obj_desc.region_count;
25 +       int i;
26 +
27 +       vdev->regions = kcalloc(count, sizeof(struct vfio_fsl_mc_region),
28 +                               GFP_KERNEL);
29 +       if (!vdev->regions)
30 +               return -ENOMEM;
31 +
32 +       for (i = 0; i < count; i++) {
33 +               struct resource *res = &mc_dev->regions[i];
34 +
35 +               vdev->regions[i].addr = res->start;
36 +               vdev->regions[i].size = PAGE_ALIGN((resource_size(res)));
37 +               vdev->regions[i].flags = 0;
38 +       }
39 +
40 +       vdev->num_regions = mc_dev->obj_desc.region_count;
41 +       return 0;
42 +}
43 +static void vfio_fsl_mc_regions_cleanup(struct vfio_fsl_mc_device *vdev)
44 +{
45 +       vdev->num_regions = 0;
46 +       kfree(vdev->regions);
47 +}
48 +
49  static int vfio_fsl_mc_open(void *device_data)
50  {
51 +       struct vfio_fsl_mc_device *vdev = device_data;
52 +       int ret;
53 +
54         if (!try_module_get(THIS_MODULE))
55                 return -ENODEV;
56  
57 +       mutex_lock(&vdev->driver_lock);
58 +       if (!vdev->refcnt) {
59 +               ret = vfio_fsl_mc_regions_init(vdev);
60 +               if (ret)
61 +                       goto err_reg_init;
62 +       }
63 +       vdev->refcnt++;
64 +
65 +       mutex_unlock(&vdev->driver_lock);
66         return 0;
67 +
68 +err_reg_init:
69 +       mutex_unlock(&vdev->driver_lock);
70 +       module_put(THIS_MODULE);
71 +       return ret;
72  }
73  
74  static void vfio_fsl_mc_release(void *device_data)
75  {
76 +       struct vfio_fsl_mc_device *vdev = device_data;
77 +
78 +       mutex_lock(&vdev->driver_lock);
79 +
80 +       if (!(--vdev->refcnt))
81 +               vfio_fsl_mc_regions_cleanup(vdev);
82 +
83 +       mutex_unlock(&vdev->driver_lock);
84 +
85         module_put(THIS_MODULE);
86  }
87  
88 @@ -59,7 +113,26 @@ static long vfio_fsl_mc_ioctl(void *devi
89         }
90         case VFIO_DEVICE_GET_REGION_INFO:
91         {
92 -               return -EINVAL;
93 +               struct vfio_region_info info;
94 +
95 +               minsz = offsetofend(struct vfio_region_info, offset);
96 +
97 +               if (copy_from_user(&info, (void __user *)arg, minsz))
98 +                       return -EFAULT;
99 +
100 +               if (info.argsz < minsz)
101 +                       return -EINVAL;
102 +
103 +               if (info.index >= vdev->num_regions)
104 +                       return -EINVAL;
105 +
106 +               /* map offset to the physical address  */
107 +               info.offset = VFIO_FSL_MC_INDEX_TO_OFFSET(info.index);
108 +               info.size = vdev->regions[info.index].size;
109 +               info.flags = vdev->regions[info.index].flags;
110 +
111 +               return copy_to_user((void __user *)arg, &info, minsz);
112 +
113         }
114         case VFIO_DEVICE_GET_IRQ_INFO:
115         {
116 @@ -206,6 +279,7 @@ static int vfio_fsl_mc_probe(struct fsl_
117                 vfio_iommu_group_put(group, dev);
118                 return ret;
119         }
120 +       mutex_init(&vdev->driver_lock);
121  
122         return ret;
123  }
124 --- a/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h
125 +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h
126 @@ -7,8 +7,27 @@
127  #ifndef VFIO_FSL_MC_PRIVATE_H
128  #define VFIO_FSL_MC_PRIVATE_H
129  
130 +#define VFIO_FSL_MC_OFFSET_SHIFT    40
131 +#define VFIO_FSL_MC_OFFSET_MASK (((u64)(1) << VFIO_FSL_MC_OFFSET_SHIFT) - 1)
132 +
133 +#define VFIO_FSL_MC_OFFSET_TO_INDEX(off) (off >> VFIO_FSL_MC_OFFSET_SHIFT)
134 +
135 +#define VFIO_FSL_MC_INDEX_TO_OFFSET(index)     \
136 +       ((u64)(index) << VFIO_FSL_MC_OFFSET_SHIFT)
137 +
138 +struct vfio_fsl_mc_region {
139 +       u32                     flags;
140 +       u32                     type;
141 +       u64                     addr;
142 +       resource_size_t         size;
143 +};
144 +
145  struct vfio_fsl_mc_device {
146         struct fsl_mc_device            *mc_dev;
147 +       int                             refcnt;
148 +       u32                             num_regions;
149 +       struct vfio_fsl_mc_region       *regions;
150 +       struct mutex driver_lock;
151  };
152  
153  #endif /* VFIO_PCI_PRIVATE_H */