diff mbox

[4/4] drm/i915: optional fewer warning patch

Message ID 1302381082-3167-5-git-send-email-ben@bwidawsk.net (mailing list archive)
State New, archived
Headers show

Commit Message

Ben Widawsky April 9, 2011, 8:31 p.m. UTC
This patch will likely produce much fewer warnings, but perhaps hide
some bugs in the driver. Any warnings while using this patch are
extremely likely to cause problems, while warnings without this patch
are also driver bugs, but much less likely to be causing issues. Without
this patch we may also get false warnings for intelligent users of the
new refcount mechanism.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_drv.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

Comments

Chris Wilson April 9, 2011, 10:31 p.m. UTC | #1
On Sat,  9 Apr 2011 13:31:22 -0700, Ben Widawsky <ben@bwidawsk.net> wrote:
> +	 *
> +	 * Intelligent users of the interface may do a force_wake_get() followed
> +	 * by many register reads and writes, knowing that the reference count
> +	 * is already incremented. So we do not want to warn on those.
>  	 */

Hmm, any place where we touch registers without holding a lock, unless
under exceptional conditions such as !SYSTEM_RUNNING, is a bug waiting to
happen. And probably already happened. Nasty, hard to reproduce race
conditions.

The complication is that some registers will be protected by
dev->config.mode_lock rather than dev->struct_mutex (and a very rare set
are protected by their own irq spinlocks). This sounds like a job for
lockdep... And a lot of documentation. Fortunately, we only have those two
conditions (KMS (detection and mode setting) vs GEM (execution and memory
managment)) and their intersection to worry about.

One of the first steps would be to review all the comments Jesse added to
document the KMS locking and back those up with assertions and updates.
Plenty of work to do before we can feel sure that the locking is sane.
-Chris
Ben Widawsky April 9, 2011, 11:32 p.m. UTC | #2
On Sat, Apr 09, 2011 at 11:31:14PM +0100, Chris Wilson wrote:
> On Sat,  9 Apr 2011 13:31:22 -0700, Ben Widawsky <ben@bwidawsk.net> wrote:
> > +	 *
> > +	 * Intelligent users of the interface may do a force_wake_get() followed
> > +	 * by many register reads and writes, knowing that the reference count
> > +	 * is already incremented. So we do not want to warn on those.
> >  	 */
> 
> Hmm, any place where we touch registers without holding a lock, unless
> under exceptional conditions such as !SYSTEM_RUNNING, is a bug waiting to
> happen. And probably already happened. Nasty, hard to reproduce race
> conditions.

The only use I had in mind was doing a bunch of reads, or perhaps
polling on a register. I didn't have a specific case but it seemed
feasible in certain cases.

> -Chris

Ben
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 96b3bfc..6da7079 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -286,8 +286,13 @@  void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
 	 * immediately. Not having the lock causes a race, but all bets are off
 	 * when using forced forcewake, which should only be touched through
 	 * root-only entry in debugfs.
+	 *
+	 * Intelligent users of the interface may do a force_wake_get() followed
+	 * by many register reads and writes, knowing that the reference count
+	 * is already incremented. So we do not want to warn on those.
 	 */
-	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex) &&
+		!dev_priv->forcewake_count);
 
 	if (dev_priv->forcewake_count++ == 0)
 		__gen6_gt_force_wake_get(dev_priv);
@@ -301,7 +306,8 @@  static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
 
 void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
 {
-	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex) &&
+		!dev_priv->forcewake_count);
 
 	if (--dev_priv->forcewake_count == 0)
 		__gen6_gt_force_wake_put(dev_priv);