[PATCH] Introduce tty_unregister_ldisc()

It's a bit strange to see tty_register_ldisc call in modules' exit
functions.

Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Alexey Dobriyan 2005-06-23 00:10:32 -07:00 committed by Linus Torvalds
parent 790a19cd57
commit bfb07599da
3 changed files with 26 additions and 14 deletions

View File

@ -22,7 +22,7 @@ copy of the structure. You must not re-register over the top of the line
discipline even with the same data or your computer again will be eaten by discipline even with the same data or your computer again will be eaten by
demons. demons.
In order to remove a line discipline call tty_register_ldisc passing NULL. In order to remove a line discipline call tty_unregister_ldisc().
In ancient times this always worked. In modern times the function will In ancient times this always worked. In modern times the function will
return -EBUSY if the ldisc is currently in use. Since the ldisc referencing return -EBUSY if the ldisc is currently in use. Since the ldisc referencing
code manages the module counts this should not usually be a concern. code manages the module counts this should not usually be a concern.

View File

@ -251,7 +251,7 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
static DEFINE_SPINLOCK(tty_ldisc_lock); static DEFINE_SPINLOCK(tty_ldisc_lock);
static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */ static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */
int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
{ {
@ -262,24 +262,35 @@ int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&tty_ldisc_lock, flags); spin_lock_irqsave(&tty_ldisc_lock, flags);
if (new_ldisc) { tty_ldiscs[disc] = *new_ldisc;
tty_ldiscs[disc] = *new_ldisc; tty_ldiscs[disc].num = disc;
tty_ldiscs[disc].num = disc; tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED; tty_ldiscs[disc].refcount = 0;
tty_ldiscs[disc].refcount = 0;
} else {
if(tty_ldiscs[disc].refcount)
ret = -EBUSY;
else
tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED;
}
spin_unlock_irqrestore(&tty_ldisc_lock, flags); spin_unlock_irqrestore(&tty_ldisc_lock, flags);
return ret; return ret;
} }
EXPORT_SYMBOL(tty_register_ldisc); EXPORT_SYMBOL(tty_register_ldisc);
int tty_unregister_ldisc(int disc)
{
unsigned long flags;
int ret = 0;
if (disc < N_TTY || disc >= NR_LDISCS)
return -EINVAL;
spin_lock_irqsave(&tty_ldisc_lock, flags);
if (tty_ldiscs[disc].refcount)
ret = -EBUSY;
else
tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED;
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
return ret;
}
EXPORT_SYMBOL(tty_unregister_ldisc);
struct tty_ldisc *tty_ldisc_get(int disc) struct tty_ldisc *tty_ldisc_get(int disc)
{ {
unsigned long flags; unsigned long flags;

View File

@ -345,6 +345,7 @@ extern int tty_check_change(struct tty_struct * tty);
extern void stop_tty(struct tty_struct * tty); extern void stop_tty(struct tty_struct * tty);
extern void start_tty(struct tty_struct * tty); extern void start_tty(struct tty_struct * tty);
extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc); extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc);
extern int tty_unregister_ldisc(int disc);
extern int tty_register_driver(struct tty_driver *driver); extern int tty_register_driver(struct tty_driver *driver);
extern int tty_unregister_driver(struct tty_driver *driver); extern int tty_unregister_driver(struct tty_driver *driver);
extern void tty_register_device(struct tty_driver *driver, unsigned index, struct device *dev); extern void tty_register_device(struct tty_driver *driver, unsigned index, struct device *dev);