From cc9bd53eb1bf50e265a8f8741a624bf67851f5c0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 30 Jul 2015 20:30:38 +0200 Subject: greybus: usb: fix hcd allocation, deregistration and deallocation Fix allocation, deregistration and deallocation of USB HCD, and update the hcd_priv helper functions. The HCD private data was not allocated correctly, something which would lead to a crash when accessed in hcd_start. The HCD was neither reregistered or deallocated on connection tear down. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 2a146d7..1ba731e 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -40,12 +40,19 @@ struct gb_usb_hub_control_response { struct gb_usb_device { struct gb_connection *connection; - struct usb_hcd *hcd; u8 version_major; u8 version_minor; }; -#define to_gb_usb_device(d) ((struct gb_usb_device*) d->hcd_priv) +static inline struct gb_usb_device *to_gb_usb_device(struct usb_hcd *hcd) +{ + return (struct gb_usb_device *)hcd->hcd_priv; +} + +static inline struct usb_hcd *gb_usb_device_to_hcd(struct gb_usb_device *dev) +{ + return container_of((void *)dev, struct usb_hcd, hcd_priv); +} /* Define get_version() routine */ define_get_version(gb_usb_device, USB); @@ -143,45 +150,44 @@ static int gb_usb_connection_init(struct gb_connection *connection) { struct device *dev = &connection->dev; struct gb_usb_device *gb_usb_dev; + struct usb_hcd *hcd; int retval; - gb_usb_dev = kzalloc(sizeof(*gb_usb_dev), GFP_KERNEL); - if (!gb_usb_dev) + hcd = usb_create_hcd(&usb_gb_hc_driver, dev, dev_name(dev)); + if (!hcd) return -ENOMEM; + gb_usb_dev = to_gb_usb_device(hcd); gb_usb_dev->connection = connection; connection->private = gb_usb_dev; /* Check for compatible protocol version */ retval = get_version(gb_usb_dev); if (retval) - goto error_create_hcd; - - gb_usb_dev->hcd = usb_create_hcd(&usb_gb_hc_driver, dev, dev_name(dev)); - if (!gb_usb_dev->hcd) { - retval = -ENODEV; - goto error_create_hcd; - } + goto err_put_hcd; - gb_usb_dev->hcd->has_tt = 1; - gb_usb_dev->hcd->hcd_priv[0] = (unsigned long) gb_usb_dev; + hcd->has_tt = 1; - retval = usb_add_hcd(gb_usb_dev->hcd, 0, 0); + retval = usb_add_hcd(hcd, 0, 0); if (retval) - goto error_add_hcd; + goto err_put_hcd; return 0; -error_add_hcd: - usb_put_hcd(gb_usb_dev->hcd); -error_create_hcd: - kfree(gb_usb_dev); + +err_put_hcd: + usb_put_hcd(hcd); + return retval; } static void gb_usb_connection_exit(struct gb_connection *connection) { - // FIXME - tear everything down! + struct gb_usb_device *gb_usb_dev = connection->private; + struct usb_hcd *hcd = gb_usb_device_to_hcd(gb_usb_dev); + + usb_remove_hcd(hcd); + usb_put_hcd(hcd); } static struct gb_protocol usb_protocol = { -- cgit v0.10.2