[v3,8/8] drm/omap: add OMAP_BO flags to affect buffer allocation
Jean-Jacques Hiblot
jjhiblot at ti.com
Tue Oct 8 16:01:05 UTC 2019
On 07/10/2019 13:25, Jean-Jacques Hiblot wrote:
> From: Tomi Valkeinen <tomi.valkeinen at 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 at ti.com>
> ---
> drivers/gpu/drm/omapdrm/omap_gem.c | 54 ++++++++++++++++++++++++++++--
> include/uapi/drm/omap_drm.h | 9 +++++
> 2 files changed, 61 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c
> index e518d93ca6df..bf18dfe2b689 100644
> --- a/drivers/gpu/drm/omapdrm/omap_gem.c
> +++ b/drivers/gpu/drm/omapdrm/omap_gem.c
> @@ -1097,6 +1097,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
> @@ -1147,10 +1150,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:
> @@ -1165,7 +1177,34 @@ static bool omap_gem_validate_flags(struct drm_device *dev, u32 flags)
> return true;
> }
>
> -/* GEM buffer object constructor */
> +/**
> + * omap_gem_new() - Create a new GEM buffer
> + * @dev: The DRM device
> + * @gsize: The requested size for the GEM buffer. If the buffer is tiled
> + * (2D buffer), the size is a pair of values: height and width
> + * expressed in pixels. If the buffers is not tiled, it is expressed
> + * in bytes.
> + * @flags: Flags give additionnal information about the allocation:
> + * OMAP_BO_TILED_x: use the TILER (2D buffers). The TILER container
> + * unit can be 8, 16 or 32 bits. Cache is always disabled for
> + * tiled buffers.
> + * OMAP_BO_SCANOUT: Scannout buffer, consummable by the DSS
> + * OMAP_BO_CACHED: Buffer CPU caching mode: cached
> + * OMAP_BO_WC: Buffer CPU caching mode: write-combined
> + * OMAP_BO_UNCACHED: Buffer CPU caching mode: uncached
> + * 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.
> + *
> + * Return: The GEM buffer or NULL if the allocation failed
> + */
> struct drm_gem_object *omap_gem_new(struct drm_device *dev,
> union omap_gem_size gsize, u32 flags)
> {
> @@ -1193,7 +1232,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.
> @@ -1253,12 +1293,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_wc(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
I modified the patch to add comment following the kernel-doc style, so
my Reviewed-by actually applies only to the code modifications, not the
comment wording.
Reviewed-by: Jean-Jacques Hiblot <jjhiblot at ti.com>
More information about the dri-devel
mailing list