[Intel-gfx] [PATCH] drm/i915: Finish enabling rps before use by sysfs or debugfs

Daniel Vetter daniel at ffwll.ch
Tue Sep 17 00:12:30 CEST 2013


On Mon, Sep 16, 2013 at 02:56:43PM -0700, Tom.O'Rourke at intel.com wrote:
> From: Tom O'Rourke <Tom.O'Rourke at intel.com>
> 
> Enabling rps (turbo setup) was put in a work queue because it may
> take quite awhile.  This change flushes the work queue to initialize
> rps values before use by sysfs or debugfs.  Specifically,
> rps.delayed_resume_work is flushed before using rps.hw_max,
> rps.max_delay, rps.min_delay, or rps.cur_delay.
> 
> This change fixes a problem in sysfs where show functions using
> uninitialized values show incorrect values and store functions
> using uninitialized values in range checks incorrectly fail to
> store valid input values.  This change also addresses similar use
> before initialized problems in debugfs.
> 
> Change-Id: Ib9c4f2066b65013094cb9278fc17958a964836e7
> Signed-off-by: Tom O'Rourke <Tom.O'Rourke at intel.com>

I think we can exercise this by going through a suspend/resume cycle and
racing concurrent reads/writes of the sysfs files in a 2nd process. With
the igt_fork and igt_system_suspend_autoresume helpers in our kernel
testsuite repro this should be a really quick testcase to write ...

I'd go for a generic "read all sysfs files" approach to increase the
chances of catching other similar fallout in the future.
-Daniel

> ---
>  drivers/gpu/drm/i915/i915_debugfs.c |   12 ++++++++++++
>  drivers/gpu/drm/i915/i915_sysfs.c   |   10 ++++++++++
>  2 files changed, 22 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 1d77624..52e90a1 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -843,6 +843,8 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
>  	drm_i915_private_t *dev_priv = dev->dev_private;
>  	int ret;
>  
> +	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
> +
>  	if (IS_GEN5(dev)) {
>  		u16 rgvswctl = I915_READ16(MEMSWCTL);
>  		u16 rgvstat = I915_READ16(MEMSTAT_ILK);
> @@ -1321,6 +1323,8 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
>  		return 0;
>  	}
>  
> +	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
> +
>  	ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
>  	if (ret)
>  		return ret;
> @@ -1972,6 +1976,8 @@ i915_max_freq_get(void *data, u64 *val)
>  	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
>  		return -ENODEV;
>  
> +	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
> +
>  	ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
>  	if (ret)
>  		return ret;
> @@ -1996,6 +2002,8 @@ i915_max_freq_set(void *data, u64 val)
>  	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
>  		return -ENODEV;
>  
> +	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
> +
>  	DRM_DEBUG_DRIVER("Manually setting max freq to %llu\n", val);
>  
>  	ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
> @@ -2034,6 +2042,8 @@ i915_min_freq_get(void *data, u64 *val)
>  	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
>  		return -ENODEV;
>  
> +	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
> +
>  	ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
>  	if (ret)
>  		return ret;
> @@ -2058,6 +2068,8 @@ i915_min_freq_set(void *data, u64 val)
>  	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
>  		return -ENODEV;
>  
> +	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
> +
>  	DRM_DEBUG_DRIVER("Manually setting min freq to %llu\n", val);
>  
>  	ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
> diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
> index d572435..270892b 100644
> --- a/drivers/gpu/drm/i915/i915_sysfs.c
> +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> @@ -213,6 +213,8 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	int ret;
>  
> +	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
> +
>  	mutex_lock(&dev_priv->rps.hw_lock);
>  	if (IS_VALLEYVIEW(dev_priv->dev)) {
>  		u32 freq;
> @@ -245,6 +247,8 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	int ret;
>  
> +	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
> +
>  	mutex_lock(&dev_priv->rps.hw_lock);
>  	if (IS_VALLEYVIEW(dev_priv->dev))
>  		ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.max_delay);
> @@ -269,6 +273,8 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
>  	if (ret)
>  		return ret;
>  
> +	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
> +
>  	mutex_lock(&dev_priv->rps.hw_lock);
>  
>  	if (IS_VALLEYVIEW(dev_priv->dev)) {
> @@ -317,6 +323,8 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	int ret;
>  
> +	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
> +
>  	mutex_lock(&dev_priv->rps.hw_lock);
>  	if (IS_VALLEYVIEW(dev_priv->dev))
>  		ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.min_delay);
> @@ -341,6 +349,8 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
>  	if (ret)
>  		return ret;
>  
> +	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
> +
>  	mutex_lock(&dev_priv->rps.hw_lock);
>  
>  	if (IS_VALLEYVIEW(dev)) {
> -- 
> 1.7.9.5
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch



More information about the Intel-gfx mailing list