aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHuang Shijie <b32955@freescale.com>2011-10-26 17:31:25 +0800
committerEric Miao <eric.miao@canonical.com>2011-11-10 07:38:52 +0800
commitc5e2891cef54d2ade28f8239c345e26bd378dc75 (patch)
treef543679f22672b3d51c38095119aac3030895059
parentca3c26d4296c524a26345edd275ab9abe6f1ed96 (diff)
ENGR00160834 UTP : replace kzalloc() with vmalloc()
When allocating large memory, such as 128K, vmalloc() uses single page for the allocation process, while kzalloc() has to consume a continuous pages for the allocation. In low memory case, the kzalloc() may fails. So use the vmalloc() instead. Also add some sanity check for the NULL pointer. Signed-off-by: Huang Shijie <b32955@freescale.com>
-rw-r--r--drivers/usb/gadget/fsl_updater.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/drivers/usb/gadget/fsl_updater.c b/drivers/usb/gadget/fsl_updater.c
index 1bfe790b687..8a08aa9e1a8 100644
--- a/drivers/usb/gadget/fsl_updater.c
+++ b/drivers/usb/gadget/fsl_updater.c
@@ -48,9 +48,10 @@ static struct utp_user_data *utp_user_data_alloc(size_t size)
{
struct utp_user_data *uud;
- uud = kzalloc(size + sizeof(*uud), GFP_KERNEL);
+ uud = vmalloc(size + sizeof(*uud));
if (!uud)
return uud;
+ memset(uud, 0, size + sizeof(*uud));
uud->data.size = size + sizeof(uud->data);
INIT_LIST_HEAD(&uud->link);
return uud;
@@ -61,7 +62,7 @@ static void utp_user_data_free(struct utp_user_data *uud)
mutex_lock(&utp_context.lock);
list_del(&uud->link);
mutex_unlock(&utp_context.lock);
- kfree(uud);
+ vfree(uud);
}
/* Get the number of element for list */
@@ -99,8 +100,10 @@ static ssize_t utp_file_read(struct file *file,
if (size >= size_to_put)
free = !0;
- if (copy_to_user(buf, &uud->data, size_to_put))
+ if (copy_to_user(buf, &uud->data, size_to_put)) {
+ printk(KERN_INFO "[ %s ] copy error\n", __func__);
return -EACCES;
+ }
if (free)
utp_user_data_free(uud);
else {
@@ -129,8 +132,12 @@ static ssize_t utp_file_write(struct file *file, const char __user *buf,
if (size < sizeof(uud->data))
return -EINVAL;
uud = utp_user_data_alloc(size);
- if (copy_from_user(&uud->data, buf, size))
+ return -ENOMEM;
+ if (copy_from_user(&uud->data, buf, size)) {
+ printk(KERN_INFO "[ %s ] copy error!\n", __func__);
+ vfree(uud);
return -EACCES;
+ }
mutex_lock(&utp_context.lock);
list_add_tail(&uud->link, &utp_context.write);
/* Go on EXEC routine process */
@@ -407,6 +414,8 @@ static int utp_exec(struct fsg_dev *fsg,
ctx->counter = 0xFFFF;
uud2r = utp_user_data_alloc(cmdsize + 1);
+ if (!uud2r)
+ return -ENOMEM;
uud2r->data.flags = UTP_FLAG_COMMAND;
uud2r->data.payload = payload;
strncpy(uud2r->data.command, command, cmdsize);
@@ -529,11 +538,12 @@ static int utp_handle_message(struct fsg_dev *fsg,
break;
case UTP_EXEC:
pr_debug("%s: EXEC\n", __func__);
- data = kzalloc(fsg->data_size, GFP_KERNEL);
+ data = vmalloc(fsg->data_size);
+ memset(data, 0, fsg->data_size);
/* copy data from usb buffer to utp buffer */
utp_do_write(fsg, data, fsg->data_size);
utp_exec(fsg, data, fsg->data_size, param);
- kfree(data);
+ vfree(data);
break;
case UTP_GET: /* data from device to host */
pr_debug("%s: GET, %d bytes\n", __func__, fsg->data_size);
@@ -544,6 +554,8 @@ static int utp_handle_message(struct fsg_dev *fsg,
utp_context.cur_state = UTP_FLAG_DATA;
pr_debug("%s: PUT, Received %d bytes\n", __func__, fsg->data_size);/* data from host to device */
uud2r = utp_user_data_alloc(fsg->data_size);
+ if (!uud2r)
+ return -ENOMEM;
uud2r->data.bufsize = fsg->data_size;
uud2r->data.flags = UTP_FLAG_DATA;
utp_do_write(fsg, uud2r->data.data, fsg->data_size);