greybus: es1: add more structure to probe error handling
authorJohan Hovold <johan@hovoldconsulting.com>
Wed, 4 Nov 2015 17:55:21 +0000 (18:55 +0100)
committerGreg Kroah-Hartman <gregkh@google.com>
Thu, 5 Nov 2015 04:35:18 +0000 (20:35 -0800)
Add more structure to probe error handling rather than use the big
hammer and call disconnect directly.

This is needed to fix some host-device life-time issues.

Note that there was never any need to clear the USB interface data as
this will be done by driver core.

Compile-only tested.

Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/es1.c

index 30477690e54e07e07581ce76e94f706bdd8b4ca4..858c4aa9e28a386cc2eae6120229fd2964a3ca56 100644 (file)
@@ -359,19 +359,11 @@ static int check_urb_status(struct urb *urb)
        return -EAGAIN;
 }
 
-static void ap_disconnect(struct usb_interface *interface)
+static void es1_destroy(struct es1_ap_dev *es1)
 {
-       struct es1_ap_dev *es1;
        struct usb_device *udev;
        int i;
 
-       es1 = usb_get_intfdata(interface);
-       if (!es1)
-               return;
-
-       for (i = 0; i < NUM_CPORT_IN_URB; ++i)
-               usb_kill_urb(es1->cport_in_urb[i]);
-
        debugfs_remove(apb1_log_enable_dentry);
        usb_log_disable(es1);
 
@@ -397,13 +389,23 @@ static void ap_disconnect(struct usb_interface *interface)
                es1->cport_in_buffer[i] = NULL;
        }
 
-       usb_set_intfdata(interface, NULL);
        udev = es1->usb_dev;
        gb_hd_remove(es1->hd);
 
        usb_put_dev(udev);
 }
 
+static void ap_disconnect(struct usb_interface *interface)
+{
+       struct es1_ap_dev *es1 = usb_get_intfdata(interface);
+       int i;
+
+       for (i = 0; i < NUM_CPORT_IN_URB; ++i)
+               usb_kill_urb(es1->cport_in_urb[i]);
+
+       es1_destroy(es1);
+}
+
 static void cport_in_callback(struct urb *urb)
 {
        struct gb_host_device *hd = urb->context;
@@ -693,12 +695,16 @@ static int ap_probe(struct usb_interface *interface,
        for (i = 0; i < NUM_CPORT_IN_URB; ++i) {
                retval = usb_submit_urb(es1->cport_in_urb[i], GFP_KERNEL);
                if (retval)
-                       goto error;
+                       goto err_kill_in_urbs;
        }
 
        return 0;
+
+err_kill_in_urbs:
+       for (--i; i >= 0; --i)
+               usb_kill_urb(es1->cport_in_urb[i]);
 error:
-       ap_disconnect(interface);
+       es1_destroy(es1);
 
        return retval;
 }