
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 marek.vasut+renesas@mailbox.org --- Cc: Aaron Williams awilliams@marvell.com Cc: Anatolij Gustschin agust@denx.de Cc: Angelo Dureghello angelo@kernel-space.org Cc: Christian Marangi ansuelsmth@gmail.com Cc: Devarsh Thakkar devarsht@ti.com Cc: Heinrich Schuchardt xypron.glpk@gmx.de Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Michael Polyntsov michael.polyntsov@iopsys.eu Cc: Michael Trimarchi michael@amarulasolutions.com Cc: Nikhil M Jain n-jain1@ti.com Cc: Peng Fan peng.fan@nxp.com Cc: Peter Robinson pbrobinson@gmail.com Cc: Rasmus Villemoes rasmus.villemoes@prevas.dk Cc: Ronald Wahl ronald.wahl@legrand.com Cc: Simon Glass sjg@chromium.org Cc: Stefan Roese sr@denx.de Cc: Tim Harvey tharvey@gateworks.com Cc: Tom Rini trini@konsulko.com Cc: u-boot@lists.denx.de --- 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)