All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] drm: Add shmem GEM library
@ 2018-09-11 12:43 Noralf Trønnes
  2018-09-11 12:43 ` [PATCH v3 1/2] drm: Add library for shmem backed GEM objects Noralf Trønnes
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Noralf Trønnes @ 2018-09-11 12:43 UTC (permalink / raw)
  To: dri-devel; +Cc: sam, david

This patchset adds a library for shmem backed GEM objects and makes use
of it in tinydrm.

When I made tinydrm I used the CMA helper because it was very easy to
use. July last year I learned that this limits which drivers to PRIME
import from, since CMA requires continuous memory. tinydrm drivers don't
require that. So I set out to change that looking first at shmem, but
that wasn't working since shmem didn't work with fbdev deferred I/O.
Then I did a vmalloc buffer attempt which worked with deferred I/O, but
maybe wouldn't be of so much use as a library for other drivers to use.
As my work to split out stuff from the CMA helper for shared use came to
an end, I had a generic fbdev emulation that uses a shadow buffer for
deferred I/O.
This means that I can now use shmem buffers after all.

I have looked at the other drivers that use drm_gem_get_pages() and
several supports different cache modes so I've done that even though
tinydrm only uses the cached one.

tinydrm can both use vmalloc and shmem buffers, it doesn't matter as far
as I can see. So the question is what will benefit the rest of DRM the most.

Note:
Sparse has this complaint, but the problem is in kvmalloc_array():
include/linux/mm.h:592:13: error: undefined identifier '__builtin_mul_overflow'

Noralf.

Changes since version 2:
- Grammar (Sam Ravnborg)
- s/drm_gem_shmem_put_pages_unlocked/drm_gem_shmem_put_pages_locked/
  (Sam Ravnborg)
- Add debug ouput in error path (Sam Ravnborg)

Changes since version 1:
- Fix missing argument in docs (kbuild test robot)
- Fix: sparse: expression using sizeof(void) (kbuild test robot)
- Rebasing gave a new checkpatch warning, so I changed to bitfields:
  CHECK: Avoid using bool structure members because of possible alignment
  issues - see: https://lkml.org/lkml/2017/11/21/384
  #834: FILE: include/drm/drm_gem_shmem_helper.h:84:
  +       bool pages_mark_dirty_on_put;
  #841: FILE: include/drm/drm_gem_shmem_helper.h:91:
  +       bool pages_mark_accessed_on_put;

Noralf Trønnes (2):
  drm: Add library for shmem backed GEM objects
  drm/tinydrm: Switch from CMA to shmem buffers

 Documentation/gpu/drm-kms-helpers.rst          |  12 +
 drivers/gpu/drm/Kconfig                        |   6 +
 drivers/gpu/drm/Makefile                       |   1 +
 drivers/gpu/drm/drm_gem_shmem_helper.c         | 678 +++++++++++++++++++++++++
 drivers/gpu/drm/tinydrm/Kconfig                |   2 +-
 drivers/gpu/drm/tinydrm/core/tinydrm-core.c    |  91 +---
 drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c |   5 +
 drivers/gpu/drm/tinydrm/ili9225.c              |  14 +-
 drivers/gpu/drm/tinydrm/ili9341.c              |   6 +-
 drivers/gpu/drm/tinydrm/mi0283qt.c             |   6 +-
 drivers/gpu/drm/tinydrm/mipi-dbi.c             |  38 +-
 drivers/gpu/drm/tinydrm/repaper.c              |  24 +-
 drivers/gpu/drm/tinydrm/st7586.c               |  15 +-
 drivers/gpu/drm/tinydrm/st7735r.c              |   6 +-
 include/drm/drm_gem_shmem_helper.h             | 198 ++++++++
 include/drm/tinydrm/tinydrm.h                  |  36 +-
 16 files changed, 984 insertions(+), 154 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_gem_shmem_helper.c
 create mode 100644 include/drm/drm_gem_shmem_helper.h

-- 
2.15.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v3 1/2] drm: Add library for shmem backed GEM objects
  2018-09-11 12:43 [PATCH v3 0/2] drm: Add shmem GEM library Noralf Trønnes
@ 2018-09-11 12:43 ` Noralf Trønnes
  2018-09-13  1:33   ` David Lechner
  2018-09-11 12:44 ` [PATCH v3 2/2] drm/tinydrm: Switch from CMA to shmem buffers Noralf Trønnes
  2018-09-14 15:48 ` [PATCH v3 0/2] drm: Add shmem GEM library Thomas Hellstrom
  2 siblings, 1 reply; 13+ messages in thread
From: Noralf Trønnes @ 2018-09-11 12:43 UTC (permalink / raw)
  To: dri-devel; +Cc: sam, david

This adds a library for shmem backed GEM objects with the necessary
drm_driver callbacks.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---

Changes since version 2:
- Grammar (Sam Ravnborg)
- s/drm_gem_shmem_put_pages_unlocked/drm_gem_shmem_put_pages_locked/
  (Sam Ravnborg)
- Add debug ouput in error path (Sam Ravnborg)

Changes since version 1:
- Fix missing argument in docs (kbuild test robot)
- Fix: sparse: expression using sizeof(void) (kbuild test robot)
- Rebasing gave a new checkpatch warning, so I changed to bitfields:
  CHECK: Avoid using bool structure members because of possible alignment issues - see: https://lkml.org/lkml/2017/11/21/384
  #834: FILE: include/drm/drm_gem_shmem_helper.h:84:
  +       bool pages_mark_dirty_on_put;
  #841: FILE: include/drm/drm_gem_shmem_helper.h:91:
  +       bool pages_mark_accessed_on_put;

 Documentation/gpu/drm-kms-helpers.rst  |  12 +
 drivers/gpu/drm/Kconfig                |   6 +
 drivers/gpu/drm/Makefile               |   1 +
 drivers/gpu/drm/drm_gem_shmem_helper.c | 678 +++++++++++++++++++++++++++++++++
 include/drm/drm_gem_shmem_helper.h     | 198 ++++++++++
 5 files changed, 895 insertions(+)
 create mode 100644 drivers/gpu/drm/drm_gem_shmem_helper.c
 create mode 100644 include/drm/drm_gem_shmem_helper.h

diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst
index f9cfcdcdf024..bc24b1b5216a 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -326,3 +326,15 @@ Legacy CRTC/Modeset Helper Functions Reference
 
 .. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
    :export:
+
+SHMEM GEM Helper Reference
+==========================
+
+.. kernel-doc:: drivers/gpu/drm/drm_gem_shmem_helper.c
+   :doc: overview
+
+.. kernel-doc:: include/drm/drm_gem_shmem_helper.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_gem_shmem_helper.c
+   :export:
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index cb88528e7b10..db588ae44bcc 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -157,6 +157,12 @@ config DRM_KMS_CMA_HELPER
 	help
 	  Choose this if you need the KMS CMA helper functions
 
+config DRM_GEM_SHMEM_HELPER
+	bool
+	depends on DRM
+	help
+	  Choose this if you need the GEM shmem helper functions
+
 config DRM_VM
 	bool
 	depends on DRM && MMU
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index a6771cef85e2..c6798590799f 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -24,6 +24,7 @@ drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
 drm-$(CONFIG_DRM_VM) += drm_vm.o
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
+drm-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_gem_shmem_helper.o
 drm-$(CONFIG_PCI) += ati_pcigart.o
 drm-$(CONFIG_DRM_PANEL) += drm_panel.o
 drm-$(CONFIG_OF) += drm_of.o
diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
new file mode 100644
index 000000000000..05641c7e5340
--- /dev/null
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -0,0 +1,678 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 Noralf Trønnes
+ */
+
+#include <linux/dma-buf.h>
+#include <linux/export.h>
+#include <linux/mutex.h>
+#include <linux/shmem_fs.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_gem_shmem_helper.h>
+#include <drm/drm_prime.h>
+#include <drm/drm_print.h>
+
+/**
+ * DOC: overview
+ *
+ * This library provides helpers for GEM objects backed by shmem buffers
+ * allocated using anonymous pageable memory.
+ */
+
+/**
+ * drm_gem_shmem_create - Allocate an object with the given size
+ * @dev: DRM device
+ * @size: Size of the object to allocate
+ *
+ * This function creates a shmem GEM object. The default cache mode is
+ * DRM_GEM_SHMEM_BO_CACHED. The &drm_driver->gem_create_object callback can be
+ * used to override this.
+ *
+ * Returns:
+ * A struct drm_gem_shmem_object * on success or an ERR_PTR()-encoded negative
+ * error code on failure.
+ */
+struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size)
+{
+	struct drm_gem_shmem_object *shmem;
+	struct drm_gem_object *obj;
+	int ret;
+
+	size = PAGE_ALIGN(size);
+
+	if (dev->driver->gem_create_object)
+		obj = dev->driver->gem_create_object(dev, size);
+	else
+		obj = kzalloc(sizeof(*shmem), GFP_KERNEL);
+	if (!obj)
+		return ERR_PTR(-ENOMEM);
+
+	shmem = to_drm_gem_shmem_obj(obj);
+
+	if (!dev->driver->gem_create_object)
+		shmem->cache_mode = DRM_GEM_SHMEM_BO_CACHED;
+
+	ret = drm_gem_object_init(dev, obj, size);
+	if (ret)
+		goto err_free;
+
+	ret = drm_gem_create_mmap_offset(obj);
+	if (ret)
+		goto err_release;
+
+	mutex_init(&shmem->pages_lock);
+	mutex_init(&shmem->vmap_lock);
+
+	return shmem;
+
+err_release:
+	drm_gem_object_release(obj);
+err_free:
+	kfree(shmem);
+
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(drm_gem_shmem_create);
+
+/**
+ * drm_gem_shmem_free_object - Free resources associated with a shmem GEM object
+ * @obj: GEM object to free
+ *
+ * This function cleans up the GEM object state and frees the memory used to
+ * store the object itself. Drivers using the shmem helpers should set this as
+ * their &drm_driver.gem_free_object_unlocked callback.
+ */
+void drm_gem_shmem_free_object(struct drm_gem_object *obj)
+{
+	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+
+	WARN_ON(shmem->vmap_use_count);
+
+	if (obj->import_attach) {
+		shmem->pages_use_count--;
+		drm_prime_gem_destroy(obj, shmem->sgt);
+		kvfree(shmem->pages);
+	}
+
+	WARN_ON(shmem->pages_use_count);
+
+	drm_gem_object_release(obj);
+	mutex_destroy(&shmem->pages_lock);
+	mutex_destroy(&shmem->vmap_lock);
+	kfree(shmem);
+}
+EXPORT_SYMBOL_GPL(drm_gem_shmem_free_object);
+
+static int drm_gem_shmem_get_pages_locked(struct drm_gem_shmem_object *shmem)
+{
+	struct drm_gem_object *obj = &shmem->base;
+	struct page **pages;
+
+	if (shmem->pages_use_count++ > 0)
+		return 0;
+
+	pages = drm_gem_get_pages(obj);
+	if (IS_ERR(pages)) {
+		DRM_DEBUG_KMS("Failed to get pages (%ld)\n", PTR_ERR(pages));
+		shmem->pages_use_count = 0;
+		return PTR_ERR(pages);
+	}
+
+	shmem->pages = pages;
+
+	return 0;
+}
+
+/*
+ * drm_gem_shmem_get_pages - Allocate backing pages for a shmem GEM object
+ * @shmem: shmem GEM object
+ *
+ * This function makes sure that backing pages exists for the shmem GEM object
+ * and increases the use count.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_gem_shmem_get_pages(struct drm_gem_shmem_object *shmem)
+{
+	int ret;
+
+	ret = mutex_lock_interruptible(&shmem->pages_lock);
+	if (ret)
+		return ret;
+	ret = drm_gem_shmem_get_pages_locked(shmem);
+	mutex_unlock(&shmem->pages_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(drm_gem_shmem_get_pages);
+
+static void drm_gem_shmem_put_pages_locked(struct drm_gem_shmem_object *shmem)
+{
+	struct drm_gem_object *obj = &shmem->base;
+
+	if (WARN_ON_ONCE(!shmem->pages_use_count))
+		return;
+
+	if (--shmem->pages_use_count > 0)
+		return;
+
+	drm_gem_put_pages(obj, shmem->pages,
+			  shmem->pages_mark_dirty_on_put,
+			  shmem->pages_mark_accessed_on_put);
+	shmem->pages = NULL;
+}
+
+/*
+ * drm_gem_shmem_put_pages - Decrease use count on the backing pages for a shmem GEM object
+ * @shmem: shmem GEM object
+ *
+ * This function decreases the use count and puts the backing pages when use drops to zero.
+ */
+void drm_gem_shmem_put_pages(struct drm_gem_shmem_object *shmem)
+{
+	mutex_lock(&shmem->pages_lock);
+	drm_gem_shmem_put_pages_locked(shmem);
+	mutex_unlock(&shmem->pages_lock);
+}
+EXPORT_SYMBOL(drm_gem_shmem_put_pages);
+
+static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem)
+{
+	struct drm_gem_object *obj = &shmem->base;
+	int ret;
+
+	if (shmem->vmap_use_count++ > 0)
+		return 0;
+
+	ret = drm_gem_shmem_get_pages(shmem);
+	if (ret)
+		goto err_zero_use;
+
+	if (obj->import_attach) {
+		shmem->vaddr = dma_buf_vmap(obj->import_attach->dmabuf);
+	} else {
+		pgprot_t prot;
+
+		switch (shmem->cache_mode) {
+		case DRM_GEM_SHMEM_BO_UNKNOWN:
+			DRM_DEBUG_KMS("Can't vmap cache mode is unknown\n");
+			ret = -EINVAL;
+			goto err_put_pages;
+
+		case DRM_GEM_SHMEM_BO_WRITECOMBINED:
+			prot = pgprot_writecombine(PAGE_KERNEL);
+			break;
+
+		case DRM_GEM_SHMEM_BO_UNCACHED:
+			prot = pgprot_noncached(PAGE_KERNEL);
+			break;
+
+		case DRM_GEM_SHMEM_BO_CACHED:
+			prot = PAGE_KERNEL;
+			break;
+		}
+
+		shmem->vaddr = vmap(shmem->pages, obj->size >> PAGE_SHIFT, VM_MAP, prot);
+	}
+
+	if (!shmem->vaddr) {
+		DRM_DEBUG_KMS("Failed to vmap pages\n");
+		ret = -ENOMEM;
+		goto err_put_pages;
+	}
+
+	return 0;
+
+err_put_pages:
+	drm_gem_shmem_put_pages(shmem);
+err_zero_use:
+	shmem->vmap_use_count = 0;
+
+	return ret;
+}
+
+/*
+ * drm_gem_shmem_vmap - Create a virtual mapping for a shmem GEM object
+ * @shmem: shmem GEM object
+ *
+ * This function makes sure that a virtual address exists for the buffer backing
+ * the shmem GEM object.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_gem_shmem_vmap(struct drm_gem_shmem_object *shmem)
+{
+	int ret;
+
+	ret = mutex_lock_interruptible(&shmem->vmap_lock);
+	if (ret)
+		return ret;
+	ret = drm_gem_shmem_vmap_locked(shmem);
+	mutex_unlock(&shmem->vmap_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(drm_gem_shmem_vmap);
+
+static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem)
+{
+	struct drm_gem_object *obj = &shmem->base;
+
+	if (WARN_ON_ONCE(!shmem->vmap_use_count))
+		return;
+
+	if (--shmem->vmap_use_count > 0)
+		return;
+
+	if (obj->import_attach)
+		dma_buf_vunmap(obj->import_attach->dmabuf, shmem->vaddr);
+	else
+		vunmap(shmem->vaddr);
+
+	shmem->vaddr = NULL;
+	drm_gem_shmem_put_pages(shmem);
+}
+
+/*
+ * drm_gem_shmem_vunmap - Unmap a virtual mapping fo a shmem GEM object
+ * @shmem: shmem GEM object
+ *
+ * This function removes the virtual address when use count drops to zero.
+ */
+void drm_gem_shmem_vunmap(struct drm_gem_shmem_object *shmem)
+{
+	mutex_lock(&shmem->vmap_lock);
+	drm_gem_shmem_vunmap_locked(shmem);
+	mutex_unlock(&shmem->vmap_lock);
+}
+EXPORT_SYMBOL(drm_gem_shmem_vunmap);
+
+static struct drm_gem_shmem_object *
+drm_gem_shmem_create_with_handle(struct drm_file *file_priv,
+				 struct drm_device *dev, size_t size,
+				 uint32_t *handle)
+{
+	struct drm_gem_shmem_object *shmem;
+	int ret;
+
+	shmem = drm_gem_shmem_create(dev, size);
+	if (IS_ERR(shmem))
+		return shmem;
+
+	/*
+	 * Allocate an id of idr table where the obj is registered
+	 * and handle has the id what user can see.
+	 */
+	ret = drm_gem_handle_create(file_priv, &shmem->base, handle);
+	/* drop reference from allocate - handle holds it now. */
+	drm_gem_object_put_unlocked(&shmem->base);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return shmem;
+}
+
+/**
+ * drm_gem_shmem_dumb_create - Create a dumb shmem buffer object
+ * @file: DRM file structure to create the dumb buffer for
+ * @dev: DRM device
+ * @args: IOCTL data
+ *
+ * This function computes the pitch of the dumb buffer and rounds it up to an
+ * integer number of bytes per pixel. Drivers for hardware that doesn't have
+ * any additional restrictions on the pitch can directly use this function as
+ * their &drm_driver.dumb_create callback.
+ *
+ * For hardware with additional restrictions, drivers can adjust the fields
+ * set up by userspace before calling into this function.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_gem_shmem_dumb_create(struct drm_file *file, struct drm_device *dev,
+			      struct drm_mode_create_dumb *args)
+{
+	u32 min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+	struct drm_gem_shmem_object *shmem;
+
+	if (!args->pitch || !args->size) {
+		args->pitch = min_pitch;
+		args->size = args->pitch * args->height;
+	} else {
+		/* ensure sane minimum values */
+		if (args->pitch < min_pitch)
+			args->pitch = min_pitch;
+		if (args->size < args->pitch * args->height)
+			args->size = args->pitch * args->height;
+	}
+
+	shmem = drm_gem_shmem_create_with_handle(file, dev, args->size, &args->handle);
+
+	return PTR_ERR_OR_ZERO(shmem);
+}
+EXPORT_SYMBOL_GPL(drm_gem_shmem_dumb_create);
+
+static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
+{
+	struct vm_area_struct *vma = vmf->vma;
+	struct drm_gem_object *obj = vma->vm_private_data;
+	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+	/* We don't use vmf->pgoff since that has the fake offset: */
+	pgoff_t pgoff = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
+	loff_t num_pages = obj->size >> PAGE_SHIFT;
+	struct page *page;
+
+	if (pgoff > num_pages || WARN_ON_ONCE(!shmem->pages))
+		return VM_FAULT_SIGBUS;
+
+	page = shmem->pages[pgoff];
+
+	return vmf_insert_page(vma, vmf->address, page);
+}
+
+static void drm_gem_shmem_vm_close(struct vm_area_struct *vma)
+{
+	struct drm_gem_object *obj = vma->vm_private_data;
+	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+
+	drm_gem_shmem_put_pages(shmem);
+	drm_gem_vm_close(vma);
+}
+
+const struct vm_operations_struct drm_gem_shmem_vm_ops = {
+	.fault = drm_gem_shmem_fault,
+	.open = drm_gem_vm_open,
+	.close = drm_gem_shmem_vm_close,
+};
+EXPORT_SYMBOL_GPL(drm_gem_shmem_vm_ops);
+
+static int drm_gem_shmem_mmap_obj(struct drm_gem_shmem_object *shmem,
+				  struct vm_area_struct *vma)
+{
+	int ret;
+
+	ret = drm_gem_shmem_get_pages(shmem);
+	if (ret)
+		goto err_close;
+
+	/* VM_PFNMAP was set by drm_gem_mmap() */
+	vma->vm_flags &= ~VM_PFNMAP;
+	vma->vm_flags |= VM_MIXEDMAP;
+
+	switch (shmem->cache_mode) {
+	case DRM_GEM_SHMEM_BO_UNKNOWN:
+		DRM_DEBUG_KMS("Can't mmap cache mode is unknown\n");
+		ret = -EINVAL;
+		goto err_put_pages;
+
+	case DRM_GEM_SHMEM_BO_WRITECOMBINED:
+		vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
+		break;
+
+	case DRM_GEM_SHMEM_BO_UNCACHED:
+		vma->vm_page_prot = pgprot_noncached(vm_get_page_prot(vma->vm_flags));
+		break;
+
+	case DRM_GEM_SHMEM_BO_CACHED:
+		/*
+		 * Shunt off cached objs to shmem file so they have their own
+		 * address_space (so unmap_mapping_range does what we want,
+		 * in particular in the case of mmap'd dmabufs)
+		 */
+		fput(vma->vm_file);
+		get_file(shmem->base.filp);
+		vma->vm_pgoff = 0;
+		vma->vm_file  = shmem->base.filp;
+		vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+		break;
+	}
+
+	return 0;
+
+err_put_pages:
+	drm_gem_shmem_put_pages(shmem);
+err_close:
+	drm_gem_vm_close(vma);
+
+	return ret;
+}
+
+/**
+ * drm_gem_shmem_mmap - Memory-map a shmem GEM object
+ * @filp: File object
+ * @vma: VMA for the area to be mapped
+ *
+ * This function implements an augmented version of the GEM DRM file mmap
+ * operation for shmem objects. Drivers which employ the shmem helpers should
+ * use this function as their &file_operations.mmap handler in the DRM device file's
+ * file_operations structure.
+ *
+ * Instead of directly referencing this function, drivers should use the
+ * DEFINE_DRM_GEM_SHMEM_FOPS() macro.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_gem_shmem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct drm_gem_shmem_object *shmem;
+	int ret;
+
+	ret = drm_gem_mmap(filp, vma);
+	if (ret)
+		return ret;
+
+	shmem = to_drm_gem_shmem_obj(vma->vm_private_data);
+
+	return drm_gem_shmem_mmap_obj(shmem, vma);
+}
+EXPORT_SYMBOL_GPL(drm_gem_shmem_mmap);
+
+static const char * const cache_mode_str[] = {
+	[DRM_GEM_SHMEM_BO_UNKNOWN] = "unknown",
+	[DRM_GEM_SHMEM_BO_UNCACHED] = "uncached",
+	[DRM_GEM_SHMEM_BO_CACHED] = "cached",
+	[DRM_GEM_SHMEM_BO_WRITECOMBINED] = "writecombined",
+};
+
+/**
+ * drm_gem_shmem_print_info() - Print &drm_gem_cma_object info for debugfs
+ * @p: DRM printer
+ * @indent: Tab indentation level
+ * @obj: GEM object
+ *
+ * This function can be used as the &drm_driver->gem_print_info callback.
+ */
+void drm_gem_shmem_print_info(struct drm_printer *p, unsigned int indent,
+			      const struct drm_gem_object *obj)
+{
+	const struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+
+	drm_printf_indent(p, indent, "cachemode=%s\n", cache_mode_str[shmem->cache_mode]);
+	drm_printf_indent(p, indent, "pages_use_count=%u\n", shmem->pages_use_count);
+	drm_printf_indent(p, indent, "vaddr=%p\n", shmem->vaddr);
+	drm_printf_indent(p, indent, "vmap_use_count=%u\n", shmem->vmap_use_count);
+}
+EXPORT_SYMBOL(drm_gem_shmem_print_info);
+
+/**
+ * drm_gem_shmem_prime_pin - Pin backing pages for a shmem GEM object
+ * @obj: GEM object
+ *
+ * This function makes sure the backing pages are pinned in memory while the
+ * buffer is exported. Drivers using the shmem helpers should set this as their
+ * DRM driver's &drm_driver.gem_prime_pin callback.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_gem_shmem_prime_pin(struct drm_gem_object *obj)
+{
+	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+
+	return drm_gem_shmem_get_pages(shmem);
+}
+EXPORT_SYMBOL(drm_gem_shmem_prime_pin);
+
+/**
+ * drm_gem_shmem_prime_unpin - Unpin backing pages for a shmem GEM object
+ * @obj: GEM object
+ *
+ * This function removes the requirement that the backing pages are pinned in
+ * memory. Drivers using the shmem helpers should set this as their DRM driver's
+ * &drm_driver.gem_prime_unpin callback.
+ */
+void drm_gem_shmem_prime_unpin(struct drm_gem_object *obj)
+{
+	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+
+	drm_gem_shmem_put_pages(shmem);
+}
+EXPORT_SYMBOL(drm_gem_shmem_prime_unpin);
+
+/**
+ * drm_gem_shmem_prime_get_sg_table - Provide a scatter/gather table of pinned
+ *                                    pages for a shmem GEM object
+ * @obj: GEM object
+ *
+ * This function exports a scatter/gather table suitable for PRIME usage by
+ * calling the standard DMA mapping API. Drivers using the shmem helpers should
+ * set this as their &drm_driver.gem_prime_get_sg_table callback.
+ *
+ * Returns:
+ * A pointer to the scatter/gather table of pinned pages or NULL on failure.
+ */
+struct sg_table *drm_gem_shmem_prime_get_sg_table(struct drm_gem_object *obj)
+{
+	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+
+	return drm_prime_pages_to_sg(shmem->pages, obj->size >> PAGE_SHIFT);
+}
+EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_get_sg_table);
+
+/**
+ * drm_gem_shmem_prime_import_sg_table - Produce a shmem GEM object from
+ *                 another driver's scatter/gather table of pinned pages
+ * @dev: Device to import into
+ * @attach: DMA-BUF attachment
+ * @sgt: Scatter/gather table of pinned pages
+ *
+ * This function imports a scatter/gather table exported via DMA-BUF by
+ * another driver. Drivers that use the shmem helpers should set this as their
+ * &drm_driver.gem_prime_import_sg_table callback.
+ *
+ * Returns:
+ * A pointer to a newly created GEM object or an ERR_PTR-encoded negative
+ * error code on failure.
+ */
+struct drm_gem_object *
+drm_gem_shmem_prime_import_sg_table(struct drm_device *dev,
+				    struct dma_buf_attachment *attach,
+				    struct sg_table *sgt)
+{
+	size_t size = PAGE_ALIGN(attach->dmabuf->size);
+	size_t npages = size >> PAGE_SHIFT;
+	struct drm_gem_shmem_object *shmem;
+	int ret;
+
+	shmem = drm_gem_shmem_create(dev, size);
+	if (IS_ERR(shmem))
+		return ERR_CAST(shmem);
+
+	shmem->pages = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
+	if (!shmem->pages) {
+		ret = -ENOMEM;
+		goto err_free_gem;
+	}
+
+	ret = drm_prime_sg_to_page_addr_arrays(sgt, shmem->pages, NULL, npages);
+	if (ret < 0)
+		goto err_free_array;
+
+	shmem->sgt = sgt;
+	shmem->cache_mode = DRM_GEM_SHMEM_BO_UNKNOWN;
+	shmem->pages_use_count = 1; /* Permanently pinned from our point of view */
+
+	DRM_DEBUG_PRIME("size = %zu\n", size);
+
+	return &shmem->base;
+
+err_free_array:
+	kvfree(shmem->pages);
+err_free_gem:
+	drm_gem_object_put_unlocked(&shmem->base);
+
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_import_sg_table);
+
+/**
+ * drm_gem_shmem_prime_mmap - Memory-map an exported shmem GEM object
+ * @obj: GEM object
+ * @vma: VMA for the area to be mapped
+ *
+ * This function maps a buffer imported via DRM PRIME into a userspace
+ * process's address space. Drivers that use the shmem helpers should set this
+ * as their &drm_driver.gem_prime_mmap callback.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_gem_shmem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
+{
+	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+	int ret;
+
+	ret = drm_gem_mmap_obj(obj, obj->size, vma);
+	if (ret)
+		return ret;
+
+	return drm_gem_shmem_mmap_obj(shmem, vma);
+}
+EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_mmap);
+
+/**
+ * drm_gem_shmem_prime_vmap - Map a shmem GEM object into the kernel's virtual
+ *                            address space
+ * @obj: GEM object
+ *
+ * This function maps a buffer exported via DRM PRIME into the kernel's
+ * virtual address space. Drivers using the shmem helpers should set this as
+ * their DRM driver's &drm_driver.gem_prime_vmap callback.
+ *
+ * Returns:
+ * The kernel virtual address of the shmem GEM object's backing store or NULL on error.
+ */
+void *drm_gem_shmem_prime_vmap(struct drm_gem_object *obj)
+{
+	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+
+	drm_gem_shmem_vmap(shmem);
+
+	return shmem->vaddr;
+}
+EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_vmap);
+
+/**
+ * drm_gem_shmem_prime_vunmap - Unmap a shmem GEM object from the kernel's
+ *                              virtual address space
+ * @obj: GEM object
+ * @vaddr: kernel virtual address where the shmem GEM object was mapped
+ *
+ * This function removes a buffer exported via DRM PRIME from the kernel's
+ * virtual address space. Drivers using the shmem helpers should set this as
+ * their &drm_driver.gem_prime_vunmap callback.
+ */
+void drm_gem_shmem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
+{
+	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+
+	drm_gem_shmem_vunmap(shmem);
+}
+EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_vunmap);
diff --git a/include/drm/drm_gem_shmem_helper.h b/include/drm/drm_gem_shmem_helper.h
new file mode 100644
index 000000000000..8dfcb2c3d667
--- /dev/null
+++ b/include/drm/drm_gem_shmem_helper.h
@@ -0,0 +1,198 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __DRM_GEM_SHMEM_HELPER_H__
+#define __DRM_GEM_SHMEM_HELPER_H__
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+
+#include <drm/drm_file.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_ioctl.h>
+#include <drm/drm_prime.h>
+
+struct dma_buf_attachment;
+struct drm_mode_create_dumb;
+struct drm_printer;
+struct sg_table;
+
+/**
+ * enum drm_gem_shmem_cache_mode - shmem buffer cache mode
+ */
+enum drm_gem_shmem_cache_mode {
+	/**
+	 * @DRM_GEM_SHMEM_BO_UNKNOWN:
+	 *
+	 * Cache mode is not known. This is the case when importing a buffer.
+	 */
+	DRM_GEM_SHMEM_BO_UNKNOWN = 0,
+
+	/**
+	 * @DRM_GEM_SHMEM_BO_UNCACHED: Buffer is uncached.
+	 */
+	DRM_GEM_SHMEM_BO_UNCACHED,
+
+	/**
+	 * @DRM_GEM_SHMEM_BO_CACHED: Buffer is cached.
+	 */
+	DRM_GEM_SHMEM_BO_CACHED,
+
+	/**
+	 * @DRM_GEM_SHMEM_BO_WRITECOMBINED: Buffer is uncached with writes combined.
+	 */
+	DRM_GEM_SHMEM_BO_WRITECOMBINED,
+};
+
+/**
+ * struct drm_gem_shmem_object - GEM object backed by shmem
+ */
+struct drm_gem_shmem_object {
+	/**
+	 * @base: Base GEM object
+	 */
+	struct drm_gem_object base;
+
+	/**
+	 * @cache_mode: Cache mode
+	 */
+	enum drm_gem_shmem_cache_mode cache_mode;
+
+	/**
+	 * @pages_lock: Protects the page table and use count
+	 */
+	struct mutex pages_lock;
+
+	/**
+	 * @pages: Page table
+	 */
+	struct page **pages;
+
+	/**
+	 * @pages_use_count:
+	 *
+	 * Reference count on the pages table.
+	 * The pages are put when the count reaches zero.
+	 */
+	unsigned int pages_use_count;
+
+	/**
+	 * @pages_mark_dirty_on_put:
+	 *
+	 * Mark pages as dirty when they are put.
+	 */
+	unsigned int pages_mark_dirty_on_put    : 1;
+
+	/**
+	 * @pages_mark_accessed_on_put:
+	 *
+	 * Mark pages as accessed when they are put.
+	 */
+	unsigned int pages_mark_accessed_on_put : 1;
+
+	/**
+	 * @sgt: Scatter/gather table for imported PRIME buffers
+	 */
+	struct sg_table *sgt;
+
+	/**
+	 * @vmap_lock: Protects the vmap address and use count
+	 */
+	struct mutex vmap_lock;
+
+	/**
+	 * @vaddr: Kernel virtual address of the backing memory
+	 */
+	void *vaddr;
+
+	/**
+	 * @vmap_use_count:
+	 *
+	 * Reference count on the virtual address.
+	 * The address are un-mapped when the count reaches zero.
+	 */
+	unsigned int vmap_use_count;
+};
+
+#define to_drm_gem_shmem_obj(obj) \
+	container_of(obj, struct drm_gem_shmem_object, base)
+
+/**
+ * DEFINE_DRM_GEM_SHMEM_FOPS() - Macro to generate file operations for shmem drivers
+ * @name: name for the generated structure
+ *
+ * This macro autogenerates a suitable &struct file_operations for shmem based
+ * drivers, which can be assigned to &drm_driver.fops. Note that this structure
+ * cannot be shared between drivers, because it contains a reference to the
+ * current module using THIS_MODULE.
+ *
+ * Note that the declaration is already marked as static - if you need a
+ * non-static version of this you're probably doing it wrong and will break the
+ * THIS_MODULE reference by accident.
+ */
+#define DEFINE_DRM_GEM_SHMEM_FOPS(name) \
+	static const struct file_operations name = {\
+		.owner		= THIS_MODULE,\
+		.open		= drm_open,\
+		.release	= drm_release,\
+		.unlocked_ioctl	= drm_ioctl,\
+		.compat_ioctl	= drm_compat_ioctl,\
+		.poll		= drm_poll,\
+		.read		= drm_read,\
+		.llseek		= noop_llseek,\
+		.mmap		= drm_gem_shmem_mmap, \
+	}
+
+struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size);
+void drm_gem_shmem_free_object(struct drm_gem_object *obj);
+
+int drm_gem_shmem_get_pages(struct drm_gem_shmem_object *shmem);
+void drm_gem_shmem_put_pages(struct drm_gem_shmem_object *shmem);
+int drm_gem_shmem_vmap(struct drm_gem_shmem_object *shmem);
+void drm_gem_shmem_vunmap(struct drm_gem_shmem_object *shmem);
+
+int drm_gem_shmem_dumb_create(struct drm_file *file, struct drm_device *dev,
+			      struct drm_mode_create_dumb *args);
+
+int drm_gem_shmem_mmap(struct file *filp, struct vm_area_struct *vma);
+
+extern const struct vm_operations_struct drm_gem_shmem_vm_ops;
+
+void drm_gem_shmem_print_info(struct drm_printer *p, unsigned int indent,
+			      const struct drm_gem_object *obj);
+
+int drm_gem_shmem_prime_pin(struct drm_gem_object *obj);
+void drm_gem_shmem_prime_unpin(struct drm_gem_object *obj);
+struct sg_table *drm_gem_shmem_prime_get_sg_table(struct drm_gem_object *obj);
+struct drm_gem_object *
+drm_gem_shmem_prime_import_sg_table(struct drm_device *dev,
+				    struct dma_buf_attachment *attach,
+				    struct sg_table *sgt);
+int drm_gem_shmem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
+void *drm_gem_shmem_prime_vmap(struct drm_gem_object *obj);
+void drm_gem_shmem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
+
+/**
+ * DRM_GEM_SHMEM_DRIVER_OPS - Default shmem GEM operations
+ *
+ * This macro provides a shortcut for setting the shmem GEM operations in
+ * the &drm_driver structure.
+ */
+#define DRM_GEM_SHMEM_DRIVER_OPS \
+	.gem_free_object_unlocked = drm_gem_shmem_free_object, \
+	.gem_print_info		= drm_gem_shmem_print_info, \
+	.gem_vm_ops		= &drm_gem_shmem_vm_ops, \
+	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd, \
+	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle, \
+	.gem_prime_pin		= drm_gem_shmem_prime_pin, \
+	.gem_prime_unpin	= drm_gem_shmem_prime_unpin, \
+	.gem_prime_import	= drm_gem_prime_import, \
+	.gem_prime_export	= drm_gem_prime_export, \
+	.gem_prime_get_sg_table	= drm_gem_shmem_prime_get_sg_table, \
+	.gem_prime_import_sg_table = drm_gem_shmem_prime_import_sg_table, \
+	.gem_prime_vmap		= drm_gem_shmem_prime_vmap, \
+	.gem_prime_vunmap	= drm_gem_shmem_prime_vunmap, \
+	.gem_prime_mmap		= drm_gem_shmem_prime_mmap, \
+	.dumb_create		= drm_gem_shmem_dumb_create
+
+#endif /* __DRM_GEM_SHMEM_HELPER_H__ */
-- 
2.15.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v3 2/2] drm/tinydrm: Switch from CMA to shmem buffers
  2018-09-11 12:43 [PATCH v3 0/2] drm: Add shmem GEM library Noralf Trønnes
  2018-09-11 12:43 ` [PATCH v3 1/2] drm: Add library for shmem backed GEM objects Noralf Trønnes
@ 2018-09-11 12:44 ` Noralf Trønnes
  2018-09-13  1:35   ` David Lechner
  2018-09-14 15:48 ` [PATCH v3 0/2] drm: Add shmem GEM library Thomas Hellstrom
  2 siblings, 1 reply; 13+ messages in thread
From: Noralf Trønnes @ 2018-09-11 12:44 UTC (permalink / raw)
  To: dri-devel; +Cc: sam, david

This move makes tinydrm useful for more drivers. tinydrm doesn't need
continuous memory, but at the time it was convenient to use the CMA
library. The spi core can do dma on is_vmalloc() addresses making this
possible.

Cc: David Lechner <david@lechnology.com>
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/tinydrm/Kconfig                |  2 +-
 drivers/gpu/drm/tinydrm/core/tinydrm-core.c    | 91 +++++++-------------------
 drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c |  5 ++
 drivers/gpu/drm/tinydrm/ili9225.c              | 14 ++--
 drivers/gpu/drm/tinydrm/ili9341.c              |  6 +-
 drivers/gpu/drm/tinydrm/mi0283qt.c             |  6 +-
 drivers/gpu/drm/tinydrm/mipi-dbi.c             | 38 ++++-------
 drivers/gpu/drm/tinydrm/repaper.c              | 24 +++----
 drivers/gpu/drm/tinydrm/st7586.c               | 15 +++--
 drivers/gpu/drm/tinydrm/st7735r.c              |  6 +-
 include/drm/tinydrm/tinydrm.h                  | 36 +++-------
 11 files changed, 89 insertions(+), 154 deletions(-)

diff --git a/drivers/gpu/drm/tinydrm/Kconfig b/drivers/gpu/drm/tinydrm/Kconfig
index 16f4b5c91f1b..aa0cabba5ace 100644
--- a/drivers/gpu/drm/tinydrm/Kconfig
+++ b/drivers/gpu/drm/tinydrm/Kconfig
@@ -2,7 +2,7 @@ menuconfig DRM_TINYDRM
 	tristate "Support for simple displays"
 	depends on DRM
 	select DRM_KMS_HELPER
-	select DRM_KMS_CMA_HELPER
+	select DRM_GEM_SHMEM_HELPER
 	help
 	  Choose this option if you have a tinydrm supported display.
 	  If M is selected the module will be called tinydrm.
diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
index 255341ee4eb9..efd83367aae2 100644
--- a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
+++ b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
@@ -12,6 +12,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_shmem_helper.h>
 #include <drm/tinydrm/tinydrm.h>
 #include <linux/device.h>
 #include <linux/dma-buf.h>
@@ -23,7 +24,7 @@
  *
  * It is based on &drm_simple_display_pipe coupled with a &drm_connector which
  * has only one fixed &drm_display_mode. The framebuffers are backed by the
- * cma helper and have support for framebuffer flushing (dirty).
+ * shmem buffers and have support for framebuffer flushing (dirty).
  * fbdev support is also included.
  *
  */
@@ -37,84 +38,38 @@
  */
 
 /**
- * tinydrm_gem_cma_prime_import_sg_table - Produce a CMA GEM object from
- *     another driver's scatter/gather table of pinned pages
- * @drm: DRM device to import into
- * @attach: DMA-BUF attachment
- * @sgt: Scatter/gather table of pinned pages
+ * tinydrm_fb_destroy - Destroy framebuffer
+ * @fb: Framebuffer
  *
- * This function imports a scatter/gather table exported via DMA-BUF by
- * another driver using drm_gem_cma_prime_import_sg_table(). It sets the
- * kernel virtual address on the CMA object. Drivers should use this as their
- * &drm_driver->gem_prime_import_sg_table callback if they need the virtual
- * address. tinydrm_gem_cma_free_object() should be used in combination with
- * this function.
- *
- * Returns:
- * A pointer to a newly created GEM object or an ERR_PTR-encoded negative
- * error code on failure.
+ * This function unmaps the virtual address on the backing buffer and destroys the framebuffer.
+ * Drivers should use this as their &drm_framebuffer_funcs->destroy callback.
  */
-struct drm_gem_object *
-tinydrm_gem_cma_prime_import_sg_table(struct drm_device *drm,
-				      struct dma_buf_attachment *attach,
-				      struct sg_table *sgt)
+void tinydrm_fb_destroy(struct drm_framebuffer *fb)
 {
-	struct drm_gem_cma_object *cma_obj;
-	struct drm_gem_object *obj;
-	void *vaddr;
-
-	vaddr = dma_buf_vmap(attach->dmabuf);
-	if (!vaddr) {
-		DRM_ERROR("Failed to vmap PRIME buffer\n");
-		return ERR_PTR(-ENOMEM);
-	}
-
-	obj = drm_gem_cma_prime_import_sg_table(drm, attach, sgt);
-	if (IS_ERR(obj)) {
-		dma_buf_vunmap(attach->dmabuf, vaddr);
-		return obj;
-	}
-
-	cma_obj = to_drm_gem_cma_obj(obj);
-	cma_obj->vaddr = vaddr;
-
-	return obj;
+	drm_gem_shmem_vunmap(to_drm_gem_shmem_obj(fb->obj[0]));
+	drm_gem_fb_destroy(fb);
 }
-EXPORT_SYMBOL(tinydrm_gem_cma_prime_import_sg_table);
-
-/**
- * tinydrm_gem_cma_free_object - Free resources associated with a CMA GEM
- *                               object
- * @gem_obj: GEM object to free
- *
- * This function frees the backing memory of the CMA GEM object, cleans up the
- * GEM object state and frees the memory used to store the object itself using
- * drm_gem_cma_free_object(). It also handles PRIME buffers which has the kernel
- * virtual address set by tinydrm_gem_cma_prime_import_sg_table(). Drivers
- * can use this as their &drm_driver->gem_free_object_unlocked callback.
- */
-void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj)
-{
-	if (gem_obj->import_attach) {
-		struct drm_gem_cma_object *cma_obj;
-
-		cma_obj = to_drm_gem_cma_obj(gem_obj);
-		dma_buf_vunmap(gem_obj->import_attach->dmabuf, cma_obj->vaddr);
-		cma_obj->vaddr = NULL;
-	}
-
-	drm_gem_cma_free_object(gem_obj);
-}
-EXPORT_SYMBOL_GPL(tinydrm_gem_cma_free_object);
+EXPORT_SYMBOL(tinydrm_fb_destroy);
 
 static struct drm_framebuffer *
 tinydrm_fb_create(struct drm_device *drm, struct drm_file *file_priv,
 		  const struct drm_mode_fb_cmd2 *mode_cmd)
 {
 	struct tinydrm_device *tdev = drm->dev_private;
+	struct drm_framebuffer *fb;
+	int ret;
 
-	return drm_gem_fb_create_with_funcs(drm, file_priv, mode_cmd,
-					    tdev->fb_funcs);
+	fb = drm_gem_fb_create_with_funcs(drm, file_priv, mode_cmd, tdev->fb_funcs);
+	if (IS_ERR(fb))
+		return fb;
+
+	ret = drm_gem_shmem_vmap(to_drm_gem_shmem_obj(fb->obj[0]));
+	if (ret) {
+		drm_gem_fb_destroy(fb);
+		return ERR_PTR(ret);
+	}
+
+	return fb;
 }
 
 static const struct drm_mode_config_funcs tinydrm_mode_config_funcs = {
diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
index dcd390163a4a..f9d35acff23d 100644
--- a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
+++ b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
@@ -9,12 +9,17 @@
 
 #include <linux/backlight.h>
 #include <linux/dma-buf.h>
+#include <linux/module.h>
 #include <linux/pm.h>
 #include <linux/spi/spi.h>
 #include <linux/swab.h>
 
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fourcc.h>
 #include <drm/tinydrm/tinydrm.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
+#include <drm/drm_print.h>
 
 static unsigned int spi_max;
 module_param(spi_max, uint, 0400);
diff --git a/drivers/gpu/drm/tinydrm/ili9225.c b/drivers/gpu/drm/tinydrm/ili9225.c
index 455fefe012f5..c24d6e4c834b 100644
--- a/drivers/gpu/drm/tinydrm/ili9225.c
+++ b/drivers/gpu/drm/tinydrm/ili9225.c
@@ -20,8 +20,11 @@
 #include <linux/spi/spi.h>
 #include <video/mipi_display.h>
 
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_shmem_helper.h>
 #include <drm/tinydrm/mipi-dbi.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
 
@@ -77,7 +80,8 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb,
 			    unsigned int color, struct drm_clip_rect *clips,
 			    unsigned int num_clips)
 {
-	struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+	struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0);
+	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem);
 	struct tinydrm_device *tdev = fb->dev->dev_private;
 	struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
 	bool swap = mipi->swap_bytes;
@@ -104,7 +108,7 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb,
 		if (ret)
 			return ret;
 	} else {
-		tr = cma_obj->vaddr;
+		tr = shmem->vaddr;
 	}
 
 	switch (mipi->rotation) {
@@ -157,7 +161,7 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb,
 }
 
 static const struct drm_framebuffer_funcs ili9225_fb_funcs = {
-	.destroy	= drm_gem_fb_destroy,
+	.destroy	= tinydrm_fb_destroy,
 	.create_handle	= drm_gem_fb_create_handle,
 	.dirty		= tinydrm_fb_dirty,
 };
@@ -361,13 +365,13 @@ static const struct drm_display_mode ili9225_mode = {
 	TINYDRM_MODE(176, 220, 35, 44),
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(ili9225_fops);
+DEFINE_DRM_GEM_SHMEM_FOPS(ili9225_fops);
 
 static struct drm_driver ili9225_driver = {
 	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
 				  DRIVER_ATOMIC,
 	.fops			= &ili9225_fops,
-	TINYDRM_GEM_DRIVER_OPS,
+	DRM_GEM_SHMEM_DRIVER_OPS,
 	.name			= "ili9225",
 	.desc			= "Ilitek ILI9225",
 	.date			= "20171106",
diff --git a/drivers/gpu/drm/tinydrm/ili9341.c b/drivers/gpu/drm/tinydrm/ili9341.c
index 6701037749a7..7a80f8e6d6f3 100644
--- a/drivers/gpu/drm/tinydrm/ili9341.c
+++ b/drivers/gpu/drm/tinydrm/ili9341.c
@@ -15,8 +15,10 @@
 #include <linux/property.h>
 #include <linux/spi/spi.h>
 
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_shmem_helper.h>
 #include <drm/drm_modeset_helper.h>
 #include <drm/tinydrm/mipi-dbi.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
@@ -139,12 +141,12 @@ static const struct drm_display_mode yx240qv29_mode = {
 	TINYDRM_MODE(240, 320, 37, 49),
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(ili9341_fops);
+DEFINE_DRM_GEM_SHMEM_FOPS(ili9341_fops);
 
 static struct drm_driver ili9341_driver = {
 	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC,
 	.fops			= &ili9341_fops,
-	TINYDRM_GEM_DRIVER_OPS,
+	DRM_GEM_SHMEM_DRIVER_OPS,
 	.debugfs_init		= mipi_dbi_debugfs_init,
 	.name			= "ili9341",
 	.desc			= "Ilitek ILI9341",
diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c
index d7bb4c5e6657..b5837a6b3633 100644
--- a/drivers/gpu/drm/tinydrm/mi0283qt.c
+++ b/drivers/gpu/drm/tinydrm/mi0283qt.c
@@ -17,9 +17,11 @@
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_modeset_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_shmem_helper.h>
 #include <drm/tinydrm/mipi-dbi.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
 #include <video/mipi_display.h>
@@ -147,13 +149,13 @@ static const struct drm_display_mode mi0283qt_mode = {
 	TINYDRM_MODE(320, 240, 58, 43),
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(mi0283qt_fops);
+DEFINE_DRM_GEM_SHMEM_FOPS(mi0283qt_fops);
 
 static struct drm_driver mi0283qt_driver = {
 	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
 				  DRIVER_ATOMIC,
 	.fops			= &mi0283qt_fops,
-	TINYDRM_GEM_DRIVER_OPS,
+	DRM_GEM_SHMEM_DRIVER_OPS,
 	.debugfs_init		= mipi_dbi_debugfs_init,
 	.name			= "mi0283qt",
 	.desc			= "Multi-Inno MI0283QT",
diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c
index cb3441e51d5f..e0f59177c2ef 100644
--- a/drivers/gpu/drm/tinydrm/mipi-dbi.c
+++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c
@@ -9,10 +9,15 @@
  * (at your option) any later version.
  */
 
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_shmem_helper.h>
 #include <drm/tinydrm/mipi-dbi.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
 #include <linux/debugfs.h>
+#include <linux/delay.h>
 #include <linux/dma-buf.h>
 #include <linux/gpio/consumer.h>
 #include <linux/module.h>
@@ -167,10 +172,11 @@ EXPORT_SYMBOL(mipi_dbi_command_buf);
 int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
 		      struct drm_clip_rect *clip, bool swap)
 {
-	struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-	struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
+	struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0);
+	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem);
+	struct dma_buf_attachment *import_attach = gem->import_attach;
 	struct drm_format_name_buf format_name;
-	void *src = cma_obj->vaddr;
+	void *src = shmem->vaddr;
 	int ret = 0;
 
 	if (import_attach) {
@@ -210,7 +216,8 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb,
 			     struct drm_clip_rect *clips,
 			     unsigned int num_clips)
 {
-	struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+	struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0);
+	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem);
 	struct tinydrm_device *tdev = fb->dev->dev_private;
 	struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
 	bool swap = mipi->swap_bytes;
@@ -235,7 +242,7 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb,
 		if (ret)
 			return ret;
 	} else {
-		tr = cma_obj->vaddr;
+		tr = shmem->vaddr;
 	}
 
 	mipi_dbi_command(mipi, MIPI_DCS_SET_COLUMN_ADDRESS,
@@ -252,7 +259,7 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb,
 }
 
 static const struct drm_framebuffer_funcs mipi_dbi_fb_funcs = {
-	.destroy	= drm_gem_fb_destroy,
+	.destroy	= tinydrm_fb_destroy,
 	.create_handle	= drm_gem_fb_create_handle,
 	.dirty		= tinydrm_fb_dirty,
 };
@@ -882,31 +889,12 @@ int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *mipi,
 {
 	size_t tx_size = tinydrm_spi_max_transfer_size(spi, 0);
 	struct device *dev = &spi->dev;
-	int ret;
 
 	if (tx_size < 16) {
 		DRM_ERROR("SPI transmit buffer too small: %zu\n", tx_size);
 		return -EINVAL;
 	}
 
-	/*
-	 * Even though it's not the SPI device that does DMA (the master does),
-	 * the dma mask is necessary for the dma_alloc_wc() in
-	 * drm_gem_cma_create(). The dma_addr returned will be a physical
-	 * adddress which might be different from the bus address, but this is
-	 * not a problem since the address will not be used.
-	 * The virtual address is used in the transfer and the SPI core
-	 * re-maps it on the SPI master device using the DMA streaming API
-	 * (spi_map_buf()).
-	 */
-	if (!dev->coherent_dma_mask) {
-		ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
-		if (ret) {
-			dev_warn(dev, "Failed to set dma mask %d\n", ret);
-			return ret;
-		}
-	}
-
 	mipi->spi = spi;
 	mipi->read_commands = mipi_dbi_dcs_read_commands;
 
diff --git a/drivers/gpu/drm/tinydrm/repaper.c b/drivers/gpu/drm/tinydrm/repaper.c
index 50a1d4216ce7..82d8c6bf0c91 100644
--- a/drivers/gpu/drm/tinydrm/repaper.c
+++ b/drivers/gpu/drm/tinydrm/repaper.c
@@ -26,7 +26,9 @@
 #include <linux/spi/spi.h>
 #include <linux/thermal.h>
 
+#include <drm/drm_drv.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_shmem_helper.h>
 #include <drm/tinydrm/tinydrm.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
 
@@ -526,8 +528,9 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb,
 			    struct drm_clip_rect *clips,
 			    unsigned int num_clips)
 {
-	struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-	struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
+	struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0);
+	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem);
+	struct dma_buf_attachment *import_attach = gem->import_attach;
 	struct tinydrm_device *tdev = fb->dev->dev_private;
 	struct repaper_epd *epd = epd_from_tinydrm(tdev);
 	struct drm_clip_rect clip;
@@ -559,7 +562,7 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb,
 			goto out_free;
 	}
 
-	tinydrm_xrgb8888_to_gray8(buf, cma_obj->vaddr, fb, &clip);
+	tinydrm_xrgb8888_to_gray8(buf, shmem->vaddr, fb, &clip);
 
 	if (import_attach) {
 		ret = dma_buf_end_cpu_access(import_attach->dmabuf,
@@ -624,7 +627,7 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb,
 }
 
 static const struct drm_framebuffer_funcs repaper_fb_funcs = {
-	.destroy	= drm_gem_fb_destroy,
+	.destroy	= tinydrm_fb_destroy,
 	.create_handle	= drm_gem_fb_create_handle,
 	.dirty		= tinydrm_fb_dirty,
 };
@@ -876,13 +879,13 @@ static const struct drm_display_mode repaper_e2271cs021_mode = {
 static const u8 repaper_e2271cs021_cs[] = { 0x00, 0x00, 0x00, 0x7f,
 					    0xff, 0xfe, 0x00, 0x00 };
 
-DEFINE_DRM_GEM_CMA_FOPS(repaper_fops);
+DEFINE_DRM_GEM_SHMEM_FOPS(repaper_fops);
 
 static struct drm_driver repaper_driver = {
 	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
 				  DRIVER_ATOMIC,
 	.fops			= &repaper_fops,
-	TINYDRM_GEM_DRIVER_OPS,
+	DRM_GEM_SHMEM_DRIVER_OPS,
 	.name			= "repaper",
 	.desc			= "Pervasive Displays RePaper e-ink panels",
 	.date			= "20170405",
@@ -929,15 +932,6 @@ static int repaper_probe(struct spi_device *spi)
 		model = spi_id->driver_data;
 	}
 
-	/* The SPI device is used to allocate dma memory */
-	if (!dev->coherent_dma_mask) {
-		ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
-		if (ret) {
-			dev_warn(dev, "Failed to set dma mask %d\n", ret);
-			return ret;
-		}
-	}
-
 	epd = devm_kzalloc(dev, sizeof(*epd), GFP_KERNEL);
 	if (!epd)
 		return -ENOMEM;
diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tinydrm/st7586.c
index 2fcbc3067d71..340c9be2613b 100644
--- a/drivers/gpu/drm/tinydrm/st7586.c
+++ b/drivers/gpu/drm/tinydrm/st7586.c
@@ -17,8 +17,10 @@
 #include <linux/spi/spi.h>
 #include <video/mipi_display.h>
 
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_shmem_helper.h>
 #include <drm/tinydrm/mipi-dbi.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
 
@@ -88,9 +90,10 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr,
 static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb,
 			   struct drm_clip_rect *clip)
 {
-	struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-	struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
-	void *src = cma_obj->vaddr;
+	struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0);
+	struct dma_buf_attachment *import_attach = gem->import_attach;
+	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem);
+	void *src = shmem->vaddr;
 	int ret = 0;
 
 	if (import_attach) {
@@ -156,7 +159,7 @@ static int st7586_fb_dirty(struct drm_framebuffer *fb,
 }
 
 static const struct drm_framebuffer_funcs st7586_fb_funcs = {
-	.destroy	= drm_gem_fb_destroy,
+	.destroy	= tinydrm_fb_destroy,
 	.create_handle	= drm_gem_fb_create_handle,
 	.dirty		= tinydrm_fb_dirty,
 };
@@ -297,13 +300,13 @@ static const struct drm_display_mode st7586_mode = {
 	TINYDRM_MODE(178, 128, 37, 27),
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(st7586_fops);
+DEFINE_DRM_GEM_SHMEM_FOPS(st7586_fops);
 
 static struct drm_driver st7586_driver = {
 	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
 				  DRIVER_ATOMIC,
 	.fops			= &st7586_fops,
-	TINYDRM_GEM_DRIVER_OPS,
+	DRM_GEM_SHMEM_DRIVER_OPS,
 	.debugfs_init		= mipi_dbi_debugfs_init,
 	.name			= "st7586",
 	.desc			= "Sitronix ST7586",
diff --git a/drivers/gpu/drm/tinydrm/st7735r.c b/drivers/gpu/drm/tinydrm/st7735r.c
index 3081bc57c116..1108088a1a03 100644
--- a/drivers/gpu/drm/tinydrm/st7735r.c
+++ b/drivers/gpu/drm/tinydrm/st7735r.c
@@ -14,8 +14,10 @@
 #include <linux/spi/spi.h>
 #include <video/mipi_display.h>
 
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_shmem_helper.h>
 #include <drm/tinydrm/mipi-dbi.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
 
@@ -113,13 +115,13 @@ static const struct drm_display_mode jd_t18003_t01_mode = {
 	TINYDRM_MODE(128, 160, 28, 35),
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(st7735r_fops);
+DEFINE_DRM_GEM_SHMEM_FOPS(st7735r_fops);
 
 static struct drm_driver st7735r_driver = {
 	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
 				  DRIVER_ATOMIC,
 	.fops			= &st7735r_fops,
-	TINYDRM_GEM_DRIVER_OPS,
+	DRM_GEM_SHMEM_DRIVER_OPS,
 	.debugfs_init		= mipi_dbi_debugfs_init,
 	.name			= "st7735r",
 	.desc			= "Sitronix ST7735R",
diff --git a/include/drm/tinydrm/tinydrm.h b/include/drm/tinydrm/tinydrm.h
index fe9827d0ca8a..e2cb254125c5 100644
--- a/include/drm/tinydrm/tinydrm.h
+++ b/include/drm/tinydrm/tinydrm.h
@@ -10,10 +10,15 @@
 #ifndef __LINUX_TINYDRM_H
 #define __LINUX_TINYDRM_H
 
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <linux/mutex.h>
 #include <drm/drm_simple_kms_helper.h>
 
+struct drm_driver;
+struct drm_framebuffer;
+struct drm_file;
+struct drm_clip_rect;
+struct drm_framebuffer_funcs;
+
 /**
  * struct tinydrm_device - tinydrm device
  */
@@ -53,27 +58,6 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe)
 	return container_of(pipe, struct tinydrm_device, pipe);
 }
 
-/**
- * TINYDRM_GEM_DRIVER_OPS - default tinydrm gem operations
- *
- * This macro provides a shortcut for setting the tinydrm GEM operations in
- * the &drm_driver structure.
- */
-#define TINYDRM_GEM_DRIVER_OPS \
-	.gem_free_object_unlocked = tinydrm_gem_cma_free_object, \
-	.gem_print_info		= drm_gem_cma_print_info, \
-	.gem_vm_ops		= &drm_gem_cma_vm_ops, \
-	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd, \
-	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle, \
-	.gem_prime_import	= drm_gem_prime_import, \
-	.gem_prime_export	= drm_gem_prime_export, \
-	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table, \
-	.gem_prime_import_sg_table = tinydrm_gem_cma_prime_import_sg_table, \
-	.gem_prime_vmap		= drm_gem_cma_prime_vmap, \
-	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap, \
-	.gem_prime_mmap		= drm_gem_cma_prime_mmap, \
-	.dumb_create		= drm_gem_cma_dumb_create
-
 /**
  * TINYDRM_MODE - tinydrm display mode
  * @hd: Horizontal resolution, width
@@ -97,11 +81,7 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe)
 	.type = DRM_MODE_TYPE_DRIVER, \
 	.clock = 1 /* pass validation */
 
-void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj);
-struct drm_gem_object *
-tinydrm_gem_cma_prime_import_sg_table(struct drm_device *drm,
-				      struct dma_buf_attachment *attach,
-				      struct sg_table *sgt);
+void tinydrm_fb_destroy(struct drm_framebuffer *fb);
 int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
 		      const struct drm_framebuffer_funcs *fb_funcs,
 		      struct drm_driver *driver);
-- 
2.15.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 1/2] drm: Add library for shmem backed GEM objects
  2018-09-11 12:43 ` [PATCH v3 1/2] drm: Add library for shmem backed GEM objects Noralf Trønnes
@ 2018-09-13  1:33   ` David Lechner
  2018-09-14 10:10     ` Eric Engestrom
  0 siblings, 1 reply; 13+ messages in thread
From: David Lechner @ 2018-09-13  1:33 UTC (permalink / raw)
  To: Noralf Trønnes, dri-devel; +Cc: sam

On 09/11/2018 07:43 AM, Noralf Trønnes wrote:
> This adds a library for shmem backed GEM objects with the necessary
> drm_driver callbacks.
> 
> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
> ---
> 

...

> +static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem)
> +{
> +	struct drm_gem_object *obj = &shmem->base;
> +	int ret;
> +
> +	if (shmem->vmap_use_count++ > 0)
> +		return 0;
> +
> +	ret = drm_gem_shmem_get_pages(shmem);
> +	if (ret)
> +		goto err_zero_use;
> +
> +	if (obj->import_attach) {
> +		shmem->vaddr = dma_buf_vmap(obj->import_attach->dmabuf);
> +	} else {
> +		pgprot_t prot;
> +
> +		switch (shmem->cache_mode) {
> +		case DRM_GEM_SHMEM_BO_UNKNOWN:
> +			DRM_DEBUG_KMS("Can't vmap cache mode is unknown\n");
> +			ret = -EINVAL;
> +			goto err_put_pages;
> +
> +		case DRM_GEM_SHMEM_BO_WRITECOMBINED:
> +			prot = pgprot_writecombine(PAGE_KERNEL);
> +			break;
> +
> +		case DRM_GEM_SHMEM_BO_UNCACHED:
> +			prot = pgprot_noncached(PAGE_KERNEL);
> +			break;
> +
> +		case DRM_GEM_SHMEM_BO_CACHED:
> +			prot = PAGE_KERNEL;
> +			break;
> +		}
> +
> +		shmem->vaddr = vmap(shmem->pages, obj->size >> PAGE_SHIFT, VM_MAP, prot);

I get a gcc warning here:

/home/david/work/ev3dev2/ev3dev-kernel/drivers/gpu/drm/drm_gem_shmem_helper.c:220:18: warning: ‘prot’ may be used uninitialized in this function [-Wmaybe-uninitialized]
    shmem->vaddr = vmap(shmem->pages, obj->size >> PAGE_SHIFT, VM_MAP, prot);
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/david/work/ev3dev2/ev3dev-kernel/drivers/gpu/drm/drm_gem_shmem_helper.c:199:12: note: ‘prot’ was declared here
    pgprot_t prot;
             ^~~~

---

And since I am making a comment anyway, it is not clear to me
what BO means in the enum names. I didn't see any hints in the
doc comments either.


> +	}
> +
> +	if (!shmem->vaddr) {
> +		DRM_DEBUG_KMS("Failed to vmap pages\n");
> +		ret = -ENOMEM;
> +		goto err_put_pages;
> +	}
> +
> +	return 0;
> +
> +err_put_pages:
> +	drm_gem_shmem_put_pages(shmem);
> +err_zero_use:
> +	shmem->vmap_use_count = 0;
> +
> +	return ret;
> +}
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 2/2] drm/tinydrm: Switch from CMA to shmem buffers
  2018-09-11 12:44 ` [PATCH v3 2/2] drm/tinydrm: Switch from CMA to shmem buffers Noralf Trønnes
@ 2018-09-13  1:35   ` David Lechner
  0 siblings, 0 replies; 13+ messages in thread
From: David Lechner @ 2018-09-13  1:35 UTC (permalink / raw)
  To: Noralf Trønnes, dri-devel; +Cc: sam

On 09/11/2018 07:44 AM, Noralf Trønnes wrote:
> This move makes tinydrm useful for more drivers. tinydrm doesn't need
> continuous memory, but at the time it was convenient to use the CMA
> library. The spi core can do dma on is_vmalloc() addresses making this
> possible.
> 
> Cc: David Lechner <david@lechnology.com>
> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
> ---

Acked-by: David Lechner <david@lechnology.com>
Tested-by: David Lechner <david@lechnology.com>

tested on st7586


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 1/2] drm: Add library for shmem backed GEM objects
  2018-09-13  1:33   ` David Lechner
@ 2018-09-14 10:10     ` Eric Engestrom
  2018-09-14 16:37       ` Noralf Trønnes
  0 siblings, 1 reply; 13+ messages in thread
From: Eric Engestrom @ 2018-09-14 10:10 UTC (permalink / raw)
  To: David Lechner; +Cc: sam, dri-devel

On Wednesday, 2018-09-12 20:33:32 -0500, David Lechner wrote:
> On 09/11/2018 07:43 AM, Noralf Trønnes wrote:
> > This adds a library for shmem backed GEM objects with the necessary
> > drm_driver callbacks.
> > 
> > Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
> > ---
> > 
> 
> ...
> 
> > +static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem)
> > +{
> > +	struct drm_gem_object *obj = &shmem->base;
> > +	int ret;
> > +
> > +	if (shmem->vmap_use_count++ > 0)
> > +		return 0;
> > +
> > +	ret = drm_gem_shmem_get_pages(shmem);
> > +	if (ret)
> > +		goto err_zero_use;
> > +
> > +	if (obj->import_attach) {
> > +		shmem->vaddr = dma_buf_vmap(obj->import_attach->dmabuf);
> > +	} else {
> > +		pgprot_t prot;
> > +
> > +		switch (shmem->cache_mode) {
> > +		case DRM_GEM_SHMEM_BO_UNKNOWN:
> > +			DRM_DEBUG_KMS("Can't vmap cache mode is unknown\n");
> > +			ret = -EINVAL;
> > +			goto err_put_pages;
> > +
> > +		case DRM_GEM_SHMEM_BO_WRITECOMBINED:
> > +			prot = pgprot_writecombine(PAGE_KERNEL);
> > +			break;
> > +
> > +		case DRM_GEM_SHMEM_BO_UNCACHED:
> > +			prot = pgprot_noncached(PAGE_KERNEL);
> > +			break;
> > +
> > +		case DRM_GEM_SHMEM_BO_CACHED:
> > +			prot = PAGE_KERNEL;
> > +			break;
> > +		}
> > +
> > +		shmem->vaddr = vmap(shmem->pages, obj->size >> PAGE_SHIFT, VM_MAP, prot);
> 
> I get a gcc warning here:
> 
> /home/david/work/ev3dev2/ev3dev-kernel/drivers/gpu/drm/drm_gem_shmem_helper.c:220:18: warning: ‘prot’ may be used uninitialized in this function [-Wmaybe-uninitialized]
>    shmem->vaddr = vmap(shmem->pages, obj->size >> PAGE_SHIFT, VM_MAP, prot);
>                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> /home/david/work/ev3dev2/ev3dev-kernel/drivers/gpu/drm/drm_gem_shmem_helper.c:199:12: note: ‘prot’ was declared here
>    pgprot_t prot;
>             ^~~~

This warning is saying that the vmap could be reached without hitting
any cases in the switch, which is technically true if one sets the
cache_mode to some garbage, but not if only existing enums from `enum
drm_gem_shmem_cache_mode` are used.

I think we should just add a `default:` next to the
DRM_GEM_SHMEM_BO_UNKNOWN case.

> 
> ---
> 
> And since I am making a comment anyway, it is not clear to me
> what BO means in the enum names. I didn't see any hints in the
> doc comments either.

Buffer Object, but yeah I guess it's not necessary in the enum names.

> 
> 
> > +	}
> > +
> > +	if (!shmem->vaddr) {
> > +		DRM_DEBUG_KMS("Failed to vmap pages\n");
> > +		ret = -ENOMEM;
> > +		goto err_put_pages;
> > +	}
> > +
> > +	return 0;
> > +
> > +err_put_pages:
> > +	drm_gem_shmem_put_pages(shmem);
> > +err_zero_use:
> > +	shmem->vmap_use_count = 0;
> > +
> > +	return ret;
> > +}
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 0/2] drm: Add shmem GEM library
  2018-09-11 12:43 [PATCH v3 0/2] drm: Add shmem GEM library Noralf Trønnes
  2018-09-11 12:43 ` [PATCH v3 1/2] drm: Add library for shmem backed GEM objects Noralf Trønnes
  2018-09-11 12:44 ` [PATCH v3 2/2] drm/tinydrm: Switch from CMA to shmem buffers Noralf Trønnes
@ 2018-09-14 15:48 ` Thomas Hellstrom
  2018-09-14 16:13   ` Daniel Vetter
  2 siblings, 1 reply; 13+ messages in thread
From: Thomas Hellstrom @ 2018-09-14 15:48 UTC (permalink / raw)
  To: Noralf Trønnes, dri-devel; +Cc: sam, david

Hi, Noralf,

On 09/11/2018 02:43 PM, Noralf Trønnes wrote:
> This patchset adds a library for shmem backed GEM objects and makes use
> of it in tinydrm.
>
> When I made tinydrm I used the CMA helper because it was very easy to
> use. July last year I learned that this limits which drivers to PRIME
> import from, since CMA requires continuous memory. tinydrm drivers don't
> require that. So I set out to change that looking first at shmem, but
> that wasn't working since shmem didn't work with fbdev deferred I/O.
> Then I did a vmalloc buffer attempt which worked with deferred I/O, but
> maybe wouldn't be of so much use as a library for other drivers to use.
> As my work to split out stuff from the CMA helper for shared use came to
> an end, I had a generic fbdev emulation that uses a shadow buffer for
> deferred I/O.
> This means that I can now use shmem buffers after all.
>
> I have looked at the other drivers that use drm_gem_get_pages() and
> several supports different cache modes so I've done that even though
> tinydrm only uses the cached one.
Out if interest, how can you use writecombine and uncached with shared 
memory?
as typically the linear kernel map of the affected pages also needs 
changing?

Thanks,
Thomas

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 0/2] drm: Add shmem GEM library
  2018-09-14 15:48 ` [PATCH v3 0/2] drm: Add shmem GEM library Thomas Hellstrom
@ 2018-09-14 16:13   ` Daniel Vetter
  2018-09-14 16:51     ` Noralf Trønnes
  0 siblings, 1 reply; 13+ messages in thread
From: Daniel Vetter @ 2018-09-14 16:13 UTC (permalink / raw)
  To: Thomas Hellstrom; +Cc: Sam Ravnborg, David Lechner, dri-devel

On Fri, Sep 14, 2018 at 5:48 PM, Thomas Hellstrom <thomas@shipmail.org> wrote:
> Hi, Noralf,
>
> On 09/11/2018 02:43 PM, Noralf Trønnes wrote:
>>
>> This patchset adds a library for shmem backed GEM objects and makes use
>> of it in tinydrm.
>>
>> When I made tinydrm I used the CMA helper because it was very easy to
>> use. July last year I learned that this limits which drivers to PRIME
>> import from, since CMA requires continuous memory. tinydrm drivers don't
>> require that. So I set out to change that looking first at shmem, but
>> that wasn't working since shmem didn't work with fbdev deferred I/O.
>> Then I did a vmalloc buffer attempt which worked with deferred I/O, but
>> maybe wouldn't be of so much use as a library for other drivers to use.
>> As my work to split out stuff from the CMA helper for shared use came to
>> an end, I had a generic fbdev emulation that uses a shadow buffer for
>> deferred I/O.
>> This means that I can now use shmem buffers after all.
>>
>> I have looked at the other drivers that use drm_gem_get_pages() and
>> several supports different cache modes so I've done that even though
>> tinydrm only uses the cached one.
>
> Out if interest, how can you use writecombine and uncached with shared
> memory?
> as typically the linear kernel map of the affected pages also needs
> changing?

I think on x86 at least the core code takes care of that. On arm, I'm
not sure this just works, since you can't change the mode of the
linear map. Instead you need specially allocated memory which is _not_
in the linear map. I guess arm boxes with pcie slots aren't that
common yet :-)
-Daniel

>
> Thanks,
> Thomas
>
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel



-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 1/2] drm: Add library for shmem backed GEM objects
  2018-09-14 10:10     ` Eric Engestrom
@ 2018-09-14 16:37       ` Noralf Trønnes
  0 siblings, 0 replies; 13+ messages in thread
From: Noralf Trønnes @ 2018-09-14 16:37 UTC (permalink / raw)
  To: Eric Engestrom, David Lechner; +Cc: sam, dri-devel


Den 14.09.2018 12.10, skrev Eric Engestrom:
> On Wednesday, 2018-09-12 20:33:32 -0500, David Lechner wrote:
>> On 09/11/2018 07:43 AM, Noralf Trønnes wrote:
>>> This adds a library for shmem backed GEM objects with the necessary
>>> drm_driver callbacks.
>>>
>>> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
>>> ---
>>>
>> ...
>>
>>> +static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem)
>>> +{
>>> +	struct drm_gem_object *obj = &shmem->base;
>>> +	int ret;
>>> +
>>> +	if (shmem->vmap_use_count++ > 0)
>>> +		return 0;
>>> +
>>> +	ret = drm_gem_shmem_get_pages(shmem);
>>> +	if (ret)
>>> +		goto err_zero_use;
>>> +
>>> +	if (obj->import_attach) {
>>> +		shmem->vaddr = dma_buf_vmap(obj->import_attach->dmabuf);
>>> +	} else {
>>> +		pgprot_t prot;
>>> +
>>> +		switch (shmem->cache_mode) {
>>> +		case DRM_GEM_SHMEM_BO_UNKNOWN:
>>> +			DRM_DEBUG_KMS("Can't vmap cache mode is unknown\n");
>>> +			ret = -EINVAL;
>>> +			goto err_put_pages;
>>> +
>>> +		case DRM_GEM_SHMEM_BO_WRITECOMBINED:
>>> +			prot = pgprot_writecombine(PAGE_KERNEL);
>>> +			break;
>>> +
>>> +		case DRM_GEM_SHMEM_BO_UNCACHED:
>>> +			prot = pgprot_noncached(PAGE_KERNEL);
>>> +			break;
>>> +
>>> +		case DRM_GEM_SHMEM_BO_CACHED:
>>> +			prot = PAGE_KERNEL;
>>> +			break;
>>> +		}
>>> +
>>> +		shmem->vaddr = vmap(shmem->pages, obj->size >> PAGE_SHIFT, VM_MAP, prot);
>> I get a gcc warning here:
>>
>> /home/david/work/ev3dev2/ev3dev-kernel/drivers/gpu/drm/drm_gem_shmem_helper.c:220:18: warning: ‘prot’ may be used uninitialized in this function [-Wmaybe-uninitialized]
>>     shmem->vaddr = vmap(shmem->pages, obj->size >> PAGE_SHIFT, VM_MAP, prot);
>>                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> /home/david/work/ev3dev2/ev3dev-kernel/drivers/gpu/drm/drm_gem_shmem_helper.c:199:12: note: ‘prot’ was declared here
>>     pgprot_t prot;
>>              ^~~~
> This warning is saying that the vmap could be reached without hitting
> any cases in the switch, which is technically true if one sets the
> cache_mode to some garbage, but not if only existing enums from `enum
> drm_gem_shmem_cache_mode` are used.
>
> I think we should just add a `default:` next to the
> DRM_GEM_SHMEM_BO_UNKNOWN case.
>
>> ---
>>
>> And since I am making a comment anyway, it is not clear to me
>> what BO means in the enum names. I didn't see any hints in the
>> doc comments either.
> Buffer Object, but yeah I guess it's not necessary in the enum names.

Yeah, the helper was called drm_shem_bo_helper in an earlier version,
forgot to remove the BO from the enum.

Noralf.

>>
>>> +	}
>>> +
>>> +	if (!shmem->vaddr) {
>>> +		DRM_DEBUG_KMS("Failed to vmap pages\n");
>>> +		ret = -ENOMEM;
>>> +		goto err_put_pages;
>>> +	}
>>> +
>>> +	return 0;
>>> +
>>> +err_put_pages:
>>> +	drm_gem_shmem_put_pages(shmem);
>>> +err_zero_use:
>>> +	shmem->vmap_use_count = 0;
>>> +
>>> +	return ret;
>>> +}
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 0/2] drm: Add shmem GEM library
  2018-09-14 16:13   ` Daniel Vetter
@ 2018-09-14 16:51     ` Noralf Trønnes
  2018-09-14 17:11       ` Thomas Hellstrom
  0 siblings, 1 reply; 13+ messages in thread
From: Noralf Trønnes @ 2018-09-14 16:51 UTC (permalink / raw)
  To: Daniel Vetter, Thomas Hellstrom; +Cc: Sam Ravnborg, David Lechner, dri-devel


Den 14.09.2018 18.13, skrev Daniel Vetter:
> On Fri, Sep 14, 2018 at 5:48 PM, Thomas Hellstrom <thomas@shipmail.org> wrote:
>> Hi, Noralf,
>>
>> On 09/11/2018 02:43 PM, Noralf Trønnes wrote:
>>> This patchset adds a library for shmem backed GEM objects and makes use
>>> of it in tinydrm.
>>>
>>> When I made tinydrm I used the CMA helper because it was very easy to
>>> use. July last year I learned that this limits which drivers to PRIME
>>> import from, since CMA requires continuous memory. tinydrm drivers don't
>>> require that. So I set out to change that looking first at shmem, but
>>> that wasn't working since shmem didn't work with fbdev deferred I/O.
>>> Then I did a vmalloc buffer attempt which worked with deferred I/O, but
>>> maybe wouldn't be of so much use as a library for other drivers to use.
>>> As my work to split out stuff from the CMA helper for shared use came to
>>> an end, I had a generic fbdev emulation that uses a shadow buffer for
>>> deferred I/O.
>>> This means that I can now use shmem buffers after all.
>>>
>>> I have looked at the other drivers that use drm_gem_get_pages() and
>>> several supports different cache modes so I've done that even though
>>> tinydrm only uses the cached one.
>> Out if interest, how can you use writecombine and uncached with shared
>> memory?
>> as typically the linear kernel map of the affected pages also needs
>> changing?
> I think on x86 at least the core code takes care of that. On arm, I'm
> not sure this just works, since you can't change the mode of the
> linear map. Instead you need specially allocated memory which is _not_
> in the linear map. I guess arm boxes with pcie slots aren't that
> common yet :-)

I was hoping to get some feedback on these cache mode flags.

These drivers use them:
   udl/udl_gem.c
   omapdrm/omap_gem.c
   msm/msm_gem.c
   etnaviv/etnaviv_gem.c

I don't know if they make sense or not, so any help is appreciated.

Noralf.

> -Daniel
>
>> Thanks,
>> Thomas
>>
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>
>

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 0/2] drm: Add shmem GEM library
  2018-09-14 16:51     ` Noralf Trønnes
@ 2018-09-14 17:11       ` Thomas Hellstrom
  2018-09-14 18:09         ` Noralf Trønnes
  0 siblings, 1 reply; 13+ messages in thread
From: Thomas Hellstrom @ 2018-09-14 17:11 UTC (permalink / raw)
  To: Noralf Trønnes, Daniel Vetter; +Cc: Sam Ravnborg, David Lechner, dri-devel

On 09/14/2018 06:51 PM, Noralf Trønnes wrote:
>
> Den 14.09.2018 18.13, skrev Daniel Vetter:
>> On Fri, Sep 14, 2018 at 5:48 PM, Thomas Hellstrom 
>> <thomas@shipmail.org> wrote:
>>> Hi, Noralf,
>>>
>>> On 09/11/2018 02:43 PM, Noralf Trønnes wrote:
>>>> This patchset adds a library for shmem backed GEM objects and makes 
>>>> use
>>>> of it in tinydrm.
>>>>
>>>> When I made tinydrm I used the CMA helper because it was very easy to
>>>> use. July last year I learned that this limits which drivers to PRIME
>>>> import from, since CMA requires continuous memory. tinydrm drivers 
>>>> don't
>>>> require that. So I set out to change that looking first at shmem, but
>>>> that wasn't working since shmem didn't work with fbdev deferred I/O.
>>>> Then I did a vmalloc buffer attempt which worked with deferred I/O, 
>>>> but
>>>> maybe wouldn't be of so much use as a library for other drivers to 
>>>> use.
>>>> As my work to split out stuff from the CMA helper for shared use 
>>>> came to
>>>> an end, I had a generic fbdev emulation that uses a shadow buffer for
>>>> deferred I/O.
>>>> This means that I can now use shmem buffers after all.
>>>>
>>>> I have looked at the other drivers that use drm_gem_get_pages() and
>>>> several supports different cache modes so I've done that even though
>>>> tinydrm only uses the cached one.
>>> Out if interest, how can you use writecombine and uncached with shared
>>> memory?
>>> as typically the linear kernel map of the affected pages also needs
>>> changing?
>> I think on x86 at least the core code takes care of that. On arm, I'm
>> not sure this just works, since you can't change the mode of the
>> linear map. Instead you need specially allocated memory which is _not_
>> in the linear map. I guess arm boxes with pcie slots aren't that
>> common yet :-)
>
> I was hoping to get some feedback on these cache mode flags.
>
> These drivers use them:
>   udl/udl_gem.c
>   omapdrm/omap_gem.c
>   msm/msm_gem.c
>   etnaviv/etnaviv_gem.c
>
> I don't know if they make sense or not, so any help is appreciated.

It's possible, as Daniel says, that the X86 PAT system now automatically 
tracks all pte inserts and changes the linear kernel map accordingly. It 
certainly didn't use to do that, so for example TTM does that 
explicitly. And it's a very slow operation since it involves a global 
cache- and TLB flush across all cores. So if PAT is doing that on a 
per-page basis, it's probably bound to be very slow.

The concern with shmem (last time I looked which was a couple of years 
ago, i admit) was that shmem needs the linear kernel map to copy data in 
and out when swapping and on hibernate. If the above drivers that you 
mention don't use shmem, that's all fine, but the combination of shmem 
and special memory that is NOT mapped in the kernel memory does look a 
bit odd to me.

/Thomas


>
> Noralf.
>
>> -Daniel
>>
>>> Thanks,
>>> Thomas
>>>
>>>
>>> _______________________________________________
>>> dri-devel mailing list
>>> dri-devel@lists.freedesktop.org
>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>>
>>

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 0/2] drm: Add shmem GEM library
  2018-09-14 17:11       ` Thomas Hellstrom
@ 2018-09-14 18:09         ` Noralf Trønnes
  2018-09-14 20:13           ` Thomas Hellstrom
  0 siblings, 1 reply; 13+ messages in thread
From: Noralf Trønnes @ 2018-09-14 18:09 UTC (permalink / raw)
  To: Thomas Hellstrom, Daniel Vetter; +Cc: Sam Ravnborg, David Lechner, dri-devel


Den 14.09.2018 19.11, skrev Thomas Hellstrom:
> On 09/14/2018 06:51 PM, Noralf Trønnes wrote:
>>
>> Den 14.09.2018 18.13, skrev Daniel Vetter:
>>> On Fri, Sep 14, 2018 at 5:48 PM, Thomas Hellstrom 
>>> <thomas@shipmail.org> wrote:
>>>> Hi, Noralf,
>>>>
>>>> On 09/11/2018 02:43 PM, Noralf Trønnes wrote:
>>>>> This patchset adds a library for shmem backed GEM objects and 
>>>>> makes use
>>>>> of it in tinydrm.
>>>>>
>>>>> When I made tinydrm I used the CMA helper because it was very easy to
>>>>> use. July last year I learned that this limits which drivers to PRIME
>>>>> import from, since CMA requires continuous memory. tinydrm drivers 
>>>>> don't
>>>>> require that. So I set out to change that looking first at shmem, but
>>>>> that wasn't working since shmem didn't work with fbdev deferred I/O.
>>>>> Then I did a vmalloc buffer attempt which worked with deferred 
>>>>> I/O, but
>>>>> maybe wouldn't be of so much use as a library for other drivers to 
>>>>> use.
>>>>> As my work to split out stuff from the CMA helper for shared use 
>>>>> came to
>>>>> an end, I had a generic fbdev emulation that uses a shadow buffer for
>>>>> deferred I/O.
>>>>> This means that I can now use shmem buffers after all.
>>>>>
>>>>> I have looked at the other drivers that use drm_gem_get_pages() and
>>>>> several supports different cache modes so I've done that even though
>>>>> tinydrm only uses the cached one.
>>>> Out if interest, how can you use writecombine and uncached with shared
>>>> memory?
>>>> as typically the linear kernel map of the affected pages also needs
>>>> changing?
>>> I think on x86 at least the core code takes care of that. On arm, I'm
>>> not sure this just works, since you can't change the mode of the
>>> linear map. Instead you need specially allocated memory which is _not_
>>> in the linear map. I guess arm boxes with pcie slots aren't that
>>> common yet :-)
>>
>> I was hoping to get some feedback on these cache mode flags.
>>
>> These drivers use them:
>>   udl/udl_gem.c
>>   omapdrm/omap_gem.c
>>   msm/msm_gem.c
>>   etnaviv/etnaviv_gem.c
>>
>> I don't know if they make sense or not, so any help is appreciated.
>
> It's possible, as Daniel says, that the X86 PAT system now 
> automatically tracks all pte inserts and changes the linear kernel map 
> accordingly. It certainly didn't use to do that, so for example TTM 
> does that explicitly. And it's a very slow operation since it involves 
> a global cache- and TLB flush across all cores. So if PAT is doing 
> that on a per-page basis, it's probably bound to be very slow.
>
> The concern with shmem (last time I looked which was a couple of years 
> ago, i admit) was that shmem needs the linear kernel map to copy data 
> in and out when swapping and on hibernate. If the above drivers that 
> you mention don't use shmem, that's all fine, but the combination of 
> shmem and special memory that is NOT mapped in the kernel memory does 
> look a bit odd to me.
>

When I started writing this helper I first looked at udl which has
different cache modes, but only uses shmem. It does hardcode cache mode
to cached though. Based on what you say I'm starting to think that maybe
the udl GEM code was just copied from some other driver and not cleaned
up properly afterwards.

In addition to shmem, msm and etnaviv use vram and omap uses
dma_alloc_wc(). So the cache modes are for distinguishing the memory
types I suppose.

They all have this type of code in their *_mmap_obj() function (with the
same comment):

     if (msm_obj->flags & MSM_BO_WC) {
         vma->vm_page_prot = 
pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
     } else if (msm_obj->flags & MSM_BO_UNCACHED) {
         vma->vm_page_prot = 
pgprot_noncached(vm_get_page_prot(vma->vm_flags));
     } else {
         /*
          * Shunt off cached objs to shmem file so they have their own
          * address_space (so unmap_mapping_range does what we want,
          * in particular in the case of mmap'd dmabufs)
          */
         fput(vma->vm_file);
         get_file(obj->filp);
         vma->vm_pgoff = 0;
         vma->vm_file  = obj->filp;

         vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
     }

So now it's starting to make more sense to me. It seems that shmem is the
cached mode and that WC and uncached is used for the other memory types.

If I've understood this correctly, it means that I can just drop the
cache modes.

Thanks,
Noralf.

> /Thomas
>
>
>>
>> Noralf.
>>
>>> -Daniel
>>>
>>>> Thanks,
>>>> Thomas
>>>>
>>>>
>>>> _______________________________________________
>>>> dri-devel mailing list
>>>> dri-devel@lists.freedesktop.org
>>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>>>
>>>
>

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 0/2] drm: Add shmem GEM library
  2018-09-14 18:09         ` Noralf Trønnes
@ 2018-09-14 20:13           ` Thomas Hellstrom
  0 siblings, 0 replies; 13+ messages in thread
From: Thomas Hellstrom @ 2018-09-14 20:13 UTC (permalink / raw)
  To: Noralf Trønnes, Daniel Vetter; +Cc: Sam Ravnborg, David Lechner, dri-devel

Hi
On 09/14/2018 08:09 PM, Noralf Trønnes wrote:
>
> Den 14.09.2018 19.11, skrev Thomas Hellstrom:
>> On 09/14/2018 06:51 PM, Noralf Trønnes wrote:
>>>
>>> Den 14.09.2018 18.13, skrev Daniel Vetter:
>>>> On Fri, Sep 14, 2018 at 5:48 PM, Thomas Hellstrom 
>>>> <thomas@shipmail.org> wrote:
>>>>> Hi, Noralf,
>>>>>
>>>>> On 09/11/2018 02:43 PM, Noralf Trønnes wrote:
>>>>>> This patchset adds a library for shmem backed GEM objects and 
>>>>>> makes use
>>>>>> of it in tinydrm.
>>>>>>
>>>>>> When I made tinydrm I used the CMA helper because it was very 
>>>>>> easy to
>>>>>> use. July last year I learned that this limits which drivers to 
>>>>>> PRIME
>>>>>> import from, since CMA requires continuous memory. tinydrm 
>>>>>> drivers don't
>>>>>> require that. So I set out to change that looking first at shmem, 
>>>>>> but
>>>>>> that wasn't working since shmem didn't work with fbdev deferred I/O.
>>>>>> Then I did a vmalloc buffer attempt which worked with deferred 
>>>>>> I/O, but
>>>>>> maybe wouldn't be of so much use as a library for other drivers 
>>>>>> to use.
>>>>>> As my work to split out stuff from the CMA helper for shared use 
>>>>>> came to
>>>>>> an end, I had a generic fbdev emulation that uses a shadow buffer 
>>>>>> for
>>>>>> deferred I/O.
>>>>>> This means that I can now use shmem buffers after all.
>>>>>>
>>>>>> I have looked at the other drivers that use drm_gem_get_pages() and
>>>>>> several supports different cache modes so I've done that even though
>>>>>> tinydrm only uses the cached one.
>>>>> Out if interest, how can you use writecombine and uncached with 
>>>>> shared
>>>>> memory?
>>>>> as typically the linear kernel map of the affected pages also needs
>>>>> changing?
>>>> I think on x86 at least the core code takes care of that. On arm, I'm
>>>> not sure this just works, since you can't change the mode of the
>>>> linear map. Instead you need specially allocated memory which is _not_
>>>> in the linear map. I guess arm boxes with pcie slots aren't that
>>>> common yet :-)
>>>
>>> I was hoping to get some feedback on these cache mode flags.
>>>
>>> These drivers use them:
>>>   udl/udl_gem.c
>>>   omapdrm/omap_gem.c
>>>   msm/msm_gem.c
>>>   etnaviv/etnaviv_gem.c
>>>
>>> I don't know if they make sense or not, so any help is appreciated.
>>
>> It's possible, as Daniel says, that the X86 PAT system now 
>> automatically tracks all pte inserts and changes the linear kernel 
>> map accordingly. It certainly didn't use to do that, so for example 
>> TTM does that explicitly. And it's a very slow operation since it 
>> involves a global cache- and TLB flush across all cores. So if PAT is 
>> doing that on a per-page basis, it's probably bound to be very slow.
>>
>> The concern with shmem (last time I looked which was a couple of 
>> years ago, i admit) was that shmem needs the linear kernel map to 
>> copy data in and out when swapping and on hibernate. If the above 
>> drivers that you mention don't use shmem, that's all fine, but the 
>> combination of shmem and special memory that is NOT mapped in the 
>> kernel memory does look a bit odd to me.
>>
>
> When I started writing this helper I first looked at udl which has
> different cache modes, but only uses shmem. It does hardcode cache mode
> to cached though. Based on what you say I'm starting to think that maybe
> the udl GEM code was just copied from some other driver and not cleaned
> up properly afterwards.
>
> In addition to shmem, msm and etnaviv use vram and omap uses
> dma_alloc_wc(). So the cache modes are for distinguishing the memory
> types I suppose.
>
> They all have this type of code in their *_mmap_obj() function (with the
> same comment):
>
>     if (msm_obj->flags & MSM_BO_WC) {
>         vma->vm_page_prot = 
> pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
>     } else if (msm_obj->flags & MSM_BO_UNCACHED) {
>         vma->vm_page_prot = 
> pgprot_noncached(vm_get_page_prot(vma->vm_flags));
>     } else {
>         /*
>          * Shunt off cached objs to shmem file so they have their own
>          * address_space (so unmap_mapping_range does what we want,
>          * in particular in the case of mmap'd dmabufs)
>          */
>         fput(vma->vm_file);
>         get_file(obj->filp);
>         vma->vm_pgoff = 0;
>         vma->vm_file  = obj->filp;
>
>         vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
>     }
>
> So now it's starting to make more sense to me. It seems that shmem is the
> cached mode and that WC and uncached is used for the other memory types.
>
> If I've understood this correctly, it means that I can just drop the
> cache modes.
>

Yes, I think that might be a good idea, at least until there is a clear 
understanding how and if the linear kernel map is handled, and it's 
probably different on each architecture.  Best would of course be if we 
were allowed to set up different mappings to a page with conflicting 
cache modes...

/Thomas




> Thanks,
> Noralf.
>
>> /Thomas
>>
>>
>>>
>>> Noralf.
>>>
>>>> -Daniel
>>>>
>>>>> Thanks,
>>>>> Thomas
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> dri-devel mailing list
>>>>> dri-devel@lists.freedesktop.org
>>>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>>>>
>>>>
>>

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

end of thread, other threads:[~2018-09-14 20:13 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-11 12:43 [PATCH v3 0/2] drm: Add shmem GEM library Noralf Trønnes
2018-09-11 12:43 ` [PATCH v3 1/2] drm: Add library for shmem backed GEM objects Noralf Trønnes
2018-09-13  1:33   ` David Lechner
2018-09-14 10:10     ` Eric Engestrom
2018-09-14 16:37       ` Noralf Trønnes
2018-09-11 12:44 ` [PATCH v3 2/2] drm/tinydrm: Switch from CMA to shmem buffers Noralf Trønnes
2018-09-13  1:35   ` David Lechner
2018-09-14 15:48 ` [PATCH v3 0/2] drm: Add shmem GEM library Thomas Hellstrom
2018-09-14 16:13   ` Daniel Vetter
2018-09-14 16:51     ` Noralf Trønnes
2018-09-14 17:11       ` Thomas Hellstrom
2018-09-14 18:09         ` Noralf Trønnes
2018-09-14 20:13           ` Thomas Hellstrom

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.