msm: smd_tty: Don't call del_timer() on uninitialized timers

Calling del_timer() on uninitialized timers can potentially lead
to a deadlock where a CPU spins forever waiting to lock the timer
base. Enabling debug objects for timers allows us to detect these
problems and resolve them before they become real bugs. This
scenario occurs in smd_tty when the timer has never been
initialized and we close the smd_tty port.

WARNING: at lib/debugobjects.c:262 debug_print_object+0x94/0xbc()
ODEBUG: assert_init not available (active state 0) object type: timer_list
hint: stub_timer+0x0/0x10
Modules linked in:
[<c001521c>] (unwind_backtrace+0x0/0x12c) from [<c007b2fc>]
(warn_slowpath_common+0x4c/0x64)
[<c007b2fc>] (warn_slowpath_common+0x4c/0x64) from [<c007b394>]
(warn_slowpath_fmt+0x2c/0x3c)
[<c007b394>] (warn_slowpath_fmt+0x2c/0x3c) from [<c02edc20>]
(debug_print_object+0x94/0xbc)
[<c02edc20>] (debug_print_object+0x94/0xbc) from [<c02ede48>]
(debug_object_assert_init+0xf4/0x10c)
[<c02ede48>] (debug_object_assert_init+0xf4/0x10c) from [<c008ac98>]
(del_timer+0x10/0x1f0)
[<c008ac98>] (del_timer+0x10/0x1f0) from [<c0037794>]
(smd_tty_close+0x80/0xac)
[<c0037794>] (smd_tty_close+0x80/0xac) from [<c0378dec>]
(tty_release+0x178/0x498)
[<c0378dec>] (tty_release+0x178/0x498) from [<c037965c>]
(tty_open+0x3a8/0x4f4)
[<c037965c>] (tty_open+0x3a8/0x4f4) from [<c01527ac>]
(chrdev_open+0x114/0x134)
[<c01527ac>] (chrdev_open+0x114/0x134) from [<c014ccec>]
(__dentry_open+0x190/0x29c)
[<c014ccec>] (__dentry_open+0x190/0x29c) from [<c014ceb0>]
(nameidata_to_filp+0x58/0x64)
[<c014ceb0>] (nameidata_to_filp+0x58/0x64) from [<c015d73c>]
(do_last+0x840/0x990)
[<c015d73c>] (do_last+0x840/0x990) from [<c015d950>]
(path_openat+0xc4/0x390)
[<c015d950>] (path_openat+0xc4/0x390) from [<c015dcfc>]
(do_filp_open+0x30/0x7c)
[<c015dcfc>] (do_filp_open+0x30/0x7c) from [<c014c9c0>]
(do_sys_open+0xd8/0x174)
[<c014c9c0>] (do_sys_open+0xd8/0x174) from [<c000e340>]
(ret_fast_syscall+0x0/0x3c)

Fix it by initializing the timer when we setup the ports. Use
mod_timer() to increase the timeout when necessary.

Change-Id: Idbc1175ed08761b435c21d858e8d016d451c2991
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
This commit is contained in:
Stephen Boyd
2012-07-02 17:28:13 -07:00
parent a8bbbb5f3e
commit f657ffbff7

View File

@@ -144,14 +144,8 @@ static void smd_tty_read(unsigned long param)
avail = tty_prepare_flip_string(tty, &ptr, avail);
if (avail <= 0) {
if (!timer_pending(&info->buf_req_timer)) {
init_timer(&info->buf_req_timer);
info->buf_req_timer.expires = jiffies +
((30 * HZ)/1000);
info->buf_req_timer.function = buf_req_retry;
info->buf_req_timer.data = param;
add_timer(&info->buf_req_timer);
}
mod_timer(&info->buf_req_timer,
jiffies + msecs_to_jiffies(30));
return;
}
@@ -572,6 +566,8 @@ static int __init smd_tty_init(void)
smd_tty[idx].driver.driver.owner = THIS_MODULE;
spin_lock_init(&smd_tty[idx].reset_lock);
smd_tty[idx].is_open = 0;
setup_timer(&smd_tty[idx].buf_req_timer, buf_req_retry,
(unsigned long)&smd_tty[idx]);
init_waitqueue_head(&smd_tty[idx].ch_opened_wait_queue);
ret = platform_driver_register(&smd_tty[idx].driver);