Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7cba160a authored by Shreyas B. Prabhu's avatar Shreyas B. Prabhu Committed by Michael Ellerman
Browse files

powernv/cpuidle: Redesign idle states management



Deep idle states like sleep and winkle are per core idle states. A core
enters these states only when all the threads enter either the
particular idle state or a deeper one. There are tasks like fastsleep
hardware bug workaround and hypervisor core state save which have to be
done only by the last thread of the core entering deep idle state and
similarly tasks like timebase resync, hypervisor core register restore
that have to be done only by the first thread waking up from these
state.

The current idle state management does not have a way to distinguish the
first/last thread of the core waking/entering idle states. Tasks like
timebase resync are done for all the threads. This is not only is
suboptimal, but can cause functionality issues when subcores and kvm is
involved.

This patch adds the necessary infrastructure to track idle states of
threads in a per-core structure. It uses this info to perform tasks like
fastsleep workaround and timebase resync only once per core.

Signed-off-by: default avatarShreyas B. Prabhu <shreyas@linux.vnet.ibm.com>
Originally-by: default avatarPreeti U. Murthy <preeti@linux.vnet.ibm.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: linux-pm@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 8eb8ac89
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
#ifndef _ASM_POWERPC_CPUIDLE_H
#define _ASM_POWERPC_CPUIDLE_H

#ifdef CONFIG_PPC_POWERNV
/* Used in powernv idle state management */
#define PNV_THREAD_RUNNING              0
#define PNV_THREAD_NAP                  1
#define PNV_THREAD_SLEEP                2
#define PNV_THREAD_WINKLE               3
#define PNV_CORE_IDLE_LOCK_BIT          0x100
#define PNV_CORE_IDLE_THREAD_BITS       0x0FF

#ifndef __ASSEMBLY__
extern u32 pnv_fastsleep_workaround_at_entry[];
extern u32 pnv_fastsleep_workaround_at_exit[];
#endif

#endif

#endif
+2 −0
Original line number Diff line number Diff line
@@ -160,6 +160,7 @@ struct opal_sg_list {
#define OPAL_PCI_ERR_INJECT			96
#define OPAL_PCI_EEH_FREEZE_SET			97
#define OPAL_HANDLE_HMI				98
#define OPAL_CONFIG_CPU_IDLE_STATE		99
#define OPAL_REGISTER_DUMP_REGION		101
#define OPAL_UNREGISTER_DUMP_REGION		102
#define OPAL_WRITE_TPO				103
@@ -175,6 +176,7 @@ struct opal_sg_list {
 */
#define OPAL_PM_NAP_ENABLED	0x00010000
#define OPAL_PM_SLEEP_ENABLED	0x00020000
#define OPAL_PM_SLEEP_ENABLED_ER1	0x00080000

#ifndef __ASSEMBLY__

+8 −0
Original line number Diff line number Diff line
@@ -152,6 +152,14 @@ struct paca_struct {
	u64 tm_scratch;                 /* TM scratch area for reclaim */
#endif

#ifdef CONFIG_PPC_POWERNV
	/* Per-core mask tracking idle threads and a lock bit-[L][TTTTTTTT] */
	u32 *core_idle_state_ptr;
	u8 thread_idle_state;		/* PNV_THREAD_RUNNING/NAP/SLEEP	*/
	/* Mask to indicate thread id in core */
	u8 thread_mask;
#endif

#ifdef CONFIG_PPC_BOOK3S_64
	/* Exclusive emergency stack pointer for machine check exception. */
	void *mc_emergency_sp;
+1 −1
Original line number Diff line number Diff line
@@ -452,7 +452,7 @@ enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF};

extern int powersave_nap;	/* set if nap mode can be used in idle loop */
extern unsigned long power7_nap(int check_irq);
extern void power7_sleep(void);
extern unsigned long power7_sleep(void);
extern void flush_instruction_cache(void);
extern void hard_reset_now(void);
extern void poweroff_now(void);
+9 −0
Original line number Diff line number Diff line
@@ -726,5 +726,14 @@ int main(void)
					arch.timing_last_enter.tv32.tbl));
#endif

#ifdef CONFIG_PPC_POWERNV
	DEFINE(PACA_CORE_IDLE_STATE_PTR,
			offsetof(struct paca_struct, core_idle_state_ptr));
	DEFINE(PACA_THREAD_IDLE_STATE,
			offsetof(struct paca_struct, thread_idle_state));
	DEFINE(PACA_THREAD_MASK,
			offsetof(struct paca_struct, thread_mask));
#endif

	return 0;
}
Loading