Subject: kern/8041: USB/ugen cleanup problems
To: None <gnats-bugs@gnats.netbsd.org>
From: Ed Gould <ed@pa.dec.com>
List: netbsd-bugs
Date: 07/20/1999 17:50:51
>Number: 8041
>Category: kern
>Synopsis: USB/ugen cleanup problems
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Tue Jul 20 17:50:01 1999
>Last-Modified:
>Originator: Ed Gould
>Organization:
--
Ed Gould Palo Alto Advanced Development Compaq Computer Corp.
+1 650 853 2108 ed@pa.dec.com 130 Lytton Avenue
ed.gould@compaq.com Palo Alto, CA 94301
>Release: 20 July 1999, NetBSD 1.4G
>Environment:
System: NetBSD toblerone.pa.dec.com 1.4G NetBSD 1.4G (TOBLERONE) #4: Tue Jul 20 16:59:31 PDT 1999 ed@toblerone.pa.dec.com:/usr/src/current/sys/arch/i386/compile/TOBLERONE i386
>Description:
After a SIGINT causes a process blocked in read() on a ugen
input desciptor to exit and thereby close the descriptor, a
later timer-driven activity of the usb0 thread causes a
kernel panic.
>How-To-Repeat:
Issue suitable open() and read() calls on a ugen device. The read
will hang (yet to be diagnosed; I believe there should be data
to read). Type ^C to cause SIGINT; the process exits. Wait
a few 10s of seconds. An unmodified kernel will panic for a
kernel-mode page fault; the enclosed fix avoids the panic but
does not fix the underlying problem.
>Fix:
Apply this patch to dev/uhci.c. Note that the existing
test for a null pointer is not sufficient. For some reason,
the pointers are being set to 0xdeadbeef. Only the test
for lstd seems to be necessary; the others were for additional
safety.
--- uhci.c.orig Mon Jul 12 04:11:42 1999
+++ uhci.c Tue Jul 20 16:51:25 1999
@@ -785,9 +785,10 @@
if (!ii->stdstart)
return;
lstd = ii->stdend;
+#define ISNULL(p) (((p) == NULL) || ((p) == (void *)0xdeadbeef))
#ifdef DIAGNOSTIC
- if (!lstd) {
- printf("uhci_check_intr: std==0\n");
+ if (ISNULL(lstd)) {
+ printf("uhci_check_intr: lstd == %p\n", lstd);
return;
}
#endif
@@ -796,9 +797,21 @@
* is a an error somewhere in the middle, or whether there was a
* short packet (SPD and not ACTIVE).
*/
+ if (ISNULL(lstd->td)) {
+ printf("uhci_check_intr: lstd->td == %p\n", lstd->td);
+ return;
+ }
if (lstd->td->td_status & UHCI_TD_ACTIVE) {
DPRINTFN(15, ("uhci_check_intr: active ii=%p\n", ii));
for (std = ii->stdstart; std != lstd; std = std->td->link.std){
+ if (ISNULL(std)) {
+ printf("uhci_check_intr: std == %p\n", std);
+ break;
+ }
+ if (ISNULL(std->td)) {
+ printf("uhci_check_intr: std->td == %p\n", std->td);
+ break;
+ }
status = std->td->td_status;
if ((status & UHCI_TD_STALLED) ||
(status & (UHCI_TD_SPD | UHCI_TD_ACTIVE)) ==
>Audit-Trail:
>Unformatted: