[Intel-gfx] [PATCH] drm/i915: have a forcewake "refcount"

Ben Widawsky ben at bwidawsk.net
Sat Mar 26 03:07:49 CET 2011


On Gen6, forcewake must be used to ensure certain HW bits are powered to
process commands (such as register writes). Forcewake should be
persistent according to the spec, so it is unnecessary to set it more
than once.

Further this "refcount" allows a userspace interaction with this part of
the HW (for say, reading and writing registers).

Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_debugfs.c |   11 +++++++++++
 drivers/gpu/drm/i915/i915_dma.c     |    3 +++
 drivers/gpu/drm/i915/i915_drv.c     |   24 ++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h     |    4 ++++
 4 files changed, 42 insertions(+), 0 deletions(-)

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 {
-- 
1.7.3.4




More information about the Intel-gfx mailing list