490f4e35f81860d9b81d6d8de562b45ab411574c
[openwrt/staging/pepe2k.git] /
1 From 9ea8e954812efc4fc9b27e553019295d4dcd0407 Mon Sep 17 00:00:00 2001
2 From: Diana Craciun <diana.craciun@nxp.com>
3 Date: Tue, 15 Oct 2019 11:22:26 +0300
4 Subject: [PATCH] vfio/fsl-mc: Added lock support in preparation for interrupt
5 handling
6
7 All the devices in a DPRC share the same pool of interrupts.
8 Because of this the access to the pool of interrupts must be
9 protected with a lock. Extend the current lock implementation
10 to have a lock per DPRC.
11
12 Signed-off-by: Diana Craciun <diana.craciun@nxp.com>
13 ---
14 drivers/vfio/fsl-mc/vfio_fsl_mc.c | 90 ++++++++++++++++++++++++++++---
15 drivers/vfio/fsl-mc/vfio_fsl_mc_private.h | 7 ++-
16 2 files changed, 89 insertions(+), 8 deletions(-)
17
18 --- a/drivers/vfio/fsl-mc/vfio_fsl_mc.c
19 +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c
20 @@ -15,6 +15,75 @@
21
22 #include "vfio_fsl_mc_private.h"
23
24 +static DEFINE_MUTEX(reflck_lock);
25 +
26 +static void vfio_fsl_mc_reflck_get(struct vfio_fsl_mc_reflck *reflck)
27 +{
28 + kref_get(&reflck->kref);
29 +}
30 +
31 +static void vfio_fsl_mc_reflck_release(struct kref *kref)
32 +{
33 + struct vfio_fsl_mc_reflck *reflck = container_of(kref,
34 + struct vfio_fsl_mc_reflck,
35 + kref);
36 +
37 + kfree(reflck);
38 + mutex_unlock(&reflck_lock);
39 +}
40 +
41 +static void vfio_fsl_mc_reflck_put(struct vfio_fsl_mc_reflck *reflck)
42 +{
43 + kref_put_mutex(&reflck->kref, vfio_fsl_mc_reflck_release, &reflck_lock);
44 +}
45 +
46 +static struct vfio_fsl_mc_reflck *vfio_fsl_mc_reflck_alloc(void)
47 +{
48 + struct vfio_fsl_mc_reflck *reflck;
49 +
50 + reflck = kzalloc(sizeof(*reflck), GFP_KERNEL);
51 + if (!reflck)
52 + return ERR_PTR(-ENOMEM);
53 +
54 + kref_init(&reflck->kref);
55 + mutex_init(&reflck->lock);
56 +
57 + return reflck;
58 +}
59 +
60 +static int vfio_fsl_mc_reflck_attach(struct vfio_fsl_mc_device *vdev)
61 +{
62 + int ret = 0;
63 +
64 + mutex_lock(&reflck_lock);
65 + if (is_fsl_mc_bus_dprc(vdev->mc_dev)) {
66 + vdev->reflck = vfio_fsl_mc_reflck_alloc();
67 + } else {
68 + struct device *mc_cont_dev = vdev->mc_dev->dev.parent;
69 + struct vfio_device *device;
70 + struct vfio_fsl_mc_device *cont_vdev;
71 +
72 + device = vfio_device_get_from_dev(mc_cont_dev);
73 + if (!device) {
74 + ret = -ENODEV;
75 + goto unlock;
76 + }
77 +
78 + cont_vdev = vfio_device_data(device);
79 + if (!cont_vdev->reflck) {
80 + vfio_device_put(device);
81 + ret = -ENODEV;
82 + goto unlock;
83 + }
84 + vfio_fsl_mc_reflck_get(cont_vdev->reflck);
85 + vdev->reflck = cont_vdev->reflck;
86 + vfio_device_put(device);
87 + }
88 +
89 +unlock:
90 + mutex_unlock(&reflck_lock);
91 + return ret;
92 +}
93
94 static int vfio_fsl_mc_regions_init(struct vfio_fsl_mc_device *vdev)
95 {
96 @@ -55,7 +124,7 @@ static int vfio_fsl_mc_open(void *device
97 if (!try_module_get(THIS_MODULE))
98 return -ENODEV;
99
100 - mutex_lock(&vdev->driver_lock);
101 + mutex_lock(&vdev->reflck->lock);
102 if (!vdev->refcnt) {
103 ret = vfio_fsl_mc_regions_init(vdev);
104 if (ret)
105 @@ -63,11 +132,11 @@ static int vfio_fsl_mc_open(void *device
106 }
107 vdev->refcnt++;
108
109 - mutex_unlock(&vdev->driver_lock);
110 + mutex_unlock(&vdev->reflck->lock);
111 return 0;
112
113 err_reg_init:
114 - mutex_unlock(&vdev->driver_lock);
115 + mutex_unlock(&vdev->reflck->lock);
116 module_put(THIS_MODULE);
117 return ret;
118 }
119 @@ -76,12 +145,12 @@ static void vfio_fsl_mc_release(void *de
120 {
121 struct vfio_fsl_mc_device *vdev = device_data;
122
123 - mutex_lock(&vdev->driver_lock);
124 + mutex_lock(&vdev->reflck->lock);
125
126 if (!(--vdev->refcnt))
127 vfio_fsl_mc_regions_cleanup(vdev);
128
129 - mutex_unlock(&vdev->driver_lock);
130 + mutex_unlock(&vdev->reflck->lock);
131
132 module_put(THIS_MODULE);
133 }
134 @@ -180,7 +249,6 @@ static int vfio_fsl_mc_mmap_mmio(struct
135 return -EINVAL;
136
137 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
138 -
139 vma->vm_pgoff = (region.addr >> PAGE_SHIFT) + pgoff;
140
141 return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
142 @@ -335,12 +403,18 @@ static int vfio_fsl_mc_probe(struct fsl_
143 return ret;
144 }
145
146 + ret = vfio_fsl_mc_reflck_attach(vdev);
147 + if (ret) {
148 + vfio_iommu_group_put(group, dev);
149 + return ret;
150 + }
151 +
152 ret = vfio_fsl_mc_init_device(vdev);
153 if (ret) {
154 + vfio_fsl_mc_reflck_put(vdev->reflck);
155 vfio_iommu_group_put(group, dev);
156 return ret;
157 }
158 - mutex_init(&vdev->driver_lock);
159
160 return ret;
161 }
162 @@ -374,6 +448,8 @@ static int vfio_fsl_mc_remove(struct fsl
163 if (!vdev)
164 return -EINVAL;
165
166 + vfio_fsl_mc_reflck_put(vdev->reflck);
167 +
168 if (is_fsl_mc_bus_dprc(mc_dev))
169 vfio_fsl_mc_cleanup_dprc(vdev->mc_dev);
170
171 --- a/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h
172 +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h
173 @@ -15,6 +15,11 @@
174 #define VFIO_FSL_MC_INDEX_TO_OFFSET(index) \
175 ((u64)(index) << VFIO_FSL_MC_OFFSET_SHIFT)
176
177 +struct vfio_fsl_mc_reflck {
178 + struct kref kref;
179 + struct mutex lock;
180 +};
181 +
182 struct vfio_fsl_mc_region {
183 u32 flags;
184 u32 type;
185 @@ -27,7 +32,7 @@ struct vfio_fsl_mc_device {
186 int refcnt;
187 u32 num_regions;
188 struct vfio_fsl_mc_region *regions;
189 - struct mutex driver_lock;
190 + struct vfio_fsl_mc_reflck *reflck;
191 };
192
193 #endif /* VFIO_PCI_PRIVATE_H */