[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [microblaze-uclinux] xmbserial.c bug when flip buffer is full
Hi Rod,
Rod Campbell wrote:
A way to address this problem could be to clear the RX FIFO in this
situation. The system is obviously under stress and an RX FIFO overrun
is probably about to happen. Also I'd increment info->stats.rxoverrun
so you can get some indication that there is a problem with the port.
In order to save all the RX data, I tried adding code similar to what is
in drivers/char/serial.c. Here the flip buffer is processed immediately
when found to be full in the RX interrupt code (instead of being
queued). But at high data rates, some incoming bytes are lost to RX
FIFO overruns when this is done.
This is a good approach. I agree that if your buffers are all really
that full, it's an overflow condition and you protocol should handle it.
Attached is a patch that implements your idea, which I've just applied
to CVS. Do you mind updating your xmbserial.c and giving it a try?
It now easily handles big text dumps via the console, and also the
zmodem utilities lsz/lrz also work fine.
Thanks for the fix.
John
Index: xmbserial.c
===================================================================
RCS file: /var/cvs/uClinux-2.4.x/arch/microblaze/kernel/xmbserial.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -b -B -w -p -r1.16 -r1.17
--- xmbserial.c 21 Apr 2005 05:30:05 -0000 1.16
+++ xmbserial.c 3 Nov 2005 06:03:38 -0000 1.17
@@ -344,6 +344,7 @@ static _INLINE_ void receive_chars(struc
struct tty_struct *tty = info->tty;
unsigned char status, ch;
unsigned int in_word;
+ unsigned int max_count=256;
if (!tty)
return;
@@ -353,12 +354,22 @@ static _INLINE_ void receive_chars(struc
{
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
/*
- * can't take any more data. Turn off receiver
- * so that the interrupt doesn't continually
- * occur.
+ * can't take any more data. Try processing the
+ * flip buf immediately, see if that helps
+ * (see drivers/char/serial for details/inspiration)
*/
- /* XUartLite_mDisableIntr(uartp); */
- break;
+ tty->flip.tqueue.routine((void *) tty);
+ if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ /* Really stuck, drain the RX fifo */
+ do {
+ in_word=uartp[XUL_RX_FIFO_OFFSET/4];
+ info->stats.rxoverrun++;
+ status=uartp[XUL_STATUS_REG_OFFSET/4];
+ } while ((status & XUL_SR_RX_FIFO_VALID_DATA) &&
+ max_count-- > 0);
+
+ return;
+ }
}
/* Grab char from RX FIFO */