diff mbox

drm/i915: have a forcewake "refcount"

Message ID 1301105269-23970-2-git-send-email-ben@bwidawsk.net (mailing list archive)
State New, archived
Headers show

Commit Message

Ben Widawsky March 26, 2011, 2:07 a.m. UTC
None
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 87c8e29..91ff99c 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1186,6 +1186,16 @@  static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
 	return 0;
 }
 
+static int i915_forcewake_count_info(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	seq_printf(m, "forcewake_count: %d\n",
+		   dev_priv->gen6_gt_forcewake_count);
+	return 0;
+}
+
 static int
 i915_wedged_open(struct inode *inode,
 		 struct file *filp)
@@ -1324,6 +1334,7 @@  static struct drm_info_list i915_debugfs_list[] = {
 	{"i915_sr_status", i915_sr_status, 0},
 	{"i915_opregion", i915_opregion, 0},
 	{"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},
+	{"i915_forcewake_count", i915_forcewake_count_info, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 7273037..35e0eaf 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -2026,6 +2026,9 @@  int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	spin_lock_init(&dev_priv->irq_lock);
 	spin_lock_init(&dev_priv->error_lock);
 
+	if (IS_GEN6(dev))
+		spin_lock_init(&dev_priv->gen6_gt_forcewake_lock);
+
 	if (IS_MOBILE(dev) || !IS_GEN2(dev))
 		dev_priv->num_pipe = 2;
 	else
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index c34a8dd..d8da39f 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -266,6 +266,17 @@  void intel_detect_pch (struct drm_device *dev)
 void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
 {
 	int count;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_priv->gen6_gt_forcewake_lock, flags);
+	if (++dev_priv->gen6_gt_forcewake_count > 1) {
+		count = 0;
+		while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1))
+			udelay(10);
+		spin_unlock_irqrestore(&dev_priv->gen6_gt_forcewake_lock, flags);
+		return;
+	}
+	WARN_ON(dev_priv->gen6_gt_forcewake_count != 1);
 
 	count = 0;
 	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1))
@@ -277,12 +288,25 @@  void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
 	count = 0;
 	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1) == 0)
 		udelay(10);
+
+	spin_unlock_irqrestore(&dev_priv->gen6_gt_forcewake_lock, flags);
 }
 
 void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_priv->gen6_gt_forcewake_lock, flags);
+	if (--dev_priv->gen6_gt_forcewake_count > 0) {
+		spin_unlock_irqrestore(&dev_priv->gen6_gt_forcewake_lock, flags);
+		return;
+	}
+	WARN_ON(dev_priv->gen6_gt_forcewake_count != 0);
+
 	I915_WRITE_NOTRACE(FORCEWAKE, 0);
 	POSTING_READ(FORCEWAKE);
+
+	spin_unlock_irqrestore(&dev_priv->gen6_gt_forcewake_lock, flags);
 }
 
 void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 5004724..f37bacd 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -703,6 +703,10 @@  typedef struct drm_i915_private {
 	struct intel_fbdev *fbdev;
 
 	struct drm_property *broadcast_rgb_property;
+
+	/* gen6 forcewake state */
+	spinlock_t gen6_gt_forcewake_lock;
+	int gen6_gt_forcewake_count;
 } drm_i915_private_t;
 
 struct drm_i915_gem_object {