All of lore.kernel.org
 help / color / mirror / Atom feed
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





             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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.