brcm2708: update to latest patches from RPi foundation
[openwrt/staging/chunkeey.git] / target / linux / brcm2708 / patches-4.19 / 950-0598-staging-vcsm-cma-Rework-to-use-dma-APIs-not-CMA.patch
diff --git a/target/linux/brcm2708/patches-4.19/950-0598-staging-vcsm-cma-Rework-to-use-dma-APIs-not-CMA.patch b/target/linux/brcm2708/patches-4.19/950-0598-staging-vcsm-cma-Rework-to-use-dma-APIs-not-CMA.patch
new file mode 100644 (file)
index 0000000..e8896c0
--- /dev/null
@@ -0,0 +1,758 @@
+From e4cb138abe457a6ab9b98458660a1c8e548fab7f Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 1 Jul 2019 11:57:25 +0100
+Subject: [PATCH] staging: vcsm-cma: Rework to use dma APIs, not CMA
+
+Due to a misunderstanding of the DMA mapping APIs, I made
+the wrong decision on how to implement this.
+
+Rework to use dma_alloc_coherent instead of the CMA
+API. This also allows it to be built as a module easily.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vc-sm-cma/Kconfig   |   4 +-
+ .../staging/vc04_services/vc-sm-cma/Makefile  |   2 +-
+ .../staging/vc04_services/vc-sm-cma/vc_sm.c   | 291 ++++++++++--------
+ .../staging/vc04_services/vc-sm-cma/vc_sm.h   |  13 +-
+ .../vc04_services/vc-sm-cma/vc_sm_cma.c       |  98 ------
+ .../vc04_services/vc-sm-cma/vc_sm_cma.h       |  39 ---
+ 6 files changed, 168 insertions(+), 279 deletions(-)
+ delete mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
+ delete mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/Kconfig
++++ b/drivers/staging/vc04_services/vc-sm-cma/Kconfig
+@@ -1,6 +1,6 @@
+ config BCM_VC_SM_CMA
+-      bool "VideoCore Shared Memory (CMA) driver"
+-      depends on BCM2835_VCHIQ && DMA_CMA
++      tristate "VideoCore Shared Memory (CMA) driver"
++      depends on BCM2835_VCHIQ
+       select RBTREE
+       select DMA_SHARED_BUFFER
+       help
+--- a/drivers/staging/vc04_services/vc-sm-cma/Makefile
++++ b/drivers/staging/vc04_services/vc-sm-cma/Makefile
+@@ -3,6 +3,6 @@ ccflags-y += -Idrivers/staging/vc04_serv
+ ccflags-y += -D__VCCOREVER__=0
+ vc-sm-cma-$(CONFIG_BCM_VC_SM_CMA) := \
+-      vc_sm.o vc_sm_cma_vchi.o vc_sm_cma.o
++      vc_sm.o vc_sm_cma_vchi.o
+ obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma.o
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -6,8 +6,8 @@
+  * Dave Stevenson <dave.stevenson@raspberrypi.org>
+  *
+  * Based on vmcs_sm driver from Broadcom Corporation for some API,
+- * and taking some code for CMA/dmabuf handling from the Android Ion
+- * driver (Google/Linaro).
++ * and taking some code for buffer allocation and dmabuf handling from
++ * videobuf2.
+  *
+  *
+  * This driver has 3 main uses:
+@@ -52,7 +52,6 @@
+ #include "vc_sm_cma_vchi.h"
+ #include "vc_sm.h"
+-#include "vc_sm_cma.h"
+ #include "vc_sm_knl.h"
+ #include <linux/broadcom/vc_sm_cma_ioctl.h>
+@@ -89,7 +88,6 @@ struct sm_state_t {
+       struct miscdevice misc_dev;
+       struct sm_instance *sm_handle;  /* Handle for videocore service. */
+-      struct cma *cma_heap;
+       spinlock_t kernelid_map_lock;   /* Spinlock protecting kernelid_map */
+       struct idr kernelid_map;
+@@ -110,8 +108,9 @@ struct sm_state_t {
+ struct vc_sm_dma_buf_attachment {
+       struct device *dev;
+-      struct sg_table *table;
++      struct sg_table sg_table;
+       struct list_head list;
++      enum dma_data_direction dma_dir;
+ };
+ /* ---- Private Variables ----------------------------------------------- */
+@@ -202,9 +201,10 @@ static int vc_sm_cma_global_state_show(s
+                                          resource->import.attach);
+                               seq_printf(s, "           SGT          %p\n",
+                                          resource->import.sgt);
++                      } else {
++                              seq_printf(s, "           SGT          %p\n",
++                                         resource->alloc.sg_table);
+                       }
+-                      seq_printf(s, "           SG_TABLE     %p\n",
+-                                 resource->sg_table);
+                       seq_printf(s, "           DMA_ADDR     %pad\n",
+                                  &resource->dma_addr);
+                       seq_printf(s, "           VC_HANDLE     %08x\n",
+@@ -296,8 +296,9 @@ static void vc_sm_vpu_free(struct vc_sm_
+  */
+ static void vc_sm_release_resource(struct vc_sm_buffer *buffer)
+ {
+-      pr_debug("[%s]: buffer %p (name %s, size %zu)\n",
+-               __func__, buffer, buffer->name, buffer->size);
++      pr_debug("[%s]: buffer %p (name %s, size %zu), imported %u\n",
++               __func__, buffer, buffer->name, buffer->size,
++               buffer->imported);
+       if (buffer->vc_handle) {
+               /* We've sent the unmap request but not had the response. */
+@@ -313,8 +314,6 @@ static void vc_sm_release_resource(struc
+       /* Release the allocation (whether imported dmabuf or CMA allocation) */
+       if (buffer->imported) {
+-              pr_debug("%s: Release imported dmabuf %p\n", __func__,
+-                       buffer->import.dma_buf);
+               if (buffer->import.dma_buf)
+                       dma_buf_put(buffer->import.dma_buf);
+               else
+@@ -322,16 +321,8 @@ static void vc_sm_release_resource(struc
+                              __func__, buffer);
+               buffer->import.dma_buf = NULL;
+       } else {
+-              if (buffer->sg_table) {
+-                      /* Our own allocation that we need to dma_unmap_sg */
+-                      dma_unmap_sg(&sm_state->pdev->dev,
+-                                   buffer->sg_table->sgl,
+-                                   buffer->sg_table->nents,
+-                                   DMA_BIDIRECTIONAL);
+-              }
+-              pr_debug("%s: Release our allocation\n", __func__);
+-              vc_sm_cma_buffer_free(&buffer->alloc);
+-              pr_debug("%s: Release our allocation - done\n", __func__);
++              dma_free_coherent(&sm_state->pdev->dev, buffer->size,
++                                buffer->cookie, buffer->dma_addr);
+       }
+@@ -371,38 +362,6 @@ static struct vc_sm_privdata_t *vc_sm_cm
+       return file_data;
+ }
+-static struct sg_table *dup_sg_table(struct sg_table *table)
+-{
+-      struct sg_table *new_table;
+-      int ret, i;
+-      struct scatterlist *sg, *new_sg;
+-
+-      new_table = kzalloc(sizeof(*new_table), GFP_KERNEL);
+-      if (!new_table)
+-              return ERR_PTR(-ENOMEM);
+-
+-      ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL);
+-      if (ret) {
+-              kfree(new_table);
+-              return ERR_PTR(ret);
+-      }
+-
+-      new_sg = new_table->sgl;
+-      for_each_sg(table->sgl, sg, table->nents, i) {
+-              memcpy(new_sg, sg, sizeof(*sg));
+-              sg->dma_address = 0;
+-              new_sg = sg_next(new_sg);
+-      }
+-
+-      return new_table;
+-}
+-
+-static void free_duped_table(struct sg_table *table)
+-{
+-      sg_free_table(table);
+-      kfree(table);
+-}
+-
+ /* Dma buf operations for use with our own allocations */
+ static int vc_sm_dma_buf_attach(struct dma_buf *dmabuf,
+@@ -410,28 +369,45 @@ static int vc_sm_dma_buf_attach(struct d
+ {
+       struct vc_sm_dma_buf_attachment *a;
+-      struct sg_table *table;
++      struct sg_table *sgt;
+       struct vc_sm_buffer *buf = dmabuf->priv;
++      struct scatterlist *rd, *wr;
++      int ret, i;
+       a = kzalloc(sizeof(*a), GFP_KERNEL);
+       if (!a)
+               return -ENOMEM;
+-      table = dup_sg_table(buf->sg_table);
+-      if (IS_ERR(table)) {
++      pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
++
++      mutex_lock(&buf->lock);
++
++      INIT_LIST_HEAD(&a->list);
++
++      sgt = &a->sg_table;
++
++      /* Copy the buf->base_sgt scatter list to the attachment, as we can't
++       * map the same scatter list to multiple attachments at the same time.
++       */
++      ret = sg_alloc_table(sgt, buf->alloc.sg_table->orig_nents, GFP_KERNEL);
++      if (ret) {
+               kfree(a);
+-              return PTR_ERR(table);
++              return -ENOMEM;
+       }
+-      a->table = table;
+-      INIT_LIST_HEAD(&a->list);
++      rd = buf->alloc.sg_table->sgl;
++      wr = sgt->sgl;
++      for (i = 0; i < sgt->orig_nents; ++i) {
++              sg_set_page(wr, sg_page(rd), rd->length, rd->offset);
++              rd = sg_next(rd);
++              wr = sg_next(wr);
++      }
++      a->dma_dir = DMA_NONE;
+       attachment->priv = a;
+-      mutex_lock(&buf->lock);
+       list_add(&a->list, &buf->attachments);
+       mutex_unlock(&buf->lock);
+-      pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
+       return 0;
+ }
+@@ -441,9 +417,20 @@ static void vc_sm_dma_buf_detach(struct
+ {
+       struct vc_sm_dma_buf_attachment *a = attachment->priv;
+       struct vc_sm_buffer *buf = dmabuf->priv;
++      struct sg_table *sgt;
+       pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
+-      free_duped_table(a->table);
++      if (!a)
++              return;
++
++      sgt = &a->sg_table;
++
++      /* release the scatterlist cache */
++      if (a->dma_dir != DMA_NONE)
++              dma_unmap_sg(attachment->dev, sgt->sgl, sgt->orig_nents,
++                           a->dma_dir);
++      sg_free_table(sgt);
++
+       mutex_lock(&buf->lock);
+       list_del(&a->list);
+       mutex_unlock(&buf->lock);
+@@ -455,13 +442,38 @@ static struct sg_table *vc_sm_map_dma_bu
+                                         enum dma_data_direction direction)
+ {
+       struct vc_sm_dma_buf_attachment *a = attachment->priv;
++      /* stealing dmabuf mutex to serialize map/unmap operations */
++      struct mutex *lock = &attachment->dmabuf->lock;
+       struct sg_table *table;
+-      table = a->table;
++      mutex_lock(lock);
++      pr_debug("%s attachment %p\n", __func__, attachment);
++      table = &a->sg_table;
++
++      /* return previously mapped sg table */
++      if (a->dma_dir == direction) {
++              mutex_unlock(lock);
++              return table;
++      }
++
++      /* release any previous cache */
++      if (a->dma_dir != DMA_NONE) {
++              dma_unmap_sg(attachment->dev, table->sgl, table->orig_nents,
++                           a->dma_dir);
++              a->dma_dir = DMA_NONE;
++      }
++
++      /* mapping to the client with new direction */
++      table->nents = dma_map_sg(attachment->dev, table->sgl,
++                                table->orig_nents, direction);
++      if (!table->nents) {
++              pr_err("failed to map scatterlist\n");
++              mutex_unlock(lock);
++              return ERR_PTR(-EIO);
++      }
+-      if (!dma_map_sg(attachment->dev, table->sgl, table->nents,
+-                      direction))
+-              return ERR_PTR(-ENOMEM);
++      a->dma_dir = direction;
++      mutex_unlock(lock);
+       pr_debug("%s attachment %p\n", __func__, attachment);
+       return table;
+@@ -478,41 +490,26 @@ static void vc_sm_unmap_dma_buf(struct d
+ static int vc_sm_dmabuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
+ {
+       struct vc_sm_buffer *buf = dmabuf->priv;
+-      struct sg_table *table = buf->sg_table;
+-      unsigned long addr = vma->vm_start;
+-      unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
+-      struct scatterlist *sg;
+-      int i;
+-      int ret = 0;
++      int ret;
+       pr_debug("%s dmabuf %p, buf %p, vm_start %08lX\n", __func__, dmabuf,
+-               buf, addr);
++               buf, vma->vm_start);
+       mutex_lock(&buf->lock);
+       /* now map it to userspace */
+-      for_each_sg(table->sgl, sg, table->nents, i) {
+-              struct page *page = sg_page(sg);
+-              unsigned long remainder = vma->vm_end - addr;
+-              unsigned long len = sg->length;
++      vma->vm_pgoff = 0;
+-              if (offset >= sg->length) {
+-                      offset -= sg->length;
+-                      continue;
+-              } else if (offset) {
+-                      page += offset / PAGE_SIZE;
+-                      len = sg->length - offset;
+-                      offset = 0;
+-              }
+-              len = min(len, remainder);
+-              ret = remap_pfn_range(vma, addr, page_to_pfn(page), len,
+-                                    vma->vm_page_prot);
+-              if (ret)
+-                      break;
+-              addr += len;
+-              if (addr >= vma->vm_end)
+-                      break;
++      ret = dma_mmap_coherent(&sm_state->pdev->dev, vma, buf->cookie,
++                              buf->dma_addr, buf->size);
++
++      if (ret) {
++              pr_err("Remapping memory failed, error: %d\n", ret);
++              return ret;
+       }
++
++      vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
++
+       mutex_unlock(&buf->lock);
+       if (ret)
+@@ -570,8 +567,8 @@ static int vc_sm_dma_buf_begin_cpu_acces
+       mutex_lock(&buf->lock);
+       list_for_each_entry(a, &buf->attachments, list) {
+-              dma_sync_sg_for_cpu(a->dev, a->table->sgl, a->table->nents,
+-                                  direction);
++              dma_sync_sg_for_cpu(a->dev, a->sg_table.sgl,
++                                  a->sg_table.nents, direction);
+       }
+       mutex_unlock(&buf->lock);
+@@ -593,8 +590,8 @@ static int vc_sm_dma_buf_end_cpu_access(
+       mutex_lock(&buf->lock);
+       list_for_each_entry(a, &buf->attachments, list) {
+-              dma_sync_sg_for_device(a->dev, a->table->sgl, a->table->nents,
+-                                     direction);
++              dma_sync_sg_for_device(a->dev, a->sg_table.sgl,
++                                     a->sg_table.nents, direction);
+       }
+       mutex_unlock(&buf->lock);
+@@ -625,7 +622,9 @@ static const struct dma_buf_ops dma_buf_
+       .map = vc_sm_dma_buf_kmap,
+       .unmap = vc_sm_dma_buf_kunmap,
+ };
++
+ /* Dma_buf operations for chaining through to an imported dma_buf */
++
+ static
+ int vc_sm_import_dma_buf_attach(struct dma_buf *dmabuf,
+                               struct dma_buf_attachment *attachment)
+@@ -819,7 +818,7 @@ vc_sm_cma_import_dmabuf_internal(struct
+       import.type = VC_SM_ALLOC_NON_CACHED;
+       dma_addr = sg_dma_address(sgt->sgl);
+-      import.addr = (uint32_t)dma_addr;
++      import.addr = (u32)dma_addr;
+       if ((import.addr & 0xC0000000) != 0xC0000000) {
+               pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
+                      __func__, &dma_addr);
+@@ -911,11 +910,12 @@ error:
+       return ret;
+ }
+-static int vc_sm_cma_vpu_alloc(u32 size, uint32_t align, const char *name,
++static int vc_sm_cma_vpu_alloc(u32 size, u32 align, const char *name,
+                              u32 mem_handle, struct vc_sm_buffer **ret_buffer)
+ {
+       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+       struct vc_sm_buffer *buffer = NULL;
++      struct sg_table *sgt;
+       int aligned_size;
+       int ret = 0;
+@@ -938,23 +938,34 @@ static int vc_sm_cma_vpu_alloc(u32 size,
+        */
+       mutex_lock(&buffer->lock);
+-      if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
+-                                    aligned_size)) {
+-              pr_err("[%s]: cma alloc of %d bytes failed\n",
++      buffer->cookie = dma_alloc_coherent(&sm_state->pdev->dev,
++                                          aligned_size, &buffer->dma_addr,
++                                          GFP_KERNEL);
++      if (!buffer->cookie) {
++              pr_err("[%s]: dma_alloc_coherent alloc of %d bytes failed\n",
+                      __func__, aligned_size);
+               ret = -ENOMEM;
+               goto error;
+       }
+-      buffer->sg_table = buffer->alloc.sg_table;
+-      pr_debug("[%s]: cma alloc of %d bytes success\n",
++      pr_debug("[%s]: alloc of %d bytes success\n",
+                __func__, aligned_size);
+-      if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
+-                     buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
+-              pr_err("[%s]: dma_map_sg failed\n", __func__);
++      sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
++      if (!sgt) {
++              ret = -ENOMEM;
++              goto error;
++      }
++
++      ret = dma_get_sgtable(&sm_state->pdev->dev, sgt, buffer->cookie,
++                            buffer->dma_addr, buffer->size);
++      if (ret < 0) {
++              pr_err("failed to get scatterlist from DMA API\n");
++              kfree(sgt);
++              ret = -ENOMEM;
+               goto error;
+       }
++      buffer->alloc.sg_table = sgt;
+       INIT_LIST_HEAD(&buffer->attachments);
+@@ -971,10 +982,10 @@ static int vc_sm_cma_vpu_alloc(u32 size,
+               ret = PTR_ERR(buffer->dma_buf);
+               goto error;
+       }
+-      buffer->dma_addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
++      buffer->dma_addr = (u32)sg_dma_address(buffer->alloc.sg_table->sgl);
+       if ((buffer->dma_addr & 0xC0000000) != 0xC0000000) {
+-              pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
+-                     __func__, &buffer->dma_addr);
++              pr_warn_once("%s: Expecting an uncached alias for dma_addr %pad\n",
++                           __func__, &buffer->dma_addr);
+               buffer->dma_addr |= 0xC0000000;
+       }
+       buffer->private = sm_state->vpu_allocs;
+@@ -1145,6 +1156,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+       struct vc_sm_import import = { 0 };
+       struct vc_sm_import_result result = { 0 };
+       struct dma_buf *dmabuf = NULL;
++      struct sg_table *sgt;
+       int aligned_size;
+       int ret = 0;
+       int status;
+@@ -1162,18 +1174,13 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+               goto error;
+       }
+-      if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
+-                                    aligned_size)) {
+-              pr_err("[%s]: cma alloc of %d bytes failed\n",
++      buffer->cookie = dma_alloc_coherent(&sm_state->pdev->dev,
++                                          aligned_size,
++                                          &buffer->dma_addr,
++                                          GFP_KERNEL);
++      if (!buffer->cookie) {
++              pr_err("[%s]: dma_alloc_coherent alloc of %d bytes failed\n",
+                      __func__, aligned_size);
+-              kfree(buffer);
+-              return -ENOMEM;
+-      }
+-      buffer->sg_table = buffer->alloc.sg_table;
+-
+-      if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
+-                     buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
+-              pr_err("[%s]: dma_map_sg failed\n", __func__);
+               ret = -ENOMEM;
+               goto error;
+       }
+@@ -1204,7 +1211,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+       }
+       buffer->dma_buf = dmabuf;
+-      import.addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
++      import.addr = buffer->dma_addr;
+       import.size = aligned_size;
+       import.kernel_id = get_kernel_id(buffer);
+@@ -1229,10 +1236,25 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+       buffer->private = private;
+       buffer->vc_handle = result.res_handle;
+       buffer->size = import.size;
+-      buffer->dma_addr = import.addr;
+       buffer->vpu_state = VPU_MAPPED;
+       buffer->kernel_id = import.kernel_id;
+-      //buffer->res_cached = ioparam->cached;
++
++      sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
++      if (!sgt) {
++              ret = -ENOMEM;
++              goto error;
++      }
++
++      ret = dma_get_sgtable(&sm_state->pdev->dev, sgt, buffer->cookie,
++                            buffer->dma_addr, buffer->size);
++      if (ret < 0) {
++              /* FIXME: error handling */
++              pr_err("failed to get scatterlist from DMA API\n");
++              kfree(sgt);
++              ret = -ENOMEM;
++              goto error;
++      }
++      buffer->alloc.sg_table = sgt;
+       fd = dma_buf_fd(dmabuf, O_CLOEXEC);
+       if (fd < 0)
+@@ -1250,11 +1272,19 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+       return 0;
+ error:
+-      if (buffer) {
+-              pr_err("[%s]: something failed - cleanup. ret %d\n", __func__,
+-                     ret);
++      pr_err("[%s]: something failed - cleanup. ret %d\n", __func__, ret);
++      if (dmabuf) {
++              /* dmabuf has been exported, therefore allow dmabuf cleanup to
++               * deal with this
++               */
+               dma_buf_put(dmabuf);
++      } else {
++              /* No dmabuf, therefore just free the buffer here */
++              if (buffer->cookie)
++                      dma_free_coherent(&sm_state->pdev->dev, buffer->size,
++                                        buffer->cookie, buffer->dma_addr);
++              kfree(buffer);
+       }
+       return ret;
+ }
+@@ -1527,13 +1557,6 @@ static void vc_sm_connected_init(void)
+       pr_info("[%s]: start\n", __func__);
+-      vc_sm_cma_add_heaps(&sm_state->cma_heap);
+-      if (!sm_state->cma_heap) {
+-              pr_err("[%s]: failed to initialise CMA heap\n",
+-                     __func__);
+-              return;
+-      }
+-
+       /*
+        * Initialize and create a VCHI connection for the shared memory service
+        * running on videocore.
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
+@@ -21,8 +21,6 @@
+ #include <linux/types.h>
+ #include <linux/miscdevice.h>
+-#include "vc_sm_cma.h"
+-
+ #define VC_SM_MAX_NAME_LEN 32
+ enum vc_sm_vpu_mapping_state {
+@@ -31,6 +29,12 @@ enum vc_sm_vpu_mapping_state {
+       VPU_UNMAPPING
+ };
++struct vc_sm_alloc_data {
++      unsigned long num_pages;
++      void *priv_virt;
++      struct sg_table *sg_table;
++};
++
+ struct vc_sm_imported {
+       struct dma_buf *dma_buf;
+       struct dma_buf_attachment *attach;
+@@ -56,8 +60,6 @@ struct vc_sm_buffer {
+       int in_use:1;   /* Kernel is still using this resource */
+       int imported:1; /* Imported dmabuf */
+-      struct sg_table *sg_table;
+-
+       enum vc_sm_vpu_mapping_state vpu_state;
+       u32 vc_handle;  /* VideoCore handle for this buffer */
+       int vpu_allocated;      /*
+@@ -69,11 +71,12 @@ struct vc_sm_buffer {
+       /* DMABUF related fields */
+       struct dma_buf *dma_buf;
+       dma_addr_t dma_addr;
++      void *cookie;
+       struct vc_sm_privdata_t *private;
+       union {
+-              struct vc_sm_cma_alloc_data alloc;
++              struct vc_sm_alloc_data alloc;
+               struct vc_sm_imported import;
+       };
+ };
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
++++ /dev/null
+@@ -1,98 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-/*
+- * VideoCore Shared Memory CMA allocator
+- *
+- * Copyright: 2018, Raspberry Pi (Trading) Ltd
+- *
+- * Based on the Android ION allocator
+- * Copyright (C) Linaro 2012
+- * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
+- *
+- */
+-
+-#include <linux/slab.h>
+-#include <linux/errno.h>
+-#include <linux/err.h>
+-#include <linux/cma.h>
+-#include <linux/scatterlist.h>
+-
+-#include "vc_sm_cma.h"
+-
+-/* CMA heap operations functions */
+-int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
+-                            struct vc_sm_cma_alloc_data *buffer,
+-                            unsigned long len)
+-{
+-      /* len should already be page aligned */
+-      unsigned long num_pages = len / PAGE_SIZE;
+-      struct sg_table *table;
+-      struct page *pages;
+-      int ret;
+-
+-      pages = cma_alloc(cma_heap, num_pages, 0, GFP_KERNEL);
+-      if (!pages)
+-              return -ENOMEM;
+-
+-      table = kmalloc(sizeof(*table), GFP_KERNEL);
+-      if (!table)
+-              goto err;
+-
+-      ret = sg_alloc_table(table, 1, GFP_KERNEL);
+-      if (ret)
+-              goto free_mem;
+-
+-      sg_set_page(table->sgl, pages, len, 0);
+-
+-      buffer->priv_virt = pages;
+-      buffer->sg_table = table;
+-      buffer->cma_heap = cma_heap;
+-      buffer->num_pages = num_pages;
+-      return 0;
+-
+-free_mem:
+-      kfree(table);
+-err:
+-      cma_release(cma_heap, pages, num_pages);
+-      return -ENOMEM;
+-}
+-
+-void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer)
+-{
+-      struct cma *cma_heap = buffer->cma_heap;
+-      struct page *pages = buffer->priv_virt;
+-
+-      /* release memory */
+-      if (cma_heap)
+-              cma_release(cma_heap, pages, buffer->num_pages);
+-
+-      /* release sg table */
+-      if (buffer->sg_table) {
+-              sg_free_table(buffer->sg_table);
+-              kfree(buffer->sg_table);
+-              buffer->sg_table = NULL;
+-      }
+-}
+-
+-int __vc_sm_cma_add_heaps(struct cma *cma, void *priv)
+-{
+-      struct cma **heap = (struct cma **)priv;
+-      const char *name = cma_get_name(cma);
+-
+-      if (!(*heap)) {
+-              phys_addr_t phys_addr = cma_get_base(cma);
+-
+-              pr_debug("%s: Adding cma heap %s (start %pap, size %lu) for use by vcsm\n",
+-                       __func__, name, &phys_addr, cma_get_size(cma));
+-              *heap = cma;
+-      } else {
+-              pr_err("%s: Ignoring heap %s as already set\n",
+-                     __func__, name);
+-      }
+-
+-      return 0;
+-}
+-
+-void vc_sm_cma_add_heaps(struct cma **cma_heap)
+-{
+-      cma_for_each_area(__vc_sm_cma_add_heaps, cma_heap);
+-}
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
++++ /dev/null
+@@ -1,39 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-
+-/*
+- * VideoCore Shared Memory CMA allocator
+- *
+- * Copyright: 2018, Raspberry Pi (Trading) Ltd
+- *
+- * Based on the Android ION allocator
+- * Copyright (C) Linaro 2012
+- * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
+- *
+- * This software is licensed under the terms of the GNU General Public
+- * License version 2, as published by the Free Software Foundation, and
+- * may be copied, distributed, and modified under those terms.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- */
+-#ifndef VC_SM_CMA_H
+-#define VC_SM_CMA_H
+-
+-struct vc_sm_cma_alloc_data {
+-      struct cma *cma_heap;
+-      unsigned long num_pages;
+-      void *priv_virt;
+-      struct sg_table *sg_table;
+-};
+-
+-int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
+-                            struct vc_sm_cma_alloc_data *buffer,
+-                            unsigned long len);
+-void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer);
+-
+-void vc_sm_cma_add_heaps(struct cma **cma_heap);
+-
+-#endif