1. Consistent "Bad address" errno's reported by simple utilities such as
	'cat /proc/tty/driver/serial'.
    2. Occasional garbage characters (lots) after the last line report (in
	my case, the usual 0-3).
    3. Kernel oops from the call sequence rs_read_proc()/line_info()/serial_in()
	in drivers/char/serial.c .
    4. Severe system hanging -- no response to anything except the reset
	button (and, I suppose, the power switch).
#3 and #4 happened only under duress: only with SMP config'd (on a dual PII)
and running a homebrew X-based performance gauge that displays serial r/w
rates, reading the proc file twice a second.  #1 and #2 could be seen using
'cat' (I suggest using 'cat -v').  For me, #2 disappeared if the output
was piped into something else (!), e.g., 'cat /proc/tty/driver/serial | cat'.
Inspection showed some very dubious code in drivers/char/serial.c (and you've
probably already guessed that auto variables (stack data) was involved).
serial_in() was dereferencing some un-initalized elements of its info pointer
arg.
A fix is below; the comments in it tell more of the story.  The idea was
to set things up better for serial_in(), based on what it needs and what
autoconfig() does.  It's not all needed (as noted), but I opted for
"completeness", just for easy comparison against autoconfig().
If anyone's interested in the pathology, I can send the kernel oopses (I
have about four or five), but I'd recommend just examining the line_info()
and serial_in() code in serial.c before diving into an oops.
This diff is against 2.3.23 from linux.kernel.org; expect a 5 line offset,
since I've elided my RCS stuff.
--- drivers/char/serial.c	1999/10/23 20:08:40	1.1
+++ drivers/char/serial.c	1999/10/23 23:06:26
@@ -3061,20 +3066,41 @@
 	}
 
 	/*
-	 * Figure out the current RS-232 lines
+	 * Figure out the current RS-232 control and status lines.
 	 */
 	if (!info) {
-		info = &scr_info;	/* This is just for serial_{in,out} */
+		info = &scr_info;	/* This is just for serial_in() */
 
-		info->magic = SERIAL_MAGIC;
+		/*
+		 * Based on info initialization in autoconfig() below.
+		 */
+		info->magic = SERIAL_MAGIC;	/* unused */
+		info->state = state;		/* unused */
 		info->port = state->port;
-		info->flags = state->flags;
+		info->flags = state->flags;	/* unused */
+#ifdef CONFIG_HUB6
+		info->hub6 = state->hub6;
+#endif
+#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
+		info->iomem_base = state->iomem_base;
+		info->iomem_reg_shift = state->iomem_reg_shift;
+#endif
+		/*
+		 * Other references used below.
+		 */
+		info->MCR = 0;
 		info->quot = 0;
-		info->tty = 0;
 	}
+
+	/*
+	 * Is info->MCR always valid here?  Or should we always do
+	 *  serial_in(info, UART_MCR)?
+	 * In any case, the old info ? test is unneeded.
+	 */
+	control = info->MCR;
+
 	save_flags(flags); cli();
 	status = serial_in(info, UART_MSR);
-	control = info ? info->MCR : serial_in(info, UART_MCR);
 	restore_flags(flags); 
 	
 	stat_buf[0] = 0;
Bruce Jerrick
Portland, Oregon, USA
email:   bjerrick@easystreet.com
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/