Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 269572
b: refs/heads/master
c: be38ab6
h: refs/heads/master
v: v3
  • Loading branch information
Thomas Hellstrom authored and Dave Airlie committed Sep 1, 2011
1 parent fa16f6b commit 4cf5ef0
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 49 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0bef23f9180b43e805ce4dabb90b24a0b558721c
refs/heads/master: be38ab6ea7b0de0542a0ff78690d63bb22f66a4d
2 changes: 2 additions & 0 deletions trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,8 @@ static int vmw_driver_unload(struct drm_device *dev)

unregister_pm_notifier(&dev_priv->pm_nb);

if (dev_priv->ctx.cmd_bounce)
vfree(dev_priv->ctx.cmd_bounce);
if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
drm_irq_uninstall(dev_priv->dev);
if (dev_priv->enable_fb) {
Expand Down
14 changes: 10 additions & 4 deletions trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@
#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
#define VMWGFX_MAX_RELOCATIONS 2048
#define VMWGFX_MAX_GMRS 2048
#define VMWGFX_MAX_VALIDATIONS 2048
#define VMWGFX_MAX_DISPLAYS 16
#define VMWGFX_CMD_BOUNCE_INIT_SIZE 32768

#define VMW_PL_GMR TTM_PL_PRIV0
#define VMW_PL_FLAG_GMR TTM_PL_FLAG_PRIV0
Expand All @@ -74,7 +75,7 @@ struct vmw_resource {
bool avail;
void (*hw_destroy) (struct vmw_resource *res);
void (*res_free) (struct vmw_resource *res);

bool on_validate_list;
/* TODO is a generic snooper needed? */
#if 0
void (*snoop)(struct vmw_resource *res,
Expand Down Expand Up @@ -143,8 +144,12 @@ struct vmw_sw_context{
struct list_head validate_nodes;
struct vmw_relocation relocs[VMWGFX_MAX_RELOCATIONS];
uint32_t cur_reloc;
struct ttm_validate_buffer val_bufs[VMWGFX_MAX_GMRS];
struct ttm_validate_buffer val_bufs[VMWGFX_MAX_VALIDATIONS];
uint32_t cur_val_buf;
uint32_t *cmd_bounce;
uint32_t cmd_bounce_size;
struct vmw_resource *resources[VMWGFX_MAX_VALIDATIONS];
uint32_t num_ref_resources;
};

struct vmw_legacy_display;
Expand Down Expand Up @@ -340,7 +345,8 @@ extern int vmw_context_define_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int vmw_context_check(struct vmw_private *dev_priv,
struct ttm_object_file *tfile,
int id);
int id,
struct vmw_resource **p_res);
extern void vmw_surface_res_free(struct vmw_resource *res);
extern int vmw_surface_init(struct vmw_private *dev_priv,
struct vmw_surface *srf,
Expand Down
166 changes: 123 additions & 43 deletions trunk/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,36 @@ static int vmw_cmd_ok(struct vmw_private *dev_priv,
return 0;
}


static int vmw_resource_to_validate_list(struct vmw_sw_context *sw_context,
struct vmw_resource **p_res)
{
int ret = 0;
struct vmw_resource *res = *p_res;

if (!res->on_validate_list) {
if (sw_context->num_ref_resources >= VMWGFX_MAX_VALIDATIONS) {
DRM_ERROR("Too many resources referenced in "
"command stream.\n");
ret = -ENOMEM;
goto out;
}
sw_context->resources[sw_context->num_ref_resources++] = res;
res->on_validate_list = true;
return 0;
}

out:
vmw_resource_unreference(p_res);
return ret;
}

static int vmw_cmd_cid_check(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGA3dCmdHeader *header)
{
struct vmw_resource *ctx;

struct vmw_cid_cmd {
SVGA3dCmdHeader header;
__le32 cid;
Expand All @@ -58,7 +84,8 @@ static int vmw_cmd_cid_check(struct vmw_private *dev_priv,
if (likely(sw_context->cid_valid && cmd->cid == sw_context->last_cid))
return 0;

ret = vmw_context_check(dev_priv, sw_context->tfile, cmd->cid);
ret = vmw_context_check(dev_priv, sw_context->tfile, cmd->cid,
&ctx);
if (unlikely(ret != 0)) {
DRM_ERROR("Could not find or use context %u\n",
(unsigned) cmd->cid);
Expand All @@ -67,39 +94,43 @@ static int vmw_cmd_cid_check(struct vmw_private *dev_priv,

sw_context->last_cid = cmd->cid;
sw_context->cid_valid = true;

return 0;
return vmw_resource_to_validate_list(sw_context, &ctx);
}

static int vmw_cmd_sid_check(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
uint32_t *sid)
{
struct vmw_surface *srf;
int ret;
struct vmw_resource *res;

if (*sid == SVGA3D_INVALID_ID)
return 0;

if (unlikely((!sw_context->sid_valid ||
*sid != sw_context->last_sid))) {
int real_id;
int ret = vmw_surface_check(dev_priv, sw_context->tfile,
*sid, &real_id);

if (unlikely(ret != 0)) {
DRM_ERROR("Could ot find or use surface 0x%08x "
"address 0x%08lx\n",
(unsigned int) *sid,
(unsigned long) sid);
return ret;
}

sw_context->last_sid = *sid;
sw_context->sid_valid = true;
*sid = real_id;
sw_context->sid_translation = real_id;
} else
if (likely((sw_context->sid_valid &&
*sid == sw_context->last_sid))) {
*sid = sw_context->sid_translation;
return 0;
}

return 0;
ret = vmw_user_surface_lookup_handle(dev_priv, sw_context->tfile,
*sid, &srf);
if (unlikely(ret != 0)) {
DRM_ERROR("Could ot find or use surface 0x%08x "
"address 0x%08lx\n",
(unsigned int) *sid,
(unsigned long) sid);
return ret;
}

sw_context->last_sid = *sid;
sw_context->sid_valid = true;
sw_context->sid_translation = srf->res.id;
*sid = sw_context->sid_translation;

res = &srf->res;
return vmw_resource_to_validate_list(sw_context, &res);
}


Expand Down Expand Up @@ -213,7 +244,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
reloc->location = ptr;

cur_validate_node = vmw_dmabuf_validate_node(bo, sw_context->cur_val_buf);
if (unlikely(cur_validate_node >= VMWGFX_MAX_GMRS)) {
if (unlikely(cur_validate_node >= VMWGFX_MAX_VALIDATIONS)) {
DRM_ERROR("Max number of DMA buffers per submission"
" exceeded.\n");
ret = -EINVAL;
Expand Down Expand Up @@ -303,6 +334,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
SVGA3dCmdSurfaceDMA dma;
} *cmd;
int ret;
struct vmw_resource *res;

cmd = container_of(header, struct vmw_dma_cmd, header);
ret = vmw_translate_guest_ptr(dev_priv, sw_context,
Expand All @@ -319,17 +351,16 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
goto out_no_reloc;
}

/**
/*
* Patch command stream with device SID.
*/

cmd->dma.host.sid = srf->res.id;
vmw_kms_cursor_snoop(srf, sw_context->tfile, bo, header);
/**
* FIXME: May deadlock here when called from the
* command parsing code.
*/
vmw_surface_unreference(&srf);

vmw_dmabuf_unreference(&vmw_bo);

res = &srf->res;
return vmw_resource_to_validate_list(sw_context, &res);

out_no_reloc:
vmw_dmabuf_unreference(&vmw_bo);
Expand Down Expand Up @@ -501,8 +532,9 @@ static int vmw_cmd_check(struct vmw_private *dev_priv,

static int vmw_cmd_check_all(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
void *buf, uint32_t size)
uint32_t size)
{
void *buf = sw_context->cmd_bounce;
int32_t cur_size = size;
int ret;

Expand Down Expand Up @@ -551,7 +583,11 @@ static void vmw_apply_relocations(struct vmw_sw_context *sw_context)
static void vmw_clear_validations(struct vmw_sw_context *sw_context)
{
struct ttm_validate_buffer *entry, *next;
uint32_t i = sw_context->num_ref_resources;

/*
* Drop references to DMA buffers held during command submission.
*/
list_for_each_entry_safe(entry, next, &sw_context->validate_nodes,
head) {
list_del(&entry->head);
Expand All @@ -560,6 +596,14 @@ static void vmw_clear_validations(struct vmw_sw_context *sw_context)
sw_context->cur_val_buf--;
}
BUG_ON(sw_context->cur_val_buf != 0);

/*
* Drop references to resources held during command submission.
*/
while (i-- > 0) {
sw_context->resources[i]->on_validate_list = false;
vmw_resource_unreference(&sw_context->resources[i]);
}
}

static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
Expand Down Expand Up @@ -603,6 +647,35 @@ static int vmw_validate_buffers(struct vmw_private *dev_priv,
return 0;
}

static int vmw_resize_cmd_bounce(struct vmw_sw_context *sw_context,
uint32_t size)
{
if (likely(sw_context->cmd_bounce_size >= size))
return 0;

if (sw_context->cmd_bounce_size == 0)
sw_context->cmd_bounce_size = VMWGFX_CMD_BOUNCE_INIT_SIZE;

while (sw_context->cmd_bounce_size < size) {
sw_context->cmd_bounce_size =
PAGE_ALIGN(sw_context->cmd_bounce_size +
(sw_context->cmd_bounce_size >> 1));
}

if (sw_context->cmd_bounce != NULL)
vfree(sw_context->cmd_bounce);

sw_context->cmd_bounce = vmalloc(sw_context->cmd_bounce_size);

if (sw_context->cmd_bounce == NULL) {
DRM_ERROR("Failed to allocate command bounce buffer.\n");
sw_context->cmd_bounce_size = 0;
return -ENOMEM;
}

return 0;
}

int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
Expand All @@ -627,33 +700,33 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
goto out_no_cmd_mutex;
}

cmd = vmw_fifo_reserve(dev_priv, arg->command_size);
if (unlikely(cmd == NULL)) {
DRM_ERROR("Failed reserving fifo space for commands.\n");
ret = -ENOMEM;
ret = vmw_resize_cmd_bounce(sw_context, arg->command_size);
if (unlikely(ret != 0))
goto out_unlock;
}

user_cmd = (void __user *)(unsigned long)arg->commands;
ret = copy_from_user(cmd, user_cmd, arg->command_size);
ret = copy_from_user(sw_context->cmd_bounce,
user_cmd, arg->command_size);

if (unlikely(ret != 0)) {
ret = -EFAULT;
DRM_ERROR("Failed copying commands.\n");
goto out_commit;
goto out_unlock;
}

sw_context->tfile = vmw_fpriv(file_priv)->tfile;
sw_context->cid_valid = false;
sw_context->sid_valid = false;
sw_context->cur_reloc = 0;
sw_context->cur_val_buf = 0;
sw_context->num_ref_resources = 0;

INIT_LIST_HEAD(&sw_context->validate_nodes);

ret = vmw_cmd_check_all(dev_priv, sw_context, cmd, arg->command_size);
ret = vmw_cmd_check_all(dev_priv, sw_context, arg->command_size);
if (unlikely(ret != 0))
goto out_err;

ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes);
if (unlikely(ret != 0))
goto out_err;
Expand All @@ -669,9 +742,17 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
arg->throttle_us);

if (unlikely(ret != 0))
goto out_err;
goto out_throttle;
}

cmd = vmw_fifo_reserve(dev_priv, arg->command_size);
if (unlikely(cmd == NULL)) {
DRM_ERROR("Failed reserving fifo space for commands.\n");
ret = -ENOMEM;
goto out_err;
}

memcpy(cmd, sw_context->cmd_bounce, arg->command_size);
vmw_fifo_commit(dev_priv, arg->command_size);

ret = vmw_fifo_send_fence(dev_priv, &sequence);
Expand Down Expand Up @@ -708,10 +789,9 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
return 0;
out_err:
vmw_free_relocations(sw_context);
out_throttle:
ttm_eu_backoff_reservation(&sw_context->validate_nodes);
vmw_clear_validations(sw_context);
out_commit:
vmw_fifo_commit(dev_priv, 0);
out_unlock:
mutex_unlock(&dev_priv->cmdbuf_mutex);
out_no_cmd_mutex:
Expand Down
5 changes: 4 additions & 1 deletion trunk/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,8 @@ int vmw_context_define_ioctl(struct drm_device *dev, void *data,

int vmw_context_check(struct vmw_private *dev_priv,
struct ttm_object_file *tfile,
int id)
int id,
struct vmw_resource **p_res)
{
struct vmw_resource *res;
int ret = 0;
Expand All @@ -376,6 +377,8 @@ int vmw_context_check(struct vmw_private *dev_priv,
container_of(res, struct vmw_user_context, res);
if (ctx->base.tfile != tfile && !ctx->base.shareable)
ret = -EPERM;
if (p_res)
*p_res = vmw_resource_reference(res);
} else
ret = -EINVAL;
read_unlock(&dev_priv->resource_lock);
Expand Down

0 comments on commit 4cf5ef0

Please sign in to comment.