diff options
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.patch | 193 |
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 */ |