Patch from Max Krasnyansky <maxk@qualcomm.com>

This changeset adds module refcounting for TTY line disciplines.  I've sent
the patch to LKM earlier.  No negative comments (actually most people didn't
seem to care).  This is needed at least for Bluetooth and IrDA (Jean is ok
with the patch).


 char/tty_io.c     |   16 ++++++++++++++++
 linux/tty_ldisc.h |    3 +++
 2 files changed, 19 insertions(+)

diff -puN drivers/char/tty_io.c~tty-module-refcounting drivers/char/tty_io.c
--- 25/drivers/char/tty_io.c~tty-module-refcounting	2003-02-14 19:09:27.000000000 -0800
+++ 25-akpm/drivers/char/tty_io.c	2003-02-14 19:09:27.000000000 -0800
@@ -289,6 +289,10 @@ static int tty_set_ldisc(struct tty_stru
 
 	if (tty->ldisc.num == ldisc)
 		return 0;	/* We are already in the desired discipline */
+
+	if (!try_module_get(ldiscs[ldisc].owner))
+	       	return -EINVAL;
+	
 	o_ldisc = tty->ldisc;
 
 	tty_wait_until_sent(tty, 0);
@@ -303,9 +307,13 @@ static int tty_set_ldisc(struct tty_stru
 	if (tty->ldisc.open)
 		retval = (tty->ldisc.open)(tty);
 	if (retval < 0) {
+		module_put(tty->ldisc.owner);
+		
 		tty->ldisc = o_ldisc;
 		tty->termios->c_line = tty->ldisc.num;
 		if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) {
+			module_put(tty->ldisc.owner);
+
 			tty->ldisc = ldiscs[N_TTY];
 			tty->termios->c_line = N_TTY;
 			if (tty->ldisc.open) {
@@ -317,7 +325,10 @@ static int tty_set_ldisc(struct tty_stru
 					      tty_name(tty, buf), r);
 			}
 		}
+	} else {
+		module_put(o_ldisc.owner);
 	}
+	
 	if (tty->ldisc.num != o_ldisc.num && tty->driver.set_ldisc)
 		tty->driver.set_ldisc(tty);
 	return retval;
@@ -493,6 +504,8 @@ void do_tty_hangup(void *data)
 	if (tty->ldisc.num != ldiscs[N_TTY].num) {
 		if (tty->ldisc.close)
 			(tty->ldisc.close)(tty);
+		module_put(tty->ldisc.owner);
+		
 		tty->ldisc = ldiscs[N_TTY];
 		tty->termios->c_line = N_TTY;
 		if (tty->ldisc.open) {
@@ -1271,11 +1284,14 @@ static void release_dev(struct file * fi
 	 */
 	if (tty->ldisc.close)
 		(tty->ldisc.close)(tty);
+	module_put(tty->ldisc.owner);
+	
 	tty->ldisc = ldiscs[N_TTY];
 	tty->termios->c_line = N_TTY;
 	if (o_tty) {
 		if (o_tty->ldisc.close)
 			(o_tty->ldisc.close)(o_tty);
+		module_put(o_tty->ldisc.owner);
 		o_tty->ldisc = ldiscs[N_TTY];
 	}
 	
diff -puN include/linux/tty_ldisc.h~tty-module-refcounting include/linux/tty_ldisc.h
--- 25/include/linux/tty_ldisc.h~tty-module-refcounting	2003-02-14 19:09:27.000000000 -0800
+++ 25-akpm/include/linux/tty_ldisc.h	2003-02-14 19:09:27.000000000 -0800
@@ -105,6 +105,7 @@ struct tty_ldisc {
 	char	*name;
 	int	num;
 	int	flags;
+	
 	/*
 	 * The following routines are called from above.
 	 */
@@ -129,6 +130,8 @@ struct tty_ldisc {
 			       char *fp, int count);
 	int	(*receive_room)(struct tty_struct *);
 	void	(*write_wakeup)(struct tty_struct *);
+
+	struct  module *owner;
 };
 
 #define TTY_LDISC_MAGIC	0x5403

_