2013-10-02 12:41:33

by Boris BREZILLON

[permalink] [raw]
Subject: [PATCH 0/3] ARM: at91/tc/clocksource: various robustness improvements

Hello,

This series include several improvements regarding the at91 tc clocksource
driver:
- use clk_prepare/unprepare_enable/disable functions instead of the
clk_enable/disable functions to prepare the transition to the common clk
framework
- check several function return values instead of considering these functions
always suceed.
- remove the deprecated IRQF_DISABLED flag

Best Regards,

Boris

Boris BREZILLON (3):
ARM: at91/tc/clocksource: replace clk_enable/disable with
clk_prepare_enable/disable_unprepare
ARM: at91/tc/clocksource: improve driver robustness
ARM: at91/tc/clocksource: remove IRQF_DISABLED

drivers/clocksource/tcb_clksrc.c | 61 +++++++++++++++++++++++++++++++-------
1 file changed, 50 insertions(+), 11 deletions(-)

--
1.7.9.5


2013-10-02 12:35:49

by Boris BREZILLON

[permalink] [raw]
Subject: [PATCH 2/3] ARM: at91/tc/clocksource: improve driver robustness

Check function return values to avoid false positive driver init.

Signed-off-by: Boris BREZILLON <[email protected]>
---
drivers/clocksource/tcb_clksrc.c | 33 ++++++++++++++++++++++++++++-----
1 file changed, 28 insertions(+), 5 deletions(-)

diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
index 0481562..10a5d9e 100644
--- a/drivers/clocksource/tcb_clksrc.c
+++ b/drivers/clocksource/tcb_clksrc.c
@@ -184,11 +184,18 @@ static struct irqaction tc_irqaction = {
.handler = ch2_irq,
};

-static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
+static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
{
+ int ret;
struct clk *t2_clk = tc->clk[2];
int irq = tc->irq[2];

+ /* try to enable t2 clk to avoid future errors in mode change */
+ ret = clk_prepare_enable(t2_clk);
+ if (ret)
+ return ret;
+ clk_disable_unprepare(t2_clk);
+
clkevt.regs = tc->regs;
clkevt.clk = t2_clk;
tc_irqaction.dev_id = &clkevt;
@@ -197,16 +204,21 @@ static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)

clkevt.clkevt.cpumask = cpumask_of(0);

+ ret = setup_irq(irq, &tc_irqaction);
+ if (ret)
+ return ret;
+
clockevents_config_and_register(&clkevt.clkevt, 32768, 1, 0xffff);

- setup_irq(irq, &tc_irqaction);
+ return ret;
}

#else /* !CONFIG_GENERIC_CLOCKEVENTS */

-static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
+static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
{
/* NOTHING */
+ return 0;
}

#endif
@@ -328,13 +340,24 @@ static int __init tcb_clksrc_init(void)
}

/* and away we go! */
- clocksource_register_hz(&clksrc, divided_rate);
+ ret = clocksource_register_hz(&clksrc, divided_rate);
+ if (ret)
+ goto err_disable_t1;

/* channel 2: periodic and oneshot timer support */
- setup_clkevents(tc, clk32k_divisor_idx);
+ ret = setup_clkevents(tc, clk32k_divisor_idx);
+ if (ret)
+ goto err_unregister_clksrc;

return 0;

+err_unregister_clksrc:
+ clocksource_unregister(&clksrc);
+
+err_disable_t1:
+ if (!tc->tcb_config || tc->tcb_config->counter_width != 32)
+ clk_disable_unprepare(tc->clk[1]);
+
err_disable_t0:
clk_disable_unprepare(t0_clk);

--
1.7.9.5

2013-10-02 12:41:45

by Boris BREZILLON

[permalink] [raw]
Subject: [PATCH 3/3] ARM: at91/tc/clocksource: remove IRQF_DISABLED

Remove the deprecated IRQF_DISABLED flag.

Signed-off-by: Boris BREZILLON <[email protected]>
---
drivers/clocksource/tcb_clksrc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
index 10a5d9e..00fdd11 100644
--- a/drivers/clocksource/tcb_clksrc.c
+++ b/drivers/clocksource/tcb_clksrc.c
@@ -180,7 +180,7 @@ static irqreturn_t ch2_irq(int irq, void *handle)

static struct irqaction tc_irqaction = {
.name = "tc_clkevt",
- .flags = IRQF_TIMER | IRQF_DISABLED,
+ .flags = IRQF_TIMER,
.handler = ch2_irq,
};

--
1.7.9.5

2013-10-02 12:41:57

by Boris BREZILLON

[permalink] [raw]
Subject: [PATCH 1/3] ARM: at91/tc/clocksource: replace clk_enable/disable with clk_prepare_enable/disable_unprepare

Replace clk_enable/disable with clk_prepare_enable/disable_unprepare to
avoid common clk framework warnings.

Signed-off-by: Boris BREZILLON <[email protected]>
Acked-by: Nicolas Ferre <[email protected]>
---
drivers/clocksource/tcb_clksrc.c | 26 +++++++++++++++++++++-----
1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
index 8a61872..0481562 100644
--- a/drivers/clocksource/tcb_clksrc.c
+++ b/drivers/clocksource/tcb_clksrc.c
@@ -100,7 +100,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d)
|| tcd->clkevt.mode == CLOCK_EVT_MODE_ONESHOT) {
__raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR));
__raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
- clk_disable(tcd->clk);
+ clk_disable_unprepare(tcd->clk);
}

switch (m) {
@@ -109,7 +109,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d)
* of oneshot, we get lower overhead and improved accuracy.
*/
case CLOCK_EVT_MODE_PERIODIC:
- clk_enable(tcd->clk);
+ clk_prepare_enable(tcd->clk);

/* slow clock, count up to RC, then irq and restart */
__raw_writel(timer_clock
@@ -126,7 +126,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d)
break;

case CLOCK_EVT_MODE_ONESHOT:
- clk_enable(tcd->clk);
+ clk_prepare_enable(tcd->clk);

/* slow clock, count up to RC, then irq and stop */
__raw_writel(timer_clock | ATMEL_TC_CPCSTOP
@@ -265,6 +265,7 @@ static int __init tcb_clksrc_init(void)
int best_divisor_idx = -1;
int clk32k_divisor_idx = -1;
int i;
+ int ret;

tc = atmel_tc_alloc(CONFIG_ATMEL_TCB_CLKSRC_BLOCK, clksrc.name);
if (!tc) {
@@ -275,7 +276,11 @@ static int __init tcb_clksrc_init(void)
pdev = tc->pdev;

t0_clk = tc->clk[0];
- clk_enable(t0_clk);
+ ret = clk_prepare_enable(t0_clk);
+ if (ret) {
+ pr_debug("can't enable T0 clk\n");
+ goto err_free_tc;
+ }

/* How fast will we be counting? Pick something over 5 MHz. */
rate = (u32) clk_get_rate(t0_clk);
@@ -313,7 +318,11 @@ static int __init tcb_clksrc_init(void)
/* tclib will give us three clocks no matter what the
* underlying platform supports.
*/
- clk_enable(tc->clk[1]);
+ ret = clk_prepare_enable(tc->clk[1]);
+ if (ret) {
+ pr_debug("can't enable T1 clk\n");
+ goto err_disable_t0;
+ }
/* setup both channel 0 & 1 */
tcb_setup_dual_chan(tc, best_divisor_idx);
}
@@ -325,5 +334,12 @@ static int __init tcb_clksrc_init(void)
setup_clkevents(tc, clk32k_divisor_idx);

return 0;
+
+err_disable_t0:
+ clk_disable_unprepare(t0_clk);
+
+err_free_tc:
+ atmel_tc_free(tc);
+ return ret;
}
arch_initcall(tcb_clksrc_init);
--
1.7.9.5

2013-10-02 12:47:37

by Nicolas Ferre

[permalink] [raw]
Subject: Re: [PATCH 2/3] ARM: at91/tc/clocksource: improve driver robustness

On 02/10/2013 14:35, Boris BREZILLON :
> Check function return values to avoid false positive driver init.
>
> Signed-off-by: Boris BREZILLON <[email protected]>

Acked-by: Nicolas Ferre <[email protected]>

> ---
> drivers/clocksource/tcb_clksrc.c | 33 ++++++++++++++++++++++++++++-----
> 1 file changed, 28 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
> index 0481562..10a5d9e 100644
> --- a/drivers/clocksource/tcb_clksrc.c
> +++ b/drivers/clocksource/tcb_clksrc.c
> @@ -184,11 +184,18 @@ static struct irqaction tc_irqaction = {
> .handler = ch2_irq,
> };
>
> -static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
> +static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
> {
> + int ret;
> struct clk *t2_clk = tc->clk[2];
> int irq = tc->irq[2];
>
> + /* try to enable t2 clk to avoid future errors in mode change */
> + ret = clk_prepare_enable(t2_clk);
> + if (ret)
> + return ret;
> + clk_disable_unprepare(t2_clk);
> +
> clkevt.regs = tc->regs;
> clkevt.clk = t2_clk;
> tc_irqaction.dev_id = &clkevt;
> @@ -197,16 +204,21 @@ static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
>
> clkevt.clkevt.cpumask = cpumask_of(0);
>
> + ret = setup_irq(irq, &tc_irqaction);
> + if (ret)
> + return ret;
> +
> clockevents_config_and_register(&clkevt.clkevt, 32768, 1, 0xffff);
>
> - setup_irq(irq, &tc_irqaction);
> + return ret;
> }
>
> #else /* !CONFIG_GENERIC_CLOCKEVENTS */
>
> -static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
> +static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
> {
> /* NOTHING */
> + return 0;
> }
>
> #endif
> @@ -328,13 +340,24 @@ static int __init tcb_clksrc_init(void)
> }
>
> /* and away we go! */
> - clocksource_register_hz(&clksrc, divided_rate);
> + ret = clocksource_register_hz(&clksrc, divided_rate);
> + if (ret)
> + goto err_disable_t1;
>
> /* channel 2: periodic and oneshot timer support */
> - setup_clkevents(tc, clk32k_divisor_idx);
> + ret = setup_clkevents(tc, clk32k_divisor_idx);
> + if (ret)
> + goto err_unregister_clksrc;
>
> return 0;
>
> +err_unregister_clksrc:
> + clocksource_unregister(&clksrc);
> +
> +err_disable_t1:
> + if (!tc->tcb_config || tc->tcb_config->counter_width != 32)
> + clk_disable_unprepare(tc->clk[1]);
> +
> err_disable_t0:
> clk_disable_unprepare(t0_clk);
>
>


--
Nicolas Ferre

2013-10-02 12:47:50

by Nicolas Ferre

[permalink] [raw]
Subject: Re: [PATCH 3/3] ARM: at91/tc/clocksource: remove IRQF_DISABLED

On 02/10/2013 14:35, Boris BREZILLON :
> Remove the deprecated IRQF_DISABLED flag.
>
> Signed-off-by: Boris BREZILLON <[email protected]>

Acked-by: Nicolas Ferre <[email protected]>

> ---
> drivers/clocksource/tcb_clksrc.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
> index 10a5d9e..00fdd11 100644
> --- a/drivers/clocksource/tcb_clksrc.c
> +++ b/drivers/clocksource/tcb_clksrc.c
> @@ -180,7 +180,7 @@ static irqreturn_t ch2_irq(int irq, void *handle)
>
> static struct irqaction tc_irqaction = {
> .name = "tc_clkevt",
> - .flags = IRQF_TIMER | IRQF_DISABLED,
> + .flags = IRQF_TIMER,
> .handler = ch2_irq,
> };
>
>


--
Nicolas Ferre

2013-10-02 13:11:36

by Boris BREZILLON

[permalink] [raw]
Subject: [PATCH 1/3] ARM: at91/tc/clocksource: replace clk_enable/disable with clk_prepare_enable/disable_unprepare

Replace clk_enable/disable with clk_prepare_enable/disable_unprepare to
avoid common clk framework warnings.

Signed-off-by: Boris BREZILLON <[email protected]>
Acked-by: Nicolas Ferre <[email protected]>
---
drivers/clocksource/tcb_clksrc.c | 26 +++++++++++++++++++++-----
1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
index 8a61872..0481562 100644
--- a/drivers/clocksource/tcb_clksrc.c
+++ b/drivers/clocksource/tcb_clksrc.c
@@ -100,7 +100,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d)
|| tcd->clkevt.mode == CLOCK_EVT_MODE_ONESHOT) {
__raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR));
__raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
- clk_disable(tcd->clk);
+ clk_disable_unprepare(tcd->clk);
}

switch (m) {
@@ -109,7 +109,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d)
* of oneshot, we get lower overhead and improved accuracy.
*/
case CLOCK_EVT_MODE_PERIODIC:
- clk_enable(tcd->clk);
+ clk_prepare_enable(tcd->clk);

/* slow clock, count up to RC, then irq and restart */
__raw_writel(timer_clock
@@ -126,7 +126,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d)
break;

case CLOCK_EVT_MODE_ONESHOT:
- clk_enable(tcd->clk);
+ clk_prepare_enable(tcd->clk);

/* slow clock, count up to RC, then irq and stop */
__raw_writel(timer_clock | ATMEL_TC_CPCSTOP
@@ -265,6 +265,7 @@ static int __init tcb_clksrc_init(void)
int best_divisor_idx = -1;
int clk32k_divisor_idx = -1;
int i;
+ int ret;

tc = atmel_tc_alloc(CONFIG_ATMEL_TCB_CLKSRC_BLOCK, clksrc.name);
if (!tc) {
@@ -275,7 +276,11 @@ static int __init tcb_clksrc_init(void)
pdev = tc->pdev;

t0_clk = tc->clk[0];
- clk_enable(t0_clk);
+ ret = clk_prepare_enable(t0_clk);
+ if (ret) {
+ pr_debug("can't enable T0 clk\n");
+ goto err_free_tc;
+ }

/* How fast will we be counting? Pick something over 5 MHz. */
rate = (u32) clk_get_rate(t0_clk);
@@ -313,7 +318,11 @@ static int __init tcb_clksrc_init(void)
/* tclib will give us three clocks no matter what the
* underlying platform supports.
*/
- clk_enable(tc->clk[1]);
+ ret = clk_prepare_enable(tc->clk[1]);
+ if (ret) {
+ pr_debug("can't enable T1 clk\n");
+ goto err_disable_t0;
+ }
/* setup both channel 0 & 1 */
tcb_setup_dual_chan(tc, best_divisor_idx);
}
@@ -325,5 +334,12 @@ static int __init tcb_clksrc_init(void)
setup_clkevents(tc, clk32k_divisor_idx);

return 0;
+
+err_disable_t0:
+ clk_disable_unprepare(t0_clk);
+
+err_free_tc:
+ atmel_tc_free(tc);
+ return ret;
}
arch_initcall(tcb_clksrc_init);
--
1.7.9.5

2013-10-03 14:31:05

by Daniel Lezcano

[permalink] [raw]
Subject: Re: [PATCH 0/3] ARM: at91/tc/clocksource: various robustness improvements

On 10/02/2013 02:34 PM, Boris BREZILLON wrote:
> Hello,
>
> This series include several improvements regarding the at91 tc clocksource
> driver:
> - use clk_prepare/unprepare_enable/disable functions instead of the
> clk_enable/disable functions to prepare the transition to the common clk
> framework
> - check several function return values instead of considering these functions
> always suceed.
> - remove the deprecated IRQF_DISABLED flag
>
> Best Regards,
>
> Boris
>
> Boris BREZILLON (3):
> ARM: at91/tc/clocksource: replace clk_enable/disable with
> clk_prepare_enable/disable_unprepare
> ARM: at91/tc/clocksource: improve driver robustness
> ARM: at91/tc/clocksource: remove IRQF_DISABLED
>
> drivers/clocksource/tcb_clksrc.c | 61 +++++++++++++++++++++++++++++++-------
> 1 file changed, 50 insertions(+), 11 deletions(-)
>

Applied to my tree for 3.13 with the subsystem name and first letter
capitalized fixed:

clocksource: tcb_clksrc: [A-Z]*

Thanks !
-- Daniel

--
<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