From: Peter Hurley <peter@hurleysoftware.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.cz>,
linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org,
One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>,
Peter Hurley <peter@hurleysoftware.com>
Subject: [PATCH v2 tty-next 7/8] n_tty: Extend debug tracing
Date: Mon, 2 Dec 2013 14:24:47 -0500 [thread overview]
Message-ID: <1386012288-5079-8-git-send-email-peter@hurleysoftware.com> (raw)
In-Reply-To: <1386012288-5079-1-git-send-email-peter@hurleysoftware.com>
Add configurable trace support to allow tracing with dev_dbg,
pr_dbg, or trace_printk. Instrument .receive_buf() and read()
paths with traces to aid in debugging flow control changes.
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
---
drivers/tty/n_tty.c | 79 ++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 63 insertions(+), 16 deletions(-)
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 5254082..26ae9d7 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -80,12 +80,18 @@
#define ECHO_BLOCK 256
#define ECHO_DISCARD_WATERMARK N_TTY_BUF_SIZE - (ECHO_BLOCK + 32)
+#define n_tty_trace_facility trace_printk
+#define _n_tty_trace(tty, f, args...) \
+ do { \
+ char buf[64]; \
+ n_tty_trace_facility("[%s] " f, tty_name(tty, buf), ##args); \
+ } while (0)
#undef N_TTY_TRACE
#ifdef N_TTY_TRACE
-# define n_tty_trace(f, args...) trace_printk(f, ##args)
+# define n_tty_trace(tty, f, args...) _n_tty_trace(tty, f, args)
#else
-# define n_tty_trace(f, args...)
+# define n_tty_trace(tty, f, args...) do { } while (0)
#endif
struct n_tty_data {
@@ -179,8 +185,13 @@ static int receive_room(struct tty_struct *tty)
* that erase characters will be handled. Other excess
* characters will be beeped.
*/
- if (left <= 0)
+ if (left <= 0) {
left = ldata->icanon && ldata->canon_head == ldata->read_tail;
+ if (left) {
+ n_tty_trace(tty, "overflow, head:%zu tail:%zu\n",
+ ldata->read_head, ldata->read_tail);
+ }
+ }
return left;
}
@@ -200,11 +211,14 @@ static int receive_room(struct tty_struct *tty)
static void n_tty_set_room(struct tty_struct *tty)
{
struct n_tty_data *ldata = tty->disc_data;
+ int avail;
/* Did this open up the receive buffer? We may need to flip */
- if (unlikely(ldata->no_room) && receive_room(tty)) {
+ if (unlikely(ldata->no_room) && (avail = receive_room(tty))) {
ldata->no_room = 0;
+ n_tty_trace(tty, "restart worker (avail = %d)\n", avail);
+
WARN_RATELIMIT(tty->port->itty == NULL,
"scheduling with invalid itty\n");
/* see if ldisc has been killed - if so, this means that
@@ -240,6 +254,8 @@ static ssize_t chars_in_buffer(struct tty_struct *tty)
static void n_tty_write_wakeup(struct tty_struct *tty)
{
+ n_tty_trace(tty, "\n");
+
if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags))
kill_fasync(&tty->fasync, SIGIO, POLL_OUT);
}
@@ -254,13 +270,16 @@ static void n_tty_check_throttle(struct tty_struct *tty)
* canonical mode and don't have a newline yet!
*/
while (1) {
- int throttled;
+ int throttled, avail;
tty_set_flow_change(tty, TTY_THROTTLE_SAFE);
- if (receive_room(tty) >= TTY_THRESHOLD_THROTTLE)
+ avail = receive_room(tty);
+ if (avail >= TTY_THRESHOLD_THROTTLE)
break;
throttled = tty_throttle_safe(tty);
- if (!throttled)
+ if (!throttled) {
+ n_tty_trace(tty, "throttled (avail = %d)/n", avail);
break;
+ }
}
__tty_set_flow_change(tty, 0);
}
@@ -289,16 +308,19 @@ static void n_tty_check_unthrottle(struct tty_struct *tty)
*/
while (1) {
- int unthrottled;
+ int unthrottled, used;
tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE);
- if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE)
+ used = chars_in_buffer(tty);
+ if (used > TTY_THRESHOLD_UNTHROTTLE)
break;
if (!tty->count)
break;
n_tty_set_room(tty);
unthrottled = tty_unthrottle_safe(tty);
- if (!unthrottled)
+ if (!unthrottled) {
+ n_tty_trace(tty, "unthrottled (used = %d)\n", used);
break;
+ }
}
__tty_set_flow_change(tty, 0);
}
@@ -374,6 +396,9 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty)
static void n_tty_flush_buffer(struct tty_struct *tty)
{
down_write(&tty->termios_rwsem);
+
+ n_tty_trace(tty, "\n");
+
reset_buffer_flags(tty->disc_data);
n_tty_set_room(tty);
@@ -770,6 +795,10 @@ static size_t __process_echoes(struct tty_struct *tty)
* of echo overrun before the next commit), then discard enough
* data at the tail to prevent a subsequent overrun */
while (ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK) {
+
+ n_tty_trace(tty, "discard echoes (%zu - %zu > %d)\n",
+ ldata->echo_commit, tail, ECHO_DISCARD_WATERMARK);
+
if (echo_buf(ldata, tail) == ECHO_OP_START) {
if (echo_buf(ldata, tail + 1) == ECHO_OP_ERASE_TAB)
tail += 3;
@@ -1369,6 +1398,7 @@ handle_newline:
set_bit(ldata->read_head & (N_TTY_BUF_SIZE - 1), ldata->read_flags);
put_tty_queue(c, ldata);
ldata->canon_head = ldata->read_head;
+ n_tty_trace(tty, "canon_head:%zu\n", ldata->canon_head);
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
if (waitqueue_active(&tty->read_wait))
wake_up_interruptible(&tty->read_wait);
@@ -1670,6 +1700,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp,
if ((!ldata->icanon && (read_cnt(ldata) >= ldata->minimum_to_wake)) ||
L_EXTPROC(tty)) {
+ n_tty_trace(tty, "reader wakeup, count:%zd\n", read_cnt(ldata));
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
if (waitqueue_active(&tty->read_wait))
wake_up_interruptible(&tty->read_wait);
@@ -1689,6 +1720,8 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp,
room = receive_room(tty);
n = min(count, room);
if (!n) {
+ if (!room)
+ n_tty_trace(tty, "buffer full\n");
if (flow && !room)
ldata->no_room = 1;
break;
@@ -1705,6 +1738,8 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp,
n_tty_check_throttle(tty);
up_read(&tty->termios_rwsem);
+ n_tty_trace(tty, "rcvd:%d\n", rcvd);
+
return rcvd;
}
@@ -1814,6 +1849,10 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped)
start_tty(tty);
+ n_tty_trace(tty, "mode:%s tail:%zu canon:%zu head:%zu\n",
+ ldata->icanon ? "canon" : "raw", ldata->read_tail,
+ ldata->canon_head, ldata->read_head);
+
/* The termios change make the tty ready for I/O */
if (waitqueue_active(&tty->write_wait))
wake_up_interruptible(&tty->write_wait);
@@ -1893,10 +1932,14 @@ static inline int input_available_p(struct tty_struct *tty, int poll)
int amt = poll && !TIME_CHAR(tty) ? MIN_CHAR(tty) : 1;
if (ldata->icanon && !L_EXTPROC(tty)) {
- if (ldata->canon_head != ldata->read_tail)
+ if (ldata->canon_head != ldata->read_tail) {
+ n_tty_trace(tty, "line avail\n");
return 1;
- } else if (read_cnt(ldata) >= amt)
+ }
+ } else if (read_cnt(ldata) >= amt) {
+ n_tty_trace(tty, "avail:%zu amt:%d\n", read_cnt(ldata), amt);
return 1;
+ }
return 0;
}
@@ -1993,8 +2036,8 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1);
size = min_t(size_t, tail + n, N_TTY_BUF_SIZE);
- n_tty_trace("%s: nr:%zu tail:%zu n:%zu size:%zu\n",
- __func__, *nr, tail, n, size);
+ n_tty_trace(tty, "nr:%zu tail:%zu n:%zu size:%zu\n",
+ *nr, tail, n, size);
eol = find_next_bit(ldata->read_flags, size, tail);
more = n - (size - tail);
@@ -2018,8 +2061,8 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
eof_push = !n && ldata->read_tail != ldata->line_start;
}
- n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu size:%zu more:%zu\n",
- __func__, eol, found, n, c, size, more);
+ n_tty_trace(tty, "eol:%zu found:%d n:%zu c:%zu size:%zu more:%zu\n",
+ eol, found, n, c, size, more);
if (n > size) {
ret = copy_to_user(*b, read_buf_addr(ldata, tail), size);
@@ -2211,6 +2254,8 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
n_tty_set_room(tty);
up_read(&tty->termios_rwsem);
+ n_tty_trace(tty, "blocking\n");
+
timeout = schedule_timeout(timeout);
down_read(&tty->termios_rwsem);
@@ -2268,6 +2313,8 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
if (b - buf)
retval = b - buf;
+ n_tty_trace(tty, "ret:%zd\n", retval);
+
return retval;
}
--
1.8.1.2
next prev parent reply other threads:[~2013-12-02 19:24 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-11-22 15:59 [PATCH tty-next 0/7] n_tty cleanup + trace additions Peter Hurley
2013-11-22 15:59 ` [PATCH tty-next 1/7] n_tty: Merge .receive_buf() flavors Peter Hurley
2013-11-22 15:59 ` [PATCH tty-next 2/7] n_tty: Un-inline slow-path n_tty_receive_char() Peter Hurley
2013-11-22 15:59 ` [PATCH tty-next 3/7] n_tty: Un-inline slow-path n_tty_receive_char_closing() Peter Hurley
2013-11-22 15:59 ` [PATCH tty-next 4/7] n_tty: Refactor PARMRK doubling checks Peter Hurley
2013-11-22 15:59 ` [PATCH tty-next 5/7] n_tty: Refactor input_available_p() by call site Peter Hurley
2013-11-24 0:22 ` One Thousand Gnomes
2013-11-24 0:26 ` One Thousand Gnomes
2013-11-24 2:01 ` Peter Hurley
2013-11-24 16:18 ` One Thousand Gnomes
2013-11-22 15:59 ` [PATCH tty-next 6/7] n_tty: Only perform wakeups for waiters Peter Hurley
2013-11-24 0:23 ` One Thousand Gnomes
2013-11-24 2:29 ` Peter Hurley
2013-11-22 15:59 ` [PATCH tty-next 7/7] n_tty: trace input/read flow control Peter Hurley
2013-11-24 0:25 ` One Thousand Gnomes
2013-11-24 2:38 ` Peter Hurley
2013-11-26 13:00 ` Peter Hurley
2013-12-02 19:24 ` [PATCH v2 tty-next 0/8] n_tty cleanup + trace additions Peter Hurley
2013-12-02 19:24 ` [PATCH v2 tty-next 1/8] n_tty: Merge .receive_buf() flavors Peter Hurley
2013-12-02 19:24 ` [PATCH v2 tty-next 2/8] n_tty: Un-inline slow-path n_tty_receive_char() Peter Hurley
2013-12-02 19:24 ` [PATCH v2 tty-next 3/8] n_tty: Un-inline slow-path n_tty_receive_char_closing() Peter Hurley
2013-12-02 19:24 ` [PATCH v2 tty-next 4/8] n_tty: Refactor PARMRK doubling checks Peter Hurley
2013-12-02 19:24 ` [PATCH v2 tty-next 5/8] n_tty: Refactor input_available_p() by call site Peter Hurley
2013-12-02 19:24 ` [PATCH v2 tty-next 6/8] n_tty: Only perform wakeups for waiters Peter Hurley
2013-12-02 19:24 ` Peter Hurley [this message]
2013-12-09 0:54 ` [PATCH v2 tty-next 7/8] n_tty: Extend debug tracing Greg Kroah-Hartman
2013-12-02 19:24 ` [PATCH v2 tty-next 8/8] n_tty: Trace echo output with separate trace configuration Peter Hurley
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=1386012288-5079-8-git-send-email-peter@hurleysoftware.com \
--to=peter@hurleysoftware.com \
--cc=gnomes@lxorguk.ukuu.org.uk \
--cc=gregkh@linuxfoundation.org \
--cc=jslaby@suse.cz \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-serial@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.