aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2007-03-12 09:55:12 -0400
committerJiri Kosina <jkosina@suse.cz>2007-03-12 09:55:12 -0400
commit47a80edb1d80ae644ea374a016c8e68d43d2671f (patch)
tree374089eed300fbc95b8286805cdb43333af9fc30
parentbe521466feb3bb1cd89de82a2b1d080e9ebd3cb6 (diff)
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>
-rw-r--r--drivers/hid/hid-core.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index f4ee1afe488f..e5894a75a6f3 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -26,6 +26,7 @@
26#include <asm/byteorder.h> 26#include <asm/byteorder.h>
27#include <linux/input.h> 27#include <linux/input.h>
28#include <linux/wait.h> 28#include <linux/wait.h>
29#include <linux/vmalloc.h>
29 30
30#include <linux/hid.h> 31#include <linux/hid.h>
31#include <linux/hiddev.h> 32#include <linux/hiddev.h>
@@ -654,12 +655,13 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
654 memcpy(device->rdesc, start, size); 655 memcpy(device->rdesc, start, size);
655 device->rsize = size; 656 device->rsize = size;
656 657
657 if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) { 658 if (!(parser = vmalloc(sizeof(struct hid_parser)))) {
658 kfree(device->rdesc); 659 kfree(device->rdesc);
659 kfree(device->collection); 660 kfree(device->collection);
660 kfree(device); 661 kfree(device);
661 return NULL; 662 return NULL;
662 } 663 }
664 memset(parser, 0, sizeof(struct hid_parser));
663 parser->device = device; 665 parser->device = device;
664 666
665 end = start + size; 667 end = start + size;
@@ -668,7 +670,7 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
668 if (item.format != HID_ITEM_FORMAT_SHORT) { 670 if (item.format != HID_ITEM_FORMAT_SHORT) {
669 dbg("unexpected long global item"); 671 dbg("unexpected long global item");
670 hid_free_device(device); 672 hid_free_device(device);
671 kfree(parser); 673 vfree(parser);
672 return NULL; 674 return NULL;
673 } 675 }
674 676
@@ -676,7 +678,7 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
676 dbg("item %u %u %u %u parsing failed\n", 678 dbg("item %u %u %u %u parsing failed\n",
677 item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); 679 item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
678 hid_free_device(device); 680 hid_free_device(device);
679 kfree(parser); 681 vfree(parser);
680 return NULL; 682 return NULL;
681 } 683 }
682 684
@@ -684,23 +686,23 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
684 if (parser->collection_stack_ptr) { 686 if (parser->collection_stack_ptr) {
685 dbg("unbalanced collection at end of report description"); 687 dbg("unbalanced collection at end of report description");
686 hid_free_device(device); 688 hid_free_device(device);
687 kfree(parser); 689 vfree(parser);
688 return NULL; 690 return NULL;
689 } 691 }
690 if (parser->local.delimiter_depth) { 692 if (parser->local.delimiter_depth) {
691 dbg("unbalanced delimiter at end of report description"); 693 dbg("unbalanced delimiter at end of report description");
692 hid_free_device(device); 694 hid_free_device(device);
693 kfree(parser); 695 vfree(parser);
694 return NULL; 696 return NULL;
695 } 697 }
696 kfree(parser); 698 vfree(parser);
697 return device; 699 return device;
698 } 700 }
699 } 701 }
700 702
701 dbg("item fetching failed at offset %d\n", (int)(end - start)); 703 dbg("item fetching failed at offset %d\n", (int)(end - start));
702 hid_free_device(device); 704 hid_free_device(device);
703 kfree(parser); 705 vfree(parser);
704 return NULL; 706 return NULL;
705} 707}
706EXPORT_SYMBOL_GPL(hid_parse_report); 708EXPORT_SYMBOL_GPL(hid_parse_report);