usb/132080: [patch] [usb] Kernel panic after NOMEM caused by rum
card
Alexander Melkov
melkov at comptek.ru
Tue Feb 24 17:20:03 PST 2009
>Number: 132080
>Category: usb
>Synopsis: [patch] [usb] Kernel panic after NOMEM caused by rum card
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-usb
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Wed Feb 25 01:20:02 UTC 2009
>Closed-Date:
>Last-Modified:
>Originator: Alexander Melkov
>Release: 7.1-STABLE
>Organization:
>Environment:
FreeBSD melkov.ru 7.1-STABLE FreeBSD 7.1-STABLE #14: Tue Feb 24 06:28:45 MSK 2009 root_at_melkov.ru:/usr/obj/usr/src/sys/MELKOV amd64
>Description:
I have <rum> device which is Cisco-Linksys Compact Wireless-G USB Adapter that runs in hostap mode (i.e. wifi access point).
Sometimes it malfunctions (that may happen several times a day), at that moment I have message "rum0: could not transmit buffer: NOMEM" from kernel.
Right after the message kernel crashes upon read from (nearly) null address.
System log:
Feb 23 19:46:22 melkov kernel: rum0: could not transmit buffer: NOMEM
Feb 23 19:46:22 melkov kernel:
Feb 23 19:46:22 melkov kernel:
Feb 23 19:46:22 melkov kernel: Fatal trap 12: page fault while in kernel mode
Feb 23 19:46:22 melkov kernel: fault virtual address = 0x290
Feb 23 19:46:22 melkov kernel: fault code = supervisor read data, page not present
Feb 23 19:46:22 melkov kernel: instruction pointer = 0x8:0xffffffff80430b0d
Feb 23 19:46:22 melkov kernel: stack pointer = 0x10:0xfffffffef21caa80
Feb 23 19:46:22 melkov kernel: frame pointer = 0x10:0xffffff00430cd080
Feb 23 19:46:22 melkov kernel: code segment = base 0x0, limit 0xfffff, type 0x1b
Feb 23 19:46:22 melkov kernel: = DPL 0, pres 1, long 1, def32 0, gran 1
Feb 23 19:46:22 melkov kernel: processor eflags = interrupt enabled, resume, IOPL = 0
Feb 23 19:46:22 melkov kernel: current process = 20 (swi6: Giant taskq)
Feb 23 19:46:22 melkov kernel: trap number = 12
Feb 23 19:46:22 melkov kernel: panic: page fault
(kgdb) bt 12
#0 doadump () at pcpu.h:195
#1 0x0000000000000004 in ?? ()
#2 0xffffffff804c8fc4 in boot (howto=260) at /usr/src/sys/kern/kern_shutdown.c:418
#3 0xffffffff804c937c in panic (fmt=0xffffffff8081f82b "%s") at /usr/src/sys/kern/kern_shutdown.c:574
#4 0xffffffff8077b48f in trap_fatal (frame=0xffffff0001514000, eva=Variable "eva" is not available.
) at /usr/src/sys/amd64/amd64/trap.c:764
#5 0xffffffff8077b865 in trap_pfault (frame=0xfffffffef21ca9d0, usermode=0) at /usr/src/sys/amd64/amd64/trap.c:680
#6 0xffffffff8077c195 in trap (frame=0xfffffffef21ca9d0) at /usr/src/sys/amd64/amd64/trap.c:449
#7 0xffffffff80764fee in calltrap () at /usr/src/sys/amd64/amd64/exception.S:209
#8 0xffffffff80430b0d in usb_transfer_complete (xfer=0xffffff0004d83800) at /usr/src/sys/dev/usb/usbdi.c:949
#9 0xffffffff8043119b in usbd_transfer (xfer=0xffffff0004d83800) at /usr/src/sys/dev/usb/usbdi.c:320
#10 0xffffffff804127d1 in rum_start (ifp=0xffffff0004e12000) at /usr/src/sys/dev/usb/if_rum.c:1360
#11 0xffffffff804fdb60 in taskqueue_run (queue=0xffffff00014d6780) at /usr/src/sys/kern/subr_taskqueue.c:282
(More stack frames follow...)
#8 0xffffffff80430b0d in usb_transfer_complete (xfer=0xffffff0004d83800) at /usr/src/sys/dev/usb/usbdi.c:949
949 STAILQ_REMOVE_HEAD(&pipe->queue, next);
(kgdb) p pipe->queue
$12 = {stqh_first = 0x0, stqh_last = 0xffffff00430cd0a0}
Apparently there's an attempt to STAILQ_REMOVE_HEAD from an empty pipe->queue, within usb_transfer_complete().
The USBD_NOMEM error code that rum_txeof() complains about probably comes from unsuccessful call to bus_dmamap_create() within usbd_transfer(), which I didn't investigate.
>How-To-Repeat:
Insert ralink-based card into usb slot and set up WPA2 PSK access point according to The Handbook.
Connect to this access point from another station, perform heavy activity, periodically conecting and disconnecting.
>Fix:
usbd_start_transfer() has two error-handling branches first of whose called usb_insert_transfer() that ensured the pipe->queue to be non-empty later in usb_transfer_complete().
I've added similar call to the second error-handling branch.
==> usbdi.c.patch <==
--- sys/dev/usb/usbdi.c.orig 2009-02-24 06:23:54.000000000 +0300
+++ sys/dev/usb/usbdi.c 2009-02-24 07:01:27.000000000 +0300
@@ -394,6 +394,8 @@
bus_dmamap_destroy(tag, dmap->map);
xfer->rqflags &= ~URQ_AUTO_DMABUF;
}
+ /* XXX: usb_transfer_complete crashes unless we call usb_insert_transfer */
+ usb_insert_transfer(xfer);
xfer->status = err;
usb_transfer_complete(xfer);
return;
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-usb
mailing list