From: Stefan Bigler <stefan.bigler@keymile.com>
To: linux-kernel@vger.kernel.org
Subject: TTY loosing data with u_serial gadget
Date: Wed, 16 Mar 2011 21:47:50 +0100 [thread overview]
Message-ID: <4D8121F6.9060600@keymile.com> (raw)
Hi all
I'm facing a problem with TTY loosing data using u_serial gadget.
I have a MPC8247 based system running 2.6.33. Data transfer is done
bidirectional
to see the problem more often. I use tty in raw mode and do some delayed
reads on the
receiver side to stress the throttling / un-throttling.
I tracked down the problem and was able to see that n_tty_receive_buf()
is not able to store all data in the read queue.
The function flush_to_ldisc() use the values of tty->receive_room to
schedule_delayed_work()or to pass data to receive_buf() and finally
n_tty_receive_buf().
Also the number of passed bytes rely on variable receive_room.
I added debug code to re-calculate the real free space.
left_space = N_TTY_BUF_SIZE - tty->read_cnt - 1;
Comparing receive_room and left_space showed in some cases big
differences up to 1600
bytes. left_space was always smaller and sometimes zero.
receive_room is calculated in n_tty_set_room() without read locking.
There are various "FIXME does n_tty_set_room need locking ?"
My test showed, adding a read looking solves the problem.
I asked me why is the locking not done? How big is the risk for dead-locks?
To minimize this risk, I reduced the changes to a minimum (see the patch
below).
The code in the patch only re-calculates the receive_room for raw mode
right before
it is used in flush_to_ldisc().
Can somebody give me an advice, what is the best way to solve this problem?
Thanks for your help.
Regards Stefan
From 91b04c875cecc890139ccdd101cfff6b02b5f22c Mon Sep 17 00:00:00 2001
From: Stefan Bigler <stefan.bigler@keymile.com>
Date: Wed, 16 Mar 2011 15:20:03 +0100
Subject: [PATCH 1/1] n_tty: fix race condition with receive_room
Do an additional update of receive_room with locking for raw tty.
The n_tty_set_room is done without locking what is known as a
potential problem.
In case of heavy load and raw tty and flush_to_ldisc() determine
the number of char to send with receive_buf(). If there is not
enough space available in receive_buf() the data is lost.
This additional update of receive_room should reduce the risk of
have invalid receive_room. It is not a clean fix but the risk of
risk a dead-lock with clean protection is too high
Signed-off-by: Stefan Bigler <stefan.bigler@keymile.com>
---
drivers/char/tty_buffer.c | 16 ++++++++++++++++
1 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/drivers/char/tty_buffer.c b/drivers/char/tty_buffer.c
index f27c4d6..5db07fe 100644
--- a/drivers/char/tty_buffer.c
+++ b/drivers/char/tty_buffer.c
@@ -431,6 +431,22 @@ static void flush_to_ldisc(struct work_struct *work)
line discipline as we want to empty the queue */
if (test_bit(TTY_FLUSHPENDING, &tty->flags))
break;
+
+ /* Take read_lock to update receive_room.
+ This avoids invalid free space information.
+ To limit the risk of introducing problems
+ only do it for raw tty */
+ if (tty->raw) {
+ unsigned long flags_r;
+ spin_lock_irqsave(&tty->read_lock,
+ flags_r);
+ tty->receive_room =
+ N_TTY_BUF_SIZE -
+ tty->read_cnt - 1;
+ spin_unlock_irqrestore(&tty->read_lock,
+ flags_r);
+ }
+
if (!tty->receive_room) {
schedule_delayed_work(&tty->buf.work, 1);
break;
--
1.7.0.5
next reply other threads:[~2011-03-16 21:23 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-16 20:47 Stefan Bigler [this message]
2011-03-17 0:04 ` TTY loosing data with u_serial gadget Greg KH
2011-03-18 16:35 ` Stefan Bigler
2011-03-18 17:08 ` Felipe Balbi
2011-03-18 18:06 ` Alan Cox
2011-03-21 9:32 ` Felipe Balbi
2011-03-22 8:53 ` Felipe Balbi
2011-03-22 11:04 ` Alan Cox
2011-03-22 17:01 ` Greg KH
2011-03-24 12:07 ` Toby Gray
2011-03-24 12:37 ` Felipe Balbi
2011-03-24 12:51 ` Toby Gray
2011-03-24 13:00 ` Felipe Balbi
2011-03-24 15:40 ` Stefan Bigler
2011-03-24 16:15 ` Toby Gray
2011-03-25 11:02 ` Felipe Balbi
2011-03-18 21:46 ` Stefan Bigler
2011-03-18 18:07 ` Alan Cox
2011-03-18 21:15 ` Stefan Bigler
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4D8121F6.9060600@keymile.com \
--to=stefan.bigler@keymile.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox