summaryrefslogtreecommitdiff
path: root/patches.tizen/0661-usb-gadget-f_mass_storage-split-fsg_common-initializ.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches.tizen/0661-usb-gadget-f_mass_storage-split-fsg_common-initializ.patch')
-rw-r--r--patches.tizen/0661-usb-gadget-f_mass_storage-split-fsg_common-initializ.patch597
1 files changed, 597 insertions, 0 deletions
diff --git a/patches.tizen/0661-usb-gadget-f_mass_storage-split-fsg_common-initializ.patch b/patches.tizen/0661-usb-gadget-f_mass_storage-split-fsg_common-initializ.patch
new file mode 100644
index 00000000000..2c6cb6ab4aa
--- /dev/null
+++ b/patches.tizen/0661-usb-gadget-f_mass_storage-split-fsg_common-initializ.patch
@@ -0,0 +1,597 @@
+From 4198374d675f23cc00a4ebd61f99ef2c8bb4ad82 Mon Sep 17 00:00:00 2001
+From: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+Date: Mon, 29 Jul 2013 14:50:17 +0200
+Subject: [PATCH 0661/1302] usb/gadget: f_mass_storage: split fsg_common
+ initialization into a number of functions
+
+When configfs is in place, the things related to intialization
+of struct fsg_common will be split over a number of places.
+This patch adds several functions which together cover the former
+intialization routine fsg_common_init.
+
+When configfs is in place, the luns will not be represented in sysfs,
+so there will be no struct device associated with a lun.
+To prepare for this some debug macros need to be adjusted. Two new
+fields are added to struct fsg_lun: name and name_pfx.
+The "name" is for storing a string which is presented to the user
+instead of the dev_name. The "name_pfx", if non-NULL, is prepended
+to the "name" at printing time.
+
+The name_pfx is for a future lun.0, which will be a default group in
+mass_storage.<name>. By design at USB function configfs group's creation
+time its name is not known (but instead set a bit later in
+drivers/usb/gadget/configfs.c:function_make) and it is this name that
+serves the purpose of the said name prefix. So instead of copying
+a yet-unknown string a pointer to it is stored in struct fsg_lun.
+
+Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
+Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
+---
+ drivers/usb/gadget/f_mass_storage.c | 424 ++++++++++++++++++++++++++++++++++--
+ drivers/usb/gadget/f_mass_storage.h | 33 +++
+ drivers/usb/gadget/storage_common.h | 20 +-
+ 3 files changed, 454 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
+index 04ee635..ef4733c 100644
+--- a/drivers/usb/gadget/f_mass_storage.c
++++ b/drivers/usb/gadget/f_mass_storage.c
+@@ -299,6 +299,7 @@ struct fsg_common {
+ unsigned int short_packet_received:1;
+ unsigned int bad_lun_okay:1;
+ unsigned int running:1;
++ unsigned int sysfs:1;
+
+ int thread_wakeup_needed;
+ struct completion thread_notifier;
+@@ -2607,6 +2608,393 @@ 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, bool zero)
++{
++ if (!common) {
++ common = kzalloc(sizeof(*common), GFP_KERNEL);
++ if (!common)
++ return ERR_PTR(-ENOMEM);
++ common->free_storage_on_release = 1;
++ } else {
++ if (zero)
++ memset(common, 0, sizeof(*common));
++ common->free_storage_on_release = 0;
++ }
++ init_rwsem(&common->filesem);
++ spin_lock_init(&common->lock);
++ kref_init(&common->ref);
++ init_completion(&common->thread_notifier);
++ init_waitqueue_head(&common->fsg_wait);
++ common->state = FSG_STATE_TERMINATED;
++
++ return common;
++}
++
++void fsg_common_set_sysfs(struct fsg_common *common, bool sysfs)
++{
++ common->sysfs = sysfs;
++}
++
++static void _fsg_common_free_buffers(struct fsg_buffhd *buffhds, unsigned n)
++{
++ if (buffhds) {
++ struct fsg_buffhd *bh = buffhds;
++ while (n--) {
++ kfree(bh->buf);
++ ++bh;
++ }
++ kfree(buffhds);
++ }
++}
++
++int fsg_common_set_num_buffers(struct fsg_common *common, unsigned int n)
++{
++ struct fsg_buffhd *bh, *new_buffhds;
++ int i, rc;
++
++ rc = fsg_num_buffers_validate(n);
++ if (rc != 0)
++ return rc;
++
++ new_buffhds = kcalloc(n, sizeof *(new_buffhds), GFP_KERNEL);
++ if (!new_buffhds)
++ return -ENOMEM;
++
++ /* Data buffers cyclic list */
++ bh = new_buffhds;
++ i = n;
++ goto buffhds_first_it;
++ do {
++ bh->next = bh + 1;
++ ++bh;
++buffhds_first_it:
++ bh->buf = kmalloc(FSG_BUFLEN, GFP_KERNEL);
++ if (unlikely(!bh->buf))
++ goto error_release;
++ } while (--i);
++ bh->next = new_buffhds;
++
++ _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers);
++ common->fsg_num_buffers = n;
++ common->buffhds = new_buffhds;
++
++ return 0;
++
++error_release:
++ _fsg_common_free_buffers(new_buffhds, n - i);
++
++ return -ENOMEM;
++}
++
++void fsg_common_free_buffers(struct fsg_common *common)
++{
++ _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers);
++ common->buffhds = NULL;
++}
++
++int fsg_common_set_nluns(struct fsg_common *common, int nluns)
++{
++ struct fsg_lun **curlun;
++
++ /* Find out how many LUNs there should be */
++ if (nluns < 1 || nluns > FSG_MAX_LUNS) {
++ pr_err("invalid number of LUNs: %u\n", nluns);
++ return -EINVAL;
++ }
++
++ curlun = kcalloc(nluns, sizeof(*curlun), GFP_KERNEL);
++ if (unlikely(!curlun))
++ return -ENOMEM;
++
++ if (common->luns)
++ fsg_common_free_luns(common);
++
++ common->luns = curlun;
++ common->nluns = nluns;
++
++ pr_info("Number of LUNs=%d\n", common->nluns);
++
++ return 0;
++}
++
++void fsg_common_free_luns(struct fsg_common *common)
++{
++ fsg_common_remove_luns(common);
++ kfree(common->luns);
++ common->luns = NULL;
++}
++
++void fsg_common_set_ops(struct fsg_common *common,
++ const struct fsg_operations *ops)
++{
++ common->ops = ops;
++}
++
++void fsg_common_set_private_data(struct fsg_common *common, void *priv)
++{
++ common->private_data = priv;
++}
++
++int fsg_common_set_cdev(struct fsg_common *common,
++ struct usb_composite_dev *cdev, bool can_stall)
++{
++ struct usb_string *us;
++ int rc;
++
++ common->gadget = cdev->gadget;
++ common->ep0 = cdev->gadget->ep0;
++ common->ep0req = cdev->req;
++ common->cdev = cdev;
++
++ us = usb_gstrings_attach(cdev, fsg_strings_array,
++ ARRAY_SIZE(fsg_strings));
++ if (IS_ERR(us)) {
++ rc = PTR_ERR(us);
++ return rc;
++ }
++ fsg_intf_desc.iInterface = us[FSG_STRING_INTERFACE].id;
++
++ /*
++ * Some peripheral controllers are known not to be able to
++ * halt bulk endpoints correctly. If one of them is present,
++ * disable stalls.
++ */
++ common->can_stall = can_stall && !(gadget_is_at91(common->gadget));
++
++ return 0;
++}
++
++static inline int fsg_common_add_sysfs(struct fsg_common *common,
++ struct fsg_lun *lun)
++{
++ int rc;
++
++ rc = device_register(&lun->dev);
++ if (rc) {
++ put_device(&lun->dev);
++ return rc;
++ }
++
++ rc = device_create_file(&lun->dev,
++ lun->cdrom
++ ? &dev_attr_ro_cdrom
++ : &dev_attr_ro);
++ if (rc)
++ goto error_cdrom;
++ rc = device_create_file(&lun->dev,
++ lun->removable
++ ? &dev_attr_file
++ : &dev_attr_file_nonremovable);
++ if (rc)
++ goto error_removable;
++ rc = device_create_file(&lun->dev, &dev_attr_nofua);
++ if (rc)
++ goto error_nofua;
++
++ return 0;
++
++error_nofua:
++ device_remove_file(&lun->dev,
++ lun->removable
++ ? &dev_attr_file
++ : &dev_attr_file_nonremovable);
++error_removable:
++ device_remove_file(&lun->dev,
++ lun->cdrom
++ ? &dev_attr_ro_cdrom
++ : &dev_attr_ro);
++error_cdrom:
++ device_unregister(&lun->dev);
++ return rc;
++}
++
++static inline void fsg_common_remove_sysfs(struct fsg_lun *lun)
++{
++ device_remove_file(&lun->dev, &dev_attr_nofua);
++ device_remove_file(&lun->dev, lun->cdrom
++ ? &dev_attr_ro_cdrom : &dev_attr_ro);
++ device_remove_file(&lun->dev, lun->removable
++ ? &dev_attr_file : &dev_attr_file_nonremovable);
++}
++
++void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs)
++{
++ if (sysfs) {
++ fsg_common_remove_sysfs(lun);
++ device_unregister(&lun->dev);
++ }
++ fsg_lun_close(lun);
++ kfree(lun->name);
++ kfree(lun);
++}
++
++void _fsg_common_remove_luns(struct fsg_common *common, int n)
++{
++ int i;
++
++ for (i = 0; i < n; ++i)
++ if (common->luns[i]) {
++ fsg_common_remove_lun(common->luns[i], common->sysfs);
++ common->luns[i] = NULL;
++ }
++}
++
++void fsg_common_remove_luns(struct fsg_common *common)
++{
++ _fsg_common_remove_luns(common, common->nluns);
++}
++
++#define MAX_LUN_NAME_LEN 80
++
++int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
++ unsigned int id, const char *name,
++ const char **name_pfx)
++{
++ struct fsg_lun *lun;
++ char *pathbuf;
++ int rc = -ENOMEM;
++ int name_len;
++
++ if (!common->nluns || !common->luns)
++ return -ENODEV;
++
++ if (common->luns[id])
++ return -EBUSY;
++
++ name_len = strlen(name) + 1;
++ if (name_len > MAX_LUN_NAME_LEN)
++ return -ENAMETOOLONG;
++
++ lun = kzalloc(sizeof(*lun), GFP_KERNEL);
++ if (!lun)
++ return -ENOMEM;
++
++ lun->name = kstrndup(name, name_len, GFP_KERNEL);
++ if (!lun->name)
++ goto error_name;
++ lun->name_pfx = name_pfx;
++
++ lun->cdrom = !!cfg->cdrom;
++ lun->ro = cfg->cdrom || cfg->ro;
++ lun->initially_ro = lun->ro;
++ lun->removable = !!cfg->removable;
++
++ common->luns[id] = lun;
++
++ if (common->sysfs) {
++ lun->dev.release = fsg_lun_release;
++ lun->dev.parent = &common->gadget->dev;
++ dev_set_drvdata(&lun->dev, &common->filesem);
++ dev_set_name(&lun->dev, name);
++
++ rc = fsg_common_add_sysfs(common, lun);
++ if (rc) {
++ pr_info("failed to register LUN%d: %d\n", id, rc);
++ goto error_sysfs;
++ }
++ }
++
++ if (cfg->filename) {
++ rc = fsg_lun_open(lun, cfg->filename);
++ if (rc)
++ goto error_lun;
++ } else if (!lun->removable) {
++ pr_err("no file given for LUN%d\n", id);
++ rc = -EINVAL;
++ goto error_lun;
++ }
++
++ pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
++ {
++ char *p = "(no medium)";
++ if (fsg_lun_is_open(lun)) {
++ p = "(error)";
++ if (pathbuf) {
++ p = d_path(&lun->filp->f_path,
++ pathbuf, PATH_MAX);
++ if (IS_ERR(p))
++ p = "(error)";
++ }
++ }
++ pr_info("LUN: %s%s%sfile: %s\n",
++ lun->removable ? "removable " : "",
++ lun->ro ? "read only " : "",
++ lun->cdrom ? "CD-ROM " : "",
++ p);
++ }
++ kfree(pathbuf);
++
++ return 0;
++
++error_lun:
++ if (common->sysfs) {
++ fsg_common_remove_sysfs(lun);
++ device_unregister(&lun->dev);
++ }
++ fsg_lun_close(lun);
++error_sysfs:
++ common->luns[id] = NULL;
++ kfree(lun->name);
++error_name:
++ kfree(lun);
++ return rc;
++}
++
++int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg)
++{
++ char buf[40]; /* enough for 2^128 decimal */
++ int i, rc;
++
++ for (i = 0; i < common->nluns; ++i) {
++ snprintf(buf, sizeof(buf), "lun%d", i);
++ rc = fsg_common_create_lun(common, &cfg->luns[i], i, buf, NULL);
++ if (rc)
++ goto fail;
++ }
++
++ pr_info("Number of LUNs=%d\n", common->nluns);
++
++ return 0;
++
++fail:
++ _fsg_common_remove_luns(common, i);
++ return rc;
++}
++
++void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn,
++ const char *pn)
++{
++ int i;
++
++ /* Prepare inquiryString */
++ i = get_default_bcdDevice();
++ snprintf(common->inquiry_string, sizeof(common->inquiry_string),
++ "%-8s%-16s%04x", vn ?: "Linux",
++ /* Assume product name dependent on the first LUN */
++ pn ?: ((*common->luns)->cdrom
++ ? "File-CD Gadget"
++ : "File-Stor Gadget"),
++ i);
++}
++
++int fsg_common_run_thread(struct fsg_common *common)
++{
++ common->state = FSG_STATE_IDLE;
++ /* Tell the thread to start working */
++ common->thread_task =
++ kthread_create(fsg_main_thread, common, "file-storage");
++ if (IS_ERR(common->thread_task)) {
++ common->state = FSG_STATE_TERMINATED;
++ return PTR_ERR(common->thread_task);
++ }
++
++ DBG(common, "I/O thread pid: %d\n", task_pid_nr(common->thread_task));
++
++ wake_up_process(common->thread_task);
++
++ return 0;
++}
++
+ struct fsg_common *fsg_common_init(struct fsg_common *common,
+ struct usb_composite_dev *cdev,
+ struct fsg_config *cfg)
+@@ -2640,6 +3028,8 @@ struct fsg_common *fsg_common_init(struct fsg_common *common,
+ memset(common, 0, sizeof *common);
+ common->free_storage_on_release = 0;
+ }
++ common->sysfs = true;
++ common->state = FSG_STATE_IDLE;
+
+ common->fsg_num_buffers = cfg->fsg_num_buffers;
+ common->buffhds = kcalloc(common->fsg_num_buffers,
+@@ -2690,6 +3080,12 @@ struct fsg_common *fsg_common_init(struct fsg_common *common,
+ }
+ *curlun_it = curlun;
+
++ curlun->name = kzalloc(MAX_LUN_NAME_LEN, GFP_KERNEL);
++ if (!curlun->name) {
++ rc = -ENOMEM;
++ common->nluns = i;
++ goto error_release;
++ }
+ curlun->cdrom = !!lcfg->cdrom;
+ curlun->ro = lcfg->cdrom || lcfg->ro;
+ curlun->initially_ro = curlun->ro;
+@@ -2699,6 +3095,7 @@ struct fsg_common *fsg_common_init(struct fsg_common *common,
+ /* curlun->dev.driver = &fsg_driver.driver; XXX */
+ dev_set_drvdata(&curlun->dev, &common->filesem);
+ dev_set_name(&curlun->dev, "lun%d", i);
++ strlcpy(curlun->name, dev_name(&curlun->dev), MAX_LUN_NAME_LEN);
+
+ rc = device_register(&curlun->dev);
+ if (rc) {
+@@ -2845,32 +3242,21 @@ static void fsg_common_release(struct kref *ref)
+ struct fsg_lun *lun = *lun_it;
+ if (!lun)
+ continue;
+- device_remove_file(&lun->dev, &dev_attr_nofua);
+- device_remove_file(&lun->dev,
+- lun->cdrom
+- ? &dev_attr_ro_cdrom
+- : &dev_attr_ro);
+- device_remove_file(&lun->dev,
+- lun->removable
+- ? &dev_attr_file
+- : &dev_attr_file_nonremovable);
++ if (common->sysfs)
++ fsg_common_remove_sysfs(lun);
+ fsg_lun_close(lun);
+- device_unregister(&lun->dev);
++ if (common->sysfs)
++ device_unregister(&lun->dev);
++ kfree(lun->name);
+ kfree(lun);
+ }
+
+ kfree(common->luns);
+ }
+
+- {
+- struct fsg_buffhd *bh = common->buffhds;
+- unsigned i = common->fsg_num_buffers;
+- do {
+- kfree(bh->buf);
+- } while (++bh, --i);
+- }
+-
+- kfree(common->buffhds);
++ if (likely(common->buffhds))
++ _fsg_common_free_buffers(common->buffhds,
++ common->fsg_num_buffers);
+ if (common->free_storage_on_release)
+ kfree(common);
+ }
+diff --git a/drivers/usb/gadget/f_mass_storage.h b/drivers/usb/gadget/f_mass_storage.h
+index b64761d..4445e82 100644
+--- a/drivers/usb/gadget/f_mass_storage.h
++++ b/drivers/usb/gadget/f_mass_storage.h
+@@ -102,6 +102,39 @@ struct fsg_common *fsg_common_init(struct fsg_common *common,
+ struct usb_composite_dev *cdev,
+ struct fsg_config *cfg);
+
++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_nluns(struct fsg_common *common, int nluns);
++
++void fsg_common_free_luns(struct fsg_common *common);
++
++void fsg_common_set_ops(struct fsg_common *common,
++ const struct fsg_operations *ops);
++
++void fsg_common_set_private_data(struct fsg_common *common, void *priv);
++
++int fsg_common_set_cdev(struct fsg_common *common,
++ struct usb_composite_dev *cdev, bool can_stall);
++
++void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs);
++
++void fsg_common_remove_luns(struct fsg_common *common);
++
++int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
++ unsigned int id, const char *name,
++ const char **name_pfx);
++
++int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg);
++
++void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn,
++ const char *pn);
++
++int fsg_common_run_thread(struct fsg_common *common);
++
+ void fsg_config_from_params(struct fsg_config *cfg,
+ const struct fsg_module_parameters *params,
+ unsigned int fsg_num_buffers);
+diff --git a/drivers/usb/gadget/storage_common.h b/drivers/usb/gadget/storage_common.h
+index 1fcda2b..9955477 100644
+--- a/drivers/usb/gadget/storage_common.h
++++ b/drivers/usb/gadget/storage_common.h
+@@ -17,10 +17,20 @@
+ #define VLDBG(lun, fmt, args...) do { } while (0)
+ #endif /* VERBOSE_DEBUG */
+
+-#define LDBG(lun, fmt, args...) dev_dbg(&(lun)->dev, fmt, ## args)
+-#define LERROR(lun, fmt, args...) dev_err(&(lun)->dev, fmt, ## args)
+-#define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args)
+-#define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args)
++#define _LMSG(func, lun, fmt, args...) \
++ do { \
++ if ((lun)->name_pfx && *(lun)->name_pfx) \
++ func("%s/%s: " fmt, *(lun)->name_pfx, \
++ (lun)->name, ## args); \
++ else \
++ func("%s: " fmt, (lun)->name, ## args); \
++ } while (0)
++
++#define LDBG(lun, fmt, args...) _LMSG(pr_debug, lun, fmt, ## args)
++#define LERROR(lun, fmt, args...) _LMSG(pr_err, lun, fmt, ## args)
++#define LWARN(lun, fmt, args...) _LMSG(pr_warn, lun, fmt, ## args)
++#define LINFO(lun, fmt, args...) _LMSG(pr_info, lun, fmt, ## args)
++
+
+ #ifdef DUMP_MSGS
+
+@@ -100,6 +110,8 @@ struct fsg_lun {
+ of bound block device */
+ unsigned int blksize; /* logical block size of bound block device */
+ struct device dev;
++ char *name; /* "function.name/lun.name" */
++ const char **name_pfx;
+ };
+
+ static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
+--
+1.8.3.2
+