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