aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/tty_buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/tty_buffer.c')
-rw-r--r--drivers/tty/tty_buffer.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 8ebd9f88a6f6..f1d30f6945af 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -255,11 +255,16 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size,
255 if (change || left < size) { 255 if (change || left < size) {
256 /* This is the slow path - looking for new buffers to use */ 256 /* This is the slow path - looking for new buffers to use */
257 if ((n = tty_buffer_alloc(port, size)) != NULL) { 257 if ((n = tty_buffer_alloc(port, size)) != NULL) {
258 unsigned long iflags;
259
258 n->flags = flags; 260 n->flags = flags;
259 buf->tail = n; 261 buf->tail = n;
262
263 spin_lock_irqsave(&buf->flush_lock, iflags);
260 b->commit = b->used; 264 b->commit = b->used;
261 smp_mb();
262 b->next = n; 265 b->next = n;
266 spin_unlock_irqrestore(&buf->flush_lock, iflags);
267
263 } else if (change) 268 } else if (change)
264 size = 0; 269 size = 0;
265 else 270 else
@@ -443,6 +448,7 @@ static void flush_to_ldisc(struct work_struct *work)
443 mutex_lock(&buf->lock); 448 mutex_lock(&buf->lock);
444 449
445 while (1) { 450 while (1) {
451 unsigned long flags;
446 struct tty_buffer *head = buf->head; 452 struct tty_buffer *head = buf->head;
447 int count; 453 int count;
448 454
@@ -450,14 +456,19 @@ static void flush_to_ldisc(struct work_struct *work)
450 if (atomic_read(&buf->priority)) 456 if (atomic_read(&buf->priority))
451 break; 457 break;
452 458
459 spin_lock_irqsave(&buf->flush_lock, flags);
453 count = head->commit - head->read; 460 count = head->commit - head->read;
454 if (!count) { 461 if (!count) {
455 if (head->next == NULL) 462 if (head->next == NULL) {
463 spin_unlock_irqrestore(&buf->flush_lock, flags);
456 break; 464 break;
465 }
457 buf->head = head->next; 466 buf->head = head->next;
467 spin_unlock_irqrestore(&buf->flush_lock, flags);
458 tty_buffer_free(port, head); 468 tty_buffer_free(port, head);
459 continue; 469 continue;
460 } 470 }
471 spin_unlock_irqrestore(&buf->flush_lock, flags);
461 472
462 count = receive_buf(tty, head, count); 473 count = receive_buf(tty, head, count);
463 if (!count) 474 if (!count)
@@ -512,6 +523,7 @@ void tty_buffer_init(struct tty_port *port)
512 struct tty_bufhead *buf = &port->buf; 523 struct tty_bufhead *buf = &port->buf;
513 524
514 mutex_init(&buf->lock); 525 mutex_init(&buf->lock);
526 spin_lock_init(&buf->flush_lock);
515 tty_buffer_reset(&buf->sentinel, 0); 527 tty_buffer_reset(&buf->sentinel, 0);
516 buf->head = &buf->sentinel; 528 buf->head = &buf->sentinel;
517 buf->tail = &buf->sentinel; 529 buf->tail = &buf->sentinel;