usb: gadget: f_mass_storage: create lun creation helpers for use in fsg_common_init

fsg_common_init is a lengthy function. Factor portions of it out.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Michal Nazarewicz <mina86@mina86.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
Andrzej Pietrasiewicz 2013-10-09 10:05:58 +02:00 committed by Felipe Balbi
parent a891d7a32f
commit b27c08c953
2 changed files with 153 additions and 91 deletions

View File

@ -2837,16 +2837,154 @@ int fsg_common_set_cdev(struct fsg_common *common,
return 0; 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;
rc = device_create_file(&lun->dev,
lun->removable
? &dev_attr_file
: &dev_attr_file_nonremovable);
if (rc)
goto error;
rc = device_create_file(&lun->dev, &dev_attr_nofua);
if (rc)
goto error;
return 0;
error:
/* removing nonexistent files is a no-op */
fsg_common_remove_sysfs(lun);
device_unregister(&lun->dev);
return rc;
}
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, *p;
int rc = -ENOMEM;
if (!common->nluns || !common->luns)
return -ENODEV;
if (common->luns[id])
return -EBUSY;
if (!cfg->filename && !cfg->removable) {
pr_err("no file given for LUN%d\n", id);
return -EINVAL;
}
lun = kzalloc(sizeof(*lun), GFP_KERNEL);
if (!lun)
return -ENOMEM;
lun->name_pfx = name_pfx;
lun->cdrom = !!cfg->cdrom;
lun->ro = cfg->cdrom || cfg->ro;
lun->initially_ro = lun->ro;
lun->removable = !!cfg->removable;
if (!common->sysfs) {
/* we DON'T own the name!*/
lun->name = name;
} else {
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);
lun->name = dev_name(&lun->dev);
rc = fsg_common_add_sysfs(common, lun);
if (rc) {
pr_info("failed to register LUN%d: %d\n", id, rc);
goto error_sysfs;
}
}
common->luns[id] = lun;
if (cfg->filename) {
rc = fsg_lun_open(lun, cfg->filename);
if (rc)
goto error_lun;
}
pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
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);
common->luns[id] = NULL;
error_sysfs:
kfree(lun);
return rc;
}
int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg)
{
char buf[8]; /* enough for 100000000 different numbers, 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;
}
struct fsg_common *fsg_common_init(struct fsg_common *common, struct fsg_common *fsg_common_init(struct fsg_common *common,
struct usb_composite_dev *cdev, struct usb_composite_dev *cdev,
struct fsg_config *cfg) struct fsg_config *cfg)
{ {
struct usb_gadget *gadget = cdev->gadget; int i, rc;
struct fsg_lun **curlun_it;
struct fsg_lun_config *lcfg;
int nluns, i, rc;
char *pathbuf;
common = fsg_common_setup(common); common = fsg_common_setup(common);
if (IS_ERR(common)) if (IS_ERR(common))
@ -2870,66 +3008,10 @@ struct fsg_common *fsg_common_init(struct fsg_common *common,
rc = fsg_common_set_nluns(common, cfg->nluns); rc = fsg_common_set_nluns(common, cfg->nluns);
if (rc) if (rc)
goto error_release; goto error_release;
curlun_it = common->luns;
nluns = cfg->nluns;
for (i = 0, lcfg = cfg->luns; i < nluns; ++i, ++curlun_it, ++lcfg) {
struct fsg_lun *curlun;
curlun = kzalloc(sizeof(*curlun), GFP_KERNEL); rc = fsg_common_create_luns(common, cfg);
if (!curlun) { if (rc)
rc = -ENOMEM;
common->nluns = i;
goto error_release; goto error_release;
}
*curlun_it = curlun;
curlun->cdrom = !!lcfg->cdrom;
curlun->ro = lcfg->cdrom || lcfg->ro;
curlun->initially_ro = curlun->ro;
curlun->removable = lcfg->removable;
curlun->dev.release = fsg_lun_release;
curlun->dev.parent = &gadget->dev;
/* curlun->dev.driver = &fsg_driver.driver; XXX */
dev_set_drvdata(&curlun->dev, &common->filesem);
dev_set_name(&curlun->dev, "lun%d", i);
curlun->name = dev_name(&curlun->dev);
rc = device_register(&curlun->dev);
if (rc) {
INFO(common, "failed to register LUN%d: %d\n", i, rc);
common->nluns = i;
put_device(&curlun->dev);
kfree(curlun);
goto error_release;
}
rc = device_create_file(&curlun->dev,
curlun->cdrom
? &dev_attr_ro_cdrom
: &dev_attr_ro);
if (rc)
goto error_luns;
rc = device_create_file(&curlun->dev,
curlun->removable
? &dev_attr_file
: &dev_attr_file_nonremovable);
if (rc)
goto error_luns;
rc = device_create_file(&curlun->dev, &dev_attr_nofua);
if (rc)
goto error_luns;
if (lcfg->filename) {
rc = fsg_lun_open(curlun, lcfg->filename);
if (rc)
goto error_luns;
} else if (!curlun->removable) {
ERROR(common, "no file given for LUN%d\n", i);
rc = -EINVAL;
goto error_luns;
}
}
/* Prepare inquiryString */ /* Prepare inquiryString */
i = get_default_bcdDevice(); i = get_default_bcdDevice();
@ -2941,7 +3023,6 @@ struct fsg_common *fsg_common_init(struct fsg_common *common,
: "File-Stor Gadget"), : "File-Stor Gadget"),
i); i);
/* Tell the thread to start working */ /* Tell the thread to start working */
common->thread_task = common->thread_task =
kthread_create(fsg_main_thread, common, "file-storage"); kthread_create(fsg_main_thread, common, "file-storage");
@ -2954,37 +3035,12 @@ struct fsg_common *fsg_common_init(struct fsg_common *common,
INFO(common, FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n"); INFO(common, FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n");
INFO(common, "Number of LUNs=%d\n", common->nluns); INFO(common, "Number of LUNs=%d\n", common->nluns);
pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
for (i = 0, nluns = common->nluns, curlun_it = common->luns;
i < nluns;
++curlun_it, ++i) {
struct fsg_lun *curlun = *curlun_it;
char *p = "(no medium)";
if (fsg_lun_is_open(curlun)) {
p = "(error)";
if (pathbuf) {
p = d_path(&curlun->filp->f_path,
pathbuf, PATH_MAX);
if (IS_ERR(p))
p = "(error)";
}
}
LINFO(curlun, "LUN: %s%s%sfile: %s\n",
curlun->removable ? "removable " : "",
curlun->ro ? "read only " : "",
curlun->cdrom ? "CD-ROM " : "",
p);
}
kfree(pathbuf);
DBG(common, "I/O thread pid: %d\n", task_pid_nr(common->thread_task)); DBG(common, "I/O thread pid: %d\n", task_pid_nr(common->thread_task));
wake_up_process(common->thread_task); wake_up_process(common->thread_task);
return common; return common;
error_luns:
common->nluns = i + 1;
error_release: error_release:
common->state = FSG_STATE_TERMINATED; /* The thread is dead */ common->state = FSG_STATE_TERMINATED; /* The thread is dead */
/* Call fsg_common_release() directly, ref might be not initialised. */ /* Call fsg_common_release() directly, ref might be not initialised. */

View File

@ -117,6 +117,12 @@ void fsg_common_free_luns(struct fsg_common *common);
int fsg_common_set_nluns(struct fsg_common *common, int nluns); int fsg_common_set_nluns(struct fsg_common *common, int nluns);
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_config_from_params(struct fsg_config *cfg, void fsg_config_from_params(struct fsg_config *cfg,
const struct fsg_module_parameters *params, const struct fsg_module_parameters *params,
unsigned int fsg_num_buffers); unsigned int fsg_num_buffers);