Re: [PATCH 4/5] iommu: Separate IOVA rcache memories from iova_domain structure

2021-12-22 Thread John Garry via iommu

On 20/12/2021 13:57, Robin Murphy wrote:
Do you have any thoughts on this patch? The decision is whether we 
stick with a single iova domain structure or support this super 
structure for iova domains which support the rcache. I did not try the 
former - it would be do-able but I am not sure on how it would look.


TBH I feel inclined to take the simpler approach of just splitting the 
rcache array to a separate allocation, making init_iova_rcaches() public 
(with a proper return value), and tweaking put_iova_domain() to make 
rcache cleanup conditional. A residual overhead of 3 extra pointers in 
iova_domain doesn't seem like *too* much for non-DMA-API users to bear. 


OK, fine. So I tried as you suggested and it looks ok to me.

I'll send something out at rc1.

Unless you want to try generalising the rcache mechanism completely away 
from IOVA API specifics, it doesn't seem like there's really enough to 
justify the bother of having its own distinct abstraction layer.


Yeah, I don't see that as necessary.

However something which could be useful is to separate the magazine code 
out for other possible users.


Thanks!
John
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 4/5] iommu: Separate IOVA rcache memories from iova_domain structure

2021-12-20 Thread Robin Murphy

Hi John,

On 2021-12-20 08:49, John Garry wrote:

On 24/09/2021 11:01, John Garry wrote:

Only dma-iommu.c and vdpa actually use the "fast" mode of IOVA alloc and
free. As such, it's wasteful that all other IOVA domains hold the rcache
memories.

In addition, the current IOVA domain init implementation is poor
(init_iova_domain()), in that errors are ignored and not passed to the
caller. The only errors can come from the IOVA rcache init, and fixing up
all the IOVA domain init callsites to handle the errors would take some
work.

Separate the IOVA rache out of the IOVA domain, and create a new IOVA
domain structure, iova_caching_domain.

Signed-off-by: John Garry 


Hi Robin,

Do you have any thoughts on this patch? The decision is whether we stick 
with a single iova domain structure or support this super structure for 
iova domains which support the rcache. I did not try the former - it 
would be do-able but I am not sure on how it would look.


TBH I feel inclined to take the simpler approach of just splitting the 
rcache array to a separate allocation, making init_iova_rcaches() public 
(with a proper return value), and tweaking put_iova_domain() to make 
rcache cleanup conditional. A residual overhead of 3 extra pointers in 
iova_domain doesn't seem like *too* much for non-DMA-API users to bear. 
Unless you want to try generalising the rcache mechanism completely away 
from IOVA API specifics, it doesn't seem like there's really enough to 
justify the bother of having its own distinct abstraction layer.


Cheers,
Robin.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 4/5] iommu: Separate IOVA rcache memories from iova_domain structure

2021-12-20 Thread John Garry via iommu

On 24/09/2021 11:01, John Garry wrote:

Only dma-iommu.c and vdpa actually use the "fast" mode of IOVA alloc and
free. As such, it's wasteful that all other IOVA domains hold the rcache
memories.

In addition, the current IOVA domain init implementation is poor
(init_iova_domain()), in that errors are ignored and not passed to the
caller. The only errors can come from the IOVA rcache init, and fixing up
all the IOVA domain init callsites to handle the errors would take some
work.

Separate the IOVA rache out of the IOVA domain, and create a new IOVA
domain structure, iova_caching_domain.

Signed-off-by: John Garry 


Hi Robin,

Do you have any thoughts on this patch? The decision is whether we stick 
with a single iova domain structure or support this super structure for 
iova domains which support the rcache. I did not try the former - it 
would be do-able but I am not sure on how it would look.


Thanks,
John

EOM


---
  drivers/iommu/dma-iommu.c|  56 +++-
  drivers/iommu/iova.c | 125 ++-
  drivers/vdpa/vdpa_user/iova_domain.c |  53 +++-
  drivers/vdpa/vdpa_user/iova_domain.h |   4 +-
  include/linux/iova.h |  18 ++--
  5 files changed, 166 insertions(+), 90 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index fd669bad96e1..70651f1a688d 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -92,8 +92,8 @@ struct iommu_dma_cookie {
union {
/* Full allocator for IOMMU_DMA_IOVA_COOKIE */
struct {
-   struct iova_domain  iovad;
-   struct fq_domainfq;
+   struct iova_caching_domain  rcached;
+   struct fq_domainfq;
};
/* Trivial linear page allocator for IOMMU_DMA_MSI_COOKIE */
dma_addr_t  msi_iova;
@@ -197,7 +197,6 @@ static void fq_ring_free(struct fq_domain *fq_domain, 
struct fq *fq)
struct iommu_dma_cookie *cookie = container_of(fq_domain,
   struct iommu_dma_cookie,
   fq);
-   struct iova_domain *iovad = &cookie->iovad;
u64 counter = atomic64_read(&fq_domain->fq_flush_finish_cnt);
unsigned idx;
  
@@ -211,7 +210,7 @@ static void fq_ring_free(struct fq_domain *fq_domain, struct fq *fq)

if (fq_domain->entry_dtor)
fq_domain->entry_dtor(fq->entries[idx].data);
  
-		free_iova_fast(iovad,

+   free_iova_fast(&cookie->rcached,
   fq->entries[idx].iova_pfn,
   fq->entries[idx].pages);
  
@@ -330,7 +329,7 @@ static int init_flush_queue(struct fq_domain *fq_domain,

  static inline size_t cookie_msi_granule(struct iommu_dma_cookie *cookie)
  {
if (cookie->type == IOMMU_DMA_IOVA_COOKIE)
-   return cookie->iovad.granule;
+   return cookie->rcached.iovad.granule;
return PAGE_SIZE;
  }
  
@@ -413,9 +412,10 @@ void iommu_put_dma_cookie(struct iommu_domain *domain)

if (!cookie)
return;
  
-	if (cookie->type == IOMMU_DMA_IOVA_COOKIE && cookie->iovad.granule) {

+   if (cookie->type == IOMMU_DMA_IOVA_COOKIE &&
+   cookie->rcached.iovad.granule) {
free_flush_queue(&cookie->fq);
-   put_iova_domain(&cookie->iovad);
+   put_iova_caching_domain(&cookie->rcached);
}
  
  	list_for_each_entry_safe(msi, tmp, &cookie->msi_page_list, list) {

@@ -449,7 +449,7 @@ EXPORT_SYMBOL(iommu_dma_get_resv_regions);
  static int cookie_init_hw_msi_region(struct iommu_dma_cookie *cookie,
phys_addr_t start, phys_addr_t end)
  {
-   struct iova_domain *iovad = &cookie->iovad;
+   struct iova_domain *iovad = &cookie->rcached.iovad;
struct iommu_dma_msi_page *msi_page;
int i, num_pages;
  
@@ -520,7 +520,8 @@ static int iova_reserve_iommu_regions(struct device *dev,

struct iommu_domain *domain)
  {
struct iommu_dma_cookie *cookie = domain->iova_cookie;
-   struct iova_domain *iovad = &cookie->iovad;
+   struct iova_caching_domain *rcached = &cookie->rcached;
+   struct iova_domain *iovad = &rcached->iovad;
struct iommu_resv_region *region;
LIST_HEAD(resv_regions);
int ret = 0;
@@ -612,14 +613,17 @@ static int iommu_dma_init_domain(struct iommu_domain 
*domain, dma_addr_t base,
 dma_addr_t limit, struct device *dev)
  {
struct iommu_dma_cookie *cookie = domain->iova_cookie;
+   struct iova_caching_domain *rcached;
unsigned long order, base_pfn;
struct iova_domain *iovad;
struct fq_domain *fq;
+   int ret;
  
  	if (!cookie || cookie->type != IOMMU_DMA_IOVA_COOKIE)

  

[PATCH 4/5] iommu: Separate IOVA rcache memories from iova_domain structure

2021-09-24 Thread John Garry
Only dma-iommu.c and vdpa actually use the "fast" mode of IOVA alloc and
free. As such, it's wasteful that all other IOVA domains hold the rcache
memories.

In addition, the current IOVA domain init implementation is poor
(init_iova_domain()), in that errors are ignored and not passed to the
caller. The only errors can come from the IOVA rcache init, and fixing up
all the IOVA domain init callsites to handle the errors would take some
work.

Separate the IOVA rache out of the IOVA domain, and create a new IOVA
domain structure, iova_caching_domain.

Signed-off-by: John Garry 
---
 drivers/iommu/dma-iommu.c|  56 +++-
 drivers/iommu/iova.c | 125 ++-
 drivers/vdpa/vdpa_user/iova_domain.c |  53 +++-
 drivers/vdpa/vdpa_user/iova_domain.h |   4 +-
 include/linux/iova.h |  18 ++--
 5 files changed, 166 insertions(+), 90 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index fd669bad96e1..70651f1a688d 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -92,8 +92,8 @@ struct iommu_dma_cookie {
union {
/* Full allocator for IOMMU_DMA_IOVA_COOKIE */
struct {
-   struct iova_domain  iovad;
-   struct fq_domainfq;
+   struct iova_caching_domain  rcached;
+   struct fq_domainfq;
};
/* Trivial linear page allocator for IOMMU_DMA_MSI_COOKIE */
dma_addr_t  msi_iova;
@@ -197,7 +197,6 @@ static void fq_ring_free(struct fq_domain *fq_domain, 
struct fq *fq)
struct iommu_dma_cookie *cookie = container_of(fq_domain,
   struct iommu_dma_cookie,
   fq);
-   struct iova_domain *iovad = &cookie->iovad;
u64 counter = atomic64_read(&fq_domain->fq_flush_finish_cnt);
unsigned idx;
 
@@ -211,7 +210,7 @@ static void fq_ring_free(struct fq_domain *fq_domain, 
struct fq *fq)
if (fq_domain->entry_dtor)
fq_domain->entry_dtor(fq->entries[idx].data);
 
-   free_iova_fast(iovad,
+   free_iova_fast(&cookie->rcached,
   fq->entries[idx].iova_pfn,
   fq->entries[idx].pages);
 
@@ -330,7 +329,7 @@ static int init_flush_queue(struct fq_domain *fq_domain,
 static inline size_t cookie_msi_granule(struct iommu_dma_cookie *cookie)
 {
if (cookie->type == IOMMU_DMA_IOVA_COOKIE)
-   return cookie->iovad.granule;
+   return cookie->rcached.iovad.granule;
return PAGE_SIZE;
 }
 
@@ -413,9 +412,10 @@ void iommu_put_dma_cookie(struct iommu_domain *domain)
if (!cookie)
return;
 
-   if (cookie->type == IOMMU_DMA_IOVA_COOKIE && cookie->iovad.granule) {
+   if (cookie->type == IOMMU_DMA_IOVA_COOKIE &&
+   cookie->rcached.iovad.granule) {
free_flush_queue(&cookie->fq);
-   put_iova_domain(&cookie->iovad);
+   put_iova_caching_domain(&cookie->rcached);
}
 
list_for_each_entry_safe(msi, tmp, &cookie->msi_page_list, list) {
@@ -449,7 +449,7 @@ EXPORT_SYMBOL(iommu_dma_get_resv_regions);
 static int cookie_init_hw_msi_region(struct iommu_dma_cookie *cookie,
phys_addr_t start, phys_addr_t end)
 {
-   struct iova_domain *iovad = &cookie->iovad;
+   struct iova_domain *iovad = &cookie->rcached.iovad;
struct iommu_dma_msi_page *msi_page;
int i, num_pages;
 
@@ -520,7 +520,8 @@ static int iova_reserve_iommu_regions(struct device *dev,
struct iommu_domain *domain)
 {
struct iommu_dma_cookie *cookie = domain->iova_cookie;
-   struct iova_domain *iovad = &cookie->iovad;
+   struct iova_caching_domain *rcached = &cookie->rcached;
+   struct iova_domain *iovad = &rcached->iovad;
struct iommu_resv_region *region;
LIST_HEAD(resv_regions);
int ret = 0;
@@ -612,14 +613,17 @@ static int iommu_dma_init_domain(struct iommu_domain 
*domain, dma_addr_t base,
 dma_addr_t limit, struct device *dev)
 {
struct iommu_dma_cookie *cookie = domain->iova_cookie;
+   struct iova_caching_domain *rcached;
unsigned long order, base_pfn;
struct iova_domain *iovad;
struct fq_domain *fq;
+   int ret;
 
if (!cookie || cookie->type != IOMMU_DMA_IOVA_COOKIE)
return -EINVAL;
 
-   iovad = &cookie->iovad;
+   rcached = &cookie->rcached;
+   iovad = &rcached->iovad;
fq = &cookie->fq;
 
/* Use the smallest supported page size for IOVA granularity */
@@ -652,7 +656,11 @@ static int iommu_dma_init_domain(struct iommu_domain 
*domain, dma_addr_t base,
fq->flush_c