linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] Convert input core to use new cleanup facilities
@ 2024-11-07  7:15 Dmitry Torokhov
  2024-11-07  7:15 ` [PATCH 1/8] Input: ff-core - convert locking to guard notation Dmitry Torokhov
                   ` (8 more replies)
  0 siblings, 9 replies; 15+ messages in thread
From: Dmitry Torokhov @ 2024-11-07  7:15 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Hans de Goede; +Cc: linux-input, linux-kernel

Hi,

This series converts input core (but not input handlers such as evdev,
joydev, etc) to use new __free() and guard() cleanup facilities that
simplify the code and ensure that all resources are released
appropriately.

Input handlers will be converted separately later.

Thanks!

Dmitry Torokhov (8):
  Input: ff-core - convert locking to guard notation
  Input: ff-core - make use of __free() cleanup facility
  Input: ff-memless - convert locking to guard notation
  Input: ff-memless - make use of __free() cleanup facility
  Input: mt - convert locking to guard notation
  Input: mt - make use of __free() cleanup facility
  Input: poller - convert locking to guard notation
  Input: use guard notation in input core

 drivers/input/ff-core.c      |  90 ++++------
 drivers/input/ff-memless.c   |  17 +-
 drivers/input/input-mt.c     |  34 ++--
 drivers/input/input-poller.c |   4 +-
 drivers/input/input.c        | 339 ++++++++++++++---------------------
 5 files changed, 184 insertions(+), 300 deletions(-)

-- 
Dmitry

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/8] Input: ff-core - convert locking to guard notation
  2024-11-07  7:15 [PATCH 0/8] Convert input core to use new cleanup facilities Dmitry Torokhov
@ 2024-11-07  7:15 ` Dmitry Torokhov
  2024-11-07  7:15 ` [PATCH 2/8] Input: ff-core - make use of __free() cleanup facility Dmitry Torokhov
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Dmitry Torokhov @ 2024-11-07  7:15 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Hans de Goede; +Cc: linux-input, linux-kernel

Use guard() and scoped_guard() notation instead of explicitly acquiring
and releasing spinlocks and mutexes to simplify the code and ensure that
all locks are released properly.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/ff-core.c | 71 +++++++++++++++++------------------------
 1 file changed, 29 insertions(+), 42 deletions(-)

diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c
index 609a5f01761b..eb01bcb69d00 100644
--- a/drivers/input/ff-core.c
+++ b/drivers/input/ff-core.c
@@ -93,7 +93,7 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect,
 {
 	struct ff_device *ff = dev->ff;
 	struct ff_effect *old;
-	int ret = 0;
+	int error;
 	int id;
 
 	if (!test_bit(EV_FF, dev->evbit))
@@ -114,22 +114,20 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect,
 	}
 
 	if (!test_bit(effect->type, ff->ffbit)) {
-		ret = compat_effect(ff, effect);
-		if (ret)
-			return ret;
+		error = compat_effect(ff, effect);
+		if (error)
+			return error;
 	}
 
-	mutex_lock(&ff->mutex);
+	guard(mutex)(&ff->mutex);
 
 	if (effect->id == -1) {
 		for (id = 0; id < ff->max_effects; id++)
 			if (!ff->effect_owners[id])
 				break;
 
-		if (id >= ff->max_effects) {
-			ret = -ENOSPC;
-			goto out;
-		}
+		if (id >= ff->max_effects)
+			return -ENOSPC;
 
 		effect->id = id;
 		old = NULL;
@@ -137,30 +135,26 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect,
 	} else {
 		id = effect->id;
 
-		ret = check_effect_access(ff, id, file);
-		if (ret)
-			goto out;
+		error = check_effect_access(ff, id, file);
+		if (error)
+			return error;
 
 		old = &ff->effects[id];
 
-		if (!check_effects_compatible(effect, old)) {
-			ret = -EINVAL;
-			goto out;
-		}
+		if (!check_effects_compatible(effect, old))
+			return -EINVAL;
 	}
 
-	ret = ff->upload(dev, effect, old);
-	if (ret)
-		goto out;
+	error = ff->upload(dev, effect, old);
+	if (error)
+		return error;
 
-	spin_lock_irq(&dev->event_lock);
-	ff->effects[id] = *effect;
-	ff->effect_owners[id] = file;
-	spin_unlock_irq(&dev->event_lock);
+	scoped_guard(spinlock_irq, &dev->event_lock) {
+		ff->effects[id] = *effect;
+		ff->effect_owners[id] = file;
+	}
 
- out:
-	mutex_unlock(&ff->mutex);
-	return ret;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(input_ff_upload);
 
@@ -178,17 +172,16 @@ static int erase_effect(struct input_dev *dev, int effect_id,
 	if (error)
 		return error;
 
-	spin_lock_irq(&dev->event_lock);
-	ff->playback(dev, effect_id, 0);
-	ff->effect_owners[effect_id] = NULL;
-	spin_unlock_irq(&dev->event_lock);
+	scoped_guard(spinlock_irq, &dev->event_lock) {
+		ff->playback(dev, effect_id, 0);
+		ff->effect_owners[effect_id] = NULL;
+	}
 
 	if (ff->erase) {
 		error = ff->erase(dev, effect_id);
 		if (error) {
-			spin_lock_irq(&dev->event_lock);
-			ff->effect_owners[effect_id] = file;
-			spin_unlock_irq(&dev->event_lock);
+			scoped_guard(spinlock_irq, &dev->event_lock)
+				ff->effect_owners[effect_id] = file;
 
 			return error;
 		}
@@ -210,16 +203,12 @@ static int erase_effect(struct input_dev *dev, int effect_id,
 int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file)
 {
 	struct ff_device *ff = dev->ff;
-	int ret;
 
 	if (!test_bit(EV_FF, dev->evbit))
 		return -ENOSYS;
 
-	mutex_lock(&ff->mutex);
-	ret = erase_effect(dev, effect_id, file);
-	mutex_unlock(&ff->mutex);
-
-	return ret;
+	guard(mutex)(&ff->mutex);
+	return erase_effect(dev, effect_id, file);
 }
 EXPORT_SYMBOL_GPL(input_ff_erase);
 
@@ -239,13 +228,11 @@ int input_ff_flush(struct input_dev *dev, struct file *file)
 
 	dev_dbg(&dev->dev, "flushing now\n");
 
-	mutex_lock(&ff->mutex);
+	guard(mutex)(&ff->mutex);
 
 	for (i = 0; i < ff->max_effects; i++)
 		erase_effect(dev, i, file);
 
-	mutex_unlock(&ff->mutex);
-
 	return 0;
 }
 EXPORT_SYMBOL_GPL(input_ff_flush);
-- 
2.47.0.277.g8800431eea-goog


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/8] Input: ff-core - make use of __free() cleanup facility
  2024-11-07  7:15 [PATCH 0/8] Convert input core to use new cleanup facilities Dmitry Torokhov
  2024-11-07  7:15 ` [PATCH 1/8] Input: ff-core - convert locking to guard notation Dmitry Torokhov
@ 2024-11-07  7:15 ` Dmitry Torokhov
       [not found]   ` <CGME20241220123701eucas1p23125e0738985ffe35cbe9624dff08972@eucas1p2.samsung.com>
  2024-11-07  7:15 ` [PATCH 3/8] Input: ff-memless - convert locking to guard notation Dmitry Torokhov
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Dmitry Torokhov @ 2024-11-07  7:15 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Hans de Goede; +Cc: linux-input, linux-kernel

Annotate allocated memory with __free(kfree) to simplify the code and
make sure memory is released appropriately.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/ff-core.c | 19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)

diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c
index eb01bcb69d00..a235d2eb6b31 100644
--- a/drivers/input/ff-core.c
+++ b/drivers/input/ff-core.c
@@ -290,8 +290,6 @@ EXPORT_SYMBOL_GPL(input_ff_event);
  */
 int input_ff_create(struct input_dev *dev, unsigned int max_effects)
 {
-	struct ff_device *ff;
-	size_t ff_dev_size;
 	int i;
 
 	if (!max_effects) {
@@ -304,25 +302,20 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects)
 		return -EINVAL;
 	}
 
-	ff_dev_size = struct_size(ff, effect_owners, max_effects);
-	if (ff_dev_size == SIZE_MAX) /* overflow */
-		return -EINVAL;
-
-	ff = kzalloc(ff_dev_size, GFP_KERNEL);
+	struct ff_device *ff __free(kfree) =
+		kzalloc(struct_size(ff, effect_owners, max_effects),
+			GFP_KERNEL);
 	if (!ff)
 		return -ENOMEM;
 
-	ff->effects = kcalloc(max_effects, sizeof(struct ff_effect),
-			      GFP_KERNEL);
-	if (!ff->effects) {
-		kfree(ff);
+	ff->effects = kcalloc(max_effects, sizeof(*ff->effects), GFP_KERNEL);
+	if (!ff->effects)
 		return -ENOMEM;
-	}
 
 	ff->max_effects = max_effects;
 	mutex_init(&ff->mutex);
 
-	dev->ff = ff;
+	dev->ff = no_free_ptr(ff);
 	dev->flush = input_ff_flush;
 	dev->event = input_ff_event;
 	__set_bit(EV_FF, dev->evbit);
-- 
2.47.0.277.g8800431eea-goog


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/8] Input: ff-memless - convert locking to guard notation
  2024-11-07  7:15 [PATCH 0/8] Convert input core to use new cleanup facilities Dmitry Torokhov
  2024-11-07  7:15 ` [PATCH 1/8] Input: ff-core - convert locking to guard notation Dmitry Torokhov
  2024-11-07  7:15 ` [PATCH 2/8] Input: ff-core - make use of __free() cleanup facility Dmitry Torokhov
@ 2024-11-07  7:15 ` Dmitry Torokhov
  2024-11-07  7:15 ` [PATCH 4/8] Input: ff-memless - make use of __free() cleanup facility Dmitry Torokhov
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Dmitry Torokhov @ 2024-11-07  7:15 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Hans de Goede; +Cc: linux-input, linux-kernel

Use guard() notation instead of explicitly acquiring and releasing
spinlocks to simplify the code and ensure that all locks are released.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/ff-memless.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index c321cdabd214..ec99c070a97c 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -401,13 +401,11 @@ static void ml_effect_timer(struct timer_list *t)
 {
 	struct ml_device *ml = from_timer(ml, t, timer);
 	struct input_dev *dev = ml->dev;
-	unsigned long flags;
 
 	pr_debug("timer: updating effects\n");
 
-	spin_lock_irqsave(&dev->event_lock, flags);
+	guard(spinlock_irqsave)(&dev->event_lock);
 	ml_play_effects(ml);
-	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
 /*
@@ -465,7 +463,7 @@ static int ml_ff_upload(struct input_dev *dev,
 	struct ml_device *ml = dev->ff->private;
 	struct ml_effect_state *state = &ml->states[effect->id];
 
-	spin_lock_irq(&dev->event_lock);
+	guard(spinlock_irq)(&dev->event_lock);
 
 	if (test_bit(FF_EFFECT_STARTED, &state->flags)) {
 		__clear_bit(FF_EFFECT_PLAYING, &state->flags);
@@ -477,8 +475,6 @@ static int ml_ff_upload(struct input_dev *dev,
 		ml_schedule_timer(ml);
 	}
 
-	spin_unlock_irq(&dev->event_lock);
-
 	return 0;
 }
 
-- 
2.47.0.277.g8800431eea-goog


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/8] Input: ff-memless - make use of __free() cleanup facility
  2024-11-07  7:15 [PATCH 0/8] Convert input core to use new cleanup facilities Dmitry Torokhov
                   ` (2 preceding siblings ...)
  2024-11-07  7:15 ` [PATCH 3/8] Input: ff-memless - convert locking to guard notation Dmitry Torokhov
@ 2024-11-07  7:15 ` Dmitry Torokhov
  2024-11-07  7:15 ` [PATCH 5/8] Input: mt - convert locking to guard notation Dmitry Torokhov
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Dmitry Torokhov @ 2024-11-07  7:15 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Hans de Goede; +Cc: linux-input, linux-kernel

Annotate allocated memory with __free(kfree) to simplify the code and
make sure memory is released appropriately.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/ff-memless.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index ec99c070a97c..0bbeceb35545 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -503,12 +503,11 @@ static void ml_ff_destroy(struct ff_device *ff)
 int input_ff_create_memless(struct input_dev *dev, void *data,
 		int (*play_effect)(struct input_dev *, void *, struct ff_effect *))
 {
-	struct ml_device *ml;
 	struct ff_device *ff;
 	int error;
 	int i;
 
-	ml = kzalloc(sizeof(struct ml_device), GFP_KERNEL);
+	struct ml_device *ml __free(kfree) = kzalloc(sizeof(*ml), GFP_KERNEL);
 	if (!ml)
 		return -ENOMEM;
 
@@ -521,13 +520,11 @@ int input_ff_create_memless(struct input_dev *dev, void *data,
 	set_bit(FF_GAIN, dev->ffbit);
 
 	error = input_ff_create(dev, FF_MEMLESS_EFFECTS);
-	if (error) {
-		kfree(ml);
+	if (error)
 		return error;
-	}
 
 	ff = dev->ff;
-	ff->private = ml;
+	ff->private = no_free_ptr(ml);
 	ff->upload = ml_ff_upload;
 	ff->playback = ml_ff_playback;
 	ff->set_gain = ml_ff_set_gain;
-- 
2.47.0.277.g8800431eea-goog


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/8] Input: mt - convert locking to guard notation
  2024-11-07  7:15 [PATCH 0/8] Convert input core to use new cleanup facilities Dmitry Torokhov
                   ` (3 preceding siblings ...)
  2024-11-07  7:15 ` [PATCH 4/8] Input: ff-memless - make use of __free() cleanup facility Dmitry Torokhov
@ 2024-11-07  7:15 ` Dmitry Torokhov
  2024-11-07  7:15 ` [PATCH 6/8] Input: mt - make use of __free() cleanup facility Dmitry Torokhov
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Dmitry Torokhov @ 2024-11-07  7:15 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Hans de Goede; +Cc: linux-input, linux-kernel

Use guard() notation instead of explicitly acquiring and releasing
spinlocks to simplify the code and ensure that all locks are released.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/input-mt.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index 6b04a674f832..45e41fc9059c 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -285,14 +285,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);
@@ -339,11 +335,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))
-- 
2.47.0.277.g8800431eea-goog


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/8] Input: mt - make use of __free() cleanup facility
  2024-11-07  7:15 [PATCH 0/8] Convert input core to use new cleanup facilities Dmitry Torokhov
                   ` (4 preceding siblings ...)
  2024-11-07  7:15 ` [PATCH 5/8] Input: mt - convert locking to guard notation Dmitry Torokhov
@ 2024-11-07  7:15 ` Dmitry Torokhov
  2024-11-07  7:15 ` [PATCH 7/8] Input: poller - convert locking to guard notation Dmitry Torokhov
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Dmitry Torokhov @ 2024-11-07  7:15 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Hans de Goede; +Cc: linux-input, linux-kernel

Annotate allocated memory with __free(kfree) to simplify the code and
make sure memory is released appropriately.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/input-mt.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index 45e41fc9059c..337006dd9dcf 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -39,20 +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;
+
+	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;
 
-	mt = kzalloc(struct_size(mt, slots, num_slots), GFP_KERNEL);
+	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;
@@ -86,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);
 
-- 
2.47.0.277.g8800431eea-goog


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 7/8] Input: poller - convert locking to guard notation
  2024-11-07  7:15 [PATCH 0/8] Convert input core to use new cleanup facilities Dmitry Torokhov
                   ` (5 preceding siblings ...)
  2024-11-07  7:15 ` [PATCH 6/8] Input: mt - make use of __free() cleanup facility Dmitry Torokhov
@ 2024-11-07  7:15 ` Dmitry Torokhov
  2024-11-07  7:15 ` [PATCH 8/8] Input: use guard notation in input core Dmitry Torokhov
  2024-12-17 21:59 ` [PATCH 0/8] Convert input core to use new cleanup facilities Dmitry Torokhov
  8 siblings, 0 replies; 15+ messages in thread
From: Dmitry Torokhov @ 2024-11-07  7:15 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Hans de Goede; +Cc: linux-input, linux-kernel

Use guard() notation instead of explicitly acquiring and releasing
mutex to simplify the code and ensure that it is released.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/input-poller.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/input/input-poller.c b/drivers/input/input-poller.c
index 688e3cb1c2a0..9c57713a6151 100644
--- a/drivers/input/input-poller.c
+++ b/drivers/input/input-poller.c
@@ -162,7 +162,7 @@ static ssize_t input_dev_set_poll_interval(struct device *dev,
 	if (interval > poller->poll_interval_max)
 		return -EINVAL;
 
-	mutex_lock(&input->mutex);
+	guard(mutex)(&input->mutex);
 
 	poller->poll_interval = interval;
 
@@ -172,8 +172,6 @@ static ssize_t input_dev_set_poll_interval(struct device *dev,
 			input_dev_poller_queue_work(poller);
 	}
 
-	mutex_unlock(&input->mutex);
-
 	return count;
 }
 
-- 
2.47.0.277.g8800431eea-goog


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 8/8] Input: use guard notation in input core
  2024-11-07  7:15 [PATCH 0/8] Convert input core to use new cleanup facilities Dmitry Torokhov
                   ` (6 preceding siblings ...)
  2024-11-07  7:15 ` [PATCH 7/8] Input: poller - convert locking to guard notation Dmitry Torokhov
@ 2024-11-07  7:15 ` Dmitry Torokhov
  2024-12-17 21:59 ` [PATCH 0/8] Convert input core to use new cleanup facilities Dmitry Torokhov
  8 siblings, 0 replies; 15+ messages in thread
From: Dmitry Torokhov @ 2024-11-07  7:15 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Hans de Goede; +Cc: linux-input, linux-kernel

Switch input core to use "guard" notation when acquiring spinlocks and
mutexes to simplify the code and ensure that locks are automatically
released when control leaves critical section.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/input.c | 339 ++++++++++++++++--------------------------
 1 file changed, 131 insertions(+), 208 deletions(-)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index fd9d40286b75..d73231e695f8 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -115,23 +115,23 @@ static void input_pass_values(struct input_dev *dev,
 
 	lockdep_assert_held(&dev->event_lock);
 
-	rcu_read_lock();
+	scoped_guard(rcu) {
+		handle = rcu_dereference(dev->grab);
+		if (handle) {
+			count = handle->handle_events(handle, vals, count);
+			break;
+		}
 
-	handle = rcu_dereference(dev->grab);
-	if (handle) {
-		count = handle->handle_events(handle, vals, count);
-	} else {
-		list_for_each_entry_rcu(handle, &dev->h_list, d_node)
+		list_for_each_entry_rcu(handle, &dev->h_list, d_node) {
 			if (handle->open) {
 				count = handle->handle_events(handle, vals,
 							      count);
 				if (!count)
 					break;
 			}
+		}
 	}
 
-	rcu_read_unlock();
-
 	/* trigger auto repeat for key events */
 	if (test_bit(EV_REP, dev->evbit) && test_bit(EV_KEY, dev->evbit)) {
 		for (v = vals; v != vals + count; v++) {
@@ -390,13 +390,9 @@ void input_handle_event(struct input_dev *dev,
 void input_event(struct input_dev *dev,
 		 unsigned int type, unsigned int code, int value)
 {
-	unsigned long flags;
-
 	if (is_event_supported(type, dev->evbit, EV_MAX)) {
-
-		spin_lock_irqsave(&dev->event_lock, flags);
+		guard(spinlock_irqsave)(&dev->event_lock);
 		input_handle_event(dev, type, code, value);
-		spin_unlock_irqrestore(&dev->event_lock, flags);
 	}
 }
 EXPORT_SYMBOL(input_event);
@@ -417,18 +413,15 @@ void input_inject_event(struct input_handle *handle,
 {
 	struct input_dev *dev = handle->dev;
 	struct input_handle *grab;
-	unsigned long flags;
 
 	if (is_event_supported(type, dev->evbit, EV_MAX)) {
-		spin_lock_irqsave(&dev->event_lock, flags);
+		guard(spinlock_irqsave)(&dev->event_lock);
+		guard(rcu)();
 
-		rcu_read_lock();
 		grab = rcu_dereference(dev->grab);
 		if (!grab || grab == handle)
 			input_handle_event(dev, type, code, value);
-		rcu_read_unlock();
 
-		spin_unlock_irqrestore(&dev->event_lock, flags);
 	}
 }
 EXPORT_SYMBOL(input_inject_event);
@@ -526,22 +519,15 @@ EXPORT_SYMBOL(input_copy_abs);
 int input_grab_device(struct input_handle *handle)
 {
 	struct input_dev *dev = handle->dev;
-	int retval;
 
-	retval = mutex_lock_interruptible(&dev->mutex);
-	if (retval)
-		return retval;
+	scoped_cond_guard(mutex_intr, return -EINTR, &dev->mutex) {
+		if (dev->grab)
+			return -EBUSY;
 
-	if (dev->grab) {
-		retval = -EBUSY;
-		goto out;
+		rcu_assign_pointer(dev->grab, handle);
 	}
 
-	rcu_assign_pointer(dev->grab, handle);
-
- out:
-	mutex_unlock(&dev->mutex);
-	return retval;
+	return 0;
 }
 EXPORT_SYMBOL(input_grab_device);
 
@@ -576,9 +562,8 @@ void input_release_device(struct input_handle *handle)
 {
 	struct input_dev *dev = handle->dev;
 
-	mutex_lock(&dev->mutex);
+	guard(mutex)(&dev->mutex);
 	__input_release_device(handle);
-	mutex_unlock(&dev->mutex);
 }
 EXPORT_SYMBOL(input_release_device);
 
@@ -592,67 +577,57 @@ EXPORT_SYMBOL(input_release_device);
 int input_open_device(struct input_handle *handle)
 {
 	struct input_dev *dev = handle->dev;
-	int retval;
-
-	retval = mutex_lock_interruptible(&dev->mutex);
-	if (retval)
-		return retval;
-
-	if (dev->going_away) {
-		retval = -ENODEV;
-		goto out;
-	}
+	int error;
 
-	handle->open++;
+	scoped_cond_guard(mutex_intr, return -EINTR, &dev->mutex) {
+		if (dev->going_away)
+			return -ENODEV;
 
-	if (handle->handler->passive_observer)
-		goto out;
+		handle->open++;
 
-	if (dev->users++ || dev->inhibited) {
-		/*
-		 * Device is already opened and/or inhibited,
-		 * so we can exit immediately and report success.
-		 */
-		goto out;
-	}
+		if (handle->handler->passive_observer)
+			return 0;
 
-	if (dev->open) {
-		retval = dev->open(dev);
-		if (retval) {
-			dev->users--;
-			handle->open--;
+		if (dev->users++ || dev->inhibited) {
 			/*
-			 * Make sure we are not delivering any more events
-			 * through this handle
+			 * Device is already opened and/or inhibited,
+			 * so we can exit immediately and report success.
 			 */
-			synchronize_rcu();
-			goto out;
+			return 0;
 		}
-	}
 
-	if (dev->poller)
-		input_dev_poller_start(dev->poller);
+		if (dev->open) {
+			error = dev->open(dev);
+			if (error) {
+				dev->users--;
+				handle->open--;
+				/*
+				 * Make sure we are not delivering any more
+				 * events through this handle.
+				 */
+				synchronize_rcu();
+				return error;
+			}
+		}
 
- out:
-	mutex_unlock(&dev->mutex);
-	return retval;
+		if (dev->poller)
+			input_dev_poller_start(dev->poller);
+	}
+
+	return 0;
 }
 EXPORT_SYMBOL(input_open_device);
 
 int input_flush_device(struct input_handle *handle, struct file *file)
 {
 	struct input_dev *dev = handle->dev;
-	int retval;
 
-	retval = mutex_lock_interruptible(&dev->mutex);
-	if (retval)
-		return retval;
-
-	if (dev->flush)
-		retval = dev->flush(dev, file);
+	scoped_cond_guard(mutex_intr, return -EINTR, &dev->mutex) {
+		if (dev->flush)
+			return dev->flush(dev, file);
+	}
 
-	mutex_unlock(&dev->mutex);
-	return retval;
+	return 0;
 }
 EXPORT_SYMBOL(input_flush_device);
 
@@ -667,7 +642,7 @@ void input_close_device(struct input_handle *handle)
 {
 	struct input_dev *dev = handle->dev;
 
-	mutex_lock(&dev->mutex);
+	guard(mutex)(&dev->mutex);
 
 	__input_release_device(handle);
 
@@ -688,8 +663,6 @@ void input_close_device(struct input_handle *handle)
 		 */
 		synchronize_rcu();
 	}
-
-	mutex_unlock(&dev->mutex);
 }
 EXPORT_SYMBOL(input_close_device);
 
@@ -726,11 +699,10 @@ static void input_disconnect_device(struct input_dev *dev)
 	 * not to protect access to dev->going_away but rather to ensure
 	 * that there are no threads in the middle of input_open_device()
 	 */
-	mutex_lock(&dev->mutex);
-	dev->going_away = true;
-	mutex_unlock(&dev->mutex);
+	scoped_guard(mutex, &dev->mutex)
+		dev->going_away = true;
 
-	spin_lock_irq(&dev->event_lock);
+	guard(spinlock_irq)(&dev->event_lock);
 
 	/*
 	 * Simulate keyup events for all pressed keys so that handlers
@@ -743,8 +715,6 @@ static void input_disconnect_device(struct input_dev *dev)
 
 	list_for_each_entry(handle, &dev->h_list, d_node)
 		handle->open = 0;
-
-	spin_unlock_irq(&dev->event_lock);
 }
 
 /**
@@ -901,14 +871,9 @@ static int input_default_setkeycode(struct input_dev *dev,
  */
 int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke)
 {
-	unsigned long flags;
-	int retval;
+	guard(spinlock_irqsave)(&dev->event_lock);
 
-	spin_lock_irqsave(&dev->event_lock, flags);
-	retval = dev->getkeycode(dev, ke);
-	spin_unlock_irqrestore(&dev->event_lock, flags);
-
-	return retval;
+	return dev->getkeycode(dev, ke);
 }
 EXPORT_SYMBOL(input_get_keycode);
 
@@ -923,18 +888,17 @@ EXPORT_SYMBOL(input_get_keycode);
 int input_set_keycode(struct input_dev *dev,
 		      const struct input_keymap_entry *ke)
 {
-	unsigned long flags;
 	unsigned int old_keycode;
-	int retval;
+	int error;
 
 	if (ke->keycode > KEY_MAX)
 		return -EINVAL;
 
-	spin_lock_irqsave(&dev->event_lock, flags);
+	guard(spinlock_irqsave)(&dev->event_lock);
 
-	retval = dev->setkeycode(dev, ke, &old_keycode);
-	if (retval)
-		goto out;
+	error = dev->setkeycode(dev, ke, &old_keycode);
+	if (error)
+		return error;
 
 	/* Make sure KEY_RESERVED did not get enabled. */
 	__clear_bit(KEY_RESERVED, dev->keybit);
@@ -962,10 +926,7 @@ int input_set_keycode(struct input_dev *dev,
 				    EV_SYN, SYN_REPORT, 1);
 	}
 
- out:
-	spin_unlock_irqrestore(&dev->event_lock, flags);
-
-	return retval;
+	return 0;
 }
 EXPORT_SYMBOL(input_set_keycode);
 
@@ -1802,26 +1763,21 @@ static void input_dev_toggle(struct input_dev *dev, bool activate)
  */
 void input_reset_device(struct input_dev *dev)
 {
-	unsigned long flags;
-
-	mutex_lock(&dev->mutex);
-	spin_lock_irqsave(&dev->event_lock, flags);
+	guard(mutex)(&dev->mutex);
+	guard(spinlock_irqsave)(&dev->event_lock);
 
 	input_dev_toggle(dev, true);
 	if (input_dev_release_keys(dev))
 		input_handle_event(dev, EV_SYN, SYN_REPORT, 1);
-
-	spin_unlock_irqrestore(&dev->event_lock, flags);
-	mutex_unlock(&dev->mutex);
 }
 EXPORT_SYMBOL(input_reset_device);
 
 static int input_inhibit_device(struct input_dev *dev)
 {
-	mutex_lock(&dev->mutex);
+	guard(mutex)(&dev->mutex);
 
 	if (dev->inhibited)
-		goto out;
+		return 0;
 
 	if (dev->users) {
 		if (dev->close)
@@ -1830,54 +1786,50 @@ static int input_inhibit_device(struct input_dev *dev)
 			input_dev_poller_stop(dev->poller);
 	}
 
-	spin_lock_irq(&dev->event_lock);
-	input_mt_release_slots(dev);
-	input_dev_release_keys(dev);
-	input_handle_event(dev, EV_SYN, SYN_REPORT, 1);
-	input_dev_toggle(dev, false);
-	spin_unlock_irq(&dev->event_lock);
+	scoped_guard(spinlock_irq, &dev->event_lock) {
+		input_mt_release_slots(dev);
+		input_dev_release_keys(dev);
+		input_handle_event(dev, EV_SYN, SYN_REPORT, 1);
+		input_dev_toggle(dev, false);
+	}
 
 	dev->inhibited = true;
 
-out:
-	mutex_unlock(&dev->mutex);
 	return 0;
 }
 
 static int input_uninhibit_device(struct input_dev *dev)
 {
-	int ret = 0;
+	int error;
 
-	mutex_lock(&dev->mutex);
+	guard(mutex)(&dev->mutex);
 
 	if (!dev->inhibited)
-		goto out;
+		return 0;
 
 	if (dev->users) {
 		if (dev->open) {
-			ret = dev->open(dev);
-			if (ret)
-				goto out;
+			error = dev->open(dev);
+			if (error)
+				return error;
 		}
 		if (dev->poller)
 			input_dev_poller_start(dev->poller);
 	}
 
 	dev->inhibited = false;
-	spin_lock_irq(&dev->event_lock);
-	input_dev_toggle(dev, true);
-	spin_unlock_irq(&dev->event_lock);
 
-out:
-	mutex_unlock(&dev->mutex);
-	return ret;
+	scoped_guard(spinlock_irq, &dev->event_lock)
+		input_dev_toggle(dev, true);
+
+	return 0;
 }
 
 static int input_dev_suspend(struct device *dev)
 {
 	struct input_dev *input_dev = to_input_dev(dev);
 
-	spin_lock_irq(&input_dev->event_lock);
+	guard(spinlock_irq)(&input_dev->event_lock);
 
 	/*
 	 * Keys that are pressed now are unlikely to be
@@ -1889,8 +1841,6 @@ static int input_dev_suspend(struct device *dev)
 	/* Turn off LEDs and sounds, if any are active. */
 	input_dev_toggle(input_dev, false);
 
-	spin_unlock_irq(&input_dev->event_lock);
-
 	return 0;
 }
 
@@ -1898,13 +1848,11 @@ static int input_dev_resume(struct device *dev)
 {
 	struct input_dev *input_dev = to_input_dev(dev);
 
-	spin_lock_irq(&input_dev->event_lock);
+	guard(spinlock_irq)(&input_dev->event_lock);
 
 	/* Restore state of LEDs and sounds, if any were active. */
 	input_dev_toggle(input_dev, true);
 
-	spin_unlock_irq(&input_dev->event_lock);
-
 	return 0;
 }
 
@@ -1912,7 +1860,7 @@ static int input_dev_freeze(struct device *dev)
 {
 	struct input_dev *input_dev = to_input_dev(dev);
 
-	spin_lock_irq(&input_dev->event_lock);
+	guard(spinlock_irq)(&input_dev->event_lock);
 
 	/*
 	 * Keys that are pressed now are unlikely to be
@@ -1921,8 +1869,6 @@ static int input_dev_freeze(struct device *dev)
 	if (input_dev_release_keys(input_dev))
 		input_handle_event(input_dev, EV_SYN, SYN_REPORT, 1);
 
-	spin_unlock_irq(&input_dev->event_lock);
-
 	return 0;
 }
 
@@ -1930,13 +1876,11 @@ static int input_dev_poweroff(struct device *dev)
 {
 	struct input_dev *input_dev = to_input_dev(dev);
 
-	spin_lock_irq(&input_dev->event_lock);
+	guard(spinlock_irq)(&input_dev->event_lock);
 
 	/* Turn off LEDs and sounds, if any are active. */
 	input_dev_toggle(input_dev, false);
 
-	spin_unlock_irq(&input_dev->event_lock);
-
 	return 0;
 }
 
@@ -2277,18 +2221,16 @@ static void __input_unregister_device(struct input_dev *dev)
 
 	input_disconnect_device(dev);
 
-	mutex_lock(&input_mutex);
-
-	list_for_each_entry_safe(handle, next, &dev->h_list, d_node)
-		handle->handler->disconnect(handle);
-	WARN_ON(!list_empty(&dev->h_list));
+	scoped_guard(mutex, &input_mutex) {
+		list_for_each_entry_safe(handle, next, &dev->h_list, d_node)
+			handle->handler->disconnect(handle);
+		WARN_ON(!list_empty(&dev->h_list));
 
-	del_timer_sync(&dev->timer);
-	list_del_init(&dev->node);
+		del_timer_sync(&dev->timer);
+		list_del_init(&dev->node);
 
-	input_wakeup_procfs_readers();
-
-	mutex_unlock(&input_mutex);
+		input_wakeup_procfs_readers();
+	}
 
 	device_del(&dev->dev);
 }
@@ -2311,9 +2253,8 @@ static void devm_input_device_unregister(struct device *dev, void *res)
 static void input_repeat_key(struct timer_list *t)
 {
 	struct input_dev *dev = from_timer(dev, t, timer);
-	unsigned long flags;
 
-	spin_lock_irqsave(&dev->event_lock, flags);
+	guard(spinlock_irqsave)(&dev->event_lock);
 
 	if (!dev->inhibited &&
 	    test_bit(dev->repeat_key, dev->key) &&
@@ -2327,8 +2268,6 @@ static void input_repeat_key(struct timer_list *t)
 			mod_timer(&dev->timer, jiffies +
 					msecs_to_jiffies(dev->rep[REP_PERIOD]));
 	}
-
-	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
 /**
@@ -2373,10 +2312,10 @@ static int input_device_tune_vals(struct input_dev *dev)
 	if (!vals)
 		return -ENOMEM;
 
-	spin_lock_irq(&dev->event_lock);
-	dev->max_vals = max_vals;
-	swap(dev->vals, vals);
-	spin_unlock_irq(&dev->event_lock);
+	scoped_guard(spinlock_irq, &dev->event_lock) {
+		dev->max_vals = max_vals;
+		swap(dev->vals, vals);
+	}
 
 	/* Because of swap() above, this frees the old vals memory */
 	kfree(vals);
@@ -2468,18 +2407,15 @@ int input_register_device(struct input_dev *dev)
 		path ? path : "N/A");
 	kfree(path);
 
-	error = mutex_lock_interruptible(&input_mutex);
-	if (error)
-		goto err_device_del;
+	error = -EINTR;
+	scoped_cond_guard(mutex_intr, goto err_device_del, &input_mutex) {
+		list_add_tail(&dev->node, &input_dev_list);
 
-	list_add_tail(&dev->node, &input_dev_list);
+		list_for_each_entry(handler, &input_handler_list, node)
+			input_attach_handler(dev, handler);
 
-	list_for_each_entry(handler, &input_handler_list, node)
-		input_attach_handler(dev, handler);
-
-	input_wakeup_procfs_readers();
-
-	mutex_unlock(&input_mutex);
+		input_wakeup_procfs_readers();
+	}
 
 	if (dev->devres_managed) {
 		dev_dbg(dev->dev.parent, "%s: registering %s with devres.\n",
@@ -2559,20 +2495,17 @@ int input_register_handler(struct input_handler *handler)
 	if (error)
 		return error;
 
-	INIT_LIST_HEAD(&handler->h_list);
+	scoped_cond_guard(mutex_intr, return -EINTR, &input_mutex) {
+		INIT_LIST_HEAD(&handler->h_list);
 
-	error = mutex_lock_interruptible(&input_mutex);
-	if (error)
-		return error;
-
-	list_add_tail(&handler->node, &input_handler_list);
+		list_add_tail(&handler->node, &input_handler_list);
 
-	list_for_each_entry(dev, &input_dev_list, node)
-		input_attach_handler(dev, handler);
+		list_for_each_entry(dev, &input_dev_list, node)
+			input_attach_handler(dev, handler);
 
-	input_wakeup_procfs_readers();
+		input_wakeup_procfs_readers();
+	}
 
-	mutex_unlock(&input_mutex);
 	return 0;
 }
 EXPORT_SYMBOL(input_register_handler);
@@ -2588,7 +2521,7 @@ void input_unregister_handler(struct input_handler *handler)
 {
 	struct input_handle *handle, *next;
 
-	mutex_lock(&input_mutex);
+	guard(mutex)(&input_mutex);
 
 	list_for_each_entry_safe(handle, next, &handler->h_list, h_node)
 		handler->disconnect(handle);
@@ -2597,8 +2530,6 @@ void input_unregister_handler(struct input_handler *handler)
 	list_del_init(&handler->node);
 
 	input_wakeup_procfs_readers();
-
-	mutex_unlock(&input_mutex);
 }
 EXPORT_SYMBOL(input_unregister_handler);
 
@@ -2618,19 +2549,17 @@ int input_handler_for_each_handle(struct input_handler *handler, void *data,
 				  int (*fn)(struct input_handle *, void *))
 {
 	struct input_handle *handle;
-	int retval = 0;
+	int retval;
 
-	rcu_read_lock();
+	guard(rcu)();
 
 	list_for_each_entry_rcu(handle, &handler->h_list, h_node) {
 		retval = fn(handle, data);
 		if (retval)
-			break;
+			return retval;
 	}
 
-	rcu_read_unlock();
-
-	return retval;
+	return 0;
 }
 EXPORT_SYMBOL(input_handler_for_each_handle);
 
@@ -2718,27 +2647,22 @@ int input_register_handle(struct input_handle *handle)
 {
 	struct input_handler *handler = handle->handler;
 	struct input_dev *dev = handle->dev;
-	int error;
 
 	input_handle_setup_event_handler(handle);
 	/*
 	 * We take dev->mutex here to prevent race with
 	 * input_release_device().
 	 */
-	error = mutex_lock_interruptible(&dev->mutex);
-	if (error)
-		return error;
-
-	/*
-	 * Filters go to the head of the list, normal handlers
-	 * to the tail.
-	 */
-	if (handler->filter)
-		list_add_rcu(&handle->d_node, &dev->h_list);
-	else
-		list_add_tail_rcu(&handle->d_node, &dev->h_list);
-
-	mutex_unlock(&dev->mutex);
+	scoped_cond_guard(mutex_intr, return -EINTR, &dev->mutex) {
+		/*
+		 * Filters go to the head of the list, normal handlers
+		 * to the tail.
+		 */
+		if (handler->filter)
+			list_add_rcu(&handle->d_node, &dev->h_list);
+		else
+			list_add_tail_rcu(&handle->d_node, &dev->h_list);
+	}
 
 	/*
 	 * Since we are supposed to be called from ->connect()
@@ -2774,9 +2698,8 @@ void input_unregister_handle(struct input_handle *handle)
 	/*
 	 * Take dev->mutex to prevent race with input_release_device().
 	 */
-	mutex_lock(&dev->mutex);
-	list_del_rcu(&handle->d_node);
-	mutex_unlock(&dev->mutex);
+	scoped_guard(mutex, &dev->mutex)
+		list_del_rcu(&handle->d_node);
 
 	synchronize_rcu();
 }
-- 
2.47.0.277.g8800431eea-goog


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/8] Convert input core to use new cleanup facilities
  2024-11-07  7:15 [PATCH 0/8] Convert input core to use new cleanup facilities Dmitry Torokhov
                   ` (7 preceding siblings ...)
  2024-11-07  7:15 ` [PATCH 8/8] Input: use guard notation in input core Dmitry Torokhov
@ 2024-12-17 21:59 ` Dmitry Torokhov
  8 siblings, 0 replies; 15+ messages in thread
From: Dmitry Torokhov @ 2024-12-17 21:59 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Hans de Goede; +Cc: linux-input, linux-kernel

On Wed, Nov 06, 2024 at 11:15:27PM -0800, Dmitry Torokhov wrote:
> Hi,
> 
> This series converts input core (but not input handlers such as evdev,
> joydev, etc) to use new __free() and guard() cleanup facilities that
> simplify the code and ensure that all resources are released
> appropriately.
> 
> Input handlers will be converted separately later.

Since there were no objections applied for the 6.14 merge window.

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/8] Input: ff-core - make use of __free() cleanup facility
       [not found]   ` <CGME20241220123701eucas1p23125e0738985ffe35cbe9624dff08972@eucas1p2.samsung.com>
@ 2024-12-20 12:36     ` Marek Szyprowski
  2024-12-20 17:22       ` Dmitry Torokhov
  0 siblings, 1 reply; 15+ messages in thread
From: Marek Szyprowski @ 2024-12-20 12:36 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina, Benjamin Tissoires, Hans de Goede
  Cc: linux-input, linux-kernel, 'Linux Samsung SOC'

On 07.11.2024 08:15, Dmitry Torokhov wrote:
> Annotate allocated memory with __free(kfree) to simplify the code and
> make sure memory is released appropriately.
>
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
>   drivers/input/ff-core.c | 19 ++++++-------------
>   1 file changed, 6 insertions(+), 13 deletions(-)

This patch landed in linux-next as commit 5203b3a18c1b ("Input: ff-core 
- make use of __free() cleanup facility"). In my tests I found that it 
causes the following kernel panic on some of my test boards. Reverting 
it, together with fd5ba0501d38 ("Input: ff-memless - make use of 
__free() cleanup facility") on top of next-20241220 fixes this panic 
issue. Here is the relevant log captured on Samsung Exynos4412 ARM 
32bit-based Trats2 board:

8<--- cut here ---
Unable to handle kernel NULL pointer dereference at virtual address 
00000024 when read
[00000024] *pgd=00000000
Internal error: Oops: 5 [#1] PREEMPT SMP ARM
Modules linked in:
CPU: 1 UID: 0 PID: 1 Comm: swapper/0 Not tainted 
6.13.0-rc3-next-20241220 #15500
Hardware name: Samsung Exynos (Flattened Device Tree)
PC is at input_ff_create+0xa0/0x13c
LR is at input_ff_create+0xb8/0x13c
pc : [<c08d7e14>]    lr : [<c08d7e2c>]    psr: 80000013
...
Process swapper/0 (pid: 1, stack limit = 0x(ptrval))
...
Call trace:
  input_ff_create from input_ff_create_memless+0x8c/0x160
  input_ff_create_memless from max77693_haptic_probe+0x1b0/0x284
  max77693_haptic_probe from platform_probe+0x80/0xc0
  platform_probe from really_probe+0x154/0x3ac
  really_probe from __driver_probe_device+0xa0/0x1d4
  __driver_probe_device from driver_probe_device+0x30/0xd0
  driver_probe_device from __driver_attach+0x10c/0x190
  __driver_attach from bus_for_each_dev+0x60/0xb4
  bus_for_each_dev from bus_add_driver+0xe0/0x220
  bus_add_driver from driver_register+0x7c/0x118
  driver_register from do_one_initcall+0x6c/0x328
  do_one_initcall from kernel_init_freeable+0x1c8/0x218
  kernel_init_freeable from kernel_init+0x1c/0x12c
  kernel_init from ret_from_fork+0x14/0x28
Exception stack(0xf0845fb0 to 0xf0845ff8)
...
---[ end trace 0000000000000000 ]---
Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
---[ end Kernel panic - not syncing: Attempted to kill init! 
exitcode=0x0000000b ]---

> diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c
> index eb01bcb69d00..a235d2eb6b31 100644
> --- a/drivers/input/ff-core.c
> +++ b/drivers/input/ff-core.c
> @@ -290,8 +290,6 @@ EXPORT_SYMBOL_GPL(input_ff_event);
>    */
>   int input_ff_create(struct input_dev *dev, unsigned int max_effects)
>   {
> -	struct ff_device *ff;
> -	size_t ff_dev_size;
>   	int i;
>   
>   	if (!max_effects) {
> @@ -304,25 +302,20 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects)
>   		return -EINVAL;
>   	}
>   
> -	ff_dev_size = struct_size(ff, effect_owners, max_effects);
> -	if (ff_dev_size == SIZE_MAX) /* overflow */
> -		return -EINVAL;
> -
> -	ff = kzalloc(ff_dev_size, GFP_KERNEL);
> +	struct ff_device *ff __free(kfree) =
> +		kzalloc(struct_size(ff, effect_owners, max_effects),
> +			GFP_KERNEL);
>   	if (!ff)
>   		return -ENOMEM;
>   
> -	ff->effects = kcalloc(max_effects, sizeof(struct ff_effect),
> -			      GFP_KERNEL);
> -	if (!ff->effects) {
> -		kfree(ff);
> +	ff->effects = kcalloc(max_effects, sizeof(*ff->effects), GFP_KERNEL);
> +	if (!ff->effects)
>   		return -ENOMEM;
> -	}
>   
>   	ff->max_effects = max_effects;
>   	mutex_init(&ff->mutex);
>   
> -	dev->ff = ff;
> +	dev->ff = no_free_ptr(ff);
>   	dev->flush = input_ff_flush;
>   	dev->event = input_ff_event;
>   	__set_bit(EV_FF, dev->evbit);

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/8] Input: ff-core - make use of __free() cleanup facility
  2024-12-20 12:36     ` Marek Szyprowski
@ 2024-12-20 17:22       ` Dmitry Torokhov
  2024-12-20 17:38         ` Marek Szyprowski
  0 siblings, 1 reply; 15+ messages in thread
From: Dmitry Torokhov @ 2024-12-20 17:22 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Jiri Kosina, Benjamin Tissoires, Hans de Goede, linux-input,
	linux-kernel, 'Linux Samsung SOC'

On Fri, Dec 20, 2024 at 01:36:59PM +0100, Marek Szyprowski wrote:
> On 07.11.2024 08:15, Dmitry Torokhov wrote:
> > Annotate allocated memory with __free(kfree) to simplify the code and
> > make sure memory is released appropriately.
> >
> > Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > ---
> >   drivers/input/ff-core.c | 19 ++++++-------------
> >   1 file changed, 6 insertions(+), 13 deletions(-)
> 
> This patch landed in linux-next as commit 5203b3a18c1b ("Input: ff-core 
> - make use of __free() cleanup facility"). In my tests I found that it 
> causes the following kernel panic on some of my test boards. Reverting 
> it, together with fd5ba0501d38 ("Input: ff-memless - make use of 
> __free() cleanup facility") on top of next-20241220 fixes this panic 
> issue.

Gah, I fixed this once and then undid it for some reason. I think the
following should fix the problem:


diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c
index a235d2eb6b31..c25e05eeb8e5 100644
--- a/drivers/input/ff-core.c
+++ b/drivers/input/ff-core.c
@@ -315,7 +315,6 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects)
 	ff->max_effects = max_effects;
 	mutex_init(&ff->mutex);
 
-	dev->ff = no_free_ptr(ff);
 	dev->flush = input_ff_flush;
 	dev->event = input_ff_event;
 	__set_bit(EV_FF, dev->evbit);
@@ -328,6 +327,7 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects)
 	if (test_bit(FF_PERIODIC, ff->ffbit))
 		__set_bit(FF_RUMBLE, dev->ffbit);
 
+	dev->ff = no_free_ptr(ff);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(input_ff_create);
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index 0bbeceb35545..e9120ba6bae0 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -524,7 +524,6 @@ int input_ff_create_memless(struct input_dev *dev, void *data,
 		return error;
 
 	ff = dev->ff;
-	ff->private = no_free_ptr(ml);
 	ff->upload = ml_ff_upload;
 	ff->playback = ml_ff_playback;
 	ff->set_gain = ml_ff_set_gain;
@@ -541,6 +540,8 @@ int input_ff_create_memless(struct input_dev *dev, void *data,
 	for (i = 0; i < FF_MEMLESS_EFFECTS; i++)
 		ml->states[i].effect = &ff->effects[i];
 
+	ff->private = no_free_ptr(ml);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(input_ff_create_memless);


Thanks.

-- 
Dmitry

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/8] Input: ff-core - make use of __free() cleanup facility
  2024-12-20 17:22       ` Dmitry Torokhov
@ 2024-12-20 17:38         ` Marek Szyprowski
  2024-12-20 17:39           ` Dmitry Torokhov
  0 siblings, 1 reply; 15+ messages in thread
From: Marek Szyprowski @ 2024-12-20 17:38 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Jiri Kosina, Benjamin Tissoires, Hans de Goede, linux-input,
	linux-kernel, 'Linux Samsung SOC'

On 20.12.2024 18:22, Dmitry Torokhov wrote:
> On Fri, Dec 20, 2024 at 01:36:59PM +0100, Marek Szyprowski wrote:
>> On 07.11.2024 08:15, Dmitry Torokhov wrote:
>>> Annotate allocated memory with __free(kfree) to simplify the code and
>>> make sure memory is released appropriately.
>>>
>>> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
>>> ---
>>>    drivers/input/ff-core.c | 19 ++++++-------------
>>>    1 file changed, 6 insertions(+), 13 deletions(-)
>> This patch landed in linux-next as commit 5203b3a18c1b ("Input: ff-core
>> - make use of __free() cleanup facility"). In my tests I found that it
>> causes the following kernel panic on some of my test boards. Reverting
>> it, together with fd5ba0501d38 ("Input: ff-memless - make use of
>> __free() cleanup facility") on top of next-20241220 fixes this panic
>> issue.
> Gah, I fixed this once and then undid it for some reason. I think the
> following should fix the problem:

Yep, this fixes the problem. Feel free to add:

Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>


> diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c
> index a235d2eb6b31..c25e05eeb8e5 100644
> --- a/drivers/input/ff-core.c
> +++ b/drivers/input/ff-core.c
> @@ -315,7 +315,6 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects)
>   	ff->max_effects = max_effects;
>   	mutex_init(&ff->mutex);
>   
> -	dev->ff = no_free_ptr(ff);
>   	dev->flush = input_ff_flush;
>   	dev->event = input_ff_event;
>   	__set_bit(EV_FF, dev->evbit);
> @@ -328,6 +327,7 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects)
>   	if (test_bit(FF_PERIODIC, ff->ffbit))
>   		__set_bit(FF_RUMBLE, dev->ffbit);
>   
> +	dev->ff = no_free_ptr(ff);
>   	return 0;
>   }
>   EXPORT_SYMBOL_GPL(input_ff_create);
> diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
> index 0bbeceb35545..e9120ba6bae0 100644
> --- a/drivers/input/ff-memless.c
> +++ b/drivers/input/ff-memless.c
> @@ -524,7 +524,6 @@ int input_ff_create_memless(struct input_dev *dev, void *data,
>   		return error;
>   
>   	ff = dev->ff;
> -	ff->private = no_free_ptr(ml);
>   	ff->upload = ml_ff_upload;
>   	ff->playback = ml_ff_playback;
>   	ff->set_gain = ml_ff_set_gain;
> @@ -541,6 +540,8 @@ int input_ff_create_memless(struct input_dev *dev, void *data,
>   	for (i = 0; i < FF_MEMLESS_EFFECTS; i++)
>   		ml->states[i].effect = &ff->effects[i];
>   
> +	ff->private = no_free_ptr(ml);
> +
>   	return 0;
>   }
>   EXPORT_SYMBOL_GPL(input_ff_create_memless);
>
>
> Thanks.
>
Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/8] Input: ff-core - make use of __free() cleanup facility
  2024-12-20 17:38         ` Marek Szyprowski
@ 2024-12-20 17:39           ` Dmitry Torokhov
  2024-12-20 17:50             ` Marek Szyprowski
  0 siblings, 1 reply; 15+ messages in thread
From: Dmitry Torokhov @ 2024-12-20 17:39 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Jiri Kosina, Benjamin Tissoires, Hans de Goede, linux-input,
	linux-kernel, 'Linux Samsung SOC'

On Fri, Dec 20, 2024 at 06:38:04PM +0100, Marek Szyprowski wrote:
> On 20.12.2024 18:22, Dmitry Torokhov wrote:
> > On Fri, Dec 20, 2024 at 01:36:59PM +0100, Marek Szyprowski wrote:
> >> On 07.11.2024 08:15, Dmitry Torokhov wrote:
> >>> Annotate allocated memory with __free(kfree) to simplify the code and
> >>> make sure memory is released appropriately.
> >>>
> >>> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> >>> ---
> >>>    drivers/input/ff-core.c | 19 ++++++-------------
> >>>    1 file changed, 6 insertions(+), 13 deletions(-)
> >> This patch landed in linux-next as commit 5203b3a18c1b ("Input: ff-core
> >> - make use of __free() cleanup facility"). In my tests I found that it
> >> causes the following kernel panic on some of my test boards. Reverting
> >> it, together with fd5ba0501d38 ("Input: ff-memless - make use of
> >> __free() cleanup facility") on top of next-20241220 fixes this panic
> >> issue.
> > Gah, I fixed this once and then undid it for some reason. I think the
> > following should fix the problem:
> 
> Yep, this fixes the problem. Feel free to add:
> 
> Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>

Thank you for the report and testing. Do you mind if I fold these fixes
into original patches?

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/8] Input: ff-core - make use of __free() cleanup facility
  2024-12-20 17:39           ` Dmitry Torokhov
@ 2024-12-20 17:50             ` Marek Szyprowski
  0 siblings, 0 replies; 15+ messages in thread
From: Marek Szyprowski @ 2024-12-20 17:50 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Jiri Kosina, Benjamin Tissoires, Hans de Goede, linux-input,
	linux-kernel, 'Linux Samsung SOC'

On 20.12.2024 18:39, Dmitry Torokhov wrote:
> On Fri, Dec 20, 2024 at 06:38:04PM +0100, Marek Szyprowski wrote:
>> On 20.12.2024 18:22, Dmitry Torokhov wrote:
>>> On Fri, Dec 20, 2024 at 01:36:59PM +0100, Marek Szyprowski wrote:
>>>> On 07.11.2024 08:15, Dmitry Torokhov wrote:
>>>>> Annotate allocated memory with __free(kfree) to simplify the code and
>>>>> make sure memory is released appropriately.
>>>>>
>>>>> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
>>>>> ---
>>>>>     drivers/input/ff-core.c | 19 ++++++-------------
>>>>>     1 file changed, 6 insertions(+), 13 deletions(-)
>>>> This patch landed in linux-next as commit 5203b3a18c1b ("Input: ff-core
>>>> - make use of __free() cleanup facility"). In my tests I found that it
>>>> causes the following kernel panic on some of my test boards. Reverting
>>>> it, together with fd5ba0501d38 ("Input: ff-memless - make use of
>>>> __free() cleanup facility") on top of next-20241220 fixes this panic
>>>> issue.
>>> Gah, I fixed this once and then undid it for some reason. I think the
>>> following should fix the problem:
>> Yep, this fixes the problem. Feel free to add:
>>
>> Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
>> Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Thank you for the report and testing. Do you mind if I fold these fixes
> into original patches?

Go ahead, no problem for me.

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2024-12-20 17:50 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-07  7:15 [PATCH 0/8] Convert input core to use new cleanup facilities Dmitry Torokhov
2024-11-07  7:15 ` [PATCH 1/8] Input: ff-core - convert locking to guard notation Dmitry Torokhov
2024-11-07  7:15 ` [PATCH 2/8] Input: ff-core - make use of __free() cleanup facility Dmitry Torokhov
     [not found]   ` <CGME20241220123701eucas1p23125e0738985ffe35cbe9624dff08972@eucas1p2.samsung.com>
2024-12-20 12:36     ` Marek Szyprowski
2024-12-20 17:22       ` Dmitry Torokhov
2024-12-20 17:38         ` Marek Szyprowski
2024-12-20 17:39           ` Dmitry Torokhov
2024-12-20 17:50             ` Marek Szyprowski
2024-11-07  7:15 ` [PATCH 3/8] Input: ff-memless - convert locking to guard notation Dmitry Torokhov
2024-11-07  7:15 ` [PATCH 4/8] Input: ff-memless - make use of __free() cleanup facility Dmitry Torokhov
2024-11-07  7:15 ` [PATCH 5/8] Input: mt - convert locking to guard notation Dmitry Torokhov
2024-11-07  7:15 ` [PATCH 6/8] Input: mt - make use of __free() cleanup facility Dmitry Torokhov
2024-11-07  7:15 ` [PATCH 7/8] Input: poller - convert locking to guard notation Dmitry Torokhov
2024-11-07  7:15 ` [PATCH 8/8] Input: use guard notation in input core Dmitry Torokhov
2024-12-17 21:59 ` [PATCH 0/8] Convert input core to use new cleanup facilities Dmitry Torokhov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).