diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem_gtt.c')
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 229 | 
1 files changed, 52 insertions, 177 deletions
| diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index bd17dd1f5da5..d646d37eec2f 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -33,11 +33,11 @@  #include <asm/set_memory.h> -#include <drm/drmP.h>  #include <drm/i915_drm.h>  #include "i915_drv.h"  #include "i915_vgpu.h" +#include "i915_reset.h"  #include "i915_trace.h"  #include "intel_drv.h"  #include "intel_frontbuffer.h" @@ -474,8 +474,7 @@ static void vm_free_page(struct i915_address_space *vm, struct page *page)  	spin_unlock(&vm->free_pages.lock);  } -static void i915_address_space_init(struct i915_address_space *vm, -				    struct drm_i915_private *dev_priv) +static void i915_address_space_init(struct i915_address_space *vm, int subclass)  {  	/*  	 * The vm->mutex must be reclaim safe (for use in the shrinker). @@ -483,7 +482,8 @@ static void i915_address_space_init(struct i915_address_space *vm,  	 * attempt holding the lock is immediately reported by lockdep.  	 */  	mutex_init(&vm->mutex); -	i915_gem_shrinker_taints_mutex(&vm->mutex); +	lockdep_set_subclass(&vm->mutex, subclass); +	i915_gem_shrinker_taints_mutex(vm->i915, &vm->mutex);  	GEM_BUG_ON(!vm->total);  	drm_mm_init(&vm->mm, 0, vm->total); @@ -491,9 +491,8 @@ static void i915_address_space_init(struct i915_address_space *vm,  	stash_init(&vm->free_pages); -	INIT_LIST_HEAD(&vm->active_list); -	INIT_LIST_HEAD(&vm->inactive_list);  	INIT_LIST_HEAD(&vm->unbound_list); +	INIT_LIST_HEAD(&vm->bound_list);  }  static void i915_address_space_fini(struct i915_address_space *vm) @@ -1423,8 +1422,6 @@ static int gen8_ppgtt_alloc_pdp(struct i915_address_space *vm,  			gen8_initialize_pd(vm, pd);  			gen8_ppgtt_set_pdpe(vm, pdp, pd, pdpe);  			GEM_BUG_ON(pdp->used_pdpes > i915_pdpes_per_pdp(vm)); - -			mark_tlbs_dirty(i915_vm_to_ppgtt(vm));  		}  		ret = gen8_ppgtt_alloc_pd(vm, pd, start, length); @@ -1490,84 +1487,6 @@ unwind:  	return -ENOMEM;  } -static void gen8_dump_pdp(struct i915_hw_ppgtt *ppgtt, -			  struct i915_page_directory_pointer *pdp, -			  u64 start, u64 length, -			  gen8_pte_t scratch_pte, -			  struct seq_file *m) -{ -	struct i915_address_space *vm = &ppgtt->vm; -	struct i915_page_directory *pd; -	u32 pdpe; - -	gen8_for_each_pdpe(pd, pdp, start, length, pdpe) { -		struct i915_page_table *pt; -		u64 pd_len = length; -		u64 pd_start = start; -		u32 pde; - -		if (pdp->page_directory[pdpe] == ppgtt->vm.scratch_pd) -			continue; - -		seq_printf(m, "\tPDPE #%d\n", pdpe); -		gen8_for_each_pde(pt, pd, pd_start, pd_len, pde) { -			u32 pte; -			gen8_pte_t *pt_vaddr; - -			if (pd->page_table[pde] == ppgtt->vm.scratch_pt) -				continue; - -			pt_vaddr = kmap_atomic_px(pt); -			for (pte = 0; pte < GEN8_PTES; pte += 4) { -				u64 va = (pdpe << GEN8_PDPE_SHIFT | -					  pde << GEN8_PDE_SHIFT | -					  pte << GEN8_PTE_SHIFT); -				int i; -				bool found = false; - -				for (i = 0; i < 4; i++) -					if (pt_vaddr[pte + i] != scratch_pte) -						found = true; -				if (!found) -					continue; - -				seq_printf(m, "\t\t0x%llx [%03d,%03d,%04d]: =", va, pdpe, pde, pte); -				for (i = 0; i < 4; i++) { -					if (pt_vaddr[pte + i] != scratch_pte) -						seq_printf(m, " %llx", pt_vaddr[pte + i]); -					else -						seq_puts(m, "  SCRATCH "); -				} -				seq_puts(m, "\n"); -			} -			kunmap_atomic(pt_vaddr); -		} -	} -} - -static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) -{ -	struct i915_address_space *vm = &ppgtt->vm; -	const gen8_pte_t scratch_pte = vm->scratch_pte; -	u64 start = 0, length = ppgtt->vm.total; - -	if (use_4lvl(vm)) { -		u64 pml4e; -		struct i915_pml4 *pml4 = &ppgtt->pml4; -		struct i915_page_directory_pointer *pdp; - -		gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) { -			if (pml4->pdps[pml4e] == ppgtt->vm.scratch_pdp) -				continue; - -			seq_printf(m, "    PML4E #%llu\n", pml4e); -			gen8_dump_pdp(ppgtt, pdp, start, length, scratch_pte, m); -		} -	} else { -		gen8_dump_pdp(ppgtt, &ppgtt->pdp, start, length, scratch_pte, m); -	} -} -  static int gen8_preallocate_top_level_pdp(struct i915_hw_ppgtt *ppgtt)  {  	struct i915_address_space *vm = &ppgtt->vm; @@ -1628,7 +1547,7 @@ static struct i915_hw_ppgtt *gen8_ppgtt_create(struct drm_i915_private *i915)  	/* From bdw, there is support for read-only pages in the PPGTT. */  	ppgtt->vm.has_read_only = true; -	i915_address_space_init(&ppgtt->vm, i915); +	i915_address_space_init(&ppgtt->vm, VM_CLASS_PPGTT);  	/* There are only few exceptions for gen >=6. chv and bxt.  	 * And we are not sure about the latter so play safe for now. @@ -1672,7 +1591,6 @@ static struct i915_hw_ppgtt *gen8_ppgtt_create(struct drm_i915_private *i915)  		gen8_ppgtt_notify_vgt(ppgtt, true);  	ppgtt->vm.cleanup = gen8_ppgtt_cleanup; -	ppgtt->debug_dump = gen8_dump_ppgtt;  	ppgtt->vm.vma_ops.bind_vma    = ppgtt_bind_vma;  	ppgtt->vm.vma_ops.unbind_vma  = ppgtt_unbind_vma; @@ -1688,60 +1606,6 @@ err_free:  	return ERR_PTR(err);  } -static void gen6_dump_ppgtt(struct i915_hw_ppgtt *base, struct seq_file *m) -{ -	struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(base); -	const gen6_pte_t scratch_pte = base->vm.scratch_pte; -	struct i915_page_table *pt; -	u32 pte, pde; - -	gen6_for_all_pdes(pt, &base->pd, pde) { -		gen6_pte_t *vaddr; - -		if (pt == base->vm.scratch_pt) -			continue; - -		if (i915_vma_is_bound(ppgtt->vma, I915_VMA_GLOBAL_BIND)) { -			u32 expected = -				GEN6_PDE_ADDR_ENCODE(px_dma(pt)) | -				GEN6_PDE_VALID; -			u32 pd_entry = readl(ppgtt->pd_addr + pde); - -			if (pd_entry != expected) -				seq_printf(m, -					   "\tPDE #%d mismatch: Actual PDE: %x Expected PDE: %x\n", -					   pde, -					   pd_entry, -					   expected); - -			seq_printf(m, "\tPDE: %x\n", pd_entry); -		} - -		vaddr = kmap_atomic_px(base->pd.page_table[pde]); -		for (pte = 0; pte < GEN6_PTES; pte += 4) { -			int i; - -			for (i = 0; i < 4; i++) -				if (vaddr[pte + i] != scratch_pte) -					break; -			if (i == 4) -				continue; - -			seq_printf(m, "\t\t(%03d, %04d) %08llx: ", -				   pde, pte, -				   (pde * GEN6_PTES + pte) * I915_GTT_PAGE_SIZE); -			for (i = 0; i < 4; i++) { -				if (vaddr[pte + i] != scratch_pte) -					seq_printf(m, " %08x", vaddr[pte + i]); -				else -					seq_puts(m, "  SCRATCH"); -			} -			seq_puts(m, "\n"); -		} -		kunmap_atomic(vaddr); -	} -} -  /* Write pde (index) from the page directory @pd to the page table @pt */  static inline void gen6_write_pde(const struct gen6_hw_ppgtt *ppgtt,  				  const unsigned int pde, @@ -2053,21 +1917,23 @@ static struct i915_vma *pd_vma_create(struct gen6_hw_ppgtt *ppgtt, int size)  	if (!vma)  		return ERR_PTR(-ENOMEM); -	init_request_active(&vma->last_fence, NULL); +	i915_active_init(i915, &vma->active, NULL); +	INIT_ACTIVE_REQUEST(&vma->last_fence);  	vma->vm = &ggtt->vm;  	vma->ops = &pd_vma_ops;  	vma->private = ppgtt; -	vma->active = RB_ROOT; -  	vma->size = size;  	vma->fence_size = size;  	vma->flags = I915_VMA_GGTT;  	vma->ggtt_view.type = I915_GGTT_VIEW_ROTATED; /* prevent fencing */  	INIT_LIST_HEAD(&vma->obj_link); + +	mutex_lock(&vma->vm->mutex);  	list_add(&vma->vm_link, &vma->vm->unbound_list); +	mutex_unlock(&vma->vm->mutex);  	return vma;  } @@ -2132,13 +1998,12 @@ static struct i915_hw_ppgtt *gen6_ppgtt_create(struct drm_i915_private *i915)  	ppgtt->base.vm.total = I915_PDES * GEN6_PTES * I915_GTT_PAGE_SIZE; -	i915_address_space_init(&ppgtt->base.vm, i915); +	i915_address_space_init(&ppgtt->base.vm, VM_CLASS_PPGTT);  	ppgtt->base.vm.allocate_va_range = gen6_alloc_va_range;  	ppgtt->base.vm.clear_range = gen6_ppgtt_clear_range;  	ppgtt->base.vm.insert_entries = gen6_ppgtt_insert_entries;  	ppgtt->base.vm.cleanup = gen6_ppgtt_cleanup; -	ppgtt->base.debug_dump = gen6_dump_ppgtt;  	ppgtt->base.vm.vma_ops.bind_vma    = ppgtt_bind_vma;  	ppgtt->base.vm.vma_ops.unbind_vma  = ppgtt_unbind_vma; @@ -2204,9 +2069,9 @@ int i915_ppgtt_init_hw(struct drm_i915_private *dev_priv)  {  	gtt_write_workarounds(dev_priv); -	if (IS_GEN6(dev_priv)) +	if (IS_GEN(dev_priv, 6))  		gen6_ppgtt_enable(dev_priv); -	else if (IS_GEN7(dev_priv)) +	else if (IS_GEN(dev_priv, 7))  		gen7_ppgtt_enable(dev_priv);  	return 0; @@ -2247,8 +2112,7 @@ void i915_ppgtt_close(struct i915_address_space *vm)  static void ppgtt_destroy_vma(struct i915_address_space *vm)  {  	struct list_head *phases[] = { -		&vm->active_list, -		&vm->inactive_list, +		&vm->bound_list,  		&vm->unbound_list,  		NULL,  	}, **phase; @@ -2271,8 +2135,7 @@ void i915_ppgtt_release(struct kref *kref)  	ppgtt_destroy_vma(&ppgtt->vm); -	GEM_BUG_ON(!list_empty(&ppgtt->vm.active_list)); -	GEM_BUG_ON(!list_empty(&ppgtt->vm.inactive_list)); +	GEM_BUG_ON(!list_empty(&ppgtt->vm.bound_list));  	GEM_BUG_ON(!list_empty(&ppgtt->vm.unbound_list));  	ppgtt->vm.cleanup(&ppgtt->vm); @@ -2288,7 +2151,7 @@ static bool needs_idle_maps(struct drm_i915_private *dev_priv)  	/* Query intel_iommu to see if we need the workaround. Presumably that  	 * was loaded first.  	 */ -	return IS_GEN5(dev_priv) && IS_MOBILE(dev_priv) && intel_vtd_active(); +	return IS_GEN(dev_priv, 5) && IS_MOBILE(dev_priv) && intel_vtd_active();  }  static void gen6_check_faults(struct drm_i915_private *dev_priv) @@ -2381,7 +2244,8 @@ int i915_gem_gtt_prepare_pages(struct drm_i915_gem_object *obj,  				     DMA_ATTR_NO_WARN))  			return 0; -		/* If the DMA remap fails, one cause can be that we have +		/* +		 * If the DMA remap fails, one cause can be that we have  		 * too many objects pinned in a small remapping table,  		 * such as swiotlb. Incrementally purge all other objects and  		 * try again - if there are no more pages to remove from @@ -2391,8 +2255,7 @@ int i915_gem_gtt_prepare_pages(struct drm_i915_gem_object *obj,  	} while (i915_gem_shrink(to_i915(obj->base.dev),  				 obj->base.size >> PAGE_SHIFT, NULL,  				 I915_SHRINK_BOUND | -				 I915_SHRINK_UNBOUND | -				 I915_SHRINK_ACTIVE)); +				 I915_SHRINK_UNBOUND));  	return -ENOSPC;  } @@ -2664,6 +2527,7 @@ static int ggtt_bind_vma(struct i915_vma *vma,  {  	struct drm_i915_private *i915 = vma->vm->i915;  	struct drm_i915_gem_object *obj = vma->obj; +	intel_wakeref_t wakeref;  	u32 pte_flags;  	/* Applicable to VLV (gen8+ do not support RO in the GGTT) */ @@ -2671,9 +2535,8 @@ static int ggtt_bind_vma(struct i915_vma *vma,  	if (i915_gem_object_is_readonly(obj))  		pte_flags |= PTE_READ_ONLY; -	intel_runtime_pm_get(i915); -	vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags); -	intel_runtime_pm_put(i915); +	with_intel_runtime_pm(i915, wakeref) +		vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);  	vma->page_sizes.gtt = I915_GTT_PAGE_SIZE; @@ -2690,10 +2553,10 @@ static int ggtt_bind_vma(struct i915_vma *vma,  static void ggtt_unbind_vma(struct i915_vma *vma)  {  	struct drm_i915_private *i915 = vma->vm->i915; +	intel_wakeref_t wakeref; -	intel_runtime_pm_get(i915); -	vma->vm->clear_range(vma->vm, vma->node.start, vma->size); -	intel_runtime_pm_put(i915); +	with_intel_runtime_pm(i915, wakeref) +		vma->vm->clear_range(vma->vm, vma->node.start, vma->size);  }  static int aliasing_gtt_bind_vma(struct i915_vma *vma, @@ -2725,9 +2588,12 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,  	}  	if (flags & I915_VMA_GLOBAL_BIND) { -		intel_runtime_pm_get(i915); -		vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags); -		intel_runtime_pm_put(i915); +		intel_wakeref_t wakeref; + +		with_intel_runtime_pm(i915, wakeref) { +			vma->vm->insert_entries(vma->vm, vma, +						cache_level, pte_flags); +		}  	}  	return 0; @@ -2738,9 +2604,11 @@ static void aliasing_gtt_unbind_vma(struct i915_vma *vma)  	struct drm_i915_private *i915 = vma->vm->i915;  	if (vma->flags & I915_VMA_GLOBAL_BIND) { -		intel_runtime_pm_get(i915); -		vma->vm->clear_range(vma->vm, vma->node.start, vma->size); -		intel_runtime_pm_put(i915); +		struct i915_address_space *vm = vma->vm; +		intel_wakeref_t wakeref; + +		with_intel_runtime_pm(i915, wakeref) +			vm->clear_range(vm, vma->node.start, vma->size);  	}  	if (vma->flags & I915_VMA_LOCAL_BIND) { @@ -2932,8 +2800,7 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv)  	mutex_lock(&dev_priv->drm.struct_mutex);  	i915_gem_fini_aliasing_ppgtt(dev_priv); -	GEM_BUG_ON(!list_empty(&ggtt->vm.active_list)); -	list_for_each_entry_safe(vma, vn, &ggtt->vm.inactive_list, vm_link) +	list_for_each_entry_safe(vma, vn, &ggtt->vm.bound_list, vm_link)  		WARN_ON(i915_vma_unbind(vma));  	if (drm_mm_node_allocated(&ggtt->error_capture)) @@ -3364,7 +3231,8 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)  	ggtt->vm.insert_entries = gen8_ggtt_insert_entries;  	/* Serialize GTT updates with aperture access on BXT if VT-d is on. */ -	if (intel_ggtt_update_needs_vtd_wa(dev_priv)) { +	if (intel_ggtt_update_needs_vtd_wa(dev_priv) || +	    IS_CHERRYVIEW(dev_priv) /* fails with concurrent use/update */) {  		ggtt->vm.insert_entries = bxt_vtd_ggtt_insert_entries__BKL;  		ggtt->vm.insert_page    = bxt_vtd_ggtt_insert_page__BKL;  		if (ggtt->vm.clear_range != nop_clear_range) @@ -3565,7 +3433,7 @@ int i915_ggtt_init_hw(struct drm_i915_private *dev_priv)  	 * and beyond the end of the GTT if we do not provide a guard.  	 */  	mutex_lock(&dev_priv->drm.struct_mutex); -	i915_address_space_init(&ggtt->vm, dev_priv); +	i915_address_space_init(&ggtt->vm, VM_CLASS_GGTT);  	ggtt->vm.is_ggtt = true; @@ -3638,32 +3506,39 @@ void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv)  	i915_check_and_clear_faults(dev_priv); +	mutex_lock(&ggtt->vm.mutex); +  	/* First fill our portion of the GTT with scratch pages */  	ggtt->vm.clear_range(&ggtt->vm, 0, ggtt->vm.total); -  	ggtt->vm.closed = true; /* skip rewriting PTE on VMA unbind */  	/* clflush objects bound into the GGTT and rebind them. */ -	GEM_BUG_ON(!list_empty(&ggtt->vm.active_list)); -	list_for_each_entry_safe(vma, vn, &ggtt->vm.inactive_list, vm_link) { +	list_for_each_entry_safe(vma, vn, &ggtt->vm.bound_list, vm_link) {  		struct drm_i915_gem_object *obj = vma->obj;  		if (!(vma->flags & I915_VMA_GLOBAL_BIND))  			continue; +		mutex_unlock(&ggtt->vm.mutex); +  		if (!i915_vma_unbind(vma)) -			continue; +			goto lock;  		WARN_ON(i915_vma_bind(vma,  				      obj ? obj->cache_level : 0,  				      PIN_UPDATE));  		if (obj)  			WARN_ON(i915_gem_object_set_to_gtt_domain(obj, false)); + +lock: +		mutex_lock(&ggtt->vm.mutex);  	}  	ggtt->vm.closed = false;  	i915_ggtt_invalidate(dev_priv); +	mutex_unlock(&ggtt->vm.mutex); +  	if (INTEL_GEN(dev_priv) >= 8) {  		struct intel_ppat *ppat = &dev_priv->ppat; | 
