mirror of
https://github.com/torvalds/linux.git
synced 2026-05-13 00:28:54 +02:00
drm/msm/adreno: Disable IFPC when sysprof is active
Moving to IFPC state clears the 'Perfcounter Select' register setup by the userspace. So, lets block the IFPC when sysprof is active by using the perfcounter oob signal to the GMU. Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com> Patchwork: https://patchwork.freedesktop.org/patch/673380/ Signed-off-by: Rob Clark <robin.clark@oss.qualcomm.com>
This commit is contained in:
parent
a242ef4a75
commit
62cd0fa699
|
|
@ -1157,6 +1157,11 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
|
|||
/* Set the GPU to the current freq */
|
||||
a6xx_gmu_set_initial_freq(gpu, gmu);
|
||||
|
||||
if (refcount_read(&gpu->sysprof_active) > 1) {
|
||||
ret = a6xx_gmu_set_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
|
||||
if (!ret)
|
||||
set_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status);
|
||||
}
|
||||
out:
|
||||
/* On failure, shut down the GMU to leave it in a good state */
|
||||
if (ret) {
|
||||
|
|
@ -1204,6 +1209,9 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu)
|
|||
a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status))
|
||||
a6xx_gmu_clear_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
|
||||
|
||||
ret = a6xx_gmu_wait_for_idle(gmu);
|
||||
|
||||
/* If the GMU isn't responding assume it is hung */
|
||||
|
|
@ -1817,6 +1825,35 @@ static int a6xx_gmu_get_irq(struct a6xx_gmu *gmu, struct platform_device *pdev,
|
|||
return irq;
|
||||
}
|
||||
|
||||
void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
|
||||
unsigned int sysprof_active;
|
||||
|
||||
/* Nothing to do if GPU is suspended. We will handle this during GMU resume */
|
||||
if (!pm_runtime_get_if_active(&gpu->pdev->dev))
|
||||
return;
|
||||
|
||||
mutex_lock(&gmu->lock);
|
||||
|
||||
sysprof_active = refcount_read(&gpu->sysprof_active);
|
||||
|
||||
/*
|
||||
* 'Perfcounter select' register values are lost during IFPC collapse. To avoid that,
|
||||
* use the currently unused perfcounter oob vote to block IFPC when sysprof is active
|
||||
*/
|
||||
if ((sysprof_active > 1) && !test_and_set_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status))
|
||||
a6xx_gmu_set_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
|
||||
else if ((sysprof_active == 1) && test_and_clear_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status))
|
||||
a6xx_gmu_clear_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
|
||||
|
||||
mutex_unlock(&gmu->lock);
|
||||
|
||||
pm_runtime_put(&gpu->pdev->dev);
|
||||
}
|
||||
|
||||
void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
|
||||
|
|
|
|||
|
|
@ -125,6 +125,8 @@ struct a6xx_gmu {
|
|||
#define GMU_STATUS_FW_START 0
|
||||
/* To track if PDC sleep seq was done */
|
||||
#define GMU_STATUS_PDC_SLEEP 1
|
||||
/* To track Perfcounter OOB set status */
|
||||
#define GMU_STATUS_OOB_PERF_SET 2
|
||||
unsigned long status;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2536,6 +2536,7 @@ static const struct adreno_gpu_funcs funcs = {
|
|||
.create_private_vm = a6xx_create_private_vm,
|
||||
.get_rptr = a6xx_get_rptr,
|
||||
.progress = a6xx_progress,
|
||||
.sysprof_setup = a6xx_gmu_sysprof_setup,
|
||||
},
|
||||
.get_timestamp = a6xx_gmu_get_timestamp,
|
||||
};
|
||||
|
|
@ -2596,6 +2597,7 @@ static const struct adreno_gpu_funcs funcs_a7xx = {
|
|||
.create_private_vm = a6xx_create_private_vm,
|
||||
.get_rptr = a6xx_get_rptr,
|
||||
.progress = a6xx_progress,
|
||||
.sysprof_setup = a6xx_gmu_sysprof_setup,
|
||||
},
|
||||
.get_timestamp = a6xx_gmu_get_timestamp,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -254,6 +254,7 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state);
|
|||
int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
|
||||
int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
|
||||
void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu);
|
||||
void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu);
|
||||
|
||||
void a6xx_preempt_init(struct msm_gpu *gpu);
|
||||
void a6xx_preempt_hw_init(struct msm_gpu *gpu);
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ struct msm_gpu_funcs {
|
|||
* for cmdstream that is buffered in this FIFO upstream of the CP fw.
|
||||
*/
|
||||
bool (*progress)(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
|
||||
void (*sysprof_setup)(struct msm_gpu *gpu);
|
||||
};
|
||||
|
||||
/* Additional state for iommu faults: */
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@ int msm_context_set_sysprof(struct msm_context *ctx, struct msm_gpu *gpu, int sy
|
|||
break;
|
||||
}
|
||||
|
||||
/* Some gpu families require additional setup for sysprof */
|
||||
if (gpu->funcs->sysprof_setup)
|
||||
gpu->funcs->sysprof_setup(gpu);
|
||||
|
||||
ctx->sysprof = sysprof;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user