@@ -1181,6 +1181,17 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
return 0;
}
+static int i915_gen6_forcewake_count_info(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ seq_printf(m, "forcewake count = %d\n", dev_priv->forcewake_count);
+
+ return 0;
+}
+
static int
i915_wedged_open(struct inode *inode,
struct file *filp)
@@ -1283,6 +1294,61 @@ static int i915_wedged_create(struct dentry *root, struct drm_minor *minor)
return drm_add_fake_info_node(minor, ent, &i915_wedged_fops);
}
+static int i915_forcewake_open(struct inode *inode, struct file *file)
+{
+ struct drm_device *dev = inode->i_private;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (!IS_GEN6(dev))
+ return 0;
+
+ /*
+ * Paranoid people might say that it's bad that we can potentially hang
+ * userspace spinning on this lock. However, if we cannot acquire this
+ * lock it means that almost certainly the driver has hung, is not
+ * unload-able, and the GPU is not resettable. Therefore hanging here is
+ * probably a minor inconvenience not to be seen my almost every user.
+ */
+ gen6_gt_force_wake_get(dev_priv);
+
+ return 0;
+}
+
+int i915_forcewake_release(struct inode *inode, struct file *file)
+{
+ struct drm_device *dev = inode->i_private;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (!IS_GEN6(dev))
+ return 0;
+
+ /* see i915_forcewake_open() */
+ gen6_gt_force_wake_put(dev_priv);
+
+ return 0;
+}
+
+static const struct file_operations i915_forcewake_fops = {
+ .owner = THIS_MODULE,
+ .open = i915_forcewake_open,
+ .release = i915_forcewake_release,
+};
+
+static int i915_forcewake_create(struct dentry *root, struct drm_minor *minor)
+{
+ struct drm_device *dev = minor->dev;
+ struct dentry *ent;
+
+ ent = debugfs_create_file("i915_forcewake_user",
+ S_IRWXU,
+ root, dev,
+ &i915_forcewake_fops);
+ if (IS_ERR(ent))
+ return PTR_ERR(ent);
+
+ return 0;
+}
+
static struct drm_info_list i915_debugfs_list[] = {
{"i915_capabilities", i915_capabilities, 0},
{"i915_gem_objects", i915_gem_object_info, 0},
@@ -1319,6 +1385,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_gen6_forcewake_count", i915_gen6_forcewake_count_info, 0},
};
#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
@@ -1330,6 +1397,10 @@ int i915_debugfs_init(struct drm_minor *minor)
if (ret)
return ret;
+ ret = i915_forcewake_create(minor->debugfs_root, minor);
+ if (ret)
+ return ret;
+
return drm_debugfs_create_files(i915_debugfs_list,
I915_DEBUGFS_ENTRIES,
minor->debugfs_root, minor);
@@ -1339,6 +1410,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_forcewake_fops,
+ 1, minor);
drm_debugfs_remove_files((struct drm_info_list *) &i915_wedged_fops,
1, minor);
}
userspace to the forcewake reference count via debugfs. v2: use new spin_locks instead of struct_mutex v3: spin locks are acquired by the get/put functions now Signed-off-by: Ben Widawsky <ben@bwidawsk.net> --- drivers/gpu/drm/i915/i915_debugfs.c | 73 +++++++++++++++++++++++++++++++++++ 1 files changed, 73 insertions(+), 0 deletions(-)