aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/tty_ldisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/tty_ldisc.c')
-rw-r--r--drivers/tty/tty_ldisc.c47
1 files changed, 26 insertions, 21 deletions
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 0f2a2c5e704c..c5782294e532 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -26,7 +26,7 @@
26 * callers who will do ldisc lookups and cannot sleep. 26 * callers who will do ldisc lookups and cannot sleep.
27 */ 27 */
28 28
29static DEFINE_SPINLOCK(tty_ldisc_lock); 29static DEFINE_RAW_SPINLOCK(tty_ldisc_lock);
30static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); 30static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
31/* Line disc dispatch table */ 31/* Line disc dispatch table */
32static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; 32static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
@@ -49,21 +49,21 @@ static void put_ldisc(struct tty_ldisc *ld)
49 * If this is the last user, free the ldisc, and 49 * If this is the last user, free the ldisc, and
50 * release the ldisc ops. 50 * release the ldisc ops.
51 * 51 *
52 * We really want an "atomic_dec_and_lock_irqsave()", 52 * We really want an "atomic_dec_and_raw_lock_irqsave()",
53 * but we don't have it, so this does it by hand. 53 * but we don't have it, so this does it by hand.
54 */ 54 */
55 local_irq_save(flags); 55 raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
56 if (atomic_dec_and_lock(&ld->users, &tty_ldisc_lock)) { 56 if (atomic_dec_and_test(&ld->users)) {
57 struct tty_ldisc_ops *ldo = ld->ops; 57 struct tty_ldisc_ops *ldo = ld->ops;
58 58
59 ldo->refcount--; 59 ldo->refcount--;
60 module_put(ldo->owner); 60 module_put(ldo->owner);
61 spin_unlock_irqrestore(&tty_ldisc_lock, flags); 61 raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
62 62
63 kfree(ld); 63 kfree(ld);
64 return; 64 return;
65 } 65 }
66 local_irq_restore(flags); 66 raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
67 wake_up(&ld->wq_idle); 67 wake_up(&ld->wq_idle);
68} 68}
69 69
@@ -88,11 +88,11 @@ int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
88 if (disc < N_TTY || disc >= NR_LDISCS) 88 if (disc < N_TTY || disc >= NR_LDISCS)
89 return -EINVAL; 89 return -EINVAL;
90 90
91 spin_lock_irqsave(&tty_ldisc_lock, flags); 91 raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
92 tty_ldiscs[disc] = new_ldisc; 92 tty_ldiscs[disc] = new_ldisc;
93 new_ldisc->num = disc; 93 new_ldisc->num = disc;
94 new_ldisc->refcount = 0; 94 new_ldisc->refcount = 0;
95 spin_unlock_irqrestore(&tty_ldisc_lock, flags); 95 raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
96 96
97 return ret; 97 return ret;
98} 98}
@@ -118,12 +118,12 @@ int tty_unregister_ldisc(int disc)
118 if (disc < N_TTY || disc >= NR_LDISCS) 118 if (disc < N_TTY || disc >= NR_LDISCS)
119 return -EINVAL; 119 return -EINVAL;
120 120
121 spin_lock_irqsave(&tty_ldisc_lock, flags); 121 raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
122 if (tty_ldiscs[disc]->refcount) 122 if (tty_ldiscs[disc]->refcount)
123 ret = -EBUSY; 123 ret = -EBUSY;
124 else 124 else
125 tty_ldiscs[disc] = NULL; 125 tty_ldiscs[disc] = NULL;
126 spin_unlock_irqrestore(&tty_ldisc_lock, flags); 126 raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
127 127
128 return ret; 128 return ret;
129} 129}
@@ -134,7 +134,7 @@ static struct tty_ldisc_ops *get_ldops(int disc)
134 unsigned long flags; 134 unsigned long flags;
135 struct tty_ldisc_ops *ldops, *ret; 135 struct tty_ldisc_ops *ldops, *ret;
136 136
137 spin_lock_irqsave(&tty_ldisc_lock, flags); 137 raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
138 ret = ERR_PTR(-EINVAL); 138 ret = ERR_PTR(-EINVAL);
139 ldops = tty_ldiscs[disc]; 139 ldops = tty_ldiscs[disc];
140 if (ldops) { 140 if (ldops) {
@@ -144,7 +144,7 @@ static struct tty_ldisc_ops *get_ldops(int disc)
144 ret = ldops; 144 ret = ldops;
145 } 145 }
146 } 146 }
147 spin_unlock_irqrestore(&tty_ldisc_lock, flags); 147 raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
148 return ret; 148 return ret;
149} 149}
150 150
@@ -152,10 +152,10 @@ static void put_ldops(struct tty_ldisc_ops *ldops)
152{ 152{
153 unsigned long flags; 153 unsigned long flags;
154 154
155 spin_lock_irqsave(&tty_ldisc_lock, flags); 155 raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
156 ldops->refcount--; 156 ldops->refcount--;
157 module_put(ldops->owner); 157 module_put(ldops->owner);
158 spin_unlock_irqrestore(&tty_ldisc_lock, flags); 158 raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
159} 159}
160 160
161/** 161/**
@@ -287,11 +287,11 @@ static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty)
287 unsigned long flags; 287 unsigned long flags;
288 struct tty_ldisc *ld; 288 struct tty_ldisc *ld;
289 289
290 spin_lock_irqsave(&tty_ldisc_lock, flags); 290 raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
291 ld = NULL; 291 ld = NULL;
292 if (test_bit(TTY_LDISC, &tty->flags)) 292 if (test_bit(TTY_LDISC, &tty->flags))
293 ld = get_ldisc(tty->ldisc); 293 ld = get_ldisc(tty->ldisc);
294 spin_unlock_irqrestore(&tty_ldisc_lock, flags); 294 raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
295 return ld; 295 return ld;
296} 296}
297 297
@@ -512,7 +512,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
512static int tty_ldisc_halt(struct tty_struct *tty) 512static int tty_ldisc_halt(struct tty_struct *tty)
513{ 513{
514 clear_bit(TTY_LDISC, &tty->flags); 514 clear_bit(TTY_LDISC, &tty->flags);
515 return cancel_work_sync(&tty->buf.work); 515 return cancel_work_sync(&tty->port->buf.work);
516} 516}
517 517
518/** 518/**
@@ -525,7 +525,7 @@ static void tty_ldisc_flush_works(struct tty_struct *tty)
525{ 525{
526 flush_work(&tty->hangup_work); 526 flush_work(&tty->hangup_work);
527 flush_work(&tty->SAK_work); 527 flush_work(&tty->SAK_work);
528 flush_work(&tty->buf.work); 528 flush_work(&tty->port->buf.work);
529} 529}
530 530
531/** 531/**
@@ -704,9 +704,9 @@ enable:
704 /* Restart the work queue in case no characters kick it off. Safe if 704 /* Restart the work queue in case no characters kick it off. Safe if
705 already running */ 705 already running */
706 if (work) 706 if (work)
707 schedule_work(&tty->buf.work); 707 schedule_work(&tty->port->buf.work);
708 if (o_work) 708 if (o_work)
709 schedule_work(&o_tty->buf.work); 709 schedule_work(&o_tty->port->buf.work);
710 mutex_unlock(&tty->ldisc_mutex); 710 mutex_unlock(&tty->ldisc_mutex);
711 tty_unlock(tty); 711 tty_unlock(tty);
712 return retval; 712 return retval;
@@ -817,7 +817,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
817 */ 817 */
818 clear_bit(TTY_LDISC, &tty->flags); 818 clear_bit(TTY_LDISC, &tty->flags);
819 tty_unlock(tty); 819 tty_unlock(tty);
820 cancel_work_sync(&tty->buf.work); 820 cancel_work_sync(&tty->port->buf.work);
821 mutex_unlock(&tty->ldisc_mutex); 821 mutex_unlock(&tty->ldisc_mutex);
822retry: 822retry:
823 tty_lock(tty); 823 tty_lock(tty);
@@ -897,6 +897,11 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
897 897
898static void tty_ldisc_kill(struct tty_struct *tty) 898static void tty_ldisc_kill(struct tty_struct *tty)
899{ 899{
900 /* There cannot be users from userspace now. But there still might be
901 * drivers holding a reference via tty_ldisc_ref. Do not steal them the
902 * ldisc until they are done. */
903 tty_ldisc_wait_idle(tty, MAX_SCHEDULE_TIMEOUT);
904
900 mutex_lock(&tty->ldisc_mutex); 905 mutex_lock(&tty->ldisc_mutex);
901 /* 906 /*
902 * Now kill off the ldisc 907 * Now kill off the ldisc