aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/pty.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/pty.c')
-rw-r--r--drivers/tty/pty.c234
1 files changed, 122 insertions, 112 deletions
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 5505ffc91da4..a82b39939a9c 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -47,6 +47,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
47 wake_up_interruptible(&tty->read_wait); 47 wake_up_interruptible(&tty->read_wait);
48 wake_up_interruptible(&tty->write_wait); 48 wake_up_interruptible(&tty->write_wait);
49 tty->packet = 0; 49 tty->packet = 0;
50 /* Review - krefs on tty_link ?? */
50 if (!tty->link) 51 if (!tty->link)
51 return; 52 return;
52 tty->link->packet = 0; 53 tty->link->packet = 0;
@@ -62,9 +63,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
62 mutex_unlock(&devpts_mutex); 63 mutex_unlock(&devpts_mutex);
63 } 64 }
64#endif 65#endif
65 tty_unlock(); 66 tty_unlock(tty);
66 tty_vhangup(tty->link); 67 tty_vhangup(tty->link);
67 tty_lock(); 68 tty_lock(tty);
68 } 69 }
69} 70}
70 71
@@ -231,8 +232,8 @@ out:
231static void pty_set_termios(struct tty_struct *tty, 232static void pty_set_termios(struct tty_struct *tty,
232 struct ktermios *old_termios) 233 struct ktermios *old_termios)
233{ 234{
234 tty->termios->c_cflag &= ~(CSIZE | PARENB); 235 tty->termios.c_cflag &= ~(CSIZE | PARENB);
235 tty->termios->c_cflag |= (CS8 | CREAD); 236 tty->termios.c_cflag |= (CS8 | CREAD);
236} 237}
237 238
238/** 239/**
@@ -282,60 +283,110 @@ done:
282 return 0; 283 return 0;
283} 284}
284 285
285/* Traditional BSD devices */ 286/**
286#ifdef CONFIG_LEGACY_PTYS 287 * pty_common_install - set up the pty pair
287 288 * @driver: the pty driver
288static int pty_install(struct tty_driver *driver, struct tty_struct *tty) 289 * @tty: the tty being instantiated
290 * @bool: legacy, true if this is BSD style
291 *
292 * Perform the initial set up for the tty/pty pair. Called from the
293 * tty layer when the port is first opened.
294 *
295 * Locking: the caller must hold the tty_mutex
296 */
297static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
298 bool legacy)
289{ 299{
290 struct tty_struct *o_tty; 300 struct tty_struct *o_tty;
301 struct tty_port *ports[2];
291 int idx = tty->index; 302 int idx = tty->index;
292 int retval; 303 int retval = -ENOMEM;
293 304
294 o_tty = alloc_tty_struct(); 305 o_tty = alloc_tty_struct();
295 if (!o_tty) 306 if (!o_tty)
296 return -ENOMEM; 307 goto err;
308 ports[0] = kmalloc(sizeof **ports, GFP_KERNEL);
309 ports[1] = kmalloc(sizeof **ports, GFP_KERNEL);
310 if (!ports[0] || !ports[1])
311 goto err_free_tty;
297 if (!try_module_get(driver->other->owner)) { 312 if (!try_module_get(driver->other->owner)) {
298 /* This cannot in fact currently happen */ 313 /* This cannot in fact currently happen */
299 retval = -ENOMEM;
300 goto err_free_tty; 314 goto err_free_tty;
301 } 315 }
302 initialize_tty_struct(o_tty, driver->other, idx); 316 initialize_tty_struct(o_tty, driver->other, idx);
303 317
304 /* We always use new tty termios data so we can do this 318 if (legacy) {
305 the easy way .. */ 319 /* We always use new tty termios data so we can do this
306 retval = tty_init_termios(tty); 320 the easy way .. */
307 if (retval) 321 retval = tty_init_termios(tty);
308 goto err_deinit_tty; 322 if (retval)
309 323 goto err_deinit_tty;
310 retval = tty_init_termios(o_tty); 324
311 if (retval) 325 retval = tty_init_termios(o_tty);
312 goto err_free_termios; 326 if (retval)
327 goto err_free_termios;
328
329 driver->other->ttys[idx] = o_tty;
330 driver->ttys[idx] = tty;
331 } else {
332 memset(&tty->termios_locked, 0, sizeof(tty->termios_locked));
333 tty->termios = driver->init_termios;
334 memset(&o_tty->termios_locked, 0, sizeof(tty->termios_locked));
335 o_tty->termios = driver->other->init_termios;
336 }
313 337
314 /* 338 /*
315 * Everything allocated ... set up the o_tty structure. 339 * Everything allocated ... set up the o_tty structure.
316 */ 340 */
317 driver->other->ttys[idx] = o_tty;
318 tty_driver_kref_get(driver->other); 341 tty_driver_kref_get(driver->other);
319 if (driver->subtype == PTY_TYPE_MASTER) 342 if (driver->subtype == PTY_TYPE_MASTER)
320 o_tty->count++; 343 o_tty->count++;
321 /* Establish the links in both directions */ 344 /* Establish the links in both directions */
322 tty->link = o_tty; 345 tty->link = o_tty;
323 o_tty->link = tty; 346 o_tty->link = tty;
347 tty_port_init(ports[0]);
348 tty_port_init(ports[1]);
349 o_tty->port = ports[0];
350 tty->port = ports[1];
324 351
325 tty_driver_kref_get(driver); 352 tty_driver_kref_get(driver);
326 tty->count++; 353 tty->count++;
327 driver->ttys[idx] = tty;
328 return 0; 354 return 0;
329err_free_termios: 355err_free_termios:
330 tty_free_termios(tty); 356 if (legacy)
357 tty_free_termios(tty);
331err_deinit_tty: 358err_deinit_tty:
332 deinitialize_tty_struct(o_tty); 359 deinitialize_tty_struct(o_tty);
333 module_put(o_tty->driver->owner); 360 module_put(o_tty->driver->owner);
334err_free_tty: 361err_free_tty:
362 kfree(ports[0]);
363 kfree(ports[1]);
335 free_tty_struct(o_tty); 364 free_tty_struct(o_tty);
365err:
336 return retval; 366 return retval;
337} 367}
338 368
369static void pty_cleanup(struct tty_struct *tty)
370{
371 kfree(tty->port);
372}
373
374/* Traditional BSD devices */
375#ifdef CONFIG_LEGACY_PTYS
376
377static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
378{
379 return pty_common_install(driver, tty, true);
380}
381
382static void pty_remove(struct tty_driver *driver, struct tty_struct *tty)
383{
384 struct tty_struct *pair = tty->link;
385 driver->ttys[tty->index] = NULL;
386 if (pair)
387 pair->driver->ttys[pair->index] = NULL;
388}
389
339static int pty_bsd_ioctl(struct tty_struct *tty, 390static int pty_bsd_ioctl(struct tty_struct *tty,
340 unsigned int cmd, unsigned long arg) 391 unsigned int cmd, unsigned long arg)
341{ 392{
@@ -366,7 +417,9 @@ static const struct tty_operations master_pty_ops_bsd = {
366 .unthrottle = pty_unthrottle, 417 .unthrottle = pty_unthrottle,
367 .set_termios = pty_set_termios, 418 .set_termios = pty_set_termios,
368 .ioctl = pty_bsd_ioctl, 419 .ioctl = pty_bsd_ioctl,
369 .resize = pty_resize 420 .cleanup = pty_cleanup,
421 .resize = pty_resize,
422 .remove = pty_remove
370}; 423};
371 424
372static const struct tty_operations slave_pty_ops_bsd = { 425static const struct tty_operations slave_pty_ops_bsd = {
@@ -379,7 +432,9 @@ static const struct tty_operations slave_pty_ops_bsd = {
379 .chars_in_buffer = pty_chars_in_buffer, 432 .chars_in_buffer = pty_chars_in_buffer,
380 .unthrottle = pty_unthrottle, 433 .unthrottle = pty_unthrottle,
381 .set_termios = pty_set_termios, 434 .set_termios = pty_set_termios,
382 .resize = pty_resize 435 .cleanup = pty_cleanup,
436 .resize = pty_resize,
437 .remove = pty_remove
383}; 438};
384 439
385static void __init legacy_pty_init(void) 440static void __init legacy_pty_init(void)
@@ -389,12 +444,18 @@ static void __init legacy_pty_init(void)
389 if (legacy_count <= 0) 444 if (legacy_count <= 0)
390 return; 445 return;
391 446
392 pty_driver = alloc_tty_driver(legacy_count); 447 pty_driver = tty_alloc_driver(legacy_count,
393 if (!pty_driver) 448 TTY_DRIVER_RESET_TERMIOS |
449 TTY_DRIVER_REAL_RAW |
450 TTY_DRIVER_DYNAMIC_ALLOC);
451 if (IS_ERR(pty_driver))
394 panic("Couldn't allocate pty driver"); 452 panic("Couldn't allocate pty driver");
395 453
396 pty_slave_driver = alloc_tty_driver(legacy_count); 454 pty_slave_driver = tty_alloc_driver(legacy_count,
397 if (!pty_slave_driver) 455 TTY_DRIVER_RESET_TERMIOS |
456 TTY_DRIVER_REAL_RAW |
457 TTY_DRIVER_DYNAMIC_ALLOC);
458 if (IS_ERR(pty_slave_driver))
398 panic("Couldn't allocate pty slave driver"); 459 panic("Couldn't allocate pty slave driver");
399 460
400 pty_driver->driver_name = "pty_master"; 461 pty_driver->driver_name = "pty_master";
@@ -410,7 +471,6 @@ static void __init legacy_pty_init(void)
410 pty_driver->init_termios.c_lflag = 0; 471 pty_driver->init_termios.c_lflag = 0;
411 pty_driver->init_termios.c_ispeed = 38400; 472 pty_driver->init_termios.c_ispeed = 38400;
412 pty_driver->init_termios.c_ospeed = 38400; 473 pty_driver->init_termios.c_ospeed = 38400;
413 pty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW;
414 pty_driver->other = pty_slave_driver; 474 pty_driver->other = pty_slave_driver;
415 tty_set_operations(pty_driver, &master_pty_ops_bsd); 475 tty_set_operations(pty_driver, &master_pty_ops_bsd);
416 476
@@ -424,8 +484,6 @@ static void __init legacy_pty_init(void)
424 pty_slave_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; 484 pty_slave_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
425 pty_slave_driver->init_termios.c_ispeed = 38400; 485 pty_slave_driver->init_termios.c_ispeed = 38400;
426 pty_slave_driver->init_termios.c_ospeed = 38400; 486 pty_slave_driver->init_termios.c_ospeed = 38400;
427 pty_slave_driver->flags = TTY_DRIVER_RESET_TERMIOS |
428 TTY_DRIVER_REAL_RAW;
429 pty_slave_driver->other = pty_driver; 487 pty_slave_driver->other = pty_driver;
430 tty_set_operations(pty_slave_driver, &slave_pty_ops_bsd); 488 tty_set_operations(pty_slave_driver, &slave_pty_ops_bsd);
431 489
@@ -497,78 +555,22 @@ static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
497 return tty; 555 return tty;
498} 556}
499 557
500static void pty_unix98_shutdown(struct tty_struct *tty)
501{
502 tty_driver_remove_tty(tty->driver, tty);
503 /* We have our own method as we don't use the tty index */
504 kfree(tty->termios);
505}
506
507/* We have no need to install and remove our tty objects as devpts does all 558/* We have no need to install and remove our tty objects as devpts does all
508 the work for us */ 559 the work for us */
509 560
510static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) 561static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
511{ 562{
512 struct tty_struct *o_tty; 563 return pty_common_install(driver, tty, false);
513 int idx = tty->index;
514
515 o_tty = alloc_tty_struct();
516 if (!o_tty)
517 return -ENOMEM;
518 if (!try_module_get(driver->other->owner)) {
519 /* This cannot in fact currently happen */
520 goto err_free_tty;
521 }
522 initialize_tty_struct(o_tty, driver->other, idx);
523
524 tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
525 if (tty->termios == NULL)
526 goto err_free_mem;
527 *tty->termios = driver->init_termios;
528 tty->termios_locked = tty->termios + 1;
529
530 o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
531 if (o_tty->termios == NULL)
532 goto err_free_mem;
533 *o_tty->termios = driver->other->init_termios;
534 o_tty->termios_locked = o_tty->termios + 1;
535
536 tty_driver_kref_get(driver->other);
537 if (driver->subtype == PTY_TYPE_MASTER)
538 o_tty->count++;
539 /* Establish the links in both directions */
540 tty->link = o_tty;
541 o_tty->link = tty;
542 /*
543 * All structures have been allocated, so now we install them.
544 * Failures after this point use release_tty to clean up, so
545 * there's no need to null out the local pointers.
546 */
547 tty_driver_kref_get(driver);
548 tty->count++;
549 return 0;
550err_free_mem:
551 deinitialize_tty_struct(o_tty);
552 kfree(o_tty->termios);
553 kfree(tty->termios);
554 module_put(o_tty->driver->owner);
555err_free_tty:
556 free_tty_struct(o_tty);
557 return -ENOMEM;
558}
559
560static void ptm_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
561{
562} 564}
563 565
564static void pts_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) 566static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
565{ 567{
566} 568}
567 569
568static const struct tty_operations ptm_unix98_ops = { 570static const struct tty_operations ptm_unix98_ops = {
569 .lookup = ptm_unix98_lookup, 571 .lookup = ptm_unix98_lookup,
570 .install = pty_unix98_install, 572 .install = pty_unix98_install,
571 .remove = ptm_unix98_remove, 573 .remove = pty_unix98_remove,
572 .open = pty_open, 574 .open = pty_open,
573 .close = pty_close, 575 .close = pty_close,
574 .write = pty_write, 576 .write = pty_write,
@@ -578,14 +580,14 @@ static const struct tty_operations ptm_unix98_ops = {
578 .unthrottle = pty_unthrottle, 580 .unthrottle = pty_unthrottle,
579 .set_termios = pty_set_termios, 581 .set_termios = pty_set_termios,
580 .ioctl = pty_unix98_ioctl, 582 .ioctl = pty_unix98_ioctl,
581 .shutdown = pty_unix98_shutdown, 583 .resize = pty_resize,
582 .resize = pty_resize 584 .cleanup = pty_cleanup
583}; 585};
584 586
585static const struct tty_operations pty_unix98_ops = { 587static const struct tty_operations pty_unix98_ops = {
586 .lookup = pts_unix98_lookup, 588 .lookup = pts_unix98_lookup,
587 .install = pty_unix98_install, 589 .install = pty_unix98_install,
588 .remove = pts_unix98_remove, 590 .remove = pty_unix98_remove,
589 .open = pty_open, 591 .open = pty_open,
590 .close = pty_close, 592 .close = pty_close,
591 .write = pty_write, 593 .write = pty_write,
@@ -594,7 +596,7 @@ static const struct tty_operations pty_unix98_ops = {
594 .chars_in_buffer = pty_chars_in_buffer, 596 .chars_in_buffer = pty_chars_in_buffer,
595 .unthrottle = pty_unthrottle, 597 .unthrottle = pty_unthrottle,
596 .set_termios = pty_set_termios, 598 .set_termios = pty_set_termios,
597 .shutdown = pty_unix98_shutdown 599 .cleanup = pty_cleanup,
598}; 600};
599 601
600/** 602/**
@@ -622,26 +624,28 @@ static int ptmx_open(struct inode *inode, struct file *filp)
622 return retval; 624 return retval;
623 625
624 /* find a device that is not in use. */ 626 /* find a device that is not in use. */
625 tty_lock(); 627 mutex_lock(&devpts_mutex);
626 index = devpts_new_index(inode); 628 index = devpts_new_index(inode);
627 tty_unlock();
628 if (index < 0) { 629 if (index < 0) {
629 retval = index; 630 retval = index;
631 mutex_unlock(&devpts_mutex);
630 goto err_file; 632 goto err_file;
631 } 633 }
632 634
635 mutex_unlock(&devpts_mutex);
636
633 mutex_lock(&tty_mutex); 637 mutex_lock(&tty_mutex);
634 mutex_lock(&devpts_mutex);
635 tty = tty_init_dev(ptm_driver, index); 638 tty = tty_init_dev(ptm_driver, index);
636 mutex_unlock(&devpts_mutex);
637 tty_lock();
638 mutex_unlock(&tty_mutex);
639 639
640 if (IS_ERR(tty)) { 640 if (IS_ERR(tty)) {
641 retval = PTR_ERR(tty); 641 retval = PTR_ERR(tty);
642 goto out; 642 goto out;
643 } 643 }
644 644
645 /* The tty returned here is locked so we can safely
646 drop the mutex */
647 mutex_unlock(&tty_mutex);
648
645 set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ 649 set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
646 650
647 tty_add_file(tty, filp); 651 tty_add_file(tty, filp);
@@ -654,15 +658,15 @@ static int ptmx_open(struct inode *inode, struct file *filp)
654 if (retval) 658 if (retval)
655 goto err_release; 659 goto err_release;
656 660
657 tty_unlock(); 661 tty_unlock(tty);
658 return 0; 662 return 0;
659err_release: 663err_release:
660 tty_unlock(); 664 tty_unlock(tty);
661 tty_release(inode, filp); 665 tty_release(inode, filp);
662 return retval; 666 return retval;
663out: 667out:
668 mutex_unlock(&tty_mutex);
664 devpts_kill_index(inode, index); 669 devpts_kill_index(inode, index);
665 tty_unlock();
666err_file: 670err_file:
667 tty_free_file(filp); 671 tty_free_file(filp);
668 return retval; 672 return retval;
@@ -672,11 +676,21 @@ static struct file_operations ptmx_fops;
672 676
673static void __init unix98_pty_init(void) 677static void __init unix98_pty_init(void)
674{ 678{
675 ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX); 679 ptm_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX,
676 if (!ptm_driver) 680 TTY_DRIVER_RESET_TERMIOS |
681 TTY_DRIVER_REAL_RAW |
682 TTY_DRIVER_DYNAMIC_DEV |
683 TTY_DRIVER_DEVPTS_MEM |
684 TTY_DRIVER_DYNAMIC_ALLOC);
685 if (IS_ERR(ptm_driver))
677 panic("Couldn't allocate Unix98 ptm driver"); 686 panic("Couldn't allocate Unix98 ptm driver");
678 pts_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX); 687 pts_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX,
679 if (!pts_driver) 688 TTY_DRIVER_RESET_TERMIOS |
689 TTY_DRIVER_REAL_RAW |
690 TTY_DRIVER_DYNAMIC_DEV |
691 TTY_DRIVER_DEVPTS_MEM |
692 TTY_DRIVER_DYNAMIC_ALLOC);
693 if (IS_ERR(pts_driver))
680 panic("Couldn't allocate Unix98 pts driver"); 694 panic("Couldn't allocate Unix98 pts driver");
681 695
682 ptm_driver->driver_name = "pty_master"; 696 ptm_driver->driver_name = "pty_master";
@@ -692,8 +706,6 @@ static void __init unix98_pty_init(void)
692 ptm_driver->init_termios.c_lflag = 0; 706 ptm_driver->init_termios.c_lflag = 0;
693 ptm_driver->init_termios.c_ispeed = 38400; 707 ptm_driver->init_termios.c_ispeed = 38400;
694 ptm_driver->init_termios.c_ospeed = 38400; 708 ptm_driver->init_termios.c_ospeed = 38400;
695 ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
696 TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
697 ptm_driver->other = pts_driver; 709 ptm_driver->other = pts_driver;
698 tty_set_operations(ptm_driver, &ptm_unix98_ops); 710 tty_set_operations(ptm_driver, &ptm_unix98_ops);
699 711
@@ -707,8 +719,6 @@ static void __init unix98_pty_init(void)
707 pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; 719 pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
708 pts_driver->init_termios.c_ispeed = 38400; 720 pts_driver->init_termios.c_ispeed = 38400;
709 pts_driver->init_termios.c_ospeed = 38400; 721 pts_driver->init_termios.c_ospeed = 38400;
710 pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
711 TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
712 pts_driver->other = ptm_driver; 722 pts_driver->other = ptm_driver;
713 tty_set_operations(pts_driver, &pty_unix98_ops); 723 tty_set_operations(pts_driver, &pty_unix98_ops);
714 724