summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/gadget/Kconfig3
-rw-r--r--drivers/usb/gadget/Makefile2
-rw-r--r--drivers/usb/gadget/acm_ms.c1
-rw-r--r--drivers/usb/gadget/f_mass_storage.c178
-rw-r--r--drivers/usb/gadget/f_mass_storage.h15
-rw-r--r--drivers/usb/gadget/mass_storage.c1
-rw-r--r--drivers/usb/gadget/multi.c1
7 files changed, 179 insertions, 22 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 98220dcca315..40adaf08d3a5 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -528,6 +528,9 @@ config USB_F_RNDIS
config USB_U_MS
tristate
+config USB_F_MASS_STORAGE
+ tristate
+
choice
tristate "USB Gadget Drivers"
default USB_ETH
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index d90a0b079182..4a86b0c06676 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -62,6 +62,8 @@ usb_f_rndis-y := f_rndis.o
obj-$(CONFIG_USB_F_RNDIS) += usb_f_rndis.o
u_ms-y := storage_common.o
obj-$(CONFIG_USB_U_MS) += u_ms.o
+usb_f_mass_storage-y := f_mass_storage.o
+obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
#
# USB gadget drivers
diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c
index 992ffb00272f..31aae8fce426 100644
--- a/drivers/usb/gadget/acm_ms.c
+++ b/drivers/usb/gadget/acm_ms.c
@@ -40,6 +40,7 @@
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
+#define USB_FMS_INCLUDED
#include "f_mass_storage.c"
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 5b99aa1846c3..a063cd5e5533 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -213,6 +213,7 @@
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/freezer.h>
+#include <linux/module.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
@@ -226,6 +227,13 @@
#define FSG_DRIVER_DESC "Mass Storage Function"
#define FSG_DRIVER_VERSION "2009/09/11"
+/* to avoid a lot of #ifndef-#endif in the temporary compatibility layer */
+#ifndef USB_FMS_INCLUDED
+#define EXPORT_SYMBOL_GPL_IF_MODULE(m) EXPORT_SYMBOL_GPL(m);
+#else
+#define EXPORT_SYMBOL_GPL_IF_MODULE(m)
+#endif
+
static const char fsg_string_interface[] = "Mass Storage";
#include "storage_common.h"
@@ -2627,11 +2635,13 @@ void fsg_common_get(struct fsg_common *common)
{
kref_get(&common->ref);
}
+EXPORT_SYMBOL_GPL_IF_MODULE(fsg_common_get);
void fsg_common_put(struct fsg_common *common)
{
kref_put(&common->ref, fsg_common_release);
}
+EXPORT_SYMBOL_GPL_IF_MODULE(fsg_common_put);
/* check if fsg_num_buffers is within a valid range */
static inline int fsg_num_buffers_validate(unsigned int fsg_num_buffers)
@@ -2643,7 +2653,7 @@ static inline int fsg_num_buffers_validate(unsigned int fsg_num_buffers)
return -EINVAL;
}
-static struct fsg_common *fsg_common_setup(struct fsg_common *common)
+static struct fsg_common *fsg_common_setup(struct fsg_common *common, bool zero)
{
if (!common) {
common = kzalloc(sizeof(*common), GFP_KERNEL);
@@ -2651,7 +2661,8 @@ static struct fsg_common *fsg_common_setup(struct fsg_common *common)
return ERR_PTR(-ENOMEM);
common->free_storage_on_release = 1;
} else {
- memset(common, 0, sizeof(*common));
+ if (zero)
+ memset(common, 0, sizeof(*common));
common->free_storage_on_release = 0;
}
init_rwsem(&common->filesem);
@@ -2668,6 +2679,7 @@ void fsg_common_set_sysfs(struct fsg_common *common, bool sysfs)
{
common->sysfs = sysfs;
}
+EXPORT_SYMBOL_GPL_IF_MODULE(fsg_common_set_sysfs);
static void _fsg_common_free_buffers(struct fsg_buffhd *buffhds, unsigned n)
{
@@ -2723,6 +2735,7 @@ error_release:
return -ENOMEM;
}
+EXPORT_SYMBOL_GPL_IF_MODULE(fsg_common_set_num_buffers);
static inline void fsg_common_remove_sysfs(struct fsg_lun *lun)
{
@@ -2761,6 +2774,7 @@ void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs)
fsg_lun_close(lun);
kfree(lun);
}
+EXPORT_SYMBOL_GPL_IF_MODULE(fsg_common_remove_lun);
static void _fsg_common_remove_luns(struct fsg_common *common, int n)
{
@@ -2772,6 +2786,7 @@ static void _fsg_common_remove_luns(struct fsg_common *common, int n)
common->luns[i] = NULL;
}
}
+EXPORT_SYMBOL_GPL_IF_MODULE(fsg_common_remove_luns);
void fsg_common_remove_luns(struct fsg_common *common)
{
@@ -2784,6 +2799,7 @@ void fsg_common_free_luns(struct fsg_common *common)
kfree(common->luns);
common->luns = NULL;
}
+EXPORT_SYMBOL_GPL_IF_MODULE(fsg_common_free_luns);
int fsg_common_set_nluns(struct fsg_common *common, int nluns)
{
@@ -2809,6 +2825,14 @@ int fsg_common_set_nluns(struct fsg_common *common, int nluns)
return 0;
}
+EXPORT_SYMBOL_GPL_IF_MODULE(fsg_common_set_nluns);
+
+void fsg_common_free_buffers(struct fsg_common *common)
+{
+ _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers);
+ common->buffhds = NULL;
+}
+EXPORT_SYMBOL_GPL_IF_MODULE(fsg_common_free_buffers);
int fsg_common_set_cdev(struct fsg_common *common,
struct usb_composite_dev *cdev, bool can_stall)
@@ -2836,6 +2860,7 @@ int fsg_common_set_cdev(struct fsg_common *common,
return 0;
}
+EXPORT_SYMBOL_GPL_IF_MODULE(fsg_common_set_cdev);
static inline int fsg_common_add_sysfs(struct fsg_common *common,
struct fsg_lun *lun)
@@ -2958,6 +2983,7 @@ error_sysfs:
kfree(lun);
return rc;
}
+EXPORT_SYMBOL_GPL_IF_MODULE(fsg_common_create_lun);
int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg)
{
@@ -2979,6 +3005,7 @@ fail:
_fsg_common_remove_luns(common, i);
return rc;
}
+EXPORT_SYMBOL_GPL_IF_MODULE(fsg_common_create_luns);
void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn,
const char *pn)
@@ -2995,6 +3022,7 @@ void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn,
: "File-Stor Gadget"),
i);
}
+EXPORT_SYMBOL_GPL_IF_MODULE(fsg_common_set_inquiry_string);
int fsg_common_run_thread(struct fsg_common *common)
{
@@ -3013,6 +3041,7 @@ int fsg_common_run_thread(struct fsg_common *common)
return 0;
}
+EXPORT_SYMBOL_GPL_IF_MODULE(fsg_common_run_thread);
struct fsg_common *fsg_common_init(struct fsg_common *common,
struct usb_composite_dev *cdev,
@@ -3020,7 +3049,7 @@ struct fsg_common *fsg_common_init(struct fsg_common *common,
{
int rc;
- common = fsg_common_setup(common);
+ common = fsg_common_setup(common, !!common);
if (IS_ERR(common))
return common;
fsg_common_set_sysfs(common, true);
@@ -3066,6 +3095,7 @@ error_release:
fsg_common_release(&common->ref);
return ERR_PTR(rc);
}
+EXPORT_SYMBOL_GPL_IF_MODULE(fsg_common_init);
static void fsg_common_release(struct kref *ref)
{
@@ -3105,24 +3135,6 @@ static void fsg_common_release(struct kref *ref)
/*-------------------------------------------------------------------------*/
-static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
-{
- struct fsg_dev *fsg = fsg_from_func(f);
- struct fsg_common *common = fsg->common;
-
- DBG(fsg, "unbind\n");
- if (fsg->common->fsg == fsg) {
- fsg->common->new_fsg = NULL;
- raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
- /* FIXME: make interruptible or killable somehow? */
- wait_event(common->fsg_wait, common->fsg != fsg);
- }
-
- fsg_common_put(common);
- usb_free_all_descriptors(&fsg->function);
- kfree(fsg);
-}
-
static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
@@ -3132,6 +3144,21 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
unsigned max_burst;
int ret;
+#ifndef USB_FMS_INCLUDED
+ struct fsg_opts *opts;
+ opts = fsg_opts_from_func_inst(f->fi);
+ if (!opts->no_configfs) {
+ ret = fsg_common_set_cdev(fsg->common, c->cdev,
+ fsg->common->can_stall);
+ if (ret)
+ return ret;
+ fsg_common_set_inquiry_string(fsg->common, 0, 0);
+ ret = fsg_common_run_thread(fsg->common);
+ if (ret)
+ return ret;
+ }
+#endif
+
fsg->gadget = gadget;
/* New interface */
@@ -3183,7 +3210,31 @@ autoconf_fail:
return -ENOTSUPP;
}
-/****************************** ADD FUNCTION ******************************/
+/****************************** ALLOCATE FUNCTION *************************/
+
+static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct fsg_dev *fsg = fsg_from_func(f);
+ struct fsg_common *common = fsg->common;
+
+ DBG(fsg, "unbind\n");
+ if (fsg->common->fsg == fsg) {
+ fsg->common->new_fsg = NULL;
+ raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+ /* FIXME: make interruptible or killable somehow? */
+ wait_event(common->fsg_wait, common->fsg != fsg);
+ }
+
+#ifdef USB_FMS_INCLUDED
+ fsg_common_put(common);
+#endif
+ usb_free_all_descriptors(&fsg->function);
+#ifdef USB_FMS_INCLUDED
+ kfree(fsg);
+#endif
+}
+
+#ifdef USB_FMS_INCLUDED
static int fsg_bind_config(struct usb_composite_dev *cdev,
struct usb_configuration *c,
@@ -3220,6 +3271,88 @@ static int fsg_bind_config(struct usb_composite_dev *cdev,
return rc;
}
+#else
+
+static void fsg_free_inst(struct usb_function_instance *fi)
+{
+ struct fsg_opts *opts;
+
+ opts = fsg_opts_from_func_inst(fi);
+ fsg_common_put(opts->common);
+ kfree(opts);
+}
+
+static struct usb_function_instance *fsg_alloc_inst(void)
+{
+ struct fsg_opts *opts;
+ int rc;
+
+ opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+ if (!opts)
+ return ERR_PTR(-ENOMEM);
+ opts->func_inst.free_func_inst = fsg_free_inst;
+ opts->common = fsg_common_setup(opts->common, false);
+ if (IS_ERR(opts->common)) {
+ rc = PTR_ERR(opts->common);
+ goto release_opts;
+ }
+ rc = fsg_common_set_nluns(opts->common, FSG_MAX_LUNS);
+ if (rc)
+ goto release_opts;
+
+ rc = fsg_common_set_num_buffers(opts->common,
+ CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS);
+ if (rc)
+ goto release_luns;
+
+ pr_info(FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n");
+
+ return &opts->func_inst;
+
+release_luns:
+ kfree(opts->common->luns);
+release_opts:
+ kfree(opts);
+ return ERR_PTR(rc);
+}
+
+static void fsg_free(struct usb_function *f)
+{
+ struct fsg_dev *fsg;
+
+ fsg = container_of(f, struct fsg_dev, function);
+
+ kfree(fsg);
+}
+
+static struct usb_function *fsg_alloc(struct usb_function_instance *fi)
+{
+ struct fsg_opts *opts = fsg_opts_from_func_inst(fi);
+ struct fsg_common *common = opts->common;
+ struct fsg_dev *fsg;
+
+ fsg = kzalloc(sizeof(*fsg), GFP_KERNEL);
+ if (unlikely(!fsg))
+ return ERR_PTR(-ENOMEM);
+
+ fsg->function.name = FSG_DRIVER_DESC;
+ fsg->function.bind = fsg_bind;
+ fsg->function.unbind = fsg_unbind;
+ fsg->function.setup = fsg_setup;
+ fsg->function.set_alt = fsg_set_alt;
+ fsg->function.disable = fsg_disable;
+ fsg->function.free_func = fsg_free;
+
+ fsg->common = common;
+
+ return &fsg->function;
+}
+
+DECLARE_USB_FUNCTION_INIT(mass_storage, fsg_alloc_inst, fsg_alloc);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michal Nazarewicz");
+
+#endif
/************************* Module parameters *************************/
@@ -3256,4 +3389,5 @@ void fsg_config_from_params(struct fsg_config *cfg,
cfg->can_stall = params->stall;
cfg->fsg_num_buffers = fsg_num_buffers;
}
+EXPORT_SYMBOL_GPL_IF_MODULE(fsg_config_from_params);
diff --git a/drivers/usb/gadget/f_mass_storage.h b/drivers/usb/gadget/f_mass_storage.h
index 7d9e0bc1cbf1..42f7db408478 100644
--- a/drivers/usb/gadget/f_mass_storage.h
+++ b/drivers/usb/gadget/f_mass_storage.h
@@ -1,6 +1,7 @@
#ifndef USB_F_MASS_STORAGE_H
#define USB_F_MASS_STORAGE_H
+#include <linux/usb/composite.h>
#include "storage_common.h"
struct fsg_module_parameters {
@@ -70,6 +71,12 @@ struct fsg_operations {
int (*thread_exits)(struct fsg_common *common);
};
+struct fsg_opts {
+ struct fsg_common *common;
+ struct usb_function_instance func_inst;
+ bool no_configfs; /* for legacy gadgets */
+};
+
struct fsg_lun_config {
const char *filename;
char ro;
@@ -94,6 +101,12 @@ struct fsg_config {
unsigned int fsg_num_buffers;
};
+static inline struct fsg_opts *
+fsg_opts_from_func_inst(const struct usb_function_instance *fi)
+{
+ return container_of(fi, struct fsg_opts, func_inst);
+}
+
void fsg_common_get(struct fsg_common *common);
void fsg_common_put(struct fsg_common *common);
@@ -106,6 +119,8 @@ void fsg_common_set_sysfs(struct fsg_common *common, bool sysfs);
int fsg_common_set_num_buffers(struct fsg_common *common, unsigned int n);
+void fsg_common_free_buffers(struct fsg_common *common);
+
int fsg_common_set_cdev(struct fsg_common *common,
struct usb_composite_dev *cdev, bool can_stall);
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c
index 4723d1b04cff..f6702514f5d7 100644
--- a/drivers/usb/gadget/mass_storage.c
+++ b/drivers/usb/gadget/mass_storage.c
@@ -55,6 +55,7 @@
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
+#define USB_FMS_INCLUDED
#include "f_mass_storage.c"
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index 6867d9dbbca4..42a5bed75388 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/multi.c
@@ -41,6 +41,7 @@ MODULE_LICENSE("GPL");
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
+#define USB_FMS_INCLUDED
#include "f_mass_storage.c"
#define USBF_ECM_INCLUDED