aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-5.4/821-vfio-0006-vfio-fsl-mc-Added-lock-support-in-preparation-for-in.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/layerscape/patches-5.4/821-vfio-0006-vfio-fsl-mc-Added-lock-support-in-preparation-for-in.patch')
-rw-r--r--target/linux/layerscape/patches-5.4/821-vfio-0006-vfio-fsl-mc-Added-lock-support-in-preparation-for-in.patch193
1 files changed, 193 insertions, 0 deletions
diff --git a/target/linux/layerscape/patches-5.4/821-vfio-0006-vfio-fsl-mc-Added-lock-support-in-preparation-for-in.patch b/target/linux/layerscape/patches-5.4/821-vfio-0006-vfio-fsl-mc-Added-lock-support-in-preparation-for-in.patch
new file mode 100644
index 0000000000..490f4e35f8
--- /dev/null
+++ b/target/linux/layerscape/patches-5.4/821-vfio-0006-vfio-fsl-mc-Added-lock-support-in-preparation-for-in.patch
@@ -0,0 +1,193 @@
+From 9ea8e954812efc4fc9b27e553019295d4dcd0407 Mon Sep 17 00:00:00 2001
+From: Diana Craciun <diana.craciun@nxp.com>
+Date: Tue, 15 Oct 2019 11:22:26 +0300
+Subject: [PATCH] vfio/fsl-mc: Added lock support in preparation for interrupt
+ handling
+
+All the devices in a DPRC share the same pool of interrupts.
+Because of this the access to the pool of interrupts must be
+protected with a lock. Extend the current lock implementation
+to have a lock per DPRC.
+
+Signed-off-by: Diana Craciun <diana.craciun@nxp.com>
+---
+ drivers/vfio/fsl-mc/vfio_fsl_mc.c | 90 ++++++++++++++++++++++++++++---
+ drivers/vfio/fsl-mc/vfio_fsl_mc_private.h | 7 ++-
+ 2 files changed, 89 insertions(+), 8 deletions(-)
+
+--- a/drivers/vfio/fsl-mc/vfio_fsl_mc.c
++++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c
+@@ -15,6 +15,75 @@
+
+ #include "vfio_fsl_mc_private.h"
+
++static DEFINE_MUTEX(reflck_lock);
++
++static void vfio_fsl_mc_reflck_get(struct vfio_fsl_mc_reflck *reflck)
++{
++ kref_get(&reflck->kref);
++}
++
++static void vfio_fsl_mc_reflck_release(struct kref *kref)
++{
++ struct vfio_fsl_mc_reflck *reflck = container_of(kref,
++ struct vfio_fsl_mc_reflck,
++ kref);
++
++ kfree(reflck);
++ mutex_unlock(&reflck_lock);
++}
++
++static void vfio_fsl_mc_reflck_put(struct vfio_fsl_mc_reflck *reflck)
++{
++ kref_put_mutex(&reflck->kref, vfio_fsl_mc_reflck_release, &reflck_lock);
++}
++
++static struct vfio_fsl_mc_reflck *vfio_fsl_mc_reflck_alloc(void)
++{
++ struct vfio_fsl_mc_reflck *reflck;
++
++ reflck = kzalloc(sizeof(*reflck), GFP_KERNEL);
++ if (!reflck)
++ return ERR_PTR(-ENOMEM);
++
++ kref_init(&reflck->kref);
++ mutex_init(&reflck->lock);
++
++ return reflck;
++}
++
++static int vfio_fsl_mc_reflck_attach(struct vfio_fsl_mc_device *vdev)
++{
++ int ret = 0;
++
++ mutex_lock(&reflck_lock);
++ if (is_fsl_mc_bus_dprc(vdev->mc_dev)) {
++ vdev->reflck = vfio_fsl_mc_reflck_alloc();
++ } else {
++ struct device *mc_cont_dev = vdev->mc_dev->dev.parent;
++ struct vfio_device *device;
++ struct vfio_fsl_mc_device *cont_vdev;
++
++ device = vfio_device_get_from_dev(mc_cont_dev);
++ if (!device) {
++ ret = -ENODEV;
++ goto unlock;
++ }
++
++ cont_vdev = vfio_device_data(device);
++ if (!cont_vdev->reflck) {
++ vfio_device_put(device);
++ ret = -ENODEV;
++ goto unlock;
++ }
++ vfio_fsl_mc_reflck_get(cont_vdev->reflck);
++ vdev->reflck = cont_vdev->reflck;
++ vfio_device_put(device);
++ }
++
++unlock:
++ mutex_unlock(&reflck_lock);
++ return ret;
++}
+
+ static int vfio_fsl_mc_regions_init(struct vfio_fsl_mc_device *vdev)
+ {
+@@ -55,7 +124,7 @@ static int vfio_fsl_mc_open(void *device
+ if (!try_module_get(THIS_MODULE))
+ return -ENODEV;
+
+- mutex_lock(&vdev->driver_lock);
++ mutex_lock(&vdev->reflck->lock);
+ if (!vdev->refcnt) {
+ ret = vfio_fsl_mc_regions_init(vdev);
+ if (ret)
+@@ -63,11 +132,11 @@ static int vfio_fsl_mc_open(void *device
+ }
+ vdev->refcnt++;
+
+- mutex_unlock(&vdev->driver_lock);
++ mutex_unlock(&vdev->reflck->lock);
+ return 0;
+
+ err_reg_init:
+- mutex_unlock(&vdev->driver_lock);
++ mutex_unlock(&vdev->reflck->lock);
+ module_put(THIS_MODULE);
+ return ret;
+ }
+@@ -76,12 +145,12 @@ static void vfio_fsl_mc_release(void *de
+ {
+ struct vfio_fsl_mc_device *vdev = device_data;
+
+- mutex_lock(&vdev->driver_lock);
++ mutex_lock(&vdev->reflck->lock);
+
+ if (!(--vdev->refcnt))
+ vfio_fsl_mc_regions_cleanup(vdev);
+
+- mutex_unlock(&vdev->driver_lock);
++ mutex_unlock(&vdev->reflck->lock);
+
+ module_put(THIS_MODULE);
+ }
+@@ -180,7 +249,6 @@ static int vfio_fsl_mc_mmap_mmio(struct
+ return -EINVAL;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+-
+ vma->vm_pgoff = (region.addr >> PAGE_SHIFT) + pgoff;
+
+ return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+@@ -335,12 +403,18 @@ static int vfio_fsl_mc_probe(struct fsl_
+ return ret;
+ }
+
++ ret = vfio_fsl_mc_reflck_attach(vdev);
++ if (ret) {
++ vfio_iommu_group_put(group, dev);
++ return ret;
++ }
++
+ ret = vfio_fsl_mc_init_device(vdev);
+ if (ret) {
++ vfio_fsl_mc_reflck_put(vdev->reflck);
+ vfio_iommu_group_put(group, dev);
+ return ret;
+ }
+- mutex_init(&vdev->driver_lock);
+
+ return ret;
+ }
+@@ -374,6 +448,8 @@ static int vfio_fsl_mc_remove(struct fsl
+ if (!vdev)
+ return -EINVAL;
+
++ vfio_fsl_mc_reflck_put(vdev->reflck);
++
+ if (is_fsl_mc_bus_dprc(mc_dev))
+ vfio_fsl_mc_cleanup_dprc(vdev->mc_dev);
+
+--- a/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h
++++ b/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h
+@@ -15,6 +15,11 @@
+ #define VFIO_FSL_MC_INDEX_TO_OFFSET(index) \
+ ((u64)(index) << VFIO_FSL_MC_OFFSET_SHIFT)
+
++struct vfio_fsl_mc_reflck {
++ struct kref kref;
++ struct mutex lock;
++};
++
+ struct vfio_fsl_mc_region {
+ u32 flags;
+ u32 type;
+@@ -27,7 +32,7 @@ struct vfio_fsl_mc_device {
+ int refcnt;
+ u32 num_regions;
+ struct vfio_fsl_mc_region *regions;
+- struct mutex driver_lock;
++ struct vfio_fsl_mc_reflck *reflck;
+ };
+
+ #endif /* VFIO_PCI_PRIVATE_H */