Merge branch 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvar...
[pandora-kernel.git] / drivers / gpu / drm / i915 / i915_debugfs.c
index 87c8e29..51c2257 100644 (file)
@@ -106,11 +106,12 @@ static const char *get_tiling_flag(struct drm_i915_gem_object *obj)
     }
 }
 
-static const char *agp_type_str(int type)
+static const char *cache_level_str(int type)
 {
        switch (type) {
-       case 0: return " uncached";
-       case 1: return " snooped";
+       case I915_CACHE_NONE: return " uncached";
+       case I915_CACHE_LLC: return " snooped (LLC)";
+       case I915_CACHE_LLC_MLC: return " snooped (LLC+MLC)";
        default: return "";
        }
 }
@@ -127,7 +128,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
                   obj->base.write_domain,
                   obj->last_rendering_seqno,
                   obj->last_fenced_seqno,
-                  agp_type_str(obj->agp_type == AGP_USER_CACHED_MEMORY),
+                  cache_level_str(obj->cache_level),
                   obj->dirty ? " dirty" : "",
                   obj->madv == I915_MADV_DONTNEED ? " purgeable" : "");
        if (obj->base.name)
@@ -714,7 +715,7 @@ static void print_error_buffers(struct seq_file *m,
                           dirty_flag(err->dirty),
                           purgeable_flag(err->purgeable),
                           ring_str(err->ring),
-                          agp_type_str(err->agp_type));
+                          cache_level_str(err->cache_level));
 
                if (err->name)
                        seq_printf(m, " (name: %d)", err->name);
@@ -852,6 +853,7 @@ static int i915_cur_delayinfo(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;
+       int ret;
 
        if (IS_GEN5(dev)) {
                u16 rgvswctl = I915_READ16(MEMSWCTL);
@@ -873,7 +875,11 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
                int max_freq;
 
                /* RPSTAT1 is in the GT power well */
-               __gen6_gt_force_wake_get(dev_priv);
+               ret = mutex_lock_interruptible(&dev->struct_mutex);
+               if (ret)
+                       return ret;
+
+               gen6_gt_force_wake_get(dev_priv);
 
                rpstat = I915_READ(GEN6_RPSTAT1);
                rpupei = I915_READ(GEN6_RP_CUR_UP_EI);
@@ -883,6 +889,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
                rpcurdown = I915_READ(GEN6_RP_CUR_DOWN);
                rpprevdown = I915_READ(GEN6_RP_PREV_DOWN);
 
+               gen6_gt_force_wake_put(dev_priv);
+               mutex_unlock(&dev->struct_mutex);
+
                seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status);
                seq_printf(m, "RPSTAT1: 0x%08x\n", rpstat);
                seq_printf(m, "Render p-state ratio: %d\n",
@@ -917,8 +926,6 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
                max_freq = rp_state_cap & 0xff;
                seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n",
                           max_freq * 50);
-
-               __gen6_gt_force_wake_put(dev_priv);
        } else {
                seq_printf(m, "no P-state info available\n");
        }
@@ -1058,6 +1065,9 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
                case FBC_MULTIPLE_PIPES:
                        seq_printf(m, "multiple pipes are enabled");
                        break;
+               case FBC_MODULE_PARAM:
+                       seq_printf(m, "disabled per module param (default off)");
+                       break;
                default:
                        seq_printf(m, "unknown reason");
                }
@@ -1186,6 +1196,42 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
        return 0;
 }
 
+static int i915_context_status(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;
+       int ret;
+
+       ret = mutex_lock_interruptible(&dev->mode_config.mutex);
+       if (ret)
+               return ret;
+
+       seq_printf(m, "power context ");
+       describe_obj(m, dev_priv->pwrctx);
+       seq_printf(m, "\n");
+
+       seq_printf(m, "render context ");
+       describe_obj(m, dev_priv->renderctx);
+       seq_printf(m, "\n");
+
+       mutex_unlock(&dev->mode_config.mutex);
+
+       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",
+                  atomic_read(&dev_priv->forcewake_count));
+
+       return 0;
+}
+
 static int
 i915_wedged_open(struct inode *inode,
                 struct file *filp)
@@ -1288,6 +1334,67 @@ 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;
+       int ret;
+
+       if (!IS_GEN6(dev))
+               return 0;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+       gen6_gt_force_wake_get(dev_priv);
+       mutex_unlock(&dev->struct_mutex);
+
+       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;
+
+       /*
+        * It's bad that we can potentially hang userspace if struct_mutex gets
+        * forever stuck.  However, if we cannot acquire this lock it means that
+        * almost certainly the driver has hung, is not unload-able. Therefore
+        * hanging here is probably a minor inconvenience not to be seen my
+        * almost every user.
+        */
+       mutex_lock(&dev->struct_mutex);
+       gen6_gt_force_wake_put(dev_priv);
+       mutex_unlock(&dev->struct_mutex);
+
+       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_IRUSR,
+                                 root, dev,
+                                 &i915_forcewake_fops);
+       if (IS_ERR(ent))
+               return PTR_ERR(ent);
+
+       return drm_add_fake_info_node(minor, ent, &i915_forcewake_fops);
+}
+
 static struct drm_info_list i915_debugfs_list[] = {
        {"i915_capabilities", i915_capabilities, 0},
        {"i915_gem_objects", i915_gem_object_info, 0},
@@ -1324,6 +1431,8 @@ 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_context_status", i915_context_status, 0},
+       {"i915_gen6_forcewake_count", i915_gen6_forcewake_count_info, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
@@ -1335,6 +1444,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);
@@ -1344,6 +1457,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);
 }