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...
This commit is contained in:
Warner Losh 2004-08-14 22:10:26 +00:00
parent 83e76ab9e3
commit 487d427700
3 changed files with 50 additions and 64 deletions

View File

@ -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(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(bus_child_pnpinfo_str, uhub_child_pnpinfo_str),
DEVMETHOD(bus_child_location_str, uhub_child_location_str),
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

View File

@ -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;

View File

@ -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);
}