diff --git a/drivers/gpu/drm/xe/xe_rtp.c b/drivers/gpu/drm/xe/xe_rtp.c index 83a40e1f9528..6a8d6ea68f25 100644 --- a/drivers/gpu/drm/xe/xe_rtp.c +++ b/drivers/gpu/drm/xe/xe_rtp.c @@ -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; diff --git a/drivers/gpu/drm/xe/xe_rtp.h b/drivers/gpu/drm/xe/xe_rtp.h index 2cc65053cd07..0032f68ea187 100644 --- a/drivers/gpu/drm/xe/xe_rtp.h +++ b/drivers/gpu/drm/xe/xe_rtp.h @@ -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 diff --git a/drivers/gpu/drm/xe/xe_rtp_types.h b/drivers/gpu/drm/xe/xe_rtp_types.h index 1d7c63d0ae94..b78092fa06e0 100644 --- a/drivers/gpu/drm/xe/xe_rtp_types.h +++ b/drivers/gpu/drm/xe/xe_rtp_types.h @@ -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 {