diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 76 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 4 |
4 files changed, 78 insertions, 12 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 69d8ed5416c3..2ad27880cd04 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -505,6 +505,8 @@ static int i915_drm_freeze(struct drm_device *dev) | |||
505 | intel_modeset_suspend_hw(dev); | 505 | intel_modeset_suspend_hw(dev); |
506 | } | 506 | } |
507 | 507 | ||
508 | i915_gem_suspend_gtt_mappings(dev); | ||
509 | |||
508 | i915_save_state(dev); | 510 | i915_save_state(dev); |
509 | 511 | ||
510 | intel_opregion_fini(dev); | 512 | intel_opregion_fini(dev); |
@@ -648,7 +650,8 @@ static int i915_drm_thaw(struct drm_device *dev) | |||
648 | mutex_lock(&dev->struct_mutex); | 650 | mutex_lock(&dev->struct_mutex); |
649 | i915_gem_restore_gtt_mappings(dev); | 651 | i915_gem_restore_gtt_mappings(dev); |
650 | mutex_unlock(&dev->struct_mutex); | 652 | mutex_unlock(&dev->struct_mutex); |
651 | } | 653 | } else if (drm_core_check_feature(dev, DRIVER_MODESET)) |
654 | i915_check_and_clear_faults(dev); | ||
652 | 655 | ||
653 | __i915_drm_thaw(dev); | 656 | __i915_drm_thaw(dev); |
654 | 657 | ||
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3979a81dd6ee..ab0f2c0a440c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -501,7 +501,8 @@ struct i915_address_space { | |||
501 | bool valid); /* Create a valid PTE */ | 501 | bool valid); /* Create a valid PTE */ |
502 | void (*clear_range)(struct i915_address_space *vm, | 502 | void (*clear_range)(struct i915_address_space *vm, |
503 | unsigned int first_entry, | 503 | unsigned int first_entry, |
504 | unsigned int num_entries); | 504 | unsigned int num_entries, |
505 | bool use_scratch); | ||
505 | void (*insert_entries)(struct i915_address_space *vm, | 506 | void (*insert_entries)(struct i915_address_space *vm, |
506 | struct sg_table *st, | 507 | struct sg_table *st, |
507 | unsigned int first_entry, | 508 | unsigned int first_entry, |
@@ -2066,6 +2067,8 @@ void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, | |||
2066 | void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, | 2067 | void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, |
2067 | struct drm_i915_gem_object *obj); | 2068 | struct drm_i915_gem_object *obj); |
2068 | 2069 | ||
2070 | void i915_check_and_clear_faults(struct drm_device *dev); | ||
2071 | void i915_gem_suspend_gtt_mappings(struct drm_device *dev); | ||
2069 | void i915_gem_restore_gtt_mappings(struct drm_device *dev); | 2072 | void i915_gem_restore_gtt_mappings(struct drm_device *dev); |
2070 | int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj); | 2073 | int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj); |
2071 | void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj, | 2074 | void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj, |
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 32aa69d7ef20..1f7b4caefb6e 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c | |||
@@ -241,7 +241,8 @@ static int gen6_ppgtt_enable(struct drm_device *dev) | |||
241 | /* PPGTT support for Sandybdrige/Gen6 and later */ | 241 | /* PPGTT support for Sandybdrige/Gen6 and later */ |
242 | static void gen6_ppgtt_clear_range(struct i915_address_space *vm, | 242 | static void gen6_ppgtt_clear_range(struct i915_address_space *vm, |
243 | unsigned first_entry, | 243 | unsigned first_entry, |
244 | unsigned num_entries) | 244 | unsigned num_entries, |
245 | bool use_scratch) | ||
245 | { | 246 | { |
246 | struct i915_hw_ppgtt *ppgtt = | 247 | struct i915_hw_ppgtt *ppgtt = |
247 | container_of(vm, struct i915_hw_ppgtt, base); | 248 | container_of(vm, struct i915_hw_ppgtt, base); |
@@ -372,7 +373,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) | |||
372 | } | 373 | } |
373 | 374 | ||
374 | ppgtt->base.clear_range(&ppgtt->base, 0, | 375 | ppgtt->base.clear_range(&ppgtt->base, 0, |
375 | ppgtt->num_pd_entries * I915_PPGTT_PT_ENTRIES); | 376 | ppgtt->num_pd_entries * I915_PPGTT_PT_ENTRIES, true); |
376 | 377 | ||
377 | ppgtt->pd_offset = first_pd_entry_in_global_pt * sizeof(gen6_gtt_pte_t); | 378 | ppgtt->pd_offset = first_pd_entry_in_global_pt * sizeof(gen6_gtt_pte_t); |
378 | 379 | ||
@@ -449,7 +450,8 @@ void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, | |||
449 | { | 450 | { |
450 | ppgtt->base.clear_range(&ppgtt->base, | 451 | ppgtt->base.clear_range(&ppgtt->base, |
451 | i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT, | 452 | i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT, |
452 | obj->base.size >> PAGE_SHIFT); | 453 | obj->base.size >> PAGE_SHIFT, |
454 | true); | ||
453 | } | 455 | } |
454 | 456 | ||
455 | extern int intel_iommu_gfx_mapped; | 457 | extern int intel_iommu_gfx_mapped; |
@@ -490,15 +492,65 @@ static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible) | |||
490 | dev_priv->mm.interruptible = interruptible; | 492 | dev_priv->mm.interruptible = interruptible; |
491 | } | 493 | } |
492 | 494 | ||
495 | void i915_check_and_clear_faults(struct drm_device *dev) | ||
496 | { | ||
497 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
498 | struct intel_ring_buffer *ring; | ||
499 | int i; | ||
500 | |||
501 | if (INTEL_INFO(dev)->gen < 6) | ||
502 | return; | ||
503 | |||
504 | for_each_ring(ring, dev_priv, i) { | ||
505 | u32 fault_reg; | ||
506 | fault_reg = I915_READ(RING_FAULT_REG(ring)); | ||
507 | if (fault_reg & RING_FAULT_VALID) { | ||
508 | DRM_DEBUG_DRIVER("Unexpected fault\n" | ||
509 | "\tAddr: 0x%08lx\\n" | ||
510 | "\tAddress space: %s\n" | ||
511 | "\tSource ID: %d\n" | ||
512 | "\tType: %d\n", | ||
513 | fault_reg & PAGE_MASK, | ||
514 | fault_reg & RING_FAULT_GTTSEL_MASK ? "GGTT" : "PPGTT", | ||
515 | RING_FAULT_SRCID(fault_reg), | ||
516 | RING_FAULT_FAULT_TYPE(fault_reg)); | ||
517 | I915_WRITE(RING_FAULT_REG(ring), | ||
518 | fault_reg & ~RING_FAULT_VALID); | ||
519 | } | ||
520 | } | ||
521 | POSTING_READ(RING_FAULT_REG(&dev_priv->ring[RCS])); | ||
522 | } | ||
523 | |||
524 | void i915_gem_suspend_gtt_mappings(struct drm_device *dev) | ||
525 | { | ||
526 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
527 | |||
528 | /* Don't bother messing with faults pre GEN6 as we have little | ||
529 | * documentation supporting that it's a good idea. | ||
530 | */ | ||
531 | if (INTEL_INFO(dev)->gen < 6) | ||
532 | return; | ||
533 | |||
534 | i915_check_and_clear_faults(dev); | ||
535 | |||
536 | dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, | ||
537 | dev_priv->gtt.base.start / PAGE_SIZE, | ||
538 | dev_priv->gtt.base.total / PAGE_SIZE, | ||
539 | false); | ||
540 | } | ||
541 | |||
493 | void i915_gem_restore_gtt_mappings(struct drm_device *dev) | 542 | void i915_gem_restore_gtt_mappings(struct drm_device *dev) |
494 | { | 543 | { |
495 | struct drm_i915_private *dev_priv = dev->dev_private; | 544 | struct drm_i915_private *dev_priv = dev->dev_private; |
496 | struct drm_i915_gem_object *obj; | 545 | struct drm_i915_gem_object *obj; |
497 | 546 | ||
547 | i915_check_and_clear_faults(dev); | ||
548 | |||
498 | /* First fill our portion of the GTT with scratch pages */ | 549 | /* First fill our portion of the GTT with scratch pages */ |
499 | dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, | 550 | dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, |
500 | dev_priv->gtt.base.start / PAGE_SIZE, | 551 | dev_priv->gtt.base.start / PAGE_SIZE, |
501 | dev_priv->gtt.base.total / PAGE_SIZE); | 552 | dev_priv->gtt.base.total / PAGE_SIZE, |
553 | true); | ||
502 | 554 | ||
503 | list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { | 555 | list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { |
504 | i915_gem_clflush_object(obj, obj->pin_display); | 556 | i915_gem_clflush_object(obj, obj->pin_display); |
@@ -565,7 +617,8 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, | |||
565 | 617 | ||
566 | static void gen6_ggtt_clear_range(struct i915_address_space *vm, | 618 | static void gen6_ggtt_clear_range(struct i915_address_space *vm, |
567 | unsigned int first_entry, | 619 | unsigned int first_entry, |
568 | unsigned int num_entries) | 620 | unsigned int num_entries, |
621 | bool use_scratch) | ||
569 | { | 622 | { |
570 | struct drm_i915_private *dev_priv = vm->dev->dev_private; | 623 | struct drm_i915_private *dev_priv = vm->dev->dev_private; |
571 | gen6_gtt_pte_t scratch_pte, __iomem *gtt_base = | 624 | gen6_gtt_pte_t scratch_pte, __iomem *gtt_base = |
@@ -578,7 +631,8 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, | |||
578 | first_entry, num_entries, max_entries)) | 631 | first_entry, num_entries, max_entries)) |
579 | num_entries = max_entries; | 632 | num_entries = max_entries; |
580 | 633 | ||
581 | scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true); | 634 | scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, use_scratch); |
635 | |||
582 | for (i = 0; i < num_entries; i++) | 636 | for (i = 0; i < num_entries; i++) |
583 | iowrite32(scratch_pte, >t_base[i]); | 637 | iowrite32(scratch_pte, >t_base[i]); |
584 | readl(gtt_base); | 638 | readl(gtt_base); |
@@ -599,7 +653,8 @@ static void i915_ggtt_insert_entries(struct i915_address_space *vm, | |||
599 | 653 | ||
600 | static void i915_ggtt_clear_range(struct i915_address_space *vm, | 654 | static void i915_ggtt_clear_range(struct i915_address_space *vm, |
601 | unsigned int first_entry, | 655 | unsigned int first_entry, |
602 | unsigned int num_entries) | 656 | unsigned int num_entries, |
657 | bool unused) | ||
603 | { | 658 | { |
604 | intel_gtt_clear_range(first_entry, num_entries); | 659 | intel_gtt_clear_range(first_entry, num_entries); |
605 | } | 660 | } |
@@ -627,7 +682,8 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj) | |||
627 | 682 | ||
628 | dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, | 683 | dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, |
629 | entry, | 684 | entry, |
630 | obj->base.size >> PAGE_SHIFT); | 685 | obj->base.size >> PAGE_SHIFT, |
686 | true); | ||
631 | 687 | ||
632 | obj->has_global_gtt_mapping = 0; | 688 | obj->has_global_gtt_mapping = 0; |
633 | } | 689 | } |
@@ -714,11 +770,11 @@ void i915_gem_setup_global_gtt(struct drm_device *dev, | |||
714 | const unsigned long count = (hole_end - hole_start) / PAGE_SIZE; | 770 | const unsigned long count = (hole_end - hole_start) / PAGE_SIZE; |
715 | DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n", | 771 | DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n", |
716 | hole_start, hole_end); | 772 | hole_start, hole_end); |
717 | ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count); | 773 | ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count, true); |
718 | } | 774 | } |
719 | 775 | ||
720 | /* And finally clear the reserved guard page */ | 776 | /* And finally clear the reserved guard page */ |
721 | ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1); | 777 | ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1, true); |
722 | } | 778 | } |
723 | 779 | ||
724 | static bool | 780 | static bool |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index fd721ea8728e..ef9b35479f01 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -604,6 +604,10 @@ | |||
604 | #define ARB_MODE_SWIZZLE_IVB (1<<5) | 604 | #define ARB_MODE_SWIZZLE_IVB (1<<5) |
605 | #define RENDER_HWS_PGA_GEN7 (0x04080) | 605 | #define RENDER_HWS_PGA_GEN7 (0x04080) |
606 | #define RING_FAULT_REG(ring) (0x4094 + 0x100*(ring)->id) | 606 | #define RING_FAULT_REG(ring) (0x4094 + 0x100*(ring)->id) |
607 | #define RING_FAULT_GTTSEL_MASK (1<<11) | ||
608 | #define RING_FAULT_SRCID(x) ((x >> 3) & 0xff) | ||
609 | #define RING_FAULT_FAULT_TYPE(x) ((x >> 1) & 0x3) | ||
610 | #define RING_FAULT_VALID (1<<0) | ||
607 | #define DONE_REG 0x40b0 | 611 | #define DONE_REG 0x40b0 |
608 | #define BSD_HWS_PGA_GEN7 (0x04180) | 612 | #define BSD_HWS_PGA_GEN7 (0x04180) |
609 | #define BLT_HWS_PGA_GEN7 (0x04280) | 613 | #define BLT_HWS_PGA_GEN7 (0x04280) |