[RFC 15/19] usb/gadget: f_mass_storage: convert to new function interface with backward compatibility

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx>

Converting mass storage to the new function interface requires converting
the USB mass storage's function code and its users.
This patch converts the f_mass_storage.c to the new function interface.
The file is now compiled into a separate usb_f_mass_storage.ko module.
The old function interface is provided by means of a preprocessor conditional
directives. After all users are converted, the old interface can be removed.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx>
Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx>
---
 drivers/usb/gadget/Kconfig          |    3 +
 drivers/usb/gadget/Makefile         |    2 +
 drivers/usb/gadget/acm_ms.c         |    1 +
 drivers/usb/gadget/f_mass_storage.c |  217 +++++++++++++++++++++++++++++++----
 drivers/usb/gadget/f_mass_storage.h |    7 ++
 drivers/usb/gadget/mass_storage.c   |    1 +
 drivers/usb/gadget/multi.c          |    1 +
 7 files changed, 212 insertions(+), 20 deletions(-)

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 71d284f..ffc1791 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -542,6 +542,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 b9c779a..dccab69 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -63,6 +63,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 992ffb0..31aae8f 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 6f578f4..22a68f7 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>
@@ -2589,11 +2590,17 @@ void fsg_common_get(struct fsg_common *common)
 {
 	kref_get(&common->ref);
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_common_get);
+#endif
 
 void fsg_common_put(struct fsg_common *common)
 {
 	kref_put(&common->ref, fsg_common_release);
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_common_put);
+#endif
 
 /* check if fsg_num_buffers is within a valid range */
 static inline int fsg_num_buffers_validate(unsigned int fsg_num_buffers)
@@ -2631,6 +2638,9 @@ void fsg_common_set_sysfs(struct fsg_common *common, bool sysfs)
 {
 	common->sysfs = sysfs;
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_common_set_sysfs);
+#endif
 
 int fsg_common_set_num_buffers(struct fsg_common *common, unsigned int n)
 {
@@ -2677,6 +2687,9 @@ error_release:
 
 	return -ENOMEM;
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_common_set_num_buffers);
+#endif
 
 void fsg_common_free_buffers(struct fsg_common *common)
 {
@@ -2693,6 +2706,9 @@ void fsg_common_free_buffers(struct fsg_common *common)
 	kfree(common->buffhds);
 	common->buffhds = NULL;
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_common_free_buffers);
+#endif
 
 int fsg_common_set_nluns(struct fsg_common *common, int nluns)
 {
@@ -2715,22 +2731,34 @@ int fsg_common_set_nluns(struct fsg_common *common, int nluns)
 
 	return 0;
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_common_set_nluns);
+#endif
 
 void fsg_common_free_luns(struct fsg_common *common)
 {
 	kfree(common->luns);
 	common->luns = NULL;
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_common_free_luns);
+#endif
 
 void fsg_common_set_ops(struct fsg_common *common, const struct fsg_operations *ops)
 {
 	common->ops = ops;
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_common_set_ops);
+#endif
 
 void fsg_common_set_private_data(struct fsg_common *common, void *priv)
 {
 	common->private_data = priv;
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_common_set_private_data);
+#endif
 
 int fsg_common_set_cdev(struct fsg_common *common,
 			 struct usb_composite_dev *cdev, bool can_stall)
@@ -2760,6 +2788,9 @@ int fsg_common_set_cdev(struct fsg_common *common,
 
 	return 0;
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_common_set_cdev);
+#endif
 
 static inline int fsg_common_add_sysfs(struct fsg_common *common,
 				       struct fsg_lun *lun)
@@ -2822,6 +2853,9 @@ void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs)
 	fsg_lun_close(lun);
 	kfree(lun);
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_common_remove_lun);
+#endif
 
 void fsg_common_remove_luns(struct fsg_common *common)
 {
@@ -2830,6 +2864,9 @@ void fsg_common_remove_luns(struct fsg_common *common)
 	for (i = 0; i < common->nluns; ++i)
 		fsg_common_remove_lun(common->luns[i], common->sysfs);
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_common_remove_luns);
+#endif
 
 int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
 			  unsigned int id)
@@ -2918,6 +2955,9 @@ error_sysfs:
 	kfree(lun);
 	return rc;
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_common_create_lun);
+#endif
 
 int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg)
 {
@@ -2938,6 +2978,9 @@ fail:
 		fsg_common_remove_lun(common->luns[i], true);
 	return rc;
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_common_create_luns);
+#endif
 
 void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn,
 				   const char *pn)
@@ -2954,6 +2997,9 @@ void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn,
 		     : "File-Stor Gadget"),
 		 i);
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_common_set_inquiry_string);
+#endif
 
 int fsg_common_run_thread(struct fsg_common *common)
 {
@@ -2972,6 +3018,9 @@ int fsg_common_run_thread(struct fsg_common *common)
 
 	return 0;
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_common_run_thread);
+#endif
 
 struct fsg_common *fsg_common_init(struct fsg_common *common,
 				   struct usb_composite_dev *cdev,
@@ -3025,6 +3074,9 @@ error_release:
 	fsg_common_release(&common->ref);
 	return ERR_PTR(rc);
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_common_init);
+#endif
 
 static inline void fsg_common_remove_sysfs(struct fsg_lun *lun)
 {
@@ -3080,24 +3132,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);
@@ -3107,6 +3141,20 @@ 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 = container_of(f->fi, struct fsg_opts, func_inst);
+	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 */
@@ -3158,7 +3206,27 @@ autoconf_fail:
 	return -ENOTSUPP;
 }
 
-/****************************** ADD FUNCTION ******************************/
+/****************************** ALLOCATE FUNCTION *************************/
+
+#ifdef USB_FMS_INCLUDED
+
+static void old_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_config(struct usb_composite_dev *cdev,
 			   struct usb_configuration *c,
@@ -3173,7 +3241,7 @@ static int fsg_bind_config(struct usb_composite_dev *cdev,
 
 	fsg->function.name        = FSG_DRIVER_DESC;
 	fsg->function.bind        = fsg_bind;
-	fsg->function.unbind      = fsg_unbind;
+	fsg->function.unbind      = old_fsg_unbind;
 	fsg->function.setup       = fsg_setup;
 	fsg->function.set_alt     = fsg_set_alt;
 	fsg->function.disable     = fsg_disable;
@@ -3195,6 +3263,112 @@ 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 = container_of(fi, struct fsg_opts, func_inst);
+	fsg_common_put(opts->common);
+	kfree(opts);
+}
+
+static struct usb_function_instance *fsg_alloc_inst(void)
+{
+	struct fsg_opts *opts;
+	int ret;
+
+	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)) {
+		ret = PTR_ERR(opts->common);
+		goto release_opts;
+	}
+	ret = fsg_common_set_nluns(opts->common, FSG_MAX_LUNS);
+	if (ret)
+		goto release_opts;
+
+	ret = fsg_common_set_num_buffers(opts->common,
+					 CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS);
+	if (ret)
+		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(ret);
+}
+
+static void fsg_free(struct usb_function *f)
+{
+	struct fsg_dev *fsg;
+
+	fsg = container_of(f, struct fsg_dev, function);
+
+	kfree(fsg);
+}
+
+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);
+	}
+
+	usb_free_all_descriptors(&fsg->function);
+}
+
+static struct usb_function *fsg_alloc(struct usb_function_instance *fi)
+{
+	struct fsg_opts *opts = container_of(fi, struct fsg_opts, func_inst);
+	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;
+	/*
+	 * Our caller holds a reference to common structure so we
+	 * don't have to be worry about it being freed until we return
+	 * from this function.  So instead of incrementing counter now
+	 * and decrement in error recovery we increment it only when
+	 * call to usb_add_function() was successful.
+	 */
+
+	return &fsg->function;
+}
+
+DECLARE_USB_FUNCTION_INIT(mass_storage, fsg_alloc_inst, fsg_alloc);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michal Nazarewicz");
+
+#endif
 
 /************************* Module parameters *************************/
 
@@ -3231,4 +3405,7 @@ void fsg_config_from_params(struct fsg_config *cfg,
 	cfg->can_stall = params->stall;
 	cfg->fsg_num_buffers = fsg_num_buffers;
 }
+#ifndef USB_FMS_INCLUDED
+EXPORT_SYMBOL(fsg_config_from_params);
+#endif
 
diff --git a/drivers/usb/gadget/f_mass_storage.h b/drivers/usb/gadget/f_mass_storage.h
index 46e6863..4925281 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;
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c
index bf60a9a..6b79814 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 ec59b2b..be8dac3 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
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux