Make cyclic_register() return error code, 0 in case of success, -EALREADY in case the called attempts to re-register already registered struct cyclic_info. The re-registration would lead to corruption of gd->cyclic_list because the re-registration would memset() one of its nodes, prevent that. Unregister only initialized struct cyclic_info.
Signed-off-by: Marek Vasut <[email protected]> --- Cc: Aaron Williams <[email protected]> Cc: Anatolij Gustschin <[email protected]> Cc: Angelo Dureghello <[email protected]> Cc: Christian Marangi <[email protected]> Cc: Devarsh Thakkar <[email protected]> Cc: Heinrich Schuchardt <[email protected]> Cc: Jaehoon Chung <[email protected]> Cc: Michael Polyntsov <[email protected]> Cc: Michael Trimarchi <[email protected]> Cc: Nikhil M Jain <[email protected]> Cc: Peng Fan <[email protected]> Cc: Peter Robinson <[email protected]> Cc: Rasmus Villemoes <[email protected]> Cc: Ronald Wahl <[email protected]> Cc: Simon Glass <[email protected]> Cc: Stefan Roese <[email protected]> Cc: Tim Harvey <[email protected]> Cc: Tom Rini <[email protected]> Cc: [email protected] --- common/cyclic.c | 14 +++++++++++--- include/cyclic.h | 9 ++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/common/cyclic.c b/common/cyclic.c index 196797fd61e..53156a704cc 100644 --- a/common/cyclic.c +++ b/common/cyclic.c @@ -27,9 +27,13 @@ struct hlist_head *cyclic_get_list(void) return (struct hlist_head *)&gd->cyclic_list; } -void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func, - uint64_t delay_us, const char *name) +int cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func, + uint64_t delay_us, const char *name) { + /* Reassignment of function would corrupt cyclic list, exit */ + if (cyclic->func) + return -EALREADY; + memset(cyclic, 0, sizeof(*cyclic)); /* Store values in struct */ @@ -38,11 +42,15 @@ void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func, cyclic->delay_us = delay_us; cyclic->start_time_us = timer_get_us(); hlist_add_head(&cyclic->list, cyclic_get_list()); + + return 0; } void cyclic_unregister(struct cyclic_info *cyclic) { - hlist_del(&cyclic->list); + /* Unregister only initialized struct cyclic_info */ + if (cyclic->func) + hlist_del(&cyclic->list); } static void cyclic_run(void) diff --git a/include/cyclic.h b/include/cyclic.h index c6c463d68e9..c86ac407332 100644 --- a/include/cyclic.h +++ b/include/cyclic.h @@ -60,8 +60,10 @@ typedef void (*cyclic_func_t)(struct cyclic_info *c); * The function @func will be called with @cyclic as its * argument. @cyclic will usually be embedded in some device-specific * structure, which the callback can retrieve using container_of(). + * + * @return 0 on success, -EALREADY on repeated registration, -ve otherwise */ -void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func, +int cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func, uint64_t delay_us, const char *name); /** @@ -89,9 +91,10 @@ struct hlist_head *cyclic_get_list(void); #else -static inline void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func, - uint64_t delay_us, const char *name) +static inline int cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func, + uint64_t delay_us, const char *name) { + return 0; } static inline void cyclic_unregister(struct cyclic_info *cyclic) -- 2.45.2

