summaryrefslogtreecommitdiffstats
path: root/drivers/tty/tty_buffer.c
diff options
context:
space:
mode:
authorJiri Slaby <jslaby@suse.cz>2012-10-18 22:26:47 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-10-23 01:58:28 +0200
commitecbbfd44a08fa80e0d664814efd4c187721b85f6 (patch)
treef1c9aea12eb27323b9e7f4b8329e47dc3c30e63d /drivers/tty/tty_buffer.c
parentTTY: add port -> tty link (diff)
downloadlinux-ecbbfd44a08fa80e0d664814efd4c187721b85f6.tar.xz
linux-ecbbfd44a08fa80e0d664814efd4c187721b85f6.zip
TTY: move tty buffers to tty_port
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>
Diffstat (limited to 'drivers/tty/tty_buffer.c')
-rw-r--r--drivers/tty/tty_buffer.c102
1 files changed, 53 insertions, 49 deletions
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index ddd74d41cbb2..06725f5cc819 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -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) {
@@ -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)
@@ -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;
}
@@ -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;
@@ -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;
}
@@ -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);
@@ -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);
}
@@ -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) {
@@ -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 ? */
}
@@ -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
@@ -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;
@@ -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);
@@ -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);
@@ -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)) {
@@ -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);
@@ -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)) {
@@ -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);
@@ -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)) {
@@ -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)) {
@@ -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;
@@ -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
@@ -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);
}
@@ -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);
}
/**
@@ -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);
@@ -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;