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 #include #include +#include #include #include @@ -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 #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