]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/vfio/vfio_iommu_spapr_tce.c
Merge tag 'hyperv-next-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/hyper...
[linux.git] / drivers / vfio / vfio_iommu_spapr_tce.c
index 8ce9ad21129f08d2e49820d76627684bd54e743e..3b18fa4d090a301e051f6057a31794a621f01585 100644 (file)
@@ -435,7 +435,7 @@ static int tce_iommu_clear(struct tce_container *container,
        unsigned long oldhpa;
        long ret;
        enum dma_data_direction direction;
-       unsigned long lastentry = entry + pages;
+       unsigned long lastentry = entry + pages, firstentry = entry;
 
        for ( ; entry < lastentry; ++entry) {
                if (tbl->it_indirect_levels && tbl->it_userspace) {
@@ -460,7 +460,7 @@ static int tce_iommu_clear(struct tce_container *container,
 
                direction = DMA_NONE;
                oldhpa = 0;
-               ret = iommu_tce_xchg(container->mm, tbl, entry, &oldhpa,
+               ret = iommu_tce_xchg_no_kill(container->mm, tbl, entry, &oldhpa,
                                &direction);
                if (ret)
                        continue;
@@ -476,6 +476,8 @@ static int tce_iommu_clear(struct tce_container *container,
                tce_iommu_unuse_page(container, oldhpa);
        }
 
+       iommu_tce_kill(tbl, firstentry, pages);
+
        return 0;
 }
 
@@ -518,8 +520,8 @@ static long tce_iommu_build(struct tce_container *container,
 
                hpa |= offset;
                dirtmp = direction;
-               ret = iommu_tce_xchg(container->mm, tbl, entry + i, &hpa,
-                               &dirtmp);
+               ret = iommu_tce_xchg_no_kill(container->mm, tbl, entry + i,
+                               &hpa, &dirtmp);
                if (ret) {
                        tce_iommu_unuse_page(container, hpa);
                        pr_err("iommu_tce: %s failed ioba=%lx, tce=%lx, ret=%ld\n",
@@ -536,6 +538,8 @@ static long tce_iommu_build(struct tce_container *container,
 
        if (ret)
                tce_iommu_clear(container, tbl, entry, i);
+       else
+               iommu_tce_kill(tbl, entry, pages);
 
        return ret;
 }
@@ -572,8 +576,8 @@ static long tce_iommu_build_v2(struct tce_container *container,
                if (mm_iommu_mapped_inc(mem))
                        break;
 
-               ret = iommu_tce_xchg(container->mm, tbl, entry + i, &hpa,
-                               &dirtmp);
+               ret = iommu_tce_xchg_no_kill(container->mm, tbl, entry + i,
+                               &hpa, &dirtmp);
                if (ret) {
                        /* dirtmp cannot be DMA_NONE here */
                        tce_iommu_unuse_page_v2(container, tbl, entry + i);
@@ -593,6 +597,8 @@ static long tce_iommu_build_v2(struct tce_container *container,
 
        if (ret)
                tce_iommu_clear(container, tbl, entry, i);
+       else
+               iommu_tce_kill(tbl, entry, pages);
 
        return ret;
 }
@@ -1234,7 +1240,7 @@ static long tce_iommu_take_ownership_ddw(struct tce_container *container,
 static int tce_iommu_attach_group(void *iommu_data,
                struct iommu_group *iommu_group)
 {
-       int ret;
+       int ret = 0;
        struct tce_container *container = iommu_data;
        struct iommu_table_group *table_group;
        struct tce_iommu_group *tcegrp = NULL;
@@ -1287,13 +1293,13 @@ static int tce_iommu_attach_group(void *iommu_data,
                        !table_group->ops->release_ownership) {
                if (container->v2) {
                        ret = -EPERM;
-                       goto unlock_exit;
+                       goto free_exit;
                }
                ret = tce_iommu_take_ownership(container, table_group);
        } else {
                if (!container->v2) {
                        ret = -EPERM;
-                       goto unlock_exit;
+                       goto free_exit;
                }
                ret = tce_iommu_take_ownership_ddw(container, table_group);
                if (!tce_groups_attached(container) && !container->tables[0])
@@ -1305,10 +1311,11 @@ static int tce_iommu_attach_group(void *iommu_data,
                list_add(&tcegrp->next, &container->group_list);
        }
 
-unlock_exit:
+free_exit:
        if (ret && tcegrp)
                kfree(tcegrp);
 
+unlock_exit:
        mutex_unlock(&container->lock);
 
        return ret;