Commit 2c2d7a67 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-gt-next-2022-08-24' of...

Merge tag 'drm-intel-gt-next-2022-08-24' of git://anongit.freedesktop.org/drm/drm-intel into drm-next

UAPI Changes:

- Create gt/gtN/.defaults/ for per gt sysfs defaults

  Create a gt/gtN/.defaults/ directory (similar to
  engine/<engine-name>/.defaults/) to expose default parameter values for
  each gt in sysfs. This allows userspace to restore default parameter values
  after they have changed.

Driver Changes:

- Support GuC v69 in parallel to v70 (Daniele)
- Improve TLB invalidation to limit performance regression (Chris, Mauro)
- Expose per-gt RPS defaults in sysfs (Ashutosh)
- Suppress OOM warning for shmemfs object allocation failure (Chris, Nirmoy)
- Disable PCI resize on 32-bit machines (Nirmoy)
- Update DG2 to GuC v70.4.1 (John)
- Fix CCS data copying on DG2 during swapping (Matt A)
- Add DG2 performance tuning setting recommended by spec (Matt R)
- Add GuC <-> kernel time stamp translation information to error logs (John)
- Record GuC CTB info in error logs (John)

- Route semaphores to GuC for Gen12+ when enabled (Michal Wi, John)
- Improve resilency to bug #3575: Handle reset timeouts under unrelated kernel hangs (Chris, Ashutosh)
- Avoid system freeze by removing shared locking on freeing objects (Chris, Nirmoy)
- Demote GuC error "No response for request" into debug when expected (Zhanjun)
- Fix GuC capture size warning and bump the size (John)
- Use streaming loads to speed up dumping the GuC log (Chris, John)
- Don't abort on CTB_UNUSED status from GuC (John)
- Don't send spurious policy update for GuC child contexts (Daniele)
- Don't leak the CCS state (Matt A)

- Prefer drm_err over pr_err (John)
- Eliminate unused calc_ctrl_surf_instr_size (Matt A)
- Add dedicated function for non-ctx register tuning settings (Matt R)
- Style and typo fixes, documentation improvements (Jason Wang, Mauro)
- Selftest improvements (Matt B, Rahul, John)
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/YwYTCjA/Rhpd1n4A@jlahtine-mobl.ger.corp.intel.com
parents 1c23f9e6 5ece208a
...@@ -75,7 +75,7 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, ...@@ -75,7 +75,7 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st,
if (size > resource_size(&mr->region)) if (size > resource_size(&mr->region))
return -ENOMEM; return -ENOMEM;
if (sg_alloc_table(st, page_count, GFP_KERNEL)) if (sg_alloc_table(st, page_count, GFP_KERNEL | __GFP_NOWARN))
return -ENOMEM; return -ENOMEM;
/* /*
...@@ -137,7 +137,7 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, ...@@ -137,7 +137,7 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st,
* trigger the out-of-memory killer and for * trigger the out-of-memory killer and for
* this we want __GFP_RETRY_MAYFAIL. * this we want __GFP_RETRY_MAYFAIL.
*/ */
gfp |= __GFP_RETRY_MAYFAIL; gfp |= __GFP_RETRY_MAYFAIL | __GFP_NOWARN;
} }
} while (1); } while (1);
...@@ -209,7 +209,7 @@ static int shmem_get_pages(struct drm_i915_gem_object *obj) ...@@ -209,7 +209,7 @@ static int shmem_get_pages(struct drm_i915_gem_object *obj)
GEM_BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS); GEM_BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS);
rebuild_st: rebuild_st:
st = kmalloc(sizeof(*st), GFP_KERNEL); st = kmalloc(sizeof(*st), GFP_KERNEL | __GFP_NOWARN);
if (!st) if (!st)
return -ENOMEM; return -ENOMEM;
......
...@@ -55,6 +55,14 @@ static inline void intel_gt_pm_might_put(struct intel_gt *gt) ...@@ -55,6 +55,14 @@ static inline void intel_gt_pm_might_put(struct intel_gt *gt)
for (tmp = 1, intel_gt_pm_get(gt); tmp; \ for (tmp = 1, intel_gt_pm_get(gt); tmp; \
intel_gt_pm_put(gt), tmp = 0) intel_gt_pm_put(gt), tmp = 0)
/**
* with_intel_gt_pm_if_awake - if GT is PM awake, get a reference to prevent
* it to sleep, run some code and then asynchrously put the reference
* away.
*
* @gt: pointer to the gt
* @wf: pointer to a temporary wakeref.
*/
#define with_intel_gt_pm_if_awake(gt, wf) \ #define with_intel_gt_pm_if_awake(gt, wf) \
for (wf = intel_gt_pm_get_if_awake(gt); wf; intel_gt_pm_put_async(gt), wf = 0) for (wf = intel_gt_pm_get_if_awake(gt); wf; intel_gt_pm_put_async(gt), wf = 0)
......
...@@ -259,6 +259,9 @@ ...@@ -259,6 +259,9 @@
#define GEN9_PREEMPT_GPGPU_COMMAND_LEVEL GEN9_PREEMPT_GPGPU_LEVEL(1, 0) #define GEN9_PREEMPT_GPGPU_COMMAND_LEVEL GEN9_PREEMPT_GPGPU_LEVEL(1, 0)
#define GEN9_PREEMPT_GPGPU_LEVEL_MASK GEN9_PREEMPT_GPGPU_LEVEL(1, 1) #define GEN9_PREEMPT_GPGPU_LEVEL_MASK GEN9_PREEMPT_GPGPU_LEVEL(1, 1)
#define DRAW_WATERMARK _MMIO(0x26c0)
#define VERT_WM_VAL REG_GENMASK(9, 0)
#define GEN12_GLOBAL_MOCS(i) _MMIO(0x4000 + (i) * 4) /* Global MOCS regs */ #define GEN12_GLOBAL_MOCS(i) _MMIO(0x4000 + (i) * 4) /* Global MOCS regs */
#define RENDER_HWS_PGA_GEN7 _MMIO(0x4080) #define RENDER_HWS_PGA_GEN7 _MMIO(0x4080)
...@@ -374,6 +377,9 @@ ...@@ -374,6 +377,9 @@
#define CHICKEN_RASTER_1 _MMIO(0x6204) #define CHICKEN_RASTER_1 _MMIO(0x6204)
#define DIS_SF_ROUND_NEAREST_EVEN REG_BIT(8) #define DIS_SF_ROUND_NEAREST_EVEN REG_BIT(8)
#define CHICKEN_RASTER_2 _MMIO(0x6208)
#define TBIMR_FAST_CLIP REG_BIT(5)
#define VFLSKPD _MMIO(0x62a8) #define VFLSKPD _MMIO(0x62a8)
#define DIS_OVER_FETCH_CACHE REG_BIT(1) #define DIS_OVER_FETCH_CACHE REG_BIT(1)
#define DIS_MULT_MISS_RD_SQUASH REG_BIT(0) #define DIS_MULT_MISS_RD_SQUASH REG_BIT(0)
...@@ -1007,6 +1013,8 @@ ...@@ -1007,6 +1013,8 @@
#define GEN11_LSN_UNSLCVC_GAFS_HALF_CL2_MAXALLOC (1 << 9) #define GEN11_LSN_UNSLCVC_GAFS_HALF_CL2_MAXALLOC (1 << 9)
#define GEN11_LSN_UNSLCVC_GAFS_HALF_SF_MAXALLOC (1 << 7) #define GEN11_LSN_UNSLCVC_GAFS_HALF_SF_MAXALLOC (1 << 7)
#define GUCPMTIMESTAMP _MMIO(0xc3e8)
#define __GEN9_RCS0_MOCS0 0xc800 #define __GEN9_RCS0_MOCS0 0xc800
#define GEN9_GFX_MOCS(i) _MMIO(__GEN9_RCS0_MOCS0 + (i) * 4) #define GEN9_GFX_MOCS(i) _MMIO(__GEN9_RCS0_MOCS0 + (i) * 4)
#define __GEN9_VCS0_MOCS0 0xc900 #define __GEN9_VCS0_MOCS0 0xc900
...@@ -1078,6 +1086,7 @@ ...@@ -1078,6 +1086,7 @@
#define GEN10_SAMPLER_MODE _MMIO(0xe18c) #define GEN10_SAMPLER_MODE _MMIO(0xe18c)
#define ENABLE_SMALLPL REG_BIT(15) #define ENABLE_SMALLPL REG_BIT(15)
#define SC_DISABLE_POWER_OPTIMIZATION_EBB REG_BIT(9)
#define GEN11_SAMPLER_ENABLE_HEADLESS_MSG REG_BIT(5) #define GEN11_SAMPLER_ENABLE_HEADLESS_MSG REG_BIT(5)
#define GEN9_HALF_SLICE_CHICKEN7 _MMIO(0xe194) #define GEN9_HALF_SLICE_CHICKEN7 _MMIO(0xe194)
...@@ -1123,6 +1132,8 @@ ...@@ -1123,6 +1132,8 @@
#define RT_CTRL _MMIO(0xe530) #define RT_CTRL _MMIO(0xe530)
#define DIS_NULL_QUERY REG_BIT(10) #define DIS_NULL_QUERY REG_BIT(10)
#define STACKID_CTRL REG_GENMASK(6, 5)
#define STACKID_CTRL_512 REG_FIELD_PREP(STACKID_CTRL, 0x2)
#define EU_PERF_CNTL1 _MMIO(0xe558) #define EU_PERF_CNTL1 _MMIO(0xe558)
#define EU_PERF_CNTL5 _MMIO(0xe55c) #define EU_PERF_CNTL5 _MMIO(0xe55c)
......
...@@ -22,11 +22,6 @@ bool is_object_gt(struct kobject *kobj) ...@@ -22,11 +22,6 @@ bool is_object_gt(struct kobject *kobj)
return !strncmp(kobj->name, "gt", 2); return !strncmp(kobj->name, "gt", 2);
} }
static struct intel_gt *kobj_to_gt(struct kobject *kobj)
{
return container_of(kobj, struct intel_gt, sysfs_gt);
}
struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev, struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
const char *name) const char *name)
{ {
...@@ -101,6 +96,10 @@ void intel_gt_sysfs_register(struct intel_gt *gt) ...@@ -101,6 +96,10 @@ void intel_gt_sysfs_register(struct intel_gt *gt)
gt->i915->sysfs_gt, "gt%d", gt->info.id)) gt->i915->sysfs_gt, "gt%d", gt->info.id))
goto exit_fail; goto exit_fail;
gt->sysfs_defaults = kobject_create_and_add(".defaults", &gt->sysfs_gt);
if (!gt->sysfs_defaults)
goto exit_fail;
intel_gt_sysfs_pm_init(gt, &gt->sysfs_gt); intel_gt_sysfs_pm_init(gt, &gt->sysfs_gt);
return; return;
...@@ -113,5 +112,6 @@ void intel_gt_sysfs_register(struct intel_gt *gt) ...@@ -113,5 +112,6 @@ void intel_gt_sysfs_register(struct intel_gt *gt)
void intel_gt_sysfs_unregister(struct intel_gt *gt) void intel_gt_sysfs_unregister(struct intel_gt *gt)
{ {
kobject_put(gt->sysfs_defaults);
kobject_put(&gt->sysfs_gt); kobject_put(&gt->sysfs_gt);
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/kobject.h> #include <linux/kobject.h>
#include "i915_gem.h" /* GEM_BUG_ON() */ #include "i915_gem.h" /* GEM_BUG_ON() */
#include "intel_gt_types.h"
struct intel_gt; struct intel_gt;
...@@ -22,6 +23,11 @@ intel_gt_create_kobj(struct intel_gt *gt, ...@@ -22,6 +23,11 @@ intel_gt_create_kobj(struct intel_gt *gt,
struct kobject *dir, struct kobject *dir,
const char *name); const char *name);
static inline struct intel_gt *kobj_to_gt(struct kobject *kobj)
{
return container_of(kobj, struct intel_gt, sysfs_gt);
}
void intel_gt_sysfs_register(struct intel_gt *gt); void intel_gt_sysfs_register(struct intel_gt *gt);
void intel_gt_sysfs_unregister(struct intel_gt *gt); void intel_gt_sysfs_unregister(struct intel_gt *gt);
struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev, struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
......
...@@ -727,6 +727,34 @@ static const struct attribute *media_perf_power_attrs[] = { ...@@ -727,6 +727,34 @@ static const struct attribute *media_perf_power_attrs[] = {
NULL NULL
}; };
static ssize_t
default_min_freq_mhz_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct intel_gt *gt = kobj_to_gt(kobj->parent);
return sysfs_emit(buf, "%u\n", gt->defaults.min_freq);
}
static struct kobj_attribute default_min_freq_mhz =
__ATTR(rps_min_freq_mhz, 0444, default_min_freq_mhz_show, NULL);
static ssize_t
default_max_freq_mhz_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct intel_gt *gt = kobj_to_gt(kobj->parent);
return sysfs_emit(buf, "%u\n", gt->defaults.max_freq);
}
static struct kobj_attribute default_max_freq_mhz =
__ATTR(rps_max_freq_mhz, 0444, default_max_freq_mhz_show, NULL);
static const struct attribute * const rps_defaults_attrs[] = {
&default_min_freq_mhz.attr,
&default_max_freq_mhz.attr,
NULL
};
static int intel_sysfs_rps_init(struct intel_gt *gt, struct kobject *kobj, static int intel_sysfs_rps_init(struct intel_gt *gt, struct kobject *kobj,
const struct attribute * const *attrs) const struct attribute * const *attrs)
{ {
...@@ -776,4 +804,10 @@ void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj) ...@@ -776,4 +804,10 @@ void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj)
"failed to create gt%u media_perf_power_attrs sysfs (%pe)\n", "failed to create gt%u media_perf_power_attrs sysfs (%pe)\n",
gt->info.id, ERR_PTR(ret)); gt->info.id, ERR_PTR(ret));
} }
ret = sysfs_create_files(gt->sysfs_defaults, rps_defaults_attrs);
if (ret)
drm_warn(&gt->i915->drm,
"failed to add gt%u rps defaults (%pe)\n",
gt->info.id, ERR_PTR(ret));
} }
...@@ -76,6 +76,11 @@ enum intel_submission_method { ...@@ -76,6 +76,11 @@ enum intel_submission_method {
INTEL_SUBMISSION_GUC, INTEL_SUBMISSION_GUC,
}; };
struct gt_defaults {
u32 min_freq;
u32 max_freq;
};
struct intel_gt { struct intel_gt {
struct drm_i915_private *i915; struct drm_i915_private *i915;
struct intel_uncore *uncore; struct intel_uncore *uncore;
...@@ -251,6 +256,10 @@ struct intel_gt { ...@@ -251,6 +256,10 @@ struct intel_gt {
/* gt/gtN sysfs */ /* gt/gtN sysfs */
struct kobject sysfs_gt; struct kobject sysfs_gt;
/* sysfs defaults per gt */
struct gt_defaults defaults;
struct kobject *sysfs_defaults;
}; };
enum intel_gt_scratch_field { enum intel_gt_scratch_field {
......
...@@ -511,44 +511,16 @@ static inline u32 *i915_flush_dw(u32 *cmd, u32 flags) ...@@ -511,44 +511,16 @@ static inline u32 *i915_flush_dw(u32 *cmd, u32 flags)
return cmd; return cmd;
} }
static u32 calc_ctrl_surf_instr_size(struct drm_i915_private *i915, int size)
{
u32 num_cmds, num_blks, total_size;
if (!GET_CCS_BYTES(i915, size))
return 0;
/*
* XY_CTRL_SURF_COPY_BLT transfers CCS in 256 byte
* blocks. one XY_CTRL_SURF_COPY_BLT command can
* transfer upto 1024 blocks.
*/
num_blks = DIV_ROUND_UP(GET_CCS_BYTES(i915, size),
NUM_CCS_BYTES_PER_BLOCK);
num_cmds = DIV_ROUND_UP(num_blks, NUM_CCS_BLKS_PER_XFER);
total_size = XY_CTRL_SURF_INSTR_SIZE * num_cmds;
/*
* Adding a flush before and after XY_CTRL_SURF_COPY_BLT
*/
total_size += 2 * MI_FLUSH_DW_SIZE;
return total_size;
}
static int emit_copy_ccs(struct i915_request *rq, static int emit_copy_ccs(struct i915_request *rq,
u32 dst_offset, u8 dst_access, u32 dst_offset, u8 dst_access,
u32 src_offset, u8 src_access, int size) u32 src_offset, u8 src_access, int size)
{ {
struct drm_i915_private *i915 = rq->engine->i915; struct drm_i915_private *i915 = rq->engine->i915;
int mocs = rq->engine->gt->mocs.uc_index << 1; int mocs = rq->engine->gt->mocs.uc_index << 1;
u32 num_ccs_blks, ccs_ring_size; u32 num_ccs_blks;
u32 *cs; u32 *cs;
ccs_ring_size = calc_ctrl_surf_instr_size(i915, size); cs = intel_ring_begin(rq, 12);
WARN_ON(!ccs_ring_size);
cs = intel_ring_begin(rq, round_up(ccs_ring_size, 2));
if (IS_ERR(cs)) if (IS_ERR(cs))
return PTR_ERR(cs); return PTR_ERR(cs);
...@@ -583,8 +555,7 @@ static int emit_copy_ccs(struct i915_request *rq, ...@@ -583,8 +555,7 @@ static int emit_copy_ccs(struct i915_request *rq,
FIELD_PREP(XY_CTRL_SURF_MOCS_MASK, mocs); FIELD_PREP(XY_CTRL_SURF_MOCS_MASK, mocs);
cs = i915_flush_dw(cs, MI_FLUSH_DW_LLC | MI_FLUSH_DW_CCS); cs = i915_flush_dw(cs, MI_FLUSH_DW_LLC | MI_FLUSH_DW_CCS);
if (ccs_ring_size & 1) *cs++ = MI_NOOP;
*cs++ = MI_NOOP;
intel_ring_advance(rq, cs); intel_ring_advance(rq, cs);
...@@ -638,40 +609,38 @@ static int emit_copy(struct i915_request *rq, ...@@ -638,40 +609,38 @@ static int emit_copy(struct i915_request *rq,
return 0; return 0;
} }
static int scatter_list_length(struct scatterlist *sg) static u64 scatter_list_length(struct scatterlist *sg)
{ {
int len = 0; u64 len = 0;
while (sg && sg_dma_len(sg)) { while (sg && sg_dma_len(sg)) {
len += sg_dma_len(sg); len += sg_dma_len(sg);
sg = sg_next(sg); sg = sg_next(sg);
}; }
return len; return len;
} }
static void static int
calculate_chunk_sz(struct drm_i915_private *i915, bool src_is_lmem, calculate_chunk_sz(struct drm_i915_private *i915, bool src_is_lmem,
int *src_sz, u32 bytes_to_cpy, u32 ccs_bytes_to_cpy) u64 bytes_to_cpy, u64 ccs_bytes_to_cpy)
{ {
if (ccs_bytes_to_cpy) { if (ccs_bytes_to_cpy && !src_is_lmem)
if (!src_is_lmem) /*
/* * When CHUNK_SZ is passed all the pages upto CHUNK_SZ
* When CHUNK_SZ is passed all the pages upto CHUNK_SZ * will be taken for the blt. in Flat-ccs supported
* will be taken for the blt. in Flat-ccs supported * platform Smem obj will have more pages than required
* platform Smem obj will have more pages than required * for main meory hence limit it to the required size
* for main meory hence limit it to the required size * for main memory
* for main memory */
*/ return min_t(u64, bytes_to_cpy, CHUNK_SZ);
*src_sz = min_t(int, bytes_to_cpy, CHUNK_SZ); else
} else { /* ccs handling is not required */ return CHUNK_SZ;
*src_sz = CHUNK_SZ;
}
} }
static void get_ccs_sg_sgt(struct sgt_dma *it, u32 bytes_to_cpy) static void get_ccs_sg_sgt(struct sgt_dma *it, u64 bytes_to_cpy)
{ {
u32 len; u64 len;
do { do {
GEM_BUG_ON(!it->sg || !sg_dma_len(it->sg)); GEM_BUG_ON(!it->sg || !sg_dma_len(it->sg));
...@@ -702,12 +671,12 @@ intel_context_migrate_copy(struct intel_context *ce, ...@@ -702,12 +671,12 @@ intel_context_migrate_copy(struct intel_context *ce,
{ {
struct sgt_dma it_src = sg_sgt(src), it_dst = sg_sgt(dst), it_ccs; struct sgt_dma it_src = sg_sgt(src), it_dst = sg_sgt(dst), it_ccs;
struct drm_i915_private *i915 = ce->engine->i915; struct drm_i915_private *i915 = ce->engine->i915;
u32 ccs_bytes_to_cpy = 0, bytes_to_cpy; u64 ccs_bytes_to_cpy = 0, bytes_to_cpy;
enum i915_cache_level ccs_cache_level; enum i915_cache_level ccs_cache_level;
u32 src_offset, dst_offset; u32 src_offset, dst_offset;
u8 src_access, dst_access; u8 src_access, dst_access;
struct i915_request *rq; struct i915_request *rq;
int src_sz, dst_sz; u64 src_sz, dst_sz;
bool ccs_is_src, overwrite_ccs; bool ccs_is_src, overwrite_ccs;
int err; int err;
...@@ -790,8 +759,8 @@ intel_context_migrate_copy(struct intel_context *ce, ...@@ -790,8 +759,8 @@ intel_context_migrate_copy(struct intel_context *ce,
if (err) if (err)
goto out_rq; goto out_rq;
calculate_chunk_sz(i915, src_is_lmem, &src_sz, src_sz = calculate_chunk_sz(i915, src_is_lmem,
bytes_to_cpy, ccs_bytes_to_cpy); bytes_to_cpy, ccs_bytes_to_cpy);
len = emit_pte(rq, &it_src, src_cache_level, src_is_lmem, len = emit_pte(rq, &it_src, src_cache_level, src_is_lmem,
src_offset, src_sz); src_offset, src_sz);
......
...@@ -1281,9 +1281,6 @@ static void intel_gt_reset_global(struct intel_gt *gt, ...@@ -1281,9 +1281,6 @@ static void intel_gt_reset_global(struct intel_gt *gt,
intel_wedge_on_timeout(&w, gt, 5 * HZ) { intel_wedge_on_timeout(&w, gt, 5 * HZ) {
intel_display_prepare_reset(gt->i915); intel_display_prepare_reset(gt->i915);
/* Flush everyone using a resource about to be clobbered */
synchronize_srcu_expedited(&gt->reset.backoff_srcu);
intel_gt_reset(gt, engine_mask, reason); intel_gt_reset(gt, engine_mask, reason);
intel_display_finish_reset(gt->i915); intel_display_finish_reset(gt->i915);
...@@ -1392,6 +1389,9 @@ void intel_gt_handle_error(struct intel_gt *gt, ...@@ -1392,6 +1389,9 @@ void intel_gt_handle_error(struct intel_gt *gt,
} }
} }
/* Flush everyone using a resource about to be clobbered */
synchronize_srcu_expedited(&gt->reset.backoff_srcu);
intel_gt_reset_global(gt, engine_mask, msg); intel_gt_reset_global(gt, engine_mask, msg);
if (!intel_uc_uses_guc_submission(&gt->uc)) { if (!intel_uc_uses_guc_submission(&gt->uc)) {
......
...@@ -1979,7 +1979,9 @@ void intel_rps_init(struct intel_rps *rps) ...@@ -1979,7 +1979,9 @@ void intel_rps_init(struct intel_rps *rps)
/* Derive initial user preferences/limits from the hardware limits */ /* Derive initial user preferences/limits from the hardware limits */
rps->max_freq_softlimit = rps->max_freq; rps->max_freq_softlimit = rps->max_freq;
rps_to_gt(rps)->defaults.max_freq = rps->max_freq_softlimit;
rps->min_freq_softlimit = rps->min_freq; rps->min_freq_softlimit = rps->min_freq;
rps_to_gt(rps)->defaults.min_freq = rps->min_freq_softlimit;
/* After setting max-softlimit, find the overclock max freq */ /* After setting max-softlimit, find the overclock max freq */
if (GRAPHICS_VER(i915) == 6 || IS_IVYBRIDGE(i915) || IS_HASWELL(i915)) { if (GRAPHICS_VER(i915) == 6 || IS_IVYBRIDGE(i915) || IS_HASWELL(i915)) {
......
...@@ -568,6 +568,7 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine, ...@@ -568,6 +568,7 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine,
static void dg2_ctx_gt_tuning_init(struct intel_engine_cs *engine, static void dg2_ctx_gt_tuning_init(struct intel_engine_cs *engine,
struct i915_wa_list *wal) struct i915_wa_list *wal)
{ {
wa_masked_en(wal, CHICKEN_RASTER_2, TBIMR_FAST_CLIP);
wa_write_clr_set(wal, GEN11_L3SQCREG5, L3_PWM_TIMER_INIT_VAL_MASK, wa_write_clr_set(wal, GEN11_L3SQCREG5, L3_PWM_TIMER_INIT_VAL_MASK,
REG_FIELD_PREP(L3_PWM_TIMER_INIT_VAL_MASK, 0x7f)); REG_FIELD_PREP(L3_PWM_TIMER_INIT_VAL_MASK, 0x7f));
wa_add(wal, wa_add(wal,
...@@ -2102,13 +2103,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) ...@@ -2102,13 +2103,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
/* Wa_1509235366:dg2 */ /* Wa_1509235366:dg2 */
wa_write_or(wal, GEN12_GAMCNTRL_CTRL, INVALIDATION_BROADCAST_MODE_DIS | wa_write_or(wal, GEN12_GAMCNTRL_CTRL, INVALIDATION_BROADCAST_MODE_DIS |
GLOBAL_INVALIDATION_MODE); GLOBAL_INVALIDATION_MODE);
/*
* The following are not actually "workarounds" but rather
* recommended tuning settings documented in the bspec's
* performance guide section.
*/
wa_write_or(wal, XEHP_L3SCQREG7, BLEND_FILL_CACHING_OPT_DIS);
} }
if (IS_DG2_GRAPHICS_STEP(i915, G11, STEP_A0, STEP_B0)) { if (IS_DG2_GRAPHICS_STEP(i915, G11, STEP_A0, STEP_B0)) {
...@@ -2119,6 +2113,13 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) ...@@ -2119,6 +2113,13 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
wa_write_or(wal, LSC_CHICKEN_BIT_0_UDW, DIS_CHAIN_2XSIMD8); wa_write_or(wal, LSC_CHICKEN_BIT_0_UDW, DIS_CHAIN_2XSIMD8);
} }
if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_B0, STEP_FOREVER) ||
IS_DG2_G11(i915) || IS_DG2_G12(i915)) {
/* Wa_1509727124:dg2 */
wa_masked_en(wal, GEN10_SAMPLER_MODE,
SC_DISABLE_POWER_OPTIMIZATION_EBB);
}
if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_A0, STEP_B0) || if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_A0, STEP_B0) ||
IS_DG2_GRAPHICS_STEP(i915, G11, STEP_A0, STEP_B0)) { IS_DG2_GRAPHICS_STEP(i915, G11, STEP_A0, STEP_B0)) {
/* Wa_14012419201:dg2 */ /* Wa_14012419201:dg2 */
...@@ -2195,15 +2196,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) ...@@ -2195,15 +2196,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
wa_write_or(wal, XEHP_L3NODEARBCFG, XEHP_LNESPARE); wa_write_or(wal, XEHP_L3NODEARBCFG, XEHP_LNESPARE);
} }
if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_A0, STEP_C0) ||
IS_DG2_G11(i915)) {
/* Wa_22012654132:dg2 */
wa_add(wal, GEN10_CACHE_MODE_SS, 0,
_MASKED_BIT_ENABLE(ENABLE_PREFETCH_INTO_IC),
0 /* write-only, so skip validation */,
true);
}
/* Wa_14013202645:dg2 */ /* Wa_14013202645:dg2 */
if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_B0, STEP_C0) || if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_B0, STEP_C0) ||
IS_DG2_GRAPHICS_STEP(i915, G11, STEP_A0, STEP_B0)) IS_DG2_GRAPHICS_STEP(i915, G11, STEP_A0, STEP_B0))
...@@ -2669,6 +2661,49 @@ ccs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) ...@@ -2669,6 +2661,49 @@ ccs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
} }
} }
/*
* The bspec performance guide has recommended MMIO tuning settings. These
* aren't truly "workarounds" but we want to program them with the same
* workaround infrastructure to ensure that they're automatically added to
* the GuC save/restore lists, re-applied at the right times, and checked for
* any conflicting programming requested by real workarounds.
*
* Programming settings should be added here only if their registers are not
* part of an engine's register state context. If a register is part of a
* context, then any tuning settings should be programmed in an appropriate
* function invoked by __intel_engine_init_ctx_wa().
*/
static void
add_render_compute_tuning_settings(struct drm_i915_private *i915,
struct i915_wa_list *wal)
{
if (IS_PONTEVECCHIO(i915)) {
wa_write(wal, XEHPC_L3SCRUB,
SCRUB_CL_DWNGRADE_SHARED | SCRUB_RATE_4B_PER_CLK);
}
if (IS_DG2(i915)) {
wa_write_or(wal, XEHP_L3SCQREG7, BLEND_FILL_CACHING_OPT_DIS);
wa_write_clr_set(wal, RT_CTRL, STACKID_CTRL, STACKID_CTRL_512);
wa_write_clr_set(wal, DRAW_WATERMARK, VERT_WM_VAL,
REG_FIELD_PREP(VERT_WM_VAL, 0x3FF));
/*
* This is also listed as Wa_22012654132 for certain DG2
* steppings, but the tuning setting programming is a superset
* since it applies to all DG2 variants and steppings.
*
* Note that register 0xE420 is write-only and cannot be read
* back for verification on DG2 (due to Wa_14012342262), so
* we need to explicitly skip the readback.
*/
wa_add(wal, GEN10_CACHE_MODE_SS, 0,
_MASKED_BIT_ENABLE(ENABLE_PREFETCH_INTO_IC),
0 /* write-only, so skip validation */,
true);
}
}
/* /*
* The workarounds in this function apply to shared registers in * The workarounds in this function apply to shared registers in
* the general render reset domain that aren't tied to a * the general render reset domain that aren't tied to a
...@@ -2683,14 +2718,9 @@ general_render_compute_wa_init(struct intel_engine_cs *engine, struct i915_wa_li ...@@ -2683,14 +2718,9 @@ general_render_compute_wa_init(struct intel_engine_cs *engine, struct i915_wa_li
{ {
struct drm_i915_private *i915 = engine->i915; struct drm_i915_private *i915 = engine->i915;
if (IS_PONTEVECCHIO(i915)) { add_render_compute_tuning_settings(i915, wal);
/*
* The following is not actually a "workaround" but rather
* a recommended tuning setting documented in the bspec's
* performance guide section.
*/
wa_write(wal, XEHPC_L3SCRUB, SCRUB_CL_DWNGRADE_SHARED | SCRUB_RATE_4B_PER_CLK);
if (IS_PONTEVECCHIO(i915)) {
/* Wa_16016694945 */ /* Wa_16016694945 */
wa_masked_en(wal, XEHPC_LNCFMISCCFGREG0, XEHPC_OVRLSCCC); wa_masked_en(wal, XEHPC_LNCFMISCCFGREG0, XEHPC_OVRLSCCC);
} }
......
...@@ -2077,7 +2077,7 @@ static int __cancel_active0(struct live_preempt_cancel *arg) ...@@ -2077,7 +2077,7 @@ static int __cancel_active0(struct live_preempt_cancel *arg)
goto out; goto out;
} }
intel_context_set_banned(rq->context); intel_context_ban(rq->context, rq);
err = intel_engine_pulse(arg->engine); err = intel_engine_pulse(arg->engine);
if (err) if (err)
goto out; goto out;
...@@ -2136,7 +2136,7 @@ static int __cancel_active1(struct live_preempt_cancel *arg) ...@@ -2136,7 +2136,7 @@ static int __cancel_active1(struct live_preempt_cancel *arg)
if (err) if (err)
goto out; goto out;
intel_context_set_banned(rq[1]->context); intel_context_ban(rq[1]->context, rq[1]);
err = intel_engine_pulse(arg->engine); err = intel_engine_pulse(arg->engine);
if (err) if (err)
goto out; goto out;
...@@ -2219,7 +2219,7 @@ static int __cancel_queued(struct live_preempt_cancel *arg) ...@@ -2219,7 +2219,7 @@ static int __cancel_queued(struct live_preempt_cancel *arg)
if (err) if (err)
goto out; goto out;
intel_context_set_banned(rq[2]->context); intel_context_ban(rq[2]->context, rq[2]);
err = intel_engine_pulse(arg->engine); err = intel_engine_pulse(arg->engine);
if (err) if (err)
goto out; goto out;
...@@ -2234,7 +2234,13 @@ static int __cancel_queued(struct live_preempt_cancel *arg) ...@@ -2234,7 +2234,13 @@ static int __cancel_queued(struct live_preempt_cancel *arg)
goto out; goto out;
} }
if (rq[1]->fence.error != 0) { /*
* The behavior between having semaphores and not is different. With
* semaphores the subsequent request is on the hardware and not cancelled
* while without the request is held in the driver and cancelled.
*/
if (intel_engine_has_semaphores(rq[1]->engine) &&
rq[1]->fence.error != 0) {
pr_err("Normal inflight1 request did not complete\n"); pr_err("Normal inflight1 request did not complete\n");
err = -EINVAL; err = -EINVAL;
goto out; goto out;
...@@ -2282,7 +2288,7 @@ static int __cancel_hostile(struct live_preempt_cancel *arg) ...@@ -2282,7 +2288,7 @@ static int __cancel_hostile(struct live_preempt_cancel *arg)
goto out; goto out;
} }
intel_context_set_banned(rq->context); intel_context_ban(rq->context, rq);
err = intel_engine_pulse(arg->engine); /* force reset */ err = intel_engine_pulse(arg->engine); /* force reset */
if (err) if (err)
goto out; goto out;
......
...@@ -1302,13 +1302,15 @@ static int igt_reset_wait(void *arg) ...@@ -1302,13 +1302,15 @@ static int igt_reset_wait(void *arg)
{ {
struct intel_gt *gt = arg; struct intel_gt *gt = arg;
struct i915_gpu_error *global = &gt->i915->gpu_error; struct i915_gpu_error *global = &gt->i915->gpu_error;
struct intel_engine_cs *engine = gt->engine[RCS0]; struct intel_engine_cs *engine;
struct i915_request *rq; struct i915_request *rq;
unsigned int reset_count; unsigned int reset_count;
struct hang h; struct hang h;
long timeout; long timeout;
int err; int err;
engine = intel_selftest_find_any_engine(gt);
if (!engine || !intel_engine_can_store_dword(engine)) if (!engine || !intel_engine_can_store_dword(engine))
return 0; return 0;
...@@ -1432,7 +1434,7 @@ static int __igt_reset_evict_vma(struct intel_gt *gt, ...@@ -1432,7 +1434,7 @@ static int __igt_reset_evict_vma(struct intel_gt *gt,
int (*fn)(void *), int (*fn)(void *),
unsigned int flags) unsigned int flags)
{ {
struct intel_engine_cs *engine = gt->engine[RCS0]; struct intel_engine_cs *engine;
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
struct task_struct *tsk = NULL; struct task_struct *tsk = NULL;
struct i915_request *rq; struct i915_request *rq;
...@@ -1444,6 +1446,8 @@ static int __igt_reset_evict_vma(struct intel_gt *gt, ...@@ -1444,6 +1446,8 @@ static int __igt_reset_evict_vma(struct intel_gt *gt,
if (!gt->ggtt->num_fences && flags & EXEC_OBJECT_NEEDS_FENCE) if (!gt->ggtt->num_fences && flags & EXEC_OBJECT_NEEDS_FENCE)
return 0; return 0;
engine = intel_selftest_find_any_engine(gt);
if (!engine || !intel_engine_can_store_dword(engine)) if (!engine || !intel_engine_can_store_dword(engine))
return 0; return 0;
...@@ -1819,12 +1823,14 @@ static int igt_handle_error(void *arg) ...@@ -1819,12 +1823,14 @@ static int igt_handle_error(void *arg)
{ {
struct intel_gt *gt = arg; struct intel_gt *gt = arg;
struct i915_gpu_error *global = &gt->i915->gpu_error; struct i915_gpu_error *global = &gt->i915->gpu_error;
struct intel_engine_cs *engine = gt->engine[RCS0]; struct intel_engine_cs *engine;
struct hang h; struct hang h;
struct i915_request *rq; struct i915_request *rq;
struct i915_gpu_coredump *error; struct i915_gpu_coredump *error;
int err; int err;
engine = intel_selftest_find_any_engine(gt);
/* Check that we can issue a global GPU and engine reset */ /* Check that we can issue a global GPU and engine reset */
if (!intel_has_reset_engine(gt)) if (!intel_has_reset_engine(gt))
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
* | | | - _`GUC_CTB_STATUS_OVERFLOW` = 1 (head/tail too large) | * | | | - _`GUC_CTB_STATUS_OVERFLOW` = 1 (head/tail too large) |
* | | | - _`GUC_CTB_STATUS_UNDERFLOW` = 2 (truncated message) | * | | | - _`GUC_CTB_STATUS_UNDERFLOW` = 2 (truncated message) |
* | | | - _`GUC_CTB_STATUS_MISMATCH` = 4 (head/tail modified) | * | | | - _`GUC_CTB_STATUS_MISMATCH` = 4 (head/tail modified) |
* | | | - _`GUC_CTB_STATUS_UNUSED` = 8 (CTB is not in use) |
* +---+-------+--------------------------------------------------------------+ * +---+-------+--------------------------------------------------------------+
* |...| | RESERVED = MBZ | * |...| | RESERVED = MBZ |
* +---+-------+--------------------------------------------------------------+ * +---+-------+--------------------------------------------------------------+
...@@ -49,9 +50,10 @@ struct guc_ct_buffer_desc { ...@@ -49,9 +50,10 @@ struct guc_ct_buffer_desc {
u32 tail; u32 tail;
u32 status; u32 status;
#define GUC_CTB_STATUS_NO_ERROR 0 #define GUC_CTB_STATUS_NO_ERROR 0
#define GUC_CTB_STATUS_OVERFLOW (1 << 0) #define GUC_CTB_STATUS_OVERFLOW BIT(0)
#define GUC_CTB_STATUS_UNDERFLOW (1 << 1) #define GUC_CTB_STATUS_UNDERFLOW BIT(1)
#define GUC_CTB_STATUS_MISMATCH (1 << 2) #define GUC_CTB_STATUS_MISMATCH BIT(2)
#define GUC_CTB_STATUS_UNUSED BIT(3)
u32 reserved[13]; u32 reserved[13];
} __packed; } __packed;
static_assert(sizeof(struct guc_ct_buffer_desc) == 64); static_assert(sizeof(struct guc_ct_buffer_desc) == 64);
......
...@@ -389,6 +389,25 @@ void intel_guc_write_params(struct intel_guc *guc) ...@@ -389,6 +389,25 @@ void intel_guc_write_params(struct intel_guc *guc)
intel_uncore_forcewake_put(uncore, FORCEWAKE_GT); intel_uncore_forcewake_put(uncore, FORCEWAKE_GT);
} }
void intel_guc_dump_time_info(struct intel_guc *guc, struct drm_printer *p)
{
struct intel_gt *gt = guc_to_gt(guc);
intel_wakeref_t wakeref;
u32 stamp = 0;
u64 ktime;
intel_device_info_print_runtime(RUNTIME_INFO(gt->i915), p);
with_intel_runtime_pm(&gt->i915->runtime_pm, wakeref)
stamp = intel_uncore_read(gt->uncore, GUCPMTIMESTAMP);
ktime = ktime_get_boottime_ns();
drm_printf(p, "Kernel timestamp: 0x%08llX [%llu]\n", ktime, ktime);
drm_printf(p, "GuC timestamp: 0x%08X [%u]\n", stamp, stamp);
drm_printf(p, "CS timestamp frequency: %u Hz, %u ns\n",
gt->clock_frequency, gt->clock_period_ns);
}
int intel_guc_init(struct intel_guc *guc) int intel_guc_init(struct intel_guc *guc)
{ {
struct intel_gt *gt = guc_to_gt(guc); struct intel_gt *gt = guc_to_gt(guc);
......
...@@ -464,4 +464,6 @@ void intel_guc_load_status(struct intel_guc *guc, struct drm_printer *p); ...@@ -464,4 +464,6 @@ void intel_guc_load_status(struct intel_guc *guc, struct drm_printer *p);
void intel_guc_write_barrier(struct intel_guc *guc); void intel_guc_write_barrier(struct intel_guc *guc);
void intel_guc_dump_time_info(struct intel_guc *guc, struct drm_printer *p);
#endif #endif
...@@ -464,7 +464,11 @@ static void fill_engine_enable_masks(struct intel_gt *gt, ...@@ -464,7 +464,11 @@ static void fill_engine_enable_masks(struct intel_gt *gt,
} }
#define LR_HW_CONTEXT_SIZE (80 * sizeof(u32)) #define LR_HW_CONTEXT_SIZE (80 * sizeof(u32))
#define LRC_SKIP_SIZE (LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SIZE) #define XEHP_LR_HW_CONTEXT_SIZE (96 * sizeof(u32))
#define LR_HW_CONTEXT_SZ(i915) (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50) ? \
XEHP_LR_HW_CONTEXT_SIZE : \
LR_HW_CONTEXT_SIZE)
#define LRC_SKIP_SIZE(i915) (LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SZ(i915))
static int guc_prep_golden_context(struct intel_guc *guc) static int guc_prep_golden_context(struct intel_guc *guc)
{ {
struct intel_gt *gt = guc_to_gt(guc); struct intel_gt *gt = guc_to_gt(guc);
...@@ -525,7 +529,7 @@ static int guc_prep_golden_context(struct intel_guc *guc) ...@@ -525,7 +529,7 @@ static int guc_prep_golden_context(struct intel_guc *guc)
* on all engines). * on all engines).
*/ */
ads_blob_write(guc, ads.eng_state_size[guc_class], ads_blob_write(guc, ads.eng_state_size[guc_class],
real_size - LRC_SKIP_SIZE); real_size - LRC_SKIP_SIZE(gt->i915));
ads_blob_write(guc, ads.golden_context_lrca[guc_class], ads_blob_write(guc, ads.golden_context_lrca[guc_class],
addr_ggtt); addr_ggtt);
...@@ -599,7 +603,7 @@ static void guc_init_golden_context(struct intel_guc *guc) ...@@ -599,7 +603,7 @@ static void guc_init_golden_context(struct intel_guc *guc)
} }
GEM_BUG_ON(ads_blob_read(guc, ads.eng_state_size[guc_class]) != GEM_BUG_ON(ads_blob_read(guc, ads.eng_state_size[guc_class]) !=
real_size - LRC_SKIP_SIZE); real_size - LRC_SKIP_SIZE(gt->i915));
GEM_BUG_ON(ads_blob_read(guc, ads.golden_context_lrca[guc_class]) != addr_ggtt); GEM_BUG_ON(ads_blob_read(guc, ads.golden_context_lrca[guc_class]) != addr_ggtt);
addr_ggtt += alloc_size; addr_ggtt += alloc_size;
......
...@@ -600,10 +600,8 @@ intel_guc_capture_getnullheader(struct intel_guc *guc, ...@@ -600,10 +600,8 @@ intel_guc_capture_getnullheader(struct intel_guc *guc,
return 0; return 0;
} }
#define GUC_CAPTURE_OVERBUFFER_MULTIPLIER 3 static int
guc_capture_output_min_size_est(struct intel_guc *guc)
int
intel_guc_capture_output_min_size_est(struct intel_guc *guc)
{ {
struct intel_gt *gt = guc_to_gt(guc); struct intel_gt *gt = guc_to_gt(guc);
struct intel_engine_cs *engine; struct intel_engine_cs *engine;
...@@ -623,13 +621,8 @@ intel_guc_capture_output_min_size_est(struct intel_guc *guc) ...@@ -623,13 +621,8 @@ intel_guc_capture_output_min_size_est(struct intel_guc *guc)
* For each engine instance, there would be 1 x guc_state_capture_group_t output * For each engine instance, there would be 1 x guc_state_capture_group_t output
* followed by 3 x guc_state_capture_t lists. The latter is how the register * followed by 3 x guc_state_capture_t lists. The latter is how the register
* dumps are split across different register types (where the '3' are global vs class * dumps are split across different register types (where the '3' are global vs class
* vs instance). Finally, let's multiply the whole thing by 3x (just so we are * vs instance).
* not limited to just 1 round of data in a worst case full register dump log)
*
* NOTE: intel_guc_log that allocates the log buffer would round this size up to
* a power of two.
*/ */
for_each_engine(engine, gt, id) { for_each_engine(engine, gt, id) {
worst_min_size += sizeof(struct guc_state_capture_group_header_t) + worst_min_size += sizeof(struct guc_state_capture_group_header_t) +
(3 * sizeof(struct guc_state_capture_header_t)); (3 * sizeof(struct guc_state_capture_header_t));
...@@ -649,7 +642,30 @@ intel_guc_capture_output_min_size_est(struct intel_guc *guc) ...@@ -649,7 +642,30 @@ intel_guc_capture_output_min_size_est(struct intel_guc *guc)
worst_min_size += (num_regs * sizeof(struct guc_mmio_reg)); worst_min_size += (num_regs * sizeof(struct guc_mmio_reg));
return (worst_min_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER); return worst_min_size;
}
/*
* Add on a 3x multiplier to allow for multiple back-to-back captures occurring
* before the i915 can read the data out and process it
*/
#define GUC_CAPTURE_OVERBUFFER_MULTIPLIER 3
static void check_guc_capture_size(struct intel_guc *guc)
{
struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
int min_size = guc_capture_output_min_size_est(guc);
int spare_size = min_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER;
if (min_size < 0)
drm_warn(&i915->drm, "Failed to calculate GuC error state capture buffer minimum size: %d!\n",
min_size);
else if (min_size > CAPTURE_BUFFER_SIZE)
drm_warn(&i915->drm, "GuC error state capture buffer is too small: %d < %d\n",
CAPTURE_BUFFER_SIZE, min_size);
else if (spare_size > CAPTURE_BUFFER_SIZE)
drm_notice(&i915->drm, "GuC error state capture buffer maybe too small: %d < %d (min = %d)\n",
CAPTURE_BUFFER_SIZE, spare_size, min_size);
} }
/* /*
...@@ -1580,5 +1596,7 @@ int intel_guc_capture_init(struct intel_guc *guc) ...@@ -1580,5 +1596,7 @@ int intel_guc_capture_init(struct intel_guc *guc)
INIT_LIST_HEAD(&guc->capture->outlist); INIT_LIST_HEAD(&guc->capture->outlist);
INIT_LIST_HEAD(&guc->capture->cachelist); INIT_LIST_HEAD(&guc->capture->cachelist);
check_guc_capture_size(guc);
return 0; return 0;
} }
...@@ -21,7 +21,6 @@ int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *m, ...@@ -21,7 +21,6 @@ int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *m,
void intel_guc_capture_get_matching_node(struct intel_gt *gt, struct intel_engine_coredump *ee, void intel_guc_capture_get_matching_node(struct intel_gt *gt, struct intel_engine_coredump *ee,
struct intel_context *ce); struct intel_context *ce);
void intel_guc_capture_process(struct intel_guc *guc); void intel_guc_capture_process(struct intel_guc *guc);
int intel_guc_capture_output_min_size_est(struct intel_guc *guc);
int intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid, int intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid,
void **outptr); void **outptr);
int intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid, int intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid,
......
...@@ -455,6 +455,7 @@ static int ct_write(struct intel_guc_ct *ct, ...@@ -455,6 +455,7 @@ static int ct_write(struct intel_guc_ct *ct,
/** /**
* wait_for_ct_request_update - Wait for CT request state update. * wait_for_ct_request_update - Wait for CT request state update.
* @ct: pointer to CT
* @req: pointer to pending request * @req: pointer to pending request
* @status: placeholder for status * @status: placeholder for status
* *
...@@ -467,9 +468,10 @@ static int ct_write(struct intel_guc_ct *ct, ...@@ -467,9 +468,10 @@ static int ct_write(struct intel_guc_ct *ct,
* * 0 response received (status is valid) * * 0 response received (status is valid)
* * -ETIMEDOUT no response within hardcoded timeout * * -ETIMEDOUT no response within hardcoded timeout
*/ */
static int wait_for_ct_request_update(struct ct_request *req, u32 *status) static int wait_for_ct_request_update(struct intel_guc_ct *ct, struct ct_request *req, u32 *status)
{ {
int err; int err;
bool ct_enabled;
/* /*
* Fast commands should complete in less than 10us, so sample quickly * Fast commands should complete in less than 10us, so sample quickly
...@@ -481,12 +483,15 @@ static int wait_for_ct_request_update(struct ct_request *req, u32 *status) ...@@ -481,12 +483,15 @@ static int wait_for_ct_request_update(struct ct_request *req, u32 *status)
#define GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS 10 #define GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS 10
#define GUC_CTB_RESPONSE_TIMEOUT_LONG_MS 1000 #define GUC_CTB_RESPONSE_TIMEOUT_LONG_MS 1000
#define done \ #define done \
(FIELD_GET(GUC_HXG_MSG_0_ORIGIN, READ_ONCE(req->status)) == \ (!(ct_enabled = intel_guc_ct_enabled(ct)) || \
FIELD_GET(GUC_HXG_MSG_0_ORIGIN, READ_ONCE(req->status)) == \
GUC_HXG_ORIGIN_GUC) GUC_HXG_ORIGIN_GUC)
err = wait_for_us(done, GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS); err = wait_for_us(done, GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS);
if (err) if (err)
err = wait_for(done, GUC_CTB_RESPONSE_TIMEOUT_LONG_MS); err = wait_for(done, GUC_CTB_RESPONSE_TIMEOUT_LONG_MS);
#undef done #undef done
if (!ct_enabled)
err = -ENODEV;
*status = req->status; *status = req->status;
return err; return err;
...@@ -703,11 +708,18 @@ static int ct_send(struct intel_guc_ct *ct, ...@@ -703,11 +708,18 @@ static int ct_send(struct intel_guc_ct *ct,
intel_guc_notify(ct_to_guc(ct)); intel_guc_notify(ct_to_guc(ct));
err = wait_for_ct_request_update(&request, status); err = wait_for_ct_request_update(ct, &request, status);
g2h_release_space(ct, GUC_CTB_HXG_MSG_MAX_LEN); g2h_release_space(ct, GUC_CTB_HXG_MSG_MAX_LEN);
if (unlikely(err)) { if (unlikely(err)) {
CT_ERROR(ct, "No response for request %#x (fence %u)\n", if (err == -ENODEV)
action[0], request.fence); /* wait_for_ct_request_update returns -ENODEV on reset/suspend in progress.
* In this case, output is debug rather than error info
*/
CT_DEBUG(ct, "Request %#x (fence %u) cancelled as CTB is disabled\n",
action[0], request.fence);
else
CT_ERROR(ct, "No response for request %#x (fence %u)\n",
action[0], request.fence);
goto unlink; goto unlink;
} }
...@@ -771,8 +783,9 @@ int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 *action, u32 len, ...@@ -771,8 +783,9 @@ int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 *action, u32 len,
ret = ct_send(ct, action, len, response_buf, response_buf_size, &status); ret = ct_send(ct, action, len, response_buf, response_buf_size, &status);
if (unlikely(ret < 0)) { if (unlikely(ret < 0)) {
CT_ERROR(ct, "Sending action %#x failed (%pe) status=%#X\n", if (ret != -ENODEV)
action[0], ERR_PTR(ret), status); CT_ERROR(ct, "Sending action %#x failed (%pe) status=%#X\n",
action[0], ERR_PTR(ret), status);
} else if (unlikely(ret)) { } else if (unlikely(ret)) {
CT_DEBUG(ct, "send action %#x returned %d (%#x)\n", CT_DEBUG(ct, "send action %#x returned %d (%#x)\n",
action[0], ret, ret); action[0], ret, ret);
...@@ -816,8 +829,22 @@ static int ct_read(struct intel_guc_ct *ct, struct ct_incoming_msg **msg) ...@@ -816,8 +829,22 @@ static int ct_read(struct intel_guc_ct *ct, struct ct_incoming_msg **msg)
if (unlikely(ctb->broken)) if (unlikely(ctb->broken))
return -EPIPE; return -EPIPE;
if (unlikely(desc->status)) if (unlikely(desc->status)) {
goto corrupted; u32 status = desc->status;
if (status & GUC_CTB_STATUS_UNUSED) {
/*
* Potentially valid if a CLIENT_RESET request resulted in
* contexts/engines being reset. But should never happen as
* no contexts should be active when CLIENT_RESET is sent.
*/
CT_ERROR(ct, "Unexpected G2H after GuC has stopped!\n");
status &= ~GUC_CTB_STATUS_UNUSED;
}
if (status)
goto corrupted;
}
GEM_BUG_ON(head > size); GEM_BUG_ON(head > size);
......
...@@ -15,6 +15,32 @@ ...@@ -15,6 +15,32 @@
static void guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log); static void guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log);
static u32 intel_guc_log_size(struct intel_guc_log *log)
{
/*
* GuC Log buffer Layout:
*
* NB: Ordering must follow "enum guc_log_buffer_type".
*
* +===============================+ 00B
* | Debug state header |
* +-------------------------------+ 32B
* | Crash dump state header |
* +-------------------------------+ 64B
* | Capture state header |
* +-------------------------------+ 96B
* | |
* +===============================+ PAGE_SIZE (4KB)
* | Debug logs |
* +===============================+ + DEBUG_SIZE
* | Crash Dump logs |
* +===============================+ + CRASH_SIZE
* | Capture logs |
* +===============================+ + CAPTURE_SIZE
*/
return PAGE_SIZE + CRASH_BUFFER_SIZE + DEBUG_BUFFER_SIZE + CAPTURE_BUFFER_SIZE;
}
/** /**
* DOC: GuC firmware log * DOC: GuC firmware log
* *
...@@ -461,32 +487,7 @@ int intel_guc_log_create(struct intel_guc_log *log) ...@@ -461,32 +487,7 @@ int intel_guc_log_create(struct intel_guc_log *log)
GEM_BUG_ON(log->vma); GEM_BUG_ON(log->vma);
/* guc_log_size = intel_guc_log_size(log);
* GuC Log buffer Layout
* (this ordering must follow "enum guc_log_buffer_type" definition)
*
* +===============================+ 00B
* | Debug state header |
* +-------------------------------+ 32B
* | Crash dump state header |
* +-------------------------------+ 64B
* | Capture state header |
* +-------------------------------+ 96B
* | |
* +===============================+ PAGE_SIZE (4KB)
* | Debug logs |
* +===============================+ + DEBUG_SIZE
* | Crash Dump logs |
* +===============================+ + CRASH_SIZE
* | Capture logs |
* +===============================+ + CAPTURE_SIZE
*/
if (intel_guc_capture_output_min_size_est(guc) > CAPTURE_BUFFER_SIZE)
DRM_WARN("GuC log buffer for state_capture maybe too small. %d < %d\n",
CAPTURE_BUFFER_SIZE, intel_guc_capture_output_min_size_est(guc));
guc_log_size = PAGE_SIZE + CRASH_BUFFER_SIZE + DEBUG_BUFFER_SIZE +
CAPTURE_BUFFER_SIZE;
vma = intel_guc_allocate_vma(guc, guc_log_size); vma = intel_guc_allocate_vma(guc, guc_log_size);
if (IS_ERR(vma)) { if (IS_ERR(vma)) {
...@@ -749,8 +750,9 @@ int intel_guc_log_dump(struct intel_guc_log *log, struct drm_printer *p, ...@@ -749,8 +750,9 @@ int intel_guc_log_dump(struct intel_guc_log *log, struct drm_printer *p,
struct intel_guc *guc = log_to_guc(log); struct intel_guc *guc = log_to_guc(log);
struct intel_uc *uc = container_of(guc, struct intel_uc, guc); struct intel_uc *uc = container_of(guc, struct intel_uc, guc);
struct drm_i915_gem_object *obj = NULL; struct drm_i915_gem_object *obj = NULL;
u32 *map; void *map;
int i = 0; u32 *page;
int i, j;
if (!intel_guc_is_supported(guc)) if (!intel_guc_is_supported(guc))
return -ENODEV; return -ENODEV;
...@@ -763,21 +765,34 @@ int intel_guc_log_dump(struct intel_guc_log *log, struct drm_printer *p, ...@@ -763,21 +765,34 @@ int intel_guc_log_dump(struct intel_guc_log *log, struct drm_printer *p,
if (!obj) if (!obj)
return 0; return 0;
page = (u32 *)__get_free_page(GFP_KERNEL);
if (!page)
return -ENOMEM;
intel_guc_dump_time_info(guc, p);
map = i915_gem_object_pin_map_unlocked(obj, I915_MAP_WC); map = i915_gem_object_pin_map_unlocked(obj, I915_MAP_WC);
if (IS_ERR(map)) { if (IS_ERR(map)) {
DRM_DEBUG("Failed to pin object\n"); DRM_DEBUG("Failed to pin object\n");
drm_puts(p, "(log data unaccessible)\n"); drm_puts(p, "(log data unaccessible)\n");
free_page((unsigned long)page);
return PTR_ERR(map); return PTR_ERR(map);
} }
for (i = 0; i < obj->base.size / sizeof(u32); i += 4) for (i = 0; i < obj->base.size; i += PAGE_SIZE) {
drm_printf(p, "0x%08x 0x%08x 0x%08x 0x%08x\n", if (!i915_memcpy_from_wc(page, map + i, PAGE_SIZE))
*(map + i), *(map + i + 1), memcpy(page, map + i, PAGE_SIZE);
*(map + i + 2), *(map + i + 3));
for (j = 0; j < PAGE_SIZE / sizeof(u32); j += 4)
drm_printf(p, "0x%08x 0x%08x 0x%08x 0x%08x\n",
*(page + j + 0), *(page + j + 1),
*(page + j + 2), *(page + j + 3));
}
drm_puts(p, "\n"); drm_puts(p, "\n");
i915_gem_object_unpin_map(obj); i915_gem_object_unpin_map(obj);
free_page((unsigned long)page);
return 0; return 0;
} }
...@@ -22,11 +22,11 @@ struct intel_guc; ...@@ -22,11 +22,11 @@ struct intel_guc;
#elif defined(CONFIG_DRM_I915_DEBUG_GEM) #elif defined(CONFIG_DRM_I915_DEBUG_GEM)
#define CRASH_BUFFER_SIZE SZ_1M #define CRASH_BUFFER_SIZE SZ_1M
#define DEBUG_BUFFER_SIZE SZ_2M #define DEBUG_BUFFER_SIZE SZ_2M
#define CAPTURE_BUFFER_SIZE SZ_1M #define CAPTURE_BUFFER_SIZE SZ_4M
#else #else
#define CRASH_BUFFER_SIZE SZ_8K #define CRASH_BUFFER_SIZE SZ_8K
#define DEBUG_BUFFER_SIZE SZ_64K #define DEBUG_BUFFER_SIZE SZ_64K
#define CAPTURE_BUFFER_SIZE SZ_16K #define CAPTURE_BUFFER_SIZE SZ_2M
#endif #endif
/* /*
......
...@@ -102,6 +102,10 @@ ...@@ -102,6 +102,10 @@
#define GUC_SEND_TRIGGER (1<<0) #define GUC_SEND_TRIGGER (1<<0)
#define GEN11_GUC_HOST_INTERRUPT _MMIO(0x1901f0) #define GEN11_GUC_HOST_INTERRUPT _MMIO(0x1901f0)
#define GEN12_GUC_SEM_INTR_ENABLES _MMIO(0xc71c)
#define GUC_SEM_INTR_ROUTE_TO_GUC BIT(31)
#define GUC_SEM_INTR_ENABLE_ALL (0xff)
#define GUC_NUM_DOORBELLS 256 #define GUC_NUM_DOORBELLS 256
/* format of the HW-monitored doorbell cacheline */ /* format of the HW-monitored doorbell cacheline */
......
...@@ -575,20 +575,24 @@ static int slpc_set_softlimits(struct intel_guc_slpc *slpc) ...@@ -575,20 +575,24 @@ static int slpc_set_softlimits(struct intel_guc_slpc *slpc)
* unless they have deviated from defaults, in which case, * unless they have deviated from defaults, in which case,
* we retain the values and set min/max accordingly. * we retain the values and set min/max accordingly.
*/ */
if (!slpc->max_freq_softlimit) if (!slpc->max_freq_softlimit) {
slpc->max_freq_softlimit = slpc->rp0_freq; slpc->max_freq_softlimit = slpc->rp0_freq;
else if (slpc->max_freq_softlimit != slpc->rp0_freq) slpc_to_gt(slpc)->defaults.max_freq = slpc->max_freq_softlimit;
} else if (slpc->max_freq_softlimit != slpc->rp0_freq) {
ret = intel_guc_slpc_set_max_freq(slpc, ret = intel_guc_slpc_set_max_freq(slpc,
slpc->max_freq_softlimit); slpc->max_freq_softlimit);
}
if (unlikely(ret)) if (unlikely(ret))
return ret; return ret;
if (!slpc->min_freq_softlimit) if (!slpc->min_freq_softlimit) {
slpc->min_freq_softlimit = slpc->min_freq; slpc->min_freq_softlimit = slpc->min_freq;
else if (slpc->min_freq_softlimit != slpc->min_freq) slpc_to_gt(slpc)->defaults.min_freq = slpc->min_freq_softlimit;
} else if (slpc->min_freq_softlimit != slpc->min_freq) {
return intel_guc_slpc_set_min_freq(slpc, return intel_guc_slpc_set_min_freq(slpc,
slpc->min_freq_softlimit); slpc->min_freq_softlimit);
}
return 0; return 0;
} }
......
...@@ -2420,7 +2420,6 @@ static int guc_context_policy_init_v70(struct intel_context *ce, bool loop) ...@@ -2420,7 +2420,6 @@ static int guc_context_policy_init_v70(struct intel_context *ce, bool loop)
struct context_policy policy; struct context_policy policy;
u32 execution_quantum; u32 execution_quantum;
u32 preemption_timeout; u32 preemption_timeout;
bool missing = false;
unsigned long flags; unsigned long flags;
int ret; int ret;
...@@ -2438,32 +2437,9 @@ static int guc_context_policy_init_v70(struct intel_context *ce, bool loop) ...@@ -2438,32 +2437,9 @@ static int guc_context_policy_init_v70(struct intel_context *ce, bool loop)
__guc_context_policy_add_preempt_to_idle(&policy, 1); __guc_context_policy_add_preempt_to_idle(&policy, 1);
ret = __guc_context_set_context_policies(guc, &policy, loop); ret = __guc_context_set_context_policies(guc, &policy, loop);
missing = ret != 0;
if (!missing && intel_context_is_parent(ce)) {
struct intel_context *child;
for_each_child(ce, child) {
__guc_context_policy_start_klv(&policy, child->guc_id.id);
if (engine->flags & I915_ENGINE_WANT_FORCED_PREEMPTION)
__guc_context_policy_add_preempt_to_idle(&policy, 1);
child->guc_state.prio = ce->guc_state.prio;
__guc_context_policy_add_priority(&policy, ce->guc_state.prio);
__guc_context_policy_add_execution_quantum(&policy, execution_quantum);
__guc_context_policy_add_preemption_timeout(&policy, preemption_timeout);
ret = __guc_context_set_context_policies(guc, &policy, loop);
if (ret) {
missing = true;
break;
}
}
}
spin_lock_irqsave(&ce->guc_state.lock, flags); spin_lock_irqsave(&ce->guc_state.lock, flags);
if (missing) if (ret != 0)
set_context_policy_required(ce); set_context_policy_required(ce);
else else
clr_context_policy_required(ce); clr_context_policy_required(ce);
...@@ -4191,13 +4167,27 @@ int intel_guc_submission_setup(struct intel_engine_cs *engine) ...@@ -4191,13 +4167,27 @@ int intel_guc_submission_setup(struct intel_engine_cs *engine)
void intel_guc_submission_enable(struct intel_guc *guc) void intel_guc_submission_enable(struct intel_guc *guc)
{ {
struct intel_gt *gt = guc_to_gt(guc);
/* Enable and route to GuC */
if (GRAPHICS_VER(gt->i915) >= 12)
intel_uncore_write(gt->uncore, GEN12_GUC_SEM_INTR_ENABLES,
GUC_SEM_INTR_ROUTE_TO_GUC |
GUC_SEM_INTR_ENABLE_ALL);
guc_init_lrc_mapping(guc); guc_init_lrc_mapping(guc);
guc_init_engine_stats(guc); guc_init_engine_stats(guc);
} }
void intel_guc_submission_disable(struct intel_guc *guc) void intel_guc_submission_disable(struct intel_guc *guc)
{ {
struct intel_gt *gt = guc_to_gt(guc);
/* Note: By the time we're here, GuC may have already been reset */ /* Note: By the time we're here, GuC may have already been reset */
/* Disable and route to host */
if (GRAPHICS_VER(gt->i915) >= 12)
intel_uncore_write(gt->uncore, GEN12_GUC_SEM_INTR_ENABLES, 0x0);
} }
static bool __guc_submission_supported(struct intel_guc *guc) static bool __guc_submission_supported(struct intel_guc *guc)
...@@ -5163,4 +5153,5 @@ bool intel_guc_virtual_engine_has_heartbeat(const struct intel_engine_cs *ve) ...@@ -5163,4 +5153,5 @@ bool intel_guc_virtual_engine_has_heartbeat(const struct intel_engine_cs *ve)
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftest_guc.c" #include "selftest_guc.c"
#include "selftest_guc_multi_lrc.c" #include "selftest_guc_multi_lrc.c"
#include "selftest_guc_hangcheck.c"
#endif #endif
...@@ -53,7 +53,7 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, ...@@ -53,7 +53,7 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
* firmware as TGL. * firmware as TGL.
*/ */
#define INTEL_GUC_FIRMWARE_DEFS(fw_def, guc_def) \ #define INTEL_GUC_FIRMWARE_DEFS(fw_def, guc_def) \
fw_def(DG2, 0, guc_def(dg2, 70, 1, 2)) \ fw_def(DG2, 0, guc_def(dg2, 70, 4, 1)) \
fw_def(ALDERLAKE_P, 0, guc_def(adlp, 70, 1, 1)) \ fw_def(ALDERLAKE_P, 0, guc_def(adlp, 70, 1, 1)) \
fw_def(ALDERLAKE_S, 0, guc_def(tgl, 70, 1, 1)) \ fw_def(ALDERLAKE_S, 0, guc_def(tgl, 70, 1, 1)) \
fw_def(DG1, 0, guc_def(dg1, 70, 1, 1)) \ fw_def(DG1, 0, guc_def(dg1, 70, 1, 1)) \
...@@ -220,11 +220,11 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw) ...@@ -220,11 +220,11 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
fw_blobs[i].rev < fw_blobs[i - 1].rev) fw_blobs[i].rev < fw_blobs[i - 1].rev)
continue; continue;
pr_err("invalid FW blob order: %s r%u comes before %s r%u\n", drm_err(&i915->drm, "Invalid FW blob order: %s r%u comes before %s r%u\n",
intel_platform_name(fw_blobs[i - 1].p), intel_platform_name(fw_blobs[i - 1].p),
fw_blobs[i - 1].rev, fw_blobs[i - 1].rev,
intel_platform_name(fw_blobs[i].p), intel_platform_name(fw_blobs[i].p),
fw_blobs[i].rev); fw_blobs[i].rev);
uc_fw->path = NULL; uc_fw->path = NULL;
} }
......
...@@ -62,7 +62,7 @@ static int intel_guc_scrub_ctbs(void *arg) ...@@ -62,7 +62,7 @@ static int intel_guc_scrub_ctbs(void *arg)
ce = intel_context_create(engine); ce = intel_context_create(engine);
if (IS_ERR(ce)) { if (IS_ERR(ce)) {
ret = PTR_ERR(ce); ret = PTR_ERR(ce);
pr_err("Failed to create context, %d: %d\n", i, ret); drm_err(&gt->i915->drm, "Failed to create context, %d: %d\n", i, ret);
goto err; goto err;
} }
...@@ -83,7 +83,7 @@ static int intel_guc_scrub_ctbs(void *arg) ...@@ -83,7 +83,7 @@ static int intel_guc_scrub_ctbs(void *arg)
if (IS_ERR(rq)) { if (IS_ERR(rq)) {
ret = PTR_ERR(rq); ret = PTR_ERR(rq);
pr_err("Failed to create request, %d: %d\n", i, ret); drm_err(&gt->i915->drm, "Failed to create request, %d: %d\n", i, ret);
goto err; goto err;
} }
...@@ -93,7 +93,7 @@ static int intel_guc_scrub_ctbs(void *arg) ...@@ -93,7 +93,7 @@ static int intel_guc_scrub_ctbs(void *arg)
for (i = 0; i < 3; ++i) { for (i = 0; i < 3; ++i) {
ret = i915_request_wait(last[i], 0, HZ); ret = i915_request_wait(last[i], 0, HZ);
if (ret < 0) { if (ret < 0) {
pr_err("Last request failed to complete: %d\n", ret); drm_err(&gt->i915->drm, "Last request failed to complete: %d\n", ret);
goto err; goto err;
} }
i915_request_put(last[i]); i915_request_put(last[i]);
...@@ -110,7 +110,7 @@ static int intel_guc_scrub_ctbs(void *arg) ...@@ -110,7 +110,7 @@ static int intel_guc_scrub_ctbs(void *arg)
/* GT will not idle if G2H are lost */ /* GT will not idle if G2H are lost */
ret = intel_gt_wait_for_idle(gt, HZ); ret = intel_gt_wait_for_idle(gt, HZ);
if (ret < 0) { if (ret < 0) {
pr_err("GT failed to idle: %d\n", ret); drm_err(&gt->i915->drm, "GT failed to idle: %d\n", ret);
goto err; goto err;
} }
...@@ -150,7 +150,7 @@ static int intel_guc_steal_guc_ids(void *arg) ...@@ -150,7 +150,7 @@ static int intel_guc_steal_guc_ids(void *arg)
ce = kcalloc(GUC_MAX_CONTEXT_ID, sizeof(*ce), GFP_KERNEL); ce = kcalloc(GUC_MAX_CONTEXT_ID, sizeof(*ce), GFP_KERNEL);
if (!ce) { if (!ce) {
pr_err("Context array allocation failed\n"); drm_err(&gt->i915->drm, "Context array allocation failed\n");
return -ENOMEM; return -ENOMEM;
} }
...@@ -164,24 +164,24 @@ static int intel_guc_steal_guc_ids(void *arg) ...@@ -164,24 +164,24 @@ static int intel_guc_steal_guc_ids(void *arg)
if (IS_ERR(ce[context_index])) { if (IS_ERR(ce[context_index])) {
ret = PTR_ERR(ce[context_index]); ret = PTR_ERR(ce[context_index]);
ce[context_index] = NULL; ce[context_index] = NULL;
pr_err("Failed to create context: %d\n", ret); drm_err(&gt->i915->drm, "Failed to create context: %d\n", ret);
goto err_wakeref; goto err_wakeref;
} }
ret = igt_spinner_init(&spin, engine->gt); ret = igt_spinner_init(&spin, engine->gt);
if (ret) { if (ret) {
pr_err("Failed to create spinner: %d\n", ret); drm_err(&gt->i915->drm, "Failed to create spinner: %d\n", ret);
goto err_contexts; goto err_contexts;
} }
spin_rq = igt_spinner_create_request(&spin, ce[context_index], spin_rq = igt_spinner_create_request(&spin, ce[context_index],
MI_ARB_CHECK); MI_ARB_CHECK);
if (IS_ERR(spin_rq)) { if (IS_ERR(spin_rq)) {
ret = PTR_ERR(spin_rq); ret = PTR_ERR(spin_rq);
pr_err("Failed to create spinner request: %d\n", ret); drm_err(&gt->i915->drm, "Failed to create spinner request: %d\n", ret);
goto err_contexts; goto err_contexts;
} }
ret = request_add_spin(spin_rq, &spin); ret = request_add_spin(spin_rq, &spin);
if (ret) { if (ret) {
pr_err("Failed to add Spinner request: %d\n", ret); drm_err(&gt->i915->drm, "Failed to add Spinner request: %d\n", ret);
goto err_spin_rq; goto err_spin_rq;
} }
...@@ -191,7 +191,7 @@ static int intel_guc_steal_guc_ids(void *arg) ...@@ -191,7 +191,7 @@ static int intel_guc_steal_guc_ids(void *arg)
if (IS_ERR(ce[context_index])) { if (IS_ERR(ce[context_index])) {
ret = PTR_ERR(ce[context_index--]); ret = PTR_ERR(ce[context_index--]);
ce[context_index] = NULL; ce[context_index] = NULL;
pr_err("Failed to create context: %d\n", ret); drm_err(&gt->i915->drm, "Failed to create context: %d\n", ret);
goto err_spin_rq; goto err_spin_rq;
} }
...@@ -200,8 +200,8 @@ static int intel_guc_steal_guc_ids(void *arg) ...@@ -200,8 +200,8 @@ static int intel_guc_steal_guc_ids(void *arg)
ret = PTR_ERR(rq); ret = PTR_ERR(rq);
rq = NULL; rq = NULL;
if (ret != -EAGAIN) { if (ret != -EAGAIN) {
pr_err("Failed to create request, %d: %d\n", drm_err(&gt->i915->drm, "Failed to create request, %d: %d\n",
context_index, ret); context_index, ret);
goto err_spin_rq; goto err_spin_rq;
} }
} else { } else {
...@@ -215,7 +215,7 @@ static int intel_guc_steal_guc_ids(void *arg) ...@@ -215,7 +215,7 @@ static int intel_guc_steal_guc_ids(void *arg)
igt_spinner_end(&spin); igt_spinner_end(&spin);
ret = intel_selftest_wait_for_rq(spin_rq); ret = intel_selftest_wait_for_rq(spin_rq);
if (ret) { if (ret) {
pr_err("Spin request failed to complete: %d\n", ret); drm_err(&gt->i915->drm, "Spin request failed to complete: %d\n", ret);
i915_request_put(last); i915_request_put(last);
goto err_spin_rq; goto err_spin_rq;
} }
...@@ -227,7 +227,7 @@ static int intel_guc_steal_guc_ids(void *arg) ...@@ -227,7 +227,7 @@ static int intel_guc_steal_guc_ids(void *arg)
ret = i915_request_wait(last, 0, HZ * 30); ret = i915_request_wait(last, 0, HZ * 30);
i915_request_put(last); i915_request_put(last);
if (ret < 0) { if (ret < 0) {
pr_err("Last request failed to complete: %d\n", ret); drm_err(&gt->i915->drm, "Last request failed to complete: %d\n", ret);
goto err_spin_rq; goto err_spin_rq;
} }
...@@ -235,7 +235,7 @@ static int intel_guc_steal_guc_ids(void *arg) ...@@ -235,7 +235,7 @@ static int intel_guc_steal_guc_ids(void *arg)
rq = nop_user_request(ce[context_index], NULL); rq = nop_user_request(ce[context_index], NULL);
if (IS_ERR(rq)) { if (IS_ERR(rq)) {
ret = PTR_ERR(rq); ret = PTR_ERR(rq);
pr_err("Failed to steal guc_id, %d: %d\n", context_index, ret); drm_err(&gt->i915->drm, "Failed to steal guc_id, %d: %d\n", context_index, ret);
goto err_spin_rq; goto err_spin_rq;
} }
...@@ -243,21 +243,20 @@ static int intel_guc_steal_guc_ids(void *arg) ...@@ -243,21 +243,20 @@ static int intel_guc_steal_guc_ids(void *arg)
ret = i915_request_wait(rq, 0, HZ); ret = i915_request_wait(rq, 0, HZ);
i915_request_put(rq); i915_request_put(rq);
if (ret < 0) { if (ret < 0) {
pr_err("Request with stolen guc_id failed to complete: %d\n", drm_err(&gt->i915->drm, "Request with stolen guc_id failed to complete: %d\n", ret);
ret);
goto err_spin_rq; goto err_spin_rq;
} }
/* Wait for idle */ /* Wait for idle */
ret = intel_gt_wait_for_idle(gt, HZ * 30); ret = intel_gt_wait_for_idle(gt, HZ * 30);
if (ret < 0) { if (ret < 0) {
pr_err("GT failed to idle: %d\n", ret); drm_err(&gt->i915->drm, "GT failed to idle: %d\n", ret);
goto err_spin_rq; goto err_spin_rq;
} }
/* Verify a guc_id was stolen */ /* Verify a guc_id was stolen */
if (guc->number_guc_id_stolen == number_guc_id_stolen) { if (guc->number_guc_id_stolen == number_guc_id_stolen) {
pr_err("No guc_id was stolen"); drm_err(&gt->i915->drm, "No guc_id was stolen");
ret = -EINVAL; ret = -EINVAL;
} else { } else {
ret = 0; ret = 0;
......
// SPDX-License-Identifier: MIT
/*
* Copyright © 2022 Intel Corporation
*/
#include "selftests/igt_spinner.h"
#include "selftests/igt_reset.h"
#include "selftests/intel_scheduler_helpers.h"
#include "gt/intel_engine_heartbeat.h"
#include "gem/selftests/mock_context.h"
#define BEAT_INTERVAL 100
static struct i915_request *nop_request(struct intel_engine_cs *engine)
{
struct i915_request *rq;
rq = intel_engine_create_kernel_request(engine);
if (IS_ERR(rq))
return rq;
i915_request_get(rq);
i915_request_add(rq);
return rq;
}
static int intel_hang_guc(void *arg)
{
struct intel_gt *gt = arg;
int ret = 0;
struct i915_gem_context *ctx;
struct intel_context *ce;
struct igt_spinner spin;
struct i915_request *rq;
intel_wakeref_t wakeref;
struct i915_gpu_error *global = &gt->i915->gpu_error;
struct intel_engine_cs *engine;
unsigned int reset_count;
u32 guc_status;
u32 old_beat;
ctx = kernel_context(gt->i915, NULL);
if (IS_ERR(ctx)) {
drm_err(&gt->i915->drm, "Failed get kernel context: %ld\n", PTR_ERR(ctx));
return PTR_ERR(ctx);
}
wakeref = intel_runtime_pm_get(gt->uncore->rpm);
ce = intel_context_create(gt->engine[BCS0]);
if (IS_ERR(ce)) {
ret = PTR_ERR(ce);
drm_err(&gt->i915->drm, "Failed to create spinner request: %d\n", ret);
goto err;
}
engine = ce->engine;
reset_count = i915_reset_count(global);
old_beat = engine->props.heartbeat_interval_ms;
ret = intel_engine_set_heartbeat(engine, BEAT_INTERVAL);
if (ret) {
drm_err(&gt->i915->drm, "Failed to boost heatbeat interval: %d\n", ret);
goto err;
}
ret = igt_spinner_init(&spin, engine->gt);
if (ret) {
drm_err(&gt->i915->drm, "Failed to create spinner: %d\n", ret);
goto err;
}
rq = igt_spinner_create_request(&spin, ce, MI_NOOP);
intel_context_put(ce);
if (IS_ERR(rq)) {
ret = PTR_ERR(rq);
drm_err(&gt->i915->drm, "Failed to create spinner request: %d\n", ret);
goto err_spin;
}
ret = request_add_spin(rq, &spin);
if (ret) {
i915_request_put(rq);
drm_err(&gt->i915->drm, "Failed to add Spinner request: %d\n", ret);
goto err_spin;
}
ret = intel_reset_guc(gt);
if (ret) {
i915_request_put(rq);
drm_err(&gt->i915->drm, "Failed to reset GuC, ret = %d\n", ret);
goto err_spin;
}
guc_status = intel_uncore_read(gt->uncore, GUC_STATUS);
if (!(guc_status & GS_MIA_IN_RESET)) {
i915_request_put(rq);
drm_err(&gt->i915->drm, "GuC failed to reset: status = 0x%08X\n", guc_status);
ret = -EIO;
goto err_spin;
}
/* Wait for the heartbeat to cause a reset */
ret = intel_selftest_wait_for_rq(rq);
i915_request_put(rq);
if (ret) {
drm_err(&gt->i915->drm, "Request failed to complete: %d\n", ret);
goto err_spin;
}
if (i915_reset_count(global) == reset_count) {
drm_err(&gt->i915->drm, "Failed to record a GPU reset\n");
ret = -EINVAL;
goto err_spin;
}
err_spin:
igt_spinner_end(&spin);
igt_spinner_fini(&spin);
intel_engine_set_heartbeat(engine, old_beat);
if (ret == 0) {
rq = nop_request(engine);
if (IS_ERR(rq)) {
ret = PTR_ERR(rq);
goto err;
}
ret = intel_selftest_wait_for_rq(rq);
i915_request_put(rq);
if (ret) {
drm_err(&gt->i915->drm, "No-op failed to complete: %d\n", ret);
goto err;
}
}
err:
intel_runtime_pm_put(gt->uncore->rpm, wakeref);
kernel_context_close(ctx);
return ret;
}
int intel_guc_hang_check(struct drm_i915_private *i915)
{
static const struct i915_subtest tests[] = {
SUBTEST(intel_hang_guc),
};
struct intel_gt *gt = to_gt(i915);
if (intel_gt_is_wedged(gt))
return 0;
if (!intel_uc_uses_guc_submission(&gt->uc))
return 0;
return intel_gt_live_subtests(tests, gt);
}
...@@ -115,30 +115,30 @@ static int __intel_guc_multi_lrc_basic(struct intel_gt *gt, unsigned int class) ...@@ -115,30 +115,30 @@ static int __intel_guc_multi_lrc_basic(struct intel_gt *gt, unsigned int class)
parent = multi_lrc_create_parent(gt, class, 0); parent = multi_lrc_create_parent(gt, class, 0);
if (IS_ERR(parent)) { if (IS_ERR(parent)) {
pr_err("Failed creating contexts: %ld", PTR_ERR(parent)); drm_err(&gt->i915->drm, "Failed creating contexts: %ld", PTR_ERR(parent));
return PTR_ERR(parent); return PTR_ERR(parent);
} else if (!parent) { } else if (!parent) {
pr_debug("Not enough engines in class: %d", class); drm_dbg(&gt->i915->drm, "Not enough engines in class: %d", class);
return 0; return 0;
} }
rq = multi_lrc_nop_request(parent); rq = multi_lrc_nop_request(parent);
if (IS_ERR(rq)) { if (IS_ERR(rq)) {
ret = PTR_ERR(rq); ret = PTR_ERR(rq);
pr_err("Failed creating requests: %d", ret); drm_err(&gt->i915->drm, "Failed creating requests: %d", ret);
goto out; goto out;
} }
ret = intel_selftest_wait_for_rq(rq); ret = intel_selftest_wait_for_rq(rq);
if (ret) if (ret)
pr_err("Failed waiting on request: %d", ret); drm_err(&gt->i915->drm, "Failed waiting on request: %d", ret);
i915_request_put(rq); i915_request_put(rq);
if (ret >= 0) { if (ret >= 0) {
ret = intel_gt_wait_for_idle(gt, HZ * 5); ret = intel_gt_wait_for_idle(gt, HZ * 5);
if (ret < 0) if (ret < 0)
pr_err("GT failed to idle: %d\n", ret); drm_err(&gt->i915->drm, "GT failed to idle: %d\n", ret);
} }
out: out:
......
...@@ -671,6 +671,18 @@ static void err_print_pciid(struct drm_i915_error_state_buf *m, ...@@ -671,6 +671,18 @@ static void err_print_pciid(struct drm_i915_error_state_buf *m,
pdev->subsystem_device); pdev->subsystem_device);
} }
static void err_print_guc_ctb(struct drm_i915_error_state_buf *m,
const char *name,
const struct intel_ctb_coredump *ctb)
{
if (!ctb->size)
return;
err_printf(m, "GuC %s CTB: raw: 0x%08X, 0x%08X/%08X, cached: 0x%08X/%08X, desc = 0x%08X, buf = 0x%08X x 0x%08X\n",
name, ctb->raw_status, ctb->raw_head, ctb->raw_tail,
ctb->head, ctb->tail, ctb->desc_offset, ctb->cmds_offset, ctb->size);
}
static void err_print_uc(struct drm_i915_error_state_buf *m, static void err_print_uc(struct drm_i915_error_state_buf *m,
const struct intel_uc_coredump *error_uc) const struct intel_uc_coredump *error_uc)
{ {
...@@ -678,7 +690,12 @@ static void err_print_uc(struct drm_i915_error_state_buf *m, ...@@ -678,7 +690,12 @@ static void err_print_uc(struct drm_i915_error_state_buf *m,
intel_uc_fw_dump(&error_uc->guc_fw, &p); intel_uc_fw_dump(&error_uc->guc_fw, &p);
intel_uc_fw_dump(&error_uc->huc_fw, &p); intel_uc_fw_dump(&error_uc->huc_fw, &p);
intel_gpu_error_print_vma(m, NULL, error_uc->guc_log); err_printf(m, "GuC timestamp: 0x%08x\n", error_uc->guc.timestamp);
intel_gpu_error_print_vma(m, NULL, error_uc->guc.vma_log);
err_printf(m, "GuC CTB fence: %d\n", error_uc->guc.last_fence);
err_print_guc_ctb(m, "Send", error_uc->guc.ctb + 0);
err_print_guc_ctb(m, "Recv", error_uc->guc.ctb + 1);
intel_gpu_error_print_vma(m, NULL, error_uc->guc.vma_ctb);
} }
static void err_free_sgl(struct scatterlist *sgl) static void err_free_sgl(struct scatterlist *sgl)
...@@ -720,6 +737,8 @@ static void err_print_gt_global_nonguc(struct drm_i915_error_state_buf *m, ...@@ -720,6 +737,8 @@ static void err_print_gt_global_nonguc(struct drm_i915_error_state_buf *m,
int i; int i;
err_printf(m, "GT awake: %s\n", str_yes_no(gt->awake)); err_printf(m, "GT awake: %s\n", str_yes_no(gt->awake));
err_printf(m, "CS timestamp frequency: %u Hz, %d ns\n",
gt->clock_frequency, gt->clock_period_ns);
err_printf(m, "EIR: 0x%08x\n", gt->eir); err_printf(m, "EIR: 0x%08x\n", gt->eir);
err_printf(m, "PGTBL_ER: 0x%08x\n", gt->pgtbl_er); err_printf(m, "PGTBL_ER: 0x%08x\n", gt->pgtbl_er);
...@@ -851,7 +870,7 @@ static void __err_print_to_sgl(struct drm_i915_error_state_buf *m, ...@@ -851,7 +870,7 @@ static void __err_print_to_sgl(struct drm_i915_error_state_buf *m,
if (error->gt) { if (error->gt) {
bool print_guc_capture = false; bool print_guc_capture = false;
if (error->gt->uc && error->gt->uc->is_guc_capture) if (error->gt->uc && error->gt->uc->guc.is_guc_capture)
print_guc_capture = true; print_guc_capture = true;
err_print_gt_display(m, error->gt); err_print_gt_display(m, error->gt);
...@@ -1006,7 +1025,8 @@ static void cleanup_uc(struct intel_uc_coredump *uc) ...@@ -1006,7 +1025,8 @@ static void cleanup_uc(struct intel_uc_coredump *uc)
{ {
kfree(uc->guc_fw.path); kfree(uc->guc_fw.path);
kfree(uc->huc_fw.path); kfree(uc->huc_fw.path);
i915_vma_coredump_free(uc->guc_log); i915_vma_coredump_free(uc->guc.vma_log);
i915_vma_coredump_free(uc->guc.vma_ctb);
kfree(uc); kfree(uc);
} }
...@@ -1655,6 +1675,23 @@ gt_record_engines(struct intel_gt_coredump *gt, ...@@ -1655,6 +1675,23 @@ gt_record_engines(struct intel_gt_coredump *gt,
} }
} }
static void gt_record_guc_ctb(struct intel_ctb_coredump *saved,
const struct intel_guc_ct_buffer *ctb,
const void *blob_ptr, struct intel_guc *guc)
{
if (!ctb || !ctb->desc)
return;
saved->raw_status = ctb->desc->status;
saved->raw_head = ctb->desc->head;
saved->raw_tail = ctb->desc->tail;
saved->head = ctb->head;
saved->tail = ctb->tail;
saved->size = ctb->size;
saved->desc_offset = ((void *)ctb->desc) - blob_ptr;
saved->cmds_offset = ((void *)ctb->cmds) - blob_ptr;
}
static struct intel_uc_coredump * static struct intel_uc_coredump *
gt_record_uc(struct intel_gt_coredump *gt, gt_record_uc(struct intel_gt_coredump *gt,
struct i915_vma_compress *compress) struct i915_vma_compress *compress)
...@@ -1675,8 +1712,22 @@ gt_record_uc(struct intel_gt_coredump *gt, ...@@ -1675,8 +1712,22 @@ gt_record_uc(struct intel_gt_coredump *gt,
*/ */
error_uc->guc_fw.path = kstrdup(uc->guc.fw.path, ALLOW_FAIL); error_uc->guc_fw.path = kstrdup(uc->guc.fw.path, ALLOW_FAIL);
error_uc->huc_fw.path = kstrdup(uc->huc.fw.path, ALLOW_FAIL); error_uc->huc_fw.path = kstrdup(uc->huc.fw.path, ALLOW_FAIL);
error_uc->guc_log = create_vma_coredump(gt->_gt, uc->guc.log.vma,
"GuC log buffer", compress); /*
* Save the GuC log and include a timestamp reference for converting the
* log times to system times (in conjunction with the error->boottime and
* gt->clock_frequency fields saved elsewhere).
*/
error_uc->guc.timestamp = intel_uncore_read(gt->_gt->uncore, GUCPMTIMESTAMP);
error_uc->guc.vma_log = create_vma_coredump(gt->_gt, uc->guc.log.vma,
"GuC log buffer", compress);
error_uc->guc.vma_ctb = create_vma_coredump(gt->_gt, uc->guc.ct.vma,
"GuC CT buffer", compress);
error_uc->guc.last_fence = uc->guc.ct.requests.last_fence;
gt_record_guc_ctb(error_uc->guc.ctb + 0, &uc->guc.ct.ctbs.send,
uc->guc.ct.ctbs.send.desc, (struct intel_guc *)&uc->guc);
gt_record_guc_ctb(error_uc->guc.ctb + 1, &uc->guc.ct.ctbs.recv,
uc->guc.ct.ctbs.send.desc, (struct intel_guc *)&uc->guc);
return error_uc; return error_uc;
} }
...@@ -1833,6 +1884,8 @@ static void gt_record_global_regs(struct intel_gt_coredump *gt) ...@@ -1833,6 +1884,8 @@ static void gt_record_global_regs(struct intel_gt_coredump *gt)
static void gt_record_info(struct intel_gt_coredump *gt) static void gt_record_info(struct intel_gt_coredump *gt)
{ {
memcpy(&gt->info, &gt->_gt->info, sizeof(struct intel_gt_info)); memcpy(&gt->info, &gt->_gt->info, sizeof(struct intel_gt_info));
gt->clock_frequency = gt->_gt->clock_frequency;
gt->clock_period_ns = gt->_gt->clock_period_ns;
} }
/* /*
...@@ -2027,9 +2080,9 @@ __i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask, u32 du ...@@ -2027,9 +2080,9 @@ __i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask, u32 du
error->gt->uc = gt_record_uc(error->gt, compress); error->gt->uc = gt_record_uc(error->gt, compress);
if (error->gt->uc) { if (error->gt->uc) {
if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE) if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE)
error->gt->uc->is_guc_capture = true; error->gt->uc->guc.is_guc_capture = true;
else else
GEM_BUG_ON(error->gt->uc->is_guc_capture); GEM_BUG_ON(error->gt->uc->guc.is_guc_capture);
} }
} }
......
...@@ -125,6 +125,15 @@ struct intel_engine_coredump { ...@@ -125,6 +125,15 @@ struct intel_engine_coredump {
struct intel_engine_coredump *next; struct intel_engine_coredump *next;
}; };
struct intel_ctb_coredump {
u32 raw_head, head;
u32 raw_tail, tail;
u32 raw_status;
u32 desc_offset;
u32 cmds_offset;
u32 size;
};
struct intel_gt_coredump { struct intel_gt_coredump {
const struct intel_gt *_gt; const struct intel_gt *_gt;
bool awake; bool awake;
...@@ -150,6 +159,8 @@ struct intel_gt_coredump { ...@@ -150,6 +159,8 @@ struct intel_gt_coredump {
u32 gtt_cache; u32 gtt_cache;
u32 aux_err; /* gen12 */ u32 aux_err; /* gen12 */
u32 gam_done; /* gen12 */ u32 gam_done; /* gen12 */
u32 clock_frequency;
u32 clock_period_ns;
/* Display related */ /* Display related */
u32 derrmr; u32 derrmr;
...@@ -163,8 +174,14 @@ struct intel_gt_coredump { ...@@ -163,8 +174,14 @@ struct intel_gt_coredump {
struct intel_uc_coredump { struct intel_uc_coredump {
struct intel_uc_fw guc_fw; struct intel_uc_fw guc_fw;
struct intel_uc_fw huc_fw; struct intel_uc_fw huc_fw;
struct i915_vma_coredump *guc_log; struct guc_info {
bool is_guc_capture; struct intel_ctb_coredump ctb[2];
struct i915_vma_coredump *vma_ctb;
struct i915_vma_coredump *vma_log;
u32 timestamp;
u16 last_fence;
bool is_guc_capture;
} guc;
} *uc; } *uc;
struct intel_gt_coredump *next; struct intel_gt_coredump *next;
......
...@@ -216,6 +216,10 @@ i915_vma_resource_fence_notify(struct i915_sw_fence *fence, ...@@ -216,6 +216,10 @@ i915_vma_resource_fence_notify(struct i915_sw_fence *fence,
/** /**
* i915_vma_resource_unbind - Unbind a vma resource * i915_vma_resource_unbind - Unbind a vma resource
* @vma_res: The vma resource to unbind. * @vma_res: The vma resource to unbind.
* @tlb: pointer to vma->obj->mm.tlb associated with the resource
* to be stored at vma_res->tlb. When not-NULL, it will be used
* to do TLB cache invalidation before freeing a VMA resource.
* Used only for async unbind.
* *
* At this point this function does little more than publish a fence that * At this point this function does little more than publish a fence that
* signals immediately unless signaling is held back. * signals immediately unless signaling is held back.
......
...@@ -49,5 +49,6 @@ selftest(perf, i915_perf_live_selftests) ...@@ -49,5 +49,6 @@ selftest(perf, i915_perf_live_selftests)
selftest(slpc, intel_slpc_live_selftests) selftest(slpc, intel_slpc_live_selftests)
selftest(guc, intel_guc_live_selftests) selftest(guc, intel_guc_live_selftests)
selftest(guc_multi_lrc, intel_guc_multi_lrc_live_selftests) selftest(guc_multi_lrc, intel_guc_multi_lrc_live_selftests)
selftest(guc_hang, intel_guc_hang_check)
/* Here be dragons: keep last to run last! */ /* Here be dragons: keep last to run last! */
selftest(late_gt_pm, intel_gt_pm_late_selftests) selftest(late_gt_pm, intel_gt_pm_late_selftests)
...@@ -971,7 +971,7 @@ static struct i915_vma *empty_batch(struct drm_i915_private *i915) ...@@ -971,7 +971,7 @@ static struct i915_vma *empty_batch(struct drm_i915_private *i915)
if (err) if (err)
goto err; goto err;
/* Force the wait wait now to avoid including it in the benchmark */ /* Force the wait now to avoid including it in the benchmark */
err = i915_vma_sync(vma); err = i915_vma_sync(vma);
if (err) if (err)
goto err_pin; goto err_pin;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment