diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-11-22 03:56:33 -0500 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-11-22 03:56:33 -0500 |
commit | a940a75a9a4b0f2523fd6d944d1c8099e7da9bbb (patch) | |
tree | e2b9804379a6aab3d2471898d257fe5590feb70c /drivers/gpu/drm/i915 | |
parent | 8b5abbe0683f285e1311c4cc29c79da07d18d0af (diff) | |
parent | e624ae8e0d4243e71daedce7570e91290438eaca (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.c | 66 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 72 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 86 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_suspend.c | 40 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 110 |
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 | ||
612 | static 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 | |||
612 | static int i915_error_state(struct seq_file *m, void *unused) | 642 | static 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 | |||
717 | out: | 735 | out: |
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 | ||
151 | static const struct intel_device_info intel_ironlake_m_info = { | 151 | static 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 | ||
143 | struct intel_display_error_state; | ||
144 | |||
143 | struct drm_i915_error_state { | 145 | struct 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 | ||
192 | struct drm_i915_display_funcs { | 195 | struct 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 |
1224 | extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); | 1227 | extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); |
1225 | extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error); | 1228 | extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error); |
1229 | |||
1230 | extern struct intel_display_error_state *intel_display_capture_error_state(struct drm_device *dev); | ||
1231 | extern 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 | ||
555 | static 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 | |||
6276 | struct 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 | |||
6307 | struct intel_display_error_state * | ||
6308 | intel_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 | |||
6346 | void | ||
6347 | intel_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 | ||