diff options
| author | Dave Airlie <[email protected]> | 2013-12-05 09:18:25 +1000 | 
|---|---|---|
| committer | Dave Airlie <[email protected]> | 2013-12-05 09:18:25 +1000 | 
| commit | 10c028e94e6e47dca88b33dcc7f9f16651e2cc90 (patch) | |
| tree | 40cb756cd7d486a626aa35444a784ce2039b78cb /drivers/gpu/drm/vmwgfx | |
| parent | 8ecffd7914484b728799dd31968f1339fae91593 (diff) | |
| parent | 6a0a7a9ead2aa18c13dd8f76c5849daf7be1f45a (diff) | |
Merge branch 'vmwgfx-fixes-3.13' of git://people.freedesktop.org/~thomash/linux into drm-fixes
A couple of fixes. The biggest thing is the DMA buffer accounting that was
incorrect.
* 'vmwgfx-fixes-3.13' of git://people.freedesktop.org/~thomash/linux:
  drm/vmwgfx: Add our connectors to sysfs
  drm/vmwgfx: Fix dma buffer memory size accounting
  drm/vmwgfx: Fix up and comment the dumb buffer implementation
  drm/vmwgfx: Correctly set the enabled state on crtcs
Diffstat (limited to 'drivers/gpu/drm/vmwgfx')
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 118 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 5 | 
6 files changed, 94 insertions, 37 deletions
| diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c index 7776e6f0aef6..0489c6152482 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c @@ -150,6 +150,8 @@ struct vmw_ttm_tt {  	bool mapped;  }; +const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt); +  /**   * Helper functions to advance a struct vmw_piter iterator.   * diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index db85985c7086..20890ad8408b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -615,6 +615,7 @@ extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma);   * TTM buffer object driver - vmwgfx_buffer.c   */ +extern const size_t vmw_tt_size;  extern struct ttm_placement vmw_vram_placement;  extern struct ttm_placement vmw_vram_ne_placement;  extern struct ttm_placement vmw_vram_sys_placement; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index ecb3d867b426..03f1c2038631 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -75,6 +75,7 @@ void vmw_display_unit_cleanup(struct vmw_display_unit *du)  		vmw_surface_unreference(&du->cursor_surface);  	if (du->cursor_dmabuf)  		vmw_dmabuf_unreference(&du->cursor_dmabuf); +	drm_sysfs_connector_remove(&du->connector);  	drm_crtc_cleanup(&du->crtc);  	drm_encoder_cleanup(&du->encoder);  	drm_connector_cleanup(&du->connector); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 79f7e8e60529..a055a26819c2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -260,6 +260,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)  		connector->encoder = NULL;  		encoder->crtc = NULL;  		crtc->fb = NULL; +		crtc->enabled = false;  		vmw_ldu_del_active(dev_priv, ldu); @@ -285,6 +286,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)  	crtc->x = set->x;  	crtc->y = set->y;  	crtc->mode = *mode; +	crtc->enabled = true;  	vmw_ldu_add_active(dev_priv, ldu, vfb); @@ -369,6 +371,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)  	encoder->possible_crtcs = (1 << unit);  	encoder->possible_clones = 0; +	(void) drm_sysfs_connector_add(connector); +  	drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);  	drm_mode_crtc_set_gamma_size(crtc, 256); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index efe2b74c5eb1..9b5ea2ac7ddf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -352,6 +352,38 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv,  /**   * Buffer management.   */ + +/** + * vmw_dmabuf_acc_size - Calculate the pinned memory usage of buffers + * + * @dev_priv: Pointer to a struct vmw_private identifying the device. + * @size: The requested buffer size. + * @user: Whether this is an ordinary dma buffer or a user dma buffer. + */ +static size_t vmw_dmabuf_acc_size(struct vmw_private *dev_priv, size_t size, +				  bool user) +{ +	static size_t struct_size, user_struct_size; +	size_t num_pages = PAGE_ALIGN(size) >> PAGE_SHIFT; +	size_t page_array_size = ttm_round_pot(num_pages * sizeof(void *)); + +	if (unlikely(struct_size == 0)) { +		size_t backend_size = ttm_round_pot(vmw_tt_size); + +		struct_size = backend_size + +			ttm_round_pot(sizeof(struct vmw_dma_buffer)); +		user_struct_size = backend_size + +			ttm_round_pot(sizeof(struct vmw_user_dma_buffer)); +	} + +	if (dev_priv->map_mode == vmw_dma_alloc_coherent) +		page_array_size += +			ttm_round_pot(num_pages * sizeof(dma_addr_t)); + +	return ((user) ? user_struct_size : struct_size) + +		page_array_size; +} +  void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)  {  	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); @@ -359,6 +391,13 @@ void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)  	kfree(vmw_bo);  } +static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo) +{ +	struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo); + +	ttm_prime_object_kfree(vmw_user_bo, prime); +} +  int vmw_dmabuf_init(struct vmw_private *dev_priv,  		    struct vmw_dma_buffer *vmw_bo,  		    size_t size, struct ttm_placement *placement, @@ -368,28 +407,23 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv,  	struct ttm_bo_device *bdev = &dev_priv->bdev;  	size_t acc_size;  	int ret; +	bool user = (bo_free == &vmw_user_dmabuf_destroy); -	BUG_ON(!bo_free); +	BUG_ON(!bo_free && (!user && (bo_free != vmw_dmabuf_bo_free))); -	acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct vmw_dma_buffer)); +	acc_size = vmw_dmabuf_acc_size(dev_priv, size, user);  	memset(vmw_bo, 0, sizeof(*vmw_bo));  	INIT_LIST_HEAD(&vmw_bo->res_list);  	ret = ttm_bo_init(bdev, &vmw_bo->base, size, -			  ttm_bo_type_device, placement, +			  (user) ? ttm_bo_type_device : +			  ttm_bo_type_kernel, placement,  			  0, interruptible,  			  NULL, acc_size, NULL, bo_free);  	return ret;  } -static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo) -{ -	struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo); - -	ttm_prime_object_kfree(vmw_user_bo, prime); -} -  static void vmw_user_dmabuf_release(struct ttm_base_object **p_base)  {  	struct vmw_user_dma_buffer *vmw_user_bo; @@ -781,54 +815,55 @@ err_ref:  } +/** + * vmw_dumb_create - Create a dumb kms buffer + * + * @file_priv: Pointer to a struct drm_file identifying the caller. + * @dev: Pointer to the drm device. + * @args: Pointer to a struct drm_mode_create_dumb structure + * + * This is a driver callback for the core drm create_dumb functionality. + * Note that this is very similar to the vmw_dmabuf_alloc ioctl, except + * that the arguments have a different format. + */  int vmw_dumb_create(struct drm_file *file_priv,  		    struct drm_device *dev,  		    struct drm_mode_create_dumb *args)  {  	struct vmw_private *dev_priv = vmw_priv(dev);  	struct vmw_master *vmaster = vmw_master(file_priv->master); -	struct vmw_user_dma_buffer *vmw_user_bo; -	struct ttm_buffer_object *tmp; +	struct vmw_dma_buffer *dma_buf;  	int ret;  	args->pitch = args->width * ((args->bpp + 7) / 8);  	args->size = args->pitch * args->height; -	vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL); -	if (vmw_user_bo == NULL) -		return -ENOMEM; -  	ret = ttm_read_lock(&vmaster->lock, true); -	if (ret != 0) { -		kfree(vmw_user_bo); +	if (unlikely(ret != 0))  		return ret; -	} -	ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, args->size, -			      &vmw_vram_sys_placement, true, -			      &vmw_user_dmabuf_destroy); -	if (ret != 0) -		goto out_no_dmabuf; - -	tmp = ttm_bo_reference(&vmw_user_bo->dma.base); -	ret = ttm_prime_object_init(vmw_fpriv(file_priv)->tfile, -				    args->size, -				    &vmw_user_bo->prime, -				    false, -				    ttm_buffer_type, -				    &vmw_user_dmabuf_release, NULL); +	ret = vmw_user_dmabuf_alloc(dev_priv, vmw_fpriv(file_priv)->tfile, +				    args->size, false, &args->handle, +				    &dma_buf);  	if (unlikely(ret != 0)) -		goto out_no_base_object; - -	args->handle = vmw_user_bo->prime.base.hash.key; +		goto out_no_dmabuf; -out_no_base_object: -	ttm_bo_unref(&tmp); +	vmw_dmabuf_unreference(&dma_buf);  out_no_dmabuf:  	ttm_read_unlock(&vmaster->lock);  	return ret;  } +/** + * vmw_dumb_map_offset - Return the address space offset of a dumb buffer + * + * @file_priv: Pointer to a struct drm_file identifying the caller. + * @dev: Pointer to the drm device. + * @handle: Handle identifying the dumb buffer. + * @offset: The address space offset returned. + * + * This is a driver callback for the core drm dumb_map_offset functionality. + */  int vmw_dumb_map_offset(struct drm_file *file_priv,  			struct drm_device *dev, uint32_t handle,  			uint64_t *offset) @@ -846,6 +881,15 @@ int vmw_dumb_map_offset(struct drm_file *file_priv,  	return 0;  } +/** + * vmw_dumb_destroy - Destroy a dumb boffer + * + * @file_priv: Pointer to a struct drm_file identifying the caller. + * @dev: Pointer to the drm device. + * @handle: Handle identifying the dumb buffer. + * + * This is a driver callback for the core drm dumb_destroy functionality. + */  int vmw_dumb_destroy(struct drm_file *file_priv,  		     struct drm_device *dev,  		     uint32_t handle) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 26387c3d5a21..22406c8651ea 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -310,6 +310,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)  		crtc->fb = NULL;  		crtc->x = 0;  		crtc->y = 0; +		crtc->enabled = false;  		vmw_sou_del_active(dev_priv, sou); @@ -370,6 +371,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)  		crtc->fb = NULL;  		crtc->x = 0;  		crtc->y = 0; +		crtc->enabled = false;  		return ret;  	} @@ -382,6 +384,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)  	crtc->fb = fb;  	crtc->x = set->x;  	crtc->y = set->y; +	crtc->enabled = true;  	return 0;  } @@ -464,6 +467,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)  	encoder->possible_crtcs = (1 << unit);  	encoder->possible_clones = 0; +	(void) drm_sysfs_connector_add(connector); +  	drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);  	drm_mode_crtc_set_gamma_size(crtc, 256); |