ath79/mikrotik: use routerbootpart partitions
[oweals/openwrt.git] / target / linux / layerscape / patches-5.4 / 821-vfio-0006-vfio-fsl-mc-Added-lock-support-in-preparation-for-in.patch
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 */