Skip to content

Commit

Permalink
HID: allocate hid_parser in a proper way
Browse files Browse the repository at this point in the history
hid_parser is non-trivially large structure, so it should be allocated
using vmalloc() to avoid unsuccessful allocations when memory fragmentation
is too high.
This structue has a very short life, it's destroyed as soon as the report
descriptor has been completely parsed.

This should be considered a temporary solution, until the hid_parser is
rewritten to consume less memory during report descriptor parsing.

Acked-by: Mariusz Kozlowski <m.kozlowski@tuxland.pl>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
  • Loading branch information
Jiri Kosina committed Mar 12, 2007
1 parent be52146 commit 47a80ed
Showing 1 changed file with 9 additions and 7 deletions.
16 changes: 9 additions & 7 deletions drivers/hid/hid-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <asm/byteorder.h>
#include <linux/input.h>
#include <linux/wait.h>
#include <linux/vmalloc.h>

#include <linux/hid.h>
#include <linux/hiddev.h>
Expand Down Expand Up @@ -654,12 +655,13 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
memcpy(device->rdesc, start, size);
device->rsize = size;

if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) {
if (!(parser = vmalloc(sizeof(struct hid_parser)))) {
kfree(device->rdesc);
kfree(device->collection);
kfree(device);
return NULL;
}
memset(parser, 0, sizeof(struct hid_parser));
parser->device = device;

end = start + size;
Expand All @@ -668,39 +670,39 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
if (item.format != HID_ITEM_FORMAT_SHORT) {
dbg("unexpected long global item");
hid_free_device(device);
kfree(parser);
vfree(parser);
return NULL;
}

if (dispatch_type[item.type](parser, &item)) {
dbg("item %u %u %u %u parsing failed\n",
item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
hid_free_device(device);
kfree(parser);
vfree(parser);
return NULL;
}

if (start == end) {
if (parser->collection_stack_ptr) {
dbg("unbalanced collection at end of report description");
hid_free_device(device);
kfree(parser);
vfree(parser);
return NULL;
}
if (parser->local.delimiter_depth) {
dbg("unbalanced delimiter at end of report description");
hid_free_device(device);
kfree(parser);
vfree(parser);
return NULL;
}
kfree(parser);
vfree(parser);
return device;
}
}

dbg("item fetching failed at offset %d\n", (int)(end - start));
hid_free_device(device);
kfree(parser);
vfree(parser);
return NULL;
}
EXPORT_SYMBOL_GPL(hid_parse_report);
Expand Down

0 comments on commit 47a80ed

Please sign in to comment.