summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2015-09-29 09:35:28 -0700
committerThomas Hellstrom <thellstrom@vmware.com>2015-09-30 05:44:54 -0700
commit067509f58dc84d412cff438e2f9c5f3bece15307 (patch)
treeb906755e4f51035897893c02092a0d1e8f322109
parent5c0d01dc41af4d1244a531df72e45a875ce064f2 (diff)
vmwgfx: Crossport Fix a command submission hang regression
Crossported from upstream: When we're out of command buffer space, we turn on the command buffer processed irq without re-checking for finished command buffers afterwards. This might lead to a missed irq and the command submission process waiting forever for space. Fix this by rerunning the command buffer submission handler whenever we're out of command space. This ensures both that we don't needlessly turn on the irq, and that if we decide to turn on the irq, we recheck for finished command buffers before going to sleep. Reported-and-tested-by: Bryan Li <ldexin@vmware.com> In addition this commit makes sure we retry space allocation if it fails due to a failing atomic kmalloc. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Sinclair Yeh <syeh@vmware.com>
-rw-r--r--vmwgfx_cmdbuf.c24
-rw-r--r--vmwgfx_execbuf.c4
2 files changed, 22 insertions, 6 deletions
diff --git a/vmwgfx_cmdbuf.c b/vmwgfx_cmdbuf.c
index 2bdee50..c1cbc1c 100644
--- a/vmwgfx_cmdbuf.c
+++ b/vmwgfx_cmdbuf.c
@@ -674,6 +674,7 @@ static bool vmw_cmdbuf_try_alloc(struct vmw_cmdbuf_man *man,
if (info->node)
return true;
+retry:
ret = drm_mm_pre_get(&man->mm);
if (ret) {
info->ret = ret;
@@ -681,10 +682,25 @@ static bool vmw_cmdbuf_try_alloc(struct vmw_cmdbuf_man *man,
}
spin_lock_bh(&man->lock);
info->node = drm_mm_search_free(&man->mm, info->page_size, 0, 0);
- if (info->node)
- info->node = drm_mm_get_block_generic(info->node,
- info->page_size,
- 0, 1);
+ if (!info->node) {
+ (void) vmw_cmdbuf_man_process(man);
+ info->node = drm_mm_search_free(&man->mm, info->page_size,
+ 0, 0);
+ if (!info->node)
+ goto out_unlock;
+ }
+
+ info->node = drm_mm_get_block_generic(info->node,
+ info->page_size,
+ 0, 1);
+
+ /* Atomic kmalloc failed? Preload and retry.*/
+ if (!info->node) {
+ spin_unlock_bh(&man->lock);
+ goto retry;
+ }
+
+out_unlock:
spin_unlock_bh(&man->lock);
return !!info->node;
diff --git a/vmwgfx_execbuf.c b/vmwgfx_execbuf.c
index a29dd70..a591691 100644
--- a/vmwgfx_execbuf.c
+++ b/vmwgfx_execbuf.c
@@ -3852,8 +3852,8 @@ static void *vmw_execbuf_cmdbuf(struct vmw_private *dev_priv,
if (IS_ERR(kernel_commands))
return kernel_commands;
- ret = copy_from_user(kernel_commands, user_commands,
- command_size);
+ ret = __copy_from_user_nocache(kernel_commands, user_commands,
+ command_size);
if (ret) {
DRM_ERROR("Failed copying commands.\n");
vmw_cmdbuf_header_free(*header);