Commit 5cff39c6 authored by Jiri Slaby's avatar Jiri Slaby Committed by Greg Kroah-Hartman

TTY: tty_buffer, cache pointer to tty->buf

During the move of tty buffers from tty_struct to tty_port, we will
need to switch all users of buf to tty->port->buf. There are many
functions where this is accessed directly in their code many times.
Cache the tty->buf pointer in such functions now and change only
single lines in each function in the next patch.

Not that it is convenient for the next patch, but the code is now also
more readable.
Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
Acked-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2fc20661
...@@ -29,17 +29,19 @@ ...@@ -29,17 +29,19 @@
void tty_buffer_free_all(struct tty_struct *tty) void tty_buffer_free_all(struct tty_struct *tty)
{ {
struct tty_bufhead *buf = &tty->buf;
struct tty_buffer *thead; struct tty_buffer *thead;
while ((thead = tty->buf.head) != NULL) {
tty->buf.head = thead->next; while ((thead = buf->head) != NULL) {
buf->head = thead->next;
kfree(thead); kfree(thead);
} }
while ((thead = tty->buf.free) != NULL) { while ((thead = buf->free) != NULL) {
tty->buf.free = thead->next; buf->free = thead->next;
kfree(thead); kfree(thead);
} }
tty->buf.tail = NULL; buf->tail = NULL;
tty->buf.memory_used = 0; buf->memory_used = 0;
} }
/** /**
...@@ -87,15 +89,17 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size) ...@@ -87,15 +89,17 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b) static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
{ {
struct tty_bufhead *buf = &tty->buf;
/* Dumb strategy for now - should keep some stats */ /* Dumb strategy for now - should keep some stats */
tty->buf.memory_used -= b->size; buf->memory_used -= b->size;
WARN_ON(tty->buf.memory_used < 0); WARN_ON(buf->memory_used < 0);
if (b->size >= 512) if (b->size >= 512)
kfree(b); kfree(b);
else { else {
b->next = tty->buf.free; b->next = buf->free;
tty->buf.free = b; buf->free = b;
} }
} }
...@@ -112,13 +116,14 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b) ...@@ -112,13 +116,14 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
static void __tty_buffer_flush(struct tty_struct *tty) static void __tty_buffer_flush(struct tty_struct *tty)
{ {
struct tty_bufhead *buf = &tty->buf;
struct tty_buffer *thead; struct tty_buffer *thead;
while ((thead = tty->buf.head) != NULL) { while ((thead = buf->head) != NULL) {
tty->buf.head = thead->next; buf->head = thead->next;
tty_buffer_free(tty, thead); tty_buffer_free(tty, thead);
} }
tty->buf.tail = NULL; buf->tail = NULL;
} }
/** /**
...@@ -135,21 +140,23 @@ static void __tty_buffer_flush(struct tty_struct *tty) ...@@ -135,21 +140,23 @@ static void __tty_buffer_flush(struct tty_struct *tty)
void tty_buffer_flush(struct tty_struct *tty) void tty_buffer_flush(struct tty_struct *tty)
{ {
struct tty_port *port = tty->port; struct tty_port *port = tty->port;
struct tty_bufhead *buf = &tty->buf;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&tty->buf.lock, flags);
spin_lock_irqsave(&buf->lock, flags);
/* If the data is being pushed to the tty layer then we can't /* If the data is being pushed to the tty layer then we can't
process it here. Instead set a flag and the flush_to_ldisc process it here. Instead set a flag and the flush_to_ldisc
path will process the flush request before it exits */ path will process the flush request before it exits */
if (test_bit(TTYP_FLUSHING, &port->iflags)) { if (test_bit(TTYP_FLUSHING, &port->iflags)) {
set_bit(TTYP_FLUSHPENDING, &port->iflags); set_bit(TTYP_FLUSHPENDING, &port->iflags);
spin_unlock_irqrestore(&tty->buf.lock, flags); spin_unlock_irqrestore(&buf->lock, flags);
wait_event(tty->read_wait, wait_event(tty->read_wait,
test_bit(TTYP_FLUSHPENDING, &port->iflags) == 0); test_bit(TTYP_FLUSHPENDING, &port->iflags) == 0);
return; return;
} else } else
__tty_buffer_flush(tty); __tty_buffer_flush(tty);
spin_unlock_irqrestore(&tty->buf.lock, flags); spin_unlock_irqrestore(&buf->lock, flags);
} }
/** /**
...@@ -197,12 +204,14 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size) ...@@ -197,12 +204,14 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
*/ */
static int __tty_buffer_request_room(struct tty_struct *tty, size_t size) static int __tty_buffer_request_room(struct tty_struct *tty, size_t size)
{ {
struct tty_bufhead *buf = &tty->buf;
struct tty_buffer *b, *n; struct tty_buffer *b, *n;
int left; int left;
/* OPTIMISATION: We could keep a per tty "zero" sized buffer to /* OPTIMISATION: We could keep a per tty "zero" sized buffer to
remove this conditional if its worth it. This would be invisible remove this conditional if its worth it. This would be invisible
to the callers */ to the callers */
if ((b = tty->buf.tail) != NULL) b = buf->tail;
if (b != NULL)
left = b->size - b->used; left = b->size - b->used;
else else
left = 0; left = 0;
...@@ -214,8 +223,8 @@ static int __tty_buffer_request_room(struct tty_struct *tty, size_t size) ...@@ -214,8 +223,8 @@ static int __tty_buffer_request_room(struct tty_struct *tty, size_t size)
b->next = n; b->next = n;
b->commit = b->used; b->commit = b->used;
} else } else
tty->buf.head = n; buf->head = n;
tty->buf.tail = n; buf->tail = n;
} else } else
size = left; size = left;
} }
...@@ -262,6 +271,7 @@ EXPORT_SYMBOL_GPL(tty_buffer_request_room); ...@@ -262,6 +271,7 @@ EXPORT_SYMBOL_GPL(tty_buffer_request_room);
int tty_insert_flip_string_fixed_flag(struct tty_struct *tty, int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
const unsigned char *chars, char flag, size_t size) const unsigned char *chars, char flag, size_t size)
{ {
struct tty_bufhead *buf = &tty->buf;
int copied = 0; int copied = 0;
do { do {
int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
...@@ -269,18 +279,18 @@ int tty_insert_flip_string_fixed_flag(struct tty_struct *tty, ...@@ -269,18 +279,18 @@ int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
unsigned long flags; unsigned long flags;
struct tty_buffer *tb; struct tty_buffer *tb;
spin_lock_irqsave(&tty->buf.lock, flags); spin_lock_irqsave(&buf->lock, flags);
space = __tty_buffer_request_room(tty, goal); space = __tty_buffer_request_room(tty, goal);
tb = tty->buf.tail; tb = buf->tail;
/* If there is no space then tb may be NULL */ /* If there is no space then tb may be NULL */
if (unlikely(space == 0)) { if (unlikely(space == 0)) {
spin_unlock_irqrestore(&tty->buf.lock, flags); spin_unlock_irqrestore(&buf->lock, flags);
break; break;
} }
memcpy(tb->char_buf_ptr + tb->used, chars, space); memcpy(tb->char_buf_ptr + tb->used, chars, space);
memset(tb->flag_buf_ptr + tb->used, flag, space); memset(tb->flag_buf_ptr + tb->used, flag, space);
tb->used += space; tb->used += space;
spin_unlock_irqrestore(&tty->buf.lock, flags); spin_unlock_irqrestore(&buf->lock, flags);
copied += space; copied += space;
chars += space; chars += space;
/* There is a small chance that we need to split the data over /* There is a small chance that we need to split the data over
...@@ -307,6 +317,7 @@ EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag); ...@@ -307,6 +317,7 @@ EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag);
int tty_insert_flip_string_flags(struct tty_struct *tty, int tty_insert_flip_string_flags(struct tty_struct *tty,
const unsigned char *chars, const char *flags, size_t size) const unsigned char *chars, const char *flags, size_t size)
{ {
struct tty_bufhead *buf = &tty->buf;
int copied = 0; int copied = 0;
do { do {
int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
...@@ -314,18 +325,18 @@ int tty_insert_flip_string_flags(struct tty_struct *tty, ...@@ -314,18 +325,18 @@ int tty_insert_flip_string_flags(struct tty_struct *tty,
unsigned long __flags; unsigned long __flags;
struct tty_buffer *tb; struct tty_buffer *tb;
spin_lock_irqsave(&tty->buf.lock, __flags); spin_lock_irqsave(&buf->lock, __flags);
space = __tty_buffer_request_room(tty, goal); space = __tty_buffer_request_room(tty, goal);
tb = tty->buf.tail; tb = buf->tail;
/* If there is no space then tb may be NULL */ /* If there is no space then tb may be NULL */
if (unlikely(space == 0)) { if (unlikely(space == 0)) {
spin_unlock_irqrestore(&tty->buf.lock, __flags); spin_unlock_irqrestore(&buf->lock, __flags);
break; break;
} }
memcpy(tb->char_buf_ptr + tb->used, chars, space); memcpy(tb->char_buf_ptr + tb->used, chars, space);
memcpy(tb->flag_buf_ptr + tb->used, flags, space); memcpy(tb->flag_buf_ptr + tb->used, flags, space);
tb->used += space; tb->used += space;
spin_unlock_irqrestore(&tty->buf.lock, __flags); spin_unlock_irqrestore(&buf->lock, __flags);
copied += space; copied += space;
chars += space; chars += space;
flags += space; flags += space;
...@@ -351,12 +362,14 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags); ...@@ -351,12 +362,14 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags);
void tty_schedule_flip(struct tty_struct *tty) void tty_schedule_flip(struct tty_struct *tty)
{ {
struct tty_bufhead *buf = &tty->buf;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&tty->buf.lock, flags);
if (tty->buf.tail != NULL) spin_lock_irqsave(&buf->lock, flags);
tty->buf.tail->commit = tty->buf.tail->used; if (buf->tail != NULL)
spin_unlock_irqrestore(&tty->buf.lock, flags); buf->tail->commit = buf->tail->used;
schedule_work(&tty->buf.work); spin_unlock_irqrestore(&buf->lock, flags);
schedule_work(&buf->work);
} }
EXPORT_SYMBOL(tty_schedule_flip); EXPORT_SYMBOL(tty_schedule_flip);
...@@ -378,20 +391,21 @@ EXPORT_SYMBOL(tty_schedule_flip); ...@@ -378,20 +391,21 @@ EXPORT_SYMBOL(tty_schedule_flip);
int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars,
size_t size) size_t size)
{ {
struct tty_bufhead *buf = &tty->buf;
int space; int space;
unsigned long flags; unsigned long flags;
struct tty_buffer *tb; struct tty_buffer *tb;
spin_lock_irqsave(&tty->buf.lock, flags); spin_lock_irqsave(&buf->lock, flags);
space = __tty_buffer_request_room(tty, size); space = __tty_buffer_request_room(tty, size);
tb = tty->buf.tail; tb = buf->tail;
if (likely(space)) { if (likely(space)) {
*chars = tb->char_buf_ptr + tb->used; *chars = tb->char_buf_ptr + tb->used;
memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space); memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
tb->used += space; tb->used += space;
} }
spin_unlock_irqrestore(&tty->buf.lock, flags); spin_unlock_irqrestore(&buf->lock, flags);
return space; return space;
} }
EXPORT_SYMBOL_GPL(tty_prepare_flip_string); EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
...@@ -415,20 +429,21 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string); ...@@ -415,20 +429,21 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
int tty_prepare_flip_string_flags(struct tty_struct *tty, int tty_prepare_flip_string_flags(struct tty_struct *tty,
unsigned char **chars, char **flags, size_t size) unsigned char **chars, char **flags, size_t size)
{ {
struct tty_bufhead *buf = &tty->buf;
int space; int space;
unsigned long __flags; unsigned long __flags;
struct tty_buffer *tb; struct tty_buffer *tb;
spin_lock_irqsave(&tty->buf.lock, __flags); spin_lock_irqsave(&buf->lock, __flags);
space = __tty_buffer_request_room(tty, size); space = __tty_buffer_request_room(tty, size);
tb = tty->buf.tail; tb = buf->tail;
if (likely(space)) { if (likely(space)) {
*chars = tb->char_buf_ptr + tb->used; *chars = tb->char_buf_ptr + tb->used;
*flags = tb->flag_buf_ptr + tb->used; *flags = tb->flag_buf_ptr + tb->used;
tb->used += space; tb->used += space;
} }
spin_unlock_irqrestore(&tty->buf.lock, __flags); spin_unlock_irqrestore(&buf->lock, __flags);
return space; return space;
} }
EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
...@@ -452,6 +467,7 @@ static void flush_to_ldisc(struct work_struct *work) ...@@ -452,6 +467,7 @@ static void flush_to_ldisc(struct work_struct *work)
struct tty_struct *tty = struct tty_struct *tty =
container_of(work, struct tty_struct, buf.work); container_of(work, struct tty_struct, buf.work);
struct tty_port *port = tty->port; struct tty_port *port = tty->port;
struct tty_bufhead *buf = &tty->buf;
unsigned long flags; unsigned long flags;
struct tty_ldisc *disc; struct tty_ldisc *disc;
...@@ -459,11 +475,11 @@ static void flush_to_ldisc(struct work_struct *work) ...@@ -459,11 +475,11 @@ static void flush_to_ldisc(struct work_struct *work)
if (disc == NULL) /* !TTY_LDISC */ if (disc == NULL) /* !TTY_LDISC */
return; return;
spin_lock_irqsave(&tty->buf.lock, flags); spin_lock_irqsave(&buf->lock, flags);
if (!test_and_set_bit(TTYP_FLUSHING, &port->iflags)) { if (!test_and_set_bit(TTYP_FLUSHING, &port->iflags)) {
struct tty_buffer *head; struct tty_buffer *head;
while ((head = tty->buf.head) != NULL) { while ((head = buf->head) != NULL) {
int count; int count;
char *char_buf; char *char_buf;
unsigned char *flag_buf; unsigned char *flag_buf;
...@@ -472,7 +488,7 @@ static void flush_to_ldisc(struct work_struct *work) ...@@ -472,7 +488,7 @@ static void flush_to_ldisc(struct work_struct *work)
if (!count) { if (!count) {
if (head->next == NULL) if (head->next == NULL)
break; break;
tty->buf.head = head->next; buf->head = head->next;
tty_buffer_free(tty, head); tty_buffer_free(tty, head);
continue; continue;
} }
...@@ -488,10 +504,10 @@ static void flush_to_ldisc(struct work_struct *work) ...@@ -488,10 +504,10 @@ static void flush_to_ldisc(struct work_struct *work)
char_buf = head->char_buf_ptr + head->read; char_buf = head->char_buf_ptr + head->read;
flag_buf = head->flag_buf_ptr + head->read; flag_buf = head->flag_buf_ptr + head->read;
head->read += count; head->read += count;
spin_unlock_irqrestore(&tty->buf.lock, flags); spin_unlock_irqrestore(&buf->lock, flags);
disc->ops->receive_buf(tty, char_buf, disc->ops->receive_buf(tty, char_buf,
flag_buf, count); flag_buf, count);
spin_lock_irqsave(&tty->buf.lock, flags); spin_lock_irqsave(&buf->lock, flags);
} }
clear_bit(TTYP_FLUSHING, &port->iflags); clear_bit(TTYP_FLUSHING, &port->iflags);
} }
...@@ -503,7 +519,7 @@ static void flush_to_ldisc(struct work_struct *work) ...@@ -503,7 +519,7 @@ static void flush_to_ldisc(struct work_struct *work)
clear_bit(TTYP_FLUSHPENDING, &port->iflags); clear_bit(TTYP_FLUSHPENDING, &port->iflags);
wake_up(&tty->read_wait); wake_up(&tty->read_wait);
} }
spin_unlock_irqrestore(&tty->buf.lock, flags); spin_unlock_irqrestore(&buf->lock, flags);
tty_ldisc_deref(disc); tty_ldisc_deref(disc);
} }
...@@ -537,16 +553,18 @@ void tty_flush_to_ldisc(struct tty_struct *tty) ...@@ -537,16 +553,18 @@ void tty_flush_to_ldisc(struct tty_struct *tty)
void tty_flip_buffer_push(struct tty_struct *tty) void tty_flip_buffer_push(struct tty_struct *tty)
{ {
struct tty_bufhead *buf = &tty->buf;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&tty->buf.lock, flags);
if (tty->buf.tail != NULL) spin_lock_irqsave(&buf->lock, flags);
tty->buf.tail->commit = tty->buf.tail->used; if (buf->tail != NULL)
spin_unlock_irqrestore(&tty->buf.lock, flags); buf->tail->commit = buf->tail->used;
spin_unlock_irqrestore(&buf->lock, flags);
if (tty->low_latency) if (tty->low_latency)
flush_to_ldisc(&tty->buf.work); flush_to_ldisc(&buf->work);
else else
schedule_work(&tty->buf.work); schedule_work(&buf->work);
} }
EXPORT_SYMBOL(tty_flip_buffer_push); EXPORT_SYMBOL(tty_flip_buffer_push);
...@@ -562,11 +580,13 @@ EXPORT_SYMBOL(tty_flip_buffer_push); ...@@ -562,11 +580,13 @@ EXPORT_SYMBOL(tty_flip_buffer_push);
void tty_buffer_init(struct tty_struct *tty) void tty_buffer_init(struct tty_struct *tty)
{ {
spin_lock_init(&tty->buf.lock); struct tty_bufhead *buf = &tty->buf;
tty->buf.head = NULL;
tty->buf.tail = NULL; spin_lock_init(&buf->lock);
tty->buf.free = NULL; buf->head = NULL;
tty->buf.memory_used = 0; buf->tail = NULL;
INIT_WORK(&tty->buf.work, flush_to_ldisc); buf->free = NULL;
buf->memory_used = 0;
INIT_WORK(&buf->work, flush_to_ldisc);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment