linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/9] clockevents/drivers/mtk: Fix spurious interrupt leading to crash
       [not found] <56255943.6060807@linaro.org>
@ 2015-10-19 20:59 ` Daniel Lezcano
  2015-10-19 20:59   ` [PATCH 2/9] clocksource/drivers/mediatek: Use GPT as sched clock source Daniel Lezcano
                     ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Daniel Lezcano @ 2015-10-19 20:59 UTC (permalink / raw)
  To: linux-arm-kernel

After analysis done by Yingjoe Chen, the timer appears to have a pending
interrupt when it is enabled.

Fix this by acknowledging the pending interrupt when enabling the timer
interrupt.

Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
---
 drivers/clocksource/mtk_timer.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c
index 50f0641..c8badc4 100644
--- a/drivers/clocksource/mtk_timer.c
+++ b/drivers/clocksource/mtk_timer.c
@@ -141,14 +141,6 @@ static irqreturn_t mtk_timer_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static void mtk_timer_global_reset(struct mtk_clock_event_device *evt)
-{
-	/* Disable all interrupts */
-	writel(0x0, evt->gpt_base + GPT_IRQ_EN_REG);
-	/* Acknowledge all interrupts */
-	writel(0x3f, evt->gpt_base + GPT_IRQ_ACK_REG);
-}
-
 static void
 mtk_timer_setup(struct mtk_clock_event_device *evt, u8 timer, u8 option)
 {
@@ -168,6 +160,12 @@ static void mtk_timer_enable_irq(struct mtk_clock_event_device *evt, u8 timer)
 {
 	u32 val;
 
+	/* Disable all interrupts */
+	writel(0x0, evt->gpt_base + GPT_IRQ_EN_REG);
+
+	/* Acknowledge all spurious pending interrupts */
+	writel(0x3f, evt->gpt_base + GPT_IRQ_ACK_REG);
+
 	val = readl(evt->gpt_base + GPT_IRQ_EN_REG);
 	writel(val | GPT_IRQ_ENABLE(timer),
 			evt->gpt_base + GPT_IRQ_EN_REG);
@@ -220,8 +218,6 @@ static void __init mtk_timer_init(struct device_node *node)
 	}
 	rate = clk_get_rate(clk);
 
-	mtk_timer_global_reset(evt);
-
 	if (request_irq(evt->dev.irq, mtk_timer_interrupt,
 			IRQF_TIMER | IRQF_IRQPOLL, "mtk_timer", evt)) {
 		pr_warn("failed to setup irq %d\n", evt->dev.irq);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/9] clocksource/drivers/mediatek: Use GPT as sched clock source
  2015-10-19 20:59 ` [PATCH 1/9] clockevents/drivers/mtk: Fix spurious interrupt leading to crash Daniel Lezcano
@ 2015-10-19 20:59   ` Daniel Lezcano
  2015-10-19 20:59   ` [PATCH 6/9] clocksource/drivers/exynos_mct: Use container_of() instead of this_cpu_ptr() Daniel Lezcano
  2015-10-22 19:50   ` [PATCH 1/9] clockevents/drivers/mtk: Fix spurious interrupt leading to crash Matthias Brugger
  2 siblings, 0 replies; 4+ messages in thread
From: Daniel Lezcano @ 2015-10-19 20:59 UTC (permalink / raw)
  To: linux-arm-kernel

From: Yingjoe Chen <yingjoe.chen@mediatek.com>

When cpu is in deep idle, arch timer will stop counting. Setup GPT as
sched clock source so it can keep counting in idle.

Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Acked-by: Stephen Boyd <sboyd@codeaurora.org>
Acked-by: Matthias Brugger <matthias.bgg@gmail.com>
---
 drivers/clocksource/mtk_timer.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c
index c8badc4..fbfc746 100644
--- a/drivers/clocksource/mtk_timer.c
+++ b/drivers/clocksource/mtk_timer.c
@@ -24,6 +24,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/sched_clock.h>
 #include <linux/slab.h>
 
 #define GPT_IRQ_EN_REG		0x00
@@ -59,6 +60,13 @@ struct mtk_clock_event_device {
 	struct clock_event_device dev;
 };
 
+static void __iomem *gpt_sched_reg __read_mostly;
+
+static u64 notrace mtk_read_sched_clock(void)
+{
+	return readl_relaxed(gpt_sched_reg);
+}
+
 static inline struct mtk_clock_event_device *to_mtk_clk(
 				struct clock_event_device *c)
 {
@@ -230,6 +238,8 @@ static void __init mtk_timer_init(struct device_node *node)
 	mtk_timer_setup(evt, GPT_CLK_SRC, TIMER_CTRL_OP_FREERUN);
 	clocksource_mmio_init(evt->gpt_base + TIMER_CNT_REG(GPT_CLK_SRC),
 			node->name, rate, 300, 32, clocksource_mmio_readl_up);
+	gpt_sched_reg = evt->gpt_base + TIMER_CNT_REG(GPT_CLK_SRC);
+	sched_clock_register(mtk_read_sched_clock, 32, rate);
 
 	/* Configure clock event */
 	mtk_timer_setup(evt, GPT_CLK_EVT, TIMER_CTRL_OP_REPEAT);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 6/9] clocksource/drivers/exynos_mct: Use container_of() instead of this_cpu_ptr()
  2015-10-19 20:59 ` [PATCH 1/9] clockevents/drivers/mtk: Fix spurious interrupt leading to crash Daniel Lezcano
  2015-10-19 20:59   ` [PATCH 2/9] clocksource/drivers/mediatek: Use GPT as sched clock source Daniel Lezcano
@ 2015-10-19 20:59   ` Daniel Lezcano
  2015-10-22 19:50   ` [PATCH 1/9] clockevents/drivers/mtk: Fix spurious interrupt leading to crash Matthias Brugger
  2 siblings, 0 replies; 4+ messages in thread
From: Daniel Lezcano @ 2015-10-19 20:59 UTC (permalink / raw)
  To: linux-arm-kernel

From: Alexey Klimov <alexey.klimov@linaro.org>

Since evt structure is embedded in per-CPU mevt structure it's
definitely faster to use container_of() to get access to mevt
if we have evt (for example as incoming function argument) instead
of more expensive approach with this_cpu_ptr(&percpu_mct_tick).
this_cpu_ptr() on per-CPU mevt structure leads to access to cp15
to get cpu id and arithmetic operations.
Container_of() is cheaper since it's just one asm instruction.
This should work if used evt pointer is correct and owned by
local mevt structure.

For example, before this patch set_state_shutdown() looks like:

 4a4:	e92d4010 	push	{r4, lr}
 4a8:	e3004000 	movw	r4, #0
 4ac:	ebfffffe 	bl	0 <debug_smp_processor_id>
 4b0:	e3003000 	movw	r3, #0
 4b4:	e3404000 	movt	r4, #0
 4b8:	e3403000 	movt	r3, #0
 4bc:	e7933100 	ldr	r3, [r3, r0, lsl #2]
 4c0:	e0844003 	add	r4, r4, r3
 4c4:	e59400c0 	ldr	r0, [r4, #192]	; 0xc0
 4c8:	ebffffd4 	bl	420 <exynos4_mct_tick_stop.isra.1>
 4cc:	e3a00000 	mov	r0, #0
 4d0:	e8bd8010 	pop	{r4, pc}

With this patch:

 4a4:	e92d4010 	push	{r4, lr}
 4a8:	e59000c0 	ldr	r0, [r0, #192]	; 0xc0
 4ac:	ebffffdb 	bl	420 <exynos4_mct_tick_stop.isra.1>
 4b0:	e3a00000 	mov	r0, #0
 4b4:	e8bd8010 	pop	{r4, pc}

Also, for me size of exynos_mct.o decreased from 84588 bytes
to 83956.

Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
---
 drivers/clocksource/exynos_mct.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index 029f96a..ff44082 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -382,24 +382,28 @@ static void exynos4_mct_tick_start(unsigned long cycles,
 static int exynos4_tick_set_next_event(unsigned long cycles,
 				       struct clock_event_device *evt)
 {
-	struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
+	struct mct_clock_event_device *mevt;
 
+	mevt = container_of(evt, struct mct_clock_event_device, evt);
 	exynos4_mct_tick_start(cycles, mevt);
-
 	return 0;
 }
 
 static int set_state_shutdown(struct clock_event_device *evt)
 {
-	exynos4_mct_tick_stop(this_cpu_ptr(&percpu_mct_tick));
+	struct mct_clock_event_device *mevt;
+
+	mevt = container_of(evt, struct mct_clock_event_device, evt);
+	exynos4_mct_tick_stop(mevt);
 	return 0;
 }
 
 static int set_state_periodic(struct clock_event_device *evt)
 {
-	struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
+	struct mct_clock_event_device *mevt;
 	unsigned long cycles_per_jiffy;
 
+	mevt = container_of(evt, struct mct_clock_event_device, evt);
 	cycles_per_jiffy = (((unsigned long long)NSEC_PER_SEC / HZ * evt->mult)
 			    >> evt->shift);
 	exynos4_mct_tick_stop(mevt);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 1/9] clockevents/drivers/mtk: Fix spurious interrupt leading to crash
  2015-10-19 20:59 ` [PATCH 1/9] clockevents/drivers/mtk: Fix spurious interrupt leading to crash Daniel Lezcano
  2015-10-19 20:59   ` [PATCH 2/9] clocksource/drivers/mediatek: Use GPT as sched clock source Daniel Lezcano
  2015-10-19 20:59   ` [PATCH 6/9] clocksource/drivers/exynos_mct: Use container_of() instead of this_cpu_ptr() Daniel Lezcano
@ 2015-10-22 19:50   ` Matthias Brugger
  2 siblings, 0 replies; 4+ messages in thread
From: Matthias Brugger @ 2015-10-22 19:50 UTC (permalink / raw)
  To: linux-arm-kernel

2015-10-19 22:59 GMT+02:00 Daniel Lezcano <daniel.lezcano@linaro.org>:
> After analysis done by Yingjoe Chen, the timer appears to have a pending
> interrupt when it is enabled.
>
> Fix this by acknowledging the pending interrupt when enabling the timer
> interrupt.
>
> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> Tested-by: Yingjoe Chen <yingjoe.chen@mediatek.com>

Acked-by: Matthias Brugger <matthias.bgg@gmail.com>

> ---
>  drivers/clocksource/mtk_timer.c | 16 ++++++----------
>  1 file changed, 6 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c
> index 50f0641..c8badc4 100644
> --- a/drivers/clocksource/mtk_timer.c
> +++ b/drivers/clocksource/mtk_timer.c
> @@ -141,14 +141,6 @@ static irqreturn_t mtk_timer_interrupt(int irq, void *dev_id)
>         return IRQ_HANDLED;
>  }
>
> -static void mtk_timer_global_reset(struct mtk_clock_event_device *evt)
> -{
> -       /* Disable all interrupts */
> -       writel(0x0, evt->gpt_base + GPT_IRQ_EN_REG);
> -       /* Acknowledge all interrupts */
> -       writel(0x3f, evt->gpt_base + GPT_IRQ_ACK_REG);
> -}
> -
>  static void
>  mtk_timer_setup(struct mtk_clock_event_device *evt, u8 timer, u8 option)
>  {
> @@ -168,6 +160,12 @@ static void mtk_timer_enable_irq(struct mtk_clock_event_device *evt, u8 timer)
>  {
>         u32 val;
>
> +       /* Disable all interrupts */
> +       writel(0x0, evt->gpt_base + GPT_IRQ_EN_REG);
> +
> +       /* Acknowledge all spurious pending interrupts */
> +       writel(0x3f, evt->gpt_base + GPT_IRQ_ACK_REG);
> +
>         val = readl(evt->gpt_base + GPT_IRQ_EN_REG);
>         writel(val | GPT_IRQ_ENABLE(timer),
>                         evt->gpt_base + GPT_IRQ_EN_REG);
> @@ -220,8 +218,6 @@ static void __init mtk_timer_init(struct device_node *node)
>         }
>         rate = clk_get_rate(clk);
>
> -       mtk_timer_global_reset(evt);
> -
>         if (request_irq(evt->dev.irq, mtk_timer_interrupt,
>                         IRQF_TIMER | IRQF_IRQPOLL, "mtk_timer", evt)) {
>                 pr_warn("failed to setup irq %d\n", evt->dev.irq);
> --
> 1.9.1
>



-- 
motzblog.wordpress.com

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-10-22 19:50 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <56255943.6060807@linaro.org>
2015-10-19 20:59 ` [PATCH 1/9] clockevents/drivers/mtk: Fix spurious interrupt leading to crash Daniel Lezcano
2015-10-19 20:59   ` [PATCH 2/9] clocksource/drivers/mediatek: Use GPT as sched clock source Daniel Lezcano
2015-10-19 20:59   ` [PATCH 6/9] clocksource/drivers/exynos_mct: Use container_of() instead of this_cpu_ptr() Daniel Lezcano
2015-10-22 19:50   ` [PATCH 1/9] clockevents/drivers/mtk: Fix spurious interrupt leading to crash Matthias Brugger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).