diff options
author | imp <imp@FreeBSD.org> | 2007-02-03 16:19:28 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2007-02-03 16:19:28 +0000 |
commit | afa51f755af744fcd5970bda4708f1ad7e817640 (patch) | |
tree | bb3b3664d023ae5f3a142c1a0499d59c3f9d0b39 /sys/dev/usb/uhub.c | |
parent | 4bd0763c3806a456be52d8ba2ead16321f126b47 (diff) | |
download | FreeBSD-src-afa51f755af744fcd5970bda4708f1ad7e817640.zip FreeBSD-src-afa51f755af744fcd5970bda4708f1ad7e817640.tar.gz |
Fix memory leak of devinfo. The leak itself was documented in
PR/108719, but there's a simpler fix: free it after it is used, and
then get rid of the redundant frees this causes. Other leaks in this
PR not yet fixed.
While I'm here, remove NetBSD/OpenBSD code and some of the portability
#defines that were getting in the way of understanding this code. The
devinfo bug was harder to spot because one needed to know that
device_set_desc_copy() was used inside of one of them (one that didn't
take an argument!).
Prefer device_printf(sc->sc_dev, "...") to printf("%s:...",
device_get_nameunit(sc->sc_dev)). This saves almost 300 bytes.
PR: 108719
Submitted by: Antoine Brodin
Diffstat (limited to 'sys/dev/usb/uhub.c')
-rw-r--r-- | sys/dev/usb/uhub.c | 188 |
1 files changed, 66 insertions, 122 deletions
diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c index 6afce88..9033761 100644 --- a/sys/dev/usb/uhub.c +++ b/sys/dev/usb/uhub.c @@ -48,15 +48,10 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> -#if defined(__NetBSD__) || defined(__OpenBSD__) -#include <sys/device.h> -#include <sys/proc.h> -#elif defined(__FreeBSD__) #include <sys/module.h> #include <sys/bus.h> #include <sys/lock.h> #include <sys/mutex.h> -#endif #include <sys/sysctl.h> #include <machine/bus.h> @@ -69,8 +64,10 @@ __FBSDID("$FreeBSD$"); #define UHUB_INTR_INTERVAL 255 /* ms */ #ifdef USB_DEBUG -#define DPRINTF(x) if (uhubdebug) logprintf x -#define DPRINTFN(n,x) if (uhubdebug>(n)) logprintf x +#define DPRINTF(x) if (uhubdebug) printf x +#define DPRINTFN(n,x) if (uhubdebug > (n)) printf x +#define DEVPRINTF(x) if (uhubdebug) device_printf x +#define DEVPRINTFN(n, x)if (uhubdebug > (n)) device_printf x int uhubdebug = 0; SYSCTL_NODE(_hw_usb, OID_AUTO, uhub, CTLFLAG_RW, 0, "USB uhub"); SYSCTL_INT(_hw_usb_uhub, OID_AUTO, debug, CTLFLAG_RW, @@ -78,6 +75,8 @@ SYSCTL_INT(_hw_usb_uhub, OID_AUTO, debug, CTLFLAG_RW, #else #define DPRINTF(x) #define DPRINTFN(n,x) +#define DEVPRINTF(x) +#define DEVPRINTFN(n,x) #endif struct uhub_softc { @@ -94,11 +93,8 @@ struct uhub_softc { 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_child_location_str_t uhub_child_location_str; static bus_child_pnpinfo_str_t uhub_child_pnpinfo_str; -#endif - /* * We need two attachment points: @@ -106,13 +102,6 @@ static bus_child_pnpinfo_str_t uhub_child_pnpinfo_str; * Every other driver only connects to hubs */ -#if defined(__NetBSD__) || defined(__OpenBSD__) -USB_DECLARE_DRIVER(uhub); - -/* Create the driver instance for the hub connected to hub case */ -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_child_pnpinfo_str, uhub_child_pnpinfo_str), DEVMETHOD(bus_child_location_str, uhub_child_location_str), @@ -144,7 +133,6 @@ static driver_t uhubroot_driver = { uhubroot_methods, sizeof(struct uhub_softc) }; -#endif USB_MATCH(uhub) { @@ -161,9 +149,11 @@ USB_MATCH(uhub) return (UMATCH_NONE); } -USB_ATTACH(uhub) +int +uhub_attach(device_t self) { - USB_ATTACH_START(uhub, sc, uaa); + struct uhub_softc *sc = device_get_softc(self); + struct usb_attach_arg *uaa = device_get_ivars(self); usbd_device_handle dev = uaa->device; char *devinfo; usbd_status err; @@ -176,33 +166,31 @@ USB_ATTACH(uhub) struct usbd_tt *tts = NULL; devinfo = malloc(1024, M_TEMP, M_NOWAIT); - if (devinfo == NULL) { - USB_ATTACH_ERROR_RETURN; - } + if (devinfo == NULL) + return (ENXIO); DPRINTFN(1,("uhub_attach\n")); sc->sc_hub = dev; usbd_devinfo(dev, 1, devinfo); - USB_ATTACH_SETUP; + sc->sc_dev = self; + device_set_desc_copy(self, devinfo); + free(devinfo, M_TEMP); if (dev->depth > 0 && UHUB_IS_HIGH_SPEED(sc)) { - printf("%s: %s transaction translator%s\n", - device_get_nameunit(sc->sc_dev), + device_printf(sc->sc_dev, "%s transaction translator%s\n", UHUB_IS_SINGLE_TT(sc) ? "single" : "multiple", UHUB_IS_SINGLE_TT(sc) ? "" : "s"); } err = usbd_set_config_index(dev, 0, 1); if (err) { - DPRINTF(("%s: configuration failed, error=%s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err))); - free(devinfo, M_TEMP); - USB_ATTACH_ERROR_RETURN; + DEVPRINTF((sc->dev, "configuration failed, error=%s\n", + usbd_errstr(err))); + return (ENXIO); } if (dev->depth > USB_HUB_MAX_DEPTH) { - printf("%s: hub depth (%d) exceeded, hub ignored\n", - device_get_nameunit(sc->sc_dev), USB_HUB_MAX_DEPTH); - free(devinfo, M_TEMP); - USB_ATTACH_ERROR_RETURN; + device_printf(sc->sc_dev, "hub depth (%d) exceeded, hub ignored\n", + USB_HUB_MAX_DEPTH); + return (ENXIO); } /* Get hub descriptor. */ @@ -219,29 +207,27 @@ USB_ATTACH(uhub) err = usbd_do_request(dev, &req, &hubdesc); } if (err) { - DPRINTF(("%s: getting hub descriptor failed, error=%s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err))); - free(devinfo, M_TEMP); - USB_ATTACH_ERROR_RETURN; + DEVPRINTF((sc->sc_dev, "getting hub descriptor failed: %s\n", + usbd_errstr(err))); + return (ENXIO); } for (nremov = 0, port = 1; port <= nports; port++) if (!UHD_NOT_REMOV(&hubdesc, port)) nremov++; - printf("%s: %d port%s with %d removable, %s powered\n", - device_get_nameunit(sc->sc_dev), nports, nports != 1 ? "s" : "", - nremov, dev->self_powered ? "self" : "bus"); + device_printf(sc->sc_dev, "%d port%s with %d removable, %s powered\n", + nports, nports != 1 ? "s" : "", nremov, + dev->self_powered ? "self" : "bus"); if (nports == 0) { - printf("%s: no ports, hub ignored\n", device_get_nameunit(sc->sc_dev)); + device_printf(sc->sc_dev, "no ports, hub ignored\n"); goto bad; } hub = malloc(sizeof(*hub) + (nports-1) * sizeof(struct usbd_port), M_USBDEV, M_NOWAIT); if (hub == NULL) { - free(devinfo, M_TEMP); - USB_ATTACH_ERROR_RETURN; + return (ENXIO); } dev->hub = hub; dev->hub->hubsoftc = sc; @@ -256,24 +242,24 @@ USB_ATTACH(uhub) if (!dev->self_powered && dev->powersrc->parent != NULL && !dev->powersrc->parent->self_powered) { - printf("%s: bus powered hub connected to bus powered hub, " - "ignored\n", device_get_nameunit(sc->sc_dev)); + device_printf(sc->sc_dev, "bus powered hub connected to bus " + "powered hub, ignored\n"); goto bad; } /* Set up interrupt pipe. */ err = usbd_device2interface_handle(dev, 0, &iface); if (err) { - printf("%s: no interface handle\n", device_get_nameunit(sc->sc_dev)); + device_printf(sc->sc_dev, "no interface handle\n"); goto bad; } ed = usbd_interface2endpoint_descriptor(iface, 0); if (ed == NULL) { - printf("%s: no endpoint descriptor\n", device_get_nameunit(sc->sc_dev)); + device_printf(sc->sc_dev, "no endpoint descriptor\n"); goto bad; } if ((ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { - printf("%s: bad interrupt endpoint\n", device_get_nameunit(sc->sc_dev)); + device_printf(sc->sc_dev, "bad interrupt endpoint\n"); goto bad; } @@ -281,8 +267,7 @@ USB_ATTACH(uhub) USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_status, sizeof(sc->sc_status), uhub_intr, UHUB_INTR_INTERVAL); if (err) { - printf("%s: cannot open interrupt pipe\n", - device_get_nameunit(sc->sc_dev)); + device_printf(sc->sc_dev, "cannot open interrupt pipe\n"); goto bad; } @@ -351,9 +336,9 @@ USB_ATTACH(uhub) /* Turn the power on. */ err = usbd_set_port_feature(dev, port, UHF_PORT_POWER); if (err) - printf("%s: port %d power on failed, %s\n", - device_get_nameunit(sc->sc_dev), port, - usbd_errstr(err)); + device_printf(sc->sc_dev, + "port %d power on failed, %s\n", port, + usbd_errstr(err)); DPRINTF(("usb_init_port: turn on port %d power\n", port)); /* Wait for stable power. */ usbd_delay_ms(dev, pwrdly); @@ -362,15 +347,12 @@ USB_ATTACH(uhub) /* The usual exploration will finish the setup. */ sc->sc_running = 1; - - USB_ATTACH_SUCCESS_RETURN; - + return (0); bad: if (hub) free(hub, M_USBDEV); - free(devinfo, M_TEMP); dev->hub = NULL; - USB_ATTACH_ERROR_RETURN; + return (ENXIO); } usbd_status @@ -403,8 +385,9 @@ uhub_explore(usbd_device_handle dev) } status = UGETW(up->status.wPortStatus); change = UGETW(up->status.wPortChange); - DPRINTFN(3,("uhub_explore: %s port %d status 0x%04x 0x%04x\n", - device_get_nameunit(sc->sc_dev), port, status, change)); + DEVPRINTFN(3,(sc->sc_dev, + "uhub_explore: port %d status 0x%04x 0x%04x\n", port, + status, change)); if (change & UPS_C_PORT_ENABLED) { DPRINTF(("uhub_explore: C_PORT_ENABLED 0x%x\n", change)); usbd_clear_port_feature(dev, port, UHF_C_PORT_ENABLE); @@ -412,21 +395,21 @@ uhub_explore(usbd_device_handle dev) /* Ignore the port error if the device vanished. */ } else if (status & UPS_PORT_ENABLED) { - printf("%s: illegal enable change, port %d\n", - device_get_nameunit(sc->sc_dev), port); + device_printf(sc->sc_dev, + "illegal enable change, port %d\n", port); } else { /* Port error condition. */ if (up->restartcnt) /* no message first time */ - printf("%s: port error, restarting " - "port %d\n", - device_get_nameunit(sc->sc_dev), port); + device_printf(sc->sc_dev, + "port error, restarting port %d\n", + port); if (up->restartcnt++ < USBD_RESTART_MAX) goto disco; else - printf("%s: port error, giving up " - "port %d\n", - device_get_nameunit(sc->sc_dev), port); + device_printf(sc->sc_dev, + "port error, giving up port %d\n", + port); } } if (!(change & UPS_C_CONNECT_STATUS)) { @@ -438,8 +421,8 @@ uhub_explore(usbd_device_handle dev) #if 0 && defined(DIAGNOSTIC) if (up->device == NULL && (status & UPS_CURRENT_CONNECT_STATUS)) - printf("%s: connected, no device\n", - device_get_nameunit(sc->sc_dev)); + deivce_printf(sc->sc_dev, + "connected, no device\n"); #endif continue; } @@ -476,16 +459,16 @@ uhub_explore(usbd_device_handle dev) /* Connected */ if (!(status & UPS_PORT_POWER)) - printf("%s: strange, connected port %d has no power\n", - device_get_nameunit(sc->sc_dev), port); + device_printf(sc->sc_dev, + "strange, connected port %d has no power\n", port); /* Wait for maximum device power up time. */ usbd_delay_ms(dev, USB_PORT_POWERUP_DELAY); /* Reset port, which implies enabling it. */ if (usbd_reset_port(dev, port, &up->status)) { - printf("%s: port %d reset failed\n", - device_get_nameunit(sc->sc_dev), port); + device_printf(sc->sc_dev, "port %d reset failed\n", + port); continue; } /* Get port status again, it might have changed during reset */ @@ -500,17 +483,17 @@ uhub_explore(usbd_device_handle dev) if (!(status & UPS_CURRENT_CONNECT_STATUS)) { /* Nothing connected, just ignore it. */ #ifdef DIAGNOSTIC - printf("%s: port %d, device disappeared after reset\n", - device_get_nameunit(sc->sc_dev), port); + device_printf(sc->sc_dev, + "port %d, device disappeared after reset\n", port); #endif continue; } #if 0 if (UHUB_IS_HIGH_SPEED(sc) && !(status & UPS_HIGH_SPEED)) { - printf("%s: port %d, transaction translation not " - "implemented, low/full speed device ignored\n", - device_get_nameunit(sc->sc_dev), port); + device_printf(sc->sc_dev, + "port %d, transaction translation not implemented," + " low/full speed device ignored\n", port); continue; } #endif @@ -537,8 +520,9 @@ uhub_explore(usbd_device_handle dev) * some other serious problem. Since we cannot leave * at 0 we have to disable the port instead. */ - printf("%s: device problem (%s), disabling port %d\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err), port); + device_printf(sc->sc_dev, + "device problem (%s), disabling port %d\n", + usbd_errstr(err), port); usbd_clear_port_feature(dev, port, UHF_PORT_ENABLE); } else { /* The port set up succeeded, reset error count. */ @@ -551,36 +535,6 @@ uhub_explore(usbd_device_handle dev) return (USBD_NORMAL_COMPLETION); } -#if defined(__NetBSD__) || defined(__OpenBSD__) -int -uhub_activate(device_t self, enum devact act) -{ - struct uhub_softc *sc = (struct uhub_softc *)self; - struct usbd_hub *hub = sc->sc_hub->hub; - usbd_device_handle dev; - int nports, port, i; - - switch (act) { - case DVACT_ACTIVATE: - return (EOPNOTSUPP); - - case DVACT_DEACTIVATE: - if (hub == NULL) /* malfunctioning hub */ - break; - nports = hub->hubdesc.bNbrPorts; - for(port = 0; port < nports; port++) { - dev = hub->ports[port].device; - if (dev != NULL && dev->subdevs != NULL) { - for (i = 0; dev->subdevs[i] != NULL; i++) - config_deactivate(dev->subdevs[i]); - } - } - break; - } - return (0); -} -#endif - /* * Called from process context when the hub is gone. * Detach all devices on active ports. @@ -592,12 +546,7 @@ USB_DETACH(uhub) struct usbd_port *rup; int port, nports; -#if defined(__NetBSD__) || defined(__OpenBSD__) - DPRINTF(("uhub_detach: sc=%p flags=%d\n", sc, flags)); -#elif defined(__FreeBSD__) DPRINTF(("uhub_detach: sc=%port\n", sc)); -#endif - if (hub == NULL) /* Must be partially working */ return (0); @@ -622,7 +571,6 @@ USB_DETACH(uhub) return (0); } -#if defined(__FreeBSD__) int uhub_child_location_str(device_t cbdev, device_t child, char *buf, size_t buflen) @@ -716,8 +664,6 @@ found_dev: mtx_unlock(&Giant); return (0); } -#endif - /* * Hub interrupt. @@ -737,7 +683,5 @@ uhub_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) usb_needs_explore(sc->sc_hub); } -#if defined(__FreeBSD__) DRIVER_MODULE(uhub, usb, uhubroot_driver, uhubroot_devclass, 0, 0); DRIVER_MODULE(uhub, uhub, uhub_driver, uhub_devclass, usbd_driver_load, 0); -#endif |