aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_debugfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_debugfs.c')
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c120
1 files changed, 116 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 26bf0552b3cb..18476bf0b580 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -27,6 +27,7 @@
27 */ 27 */
28 28
29#include <linux/seq_file.h> 29#include <linux/seq_file.h>
30#include <linux/debugfs.h>
30#include "drmP.h" 31#include "drmP.h"
31#include "drm.h" 32#include "drm.h"
32#include "i915_drm.h" 33#include "i915_drm.h"
@@ -96,13 +97,14 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
96 { 97 {
97 struct drm_gem_object *obj = obj_priv->obj; 98 struct drm_gem_object *obj = obj_priv->obj;
98 99
99 seq_printf(m, " %p: %s %8zd %08x %08x %d %s", 100 seq_printf(m, " %p: %s %8zd %08x %08x %d%s%s",
100 obj, 101 obj,
101 get_pin_flag(obj_priv), 102 get_pin_flag(obj_priv),
102 obj->size, 103 obj->size,
103 obj->read_domains, obj->write_domain, 104 obj->read_domains, obj->write_domain,
104 obj_priv->last_rendering_seqno, 105 obj_priv->last_rendering_seqno,
105 obj_priv->dirty ? "dirty" : ""); 106 obj_priv->dirty ? " dirty" : "",
107 obj_priv->madv == I915_MADV_DONTNEED ? " purgeable" : "");
106 108
107 if (obj->name) 109 if (obj->name)
108 seq_printf(m, " (name: %d)", obj->name); 110 seq_printf(m, " (name: %d)", obj->name);
@@ -160,7 +162,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
160 struct drm_device *dev = node->minor->dev; 162 struct drm_device *dev = node->minor->dev;
161 drm_i915_private_t *dev_priv = dev->dev_private; 163 drm_i915_private_t *dev_priv = dev->dev_private;
162 164
163 if (!IS_IGDNG(dev)) { 165 if (!IS_IRONLAKE(dev)) {
164 seq_printf(m, "Interrupt enable: %08x\n", 166 seq_printf(m, "Interrupt enable: %08x\n",
165 I915_READ(IER)); 167 I915_READ(IER));
166 seq_printf(m, "Interrupt identity: %08x\n", 168 seq_printf(m, "Interrupt identity: %08x\n",
@@ -412,6 +414,109 @@ static int i915_registers_info(struct seq_file *m, void *data) {
412 return 0; 414 return 0;
413} 415}
414 416
417static int
418i915_wedged_open(struct inode *inode,
419 struct file *filp)
420{
421 filp->private_data = inode->i_private;
422 return 0;
423}
424
425static ssize_t
426i915_wedged_read(struct file *filp,
427 char __user *ubuf,
428 size_t max,
429 loff_t *ppos)
430{
431 struct drm_device *dev = filp->private_data;
432 drm_i915_private_t *dev_priv = dev->dev_private;
433 char buf[80];
434 int len;
435
436 len = snprintf(buf, sizeof (buf),
437 "wedged : %d\n",
438 atomic_read(&dev_priv->mm.wedged));
439
440 return simple_read_from_buffer(ubuf, max, ppos, buf, len);
441}
442
443static ssize_t
444i915_wedged_write(struct file *filp,
445 const char __user *ubuf,
446 size_t cnt,
447 loff_t *ppos)
448{
449 struct drm_device *dev = filp->private_data;
450 drm_i915_private_t *dev_priv = dev->dev_private;
451 char buf[20];
452 int val = 1;
453
454 if (cnt > 0) {
455 if (cnt > sizeof (buf) - 1)
456 return -EINVAL;
457
458 if (copy_from_user(buf, ubuf, cnt))
459 return -EFAULT;
460 buf[cnt] = 0;
461
462 val = simple_strtoul(buf, NULL, 0);
463 }
464
465 DRM_INFO("Manually setting wedged to %d\n", val);
466
467 atomic_set(&dev_priv->mm.wedged, val);
468 if (val) {
469 DRM_WAKEUP(&dev_priv->irq_queue);
470 queue_work(dev_priv->wq, &dev_priv->error_work);
471 }
472
473 return cnt;
474}
475
476static const struct file_operations i915_wedged_fops = {
477 .owner = THIS_MODULE,
478 .open = i915_wedged_open,
479 .read = i915_wedged_read,
480 .write = i915_wedged_write,
481};
482
483/* As the drm_debugfs_init() routines are called before dev->dev_private is
484 * allocated we need to hook into the minor for release. */
485static int
486drm_add_fake_info_node(struct drm_minor *minor,
487 struct dentry *ent,
488 const void *key)
489{
490 struct drm_info_node *node;
491
492 node = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
493 if (node == NULL) {
494 debugfs_remove(ent);
495 return -ENOMEM;
496 }
497
498 node->minor = minor;
499 node->dent = ent;
500 node->info_ent = (void *) key;
501 list_add(&node->list, &minor->debugfs_nodes.list);
502
503 return 0;
504}
505
506static int i915_wedged_create(struct dentry *root, struct drm_minor *minor)
507{
508 struct drm_device *dev = minor->dev;
509 struct dentry *ent;
510
511 ent = debugfs_create_file("i915_wedged",
512 S_IRUGO | S_IWUSR,
513 root, dev,
514 &i915_wedged_fops);
515 if (IS_ERR(ent))
516 return PTR_ERR(ent);
517
518 return drm_add_fake_info_node(minor, ent, &i915_wedged_fops);
519}
415 520
416static struct drm_info_list i915_debugfs_list[] = { 521static struct drm_info_list i915_debugfs_list[] = {
417 {"i915_regs", i915_registers_info, 0}, 522 {"i915_regs", i915_registers_info, 0},
@@ -432,6 +537,12 @@ static struct drm_info_list i915_debugfs_list[] = {
432 537
433int i915_debugfs_init(struct drm_minor *minor) 538int i915_debugfs_init(struct drm_minor *minor)
434{ 539{
540 int ret;
541
542 ret = i915_wedged_create(minor->debugfs_root, minor);
543 if (ret)
544 return ret;
545
435 return drm_debugfs_create_files(i915_debugfs_list, 546 return drm_debugfs_create_files(i915_debugfs_list,
436 I915_DEBUGFS_ENTRIES, 547 I915_DEBUGFS_ENTRIES,
437 minor->debugfs_root, minor); 548 minor->debugfs_root, minor);
@@ -441,7 +552,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor)
441{ 552{
442 drm_debugfs_remove_files(i915_debugfs_list, 553 drm_debugfs_remove_files(i915_debugfs_list,
443 I915_DEBUGFS_ENTRIES, minor); 554 I915_DEBUGFS_ENTRIES, minor);
555 drm_debugfs_remove_files((struct drm_info_list *) &i915_wedged_fops,
556 1, minor);
444} 557}
445 558
446#endif /* CONFIG_DEBUG_FS */ 559#endif /* CONFIG_DEBUG_FS */
447