aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char')
-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
4 files changed, 50 insertions, 17 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