Commit 35a6e15a authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-etnaviv-next-2024-11-07' of https://git.pengutronix.de/git/lst/linux into drm-next



- improve handling of DMA address limited systems
- improve GPU hangcheck
- fix address space collision on >= 4K CPU pages
- flush all known writeback caches before memory release
- various code cleanups

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Lucas Stach <l.stach@pengutronix.de>
Link: https://patchwork.freedesktop.org/patch/msgid/c84075a0257e7bee222d008fa3118117422d664e.camel@pengutronix.de
parents 1f8bdc31 2c7ac7dd
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -482,7 +482,8 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
	} else {
		CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE,
				       VIVS_GL_FLUSH_CACHE_DEPTH |
				       VIVS_GL_FLUSH_CACHE_COLOR);
				       VIVS_GL_FLUSH_CACHE_COLOR |
				       VIVS_GL_FLUSH_CACHE_SHADER_L1);
		if (has_blt) {
			CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
			CMD_LOAD_STATE(buffer, VIVS_BLT_SET_COMMAND, 0x1);
+2 −2
Original line number Diff line number Diff line
@@ -5,8 +5,6 @@

#include <linux/dma-mapping.h>

#include <drm/drm_mm.h>

#include "etnaviv_cmdbuf.h"
#include "etnaviv_gem.h"
#include "etnaviv_gpu.h"
@@ -55,6 +53,7 @@ etnaviv_cmdbuf_suballoc_new(struct device *dev)
	return suballoc;

free_suballoc:
	mutex_destroy(&suballoc->lock);
	kfree(suballoc);

	return ERR_PTR(ret);
@@ -79,6 +78,7 @@ void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc)
{
	dma_free_wc(suballoc->dev, SUBALLOC_SIZE, suballoc->vaddr,
		    suballoc->paddr);
	mutex_destroy(&suballoc->lock);
	kfree(suballoc);
}

+16 −5
Original line number Diff line number Diff line
@@ -538,6 +538,16 @@ static int etnaviv_bind(struct device *dev)
	priv->num_gpus = 0;
	priv->shm_gfp_mask = GFP_HIGHUSER | __GFP_RETRY_MAYFAIL | __GFP_NOWARN;

	/*
	 * If the GPU is part of a system with DMA addressing limitations,
	 * request pages for our SHM backend buffers from the DMA32 zone to
	 * hopefully avoid performance killing SWIOTLB bounce buffering.
	 */
	if (dma_addressing_limited(dev)) {
		priv->shm_gfp_mask |= GFP_DMA32;
		priv->shm_gfp_mask &= ~__GFP_HIGHMEM;
	}

	priv->cmdbuf_suballoc = etnaviv_cmdbuf_suballoc_new(drm->dev);
	if (IS_ERR(priv->cmdbuf_suballoc)) {
		dev_err(drm->dev, "Failed to create cmdbuf suballocator\n");
@@ -564,6 +574,7 @@ static int etnaviv_bind(struct device *dev)
out_destroy_suballoc:
	etnaviv_cmdbuf_suballoc_destroy(priv->cmdbuf_suballoc);
out_free_priv:
	mutex_destroy(&priv->gem_lock);
	kfree(priv);
out_put:
	drm_dev_put(drm);
@@ -608,7 +619,7 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
			if (!of_device_is_available(core_node))
				continue;

			drm_of_component_match_add(&pdev->dev, &match,
			drm_of_component_match_add(dev, &match,
						   component_compare_of, core_node);
		}
	} else {
@@ -631,9 +642,9 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
	 * bit to make sure we are allocating the command buffers and
	 * TLBs in the lower 4 GiB address space.
	 */
	if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)) ||
	    dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32))) {
		dev_dbg(&pdev->dev, "No suitable DMA available\n");
	if (dma_set_mask(dev, DMA_BIT_MASK(40)) ||
	    dma_set_coherent_mask(dev, DMA_BIT_MASK(32))) {
		dev_dbg(dev, "No suitable DMA available\n");
		return -ENODEV;
	}

@@ -644,7 +655,7 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
	 */
	first_node = etnaviv_of_first_available_node();
	if (first_node) {
		of_dma_configure(&pdev->dev, first_node, true);
		of_dma_configure(dev, first_node, true);
		of_node_put(first_node);
	}

+7 −7
Original line number Diff line number Diff line
@@ -514,6 +514,7 @@ void etnaviv_gem_free_object(struct drm_gem_object *obj)
	etnaviv_obj->ops->release(etnaviv_obj);
	drm_gem_object_release(obj);

	mutex_destroy(&etnaviv_obj->lock);
	kfree(etnaviv_obj);
}

@@ -543,7 +544,7 @@ static const struct drm_gem_object_funcs etnaviv_gem_object_funcs = {
	.vm_ops = &vm_ops,
};

static int etnaviv_gem_new_impl(struct drm_device *dev, u32 flags,
static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags,
	const struct etnaviv_gem_ops *ops, struct drm_gem_object **obj)
{
	struct etnaviv_gem_object *etnaviv_obj;
@@ -570,6 +571,7 @@ static int etnaviv_gem_new_impl(struct drm_device *dev, u32 flags,
	if (!etnaviv_obj)
		return -ENOMEM;

	etnaviv_obj->size = ALIGN(size, SZ_4K);
	etnaviv_obj->flags = flags;
	etnaviv_obj->ops = ops;

@@ -590,15 +592,13 @@ int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
	struct drm_gem_object *obj = NULL;
	int ret;

	size = PAGE_ALIGN(size);

	ret = etnaviv_gem_new_impl(dev, flags, &etnaviv_gem_shmem_ops, &obj);
	ret = etnaviv_gem_new_impl(dev, size, flags, &etnaviv_gem_shmem_ops, &obj);
	if (ret)
		goto fail;

	lockdep_set_class(&to_etnaviv_bo(obj)->lock, &etnaviv_shm_lock_class);

	ret = drm_gem_object_init(dev, obj, size);
	ret = drm_gem_object_init(dev, obj, PAGE_ALIGN(size));
	if (ret)
		goto fail;

@@ -627,7 +627,7 @@ int etnaviv_gem_new_private(struct drm_device *dev, size_t size, u32 flags,
	struct drm_gem_object *obj;
	int ret;

	ret = etnaviv_gem_new_impl(dev, flags, ops, &obj);
	ret = etnaviv_gem_new_impl(dev, size, flags, ops, &obj);
	if (ret)
		return ret;

@@ -686,7 +686,7 @@ static void etnaviv_gem_userptr_release(struct etnaviv_gem_object *etnaviv_obj)
		kfree(etnaviv_obj->sgt);
	}
	if (etnaviv_obj->pages) {
		int npages = etnaviv_obj->base.size >> PAGE_SHIFT;
		unsigned int npages = etnaviv_obj->base.size >> PAGE_SHIFT;

		unpin_user_pages(etnaviv_obj->pages, npages);
		kvfree(etnaviv_obj->pages);
+5 −0
Original line number Diff line number Diff line
@@ -36,6 +36,11 @@ struct etnaviv_gem_object {
	const struct etnaviv_gem_ops *ops;
	struct mutex lock;

	/*
	 * The actual size that is visible to the GPU, not necessarily
	 * PAGE_SIZE aligned, but should be aligned to GPU page size.
	 */
	u32 size;
	u32 flags;

	struct list_head gem_node;
Loading