aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-11-22 03:56:33 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2010-11-22 03:56:33 -0500
commita940a75a9a4b0f2523fd6d944d1c8099e7da9bbb (patch)
treee2b9804379a6aab3d2471898d257fe5590feb70c /drivers/gpu/drm/i915
parent8b5abbe0683f285e1311c4cc29c79da07d18d0af (diff)
parente624ae8e0d4243e71daedce7570e91290438eaca (diff)
Merge branch 'drm-intel-next' of arrandale:git/linux-2.6 into drm-intel-next
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c66
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c3
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h12
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c72
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c86
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h6
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c40
-rw-r--r--drivers/gpu/drm/i915/intel_display.c110
8 files changed, 281 insertions, 114 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 4c8fae9baaad..421b8414b577 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -609,6 +609,36 @@ static const char *purgeable_flag(int purgeable)
609 return purgeable ? " purgeable" : ""; 609 return purgeable ? " purgeable" : "";
610} 610}
611 611
612static void print_error_buffers(struct seq_file *m,
613 const char *name,
614 struct drm_i915_error_buffer *err,
615 int count)
616{
617 seq_printf(m, "%s [%d]:\n", name, count);
618
619 while (count--) {
620 seq_printf(m, " %08x %8zd %04x %04x %08x%s%s%s%s%s",
621 err->gtt_offset,
622 err->size,
623 err->read_domains,
624 err->write_domain,
625 err->seqno,
626 pin_flag(err->pinned),
627 tiling_flag(err->tiling),
628 dirty_flag(err->dirty),
629 purgeable_flag(err->purgeable),
630 ring_str(err->ring));
631
632 if (err->name)
633 seq_printf(m, " (name: %d)", err->name);
634 if (err->fence_reg != I915_FENCE_REG_NONE)
635 seq_printf(m, " (fence: %d)", err->fence_reg);
636
637 seq_printf(m, "\n");
638 err++;
639 }
640}
641
612static int i915_error_state(struct seq_file *m, void *unused) 642static int i915_error_state(struct seq_file *m, void *unused)
613{ 643{
614 struct drm_info_node *node = (struct drm_info_node *) m->private; 644 struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -658,30 +688,15 @@ static int i915_error_state(struct seq_file *m, void *unused)
658 seq_printf(m, " INSTPM: 0x%08x\n", error->instpm); 688 seq_printf(m, " INSTPM: 0x%08x\n", error->instpm);
659 seq_printf(m, " seqno: 0x%08x\n", error->seqno); 689 seq_printf(m, " seqno: 0x%08x\n", error->seqno);
660 690
661 if (error->active_bo_count) { 691 if (error->active_bo)
662 seq_printf(m, "Buffers [%d]:\n", error->active_bo_count); 692 print_error_buffers(m, "Active",
663 693 error->active_bo,
664 for (i = 0; i < error->active_bo_count; i++) { 694 error->active_bo_count);
665 seq_printf(m, " %08x %8zd %08x %08x %08x%s%s%s%s %s", 695
666 error->active_bo[i].gtt_offset, 696 if (error->pinned_bo)
667 error->active_bo[i].size, 697 print_error_buffers(m, "Pinned",
668 error->active_bo[i].read_domains, 698 error->pinned_bo,
669 error->active_bo[i].write_domain, 699 error->pinned_bo_count);
670 error->active_bo[i].seqno,
671 pin_flag(error->active_bo[i].pinned),
672 tiling_flag(error->active_bo[i].tiling),
673 dirty_flag(error->active_bo[i].dirty),
674 purgeable_flag(error->active_bo[i].purgeable),
675 ring_str(error->active_bo[i].ring));
676
677 if (error->active_bo[i].name)
678 seq_printf(m, " (name: %d)", error->active_bo[i].name);
679 if (error->active_bo[i].fence_reg != I915_FENCE_REG_NONE)
680 seq_printf(m, " (fence: %d)", error->active_bo[i].fence_reg);
681
682 seq_printf(m, "\n");
683 }
684 }
685 700
686 for (i = 0; i < ARRAY_SIZE(error->batchbuffer); i++) { 701 for (i = 0; i < ARRAY_SIZE(error->batchbuffer); i++) {
687 if (error->batchbuffer[i]) { 702 if (error->batchbuffer[i]) {
@@ -714,6 +729,9 @@ static int i915_error_state(struct seq_file *m, void *unused)
714 if (error->overlay) 729 if (error->overlay)
715 intel_overlay_print_error_state(m, error->overlay); 730 intel_overlay_print_error_state(m, error->overlay);
716 731
732 if (error->display)
733 intel_display_print_error_state(m, dev, error->display);
734
717out: 735out:
718 spin_unlock_irqrestore(&dev_priv->error_lock, flags); 736 spin_unlock_irqrestore(&dev_priv->error_lock, flags);
719 737
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 57e892d484ad..f0e6bd06fc0e 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -150,7 +150,8 @@ static const struct intel_device_info intel_ironlake_d_info = {
150 150
151static const struct intel_device_info intel_ironlake_m_info = { 151static const struct intel_device_info intel_ironlake_m_info = {
152 .gen = 5, .is_mobile = 1, 152 .gen = 5, .is_mobile = 1,
153 .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1, 153 .need_gfx_hws = 1, .has_rc6 = 1, .has_hotplug = 1,
154 .has_fbc = 0, /* disabled due to buggy hardware */
154 .has_bsd_ring = 1, 155 .has_bsd_ring = 1,
155}; 156};
156 157
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 73a41f7ab8c6..4c20ad92c0f3 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -140,6 +140,8 @@ struct sdvo_device_mapping {
140 u8 ddc_pin; 140 u8 ddc_pin;
141}; 141};
142 142
143struct intel_display_error_state;
144
143struct drm_i915_error_state { 145struct drm_i915_error_state {
144 u32 eir; 146 u32 eir;
145 u32 pgtbl_er; 147 u32 pgtbl_er;
@@ -184,9 +186,10 @@ struct drm_i915_error_state {
184 u32 dirty:1; 186 u32 dirty:1;
185 u32 purgeable:1; 187 u32 purgeable:1;
186 u32 ring:4; 188 u32 ring:4;
187 } *active_bo; 189 } *active_bo, *pinned_bo;
188 u32 active_bo_count; 190 u32 active_bo_count, pinned_bo_count;
189 struct intel_overlay_error_state *overlay; 191 struct intel_overlay_error_state *overlay;
192 struct intel_display_error_state *display;
190}; 193};
191 194
192struct drm_i915_display_funcs { 195struct drm_i915_display_funcs {
@@ -1223,6 +1226,11 @@ extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
1223#ifdef CONFIG_DEBUG_FS 1226#ifdef CONFIG_DEBUG_FS
1224extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); 1227extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
1225extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error); 1228extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error);
1229
1230extern struct intel_display_error_state *intel_display_capture_error_state(struct drm_device *dev);
1231extern void intel_display_print_error_state(struct seq_file *m,
1232 struct drm_device *dev,
1233 struct intel_display_error_state *error);
1226#endif 1234#endif
1227 1235
1228/** 1236/**
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 54fc1e7eb872..4010cd34283d 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -581,6 +581,19 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
581 struct drm_i915_gem_object *obj_priv; 581 struct drm_i915_gem_object *obj_priv;
582 int ret = 0; 582 int ret = 0;
583 583
584 if (args->size == 0)
585 return 0;
586
587 if (!access_ok(VERIFY_WRITE,
588 (char __user *)(uintptr_t)args->data_ptr,
589 args->size))
590 return -EFAULT;
591
592 ret = fault_in_pages_writeable((char __user *)(uintptr_t)args->data_ptr,
593 args->size);
594 if (ret)
595 return -EFAULT;
596
584 ret = i915_mutex_lock_interruptible(dev); 597 ret = i915_mutex_lock_interruptible(dev);
585 if (ret) 598 if (ret)
586 return ret; 599 return ret;
@@ -598,23 +611,6 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
598 goto out; 611 goto out;
599 } 612 }
600 613
601 if (args->size == 0)
602 goto out;
603
604 if (!access_ok(VERIFY_WRITE,
605 (char __user *)(uintptr_t)args->data_ptr,
606 args->size)) {
607 ret = -EFAULT;
608 goto out;
609 }
610
611 ret = fault_in_pages_writeable((char __user *)(uintptr_t)args->data_ptr,
612 args->size);
613 if (ret) {
614 ret = -EFAULT;
615 goto out;
616 }
617
618 ret = i915_gem_object_set_cpu_read_domain_range(obj, 614 ret = i915_gem_object_set_cpu_read_domain_range(obj,
619 args->offset, 615 args->offset,
620 args->size); 616 args->size);
@@ -1025,7 +1021,20 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
1025 struct drm_i915_gem_pwrite *args = data; 1021 struct drm_i915_gem_pwrite *args = data;
1026 struct drm_gem_object *obj; 1022 struct drm_gem_object *obj;
1027 struct drm_i915_gem_object *obj_priv; 1023 struct drm_i915_gem_object *obj_priv;
1028 int ret = 0; 1024 int ret;
1025
1026 if (args->size == 0)
1027 return 0;
1028
1029 if (!access_ok(VERIFY_READ,
1030 (char __user *)(uintptr_t)args->data_ptr,
1031 args->size))
1032 return -EFAULT;
1033
1034 ret = fault_in_pages_readable((char __user *)(uintptr_t)args->data_ptr,
1035 args->size);
1036 if (ret)
1037 return -EFAULT;
1029 1038
1030 ret = i915_mutex_lock_interruptible(dev); 1039 ret = i915_mutex_lock_interruptible(dev);
1031 if (ret) 1040 if (ret)
@@ -1038,30 +1047,12 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
1038 } 1047 }
1039 obj_priv = to_intel_bo(obj); 1048 obj_priv = to_intel_bo(obj);
1040 1049
1041
1042 /* Bounds check destination. */ 1050 /* Bounds check destination. */
1043 if (args->offset > obj->size || args->size > obj->size - args->offset) { 1051 if (args->offset > obj->size || args->size > obj->size - args->offset) {
1044 ret = -EINVAL; 1052 ret = -EINVAL;
1045 goto out; 1053 goto out;
1046 } 1054 }
1047 1055
1048 if (args->size == 0)
1049 goto out;
1050
1051 if (!access_ok(VERIFY_READ,
1052 (char __user *)(uintptr_t)args->data_ptr,
1053 args->size)) {
1054 ret = -EFAULT;
1055 goto out;
1056 }
1057
1058 ret = fault_in_pages_readable((char __user *)(uintptr_t)args->data_ptr,
1059 args->size);
1060 if (ret) {
1061 ret = -EFAULT;
1062 goto out;
1063 }
1064
1065 /* We can only do the GTT pwrite on untiled buffers, as otherwise 1056 /* We can only do the GTT pwrite on untiled buffers, as otherwise
1066 * it would end up going through the fenced access, and we'll get 1057 * it would end up going through the fenced access, and we'll get
1067 * different detiling behavior between reading and writing. 1058 * different detiling behavior between reading and writing.
@@ -3759,8 +3750,15 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
3759 3750
3760 for (i = 0; i < count; i++) { 3751 for (i = 0; i < count; i++) {
3761 char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr; 3752 char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr;
3762 size_t length = exec[i].relocation_count * sizeof(struct drm_i915_gem_relocation_entry); 3753 int length; /* limited by fault_in_pages_readable() */
3754
3755 /* First check for malicious input causing overflow */
3756 if (exec[i].relocation_count >
3757 INT_MAX / sizeof(struct drm_i915_gem_relocation_entry))
3758 return -EINVAL;
3763 3759
3760 length = exec[i].relocation_count *
3761 sizeof(struct drm_i915_gem_relocation_entry);
3764 if (!access_ok(VERIFY_READ, ptr, length)) 3762 if (!access_ok(VERIFY_READ, ptr, length))
3765 return -EFAULT; 3763 return -EFAULT;
3766 3764
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index ef3503733ebb..0b6052abedd1 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -552,6 +552,40 @@ i915_ringbuffer_last_batch(struct drm_device *dev,
552 return bbaddr; 552 return bbaddr;
553} 553}
554 554
555static u32 capture_bo_list(struct drm_i915_error_buffer *err,
556 int count,
557 struct list_head *head)
558{
559 struct drm_i915_gem_object *obj;
560 int i = 0;
561
562 list_for_each_entry(obj, head, mm_list) {
563 err->size = obj->base.size;
564 err->name = obj->base.name;
565 err->seqno = obj->last_rendering_seqno;
566 err->gtt_offset = obj->gtt_offset;
567 err->read_domains = obj->base.read_domains;
568 err->write_domain = obj->base.write_domain;
569 err->fence_reg = obj->fence_reg;
570 err->pinned = 0;
571 if (obj->pin_count > 0)
572 err->pinned = 1;
573 if (obj->user_pin_count > 0)
574 err->pinned = -1;
575 err->tiling = obj->tiling_mode;
576 err->dirty = obj->dirty;
577 err->purgeable = obj->madv != I915_MADV_WILLNEED;
578 err->ring = obj->ring->id;
579
580 if (++i == count)
581 break;
582
583 err++;
584 }
585
586 return i;
587}
588
555/** 589/**
556 * i915_capture_error_state - capture an error record for later analysis 590 * i915_capture_error_state - capture an error record for later analysis
557 * @dev: drm device 591 * @dev: drm device
@@ -700,45 +734,39 @@ static void i915_capture_error_state(struct drm_device *dev)
700 error->ringbuffer = i915_error_object_create(dev, 734 error->ringbuffer = i915_error_object_create(dev,
701 dev_priv->render_ring.gem_object); 735 dev_priv->render_ring.gem_object);
702 736
703 /* Record buffers on the active list. */ 737 /* Record buffers on the active and pinned lists. */
704 error->active_bo = NULL; 738 error->active_bo = NULL;
705 error->active_bo_count = 0; 739 error->pinned_bo = NULL;
706 740
707 if (count) 741 error->active_bo_count = count;
742 list_for_each_entry(obj_priv, &dev_priv->mm.pinned_list, mm_list)
743 count++;
744 error->pinned_bo_count = count - error->active_bo_count;
745
746 if (count) {
708 error->active_bo = kmalloc(sizeof(*error->active_bo)*count, 747 error->active_bo = kmalloc(sizeof(*error->active_bo)*count,
709 GFP_ATOMIC); 748 GFP_ATOMIC);
749 if (error->active_bo)
750 error->pinned_bo =
751 error->active_bo + error->active_bo_count;
752 }
710 753
711 if (error->active_bo) { 754 if (error->active_bo)
712 int i = 0; 755 error->active_bo_count =
713 list_for_each_entry(obj_priv, &dev_priv->mm.active_list, mm_list) { 756 capture_bo_list(error->active_bo,
714 struct drm_gem_object *obj = &obj_priv->base; 757 error->active_bo_count,
758 &dev_priv->mm.active_list);
715 759
716 error->active_bo[i].size = obj->size; 760 if (error->pinned_bo)
717 error->active_bo[i].name = obj->name; 761 error->pinned_bo_count =
718 error->active_bo[i].seqno = obj_priv->last_rendering_seqno; 762 capture_bo_list(error->pinned_bo,
719 error->active_bo[i].gtt_offset = obj_priv->gtt_offset; 763 error->pinned_bo_count,
720 error->active_bo[i].read_domains = obj->read_domains; 764 &dev_priv->mm.pinned_list);
721 error->active_bo[i].write_domain = obj->write_domain;
722 error->active_bo[i].fence_reg = obj_priv->fence_reg;
723 error->active_bo[i].pinned = 0;
724 if (obj_priv->pin_count > 0)
725 error->active_bo[i].pinned = 1;
726 if (obj_priv->user_pin_count > 0)
727 error->active_bo[i].pinned = -1;
728 error->active_bo[i].tiling = obj_priv->tiling_mode;
729 error->active_bo[i].dirty = obj_priv->dirty;
730 error->active_bo[i].purgeable = obj_priv->madv != I915_MADV_WILLNEED;
731 error->active_bo[i].ring = obj_priv->ring->id;
732
733 if (++i == count)
734 break;
735 }
736 error->active_bo_count = i;
737 }
738 765
739 do_gettimeofday(&error->time); 766 do_gettimeofday(&error->time);
740 767
741 error->overlay = intel_overlay_capture_error_state(dev); 768 error->overlay = intel_overlay_capture_error_state(dev);
769 error->display = intel_display_capture_error_state(dev);
742 770
743 spin_lock_irqsave(&dev_priv->error_lock, flags); 771 spin_lock_irqsave(&dev_priv->error_lock, flags);
744 if (dev_priv->first_error == NULL) { 772 if (dev_priv->first_error == NULL) {
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 886c0e072490..ec2a8b07ba5b 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1193,7 +1193,6 @@
1193#define VTOTAL(pipe) _PIPE(pipe, VTOTAL_A, VTOTAL_B) 1193#define VTOTAL(pipe) _PIPE(pipe, VTOTAL_A, VTOTAL_B)
1194#define VBLANK(pipe) _PIPE(pipe, VBLANK_A, VBLANK_B) 1194#define VBLANK(pipe) _PIPE(pipe, VBLANK_A, VBLANK_B)
1195#define VSYNC(pipe) _PIPE(pipe, VSYNC_A, VSYNC_B) 1195#define VSYNC(pipe) _PIPE(pipe, VSYNC_A, VSYNC_B)
1196#define PIPESRC(pipe) _PIPE(pipe, PIPEASRC, PIPEBSRC)
1197#define BCLRPAT(pipe) _PIPE(pipe, BCLRPAT_A, BCLRPAT_B) 1196#define BCLRPAT(pipe) _PIPE(pipe, BCLRPAT_A, BCLRPAT_B)
1198 1197
1199/* VGA port control */ 1198/* VGA port control */
@@ -2207,6 +2206,7 @@
2207#define PIPE_6BPC (2 << 5) 2206#define PIPE_6BPC (2 << 5)
2208#define PIPE_12BPC (3 << 5) 2207#define PIPE_12BPC (3 << 5)
2209 2208
2209#define PIPESRC(pipe) _PIPE(pipe, PIPEASRC, PIPEBSRC)
2210#define PIPECONF(pipe) _PIPE(pipe, PIPEACONF, PIPEBCONF) 2210#define PIPECONF(pipe) _PIPE(pipe, PIPEACONF, PIPEBCONF)
2211#define PIPEDSL(pipe) _PIPE(pipe, PIPEADSL, PIPEBDSL) 2211#define PIPEDSL(pipe) _PIPE(pipe, PIPEADSL, PIPEBDSL)
2212 2212
@@ -2376,6 +2376,10 @@
2376#define CURBBASE 0x700c4 2376#define CURBBASE 0x700c4
2377#define CURBPOS 0x700c8 2377#define CURBPOS 0x700c8
2378 2378
2379#define CURCNTR(pipe) _PIPE(pipe, CURACNTR, CURBCNTR)
2380#define CURBASE(pipe) _PIPE(pipe, CURABASE, CURBBASE)
2381#define CURPOS(pipe) _PIPE(pipe, CURAPOS, CURBPOS)
2382
2379/* Display A control */ 2383/* Display A control */
2380#define DSPACNTR 0x70180 2384#define DSPACNTR 0x70180
2381#define DISPLAY_PLANE_ENABLE (1<<31) 2385#define DISPLAY_PLANE_ENABLE (1<<31)
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 454c064f8ef7..42729d25da58 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -239,6 +239,16 @@ static void i915_save_modeset_reg(struct drm_device *dev)
239 if (drm_core_check_feature(dev, DRIVER_MODESET)) 239 if (drm_core_check_feature(dev, DRIVER_MODESET))
240 return; 240 return;
241 241
242 /* Cursor state */
243 dev_priv->saveCURACNTR = I915_READ(CURACNTR);
244 dev_priv->saveCURAPOS = I915_READ(CURAPOS);
245 dev_priv->saveCURABASE = I915_READ(CURABASE);
246 dev_priv->saveCURBCNTR = I915_READ(CURBCNTR);
247 dev_priv->saveCURBPOS = I915_READ(CURBPOS);
248 dev_priv->saveCURBBASE = I915_READ(CURBBASE);
249 if (IS_GEN2(dev))
250 dev_priv->saveCURSIZE = I915_READ(CURSIZE);
251
242 if (HAS_PCH_SPLIT(dev)) { 252 if (HAS_PCH_SPLIT(dev)) {
243 dev_priv->savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL); 253 dev_priv->savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL);
244 dev_priv->saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL); 254 dev_priv->saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL);
@@ -529,6 +539,16 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
529 I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); 539 I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
530 I915_WRITE(DSPBADDR, I915_READ(DSPBADDR)); 540 I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
531 541
542 /* Cursor state */
543 I915_WRITE(CURAPOS, dev_priv->saveCURAPOS);
544 I915_WRITE(CURACNTR, dev_priv->saveCURACNTR);
545 I915_WRITE(CURABASE, dev_priv->saveCURABASE);
546 I915_WRITE(CURBPOS, dev_priv->saveCURBPOS);
547 I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR);
548 I915_WRITE(CURBBASE, dev_priv->saveCURBBASE);
549 if (IS_GEN2(dev))
550 I915_WRITE(CURSIZE, dev_priv->saveCURSIZE);
551
532 return; 552 return;
533} 553}
534 554
@@ -543,16 +563,6 @@ void i915_save_display(struct drm_device *dev)
543 /* Don't save them in KMS mode */ 563 /* Don't save them in KMS mode */
544 i915_save_modeset_reg(dev); 564 i915_save_modeset_reg(dev);
545 565
546 /* Cursor state */
547 dev_priv->saveCURACNTR = I915_READ(CURACNTR);
548 dev_priv->saveCURAPOS = I915_READ(CURAPOS);
549 dev_priv->saveCURABASE = I915_READ(CURABASE);
550 dev_priv->saveCURBCNTR = I915_READ(CURBCNTR);
551 dev_priv->saveCURBPOS = I915_READ(CURBPOS);
552 dev_priv->saveCURBBASE = I915_READ(CURBBASE);
553 if (IS_GEN2(dev))
554 dev_priv->saveCURSIZE = I915_READ(CURSIZE);
555
556 /* CRT state */ 566 /* CRT state */
557 if (HAS_PCH_SPLIT(dev)) { 567 if (HAS_PCH_SPLIT(dev)) {
558 dev_priv->saveADPA = I915_READ(PCH_ADPA); 568 dev_priv->saveADPA = I915_READ(PCH_ADPA);
@@ -657,16 +667,6 @@ void i915_restore_display(struct drm_device *dev)
657 /* Don't restore them in KMS mode */ 667 /* Don't restore them in KMS mode */
658 i915_restore_modeset_reg(dev); 668 i915_restore_modeset_reg(dev);
659 669
660 /* Cursor state */
661 I915_WRITE(CURAPOS, dev_priv->saveCURAPOS);
662 I915_WRITE(CURACNTR, dev_priv->saveCURACNTR);
663 I915_WRITE(CURABASE, dev_priv->saveCURABASE);
664 I915_WRITE(CURBPOS, dev_priv->saveCURBPOS);
665 I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR);
666 I915_WRITE(CURBBASE, dev_priv->saveCURBBASE);
667 if (IS_GEN2(dev))
668 I915_WRITE(CURSIZE, dev_priv->saveCURSIZE);
669
670 /* CRT state */ 670 /* CRT state */
671 if (HAS_PCH_SPLIT(dev)) 671 if (HAS_PCH_SPLIT(dev))
672 I915_WRITE(PCH_ADPA, dev_priv->saveADPA); 672 I915_WRITE(PCH_ADPA, dev_priv->saveADPA);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3fa5aaa941d2..d4bc443f43fc 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6269,3 +6269,113 @@ int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
6269 pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl); 6269 pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl);
6270 return 0; 6270 return 0;
6271} 6271}
6272
6273#ifdef CONFIG_DEBUG_FS
6274#include <linux/seq_file.h>
6275
6276struct intel_display_error_state {
6277 struct intel_cursor_error_state {
6278 u32 control;
6279 u32 position;
6280 u32 base;
6281 u32 size;
6282 } cursor[2];
6283
6284 struct intel_pipe_error_state {
6285 u32 conf;
6286 u32 source;
6287
6288 u32 htotal;
6289 u32 hblank;
6290 u32 hsync;
6291 u32 vtotal;
6292 u32 vblank;
6293 u32 vsync;
6294 } pipe[2];
6295
6296 struct intel_plane_error_state {
6297 u32 control;
6298 u32 stride;
6299 u32 size;
6300 u32 pos;
6301 u32 addr;
6302 u32 surface;
6303 u32 tile_offset;
6304 } plane[2];
6305};
6306
6307struct intel_display_error_state *
6308intel_display_capture_error_state(struct drm_device *dev)
6309{
6310 drm_i915_private_t *dev_priv = dev->dev_private;
6311 struct intel_display_error_state *error;
6312 int i;
6313
6314 error = kmalloc(sizeof(*error), GFP_ATOMIC);
6315 if (error == NULL)
6316 return NULL;
6317
6318 for (i = 0; i < 2; i++) {
6319 error->cursor[i].control = I915_READ(CURCNTR(i));
6320 error->cursor[i].position = I915_READ(CURPOS(i));
6321 error->cursor[i].base = I915_READ(CURBASE(i));
6322
6323 error->plane[i].control = I915_READ(DSPCNTR(i));
6324 error->plane[i].stride = I915_READ(DSPSTRIDE(i));
6325 error->plane[i].size = I915_READ(DSPSIZE(i));
6326 error->plane[i].pos= I915_READ(DSPPOS(i));
6327 error->plane[i].addr = I915_READ(DSPADDR(i));
6328 if (INTEL_INFO(dev)->gen >= 4) {
6329 error->plane[i].surface = I915_READ(DSPSURF(i));
6330 error->plane[i].tile_offset = I915_READ(DSPTILEOFF(i));
6331 }
6332
6333 error->pipe[i].conf = I915_READ(PIPECONF(i));
6334 error->pipe[i].source = I915_READ(PIPESRC(i));
6335 error->pipe[i].htotal = I915_READ(HTOTAL(i));
6336 error->pipe[i].hblank = I915_READ(HBLANK(i));
6337 error->pipe[i].hsync = I915_READ(HSYNC(i));
6338 error->pipe[i].vtotal = I915_READ(VTOTAL(i));
6339 error->pipe[i].vblank = I915_READ(VBLANK(i));
6340 error->pipe[i].vsync = I915_READ(VSYNC(i));
6341 }
6342
6343 return error;
6344}
6345
6346void
6347intel_display_print_error_state(struct seq_file *m,
6348 struct drm_device *dev,
6349 struct intel_display_error_state *error)
6350{
6351 int i;
6352
6353 for (i = 0; i < 2; i++) {
6354 seq_printf(m, "Pipe [%d]:\n", i);
6355 seq_printf(m, " CONF: %08x\n", error->pipe[i].conf);
6356 seq_printf(m, " SRC: %08x\n", error->pipe[i].source);
6357 seq_printf(m, " HTOTAL: %08x\n", error->pipe[i].htotal);
6358 seq_printf(m, " HBLANK: %08x\n", error->pipe[i].hblank);
6359 seq_printf(m, " HSYNC: %08x\n", error->pipe[i].hsync);
6360 seq_printf(m, " VTOTAL: %08x\n", error->pipe[i].vtotal);
6361 seq_printf(m, " VBLANK: %08x\n", error->pipe[i].vblank);
6362 seq_printf(m, " VSYNC: %08x\n", error->pipe[i].vsync);
6363
6364 seq_printf(m, "Plane [%d]:\n", i);
6365 seq_printf(m, " CNTR: %08x\n", error->plane[i].control);
6366 seq_printf(m, " STRIDE: %08x\n", error->plane[i].stride);
6367 seq_printf(m, " SIZE: %08x\n", error->plane[i].size);
6368 seq_printf(m, " POS: %08x\n", error->plane[i].pos);
6369 seq_printf(m, " ADDR: %08x\n", error->plane[i].addr);
6370 if (INTEL_INFO(dev)->gen >= 4) {
6371 seq_printf(m, " SURF: %08x\n", error->plane[i].surface);
6372 seq_printf(m, " TILEOFF: %08x\n", error->plane[i].tile_offset);
6373 }
6374
6375 seq_printf(m, "Cursor [%d]:\n", i);
6376 seq_printf(m, " CNTR: %08x\n", error->cursor[i].control);
6377 seq_printf(m, " POS: %08x\n", error->cursor[i].position);
6378 seq_printf(m, " BASE: %08x\n", error->cursor[i].base);
6379 }
6380}
6381#endif