drm/i915/gvt: Fix inconsistent locks holding sequence
authorChuanxiao Dong <chuanxiao.dong@intel.com>
Mon, 26 Jun 2017 07:20:50 +0000 (15:20 +0800)
committerZhenyu Wang <zhenyuw@linux.intel.com>
Mon, 26 Jun 2017 08:32:20 +0000 (16:32 +0800)
There are two kinds of locking sequence.

One is in the thread which is started by vfio ioctl to do
the iommu unmapping. The locking sequence is:
down_read(&group_lock) ----> mutex_lock(&cached_lock)

The other is in the vfio release thread which will unpin all
the cached pages. The lock sequence is:
mutex_lock(&cached_lock) ---> down_read(&group_lock)

And, the cache_lock is used to protect the rb tree of the cache
node and doing vfio unpin doesn't require this lock. Move the
vfio unpin out of the cache_lock protected region.

v2:
- use for style instead of do{}while(1). (Zhenyu)

Fixes: f30437c5e7bf ("drm/i915/gvt: add KVMGT support")
Signed-off-by: Chuanxiao Dong <chuanxiao.dong@intel.com>
Cc: Zhenyu Wang <zhenyuw@linux.intel.com>
Cc: stable@vger.kernel.org # v4.10+
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
drivers/gpu/drm/i915/gvt/kvmgt.c

index 56a8d6a7d9c67c3335191138034ab375e2bd03b6..75a6e1d8af0d3ce785258cea4393a81d8b0166ef 100644 (file)
@@ -260,16 +260,20 @@ static void gvt_cache_destroy(struct intel_vgpu *vgpu)
        struct device *dev = mdev_dev(vgpu->vdev.mdev);
        unsigned long gfn;
 
-       mutex_lock(&vgpu->vdev.cache_lock);
-       while ((node = rb_first(&vgpu->vdev.cache))) {
+       for (;;) {
+               mutex_lock(&vgpu->vdev.cache_lock);
+               node = rb_first(&vgpu->vdev.cache);
+               if (!node) {
+                       mutex_unlock(&vgpu->vdev.cache_lock);
+                       break;
+               }
                dma = rb_entry(node, struct gvt_dma, node);
                gvt_dma_unmap_iova(vgpu, dma->iova);
                gfn = dma->gfn;
-
-               vfio_unpin_pages(dev, &gfn, 1);
                __gvt_cache_remove_entry(vgpu, dma);
+               mutex_unlock(&vgpu->vdev.cache_lock);
+               vfio_unpin_pages(dev, &gfn, 1);
        }
-       mutex_unlock(&vgpu->vdev.cache_lock);
 }
 
 static struct intel_vgpu_type *intel_gvt_find_vgpu_type(struct intel_gvt *gvt,