mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 14:53:58 -04:00
Context Timestamp (CTX_TIMESTAMP) in the LRC accumulates the run ticks
of the context, but only gets updated when the context switches out. In
order to check how long a context has been active before it switches
out, two things are required:
(1) Determine if the context is running:
To do so, we program the WA BB to set an initial value for CTX_TIMESTAMP
in the LRC. The value chosen is 1 since 0 is the initial value when the
LRC is initialized. During a query, we just check for this value to
determine if the context is active. If the context switched out, it
would overwrite this location with the actual CTX_TIMESTAMP MMIO value.
Note that WA BB runs as the last part of the context restore, so reusing
this LRC location will not clobber anything.
(2) Calculate the time that the context has been active for:
The CTX_TIMESTAMP ticks only when the context is active. If a context is
active, we just use the CTX_TIMESTAMP MMIO as the new value of
utilization. While doing so, we need to read the CTX_TIMESTAMP MMIO
for the specific engine instance. Since we do not know which instance
the context is running on until it is scheduled, we also read the
ENGINE_ID MMIO in the WA BB and store it in the PPHSWP.
Using the above 2 instructions in a WA BB, capture active context
utilization.
v2: (Matt Brost)
- This breaks TDR, fix it by saving the CTX_TIMESTAMP register
"drm/xe: Save CTX_TIMESTAMP mmio value instead of LRC value"
- Drop tile from LRC if using gt
"drm/xe: Save the gt pointer in LRC and drop the tile"
v3:
- Remove helpers for bb_per_ctx_ptr (Matt)
- Add define for context active value (Matt)
- Use 64 bit CTX TIMESTAMP for platforms that support it. For platforms
that don't, live with the rare race. (Matt, Lucas)
- Convert engine id to hwe and get the MMIO value (Lucas)
- Correct commit message on when WA BB runs (Lucas)
v4:
- s/GRAPHICS_VER(...)/xe->info.has_64bit_timestamp/ (Matt)
- Drop support for active utilization on a VF (CI failure)
- In xe_lrc_init ensure the lrc value is 0 to begin with (CI regression)
v5:
- Minor checkpatch fix
- Squash into previous commit and make TDR use 32-bit time
- Update code comment to match commit msg
Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/4532
Cc: <stable@vger.kernel.org> # v6.13+
Suggested-by: Lucas De Marchi <lucas.demarchi@intel.com>
Signed-off-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com>
Link: https://lore.kernel.org/r/20250509161159.2173069-8-umesh.nerlige.ramappa@intel.com
(cherry picked from commit 82b98cadb0)
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
143 lines
4.1 KiB
C
143 lines
4.1 KiB
C
/* SPDX-License-Identifier: MIT */
|
|
/*
|
|
* Copyright © 2021 Intel Corporation
|
|
*/
|
|
#ifndef _XE_LRC_H_
|
|
#define _XE_LRC_H_
|
|
|
|
#include <linux/types.h>
|
|
|
|
#include "xe_lrc_types.h"
|
|
|
|
struct drm_printer;
|
|
struct xe_bb;
|
|
struct xe_device;
|
|
struct xe_exec_queue;
|
|
enum xe_engine_class;
|
|
struct xe_gt;
|
|
struct xe_hw_engine;
|
|
struct xe_lrc;
|
|
struct xe_vm;
|
|
|
|
struct xe_lrc_snapshot {
|
|
struct xe_bo *lrc_bo;
|
|
void *lrc_snapshot;
|
|
unsigned long lrc_size, lrc_offset;
|
|
|
|
u32 context_desc;
|
|
u32 ring_addr;
|
|
u32 indirect_context_desc;
|
|
u32 head;
|
|
u32 start;
|
|
struct {
|
|
u32 internal;
|
|
u32 memory;
|
|
} tail;
|
|
u32 start_seqno;
|
|
u32 seqno;
|
|
u32 ctx_timestamp;
|
|
u32 ctx_job_timestamp;
|
|
};
|
|
|
|
#define LRC_PPHWSP_FLUSH_INVAL_SCRATCH_ADDR (0x34 * 4)
|
|
#define LRC_PPHWSP_PXP_INVAL_SCRATCH_ADDR (0x40 * 4)
|
|
|
|
#define XE_LRC_CREATE_RUNALONE 0x1
|
|
#define XE_LRC_CREATE_PXP 0x2
|
|
struct xe_lrc *xe_lrc_create(struct xe_hw_engine *hwe, struct xe_vm *vm,
|
|
u32 ring_size, u16 msix_vec, u32 flags);
|
|
void xe_lrc_destroy(struct kref *ref);
|
|
|
|
/**
|
|
* xe_lrc_get - Get reference to the LRC
|
|
* @lrc: Logical Ring Context
|
|
*
|
|
* Increment reference count of @lrc
|
|
*/
|
|
static inline struct xe_lrc *xe_lrc_get(struct xe_lrc *lrc)
|
|
{
|
|
kref_get(&lrc->refcount);
|
|
return lrc;
|
|
}
|
|
|
|
/**
|
|
* xe_lrc_put - Put reference of the LRC
|
|
* @lrc: Logical Ring Context
|
|
*
|
|
* Decrement reference count of @lrc, call xe_lrc_destroy when
|
|
* reference count reaches 0.
|
|
*/
|
|
static inline void xe_lrc_put(struct xe_lrc *lrc)
|
|
{
|
|
kref_put(&lrc->refcount, xe_lrc_destroy);
|
|
}
|
|
|
|
size_t xe_gt_lrc_size(struct xe_gt *gt, enum xe_engine_class class);
|
|
u32 xe_lrc_pphwsp_offset(struct xe_lrc *lrc);
|
|
u32 xe_lrc_regs_offset(struct xe_lrc *lrc);
|
|
|
|
void xe_lrc_set_ring_tail(struct xe_lrc *lrc, u32 tail);
|
|
u32 xe_lrc_ring_tail(struct xe_lrc *lrc);
|
|
void xe_lrc_set_ring_head(struct xe_lrc *lrc, u32 head);
|
|
u32 xe_lrc_ring_head(struct xe_lrc *lrc);
|
|
u32 xe_lrc_ring_space(struct xe_lrc *lrc);
|
|
void xe_lrc_write_ring(struct xe_lrc *lrc, const void *data, size_t size);
|
|
|
|
bool xe_lrc_ring_is_idle(struct xe_lrc *lrc);
|
|
|
|
u32 xe_lrc_indirect_ring_ggtt_addr(struct xe_lrc *lrc);
|
|
u32 xe_lrc_ggtt_addr(struct xe_lrc *lrc);
|
|
u32 *xe_lrc_regs(struct xe_lrc *lrc);
|
|
|
|
u32 xe_lrc_read_ctx_reg(struct xe_lrc *lrc, int reg_nr);
|
|
void xe_lrc_write_ctx_reg(struct xe_lrc *lrc, int reg_nr, u32 val);
|
|
|
|
u64 xe_lrc_descriptor(struct xe_lrc *lrc);
|
|
|
|
u32 xe_lrc_seqno_ggtt_addr(struct xe_lrc *lrc);
|
|
struct dma_fence *xe_lrc_alloc_seqno_fence(void);
|
|
void xe_lrc_free_seqno_fence(struct dma_fence *fence);
|
|
void xe_lrc_init_seqno_fence(struct xe_lrc *lrc, struct dma_fence *fence);
|
|
s32 xe_lrc_seqno(struct xe_lrc *lrc);
|
|
|
|
u32 xe_lrc_start_seqno_ggtt_addr(struct xe_lrc *lrc);
|
|
s32 xe_lrc_start_seqno(struct xe_lrc *lrc);
|
|
|
|
u32 xe_lrc_parallel_ggtt_addr(struct xe_lrc *lrc);
|
|
struct iosys_map xe_lrc_parallel_map(struct xe_lrc *lrc);
|
|
|
|
size_t xe_lrc_skip_size(struct xe_device *xe);
|
|
|
|
void xe_lrc_dump_default(struct drm_printer *p,
|
|
struct xe_gt *gt,
|
|
enum xe_engine_class);
|
|
|
|
void xe_lrc_emit_hwe_state_instructions(struct xe_exec_queue *q, struct xe_bb *bb);
|
|
|
|
struct xe_lrc_snapshot *xe_lrc_snapshot_capture(struct xe_lrc *lrc);
|
|
void xe_lrc_snapshot_capture_delayed(struct xe_lrc_snapshot *snapshot);
|
|
void xe_lrc_snapshot_print(struct xe_lrc_snapshot *snapshot, struct drm_printer *p);
|
|
void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot);
|
|
|
|
u32 xe_lrc_ctx_timestamp_ggtt_addr(struct xe_lrc *lrc);
|
|
u32 xe_lrc_ctx_timestamp_udw_ggtt_addr(struct xe_lrc *lrc);
|
|
u64 xe_lrc_ctx_timestamp(struct xe_lrc *lrc);
|
|
u32 xe_lrc_ctx_job_timestamp_ggtt_addr(struct xe_lrc *lrc);
|
|
u32 xe_lrc_ctx_job_timestamp(struct xe_lrc *lrc);
|
|
|
|
/**
|
|
* xe_lrc_update_timestamp - readout LRC timestamp and update cached value
|
|
* @lrc: logical ring context for this exec queue
|
|
* @old_ts: pointer where to save the previous timestamp
|
|
*
|
|
* Read the current timestamp for this LRC and update the cached value. The
|
|
* previous cached value is also returned in @old_ts so the caller can calculate
|
|
* the delta between 2 updates. Note that this is not intended to be called from
|
|
* any place, but just by the paths updating the drm client utilization.
|
|
*
|
|
* Returns the current LRC timestamp
|
|
*/
|
|
u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts);
|
|
|
|
#endif
|