summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2004-08-14 22:10:26 +0000
committerimp <imp@FreeBSD.org>2004-08-14 22:10:26 +0000
commitda6b7d8015bfe072fdecf22c4958f40e135d3c2b (patch)
tree9b99e9bea5a7c62b7a26bf54ee02ab0537c960ee /sys/dev
parentbce29358a4ba1d2f5f059296d3e2d2d6ff05ce13 (diff)
downloadFreeBSD-src-da6b7d8015bfe072fdecf22c4958f40e135d3c2b.zip
FreeBSD-src-da6b7d8015bfe072fdecf22c4958f40e135d3c2b.tar.gz
Next step in making usb more newbus:
o reprobe children when a new driver is added to uhub o fix the usbd_probe_and_attach to set the ivars to a malloc'd area, as well as freeing the ivars on child destruction. o Don't delete children that don't attach. Evidentally, the need to do this is a common misconception. o minor formatting foo that may violate style(9) at the moment, but keeps the diffs against my p4 tree smaller. This does not solve the ugen gobbling things up problem, but the fixes I have for that expose bugs in other parts of the tree...
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/uhub.c40
-rw-r--r--sys/dev/usb/usb_port.h6
-rw-r--r--sys/dev/usb/usb_subr.c68
3 files changed, 50 insertions, 64 deletions
diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c
index d4f6833..2e99a1f 100644
--- a/sys/dev/usb/uhub.c
+++ b/sys/dev/usb/uhub.c
@@ -90,10 +90,9 @@ Static usbd_status uhub_explore(usbd_device_handle hub);
Static void uhub_intr(usbd_xfer_handle, usbd_private_handle,usbd_status);
#if defined(__FreeBSD__)
-Static bus_driver_added_t uhub_driver_added;
Static bus_child_detached_t uhub_child_detached;
-int uhub_child_location_str(device_t, device_t, char*, size_t);
-int uhub_child_pnpinfo_str(device_t, device_t, char*, size_t);
+Static bus_child_location_str_t uhub_child_location_str;
+Static bus_child_pnpinfo_str_t uhub_child_pnpinfo_str;
#endif
@@ -111,25 +110,26 @@ CFATTACH_DECL(uhub_uhub, sizeof(struct uhub_softc),
uhub_match, uhub_attach, uhub_detach, uhub_activate);
#elif defined(__FreeBSD__)
USB_DECLARE_DRIVER_INIT(uhub,
- DEVMETHOD(bus_driver_added, uhub_driver_added),
- DEVMETHOD(bus_child_detached, uhub_child_detached),
- DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_str),
- DEVMETHOD(bus_child_location_str, uhub_child_location_str),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
- DEVMETHOD(device_shutdown, bus_generic_shutdown)
- );
+ DEVMETHOD(bus_child_detached, uhub_child_detached),
+ DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_str),
+ DEVMETHOD(bus_child_location_str, uhub_child_location_str),
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown)
+ );
/* Create the driver instance for the hub connected to usb case. */
devclass_t uhubroot_devclass;
Static device_method_t uhubroot_methods[] = {
DEVMETHOD(bus_child_detached, uhub_child_detached),
- DEVMETHOD(device_probe, uhub_match),
- DEVMETHOD(device_attach, uhub_attach),
- DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_str),
DEVMETHOD(bus_child_location_str, uhub_child_location_str),
+ DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_str),
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+ DEVMETHOD(device_probe, uhub_match),
+ DEVMETHOD(device_attach, uhub_attach),
DEVMETHOD(device_detach, uhub_detach),
DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, bus_generic_resume),
@@ -714,18 +714,6 @@ uhub_child_detached(device_t self, device_t child)
}
}
}
-
-Static void
-uhub_driver_added(device_t _dev, driver_t *_driver)
-{
- /*
- * Don't do anything, as reprobing does not work currently.
- * In the future we should properly allocate ivars so we can
- * leave the devices attached to the newbus tree. Once we do
- * that, then we can reprobe on driver loading with the
- * default driver added routines.
- */
-}
#endif
diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h
index bb9addc..abfac81 100644
--- a/sys/dev/usb/usb_port.h
+++ b/sys/dev/usb/usb_port.h
@@ -417,7 +417,11 @@ typedef struct callout usb_callout_t;
#define PWR_RESUME 0
#define PWR_SUSPEND 1
-#define config_detach(dev, flag) device_delete_child(device_get_parent(dev), dev)
+#define config_detach(dev, flag) \
+ do { \
+ free(device_get_ivars(dev), M_USB); \
+ device_delete_child(device_get_parent(dev), dev); \
+ } while (0);
typedef struct malloc_type *usb_malloc_type;
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c
index 52e363d..3f50e63 100644
--- a/sys/dev/usb/usb_subr.c
+++ b/sys/dev/usb/usb_subr.c
@@ -853,20 +853,22 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
usbd_interface_handle ifaces[256]; /* 256 is the absolute max */
#if defined(__FreeBSD__)
- /*
- * XXX uaa is a static var. Not a problem as it _should_ be used only
- * during probe and attach. Should be changed however.
- */
- device_t bdev;
+ /* XXX FreeBSD may leak resources on failure cases -- fixme */
+ device_t bdev;
+ struct usb_attach_arg *uaap;
+
bdev = device_add_child(parent, NULL, -1);
if (!bdev) {
- printf("%s: Device creation failed\n", USBDEVNAME(dev->bus->bdev));
- return (USBD_INVAL);
+ device_printf(parent, "Device creation failed\n");
+ return (USBD_INVAL);
}
- device_set_ivars(bdev, &uaa);
device_quiet(bdev);
+ uaap = malloc(sizeof(uaa), M_USB, M_NOWAIT);
+ if (uaap == NULL) {
+ return (USBD_INVAL);
+ }
+ device_set_ivars(bdev, uaap);
#endif
-
uaa.device = dev;
uaa.iface = NULL;
uaa.ifaces = NULL;
@@ -888,15 +890,14 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
return (USBD_NOMEM);
dev->subdevs[0] = bdev;
dev->subdevs[1] = 0;
+ *uaap = uaa;
dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
if (dv) {
return (USBD_NORMAL_COMPLETION);
- } else {
- tmpdv = dev->subdevs;
- dev->subdevs = NULL;
- free(tmpdv, M_USB);
}
-
+ tmpdv = dev->subdevs;
+ dev->subdevs = NULL;
+ free(tmpdv, M_USB);
DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
DPRINTF(("usbd_probe_and_attach: looping over %d configurations\n",
@@ -915,10 +916,6 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
printf("%s: port %d, set config at addr %d failed\n",
USBDEVPTRNAME(parent), port, addr);
#endif
-#if defined(__FreeBSD__)
- device_delete_child(parent, bdev);
-#endif
-
return (err);
}
nifaces = dev->cdesc->bNumInterface;
@@ -929,18 +926,11 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
uaa.nifaces = nifaces;
dev->subdevs = malloc((nifaces+1) * sizeof dv, M_USB,M_NOWAIT);
if (dev->subdevs == NULL) {
-#if defined(__FreeBSD__)
- device_delete_child(parent, bdev);
-#endif
return (USBD_NOMEM);
}
dev->ifacenums = malloc((nifaces) * sizeof(*dev->ifacenums),
M_USB,M_NOWAIT);
if (dev->ifacenums == NULL) {
- free(tmpdv, M_USB);
-#if defined(__FreeBSD__)
- device_delete_child(parent, bdev);
-#endif
return (USBD_NOMEM);
}
@@ -953,6 +943,7 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
dev->subdevs[found] = bdev;
dev->subdevs[found + 1] = 0;
dev->ifacenums[found] = i;
+ *uaap = uaa;
dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print,
usbd_submatch);
if (dv != NULL) {
@@ -963,11 +954,15 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
/* create another child for the next iface */
bdev = device_add_child(parent, NULL, -1);
if (!bdev) {
- printf("%s: Device creation failed\n",
- USBDEVNAME(dev->bus->bdev));
+ device_printf(parent,
+ "Device add failed\n");
return (USBD_NORMAL_COMPLETION);
}
- device_set_ivars(bdev, &uaa);
+ uaap = malloc(sizeof(uaa), M_USB, M_NOWAIT);
+ if (uaap == NULL) {
+ return (USBD_NOMEM);
+ }
+ device_set_ivars(bdev, uaap);
device_quiet(bdev);
#endif
} else {
@@ -976,8 +971,9 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
}
if (found != 0) {
#if defined(__FreeBSD__)
- /* remove the last created child again; it is unused */
+ /* remove the last created child. It is unused */
device_delete_child(parent, bdev);
+ /* free(uaap, M_USB); */ /* May be needed? xxx */
#endif
return (USBD_NORMAL_COMPLETION);
}
@@ -1000,18 +996,19 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
uaa.configno = UHUB_UNK_CONFIGURATION;
uaa.ifaceno = UHUB_UNK_INTERFACE;
dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
- if (dev->subdevs == 0)
+ if (dev->subdevs == 0) {
return (USBD_NOMEM);
+ }
dev->subdevs[0] = bdev;
dev->subdevs[1] = 0;
+ *uaap = uaa;
dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
if (dv != NULL) {
return (USBD_NORMAL_COMPLETION);
- } else {
- tmpdv = dev->subdevs;
- dev->subdevs = 0;
- free(tmpdv, M_USB);
}
+ tmpdv = dev->subdevs;
+ dev->subdevs = 0;
+ free(tmpdv, M_USB);
/*
* The generic attach failed, but leave the device as it is.
@@ -1019,9 +1016,6 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
* fully operational and not harming anyone.
*/
DPRINTF(("usbd_probe_and_attach: generic attach failed\n"));
-#if defined(__FreeBSD__)
- device_delete_child(parent, bdev);
-#endif
return (USBD_NORMAL_COMPLETION);
}
OpenPOWER on IntegriCloud