aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/tty_buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/tty_buffer.c')
-rw-r--r--drivers/tty/tty_buffer.c131
1 files changed, 42 insertions, 89 deletions
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 45d916198f78..bb119934e76c 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -16,6 +16,7 @@
16#include <linux/bitops.h> 16#include <linux/bitops.h>
17#include <linux/delay.h> 17#include <linux/delay.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/ratelimit.h>
19 20
20/** 21/**
21 * tty_buffer_free_all - free buffers used by a tty 22 * tty_buffer_free_all - free buffers used by a tty
@@ -119,11 +120,14 @@ static void __tty_buffer_flush(struct tty_port *port)
119 struct tty_bufhead *buf = &port->buf; 120 struct tty_bufhead *buf = &port->buf;
120 struct tty_buffer *thead; 121 struct tty_buffer *thead;
121 122
122 while ((thead = buf->head) != NULL) { 123 if (unlikely(buf->head == NULL))
123 buf->head = thead->next; 124 return;
124 tty_buffer_free(port, thead); 125 while ((thead = buf->head->next) != NULL) {
126 tty_buffer_free(port, buf->head);
127 buf->head = thead;
125 } 128 }
126 buf->tail = NULL; 129 WARN_ON(buf->head != buf->tail);
130 buf->head->read = buf->head->commit;
127} 131}
128 132
129/** 133/**
@@ -194,19 +198,22 @@ static struct tty_buffer *tty_buffer_find(struct tty_port *port, size_t size)
194 have queued and recycle that ? */ 198 have queued and recycle that ? */
195} 199}
196/** 200/**
197 * __tty_buffer_request_room - grow tty buffer if needed 201 * tty_buffer_request_room - grow tty buffer if needed
198 * @tty: tty structure 202 * @tty: tty structure
199 * @size: size desired 203 * @size: size desired
200 * 204 *
201 * Make at least size bytes of linear space available for the tty 205 * Make at least size bytes of linear space available for the tty
202 * buffer. If we fail return the size we managed to find. 206 * buffer. If we fail return the size we managed to find.
203 * Locking: Caller must hold port->buf.lock 207 *
208 * Locking: Takes port->buf.lock
204 */ 209 */
205static int __tty_buffer_request_room(struct tty_port *port, size_t size) 210int tty_buffer_request_room(struct tty_port *port, size_t size)
206{ 211{
207 struct tty_bufhead *buf = &port->buf; 212 struct tty_bufhead *buf = &port->buf;
208 struct tty_buffer *b, *n; 213 struct tty_buffer *b, *n;
209 int left; 214 int left;
215 unsigned long flags;
216 spin_lock_irqsave(&buf->lock, flags);
210 /* OPTIMISATION: We could keep a per tty "zero" sized buffer to 217 /* OPTIMISATION: We could keep a per tty "zero" sized buffer to
211 remove this conditional if its worth it. This would be invisible 218 remove this conditional if its worth it. This would be invisible
212 to the callers */ 219 to the callers */
@@ -228,37 +235,14 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size)
228 } else 235 } else
229 size = left; 236 size = left;
230 } 237 }
231 238 spin_unlock_irqrestore(&buf->lock, flags);
232 return size; 239 return size;
233} 240}
234
235
236/**
237 * tty_buffer_request_room - grow tty buffer if needed
238 * @tty: tty structure
239 * @size: size desired
240 *
241 * Make at least size bytes of linear space available for the tty
242 * buffer. If we fail return the size we managed to find.
243 *
244 * Locking: Takes port->buf.lock
245 */
246int tty_buffer_request_room(struct tty_struct *tty, size_t size)
247{
248 struct tty_port *port = tty->port;
249 unsigned long flags;
250 int length;
251
252 spin_lock_irqsave(&port->buf.lock, flags);
253 length = __tty_buffer_request_room(port, size);
254 spin_unlock_irqrestore(&port->buf.lock, flags);
255 return length;
256}
257EXPORT_SYMBOL_GPL(tty_buffer_request_room); 241EXPORT_SYMBOL_GPL(tty_buffer_request_room);
258 242
259/** 243/**
260 * tty_insert_flip_string_fixed_flag - Add characters to the tty buffer 244 * tty_insert_flip_string_fixed_flag - Add characters to the tty buffer
261 * @tty: tty structure 245 * @port: tty port
262 * @chars: characters 246 * @chars: characters
263 * @flag: flag value for each character 247 * @flag: flag value for each character
264 * @size: size 248 * @size: size
@@ -269,29 +253,21 @@ EXPORT_SYMBOL_GPL(tty_buffer_request_room);
269 * Locking: Called functions may take port->buf.lock 253 * Locking: Called functions may take port->buf.lock
270 */ 254 */
271 255
272int tty_insert_flip_string_fixed_flag(struct tty_struct *tty, 256int tty_insert_flip_string_fixed_flag(struct tty_port *port,
273 const unsigned char *chars, char flag, size_t size) 257 const unsigned char *chars, char flag, size_t size)
274{ 258{
275 struct tty_bufhead *buf = &tty->port->buf;
276 int copied = 0; 259 int copied = 0;
277 do { 260 do {
278 int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); 261 int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
279 int space; 262 int space = tty_buffer_request_room(port, goal);
280 unsigned long flags; 263 struct tty_buffer *tb = port->buf.tail;
281 struct tty_buffer *tb;
282
283 spin_lock_irqsave(&buf->lock, flags);
284 space = __tty_buffer_request_room(tty->port, goal);
285 tb = buf->tail;
286 /* If there is no space then tb may be NULL */ 264 /* If there is no space then tb may be NULL */
287 if (unlikely(space == 0)) { 265 if (unlikely(space == 0)) {
288 spin_unlock_irqrestore(&buf->lock, flags);
289 break; 266 break;
290 } 267 }
291 memcpy(tb->char_buf_ptr + tb->used, chars, space); 268 memcpy(tb->char_buf_ptr + tb->used, chars, space);
292 memset(tb->flag_buf_ptr + tb->used, flag, space); 269 memset(tb->flag_buf_ptr + tb->used, flag, space);
293 tb->used += space; 270 tb->used += space;
294 spin_unlock_irqrestore(&buf->lock, flags);
295 copied += space; 271 copied += space;
296 chars += space; 272 chars += space;
297 /* There is a small chance that we need to split the data over 273 /* There is a small chance that we need to split the data over
@@ -303,7 +279,7 @@ EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag);
303 279
304/** 280/**
305 * tty_insert_flip_string_flags - Add characters to the tty buffer 281 * tty_insert_flip_string_flags - Add characters to the tty buffer
306 * @tty: tty structure 282 * @port: tty port
307 * @chars: characters 283 * @chars: characters
308 * @flags: flag bytes 284 * @flags: flag bytes
309 * @size: size 285 * @size: size
@@ -315,29 +291,21 @@ EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag);
315 * Locking: Called functions may take port->buf.lock 291 * Locking: Called functions may take port->buf.lock
316 */ 292 */
317 293
318int tty_insert_flip_string_flags(struct tty_struct *tty, 294int tty_insert_flip_string_flags(struct tty_port *port,
319 const unsigned char *chars, const char *flags, size_t size) 295 const unsigned char *chars, const char *flags, size_t size)
320{ 296{
321 struct tty_bufhead *buf = &tty->port->buf;
322 int copied = 0; 297 int copied = 0;
323 do { 298 do {
324 int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); 299 int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
325 int space; 300 int space = tty_buffer_request_room(port, goal);
326 unsigned long __flags; 301 struct tty_buffer *tb = port->buf.tail;
327 struct tty_buffer *tb;
328
329 spin_lock_irqsave(&buf->lock, __flags);
330 space = __tty_buffer_request_room(tty->port, goal);
331 tb = buf->tail;
332 /* If there is no space then tb may be NULL */ 302 /* If there is no space then tb may be NULL */
333 if (unlikely(space == 0)) { 303 if (unlikely(space == 0)) {
334 spin_unlock_irqrestore(&buf->lock, __flags);
335 break; 304 break;
336 } 305 }
337 memcpy(tb->char_buf_ptr + tb->used, chars, space); 306 memcpy(tb->char_buf_ptr + tb->used, chars, space);
338 memcpy(tb->flag_buf_ptr + tb->used, flags, space); 307 memcpy(tb->flag_buf_ptr + tb->used, flags, space);
339 tb->used += space; 308 tb->used += space;
340 spin_unlock_irqrestore(&buf->lock, __flags);
341 copied += space; 309 copied += space;
342 chars += space; 310 chars += space;
343 flags += space; 311 flags += space;
@@ -350,7 +318,7 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags);
350 318
351/** 319/**
352 * tty_schedule_flip - push characters to ldisc 320 * tty_schedule_flip - push characters to ldisc
353 * @tty: tty to push from 321 * @port: tty port to push from
354 * 322 *
355 * Takes any pending buffers and transfers their ownership to the 323 * Takes any pending buffers and transfers their ownership to the
356 * ldisc side of the queue. It then schedules those characters for 324 * ldisc side of the queue. It then schedules those characters for
@@ -361,11 +329,11 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags);
361 * Locking: Takes port->buf.lock 329 * Locking: Takes port->buf.lock
362 */ 330 */
363 331
364void tty_schedule_flip(struct tty_struct *tty) 332void tty_schedule_flip(struct tty_port *port)
365{ 333{
366 struct tty_bufhead *buf = &tty->port->buf; 334 struct tty_bufhead *buf = &port->buf;
367 unsigned long flags; 335 unsigned long flags;
368 WARN_ON(tty->low_latency); 336 WARN_ON(port->low_latency);
369 337
370 spin_lock_irqsave(&buf->lock, flags); 338 spin_lock_irqsave(&buf->lock, flags);
371 if (buf->tail != NULL) 339 if (buf->tail != NULL)
@@ -377,7 +345,7 @@ EXPORT_SYMBOL(tty_schedule_flip);
377 345
378/** 346/**
379 * tty_prepare_flip_string - make room for characters 347 * tty_prepare_flip_string - make room for characters
380 * @tty: tty 348 * @port: tty port
381 * @chars: return pointer for character write area 349 * @chars: return pointer for character write area
382 * @size: desired size 350 * @size: desired size
383 * 351 *
@@ -390,31 +358,23 @@ EXPORT_SYMBOL(tty_schedule_flip);
390 * Locking: May call functions taking port->buf.lock 358 * Locking: May call functions taking port->buf.lock
391 */ 359 */
392 360
393int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, 361int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars,
394 size_t size) 362 size_t size)
395{ 363{
396 struct tty_bufhead *buf = &tty->port->buf; 364 int space = tty_buffer_request_room(port, size);
397 int space;
398 unsigned long flags;
399 struct tty_buffer *tb;
400
401 spin_lock_irqsave(&buf->lock, flags);
402 space = __tty_buffer_request_room(tty->port, size);
403
404 tb = buf->tail;
405 if (likely(space)) { 365 if (likely(space)) {
366 struct tty_buffer *tb = port->buf.tail;
406 *chars = tb->char_buf_ptr + tb->used; 367 *chars = tb->char_buf_ptr + tb->used;
407 memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space); 368 memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
408 tb->used += space; 369 tb->used += space;
409 } 370 }
410 spin_unlock_irqrestore(&buf->lock, flags);
411 return space; 371 return space;
412} 372}
413EXPORT_SYMBOL_GPL(tty_prepare_flip_string); 373EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
414 374
415/** 375/**
416 * tty_prepare_flip_string_flags - make room for characters 376 * tty_prepare_flip_string_flags - make room for characters
417 * @tty: tty 377 * @port: tty port
418 * @chars: return pointer for character write area 378 * @chars: return pointer for character write area
419 * @flags: return pointer for status flag write area 379 * @flags: return pointer for status flag write area
420 * @size: desired size 380 * @size: desired size
@@ -428,24 +388,16 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
428 * Locking: May call functions taking port->buf.lock 388 * Locking: May call functions taking port->buf.lock
429 */ 389 */
430 390
431int tty_prepare_flip_string_flags(struct tty_struct *tty, 391int tty_prepare_flip_string_flags(struct tty_port *port,
432 unsigned char **chars, char **flags, size_t size) 392 unsigned char **chars, char **flags, size_t size)
433{ 393{
434 struct tty_bufhead *buf = &tty->port->buf; 394 int space = tty_buffer_request_room(port, size);
435 int space;
436 unsigned long __flags;
437 struct tty_buffer *tb;
438
439 spin_lock_irqsave(&buf->lock, __flags);
440 space = __tty_buffer_request_room(tty->port, size);
441
442 tb = buf->tail;
443 if (likely(space)) { 395 if (likely(space)) {
396 struct tty_buffer *tb = port->buf.tail;
444 *chars = tb->char_buf_ptr + tb->used; 397 *chars = tb->char_buf_ptr + tb->used;
445 *flags = tb->flag_buf_ptr + tb->used; 398 *flags = tb->flag_buf_ptr + tb->used;
446 tb->used += space; 399 tb->used += space;
447 } 400 }
448 spin_unlock_irqrestore(&buf->lock, __flags);
449 return space; 401 return space;
450} 402}
451EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); 403EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
@@ -539,16 +491,17 @@ static void flush_to_ldisc(struct work_struct *work)
539 */ 491 */
540void tty_flush_to_ldisc(struct tty_struct *tty) 492void tty_flush_to_ldisc(struct tty_struct *tty)
541{ 493{
542 if (!tty->low_latency) 494 if (!tty->port->low_latency)
543 flush_work(&tty->port->buf.work); 495 flush_work(&tty->port->buf.work);
544} 496}
545 497
546/** 498/**
547 * tty_flip_buffer_push - terminal 499 * tty_flip_buffer_push - terminal
548 * @tty: tty to push 500 * @port: tty port to push
549 * 501 *
550 * Queue a push of the terminal flip buffers to the line discipline. This 502 * Queue a push of the terminal flip buffers to the line discipline. This
551 * function must not be called from IRQ context if tty->low_latency is set. 503 * function must not be called from IRQ context if port->low_latency is
504 * set.
552 * 505 *
553 * In the event of the queue being busy for flipping the work will be 506 * In the event of the queue being busy for flipping the work will be
554 * held off and retried later. 507 * held off and retried later.
@@ -556,9 +509,9 @@ void tty_flush_to_ldisc(struct tty_struct *tty)
556 * Locking: tty buffer lock. Driver locks in low latency mode. 509 * Locking: tty buffer lock. Driver locks in low latency mode.
557 */ 510 */
558 511
559void tty_flip_buffer_push(struct tty_struct *tty) 512void tty_flip_buffer_push(struct tty_port *port)
560{ 513{
561 struct tty_bufhead *buf = &tty->port->buf; 514 struct tty_bufhead *buf = &port->buf;
562 unsigned long flags; 515 unsigned long flags;
563 516
564 spin_lock_irqsave(&buf->lock, flags); 517 spin_lock_irqsave(&buf->lock, flags);
@@ -566,7 +519,7 @@ void tty_flip_buffer_push(struct tty_struct *tty)
566 buf->tail->commit = buf->tail->used; 519 buf->tail->commit = buf->tail->used;
567 spin_unlock_irqrestore(&buf->lock, flags); 520 spin_unlock_irqrestore(&buf->lock, flags);
568 521
569 if (tty->low_latency) 522 if (port->low_latency)
570 flush_to_ldisc(&buf->work); 523 flush_to_ldisc(&buf->work);
571 else 524 else
572 schedule_work(&buf->work); 525 schedule_work(&buf->work);