Message ID | 20181113082823.2440-3-aik@ozlabs.ru |
---|---|
State | Superseded |
Headers | show |
Series | powerpc/powernv/npu, vfio: NVIDIA V100 + P9 passthrough | expand |
On Tue, Nov 13, 2018 at 07:28:03PM +1100, Alexey Kardashevskiy wrote: > Normally mm_iommu_get() is supposed to add a reference and > mm_iommu_put() to remove it. However historically mm_iommu_find() does > the referencing and mm_iommu_get() is doing allocation and referencing. > > We are going to add another helper to preregister device memory so > instead of having mm_iommu_new() which pre-registers the normal memory > and references the region, we need separate helpers for pre-registering > and referencing. > > This renames: > - mm_iommu_get to mm_iommu_new; > - mm_iommu_find to mm_iommu_get. > > To make the mm_iommu_get name reflect what it is supposed to do, this > changes mm_iommu_get() to reference the region so from now on for every > mm_iommu_get() we need a matching mm_iommu_put(). > > Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> > --- > Changes: > v2: > * merged 2 patches into one > --- > arch/powerpc/include/asm/mmu_context.h | 4 +-- > arch/powerpc/mm/mmu_context_iommu.c | 13 ++++++--- > drivers/vfio/vfio_iommu_spapr_tce.c | 37 +++++++++++++++++--------- > 3 files changed, 35 insertions(+), 19 deletions(-) > > diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h > index 0381394..2d6b00d 100644 > --- a/arch/powerpc/include/asm/mmu_context.h > +++ b/arch/powerpc/include/asm/mmu_context.h > @@ -21,7 +21,7 @@ struct mm_iommu_table_group_mem_t; > > extern int isolate_lru_page(struct page *page); /* from internal.h */ > extern bool mm_iommu_preregistered(struct mm_struct *mm); > -extern long mm_iommu_get(struct mm_struct *mm, > +extern long mm_iommu_new(struct mm_struct *mm, > unsigned long ua, unsigned long entries, > struct mm_iommu_table_group_mem_t **pmem); > extern long mm_iommu_put(struct mm_struct *mm, > @@ -32,7 +32,7 @@ extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup(struct mm_struct *mm, > unsigned long ua, unsigned long size); > extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup_rm( > struct mm_struct *mm, unsigned long ua, unsigned long size); > -extern struct mm_iommu_table_group_mem_t *mm_iommu_find(struct mm_struct *mm, > +extern struct mm_iommu_table_group_mem_t *mm_iommu_get(struct mm_struct *mm, > unsigned long ua, unsigned long entries); > extern long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem, > unsigned long ua, unsigned int pageshift, unsigned long *hpa); > diff --git a/arch/powerpc/mm/mmu_context_iommu.c b/arch/powerpc/mm/mmu_context_iommu.c > index 1d5161f..babc6ad 100644 > --- a/arch/powerpc/mm/mmu_context_iommu.c > +++ b/arch/powerpc/mm/mmu_context_iommu.c > @@ -89,7 +89,7 @@ bool mm_iommu_preregistered(struct mm_struct *mm) > } > EXPORT_SYMBOL_GPL(mm_iommu_preregistered); > > -long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries, > +long mm_iommu_new(struct mm_struct *mm, unsigned long ua, unsigned long entries, > struct mm_iommu_table_group_mem_t **pmem) > { > struct mm_iommu_table_group_mem_t *mem; > @@ -202,7 +202,7 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries, > > return ret; > } > -EXPORT_SYMBOL_GPL(mm_iommu_get); > +EXPORT_SYMBOL_GPL(mm_iommu_new); > > static void mm_iommu_unpin(struct mm_iommu_table_group_mem_t *mem) > { > @@ -318,21 +318,26 @@ struct mm_iommu_table_group_mem_t *mm_iommu_lookup_rm(struct mm_struct *mm, > return ret; > } > > -struct mm_iommu_table_group_mem_t *mm_iommu_find(struct mm_struct *mm, > +struct mm_iommu_table_group_mem_t *mm_iommu_get(struct mm_struct *mm, > unsigned long ua, unsigned long entries) > { > struct mm_iommu_table_group_mem_t *mem, *ret = NULL; > > + mutex_lock(&mem_list_mutex); > + > list_for_each_entry_rcu(mem, &mm->context.iommu_group_mem_list, next) { > if ((mem->ua == ua) && (mem->entries == entries)) { > ret = mem; > + ++mem->used; > break; > } > } > > + mutex_unlock(&mem_list_mutex); > + > return ret; > } > -EXPORT_SYMBOL_GPL(mm_iommu_find); > +EXPORT_SYMBOL_GPL(mm_iommu_get); > > long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem, > unsigned long ua, unsigned int pageshift, unsigned long *hpa) > diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c > index ad63725..56db071 100644 > --- a/drivers/vfio/vfio_iommu_spapr_tce.c > +++ b/drivers/vfio/vfio_iommu_spapr_tce.c > @@ -151,12 +151,13 @@ static long tce_iommu_unregister_pages(struct tce_container *container, > { > struct mm_iommu_table_group_mem_t *mem; > struct tce_iommu_prereg *tcemem; > - bool found = false; > + bool found; > + long ret; > > if ((vaddr & ~PAGE_MASK) || (size & ~PAGE_MASK)) > return -EINVAL; > > - mem = mm_iommu_find(container->mm, vaddr, size >> PAGE_SHIFT); > + mem = mm_iommu_get(container->mm, vaddr, size >> PAGE_SHIFT); > if (!mem) > return -ENOENT; > > @@ -168,9 +169,13 @@ static long tce_iommu_unregister_pages(struct tce_container *container, > } > > if (!found) > - return -ENOENT; > + ret = -ENOENT; > + else > + ret = tce_iommu_prereg_free(container, tcemem); > > - return tce_iommu_prereg_free(container, tcemem); > + mm_iommu_put(container->mm, mem); > + > + return ret; > } > > static long tce_iommu_register_pages(struct tce_container *container, > @@ -185,22 +190,24 @@ static long tce_iommu_register_pages(struct tce_container *container, > ((vaddr + size) < vaddr)) > return -EINVAL; > > - mem = mm_iommu_find(container->mm, vaddr, entries); > + mem = mm_iommu_get(container->mm, vaddr, entries); > if (mem) { > list_for_each_entry(tcemem, &container->prereg_list, next) { > - if (tcemem->mem == mem) > - return -EBUSY; > + if (tcemem->mem == mem) { > + ret = -EBUSY; > + goto put_exit; > + } > } > + } else { > + ret = mm_iommu_new(container->mm, vaddr, entries, &mem); > + if (ret) > + return ret; > } > > - ret = mm_iommu_get(container->mm, vaddr, entries, &mem); > - if (ret) > - return ret; > - > tcemem = kzalloc(sizeof(*tcemem), GFP_KERNEL); > if (!tcemem) { > - mm_iommu_put(container->mm, mem); > - return -ENOMEM; > + ret = -ENOMEM; > + goto put_exit; > } > > tcemem->mem = mem; > @@ -209,6 +216,10 @@ static long tce_iommu_register_pages(struct tce_container *container, > container->enabled = true; > > return 0; > + > +put_exit: > + mm_iommu_put(container->mm, mem); > + return ret; > } > > static bool tce_page_is_contained(struct page *page, unsigned page_shift)
diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index 0381394..2d6b00d 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h @@ -21,7 +21,7 @@ struct mm_iommu_table_group_mem_t; extern int isolate_lru_page(struct page *page); /* from internal.h */ extern bool mm_iommu_preregistered(struct mm_struct *mm); -extern long mm_iommu_get(struct mm_struct *mm, +extern long mm_iommu_new(struct mm_struct *mm, unsigned long ua, unsigned long entries, struct mm_iommu_table_group_mem_t **pmem); extern long mm_iommu_put(struct mm_struct *mm, @@ -32,7 +32,7 @@ extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup(struct mm_struct *mm, unsigned long ua, unsigned long size); extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup_rm( struct mm_struct *mm, unsigned long ua, unsigned long size); -extern struct mm_iommu_table_group_mem_t *mm_iommu_find(struct mm_struct *mm, +extern struct mm_iommu_table_group_mem_t *mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries); extern long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem, unsigned long ua, unsigned int pageshift, unsigned long *hpa); diff --git a/arch/powerpc/mm/mmu_context_iommu.c b/arch/powerpc/mm/mmu_context_iommu.c index 1d5161f..babc6ad 100644 --- a/arch/powerpc/mm/mmu_context_iommu.c +++ b/arch/powerpc/mm/mmu_context_iommu.c @@ -89,7 +89,7 @@ bool mm_iommu_preregistered(struct mm_struct *mm) } EXPORT_SYMBOL_GPL(mm_iommu_preregistered); -long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries, +long mm_iommu_new(struct mm_struct *mm, unsigned long ua, unsigned long entries, struct mm_iommu_table_group_mem_t **pmem) { struct mm_iommu_table_group_mem_t *mem; @@ -202,7 +202,7 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries, return ret; } -EXPORT_SYMBOL_GPL(mm_iommu_get); +EXPORT_SYMBOL_GPL(mm_iommu_new); static void mm_iommu_unpin(struct mm_iommu_table_group_mem_t *mem) { @@ -318,21 +318,26 @@ struct mm_iommu_table_group_mem_t *mm_iommu_lookup_rm(struct mm_struct *mm, return ret; } -struct mm_iommu_table_group_mem_t *mm_iommu_find(struct mm_struct *mm, +struct mm_iommu_table_group_mem_t *mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries) { struct mm_iommu_table_group_mem_t *mem, *ret = NULL; + mutex_lock(&mem_list_mutex); + list_for_each_entry_rcu(mem, &mm->context.iommu_group_mem_list, next) { if ((mem->ua == ua) && (mem->entries == entries)) { ret = mem; + ++mem->used; break; } } + mutex_unlock(&mem_list_mutex); + return ret; } -EXPORT_SYMBOL_GPL(mm_iommu_find); +EXPORT_SYMBOL_GPL(mm_iommu_get); long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem, unsigned long ua, unsigned int pageshift, unsigned long *hpa) diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c index ad63725..56db071 100644 --- a/drivers/vfio/vfio_iommu_spapr_tce.c +++ b/drivers/vfio/vfio_iommu_spapr_tce.c @@ -151,12 +151,13 @@ static long tce_iommu_unregister_pages(struct tce_container *container, { struct mm_iommu_table_group_mem_t *mem; struct tce_iommu_prereg *tcemem; - bool found = false; + bool found; + long ret; if ((vaddr & ~PAGE_MASK) || (size & ~PAGE_MASK)) return -EINVAL; - mem = mm_iommu_find(container->mm, vaddr, size >> PAGE_SHIFT); + mem = mm_iommu_get(container->mm, vaddr, size >> PAGE_SHIFT); if (!mem) return -ENOENT; @@ -168,9 +169,13 @@ static long tce_iommu_unregister_pages(struct tce_container *container, } if (!found) - return -ENOENT; + ret = -ENOENT; + else + ret = tce_iommu_prereg_free(container, tcemem); - return tce_iommu_prereg_free(container, tcemem); + mm_iommu_put(container->mm, mem); + + return ret; } static long tce_iommu_register_pages(struct tce_container *container, @@ -185,22 +190,24 @@ static long tce_iommu_register_pages(struct tce_container *container, ((vaddr + size) < vaddr)) return -EINVAL; - mem = mm_iommu_find(container->mm, vaddr, entries); + mem = mm_iommu_get(container->mm, vaddr, entries); if (mem) { list_for_each_entry(tcemem, &container->prereg_list, next) { - if (tcemem->mem == mem) - return -EBUSY; + if (tcemem->mem == mem) { + ret = -EBUSY; + goto put_exit; + } } + } else { + ret = mm_iommu_new(container->mm, vaddr, entries, &mem); + if (ret) + return ret; } - ret = mm_iommu_get(container->mm, vaddr, entries, &mem); - if (ret) - return ret; - tcemem = kzalloc(sizeof(*tcemem), GFP_KERNEL); if (!tcemem) { - mm_iommu_put(container->mm, mem); - return -ENOMEM; + ret = -ENOMEM; + goto put_exit; } tcemem->mem = mem; @@ -209,6 +216,10 @@ static long tce_iommu_register_pages(struct tce_container *container, container->enabled = true; return 0; + +put_exit: + mm_iommu_put(container->mm, mem); + return ret; } static bool tce_page_is_contained(struct page *page, unsigned page_shift)
Normally mm_iommu_get() is supposed to add a reference and mm_iommu_put() to remove it. However historically mm_iommu_find() does the referencing and mm_iommu_get() is doing allocation and referencing. We are going to add another helper to preregister device memory so instead of having mm_iommu_new() which pre-registers the normal memory and references the region, we need separate helpers for pre-registering and referencing. This renames: - mm_iommu_get to mm_iommu_new; - mm_iommu_find to mm_iommu_get. To make the mm_iommu_get name reflect what it is supposed to do, this changes mm_iommu_get() to reference the region so from now on for every mm_iommu_get() we need a matching mm_iommu_put(). Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> --- Changes: v2: * merged 2 patches into one --- arch/powerpc/include/asm/mmu_context.h | 4 +-- arch/powerpc/mm/mmu_context_iommu.c | 13 ++++++--- drivers/vfio/vfio_iommu_spapr_tce.c | 37 +++++++++++++++++--------- 3 files changed, 35 insertions(+), 19 deletions(-)