From: Andrzej Pietrasiewicz <andrze...@samsung.com>

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. As a consequence, issuing of
some debug messages needs to be adjusted.

Signed-off-by: Andrzej Pietrasiewicz <andrze...@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.p...@samsung.com>
---
 drivers/usb/gadget/f_mass_storage.c |  400 +++++++++++++++++++++++++++++++++--
 drivers/usb/gadget/f_mass_storage.h |   31 +++
 drivers/usb/gadget/storage_common.c |   24 +--
 3 files changed, 430 insertions(+), 25 deletions(-)

diff --git a/drivers/usb/gadget/f_mass_storage.c 
b/drivers/usb/gadget/f_mass_storage.c
index 8d0b451..fc3b5ff 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;
@@ -2604,6 +2605,374 @@ 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;
+}
+
+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;
+
+       common->fsg_num_buffers = n;
+       kfree(common->buffhds);
+       common->buffhds = new_buffhds;
+
+       return 0;
+
+error_release:
+       bh = new_buffhds;
+       i = n - i;
+       while (i--) {
+               kfree(bh->buf);
+               bh++;
+       };
+
+       kfree(new_buffhds);
+
+       return -ENOMEM;
+}
+
+void fsg_common_free_buffers(struct fsg_common *common)
+{
+       struct fsg_buffhd *bh;
+       int i;
+
+       bh = common->buffhds;
+       i = common->fsg_num_buffers;
+       while (i--) {
+               kfree(bh->buf);
+               bh++;
+       };
+
+       kfree(common->buffhds);
+       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) {
+               ERROR(common, "invalid number of LUNs: %u\n", nluns);
+               return -EINVAL;
+       }
+
+       curlun = kcalloc(nluns, sizeof(*curlun), GFP_KERNEL);
+       if (unlikely(!curlun))
+               return -ENOMEM;
+
+       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)
+{
+       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;
+}
+
+void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs)
+{
+       if (sysfs) {
+               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);
+               device_unregister(&lun->dev);
+       }
+       fsg_lun_close(lun);
+       kfree(lun);
+}
+
+void fsg_common_remove_luns(struct fsg_common *common)
+{
+       int i;
+
+       for (i = 0; i < common->nluns; ++i)
+               fsg_common_remove_lun(common->luns[i], common->sysfs);
+}
+
+int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config 
*cfg,
+                         unsigned int id)
+{
+       struct fsg_lun *lun;
+       char *pathbuf;
+       int rc;
+
+       if (!common->nluns || !common->luns)
+               return -ENODEV;
+
+       if (common->luns[id])
+               return -EBUSY;
+
+       lun = kzalloc(sizeof(*lun), GFP_KERNEL);
+       if (!lun)
+               return -ENOMEM;
+
+       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, "lun%d", id);
+
+               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) {
+               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);
+               device_unregister(&lun->dev);
+       }
+       fsg_lun_close(lun);
+error_sysfs:
+       kfree(lun);
+       return rc;
+}
+
+int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg)
+{
+       int i, rc;
+
+       for (i = 0; i < common->nluns; ++i) {
+               rc = fsg_common_create_lun(common, &cfg->luns[i], i);
+               if (rc)
+                       goto fail;
+       }
+
+       pr_info("Number of LUNs=%d\n", common->nluns);
+
+       return 0;
+
+fail:
+       while (--i >= 0)
+               fsg_common_remove_lun(common->luns[i], true);
+       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)
@@ -2637,6 +3006,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,
@@ -2818,6 +3189,15 @@ error_release:
        return ERR_PTR(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);
+}
+
 static void fsg_common_release(struct kref *ref)
 {
        struct fsg_common *common = container_of(ref, struct fsg_common, ref);
@@ -2836,32 +3216,26 @@ static void fsg_common_release(struct kref *ref)
                for (; i; --i, ++lun) {
                        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);
                }
 
                kfree(common->luns);
        }
 
-       {
+       if (likely(common->buffhds)){
                struct fsg_buffhd *bh = common->buffhds;
                unsigned i = common->fsg_num_buffers;
                do {
                        kfree(bh->buf);
                } while (++bh, --i);
-       }
 
-       kfree(common->buffhds);
+               kfree(common->buffhds);
+       }
        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..46e6863 100644
--- a/drivers/usb/gadget/f_mass_storage.h
+++ b/drivers/usb/gadget/f_mass_storage.h
@@ -102,6 +102,37 @@ 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);
+
+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.c 
b/drivers/usb/gadget/storage_common.c
index 942324c..a70a5d3 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -179,7 +179,7 @@ EXPORT_SYMBOL(fsg_ss_function);
 void fsg_lun_close(struct fsg_lun *curlun)
 {
        if (curlun->filp) {
-               LDBG(curlun, "close backing file\n");
+               pr_debug("close backing file\n");
                fput(curlun->filp);
                curlun->filp = NULL;
        }
@@ -208,7 +208,7 @@ int fsg_lun_open(struct fsg_lun *curlun, const char 
*filename)
        if (ro)
                filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0);
        if (IS_ERR(filp)) {
-               LINFO(curlun, "unable to open backing file: %s\n", filename);
+               pr_info("unable to open backing file: %s\n", filename);
                return PTR_ERR(filp);
        }
 
@@ -217,7 +217,7 @@ int fsg_lun_open(struct fsg_lun *curlun, const char 
*filename)
 
        inode = file_inode(filp);
        if ((!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))) {
-               LINFO(curlun, "invalid file type: %s\n", filename);
+               pr_info("invalid file type: %s\n", filename);
                goto out;
        }
 
@@ -226,7 +226,7 @@ int fsg_lun_open(struct fsg_lun *curlun, const char 
*filename)
         * If we can't write the file, use it read-only.
         */
        if (!(filp->f_op->read || filp->f_op->aio_read)) {
-               LINFO(curlun, "file not readable: %s\n", filename);
+               pr_info("file not readable: %s\n", filename);
                goto out;
        }
        if (!(filp->f_op->write || filp->f_op->aio_write))
@@ -234,7 +234,7 @@ int fsg_lun_open(struct fsg_lun *curlun, const char 
*filename)
 
        size = i_size_read(inode->i_mapping->host);
        if (size < 0) {
-               LINFO(curlun, "unable to find file size: %s\n", filename);
+               pr_info("unable to find file size: %s\n", filename);
                rc = (int) size;
                goto out;
        }
@@ -256,13 +256,13 @@ int fsg_lun_open(struct fsg_lun *curlun, const char 
*filename)
                min_sectors = 300;      /* Smallest track is 300 frames */
                if (num_sectors >= 256*60*75) {
                        num_sectors = 256*60*75 - 1;
-                       LINFO(curlun, "file too big: %s\n", filename);
-                       LINFO(curlun, "using only first %d blocks\n",
+                       pr_info("file too big: %s\n", filename);
+                       pr_info("using only first %d blocks\n",
                                        (int) num_sectors);
                }
        }
        if (num_sectors < min_sectors) {
-               LINFO(curlun, "file too small: %s\n", filename);
+               pr_info("file too small: %s\n", filename);
                rc = -ETOOSMALL;
                goto out;
        }
@@ -276,7 +276,7 @@ int fsg_lun_open(struct fsg_lun *curlun, const char 
*filename)
        curlun->filp = filp;
        curlun->file_length = size;
        curlun->num_sectors = num_sectors;
-       LDBG(curlun, "open backing file: %s\n", filename);
+       pr_debug("open backing file: %s\n", filename);
        return 0;
 
 out:
@@ -391,12 +391,12 @@ ssize_t fsg_store_ro(struct device *dev, struct 
device_attribute *attr,
         */
        down_read(filesem);
        if (fsg_lun_is_open(curlun)) {
-               LDBG(curlun, "read-only status change prevented\n");
+               pr_debug("read-only status change prevented\n");
                rc = -EBUSY;
        } else {
                curlun->ro = ro;
                curlun->initially_ro = ro;
-               LDBG(curlun, "read-only status set to %d\n", curlun->ro);
+               pr_debug("read-only status set to %d\n", curlun->ro);
                rc = count;
        }
        up_read(filesem);
@@ -434,7 +434,7 @@ ssize_t fsg_store_file(struct device *dev, struct 
device_attribute *attr,
        int             rc = 0;
 
        if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) {
-               LDBG(curlun, "eject attempt prevented\n");
+               pr_debug("eject attempt prevented\n");
                return -EBUSY;                          /* "Door is locked" */
        }
 
-- 
1.7.9.5

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

Reply via email to