LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] i2c-mpc: Do not generate STOP after read.
From: Joakim Tjernlund @ 2009-09-22 11:50 UTC (permalink / raw)
  To: linux-i2c, linuxppc-dev, Esben Haabendal; +Cc: Esben Haabendal

The driver always ends a read with a STOP condition which
breaks subsequent I2C reads/writes in the same transaction as
these expect to do a repeated START(ReSTART).

This will also help I2C multimaster as the bus will not be released
after the first read, but when the whole transaction ends.

Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
---

This should also fix a problem reported by Esben Haabendal:

[PATCH v2] i2c-mpc: generate START condition after STOP caused by read i2c_msg

This fixes MAL (arbitration lost) bug caused by illegal use of
RSTA (repeated START) after STOP condition generated after last byte
of reads. With this patch, it is possible to do an i2c_transfer() with
additional i2c_msg's following the I2C_M_RD messages.

It still needs to be resolved if it is possible to fix this issue
by removing the STOP condition after reads in a robust way.

Signed-off-by: Esben Haabendal <eha@doredevelopment.dk>

 drivers/i2c/busses/i2c-mpc.c |   10 ++--------
 1 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index cdb1858..88ae582 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -369,9 +369,6 @@ static int mpc_write(struct mpc_i2c *i2c, int target,
 	unsigned timeout = i2c->adap.timeout;
 	u32 flags = restart ? CCR_RSTA : 0;
 
-	/* Start with MEN */
-	if (!restart)
-		writeccr(i2c, CCR_MEN);
 	/* Start as master */
 	writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
 	/* Write target byte */
@@ -400,9 +397,6 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
 	int i, result;
 	u32 flags = restart ? CCR_RSTA : 0;
 
-	/* Start with MEN */
-	if (!restart)
-		writeccr(i2c, CCR_MEN);
 	/* Switch to read - restart */
 	writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
 	/* Write target address byte - this time with the read flag set */
@@ -429,9 +423,9 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
 		/* Generate txack on next to last byte */
 		if (i == length - 2)
 			writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
-		/* Generate stop on last byte */
+		/* Do not generate stop on last byte */
 		if (i == length - 1)
-			writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK);
+			writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX);
 		data[i] = readb(i2c->base + MPC_I2C_DR);
 	}
 
-- 
1.6.4.3

^ permalink raw reply related

* Re: [PATCH] perf_event, powerpc: Fix compilation after big perf_counter rename
From: Michael Ellerman @ 2009-09-22 11:52 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Peter Zijlstra, linux-kernel, linuxppc-dev, Paul Mackerras,
	Ingo Molnar, Linus Torvalds, David S. Miller
In-Reply-To: <1253606415.7103.216.camel@pasglop>

[-- Attachment #1: Type: text/plain, Size: 505 bytes --]

On Tue, 2009-09-22 at 18:00 +1000, Benjamin Herrenschmidt wrote:
> On Tue, 2009-09-22 at 09:28 +0200, Ingo Molnar wrote:
> > 
> > Nevertheless you are right that i should have caught this particular 
> > PowerPC build bug - i missed it - sorry about that!
> > 
> Allright. Well, to help in general, we are setting up a build-bot
> here too that will build -tip HEAD for at least powerpc daily with
> a few configs too.

Results here:

http://kisskb.ellerman.id.au/kisskb/branch/12/

cheers

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* [v6 PATCH 7/7]: pSeries: implement pSeries processor idle module.
From: Arun R Bharadwaj @ 2009-09-22 11:33 UTC (permalink / raw)
  To: Peter Zijlstra, Joel Schopp, Benjamin Herrenschmidt,
	Paul Mackerras, Ingo Molnar, Vaidyanathan Srinivasan,
	Dipankar Sarma, Balbir Singh, Gautham R Shenoy, Shaohua Li,
	Venkatesh Pallipadi, Arun Bharadwaj
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <20090922112526.GA7788@linux.vnet.ibm.com>

* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2009-09-22 16:55:27]:

This patch creates arch/powerpc/platforms/pseries/processor_idle.c,
which implements the cpuidle infrastructure for pseries.
It implements a pseries_cpuidle_loop() which would be the main idle loop
called from cpu_idle(). It makes decision of entering either cede1 or cede2
for dedicated lpar and shared_cede for shared lpar processor based on the
decision taken by the cpuidle governor.

Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
 arch/powerpc/platforms/pseries/Makefile         |    1 
 arch/powerpc/platforms/pseries/processor_idle.c |  191 ++++++++++++++++++++++++
 arch/powerpc/platforms/pseries/pseries.h        |    9 +
 arch/powerpc/platforms/pseries/setup.c          |    8 -
 4 files changed, 207 insertions(+), 2 deletions(-)

Index: linux.trees.git/arch/powerpc/platforms/pseries/Makefile
===================================================================
--- linux.trees.git.orig/arch/powerpc/platforms/pseries/Makefile
+++ linux.trees.git/arch/powerpc/platforms/pseries/Makefile
@@ -26,3 +26,4 @@ obj-$(CONFIG_HCALL_STATS)	+= hvCall_inst
 obj-$(CONFIG_PHYP_DUMP)	+= phyp_dump.o
 obj-$(CONFIG_CMM)		+= cmm.o
 obj-$(CONFIG_DTL)		+= dtl.o
+obj-$(CONFIG_PSERIES_PROCESSOR_IDLE)	+= processor_idle.o
Index: linux.trees.git/arch/powerpc/platforms/pseries/pseries.h
===================================================================
--- linux.trees.git.orig/arch/powerpc/platforms/pseries/pseries.h
+++ linux.trees.git/arch/powerpc/platforms/pseries/pseries.h
@@ -10,6 +10,8 @@
 #ifndef _PSERIES_PSERIES_H
 #define _PSERIES_PSERIES_H
 
+#include <linux/cpuidle.h>
+
 extern void __init fw_feature_init(const char *hypertas, unsigned long len);
 
 struct pt_regs;
@@ -40,4 +42,11 @@ extern unsigned long rtas_poweron_auto;
 
 extern void find_udbg_vterm(void);
 
+DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
+
+#ifdef CONFIG_PSERIES_PROCESSOR_IDLE
+int pseries_processor_idle_init(void);
+extern struct cpuidle_driver pseries_idle_driver;
+#endif
+
 #endif /* _PSERIES_PSERIES_H */
Index: linux.trees.git/arch/powerpc/platforms/pseries/processor_idle.c
===================================================================
--- /dev/null
+++ linux.trees.git/arch/powerpc/platforms/pseries/processor_idle.c
@@ -0,0 +1,191 @@
+/*
+ *  processor_idle - idle state cpuidle driver.
+ *  Adapted from drivers/acpi/processor_idle.c
+ *
+ *  Arun R Bharadwaj <arun@linux.vnet.ibm.com>
+ *
+ *  Copyright (C) 2009 IBM Corporation.
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/cpuidle.h>
+
+#include <asm/paca.h>
+#include <asm/reg.h>
+#include <asm/system.h>
+#include <asm/machdep.h>
+#include <asm/firmware.h>
+
+#include "plpar_wrappers.h"
+#include "pseries.h"
+
+MODULE_AUTHOR("Arun R Bharadwaj");
+MODULE_DESCRIPTION("pSeries Idle State Driver");
+MODULE_LICENSE("GPL");
+
+struct cpuidle_driver pseries_idle_driver = {
+	.name =		"pseries_idle",
+	.owner =	THIS_MODULE,
+};
+
+DEFINE_PER_CPU(struct cpuidle_device, pseries_dev);
+
+#define IDLE_STATE_COUNT	2
+
+static int pseries_idle_init(struct cpuidle_device *dev)
+{
+	return cpuidle_register_device(dev);
+}
+
+static void shared_cede(void)
+{
+	get_lppaca()->idle = 1;
+	cede_processor();
+	get_lppaca()->idle = 0;
+}
+
+static void cede1(void)
+{
+	local_irq_enable();
+	set_thread_flag(TIF_POLLING_NRFLAG);
+	while (!need_resched()) {
+		ppc64_runlatch_off();
+		HMT_low();
+		HMT_very_low();
+	}
+	HMT_medium();
+	clear_thread_flag(TIF_POLLING_NRFLAG);
+	smp_mb();
+	local_irq_disable();
+}
+
+static void cede2(void)
+{
+	ppc64_runlatch_off();
+	HMT_medium();
+	cede_processor();
+}
+
+static int pseries_cpuidle_loop(struct cpuidle_device *dev,
+				struct cpuidle_state *st)
+{
+	ktime_t t1, t2;
+	s64 diff;
+	int ret;
+	unsigned long in_purr, out_purr;
+
+	get_lppaca()->idle = 1;
+	get_lppaca()->donate_dedicated_cpu = 1;
+	in_purr = mfspr(SPRN_PURR);
+
+	t1 = ktime_get();
+
+	if (strcmp(st->desc, "shared_cede") == 0)
+		shared_cede();
+	else if (strcmp(st->desc, "cede1") == 0)
+		cede1();
+	else
+		cede2();
+
+	t2 = ktime_get();
+	diff = ktime_to_us(ktime_sub(t2, t1));
+	if (diff > INT_MAX)
+		diff = INT_MAX;
+
+	ret = (int) diff;
+
+	out_purr = mfspr(SPRN_PURR);
+	get_lppaca()->wait_state_cycles += out_purr - in_purr;
+	get_lppaca()->donate_dedicated_cpu = 0;
+	get_lppaca()->idle = 0;
+
+	return ret;
+}
+
+static int pseries_setup_cpuidle(struct cpuidle_device *dev, int cpu)
+{
+	int i;
+	struct cpuidle_state *state;
+
+	dev->cpu = cpu;
+
+	if (get_lppaca()->shared_proc) {
+		state = &dev->states[0];
+		snprintf(state->name, CPUIDLE_NAME_LEN, "IDLE");
+		state->enter = pseries_cpuidle_loop;
+		strncpy(state->desc, "shared_cede", CPUIDLE_DESC_LEN);
+		state->exit_latency = 0;
+		state->target_residency = 0;
+		return 0;
+	}
+
+	for (i = 0; i < IDLE_STATE_COUNT; i++) {
+		state = &dev->states[i];
+
+		snprintf(state->name, CPUIDLE_NAME_LEN, "IDLE%d", i);
+		state->enter = pseries_cpuidle_loop;
+
+		switch (i) {
+		case 0:
+			strncpy(state->desc, "cede1", CPUIDLE_DESC_LEN);
+			state->exit_latency = 0;
+			state->target_residency = 0;
+			break;
+
+		case 1:
+			strncpy(state->desc, "cede2", CPUIDLE_DESC_LEN);
+			state->exit_latency = 1;
+			state->target_residency =
+					__get_cpu_var(smt_snooze_delay);
+			break;
+		}
+	}
+	dev->state_count = IDLE_STATE_COUNT;
+
+	return 0;
+}
+
+int __init pseries_processor_idle_init(void)
+{
+	int cpu;
+	int result = cpuidle_register_driver(&pseries_idle_driver);
+
+	if (result < 0)
+		return result;
+
+	printk(KERN_DEBUG "pSeries idle driver registered\n");
+
+	if (!firmware_has_feature(FW_FEATURE_SPLPAR)) {
+		printk(KERN_DEBUG "Using default idle\n");
+		return 0;
+	}
+
+	for_each_online_cpu(cpu) {
+		pseries_setup_cpuidle(&per_cpu(pseries_dev, cpu), cpu);
+		pseries_idle_init(&per_cpu(pseries_dev, cpu));
+	}
+
+	printk(KERN_DEBUG "Using cpuidle idle loop\n");
+
+	return 0;
+}
Index: linux.trees.git/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- linux.trees.git.orig/arch/powerpc/platforms/pseries/setup.c
+++ linux.trees.git/arch/powerpc/platforms/pseries/setup.c
@@ -297,9 +297,13 @@ static void __init pSeries_setup_arch(vo
 
 	pSeries_nvram_init();
 
-	/* Choose an idle loop */
-	if (firmware_has_feature(FW_FEATURE_SPLPAR))
+	/* Register an idle loop with cpuidle */
+	if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
 		vpa_init(boot_cpuid);
+#ifdef CONFIG_PSERIES_PROCESSOR_IDLE
+		pseries_processor_idle_init();
+#endif
+	}
 
 	if (firmware_has_feature(FW_FEATURE_LPAR))
 		ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;

^ permalink raw reply

* [v6 PATCH 6/7]: POWER: add a default_idle idle loop for POWER.
From: Arun R Bharadwaj @ 2009-09-22 11:32 UTC (permalink / raw)
  To: Peter Zijlstra, Joel Schopp, Benjamin Herrenschmidt,
	Paul Mackerras, Ingo Molnar, Vaidyanathan Srinivasan,
	Dipankar Sarma, Balbir Singh, Gautham R Shenoy, Shaohua Li,
	Venkatesh Pallipadi, Arun Bharadwaj
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <20090922112526.GA7788@linux.vnet.ibm.com>

* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2009-09-22 16:55:27]:

In arch/powerpc/kernel/idle.c create a default_idle() routine by moving
the failover condition of the cpu_idle() idle loop. This is needed by
cpuidle infrastructure to call default_idle when other idle routines
are not yet registered. Functionality remains the same, but the code is
slightly moved around.


Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
 arch/powerpc/Kconfig              |    3 +++
 arch/powerpc/include/asm/system.h |    1 +
 arch/powerpc/kernel/idle.c        |    6 ++++++
 3 files changed, 10 insertions(+)

Index: linux.trees.git/arch/powerpc/Kconfig
===================================================================
--- linux.trees.git.orig/arch/powerpc/Kconfig
+++ linux.trees.git/arch/powerpc/Kconfig
@@ -91,6 +91,9 @@ config ARCH_HAS_ILOG2_U64
 config ARCH_HAS_CPU_IDLE_WAIT
 	def_bool y
 
+config ARCH_HAS_DEFAULT_IDLE
+	def_bool y
+
 config GENERIC_HWEIGHT
 	bool
 	default y
Index: linux.trees.git/arch/powerpc/include/asm/system.h
===================================================================
--- linux.trees.git.orig/arch/powerpc/include/asm/system.h
+++ linux.trees.git/arch/powerpc/include/asm/system.h
@@ -218,6 +218,7 @@ extern unsigned long klimit;
 extern void *alloc_maybe_bootmem(size_t size, gfp_t mask);
 extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
 
+extern void default_idle(void);
 extern int powersave_nap;	/* set if nap mode can be used in idle loop */
 
 /*
Index: linux.trees.git/arch/powerpc/kernel/idle.c
===================================================================
--- linux.trees.git.orig/arch/powerpc/kernel/idle.c
+++ linux.trees.git/arch/powerpc/kernel/idle.c
@@ -113,6 +113,12 @@ void cpu_idle_wait(void)
 }
 EXPORT_SYMBOL_GPL(cpu_idle_wait);
 
+void default_idle(void)
+{
+	HMT_low();
+	HMT_very_low();
+}
+
 int powersave_nap;
 
 #ifdef CONFIG_SYSCTL

^ permalink raw reply

* [v6 PATCH 5/7]: pSeries/cpuidle: remove dedicate/shared idle loops, which will be moved to arch/powerpc/platforms/pseries/processor_idle.c
From: Arun R Bharadwaj @ 2009-09-22 11:31 UTC (permalink / raw)
  To: Peter Zijlstra, Joel Schopp, Benjamin Herrenschmidt,
	Paul Mackerras, Ingo Molnar, Vaidyanathan Srinivasan,
	Dipankar Sarma, Balbir Singh, Gautham R Shenoy, Shaohua Li,
	Venkatesh Pallipadi, Arun Bharadwaj
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <20090922112526.GA7788@linux.vnet.ibm.com>

* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2009-09-22 16:55:27]:

This patch removes the routines, pseries_shared_idle_sleep and
pseries_dedicated_idle_sleep, since this is implemented as a part
of arch/powerpc/platform/pseries/processor_idle.c

Also, similar to x86, call cpuidle_idle_call from cpu_idle() idle
loop instead of ppc_md.power_save.


Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/idle.c             |   50 +++++++-----------
 arch/powerpc/platforms/pseries/setup.c |   89 ---------------------------------
 2 files changed, 22 insertions(+), 117 deletions(-)

Index: linux.trees.git/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- linux.trees.git.orig/arch/powerpc/platforms/pseries/setup.c
+++ linux.trees.git/arch/powerpc/platforms/pseries/setup.c
@@ -75,9 +75,6 @@ EXPORT_SYMBOL(CMO_PageSize);
 
 int fwnmi_active;  /* TRUE if an FWNMI handler is present */
 
-static void pseries_shared_idle_sleep(void);
-static void pseries_dedicated_idle_sleep(void);
-
 static struct device_node *pSeries_mpic_node;
 
 static void pSeries_show_cpuinfo(struct seq_file *m)
@@ -301,18 +298,8 @@ static void __init pSeries_setup_arch(vo
 	pSeries_nvram_init();
 
 	/* Choose an idle loop */
-	if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
+	if (firmware_has_feature(FW_FEATURE_SPLPAR))
 		vpa_init(boot_cpuid);
-		if (get_lppaca()->shared_proc) {
-			printk(KERN_DEBUG "Using shared processor idle loop\n");
-			ppc_md.power_save = pseries_shared_idle_sleep;
-		} else {
-			printk(KERN_DEBUG "Using dedicated idle loop\n");
-			ppc_md.power_save = pseries_dedicated_idle_sleep;
-		}
-	} else {
-		printk(KERN_DEBUG "Using default idle loop\n");
-	}
 
 	if (firmware_has_feature(FW_FEATURE_LPAR))
 		ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
@@ -500,80 +487,6 @@ static int __init pSeries_probe(void)
 	return 1;
 }
 
-
-DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
-
-static void pseries_dedicated_idle_sleep(void)
-{ 
-	unsigned int cpu = smp_processor_id();
-	unsigned long start_snooze;
-	unsigned long in_purr, out_purr;
-
-	/*
-	 * Indicate to the HV that we are idle. Now would be
-	 * a good time to find other work to dispatch.
-	 */
-	get_lppaca()->idle = 1;
-	get_lppaca()->donate_dedicated_cpu = 1;
-	in_purr = mfspr(SPRN_PURR);
-
-	/*
-	 * We come in with interrupts disabled, and need_resched()
-	 * has been checked recently.  If we should poll for a little
-	 * while, do so.
-	 */
-	if (__get_cpu_var(smt_snooze_delay)) {
-		start_snooze = get_tb() +
-			__get_cpu_var(smt_snooze_delay) * tb_ticks_per_usec;
-		local_irq_enable();
-		set_thread_flag(TIF_POLLING_NRFLAG);
-
-		while (get_tb() < start_snooze) {
-			if (need_resched() || cpu_is_offline(cpu))
-				goto out;
-			ppc64_runlatch_off();
-			HMT_low();
-			HMT_very_low();
-		}
-
-		HMT_medium();
-		clear_thread_flag(TIF_POLLING_NRFLAG);
-		smp_mb();
-		local_irq_disable();
-		if (need_resched() || cpu_is_offline(cpu))
-			goto out;
-	}
-
-	cede_processor();
-
-out:
-	HMT_medium();
-	out_purr = mfspr(SPRN_PURR);
-	get_lppaca()->wait_state_cycles += out_purr - in_purr;
-	get_lppaca()->donate_dedicated_cpu = 0;
-	get_lppaca()->idle = 0;
-}
-
-static void pseries_shared_idle_sleep(void)
-{
-	/*
-	 * Indicate to the HV that we are idle. Now would be
-	 * a good time to find other work to dispatch.
-	 */
-	get_lppaca()->idle = 1;
-
-	/*
-	 * 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.
-	 */
-	cede_processor();
-
-	get_lppaca()->idle = 0;
-}
-
 static int pSeries_pci_probe_mode(struct pci_bus *bus)
 {
 	if (firmware_has_feature(FW_FEATURE_LPAR))
Index: linux.trees.git/arch/powerpc/kernel/idle.c
===================================================================
--- linux.trees.git.orig/arch/powerpc/kernel/idle.c
+++ linux.trees.git/arch/powerpc/kernel/idle.c
@@ -25,6 +25,7 @@
 #include <linux/cpu.h>
 #include <linux/sysctl.h>
 #include <linux/tick.h>
+#include <linux/cpuidle.h>
 
 #include <asm/system.h>
 #include <asm/processor.h>
@@ -60,35 +61,26 @@ void cpu_idle(void)
 		while (!need_resched() && !cpu_should_die()) {
 			ppc64_runlatch_off();
 
-			if (ppc_md.power_save) {
-				clear_thread_flag(TIF_POLLING_NRFLAG);
-				/*
-				 * smp_mb is so clearing of TIF_POLLING_NRFLAG
-				 * is ordered w.r.t. need_resched() test.
-				 */
-				smp_mb();
-				local_irq_disable();
-
-				/* Don't trace irqs off for idle */
-				stop_critical_timings();
-
-				/* check again after disabling irqs */
-				if (!need_resched() && !cpu_should_die())
-					ppc_md.power_save();
-
-				start_critical_timings();
-
-				local_irq_enable();
-				set_thread_flag(TIF_POLLING_NRFLAG);
-
-			} else {
-				/*
-				 * Go into low thread priority and possibly
-				 * low power mode.
-				 */
-				HMT_low();
-				HMT_very_low();
-			}
+			clear_thread_flag(TIF_POLLING_NRFLAG);
+			/*
+			 * smp_mb is so clearing of TIF_POLLING_NRFLAG
+			 * is ordered w.r.t. need_resched() test.
+			 */
+			smp_mb();
+			local_irq_disable();
+
+			/* Don't trace irqs off for idle */
+			stop_critical_timings();
+
+			/* check again after disabling irqs */
+			if (!need_resched() && !cpu_should_die())
+				cpuidle_idle_call();
+
+			start_critical_timings();
+
+			local_irq_enable();
+			set_thread_flag(TIF_POLLING_NRFLAG);
+
 		}
 
 		HMT_medium();

^ permalink raw reply

* [v6 PATCH 4/7]: POWER: enable cpuidle for POWER.
From: Arun R Bharadwaj @ 2009-09-22 11:30 UTC (permalink / raw)
  To: Peter Zijlstra, Joel Schopp, Benjamin Herrenschmidt,
	Paul Mackerras, Ingo Molnar, Vaidyanathan Srinivasan,
	Dipankar Sarma, Balbir Singh, Gautham R Shenoy, Shaohua Li,
	Venkatesh Pallipadi, Arun Bharadwaj
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <20090922112526.GA7788@linux.vnet.ibm.com>

* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2009-09-22 16:55:27]:

This patch enables the cpuidle option in Kconfig for pSeries.

Currently cpuidle infrastructure is enabled only for x86 and ARM.
This code is almost completely borrowed from x86 to enable
cpuidle for pSeries.

Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
 arch/powerpc/Kconfig              |   17 +++++++++++++++++
 arch/powerpc/include/asm/system.h |    2 ++
 arch/powerpc/kernel/idle.c        |   19 +++++++++++++++++++
 3 files changed, 38 insertions(+)

Index: linux.trees.git/arch/powerpc/Kconfig
===================================================================
--- linux.trees.git.orig/arch/powerpc/Kconfig
+++ linux.trees.git/arch/powerpc/Kconfig
@@ -88,6 +88,9 @@ config ARCH_HAS_ILOG2_U64
 	bool
 	default y if 64BIT
 
+config ARCH_HAS_CPU_IDLE_WAIT
+	def_bool y
+
 config GENERIC_HWEIGHT
 	bool
 	default y
@@ -243,6 +246,20 @@ source "kernel/Kconfig.freezer"
 source "arch/powerpc/sysdev/Kconfig"
 source "arch/powerpc/platforms/Kconfig"
 
+menu "Power management options"
+
+source "drivers/cpuidle/Kconfig"
+
+config PSERIES_PROCESSOR_IDLE
+	bool "Idle Power Management Support for pSeries"
+	depends on PPC_PSERIES && CPU_IDLE
+	default y
+	help
+	  Idle Power Management Support for pSeries. This hooks onto cpuidle
+	  infrastructure to help in idle cpu power management.
+
+endmenu
+
 menu "Kernel options"
 
 config HIGHMEM
Index: linux.trees.git/arch/powerpc/include/asm/system.h
===================================================================
--- linux.trees.git.orig/arch/powerpc/include/asm/system.h
+++ linux.trees.git/arch/powerpc/include/asm/system.h
@@ -546,5 +546,7 @@ extern void account_system_vtime(struct 
 
 extern struct dentry *powerpc_debugfs_root;
 
+void cpu_idle_wait(void);
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_SYSTEM_H */
Index: linux.trees.git/arch/powerpc/kernel/idle.c
===================================================================
--- linux.trees.git.orig/arch/powerpc/kernel/idle.c
+++ linux.trees.git/arch/powerpc/kernel/idle.c
@@ -102,6 +102,25 @@ void cpu_idle(void)
 	}
 }
 
+static void do_nothing(void *unused)
+{
+}
+
+/*
+ * cpu_idle_wait - Used to ensure that all the CPUs come out of the old
+ * idle loop and start using the new idle loop.
+ * Required while changing idle handler on SMP systems.
+ * Caller must have changed idle handler to the new value before the call.
+ */
+void cpu_idle_wait(void)
+{
+	/* Ensure that new value of ppc_md.power_save is set */
+	smp_mb();
+	/* kick all the CPUs so that they exit out of ppc_md.power_save */
+	smp_call_function(do_nothing, NULL, 1);
+}
+EXPORT_SYMBOL_GPL(cpu_idle_wait);
+
 int powersave_nap;
 
 #ifdef CONFIG_SYSCTL

^ permalink raw reply

* [v6 PATCH 3/7]: x86: refactor x86 idle power management code and remove all instances of pm_idle.
From: Arun R Bharadwaj @ 2009-09-22 11:29 UTC (permalink / raw)
  To: Peter Zijlstra, Joel Schopp, Benjamin Herrenschmidt,
	Paul Mackerras, Ingo Molnar, Vaidyanathan Srinivasan,
	Dipankar Sarma, Balbir Singh, Gautham R Shenoy, Shaohua Li,
	Venkatesh Pallipadi, Arun Bharadwaj
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <20090922112526.GA7788@linux.vnet.ibm.com>

* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2009-09-22 16:55:27]:

This patch cleans up x86 of all instances of pm_idle.

pm_idle which was earlier called from cpu_idle() idle loop
is replaced by cpuidle_idle_call.

x86 also registers to cpuidle when the idle routine is selected,
by populating the cpuidle_device data structure for each cpu.

This is replicated for apm module and for xen, which also used pm_idle.


Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
 arch/x86/kernel/apm_32.c     |   37 +++++++++++++++++++++--
 arch/x86/kernel/process.c    |   69 ++++++++++++++++++++++++++++++++++---------
 arch/x86/kernel/process_32.c |    3 +
 arch/x86/kernel/process_64.c |    3 +
 arch/x86/xen/setup.c         |   22 +++++++++++++
 5 files changed, 114 insertions(+), 20 deletions(-)

Index: linux.trees.git/arch/x86/kernel/process.c
===================================================================
--- linux.trees.git.orig/arch/x86/kernel/process.c
+++ linux.trees.git/arch/x86/kernel/process.c
@@ -9,6 +9,8 @@
 #include <linux/pm.h>
 #include <linux/clockchips.h>
 #include <linux/random.h>
+#include <linux/cpuidle.h>
+
 #include <trace/power.h>
 #include <asm/system.h>
 #include <asm/apic.h>
@@ -247,12 +249,6 @@ int sys_vfork(struct pt_regs *regs)
 unsigned long boot_option_idle_override = 0;
 EXPORT_SYMBOL(boot_option_idle_override);
 
-/*
- * Powermanagement idle function, if any..
- */
-void (*pm_idle)(void);
-EXPORT_SYMBOL(pm_idle);
-
 #ifdef CONFIG_X86_32
 /*
  * This halt magic was a workaround for ancient floppy DMA
@@ -531,15 +527,58 @@ static void c1e_idle(void)
 		default_idle();
 }
 
+static void (*local_idle)(void);
+DEFINE_PER_CPU(struct cpuidle_device, idle_devices);
+
+struct cpuidle_driver cpuidle_default_driver = {
+	.name =         "cpuidle_default",
+};
+
+static int local_idle_loop(struct cpuidle_device *dev, struct cpuidle_state *st)
+{
+	ktime_t t1, t2;
+	s64 diff;
+	int ret;
+
+	t1 = ktime_get();
+	local_idle();
+	t2 = ktime_get();
+
+	diff = ktime_to_us(ktime_sub(t2, t1));
+	if (diff > INT_MAX)
+		diff = INT_MAX;
+	ret = (int) diff;
+
+	return ret;
+}
+static int __cpuinit setup_cpuidle_simple(void)
+{
+	struct cpuidle_device *dev;
+	int cpu;
+
+	if (!cpuidle_curr_driver)
+		cpuidle_register_driver(&cpuidle_default_driver);
+
+	for_each_online_cpu(cpu) {
+		dev = &per_cpu(idle_devices, cpu);
+		dev->cpu = cpu;
+		dev->states[0].enter = local_idle_loop;
+		dev->state_count = 1;
+		cpuidle_register_device(dev);
+	}
+	return 0;
+}
+late_initcall(setup_cpuidle_simple);
+
 void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
-	if (pm_idle == poll_idle && smp_num_siblings > 1) {
+	if (local_idle == poll_idle && smp_num_siblings > 1) {
 		printk(KERN_WARNING "WARNING: polling idle and HT enabled,"
 			" performance may degrade.\n");
 	}
 #endif
-	if (pm_idle)
+	if (local_idle)
 		return;
 
 	if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) {
@@ -547,18 +586,20 @@ void __cpuinit select_idle_routine(const
 		 * One CPU supports mwait => All CPUs supports mwait
 		 */
 		printk(KERN_INFO "using mwait in idle threads.\n");
-		pm_idle = mwait_idle;
+		local_idle = mwait_idle;
 	} else if (check_c1e_idle(c)) {
 		printk(KERN_INFO "using C1E aware idle routine\n");
-		pm_idle = c1e_idle;
+		local_idle = c1e_idle;
 	} else
-		pm_idle = default_idle;
+		local_idle = default_idle;
+
+	return;
 }
 
 void __init init_c1e_mask(void)
 {
 	/* If we're using c1e_idle, we need to allocate c1e_mask. */
-	if (pm_idle == c1e_idle) {
+	if (local_idle == c1e_idle) {
 		alloc_cpumask_var(&c1e_mask, GFP_KERNEL);
 		cpumask_clear(c1e_mask);
 	}
@@ -571,7 +612,7 @@ static int __init idle_setup(char *str)
 
 	if (!strcmp(str, "poll")) {
 		printk("using polling idle threads.\n");
-		pm_idle = poll_idle;
+		local_idle = poll_idle;
 	} else if (!strcmp(str, "mwait"))
 		force_mwait = 1;
 	else if (!strcmp(str, "halt")) {
@@ -582,7 +623,7 @@ static int __init idle_setup(char *str)
 		 * To continue to load the CPU idle driver, don't touch
 		 * the boot_option_idle_override.
 		 */
-		pm_idle = default_idle;
+		local_idle = default_idle;
 		idle_halt = 1;
 		return 0;
 	} else if (!strcmp(str, "nomwait")) {
Index: linux.trees.git/arch/x86/kernel/process_32.c
===================================================================
--- linux.trees.git.orig/arch/x86/kernel/process_32.c
+++ linux.trees.git/arch/x86/kernel/process_32.c
@@ -40,6 +40,7 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <linux/kdebug.h>
+#include <linux/cpuidle.h>
 
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -113,7 +114,7 @@ void cpu_idle(void)
 			local_irq_disable();
 			/* Don't trace irqs off for idle */
 			stop_critical_timings();
-			pm_idle();
+			cpuidle_idle_call();
 			start_critical_timings();
 		}
 		tick_nohz_restart_sched_tick();
Index: linux.trees.git/arch/x86/kernel/process_64.c
===================================================================
--- linux.trees.git.orig/arch/x86/kernel/process_64.c
+++ linux.trees.git/arch/x86/kernel/process_64.c
@@ -39,6 +39,7 @@
 #include <linux/io.h>
 #include <linux/ftrace.h>
 #include <linux/dmi.h>
+#include <linux/cpuidle.h>
 
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -142,7 +143,7 @@ void cpu_idle(void)
 			enter_idle();
 			/* Don't trace irqs off for idle */
 			stop_critical_timings();
-			pm_idle();
+			cpuidle_idle_call();
 			start_critical_timings();
 			/* In many cases the interrupt that ended idle
 			   has already called exit_idle. But some idle
Index: linux.trees.git/arch/x86/kernel/apm_32.c
===================================================================
--- linux.trees.git.orig/arch/x86/kernel/apm_32.c
+++ linux.trees.git/arch/x86/kernel/apm_32.c
@@ -2257,6 +2257,38 @@ static struct dmi_system_id __initdata a
 	{ }
 };
 
+DEFINE_PER_CPU(struct cpuidle_device, apm_idle_devices);
+
+struct cpuidle_driver cpuidle_apm_driver = {
+	.name =         "cpuidle_apm",
+};
+
+void __cpuinit setup_cpuidle_apm(void)
+{
+	struct cpuidle_device *dev;
+
+	if (!cpuidle_curr_driver)
+		cpuidle_register_driver(&cpuidle_apm_driver);
+
+	dev = &per_cpu(apm_idle_devices, smp_processor_id());
+	dev->cpu = smp_processor_id();
+	dev->states[0].enter = apm_cpu_idle;
+	dev->state_count = 1;
+	cpuidle_register_device(dev);
+}
+
+void exit_cpuidle_apm(void)
+{
+	struct cpuidle_device *dev;
+	int cpu;
+
+	for_each_online_cpu(cpu) {
+		dev = &per_cpu(apm_idle_devices, cpu);
+		cpuidle_unregister_device(dev);
+	}
+}
+
+
 /*
  * Just start the APM thread. We do NOT want to do APM BIOS
  * calls from anything but the APM thread, if for no other reason
@@ -2394,8 +2426,7 @@ static int __init apm_init(void)
 	if (HZ != 100)
 		idle_period = (idle_period * HZ) / 100;
 	if (idle_threshold < 100) {
-		original_pm_idle = pm_idle;
-		pm_idle  = apm_cpu_idle;
+		setup_cpuidle_apm();
 		set_pm_idle = 1;
 	}
 
@@ -2407,7 +2438,7 @@ static void __exit apm_exit(void)
 	int error;
 
 	if (set_pm_idle) {
-		pm_idle = original_pm_idle;
+		exit_cpuidle_apm();
 		/*
 		 * We are about to unload the current idle thread pm callback
 		 * (pm_idle), Wait for all processors to update cached/local
Index: linux.trees.git/arch/x86/xen/setup.c
===================================================================
--- linux.trees.git.orig/arch/x86/xen/setup.c
+++ linux.trees.git/arch/x86/xen/setup.c
@@ -8,6 +8,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/pm.h>
+#include <linux/cpuidle.h>
 
 #include <asm/elf.h>
 #include <asm/vdso.h>
@@ -151,6 +152,25 @@ void __cpuinit xen_enable_syscall(void)
 #endif /* CONFIG_X86_64 */
 }
 
+DEFINE_PER_CPU(struct cpuidle_device, idle_devices);
+struct cpuidle_driver cpuidle_xen_driver = {
+	.name =         "cpuidle_xen",
+};
+
+void __cpuinit setup_cpuidle_xen(void)
+{
+	struct cpuidle_device *dev;
+
+	if (!cpuidle_curr_driver)
+		cpuidle_register_driver(&cpuidle_xen_driver);
+
+	dev = &per_cpu(idle_devices, smp_processor_id());
+	dev->cpu = smp_processor_id();
+	dev->states[0].enter = xen_idle;
+	dev->state_count = 1;
+	cpuidle_register_device(dev);
+}
+
 void __init xen_arch_setup(void)
 {
 	struct physdev_set_iopl set_iopl;
@@ -186,7 +206,7 @@ void __init xen_arch_setup(void)
 	       MAX_GUEST_CMDLINE > COMMAND_LINE_SIZE ?
 	       COMMAND_LINE_SIZE : MAX_GUEST_CMDLINE);
 
-	pm_idle = xen_idle;
+	setup_cpuidle_xen();
 
 	paravirt_disable_iospace();
 

^ permalink raw reply

* [v6 PATCH 2/7]: cpuidle: implement a list based approach to register a set of idle routines.
From: Arun R Bharadwaj @ 2009-09-22 11:28 UTC (permalink / raw)
  To: Peter Zijlstra, Joel Schopp, Benjamin Herrenschmidt,
	Paul Mackerras, Ingo Molnar, Vaidyanathan Srinivasan,
	Dipankar Sarma, Balbir Singh, Gautham R Shenoy, Shaohua Li,
	Venkatesh Pallipadi, Arun Bharadwaj
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <20090922112526.GA7788@linux.vnet.ibm.com>

* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2009-09-22 16:55:27]:

Implement a list based registering mechanism for architectures which
have multiple sets of idle routines which are to be registered.

Currently, in x86 it is done by merely setting pm_idle = idle_routine
and managing this pm_idle pointer is messy.

To give an example of how this mechanism works:
In x86, initially, idle routine is selected from the set of poll/mwait/
c1e/default idle loops. So the selected idle loop is registered in cpuidle
as one idle state cpuidle devices. Once ACPI comes up, it registers
another set of idle states on top of this state. Again, suppose a module
registers another set of idle loops, it is added to this list.

This provides a clean way of registering and unregistering idle state
routines.

In the current implementation, pm_idle is set as the current idle routine
being used and the old idle routine has to be maintained and when a module
registers/unregisters an idle routine, confusion arises.


Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
 drivers/cpuidle/cpuidle.c |   51 ++++++++++++++++++++++++++++++++++++++++++----
 include/linux/cpuidle.h   |    1 
 2 files changed, 48 insertions(+), 4 deletions(-)

Index: linux.trees.git/drivers/cpuidle/cpuidle.c
===================================================================
--- linux.trees.git.orig/drivers/cpuidle/cpuidle.c
+++ linux.trees.git/drivers/cpuidle/cpuidle.c
@@ -21,6 +21,7 @@
 #include "cpuidle.h"
 
 DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
+DEFINE_PER_CPU(struct list_head, cpuidle_devices_list);
 
 DEFINE_MUTEX(cpuidle_lock);
 LIST_HEAD(cpuidle_detected_devices);
@@ -111,6 +112,45 @@ void cpuidle_resume_and_unlock(void)
 
 EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
 
+int cpuidle_add_to_list(struct cpuidle_device *dev)
+{
+	int ret, cpu = dev->cpu;
+	struct cpuidle_device *old_dev;
+
+	if (!list_empty(&per_cpu(cpuidle_devices_list, cpu))) {
+		old_dev = list_first_entry(&per_cpu(cpuidle_devices_list, cpu),
+				struct cpuidle_device, idle_list);
+		cpuidle_remove_state_sysfs(old_dev);
+	}
+
+	list_add(&dev->idle_list, &per_cpu(cpuidle_devices_list, cpu));
+	ret = cpuidle_add_state_sysfs(dev);
+	return ret;
+}
+
+void cpuidle_remove_from_list(struct cpuidle_device *dev)
+{
+	struct cpuidle_device *temp_dev;
+	struct list_head *pos;
+	int ret, cpu = dev->cpu;
+
+	list_for_each(pos, &per_cpu(cpuidle_devices_list, cpu)) {
+		temp_dev = container_of(pos, struct cpuidle_device, idle_list);
+		if (dev == temp_dev) {
+			list_del(&temp_dev->idle_list);
+			cpuidle_remove_state_sysfs(temp_dev);
+			break;
+		}
+	}
+
+	if (!list_empty(&per_cpu(cpuidle_devices_list, cpu))) {
+		temp_dev = list_first_entry(&per_cpu(cpuidle_devices_list, cpu),
+					struct cpuidle_device, idle_list);
+		ret = cpuidle_add_state_sysfs(temp_dev);
+	}
+	cpuidle_kick_cpus();
+}
+
 /**
  * cpuidle_enable_device - enables idle PM for a CPU
  * @dev: the CPU
@@ -135,7 +175,7 @@ int cpuidle_enable_device(struct cpuidle
 			return ret;
 	}
 
-	if ((ret = cpuidle_add_state_sysfs(dev)))
+	if ((cpuidle_add_to_list(dev)))
 		return ret;
 
 	if (cpuidle_curr_governor->enable &&
@@ -156,7 +196,7 @@ int cpuidle_enable_device(struct cpuidle
 	return 0;
 
 fail_sysfs:
-	cpuidle_remove_state_sysfs(dev);
+	cpuidle_remove_from_list(dev);
 
 	return ret;
 }
@@ -182,7 +222,7 @@ void cpuidle_disable_device(struct cpuid
 	if (cpuidle_curr_governor->disable)
 		cpuidle_curr_governor->disable(dev);
 
-	cpuidle_remove_state_sysfs(dev);
+	cpuidle_remove_from_list(dev);
 }
 
 EXPORT_SYMBOL_GPL(cpuidle_disable_device);
@@ -350,12 +390,15 @@ static inline void latency_notifier_init
  */
 static int __init cpuidle_init(void)
 {
-	int ret;
+	int ret, cpu;
 
 	ret = cpuidle_add_class_sysfs(&cpu_sysdev_class);
 	if (ret)
 		return ret;
 
+	for_each_possible_cpu(cpu)
+		INIT_LIST_HEAD(&per_cpu(cpuidle_devices_list, cpu));
+
 	latency_notifier_init(&cpuidle_latency_notifier);
 
 	return 0;
Index: linux.trees.git/include/linux/cpuidle.h
===================================================================
--- linux.trees.git.orig/include/linux/cpuidle.h
+++ linux.trees.git/include/linux/cpuidle.h
@@ -93,6 +93,7 @@ struct cpuidle_device {
 	struct cpuidle_state	*last_state;
 
 	struct list_head 	device_list;
+	struct list_head	idle_list;
 	struct kobject		kobj;
 	struct completion	kobj_unregister;
 	void			*governor_data;

^ permalink raw reply

* [v6 PATCH 1/7]: cpuidle: cleanup drivers/cpuidle/cpuidle.c
From: Arun R Bharadwaj @ 2009-09-22 11:27 UTC (permalink / raw)
  To: Peter Zijlstra, Joel Schopp, Benjamin Herrenschmidt,
	Paul Mackerras, Ingo Molnar, Vaidyanathan Srinivasan,
	Dipankar Sarma, Balbir Singh, Gautham R Shenoy, Shaohua Li,
	Venkatesh Pallipadi, Arun Bharadwaj
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <20090922112526.GA7788@linux.vnet.ibm.com>

* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2009-09-22 16:55:27]:

This patch cleans up drivers/cpuidle/cpuidle.c
Earlier cpuidle assumed pm_idle as the default idle loop. Break that
assumption and make it more generic. cpuidle_idle_call() which is the
main idle loop of cpuidle is to be called by architectures which have
registered to cpuidle.

Remove routines cpuidle_install/uninstall_idle_handler() and
cpuidle_kick_cpus() which are not needed anymore.

Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
 drivers/cpuidle/cpuidle.c  |   48 +++++++--------------------------------------
 drivers/cpuidle/cpuidle.h  |    1 
 drivers/cpuidle/governor.c |    3 --
 include/linux/cpuidle.h    |    3 ++
 4 files changed, 11 insertions(+), 44 deletions(-)

Index: linux.trees.git/drivers/cpuidle/cpuidle.c
===================================================================
--- linux.trees.git.orig/drivers/cpuidle/cpuidle.c
+++ linux.trees.git/drivers/cpuidle/cpuidle.c
@@ -24,9 +24,6 @@ DEFINE_PER_CPU(struct cpuidle_device *, 
 
 DEFINE_MUTEX(cpuidle_lock);
 LIST_HEAD(cpuidle_detected_devices);
-static void (*pm_idle_old)(void);
-
-static int enabled_devices;
 
 #if defined(CONFIG_ARCH_HAS_CPU_IDLE_WAIT)
 static void cpuidle_kick_cpus(void)
@@ -46,7 +43,7 @@ static int __cpuidle_register_device(str
  *
  * NOTE: no locks or semaphores should be used here
  */
-static void cpuidle_idle_call(void)
+void cpuidle_idle_call(void)
 {
 	struct cpuidle_device *dev = __get_cpu_var(cpuidle_devices);
 	struct cpuidle_state *target_state;
@@ -54,13 +51,10 @@ static void cpuidle_idle_call(void)
 
 	/* check if the device is ready */
 	if (!dev || !dev->enabled) {
-		if (pm_idle_old)
-			pm_idle_old();
-		else
 #if defined(CONFIG_ARCH_HAS_DEFAULT_IDLE)
-			default_idle();
+		default_idle();
 #else
-			local_irq_enable();
+		local_irq_enable();
 #endif
 		return;
 	}
@@ -74,7 +68,11 @@ static void cpuidle_idle_call(void)
 	hrtimer_peek_ahead_timers();
 #endif
 	/* ask the governor for the next state */
-	next_state = cpuidle_curr_governor->select(dev);
+	if (dev->state_count > 1)
+		next_state = cpuidle_curr_governor->select(dev);
+	else
+		next_state = 0;
+
 	if (need_resched())
 		return;
 	target_state = &dev->states[next_state];
@@ -94,35 +92,11 @@ static void cpuidle_idle_call(void)
 }
 
 /**
- * cpuidle_install_idle_handler - installs the cpuidle idle loop handler
- */
-void cpuidle_install_idle_handler(void)
-{
-	if (enabled_devices && (pm_idle != cpuidle_idle_call)) {
-		/* Make sure all changes finished before we switch to new idle */
-		smp_wmb();
-		pm_idle = cpuidle_idle_call;
-	}
-}
-
-/**
- * cpuidle_uninstall_idle_handler - uninstalls the cpuidle idle loop handler
- */
-void cpuidle_uninstall_idle_handler(void)
-{
-	if (enabled_devices && pm_idle_old && (pm_idle != pm_idle_old)) {
-		pm_idle = pm_idle_old;
-		cpuidle_kick_cpus();
-	}
-}
-
-/**
  * cpuidle_pause_and_lock - temporarily disables CPUIDLE
  */
 void cpuidle_pause_and_lock(void)
 {
 	mutex_lock(&cpuidle_lock);
-	cpuidle_uninstall_idle_handler();
 }
 
 EXPORT_SYMBOL_GPL(cpuidle_pause_and_lock);
@@ -132,7 +106,6 @@ EXPORT_SYMBOL_GPL(cpuidle_pause_and_lock
  */
 void cpuidle_resume_and_unlock(void)
 {
-	cpuidle_install_idle_handler();
 	mutex_unlock(&cpuidle_lock);
 }
 
@@ -180,7 +153,6 @@ int cpuidle_enable_device(struct cpuidle
 
 	dev->enabled = 1;
 
-	enabled_devices++;
 	return 0;
 
 fail_sysfs:
@@ -211,7 +183,6 @@ void cpuidle_disable_device(struct cpuid
 		cpuidle_curr_governor->disable(dev);
 
 	cpuidle_remove_state_sysfs(dev);
-	enabled_devices--;
 }
 
 EXPORT_SYMBOL_GPL(cpuidle_disable_device);
@@ -303,7 +274,6 @@ int cpuidle_register_device(struct cpuid
 	}
 
 	cpuidle_enable_device(dev);
-	cpuidle_install_idle_handler();
 
 	mutex_unlock(&cpuidle_lock);
 
@@ -382,8 +352,6 @@ static int __init cpuidle_init(void)
 {
 	int ret;
 
-	pm_idle_old = pm_idle;
-
 	ret = cpuidle_add_class_sysfs(&cpu_sysdev_class);
 	if (ret)
 		return ret;
Index: linux.trees.git/drivers/cpuidle/governor.c
===================================================================
--- linux.trees.git.orig/drivers/cpuidle/governor.c
+++ linux.trees.git/drivers/cpuidle/governor.c
@@ -48,8 +48,6 @@ int cpuidle_switch_governor(struct cpuid
 	if (gov == cpuidle_curr_governor)
 		return 0;
 
-	cpuidle_uninstall_idle_handler();
-
 	if (cpuidle_curr_governor) {
 		list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
 			cpuidle_disable_device(dev);
@@ -63,7 +61,6 @@ int cpuidle_switch_governor(struct cpuid
 			return -EINVAL;
 		list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
 			cpuidle_enable_device(dev);
-		cpuidle_install_idle_handler();
 		printk(KERN_INFO "cpuidle: using governor %s\n", gov->name);
 	}
 
Index: linux.trees.git/include/linux/cpuidle.h
===================================================================
--- linux.trees.git.orig/include/linux/cpuidle.h
+++ linux.trees.git/include/linux/cpuidle.h
@@ -112,6 +112,9 @@ static inline int cpuidle_get_last_resid
 	return dev->last_residency;
 }
 
+extern void cpuidle_idle_call(void);
+extern struct cpuidle_driver *cpuidle_curr_driver;
+
 
 /****************************
  * CPUIDLE DRIVER INTERFACE *
Index: linux.trees.git/drivers/cpuidle/cpuidle.h
===================================================================
--- linux.trees.git.orig/drivers/cpuidle/cpuidle.h
+++ linux.trees.git/drivers/cpuidle/cpuidle.h
@@ -9,7 +9,6 @@
 
 /* For internal use only */
 extern struct cpuidle_governor *cpuidle_curr_governor;
-extern struct cpuidle_driver *cpuidle_curr_driver;
 extern struct list_head cpuidle_governors;
 extern struct list_head cpuidle_detected_devices;
 extern struct mutex cpuidle_lock;

^ permalink raw reply

* [v6 PATCH 0/7]: cpuidle/x86/POWER: Cleanup idle power management code in x86, cleanup drivers/cpuidle/cpuidle.c and introduce cpuidle to POWER.
From: Arun R Bharadwaj @ 2009-09-22 11:25 UTC (permalink / raw)
  To: Peter Zijlstra, Joel Schopp, Benjamin Herrenschmidt,
	Paul Mackerras, Ingo Molnar, Vaidyanathan Srinivasan,
	Dipankar Sarma, Balbir Singh, Gautham R Shenoy, Shaohua Li,
	Venkatesh Pallipadi, Arun Bharadwaj
  Cc: linuxppc-dev, linux-kernel

Hi,

This patchset introduces cpuidle infrastructure to POWER, prototyping
for pSeries, and also does a major refactoring of current x86 idle
power management and a cleanup of cpuidle infrastructure.

My earlier iterations can be found at:

v5 --> http://lkml.org/lkml/2009/9/22/26
v4 --> http://lkml.org/lkml/2009/9/1/133
v3 --> http://lkml.org/lkml/2009/8/27/124
v2 --> http://lkml.org/lkml/2009/8/26/233
v1 --> http://lkml.org/lkml/2009/8/19/150


Changes in this version:
------------------------------------------
Remove the bug from previous iteration in the routine
cpuidle_remove_from_list(), which was causing the kernel to panic on
platform supporting multiple sleep states.

Add the routine cpuidle_kick_cpus() in POWER, which is needed to kick
the cpus out of their idle when changing the idle routines.


TODO:
-------------------------------------------
Peterz suggested it would be nice to have a sysfs interface through
which an idle routine can be forced at runtime.

Also, current implementation registers every cpu as a cpuidle_device,
but this is an overkill and the registering mechanism should be a
systemwide process and not per-cpu. (probably one of the original
cpuidle authors can reply to this - Venki, Shaohua Li? ).

ppc_md.power_save has been replaced by cpuidle_idle_call only for
pseries. So this needs to be done for all POWER platforms so that
ppc_md.power_save is completely removed.


Any comments on the design is welcome.

--arun

^ permalink raw reply

* RE: [PATCH][v3] powerpc/85xx: P1020RDB Support Added
From: Aggrwal Poonam-B10812 @ 2009-09-22 10:22 UTC (permalink / raw)
  To: Aggrwal Poonam-B10812, linuxppc-dev
In-Reply-To: <1251719528-13265-1-git-send-email-poonam.aggrwal@freescale.com>

Hello Kumar

Could you please accept this patch if it is okay.

Regards
POonam=20

> -----Original Message-----
> From: Aggrwal Poonam-B10812=20
> Sent: Monday, August 31, 2009 5:22 PM
> To: linuxppc-dev@ozlabs.org
> Cc: Aggrwal Poonam-B10812
> Subject: [PATCH][v3] powerpc/85xx: P1020RDB Support Added
>=20
> P1020 is another member of Freescale QorIQ series of processors.
> It is an e500 based dual core SOC.
> Being a scaled down version of P2020 it has following=20
> differences from P2020:
> - 533MHz - 800MHz core frequency.
> - 256Kbyte L2 cache
> - Ethernet controllers with classification capabilities(new=20
> controller).
> From board perspective P1020RDB is same as P2020RDB.
>=20
> * This code adds the basic basic platform support for P1020RDB.
>=20
> Signed-off-by: Poonam Aggrwal <poonam.aggrwal@freescale.com>
> ---
> - based on=20
> http://www.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git
> - branch->next
> - The patch does not contain ethernet support because P1020=20
> contains new eTSEC
>   controller. The support will be added in the later patches.
>  arch/powerpc/boot/dts/p1020rdb.dts        |  477=20
> +++++++++++++++++++++++++++++
>  arch/powerpc/platforms/85xx/mpc85xx_rdb.c |   24 ++
>  2 files changed, 501 insertions(+), 0 deletions(-)  create=20
> mode 100644 arch/powerpc/boot/dts/p1020rdb.dts
>=20
> diff --git a/arch/powerpc/boot/dts/p1020rdb.dts=20
> b/arch/powerpc/boot/dts/p1020rdb.dts
> new file mode 100644
> index 0000000..de5672c
> --- /dev/null
> +++ b/arch/powerpc/boot/dts/p1020rdb.dts
> @@ -0,0 +1,477 @@
> +/*
> + * P1020 RDB Device Tree Source
> + *
> + * Copyright 2009 Freescale Semiconductor Inc.
> + *
> + * This program is free software; you can redistribute  it and/or=20
> +modify it
> + * under  the terms of  the GNU General  Public License as=20
> published by=20
> +the
> + * Free Software Foundation;  either version 2 of the =20
> License, or (at=20
> +your
> + * option) any later version.
> + */
> +
> +/dts-v1/;
> +/ {
> +	model =3D "fsl,P1020";
> +	compatible =3D "fsl,P1020RDB";
> +	#address-cells =3D <2>;
> +	#size-cells =3D <2>;
> +
> +	aliases {
> +		serial0 =3D &serial0;
> +		serial1 =3D &serial1;
> +		pci0 =3D &pci0;
> +		pci1 =3D &pci1;
> +	};
> +
> +	cpus {
> +		#address-cells =3D <1>;
> +		#size-cells =3D <0>;
> +
> +		PowerPC,P1020@0 {
> +			device_type =3D "cpu";
> +			reg =3D <0x0>;
> +			next-level-cache =3D <&L2>;
> +		};
> +
> +		PowerPC,P1020@1 {
> +			device_type =3D "cpu";
> +			reg =3D <0x1>;
> +			next-level-cache =3D <&L2>;
> +		};
> +	};
> +
> +	memory {
> +		device_type =3D "memory";
> +	};
> +
> +	localbus@ffe05000 {
> +		#address-cells =3D <2>;
> +		#size-cells =3D <1>;
> +		compatible =3D "fsl,p1020-elbc", "fsl,elbc", "simple-bus";
> +		reg =3D <0 0xffe05000 0 0x1000>;
> +		interrupts =3D <19 2>;
> +		interrupt-parent =3D <&mpic>;
> +
> +		/* NOR and NAND Flashes */
> +		ranges =3D <0x0 0x0 0x0 0xef000000 0x01000000
> +			  0x1 0x0 0x0 0xffa00000 0x00040000
> +			  0x2 0x0 0x0 0xffb00000 0x00020000>;
> +
> +		nor@0,0 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <1>;
> +			compatible =3D "cfi-flash";
> +			reg =3D <0x0 0x0 0x1000000>;
> +			bank-width =3D <2>;
> +			device-width =3D <1>;
> +
> +			partition@0 {
> +				/* This location must not be altered  */
> +				/* 256KB for Vitesse 7385=20
> Switch firmware */
> +				reg =3D <0x0 0x00040000>;
> +				label =3D "NOR (RO) Vitesse-7385=20
> Firmware";
> +				read-only;
> +			};
> +
> +			partition@40000 {
> +				/* 256KB for DTB Image */
> +				reg =3D <0x00040000 0x00040000>;
> +				label =3D "NOR (RO) DTB Image";
> +				read-only;
> +			};
> +
> +			partition@80000 {
> +				/* 3.5 MB for Linux Kernel Image */
> +				reg =3D <0x00080000 0x00380000>;
> +				label =3D "NOR (RO) Linux Kernel Image";
> +				read-only;
> +			};
> +
> +			partition@400000 {
> +				/* 11MB for JFFS2 based Root=20
> file System */
> +				reg =3D <0x00400000 0x00b00000>;
> +				label =3D "NOR (RW) JFFS2 Root=20
> File System";
> +			};
> +
> +			partition@f00000 {
> +				/* This location must not be altered  */
> +				/* 512KB for u-boot Bootloader Image */
> +				/* 512KB for u-boot Environment=20
> Variables */
> +				reg =3D <0x00f00000 0x00100000>;
> +				label =3D "NOR (RO) U-Boot Image";
> +				read-only;
> +			};
> +		};
> +
> +		nand@1,0 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <1>;
> +			compatible =3D "fsl,p1020-fcm-nand",
> +				     "fsl,elbc-fcm-nand";
> +			reg =3D <0x1 0x0 0x40000>;
> +
> +			partition@0 {
> +				/* This location must not be altered  */
> +				/* 1MB for u-boot Bootloader Image */
> +				reg =3D <0x0 0x00100000>;
> +				label =3D "NAND (RO) U-Boot Image";
> +				read-only;
> +			};
> +
> +			partition@100000 {
> +				/* 1MB for DTB Image */
> +				reg =3D <0x00100000 0x00100000>;
> +				label =3D "NAND (RO) DTB Image";
> +				read-only;
> +			};
> +
> +			partition@200000 {
> +				/* 4MB for Linux Kernel Image */
> +				reg =3D <0x00200000 0x00400000>;
> +				label =3D "NAND (RO) Linux Kernel Image";
> +				read-only;
> +			};
> +
> +			partition@600000 {
> +				/* 4MB for Compressed Root file=20
> System Image */
> +				reg =3D <0x00600000 0x00400000>;
> +				label =3D "NAND (RO) Compressed=20
> RFS Image";
> +				read-only;
> +			};
> +
> +			partition@a00000 {
> +				/* 7MB for JFFS2 based Root=20
> file System */
> +				reg =3D <0x00a00000 0x00700000>;
> +				label =3D "NAND (RW) JFFS2 Root=20
> File System";
> +			};
> +
> +			partition@1100000 {
> +				/* 15MB for JFFS2 based Root=20
> file System */
> +				reg =3D <0x01100000 0x00f00000>;
> +				label =3D "NAND (RW) Writable User area";
> +			};
> +		};
> +
> +		L2switch@2,0 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <1>;
> +			compatible =3D "vitesse-7385";
> +			reg =3D <0x2 0x0 0x20000>;
> +		};
> +
> +	};
> +
> +	soc@ffe00000 {
> +		#address-cells =3D <1>;
> +		#size-cells =3D <1>;
> +		device_type =3D "soc";
> +		compatible =3D "fsl,p1020-immr", "simple-bus";
> +		ranges =3D <0x0  0x0 0xffe00000 0x100000>;
> +		bus-frequency =3D <0>;		// Filled out by uboot.
> +
> +		ecm-law@0 {
> +			compatible =3D "fsl,ecm-law";
> +			reg =3D <0x0 0x1000>;
> +			fsl,num-laws =3D <12>;
> +		};
> +
> +		ecm@1000 {
> +			compatible =3D "fsl,p1020-ecm", "fsl,ecm";
> +			reg =3D <0x1000 0x1000>;
> +			interrupts =3D <16 2>;
> +			interrupt-parent =3D <&mpic>;
> +		};
> +
> +		memory-controller@2000 {
> +			compatible =3D "fsl,p1020-memory-controller";
> +			reg =3D <0x2000 0x1000>;
> +			interrupt-parent =3D <&mpic>;
> +			interrupts =3D <16 2>;
> +		};
> +
> +		i2c@3000 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <0>;
> +			cell-index =3D <0>;
> +			compatible =3D "fsl-i2c";
> +			reg =3D <0x3000 0x100>;
> +			interrupts =3D <43 2>;
> +			interrupt-parent =3D <&mpic>;
> +			dfsrr;
> +			rtc@68 {
> +				compatible =3D "dallas,ds1339";
> +				reg =3D <0x68>;
> +			};
> +		};
> +
> +		i2c@3100 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <0>;
> +			cell-index =3D <1>;
> +			compatible =3D "fsl-i2c";
> +			reg =3D <0x3100 0x100>;
> +			interrupts =3D <43 2>;
> +			interrupt-parent =3D <&mpic>;
> +			dfsrr;
> +		};
> +
> +		serial0: serial@4500 {
> +			cell-index =3D <0>;
> +			device_type =3D "serial";
> +			compatible =3D "ns16550";
> +			reg =3D <0x4500 0x100>;
> +			clock-frequency =3D <0>;
> +			interrupts =3D <42 2>;
> +			interrupt-parent =3D <&mpic>;
> +		};
> +
> +		serial1: serial@4600 {
> +			cell-index =3D <1>;
> +			device_type =3D "serial";
> +			compatible =3D "ns16550";
> +			reg =3D <0x4600 0x100>;
> +			clock-frequency =3D <0>;
> +			interrupts =3D <42 2>;
> +			interrupt-parent =3D <&mpic>;
> +		};
> +
> +		spi@7000 {
> +			cell-index =3D <0>;
> +			#address-cells =3D <1>;
> +			#size-cells =3D <0>;
> +			compatible =3D "fsl,espi";
> +			reg =3D <0x7000 0x1000>;
> +			interrupts =3D <59 0x2>;
> +			interrupt-parent =3D <&mpic>;
> +			mode =3D "cpu";
> +
> +			fsl_m25p80@0 {
> +				#address-cells =3D <1>;
> +				#size-cells =3D <1>;
> +				compatible =3D "fsl,espi-flash";
> +				reg =3D <0>;
> +				linux,modalias =3D "fsl_m25p80";
> +				modal =3D "s25sl128b";
> +				spi-max-frequency =3D <50000000>;
> +				mode =3D <0>;
> +
> +				partition@0 {
> +					/* 512KB for u-boot=20
> Bootloader Image */
> +					reg =3D <0x0 0x00080000>;
> +					label =3D "SPI (RO) U-Boot Image";
> +					read-only;
> +				};
> +
> +				partition@80000 {
> +					/* 512KB for DTB Image */
> +					reg =3D <0x00080000 0x00080000>;
> +					label =3D "SPI (RO) DTB Image";
> +					read-only;
> +				};
> +
> +				partition@100000 {
> +					/* 4MB for Linux Kernel Image */
> +					reg =3D <0x00100000 0x00400000>;
> +					label =3D "SPI (RO) Linux=20
> Kernel Image";
> +					read-only;
> +				};
> +
> +				partition@500000 {
> +					/* 4MB for Compressed=20
> RFS Image */
> +					reg =3D <0x00500000 0x00400000>;
> +					label =3D "SPI (RO)=20
> Compressed RFS Image";
> +					read-only;
> +				};
> +
> +				partition@900000 {
> +					/* 7MB for JFFS2 based RFS */
> +					reg =3D <0x00900000 0x00700000>;
> +					label =3D "SPI (RW) JFFS2 RFS";
> +				};
> +			};
> +		};
> +
> +		gpio: gpio-controller@f000 {
> +			#gpio-cells =3D <2>;
> +			compatible =3D "fsl,mpc8572-gpio";
> +			reg =3D <0xf000 0x100>;
> +			interrupts =3D <47 0x2>;
> +			interrupt-parent =3D <&mpic>;
> +			gpio-controller;
> +		};
> +
> +		L2: l2-cache-controller@20000 {
> +			compatible =3D "fsl,p1020-l2-cache-controller";
> +			reg =3D <0x20000 0x1000>;
> +			cache-line-size =3D <32>;	// 32 bytes
> +			cache-size =3D <0x40000>; // L2,256K
> +			interrupt-parent =3D <&mpic>;
> +			interrupts =3D <16 2>;
> +		};
> +
> +		dma@21300 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <1>;
> +			compatible =3D "fsl,eloplus-dma";
> +			reg =3D <0x21300 0x4>;
> +			ranges =3D <0x0 0x21100 0x200>;
> +			cell-index =3D <0>;
> +			dma-channel@0 {
> +				compatible =3D "fsl,eloplus-dma-channel";
> +				reg =3D <0x0 0x80>;
> +				cell-index =3D <0>;
> +				interrupt-parent =3D <&mpic>;
> +				interrupts =3D <20 2>;
> +			};
> +			dma-channel@80 {
> +				compatible =3D "fsl,eloplus-dma-channel";
> +				reg =3D <0x80 0x80>;
> +				cell-index =3D <1>;
> +				interrupt-parent =3D <&mpic>;
> +				interrupts =3D <21 2>;
> +			};
> +			dma-channel@100 {
> +				compatible =3D "fsl,eloplus-dma-channel";
> +				reg =3D <0x100 0x80>;
> +				cell-index =3D <2>;
> +				interrupt-parent =3D <&mpic>;
> +				interrupts =3D <22 2>;
> +			};
> +			dma-channel@180 {
> +				compatible =3D "fsl,eloplus-dma-channel";
> +				reg =3D <0x180 0x80>;
> +				cell-index =3D <3>;
> +				interrupt-parent =3D <&mpic>;
> +				interrupts =3D <23 2>;
> +			};
> +		};
> +
> +		usb@22000 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <0>;
> +			compatible =3D "fsl-usb2-dr";
> +			reg =3D <0x22000 0x1000>;
> +			interrupt-parent =3D <&mpic>;
> +			interrupts =3D <28 0x2>;
> +			phy_type =3D "ulpi";
> +		};
> +
> +		usb@23000 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <0>;
> +			compatible =3D "fsl-usb2-dr";
> +			reg =3D <0x23000 0x1000>;
> +			interrupt-parent =3D <&mpic>;
> +			interrupts =3D <46 0x2>;
> +			phy_type =3D "ulpi";
> +		};
> +
> +		sdhci@2e000 {
> +			compatible =3D "fsl,p1020-esdhc", "fsl,esdhc";
> +			reg =3D <0x2e000 0x1000>;
> +			interrupts =3D <72 0x2>;
> +			interrupt-parent =3D <&mpic>;
> +			/* Filled in by U-Boot */
> +			clock-frequency =3D <0>;
> +		};
> +
> +		crypto@30000 {
> +			compatible =3D "fsl,sec3.1",=20
> "fsl,sec3.0", "fsl,sec2.4",
> +				     "fsl,sec2.2",=20
> "fsl,sec2.1", "fsl,sec2.0";
> +			reg =3D <0x30000 0x10000>;
> +			interrupts =3D <45 2 58 2>;
> +			interrupt-parent =3D <&mpic>;
> +			fsl,num-channels =3D <4>;
> +			fsl,channel-fifo-len =3D <24>;
> +			fsl,exec-units-mask =3D <0xbfe>;
> +			fsl,descriptor-types-mask =3D <0x3ab0ebf>;
> +		};
> +
> +		mpic: pic@40000 {
> +			interrupt-controller;
> +			#address-cells =3D <0>;
> +			#interrupt-cells =3D <2>;
> +			reg =3D <0x40000 0x40000>;
> +			compatible =3D "chrp,open-pic";
> +			device_type =3D "open-pic";
> +		};
> +
> +		msi@41600 {
> +			compatible =3D "fsl,p1020-msi", "fsl,mpic-msi";
> +			reg =3D <0x41600 0x80>;
> +			msi-available-ranges =3D <0 0x100>;
> +			interrupts =3D <
> +				0xe0 0
> +				0xe1 0
> +				0xe2 0
> +				0xe3 0
> +				0xe4 0
> +				0xe5 0
> +				0xe6 0
> +				0xe7 0>;
> +			interrupt-parent =3D <&mpic>;
> +		};
> +
> +		global-utilities@e0000 {	//global utilities block
> +			compatible =3D "fsl,p1020-guts";
> +			reg =3D <0xe0000 0x1000>;
> +			fsl,has-rstcr;
> +		};
> +	};
> +
> +	pci0: pcie@ffe09000 {
> +		compatible =3D "fsl,mpc8548-pcie";
> +		device_type =3D "pci";
> +		#interrupt-cells =3D <1>;
> +		#size-cells =3D <2>;
> +		#address-cells =3D <3>;
> +		reg =3D <0 0xffe09000 0 0x1000>;
> +		bus-range =3D <0 255>;
> +		ranges =3D <0x2000000 0x0 0xa0000000 0 0xa0000000=20
> 0x0 0x20000000
> +			  0x1000000 0x0 0x00000000 0 0xffc30000=20
> 0x0 0x10000>;
> +		clock-frequency =3D <33333333>;
> +		interrupt-parent =3D <&mpic>;
> +		interrupts =3D <16 2>;
> +		pcie@0 {
> +			reg =3D <0x0 0x0 0x0 0x0 0x0>;
> +			#size-cells =3D <2>;
> +			#address-cells =3D <3>;
> +			device_type =3D "pci";
> +			ranges =3D <0x2000000 0x0 0xa0000000
> +				  0x2000000 0x0 0xa0000000
> +				  0x0 0x20000000
> +
> +				  0x1000000 0x0 0x0
> +				  0x1000000 0x0 0x0
> +				  0x0 0x100000>;
> +		};
> +	};
> +
> +	pci1: pcie@ffe0a000 {
> +		compatible =3D "fsl,mpc8548-pcie";
> +		device_type =3D "pci";
> +		#interrupt-cells =3D <1>;
> +		#size-cells =3D <2>;
> +		#address-cells =3D <3>;
> +		reg =3D <0 0xffe0a000 0 0x1000>;
> +		bus-range =3D <0 255>;
> +		ranges =3D <0x2000000 0x0 0xc0000000 0 0xc0000000=20
> 0x0 0x20000000
> +			  0x1000000 0x0 0x00000000 0 0xffc20000=20
> 0x0 0x10000>;
> +		clock-frequency =3D <33333333>;
> +		interrupt-parent =3D <&mpic>;
> +		interrupts =3D <16 2>;
> +		pcie@0 {
> +			reg =3D <0x0 0x0 0x0 0x0 0x0>;
> +			#size-cells =3D <2>;
> +			#address-cells =3D <3>;
> +			device_type =3D "pci";
> +			ranges =3D <0x2000000 0x0 0xc0000000
> +				  0x2000000 0x0 0xc0000000
> +				  0x0 0x20000000
> +
> +				  0x1000000 0x0 0x0
> +				  0x1000000 0x0 0x0
> +				  0x0 0x100000>;
> +		};
> +	};
> +};
> diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c=20
> b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
> index c8468de..495bd8b 100644
> --- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
> +++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
> @@ -113,6 +113,7 @@ static int __init mpc85xxrdb_publish_devices(void)
>  	return of_platform_bus_probe(NULL, mpc85xxrdb_ids,=20
> NULL);  }  machine_device_initcall(p2020_rdb,=20
> mpc85xxrdb_publish_devices);
> +machine_device_initcall(p1020_rdb, mpc85xxrdb_publish_devices);
> =20
>  /*
>   * Called very early, device-tree isn't unflattened @@=20
> -126,6 +127,15 @@ static int __init p2020_rdb_probe(void)
>  	return 0;
>  }
> =20
> +static int __init p1020_rdb_probe(void) {
> +	unsigned long root =3D of_get_flat_dt_root();
> +
> +	if (of_flat_dt_is_compatible(root, "fsl,P1020RDB"))
> +		return 1;
> +	return 0;
> +}
> +
>  define_machine(p2020_rdb) {
>  	.name			=3D "P2020 RDB",
>  	.probe			=3D p2020_rdb_probe,
> @@ -139,3 +149,17 @@ define_machine(p2020_rdb) {
>  	.calibrate_decr		=3D generic_calibrate_decr,
>  	.progress		=3D udbg_progress,
>  };
> +
> +define_machine(p1020_rdb) {
> +	.name			=3D "P1020 RDB",
> +	.probe			=3D p1020_rdb_probe,
> +	.setup_arch		=3D mpc85xx_rdb_setup_arch,
> +	.init_IRQ		=3D mpc85xx_rdb_pic_init,
> +#ifdef CONFIG_PCI
> +	.pcibios_fixup_bus	=3D fsl_pcibios_fixup_bus,
> +#endif
> +	.get_irq		=3D mpic_get_irq,
> +	.restart		=3D fsl_rstcr_restart,
> +	.calibrate_decr		=3D generic_calibrate_decr,
> +	.progress		=3D udbg_progress,
> +};
> --
> 1.5.6.5
>=20
>=20

^ permalink raw reply

* RE: [PATCH][v2] powerpc/85xx: Create dts for each core in CAMP mode for P2020RDB
From: Aggrwal Poonam-B10812 @ 2009-09-22 10:21 UTC (permalink / raw)
  To: Aggrwal Poonam-B10812, linuxppc-dev
In-Reply-To: <1253380436-1590-1-git-send-email-poonam.aggrwal@freescale.com>

Hello Kumar

Could you please accept this patch if it is fine.

Regards
Poonam=20

> -----Original Message-----
> From: Aggrwal Poonam-B10812=20
> Sent: Saturday, September 19, 2009 10:44 PM
> To: linuxppc-dev@ozlabs.org
> Cc: Aggrwal Poonam-B10812
> Subject: [PATCH][v2] powerpc/85xx: Create dts for each core=20
> in CAMP mode for P2020RDB
>=20
> This patch creates the dts files for each core and splits the=20
> devices between the two cores for P2020RDB.
>=20
> core0 has memory, L2, i2c, spi, dma1, usb, eth0, eth1,=20
> crypto, global-util, pci0
> core1 has L2, dma2, eth0, pci1, msi.
>=20
> MPIC is shared between two cores but each core will protect=20
> its interrupts from other core by using "protected-sources" of mpic.
>=20
> Signed-off-by: Poonam Aggrwal <poonam.aggrwal@freescale.com>
> ---
> - based on=20
> http://www.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git
> - branch->next
> - Removed interrupt properties for serial ports to make them=20
> work in polling mode.
>  arch/powerpc/boot/dts/p2020rdb_camp_core0.dts |  363=20
> +++++++++++++++++++++++++ =20
> arch/powerpc/boot/dts/p2020rdb_camp_core1.dts |  184 +++++++++++++
>  arch/powerpc/platforms/85xx/mpc85xx_rdb.c     |   10 +-
>  3 files changed, 556 insertions(+), 1 deletions(-)  create=20
> mode 100644 arch/powerpc/boot/dts/p2020rdb_camp_core0.dts
>  create mode 100644 arch/powerpc/boot/dts/p2020rdb_camp_core1.dts
>=20
> diff --git a/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts=20
> b/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts
> new file mode 100644
> index 0000000..0fe93d0
> --- /dev/null
> +++ b/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts
> @@ -0,0 +1,363 @@
> +/*
> + * P2020 RDB  Core0 Device Tree Source in CAMP mode.
> + *
> + * In CAMP mode, each core needs to have its own dts. Only=20
> mpic and L2=20
> +cache
> + * can be shared, all the other devices must be assigned to=20
> one core only.
> + * This dts file allows core0 to have memory, l2, i2c, spi,=20
> gpio, dma1,=20
> +usb,
> + * eth1, eth2, sdhc, crypto, global-util, pci0.
> + *
> + * Copyright 2009 Freescale Semiconductor Inc.
> + *
> + * This program is free software; you can redistribute  it and/or=20
> +modify it
> + * under  the terms of  the GNU General  Public License as=20
> published by=20
> +the
> + * Free Software Foundation;  either version 2 of the =20
> License, or (at=20
> +your
> + * option) any later version.
> + */
> +
> +/dts-v1/;
> +/ {
> +	model =3D "fsl,P2020";
> +	compatible =3D "fsl,P2020RDB", "fsl,MPC85XXRDB-CAMP";
> +	#address-cells =3D <2>;
> +	#size-cells =3D <2>;
> +
> +	aliases {
> +		ethernet1 =3D &enet1;
> +		ethernet2 =3D &enet2;
> +		serial0 =3D &serial0;
> +		pci0 =3D &pci0;
> +	};
> +
> +	cpus {
> +		#address-cells =3D <1>;
> +		#size-cells =3D <0>;
> +
> +		PowerPC,P2020@0 {
> +			device_type =3D "cpu";
> +			reg =3D <0x0>;
> +			next-level-cache =3D <&L2>;
> +		};
> +	};
> +
> +	memory {
> +		device_type =3D "memory";
> +	};
> +
> +	soc@ffe00000 {
> +		#address-cells =3D <1>;
> +		#size-cells =3D <1>;
> +		device_type =3D "soc";
> +		compatible =3D "fsl,p2020-immr", "simple-bus";
> +		ranges =3D <0x0  0x0 0xffe00000 0x100000>;
> +		bus-frequency =3D <0>;		// Filled out by uboot.
> +
> +		ecm-law@0 {
> +			compatible =3D "fsl,ecm-law";
> +			reg =3D <0x0 0x1000>;
> +			fsl,num-laws =3D <12>;
> +		};
> +
> +		ecm@1000 {
> +			compatible =3D "fsl,p2020-ecm", "fsl,ecm";
> +			reg =3D <0x1000 0x1000>;
> +			interrupts =3D <17 2>;
> +			interrupt-parent =3D <&mpic>;
> +		};
> +
> +		memory-controller@2000 {
> +			compatible =3D "fsl,p2020-memory-controller";
> +			reg =3D <0x2000 0x1000>;
> +			interrupt-parent =3D <&mpic>;
> +			interrupts =3D <18 2>;
> +		};
> +
> +		i2c@3000 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <0>;
> +			cell-index =3D <0>;
> +			compatible =3D "fsl-i2c";
> +			reg =3D <0x3000 0x100>;
> +			interrupts =3D <43 2>;
> +			interrupt-parent =3D <&mpic>;
> +			dfsrr;
> +			rtc@68 {
> +				compatible =3D "dallas,ds1339";
> +				reg =3D <0x68>;
> +			};
> +		};
> +
> +		i2c@3100 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <0>;
> +			cell-index =3D <1>;
> +			compatible =3D "fsl-i2c";
> +			reg =3D <0x3100 0x100>;
> +			interrupts =3D <43 2>;
> +			interrupt-parent =3D <&mpic>;
> +			dfsrr;
> +		};
> +
> +		serial0: serial@4500 {
> +			cell-index =3D <0>;
> +			device_type =3D "serial";
> +			compatible =3D "ns16550";
> +			reg =3D <0x4500 0x100>;
> +			clock-frequency =3D <0>;
> +		};
> +
> +		spi@7000 {
> +			cell-index =3D <0>;
> +			#address-cells =3D <1>;
> +			#size-cells =3D <0>;
> +			compatible =3D "fsl,espi";
> +			reg =3D <0x7000 0x1000>;
> +			interrupts =3D <59 0x2>;
> +			interrupt-parent =3D <&mpic>;
> +			mode =3D "cpu";
> +
> +			fsl_m25p80@0 {
> +				#address-cells =3D <1>;
> +				#size-cells =3D <1>;
> +				compatible =3D "fsl,espi-flash";
> +				reg =3D <0>;
> +				linux,modalias =3D "fsl_m25p80";
> +				modal =3D "s25sl128b";
> +				spi-max-frequency =3D <50000000>;
> +				mode =3D <0>;
> +
> +				partition@0 {
> +					/* 512KB for u-boot=20
> Bootloader Image */
> +					reg =3D <0x0 0x00080000>;
> +					label =3D "SPI (RO) U-Boot Image";
> +					read-only;
> +				};
> +
> +				partition@80000 {
> +					/* 512KB for DTB Image */
> +					reg =3D <0x00080000 0x00080000>;
> +					label =3D "SPI (RO) DTB Image";
> +					read-only;
> +				};
> +
> +				partition@100000 {
> +					/* 4MB for Linux Kernel Image */
> +					reg =3D <0x00100000 0x00400000>;
> +					label =3D "SPI (RO) Linux=20
> Kernel Image";
> +					read-only;
> +				};
> +
> +				partition@500000 {
> +					/* 4MB for Compressed=20
> RFS Image */
> +					reg =3D <0x00500000 0x00400000>;
> +					label =3D "SPI (RO)=20
> Compressed RFS Image";
> +					read-only;
> +				};
> +
> +				partition@900000 {
> +					/* 7MB for JFFS2 based RFS */
> +					reg =3D <0x00900000 0x00700000>;
> +					label =3D "SPI (RW) JFFS2 RFS";
> +				};
> +			};
> +		};
> +
> +		gpio: gpio-controller@f000 {
> +			#gpio-cells =3D <2>;
> +			compatible =3D "fsl,mpc8572-gpio";
> +			reg =3D <0xf000 0x100>;
> +			interrupts =3D <47 0x2>;
> +			interrupt-parent =3D <&mpic>;
> +			gpio-controller;
> +		};
> +
> +		L2: l2-cache-controller@20000 {
> +			compatible =3D "fsl,p2020-l2-cache-controller";
> +			reg =3D <0x20000 0x1000>;
> +			cache-line-size =3D <32>;	// 32 bytes
> +			cache-size =3D <0x80000>; // L2,512K
> +			interrupt-parent =3D <&mpic>;
> +			interrupts =3D <16 2>;
> +		};
> +
> +		dma@21300 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <1>;
> +			compatible =3D "fsl,eloplus-dma";
> +			reg =3D <0x21300 0x4>;
> +			ranges =3D <0x0 0x21100 0x200>;
> +			cell-index =3D <0>;
> +			dma-channel@0 {
> +				compatible =3D "fsl,eloplus-dma-channel";
> +				reg =3D <0x0 0x80>;
> +				cell-index =3D <0>;
> +				interrupt-parent =3D <&mpic>;
> +				interrupts =3D <20 2>;
> +			};
> +			dma-channel@80 {
> +				compatible =3D "fsl,eloplus-dma-channel";
> +				reg =3D <0x80 0x80>;
> +				cell-index =3D <1>;
> +				interrupt-parent =3D <&mpic>;
> +				interrupts =3D <21 2>;
> +			};
> +			dma-channel@100 {
> +				compatible =3D "fsl,eloplus-dma-channel";
> +				reg =3D <0x100 0x80>;
> +				cell-index =3D <2>;
> +				interrupt-parent =3D <&mpic>;
> +				interrupts =3D <22 2>;
> +			};
> +			dma-channel@180 {
> +				compatible =3D "fsl,eloplus-dma-channel";
> +				reg =3D <0x180 0x80>;
> +				cell-index =3D <3>;
> +				interrupt-parent =3D <&mpic>;
> +				interrupts =3D <23 2>;
> +			};
> +		};
> +
> +		usb@22000 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <0>;
> +			compatible =3D "fsl-usb2-dr";
> +			reg =3D <0x22000 0x1000>;
> +			interrupt-parent =3D <&mpic>;
> +			interrupts =3D <28 0x2>;
> +			phy_type =3D "ulpi";
> +		};
> +
> +		mdio@24520 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <0>;
> +			compatible =3D "fsl,gianfar-mdio";
> +			reg =3D <0x24520 0x20>;
> +
> +			phy0: ethernet-phy@0 {
> +				interrupt-parent =3D <&mpic>;
> +				interrupts =3D <3 1>;
> +				reg =3D <0x0>;
> +			};
> +			phy1: ethernet-phy@1 {
> +				interrupt-parent =3D <&mpic>;
> +				interrupts =3D <3 1>;
> +				reg =3D <0x1>;
> +			};
> +		};
> +
> +		mdio@25520 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <0>;
> +			compatible =3D "fsl,gianfar-tbi";
> +			reg =3D <0x26520 0x20>;
> +
> +			tbi0: tbi-phy@11 {
> +				reg =3D <0x11>;
> +				device_type =3D "tbi-phy";
> +			};
> +		};
> +
> +		enet1: ethernet@25000 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <1>;
> +			cell-index =3D <1>;
> +			device_type =3D "network";
> +			model =3D "eTSEC";
> +			compatible =3D "gianfar";
> +			reg =3D <0x25000 0x1000>;
> +			ranges =3D <0x0 0x25000 0x1000>;
> +			local-mac-address =3D [ 00 00 00 00 00 00 ];
> +			interrupts =3D <35 2 36 2 40 2>;
> +			interrupt-parent =3D <&mpic>;
> +			tbi-handle =3D <&tbi0>;
> +			phy-handle =3D <&phy0>;
> +			phy-connection-type =3D "sgmii";
> +
> +		};
> +
> +		enet2: ethernet@26000 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <1>;
> +			cell-index =3D <2>;
> +			device_type =3D "network";
> +			model =3D "eTSEC";
> +			compatible =3D "gianfar";
> +			reg =3D <0x26000 0x1000>;
> +			ranges =3D <0x0 0x26000 0x1000>;
> +			local-mac-address =3D [ 00 00 00 00 00 00 ];
> +			interrupts =3D <31 2 32 2 33 2>;
> +			interrupt-parent =3D <&mpic>;
> +			phy-handle =3D <&phy1>;
> +			phy-connection-type =3D "rgmii-id";
> +		};
> +
> +		sdhci@2e000 {
> +			compatible =3D "fsl,p2020-esdhc", "fsl,esdhc";
> +			reg =3D <0x2e000 0x1000>;
> +			interrupts =3D <72 0x2>;
> +			interrupt-parent =3D <&mpic>;
> +			/* Filled in by U-Boot */
> +			clock-frequency =3D <0>;
> +		};
> +
> +		crypto@30000 {
> +			compatible =3D "fsl,sec3.1",=20
> "fsl,sec3.0", "fsl,sec2.4",
> +				     "fsl,sec2.2",=20
> "fsl,sec2.1", "fsl,sec2.0";
> +			reg =3D <0x30000 0x10000>;
> +			interrupts =3D <45 2 58 2>;
> +			interrupt-parent =3D <&mpic>;
> +			fsl,num-channels =3D <4>;
> +			fsl,channel-fifo-len =3D <24>;
> +			fsl,exec-units-mask =3D <0xbfe>;
> +			fsl,descriptor-types-mask =3D <0x3ab0ebf>;
> +		};
> +
> +		mpic: pic@40000 {
> +			interrupt-controller;
> +			#address-cells =3D <0>;
> +			#interrupt-cells =3D <2>;
> +			reg =3D <0x40000 0x40000>;
> +			compatible =3D "chrp,open-pic";
> +			device_type =3D "open-pic";
> +			protected-sources =3D <
> +			42 76 77 78 79 /* serial1 , dma2 */
> +			29 30 34 26 /* enet0, pci1 */
> +			0xe0 0xe1 0xe2 0xe3 /* msi */
> +			0xe4 0xe5 0xe6 0xe7
> +			>;
> +		};
> +
> +		global-utilities@e0000 {
> +			compatible =3D "fsl,p2020-guts";
> +			reg =3D <0xe0000 0x1000>;
> +			fsl,has-rstcr;
> +		};
> +	};
> +
> +	pci0: pcie@ffe09000 {
> +		compatible =3D "fsl,mpc8548-pcie";
> +		device_type =3D "pci";
> +		#interrupt-cells =3D <1>;
> +		#size-cells =3D <2>;
> +		#address-cells =3D <3>;
> +		reg =3D <0 0xffe09000 0 0x1000>;
> +		bus-range =3D <0 255>;
> +		ranges =3D <0x2000000 0x0 0xa0000000 0 0xa0000000=20
> 0x0 0x20000000
> +			  0x1000000 0x0 0x00000000 0 0xffc30000=20
> 0x0 0x10000>;
> +		clock-frequency =3D <33333333>;
> +		interrupt-parent =3D <&mpic>;
> +		interrupts =3D <25 2>;
> +		pcie@0 {
> +			reg =3D <0x0 0x0 0x0 0x0 0x0>;
> +			#size-cells =3D <2>;
> +			#address-cells =3D <3>;
> +			device_type =3D "pci";
> +			ranges =3D <0x2000000 0x0 0xa0000000
> +				  0x2000000 0x0 0xa0000000
> +				  0x0 0x20000000
> +
> +				  0x1000000 0x0 0x0
> +				  0x1000000 0x0 0x0
> +				  0x0 0x100000>;
> +		};
> +	};
> +};
> diff --git a/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts=20
> b/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts
> new file mode 100644
> index 0000000..e95a512
> --- /dev/null
> +++ b/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts
> @@ -0,0 +1,184 @@
> +/*
> + * P2020 RDB Core1 Device Tree Source in CAMP mode.
> + *
> + * In CAMP mode, each core needs to have its own dts. Only=20
> mpic and L2=20
> +cache
> + * can be shared, all the other devices must be assigned to=20
> one core only.
> + * This dts allows core1 to have l2, dma2, eth0, pci1, msi.
> + *
> + * Please note to add "-b 1" for core1's dts compiling.
> + *
> + * Copyright 2009 Freescale Semiconductor Inc.
> + *
> + * This program is free software; you can redistribute  it and/or=20
> +modify it
> + * under  the terms of  the GNU General  Public License as=20
> published by=20
> +the
> + * Free Software Foundation;  either version 2 of the =20
> License, or (at=20
> +your
> + * option) any later version.
> + */
> +
> +/dts-v1/;
> +/ {
> +	model =3D "fsl,P2020";
> +	compatible =3D "fsl,P2020RDB", "fsl,MPC85XXRDB-CAMP";
> +	#address-cells =3D <2>;
> +	#size-cells =3D <2>;
> +
> +	aliases {
> +		ethernet0 =3D &enet0;
> +		serial0 =3D &serial0;
> +		pci1 =3D &pci1;
> +	};
> +
> +	cpus {
> +		#address-cells =3D <1>;
> +		#size-cells =3D <0>;
> +
> +		PowerPC,P2020@1 {
> +			device_type =3D "cpu";
> +			reg =3D <0x1>;
> +			next-level-cache =3D <&L2>;
> +		};
> +	};
> +
> +	memory {
> +		device_type =3D "memory";
> +	};
> +
> +	soc@ffe00000 {
> +		#address-cells =3D <1>;
> +		#size-cells =3D <1>;
> +		device_type =3D "soc";
> +		compatible =3D "fsl,p2020-immr", "simple-bus";
> +		ranges =3D <0x0  0x0 0xffe00000 0x100000>;
> +		bus-frequency =3D <0>;		// Filled out by uboot.
> +
> +		serial0: serial@4600 {
> +			cell-index =3D <1>;
> +			device_type =3D "serial";
> +			compatible =3D "ns16550";
> +			reg =3D <0x4600 0x100>;
> +			clock-frequency =3D <0>;
> +		};
> +
> +		dma@c300 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <1>;
> +			compatible =3D "fsl,eloplus-dma";
> +			reg =3D <0xc300 0x4>;
> +			ranges =3D <0x0 0xc100 0x200>;
> +			cell-index =3D <1>;
> +			dma-channel@0 {
> +				compatible =3D "fsl,eloplus-dma-channel";
> +				reg =3D <0x0 0x80>;
> +				cell-index =3D <0>;
> +				interrupt-parent =3D <&mpic>;
> +				interrupts =3D <76 2>;
> +			};
> +			dma-channel@80 {
> +				compatible =3D "fsl,eloplus-dma-channel";
> +				reg =3D <0x80 0x80>;
> +				cell-index =3D <1>;
> +				interrupt-parent =3D <&mpic>;
> +				interrupts =3D <77 2>;
> +			};
> +			dma-channel@100 {
> +				compatible =3D "fsl,eloplus-dma-channel";
> +				reg =3D <0x100 0x80>;
> +				cell-index =3D <2>;
> +				interrupt-parent =3D <&mpic>;
> +				interrupts =3D <78 2>;
> +			};
> +			dma-channel@180 {
> +				compatible =3D "fsl,eloplus-dma-channel";
> +				reg =3D <0x180 0x80>;
> +				cell-index =3D <3>;
> +				interrupt-parent =3D <&mpic>;
> +				interrupts =3D <79 2>;
> +			};
> +		};
> +
> +		L2: l2-cache-controller@20000 {
> +			compatible =3D "fsl,p2020-l2-cache-controller";
> +			reg =3D <0x20000 0x1000>;
> +			cache-line-size =3D <32>;	// 32 bytes
> +			cache-size =3D <0x80000>; // L2,512K
> +			interrupt-parent =3D <&mpic>;
> +		};
> +
> +
> +		enet0: ethernet@24000 {
> +			#address-cells =3D <1>;
> +			#size-cells =3D <1>;
> +			cell-index =3D <0>;
> +			device_type =3D "network";
> +			model =3D "eTSEC";
> +			compatible =3D "gianfar";
> +			reg =3D <0x24000 0x1000>;
> +			ranges =3D <0x0 0x24000 0x1000>;
> +			local-mac-address =3D [ 00 00 00 00 00 00 ];
> +			interrupts =3D <29 2 30 2 34 2>;
> +			interrupt-parent =3D <&mpic>;
> +			fixed-link =3D <1 1 1000 0 0>;
> +			phy-connection-type =3D "rgmii-id";
> +
> +		};
> +
> +		mpic: pic@40000 {
> +			interrupt-controller;
> +			#address-cells =3D <0>;
> +			#interrupt-cells =3D <2>;
> +			reg =3D <0x40000 0x40000>;
> +			compatible =3D "chrp,open-pic";
> +			device_type =3D "open-pic";
> +			protected-sources =3D <
> +			17 18 43 42 59 47 /*ecm, mem, i2c,=20
> serial0, spi,gpio */
> +			16 20 21 22 23 28 	/* L2, dma1, USB */
> +			03 35 36 40 31 32 33 	/* mdio, enet1, enet2 */
> +			72 45 58 25 		/* sdhci,=20
> crypto , pci */
> +			>;
> +		};
> +
> +		msi@41600 {
> +			compatible =3D "fsl,p2020-msi", "fsl,mpic-msi";
> +			reg =3D <0x41600 0x80>;
> +			msi-available-ranges =3D <0 0x100>;
> +			interrupts =3D <
> +				0xe0 0
> +				0xe1 0
> +				0xe2 0
> +				0xe3 0
> +				0xe4 0
> +				0xe5 0
> +				0xe6 0
> +				0xe7 0>;
> +			interrupt-parent =3D <&mpic>;
> +		};
> +	};
> +
> +	pci1: pcie@ffe0a000 {
> +		compatible =3D "fsl,mpc8548-pcie";
> +		device_type =3D "pci";
> +		#interrupt-cells =3D <1>;
> +		#size-cells =3D <2>;
> +		#address-cells =3D <3>;
> +		reg =3D <0 0xffe0a000 0 0x1000>;
> +		bus-range =3D <0 255>;
> +		ranges =3D <0x2000000 0x0 0xc0000000 0 0xc0000000=20
> 0x0 0x20000000
> +			  0x1000000 0x0 0x00000000 0 0xffc20000=20
> 0x0 0x10000>;
> +		clock-frequency =3D <33333333>;
> +		interrupt-parent =3D <&mpic>;
> +		interrupts =3D <26 2>;
> +		pcie@0 {
> +			reg =3D <0x0 0x0 0x0 0x0 0x0>;
> +			#size-cells =3D <2>;
> +			#address-cells =3D <3>;
> +			device_type =3D "pci";
> +			ranges =3D <0x2000000 0x0 0xc0000000
> +				  0x2000000 0x0 0xc0000000
> +				  0x0 0x20000000
> +
> +				  0x1000000 0x0 0x0
> +				  0x1000000 0x0 0x0
> +				  0x0 0x100000>;
> +		};
> +	};
> +};
> diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c=20
> b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
> index c8468de..d173164 100644
> --- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
> +++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
> @@ -44,6 +44,7 @@ void __init mpc85xx_rdb_pic_init(void)
>  	struct mpic *mpic;
>  	struct resource r;
>  	struct device_node *np;
> +	unsigned long root =3D of_get_flat_dt_root();
> =20
>  	np =3D of_find_node_by_type(NULL, "open-pic");
>  	if (np =3D=3D NULL) {
> @@ -57,11 +58,18 @@ void __init mpc85xx_rdb_pic_init(void)
>  		return;
>  	}
> =20
> -	mpic =3D mpic_alloc(np, r.start,
> +	if (of_flat_dt_is_compatible(root, "fsl,85XXRDB-CAMP")) {
> +		mpic =3D mpic_alloc(np, r.start,
> +			MPIC_PRIMARY |
> +			MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS,
> +			0, 256, " OpenPIC  ");
> +	} else {
> +		mpic =3D mpic_alloc(np, r.start,
>  		  MPIC_PRIMARY | MPIC_WANTS_RESET |
>  		  MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
>  		  MPIC_SINGLE_DEST_CPU,
>  		  0, 256, " OpenPIC  ");
> +	}
> =20
>  	BUG_ON(mpic =3D=3D NULL);
>  	of_node_put(np);
> --
> 1.5.6.5
>=20
>=20

^ permalink raw reply

* Re: [PATCH] Re: [405EX] Bad page map in process ...
From: Benjamin Herrenschmidt @ 2009-09-22 10:13 UTC (permalink / raw)
  To: Weirich, Bernhard; +Cc: linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1253614035.7103.223.camel@pasglop>

On Tue, 2009-09-22 at 20:07 +1000, Benjamin Herrenschmidt wrote:
> On Tue, 2009-09-22 at 11:29 +0200, Weirich, Bernhard wrote:
> > Hello,
> > 
> > I found the cause of the problem.
> > My architecture does not define the _PAGE_SPECIAL macro, thus in pte-common.h line 32, it is defined as 0
> > And then in line 180, since _PAGE_SPECIAL is defined, the macro __HAVE_ARCH_PTE_SPECIAL is erroneously defined.
> > This makes any ppc architecture to act as if it has a pte special bit!
> > I suggest the following simple patch to fix this.
> 
> Thank ! That looks indeed like a bug.
> 
> Note that with 2.6.32, we should be able to use 0x20 as _PAGE_SPECIAL on
> 40x which would improve performances in some areas.

I had a quick look at it seems like 2.6.30 also has that bit free. In
fact, 8xx also appears to have a few bits free.

Maybe we should just define _PAGE_SPECIAL for all the "missing"
processor types (I think that's really the only 2 ones) and remove
the condition around  #define __HAVE_ARCH_PTE_SPECIAL

Care to send a patch ? :-)

Cheers,
Ben.

> Cheers,
> Ben.
> 
> > Bernhard WEIRICH
> > Software Development
> > 
> > 
> > Signed-off-by: Bernhard Weirich <bernhard.weirich@riedel.net>
> > --- linux/arch/powerpc/include/asm/pte-common.h	2009-09-16 11:23:44.000000000 +0200
> > +++ linux/arch/powerpc/include/asm/pte-common.h	2009-09-22 11:13:08.000000000 +0200
> > @@ -176,7 +176,7 @@
> >  #define HAVE_PAGE_AGP
> >  
> >  /* Advertise support for _PAGE_SPECIAL */
> > -#ifdef _PAGE_SPECIAL
> > +#if _PAGE_SPECIAL != 0
> >  #define __HAVE_ARCH_PTE_SPECIAL
> >  #endif
> >  
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH] Re: [405EX] Bad page map in process ...
From: Benjamin Herrenschmidt @ 2009-09-22 10:07 UTC (permalink / raw)
  To: Weirich, Bernhard; +Cc: linuxppc-dev@lists.ozlabs.org
In-Reply-To: <CE92B8B581B4584FB8CA86B51EDE8AC5243C568B04@wupexchange.riedel.net>

On Tue, 2009-09-22 at 11:29 +0200, Weirich, Bernhard wrote:
> Hello,
> 
> I found the cause of the problem.
> My architecture does not define the _PAGE_SPECIAL macro, thus in pte-common.h line 32, it is defined as 0
> And then in line 180, since _PAGE_SPECIAL is defined, the macro __HAVE_ARCH_PTE_SPECIAL is erroneously defined.
> This makes any ppc architecture to act as if it has a pte special bit!
> I suggest the following simple patch to fix this.

Thank ! That looks indeed like a bug.

Note that with 2.6.32, we should be able to use 0x20 as _PAGE_SPECIAL on
40x which would improve performances in some areas.

Cheers,
Ben.

> Bernhard WEIRICH
> Software Development
> 
> 
> Signed-off-by: Bernhard Weirich <bernhard.weirich@riedel.net>
> --- linux/arch/powerpc/include/asm/pte-common.h	2009-09-16 11:23:44.000000000 +0200
> +++ linux/arch/powerpc/include/asm/pte-common.h	2009-09-22 11:13:08.000000000 +0200
> @@ -176,7 +176,7 @@
>  #define HAVE_PAGE_AGP
>  
>  /* Advertise support for _PAGE_SPECIAL */
> -#ifdef _PAGE_SPECIAL
> +#if _PAGE_SPECIAL != 0
>  #define __HAVE_ARCH_PTE_SPECIAL
>  #endif
>  
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [LTP] mmapstress03 weirdness? (fwd)
From: Geert Uytterhoeven @ 2009-09-22  9:53 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Linux/PPC Development, Linux Kernel Development,
	Linux Test Project
In-Reply-To: <1253578781.7103.186.camel@pasglop>

On Tue, 22 Sep 2009, Benjamin Herrenschmidt wrote:
> On Mon, 2009-09-21 at 15:40 +0200, Geert Uytterhoeven wrote:
> > With 32-bit userland, this boils down to:
> > | mmap addr 0x7fff0000 size 0x7fff0000
> > | mmap returned 0x7fff0000
> > 
> > i.e. mmap() succeeds, but (1) the test expects it to fail, so the test returns
> > TFAIL, but (2) ltp-pan still reports that the tests passed?
> 
> What is the output of /proc/<pid>/maps after that mmap ?

| 00100000-00120000 r-xp 00100000 00:00 0                                  [vdso]
| 0f470000-0f5d0000 r-xp 00000000 03:03 56852565                           /lib/libc-2.5.so
| 0f5d0000-0f5e0000 r--p 00160000 03:03 56852565                           /lib/libc-2.5.so
| 0f5e0000-0f5f0000 rw-p 00170000 03:03 56852565                           /lib/libc-2.5.so
| 0ffc0000-0ffe0000 r-xp 00000000 03:03 56852482                           /lib/ld-2.5.so
| 0ffe0000-0fff0000 r--p 00010000 03:03 56852482                           /lib/ld-2.5.so
| 0fff0000-10000000 rw-p 00020000 03:03 56852482                           /lib/ld-2.5.so
| 10000000-10010000 r-xp 00000000 03:03 65571126                           /tmp/a.out
| 10010000-10020000 rw-p 00000000 03:03 65571126                           /tmp/a.out
| 7fff0000-fffe0000 rw-s 00000000 00:09 5580806                            /dev/zero (deleted)

I.e. the big mmap() took out the stack mapping, which was previously at:

| ffa00000-ffb50000 rw-p ffa00000 00:00 0                                  [stack]

> With a 64-bit kernel, 32-bit userspace has access to the entire 4G
> address space, so mapping 2G-64k at the 2G-64k point can work, provided
> you aren't overlapping an existing mapping such as the stack.
> 
> > In addition, sometimes mmapstress03 fails due to SEGV. I created a small test
> > program that just does the above mmap(), and depending on the distro and what
> > else I print later it crashes with a SEGV, too. Probably this happens because
> > the mmap() did succeed, and corrupted some existing mappings, cfr. the notes
> > for MAP_FIXED:
> 
> That's possible.
> 
> >        MAP_FIXED
> >               Don’t  interpret  addr  as  a hint: place the mapping at exactly
> >               that address.  addr must be a multiple of the page size.  If the
> >               memory  region  specified  by addr and len overlaps pages of any
> >               existing mapping(s), then the overlapped part  of  the  existing
> >               mapping(s)  will  be discarded.  If the specified address cannot
> >               be used, mmap() will fail.  Because requiring  a  fixed  address
> >               for  a  mapping is less portable, the use of this option is dis‐
> >               couraged.
> 
> Yeah, I suppose the test might be wiping out its own stack for example

Indeed.

> IE. I think that test is just bogus :-)
> 
> > JFYI, with 64-bit userland, this boils down to:
> > 
> > | mmap addr 0x7fffffffffff0000 size 0x7fffffffffff0000
> > | mmap returned 0xffffffffffffffff
> > 
> > i.e. mmap() fails as expected, and the test succeeds.
> 
> Right because on 64-bit userspace, you only are allowed something like
> 16T of address space.
> 
> > Does all of this sound OK?
> > Thanks for your comments!
> 
> Yes, I think so far, it's just bogus tests :-)

Thanks for the confirmation, Segher and Ben!

With kind regards,

Geert Uytterhoeven
Software Architect
Techsoft Centre

Technology and Software Centre Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium

Phone:    +32 (0)2 700 8453
Fax:      +32 (0)2 700 8622
E-mail:   Geert.Uytterhoeven@sonycom.com
Internet: http://www.sony-europe.com/

A division of Sony Europe (Belgium) N.V.
VAT BE 0413.825.160 · RPR Brussels
Fortis · BIC GEBABEBB · IBAN BE41293037680010

^ permalink raw reply

* [405EX] Bad page map in process ...
From: Weirich, Bernhard @ 2009-09-22  8:05 UTC (permalink / raw)
  To: linuxppc-dev@lists.ozlabs.org

Hello,

I use mmap to map an IO address space to user space on a PPC405EX processor=
.

till kernel 2.6.29 this worked without problems, since 2.6.30. I get intimi=
dating error messages when I do the unmap, mmap works fine, though.

BUG: Bad page map in process deviceDaemon  pte:ffe3b45e pmd:0f11a400
addr:48271000 vm_flags:400844ff anon_vma:(null) mapping:cede3a18 index:ffff=
fe3b
vma->vm_ops->fault: ebm_alloc+0x700/0x708 [fpga_bus_m]
vma->vm_file->f_op->mmap: fpga_regs_ioctl+0x100/0x3e0 [fpga_bus_m]
Call Trace:
[cf1bbda0] [c0006e94] show_stack+0x40/0x15c (unreliable)
[cf1bbdd0] [c00776cc] print_bad_pte+0x12c/0x1e4
[cf1bbe00] [c0077820] vm_normal_page+0x9c/0xb4
[cf1bbe20] [c0078374] unmap_vmas+0x228/0x5f8
[cf1bbeb0] [c007c8b4] unmap_region+0x98/0x138
[cf1bbef0] [c007d9cc] do_munmap+0x280/0x304
[cf1bbf20] [c007da88] sys_munmap+0x38/0x5c
[cf1bbf40] [c000efa4] ret_from_syscall+0x0/0x3c

So far I found out that in mm/memory.c, function vm_normal_page, pfn is gre=
ater than highest_memmap_pfn, thus the error is triggered.
It is correct that pfn is higher than the end of physical ram, but it is in=
 a valid IO mapped region.
I guess the problem is that pte_special(pte) returns 0.
I realized that in the 2.6.29 kernel HAVE_PTE_SPECIAL was 0 and the !HAVE_P=
TE_SPECIAL case silently returned NULL before checking whether pfn < highes=
t_memmap_pfn.

In 2.6.30 HAVE_PTE_SPECIAL is 1 and pte_special(pte) returns 0 so the code =
jumps to the pfn < highest_memmap_pfn check. Thus I believe that the there =
is a problem with the pte_special flag.

I will investigate further but maybe someone with more knowledge about page=
 handling on ppc can help me here.

Bernhard WEIRICH
Software Development

^ permalink raw reply

* R: High load average  but low cpu (xenomai can be the explanation?)
From: Bosi Daniele @ 2009-09-22  9:32 UTC (permalink / raw)
  To: 'dibacco@libero.it', linuxppc-dev@lists.ozlabs.org
In-Reply-To: <30044818.1469311253607282485.JavaMail.root@wmail36>

I suggest you to take a look at the meaning of the data showed by "/proc/lo=
adavg".

See:
http://www.luci.org/luci-discuss/200210/msg00055.html

for more details.

In my opinion your loadavg of 3.0 means only that in your application there=
 is an average of 3 task waiting for running on the CPU. This in general do=
esn't mean that the CPU load must be 100 %.

Maybe there should be some scheduler issues.

If you take a look into your app sources maybe you can know more about what=
 happens.


-----Messaggio originale-----
Da: dibacco@libero.it [mailto:dibacco@libero.it]
Inviato: marted=EC 22 settembre 2009 10.15
A: Bosi Daniele; linuxppc-dev@lists.ozlabs.org
Oggetto: R: High load average but low cpu (xenomai can be the explanation?)

It is an AgentX subagent, it does a lot of things like accessing the hardwa=
re,
handling messages from the main snmp agent received from an unix socket,
writing files on jffs2 partition, polling hardware for alarms.
If I kill it,
the load goes down. Anyway the subagent only takes 2-3% of the CPU..

Thank
you,
Antonio.



>Da: Daniele.Bosi@mta.it
>
>Can you give us some more details
about your app?
>Is it multithread or single process?
>What do the process do?

>
>Bye Daniele
>
>
>
>-----Messaggio originale-----
>Da: linuxppc-dev-
bounces+daniele.bosi=3Dmta.it@lists.ozlabs.org [mailto:linuxppc-dev-
bounces+daniele.bosi=3Dmta.it@lists.ozlabs.org] Per conto di dibacco@libero=
.it

>Oggetto: High load average but low cpu (xenomai can be the explanation?)
>

>Hi,
>
>I have an MPC880 @133MHz. If I look into the load (with uptime) I get

>values around 3.0 but my CPU is always under 5 percent (top). How could I

>explain this? I'm using linux 2.6.19 with xenomai but no xenomai applicati=
on
is
>running at all. I have a cramfs on a nor flash. What could be the problem?
If I
>kill the process I developed the average load goes down.
>
>Thank you,

>Adi
>_______________________________________________
>Linuxppc-dev mailing
list
>Linuxppc-dev@lists.ozlabs.org
>https://lists.ozlabs.org/listinfo/linuxppc-
dev
>_______________________________________________
>Linuxppc-dev mailing list

>Linuxppc-dev@lists.ozlabs.org
>https://lists.ozlabs.org/listinfo/linuxppc-dev

>

^ permalink raw reply

* [PATCH] Re: [405EX] Bad page map in process ...
From: Weirich, Bernhard @ 2009-09-22  9:29 UTC (permalink / raw)
  To: linuxppc-dev@lists.ozlabs.org

Hello,

I found the cause of the problem.
My architecture does not define the _PAGE_SPECIAL macro, thus in pte-common=
.h line 32, it is defined as 0
And then in line 180, since _PAGE_SPECIAL is defined, the macro __HAVE_ARCH=
_PTE_SPECIAL is erroneously defined.
This makes any ppc architecture to act as if it has a pte special bit!
I suggest the following simple patch to fix this.

Bernhard WEIRICH
Software Development


Signed-off-by: Bernhard Weirich <bernhard.weirich@riedel.net>
--- linux/arch/powerpc/include/asm/pte-common.h	2009-09-16 11:23:44.0000000=
00 +0200
+++ linux/arch/powerpc/include/asm/pte-common.h	2009-09-22 11:13:08.0000000=
00 +0200
@@ -176,7 +176,7 @@
 #define HAVE_PAGE_AGP
=20
 /* Advertise support for _PAGE_SPECIAL */
-#ifdef _PAGE_SPECIAL
+#if _PAGE_SPECIAL !=3D 0
 #define __HAVE_ARCH_PTE_SPECIAL
 #endif
=20

^ permalink raw reply

* Re: [v5 RFC PATCH 0/7]: cpuidle/x86/POWER (REDESIGN): Cleanup idle power management code in x86, cleanup drivers/cpuidle/cpuidle.c and introduce cpuidle to POWER.
From: Arun R Bharadwaj @ 2009-09-22  8:56 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Gautham R Shenoy, linux-kernel, Paul Mackerras, Arun Bharadwaj,
	Ingo Molnar, linuxppc-dev
In-Reply-To: <1253604359.8439.278.camel@twins>

* Peter Zijlstra <a.p.zijlstra@chello.nl> [2009-09-22 09:25:59]:

> 
> 
> Much better :-)
> 
> 
> But I'm puzzled by all the per-cpu-ish-ness of the stuff. Why would you
> need to register things on a per-cpu basis?
> 
> Also:
> 
> 
> +       list_for_each(pos, &per_cpu(cpuidle_devices_list, cpu)) {
> +               temp_dev = container_of(pos, struct cpuidle_device,
> +                                       percpu_list[cpu]);
> +               if (dev == temp_dev) {
> +                       list_del(&temp_dev->percpu_list[cpu]);
> +                       cpuidle_remove_state_sysfs(temp_dev);
> +               }
> +       }
> 
> Looks buggy, either you want to break out of the loop on dev ==
> temp_dev, or you want to use list_for_each_safe().
> 
> 
> 

Hi Peter,

There were a couple of buggy issues, which i have cleaned up for the
next iteration.

        * As you pointed out above, the loop is buggy.
        * Also, the percpu_list[NR_CPUS] which i am defining inside
          struct cpuidle_device is wrong. It does not need to be an
          array.

Thanks for the quick turnaround
arun

^ permalink raw reply

* R: High load average  but low cpu (xenomai can be the explanation?)
From: dibacco @ 2009-09-22  8:14 UTC (permalink / raw)
  To: Daniele.Bosi, linuxppc-dev@lists.ozlabs.org

It is an AgentX subagent, it does a lot of things like accessing the hardware, 
handling messages from the main snmp agent received from an unix socket, 
writing files on jffs2 partition, polling hardware for alarms.
If I kill it, 
the load goes down. Anyway the subagent only takes 2-3% of the CPU..

Thank 
you,
Antonio.



>Da: Daniele.Bosi@mta.it
>
>Can you give us some more details 
about your app?
>Is it multithread or single process?
>What do the process do?

>
>Bye Daniele
>
>
>
>-----Messaggio originale-----
>Da: linuxppc-dev-
bounces+daniele.bosi=mta.it@lists.ozlabs.org [mailto:linuxppc-dev-
bounces+daniele.bosi=mta.it@lists.ozlabs.org] Per conto di dibacco@libero.it

>Oggetto: High load average but low cpu (xenomai can be the explanation?)
>

>Hi,
>
>I have an MPC880 @133MHz. If I look into the load (with uptime) I get

>values around 3.0 but my CPU is always under 5 percent (top). How could I

>explain this? I'm using linux 2.6.19 with xenomai but no xenomai application 
is
>running at all. I have a cramfs on a nor flash. What could be the problem? 
If I
>kill the process I developed the average load goes down.
>
>Thank you,

>Adi
>_______________________________________________
>Linuxppc-dev mailing 
list
>Linuxppc-dev@lists.ozlabs.org
>https://lists.ozlabs.org/listinfo/linuxppc-
dev
>_______________________________________________
>Linuxppc-dev mailing list

>Linuxppc-dev@lists.ozlabs.org
>https://lists.ozlabs.org/listinfo/linuxppc-dev

>

^ permalink raw reply

* Re: [PATCH] perf_event, powerpc: Fix compilation after big perf_counter rename
From: Ingo Molnar @ 2009-09-22  8:13 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Peter Zijlstra, linux-kernel, linuxppc-dev, Paul Mackerras,
	Linus Torvalds, David S. Miller
In-Reply-To: <1253606415.7103.216.camel@pasglop>


* Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> On Tue, 2009-09-22 at 09:28 +0200, Ingo Molnar wrote:
> > 
> > Nevertheless you are right that i should have caught this particular 
> > PowerPC build bug - i missed it - sorry about that!
> 
> Allright. Well, to help in general, we are setting up a build-bot here 
> too that will build -tip HEAD for at least powerpc daily with a few 
> configs too.

Cool, that's really useful! Especially during the weekends that will be 
helpful, in that timeframe linux-next driven testing has a latency of 
72-95 hours and -tip usually has an uptick in patches.

Thanks,

	Ingo

^ permalink raw reply

* Re: [PATCH] perf_event, powerpc: Fix compilation after big perf_counter rename
From: Benjamin Herrenschmidt @ 2009-09-22  8:00 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Peter Zijlstra, linux-kernel, linuxppc-dev, Paul Mackerras,
	Linus Torvalds, David S. Miller
In-Reply-To: <20090922072834.GA25470@elte.hu>

On Tue, 2009-09-22 at 09:28 +0200, Ingo Molnar wrote:
> 
> Nevertheless you are right that i should have caught this particular 
> PowerPC build bug - i missed it - sorry about that!
> 
Allright. Well, to help in general, we are setting up a build-bot
here too that will build -tip HEAD for at least powerpc daily with
a few configs too.

Cheers,
Ben.

^ permalink raw reply

* Re: [v5 RFC PATCH 0/7]: cpuidle/x86/POWER (REDESIGN): Cleanup idle power management code in x86, cleanup drivers/cpuidle/cpuidle.c and introduce cpuidle to POWER.
From: Peter Zijlstra @ 2009-09-22  7:25 UTC (permalink / raw)
  To: arun
  Cc: Gautham R Shenoy, linux-kernel, Paul Mackerras, Ingo Molnar,
	linuxppc-dev
In-Reply-To: <20090922053314.GA6417@linux.vnet.ibm.com>



Much better :-)


But I'm puzzled by all the per-cpu-ish-ness of the stuff. Why would you
need to register things on a per-cpu basis?

Also:


+       list_for_each(pos, &per_cpu(cpuidle_devices_list, cpu)) {
+               temp_dev = container_of(pos, struct cpuidle_device,
+                                       percpu_list[cpu]);
+               if (dev == temp_dev) {
+                       list_del(&temp_dev->percpu_list[cpu]);
+                       cpuidle_remove_state_sysfs(temp_dev);
+               }
+       }

Looks buggy, either you want to break out of the loop on dev ==
temp_dev, or you want to use list_for_each_safe().

^ permalink raw reply

* Re: [PATCH] perf_event, powerpc: Fix compilation after big perf_counter rename
From: Ingo Molnar @ 2009-09-22  7:28 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Peter Zijlstra, linux-kernel, linuxppc-dev, Paul Mackerras,
	Linus Torvalds, David S. Miller
In-Reply-To: <1253584591.7103.197.camel@pasglop>


* Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> On Tue, 2009-09-22 at 09:48 +1000, Paul Mackerras wrote:
>
> > This fixes two places in the powerpc perf_event (perf_counter) code 
> > where 'list_entry' needs to be changed to 'group_entry', but were 
> > missed in commit 65abc865 ("perf_counter: Rename list_entry -> 
> > group_entry, counter_list -> group_list").

Oops, indeed - queued up the fix and will send it to Linus shortly - 
thanks!

> Ingo: This is becoming a recurring one now... powerpc build upstream 
> is broken approx everyday by some new perfctr build breakage.
>
> You really aren't build testing other architectures than x86 right ?

On the contrary - i am build testing every architecture on a daily 
basis. (and sometimes i do it multiple times a day - yesterday i did 5 
cross builds during the rename) In fact i am testing more architectures 
than linux-next does.

Here's the log of the test i ran yesterday before i sent those bits to 
Linus:

testing 24 architectures.
                                 (warns)               (warns)
testing      alpha:  -git:  pass (   24),  -tip:  pass (   24)
testing        arm:  -git:  fail (   11),  -tip:  fail (   13)
testing   blackfin:  -git:  pass (    3),  -tip:  pass (    3)
testing       cris:  -git:  fail (   34),  -tip:  pass (   20)
testing        frv:  -git:  fail (   13),  -tip:  fail (   13)
testing      h8300:  -git:  fail (  441),  -tip:  fail (  185)
testing       i386:  -git:  pass (    2),  -tip:  pass (    5)
testing       ia64:  -git:  fail (  172),  -tip:  pass (  160)
testing       m32r:  -git:  pass (   39),  -tip:  pass (   39)
testing       m68k:  -git:  pass (   42),  -tip:  pass (   42)
testing  m68knommu:  -git:  fail (   80),  -tip:  fail (   80)
testing microblaze:  -git:  fail (   14),  -tip:  fail (   14)
testing       mips:  -git:  pass (    6),  -tip:  pass (    6)
testing    mn10300:  -git:  fail (   10),  -tip:  fail (   10)
testing     parisc:  -git:  pass (   26),  -tip:  pass (   26)
testing    powerpc:  -git:  fail (   36),  -tip:  fail (   45)
testing       s390:  -git:  pass (    6),  -tip:  pass (    6)
testing      score:  -git:  fail (   13),  -tip:  fail (   13)
testing         sh:  -git:  fail (   22),  -tip:  fail (   19)
testing      sparc:  -git:  pass (    3),  -tip:  pass (    3)
testing         um:  -git:  pass (    3),  -tip:  pass (    3)
testing     xtensa:  -git:  fail (   46),  -tip:  fail (   46)
testing     x86-64:  -git:  pass (    0),  -tip:  pass (    0)
testing     x86-32:  -git:  pass (    0),  -tip:  pass (    0)

In fact there are architectures that dont build in Linus's tree and 
build in -tip:

testing       cris:  -git:  fail (   34),  -tip:  pass (   20)

Because not only do i test every architecture i also try to fix upstream 
bugs on non-x86 pro-actively. See for example this upstream fix:

 8d7ac69: Blackfin: Fix link errors with binutils 2.19 and GCC 4.3

Nevertheless you are right that i should have caught this particular 
PowerPC build bug - i missed it - sorry about that!

Thanks,

	Ingo

^ permalink raw reply

* Re: MPC8536 PCI rescan to discover FPGA
From: Benjamin Herrenschmidt @ 2009-09-22  7:23 UTC (permalink / raw)
  To: David Hawkins; +Cc: linuxppc-dev@ozlabs.org list, Felix Radensky, Ira Snyder
In-Reply-To: <4AB7A411.3030406@ovro.caltech.edu>

On Mon, 2009-09-21 at 09:04 -0700, David Hawkins wrote:
> This can be made to work using the kernel hot-swap
> interface. PCI devices have an ENUM# interrupt that
> they assert when inserted or extracted, and the host
> hot-swap driver can be hooked up to it. PCI-E may
> have a similar mechanism, if it does, then when your
> FPGA configures as a PCI-E device, it can assert that
> interrupt line (or send the appropriate PCI-E
> message to simulate that interrupt).
> 
> However, even if PCI-E does not have the concept of
> an ENUM# interrupt there is a way to generate a fake
> hot-swap event and generate a re-scan of the PCI bus.
> 
> I haven't tested the kernel hot-swap interface, but I
> know that Ira did, so I'll cc him on this mail, and he
> can let you know what he tested.

Right. However, in case it's a bit too much work to get
hotswap implemented on the machine, you may still be able
to do something simpler from your platform code, after you've
finished loading the FPGA. I assume the FPGA doesn't contain a
P2P bridge that would require probing further below the FPGA
itself.

The basic idea is to call pci_scan_slot() on the devfn where
the FPGA is supposed to respond.

Then you need to also do some fixup. First you need to call
pcibios_setup_bus_devices(). This will wire up the device
to an OF node if you have one, setup some default DMA ops,
etc...

Note that this function will walk over all devices on that bus
which is interesting since some of those may have already been
fully setup initially. Hopefully that isn't a problem. If it
was to become one, we would have to figure out a way to skip
devices that have already been "setup".

And finally you call pcibios_finish_adding_to_bus() which will
do the resource allocation pass on all new devices on the bus
and register them with the core device layer.

Cheers,
Ben.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox