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