101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/types.h>
201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/errno.h>
38b3ffa173ffa13ac47c1d7524af92d4b2c95abfcJiri Slaby#include <linux/kmod.h>
401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/sched.h>
501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/interrupt.h>
601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/tty.h>
701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/tty_driver.h>
801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/file.h>
901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/mm.h>
1001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/string.h>
1101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/slab.h>
1201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/poll.h>
1301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/proc_fs.h>
1401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/init.h>
1501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/module.h>
1601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/device.h>
1701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/wait.h>
1801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/bitops.h>
1901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/seq_file.h>
2001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox#include <linux/uaccess.h>
210c73c08ec73dbe080b9ec56696ee21d32754d918Jiri Slaby#include <linux/ratelimit.h>
2201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
2301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox/*
2401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	This guards the refcounted line discipline lists. The lock
2501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	must be taken with irqs off because there are hangup path
2601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	callers who will do ldisc lookups and cannot sleep.
2701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox */
2801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
2901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxstatic DEFINE_SPINLOCK(tty_ldisc_lock);
3001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxstatic DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
31100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slabystatic DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_idle);
3201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox/* Line disc dispatch table */
3301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxstatic struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
3401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
3565b770468e98941e45e19780dff9283e663e6b8bLinus Torvaldsstatic inline struct tty_ldisc *get_ldisc(struct tty_ldisc *ld)
3665b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds{
3765b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds	if (ld)
3865b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds		atomic_inc(&ld->users);
3965b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds	return ld;
4065b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds}
4165b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds
42cbe9352fa08f90aa03b4dbf1bbabfc95d196e562Linus Torvaldsstatic void put_ldisc(struct tty_ldisc *ld)
4365b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds{
44cbe9352fa08f90aa03b4dbf1bbabfc95d196e562Linus Torvalds	unsigned long flags;
45cbe9352fa08f90aa03b4dbf1bbabfc95d196e562Linus Torvalds
4665b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds	if (WARN_ON_ONCE(!ld))
4765b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds		return;
4865b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds
4965b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds	/*
5065b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds	 * If this is the last user, free the ldisc, and
5165b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds	 * release the ldisc ops.
52cbe9352fa08f90aa03b4dbf1bbabfc95d196e562Linus Torvalds	 *
53cbe9352fa08f90aa03b4dbf1bbabfc95d196e562Linus Torvalds	 * We really want an "atomic_dec_and_lock_irqsave()",
54cbe9352fa08f90aa03b4dbf1bbabfc95d196e562Linus Torvalds	 * but we don't have it, so this does it by hand.
5565b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds	 */
56cbe9352fa08f90aa03b4dbf1bbabfc95d196e562Linus Torvalds	local_irq_save(flags);
57cbe9352fa08f90aa03b4dbf1bbabfc95d196e562Linus Torvalds	if (atomic_dec_and_lock(&ld->users, &tty_ldisc_lock)) {
5865b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds		struct tty_ldisc_ops *ldo = ld->ops;
5965b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds
6065b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds		ldo->refcount--;
6165b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds		module_put(ldo->owner);
6265b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds		spin_unlock_irqrestore(&tty_ldisc_lock, flags);
63cbe9352fa08f90aa03b4dbf1bbabfc95d196e562Linus Torvalds
64cbe9352fa08f90aa03b4dbf1bbabfc95d196e562Linus Torvalds		kfree(ld);
65cbe9352fa08f90aa03b4dbf1bbabfc95d196e562Linus Torvalds		return;
6665b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds	}
67cbe9352fa08f90aa03b4dbf1bbabfc95d196e562Linus Torvalds	local_irq_restore(flags);
68100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby	wake_up(&tty_ldisc_idle);
6965b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds}
7065b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds
7101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox/**
7201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	tty_register_ldisc	-	install a line discipline
7301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@disc: ldisc number
7401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@new_ldisc: pointer to the ldisc object
7501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
7601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Installs a new line discipline into the kernel. The discipline
7701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	is set up as unreferenced and then made available to the kernel
7801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	from this point onwards.
7901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
8001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Locking:
8101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *		takes tty_ldisc_lock to guard against ldisc races
8201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox */
8301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
8401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxint tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
8501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
8601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	unsigned long flags;
8701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	int ret = 0;
8801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
8901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	if (disc < N_TTY || disc >= NR_LDISCS)
9001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox		return -EINVAL;
9101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
9201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	spin_lock_irqsave(&tty_ldisc_lock, flags);
9301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	tty_ldiscs[disc] = new_ldisc;
9401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	new_ldisc->num = disc;
9501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	new_ldisc->refcount = 0;
9601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
9701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
9801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	return ret;
9901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
10001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan CoxEXPORT_SYMBOL(tty_register_ldisc);
10101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
10201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox/**
10301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	tty_unregister_ldisc	-	unload a line discipline
10401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@disc: ldisc number
10501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@new_ldisc: pointer to the ldisc object
10601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
10701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Remove a line discipline from the kernel providing it is not
10801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	currently in use.
10901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
11001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Locking:
11101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *		takes tty_ldisc_lock to guard against ldisc races
11201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox */
11301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
11401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxint tty_unregister_ldisc(int disc)
11501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
11601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	unsigned long flags;
11701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	int ret = 0;
11801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
11901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	if (disc < N_TTY || disc >= NR_LDISCS)
12001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox		return -EINVAL;
12101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
12201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	spin_lock_irqsave(&tty_ldisc_lock, flags);
12301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	if (tty_ldiscs[disc]->refcount)
12401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox		ret = -EBUSY;
12501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	else
12601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox		tty_ldiscs[disc] = NULL;
12701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
12801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
12901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	return ret;
13001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
13101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan CoxEXPORT_SYMBOL(tty_unregister_ldisc);
13201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
133f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvaldsstatic struct tty_ldisc_ops *get_ldops(int disc)
134f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds{
135f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	unsigned long flags;
136f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	struct tty_ldisc_ops *ldops, *ret;
137f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds
138f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	spin_lock_irqsave(&tty_ldisc_lock, flags);
139f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	ret = ERR_PTR(-EINVAL);
140f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	ldops = tty_ldiscs[disc];
141f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	if (ldops) {
142f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds		ret = ERR_PTR(-EAGAIN);
143f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds		if (try_module_get(ldops->owner)) {
144f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds			ldops->refcount++;
145f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds			ret = ldops;
146f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds		}
147f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	}
148f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
149f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	return ret;
150f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds}
151f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds
152f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvaldsstatic void put_ldops(struct tty_ldisc_ops *ldops)
153f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds{
154f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	unsigned long flags;
155f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds
156f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	spin_lock_irqsave(&tty_ldisc_lock, flags);
157f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	ldops->refcount--;
158f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	module_put(ldops->owner);
159f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
160f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds}
16101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
16201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox/**
16301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	tty_ldisc_get		-	take a reference to an ldisc
16401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@disc: ldisc number
16501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
16601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Takes a reference to a line discipline. Deals with refcounts and
16701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	module locking counts. Returns NULL if the discipline is not available.
16801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Returns a pointer to the discipline and bumps the ref count if it is
16901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	available
17001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
17101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Locking:
17201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *		takes tty_ldisc_lock to guard against ldisc races
17301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox */
17401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
175c65c9bc3efa5589f691276bb9db689119a711222Alan Coxstatic struct tty_ldisc *tty_ldisc_get(int disc)
17601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
177c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	struct tty_ldisc *ld;
178182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds	struct tty_ldisc_ops *ldops;
17901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
18001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	if (disc < N_TTY || disc >= NR_LDISCS)
181c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		return ERR_PTR(-EINVAL);
182182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds
183182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds	/*
184182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds	 * Get the ldisc ops - we may need to request them to be loaded
185182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds	 * dynamically and try again.
186182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds	 */
187182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds	ldops = get_ldops(disc);
188182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds	if (IS_ERR(ldops)) {
18901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox		request_module("tty-ldisc-%d", disc);
190182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds		ldops = get_ldops(disc);
191182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds		if (IS_ERR(ldops))
192182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds			return ERR_CAST(ldops);
193182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds	}
194182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds
195182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds	ld = kmalloc(sizeof(struct tty_ldisc), GFP_KERNEL);
196182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds	if (ld == NULL) {
197182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds		put_ldops(ldops);
198182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds		return ERR_PTR(-ENOMEM);
19901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	}
200182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds
201182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds	ld->ops = ldops;
202182274f85fc26ec3aa8c78dba8b0e7763af3c586Linus Torvalds	atomic_set(&ld->users, 1);
203c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	return ld;
20401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
20501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
206852e99d22f2231d232c45216b027565e3bae7addAlan Coxstatic void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
20701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
20801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	return (*pos < NR_LDISCS) ? pos : NULL;
20901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
21001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
211852e99d22f2231d232c45216b027565e3bae7addAlan Coxstatic void *tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos)
21201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
21301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	(*pos)++;
21401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	return (*pos < NR_LDISCS) ? pos : NULL;
21501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
21601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
21701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxstatic void tty_ldiscs_seq_stop(struct seq_file *m, void *v)
21801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
21901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
22001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
22101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxstatic int tty_ldiscs_seq_show(struct seq_file *m, void *v)
22201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
22301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	int i = *(loff_t *)v;
224f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	struct tty_ldisc_ops *ldops;
225852e99d22f2231d232c45216b027565e3bae7addAlan Cox
226f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	ldops = get_ldops(i);
227f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	if (IS_ERR(ldops))
22801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox		return 0;
229f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	seq_printf(m, "%-10s %2d\n", ldops->name ? ldops->name : "???", i);
230f0de0e8d3565ee7feba6228d99763d4cea2087a6Linus Torvalds	put_ldops(ldops);
23101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	return 0;
23201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
23301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
23401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxstatic const struct seq_operations tty_ldiscs_seq_ops = {
23501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	.start	= tty_ldiscs_seq_start,
23601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	.next	= tty_ldiscs_seq_next,
23701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	.stop	= tty_ldiscs_seq_stop,
23801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	.show	= tty_ldiscs_seq_show,
23901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox};
24001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
24101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxstatic int proc_tty_ldiscs_open(struct inode *inode, struct file *file)
24201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
24301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	return seq_open(file, &tty_ldiscs_seq_ops);
24401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
24501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
24601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxconst struct file_operations tty_ldiscs_proc_fops = {
24701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	.owner		= THIS_MODULE,
24801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	.open		= proc_tty_ldiscs_open,
24901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	.read		= seq_read,
25001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	.llseek		= seq_lseek,
25101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	.release	= seq_release,
25201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox};
25301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
25401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox/**
25501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	tty_ldisc_assign	-	set ldisc on a tty
25601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@tty: tty to assign
25701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@ld: line discipline
25801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
25901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Install an instance of a line discipline into a tty structure. The
2608d2ead743dd54dff1fe3d0f4933e5da8bfe07472Alan Cox *	ldisc must have a reference count above zero to ensure it remains.
26101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	The tty instance refcount starts at zero.
26201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
26301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Locking:
26401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *		Caller must hold references
26501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox */
26601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
26701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxstatic void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
26801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
269c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	tty->ldisc = ld;
27001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
27101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
27201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox/**
27301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	tty_ldisc_try		-	internal helper
27401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@tty: the tty
27501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
27601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Make a single attempt to grab and bump the refcount on
27701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	the tty ldisc. Return 0 on failure or 1 on success. This is
27801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	used to implement both the waiting and non waiting versions
27901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	of tty_ldisc_ref
28001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
28101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Locking: takes tty_ldisc_lock
28201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox */
28301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
28465b770468e98941e45e19780dff9283e663e6b8bLinus Torvaldsstatic struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty)
28501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
28601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	unsigned long flags;
28701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	struct tty_ldisc *ld;
28801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
28901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	spin_lock_irqsave(&tty_ldisc_lock, flags);
29065b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds	ld = NULL;
29165b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds	if (test_bit(TTY_LDISC, &tty->flags))
29265b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds		ld = get_ldisc(tty->ldisc);
29301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
29465b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds	return ld;
29501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
29601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
29701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox/**
29801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	tty_ldisc_ref_wait	-	wait for the tty ldisc
29901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@tty: tty device
30001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
30101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Dereference the line discipline for the terminal and take a
30201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	reference to it. If the line discipline is in flux then
30301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	wait patiently until it changes.
30401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
30501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Note: Must not be called from an IRQ/timer context. The caller
30601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	must also be careful not to hold other locks that will deadlock
30701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	against a discipline change, such as an existing ldisc reference
30801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	(which we check for)
30901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
31001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Locking: call functions take tty_ldisc_lock
31101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox */
31201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
31301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxstruct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
31401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
31565b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds	struct tty_ldisc *ld;
31665b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds
31701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	/* wait_event is a macro */
31865b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds	wait_event(tty_ldisc_wait, (ld = tty_ldisc_try(tty)) != NULL);
31965b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds	return ld;
32001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
32101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan CoxEXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
32201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
32301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox/**
32401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	tty_ldisc_ref		-	get the tty ldisc
32501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@tty: tty device
32601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
32701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Dereference the line discipline for the terminal and take a
32801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	reference to it. If the line discipline is in flux then
32901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	return NULL. Can be called from IRQ and timer functions.
33001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
33101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Locking: called functions take tty_ldisc_lock
33201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox */
33301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
33401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxstruct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
33501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
33665b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds	return tty_ldisc_try(tty);
33701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
33801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan CoxEXPORT_SYMBOL_GPL(tty_ldisc_ref);
33901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
34001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox/**
34101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	tty_ldisc_deref		-	free a tty ldisc reference
34201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@ld: reference to free up
34301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
34401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
34501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	be called in IRQ context.
34601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
34701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Locking: takes tty_ldisc_lock
34801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox */
34901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
35001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxvoid tty_ldisc_deref(struct tty_ldisc *ld)
35101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
35265b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds	put_ldisc(ld);
35301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
35401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan CoxEXPORT_SYMBOL_GPL(tty_ldisc_deref);
35501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
35665b770468e98941e45e19780dff9283e663e6b8bLinus Torvaldsstatic inline void tty_ldisc_put(struct tty_ldisc *ld)
35765b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds{
35865b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds	put_ldisc(ld);
35965b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds}
36065b770468e98941e45e19780dff9283e663e6b8bLinus Torvalds
36101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox/**
36201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	tty_ldisc_enable	-	allow ldisc use
36301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@tty: terminal to activate ldisc on
36401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
36501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Set the TTY_LDISC flag when the line discipline can be called
366c9b3976e3fec266be25c5001a70aa0a890b6c476Alan Cox *	again. Do necessary wakeups for existing sleepers. Clear the LDISC
367c9b3976e3fec266be25c5001a70aa0a890b6c476Alan Cox *	changing flag to indicate any ldisc change is now over.
36801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
369c9b3976e3fec266be25c5001a70aa0a890b6c476Alan Cox *	Note: nobody should set the TTY_LDISC bit except via this function.
370c9b3976e3fec266be25c5001a70aa0a890b6c476Alan Cox *	Clearing directly is allowed.
37101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox */
37201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
37301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxvoid tty_ldisc_enable(struct tty_struct *tty)
37401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
37501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	set_bit(TTY_LDISC, &tty->flags);
376c9b3976e3fec266be25c5001a70aa0a890b6c476Alan Cox	clear_bit(TTY_LDISC_CHANGING, &tty->flags);
37701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	wake_up(&tty_ldisc_wait);
37801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
37901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
38001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox/**
381f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox *	tty_ldisc_flush	-	flush line discipline queue
382f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox *	@tty: tty
383f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox *
384f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox *	Flush the line discipline queue (if any) for this tty. If there
385f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox *	is no line discipline active this is a no-op.
386f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox */
387f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox
388f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Coxvoid tty_ldisc_flush(struct tty_struct *tty)
389f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox{
390f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox	struct tty_ldisc *ld = tty_ldisc_ref(tty);
391f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox	if (ld) {
392f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox		if (ld->ops->flush_buffer)
393f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox			ld->ops->flush_buffer(tty);
394f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox		tty_ldisc_deref(ld);
395f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox	}
396f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox	tty_buffer_flush(tty);
397f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox}
398f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan CoxEXPORT_SYMBOL_GPL(tty_ldisc_flush);
399f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox
400f2c4c65c8350d885d74dcdea7061dcecc1223c36Alan Cox/**
40101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	tty_set_termios_ldisc		-	set ldisc field
40201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@tty: tty structure
40301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@num: line discipline number
40401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
40501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	This is probably overkill for real world processors but
40601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	they are not on hot paths so a little discipline won't do
40701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	any harm.
40801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
40901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Locking: takes termios_mutex
41001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox */
41101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
41201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxstatic void tty_set_termios_ldisc(struct tty_struct *tty, int num)
41301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
41401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	mutex_lock(&tty->termios_mutex);
41501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	tty->termios->c_line = num;
41601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	mutex_unlock(&tty->termios_mutex);
41701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
41801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
419c65c9bc3efa5589f691276bb9db689119a711222Alan Cox/**
420c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	tty_ldisc_open		-	open a line discipline
421c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	@tty: tty we are opening the ldisc on
422c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	@ld: discipline to open
423c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *
424c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	A helper opening method. Also a convenient debugging and check
425c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	point.
426ec79d6056de58511d8e46d9ae59d3878f958dc3eArnd Bergmann *
427ec79d6056de58511d8e46d9ae59d3878f958dc3eArnd Bergmann *	Locking: always called with BTM already held.
428c65c9bc3efa5589f691276bb9db689119a711222Alan Cox */
429c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
430c65c9bc3efa5589f691276bb9db689119a711222Alan Coxstatic int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
431c65c9bc3efa5589f691276bb9db689119a711222Alan Cox{
432c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags));
433f18f9498e90327b9b0e245e191029e6e1996d203Alan Cox	if (ld->ops->open) {
434f18f9498e90327b9b0e245e191029e6e1996d203Alan Cox		int ret;
435ec79d6056de58511d8e46d9ae59d3878f958dc3eArnd Bergmann                /* BTM here locks versus a hangup event */
436f18f9498e90327b9b0e245e191029e6e1996d203Alan Cox		ret = ld->ops->open(tty);
4377f90cfc505d613f4faf096e0d84ffe99208057d9Jiri Slaby		if (ret)
4387f90cfc505d613f4faf096e0d84ffe99208057d9Jiri Slaby			clear_bit(TTY_LDISC_OPEN, &tty->flags);
439f18f9498e90327b9b0e245e191029e6e1996d203Alan Cox		return ret;
440f18f9498e90327b9b0e245e191029e6e1996d203Alan Cox	}
441c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	return 0;
442c65c9bc3efa5589f691276bb9db689119a711222Alan Cox}
443c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
444c65c9bc3efa5589f691276bb9db689119a711222Alan Cox/**
445c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	tty_ldisc_close		-	close a line discipline
446c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	@tty: tty we are opening the ldisc on
447c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	@ld: discipline to close
448c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *
449c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	A helper close method. Also a convenient debugging and check
450c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	point.
451c65c9bc3efa5589f691276bb9db689119a711222Alan Cox */
452c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
453c65c9bc3efa5589f691276bb9db689119a711222Alan Coxstatic void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
454c65c9bc3efa5589f691276bb9db689119a711222Alan Cox{
455c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	WARN_ON(!test_bit(TTY_LDISC_OPEN, &tty->flags));
456c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	clear_bit(TTY_LDISC_OPEN, &tty->flags);
457c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	if (ld->ops->close)
458c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		ld->ops->close(tty);
459c65c9bc3efa5589f691276bb9db689119a711222Alan Cox}
46001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
46101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox/**
46201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	tty_ldisc_restore	-	helper for tty ldisc change
46301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@tty: tty to recover
46401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@old: previous ldisc
46501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
46601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Restore the previous line discipline or N_TTY when a line discipline
46701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	change fails due to an open error
46801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox */
46901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
47001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxstatic void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
47101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
47201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	char buf[64];
473c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	struct tty_ldisc *new_ldisc;
474c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	int r;
47501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
47601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	/* There is an outstanding reference here so this is safe */
477c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	old = tty_ldisc_get(old->ops->num);
478c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	WARN_ON(IS_ERR(old));
47901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	tty_ldisc_assign(tty, old);
48001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	tty_set_termios_ldisc(tty, old->ops->num);
481c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	if (tty_ldisc_open(tty, old) < 0) {
482c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		tty_ldisc_put(old);
48301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox		/* This driver is always present */
484852e99d22f2231d232c45216b027565e3bae7addAlan Cox		new_ldisc = tty_ldisc_get(N_TTY);
485c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		if (IS_ERR(new_ldisc))
48601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox			panic("n_tty: get");
487c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		tty_ldisc_assign(tty, new_ldisc);
48801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox		tty_set_termios_ldisc(tty, N_TTY);
489c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		r = tty_ldisc_open(tty, new_ldisc);
490c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		if (r < 0)
491c65c9bc3efa5589f691276bb9db689119a711222Alan Cox			panic("Couldn't open N_TTY ldisc for "
492c65c9bc3efa5589f691276bb9db689119a711222Alan Cox			      "%s --- error %d.",
493c65c9bc3efa5589f691276bb9db689119a711222Alan Cox			      tty_name(tty, buf), r);
49401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	}
49501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
49601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
49701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox/**
498c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	tty_ldisc_halt		-	shut down the line discipline
499e8b70e7d3e86319a8b2aaabde3866833d92cd80fAlan Cox *	@tty: tty device
500e8b70e7d3e86319a8b2aaabde3866833d92cd80fAlan Cox *
501e8b70e7d3e86319a8b2aaabde3866833d92cd80fAlan Cox *	Shut down the line discipline and work queue for this tty device.
502e8b70e7d3e86319a8b2aaabde3866833d92cd80fAlan Cox *	The TTY_LDISC flag being cleared ensures no further references can
503e8b70e7d3e86319a8b2aaabde3866833d92cd80fAlan Cox *	be obtained while the delayed work queue halt ensures that no more
504e8b70e7d3e86319a8b2aaabde3866833d92cd80fAlan Cox *	data is fed to the ldisc.
505e8b70e7d3e86319a8b2aaabde3866833d92cd80fAlan Cox *
5065c58ceff103d8a654f24769bb1baaf84a841b0ccLinus Torvalds *	You need to do a 'flush_scheduled_work()' (outside the ldisc_mutex)
5075c58ceff103d8a654f24769bb1baaf84a841b0ccLinus Torvalds *	in order to make sure any currently executing ldisc work is also
5085c58ceff103d8a654f24769bb1baaf84a841b0ccLinus Torvalds *	flushed.
509e8b70e7d3e86319a8b2aaabde3866833d92cd80fAlan Cox */
510e8b70e7d3e86319a8b2aaabde3866833d92cd80fAlan Cox
511c65c9bc3efa5589f691276bb9db689119a711222Alan Coxstatic int tty_ldisc_halt(struct tty_struct *tty)
512e8b70e7d3e86319a8b2aaabde3866833d92cd80fAlan Cox{
513e8b70e7d3e86319a8b2aaabde3866833d92cd80fAlan Cox	clear_bit(TTY_LDISC, &tty->flags);
514f23eb2b2b28547fc70df82dd5049eb39bec5ba12Linus Torvalds	return cancel_work_sync(&tty->buf.work);
515e8b70e7d3e86319a8b2aaabde3866833d92cd80fAlan Cox}
516e8b70e7d3e86319a8b2aaabde3866833d92cd80fAlan Cox
517e8b70e7d3e86319a8b2aaabde3866833d92cd80fAlan Cox/**
5180a1f1a0b626d79071ee9fe91b7fcd28be6332677Tejun Heo *	tty_ldisc_flush_works	-	flush all works of a tty
5190a1f1a0b626d79071ee9fe91b7fcd28be6332677Tejun Heo *	@tty: tty device to flush works for
5200a1f1a0b626d79071ee9fe91b7fcd28be6332677Tejun Heo *
5210a1f1a0b626d79071ee9fe91b7fcd28be6332677Tejun Heo *	Sync flush all works belonging to @tty.
5220a1f1a0b626d79071ee9fe91b7fcd28be6332677Tejun Heo */
5230a1f1a0b626d79071ee9fe91b7fcd28be6332677Tejun Heostatic void tty_ldisc_flush_works(struct tty_struct *tty)
5240a1f1a0b626d79071ee9fe91b7fcd28be6332677Tejun Heo{
5250a1f1a0b626d79071ee9fe91b7fcd28be6332677Tejun Heo	flush_work_sync(&tty->hangup_work);
5260a1f1a0b626d79071ee9fe91b7fcd28be6332677Tejun Heo	flush_work_sync(&tty->SAK_work);
527f23eb2b2b28547fc70df82dd5049eb39bec5ba12Linus Torvalds	flush_work_sync(&tty->buf.work);
5280a1f1a0b626d79071ee9fe91b7fcd28be6332677Tejun Heo}
5290a1f1a0b626d79071ee9fe91b7fcd28be6332677Tejun Heo
5300a1f1a0b626d79071ee9fe91b7fcd28be6332677Tejun Heo/**
531100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby *	tty_ldisc_wait_idle	-	wait for the ldisc to become idle
532100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby *	@tty: tty to wait for
533df92d0561de364de53c42abc5d43e04ab6f326a5Jiri Slaby *	@timeout: for how long to wait at most
534100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby *
535100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby *	Wait for the line discipline to become idle. The discipline must
536100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby *	have been halted for this to guarantee it remains idle.
537100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby */
538df92d0561de364de53c42abc5d43e04ab6f326a5Jiri Slabystatic int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout)
539100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby{
540df92d0561de364de53c42abc5d43e04ab6f326a5Jiri Slaby	long ret;
54192f6fa09bd453ffe3351fa1f1377a1b7cfa911e6Jiri Slaby	ret = wait_event_timeout(tty_ldisc_idle,
542df92d0561de364de53c42abc5d43e04ab6f326a5Jiri Slaby			atomic_read(&tty->ldisc->users) == 1, timeout);
543100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby	return ret > 0 ? 0 : -EBUSY;
544100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby}
545100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby
546100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby/**
54701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	tty_set_ldisc		-	set line discipline
54801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@tty: the terminal to set
54901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@ldisc: the line discipline
55001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
55101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Set the discipline of a tty line. Must be called from a process
552c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	context. The ldisc change logic has to protect itself against any
553c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	overlapping ldisc change (including on the other end of pty pairs),
554c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	the close of one side of a tty/pty pair, and eventually hangup.
55501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
556c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	Locking: takes tty_ldisc_lock, termios_mutex
55701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox */
55801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
55901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxint tty_set_ldisc(struct tty_struct *tty, int ldisc)
56001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
56101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	int retval;
562c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	struct tty_ldisc *o_ldisc, *new_ldisc;
563c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	int work, o_work = 0;
56401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	struct tty_struct *o_tty;
56501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
566c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	new_ldisc = tty_ldisc_get(ldisc);
567c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	if (IS_ERR(new_ldisc))
568c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		return PTR_ERR(new_ldisc);
56901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
570ec79d6056de58511d8e46d9ae59d3878f958dc3eArnd Bergmann	tty_lock();
57101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	/*
572c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 *	We need to look at the tty locking here for pty/tty pairs
573c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 *	when both sides try to change in parallel.
57401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	 */
57501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
576c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	o_tty = tty->link;	/* o_tty is the pty side or NULL */
577c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
57801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
579c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	/*
580c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 *	Check the no-op case
581c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 */
582c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
583c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	if (tty->ldisc->ops->num == ldisc) {
584ec79d6056de58511d8e46d9ae59d3878f958dc3eArnd Bergmann		tty_unlock();
585c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		tty_ldisc_put(new_ldisc);
58601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox		return 0;
58701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	}
58801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
589ec79d6056de58511d8e46d9ae59d3878f958dc3eArnd Bergmann	tty_unlock();
59001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	/*
591c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 *	Problem: What do we do if this blocks ?
592c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 *	We could deadlock here
593c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 */
594c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
595c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	tty_wait_until_sent(tty, 0);
596c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
59760af22d2ed490554cc92c8d0fed0b5b9cf687568Arnd Bergmann	tty_lock();
598c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	mutex_lock(&tty->ldisc_mutex);
599c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
600c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	/*
601c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 *	We could be midstream of another ldisc change which has
602c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 *	dropped the lock during processing. If so we need to wait.
603c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 */
604c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
605c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) {
606c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		mutex_unlock(&tty->ldisc_mutex);
60760af22d2ed490554cc92c8d0fed0b5b9cf687568Arnd Bergmann		tty_unlock();
608c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		wait_event(tty_ldisc_wait,
609c65c9bc3efa5589f691276bb9db689119a711222Alan Cox			test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0);
61060af22d2ed490554cc92c8d0fed0b5b9cf687568Arnd Bergmann		tty_lock();
611c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		mutex_lock(&tty->ldisc_mutex);
612c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	}
613eeb89d918c2fa2b809e464136bbafdaec2aacb30Alan Cox
614c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	set_bit(TTY_LDISC_CHANGING, &tty->flags);
615852e99d22f2231d232c45216b027565e3bae7addAlan Cox
616c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	/*
61701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	 *	No more input please, we are switching. The new ldisc
61801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	 *	will update this value in the ldisc open function
61901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	 */
62001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
62101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	tty->receive_room = 0;
62201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
62301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	o_ldisc = tty->ldisc;
624eeb89d918c2fa2b809e464136bbafdaec2aacb30Alan Cox
625ec79d6056de58511d8e46d9ae59d3878f958dc3eArnd Bergmann	tty_unlock();
62601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	/*
62701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	 *	Make sure we don't change while someone holds a
62801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	 *	reference to the line discipline. The TTY_LDISC bit
62901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	 *	prevents anyone taking a reference once it is clear.
63001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	 *	We need the lock to avoid racing reference takers.
631c9b3976e3fec266be25c5001a70aa0a890b6c476Alan Cox	 *
632c9b3976e3fec266be25c5001a70aa0a890b6c476Alan Cox	 *	We must clear the TTY_LDISC bit here to avoid a livelock
633c9b3976e3fec266be25c5001a70aa0a890b6c476Alan Cox	 *	with a userspace app continually trying to use the tty in
634c9b3976e3fec266be25c5001a70aa0a890b6c476Alan Cox	 *	parallel to the change and re-referencing the tty.
63501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	 */
63601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
637c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	work = tty_ldisc_halt(tty);
63801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	if (o_tty)
639c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		o_work = tty_ldisc_halt(o_tty);
64001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
64101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	/*
642c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 * Wait for ->hangup_work and ->buf.work handlers to terminate.
643c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 * We must drop the mutex here in case a hangup is also in process.
64401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	 */
645c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
646c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	mutex_unlock(&tty->ldisc_mutex);
647c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
6480a1f1a0b626d79071ee9fe91b7fcd28be6332677Tejun Heo	tty_ldisc_flush_works(tty);
649c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
650df92d0561de364de53c42abc5d43e04ab6f326a5Jiri Slaby	retval = tty_ldisc_wait_idle(tty, 5 * HZ);
651100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby
652ec79d6056de58511d8e46d9ae59d3878f958dc3eArnd Bergmann	tty_lock();
65360af22d2ed490554cc92c8d0fed0b5b9cf687568Arnd Bergmann	mutex_lock(&tty->ldisc_mutex);
654100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby
655100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby	/* handle wait idle failure locked */
656100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby	if (retval) {
657100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby		tty_ldisc_put(new_ldisc);
658100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby		goto enable;
659100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby	}
660100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slaby
661c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	if (test_bit(TTY_HUPPED, &tty->flags)) {
662c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		/* We were raced by the hangup method. It will have stomped
663c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		   the ldisc data and closed the ldisc down */
664c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		clear_bit(TTY_LDISC_CHANGING, &tty->flags);
665c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		mutex_unlock(&tty->ldisc_mutex);
666c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		tty_ldisc_put(new_ldisc);
667ec79d6056de58511d8e46d9ae59d3878f958dc3eArnd Bergmann		tty_unlock();
668c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		return -EIO;
669c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	}
670c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
67101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	/* Shutdown the current discipline. */
672c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	tty_ldisc_close(tty, o_ldisc);
67301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
67401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	/* Now set up the new line discipline. */
675c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	tty_ldisc_assign(tty, new_ldisc);
67601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	tty_set_termios_ldisc(tty, ldisc);
677c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
678c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	retval = tty_ldisc_open(tty, new_ldisc);
67901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	if (retval < 0) {
680c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		/* Back to the old one or N_TTY if we can't */
681c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		tty_ldisc_put(new_ldisc);
682c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		tty_ldisc_restore(tty, o_ldisc);
68301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	}
684c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
68501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	/* At this point we hold a reference to the new ldisc and a
68601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	   a reference to the old ldisc. If we ended up flipping back
68701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	   to the existing ldisc we have two references to it */
68801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
689c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	if (tty->ldisc->ops->num != o_ldisc->ops->num && tty->ops->set_ldisc)
69001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox		tty->ops->set_ldisc(tty);
69101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
692c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	tty_ldisc_put(o_ldisc);
69301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
694100eeae2c5ce23b4db93ff320ee330ef1d740151Jiri Slabyenable:
69501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	/*
696c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 *	Allow ldisc referencing to occur again
69701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	 */
69801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
69901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	tty_ldisc_enable(tty);
70001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	if (o_tty)
70101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox		tty_ldisc_enable(o_tty);
70201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
703c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	/* Restart the work queue in case no characters kick it off. Safe if
70401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	   already running */
70501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	if (work)
706f23eb2b2b28547fc70df82dd5049eb39bec5ba12Linus Torvalds		schedule_work(&tty->buf.work);
707c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	if (o_work)
708f23eb2b2b28547fc70df82dd5049eb39bec5ba12Linus Torvalds		schedule_work(&o_tty->buf.work);
709c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	mutex_unlock(&tty->ldisc_mutex);
710ec79d6056de58511d8e46d9ae59d3878f958dc3eArnd Bergmann	tty_unlock();
71101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	return retval;
71201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
71301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
714c65c9bc3efa5589f691276bb9db689119a711222Alan Cox/**
715c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	tty_reset_termios	-	reset terminal state
716c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	@tty: tty to reset
717c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *
718c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	Restore a terminal to the driver default state.
719c65c9bc3efa5589f691276bb9db689119a711222Alan Cox */
720c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
721c65c9bc3efa5589f691276bb9db689119a711222Alan Coxstatic void tty_reset_termios(struct tty_struct *tty)
722c65c9bc3efa5589f691276bb9db689119a711222Alan Cox{
723c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	mutex_lock(&tty->termios_mutex);
724c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	*tty->termios = tty->driver->init_termios;
725c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
726c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
727c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	mutex_unlock(&tty->termios_mutex);
728c65c9bc3efa5589f691276bb9db689119a711222Alan Cox}
729c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
730c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
731c65c9bc3efa5589f691276bb9db689119a711222Alan Cox/**
732c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	tty_ldisc_reinit	-	reinitialise the tty ldisc
733c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	@tty: tty to reinit
734638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox *	@ldisc: line discipline to reinitialize
735c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *
736638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox *	Switch the tty to a line discipline and leave the ldisc
737638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox *	state closed
738c65c9bc3efa5589f691276bb9db689119a711222Alan Cox */
739c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
7401c95ba1e1de7edffc0c4e275e147f1a9eb1f81aePhilippe Rétornazstatic int tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
741c65c9bc3efa5589f691276bb9db689119a711222Alan Cox{
7421c95ba1e1de7edffc0c4e275e147f1a9eb1f81aePhilippe Rétornaz	struct tty_ldisc *ld = tty_ldisc_get(ldisc);
7431c95ba1e1de7edffc0c4e275e147f1a9eb1f81aePhilippe Rétornaz
7441c95ba1e1de7edffc0c4e275e147f1a9eb1f81aePhilippe Rétornaz	if (IS_ERR(ld))
7451c95ba1e1de7edffc0c4e275e147f1a9eb1f81aePhilippe Rétornaz		return -1;
746c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
747c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	tty_ldisc_close(tty, tty->ldisc);
748c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	tty_ldisc_put(tty->ldisc);
749c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	tty->ldisc = NULL;
750c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	/*
751c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 *	Switch the line discipline back
752c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 */
753c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	tty_ldisc_assign(tty, ld);
754638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox	tty_set_termios_ldisc(tty, ldisc);
7551c95ba1e1de7edffc0c4e275e147f1a9eb1f81aePhilippe Rétornaz
7561c95ba1e1de7edffc0c4e275e147f1a9eb1f81aePhilippe Rétornaz	return 0;
757c65c9bc3efa5589f691276bb9db689119a711222Alan Cox}
758c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
759c65c9bc3efa5589f691276bb9db689119a711222Alan Cox/**
760c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	tty_ldisc_hangup		-	hangup ldisc reset
761c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	@tty: tty being hung up
762c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *
763c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	Some tty devices reset their termios when they receive a hangup
764c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	event. In that situation we must also switch back to N_TTY properly
765c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	before we reset the termios data.
766c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *
767c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	Locking: We can take the ldisc mutex as the rest of the code is
768c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	careful to allow for this.
769c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *
770c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	In the pty pair case this occurs in the close() path of the
771c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	tty itself so we must be careful about locking rules.
772c65c9bc3efa5589f691276bb9db689119a711222Alan Cox */
773c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
774c65c9bc3efa5589f691276bb9db689119a711222Alan Coxvoid tty_ldisc_hangup(struct tty_struct *tty)
775c65c9bc3efa5589f691276bb9db689119a711222Alan Cox{
776c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	struct tty_ldisc *ld;
777638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox	int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS;
778638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox	int err = 0;
779c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
780c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	/*
781c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 * FIXME! What are the locking issues here? This may me overdoing
782c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 * things... This question is especially important now that we've
783c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 * removed the irqlock.
784c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 */
785c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	ld = tty_ldisc_ref(tty);
786c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	if (ld != NULL) {
787c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		/* We may have no line discipline at this point */
788c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		if (ld->ops->flush_buffer)
789c65c9bc3efa5589f691276bb9db689119a711222Alan Cox			ld->ops->flush_buffer(tty);
790c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		tty_driver_flush_buffer(tty);
791c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
792c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		    ld->ops->write_wakeup)
793c65c9bc3efa5589f691276bb9db689119a711222Alan Cox			ld->ops->write_wakeup(tty);
794c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		if (ld->ops->hangup)
795c65c9bc3efa5589f691276bb9db689119a711222Alan Cox			ld->ops->hangup(tty);
796c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		tty_ldisc_deref(ld);
797c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	}
798c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	/*
799c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 * FIXME: Once we trust the LDISC code better we can wait here for
800c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 * ldisc completion and fix the driver call race
801c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 */
802c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
803c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	wake_up_interruptible_poll(&tty->read_wait, POLLIN);
804c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	/*
805c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 * Shutdown the current line discipline, and reset it to
806638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox	 * N_TTY if need be.
807638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox	 *
808638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox	 * Avoid racing set_ldisc or tty_ldisc_release
809c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	 */
810638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox	mutex_lock(&tty->ldisc_mutex);
81160af22d2ed490554cc92c8d0fed0b5b9cf687568Arnd Bergmann
81260af22d2ed490554cc92c8d0fed0b5b9cf687568Arnd Bergmann	/*
81360af22d2ed490554cc92c8d0fed0b5b9cf687568Arnd Bergmann	 * this is like tty_ldisc_halt, but we need to give up
814f23eb2b2b28547fc70df82dd5049eb39bec5ba12Linus Torvalds	 * the BTM before calling cancel_work_sync, which may
815f23eb2b2b28547fc70df82dd5049eb39bec5ba12Linus Torvalds	 * need to wait for another function taking the BTM
81660af22d2ed490554cc92c8d0fed0b5b9cf687568Arnd Bergmann	 */
81760af22d2ed490554cc92c8d0fed0b5b9cf687568Arnd Bergmann	clear_bit(TTY_LDISC, &tty->flags);
81860af22d2ed490554cc92c8d0fed0b5b9cf687568Arnd Bergmann	tty_unlock();
819f23eb2b2b28547fc70df82dd5049eb39bec5ba12Linus Torvalds	cancel_work_sync(&tty->buf.work);
82060af22d2ed490554cc92c8d0fed0b5b9cf687568Arnd Bergmann	mutex_unlock(&tty->ldisc_mutex);
8210c73c08ec73dbe080b9ec56696ee21d32754d918Jiri Slabyretry:
82260af22d2ed490554cc92c8d0fed0b5b9cf687568Arnd Bergmann	tty_lock();
82360af22d2ed490554cc92c8d0fed0b5b9cf687568Arnd Bergmann	mutex_lock(&tty->ldisc_mutex);
82460af22d2ed490554cc92c8d0fed0b5b9cf687568Arnd Bergmann
825638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox	/* At this point we have a closed ldisc and we want to
826638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox	   reopen it. We could defer this to the next open but
827638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox	   it means auditing a lot of other paths so this is
828638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox	   a FIXME */
829638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox	if (tty->ldisc) {	/* Not yet closed */
8300c73c08ec73dbe080b9ec56696ee21d32754d918Jiri Slaby		if (atomic_read(&tty->ldisc->users) != 1) {
8310c73c08ec73dbe080b9ec56696ee21d32754d918Jiri Slaby			char cur_n[TASK_COMM_LEN], tty_n[64];
8320c73c08ec73dbe080b9ec56696ee21d32754d918Jiri Slaby			long timeout = 3 * HZ;
8330c73c08ec73dbe080b9ec56696ee21d32754d918Jiri Slaby			tty_unlock();
8340c73c08ec73dbe080b9ec56696ee21d32754d918Jiri Slaby
8350c73c08ec73dbe080b9ec56696ee21d32754d918Jiri Slaby			while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
8360c73c08ec73dbe080b9ec56696ee21d32754d918Jiri Slaby				timeout = MAX_SCHEDULE_TIMEOUT;
8370c73c08ec73dbe080b9ec56696ee21d32754d918Jiri Slaby				printk_ratelimited(KERN_WARNING
8380c73c08ec73dbe080b9ec56696ee21d32754d918Jiri Slaby					"%s: waiting (%s) for %s took too long, but we keep waiting...\n",
8390c73c08ec73dbe080b9ec56696ee21d32754d918Jiri Slaby					__func__, get_task_comm(cur_n, current),
8400c73c08ec73dbe080b9ec56696ee21d32754d918Jiri Slaby					tty_name(tty, tty_n));
8410c73c08ec73dbe080b9ec56696ee21d32754d918Jiri Slaby			}
8420c73c08ec73dbe080b9ec56696ee21d32754d918Jiri Slaby			mutex_unlock(&tty->ldisc_mutex);
8430c73c08ec73dbe080b9ec56696ee21d32754d918Jiri Slaby			goto retry;
8440c73c08ec73dbe080b9ec56696ee21d32754d918Jiri Slaby		}
845300420722e0734a4254f3b634e0f82664495d210Jiri Slaby
846638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox		if (reset == 0) {
8471c95ba1e1de7edffc0c4e275e147f1a9eb1f81aePhilippe Rétornaz
8481c95ba1e1de7edffc0c4e275e147f1a9eb1f81aePhilippe Rétornaz			if (!tty_ldisc_reinit(tty, tty->termios->c_line))
8491c95ba1e1de7edffc0c4e275e147f1a9eb1f81aePhilippe Rétornaz				err = tty_ldisc_open(tty, tty->ldisc);
8501c95ba1e1de7edffc0c4e275e147f1a9eb1f81aePhilippe Rétornaz			else
8511c95ba1e1de7edffc0c4e275e147f1a9eb1f81aePhilippe Rétornaz				err = 1;
852638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox		}
853638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox		/* If the re-open fails or we reset then go to N_TTY. The
854638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox		   N_TTY open cannot fail */
855638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox		if (reset || err) {
8561c95ba1e1de7edffc0c4e275e147f1a9eb1f81aePhilippe Rétornaz			BUG_ON(tty_ldisc_reinit(tty, N_TTY));
857c8d50041734534e0a4b0ea13df36ed5857fccd56Alan Cox			WARN_ON(tty_ldisc_open(tty, tty->ldisc));
858c8d50041734534e0a4b0ea13df36ed5857fccd56Alan Cox		}
859638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox		tty_ldisc_enable(tty);
860c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	}
861638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox	mutex_unlock(&tty->ldisc_mutex);
862638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox	if (reset)
863638b9648ab51c9c549ff5735d3de519ef6199df3Alan Cox		tty_reset_termios(tty);
864c65c9bc3efa5589f691276bb9db689119a711222Alan Cox}
86501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
86601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox/**
86701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	tty_ldisc_setup			-	open line discipline
86801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@tty: tty being shut down
86901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@o_tty: pair tty for pty/tty pairs
87001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
87101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Called during the initial open of a tty/pty pair in order to set up the
872c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	line disciplines and bind them to the tty. This has no locking issues
873c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	as the device isn't yet active.
87401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox */
87501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
87601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxint tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
87701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
878c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	struct tty_ldisc *ld = tty->ldisc;
87901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	int retval;
88001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
881c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	retval = tty_ldisc_open(tty, ld);
882c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	if (retval)
883c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		return retval;
884c65c9bc3efa5589f691276bb9db689119a711222Alan Cox
885c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	if (o_tty) {
886c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		retval = tty_ldisc_open(o_tty, o_tty->ldisc);
88701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox		if (retval) {
888c65c9bc3efa5589f691276bb9db689119a711222Alan Cox			tty_ldisc_close(tty, ld);
88901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox			return retval;
89001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox		}
89101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox		tty_ldisc_enable(o_tty);
89201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	}
89301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	tty_ldisc_enable(tty);
89401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	return 0;
89501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
89601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox/**
89701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	tty_ldisc_release		-	release line discipline
89801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@tty: tty being shut down
89901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@o_tty: pair tty for pty/tty pairs
90001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
901852e99d22f2231d232c45216b027565e3bae7addAlan Cox *	Called during the final close of a tty/pty pair in order to shut down
902852e99d22f2231d232c45216b027565e3bae7addAlan Cox *	the line discpline layer. On exit the ldisc assigned is N_TTY and the
903c65c9bc3efa5589f691276bb9db689119a711222Alan Cox *	ldisc has not been opened.
90401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox */
90501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
90601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxvoid tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
90701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
90801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	/*
90901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	 * Prevent flush_to_ldisc() from rescheduling the work for later.  Then
91001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	 * kill any delayed work. As this is the final close it does not
91101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	 * race with the set_ldisc code path.
91201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	 */
91301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
91460af22d2ed490554cc92c8d0fed0b5b9cf687568Arnd Bergmann	tty_unlock();
915e8b70e7d3e86319a8b2aaabde3866833d92cd80fAlan Cox	tty_ldisc_halt(tty);
9160a1f1a0b626d79071ee9fe91b7fcd28be6332677Tejun Heo	tty_ldisc_flush_works(tty);
91760af22d2ed490554cc92c8d0fed0b5b9cf687568Arnd Bergmann	tty_lock();
91801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
919c8d50041734534e0a4b0ea13df36ed5857fccd56Alan Cox	mutex_lock(&tty->ldisc_mutex);
92001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	/*
921aef29bc2603014cb28dfe39bab8d888546fe18e7Alan Cox	 * Now kill off the ldisc
92201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	 */
923aef29bc2603014cb28dfe39bab8d888546fe18e7Alan Cox	tty_ldisc_close(tty, tty->ldisc);
924aef29bc2603014cb28dfe39bab8d888546fe18e7Alan Cox	tty_ldisc_put(tty->ldisc);
925aef29bc2603014cb28dfe39bab8d888546fe18e7Alan Cox	/* Force an oops if we mess this up */
926aef29bc2603014cb28dfe39bab8d888546fe18e7Alan Cox	tty->ldisc = NULL;
927aef29bc2603014cb28dfe39bab8d888546fe18e7Alan Cox
928aef29bc2603014cb28dfe39bab8d888546fe18e7Alan Cox	/* Ensure the next open requests the N_TTY ldisc */
929aef29bc2603014cb28dfe39bab8d888546fe18e7Alan Cox	tty_set_termios_ldisc(tty, N_TTY);
930c8d50041734534e0a4b0ea13df36ed5857fccd56Alan Cox	mutex_unlock(&tty->ldisc_mutex);
93101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
932c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	/* This will need doing differently if we need to lock */
933c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	if (o_tty)
934c65c9bc3efa5589f691276bb9db689119a711222Alan Cox		tty_ldisc_release(o_tty, NULL);
935aef29bc2603014cb28dfe39bab8d888546fe18e7Alan Cox
936aef29bc2603014cb28dfe39bab8d888546fe18e7Alan Cox	/* And the memory resources remaining (buffers, termios) will be
937aef29bc2603014cb28dfe39bab8d888546fe18e7Alan Cox	   disposed of when the kref hits zero */
93801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
93901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
94001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox/**
94101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	tty_ldisc_init		-	ldisc setup for new tty
94201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	@tty: tty being allocated
94301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *
94401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	Set up the line discipline objects for a newly allocated tty. Note that
94501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox *	the tty structure is not completely set up when this call is made.
94601e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox */
94701e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
94801e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxvoid tty_ldisc_init(struct tty_struct *tty)
94901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
950c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	struct tty_ldisc *ld = tty_ldisc_get(N_TTY);
951c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	if (IS_ERR(ld))
95201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox		panic("n_tty: init_tty");
953c65c9bc3efa5589f691276bb9db689119a711222Alan Cox	tty_ldisc_assign(tty, ld);
95401e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
95501e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox
9566716671d8c1c07a8072098764d1b7cbfef7412adJiri Slaby/**
9576716671d8c1c07a8072098764d1b7cbfef7412adJiri Slaby *	tty_ldisc_init		-	ldisc cleanup for new tty
9586716671d8c1c07a8072098764d1b7cbfef7412adJiri Slaby *	@tty: tty that was allocated recently
9596716671d8c1c07a8072098764d1b7cbfef7412adJiri Slaby *
9606716671d8c1c07a8072098764d1b7cbfef7412adJiri Slaby *	The tty structure must not becompletely set up (tty_ldisc_setup) when
9616716671d8c1c07a8072098764d1b7cbfef7412adJiri Slaby *      this call is made.
9626716671d8c1c07a8072098764d1b7cbfef7412adJiri Slaby */
9636716671d8c1c07a8072098764d1b7cbfef7412adJiri Slabyvoid tty_ldisc_deinit(struct tty_struct *tty)
9646716671d8c1c07a8072098764d1b7cbfef7412adJiri Slaby{
9656716671d8c1c07a8072098764d1b7cbfef7412adJiri Slaby	put_ldisc(tty->ldisc);
9666716671d8c1c07a8072098764d1b7cbfef7412adJiri Slaby	tty_ldisc_assign(tty, NULL);
9676716671d8c1c07a8072098764d1b7cbfef7412adJiri Slaby}
9686716671d8c1c07a8072098764d1b7cbfef7412adJiri Slaby
96901e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Coxvoid tty_ldisc_begin(void)
97001e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox{
97101e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	/* Setup the default TTY line discipline. */
97201e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox	(void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
97301e1abb2c27e43339b8829a2e3b1c6f53806b77aAlan Cox}
974