summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Kardashevskiy <aik@ozlabs.ru>2017-03-17 00:48:29 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-03-22 12:43:38 +0100
commit53e18968a9c0753e542cc4f6b0cc2da5db64ffd9 (patch)
treeb0b2bcefa0a062bb4380fba162eb36876f0e331e
parent2e60baca235b05d4026207e31b6fc385c0c1c122 (diff)
vfio/spapr: Postpone default window creation
[ Upstream commit d9c728949ddc9de5734bf3b12ea906ca8a77f2a0 ] We are going to allow the userspace to configure container in one memory context and pass container fd to another so we are postponing memory allocations accounted against the locked memory limit. One of previous patches took care of it_userspace. At the moment we create the default DMA window when the first group is attached to a container; this is done for the userspace which is not DDW-aware but familiar with the SPAPR TCE IOMMU v2 in the part of memory pre-registration - such client expects the default DMA window to exist. This postpones the default DMA window allocation till one of the folliwing happens: 1. first map/unmap request arrives; 2. new window is requested; This adds noop for the case when the userspace requested removal of the default window which has not been created yet. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Acked-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Signed-off-by: Sasha Levin <alexander.levin@verizon.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/vfio/vfio_iommu_spapr_tce.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c
index e95c3ebcec59..c8823578a1b2 100644
--- a/drivers/vfio/vfio_iommu_spapr_tce.c
+++ b/drivers/vfio/vfio_iommu_spapr_tce.c
@@ -106,6 +106,7 @@ struct tce_container {
struct mutex lock;
bool enabled;
bool v2;
+ bool def_window_pending;
unsigned long locked_pages;
struct mm_struct *mm;
struct iommu_table *tables[IOMMU_TABLE_GROUP_MAX_TABLES];
@@ -791,6 +792,9 @@ static long tce_iommu_create_default_window(struct tce_container *container)
struct tce_iommu_group *tcegrp;
struct iommu_table_group *table_group;
+ if (!container->def_window_pending)
+ return 0;
+
if (!tce_groups_attached(container))
return -ENODEV;
@@ -804,6 +808,9 @@ static long tce_iommu_create_default_window(struct tce_container *container)
table_group->tce32_size, 1, &start_addr);
WARN_ON_ONCE(!ret && start_addr);
+ if (!ret)
+ container->def_window_pending = false;
+
return ret;
}
@@ -907,6 +914,10 @@ static long tce_iommu_ioctl(void *iommu_data,
VFIO_DMA_MAP_FLAG_WRITE))
return -EINVAL;
+ ret = tce_iommu_create_default_window(container);
+ if (ret)
+ return ret;
+
num = tce_iommu_find_table(container, param.iova, &tbl);
if (num < 0)
return -ENXIO;
@@ -970,6 +981,10 @@ static long tce_iommu_ioctl(void *iommu_data,
if (param.flags)
return -EINVAL;
+ ret = tce_iommu_create_default_window(container);
+ if (ret)
+ return ret;
+
num = tce_iommu_find_table(container, param.iova, &tbl);
if (num < 0)
return -ENXIO;
@@ -1107,6 +1122,10 @@ static long tce_iommu_ioctl(void *iommu_data,
mutex_lock(&container->lock);
+ ret = tce_iommu_create_default_window(container);
+ if (ret)
+ return ret;
+
ret = tce_iommu_create_window(container, create.page_shift,
create.window_size, create.levels,
&create.start_addr);
@@ -1143,6 +1162,11 @@ static long tce_iommu_ioctl(void *iommu_data,
if (remove.flags)
return -EINVAL;
+ if (container->def_window_pending && !remove.start_addr) {
+ container->def_window_pending = false;
+ return 0;
+ }
+
mutex_lock(&container->lock);
ret = tce_iommu_remove_window(container, remove.start_addr);
@@ -1240,7 +1264,6 @@ static int tce_iommu_attach_group(void *iommu_data,
struct tce_container *container = iommu_data;
struct iommu_table_group *table_group;
struct tce_iommu_group *tcegrp = NULL;
- bool create_default_window = false;
mutex_lock(&container->lock);
@@ -1288,25 +1311,12 @@ static int tce_iommu_attach_group(void *iommu_data,
} else {
ret = tce_iommu_take_ownership_ddw(container, table_group);
if (!tce_groups_attached(container) && !container->tables[0])
- create_default_window = true;
+ container->def_window_pending = true;
}
if (!ret) {
tcegrp->grp = iommu_group;
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: