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: Krzysztof Opasiak <k.opasiak@samsung.com> Acked-by: Michal Nazarewicz <mina86@mina86.com>
This commit is contained in:
parent
5542f58c95
commit
dd02ea5a33
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue