diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-09-01 09:38:00 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-09-01 09:38:00 -0700 |
commit | 8e1e49550dc85694abd04d86a8ee36bc98bd8b9e (patch) | |
tree | 03133476605e455accd14770365ea05a3bce7007 /drivers/tty/tty_buffer.c | |
parent | e925992671907314b7db6793a28eb39b36bc21a4 (diff) | |
parent | ebf05c7dc92c11b0355aaa0e94064beadaa4b05c (diff) |
Merge tag 'tty-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver updates from Greg KH:
"Here is the big set of tty and serial driver changes for 6.6-rc1.
Lots of cleanups in here this cycle, and some driver updates. Short
summary is:
- Jiri's continued work to make the tty code and apis be a bit more
sane with regards to modern kernel coding style and types
- cpm_uart driver updates
- n_gsm updates and fixes
- meson driver updates
- sc16is7xx driver updates
- 8250 driver updates for different hardware types
- qcom-geni driver fixes
- tegra serial driver change
- stm32 driver updates
- synclink_gt driver cleanups
- tty structure size reduction
All of these have been in linux-next this week with no reported
issues. The last bit of cleanups from Jiri and the tty structure size
reduction came in last week, a bit late but as they were just style
changes and size reductions, I figured they should get into this merge
cycle so that others can work on top of them with no merge conflicts"
* tag 'tty-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (199 commits)
tty: shrink the size of struct tty_struct by 40 bytes
tty: n_tty: deduplicate copy code in n_tty_receive_buf_real_raw()
tty: n_tty: extract ECHO_OP processing to a separate function
tty: n_tty: unify counts to size_t
tty: n_tty: use u8 for chars and flags
tty: n_tty: simplify chars_in_buffer()
tty: n_tty: remove unsigned char casts from character constants
tty: n_tty: move newline handling to a separate function
tty: n_tty: move canon handling to a separate function
tty: n_tty: use MASK() for masking out size bits
tty: n_tty: make n_tty_data::num_overrun unsigned
tty: n_tty: use time_is_before_jiffies() in n_tty_receive_overrun()
tty: n_tty: use 'num' for writes' counts
tty: n_tty: use output character directly
tty: n_tty: make flow of n_tty_receive_buf_common() a bool
Revert "tty: serial: meson: Add a earlycon for the T7 SoC"
Documentation: devices.txt: Fix minors for ttyCPM*
Documentation: devices.txt: Remove ttySIOC*
Documentation: devices.txt: Remove ttyIOC*
serial: 8250_bcm7271: improve bcm7271 8250 port
...
Diffstat (limited to 'drivers/tty/tty_buffer.c')
-rw-r--r-- | drivers/tty/tty_buffer.c | 192 |
1 files changed, 61 insertions, 131 deletions
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 2df86ed90574..5f6d0cf67571 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -177,8 +177,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size) */ if (atomic_read(&port->buf.mem_used) > port->buf.mem_limit) return NULL; - p = kmalloc(sizeof(struct tty_buffer) + 2 * size, - GFP_ATOMIC | __GFP_NOWARN); + p = kmalloc(struct_size(p, data, 2 * size), GFP_ATOMIC | __GFP_NOWARN); if (p == NULL) return NULL; @@ -263,38 +262,32 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size, bool flags) { struct tty_bufhead *buf = &port->buf; - struct tty_buffer *b, *n; - int left, change; - - b = buf->tail; - if (!b->flags) - left = 2 * b->size - b->used; - else - left = b->size - b->used; - - change = !b->flags && flags; - if (change || left < size) { - /* This is the slow path - looking for new buffers to use */ - n = tty_buffer_alloc(port, size); - if (n != NULL) { - n->flags = flags; - buf->tail = n; - /* - * Paired w/ acquire in flush_to_ldisc() and lookahead_bufs() - * ensures they see all buffer data. - */ - smp_store_release(&b->commit, b->used); - /* - * Paired w/ acquire in flush_to_ldisc() and lookahead_bufs() - * ensures the latest commit value can be read before the head - * is advanced to the next buffer. - */ - smp_store_release(&b->next, n); - } else if (change) - size = 0; - else - size = left; - } + struct tty_buffer *n, *b = buf->tail; + size_t left = (b->flags ? 1 : 2) * b->size - b->used; + bool change = !b->flags && flags; + + if (!change && left >= size) + return size; + + /* This is the slow path - looking for new buffers to use */ + n = tty_buffer_alloc(port, size); + if (n == NULL) + return change ? 0 : left; + + n->flags = flags; + buf->tail = n; + /* + * Paired w/ acquire in flush_to_ldisc() and lookahead_bufs() + * ensures they see all buffer data. + */ + smp_store_release(&b->commit, b->used); + /* + * Paired w/ acquire in flush_to_ldisc() and lookahead_bufs() + * ensures the latest commit value can be read before the head + * is advanced to the next buffer. + */ + smp_store_release(&b->next, n); + return size; } @@ -304,108 +297,45 @@ int tty_buffer_request_room(struct tty_port *port, size_t size) } EXPORT_SYMBOL_GPL(tty_buffer_request_room); -/** - * tty_insert_flip_string_fixed_flag - add characters to the tty buffer - * @port: tty port - * @chars: characters - * @flag: flag value for each character - * @size: size - * - * Queue a series of bytes to the tty buffering. All the characters passed are - * marked with the supplied flag. - * - * Returns: the number added. - */ -int tty_insert_flip_string_fixed_flag(struct tty_port *port, - const unsigned char *chars, char flag, size_t size) +size_t __tty_insert_flip_string_flags(struct tty_port *port, const u8 *chars, + const u8 *flags, bool mutable_flags, + size_t size) { - int copied = 0; - bool flags = flag != TTY_NORMAL; + bool need_flags = mutable_flags || flags[0] != TTY_NORMAL; + size_t copied = 0; do { - int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); - int space = __tty_buffer_request_room(port, goal, flags); + size_t goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); + size_t space = __tty_buffer_request_room(port, goal, need_flags); struct tty_buffer *tb = port->buf.tail; if (unlikely(space == 0)) break; - memcpy(char_buf_ptr(tb, tb->used), chars, space); - if (tb->flags) - memset(flag_buf_ptr(tb, tb->used), flag, space); - tb->used += space; - copied += space; - chars += space; - /* There is a small chance that we need to split the data over - * several buffers. If this is the case we must loop. - */ - } while (unlikely(size > copied)); - return copied; -} -EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag); -/** - * tty_insert_flip_string_flags - add characters to the tty buffer - * @port: tty port - * @chars: characters - * @flags: flag bytes - * @size: size - * - * Queue a series of bytes to the tty buffering. For each character the flags - * array indicates the status of the character. - * - * Returns: the number added. - */ -int tty_insert_flip_string_flags(struct tty_port *port, - const unsigned char *chars, const char *flags, size_t size) -{ - int copied = 0; + memcpy(char_buf_ptr(tb, tb->used), chars, space); - do { - int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); - int space = tty_buffer_request_room(port, goal); - struct tty_buffer *tb = port->buf.tail; + if (mutable_flags) { + memcpy(flag_buf_ptr(tb, tb->used), flags, space); + flags += space; + } else if (tb->flags) { + memset(flag_buf_ptr(tb, tb->used), flags[0], space); + } else { + /* tb->flags should be available once requested */ + WARN_ON_ONCE(need_flags); + } - if (unlikely(space == 0)) - break; - memcpy(char_buf_ptr(tb, tb->used), chars, space); - memcpy(flag_buf_ptr(tb, tb->used), flags, space); tb->used += space; copied += space; chars += space; - flags += space; + /* There is a small chance that we need to split the data over * several buffers. If this is the case we must loop. */ } while (unlikely(size > copied)); - return copied; -} -EXPORT_SYMBOL(tty_insert_flip_string_flags); - -/** - * __tty_insert_flip_char - add one character to the tty buffer - * @port: tty port - * @ch: character - * @flag: flag byte - * - * Queue a single byte @ch to the tty buffering, with an optional flag. This is - * the slow path of tty_insert_flip_char(). - */ -int __tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag) -{ - struct tty_buffer *tb; - bool flags = flag != TTY_NORMAL; - - if (!__tty_buffer_request_room(port, 1, flags)) - return 0; - tb = port->buf.tail; - if (tb->flags) - *flag_buf_ptr(tb, tb->used) = flag; - *char_buf_ptr(tb, tb->used++) = ch; - - return 1; + return copied; } -EXPORT_SYMBOL(__tty_insert_flip_char); +EXPORT_SYMBOL(__tty_insert_flip_string_flags); /** * tty_prepare_flip_string - make room for characters @@ -421,10 +351,9 @@ EXPORT_SYMBOL(__tty_insert_flip_char); * Returns: the length available and buffer pointer (@chars) to the space which * is now allocated and accounted for as ready for normal characters. */ -int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, - size_t size) +size_t tty_prepare_flip_string(struct tty_port *port, u8 **chars, size_t size) { - int space = __tty_buffer_request_room(port, size, false); + size_t space = __tty_buffer_request_room(port, size, false); if (likely(space)) { struct tty_buffer *tb = port->buf.tail; @@ -434,6 +363,7 @@ int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, memset(flag_buf_ptr(tb, tb->used), TTY_NORMAL, space); tb->used += space; } + return space; } EXPORT_SYMBOL_GPL(tty_prepare_flip_string); @@ -450,13 +380,13 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string); * * Returns: the number of bytes processed. */ -int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p, - const char *f, int count) +size_t tty_ldisc_receive_buf(struct tty_ldisc *ld, const u8 *p, const u8 *f, + size_t count) { if (ld->ops->receive_buf2) count = ld->ops->receive_buf2(ld->tty, p, f, count); else { - count = min_t(int, count, ld->tty->receive_room); + count = min_t(size_t, count, ld->tty->receive_room); if (count && ld->ops->receive_buf) ld->ops->receive_buf(ld->tty, p, f, count); } @@ -489,7 +419,7 @@ static void lookahead_bufs(struct tty_port *port, struct tty_buffer *head) } if (port->client_ops->lookahead_buf) { - unsigned char *p, *f = NULL; + u8 *p, *f = NULL; p = char_buf_ptr(head, head->lookahead); if (head->flags) @@ -502,12 +432,12 @@ static void lookahead_bufs(struct tty_port *port, struct tty_buffer *head) } } -static int -receive_buf(struct tty_port *port, struct tty_buffer *head, int count) +static size_t +receive_buf(struct tty_port *port, struct tty_buffer *head, size_t count) { - unsigned char *p = char_buf_ptr(head, head->read); - const char *f = NULL; - int n; + u8 *p = char_buf_ptr(head, head->read); + const u8 *f = NULL; + size_t n; if (head->flags) f = flag_buf_ptr(head, head->read); @@ -539,7 +469,7 @@ static void flush_to_ldisc(struct work_struct *work) while (1) { struct tty_buffer *head = buf->head; struct tty_buffer *next; - int count, rcvd; + size_t count, rcvd; /* Ldisc or user is trying to gain exclusive access */ if (atomic_read(&buf->priority)) @@ -620,7 +550,7 @@ EXPORT_SYMBOL(tty_flip_buffer_push); * Returns: the number added. */ int tty_insert_flip_string_and_push_buffer(struct tty_port *port, - const unsigned char *chars, size_t size) + const u8 *chars, size_t size) { struct tty_bufhead *buf = &port->buf; unsigned long flags; |