powerpc/iommu: Add "borrowing" iommu_table_group_ops
[linux-2.6-microblaze.git] / drivers / vfio / vfio_iommu_spapr_tce.c
index 60a50ce..c3f8ae1 100644 (file)
@@ -1189,52 +1189,6 @@ static long tce_iommu_ioctl(void *iommu_data,
 
 static void tce_iommu_release_ownership(struct tce_container *container,
                struct iommu_table_group *table_group)
-{
-       int i;
-
-       for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) {
-               struct iommu_table *tbl = container->tables[i];
-
-               if (!tbl)
-                       continue;
-
-               tce_iommu_clear(container, tbl, tbl->it_offset, tbl->it_size);
-               if (tbl->it_map)
-                       iommu_release_ownership(tbl);
-
-               container->tables[i] = NULL;
-       }
-}
-
-static int tce_iommu_take_ownership(struct tce_container *container,
-               struct iommu_table_group *table_group)
-{
-       int i, j, rc = 0;
-
-       for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) {
-               struct iommu_table *tbl = table_group->tables[i];
-
-               if (!tbl || !tbl->it_map)
-                       continue;
-
-               rc = iommu_take_ownership(tbl);
-               if (rc) {
-                       for (j = 0; j < i; ++j)
-                               iommu_release_ownership(
-                                               table_group->tables[j]);
-
-                       return rc;
-               }
-       }
-
-       for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i)
-               container->tables[i] = table_group->tables[i];
-
-       return 0;
-}
-
-static void tce_iommu_release_ownership_ddw(struct tce_container *container,
-               struct iommu_table_group *table_group)
 {
        long i;
 
@@ -1250,18 +1204,14 @@ static void tce_iommu_release_ownership_ddw(struct tce_container *container,
        table_group->ops->release_ownership(table_group);
 }
 
-static long tce_iommu_take_ownership_ddw(struct tce_container *container,
+static long tce_iommu_take_ownership(struct tce_container *container,
                struct iommu_table_group *table_group)
 {
        long i, ret = 0;
 
-       if (!table_group->ops->create_table || !table_group->ops->set_window ||
-                       !table_group->ops->release_ownership) {
-               WARN_ON_ONCE(1);
-               return -EFAULT;
-       }
-
-       table_group->ops->take_ownership(table_group);
+       ret = table_group->ops->take_ownership(table_group);
+       if (ret)
+               return ret;
 
        /* Set all windows to the new group */
        for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) {
@@ -1307,9 +1257,14 @@ static int tce_iommu_attach_group(void *iommu_data,
                goto unlock_exit;
        }
 
-       if (tce_groups_attached(container) && (!table_group->ops ||
-                       !table_group->ops->take_ownership ||
-                       !table_group->ops->release_ownership)) {
+       /* v2 requires full support of dynamic DMA windows */
+       if (container->v2 && table_group->max_dynamic_windows_supported == 0) {
+               ret = -EINVAL;
+               goto unlock_exit;
+       }
+
+       /* v1 reuses TCE tables and does not share them among PEs */
+       if (!container->v2 && tce_groups_attached(container)) {
                ret = -EBUSY;
                goto unlock_exit;
        }
@@ -1344,29 +1299,15 @@ static int tce_iommu_attach_group(void *iommu_data,
                goto unlock_exit;
        }
 
-       if (!table_group->ops || !table_group->ops->take_ownership ||
-                       !table_group->ops->release_ownership) {
-               if (container->v2) {
-                       ret = -EPERM;
-                       goto free_exit;
-               }
-               ret = tce_iommu_take_ownership(container, table_group);
-       } else {
-               if (!container->v2) {
-                       ret = -EPERM;
-                       goto free_exit;
-               }
-               ret = tce_iommu_take_ownership_ddw(container, table_group);
-               if (!tce_groups_attached(container) && !container->tables[0])
-                       container->def_window_pending = true;
-       }
+       ret = tce_iommu_take_ownership(container, table_group);
+       if (!tce_groups_attached(container) && !container->tables[0])
+               container->def_window_pending = true;
 
        if (!ret) {
                tcegrp->grp = iommu_group;
                list_add(&tcegrp->next, &container->group_list);
        }
 
-free_exit:
        if (ret && tcegrp)
                kfree(tcegrp);
 
@@ -1405,10 +1346,7 @@ static void tce_iommu_detach_group(void *iommu_data,
        table_group = iommu_group_get_iommudata(iommu_group);
        BUG_ON(!table_group);
 
-       if (!table_group->ops || !table_group->ops->release_ownership)
-               tce_iommu_release_ownership(container, table_group);
-       else
-               tce_iommu_release_ownership_ddw(container, table_group);
+       tce_iommu_release_ownership(container, table_group);
 
 unlock_exit:
        mutex_unlock(&container->lock);