kern/114492: device_attach() doesn't unset devclass on error

Raaf raaf at zen.mooo.com
Wed Jul 11 06:50:02 UTC 2007


>Number:         114492
>Category:       kern
>Synopsis:       device_attach() doesn't unset devclass on error
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jul 11 06:50:01 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator:     Raaf
>Release:        FreeBSD 6.2-STABLE i386
>Organization:
>Environment:
System: FreeBSD zen.mooo.com 6.2-STABLE FreeBSD 6.2-STABLE #10: Wed Jul 11 08:00:54 CEST 2007 raaf at zen.mooo.com:/usr/obj/usr/src/sys/RANI i386

>Description:
device_attach() doesn't unset devclass on error.

I have a Sony Ericsson mobile phone that has 9 USB interfaces.

Interface 1: Is handled by umodem(4)
Interface 2: Is the associated data interface for interfaces 1 and 3
Interface 3: Is also handled by umodem(4)
Interface 8: Is handled by umass(4)

device_attach() fails on interface 3 because interface 3 requires data
interface 2 which is already taken by interface 1.

Thats is not a big problem.

However because device_attach() doesn't unset devclass on error, all
subsequent calls on the remaining device interfaces will be called
with devclass set to that of the umodem driver, and umass match/attach
will never be called for interface 8.

Note that this current code in device_attach() doesn't do anything:
----------------------------------------------------------------------
/* Unset the class; set in device_probe_child */
if (dev->devclass == 0)
	device_set_devclass(dev, 0);
----------------------------------------------------------------------

>How-To-Repeat:
	
>Fix:

The following patch fixes it for me.

--- patch-subr_bus.c begins here ---
--- sys/kern/subr_bus.c.orig	Wed Jul 11 07:50:24 2007
+++ sys/kern/subr_bus.c	Wed Jul 11 07:56:54 2007
@@ -2322,6 +2322,7 @@
 device_probe_and_attach(device_t dev)
 {
 	int error;
+	int hasclass = (dev->devclass != 0);
 
 	GIANT_REQUIRED;
 
@@ -2344,6 +2345,9 @@
 		return (error);
 	}
 	error = device_attach(dev);
+	/* Unset the class; set in device_probe_child */
+	if(error && !hasclass)
+		device_set_devclass(dev, NULL);
 
 	return (error);
 }
@@ -2378,9 +2382,6 @@
 	if ((error = DEVICE_ATTACH(dev)) != 0) {
 		printf("device_attach: %s%d attach returned %d\n",
 		    dev->driver->name, dev->unit, error);
-		/* Unset the class; set in device_probe_child */
-		if (dev->devclass == 0)
-			device_set_devclass(dev, 0);
 		device_set_driver(dev, NULL);
 		device_sysctl_fini(dev);
 		dev->state = DS_NOTPRESENT;
--- patch-subr_bus.c ends here ---



>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list