From: Thomas Zimmermann <tzimmermann@suse.de>
To: daniel@ffwll.ch, noralf@tronnes.org, airlied@linux.ie,
rong.a.chen@intel.com, feng.tang@intel.com, ying.huang@intel.com,
sean@poorly.run, maxime.ripard@bootlin.com,
maarten.lankhorst@linux.intel.com, dave@stgolabs.net
Cc: Thomas Zimmermann <tzimmermann@suse.de>, dri-devel@lists.freedesktop.org
Subject: [PATCH v2 1/3] drm/vram: Add kmap ref-counting to GEM VRAM objects
Date: Wed, 4 Sep 2019 13:56:42 +0200 [thread overview]
Message-ID: <20190904115644.7620-2-tzimmermann@suse.de> (raw)
In-Reply-To: <20190904115644.7620-1-tzimmermann@suse.de>
The kmap and kunmap operations of GEM VRAM buffers can now be called
in interleaving pairs. The first call to drm_gem_vram_kmap() maps the
buffer's memory to kernel address space and the final call to
drm_gem_vram_kunmap() unmaps the memory. Intermediate calls to these
functions increment or decrement a reference counter.
This change allows for keeping buffer memory mapped for longer and
minimizes the amount of changes to TLB, page tables, etc.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Davidlohr Bueso <dave@stgolabs.net>
---
drivers/gpu/drm/drm_gem_vram_helper.c | 74 ++++++++++++++++++++-------
include/drm/drm_gem_vram_helper.h | 19 +++++++
2 files changed, 75 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c
index fd751078bae1..6c7912092876 100644
--- a/drivers/gpu/drm/drm_gem_vram_helper.c
+++ b/drivers/gpu/drm/drm_gem_vram_helper.c
@@ -26,7 +26,11 @@ static void drm_gem_vram_cleanup(struct drm_gem_vram_object *gbo)
* TTM buffer object in 'bo' has already been cleaned
* up; only release the GEM object.
*/
+
+ WARN_ON(gbo->kmap_use_count);
+
drm_gem_object_release(&gbo->bo.base);
+ mutex_destroy(&gbo->kmap_lock);
}
static void drm_gem_vram_destroy(struct drm_gem_vram_object *gbo)
@@ -100,6 +104,8 @@ static int drm_gem_vram_init(struct drm_device *dev,
if (ret)
goto err_drm_gem_object_release;
+ mutex_init(&gbo->kmap_lock);
+
return 0;
err_drm_gem_object_release:
@@ -283,6 +289,34 @@ int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo)
}
EXPORT_SYMBOL(drm_gem_vram_unpin);
+static void *drm_gem_vram_kmap_locked(struct drm_gem_vram_object *gbo,
+ bool map, bool *is_iomem)
+{
+ int ret;
+ struct ttm_bo_kmap_obj *kmap = &gbo->kmap;
+
+ if (gbo->kmap_use_count > 0)
+ goto out;
+
+ if (kmap->virtual || !map)
+ goto out;
+
+ ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, kmap);
+ if (ret)
+ return ERR_PTR(ret);
+
+out:
+ if (!kmap->virtual) {
+ if (is_iomem)
+ *is_iomem = false;
+ return NULL; /* not mapped; don't increment ref */
+ }
+ ++gbo->kmap_use_count;
+ if (is_iomem)
+ return ttm_kmap_obj_virtual(kmap, is_iomem);
+ return kmap->virtual;
+}
+
/**
* drm_gem_vram_kmap() - Maps a GEM VRAM object into kernel address space
* @gbo: the GEM VRAM object
@@ -304,40 +338,44 @@ void *drm_gem_vram_kmap(struct drm_gem_vram_object *gbo, bool map,
bool *is_iomem)
{
int ret;
- struct ttm_bo_kmap_obj *kmap = &gbo->kmap;
-
- if (kmap->virtual || !map)
- goto out;
+ void *virtual;
- ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, kmap);
+ ret = mutex_lock_interruptible(&gbo->kmap_lock);
if (ret)
return ERR_PTR(ret);
+ virtual = drm_gem_vram_kmap_locked(gbo, map, is_iomem);
+ mutex_unlock(&gbo->kmap_lock);
-out:
- if (!is_iomem)
- return kmap->virtual;
- if (!kmap->virtual) {
- *is_iomem = false;
- return NULL;
- }
- return ttm_kmap_obj_virtual(kmap, is_iomem);
+ return virtual;
}
EXPORT_SYMBOL(drm_gem_vram_kmap);
-/**
- * drm_gem_vram_kunmap() - Unmaps a GEM VRAM object
- * @gbo: the GEM VRAM object
- */
-void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo)
+static void drm_gem_vram_kunmap_locked(struct drm_gem_vram_object *gbo)
{
struct ttm_bo_kmap_obj *kmap = &gbo->kmap;
+ if (WARN_ON_ONCE(!gbo->kmap_use_count))
+ return;
+ if (--gbo->kmap_use_count > 0)
+ return;
+
if (!kmap->virtual)
return;
ttm_bo_kunmap(kmap);
kmap->virtual = NULL;
}
+
+/**
+ * drm_gem_vram_kunmap() - Unmaps a GEM VRAM object
+ * @gbo: the GEM VRAM object
+ */
+void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo)
+{
+ mutex_lock(&gbo->kmap_lock);
+ drm_gem_vram_kunmap_locked(gbo);
+ mutex_unlock(&gbo->kmap_lock);
+}
EXPORT_SYMBOL(drm_gem_vram_kunmap);
/**
diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h
index ac217d768456..8c08bc87b788 100644
--- a/include/drm/drm_gem_vram_helper.h
+++ b/include/drm/drm_gem_vram_helper.h
@@ -34,11 +34,30 @@ struct vm_area_struct;
* backed by VRAM. It can be used for simple framebuffer devices with
* dedicated memory. The buffer object can be evicted to system memory if
* video memory becomes scarce.
+ *
+ * GEM VRAM objects perform reference counting for pin and mapping
+ * operations. So a buffer object that has been pinned N times with
+ * drm_gem_vram_pin() must be unpinned N times with
+ * drm_gem_vram_unpin(). The same applies to pairs of
+ * drm_gem_vram_kmap() and drm_gem_vram_kunmap().
*/
struct drm_gem_vram_object {
struct ttm_buffer_object bo;
struct ttm_bo_kmap_obj kmap;
+ /**
+ * @kmap_lock: Protects the kmap address and use count
+ */
+ struct mutex kmap_lock;
+
+ /**
+ * @kmap_use_count:
+ *
+ * Reference count on the virtual address.
+ * The address are un-mapped when the count reaches zero.
+ */
+ unsigned int kmap_use_count;
+
/* Supported placements are %TTM_PL_VRAM and %TTM_PL_SYSTEM */
struct ttm_placement placement;
struct ttm_place placements[2];
--
2.23.0
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
next prev parent reply other threads:[~2019-09-04 11:56 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-09-04 11:56 [PATCH v2 0/3] ast, mgag200: Map console BO while it's being displayed Thomas Zimmermann
2019-09-04 11:56 ` Thomas Zimmermann [this message]
2019-09-05 6:18 ` [PATCH v2 1/3] drm/vram: Add kmap ref-counting to GEM VRAM objects Gerd Hoffmann
2019-09-04 11:56 ` [PATCH v2 2/3] drm/ast: Map fbdev framebuffer while it's being displayed Thomas Zimmermann
2019-09-05 6:25 ` Gerd Hoffmann
2019-09-04 11:56 ` [PATCH v2 3/3] drm/mgag200: " Thomas Zimmermann
2019-09-11 16:13 ` Deucher, Alexander
2019-09-04 12:13 ` [PATCH v2 0/3] ast, mgag200: Map console BO " Daniel Vetter
2019-09-04 17:14 ` Davidlohr Bueso
2019-09-04 18:43 ` Daniel Vetter
2019-09-05 7:00 ` Gerd Hoffmann
2019-09-05 7:56 ` Daniel Vetter
2019-09-05 8:19 ` Thomas Zimmermann
2019-09-05 9:29 ` Gerd Hoffmann
2019-09-06 8:10 ` Thomas Zimmermann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190904115644.7620-2-tzimmermann@suse.de \
--to=tzimmermann@suse.de \
--cc=airlied@linux.ie \
--cc=daniel@ffwll.ch \
--cc=dave@stgolabs.net \
--cc=dri-devel@lists.freedesktop.org \
--cc=feng.tang@intel.com \
--cc=maarten.lankhorst@linux.intel.com \
--cc=maxime.ripard@bootlin.com \
--cc=noralf@tronnes.org \
--cc=rong.a.chen@intel.com \
--cc=sean@poorly.run \
--cc=ying.huang@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox