Skip to content

Commit 5b26d57

Browse files
aditya23788mattrope
authored andcommitted
drm/i915: Add Wa_14010733141
The WA requires the following procedure for VDBox SFC reset: If (MFX-SFC usage is 1) { 1.Issue a MFX-SFC forced lock 2.Wait for MFX-SFC forced lock ack 3.Check the MFX-SFC usage bit If (MFX-SFC usage bit is 1) Reset VDBOX and SFC else Reset VDBOX Release the force lock MFX-SFC } else if(HCP+SFC usage is 1) { 1.Issue a VE-SFC forced lock 2.Wait for SFC forced lock ack 3.Check the VE-SFC usage bit If (VE-SFC usage bit is 1) Reset VDBOX else Reset VDBOX and SFC Release the force lock VE-SFC. } else Reset VDBOX - Restructure: the changes to the original code flow should stay relatively minimal; we only need to do an extra HCP check after the usual VD-MFX check and, if true, switch the register/bit we're performing the lock on.(MattR) v2: - Assign unlock mask using paired_engine->mask instead of using BIT(paired_vecs->id). (Daniele) Bspec: 52890, 53509 Cc: Tvrtko Ursulin <[email protected]> Cc: Matt Roper <[email protected]> Cc: Daniele Ceraolo Spurio <[email protected]> Cc: Lucas De Marchi <[email protected]> Signed-off-by: Aditya Swarup <[email protected]> Co-developed-by: Matt Roper <[email protected]> Signed-off-by: Matt Roper <[email protected]> Reviewed-by: Daniele Ceraolo Spurio <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 6151603 commit 5b26d57

File tree

2 files changed

+137
-63
lines changed

2 files changed

+137
-63
lines changed

drivers/gpu/drm/i915/gt/intel_reset.c

Lines changed: 131 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -338,106 +338,170 @@ static int gen6_reset_engines(struct intel_gt *gt,
338338
return gen6_hw_domain_reset(gt, hw_mask);
339339
}
340340

341-
static int gen11_lock_sfc(struct intel_engine_cs *engine, u32 *hw_mask)
341+
static struct intel_engine_cs *find_sfc_paired_vecs_engine(struct intel_engine_cs *engine)
342+
{
343+
int vecs_id;
344+
345+
GEM_BUG_ON(engine->class != VIDEO_DECODE_CLASS);
346+
347+
vecs_id = _VECS((engine->instance) / 2);
348+
349+
return engine->gt->engine[vecs_id];
350+
}
351+
352+
struct sfc_lock_data {
353+
i915_reg_t lock_reg;
354+
i915_reg_t ack_reg;
355+
i915_reg_t usage_reg;
356+
u32 lock_bit;
357+
u32 ack_bit;
358+
u32 usage_bit;
359+
u32 reset_bit;
360+
};
361+
362+
static void get_sfc_forced_lock_data(struct intel_engine_cs *engine,
363+
struct sfc_lock_data *sfc_lock)
364+
{
365+
switch (engine->class) {
366+
default:
367+
MISSING_CASE(engine->class);
368+
fallthrough;
369+
case VIDEO_DECODE_CLASS:
370+
sfc_lock->lock_reg = GEN11_VCS_SFC_FORCED_LOCK(engine);
371+
sfc_lock->lock_bit = GEN11_VCS_SFC_FORCED_LOCK_BIT;
372+
373+
sfc_lock->ack_reg = GEN11_VCS_SFC_LOCK_STATUS(engine);
374+
sfc_lock->ack_bit = GEN11_VCS_SFC_LOCK_ACK_BIT;
375+
376+
sfc_lock->usage_reg = GEN11_VCS_SFC_LOCK_STATUS(engine);
377+
sfc_lock->usage_bit = GEN11_VCS_SFC_USAGE_BIT;
378+
sfc_lock->reset_bit = GEN11_VCS_SFC_RESET_BIT(engine->instance);
379+
380+
break;
381+
case VIDEO_ENHANCEMENT_CLASS:
382+
sfc_lock->lock_reg = GEN11_VECS_SFC_FORCED_LOCK(engine);
383+
sfc_lock->lock_bit = GEN11_VECS_SFC_FORCED_LOCK_BIT;
384+
385+
sfc_lock->ack_reg = GEN11_VECS_SFC_LOCK_ACK(engine);
386+
sfc_lock->ack_bit = GEN11_VECS_SFC_LOCK_ACK_BIT;
387+
388+
sfc_lock->usage_reg = GEN11_VECS_SFC_USAGE(engine);
389+
sfc_lock->usage_bit = GEN11_VECS_SFC_USAGE_BIT;
390+
sfc_lock->reset_bit = GEN11_VECS_SFC_RESET_BIT(engine->instance);
391+
392+
break;
393+
}
394+
}
395+
396+
static int gen11_lock_sfc(struct intel_engine_cs *engine,
397+
u32 *reset_mask,
398+
u32 *unlock_mask)
342399
{
343400
struct intel_uncore *uncore = engine->uncore;
344401
u8 vdbox_sfc_access = engine->gt->info.vdbox_sfc_access;
345-
i915_reg_t sfc_forced_lock, sfc_forced_lock_ack;
346-
u32 sfc_forced_lock_bit, sfc_forced_lock_ack_bit;
347-
i915_reg_t sfc_usage;
348-
u32 sfc_usage_bit;
349-
u32 sfc_reset_bit;
402+
struct sfc_lock_data sfc_lock;
403+
bool lock_obtained, lock_to_other = false;
350404
int ret;
351405

352406
switch (engine->class) {
353407
case VIDEO_DECODE_CLASS:
354408
if ((BIT(engine->instance) & vdbox_sfc_access) == 0)
355409
return 0;
356410

357-
sfc_forced_lock = GEN11_VCS_SFC_FORCED_LOCK(engine);
358-
sfc_forced_lock_bit = GEN11_VCS_SFC_FORCED_LOCK_BIT;
359-
360-
sfc_forced_lock_ack = GEN11_VCS_SFC_LOCK_STATUS(engine);
361-
sfc_forced_lock_ack_bit = GEN11_VCS_SFC_LOCK_ACK_BIT;
411+
fallthrough;
412+
case VIDEO_ENHANCEMENT_CLASS:
413+
get_sfc_forced_lock_data(engine, &sfc_lock);
362414

363-
sfc_usage = GEN11_VCS_SFC_LOCK_STATUS(engine);
364-
sfc_usage_bit = GEN11_VCS_SFC_USAGE_BIT;
365-
sfc_reset_bit = GEN11_VCS_SFC_RESET_BIT(engine->instance);
366415
break;
416+
default:
417+
return 0;
418+
}
367419

368-
case VIDEO_ENHANCEMENT_CLASS:
369-
sfc_forced_lock = GEN11_VECS_SFC_FORCED_LOCK(engine);
370-
sfc_forced_lock_bit = GEN11_VECS_SFC_FORCED_LOCK_BIT;
420+
if (!(intel_uncore_read_fw(uncore, sfc_lock.usage_reg) & sfc_lock.usage_bit)) {
421+
struct intel_engine_cs *paired_vecs;
371422

372-
sfc_forced_lock_ack = GEN11_VECS_SFC_LOCK_ACK(engine);
373-
sfc_forced_lock_ack_bit = GEN11_VECS_SFC_LOCK_ACK_BIT;
423+
if (engine->class != VIDEO_DECODE_CLASS ||
424+
!IS_GEN(engine->i915, 12))
425+
return 0;
374426

375-
sfc_usage = GEN11_VECS_SFC_USAGE(engine);
376-
sfc_usage_bit = GEN11_VECS_SFC_USAGE_BIT;
377-
sfc_reset_bit = GEN11_VECS_SFC_RESET_BIT(engine->instance);
378-
break;
427+
/*
428+
* Wa_14010733141
429+
*
430+
* If the VCS-MFX isn't using the SFC, we also need to check
431+
* whether VCS-HCP is using it. If so, we need to issue a *VE*
432+
* forced lock on the VE engine that shares the same SFC.
433+
*/
434+
if (!(intel_uncore_read_fw(uncore,
435+
GEN12_HCP_SFC_LOCK_STATUS(engine)) &
436+
GEN12_HCP_SFC_USAGE_BIT))
437+
return 0;
379438

380-
default:
381-
return 0;
439+
paired_vecs = find_sfc_paired_vecs_engine(engine);
440+
get_sfc_forced_lock_data(paired_vecs, &sfc_lock);
441+
lock_to_other = true;
442+
*unlock_mask |= paired_vecs->mask;
443+
} else {
444+
*unlock_mask |= engine->mask;
382445
}
383446

384447
/*
385-
* If the engine is using a SFC, tell the engine that a software reset
448+
* If the engine is using an SFC, tell the engine that a software reset
386449
* is going to happen. The engine will then try to force lock the SFC.
387450
* If SFC ends up being locked to the engine we want to reset, we have
388451
* to reset it as well (we will unlock it once the reset sequence is
389452
* completed).
390453
*/
391-
if (!(intel_uncore_read_fw(uncore, sfc_usage) & sfc_usage_bit))
392-
return 0;
393-
394-
rmw_set_fw(uncore, sfc_forced_lock, sfc_forced_lock_bit);
454+
rmw_set_fw(uncore, sfc_lock.lock_reg, sfc_lock.lock_bit);
395455

396456
ret = __intel_wait_for_register_fw(uncore,
397-
sfc_forced_lock_ack,
398-
sfc_forced_lock_ack_bit,
399-
sfc_forced_lock_ack_bit,
457+
sfc_lock.ack_reg,
458+
sfc_lock.ack_bit,
459+
sfc_lock.ack_bit,
400460
1000, 0, NULL);
401461

402-
/* Was the SFC released while we were trying to lock it? */
403-
if (!(intel_uncore_read_fw(uncore, sfc_usage) & sfc_usage_bit))
462+
/*
463+
* Was the SFC released while we were trying to lock it?
464+
*
465+
* We should reset both the engine and the SFC if:
466+
* - We were locking the SFC to this engine and the lock succeeded
467+
* OR
468+
* - We were locking the SFC to a different engine (Wa_14010733141)
469+
* but the SFC was released before the lock was obtained.
470+
*
471+
* Otherwise we need only reset the engine by itself and we can
472+
* leave the SFC alone.
473+
*/
474+
lock_obtained = (intel_uncore_read_fw(uncore, sfc_lock.usage_reg) &
475+
sfc_lock.usage_bit) != 0;
476+
if (lock_obtained == lock_to_other)
404477
return 0;
405478

406479
if (ret) {
407480
ENGINE_TRACE(engine, "Wait for SFC forced lock ack failed\n");
408481
return ret;
409482
}
410483

411-
*hw_mask |= sfc_reset_bit;
484+
*reset_mask |= sfc_lock.reset_bit;
412485
return 0;
413486
}
414487

415488
static void gen11_unlock_sfc(struct intel_engine_cs *engine)
416489
{
417490
struct intel_uncore *uncore = engine->uncore;
418491
u8 vdbox_sfc_access = engine->gt->info.vdbox_sfc_access;
419-
i915_reg_t sfc_forced_lock;
420-
u32 sfc_forced_lock_bit;
421-
422-
switch (engine->class) {
423-
case VIDEO_DECODE_CLASS:
424-
if ((BIT(engine->instance) & vdbox_sfc_access) == 0)
425-
return;
426-
427-
sfc_forced_lock = GEN11_VCS_SFC_FORCED_LOCK(engine);
428-
sfc_forced_lock_bit = GEN11_VCS_SFC_FORCED_LOCK_BIT;
429-
break;
492+
struct sfc_lock_data sfc_lock = {};
430493

431-
case VIDEO_ENHANCEMENT_CLASS:
432-
sfc_forced_lock = GEN11_VECS_SFC_FORCED_LOCK(engine);
433-
sfc_forced_lock_bit = GEN11_VECS_SFC_FORCED_LOCK_BIT;
434-
break;
494+
if (engine->class != VIDEO_DECODE_CLASS &&
495+
engine->class != VIDEO_ENHANCEMENT_CLASS)
496+
return;
435497

436-
default:
498+
if (engine->class == VIDEO_DECODE_CLASS &&
499+
(BIT(engine->instance) & vdbox_sfc_access) == 0)
437500
return;
438-
}
439501

440-
rmw_clear_fw(uncore, sfc_forced_lock, sfc_forced_lock_bit);
502+
get_sfc_forced_lock_data(engine, &sfc_lock);
503+
504+
rmw_clear_fw(uncore, sfc_lock.lock_reg, sfc_lock.lock_bit);
441505
}
442506

443507
static int gen11_reset_engines(struct intel_gt *gt,
@@ -456,34 +520,38 @@ static int gen11_reset_engines(struct intel_gt *gt,
456520
};
457521
struct intel_engine_cs *engine;
458522
intel_engine_mask_t tmp;
459-
u32 hw_mask;
523+
u32 reset_mask, unlock_mask = 0;
460524
int ret;
461525

462526
if (engine_mask == ALL_ENGINES) {
463-
hw_mask = GEN11_GRDOM_FULL;
527+
reset_mask = GEN11_GRDOM_FULL;
464528
} else {
465-
hw_mask = 0;
529+
reset_mask = 0;
466530
for_each_engine_masked(engine, gt, engine_mask, tmp) {
467531
GEM_BUG_ON(engine->id >= ARRAY_SIZE(hw_engine_mask));
468-
hw_mask |= hw_engine_mask[engine->id];
469-
ret = gen11_lock_sfc(engine, &hw_mask);
532+
reset_mask |= hw_engine_mask[engine->id];
533+
ret = gen11_lock_sfc(engine, &reset_mask, &unlock_mask);
470534
if (ret)
471535
goto sfc_unlock;
472536
}
473537
}
474538

475-
ret = gen6_hw_domain_reset(gt, hw_mask);
539+
ret = gen6_hw_domain_reset(gt, reset_mask);
476540

477541
sfc_unlock:
478542
/*
479543
* We unlock the SFC based on the lock status and not the result of
480544
* gen11_lock_sfc to make sure that we clean properly if something
481545
* wrong happened during the lock (e.g. lock acquired after timeout
482546
* expiration).
547+
*
548+
* Due to Wa_14010733141, we may have locked an SFC to an engine that
549+
* wasn't being reset. So instead of calling gen11_unlock_sfc()
550+
* on engine_mask, we instead call it on the mask of engines that our
551+
* gen11_lock_sfc() calls told us actually had locks attempted.
483552
*/
484-
if (engine_mask != ALL_ENGINES)
485-
for_each_engine_masked(engine, gt, engine_mask, tmp)
486-
gen11_unlock_sfc(engine);
553+
for_each_engine_masked(engine, gt, unlock_mask, tmp)
554+
gen11_unlock_sfc(engine);
487555

488556
return ret;
489557
}

drivers/gpu/drm/i915/i915_reg.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,12 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
416416
#define GEN11_VECS_SFC_USAGE(engine) _MMIO((engine)->mmio_base + 0x2014)
417417
#define GEN11_VECS_SFC_USAGE_BIT (1 << 0)
418418

419+
#define GEN12_HCP_SFC_FORCED_LOCK(engine) _MMIO((engine)->mmio_base + 0x2910)
420+
#define GEN12_HCP_SFC_FORCED_LOCK_BIT REG_BIT(0)
421+
#define GEN12_HCP_SFC_LOCK_STATUS(engine) _MMIO((engine)->mmio_base + 0x2914)
422+
#define GEN12_HCP_SFC_LOCK_ACK_BIT REG_BIT(1)
423+
#define GEN12_HCP_SFC_USAGE_BIT REG_BIT(0)
424+
419425
#define GEN12_SFC_DONE(n) _MMIO(0x1cc00 + (n) * 0x100)
420426
#define GEN12_SFC_DONE_MAX 4
421427

0 commit comments

Comments
 (0)