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

Commit 0d44684c authored by Harshdeep Dhatt's avatar Harshdeep Dhatt
Browse files

msm: kgsl: Take GMU snapshot on GMU failures



GMU can fail to turn on GX or it can fail the START HFI.
So take snapshot and put GMU in NMI. When this happens,
kgsl will call gmu_stop() and as GMU is already in fault
aka NMI, reset the GMU and GPU. If oob during adreno_stop
fails, take gmu snapshot and only do things that don't need
gx to be on.

Change-Id: Iafc9b34063a7ff2415d3462dd289b52e425fbf3b
Signed-off-by: default avatarHarshdeep Dhatt <hdhatt@codeaurora.org>
parent 7e53b80b
Loading
Loading
Loading
Loading
+19 −25
Original line number Diff line number Diff line
@@ -2057,12 +2057,16 @@ static int _adreno_start(struct adreno_device *adreno_dev)

	/* Send OOB request to turn on the GX */
	status = gmu_core_dev_oob_set(device, oob_gpu);
	if (status)
		goto error_boot_oob_clear;
	if (status) {
		gmu_core_snapshot(device);
		goto error_oob_clear;
	}

	status = gmu_core_dev_hfi_start_msg(device);
	if (status)
	if (status) {
		gmu_core_snapshot(device);
		goto error_oob_clear;
	}

	if (device->pwrctrl.bus_control) {
		/* VBIF waiting for RAM */
@@ -2274,29 +2278,15 @@ static int adreno_stop(struct kgsl_device *device)
	error = gmu_core_dev_oob_set(device, oob_gpu);
	if (error) {
		gmu_core_dev_oob_clear(device, oob_gpu);

		if (gmu_core_regulator_isenabled(device)) {
			/* GPU is on. Try recovery */
			set_bit(GMU_FAULT, &device->gmu_core.flags);
			gmu_core_snapshot(device);
			error = -EINVAL;
			goto no_gx_power;
	}
	}

	adreno_dispatcher_stop(adreno_dev);

	adreno_ringbuffer_stop(adreno_dev);

	kgsl_pwrscale_update_stats(device);

	adreno_irqctrl(adreno_dev, 0);

	if (!IS_ERR_OR_NULL(adreno_dev->gpu_llc_slice))
		llcc_slice_deactivate(adreno_dev->gpu_llc_slice);

	if (!IS_ERR_OR_NULL(adreno_dev->gpuhtw_llc_slice))
		llcc_slice_deactivate(adreno_dev->gpuhtw_llc_slice);

	/* Save active coresight registers if applicable */
	adreno_coresight_stop(adreno_dev);

@@ -2314,19 +2304,23 @@ static int adreno_stop(struct kgsl_device *device)
	 */

	if (!error && gmu_core_dev_wait_for_lowest_idle(device)) {
		set_bit(GMU_FAULT, &device->gmu_core.flags);
		gmu_core_snapshot(device);
		/*
		 * Assume GMU hang after 10ms without responding.
		 * It shall be relative safe to clear vbif and stop
		 * MMU later. Early return in adreno_stop function
		 * will result in kernel panic in adreno_start
		 */
		error = -EINVAL;
	}

	adreno_clear_pending_transactions(device);

no_gx_power:
	adreno_dispatcher_stop(adreno_dev);

	adreno_ringbuffer_stop(adreno_dev);

	if (!IS_ERR_OR_NULL(adreno_dev->gpu_llc_slice))
		llcc_slice_deactivate(adreno_dev->gpu_llc_slice);

	if (!IS_ERR_OR_NULL(adreno_dev->gpuhtw_llc_slice))
		llcc_slice_deactivate(adreno_dev->gpuhtw_llc_slice);

	/*
	 * The halt is not cleared in the above function if we have GBIF.
	 * Clear it here if GMU is enabled as GMU stop needs access to
+11 −0
Original line number Diff line number Diff line
@@ -1674,6 +1674,12 @@ static void gmu_stop(struct kgsl_device *device)
	if (!test_bit(GMU_CLK_ON, &device->gmu_core.flags))
		return;

	/* Force suspend if gmu is already in fault */
	if (test_bit(GMU_FAULT, &device->gmu_core.flags)) {
		gmu_core_suspend(device);
		return;
	}

	/* Wait for the lowest idle level we requested */
	if (gmu_core_dev_wait_for_lowest_idle(device))
		goto error;
@@ -1701,6 +1707,11 @@ static void gmu_stop(struct kgsl_device *device)
error:
	dev_err(&gmu->pdev->dev, "Failed to stop GMU\n");
	gmu_core_snapshot(device);
	/*
	 * We failed to stop the gmu successfully. Force a suspend
	 * to set things up for a fresh start.
	 */
	gmu_core_suspend(device);
}

static void gmu_remove(struct kgsl_device *device)