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