Commit 1e727616 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

[PATCH] usbcore: Make the core release hcd structures

This patch contains changes to usbcore making the core responsible for
deallocating memory for usb_hcd structures, rather than calling back into
the host controller drivers.  This solves a long-standing oops, since the
drivers may have been unloaded from memory by the time the release routine
is called.  (There probably are some Bugzilla entries caused by this, but
I don't know which ones.)

To really fix this up properly will require merging the HCD "glue" layer
into the higher core structures.  As things stand now, a usb_hcd contains
a usb_bus member, and the usb_bus is associated with a class_device: when
the class_device is released the usb_hcd gets deallocated.  It's awkward
in that neither the usb_hcd nor the usb_bus has its own reference count,
and the class_device is created when the bus is registered (not when it is
initialized).
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent 691f9abb
......@@ -38,14 +38,6 @@
/*-------------------------------------------------------------------------*/
static void hcd_pci_release(struct usb_bus *bus)
{
struct usb_hcd *hcd = bus->hcpriv;
if (hcd)
hcd->driver->hcd_free(hcd);
}
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
......@@ -161,7 +153,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
if ((retval = hcd_buffer_create (hcd)) != 0) {
clean_3:
driver->hcd_free (hcd);
kfree (hcd);
goto clean_2;
}
......@@ -195,8 +187,8 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
usb_bus_init (&hcd->self);
hcd->self.op = &usb_hcd_operations;
hcd->self.release = &usb_hcd_release;
hcd->self.hcpriv = (void *) hcd;
hcd->self.release = &hcd_pci_release;
init_timer (&hcd->rh_timer);
INIT_LIST_HEAD (&hcd->dev_list);
......
......@@ -1622,3 +1622,13 @@ void usb_hc_died (struct usb_hcd *hcd)
}
EXPORT_SYMBOL (usb_hc_died);
/*-------------------------------------------------------------------------*/
void usb_hcd_release(struct usb_bus *bus)
{
struct usb_hcd *hcd;
hcd = container_of (bus, struct usb_hcd, self);
kfree(hcd);
}
EXPORT_SYMBOL (usb_hcd_release);
......@@ -192,7 +192,6 @@ struct hc_driver {
/* memory lifecycle */
struct usb_hcd *(*hcd_alloc) (void);
void (*hcd_free) (struct usb_hcd *hcd);
/* manage i/o requests, device state */
int (*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb,
......@@ -360,6 +359,8 @@ static inline int hcd_register_root (struct usb_device *usb_dev,
return usb_register_root_hub (usb_dev, hcd->self.controller);
}
extern void usb_hcd_release (struct usb_bus *);
extern void usb_set_device_state(struct usb_device *udev,
enum usb_device_state new_state);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment