mirror of
https://github.com/torvalds/linux.git
synced 2026-05-21 13:27:57 +02:00
drm/xe/guc_pc: Add _locked variant for min/max freq
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. Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Link: https://lore.kernel.org/r/20250618-wa-22019338487-v5-1-b888388477f2@intel.com Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
This commit is contained in:
parent
a1c940cbf5
commit
1beae9aa2b
|
|
@ -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,29 @@ 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 +652,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 +688,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;
|
||||
guard(mutex)(&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;
|
||||
}
|
||||
|
||||
ret = pc_set_max_freq(pc, freq);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
pc->user_requested_max = freq;
|
||||
|
||||
out:
|
||||
mutex_unlock(&pc->freq_lock);
|
||||
return ret;
|
||||
return xe_guc_pc_set_max_freq_locked(pc, freq);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user