diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2013-11-22 12:09:55 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-12-08 19:57:38 -0500 |
commit | 4d18e6eff81e1d4d81d0942d5b7e96904b3b32df (patch) | |
tree | a6c66c84189a50bff8b6b05a7187a8cda4b67cfc | |
parent | 82f91fe092b6eacd82e976b8955443f9fd97d07e (diff) |
tty: Enable configurable tty flip buffer limit
Allow driver to configure its maximum flip buffer memory
consumption/limit. This is necessary for very-high speed line
rates (in excess of 10MB/sec) because the flip buffers can
be saturated before the line discipline has a chance to
throttle the input.
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/tty/tty_buffer.c | 24 | ||||
-rw-r--r-- | include/linux/tty.h | 1 | ||||
-rw-r--r-- | include/linux/tty_flip.h | 1 |
3 files changed, 23 insertions, 3 deletions
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index c043136fbe51..57eb34b2ec24 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c | |||
@@ -26,7 +26,7 @@ | |||
26 | * Byte threshold to limit memory consumption for flip buffers. | 26 | * Byte threshold to limit memory consumption for flip buffers. |
27 | * The actual memory limit is > 2x this amount. | 27 | * The actual memory limit is > 2x this amount. |
28 | */ | 28 | */ |
29 | #define TTYB_MEM_LIMIT 65536 | 29 | #define TTYB_DEFAULT_MEM_LIMIT 65536 |
30 | 30 | ||
31 | /* | 31 | /* |
32 | * We default to dicing tty buffer allocations to this many characters | 32 | * We default to dicing tty buffer allocations to this many characters |
@@ -89,7 +89,7 @@ void tty_buffer_unlock_exclusive(struct tty_port *port) | |||
89 | 89 | ||
90 | int tty_buffer_space_avail(struct tty_port *port) | 90 | int tty_buffer_space_avail(struct tty_port *port) |
91 | { | 91 | { |
92 | int space = TTYB_MEM_LIMIT - atomic_read(&port->buf.memory_used); | 92 | int space = port->buf.mem_limit - atomic_read(&port->buf.memory_used); |
93 | return max(space, 0); | 93 | return max(space, 0); |
94 | } | 94 | } |
95 | 95 | ||
@@ -162,7 +162,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size) | |||
162 | 162 | ||
163 | /* Should possibly check if this fails for the largest buffer we | 163 | /* Should possibly check if this fails for the largest buffer we |
164 | have queued and recycle that ? */ | 164 | have queued and recycle that ? */ |
165 | if (atomic_read(&port->buf.memory_used) > TTYB_MEM_LIMIT) | 165 | if (atomic_read(&port->buf.memory_used) > port->buf.mem_limit) |
166 | return NULL; | 166 | return NULL; |
167 | p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); | 167 | p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); |
168 | if (p == NULL) | 168 | if (p == NULL) |
@@ -536,4 +536,22 @@ void tty_buffer_init(struct tty_port *port) | |||
536 | atomic_set(&buf->memory_used, 0); | 536 | atomic_set(&buf->memory_used, 0); |
537 | atomic_set(&buf->priority, 0); | 537 | atomic_set(&buf->priority, 0); |
538 | INIT_WORK(&buf->work, flush_to_ldisc); | 538 | INIT_WORK(&buf->work, flush_to_ldisc); |
539 | buf->mem_limit = TTYB_DEFAULT_MEM_LIMIT; | ||
539 | } | 540 | } |
541 | |||
542 | /** | ||
543 | * tty_buffer_set_limit - change the tty buffer memory limit | ||
544 | * @port: tty port to change | ||
545 | * | ||
546 | * Change the tty buffer memory limit. | ||
547 | * Must be called before the other tty buffer functions are used. | ||
548 | */ | ||
549 | |||
550 | int tty_buffer_set_limit(struct tty_port *port, int limit) | ||
551 | { | ||
552 | if (limit < MIN_TTYB_SIZE) | ||
553 | return -EINVAL; | ||
554 | port->buf.mem_limit = limit; | ||
555 | return 0; | ||
556 | } | ||
557 | EXPORT_SYMBOL_GPL(tty_buffer_set_limit); | ||
diff --git a/include/linux/tty.h b/include/linux/tty.h index 97d660ed70c1..2225745060d6 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -61,6 +61,7 @@ struct tty_bufhead { | |||
61 | struct tty_buffer sentinel; | 61 | struct tty_buffer sentinel; |
62 | struct llist_head free; /* Free queue head */ | 62 | struct llist_head free; /* Free queue head */ |
63 | atomic_t memory_used; /* In-use buffers excluding free list */ | 63 | atomic_t memory_used; /* In-use buffers excluding free list */ |
64 | int mem_limit; | ||
64 | struct tty_buffer *tail; /* Active buffer */ | 65 | struct tty_buffer *tail; /* Active buffer */ |
65 | }; | 66 | }; |
66 | /* | 67 | /* |
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h index 21ddd7d9ea1f..2da8bc2a5486 100644 --- a/include/linux/tty_flip.h +++ b/include/linux/tty_flip.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef _LINUX_TTY_FLIP_H | 1 | #ifndef _LINUX_TTY_FLIP_H |
2 | #define _LINUX_TTY_FLIP_H | 2 | #define _LINUX_TTY_FLIP_H |
3 | 3 | ||
4 | extern int tty_buffer_set_limit(struct tty_port *port, int limit); | ||
4 | extern int tty_buffer_space_avail(struct tty_port *port); | 5 | extern int tty_buffer_space_avail(struct tty_port *port); |
5 | extern int tty_buffer_request_room(struct tty_port *port, size_t size); | 6 | extern int tty_buffer_request_room(struct tty_port *port, size_t size); |
6 | extern int tty_insert_flip_string_flags(struct tty_port *port, | 7 | extern int tty_insert_flip_string_flags(struct tty_port *port, |