summaryrefslogtreecommitdiffstats
path: root/drivers/staging/greybus/usb.c
diff options
context:
space:
mode:
authorJohan Hovold2015-07-30 20:30:38 +0200
committerGreg Kroah-Hartman2015-07-30 22:49:49 +0200
commitcc9bd53eb1bf50e265a8f8741a624bf67851f5c0 (patch)
treec18feef83cb7c829e5b27cfb38e619dc3b098ca8 /drivers/staging/greybus/usb.c
parentgreybus: usb: renumber operation types (diff)
downloadkernel-qcow2-linux-cc9bd53eb1bf50e265a8f8741a624bf67851f5c0.tar.gz
kernel-qcow2-linux-cc9bd53eb1bf50e265a8f8741a624bf67851f5c0.tar.xz
kernel-qcow2-linux-cc9bd53eb1bf50e265a8f8741a624bf67851f5c0.zip
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 <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/usb.c')
-rw-r--r--drivers/staging/greybus/usb.c46
1 files changed, 26 insertions, 20 deletions
diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c
index 2a146d77ecda..1ba731e6bfad 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 = {