aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-06-16 15:03:43 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-16 15:03:43 -0400
commit15bdb5652689d51cc0316de61774d2732472d9e1 (patch)
treefb79ca4d6bf8d46c466bc1f1c085b7c3ee6c7683 /drivers
parent98523d4630865c407d3787fd592e5e399488b93b (diff)
parent1a2c4b3147ac0645605d6def2855478861d9361b (diff)
Merge branch 'serial'
* serial: imx: Check for NULL pointer deref before calling tty_encode_baud_rate atmel_serial: fix hang in set_termios when crtscts is enabled MAINTAINERS: update 8250 section, give Alan Cox a name tty: fix sanity check pty: Narrow the race on ldisc locking tty: fix unused warning when TCGETX is not defined ldisc: debug aids ldisc: Make sure the ldisc isn't active when we close it tty: Fix leaks introduced by the shift to separate ldisc objects Fix conflicts in drivers/char/pty.c due to earlier version of the ldisc race narrowing.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/pty.c57
-rw-r--r--drivers/char/tty_io.c2
-rw-r--r--drivers/char/tty_ioctl.c5
-rw-r--r--drivers/char/tty_ldisc.c3
-rw-r--r--drivers/serial/atmel_serial.c8
-rw-r--r--drivers/serial/imx.c12
6 files changed, 62 insertions, 25 deletions
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 3910ce112a95..daebe1ba43d4 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -95,23 +95,34 @@ static void pty_unthrottle(struct tty_struct *tty)
95 * a count. 95 * a count.
96 * 96 *
97 * FIXME: Our pty_write method is called with our ldisc lock held but 97 * FIXME: Our pty_write method is called with our ldisc lock held but
98 * not our partners. We can't just take the other one blindly without 98 * not our partners. We can't just wait on the other one blindly without
99 * risking deadlocks. 99 * risking deadlocks. At some point when everything has settled down we need
100 * to look into making pty_write at least able to sleep over an ldisc change.
101 *
102 * The return on no ldisc is a bit counter intuitive but the logic works
103 * like this. During an ldisc change the other end will flush its buffers. We
104 * thus return the full length which is identical to the case where we had
105 * proper locking and happened to queue the bytes just before the flush during
106 * the ldisc change.
100 */ 107 */
101static int pty_write(struct tty_struct *tty, const unsigned char *buf, 108static int pty_write(struct tty_struct *tty, const unsigned char *buf,
102 int count) 109 int count)
103{ 110{
104 struct tty_struct *to = tty->link; 111 struct tty_struct *to = tty->link;
105 int c; 112 struct tty_ldisc *ld;
113 int c = count;
106 114
107 if (!to || !to->ldisc || tty->stopped) 115 if (!to || tty->stopped)
108 return 0; 116 return 0;
109 117 ld = tty_ldisc_ref(to);
110 c = to->receive_room; 118
111 if (c > count) 119 if (ld) {
112 c = count; 120 c = to->receive_room;
113 to->ldisc->ops->receive_buf(to, buf, NULL, c); 121 if (c > count)
114 122 c = count;
123 ld->ops->receive_buf(to, buf, NULL, c);
124 tty_ldisc_deref(ld);
125 }
115 return c; 126 return c;
116} 127}
117 128
@@ -145,14 +156,23 @@ static int pty_write_room(struct tty_struct *tty)
145static int pty_chars_in_buffer(struct tty_struct *tty) 156static int pty_chars_in_buffer(struct tty_struct *tty)
146{ 157{
147 struct tty_struct *to = tty->link; 158 struct tty_struct *to = tty->link;
148 int count; 159 struct tty_ldisc *ld;
160 int count = 0;
149 161
150 /* We should get the line discipline lock for "tty->link" */ 162 /* We should get the line discipline lock for "tty->link" */
151 if (!to || !to->ldisc || !to->ldisc->ops->chars_in_buffer) 163 if (!to)
164 return 0;
165 /* We cannot take a sleeping reference here without deadlocking with
166 an ldisc change - but it doesn't really matter */
167 ld = tty_ldisc_ref(to);
168 if (ld == NULL)
152 return 0; 169 return 0;
153 170
154 /* The ldisc must report 0 if no characters available to be read */ 171 /* The ldisc must report 0 if no characters available to be read */
155 count = to->ldisc->ops->chars_in_buffer(to); 172 if (ld->ops->chars_in_buffer)
173 count = ld->ops->chars_in_buffer(to);
174
175 tty_ldisc_deref(ld);
156 176
157 if (tty->driver->subtype == PTY_TYPE_SLAVE) 177 if (tty->driver->subtype == PTY_TYPE_SLAVE)
158 return count; 178 return count;
@@ -182,12 +202,19 @@ static void pty_flush_buffer(struct tty_struct *tty)
182{ 202{
183 struct tty_struct *to = tty->link; 203 struct tty_struct *to = tty->link;
184 unsigned long flags; 204 unsigned long flags;
205 struct tty_ldisc *ld;
206
207 if (!to)
208 return;
209 ld = tty_ldisc_ref(to);
185 210
186 if (!to || !to->ldisc) 211 /* The other end is changing discipline */
212 if (!ld)
187 return; 213 return;
188 214
189 if (to->ldisc->ops->flush_buffer) 215 if (ld->ops->flush_buffer)
190 to->ldisc->ops->flush_buffer(to); 216 to->ldisc->ops->flush_buffer(to);
217 tty_ldisc_deref(ld);
191 218
192 if (to->packet) { 219 if (to->packet) {
193 spin_lock_irqsave(&tty->ctrl_lock, flags); 220 spin_lock_irqsave(&tty->ctrl_lock, flags);
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 939e198d7670..a3afa0c387cd 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1263,7 +1263,9 @@ static int tty_reopen(struct tty_struct *tty)
1263 tty->count++; 1263 tty->count++;
1264 tty->driver = driver; /* N.B. why do this every time?? */ 1264 tty->driver = driver; /* N.B. why do this every time?? */
1265 1265
1266 mutex_lock(&tty->ldisc_mutex);
1266 WARN_ON(!test_bit(TTY_LDISC, &tty->flags)); 1267 WARN_ON(!test_bit(TTY_LDISC, &tty->flags));
1268 mutex_unlock(&tty->ldisc_mutex);
1267 1269
1268 return 0; 1270 return 0;
1269} 1271}
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 8116bb1c8f80..b24f6c6a1ea3 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -947,7 +947,6 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
947 void __user *p = (void __user *)arg; 947 void __user *p = (void __user *)arg;
948 int ret = 0; 948 int ret = 0;
949 struct ktermios kterm; 949 struct ktermios kterm;
950 struct termiox ktermx;
951 950
952 if (tty->driver->type == TTY_DRIVER_TYPE_PTY && 951 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
953 tty->driver->subtype == PTY_TYPE_MASTER) 952 tty->driver->subtype == PTY_TYPE_MASTER)
@@ -1049,7 +1048,8 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
1049 return ret; 1048 return ret;
1050#endif 1049#endif
1051#ifdef TCGETX 1050#ifdef TCGETX
1052 case TCGETX: 1051 case TCGETX: {
1052 struct termiox ktermx;
1053 if (real_tty->termiox == NULL) 1053 if (real_tty->termiox == NULL)
1054 return -EINVAL; 1054 return -EINVAL;
1055 mutex_lock(&real_tty->termios_mutex); 1055 mutex_lock(&real_tty->termios_mutex);
@@ -1058,6 +1058,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
1058 if (copy_to_user(p, &ktermx, sizeof(struct termiox))) 1058 if (copy_to_user(p, &ktermx, sizeof(struct termiox)))
1059 ret = -EFAULT; 1059 ret = -EFAULT;
1060 return ret; 1060 return ret;
1061 }
1061 case TCSETX: 1062 case TCSETX:
1062 return set_termiox(real_tty, p, 0); 1063 return set_termiox(real_tty, p, 0);
1063 case TCSETXW: 1064 case TCSETXW:
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
index 94b3e06d73ec..a19e935847b0 100644
--- a/drivers/char/tty_ldisc.c
+++ b/drivers/char/tty_ldisc.c
@@ -207,6 +207,7 @@ static void tty_ldisc_put(struct tty_ldisc *ld)
207 ldo->refcount--; 207 ldo->refcount--;
208 module_put(ldo->owner); 208 module_put(ldo->owner);
209 spin_unlock_irqrestore(&tty_ldisc_lock, flags); 209 spin_unlock_irqrestore(&tty_ldisc_lock, flags);
210 WARN_ON(ld->refcount);
210 kfree(ld); 211 kfree(ld);
211} 212}
212 213
@@ -793,6 +794,8 @@ void tty_ldisc_hangup(struct tty_struct *tty)
793 /* Avoid racing set_ldisc */ 794 /* Avoid racing set_ldisc */
794 mutex_lock(&tty->ldisc_mutex); 795 mutex_lock(&tty->ldisc_mutex);
795 /* Switch back to N_TTY */ 796 /* Switch back to N_TTY */
797 tty_ldisc_halt(tty);
798 tty_ldisc_wait_idle(tty);
796 tty_ldisc_reinit(tty); 799 tty_ldisc_reinit(tty);
797 /* At this point we have a closed ldisc and we want to 800 /* At this point we have a closed ldisc and we want to
798 reopen it. We could defer this to the next open but 801 reopen it. We could defer this to the next open but
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index b3497d7e5354..338b15c0a548 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -1104,11 +1104,13 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
1104 /* update the per-port timeout */ 1104 /* update the per-port timeout */
1105 uart_update_timeout(port, termios->c_cflag, baud); 1105 uart_update_timeout(port, termios->c_cflag, baud);
1106 1106
1107 /* save/disable interrupts and drain transmitter */ 1107 /*
1108 * save/disable interrupts. The tty layer will ensure that the
1109 * transmitter is empty if requested by the caller, so there's
1110 * no need to wait for it here.
1111 */
1108 imr = UART_GET_IMR(port); 1112 imr = UART_GET_IMR(port);
1109 UART_PUT_IDR(port, -1); 1113 UART_PUT_IDR(port, -1);
1110 while (!(UART_GET_CSR(port) & ATMEL_US_TXEMPTY))
1111 cpu_relax();
1112 1114
1113 /* disable receiver and transmitter */ 1115 /* disable receiver and transmitter */
1114 UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS); 1116 UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 285b414f3054..5d7b58f1fe42 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -924,11 +924,13 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
924 rational_best_approximation(16 * div * baud, sport->port.uartclk, 924 rational_best_approximation(16 * div * baud, sport->port.uartclk,
925 1 << 16, 1 << 16, &num, &denom); 925 1 << 16, 1 << 16, &num, &denom);
926 926
927 tdiv64 = sport->port.uartclk; 927 if (port->info && port->info->port.tty) {
928 tdiv64 *= num; 928 tdiv64 = sport->port.uartclk;
929 do_div(tdiv64, denom * 16 * div); 929 tdiv64 *= num;
930 tty_encode_baud_rate(sport->port.info->port.tty, 930 do_div(tdiv64, denom * 16 * div);
931 (speed_t)tdiv64, (speed_t)tdiv64); 931 tty_encode_baud_rate(sport->port.info->port.tty,
932 (speed_t)tdiv64, (speed_t)tdiv64);
933 }
932 934
933 num -= 1; 935 num -= 1;
934 denom -= 1; 936 denom -= 1;