Commit 1ec1d6dd authored by Alex Elder's avatar Alex Elder Committed by Greg Kroah-Hartman

greybus: leverage ap_disconnect() in ap_probe()

With a few minor changes, ap_disconnect() can correctly handle
cleaning up even a partially initialized USB interface.  Make those
changes, and then use ap_disconnect() to simplify cleanup for all
the error paths in ap_probe().  Reset all fields as they're cleaned
up to facilitate debugging.
Signed-off-by: default avatarAlex Elder <elder@linaro.org>
parent 6892537f
...@@ -277,22 +277,37 @@ static void ap_disconnect(struct usb_interface *interface) ...@@ -277,22 +277,37 @@ static void ap_disconnect(struct usb_interface *interface)
/* Tear down everything! */ /* Tear down everything! */
for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { for (i = 0; i < NUM_CPORT_OUT_URB; ++i) {
usb_kill_urb(es1->cport_out_urb[i]); struct urb *urb = es1->cport_out_urb[i];
usb_free_urb(es1->cport_out_urb[i]);
if (!urb)
break;
usb_kill_urb(urb);
usb_free_urb(urb);
es1->cport_out_urb[i] = NULL;
es1->cport_out_urb_busy[i] = false; /* just to be anal */
} }
for (i = 0; i < NUM_CPORT_IN_URB; ++i) { for (i = 0; i < NUM_CPORT_IN_URB; ++i) {
usb_kill_urb(es1->cport_in_urb[i]); struct urb *urb = es1->cport_in_urb[i];
usb_free_urb(es1->cport_in_urb[i]);
if (!urb)
break;
usb_kill_urb(urb);
usb_free_urb(urb);
kfree(es1->cport_in_buffer[i]); kfree(es1->cport_in_buffer[i]);
es1->cport_in_buffer[i] = NULL;
} }
usb_kill_urb(es1->svc_urb); usb_kill_urb(es1->svc_urb);
usb_free_urb(es1->svc_urb); usb_free_urb(es1->svc_urb);
usb_put_dev(es1->usb_dev); es1->svc_urb = NULL;
kfree(es1->svc_buffer); kfree(es1->svc_buffer);
greybus_remove_hd(es1->hd); es1->svc_buffer = NULL;
usb_set_intfdata(interface, NULL); usb_set_intfdata(interface, NULL);
greybus_remove_hd(es1->hd);
usb_put_dev(es1->usb_dev);
} }
/* Callback for when we get a SVC message */ /* Callback for when we get a SVC message */
...@@ -466,7 +481,7 @@ static int ap_probe(struct usb_interface *interface, ...@@ -466,7 +481,7 @@ static int ap_probe(struct usb_interface *interface,
es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL); es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!es1->svc_urb) if (!es1->svc_urb)
goto error_int_urb; goto error;
usb_fill_int_urb(es1->svc_urb, udev, usb_fill_int_urb(es1->svc_urb, udev,
usb_rcvintpipe(udev, es1->svc_endpoint), usb_rcvintpipe(udev, es1->svc_endpoint),
...@@ -474,7 +489,7 @@ static int ap_probe(struct usb_interface *interface, ...@@ -474,7 +489,7 @@ static int ap_probe(struct usb_interface *interface,
es1, svc_interval); es1, svc_interval);
retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL);
if (retval) if (retval)
goto error_submit_urb; goto error;
/* Allocate buffers for our cport in messages and start them up */ /* Allocate buffers for our cport in messages and start them up */
for (i = 0; i < NUM_CPORT_IN_URB; ++i) { for (i = 0; i < NUM_CPORT_IN_URB; ++i) {
...@@ -483,10 +498,10 @@ static int ap_probe(struct usb_interface *interface, ...@@ -483,10 +498,10 @@ static int ap_probe(struct usb_interface *interface,
urb = usb_alloc_urb(0, GFP_KERNEL); urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) if (!urb)
goto error_bulk_in_urb; goto error;
buffer = kmalloc(ES1_GBUF_MSG_SIZE, GFP_KERNEL); buffer = kmalloc(ES1_GBUF_MSG_SIZE, GFP_KERNEL);
if (!buffer) if (!buffer)
goto error_bulk_in_urb; goto error;
usb_fill_bulk_urb(urb, udev, usb_fill_bulk_urb(urb, udev,
usb_rcvbulkpipe(udev, es1->cport_in_endpoint), usb_rcvbulkpipe(udev, es1->cport_in_endpoint),
...@@ -495,7 +510,7 @@ static int ap_probe(struct usb_interface *interface, ...@@ -495,7 +510,7 @@ static int ap_probe(struct usb_interface *interface,
es1->cport_in_buffer[i] = buffer; es1->cport_in_buffer[i] = buffer;
retval = usb_submit_urb(urb, GFP_KERNEL); retval = usb_submit_urb(urb, GFP_KERNEL);
if (retval) if (retval)
goto error_bulk_in_urb; goto error;
} }
/* Allocate urbs for our CPort OUT messages */ /* Allocate urbs for our CPort OUT messages */
...@@ -504,31 +519,16 @@ static int ap_probe(struct usb_interface *interface, ...@@ -504,31 +519,16 @@ static int ap_probe(struct usb_interface *interface,
urb = usb_alloc_urb(0, GFP_KERNEL); urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) if (!urb)
goto error_bulk_out_urb; goto error;
es1->cport_out_urb[i] = urb; es1->cport_out_urb[i] = urb;
es1->cport_out_urb_busy[i] = false; /* just to be anal */ es1->cport_out_urb_busy[i] = false; /* just to be anal */
} }
return 0; return 0;
error_bulk_out_urb:
for (i = 0; i < NUM_CPORT_OUT_URB; ++i)
usb_free_urb(es1->cport_out_urb[i]);
error_bulk_in_urb:
for (i = 0; i < NUM_CPORT_IN_URB; ++i) {
usb_kill_urb(es1->cport_in_urb[i]);
usb_free_urb(es1->cport_in_urb[i]);
kfree(es1->cport_in_buffer[i]);
}
error_submit_urb:
usb_free_urb(es1->svc_urb);
error_int_urb:
kfree(es1->svc_buffer);
error: error:
greybus_remove_hd(es1->hd); ap_disconnect(interface);
return retval; return retval;
} }
......
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