LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] Add IPIC MSI interrupt support
From: Michael Ellerman @ 2007-12-04  5:38 UTC (permalink / raw)
  To: Li Li; +Cc: linuxppc-dev, Gala Kumar, Li Tony
In-Reply-To: <1196672870.14353.21.camel@Guyver>

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

On Mon, 2007-12-03 at 17:07 +0800, Li Li wrote:
> Hi Michael,
> 
> I emulate mpic to write this IPIC MSI routines. :)
> 
> 
> > > diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c
> > > index 6048f1b..dbea34b 100644
> > > --- a/arch/powerpc/platforms/83xx/mpc837x_mds.c
> > > +++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c

> > > +
> > > +#define	ipic_msi_irq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq)
> > 
> > What's wrong with virq_to_hw() ?
> > 
> 
> viqr_to_hw is not __inline__.

Hmm, ok. The three places you use it you also take a spin lock, so I'm
not sure the function call's really going to kill you performance wise.

> > > +
> > > +static void ipic_msi_compose_msg(struct ipic_msi *msi, int hwirq,
> > > +						struct msi_msg *msg)
> > > +{
> > > +	unsigned int srs;
> > > +	unsigned int ibs;
> > > +
> > > +	srs = hwirq / msi->int_per_msir;
> > > +	ibs = hwirq - srs * msi->int_per_msir;
> > > +
> > > +	msg->address_lo = msi->msi_addr_lo;
> > > +	msg->address_hi = msi->msi_addr_hi;
> > > +	msg->data = (srs << 5) | (ibs & 0x1F);
> > > +
> > > +	pr_debug("%s: allocated srs: %d, ibs: %d\n",
> > > +		__FUNCTION__, srs, ibs);
> > > +
> > > +}
> > > +
> > > +static int ipic_msi_setup_irqs(struct pci_dev *pdev, int nvec, int type)
> > > +{
> > > +	struct ipic_msi *msi = ipic_msi;
> > > +	irq_hw_number_t hwirq;
> > > +	unsigned int virq;
> > > +	struct msi_desc *entry;
> > > +	struct msi_msg msg;
> > > +
> > > +	list_for_each_entry(entry, &pdev->msi_list, list) {
> > > +		hwirq = ipic_msi_alloc_hwirqs(msi, 1);
> > > +		if (hwirq < 0) {
> > > +			pr_debug("%s: fail allocating msi interrupt\n",
> > > +					__FUNCTION__);
> > > +			return hwirq;
> > > +		}
> > > +
> > > +		/* This hwirq belongs to the irq_host other than irq_host of IPIC
> > > + 		 * So, it is independent to hwirq of IPIC */
> > > +		virq = irq_create_mapping(msi->irqhost, hwirq);
> > > +		if (virq == NO_IRQ) {
> > > +			pr_debug("%s: fail mapping hwirq 0x%lx\n",
> > > +					__FUNCTION__, hwirq);
> > > +			ipic_msi_free_hwirqs(msi, hwirq, 1);
> > > +			return -ENOSPC;
> > > +		}
> > > +		set_irq_msi(virq, entry);
> > > +		ipic_msi_compose_msg(msi, hwirq, &msg);
> > > +		write_msi_msg(virq, &msg);
> > > +
> > > +		hwirq++;
> > 
> >                   ^^^^ this looks like my bug
> 
> I have a question here. Do we support more MSI interrupts on ONE pci
> device?

I'm not sure what you mean? For MSI there is only one MSI per device,
but this code is used also for MSI-X which supports > 1 MSI per device.

Either way we shouldn't be incrementing hwirq by hand, it's reassigned
at the top of the loop. I think that's left over from old code that
allocated nvec hwirqs in a block and then created virq mappings for each
one, whereas the new code allocates each hwirq separately.

cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

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

^ permalink raw reply

* [PATCH 1/7] powerpc: Drivers should call machine_power_off not pm_power_off
From: Mark A. Greer @ 2007-12-04  5:43 UTC (permalink / raw)
  To: linuxppc-dev, Helge Deller
In-Reply-To: <20071204053736.GA27862@mag.az.mvista.com>

From: Mark A. Greer <mgreer@mvista.com>

Drivers should call machine_power_off() not pm_power_off to power off
a machine.

Signed-off-by: Mark A. Greer <mgreer@mvista.com>
---
 drivers/parisc/power.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c
index 90cca5e..188a1ac 100644
--- a/drivers/parisc/power.c
+++ b/drivers/parisc/power.c
@@ -93,11 +93,9 @@ static void process_shutdown(void)
 		lcd_print(msg);
 
 		/* send kill signal */
-		if (kill_cad_pid(SIGINT, 1)) {
+		if (kill_cad_pid(SIGINT, 1))
 			/* just in case killing init process failed */
-			if (pm_power_off)
-				pm_power_off();
-		}
+			machine_power_off();
 	}
 }
 

^ permalink raw reply related

* [PATCH 2/7] powerpc: xmon should call machine_xxx not ppc_md.xxx directly
From: Mark A. Greer @ 2007-12-04  5:44 UTC (permalink / raw)
  To: Mark A. Greer; +Cc: linuxppc-dev
In-Reply-To: <20071204053736.GA27862@mag.az.mvista.com>

From: Mark A. Greer <mgreer@mvista.com>

xmon should call machine_[restart|halt|power_off] instead of
ppc_md.[restart|halt|power_off].

Signed-off-by: Mark A. Greer <mgreer@mvista.com>
---
I'm not sure about this one.  Does anyone see a problem with this?

 arch/powerpc/xmon/xmon.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 121b04d..56267e3 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -908,11 +908,11 @@ static void bootcmds(void)
 
 	cmd = inchar();
 	if (cmd == 'r')
-		ppc_md.restart(NULL);
+		machine_restart();
 	else if (cmd == 'h')
-		ppc_md.halt();
+		machine_halt();
 	else if (cmd == 'p')
-		ppc_md.power_off();
+		machine_power_off();
 }
 
 static int cpu_cmd(void)

^ permalink raw reply related

* [PATCH 3/7] powerpc: ras.c should call machine_power_off()
From: Mark A. Greer @ 2007-12-04  5:45 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20071204053736.GA27862@mag.az.mvista.com>

From: Mark A. Greer <mgreer@mvista.com>

machine_power_off() is the proper interface to use for powering
off a machine.

Signed-off-by: Mark A. Greer <mgreer@mvista.com>
---
 arch/powerpc/platforms/pseries/ras.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index a1ab25c..64564b2 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -242,7 +242,7 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
 		 * without actually failing while injecting errors.
 		 * Error data will not be logged to syslog.
 		 */
-		ppc_md.power_off();
+		machine_power_off();
 #endif
 	} else {
 		udbg_printf("Recoverable HW Error <0x%lx 0x%x>\n",

^ permalink raw reply related

* [PATCH 4/7] powerpc: Rework the machine_[restart|power_off|halt] routines
From: Mark A. Greer @ 2007-12-04  5:47 UTC (permalink / raw)
  To: linuxppc-dev, Benjamin Herrenschmidt
In-Reply-To: <20071204053736.GA27862@mag.az.mvista.com>

From: Mark A. Greer <mgreer@mvista.com>

Factor out common code from the machine_xxx routines and make them better
handle a ppc_md hook that doesn't exist or fails better.  In particular,
have machine_power_off() try ppc_md.halt if ppc_md.power_off is NULL or fails,
and have machine_halt() try to power off when ppc_md.halt is NULL or fails.

Signed-off-by: Mark A. Greer <mgreer@mvista.com>
---
 arch/powerpc/kernel/setup-common.c |   40 ++++++++++++++-------------
 1 file changed, 22 insertions(+), 18 deletions(-)

diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 6adb5a1..1f8f9aa 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -105,17 +105,23 @@ void machine_shutdown(void)
 		ppc_md.machine_shutdown();
 }
 
-void machine_restart(char *cmd)
+static void default_halt(const char *s)
 {
-	machine_shutdown();
-	if (ppc_md.restart)
-		ppc_md.restart(cmd);
 #ifdef CONFIG_SMP
 	smp_send_stop();
 #endif
-	printk(KERN_EMERG "System Halted, OK to turn off power\n");
+	printk(KERN_EMERG "%s", s);
 	local_irq_disable();
-	while (1) ;
+	while (1);
+}
+
+void machine_restart(char *cmd)
+{
+	machine_shutdown();
+	if (ppc_md.restart)
+		ppc_md.restart(cmd);
+	default_halt("System not restarted; halting instead.\n"
+			"OK to turn off power\n");
 }
 
 void machine_power_off(void)
@@ -123,12 +129,10 @@ void machine_power_off(void)
 	machine_shutdown();
 	if (ppc_md.power_off)
 		ppc_md.power_off();
-#ifdef CONFIG_SMP
-	smp_send_stop();
-#endif
-	printk(KERN_EMERG "System Halted, OK to turn off power\n");
-	local_irq_disable();
-	while (1) ;
+	printk(KERN_EMERG "System not powered off; halting instead.\n");
+	if (ppc_md.halt)
+		ppc_md.halt();
+	default_halt("OK to turn off power\n");
 }
 /* Used by the G5 thermal driver */
 EXPORT_SYMBOL_GPL(machine_power_off);
@@ -141,12 +145,12 @@ void machine_halt(void)
 	machine_shutdown();
 	if (ppc_md.halt)
 		ppc_md.halt();
-#ifdef CONFIG_SMP
-	smp_send_stop();
-#endif
-	printk(KERN_EMERG "System Halted, OK to turn off power\n");
-	local_irq_disable();
-	while (1) ;
+	if (ppc_md.power_off) {
+		printk(KERN_EMERG "System not halted; powering off instead.\n");
+		ppc_md.power_off();
+		printk(KERN_EMERG "Poweroff failed.\n");
+	}
+	default_halt("OK to turn off power\n");
 }
 
 

^ permalink raw reply related

* Re: [PATCH] powermac: proper sleep management
From: Paul Mackerras @ 2007-12-04  5:48 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev list, linux-pm
In-Reply-To: <1194981933.6695.17.camel@johannes.berg>

Johannes Berg writes:

> +		printk(KERN_INFO
> +		       "via-pmu: the PMU_IOC_SLEEP ioctl is deprecated.\n");
> +		printk(KERN_INFO "via-pmu: use \"echo mem >"
> +		       " /sys/power/state\"  instead!\n");
> +		printk(KERN_INFO
> +		       "via-pmu: this ioctl will be removed soon.\n");

I don't like this.  I would rather keep the ioctls indefinitely and
not make any noise about programs using them.  The ioctls are part of
the kernel/user ABI, and thus need to be preserved, especially since
it only takes about 6 or 7 lines of code to implement them.

Paul.

^ permalink raw reply

* [PATCH 5/7] powerpc: Replace ppc_md.power_off with pm_power_off
From: Mark A. Greer @ 2007-12-04  5:48 UTC (permalink / raw)
  To: linuxppc-dev, Benjamin Herrenschmidt
In-Reply-To: <20071204053736.GA27862@mag.az.mvista.com>

From: Mark A. Greer <mgreer@mvista.com>

The ppc_md.power_off hook performs the same function that the
pm_power_off hook is supposed to.  However, it is powerpc-specific
and prevents kernel drivers (e.g., IPMI) from changing how a platform
is powered off.  So, get rid of ppc_md.power_off and replace it with
pm_power_off.

Signed-off-by: Mark A. Greer <mgreer@mvista.com>
---
 arch/powerpc/kernel/setup-common.c               |   14 +--
 arch/powerpc/platforms/52xx/efika.c              |    2 
 arch/powerpc/platforms/cell/setup.c              |    2 
 arch/powerpc/platforms/celleb/setup.c            |    2 
 arch/powerpc/platforms/chrp/setup.c              |    2 
 arch/powerpc/platforms/embedded6xx/linkstation.c |    3 
 arch/powerpc/platforms/iseries/setup.c           |    2 
 arch/powerpc/platforms/maple/setup.c             |    4 
 arch/powerpc/platforms/powermac/setup.c          |    2 
 arch/powerpc/platforms/ps3/setup.c               |    2 
 arch/powerpc/platforms/pseries/setup.c           |   59 ++++++-------
 include/asm-powerpc/machdep.h                    |    1 
 12 files changed, 48 insertions(+), 47 deletions(-)


diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 1f8f9aa..d9f2e07 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -76,6 +76,9 @@ EXPORT_SYMBOL(ppc_md);
 struct machdep_calls *machine_id;
 EXPORT_SYMBOL(machine_id);
 
+void (*pm_power_off)(void);
+EXPORT_SYMBOL_GPL(pm_power_off);
+
 unsigned long klimit = (unsigned long) _end;
 
 char cmd_line[COMMAND_LINE_SIZE];
@@ -127,8 +130,8 @@ void machine_restart(char *cmd)
 void machine_power_off(void)
 {
 	machine_shutdown();
-	if (ppc_md.power_off)
-		ppc_md.power_off();
+	if (pm_power_off)
+		pm_power_off();
 	printk(KERN_EMERG "System not powered off; halting instead.\n");
 	if (ppc_md.halt)
 		ppc_md.halt();
@@ -137,17 +140,14 @@ void machine_power_off(void)
 /* Used by the G5 thermal driver */
 EXPORT_SYMBOL_GPL(machine_power_off);
 
-void (*pm_power_off)(void) = machine_power_off;
-EXPORT_SYMBOL_GPL(pm_power_off);
-
 void machine_halt(void)
 {
 	machine_shutdown();
 	if (ppc_md.halt)
 		ppc_md.halt();
-	if (ppc_md.power_off) {
+	if (pm_power_off) {
 		printk(KERN_EMERG "System not halted; powering off instead.\n");
-		ppc_md.power_off();
+		pm_power_off();
 		printk(KERN_EMERG "Poweroff failed.\n");
 	}
 	default_halt("OK to turn off power\n");
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index a0da70c..c2d5f06 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -205,6 +205,7 @@ static int __init efika_probe(void)
 	DMA_MODE_READ = 0x44;
 	DMA_MODE_WRITE = 0x48;
 
+	pm_power_off = rtas_power_off;
 	return 1;
 }
 
@@ -218,7 +219,6 @@ define_machine(efika)
 	.init_IRQ		= mpc52xx_init_irq,
 	.get_irq		= mpc52xx_get_irq,
 	.restart		= rtas_restart,
-	.power_off		= rtas_power_off,
 	.halt			= rtas_halt,
 	.set_rtc_time		= rtas_set_rtc_time,
 	.get_rtc_time		= rtas_get_rtc_time,
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index 98e7ef8..06f44f5 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -191,6 +191,7 @@ static int __init cell_probe(void)
 		return 0;
 
 	hpte_init_native();
+	pm_power_off = rtas_power_off;
 
 	return 1;
 }
@@ -201,7 +202,6 @@ define_machine(cell) {
 	.setup_arch		= cell_setup_arch,
 	.show_cpuinfo		= cell_show_cpuinfo,
 	.restart		= rtas_restart,
-	.power_off		= rtas_power_off,
 	.halt			= rtas_halt,
 	.get_boot_time		= rtas_get_boot_time,
 	.get_rtc_time		= rtas_get_rtc_time,
diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c
index ddfb35a..450841a 100644
--- a/arch/powerpc/platforms/celleb/setup.c
+++ b/arch/powerpc/platforms/celleb/setup.c
@@ -116,6 +116,7 @@ static int __init celleb_probe(void)
 
 	powerpc_firmware_features |= FW_FEATURE_CELLEB_POSSIBLE;
 	hpte_init_beat_v3();
+	pm_power_off = beat_power_off;
 	return 1;
 }
 
@@ -145,7 +146,6 @@ define_machine(celleb) {
 	.setup_arch		= celleb_setup_arch,
 	.show_cpuinfo		= celleb_show_cpuinfo,
 	.restart		= beat_restart,
-	.power_off		= beat_power_off,
 	.halt			= beat_halt,
 	.get_rtc_time		= beat_get_rtc_time,
 	.set_rtc_time		= beat_set_rtc_time,
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 5930626..99edb04 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -586,6 +586,7 @@ static int __init chrp_probe(void)
 	DMA_MODE_READ = 0x44;
 	DMA_MODE_WRITE = 0x48;
 
+	pm_power_off = rtas_power_off;
 	return 1;
 }
 
@@ -597,7 +598,6 @@ define_machine(chrp) {
 	.show_cpuinfo		= chrp_show_cpuinfo,
 	.init_IRQ		= chrp_init_IRQ,
 	.restart		= rtas_restart,
-	.power_off		= rtas_power_off,
 	.halt			= rtas_halt,
 	.time_init		= chrp_time_init,
 	.set_rtc_time		= chrp_set_rtc_time,
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
index eb5d74e..8792840 100644
--- a/arch/powerpc/platforms/embedded6xx/linkstation.c
+++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
@@ -182,6 +182,8 @@ static int __init linkstation_probe(void)
 
 	if (!of_flat_dt_is_compatible(root, "linkstation"))
 		return 0;
+
+	pm_power_off = linkstation_power_off;
 	return 1;
 }
 
@@ -193,7 +195,6 @@ define_machine(linkstation){
 	.show_cpuinfo 		= linkstation_show_cpuinfo,
 	.get_irq 		= mpic_get_irq,
 	.restart 		= linkstation_restart,
-	.power_off 		= linkstation_power_off,
 	.halt	 		= linkstation_halt,
 	.calibrate_decr 	= generic_calibrate_decr,
 };
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 2175a71..6051204 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -633,6 +633,7 @@ static int __init iseries_probe(void)
 	/* iSeries does not support 16M pages */
 	cur_cpu_spec->cpu_features &= ~CPU_FTR_16M_PAGE;
 
+	pm_power_off = mf_power_off;
 	return 1;
 }
 
@@ -645,7 +646,6 @@ define_machine(iseries) {
 	.init_early	= iSeries_init_early,
 	.pcibios_fixup	= iSeries_pci_final_fixup,
 	.restart	= mf_reboot,
-	.power_off	= mf_power_off,
 	.halt		= mf_power_off,
 	.get_boot_time	= iSeries_get_boot_time,
 	.set_rtc_time	= iSeries_set_rtc_time,
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 144177d..d0eb901 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -172,7 +172,7 @@ static void __init maple_use_rtas_reboot_and_halt_if_present(void)
 	if (rtas_service_present("system-reboot") &&
 	    rtas_service_present("power-off")) {
 		ppc_md.restart = rtas_restart;
-		ppc_md.power_off = rtas_power_off;
+		pm_power_off = rtas_power_off;
 		ppc_md.halt = rtas_halt;
 	}
 }
@@ -315,6 +315,7 @@ static int __init maple_probe(void)
 	alloc_dart_table();
 
 	hpte_init_native();
+	pm_power_off = maple_power_off;
 
 	return 1;
 }
@@ -328,7 +329,6 @@ define_machine(maple_md) {
 	.pci_irq_fixup		= maple_pci_irq_fixup,
 	.pci_get_legacy_ide_irq	= maple_pci_get_legacy_ide_irq,
 	.restart		= maple_restart,
-	.power_off		= maple_power_off,
 	.halt			= maple_halt,
        	.get_boot_time		= maple_get_boot_time,
        	.set_rtc_time		= maple_set_rtc_time,
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 02c5330..8429002 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -577,6 +577,7 @@ static int __init pmac_probe(void)
 
 	hpte_init_native();
 #endif
+	pm_power_off = pmac_power_off;
 
 #ifdef CONFIG_PPC32
 	/* isa_io_base gets set in pmac_pci_init */
@@ -676,7 +677,6 @@ define_machine(powermac) {
 	.get_irq		= NULL,	/* changed later */
 	.pci_irq_fixup		= pmac_pci_irq_fixup,
 	.restart		= pmac_restart,
-	.power_off		= pmac_power_off,
 	.halt			= pmac_halt,
 	.time_init		= pmac_time_init,
 	.get_boot_time		= pmac_get_boot_time,
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 5c2cbb0..74942d8 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -233,6 +233,7 @@ static int __init ps3_probe(void)
 	ps3_mm_init();
 	ps3_mm_vas_create(&htab_size);
 	ps3_hpte_init(htab_size);
+	pm_power_off = ps3_power_off;
 
 	DBG(" <- %s:%d\n", __func__, __LINE__);
 	return 1;
@@ -265,7 +266,6 @@ define_machine(ps3) {
 	.calibrate_decr			= ps3_calibrate_decr,
 	.progress			= ps3_progress,
 	.restart			= ps3_restart,
-	.power_off			= ps3_power_off,
 #if defined(CONFIG_KEXEC)
 	.kexec_cpu_down			= ps3_kexec_cpu_down,
 	.machine_kexec			= default_machine_kexec,
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index fdb9b1c..51ef84c 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -353,6 +353,34 @@ static int __init pSeries_probe_hypertas(unsigned long node,
 	return 1;
 }
 
+/**
+ * pSeries_power_off - tell firmware about how to power off the system.
+ *
+ * This function calls either the power-off rtas token in normal cases
+ * or the ibm,power-off-ups token (if present & requested) in case of
+ * a power failure. If power-off token is used, power on will only be
+ * possible with power button press. If ibm,power-off-ups token is used
+ * it will allow auto poweron after power is restored.
+ */
+void pSeries_power_off(void)
+{
+	int rc;
+	int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups");
+
+	if (rtas_flash_term_hook)
+		rtas_flash_term_hook(SYS_POWER_OFF);
+
+	if (rtas_poweron_auto == 0 ||
+		rtas_poweroff_ups_token == RTAS_UNKNOWN_SERVICE) {
+		rc = rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1);
+		printk(KERN_INFO "RTAS power-off returned %d\n", rc);
+	} else {
+		rc = rtas_call(rtas_poweroff_ups_token, 0, 1, NULL);
+		printk(KERN_INFO "RTAS ibm,power-off-ups returned %d\n", rc);
+	}
+	for (;;);
+}
+
 static int __init pSeries_probe(void)
 {
 	unsigned long root = of_get_flat_dt_root();
@@ -380,6 +408,8 @@ static int __init pSeries_probe(void)
 	else
 		hpte_init_native();
 
+	pm_power_off = pSeries_power_off;
+
 	DBG("Machine is%s LPAR !\n",
 	    (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
 
@@ -463,34 +493,6 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus)
 	return PCI_PROBE_NORMAL;
 }
 
-/**
- * pSeries_power_off - tell firmware about how to power off the system.
- *
- * This function calls either the power-off rtas token in normal cases
- * or the ibm,power-off-ups token (if present & requested) in case of
- * a power failure. If power-off token is used, power on will only be
- * possible with power button press. If ibm,power-off-ups token is used
- * it will allow auto poweron after power is restored.
- */
-void pSeries_power_off(void)
-{
-	int rc;
-	int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups");
-
-	if (rtas_flash_term_hook)
-		rtas_flash_term_hook(SYS_POWER_OFF);
-
-	if (rtas_poweron_auto == 0 ||
-		rtas_poweroff_ups_token == RTAS_UNKNOWN_SERVICE) {
-		rc = rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1);
-		printk(KERN_INFO "RTAS power-off returned %d\n", rc);
-	} else {
-		rc = rtas_call(rtas_poweroff_ups_token, 0, 1, NULL);
-		printk(KERN_INFO "RTAS ibm,power-off-ups returned %d\n", rc);
-	}
-	for (;;);
-}
-
 #ifndef CONFIG_PCI
 void pSeries_final_fixup(void) { }
 #endif
@@ -505,7 +507,6 @@ define_machine(pseries) {
 	.pcibios_fixup		= pSeries_final_fixup,
 	.pci_probe_mode		= pSeries_pci_probe_mode,
 	.restart		= rtas_restart,
-	.power_off		= pSeries_power_off,
 	.halt			= rtas_halt,
 	.panic			= rtas_os_term,
 	.get_boot_time		= rtas_get_boot_time,
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 6968f43..bca57bc 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -129,7 +129,6 @@ struct machdep_calls {
 #endif
 
 	void		(*restart)(char *cmd);
-	void		(*power_off)(void);
 	void		(*halt)(void);
 	void		(*panic)(char *str);
 	void		(*cpu_die)(void);

^ permalink raw reply related

* [PATCH 6/7] powerpc: Remove redundant power_off and halt routines
From: Mark A. Greer @ 2007-12-04  5:49 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20071204053736.GA27862@mag.az.mvista.com>

From: Mark A. Greer <mgreer@mvista.com>

Remove platform-specific power_off and halt routines, and ppc_md
initializations that are not necessary.

Signed-off-by: Mark A. Greer <mgreer@mvista.com>
---
 arch/powerpc/platforms/embedded6xx/holly.c        |   12 ------------
 arch/powerpc/platforms/embedded6xx/linkstation.c  |    7 -------
 arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c |   11 -----------
 arch/powerpc/platforms/iseries/setup.c            |    1 -
 arch/powerpc/platforms/maple/setup.c              |    6 ------
 arch/powerpc/platforms/powermac/setup.c           |    7 -------
 6 files changed, 44 deletions(-)

diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c
index b6de2b5..70cfd37 100644
--- a/arch/powerpc/platforms/embedded6xx/holly.c
+++ b/arch/powerpc/platforms/embedded6xx/holly.c
@@ -253,18 +253,6 @@ void holly_restart(char *cmd)
 	for (;;) ;
 }
 
-void holly_power_off(void)
-{
-	local_irq_disable();
-	/* No way to shut power off with software */
-	for (;;) ;
-}
-
-void holly_halt(void)
-{
-	holly_power_off();
-}
-
 /*
  * Called very early, device-tree isn't unflattened
  */
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
index 8792840..3382eef 100644
--- a/arch/powerpc/platforms/embedded6xx/linkstation.c
+++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
@@ -162,12 +162,6 @@ static void linkstation_power_off(void)
 	/* NOTREACHED */
 }
 
-static void linkstation_halt(void)
-{
-	linkstation_power_off();
-	/* NOTREACHED */
-}
-
 static void linkstation_show_cpuinfo(struct seq_file *m)
 {
 	seq_printf(m, "vendor\t\t: Buffalo Technology\n");
@@ -195,6 +189,5 @@ define_machine(linkstation){
 	.show_cpuinfo 		= linkstation_show_cpuinfo,
 	.get_irq 		= mpic_get_irq,
 	.restart 		= linkstation_restart,
-	.halt	 		= linkstation_halt,
 	.calibrate_decr 	= generic_calibrate_decr,
 };
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
index a2c04b9..557a6fe 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
@@ -179,17 +179,6 @@ void mpc7448_hpc2_restart(char *cmd)
 	for (;;) ;		/* Spin until reset happens */
 }
 
-void mpc7448_hpc2_power_off(void)
-{
-	local_irq_disable();
-	for (;;) ;		/* No way to shut power off with software */
-}
-
-void mpc7448_hpc2_halt(void)
-{
-	mpc7448_hpc2_power_off();
-}
-
 /*
  * Called very early, device-tree isn't unflattened
  */
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 362084e..0eabbc3 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -650,7 +650,6 @@ define_machine(iseries) {
 	.init_early	= iSeries_init_early,
 	.pcibios_fixup	= iSeries_pci_final_fixup,
 	.restart	= mf_reboot,
-	.halt		= mf_power_off,
 	.get_boot_time	= iSeries_get_boot_time,
 	.set_rtc_time	= iSeries_set_rtc_time,
 	.get_rtc_time	= iSeries_get_rtc_time,
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index d0eb901..ac5f99a 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -151,11 +151,6 @@ static void maple_power_off(void)
 	printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
 }
 
-static void maple_halt(void)
-{
-	maple_power_off();
-}
-
 #ifdef CONFIG_SMP
 struct smp_ops_t maple_smp_ops = {
 	.probe		= smp_mpic_probe,
@@ -329,7 +324,6 @@ define_machine(maple_md) {
 	.pci_irq_fixup		= maple_pci_irq_fixup,
 	.pci_get_legacy_ide_irq	= maple_pci_get_legacy_ide_irq,
 	.restart		= maple_restart,
-	.halt			= maple_halt,
        	.get_boot_time		= maple_get_boot_time,
        	.set_rtc_time		= maple_set_rtc_time,
        	.get_rtc_time		= maple_get_rtc_time,
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 8429002..002b0b4 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -499,12 +499,6 @@ static void pmac_power_off(void)
 	}
 }
 
-static void
-pmac_halt(void)
-{
-	pmac_power_off();
-}
-
 /* 
  * Early initialization.
  */
@@ -677,7 +671,6 @@ define_machine(powermac) {
 	.get_irq		= NULL,	/* changed later */
 	.pci_irq_fixup		= pmac_pci_irq_fixup,
 	.restart		= pmac_restart,
-	.halt			= pmac_halt,
 	.time_init		= pmac_time_init,
 	.get_boot_time		= pmac_get_boot_time,
 	.set_rtc_time		= pmac_set_rtc_time,

^ permalink raw reply related

* [PATCH 7/7] powerpc: Remove incorrect panic() calls
From: Mark A. Greer @ 2007-12-04  5:50 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20071204053736.GA27862@mag.az.mvista.com>

From: Mark A. Greer <mgreer@mvista.com>

Platform-specific restart routines should not call panic() when they
fail.  Instead, they should return so the caller (machine_restart())
can halt the system more gracefully.

Signed-off-by: Mark A. Greer <mgreer@mvista.com>
---
 arch/powerpc/platforms/82xx/pq2.c              |    2 --
 arch/powerpc/platforms/8xx/m8xx_setup.c        |    1 -
 arch/powerpc/platforms/embedded6xx/prpmc2800.c |    1 -
 3 files changed, 4 deletions(-)

diff --git a/arch/powerpc/platforms/82xx/pq2.c b/arch/powerpc/platforms/82xx/pq2.c
index a497cba..16cd460 100644
--- a/arch/powerpc/platforms/82xx/pq2.c
+++ b/arch/powerpc/platforms/82xx/pq2.c
@@ -31,8 +31,6 @@ void pq2_restart(char *cmd)
 	/* Clear the ME,EE,IR & DR bits in MSR to cause checkstop */
 	mtmsr(mfmsr() & ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR));
 	in_8(&cpm2_immr->im_clkrst.res[0]);
-
-	panic("Restart failed\n");
 }
 
 #ifdef CONFIG_PCI
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index d35eda8..1014310 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -221,7 +221,6 @@ void mpc8xx_restart(char *cmd)
 	mtmsr(mfmsr() & ~0x1000);
 
 	in_8(&clk_r->res[0]);
-	panic("Restart failed\n");
 }
 
 static void cpm_cascade(unsigned int irq, struct irq_desc *desc)
diff --git a/arch/powerpc/platforms/embedded6xx/prpmc2800.c b/arch/powerpc/platforms/embedded6xx/prpmc2800.c
index 653a5eb..fe5920c 100644
--- a/arch/powerpc/platforms/embedded6xx/prpmc2800.c
+++ b/arch/powerpc/platforms/embedded6xx/prpmc2800.c
@@ -108,7 +108,6 @@ static void prpmc2800_restart(char *cmd)
 	prpmc2800_reset_board();
 
 	while (i-- > 0);
-	panic("restart failed\n");
 }
 
 #ifdef CONFIG_NOT_COHERENT_CACHE

^ permalink raw reply related

* [PATCH v2] Fix hardware IRQ time accounting problem.
From: Tony Breeds @ 2007-12-04  5:51 UTC (permalink / raw)
  To: Paul Mackerras, LinuxPPC-dev, Linux Kernel ML
  Cc: Johannes Berg, Frederik Himpe, linux-usb-devel

The commit fa13a5a1f25f671d084d8884be96fc48d9b68275 (sched: restore
deterministic CPU accounting on powerpc), unconditionally calls
update_process_tick() in system context.  In the deterministic accounting case
this is the correct thing to do.  However, in the non-deterministic accounting
case we need to not do this, and results in the time accounted as hardware irq
time being artificially elevated.

Also this patch collapses 2 consecutive '#ifdef CONFIG_VIRT_CPU_ACCOUNTING'
checks in time.h into one for neatness.

Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
The problem was seen and reported by Johannes Berg  and Frederik Himpe.
Paul, I think this is good for 2.6.24.

Changes since v1:
 - I noticed that the #define was explictly using "current" rather than
   the task passed in.  Using tsk is the right thing to do.
 - The whiteapce changes dirty-up the patch and are un-needed with the
   change above.

 arch/powerpc/kernel/process.c |    2 +-
 include/asm-powerpc/time.h    |    8 ++------
 2 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 41e13f4..b9d8837 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -350,7 +350,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
 	local_irq_save(flags);
 
 	account_system_vtime(current);
-	account_process_tick(current, 0);
+	account_process_vtime(current);
 	calculate_steal_time();
 
 	last = _switch(old_thread, new_thread);
diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h
index 780f826..a7281e0 100644
--- a/include/asm-powerpc/time.h
+++ b/include/asm-powerpc/time.h
@@ -237,18 +237,14 @@ struct cpu_usage {
 
 DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array);
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-extern void account_process_vtime(struct task_struct *tsk);
-#else
-#define account_process_vtime(tsk)		do { } while (0)
-#endif
-
 #if defined(CONFIG_VIRT_CPU_ACCOUNTING)
 extern void calculate_steal_time(void);
 extern void snapshot_timebases(void);
+#define account_process_vtime(tsk)		account_process_tick(tsk, 0);
 #else
 #define calculate_steal_time()			do { } while (0)
 #define snapshot_timebases()			do { } while (0)
+#define account_process_vtime(tsk)		do { } while (0)
 #endif
 
 extern void secondary_cpu_time_init(void);
-- 
1.5.3.6

^ permalink raw reply related

* [PATCH] pci: Fix bus resource assignment on 32 bits with 64b resources
From: Benjamin Herrenschmidt @ 2007-12-04  6:08 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: linuxppc-dev, linux-pci, linux-kernel

The current pci_assign_unassigned_resources() code doesn't work properly
on 32 bits platforms with 64 bits resources. The main reason is the use
of unsigned long in various places instead of resource_size_t.

This fixes it, along with some tricks to avoid casting to 64 bits on
platforms that don't need it in every printk around.

This is a pre-requisite for making powerpc use the generic code instead of
its own half-useful implementation.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

 drivers/pci/pci.h       |   11 +++++++++++
 drivers/pci/setup-bus.c |   32 +++++++++++++++++---------------
 drivers/pci/setup-res.c |    5 ++---
 include/linux/pci.h     |    4 ++--
 4 files changed, 32 insertions(+), 20 deletions(-)

Index: linux-work/drivers/pci/pci.h
===================================================================
--- linux-work.orig/drivers/pci/pci.h	2007-12-04 17:00:43.000000000 +1100
+++ linux-work/drivers/pci/pci.h	2007-12-04 17:02:11.000000000 +1100
@@ -91,3 +91,14 @@ pci_match_one_device(const struct pci_de
 }
 
 struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev);
+
+#ifdef CONFIG_RESOURCES_64BIT
+#define RESOURCE_ORDER(order)	(1ULL << (order))
+#define RES_PR			"%016llx"
+#else
+#define RESOURCE_ORDER(order)	(1UL << (order))
+#define RES_PR			"%08lx"
+#endif
+
+#define RANGE_PR		RES_PR "-" RES_PR
+
Index: linux-work/drivers/pci/setup-bus.c
===================================================================
--- linux-work.orig/drivers/pci/setup-bus.c	2007-12-04 17:00:43.000000000 +1100
+++ linux-work/drivers/pci/setup-bus.c	2007-12-04 17:04:23.000000000 +1100
@@ -26,6 +26,7 @@
 #include <linux/cache.h>
 #include <linux/slab.h>
 
+#include "pci.h"
 
 #define DEBUG_CONFIG 1
 #if DEBUG_CONFIG
@@ -89,8 +90,9 @@ void pci_setup_cardbus(struct pci_bus *b
 		 * The IO resource is allocated a range twice as large as it
 		 * would normally need.  This allows us to set both IO regs.
 		 */
-		printk("  IO window: %08lx-%08lx\n",
-			region.start, region.end);
+		printk(KERN_INFO "  IO window: 0x%08lx-0x%08lx\n",
+		       (unsigned long)region.start,
+		       (unsigned long)region.end);
 		pci_write_config_dword(bridge, PCI_CB_IO_BASE_0,
 					region.start);
 		pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0,
@@ -99,7 +101,7 @@ void pci_setup_cardbus(struct pci_bus *b
 
 	pcibios_resource_to_bus(bridge, &region, bus->resource[1]);
 	if (bus->resource[1]->flags & IORESOURCE_IO) {
-		printk("  IO window: %08lx-%08lx\n",
+		printk(KERN_INFO "  IO window: "RANGE_PR"\n",
 			region.start, region.end);
 		pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
 					region.start);
@@ -109,7 +111,7 @@ void pci_setup_cardbus(struct pci_bus *b
 
 	pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
 	if (bus->resource[2]->flags & IORESOURCE_MEM) {
-		printk("  PREFETCH window: %08lx-%08lx\n",
+		printk(KERN_INFO "  PREFETCH window: "RANGE_PR"\n",
 			region.start, region.end);
 		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
 					region.start);
@@ -119,7 +121,7 @@ void pci_setup_cardbus(struct pci_bus *b
 
 	pcibios_resource_to_bus(bridge, &region, bus->resource[3]);
 	if (bus->resource[3]->flags & IORESOURCE_MEM) {
-		printk("  MEM window: %08lx-%08lx\n",
+		printk(KERN_INFO "  MEM window: "RANGE_PR"\n",
 			region.start, region.end);
 		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
 					region.start);
@@ -159,7 +161,8 @@ pci_setup_bridge(struct pci_bus *bus)
 		/* Set up upper 16 bits of I/O base/limit. */
 		io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
 		DBG(KERN_INFO "  IO window: %04lx-%04lx\n",
-				region.start, region.end);
+		    (unsigned long)region.start,
+		    (unsigned long)region.end);
 	}
 	else {
 		/* Clear upper 16 bits of I/O base/limit. */
@@ -180,7 +183,7 @@ pci_setup_bridge(struct pci_bus *bus)
 	if (bus->resource[1]->flags & IORESOURCE_MEM) {
 		l = (region.start >> 16) & 0xfff0;
 		l |= region.end & 0xfff00000;
-		DBG(KERN_INFO "  MEM window: %08lx-%08lx\n",
+		DBG(KERN_INFO "  MEM window: "RANGE_PR"\n",
 				region.start, region.end);
 	}
 	else {
@@ -199,7 +202,7 @@ pci_setup_bridge(struct pci_bus *bus)
 	if (bus->resource[2]->flags & IORESOURCE_PREFETCH) {
 		l = (region.start >> 16) & 0xfff0;
 		l |= region.end & 0xfff00000;
-		DBG(KERN_INFO "  PREFETCH window: %08lx-%08lx\n",
+		DBG(KERN_INFO "  PREFETCH window: "RANGE_PR"\n",
 				region.start, region.end);
 	}
 	else {
@@ -323,8 +326,8 @@ static void pbus_size_io(struct pci_bus 
 static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
 {
 	struct pci_dev *dev;
-	unsigned long min_align, align, size;
-	unsigned long aligns[12];	/* Alignments from 1Mb to 2Gb */
+	resource_size_t min_align, align, size;
+	resource_size_t aligns[12];	/* Alignments from 1Mb to 2Gb */
 	int order, max_order;
 	struct resource *b_res = find_free_bus_resource(bus, type);
 
@@ -340,7 +343,7 @@ static int pbus_size_mem(struct pci_bus 
 		
 		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
 			struct resource *r = &dev->resource[i];
-			unsigned long r_size;
+			resource_size_t r_size;
 
 			if (r->parent || (r->flags & mask) != type)
 				continue;
@@ -350,10 +353,9 @@ static int pbus_size_mem(struct pci_bus 
 			order = __ffs(align) - 20;
 			if (order > 11) {
 				printk(KERN_WARNING "PCI: region %s/%d "
-				       "too large: %llx-%llx\n",
+				       "too large: " RANGE_PR "\n",
 					pci_name(dev), i,
-					(unsigned long long)r->start,
-					(unsigned long long)r->end);
+					r->start, r->end);
 				r->flags = 0;
 				continue;
 			}
@@ -372,7 +374,7 @@ static int pbus_size_mem(struct pci_bus 
 	align = 0;
 	min_align = 0;
 	for (order = 0; order <= max_order; order++) {
-		unsigned long align1 = 1UL << (order + 20);
+		resource_size_t align1 = RESOURCE_ORDER(order + 20);
 
 		if (!align)
 			min_align = align1;
Index: linux-work/drivers/pci/setup-res.c
===================================================================
--- linux-work.orig/drivers/pci/setup-res.c	2007-12-04 17:00:43.000000000 +1100
+++ linux-work/drivers/pci/setup-res.c	2007-12-04 17:02:11.000000000 +1100
@@ -51,9 +51,8 @@ pci_update_resource(struct pci_dev *dev,
 
 	pcibios_resource_to_bus(dev, &region, res);
 
-	pr_debug("  got res [%llx:%llx] bus [%lx:%lx] flags %lx for "
-		 "BAR %d of %s\n", (unsigned long long)res->start,
-		 (unsigned long long)res->end,
+	pr_debug("  got res ["RANGE_PR"] bus ["RANGE_PR"] flags %lx for "
+		 "BAR %d of %s\n", res->start, res->end,
 		 region.start, region.end, res->flags, resno, pci_name(dev));
 
 	new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
Index: linux-work/include/linux/pci.h
===================================================================
--- linux-work.orig/include/linux/pci.h	2007-12-04 17:00:43.000000000 +1100
+++ linux-work/include/linux/pci.h	2007-12-04 17:02:11.000000000 +1100
@@ -314,8 +314,8 @@ struct pci_raw_ops {
 extern struct pci_raw_ops *raw_pci_ops;
 
 struct pci_bus_region {
-	unsigned long start;
-	unsigned long end;
+	resource_size_t start;
+	resource_size_t end;
 };
 
 struct pci_dynids {

^ permalink raw reply

* zImage.initrd.ebony image /ramdisk Image
From: vinay kumar @ 2007-12-04  7:15 UTC (permalink / raw)
  To: linuxppc-embedded

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

I am trying to boot linux on ebony.
Can any one please help me in either sharing a ready made image of
kernel and ramdisk or united image.

How do we build a fresh image ourselves.?

Thanks a lot.
Vinay

[-- Attachment #2: Type: text/html, Size: 230 bytes --]

^ permalink raw reply

* Re: [PATCH 4/7] powerpc: Rework the machine_[restart|power_off|halt] routines
From: Benjamin Herrenschmidt @ 2007-12-04  7:20 UTC (permalink / raw)
  To: Mark A. Greer; +Cc: linuxppc-dev
In-Reply-To: <20071204054718.GE27862@mag.az.mvista.com>


On Mon, 2007-12-03 at 22:47 -0700, Mark A. Greer wrote:
> From: Mark A. Greer <mgreer@mvista.com>
> 
> Factor out common code from the machine_xxx routines and make them better
> handle a ppc_md hook that doesn't exist or fails better.  In particular,
> have machine_power_off() try ppc_md.halt if ppc_md.power_off is NULL or fails,
> and have machine_halt() try to power off when ppc_md.halt is NULL or fails.
> 
> Signed-off-by: Mark A. Greer <mgreer@mvista.com>

Quick glance... looks fine.

> ---
>  arch/powerpc/kernel/setup-common.c |   40 ++++++++++++++-------------
>  1 file changed, 22 insertions(+), 18 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
> index 6adb5a1..1f8f9aa 100644
> --- a/arch/powerpc/kernel/setup-common.c
> +++ b/arch/powerpc/kernel/setup-common.c
> @@ -105,17 +105,23 @@ void machine_shutdown(void)
>  		ppc_md.machine_shutdown();
>  }
>  
> -void machine_restart(char *cmd)
> +static void default_halt(const char *s)
>  {
> -	machine_shutdown();
> -	if (ppc_md.restart)
> -		ppc_md.restart(cmd);
>  #ifdef CONFIG_SMP
>  	smp_send_stop();
>  #endif
> -	printk(KERN_EMERG "System Halted, OK to turn off power\n");
> +	printk(KERN_EMERG "%s", s);
>  	local_irq_disable();
> -	while (1) ;
> +	while (1);
> +}
> +
> +void machine_restart(char *cmd)
> +{
> +	machine_shutdown();
> +	if (ppc_md.restart)
> +		ppc_md.restart(cmd);
> +	default_halt("System not restarted; halting instead.\n"
> +			"OK to turn off power\n");
>  }
>  
>  void machine_power_off(void)
> @@ -123,12 +129,10 @@ void machine_power_off(void)
>  	machine_shutdown();
>  	if (ppc_md.power_off)
>  		ppc_md.power_off();
> -#ifdef CONFIG_SMP
> -	smp_send_stop();
> -#endif
> -	printk(KERN_EMERG "System Halted, OK to turn off power\n");
> -	local_irq_disable();
> -	while (1) ;
> +	printk(KERN_EMERG "System not powered off; halting instead.\n");
> +	if (ppc_md.halt)
> +		ppc_md.halt();
> +	default_halt("OK to turn off power\n");
>  }
>  /* Used by the G5 thermal driver */
>  EXPORT_SYMBOL_GPL(machine_power_off);
> @@ -141,12 +145,12 @@ void machine_halt(void)
>  	machine_shutdown();
>  	if (ppc_md.halt)
>  		ppc_md.halt();
> -#ifdef CONFIG_SMP
> -	smp_send_stop();
> -#endif
> -	printk(KERN_EMERG "System Halted, OK to turn off power\n");
> -	local_irq_disable();
> -	while (1) ;
> +	if (ppc_md.power_off) {
> +		printk(KERN_EMERG "System not halted; powering off instead.\n");
> +		ppc_md.power_off();
> +		printk(KERN_EMERG "Poweroff failed.\n");
> +	}
> +	default_halt("OK to turn off power\n");
>  }
>  
> 

^ permalink raw reply

* Re: [PATCH 5/7] powerpc: Replace ppc_md.power_off with pm_power_off
From: Benjamin Herrenschmidt @ 2007-12-04  7:23 UTC (permalink / raw)
  To: Mark A. Greer; +Cc: linuxppc-dev
In-Reply-To: <20071204054821.GF27862@mag.az.mvista.com>


On Mon, 2007-12-03 at 22:48 -0700, Mark A. Greer wrote:
> From: Mark A. Greer <mgreer@mvista.com>
> 
> The ppc_md.power_off hook performs the same function that the
> pm_power_off hook is supposed to.  However, it is powerpc-specific
> and prevents kernel drivers (e.g., IPMI) from changing how a platform
> is powered off.  So, get rid of ppc_md.power_off and replace it with
> pm_power_off.

I'm less happy with that one... probably aesthetics :-)

Can't we just have the generic code call pm_power_off and ppc_md and
which ever powers the machine off wins ?

> Signed-off-by: Mark A. Greer <mgreer@mvista.com>
> ---
>  arch/powerpc/kernel/setup-common.c               |   14 +--
>  arch/powerpc/platforms/52xx/efika.c              |    2 
>  arch/powerpc/platforms/cell/setup.c              |    2 
>  arch/powerpc/platforms/celleb/setup.c            |    2 
>  arch/powerpc/platforms/chrp/setup.c              |    2 
>  arch/powerpc/platforms/embedded6xx/linkstation.c |    3 
>  arch/powerpc/platforms/iseries/setup.c           |    2 
>  arch/powerpc/platforms/maple/setup.c             |    4 
>  arch/powerpc/platforms/powermac/setup.c          |    2 
>  arch/powerpc/platforms/ps3/setup.c               |    2 
>  arch/powerpc/platforms/pseries/setup.c           |   59 ++++++-------
>  include/asm-powerpc/machdep.h                    |    1 
>  12 files changed, 48 insertions(+), 47 deletions(-)
> 
> 
> diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
> index 1f8f9aa..d9f2e07 100644
> --- a/arch/powerpc/kernel/setup-common.c
> +++ b/arch/powerpc/kernel/setup-common.c
> @@ -76,6 +76,9 @@ EXPORT_SYMBOL(ppc_md);
>  struct machdep_calls *machine_id;
>  EXPORT_SYMBOL(machine_id);
>  
> +void (*pm_power_off)(void);
> +EXPORT_SYMBOL_GPL(pm_power_off);
> +
>  unsigned long klimit = (unsigned long) _end;
>  
>  char cmd_line[COMMAND_LINE_SIZE];
> @@ -127,8 +130,8 @@ void machine_restart(char *cmd)
>  void machine_power_off(void)
>  {
>  	machine_shutdown();
> -	if (ppc_md.power_off)
> -		ppc_md.power_off();
> +	if (pm_power_off)
> +		pm_power_off();
>  	printk(KERN_EMERG "System not powered off; halting instead.\n");
>  	if (ppc_md.halt)
>  		ppc_md.halt();
> @@ -137,17 +140,14 @@ void machine_power_off(void)
>  /* Used by the G5 thermal driver */
>  EXPORT_SYMBOL_GPL(machine_power_off);
>  
> -void (*pm_power_off)(void) = machine_power_off;
> -EXPORT_SYMBOL_GPL(pm_power_off);
> -
>  void machine_halt(void)
>  {
>  	machine_shutdown();
>  	if (ppc_md.halt)
>  		ppc_md.halt();
> -	if (ppc_md.power_off) {
> +	if (pm_power_off) {
>  		printk(KERN_EMERG "System not halted; powering off instead.\n");
> -		ppc_md.power_off();
> +		pm_power_off();
>  		printk(KERN_EMERG "Poweroff failed.\n");
>  	}
>  	default_halt("OK to turn off power\n");
> diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
> index a0da70c..c2d5f06 100644
> --- a/arch/powerpc/platforms/52xx/efika.c
> +++ b/arch/powerpc/platforms/52xx/efika.c
> @@ -205,6 +205,7 @@ static int __init efika_probe(void)
>  	DMA_MODE_READ = 0x44;
>  	DMA_MODE_WRITE = 0x48;
>  
> +	pm_power_off = rtas_power_off;
>  	return 1;
>  }
>  
> @@ -218,7 +219,6 @@ define_machine(efika)
>  	.init_IRQ		= mpc52xx_init_irq,
>  	.get_irq		= mpc52xx_get_irq,
>  	.restart		= rtas_restart,
> -	.power_off		= rtas_power_off,
>  	.halt			= rtas_halt,
>  	.set_rtc_time		= rtas_set_rtc_time,
>  	.get_rtc_time		= rtas_get_rtc_time,
> diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
> index 98e7ef8..06f44f5 100644
> --- a/arch/powerpc/platforms/cell/setup.c
> +++ b/arch/powerpc/platforms/cell/setup.c
> @@ -191,6 +191,7 @@ static int __init cell_probe(void)
>  		return 0;
>  
>  	hpte_init_native();
> +	pm_power_off = rtas_power_off;
>  
>  	return 1;
>  }
> @@ -201,7 +202,6 @@ define_machine(cell) {
>  	.setup_arch		= cell_setup_arch,
>  	.show_cpuinfo		= cell_show_cpuinfo,
>  	.restart		= rtas_restart,
> -	.power_off		= rtas_power_off,
>  	.halt			= rtas_halt,
>  	.get_boot_time		= rtas_get_boot_time,
>  	.get_rtc_time		= rtas_get_rtc_time,
> diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c
> index ddfb35a..450841a 100644
> --- a/arch/powerpc/platforms/celleb/setup.c
> +++ b/arch/powerpc/platforms/celleb/setup.c
> @@ -116,6 +116,7 @@ static int __init celleb_probe(void)
>  
>  	powerpc_firmware_features |= FW_FEATURE_CELLEB_POSSIBLE;
>  	hpte_init_beat_v3();
> +	pm_power_off = beat_power_off;
>  	return 1;
>  }
>  
> @@ -145,7 +146,6 @@ define_machine(celleb) {
>  	.setup_arch		= celleb_setup_arch,
>  	.show_cpuinfo		= celleb_show_cpuinfo,
>  	.restart		= beat_restart,
> -	.power_off		= beat_power_off,
>  	.halt			= beat_halt,
>  	.get_rtc_time		= beat_get_rtc_time,
>  	.set_rtc_time		= beat_set_rtc_time,
> diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
> index 5930626..99edb04 100644
> --- a/arch/powerpc/platforms/chrp/setup.c
> +++ b/arch/powerpc/platforms/chrp/setup.c
> @@ -586,6 +586,7 @@ static int __init chrp_probe(void)
>  	DMA_MODE_READ = 0x44;
>  	DMA_MODE_WRITE = 0x48;
>  
> +	pm_power_off = rtas_power_off;
>  	return 1;
>  }
>  
> @@ -597,7 +598,6 @@ define_machine(chrp) {
>  	.show_cpuinfo		= chrp_show_cpuinfo,
>  	.init_IRQ		= chrp_init_IRQ,
>  	.restart		= rtas_restart,
> -	.power_off		= rtas_power_off,
>  	.halt			= rtas_halt,
>  	.time_init		= chrp_time_init,
>  	.set_rtc_time		= chrp_set_rtc_time,
> diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
> index eb5d74e..8792840 100644
> --- a/arch/powerpc/platforms/embedded6xx/linkstation.c
> +++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
> @@ -182,6 +182,8 @@ static int __init linkstation_probe(void)
>  
>  	if (!of_flat_dt_is_compatible(root, "linkstation"))
>  		return 0;
> +
> +	pm_power_off = linkstation_power_off;
>  	return 1;
>  }
>  
> @@ -193,7 +195,6 @@ define_machine(linkstation){
>  	.show_cpuinfo 		= linkstation_show_cpuinfo,
>  	.get_irq 		= mpic_get_irq,
>  	.restart 		= linkstation_restart,
> -	.power_off 		= linkstation_power_off,
>  	.halt	 		= linkstation_halt,
>  	.calibrate_decr 	= generic_calibrate_decr,
>  };
> diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
> index 2175a71..6051204 100644
> --- a/arch/powerpc/platforms/iseries/setup.c
> +++ b/arch/powerpc/platforms/iseries/setup.c
> @@ -633,6 +633,7 @@ static int __init iseries_probe(void)
>  	/* iSeries does not support 16M pages */
>  	cur_cpu_spec->cpu_features &= ~CPU_FTR_16M_PAGE;
>  
> +	pm_power_off = mf_power_off;
>  	return 1;
>  }
>  
> @@ -645,7 +646,6 @@ define_machine(iseries) {
>  	.init_early	= iSeries_init_early,
>  	.pcibios_fixup	= iSeries_pci_final_fixup,
>  	.restart	= mf_reboot,
> -	.power_off	= mf_power_off,
>  	.halt		= mf_power_off,
>  	.get_boot_time	= iSeries_get_boot_time,
>  	.set_rtc_time	= iSeries_set_rtc_time,
> diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
> index 144177d..d0eb901 100644
> --- a/arch/powerpc/platforms/maple/setup.c
> +++ b/arch/powerpc/platforms/maple/setup.c
> @@ -172,7 +172,7 @@ static void __init maple_use_rtas_reboot_and_halt_if_present(void)
>  	if (rtas_service_present("system-reboot") &&
>  	    rtas_service_present("power-off")) {
>  		ppc_md.restart = rtas_restart;
> -		ppc_md.power_off = rtas_power_off;
> +		pm_power_off = rtas_power_off;
>  		ppc_md.halt = rtas_halt;
>  	}
>  }
> @@ -315,6 +315,7 @@ static int __init maple_probe(void)
>  	alloc_dart_table();
>  
>  	hpte_init_native();
> +	pm_power_off = maple_power_off;
>  
>  	return 1;
>  }
> @@ -328,7 +329,6 @@ define_machine(maple_md) {
>  	.pci_irq_fixup		= maple_pci_irq_fixup,
>  	.pci_get_legacy_ide_irq	= maple_pci_get_legacy_ide_irq,
>  	.restart		= maple_restart,
> -	.power_off		= maple_power_off,
>  	.halt			= maple_halt,
>         	.get_boot_time		= maple_get_boot_time,
>         	.set_rtc_time		= maple_set_rtc_time,
> diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
> index 02c5330..8429002 100644
> --- a/arch/powerpc/platforms/powermac/setup.c
> +++ b/arch/powerpc/platforms/powermac/setup.c
> @@ -577,6 +577,7 @@ static int __init pmac_probe(void)
>  
>  	hpte_init_native();
>  #endif
> +	pm_power_off = pmac_power_off;
>  
>  #ifdef CONFIG_PPC32
>  	/* isa_io_base gets set in pmac_pci_init */
> @@ -676,7 +677,6 @@ define_machine(powermac) {
>  	.get_irq		= NULL,	/* changed later */
>  	.pci_irq_fixup		= pmac_pci_irq_fixup,
>  	.restart		= pmac_restart,
> -	.power_off		= pmac_power_off,
>  	.halt			= pmac_halt,
>  	.time_init		= pmac_time_init,
>  	.get_boot_time		= pmac_get_boot_time,
> diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
> index 5c2cbb0..74942d8 100644
> --- a/arch/powerpc/platforms/ps3/setup.c
> +++ b/arch/powerpc/platforms/ps3/setup.c
> @@ -233,6 +233,7 @@ static int __init ps3_probe(void)
>  	ps3_mm_init();
>  	ps3_mm_vas_create(&htab_size);
>  	ps3_hpte_init(htab_size);
> +	pm_power_off = ps3_power_off;
>  
>  	DBG(" <- %s:%d\n", __func__, __LINE__);
>  	return 1;
> @@ -265,7 +266,6 @@ define_machine(ps3) {
>  	.calibrate_decr			= ps3_calibrate_decr,
>  	.progress			= ps3_progress,
>  	.restart			= ps3_restart,
> -	.power_off			= ps3_power_off,
>  #if defined(CONFIG_KEXEC)
>  	.kexec_cpu_down			= ps3_kexec_cpu_down,
>  	.machine_kexec			= default_machine_kexec,
> diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
> index fdb9b1c..51ef84c 100644
> --- a/arch/powerpc/platforms/pseries/setup.c
> +++ b/arch/powerpc/platforms/pseries/setup.c
> @@ -353,6 +353,34 @@ static int __init pSeries_probe_hypertas(unsigned long node,
>  	return 1;
>  }
>  
> +/**
> + * pSeries_power_off - tell firmware about how to power off the system.
> + *
> + * This function calls either the power-off rtas token in normal cases
> + * or the ibm,power-off-ups token (if present & requested) in case of
> + * a power failure. If power-off token is used, power on will only be
> + * possible with power button press. If ibm,power-off-ups token is used
> + * it will allow auto poweron after power is restored.
> + */
> +void pSeries_power_off(void)
> +{
> +	int rc;
> +	int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups");
> +
> +	if (rtas_flash_term_hook)
> +		rtas_flash_term_hook(SYS_POWER_OFF);
> +
> +	if (rtas_poweron_auto == 0 ||
> +		rtas_poweroff_ups_token == RTAS_UNKNOWN_SERVICE) {
> +		rc = rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1);
> +		printk(KERN_INFO "RTAS power-off returned %d\n", rc);
> +	} else {
> +		rc = rtas_call(rtas_poweroff_ups_token, 0, 1, NULL);
> +		printk(KERN_INFO "RTAS ibm,power-off-ups returned %d\n", rc);
> +	}
> +	for (;;);
> +}
> +
>  static int __init pSeries_probe(void)
>  {
>  	unsigned long root = of_get_flat_dt_root();
> @@ -380,6 +408,8 @@ static int __init pSeries_probe(void)
>  	else
>  		hpte_init_native();
>  
> +	pm_power_off = pSeries_power_off;
> +
>  	DBG("Machine is%s LPAR !\n",
>  	    (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
>  
> @@ -463,34 +493,6 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus)
>  	return PCI_PROBE_NORMAL;
>  }
>  
> -/**
> - * pSeries_power_off - tell firmware about how to power off the system.
> - *
> - * This function calls either the power-off rtas token in normal cases
> - * or the ibm,power-off-ups token (if present & requested) in case of
> - * a power failure. If power-off token is used, power on will only be
> - * possible with power button press. If ibm,power-off-ups token is used
> - * it will allow auto poweron after power is restored.
> - */
> -void pSeries_power_off(void)
> -{
> -	int rc;
> -	int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups");
> -
> -	if (rtas_flash_term_hook)
> -		rtas_flash_term_hook(SYS_POWER_OFF);
> -
> -	if (rtas_poweron_auto == 0 ||
> -		rtas_poweroff_ups_token == RTAS_UNKNOWN_SERVICE) {
> -		rc = rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1);
> -		printk(KERN_INFO "RTAS power-off returned %d\n", rc);
> -	} else {
> -		rc = rtas_call(rtas_poweroff_ups_token, 0, 1, NULL);
> -		printk(KERN_INFO "RTAS ibm,power-off-ups returned %d\n", rc);
> -	}
> -	for (;;);
> -}
> -
>  #ifndef CONFIG_PCI
>  void pSeries_final_fixup(void) { }
>  #endif
> @@ -505,7 +507,6 @@ define_machine(pseries) {
>  	.pcibios_fixup		= pSeries_final_fixup,
>  	.pci_probe_mode		= pSeries_pci_probe_mode,
>  	.restart		= rtas_restart,
> -	.power_off		= pSeries_power_off,
>  	.halt			= rtas_halt,
>  	.panic			= rtas_os_term,
>  	.get_boot_time		= rtas_get_boot_time,
> diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
> index 6968f43..bca57bc 100644
> --- a/include/asm-powerpc/machdep.h
> +++ b/include/asm-powerpc/machdep.h
> @@ -129,7 +129,6 @@ struct machdep_calls {
>  #endif
>  
>  	void		(*restart)(char *cmd);
> -	void		(*power_off)(void);
>  	void		(*halt)(void);
>  	void		(*panic)(char *str);
>  	void		(*cpu_die)(void);

^ permalink raw reply

* RE: [PATCH] ipic: change ack operation that register isaccessedonly when needed
From: Li Yang @ 2007-12-04  7:23 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev
In-Reply-To: <1196734556.13230.258.camel@pasglop>

> -----Original Message-----
> From: Benjamin Herrenschmidt [mailto:benh@kernel.crashing.org]=20
> Sent: Tuesday, December 04, 2007 10:16 AM
> To: Li Yang
> Cc: galak@kernel.crashing.org; linuxppc-dev@ozlabs.org
> Subject: RE: [PATCH] ipic: change ack operation that register=20
> isaccessedonly when needed
>=20
>=20
> On Tue, 2007-12-04 at 10:06 +0800, Li Yang wrote:
> > > That should be handled by the higher level flow handler.=20
> The generic=20
> > > edge one calls ack and the level one mask_and_ack.
> > > Just make them do the right thing, no need to test for=20
> the flow type=20
> > > in the low level function.
> >=20
> > But actually ack is called by edge and per cpu handlers. =20
> Mask_and_ack=20
> > is also called by edge handler when the same interrupt is=20
> already in=20
> > progress.  So I don't think that ack/mask_and_ack=20
> implicates flow type=20
> > by design.
>=20
> They do and you can pass different irq_chip with different=20
> mask/ack routines if necessary.
Hi Ben,

I mean that mask_ack_irq() routine is used by both generic
handle_edge_irq() and handle_level_irq().  mask_ack_irq doesn't know if
the flow type is level or edge.  Do you suggest to use different
irq_chip for level and edge?

- Leo

^ permalink raw reply

* RE: [PATCH] ipic: change ack operation that register isaccessedonly when needed
From: Benjamin Herrenschmidt @ 2007-12-04  7:39 UTC (permalink / raw)
  To: Li Yang; +Cc: linuxppc-dev
In-Reply-To: <989B956029373F45A0B8AF029708189001B4D360@zch01exm26.fsl.freescale.net>


On Tue, 2007-12-04 at 15:23 +0800, Li Yang wrote:
> > -----Original Message-----
> > From: Benjamin Herrenschmidt [mailto:benh@kernel.crashing.org] 
> > Sent: Tuesday, December 04, 2007 10:16 AM
> > To: Li Yang
> > Cc: galak@kernel.crashing.org; linuxppc-dev@ozlabs.org
> > Subject: RE: [PATCH] ipic: change ack operation that register 
> > isaccessedonly when needed
> > 
> > 
> > On Tue, 2007-12-04 at 10:06 +0800, Li Yang wrote:
> > > > That should be handled by the higher level flow handler. 
> > The generic 
> > > > edge one calls ack and the level one mask_and_ack.
> > > > Just make them do the right thing, no need to test for 
> > the flow type 
> > > > in the low level function.
> > > 
> > > But actually ack is called by edge and per cpu handlers.  
> > Mask_and_ack 
> > > is also called by edge handler when the same interrupt is 
> > already in 
> > > progress.  So I don't think that ack/mask_and_ack 
> > implicates flow type 
> > > by design.
> > 
> > They do and you can pass different irq_chip with different 
> > mask/ack routines if necessary.
> Hi Ben,
> 
> I mean that mask_ack_irq() routine is used by both generic
> handle_edge_irq() and handle_level_irq().  mask_ack_irq doesn't know if
> the flow type is level or edge.  Do you suggest to use different
> irq_chip for level and edge?

That would be an option. I dislike testing the flow type in the fast
path.

Ben.

^ permalink raw reply

* Re: [PATCH] Add IPIC MSI interrupt support
From: Benjamin Herrenschmidt @ 2007-12-04  7:51 UTC (permalink / raw)
  To: michael; +Cc: linuxppc-dev, Gala Kumar, Li Li, Li Tony
In-Reply-To: <1196746689.20158.4.camel@concordia>

> I'm not sure what you mean? For MSI there is only one MSI per device,
> but this code is used also for MSI-X which supports > 1 MSI per device.

Or more specifically, for MSI, -linux- supports only one per device (in
theory, it's possible to have multiple MSI non-X but it's a mess).

> Either way we shouldn't be incrementing hwirq by hand, it's reassigned
> at the top of the loop. I think that's left over from old code that
> allocated nvec hwirqs in a block and then created virq mappings for each
> one, whereas the new code allocates each hwirq separately.
> 
> cheers
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* [PATCH 1/3] cell: fix undefined reference to mmio_nvram_init
From: Ishizaki Kou @ 2007-12-04  8:34 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev

This patch fixes the following link error with
CONFIG_PPC_CELL_NATIVE=y and CONFIG_PPC_CELL_BLADE=n:

arch/powerpc/platforms/built-in.o: In function `.cell_setup_arch':
setup.c:(.init.text+0xe80): undefined reference to `.mmio_nvram_init'

Signed-off-by: Kou Ishizaki <Kou.Ishizaki@toshiba.co.jp>
---

Index: linux-powerpc-git/arch/powerpc/platforms/cell/setup.c
===================================================================
--- linux-powerpc-git.orig/arch/powerpc/platforms/cell/setup.c
+++ linux-powerpc-git/arch/powerpc/platforms/cell/setup.c
@@ -179,7 +179,9 @@ static void __init cell_setup_arch(void)
 	conswitchp = &dummy_con;
 #endif
 
+#ifdef CONFIG_MMIO_NVRAM
 	mmio_nvram_init();
+#endif
 }
 
 static int __init cell_probe(void)

^ permalink raw reply

* [PATCH 2/3] celleb: add supporting for native CBE
From: Ishizaki Kou @ 2007-12-04  8:38 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev

This patch adds supporting for native CBE on Celleb.  Many codes in
platforms/cell/ are used when native CBE environment.

Signed-off-by: Kou Ishizaki <Kou.Ishizaki@toshiba.co.jp>
---

Index: linux-powerpc-git/arch/powerpc/platforms/cell/iommu.c
===================================================================
--- linux-powerpc-git.orig/arch/powerpc/platforms/cell/iommu.c
+++ linux-powerpc-git/arch/powerpc/platforms/cell/iommu.c
@@ -34,6 +34,7 @@
 #include <asm/udbg.h>
 #include <asm/of_platform.h>
 #include <asm/lmb.h>
+#include <asm/firmware.h>
 #include <asm/cell-regs.h>
 
 #include "interrupt.h"
@@ -699,7 +700,8 @@ static int __init cell_iommu_init(void)
 {
 	struct device_node *np;
 
-	if (!machine_is(cell))
+	if ((!machine_is(cell) && !machine_is(celleb)) ||
+	    firmware_has_feature(FW_FEATURE_LPAR))
 		return -ENODEV;
 
 	/* If IOMMU is disabled or we have little enough RAM to not need
Index: linux-powerpc-git/arch/powerpc/platforms/celleb/Kconfig
===================================================================
--- linux-powerpc-git.orig/arch/powerpc/platforms/celleb/Kconfig
+++ linux-powerpc-git/arch/powerpc/platforms/celleb/Kconfig
@@ -2,6 +2,8 @@ config PPC_CELLEB
 	bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
 	depends on PPC_MULTIPLATFORM && PPC64
 	select PPC_CELL
+	select PPC_CELL_NATIVE
+	select PPC_RTAS
 	select PPC_INDIRECT_IO
 	select PPC_OF_PLATFORM_PCI
 	select HAS_TXX9_SERIAL
Index: linux-powerpc-git/arch/powerpc/platforms/celleb/iommu.c
===================================================================
--- linux-powerpc-git.orig/arch/powerpc/platforms/celleb/iommu.c
+++ linux-powerpc-git/arch/powerpc/platforms/celleb/iommu.c
@@ -24,6 +24,7 @@
 #include <linux/pci.h>
 
 #include <asm/of_platform.h>
+#include <asm/firmware.h>
 
 #include "beat_wrapper.h"
 
@@ -91,7 +92,7 @@ static struct notifier_block celleb_of_b
 
 static int __init celleb_init_iommu(void)
 {
-	if (!machine_is(celleb))
+	if (!firmware_has_feature(FW_FEATURE_BEAT))
 		return -ENODEV;
 
 	celleb_init_direct_mapping();
Index: linux-powerpc-git/arch/powerpc/platforms/celleb/setup.c
===================================================================
--- linux-powerpc-git.orig/arch/powerpc/platforms/celleb/setup.c
+++ linux-powerpc-git/arch/powerpc/platforms/celleb/setup.c
@@ -53,11 +53,16 @@
 #include <asm/spu_priv1.h>
 #include <asm/firmware.h>
 #include <asm/of_platform.h>
+#include <asm/rtas.h>
+#include <asm/cell-regs.h>
 
 #include "interrupt.h"
 #include "beat_wrapper.h"
 #include "beat.h"
 #include "pci.h"
+#include "../cell/interrupt.h"
+#include "../cell/pervasive.h"
+#include "../cell/ras.h"
 
 static char celleb_machine_type[128] = "Celleb";
 
@@ -88,16 +93,74 @@ static void celleb_progress(char *s, uns
 	printk("*** %04x : %s\n", hex, s ? s : "");
 }
 
-static void __init celleb_setup_arch(void)
+static void __init celleb_init_IRQ_native(void)
+{
+	iic_init_IRQ();
+	spider_init_IRQ();
+}
+
+static void __init celleb_setup_arch_beat(void)
 {
+	ppc_md.restart		= beat_restart;
+	ppc_md.power_off	= beat_power_off;
+	ppc_md.halt		= beat_halt;
+	ppc_md.get_rtc_time	= beat_get_rtc_time;
+	ppc_md.set_rtc_time	= beat_set_rtc_time;
+	ppc_md.power_save	= beat_power_save;
+	ppc_md.nvram_size	= beat_nvram_get_size;
+	ppc_md.nvram_read	= beat_nvram_read;
+	ppc_md.nvram_write	= beat_nvram_write;
+	ppc_md.set_dabr		= beat_set_xdabr;
+	ppc_md.init_IRQ		= beatic_init_IRQ;
+	ppc_md.get_irq		= beatic_get_irq;
+#ifdef CONFIG_KEXEC
+	ppc_md.kexec_cpu_down	= beat_kexec_cpu_down;
+#endif
+
 #ifdef CONFIG_SPU_BASE
-	spu_priv1_ops = &spu_priv1_beat_ops;
-	spu_management_ops = &spu_management_of_ops;
+	spu_priv1_ops		= &spu_priv1_beat_ops;
+	spu_management_ops	= &spu_management_of_ops;
 #endif
 
 #ifdef CONFIG_SMP
 	smp_init_celleb();
 #endif
+}
+
+static void __init celleb_setup_arch_native(void)
+{
+	ppc_md.restart		= rtas_restart;
+	ppc_md.power_off	= rtas_power_off;
+	ppc_md.halt		= rtas_halt;
+	ppc_md.get_boot_time	= rtas_get_boot_time;
+	ppc_md.get_rtc_time	= rtas_get_rtc_time;
+	ppc_md.set_rtc_time	= rtas_set_rtc_time;
+	ppc_md.init_IRQ		= celleb_init_IRQ_native;
+
+#ifdef CONFIG_SPU_BASE
+	spu_priv1_ops		= &spu_priv1_mmio_ops;
+	spu_management_ops	= &spu_management_of_ops;
+#endif
+
+	cbe_regs_init();
+
+#ifdef CONFIG_CBE_RAS
+	cbe_ras_init();
+#endif
+
+#ifdef CONFIG_SMP
+	smp_init_cell();
+#endif
+
+	cbe_pervasive_init();
+}
+
+static void __init celleb_setup_arch(void)
+{
+	if (firmware_has_feature(FW_FEATURE_BEAT))
+		celleb_setup_arch_beat();
+	else
+		celleb_setup_arch_native();
 
 	/* init to some ~sane value until calibrate_delay() runs */
 	loops_per_jiffy = 50000000;
@@ -111,12 +174,19 @@ static int __init celleb_probe(void)
 {
 	unsigned long root = of_get_flat_dt_root();
 
-	if (!of_flat_dt_is_compatible(root, "Beat"))
-		return 0;
+	if (of_flat_dt_is_compatible(root, "Beat")) {
+		powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS
+			| FW_FEATURE_BEAT | FW_FEATURE_LPAR;
+		hpte_init_beat_v3();
+		return 1;
+	}
+	if (of_flat_dt_is_compatible(root, "TOSHIBA,Celleb")) {
+		powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS;
+		hpte_init_native();
+		return 1;
+	}
 
-	powerpc_firmware_features |= FW_FEATURE_CELLEB_POSSIBLE;
-	hpte_init_beat_v3();
-	return 1;
+	return 0;
 }
 
 static struct of_device_id celleb_bus_ids[] __initdata = {
@@ -144,24 +214,11 @@ define_machine(celleb) {
 	.probe			= celleb_probe,
 	.setup_arch		= celleb_setup_arch,
 	.show_cpuinfo		= celleb_show_cpuinfo,
-	.restart		= beat_restart,
-	.power_off		= beat_power_off,
-	.halt			= beat_halt,
-	.get_rtc_time		= beat_get_rtc_time,
-	.set_rtc_time		= beat_set_rtc_time,
 	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= celleb_progress,
-	.power_save		= beat_power_save,
-	.nvram_size		= beat_nvram_get_size,
-	.nvram_read		= beat_nvram_read,
-	.nvram_write		= beat_nvram_write,
-	.set_dabr		= beat_set_xdabr,
-	.init_IRQ		= beatic_init_IRQ,
-	.get_irq		= beatic_get_irq,
 	.pci_probe_mode 	= celleb_pci_probe_mode,
 	.pci_setup_phb		= celleb_setup_phb,
 #ifdef CONFIG_KEXEC
-	.kexec_cpu_down		= beat_kexec_cpu_down,
 	.machine_kexec		= default_machine_kexec,
 	.machine_kexec_prepare	= default_machine_kexec_prepare,
 	.machine_crash_shutdown	= default_machine_crash_shutdown,
Index: linux-powerpc-git/include/asm-powerpc/firmware.h
===================================================================
--- linux-powerpc-git.orig/include/asm-powerpc/firmware.h
+++ linux-powerpc-git/include/asm-powerpc/firmware.h
@@ -64,7 +64,7 @@ enum {
 	FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
 	FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
 	FW_FEATURE_CELLEB_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_BEAT,
-	FW_FEATURE_CELLEB_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_BEAT,
+	FW_FEATURE_CELLEB_ALWAYS = 0,
 	FW_FEATURE_NATIVE_POSSIBLE = 0,
 	FW_FEATURE_NATIVE_ALWAYS = 0,
 	FW_FEATURE_POSSIBLE =

^ permalink raw reply

* [PATCH 3/3] update celleb_defconfig to support for native CBE
From: Ishizaki Kou @ 2007-12-04  8:41 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev

This patch updates celleb_defconfig to support for native CBE.

Signed-off-by: Kou Ishizaki <Kou.Ishizaki@toshiba.co.jp>
---

Index: linux-powerpc-git/arch/powerpc/configs/celleb_defconfig
===================================================================
--- linux-powerpc-git.orig/arch/powerpc/configs/celleb_defconfig
+++ linux-powerpc-git/arch/powerpc/configs/celleb_defconfig
@@ -44,7 +44,8 @@ CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
-# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_PPC_DCR_MMIO=y
+CONFIG_PPC_DCR=y
 CONFIG_PPC_OF_PLATFORM_PCI=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -141,7 +142,7 @@ CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_PPC_CELLEB=y
 # CONFIG_PPC_PS3 is not set
 CONFIG_PPC_CELL=y
-# CONFIG_PPC_CELL_NATIVE is not set
+CONFIG_PPC_CELL_NATIVE=y
 # CONFIG_PPC_IBM_CELL_BLADE is not set
 
 #
@@ -150,18 +151,24 @@ CONFIG_PPC_CELL=y
 CONFIG_SPU_FS=y
 CONFIG_SPU_FS_64K_LS=y
 CONFIG_SPU_BASE=y
+CONFIG_CBE_RAS=y
+# CONFIG_CBE_THERM is not set
 # CONFIG_PQ2ADS is not set
+CONFIG_PPC_NATIVE=y
+CONFIG_UDBG_RTAS_CONSOLE=y
 CONFIG_PPC_UDBG_BEAT=y
-# CONFIG_MPIC is not set
+CONFIG_MPIC=y
 # CONFIG_MPIC_WEIRD is not set
 # CONFIG_PPC_I8259 is not set
 # CONFIG_U3_DART is not set
-# CONFIG_PPC_RTAS is not set
+CONFIG_PPC_RTAS=y
+# CONFIG_RTAS_ERROR_LOGGING is not set
+# CONFIG_RTAS_PROC is not set
 # CONFIG_MMIO_NVRAM is not set
 # CONFIG_PPC_MPC106 is not set
 # CONFIG_PPC_970_NAP is not set
-# CONFIG_PPC_INDIRECT_IO is not set
-# CONFIG_GENERIC_IOMAP is not set
+CONFIG_PPC_INDIRECT_IO=y
+CONFIG_GENERIC_IOMAP=y
 # CONFIG_CPU_FREQ is not set
 # CONFIG_CPM2 is not set
 # CONFIG_FSL_ULI1575 is not set
@@ -723,6 +730,7 @@ CONFIG_SERIAL_TXX9_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_HVC_DRIVER=y
+CONFIG_HVC_RTAS=y
 CONFIG_HVC_BEAT=y
 # CONFIG_IPMI_HANDLER is not set
 CONFIG_WATCHDOG=y
@@ -732,6 +740,7 @@ CONFIG_WATCHDOG=y
 # Watchdog Device Drivers
 #
 # CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_WATCHDOG_RTAS is not set
 
 #
 # PCI-based Watchdog Cards
@@ -1243,16 +1252,7 @@ CONFIG_XMON_DEFAULT=y
 CONFIG_XMON_DISASSEMBLY=y
 CONFIG_IRQSTACKS=y
 # CONFIG_BOOTX_TEXT is not set
-CONFIG_PPC_EARLY_DEBUG=y
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
-# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
-CONFIG_PPC_EARLY_DEBUG_BEAT=y
-# CONFIG_PPC_EARLY_DEBUG_44x is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
 
 #
 # Security options

^ permalink raw reply

* Re: reboot of mpc8270 sometimes fails
From: Theo Gjaltema @ 2007-12-04  8:42 UTC (permalink / raw)
  To: lobo fan; +Cc: linuxppc-embedded@ozlabs.org
In-Reply-To: <d111b2340711212024o2c261b6bn790edf4b4b9f9d50@mail.gmail.com>

Index: m8260_setup.c
===================================================================
RCS file: /home/.dbCVS_linux/kernel_2_4_25/arch/ppc/kernel/m8260_setup.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -c -r1.1.1.2 -r1.2
*** m8260_setup.c	2006/11/17 07:58:49	1.1.1.2
--- m8260_setup.c	2007/10/08 07:53:54	1.2
***************
*** 148,154 ****
--- 148,164 ----
  		if (!strncmp(cmd, "startaddr=", 10))
  			startaddr = simple_strtoul(&cmd[10], NULL, 0);
  	}
+ #if defined (CONFIG_8260)
+ 	{
+ #include <asm-ppc/cpm_8260.h>
+ 	    volatile	cpm8260_t	*cp = &((immap_t *)IMAP_ADDR)->im_cpm;
  
+ 	    cp->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG);   /* see page 14.17 $14.4.2 of the CPM manual */
+ 	    
+ 	    while (cp->cp_cpcr & CPM_CR_FLG);          /* Wait for it (should be 2 clocks). */
+ 
+ 	}
+ #endif
  	m8260_gorom((unsigned int)__pa(__res), startaddr);
  }
  




lobo fan schreef:
> Hi Theo,
> Could you please give me the patch? I am very interested in your patch.
>
> -- 
> Thanks.
>
> Best Regards,
> Lobo
> ------------------------------------------------------------------------
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded

^ permalink raw reply

* Re: [PATCH] Add IPIC MSI interrupt support
From: Li Li @ 2007-12-04  9:10 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev, Gala Kumar, Li Tony
In-Reply-To: <1196754717.13230.286.camel@pasglop>

Yes. According to the PCI spec, a PCI device can request multi MSI
interrupts and require that interrupts are consecutive.
But it is ok if only allocate one to it.
Anyway, the hwirq should be allocated from bitmap instead of increment
by hand.

I will correct this and resend the patch.

- Tony

On Tue, 2007-12-04 at 15:51 +0800, Benjamin Herrenschmidt wrote:
> > I'm not sure what you mean? For MSI there is only one MSI per
> device, 
> > but this code is used also for MSI-X which supports > 1 MSI per
> device.
> 
> Or more specifically, for MSI, -linux- supports only one per device
> (in 
> theory, it's possible to have multiple MSI non-X but it's a mess).
> 
> > Either way we shouldn't be incrementing hwirq by hand, it's
> reassigned 
> > at the top of the loop. I think that's left over from old code that 
> > allocated nvec hwirqs in a block and then created virq mappings for
> each 
> > one, whereas the new code allocates each hwirq separately. 
> > 
> > cheers 
> > 
> > _______________________________________________ 
> > Linuxppc-dev mailing list 
> > Linuxppc-dev@ozlabs.org 
> > https://ozlabs.org/mailman/listinfo/linuxppc-dev
> 

^ permalink raw reply

* Re: Unable to Read PPC440EPx Board ID thru Board Control and Status Registers (BCSR)
From: Stefan Roese @ 2007-12-04  9:28 UTC (permalink / raw)
  To: Dell Query; +Cc: linuxppc-embedded
In-Reply-To: <86675.82133.qm@web45613.mail.sp1.yahoo.com>

On Monday 03 December 2007, Dell Query wrote:
> I finally got the new pdf files from other Resource CDs and used 0xc000000
> address, without 0x2000 offset.

Good.

> It works! Thanks a lot for the help.
>
> But may I know why in Linux it is mapped to 0x1c000000, wherein the doc
> stated 0xc000000?

The doc most probably only refers to the virtual address mapped in U-Boot 
here.

Best regards,
Stefan

=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de
=====================================================================

^ permalink raw reply

* RE: [PATCH] Add IPIC MSI interrupt support
From: Li Tony @ 2007-12-04 10:34 UTC (permalink / raw)
  To: michael; +Cc: linuxppc-dev, Gala Kumar
In-Reply-To: <1196746689.20158.4.camel@concordia>

=20

> -----Original Message-----
> From: Michael Ellerman [mailto:michael@ellerman.id.au]=20
> Sent: 2007=C4=EA12=D4=C24=C8=D5 13:38
> To: Li Tony
> Cc: Li Tony; Gala Kumar; linuxppc-dev
> Subject: Re: [PATCH] Add IPIC MSI interrupt support
>=20
> On Mon, 2007-12-03 at 17:07 +0800, Li Li wrote:
> > Hi Michael,
> >=20
> > I emulate mpic to write this IPIC MSI routines. :)
> >=20
> >=20
> > > > diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c=20
> > > > b/arch/powerpc/platforms/83xx/mpc837x_mds.c
> > > > index 6048f1b..dbea34b 100644
> > > > --- a/arch/powerpc/platforms/83xx/mpc837x_mds.c
> > > > +++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
>=20
> > > > +
> > > > +#define	ipic_msi_irq_to_hw(virq)=09
> ((unsigned int)irq_map[virq].hwirq)
> > >=20
> > > What's wrong with virq_to_hw() ?
> > >=20
> >=20
> > viqr_to_hw is not __inline__.
>=20
> Hmm, ok. The three places you use it you also take a spin=20
> lock, so I'm not sure the function call's really going to=20
> kill you performance wise.
>=20

I am not very sure about spin_lock influence.
But maybe somebody will change the virq_to_hw implementation.
I will take virq_to_hw instead.=20

I see that the virq_to_hw is do inline in 2.6.22.
Why remove it?

> > > > +
> > > > +static void ipic_msi_compose_msg(struct ipic_msi *msi,=20
> int hwirq,
> > > > +						struct=20
> msi_msg *msg)
> > > > +{
> > > > +	unsigned int srs;
> > > > +	unsigned int ibs;
> > > > +
> > > > +	srs =3D hwirq / msi->int_per_msir;
> > > > +	ibs =3D hwirq - srs * msi->int_per_msir;
> > > > +
> > > > +	msg->address_lo =3D msi->msi_addr_lo;
> > > > +	msg->address_hi =3D msi->msi_addr_hi;
> > > > +	msg->data =3D (srs << 5) | (ibs & 0x1F);
> > > > +
> > > > +	pr_debug("%s: allocated srs: %d, ibs: %d\n",
> > > > +		__FUNCTION__, srs, ibs);
> > > > +
> > > > +}
> > > > +
> > > > +static int ipic_msi_setup_irqs(struct pci_dev *pdev, int nvec,=20
> > > > +int type) {
> > > > +	struct ipic_msi *msi =3D ipic_msi;
> > > > +	irq_hw_number_t hwirq;
> > > > +	unsigned int virq;
> > > > +	struct msi_desc *entry;
> > > > +	struct msi_msg msg;
> > > > +
> > > > +	list_for_each_entry(entry, &pdev->msi_list, list) {
> > > > +		hwirq =3D ipic_msi_alloc_hwirqs(msi, 1);
> > > > +		if (hwirq < 0) {
> > > > +			pr_debug("%s: fail allocating=20
> msi interrupt\n",
> > > > +					__FUNCTION__);
> > > > +			return hwirq;
> > > > +		}
> > > > +
> > > > +		/* This hwirq belongs to the irq_host=20
> other than irq_host of IPIC
> > > > + 		 * So, it is independent to hwirq of IPIC */
> > > > +		virq =3D irq_create_mapping(msi->irqhost, hwirq);
> > > > +		if (virq =3D=3D NO_IRQ) {
> > > > +			pr_debug("%s: fail mapping=20
> hwirq 0x%lx\n",
> > > > +					__FUNCTION__, hwirq);
> > > > +			ipic_msi_free_hwirqs(msi, hwirq, 1);
> > > > +			return -ENOSPC;
> > > > +		}
> > > > +		set_irq_msi(virq, entry);
> > > > +		ipic_msi_compose_msg(msi, hwirq, &msg);
> > > > +		write_msi_msg(virq, &msg);
> > > > +
> > > > +		hwirq++;
> > >=20
> > >                   ^^^^ this looks like my bug
> >=20
> > I have a question here. Do we support more MSI interrupts=20
> on ONE pci=20
> > device?
>=20
> I'm not sure what you mean? For MSI there is only one MSI per=20
> device, but this code is used also for MSI-X which supports >=20
> 1 MSI per device.
>=20
> Either way we shouldn't be incrementing hwirq by hand, it's=20
> reassigned at the top of the loop. I think that's left over=20
> from old code that allocated nvec hwirqs in a block and then=20
> created virq mappings for each one, whereas the new code=20
> allocates each hwirq separately.
>=20
> cheers
>=20
> --
> Michael Ellerman
> OzLabs, IBM Australia Development Lab
>=20
> wwweb: http://michael.ellerman.id.au
> phone: +61 2 6212 1183 (tie line 70 21183)
>=20
> We do not inherit the earth from our ancestors, we borrow it=20
> from our children. - S.M.A.R.T Person
>=20

^ permalink raw reply

* [PATCH 1/2] powerpc: Add MPC837xE MDS PCIE RC mode support
From: Li Li @ 2007-12-04 10:35 UTC (permalink / raw)
  To: Kumar Gala, kim phillips, linuxppc-dev

Modified based on discussion in list.

1.Change the device node to pcie
2.Add PPC_83XX_PCI_PRIMARY flag
3.Rearrange the codes

The PCIE controller is initiated in u-boot.

Signed-off-by: Tony Li <tony.li@freescale.com>
---
 arch/powerpc/boot/dts/mpc8377_mds.dts     |   54 ++++++++--
 arch/powerpc/boot/dts/mpc8378_mds.dts     |   54 ++++++++--
 arch/powerpc/platforms/83xx/Kconfig       |    7 +
 arch/powerpc/platforms/83xx/mpc8313_rdb.c |   10 ++-
 arch/powerpc/platforms/83xx/mpc832x_mds.c |   12 ++-
 arch/powerpc/platforms/83xx/mpc832x_rdb.c |   10 ++-
 arch/powerpc/platforms/83xx/mpc834x_itx.c |   10 ++-
 arch/powerpc/platforms/83xx/mpc834x_mds.c |   10 ++-
 arch/powerpc/platforms/83xx/mpc836x_mds.c |   12 ++-
 arch/powerpc/platforms/83xx/mpc837x_mds.c |   19 +++-
 arch/powerpc/platforms/83xx/mpc83xx.h     |    6 +-
 arch/powerpc/platforms/83xx/pci.c         |  174 +++++++++++++++++++++++++++--
 12 files changed, 338 insertions(+), 40 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc8377_mds.dts b/arch/powerpc/boot/dts/mpc8377_mds.dts
index 4402e39..8f54349 100644
--- a/arch/powerpc/boot/dts/mpc8377_mds.dts
+++ b/arch/powerpc/boot/dts/mpc8377_mds.dts
@@ -197,14 +197,6 @@
 			clock = <d#100>;
 		};
 
-		serdes2:serdes@e3100 {
-			compatible = "fsl,serdes";
-			reg = <e3100 100>;
-			vdd-1v;
-			protocol = "pcie";
-			clock = <d#100>;
-		};
-
 		/* IPIC
 		 * interrupts cell = <intr #, sense>
 		 * sense values match linux IORESOURCE_IRQ_* defines:
@@ -279,4 +271,50 @@
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};
+
+	pcie@e0009000 {
+		interrupt-map-mask = <f800 0 0 7>;
+		interrupt-map = <
+			0000 0 0 1 &ipic 1 8
+			0000 0 0 2 &ipic 1 8
+			0000 0 0 3 &ipic 1 8
+			0000 0 0 4 &ipic 1 8
+		>;
+		interrupt-parent = < &ipic >;
+		interrupts = <1 8>;
+		bus-range = <0 0>;
+		ranges = <02000000 0 A8000000 A8000000 0 10000000
+		          01000000 0 00000000 B8000000 0 00800000>;
+		clock-frequency = <0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <e0009000 00001000
+		       a0000000 08000000>;
+		compatible = "fsl,mpc8377-pcie";
+		device_type = "pci";
+	};
+
+	pcie@e000a000 {
+		interrupt-map-mask = <f800 0 0 7>;
+		interrupt-map = <
+			0000 0 0 1 &ipic 2 8
+			0000 0 0 2 &ipic 2 8
+			0000 0 0 3 &ipic 2 8
+			0000 0 0 4 &ipic 2 8
+		>;
+		interrupt-parent = < &ipic >;
+		interrupts = <2 8>;
+		bus-range = <0 0>;
+		ranges = <02000000 0 C8000000 C8000000 0 10000000
+			  01000000 0 00000000 D8000000 0 00800000>;
+		clock-frequency = <0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <e000a000 00001000
+		       c0000000 08000000>;
+		compatible = "fsl,mpc8377-pcie";
+		device_type = "pci";
+	};
 };
diff --git a/arch/powerpc/boot/dts/mpc8378_mds.dts b/arch/powerpc/boot/dts/mpc8378_mds.dts
index 54171f4..e09b0c5 100644
--- a/arch/powerpc/boot/dts/mpc8378_mds.dts
+++ b/arch/powerpc/boot/dts/mpc8378_mds.dts
@@ -179,14 +179,6 @@
 			clock = <d#100>;
 		};
 
-		serdes2:serdes@e3100 {
-			compatible = "fsl,serdes";
-			reg = <e3100 100>;
-			vdd-1v;
-			protocol = "pcie";
-			clock = <d#100>;
-		};
-
 		/* IPIC
 		 * interrupts cell = <intr #, sense>
 		 * sense values match linux IORESOURCE_IRQ_* defines:
@@ -261,4 +253,50 @@
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};
+
+	pcie@e0009000 {
+		interrupt-map-mask = <f800 0 0 7>;
+		interrupt-map = <
+			0000 0 0 1 &ipic 1 8
+			0000 0 0 2 &ipic 1 8
+			0000 0 0 3 &ipic 1 8
+			0000 0 0 4 &ipic 1 8
+		>;
+		interrupt-parent = < &ipic >;
+		interrupts = <1 8>;
+		bus-range = <0 0>;
+		ranges = <02000000 0 A8000000 A8000000 0 10000000
+		          01000000 0 00000000 B8000000 0 00800000>;
+		clock-frequency = <0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <e0009000 00001000
+		       a0000000 08000000>;
+		compatible = "fsl,mpc8377-pcie";
+		device_type = "pci";
+	};
+
+	pcie@e000a000 {
+		interrupt-map-mask = <f800 0 0 7>;
+		interrupt-map = <
+			0000 0 0 1 &ipic 2 8
+			0000 0 0 2 &ipic 2 8
+			0000 0 0 3 &ipic 2 8
+			0000 0 0 4 &ipic 2 8
+		>;
+		interrupt-parent = < &ipic >;
+		interrupts = <2 8>;
+		bus-range = <0 0>;
+		ranges = <02000000 0 C8000000 C8000000 0 10000000
+			  01000000 0 00000000 D8000000 0 00800000>;
+		clock-frequency = <0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <e000a000 00001000
+		       c0000000 08000000>;
+		compatible = "fsl,mpc8377-pcie";
+		device_type = "pci";
+	};
 };
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 0c61e7a..00154c5 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -87,3 +87,10 @@ config PPC_MPC837x
 	select PPC_INDIRECT_PCI
 	select FSL_SERDES
 	default y if MPC837x_MDS
+
+config PPC_MPC83XX_PCIE
+	bool "MPC837X PCI Express support"
+	depends on PCIEPORTBUS && PPC_MPC837x
+	default n
+	help
+	  Enables MPC837x PCI express RC mode
diff --git a/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
index 33766b8..25d8df4 100644
--- a/arch/powerpc/platforms/83xx/mpc8313_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
@@ -37,14 +37,20 @@ static void __init mpc8313_rdb_setup_arch(void)
 {
 #ifdef CONFIG_PCI
 	struct device_node *np;
+	int primary_pci_bus = 1;
 #endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc8313_rdb_setup_arch()", 0);
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
-		mpc83xx_add_bridge(np);
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+		if (primary_pci_bus) {
+			mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+			primary_pci_bus = 0;
+		} else
+			mpc83xx_add_bridge(np, PPC_83XX_PCI);
+	}
 #endif
 	mpc831x_usb_cfg();
 }
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index 972fa85..ddb0b2e 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -58,6 +58,9 @@ static u8 *bcsr_regs = NULL;
 static void __init mpc832x_sys_setup_arch(void)
 {
 	struct device_node *np;
+#ifdef CONFIG_PCI
+	int primary_pci_bus = 1;
+#endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc832x_sys_setup_arch()", 0);
@@ -73,8 +76,13 @@ static void __init mpc832x_sys_setup_arch(void)
 	}
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
-		mpc83xx_add_bridge(np);
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+		if (primary_pci_bus) {
+			mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+			primary_pci_bus = 0;
+		} else
+			mpc83xx_add_bridge(np, PPC_83XX_PCI);
+	}
 #endif
 
 #ifdef CONFIG_QUICC_ENGINE
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
index fbca336..aef35f5 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -87,14 +87,20 @@ static void __init mpc832x_rdb_setup_arch(void)
 {
 #if defined(CONFIG_PCI) || defined(CONFIG_QUICC_ENGINE)
 	struct device_node *np;
+	int primary_pci_bus = 1;
 #endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc832x_rdb_setup_arch()", 0);
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
-		mpc83xx_add_bridge(np);
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+		if (primary_pci_bus) {
+			mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+			primary_pci_bus = 0;
+		} else
+			mpc83xx_add_bridge(np, PPC_83XX_PCI);
+	}
 #endif
 
 #ifdef CONFIG_QUICC_ENGINE
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index aa76819..c428f62 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -46,14 +46,20 @@ static void __init mpc834x_itx_setup_arch(void)
 {
 #ifdef CONFIG_PCI
 	struct device_node *np;
+	int primary_pci_bus = 1;
 #endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc834x_itx_setup_arch()", 0);
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
-		mpc83xx_add_bridge(np);
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+		if (primary_pci_bus) {
+			mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+			primary_pci_bus = 0;
+		} else
+			mpc83xx_add_bridge(np, PPC_83XX_PCI);
+	}
 #endif
 
 	mpc834x_usb_cfg();
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index 00aed7c..e86dce8 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -77,14 +77,20 @@ static void __init mpc834x_mds_setup_arch(void)
 {
 #ifdef CONFIG_PCI
 	struct device_node *np;
+	int primary_pci_bus = 1;
 #endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc834x_mds_setup_arch()", 0);
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
-		mpc83xx_add_bridge(np);
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+		if (primary_pci_bus) {
+			mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+			primary_pci_bus = 0;
+		} else
+			mpc83xx_add_bridge(np, PPC_83XX_PCI);
+	}
 #endif
 
 	mpc834xemds_usb_cfg();
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index 0f3855c..6e6670c 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -64,6 +64,9 @@ static u8 *bcsr_regs = NULL;
 static void __init mpc836x_mds_setup_arch(void)
 {
 	struct device_node *np;
+#ifdef CONFIG_PCI
+	int primary_pci_bus = 1;
+#endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc836x_mds_setup_arch()", 0);
@@ -79,8 +82,13 @@ static void __init mpc836x_mds_setup_arch(void)
 	}
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
-		mpc83xx_add_bridge(np);
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+		if (primary_pci_bus) {
+			mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+			primary_pci_bus = 0;
+		} else
+			mpc83xx_add_bridge(np, PPC_83XX_PCI);
+	}
 #endif
 
 #ifdef CONFIG_QUICC_ENGINE
diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c
index 166c111..b1d3570 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
@@ -36,14 +36,29 @@ static void __init mpc837x_mds_setup_arch(void)
 {
 #ifdef CONFIG_PCI
 	struct device_node *np;
+	int primary_pci_bus = 1;
 #endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc837x_mds_setup_arch()", 0);
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
-		mpc83xx_add_bridge(np);
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+		if (primary_pci_bus) {
+			mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+			primary_pci_bus = 0;
+		} else
+			mpc83xx_add_bridge(np, PPC_83XX_PCI);
+	}
+#endif
+#ifdef CONFIG_PPC_MPC83XX_PCIE
+	for_each_compatible_node(np, "pci", "fsl,mpc8377-pcie") {
+		if (primary_pci_bus) {
+			mpc83xx_add_bridge(np, PPC_83XX_PCIE | PPC_83XX_PCI_PRIMARY);
+			primary_pci_bus = 0;
+		} else
+			mpc83xx_add_bridge(np, PPC_83XX_PCIE);
+	}
 #endif
 }
 
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
index b778cb4..552e9bf 100644
--- a/arch/powerpc/platforms/83xx/mpc83xx.h
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -47,8 +47,10 @@
  * Declaration for the various functions exported by the
  * mpc83xx_* files. Mostly for use by mpc83xx_setup
  */
-
-extern int mpc83xx_add_bridge(struct device_node *dev);
+#define PPC_83XX_PCI_PRIMARY	0x1
+#define PPC_83XX_PCI		0x2
+#define PPC_83XX_PCIE		0x4
+extern int mpc83xx_add_bridge(struct device_node *dev, int flags);
 extern void mpc83xx_restart(char *cmd);
 extern long mpc83xx_time_init(void);
 extern int mpc834x_usb_cfg(void);
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
index 80425d7..9004140 100644
--- a/arch/powerpc/platforms/83xx/pci.c
+++ b/arch/powerpc/platforms/83xx/pci.c
@@ -25,6 +25,8 @@
 #include <asm/prom.h>
 #include <sysdev/fsl_soc.h>
 
+#include "mpc83xx.h"
+
 #undef DEBUG
 
 #ifdef DEBUG
@@ -33,13 +35,159 @@
 #define DBG(x...)
 #endif
 
-int __init mpc83xx_add_bridge(struct device_node *dev)
+#if defined(CONFIG_PPC_MPC83XX_PCIE)
+
+/* PCIE Registers */
+#define PEX_LTSSM_STAT		0x404
+#define PEX_LTSSM_STAT_L0	0x16
+#define PEX_GCLK_RATIO		0x440
+
+/* PCIE config space Read/Write routines */
+static int direct_read_config_pcie(struct pci_bus *bus,
+			uint devfn, int offset, int len, u32 *val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	void __iomem *cfg_addr;
+	u32 bus_no;
+
+	if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (ppc_md.pci_exclude_device)
+		if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+	switch (len) {
+	case 2:
+		if (offset & 1)
+			return -EINVAL;
+		break;
+	case 4:
+	if (offset & 3)
+		return -EINVAL;
+		break;
+	}
+
+	pr_debug("_read_cfg_pcie: bus=%d devfn=%x off=%x len=%x\n",
+		bus->number, devfn, offset, len);
+
+	if (bus->number == hose->first_busno) {
+		/*
+		 * The PCIE can only link one device.
+		 * It`s device number must be 0
+		 */
+		if (devfn & 0xf8)
+			return PCIBIOS_DEVICE_NOT_FOUND;
+		bus_no = hose->self_busno;
+	} else
+		bus_no = bus->number;
+
+	cfg_addr = (void __iomem *)((ulong) hose->cfg_addr +
+		((bus_no << 20) | (devfn << 12) | (offset & 0xfff)));
+
+	switch (len) {
+	case 1:
+		*val = in_8(cfg_addr);
+		break;
+	case 2:
+		*val = in_le16(cfg_addr);
+		break;
+	default:
+		*val = in_le32(cfg_addr);
+		break;
+	}
+	pr_debug("_read_cfg_pcie: val=%x cfg_addr=%p\n", *val, cfg_addr);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int direct_write_config_pcie(struct pci_bus *bus,
+			uint devfn, int offset, int len, u32 val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	void __iomem *cfg_addr;
+	u32 bus_no;
+
+	if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (ppc_md.pci_exclude_device)
+		if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+	switch (len) {
+	case 2:
+		if (offset & 1)
+			return -EINVAL;
+		break;
+	case 4:
+		if (offset & 3)
+			return -EINVAL;
+		break;
+	}
+
+	if (bus->number == hose->first_busno) {
+		/*
+		 * The PCIE can only link one device.
+		 * It`s device number must be 0
+		 */
+		if (devfn & 0xf8)
+			return PCIBIOS_DEVICE_NOT_FOUND;
+		bus_no = hose->self_busno;
+	} else
+		bus_no = bus->number;
+
+	cfg_addr = (void __iomem *)((ulong) hose->cfg_addr +
+		((bus_no << 20) | (devfn << 12) | (offset & 0xfff)));
+
+	switch (len) {
+	case 1:
+		out_8(cfg_addr, val);
+		break;
+	case 2:
+		out_le16(cfg_addr, val);
+		break;
+	default:
+		out_le32(cfg_addr, val);
+		break;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops direct_pcie_ops = {
+	direct_read_config_pcie,
+	direct_write_config_pcie
+};
+
+static void __init mpc83xx_setup_pcie(struct pci_controller *hose,
+			struct resource *reg, struct resource *cfg_space)
+{
+	void __iomem *hose_cfg_base, *mbase;
+	u32 val;
+
+	hose_cfg_base = ioremap(reg->start, reg->end - reg->start + 1);
+
+	val = in_le32(hose_cfg_base + PEX_LTSSM_STAT);
+	if (val < PEX_LTSSM_STAT_L0)
+		hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+
+	mbase = ioremap(cfg_space->start & PAGE_MASK, cfg_space->end - cfg_space->start + 1);
+	hose->cfg_addr = mbase + (cfg_space->start & ~PAGE_MASK);
+	hose->ops = &direct_pcie_ops;
+}
+#endif /* CONFIG_PPC_MPC83XX_PCIE */
+
+int __init mpc83xx_add_bridge(struct device_node *dev, int flags)
 {
 	int len;
 	struct pci_controller *hose;
 	struct resource rsrc;
+#if defined(CONFIG_PPC_MPC83XX_PCIE)
+	struct resource cfg_space;
+#endif
 	const int *bus_range;
-	int primary = 1, has_address = 0;
+	int has_address = 0;
 	phys_addr_t immr = get_immrbase();
 
 	DBG("Adding PCI host bridge %s\n", dev->full_name);
@@ -63,17 +211,24 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
 	/* MPC83xx supports up to two host controllers one at 0x8500 from immrbar
-	 * the other at 0x8600, we consider the 0x8500 the primary controller
+	 * the other at 0x8600.
 	 */
 	/* PCI 1 */
-	if ((rsrc.start & 0xfffff) == 0x8500) {
+	if ((rsrc.start & 0xfffff) == 0x8500)
 		setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304, 0);
-	}
 	/* PCI 2 */
-	if ((rsrc.start & 0xfffff) == 0x8600) {
+	if ((rsrc.start & 0xfffff) == 0x8600)
 		setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384, 0);
-		primary = 0;
+
+#if defined(CONFIG_PPC_MPC83XX_PCIE)
+	if (flags & PPC_83XX_PCIE) {
+		if (of_address_to_resource(dev, 1, &cfg_space)) {
+			printk("PCIE RC losts configure space. Skip it\n");
+			return 1;
+		}
+		mpc83xx_setup_pcie(hose, &rsrc, &cfg_space);
 	}
+#endif
 
 	printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. "
 	       "Firmware bus number: %d->%d\n",
@@ -85,7 +240,10 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
 
 	/* Interpret the "ranges" property */
 	/* This also maps the I/O region and sets isa_io/mem_base */
-	pci_process_bridge_OF_ranges(hose, dev, primary);
+	if (flags & PPC_83XX_PCI_PRIMARY)
+		pci_process_bridge_OF_ranges(hose, dev, 1);
+	else
+		pci_process_bridge_OF_ranges(hose, dev, 0);
 
 	return 0;
 }
-- 
1.5.2

^ permalink raw reply related


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