Actually there is two different functions for freeing usb devices
resources:

 - usbd_remove_device() which is only called if an error occurs when
   adding a new device

 - usb_free_device() which is called when a device is detached


The diff below merge the two functions into one and as a side effect
correctly free all the device resources if there's an error when adding
a new device. In other words it plugs some possible memory leaks if
usb_probe_and_attach() fails.

While here set a pointer to NULL instead of 0 after freeing it.

Ok?

Martin

Index: usb_subr.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/usb_subr.c,v
retrieving revision 1.82
diff -u -p -r1.82 usb_subr.c
--- usb_subr.c  15 May 2012 12:52:44 -0000      1.82
+++ usb_subr.c  15 Aug 2012 10:24:02 -0000
@@ -967,7 +967,7 @@ usbd_probe_and_attach(struct device *par
                }
 
                free(dev->subdevs, M_USB);
-               dev->subdevs = 0;
+               dev->subdevs = NULL;
        }
        /* No interfaces were attached in any of the configurations. */
 
@@ -1101,7 +1101,7 @@ usbd_new_device(struct device *parent, u
        err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
            &dev->default_pipe);
        if (err) {
-               usbd_remove_device(dev, up);
+               usb_free_device(dev, up);
                return (err);
        }
 
@@ -1150,7 +1150,7 @@ usbd_new_device(struct device *parent, u
        if (err) {
                DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
                    "failed\n", addr));
-               usbd_remove_device(dev, up);
+               usb_free_device(dev, up);
                return (err);
        }
 
@@ -1175,13 +1175,13 @@ usbd_new_device(struct device *parent, u
                /* Illegal device descriptor */
                DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n",
                    dd->bDescriptorType));
-               usbd_remove_device(dev, up);
+               usb_free_device(dev, up);
                return (USBD_INVAL);
        }
 
        if (dd->bLength < USB_DEVICE_DESCRIPTOR_SIZE) {
                DPRINTFN(-1,("usbd_new_device: bad length %d\n", dd->bLength));
-               usbd_remove_device(dev, up);
+               usb_free_device(dev, up);
                return (USBD_INVAL);
        }
 
@@ -1191,7 +1191,7 @@ usbd_new_device(struct device *parent, u
        if (err) {
                DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
                    "failed\n", addr));
-               usbd_remove_device(dev, up);
+               usb_free_device(dev, up);
                return (err);
        }
 
@@ -1201,7 +1201,7 @@ usbd_new_device(struct device *parent, u
        if (err) {
                DPRINTFN(-1,("usbd_new_device: set address %d failed\n", addr));
                err = USBD_SET_ADDR_FAILED;
-               usbd_remove_device(dev, up);
+               usb_free_device(dev, up);
                return (err);
        }
 
@@ -1233,7 +1233,7 @@ usbd_new_device(struct device *parent, u
 
        err = usbd_probe_and_attach(parent, dev, port, addr);
        if (err) {
-               usbd_remove_device(dev, up);
+               usb_free_device(dev, up);
                return (err);
        }
 
@@ -1256,19 +1256,6 @@ usbd_reload_device_desc(usbd_device_hand
        return (USBD_NORMAL_COMPLETION);
 }
 
-void
-usbd_remove_device(usbd_device_handle dev, struct usbd_port *up)
-{
-       DPRINTF(("usbd_remove_device: %p\n", dev));
-
-       if (dev->default_pipe != NULL)
-               usbd_kill_pipe(dev->default_pipe);
-       up->device = NULL;
-       dev->bus->devices[dev->address] = NULL;
-
-       free(dev, M_USB);
-}
-
 int
 usbd_print(void *aux, const char *pnp)
 {
@@ -1414,10 +1401,12 @@ usbd_fill_deviceinfo(usbd_device_handle 
 }
 
 void
-usb_free_device(usbd_device_handle dev)
+usb_free_device(usbd_device_handle dev, struct usbd_port *up)
 {
        int ifcidx, nifc;
 
+       DPRINTF(("usb_free_device: %p\n", dev));
+
        if (dev->default_pipe != NULL)
                usbd_kill_pipe(dev->default_pipe);
        if (dev->ifaces != NULL) {
@@ -1430,6 +1419,9 @@ usb_free_device(usbd_device_handle dev)
                free(dev->cdesc, M_USB);
        if (dev->subdevs != NULL)
                free(dev->subdevs, M_USB);
+       up->device = NULL;
+       dev->bus->devices[dev->address] = NULL;
+
        free(dev, M_USB);
 }
 
@@ -1483,7 +1475,5 @@ usb_disconnect_port(struct usbd_port *up
                }
        }
 
-       dev->bus->devices[dev->address] = NULL;
-       up->device = NULL;
-       usb_free_device(dev);
+       usb_free_device(dev, up);
 }
Index: usbdivar.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdivar.h,v
retrieving revision 1.44
diff -u -p -r1.44 usbdivar.h
--- usbdivar.h  15 May 2012 12:48:32 -0000      1.44
+++ usbdivar.h  15 Aug 2012 10:11:06 -0000
@@ -240,10 +240,9 @@ usbd_status        usbd_setup_pipe(usbd_device_
                    usbd_pipe_handle *pipe);
 usbd_status    usbd_new_device(struct device *parent, usbd_bus_handle bus,
                    int depth, int lowspeed, int port, struct usbd_port *);
-void           usbd_remove_device(usbd_device_handle, struct usbd_port *);
 int            usbd_printBCD(char *cp, size_t len, int bcd);
 usbd_status    usbd_fill_iface_data(usbd_device_handle dev, int i, int a);
-void           usb_free_device(usbd_device_handle);
+void           usb_free_device(usbd_device_handle, struct usbd_port *);
 
 usbd_status    usb_insert_transfer(usbd_xfer_handle xfer);
 void           usb_transfer_complete(usbd_xfer_handle xfer);

Reply via email to