Commit dd02ea5a authored by Krzysztof Opasiak's avatar Krzysztof Opasiak Committed by Felipe Balbi

usb: gadget: mass_storage: Use static array for luns

This patch replace dynamicly allocated luns array with static one.
This simplifies the code of mass storage function and modules.
Signed-off-by: default avatarKrzysztof Opasiak <k.opasiak@samsung.com>
Acked-by: default avatarMichal Nazarewicz <mina86@mina86.com>
parent 5542f58c
......@@ -279,9 +279,8 @@ struct fsg_common {
int cmnd_size;
u8 cmnd[MAX_COMMAND_SIZE];
unsigned int nluns;
unsigned int lun;
struct fsg_lun **luns;
struct fsg_lun *luns[FSG_MAX_LUNS];
struct fsg_lun *curlun;
unsigned int bulk_out_maxpacket;
......@@ -490,6 +489,16 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
spin_unlock(&common->lock);
}
static int _fsg_common_get_max_lun(struct fsg_common *common)
{
int i = ARRAY_SIZE(common->luns) - 1;
while (i >= 0 && !common->luns[i])
--i;
return i;
}
static int fsg_setup(struct usb_function *f,
const struct usb_ctrlrequest *ctrl)
{
......@@ -533,7 +542,7 @@ static int fsg_setup(struct usb_function *f,
w_length != 1)
return -EDOM;
VDBG(fsg, "get max LUN\n");
*(u8 *)req->buf = fsg->common->nluns - 1;
*(u8 *)req->buf = _fsg_common_get_max_lun(fsg->common);
/* Respond with data/status */
req->length = min((u16)1, w_length);
......@@ -2131,8 +2140,9 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
}
/* Is the CBW meaningful? */
if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
if (cbw->Lun >= ARRAY_SIZE(common->luns) ||
cbw->Flags & ~US_BULK_FLAG_IN || cbw->Length <= 0 ||
cbw->Length > MAX_COMMAND_SIZE) {
DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
"cmdlen %u\n",
cbw->Lun, cbw->Flags, cbw->Length);
......@@ -2159,7 +2169,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
if (common->data_size == 0)
common->data_dir = DATA_DIR_NONE;
common->lun = cbw->Lun;
if (common->lun < common->nluns)
if (common->lun < ARRAY_SIZE(common->luns))
common->curlun = common->luns[common->lun];
else
common->curlun = NULL;
......@@ -2307,7 +2317,7 @@ static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg)
}
common->running = 1;
for (i = 0; i < common->nluns; ++i)
for (i = 0; i < ARRAY_SIZE(common->luns); ++i)
if (common->luns[i])
common->luns[i]->unit_attention_data =
SS_RESET_OCCURRED;
......@@ -2409,7 +2419,7 @@ static void handle_exception(struct fsg_common *common)
if (old_state == FSG_STATE_ABORT_BULK_OUT)
common->state = FSG_STATE_STATUS_PHASE;
else {
for (i = 0; i < common->nluns; ++i) {
for (i = 0; i < ARRAY_SIZE(common->luns); ++i) {
curlun = common->luns[i];
if (!curlun)
continue;
......@@ -2453,7 +2463,7 @@ static void handle_exception(struct fsg_common *common)
* a waste of time. Ditto for the INTERFACE_CHANGE and
* CONFIG_CHANGE cases.
*/
/* for (i = 0; i < common->nluns; ++i) */
/* for (i = 0; i < common->ARRAY_SIZE(common->luns); ++i) */
/* if (common->luns[i]) */
/* common->luns[i]->unit_attention_data = */
/* SS_RESET_OCCURRED; */
......@@ -2552,12 +2562,11 @@ static int fsg_main_thread(void *common_)
if (!common->ops || !common->ops->thread_exits
|| common->ops->thread_exits(common) < 0) {
struct fsg_lun **curlun_it = common->luns;
unsigned i = common->nluns;
int i;
down_write(&common->filesem);
for (; i--; ++curlun_it) {
struct fsg_lun *curlun = *curlun_it;
for (i = 0; i < ARRAY_SIZE(common->luns); --i) {
struct fsg_lun *curlun = common->luns[i];
if (!curlun || !fsg_lun_is_open(curlun))
continue;
......@@ -2676,6 +2685,7 @@ static struct fsg_common *fsg_common_setup(struct fsg_common *common)
init_completion(&common->thread_notifier);
init_waitqueue_head(&common->fsg_wait);
common->state = FSG_STATE_TERMINATED;
memset(common->luns, 0, sizeof(common->luns));
return common;
}
......@@ -2764,42 +2774,10 @@ static void _fsg_common_remove_luns(struct fsg_common *common, int n)
void fsg_common_remove_luns(struct fsg_common *common)
{
_fsg_common_remove_luns(common, common->nluns);
_fsg_common_remove_luns(common, ARRAY_SIZE(common->luns));
}
EXPORT_SYMBOL_GPL(fsg_common_remove_luns);
void fsg_common_free_luns(struct fsg_common *common)
{
fsg_common_remove_luns(common);
kfree(common->luns);
common->luns = NULL;
}
EXPORT_SYMBOL_GPL(fsg_common_free_luns);
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(FSG_MAX_LUNS, sizeof(*curlun), GFP_KERNEL);
if (unlikely(!curlun))
return -ENOMEM;
if (common->luns)
fsg_common_free_luns(common);
common->luns = curlun;
common->nluns = nluns;
return 0;
}
EXPORT_SYMBOL_GPL(fsg_common_set_nluns);
void fsg_common_set_ops(struct fsg_common *common,
const struct fsg_operations *ops)
{
......@@ -2881,7 +2859,7 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
char *pathbuf, *p;
int rc = -ENOMEM;
if (!common->nluns || !common->luns)
if (id >= ARRAY_SIZE(common->luns))
return -ENODEV;
if (common->luns[id])
......@@ -2965,14 +2943,16 @@ 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) {
fsg_common_remove_luns(common);
for (i = 0; i < cfg->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);
pr_info("Number of LUNs=%d\n", cfg->nluns);
return 0;
......@@ -3021,6 +3001,7 @@ EXPORT_SYMBOL_GPL(fsg_common_run_thread);
static void fsg_common_release(struct kref *ref)
{
struct fsg_common *common = container_of(ref, struct fsg_common, ref);
int i;
/* If the thread isn't already dead, tell it to exit now */
if (common->state != FSG_STATE_TERMINATED) {
......@@ -3028,22 +3009,14 @@ static void fsg_common_release(struct kref *ref)
wait_for_completion(&common->thread_notifier);
}
if (likely(common->luns)) {
struct fsg_lun **lun_it = common->luns;
unsigned i = common->nluns;
/* In error recovery common->nluns may be zero. */
for (; i; --i, ++lun_it) {
struct fsg_lun *lun = *lun_it;
if (!lun)
continue;
fsg_lun_close(lun);
for (i = 0; i < ARRAY_SIZE(common->luns); ++i) {
struct fsg_lun *lun = common->luns[i];
if (!lun)
continue;
fsg_lun_close(lun);
if (device_is_registered(&lun->dev))
device_unregister(&lun->dev);
kfree(lun);
}
kfree(common->luns);
device_unregister(&lun->dev);
kfree(lun);
}
_fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers);
......@@ -3057,6 +3030,7 @@ static void fsg_common_release(struct kref *ref)
static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
struct fsg_common *common = fsg->common;
struct usb_gadget *gadget = c->cdev->gadget;
int i;
struct usb_ep *ep;
......@@ -3064,6 +3038,13 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
int ret;
struct fsg_opts *opts;
/* Don't allow to bind if we don't have at least one LUN */
ret = _fsg_common_get_max_lun(common);
if (ret < 0) {
pr_err("There should be at least one LUN.\n");
return -EINVAL;
}
opts = fsg_opts_from_func_inst(f->fi);
if (!opts->no_configfs) {
ret = fsg_common_set_cdev(fsg->common, c->cdev,
......@@ -3517,14 +3498,11 @@ static struct usb_function_instance *fsg_alloc_inst(void)
rc = PTR_ERR(opts->common);
goto release_opts;
}
rc = fsg_common_set_nluns(opts->common, FSG_MAX_LUNS);
if (rc)
goto release_opts;
rc = fsg_common_set_num_buffers(opts->common,
CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS);
if (rc)
goto release_luns;
goto release_opts;
pr_info(FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n");
......@@ -3547,8 +3525,6 @@ static struct usb_function_instance *fsg_alloc_inst(void)
release_buffers:
fsg_common_free_buffers(opts->common);
release_luns:
kfree(opts->common->luns);
release_opts:
kfree(opts);
return ERR_PTR(rc);
......@@ -3574,23 +3550,12 @@ static struct usb_function *fsg_alloc(struct usb_function_instance *fi)
struct fsg_opts *opts = fsg_opts_from_func_inst(fi);
struct fsg_common *common = opts->common;
struct fsg_dev *fsg;
unsigned nluns, i;
fsg = kzalloc(sizeof(*fsg), GFP_KERNEL);
if (unlikely(!fsg))
return ERR_PTR(-ENOMEM);
mutex_lock(&opts->lock);
if (!opts->refcnt) {
for (nluns = i = 0; i < FSG_MAX_LUNS; ++i)
if (common->luns[i])
nluns = i + 1;
if (!nluns)
pr_warn("No LUNS defined, continuing anyway\n");
else
common->nluns = nluns;
pr_info("Number of LUNs=%u\n", common->nluns);
}
opts->refcnt++;
mutex_unlock(&opts->lock);
......
......@@ -141,10 +141,6 @@ void fsg_common_remove_lun(struct fsg_lun *lun);
void fsg_common_remove_luns(struct fsg_common *common);
void fsg_common_free_luns(struct fsg_common *common);
int fsg_common_set_nluns(struct fsg_common *common, int nluns);
void fsg_common_set_ops(struct fsg_common *common,
const struct fsg_operations *ops);
......
......@@ -186,10 +186,6 @@ static int acm_ms_bind(struct usb_composite_dev *cdev)
if (status)
goto fail;
status = fsg_common_set_nluns(opts->common, config.nluns);
if (status)
goto fail_set_nluns;
status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
if (status)
goto fail_set_cdev;
......@@ -239,8 +235,6 @@ static int acm_ms_bind(struct usb_composite_dev *cdev)
fail_string_ids:
fsg_common_remove_luns(opts->common);
fail_set_cdev:
fsg_common_free_luns(opts->common);
fail_set_nluns:
fsg_common_free_buffers(opts->common);
fail:
usb_put_function_instance(fi_msg);
......
......@@ -177,10 +177,6 @@ static int msg_bind(struct usb_composite_dev *cdev)
if (status)
goto fail;
status = fsg_common_set_nluns(opts->common, config.nluns);
if (status)
goto fail_set_nluns;
fsg_common_set_ops(opts->common, &ops);
status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
......@@ -227,8 +223,6 @@ static int msg_bind(struct usb_composite_dev *cdev)
fail_string_ids:
fsg_common_remove_luns(opts->common);
fail_set_cdev:
fsg_common_free_luns(opts->common);
fail_set_nluns:
fsg_common_free_buffers(opts->common);
fail:
usb_put_function_instance(fi_msg);
......
......@@ -393,10 +393,6 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
if (status)
goto fail2;
status = fsg_common_set_nluns(fsg_opts->common, config.nluns);
if (status)
goto fail_set_nluns;
status = fsg_common_set_cdev(fsg_opts->common, cdev, config.can_stall);
if (status)
goto fail_set_cdev;
......@@ -448,8 +444,6 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
fail_string_ids:
fsg_common_remove_luns(fsg_opts->common);
fail_set_cdev:
fsg_common_free_luns(fsg_opts->common);
fail_set_nluns:
fsg_common_free_buffers(fsg_opts->common);
fail2:
usb_put_function_instance(fi_msg);
......
......@@ -339,19 +339,15 @@ static int nokia_bind(struct usb_composite_dev *cdev)
if (status)
goto err_msg_inst;
status = fsg_common_set_nluns(fsg_opts->common, fsg_config.nluns);
if (status)
goto err_msg_buf;
status = fsg_common_set_cdev(fsg_opts->common, cdev, fsg_config.can_stall);
if (status)
goto err_msg_set_nluns;
goto err_msg_buf;
fsg_common_set_sysfs(fsg_opts->common, true);
status = fsg_common_create_luns(fsg_opts->common, &fsg_config);
if (status)
goto err_msg_set_nluns;
goto err_msg_buf;
fsg_common_set_inquiry_string(fsg_opts->common, fsg_config.vendor_name,
fsg_config.product_name);
......@@ -360,7 +356,7 @@ static int nokia_bind(struct usb_composite_dev *cdev)
status = usb_add_config(cdev, &nokia_config_500ma_driver,
nokia_bind_config);
if (status < 0)
goto err_msg_set_cdev;
goto err_msg_luns;
status = usb_add_config(cdev, &nokia_config_100ma_driver,
nokia_bind_config);
......@@ -381,10 +377,8 @@ static int nokia_bind(struct usb_composite_dev *cdev)
if (!IS_ERR_OR_NULL(f_phonet_cfg1))
usb_put_function(f_phonet_cfg1);
usb_put_function(f_ecm_cfg1);
err_msg_set_cdev:
err_msg_luns:
fsg_common_remove_luns(fsg_opts->common);
err_msg_set_nluns:
fsg_common_free_luns(fsg_opts->common);
err_msg_buf:
fsg_common_free_buffers(fsg_opts->common);
err_msg_inst:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment