aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2005-11-09 16:59:56 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-04 16:48:30 -0500
commit87c4252a35310fdbb2aabb880a39b83f83cadf62 (patch)
treee1e5588651b6652696b9f4e81bb1776b1e4a4778 /drivers
parentc9a50cc9318772e62d56f2a9172bdfda72bdacbe (diff)
[PATCH] USB: file-storage gadget: Add reference count for children
This patch (as601) adds a proper reference count to the file-storage gadget's main data structure, to keep track of references held by child devices (LUNs in this case). Before this, the driver would wait for each child to be released before unbinding. While there's nothing really wrong with that (you can't create a hang by doing "rmmod g_file_storage </sys/.../lun0/ro" since the open file will prevent rmmod from running), the code might as well follow the standard procedures. Besides, this shrinks the size of the structure by a few words... :-) Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-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);