[RFC] tentative fix for drm/i915/gt regression on preempt-rt

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Back in September, I reported a PM regression pinpointed by bisect:

https://lore.kernel.org/linux-rt-users/20220916181934.GA16961@xxxxxxxxxxxxx/T/#u

Around Feb, I checked and didn't see any relevant mainline changes, so I
decided to take a look at it myself, which is when I saw the eight patches
from Sebastian that included a trial of converting the uncore->lock to raw:

https://lore.kernel.org/all/20211006164628.s2mtsdd2jdbfyf7g@xxxxxxxxxxxxx/

With a focus on just the suspend/resume regression reported through me, I
thought I had a way to perhaps at least fix that one issue.  I didn't have
the right hardware to reproduce it, but I was pretty sure it was clear what
was happening (as per details in the commit log)

I was pretty sure my change would fix the BUG() but since I've never touched
i915 before, I couldn't quite be 100% confident my reasoning wasn't opening
a door to some other locking issue.  So I put it in our internal soak pool
late March and since it fixed the BUG() and didn't trigger any new splat,
I'd largely forgot about it.

OK, with all that context, I'll finally get to the point.  It would be nice
if others who have worked on i915/rt can take a look at it and pick it apart.

This is still the v5.15-rt version, but I just checked mainline and also
linux-rt-devel and I'm not seeing any reason to believe it was fixed yet.

(Oh, and I'm told the impacted board is NUC7i5DNK1E -- and others?)

Thanks,
Paul.

--

>From 20200bee7252d4c9c2a748a9e90fba33f2da9734 Mon Sep 17 00:00:00 2001
From: Paul Gortmaker <paul.gortmaker@xxxxxxxxxxxxx>
Date: Thu, 9 Feb 2023 21:42:25 -0500
Subject: [PATCH] drm/i915/gt: don't use preempt_disable/enable around reset
 call

It turns out that a relatively recent commit breaks PM-suspend
operations on preempt-rt, on multiple versions, due to all the
linux-stable backports, including this v5.15 one:

  commit 0ee5874dad61d2b154a9e3db196fc33e8208ce1b
  Author: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
  Date:   Tue Jul 12 16:21:32 2022 +0100

    drm/i915/gt: Serialize GRDOM access between multiple engine resets

    [ Upstream commit b24dcf1dc507f69ed3b5c66c2b6a0209ae80d4d4 ]

Below is an example of the regression on v5.15-rt, with backport:

  BUG: sleeping function called from invalid context at kernel/locking/spinlock_rt.c:46
  in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 45092, name: kworker/u8:4
  preempt_count: 1, expected: 0
  RCU nest depth: 0, expected: 0
  INFO: lockdep is turned off.
  Preemption disabled at:
  [<ffffffffc0636522>] __intel_gt_reset+0x92/0x100 [i915]
  CPU: 3 PID: 45092 Comm: kworker/u8:4 Tainted: G        W  O      5.15.59-rt48-preempt-rt #1
  Hardware name: Intel(R) Client Systems NUC7i5DNKE/NUC7i5DNB, BIOS DNKBLi5v.86A.0064.2019.0523.1933 05/23/2019
  Workqueue: events_unbound async_run_entry_fn
  Call Trace:
   <TASK>
   show_stack+0x52/0x5c
   dump_stack_lvl+0x5b/0x86
   dump_stack+0x10/0x16
   __might_resched.cold+0xf7/0x12f
   ? __gen6_reset_engines.constprop.0+0x80/0x80 [i915]
   rt_spin_lock+0x4e/0xf0
   ? gen8_reset_engines+0x2e/0x1e0 [i915]
   gen8_reset_engines+0x2e/0x1e0 [i915]
   ? __gen6_reset_engines.constprop.0+0x80/0x80 [i915]
   __intel_gt_reset+0x9d/0x100 [i915]
   gt_sanitize+0x16c/0x190 [i915]
   intel_gt_suspend_late+0x3d/0xc0 [i915]
   i915_gem_suspend_late+0x57/0x130 [i915]
   i915_drm_suspend_late+0x38/0x110 [i915]
   i915_pm_suspend_late+0x1d/0x30 [i915]
   pm_generic_suspend_late+0x28/0x40
   pci_pm_suspend_late+0x37/0x50
   ? pci_pm_poweroff_late+0x50/0x50
   dpm_run_callback.cold+0x3c/0xa8
   __device_suspend_late+0xa4/0x1e0
   async_suspend_late+0x20/0xa0
   async_run_entry_fn+0x28/0xc0
   process_one_work+0x239/0x6c0
   worker_thread+0x58/0x3e0
   kthread+0x1a9/0x1d0
   ? process_one_work+0x6c0/0x6c0
   ? set_kthread_struct+0x50/0x50
   ret_from_fork+0x1f/0x30
   </TASK>
  PM: late suspend of devices complete after 26.497 msecs

This happens, because the reset code now takes uncore->lock and that reacts
badly with commit ade8a0f59844 ("drm/i915: Make all GPU resets atomic")

Specifically this part, called out above with "Preemption disabled at:"

+         preempt_disable();
+         ret = reset(i915, engine_mask, retry);
+         preempt_enable();

A conversion to raw lock was considered independently in:

https://lore.kernel.org/all/20211006164628.s2mtsdd2jdbfyf7g@xxxxxxxxxxxxx/

...but was ruled out for latency reasons.  However I believe there is a
more simple solution, at least for this recent regression.  If we now have
the uncore->lock now wrapping the reset functions from b24dcf1dc507 (and
backports) then we aren't in any way relying on the added calls to
preempt_dis/enable() above to ensure non-conflicting resets or similar.

Hence we can "downgrade" them to migrate_dis/enable() so the reset
functions can run as-is, without any raw lock conversions or similar.

Signed-off-by: Paul Gortmaker <paul.gortmaker@xxxxxxxxxxxxx>

diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c
index 9dc244b70ce4..341833c364fe 100644
--- a/drivers/gpu/drm/i915/gt/intel_reset.c
+++ b/drivers/gpu/drm/i915/gt/intel_reset.c
@@ -736,9 +736,9 @@ int __intel_gt_reset(struct intel_gt *gt, intel_engine_mask_t engine_mask)
 	intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL);
 	for (retry = 0; ret == -ETIMEDOUT && retry < retries; retry++) {
 		GT_TRACE(gt, "engine_mask=%x\n", engine_mask);
-		preempt_disable();
+		migrate_disable();
 		ret = reset(gt, engine_mask, retry);
-		preempt_enable();
+		migrate_enable();
 	}
 	intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL);
 
-- 
2.17.1




[Index of Archives]     [RT Stable]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]

  Powered by Linux