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
---
Changes from v1:
- Use existing DT flags, if both pool(device usable) and export(userspace
usable) properties are in the SRAM node then export as a DMA-BUF Heap
- Rebase on 6.3-rc5
drivers/misc/Kconfig | 7 +
drivers/misc/Makefile| 1 +
drivers/misc/sram-dma-heap.c | 245 +++
drivers/misc/sram.c | 6 +
drivers/misc/sram.h | 16 +++
5 files changed, 275 insertions(+)
create mode 100644 drivers/misc/sram-dma-heap.c
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 433aa41977852..8b4c111a6493b 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 56de43943cd51..bbdc64aa8af1a 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 0..c511f4ac1280e
--- /dev/null
+++ b/drivers/misc/sram-dma-heap.c
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SRAM DMA-Heap userspace exporter
+ *
+ * Copyright (C) 2019-2022 Texas Instruments Incorporated - https://www.ti.com/
+ * Andrew Davis
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#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(>list);
+
+ attachment->priv = a;
+
+ mutex_lock(>attachments_lock);
+ list_add(>list, >attachments);
+ mutex_unlock(>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(>attachments_lock);
+ list_del(>list);
+ mutex_unlock(>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))
+