forked from Minki/linux
Fixes for instability on Baytrail and Haswell;
Ice Lake RPS; Sandy Bridge RC6; and few others around GT hangchec/reset; livelock; and a null dereference. -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEbSBwaO7dZQkcLOKj+mJfZA7rE8oFAl59tisACgkQ+mJfZA7r E8rKBgf/Vo+ZCQ33KLmthESO1QCENOd3QNknwZ454/rTM611x1x/xQ+j9Cv9z742 /oshYQyPzbqjDE8TYl77MYKPdn93EIfVlJOj1jmwlYms1WUlLAkIR7HgBydB0j3L W0WMBw5BQ5b15leS/MlAJ1CKj/M6hX5pWYNGoxa8A/q3kErQFAw22J/XuvrSvKLc lHcwLsLCq6O5M3xe1ztZZ/T5Kh1lKgTWZhG/jchxMe0Lr7R+CPUM7unU9kcBX3ml gEFIm2a4aH6ARnq8QHnu0ziyzOP13O2DZ27+xjtKP/NlFABC8XbFlj/N13kumfuk uKMwX2O8PcZykStYyINc1DIL1FJmog== =2wdN -----END PGP SIGNATURE----- Merge tag 'drm-intel-next-fixes-2020-03-27' of git://anongit.freedesktop.org/drm/drm-intel into drm-next Fixes for instability on Baytrail and Haswell; Ice Lake RPS; Sandy Bridge RC6; and few others around GT hangchec/reset; livelock; and a null dereference. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Rodrigo Vivi <rodrigo.vivi@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200327081607.GA3082710@intel.com
This commit is contained in:
commit
700d6ab987
@ -14748,8 +14748,8 @@ static int intel_atomic_check(struct drm_device *dev,
|
||||
/* Catch I915_MODE_FLAG_INHERITED */
|
||||
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
|
||||
new_crtc_state, i) {
|
||||
if (new_crtc_state->hw.mode.private_flags !=
|
||||
old_crtc_state->hw.mode.private_flags)
|
||||
if (new_crtc_state->uapi.mode.private_flags !=
|
||||
old_crtc_state->uapi.mode.private_flags)
|
||||
new_crtc_state->uapi.mode_changed = true;
|
||||
}
|
||||
|
||||
|
@ -574,7 +574,7 @@ static void engines_idle_release(struct i915_gem_context *ctx,
|
||||
int err = 0;
|
||||
|
||||
/* serialises with execbuf */
|
||||
RCU_INIT_POINTER(ce->gem_context, NULL);
|
||||
set_bit(CONTEXT_CLOSED_BIT, &ce->flags);
|
||||
if (!intel_context_pin_if_active(ce))
|
||||
continue;
|
||||
|
||||
|
@ -192,12 +192,16 @@ i915_gem_context_unlock_engines(struct i915_gem_context *ctx)
|
||||
static inline struct intel_context *
|
||||
i915_gem_context_get_engine(struct i915_gem_context *ctx, unsigned int idx)
|
||||
{
|
||||
struct intel_context *ce = ERR_PTR(-EINVAL);
|
||||
struct intel_context *ce;
|
||||
|
||||
rcu_read_lock(); {
|
||||
struct i915_gem_engines *e = rcu_dereference(ctx->engines);
|
||||
if (likely(idx < e->num_engines && e->engines[idx]))
|
||||
if (unlikely(!e)) /* context was closed! */
|
||||
ce = ERR_PTR(-ENOENT);
|
||||
else if (likely(idx < e->num_engines && e->engines[idx]))
|
||||
ce = intel_context_get(e->engines[idx]);
|
||||
else
|
||||
ce = ERR_PTR(-EINVAL);
|
||||
} rcu_read_unlock();
|
||||
|
||||
return ce;
|
||||
|
@ -2316,7 +2316,7 @@ static void eb_request_add(struct i915_execbuffer *eb)
|
||||
prev = __i915_request_commit(rq);
|
||||
|
||||
/* Check that the context wasn't destroyed before submission */
|
||||
if (likely(rcu_access_pointer(eb->context->gem_context))) {
|
||||
if (likely(!intel_context_is_closed(eb->context))) {
|
||||
attr = eb->gem_context->sched;
|
||||
|
||||
/*
|
||||
|
@ -97,6 +97,8 @@ int __intel_context_do_pin(struct intel_context *ce)
|
||||
{
|
||||
int err;
|
||||
|
||||
GEM_BUG_ON(intel_context_is_closed(ce));
|
||||
|
||||
if (unlikely(!test_bit(CONTEXT_ALLOC_BIT, &ce->flags))) {
|
||||
err = intel_context_alloc_state(ce);
|
||||
if (err)
|
||||
|
@ -173,6 +173,11 @@ static inline bool intel_context_is_barrier(const struct intel_context *ce)
|
||||
return test_bit(CONTEXT_BARRIER_BIT, &ce->flags);
|
||||
}
|
||||
|
||||
static inline bool intel_context_is_closed(const struct intel_context *ce)
|
||||
{
|
||||
return test_bit(CONTEXT_CLOSED_BIT, &ce->flags);
|
||||
}
|
||||
|
||||
static inline bool intel_context_use_semaphores(const struct intel_context *ce)
|
||||
{
|
||||
return test_bit(CONTEXT_USE_SEMAPHORES, &ce->flags);
|
||||
|
@ -62,10 +62,11 @@ struct intel_context {
|
||||
#define CONTEXT_BARRIER_BIT 0
|
||||
#define CONTEXT_ALLOC_BIT 1
|
||||
#define CONTEXT_VALID_BIT 2
|
||||
#define CONTEXT_USE_SEMAPHORES 3
|
||||
#define CONTEXT_BANNED 4
|
||||
#define CONTEXT_FORCE_SINGLE_SUBMISSION 5
|
||||
#define CONTEXT_NOPREEMPT 6
|
||||
#define CONTEXT_CLOSED_BIT 3
|
||||
#define CONTEXT_USE_SEMAPHORES 4
|
||||
#define CONTEXT_BANNED 5
|
||||
#define CONTEXT_FORCE_SINGLE_SUBMISSION 6
|
||||
#define CONTEXT_NOPREEMPT 7
|
||||
|
||||
u32 *lrc_reg_state;
|
||||
u64 lrc_desc;
|
||||
|
@ -1663,7 +1663,7 @@ static bool virtual_matches(const struct virtual_engine *ve,
|
||||
}
|
||||
|
||||
static void virtual_xfer_breadcrumbs(struct virtual_engine *ve,
|
||||
struct intel_engine_cs *engine)
|
||||
struct i915_request *rq)
|
||||
{
|
||||
struct intel_engine_cs *old = ve->siblings[0];
|
||||
|
||||
@ -1671,9 +1671,19 @@ static void virtual_xfer_breadcrumbs(struct virtual_engine *ve,
|
||||
|
||||
spin_lock(&old->breadcrumbs.irq_lock);
|
||||
if (!list_empty(&ve->context.signal_link)) {
|
||||
list_move_tail(&ve->context.signal_link,
|
||||
&engine->breadcrumbs.signalers);
|
||||
intel_engine_signal_breadcrumbs(engine);
|
||||
list_del_init(&ve->context.signal_link);
|
||||
|
||||
/*
|
||||
* We cannot acquire the new engine->breadcrumbs.irq_lock
|
||||
* (as we are holding a breadcrumbs.irq_lock already),
|
||||
* so attach this request to the signaler on submission.
|
||||
* The queued irq_work will occur when we finally drop
|
||||
* the engine->active.lock after dequeue.
|
||||
*/
|
||||
set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &rq->fence.flags);
|
||||
|
||||
/* Also transfer the pending irq_work for the old breadcrumb. */
|
||||
intel_engine_signal_breadcrumbs(rq->engine);
|
||||
}
|
||||
spin_unlock(&old->breadcrumbs.irq_lock);
|
||||
}
|
||||
@ -2045,7 +2055,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
|
||||
engine);
|
||||
|
||||
if (!list_empty(&ve->context.signals))
|
||||
virtual_xfer_breadcrumbs(ve, engine);
|
||||
virtual_xfer_breadcrumbs(ve, rq);
|
||||
|
||||
/*
|
||||
* Move the bound engine to the top of the list
|
||||
|
@ -603,6 +603,7 @@ void intel_rc6_unpark(struct intel_rc6 *rc6)
|
||||
void intel_rc6_park(struct intel_rc6 *rc6)
|
||||
{
|
||||
struct intel_uncore *uncore = rc6_to_uncore(rc6);
|
||||
unsigned int target;
|
||||
|
||||
if (!rc6->enabled)
|
||||
return;
|
||||
@ -617,7 +618,14 @@ void intel_rc6_park(struct intel_rc6 *rc6)
|
||||
|
||||
/* Turn off the HW timers and go directly to rc6 */
|
||||
set(uncore, GEN6_RC_CONTROL, GEN6_RC_CTL_RC6_ENABLE);
|
||||
set(uncore, GEN6_RC_STATE, 0x4 << RC_SW_TARGET_STATE_SHIFT);
|
||||
|
||||
if (HAS_RC6pp(rc6_to_i915(rc6)))
|
||||
target = 0x6; /* deepest rc6 */
|
||||
else if (HAS_RC6p(rc6_to_i915(rc6)))
|
||||
target = 0x5; /* deep rc6 */
|
||||
else
|
||||
target = 0x4; /* normal rc6 */
|
||||
set(uncore, GEN6_RC_STATE, target << RC_SW_TARGET_STATE_SHIFT);
|
||||
}
|
||||
|
||||
void intel_rc6_disable(struct intel_rc6 *rc6)
|
||||
|
@ -88,6 +88,11 @@ static bool mark_guilty(struct i915_request *rq)
|
||||
bool banned;
|
||||
int i;
|
||||
|
||||
if (intel_context_is_closed(rq->context)) {
|
||||
intel_context_set_banned(rq->context);
|
||||
return true;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
ctx = rcu_dereference(rq->context->gem_context);
|
||||
if (ctx && !kref_get_unless_zero(&ctx->ref))
|
||||
|
@ -2088,7 +2088,7 @@ int intel_ring_submission_setup(struct intel_engine_cs *engine)
|
||||
|
||||
GEM_BUG_ON(timeline->hwsp_ggtt != engine->status_page.vma);
|
||||
|
||||
if (IS_GEN(engine->i915, 7) && engine->class == RENDER_CLASS) {
|
||||
if (IS_HASWELL(engine->i915) && engine->class == RENDER_CLASS) {
|
||||
err = gen7_ctx_switch_bb_init(engine);
|
||||
if (err)
|
||||
goto err_ring_unpin;
|
||||
|
@ -770,6 +770,19 @@ void intel_rps_park(struct intel_rps *rps)
|
||||
intel_uncore_forcewake_get(rps_to_uncore(rps), FORCEWAKE_MEDIA);
|
||||
rps_set(rps, rps->idle_freq, false);
|
||||
intel_uncore_forcewake_put(rps_to_uncore(rps), FORCEWAKE_MEDIA);
|
||||
|
||||
/*
|
||||
* Since we will try and restart from the previously requested
|
||||
* frequency on unparking, treat this idle point as a downclock
|
||||
* interrupt and reduce the frequency for resume. If we park/unpark
|
||||
* more frequently than the rps worker can run, we will not respond
|
||||
* to any EI and never see a change in frequency.
|
||||
*
|
||||
* (Note we accommodate Cherryview's limitation of only using an
|
||||
* even bin by applying it to all.)
|
||||
*/
|
||||
rps->cur_freq =
|
||||
max_t(int, round_down(rps->cur_freq - 1, 2), rps->min_freq);
|
||||
}
|
||||
|
||||
void intel_rps_boost(struct i915_request *rq)
|
||||
|
@ -12,6 +12,21 @@
|
||||
|
||||
#include "selftests/i915_random.h"
|
||||
|
||||
static u64 rc6_residency(struct intel_rc6 *rc6)
|
||||
{
|
||||
u64 result;
|
||||
|
||||
/* XXX VLV_GT_MEDIA_RC6? */
|
||||
|
||||
result = intel_rc6_residency_ns(rc6, GEN6_GT_GFX_RC6);
|
||||
if (HAS_RC6p(rc6_to_i915(rc6)))
|
||||
result += intel_rc6_residency_ns(rc6, GEN6_GT_GFX_RC6p);
|
||||
if (HAS_RC6pp(rc6_to_i915(rc6)))
|
||||
result += intel_rc6_residency_ns(rc6, GEN6_GT_GFX_RC6pp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int live_rc6_manual(void *arg)
|
||||
{
|
||||
struct intel_gt *gt = arg;
|
||||
@ -38,9 +53,9 @@ int live_rc6_manual(void *arg)
|
||||
__intel_rc6_disable(rc6);
|
||||
msleep(1); /* wakeup is not immediate, takes about 100us on icl */
|
||||
|
||||
res[0] = intel_rc6_residency_ns(rc6, GEN6_GT_GFX_RC6);
|
||||
res[0] = rc6_residency(rc6);
|
||||
msleep(250);
|
||||
res[1] = intel_rc6_residency_ns(rc6, GEN6_GT_GFX_RC6);
|
||||
res[1] = rc6_residency(rc6);
|
||||
if ((res[1] - res[0]) >> 10) {
|
||||
pr_err("RC6 residency increased by %lldus while disabled for 250ms!\n",
|
||||
(res[1] - res[0]) >> 10);
|
||||
@ -51,9 +66,9 @@ int live_rc6_manual(void *arg)
|
||||
/* Manually enter RC6 */
|
||||
intel_rc6_park(rc6);
|
||||
|
||||
res[0] = intel_rc6_residency_ns(rc6, GEN6_GT_GFX_RC6);
|
||||
res[0] = rc6_residency(rc6);
|
||||
msleep(100);
|
||||
res[1] = intel_rc6_residency_ns(rc6, GEN6_GT_GFX_RC6);
|
||||
res[1] = rc6_residency(rc6);
|
||||
|
||||
if (res[1] == res[0]) {
|
||||
pr_err("Did not enter RC6! RC6_STATE=%08x, RC6_CONTROL=%08x, residency=%lld\n",
|
||||
|
@ -2700,6 +2700,14 @@ static void gen12_oa_disable(struct i915_perf_stream *stream)
|
||||
50))
|
||||
drm_err(&stream->perf->i915->drm,
|
||||
"wait for OA to be disabled timed out\n");
|
||||
|
||||
intel_uncore_write(uncore, GEN12_OA_TLB_INV_CR, 1);
|
||||
if (intel_wait_for_register(uncore,
|
||||
GEN12_OA_TLB_INV_CR,
|
||||
1, 0,
|
||||
50))
|
||||
drm_err(&stream->perf->i915->drm,
|
||||
"wait for OA tlb invalidate timed out\n");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -693,6 +693,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
|
||||
#define OABUFFER_SIZE_8M (6 << 3)
|
||||
#define OABUFFER_SIZE_16M (7 << 3)
|
||||
|
||||
#define GEN12_OA_TLB_INV_CR _MMIO(0xceec)
|
||||
|
||||
/* Gen12 OAR unit */
|
||||
#define GEN12_OAR_OACONTROL _MMIO(0x2960)
|
||||
#define GEN12_OAR_OACONTROL_COUNTER_FORMAT_SHIFT 1
|
||||
|
@ -1097,6 +1097,7 @@ void i915_vma_release(struct kref *ref)
|
||||
void i915_vma_parked(struct intel_gt *gt)
|
||||
{
|
||||
struct i915_vma *vma, *next;
|
||||
LIST_HEAD(closed);
|
||||
|
||||
spin_lock_irq(>->closed_lock);
|
||||
list_for_each_entry_safe(vma, next, >->closed_vma, closed_link) {
|
||||
@ -1108,28 +1109,26 @@ void i915_vma_parked(struct intel_gt *gt)
|
||||
if (!kref_get_unless_zero(&obj->base.refcount))
|
||||
continue;
|
||||
|
||||
if (i915_vm_tryopen(vm)) {
|
||||
list_del_init(&vma->closed_link);
|
||||
} else {
|
||||
if (!i915_vm_tryopen(vm)) {
|
||||
i915_gem_object_put(obj);
|
||||
obj = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
spin_unlock_irq(>->closed_lock);
|
||||
|
||||
if (obj) {
|
||||
__i915_vma_put(vma);
|
||||
i915_gem_object_put(obj);
|
||||
}
|
||||
|
||||
i915_vm_close(vm);
|
||||
|
||||
/* Restart after dropping lock */
|
||||
spin_lock_irq(>->closed_lock);
|
||||
next = list_first_entry(>->closed_vma,
|
||||
typeof(*next), closed_link);
|
||||
list_move(&vma->closed_link, &closed);
|
||||
}
|
||||
spin_unlock_irq(>->closed_lock);
|
||||
|
||||
/* As the GT is held idle, no vma can be reopened as we destroy them */
|
||||
list_for_each_entry_safe(vma, next, &closed, closed_link) {
|
||||
struct drm_i915_gem_object *obj = vma->obj;
|
||||
struct i915_address_space *vm = vma->vm;
|
||||
|
||||
INIT_LIST_HEAD(&vma->closed_link);
|
||||
__i915_vma_put(vma);
|
||||
|
||||
i915_gem_object_put(obj);
|
||||
i915_vm_close(vm);
|
||||
}
|
||||
}
|
||||
|
||||
static void __i915_vma_iounmap(struct i915_vma *vma)
|
||||
|
Loading…
Reference in New Issue
Block a user