aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/tty.txt2
-rw-r--r--drivers/char/tty_io.c37
-rw-r--r--include/linux/tty.h1
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
22discipline even with the same data or your computer again will be eaten by 22discipline even with the same data or your computer again will be eaten by
23demons. 23demons.
24 24
25In order to remove a line discipline call tty_register_ldisc passing NULL. 25In order to remove a line discipline call tty_unregister_ldisc().
26In ancient times this always worked. In modern times the function will 26In ancient times this always worked. In modern times the function will
27return -EBUSY if the ldisc is currently in use. Since the ldisc referencing 27return -EBUSY if the ldisc is currently in use. Since the ldisc referencing
28code manages the module counts this should not usually be a concern. 28code 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
252static DEFINE_SPINLOCK(tty_ldisc_lock); 252static DEFINE_SPINLOCK(tty_ldisc_lock);
253static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); 253static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
254static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */ 254static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */
255 255
256int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) 256int 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
281EXPORT_SYMBOL(tty_register_ldisc); 273EXPORT_SYMBOL(tty_register_ldisc);
282 274
275int 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}
292EXPORT_SYMBOL(tty_unregister_ldisc);
293
283struct tty_ldisc *tty_ldisc_get(int disc) 294struct 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);
345extern void stop_tty(struct tty_struct * tty); 345extern void stop_tty(struct tty_struct * tty);
346extern void start_tty(struct tty_struct * tty); 346extern void start_tty(struct tty_struct * tty);
347extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc); 347extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc);
348extern int tty_unregister_ldisc(int disc);
348extern int tty_register_driver(struct tty_driver *driver); 349extern int tty_register_driver(struct tty_driver *driver);
349extern int tty_unregister_driver(struct tty_driver *driver); 350extern int tty_unregister_driver(struct tty_driver *driver);
350extern void tty_register_device(struct tty_driver *driver, unsigned index, struct device *dev); 351extern void tty_register_device(struct tty_driver *driver, unsigned index, struct device *dev);