aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/n_tty.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/n_tty.c')
-rw-r--r--drivers/char/n_tty.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 0c09409fa45d..001d9d875387 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -183,22 +183,24 @@ static void reset_buffer_flags(struct tty_struct *tty)
183 * at hangup) or when the N_TTY line discipline internally has to 183 * at hangup) or when the N_TTY line discipline internally has to
184 * clean the pending queue (for example some signals). 184 * clean the pending queue (for example some signals).
185 * 185 *
186 * FIXME: tty->ctrl_status is not spinlocked and relies on 186 * Locking: ctrl_lock
187 * lock_kernel() still.
188 */ 187 */
189 188
190static void n_tty_flush_buffer(struct tty_struct *tty) 189static void n_tty_flush_buffer(struct tty_struct *tty)
191{ 190{
191 unsigned long flags;
192 /* clear everything and unthrottle the driver */ 192 /* clear everything and unthrottle the driver */
193 reset_buffer_flags(tty); 193 reset_buffer_flags(tty);
194 194
195 if (!tty->link) 195 if (!tty->link)
196 return; 196 return;
197 197
198 spin_lock_irqsave(&tty->ctrl_lock, flags);
198 if (tty->link->packet) { 199 if (tty->link->packet) {
199 tty->ctrl_status |= TIOCPKT_FLUSHREAD; 200 tty->ctrl_status |= TIOCPKT_FLUSHREAD;
200 wake_up_interruptible(&tty->link->read_wait); 201 wake_up_interruptible(&tty->link->read_wait);
201 } 202 }
203 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
202} 204}
203 205
204/** 206/**
@@ -264,7 +266,7 @@ static inline int is_continuation(unsigned char c, struct tty_struct *tty)
264 * relevant in the world today. If you ever need them, add them here. 266 * relevant in the world today. If you ever need them, add them here.
265 * 267 *
266 * Called from both the receive and transmit sides and can be called 268 * Called from both the receive and transmit sides and can be called
267 * re-entrantly. Relies on lock_kernel() still. 269 * re-entrantly. Relies on lock_kernel() for tty->column state.
268 */ 270 */
269 271
270static int opost(unsigned char c, struct tty_struct *tty) 272static int opost(unsigned char c, struct tty_struct *tty)
@@ -275,6 +277,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
275 if (!space) 277 if (!space)
276 return -1; 278 return -1;
277 279
280 lock_kernel();
278 if (O_OPOST(tty)) { 281 if (O_OPOST(tty)) {
279 switch (c) { 282 switch (c) {
280 case '\n': 283 case '\n':
@@ -323,6 +326,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
323 } 326 }
324 } 327 }
325 tty->driver->put_char(tty, c); 328 tty->driver->put_char(tty, c);
329 unlock_kernel();
326 return 0; 330 return 0;
327} 331}
328 332
@@ -337,7 +341,8 @@ static int opost(unsigned char c, struct tty_struct *tty)
337 * the simple cases normally found and helps to generate blocks of 341 * the simple cases normally found and helps to generate blocks of
338 * symbols for the console driver and thus improve performance. 342 * symbols for the console driver and thus improve performance.
339 * 343 *
340 * Called from write_chan under the tty layer write lock. 344 * Called from write_chan under the tty layer write lock. Relies
345 * on lock_kernel for the tty->column state.
341 */ 346 */
342 347
343static ssize_t opost_block(struct tty_struct *tty, 348static ssize_t opost_block(struct tty_struct *tty,
@@ -353,6 +358,7 @@ static ssize_t opost_block(struct tty_struct *tty,
353 if (nr > space) 358 if (nr > space)
354 nr = space; 359 nr = space;
355 360
361 lock_kernel();
356 for (i = 0, cp = buf; i < nr; i++, cp++) { 362 for (i = 0, cp = buf; i < nr; i++, cp++) {
357 switch (*cp) { 363 switch (*cp) {
358 case '\n': 364 case '\n':
@@ -387,6 +393,7 @@ break_out:
387 if (tty->driver->flush_chars) 393 if (tty->driver->flush_chars)
388 tty->driver->flush_chars(tty); 394 tty->driver->flush_chars(tty);
389 i = tty->driver->write(tty, buf, i); 395 i = tty->driver->write(tty, buf, i);
396 unlock_kernel();
390 return i; 397 return i;
391} 398}
392 399
@@ -1194,6 +1201,11 @@ extern ssize_t redirected_tty_write(struct file *, const char __user *,
1194 * Perform job control management checks on this file/tty descriptor 1201 * Perform job control management checks on this file/tty descriptor
1195 * and if appropriate send any needed signals and return a negative 1202 * and if appropriate send any needed signals and return a negative
1196 * error code if action should be taken. 1203 * error code if action should be taken.
1204 *
1205 * FIXME:
1206 * Locking: None - redirected write test is safe, testing
1207 * current->signal should possibly lock current->sighand
1208 * pgrp locking ?
1197 */ 1209 */
1198 1210
1199static int job_control(struct tty_struct *tty, struct file *file) 1211static int job_control(struct tty_struct *tty, struct file *file)
@@ -1246,6 +1258,7 @@ static ssize_t read_chan(struct tty_struct *tty, struct file *file,
1246 ssize_t size; 1258 ssize_t size;
1247 long timeout; 1259 long timeout;
1248 unsigned long flags; 1260 unsigned long flags;
1261 int packet;
1249 1262
1250do_it_again: 1263do_it_again:
1251 1264
@@ -1289,16 +1302,19 @@ do_it_again:
1289 if (mutex_lock_interruptible(&tty->atomic_read_lock)) 1302 if (mutex_lock_interruptible(&tty->atomic_read_lock))
1290 return -ERESTARTSYS; 1303 return -ERESTARTSYS;
1291 } 1304 }
1305 packet = tty->packet;
1292 1306
1293 add_wait_queue(&tty->read_wait, &wait); 1307 add_wait_queue(&tty->read_wait, &wait);
1294 while (nr) { 1308 while (nr) {
1295 /* First test for status change. */ 1309 /* First test for status change. */
1296 if (tty->packet && tty->link->ctrl_status) { 1310 if (packet && tty->link->ctrl_status) {
1297 unsigned char cs; 1311 unsigned char cs;
1298 if (b != buf) 1312 if (b != buf)
1299 break; 1313 break;
1314 spin_lock_irqsave(&tty->link->ctrl_lock, flags);
1300 cs = tty->link->ctrl_status; 1315 cs = tty->link->ctrl_status;
1301 tty->link->ctrl_status = 0; 1316 tty->link->ctrl_status = 0;
1317 spin_unlock_irqrestore(&tty->link->ctrl_lock, flags);
1302 if (tty_put_user(tty, cs, b++)) { 1318 if (tty_put_user(tty, cs, b++)) {
1303 retval = -EFAULT; 1319 retval = -EFAULT;
1304 b--; 1320 b--;
@@ -1333,6 +1349,7 @@ do_it_again:
1333 retval = -ERESTARTSYS; 1349 retval = -ERESTARTSYS;
1334 break; 1350 break;
1335 } 1351 }
1352 /* FIXME: does n_tty_set_room need locking ? */
1336 n_tty_set_room(tty); 1353 n_tty_set_room(tty);
1337 timeout = schedule_timeout(timeout); 1354 timeout = schedule_timeout(timeout);
1338 continue; 1355 continue;
@@ -1340,7 +1357,7 @@ do_it_again:
1340 __set_current_state(TASK_RUNNING); 1357 __set_current_state(TASK_RUNNING);
1341 1358
1342 /* Deal with packet mode. */ 1359 /* Deal with packet mode. */
1343 if (tty->packet && b == buf) { 1360 if (packet && b == buf) {
1344 if (tty_put_user(tty, TIOCPKT_DATA, b++)) { 1361 if (tty_put_user(tty, TIOCPKT_DATA, b++)) {
1345 retval = -EFAULT; 1362 retval = -EFAULT;
1346 b--; 1363 b--;
@@ -1388,6 +1405,8 @@ do_it_again:
1388 break; 1405 break;
1389 } else { 1406 } else {
1390 int uncopied; 1407 int uncopied;
1408 /* The copy function takes the read lock and handles
1409 locking internally for this case */
1391 uncopied = copy_from_read_buf(tty, &b, &nr); 1410 uncopied = copy_from_read_buf(tty, &b, &nr);
1392 uncopied += copy_from_read_buf(tty, &b, &nr); 1411 uncopied += copy_from_read_buf(tty, &b, &nr);
1393 if (uncopied) { 1412 if (uncopied) {
@@ -1429,7 +1448,6 @@ do_it_again:
1429 goto do_it_again; 1448 goto do_it_again;
1430 1449
1431 n_tty_set_room(tty); 1450 n_tty_set_room(tty);
1432
1433 return retval; 1451 return retval;
1434} 1452}
1435 1453