Inside the linux kernel idle loop, for quite a few architectures (SH, ARM, X86 etc.. afaik) are the following lines:
if(cpuidle_idle_call())
pm_idle();
My doubt:
At-least for ARM, The default pm_idle function consists of WFI (Wait for interrupt) instruction but the confusing part is, interrupts are disabled then and are enabled after the WFI instruction executes, How does a CPU get back online from WFI when interrupts were disabled ?
I tried searching for my answers in various versions of linux, but the related code is unchanged since 2.6.32 (the last version i referred to) so it's more likely that I am missing something.
WFI wakes even if interrupts are disabled, but the ARM core doesn't receive the interrupts until interrupts are enabled again.
There are a couple of reasons for cpuidle_idle_call() to return an "error".
The missing driver is the most likely thing to happen. But in this case the kernel still has to burn cycles somehow. So it calls pm_idle, which on arm by default maps to default_idle. There the kernel checks if the cpu has a arm_pm_idle registered, which can be thought of like a lightweight cpuidle driver. If all fails it will fallback to cpu_idle, which HAS to be implemented and most of the time drains the write buffer and goes into WFI-mode.
There is a lot of redundancy in that whole thing, but that allows the developers to write simple idle-drivers and make them into full grown cpuidle drivers later if necessary.
The thing is that different SoCs provide different capabilities. For example, on kirkwood the idle-driver will set the DDR into Self refresh mode before switching to wfi-mode to safe some power. In theory it could also be extended to switch the cpu to a slower clock.
For your other question. Disabling interrupts will only prevent the cpu to trigger the interrupt-handler, it still needs to register that the interrupt occurred, otherwise you might loose data. So the handlers get disabled, but an incoming interrupt will still trigger the wakeup functionality of WFI.