svn commit: r185059 - in head/sys: dev/acpica dev/sio isa kern

John Baldwin jhb at FreeBSD.org
Tue Nov 18 13:01:55 PST 2008


Author: jhb
Date: Tue Nov 18 21:01:54 2008
New Revision: 185059
URL: http://svn.freebsd.org/changeset/base/185059

Log:
  Allow device hints to wire the unit numbers of devices.
  - An "at" hint now reserves a device name.
  - A new BUS_HINT_DEVICE_UNIT method is added to the bus interface.  When
    determining the unit number of a device, this method is invoked to
    let the bus driver specify the unit of a device given a specific
    devclass.  This is the only way a device can be given a name reserved
    via an "at" hint.
  - Implement BUS_HINT_DEVICE_UNIT() for the acpi(4) and isa(4) bus drivers.
    Both of these busses implement this by comparing the resources for a
    given hint device with the resources enumerated by ACPI/PnPBIOS and
    wire a unit if the hint resources are a subset of the "real" resources.
  - Use bus_hinted_children() for adding hinted devices on isa(4) busses
    now instead of doing it by hand.
  - Remove the unit kludging from sio(4) as it is no longer necessary.
  
  Prodding from:	peter, imp
  OK'd by:	marcel
  MFC after:	1 month

Modified:
  head/sys/dev/acpica/acpi.c
  head/sys/dev/sio/sio_pci.c
  head/sys/dev/sio/sio_puc.c
  head/sys/isa/isa_common.c
  head/sys/isa/isa_common.h
  head/sys/isa/isahint.c
  head/sys/isa/isavar.h
  head/sys/kern/bus_if.m
  head/sys/kern/subr_bus.c

Modified: head/sys/dev/acpica/acpi.c
==============================================================================
--- head/sys/dev/acpica/acpi.c	Tue Nov 18 20:41:14 2008	(r185058)
+++ head/sys/dev/acpica/acpi.c	Tue Nov 18 21:01:54 2008	(r185059)
@@ -158,6 +158,8 @@ static int	acpi_child_pnpinfo_str_method
 #if defined(__i386__) || defined(__amd64__)
 static void	acpi_enable_pcie(void);
 #endif
+static void	acpi_hint_device_unit(device_t acdev, device_t child,
+		    const char *name, int *unitp);
 
 static device_method_t acpi_methods[] = {
     /* Device interface */
@@ -187,6 +189,7 @@ static device_method_t acpi_methods[] = 
     DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
     DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
     DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
+    DEVMETHOD(bus_hint_device_unit,	acpi_hint_device_unit),
 
     /* ACPI bus */
     DEVMETHOD(acpi_id_probe,		acpi_device_id_probe),
@@ -949,6 +952,89 @@ acpi_get_rlist(device_t dev, device_t ch
     return (&ad->ad_rl);
 }
 
+static int
+acpi_match_resource_hint(device_t dev, int type, long value)
+{
+    struct acpi_device *ad = device_get_ivars(dev);
+    struct resource_list *rl = &ad->ad_rl;
+    struct resource_list_entry *rle;
+
+    STAILQ_FOREACH(rle, rl, link) {
+	if (rle->type != type)
+	    continue;
+	if (rle->start <= value && rle->end >= value)
+	    return (1);
+    }
+    return (0);
+}
+
+/*
+ * Wire device unit numbers based on resource matches in hints.
+ */
+static void
+acpi_hint_device_unit(device_t acdev, device_t child, const char *name,
+    int *unitp)
+{
+    const char *s;
+    long value;
+    int line, matches, unit;
+
+    /*
+     * Iterate over all the hints for the devices with the specified
+     * name to see if one's resources are a subset of this device.
+     */
+    line = 0;
+    for (;;) {
+	if (resource_find_dev(&line, name, &unit, "at", NULL) != 0)
+	    break;
+
+	/* Must have an "at" for acpi or isa. */
+	resource_string_value(name, unit, "at", &s);
+	if (!(strcmp(s, "acpi0") == 0 || strcmp(s, "acpi") == 0 ||
+	    strcmp(s, "isa0") == 0 || strcmp(s, "isa") == 0))
+	    continue;
+
+	/*
+	 * Check for matching resources.  We must have at least one,
+	 * and all resources specified have to match.
+	 *
+	 * XXX: We may want to revisit this to be more lenient and wire
+	 * as long as it gets one match.
+	 */
+	matches = 0;
+	if (resource_long_value(name, unit, "port", &value) == 0) {
+	    if (acpi_match_resource_hint(child, SYS_RES_IOPORT, value))
+		matches++;
+	    else
+		continue;
+	}
+	if (resource_long_value(name, unit, "maddr", &value) == 0) {
+	    if (acpi_match_resource_hint(child, SYS_RES_MEMORY, value))
+		matches++;
+	    else
+		continue;
+	}
+	if (resource_long_value(name, unit, "irq", &value) == 0) {
+	    if (acpi_match_resource_hint(child, SYS_RES_IRQ, value))
+		matches++;
+	    else
+		continue;
+	}
+	if (resource_long_value(name, unit, "drq", &value) == 0) {
+	    if (acpi_match_resource_hint(child, SYS_RES_DRQ, value))
+		matches++;
+	    else
+		continue;
+	}
+
+	if (matches > 0) {
+	    /* We have a winner! */
+	    *unitp = unit;
+	    break;
+	}
+    }
+}
+
 /*
  * Pre-allocate/manage all memory and IO resources.  Since rman can't handle
  * duplicates, we merge any in the sysresource attach routine.

Modified: head/sys/dev/sio/sio_pci.c
==============================================================================
--- head/sys/dev/sio/sio_pci.c	Tue Nov 18 20:41:14 2008	(r185058)
+++ head/sys/dev/sio/sio_pci.c	Tue Nov 18 21:01:54 2008	(r185059)
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
 #include <dev/pci/pcivar.h>
 
 static	int	sio_pci_attach(device_t dev);
-static	void	sio_pci_kludge_unit(device_t dev);
 static	int	sio_pci_probe(device_t dev);
 
 static device_method_t sio_pci_methods[] = {
@@ -101,39 +100,9 @@ sio_pci_attach(dev)
 		id++;
 	if (id->desc == NULL)
 		return (ENXIO);
-	sio_pci_kludge_unit(dev);
 	return (sioattach(dev, id->rid, 0UL));
 }
 
-/*
- * Don't cut and paste this to other drivers.  It is a horrible kludge
- * which will fail to work and also be unnecessary in future versions.
- */
-static void
-sio_pci_kludge_unit(dev)
-	device_t dev;
-{
-	devclass_t	dc;
-	int		err;
-	int		start;
-	int		unit;
-
-	unit = 0;
-	start = 0;
-	while (resource_int_value("sio", unit, "port", &start) == 0 && 
-	    start > 0)
-		unit++;
-	if (device_get_unit(dev) < unit) {
-		dc = device_get_devclass(dev);
-		while (devclass_get_device(dc, unit))
-			unit++;
-		device_printf(dev, "moving to sio%d\n", unit);
-		err = device_set_unit(dev, unit);	/* EVIL DO NOT COPY */
-		if (err)
-			device_printf(dev, "error moving device %d\n", err);
-	}
-}
-
 static int
 sio_pci_probe(dev)
 	device_t	dev;

Modified: head/sys/dev/sio/sio_puc.c
==============================================================================
--- head/sys/dev/sio/sio_puc.c	Tue Nov 18 20:41:14 2008	(r185058)
+++ head/sys/dev/sio/sio_puc.c	Tue Nov 18 21:01:54 2008	(r185059)
@@ -62,34 +62,6 @@ static driver_t sio_puc_driver = {
 	0,
 };
 
-/*
- * Don't cut and paste this to other drivers.  It is a horrible kludge
- * which will fail to work and also be unnecessary in future versions.
- */
-static void
-sio_puc_kludge_unit(device_t dev)
-{
-	devclass_t	dc;
-	int		err;
-	int		start;
-	int		unit;
-
-	unit = 0;
-	start = 0;
-	while (resource_int_value("sio", unit, "port", &start) == 0 && 
-	    start > 0)
-		unit++;
-	if (device_get_unit(dev) < unit) {
-		dc = device_get_devclass(dev);
-		while (devclass_get_device(dc, unit))
-			unit++;
-		device_printf(dev, "moving to sio%d\n", unit);
-		err = device_set_unit(dev, unit);	/* EVIL DO NOT COPY */
-		if (err)
-			device_printf(dev, "error moving device %d\n", err);
-	}
-}
-
 static int
 sio_puc_attach(device_t dev)
 {
@@ -98,7 +70,6 @@ sio_puc_attach(device_t dev)
 	if (BUS_READ_IVAR(device_get_parent(dev), dev, PUC_IVAR_CLOCK,
 	    &rclk) != 0)
 		rclk = DEFAULT_RCLK;
-	sio_puc_kludge_unit(dev);
 	return (sioattach(dev, 0, rclk));
 }
 

Modified: head/sys/isa/isa_common.c
==============================================================================
--- head/sys/isa/isa_common.c	Tue Nov 18 20:41:14 2008	(r185058)
+++ head/sys/isa/isa_common.c	Tue Nov 18 21:01:54 2008	(r185059)
@@ -467,15 +467,41 @@ isa_assign_resources(device_t child)
 	return (0);
 }
 
+/*
+ * Claim any unallocated resources to keep other devices from using
+ * them.
+ */
+static void
+isa_claim_resources(device_t dev, device_t child)
+{
+	struct isa_device *idev = DEVTOISA(child);
+	struct resource_list *rl = &idev->id_resources;
+	struct resource_list_entry *rle;
+	int rid;
+
+	STAILQ_FOREACH(rle, rl, link) {
+		if (!rle->res) {
+			rid = rle->rid;
+			resource_list_alloc(rl, dev, child, rle->type, &rid,
+			    0ul, ~0ul, 1, 0);
+		}
+	}
+}
+
+/*
+ * Called after other devices have initialised to probe for isa devices.
+ */
 void
 isa_probe_children(device_t dev)
 {
-	device_t *children;
+	struct isa_device *idev;
+	device_t *children, child;
 	struct isa_config *cfg;
 	int nchildren, i;
 
 	/*
-	 * Create all the children by calling driver's identify methods.
+	 * Create all the non-hinted children by calling drivers'
+	 * identify methods.
 	 */
 	bus_generic_probe(dev);
 
@@ -496,8 +522,7 @@ isa_probe_children(device_t dev)
 	}
 
 	for (i = 0; i < nchildren; i++) {
-		device_t child = children[i];
-		struct isa_device *idev = DEVTOISA(child);
+		idev = DEVTOISA(children[i]);
 
 		bzero(cfg, sizeof(*cfg));
 		if (idev->id_config_cb)
@@ -507,16 +532,39 @@ isa_probe_children(device_t dev)
 	free(cfg, M_TEMP);
 
 	/*
-	 * Next probe all non-pnp devices so that they claim their
-	 * resources first.
+	 * Next, probe all the PnP BIOS devices so they can subsume any
+	 * hints.
+	 */
+	for (i = 0; i < nchildren; i++) {
+		child = children[i];
+		idev = DEVTOISA(child);
+
+		if (idev->id_order > ISA_ORDER_PNPBIOS)
+			continue;
+		if (!TAILQ_EMPTY(&idev->id_configs) &&
+		    !isa_assign_resources(child))
+			continue;
+
+		if (device_probe_and_attach(child) == 0)
+			isa_claim_resources(dev, child);
+	}
+	free(children, M_TEMP);
+
+	/*
+	 * Next, enumerate hinted devices and probe all non-pnp devices so
+	 * that they claim their resources first.
 	 */
+	bus_enumerate_hinted_children(dev);
+	if (device_get_children(dev, &children, &nchildren))
+		return;
 	if (bootverbose)
 		printf("isa_probe_children: probing non-PnP devices\n");
 	for (i = 0; i < nchildren; i++) {
-		device_t child = children[i];
-		struct isa_device *idev = DEVTOISA(child);
+		child = children[i];
+		idev = DEVTOISA(child);
 
-		if (TAILQ_FIRST(&idev->id_configs))
+		if (device_is_attached(child) ||
+		    !TAILQ_EMPTY(&idev->id_configs))
 			continue;
 
 		device_probe_and_attach(child);
@@ -528,31 +576,15 @@ isa_probe_children(device_t dev)
 	if (bootverbose)
 		printf("isa_probe_children: probing PnP devices\n");
 	for (i = 0; i < nchildren; i++) {
-		device_t child = children[i];
-		struct isa_device* idev = DEVTOISA(child);
+		child = children[i];
+		idev = DEVTOISA(child);
 
-		if (!TAILQ_FIRST(&idev->id_configs))
+		if (device_is_attached(child) || TAILQ_EMPTY(&idev->id_configs))
 			continue;
 
 		if (isa_assign_resources(child)) {
-			struct resource_list *rl = &idev->id_resources;
-			struct resource_list_entry *rle;
-
 			device_probe_and_attach(child);
-
-			/*
-			 * Claim any unallocated resources to keep other
-			 * devices from using them.
-			 */
-			STAILQ_FOREACH(rle, rl, link) {
-				if (!rle->res) {
-					int rid = rle->rid;
-					resource_list_alloc(rl, dev, child,
-							    rle->type,
-							    &rid,
-							    0, ~0, 1, 0);
-				}
-			}
+			isa_claim_resources(dev, child);
 		}
 	}
 
@@ -580,6 +612,7 @@ isa_add_child(device_t dev, int order, c
 
 	resource_list_init(&idev->id_resources);
 	TAILQ_INIT(&idev->id_configs);
+	idev->id_order = order;
 
 	device_set_ivars(child, idev);
 
@@ -833,23 +866,9 @@ static void
 isa_child_detached(device_t dev, device_t child)
 {
 	struct isa_device* idev = DEVTOISA(child);
-	struct resource_list *rl = &idev->id_resources;
-	struct resource_list_entry *rle;
 
-	if (TAILQ_FIRST(&idev->id_configs)) {
-		/*
-		 * Claim any unallocated resources to keep other
-		 * devices from using them.
-		 */
-		STAILQ_FOREACH(rle, rl, link) {
-			if (!rle->res) {
-				int rid = rle->rid;
-				resource_list_alloc(rl, dev, child,
-						    rle->type,
-						    &rid, 0, ~0, 1, 0);
-			}
-		}
-	}
+	if (TAILQ_FIRST(&idev->id_configs))
+		isa_claim_resources(dev, child);
 }
 
 static void
@@ -900,20 +919,8 @@ isa_driver_added(device_t dev, driver_t 
 
 		device_probe_and_attach(child);
 
-		if (TAILQ_FIRST(&idev->id_configs)) {
-			/*
-			 * Claim any unallocated resources to keep other
-			 * devices from using them.
-			 */
-			STAILQ_FOREACH(rle, rl, link) {
-				if (!rle->res) {
-					int rid = rle->rid;
-					resource_list_alloc(rl, dev, child,
-							    rle->type,
-							    &rid, 0, ~0, 1, 0);
-				}
-			}
-		}
+		if (TAILQ_FIRST(&idev->id_configs))
+			isa_claim_resources(dev, child);
 	}
 
 	free(children, M_TEMP);
@@ -1077,6 +1084,8 @@ static device_method_t isa_methods[] = {
 	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
 	DEVMETHOD(bus_child_pnpinfo_str, isa_child_pnpinfo_str),
 	DEVMETHOD(bus_child_location_str, isa_child_location_str),
+	DEVMETHOD(bus_hinted_child,	isa_hinted_child),
+	DEVMETHOD(bus_hint_device_unit,	isa_hint_device_unit),
 
 	/* ISA interface */
 	DEVMETHOD(isa_add_config,	isa_add_config),
@@ -1086,11 +1095,7 @@ static device_method_t isa_methods[] = {
 	{ 0, 0 }
 };
 
-driver_t isa_driver = {
-	"isa",
-	isa_methods,
-	1,			/* no softc */
-};
+DEFINE_CLASS_0(isa, isa_driver, isa_methods, 0);
 
 devclass_t isa_devclass;
 

Modified: head/sys/isa/isa_common.h
==============================================================================
--- head/sys/isa/isa_common.h	Tue Nov 18 20:41:14 2008	(r185058)
+++ head/sys/isa/isa_common.h	Tue Nov 18 21:01:54 2008	(r185059)
@@ -59,6 +59,7 @@ struct isa_device {
 	int			id_pnpbios_handle; /* pnp handle, if any */
 	int			id_pnp_csn; /* pnp Card Number */
 	int			id_pnp_ldn; /* pnp Logical device on card */
+	int			id_order;
 };
 
 #define DEVTOISA(dev)	((struct isa_device *) device_get_ivars(dev))

Modified: head/sys/isa/isahint.c
==============================================================================
--- head/sys/isa/isahint.c	Tue Nov 18 20:41:14 2008	(r185058)
+++ head/sys/isa/isahint.c	Tue Nov 18 21:01:54 2008	(r185059)
@@ -33,10 +33,11 @@ __FBSDID("$FreeBSD$");
 #include <sys/bus.h>
 #include <sys/module.h>
 #include <isa/isavar.h>
+#include <isa/isa_common.h>
 #include <machine/resource.h>
 
-static void
-isahint_add_device(device_t parent, const char *name, int unit)
+void
+isa_hinted_child(device_t parent, const char *name, int unit)
 {
 	device_t	child;
 	int		sensitive, start, count;
@@ -82,43 +83,79 @@ isahint_add_device(device_t parent, cons
 	isa_set_configattr(child, (isa_get_configattr(child)|ISACFGATTR_HINTS));
 }
 
-static void
-isahint_identify(driver_t *driver, device_t parent)
+static int
+isa_match_resource_hint(device_t dev, int type, long value)
 {
-	int i;
-	static char buf[] = "isaXXX";
-	const char *dname;
-	int dunit;
-
-	/*
-	 * Add all devices configured to be attached to parent.
-	 */
-	sprintf(buf, "isa%d", device_get_unit(parent));
-	i = 0;
-	while (resource_find_match(&i, &dname, &dunit, "at", buf) == 0)
-		isahint_add_device(parent, dname, dunit);
-
-	/*
-	 * and isa?
-	 */
-	i = 0;
-	while (resource_find_match(&i, &dname, &dunit, "at", "isa") == 0)
-		isahint_add_device(parent, dname, dunit);
+	struct isa_device* idev = DEVTOISA(dev);
+	struct resource_list *rl = &idev->id_resources;
+	struct resource_list_entry *rle;
+
+	STAILQ_FOREACH(rle, rl, link) {
+		if (rle->type != type)
+			continue;
+		if (rle->start <= value && rle->end >= value)
+			return (1);
+	}
+	return (0);
 }
 
-static device_method_t isahint_methods[] = {
-	/* Device interface */
-	DEVMETHOD(device_identify,	isahint_identify),
-
-	{ 0, 0 }
-};
-
-static driver_t isahint_driver = {
-	"hint",
-	isahint_methods,
-	1,			/* no softc */
-};
-
-static devclass_t hint_devclass;
-
-DRIVER_MODULE(isahint, isa, isahint_driver, hint_devclass, 0, 0);
+void
+isa_hint_device_unit(device_t bus, device_t child, const char *name, int *unitp)
+{
+	const char *s;
+	long value;
+	int line, matches, unit;
+
+	line = 0;
+	for (;;) {
+		if (resource_find_dev(&line, name, &unit, "at", NULL) != 0)
+			break;
+
+		/* Must have an "at" for isa. */
+		resource_string_value(name, unit, "at", &s);
+		if (!(strcmp(s, device_get_nameunit(bus)) == 0 ||
+		    strcmp(s, device_get_name(bus)) == 0))
+			continue;
+
+		/*
+		 * Check for matching resources.  We must have at least one,
+		 * and all resources specified have to match.
+		 *
+		 * XXX: We may want to revisit this to be more lenient and wire
+		 * as long as it gets one match.
+		 */
+		matches = 0;
+		if (resource_long_value(name, unit, "port", &value) == 0) {
+			if (isa_match_resource_hint(child, SYS_RES_IOPORT,
+			    value))
+				matches++;
+			else
+				continue;
+		}
+		if (resource_long_value(name, unit, "maddr", &value) == 0) {
+			if (isa_match_resource_hint(child, SYS_RES_MEMORY,
+			    value))
+				matches++;
+			else
+				continue;
+		}
+		if (resource_long_value(name, unit, "irq", &value) == 0) {
+			if (isa_match_resource_hint(child, SYS_RES_IRQ, value))
+				matches++;
+			else
+				continue;
+		}
+		if (resource_long_value(name, unit, "drq", &value) == 0) {
+			if (isa_match_resource_hint(child, SYS_RES_DRQ, value))
+				matches++;
+			else
+				continue;
+		}
+
+		if (matches > 0) {
+			/* We have a winner! */
+			*unitp = unit;
+			break;
+		}
+	}
+}

Modified: head/sys/isa/isavar.h
==============================================================================
--- head/sys/isa/isavar.h	Tue Nov 18 20:41:14 2008	(r185058)
+++ head/sys/isa/isavar.h	Tue Nov 18 21:01:54 2008	(r185059)
@@ -181,6 +181,9 @@ int	isa_dmatc(int chan);
 		    (int)(chan), (uintmax_t)(size)); \
 	} while (0) 
 
+void	isa_hinted_child(device_t parent, const char *name, int unit);
+void	isa_hint_device_unit(device_t bus, device_t child, const char *name,
+	    int *unitp);
 int	isab_attach(device_t dev);
 
 #ifdef PC98

Modified: head/sys/kern/bus_if.m
==============================================================================
--- head/sys/kern/bus_if.m	Tue Nov 18 20:41:14 2008	(r185058)
+++ head/sys/kern/bus_if.m	Tue Nov 18 21:01:54 2008	(r185059)
@@ -544,7 +544,7 @@ METHOD int config_intr {
  */
 METHOD void hinted_child {
 	device_t	_dev;
-	const char *	_dname;
+	const char	*_dname;
 	int		_dunit;
 };
 
@@ -558,3 +558,19 @@ METHOD bus_dma_tag_t get_dma_tag {
 	device_t	_dev;
 	device_t	_child;
 } DEFAULT bus_generic_get_dma_tag;
+
+/**
+ * @brief Allow the bus to determine the unit number of a device.
+ *
+ * @param _dev		the parent device of @p _child
+ * @param _child	the device whose unit is to be wired
+ * @param _name		the name of the device's new devclass
+ * @param _unitp	a pointer to the device's new unit value
+ */
+METHOD void hint_device_unit {
+	device_t	_dev;
+	device_t	_child;
+	const char	*_name;
+	int		*_unitp;
+};
+

Modified: head/sys/kern/subr_bus.c
==============================================================================
--- head/sys/kern/subr_bus.c	Tue Nov 18 20:41:14 2008	(r185058)
+++ head/sys/kern/subr_bus.c	Tue Nov 18 21:01:54 2008	(r185059)
@@ -1315,12 +1315,18 @@ devclass_get_sysctl_tree(devclass_t dc)
  * @retval ENOMEM	memory allocation failure
  */
 static int
-devclass_alloc_unit(devclass_t dc, int *unitp)
+devclass_alloc_unit(devclass_t dc, device_t dev, int *unitp)
 {
+	const char *s;
 	int unit = *unitp;
 
 	PDEBUG(("unit %d in devclass %s", unit, DEVCLANAME(dc)));
 
+	/* Ask the parent bus if it wants to wire this device. */
+	if (unit == -1)
+		BUS_HINT_DEVICE_UNIT(device_get_parent(dev), dev, dc->name,
+		    &unit);
+
 	/* If we were given a wired unit number, check for existing device */
 	/* XXX imp XXX */
 	if (unit != -1) {
@@ -1334,8 +1340,18 @@ devclass_alloc_unit(devclass_t dc, int *
 	} else {
 		/* Unwired device, find the next available slot for it */
 		unit = 0;
-		while (unit < dc->maxunit && dc->devices[unit] != NULL)
-			unit++;
+		for (unit = 0;; unit++) {
+			/* If there is an "at" hint for a unit then skip it. */
+			if (resource_string_value(dc->name, unit, "at", &s) ==
+			    0)
+				continue;
+
+			/* If this device slot is already in use, skip it. */
+			if (unit < dc->maxunit && dc->devices[unit] != NULL)
+				continue;
+
+			break;
+		}
 	}
 
 	/*
@@ -1397,7 +1413,7 @@ devclass_add_device(devclass_t dc, devic
 	if (!dev->nameunit)
 		return (ENOMEM);
 
-	if ((error = devclass_alloc_unit(dc, &dev->unit)) != 0) {
+	if ((error = devclass_alloc_unit(dc, dev, &dev->unit)) != 0) {
 		free(dev->nameunit, M_BUS);
 		dev->nameunit = NULL;
 		return (error);


More information about the svn-src-head mailing list