tty: Prevent deadlock in n_gsm driver
authorDirkjan Bussink <d.bussink@gmail.com>
Wed, 30 Jan 2013 10:44:50 +0000 (11:44 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 28 Feb 2013 14:58:59 +0000 (06:58 -0800)
commit0c10d7fd0d53e3e44cc04edc37120bce6d74e2ca
tree720cd82debce25b029a9a04087b3e728c47c4724
parentceb0446b6dff34bfe41c9fa54796e7b21a17bd56
tty: Prevent deadlock in n_gsm driver

commit 4d9b109060f690f5c835130ff54165ae157b3087 upstream.

This change fixes a deadlock when the multiplexer is closed while there
are still client side ports open.

When the multiplexer is closed and there are active tty's it tries to
close them with tty_vhangup. This has a problem though, because
tty_vhangup needs the tty_lock. This patch changes it to unlock the
tty_lock before attempting the hangup and relocks afterwards. The
additional call to tty_port_tty_set is needed because otherwise the
port stays active because of the reference counter.

This change also exposed another problem that other code paths don't
expect that the multiplexer could have been closed. This patch also adds
checks for these cases in the gsmtty_ class of function that could be
called.

The documentation explicitly states that "first close all virtual ports
before closing the physical port" but we've found this to not always
reality in our field situations. The GPRS / UTMS modem sometimes crashes
and needs a power cycle in that case which means cleanly shutting down
everything is not always possible. This change makes it much more robust
for our situation where at least the system is recoverable with this patch
and doesn't hang in a deadlock situation inside the kernel.

The patch is against the long term support kernel (3.4.27) and should
apply cleanly to more recent branches. Tested with a Telit GE864-QUADV2
and Telit HE910 modem.

Signed-off-by: Dirkjan Bussink <dirkjan.bussink@nedap.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/n_gsm.c