Commit 10c028e9 authored by Dave Airlie's avatar Dave Airlie

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
parents 8ecffd79 6a0a7a9e
...@@ -150,6 +150,8 @@ struct vmw_ttm_tt { ...@@ -150,6 +150,8 @@ struct vmw_ttm_tt {
bool mapped; bool mapped;
}; };
const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt);
/** /**
* Helper functions to advance a struct vmw_piter iterator. * Helper functions to advance a struct vmw_piter iterator.
* *
......
...@@ -615,6 +615,7 @@ extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma); ...@@ -615,6 +615,7 @@ extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma);
* TTM buffer object driver - vmwgfx_buffer.c * 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_placement;
extern struct ttm_placement vmw_vram_ne_placement; extern struct ttm_placement vmw_vram_ne_placement;
extern struct ttm_placement vmw_vram_sys_placement; extern struct ttm_placement vmw_vram_sys_placement;
......
...@@ -75,6 +75,7 @@ void vmw_display_unit_cleanup(struct vmw_display_unit *du) ...@@ -75,6 +75,7 @@ void vmw_display_unit_cleanup(struct vmw_display_unit *du)
vmw_surface_unreference(&du->cursor_surface); vmw_surface_unreference(&du->cursor_surface);
if (du->cursor_dmabuf) if (du->cursor_dmabuf)
vmw_dmabuf_unreference(&du->cursor_dmabuf); vmw_dmabuf_unreference(&du->cursor_dmabuf);
drm_sysfs_connector_remove(&du->connector);
drm_crtc_cleanup(&du->crtc); drm_crtc_cleanup(&du->crtc);
drm_encoder_cleanup(&du->encoder); drm_encoder_cleanup(&du->encoder);
drm_connector_cleanup(&du->connector); drm_connector_cleanup(&du->connector);
......
...@@ -260,6 +260,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set) ...@@ -260,6 +260,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
connector->encoder = NULL; connector->encoder = NULL;
encoder->crtc = NULL; encoder->crtc = NULL;
crtc->fb = NULL; crtc->fb = NULL;
crtc->enabled = false;
vmw_ldu_del_active(dev_priv, ldu); vmw_ldu_del_active(dev_priv, ldu);
...@@ -285,6 +286,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set) ...@@ -285,6 +286,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
crtc->x = set->x; crtc->x = set->x;
crtc->y = set->y; crtc->y = set->y;
crtc->mode = *mode; crtc->mode = *mode;
crtc->enabled = true;
vmw_ldu_add_active(dev_priv, ldu, vfb); vmw_ldu_add_active(dev_priv, ldu, vfb);
...@@ -369,6 +371,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) ...@@ -369,6 +371,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
encoder->possible_crtcs = (1 << unit); encoder->possible_crtcs = (1 << unit);
encoder->possible_clones = 0; encoder->possible_clones = 0;
(void) drm_sysfs_connector_add(connector);
drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs); drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
drm_mode_crtc_set_gamma_size(crtc, 256); drm_mode_crtc_set_gamma_size(crtc, 256);
......
...@@ -352,6 +352,38 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv, ...@@ -352,6 +352,38 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv,
/** /**
* Buffer management. * 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) void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
{ {
struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(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) ...@@ -359,6 +391,13 @@ void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
kfree(vmw_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, int vmw_dmabuf_init(struct vmw_private *dev_priv,
struct vmw_dma_buffer *vmw_bo, struct vmw_dma_buffer *vmw_bo,
size_t size, struct ttm_placement *placement, size_t size, struct ttm_placement *placement,
...@@ -368,28 +407,23 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv, ...@@ -368,28 +407,23 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv,
struct ttm_bo_device *bdev = &dev_priv->bdev; struct ttm_bo_device *bdev = &dev_priv->bdev;
size_t acc_size; size_t acc_size;
int ret; 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)); memset(vmw_bo, 0, sizeof(*vmw_bo));
INIT_LIST_HEAD(&vmw_bo->res_list); INIT_LIST_HEAD(&vmw_bo->res_list);
ret = ttm_bo_init(bdev, &vmw_bo->base, size, 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, 0, interruptible,
NULL, acc_size, NULL, bo_free); NULL, acc_size, NULL, bo_free);
return ret; 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) static void vmw_user_dmabuf_release(struct ttm_base_object **p_base)
{ {
struct vmw_user_dma_buffer *vmw_user_bo; struct vmw_user_dma_buffer *vmw_user_bo;
...@@ -781,54 +815,55 @@ int vmw_user_stream_lookup(struct vmw_private *dev_priv, ...@@ -781,54 +815,55 @@ int vmw_user_stream_lookup(struct vmw_private *dev_priv,
} }
/**
* 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, int vmw_dumb_create(struct drm_file *file_priv,
struct drm_device *dev, struct drm_device *dev,
struct drm_mode_create_dumb *args) struct drm_mode_create_dumb *args)
{ {
struct vmw_private *dev_priv = vmw_priv(dev); struct vmw_private *dev_priv = vmw_priv(dev);
struct vmw_master *vmaster = vmw_master(file_priv->master); struct vmw_master *vmaster = vmw_master(file_priv->master);
struct vmw_user_dma_buffer *vmw_user_bo; struct vmw_dma_buffer *dma_buf;
struct ttm_buffer_object *tmp;
int ret; int ret;
args->pitch = args->width * ((args->bpp + 7) / 8); args->pitch = args->width * ((args->bpp + 7) / 8);
args->size = args->pitch * args->height; 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); ret = ttm_read_lock(&vmaster->lock, true);
if (ret != 0) { if (unlikely(ret != 0))
kfree(vmw_user_bo);
return ret; return ret;
}
ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, args->size, ret = vmw_user_dmabuf_alloc(dev_priv, vmw_fpriv(file_priv)->tfile,
&vmw_vram_sys_placement, true, args->size, false, &args->handle,
&vmw_user_dmabuf_destroy); &dma_buf);
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);
if (unlikely(ret != 0)) if (unlikely(ret != 0))
goto out_no_base_object; goto out_no_dmabuf;
args->handle = vmw_user_bo->prime.base.hash.key;
out_no_base_object: vmw_dmabuf_unreference(&dma_buf);
ttm_bo_unref(&tmp);
out_no_dmabuf: out_no_dmabuf:
ttm_read_unlock(&vmaster->lock); ttm_read_unlock(&vmaster->lock);
return ret; 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, int vmw_dumb_map_offset(struct drm_file *file_priv,
struct drm_device *dev, uint32_t handle, struct drm_device *dev, uint32_t handle,
uint64_t *offset) uint64_t *offset)
...@@ -846,6 +881,15 @@ int vmw_dumb_map_offset(struct drm_file *file_priv, ...@@ -846,6 +881,15 @@ int vmw_dumb_map_offset(struct drm_file *file_priv,
return 0; 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, int vmw_dumb_destroy(struct drm_file *file_priv,
struct drm_device *dev, struct drm_device *dev,
uint32_t handle) uint32_t handle)
......
...@@ -310,6 +310,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set) ...@@ -310,6 +310,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
crtc->fb = NULL; crtc->fb = NULL;
crtc->x = 0; crtc->x = 0;
crtc->y = 0; crtc->y = 0;
crtc->enabled = false;
vmw_sou_del_active(dev_priv, sou); vmw_sou_del_active(dev_priv, sou);
...@@ -370,6 +371,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set) ...@@ -370,6 +371,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
crtc->fb = NULL; crtc->fb = NULL;
crtc->x = 0; crtc->x = 0;
crtc->y = 0; crtc->y = 0;
crtc->enabled = false;
return ret; return ret;
} }
...@@ -382,6 +384,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set) ...@@ -382,6 +384,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
crtc->fb = fb; crtc->fb = fb;
crtc->x = set->x; crtc->x = set->x;
crtc->y = set->y; crtc->y = set->y;
crtc->enabled = true;
return 0; return 0;
} }
...@@ -464,6 +467,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) ...@@ -464,6 +467,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
encoder->possible_crtcs = (1 << unit); encoder->possible_crtcs = (1 << unit);
encoder->possible_clones = 0; encoder->possible_clones = 0;
(void) drm_sysfs_connector_add(connector);
drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs); drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);
drm_mode_crtc_set_gamma_size(crtc, 256); drm_mode_crtc_set_gamma_size(crtc, 256);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment