[Intel-gfx] [RFC] drm/i915: Check if we hold a wakeref during ioread32/iowrite32
Chris Wilson
chris at chris-wilson.co.uk
Tue Feb 23 16:54:52 UTC 2016
On Tue, Feb 23, 2016 at 05:09:29PM +0200, Imre Deak wrote:
> On ti, 2016-02-23 at 14:55 +0000, Chris Wilson wrote:
> > On Tue, Feb 23, 2016 at 04:47:17PM +0200, Imre Deak wrote:
> > > The device needs to be in D0 state whenever we call these
> > > functions, so
> > > add the corresponding assert checks.
> >
> > No. In quite a few of those cases we are calling iowrite to non-
> > device
> > memory, even normal pages.
>
> Hm right didn't think about that. I guess the only case we care about
> then are accesses through the GTT.
>
> > How's the separation of struct_mutex from rpm going so that we can
> > forgo
> > adding assertions and use explicit power management instead?
>
> It's planned to be done, but no one is working on that yet. This is
> something we could still have regardless, similarly to other helpers
> accessing the device.
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 31b600d31158..b8687b6a6acb 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1430,24 +1430,6 @@ static int intel_runtime_suspend(struct device *device)
DRM_DEBUG_KMS("Suspending device\n");
- /*
- * We could deadlock here in case another thread holding struct_mutex
- * calls RPM suspend concurrently, since the RPM suspend will wait
- * first for this RPM suspend to finish. In this case the concurrent
- * RPM resume will be followed by its RPM suspend counterpart. Still
- * for consistency return -EAGAIN, which will reschedule this suspend.
- */
- if (!mutex_trylock(&dev->struct_mutex)) {
- DRM_DEBUG_KMS("device lock contention, deffering suspend\n");
- /*
- * Bump the expiration timestamp, otherwise the suspend won't
- * be rescheduled.
- */
- pm_runtime_mark_last_busy(device);
-
- return -EAGAIN;
- }
-
disable_rpm_wakeref_asserts(dev_priv);
/*
@@ -1455,7 +1437,6 @@ static int intel_runtime_suspend(struct device *device)
* an RPM reference.
*/
i915_gem_release_all_mmaps(dev_priv);
- mutex_unlock(&dev->struct_mutex);
intel_guc_suspend(dev);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 79706621e6e4..4f6127466822 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1670,9 +1670,13 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj)
/* Serialisation between user GTT access and our code depends upon
* revoking the CPU's PTE whilst the mutex is held. The next user
* pagefault then has to wait until we release the mutex.
+ *
+ * Note that RPM complicates somewhat by adding an additional
+ * requirement that operations to the GGTT be made holding the RPM
+ * wakeref. This in turns allow us to release the mmap from within
+ * the RPM suspend code ignoring the struct_mutex serialisation in
+ * lieu of the RPM barriers.
*/
- lockdep_assert_held(&obj->base.dev->struct_mutex);
-
if (!obj->fault_mappable)
return;
@@ -1685,11 +1689,21 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj)
obj->fault_mappable = false;
}
+static void assert_rpm_release_all_mmaps(struct drm_i915_private *dev_priv)
+{
+ assert_rpm_wakelock_held(dev_priv);
+}
+
void
i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv)
{
struct drm_i915_gem_object *obj;
+ /* This should only be called by RPM as we require the bound_list
+ * to be protected by the RPM barriers and not struct_mutex.
+ * We check that we are holding the wakeref whenever we manipulate
+ * the dev_priv->mm.bound_list (via assert_rpm_release_all_mmaps).
+ */
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list)
i915_gem_release_mmap(obj);
}
@@ -2224,9 +2238,11 @@ i915_gem_object_retire__read(struct i915_gem_active *active,
* so that we don't steal from recently used but inactive objects
* (unless we are forced to ofc!)
*/
- if (obj->bind_count)
+ if (obj->bind_count) {
+ assert_rpm_release_all_mmaps(request->i915);
list_move_tail(&obj->global_list,
&request->i915->mm.bound_list);
+ }
if (i915_gem_object_has_active_reference(obj)) {
i915_gem_object_unset_active_reference(obj);
@@ -2751,9 +2767,11 @@ int i915_vma_unbind(struct i915_vma *vma)
/* Since the unbound list is global, only move to that list if
* no more VMAs exist. */
- if (--obj->bind_count == 0)
+ if (--obj->bind_count == 0) {
+ assert_rpm_release_all_mmaps(to_i915(obj->base.dev));
list_move_tail(&obj->global_list,
&to_i915(obj->base.dev)->mm.unbound_list);
+ }
/* And finally now the object is completely decoupled from this vma,
* we can drop its hold on the backing storage and allow it to be
@@ -2913,6 +2931,7 @@ i915_vma_insert(struct i915_vma *vma,
goto err_remove_node;
}
+ assert_rpm_release_all_mmaps(dev_priv);
list_move_tail(&obj->global_list, &dev_priv->mm.bound_list);
list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
obj->bind_count++;
--
Chris Wilson, Intel Open Source Technology Centre
More information about the Intel-gfx
mailing list