Re: [PATCH v2 4/9] xen/grant-table: Allow allocating buffers suitable for DMA

2018-06-06 Thread Oleksandr Andrushchenko

On 06/04/2018 09:46 PM, Boris Ostrovsky wrote:

On 06/01/2018 07:41 AM, Oleksandr Andrushchenko wrote:

From: Oleksandr Andrushchenko 

Extend grant table module API to allow allocating buffers that can
be used for DMA operations and mapping foreign grant references
on top of those.
The resulting buffer is similar to the one allocated by the balloon
driver in terms that proper memory reservation is made
({increase|decrease}_reservation and VA mappings updated if needed).
This is useful for sharing foreign buffers with HW drivers which
cannot work with scattered buffers provided by the balloon driver,
but require DMAable memory instead.

Signed-off-by: Oleksandr Andrushchenko 
---
  drivers/xen/Kconfig   |  13 +
  drivers/xen/grant-table.c | 109 ++
  include/xen/grant_table.h |  18 +++
  3 files changed, 140 insertions(+)

diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index e5d0c28372ea..39536ddfbce4 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -161,6 +161,19 @@ config XEN_GRANT_DEV_ALLOC
  to other domains. This can be used to implement frontend drivers
  or as part of an inter-domain shared memory channel.
  
+config XEN_GRANT_DMA_ALLOC

+   bool "Allow allocating DMA capable buffers with grant reference module"
+   depends on XEN && HAS_DMA
+   help
+ Extends grant table module API to allow allocating DMA capable
+ buffers and mapping foreign grant references on top of it.
+ The resulting buffer is similar to one allocated by the balloon
+ driver in terms that proper memory reservation is made
+ ({increase|decrease}_reservation and VA mappings updated if needed).
+ This is useful for sharing foreign buffers with HW drivers which
+ cannot work with scattered buffers provided by the balloon driver,
+ but require DMAable memory instead.
+
  config SWIOTLB_XEN
def_bool y
select SWIOTLB
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index dbb48a89e987..5658e58d9cc6 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -45,6 +45,9 @@
  #include 
  #include 
  #include 
+#ifdef CONFIG_XEN_GRANT_DMA_ALLOC
+#include 
+#endif
  
  #include 

  #include 
@@ -57,6 +60,7 @@
  #ifdef CONFIG_X86
  #include 
  #endif
+#include 
  #include 
  #include 
  
@@ -811,6 +815,73 @@ int gnttab_alloc_pages(int nr_pages, struct page **pages)

  }
  EXPORT_SYMBOL_GPL(gnttab_alloc_pages);
  
+#ifdef CONFIG_XEN_GRANT_DMA_ALLOC

+/**
+ * gnttab_dma_alloc_pages - alloc DMAable pages suitable for grant mapping into
+ * @args: arguments to the function
+ */
+int gnttab_dma_alloc_pages(struct gnttab_dma_alloc_args *args)
+{
+   unsigned long pfn, start_pfn;
+   size_t size;
+   int i, ret;
+
+   size = args->nr_pages << PAGE_SHIFT;
+   if (args->coherent)
+   args->vaddr = dma_alloc_coherent(args->dev, size,
+>dev_bus_addr,
+GFP_KERNEL | __GFP_NOWARN);
+   else
+   args->vaddr = dma_alloc_wc(args->dev, size,
+  >dev_bus_addr,
+  GFP_KERNEL | __GFP_NOWARN);
+   if (!args->vaddr) {
+   pr_err("Failed to allocate DMA buffer of size %zu\n", size);
+   return -ENOMEM;
+   }
+
+   start_pfn = __phys_to_pfn(args->dev_bus_addr);
+   for (pfn = start_pfn, i = 0; pfn < start_pfn + args->nr_pages;
+   pfn++, i++) {
+   struct page *page = pfn_to_page(pfn);
+
+   args->pages[i] = page;
+   args->frames[i] = xen_page_to_gfn(page);
+   xenmem_reservation_scrub_page(page);
+   }
+
+   xenmem_reservation_va_mapping_reset(args->nr_pages, args->pages);
+
+   ret = xenmem_reservation_decrease(args->nr_pages, args->frames);
+   if (ret != args->nr_pages) {
+   pr_err("Failed to decrease reservation for DMA buffer\n");
+   ret = -EFAULT;
+   goto fail_free_dma;
+   }
+
+   ret = gnttab_pages_set_private(args->nr_pages, args->pages);
+   if (ret < 0)
+   goto fail_clear_private;
+
+   return 0;
+
+fail_clear_private:
+   gnttab_pages_clear_private(args->nr_pages, args->pages);
+fail_free_dma:
+   xenmem_reservation_increase(args->nr_pages, args->frames);
+   xenmem_reservation_va_mapping_update(args->nr_pages, args->pages,
+args->frames);
+   if (args->coherent)
+   dma_free_coherent(args->dev, size,
+ args->vaddr, args->dev_bus_addr);
+   else
+   dma_free_wc(args->dev, size,
+   args->vaddr, args->dev_bus_addr);
+   return ret;
+}


Would it be possible to call gnttab_dma_free_pages() 

Re: [PATCH v2 4/9] xen/grant-table: Allow allocating buffers suitable for DMA

2018-06-05 Thread Boris Ostrovsky
On 06/01/2018 07:41 AM, Oleksandr Andrushchenko wrote:
> From: Oleksandr Andrushchenko 
>
> Extend grant table module API to allow allocating buffers that can
> be used for DMA operations and mapping foreign grant references
> on top of those.
> The resulting buffer is similar to the one allocated by the balloon
> driver in terms that proper memory reservation is made
> ({increase|decrease}_reservation and VA mappings updated if needed).
> This is useful for sharing foreign buffers with HW drivers which
> cannot work with scattered buffers provided by the balloon driver,
> but require DMAable memory instead.
>
> Signed-off-by: Oleksandr Andrushchenko 
> ---
>  drivers/xen/Kconfig   |  13 +
>  drivers/xen/grant-table.c | 109 ++
>  include/xen/grant_table.h |  18 +++
>  3 files changed, 140 insertions(+)
>
> diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
> index e5d0c28372ea..39536ddfbce4 100644
> --- a/drivers/xen/Kconfig
> +++ b/drivers/xen/Kconfig
> @@ -161,6 +161,19 @@ config XEN_GRANT_DEV_ALLOC
> to other domains. This can be used to implement frontend drivers
> or as part of an inter-domain shared memory channel.
>  
> +config XEN_GRANT_DMA_ALLOC
> + bool "Allow allocating DMA capable buffers with grant reference module"
> + depends on XEN && HAS_DMA
> + help
> +   Extends grant table module API to allow allocating DMA capable
> +   buffers and mapping foreign grant references on top of it.
> +   The resulting buffer is similar to one allocated by the balloon
> +   driver in terms that proper memory reservation is made
> +   ({increase|decrease}_reservation and VA mappings updated if needed).
> +   This is useful for sharing foreign buffers with HW drivers which
> +   cannot work with scattered buffers provided by the balloon driver,
> +   but require DMAable memory instead.
> +
>  config SWIOTLB_XEN
>   def_bool y
>   select SWIOTLB
> diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
> index dbb48a89e987..5658e58d9cc6 100644
> --- a/drivers/xen/grant-table.c
> +++ b/drivers/xen/grant-table.c
> @@ -45,6 +45,9 @@
>  #include 
>  #include 
>  #include 
> +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC
> +#include 
> +#endif
>  
>  #include 
>  #include 
> @@ -57,6 +60,7 @@
>  #ifdef CONFIG_X86
>  #include 
>  #endif
> +#include 
>  #include 
>  #include 
>  
> @@ -811,6 +815,73 @@ int gnttab_alloc_pages(int nr_pages, struct page **pages)
>  }
>  EXPORT_SYMBOL_GPL(gnttab_alloc_pages);
>  
> +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC
> +/**
> + * gnttab_dma_alloc_pages - alloc DMAable pages suitable for grant mapping 
> into
> + * @args: arguments to the function
> + */
> +int gnttab_dma_alloc_pages(struct gnttab_dma_alloc_args *args)
> +{
> + unsigned long pfn, start_pfn;
> + size_t size;
> + int i, ret;
> +
> + size = args->nr_pages << PAGE_SHIFT;
> + if (args->coherent)
> + args->vaddr = dma_alloc_coherent(args->dev, size,
> +  >dev_bus_addr,
> +  GFP_KERNEL | __GFP_NOWARN);
> + else
> + args->vaddr = dma_alloc_wc(args->dev, size,
> +>dev_bus_addr,
> +GFP_KERNEL | __GFP_NOWARN);
> + if (!args->vaddr) {
> + pr_err("Failed to allocate DMA buffer of size %zu\n", size);
> + return -ENOMEM;
> + }
> +
> + start_pfn = __phys_to_pfn(args->dev_bus_addr);
> + for (pfn = start_pfn, i = 0; pfn < start_pfn + args->nr_pages;
> + pfn++, i++) {
> + struct page *page = pfn_to_page(pfn);
> +
> + args->pages[i] = page;
> + args->frames[i] = xen_page_to_gfn(page);
> + xenmem_reservation_scrub_page(page);
> + }
> +
> + xenmem_reservation_va_mapping_reset(args->nr_pages, args->pages);
> +
> + ret = xenmem_reservation_decrease(args->nr_pages, args->frames);
> + if (ret != args->nr_pages) {
> + pr_err("Failed to decrease reservation for DMA buffer\n");
> + ret = -EFAULT;
> + goto fail_free_dma;
> + }
> +
> + ret = gnttab_pages_set_private(args->nr_pages, args->pages);
> + if (ret < 0)
> + goto fail_clear_private;
> +
> + return 0;
> +
> +fail_clear_private:
> + gnttab_pages_clear_private(args->nr_pages, args->pages);
> +fail_free_dma:
> + xenmem_reservation_increase(args->nr_pages, args->frames);
> + xenmem_reservation_va_mapping_update(args->nr_pages, args->pages,
> +  args->frames);
> + if (args->coherent)
> + dma_free_coherent(args->dev, size,
> +   args->vaddr, args->dev_bus_addr);
> + else
> + dma_free_wc(args->dev, size,
> + args->vaddr, args->dev_bus_addr);
> + return 

[PATCH v2 4/9] xen/grant-table: Allow allocating buffers suitable for DMA

2018-06-01 Thread Oleksandr Andrushchenko
From: Oleksandr Andrushchenko 

Extend grant table module API to allow allocating buffers that can
be used for DMA operations and mapping foreign grant references
on top of those.
The resulting buffer is similar to the one allocated by the balloon
driver in terms that proper memory reservation is made
({increase|decrease}_reservation and VA mappings updated if needed).
This is useful for sharing foreign buffers with HW drivers which
cannot work with scattered buffers provided by the balloon driver,
but require DMAable memory instead.

Signed-off-by: Oleksandr Andrushchenko 
---
 drivers/xen/Kconfig   |  13 +
 drivers/xen/grant-table.c | 109 ++
 include/xen/grant_table.h |  18 +++
 3 files changed, 140 insertions(+)

diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index e5d0c28372ea..39536ddfbce4 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -161,6 +161,19 @@ config XEN_GRANT_DEV_ALLOC
  to other domains. This can be used to implement frontend drivers
  or as part of an inter-domain shared memory channel.
 
+config XEN_GRANT_DMA_ALLOC
+   bool "Allow allocating DMA capable buffers with grant reference module"
+   depends on XEN && HAS_DMA
+   help
+ Extends grant table module API to allow allocating DMA capable
+ buffers and mapping foreign grant references on top of it.
+ The resulting buffer is similar to one allocated by the balloon
+ driver in terms that proper memory reservation is made
+ ({increase|decrease}_reservation and VA mappings updated if needed).
+ This is useful for sharing foreign buffers with HW drivers which
+ cannot work with scattered buffers provided by the balloon driver,
+ but require DMAable memory instead.
+
 config SWIOTLB_XEN
def_bool y
select SWIOTLB
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index dbb48a89e987..5658e58d9cc6 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -45,6 +45,9 @@
 #include 
 #include 
 #include 
+#ifdef CONFIG_XEN_GRANT_DMA_ALLOC
+#include 
+#endif
 
 #include 
 #include 
@@ -57,6 +60,7 @@
 #ifdef CONFIG_X86
 #include 
 #endif
+#include 
 #include 
 #include 
 
@@ -811,6 +815,73 @@ int gnttab_alloc_pages(int nr_pages, struct page **pages)
 }
 EXPORT_SYMBOL_GPL(gnttab_alloc_pages);
 
+#ifdef CONFIG_XEN_GRANT_DMA_ALLOC
+/**
+ * gnttab_dma_alloc_pages - alloc DMAable pages suitable for grant mapping into
+ * @args: arguments to the function
+ */
+int gnttab_dma_alloc_pages(struct gnttab_dma_alloc_args *args)
+{
+   unsigned long pfn, start_pfn;
+   size_t size;
+   int i, ret;
+
+   size = args->nr_pages << PAGE_SHIFT;
+   if (args->coherent)
+   args->vaddr = dma_alloc_coherent(args->dev, size,
+>dev_bus_addr,
+GFP_KERNEL | __GFP_NOWARN);
+   else
+   args->vaddr = dma_alloc_wc(args->dev, size,
+  >dev_bus_addr,
+  GFP_KERNEL | __GFP_NOWARN);
+   if (!args->vaddr) {
+   pr_err("Failed to allocate DMA buffer of size %zu\n", size);
+   return -ENOMEM;
+   }
+
+   start_pfn = __phys_to_pfn(args->dev_bus_addr);
+   for (pfn = start_pfn, i = 0; pfn < start_pfn + args->nr_pages;
+   pfn++, i++) {
+   struct page *page = pfn_to_page(pfn);
+
+   args->pages[i] = page;
+   args->frames[i] = xen_page_to_gfn(page);
+   xenmem_reservation_scrub_page(page);
+   }
+
+   xenmem_reservation_va_mapping_reset(args->nr_pages, args->pages);
+
+   ret = xenmem_reservation_decrease(args->nr_pages, args->frames);
+   if (ret != args->nr_pages) {
+   pr_err("Failed to decrease reservation for DMA buffer\n");
+   ret = -EFAULT;
+   goto fail_free_dma;
+   }
+
+   ret = gnttab_pages_set_private(args->nr_pages, args->pages);
+   if (ret < 0)
+   goto fail_clear_private;
+
+   return 0;
+
+fail_clear_private:
+   gnttab_pages_clear_private(args->nr_pages, args->pages);
+fail_free_dma:
+   xenmem_reservation_increase(args->nr_pages, args->frames);
+   xenmem_reservation_va_mapping_update(args->nr_pages, args->pages,
+args->frames);
+   if (args->coherent)
+   dma_free_coherent(args->dev, size,
+ args->vaddr, args->dev_bus_addr);
+   else
+   dma_free_wc(args->dev, size,
+   args->vaddr, args->dev_bus_addr);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(gnttab_dma_alloc_pages);
+#endif
+
 void gnttab_pages_clear_private(int nr_pages, struct page **pages)
 {
int i;
@@ -838,6 +909,44 @@ void gnttab_free_pages(int