Commit f97decac authored by Jordan Crouse's avatar Jordan Crouse Committed by Rob Clark
Browse files

drm/msm: Support multiple ringbuffers



Add the infrastructure to support the idea of multiple ringbuffers.
Assign each ringbuffer an id and use that as an index for the various
ring specific operations.

The biggest delta is to support legacy fences. Each fence gets its own
sequence number but the legacy functions expect to use a unique integer.
To handle this we return a unique identifier for each submission but
map it to a specific ring/sequence under the covers. Newer users use
a dma_fence pointer anyway so they don't care about the actual sequence
ID or ring.

The actual mechanics for multiple ringbuffers are very target specific
so this code just allows for the possibility but still only defines
one ringbuffer for each target family.

Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
parent cd414f3d
Loading
Loading
Loading
Loading
+5 −4
Original line number Original line Diff line number Diff line
@@ -44,7 +44,7 @@ static bool a3xx_idle(struct msm_gpu *gpu);


static bool a3xx_me_init(struct msm_gpu *gpu)
static bool a3xx_me_init(struct msm_gpu *gpu)
{
{
	struct msm_ringbuffer *ring = gpu->rb;
	struct msm_ringbuffer *ring = gpu->rb[0];


	OUT_PKT3(ring, CP_ME_INIT, 17);
	OUT_PKT3(ring, CP_ME_INIT, 17);
	OUT_RING(ring, 0x000003f7);
	OUT_RING(ring, 0x000003f7);
@@ -65,7 +65,7 @@ static bool a3xx_me_init(struct msm_gpu *gpu)
	OUT_RING(ring, 0x00000000);
	OUT_RING(ring, 0x00000000);
	OUT_RING(ring, 0x00000000);
	OUT_RING(ring, 0x00000000);


	gpu->funcs->flush(gpu);
	gpu->funcs->flush(gpu, ring);
	return a3xx_idle(gpu);
	return a3xx_idle(gpu);
}
}


@@ -339,7 +339,7 @@ static void a3xx_destroy(struct msm_gpu *gpu)
static bool a3xx_idle(struct msm_gpu *gpu)
static bool a3xx_idle(struct msm_gpu *gpu)
{
{
	/* wait for ringbuffer to drain: */
	/* wait for ringbuffer to drain: */
	if (!adreno_idle(gpu))
	if (!adreno_idle(gpu, gpu->rb[0]))
		return false;
		return false;


	/* then wait for GPU to finish: */
	/* then wait for GPU to finish: */
@@ -446,6 +446,7 @@ static const struct adreno_gpu_funcs funcs = {
		.recover = a3xx_recover,
		.recover = a3xx_recover,
		.submit = adreno_submit,
		.submit = adreno_submit,
		.flush = adreno_flush,
		.flush = adreno_flush,
		.active_ring = adreno_active_ring,
		.irq = a3xx_irq,
		.irq = a3xx_irq,
		.destroy = a3xx_destroy,
		.destroy = a3xx_destroy,
#ifdef CONFIG_DEBUG_FS
#ifdef CONFIG_DEBUG_FS
@@ -491,7 +492,7 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
	adreno_gpu->registers = a3xx_registers;
	adreno_gpu->registers = a3xx_registers;
	adreno_gpu->reg_offsets = a3xx_register_offsets;
	adreno_gpu->reg_offsets = a3xx_register_offsets;


	ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs);
	ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
	if (ret)
	if (ret)
		goto fail;
		goto fail;


+5 −4
Original line number Original line Diff line number Diff line
@@ -116,7 +116,7 @@ static void a4xx_enable_hwcg(struct msm_gpu *gpu)


static bool a4xx_me_init(struct msm_gpu *gpu)
static bool a4xx_me_init(struct msm_gpu *gpu)
{
{
	struct msm_ringbuffer *ring = gpu->rb;
	struct msm_ringbuffer *ring = gpu->rb[0];


	OUT_PKT3(ring, CP_ME_INIT, 17);
	OUT_PKT3(ring, CP_ME_INIT, 17);
	OUT_RING(ring, 0x000003f7);
	OUT_RING(ring, 0x000003f7);
@@ -137,7 +137,7 @@ static bool a4xx_me_init(struct msm_gpu *gpu)
	OUT_RING(ring, 0x00000000);
	OUT_RING(ring, 0x00000000);
	OUT_RING(ring, 0x00000000);
	OUT_RING(ring, 0x00000000);


	gpu->funcs->flush(gpu);
	gpu->funcs->flush(gpu, ring);
	return a4xx_idle(gpu);
	return a4xx_idle(gpu);
}
}


@@ -337,7 +337,7 @@ static void a4xx_destroy(struct msm_gpu *gpu)
static bool a4xx_idle(struct msm_gpu *gpu)
static bool a4xx_idle(struct msm_gpu *gpu)
{
{
	/* wait for ringbuffer to drain: */
	/* wait for ringbuffer to drain: */
	if (!adreno_idle(gpu))
	if (!adreno_idle(gpu, gpu->rb[0]))
		return false;
		return false;


	/* then wait for GPU to finish: */
	/* then wait for GPU to finish: */
@@ -534,6 +534,7 @@ static const struct adreno_gpu_funcs funcs = {
		.recover = a4xx_recover,
		.recover = a4xx_recover,
		.submit = adreno_submit,
		.submit = adreno_submit,
		.flush = adreno_flush,
		.flush = adreno_flush,
		.active_ring = adreno_active_ring,
		.irq = a4xx_irq,
		.irq = a4xx_irq,
		.destroy = a4xx_destroy,
		.destroy = a4xx_destroy,
#ifdef CONFIG_DEBUG_FS
#ifdef CONFIG_DEBUG_FS
@@ -573,7 +574,7 @@ struct msm_gpu *a4xx_gpu_init(struct drm_device *dev)
	adreno_gpu->registers = a4xx_registers;
	adreno_gpu->registers = a4xx_registers;
	adreno_gpu->reg_offsets = a4xx_register_offsets;
	adreno_gpu->reg_offsets = a4xx_register_offsets;


	ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs);
	ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
	if (ret)
	if (ret)
		goto fail;
		goto fail;


+28 −26
Original line number Original line Diff line number Diff line
@@ -117,7 +117,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
	struct msm_file_private *ctx)
	struct msm_file_private *ctx)
{
{
	struct msm_drm_private *priv = gpu->dev->dev_private;
	struct msm_drm_private *priv = gpu->dev->dev_private;
	struct msm_ringbuffer *ring = gpu->rb;
	struct msm_ringbuffer *ring = submit->ring;
	unsigned int i, ibs = 0;
	unsigned int i, ibs = 0;


	for (i = 0; i < submit->nr_cmds; i++) {
	for (i = 0; i < submit->nr_cmds; i++) {
@@ -138,15 +138,15 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
	}
	}


	OUT_PKT4(ring, REG_A5XX_CP_SCRATCH_REG(2), 1);
	OUT_PKT4(ring, REG_A5XX_CP_SCRATCH_REG(2), 1);
	OUT_RING(ring, submit->fence->seqno);
	OUT_RING(ring, submit->seqno);


	OUT_PKT7(ring, CP_EVENT_WRITE, 4);
	OUT_PKT7(ring, CP_EVENT_WRITE, 4);
	OUT_RING(ring, CACHE_FLUSH_TS | (1 << 31));
	OUT_RING(ring, CACHE_FLUSH_TS | (1 << 31));
	OUT_RING(ring, lower_32_bits(rbmemptr(gpu, fence)));
	OUT_RING(ring, lower_32_bits(rbmemptr(ring, fence)));
	OUT_RING(ring, upper_32_bits(rbmemptr(gpu, fence)));
	OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence)));
	OUT_RING(ring, submit->fence->seqno);
	OUT_RING(ring, submit->seqno);


	gpu->funcs->flush(gpu);
	gpu->funcs->flush(gpu, ring);
}
}


static const struct {
static const struct {
@@ -262,7 +262,7 @@ void a5xx_set_hwcg(struct msm_gpu *gpu, bool state)
static int a5xx_me_init(struct msm_gpu *gpu)
static int a5xx_me_init(struct msm_gpu *gpu)
{
{
	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
	struct msm_ringbuffer *ring = gpu->rb;
	struct msm_ringbuffer *ring = gpu->rb[0];


	OUT_PKT7(ring, CP_ME_INIT, 8);
	OUT_PKT7(ring, CP_ME_INIT, 8);


@@ -293,9 +293,8 @@ static int a5xx_me_init(struct msm_gpu *gpu)
	OUT_RING(ring, 0x00000000);
	OUT_RING(ring, 0x00000000);
	OUT_RING(ring, 0x00000000);
	OUT_RING(ring, 0x00000000);


	gpu->funcs->flush(gpu);
	gpu->funcs->flush(gpu, ring);

	return a5xx_idle(gpu, ring) ? 0 : -EINVAL;
	return a5xx_idle(gpu) ? 0 : -EINVAL;
}
}


static struct drm_gem_object *a5xx_ucode_load_bo(struct msm_gpu *gpu,
static struct drm_gem_object *a5xx_ucode_load_bo(struct msm_gpu *gpu,
@@ -581,11 +580,11 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
	 * ticking correctly
	 * ticking correctly
	 */
	 */
	if (adreno_is_a530(adreno_gpu)) {
	if (adreno_is_a530(adreno_gpu)) {
		OUT_PKT7(gpu->rb, CP_EVENT_WRITE, 1);
		OUT_PKT7(gpu->rb[0], CP_EVENT_WRITE, 1);
		OUT_RING(gpu->rb, 0x0F);
		OUT_RING(gpu->rb[0], 0x0F);


		gpu->funcs->flush(gpu);
		gpu->funcs->flush(gpu, gpu->rb[0]);
		if (!a5xx_idle(gpu))
		if (!a5xx_idle(gpu, gpu->rb[0]))
			return -EINVAL;
			return -EINVAL;
	}
	}


@@ -598,11 +597,11 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
	 */
	 */
	ret = a5xx_zap_shader_init(gpu);
	ret = a5xx_zap_shader_init(gpu);
	if (!ret) {
	if (!ret) {
		OUT_PKT7(gpu->rb, CP_SET_SECURE_MODE, 1);
		OUT_PKT7(gpu->rb[0], CP_SET_SECURE_MODE, 1);
		OUT_RING(gpu->rb, 0x00000000);
		OUT_RING(gpu->rb[0], 0x00000000);


		gpu->funcs->flush(gpu);
		gpu->funcs->flush(gpu, gpu->rb[0]);
		if (!a5xx_idle(gpu))
		if (!a5xx_idle(gpu, gpu->rb[0]))
			return -EINVAL;
			return -EINVAL;
	} else {
	} else {
		/* Print a warning so if we die, we know why */
		/* Print a warning so if we die, we know why */
@@ -676,18 +675,19 @@ static inline bool _a5xx_check_idle(struct msm_gpu *gpu)
		A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT);
		A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT);
}
}


bool a5xx_idle(struct msm_gpu *gpu)
bool a5xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
{
{
	/* wait for CP to drain ringbuffer: */
	/* wait for CP to drain ringbuffer: */
	if (!adreno_idle(gpu))
	if (!adreno_idle(gpu, ring))
		return false;
		return false;


	if (spin_until(_a5xx_check_idle(gpu))) {
	if (spin_until(_a5xx_check_idle(gpu))) {
		DRM_ERROR("%s: %ps: timeout waiting for GPU to idle: status %8.8X irq %8.8X\n",
		DRM_ERROR("%s: %ps: timeout waiting for GPU to idle: status %8.8X irq %8.8X rptr/wptr %d/%d\n",
			gpu->name, __builtin_return_address(0),
			gpu->name, __builtin_return_address(0),
			gpu_read(gpu, REG_A5XX_RBBM_STATUS),
			gpu_read(gpu, REG_A5XX_RBBM_STATUS),
			gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS));
			gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS),

			gpu_read(gpu, REG_A5XX_CP_RB_RPTR),
			gpu_read(gpu, REG_A5XX_CP_RB_WPTR));
		return false;
		return false;
	}
	}


@@ -818,9 +818,10 @@ static void a5xx_fault_detect_irq(struct msm_gpu *gpu)
{
{
	struct drm_device *dev = gpu->dev;
	struct drm_device *dev = gpu->dev;
	struct msm_drm_private *priv = dev->dev_private;
	struct msm_drm_private *priv = dev->dev_private;
	struct msm_ringbuffer *ring = gpu->funcs->active_ring(gpu);


	dev_err(dev->dev, "gpu fault fence %x status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x\n",
	dev_err(dev->dev, "gpu fault ring %d fence %x status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x\n",
		gpu->memptrs->fence,
		ring ? ring->id : -1, ring ? ring->seqno : 0,
		gpu_read(gpu, REG_A5XX_RBBM_STATUS),
		gpu_read(gpu, REG_A5XX_RBBM_STATUS),
		gpu_read(gpu, REG_A5XX_CP_RB_RPTR),
		gpu_read(gpu, REG_A5XX_CP_RB_RPTR),
		gpu_read(gpu, REG_A5XX_CP_RB_WPTR),
		gpu_read(gpu, REG_A5XX_CP_RB_WPTR),
@@ -1010,6 +1011,7 @@ static const struct adreno_gpu_funcs funcs = {
		.recover = a5xx_recover,
		.recover = a5xx_recover,
		.submit = a5xx_submit,
		.submit = a5xx_submit,
		.flush = adreno_flush,
		.flush = adreno_flush,
		.active_ring = adreno_active_ring,
		.irq = a5xx_irq,
		.irq = a5xx_irq,
		.destroy = a5xx_destroy,
		.destroy = a5xx_destroy,
#ifdef CONFIG_DEBUG_FS
#ifdef CONFIG_DEBUG_FS
@@ -1045,7 +1047,7 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)


	a5xx_gpu->lm_leakage = 0x4E001A;
	a5xx_gpu->lm_leakage = 0x4E001A;


	ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs);
	ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
	if (ret) {
	if (ret) {
		a5xx_destroy(&(a5xx_gpu->base.base));
		a5xx_destroy(&(a5xx_gpu->base.base));
		return ERR_PTR(ret);
		return ERR_PTR(ret);
+1 −1
Original line number Original line Diff line number Diff line
@@ -55,7 +55,7 @@ static inline int spin_usecs(struct msm_gpu *gpu, uint32_t usecs,
	return -ETIMEDOUT;
	return -ETIMEDOUT;
}
}


bool a5xx_idle(struct msm_gpu *gpu);
bool a5xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
void a5xx_set_hwcg(struct msm_gpu *gpu, bool state);
void a5xx_set_hwcg(struct msm_gpu *gpu, bool state);


#endif /* __A5XX_GPU_H__ */
#endif /* __A5XX_GPU_H__ */
+3 −3
Original line number Original line Diff line number Diff line
@@ -173,7 +173,7 @@ static int a5xx_gpmu_init(struct msm_gpu *gpu)
{
{
	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
	struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
	struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
	struct msm_ringbuffer *ring = gpu->rb;
	struct msm_ringbuffer *ring = gpu->rb[0];


	if (!a5xx_gpu->gpmu_dwords)
	if (!a5xx_gpu->gpmu_dwords)
		return 0;
		return 0;
@@ -192,9 +192,9 @@ static int a5xx_gpmu_init(struct msm_gpu *gpu)
	OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1);
	OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1);
	OUT_RING(ring, 1);
	OUT_RING(ring, 1);


	gpu->funcs->flush(gpu);
	gpu->funcs->flush(gpu, ring);


	if (!a5xx_idle(gpu)) {
	if (!a5xx_idle(gpu, ring)) {
		DRM_ERROR("%s: Unable to load GPMU firmware. GPMU will not be active\n",
		DRM_ERROR("%s: Unable to load GPMU firmware. GPMU will not be active\n",
			gpu->name);
			gpu->name);
		return -EINVAL;
		return -EINVAL;
Loading