aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/tty_ldisc.c
diff options
context:
space:
mode:
authorIvo Sieben <meltedpianoman@gmail.com>2012-10-17 08:03:14 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-10-24 14:37:02 -0400
commitc97399418a25b18943c9910fb28e0ee5ecc3c316 (patch)
tree0c4d711eae09998e4b4fe4b7efe6036d0cdf896c /drivers/tty/tty_ldisc.c
parentad3d1e5fc94e1d617298cf9b8fb522e2d219521a (diff)
tty: Use raw spin lock to protect TTY ldisc administration
The global "normal" spin lock that guards the line discipline administration is replaced by a raw spin lock. On a PREEMPT_RT system this prevents unwanted scheduling overhead around the line discipline administration. On a 200 MHz AT91SAM9261 processor setup this fixes about 100us of scheduling overhead on a TTY read or write call. Signed-off-by: Ivo Sieben <meltedpianoman@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/tty_ldisc.c')
-rw-r--r--drivers/tty/tty_ldisc.c32
1 files changed, 16 insertions, 16 deletions
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index f4e6754525dc..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