diff options
author | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2021-12-30 18:02:50 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-12-30 19:44:06 +0300 |
commit | c18e2760308e30f007fa24b558b87c39d7e86ff1 (patch) | |
tree | ae57aa609914f9df5aebc50dd3a1a11238a6ac47 /include/linux/counter.h | |
parent | e152833b2c97b043bdc5f650eda2f432cf1a21a3 (diff) | |
download | linux-c18e2760308e30f007fa24b558b87c39d7e86ff1.tar.xz |
counter: Provide alternative counter registration functions
The current implementation gets device lifetime tracking wrong. The
problem is that allocation of struct counter_device is controlled by the
individual drivers but this structure contains a struct device that
might have to live longer than a driver is bound. As a result a command
sequence like:
{ sleep 5; echo bang; } > /dev/counter0 &
sleep 1;
echo 40000000.timer:counter > /sys/bus/platform/drivers/stm32-timer-counter/unbind
can keep a reference to the struct device and unbinding results in
freeing the memory occupied by this device resulting in an oops.
This commit provides two new functions (plus some helpers):
- counter_alloc() to allocate a struct counter_device that is
automatically freed once the embedded struct device is released
- counter_add() to register such a device.
Note that this commit doesn't fix any issues, all drivers have to be
converted to these new functions to correct the lifetime problems.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Link: https://lore.kernel.org/r/20211230150300.72196-14-u.kleine-koenig@pengutronix.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'include/linux/counter.h')
-rw-r--r-- | include/linux/counter.h | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/include/linux/counter.h b/include/linux/counter.h index 627f1757f6bb..ed8d5820f0d1 100644 --- a/include/linux/counter.h +++ b/include/linux/counter.h @@ -327,14 +327,29 @@ struct counter_device { spinlock_t events_in_lock; struct mutex events_out_lock; struct mutex ops_exist_lock; + + /* + * This can go away once all drivers are converted to + * counter_alloc()/counter_add(). + */ + bool legacy_device; }; void *counter_priv(const struct counter_device *const counter); int counter_register(struct counter_device *const counter); + +struct counter_device *counter_alloc(size_t sizeof_priv); +void counter_put(struct counter_device *const counter); +int counter_add(struct counter_device *const counter); + void counter_unregister(struct counter_device *const counter); int devm_counter_register(struct device *dev, struct counter_device *const counter); +struct counter_device *devm_counter_alloc(struct device *dev, + size_t sizeof_priv); +int devm_counter_add(struct device *dev, + struct counter_device *const counter); void counter_push_event(struct counter_device *const counter, const u8 event, const u8 channel); |