[PATCH 2/2] Base pSeries PCIe support
Jake Moilanen
moilanen at austin.ibm.com
Sun Apr 2 08:57:23 EST 2006
On Sat, 1 Apr 2006 19:36:07 +1100
Paul Mackerras <paulus at samba.org> wrote:
> Jake Moilanen writes:
>
> > The NR_IRQS got bumped up to 1024, as vectors can go much higher.
> > Unfortunately, this number was arbitrarily picked as there is no claim
> > at what the max number really is by either the firmware team, or the
> > PAPR+.
>
> What matters is the number of different vectors, not the actual value
> of the vectors, because we remap interrupt numbers that the firmware
> gives us to logical Linux irq numbers between 0 and NR_IRQS-1. We had
> to do that when the POWER5 systems came out, because the interrupt
> numbers there occupy 24 bits.
Ah. That sounds right. I haven't had a chance to test this version of
the patch. Firmware is currently broken on my machine.
Here's try #2
I ended up putting #ifdef CONFIG_PPC_RTAS around this, as non-rtas
kernels won't like all the rtas calls.
Signed-off-by: Jake Moilanen <moilanen at austin.ibm.com>
---
Index: 2.6.16/arch/powerpc/kernel/prom.c
===================================================================
--- 2.6.16.orig/arch/powerpc/kernel/prom.c 2006-04-01 16:34:45.000000000 -0600
+++ 2.6.16/arch/powerpc/kernel/prom.c 2006-04-01 16:52:53.000000000 -0600
@@ -88,6 +88,8 @@
struct device_node *dflt_interrupt_controller;
int num_interrupt_controllers;
+void __init finish_node_msi(struct device_node *dn, unsigned long *mem_start, int measure_only);
+
/*
* Wrapper for allocating memory for various data that needs to be
* attached to device nodes as they are processed at boot or when
@@ -295,6 +297,7 @@
{
unsigned int *ints;
int intlen, intrcells, intrcount;
+ int dummy;
int i, j, n, sense;
unsigned int *irq, virq;
struct device_node *ic;
@@ -341,6 +344,13 @@
return 0;
}
+#ifdef CONFIG_PPC_RTAS
+ if(of_find_property(np, "ibm,req#msi", &dummy)) {
+ finish_node_msi(np, mem_start, measure_only);
+ return 0;
+ }
+#endif
+
ints = (unsigned int *) get_property(np, "interrupts", &intlen);
TRACE("ints=%p, intlen=%d\n", ints, intlen);
if (ints == NULL)
@@ -503,6 +513,82 @@
DBG(" <- finish_device_tree\n");
}
+#ifdef CONFIG_PPC_RTAS
+void __devinit finish_node_msi(struct device_node *dn, unsigned long *mem_start, int measure_only)
+{
+ static int seq_num = 1;
+ int i;
+ int rc;
+ int query_token = rtas_token("ibm,query-interrupt-source-number");
+ int devfn;
+ int busno;
+ u32 *reg;
+ int reglen;
+ int ret[3];
+ unsigned int virq;
+ unsigned int addr;
+ unsigned long buid = -1;
+ unsigned long wait_time;
+
+ reg = (u32 *) get_property(dn, "reg", ®len);
+ if (reg == NULL || reglen < 20)
+ return;
+
+ devfn = (reg[0] >> 8) & 0xff;
+ busno = (reg[0] >> 16) & 0xff;
+
+ buid = get_phb_buid(dn->parent);
+ addr = (busno << 16) | (devfn << 8);
+
+ while (1) {
+ rc = rtas_call(rtas_token("ibm,change-msi"), 6, 3, ret, addr,
+ buid >> 32, buid & 0xffffffff,
+ 1, 1, seq_num);
+
+ if (!rc)
+ break;
+ else if (rc == RTAS_BUSY)
+ udelay(1);
+ else if (rtas_is_extended_busy(rc)) {
+ wait_time = rtas_extended_busy_delay_time(rc);
+ udelay(wait_time * 1000);
+ } else {
+ printk(KERN_WARNING "error[%d]: getting the number of"
+ "MSI interrupts for %s\n", rc, dn->name);
+ return;
+ }
+
+ seq_num = ret[1];
+ }
+
+ dn->n_intrs = ret[0];
+
+ dn->intrs = prom_alloc(dn->n_intrs * sizeof(*(dn->intrs)), mem_start);
+ if (!dn->intrs) {
+ printk(KERN_WARNING "finish_node_msi: can't allocate space\n");
+ return;
+ }
+
+ if (measure_only)
+ return;
+
+ for (i = 0; i < dn->n_intrs; i++) {
+ rc = rtas_call(query_token, 4, 3, ret, addr, buid >> 32, buid & 0xffffffff, i);
+
+ if (!rc) {
+ virq = virt_irq_create_mapping(ret[0]);
+
+ dn->intrs[i].line = irq_offset_up(virq);
+ dn->intrs[i].sense = ret[1];
+ } else {
+ printk(KERN_WARNING "error[%d]: query-interrupt-source-number for %s\n",
+ rc, dn->name);
+ }
+ }
+
+}
+#endif /* #ifdef CONFIG_PPC_RTAS */
+
static inline char *find_flat_dt_string(u32 offset)
{
return ((char *)initial_boot_params) +
Index: 2.6.16/include/asm-powerpc/pci-bridge.h
===================================================================
--- 2.6.16.orig/include/asm-powerpc/pci-bridge.h 2006-04-01 16:34:45.000000000 -0600
+++ 2.6.16/include/asm-powerpc/pci-bridge.h 2006-04-01 16:52:38.000000000 -0600
@@ -141,6 +141,7 @@
void pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus);
extern int pcibios_remove_root_bus(struct pci_controller *phb);
+extern unsigned long __devinit get_phb_buid (struct device_node *phb);
static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
{
More information about the Linuxppc-dev
mailing list