diff options
Diffstat (limited to 'drivers/vfio')
-rw-r--r-- | drivers/vfio/vfio_iommu_spapr_tce.c | 94 |
1 files changed, 16 insertions, 78 deletions
diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c index 60a50ce8701e..c3f8ae102ece 100644 --- a/drivers/vfio/vfio_iommu_spapr_tce.c +++ b/drivers/vfio/vfio_iommu_spapr_tce.c @@ -1190,52 +1190,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; if (!table_group->ops->unset_window) { @@ -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); |