diff options
author | Huang Shijie <b32955@freescale.com> | 2011-10-26 05:31:25 -0400 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 09:05:45 -0400 |
commit | 47e5735be6c980155d8b79aed01968fbc6dc2a8a (patch) | |
tree | c08c79e5c96b93e495c1fea066442d8a3d6d9dff | |
parent | 707c595fc8572f74d9195756f5896bae04d11662 (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.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/drivers/usb/gadget/fsl_updater.c b/drivers/usb/gadget/fsl_updater.c index dbc0a6cf6e88..83333d1c16db 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) | |||
48 | { | 48 | { |
49 | struct utp_user_data *uud; | 49 | struct utp_user_data *uud; |
50 | 50 | ||
51 | uud = kzalloc(size + sizeof(*uud), GFP_KERNEL); | 51 | uud = vmalloc(size + sizeof(*uud)); |
52 | if (!uud) | 52 | if (!uud) |
53 | return uud; | 53 | return uud; |
54 | memset(uud, 0, size + sizeof(*uud)); | ||
54 | uud->data.size = size + sizeof(uud->data); | 55 | uud->data.size = size + sizeof(uud->data); |
55 | INIT_LIST_HEAD(&uud->link); | 56 | INIT_LIST_HEAD(&uud->link); |
56 | return uud; | 57 | return uud; |
@@ -61,7 +62,7 @@ static void utp_user_data_free(struct utp_user_data *uud) | |||
61 | mutex_lock(&utp_context.lock); | 62 | mutex_lock(&utp_context.lock); |
62 | list_del(&uud->link); | 63 | list_del(&uud->link); |
63 | mutex_unlock(&utp_context.lock); | 64 | mutex_unlock(&utp_context.lock); |
64 | kfree(uud); | 65 | vfree(uud); |
65 | } | 66 | } |
66 | 67 | ||
67 | /* Get the number of element for list */ | 68 | /* Get the number of element for list */ |
@@ -101,8 +102,10 @@ static ssize_t utp_file_read(struct file *file, | |||
101 | 102 | ||
102 | if (size >= size_to_put) | 103 | if (size >= size_to_put) |
103 | free = !0; | 104 | free = !0; |
104 | if (copy_to_user(buf, &uud->data, size_to_put)) | 105 | if (copy_to_user(buf, &uud->data, size_to_put)) { |
106 | printk(KERN_INFO "[ %s ] copy error\n", __func__); | ||
105 | return -EACCES; | 107 | return -EACCES; |
108 | } | ||
106 | if (free) | 109 | if (free) |
107 | utp_user_data_free(uud); | 110 | utp_user_data_free(uud); |
108 | else { | 111 | else { |
@@ -131,8 +134,12 @@ static ssize_t utp_file_write(struct file *file, const char __user *buf, | |||
131 | if (size < sizeof(uud->data)) | 134 | if (size < sizeof(uud->data)) |
132 | return -EINVAL; | 135 | return -EINVAL; |
133 | uud = utp_user_data_alloc(size); | 136 | uud = utp_user_data_alloc(size); |
134 | if (copy_from_user(&uud->data, buf, size)) | 137 | return -ENOMEM; |
138 | if (copy_from_user(&uud->data, buf, size)) { | ||
139 | printk(KERN_INFO "[ %s ] copy error!\n", __func__); | ||
140 | vfree(uud); | ||
135 | return -EACCES; | 141 | return -EACCES; |
142 | } | ||
136 | mutex_lock(&utp_context.lock); | 143 | mutex_lock(&utp_context.lock); |
137 | list_add_tail(&uud->link, &utp_context.write); | 144 | list_add_tail(&uud->link, &utp_context.write); |
138 | /* Go on EXEC routine process */ | 145 | /* Go on EXEC routine process */ |
@@ -389,6 +396,8 @@ static int utp_exec(struct fsg_dev *fsg, | |||
389 | 396 | ||
390 | ctx->counter = 0xFFFF; | 397 | ctx->counter = 0xFFFF; |
391 | uud2r = utp_user_data_alloc(cmdsize + 1); | 398 | uud2r = utp_user_data_alloc(cmdsize + 1); |
399 | if (!uud2r) | ||
400 | return -ENOMEM; | ||
392 | uud2r->data.flags = UTP_FLAG_COMMAND; | 401 | uud2r->data.flags = UTP_FLAG_COMMAND; |
393 | uud2r->data.payload = payload; | 402 | uud2r->data.payload = payload; |
394 | strncpy(uud2r->data.command, command, cmdsize); | 403 | strncpy(uud2r->data.command, command, cmdsize); |
@@ -511,11 +520,12 @@ static int utp_handle_message(struct fsg_dev *fsg, | |||
511 | break; | 520 | break; |
512 | case UTP_EXEC: | 521 | case UTP_EXEC: |
513 | pr_debug("%s: EXEC\n", __func__); | 522 | pr_debug("%s: EXEC\n", __func__); |
514 | data = kzalloc(fsg->common->data_size, GFP_KERNEL); | 523 | data = vmalloc(fsg->common->data_size); |
524 | memset(data, 0, fsg->common->data_size); | ||
515 | /* copy data from usb buffer to utp buffer */ | 525 | /* copy data from usb buffer to utp buffer */ |
516 | utp_do_write(fsg, data, fsg->common->data_size); | 526 | utp_do_write(fsg, data, fsg->common->data_size); |
517 | utp_exec(fsg, data, fsg->common->data_size, param); | 527 | utp_exec(fsg, data, fsg->common->data_size, param); |
518 | kfree(data); | 528 | vfree(data); |
519 | break; | 529 | break; |
520 | case UTP_GET: /* data from device to host */ | 530 | case UTP_GET: /* data from device to host */ |
521 | pr_debug("%s: GET, %d bytes\n", __func__, | 531 | pr_debug("%s: GET, %d bytes\n", __func__, |