drm/xe/rtp: Add FIELD_SET_FUNC RTP action

Most of our RTP programming involves programming constant values into
register fields.  However there are a few cases (e.g., RING_CMD_CCTL
programming) that rely on dynamic per-GT or per-engine checks to decide
what value will be programmed.  Add a FIELD_SET_FUNC RTP action which
will call the provided function pointer once at RTP processing time to
determine the appropriate value.

v2:
 - Tweak kerneldoc to avoid duplicating explanation from FIELD_SET.
   (Gustavo)

Reviewed-by: Gustavo Sousa <gustavo.sousa@intel.com>
Link: https://patch.msgid.link/20260617-rtp_with_dynamic_vals-v2-2-3f4cb34c2ea1@intel.com
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
This commit is contained in:
Matt Roper 2026-06-17 12:24:46 -07:00
parent 4d39b3e7d5
commit 7a88843300
3 changed files with 42 additions and 4 deletions

View File

@ -227,17 +227,23 @@ static bool rule_matches(const struct xe_device *xe,
static void rtp_add_sr_entry(const struct xe_rtp_action *action,
struct xe_gt *gt,
struct xe_hw_engine *hwe,
u32 mmio_base,
struct xe_reg_sr *sr)
{
struct xe_reg_sr_entry sr_entry = {
.reg = action->reg,
.clr_bits = action->clr_bits,
.set_bits = action->set_bits,
.read_mask = action->read_mask,
};
if (action->use_func)
sr_entry.set_bits = action->set_func(gt, hwe);
else
sr_entry.set_bits = action->set_bits;
sr_entry.reg.addr += mmio_base;
xe_reg_sr_add(sr, &sr_entry, gt);
}
@ -259,7 +265,7 @@ static bool rtp_process_one_sr(const struct xe_rtp_entry_sr *entry,
else
mmio_base = 0;
rtp_add_sr_entry(action, gt, mmio_base, sr);
rtp_add_sr_entry(action, gt, hwe, mmio_base, sr);
}
return true;

View File

@ -322,6 +322,25 @@ struct xe_reg_sr;
.clr_bits = (mask_bits_), .set_bits = (val_), \
.read_mask = 0, ##__VA_ARGS__ }
/**
* XE_RTP_ACTION_FIELD_SET_FUNC: Set a bit range to the value returned by a function
* @reg_: Register
* @mask_bits_: Mask of bits to be changed in the register, forming a field
* @func_: Function that returns value to set in the field denoted by @mask_bits_
* @...: Additional fields to override in the struct xe_rtp_action entry
*
* This macro works like XE_RTP_ACTION_FIELD_SET(), except that the
* field value is evaluated at the time the RTP table is processed.
*
* @func_ will only be called a single time, when the RTP table is being
* processed. After processing, the value in the reg_sr entry is fixed and
* will not be re-evaluated.
*/
#define XE_RTP_ACTION_FIELD_SET_FUNC(reg_, mask_bits_, func_, ...) \
{ .reg = XE_RTP_DROP_CAST(reg_), \
.clr_bits = mask_bits_, .set_func = func_, .use_func = 1, \
.read_mask = mask_bits_, ##__VA_ARGS__ }
/**
* XE_RTP_ACTION_WHITELIST - Add register to userspace whitelist
* @reg_: Register

View File

@ -30,8 +30,14 @@ struct xe_rtp_action {
*/
u32 clr_bits;
/** @set_bits: bits to set when updating register */
u32 set_bits;
union {
/** @set_bits: bits to set when updating register */
u32 set_bits;
/** @set_func: function to provide bits to set when updating register */
u32 (*set_func)(struct xe_gt *gt,
struct xe_hw_engine *hwe);
};
#define XE_RTP_NOCHECK .read_mask = 0
/** @read_mask: mask for bits to consider when reading value back */
@ -40,6 +46,13 @@ struct xe_rtp_action {
#define XE_RTP_ACTION_FLAG_ENGINE_BASE BIT(0)
/** @flags: flags to apply on rule evaluation or action */
u8 flags;
/**
* @use_func:
* Internal flag indicating @set_func should be called instead of
* using @set_bits.
*/
u8 use_func:1;
};
enum {