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/rocket.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/rocket.c')
-rw-r--r-- | drivers/char/rocket.c | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 584d791e84a6..4a4110e703a5 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
@@ -135,6 +135,7 @@ static int rcktpt_type[NUM_BOARDS]; | |||
135 | static int is_PCI[NUM_BOARDS]; | 135 | static int is_PCI[NUM_BOARDS]; |
136 | static rocketModel_t rocketModel[NUM_BOARDS]; | 136 | static rocketModel_t rocketModel[NUM_BOARDS]; |
137 | static int max_board; | 137 | static int max_board; |
138 | static const struct tty_port_operations rocket_port_ops; | ||
138 | 139 | ||
139 | /* | 140 | /* |
140 | * The following arrays define the interrupt bits corresponding to each AIOP. | 141 | * The following arrays define the interrupt bits corresponding to each AIOP. |
@@ -649,9 +650,8 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) | |||
649 | info->board = board; | 650 | info->board = board; |
650 | info->aiop = aiop; | 651 | info->aiop = aiop; |
651 | info->chan = chan; | 652 | info->chan = chan; |
652 | info->port.closing_wait = 3000; | 653 | tty_port_init(&info->port); |
653 | info->port.close_delay = 50; | 654 | info->port.ops = &rocket_port_ops; |
654 | init_waitqueue_head(&info->port.open_wait); | ||
655 | init_completion(&info->close_wait); | 655 | init_completion(&info->close_wait); |
656 | info->flags &= ~ROCKET_MODE_MASK; | 656 | info->flags &= ~ROCKET_MODE_MASK; |
657 | switch (pc104[board][line]) { | 657 | switch (pc104[board][line]) { |
@@ -864,11 +864,18 @@ static void configure_r_port(struct r_port *info, | |||
864 | } | 864 | } |
865 | } | 865 | } |
866 | 866 | ||
867 | static int carrier_raised(struct tty_port *port) | ||
868 | { | ||
869 | struct r_port *info = container_of(port, struct r_port, port); | ||
870 | return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0; | ||
871 | } | ||
872 | |||
867 | /* info->port.count is considered critical, protected by spinlocks. */ | 873 | /* info->port.count is considered critical, protected by spinlocks. */ |
868 | static int block_til_ready(struct tty_struct *tty, struct file *filp, | 874 | static int block_til_ready(struct tty_struct *tty, struct file *filp, |
869 | struct r_port *info) | 875 | struct r_port *info) |
870 | { | 876 | { |
871 | DECLARE_WAITQUEUE(wait, current); | 877 | DECLARE_WAITQUEUE(wait, current); |
878 | struct tty_port *port = &info->port; | ||
872 | int retval; | 879 | int retval; |
873 | int do_clocal = 0, extra_count = 0; | 880 | int do_clocal = 0, extra_count = 0; |
874 | unsigned long flags; | 881 | unsigned long flags; |
@@ -898,13 +905,13 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
898 | 905 | ||
899 | /* | 906 | /* |
900 | * Block waiting for the carrier detect and the line to become free. While we are in | 907 | * Block waiting for the carrier detect and the line to become free. While we are in |
901 | * this loop, info->port.count is dropped by one, so that rp_close() knows when to free things. | 908 | * this loop, port->count is dropped by one, so that rp_close() knows when to free things. |
902 | * We restore it upon exit, either normal or abnormal. | 909 | * We restore it upon exit, either normal or abnormal. |
903 | */ | 910 | */ |
904 | retval = 0; | 911 | retval = 0; |
905 | add_wait_queue(&info->port.open_wait, &wait); | 912 | add_wait_queue(&port->open_wait, &wait); |
906 | #ifdef ROCKET_DEBUG_OPEN | 913 | #ifdef ROCKET_DEBUG_OPEN |
907 | printk(KERN_INFO "block_til_ready before block: ttyR%d, count = %d\n", info->line, info->port.count); | 914 | printk(KERN_INFO "block_til_ready before block: ttyR%d, count = %d\n", info->line, port->count); |
908 | #endif | 915 | #endif |
909 | spin_lock_irqsave(&info->slock, flags); | 916 | spin_lock_irqsave(&info->slock, flags); |
910 | 917 | ||
@@ -913,10 +920,10 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
913 | #else | 920 | #else |
914 | if (!tty_hung_up_p(filp)) { | 921 | if (!tty_hung_up_p(filp)) { |
915 | extra_count = 1; | 922 | extra_count = 1; |
916 | info->port.count--; | 923 | port->count--; |
917 | } | 924 | } |
918 | #endif | 925 | #endif |
919 | info->port.blocked_open++; | 926 | port->blocked_open++; |
920 | 927 | ||
921 | spin_unlock_irqrestore(&info->slock, flags); | 928 | spin_unlock_irqrestore(&info->slock, flags); |
922 | 929 | ||
@@ -933,7 +940,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
933 | retval = -ERESTARTSYS; | 940 | retval = -ERESTARTSYS; |
934 | break; | 941 | break; |
935 | } | 942 | } |
936 | if (!(info->flags & ROCKET_CLOSING) && (do_clocal || (sGetChanStatusLo(&info->channel) & CD_ACT))) | 943 | if (!(info->flags & ROCKET_CLOSING) && |
944 | (do_clocal || tty_port_carrier_raised(port))) | ||
937 | break; | 945 | break; |
938 | if (signal_pending(current)) { | 946 | if (signal_pending(current)) { |
939 | retval = -ERESTARTSYS; | 947 | retval = -ERESTARTSYS; |
@@ -941,24 +949,24 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
941 | } | 949 | } |
942 | #ifdef ROCKET_DEBUG_OPEN | 950 | #ifdef ROCKET_DEBUG_OPEN |
943 | printk(KERN_INFO "block_til_ready blocking: ttyR%d, count = %d, flags=0x%0x\n", | 951 | printk(KERN_INFO "block_til_ready blocking: ttyR%d, count = %d, flags=0x%0x\n", |
944 | info->line, info->port.count, info->flags); | 952 | info->line, port->count, info->flags); |
945 | #endif | 953 | #endif |
946 | schedule(); /* Don't hold spinlock here, will hang PC */ | 954 | schedule(); /* Don't hold spinlock here, will hang PC */ |
947 | } | 955 | } |
948 | __set_current_state(TASK_RUNNING); | 956 | __set_current_state(TASK_RUNNING); |
949 | remove_wait_queue(&info->port.open_wait, &wait); | 957 | remove_wait_queue(&port->open_wait, &wait); |
950 | 958 | ||
951 | spin_lock_irqsave(&info->slock, flags); | 959 | spin_lock_irqsave(&info->slock, flags); |
952 | 960 | ||
953 | if (extra_count) | 961 | if (extra_count) |
954 | info->port.count++; | 962 | port->count++; |
955 | info->port.blocked_open--; | 963 | port->blocked_open--; |
956 | 964 | ||
957 | spin_unlock_irqrestore(&info->slock, flags); | 965 | spin_unlock_irqrestore(&info->slock, flags); |
958 | 966 | ||
959 | #ifdef ROCKET_DEBUG_OPEN | 967 | #ifdef ROCKET_DEBUG_OPEN |
960 | printk(KERN_INFO "block_til_ready after blocking: ttyR%d, count = %d\n", | 968 | printk(KERN_INFO "block_til_ready after blocking: ttyR%d, count = %d\n", |
961 | info->line, info->port.count); | 969 | info->line, port->count); |
962 | #endif | 970 | #endif |
963 | if (retval) | 971 | if (retval) |
964 | return retval; | 972 | return retval; |
@@ -2371,6 +2379,10 @@ static const struct tty_operations rocket_ops = { | |||
2371 | .tiocmset = rp_tiocmset, | 2379 | .tiocmset = rp_tiocmset, |
2372 | }; | 2380 | }; |
2373 | 2381 | ||
2382 | static const struct tty_port_operations rocket_port_ops = { | ||
2383 | .carrier_raised = carrier_raised, | ||
2384 | }; | ||
2385 | |||
2374 | /* | 2386 | /* |
2375 | * The module "startup" routine; it's run when the module is loaded. | 2387 | * The module "startup" routine; it's run when the module is loaded. |
2376 | */ | 2388 | */ |