Panic with ugen
Jay Cornwall
jay at evilrealms.net
Fri Nov 28 05:42:49 PST 2003
Martin wrote:
>>Could you try the attached patch, to see if it fixes the panic on the second
>>run of your program?
> No success. Still same panic.
Oops, my bad. I misread your backtrace, and fixed a similar bug in
ugen_set_interface rather than ugen_set_config.
Could you try the attached patch (rm -f sys/dev/usb/ugen.c, cvs up
sys/dev/usb/ugen.c, patch ...) to see if it alleviates the panic? It
should at least give a more specific panic, if it doesn't fix the problem.
--
Cheers,
Jay
http://www.imperial.ac.uk/ - 3rd year CS student
-------------- next part --------------
Index: sys/dev/usb/ugen.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/ugen.c,v
retrieving revision 1.81
diff -u -3 -p -r1.81 ugen.c
--- sys/dev/usb/ugen.c 9 Nov 2003 09:17:22 -0000 1.81
+++ sys/dev/usb/ugen.c 28 Nov 2003 13:36:27 -0000
@@ -322,10 +322,6 @@ ugen_set_config(struct ugen_softc *sc, i
DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
USBDEVNAME(sc->sc_dev), configno, sc));
-#if defined(__FreeBSD__)
- ugen_destroy_devnodes(sc);
-#endif
-
/* We start at 1, not 0, because we don't care whether the
* control endpoint is open or not. It is always present.
*/
@@ -347,15 +343,22 @@ ugen_set_config(struct ugen_softc *sc, i
err = usbd_interface_count(dev, &niface);
if (err)
return (err);
+
+#if defined(__FreeBSD__)
+ ugen_destroy_devnodes(sc);
+#endif
+
memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints);
for (ifaceno = 0; ifaceno < niface; ifaceno++) {
DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno));
err = usbd_device2interface_handle(dev, ifaceno, &iface);
- if (err)
- return (err);
+ if (err) {
+ panic("ugen_set_config: can't obtain interface handle");
+ }
err = usbd_endpoint_count(iface, &nendpt);
- if (err)
- return (err);
+ if (err) {
+ panic("ugen_set_config: endpoint count failed");
+ }
for (endptno = 0; endptno < nendpt; endptno++) {
ed = usbd_interface2endpoint_descriptor(iface,endptno);
endpt = ed->bEndpointAddress;
@@ -1014,8 +1017,8 @@ ugen_set_interface(struct ugen_softc *sc
usbd_interface_handle iface;
usb_endpoint_descriptor_t *ed;
usbd_status err;
- struct ugen_endpoint *sce;
- u_int8_t niface, nendpt, endptno, endpt;
+ struct ugen_endpoint *sce, **sce_cache;
+ u_int8_t niface, nendpt, nendpt_cache, endptno, endpt;
int dir;
DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno));
@@ -1033,30 +1036,46 @@ ugen_set_interface(struct ugen_softc *sc
if (err)
return (err);
-#if defined(__FreeBSD__)
- /* destroy the existing devices, we remake the new ones in a moment */
- ugen_destroy_devnodes(sc);
-#endif
+ /* store an array of endpoint descriptors to destroy if the interface
+ * change succeeds - these aren't available afterwards */
+ sce_cache = malloc(sizeof(struct ugen_endpoint *) * nendpt, M_TEMP,
+ M_WAITOK);
+ nendpt_cache = nendpt;
- /* XXX should only do this after setting new altno has succeeded */
for (endptno = 0; endptno < nendpt; endptno++) {
ed = usbd_interface2endpoint_descriptor(iface,endptno);
endpt = ed->bEndpointAddress;
dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
- sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
- sce->sc = 0;
- sce->edesc = 0;
- sce->iface = 0;
+ sce_cache[endptno] = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
}
/* change setting */
err = usbd_set_interface(iface, altno);
- if (err)
+ if (err) {
+ free(sce_cache, M_TEMP);
return (err);
+ }
err = usbd_endpoint_count(iface, &nendpt);
- if (err)
- return (err);
+ if (err) {
+ panic("ugen_set_interface: endpoint count failed");
+ }
+
+#if defined(__FreeBSD__)
+ /* destroy the existing devices, we remake the new ones in a moment */
+ ugen_destroy_devnodes(sc);
+#endif
+
+ /* now we can clear the old interface's ugen_endpoints */
+ for (endptno = 0; endptno < nendpt_cache; endptno++) {
+ sce = sce_cache[endptno];
+ sce->sc = 0;
+ sce->edesc = 0;
+ sce->iface = 0;
+ }
+ free(sce_cache, M_TEMP);
+
+ /* set the new interface's ugen_endpoints */
for (endptno = 0; endptno < nendpt; endptno++) {
ed = usbd_interface2endpoint_descriptor(iface,endptno);
endpt = ed->bEndpointAddress;
More information about the freebsd-current
mailing list