diff options
author | Alan Cox <alan@redhat.com> | 2009-01-02 08:45:05 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-02 13:19:38 -0500 |
commit | 31f35939d1d9bcfb3099b32c67b896d2792603f9 (patch) | |
tree | 39b6ceaf0e7477e0357ff8235814f579adad3f28 /drivers/char/isicom.c | |
parent | c9b3976e3fec266be25c5001a70aa0a890b6c476 (diff) |
tty_port: Add a port level carrier detect operation
This is the first step to generalising the various pieces of waiting logic
duplicated in all sorts of serial drivers.
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/isicom.c')
-rw-r--r-- | drivers/char/isicom.c | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 04e4549299ba..b3da4858fd4a 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -830,20 +830,28 @@ static int isicom_setup_port(struct tty_struct *tty) | |||
830 | return 0; | 830 | return 0; |
831 | } | 831 | } |
832 | 832 | ||
833 | static int isicom_carrier_raised(struct tty_port *port) | ||
834 | { | ||
835 | struct isi_port *ip = container_of(port, struct isi_port, port); | ||
836 | return (ip->status & ISI_DCD)?1 : 0; | ||
837 | } | ||
838 | |||
833 | static int block_til_ready(struct tty_struct *tty, struct file *filp, | 839 | static int block_til_ready(struct tty_struct *tty, struct file *filp, |
834 | struct isi_port *port) | 840 | struct isi_port *ip) |
835 | { | 841 | { |
836 | struct isi_board *card = port->card; | 842 | struct isi_board *card = ip->card; |
843 | struct tty_port *port = &ip->port; | ||
837 | int do_clocal = 0, retval; | 844 | int do_clocal = 0, retval; |
838 | unsigned long flags; | 845 | unsigned long flags; |
839 | DECLARE_WAITQUEUE(wait, current); | 846 | DECLARE_WAITQUEUE(wait, current); |
847 | int cd; | ||
840 | 848 | ||
841 | /* block if port is in the process of being closed */ | 849 | /* block if port is in the process of being closed */ |
842 | 850 | ||
843 | if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) { | 851 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { |
844 | pr_dbg("block_til_ready: close in progress.\n"); | 852 | pr_dbg("block_til_ready: close in progress.\n"); |
845 | interruptible_sleep_on(&port->port.close_wait); | 853 | interruptible_sleep_on(&port->close_wait); |
846 | if (port->port.flags & ASYNC_HUP_NOTIFY) | 854 | if (port->flags & ASYNC_HUP_NOTIFY) |
847 | return -EAGAIN; | 855 | return -EAGAIN; |
848 | else | 856 | else |
849 | return -ERESTARTSYS; | 857 | return -ERESTARTSYS; |
@@ -854,7 +862,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
854 | if ((filp->f_flags & O_NONBLOCK) || | 862 | if ((filp->f_flags & O_NONBLOCK) || |
855 | (tty->flags & (1 << TTY_IO_ERROR))) { | 863 | (tty->flags & (1 << TTY_IO_ERROR))) { |
856 | pr_dbg("block_til_ready: non-block mode.\n"); | 864 | pr_dbg("block_til_ready: non-block mode.\n"); |
857 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | 865 | port->flags |= ASYNC_NORMAL_ACTIVE; |
858 | return 0; | 866 | return 0; |
859 | } | 867 | } |
860 | 868 | ||
@@ -864,29 +872,29 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
864 | /* block waiting for DCD to be asserted, and while | 872 | /* block waiting for DCD to be asserted, and while |
865 | callout dev is busy */ | 873 | callout dev is busy */ |
866 | retval = 0; | 874 | retval = 0; |
867 | add_wait_queue(&port->port.open_wait, &wait); | 875 | add_wait_queue(&port->open_wait, &wait); |
868 | 876 | ||
869 | spin_lock_irqsave(&card->card_lock, flags); | 877 | spin_lock_irqsave(&card->card_lock, flags); |
870 | if (!tty_hung_up_p(filp)) | 878 | if (!tty_hung_up_p(filp)) |
871 | port->port.count--; | 879 | port->count--; |
872 | port->port.blocked_open++; | 880 | port->blocked_open++; |
873 | spin_unlock_irqrestore(&card->card_lock, flags); | 881 | spin_unlock_irqrestore(&card->card_lock, flags); |
874 | 882 | ||
875 | while (1) { | 883 | while (1) { |
876 | raise_dtr_rts(port); | 884 | raise_dtr_rts(ip); |
877 | 885 | ||
878 | set_current_state(TASK_INTERRUPTIBLE); | 886 | set_current_state(TASK_INTERRUPTIBLE); |
879 | if (tty_hung_up_p(filp) || !(port->port.flags & ASYNC_INITIALIZED)) { | 887 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { |
880 | if (port->port.flags & ASYNC_HUP_NOTIFY) | 888 | if (port->flags & ASYNC_HUP_NOTIFY) |
881 | retval = -EAGAIN; | 889 | retval = -EAGAIN; |
882 | else | 890 | else |
883 | retval = -ERESTARTSYS; | 891 | retval = -ERESTARTSYS; |
884 | break; | 892 | break; |
885 | } | 893 | } |
886 | if (!(port->port.flags & ASYNC_CLOSING) && | 894 | cd = tty_port_carrier_raised(port); |
887 | (do_clocal || (port->status & ISI_DCD))) { | 895 | if (!(port->flags & ASYNC_CLOSING) && |
896 | (do_clocal || cd)) | ||
888 | break; | 897 | break; |
889 | } | ||
890 | if (signal_pending(current)) { | 898 | if (signal_pending(current)) { |
891 | retval = -ERESTARTSYS; | 899 | retval = -ERESTARTSYS; |
892 | break; | 900 | break; |
@@ -894,15 +902,15 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
894 | schedule(); | 902 | schedule(); |
895 | } | 903 | } |
896 | set_current_state(TASK_RUNNING); | 904 | set_current_state(TASK_RUNNING); |
897 | remove_wait_queue(&port->port.open_wait, &wait); | 905 | remove_wait_queue(&port->open_wait, &wait); |
898 | spin_lock_irqsave(&card->card_lock, flags); | 906 | spin_lock_irqsave(&card->card_lock, flags); |
899 | if (!tty_hung_up_p(filp)) | 907 | if (!tty_hung_up_p(filp)) |
900 | port->port.count++; | 908 | port->count++; |
901 | port->port.blocked_open--; | 909 | port->blocked_open--; |
902 | spin_unlock_irqrestore(&card->card_lock, flags); | 910 | spin_unlock_irqrestore(&card->card_lock, flags); |
903 | if (retval) | 911 | if (retval) |
904 | return retval; | 912 | return retval; |
905 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | 913 | port->flags |= ASYNC_NORMAL_ACTIVE; |
906 | return 0; | 914 | return 0; |
907 | } | 915 | } |
908 | 916 | ||
@@ -1452,6 +1460,10 @@ static const struct tty_operations isicom_ops = { | |||
1452 | .break_ctl = isicom_send_break, | 1460 | .break_ctl = isicom_send_break, |
1453 | }; | 1461 | }; |
1454 | 1462 | ||
1463 | static const struct tty_port_operations isicom_port_ops = { | ||
1464 | .carrier_raised = isicom_carrier_raised, | ||
1465 | }; | ||
1466 | |||
1455 | static int __devinit reset_card(struct pci_dev *pdev, | 1467 | static int __devinit reset_card(struct pci_dev *pdev, |
1456 | const unsigned int card, unsigned int *signature) | 1468 | const unsigned int card, unsigned int *signature) |
1457 | { | 1469 | { |
@@ -1794,6 +1806,7 @@ static int __init isicom_init(void) | |||
1794 | spin_lock_init(&isi_card[idx].card_lock); | 1806 | spin_lock_init(&isi_card[idx].card_lock); |
1795 | for (channel = 0; channel < 16; channel++, port++) { | 1807 | for (channel = 0; channel < 16; channel++, port++) { |
1796 | tty_port_init(&port->port); | 1808 | tty_port_init(&port->port); |
1809 | port->port.ops = &isicom_port_ops; | ||
1797 | port->magic = ISICOM_MAGIC; | 1810 | port->magic = ISICOM_MAGIC; |
1798 | port->card = &isi_card[idx]; | 1811 | port->card = &isi_card[idx]; |
1799 | port->channel = channel; | 1812 | port->channel = channel; |