All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] misc: sram: Add DMA-BUF Heap exporting of SRAM areas
@ 2024-04-09 12:06 Pascal FONTAIN
  2024-04-09 12:06 ` [PATCH v3 1/2] misc: sram: Move probe of sram subsystem Pascal FONTAIN
  2024-04-09 12:06 ` [PATCH v3 2/2] misc: sram: Add DMA-BUF Heap exporting of SRAM areas Pascal FONTAIN
  0 siblings, 2 replies; 8+ messages in thread
From: Pascal FONTAIN @ 2024-04-09 12:06 UTC (permalink / raw
  To: linux-kernel; +Cc: afd, Pascal Fontain

From: Pascal Fontain <pascal.fontain@bachmann.info>

Changes from v2:
 - Move sram initialization to device phase
 - Solve compile problems found by kernel test robot

Andrew Davis (1):
  misc: sram: Add DMA-BUF Heap exporting of SRAM areas

Pascal Fontain (1):
  misc: sram: Move probe of sram subsystem

 drivers/misc/Kconfig         |   7 +
 drivers/misc/Makefile        |   1 +
 drivers/misc/sram-dma-heap.c | 246 +++++++++++++++++++++++++++++++++++
 drivers/misc/sram.c          |   8 +-
 drivers/misc/sram.h          |  16 +++
 5 files changed, 277 insertions(+), 1 deletion(-)
 create mode 100644 drivers/misc/sram-dma-heap.c

-- 
2.39.2


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v3 1/2] misc: sram: Move probe of sram subsystem
  2024-04-09 12:06 [PATCH v3 0/2] misc: sram: Add DMA-BUF Heap exporting of SRAM areas Pascal FONTAIN
@ 2024-04-09 12:06 ` Pascal FONTAIN
  2024-04-09 12:10   ` Arnd Bergmann
  2024-04-09 12:06 ` [PATCH v3 2/2] misc: sram: Add DMA-BUF Heap exporting of SRAM areas Pascal FONTAIN
  1 sibling, 1 reply; 8+ messages in thread
From: Pascal FONTAIN @ 2024-04-09 12:06 UTC (permalink / raw
  To: linux-kernel, Arnd Bergmann, Greg Kroah-Hartman; +Cc: afd, Pascal Fontain

From: Pascal Fontain <pascal.fontain@bachmann.info>

The sram subsystem might use the dma-buf subsystem which only gets
initialized in subsys_initcall phase. Because of this we move the sram
initcall into the device phase.

Signed-off-by: Pascal Fontain <pascal.fontain@bachmann.info>
---
 drivers/misc/sram.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
index e248c0a8882f..632f90d9bcea 100644
--- a/drivers/misc/sram.c
+++ b/drivers/misc/sram.c
@@ -461,4 +461,4 @@ static int __init sram_init(void)
 	return platform_driver_register(&sram_driver);
 }
 
-postcore_initcall(sram_init);
+device_initcall(sram_init);
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 2/2] misc: sram: Add DMA-BUF Heap exporting of SRAM areas
  2024-04-09 12:06 [PATCH v3 0/2] misc: sram: Add DMA-BUF Heap exporting of SRAM areas Pascal FONTAIN
  2024-04-09 12:06 ` [PATCH v3 1/2] misc: sram: Move probe of sram subsystem Pascal FONTAIN
@ 2024-04-09 12:06 ` Pascal FONTAIN
  2024-04-09 12:14   ` Greg Kroah-Hartman
  2024-04-09 14:38   ` Andrew Davis
  1 sibling, 2 replies; 8+ messages in thread
From: Pascal FONTAIN @ 2024-04-09 12:06 UTC (permalink / raw
  To: linux-kernel, Derek Kiernan, Dragan Cvetic, Arnd Bergmann,
	Greg Kroah-Hartman, Sumit Semwal, Christian König
  Cc: afd, Pascal Fontain, linux-media, dri-devel, linaro-mm-sig

From: Andrew Davis <afd@ti.com>

This new export type exposes to userspace the SRAM area as a DMA-BUF
Heap,
this allows for allocations of DMA-BUFs that can be consumed by various
DMA-BUF supporting devices.

Signed-off-by: Andrew Davis <afd@ti.com>
Tested-by: Pascal Fontain <pascal.fontain@bachmann.info>
---
 drivers/misc/Kconfig         |   7 +
 drivers/misc/Makefile        |   1 +
 drivers/misc/sram-dma-heap.c | 246 +++++++++++++++++++++++++++++++++++
 drivers/misc/sram.c          |   6 +
 drivers/misc/sram.h          |  16 +++
 5 files changed, 276 insertions(+)
 create mode 100644 drivers/misc/sram-dma-heap.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 9e4ad4d61f06..e6674e913168 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -448,6 +448,13 @@ config SRAM
 config SRAM_EXEC
 	bool
 
+config SRAM_DMA_HEAP
+	bool "Export on-chip SRAM pools using DMA-Heaps"
+	depends on DMABUF_HEAPS && SRAM
+	help
+	  This driver allows the export of on-chip SRAM marked as both pool
+	  and exportable to userspace using the DMA-Heaps interface.
+
 config DW_XDATA_PCIE
 	depends on PCI
 	tristate "Synopsys DesignWare xData PCIe driver"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index cdc6405584e3..63effdde5163 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/
 obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
 obj-$(CONFIG_SRAM)		+= sram.o
 obj-$(CONFIG_SRAM_EXEC)		+= sram-exec.o
+obj-$(CONFIG_SRAM_DMA_HEAP)	+= sram-dma-heap.o
 obj-$(CONFIG_GENWQE)		+= genwqe/
 obj-$(CONFIG_ECHO)		+= echo/
 obj-$(CONFIG_CXL_BASE)		+= cxl/
diff --git a/drivers/misc/sram-dma-heap.c b/drivers/misc/sram-dma-heap.c
new file mode 100644
index 000000000000..e5a0bafe8cb9
--- /dev/null
+++ b/drivers/misc/sram-dma-heap.c
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SRAM DMA-Heap userspace exporter
+ *
+ * Copyright (C) 2019-2022 Texas Instruments Incorporated - https://www.ti.com/
+ *	Andrew Davis <afd@ti.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/genalloc.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/dma-buf.h>
+#include <linux/dma-heap.h>
+
+#include "sram.h"
+
+struct sram_dma_heap {
+	struct dma_heap *heap;
+	struct gen_pool *pool;
+};
+
+struct sram_dma_heap_buffer {
+	struct gen_pool *pool;
+	struct list_head attachments;
+	struct mutex attachments_lock;
+	unsigned long len;
+	void *vaddr;
+	phys_addr_t paddr;
+};
+
+struct dma_heap_attachment {
+	struct device *dev;
+	struct sg_table *table;
+	struct list_head list;
+};
+
+static int dma_heap_attach(struct dma_buf *dmabuf,
+			   struct dma_buf_attachment *attachment)
+{
+	struct sram_dma_heap_buffer *buffer = dmabuf->priv;
+	struct dma_heap_attachment *a;
+	struct sg_table *table;
+
+	a = kzalloc(sizeof(*a), GFP_KERNEL);
+	if (!a)
+		return -ENOMEM;
+
+	table = kmalloc(sizeof(*table), GFP_KERNEL);
+	if (!table) {
+		kfree(a);
+		return -ENOMEM;
+	}
+	if (sg_alloc_table(table, 1, GFP_KERNEL)) {
+		kfree(table);
+		kfree(a);
+		return -ENOMEM;
+	}
+	sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(buffer->paddr)), buffer->len, 0);
+
+	a->table = table;
+	a->dev = attachment->dev;
+	INIT_LIST_HEAD(&a->list);
+
+	attachment->priv = a;
+
+	mutex_lock(&buffer->attachments_lock);
+	list_add(&a->list, &buffer->attachments);
+	mutex_unlock(&buffer->attachments_lock);
+
+	return 0;
+}
+
+static void dma_heap_detatch(struct dma_buf *dmabuf,
+			     struct dma_buf_attachment *attachment)
+{
+	struct sram_dma_heap_buffer *buffer = dmabuf->priv;
+	struct dma_heap_attachment *a = attachment->priv;
+
+	mutex_lock(&buffer->attachments_lock);
+	list_del(&a->list);
+	mutex_unlock(&buffer->attachments_lock);
+
+	sg_free_table(a->table);
+	kfree(a->table);
+	kfree(a);
+}
+
+static struct sg_table *dma_heap_map_dma_buf(struct dma_buf_attachment *attachment,
+					     enum dma_data_direction direction)
+{
+	struct dma_heap_attachment *a = attachment->priv;
+	struct sg_table *table = a->table;
+
+	/*
+	 * As this heap is backed by uncached SRAM memory we do not need to
+	 * perform any sync operations on the buffer before allowing device
+	 * domain access. For this reason we use SKIP_CPU_SYNC and also do
+	 * not use or provide begin/end_cpu_access() dma-buf functions.
+	 */
+	if (!dma_map_sg_attrs(attachment->dev, table->sgl, table->nents,
+			      direction, DMA_ATTR_SKIP_CPU_SYNC))
+		return ERR_PTR(-ENOMEM);
+
+	return table;
+}
+
+static void dma_heap_unmap_dma_buf(struct dma_buf_attachment *attachment,
+				   struct sg_table *table,
+				   enum dma_data_direction direction)
+{
+	dma_unmap_sg_attrs(attachment->dev, table->sgl, table->nents,
+			   direction, DMA_ATTR_SKIP_CPU_SYNC);
+}
+
+static void dma_heap_dma_buf_release(struct dma_buf *dmabuf)
+{
+	struct sram_dma_heap_buffer *buffer = dmabuf->priv;
+
+	gen_pool_free(buffer->pool, (unsigned long)buffer->vaddr, buffer->len);
+	kfree(buffer);
+}
+
+static int dma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
+{
+	struct sram_dma_heap_buffer *buffer = dmabuf->priv;
+	int ret;
+
+	/* SRAM mappings are not cached */
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+	ret = vm_iomap_memory(vma, buffer->paddr, buffer->len);
+	if (ret)
+		pr_err("Could not map buffer to userspace\n");
+
+	return ret;
+}
+
+static int dma_heap_vmap(struct dma_buf *dmabuf, struct iosys_map *map)
+{
+	struct sram_dma_heap_buffer *buffer = dmabuf->priv;
+
+	iosys_map_set_vaddr(map, buffer->vaddr);
+
+	return 0;
+}
+
+static const struct dma_buf_ops sram_dma_heap_buf_ops = {
+	.attach = dma_heap_attach,
+	.detach = dma_heap_detatch,
+	.map_dma_buf = dma_heap_map_dma_buf,
+	.unmap_dma_buf = dma_heap_unmap_dma_buf,
+	.release = dma_heap_dma_buf_release,
+	.mmap = dma_heap_mmap,
+	.vmap = dma_heap_vmap,
+};
+
+static struct dma_buf *sram_dma_heap_allocate(struct dma_heap *heap,
+					      unsigned long len,
+					      unsigned long fd_flags,
+					      unsigned long heap_flags)
+{
+	struct sram_dma_heap *sram_dma_heap = dma_heap_get_drvdata(heap);
+	struct sram_dma_heap_buffer *buffer;
+
+	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+	struct dma_buf *dmabuf;
+	int ret;
+
+	buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
+	if (!buffer)
+		return ERR_PTR(-ENOMEM);
+	buffer->pool = sram_dma_heap->pool;
+	INIT_LIST_HEAD(&buffer->attachments);
+	mutex_init(&buffer->attachments_lock);
+	buffer->len = len;
+
+	buffer->vaddr = (void *)gen_pool_alloc(buffer->pool, buffer->len);
+	if (!buffer->vaddr) {
+		ret = -ENOMEM;
+		goto free_buffer;
+	}
+
+	buffer->paddr = gen_pool_virt_to_phys(buffer->pool, (unsigned long)buffer->vaddr);
+	if (buffer->paddr == -1) {
+		ret = -ENOMEM;
+		goto free_pool;
+	}
+
+	/* create the dmabuf */
+	exp_info.exp_name = dma_heap_get_name(heap);
+	exp_info.ops = &sram_dma_heap_buf_ops;
+	exp_info.size = buffer->len;
+	exp_info.flags = fd_flags;
+	exp_info.priv = buffer;
+	dmabuf = dma_buf_export(&exp_info);
+	if (IS_ERR(dmabuf)) {
+		ret = PTR_ERR(dmabuf);
+		goto free_pool;
+	}
+
+	return dmabuf;
+
+free_pool:
+	gen_pool_free(buffer->pool, (unsigned long)buffer->vaddr, buffer->len);
+free_buffer:
+	kfree(buffer);
+
+	return ERR_PTR(ret);
+}
+
+static struct dma_heap_ops sram_dma_heap_ops = {
+	.allocate = sram_dma_heap_allocate,
+};
+
+int sram_add_dma_heap(struct sram_dev *sram,
+		      struct sram_reserve *block,
+		      phys_addr_t start,
+		      struct sram_partition *part)
+{
+	struct sram_dma_heap *sram_dma_heap;
+	struct dma_heap_export_info exp_info;
+
+	dev_info(sram->dev, "Exporting SRAM Heap '%s'\n", block->label);
+
+	sram_dma_heap = kzalloc(sizeof(*sram_dma_heap), GFP_KERNEL);
+	if (!sram_dma_heap)
+		return -ENOMEM;
+	sram_dma_heap->pool = part->pool;
+
+	exp_info.name = kasprintf(GFP_KERNEL, "sram_%s", block->label);
+	exp_info.ops = &sram_dma_heap_ops;
+	exp_info.priv = sram_dma_heap;
+	sram_dma_heap->heap = dma_heap_add(&exp_info);
+	if (IS_ERR(sram_dma_heap->heap)) {
+		int ret = PTR_ERR(sram_dma_heap->heap);
+
+		kfree(sram_dma_heap);
+		return ret;
+	}
+
+	return 0;
+}
diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
index 632f90d9bcea..643c77598beb 100644
--- a/drivers/misc/sram.c
+++ b/drivers/misc/sram.c
@@ -120,6 +120,12 @@ static int sram_add_partition(struct sram_dev *sram, struct sram_reserve *block,
 		ret = sram_add_pool(sram, block, start, part);
 		if (ret)
 			return ret;
+
+		if (block->export) {
+			ret = sram_add_dma_heap(sram, block, start, part);
+			if (ret)
+				return ret;
+		}
 	}
 	if (block->export) {
 		ret = sram_add_export(sram, block, start, part);
diff --git a/drivers/misc/sram.h b/drivers/misc/sram.h
index 397205b8bf6f..062bdd25fa06 100644
--- a/drivers/misc/sram.h
+++ b/drivers/misc/sram.h
@@ -60,4 +60,20 @@ static inline int sram_add_protect_exec(struct sram_partition *part)
 	return -ENODEV;
 }
 #endif /* CONFIG_SRAM_EXEC */
+
+#ifdef CONFIG_SRAM_DMA_HEAP
+int sram_add_dma_heap(struct sram_dev *sram,
+		      struct sram_reserve *block,
+		      phys_addr_t start,
+		      struct sram_partition *part);
+#else
+static inline int sram_add_dma_heap(struct sram_dev *sram,
+				    struct sram_reserve *block,
+				    phys_addr_t start,
+				    struct sram_partition *part)
+{
+	return 0;
+}
+#endif /* CONFIG_SRAM_DMA_HEAP */
+
 #endif /* __SRAM_H */
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 1/2] misc: sram: Move probe of sram subsystem
  2024-04-09 12:06 ` [PATCH v3 1/2] misc: sram: Move probe of sram subsystem Pascal FONTAIN
@ 2024-04-09 12:10   ` Arnd Bergmann
  0 siblings, 0 replies; 8+ messages in thread
From: Arnd Bergmann @ 2024-04-09 12:10 UTC (permalink / raw
  To: Pascal FONTAIN, linux-kernel, Greg Kroah-Hartman; +Cc: Andrew Davis

On Tue, Apr 9, 2024, at 14:06, Pascal FONTAIN wrote:
> From: Pascal Fontain <pascal.fontain@bachmann.info>
>
> The sram subsystem might use the dma-buf subsystem which only gets
> initialized in subsys_initcall phase. Because of this we move the sram
> initcall into the device phase.
>
> Signed-off-by: Pascal Fontain <pascal.fontain@bachmann.info>

This does not look safe unless you check all users of the sram
driver to ensure they are not needed early and they can handle
deferred probing.

      Arnd

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 2/2] misc: sram: Add DMA-BUF Heap exporting of SRAM areas
  2024-04-09 12:06 ` [PATCH v3 2/2] misc: sram: Add DMA-BUF Heap exporting of SRAM areas Pascal FONTAIN
@ 2024-04-09 12:14   ` Greg Kroah-Hartman
  2024-04-19 16:57     ` Christian Gmeiner
  2024-04-09 14:38   ` Andrew Davis
  1 sibling, 1 reply; 8+ messages in thread
From: Greg Kroah-Hartman @ 2024-04-09 12:14 UTC (permalink / raw
  To: Pascal FONTAIN
  Cc: linux-kernel, Derek Kiernan, Dragan Cvetic, Arnd Bergmann,
	Sumit Semwal, Christian König, afd, linux-media, dri-devel,
	linaro-mm-sig

On Tue, Apr 09, 2024 at 02:06:05PM +0200, Pascal FONTAIN wrote:
> From: Andrew Davis <afd@ti.com>
> 
> This new export type exposes to userspace the SRAM area as a DMA-BUF
> Heap,
> this allows for allocations of DMA-BUFs that can be consumed by various
> DMA-BUF supporting devices.
> 
> Signed-off-by: Andrew Davis <afd@ti.com>
> Tested-by: Pascal Fontain <pascal.fontain@bachmann.info>

When sending on a patch from someone else, you too must sign off on it
as per our documenation.  Please read it and understand what you are
agreeing to when you do that for a new version please.

> ---
>  drivers/misc/Kconfig         |   7 +
>  drivers/misc/Makefile        |   1 +
>  drivers/misc/sram-dma-heap.c | 246 +++++++++++++++++++++++++++++++++++
>  drivers/misc/sram.c          |   6 +
>  drivers/misc/sram.h          |  16 +++
>  5 files changed, 276 insertions(+)
>  create mode 100644 drivers/misc/sram-dma-heap.c
> 
> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> index 9e4ad4d61f06..e6674e913168 100644
> --- a/drivers/misc/Kconfig
> +++ b/drivers/misc/Kconfig
> @@ -448,6 +448,13 @@ config SRAM
>  config SRAM_EXEC
>  	bool
>  
> +config SRAM_DMA_HEAP
> +	bool "Export on-chip SRAM pools using DMA-Heaps"
> +	depends on DMABUF_HEAPS && SRAM
> +	help
> +	  This driver allows the export of on-chip SRAM marked as both pool
> +	  and exportable to userspace using the DMA-Heaps interface.

What will use this in userspace?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 2/2] misc: sram: Add DMA-BUF Heap exporting of SRAM areas
  2024-04-09 12:06 ` [PATCH v3 2/2] misc: sram: Add DMA-BUF Heap exporting of SRAM areas Pascal FONTAIN
  2024-04-09 12:14   ` Greg Kroah-Hartman
@ 2024-04-09 14:38   ` Andrew Davis
  1 sibling, 0 replies; 8+ messages in thread
From: Andrew Davis @ 2024-04-09 14:38 UTC (permalink / raw
  To: Pascal FONTAIN, linux-kernel, Derek Kiernan, Dragan Cvetic,
	Arnd Bergmann, Greg Kroah-Hartman, Sumit Semwal,
	Christian König, Robin Murphy
  Cc: linux-media, dri-devel, linaro-mm-sig

On 4/9/24 7:06 AM, Pascal FONTAIN wrote:
> From: Andrew Davis <afd@ti.com>
> 
> This new export type exposes to userspace the SRAM area as a DMA-BUF
> Heap,
> this allows for allocations of DMA-BUFs that can be consumed by various
> DMA-BUF supporting devices.
> 
> Signed-off-by: Andrew Davis <afd@ti.com>
> Tested-by: Pascal Fontain <pascal.fontain@bachmann.info>
> ---

The last time I posted this I got this comment[0], for which I
didn't really have a good response and so haven't reposted this
since then.

Bacically this driver is backed by something other than "normal"
memory. So we really need to be careful here, the page pointer is
really just a cookie to keep track for the real mappings. We might
be able to use something similar to dma_get_sgtable() to hide that,
but under the hood it would still a bit unsafe[1].

Andrew

[0] https://patchwork.kernel.org/project/linux-media/patch/20230713191316.116019-1-afd@ti.com/#25475464
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/dma/mapping.c#n388

>   drivers/misc/Kconfig         |   7 +
>   drivers/misc/Makefile        |   1 +
>   drivers/misc/sram-dma-heap.c | 246 +++++++++++++++++++++++++++++++++++
>   drivers/misc/sram.c          |   6 +
>   drivers/misc/sram.h          |  16 +++
>   5 files changed, 276 insertions(+)
>   create mode 100644 drivers/misc/sram-dma-heap.c
> 
> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> index 9e4ad4d61f06..e6674e913168 100644
> --- a/drivers/misc/Kconfig
> +++ b/drivers/misc/Kconfig
> @@ -448,6 +448,13 @@ config SRAM
>   config SRAM_EXEC
>   	bool
>   
> +config SRAM_DMA_HEAP
> +	bool "Export on-chip SRAM pools using DMA-Heaps"
> +	depends on DMABUF_HEAPS && SRAM
> +	help
> +	  This driver allows the export of on-chip SRAM marked as both pool
> +	  and exportable to userspace using the DMA-Heaps interface.
> +
>   config DW_XDATA_PCIE
>   	depends on PCI
>   	tristate "Synopsys DesignWare xData PCIe driver"
> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
> index cdc6405584e3..63effdde5163 100644
> --- a/drivers/misc/Makefile
> +++ b/drivers/misc/Makefile
> @@ -47,6 +47,7 @@ obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/
>   obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
>   obj-$(CONFIG_SRAM)		+= sram.o
>   obj-$(CONFIG_SRAM_EXEC)		+= sram-exec.o
> +obj-$(CONFIG_SRAM_DMA_HEAP)	+= sram-dma-heap.o
>   obj-$(CONFIG_GENWQE)		+= genwqe/
>   obj-$(CONFIG_ECHO)		+= echo/
>   obj-$(CONFIG_CXL_BASE)		+= cxl/
> diff --git a/drivers/misc/sram-dma-heap.c b/drivers/misc/sram-dma-heap.c
> new file mode 100644
> index 000000000000..e5a0bafe8cb9
> --- /dev/null
> +++ b/drivers/misc/sram-dma-heap.c
> @@ -0,0 +1,246 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * SRAM DMA-Heap userspace exporter
> + *
> + * Copyright (C) 2019-2022 Texas Instruments Incorporated - https://www.ti.com/
> + *	Andrew Davis <afd@ti.com>
> + */
> +
> +#include <linux/dma-mapping.h>
> +#include <linux/err.h>
> +#include <linux/genalloc.h>
> +#include <linux/io.h>
> +#include <linux/mm.h>
> +#include <linux/scatterlist.h>
> +#include <linux/slab.h>
> +#include <linux/dma-buf.h>
> +#include <linux/dma-heap.h>
> +
> +#include "sram.h"
> +
> +struct sram_dma_heap {
> +	struct dma_heap *heap;
> +	struct gen_pool *pool;
> +};
> +
> +struct sram_dma_heap_buffer {
> +	struct gen_pool *pool;
> +	struct list_head attachments;
> +	struct mutex attachments_lock;
> +	unsigned long len;
> +	void *vaddr;
> +	phys_addr_t paddr;
> +};
> +
> +struct dma_heap_attachment {
> +	struct device *dev;
> +	struct sg_table *table;
> +	struct list_head list;
> +};
> +
> +static int dma_heap_attach(struct dma_buf *dmabuf,
> +			   struct dma_buf_attachment *attachment)
> +{
> +	struct sram_dma_heap_buffer *buffer = dmabuf->priv;
> +	struct dma_heap_attachment *a;
> +	struct sg_table *table;
> +
> +	a = kzalloc(sizeof(*a), GFP_KERNEL);
> +	if (!a)
> +		return -ENOMEM;
> +
> +	table = kmalloc(sizeof(*table), GFP_KERNEL);
> +	if (!table) {
> +		kfree(a);
> +		return -ENOMEM;
> +	}
> +	if (sg_alloc_table(table, 1, GFP_KERNEL)) {
> +		kfree(table);
> +		kfree(a);
> +		return -ENOMEM;
> +	}
> +	sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(buffer->paddr)), buffer->len, 0);
> +
> +	a->table = table;
> +	a->dev = attachment->dev;
> +	INIT_LIST_HEAD(&a->list);
> +
> +	attachment->priv = a;
> +
> +	mutex_lock(&buffer->attachments_lock);
> +	list_add(&a->list, &buffer->attachments);
> +	mutex_unlock(&buffer->attachments_lock);
> +
> +	return 0;
> +}
> +
> +static void dma_heap_detatch(struct dma_buf *dmabuf,
> +			     struct dma_buf_attachment *attachment)
> +{
> +	struct sram_dma_heap_buffer *buffer = dmabuf->priv;
> +	struct dma_heap_attachment *a = attachment->priv;
> +
> +	mutex_lock(&buffer->attachments_lock);
> +	list_del(&a->list);
> +	mutex_unlock(&buffer->attachments_lock);
> +
> +	sg_free_table(a->table);
> +	kfree(a->table);
> +	kfree(a);
> +}
> +
> +static struct sg_table *dma_heap_map_dma_buf(struct dma_buf_attachment *attachment,
> +					     enum dma_data_direction direction)
> +{
> +	struct dma_heap_attachment *a = attachment->priv;
> +	struct sg_table *table = a->table;
> +
> +	/*
> +	 * As this heap is backed by uncached SRAM memory we do not need to
> +	 * perform any sync operations on the buffer before allowing device
> +	 * domain access. For this reason we use SKIP_CPU_SYNC and also do
> +	 * not use or provide begin/end_cpu_access() dma-buf functions.
> +	 */
> +	if (!dma_map_sg_attrs(attachment->dev, table->sgl, table->nents,
> +			      direction, DMA_ATTR_SKIP_CPU_SYNC))
> +		return ERR_PTR(-ENOMEM);
> +
> +	return table;
> +}
> +
> +static void dma_heap_unmap_dma_buf(struct dma_buf_attachment *attachment,
> +				   struct sg_table *table,
> +				   enum dma_data_direction direction)
> +{
> +	dma_unmap_sg_attrs(attachment->dev, table->sgl, table->nents,
> +			   direction, DMA_ATTR_SKIP_CPU_SYNC);
> +}
> +
> +static void dma_heap_dma_buf_release(struct dma_buf *dmabuf)
> +{
> +	struct sram_dma_heap_buffer *buffer = dmabuf->priv;
> +
> +	gen_pool_free(buffer->pool, (unsigned long)buffer->vaddr, buffer->len);
> +	kfree(buffer);
> +}
> +
> +static int dma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
> +{
> +	struct sram_dma_heap_buffer *buffer = dmabuf->priv;
> +	int ret;
> +
> +	/* SRAM mappings are not cached */
> +	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
> +
> +	ret = vm_iomap_memory(vma, buffer->paddr, buffer->len);
> +	if (ret)
> +		pr_err("Could not map buffer to userspace\n");
> +
> +	return ret;
> +}
> +
> +static int dma_heap_vmap(struct dma_buf *dmabuf, struct iosys_map *map)
> +{
> +	struct sram_dma_heap_buffer *buffer = dmabuf->priv;
> +
> +	iosys_map_set_vaddr(map, buffer->vaddr);
> +
> +	return 0;
> +}
> +
> +static const struct dma_buf_ops sram_dma_heap_buf_ops = {
> +	.attach = dma_heap_attach,
> +	.detach = dma_heap_detatch,
> +	.map_dma_buf = dma_heap_map_dma_buf,
> +	.unmap_dma_buf = dma_heap_unmap_dma_buf,
> +	.release = dma_heap_dma_buf_release,
> +	.mmap = dma_heap_mmap,
> +	.vmap = dma_heap_vmap,
> +};
> +
> +static struct dma_buf *sram_dma_heap_allocate(struct dma_heap *heap,
> +					      unsigned long len,
> +					      unsigned long fd_flags,
> +					      unsigned long heap_flags)
> +{
> +	struct sram_dma_heap *sram_dma_heap = dma_heap_get_drvdata(heap);
> +	struct sram_dma_heap_buffer *buffer;
> +
> +	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
> +	struct dma_buf *dmabuf;
> +	int ret;
> +
> +	buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
> +	if (!buffer)
> +		return ERR_PTR(-ENOMEM);
> +	buffer->pool = sram_dma_heap->pool;
> +	INIT_LIST_HEAD(&buffer->attachments);
> +	mutex_init(&buffer->attachments_lock);
> +	buffer->len = len;
> +
> +	buffer->vaddr = (void *)gen_pool_alloc(buffer->pool, buffer->len);
> +	if (!buffer->vaddr) {
> +		ret = -ENOMEM;
> +		goto free_buffer;
> +	}
> +
> +	buffer->paddr = gen_pool_virt_to_phys(buffer->pool, (unsigned long)buffer->vaddr);
> +	if (buffer->paddr == -1) {
> +		ret = -ENOMEM;
> +		goto free_pool;
> +	}
> +
> +	/* create the dmabuf */
> +	exp_info.exp_name = dma_heap_get_name(heap);
> +	exp_info.ops = &sram_dma_heap_buf_ops;
> +	exp_info.size = buffer->len;
> +	exp_info.flags = fd_flags;
> +	exp_info.priv = buffer;
> +	dmabuf = dma_buf_export(&exp_info);
> +	if (IS_ERR(dmabuf)) {
> +		ret = PTR_ERR(dmabuf);
> +		goto free_pool;
> +	}
> +
> +	return dmabuf;
> +
> +free_pool:
> +	gen_pool_free(buffer->pool, (unsigned long)buffer->vaddr, buffer->len);
> +free_buffer:
> +	kfree(buffer);
> +
> +	return ERR_PTR(ret);
> +}
> +
> +static struct dma_heap_ops sram_dma_heap_ops = {
> +	.allocate = sram_dma_heap_allocate,
> +};
> +
> +int sram_add_dma_heap(struct sram_dev *sram,
> +		      struct sram_reserve *block,
> +		      phys_addr_t start,
> +		      struct sram_partition *part)
> +{
> +	struct sram_dma_heap *sram_dma_heap;
> +	struct dma_heap_export_info exp_info;
> +
> +	dev_info(sram->dev, "Exporting SRAM Heap '%s'\n", block->label);
> +
> +	sram_dma_heap = kzalloc(sizeof(*sram_dma_heap), GFP_KERNEL);
> +	if (!sram_dma_heap)
> +		return -ENOMEM;
> +	sram_dma_heap->pool = part->pool;
> +
> +	exp_info.name = kasprintf(GFP_KERNEL, "sram_%s", block->label);
> +	exp_info.ops = &sram_dma_heap_ops;
> +	exp_info.priv = sram_dma_heap;
> +	sram_dma_heap->heap = dma_heap_add(&exp_info);
> +	if (IS_ERR(sram_dma_heap->heap)) {
> +		int ret = PTR_ERR(sram_dma_heap->heap);
> +
> +		kfree(sram_dma_heap);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
> index 632f90d9bcea..643c77598beb 100644
> --- a/drivers/misc/sram.c
> +++ b/drivers/misc/sram.c
> @@ -120,6 +120,12 @@ static int sram_add_partition(struct sram_dev *sram, struct sram_reserve *block,
>   		ret = sram_add_pool(sram, block, start, part);
>   		if (ret)
>   			return ret;
> +
> +		if (block->export) {
> +			ret = sram_add_dma_heap(sram, block, start, part);
> +			if (ret)
> +				return ret;
> +		}
>   	}
>   	if (block->export) {
>   		ret = sram_add_export(sram, block, start, part);
> diff --git a/drivers/misc/sram.h b/drivers/misc/sram.h
> index 397205b8bf6f..062bdd25fa06 100644
> --- a/drivers/misc/sram.h
> +++ b/drivers/misc/sram.h
> @@ -60,4 +60,20 @@ static inline int sram_add_protect_exec(struct sram_partition *part)
>   	return -ENODEV;
>   }
>   #endif /* CONFIG_SRAM_EXEC */
> +
> +#ifdef CONFIG_SRAM_DMA_HEAP
> +int sram_add_dma_heap(struct sram_dev *sram,
> +		      struct sram_reserve *block,
> +		      phys_addr_t start,
> +		      struct sram_partition *part);
> +#else
> +static inline int sram_add_dma_heap(struct sram_dev *sram,
> +				    struct sram_reserve *block,
> +				    phys_addr_t start,
> +				    struct sram_partition *part)
> +{
> +	return 0;
> +}
> +#endif /* CONFIG_SRAM_DMA_HEAP */
> +
>   #endif /* __SRAM_H */

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 2/2] misc: sram: Add DMA-BUF Heap exporting of SRAM areas
  2024-04-09 12:14   ` Greg Kroah-Hartman
@ 2024-04-19 16:57     ` Christian Gmeiner
  2024-04-20  6:36       ` Greg Kroah-Hartman
  0 siblings, 1 reply; 8+ messages in thread
From: Christian Gmeiner @ 2024-04-19 16:57 UTC (permalink / raw
  To: Greg Kroah-Hartman
  Cc: Pascal FONTAIN, linux-kernel, Derek Kiernan, Dragan Cvetic,
	Arnd Bergmann, Sumit Semwal, Christian König, afd,
	linux-media, dri-devel, linaro-mm-sig

Am Di., 9. Apr. 2024 um 14:14 Uhr schrieb Greg Kroah-Hartman
<gregkh@linuxfoundation.org>:
>
> On Tue, Apr 09, 2024 at 02:06:05PM +0200, Pascal FONTAIN wrote:
> > From: Andrew Davis <afd@ti.com>
> >
> > This new export type exposes to userspace the SRAM area as a DMA-BUF
> > Heap,
> > this allows for allocations of DMA-BUFs that can be consumed by various
> > DMA-BUF supporting devices.
> >
> > Signed-off-by: Andrew Davis <afd@ti.com>
> > Tested-by: Pascal Fontain <pascal.fontain@bachmann.info>
>
> When sending on a patch from someone else, you too must sign off on it
> as per our documenation.  Please read it and understand what you are
> agreeing to when you do that for a new version please.
>
> > ---
> >  drivers/misc/Kconfig         |   7 +
> >  drivers/misc/Makefile        |   1 +
> >  drivers/misc/sram-dma-heap.c | 246 +++++++++++++++++++++++++++++++++++
> >  drivers/misc/sram.c          |   6 +
> >  drivers/misc/sram.h          |  16 +++
> >  5 files changed, 276 insertions(+)
> >  create mode 100644 drivers/misc/sram-dma-heap.c
> >
> > diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> > index 9e4ad4d61f06..e6674e913168 100644
> > --- a/drivers/misc/Kconfig
> > +++ b/drivers/misc/Kconfig
> > @@ -448,6 +448,13 @@ config SRAM
> >  config SRAM_EXEC
> >       bool
> >
> > +config SRAM_DMA_HEAP
> > +     bool "Export on-chip SRAM pools using DMA-Heaps"
> > +     depends on DMABUF_HEAPS && SRAM
> > +     help
> > +       This driver allows the export of on-chip SRAM marked as both pool
> > +       and exportable to userspace using the DMA-Heaps interface.
>
> What will use this in userspace?
>

I could imagine a way it might be used.

Imagine a SoC like TI's AM64x series, where some cores (A53) run Linux
and others (R5F) are managed by remoteproc to
execute a RTOS. When it comes to efficiently exchanging large data
sets, the conventional method involves using rpmsg,
which has limitations due to message size and could potentially slow
down data transfer. However, an alternative
approach could be to allocate a sizable chunk of SRAM memory in
userspace. By utilizing memcpy() to copy data into
this memory, followed by a single rpmsg signal to notify the RTOS that
the data is ready, we can leverage the faster access
speed of SRAM compared to DDR from the remoteproc.

-- 
greets
--
Christian Gmeiner, MSc

https://christian-gmeiner.info/privacypolicy

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 2/2] misc: sram: Add DMA-BUF Heap exporting of SRAM areas
  2024-04-19 16:57     ` Christian Gmeiner
@ 2024-04-20  6:36       ` Greg Kroah-Hartman
  0 siblings, 0 replies; 8+ messages in thread
From: Greg Kroah-Hartman @ 2024-04-20  6:36 UTC (permalink / raw
  To: Christian Gmeiner
  Cc: Pascal FONTAIN, linux-kernel, Derek Kiernan, Dragan Cvetic,
	Arnd Bergmann, Sumit Semwal, Christian König, afd,
	linux-media, dri-devel, linaro-mm-sig

On Fri, Apr 19, 2024 at 06:57:47PM +0200, Christian Gmeiner wrote:
> Am Di., 9. Apr. 2024 um 14:14 Uhr schrieb Greg Kroah-Hartman
> <gregkh@linuxfoundation.org>:
> >
> > On Tue, Apr 09, 2024 at 02:06:05PM +0200, Pascal FONTAIN wrote:
> > > From: Andrew Davis <afd@ti.com>
> > >
> > > This new export type exposes to userspace the SRAM area as a DMA-BUF
> > > Heap,
> > > this allows for allocations of DMA-BUFs that can be consumed by various
> > > DMA-BUF supporting devices.
> > >
> > > Signed-off-by: Andrew Davis <afd@ti.com>
> > > Tested-by: Pascal Fontain <pascal.fontain@bachmann.info>
> >
> > When sending on a patch from someone else, you too must sign off on it
> > as per our documenation.  Please read it and understand what you are
> > agreeing to when you do that for a new version please.
> >
> > > ---
> > >  drivers/misc/Kconfig         |   7 +
> > >  drivers/misc/Makefile        |   1 +
> > >  drivers/misc/sram-dma-heap.c | 246 +++++++++++++++++++++++++++++++++++
> > >  drivers/misc/sram.c          |   6 +
> > >  drivers/misc/sram.h          |  16 +++
> > >  5 files changed, 276 insertions(+)
> > >  create mode 100644 drivers/misc/sram-dma-heap.c
> > >
> > > diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> > > index 9e4ad4d61f06..e6674e913168 100644
> > > --- a/drivers/misc/Kconfig
> > > +++ b/drivers/misc/Kconfig
> > > @@ -448,6 +448,13 @@ config SRAM
> > >  config SRAM_EXEC
> > >       bool
> > >
> > > +config SRAM_DMA_HEAP
> > > +     bool "Export on-chip SRAM pools using DMA-Heaps"
> > > +     depends on DMABUF_HEAPS && SRAM
> > > +     help
> > > +       This driver allows the export of on-chip SRAM marked as both pool
> > > +       and exportable to userspace using the DMA-Heaps interface.
> >
> > What will use this in userspace?
> >
> 
> I could imagine a way it might be used.

This implies it is not needed because no one actually has actually used
it for anything, so why make this change?

> Imagine a SoC like TI's AM64x series, where some cores (A53) run Linux
> and others (R5F) are managed by remoteproc to
> execute a RTOS. When it comes to efficiently exchanging large data
> sets, the conventional method involves using rpmsg,
> which has limitations due to message size and could potentially slow
> down data transfer. However, an alternative
> approach could be to allocate a sizable chunk of SRAM memory in
> userspace. By utilizing memcpy() to copy data into
> this memory, followed by a single rpmsg signal to notify the RTOS that
> the data is ready, we can leverage the faster access
> speed of SRAM compared to DDR from the remoteproc.

Why is virtio not used instead?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2024-04-20  6:36 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-04-09 12:06 [PATCH v3 0/2] misc: sram: Add DMA-BUF Heap exporting of SRAM areas Pascal FONTAIN
2024-04-09 12:06 ` [PATCH v3 1/2] misc: sram: Move probe of sram subsystem Pascal FONTAIN
2024-04-09 12:10   ` Arnd Bergmann
2024-04-09 12:06 ` [PATCH v3 2/2] misc: sram: Add DMA-BUF Heap exporting of SRAM areas Pascal FONTAIN
2024-04-09 12:14   ` Greg Kroah-Hartman
2024-04-19 16:57     ` Christian Gmeiner
2024-04-20  6:36       ` Greg Kroah-Hartman
2024-04-09 14:38   ` Andrew Davis

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.