From: Oleksandr Andrushchenko <andr2000@gmail.com> To: xen-devel@lists.xenproject.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-media@vger.kernel.org, jgross@suse.com, boris.ostrovsky@oracle.com, konrad.wilk@oracle.com Cc: daniel.vetter@intel.com, andr2000@gmail.com, dongwon.kim@intel.com, matthew.d.roper@intel.com, Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> Subject: [PATCH v3 5/9] xen/gntdev: Allow mappings for DMA buffers Date: Tue, 12 Jun 2018 16:41:56 +0300 [thread overview] Message-ID: <20180612134200.17456-6-andr2000@gmail.com> (raw) In-Reply-To: <20180612134200.17456-1-andr2000@gmail.com> From: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> Allow mappings for DMA backed buffers if grant table module supports such: this extends grant device to not only map buffers made of balloon pages, but also from buffers allocated with dma_alloc_xxx. Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> --- drivers/xen/gntdev.c | 99 ++++++++++++++++++++++++++++++++++++++- include/uapi/xen/gntdev.h | 15 ++++++ 2 files changed, 112 insertions(+), 2 deletions(-) diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index bd56653b9bbc..d6b79ad1cd6f 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -37,6 +37,9 @@ #include <linux/slab.h> #include <linux/highmem.h> #include <linux/refcount.h> +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC +#include <linux/of_device.h> +#endif #include <xen/xen.h> #include <xen/grant_table.h> @@ -72,6 +75,11 @@ struct gntdev_priv { struct mutex lock; struct mm_struct *mm; struct mmu_notifier mn; + +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + /* Device for which DMA memory is allocated. */ + struct device *dma_dev; +#endif }; struct unmap_notify { @@ -96,10 +104,27 @@ struct grant_map { struct gnttab_unmap_grant_ref *kunmap_ops; struct page **pages; unsigned long pages_vm_start; + +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + /* + * If dmabuf_vaddr is not NULL then this mapping is backed by DMA + * capable memory. + */ + + struct device *dma_dev; + /* Flags used to create this DMA buffer: GNTDEV_DMA_FLAG_XXX. */ + int dma_flags; + void *dma_vaddr; + dma_addr_t dma_bus_addr; + /* Needed to avoid allocation in gnttab_dma_free_pages(). */ + xen_pfn_t *frames; +#endif }; static int unmap_grant_pages(struct grant_map *map, int offset, int pages); +static struct miscdevice gntdev_miscdev; + /* ------------------------------------------------------------------ */ static void gntdev_print_maps(struct gntdev_priv *priv, @@ -121,8 +146,27 @@ static void gntdev_free_map(struct grant_map *map) if (map == NULL) return; +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + if (map->dma_vaddr) { + struct gnttab_dma_alloc_args args; + + args.dev = map->dma_dev; + args.coherent = map->dma_flags & GNTDEV_DMA_FLAG_COHERENT; + args.nr_pages = map->count; + args.pages = map->pages; + args.frames = map->frames; + args.vaddr = map->dma_vaddr; + args.dev_bus_addr = map->dma_bus_addr; + + gnttab_dma_free_pages(&args); + } else +#endif if (map->pages) gnttab_free_pages(map->count, map->pages); + +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + kfree(map->frames); +#endif kfree(map->pages); kfree(map->grants); kfree(map->map_ops); @@ -132,7 +176,8 @@ static void gntdev_free_map(struct grant_map *map) kfree(map); } -static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) +static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count, + int dma_flags) { struct grant_map *add; int i; @@ -155,6 +200,37 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) NULL == add->pages) goto err; +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + add->dma_flags = dma_flags; + + /* + * Check if this mapping is requested to be backed + * by a DMA buffer. + */ + if (dma_flags & (GNTDEV_DMA_FLAG_WC | GNTDEV_DMA_FLAG_COHERENT)) { + struct gnttab_dma_alloc_args args; + + add->frames = kcalloc(count, sizeof(add->frames[0]), + GFP_KERNEL); + if (!add->frames) + goto err; + + /* Remember the device, so we can free DMA memory. */ + add->dma_dev = priv->dma_dev; + + args.dev = priv->dma_dev; + args.coherent = dma_flags & GNTDEV_DMA_FLAG_COHERENT; + args.nr_pages = count; + args.pages = add->pages; + args.frames = add->frames; + + if (gnttab_dma_alloc_pages(&args)) + goto err; + + add->dma_vaddr = args.vaddr; + add->dma_bus_addr = args.dev_bus_addr; + } else +#endif if (gnttab_alloc_pages(count, add->pages)) goto err; @@ -325,6 +401,14 @@ static int map_grant_pages(struct grant_map *map) map->unmap_ops[i].handle = map->map_ops[i].handle; if (use_ptemod) map->kunmap_ops[i].handle = map->kmap_ops[i].handle; +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + else if (map->dma_vaddr) { + unsigned long mfn; + + mfn = pfn_to_bfn(page_to_pfn(map->pages[i])); + map->unmap_ops[i].dev_bus_addr = __pfn_to_phys(mfn); + } +#endif } return err; } @@ -548,6 +632,17 @@ static int gntdev_open(struct inode *inode, struct file *flip) } flip->private_data = priv; +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + priv->dma_dev = gntdev_miscdev.this_device; + + /* + * The device is not spawn from a device tree, so arch_setup_dma_ops + * is not called, thus leaving the device with dummy DMA ops. + * Fix this call of_dma_configure() with a NULL node to set + * default DMA ops. + */ + of_dma_configure(priv->dma_dev, NULL); +#endif pr_debug("priv %p\n", priv); return 0; @@ -589,7 +684,7 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv, return -EINVAL; err = -ENOMEM; - map = gntdev_alloc_map(priv, op.count); + map = gntdev_alloc_map(priv, op.count, 0 /* This is not a dma-buf. */); if (!map) return err; diff --git a/include/uapi/xen/gntdev.h b/include/uapi/xen/gntdev.h index 6d1163456c03..4b9d498a31d4 100644 --- a/include/uapi/xen/gntdev.h +++ b/include/uapi/xen/gntdev.h @@ -200,4 +200,19 @@ struct ioctl_gntdev_grant_copy { /* Send an interrupt on the indicated event channel */ #define UNMAP_NOTIFY_SEND_EVENT 0x2 +/* + * Flags to be used while requesting memory mapping's backing storage + * to be allocated with DMA API. + */ + +/* + * The buffer is backed with memory allocated with dma_alloc_wc. + */ +#define GNTDEV_DMA_FLAG_WC (1 << 0) + +/* + * The buffer is backed with memory allocated with dma_alloc_coherent. + */ +#define GNTDEV_DMA_FLAG_COHERENT (1 << 1) + #endif /* __LINUX_PUBLIC_GNTDEV_H__ */ -- 2.17.1
WARNING: multiple messages have this Message-ID (diff)
From: Oleksandr Andrushchenko <andr2000@gmail.com> To: xen-devel@lists.xenproject.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-media@vger.kernel.org, jgross@suse.com, boris.ostrovsky@oracle.com, konrad.wilk@oracle.com Cc: andr2000@gmail.com, daniel.vetter@intel.com, dongwon.kim@intel.com, Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> Subject: [PATCH v3 5/9] xen/gntdev: Allow mappings for DMA buffers Date: Tue, 12 Jun 2018 16:41:56 +0300 [thread overview] Message-ID: <20180612134200.17456-6-andr2000@gmail.com> (raw) In-Reply-To: <20180612134200.17456-1-andr2000@gmail.com> From: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> Allow mappings for DMA backed buffers if grant table module supports such: this extends grant device to not only map buffers made of balloon pages, but also from buffers allocated with dma_alloc_xxx. Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> --- drivers/xen/gntdev.c | 99 ++++++++++++++++++++++++++++++++++++++- include/uapi/xen/gntdev.h | 15 ++++++ 2 files changed, 112 insertions(+), 2 deletions(-) diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index bd56653b9bbc..d6b79ad1cd6f 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -37,6 +37,9 @@ #include <linux/slab.h> #include <linux/highmem.h> #include <linux/refcount.h> +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC +#include <linux/of_device.h> +#endif #include <xen/xen.h> #include <xen/grant_table.h> @@ -72,6 +75,11 @@ struct gntdev_priv { struct mutex lock; struct mm_struct *mm; struct mmu_notifier mn; + +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + /* Device for which DMA memory is allocated. */ + struct device *dma_dev; +#endif }; struct unmap_notify { @@ -96,10 +104,27 @@ struct grant_map { struct gnttab_unmap_grant_ref *kunmap_ops; struct page **pages; unsigned long pages_vm_start; + +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + /* + * If dmabuf_vaddr is not NULL then this mapping is backed by DMA + * capable memory. + */ + + struct device *dma_dev; + /* Flags used to create this DMA buffer: GNTDEV_DMA_FLAG_XXX. */ + int dma_flags; + void *dma_vaddr; + dma_addr_t dma_bus_addr; + /* Needed to avoid allocation in gnttab_dma_free_pages(). */ + xen_pfn_t *frames; +#endif }; static int unmap_grant_pages(struct grant_map *map, int offset, int pages); +static struct miscdevice gntdev_miscdev; + /* ------------------------------------------------------------------ */ static void gntdev_print_maps(struct gntdev_priv *priv, @@ -121,8 +146,27 @@ static void gntdev_free_map(struct grant_map *map) if (map == NULL) return; +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + if (map->dma_vaddr) { + struct gnttab_dma_alloc_args args; + + args.dev = map->dma_dev; + args.coherent = map->dma_flags & GNTDEV_DMA_FLAG_COHERENT; + args.nr_pages = map->count; + args.pages = map->pages; + args.frames = map->frames; + args.vaddr = map->dma_vaddr; + args.dev_bus_addr = map->dma_bus_addr; + + gnttab_dma_free_pages(&args); + } else +#endif if (map->pages) gnttab_free_pages(map->count, map->pages); + +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + kfree(map->frames); +#endif kfree(map->pages); kfree(map->grants); kfree(map->map_ops); @@ -132,7 +176,8 @@ static void gntdev_free_map(struct grant_map *map) kfree(map); } -static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) +static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count, + int dma_flags) { struct grant_map *add; int i; @@ -155,6 +200,37 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) NULL == add->pages) goto err; +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + add->dma_flags = dma_flags; + + /* + * Check if this mapping is requested to be backed + * by a DMA buffer. + */ + if (dma_flags & (GNTDEV_DMA_FLAG_WC | GNTDEV_DMA_FLAG_COHERENT)) { + struct gnttab_dma_alloc_args args; + + add->frames = kcalloc(count, sizeof(add->frames[0]), + GFP_KERNEL); + if (!add->frames) + goto err; + + /* Remember the device, so we can free DMA memory. */ + add->dma_dev = priv->dma_dev; + + args.dev = priv->dma_dev; + args.coherent = dma_flags & GNTDEV_DMA_FLAG_COHERENT; + args.nr_pages = count; + args.pages = add->pages; + args.frames = add->frames; + + if (gnttab_dma_alloc_pages(&args)) + goto err; + + add->dma_vaddr = args.vaddr; + add->dma_bus_addr = args.dev_bus_addr; + } else +#endif if (gnttab_alloc_pages(count, add->pages)) goto err; @@ -325,6 +401,14 @@ static int map_grant_pages(struct grant_map *map) map->unmap_ops[i].handle = map->map_ops[i].handle; if (use_ptemod) map->kunmap_ops[i].handle = map->kmap_ops[i].handle; +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + else if (map->dma_vaddr) { + unsigned long mfn; + + mfn = pfn_to_bfn(page_to_pfn(map->pages[i])); + map->unmap_ops[i].dev_bus_addr = __pfn_to_phys(mfn); + } +#endif } return err; } @@ -548,6 +632,17 @@ static int gntdev_open(struct inode *inode, struct file *flip) } flip->private_data = priv; +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + priv->dma_dev = gntdev_miscdev.this_device; + + /* + * The device is not spawn from a device tree, so arch_setup_dma_ops + * is not called, thus leaving the device with dummy DMA ops. + * Fix this call of_dma_configure() with a NULL node to set + * default DMA ops. + */ + of_dma_configure(priv->dma_dev, NULL); +#endif pr_debug("priv %p\n", priv); return 0; @@ -589,7 +684,7 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv, return -EINVAL; err = -ENOMEM; - map = gntdev_alloc_map(priv, op.count); + map = gntdev_alloc_map(priv, op.count, 0 /* This is not a dma-buf. */); if (!map) return err; diff --git a/include/uapi/xen/gntdev.h b/include/uapi/xen/gntdev.h index 6d1163456c03..4b9d498a31d4 100644 --- a/include/uapi/xen/gntdev.h +++ b/include/uapi/xen/gntdev.h @@ -200,4 +200,19 @@ struct ioctl_gntdev_grant_copy { /* Send an interrupt on the indicated event channel */ #define UNMAP_NOTIFY_SEND_EVENT 0x2 +/* + * Flags to be used while requesting memory mapping's backing storage + * to be allocated with DMA API. + */ + +/* + * The buffer is backed with memory allocated with dma_alloc_wc. + */ +#define GNTDEV_DMA_FLAG_WC (1 << 0) + +/* + * The buffer is backed with memory allocated with dma_alloc_coherent. + */ +#define GNTDEV_DMA_FLAG_COHERENT (1 << 1) + #endif /* __LINUX_PUBLIC_GNTDEV_H__ */ -- 2.17.1 _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
next prev parent reply other threads:[~2018-06-12 13:43 UTC|newest] Thread overview: 80+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-06-12 13:41 [PATCH v3 0/9] xen: dma-buf support for grant device Oleksandr Andrushchenko 2018-06-12 13:41 ` Oleksandr Andrushchenko 2018-06-12 13:41 ` [PATCH v3 1/9] xen/grant-table: Export gnttab_{alloc|free}_pages as GPL Oleksandr Andrushchenko 2018-06-12 13:41 ` Oleksandr Andrushchenko 2018-06-12 13:41 ` Oleksandr Andrushchenko 2018-06-12 13:41 ` [PATCH v3 2/9] xen/grant-table: Make set/clear page private code shared Oleksandr Andrushchenko 2018-06-12 13:41 ` Oleksandr Andrushchenko 2018-06-12 13:41 ` Oleksandr Andrushchenko 2018-06-12 13:41 ` [PATCH v3 3/9] xen/balloon: Share common memory reservation routines Oleksandr Andrushchenko 2018-06-12 13:41 ` Oleksandr Andrushchenko 2018-06-12 13:41 ` Oleksandr Andrushchenko 2018-06-13 0:47 ` Boris Ostrovsky 2018-06-13 6:26 ` Oleksandr Andrushchenko 2018-06-13 6:26 ` Oleksandr Andrushchenko 2018-06-13 12:02 ` Boris Ostrovsky 2018-06-13 12:02 ` Boris Ostrovsky 2018-06-13 12:03 ` Oleksandr Andrushchenko 2018-06-13 12:03 ` Oleksandr Andrushchenko 2018-06-13 12:27 ` Oleksandr Andrushchenko 2018-06-13 12:27 ` Oleksandr Andrushchenko 2018-06-13 0:47 ` Boris Ostrovsky 2018-06-13 1:07 ` Boris Ostrovsky 2018-06-13 6:50 ` Oleksandr Andrushchenko 2018-06-13 6:50 ` Oleksandr Andrushchenko 2018-06-13 1:07 ` Boris Ostrovsky 2018-06-12 13:41 ` [PATCH v3 4/9] xen/grant-table: Allow allocating buffers suitable for DMA Oleksandr Andrushchenko 2018-06-12 13:41 ` Oleksandr Andrushchenko 2018-06-13 1:12 ` Boris Ostrovsky 2018-06-13 7:07 ` Oleksandr Andrushchenko 2018-06-13 7:07 ` Oleksandr Andrushchenko 2018-06-13 7:07 ` Oleksandr Andrushchenko 2018-06-13 1:12 ` Boris Ostrovsky 2018-06-12 13:41 ` Oleksandr Andrushchenko 2018-06-12 13:41 ` [PATCH v3 5/9] xen/gntdev: Allow mappings for DMA buffers Oleksandr Andrushchenko 2018-06-12 13:41 ` Oleksandr Andrushchenko [this message] 2018-06-12 13:41 ` Oleksandr Andrushchenko 2018-06-13 1:26 ` Boris Ostrovsky 2018-06-13 1:26 ` Boris Ostrovsky 2018-06-13 7:16 ` Oleksandr Andrushchenko 2018-06-13 7:16 ` Oleksandr Andrushchenko 2018-06-14 7:00 ` Oleksandr Andrushchenko 2018-06-14 7:00 ` Oleksandr Andrushchenko 2018-06-12 13:41 ` [PATCH v3 6/9] xen/gntdev: Make private routines/structures accessible Oleksandr Andrushchenko 2018-06-12 13:41 ` Oleksandr Andrushchenko 2018-06-13 1:38 ` Boris Ostrovsky 2018-06-13 1:38 ` Boris Ostrovsky 2018-06-13 7:23 ` Oleksandr Andrushchenko 2018-06-13 7:23 ` Oleksandr Andrushchenko 2018-06-12 13:41 ` Oleksandr Andrushchenko 2018-06-12 13:41 ` [PATCH v3 7/9] xen/gntdev: Add initial support for dma-buf UAPI Oleksandr Andrushchenko 2018-06-12 13:41 ` Oleksandr Andrushchenko 2018-06-13 1:49 ` Boris Ostrovsky 2018-06-13 1:49 ` Boris Ostrovsky 2018-06-13 8:17 ` Oleksandr Andrushchenko 2018-06-13 8:17 ` Oleksandr Andrushchenko 2018-06-12 13:41 ` [PATCH v3 8/9] xen/gntdev: Implement dma-buf export functionality Oleksandr Andrushchenko 2018-06-12 13:41 ` Oleksandr Andrushchenko 2018-06-12 13:41 ` Oleksandr Andrushchenko 2018-06-13 2:58 ` Boris Ostrovsky 2018-06-13 11:57 ` Oleksandr Andrushchenko 2018-06-13 11:57 ` Oleksandr Andrushchenko 2018-06-13 22:19 ` Boris Ostrovsky 2018-06-13 22:19 ` Boris Ostrovsky 2018-06-14 5:41 ` Oleksandr Andrushchenko 2018-06-14 5:41 ` Oleksandr Andrushchenko 2018-06-13 2:58 ` Boris Ostrovsky 2018-06-12 13:42 ` [PATCH v3 9/9] xen/gntdev: Implement dma-buf import functionality Oleksandr Andrushchenko 2018-06-13 3:14 ` Boris Ostrovsky 2018-06-13 9:04 ` Oleksandr Andrushchenko 2018-06-13 9:04 ` Oleksandr Andrushchenko 2018-06-13 22:03 ` Boris Ostrovsky 2018-06-13 22:03 ` Boris Ostrovsky 2018-06-14 6:39 ` Oleksandr Andrushchenko 2018-06-14 6:39 ` Oleksandr Andrushchenko 2018-06-13 3:14 ` Boris Ostrovsky 2018-06-12 13:42 ` Oleksandr Andrushchenko 2018-06-14 6:47 ` [PATCH v3 0/9] xen: dma-buf support for grant device Oleksandr Andrushchenko 2018-06-14 6:47 ` Oleksandr Andrushchenko 2018-06-14 17:48 ` Boris Ostrovsky 2018-06-14 17:48 ` Boris Ostrovsky
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20180612134200.17456-6-andr2000@gmail.com \ --to=andr2000@gmail.com \ --cc=boris.ostrovsky@oracle.com \ --cc=daniel.vetter@intel.com \ --cc=dongwon.kim@intel.com \ --cc=dri-devel@lists.freedesktop.org \ --cc=jgross@suse.com \ --cc=konrad.wilk@oracle.com \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-media@vger.kernel.org \ --cc=matthew.d.roper@intel.com \ --cc=oleksandr_andrushchenko@epam.com \ --cc=xen-devel@lists.xenproject.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.