Skip to content

Commit

Permalink
TTY: move tty buffers to tty_port
Browse files Browse the repository at this point in the history
So this is it. The big step why we did all the work over the past
kernel releases. Now everything is prepared, so nothing protects us
from doing that big step.

           |  |            \  \ nnnn/^l      |  |
           |  |             \  /     /       |  |
           |  '-,.__   =>    \/   ,-`    =>  |  '-,.__
           | O __.´´)        (  .`           | O __.´´)
            ~~~   ~~          ``              ~~~   ~~
The buffers are now in the tty_port structure and we can start
teaching the buffer helpers (insert char/string, flip etc.) to use
tty_port instead of tty_struct all around.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Jiri Slaby authored and Greg Kroah-Hartman committed Oct 22, 2012
1 parent 967fab6 commit ecbbfd4
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 63 deletions.
7 changes: 5 additions & 2 deletions drivers/tty/n_tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,11 @@ static void n_tty_set_room(struct tty_struct *tty)
tty->receive_room = left;

/* Did this open up the receive buffer? We may need to flip */
if (left && !old_left)
schedule_work(&tty->buf.work);
if (left && !old_left) {
WARN_RATELIMIT(tty->port->itty == NULL,
"scheduling with invalid itty");
schedule_work(&tty->port->buf.work);
}
}

static void put_tty_queue_nolock(unsigned char c, struct n_tty_data *ldata)
Expand Down
2 changes: 1 addition & 1 deletion drivers/tty/pty.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ static void pty_unthrottle(struct tty_struct *tty)

static int pty_space(struct tty_struct *to)
{
int n = 8192 - to->buf.memory_used;
int n = 8192 - to->port->buf.memory_used;
if (n < 0)
return 0;
return n;
Expand Down
102 changes: 53 additions & 49 deletions drivers/tty/tty_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
* Locking: none
*/

void tty_buffer_free_all(struct tty_struct *tty)
void tty_buffer_free_all(struct tty_port *port)
{
struct tty_bufhead *buf = &tty->buf;
struct tty_bufhead *buf = &port->buf;
struct tty_buffer *thead;

while ((thead = buf->head) != NULL) {
Expand All @@ -56,11 +56,11 @@ void tty_buffer_free_all(struct tty_struct *tty)
* Locking: Caller must hold tty->buf.lock
*/

static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size)
{
struct tty_buffer *p;

if (tty->buf.memory_used + size > 65536)
if (port->buf.memory_used + size > 65536)
return NULL;
p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
if (p == NULL)
Expand All @@ -72,7 +72,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
p->read = 0;
p->char_buf_ptr = (char *)(p->data);
p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
tty->buf.memory_used += size;
port->buf.memory_used += size;
return p;
}

Expand All @@ -87,9 +87,9 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
* Locking: Caller must hold tty->buf.lock
*/

static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b)
{
struct tty_bufhead *buf = &tty->buf;
struct tty_bufhead *buf = &port->buf;

/* Dumb strategy for now - should keep some stats */
buf->memory_used -= b->size;
Expand All @@ -114,14 +114,14 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
* Locking: Caller must hold tty->buf.lock
*/

static void __tty_buffer_flush(struct tty_struct *tty)
static void __tty_buffer_flush(struct tty_port *port)
{
struct tty_bufhead *buf = &tty->buf;
struct tty_bufhead *buf = &port->buf;
struct tty_buffer *thead;

while ((thead = buf->head) != NULL) {
buf->head = thead->next;
tty_buffer_free(tty, thead);
tty_buffer_free(port, thead);
}
buf->tail = NULL;
}
Expand All @@ -140,7 +140,7 @@ static void __tty_buffer_flush(struct tty_struct *tty)
void tty_buffer_flush(struct tty_struct *tty)
{
struct tty_port *port = tty->port;
struct tty_bufhead *buf = &tty->buf;
struct tty_bufhead *buf = &port->buf;
unsigned long flags;

spin_lock_irqsave(&buf->lock, flags);
Expand All @@ -155,7 +155,7 @@ void tty_buffer_flush(struct tty_struct *tty)
test_bit(TTYP_FLUSHPENDING, &port->iflags) == 0);
return;
} else
__tty_buffer_flush(tty);
__tty_buffer_flush(port);
spin_unlock_irqrestore(&buf->lock, flags);
}

Expand All @@ -171,9 +171,9 @@ void tty_buffer_flush(struct tty_struct *tty)
* Locking: Caller must hold tty->buf.lock
*/

static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
static struct tty_buffer *tty_buffer_find(struct tty_port *port, size_t size)
{
struct tty_buffer **tbh = &tty->buf.free;
struct tty_buffer **tbh = &port->buf.free;
while ((*tbh) != NULL) {
struct tty_buffer *t = *tbh;
if (t->size >= size) {
Expand All @@ -182,14 +182,14 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
t->used = 0;
t->commit = 0;
t->read = 0;
tty->buf.memory_used += t->size;
port->buf.memory_used += t->size;
return t;
}
tbh = &((*tbh)->next);
}
/* Round the buffer size out */
size = (size + 0xFF) & ~0xFF;
return tty_buffer_alloc(tty, size);
return tty_buffer_alloc(port, size);
/* Should possibly check if this fails for the largest buffer we
have queued and recycle that ? */
}
Expand All @@ -200,11 +200,11 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
*
* Make at least size bytes of linear space available for the tty
* buffer. If we fail return the size we managed to find.
* Locking: Caller must hold tty->buf.lock
* Locking: Caller must hold port->buf.lock
*/
static int __tty_buffer_request_room(struct tty_struct *tty, size_t size)
static int __tty_buffer_request_room(struct tty_port *port, size_t size)
{
struct tty_bufhead *buf = &tty->buf;
struct tty_bufhead *buf = &port->buf;
struct tty_buffer *b, *n;
int left;
/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
Expand All @@ -218,7 +218,7 @@ static int __tty_buffer_request_room(struct tty_struct *tty, size_t size)

if (left < size) {
/* This is the slow path - looking for new buffers to use */
if ((n = tty_buffer_find(tty, size)) != NULL) {
if ((n = tty_buffer_find(port, size)) != NULL) {
if (b != NULL) {
b->next = n;
b->commit = b->used;
Expand All @@ -241,16 +241,17 @@ static int __tty_buffer_request_room(struct tty_struct *tty, size_t size)
* Make at least size bytes of linear space available for the tty
* buffer. If we fail return the size we managed to find.
*
* Locking: Takes tty->buf.lock
* Locking: Takes port->buf.lock
*/
int tty_buffer_request_room(struct tty_struct *tty, size_t size)
{
struct tty_port *port = tty->port;
unsigned long flags;
int length;

spin_lock_irqsave(&tty->buf.lock, flags);
length = __tty_buffer_request_room(tty, size);
spin_unlock_irqrestore(&tty->buf.lock, flags);
spin_lock_irqsave(&port->buf.lock, flags);
length = __tty_buffer_request_room(port, size);
spin_unlock_irqrestore(&port->buf.lock, flags);
return length;
}
EXPORT_SYMBOL_GPL(tty_buffer_request_room);
Expand All @@ -265,13 +266,13 @@ EXPORT_SYMBOL_GPL(tty_buffer_request_room);
* Queue a series of bytes to the tty buffering. All the characters
* passed are marked with the supplied flag. Returns the number added.
*
* Locking: Called functions may take tty->buf.lock
* Locking: Called functions may take port->buf.lock
*/

int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
const unsigned char *chars, char flag, size_t size)
{
struct tty_bufhead *buf = &tty->buf;
struct tty_bufhead *buf = &tty->port->buf;
int copied = 0;
do {
int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
Expand All @@ -280,7 +281,7 @@ int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
struct tty_buffer *tb;

spin_lock_irqsave(&buf->lock, flags);
space = __tty_buffer_request_room(tty, goal);
space = __tty_buffer_request_room(tty->port, goal);
tb = buf->tail;
/* If there is no space then tb may be NULL */
if (unlikely(space == 0)) {
Expand Down Expand Up @@ -311,13 +312,13 @@ EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag);
* the flags array indicates the status of the character. Returns the
* number added.
*
* Locking: Called functions may take tty->buf.lock
* Locking: Called functions may take port->buf.lock
*/

int tty_insert_flip_string_flags(struct tty_struct *tty,
const unsigned char *chars, const char *flags, size_t size)
{
struct tty_bufhead *buf = &tty->buf;
struct tty_bufhead *buf = &tty->port->buf;
int copied = 0;
do {
int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
Expand All @@ -326,7 +327,7 @@ int tty_insert_flip_string_flags(struct tty_struct *tty,
struct tty_buffer *tb;

spin_lock_irqsave(&buf->lock, __flags);
space = __tty_buffer_request_room(tty, goal);
space = __tty_buffer_request_room(tty->port, goal);
tb = buf->tail;
/* If there is no space then tb may be NULL */
if (unlikely(space == 0)) {
Expand Down Expand Up @@ -357,12 +358,12 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags);
* Note that this function can only be used when the low_latency flag
* is unset. Otherwise the workqueue won't be flushed.
*
* Locking: Takes tty->buf.lock
* Locking: Takes port->buf.lock
*/

void tty_schedule_flip(struct tty_struct *tty)
{
struct tty_bufhead *buf = &tty->buf;
struct tty_bufhead *buf = &tty->port->buf;
unsigned long flags;

spin_lock_irqsave(&buf->lock, flags);
Expand All @@ -385,19 +386,19 @@ EXPORT_SYMBOL(tty_schedule_flip);
* that need their own block copy routines into the buffer. There is no
* guarantee the buffer is a DMA target!
*
* Locking: May call functions taking tty->buf.lock
* Locking: May call functions taking port->buf.lock
*/

int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars,
size_t size)
size_t size)
{
struct tty_bufhead *buf = &tty->buf;
struct tty_bufhead *buf = &tty->port->buf;
int space;
unsigned long flags;
struct tty_buffer *tb;

spin_lock_irqsave(&buf->lock, flags);
space = __tty_buffer_request_room(tty, size);
space = __tty_buffer_request_room(tty->port, size);

tb = buf->tail;
if (likely(space)) {
Expand All @@ -423,19 +424,19 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
* that need their own block copy routines into the buffer. There is no
* guarantee the buffer is a DMA target!
*
* Locking: May call functions taking tty->buf.lock
* Locking: May call functions taking port->buf.lock
*/

int tty_prepare_flip_string_flags(struct tty_struct *tty,
unsigned char **chars, char **flags, size_t size)
{
struct tty_bufhead *buf = &tty->buf;
struct tty_bufhead *buf = &tty->port->buf;
int space;
unsigned long __flags;
struct tty_buffer *tb;

spin_lock_irqsave(&buf->lock, __flags);
space = __tty_buffer_request_room(tty, size);
space = __tty_buffer_request_room(tty->port, size);

tb = buf->tail;
if (likely(space)) {
Expand Down Expand Up @@ -464,13 +465,16 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);

static void flush_to_ldisc(struct work_struct *work)
{
struct tty_struct *tty =
container_of(work, struct tty_struct, buf.work);
struct tty_port *port = tty->port;
struct tty_bufhead *buf = &tty->buf;
struct tty_port *port = container_of(work, struct tty_port, buf.work);
struct tty_bufhead *buf = &port->buf;
struct tty_struct *tty;
unsigned long flags;
struct tty_ldisc *disc;

tty = port->itty;
if (WARN_RATELIMIT(tty == NULL, "tty is NULL"))
return;

disc = tty_ldisc_ref(tty);
if (disc == NULL) /* !TTY_LDISC */
return;
Expand All @@ -489,7 +493,7 @@ static void flush_to_ldisc(struct work_struct *work)
if (head->next == NULL)
break;
buf->head = head->next;
tty_buffer_free(tty, head);
tty_buffer_free(port, head);
continue;
}
/* Ldisc or user is trying to flush the buffers
Expand All @@ -515,7 +519,7 @@ static void flush_to_ldisc(struct work_struct *work)
/* We may have a deferred request to flush the input buffer,
if so pull the chain under the lock and empty the queue */
if (test_bit(TTYP_FLUSHPENDING, &port->iflags)) {
__tty_buffer_flush(tty);
__tty_buffer_flush(port);
clear_bit(TTYP_FLUSHPENDING, &port->iflags);
wake_up(&tty->read_wait);
}
Expand All @@ -535,7 +539,7 @@ static void flush_to_ldisc(struct work_struct *work)
void tty_flush_to_ldisc(struct tty_struct *tty)
{
if (!tty->low_latency)
flush_work(&tty->buf.work);
flush_work(&tty->port->buf.work);
}

/**
Expand All @@ -553,7 +557,7 @@ void tty_flush_to_ldisc(struct tty_struct *tty)

void tty_flip_buffer_push(struct tty_struct *tty)
{
struct tty_bufhead *buf = &tty->buf;
struct tty_bufhead *buf = &tty->port->buf;
unsigned long flags;

spin_lock_irqsave(&buf->lock, flags);
Expand All @@ -578,9 +582,9 @@ EXPORT_SYMBOL(tty_flip_buffer_push);
* Locking: none
*/

void tty_buffer_init(struct tty_struct *tty)
void tty_buffer_init(struct tty_port *port)
{
struct tty_bufhead *buf = &tty->buf;
struct tty_bufhead *buf = &port->buf;

spin_lock_init(&buf->lock);
buf->head = NULL;
Expand Down
2 changes: 0 additions & 2 deletions drivers/tty/tty_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ void free_tty_struct(struct tty_struct *tty)
if (tty->dev)
put_device(tty->dev);
kfree(tty->write_buf);
tty_buffer_free_all(tty);
tty->magic = 0xDEADDEAD;
kfree(tty);
}
Expand Down Expand Up @@ -2935,7 +2934,6 @@ void initialize_tty_struct(struct tty_struct *tty,
tty_ldisc_init(tty);
tty->session = NULL;
tty->pgrp = NULL;
tty_buffer_init(tty);
mutex_init(&tty->legacy_mutex);
mutex_init(&tty->termios_mutex);
mutex_init(&tty->ldisc_mutex);
Expand Down
Loading

0 comments on commit ecbbfd4

Please sign in to comment.