From a67e1ae4bf3570e93f8d8fe33b1830de058c1b72 Mon Sep 17 00:00:00 2001 From: Jianxun Zhang Date: Thu, 25 Aug 2016 15:30:55 -0700 Subject: [PATCH] uvesafb: provide option to specify timeout for task completion We try to make this change a generic extension, but it is actually for a corner case. When a VM (qemu) gets a very limited cpu bandwidth from host, which could be under a heavy load, the existing 5000 ms timeout could occur and trigger error messages in the task function's callers. This change adds a new timeout parameter so that we can tweak the value as a workaround or for troubleshooting purposes. In the infinite wait case, A warning message is printed at 5000ms interval. In real world, the current 5 sec is generous enough for a video request in my opinion, so this change could not be very useful. Upstream Status: Inappropriate Signed-off-by: Jianxun Zhang Signed-off-by: Bruce Ashfield --- drivers/video/fbdev/uvesafb.c | 28 ++++++++++++++++++++++------ include/video/uvesafb.h | 4 +++- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/video/fbdev/uvesafb.c b/drivers/video/fbdev/uvesafb.c index 13bbb61a9d8f..bd26813c7562 100644 --- a/drivers/video/fbdev/uvesafb.c +++ b/drivers/video/fbdev/uvesafb.c @@ -40,6 +40,7 @@ static struct fb_fix_screeninfo uvesafb_fix = { .visual = FB_VISUAL_TRUECOLOR, }; +static int task_timeout = UVESAFB_TIMEOUT; /* timeout [ms] of task execution */ static int mtrr = 3; /* enable mtrr by default */ static bool blank = 1; /* enable blanking by default */ static int ypan = 1; /* 0: scroll, 1: ypan, 2: ywrap */ @@ -143,7 +144,9 @@ static int uvesafb_exec(struct uvesafb_ktask *task) struct cn_msg *m; int err; int len = sizeof(task->t) + task->t.buf_len; - + int forever_wait = task_timeout < 0 ? 1 : 0; + /* For infinite wait case, set interval to the legacy 5000 ms */ + int timeout = forever_wait ? 5000 : task_timeout; /* * Check whether the message isn't longer than the maximum * allowed by connector. @@ -212,11 +215,19 @@ static int uvesafb_exec(struct uvesafb_ktask *task) err = 0; if (!err && !(task->t.flags & TF_EXIT)) { - err = !wait_for_completion_timeout(task->done, - msecs_to_jiffies(UVESAFB_TIMEOUT)); - if (err) - printk_ratelimited(KERN_ERR "uvesafb: %u ms task timeout error\n", - UVESAFB_TIMEOUT); + do { + err = !wait_for_completion_timeout(task->done, + msecs_to_jiffies(timeout)); + if (err) + printk_ratelimited( + KERN_WARNING + "uvesafb: %u ms task timeout%s\n", + timeout, + forever_wait ? + ", infinitely waiting." : "."); + else + break; + } while (forever_wait); } mutex_lock(&uvfb_lock); @@ -1840,6 +1851,8 @@ static int uvesafb_setup(char *options) while ((this_opt = strsep(&options, ",")) != NULL) { if (!*this_opt) continue; + if (!strncmp(this_opt, "task_timeout", 12)) + task_timeout = simple_strtol(this_opt+12, NULL, 0); if (!strcmp(this_opt, "redraw")) ypan = 0; else if (!strcmp(this_opt, "ypan")) @@ -1986,6 +1999,9 @@ static const struct kernel_param_ops param_ops_scroll = { }; #define param_check_scroll(name, p) __param_check(name, p, void) +module_param(task_timeout, int, 0400); +MODULE_PARM_DESC(task_timeout, + "Timeout [ms] of a task's completion, or set to any negative value to infinitely wait"); module_param_named(scroll, ypan, scroll, 0); MODULE_PARM_DESC(scroll, "Scrolling mode, set to 'redraw', 'ypan', or 'ywrap'"); diff --git a/include/video/uvesafb.h b/include/video/uvesafb.h index 30f53625415c..bfd1982e8185 100644 --- a/include/video/uvesafb.h +++ b/include/video/uvesafb.h @@ -88,7 +88,9 @@ struct vbe_mode_ib { #define UVESAFB_DEFAULT_MODE "640x480-16" -/* How long to wait for a reply from userspace [ms] */ +/* How long to wait for a reply from userspace [ms] + * This is the default value of module param task_timeout + */ #define UVESAFB_TIMEOUT 5000 /* Max number of concurrent tasks */ -- 2.5.0