mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02: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
					
				
					 2 changed files with 37 additions and 8 deletions
				
			
		| 
						 | 
					@ -112,6 +112,13 @@ struct msm_gpu_devfreq {
 | 
				
			||||||
	 * it is inactive.
 | 
						 * it is inactive.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	unsigned long idle_freq;
 | 
						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 {
 | 
					struct msm_gpu {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,8 +88,12 @@ static struct devfreq_dev_profile msm_devfreq_profile = {
 | 
				
			||||||
	.get_cur_freq = msm_devfreq_get_cur_freq,
 | 
						.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)
 | 
					void msm_devfreq_init(struct msm_gpu *gpu)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct msm_gpu_devfreq *df = &gpu->devfreq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* We need target support to do devfreq */
 | 
						/* We need target support to do devfreq */
 | 
				
			||||||
	if (!gpu->funcs->gpu_busy)
 | 
						if (!gpu->funcs->gpu_busy)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -105,25 +109,27 @@ void msm_devfreq_init(struct msm_gpu *gpu)
 | 
				
			||||||
	msm_devfreq_profile.freq_table = NULL;
 | 
						msm_devfreq_profile.freq_table = NULL;
 | 
				
			||||||
	msm_devfreq_profile.max_state = 0;
 | 
						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,
 | 
								&msm_devfreq_profile, DEVFREQ_GOV_SIMPLE_ONDEMAND,
 | 
				
			||||||
			NULL);
 | 
								NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (IS_ERR(gpu->devfreq.devfreq)) {
 | 
						if (IS_ERR(df->devfreq)) {
 | 
				
			||||||
		DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n");
 | 
							DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n");
 | 
				
			||||||
		gpu->devfreq.devfreq = NULL;
 | 
							df->devfreq = NULL;
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devfreq_suspend_device(gpu->devfreq.devfreq);
 | 
						devfreq_suspend_device(df->devfreq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gpu->cooling = of_devfreq_cooling_register(gpu->pdev->dev.of_node,
 | 
						gpu->cooling = of_devfreq_cooling_register(gpu->pdev->dev.of_node, df->devfreq);
 | 
				
			||||||
			gpu->devfreq.devfreq);
 | 
					 | 
				
			||||||
	if (IS_ERR(gpu->cooling)) {
 | 
						if (IS_ERR(gpu->cooling)) {
 | 
				
			||||||
		DRM_DEV_ERROR(&gpu->pdev->dev,
 | 
							DRM_DEV_ERROR(&gpu->pdev->dev,
 | 
				
			||||||
				"Couldn't register GPU cooling device\n");
 | 
									"Couldn't register GPU cooling device\n");
 | 
				
			||||||
		gpu->cooling = NULL;
 | 
							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)
 | 
					void msm_devfreq_cleanup(struct msm_gpu *gpu)
 | 
				
			||||||
| 
						 | 
					@ -154,6 +160,11 @@ void msm_devfreq_active(struct msm_gpu *gpu)
 | 
				
			||||||
	if (!df->devfreq)
 | 
						if (!df->devfreq)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Cancel any pending transition to idle frequency:
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						hrtimer_cancel(&df->idle_work.timer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Hold devfreq lock to synchronize with get_dev_status()/
 | 
						 * Hold devfreq lock to synchronize with get_dev_status()/
 | 
				
			||||||
	 * target() callbacks
 | 
						 * target() callbacks
 | 
				
			||||||
| 
						 | 
					@ -184,9 +195,12 @@ void msm_devfreq_active(struct msm_gpu *gpu)
 | 
				
			||||||
	mutex_unlock(&df->devfreq->lock);
 | 
						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;
 | 
						unsigned long idle_freq, target_freq = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!df->devfreq)
 | 
						if (!df->devfreq)
 | 
				
			||||||
| 
						 | 
					@ -207,3 +221,11 @@ void msm_devfreq_idle(struct msm_gpu *gpu)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_unlock(&df->devfreq->lock);
 | 
						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 a new issue