Skip to content

Commit 7c108fd

Browse files
committed
drm/i915: Move fence cancellation to runtime suspend
At the moment, we have dependency on the RPM as a barrier itself in both i915_gem_release_all_mmaps() and i915_gem_restore_fences(). i915_gem_restore_fences() is also called along !runtime pm paths, but we can move the markup of lost fences alongside releasing the mmaps into a common i915_gem_runtime_suspend(). This has the advantage of locating all the tricky barrier dependencies into one location. v2: Just mark the fence as invalid (fence->dirty) so that upon waking we will be sure to clear the fence after use, or restore it to the correct value before use. This makes sure that if the fence is left intact across the sleep, we do not leave it pointing to a region of GTT for the next unsuspecting user. Suggested-by: Daniel Vetter <[email protected]> Signed-off-by: Chris Wilson <[email protected]> Cc: Daniel Vetter <[email protected]> Cc: Imre Deak <[email protected]> Reviewed-by: Imre Deak <[email protected]> Link: http://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 2eedfc7 commit 7c108fd

File tree

4 files changed

+28
-14
lines changed

4 files changed

+28
-14
lines changed

drivers/gpu/drm/i915/i915_drv.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2278,10 +2278,8 @@ static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
22782278

22792279
vlv_check_no_gt_access(dev_priv);
22802280

2281-
if (rpm_resume) {
2281+
if (rpm_resume)
22822282
intel_init_clock_gating(dev);
2283-
i915_gem_restore_fences(dev);
2284-
}
22852283

22862284
return ret;
22872285
}
@@ -2307,7 +2305,7 @@ static int intel_runtime_suspend(struct device *kdev)
23072305
* We are safe here against re-faults, since the fault handler takes
23082306
* an RPM reference.
23092307
*/
2310-
i915_gem_release_all_mmaps(dev_priv);
2308+
i915_gem_runtime_suspend(dev_priv);
23112309

23122310
intel_guc_suspend(dev);
23132311

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3130,9 +3130,10 @@ void i915_vma_destroy(struct i915_vma *vma);
31303130

31313131
int i915_gem_object_unbind(struct drm_i915_gem_object *obj);
31323132
int i915_gem_object_put_pages(struct drm_i915_gem_object *obj);
3133-
void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv);
31343133
void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
31353134

3135+
void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv);
3136+
31363137
int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj);
31373138

31383139
static inline int __sg_page_count(struct scatterlist *sg)

drivers/gpu/drm/i915/i915_gem.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,10 +1952,10 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj)
19521952
intel_runtime_pm_put(i915);
19531953
}
19541954

1955-
void
1956-
i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv)
1955+
void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv)
19571956
{
19581957
struct drm_i915_gem_object *obj, *on;
1958+
int i;
19591959

19601960
/*
19611961
* Only called during RPM suspend. All users of the userfault_list
@@ -1970,6 +1970,23 @@ i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv)
19701970
drm_vma_node_unmap(&obj->base.vma_node,
19711971
obj->base.dev->anon_inode->i_mapping);
19721972
}
1973+
1974+
/* The fence will be lost when the device powers down. If any were
1975+
* in use by hardware (i.e. they are pinned), we should not be powering
1976+
* down! All other fences will be reacquired by the user upon waking.
1977+
*/
1978+
for (i = 0; i < dev_priv->num_fence_regs; i++) {
1979+
struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
1980+
1981+
if (WARN_ON(reg->pin_count))
1982+
continue;
1983+
1984+
if (!reg->vma)
1985+
continue;
1986+
1987+
GEM_BUG_ON(!list_empty(&reg->vma->obj->userfault_link));
1988+
reg->dirty = true;
1989+
}
19731990
}
19741991

19751992
/**

drivers/gpu/drm/i915/i915_gem_fence.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,9 @@ i915_vma_get_fence(struct i915_vma *vma)
343343
struct drm_i915_fence_reg *fence;
344344
struct i915_vma *set = i915_gem_object_is_tiled(vma->obj) ? vma : NULL;
345345

346+
/* Note that we revoke fences on runtime suspend. Therefore the user
347+
* must keep the device awake whilst using the fence.
348+
*/
346349
assert_rpm_wakelock_held(to_i915(vma->vm->dev));
347350

348351
/* Just update our place in the LRU if our fence is getting reused. */
@@ -368,19 +371,14 @@ i915_vma_get_fence(struct i915_vma *vma)
368371
* @dev: DRM device
369372
*
370373
* Restore the hw fence state to match the software tracking again, to be called
371-
* after a gpu reset and on resume.
374+
* after a gpu reset and on resume. Note that on runtime suspend we only cancel
375+
* the fences, to be reacquired by the user later.
372376
*/
373377
void i915_gem_restore_fences(struct drm_device *dev)
374378
{
375379
struct drm_i915_private *dev_priv = to_i915(dev);
376380
int i;
377381

378-
/* Note that this may be called outside of struct_mutex, by
379-
* runtime suspend/resume. The barrier we require is enforced by
380-
* rpm itself - all access to fences/GTT are only within an rpm
381-
* wakeref, and to acquire that wakeref you must pass through here.
382-
*/
383-
384382
for (i = 0; i < dev_priv->num_fence_regs; i++) {
385383
struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
386384
struct i915_vma *vma = reg->vma;

0 commit comments

Comments
 (0)