aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c5
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h5
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c76
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h4
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,
2066void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, 2067void 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
2070void i915_check_and_clear_faults(struct drm_device *dev);
2071void i915_gem_suspend_gtt_mappings(struct drm_device *dev);
2069void i915_gem_restore_gtt_mappings(struct drm_device *dev); 2072void i915_gem_restore_gtt_mappings(struct drm_device *dev);
2070int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj); 2073int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj);
2071void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj, 2074void 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 */
242static void gen6_ppgtt_clear_range(struct i915_address_space *vm, 242static 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
455extern int intel_iommu_gfx_mapped; 457extern 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
495void 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
524void 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
493void i915_gem_restore_gtt_mappings(struct drm_device *dev) 542void 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
566static void gen6_ggtt_clear_range(struct i915_address_space *vm, 618static 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, &gtt_base[i]); 637 iowrite32(scratch_pte, &gtt_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
600static void i915_ggtt_clear_range(struct i915_address_space *vm, 654static 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
724static bool 780static 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)