aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2009-01-02 08:47:58 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-02 13:19:41 -0500
commitd1c815e549ff40f9e9db65654855118e6bdff6a4 (patch)
tree7e20548f68c053be312f080e7c1fd7678df45bd7 /drivers/char
parent542f54823614915780c3459b0e6062f06c0c0f99 (diff)
tty: relock epca
Bring epca into line with the port locking. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/epca.c195
1 files changed, 104 insertions, 91 deletions
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index da2d2cf16f5..e07d7925c30 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -69,7 +69,9 @@ static int invalid_lilo_config;
69 69
70/* 70/*
71 * The ISA boards do window flipping into the same spaces so its only sane with 71 * The ISA boards do window flipping into the same spaces so its only sane with
72 * a single lock. It's still pretty efficient. 72 * a single lock. It's still pretty efficient. This lock guards the hardware
73 * and the tty_port lock guards the kernel side stuff like use counts. Take
74 * this lock inside the port lock if you must take both.
73 */ 75 */
74static DEFINE_SPINLOCK(epca_lock); 76static DEFINE_SPINLOCK(epca_lock);
75 77
@@ -156,7 +158,7 @@ static struct channel *verifyChannel(struct tty_struct *);
156static void pc_sched_event(struct channel *, int); 158static void pc_sched_event(struct channel *, int);
157static void epca_error(int, char *); 159static void epca_error(int, char *);
158static void pc_close(struct tty_struct *, struct file *); 160static void pc_close(struct tty_struct *, struct file *);
159static void shutdown(struct channel *); 161static void shutdown(struct channel *, struct tty_struct *tty);
160static void pc_hangup(struct tty_struct *); 162static void pc_hangup(struct tty_struct *);
161static int pc_write_room(struct tty_struct *); 163static int pc_write_room(struct tty_struct *);
162static int pc_chars_in_buffer(struct tty_struct *); 164static int pc_chars_in_buffer(struct tty_struct *);
@@ -419,76 +421,78 @@ static void epca_error(int line, char *msg)
419static void pc_close(struct tty_struct *tty, struct file *filp) 421static void pc_close(struct tty_struct *tty, struct file *filp)
420{ 422{
421 struct channel *ch; 423 struct channel *ch;
424 struct tty_port *port;
422 unsigned long flags; 425 unsigned long flags;
423 /* 426 /*
424 * verifyChannel returns the channel from the tty struct if it is 427 * verifyChannel returns the channel from the tty struct if it is
425 * valid. This serves as a sanity check. 428 * valid. This serves as a sanity check.
426 */ 429 */
427 ch = verifyChannel(tty); 430 ch = verifyChannel(tty);
428 if (ch != NULL) { 431 if (ch == NULL)
429 spin_lock_irqsave(&epca_lock, flags); 432 return;
430 if (tty_hung_up_p(filp)) { 433 port = &ch->port;
431 spin_unlock_irqrestore(&epca_lock, flags);
432 return;
433 }
434 if (ch->port.count-- > 1) {
435 /* Begin channel is open more than once */
436 /*
437 * Return without doing anything. Someone might still
438 * be using the channel.
439 */
440 spin_unlock_irqrestore(&epca_lock, flags);
441 return;
442 }
443 /* Port open only once go ahead with shutdown & reset */
444 BUG_ON(ch->port.count < 0);
445 434
435 spin_lock_irqsave(&port->lock, flags);
436 if (tty_hung_up_p(filp)) {
437 spin_unlock_irqrestore(&port->lock, flags);
438 return;
439 }
440 if (port->count-- > 1) {
441 /* Begin channel is open more than once */
446 /* 442 /*
447 * Let the rest of the driver know the channel is being closed. 443 * Return without doing anything. Someone might still
448 * This becomes important if an open is attempted before close 444 * be using the channel.
449 * is finished.
450 */ 445 */
451 ch->port.flags |= ASYNC_CLOSING; 446 spin_unlock_irqrestore(&port->lock, flags);
452 tty->closing = 1; 447 return;
453 448 }
454 spin_unlock_irqrestore(&epca_lock, flags); 449 /* Port open only once go ahead with shutdown & reset */
455 450 WARN_ON(port->count < 0);
456 if (ch->port.flags & ASYNC_INITIALIZED) {
457 /* Setup an event to indicate when the
458 transmit buffer empties */
459 setup_empty_event(tty, ch);
460 /* 30 seconds timeout */
461 tty_wait_until_sent(tty, 3000);
462 }
463 pc_flush_buffer(tty);
464 451
465 tty_ldisc_flush(tty); 452 /*
466 shutdown(ch); 453 * Let the rest of the driver know the channel is being closed.
454 * This becomes important if an open is attempted before close
455 * is finished.
456 */
457 port->flags |= ASYNC_CLOSING;
458 tty->closing = 1;
467 459
468 spin_lock_irqsave(&epca_lock, flags); 460 spin_unlock_irqrestore(&port->lock, flags);
469 tty->closing = 0;
470 ch->event = 0;
471 ch->port.tty = NULL;
472 spin_unlock_irqrestore(&epca_lock, flags);
473 461
474 if (ch->port.blocked_open) { 462 if (port->flags & ASYNC_INITIALIZED) {
475 if (ch->close_delay) 463 /* Setup an event to indicate when the
476 msleep_interruptible(jiffies_to_msecs(ch->close_delay)); 464 transmit buffer empties */
477 wake_up_interruptible(&ch->port.open_wait); 465 setup_empty_event(tty, ch);
478 } 466 /* 30 seconds timeout */
479 ch->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED | 467 tty_wait_until_sent(tty, 3000);
480 ASYNC_CLOSING); 468 }
481 wake_up_interruptible(&ch->port.close_wait); 469 pc_flush_buffer(tty);
470 tty_ldisc_flush(tty);
471 shutdown(ch, tty);
472
473 spin_lock_irqsave(&port->lock, flags);
474 tty->closing = 0;
475 ch->event = 0;
476 port->tty = NULL;
477 spin_unlock_irqrestore(&port->lock, flags);
478
479 if (port->blocked_open) {
480 if (ch->close_delay)
481 msleep_interruptible(jiffies_to_msecs(ch->close_delay));
482 wake_up_interruptible(&port->open_wait);
482 } 483 }
484 port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED |
485 ASYNC_CLOSING);
486 wake_up_interruptible(&port->close_wait);
483} 487}
484 488
485static void shutdown(struct channel *ch) 489static void shutdown(struct channel *ch, struct tty_struct *tty)
486{ 490{
487 unsigned long flags; 491 unsigned long flags;
488 struct tty_struct *tty;
489 struct board_chan __iomem *bc; 492 struct board_chan __iomem *bc;
493 struct tty_port *port = &ch->port;
490 494
491 if (!(ch->port.flags & ASYNC_INITIALIZED)) 495 if (!(port->flags & ASYNC_INITIALIZED))
492 return; 496 return;
493 497
494 spin_lock_irqsave(&epca_lock, flags); 498 spin_lock_irqsave(&epca_lock, flags);
@@ -503,7 +507,6 @@ static void shutdown(struct channel *ch)
503 */ 507 */
504 if (bc) 508 if (bc)
505 writeb(0, &bc->idata); 509 writeb(0, &bc->idata);
506 tty = ch->port.tty;
507 510
508 /* If we're a modem control device and HUPCL is on, drop RTS & DTR. */ 511 /* If we're a modem control device and HUPCL is on, drop RTS & DTR. */
509 if (tty->termios->c_cflag & HUPCL) { 512 if (tty->termios->c_cflag & HUPCL) {
@@ -517,13 +520,15 @@ static void shutdown(struct channel *ch)
517 * will have to reinitialized. Set a flag to indicate this. 520 * will have to reinitialized. Set a flag to indicate this.
518 */ 521 */
519 /* Prevent future Digi programmed interrupts from coming active */ 522 /* Prevent future Digi programmed interrupts from coming active */
520 ch->port.flags &= ~ASYNC_INITIALIZED; 523 port->flags &= ~ASYNC_INITIALIZED;
521 spin_unlock_irqrestore(&epca_lock, flags); 524 spin_unlock_irqrestore(&epca_lock, flags);
522} 525}
523 526
524static void pc_hangup(struct tty_struct *tty) 527static void pc_hangup(struct tty_struct *tty)
525{ 528{
526 struct channel *ch; 529 struct channel *ch;
530 struct tty_port *port;
531
527 /* 532 /*
528 * verifyChannel returns the channel from the tty struct if it is 533 * verifyChannel returns the channel from the tty struct if it is
529 * valid. This serves as a sanity check. 534 * valid. This serves as a sanity check.
@@ -531,18 +536,19 @@ static void pc_hangup(struct tty_struct *tty)
531 ch = verifyChannel(tty); 536 ch = verifyChannel(tty);
532 if (ch != NULL) { 537 if (ch != NULL) {
533 unsigned long flags; 538 unsigned long flags;
539 port = &ch->port;
534 540
535 pc_flush_buffer(tty); 541 pc_flush_buffer(tty);
536 tty_ldisc_flush(tty); 542 tty_ldisc_flush(tty);
537 shutdown(ch); 543 shutdown(ch, tty);
538 544
539 spin_lock_irqsave(&epca_lock, flags); 545 spin_lock_irqsave(&port->lock, flags);
540 ch->port.tty = NULL; 546 port->tty = NULL;
541 ch->event = 0; 547 ch->event = 0; /* FIXME: review locking of ch->event */
542 ch->port.count = 0; 548 port->count = 0;
543 ch->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED); 549 port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED);
544 spin_unlock_irqrestore(&epca_lock, flags); 550 spin_unlock_irqrestore(&port->lock, flags);
545 wake_up_interruptible(&ch->port.open_wait); 551 wake_up_interruptible(&port->open_wait);
546 } 552 }
547} 553}
548 554
@@ -792,9 +798,10 @@ static int block_til_ready(struct tty_struct *tty,
792 DECLARE_WAITQUEUE(wait, current); 798 DECLARE_WAITQUEUE(wait, current);
793 int retval, do_clocal = 0; 799 int retval, do_clocal = 0;
794 unsigned long flags; 800 unsigned long flags;
801 struct tty_port *port = &ch->port;
795 802
796 if (tty_hung_up_p(filp)) { 803 if (tty_hung_up_p(filp)) {
797 if (ch->port.flags & ASYNC_HUP_NOTIFY) 804 if (port->flags & ASYNC_HUP_NOTIFY)
798 retval = -EAGAIN; 805 retval = -EAGAIN;
799 else 806 else
800 retval = -ERESTARTSYS; 807 retval = -ERESTARTSYS;
@@ -805,10 +812,10 @@ static int block_til_ready(struct tty_struct *tty,
805 * If the device is in the middle of being closed, then block until 812 * If the device is in the middle of being closed, then block until
806 * it's done, and then try again. 813 * it's done, and then try again.
807 */ 814 */
808 if (ch->port.flags & ASYNC_CLOSING) { 815 if (port->flags & ASYNC_CLOSING) {
809 interruptible_sleep_on(&ch->port.close_wait); 816 interruptible_sleep_on(&port->close_wait);
810 817
811 if (ch->port.flags & ASYNC_HUP_NOTIFY) 818 if (port->flags & ASYNC_HUP_NOTIFY)
812 return -EAGAIN; 819 return -EAGAIN;
813 else 820 else
814 return -ERESTARTSYS; 821 return -ERESTARTSYS;
@@ -819,7 +826,7 @@ static int block_til_ready(struct tty_struct *tty,
819 * If non-blocking mode is set, then make the check up front 826 * If non-blocking mode is set, then make the check up front
820 * and then exit. 827 * and then exit.
821 */ 828 */
822 ch->port.flags |= ASYNC_NORMAL_ACTIVE; 829 port->flags |= ASYNC_NORMAL_ACTIVE;
823 return 0; 830 return 0;
824 } 831 }
825 if (tty->termios->c_cflag & CLOCAL) 832 if (tty->termios->c_cflag & CLOCAL)
@@ -827,31 +834,31 @@ static int block_til_ready(struct tty_struct *tty,
827 /* Block waiting for the carrier detect and the line to become free */ 834 /* Block waiting for the carrier detect and the line to become free */
828 835
829 retval = 0; 836 retval = 0;
830 add_wait_queue(&ch->port.open_wait, &wait); 837 add_wait_queue(&port->open_wait, &wait);
831 838
832 spin_lock_irqsave(&epca_lock, flags); 839 spin_lock_irqsave(&port->lock, flags);
833 /* We dec count so that pc_close will know when to free things */ 840 /* We dec count so that pc_close will know when to free things */
834 if (!tty_hung_up_p(filp)) 841 if (!tty_hung_up_p(filp))
835 ch->port.count--; 842 port->count--;
836 ch->port.blocked_open++; 843 port->blocked_open++;
837 while (1) { 844 while (1) {
838 set_current_state(TASK_INTERRUPTIBLE); 845 set_current_state(TASK_INTERRUPTIBLE);
839 if (tty_hung_up_p(filp) || 846 if (tty_hung_up_p(filp) ||
840 !(ch->port.flags & ASYNC_INITIALIZED)) { 847 !(port->flags & ASYNC_INITIALIZED)) {
841 if (ch->port.flags & ASYNC_HUP_NOTIFY) 848 if (port->flags & ASYNC_HUP_NOTIFY)
842 retval = -EAGAIN; 849 retval = -EAGAIN;
843 else 850 else
844 retval = -ERESTARTSYS; 851 retval = -ERESTARTSYS;
845 break; 852 break;
846 } 853 }
847 if (!(ch->port.flags & ASYNC_CLOSING) && 854 if (!(port->flags & ASYNC_CLOSING) &&
848 (do_clocal || (ch->imodem & ch->dcd))) 855 (do_clocal || (ch->imodem & ch->dcd)))
849 break; 856 break;
850 if (signal_pending(current)) { 857 if (signal_pending(current)) {
851 retval = -ERESTARTSYS; 858 retval = -ERESTARTSYS;
852 break; 859 break;
853 } 860 }
854 spin_unlock_irqrestore(&epca_lock, flags); 861 spin_unlock_irqrestore(&port->lock, flags);
855 /* 862 /*
856 * Allow someone else to be scheduled. We will occasionally go 863 * Allow someone else to be scheduled. We will occasionally go
857 * through this loop until one of the above conditions change. 864 * through this loop until one of the above conditions change.
@@ -859,27 +866,28 @@ static int block_til_ready(struct tty_struct *tty,
859 * and prevent this loop from hogging the cpu. 866 * and prevent this loop from hogging the cpu.
860 */ 867 */
861 schedule(); 868 schedule();
862 spin_lock_irqsave(&epca_lock, flags); 869 spin_lock_irqsave(&port->lock, flags);
863 } 870 }
864 871
865 __set_current_state(TASK_RUNNING); 872 __set_current_state(TASK_RUNNING);
866 remove_wait_queue(&ch->port.open_wait, &wait); 873 remove_wait_queue(&port->open_wait, &wait);
867 if (!tty_hung_up_p(filp)) 874 if (!tty_hung_up_p(filp))
868 ch->port.count++; 875 port->count++;
869 ch->port.blocked_open--; 876 port->blocked_open--;
870 877
871 spin_unlock_irqrestore(&epca_lock, flags); 878 spin_unlock_irqrestore(&port->lock, flags);
872 879
873 if (retval) 880 if (retval)
874 return retval; 881 return retval;
875 882
876 ch->port.flags |= ASYNC_NORMAL_ACTIVE; 883 port->flags |= ASYNC_NORMAL_ACTIVE;
877 return 0; 884 return 0;
878} 885}
879 886
880static int pc_open(struct tty_struct *tty, struct file *filp) 887static int pc_open(struct tty_struct *tty, struct file *filp)
881{ 888{
882 struct channel *ch; 889 struct channel *ch;
890 struct tty_port *port;
883 unsigned long flags; 891 unsigned long flags;
884 int line, retval, boardnum; 892 int line, retval, boardnum;
885 struct board_chan __iomem *bc; 893 struct board_chan __iomem *bc;
@@ -890,6 +898,7 @@ static int pc_open(struct tty_struct *tty, struct file *filp)
890 return -ENODEV; 898 return -ENODEV;
891 899
892 ch = &digi_channels[line]; 900 ch = &digi_channels[line];
901 port = &ch->port;
893 boardnum = ch->boardnum; 902 boardnum = ch->boardnum;
894 903
895 /* Check status of board configured in system. */ 904 /* Check status of board configured in system. */
@@ -926,22 +935,24 @@ static int pc_open(struct tty_struct *tty, struct file *filp)
926 return -ENODEV; 935 return -ENODEV;
927 } 936 }
928 937
929 spin_lock_irqsave(&epca_lock, flags); 938 spin_lock_irqsave(&port->lock, flags);
930 /* 939 /*
931 * Every time a channel is opened, increment a counter. This is 940 * Every time a channel is opened, increment a counter. This is
932 * necessary because we do not wish to flush and shutdown the channel 941 * necessary because we do not wish to flush and shutdown the channel
933 * until the last app holding the channel open, closes it. 942 * until the last app holding the channel open, closes it.
934 */ 943 */
935 ch->port.count++; 944 port->count++;
936 /* 945 /*
937 * Set a kernel structures pointer to our local channel structure. This 946 * Set a kernel structures pointer to our local channel structure. This
938 * way we can get to it when passed only a tty struct. 947 * way we can get to it when passed only a tty struct.
939 */ 948 */
940 tty->driver_data = ch; 949 tty->driver_data = ch;
950 port->tty = tty;
941 /* 951 /*
942 * If this is the first time the channel has been opened, initialize 952 * If this is the first time the channel has been opened, initialize
943 * the tty->termios struct otherwise let pc_close handle it. 953 * the tty->termios struct otherwise let pc_close handle it.
944 */ 954 */
955 spin_lock(&epca_lock);
945 globalwinon(ch); 956 globalwinon(ch);
946 ch->statusflags = 0; 957 ch->statusflags = 0;
947 958
@@ -956,16 +967,16 @@ static int pc_open(struct tty_struct *tty, struct file *filp)
956 writew(head, &bc->rout); 967 writew(head, &bc->rout);
957 968
958 /* Set the channels associated tty structure */ 969 /* Set the channels associated tty structure */
959 ch->port.tty = tty;
960 970
961 /* 971 /*
962 * The below routine generally sets up parity, baud, flow control 972 * The below routine generally sets up parity, baud, flow control
963 * issues, etc.... It effect both control flags and input flags. 973 * issues, etc.... It effect both control flags and input flags.
964 */ 974 */
965 epcaparam(tty, ch); 975 epcaparam(tty, ch);
966 ch->port.flags |= ASYNC_INITIALIZED;
967 memoff(ch); 976 memoff(ch);
968 spin_unlock_irqrestore(&epca_lock, flags); 977 spin_unlock(&epca_lock);
978 port->flags |= ASYNC_INITIALIZED;
979 spin_unlock_irqrestore(&port->lock, flags);
969 980
970 retval = block_til_ready(tty, filp, ch); 981 retval = block_til_ready(tty, filp, ch);
971 if (retval) 982 if (retval)
@@ -974,13 +985,15 @@ static int pc_open(struct tty_struct *tty, struct file *filp)
974 * Set this again in case a hangup set it to zero while this open() was 985 * Set this again in case a hangup set it to zero while this open() was
975 * waiting for the line... 986 * waiting for the line...
976 */ 987 */
977 spin_lock_irqsave(&epca_lock, flags); 988 spin_lock_irqsave(&port->lock, flags);
978 ch->port.tty = tty; 989 port->tty = tty;
990 spin_lock(&epca_lock);
979 globalwinon(ch); 991 globalwinon(ch);
980 /* Enable Digi Data events */ 992 /* Enable Digi Data events */
981 writeb(1, &bc->idata); 993 writeb(1, &bc->idata);
982 memoff(ch); 994 memoff(ch);
983 spin_unlock_irqrestore(&epca_lock, flags); 995 spin_unlock(&epca_lock);
996 spin_unlock_irqrestore(&port->lock, flags);
984 return 0; 997 return 0;
985} 998}
986 999