diff options
Diffstat (limited to 'drivers/tty/hvc/hvsi.c')
-rw-r--r-- | drivers/tty/hvc/hvsi.c | 35 |
1 files changed, 21 insertions, 14 deletions
diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c index 68b729b8d1eb..6f5bc49c441f 100644 --- a/drivers/tty/hvc/hvsi.c +++ b/drivers/tty/hvc/hvsi.c | |||
@@ -76,7 +76,6 @@ struct hvsi_struct { | |||
76 | wait_queue_head_t stateq; /* woken when HVSI state changes */ | 76 | wait_queue_head_t stateq; /* woken when HVSI state changes */ |
77 | spinlock_t lock; | 77 | spinlock_t lock; |
78 | int index; | 78 | int index; |
79 | struct tty_struct *tty; | ||
80 | uint8_t throttle_buf[128]; | 79 | uint8_t throttle_buf[128]; |
81 | uint8_t outbuf[N_OUTBUF]; /* to implement write_room and chars_in_buffer */ | 80 | uint8_t outbuf[N_OUTBUF]; /* to implement write_room and chars_in_buffer */ |
82 | /* inbuf is for packet reassembly. leave a little room for leftovers. */ | 81 | /* inbuf is for packet reassembly. leave a little room for leftovers. */ |
@@ -492,14 +491,17 @@ static irqreturn_t hvsi_interrupt(int irq, void *arg) | |||
492 | { | 491 | { |
493 | struct hvsi_struct *hp = (struct hvsi_struct *)arg; | 492 | struct hvsi_struct *hp = (struct hvsi_struct *)arg; |
494 | struct hvsi_struct *handshake; | 493 | struct hvsi_struct *handshake; |
494 | struct tty_struct *tty; | ||
495 | unsigned long flags; | 495 | unsigned long flags; |
496 | int again = 1; | 496 | int again = 1; |
497 | 497 | ||
498 | pr_debug("%s\n", __func__); | 498 | pr_debug("%s\n", __func__); |
499 | 499 | ||
500 | tty = tty_port_tty_get(&hp->port); | ||
501 | |||
500 | while (again) { | 502 | while (again) { |
501 | spin_lock_irqsave(&hp->lock, flags); | 503 | spin_lock_irqsave(&hp->lock, flags); |
502 | again = hvsi_load_chunk(hp, hp->tty, &handshake); | 504 | again = hvsi_load_chunk(hp, tty, &handshake); |
503 | spin_unlock_irqrestore(&hp->lock, flags); | 505 | spin_unlock_irqrestore(&hp->lock, flags); |
504 | 506 | ||
505 | if (handshake) { | 507 | if (handshake) { |
@@ -509,15 +511,16 @@ static irqreturn_t hvsi_interrupt(int irq, void *arg) | |||
509 | } | 511 | } |
510 | 512 | ||
511 | spin_lock_irqsave(&hp->lock, flags); | 513 | spin_lock_irqsave(&hp->lock, flags); |
512 | if (hp->tty && hp->n_throttle | 514 | if (tty && hp->n_throttle && !test_bit(TTY_THROTTLED, &tty->flags)) { |
513 | && (!test_bit(TTY_THROTTLED, &hp->tty->flags))) { | 515 | /* we weren't hung up and we weren't throttled, so we can |
514 | /* we weren't hung up and we weren't throttled, so we can deliver the | 516 | * deliver the rest now */ |
515 | * rest now */ | 517 | hvsi_send_overflow(hp, tty); |
516 | hvsi_send_overflow(hp, hp->tty); | 518 | tty_flip_buffer_push(tty); |
517 | tty_flip_buffer_push(hp->tty); | ||
518 | } | 519 | } |
519 | spin_unlock_irqrestore(&hp->lock, flags); | 520 | spin_unlock_irqrestore(&hp->lock, flags); |
520 | 521 | ||
522 | tty_kref_put(tty); | ||
523 | |||
521 | return IRQ_HANDLED; | 524 | return IRQ_HANDLED; |
522 | } | 525 | } |
523 | 526 | ||
@@ -724,8 +727,8 @@ static int hvsi_open(struct tty_struct *tty, struct file *filp) | |||
724 | if (hp->state == HVSI_FSP_DIED) | 727 | if (hp->state == HVSI_FSP_DIED) |
725 | return -EIO; | 728 | return -EIO; |
726 | 729 | ||
730 | tty_port_tty_set(&hp->port, tty); | ||
727 | spin_lock_irqsave(&hp->lock, flags); | 731 | spin_lock_irqsave(&hp->lock, flags); |
728 | hp->tty = tty; | ||
729 | hp->port.count++; | 732 | hp->port.count++; |
730 | atomic_set(&hp->seqno, 0); | 733 | atomic_set(&hp->seqno, 0); |
731 | h_vio_signal(hp->vtermno, VIO_IRQ_ENABLE); | 734 | h_vio_signal(hp->vtermno, VIO_IRQ_ENABLE); |
@@ -784,7 +787,7 @@ static void hvsi_close(struct tty_struct *tty, struct file *filp) | |||
784 | spin_lock_irqsave(&hp->lock, flags); | 787 | spin_lock_irqsave(&hp->lock, flags); |
785 | 788 | ||
786 | if (--hp->port.count == 0) { | 789 | if (--hp->port.count == 0) { |
787 | hp->tty = NULL; | 790 | tty_port_tty_set(&hp->port, NULL); |
788 | hp->inbuf_end = hp->inbuf; /* discard remaining partial packets */ | 791 | hp->inbuf_end = hp->inbuf; /* discard remaining partial packets */ |
789 | 792 | ||
790 | /* only close down connection if it is not the console */ | 793 | /* only close down connection if it is not the console */ |
@@ -830,12 +833,11 @@ static void hvsi_hangup(struct tty_struct *tty) | |||
830 | 833 | ||
831 | pr_debug("%s\n", __func__); | 834 | pr_debug("%s\n", __func__); |
832 | 835 | ||
833 | spin_lock_irqsave(&hp->lock, flags); | 836 | tty_port_tty_set(&hp->port, NULL); |
834 | 837 | ||
838 | spin_lock_irqsave(&hp->lock, flags); | ||
835 | hp->port.count = 0; | 839 | hp->port.count = 0; |
836 | hp->n_outbuf = 0; | 840 | hp->n_outbuf = 0; |
837 | hp->tty = NULL; | ||
838 | |||
839 | spin_unlock_irqrestore(&hp->lock, flags); | 841 | spin_unlock_irqrestore(&hp->lock, flags); |
840 | } | 842 | } |
841 | 843 | ||
@@ -863,6 +865,7 @@ static void hvsi_write_worker(struct work_struct *work) | |||
863 | { | 865 | { |
864 | struct hvsi_struct *hp = | 866 | struct hvsi_struct *hp = |
865 | container_of(work, struct hvsi_struct, writer.work); | 867 | container_of(work, struct hvsi_struct, writer.work); |
868 | struct tty_struct *tty; | ||
866 | unsigned long flags; | 869 | unsigned long flags; |
867 | #ifdef DEBUG | 870 | #ifdef DEBUG |
868 | static long start_j = 0; | 871 | static long start_j = 0; |
@@ -896,7 +899,11 @@ static void hvsi_write_worker(struct work_struct *work) | |||
896 | start_j = 0; | 899 | start_j = 0; |
897 | #endif /* DEBUG */ | 900 | #endif /* DEBUG */ |
898 | wake_up_all(&hp->emptyq); | 901 | wake_up_all(&hp->emptyq); |
899 | tty_wakeup(hp->tty); | 902 | tty = tty_port_tty_get(&hp->port); |
903 | if (tty) { | ||
904 | tty_wakeup(tty); | ||
905 | tty_kref_put(tty); | ||
906 | } | ||
900 | } | 907 | } |
901 | 908 | ||
902 | out: | 909 | out: |