Commit bfb07599 authored by Alexey Dobriyan's avatar Alexey Dobriyan Committed by Linus Torvalds

[PATCH] Introduce tty_unregister_ldisc()

It's a bit strange to see tty_register_ldisc call in modules' exit
functions.
Signed-off-by: default avatarAlexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 790a19cd
...@@ -22,7 +22,7 @@ copy of the structure. You must not re-register over the top of the line ...@@ -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.
......
...@@ -251,7 +251,7 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) ...@@ -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) ...@@ -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;
......
...@@ -345,6 +345,7 @@ extern int tty_check_change(struct tty_struct * tty); ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment