diff options
Diffstat (limited to 'drivers/char/tty_ldisc.c')
-rw-r--r-- | drivers/char/tty_ldisc.c | 556 |
1 files changed, 366 insertions, 190 deletions
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index f78f5b0127a8..a19e935847b0 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c | |||
@@ -115,19 +115,22 @@ EXPORT_SYMBOL(tty_unregister_ldisc); | |||
115 | /** | 115 | /** |
116 | * tty_ldisc_try_get - try and reference an ldisc | 116 | * tty_ldisc_try_get - try and reference an ldisc |
117 | * @disc: ldisc number | 117 | * @disc: ldisc number |
118 | * @ld: tty ldisc structure to complete | ||
119 | * | 118 | * |
120 | * Attempt to open and lock a line discipline into place. Return | 119 | * Attempt to open and lock a line discipline into place. Return |
121 | * the line discipline refcounted and assigned in ld. On an error | 120 | * the line discipline refcounted or an error. |
122 | * report the error code back | ||
123 | */ | 121 | */ |
124 | 122 | ||
125 | static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld) | 123 | static struct tty_ldisc *tty_ldisc_try_get(int disc) |
126 | { | 124 | { |
127 | unsigned long flags; | 125 | unsigned long flags; |
126 | struct tty_ldisc *ld; | ||
128 | struct tty_ldisc_ops *ldops; | 127 | struct tty_ldisc_ops *ldops; |
129 | int err = -EINVAL; | 128 | int err = -EINVAL; |
130 | 129 | ||
130 | ld = kmalloc(sizeof(struct tty_ldisc), GFP_KERNEL); | ||
131 | if (ld == NULL) | ||
132 | return ERR_PTR(-ENOMEM); | ||
133 | |||
131 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 134 | spin_lock_irqsave(&tty_ldisc_lock, flags); |
132 | ld->ops = NULL; | 135 | ld->ops = NULL; |
133 | ldops = tty_ldiscs[disc]; | 136 | ldops = tty_ldiscs[disc]; |
@@ -140,17 +143,21 @@ static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld) | |||
140 | /* lock it */ | 143 | /* lock it */ |
141 | ldops->refcount++; | 144 | ldops->refcount++; |
142 | ld->ops = ldops; | 145 | ld->ops = ldops; |
146 | ld->refcount = 0; | ||
143 | err = 0; | 147 | err = 0; |
144 | } | 148 | } |
145 | } | 149 | } |
146 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 150 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
147 | return err; | 151 | if (err) { |
152 | kfree(ld); | ||
153 | return ERR_PTR(err); | ||
154 | } | ||
155 | return ld; | ||
148 | } | 156 | } |
149 | 157 | ||
150 | /** | 158 | /** |
151 | * tty_ldisc_get - take a reference to an ldisc | 159 | * tty_ldisc_get - take a reference to an ldisc |
152 | * @disc: ldisc number | 160 | * @disc: ldisc number |
153 | * @ld: tty line discipline structure to use | ||
154 | * | 161 | * |
155 | * Takes a reference to a line discipline. Deals with refcounts and | 162 | * Takes a reference to a line discipline. Deals with refcounts and |
156 | * module locking counts. Returns NULL if the discipline is not available. | 163 | * module locking counts. Returns NULL if the discipline is not available. |
@@ -161,52 +168,55 @@ static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld) | |||
161 | * takes tty_ldisc_lock to guard against ldisc races | 168 | * takes tty_ldisc_lock to guard against ldisc races |
162 | */ | 169 | */ |
163 | 170 | ||
164 | static int tty_ldisc_get(int disc, struct tty_ldisc *ld) | 171 | static struct tty_ldisc *tty_ldisc_get(int disc) |
165 | { | 172 | { |
166 | int err; | 173 | struct tty_ldisc *ld; |
167 | 174 | ||
168 | if (disc < N_TTY || disc >= NR_LDISCS) | 175 | if (disc < N_TTY || disc >= NR_LDISCS) |
169 | return -EINVAL; | 176 | return ERR_PTR(-EINVAL); |
170 | err = tty_ldisc_try_get(disc, ld); | 177 | ld = tty_ldisc_try_get(disc); |
171 | if (err < 0) { | 178 | if (IS_ERR(ld)) { |
172 | request_module("tty-ldisc-%d", disc); | 179 | request_module("tty-ldisc-%d", disc); |
173 | err = tty_ldisc_try_get(disc, ld); | 180 | ld = tty_ldisc_try_get(disc); |
174 | } | 181 | } |
175 | return err; | 182 | return ld; |
176 | } | 183 | } |
177 | 184 | ||
178 | /** | 185 | /** |
179 | * tty_ldisc_put - drop ldisc reference | 186 | * tty_ldisc_put - drop ldisc reference |
180 | * @disc: ldisc number | 187 | * @ld: ldisc |
181 | * | 188 | * |
182 | * Drop a reference to a line discipline. Manage refcounts and | 189 | * Drop a reference to a line discipline. Manage refcounts and |
183 | * module usage counts | 190 | * module usage counts. Free the ldisc once the recount hits zero. |
184 | * | 191 | * |
185 | * Locking: | 192 | * Locking: |
186 | * takes tty_ldisc_lock to guard against ldisc races | 193 | * takes tty_ldisc_lock to guard against ldisc races |
187 | */ | 194 | */ |
188 | 195 | ||
189 | static void tty_ldisc_put(struct tty_ldisc_ops *ld) | 196 | static void tty_ldisc_put(struct tty_ldisc *ld) |
190 | { | 197 | { |
191 | unsigned long flags; | 198 | unsigned long flags; |
192 | int disc = ld->num; | 199 | int disc = ld->ops->num; |
200 | struct tty_ldisc_ops *ldo; | ||
193 | 201 | ||
194 | BUG_ON(disc < N_TTY || disc >= NR_LDISCS); | 202 | BUG_ON(disc < N_TTY || disc >= NR_LDISCS); |
195 | 203 | ||
196 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 204 | spin_lock_irqsave(&tty_ldisc_lock, flags); |
197 | ld = tty_ldiscs[disc]; | 205 | ldo = tty_ldiscs[disc]; |
198 | BUG_ON(ld->refcount == 0); | 206 | BUG_ON(ldo->refcount == 0); |
199 | ld->refcount--; | 207 | ldo->refcount--; |
200 | module_put(ld->owner); | 208 | module_put(ldo->owner); |
201 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 209 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
210 | WARN_ON(ld->refcount); | ||
211 | kfree(ld); | ||
202 | } | 212 | } |
203 | 213 | ||
204 | static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) | 214 | static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) |
205 | { | 215 | { |
206 | return (*pos < NR_LDISCS) ? pos : NULL; | 216 | return (*pos < NR_LDISCS) ? pos : NULL; |
207 | } | 217 | } |
208 | 218 | ||
209 | static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos) | 219 | static void *tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos) |
210 | { | 220 | { |
211 | (*pos)++; | 221 | (*pos)++; |
212 | return (*pos < NR_LDISCS) ? pos : NULL; | 222 | return (*pos < NR_LDISCS) ? pos : NULL; |
@@ -219,12 +229,13 @@ static void tty_ldiscs_seq_stop(struct seq_file *m, void *v) | |||
219 | static int tty_ldiscs_seq_show(struct seq_file *m, void *v) | 229 | static int tty_ldiscs_seq_show(struct seq_file *m, void *v) |
220 | { | 230 | { |
221 | int i = *(loff_t *)v; | 231 | int i = *(loff_t *)v; |
222 | struct tty_ldisc ld; | 232 | struct tty_ldisc *ld; |
223 | 233 | ||
224 | if (tty_ldisc_get(i, &ld) < 0) | 234 | ld = tty_ldisc_try_get(i); |
235 | if (IS_ERR(ld)) | ||
225 | return 0; | 236 | return 0; |
226 | seq_printf(m, "%-10s %2d\n", ld.ops->name ? ld.ops->name : "???", i); | 237 | seq_printf(m, "%-10s %2d\n", ld->ops->name ? ld->ops->name : "???", i); |
227 | tty_ldisc_put(ld.ops); | 238 | tty_ldisc_put(ld); |
228 | return 0; | 239 | return 0; |
229 | } | 240 | } |
230 | 241 | ||
@@ -254,7 +265,7 @@ const struct file_operations tty_ldiscs_proc_fops = { | |||
254 | * @ld: line discipline | 265 | * @ld: line discipline |
255 | * | 266 | * |
256 | * Install an instance of a line discipline into a tty structure. The | 267 | * Install an instance of a line discipline into a tty structure. The |
257 | * ldisc must have a reference count above zero to ensure it remains/ | 268 | * ldisc must have a reference count above zero to ensure it remains. |
258 | * The tty instance refcount starts at zero. | 269 | * The tty instance refcount starts at zero. |
259 | * | 270 | * |
260 | * Locking: | 271 | * Locking: |
@@ -263,8 +274,7 @@ const struct file_operations tty_ldiscs_proc_fops = { | |||
263 | 274 | ||
264 | static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) | 275 | static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) |
265 | { | 276 | { |
266 | ld->refcount = 0; | 277 | tty->ldisc = ld; |
267 | tty->ldisc = *ld; | ||
268 | } | 278 | } |
269 | 279 | ||
270 | /** | 280 | /** |
@@ -286,7 +296,7 @@ static int tty_ldisc_try(struct tty_struct *tty) | |||
286 | int ret = 0; | 296 | int ret = 0; |
287 | 297 | ||
288 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 298 | spin_lock_irqsave(&tty_ldisc_lock, flags); |
289 | ld = &tty->ldisc; | 299 | ld = tty->ldisc; |
290 | if (test_bit(TTY_LDISC, &tty->flags)) { | 300 | if (test_bit(TTY_LDISC, &tty->flags)) { |
291 | ld->refcount++; | 301 | ld->refcount++; |
292 | ret = 1; | 302 | ret = 1; |
@@ -315,10 +325,9 @@ struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) | |||
315 | { | 325 | { |
316 | /* wait_event is a macro */ | 326 | /* wait_event is a macro */ |
317 | wait_event(tty_ldisc_wait, tty_ldisc_try(tty)); | 327 | wait_event(tty_ldisc_wait, tty_ldisc_try(tty)); |
318 | WARN_ON(tty->ldisc.refcount == 0); | 328 | WARN_ON(tty->ldisc->refcount == 0); |
319 | return &tty->ldisc; | 329 | return tty->ldisc; |
320 | } | 330 | } |
321 | |||
322 | EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); | 331 | EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); |
323 | 332 | ||
324 | /** | 333 | /** |
@@ -335,10 +344,9 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); | |||
335 | struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) | 344 | struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) |
336 | { | 345 | { |
337 | if (tty_ldisc_try(tty)) | 346 | if (tty_ldisc_try(tty)) |
338 | return &tty->ldisc; | 347 | return tty->ldisc; |
339 | return NULL; | 348 | return NULL; |
340 | } | 349 | } |
341 | |||
342 | EXPORT_SYMBOL_GPL(tty_ldisc_ref); | 350 | EXPORT_SYMBOL_GPL(tty_ldisc_ref); |
343 | 351 | ||
344 | /** | 352 | /** |
@@ -366,7 +374,6 @@ void tty_ldisc_deref(struct tty_ldisc *ld) | |||
366 | wake_up(&tty_ldisc_wait); | 374 | wake_up(&tty_ldisc_wait); |
367 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 375 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
368 | } | 376 | } |
369 | |||
370 | EXPORT_SYMBOL_GPL(tty_ldisc_deref); | 377 | EXPORT_SYMBOL_GPL(tty_ldisc_deref); |
371 | 378 | ||
372 | /** | 379 | /** |
@@ -389,6 +396,26 @@ void tty_ldisc_enable(struct tty_struct *tty) | |||
389 | } | 396 | } |
390 | 397 | ||
391 | /** | 398 | /** |
399 | * tty_ldisc_flush - flush line discipline queue | ||
400 | * @tty: tty | ||
401 | * | ||
402 | * Flush the line discipline queue (if any) for this tty. If there | ||
403 | * is no line discipline active this is a no-op. | ||
404 | */ | ||
405 | |||
406 | void tty_ldisc_flush(struct tty_struct *tty) | ||
407 | { | ||
408 | struct tty_ldisc *ld = tty_ldisc_ref(tty); | ||
409 | if (ld) { | ||
410 | if (ld->ops->flush_buffer) | ||
411 | ld->ops->flush_buffer(tty); | ||
412 | tty_ldisc_deref(ld); | ||
413 | } | ||
414 | tty_buffer_flush(tty); | ||
415 | } | ||
416 | EXPORT_SYMBOL_GPL(tty_ldisc_flush); | ||
417 | |||
418 | /** | ||
392 | * tty_set_termios_ldisc - set ldisc field | 419 | * tty_set_termios_ldisc - set ldisc field |
393 | * @tty: tty structure | 420 | * @tty: tty structure |
394 | * @num: line discipline number | 421 | * @num: line discipline number |
@@ -407,6 +434,39 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | |||
407 | mutex_unlock(&tty->termios_mutex); | 434 | mutex_unlock(&tty->termios_mutex); |
408 | } | 435 | } |
409 | 436 | ||
437 | /** | ||
438 | * tty_ldisc_open - open a line discipline | ||
439 | * @tty: tty we are opening the ldisc on | ||
440 | * @ld: discipline to open | ||
441 | * | ||
442 | * A helper opening method. Also a convenient debugging and check | ||
443 | * point. | ||
444 | */ | ||
445 | |||
446 | static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) | ||
447 | { | ||
448 | WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); | ||
449 | if (ld->ops->open) | ||
450 | return ld->ops->open(tty); | ||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | /** | ||
455 | * tty_ldisc_close - close a line discipline | ||
456 | * @tty: tty we are opening the ldisc on | ||
457 | * @ld: discipline to close | ||
458 | * | ||
459 | * A helper close method. Also a convenient debugging and check | ||
460 | * point. | ||
461 | */ | ||
462 | |||
463 | static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld) | ||
464 | { | ||
465 | WARN_ON(!test_bit(TTY_LDISC_OPEN, &tty->flags)); | ||
466 | clear_bit(TTY_LDISC_OPEN, &tty->flags); | ||
467 | if (ld->ops->close) | ||
468 | ld->ops->close(tty); | ||
469 | } | ||
410 | 470 | ||
411 | /** | 471 | /** |
412 | * tty_ldisc_restore - helper for tty ldisc change | 472 | * tty_ldisc_restore - helper for tty ldisc change |
@@ -420,66 +480,136 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | |||
420 | static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) | 480 | static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) |
421 | { | 481 | { |
422 | char buf[64]; | 482 | char buf[64]; |
423 | struct tty_ldisc new_ldisc; | 483 | struct tty_ldisc *new_ldisc; |
484 | int r; | ||
424 | 485 | ||
425 | /* There is an outstanding reference here so this is safe */ | 486 | /* There is an outstanding reference here so this is safe */ |
426 | tty_ldisc_get(old->ops->num, old); | 487 | old = tty_ldisc_get(old->ops->num); |
488 | WARN_ON(IS_ERR(old)); | ||
427 | tty_ldisc_assign(tty, old); | 489 | tty_ldisc_assign(tty, old); |
428 | tty_set_termios_ldisc(tty, old->ops->num); | 490 | tty_set_termios_ldisc(tty, old->ops->num); |
429 | if (old->ops->open && (old->ops->open(tty) < 0)) { | 491 | if (tty_ldisc_open(tty, old) < 0) { |
430 | tty_ldisc_put(old->ops); | 492 | tty_ldisc_put(old); |
431 | /* This driver is always present */ | 493 | /* This driver is always present */ |
432 | if (tty_ldisc_get(N_TTY, &new_ldisc) < 0) | 494 | new_ldisc = tty_ldisc_get(N_TTY); |
495 | if (IS_ERR(new_ldisc)) | ||
433 | panic("n_tty: get"); | 496 | panic("n_tty: get"); |
434 | tty_ldisc_assign(tty, &new_ldisc); | 497 | tty_ldisc_assign(tty, new_ldisc); |
435 | tty_set_termios_ldisc(tty, N_TTY); | 498 | tty_set_termios_ldisc(tty, N_TTY); |
436 | if (new_ldisc.ops->open) { | 499 | r = tty_ldisc_open(tty, new_ldisc); |
437 | int r = new_ldisc.ops->open(tty); | 500 | if (r < 0) |
438 | if (r < 0) | 501 | panic("Couldn't open N_TTY ldisc for " |
439 | panic("Couldn't open N_TTY ldisc for " | 502 | "%s --- error %d.", |
440 | "%s --- error %d.", | 503 | tty_name(tty, buf), r); |
441 | tty_name(tty, buf), r); | ||
442 | } | ||
443 | } | 504 | } |
444 | } | 505 | } |
445 | 506 | ||
446 | /** | 507 | /** |
508 | * tty_ldisc_halt - shut down the line discipline | ||
509 | * @tty: tty device | ||
510 | * | ||
511 | * Shut down the line discipline and work queue for this tty device. | ||
512 | * The TTY_LDISC flag being cleared ensures no further references can | ||
513 | * be obtained while the delayed work queue halt ensures that no more | ||
514 | * data is fed to the ldisc. | ||
515 | * | ||
516 | * In order to wait for any existing references to complete see | ||
517 | * tty_ldisc_wait_idle. | ||
518 | */ | ||
519 | |||
520 | static int tty_ldisc_halt(struct tty_struct *tty) | ||
521 | { | ||
522 | clear_bit(TTY_LDISC, &tty->flags); | ||
523 | return cancel_delayed_work(&tty->buf.work); | ||
524 | } | ||
525 | |||
526 | /** | ||
527 | * tty_ldisc_wait_idle - wait for the ldisc to become idle | ||
528 | * @tty: tty to wait for | ||
529 | * | ||
530 | * Wait for the line discipline to become idle. The discipline must | ||
531 | * have been halted for this to guarantee it remains idle. | ||
532 | * | ||
533 | * tty_ldisc_lock protects the ref counts currently. | ||
534 | */ | ||
535 | |||
536 | static int tty_ldisc_wait_idle(struct tty_struct *tty) | ||
537 | { | ||
538 | unsigned long flags; | ||
539 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
540 | while (tty->ldisc->refcount) { | ||
541 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
542 | if (wait_event_timeout(tty_ldisc_wait, | ||
543 | tty->ldisc->refcount == 0, 5 * HZ) == 0) | ||
544 | return -EBUSY; | ||
545 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
546 | } | ||
547 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | /** | ||
447 | * tty_set_ldisc - set line discipline | 552 | * tty_set_ldisc - set line discipline |
448 | * @tty: the terminal to set | 553 | * @tty: the terminal to set |
449 | * @ldisc: the line discipline | 554 | * @ldisc: the line discipline |
450 | * | 555 | * |
451 | * Set the discipline of a tty line. Must be called from a process | 556 | * Set the discipline of a tty line. Must be called from a process |
452 | * context. | 557 | * context. The ldisc change logic has to protect itself against any |
558 | * overlapping ldisc change (including on the other end of pty pairs), | ||
559 | * the close of one side of a tty/pty pair, and eventually hangup. | ||
453 | * | 560 | * |
454 | * Locking: takes tty_ldisc_lock. | 561 | * Locking: takes tty_ldisc_lock, termios_mutex |
455 | * called functions take termios_mutex | ||
456 | */ | 562 | */ |
457 | 563 | ||
458 | int tty_set_ldisc(struct tty_struct *tty, int ldisc) | 564 | int tty_set_ldisc(struct tty_struct *tty, int ldisc) |
459 | { | 565 | { |
460 | int retval; | 566 | int retval; |
461 | struct tty_ldisc o_ldisc, new_ldisc; | 567 | struct tty_ldisc *o_ldisc, *new_ldisc; |
462 | int work; | 568 | int work, o_work = 0; |
463 | unsigned long flags; | ||
464 | struct tty_struct *o_tty; | 569 | struct tty_struct *o_tty; |
465 | 570 | ||
466 | restart: | 571 | new_ldisc = tty_ldisc_get(ldisc); |
467 | /* This is a bit ugly for now but means we can break the 'ldisc | 572 | if (IS_ERR(new_ldisc)) |
468 | is part of the tty struct' assumption later */ | 573 | return PTR_ERR(new_ldisc); |
469 | retval = tty_ldisc_get(ldisc, &new_ldisc); | 574 | |
470 | if (retval) | 575 | /* |
471 | return retval; | 576 | * We need to look at the tty locking here for pty/tty pairs |
577 | * when both sides try to change in parallel. | ||
578 | */ | ||
579 | |||
580 | o_tty = tty->link; /* o_tty is the pty side or NULL */ | ||
581 | |||
582 | |||
583 | /* | ||
584 | * Check the no-op case | ||
585 | */ | ||
586 | |||
587 | if (tty->ldisc->ops->num == ldisc) { | ||
588 | tty_ldisc_put(new_ldisc); | ||
589 | return 0; | ||
590 | } | ||
472 | 591 | ||
473 | /* | 592 | /* |
474 | * Problem: What do we do if this blocks ? | 593 | * Problem: What do we do if this blocks ? |
594 | * We could deadlock here | ||
475 | */ | 595 | */ |
476 | 596 | ||
477 | tty_wait_until_sent(tty, 0); | 597 | tty_wait_until_sent(tty, 0); |
478 | 598 | ||
479 | if (tty->ldisc.ops->num == ldisc) { | 599 | mutex_lock(&tty->ldisc_mutex); |
480 | tty_ldisc_put(new_ldisc.ops); | 600 | |
481 | return 0; | 601 | /* |
602 | * We could be midstream of another ldisc change which has | ||
603 | * dropped the lock during processing. If so we need to wait. | ||
604 | */ | ||
605 | |||
606 | while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { | ||
607 | mutex_unlock(&tty->ldisc_mutex); | ||
608 | wait_event(tty_ldisc_wait, | ||
609 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); | ||
610 | mutex_lock(&tty->ldisc_mutex); | ||
482 | } | 611 | } |
612 | set_bit(TTY_LDISC_CHANGING, &tty->flags); | ||
483 | 613 | ||
484 | /* | 614 | /* |
485 | * No more input please, we are switching. The new ldisc | 615 | * No more input please, we are switching. The new ldisc |
@@ -489,8 +619,6 @@ restart: | |||
489 | tty->receive_room = 0; | 619 | tty->receive_room = 0; |
490 | 620 | ||
491 | o_ldisc = tty->ldisc; | 621 | o_ldisc = tty->ldisc; |
492 | o_tty = tty->link; | ||
493 | |||
494 | /* | 622 | /* |
495 | * Make sure we don't change while someone holds a | 623 | * Make sure we don't change while someone holds a |
496 | * reference to the line discipline. The TTY_LDISC bit | 624 | * reference to the line discipline. The TTY_LDISC bit |
@@ -501,108 +629,183 @@ restart: | |||
501 | * with a userspace app continually trying to use the tty in | 629 | * with a userspace app continually trying to use the tty in |
502 | * parallel to the change and re-referencing the tty. | 630 | * parallel to the change and re-referencing the tty. |
503 | */ | 631 | */ |
504 | clear_bit(TTY_LDISC, &tty->flags); | ||
505 | if (o_tty) | ||
506 | clear_bit(TTY_LDISC, &o_tty->flags); | ||
507 | 632 | ||
508 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 633 | work = tty_ldisc_halt(tty); |
509 | if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) { | ||
510 | if (tty->ldisc.refcount) { | ||
511 | /* Free the new ldisc we grabbed. Must drop the lock | ||
512 | first. */ | ||
513 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
514 | tty_ldisc_put(o_ldisc.ops); | ||
515 | /* | ||
516 | * There are several reasons we may be busy, including | ||
517 | * random momentary I/O traffic. We must therefore | ||
518 | * retry. We could distinguish between blocking ops | ||
519 | * and retries if we made tty_ldisc_wait() smarter. | ||
520 | * That is up for discussion. | ||
521 | */ | ||
522 | if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0) | ||
523 | return -ERESTARTSYS; | ||
524 | goto restart; | ||
525 | } | ||
526 | if (o_tty && o_tty->ldisc.refcount) { | ||
527 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
528 | tty_ldisc_put(o_tty->ldisc.ops); | ||
529 | if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0) | ||
530 | return -ERESTARTSYS; | ||
531 | goto restart; | ||
532 | } | ||
533 | } | ||
534 | /* | ||
535 | * If the TTY_LDISC bit is set, then we are racing against | ||
536 | * another ldisc change | ||
537 | */ | ||
538 | if (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { | ||
539 | struct tty_ldisc *ld; | ||
540 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
541 | tty_ldisc_put(new_ldisc.ops); | ||
542 | ld = tty_ldisc_ref_wait(tty); | ||
543 | tty_ldisc_deref(ld); | ||
544 | goto restart; | ||
545 | } | ||
546 | /* | ||
547 | * This flag is used to avoid two parallel ldisc changes. Once | ||
548 | * open and close are fine grained locked this may work better | ||
549 | * as a mutex shared with the open/close/hup paths | ||
550 | */ | ||
551 | set_bit(TTY_LDISC_CHANGING, &tty->flags); | ||
552 | if (o_tty) | 634 | if (o_tty) |
553 | set_bit(TTY_LDISC_CHANGING, &o_tty->flags); | 635 | o_work = tty_ldisc_halt(o_tty); |
554 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
555 | |||
556 | /* | ||
557 | * From this point on we know nobody has an ldisc | ||
558 | * usage reference, nor can they obtain one until | ||
559 | * we say so later on. | ||
560 | */ | ||
561 | 636 | ||
562 | work = cancel_delayed_work(&tty->buf.work); | ||
563 | /* | 637 | /* |
564 | * Wait for ->hangup_work and ->buf.work handlers to terminate | 638 | * Wait for ->hangup_work and ->buf.work handlers to terminate. |
565 | * MUST NOT hold locks here. | 639 | * We must drop the mutex here in case a hangup is also in process. |
566 | */ | 640 | */ |
641 | |||
642 | mutex_unlock(&tty->ldisc_mutex); | ||
643 | |||
567 | flush_scheduled_work(); | 644 | flush_scheduled_work(); |
645 | |||
646 | /* Let any existing reference holders finish */ | ||
647 | retval = tty_ldisc_wait_idle(tty); | ||
648 | if (retval < 0) { | ||
649 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | ||
650 | tty_ldisc_put(new_ldisc); | ||
651 | return retval; | ||
652 | } | ||
653 | |||
654 | mutex_lock(&tty->ldisc_mutex); | ||
655 | if (test_bit(TTY_HUPPED, &tty->flags)) { | ||
656 | /* We were raced by the hangup method. It will have stomped | ||
657 | the ldisc data and closed the ldisc down */ | ||
658 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | ||
659 | mutex_unlock(&tty->ldisc_mutex); | ||
660 | tty_ldisc_put(new_ldisc); | ||
661 | return -EIO; | ||
662 | } | ||
663 | |||
568 | /* Shutdown the current discipline. */ | 664 | /* Shutdown the current discipline. */ |
569 | if (o_ldisc.ops->close) | 665 | tty_ldisc_close(tty, o_ldisc); |
570 | (o_ldisc.ops->close)(tty); | ||
571 | 666 | ||
572 | /* Now set up the new line discipline. */ | 667 | /* Now set up the new line discipline. */ |
573 | tty_ldisc_assign(tty, &new_ldisc); | 668 | tty_ldisc_assign(tty, new_ldisc); |
574 | tty_set_termios_ldisc(tty, ldisc); | 669 | tty_set_termios_ldisc(tty, ldisc); |
575 | if (new_ldisc.ops->open) | 670 | |
576 | retval = (new_ldisc.ops->open)(tty); | 671 | retval = tty_ldisc_open(tty, new_ldisc); |
577 | if (retval < 0) { | 672 | if (retval < 0) { |
578 | tty_ldisc_put(new_ldisc.ops); | 673 | /* Back to the old one or N_TTY if we can't */ |
579 | tty_ldisc_restore(tty, &o_ldisc); | 674 | tty_ldisc_put(new_ldisc); |
675 | tty_ldisc_restore(tty, o_ldisc); | ||
580 | } | 676 | } |
677 | |||
581 | /* At this point we hold a reference to the new ldisc and a | 678 | /* At this point we hold a reference to the new ldisc and a |
582 | a reference to the old ldisc. If we ended up flipping back | 679 | a reference to the old ldisc. If we ended up flipping back |
583 | to the existing ldisc we have two references to it */ | 680 | to the existing ldisc we have two references to it */ |
584 | 681 | ||
585 | if (tty->ldisc.ops->num != o_ldisc.ops->num && tty->ops->set_ldisc) | 682 | if (tty->ldisc->ops->num != o_ldisc->ops->num && tty->ops->set_ldisc) |
586 | tty->ops->set_ldisc(tty); | 683 | tty->ops->set_ldisc(tty); |
587 | 684 | ||
588 | tty_ldisc_put(o_ldisc.ops); | 685 | tty_ldisc_put(o_ldisc); |
589 | 686 | ||
590 | /* | 687 | /* |
591 | * Allow ldisc referencing to occur as soon as the driver | 688 | * Allow ldisc referencing to occur again |
592 | * ldisc callback completes. | ||
593 | */ | 689 | */ |
594 | 690 | ||
595 | tty_ldisc_enable(tty); | 691 | tty_ldisc_enable(tty); |
596 | if (o_tty) | 692 | if (o_tty) |
597 | tty_ldisc_enable(o_tty); | 693 | tty_ldisc_enable(o_tty); |
598 | 694 | ||
599 | /* Restart it in case no characters kick it off. Safe if | 695 | /* Restart the work queue in case no characters kick it off. Safe if |
600 | already running */ | 696 | already running */ |
601 | if (work) | 697 | if (work) |
602 | schedule_delayed_work(&tty->buf.work, 1); | 698 | schedule_delayed_work(&tty->buf.work, 1); |
699 | if (o_work) | ||
700 | schedule_delayed_work(&o_tty->buf.work, 1); | ||
701 | mutex_unlock(&tty->ldisc_mutex); | ||
603 | return retval; | 702 | return retval; |
604 | } | 703 | } |
605 | 704 | ||
705 | /** | ||
706 | * tty_reset_termios - reset terminal state | ||
707 | * @tty: tty to reset | ||
708 | * | ||
709 | * Restore a terminal to the driver default state. | ||
710 | */ | ||
711 | |||
712 | static void tty_reset_termios(struct tty_struct *tty) | ||
713 | { | ||
714 | mutex_lock(&tty->termios_mutex); | ||
715 | *tty->termios = tty->driver->init_termios; | ||
716 | tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); | ||
717 | tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); | ||
718 | mutex_unlock(&tty->termios_mutex); | ||
719 | } | ||
720 | |||
721 | |||
722 | /** | ||
723 | * tty_ldisc_reinit - reinitialise the tty ldisc | ||
724 | * @tty: tty to reinit | ||
725 | * | ||
726 | * Switch the tty back to N_TTY line discipline and leave the | ||
727 | * ldisc state closed | ||
728 | */ | ||
729 | |||
730 | static void tty_ldisc_reinit(struct tty_struct *tty) | ||
731 | { | ||
732 | struct tty_ldisc *ld; | ||
733 | |||
734 | tty_ldisc_close(tty, tty->ldisc); | ||
735 | tty_ldisc_put(tty->ldisc); | ||
736 | tty->ldisc = NULL; | ||
737 | /* | ||
738 | * Switch the line discipline back | ||
739 | */ | ||
740 | ld = tty_ldisc_get(N_TTY); | ||
741 | BUG_ON(IS_ERR(ld)); | ||
742 | tty_ldisc_assign(tty, ld); | ||
743 | tty_set_termios_ldisc(tty, N_TTY); | ||
744 | } | ||
745 | |||
746 | /** | ||
747 | * tty_ldisc_hangup - hangup ldisc reset | ||
748 | * @tty: tty being hung up | ||
749 | * | ||
750 | * Some tty devices reset their termios when they receive a hangup | ||
751 | * event. In that situation we must also switch back to N_TTY properly | ||
752 | * before we reset the termios data. | ||
753 | * | ||
754 | * Locking: We can take the ldisc mutex as the rest of the code is | ||
755 | * careful to allow for this. | ||
756 | * | ||
757 | * In the pty pair case this occurs in the close() path of the | ||
758 | * tty itself so we must be careful about locking rules. | ||
759 | */ | ||
760 | |||
761 | void tty_ldisc_hangup(struct tty_struct *tty) | ||
762 | { | ||
763 | struct tty_ldisc *ld; | ||
764 | |||
765 | /* | ||
766 | * FIXME! What are the locking issues here? This may me overdoing | ||
767 | * things... This question is especially important now that we've | ||
768 | * removed the irqlock. | ||
769 | */ | ||
770 | ld = tty_ldisc_ref(tty); | ||
771 | if (ld != NULL) { | ||
772 | /* We may have no line discipline at this point */ | ||
773 | if (ld->ops->flush_buffer) | ||
774 | ld->ops->flush_buffer(tty); | ||
775 | tty_driver_flush_buffer(tty); | ||
776 | if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) && | ||
777 | ld->ops->write_wakeup) | ||
778 | ld->ops->write_wakeup(tty); | ||
779 | if (ld->ops->hangup) | ||
780 | ld->ops->hangup(tty); | ||
781 | tty_ldisc_deref(ld); | ||
782 | } | ||
783 | /* | ||
784 | * FIXME: Once we trust the LDISC code better we can wait here for | ||
785 | * ldisc completion and fix the driver call race | ||
786 | */ | ||
787 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); | ||
788 | wake_up_interruptible_poll(&tty->read_wait, POLLIN); | ||
789 | /* | ||
790 | * Shutdown the current line discipline, and reset it to | ||
791 | * N_TTY. | ||
792 | */ | ||
793 | if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { | ||
794 | /* Avoid racing set_ldisc */ | ||
795 | mutex_lock(&tty->ldisc_mutex); | ||
796 | /* Switch back to N_TTY */ | ||
797 | tty_ldisc_halt(tty); | ||
798 | tty_ldisc_wait_idle(tty); | ||
799 | tty_ldisc_reinit(tty); | ||
800 | /* At this point we have a closed ldisc and we want to | ||
801 | reopen it. We could defer this to the next open but | ||
802 | it means auditing a lot of other paths so this is a FIXME */ | ||
803 | WARN_ON(tty_ldisc_open(tty, tty->ldisc)); | ||
804 | tty_ldisc_enable(tty); | ||
805 | mutex_unlock(&tty->ldisc_mutex); | ||
806 | tty_reset_termios(tty); | ||
807 | } | ||
808 | } | ||
606 | 809 | ||
607 | /** | 810 | /** |
608 | * tty_ldisc_setup - open line discipline | 811 | * tty_ldisc_setup - open line discipline |
@@ -610,24 +813,23 @@ restart: | |||
610 | * @o_tty: pair tty for pty/tty pairs | 813 | * @o_tty: pair tty for pty/tty pairs |
611 | * | 814 | * |
612 | * Called during the initial open of a tty/pty pair in order to set up the | 815 | * Called during the initial open of a tty/pty pair in order to set up the |
613 | * line discplines and bind them to the tty. | 816 | * line disciplines and bind them to the tty. This has no locking issues |
817 | * as the device isn't yet active. | ||
614 | */ | 818 | */ |
615 | 819 | ||
616 | int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) | 820 | int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) |
617 | { | 821 | { |
618 | struct tty_ldisc *ld = &tty->ldisc; | 822 | struct tty_ldisc *ld = tty->ldisc; |
619 | int retval; | 823 | int retval; |
620 | 824 | ||
621 | if (ld->ops->open) { | 825 | retval = tty_ldisc_open(tty, ld); |
622 | retval = (ld->ops->open)(tty); | 826 | if (retval) |
623 | if (retval) | 827 | return retval; |
624 | return retval; | 828 | |
625 | } | 829 | if (o_tty) { |
626 | if (o_tty && o_tty->ldisc.ops->open) { | 830 | retval = tty_ldisc_open(o_tty, o_tty->ldisc); |
627 | retval = (o_tty->ldisc.ops->open)(o_tty); | ||
628 | if (retval) { | 831 | if (retval) { |
629 | if (ld->ops->close) | 832 | tty_ldisc_close(tty, ld); |
630 | (ld->ops->close)(tty); | ||
631 | return retval; | 833 | return retval; |
632 | } | 834 | } |
633 | tty_ldisc_enable(o_tty); | 835 | tty_ldisc_enable(o_tty); |
@@ -635,32 +837,25 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) | |||
635 | tty_ldisc_enable(tty); | 837 | tty_ldisc_enable(tty); |
636 | return 0; | 838 | return 0; |
637 | } | 839 | } |
638 | |||
639 | /** | 840 | /** |
640 | * tty_ldisc_release - release line discipline | 841 | * tty_ldisc_release - release line discipline |
641 | * @tty: tty being shut down | 842 | * @tty: tty being shut down |
642 | * @o_tty: pair tty for pty/tty pairs | 843 | * @o_tty: pair tty for pty/tty pairs |
643 | * | 844 | * |
644 | * Called during the final close of a tty/pty pair in order to shut down the | 845 | * Called during the final close of a tty/pty pair in order to shut down |
645 | * line discpline layer. | 846 | * the line discpline layer. On exit the ldisc assigned is N_TTY and the |
847 | * ldisc has not been opened. | ||
646 | */ | 848 | */ |
647 | 849 | ||
648 | void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | 850 | void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) |
649 | { | 851 | { |
650 | unsigned long flags; | ||
651 | struct tty_ldisc ld; | ||
652 | /* | 852 | /* |
653 | * Prevent flush_to_ldisc() from rescheduling the work for later. Then | 853 | * Prevent flush_to_ldisc() from rescheduling the work for later. Then |
654 | * kill any delayed work. As this is the final close it does not | 854 | * kill any delayed work. As this is the final close it does not |
655 | * race with the set_ldisc code path. | 855 | * race with the set_ldisc code path. |
656 | */ | 856 | */ |
657 | clear_bit(TTY_LDISC, &tty->flags); | ||
658 | cancel_delayed_work(&tty->buf.work); | ||
659 | |||
660 | /* | ||
661 | * Wait for ->hangup_work and ->buf.work handlers to terminate | ||
662 | */ | ||
663 | 857 | ||
858 | tty_ldisc_halt(tty); | ||
664 | flush_scheduled_work(); | 859 | flush_scheduled_work(); |
665 | 860 | ||
666 | /* | 861 | /* |
@@ -668,38 +863,19 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | |||
668 | * side waiters as the file is closing so user count on the file | 863 | * side waiters as the file is closing so user count on the file |
669 | * side is zero. | 864 | * side is zero. |
670 | */ | 865 | */ |
671 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 866 | |
672 | while (tty->ldisc.refcount) { | 867 | tty_ldisc_wait_idle(tty); |
673 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 868 | |
674 | wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0); | ||
675 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
676 | } | ||
677 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
678 | /* | 869 | /* |
679 | * Shutdown the current line discipline, and reset it to N_TTY. | 870 | * Shutdown the current line discipline, and reset it to N_TTY. |
680 | * | 871 | * |
681 | * FIXME: this MUST get fixed for the new reflocking | 872 | * FIXME: this MUST get fixed for the new reflocking |
682 | */ | 873 | */ |
683 | if (tty->ldisc.ops->close) | ||
684 | (tty->ldisc.ops->close)(tty); | ||
685 | tty_ldisc_put(tty->ldisc.ops); | ||
686 | 874 | ||
687 | /* | 875 | tty_ldisc_reinit(tty); |
688 | * Switch the line discipline back | 876 | /* This will need doing differently if we need to lock */ |
689 | */ | 877 | if (o_tty) |
690 | WARN_ON(tty_ldisc_get(N_TTY, &ld)); | 878 | tty_ldisc_release(o_tty, NULL); |
691 | tty_ldisc_assign(tty, &ld); | ||
692 | tty_set_termios_ldisc(tty, N_TTY); | ||
693 | if (o_tty) { | ||
694 | /* FIXME: could o_tty be in setldisc here ? */ | ||
695 | clear_bit(TTY_LDISC, &o_tty->flags); | ||
696 | if (o_tty->ldisc.ops->close) | ||
697 | (o_tty->ldisc.ops->close)(o_tty); | ||
698 | tty_ldisc_put(o_tty->ldisc.ops); | ||
699 | WARN_ON(tty_ldisc_get(N_TTY, &ld)); | ||
700 | tty_ldisc_assign(o_tty, &ld); | ||
701 | tty_set_termios_ldisc(o_tty, N_TTY); | ||
702 | } | ||
703 | } | 879 | } |
704 | 880 | ||
705 | /** | 881 | /** |
@@ -712,10 +888,10 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | |||
712 | 888 | ||
713 | void tty_ldisc_init(struct tty_struct *tty) | 889 | void tty_ldisc_init(struct tty_struct *tty) |
714 | { | 890 | { |
715 | struct tty_ldisc ld; | 891 | struct tty_ldisc *ld = tty_ldisc_get(N_TTY); |
716 | if (tty_ldisc_get(N_TTY, &ld) < 0) | 892 | if (IS_ERR(ld)) |
717 | panic("n_tty: init_tty"); | 893 | panic("n_tty: init_tty"); |
718 | tty_ldisc_assign(tty, &ld); | 894 | tty_ldisc_assign(tty, ld); |
719 | } | 895 | } |
720 | 896 | ||
721 | void tty_ldisc_begin(void) | 897 | void tty_ldisc_begin(void) |