|
@@ -97,6 +97,7 @@ struct tce_container {
|
|
struct mutex lock;
|
|
struct mutex lock;
|
|
bool enabled;
|
|
bool enabled;
|
|
bool v2;
|
|
bool v2;
|
|
|
|
+ bool def_window_pending;
|
|
unsigned long locked_pages;
|
|
unsigned long locked_pages;
|
|
struct iommu_table *tables[IOMMU_TABLE_GROUP_MAX_TABLES];
|
|
struct iommu_table *tables[IOMMU_TABLE_GROUP_MAX_TABLES];
|
|
struct list_head group_list;
|
|
struct list_head group_list;
|
|
@@ -717,6 +718,9 @@ static long tce_iommu_create_default_window(struct tce_container *container)
|
|
struct tce_iommu_group *tcegrp;
|
|
struct tce_iommu_group *tcegrp;
|
|
struct iommu_table_group *table_group;
|
|
struct iommu_table_group *table_group;
|
|
|
|
|
|
|
|
+ if (!container->def_window_pending)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
if (!tce_groups_attached(container))
|
|
if (!tce_groups_attached(container))
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
|
|
|
@@ -730,6 +734,9 @@ static long tce_iommu_create_default_window(struct tce_container *container)
|
|
table_group->tce32_size, 1, &start_addr);
|
|
table_group->tce32_size, 1, &start_addr);
|
|
WARN_ON_ONCE(!ret && start_addr);
|
|
WARN_ON_ONCE(!ret && start_addr);
|
|
|
|
|
|
|
|
+ if (!ret)
|
|
|
|
+ container->def_window_pending = false;
|
|
|
|
+
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -823,6 +830,10 @@ static long tce_iommu_ioctl(void *iommu_data,
|
|
VFIO_DMA_MAP_FLAG_WRITE))
|
|
VFIO_DMA_MAP_FLAG_WRITE))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
+ ret = tce_iommu_create_default_window(container);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
num = tce_iommu_find_table(container, param.iova, &tbl);
|
|
num = tce_iommu_find_table(container, param.iova, &tbl);
|
|
if (num < 0)
|
|
if (num < 0)
|
|
return -ENXIO;
|
|
return -ENXIO;
|
|
@@ -886,6 +897,10 @@ static long tce_iommu_ioctl(void *iommu_data,
|
|
if (param.flags)
|
|
if (param.flags)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
+ ret = tce_iommu_create_default_window(container);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
num = tce_iommu_find_table(container, param.iova, &tbl);
|
|
num = tce_iommu_find_table(container, param.iova, &tbl);
|
|
if (num < 0)
|
|
if (num < 0)
|
|
return -ENXIO;
|
|
return -ENXIO;
|
|
@@ -1012,6 +1027,10 @@ static long tce_iommu_ioctl(void *iommu_data,
|
|
|
|
|
|
mutex_lock(&container->lock);
|
|
mutex_lock(&container->lock);
|
|
|
|
|
|
|
|
+ ret = tce_iommu_create_default_window(container);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
ret = tce_iommu_create_window(container, create.page_shift,
|
|
ret = tce_iommu_create_window(container, create.page_shift,
|
|
create.window_size, create.levels,
|
|
create.window_size, create.levels,
|
|
&create.start_addr);
|
|
&create.start_addr);
|
|
@@ -1044,6 +1063,11 @@ static long tce_iommu_ioctl(void *iommu_data,
|
|
if (remove.flags)
|
|
if (remove.flags)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
+ if (container->def_window_pending && !remove.start_addr) {
|
|
|
|
+ container->def_window_pending = false;
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
mutex_lock(&container->lock);
|
|
mutex_lock(&container->lock);
|
|
|
|
|
|
ret = tce_iommu_remove_window(container, remove.start_addr);
|
|
ret = tce_iommu_remove_window(container, remove.start_addr);
|
|
@@ -1141,7 +1165,6 @@ static int tce_iommu_attach_group(void *iommu_data,
|
|
struct tce_container *container = iommu_data;
|
|
struct tce_container *container = iommu_data;
|
|
struct iommu_table_group *table_group;
|
|
struct iommu_table_group *table_group;
|
|
struct tce_iommu_group *tcegrp = NULL;
|
|
struct tce_iommu_group *tcegrp = NULL;
|
|
- bool create_default_window = false;
|
|
|
|
|
|
|
|
mutex_lock(&container->lock);
|
|
mutex_lock(&container->lock);
|
|
|
|
|
|
@@ -1189,25 +1212,12 @@ static int tce_iommu_attach_group(void *iommu_data,
|
|
} else {
|
|
} else {
|
|
ret = tce_iommu_take_ownership_ddw(container, table_group);
|
|
ret = tce_iommu_take_ownership_ddw(container, table_group);
|
|
if (!tce_groups_attached(container) && !container->tables[0])
|
|
if (!tce_groups_attached(container) && !container->tables[0])
|
|
- create_default_window = true;
|
|
|
|
|
|
+ container->def_window_pending = true;
|
|
}
|
|
}
|
|
|
|
|
|
if (!ret) {
|
|
if (!ret) {
|
|
tcegrp->grp = iommu_group;
|
|
tcegrp->grp = iommu_group;
|
|
list_add(&tcegrp->next, &container->group_list);
|
|
list_add(&tcegrp->next, &container->group_list);
|
|
- /*
|
|
|
|
- * If it the first group attached, check if there is
|
|
|
|
- * a default DMA window and create one if none as
|
|
|
|
- * the userspace expects it to exist.
|
|
|
|
- */
|
|
|
|
- if (create_default_window) {
|
|
|
|
- ret = tce_iommu_create_default_window(container);
|
|
|
|
- if (ret) {
|
|
|
|
- list_del(&tcegrp->next);
|
|
|
|
- tce_iommu_release_ownership_ddw(container,
|
|
|
|
- table_group);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
|
|
|
|
unlock_exit:
|
|
unlock_exit:
|