summaryrefslogtreecommitdiff
path: root/drivers/input/input-mt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/input-mt.c')
-rw-r--r--drivers/input/input-mt.c37
1 files changed, 15 insertions, 22 deletions
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index 14b53dac1253..337006dd9dcf 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -39,17 +39,20 @@ static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src)
int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
unsigned int flags)
{
- struct input_mt *mt = dev->mt;
- int i;
-
if (!num_slots)
return 0;
- if (mt)
- return mt->num_slots != num_slots ? -EINVAL : 0;
- mt = kzalloc(struct_size(mt, slots, num_slots), GFP_KERNEL);
+ if (dev->mt)
+ return dev->mt->num_slots != num_slots ? -EINVAL : 0;
+
+ /* Arbitrary limit for avoiding too large memory allocation. */
+ if (num_slots > 1024)
+ return -EINVAL;
+
+ struct input_mt *mt __free(kfree) =
+ kzalloc(struct_size(mt, slots, num_slots), GFP_KERNEL);
if (!mt)
- goto err_mem;
+ return -ENOMEM;
mt->num_slots = num_slots;
mt->flags = flags;
@@ -83,21 +86,18 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
unsigned int n2 = num_slots * num_slots;
mt->red = kcalloc(n2, sizeof(*mt->red), GFP_KERNEL);
if (!mt->red)
- goto err_mem;
+ return -ENOMEM;
}
/* Mark slots as 'inactive' */
- for (i = 0; i < num_slots; i++)
+ for (unsigned int i = 0; i < num_slots; i++)
input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1);
/* Mark slots as 'unused' */
mt->frame = 1;
- dev->mt = mt;
+ dev->mt = no_free_ptr(mt);
return 0;
-err_mem:
- kfree(mt);
- return -ENOMEM;
}
EXPORT_SYMBOL(input_mt_init_slots);
@@ -282,14 +282,10 @@ void input_mt_drop_unused(struct input_dev *dev)
struct input_mt *mt = dev->mt;
if (mt) {
- unsigned long flags;
-
- spin_lock_irqsave(&dev->event_lock, flags);
+ guard(spinlock_irqsave)(&dev->event_lock);
__input_mt_drop_unused(dev, mt);
mt->frame++;
-
- spin_unlock_irqrestore(&dev->event_lock, flags);
}
}
EXPORT_SYMBOL(input_mt_drop_unused);
@@ -336,11 +332,8 @@ void input_mt_sync_frame(struct input_dev *dev)
return;
if (mt->flags & INPUT_MT_DROP_UNUSED) {
- unsigned long flags;
-
- spin_lock_irqsave(&dev->event_lock, flags);
+ guard(spinlock_irqsave)(&dev->event_lock);
__input_mt_drop_unused(dev, mt);
- spin_unlock_irqrestore(&dev->event_lock, flags);
}
if ((mt->flags & INPUT_MT_POINTER) && !(mt->flags & INPUT_MT_SEMI_MT))