[PATCH] ppc64: Move pSeries idle functions into pSeries_setup.c

dedicated_idle() and shared_idle() are only used by pSeries, so move them into
pSeries_setup.c

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
index 44d9af7..849ed9b 100644
--- a/arch/ppc64/kernel/pSeries_setup.c
+++ b/arch/ppc64/kernel/pSeries_setup.c
@@ -418,6 +418,133 @@
 	return 1;
 }
 
+DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
+
+int dedicated_idle(void)
+{
+	long oldval;
+	struct paca_struct *lpaca = get_paca(), *ppaca;
+	unsigned long start_snooze;
+	unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
+	unsigned int cpu = smp_processor_id();
+
+	ppaca = &paca[cpu ^ 1];
+
+	while (1) {
+		/*
+		 * Indicate to the HV that we are idle. Now would be
+		 * a good time to find other work to dispatch.
+		 */
+		lpaca->lppaca.idle = 1;
+
+		oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
+		if (!oldval) {
+			set_thread_flag(TIF_POLLING_NRFLAG);
+			start_snooze = __get_tb() +
+				*smt_snooze_delay * tb_ticks_per_usec;
+			while (!need_resched() && !cpu_is_offline(cpu)) {
+				/*
+				 * Go into low thread priority and possibly
+				 * low power mode.
+				 */
+				HMT_low();
+				HMT_very_low();
+
+				if (*smt_snooze_delay == 0 ||
+				    __get_tb() < start_snooze)
+					continue;
+
+				HMT_medium();
+
+				if (!(ppaca->lppaca.idle)) {
+					local_irq_disable();
+
+					/*
+					 * We are about to sleep the thread
+					 * and so wont be polling any
+					 * more.
+					 */
+					clear_thread_flag(TIF_POLLING_NRFLAG);
+
+					/*
+					 * SMT dynamic mode. Cede will result
+					 * in this thread going dormant, if the
+					 * partner thread is still doing work.
+					 * Thread wakes up if partner goes idle,
+					 * an interrupt is presented, or a prod
+					 * occurs.  Returning from the cede
+					 * enables external interrupts.
+					 */
+					if (!need_resched())
+						cede_processor();
+					else
+						local_irq_enable();
+				} else {
+					/*
+					 * Give the HV an opportunity at the
+					 * processor, since we are not doing
+					 * any work.
+					 */
+					poll_pending();
+				}
+			}
+
+			clear_thread_flag(TIF_POLLING_NRFLAG);
+		} else {
+			set_need_resched();
+		}
+
+		HMT_medium();
+		lpaca->lppaca.idle = 0;
+		schedule();
+		if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
+			cpu_die();
+	}
+	return 0;
+}
+
+static int shared_idle(void)
+{
+	struct paca_struct *lpaca = get_paca();
+	unsigned int cpu = smp_processor_id();
+
+	while (1) {
+		/*
+		 * Indicate to the HV that we are idle. Now would be
+		 * a good time to find other work to dispatch.
+		 */
+		lpaca->lppaca.idle = 1;
+
+		while (!need_resched() && !cpu_is_offline(cpu)) {
+			local_irq_disable();
+
+			/*
+			 * Yield the processor to the hypervisor.  We return if
+			 * an external interrupt occurs (which are driven prior
+			 * to returning here) or if a prod occurs from another
+			 * processor. When returning here, external interrupts
+			 * are enabled.
+			 *
+			 * Check need_resched() again with interrupts disabled
+			 * to avoid a race.
+			 */
+			if (!need_resched())
+				cede_processor();
+			else
+				local_irq_enable();
+		}
+
+		HMT_medium();
+		lpaca->lppaca.idle = 0;
+		schedule();
+		if (cpu_is_offline(smp_processor_id()) &&
+		    system_state == SYSTEM_RUNNING)
+			cpu_die();
+	}
+
+	return 0;
+}
+
 struct machdep_calls __initdata pSeries_md = {
 	.probe			= pSeries_probe,
 	.setup_arch		= pSeries_setup_arch,