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); |