HID: core: statically allocate read buffers
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>
Thu, 3 Feb 2022 14:32:15 +0000 (15:32 +0100)
committerJiri Kosina <jkosina@suse.cz>
Tue, 1 Mar 2022 14:46:02 +0000 (15:46 +0100)
This is a preparation patch for rethinking the generic processing
of HID reports.

We can actually pre-allocate all of our memory instead of dynamically
allocating/freeing it whenever we parse a report.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: Ping Cheng <ping.cheng@wacom.com>
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
drivers/hid/hid-core.c
include/linux/hid.h

index f1aed5bbd00080429acab1d9ba31eba48794b969..75e7b8447bf7bf82b0a9043bf0a1f10b807c722f 100644 (file)
@@ -101,7 +101,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
 
        field = kzalloc((sizeof(struct hid_field) +
                         usages * sizeof(struct hid_usage) +
-                        usages * sizeof(unsigned)), GFP_KERNEL);
+                        2 * usages * sizeof(unsigned int)), GFP_KERNEL);
        if (!field)
                return NULL;
 
@@ -109,6 +109,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
        report->field[field->index] = field;
        field->usage = (struct hid_usage *)(field + 1);
        field->value = (s32 *)(field->usage + usages);
+       field->new_value = (s32 *)(field->value + usages);
        field->report = report;
 
        return field;
@@ -1541,9 +1542,8 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field,
        __s32 max = field->logical_maximum;
        __s32 *value;
 
-       value = kmalloc_array(count, sizeof(__s32), GFP_ATOMIC);
-       if (!value)
-               return;
+       value = field->new_value;
+       memset(value, 0, count * sizeof(__s32));
 
        for (n = 0; n < count; n++) {
 
@@ -1557,7 +1557,7 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field,
                    value[n] >= min && value[n] <= max &&
                    value[n] - min < field->maxusage &&
                    field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
-                       goto exit;
+                       return;
        }
 
        for (n = 0; n < count; n++) {
@@ -1581,8 +1581,6 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field,
        }
 
        memcpy(field->value, value, count * sizeof(__s32));
-exit:
-       kfree(value);
 }
 
 /*
index 7487b0586fe6acd17dd466065e37b2f62983a6f7..3fbfe0986659b000ee52f321c442cfe9a8f67397 100644 (file)
@@ -476,6 +476,7 @@ struct hid_field {
        unsigned  report_count;         /* number of this field in the report */
        unsigned  report_type;          /* (input,output,feature) */
        __s32    *value;                /* last known value(s) */
+       __s32    *new_value;            /* newly read value(s) */
        __s32     logical_minimum;
        __s32     logical_maximum;
        __s32     physical_minimum;