Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b27c08c9 authored by Andrzej Pietrasiewicz's avatar Andrzej Pietrasiewicz Committed by Felipe Balbi
Browse files

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: default avatarAndrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Acked-by: default avatarMichal Nazarewicz <mina86@mina86.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent a891d7a3
Loading
Loading
Loading
Loading
+147 −91
Original line number Diff line number Diff line
@@ -2837,16 +2837,154 @@ int fsg_common_set_cdev(struct fsg_common *common,
	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 usb_composite_dev *cdev,
				   struct fsg_config *cfg)
{
	struct usb_gadget *gadget = cdev->gadget;
	struct fsg_lun **curlun_it;
	struct fsg_lun_config *lcfg;
	int nluns, i, rc;
	char *pathbuf;

	int i, rc;

	common = fsg_common_setup(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);
	if (rc)
		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);
		if (!curlun) {
			rc = -ENOMEM;
			common->nluns = i;
			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);
	rc = fsg_common_create_luns(common, cfg);
	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;
		}
	}

		goto error_release;

	/* Prepare inquiryString */
	i = get_default_bcdDevice();
@@ -2941,7 +3023,6 @@ struct fsg_common *fsg_common_init(struct fsg_common *common,
				     : "File-Stor Gadget"),
		 i);


	/* Tell the thread to start working */
	common->thread_task =
		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, "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));

	wake_up_process(common->thread_task);

	return common;

error_luns:
	common->nluns = i + 1;
error_release:
	common->state = FSG_STATE_TERMINATED;	/* The thread is dead */
	/* Call fsg_common_release() directly, ref might be not initialised. */
+6 −0
Original line number Diff line number Diff line
@@ -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_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,
			    const struct fsg_module_parameters *params,
			    unsigned int fsg_num_buffers);