diff options
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c')
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 44 | 
1 files changed, 30 insertions, 14 deletions
| diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index 4d23d0a70bcb..621d98b376bb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -188,13 +188,18 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)  	switch (dev_priv->map_mode) {  	case vmw_dma_map_bind:  	case vmw_dma_map_populate: -		vsgt->sgt = &vmw_tt->sgt; -		ret = sg_alloc_table_from_pages_segment( -			&vmw_tt->sgt, vsgt->pages, vsgt->num_pages, 0, -			(unsigned long)vsgt->num_pages << PAGE_SHIFT, -			dma_get_max_seg_size(dev_priv->drm.dev), GFP_KERNEL); -		if (ret) -			goto out_sg_alloc_fail; +		if (vmw_tt->dma_ttm.page_flags  & TTM_TT_FLAG_EXTERNAL) { +			vsgt->sgt = vmw_tt->dma_ttm.sg; +		} else { +			vsgt->sgt = &vmw_tt->sgt; +			ret = sg_alloc_table_from_pages_segment(&vmw_tt->sgt, +				vsgt->pages, vsgt->num_pages, 0, +				(unsigned long)vsgt->num_pages << PAGE_SHIFT, +				dma_get_max_seg_size(dev_priv->drm.dev), +				GFP_KERNEL); +			if (ret) +				goto out_sg_alloc_fail; +		}  		ret = vmw_ttm_map_for_dma(vmw_tt);  		if (unlikely(ret != 0)) @@ -209,8 +214,9 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)  	return 0;  out_map_fail: -	sg_free_table(vmw_tt->vsgt.sgt); -	vmw_tt->vsgt.sgt = NULL; +	drm_warn(&dev_priv->drm, "VSG table map failed!"); +	sg_free_table(vsgt->sgt); +	vsgt->sgt = NULL;  out_sg_alloc_fail:  	return ret;  } @@ -356,15 +362,17 @@ static void vmw_ttm_destroy(struct ttm_device *bdev, struct ttm_tt *ttm)  static int vmw_ttm_populate(struct ttm_device *bdev,  			    struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)  { -	int ret; +	bool external = (ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0; -	/* TODO: maybe completely drop this ? */  	if (ttm_tt_is_populated(ttm))  		return 0; -	ret = ttm_pool_alloc(&bdev->pool, ttm, ctx); +	if (external && ttm->sg) +		return  drm_prime_sg_to_dma_addr_array(ttm->sg, +						       ttm->dma_address, +						       ttm->num_pages); -	return ret; +	return ttm_pool_alloc(&bdev->pool, ttm, ctx);  }  static void vmw_ttm_unpopulate(struct ttm_device *bdev, @@ -372,6 +380,10 @@ static void vmw_ttm_unpopulate(struct ttm_device *bdev,  {  	struct vmw_ttm_tt *vmw_tt = container_of(ttm, struct vmw_ttm_tt,  						 dma_ttm); +	bool external = (ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0; + +	if (external) +		return;  	vmw_ttm_unbind(bdev, ttm); @@ -390,6 +402,7 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo,  {  	struct vmw_ttm_tt *vmw_be;  	int ret; +	bool external = bo->type == ttm_bo_type_sg;  	vmw_be = kzalloc(sizeof(*vmw_be), GFP_KERNEL);  	if (!vmw_be) @@ -398,7 +411,10 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo,  	vmw_be->dev_priv = vmw_priv_from_ttm(bo->bdev);  	vmw_be->mob = NULL; -	if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent) +	if (external) +		page_flags |= TTM_TT_FLAG_EXTERNAL | TTM_TT_FLAG_EXTERNAL_MAPPABLE; + +	if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent || external)  		ret = ttm_sg_tt_init(&vmw_be->dma_ttm, bo, page_flags,  				     ttm_cached);  	else | 
