diff options
author | Paul Mackerras <paulus@samba.org> | 2006-04-18 07:49:11 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-04-18 07:49:11 -0400 |
commit | f39224a8c1828bdd327539da72a53d8a13595838 (patch) | |
tree | cc9e9139e2e7e2e36774e5c52a5311439160633c /include | |
parent | 183b73ae7c9e4e19fa95d88e1778481899a65210 (diff) |
powerpc: Use correct sequence for putting CPU into nap mode
We weren't using the recommended sequence for putting the CPU into
nap mode. When I changed the idle loop, for some reason 7447A cpus
started hanging when we put them into nap mode. Changing to the
recommended sequence fixes that.
The complexity here is that the recommended sequence is a loop that
keeps putting the cpu back into nap mode. Clearly we need some way
to break out of the loop when an interrupt (external interrupt,
decrementer, performance monitor) occurs. Here we use a bit in
the thread_info struct to indicate that we need this, and the exception
entry code notices this and arranges for the exception to return
to the value in the link register, thus breaking out of the loop.
We use a new `local_flags' field in the thread_info which we can
alter without needing to use an atomic update sequence.
The PPC970 has the same recommended sequence, so we do the same thing
there too.
This also fixes a bug in the kernel stack overflow handling code on
32-bit, since it was causing a value that we needed in a register to
get trashed.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-powerpc/thread_info.h | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h index ffc7462d77ba..88b553c6b26c 100644 --- a/include/asm-powerpc/thread_info.h +++ b/include/asm-powerpc/thread_info.h | |||
@@ -37,6 +37,8 @@ struct thread_info { | |||
37 | int preempt_count; /* 0 => preemptable, | 37 | int preempt_count; /* 0 => preemptable, |
38 | <0 => BUG */ | 38 | <0 => BUG */ |
39 | struct restart_block restart_block; | 39 | struct restart_block restart_block; |
40 | unsigned long local_flags; /* private flags for thread */ | ||
41 | |||
40 | /* low level flags - has atomic operations done on it */ | 42 | /* low level flags - has atomic operations done on it */ |
41 | unsigned long flags ____cacheline_aligned_in_smp; | 43 | unsigned long flags ____cacheline_aligned_in_smp; |
42 | }; | 44 | }; |
@@ -143,6 +145,12 @@ static inline struct thread_info *current_thread_info(void) | |||
143 | _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK) | 145 | _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK) |
144 | #define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR) | 146 | #define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR) |
145 | 147 | ||
148 | /* Bits in local_flags */ | ||
149 | /* Don't move TLF_NAPPING without adjusting the code in entry_32.S */ | ||
150 | #define TLF_NAPPING 0 /* idle thread enabled NAP mode */ | ||
151 | |||
152 | #define _TLF_NAPPING (1 << TLF_NAPPING) | ||
153 | |||
146 | #endif /* __KERNEL__ */ | 154 | #endif /* __KERNEL__ */ |
147 | 155 | ||
148 | #endif /* _ASM_POWERPC_THREAD_INFO_H */ | 156 | #endif /* _ASM_POWERPC_THREAD_INFO_H */ |