[PATCH 59/69] clocksource/drivers/dw_apb_timer: Use {readl|writel}_relaxed in critical path

From: Daniel Lezcano
Date: Fri Dec 18 2015 - 09:19:59 EST


From: Jisheng Zhang <jszhang@xxxxxxxxxxx>

It's safe to use the relaxed version. From another side, the relaxed io
accessor macros are available on all architectures now, so we can use
the relaxed versions to get a trivial system performance improvement,
we measured time the following functions spent on Marvell BG4CT:

4096 rounds of __apbt_read_clocksource() call:

before the patch: 1263240ns on average
after the patch: 1250080ns on average
improved by 1%

4096 rounds of apbt_eoi() call:

before the patch: 1290960ns on average
after the patch: 1248240ns on average

4096 rounds of apbt_next_event() call:

before the patch: 3333660ns on average
after the patch: 1322040ns on average

improved by 60%!

Signed-off-by: Jisheng Zhang <jszhang@xxxxxxxxxxx>
Signed-off-by: Daniel Lezcano <daniel.lezcano@xxxxxxxxxx>
---
drivers/clocksource/dw_apb_timer.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c
index 3a6d9db..7f95b53 100644
--- a/drivers/clocksource/dw_apb_timer.c
+++ b/drivers/clocksource/dw_apb_timer.c
@@ -60,6 +60,17 @@ static void apbt_writel(struct dw_apb_timer *timer, u32 val,
writel(val, timer->base + offs);
}

+static inline u32 apbt_readl_relaxed(struct dw_apb_timer *timer, unsigned long offs)
+{
+ return readl_relaxed(timer->base + offs);
+}
+
+static inline void apbt_writel_relaxed(struct dw_apb_timer *timer, u32 val,
+ unsigned long offs)
+{
+ writel_relaxed(val, timer->base + offs);
+}
+
static void apbt_disable_int(struct dw_apb_timer *timer)
{
u32 ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
@@ -81,7 +92,7 @@ void dw_apb_clockevent_pause(struct dw_apb_clock_event_device *dw_ced)

static void apbt_eoi(struct dw_apb_timer *timer)
{
- apbt_readl(timer, APBTMR_N_EOI);
+ apbt_readl_relaxed(timer, APBTMR_N_EOI);
}

static irqreturn_t dw_apb_clockevent_irq(int irq, void *data)
@@ -200,13 +211,13 @@ static int apbt_next_event(unsigned long delta,
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);

/* Disable timer */
- ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
+ ctrl = apbt_readl_relaxed(&dw_ced->timer, APBTMR_N_CONTROL);
ctrl &= ~APBTMR_CONTROL_ENABLE;
- apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+ apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
/* write new count */
- apbt_writel(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT);
+ apbt_writel_relaxed(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT);
ctrl |= APBTMR_CONTROL_ENABLE;
- apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+ apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);

return 0;
}
@@ -342,7 +353,8 @@ static cycle_t __apbt_read_clocksource(struct clocksource *cs)
struct dw_apb_clocksource *dw_cs =
clocksource_to_dw_apb_clocksource(cs);

- current_count = apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE);
+ current_count = apbt_readl_relaxed(&dw_cs->timer,
+ APBTMR_N_CURRENT_VALUE);

return (cycle_t)~current_count;
}
--
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/