Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clocksource/drivers/exynos_mct: Use container_of() instead of this_cpu_ptr()

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>

authored by

Alexey Klimov and committed by
Daniel Lezcano
31f79874 ba49af35

+8 -4
+8 -4
drivers/clocksource/exynos_mct.c
··· 382 382 static int exynos4_tick_set_next_event(unsigned long cycles, 383 383 struct clock_event_device *evt) 384 384 { 385 - struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); 385 + struct mct_clock_event_device *mevt; 386 386 387 + mevt = container_of(evt, struct mct_clock_event_device, evt); 387 388 exynos4_mct_tick_start(cycles, mevt); 388 - 389 389 return 0; 390 390 } 391 391 392 392 static int set_state_shutdown(struct clock_event_device *evt) 393 393 { 394 - exynos4_mct_tick_stop(this_cpu_ptr(&percpu_mct_tick)); 394 + struct mct_clock_event_device *mevt; 395 + 396 + mevt = container_of(evt, struct mct_clock_event_device, evt); 397 + exynos4_mct_tick_stop(mevt); 395 398 return 0; 396 399 } 397 400 398 401 static int set_state_periodic(struct clock_event_device *evt) 399 402 { 400 - struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); 403 + struct mct_clock_event_device *mevt; 401 404 unsigned long cycles_per_jiffy; 402 405 406 + mevt = container_of(evt, struct mct_clock_event_device, evt); 403 407 cycles_per_jiffy = (((unsigned long long)NSEC_PER_SEC / HZ * evt->mult) 404 408 >> evt->shift); 405 409 exynos4_mct_tick_stop(mevt);