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

Commit 4471b4c1 authored by Jordan Crouse's avatar Jordan Crouse
Browse files

msm: kgsl: Add debugging for CP_INIT failures



Failure during CP_INIT (ringbuffer initalization) could be an
indication of any number of interesting and challenging issues.
Print a number of possibly useful register values to the kmsg in
addition to forcing a full snapshot.

Also reduce the timeout on any start operation from 20 seconds
down to 2 seconds. No init operation should ever take that long
and it allows us to debug issues quicker and gives the
rest of the system less time to pile on additional fences and
other things that might bring the world to a halt faster.

Change-Id: Ic0dedbad1ad5c5113670189f711a71170fa59acc
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent fee2547d
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -2217,13 +2217,14 @@ bool adreno_isidle(struct kgsl_device *device)
/**
 * adreno_spin_idle() - Spin wait for the GPU to idle
 * @device: Pointer to the KGSL device
 * @timeout: milliseconds to wait before returning error
 *
 * Spin the CPU waiting for the RBBM status to return idle
 */
int adreno_spin_idle(struct kgsl_device *device)
int adreno_spin_idle(struct kgsl_device *device, unsigned int timeout)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	unsigned long wait = jiffies + msecs_to_jiffies(ADRENO_IDLE_TIMEOUT);
	unsigned long wait = jiffies + msecs_to_jiffies(timeout);

	kgsl_cffdump_regpoll(device,
		adreno_getreg(adreno_dev, ADRENO_REG_RBBM_STATUS) << 2,
@@ -2277,7 +2278,7 @@ int adreno_idle(struct kgsl_device *device)
	if (ret)
		return ret;

	return adreno_spin_idle(device);
	return adreno_spin_idle(device, ADRENO_IDLE_TIMEOUT);
}

/**
+1 −1
Original line number Diff line number Diff line
@@ -802,7 +802,7 @@ long adreno_ioctl_helper(struct kgsl_device_private *dev_priv,
		unsigned int cmd, unsigned long arg,
		const struct kgsl_ioctl *cmds, int len);

int adreno_spin_idle(struct kgsl_device *device);
int adreno_spin_idle(struct kgsl_device *device, unsigned int timeout);
int adreno_idle(struct kgsl_device *device);
bool adreno_isidle(struct kgsl_device *device);

+11 −3
Original line number Diff line number Diff line
@@ -635,6 +635,8 @@ static int a3xx_rb_init(struct adreno_device *adreno_dev,
			 struct adreno_ringbuffer *rb)
{
	unsigned int *cmds;
	int ret;

	cmds = adreno_ringbuffer_allocspace(rb, 18);
	if (IS_ERR(cmds))
		return PTR_ERR(cmds);
@@ -664,9 +666,15 @@ static int a3xx_rb_init(struct adreno_device *adreno_dev,
	*cmds++ = 0x00000000;
	*cmds++ = 0x00000000;

	adreno_ringbuffer_submit(rb, NULL);
	ret = adreno_ringbuffer_submit_spin(rb, NULL, 2000);
	if (ret) {
		struct kgsl_device *device = &adreno_dev->dev;

	return 0;
		dev_err(device->dev, "CP initialization failed to idle\n");
		kgsl_device_snapshot(device, NULL);
	}

	return ret;
}

/*
@@ -1726,7 +1734,7 @@ static int _ringbuffer_bootstrap_ucode(struct adreno_ringbuffer *rb,
	}

	/* idle device to validate bootstrap */
	ret = adreno_spin_idle(device);
	ret = adreno_spin_idle(device, 2000);

	if (ret) {
		KGSL_DRV_ERR(rb->device,
+11 −2
Original line number Diff line number Diff line
@@ -1576,6 +1576,8 @@ static int a4xx_rb_init(struct adreno_device *adreno_dev,
			 struct adreno_ringbuffer *rb)
{
	unsigned int *cmds;
	int ret;

	cmds = adreno_ringbuffer_allocspace(rb, 20);
	if (IS_ERR(cmds))
		return PTR_ERR(cmds);
@@ -1614,8 +1616,15 @@ static int a4xx_rb_init(struct adreno_device *adreno_dev,
	*cmds++ = cp_type3_packet(CP_PREEMPT_ENABLE, 1);
	*cmds++ = 1;

	adreno_ringbuffer_submit(rb, NULL);
	return 0;
	ret = adreno_ringbuffer_submit_spin(rb, NULL, 2000);
	if (ret) {
		struct kgsl_device *device = &adreno_dev->dev;

		dev_err(device->dev, "CP initialization failed to idle\n");
		kgsl_device_snapshot(device, NULL);
	}

	return ret;
}

static ADRENO_CORESIGHT_ATTR(cfg_debbus_ctrlt, &a4xx_coresight_registers[0]);
+47 −15
Original line number Diff line number Diff line
@@ -1001,9 +1001,7 @@ static int _gpmu_send_init_cmds(struct adreno_device *adreno_dev)

	/* Copy to the RB the predefined fw sequence cmds */
	memcpy(cmds, adreno_dev->gpmu_cmds, size << 2);
	adreno_ringbuffer_submit(rb, NULL);

	return adreno_spin_idle(&adreno_dev->dev);
	return adreno_ringbuffer_submit_spin(rb, NULL, 2000);
}

/*
@@ -1994,11 +1992,31 @@ static int _preemption_init(
	return cmds - cmds_orig;
}

/* Print some key registers if a spin-for-idle times out */
static void spin_idle_debug(struct kgsl_device *device)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	unsigned int rptr, wptr;
	unsigned int status, status3, intstatus;
	unsigned int hwfault;

	adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_RPTR, &rptr);
	adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_WPTR, &wptr);

	kgsl_regread(device, A5XX_RBBM_STATUS, &status);
	kgsl_regread(device, A5XX_RBBM_STATUS3, &status3);
	kgsl_regread(device, A5XX_RBBM_INT_0_STATUS, &intstatus);
	kgsl_regread(device, A5XX_CP_HW_FAULT, &hwfault);

	dev_err(device->dev,
		" rb=%X/%X rbbm_status=%8.8X/%8.8X int_0_status=%8.8X\n",
		rptr, wptr, status, status3, intstatus);
	dev_err(device->dev, " hwfault=%8.8X\n", hwfault);
}

static void a5xx_post_start(struct adreno_device *adreno_dev)
{
	unsigned int *cmds, *start;
	int status = 0;
	struct kgsl_device *device = &(adreno_dev->dev);
	struct adreno_ringbuffer *rb = adreno_dev->cur_rb;

	cmds = adreno_ringbuffer_allocspace(rb, 42);
@@ -2024,13 +2042,10 @@ static void a5xx_post_start(struct adreno_device *adreno_dev)
	if (cmds == start)
		return;

	adreno_ringbuffer_submit(rb, NULL);
	if (adreno_ringbuffer_submit_spin(rb, NULL, 2000)) {
		struct kgsl_device *device = &adreno_dev->dev;

	/* idle device to validate hw INIT */
	status = adreno_spin_idle(device);
	if (status) {
		KGSL_DRV_ERR(rb->device,
		"hw initialization failed to idle\n");
		KGSL_DRV_ERR(device, "hw initialization failed to idle\n");
		kgsl_device_snapshot(device, NULL);
	}
}
@@ -2075,6 +2090,7 @@ static int a5xx_rb_init(struct adreno_device *adreno_dev,
			 struct adreno_ringbuffer *rb)
{
	unsigned int *cmds;
	int ret;

	cmds = adreno_ringbuffer_allocspace(rb, 8);
	if (IS_ERR(cmds))
@@ -2104,15 +2120,23 @@ static int a5xx_rb_init(struct adreno_device *adreno_dev,
	*cmds++ = 0x00000000;
	*cmds++ = 0x00000000;

	adreno_ringbuffer_submit(rb, NULL);
	ret = adreno_ringbuffer_submit_spin(rb, NULL, 2000);
	if (ret != 0) {
		struct kgsl_device *device = &adreno_dev->dev;

	return 0;
		dev_err(device->dev, "CP initialization failed to idle\n");
		spin_idle_debug(device);
		kgsl_device_snapshot(device, NULL);
	}

	return ret;
}

int a5xx_switch_to_unsecure_mode(struct adreno_device *adreno_dev,
				struct adreno_ringbuffer *rb)
{
	unsigned int *cmds;
	int ret;

	cmds = adreno_ringbuffer_allocspace(rb, 2);
	if (IS_ERR(cmds))
@@ -2122,8 +2146,16 @@ int a5xx_switch_to_unsecure_mode(struct adreno_device *adreno_dev,

	cmds += cp_secure_mode(adreno_dev, cmds, 0);

	adreno_ringbuffer_submit(rb, NULL);
	return 0;
	ret = adreno_ringbuffer_submit_spin(rb, NULL, 2000);
	if (ret != 0) {
		struct kgsl_device *device = &adreno_dev->dev;

		dev_err(device->dev, "Switch to unsecure failed to idle\n");
		spin_idle_debug(device);
		kgsl_device_snapshot(device, NULL);
	}

	return ret;
}

static int _load_firmware(struct adreno_device *adreno_dev, const char *fwfile,
Loading