aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2009-01-02 08:45:26 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-02 13:19:38 -0500
commit3e61696bdc2103107674b06d0daf30b76193e922 (patch)
treecc4f2b7b7b0ce2162613bb9d3cf819f6bbfd3628
parent5d951fb458f847e5485b5251597fbf326000bb3b (diff)
isicom: redo locking to use tty port locks
This helps set the basis for moving block_til_ready into common code. We also introduce a tty_port_hangup helper as this will also be generally needed. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/char/isicom.c35
-rw-r--r--drivers/char/synclinkmp.c20
-rw-r--r--drivers/char/tty_port.c24
-rw-r--r--include/linux/tty.h1
4 files changed, 54 insertions, 26 deletions
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index a449449e301c..db53db91ae4a 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -841,7 +841,6 @@ static int isicom_carrier_raised(struct tty_port *port)
841static int block_til_ready(struct tty_struct *tty, struct file *filp, 841static int block_til_ready(struct tty_struct *tty, struct file *filp,
842 struct isi_port *ip) 842 struct isi_port *ip)
843{ 843{
844 struct isi_board *card = ip->card;
845 struct tty_port *port = &ip->port; 844 struct tty_port *port = &ip->port;
846 int do_clocal = 0, retval; 845 int do_clocal = 0, retval;
847 unsigned long flags; 846 unsigned long flags;
@@ -876,11 +875,11 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
876 retval = 0; 875 retval = 0;
877 add_wait_queue(&port->open_wait, &wait); 876 add_wait_queue(&port->open_wait, &wait);
878 877
879 spin_lock_irqsave(&card->card_lock, flags); 878 spin_lock_irqsave(&port->lock, flags);
880 if (!tty_hung_up_p(filp)) 879 if (!tty_hung_up_p(filp))
881 port->count--; 880 port->count--;
882 port->blocked_open++; 881 port->blocked_open++;
883 spin_unlock_irqrestore(&card->card_lock, flags); 882 spin_unlock_irqrestore(&port->lock, flags);
884 883
885 while (1) { 884 while (1) {
886 tty_port_raise_dtr_rts(port); 885 tty_port_raise_dtr_rts(port);
@@ -905,14 +904,13 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
905 } 904 }
906 set_current_state(TASK_RUNNING); 905 set_current_state(TASK_RUNNING);
907 remove_wait_queue(&port->open_wait, &wait); 906 remove_wait_queue(&port->open_wait, &wait);
908 spin_lock_irqsave(&card->card_lock, flags); 907 spin_lock_irqsave(&port->lock, flags);
909 if (!tty_hung_up_p(filp)) 908 if (!tty_hung_up_p(filp))
910 port->count++; 909 port->count++;
911 port->blocked_open--; 910 port->blocked_open--;
912 spin_unlock_irqrestore(&card->card_lock, flags); 911 if (retval == 0)
913 if (retval) 912 port->flags |= ASYNC_NORMAL_ACTIVE;
914 return retval; 913 spin_unlock_irqrestore(&port->lock, flags);
915 port->flags |= ASYNC_NORMAL_ACTIVE;
916 return 0; 914 return 0;
917} 915}
918 916
@@ -1034,9 +1032,9 @@ static void isicom_close(struct tty_struct *tty, struct file *filp)
1034 1032
1035 pr_dbg("Close start!!!.\n"); 1033 pr_dbg("Close start!!!.\n");
1036 1034
1037 spin_lock_irqsave(&card->card_lock, flags); 1035 spin_lock_irqsave(&port->port.lock, flags);
1038 if (tty_hung_up_p(filp)) { 1036 if (tty_hung_up_p(filp)) {
1039 spin_unlock_irqrestore(&card->card_lock, flags); 1037 spin_unlock_irqrestore(&port->port.lock, flags);
1040 return; 1038 return;
1041 } 1039 }
1042 1040
@@ -1054,12 +1052,12 @@ static void isicom_close(struct tty_struct *tty, struct file *filp)
1054 } 1052 }
1055 1053
1056 if (port->port.count) { 1054 if (port->port.count) {
1057 spin_unlock_irqrestore(&card->card_lock, flags); 1055 spin_unlock_irqrestore(&port->port.lock, flags);
1058 return; 1056 return;
1059 } 1057 }
1060 port->port.flags |= ASYNC_CLOSING; 1058 port->port.flags |= ASYNC_CLOSING;
1061 tty->closing = 1; 1059 tty->closing = 1;
1062 spin_unlock_irqrestore(&card->card_lock, flags); 1060 spin_unlock_irqrestore(&port->port.lock, flags);
1063 1061
1064 if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) 1062 if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
1065 tty_wait_until_sent(tty, port->port.closing_wait); 1063 tty_wait_until_sent(tty, port->port.closing_wait);
@@ -1076,22 +1074,22 @@ static void isicom_close(struct tty_struct *tty, struct file *filp)
1076 isicom_flush_buffer(tty); 1074 isicom_flush_buffer(tty);
1077 tty_ldisc_flush(tty); 1075 tty_ldisc_flush(tty);
1078 1076
1079 spin_lock_irqsave(&card->card_lock, flags); 1077 spin_lock_irqsave(&port->port.lock, flags);
1080 tty->closing = 0; 1078 tty->closing = 0;
1081 1079
1082 if (port->port.blocked_open) { 1080 if (port->port.blocked_open) {
1083 spin_unlock_irqrestore(&card->card_lock, flags); 1081 spin_unlock_irqrestore(&port->port.lock, flags);
1084 if (port->port.close_delay) { 1082 if (port->port.close_delay) {
1085 pr_dbg("scheduling until time out.\n"); 1083 pr_dbg("scheduling until time out.\n");
1086 msleep_interruptible( 1084 msleep_interruptible(
1087 jiffies_to_msecs(port->port.close_delay)); 1085 jiffies_to_msecs(port->port.close_delay));
1088 } 1086 }
1089 spin_lock_irqsave(&card->card_lock, flags); 1087 spin_lock_irqsave(&port->port.lock, flags);
1090 wake_up_interruptible(&port->port.open_wait); 1088 wake_up_interruptible(&port->port.open_wait);
1091 } 1089 }
1092 port->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); 1090 port->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
1093 wake_up_interruptible(&port->port.close_wait); 1091 wake_up_interruptible(&port->port.close_wait);
1094 spin_unlock_irqrestore(&card->card_lock, flags); 1092 spin_unlock_irqrestore(&port->port.lock, flags);
1095} 1093}
1096 1094
1097/* write et all */ 1095/* write et all */
@@ -1430,10 +1428,7 @@ static void isicom_hangup(struct tty_struct *tty)
1430 isicom_shutdown_port(port); 1428 isicom_shutdown_port(port);
1431 spin_unlock_irqrestore(&port->card->card_lock, flags); 1429 spin_unlock_irqrestore(&port->card->card_lock, flags);
1432 1430
1433 port->port.count = 0; 1431 tty_port_hangup(&port->port);
1434 port->port.flags &= ~ASYNC_NORMAL_ACTIVE;
1435 tty_port_tty_set(&port->port, NULL);
1436 wake_up_interruptible(&port->port.open_wait);
1437} 1432}
1438 1433
1439 1434
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index fcf1ec77450d..1f5c21ec4b14 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -3331,6 +3331,17 @@ static int carrier_raised(struct tty_port *port)
3331 return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; 3331 return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
3332} 3332}
3333 3333
3334static void raise_dtr_rts(struct tty_port *port)
3335{
3336 SLMP_INFO *info = container_of(port, SLMP_INFO, port);
3337 unsigned long flags;
3338
3339 spin_lock_irqsave(&info->lock,flags);
3340 info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
3341 set_signals(info);
3342 spin_unlock_irqrestore(&info->lock,flags);
3343}
3344
3334/* Block the current process until the specified port is ready to open. 3345/* Block the current process until the specified port is ready to open.
3335 */ 3346 */
3336static int block_til_ready(struct tty_struct *tty, struct file *filp, 3347static int block_til_ready(struct tty_struct *tty, struct file *filp,
@@ -3381,12 +3392,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
3381 port->blocked_open++; 3392 port->blocked_open++;
3382 3393
3383 while (1) { 3394 while (1) {
3384 if ((tty->termios->c_cflag & CBAUD)) { 3395 if (tty->termios->c_cflag & CBAUD)
3385 spin_lock_irqsave(&info->lock,flags); 3396 tty_port_raise_dtr_rts(port);
3386 info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
3387 set_signals(info);
3388 spin_unlock_irqrestore(&info->lock,flags);
3389 }
3390 3397
3391 set_current_state(TASK_INTERRUPTIBLE); 3398 set_current_state(TASK_INTERRUPTIBLE);
3392 3399
@@ -3793,6 +3800,7 @@ static void add_device(SLMP_INFO *info)
3793 3800
3794static const struct tty_port_operations port_ops = { 3801static const struct tty_port_operations port_ops = {
3795 .carrier_raised = carrier_raised, 3802 .carrier_raised = carrier_raised,
3803 .raise_dtr_rts = raise_dtr_rts,
3796}; 3804};
3797 3805
3798/* Allocate and initialize a device instance structure 3806/* Allocate and initialize a device instance structure
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c
index 0557b6384747..9f418bca4a22 100644
--- a/drivers/char/tty_port.c
+++ b/drivers/char/tty_port.c
@@ -7,6 +7,7 @@
7#include <linux/tty.h> 7#include <linux/tty.h>
8#include <linux/tty_driver.h> 8#include <linux/tty_driver.h>
9#include <linux/tty_flip.h> 9#include <linux/tty_flip.h>
10#include <linux/serial.h>
10#include <linux/timer.h> 11#include <linux/timer.h>
11#include <linux/string.h> 12#include <linux/string.h>
12#include <linux/slab.h> 13#include <linux/slab.h>
@@ -96,6 +97,29 @@ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
96EXPORT_SYMBOL(tty_port_tty_set); 97EXPORT_SYMBOL(tty_port_tty_set);
97 98
98/** 99/**
100 * tty_port_hangup - hangup helper
101 * @port: tty port
102 *
103 * Perform port level tty hangup flag and count changes. Drop the tty
104 * reference.
105 */
106
107void tty_port_hangup(struct tty_port *port)
108{
109 unsigned long flags;
110
111 spin_lock_irqsave(&port->lock, flags);
112 port->count = 0;
113 port->flags &= ~ASYNC_NORMAL_ACTIVE;
114 if (port->tty)
115 tty_kref_put(port->tty);
116 port->tty = NULL;
117 spin_unlock_irqrestore(&port->lock, flags);
118 wake_up_interruptible(&port->open_wait);
119}
120EXPORT_SYMBOL(tty_port_hangup);
121
122/**
99 * tty_port_carrier_raised - carrier raised check 123 * tty_port_carrier_raised - carrier raised check
100 * @port: tty port 124 * @port: tty port
101 * 125 *
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 5001bbcacff6..a1a93140e6e4 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -438,6 +438,7 @@ extern struct tty_struct *tty_port_tty_get(struct tty_port *port);
438extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty); 438extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty);
439extern int tty_port_carrier_raised(struct tty_port *port); 439extern int tty_port_carrier_raised(struct tty_port *port);
440extern void tty_port_raise_dtr_rts(struct tty_port *port); 440extern void tty_port_raise_dtr_rts(struct tty_port *port);
441extern void tty_port_hangup(struct tty_port *port);
441 442
442extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc); 443extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc);
443extern int tty_unregister_ldisc(int disc); 444extern int tty_unregister_ldisc(int disc);