diff options
author | Andrzej Pietrasiewicz <andrzej.p@samsung.com> | 2013-10-09 10:05:55 +0200 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2013-10-10 10:21:48 -0500 |
commit | 6313caace5f5b4fd2c23b9bc40ea26f252a28bf9 (patch) | |
tree | 9049255d6fc9513af94e4a54f206117437171b2b /drivers/usb/gadget/f_mass_storage.c | |
parent | b24650df9521f1845571568684621cefb0ba4e3b (diff) | |
download | op-kernel-dev-6313caace5f5b4fd2c23b9bc40ea26f252a28bf9.zip op-kernel-dev-6313caace5f5b4fd2c23b9bc40ea26f252a28bf9.tar.gz |
usb: gadget: f_mass_storage: create fsg_common_set_num_buffers for use in fsg_common_init
fsg_common_init is a lengthy function. Factor a portion 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>
Diffstat (limited to 'drivers/usb/gadget/f_mass_storage.c')
-rw-r--r-- | drivers/usb/gadget/f_mass_storage.c | 72 |
1 files changed, 46 insertions, 26 deletions
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index da87ffe..79d98997 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -2681,6 +2681,49 @@ static void _fsg_common_free_buffers(struct fsg_buffhd *buffhds, unsigned n) } } +int fsg_common_set_num_buffers(struct fsg_common *common, unsigned int n) +{ + struct fsg_buffhd *bh, *buffhds; + int i, rc; + + rc = fsg_num_buffers_validate(n); + if (rc != 0) + return rc; + + buffhds = kcalloc(n, sizeof(*buffhds), GFP_KERNEL); + if (!buffhds) + return -ENOMEM; + + /* Data buffers cyclic list */ + bh = 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 = buffhds; + + _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers); + common->fsg_num_buffers = n; + common->buffhds = buffhds; + + return 0; + +error_release: + /* + * "buf"s pointed to by heads after n - i are NULL + * so releasing them won't hurt + */ + _fsg_common_free_buffers(buffhds, n); + + return -ENOMEM; +} + static inline void fsg_common_remove_sysfs(struct fsg_lun *lun) { device_remove_file(&lun->dev, &dev_attr_nofua); @@ -2714,17 +2757,12 @@ struct fsg_common *fsg_common_init(struct fsg_common *common, struct fsg_config *cfg) { struct usb_gadget *gadget = cdev->gadget; - struct fsg_buffhd *bh; struct fsg_lun **curlun_it; struct fsg_lun_config *lcfg; struct usb_string *us; int nluns, i, rc; char *pathbuf; - rc = fsg_num_buffers_validate(cfg->fsg_num_buffers); - if (rc != 0) - return ERR_PTR(rc); - /* Find out how many LUNs there should be */ nluns = cfg->nluns; if (nluns < 1 || nluns > FSG_MAX_LUNS) { @@ -2738,15 +2776,12 @@ struct fsg_common *fsg_common_init(struct fsg_common *common, fsg_common_set_sysfs(common, true); common->state = FSG_STATE_IDLE; - common->fsg_num_buffers = cfg->fsg_num_buffers; - common->buffhds = kcalloc(common->fsg_num_buffers, - sizeof *(common->buffhds), GFP_KERNEL); - if (!common->buffhds) { + rc = fsg_common_set_num_buffers(common, cfg->fsg_num_buffers); + if (rc) { if (common->free_storage_on_release) kfree(common); - return ERR_PTR(-ENOMEM); + return ERR_PTR(rc); } - common->ops = cfg->ops; common->private_data = cfg->private_data; @@ -2833,21 +2868,6 @@ struct fsg_common *fsg_common_init(struct fsg_common *common, } common->nluns = nluns; - /* Data buffers cyclic list */ - bh = common->buffhds; - i = common->fsg_num_buffers; - goto buffhds_first_it; - do { - bh->next = bh + 1; - ++bh; -buffhds_first_it: - bh->buf = kmalloc(FSG_BUFLEN, GFP_KERNEL); - if (unlikely(!bh->buf)) { - rc = -ENOMEM; - goto error_release; - } - } while (--i); - bh->next = common->buffhds; /* Prepare inquiryString */ i = get_default_bcdDevice(); |