mirror of
https://github.com/torvalds/linux.git
synced 2024-12-26 21:02:19 +00:00
drm/msm/devfreq: Add 1ms delay before clamping freq
Add a short delay before clamping to idle frequency on active->idle transition. It takes ~0.5ms to increase the freq again on the next idle->active transition, so this helps avoid extra freq transitions on workloads that bounce between CPU and GPU. Signed-off-by: Rob Clark <robdclark@chromium.org> Link: https://lore.kernel.org/r/20210927230455.1066297-2-robdclark@gmail.com Signed-off-by: Rob Clark <robdclark@chromium.org>
This commit is contained in:
parent
ddb6e37a50
commit
658f4c8296
@ -112,6 +112,13 @@ struct msm_gpu_devfreq {
|
||||
* it is inactive.
|
||||
*/
|
||||
unsigned long idle_freq;
|
||||
|
||||
/**
|
||||
* idle_work:
|
||||
*
|
||||
* Used to delay clamping to idle freq on active->idle transition.
|
||||
*/
|
||||
struct msm_hrtimer_work idle_work;
|
||||
};
|
||||
|
||||
struct msm_gpu {
|
||||
|
@ -88,8 +88,12 @@ static struct devfreq_dev_profile msm_devfreq_profile = {
|
||||
.get_cur_freq = msm_devfreq_get_cur_freq,
|
||||
};
|
||||
|
||||
static void msm_devfreq_idle_work(struct kthread_work *work);
|
||||
|
||||
void msm_devfreq_init(struct msm_gpu *gpu)
|
||||
{
|
||||
struct msm_gpu_devfreq *df = &gpu->devfreq;
|
||||
|
||||
/* We need target support to do devfreq */
|
||||
if (!gpu->funcs->gpu_busy)
|
||||
return;
|
||||
@ -105,25 +109,27 @@ void msm_devfreq_init(struct msm_gpu *gpu)
|
||||
msm_devfreq_profile.freq_table = NULL;
|
||||
msm_devfreq_profile.max_state = 0;
|
||||
|
||||
gpu->devfreq.devfreq = devm_devfreq_add_device(&gpu->pdev->dev,
|
||||
df->devfreq = devm_devfreq_add_device(&gpu->pdev->dev,
|
||||
&msm_devfreq_profile, DEVFREQ_GOV_SIMPLE_ONDEMAND,
|
||||
NULL);
|
||||
|
||||
if (IS_ERR(gpu->devfreq.devfreq)) {
|
||||
if (IS_ERR(df->devfreq)) {
|
||||
DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n");
|
||||
gpu->devfreq.devfreq = NULL;
|
||||
df->devfreq = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
devfreq_suspend_device(gpu->devfreq.devfreq);
|
||||
devfreq_suspend_device(df->devfreq);
|
||||
|
||||
gpu->cooling = of_devfreq_cooling_register(gpu->pdev->dev.of_node,
|
||||
gpu->devfreq.devfreq);
|
||||
gpu->cooling = of_devfreq_cooling_register(gpu->pdev->dev.of_node, df->devfreq);
|
||||
if (IS_ERR(gpu->cooling)) {
|
||||
DRM_DEV_ERROR(&gpu->pdev->dev,
|
||||
"Couldn't register GPU cooling device\n");
|
||||
gpu->cooling = NULL;
|
||||
}
|
||||
|
||||
msm_hrtimer_work_init(&df->idle_work, gpu->worker, msm_devfreq_idle_work,
|
||||
CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
}
|
||||
|
||||
void msm_devfreq_cleanup(struct msm_gpu *gpu)
|
||||
@ -154,6 +160,11 @@ void msm_devfreq_active(struct msm_gpu *gpu)
|
||||
if (!df->devfreq)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Cancel any pending transition to idle frequency:
|
||||
*/
|
||||
hrtimer_cancel(&df->idle_work.timer);
|
||||
|
||||
/*
|
||||
* Hold devfreq lock to synchronize with get_dev_status()/
|
||||
* target() callbacks
|
||||
@ -184,9 +195,12 @@ void msm_devfreq_active(struct msm_gpu *gpu)
|
||||
mutex_unlock(&df->devfreq->lock);
|
||||
}
|
||||
|
||||
void msm_devfreq_idle(struct msm_gpu *gpu)
|
||||
|
||||
static void msm_devfreq_idle_work(struct kthread_work *work)
|
||||
{
|
||||
struct msm_gpu_devfreq *df = &gpu->devfreq;
|
||||
struct msm_gpu_devfreq *df = container_of(work,
|
||||
struct msm_gpu_devfreq, idle_work.work);
|
||||
struct msm_gpu *gpu = container_of(df, struct msm_gpu, devfreq);
|
||||
unsigned long idle_freq, target_freq = 0;
|
||||
|
||||
if (!df->devfreq)
|
||||
@ -207,3 +221,11 @@ void msm_devfreq_idle(struct msm_gpu *gpu)
|
||||
|
||||
mutex_unlock(&df->devfreq->lock);
|
||||
}
|
||||
|
||||
void msm_devfreq_idle(struct msm_gpu *gpu)
|
||||
{
|
||||
struct msm_gpu_devfreq *df = &gpu->devfreq;
|
||||
|
||||
msm_hrtimer_queue_work(&df->idle_work, ms_to_ktime(1),
|
||||
HRTIMER_MODE_ABS);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user