diff options
Diffstat (limited to 'drivers/tty/n_hdlc.c')
-rw-r--r-- | drivers/tty/n_hdlc.c | 90 |
1 files changed, 45 insertions, 45 deletions
diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index 47d32281032c..52fc0c9a6364 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c | |||
@@ -581,8 +581,9 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, | |||
581 | __u8 __user *buf, size_t nr) | 581 | __u8 __user *buf, size_t nr) |
582 | { | 582 | { |
583 | struct n_hdlc *n_hdlc = tty2n_hdlc(tty); | 583 | struct n_hdlc *n_hdlc = tty2n_hdlc(tty); |
584 | int ret; | 584 | int ret = 0; |
585 | struct n_hdlc_buf *rbuf; | 585 | struct n_hdlc_buf *rbuf; |
586 | DECLARE_WAITQUEUE(wait, current); | ||
586 | 587 | ||
587 | if (debuglevel >= DEBUG_LEVEL_INFO) | 588 | if (debuglevel >= DEBUG_LEVEL_INFO) |
588 | printk("%s(%d)n_hdlc_tty_read() called\n",__FILE__,__LINE__); | 589 | printk("%s(%d)n_hdlc_tty_read() called\n",__FILE__,__LINE__); |
@@ -598,57 +599,55 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, | |||
598 | return -EFAULT; | 599 | return -EFAULT; |
599 | } | 600 | } |
600 | 601 | ||
601 | tty_lock(); | 602 | add_wait_queue(&tty->read_wait, &wait); |
602 | 603 | ||
603 | for (;;) { | 604 | for (;;) { |
604 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { | 605 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { |
605 | tty_unlock(); | 606 | ret = -EIO; |
606 | return -EIO; | 607 | break; |
607 | } | 608 | } |
609 | if (tty_hung_up_p(file)) | ||
610 | break; | ||
608 | 611 | ||
609 | n_hdlc = tty2n_hdlc (tty); | 612 | set_current_state(TASK_INTERRUPTIBLE); |
610 | if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || | ||
611 | tty != n_hdlc->tty) { | ||
612 | tty_unlock(); | ||
613 | return 0; | ||
614 | } | ||
615 | 613 | ||
616 | rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list); | 614 | rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list); |
617 | if (rbuf) | 615 | if (rbuf) { |
616 | if (rbuf->count > nr) { | ||
617 | /* too large for caller's buffer */ | ||
618 | ret = -EOVERFLOW; | ||
619 | } else { | ||
620 | if (copy_to_user(buf, rbuf->buf, rbuf->count)) | ||
621 | ret = -EFAULT; | ||
622 | else | ||
623 | ret = rbuf->count; | ||
624 | } | ||
625 | |||
626 | if (n_hdlc->rx_free_buf_list.count > | ||
627 | DEFAULT_RX_BUF_COUNT) | ||
628 | kfree(rbuf); | ||
629 | else | ||
630 | n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, rbuf); | ||
618 | break; | 631 | break; |
632 | } | ||
619 | 633 | ||
620 | /* no data */ | 634 | /* no data */ |
621 | if (file->f_flags & O_NONBLOCK) { | 635 | if (file->f_flags & O_NONBLOCK) { |
622 | tty_unlock(); | 636 | ret = -EAGAIN; |
623 | return -EAGAIN; | 637 | break; |
624 | } | 638 | } |
625 | 639 | ||
626 | interruptible_sleep_on (&tty->read_wait); | 640 | schedule(); |
641 | |||
627 | if (signal_pending(current)) { | 642 | if (signal_pending(current)) { |
628 | tty_unlock(); | 643 | ret = -EINTR; |
629 | return -EINTR; | 644 | break; |
630 | } | 645 | } |
631 | } | 646 | } |
632 | 647 | ||
633 | if (rbuf->count > nr) | 648 | remove_wait_queue(&tty->read_wait, &wait); |
634 | /* frame too large for caller's buffer (discard frame) */ | 649 | __set_current_state(TASK_RUNNING); |
635 | ret = -EOVERFLOW; | 650 | |
636 | else { | ||
637 | /* Copy the data to the caller's buffer */ | ||
638 | if (copy_to_user(buf, rbuf->buf, rbuf->count)) | ||
639 | ret = -EFAULT; | ||
640 | else | ||
641 | ret = rbuf->count; | ||
642 | } | ||
643 | |||
644 | /* return HDLC buffer to free list unless the free list */ | ||
645 | /* count has exceeded the default value, in which case the */ | ||
646 | /* buffer is freed back to the OS to conserve memory */ | ||
647 | if (n_hdlc->rx_free_buf_list.count > DEFAULT_RX_BUF_COUNT) | ||
648 | kfree(rbuf); | ||
649 | else | ||
650 | n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf); | ||
651 | tty_unlock(); | ||
652 | return ret; | 651 | return ret; |
653 | 652 | ||
654 | } /* end of n_hdlc_tty_read() */ | 653 | } /* end of n_hdlc_tty_read() */ |
@@ -691,14 +690,15 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, | |||
691 | count = maxframe; | 690 | count = maxframe; |
692 | } | 691 | } |
693 | 692 | ||
694 | tty_lock(); | ||
695 | |||
696 | add_wait_queue(&tty->write_wait, &wait); | 693 | add_wait_queue(&tty->write_wait, &wait); |
697 | set_current_state(TASK_INTERRUPTIBLE); | 694 | |
695 | for (;;) { | ||
696 | set_current_state(TASK_INTERRUPTIBLE); | ||
698 | 697 | ||
699 | /* Allocate transmit buffer */ | 698 | tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list); |
700 | /* sleep until transmit buffer available */ | 699 | if (tbuf) |
701 | while (!(tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list))) { | 700 | break; |
701 | |||
702 | if (file->f_flags & O_NONBLOCK) { | 702 | if (file->f_flags & O_NONBLOCK) { |
703 | error = -EAGAIN; | 703 | error = -EAGAIN; |
704 | break; | 704 | break; |
@@ -719,7 +719,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, | |||
719 | } | 719 | } |
720 | } | 720 | } |
721 | 721 | ||
722 | set_current_state(TASK_RUNNING); | 722 | __set_current_state(TASK_RUNNING); |
723 | remove_wait_queue(&tty->write_wait, &wait); | 723 | remove_wait_queue(&tty->write_wait, &wait); |
724 | 724 | ||
725 | if (!error) { | 725 | if (!error) { |
@@ -731,7 +731,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, | |||
731 | n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); | 731 | n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); |
732 | n_hdlc_send_frames(n_hdlc,tty); | 732 | n_hdlc_send_frames(n_hdlc,tty); |
733 | } | 733 | } |
734 | tty_unlock(); | 734 | |
735 | return error; | 735 | return error; |
736 | 736 | ||
737 | } /* end of n_hdlc_tty_write() */ | 737 | } /* end of n_hdlc_tty_write() */ |