HID: allocate hid_parser in a proper way

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>

+9 -7
+9 -7
drivers/hid/hid-core.c
··· 26 26 #include <asm/byteorder.h> 27 27 #include <linux/input.h> 28 28 #include <linux/wait.h> 29 + #include <linux/vmalloc.h> 29 30 30 31 #include <linux/hid.h> 31 32 #include <linux/hiddev.h> ··· 655 654 memcpy(device->rdesc, start, size); 656 655 device->rsize = size; 657 656 658 - if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) { 657 + if (!(parser = vmalloc(sizeof(struct hid_parser)))) { 659 658 kfree(device->rdesc); 660 659 kfree(device->collection); 661 660 kfree(device); 662 661 return NULL; 663 662 } 663 + memset(parser, 0, sizeof(struct hid_parser)); 664 664 parser->device = device; 665 665 666 666 end = start + size; ··· 670 668 if (item.format != HID_ITEM_FORMAT_SHORT) { 671 669 dbg("unexpected long global item"); 672 670 hid_free_device(device); 673 - kfree(parser); 671 + vfree(parser); 674 672 return NULL; 675 673 } 676 674 ··· 678 676 dbg("item %u %u %u %u parsing failed\n", 679 677 item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); 680 678 hid_free_device(device); 681 - kfree(parser); 679 + vfree(parser); 682 680 return NULL; 683 681 } 684 682 ··· 686 684 if (parser->collection_stack_ptr) { 687 685 dbg("unbalanced collection at end of report description"); 688 686 hid_free_device(device); 689 - kfree(parser); 687 + vfree(parser); 690 688 return NULL; 691 689 } 692 690 if (parser->local.delimiter_depth) { 693 691 dbg("unbalanced delimiter at end of report description"); 694 692 hid_free_device(device); 695 - kfree(parser); 693 + vfree(parser); 696 694 return NULL; 697 695 } 698 - kfree(parser); 696 + vfree(parser); 699 697 return device; 700 698 } 701 699 } 702 700 703 701 dbg("item fetching failed at offset %d\n", (int)(end - start)); 704 702 hid_free_device(device); 705 - kfree(parser); 703 + vfree(parser); 706 704 return NULL; 707 705 } 708 706 EXPORT_SYMBOL_GPL(hid_parse_report);