aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/n_tty.c
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2013-03-11 16:44:32 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-03-18 19:44:01 -0400
commitb66f4fa509153ca9d313075806d5c6425dfa43c5 (patch)
tree75ffb2d9571849938b20b15e51a361ac58d29b08 /drivers/tty/n_tty.c
parent25518c68b334aa977d857dd71dd53f694ffb11e8 (diff)
n_tty: Fully initialize ldisc before restarting buffer work
Buffer work may already be pending when the n_tty ldisc is re-opened, eg., when setting the ldisc (via TIOCSETD ioctl) and when hanging up the tty. Since n_tty_set_room() may restart buffer work, first ensure the ldisc is completely initialized. Factor n_tty_set_room() out of reset_buffer_flags() (only 2 callers) and reorganize n_tty_open() to set termios last; buffer work will be restarted there if necessary, after the char_map is properly initialized. Fixes this WARNING: [ 549.561769] ------------[ cut here ]------------ [ 549.598755] WARNING: at drivers/tty/n_tty.c:160 n_tty_set_room+0xff/0x130() [ 549.604058] scheduling buffer work for halted ldisc [ 549.607741] Pid: 9417, comm: trinity-child28 Tainted: G D W 3.7.0-next-20121217-sasha-00023-g8689ef9 #219 [ 549.652580] Call Trace: [ 549.662754] [<ffffffff81c432cf>] ? n_tty_set_room+0xff/0x130 [ 549.665458] [<ffffffff8110cae7>] warn_slowpath_common+0x87/0xb0 [ 549.668257] [<ffffffff8110cb71>] warn_slowpath_fmt+0x41/0x50 [ 549.671007] [<ffffffff81c432cf>] n_tty_set_room+0xff/0x130 [ 549.673268] [<ffffffff81c44597>] reset_buffer_flags+0x137/0x150 [ 549.675607] [<ffffffff81c45b71>] n_tty_open+0x131/0x1c0 [ 549.677699] [<ffffffff81c47824>] tty_ldisc_open.isra.5+0x54/0x70 [ 549.680147] [<ffffffff81c482bf>] tty_ldisc_hangup+0x11f/0x1e0 [ 549.682409] [<ffffffff81c3fa17>] __tty_hangup+0x137/0x440 [ 549.684634] [<ffffffff81c3fd49>] tty_vhangup+0x9/0x10 [ 549.686443] [<ffffffff81c4a42c>] pty_close+0x14c/0x160 [ 549.688446] [<ffffffff81c41225>] tty_release+0xd5/0x490 [ 549.690460] [<ffffffff8127d8a2>] __fput+0x122/0x250 [ 549.692577] [<ffffffff8127d9d9>] ____fput+0x9/0x10 [ 549.694534] [<ffffffff811348c2>] task_work_run+0xb2/0xf0 [ 549.696349] [<ffffffff81113c6d>] do_exit+0x36d/0x580 [ 549.698286] [<ffffffff8107d964>] ? syscall_trace_enter+0x24/0x2e0 [ 549.702729] [<ffffffff81113f4a>] do_group_exit+0x8a/0xc0 [ 549.706775] [<ffffffff81113f92>] sys_exit_group+0x12/0x20 [ 549.711088] [<ffffffff83cfab18>] tracesys+0xe1/0xe6 [ 549.728001] ---[ end trace 73eb41728f11f87e ]--- Reported-by: Sasha Levin <levinsasha928@gmail.com> Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/n_tty.c')
-rw-r--r--drivers/tty/n_tty.c17
1 files changed, 8 insertions, 9 deletions
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 0d3f715de7d2..d655416087b7 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -204,9 +204,8 @@ static void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
204 * Locking: tty_read_lock for read fields. 204 * Locking: tty_read_lock for read fields.
205 */ 205 */
206 206
207static void reset_buffer_flags(struct tty_struct *tty) 207static void reset_buffer_flags(struct n_tty_data *ldata)
208{ 208{
209 struct n_tty_data *ldata = tty->disc_data;
210 unsigned long flags; 209 unsigned long flags;
211 210
212 raw_spin_lock_irqsave(&ldata->read_lock, flags); 211 raw_spin_lock_irqsave(&ldata->read_lock, flags);
@@ -219,7 +218,6 @@ static void reset_buffer_flags(struct tty_struct *tty)
219 218
220 ldata->canon_head = ldata->canon_data = ldata->erasing = 0; 219 ldata->canon_head = ldata->canon_data = ldata->erasing = 0;
221 bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); 220 bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
222 n_tty_set_room(tty);
223} 221}
224 222
225static void n_tty_packet_mode_flush(struct tty_struct *tty) 223static void n_tty_packet_mode_flush(struct tty_struct *tty)
@@ -247,7 +245,8 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty)
247 245
248static void n_tty_flush_buffer(struct tty_struct *tty) 246static void n_tty_flush_buffer(struct tty_struct *tty)
249{ 247{
250 reset_buffer_flags(tty); 248 reset_buffer_flags(tty->disc_data);
249 n_tty_set_room(tty);
251 250
252 if (tty->link) 251 if (tty->link)
253 n_tty_packet_mode_flush(tty); 252 n_tty_packet_mode_flush(tty);
@@ -1633,14 +1632,14 @@ static int n_tty_open(struct tty_struct *tty)
1633 goto err_free_bufs; 1632 goto err_free_bufs;
1634 1633
1635 tty->disc_data = ldata; 1634 tty->disc_data = ldata;
1636 /* indicate buffer work may resume */ 1635 reset_buffer_flags(tty->disc_data);
1637 clear_bit(TTY_LDISC_HALTED, &tty->flags);
1638 reset_buffer_flags(tty);
1639 tty_unthrottle(tty);
1640 ldata->column = 0; 1636 ldata->column = 0;
1641 n_tty_set_termios(tty, NULL);
1642 tty->minimum_to_wake = 1; 1637 tty->minimum_to_wake = 1;
1643 tty->closing = 0; 1638 tty->closing = 0;
1639 /* indicate buffer work may resume */
1640 clear_bit(TTY_LDISC_HALTED, &tty->flags);
1641 n_tty_set_termios(tty, NULL);
1642 tty_unthrottle(tty);
1644 1643
1645 return 0; 1644 return 0;
1646err_free_bufs: 1645err_free_bufs: