summaryrefslogtreecommitdiff
path: root/drivers/input/ff-memless.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/ff-memless.c')
-rw-r--r--drivers/input/ff-memless.c49
1 files changed, 19 insertions, 30 deletions
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index 2743ed4656e4..e0c1c61aae71 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Force feedback support for memoryless devices
*
@@ -5,26 +6,11 @@
* Copyright (c) 2006 Dmitry Torokhov <dtor@mail.ru>
*/
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
/* #define DEBUG */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/export.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/module.h>
@@ -151,7 +137,7 @@ static void ml_schedule_timer(struct ml_device *ml)
if (!events) {
pr_debug("no actions\n");
- del_timer(&ml->timer);
+ timer_delete(&ml->timer);
} else {
pr_debug("timer set\n");
mod_timer(&ml->timer, earliest);
@@ -414,15 +400,13 @@ static void ml_play_effects(struct ml_device *ml)
static void ml_effect_timer(struct timer_list *t)
{
- struct ml_device *ml = from_timer(ml, t, timer);
+ struct ml_device *ml = timer_container_of(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);
}
/*
@@ -480,7 +464,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);
@@ -492,8 +476,6 @@ static int ml_ff_upload(struct input_dev *dev,
ml_schedule_timer(ml);
}
- spin_unlock_irq(&dev->event_lock);
-
return 0;
}
@@ -501,6 +483,15 @@ static void ml_ff_destroy(struct ff_device *ff)
{
struct ml_device *ml = ff->private;
+ /*
+ * Even though we stop all playing effects when tearing down
+ * an input device (via input_device_flush() that calls into
+ * input_ff_flush() that stops and erases all effects), we
+ * do not actually stop the timer, and therefore we should
+ * do it here.
+ */
+ timer_delete_sync(&ml->timer);
+
kfree(ml->private);
}
@@ -513,12 +504,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;
@@ -531,13 +521,10 @@ 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->upload = ml_ff_upload;
ff->playback = ml_ff_playback;
ff->set_gain = ml_ff_set_gain;
@@ -554,6 +541,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);