A first version of this work had been sent by Tomi Valkeinen in may 2017 (https://www.spinics.net/lists/dri-devel/msg140663.html).
This series adds a few new OMAP_BO flags to help the userspace manage situations where it needs to use lots of buffers, and would currently run out of TILER space. The TILER space is limited to mapping 128MB at any given time and some applications might need more.
This seres is also the opportunity to do some cleanup in the flags and improve the comments describing them.
The user-space patches for libdrm, although ready, haven't been posted yet. It will be be done when this series have been discussed and hopefully in the process of getting merged.
JJ
changes in v2: - fixed build error that crept in during rebase before sending (sorry about that) - rework the refcount part a bit.
Jean-Jacques Hiblot (1): drm/omap: use refcount API to track the number of users of dma_addr
Tomi Valkeinen (7): drm/omap: add omap_gem_unpin_locked() drm/omap: accept NULL for dma_addr in omap_gem_pin drm/omap: cleanup OMAP_BO flags drm/omap: remove OMAP_BO_TILED define drm/omap: cleanup OMAP_BO_SCANOUT use drm/omap: add omap_gem_validate_flags() drm/omap: add OMAP_BO flags to affect buffer allocation
drivers/gpu/drm/omapdrm/omap_dmm_tiler.h | 2 +- drivers/gpu/drm/omapdrm/omap_fb.c | 6 +- drivers/gpu/drm/omapdrm/omap_gem.c | 162 +++++++++++++++------- drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c | 2 +- include/uapi/drm/omap_drm.h | 27 ++-- 5 files changed, 136 insertions(+), 63 deletions(-)
This would give us a WARN_ON() if the pin/unpin calls are unbalanced.
Proposed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com --- drivers/gpu/drm/omapdrm/omap_gem.c | 45 +++++++++++++++--------------- 1 file changed, 23 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 37378dbc50d0..0b6eef120cc9 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -65,7 +65,7 @@ struct omap_gem_object { /** * # of users of dma_addr */ - u32 dma_addr_cnt; + refcount_t dma_addr_cnt;
/** * If the buffer has been imported from a dmabuf the OMAP_DB_DMABUF flag @@ -771,13 +771,15 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) mutex_lock(&omap_obj->lock);
if (!omap_gem_is_contiguous(omap_obj) && priv->has_dmm) { - if (omap_obj->dma_addr_cnt == 0) { + if (refcount_read(&omap_obj->dma_addr_cnt) == 0) { u32 npages = obj->size >> PAGE_SHIFT; enum tiler_fmt fmt = gem2fmt(omap_obj->flags); struct tiler_block *block;
BUG_ON(omap_obj->block);
+ refcount_set(&omap_obj->dma_addr_cnt, 1); + ret = omap_gem_attach_pages(obj); if (ret) goto fail; @@ -811,10 +813,10 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) omap_obj->block = block;
DBG("got dma address: %pad", &omap_obj->dma_addr); + } else { + refcount_inc(&omap_obj->dma_addr_cnt); }
- omap_obj->dma_addr_cnt++; - *dma_addr = omap_obj->dma_addr; } else if (omap_gem_is_contiguous(omap_obj)) { *dma_addr = omap_obj->dma_addr; @@ -844,23 +846,21 @@ void omap_gem_unpin(struct drm_gem_object *obj)
mutex_lock(&omap_obj->lock);
- if (omap_obj->dma_addr_cnt > 0) { - omap_obj->dma_addr_cnt--; - if (omap_obj->dma_addr_cnt == 0) { - ret = tiler_unpin(omap_obj->block); - if (ret) { - dev_err(obj->dev->dev, - "could not unpin pages: %d\n", ret); - } - ret = tiler_release(omap_obj->block); - if (ret) { - dev_err(obj->dev->dev, - "could not release unmap: %d\n", ret); - } - omap_obj->dma_addr = 0; - omap_obj->block = NULL; + if (refcount_dec_and_test(&omap_obj->dma_addr_cnt)) { + ret = tiler_unpin(omap_obj->block); + if (ret) { + dev_err(obj->dev->dev, + "could not unpin pages: %d\n", ret); } + ret = tiler_release(omap_obj->block); + if (ret) { + dev_err(obj->dev->dev, + "could not release unmap: %d\n", ret); + } + omap_obj->dma_addr = 0; + omap_obj->block = NULL; } +}
mutex_unlock(&omap_obj->lock); } @@ -877,7 +877,7 @@ int omap_gem_rotated_dma_addr(struct drm_gem_object *obj, u32 orient,
mutex_lock(&omap_obj->lock);
- if ((omap_obj->dma_addr_cnt > 0) && omap_obj->block && + if ((refcount_read(&omap_obj->dma_addr_cnt) > 0) && omap_obj->block && (omap_obj->flags & OMAP_BO_TILED)) { *dma_addr = tiler_tsptr(omap_obj->block, orient, x, y); ret = 0; @@ -1028,7 +1028,8 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
seq_printf(m, "%08x: %2d (%2d) %08llx %pad (%2d) %p %4d", omap_obj->flags, obj->name, kref_read(&obj->refcount), - off, &omap_obj->dma_addr, omap_obj->dma_addr_cnt, + off, &omap_obj->dma_addr, + refcount_read(&omap_obj->dma_addr_cnt), omap_obj->vaddr, omap_obj->roll);
if (omap_obj->flags & OMAP_BO_TILED) { @@ -1091,7 +1092,7 @@ void omap_gem_free_object(struct drm_gem_object *obj) mutex_lock(&omap_obj->lock);
/* The object should not be pinned. */ - WARN_ON(omap_obj->dma_addr_cnt > 0); + WARN_ON(refcount_read(&omap_obj->dma_addr_cnt) > 0);
if (omap_obj->pages) { if (omap_obj->flags & OMAP_BO_MEM_DMABUF)
On 08/07/2019 13:45, Jean-Jacques Hiblot wrote:
This would give us a WARN_ON() if the pin/unpin calls are unbalanced.
Proposed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com
drivers/gpu/drm/omapdrm/omap_gem.c | 45 +++++++++++++++--------------- 1 file changed, 23 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 37378dbc50d0..0b6eef120cc9 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -65,7 +65,7 @@ struct omap_gem_object { /** * # of users of dma_addr */
- u32 dma_addr_cnt;
refcount_t dma_addr_cnt;
/**
- If the buffer has been imported from a dmabuf the OMAP_DB_DMABUF flag
@@ -771,13 +771,15 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) mutex_lock(&omap_obj->lock);
if (!omap_gem_is_contiguous(omap_obj) && priv->has_dmm) {
if (omap_obj->dma_addr_cnt == 0) {
if (refcount_read(&omap_obj->dma_addr_cnt) == 0) { u32 npages = obj->size >> PAGE_SHIFT; enum tiler_fmt fmt = gem2fmt(omap_obj->flags); struct tiler_block *block; BUG_ON(omap_obj->block);
refcount_set(&omap_obj->dma_addr_cnt, 1);
ret = omap_gem_attach_pages(obj); if (ret) goto fail;
@@ -811,10 +813,10 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) omap_obj->block = block;
DBG("got dma address: %pad", &omap_obj->dma_addr);
} else {
}refcount_inc(&omap_obj->dma_addr_cnt);
omap_obj->dma_addr_cnt++;
Was there a reason to not have refcount_inc() here, but to use refcount_set above?
Reviewed-by: Tomi Valkeinen tomi.valkeinen@ti.com
Tomi
From: Tomi Valkeinen tomi.valkeinen@ti.com
Add omap_gem_unpin_locked() which is a version of omap_gem_unpin() that expects the caller to hold the omap_obj lock.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com --- drivers/gpu/drm/omapdrm/omap_gem.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 0b6eef120cc9..3071e815da73 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -832,20 +832,16 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) }
/** - * omap_gem_unpin() - Unpin a GEM object from memory + * omap_gem_unpin_locked() - Unpin a GEM object from memory * @obj: the GEM object * - * Unpin the given GEM object previously pinned with omap_gem_pin(). Pins are - * reference-counted, the actualy unpin will only be performed when the number - * of calls to this function matches the number of calls to omap_gem_pin(). + * omap_gem_unpin() without locking. */ -void omap_gem_unpin(struct drm_gem_object *obj) +static void omap_gem_unpin_locked(struct drm_gem_object *obj) { struct omap_gem_object *omap_obj = to_omap_bo(obj); int ret;
- mutex_lock(&omap_obj->lock); - if (refcount_dec_and_test(&omap_obj->dma_addr_cnt)) { ret = tiler_unpin(omap_obj->block); if (ret) { @@ -862,6 +858,20 @@ void omap_gem_unpin(struct drm_gem_object *obj) } }
+/** + * omap_gem_unpin() - Unpin a GEM object from memory + * @obj: the GEM object + * + * Unpin the given GEM object previously pinned with omap_gem_pin(). Pins are + * reference-counted, the actual unpin will only be performed when the number + * of calls to this function matches the number of calls to omap_gem_pin(). + */ +void omap_gem_unpin(struct drm_gem_object *obj) +{ + struct omap_gem_object *omap_obj = to_omap_bo(obj); + + mutex_lock(&omap_obj->lock); + omap_gem_unpin_locked(obj); mutex_unlock(&omap_obj->lock); }
From: Tomi Valkeinen tomi.valkeinen@ti.com
Allow NULL to be passed in 'dma_addr' for omap_gem_pin(), in case the caller does not need the dma_addr.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com --- drivers/gpu/drm/omapdrm/omap_gem.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 3071e815da73..2ac83cdbb15a 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -817,9 +817,11 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) refcount_inc(&omap_obj->dma_addr_cnt); }
- *dma_addr = omap_obj->dma_addr; + if (dma_addr) + *dma_addr = omap_obj->dma_addr; } else if (omap_gem_is_contiguous(omap_obj)) { - *dma_addr = omap_obj->dma_addr; + if (dma_addr) + *dma_addr = omap_obj->dma_addr; } else { ret = -EINVAL; goto fail;
From: Tomi Valkeinen tomi.valkeinen@ti.com
Reorder OMAP_BO flags and improve the comments.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com --- include/uapi/drm/omap_drm.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/include/uapi/drm/omap_drm.h b/include/uapi/drm/omap_drm.h index 1fccffef9e27..d8ee2f840697 100644 --- a/include/uapi/drm/omap_drm.h +++ b/include/uapi/drm/omap_drm.h @@ -38,19 +38,20 @@ struct drm_omap_param { __u64 value; /* in (set_param), out (get_param) */ };
-#define OMAP_BO_SCANOUT 0x00000001 /* scanout capable (phys contiguous) */ -#define OMAP_BO_CACHE_MASK 0x00000006 /* cache type mask, see cache modes */ -#define OMAP_BO_TILED_MASK 0x00000f00 /* tiled mapping mask, see tiled modes */ +/* Scanout buffer, consumable by DSS */ +#define OMAP_BO_SCANOUT 0x00000001
-/* cache modes */ -#define OMAP_BO_CACHED 0x00000000 /* default */ -#define OMAP_BO_WC 0x00000002 /* write-combine */ -#define OMAP_BO_UNCACHED 0x00000004 /* strongly-ordered (uncached) */ +/* Buffer CPU caching mode: cached, write-combining or uncached. */ +#define OMAP_BO_CACHED 0x00000000 +#define OMAP_BO_WC 0x00000002 +#define OMAP_BO_UNCACHED 0x00000004 +#define OMAP_BO_CACHE_MASK 0x00000006
-/* tiled modes */ +/* Use TILER for the buffer. The TILER container unit can be 8, 16 or 32 bits. */ #define OMAP_BO_TILED_8 0x00000100 #define OMAP_BO_TILED_16 0x00000200 #define OMAP_BO_TILED_32 0x00000300 +#define OMAP_BO_TILED_MASK 0x00000f00 #define OMAP_BO_TILED (OMAP_BO_TILED_8 | OMAP_BO_TILED_16 | OMAP_BO_TILED_32)
union omap_gem_size {
From: Tomi Valkeinen tomi.valkeinen@ti.com
OMAP_BO_TILED does not make sense, as OMAP_BO_TILED_* values are not bitmasks but normal values. As we already have OMAP_BO_TILED_MASK for the mask, we can remove OMAP_BO_TILED and use OMAP_BO_TILED_MASK instead.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com --- drivers/gpu/drm/omapdrm/omap_dmm_tiler.h | 2 +- drivers/gpu/drm/omapdrm/omap_fb.c | 6 +++--- drivers/gpu/drm/omapdrm/omap_gem.c | 18 +++++++++--------- drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c | 2 +- include/uapi/drm/omap_drm.h | 1 - 5 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.h b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.h index 835e6654fa82..43c1d096b021 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.h +++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.h @@ -113,7 +113,7 @@ extern struct platform_driver omap_dmm_driver; /* GEM bo flags -> tiler fmt */ static inline enum tiler_fmt gem2fmt(u32 flags) { - switch (flags & OMAP_BO_TILED) { + switch (flags & OMAP_BO_TILED_MASK) { case OMAP_BO_TILED_8: return TILFMT_8BIT; case OMAP_BO_TILED_16: diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 1c9048e35d90..e0e8d1cc3862 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -76,7 +76,7 @@ static u32 get_linear_addr(struct drm_framebuffer *fb,
bool omap_framebuffer_supports_rotation(struct drm_framebuffer *fb) { - return omap_gem_flags(fb->obj[0]) & OMAP_BO_TILED; + return omap_gem_flags(fb->obj[0]) & OMAP_BO_TILED_MASK; }
/* Note: DRM rotates counter-clockwise, TILER & DSS rotates clockwise */ @@ -135,7 +135,7 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, x = state->src_x >> 16; y = state->src_y >> 16;
- if (omap_gem_flags(fb->obj[0]) & OMAP_BO_TILED) { + if (omap_gem_flags(fb->obj[0]) & OMAP_BO_TILED_MASK) { u32 w = state->src_w >> 16; u32 h = state->src_h >> 16;
@@ -193,7 +193,7 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, plane = &omap_fb->planes[1];
if (info->rotation_type == OMAP_DSS_ROT_TILER) { - WARN_ON(!(omap_gem_flags(fb->obj[1]) & OMAP_BO_TILED)); + WARN_ON(!(omap_gem_flags(fb->obj[1]) & OMAP_BO_TILED_MASK)); omap_gem_rotated_dma_addr(fb->obj[1], orient, x/2, y/2, &info->p_uv_addr); } else { diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 2ac83cdbb15a..07dba300ec07 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -194,7 +194,7 @@ static void omap_gem_evict(struct drm_gem_object *obj) struct omap_gem_object *omap_obj = to_omap_bo(obj); struct omap_drm_private *priv = obj->dev->dev_private;
- if (omap_obj->flags & OMAP_BO_TILED) { + if (omap_obj->flags & OMAP_BO_TILED_MASK) { enum tiler_fmt fmt = gem2fmt(omap_obj->flags); int i;
@@ -322,7 +322,7 @@ size_t omap_gem_mmap_size(struct drm_gem_object *obj) struct omap_gem_object *omap_obj = to_omap_bo(obj); size_t size = obj->size;
- if (omap_obj->flags & OMAP_BO_TILED) { + if (omap_obj->flags & OMAP_BO_TILED_MASK) { /* for tiled buffers, the virtual size has stride rounded up * to 4kb.. (to hide the fact that row n+1 might start 16kb or * 32kb later!). But we don't back the entire buffer with @@ -511,7 +511,7 @@ vm_fault_t omap_gem_fault(struct vm_fault *vmf) * probably trigger put_pages()? */
- if (omap_obj->flags & OMAP_BO_TILED) + if (omap_obj->flags & OMAP_BO_TILED_MASK) ret = omap_gem_fault_2d(obj, vma, vmf); else ret = omap_gem_fault_1d(obj, vma, vmf); @@ -784,7 +784,7 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) if (ret) goto fail;
- if (omap_obj->flags & OMAP_BO_TILED) { + if (omap_obj->flags & OMAP_BO_TILED_MASK) { block = tiler_reserve_2d(fmt, omap_obj->width, omap_obj->height, 0); @@ -890,7 +890,7 @@ int omap_gem_rotated_dma_addr(struct drm_gem_object *obj, u32 orient, mutex_lock(&omap_obj->lock);
if ((refcount_read(&omap_obj->dma_addr_cnt) > 0) && omap_obj->block && - (omap_obj->flags & OMAP_BO_TILED)) { + (omap_obj->flags & OMAP_BO_TILED_MASK)) { *dma_addr = tiler_tsptr(omap_obj->block, orient, x, y); ret = 0; } @@ -905,7 +905,7 @@ int omap_gem_tiled_stride(struct drm_gem_object *obj, u32 orient) { struct omap_gem_object *omap_obj = to_omap_bo(obj); int ret = -EINVAL; - if (omap_obj->flags & OMAP_BO_TILED) + if (omap_obj->flags & OMAP_BO_TILED_MASK) ret = tiler_stride(gem2fmt(omap_obj->flags), orient); return ret; } @@ -1044,7 +1044,7 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) refcount_read(&omap_obj->dma_addr_cnt), omap_obj->vaddr, omap_obj->roll);
- if (omap_obj->flags & OMAP_BO_TILED) { + if (omap_obj->flags & OMAP_BO_TILED_MASK) { seq_printf(m, " %dx%d", omap_obj->width, omap_obj->height); if (omap_obj->block) { struct tcm_area *area = &omap_obj->block->area; @@ -1143,7 +1143,7 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, int ret;
/* Validate the flags and compute the memory and cache flags. */ - if (flags & OMAP_BO_TILED) { + if (flags & OMAP_BO_TILED_MASK) { if (!priv->usergart) { dev_err(dev->dev, "Tiled buffers require DMM\n"); return NULL; @@ -1185,7 +1185,7 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, omap_obj->flags = flags; mutex_init(&omap_obj->lock);
- if (flags & OMAP_BO_TILED) { + if (flags & OMAP_BO_TILED_MASK) { /* * For tiled buffers align dimensions to slot boundaries and * calculate size based on aligned dimensions. diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c index 07c0b1b486f7..a4a4415e4666 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c +++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c @@ -64,7 +64,7 @@ static int omap_gem_dmabuf_begin_cpu_access(struct dma_buf *buffer, { struct drm_gem_object *obj = buffer->priv; struct page **pages; - if (omap_gem_flags(obj) & OMAP_BO_TILED) { + if (omap_gem_flags(obj) & OMAP_BO_TILED_MASK) { /* TODO we would need to pin at least part of the buffer to * get de-tiled view. For now just reject it. */ diff --git a/include/uapi/drm/omap_drm.h b/include/uapi/drm/omap_drm.h index d8ee2f840697..5a142fad473c 100644 --- a/include/uapi/drm/omap_drm.h +++ b/include/uapi/drm/omap_drm.h @@ -52,7 +52,6 @@ struct drm_omap_param { #define OMAP_BO_TILED_16 0x00000200 #define OMAP_BO_TILED_32 0x00000300 #define OMAP_BO_TILED_MASK 0x00000f00 -#define OMAP_BO_TILED (OMAP_BO_TILED_8 | OMAP_BO_TILED_16 | OMAP_BO_TILED_32)
union omap_gem_size { __u32 bytes; /* (for non-tiled formats) */
From: Tomi Valkeinen tomi.valkeinen@ti.com
omap_gem_new() has a comment about OMAP_BO_SCANOUT which does not make sense. Also, for the TILER case, we drop OMAP_BO_SCANOUT flag for some reason.
It's not clear what the original purpose of OMAP_BO_SCANOUT is, but presuming it means "scanout buffer, something that can be consumed by DSS", this patch cleans up the above issues.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com --- drivers/gpu/drm/omapdrm/omap_gem.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 07dba300ec07..5c4cdf618347 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -1153,7 +1153,6 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, * Tiled buffers are always shmem paged backed. When they are * scanned out, they are remapped into DMM/TILER. */ - flags &= ~OMAP_BO_SCANOUT; flags |= OMAP_BO_MEM_SHMEM;
/* @@ -1164,9 +1163,8 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, flags |= tiler_get_cpu_cache_flags(); } else if ((flags & OMAP_BO_SCANOUT) && !priv->has_dmm) { /* - * OMAP_BO_SCANOUT hints that the buffer doesn't need to be - * tiled. However, to lower the pressure on memory allocation, - * use contiguous memory only if no TILER is available. + * If we don't have DMM, we must allocate scanout buffers + * from contiguous DMA memory. */ flags |= OMAP_BO_MEM_DMA_API; } else if (!(flags & OMAP_BO_MEM_DMABUF)) {
From: Tomi Valkeinen tomi.valkeinen@ti.com
Add a helper function omap_gem_validate_flags() which validates the omap_bo flags passed from the userspace.
Also drop the dev_err() message, as the userspace can cause that at will.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com --- drivers/gpu/drm/omapdrm/omap_gem.c | 40 ++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 5c4cdf618347..cafa9d0bf3c1 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -1131,6 +1131,38 @@ void omap_gem_free_object(struct drm_gem_object *obj) kfree(omap_obj); }
+static bool omap_gem_validate_flags(struct drm_device *dev, u32 flags) +{ + struct omap_drm_private *priv = dev->dev_private; + + switch (flags & OMAP_BO_CACHE_MASK) { + case OMAP_BO_CACHED: + case OMAP_BO_WC: + case OMAP_BO_CACHE_MASK: + break; + + default: + return false; + } + + if (flags & OMAP_BO_TILED_MASK) { + if (!priv->usergart) + return false; + + switch (flags & OMAP_BO_TILED_MASK) { + case OMAP_BO_TILED_8: + case OMAP_BO_TILED_16: + case OMAP_BO_TILED_32: + break; + + default: + return false; + } + } + + return true; +} + /* GEM buffer object constructor */ struct drm_gem_object *omap_gem_new(struct drm_device *dev, union omap_gem_size gsize, u32 flags) @@ -1142,13 +1174,11 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, size_t size; int ret;
+ if (!omap_gem_validate_flags(dev, flags)) + return NULL; + /* Validate the flags and compute the memory and cache flags. */ if (flags & OMAP_BO_TILED_MASK) { - if (!priv->usergart) { - dev_err(dev->dev, "Tiled buffers require DMM\n"); - return NULL; - } - /* * Tiled buffers are always shmem paged backed. When they are * scanned out, they are remapped into DMM/TILER.
From: Tomi Valkeinen tomi.valkeinen@ti.com
On SoCs with DMM/TILER, we have two ways to allocate buffers: normal dma_alloc or via DMM (which basically functions as an IOMMU). DMM can map 128MB at a time, and we only map the DMM buffers when they are used (i.e. not at alloc time). If DMM is present, omapdrm always uses DMM.
There are use cases that require lots of big buffers that are being used at the same time by different IPs. At the moment the userspace has a hard maximum of 128MB.
This patch adds three new flags that can be used by the userspace to solve the situation:
OMAP_BO_MEM_CONTIG: The driver will use dma_alloc to get the memory. This can be used to avoid DMM if the userspace knows it needs more than 128M of memory at the same time.
OMAP_BO_MEM_DMM: The driver will use DMM to get the memory. There's not much use for this flag at the moment, as on platforms with DMM it is used by default, but it's here for completeness.
OMAP_BO_MEM_PIN: The driver will pin the memory at alloc time, and keep it pinned. This can be used to 1) get an error at alloc time if DMM space is full, and 2) get rid of the constant pin/unpin operations which may have some effect on performance.
If none of the flags are given, the behavior is the same as currently.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com --- drivers/gpu/drm/omapdrm/omap_gem.c | 25 ++++++++++++++++++++++++- include/uapi/drm/omap_drm.h | 9 +++++++++ 2 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index cafa9d0bf3c1..d744d27e200a 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -1095,6 +1095,9 @@ void omap_gem_free_object(struct drm_gem_object *obj) list_del(&omap_obj->mm_list); mutex_unlock(&priv->list_lock);
+ if (omap_obj->flags & OMAP_BO_MEM_PIN) + omap_gem_unpin_locked(obj); + /* * We own the sole reference to the object at this point, but to keep * lockdep happy, we must still take the omap_obj_lock to call @@ -1145,10 +1148,19 @@ static bool omap_gem_validate_flags(struct drm_device *dev, u32 flags) return false; }
+ if ((flags & OMAP_BO_MEM_CONTIG) && (flags & OMAP_BO_MEM_DMM)) + return false; + + if ((flags & OMAP_BO_MEM_DMM) && !priv->usergart) + return false; + if (flags & OMAP_BO_TILED_MASK) { if (!priv->usergart) return false;
+ if (flags & OMAP_BO_MEM_CONTIG) + return false; + switch (flags & OMAP_BO_TILED_MASK) { case OMAP_BO_TILED_8: case OMAP_BO_TILED_16: @@ -1191,7 +1203,8 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, */ flags &= ~(OMAP_BO_CACHED|OMAP_BO_WC|OMAP_BO_UNCACHED); flags |= tiler_get_cpu_cache_flags(); - } else if ((flags & OMAP_BO_SCANOUT) && !priv->has_dmm) { + } else if ((flags & OMAP_BO_MEM_CONTIG) || + ((flags & OMAP_BO_SCANOUT) && !priv->has_dmm)) { /* * If we don't have DMM, we must allocate scanout buffers * from contiguous DMA memory. @@ -1251,12 +1264,22 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, goto err_release; }
+ if (flags & OMAP_BO_MEM_PIN) { + ret = omap_gem_pin(obj, NULL); + if (ret) + goto err_free_dma; + } + mutex_lock(&priv->list_lock); list_add(&omap_obj->mm_list, &priv->obj_list); mutex_unlock(&priv->list_lock);
return obj;
+err_free_dma: + if (flags & OMAP_BO_MEM_DMA_API) + dma_free_writecombine(dev->dev, size, + omap_obj->vaddr, omap_obj->dma_addr); err_release: drm_gem_object_release(obj); err_free: diff --git a/include/uapi/drm/omap_drm.h b/include/uapi/drm/omap_drm.h index 5a142fad473c..842d3180a442 100644 --- a/include/uapi/drm/omap_drm.h +++ b/include/uapi/drm/omap_drm.h @@ -47,6 +47,15 @@ struct drm_omap_param { #define OMAP_BO_UNCACHED 0x00000004 #define OMAP_BO_CACHE_MASK 0x00000006
+/* Force allocation from contiguous DMA memory */ +#define OMAP_BO_MEM_CONTIG 0x00000008 + +/* Force allocation via DMM */ +#define OMAP_BO_MEM_DMM 0x00000010 + +/* Pin the buffer when allocating and keep pinned */ +#define OMAP_BO_MEM_PIN 0x00000020 + /* Use TILER for the buffer. The TILER container unit can be 8, 16 or 32 bits. */ #define OMAP_BO_TILED_8 0x00000100 #define OMAP_BO_TILED_16 0x00000200
Hi JJ,
On 08/07/2019 13:45, Jean-Jacques Hiblot wrote:
A first version of this work had been sent by Tomi Valkeinen in may 2017 (https://www.spinics.net/lists/dri-devel/msg140663.html).
This series adds a few new OMAP_BO flags to help the userspace manage situations where it needs to use lots of buffers, and would currently run out of TILER space. The TILER space is limited to mapping 128MB at any given time and some applications might need more.
This seres is also the opportunity to do some cleanup in the flags and improve the comments describing them.
The user-space patches for libdrm, although ready, haven't been posted yet. It will be be done when this series have been discussed and hopefully in the process of getting merged.
JJ
changes in v2:
- fixed build error that crept in during rebase before sending (sorry about that)
- rework the refcount part a bit.
Jean-Jacques Hiblot (1): drm/omap: use refcount API to track the number of users of dma_addr
Tomi Valkeinen (7): drm/omap: add omap_gem_unpin_locked() drm/omap: accept NULL for dma_addr in omap_gem_pin drm/omap: cleanup OMAP_BO flags drm/omap: remove OMAP_BO_TILED define drm/omap: cleanup OMAP_BO_SCANOUT use drm/omap: add omap_gem_validate_flags() drm/omap: add OMAP_BO flags to affect buffer allocation
Were there any changes to these patches compared to the ones I sent a few years back?
If I recall right, one valid comment from Laurent was also about adding kernel-doc for include/uapi/drm/omap_drm.h. The OMAP_BO_* flags could have a bit more explanations in the form of kernel doc.
Tomi
On 01/08/2019 11:02, Tomi Valkeinen wrote:
Hi JJ,
On 08/07/2019 13:45, Jean-Jacques Hiblot wrote:
A first version of this work had been sent by Tomi Valkeinen in may 2017 (https://www.spinics.net/lists/dri-devel/msg140663.html).
This series adds a few new OMAP_BO flags to help the userspace manage situations where it needs to use lots of buffers, and would currently run out of TILER space. The TILER space is limited to mapping 128MB at any given time and some applications might need more.
This seres is also the opportunity to do some cleanup in the flags and improve the comments describing them.
The user-space patches for libdrm, although ready, haven't been posted yet. It will be be done when this series have been discussed and hopefully in the process of getting merged.
JJ
changes in v2:
- fixed build error that crept in during rebase before sending (sorry
about that)
- rework the refcount part a bit.
Jean-Jacques Hiblot (1): drm/omap: use refcount API to track the number of users of dma_addr
Tomi Valkeinen (7): drm/omap: add omap_gem_unpin_locked() drm/omap: accept NULL for dma_addr in omap_gem_pin drm/omap: cleanup OMAP_BO flags drm/omap: remove OMAP_BO_TILED define drm/omap: cleanup OMAP_BO_SCANOUT use drm/omap: add omap_gem_validate_flags() drm/omap: add OMAP_BO flags to affect buffer allocation
Were there any changes to these patches compared to the ones I sent a few years back?
Yes they are a bit different. I took the patches from the TI tree no from ML. In thoses patches you had already taken in account most (all ?) of the comments, including a better description of the different flags and some changes in names. I only modified and reordered them to fix a build breakage. (this is related to OMAP_BO_TILED being removed)
Also I added a patch to address Laurent's comment about the use of atomic
If I recall right, one valid comment from Laurent was also about adding kernel-doc for include/uapi/drm/omap_drm.h. The OMAP_BO_* flags could have a bit more explanations in the form of kernel doc.
OK I didn't address this one. I'll will for v2.
Tomi
On 01/08/2019 11:02, Tomi Valkeinen wrote:
Hi JJ,
On 08/07/2019 13:45, Jean-Jacques Hiblot wrote:
A first version of this work had been sent by Tomi Valkeinen in may 2017 (https://www.spinics.net/lists/dri-devel/msg140663.html).
This series adds a few new OMAP_BO flags to help the userspace manage situations where it needs to use lots of buffers, and would currently run out of TILER space. The TILER space is limited to mapping 128MB at any given time and some applications might need more.
This seres is also the opportunity to do some cleanup in the flags and improve the comments describing them.
The user-space patches for libdrm, although ready, haven't been posted yet. It will be be done when this series have been discussed and hopefully in the process of getting merged.
JJ
changes in v2:
- fixed build error that crept in during rebase before sending (sorry
about that)
- rework the refcount part a bit.
Jean-Jacques Hiblot (1): drm/omap: use refcount API to track the number of users of dma_addr
Tomi Valkeinen (7): drm/omap: add omap_gem_unpin_locked() drm/omap: accept NULL for dma_addr in omap_gem_pin drm/omap: cleanup OMAP_BO flags drm/omap: remove OMAP_BO_TILED define drm/omap: cleanup OMAP_BO_SCANOUT use drm/omap: add omap_gem_validate_flags() drm/omap: add OMAP_BO flags to affect buffer allocation
Were there any changes to these patches compared to the ones I sent a few years back?
Yes they are a bit different. I took the patches from the TI tree no from ML. In thoses patches you had already taken in account most (all ?) of the comments, including a better description of the different flags and some changes in names. I only modified and reordered them to fix a build breakage. (this is related to OMAP_BO_TILED being removed)
Also I added a patch to address Laurent's comment about the use of atomic
If I recall right, one valid comment from Laurent was also about adding kernel-doc for include/uapi/drm/omap_drm.h. The OMAP_BO_* flags could have a bit more explanations in the form of kernel doc.
OK I didn't address this one. I'll update the comments in a v3.
Tomi
dri-devel@lists.freedesktop.org