* [PATCH 0/3] PPC64 PCIe support
@ 2006-06-07 21:02 Jake Moilanen
2006-06-07 21:05 ` [PATCH 1/3] PCIe device_type pciex Jake Moilanen
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Jake Moilanen @ 2006-06-07 21:02 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Paul Mackerras
Here are the three patches for PCIe/MSI on pSeries for 2.6.18.
Since MSI is a requirement for PCIe, I have put these in one batch.
This is enough to probe, find, configure, and run basic I/O to PCIe
enabled devices. However, these patches do not include support for
PCIe hotplug, nor multiple MSI vectors.
There is a supplemental patches which will be needed in the
future. Specifically adding a PCIe bit for
ibm,client-architecture-support. To my knowledge this bit has not been
defined yet.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/3] PCIe device_type pciex
2006-06-07 21:02 [PATCH 0/3] PPC64 PCIe support Jake Moilanen
@ 2006-06-07 21:05 ` Jake Moilanen
2006-06-07 21:15 ` [PATCH 2/3] MSI power abstraction Jake Moilanen
2006-06-07 21:25 ` [PATCH 3/3] RTAS MSI Jake Moilanen
2 siblings, 0 replies; 6+ messages in thread
From: Jake Moilanen @ 2006-06-07 21:05 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
This adds support to recognize the PCIe device_type "pciex" and made
the portdrv buildable.
Signed-off-by: Jake Moilanen <moilanen@austin.ibm.com>
Index: 2.6/arch/powerpc/Kconfig
===================================================================
--- 2.6.orig/arch/powerpc/Kconfig 2006-05-31 15:33:57.000000000 -0500
+++ 2.6/arch/powerpc/Kconfig 2006-05-31 15:34:10.000000000 -0500
@@ -849,6 +849,8 @@
endchoice
+source "drivers/pci/pcie/Kconfig"
+
source "drivers/pci/Kconfig"
source "drivers/pcmcia/Kconfig"
Index: 2.6/arch/powerpc/kernel/pci_64.c
===================================================================
--- 2.6.orig/arch/powerpc/kernel/pci_64.c 2006-05-31 15:33:57.000000000 -0500
+++ 2.6/arch/powerpc/kernel/pci_64.c 2006-05-31 15:34:10.000000000 -0500
@@ -396,7 +396,7 @@
dev->current_state = 4; /* unknown power state */
- if (!strcmp(type, "pci")) {
+ if (!strcmp(type, "pci") || !strcmp(type, "pciex")) {
/* a PCI-PCI bridge */
dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
dev->rom_base_reg = PCI_ROM_ADDRESS1;
Index: 2.6/arch/powerpc/kernel/rtas_pci.c
===================================================================
--- 2.6.orig/arch/powerpc/kernel/rtas_pci.c 2006-05-31 15:33:57.000000000 -0500
+++ 2.6/arch/powerpc/kernel/rtas_pci.c 2006-05-31 15:34:10.000000000 -0500
@@ -313,7 +313,9 @@
for (node = of_get_next_child(root, NULL);
node != NULL;
node = of_get_next_child(root, node)) {
- if (node->type == NULL || strcmp(node->type, "pci") != 0)
+
+ if (node->type == NULL || (strcmp(node->type, "pci") != 0 &&
+ strcmp(node->type, "pciex") != 0))
continue;
phb = pcibios_alloc_controller(node);
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/3] MSI power abstraction
2006-06-07 21:02 [PATCH 0/3] PPC64 PCIe support Jake Moilanen
2006-06-07 21:05 ` [PATCH 1/3] PCIe device_type pciex Jake Moilanen
@ 2006-06-07 21:15 ` Jake Moilanen
2006-06-07 21:25 ` [PATCH 3/3] RTAS MSI Jake Moilanen
2 siblings, 0 replies; 6+ messages in thread
From: Jake Moilanen @ 2006-06-07 21:15 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
Instead of trying to make PPC64 MSI fit in a Intel-centric MSI layer, a
simple short-term solution is to hook the pci_{en/dis}able_msi() calls
and make a machdep call.
The rest of the MSI functions are superfluous for what is needed at this
time. Many of which can have machdep calls added as needed.
Ben and Michael Ellerman are looking into rewrite the MSI layer to be
more generic. However, in the meantime this works as a interim
solution.
Signed-off-by: Jake Moilanen <moilanen@austin.ibm.com>
Index: 2.6/arch/powerpc/kernel/irq.c
===================================================================
--- 2.6.orig/arch/powerpc/kernel/irq.c 2006-06-07 15:23:41.000000000 -0500
+++ 2.6/arch/powerpc/kernel/irq.c 2006-06-07 15:29:32.000000000 -0500
@@ -47,6 +47,7 @@
#include <linux/cpumask.h>
#include <linux/profile.h>
#include <linux/bitops.h>
+#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -436,6 +437,30 @@
}
EXPORT_SYMBOL(do_softirq);
+#ifdef CONFIG_PCI_MSI
+int pci_enable_msi(struct pci_dev * pdev)
+{
+ if (ppc_md.enable_msi)
+ return ppc_md.enable_msi(pdev);
+ else
+ return -1;
+}
+
+void pci_disable_msi(struct pci_dev * pdev)
+{
+ if (ppc_md.disable_msi)
+ ppc_md.disable_msi(pdev);
+}
+
+void pci_scan_msi_device(struct pci_dev *dev) {}
+int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) {return -1;}
+void pci_disable_msix(struct pci_dev *dev) {}
+void msi_remove_pci_irq_vectors(struct pci_dev *dev) {}
+void disable_msi_mode(struct pci_dev *dev, int pos, int type) {}
+void pci_no_msi(void) {}
+
+#endif
+
#ifdef CONFIG_PPC64
static int __init setup_noirqdistrib(char *str)
{
Index: 2.6/include/asm-powerpc/machdep.h
===================================================================
--- 2.6.orig/include/asm-powerpc/machdep.h 2006-06-07 15:23:41.000000000 -0500
+++ 2.6/include/asm-powerpc/machdep.h 2006-06-07 15:24:48.000000000 -0500
@@ -238,6 +238,11 @@
*/
void (*machine_kexec)(struct kimage *image);
#endif /* CONFIG_KEXEC */
+
+#ifdef CONFIG_PCI_MSI
+ int (*enable_msi)(struct pci_dev *pdev);
+ void (*disable_msi)(struct pci_dev *pdev);
+#endif /* CONFIG_PCI_MSI */
};
extern void power4_idle(void);
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 3/3] RTAS MSI
2006-06-07 21:02 [PATCH 0/3] PPC64 PCIe support Jake Moilanen
2006-06-07 21:05 ` [PATCH 1/3] PCIe device_type pciex Jake Moilanen
2006-06-07 21:15 ` [PATCH 2/3] MSI power abstraction Jake Moilanen
@ 2006-06-07 21:25 ` Jake Moilanen
2006-06-07 22:58 ` Nathan Lynch
2 siblings, 1 reply; 6+ messages in thread
From: Jake Moilanen @ 2006-06-07 21:25 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
This provides support for the pSeries RTAS interfaces for MSI.
It follows the altix conventions, and is based on top of the altix patch.
Signed-off-by: Jake Moilanen <moilanen@austin.ibm.com>
Index: 2.6/drivers/pci/Makefile
===================================================================
--- 2.6.orig/drivers/pci/Makefile 2006-06-07 15:29:55.000000000 -0500
+++ 2.6/drivers/pci/Makefile 2006-06-07 15:59:28.000000000 -0500
@@ -26,7 +26,14 @@
obj-$(CONFIG_PPC64) += setup-bus.o
obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
obj-$(CONFIG_X86_VISWS) += setup-irq.o
-obj-$(CONFIG_PCI_MSI) += msi.o
+
+msiobj-$(CONFIG_X86) += msi.o msi-apic.o msi-intel.o
+msiobj-$(CONFIG_IA64) += msi.o msi-apic.o msi-intel.o
+msiobj-$(CONFIG_IA64_GENERIC) += msi.o msi-altix.o
+msiobj-$(CONFIG_IA64_SGI_SN2) += msi.o msi-altix.o
+msiobj-$(CONFIG_PPC_PSERIES) += msi-rtas.o
+
+obj-$(CONFIG_PCI_MSI) += $(msiobj-y)
#
# ACPI Related PCI FW Functions
Index: 2.6/drivers/pci/msi-rtas.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ 2.6/drivers/pci/msi-rtas.c 2006-06-07 15:59:59.000000000 -0500
@@ -0,0 +1,162 @@
+/*
+ * Jake Moilanen <moilanen@austin.ibm.com>
+ * Copyright (C) 2006 IBM
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <asm/rtas.h>
+#include <asm/hw_irq.h>
+
+int rtas_enable_msi(struct pci_dev* pdev)
+{
+ 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];
+ int dummy;
+ unsigned int virq;
+ unsigned int addr;
+ unsigned long buid = -1;
+ unsigned long wait_time;
+ struct device_node * dn;
+
+ BUG_ON(!pdev);
+
+ dn = pci_device_to_OF_node(pdev);
+
+ if (!of_find_property(dn, "ibm,req#msi", &dummy))
+ return -ENOENT;
+
+ reg = (u32 *) get_property(dn, "reg", ®len);
+ if (reg == NULL || reglen < 20)
+ return -ENXIO;
+
+ 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,
+ 0, 0, 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 -EIO;
+ }
+
+ seq_num = ret[1];
+ }
+
+ /* Return if there's no MSI interrupts */
+ if (!ret[0])
+ return -ENOENT;
+
+ dn->n_intrs = ret[0];
+
+ dn->intrs = kmalloc(dn->n_intrs * sizeof(*(dn->intrs)), GFP_KERNEL);
+ if (!dn->intrs) {
+ printk(KERN_WARNING "rtas_enable_msi: can't allocate space\n");
+ return -ENOMEM;
+ }
+
+ 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);
+ }
+ }
+
+ /* Just give the first vector out for now */
+ pdev->irq = dn->intrs[0].line;
+
+ return 0;
+}
+
+void rtas_disable_msi(struct pci_dev* pdev)
+{
+ static int seq_num = 1;
+ struct device_node * dn;
+ int rc;
+ int devfn;
+ int busno;
+ u32 *reg;
+ int reglen;
+ int ret[3];
+ int dummy;
+ unsigned int addr;
+ unsigned long buid = -1;
+ unsigned long wait_time;
+
+ BUG_ON(!pdev);
+
+ dn = pci_device_to_OF_node(pdev);
+
+ if (!of_find_property(dn, "ibm,req#msi", &dummy))
+ return;
+
+ 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,
+ 2, 0, 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]: setting the number of "
+ "MSI interrupts for %s\n", rc, dn->name);
+ return;
+ }
+
+ seq_num = ret[1];
+ }
+
+ dn->n_intrs = 0;
+
+ kfree(dn->intrs);
+}
Index: 2.6/drivers/pci/Kconfig
===================================================================
--- 2.6.orig/drivers/pci/Kconfig 2006-06-07 15:29:55.000000000 -0500
+++ 2.6/drivers/pci/Kconfig 2006-06-07 15:59:28.000000000 -0500
@@ -4,7 +4,7 @@
config PCI_MSI
bool "Message Signaled Interrupts (MSI and MSI-X)"
depends on PCI
- depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64
+ depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64 || PPC_PSERIES
help
This allows device drivers to enable MSI (Message Signaled
Interrupts). Message Signaled Interrupts enable a device to
Index: 2.6/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- 2.6.orig/arch/powerpc/platforms/pseries/setup.c 2006-06-07 15:29:55.000000000 -0500
+++ 2.6/arch/powerpc/platforms/pseries/setup.c 2006-06-07 15:59:28.000000000 -0500
@@ -78,6 +78,8 @@
#endif
extern void find_udbg_vterm(void);
+extern int rtas_enable_msi(struct pci_dev* pdev);
+extern void rtas_disable_msi(struct pci_dev * pdev);
int fwnmi_active; /* TRUE if an FWNMI handler is present */
@@ -205,6 +207,10 @@
} else {
ppc_md.init_IRQ = xics_init_IRQ;
ppc_md.get_irq = xics_get_irq;
+#ifdef CONFIG_PCI_MSI
+ ppc_md.enable_msi = rtas_enable_msi;
+ ppc_md.disable_msi = rtas_disable_msi;
+#endif
}
#ifdef CONFIG_SMP
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 3/3] RTAS MSI
2006-06-07 21:25 ` [PATCH 3/3] RTAS MSI Jake Moilanen
@ 2006-06-07 22:58 ` Nathan Lynch
2006-06-08 16:13 ` Jake Moilanen
0 siblings, 1 reply; 6+ messages in thread
From: Nathan Lynch @ 2006-06-07 22:58 UTC (permalink / raw)
To: Jake Moilanen; +Cc: linuxppc-dev, paulus
Hi Jake, some comments below:
Jake Moilanen wrote:
> Index: 2.6/drivers/pci/msi-rtas.c
> ===================================================================
> --- /dev/null 1970-01-01 00:00:00.000000000 +0000
> +++ 2.6/drivers/pci/msi-rtas.c 2006-06-07 15:59:59.000000000 -0500
> @@ -0,0 +1,162 @@
> +/*
> + * Jake Moilanen <moilanen@austin.ibm.com>
> + * Copyright (C) 2006 IBM
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; version 2 of the
> + * License.
> + *
> + */
> +
> +#include <linux/pci.h>
> +#include <linux/irq.h>
> +#include <asm/rtas.h>
> +#include <asm/hw_irq.h>
> +
> +int rtas_enable_msi(struct pci_dev* pdev)
> +{
> + 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];
> + int dummy;
> + unsigned int virq;
> + unsigned int addr;
> + unsigned long buid = -1;
> + unsigned long wait_time;
> + struct device_node * dn;
> +
> + BUG_ON(!pdev);
> +
> + dn = pci_device_to_OF_node(pdev);
> +
> + if (!of_find_property(dn, "ibm,req#msi", &dummy))
> + return -ENOENT;
> +
> + reg = (u32 *) get_property(dn, "reg", ®len);
> + if (reg == NULL || reglen < 20)
> + return -ENXIO;
> +
> + 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,
> + 0, 0, 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 -EIO;
> + }
> +
> + seq_num = ret[1];
> + }
Please see John Rose's patch from a few days ago for handling RTAS
delays with msleep instead of udelay. As written, this loop could tie
up the cpu for an arbitrary amount of time, and it is this kind of
situation John's patch is intended to address.
> +
> + /* Return if there's no MSI interrupts */
> + if (!ret[0])
> + return -ENOENT;
> +
> + dn->n_intrs = ret[0];
> +
> + dn->intrs = kmalloc(dn->n_intrs * sizeof(*(dn->intrs)), GFP_KERNEL);
> + if (!dn->intrs) {
> + printk(KERN_WARNING "rtas_enable_msi: can't allocate space\n");
> + return -ENOMEM;
> + }
> +
> + 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);
> + }
> + }
> +
> + /* Just give the first vector out for now */
> + pdev->irq = dn->intrs[0].line;
> +
> + return 0;
> +}
> +
> +void rtas_disable_msi(struct pci_dev* pdev)
> +{
> + static int seq_num = 1;
> + struct device_node * dn;
> + int rc;
> + int devfn;
> + int busno;
> + u32 *reg;
> + int reglen;
> + int ret[3];
> + int dummy;
> + unsigned int addr;
> + unsigned long buid = -1;
> + unsigned long wait_time;
> +
> + BUG_ON(!pdev);
> +
> + dn = pci_device_to_OF_node(pdev);
> +
> + if (!of_find_property(dn, "ibm,req#msi", &dummy))
> + return;
> +
> + 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,
> + 2, 0, 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]: setting the number of "
> + "MSI interrupts for %s\n", rc, dn->name);
> + return;
> + }
> +
> + seq_num = ret[1];
> + }
Same as above applies here.
> +
> + dn->n_intrs = 0;
> +
> + kfree(dn->intrs);
> +}
> Index: 2.6/drivers/pci/Kconfig
> ===================================================================
> --- 2.6.orig/drivers/pci/Kconfig 2006-06-07 15:29:55.000000000 -0500
> +++ 2.6/drivers/pci/Kconfig 2006-06-07 15:59:28.000000000 -0500
> @@ -4,7 +4,7 @@
> config PCI_MSI
> bool "Message Signaled Interrupts (MSI and MSI-X)"
> depends on PCI
> - depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64
> + depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64 || PPC_PSERIES
> help
> This allows device drivers to enable MSI (Message Signaled
> Interrupts). Message Signaled Interrupts enable a device to
> Index: 2.6/arch/powerpc/platforms/pseries/setup.c
> ===================================================================
> --- 2.6.orig/arch/powerpc/platforms/pseries/setup.c 2006-06-07 15:29:55.000000000 -0500
> +++ 2.6/arch/powerpc/platforms/pseries/setup.c 2006-06-07 15:59:28.000000000 -0500
> @@ -78,6 +78,8 @@
> #endif
>
> extern void find_udbg_vterm(void);
> +extern int rtas_enable_msi(struct pci_dev* pdev);
> +extern void rtas_disable_msi(struct pci_dev * pdev);
These belong in a header.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 3/3] RTAS MSI
2006-06-07 22:58 ` Nathan Lynch
@ 2006-06-08 16:13 ` Jake Moilanen
0 siblings, 0 replies; 6+ messages in thread
From: Jake Moilanen @ 2006-06-08 16:13 UTC (permalink / raw)
To: Nathan Lynch; +Cc: linuxppc-dev, paulus
Here's a version addressing Nathan's concerns.
Signed-off-by: Jake Moilanen <moilanen@austin.ibm.com>
Index: 2.6/drivers/pci/Makefile
===================================================================
--- 2.6.orig/drivers/pci/Makefile 2006-06-08 10:30:14.000000000 -0500
+++ 2.6/drivers/pci/Makefile 2006-06-08 10:30:21.000000000 -0500
@@ -26,7 +26,14 @@
obj-$(CONFIG_PPC64) += setup-bus.o
obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
obj-$(CONFIG_X86_VISWS) += setup-irq.o
-obj-$(CONFIG_PCI_MSI) += msi.o
+
+msiobj-$(CONFIG_X86) += msi.o msi-apic.o msi-intel.o
+msiobj-$(CONFIG_IA64) += msi.o msi-apic.o msi-intel.o
+msiobj-$(CONFIG_IA64_GENERIC) += msi.o msi-altix.o
+msiobj-$(CONFIG_IA64_SGI_SN2) += msi.o msi-altix.o
+msiobj-$(CONFIG_PPC_PSERIES) += msi-rtas.o
+
+obj-$(CONFIG_PCI_MSI) += $(msiobj-y)
#
# ACPI Related PCI FW Functions
Index: 2.6/drivers/pci/msi-rtas.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ 2.6/drivers/pci/msi-rtas.c 2006-06-08 10:51:13.000000000 -0500
@@ -0,0 +1,150 @@
+/*
+ * Jake Moilanen <moilanen@austin.ibm.com>
+ * Copyright (C) 2006 IBM
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <asm/rtas.h>
+#include <asm/hw_irq.h>
+#include <asm/ppc-pci.h>
+
+int rtas_enable_msi(struct pci_dev* pdev)
+{
+ 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];
+ int dummy;
+ unsigned int virq;
+ unsigned int addr;
+ unsigned long buid = -1;
+ struct device_node * dn;
+
+ BUG_ON(!pdev);
+
+ dn = pci_device_to_OF_node(pdev);
+
+ if (!of_find_property(dn, "ibm,req#msi", &dummy))
+ return -ENOENT;
+
+ reg = (u32 *) get_property(dn, "reg", ®len);
+ if (reg == NULL || reglen < 20)
+ return -ENXIO;
+
+ devfn = (reg[0] >> 8) & 0xff;
+ busno = (reg[0] >> 16) & 0xff;
+
+ buid = get_phb_buid(dn->parent);
+ addr = (busno << 16) | (devfn << 8);
+
+ do {
+ rc = rtas_call(rtas_token("ibm,change-msi"), 6, 3, ret, addr,
+ buid >> 32, buid & 0xffffffff,
+ 0, 0, seq_num);
+
+ seq_num = ret[1];
+ } while (rtas_busy_delay(rc));
+
+ if (rc)
+ {
+ printk(KERN_WARNING "error[%d]: getting the number of "
+ "MSI interrupts for %s\n", rc, dn->name);
+ return -EIO;
+ }
+
+ /* Return if there's no MSI interrupts */
+ if (!ret[0])
+ return -ENOENT;
+
+ dn->n_intrs = ret[0];
+
+ dn->intrs = kmalloc(dn->n_intrs * sizeof(*(dn->intrs)), GFP_KERNEL);
+ if (!dn->intrs) {
+ printk(KERN_WARNING "rtas_enable_msi: can't allocate space\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < dn->n_intrs; i++) {
+ do {
+ rc = rtas_call(query_token, 4, 3, ret, addr,
+ buid >> 32, buid & 0xffffffff, i);
+ } while (rtas_busy_delay(rc));
+
+ 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);
+ }
+ }
+
+ /* Just give the first vector out for now */
+ pdev->irq = dn->intrs[0].line;
+
+ return 0;
+}
+
+void rtas_disable_msi(struct pci_dev* pdev)
+{
+ int seq_num = 1;
+ struct device_node * dn;
+ int rc;
+ int devfn;
+ int busno;
+ u32 *reg;
+ int reglen;
+ int ret[3];
+ int dummy;
+ unsigned int addr;
+ unsigned long buid = -1;
+
+ BUG_ON(!pdev);
+
+ dn = pci_device_to_OF_node(pdev);
+
+ if (!of_find_property(dn, "ibm,req#msi", &dummy))
+ return;
+
+ 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);
+
+ do {
+ rc = rtas_call(rtas_token("ibm,change-msi"), 6, 3, ret, addr,
+ buid >> 32, buid & 0xffffffff,
+ 2, 0, seq_num);
+
+ seq_num = ret[1];
+ } while (rtas_busy_delay(rc));
+
+ if (rc) {
+ printk(KERN_WARNING "error[%d]: setting the number of "
+ "MSI interrupts for %s\n", rc, dn->name);
+ return;
+ }
+
+ dn->n_intrs = 0;
+
+ kfree(dn->intrs);
+}
Index: 2.6/drivers/pci/Kconfig
===================================================================
--- 2.6.orig/drivers/pci/Kconfig 2006-06-08 10:30:14.000000000 -0500
+++ 2.6/drivers/pci/Kconfig 2006-06-08 10:30:21.000000000 -0500
@@ -4,7 +4,7 @@
config PCI_MSI
bool "Message Signaled Interrupts (MSI and MSI-X)"
depends on PCI
- depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64
+ depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64 || PPC_PSERIES
help
This allows device drivers to enable MSI (Message Signaled
Interrupts). Message Signaled Interrupts enable a device to
Index: 2.6/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- 2.6.orig/arch/powerpc/platforms/pseries/setup.c 2006-06-08 10:30:14.000000000 -0500
+++ 2.6/arch/powerpc/platforms/pseries/setup.c 2006-06-08 10:30:21.000000000 -0500
@@ -205,6 +205,10 @@
} else {
ppc_md.init_IRQ = xics_init_IRQ;
ppc_md.get_irq = xics_get_irq;
+#ifdef CONFIG_PCI_MSI
+ ppc_md.enable_msi = rtas_enable_msi;
+ ppc_md.disable_msi = rtas_disable_msi;
+#endif
}
#ifdef CONFIG_SMP
Index: 2.6/include/asm-powerpc/rtas.h
===================================================================
--- 2.6.orig/include/asm-powerpc/rtas.h 2006-06-08 10:30:21.000000000 -0500
+++ 2.6/include/asm-powerpc/rtas.h 2006-06-08 10:30:21.000000000 -0500
@@ -4,6 +4,7 @@
#include <linux/spinlock.h>
#include <asm/page.h>
+#include <linux/pci.h>
/*
* Definitions for talking to the RTAS on CHRP machines.
@@ -182,6 +183,9 @@
extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal);
+extern int rtas_enable_msi(struct pci_dev* pdev);
+extern void rtas_disable_msi(struct pci_dev * pdev);
+
/* Error types logged. */
#define ERR_FLAG_ALREADY_LOGGED 0x0
#define ERR_FLAG_BOOT 0x1 /* log was pulled from NVRAM on boot */
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2006-06-08 16:21 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-06-07 21:02 [PATCH 0/3] PPC64 PCIe support Jake Moilanen
2006-06-07 21:05 ` [PATCH 1/3] PCIe device_type pciex Jake Moilanen
2006-06-07 21:15 ` [PATCH 2/3] MSI power abstraction Jake Moilanen
2006-06-07 21:25 ` [PATCH 3/3] RTAS MSI Jake Moilanen
2006-06-07 22:58 ` Nathan Lynch
2006-06-08 16:13 ` Jake Moilanen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).