Commit 614351f4 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-gt-next-2023-10-12' of...

Merge tag 'drm-intel-gt-next-2023-10-12' of git://anongit.freedesktop.org/drm/drm-intel into drm-next

Driver Changes:

Fixes/improvements/new stuff:

- Register engines early to avoid type confusion (Mathias Krause)
- Suppress 'ignoring reset notification' message [guc] (John Harrison)
- Update 'recommended' version to 70.12.1 for DG2/ADL-S/ADL-P/MTL [guc] (John Harrison)
- Enable WA 14018913170 [guc, dg2] (Daniele Ceraolo Spurio)

Future platform enablement:

- Clean steer semaphore on resume (Nirmoy Das)
- Skip MCR ops for ring fault register [mtl] (Nirmoy Das)
- Make i915_gem_shrinker multi-gt aware [gem] (Jonathan Cavitt)
- Enable GGTT updates with binder in MTL (Nirmoy Das, Chris Wilson)
- Invalidate the TLBs on each GT (Chris Wilson)

Miscellaneous:

- Clarify type evolution of uabi_node/uabi_engines (Mathias Krause)
- Annotate struct ct_incoming_msg with __counted_by [guc] (Kees Cook)
- More use of GT specific print helpers [gt] (John Harrison)
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/ZSfKotZVdypU6NaX@tursulin-desk
parents 7971debd 039adf39
...@@ -198,7 +198,7 @@ static void flush_tlb_invalidate(struct drm_i915_gem_object *obj) ...@@ -198,7 +198,7 @@ static void flush_tlb_invalidate(struct drm_i915_gem_object *obj)
for_each_gt(gt, i915, id) { for_each_gt(gt, i915, id) {
if (!obj->mm.tlb[id]) if (!obj->mm.tlb[id])
return; continue;
intel_gt_invalidate_tlb_full(gt, obj->mm.tlb[id]); intel_gt_invalidate_tlb_full(gt, obj->mm.tlb[id]);
obj->mm.tlb[id] = 0; obj->mm.tlb[id] = 0;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include "gt/intel_gt_requests.h" #include "gt/intel_gt_requests.h"
#include "gt/intel_gt.h"
#include "i915_trace.h" #include "i915_trace.h"
...@@ -119,7 +120,8 @@ i915_gem_shrink(struct i915_gem_ww_ctx *ww, ...@@ -119,7 +120,8 @@ i915_gem_shrink(struct i915_gem_ww_ctx *ww,
intel_wakeref_t wakeref = 0; intel_wakeref_t wakeref = 0;
unsigned long count = 0; unsigned long count = 0;
unsigned long scanned = 0; unsigned long scanned = 0;
int err = 0; int err = 0, i = 0;
struct intel_gt *gt;
/* CHV + VTD workaround use stop_machine(); need to trylock vm->mutex */ /* CHV + VTD workaround use stop_machine(); need to trylock vm->mutex */
bool trylock_vm = !ww && intel_vm_no_concurrent_access_wa(i915); bool trylock_vm = !ww && intel_vm_no_concurrent_access_wa(i915);
...@@ -147,9 +149,11 @@ i915_gem_shrink(struct i915_gem_ww_ctx *ww, ...@@ -147,9 +149,11 @@ i915_gem_shrink(struct i915_gem_ww_ctx *ww,
* what we can do is give them a kick so that we do not keep idle * what we can do is give them a kick so that we do not keep idle
* contexts around longer than is necessary. * contexts around longer than is necessary.
*/ */
if (shrink & I915_SHRINK_ACTIVE) if (shrink & I915_SHRINK_ACTIVE) {
for_each_gt(gt, i915, i)
/* Retire requests to unpin all idle contexts */ /* Retire requests to unpin all idle contexts */
intel_gt_retire_requests(to_gt(i915)); intel_gt_retire_requests(gt);
}
/* /*
* As we may completely rewrite the (un)bound list whilst unbinding * As we may completely rewrite the (un)bound list whilst unbinding
...@@ -389,6 +393,8 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr ...@@ -389,6 +393,8 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr
struct i915_vma *vma, *next; struct i915_vma *vma, *next;
unsigned long freed_pages = 0; unsigned long freed_pages = 0;
intel_wakeref_t wakeref; intel_wakeref_t wakeref;
struct intel_gt *gt;
int i;
with_intel_runtime_pm(&i915->runtime_pm, wakeref) with_intel_runtime_pm(&i915->runtime_pm, wakeref)
freed_pages += i915_gem_shrink(NULL, i915, -1UL, NULL, freed_pages += i915_gem_shrink(NULL, i915, -1UL, NULL,
...@@ -397,9 +403,10 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr ...@@ -397,9 +403,10 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr
I915_SHRINK_VMAPS); I915_SHRINK_VMAPS);
/* We also want to clear any cached iomaps as they wrap vmap */ /* We also want to clear any cached iomaps as they wrap vmap */
mutex_lock(&to_gt(i915)->ggtt->vm.mutex); for_each_gt(gt, i915, i) {
mutex_lock(&gt->ggtt->vm.mutex);
list_for_each_entry_safe(vma, next, list_for_each_entry_safe(vma, next,
&to_gt(i915)->ggtt->vm.bound_list, vm_link) { &gt->ggtt->vm.bound_list, vm_link) {
unsigned long count = i915_vma_size(vma) >> PAGE_SHIFT; unsigned long count = i915_vma_size(vma) >> PAGE_SHIFT;
struct drm_i915_gem_object *obj = vma->obj; struct drm_i915_gem_object *obj = vma->obj;
...@@ -414,7 +421,8 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr ...@@ -414,7 +421,8 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr
i915_gem_object_unlock(obj); i915_gem_object_unlock(obj);
} }
mutex_unlock(&to_gt(i915)->ggtt->vm.mutex); mutex_unlock(&gt->ggtt->vm.mutex);
}
*(unsigned long *)ptr += freed_pages; *(unsigned long *)ptr += freed_pages;
return NOTIFY_DONE; return NOTIFY_DONE;
......
...@@ -170,6 +170,8 @@ intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value) ...@@ -170,6 +170,8 @@ intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value)
#define I915_GEM_HWS_SEQNO 0x40 #define I915_GEM_HWS_SEQNO 0x40
#define I915_GEM_HWS_SEQNO_ADDR (I915_GEM_HWS_SEQNO * sizeof(u32)) #define I915_GEM_HWS_SEQNO_ADDR (I915_GEM_HWS_SEQNO * sizeof(u32))
#define I915_GEM_HWS_MIGRATE (0x42 * sizeof(u32)) #define I915_GEM_HWS_MIGRATE (0x42 * sizeof(u32))
#define I915_GEM_HWS_GGTT_BIND 0x46
#define I915_GEM_HWS_GGTT_BIND_ADDR (I915_GEM_HWS_GGTT_BIND * sizeof(u32))
#define I915_GEM_HWS_PXP 0x60 #define I915_GEM_HWS_PXP 0x60
#define I915_GEM_HWS_PXP_ADDR (I915_GEM_HWS_PXP * sizeof(u32)) #define I915_GEM_HWS_PXP_ADDR (I915_GEM_HWS_PXP * sizeof(u32))
#define I915_GEM_HWS_GSC 0x62 #define I915_GEM_HWS_GSC 0x62
......
...@@ -316,8 +316,7 @@ u32 intel_engine_context_size(struct intel_gt *gt, u8 class) ...@@ -316,8 +316,7 @@ u32 intel_engine_context_size(struct intel_gt *gt, u8 class)
* out in the wash. * out in the wash.
*/ */
cxt_size = intel_uncore_read(uncore, CXT_SIZE) + 1; cxt_size = intel_uncore_read(uncore, CXT_SIZE) + 1;
drm_dbg(&gt->i915->drm, gt_dbg(gt, "graphics_ver = %d CXT_SIZE = %d bytes [0x%08x]\n",
"graphics_ver = %d CXT_SIZE = %d bytes [0x%08x]\n",
GRAPHICS_VER(gt->i915), cxt_size * 64, GRAPHICS_VER(gt->i915), cxt_size * 64,
cxt_size - 1); cxt_size - 1);
return round_up(cxt_size * 64, PAGE_SIZE); return round_up(cxt_size * 64, PAGE_SIZE);
...@@ -788,7 +787,7 @@ static void engine_mask_apply_media_fuses(struct intel_gt *gt) ...@@ -788,7 +787,7 @@ static void engine_mask_apply_media_fuses(struct intel_gt *gt)
if (!(BIT(i) & vdbox_mask)) { if (!(BIT(i) & vdbox_mask)) {
gt->info.engine_mask &= ~BIT(_VCS(i)); gt->info.engine_mask &= ~BIT(_VCS(i));
drm_dbg(&i915->drm, "vcs%u fused off\n", i); gt_dbg(gt, "vcs%u fused off\n", i);
continue; continue;
} }
...@@ -796,8 +795,7 @@ static void engine_mask_apply_media_fuses(struct intel_gt *gt) ...@@ -796,8 +795,7 @@ static void engine_mask_apply_media_fuses(struct intel_gt *gt)
gt->info.vdbox_sfc_access |= BIT(i); gt->info.vdbox_sfc_access |= BIT(i);
logical_vdbox++; logical_vdbox++;
} }
drm_dbg(&i915->drm, "vdbox enable: %04x, instances: %04lx\n", gt_dbg(gt, "vdbox enable: %04x, instances: %04lx\n", vdbox_mask, VDBOX_MASK(gt));
vdbox_mask, VDBOX_MASK(gt));
GEM_BUG_ON(vdbox_mask != VDBOX_MASK(gt)); GEM_BUG_ON(vdbox_mask != VDBOX_MASK(gt));
for (i = 0; i < I915_MAX_VECS; i++) { for (i = 0; i < I915_MAX_VECS; i++) {
...@@ -808,11 +806,10 @@ static void engine_mask_apply_media_fuses(struct intel_gt *gt) ...@@ -808,11 +806,10 @@ static void engine_mask_apply_media_fuses(struct intel_gt *gt)
if (!(BIT(i) & vebox_mask)) { if (!(BIT(i) & vebox_mask)) {
gt->info.engine_mask &= ~BIT(_VECS(i)); gt->info.engine_mask &= ~BIT(_VECS(i));
drm_dbg(&i915->drm, "vecs%u fused off\n", i); gt_dbg(gt, "vecs%u fused off\n", i);
} }
} }
drm_dbg(&i915->drm, "vebox enable: %04x, instances: %04lx\n", gt_dbg(gt, "vebox enable: %04x, instances: %04lx\n", vebox_mask, VEBOX_MASK(gt));
vebox_mask, VEBOX_MASK(gt));
GEM_BUG_ON(vebox_mask != VEBOX_MASK(gt)); GEM_BUG_ON(vebox_mask != VEBOX_MASK(gt));
} }
...@@ -838,7 +835,7 @@ static void engine_mask_apply_compute_fuses(struct intel_gt *gt) ...@@ -838,7 +835,7 @@ static void engine_mask_apply_compute_fuses(struct intel_gt *gt)
*/ */
for_each_clear_bit(i, &ccs_mask, I915_MAX_CCS) { for_each_clear_bit(i, &ccs_mask, I915_MAX_CCS) {
info->engine_mask &= ~BIT(_CCS(i)); info->engine_mask &= ~BIT(_CCS(i));
drm_dbg(&i915->drm, "ccs%u fused off\n", i); gt_dbg(gt, "ccs%u fused off\n", i);
} }
} }
...@@ -866,8 +863,8 @@ static void engine_mask_apply_copy_fuses(struct intel_gt *gt) ...@@ -866,8 +863,8 @@ static void engine_mask_apply_copy_fuses(struct intel_gt *gt)
_BCS(instance)); _BCS(instance));
if (mask & info->engine_mask) { if (mask & info->engine_mask) {
drm_dbg(&i915->drm, "bcs%u fused off\n", instance); gt_dbg(gt, "bcs%u fused off\n", instance);
drm_dbg(&i915->drm, "bcs%u fused off\n", instance + 1); gt_dbg(gt, "bcs%u fused off\n", instance + 1);
info->engine_mask &= ~mask; info->engine_mask &= ~mask;
} }
...@@ -907,8 +904,7 @@ static intel_engine_mask_t init_engine_mask(struct intel_gt *gt) ...@@ -907,8 +904,7 @@ static intel_engine_mask_t init_engine_mask(struct intel_gt *gt)
* submission, which will wake up the GSC power well. * submission, which will wake up the GSC power well.
*/ */
if (__HAS_ENGINE(info->engine_mask, GSC0) && !intel_uc_wants_gsc_uc(&gt->uc)) { if (__HAS_ENGINE(info->engine_mask, GSC0) && !intel_uc_wants_gsc_uc(&gt->uc)) {
drm_notice(&gt->i915->drm, gt_notice(gt, "No GSC FW selected, disabling GSC CS and media C6\n");
"No GSC FW selected, disabling GSC CS and media C6\n");
info->engine_mask &= ~BIT(GSC0); info->engine_mask &= ~BIT(GSC0);
} }
...@@ -1097,8 +1093,7 @@ static int init_status_page(struct intel_engine_cs *engine) ...@@ -1097,8 +1093,7 @@ static int init_status_page(struct intel_engine_cs *engine)
*/ */
obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE); obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE);
if (IS_ERR(obj)) { if (IS_ERR(obj)) {
drm_err(&engine->i915->drm, gt_err(engine->gt, "Failed to allocate status page\n");
"Failed to allocate status page\n");
return PTR_ERR(obj); return PTR_ERR(obj);
} }
...@@ -1418,6 +1413,20 @@ void intel_engine_destroy_pinned_context(struct intel_context *ce) ...@@ -1418,6 +1413,20 @@ void intel_engine_destroy_pinned_context(struct intel_context *ce)
intel_context_put(ce); intel_context_put(ce);
} }
static struct intel_context *
create_ggtt_bind_context(struct intel_engine_cs *engine)
{
static struct lock_class_key kernel;
/*
* MI_UPDATE_GTT can insert up to 511 PTE entries and there could be multiple
* bind requets at a time so get a bigger ring.
*/
return intel_engine_create_pinned_context(engine, engine->gt->vm, SZ_512K,
I915_GEM_HWS_GGTT_BIND_ADDR,
&kernel, "ggtt_bind_context");
}
static struct intel_context * static struct intel_context *
create_kernel_context(struct intel_engine_cs *engine) create_kernel_context(struct intel_engine_cs *engine)
{ {
...@@ -1441,7 +1450,7 @@ create_kernel_context(struct intel_engine_cs *engine) ...@@ -1441,7 +1450,7 @@ create_kernel_context(struct intel_engine_cs *engine)
*/ */
static int engine_init_common(struct intel_engine_cs *engine) static int engine_init_common(struct intel_engine_cs *engine)
{ {
struct intel_context *ce; struct intel_context *ce, *bce = NULL;
int ret; int ret;
engine->set_default_submission(engine); engine->set_default_submission(engine);
...@@ -1457,17 +1466,33 @@ static int engine_init_common(struct intel_engine_cs *engine) ...@@ -1457,17 +1466,33 @@ static int engine_init_common(struct intel_engine_cs *engine)
ce = create_kernel_context(engine); ce = create_kernel_context(engine);
if (IS_ERR(ce)) if (IS_ERR(ce))
return PTR_ERR(ce); return PTR_ERR(ce);
/*
* Create a separate pinned context for GGTT update with blitter engine
* if a platform require such service. MI_UPDATE_GTT works on other
* engines as well but BCS should be less busy engine so pick that for
* GGTT updates.
*/
if (i915_ggtt_require_binder(engine->i915) && engine->id == BCS0) {
bce = create_ggtt_bind_context(engine);
if (IS_ERR(bce)) {
ret = PTR_ERR(bce);
goto err_ce_context;
}
}
ret = measure_breadcrumb_dw(ce); ret = measure_breadcrumb_dw(ce);
if (ret < 0) if (ret < 0)
goto err_context; goto err_bce_context;
engine->emit_fini_breadcrumb_dw = ret; engine->emit_fini_breadcrumb_dw = ret;
engine->kernel_context = ce; engine->kernel_context = ce;
engine->bind_context = bce;
return 0; return 0;
err_context: err_bce_context:
intel_engine_destroy_pinned_context(bce);
err_ce_context:
intel_engine_destroy_pinned_context(ce); intel_engine_destroy_pinned_context(ce);
return ret; return ret;
} }
...@@ -1537,6 +1562,10 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine) ...@@ -1537,6 +1562,10 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine)
if (engine->kernel_context) if (engine->kernel_context)
intel_engine_destroy_pinned_context(engine->kernel_context); intel_engine_destroy_pinned_context(engine->kernel_context);
if (engine->bind_context)
intel_engine_destroy_pinned_context(engine->bind_context);
GEM_BUG_ON(!llist_empty(&engine->barrier_tasks)); GEM_BUG_ON(!llist_empty(&engine->barrier_tasks));
cleanup_status_page(engine); cleanup_status_page(engine);
......
...@@ -402,7 +402,15 @@ struct intel_engine_cs { ...@@ -402,7 +402,15 @@ struct intel_engine_cs {
unsigned long context_tag; unsigned long context_tag;
/*
* The type evolves during initialization, see related comment for
* struct drm_i915_private's uabi_engines member.
*/
union {
struct llist_node uabi_llist;
struct list_head uabi_list;
struct rb_node uabi_node; struct rb_node uabi_node;
};
struct intel_sseu sseu; struct intel_sseu sseu;
...@@ -416,6 +424,9 @@ struct intel_engine_cs { ...@@ -416,6 +424,9 @@ struct intel_engine_cs {
struct llist_head barrier_tasks; struct llist_head barrier_tasks;
struct intel_context *kernel_context; /* pinned */ struct intel_context *kernel_context; /* pinned */
struct intel_context *bind_context; /* pinned, only for BCS0 */
/* mark the bind context's availability status */
bool bind_context_ready;
/** /**
* pinned_contexts_list: List of pinned contexts. This list is only * pinned_contexts_list: List of pinned contexts. This list is only
......
...@@ -38,8 +38,7 @@ intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance) ...@@ -38,8 +38,7 @@ intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance)
void intel_engine_add_user(struct intel_engine_cs *engine) void intel_engine_add_user(struct intel_engine_cs *engine)
{ {
llist_add((struct llist_node *)&engine->uabi_node, llist_add(&engine->uabi_llist, &engine->i915->uabi_engines_llist);
(struct llist_head *)&engine->i915->uabi_engines);
} }
static const u8 uabi_classes[] = { static const u8 uabi_classes[] = {
...@@ -54,9 +53,9 @@ static int engine_cmp(void *priv, const struct list_head *A, ...@@ -54,9 +53,9 @@ static int engine_cmp(void *priv, const struct list_head *A,
const struct list_head *B) const struct list_head *B)
{ {
const struct intel_engine_cs *a = const struct intel_engine_cs *a =
container_of((struct rb_node *)A, typeof(*a), uabi_node); container_of(A, typeof(*a), uabi_list);
const struct intel_engine_cs *b = const struct intel_engine_cs *b =
container_of((struct rb_node *)B, typeof(*b), uabi_node); container_of(B, typeof(*b), uabi_list);
if (uabi_classes[a->class] < uabi_classes[b->class]) if (uabi_classes[a->class] < uabi_classes[b->class])
return -1; return -1;
...@@ -73,7 +72,7 @@ static int engine_cmp(void *priv, const struct list_head *A, ...@@ -73,7 +72,7 @@ static int engine_cmp(void *priv, const struct list_head *A,
static struct llist_node *get_engines(struct drm_i915_private *i915) static struct llist_node *get_engines(struct drm_i915_private *i915)
{ {
return llist_del_all((struct llist_head *)&i915->uabi_engines); return llist_del_all(&i915->uabi_engines_llist);
} }
static void sort_engines(struct drm_i915_private *i915, static void sort_engines(struct drm_i915_private *i915,
...@@ -83,9 +82,8 @@ static void sort_engines(struct drm_i915_private *i915, ...@@ -83,9 +82,8 @@ static void sort_engines(struct drm_i915_private *i915,
llist_for_each_safe(pos, next, get_engines(i915)) { llist_for_each_safe(pos, next, get_engines(i915)) {
struct intel_engine_cs *engine = struct intel_engine_cs *engine =
container_of((struct rb_node *)pos, typeof(*engine), container_of(pos, typeof(*engine), uabi_llist);
uabi_node); list_add(&engine->uabi_list, engines);
list_add((struct list_head *)&engine->uabi_node, engines);
} }
list_sort(NULL, engines, engine_cmp); list_sort(NULL, engines, engine_cmp);
} }
...@@ -213,8 +211,7 @@ void intel_engines_driver_register(struct drm_i915_private *i915) ...@@ -213,8 +211,7 @@ void intel_engines_driver_register(struct drm_i915_private *i915)
p = &i915->uabi_engines.rb_node; p = &i915->uabi_engines.rb_node;
list_for_each_safe(it, next, &engines) { list_for_each_safe(it, next, &engines) {
struct intel_engine_cs *engine = struct intel_engine_cs *engine =
container_of((struct rb_node *)it, typeof(*engine), container_of(it, typeof(*engine), uabi_list);
uabi_node);
if (intel_gt_has_unrecoverable_error(engine->gt)) if (intel_gt_has_unrecoverable_error(engine->gt))
continue; /* ignore incomplete engines */ continue; /* ignore incomplete engines */
......
...@@ -15,18 +15,23 @@ ...@@ -15,18 +15,23 @@
#include "display/intel_display.h" #include "display/intel_display.h"
#include "gem/i915_gem_lmem.h" #include "gem/i915_gem_lmem.h"
#include "intel_context.h"
#include "intel_ggtt_gmch.h" #include "intel_ggtt_gmch.h"
#include "intel_gpu_commands.h"
#include "intel_gt.h" #include "intel_gt.h"
#include "intel_gt_regs.h" #include "intel_gt_regs.h"
#include "intel_pci_config.h" #include "intel_pci_config.h"
#include "intel_ring.h"
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_pci.h" #include "i915_pci.h"
#include "i915_request.h"
#include "i915_scatterlist.h" #include "i915_scatterlist.h"
#include "i915_utils.h" #include "i915_utils.h"
#include "i915_vgpu.h" #include "i915_vgpu.h"
#include "intel_gtt.h" #include "intel_gtt.h"
#include "gen8_ppgtt.h" #include "gen8_ppgtt.h"
#include "intel_engine_pm.h"
static void i915_ggtt_color_adjust(const struct drm_mm_node *node, static void i915_ggtt_color_adjust(const struct drm_mm_node *node,
unsigned long color, unsigned long color,
...@@ -252,6 +257,145 @@ u64 gen8_ggtt_pte_encode(dma_addr_t addr, ...@@ -252,6 +257,145 @@ u64 gen8_ggtt_pte_encode(dma_addr_t addr,
return pte; return pte;
} }
static bool should_update_ggtt_with_bind(struct i915_ggtt *ggtt)
{
struct intel_gt *gt = ggtt->vm.gt;
return intel_gt_is_bind_context_ready(gt);
}
static struct intel_context *gen8_ggtt_bind_get_ce(struct i915_ggtt *ggtt)
{
struct intel_context *ce;
struct intel_gt *gt = ggtt->vm.gt;
if (intel_gt_is_wedged(gt))
return NULL;
ce = gt->engine[BCS0]->bind_context;
GEM_BUG_ON(!ce);
/*
* If the GT is not awake already at this stage then fallback
* to pci based GGTT update otherwise __intel_wakeref_get_first()
* would conflict with fs_reclaim trying to allocate memory while
* doing rpm_resume().
*/
if (!intel_gt_pm_get_if_awake(gt))
return NULL;
intel_engine_pm_get(ce->engine);
return ce;
}
static void gen8_ggtt_bind_put_ce(struct intel_context *ce)
{
intel_engine_pm_put(ce->engine);
intel_gt_pm_put(ce->engine->gt);
}
static bool gen8_ggtt_bind_ptes(struct i915_ggtt *ggtt, u32 offset,
struct sg_table *pages, u32 num_entries,
const gen8_pte_t pte)
{
struct i915_sched_attr attr = {};
struct intel_gt *gt = ggtt->vm.gt;
const gen8_pte_t scratch_pte = ggtt->vm.scratch[0]->encode;
struct sgt_iter iter;
struct i915_request *rq;
struct intel_context *ce;
u32 *cs;
if (!num_entries)
return true;
ce = gen8_ggtt_bind_get_ce(ggtt);
if (!ce)
return false;
if (pages)
iter = __sgt_iter(pages->sgl, true);
while (num_entries) {
int count = 0;
dma_addr_t addr;
/*
* MI_UPDATE_GTT can update 512 entries in a single command but
* that end up with engine reset, 511 works.
*/
u32 n_ptes = min_t(u32, 511, num_entries);
if (mutex_lock_interruptible(&ce->timeline->mutex))
goto put_ce;
intel_context_enter(ce);
rq = __i915_request_create(ce, GFP_NOWAIT | GFP_ATOMIC);
intel_context_exit(ce);
if (IS_ERR(rq)) {
GT_TRACE(gt, "Failed to get bind request\n");
mutex_unlock(&ce->timeline->mutex);
goto put_ce;
}
cs = intel_ring_begin(rq, 2 * n_ptes + 2);
if (IS_ERR(cs)) {
GT_TRACE(gt, "Failed to ring space for GGTT bind\n");
i915_request_set_error_once(rq, PTR_ERR(cs));
/* once a request is created, it must be queued */
goto queue_err_rq;
}
*cs++ = MI_UPDATE_GTT | (2 * n_ptes);
*cs++ = offset << 12;
if (pages) {
for_each_sgt_daddr_next(addr, iter) {
if (count == n_ptes)
break;
*cs++ = lower_32_bits(pte | addr);
*cs++ = upper_32_bits(pte | addr);
count++;
}
/* fill remaining with scratch pte, if any */
if (count < n_ptes) {
memset64((u64 *)cs, scratch_pte,
n_ptes - count);
cs += (n_ptes - count) * 2;
}
} else {
memset64((u64 *)cs, pte, n_ptes);
cs += n_ptes * 2;
}
intel_ring_advance(rq, cs);
queue_err_rq:
i915_request_get(rq);
__i915_request_commit(rq);
__i915_request_queue(rq, &attr);
mutex_unlock(&ce->timeline->mutex);
/* This will break if the request is complete or after engine reset */
i915_request_wait(rq, 0, MAX_SCHEDULE_TIMEOUT);
if (rq->fence.error)
goto err_rq;
i915_request_put(rq);
num_entries -= n_ptes;
offset += n_ptes;
}
gen8_ggtt_bind_put_ce(ce);
return true;
err_rq:
i915_request_put(rq);
put_ce:
gen8_ggtt_bind_put_ce(ce);
return false;
}
static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte) static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte)
{ {
writeq(pte, addr); writeq(pte, addr);
...@@ -272,6 +416,21 @@ static void gen8_ggtt_insert_page(struct i915_address_space *vm, ...@@ -272,6 +416,21 @@ static void gen8_ggtt_insert_page(struct i915_address_space *vm,
ggtt->invalidate(ggtt); ggtt->invalidate(ggtt);
} }
static void gen8_ggtt_insert_page_bind(struct i915_address_space *vm,
dma_addr_t addr, u64 offset,
unsigned int pat_index, u32 flags)
{
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
gen8_pte_t pte;
pte = ggtt->vm.pte_encode(addr, pat_index, flags);
if (should_update_ggtt_with_bind(i915_vm_to_ggtt(vm)) &&
gen8_ggtt_bind_ptes(ggtt, offset, NULL, 1, pte))
return ggtt->invalidate(ggtt);
gen8_ggtt_insert_page(vm, addr, offset, pat_index, flags);
}
static void gen8_ggtt_insert_entries(struct i915_address_space *vm, static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
struct i915_vma_resource *vma_res, struct i915_vma_resource *vma_res,
unsigned int pat_index, unsigned int pat_index,
...@@ -311,6 +470,50 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, ...@@ -311,6 +470,50 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
ggtt->invalidate(ggtt); ggtt->invalidate(ggtt);
} }
static bool __gen8_ggtt_insert_entries_bind(struct i915_address_space *vm,
struct i915_vma_resource *vma_res,
unsigned int pat_index, u32 flags)
{
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
gen8_pte_t scratch_pte = vm->scratch[0]->encode;
gen8_pte_t pte_encode;
u64 start, end;
pte_encode = ggtt->vm.pte_encode(0, pat_index, flags);
start = (vma_res->start - vma_res->guard) / I915_GTT_PAGE_SIZE;
end = start + vma_res->guard / I915_GTT_PAGE_SIZE;
if (!gen8_ggtt_bind_ptes(ggtt, start, NULL, end - start, scratch_pte))
goto err;
start = end;
end += (vma_res->node_size + vma_res->guard) / I915_GTT_PAGE_SIZE;
if (!gen8_ggtt_bind_ptes(ggtt, start, vma_res->bi.pages,
vma_res->node_size / I915_GTT_PAGE_SIZE, pte_encode))
goto err;
start += vma_res->node_size / I915_GTT_PAGE_SIZE;
if (!gen8_ggtt_bind_ptes(ggtt, start, NULL, end - start, scratch_pte))
goto err;
return true;
err:
return false;
}
static void gen8_ggtt_insert_entries_bind(struct i915_address_space *vm,
struct i915_vma_resource *vma_res,
unsigned int pat_index, u32 flags)
{
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
if (should_update_ggtt_with_bind(i915_vm_to_ggtt(vm)) &&
__gen8_ggtt_insert_entries_bind(vm, vma_res, pat_index, flags))
return ggtt->invalidate(ggtt);
gen8_ggtt_insert_entries(vm, vma_res, pat_index, flags);
}
static void gen8_ggtt_clear_range(struct i915_address_space *vm, static void gen8_ggtt_clear_range(struct i915_address_space *vm,
u64 start, u64 length) u64 start, u64 length)
{ {
...@@ -332,6 +535,27 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm, ...@@ -332,6 +535,27 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,
gen8_set_pte(&gtt_base[i], scratch_pte); gen8_set_pte(&gtt_base[i], scratch_pte);
} }
static void gen8_ggtt_scratch_range_bind(struct i915_address_space *vm,
u64 start, u64 length)
{
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
unsigned int first_entry = start / I915_GTT_PAGE_SIZE;
unsigned int num_entries = length / I915_GTT_PAGE_SIZE;
const gen8_pte_t scratch_pte = vm->scratch[0]->encode;
const int max_entries = ggtt_total_entries(ggtt) - first_entry;
if (WARN(num_entries > max_entries,
"First entry = %d; Num entries = %d (max=%d)\n",
first_entry, num_entries, max_entries))
num_entries = max_entries;
if (should_update_ggtt_with_bind(ggtt) && gen8_ggtt_bind_ptes(ggtt, first_entry,
NULL, num_entries, scratch_pte))
return ggtt->invalidate(ggtt);
gen8_ggtt_clear_range(vm, start, length);
}
static void gen6_ggtt_insert_page(struct i915_address_space *vm, static void gen6_ggtt_insert_page(struct i915_address_space *vm,
dma_addr_t addr, dma_addr_t addr,
u64 offset, u64 offset,
...@@ -1008,6 +1232,17 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt) ...@@ -1008,6 +1232,17 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND; I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND;
} }
if (i915_ggtt_require_binder(i915)) {
ggtt->vm.scratch_range = gen8_ggtt_scratch_range_bind;
ggtt->vm.insert_page = gen8_ggtt_insert_page_bind;
ggtt->vm.insert_entries = gen8_ggtt_insert_entries_bind;
/*
* On GPU is hung, we might bind VMAs for error capture.
* Fallback to CPU GGTT updates in that case.
*/
ggtt->vm.raw_insert_page = gen8_ggtt_insert_page;
}
if (intel_uc_wants_guc(&ggtt->vm.gt->uc)) if (intel_uc_wants_guc(&ggtt->vm.gt->uc))
ggtt->invalidate = guc_ggtt_invalidate; ggtt->invalidate = guc_ggtt_invalidate;
else else
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "gem/i915_gem_region.h" #include "gem/i915_gem_region.h"
#include "gt/intel_gsc.h" #include "gt/intel_gsc.h"
#include "gt/intel_gt.h" #include "gt/intel_gt.h"
#include "gt/intel_gt_print.h"
#define GSC_BAR_LENGTH 0x00000FFC #define GSC_BAR_LENGTH 0x00000FFC
...@@ -49,13 +50,13 @@ gsc_ext_om_alloc(struct intel_gsc *gsc, struct intel_gsc_intf *intf, size_t size ...@@ -49,13 +50,13 @@ gsc_ext_om_alloc(struct intel_gsc *gsc, struct intel_gsc_intf *intf, size_t size
I915_BO_ALLOC_CONTIGUOUS | I915_BO_ALLOC_CONTIGUOUS |
I915_BO_ALLOC_CPU_CLEAR); I915_BO_ALLOC_CPU_CLEAR);
if (IS_ERR(obj)) { if (IS_ERR(obj)) {
drm_err(&gt->i915->drm, "Failed to allocate gsc memory\n"); gt_err(gt, "Failed to allocate gsc memory\n");
return PTR_ERR(obj); return PTR_ERR(obj);
} }
err = i915_gem_object_pin_pages_unlocked(obj); err = i915_gem_object_pin_pages_unlocked(obj);
if (err) { if (err) {
drm_err(&gt->i915->drm, "Failed to pin pages for gsc memory\n"); gt_err(gt, "Failed to pin pages for gsc memory\n");
goto out_put; goto out_put;
} }
...@@ -286,12 +287,12 @@ static void gsc_irq_handler(struct intel_gt *gt, unsigned int intf_id) ...@@ -286,12 +287,12 @@ static void gsc_irq_handler(struct intel_gt *gt, unsigned int intf_id)
int ret; int ret;
if (intf_id >= INTEL_GSC_NUM_INTERFACES) { if (intf_id >= INTEL_GSC_NUM_INTERFACES) {
drm_warn_once(&gt->i915->drm, "GSC irq: intf_id %d is out of range", intf_id); gt_warn_once(gt, "GSC irq: intf_id %d is out of range", intf_id);
return; return;
} }
if (!HAS_HECI_GSC(gt->i915)) { if (!HAS_HECI_GSC(gt->i915)) {
drm_warn_once(&gt->i915->drm, "GSC irq: not supported"); gt_warn_once(gt, "GSC irq: not supported");
return; return;
} }
...@@ -300,7 +301,7 @@ static void gsc_irq_handler(struct intel_gt *gt, unsigned int intf_id) ...@@ -300,7 +301,7 @@ static void gsc_irq_handler(struct intel_gt *gt, unsigned int intf_id)
ret = generic_handle_irq(gt->gsc.intf[intf_id].irq); ret = generic_handle_irq(gt->gsc.intf[intf_id].irq);
if (ret) if (ret)
drm_err_ratelimited(&gt->i915->drm, "error handling GSC irq: %d\n", ret); gt_err_ratelimited(gt, "error handling GSC irq: %d\n", ret);
} }
void intel_gsc_irq_handler(struct intel_gt *gt, u32 iir) void intel_gsc_irq_handler(struct intel_gt *gt, u32 iir)
......
...@@ -268,10 +268,21 @@ intel_gt_clear_error_registers(struct intel_gt *gt, ...@@ -268,10 +268,21 @@ intel_gt_clear_error_registers(struct intel_gt *gt,
I915_MASTER_ERROR_INTERRUPT); I915_MASTER_ERROR_INTERRUPT);
} }
if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) { /*
* For the media GT, this ring fault register is not replicated,
* so don't do multicast/replicated register read/write operation on it.
*/
if (MEDIA_VER(i915) >= 13 && gt->type == GT_MEDIA) {
intel_uncore_rmw(uncore, XELPMP_RING_FAULT_REG,
RING_FAULT_VALID, 0);
intel_uncore_posting_read(uncore,
XELPMP_RING_FAULT_REG);
} else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) {
intel_gt_mcr_multicast_rmw(gt, XEHP_RING_FAULT_REG, intel_gt_mcr_multicast_rmw(gt, XEHP_RING_FAULT_REG,
RING_FAULT_VALID, 0); RING_FAULT_VALID, 0);
intel_gt_mcr_read_any(gt, XEHP_RING_FAULT_REG); intel_gt_mcr_read_any(gt, XEHP_RING_FAULT_REG);
} else if (GRAPHICS_VER(i915) >= 12) { } else if (GRAPHICS_VER(i915) >= 12) {
intel_uncore_rmw(uncore, GEN12_RING_FAULT_REG, RING_FAULT_VALID, 0); intel_uncore_rmw(uncore, GEN12_RING_FAULT_REG, RING_FAULT_VALID, 0);
intel_uncore_posting_read(uncore, GEN12_RING_FAULT_REG); intel_uncore_posting_read(uncore, GEN12_RING_FAULT_REG);
...@@ -1028,3 +1039,52 @@ bool intel_gt_needs_wa_22016122933(struct intel_gt *gt) ...@@ -1028,3 +1039,52 @@ bool intel_gt_needs_wa_22016122933(struct intel_gt *gt)
{ {
return MEDIA_VER_FULL(gt->i915) == IP_VER(13, 0) && gt->type == GT_MEDIA; return MEDIA_VER_FULL(gt->i915) == IP_VER(13, 0) && gt->type == GT_MEDIA;
} }
static void __intel_gt_bind_context_set_ready(struct intel_gt *gt, bool ready)
{
struct intel_engine_cs *engine = gt->engine[BCS0];
if (engine && engine->bind_context)
engine->bind_context_ready = ready;
}
/**
* intel_gt_bind_context_set_ready - Set the context binding as ready
*
* @gt: GT structure
*
* This function marks the binder context as ready.
*/
void intel_gt_bind_context_set_ready(struct intel_gt *gt)
{
__intel_gt_bind_context_set_ready(gt, true);
}
/**
* intel_gt_bind_context_set_unready - Set the context binding as ready
* @gt: GT structure
*
* This function marks the binder context as not ready.
*/
void intel_gt_bind_context_set_unready(struct intel_gt *gt)
{
__intel_gt_bind_context_set_ready(gt, false);
}
/**
* intel_gt_is_bind_context_ready - Check if context binding is ready
*
* @gt: GT structure
*
* This function returns binder context's ready status.
*/
bool intel_gt_is_bind_context_ready(struct intel_gt *gt)
{
struct intel_engine_cs *engine = gt->engine[BCS0];
if (engine)
return engine->bind_context_ready;
return false;
}
...@@ -176,4 +176,7 @@ enum i915_map_type intel_gt_coherent_map_type(struct intel_gt *gt, ...@@ -176,4 +176,7 @@ enum i915_map_type intel_gt_coherent_map_type(struct intel_gt *gt,
struct drm_i915_gem_object *obj, struct drm_i915_gem_object *obj,
bool always_coherent); bool always_coherent);
void intel_gt_bind_context_set_ready(struct intel_gt *gt);
void intel_gt_bind_context_set_unready(struct intel_gt *gt);
bool intel_gt_is_bind_context_ready(struct intel_gt *gt);
#endif /* __INTEL_GT_H__ */ #endif /* __INTEL_GT_H__ */
...@@ -419,6 +419,28 @@ void intel_gt_mcr_unlock(struct intel_gt *gt, unsigned long flags) ...@@ -419,6 +419,28 @@ void intel_gt_mcr_unlock(struct intel_gt *gt, unsigned long flags)
intel_uncore_write_fw(gt->uncore, MTL_STEER_SEMAPHORE, 0x1); intel_uncore_write_fw(gt->uncore, MTL_STEER_SEMAPHORE, 0x1);
} }
/**
* intel_gt_mcr_lock_sanitize - Sanitize MCR steering lock
* @gt: GT structure
*
* This will be used to sanitize the initial status of the hardware lock
* during driver load and resume since there won't be any concurrent access
* from other agents at those times, but it's possible that boot firmware
* may have left the lock in a bad state.
*
*/
void intel_gt_mcr_lock_sanitize(struct intel_gt *gt)
{
/*
* This gets called at load/resume time, so we shouldn't be
* racing with other driver threads grabbing the mcr lock.
*/
lockdep_assert_not_held(&gt->mcr_lock);
if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 70))
intel_uncore_write_fw(gt->uncore, MTL_STEER_SEMAPHORE, 0x1);
}
/** /**
* intel_gt_mcr_read - read a specific instance of an MCR register * intel_gt_mcr_read - read a specific instance of an MCR register
* @gt: GT structure * @gt: GT structure
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
void intel_gt_mcr_init(struct intel_gt *gt); void intel_gt_mcr_init(struct intel_gt *gt);
void intel_gt_mcr_lock(struct intel_gt *gt, unsigned long *flags); void intel_gt_mcr_lock(struct intel_gt *gt, unsigned long *flags);
void intel_gt_mcr_unlock(struct intel_gt *gt, unsigned long flags); void intel_gt_mcr_unlock(struct intel_gt *gt, unsigned long flags);
void intel_gt_mcr_lock_sanitize(struct intel_gt *gt);
u32 intel_gt_mcr_read(struct intel_gt *gt, u32 intel_gt_mcr_read(struct intel_gt *gt,
i915_mcr_reg_t reg, i915_mcr_reg_t reg,
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "intel_engine_pm.h" #include "intel_engine_pm.h"
#include "intel_gt.h" #include "intel_gt.h"
#include "intel_gt_clock_utils.h" #include "intel_gt_clock_utils.h"
#include "intel_gt_mcr.h"
#include "intel_gt_pm.h" #include "intel_gt_pm.h"
#include "intel_gt_print.h" #include "intel_gt_print.h"
#include "intel_gt_requests.h" #include "intel_gt_requests.h"
...@@ -216,6 +217,21 @@ void intel_gt_pm_fini(struct intel_gt *gt) ...@@ -216,6 +217,21 @@ void intel_gt_pm_fini(struct intel_gt *gt)
intel_rc6_fini(&gt->rc6); intel_rc6_fini(&gt->rc6);
} }
void intel_gt_resume_early(struct intel_gt *gt)
{
/*
* Sanitize steer semaphores during driver resume. This is necessary
* to address observed cases of steer semaphores being
* held after a suspend operation. Confirmation from the hardware team
* assures the safety of this operation, as no lock acquisitions
* by other agents occur during driver load/resume process.
*/
intel_gt_mcr_lock_sanitize(gt);
intel_uncore_resume_early(gt->uncore);
intel_gt_check_and_clear_faults(gt);
}
int intel_gt_resume(struct intel_gt *gt) int intel_gt_resume(struct intel_gt *gt)
{ {
struct intel_engine_cs *engine; struct intel_engine_cs *engine;
...@@ -280,6 +296,7 @@ int intel_gt_resume(struct intel_gt *gt) ...@@ -280,6 +296,7 @@ int intel_gt_resume(struct intel_gt *gt)
out_fw: out_fw:
intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL); intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL);
intel_gt_pm_put(gt); intel_gt_pm_put(gt);
intel_gt_bind_context_set_ready(gt);
return err; return err;
err_wedged: err_wedged:
...@@ -306,6 +323,7 @@ static void wait_for_suspend(struct intel_gt *gt) ...@@ -306,6 +323,7 @@ static void wait_for_suspend(struct intel_gt *gt)
void intel_gt_suspend_prepare(struct intel_gt *gt) void intel_gt_suspend_prepare(struct intel_gt *gt)
{ {
intel_gt_bind_context_set_unready(gt);
user_forcewake(gt, true); user_forcewake(gt, true);
wait_for_suspend(gt); wait_for_suspend(gt);
} }
...@@ -359,6 +377,7 @@ void intel_gt_suspend_late(struct intel_gt *gt) ...@@ -359,6 +377,7 @@ void intel_gt_suspend_late(struct intel_gt *gt)
void intel_gt_runtime_suspend(struct intel_gt *gt) void intel_gt_runtime_suspend(struct intel_gt *gt)
{ {
intel_gt_bind_context_set_unready(gt);
intel_uc_runtime_suspend(&gt->uc); intel_uc_runtime_suspend(&gt->uc);
GT_TRACE(gt, "\n"); GT_TRACE(gt, "\n");
...@@ -376,6 +395,7 @@ int intel_gt_runtime_resume(struct intel_gt *gt) ...@@ -376,6 +395,7 @@ int intel_gt_runtime_resume(struct intel_gt *gt)
if (ret) if (ret)
return ret; return ret;
intel_gt_bind_context_set_ready(gt);
return 0; return 0;
} }
......
...@@ -78,6 +78,7 @@ void intel_gt_pm_fini(struct intel_gt *gt); ...@@ -78,6 +78,7 @@ void intel_gt_pm_fini(struct intel_gt *gt);
void intel_gt_suspend_prepare(struct intel_gt *gt); void intel_gt_suspend_prepare(struct intel_gt *gt);
void intel_gt_suspend_late(struct intel_gt *gt); void intel_gt_suspend_late(struct intel_gt *gt);
int intel_gt_resume(struct intel_gt *gt); int intel_gt_resume(struct intel_gt *gt);
void intel_gt_resume_early(struct intel_gt *gt);
void intel_gt_runtime_suspend(struct intel_gt *gt); void intel_gt_runtime_suspend(struct intel_gt *gt);
int intel_gt_runtime_resume(struct intel_gt *gt); int intel_gt_runtime_resume(struct intel_gt *gt);
......
...@@ -16,6 +16,9 @@ ...@@ -16,6 +16,9 @@
#define gt_warn(_gt, _fmt, ...) \ #define gt_warn(_gt, _fmt, ...) \
drm_warn(&(_gt)->i915->drm, "GT%u: " _fmt, (_gt)->info.id, ##__VA_ARGS__) drm_warn(&(_gt)->i915->drm, "GT%u: " _fmt, (_gt)->info.id, ##__VA_ARGS__)
#define gt_warn_once(_gt, _fmt, ...) \
drm_warn_once(&(_gt)->i915->drm, "GT%u: " _fmt, (_gt)->info.id, ##__VA_ARGS__)
#define gt_notice(_gt, _fmt, ...) \ #define gt_notice(_gt, _fmt, ...) \
drm_notice(&(_gt)->i915->drm, "GT%u: " _fmt, (_gt)->info.id, ##__VA_ARGS__) drm_notice(&(_gt)->i915->drm, "GT%u: " _fmt, (_gt)->info.id, ##__VA_ARGS__)
......
...@@ -1084,6 +1084,7 @@ ...@@ -1084,6 +1084,7 @@
#define GEN12_RING_FAULT_REG _MMIO(0xcec4) #define GEN12_RING_FAULT_REG _MMIO(0xcec4)
#define XEHP_RING_FAULT_REG MCR_REG(0xcec4) #define XEHP_RING_FAULT_REG MCR_REG(0xcec4)
#define XELPMP_RING_FAULT_REG _MMIO(0xcec4)
#define GEN8_RING_FAULT_ENGINE_ID(x) (((x) >> 12) & 0x7) #define GEN8_RING_FAULT_ENGINE_ID(x) (((x) >> 12) & 0x7)
#define RING_FAULT_GTTSEL_MASK (1 << 11) #define RING_FAULT_GTTSEL_MASK (1 << 11)
#define RING_FAULT_SRCID(x) (((x) >> 3) & 0xff) #define RING_FAULT_SRCID(x) (((x) >> 3) & 0xff)
......
...@@ -21,6 +21,11 @@ ...@@ -21,6 +21,11 @@
#include "intel_gt_regs.h" #include "intel_gt_regs.h"
#include "intel_gtt.h" #include "intel_gtt.h"
bool i915_ggtt_require_binder(struct drm_i915_private *i915)
{
/* Wa_13010847436 & Wa_14019519902 */
return MEDIA_VER_FULL(i915) == IP_VER(13, 0);
}
static bool intel_ggtt_update_needs_vtd_wa(struct drm_i915_private *i915) static bool intel_ggtt_update_needs_vtd_wa(struct drm_i915_private *i915)
{ {
......
...@@ -171,6 +171,9 @@ struct intel_gt; ...@@ -171,6 +171,9 @@ struct intel_gt;
#define for_each_sgt_daddr(__dp, __iter, __sgt) \ #define for_each_sgt_daddr(__dp, __iter, __sgt) \
__for_each_sgt_daddr(__dp, __iter, __sgt, I915_GTT_PAGE_SIZE) __for_each_sgt_daddr(__dp, __iter, __sgt, I915_GTT_PAGE_SIZE)
#define for_each_sgt_daddr_next(__dp, __iter) \
__for_each_daddr_next(__dp, __iter, I915_GTT_PAGE_SIZE)
struct i915_page_table { struct i915_page_table {
struct drm_i915_gem_object *base; struct drm_i915_gem_object *base;
union { union {
...@@ -688,4 +691,6 @@ static inline struct sgt_dma { ...@@ -688,4 +691,6 @@ static inline struct sgt_dma {
return (struct sgt_dma){ sg, addr, addr + sg_dma_len(sg) }; return (struct sgt_dma){ sg, addr, addr + sg_dma_len(sg) };
} }
bool i915_ggtt_require_binder(struct drm_i915_private *i915);
#endif #endif
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "intel_engine_regs.h" #include "intel_engine_regs.h"
#include "intel_gt.h" #include "intel_gt.h"
#include "intel_gt_pm.h" #include "intel_gt_pm.h"
#include "intel_gt_print.h"
#include "intel_gt_requests.h" #include "intel_gt_requests.h"
#include "intel_mchbar_regs.h" #include "intel_mchbar_regs.h"
#include "intel_pci_config.h" #include "intel_pci_config.h"
...@@ -592,7 +593,7 @@ static int gen8_engine_reset_prepare(struct intel_engine_cs *engine) ...@@ -592,7 +593,7 @@ static int gen8_engine_reset_prepare(struct intel_engine_cs *engine)
ret = __intel_wait_for_register_fw(uncore, reg, mask, ack, ret = __intel_wait_for_register_fw(uncore, reg, mask, ack,
700, 0, NULL); 700, 0, NULL);
if (ret) if (ret)
drm_err(&engine->i915->drm, gt_err(engine->gt,
"%s reset request timed out: {request: %08x, RESET_CTL: %08x}\n", "%s reset request timed out: {request: %08x, RESET_CTL: %08x}\n",
engine->name, request, engine->name, request,
intel_uncore_read_fw(uncore, reg)); intel_uncore_read_fw(uncore, reg));
...@@ -1199,17 +1200,16 @@ void intel_gt_reset(struct intel_gt *gt, ...@@ -1199,17 +1200,16 @@ void intel_gt_reset(struct intel_gt *gt,
goto unlock; goto unlock;
if (reason) if (reason)
drm_notice(&gt->i915->drm, gt_notice(gt, "Resetting chip for %s\n", reason);
"Resetting chip for %s\n", reason);
atomic_inc(&gt->i915->gpu_error.reset_count); atomic_inc(&gt->i915->gpu_error.reset_count);
awake = reset_prepare(gt); awake = reset_prepare(gt);
if (!intel_has_gpu_reset(gt)) { if (!intel_has_gpu_reset(gt)) {
if (gt->i915->params.reset) if (gt->i915->params.reset)
drm_err(&gt->i915->drm, "GPU reset not supported\n"); gt_err(gt, "GPU reset not supported\n");
else else
drm_dbg(&gt->i915->drm, "GPU reset disabled\n"); gt_dbg(gt, "GPU reset disabled\n");
goto error; goto error;
} }
...@@ -1217,7 +1217,7 @@ void intel_gt_reset(struct intel_gt *gt, ...@@ -1217,7 +1217,7 @@ void intel_gt_reset(struct intel_gt *gt,
intel_runtime_pm_disable_interrupts(gt->i915); intel_runtime_pm_disable_interrupts(gt->i915);
if (do_reset(gt, stalled_mask)) { if (do_reset(gt, stalled_mask)) {
drm_err(&gt->i915->drm, "Failed to reset chip\n"); gt_err(gt, "Failed to reset chip\n");
goto taint; goto taint;
} }
...@@ -1236,9 +1236,7 @@ void intel_gt_reset(struct intel_gt *gt, ...@@ -1236,9 +1236,7 @@ void intel_gt_reset(struct intel_gt *gt,
*/ */
ret = intel_gt_init_hw(gt); ret = intel_gt_init_hw(gt);
if (ret) { if (ret) {
drm_err(&gt->i915->drm, gt_err(gt, "Failed to initialise HW following reset (%d)\n", ret);
"Failed to initialise HW following reset (%d)\n",
ret);
goto taint; goto taint;
} }
...@@ -1605,9 +1603,7 @@ static void intel_wedge_me(struct work_struct *work) ...@@ -1605,9 +1603,7 @@ static void intel_wedge_me(struct work_struct *work)
{ {
struct intel_wedge_me *w = container_of(work, typeof(*w), work.work); struct intel_wedge_me *w = container_of(work, typeof(*w), work.work);
drm_err(&w->gt->i915->drm, gt_err(w->gt, "%s timed out, cancelling all in-flight rendering.\n", w->name);
"%s timed out, cancelling all in-flight rendering.\n",
w->name);
intel_gt_set_wedged(w->gt); intel_gt_set_wedged(w->gt);
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "intel_gpu_commands.h" #include "intel_gpu_commands.h"
#include "intel_gt.h" #include "intel_gt.h"
#include "intel_gt_mcr.h" #include "intel_gt_mcr.h"
#include "intel_gt_print.h"
#include "intel_gt_regs.h" #include "intel_gt_regs.h"
#include "intel_ring.h" #include "intel_ring.h"
#include "intel_workarounds.h" #include "intel_workarounds.h"
...@@ -119,7 +120,7 @@ static void wa_init_finish(struct i915_wa_list *wal) ...@@ -119,7 +120,7 @@ static void wa_init_finish(struct i915_wa_list *wal)
if (!wal->count) if (!wal->count)
return; return;
drm_dbg(&wal->gt->i915->drm, "Initialized %u %s workarounds on %s\n", gt_dbg(wal->gt, "Initialized %u %s workarounds on %s\n",
wal->wa_count, wal->name, wal->engine_name); wal->wa_count, wal->name, wal->engine_name);
} }
...@@ -1780,7 +1781,7 @@ wa_verify(struct intel_gt *gt, const struct i915_wa *wa, u32 cur, ...@@ -1780,7 +1781,7 @@ wa_verify(struct intel_gt *gt, const struct i915_wa *wa, u32 cur,
const char *name, const char *from) const char *name, const char *from)
{ {
if ((cur ^ wa->set) & wa->read) { if ((cur ^ wa->set) & wa->read) {
drm_err(&gt->i915->drm, gt_err(gt,
"%s workaround lost on %s! (reg[%x]=0x%x, relevant bits were 0x%x vs expected 0x%x)\n", "%s workaround lost on %s! (reg[%x]=0x%x, relevant bits were 0x%x vs expected 0x%x)\n",
name, from, i915_mmio_reg_offset(wa->reg), name, from, i915_mmio_reg_offset(wa->reg),
cur, cur & wa->read, wa->set & wa->read); cur, cur & wa->read, wa->set & wa->read);
......
...@@ -68,8 +68,7 @@ static void gsc_work(struct work_struct *work) ...@@ -68,8 +68,7 @@ static void gsc_work(struct work_struct *work)
* A proxy failure right after firmware load means the proxy-init * A proxy failure right after firmware load means the proxy-init
* step has failed so mark GSC as not usable after this * step has failed so mark GSC as not usable after this
*/ */
drm_err(&gt->i915->drm, gt_err(gt, "GSC proxy handler failed to init\n");
"GSC proxy handler failed to init\n");
intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_LOAD_FAIL); intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_LOAD_FAIL);
} }
goto out_put; goto out_put;
...@@ -83,11 +82,10 @@ static void gsc_work(struct work_struct *work) ...@@ -83,11 +82,10 @@ static void gsc_work(struct work_struct *work)
* status register to check if the proxy init was actually successful * status register to check if the proxy init was actually successful
*/ */
if (intel_gsc_uc_fw_proxy_init_done(gsc, false)) { if (intel_gsc_uc_fw_proxy_init_done(gsc, false)) {
drm_dbg(&gt->i915->drm, "GSC Proxy initialized\n"); gt_dbg(gt, "GSC Proxy initialized\n");
intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_RUNNING); intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_RUNNING);
} else { } else {
drm_err(&gt->i915->drm, gt_err(gt, "GSC status reports proxy init not complete\n");
"GSC status reports proxy init not complete\n");
intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_LOAD_FAIL); intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_LOAD_FAIL);
} }
} }
......
...@@ -319,6 +319,12 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) ...@@ -319,6 +319,12 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc)
if (!RCS_MASK(gt)) if (!RCS_MASK(gt))
flags |= GUC_WA_RCS_REGS_IN_CCS_REGS_LIST; flags |= GUC_WA_RCS_REGS_IN_CCS_REGS_LIST;
/* Wa_14018913170 */
if (GUC_FIRMWARE_VER(guc) >= MAKE_GUC_VER(70, 7, 0)) {
if (IS_DG2(gt->i915) || IS_METEORLAKE(gt->i915) || IS_PONTEVECCHIO(gt->i915))
flags |= GUC_WA_ENABLE_TSC_CHECK_ON_RC6;
}
return flags; return flags;
} }
......
...@@ -295,6 +295,7 @@ struct intel_guc { ...@@ -295,6 +295,7 @@ struct intel_guc {
#define MAKE_GUC_VER(maj, min, pat) (((maj) << 16) | ((min) << 8) | (pat)) #define MAKE_GUC_VER(maj, min, pat) (((maj) << 16) | ((min) << 8) | (pat))
#define MAKE_GUC_VER_STRUCT(ver) MAKE_GUC_VER((ver).major, (ver).minor, (ver).patch) #define MAKE_GUC_VER_STRUCT(ver) MAKE_GUC_VER((ver).major, (ver).minor, (ver).patch)
#define GUC_SUBMIT_VER(guc) MAKE_GUC_VER_STRUCT((guc)->submission_version) #define GUC_SUBMIT_VER(guc) MAKE_GUC_VER_STRUCT((guc)->submission_version)
#define GUC_FIRMWARE_VER(guc) MAKE_GUC_VER_STRUCT((guc)->fw.file_selected.ver)
static inline struct intel_guc *log_to_guc(struct intel_guc_log *log) static inline struct intel_guc *log_to_guc(struct intel_guc_log *log)
{ {
......
...@@ -96,7 +96,7 @@ struct ct_request { ...@@ -96,7 +96,7 @@ struct ct_request {
struct ct_incoming_msg { struct ct_incoming_msg {
struct list_head link; struct list_head link;
u32 size; u32 size;
u32 msg[]; u32 msg[] __counted_by(size);
}; };
enum { CTB_SEND = 0, CTB_RECV = 1 }; enum { CTB_SEND = 0, CTB_RECV = 1 };
......
...@@ -100,6 +100,7 @@ ...@@ -100,6 +100,7 @@
#define GUC_WA_HOLD_CCS_SWITCHOUT BIT(17) #define GUC_WA_HOLD_CCS_SWITCHOUT BIT(17)
#define GUC_WA_POLLCS BIT(18) #define GUC_WA_POLLCS BIT(18)
#define GUC_WA_RCS_REGS_IN_CCS_REGS_LIST BIT(21) #define GUC_WA_RCS_REGS_IN_CCS_REGS_LIST BIT(21)
#define GUC_WA_ENABLE_TSC_CHECK_ON_RC6 BIT(22)
#define GUC_CTL_FEATURE 2 #define GUC_CTL_FEATURE 2
#define GUC_CTL_ENABLE_SLPC BIT(2) #define GUC_CTL_ENABLE_SLPC BIT(2)
......
...@@ -4802,19 +4802,19 @@ static void guc_context_replay(struct intel_context *ce) ...@@ -4802,19 +4802,19 @@ static void guc_context_replay(struct intel_context *ce)
static void guc_handle_context_reset(struct intel_guc *guc, static void guc_handle_context_reset(struct intel_guc *guc,
struct intel_context *ce) struct intel_context *ce)
{ {
bool capture = intel_context_is_schedulable(ce);
trace_intel_context_reset(ce); trace_intel_context_reset(ce);
guc_dbg(guc, "Got context reset notification: 0x%04X on %s, exiting = %s, banned = %s\n", guc_dbg(guc, "%s context reset notification: 0x%04X on %s, exiting = %s, banned = %s\n",
capture ? "Got" : "Ignoring",
ce->guc_id.id, ce->engine->name, ce->guc_id.id, ce->engine->name,
str_yes_no(intel_context_is_exiting(ce)), str_yes_no(intel_context_is_exiting(ce)),
str_yes_no(intel_context_is_banned(ce))); str_yes_no(intel_context_is_banned(ce)));
if (likely(intel_context_is_schedulable(ce))) { if (capture) {
capture_error_state(guc, ce); capture_error_state(guc, ce);
guc_context_replay(ce); guc_context_replay(ce);
} else {
guc_info(guc, "Ignoring context reset notification of exiting context 0x%04X on %s",
ce->guc_id.id, ce->engine->name);
} }
} }
......
...@@ -88,12 +88,12 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, ...@@ -88,12 +88,12 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
* security fixes, etc. to be enabled. * security fixes, etc. to be enabled.
*/ */
#define INTEL_GUC_FIRMWARE_DEFS(fw_def, guc_maj, guc_mmp) \ #define INTEL_GUC_FIRMWARE_DEFS(fw_def, guc_maj, guc_mmp) \
fw_def(METEORLAKE, 0, guc_maj(mtl, 70, 6, 6)) \ fw_def(METEORLAKE, 0, guc_maj(mtl, 70, 12, 1)) \
fw_def(DG2, 0, guc_maj(dg2, 70, 5, 1)) \ fw_def(DG2, 0, guc_maj(dg2, 70, 12, 1)) \
fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 5, 1)) \ fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 12, 1)) \
fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 70, 1, 1)) \ fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 70, 1, 1)) \
fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 69, 0, 3)) \ fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 69, 0, 3)) \
fw_def(ALDERLAKE_S, 0, guc_maj(tgl, 70, 5, 1)) \ fw_def(ALDERLAKE_S, 0, guc_maj(tgl, 70, 12, 1)) \
fw_def(ALDERLAKE_S, 0, guc_mmp(tgl, 70, 1, 1)) \ fw_def(ALDERLAKE_S, 0, guc_mmp(tgl, 70, 1, 1)) \
fw_def(ALDERLAKE_S, 0, guc_mmp(tgl, 69, 0, 3)) \ fw_def(ALDERLAKE_S, 0, guc_mmp(tgl, 69, 0, 3)) \
fw_def(DG1, 0, guc_maj(dg1, 70, 5, 1)) \ fw_def(DG1, 0, guc_maj(dg1, 70, 5, 1)) \
......
...@@ -71,6 +71,7 @@ ...@@ -71,6 +71,7 @@
#include "gem/i915_gem_pm.h" #include "gem/i915_gem_pm.h"
#include "gt/intel_gt.h" #include "gt/intel_gt.h"
#include "gt/intel_gt_pm.h" #include "gt/intel_gt_pm.h"
#include "gt/intel_gt_print.h"
#include "gt/intel_rc6.h" #include "gt/intel_rc6.h"
#include "pxp/intel_pxp.h" #include "pxp/intel_pxp.h"
...@@ -429,7 +430,7 @@ static int i915_pcode_init(struct drm_i915_private *i915) ...@@ -429,7 +430,7 @@ static int i915_pcode_init(struct drm_i915_private *i915)
for_each_gt(gt, i915, id) { for_each_gt(gt, i915, id) {
ret = intel_pcode_init(gt->uncore); ret = intel_pcode_init(gt->uncore);
if (ret) { if (ret) {
drm_err(&gt->i915->drm, "gt%d: intel_pcode_init failed %d\n", id, ret); gt_err(gt, "intel_pcode_init failed %d\n", ret);
return ret; return ret;
} }
} }
...@@ -1328,10 +1329,8 @@ static int i915_drm_resume_early(struct drm_device *dev) ...@@ -1328,10 +1329,8 @@ static int i915_drm_resume_early(struct drm_device *dev)
drm_err(&dev_priv->drm, drm_err(&dev_priv->drm,
"Resume prepare failed: %d, continuing anyway\n", ret); "Resume prepare failed: %d, continuing anyway\n", ret);
for_each_gt(gt, dev_priv, i) { for_each_gt(gt, dev_priv, i)
intel_uncore_resume_early(gt->uncore); intel_gt_resume_early(gt);
intel_gt_check_and_clear_faults(gt);
}
intel_display_power_resume_early(dev_priv); intel_display_power_resume_early(dev_priv);
......
...@@ -222,7 +222,22 @@ struct drm_i915_private { ...@@ -222,7 +222,22 @@ struct drm_i915_private {
bool mchbar_need_disable; bool mchbar_need_disable;
} gmch; } gmch;
/*
* Chaining user engines happens in multiple stages, starting with a
* simple lock-less linked list created by intel_engine_add_user(),
* which later gets sorted and converted to an intermediate regular
* list, just to be converted once again to its final rb tree structure
* in intel_engines_driver_register().
*
* Make sure to use the right iterator helper, depending on if the code
* in question runs before or after intel_engines_driver_register() --
* for_each_uabi_engine() can only be used afterwards!
*/
union {
struct llist_head uabi_engines_llist;
struct list_head uabi_engines_list;
struct rb_root uabi_engines; struct rb_root uabi_engines;
};
unsigned int engine_uabi_class_count[I915_LAST_UABI_ENGINE_CLASS + 1]; unsigned int engine_uabi_class_count[I915_LAST_UABI_ENGINE_CLASS + 1];
/* protects the irq masks */ /* protects the irq masks */
......
...@@ -1199,6 +1199,13 @@ int i915_gem_init(struct drm_i915_private *dev_priv) ...@@ -1199,6 +1199,13 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
goto err_unlock; goto err_unlock;
} }
/*
* Register engines early to ensure the engine list is in its final
* rb-tree form, lowering the amount of code that has to deal with
* the intermediate llist state.
*/
intel_engines_driver_register(dev_priv);
return 0; return 0;
/* /*
...@@ -1246,8 +1253,6 @@ int i915_gem_init(struct drm_i915_private *dev_priv) ...@@ -1246,8 +1253,6 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
void i915_gem_driver_register(struct drm_i915_private *i915) void i915_gem_driver_register(struct drm_i915_private *i915)
{ {
i915_gem_driver_register__shrinker(i915); i915_gem_driver_register__shrinker(i915);
intel_engines_driver_register(i915);
} }
void i915_gem_driver_unregister(struct drm_i915_private *i915) void i915_gem_driver_unregister(struct drm_i915_private *i915)
......
...@@ -1234,7 +1234,16 @@ static void engine_record_registers(struct intel_engine_coredump *ee) ...@@ -1234,7 +1234,16 @@ static void engine_record_registers(struct intel_engine_coredump *ee)
if (GRAPHICS_VER(i915) >= 6) { if (GRAPHICS_VER(i915) >= 6) {
ee->rc_psmi = ENGINE_READ(engine, RING_PSMI_CTL); ee->rc_psmi = ENGINE_READ(engine, RING_PSMI_CTL);
if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) /*
* For the media GT, this ring fault register is not replicated,
* so don't do multicast/replicated register read/write
* operation on it.
*/
if (MEDIA_VER(i915) >= 13 && engine->gt->type == GT_MEDIA)
ee->fault_reg = intel_uncore_read(engine->uncore,
XELPMP_RING_FAULT_REG);
else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50))
ee->fault_reg = intel_gt_mcr_read_any(engine->gt, ee->fault_reg = intel_gt_mcr_read_any(engine->gt,
XEHP_RING_FAULT_REG); XEHP_RING_FAULT_REG);
else if (GRAPHICS_VER(i915) >= 12) else if (GRAPHICS_VER(i915) >= 12)
......
...@@ -206,6 +206,7 @@ ...@@ -206,6 +206,7 @@
#include "gt/intel_gt.h" #include "gt/intel_gt.h"
#include "gt/intel_gt_clock_utils.h" #include "gt/intel_gt_clock_utils.h"
#include "gt/intel_gt_mcr.h" #include "gt/intel_gt_mcr.h"
#include "gt/intel_gt_print.h"
#include "gt/intel_gt_regs.h" #include "gt/intel_gt_regs.h"
#include "gt/intel_lrc.h" #include "gt/intel_lrc.h"
#include "gt/intel_lrc_reg.h" #include "gt/intel_lrc_reg.h"
...@@ -1659,8 +1660,7 @@ static void i915_oa_stream_destroy(struct i915_perf_stream *stream) ...@@ -1659,8 +1660,7 @@ static void i915_oa_stream_destroy(struct i915_perf_stream *stream)
free_noa_wait(stream); free_noa_wait(stream);
if (perf->spurious_report_rs.missed) { if (perf->spurious_report_rs.missed) {
drm_notice(&gt->i915->drm, gt_notice(gt, "%d spurious OA report notices suppressed due to ratelimiting\n",
"%d spurious OA report notices suppressed due to ratelimiting\n",
perf->spurious_report_rs.missed); perf->spurious_report_rs.missed);
} }
} }
...@@ -1852,7 +1852,7 @@ static int alloc_oa_buffer(struct i915_perf_stream *stream) ...@@ -1852,7 +1852,7 @@ static int alloc_oa_buffer(struct i915_perf_stream *stream)
*/ */
ret = i915_vma_pin(vma, 0, SZ_16M, PIN_GLOBAL | PIN_HIGH); ret = i915_vma_pin(vma, 0, SZ_16M, PIN_GLOBAL | PIN_HIGH);
if (ret) { if (ret) {
drm_err(&gt->i915->drm, "Failed to pin OA buffer %d\n", ret); gt_err(gt, "Failed to pin OA buffer %d\n", ret);
goto err_unref; goto err_unref;
} }
......
...@@ -91,6 +91,16 @@ static inline struct scatterlist *__sg_next(struct scatterlist *sg) ...@@ -91,6 +91,16 @@ static inline struct scatterlist *__sg_next(struct scatterlist *sg)
((__dp) = (__iter).dma + (__iter).curr), (__iter).sgp; \ ((__dp) = (__iter).dma + (__iter).curr), (__iter).sgp; \
(((__iter).curr += (__step)) >= (__iter).max) ? \ (((__iter).curr += (__step)) >= (__iter).max) ? \
(__iter) = __sgt_iter(__sg_next((__iter).sgp), true), 0 : 0) (__iter) = __sgt_iter(__sg_next((__iter).sgp), true), 0 : 0)
/**
* __for_each_daddr_next - iterates over the device addresses with pre-initialized iterator.
* @__dp: Device address (output)
* @__iter: 'struct sgt_iter' (iterator state, external)
* @__step: step size
*/
#define __for_each_daddr_next(__dp, __iter, __step) \
for (; ((__dp) = (__iter).dma + (__iter).curr), (__iter).sgp; \
(((__iter).curr += (__step)) >= (__iter).max) ? \
(__iter) = __sgt_iter(__sg_next((__iter).sgp), true), 0 : 0)
/** /**
* for_each_sgt_page - iterate over the pages of the given sg_table * for_each_sgt_page - iterate over the pages of the given sg_table
......
...@@ -10,21 +10,12 @@ ...@@ -10,21 +10,12 @@
#include "intel_wakeref.h" #include "intel_wakeref.h"
#include "i915_drv.h" #include "i915_drv.h"
static void rpm_get(struct intel_wakeref *wf)
{
wf->wakeref = intel_runtime_pm_get(&wf->i915->runtime_pm);
}
static void rpm_put(struct intel_wakeref *wf)
{
intel_wakeref_t wakeref = fetch_and_zero(&wf->wakeref);
intel_runtime_pm_put(&wf->i915->runtime_pm, wakeref);
INTEL_WAKEREF_BUG_ON(!wakeref);
}
int __intel_wakeref_get_first(struct intel_wakeref *wf) int __intel_wakeref_get_first(struct intel_wakeref *wf)
{ {
intel_wakeref_t wakeref;
int ret = 0;
wakeref = intel_runtime_pm_get(&wf->i915->runtime_pm);
/* /*
* Treat get/put as different subclasses, as we may need to run * Treat get/put as different subclasses, as we may need to run
* the put callback from under the shrinker and do not want to * the put callback from under the shrinker and do not want to
...@@ -32,41 +23,52 @@ int __intel_wakeref_get_first(struct intel_wakeref *wf) ...@@ -32,41 +23,52 @@ int __intel_wakeref_get_first(struct intel_wakeref *wf)
* upon acquiring the wakeref. * upon acquiring the wakeref.
*/ */
mutex_lock_nested(&wf->mutex, SINGLE_DEPTH_NESTING); mutex_lock_nested(&wf->mutex, SINGLE_DEPTH_NESTING);
if (!atomic_read(&wf->count)) {
int err;
rpm_get(wf); if (!atomic_read(&wf->count)) {
INTEL_WAKEREF_BUG_ON(wf->wakeref);
wf->wakeref = wakeref;
wakeref = 0;
err = wf->ops->get(wf); ret = wf->ops->get(wf);
if (unlikely(err)) { if (ret) {
rpm_put(wf); wakeref = xchg(&wf->wakeref, 0);
mutex_unlock(&wf->mutex); wake_up_var(&wf->wakeref);
return err; goto unlock;
} }
smp_mb__before_atomic(); /* release wf->count */ smp_mb__before_atomic(); /* release wf->count */
} }
atomic_inc(&wf->count); atomic_inc(&wf->count);
INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <= 0);
unlock:
mutex_unlock(&wf->mutex); mutex_unlock(&wf->mutex);
if (unlikely(wakeref))
intel_runtime_pm_put(&wf->i915->runtime_pm, wakeref);
INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <= 0); return ret;
return 0;
} }
static void ____intel_wakeref_put_last(struct intel_wakeref *wf) static void ____intel_wakeref_put_last(struct intel_wakeref *wf)
{ {
intel_wakeref_t wakeref = 0;
INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <= 0); INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <= 0);
if (unlikely(!atomic_dec_and_test(&wf->count))) if (unlikely(!atomic_dec_and_test(&wf->count)))
goto unlock; goto unlock;
/* ops->put() must reschedule its own release on error/deferral */ /* ops->put() must reschedule its own release on error/deferral */
if (likely(!wf->ops->put(wf))) { if (likely(!wf->ops->put(wf))) {
rpm_put(wf); INTEL_WAKEREF_BUG_ON(!wf->wakeref);
wakeref = xchg(&wf->wakeref, 0);
wake_up_var(&wf->wakeref); wake_up_var(&wf->wakeref);
} }
unlock: unlock:
mutex_unlock(&wf->mutex); mutex_unlock(&wf->mutex);
if (wakeref)
intel_runtime_pm_put(&wf->i915->runtime_pm, wakeref);
} }
void __intel_wakeref_put_last(struct intel_wakeref *wf, unsigned long flags) void __intel_wakeref_put_last(struct intel_wakeref *wf, unsigned long flags)
......
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