summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/tty_io.c17
-rw-r--r--drivers/tty/tty_ldisc.c24
2 files changed, 21 insertions, 20 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 458763418701..95e97128e2ee 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1510,6 +1510,17 @@ void tty_free_termios(struct tty_struct *tty)
}
EXPORT_SYMBOL(tty_free_termios);
+/**
+ * tty_flush_works - flush all works of a tty
+ * @tty: tty device to flush works for
+ *
+ * Sync flush all works belonging to @tty.
+ */
+static void tty_flush_works(struct tty_struct *tty)
+{
+ flush_work(&tty->SAK_work);
+ flush_work(&tty->hangup_work);
+}
/**
* release_one_tty - release tty structure memory
@@ -1831,6 +1842,12 @@ int tty_release(struct inode *inode, struct file *filp)
* Ask the line discipline code to release its structures
*/
tty_ldisc_release(tty, o_tty);
+
+ /* Wait for pending work before tty destruction commmences */
+ tty_flush_works(tty);
+ if (o_tty)
+ tty_flush_works(o_tty);
+
/*
* The release_tty function takes care of the details of clearing
* the slots and preserving the termios structure. The tty_unlock_pair
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index cbb945b03cdb..7f7e1a3d3825 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -499,18 +499,6 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
}
/**
- * tty_ldisc_flush_works - flush all works of a tty
- * @tty: tty device to flush works for
- *
- * Sync flush all works belonging to @tty.
- */
-static void tty_ldisc_flush_works(struct tty_struct *tty)
-{
- flush_work(&tty->SAK_work);
- flush_work(&tty->hangup_work);
-}
-
-/**
* tty_ldisc_wait_idle - wait for the ldisc to become idle
* @tty: tty to wait for
* @timeout: for how long to wait at most
@@ -698,13 +686,13 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
retval = tty_ldisc_halt(tty, o_tty, 5 * HZ);
/*
- * Wait for ->hangup_work and ->buf.work handlers to terminate.
+ * Wait for hangup to complete, if pending.
* We must drop the mutex here in case a hangup is also in process.
*/
mutex_unlock(&tty->ldisc_mutex);
- tty_ldisc_flush_works(tty);
+ flush_work(&tty->hangup_work);
tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
@@ -951,15 +939,11 @@ static void tty_ldisc_kill(struct tty_struct *tty)
void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
{
/*
- * Prevent flush_to_ldisc() from rescheduling the work for later. Then
- * kill any delayed work. As this is the final close it does not
- * race with the set_ldisc code path.
+ * Shutdown this line discipline. As this is the final close,
+ * it does not race with the set_ldisc code path.
*/
tty_ldisc_halt(tty, o_tty, MAX_SCHEDULE_TIMEOUT);
- tty_ldisc_flush_works(tty);
- if (o_tty)
- tty_ldisc_flush_works(o_tty);
tty_lock_pair(tty, o_tty);
/* This will need doing differently if we need to lock */