aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/tty_buffer.c
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2013-06-15 09:36:09 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-23 19:47:09 -0400
commite8437d7ecbc50198705331449367d401ebb3181f (patch)
treea5e2eff33c0ea9b5349bb03e890f3768730365e2 /drivers/tty/tty_buffer.c
parent7bfe0b7116be207cf2204ae06335cc89d8f8ee02 (diff)
tty: Make driver-side flip buffers lockless
Driver-side flip buffer input is already single-threaded; 'publish' the .next link as the last operation on the tail buffer so the 'consumer' sees the already-completed flip buffer. The commit buffer index is already 'published' by driver-side functions. Signed-off-by: Peter Hurley <peter@hurleysoftware.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.c31
1 files changed, 4 insertions, 27 deletions
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 5d5a56407aa8..685757c6ce87 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -62,8 +62,6 @@ static void tty_buffer_reset(struct tty_buffer *p, size_t size)
62 * 62 *
63 * Remove all the buffers pending on a tty whether queued with data 63 * Remove all the buffers pending on a tty whether queued with data
64 * or in the free ring. Must be called when the tty is no longer in use 64 * or in the free ring. Must be called when the tty is no longer in use
65 *
66 * Locking: none
67 */ 65 */
68 66
69void tty_buffer_free_all(struct tty_port *port) 67void tty_buffer_free_all(struct tty_port *port)
@@ -216,29 +214,26 @@ void tty_buffer_flush(struct tty_struct *tty)
216 * 214 *
217 * Make at least size bytes of linear space available for the tty 215 * Make at least size bytes of linear space available for the tty
218 * buffer. If we fail return the size we managed to find. 216 * buffer. If we fail return the size we managed to find.
219 *
220 * Locking: Takes port->buf.lock
221 */ 217 */
222int tty_buffer_request_room(struct tty_port *port, size_t size) 218int tty_buffer_request_room(struct tty_port *port, size_t size)
223{ 219{
224 struct tty_bufhead *buf = &port->buf; 220 struct tty_bufhead *buf = &port->buf;
225 struct tty_buffer *b, *n; 221 struct tty_buffer *b, *n;
226 int left; 222 int left;
227 unsigned long flags; 223
228 spin_lock_irqsave(&buf->lock, flags);
229 b = buf->tail; 224 b = buf->tail;
230 left = b->size - b->used; 225 left = b->size - b->used;
231 226
232 if (left < size) { 227 if (left < size) {
233 /* This is the slow path - looking for new buffers to use */ 228 /* This is the slow path - looking for new buffers to use */
234 if ((n = tty_buffer_alloc(port, size)) != NULL) { 229 if ((n = tty_buffer_alloc(port, size)) != NULL) {
235 b->next = n;
236 b->commit = b->used;
237 buf->tail = n; 230 buf->tail = n;
231 b->commit = b->used;
232 smp_mb();
233 b->next = n;
238 } else 234 } else
239 size = left; 235 size = left;
240 } 236 }
241 spin_unlock_irqrestore(&buf->lock, flags);
242 return size; 237 return size;
243} 238}
244EXPORT_SYMBOL_GPL(tty_buffer_request_room); 239EXPORT_SYMBOL_GPL(tty_buffer_request_room);
@@ -252,8 +247,6 @@ EXPORT_SYMBOL_GPL(tty_buffer_request_room);
252 * 247 *
253 * Queue a series of bytes to the tty buffering. All the characters 248 * Queue a series of bytes to the tty buffering. All the characters
254 * passed are marked with the supplied flag. Returns the number added. 249 * passed are marked with the supplied flag. Returns the number added.
255 *
256 * Locking: Called functions may take port->buf.lock
257 */ 250 */
258 251
259int tty_insert_flip_string_fixed_flag(struct tty_port *port, 252int tty_insert_flip_string_fixed_flag(struct tty_port *port,
@@ -288,8 +281,6 @@ EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag);
288 * Queue a series of bytes to the tty buffering. For each character 281 * Queue a series of bytes to the tty buffering. For each character
289 * the flags array indicates the status of the character. Returns the 282 * the flags array indicates the status of the character. Returns the
290 * number added. 283 * number added.
291 *
292 * Locking: Called functions may take port->buf.lock
293 */ 284 */
294 285
295int tty_insert_flip_string_flags(struct tty_port *port, 286int tty_insert_flip_string_flags(struct tty_port *port,
@@ -324,19 +315,14 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags);
324 * processing by the line discipline. 315 * processing by the line discipline.
325 * Note that this function can only be used when the low_latency flag 316 * Note that this function can only be used when the low_latency flag
326 * is unset. Otherwise the workqueue won't be flushed. 317 * is unset. Otherwise the workqueue won't be flushed.
327 *
328 * Locking: Takes port->buf.lock
329 */ 318 */
330 319
331void tty_schedule_flip(struct tty_port *port) 320void tty_schedule_flip(struct tty_port *port)
332{ 321{
333 struct tty_bufhead *buf = &port->buf; 322 struct tty_bufhead *buf = &port->buf;
334 unsigned long flags;
335 WARN_ON(port->low_latency); 323 WARN_ON(port->low_latency);
336 324
337 spin_lock_irqsave(&buf->lock, flags);
338 buf->tail->commit = buf->tail->used; 325 buf->tail->commit = buf->tail->used;
339 spin_unlock_irqrestore(&buf->lock, flags);
340 schedule_work(&buf->work); 326 schedule_work(&buf->work);
341} 327}
342EXPORT_SYMBOL(tty_schedule_flip); 328EXPORT_SYMBOL(tty_schedule_flip);
@@ -352,8 +338,6 @@ EXPORT_SYMBOL(tty_schedule_flip);
352 * accounted for as ready for normal characters. This is used for drivers 338 * accounted for as ready for normal characters. This is used for drivers
353 * that need their own block copy routines into the buffer. There is no 339 * that need their own block copy routines into the buffer. There is no
354 * guarantee the buffer is a DMA target! 340 * guarantee the buffer is a DMA target!
355 *
356 * Locking: May call functions taking port->buf.lock
357 */ 341 */
358 342
359int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, 343int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars,
@@ -382,8 +366,6 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
382 * accounted for as ready for characters. This is used for drivers 366 * accounted for as ready for characters. This is used for drivers
383 * that need their own block copy routines into the buffer. There is no 367 * that need their own block copy routines into the buffer. There is no
384 * guarantee the buffer is a DMA target! 368 * guarantee the buffer is a DMA target!
385 *
386 * Locking: May call functions taking port->buf.lock
387 */ 369 */
388 370
389int tty_prepare_flip_string_flags(struct tty_port *port, 371int tty_prepare_flip_string_flags(struct tty_port *port,
@@ -511,18 +493,13 @@ void tty_flush_to_ldisc(struct tty_struct *tty)
511 * 493 *
512 * In the event of the queue being busy for flipping the work will be 494 * In the event of the queue being busy for flipping the work will be
513 * held off and retried later. 495 * held off and retried later.
514 *
515 * Locking: tty buffer lock. Driver locks in low latency mode.
516 */ 496 */
517 497
518void tty_flip_buffer_push(struct tty_port *port) 498void tty_flip_buffer_push(struct tty_port *port)
519{ 499{
520 struct tty_bufhead *buf = &port->buf; 500 struct tty_bufhead *buf = &port->buf;
521 unsigned long flags;
522 501
523 spin_lock_irqsave(&buf->lock, flags);
524 buf->tail->commit = buf->tail->used; 502 buf->tail->commit = buf->tail->used;
525 spin_unlock_irqrestore(&buf->lock, flags);
526 503
527 if (port->low_latency) 504 if (port->low_latency)
528 flush_to_ldisc(&buf->work); 505 flush_to_ldisc(&buf->work);