diff options
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c | 59 |
1 files changed, 26 insertions, 33 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c index c706ad30411b..9f45d5004cae 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c @@ -101,6 +101,7 @@ struct vmw_cmdbuf_context { * @handle: DMA address handle for the command buffer space if @using_mob is * false. Immutable. * @size: The size of the command buffer space. Immutable. + * @num_contexts: Number of contexts actually enabled. */ struct vmw_cmdbuf_man { struct mutex cur_mutex; @@ -128,6 +129,7 @@ struct vmw_cmdbuf_man { bool has_pool; dma_addr_t handle; size_t size; + u32 num_contexts; }; /** @@ -185,7 +187,7 @@ struct vmw_cmdbuf_alloc_info { /* Loop over each context in the command buffer manager. */ #define for_each_cmdbuf_ctx(_man, _i, _ctx) \ - for (_i = 0, _ctx = &(_man)->ctx[0]; (_i) < SVGA_CB_CONTEXT_MAX; \ + for (_i = 0, _ctx = &(_man)->ctx[0]; (_i) < (_man)->num_contexts; \ ++(_i), ++(_ctx)) static int vmw_cmdbuf_startstop(struct vmw_cmdbuf_man *man, u32 context, @@ -514,6 +516,7 @@ static void vmw_cmdbuf_work_func(struct work_struct *work) struct list_head restart_head[SVGA_CB_CONTEXT_MAX]; int i; struct vmw_cmdbuf_context *ctx; + bool global_block = false; for_each_cmdbuf_ctx(man, i, ctx) { INIT_LIST_HEAD(&restart_head[i]); @@ -531,6 +534,7 @@ static void vmw_cmdbuf_work_func(struct work_struct *work) list_del_init(&entry->list); restart[entry->cb_context] = true; + global_block = true; if (!vmw_cmd_describe(header, &error_cmd_size, &cmd_name)) { DRM_ERROR("Unknown command causing device error.\n"); @@ -564,23 +568,21 @@ static void vmw_cmdbuf_work_func(struct work_struct *work) cb_hdr->length -= new_start_offset; cb_hdr->errorOffset = 0; cb_hdr->offset = 0; + list_add_tail(&entry->list, &restart_head[entry->cb_context]); - man->ctx[entry->cb_context].block_submission = true; } + + for_each_cmdbuf_ctx(man, i, ctx) + man->ctx[i].block_submission = true; + spin_unlock(&man->lock); - /* Preempt all contexts with errors */ - for_each_cmdbuf_ctx(man, i, ctx) { - if (ctx->block_submission && vmw_cmdbuf_preempt(man, i)) - DRM_ERROR("Failed preempting command buffer " - "context %u.\n", i); - } + /* Preempt all contexts */ + if (global_block && vmw_cmdbuf_preempt(man, 0)) + DRM_ERROR("Failed preempting command buffer contexts\n"); spin_lock(&man->lock); for_each_cmdbuf_ctx(man, i, ctx) { - if (!ctx->block_submission) - continue; - /* Move preempted command buffers to the preempted queue. */ vmw_cmdbuf_ctx_process(man, ctx, &dummy); @@ -594,19 +596,16 @@ static void vmw_cmdbuf_work_func(struct work_struct *work) * Finally add all command buffers first in the submitted * queue, to rerun them. */ - list_splice_init(&restart_head[i], &ctx->submitted); ctx->block_submission = false; + list_splice_init(&restart_head[i], &ctx->submitted); } vmw_cmdbuf_man_process(man); spin_unlock(&man->lock); - for_each_cmdbuf_ctx(man, i, ctx) { - if (restart[i] && vmw_cmdbuf_startstop(man, i, true)) - DRM_ERROR("Failed restarting command buffer " - "context %u.\n", i); - } + if (global_block && vmw_cmdbuf_startstop(man, 0, true)) + DRM_ERROR("Failed restarting command buffer contexts\n"); /* Send a new fence in case one was removed */ if (send_fence) { @@ -1245,7 +1244,7 @@ int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man, return -ENOMEM; ret = ttm_bo_create(&dev_priv->bdev, size, ttm_bo_type_device, - &vmw_mob_ne_placement, 0, false, NULL, + &vmw_mob_ne_placement, 0, false, &man->cmd_space); if (ret) return ret; @@ -1307,6 +1306,8 @@ struct vmw_cmdbuf_man *vmw_cmdbuf_man_create(struct vmw_private *dev_priv) if (!man) return ERR_PTR(-ENOMEM); + man->num_contexts = (dev_priv->capabilities & SVGA_CAP_HP_CMD_QUEUE) ? + 2 : 1; man->headers = dma_pool_create("vmwgfx cmdbuf", &dev_priv->dev->pdev->dev, sizeof(SVGACBHeader), @@ -1341,14 +1342,11 @@ struct vmw_cmdbuf_man *vmw_cmdbuf_man_create(struct vmw_private *dev_priv) INIT_WORK(&man->work, &vmw_cmdbuf_work_func); vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_ERROR, &dev_priv->error_waiters); - for_each_cmdbuf_ctx(man, i, ctx) { - ret = vmw_cmdbuf_startstop(man, i, true); - if (ret) { - DRM_ERROR("Failed starting command buffer " - "context %u.\n", i); - vmw_cmdbuf_man_destroy(man); - return ERR_PTR(ret); - } + ret = vmw_cmdbuf_startstop(man, 0, true); + if (ret) { + DRM_ERROR("Failed starting command buffer contexts\n"); + vmw_cmdbuf_man_destroy(man); + return ERR_PTR(ret); } return man; @@ -1398,16 +1396,11 @@ void vmw_cmdbuf_remove_pool(struct vmw_cmdbuf_man *man) */ void vmw_cmdbuf_man_destroy(struct vmw_cmdbuf_man *man) { - struct vmw_cmdbuf_context *ctx; - unsigned int i; - WARN_ON_ONCE(man->has_pool); (void) vmw_cmdbuf_idle(man, false, 10*HZ); - for_each_cmdbuf_ctx(man, i, ctx) - if (vmw_cmdbuf_startstop(man, i, false)) - DRM_ERROR("Failed stopping command buffer " - "context %u.\n", i); + if (vmw_cmdbuf_startstop(man, 0, false)) + DRM_ERROR("Failed stopping command buffer contexts.\n"); vmw_generic_waiter_remove(man->dev_priv, SVGA_IRQFLAG_ERROR, &man->dev_priv->error_waiters); |