diff options
| -rw-r--r-- | Documentation/tty.txt | 2 | ||||
| -rw-r--r-- | drivers/char/tty_io.c | 37 | ||||
| -rw-r--r-- | include/linux/tty.h | 1 |
3 files changed, 26 insertions, 14 deletions
diff --git a/Documentation/tty.txt b/Documentation/tty.txt index 3958cf746dde..8ff7bc2a0811 100644 --- a/Documentation/tty.txt +++ b/Documentation/tty.txt | |||
| @@ -22,7 +22,7 @@ copy of the structure. You must not re-register over the top of the line | |||
| 22 | discipline even with the same data or your computer again will be eaten by | 22 | discipline even with the same data or your computer again will be eaten by |
| 23 | demons. | 23 | demons. |
| 24 | 24 | ||
| 25 | In order to remove a line discipline call tty_register_ldisc passing NULL. | 25 | In order to remove a line discipline call tty_unregister_ldisc(). |
| 26 | In ancient times this always worked. In modern times the function will | 26 | In ancient times this always worked. In modern times the function will |
| 27 | return -EBUSY if the ldisc is currently in use. Since the ldisc referencing | 27 | return -EBUSY if the ldisc is currently in use. Since the ldisc referencing |
| 28 | code manages the module counts this should not usually be a concern. | 28 | code manages the module counts this should not usually be a concern. |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 31831030f73f..cc4b43bad703 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
| @@ -251,7 +251,7 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | |||
| 251 | 251 | ||
| 252 | static DEFINE_SPINLOCK(tty_ldisc_lock); | 252 | static DEFINE_SPINLOCK(tty_ldisc_lock); |
| 253 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); | 253 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); |
| 254 | static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */ | 254 | static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */ |
| 255 | 255 | ||
| 256 | int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) | 256 | int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) |
| 257 | { | 257 | { |
| @@ -262,24 +262,35 @@ int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) | |||
| 262 | return -EINVAL; | 262 | return -EINVAL; |
| 263 | 263 | ||
| 264 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 264 | spin_lock_irqsave(&tty_ldisc_lock, flags); |
| 265 | if (new_ldisc) { | 265 | tty_ldiscs[disc] = *new_ldisc; |
| 266 | tty_ldiscs[disc] = *new_ldisc; | 266 | tty_ldiscs[disc].num = disc; |
| 267 | tty_ldiscs[disc].num = disc; | 267 | tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED; |
| 268 | tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED; | 268 | tty_ldiscs[disc].refcount = 0; |
| 269 | tty_ldiscs[disc].refcount = 0; | ||
| 270 | } else { | ||
| 271 | if(tty_ldiscs[disc].refcount) | ||
| 272 | ret = -EBUSY; | ||
| 273 | else | ||
| 274 | tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED; | ||
| 275 | } | ||
| 276 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 269 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
| 277 | 270 | ||
| 278 | return ret; | 271 | return ret; |
| 279 | } | 272 | } |
| 280 | |||
| 281 | EXPORT_SYMBOL(tty_register_ldisc); | 273 | EXPORT_SYMBOL(tty_register_ldisc); |
| 282 | 274 | ||
| 275 | int tty_unregister_ldisc(int disc) | ||
| 276 | { | ||
| 277 | unsigned long flags; | ||
| 278 | int ret = 0; | ||
| 279 | |||
| 280 | if (disc < N_TTY || disc >= NR_LDISCS) | ||
| 281 | return -EINVAL; | ||
| 282 | |||
| 283 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
| 284 | if (tty_ldiscs[disc].refcount) | ||
| 285 | ret = -EBUSY; | ||
| 286 | else | ||
| 287 | tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED; | ||
| 288 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
| 289 | |||
| 290 | return ret; | ||
| 291 | } | ||
| 292 | EXPORT_SYMBOL(tty_unregister_ldisc); | ||
| 293 | |||
| 283 | struct tty_ldisc *tty_ldisc_get(int disc) | 294 | struct tty_ldisc *tty_ldisc_get(int disc) |
| 284 | { | 295 | { |
| 285 | unsigned long flags; | 296 | unsigned long flags; |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 1b76106272d3..59ff42c629ec 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
| @@ -345,6 +345,7 @@ extern int tty_check_change(struct tty_struct * tty); | |||
| 345 | extern void stop_tty(struct tty_struct * tty); | 345 | extern void stop_tty(struct tty_struct * tty); |
| 346 | extern void start_tty(struct tty_struct * tty); | 346 | extern void start_tty(struct tty_struct * tty); |
| 347 | extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc); | 347 | extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc); |
| 348 | extern int tty_unregister_ldisc(int disc); | ||
| 348 | extern int tty_register_driver(struct tty_driver *driver); | 349 | extern int tty_register_driver(struct tty_driver *driver); |
| 349 | extern int tty_unregister_driver(struct tty_driver *driver); | 350 | extern int tty_unregister_driver(struct tty_driver *driver); |
| 350 | extern void tty_register_device(struct tty_driver *driver, unsigned index, struct device *dev); | 351 | extern void tty_register_device(struct tty_driver *driver, unsigned index, struct device *dev); |
