[Intel-gfx] [PATCH 04/11] drm/i915: ppgtt binding/unbinding support

Ben Widawsky ben at bwidawsk.net
Wed Nov 30 00:46:15 CET 2011


On Mon, Nov 28, 2011 at 09:35:31PM +0100, Daniel Vetter wrote:
> This adds support to bind/unbind objects and wires it up. Objects are
> only put into the ppgtt when necessary, i.e. at execbuf time.
> 
> Objects are still unconditionally put into the global gtt.
> 
> v2: Kill the quick hack and explicitly pass cache_level to ppgtt_bind
> like for the global gtt function. Noticed by Chris Wilson.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
> ---

> diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> index c918124..9c81cda 100644
> --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> @@ -513,6 +513,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
>  			    struct drm_file *file,
>  			    struct list_head *objects)
>  {
> +	drm_i915_private_t *dev_priv = ring->dev->dev_private;
>  	struct drm_i915_gem_object *obj;
>  	int ret, retry;
>  	bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
> @@ -621,6 +622,14 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
>  			}
>  
>  			i915_gem_object_unpin(obj);
> +
> +			/* ... and ensure ppgtt mapping exist if needed. */
> +			if (dev_priv->mm.aliasing_ppgtt && !obj->has_aliasing_ppgtt_mapping) {
> +				i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,
> +						       obj, obj->cache_level);
> +
> +				obj->has_aliasing_ppgtt_mapping = 1;
> +			}
>  		}
>  
>  		if (ret != -ENOSPC || retry > 1)
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> index bd9b520..061ae12 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> @@ -34,22 +34,31 @@ static void i915_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
>  				   unsigned first_entry,
>  				   unsigned num_entries)
>  {
> -	int i, j;
>  	uint32_t *pt_vaddr;
>  	uint32_t scratch_pte;
> +	unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES;
> +	unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
> +	unsigned last_pte, i;
>  
>  	scratch_pte = GEN6_PTE_ADDR_ENCODE(ppgtt->scratch_page_dma_addr);
>  	scratch_pte |= GEN6_PTE_VALID | GEN6_PTE_CACHE_LLC;
>  
> -	for (i = 0; i < ppgtt->num_pd_entries; i++) {
> -		pt_vaddr = kmap_atomic(ppgtt->pt_pages[i]);
> +	while (num_entries) {
> +		last_pte = first_pte + num_entries;
> +		if (last_pte > I915_PPGTT_PT_ENTRIES)
> +			last_pte = I915_PPGTT_PT_ENTRIES;
> +
> +		pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pd]);
>  
> -		for (j = 0; j < I915_PPGTT_PT_ENTRIES; j++)
> -			pt_vaddr[j] = scratch_pte;
> +		for (i = first_pte; i < last_pte; i++)
> +			pt_vaddr[i] = scratch_pte;
>  
>  		kunmap_atomic(pt_vaddr);
> -	}
>  
> +		num_entries -= last_pte - first_pte;
> +		first_pte = 0;
> +		act_pd++;
> +	}
>  }
>  
>  int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
> @@ -162,6 +171,131 @@ void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev)
>  	kfree(ppgtt);
>  }
>  
> +static void i915_ppgtt_insert_sg_entries(struct i915_hw_ppgtt *ppgtt,
> +					 struct scatterlist *sg_list,
> +					 unsigned sg_len,
> +					 unsigned first_entry,
> +					 uint32_t pte_flags)
> +{
> +	uint32_t *pt_vaddr, pte;
> +	unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES;
> +	unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
> +	unsigned i, j, m, segment_len;
> +	dma_addr_t page_addr;
> +	struct scatterlist *sg;
> +
> +	/* init sg walking */
> +	sg = sg_list;
> +	i = 0;
> +	segment_len = sg_dma_len(sg) >> PAGE_SHIFT;
> +	m = 0;
> +
> +	while (i < sg_len) {
> +		pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pd]);
> +
> +		for (j = first_pte; j < I915_PPGTT_PT_ENTRIES; j++) {
> +			page_addr = sg_dma_address(sg) + (m << PAGE_SHIFT);
> +			pte = GEN6_PTE_ADDR_ENCODE(page_addr);
> +			pt_vaddr[j] = pte | pte_flags;
> +
> +			/* grab the next page */
> +			m++;
> +			if (m == segment_len) {
> +				sg = sg_next(sg);
> +				i++;
> +				if (i == sg_len)
> +					break;
> +
> +				segment_len = sg_dma_len(sg) >> PAGE_SHIFT;
> +				m = 0;
> +			}
> +		}
> +
> +		kunmap_atomic(pt_vaddr);
> +
> +		first_pte = 0;
> +		act_pd++;
> +	}
> +}
> +
> +static void i915_ppgtt_insert_pages(struct i915_hw_ppgtt *ppgtt,
> +				    unsigned first_entry, unsigned num_entries,
> +				    struct page **pages, uint32_t pte_flags)
> +{
> +	uint32_t *pt_vaddr, pte;
> +	unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES;
> +	unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
> +	unsigned last_pte, i;
> +	dma_addr_t page_addr;
> +
> +	while (num_entries) {
> +		last_pte = first_pte + num_entries;
> +		last_pte = min_t(unsigned, last_pte, I915_PPGTT_PT_ENTRIES);
> +
> +		pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pd]);
> +
> +		for (i = first_pte; i < last_pte; i++) {
> +			page_addr = page_to_phys(*pages);
> +			pte = GEN6_PTE_ADDR_ENCODE(page_addr);
> +			pt_vaddr[i] = pte | pte_flags;
> +
> +			pages++;
> +		}
> +
> +		kunmap_atomic(pt_vaddr);
> +
> +		num_entries -= last_pte - first_pte;
> +		first_pte = 0;
> +		act_pd++;
> +	}
> +}

Same comment as 3/11 on these... don't we need a clflush?



More information about the Intel-gfx mailing list