diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c index d4f68336294d..2e99a1fbdd92 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(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 diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h index bb9addc234a1..abfac816445b 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 52e363d68053..3f50e6391c4c 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); }