aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/gadget/file_storage.c30
1 files changed, 17 insertions, 13 deletions
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index ea09aaa3cab6..f6f0b2aa1145 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -224,6 +224,7 @@
224#include <linux/fs.h> 224#include <linux/fs.h>
225#include <linux/init.h> 225#include <linux/init.h>
226#include <linux/kernel.h> 226#include <linux/kernel.h>
227#include <linux/kref.h>
227#include <linux/kthread.h> 228#include <linux/kthread.h>
228#include <linux/limits.h> 229#include <linux/limits.h>
229#include <linux/list.h> 230#include <linux/list.h>
@@ -631,6 +632,9 @@ struct fsg_dev {
631 /* filesem protects: backing files in use */ 632 /* filesem protects: backing files in use */
632 struct rw_semaphore filesem; 633 struct rw_semaphore filesem;
633 634
635 /* reference counting: wait until all LUNs are released */
636 struct kref ref;
637
634 struct usb_ep *ep0; // Handy copy of gadget->ep0 638 struct usb_ep *ep0; // Handy copy of gadget->ep0
635 struct usb_request *ep0req; // For control responses 639 struct usb_request *ep0req; // For control responses
636 volatile unsigned int ep0_req_tag; 640 volatile unsigned int ep0_req_tag;
@@ -694,7 +698,6 @@ struct fsg_dev {
694 unsigned int nluns; 698 unsigned int nluns;
695 struct lun *luns; 699 struct lun *luns;
696 struct lun *curlun; 700 struct lun *curlun;
697 struct completion lun_released;
698}; 701};
699 702
700typedef void (*fsg_routine_t)(struct fsg_dev *); 703typedef void (*fsg_routine_t)(struct fsg_dev *);
@@ -3642,11 +3645,19 @@ static DEVICE_ATTR(file, 0444, show_file, NULL);
3642 3645
3643/*-------------------------------------------------------------------------*/ 3646/*-------------------------------------------------------------------------*/
3644 3647
3648static void fsg_release(struct kref *ref)
3649{
3650 struct fsg_dev *fsg = container_of(ref, struct fsg_dev, ref);
3651
3652 kfree(fsg->luns);
3653 kfree(fsg);
3654}
3655
3645static void lun_release(struct device *dev) 3656static void lun_release(struct device *dev)
3646{ 3657{
3647 struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev); 3658 struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev);
3648 3659
3649 complete(&fsg->lun_released); 3660 kref_put(&fsg->ref, fsg_release);
3650} 3661}
3651 3662
3652static void fsg_unbind(struct usb_gadget *gadget) 3663static void fsg_unbind(struct usb_gadget *gadget)
@@ -3660,14 +3671,12 @@ static void fsg_unbind(struct usb_gadget *gadget)
3660 clear_bit(REGISTERED, &fsg->atomic_bitflags); 3671 clear_bit(REGISTERED, &fsg->atomic_bitflags);
3661 3672
3662 /* Unregister the sysfs attribute files and the LUNs */ 3673 /* Unregister the sysfs attribute files and the LUNs */
3663 init_completion(&fsg->lun_released);
3664 for (i = 0; i < fsg->nluns; ++i) { 3674 for (i = 0; i < fsg->nluns; ++i) {
3665 curlun = &fsg->luns[i]; 3675 curlun = &fsg->luns[i];
3666 if (curlun->registered) { 3676 if (curlun->registered) {
3667 device_remove_file(&curlun->dev, &dev_attr_ro); 3677 device_remove_file(&curlun->dev, &dev_attr_ro);
3668 device_remove_file(&curlun->dev, &dev_attr_file); 3678 device_remove_file(&curlun->dev, &dev_attr_file);
3669 device_unregister(&curlun->dev); 3679 device_unregister(&curlun->dev);
3670 wait_for_completion(&fsg->lun_released);
3671 curlun->registered = 0; 3680 curlun->registered = 0;
3672 } 3681 }
3673 } 3682 }
@@ -3846,6 +3855,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
3846 curlun->dev.release = lun_release; 3855 curlun->dev.release = lun_release;
3847 device_create_file(&curlun->dev, &dev_attr_ro); 3856 device_create_file(&curlun->dev, &dev_attr_ro);
3848 device_create_file(&curlun->dev, &dev_attr_file); 3857 device_create_file(&curlun->dev, &dev_attr_file);
3858 kref_get(&fsg->ref);
3849 } 3859 }
3850 3860
3851 if (file[i] && *file[i]) { 3861 if (file[i] && *file[i]) {
@@ -4061,6 +4071,7 @@ static int __init fsg_alloc(void)
4061 return -ENOMEM; 4071 return -ENOMEM;
4062 spin_lock_init(&fsg->lock); 4072 spin_lock_init(&fsg->lock);
4063 init_rwsem(&fsg->filesem); 4073 init_rwsem(&fsg->filesem);
4074 kref_init(&fsg->ref);
4064 init_waitqueue_head(&fsg->thread_wqh); 4075 init_waitqueue_head(&fsg->thread_wqh);
4065 init_completion(&fsg->thread_notifier); 4076 init_completion(&fsg->thread_notifier);
4066 4077
@@ -4069,13 +4080,6 @@ static int __init fsg_alloc(void)
4069} 4080}
4070 4081
4071 4082
4072static void fsg_free(struct fsg_dev *fsg)
4073{
4074 kfree(fsg->luns);
4075 kfree(fsg);
4076}
4077
4078
4079static int __init fsg_init(void) 4083static int __init fsg_init(void)
4080{ 4084{
4081 int rc; 4085 int rc;
@@ -4085,7 +4089,7 @@ static int __init fsg_init(void)
4085 return rc; 4089 return rc;
4086 fsg = the_fsg; 4090 fsg = the_fsg;
4087 if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0) 4091 if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0)
4088 fsg_free(fsg); 4092 kref_put(&fsg->ref, fsg_release);
4089 return rc; 4093 return rc;
4090} 4094}
4091module_init(fsg_init); 4095module_init(fsg_init);
@@ -4103,6 +4107,6 @@ static void __exit fsg_cleanup(void)
4103 wait_for_completion(&fsg->thread_notifier); 4107 wait_for_completion(&fsg->thread_notifier);
4104 4108
4105 close_all_backing_files(fsg); 4109 close_all_backing_files(fsg);
4106 fsg_free(fsg); 4110 kref_put(&fsg->ref, fsg_release);
4107} 4111}
4108module_exit(fsg_cleanup); 4112module_exit(fsg_cleanup);