Message ID | 20191007112555.25278-9-jjhiblot@ti.com |
---|---|
State | Superseded |
Headers | show |
Series | None | expand |
On 07/10/2019 13:25, Jean-Jacques Hiblot wrote: > 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 | 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@ti.com>
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