struct tty_ldisc *ld;
struct tty_ldisc_ops *ldops;
int err = -EINVAL;
-
+
ld = kmalloc(sizeof(struct tty_ldisc), GFP_KERNEL);
if (ld == NULL)
return ERR_PTR(-ENOMEM);
}
}
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
- if (err)
+ if (err) {
+ kfree(ld);
return ERR_PTR(err);
+ }
return ld;
}
ldo->refcount--;
module_put(ldo->owner);
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ WARN_ON(ld->refcount);
kfree(ld);
}
-static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
+static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
{
return (*pos < NR_LDISCS) ? pos : NULL;
}
-static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos)
+static void *tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos)
{
(*pos)++;
return (*pos < NR_LDISCS) ? pos : NULL;
{
int i = *(loff_t *)v;
struct tty_ldisc *ld;
-
+
ld = tty_ldisc_try_get(i);
if (IS_ERR(ld))
return 0;
* @ld: line discipline
*
* Install an instance of a line discipline into a tty structure. The
- * ldisc must have a reference count above zero to ensure it remains/
+ * ldisc must have a reference count above zero to ensure it remains.
* The tty instance refcount starts at zero.
*
* Locking:
WARN_ON(tty->ldisc->refcount == 0);
return tty->ldisc;
}
-
EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
/**
return tty->ldisc;
return NULL;
}
-
EXPORT_SYMBOL_GPL(tty_ldisc_ref);
/**
wake_up(&tty_ldisc_wait);
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
}
-
EXPORT_SYMBOL_GPL(tty_ldisc_deref);
/**
}
/**
+ * tty_ldisc_flush - flush line discipline queue
+ * @tty: tty
+ *
+ * Flush the line discipline queue (if any) for this tty. If there
+ * is no line discipline active this is a no-op.
+ */
+
+void tty_ldisc_flush(struct tty_struct *tty)
+{
+ struct tty_ldisc *ld = tty_ldisc_ref(tty);
+ if (ld) {
+ if (ld->ops->flush_buffer)
+ ld->ops->flush_buffer(tty);
+ tty_ldisc_deref(ld);
+ }
+ tty_buffer_flush(tty);
+}
+EXPORT_SYMBOL_GPL(tty_ldisc_flush);
+
+/**
* tty_set_termios_ldisc - set ldisc field
* @tty: tty structure
* @num: line discipline number
if (tty_ldisc_open(tty, old) < 0) {
tty_ldisc_put(old);
/* This driver is always present */
- new_ldisc =tty_ldisc_get(N_TTY);
+ new_ldisc = tty_ldisc_get(N_TTY);
if (IS_ERR(new_ldisc))
panic("n_tty: get");
tty_ldisc_assign(tty, new_ldisc);
* be obtained while the delayed work queue halt ensures that no more
* data is fed to the ldisc.
*
- * In order to wait for any existing references to complete see
+ * In order to wait for any existing references to complete see
* tty_ldisc_wait_idle.
*/
mutex_lock(&tty->ldisc_mutex);
}
set_bit(TTY_LDISC_CHANGING, &tty->flags);
-
+
/*
* No more input please, we are switching. The new ldisc
* will update this value in the ldisc open function
/* Avoid racing set_ldisc */
mutex_lock(&tty->ldisc_mutex);
/* Switch back to N_TTY */
+ tty_ldisc_halt(tty);
+ tty_ldisc_wait_idle(tty);
tty_ldisc_reinit(tty);
/* At this point we have a closed ldisc and we want to
reopen it. We could defer this to the next open but
* @tty: tty being shut down
* @o_tty: pair tty for pty/tty pairs
*
- * Called during the final close of a tty/pty pair in order to shut down the
- * line discpline layer. On exit the ldisc assigned is N_TTY and the
+ * Called during the final close of a tty/pty pair in order to shut down
+ * the line discpline layer. On exit the ldisc assigned is N_TTY and the
* ldisc has not been opened.
*/