On 07/08/2019 10:46, Geert Uytterhoeven wrote: > Fix various issues in the error path of ostm_init(): > 1. Drop error message printing on of_iomap() failure, as the memory > allocation core already takes of that, > 2. Handle irq_of_parse_and_map() failures correctly: it returns > unsigned int, hence make irq unsigned int, and zero is an error, > 3. Propagate/return appropriate error codes instead of -EFAULT. > 4. Add a missing clk_put(), > 5. Split the single cleanup block in separate phases, to avoid > clk_put() calling WARN() when passed an error pointer. Does it make sense to convert to timer-of API? > Signed-off-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx> > --- > v3: > - New. > --- > drivers/clocksource/renesas-ostm.c | 54 ++++++++++++++++-------------- > 1 file changed, 29 insertions(+), 25 deletions(-) > > diff --git a/drivers/clocksource/renesas-ostm.c b/drivers/clocksource/renesas-ostm.c > index 37c39b901bb12b38..1e22e54d7b0df40d 100644 > --- a/drivers/clocksource/renesas-ostm.c > +++ b/drivers/clocksource/renesas-ostm.c > @@ -155,7 +155,7 @@ static irqreturn_t ostm_timer_interrupt(int irq, void *dev_id) > return IRQ_HANDLED; > } > > -static int __init ostm_init_clkevt(struct ostm_device *ostm, int irq, > +static int __init ostm_init_clkevt(struct ostm_device *ostm, unsigned int irq, > unsigned long rate) > { > struct clock_event_device *ced = &ostm->ced; > @@ -185,11 +185,11 @@ static int __init ostm_init_clkevt(struct ostm_device *ostm, int irq, > > static int __init ostm_init(struct device_node *np) > { > - struct ostm_device *ostm; > - int ret = -EFAULT; > struct clk *ostm_clk = NULL; > - int irq; > + struct ostm_device *ostm; > unsigned long rate; > + unsigned int irq; > + int ret; > > ostm = kzalloc(sizeof(*ostm), GFP_KERNEL); > if (!ostm) > @@ -197,27 +197,29 @@ static int __init ostm_init(struct device_node *np) > > ostm->base = of_iomap(np, 0); > if (!ostm->base) { > - pr_err("ostm: failed to remap I/O memory\n"); > - goto err; > + ret = -ENOMEM; > + goto err_free; > } > > irq = irq_of_parse_and_map(np, 0); > - if (irq < 0) { > + if (!irq) { > pr_err("ostm: Failed to get irq\n"); > - goto err; > + ret = -EINVAL; > + goto err_unmap; > } > > ostm_clk = of_clk_get(np, 0); > if (IS_ERR(ostm_clk)) { > pr_err("ostm: Failed to get clock\n"); > ostm_clk = NULL; > - goto err; > + ret = PTR_ERR(ostm_clk); > + goto err_unmap; > } > > ret = clk_prepare_enable(ostm_clk); > if (ret) { > pr_err("ostm: Failed to enable clock\n"); > - goto err; > + goto err_clk_put; > } > > rate = clk_get_rate(ostm_clk); > @@ -229,28 +231,30 @@ static int __init ostm_init(struct device_node *np) > */ > if (!system_clock) { > ret = ostm_init_clksrc(ostm, rate); > + if (ret) > + goto err_clk_disable; > > - if (!ret) { > - ostm_init_sched_clock(ostm, rate); > - pr_info("ostm: used for clocksource\n"); > - } > - > + ostm_init_sched_clock(ostm, rate); > + pr_info("ostm: used for clocksource\n"); > } else { > ret = ostm_init_clkevt(ostm, irq, rate); > + if (ret) > + goto err_clk_disable; > > - if (!ret) > - pr_info("ostm: used for clock events\n"); > - } > - > -err: > - if (ret) { > - clk_disable_unprepare(ostm_clk); > - iounmap(ostm->base); > - kfree(ostm); > - return ret; > + pr_info("ostm: used for clock events\n"); > } > > return 0; > + > +err_clk_disable: > + clk_disable_unprepare(ostm_clk); > +err_clk_put: > + clk_put(ostm_clk); > +err_unmap: > + iounmap(ostm->base); > +err_free: > + kfree(ostm); > + return ret; > } > > TIMER_OF_DECLARE(ostm, "renesas,ostm", ostm_init); > -- <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook | <http://twitter.com/#!/linaroorg> Twitter | <http://www.linaro.org/linaro-blog/> Blog