mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-11 07:39:47 +00:00
- Fixes on execlist to avoid GPU hang situation (Chris)
- Fixes couple deadlocks (Chris) - Timeslice preemption fixes (Chris) - Fix Display Port interrupt handling on Tiger Lake (Imre) - Reduce debug noise around Frame Buffer Compression (Peter) - Fix logic around IPC W/a for Coffee Lake and Kaby Lake (Sultan) - Avoid dereferencing a dead context (Chris) -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEbSBwaO7dZQkcLOKj+mJfZA7rE8oFAl607QgACgkQ+mJfZA7r E8oP4gf+MxxjhkjPI+kmBDVE7f1kSnjYDdITWbmGPdzkaVEqTNwdmu2liYuy+Be0 qKtncD6/3Xs16JU905Ew7EbBODvDhWHkRJ2QH3MAPnu28qjFgDHl/tbbnYzWQsDJ JNt0vYJ1jUpm+QrRy1W2woWO95fjsYzYDsVHhKZzVoiHmoEULH1XyFqJfYh4yoLZ puKSj/LXGeVTRPEU9HL9Hhs2wpB5SI/pda7UgLMj0Cjc+3MkdDMPI9qKTOtlype8 yErtqGMYsMifSrKhaMXYPZCtGexScknUS5mq9WjGJITgd8LqACEeciP7twkO0ZMx Del31B21K3Gjq9mdmv32Bur0LA++Dg== =Byvp -----END PGP SIGNATURE----- Merge tag 'drm-intel-fixes-2020-05-07' of git://anongit.freedesktop.org/drm/drm-intel into drm-fixes - Fixes on execlist to avoid GPU hang situation (Chris) - Fixes couple deadlocks (Chris) - Timeslice preemption fixes (Chris) - Fix Display Port interrupt handling on Tiger Lake (Imre) - Reduce debug noise around Frame Buffer Compression (Peter) - Fix logic around IPC W/a for Coffee Lake and Kaby Lake (Sultan) - Avoid dereferencing a dead context (Chris) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Rodrigo Vivi <rodrigo.vivi@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200508052437.GA3212215@intel.com
This commit is contained in:
commit
0c77ca2f9d
@ -485,8 +485,7 @@ static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv,
|
||||
if (!ret)
|
||||
goto err_llb;
|
||||
else if (ret > 1) {
|
||||
DRM_INFO("Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n");
|
||||
|
||||
DRM_INFO_ONCE("Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n");
|
||||
}
|
||||
|
||||
fbc->threshold = ret;
|
||||
|
@ -368,7 +368,6 @@ static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj)
|
||||
struct drm_i915_private *i915 = to_i915(obj->base.dev);
|
||||
struct i915_vma *vma;
|
||||
|
||||
GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
|
||||
if (!atomic_read(&obj->bind_count))
|
||||
return;
|
||||
|
||||
@ -400,12 +399,8 @@ static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj)
|
||||
void
|
||||
i915_gem_object_unpin_from_display_plane(struct i915_vma *vma)
|
||||
{
|
||||
struct drm_i915_gem_object *obj = vma->obj;
|
||||
|
||||
assert_object_held(obj);
|
||||
|
||||
/* Bump the LRU to try and avoid premature eviction whilst flipping */
|
||||
i915_gem_object_bump_inactive_ggtt(obj);
|
||||
i915_gem_object_bump_inactive_ggtt(vma->obj);
|
||||
|
||||
i915_vma_unpin(vma);
|
||||
}
|
||||
|
@ -69,7 +69,13 @@ struct intel_context {
|
||||
#define CONTEXT_NOPREEMPT 7
|
||||
|
||||
u32 *lrc_reg_state;
|
||||
u64 lrc_desc;
|
||||
union {
|
||||
struct {
|
||||
u32 lrca;
|
||||
u32 ccid;
|
||||
};
|
||||
u64 desc;
|
||||
} lrc;
|
||||
u32 tag; /* cookie passed to HW to track this context on submission */
|
||||
|
||||
/* Time on GPU as tracked by the hw. */
|
||||
|
@ -333,13 +333,4 @@ intel_engine_has_preempt_reset(const struct intel_engine_cs *engine)
|
||||
return intel_engine_has_preemption(engine);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
intel_engine_has_timeslices(const struct intel_engine_cs *engine)
|
||||
{
|
||||
if (!IS_ACTIVE(CONFIG_DRM_I915_TIMESLICE_DURATION))
|
||||
return false;
|
||||
|
||||
return intel_engine_has_semaphores(engine);
|
||||
}
|
||||
|
||||
#endif /* _INTEL_RINGBUFFER_H_ */
|
||||
|
@ -1295,6 +1295,12 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine,
|
||||
|
||||
if (engine->id == RENDER_CLASS && IS_GEN_RANGE(dev_priv, 4, 7))
|
||||
drm_printf(m, "\tCCID: 0x%08x\n", ENGINE_READ(engine, CCID));
|
||||
if (HAS_EXECLISTS(dev_priv)) {
|
||||
drm_printf(m, "\tEL_STAT_HI: 0x%08x\n",
|
||||
ENGINE_READ(engine, RING_EXECLIST_STATUS_HI));
|
||||
drm_printf(m, "\tEL_STAT_LO: 0x%08x\n",
|
||||
ENGINE_READ(engine, RING_EXECLIST_STATUS_LO));
|
||||
}
|
||||
drm_printf(m, "\tRING_START: 0x%08x\n",
|
||||
ENGINE_READ(engine, RING_START));
|
||||
drm_printf(m, "\tRING_HEAD: 0x%08x\n",
|
||||
|
@ -156,6 +156,20 @@ struct intel_engine_execlists {
|
||||
*/
|
||||
struct i915_priolist default_priolist;
|
||||
|
||||
/**
|
||||
* @ccid: identifier for contexts submitted to this engine
|
||||
*/
|
||||
u32 ccid;
|
||||
|
||||
/**
|
||||
* @yield: CCID at the time of the last semaphore-wait interrupt.
|
||||
*
|
||||
* Instead of leaving a semaphore busy-spinning on an engine, we would
|
||||
* like to switch to another ready context, i.e. yielding the semaphore
|
||||
* timeslice.
|
||||
*/
|
||||
u32 yield;
|
||||
|
||||
/**
|
||||
* @error_interrupt: CS Master EIR
|
||||
*
|
||||
@ -295,8 +309,7 @@ struct intel_engine_cs {
|
||||
u32 context_size;
|
||||
u32 mmio_base;
|
||||
|
||||
unsigned int context_tag;
|
||||
#define NUM_CONTEXT_TAG roundup_pow_of_two(2 * EXECLIST_MAX_PORTS)
|
||||
unsigned long context_tag;
|
||||
|
||||
struct rb_node uabi_node;
|
||||
|
||||
@ -483,10 +496,11 @@ struct intel_engine_cs {
|
||||
#define I915_ENGINE_SUPPORTS_STATS BIT(1)
|
||||
#define I915_ENGINE_HAS_PREEMPTION BIT(2)
|
||||
#define I915_ENGINE_HAS_SEMAPHORES BIT(3)
|
||||
#define I915_ENGINE_NEEDS_BREADCRUMB_TASKLET BIT(4)
|
||||
#define I915_ENGINE_IS_VIRTUAL BIT(5)
|
||||
#define I915_ENGINE_HAS_RELATIVE_MMIO BIT(6)
|
||||
#define I915_ENGINE_REQUIRES_CMD_PARSER BIT(7)
|
||||
#define I915_ENGINE_HAS_TIMESLICES BIT(4)
|
||||
#define I915_ENGINE_NEEDS_BREADCRUMB_TASKLET BIT(5)
|
||||
#define I915_ENGINE_IS_VIRTUAL BIT(6)
|
||||
#define I915_ENGINE_HAS_RELATIVE_MMIO BIT(7)
|
||||
#define I915_ENGINE_REQUIRES_CMD_PARSER BIT(8)
|
||||
unsigned int flags;
|
||||
|
||||
/*
|
||||
@ -584,6 +598,15 @@ intel_engine_has_semaphores(const struct intel_engine_cs *engine)
|
||||
return engine->flags & I915_ENGINE_HAS_SEMAPHORES;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
intel_engine_has_timeslices(const struct intel_engine_cs *engine)
|
||||
{
|
||||
if (!IS_ACTIVE(CONFIG_DRM_I915_TIMESLICE_DURATION))
|
||||
return false;
|
||||
|
||||
return engine->flags & I915_ENGINE_HAS_TIMESLICES;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
intel_engine_needs_breadcrumb_tasklet(const struct intel_engine_cs *engine)
|
||||
{
|
||||
|
@ -39,6 +39,15 @@ cs_irq_handler(struct intel_engine_cs *engine, u32 iir)
|
||||
}
|
||||
}
|
||||
|
||||
if (iir & GT_WAIT_SEMAPHORE_INTERRUPT) {
|
||||
WRITE_ONCE(engine->execlists.yield,
|
||||
ENGINE_READ_FW(engine, RING_EXECLIST_STATUS_HI));
|
||||
ENGINE_TRACE(engine, "semaphore yield: %08x\n",
|
||||
engine->execlists.yield);
|
||||
if (del_timer(&engine->execlists.timer))
|
||||
tasklet = true;
|
||||
}
|
||||
|
||||
if (iir & GT_CONTEXT_SWITCH_INTERRUPT)
|
||||
tasklet = true;
|
||||
|
||||
@ -228,7 +237,8 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
|
||||
const u32 irqs =
|
||||
GT_CS_MASTER_ERROR_INTERRUPT |
|
||||
GT_RENDER_USER_INTERRUPT |
|
||||
GT_CONTEXT_SWITCH_INTERRUPT;
|
||||
GT_CONTEXT_SWITCH_INTERRUPT |
|
||||
GT_WAIT_SEMAPHORE_INTERRUPT;
|
||||
struct intel_uncore *uncore = gt->uncore;
|
||||
const u32 dmask = irqs << 16 | irqs;
|
||||
const u32 smask = irqs << 16;
|
||||
@ -366,7 +376,8 @@ void gen8_gt_irq_postinstall(struct intel_gt *gt)
|
||||
const u32 irqs =
|
||||
GT_CS_MASTER_ERROR_INTERRUPT |
|
||||
GT_RENDER_USER_INTERRUPT |
|
||||
GT_CONTEXT_SWITCH_INTERRUPT;
|
||||
GT_CONTEXT_SWITCH_INTERRUPT |
|
||||
GT_WAIT_SEMAPHORE_INTERRUPT;
|
||||
const u32 gt_interrupts[] = {
|
||||
irqs << GEN8_RCS_IRQ_SHIFT | irqs << GEN8_BCS_IRQ_SHIFT,
|
||||
irqs << GEN8_VCS0_IRQ_SHIFT | irqs << GEN8_VCS1_IRQ_SHIFT,
|
||||
|
@ -456,10 +456,10 @@ assert_priority_queue(const struct i915_request *prev,
|
||||
* engine info, SW context ID and SW counter need to form a unique number
|
||||
* (Context ID) per lrc.
|
||||
*/
|
||||
static u64
|
||||
static u32
|
||||
lrc_descriptor(struct intel_context *ce, struct intel_engine_cs *engine)
|
||||
{
|
||||
u64 desc;
|
||||
u32 desc;
|
||||
|
||||
desc = INTEL_LEGACY_32B_CONTEXT;
|
||||
if (i915_vm_is_4lvl(ce->vm))
|
||||
@ -470,21 +470,7 @@ lrc_descriptor(struct intel_context *ce, struct intel_engine_cs *engine)
|
||||
if (IS_GEN(engine->i915, 8))
|
||||
desc |= GEN8_CTX_L3LLC_COHERENT;
|
||||
|
||||
desc |= i915_ggtt_offset(ce->state); /* bits 12-31 */
|
||||
/*
|
||||
* The following 32bits are copied into the OA reports (dword 2).
|
||||
* Consider updating oa_get_render_ctx_id in i915_perf.c when changing
|
||||
* anything below.
|
||||
*/
|
||||
if (INTEL_GEN(engine->i915) >= 11) {
|
||||
desc |= (u64)engine->instance << GEN11_ENGINE_INSTANCE_SHIFT;
|
||||
/* bits 48-53 */
|
||||
|
||||
desc |= (u64)engine->class << GEN11_ENGINE_CLASS_SHIFT;
|
||||
/* bits 61-63 */
|
||||
}
|
||||
|
||||
return desc;
|
||||
return i915_ggtt_offset(ce->state) | desc;
|
||||
}
|
||||
|
||||
static inline unsigned int dword_in_page(void *addr)
|
||||
@ -1192,7 +1178,7 @@ static void reset_active(struct i915_request *rq,
|
||||
__execlists_update_reg_state(ce, engine, head);
|
||||
|
||||
/* We've switched away, so this should be a no-op, but intent matters */
|
||||
ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
|
||||
ce->lrc.desc |= CTX_DESC_FORCE_RESTORE;
|
||||
}
|
||||
|
||||
static u32 intel_context_get_runtime(const struct intel_context *ce)
|
||||
@ -1251,18 +1237,23 @@ __execlists_schedule_in(struct i915_request *rq)
|
||||
if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
|
||||
execlists_check_context(ce, engine);
|
||||
|
||||
ce->lrc_desc &= ~GENMASK_ULL(47, 37);
|
||||
if (ce->tag) {
|
||||
/* Use a fixed tag for OA and friends */
|
||||
ce->lrc_desc |= (u64)ce->tag << 32;
|
||||
GEM_BUG_ON(ce->tag <= BITS_PER_LONG);
|
||||
ce->lrc.ccid = ce->tag;
|
||||
} else {
|
||||
/* We don't need a strict matching tag, just different values */
|
||||
ce->lrc_desc |=
|
||||
(u64)(++engine->context_tag % NUM_CONTEXT_TAG) <<
|
||||
GEN11_SW_CTX_ID_SHIFT;
|
||||
BUILD_BUG_ON(NUM_CONTEXT_TAG > GEN12_MAX_CONTEXT_HW_ID);
|
||||
unsigned int tag = ffs(engine->context_tag);
|
||||
|
||||
GEM_BUG_ON(tag == 0 || tag >= BITS_PER_LONG);
|
||||
clear_bit(tag - 1, &engine->context_tag);
|
||||
ce->lrc.ccid = tag << (GEN11_SW_CTX_ID_SHIFT - 32);
|
||||
|
||||
BUILD_BUG_ON(BITS_PER_LONG > GEN12_MAX_CONTEXT_HW_ID);
|
||||
}
|
||||
|
||||
ce->lrc.ccid |= engine->execlists.ccid;
|
||||
|
||||
__intel_gt_pm_get(engine->gt);
|
||||
execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_IN);
|
||||
intel_engine_context_in(engine);
|
||||
@ -1302,7 +1293,8 @@ static void kick_siblings(struct i915_request *rq, struct intel_context *ce)
|
||||
|
||||
static inline void
|
||||
__execlists_schedule_out(struct i915_request *rq,
|
||||
struct intel_engine_cs * const engine)
|
||||
struct intel_engine_cs * const engine,
|
||||
unsigned int ccid)
|
||||
{
|
||||
struct intel_context * const ce = rq->context;
|
||||
|
||||
@ -1320,6 +1312,14 @@ __execlists_schedule_out(struct i915_request *rq,
|
||||
i915_request_completed(rq))
|
||||
intel_engine_add_retire(engine, ce->timeline);
|
||||
|
||||
ccid >>= GEN11_SW_CTX_ID_SHIFT - 32;
|
||||
ccid &= GEN12_MAX_CONTEXT_HW_ID;
|
||||
if (ccid < BITS_PER_LONG) {
|
||||
GEM_BUG_ON(ccid == 0);
|
||||
GEM_BUG_ON(test_bit(ccid - 1, &engine->context_tag));
|
||||
set_bit(ccid - 1, &engine->context_tag);
|
||||
}
|
||||
|
||||
intel_context_update_runtime(ce);
|
||||
intel_engine_context_out(engine);
|
||||
execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT);
|
||||
@ -1345,15 +1345,17 @@ execlists_schedule_out(struct i915_request *rq)
|
||||
{
|
||||
struct intel_context * const ce = rq->context;
|
||||
struct intel_engine_cs *cur, *old;
|
||||
u32 ccid;
|
||||
|
||||
trace_i915_request_out(rq);
|
||||
|
||||
ccid = rq->context->lrc.ccid;
|
||||
old = READ_ONCE(ce->inflight);
|
||||
do
|
||||
cur = ptr_unmask_bits(old, 2) ? ptr_dec(old) : NULL;
|
||||
while (!try_cmpxchg(&ce->inflight, &old, cur));
|
||||
if (!cur)
|
||||
__execlists_schedule_out(rq, old);
|
||||
__execlists_schedule_out(rq, old, ccid);
|
||||
|
||||
i915_request_put(rq);
|
||||
}
|
||||
@ -1361,7 +1363,7 @@ execlists_schedule_out(struct i915_request *rq)
|
||||
static u64 execlists_update_context(struct i915_request *rq)
|
||||
{
|
||||
struct intel_context *ce = rq->context;
|
||||
u64 desc = ce->lrc_desc;
|
||||
u64 desc = ce->lrc.desc;
|
||||
u32 tail, prev;
|
||||
|
||||
/*
|
||||
@ -1400,7 +1402,7 @@ static u64 execlists_update_context(struct i915_request *rq)
|
||||
*/
|
||||
wmb();
|
||||
|
||||
ce->lrc_desc &= ~CTX_DESC_FORCE_RESTORE;
|
||||
ce->lrc.desc &= ~CTX_DESC_FORCE_RESTORE;
|
||||
return desc;
|
||||
}
|
||||
|
||||
@ -1754,7 +1756,8 @@ static void defer_active(struct intel_engine_cs *engine)
|
||||
}
|
||||
|
||||
static bool
|
||||
need_timeslice(struct intel_engine_cs *engine, const struct i915_request *rq)
|
||||
need_timeslice(const struct intel_engine_cs *engine,
|
||||
const struct i915_request *rq)
|
||||
{
|
||||
int hint;
|
||||
|
||||
@ -1768,6 +1771,32 @@ need_timeslice(struct intel_engine_cs *engine, const struct i915_request *rq)
|
||||
return hint >= effective_prio(rq);
|
||||
}
|
||||
|
||||
static bool
|
||||
timeslice_yield(const struct intel_engine_execlists *el,
|
||||
const struct i915_request *rq)
|
||||
{
|
||||
/*
|
||||
* Once bitten, forever smitten!
|
||||
*
|
||||
* If the active context ever busy-waited on a semaphore,
|
||||
* it will be treated as a hog until the end of its timeslice (i.e.
|
||||
* until it is scheduled out and replaced by a new submission,
|
||||
* possibly even its own lite-restore). The HW only sends an interrupt
|
||||
* on the first miss, and we do know if that semaphore has been
|
||||
* signaled, or even if it is now stuck on another semaphore. Play
|
||||
* safe, yield if it might be stuck -- it will be given a fresh
|
||||
* timeslice in the near future.
|
||||
*/
|
||||
return rq->context->lrc.ccid == READ_ONCE(el->yield);
|
||||
}
|
||||
|
||||
static bool
|
||||
timeslice_expired(const struct intel_engine_execlists *el,
|
||||
const struct i915_request *rq)
|
||||
{
|
||||
return timer_expired(&el->timer) || timeslice_yield(el, rq);
|
||||
}
|
||||
|
||||
static int
|
||||
switch_prio(struct intel_engine_cs *engine, const struct i915_request *rq)
|
||||
{
|
||||
@ -1783,8 +1812,7 @@ timeslice(const struct intel_engine_cs *engine)
|
||||
return READ_ONCE(engine->props.timeslice_duration_ms);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
active_timeslice(const struct intel_engine_cs *engine)
|
||||
static unsigned long active_timeslice(const struct intel_engine_cs *engine)
|
||||
{
|
||||
const struct intel_engine_execlists *execlists = &engine->execlists;
|
||||
const struct i915_request *rq = *execlists->active;
|
||||
@ -1946,13 +1974,14 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
|
||||
|
||||
last = NULL;
|
||||
} else if (need_timeslice(engine, last) &&
|
||||
timer_expired(&engine->execlists.timer)) {
|
||||
timeslice_expired(execlists, last)) {
|
||||
ENGINE_TRACE(engine,
|
||||
"expired last=%llx:%lld, prio=%d, hint=%d\n",
|
||||
"expired last=%llx:%lld, prio=%d, hint=%d, yield?=%s\n",
|
||||
last->fence.context,
|
||||
last->fence.seqno,
|
||||
last->sched.attr.priority,
|
||||
execlists->queue_priority_hint);
|
||||
execlists->queue_priority_hint,
|
||||
yesno(timeslice_yield(execlists, last)));
|
||||
|
||||
ring_set_paused(engine, 1);
|
||||
defer_active(engine);
|
||||
@ -2213,6 +2242,7 @@ done:
|
||||
}
|
||||
clear_ports(port + 1, last_port - port);
|
||||
|
||||
WRITE_ONCE(execlists->yield, -1);
|
||||
execlists_submit_ports(engine);
|
||||
set_preempt_timeout(engine, *active);
|
||||
} else {
|
||||
@ -3043,7 +3073,7 @@ __execlists_context_pin(struct intel_context *ce,
|
||||
if (IS_ERR(vaddr))
|
||||
return PTR_ERR(vaddr);
|
||||
|
||||
ce->lrc_desc = lrc_descriptor(ce, engine) | CTX_DESC_FORCE_RESTORE;
|
||||
ce->lrc.lrca = lrc_descriptor(ce, engine) | CTX_DESC_FORCE_RESTORE;
|
||||
ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
|
||||
__execlists_update_reg_state(ce, engine, ce->ring->tail);
|
||||
|
||||
@ -3072,7 +3102,7 @@ static void execlists_context_reset(struct intel_context *ce)
|
||||
ce, ce->engine, ce->ring, true);
|
||||
__execlists_update_reg_state(ce, ce->engine, ce->ring->tail);
|
||||
|
||||
ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
|
||||
ce->lrc.desc |= CTX_DESC_FORCE_RESTORE;
|
||||
}
|
||||
|
||||
static const struct intel_context_ops execlists_context_ops = {
|
||||
@ -3541,7 +3571,7 @@ static void enable_execlists(struct intel_engine_cs *engine)
|
||||
|
||||
enable_error_interrupt(engine);
|
||||
|
||||
engine->context_tag = 0;
|
||||
engine->context_tag = GENMASK(BITS_PER_LONG - 2, 0);
|
||||
}
|
||||
|
||||
static bool unexpected_starting_state(struct intel_engine_cs *engine)
|
||||
@ -3753,7 +3783,7 @@ out_replay:
|
||||
head, ce->ring->tail);
|
||||
__execlists_reset_reg_state(ce, engine);
|
||||
__execlists_update_reg_state(ce, engine, head);
|
||||
ce->lrc_desc |= CTX_DESC_FORCE_RESTORE; /* paranoid: GPU was reset! */
|
||||
ce->lrc.desc |= CTX_DESC_FORCE_RESTORE; /* paranoid: GPU was reset! */
|
||||
|
||||
unwind:
|
||||
/* Push back any incomplete requests for replay after the reset. */
|
||||
@ -4369,8 +4399,11 @@ void intel_execlists_set_default_submission(struct intel_engine_cs *engine)
|
||||
engine->flags |= I915_ENGINE_SUPPORTS_STATS;
|
||||
if (!intel_vgpu_active(engine->i915)) {
|
||||
engine->flags |= I915_ENGINE_HAS_SEMAPHORES;
|
||||
if (HAS_LOGICAL_RING_PREEMPTION(engine->i915))
|
||||
if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) {
|
||||
engine->flags |= I915_ENGINE_HAS_PREEMPTION;
|
||||
if (IS_ACTIVE(CONFIG_DRM_I915_TIMESLICE_DURATION))
|
||||
engine->flags |= I915_ENGINE_HAS_TIMESLICES;
|
||||
}
|
||||
}
|
||||
|
||||
if (INTEL_GEN(engine->i915) >= 12)
|
||||
@ -4449,6 +4482,7 @@ logical_ring_default_irqs(struct intel_engine_cs *engine)
|
||||
engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << shift;
|
||||
engine->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift;
|
||||
engine->irq_keep_mask |= GT_CS_MASTER_ERROR_INTERRUPT << shift;
|
||||
engine->irq_keep_mask |= GT_WAIT_SEMAPHORE_INTERRUPT << shift;
|
||||
}
|
||||
|
||||
static void rcs_submission_override(struct intel_engine_cs *engine)
|
||||
@ -4516,6 +4550,11 @@ int intel_execlists_submission_setup(struct intel_engine_cs *engine)
|
||||
else
|
||||
execlists->csb_size = GEN11_CSB_ENTRIES;
|
||||
|
||||
if (INTEL_GEN(engine->i915) >= 11) {
|
||||
execlists->ccid |= engine->instance << (GEN11_ENGINE_INSTANCE_SHIFT - 32);
|
||||
execlists->ccid |= engine->class << (GEN11_ENGINE_CLASS_SHIFT - 32);
|
||||
}
|
||||
|
||||
reset_csb_pointers(engine);
|
||||
|
||||
/* Finally, take ownership and responsibility for cleanup! */
|
||||
|
@ -929,7 +929,7 @@ create_rewinder(struct intel_context *ce,
|
||||
goto err;
|
||||
}
|
||||
|
||||
cs = intel_ring_begin(rq, 10);
|
||||
cs = intel_ring_begin(rq, 14);
|
||||
if (IS_ERR(cs)) {
|
||||
err = PTR_ERR(cs);
|
||||
goto err;
|
||||
@ -941,8 +941,8 @@ create_rewinder(struct intel_context *ce,
|
||||
*cs++ = MI_SEMAPHORE_WAIT |
|
||||
MI_SEMAPHORE_GLOBAL_GTT |
|
||||
MI_SEMAPHORE_POLL |
|
||||
MI_SEMAPHORE_SAD_NEQ_SDD;
|
||||
*cs++ = 0;
|
||||
MI_SEMAPHORE_SAD_GTE_SDD;
|
||||
*cs++ = idx;
|
||||
*cs++ = offset;
|
||||
*cs++ = 0;
|
||||
|
||||
@ -951,6 +951,11 @@ create_rewinder(struct intel_context *ce,
|
||||
*cs++ = offset + idx * sizeof(u32);
|
||||
*cs++ = 0;
|
||||
|
||||
*cs++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT;
|
||||
*cs++ = offset;
|
||||
*cs++ = 0;
|
||||
*cs++ = idx + 1;
|
||||
|
||||
intel_ring_advance(rq, cs);
|
||||
|
||||
rq->sched.attr.priority = I915_PRIORITY_MASK;
|
||||
@ -984,7 +989,7 @@ static int live_timeslice_rewind(void *arg)
|
||||
|
||||
for_each_engine(engine, gt, id) {
|
||||
enum { A1, A2, B1 };
|
||||
enum { X = 1, Y, Z };
|
||||
enum { X = 1, Z, Y };
|
||||
struct i915_request *rq[3] = {};
|
||||
struct intel_context *ce;
|
||||
unsigned long heartbeat;
|
||||
@ -1017,13 +1022,13 @@ static int live_timeslice_rewind(void *arg)
|
||||
goto err;
|
||||
}
|
||||
|
||||
rq[0] = create_rewinder(ce, NULL, slot, 1);
|
||||
rq[0] = create_rewinder(ce, NULL, slot, X);
|
||||
if (IS_ERR(rq[0])) {
|
||||
intel_context_put(ce);
|
||||
goto err;
|
||||
}
|
||||
|
||||
rq[1] = create_rewinder(ce, NULL, slot, 2);
|
||||
rq[1] = create_rewinder(ce, NULL, slot, Y);
|
||||
intel_context_put(ce);
|
||||
if (IS_ERR(rq[1]))
|
||||
goto err;
|
||||
@ -1041,7 +1046,7 @@ static int live_timeslice_rewind(void *arg)
|
||||
goto err;
|
||||
}
|
||||
|
||||
rq[2] = create_rewinder(ce, rq[0], slot, 3);
|
||||
rq[2] = create_rewinder(ce, rq[0], slot, Z);
|
||||
intel_context_put(ce);
|
||||
if (IS_ERR(rq[2]))
|
||||
goto err;
|
||||
@ -1055,15 +1060,12 @@ static int live_timeslice_rewind(void *arg)
|
||||
GEM_BUG_ON(!timer_pending(&engine->execlists.timer));
|
||||
|
||||
/* ELSP[] = { { A:rq1, A:rq2 }, { B:rq1 } } */
|
||||
GEM_BUG_ON(!i915_request_is_active(rq[A1]));
|
||||
GEM_BUG_ON(!i915_request_is_active(rq[A2]));
|
||||
GEM_BUG_ON(!i915_request_is_active(rq[B1]));
|
||||
|
||||
/* Wait for the timeslice to kick in */
|
||||
del_timer(&engine->execlists.timer);
|
||||
tasklet_hi_schedule(&engine->execlists.tasklet);
|
||||
intel_engine_flush_submission(engine);
|
||||
|
||||
if (i915_request_is_active(rq[A2])) { /* semaphore yielded! */
|
||||
/* Wait for the timeslice to kick in */
|
||||
del_timer(&engine->execlists.timer);
|
||||
tasklet_hi_schedule(&engine->execlists.tasklet);
|
||||
intel_engine_flush_submission(engine);
|
||||
}
|
||||
/* -> ELSP[] = { { A:rq1 }, { B:rq1 } } */
|
||||
GEM_BUG_ON(!i915_request_is_active(rq[A1]));
|
||||
GEM_BUG_ON(!i915_request_is_active(rq[B1]));
|
||||
|
@ -217,7 +217,7 @@ static void guc_wq_item_append(struct intel_guc *guc,
|
||||
static void guc_add_request(struct intel_guc *guc, struct i915_request *rq)
|
||||
{
|
||||
struct intel_engine_cs *engine = rq->engine;
|
||||
u32 ctx_desc = lower_32_bits(rq->context->lrc_desc);
|
||||
u32 ctx_desc = rq->context->lrc.ccid;
|
||||
u32 ring_tail = intel_ring_set_tail(rq->ring, rq->tail) / sizeof(u64);
|
||||
|
||||
guc_wq_item_append(guc, engine->guc_id, ctx_desc,
|
||||
|
@ -290,7 +290,7 @@ static void
|
||||
shadow_context_descriptor_update(struct intel_context *ce,
|
||||
struct intel_vgpu_workload *workload)
|
||||
{
|
||||
u64 desc = ce->lrc_desc;
|
||||
u64 desc = ce->lrc.desc;
|
||||
|
||||
/*
|
||||
* Update bits 0-11 of the context descriptor which includes flags
|
||||
@ -300,7 +300,7 @@ shadow_context_descriptor_update(struct intel_context *ce,
|
||||
desc |= (u64)workload->ctx_desc.addressing_mode <<
|
||||
GEN8_CTX_ADDRESSING_MODE_SHIFT;
|
||||
|
||||
ce->lrc_desc = desc;
|
||||
ce->lrc.desc = desc;
|
||||
}
|
||||
|
||||
static int copy_workload_to_ring_buffer(struct intel_vgpu_workload *workload)
|
||||
|
@ -1207,8 +1207,6 @@ static void engine_record_registers(struct intel_engine_coredump *ee)
|
||||
static void record_request(const struct i915_request *request,
|
||||
struct i915_request_coredump *erq)
|
||||
{
|
||||
const struct i915_gem_context *ctx;
|
||||
|
||||
erq->flags = request->fence.flags;
|
||||
erq->context = request->fence.context;
|
||||
erq->seqno = request->fence.seqno;
|
||||
@ -1219,9 +1217,13 @@ static void record_request(const struct i915_request *request,
|
||||
|
||||
erq->pid = 0;
|
||||
rcu_read_lock();
|
||||
ctx = rcu_dereference(request->context->gem_context);
|
||||
if (ctx)
|
||||
erq->pid = pid_nr(ctx->pid);
|
||||
if (!intel_context_is_closed(request->context)) {
|
||||
const struct i915_gem_context *ctx;
|
||||
|
||||
ctx = rcu_dereference(request->context->gem_context);
|
||||
if (ctx)
|
||||
erq->pid = pid_nr(ctx->pid);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
|
@ -3361,7 +3361,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
|
||||
u32 de_pipe_masked = gen8_de_pipe_fault_mask(dev_priv) |
|
||||
GEN8_PIPE_CDCLK_CRC_DONE;
|
||||
u32 de_pipe_enables;
|
||||
u32 de_port_masked = GEN8_AUX_CHANNEL_A;
|
||||
u32 de_port_masked = gen8_de_port_aux_mask(dev_priv);
|
||||
u32 de_port_enables;
|
||||
u32 de_misc_masked = GEN8_DE_EDP_PSR;
|
||||
enum pipe pipe;
|
||||
@ -3369,18 +3369,8 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
|
||||
if (INTEL_GEN(dev_priv) <= 10)
|
||||
de_misc_masked |= GEN8_DE_MISC_GSE;
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 9) {
|
||||
de_port_masked |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C |
|
||||
GEN9_AUX_CHANNEL_D;
|
||||
if (IS_GEN9_LP(dev_priv))
|
||||
de_port_masked |= BXT_DE_PORT_GMBUS;
|
||||
}
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 11)
|
||||
de_port_masked |= ICL_AUX_CHANNEL_E;
|
||||
|
||||
if (IS_CNL_WITH_PORT_F(dev_priv) || INTEL_GEN(dev_priv) >= 11)
|
||||
de_port_masked |= CNL_AUX_CHANNEL_F;
|
||||
if (IS_GEN9_LP(dev_priv))
|
||||
de_port_masked |= BXT_DE_PORT_GMBUS;
|
||||
|
||||
de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK |
|
||||
GEN8_PIPE_FIFO_UNDERRUN;
|
||||
|
@ -1310,8 +1310,7 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
|
||||
* dropped by GuC. They won't be part of the context
|
||||
* ID in the OA reports, so squash those lower bits.
|
||||
*/
|
||||
stream->specific_ctx_id =
|
||||
lower_32_bits(ce->lrc_desc) >> 12;
|
||||
stream->specific_ctx_id = ce->lrc.lrca >> 12;
|
||||
|
||||
/*
|
||||
* GuC uses the top bit to signal proxy submission, so
|
||||
@ -1328,11 +1327,10 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
|
||||
((1U << GEN11_SW_CTX_ID_WIDTH) - 1) << (GEN11_SW_CTX_ID_SHIFT - 32);
|
||||
/*
|
||||
* Pick an unused context id
|
||||
* 0 - (NUM_CONTEXT_TAG - 1) are used by other contexts
|
||||
* 0 - BITS_PER_LONG are used by other contexts
|
||||
* GEN12_MAX_CONTEXT_HW_ID (0x7ff) is used by idle context
|
||||
*/
|
||||
stream->specific_ctx_id = (GEN12_MAX_CONTEXT_HW_ID - 1) << (GEN11_SW_CTX_ID_SHIFT - 32);
|
||||
BUILD_BUG_ON((GEN12_MAX_CONTEXT_HW_ID - 1) < NUM_CONTEXT_TAG);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3094,6 +3094,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
|
||||
#define GT_BSD_CS_ERROR_INTERRUPT (1 << 15)
|
||||
#define GT_BSD_USER_INTERRUPT (1 << 12)
|
||||
#define GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 (1 << 11) /* hsw+; rsvd on snb, ivb, vlv */
|
||||
#define GT_WAIT_SEMAPHORE_INTERRUPT REG_BIT(11) /* bdw+ */
|
||||
#define GT_CONTEXT_SWITCH_INTERRUPT (1 << 8)
|
||||
#define GT_RENDER_L3_PARITY_ERROR_INTERRUPT (1 << 5) /* !snb */
|
||||
#define GT_RENDER_PIPECTL_NOTIFY_INTERRUPT (1 << 4)
|
||||
|
@ -1228,18 +1228,6 @@ int __i915_vma_unbind(struct i915_vma *vma)
|
||||
|
||||
lockdep_assert_held(&vma->vm->mutex);
|
||||
|
||||
/*
|
||||
* First wait upon any activity as retiring the request may
|
||||
* have side-effects such as unpinning or even unbinding this vma.
|
||||
*
|
||||
* XXX Actually waiting under the vm->mutex is a hinderance and
|
||||
* should be pipelined wherever possible. In cases where that is
|
||||
* unavoidable, we should lift the wait to before the mutex.
|
||||
*/
|
||||
ret = i915_vma_sync(vma);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (i915_vma_is_pinned(vma)) {
|
||||
vma_print_allocator(vma, "is pinned");
|
||||
return -EAGAIN;
|
||||
@ -1313,15 +1301,20 @@ int i915_vma_unbind(struct i915_vma *vma)
|
||||
if (!drm_mm_node_allocated(&vma->node))
|
||||
return 0;
|
||||
|
||||
if (i915_vma_is_bound(vma, I915_VMA_GLOBAL_BIND))
|
||||
/* XXX not always required: nop_clear_range */
|
||||
wakeref = intel_runtime_pm_get(&vm->i915->runtime_pm);
|
||||
|
||||
/* Optimistic wait before taking the mutex */
|
||||
err = i915_vma_sync(vma);
|
||||
if (err)
|
||||
goto out_rpm;
|
||||
|
||||
if (i915_vma_is_pinned(vma)) {
|
||||
vma_print_allocator(vma, "is pinned");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (i915_vma_is_bound(vma, I915_VMA_GLOBAL_BIND))
|
||||
/* XXX not always required: nop_clear_range */
|
||||
wakeref = intel_runtime_pm_get(&vm->i915->runtime_pm);
|
||||
|
||||
err = mutex_lock_interruptible(&vm->mutex);
|
||||
if (err)
|
||||
goto out_rpm;
|
||||
|
@ -4992,7 +4992,7 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state,
|
||||
* WaIncreaseLatencyIPCEnabled: kbl,cfl
|
||||
* Display WA #1141: kbl,cfl
|
||||
*/
|
||||
if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) ||
|
||||
if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) &&
|
||||
dev_priv->ipc_enabled)
|
||||
latency += 4;
|
||||
|
||||
|
@ -173,7 +173,7 @@ static int igt_vma_create(void *arg)
|
||||
}
|
||||
|
||||
nc = 0;
|
||||
for_each_prime_number(num_ctx, 2 * NUM_CONTEXT_TAG) {
|
||||
for_each_prime_number(num_ctx, 2 * BITS_PER_LONG) {
|
||||
for (; nc < num_ctx; nc++) {
|
||||
ctx = mock_context(i915, "mock");
|
||||
if (!ctx)
|
||||
|
Loading…
x
Reference in New Issue
Block a user