diff options
author | Huang Shijie <b32955@freescale.com> | 2011-10-26 17:31:25 +0800 |
---|---|---|
committer | Jason Liu <r64343@freescale.com> | 2012-01-09 21:02:48 +0800 |
commit | 83d807394e3c150757981fa73ba2bc9dcf6ac7a3 (patch) | |
tree | aeddef8632fce9f12fcd503749d52c9f1c34771d /drivers/usb | |
parent | aa5dc5212f54f026060ce98d92bdde054fddbe24 (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>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/gadget/fsl_updater.c | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/drivers/usb/gadget/fsl_updater.c b/drivers/usb/gadget/fsl_updater.c index 1bfe790b687f..8a08aa9e1a85 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); |