diff mbox

[2/2] drm/i915: debugger debugfs entry

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

Commit Message

Ben Widawsky June 22, 2011, 11:07 p.m. UTC
Provide a way for userspace shader debugger to notify the kernel that it
will be debugging. This interface does two things, provides a way for
the kernel to prepare for debugging, and act as a lock between
concurrent debugging (of course none of this is enforced).
---
 drivers/gpu/drm/i915/i915_debugfs.c |   73 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h     |    6 +++
 drivers/gpu/drm/i915/i915_irq.c     |    2 +-
 3 files changed, 80 insertions(+), 1 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 4d46441..ab6e2a2 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1395,6 +1395,74 @@  static int i915_forcewake_create(struct dentry *root, struct drm_minor *minor)
 	return drm_add_fake_info_node(minor, ent, &i915_forcewake_fops);
 }
 
+static int i915_debugger_open(struct inode *inode, struct file *file)
+{
+	struct drm_device *dev = inode->i_private;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret;
+
+	if (atomic_add_return(1, &dev_priv->debug.debugging) != 1) {
+		atomic_dec(&dev_priv->debug.debugging);
+		return -EBUSY;
+	}
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret) {
+		atomic_dec(&dev_priv->debug.debugging);
+		return ret;
+	}
+
+	del_timer_sync(&dev_priv->hangcheck_timer);
+	dev_priv->hangcheck_disabled = true;
+
+	dev_priv->debug.debugger = current;
+
+	mutex_unlock(&dev->struct_mutex);
+	return 0;
+}
+
+static int i915_debugger_release(struct inode *inode, struct file *file)
+{
+	struct drm_device *dev = inode->i_private;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	mutex_lock(&dev->struct_mutex);
+
+	if (WARN_ON(dev_priv->debug.debugger != current))
+		return -ENXIO;
+
+	WARN_ON(atomic_dec_and_test(&dev_priv->debug.debugging) == 0);
+
+	dev_priv->debug.debugger = NULL;
+	dev_priv->hangcheck_disabled = false;
+	mutex_unlock(&dev->struct_mutex);
+	return 0;
+}
+
+static const struct file_operations i915_debugger_fops = {
+	.owner = THIS_MODULE,
+	.open = i915_debugger_open,
+	.release = i915_debugger_release,
+};
+
+static int i915_debugger_create(struct dentry *root, struct drm_minor *minor)
+{
+	struct drm_device *dev = minor->dev;
+	struct dentry *ent;
+
+	ent = debugfs_create_file("i915_debugger",
+				  S_IRUSR,
+				  root, dev,
+				  &i915_debugger_fops);
+	if (IS_ERR(ent))
+		return PTR_ERR(ent);
+
+	return drm_add_fake_info_node(minor, ent, &i915_debugger_fops);
+
+	return 0;
+}
+
+
 static struct drm_info_list i915_debugfs_list[] = {
 	{"i915_capabilities", i915_capabilities, 0},
 	{"i915_gem_objects", i915_gem_object_info, 0},
@@ -1448,6 +1516,9 @@  int i915_debugfs_init(struct drm_minor *minor)
 	if (ret)
 		return ret;
 
+	ret = i915_debugger_create(minor->debugfs_root, minor);
+	if (ret)
+		return ret;
 	return drm_debugfs_create_files(i915_debugfs_list,
 					I915_DEBUGFS_ENTRIES,
 					minor->debugfs_root, minor);
@@ -1457,6 +1528,8 @@  void i915_debugfs_cleanup(struct drm_minor *minor)
 {
 	drm_debugfs_remove_files(i915_debugfs_list,
 				 I915_DEBUGFS_ENTRIES, minor);
+	drm_debugfs_remove_files((struct drm_info_list *) &i915_debugger_fops,
+				 1, minor);
 	drm_debugfs_remove_files((struct drm_info_list *) &i915_forcewake_fops,
 				 1, minor);
 	drm_debugfs_remove_files((struct drm_info_list *) &i915_wedged_fops,
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 05f82a7..a4418eb 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -720,6 +720,12 @@  typedef struct drm_i915_private {
 	struct drm_property *force_audio_property;
 
 	atomic_t forcewake_count;
+
+	struct {
+		atomic_t debugging;
+		struct task_struct *debugger;
+	} debug;
+
 } drm_i915_private_t;
 
 enum i915_cache_level {
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index af72412..ca8ec0f 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1723,7 +1723,7 @@  void i915_hangcheck_elapsed(unsigned long data)
 	}
 
 repeat:
-	BUG_ON(dev_priv->hangcheck_disabled);
+	WARN_ON(dev_priv->hangcheck_disabled);
 	/* Reset timer case chip hangs without another request being added */
 	mod_timer(&dev_priv->hangcheck_timer,
 		  jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));