[PATCH v4 1/3] drm/xe/guc_pc: Add _locked variant for min/max freq

Rodrigo Vivi rodrigo.vivi at intel.com
Mon Jun 16 14:26:57 UTC 2025


On Sun, Jun 15, 2025 at 11:17:34PM -0700, Lucas De Marchi wrote:
> There are places in which the getters/setters are called one after the
> other causing a multiple lock()/unlock(). These are not currently a
> problem since they are all happening from the same thread, but there's a
> race possibility as calls are added outside of the early init when the
> max/min and stashed values need to be correlated.
> 
> Add the _locked() variants to prepare for that.
> 
> Signed-off-by: Lucas De Marchi <lucas.demarchi at intel.com>

Reviewed-by: Rodrigo Vivi <rodrigo.vivi at intel.com>

> ---
>  drivers/gpu/drm/xe/xe_guc_pc.c | 124 +++++++++++++++++++++++------------------
>  1 file changed, 70 insertions(+), 54 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c
> index 39d2acb2f30f6..53aaf937d4bec 100644
> --- a/drivers/gpu/drm/xe/xe_guc_pc.c
> +++ b/drivers/gpu/drm/xe/xe_guc_pc.c
> @@ -5,6 +5,7 @@
>  
>  #include "xe_guc_pc.h"
>  
> +#include <linux/cleanup.h>
>  #include <linux/delay.h>
>  #include <linux/ktime.h>
>  
> @@ -554,6 +555,25 @@ u32 xe_guc_pc_get_rpn_freq(struct xe_guc_pc *pc)
>  	return pc->rpn_freq;
>  }
>  
> +static int xe_guc_pc_get_min_freq_locked(struct xe_guc_pc *pc, u32 *freq)
> +{
> +	int ret;
> +
> +	lockdep_assert_held(&pc->freq_lock);
> +
> +	/* Might be in the middle of a gt reset */
> +	if (!pc->freq_ready)
> +		return -EAGAIN;
> +
> +	ret = pc_action_query_task_state(pc);
> +	if (ret)
> +		return ret;
> +
> +	*freq = pc_get_min_freq(pc);
> +
> +	return 0;
> +}
> +
>  /**
>   * xe_guc_pc_get_min_freq - Get the min operational frequency
>   * @pc: The GuC PC
> @@ -563,27 +583,29 @@ u32 xe_guc_pc_get_rpn_freq(struct xe_guc_pc *pc)
>   *         -EAGAIN if GuC PC not ready (likely in middle of a reset).
>   */
>  int xe_guc_pc_get_min_freq(struct xe_guc_pc *pc, u32 *freq)
> +{
> +	guard(mutex)(&pc->freq_lock);
> +
> +	return xe_guc_pc_get_min_freq_locked(pc, freq);
> +}
> +
> +static int xe_guc_pc_set_min_freq_locked(struct xe_guc_pc *pc, u32 freq)
>  {
>  	int ret;
>  
> -	xe_device_assert_mem_access(pc_to_xe(pc));
> +	lockdep_assert_held(&pc->freq_lock);
>  
> -	mutex_lock(&pc->freq_lock);
> -	if (!pc->freq_ready) {
> -		/* Might be in the middle of a gt reset */
> -		ret = -EAGAIN;
> -		goto out;
> -	}
> +	/* Might be in the middle of a gt reset */
> +	if (!pc->freq_ready)
> +		return -EAGAIN;
>  
> -	ret = pc_action_query_task_state(pc);
> +	ret = pc_set_min_freq(pc, freq);
>  	if (ret)
> -		goto out;
> +		return ret;
>  
> -	*freq = pc_get_min_freq(pc);
> +	pc->user_requested_min = freq;
>  
> -out:
> -	mutex_unlock(&pc->freq_lock);
> -	return ret;
> +	return 0;
>  }
>  
>  /**
> @@ -596,25 +618,30 @@ int xe_guc_pc_get_min_freq(struct xe_guc_pc *pc, u32 *freq)
>   *         -EINVAL if value out of bounds.
>   */
>  int xe_guc_pc_set_min_freq(struct xe_guc_pc *pc, u32 freq)
> +{
> +	guard(mutex)(&pc->freq_lock);
> +
> +	return xe_guc_pc_set_min_freq_locked(pc, freq);
> +}
> +
> +
> +static int xe_guc_pc_get_max_freq_locked(struct xe_guc_pc *pc, u32 *freq)
>  {
>  	int ret;
>  
> -	mutex_lock(&pc->freq_lock);
> -	if (!pc->freq_ready) {
> -		/* Might be in the middle of a gt reset */
> -		ret = -EAGAIN;
> -		goto out;
> -	}
> +	lockdep_assert_held(&pc->freq_lock);
>  
> -	ret = pc_set_min_freq(pc, freq);
> +	/* Might be in the middle of a gt reset */
> +	if (!pc->freq_ready)
> +		return -EAGAIN;
> +
> +	ret = pc_action_query_task_state(pc);
>  	if (ret)
> -		goto out;
> +		return ret;
>  
> -	pc->user_requested_min = freq;
> +	*freq = pc_get_max_freq(pc);
>  
> -out:
> -	mutex_unlock(&pc->freq_lock);
> -	return ret;
> +	return 0;
>  }
>  
>  /**
> @@ -626,25 +653,29 @@ int xe_guc_pc_set_min_freq(struct xe_guc_pc *pc, u32 freq)
>   *         -EAGAIN if GuC PC not ready (likely in middle of a reset).
>   */
>  int xe_guc_pc_get_max_freq(struct xe_guc_pc *pc, u32 *freq)
> +{
> +	guard(mutex)(&pc->freq_lock);
> +
> +	return xe_guc_pc_get_max_freq_locked(pc, freq);
> +}
> +
> +static int xe_guc_pc_set_max_freq_locked(struct xe_guc_pc *pc, u32 freq)
>  {
>  	int ret;
>  
> -	mutex_lock(&pc->freq_lock);
> -	if (!pc->freq_ready) {
> -		/* Might be in the middle of a gt reset */
> -		ret = -EAGAIN;
> -		goto out;
> -	}
> +	lockdep_assert_held(&pc->freq_lock);
>  
> -	ret = pc_action_query_task_state(pc);
> +	/* Might be in the middle of a gt reset */
> +	if (!pc->freq_ready)
> +		return -EAGAIN;
> +
> +	ret = pc_set_max_freq(pc, freq);
>  	if (ret)
> -		goto out;
> +		return ret;
>  
> -	*freq = pc_get_max_freq(pc);
> +	pc->user_requested_max = freq;
>  
> -out:
> -	mutex_unlock(&pc->freq_lock);
> -	return ret;
> +	return 0;
>  }
>  
>  /**
> @@ -658,24 +689,9 @@ int xe_guc_pc_get_max_freq(struct xe_guc_pc *pc, u32 *freq)
>   */
>  int xe_guc_pc_set_max_freq(struct xe_guc_pc *pc, u32 freq)
>  {
> -	int ret;
> -
> -	mutex_lock(&pc->freq_lock);
> -	if (!pc->freq_ready) {
> -		/* Might be in the middle of a gt reset */
> -		ret = -EAGAIN;
> -		goto out;
> -	}
> -
> -	ret = pc_set_max_freq(pc, freq);
> -	if (ret)
> -		goto out;
> +	guard(mutex)(&pc->freq_lock);
>  
> -	pc->user_requested_max = freq;
> -
> -out:
> -	mutex_unlock(&pc->freq_lock);
> -	return ret;
> +	return xe_guc_pc_set_max_freq_locked(pc, freq);
>  }
>  
>  /**
> 
> -- 
> 2.49.0
> 


More information about the Intel-xe mailing list