- May 04, 2014
-
-
Peter Hurley authored
This reverts commit 6a20dbd6. Although the commit correctly identifies an unsafe race condition between __tty_buffer_request_room() and flush_to_ldisc(), the commit fixes the race with an unnecessary spinlock in a lockless algorithm. The follow-on commit, "tty: Fix lockless tty buffer race" fixes the race locklessly. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
- Apr 25, 2014
-
-
Manfred Schlaegl authored
The race was introduced while development of linux-3.11 by e8437d7e and e9975fde. Originally it was found and reproduced on linux-3.12.15 and linux-3.12.15-rt25, by sending 500 byte blocks with 115kbaud to the target uart in a loop with 100 milliseconds delay. In short: 1. The consumer flush_to_ldisc is on to remove the head tty_buffer. 2. The producer adds a number of bytes, so that a new tty_buffer must be allocated and added by __tty_buffer_request_room. 3. The consumer removes the head tty_buffer element, without handling newly committed data. Detailed example: * Initial buffer: * Head, Tail -> 0: used=250; commit=250; read=240; next=NULL * Consumer: ''flush_to_ldisc'' * consumed 10 Byte * buffer: * Head, Tail -> 0: used=250; commit=250; read=250; next=NULL {{{ count = head->commit - head->read; // count = 0 if (!count) { // enter // INTERRUPTED BY PRODUCER -> if (head->next == NULL) break; buf->head = head->next; tty_buffer_free(port, head); continue; } }}} * Producer: tty_insert_flip_... 10 bytes + tty_flip_buffer_push * buffer: * Head, Tail -> 0: used=250; commit=250; read=250; next=NULL * added 6 bytes: head-element filled to maximum. * buffer: * Head, Tail -> 0: used=256; commit=250; read=250; next=NULL * added 4 bytes: __tty_buffer_request_room is called * buffer: * Head -> 0: used=256; commit=256; read=250; next=1 * Tail -> 1: used=4; commit=0; read=250 next=NULL * push (tty_flip_buffer_push) * buffer: * Head -> 0: used=256; commit=256; read=250; next=1 * Tail -> 1: used=4; commit=4; read=250 next=NULL * Consumer {{{ count = head->commit - head->read; if (!count) { // INTERRUPTED BY PRODUCER <- if (head->next == NULL) // -> no break break; buf->head = head->next; tty_buffer_free(port, head); // ERROR: tty_buffer head freed -> 6 bytes lost continue; } }}} This patch reintroduces a spin_lock to protect this case. Perhaps later a lock-less solution could be found. Signed-off-by:
Manfred Schlaegl <manfred.schlaegl@gmx.at> Cc: stable <stable@vger.kernel.org> # 3.11 Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
- Mar 01, 2014
-
-
Peter Hurley authored
The user-settable knob, low_latency, has been the source of several BUG reports which stem from flush_to_ldisc() running in interrupt context. Since 3.12, which added several sleeping locks (termios_rwsem and buf->lock) to the input processing path, the frequency of these BUG reports has increased. Note that changes in 3.12 did not introduce this regression; sleeping locks were first added to the input processing path with the removal of the BKL from N_TTY in commit a88a69c9, 'n_tty: Fix loss of echoed characters and remove bkl from n_tty' and later in commit 38db8979, 'tty: throttling race fix'. Since those changes, executing flush_to_ldisc() in interrupt_context (ie, low_latency set), is unsafe. However, since most devices do not validate if the low_latency setting is appropriate for the context (process or interrupt) in which they receive data, some reports are due to misconfiguration. Further, serial dma devices for which dma fails, resort to interrupt receiving as a backup without resetting low_latency. Historically, low_latency was used to force wake-up the reading process rather than wait for the next scheduler tick. The effect was to trim multiple milliseconds of latency from when the process would receive new data. Recent tests [1] have shown that the reading process now receives data with only 10's of microseconds latency without low_latency set. Remove the low_latency rx steering from tty_flip_buffer_push(); however, leave the knob as an optional hint to drivers that can tune their rx fifos and such like. Cleanup stale code comments regarding low_latency. [1] https://lkml.org/lkml/2014/2/20/434 "Yay.. thats an annoying historical pain in the butt gone." -- Alan Cox Reported-by:
Beat Bolli <bbolli@ewanet.ch> Reported-by:
Pavel Roskin <proski@gnu.org> Acked-by:
David Sterba <dsterba@suse.cz> Cc: Grant Edwards <grant.b.edwards@gmail.com> Cc: Stanislaw Gruszka <sgruszka@redhat.com> Cc: Hal Murray <murray+fedora@ip-64-139-1-69.sjc.megapath.net> Cc: <stable@vger.kernel.org> # 3.12.x+ Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Alan Cox <alan@linux.intel.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
- Jan 08, 2014
-
-
Paul Gortmaker authored
None of these files are actually using any __init type directives and hence don't need to include <linux/init.h>. Most are just a left over from __devinit and __cpuinit removal, or simply due to code getting copied from one driver to the next. Signed-off-by:
Paul Gortmaker <paul.gortmaker@windriver.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
- Dec 09, 2013
-
-
Peter Hurley authored
tty flip buffers use GFP_ATOMIC allocations for received data which is to be processed by the line discipline. For each byte received, an extra byte is used to indicate the error status of that byte. Instead, if the received data is error-free, encode the entire buffer without status bytes. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
Commit d7a68be4, 'tty: Only perform flip buffer flush from tty_buffer_flush()', removed buffer flushing from flush_to_ldisc(). Fix function header comment which describes the former behavior. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
There is no in-tree user of tty_prepare_flip_string_flags(); remove. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
Trim up the memory_used field name to mem_used. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
Allow driver to configure its maximum flip buffer memory consumption/limit. This is necessary for very-high speed line rates (in excess of 10MB/sec) because the flip buffers can be saturated before the line discipline has a chance to throttle the input. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
- Jul 24, 2013
-
-
Peter Hurley authored
TTY_BUFFER_PAGE is only used within drivers/tty/tty_buffer.c; relocate to that file scope. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
Convert the tty_buffer_flush() exclusion mechanism to a public interface - tty_buffer_lock/unlock_exclusive() - and use the interface to safely write the paste selection to the line discipline. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
__tty_flush_buffer() is now only called by tty_flush_buffer(); merge functions. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
Atomic bit ops are no longer required to indicate a flip buffer flush is pending, as the flush_mutex is sufficient barrier. Remove the unnecessary port .iflags field and localize flip buffer state to struct tty_bufhead. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
Now that dropping the buffer lock is not necessary (as result of converting the spin lock to a mutex), the flip buffer flush no longer needs to be handled by the buffer work. Simply signal a flush is required; the buffer work will exit the i/o loop, which allows tty_buffer_flush() to proceed. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
The buffer work may race with parallel tty_buffer_flush. Use a mutex to guarantee exclusive modify access to the head flip buffer. Remove the unneeded spin lock. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
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>
-
Peter Hurley authored
Lockless flip buffers require atomically updating the bytes-in-use watermark. The pty driver also peeks at the watermark value to limit memory consumption to a much lower value than the default; query the watermark with new fn, tty_buffer_space_avail(). Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
Use a 0-sized sentinel to avoid assigning the head ptr from the driver side thread. This also eliminates testing head/tail for NULL. When the sentinel is first 'consumed' by the buffer work (or by tty_buffer_flush()), it is detached from the list but not freed nor added to the free list. Both buffer work and tty_buffer_flush() continue to preserve at least 1 flip buffer to which head & tail is pointed. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
In preparation for lockless flip buffers, make the flip buffer free list lockless. NB: using llist is not the optimal solution, as the driver and buffer work may contend over the llist head unnecessarily. However, test measurements indicate this contention is low. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
tty_buffer_find() implements a simple free list lookaside cache. Merge this functionality into tty_buffer_alloc() to reflect the more traditional alloc/free symmetry. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
Factor shared code; prepare for adding 0-sized sentinel flip buffer. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
Since flip buffers are size-aligned to 256 bytes and all flip buffers 512-bytes or larger are not added to the free list, the free list only contains 256-byte flip buffers. Remove the list search when allocating a new flip buffer. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
The char_buf_ptr and flag_buf_ptr values are trivially derived from the .data field offset; compute values as needed. Fixes a long-standing type-mismatch with the char and flag ptrs. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
Although line discipline receiving is single-producer/single-consumer, using tty->receive_room to manage flow control creates unnecessary critical regions requiring additional lock use. Instead, introduce the optional .receive_buf2() ldisc method which returns the # of bytes actually received. Serialization is guaranteed by the caller. In turn, the line discipline should schedule the buffer work item whenever space becomes available; ie., when there is room to receive data and receive_room() previously returned 0 (the buffer work item stops processing if receive_buf2() returns 0). Note the 'no room' state need not be atomic despite concurrent use by two threads because only the buffer work thread can set the state and only the read() thread can clear the state. Add n_tty_receive_buf2() as the receive_buf2() method for N_TTY. Provide a public helper function, tty_ldisc_receive_buf(), to use when directly accessing the receive_buf() methods. Line disciplines not using input flow control can continue to set tty->receive_room to a fixed value and only provide the receive_buf() method. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
Ldisc interface functions must be called with interrupts enabled. Separating the ldisc calls into a helper function simplies the eventual removal of the spinlock. Note that access to the buf->head ptr outside the spinlock is safe here because; * __tty_buffer_flush() is prevented from running while buffer work performs i/o, * tty_buffer_find() only assigns buf->head if the flip buffer list is empty (which is never the case in flush_to_ldisc() since at least one buffer is always left in the list after use) Access to the read index outside the spinlock is safe here for the same reasons. Update the buffer's read index _after_ the data has been received by the ldisc. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Peter Hurley authored
Line discipline locking was performed with a combination of a mutex, a status bit, a count, and a waitqueue -- basically, a rw semaphore. Replace the existing combination with an ld_semaphore. Fixes: 1) the 'reference acquire after ldisc locked' bug 2) the over-complicated halt mechanism 3) lock order wrt. tty_lock() 4) dropping locks while changing ldisc 5) previously unidentified deadlock while locking ldisc from both linked ttys concurrently 6) previously unidentified recursive deadlocks Adds much-needed lockdep diagnostics. Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
- Apr 10, 2013
-
-
Peter Hurley authored
As Ilya Zykov identified in his patch 'PROBLEM: Race condition in tty buffer's function flush_to_ldisc()', a race condition exists which allows a parallel flush_to_ldisc() to flush and free the tty flip buffers while those buffers are in-use. For example, CPU 0 | CPU 1 | CPU 2 | flush_to_ldisc() | | grab spin lock | tty_buffer_flush() | | flush_to_ldisc() wait for spin lock | | wait for spin lock | if (!test_and_set_bit(TTYP_FLUSHING)) | | while (next flip buffer) | | ... | | drop spin lock | grab spin lock | | if (test_bit(TTYP_FLUSHING)) | | set_bit(TTYP_FLUSHPENDING) | receive_buf() | drop spin lock | | | | grab spin lock | | if (!test_and_set_bit(TTYP_FLUSHING)) | | if (test_bit(TTYP_FLUSHPENDING)) | | __tty_buffer_flush() CPU 2 has just flushed and freed all tty flip buffers while CPU 1 is transferring data from the head flip buffer. The original patch was rejected under the assumption that parallel flush_to_ldisc() was not possible. Because of necessary changes to the workqueue api, work items can execute in parallel on SMP. This patch differs slightly from the original patch by testing for a pending flush _after_ each receive_buf(), since TTYP_FLUSHPENDING can only be set while the lock is dropped around receive_buf(). Reported-by:
Ilya Zykov <linux@izyk.ru> Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Acked-by:
Ilya Zykov <linux@izyk.ru> Cc: Jiri Slaby <jslaby@suse.cz> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
- Mar 04, 2013
-
-
Jiri Slaby authored
We added a warning to flush_to_ldisc to report cases when it is called with a NULL tty. It was for debugging purposes and it lead to a patchset from Peter Hurley. The patchset however did not make it to 3.9, so disable the warning now to not disturb people. We can re-add it when the series is in and we are hunting for another bugs. Reported-by:
David Miller <davem@davemloft.net> Cc: stable <stable@vger.kernel.org> # 3.8 Signed-off-by:
Jiri Slaby <jslaby@suse.cz> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
- Feb 13, 2013
-
-
George Spelvin authored
The PPS (Pulse-Per-Second) line discipline has developed a number of unhealthy attachments to core tty data and functions, ultimately leading to its breakage. The previous patches fixed the crashing. This one reduces coupling further by eliminating the timestamp parameter from the dcd_change ldisc method. This reduces header file linkage and makes the extension more generic, and the timestamp read is delayed only slightly, from just before the ldisc->ops->dcd_change method call to just after. Fix attendant build breakage in drivers/tty/n_tty.c drivers/tty/tty_buffer.c drivers/staging/speakup/selection.c drivers/staging/dgrp/dgrp_*.c Cc: William Hubbs <w.d.hubbs@gmail.com> Cc: Chris Brannon <chris@the-brannons.com> Cc: Kirk Reiser <kirk@braille.uwo.ca> Cc: Samuel Thibault <samuel.thibault@ens-lyon.org> Signed-off-by:
Peter Hurley <peter@hurleysoftware.com> Signed-off-by:
George Spelvin <linux@horizon.com> Acked-by:
Rodolfo Giometti <giometti@enneenne.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
- Jan 21, 2013
-
-
Ilya Zykov authored
The root of problem is carelessly zeroing pointer(in function __tty_buffer_flush()), when another thread can use it. It can be cause of "NULL pointer dereference". Main idea of the patch, this is never free last (struct tty_buffer) in the active buffer. Only flush the data for ldisc(buf->head->read = buf->head->commit). At that moment driver can collect(write) data in buffer without conflict. It is repeat behavior of flush_to_ldisc(), only without feeding data to ldisc. Also revert: commit c56a00a1 tty: hold lock across tty buffer finding and buffer filling In order to delete the unneeded locks any more. Signed-off-by:
Ilya Zykov <ilya@ilyx.ru> CC: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
- Jan 16, 2013
-
-
Jiri Slaby authored
Now, we start converting tty buffer functions to actually use tty_port. This will allow us to get rid of the need of tty in many call sites. Only tty_port will needed and hence no more tty_port_tty_get in those paths. This is the last one: tty_schedule_flip Signed-off-by:
Jiri Slaby <jslaby@suse.cz> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Jiri Slaby authored
Now, we start converting tty buffer functions to actually use tty_port. This will allow us to get rid of the need of tty in many call sites. Only tty_port will needed and hence no more tty_port_tty_get in those paths. Now, the one where most of tty_port_tty_get gets removed: tty_flip_buffer_push. IOW we also closed all the races in drivers not using tty_port_tty_get at all yet. Also we move tty_flip_buffer_push declaration from include/linux/tty.h to include/linux/tty_flip.h to all others while we are changing it anyway. Signed-off-by:
Jiri Slaby <jslaby@suse.cz> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Jiri Slaby authored
One point is to have less places where we actually need tty pointer. The other is that low_latency is bound to buffer processing and buffers are now in tty_port. So it makes sense to move low_latency to tty_port too. Signed-off-by:
Jiri Slaby <jslaby@suse.cz> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Jiri Slaby authored
Now, we start converting tty buffer functions to actually use tty_port. This will allow us to get rid of the need of tty pointer in many call sites. Only tty_port will be needed and hence no more tty_port_tty_get calls in those paths. Now 4 string flipping ones are on turn: * tty_insert_flip_string_flags * tty_insert_flip_string_fixed_flag * tty_prepare_flip_string * tty_prepare_flip_string_flags Signed-off-by:
Jiri Slaby <jslaby@suse.cz> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
Jiri Slaby authored
Now, we start converting tty buffer functions to actually use tty_port. This will allow us to get rid of the need of tty pointer in many call sites. Only tty_port will be needed and hence no more tty_port_tty_get calls in those paths. Here we start with tty_buffer_request_room. Signed-off-by:
Jiri Slaby <jslaby@suse.cz> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
- Oct 25, 2012
-
-
Sasha Levin authored
WARN_RATELIMIT() expects the warning to end with a newline if one is needed. Not doing so results in odd looking warnings such as: [ 1339.454272] tty is NULLPid: 7147, comm: kworker/4:0 Tainted: G W 3.7.0-rc2-next-20121025-sasha-00001-g673f98e-dirty #75 Signed-off-by:
Sasha Levin <sasha.levin@oracle.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
- Oct 24, 2012
-
-
Ivo Sieben authored
When a driver has the low_latency flag set and uses the schedule_flip() function to initiate copying data to the line discipline, a workqueue is scheduled in but never actually flushed. This is incorrect use of the low_latency flag (driver should not support the low_latency flag, or use the tty_flip_buffer_push() function instead). Make sure a warning is reported to catch incorrect use of the low_latency flag. This patch goes with: cee4ad1e Signed-off-by:
Ivo Sieben <meltedpianoman@gmail.com> Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
- Oct 23, 2012
-
-
Jiri Slaby authored
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>
-