diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 116 |
1 files changed, 115 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 26bf0552b3cb..9087c4cfb6ba 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" |
@@ -412,6 +413,109 @@ static int i915_registers_info(struct seq_file *m, void *data) { | |||
412 | return 0; | 413 | return 0; |
413 | } | 414 | } |
414 | 415 | ||
416 | static int | ||
417 | i915_wedged_open(struct inode *inode, | ||
418 | struct file *filp) | ||
419 | { | ||
420 | filp->private_data = inode->i_private; | ||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static ssize_t | ||
425 | i915_wedged_read(struct file *filp, | ||
426 | char __user *ubuf, | ||
427 | size_t max, | ||
428 | loff_t *ppos) | ||
429 | { | ||
430 | struct drm_device *dev = filp->private_data; | ||
431 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
432 | char buf[80]; | ||
433 | int len; | ||
434 | |||
435 | len = snprintf(buf, sizeof (buf), | ||
436 | "wedged : %d\n", | ||
437 | atomic_read(&dev_priv->mm.wedged)); | ||
438 | |||
439 | return simple_read_from_buffer(ubuf, max, ppos, buf, len); | ||
440 | } | ||
441 | |||
442 | static ssize_t | ||
443 | i915_wedged_write(struct file *filp, | ||
444 | const char __user *ubuf, | ||
445 | size_t cnt, | ||
446 | loff_t *ppos) | ||
447 | { | ||
448 | struct drm_device *dev = filp->private_data; | ||
449 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
450 | char buf[20]; | ||
451 | int val = 1; | ||
452 | |||
453 | if (cnt > 0) { | ||
454 | if (cnt > sizeof (buf) - 1) | ||
455 | return -EINVAL; | ||
456 | |||
457 | if (copy_from_user(buf, ubuf, cnt)) | ||
458 | return -EFAULT; | ||
459 | buf[cnt] = 0; | ||
460 | |||
461 | val = simple_strtoul(buf, NULL, 0); | ||
462 | } | ||
463 | |||
464 | DRM_INFO("Manually setting wedged to %d\n", val); | ||
465 | |||
466 | atomic_set(&dev_priv->mm.wedged, val); | ||
467 | if (val) { | ||
468 | DRM_WAKEUP(&dev_priv->irq_queue); | ||
469 | queue_work(dev_priv->wq, &dev_priv->error_work); | ||
470 | } | ||
471 | |||
472 | return cnt; | ||
473 | } | ||
474 | |||
475 | static const struct file_operations i915_wedged_fops = { | ||
476 | .owner = THIS_MODULE, | ||
477 | .open = i915_wedged_open, | ||
478 | .read = i915_wedged_read, | ||
479 | .write = i915_wedged_write, | ||
480 | }; | ||
481 | |||
482 | /* As the drm_debugfs_init() routines are called before dev->dev_private is | ||
483 | * allocated we need to hook into the minor for release. */ | ||
484 | static int | ||
485 | drm_add_fake_info_node(struct drm_minor *minor, | ||
486 | struct dentry *ent, | ||
487 | const void *key) | ||
488 | { | ||
489 | struct drm_info_node *node; | ||
490 | |||
491 | node = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL); | ||
492 | if (node == NULL) { | ||
493 | debugfs_remove(ent); | ||
494 | return -ENOMEM; | ||
495 | } | ||
496 | |||
497 | node->minor = minor; | ||
498 | node->dent = ent; | ||
499 | node->info_ent = (void *) key; | ||
500 | list_add(&node->list, &minor->debugfs_nodes.list); | ||
501 | |||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | static int i915_wedged_create(struct dentry *root, struct drm_minor *minor) | ||
506 | { | ||
507 | struct drm_device *dev = minor->dev; | ||
508 | struct dentry *ent; | ||
509 | |||
510 | ent = debugfs_create_file("i915_wedged", | ||
511 | S_IRUGO | S_IWUSR, | ||
512 | root, dev, | ||
513 | &i915_wedged_fops); | ||
514 | if (IS_ERR(ent)) | ||
515 | return PTR_ERR(ent); | ||
516 | |||
517 | return drm_add_fake_info_node(minor, ent, &i915_wedged_fops); | ||
518 | } | ||
415 | 519 | ||
416 | static struct drm_info_list i915_debugfs_list[] = { | 520 | static struct drm_info_list i915_debugfs_list[] = { |
417 | {"i915_regs", i915_registers_info, 0}, | 521 | {"i915_regs", i915_registers_info, 0}, |
@@ -432,6 +536,12 @@ static struct drm_info_list i915_debugfs_list[] = { | |||
432 | 536 | ||
433 | int i915_debugfs_init(struct drm_minor *minor) | 537 | int i915_debugfs_init(struct drm_minor *minor) |
434 | { | 538 | { |
539 | int ret; | ||
540 | |||
541 | ret = i915_wedged_create(minor->debugfs_root, minor); | ||
542 | if (ret) | ||
543 | return ret; | ||
544 | |||
435 | return drm_debugfs_create_files(i915_debugfs_list, | 545 | return drm_debugfs_create_files(i915_debugfs_list, |
436 | I915_DEBUGFS_ENTRIES, | 546 | I915_DEBUGFS_ENTRIES, |
437 | minor->debugfs_root, minor); | 547 | minor->debugfs_root, minor); |
@@ -439,9 +549,13 @@ int i915_debugfs_init(struct drm_minor *minor) | |||
439 | 549 | ||
440 | void i915_debugfs_cleanup(struct drm_minor *minor) | 550 | void i915_debugfs_cleanup(struct drm_minor *minor) |
441 | { | 551 | { |
552 | const void *key; | ||
553 | |||
442 | drm_debugfs_remove_files(i915_debugfs_list, | 554 | drm_debugfs_remove_files(i915_debugfs_list, |
443 | I915_DEBUGFS_ENTRIES, minor); | 555 | I915_DEBUGFS_ENTRIES, minor); |
556 | |||
557 | key = &i915_wedged_fops; | ||
558 | drm_debugfs_remove_files((struct drm_info_list *) &key, 1, minor); | ||
444 | } | 559 | } |
445 | 560 | ||
446 | #endif /* CONFIG_DEBUG_FS */ | 561 | #endif /* CONFIG_DEBUG_FS */ |
447 | |||