mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
The pm_qos idle wake-up mechanism currently wakes up *all* idle CPUs when there's a pm_qos request change, instead of just the CPUs which are affected by the change. This is horribly suboptimal and increases power consumption by needlessly waking idled CPUs. Additionally, pm_qos may kick CPUs which aren't even idle, since wake_up_all_idle_cpus() only checks if a CPU is running the idle task, which says nothing about whether or not the CPU is really in an idle state. Optimize the pm_qos wake-ups by only sending IPIs to CPUs that are idle, and by using arch_send_wakeup_ipi_mask() instead of wake_up_if_idle() which is used under the hood in wake_up_all_idle_cpus(). Using IPI_WAKEUP instead of IPI_RESCHEDULE, which is what wake_up_if_idle() uses behind the scenes, has the benefit of doing zero work upon receipt of the IPI; IPI_WAKEUP is designed purely for sending an IPI without a payload. Determining which CPUs are idle is done efficiently with an atomic bitmask instead of using the wake_up_if_idle() API, which checks the CPU's runqueue in an RCU read-side critical section and under a spin lock. Not very efficient in comparison to a simple, atomic bitwise operation. A cpumask isn't needed for this because NR_CPUS is guaranteed to fit within a word. CPUs are marked as idle as soon as IRQs are disabled in the idle loop, since any IPI sent after that point will cause the CPU's idle attempt to immediately exit (like when executing the wfi instruction). CPUs are marked as not-idle as soon as they wake up in order to avoid sending redundant IPIs to CPUs that are already awake. Change-Id: I04c9e2bd9317357e16d8184a104fe603d0d2dab2 Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com> Signed-off-by: Richard Raya <rdxzv.dev@gmail.com>