diff options
| author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2012-10-22 16:15:05 -0400 |
|---|---|---|
| committer | Felipe Balbi <balbi@ti.com> | 2012-10-31 09:07:00 -0400 |
| commit | 0f9df939385527049c8062a099fbfa1479fe7ce0 (patch) | |
| tree | 355113ab013a0ab8b3719c3b45eb59f5ef027e09 | |
| parent | d0eca719dd11ad0619e8dd6a1f3eceb95b0216dd (diff) | |
usb: gadget: uvc: fix error path in uvc_function_bind()
The "video->minor = -1" assigment is done in V4L2 by
video_register_device() so it is removed here.
Now. uvc_function_bind() calls in error case uvc_function_unbind() for
cleanup. The problem is that uvc_function_unbind() frees the uvc struct
and uvc_bind_config() does as well in error case of usb_add_function().
Removing kfree() in usb_add_function() would make the patch smaller but
it would look odd because the new allocated memory is not cleaned up.
However it is not guaranteed that if we call usb_add_function() we also
get to the bind function.
Therefore the patch extracts the conditional cleanup from
uvc_function_unbind() applies to uvc_function_bind().
uvc_function_unbind() now contains only the complete cleanup which is
required once everything has been registrated.
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Bhupesh Sharma <bhupesh.sharma@st.com>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
| -rw-r--r-- | drivers/usb/gadget/f_uvc.c | 39 |
1 files changed, 21 insertions, 18 deletions
diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 2a8bf0655c60..10f13c1213c7 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c | |||
| @@ -417,7 +417,6 @@ uvc_register_video(struct uvc_device *uvc) | |||
| 417 | return -ENOMEM; | 417 | return -ENOMEM; |
| 418 | 418 | ||
| 419 | video->parent = &cdev->gadget->dev; | 419 | video->parent = &cdev->gadget->dev; |
| 420 | video->minor = -1; | ||
| 421 | video->fops = &uvc_v4l2_fops; | 420 | video->fops = &uvc_v4l2_fops; |
| 422 | video->release = video_device_release; | 421 | video->release = video_device_release; |
| 423 | strncpy(video->name, cdev->gadget->name, sizeof(video->name)); | 422 | strncpy(video->name, cdev->gadget->name, sizeof(video->name)); |
| @@ -577,23 +576,12 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f) | |||
| 577 | 576 | ||
| 578 | INFO(cdev, "uvc_function_unbind\n"); | 577 | INFO(cdev, "uvc_function_unbind\n"); |
| 579 | 578 | ||
| 580 | if (uvc->vdev) { | 579 | video_unregister_device(uvc->vdev); |
| 581 | if (uvc->vdev->minor == -1) | 580 | uvc->control_ep->driver_data = NULL; |
| 582 | video_device_release(uvc->vdev); | 581 | uvc->video.ep->driver_data = NULL; |
| 583 | else | ||
| 584 | video_unregister_device(uvc->vdev); | ||
| 585 | uvc->vdev = NULL; | ||
| 586 | } | ||
| 587 | |||
| 588 | if (uvc->control_ep) | ||
| 589 | uvc->control_ep->driver_data = NULL; | ||
| 590 | if (uvc->video.ep) | ||
| 591 | uvc->video.ep->driver_data = NULL; | ||
| 592 | 582 | ||
| 593 | if (uvc->control_req) { | 583 | usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); |
| 594 | usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); | 584 | kfree(uvc->control_buf); |
| 595 | kfree(uvc->control_buf); | ||
| 596 | } | ||
| 597 | 585 | ||
| 598 | kfree(f->descriptors); | 586 | kfree(f->descriptors); |
| 599 | kfree(f->hs_descriptors); | 587 | kfree(f->hs_descriptors); |
| @@ -740,7 +728,22 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) | |||
| 740 | return 0; | 728 | return 0; |
| 741 | 729 | ||
| 742 | error: | 730 | error: |
| 743 | uvc_function_unbind(c, f); | 731 | if (uvc->vdev) |
| 732 | video_device_release(uvc->vdev); | ||
| 733 | |||
| 734 | if (uvc->control_ep) | ||
| 735 | uvc->control_ep->driver_data = NULL; | ||
| 736 | if (uvc->video.ep) | ||
| 737 | uvc->video.ep->driver_data = NULL; | ||
| 738 | |||
| 739 | if (uvc->control_req) { | ||
| 740 | usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); | ||
| 741 | kfree(uvc->control_buf); | ||
| 742 | } | ||
| 743 | |||
| 744 | kfree(f->descriptors); | ||
| 745 | kfree(f->hs_descriptors); | ||
| 746 | kfree(f->ss_descriptors); | ||
| 744 | return ret; | 747 | return ret; |
| 745 | } | 748 | } |
| 746 | 749 | ||
