Skip to content

Commit 23aae18

Browse files
committed
Merge tag 'drm-intel-next-fixes-2019-11-07' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
One RCU fix and fix for suspend GEM_BUG_ON (with dependencies). Signed-off-by: Dave Airlie <[email protected]> From: Joonas Lahtinen <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
2 parents 393fdfd + d9dace9 commit 23aae18

File tree

14 files changed

+118
-118
lines changed

14 files changed

+118
-118
lines changed

drivers/gpu/drm/i915/gem/i915_gem_pm.c

Lines changed: 3 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -11,59 +11,13 @@
1111

1212
#include "i915_drv.h"
1313

14-
static bool switch_to_kernel_context_sync(struct intel_gt *gt)
15-
{
16-
bool result = !intel_gt_is_wedged(gt);
17-
18-
if (intel_gt_wait_for_idle(gt, I915_GEM_IDLE_TIMEOUT) == -ETIME) {
19-
/* XXX hide warning from gem_eio */
20-
if (i915_modparams.reset) {
21-
dev_err(gt->i915->drm.dev,
22-
"Failed to idle engines, declaring wedged!\n");
23-
GEM_TRACE_DUMP();
24-
}
25-
26-
/*
27-
* Forcibly cancel outstanding work and leave
28-
* the gpu quiet.
29-
*/
30-
intel_gt_set_wedged(gt);
31-
result = false;
32-
}
33-
34-
if (intel_gt_pm_wait_for_idle(gt))
35-
result = false;
36-
37-
return result;
38-
}
39-
40-
static void user_forcewake(struct intel_gt *gt, bool suspend)
41-
{
42-
int count = atomic_read(&gt->user_wakeref);
43-
44-
/* Inside suspend/resume so single threaded, no races to worry about. */
45-
if (likely(!count))
46-
return;
47-
48-
intel_gt_pm_get(gt);
49-
if (suspend) {
50-
GEM_BUG_ON(count > atomic_read(&gt->wakeref.count));
51-
atomic_sub(count, &gt->wakeref.count);
52-
} else {
53-
atomic_add(count, &gt->wakeref.count);
54-
}
55-
intel_gt_pm_put(gt);
56-
}
57-
5814
void i915_gem_suspend(struct drm_i915_private *i915)
5915
{
6016
GEM_TRACE("\n");
6117

6218
intel_wakeref_auto(&i915->ggtt.userfault_wakeref, 0);
6319
flush_workqueue(i915->wq);
6420

65-
user_forcewake(&i915->gt, true);
66-
6721
/*
6822
* We have to flush all the executing contexts to main memory so
6923
* that they can saved in the hibernation image. To ensure the last
@@ -73,8 +27,7 @@ void i915_gem_suspend(struct drm_i915_private *i915)
7327
* state. Fortunately, the kernel_context is disposable and we do
7428
* not rely on its state.
7529
*/
76-
intel_gt_suspend(&i915->gt);
77-
intel_uc_suspend(&i915->gt.uc);
30+
intel_gt_suspend_prepare(&i915->gt);
7831

7932
i915_gem_drain_freed_objects(i915);
8033
}
@@ -116,6 +69,8 @@ void i915_gem_suspend_late(struct drm_i915_private *i915)
11669
* machine in an unusable condition.
11770
*/
11871

72+
intel_gt_suspend_late(&i915->gt);
73+
11974
spin_lock_irqsave(&i915->mm.obj_lock, flags);
12075
for (phase = phases; *phase; phase++) {
12176
LIST_HEAD(keep);
@@ -140,8 +95,6 @@ void i915_gem_suspend_late(struct drm_i915_private *i915)
14095
list_splice_tail(&keep, *phase);
14196
}
14297
spin_unlock_irqrestore(&i915->mm.obj_lock, flags);
143-
144-
i915_gem_sanitize(i915);
14598
}
14699

147100
void i915_gem_resume(struct drm_i915_private *i915)
@@ -161,14 +114,6 @@ void i915_gem_resume(struct drm_i915_private *i915)
161114
if (intel_gt_resume(&i915->gt))
162115
goto err_wedged;
163116

164-
intel_uc_resume(&i915->gt.uc);
165-
166-
/* Always reload a context for powersaving. */
167-
if (!switch_to_kernel_context_sync(&i915->gt))
168-
goto err_wedged;
169-
170-
user_forcewake(&i915->gt, false);
171-
172117
out_unlock:
173118
intel_uncore_forcewake_put(&i915->uncore, FORCEWAKE_ALL);
174119
return;

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@ void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915)
3131
intel_uc_init_early(&gt->uc);
3232
}
3333

34-
void intel_gt_init_hw_early(struct drm_i915_private *i915)
34+
void intel_gt_init_hw_early(struct intel_gt *gt, struct i915_ggtt *ggtt)
3535
{
36-
i915->gt.ggtt = &i915->ggtt;
36+
gt->ggtt = ggtt;
37+
38+
intel_gt_sanitize(gt, false);
3739
}
3840

3941
static void init_unused_ring(struct intel_gt *gt, u32 base)

drivers/gpu/drm/i915/gt/intel_gt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ static inline struct intel_gt *huc_to_gt(struct intel_huc *huc)
2828
}
2929

3030
void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915);
31-
void intel_gt_init_hw_early(struct drm_i915_private *i915);
31+
void intel_gt_init_hw_early(struct intel_gt *gt, struct i915_ggtt *ggtt);
3232
int __must_check intel_gt_init_hw(struct intel_gt *gt);
3333
int intel_gt_init(struct intel_gt *gt);
3434
void intel_gt_driver_register(struct intel_gt *gt);

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

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
* Copyright © 2019 Intel Corporation
55
*/
66

7+
#include <linux/suspend.h>
8+
79
#include "i915_drv.h"
810
#include "i915_globals.h"
911
#include "i915_params.h"
@@ -18,6 +20,24 @@
1820
#include "intel_rps.h"
1921
#include "intel_wakeref.h"
2022

23+
static void user_forcewake(struct intel_gt *gt, bool suspend)
24+
{
25+
int count = atomic_read(&gt->user_wakeref);
26+
27+
/* Inside suspend/resume so single threaded, no races to worry about. */
28+
if (likely(!count))
29+
return;
30+
31+
intel_gt_pm_get(gt);
32+
if (suspend) {
33+
GEM_BUG_ON(count > atomic_read(&gt->wakeref.count));
34+
atomic_sub(count, &gt->wakeref.count);
35+
} else {
36+
atomic_add(count, &gt->wakeref.count);
37+
}
38+
intel_gt_pm_put(gt);
39+
}
40+
2141
static int __gt_unpark(struct intel_wakeref *wf)
2242
{
2343
struct intel_gt *gt = container_of(wf, typeof(*gt), wakeref);
@@ -118,15 +138,31 @@ void intel_gt_sanitize(struct intel_gt *gt, bool force)
118138
{
119139
struct intel_engine_cs *engine;
120140
enum intel_engine_id id;
141+
intel_wakeref_t wakeref;
121142

122-
GEM_TRACE("\n");
143+
GEM_TRACE("force:%s\n", yesno(force));
144+
145+
/* Use a raw wakeref to avoid calling intel_display_power_get early */
146+
wakeref = intel_runtime_pm_get(gt->uncore->rpm);
147+
intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL);
148+
149+
/*
150+
* As we have just resumed the machine and woken the device up from
151+
* deep PCI sleep (presumably D3_cold), assume the HW has been reset
152+
* back to defaults, recovering from whatever wedged state we left it
153+
* in and so worth trying to use the device once more.
154+
*/
155+
if (intel_gt_is_wedged(gt))
156+
intel_gt_unset_wedged(gt);
123157

124158
intel_uc_sanitize(&gt->uc);
125159

126160
for_each_engine(engine, gt, id)
127161
if (engine->reset.prepare)
128162
engine->reset.prepare(engine);
129163

164+
intel_uc_reset_prepare(&gt->uc);
165+
130166
if (reset_engines(gt) || force) {
131167
for_each_engine(engine, gt, id)
132168
__intel_engine_reset(engine, false);
@@ -135,6 +171,9 @@ void intel_gt_sanitize(struct intel_gt *gt, bool force)
135171
for_each_engine(engine, gt, id)
136172
if (engine->reset.finish)
137173
engine->reset.finish(engine);
174+
175+
intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL);
176+
intel_runtime_pm_put(gt->uncore->rpm, wakeref);
138177
}
139178

140179
void intel_gt_pm_fini(struct intel_gt *gt)
@@ -148,6 +187,8 @@ int intel_gt_resume(struct intel_gt *gt)
148187
enum intel_engine_id id;
149188
int err = 0;
150189

190+
GEM_TRACE("\n");
191+
151192
/*
152193
* After resume, we may need to poke into the pinned kernel
153194
* contexts to paper over any damage caused by the sudden suspend.
@@ -186,14 +227,22 @@ int intel_gt_resume(struct intel_gt *gt)
186227
}
187228

188229
intel_rc6_enable(&gt->rc6);
230+
231+
intel_uc_resume(&gt->uc);
232+
233+
user_forcewake(gt, false);
234+
189235
intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL);
190236
intel_gt_pm_put(gt);
191237

192238
return err;
193239
}
194240

195-
static void wait_for_idle(struct intel_gt *gt)
241+
static void wait_for_suspend(struct intel_gt *gt)
196242
{
243+
if (!intel_gt_pm_is_awake(gt))
244+
return;
245+
197246
if (intel_gt_wait_for_idle(gt, I915_GEM_IDLE_TIMEOUT) == -ETIME) {
198247
/*
199248
* Forcibly cancel outstanding work and leave
@@ -205,27 +254,65 @@ static void wait_for_idle(struct intel_gt *gt)
205254
intel_gt_pm_wait_for_idle(gt);
206255
}
207256

208-
void intel_gt_suspend(struct intel_gt *gt)
257+
void intel_gt_suspend_prepare(struct intel_gt *gt)
258+
{
259+
user_forcewake(gt, true);
260+
wait_for_suspend(gt);
261+
262+
intel_uc_suspend(&gt->uc);
263+
}
264+
265+
static suspend_state_t pm_suspend_target(void)
266+
{
267+
#if IS_ENABLED(CONFIG_PM_SLEEP)
268+
return pm_suspend_target_state;
269+
#else
270+
return PM_SUSPEND_TO_IDLE;
271+
#endif
272+
}
273+
274+
void intel_gt_suspend_late(struct intel_gt *gt)
209275
{
210276
intel_wakeref_t wakeref;
211277

212278
/* We expect to be idle already; but also want to be independent */
213-
wait_for_idle(gt);
279+
wait_for_suspend(gt);
280+
281+
/*
282+
* On disabling the device, we want to turn off HW access to memory
283+
* that we no longer own.
284+
*
285+
* However, not all suspend-states disable the device. S0 (s2idle)
286+
* is effectively runtime-suspend, the device is left powered on
287+
* but needs to be put into a low power state. We need to keep
288+
* powermanagement enabled, but we also retain system state and so
289+
* it remains safe to keep on using our allocated memory.
290+
*/
291+
if (pm_suspend_target() == PM_SUSPEND_TO_IDLE)
292+
return;
214293

215294
with_intel_runtime_pm(gt->uncore->rpm, wakeref) {
216295
intel_rps_disable(&gt->rps);
217296
intel_rc6_disable(&gt->rc6);
218297
intel_llc_disable(&gt->llc);
219298
}
299+
300+
intel_gt_sanitize(gt, false);
301+
302+
GEM_TRACE("\n");
220303
}
221304

222305
void intel_gt_runtime_suspend(struct intel_gt *gt)
223306
{
224307
intel_uc_runtime_suspend(&gt->uc);
308+
309+
GEM_TRACE("\n");
225310
}
226311

227312
int intel_gt_runtime_resume(struct intel_gt *gt)
228313
{
314+
GEM_TRACE("\n");
315+
229316
intel_gt_init_swizzling(gt);
230317

231318
return intel_uc_runtime_resume(&gt->uc);

drivers/gpu/drm/i915/gt/intel_gt_pm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ void intel_gt_pm_fini(struct intel_gt *gt);
4343

4444
void intel_gt_sanitize(struct intel_gt *gt, bool force);
4545

46+
void intel_gt_suspend_prepare(struct intel_gt *gt);
47+
void intel_gt_suspend_late(struct intel_gt *gt);
4648
int intel_gt_resume(struct intel_gt *gt);
47-
void intel_gt_suspend(struct intel_gt *gt);
4849

4950
void intel_gt_runtime_suspend(struct intel_gt *gt);
5051
int intel_gt_runtime_resume(struct intel_gt *gt);

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,11 @@ void intel_rc6_init(struct intel_rc6 *rc6)
525525

526526
void intel_rc6_sanitize(struct intel_rc6 *rc6)
527527
{
528+
if (rc6->enabled) { /* unbalanced suspend/resume */
529+
rpm_get(rc6);
530+
rc6->enabled = false;
531+
}
532+
528533
if (rc6->supported)
529534
__intel_rc6_disable(rc6);
530535
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ static int live_gt_resume(void *arg)
1515

1616
/* Do several suspend/resume cycles to check we don't explode! */
1717
do {
18-
intel_gt_suspend(gt);
18+
intel_gt_suspend_prepare(gt);
19+
intel_gt_suspend_late(gt);
1920

2021
if (gt->rc6.enabled) {
2122
pr_err("rc6 still enabled after suspend!\n");

drivers/gpu/drm/i915/i915_drv.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -603,8 +603,6 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv)
603603
if (ret)
604604
goto err_uncore;
605605

606-
i915_gem_init_mmio(dev_priv);
607-
608606
return 0;
609607

610608
err_uncore:
@@ -1177,7 +1175,7 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
11771175
if (ret)
11781176
goto err_ggtt;
11791177

1180-
intel_gt_init_hw_early(dev_priv);
1178+
intel_gt_init_hw_early(&dev_priv->gt, &dev_priv->ggtt);
11811179

11821180
ret = i915_ggtt_enable_hw(dev_priv);
11831181
if (ret) {
@@ -1821,7 +1819,7 @@ static int i915_drm_resume(struct drm_device *dev)
18211819

18221820
disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
18231821

1824-
i915_gem_sanitize(dev_priv);
1822+
intel_gt_sanitize(&dev_priv->gt, true);
18251823

18261824
ret = i915_ggtt_enable_hw(dev_priv);
18271825
if (ret)
@@ -1952,8 +1950,6 @@ static int i915_drm_resume_early(struct drm_device *dev)
19521950

19531951
intel_power_domains_resume(dev_priv);
19541952

1955-
intel_gt_sanitize(&dev_priv->gt, true);
1956-
19571953
enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
19581954

19591955
return ret;

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1779,7 +1779,6 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
17791779
/* i915_gem.c */
17801780
int i915_gem_init_userptr(struct drm_i915_private *dev_priv);
17811781
void i915_gem_cleanup_userptr(struct drm_i915_private *dev_priv);
1782-
void i915_gem_sanitize(struct drm_i915_private *i915);
17831782
void i915_gem_init_early(struct drm_i915_private *dev_priv);
17841783
void i915_gem_cleanup_early(struct drm_i915_private *dev_priv);
17851784
int i915_gem_freeze(struct drm_i915_private *dev_priv);
@@ -1863,7 +1862,6 @@ static inline u32 i915_reset_engine_count(struct i915_gpu_error *error,
18631862
return atomic_read(&error->reset_engine_count[engine->uabi_class]);
18641863
}
18651864

1866-
void i915_gem_init_mmio(struct drm_i915_private *i915);
18671865
int __must_check i915_gem_init(struct drm_i915_private *dev_priv);
18681866
void i915_gem_driver_register(struct drm_i915_private *i915);
18691867
void i915_gem_driver_unregister(struct drm_i915_private *i915);

0 commit comments

Comments
 (0)