Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit db82a043 authored by Lucas Stach's avatar Lucas Stach
Browse files

drm/etnaviv: split out cmdbuf mapping into address space



This allows to decouple the cmdbuf suballocator create and mapping
the region into the GPU address space. Allowing multiple AS to share
a single cmdbuf suballoc.

Signed-off-by: default avatarLucas Stach <l.stach@pengutronix.de>
Reviewed-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: default avatarGuido Günther <agx@sigxcpu.org>
parent db41fe7d
Loading
Loading
Loading
Loading
+13 −10
Original line number Diff line number Diff line
@@ -118,7 +118,8 @@ static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu,
	u32 *ptr = buf->vaddr + off;

	dev_info(gpu->dev, "virt %p phys 0x%08x free 0x%08x\n",
			ptr, etnaviv_cmdbuf_get_va(buf) + off, size - len * 4 - off);
			ptr, etnaviv_cmdbuf_get_va(buf, &gpu->cmdbuf_mapping) +
			off, size - len * 4 - off);

	print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4,
			ptr, len * 4, 0);
@@ -151,7 +152,8 @@ static u32 etnaviv_buffer_reserve(struct etnaviv_gpu *gpu,
	if (buffer->user_size + cmd_dwords * sizeof(u64) > buffer->size)
		buffer->user_size = 0;

	return etnaviv_cmdbuf_get_va(buffer) + buffer->user_size;
	return etnaviv_cmdbuf_get_va(buffer, &gpu->cmdbuf_mapping) +
	       buffer->user_size;
}

u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
@@ -164,8 +166,8 @@ u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
	buffer->user_size = 0;

	CMD_WAIT(buffer);
	CMD_LINK(buffer, 2, etnaviv_cmdbuf_get_va(buffer) +
		 buffer->user_size - 4);
	CMD_LINK(buffer, 2, etnaviv_cmdbuf_get_va(buffer, &gpu->cmdbuf_mapping)
		 + buffer->user_size - 4);

	return buffer->user_size / 8;
}
@@ -291,8 +293,8 @@ void etnaviv_sync_point_queue(struct etnaviv_gpu *gpu, unsigned int event)

	/* Append waitlink */
	CMD_WAIT(buffer);
	CMD_LINK(buffer, 2, etnaviv_cmdbuf_get_va(buffer) +
			    buffer->user_size - 4);
	CMD_LINK(buffer, 2, etnaviv_cmdbuf_get_va(buffer, &gpu->cmdbuf_mapping)
		 + buffer->user_size - 4);

	/*
	 * Kick off the 'sync point' command by replacing the previous
@@ -319,7 +321,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
	if (drm_debug & DRM_UT_DRIVER)
		etnaviv_buffer_dump(gpu, buffer, 0, 0x50);

	link_target = etnaviv_cmdbuf_get_va(cmdbuf);
	link_target = etnaviv_cmdbuf_get_va(cmdbuf, &gpu->cmdbuf_mapping);
	link_dwords = cmdbuf->size / 8;

	/*
@@ -412,12 +414,13 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
	CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) |
		       VIVS_GL_EVENT_FROM_PE);
	CMD_WAIT(buffer);
	CMD_LINK(buffer, 2, etnaviv_cmdbuf_get_va(buffer) +
			    buffer->user_size - 4);
	CMD_LINK(buffer, 2, etnaviv_cmdbuf_get_va(buffer, &gpu->cmdbuf_mapping)
		 + buffer->user_size - 4);

	if (drm_debug & DRM_UT_DRIVER)
		pr_info("stream link to 0x%08x @ 0x%08x %p\n",
			return_target, etnaviv_cmdbuf_get_va(cmdbuf),
			return_target,
			etnaviv_cmdbuf_get_va(cmdbuf, &gpu->cmdbuf_mapping),
			cmdbuf->vaddr);

	if (drm_debug & DRM_UT_DRIVER) {
+19 −16
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <drm/drm_mm.h>

#include "etnaviv_cmdbuf.h"
#include "etnaviv_gem.h"
#include "etnaviv_gpu.h"
#include "etnaviv_mmu.h"
#include "etnaviv_perfmon.h"
@@ -22,10 +23,6 @@ struct etnaviv_cmdbuf_suballoc {
	void *vaddr;
	dma_addr_t paddr;

	/* GPU mapping */
	u32 iova;
	struct drm_mm_node vram_node; /* only used on MMUv2 */

	/* allocation management */
	struct mutex lock;
	DECLARE_BITMAP(granule_map, SUBALLOC_GRANULES);
@@ -54,26 +51,31 @@ etnaviv_cmdbuf_suballoc_new(struct etnaviv_gpu * gpu)
		goto free_suballoc;
	}

	ret = etnaviv_iommu_get_suballoc_va(gpu, suballoc->paddr,
					    &suballoc->vram_node, SUBALLOC_SIZE,
					    &suballoc->iova);
	if (ret)
		goto free_dma;

	return suballoc;

free_dma:
	dma_free_wc(gpu->dev, SUBALLOC_SIZE, suballoc->vaddr, suballoc->paddr);
free_suballoc:
	kfree(suballoc);

	return ERR_PTR(ret);
}

int etnaviv_cmdbuf_suballoc_map(struct etnaviv_cmdbuf_suballoc *suballoc,
				struct etnaviv_iommu *mmu,
				struct etnaviv_vram_mapping *mapping,
				u32 memory_base)
{
	return etnaviv_iommu_get_suballoc_va(mmu, mapping, memory_base,
					     suballoc->paddr, SUBALLOC_SIZE);
}

void etnaviv_cmdbuf_suballoc_unmap(struct etnaviv_iommu *mmu,
				   struct etnaviv_vram_mapping *mapping)
{
	etnaviv_iommu_put_suballoc_va(mmu, mapping);
}

void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc)
{
	etnaviv_iommu_put_suballoc_va(suballoc->gpu, &suballoc->vram_node,
				      SUBALLOC_SIZE, suballoc->iova);
	dma_free_wc(suballoc->gpu->dev, SUBALLOC_SIZE, suballoc->vaddr,
		    suballoc->paddr);
	kfree(suballoc);
@@ -127,9 +129,10 @@ void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf)
	wake_up_all(&suballoc->free_event);
}

u32 etnaviv_cmdbuf_get_va(struct etnaviv_cmdbuf *buf)
u32 etnaviv_cmdbuf_get_va(struct etnaviv_cmdbuf *buf,
			  struct etnaviv_vram_mapping *mapping)
{
	return buf->suballoc->iova + buf->suballoc_offset;
	return mapping->iova + buf->suballoc_offset;
}

dma_addr_t etnaviv_cmdbuf_get_pa(struct etnaviv_cmdbuf *buf)
+10 −1
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@
#include <linux/types.h>

struct etnaviv_gpu;
struct etnaviv_iommu;
struct etnaviv_vram_mapping;
struct etnaviv_cmdbuf_suballoc;
struct etnaviv_perfmon_request;

@@ -25,13 +27,20 @@ struct etnaviv_cmdbuf {
struct etnaviv_cmdbuf_suballoc *
etnaviv_cmdbuf_suballoc_new(struct etnaviv_gpu * gpu);
void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc);
int etnaviv_cmdbuf_suballoc_map(struct etnaviv_cmdbuf_suballoc *suballoc,
				struct etnaviv_iommu *mmu,
				struct etnaviv_vram_mapping *mapping,
				u32 memory_base);
void etnaviv_cmdbuf_suballoc_unmap(struct etnaviv_iommu *mmu,
				   struct etnaviv_vram_mapping *mapping);


int etnaviv_cmdbuf_init(struct etnaviv_cmdbuf_suballoc *suballoc,
		struct etnaviv_cmdbuf *cmdbuf, u32 size);
void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf);

u32 etnaviv_cmdbuf_get_va(struct etnaviv_cmdbuf *buf);
u32 etnaviv_cmdbuf_get_va(struct etnaviv_cmdbuf *buf,
			  struct etnaviv_vram_mapping *mapping);
dma_addr_t etnaviv_cmdbuf_get_pa(struct etnaviv_cmdbuf *buf);

#endif /* __ETNAVIV_CMDBUF_H__ */
+4 −2
Original line number Diff line number Diff line
@@ -172,11 +172,13 @@ void etnaviv_core_dump(struct etnaviv_gem_submit *submit)
	etnaviv_core_dump_mmu(&iter, gpu->mmu, mmu_size);
	etnaviv_core_dump_mem(&iter, ETDUMP_BUF_RING, gpu->buffer.vaddr,
			      gpu->buffer.size,
			      etnaviv_cmdbuf_get_va(&gpu->buffer));
			      etnaviv_cmdbuf_get_va(&gpu->buffer,
						    &gpu->cmdbuf_mapping));

	etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD,
			      submit->cmdbuf.vaddr, submit->cmdbuf.size,
			      etnaviv_cmdbuf_get_va(&submit->cmdbuf));
			      etnaviv_cmdbuf_get_va(&submit->cmdbuf,
						    &gpu->cmdbuf_mapping));

	/* Reserve space for the bomap */
	if (n_bomap_pages) {
+15 −4
Original line number Diff line number Diff line
@@ -687,8 +687,8 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
	prefetch = etnaviv_buffer_init(gpu);

	gpu_write(gpu, VIVS_HI_INTR_ENBL, ~0U);
	etnaviv_gpu_start_fe(gpu, etnaviv_cmdbuf_get_va(&gpu->buffer),
			     prefetch);
	etnaviv_gpu_start_fe(gpu, etnaviv_cmdbuf_get_va(&gpu->buffer,
			     &gpu->cmdbuf_mapping), prefetch);
}

int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
@@ -767,16 +767,24 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
		goto destroy_iommu;
	}

	ret = etnaviv_cmdbuf_suballoc_map(gpu->cmdbuf_suballoc, gpu->mmu,
					  &gpu->cmdbuf_mapping,
					  gpu->memory_base);
	if (ret) {
		dev_err(gpu->dev, "failed to map cmdbuf suballoc\n");
		goto destroy_suballoc;
	}

	/* Create buffer: */
	ret = etnaviv_cmdbuf_init(gpu->cmdbuf_suballoc, &gpu->buffer,
				  PAGE_SIZE);
	if (ret) {
		dev_err(gpu->dev, "could not create command buffer\n");
		goto destroy_suballoc;
		goto unmap_suballoc;
	}

	if (gpu->mmu->version == ETNAVIV_IOMMU_V1 &&
	    etnaviv_cmdbuf_get_va(&gpu->buffer) > 0x80000000) {
	    etnaviv_cmdbuf_get_va(&gpu->buffer, &gpu->cmdbuf_mapping) > 0x80000000) {
		ret = -EINVAL;
		dev_err(gpu->dev,
			"command buffer outside valid memory window\n");
@@ -805,6 +813,8 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)

free_buffer:
	etnaviv_cmdbuf_free(&gpu->buffer);
unmap_suballoc:
	etnaviv_cmdbuf_suballoc_unmap(gpu->mmu, &gpu->cmdbuf_mapping);
destroy_suballoc:
	etnaviv_cmdbuf_suballoc_destroy(gpu->cmdbuf_suballoc);
destroy_iommu:
@@ -1681,6 +1691,7 @@ static void etnaviv_gpu_unbind(struct device *dev, struct device *master,

	if (gpu->initialized) {
		etnaviv_cmdbuf_free(&gpu->buffer);
		etnaviv_cmdbuf_suballoc_unmap(gpu->mmu, &gpu->cmdbuf_mapping);
		etnaviv_cmdbuf_suballoc_destroy(gpu->cmdbuf_suballoc);
		etnaviv_iommu_destroy(gpu->mmu);
		gpu->initialized = false;
Loading