summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/gadget/f_mass_storage.c52
-rw-r--r--include/usb/mass_storage.h1
2 files changed, 44 insertions, 9 deletions
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index a49ac78033..1c26c4d996 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -263,8 +263,6 @@ static struct usb_gadget_strings fsg_stringtab = {
struct bthread *thread_task;
-struct kref {int x; };
-
struct fsg_dev;
static struct file_list *ums_files;
@@ -282,6 +280,8 @@ struct fsg_common {
struct fsg_buffhd *next_buffhd_to_drain;
struct fsg_buffhd buffhds[FSG_NUM_BUFFERS];
+ struct f_ums_opts *opts;
+
int cmnd_size;
u8 cmnd[MAX_COMMAND_SIZE];
@@ -322,6 +322,20 @@ struct fsg_common {
char inquiry_string[8 + 16 + 4 + 1];
};
+static struct f_ums_opts *f_ums_opts_get(struct f_ums_opts *opts)
+{
+ opts->refcnt++;
+ return opts;
+}
+
+static void f_ums_opts_put(struct f_ums_opts *opts)
+{
+ if (--opts->refcnt == 0) {
+ kfree(opts->common);
+ kfree(opts);
+ }
+}
+
struct fsg_config {
unsigned nluns;
struct fsg_lun_config {
@@ -348,6 +362,8 @@ struct fsg_dev {
struct usb_gadget *gadget; /* Copy of cdev->gadget */
struct fsg_common *common;
+ int refcnt;
+
u16 interface_number;
unsigned int bulk_in_enabled:1;
@@ -360,6 +376,17 @@ struct fsg_dev {
struct usb_ep *bulk_out;
};
+static struct fsg_dev *fsg_dev_get(struct fsg_dev *fsg)
+{
+ fsg->refcnt++;
+ return fsg;
+}
+
+static void fsg_dev_put(struct fsg_dev *fsg)
+{
+ if (--fsg->refcnt == 0)
+ kfree(fsg);
+}
static inline int __fsg_is_set(struct fsg_common *common,
const char *func, unsigned line)
@@ -2337,12 +2364,14 @@ static void handle_exception(struct fsg_common *common)
static void fsg_main_thread(void *fsg_)
{
- struct fsg_dev *fsg = fsg_;
+ struct fsg_dev *fsg = fsg_dev_get(fsg_);
struct fsg_common *common = fsg->common;
+ struct f_ums_opts *opts = f_ums_opts_get(common->opts);
struct fsg_buffhd *bh;
unsigned i;
int ret = 0;
+
/* The main loop */
while (common->state != FSG_STATE_TERMINATED) {
if (exception_in_progress(common)) {
@@ -2394,11 +2423,14 @@ static void fsg_main_thread(void *fsg_)
ums_count = 0;
ums_files = NULL;
+
+ f_ums_opts_put(opts);
+ fsg_dev_put(fsg);
}
static void fsg_common_release(struct fsg_common *common);
-static struct fsg_common *fsg_common_setup(void)
+static struct fsg_common *fsg_common_setup(struct f_ums_opts *opts)
{
struct fsg_common *common;
@@ -2409,6 +2441,7 @@ static struct fsg_common *fsg_common_setup(void)
common->ops = NULL;
common->private_data = NULL;
+ common->opts = opts;
return common;
}
@@ -2659,7 +2692,7 @@ static void fsg_free(struct usb_function *f)
fsg = container_of(f, struct fsg_dev, function);
- kfree(fsg);
+ fsg_dev_put(fsg);
}
static struct usb_function *fsg_alloc(struct usb_function_instance *fi)
@@ -2683,7 +2716,7 @@ static struct usb_function *fsg_alloc(struct usb_function_instance *fi)
fsg->function.free_func = fsg_free;
fsg->common = common;
- common->fsg = fsg;
+ common->fsg = fsg_dev_get(fsg);
return &fsg->function;
}
@@ -2692,8 +2725,7 @@ static void fsg_free_instance(struct usb_function_instance *fi)
{
struct f_ums_opts *opts = fsg_opts_from_func_inst(fi);
- kfree(opts->common);
- kfree(opts);
+ f_ums_opts_put(opts);
}
static struct usb_function_instance *fsg_alloc_inst(void)
@@ -2706,12 +2738,14 @@ static struct usb_function_instance *fsg_alloc_inst(void)
opts->func_inst.free_func_inst = fsg_free_instance;
- opts->common = fsg_common_setup();
+ opts->common = fsg_common_setup(opts);
if (!opts->common) {
free(opts);
return ERR_PTR(-ENOMEM);
}
+ f_ums_opts_get(opts);
+
return &opts->func_inst;
}
diff --git a/include/usb/mass_storage.h b/include/usb/mass_storage.h
index 084b3c8e8f..7be665ee47 100644
--- a/include/usb/mass_storage.h
+++ b/include/usb/mass_storage.h
@@ -20,6 +20,7 @@ struct f_ums_opts {
struct file_list *files;
unsigned int num_sectors;
int fd;
+ int refcnt;
char name[16];
};