* [PATCH 2/7] Powerpc MSI infrastructure
2007-04-19 7:35 [PATCH 1/7] Rip out the existing powerpc msi stubs Michael Ellerman
@ 2007-04-19 7:35 ` Michael Ellerman
2007-04-21 23:15 ` Milton Miller
2007-04-19 7:35 ` [PATCH 3/7] RTAS MSI implementation Michael Ellerman
` (4 subsequent siblings)
5 siblings, 1 reply; 34+ messages in thread
From: Michael Ellerman @ 2007-04-19 7:35 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-pci
This patch provides the architecture specific hooks to support MSI on
powerpc. We implement the newly added arch_setup_msi_irqs() and
arch_teardown_msi_irqs(), and then delegate to ppc_md routines.
Platforms that don't implement MSI will leave the ppc_md calls blank,
arch_msi_check_device() will detect this and return ENOSYS. Drivers
should detect this error and continue to use LSI.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/Kconfig | 1 +
arch/powerpc/kernel/Makefile | 1 +
arch/powerpc/kernel/msi.c | 38 ++++++++++++++++++++++++++++++++++++++
include/asm-powerpc/machdep.h | 6 ++++++
4 files changed, 46 insertions(+)
Index: msi-new/arch/powerpc/Kconfig
===================================================================
--- msi-new.orig/arch/powerpc/Kconfig
+++ msi-new/arch/powerpc/Kconfig
@@ -662,6 +662,7 @@ config PCI
&& !PPC_85xx && !PPC_86xx
default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
default PCI_QSPAN if !4xx && !CPM2 && 8xx
+ select ARCH_SUPPORTS_MSI
help
Find out whether your system includes a PCI bus. PCI is the name of
a bus system, i.e. the way the CPU talks to the other stuff inside
Index: msi-new/arch/powerpc/kernel/Makefile
===================================================================
--- msi-new.orig/arch/powerpc/kernel/Makefile
+++ msi-new/arch/powerpc/kernel/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_MODULES) += $(module-y)
pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o
pci32-$(CONFIG_PPC32) := pci_32.o
obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y)
+obj-$(CONFIG_PCI_MSI) += msi.o
kexec-$(CONFIG_PPC64) := machine_kexec_64.o
kexec-$(CONFIG_PPC32) := machine_kexec_32.o
obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o $(kexec-y)
Index: msi-new/arch/powerpc/kernel/msi.c
===================================================================
--- /dev/null
+++ msi-new/arch/powerpc/kernel/msi.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/msi.h>
+
+#include <asm/machdep.h>
+
+int arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
+{
+ if (ppc_md.msi_check_device) {
+ pr_debug("msi: Using platform check routine.\n");
+ return ppc_md.msi_check_device(dev, nvec, type);
+ }
+
+ if (!ppc_md.setup_msi_irqs || !ppc_md.teardown_msi_irqs) {
+ pr_debug("msi: Platform doesn't provide MSI callbacks.\n");
+ return -ENOSYS;
+ }
+
+ return 0;
+}
+
+int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+ return ppc_md.setup_msi_irqs(dev, nvec, type);
+}
+
+void arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+ return ppc_md.teardown_msi_irqs(dev);
+}
Index: msi-new/include/asm-powerpc/machdep.h
===================================================================
--- msi-new.orig/include/asm-powerpc/machdep.h
+++ msi-new/include/asm-powerpc/machdep.h
@@ -115,6 +115,12 @@ struct machdep_calls {
/* To setup PHBs when using automatic OF platform driver for PCI */
int (*pci_setup_phb)(struct pci_controller *host);
+#ifdef CONFIG_PCI_MSI
+ int (*msi_check_device)(struct pci_dev* dev, int nvec, int type);
+ int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type);
+ void (*teardown_msi_irqs)(struct pci_dev *dev);
+#endif
+
void (*restart)(char *cmd);
void (*power_off)(void);
void (*halt)(void);
^ permalink raw reply [flat|nested] 34+ messages in thread* Re: [PATCH 2/7] Powerpc MSI infrastructure
2007-04-19 7:35 ` [PATCH 2/7] Powerpc MSI infrastructure Michael Ellerman
@ 2007-04-21 23:15 ` Milton Miller
2007-04-23 4:28 ` Michael Ellerman
0 siblings, 1 reply; 34+ messages in thread
From: Milton Miller @ 2007-04-21 23:15 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, linux-pci
On Apr 19, 2007, Michael Ellerman wrote:
> This patch provides the architecture specific hooks to support MSI on
> powerpc. We implement the newly added arch_setup_msi_irqs() and
> arch_teardown_msi_irqs(), and then delegate to ppc_md routines.
>
> Index: msi-new/arch/powerpc/kernel/msi.c
> ===================================================================
> --- /dev/null
> +++ msi-new/arch/powerpc/kernel/msi.c
> @@ -0,0 +1,38 @@
> +/*
> + * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version
> + * 2 of the License, or (at your option) any later version.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/msi.h>
> +
> +#include <asm/machdep.h>
> +
> +int arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
> +{
> + if (ppc_md.msi_check_device) {
> + pr_debug("msi: Using platform check routine.\n");
> + return ppc_md.msi_check_device(dev, nvec, type);
> + }
> +
> + if (!ppc_md.setup_msi_irqs || !ppc_md.teardown_msi_irqs) {
> + pr_debug("msi: Platform doesn't provide MSI callbacks.\n");
> + return -ENOSYS;
> + }
Should we not do this check first? Or do you expect some platform
to fill out these hooks in the check call above? Othewise we will
branch to function pointer NULL.
> +
> + return 0;
> +}
> +
> +int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
> +{
> + return ppc_md.setup_msi_irqs(dev, nvec, type);
> +}
> +
> +void arch_teardown_msi_irqs(struct pci_dev *dev)
> +{
> + return ppc_md.teardown_msi_irqs(dev);
> +}
> Index: msi-new/arch/powerpc/kernel/Makefile
> ===================================================================
> --- msi-new.orig/arch/powerpc/kernel/Makefile
> +++ msi-new/arch/powerpc/kernel/Makefile
> +obj-$(CONFIG_PCI_MSI) += msi.o
Do we really need a new file for these simple hooks? It doesn't look
like anthing else is going to be added to it either. I'd prefer to
just do an ifdef in pci.c. Hmmm, we don't seem to have that, but
these are soo small I'd include machdep.h and put them inline in
asm-powerpc/pci.h.
milton
^ permalink raw reply [flat|nested] 34+ messages in thread* Re: [PATCH 2/7] Powerpc MSI infrastructure
2007-04-21 23:15 ` Milton Miller
@ 2007-04-23 4:28 ` Michael Ellerman
0 siblings, 0 replies; 34+ messages in thread
From: Michael Ellerman @ 2007-04-23 4:28 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, linux-pci
[-- Attachment #1: Type: text/plain, Size: 3192 bytes --]
On Sat, 2007-04-21 at 18:15 -0500, Milton Miller wrote:
> On Apr 19, 2007, Michael Ellerman wrote:
> > This patch provides the architecture specific hooks to support MSI on
> > powerpc. We implement the newly added arch_setup_msi_irqs() and
> > arch_teardown_msi_irqs(), and then delegate to ppc_md routines.
> >
>
> > Index: msi-new/arch/powerpc/kernel/msi.c
> > ===================================================================
> > --- /dev/null
> > +++ msi-new/arch/powerpc/kernel/msi.c
> > @@ -0,0 +1,38 @@
> > +/*
> > + * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
> > + *
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License
> > + * as published by the Free Software Foundation; either version
> > + * 2 of the License, or (at your option) any later version.
> > + */
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/msi.h>
> > +
> > +#include <asm/machdep.h>
> > +
> > +int arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
> > +{
> > + if (ppc_md.msi_check_device) {
> > + pr_debug("msi: Using platform check routine.\n");
> > + return ppc_md.msi_check_device(dev, nvec, type);
> > + }
> > +
> > + if (!ppc_md.setup_msi_irqs || !ppc_md.teardown_msi_irqs) {
> > + pr_debug("msi: Platform doesn't provide MSI callbacks.\n");
> > + return -ENOSYS;
> > + }
>
> Should we not do this check first? Or do you expect some platform
> to fill out these hooks in the check call above? Othewise we will
> branch to function pointer NULL.
Not really. More a case of if you provide check then you'd better get
your act together and provide the others. I'll rearrange it to be safer.
>
> > +
> > + return 0;
> > +}
> > +
> > +int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
> > +{
> > + return ppc_md.setup_msi_irqs(dev, nvec, type);
> > +}
> > +
> > +void arch_teardown_msi_irqs(struct pci_dev *dev)
> > +{
> > + return ppc_md.teardown_msi_irqs(dev);
> > +}
>
>
> > Index: msi-new/arch/powerpc/kernel/Makefile
> > ===================================================================
> > --- msi-new.orig/arch/powerpc/kernel/Makefile
> > +++ msi-new/arch/powerpc/kernel/Makefile
>
> > +obj-$(CONFIG_PCI_MSI) += msi.o
>
>
> Do we really need a new file for these simple hooks? It doesn't look
> like anthing else is going to be added to it either. I'd prefer to
> just do an ifdef in pci.c. Hmmm, we don't seem to have that, but
> these are soo small I'd include machdep.h and put them inline in
> asm-powerpc/pci.h.
I'd rather leave it as is. We can't have them inline, because they're
already defined in drivers/pci/msi.c. And having the CONFIG logic in the
Makefile is cleaner than #ifdef goo. Also it might grow one day, if we
make the hooks per pci_dev or per bus rather than in ppc_md.
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 [flat|nested] 34+ messages in thread
* [PATCH 3/7] RTAS MSI implementation
2007-04-19 7:35 [PATCH 1/7] Rip out the existing powerpc msi stubs Michael Ellerman
2007-04-19 7:35 ` [PATCH 2/7] Powerpc MSI infrastructure Michael Ellerman
@ 2007-04-19 7:35 ` Michael Ellerman
2007-04-19 7:35 ` [PATCH 4/7] Tell Phyp we support MSI Michael Ellerman
` (3 subsequent siblings)
5 siblings, 0 replies; 34+ messages in thread
From: Michael Ellerman @ 2007-04-19 7:35 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-pci
Implements MSI support via RTAS. For now we assumes that if the required
RTAS tokens for MSI are present, then we want to use the RTAS MSI
routines.
When RTAS is managing MSIs for us, it will/may enable MSI on devices that
support it by default. This is contrary to the Linux model where a device
is in LSI mode until the driver requests MSIs.
To remedy this we add a pci_irq_fixup call, which disables MSI if they've
been assigned by firmware and the device also supports LSI. Devices that
don't support LSI at all will be left as is, drivers are still expected
to call pci_enable_msi() before using the device.
At the moment there is no pci_irq_fixup on pSeries, so we can just set it
unconditionally. If other platforms use the RTAS MSI backend they'll need
to check that still holds.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/pseries/Makefile | 1
arch/powerpc/platforms/pseries/msi.c | 266 ++++++++++++++++++++++++++++++++
2 files changed, 267 insertions(+)
Index: msi-new/arch/powerpc/platforms/pseries/Makefile
===================================================================
--- msi-new.orig/arch/powerpc/platforms/pseries/Makefile
+++ msi-new/arch/powerpc/platforms/pseries/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_SCANLOG) += scanlog.o
obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o
obj-$(CONFIG_KEXEC) += kexec.o
obj-$(CONFIG_PCI) += pci.o pci_dlpar.o
+obj-$(CONFIG_PCI_MSI) += msi.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o
Index: msi-new/arch/powerpc/platforms/pseries/msi.c
===================================================================
--- /dev/null
+++ msi-new/arch/powerpc/platforms/pseries/msi.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2006 Jake Moilanen <moilanen@austin.ibm.com>, IBM Corp.
+ * Copyright 2006 Michael Ellerman, IBM Corp.
+ *
+ * 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/device.h>
+#include <linux/irq.h>
+#include <linux/msi.h>
+
+#include <asm/rtas.h>
+#include <asm/hw_irq.h>
+#include <asm/ppc-pci.h>
+
+static int query_token, change_token;
+
+#define RTAS_QUERY_FN 0
+#define RTAS_CHANGE_FN 1
+#define RTAS_RESET_FN 2
+#define RTAS_CHANGE_MSI_FN 3
+#define RTAS_CHANGE_MSIX_FN 4
+
+static struct pci_dn *get_pdn(struct pci_dev *pdev)
+{
+ struct device_node *dn;
+ struct pci_dn *pdn;
+
+ dn = pci_device_to_OF_node(pdev);
+ if (!dn) {
+ dev_dbg(&pdev->dev, "rtas_msi: No OF device node\n");
+ return NULL;
+ }
+
+ pdn = PCI_DN(dn);
+ if (!pdn) {
+ dev_dbg(&pdev->dev, "rtas_msi: No PCI DN\n");
+ return NULL;
+ }
+
+ return pdn;
+}
+
+/* RTAS Helpers */
+
+static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs)
+{
+ u32 addr, seq_num, rtas_ret[3];
+ unsigned long buid;
+ int rc;
+
+ addr = rtas_config_addr(pdn->busno, pdn->devfn, 0);
+ buid = pdn->phb->buid;
+
+ seq_num = 1;
+ do {
+ if (func == RTAS_CHANGE_MSI_FN || func == RTAS_CHANGE_MSIX_FN)
+ rc = rtas_call(change_token, 6, 4, rtas_ret, addr,
+ BUID_HI(buid), BUID_LO(buid),
+ func, num_irqs, seq_num);
+ else
+ rc = rtas_call(change_token, 6, 3, rtas_ret, addr,
+ BUID_HI(buid), BUID_LO(buid),
+ func, num_irqs, seq_num);
+
+ seq_num = rtas_ret[1];
+ } while (rtas_busy_delay(rc));
+
+ if (rc == 0) /* Success */
+ rc = rtas_ret[0];
+
+ pr_debug("rtas_msi: ibm,change_msi(func=%d,num=%d) = (%d)\n",
+ func, num_irqs, rc);
+
+ return rc;
+}
+
+static void rtas_disable_msi(struct pci_dev *pdev)
+{
+ struct pci_dn *pdn;
+
+ pdn = get_pdn(pdev);
+ if (!pdn)
+ return;
+
+ if (rtas_change_msi(pdn, RTAS_CHANGE_FN, 0) != 0)
+ pr_debug("rtas_msi: Setting MSIs to 0 failed!\n");
+}
+
+static int rtas_query_irq_number(struct pci_dn *pdn, int offset)
+{
+ u32 addr, rtas_ret[2];
+ unsigned long buid;
+ int rc;
+
+ addr = rtas_config_addr(pdn->busno, pdn->devfn, 0);
+ buid = pdn->phb->buid;
+
+ do {
+ rc = rtas_call(query_token, 4, 3, rtas_ret, addr,
+ BUID_HI(buid), BUID_LO(buid), offset);
+ } while (rtas_busy_delay(rc));
+
+ if (rc) {
+ pr_debug("rtas_msi: error (%d) querying source number\n", rc);
+ return rc;
+ }
+
+ return rtas_ret[0];
+}
+
+static void rtas_teardown_msi_irqs(struct pci_dev *pdev)
+{
+ struct msi_desc *entry;
+
+ list_for_each_entry(entry, &pdev->msi_list, list) {
+ set_irq_msi(entry->irq, NULL);
+ irq_dispose_mapping(entry->irq);
+ }
+
+ rtas_disable_msi(pdev);
+}
+
+static int check_req_msi(struct pci_dev *pdev, int nvec)
+{
+ struct device_node *dn;
+ struct pci_dn *pdn;
+ const u32 *req_msi;
+
+ pdn = get_pdn(pdev);
+ if (!pdn)
+ return -ENODEV;
+
+ dn = pdn->node;
+
+ req_msi = of_get_property(dn, "ibm,req#msi", NULL);
+ if (!req_msi) {
+ pr_debug("rtas_msi: No ibm,req#msi on %s\n", dn->full_name);
+ return -ENOENT;
+ }
+
+ if (*req_msi < nvec) {
+ pr_debug("rtas_msi: ibm,req#msi requests < %d MSIs\n", nvec);
+ return -ENOSPC;
+ }
+
+ return 0;
+}
+
+static int rtas_msi_check_device(struct pci_dev *pdev, int nvec, int type)
+{
+ if (type == PCI_CAP_ID_MSIX)
+ pr_debug("rtas_msi: MSI-X untested, trying anyway.\n");
+
+ return check_req_msi(pdev, nvec);
+}
+
+static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+{
+ struct pci_dn *pdn;
+ int hwirq, virq, i, rc;
+ struct msi_desc *entry;
+
+ pdn = get_pdn(pdev);
+ if (!pdn)
+ return -ENODEV;
+
+ /*
+ * Try the new more explicit firmware interface, if that fails fall
+ * back to the old interface. The old interface is known to never
+ * return MSI-Xs.
+ */
+ if (type == PCI_CAP_ID_MSI) {
+ rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec);
+
+ if (rc != nvec) {
+ pr_debug("rtas_msi: trying the old firmware call.\n");
+ rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec);
+ }
+ } else
+ rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec);
+
+ if (rc != nvec) {
+ pr_debug("rtas_msi: rtas_change_msi() failed\n");
+
+ /*
+ * In case of an error it's not clear whether the device is
+ * left with MSI enabled or not, so we explicitly disable.
+ */
+ goto out_free;
+ }
+
+ i = 0;
+ list_for_each_entry(entry, &pdev->msi_list, list) {
+ hwirq = rtas_query_irq_number(pdn, i);
+ if (hwirq < 0) {
+ rc = hwirq;
+ pr_debug("rtas_msi: error (%d) getting hwirq\n", rc);
+ goto out_free;
+ }
+
+ virq = irq_create_mapping(NULL, hwirq);
+
+ if (virq == NO_IRQ) {
+ pr_debug("rtas_msi: Failed mapping hwirq %d\n", hwirq);
+ rc = -ENOSPC;
+ goto out_free;
+ }
+
+ dev_dbg(&pdev->dev, "rtas_msi: allocated virq %d\n", virq);
+ set_irq_msi(virq, entry);
+ unmask_msi_irq(virq);
+ }
+
+ return 0;
+
+ out_free:
+ rtas_teardown_msi_irqs(pdev);
+ return rc;
+}
+
+static void rtas_msi_pci_irq_fixup(struct pci_dev *pdev)
+{
+ /* No LSI -> leave MSIs (if any) configured */
+ if (pdev->irq == NO_IRQ) {
+ dev_dbg(&pdev->dev, "rtas_msi: no LSI, nothing to do.\n");
+ return;
+ }
+
+ /* No MSI -> MSIs can't have been assigned by fw, leave LSI */
+ if (check_req_msi(pdev, 1)) {
+ dev_dbg(&pdev->dev, "rtas_msi: no req#msi, nothing to do.\n");
+ return;
+ }
+
+ dev_dbg(&pdev->dev, "rtas_msi: disabling existing MSI.\n");
+ rtas_disable_msi(pdev);
+}
+
+static int rtas_msi_init(void)
+{
+ query_token = rtas_token("ibm,query-interrupt-source-number");
+ change_token = rtas_token("ibm,change-msi");
+
+ if ((query_token == RTAS_UNKNOWN_SERVICE) ||
+ (change_token == RTAS_UNKNOWN_SERVICE)) {
+ pr_debug("rtas_msi: no RTAS tokens, no MSI support.\n");
+ return -1;
+ }
+
+ pr_debug("rtas_msi: Registering RTAS MSI callbacks.\n");
+
+ ppc_md.setup_msi_irqs = rtas_setup_msi_irqs;
+ ppc_md.teardown_msi_irqs = rtas_teardown_msi_irqs;
+ ppc_md.msi_check_device = rtas_msi_check_device;
+
+ WARN_ON(ppc_md.pci_irq_fixup);
+ ppc_md.pci_irq_fixup = rtas_msi_pci_irq_fixup;
+
+ return 0;
+}
+arch_initcall(rtas_msi_init);
^ permalink raw reply [flat|nested] 34+ messages in thread* [PATCH 4/7] Tell Phyp we support MSI
2007-04-19 7:35 [PATCH 1/7] Rip out the existing powerpc msi stubs Michael Ellerman
2007-04-19 7:35 ` [PATCH 2/7] Powerpc MSI infrastructure Michael Ellerman
2007-04-19 7:35 ` [PATCH 3/7] RTAS MSI implementation Michael Ellerman
@ 2007-04-19 7:35 ` Michael Ellerman
2007-04-19 7:35 ` [PATCH 5/7] Enable MSI mappings for MPIC Michael Ellerman
` (2 subsequent siblings)
5 siblings, 0 replies; 34+ messages in thread
From: Michael Ellerman @ 2007-04-19 7:35 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-pci
Tell Phyp we support MSI via the client architecture support mechanism.
Signed-off-by: Jake Moilanen <moilanen@austin.ibm.com>
---
arch/powerpc/kernel/prom_init.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
Index: msi-new/arch/powerpc/kernel/prom_init.c
===================================================================
--- msi-new.orig/arch/powerpc/kernel/prom_init.c
+++ msi-new/arch/powerpc/kernel/prom_init.c
@@ -635,6 +635,12 @@ static void __init early_cmdline_parse(v
/* ibm,dynamic-reconfiguration-memory property supported */
#define OV5_DRCONF_MEMORY 0x20
#define OV5_LARGE_PAGES 0x10 /* large pages supported */
+/* PCIe/MSI support. Without MSI full PCIe is not supported */
+#ifdef CONFIG_PCI_MSI
+#define OV5_MSI 0x01 /* PCIe/MSI support */
+#else
+#define OV5_MSI 0x00
+#endif /* CONFIG_PCI_MSI */
/*
* The architecture vector has an array of PVR mask/value pairs,
@@ -679,7 +685,7 @@ static unsigned char ibm_architecture_ve
/* option vector 5: PAPR/OF options */
3 - 2, /* length */
0, /* don't ignore, don't halt */
- OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY,
+ OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | OV5_MSI,
};
/* Old method - ELF header with PT_NOTE sections */
^ permalink raw reply [flat|nested] 34+ messages in thread* [PATCH 5/7] Enable MSI mappings for MPIC
2007-04-19 7:35 [PATCH 1/7] Rip out the existing powerpc msi stubs Michael Ellerman
` (2 preceding siblings ...)
2007-04-19 7:35 ` [PATCH 4/7] Tell Phyp we support MSI Michael Ellerman
@ 2007-04-19 7:35 ` Michael Ellerman
2007-04-21 23:16 ` Milton Miller
2007-04-19 7:35 ` [PATCH 6/7] MPIC MSI allocator Michael Ellerman
2007-04-19 7:35 ` [PATCH 7/7] MPIC MSI backend Michael Ellerman
5 siblings, 1 reply; 34+ messages in thread
From: Michael Ellerman @ 2007-04-19 7:35 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-pci
On some Apple machines the HT MSI mappings are not enabled by firmware, so
we need to do it by hand.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/sysdev/mpic.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
Index: msi-new/arch/powerpc/sysdev/mpic.c
===================================================================
--- msi-new.orig/arch/powerpc/sysdev/mpic.c
+++ msi-new/arch/powerpc/sysdev/mpic.c
@@ -379,6 +379,50 @@ static void mpic_shutdown_ht_interrupt(s
spin_unlock_irqrestore(&mpic->fixup_lock, flags);
}
+#ifdef CONFIG_PCI_MSI
+static void __init mpic_scan_ht_msi(struct mpic *mpic, u8 __iomem *devbase,
+ unsigned int devfn)
+{
+ u8 __iomem *base;
+ u8 pos, flags;
+ u64 addr = 0;
+
+ for (pos = readb(devbase + PCI_CAPABILITY_LIST); pos != 0;
+ pos = readb(devbase + pos + PCI_CAP_LIST_NEXT)) {
+ u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
+ if (id == PCI_CAP_ID_HT) {
+ id = readb(devbase + pos + 3);
+ if ((id & HT_5BIT_CAP_MASK) == HT_CAPTYPE_MSI_MAPPING)
+ break;
+ }
+ }
+
+ if (pos == 0)
+ return;
+
+ base = devbase + pos;
+
+ flags = readb(base + HT_MSI_FLAGS);
+ if (!(flags & HT_MSI_FLAGS_FIXED)) {
+ addr = readl(base + HT_MSI_ADDR_LO) & HT_MSI_ADDR_LO_MASK;
+ addr = addr | ((u64)readl(base + HT_MSI_ADDR_HI) << 32);
+ }
+
+ printk(KERN_DEBUG "mpic: - HT:%02x.%x %s MSI mapping found @ 0x%lx\n",
+ PCI_SLOT(devfn), PCI_FUNC(devfn),
+ flags & HT_MSI_FLAGS_ENABLE ? "enabled" : "disabled", addr);
+
+ if (!(flags & HT_MSI_FLAGS_ENABLE))
+ writeb(flags | HT_MSI_FLAGS_ENABLE, base + HT_MSI_FLAGS);
+}
+#else
+static void __init mpic_scan_ht_msi(struct mpic *mpic, u8 __iomem *devbase,
+ unsigned int devfn)
+{
+ return;
+}
+#endif
+
static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
unsigned int devfn, u32 vdid)
{
@@ -470,6 +514,7 @@ static void __init mpic_scan_ht_pics(str
goto next;
mpic_scan_ht_pic(mpic, devbase, devfn, l);
+ mpic_scan_ht_msi(mpic, devbase, devfn);
next:
/* next device, if function 0 */
^ permalink raw reply [flat|nested] 34+ messages in thread* Re: [PATCH 5/7] Enable MSI mappings for MPIC
2007-04-19 7:35 ` [PATCH 5/7] Enable MSI mappings for MPIC Michael Ellerman
@ 2007-04-21 23:16 ` Milton Miller
2007-04-22 0:06 ` Benjamin Herrenschmidt
0 siblings, 1 reply; 34+ messages in thread
From: Milton Miller @ 2007-04-21 23:16 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, linux-pci
On Apr 19, 2007, Michael Ellerman wrote:
> On some Apple machines the HT MSI mappings are not enabled by
> firmware, so
> we need to do it by hand.
>
> +#ifdef CONFIG_PCI_MSI
> +static void __init mpic_scan_ht_msi(struct mpic *mpic, u8 __iomem
> *devbase,
> + unsigned int devfn)
> +{
> + u8 __iomem *base;
> + u8 pos, flags;
> + u64 addr = 0;
> +
> + for (pos = readb(devbase + PCI_CAPABILITY_LIST); pos != 0;
> + pos = readb(devbase + pos + PCI_CAP_LIST_NEXT)) {
> + u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
> + if (id == PCI_CAP_ID_HT) {
> + id = readb(devbase + pos + 3);
> + if ((id & HT_5BIT_CAP_MASK) == HT_CAPTYPE_MSI_MAPPING)
>
This is just begging to be written in terms of
pci_bus_find_ht_capability. Well,
we have pci_bus_find_capability, and pci_find_ht_capability, I'm sure
we could
create that. It also means this and the other nearby functions want
to be
written in terms of a struct pci_bus and config accessors.
milton
^ permalink raw reply [flat|nested] 34+ messages in thread* Re: [PATCH 5/7] Enable MSI mappings for MPIC
2007-04-21 23:16 ` Milton Miller
@ 2007-04-22 0:06 ` Benjamin Herrenschmidt
2007-04-22 4:53 ` Milton Miller
0 siblings, 1 reply; 34+ messages in thread
From: Benjamin Herrenschmidt @ 2007-04-22 0:06 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, linux-pci
> This is just begging to be written in terms of
> pci_bus_find_ht_capability. Well,
> we have pci_bus_find_capability, and pci_find_ht_capability, I'm sure
> we could
> create that. It also means this and the other nearby functions want
> to be
> written in terms of a struct pci_bus and config accessors.
A lot of that code has to run way before the PCI config stuff is even
useable and certainly before the PCI layer data structures have been
created.... Sucks but that's how it is for now. We might be able to
tweak and delay init of the APICs etc... but I don't think I can be
bothered for now as it's a bit of a corner case.
Ben.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 5/7] Enable MSI mappings for MPIC
2007-04-22 0:06 ` Benjamin Herrenschmidt
@ 2007-04-22 4:53 ` Milton Miller
2007-04-23 4:10 ` Michael Ellerman
0 siblings, 1 reply; 34+ messages in thread
From: Milton Miller @ 2007-04-22 4:53 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linux-pci
On Apr 21, 2007, at 7:06 PM, Benjamin Herrenschmidt wrote:
>> This is just begging to be written in terms of
>> pci_bus_find_ht_capability. Well,
>> we have pci_bus_find_capability, and pci_find_ht_capability, I'm sure
>> we could
>> create that. It also means this and the other nearby functions want
>> to be
>> written in terms of a struct pci_bus and config accessors.
>
> A lot of that code has to run way before the PCI config stuff is even
> useable and certainly before the PCI layer data structures have been
> created.... Sucks but that's how it is for now. We might be able to
> tweak and delay init of the APICs etc... but I don't think I can be
> bothered for now as it's a bit of a corner case.
>
I wasn't proposing to make the code wait until the pci layer had
discovered the ht bridge. Rather I was thinking that a struct
pci_bus instance created for the purpose with only ops and maybe
sysdata initialized. The purpose being to reuse the generic code.
Maybe I'll have to code something up. Perhaps when I'm a bit
less overloaded.
milton
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 5/7] Enable MSI mappings for MPIC
2007-04-22 4:53 ` Milton Miller
@ 2007-04-23 4:10 ` Michael Ellerman
0 siblings, 0 replies; 34+ messages in thread
From: Michael Ellerman @ 2007-04-23 4:10 UTC (permalink / raw)
To: Milton Miller; +Cc: linux-pci, linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 1615 bytes --]
On Sat, 2007-04-21 at 23:53 -0500, Milton Miller wrote:
> On Apr 21, 2007, at 7:06 PM, Benjamin Herrenschmidt wrote:
> >> This is just begging to be written in terms of
> >> pci_bus_find_ht_capability. Well,
> >> we have pci_bus_find_capability, and pci_find_ht_capability, I'm sure
> >> we could
> >> create that. It also means this and the other nearby functions want
> >> to be
> >> written in terms of a struct pci_bus and config accessors.
> >
> > A lot of that code has to run way before the PCI config stuff is even
> > useable and certainly before the PCI layer data structures have been
> > created.... Sucks but that's how it is for now. We might be able to
> > tweak and delay init of the APICs etc... but I don't think I can be
> > bothered for now as it's a bit of a corner case.
> >
>
> I wasn't proposing to make the code wait until the pci layer had
> discovered the ht bridge. Rather I was thinking that a struct
> pci_bus instance created for the purpose with only ops and maybe
> sysdata initialized. The purpose being to reuse the generic code.
That'd be nice in a way. Although there'd be scope for breakage from
time to time as PCI changes get made without taking into account this
special case.
> Maybe I'll have to code something up. Perhaps when I'm a bit
> less overloaded.
All yours :)
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 [flat|nested] 34+ messages in thread
* [PATCH 6/7] MPIC MSI allocator
2007-04-19 7:35 [PATCH 1/7] Rip out the existing powerpc msi stubs Michael Ellerman
` (3 preceding siblings ...)
2007-04-19 7:35 ` [PATCH 5/7] Enable MSI mappings for MPIC Michael Ellerman
@ 2007-04-19 7:35 ` Michael Ellerman
2007-04-21 23:17 ` Milton Miller
2007-04-23 3:50 ` Olof Johansson
2007-04-19 7:35 ` [PATCH 7/7] MPIC MSI backend Michael Ellerman
5 siblings, 2 replies; 34+ messages in thread
From: Michael Ellerman @ 2007-04-19 7:35 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-pci
To support MSI on MPIC we need a way to reserve and allocate hardware irq
numbers, this patch implements an allocator for that.
New firmware platforms must define a "msi-available-ranges" property on their
MPIC node for MSI to work. For BROKEN_U3 we do a best-guess setup.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/sysdev/Makefile | 5 -
arch/powerpc/sysdev/mpic.c | 4
arch/powerpc/sysdev/mpic.h | 24 +++++
arch/powerpc/sysdev/mpic_msi.c | 175 +++++++++++++++++++++++++++++++++++++++++
include/asm-powerpc/mpic.h | 11 ++
5 files changed, 218 insertions(+), 1 deletion(-)
Index: msi-new/arch/powerpc/sysdev/Makefile
===================================================================
--- msi-new.orig/arch/powerpc/sysdev/Makefile
+++ msi-new/arch/powerpc/sysdev/Makefile
@@ -2,7 +2,10 @@ ifeq ($(CONFIG_PPC64),y)
EXTRA_CFLAGS += -mno-minimal-toc
endif
-obj-$(CONFIG_MPIC) += mpic.o
+mpic-obj-y := mpic.o
+mpic-obj-$(CONFIG_PCI_MSI) += mpic_msi.o
+obj-$(CONFIG_MPIC) += $(mpic-obj-y)
+
obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
obj-$(CONFIG_PPC_MPC106) += grackle.o
obj-$(CONFIG_PPC_DCR) += dcr.o
Index: msi-new/arch/powerpc/sysdev/mpic.c
===================================================================
--- msi-new.orig/arch/powerpc/sysdev/mpic.c
+++ msi-new/arch/powerpc/sysdev/mpic.c
@@ -36,6 +36,8 @@
#include <asm/mpic.h>
#include <asm/smp.h>
+#include "mpic.h"
+
#ifdef DEBUG
#define DBG(fmt...) printk(fmt)
#else
@@ -879,6 +881,8 @@ static int mpic_host_map(struct irq_host
if (hw >= mpic->irq_count)
return -EINVAL;
+ mpic_msi_reserve_hwirq(mpic, hw);
+
/* Default chip */
chip = &mpic->hc_irq;
Index: msi-new/arch/powerpc/sysdev/mpic.h
===================================================================
--- /dev/null
+++ msi-new/arch/powerpc/sysdev/mpic.h
@@ -0,0 +1,24 @@
+#ifndef _POWERPC_SYSDEV_MPIC_H
+#define _POWERPC_SYSDEV_MPIC_H
+
+/*
+ * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#ifdef CONFIG_PCI_MSI
+extern void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq);
+#else
+static inline void mpic_msi_reserve_hwirq(struct mpic *mpic,
+ irq_hw_number_t hwirq)
+{
+ return;
+}
+#endif
+
+#endif /* _POWERPC_SYSDEV_MPIC_H */
Index: msi-new/arch/powerpc/sysdev/mpic_msi.c
===================================================================
--- /dev/null
+++ msi-new/arch/powerpc/sysdev/mpic_msi.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/bootmem.h>
+#include <linux/bitmap.h>
+#include <linux/msi.h>
+#include <asm/mpic.h>
+#include <asm/prom.h>
+#include <asm/hw_irq.h>
+#include <asm/ppc-pci.h>
+
+
+static void __mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
+{
+ pr_debug("mpic: reserving hwirq 0x%lx\n", hwirq);
+ bitmap_allocate_region(mpic->hwirq_bitmap, hwirq, 0);
+}
+
+void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
+{
+ unsigned long flags;
+
+ /* The mpic calls this even when there is no allocator setup */
+ if (!mpic->hwirq_bitmap)
+ return;
+
+ spin_lock_irqsave(&mpic->bitmap_lock, flags);
+ __mpic_msi_reserve_hwirq(mpic, hwirq);
+ spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
+}
+
+irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num)
+{
+ unsigned long flags;
+ int offset, order = fls(num) - 1;
+
+ spin_lock_irqsave(&mpic->bitmap_lock, flags);
+ /*
+ * This is fast, but stricter than we need. We might want to add
+ * a fallback routine which does a linear search with no alignment.
+ */
+ offset = bitmap_find_free_region(mpic->hwirq_bitmap, mpic->irq_count,
+ order);
+ spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
+
+ pr_debug("mpic: allocated 0x%x (2^%d) at offset 0x%x\n",
+ num, order, offset);
+
+ return offset;
+}
+
+void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num)
+{
+ unsigned long flags;
+ int order = fls(num) - 1;
+
+ pr_debug("mpic: freeing 0x%x (2^%d) at offset 0x%x\n",
+ num, order, offset);
+
+ spin_lock_irqsave(&mpic->bitmap_lock, flags);
+ bitmap_release_region(mpic->hwirq_bitmap, offset, order);
+ spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
+}
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
+{
+ irq_hw_number_t hwirq;
+ struct irq_host_ops *ops = mpic->irqhost->ops;
+ struct device_node *np;
+ int flags, index, i;
+ struct of_irq oirq;
+
+ pr_debug("mpic: found U3, guessing msi allocator setup\n");
+
+ /* Reserve source numbers we know are reserved in the HW */
+ for (i = 0; i < 8; i++) __mpic_msi_reserve_hwirq(mpic, i);
+ for (i = 42; i < 46; i++) __mpic_msi_reserve_hwirq(mpic, i);
+ for (i = 100; i < 105; i++) __mpic_msi_reserve_hwirq(mpic, i);
+
+ np = NULL;
+ while ((np = of_find_all_nodes(np))) {
+ pr_debug("mpic: mapping hwirqs for %s\n", np->full_name);
+
+ index = 0;
+ while (of_irq_map_one(np, index++, &oirq) == 0) {
+ ops->xlate(mpic->irqhost, NULL, oirq.specifier,
+ oirq.size, &hwirq, &flags);
+ __mpic_msi_reserve_hwirq(mpic, hwirq);
+ }
+ }
+
+ return 0;
+}
+#else
+static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) { return -1; }
+#endif
+
+static int mpic_msi_reserve_dt_hwirqs(struct mpic *mpic)
+{
+ int i, len;
+ const u32 *p;
+
+ p = of_get_property(mpic->of_node, "msi-available-ranges", &len);
+ if (!p) {
+ pr_debug("mpic: no msi-available-ranges property found on %s\n",
+ mpic->of_node->full_name);
+ return -ENODEV;
+ }
+
+ if (len % 8 != 0) {
+ printk(KERN_WARNING "mpic: Malformed msi-available-ranges "
+ "property on %s\n", mpic->of_node->full_name);
+ return -EINVAL;
+ }
+
+ bitmap_allocate_region(mpic->hwirq_bitmap, 0,
+ fls(mpic->irq_count) - 1);
+
+ /* Format is: (<u32 start> <u32 count>)+ */
+ len /= sizeof(u32);
+ for (i = 0; i < len / 2; i++, p += 2)
+ mpic_msi_free_hwirqs(mpic, *p, *(p + 1));
+
+ return 0;
+}
+
+int mpic_msi_init_allocator(struct mpic *mpic)
+{
+ int rc, size;
+
+ BUG_ON(mpic->hwirq_bitmap);
+ spin_lock_init(&mpic->bitmap_lock);
+
+ size = mpic->irq_count / 8;
+ pr_debug("mpic: allocator bitmap size is 0x%x bytes\n", size);
+
+ if (mem_init_done)
+ mpic->hwirq_bitmap = kmalloc(size, GFP_KERNEL);
+ else
+ mpic->hwirq_bitmap = alloc_bootmem(size);
+
+ if (!mpic->hwirq_bitmap) {
+ pr_debug("mpic: ENOMEM allocating allocator bitmap!\n");
+ return -ENOMEM;
+ }
+
+ memset(mpic->hwirq_bitmap, 0, size);
+
+ rc = mpic_msi_reserve_dt_hwirqs(mpic);
+ if (rc) {
+ if (mpic->flags & MPIC_BROKEN_U3)
+ rc = mpic_msi_reserve_u3_hwirqs(mpic);
+
+ if (rc)
+ goto out_free;
+ }
+
+ return 0;
+
+ out_free:
+ if (mem_init_done)
+ kfree(mpic->hwirq_bitmap);
+
+ mpic->hwirq_bitmap = NULL;
+ return rc;
+}
Index: msi-new/include/asm-powerpc/mpic.h
===================================================================
--- msi-new.orig/include/asm-powerpc/mpic.h
+++ msi-new/include/asm-powerpc/mpic.h
@@ -292,6 +292,11 @@ struct mpic
u32 *hw_set;
#endif
+#ifdef CONFIG_PCI_MSI
+ spinlock_t bitmap_lock;
+ unsigned long *hwirq_bitmap;
+#endif
+
/* link */
struct mpic *next;
};
@@ -440,5 +445,11 @@ void mpic_set_clk_ratio(struct mpic *mpi
/* Enable/Disable EPIC serial interrupt mode */
void mpic_set_serial_int(struct mpic *mpic, int enable);
+#ifdef CONFIG_PCI_MSI
+extern int mpic_msi_init_allocator(struct mpic *mpic);
+extern irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num);
+extern void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num);
+#endif
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_MPIC_H */
^ permalink raw reply [flat|nested] 34+ messages in thread* Re: [PATCH 6/7] MPIC MSI allocator
2007-04-19 7:35 ` [PATCH 6/7] MPIC MSI allocator Michael Ellerman
@ 2007-04-21 23:17 ` Milton Miller
2007-04-23 4:04 ` Michael Ellerman
2007-04-23 3:50 ` Olof Johansson
1 sibling, 1 reply; 34+ messages in thread
From: Milton Miller @ 2007-04-21 23:17 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, linux-pci
On Apr 19, 2007, Michael Ellerman wrote:
> To support MSI on MPIC we need a way to reserve and allocate hardware
> irq
> numbers, this patch implements an allocator for that.
> Index: msi-new/arch/powerpc/sysdev/mpic_msi.c
> ===================================================================
> --- /dev/null
> +++ msi-new/arch/powerpc/sysdev/mpic_msi.c
...
> +irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num)
> +{
> + unsigned long flags;
> + int offset, order = fls(num) - 1;
get_count_order would be more clear. Also it has
a correction factor. (Applies several places).
> +#ifdef CONFIG_MPIC_BROKEN_U3
> +static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
> +{
> + irq_hw_number_t hwirq;
> + struct irq_host_ops *ops = mpic->irqhost->ops;
> + struct device_node *np;
> + int flags, index, i;
> + struct of_irq oirq;
> +
> + pr_debug("mpic: found U3, guessing msi allocator setup\n");
> +
> + /* Reserve source numbers we know are reserved in the HW */
> + for (i = 0; i < 8; i++) __mpic_msi_reserve_hwirq(mpic, i);
> + for (i = 42; i < 46; i++) __mpic_msi_reserve_hwirq(mpic, i);
> + for (i = 100; i < 105; i++) __mpic_msi_reserve_hwirq(mpic, i);
More lines please.
> +#else
> +static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) { return -1;
> }
and here.
> + if (len % 8 != 0) {
> + printk(KERN_WARNING "mpic: Malformed msi-available-ranges "
> + "property on %s\n", mpic->of_node->full_name);
> + return -EINVAL;
> + }
> +
> + bitmap_allocate_region(mpic->hwirq_bitmap, 0,
> + fls(mpic->irq_count) - 1);
> +
> + /* Format is: (<u32 start> <u32 count>)+ */
> + len /= sizeof(u32);
> + for (i = 0; i < len / 2; i++, p += 2)
how about just dividing by the calculated 8 above? or use
count = len / 8.
> + mpic_msi_free_hwirqs(mpic, *p, *(p + 1));
> +
> + return 0;
> +}
> +
> +int mpic_msi_init_allocator(struct mpic *mpic)
> +{
> + int rc, size;
> +
> + BUG_ON(mpic->hwirq_bitmap);
> + spin_lock_init(&mpic->bitmap_lock);
> +
> + size = mpic->irq_count / 8;
> + pr_debug("mpic: allocator bitmap size is 0x%x bytes\n", size);
BITS_TO_LONGS() * sizeof(long). We need to round up to longs to
use bitmask_*, especially being a big endian architecture.
milton
^ permalink raw reply [flat|nested] 34+ messages in thread* Re: [PATCH 6/7] MPIC MSI allocator
2007-04-21 23:17 ` Milton Miller
@ 2007-04-23 4:04 ` Michael Ellerman
2007-04-23 6:20 ` Milton Miller
0 siblings, 1 reply; 34+ messages in thread
From: Michael Ellerman @ 2007-04-23 4:04 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, linux-pci
[-- Attachment #1: Type: text/plain, Size: 3035 bytes --]
On Sat, 2007-04-21 at 18:17 -0500, Milton Miller wrote:
> On Apr 19, 2007, Michael Ellerman wrote:
> > To support MSI on MPIC we need a way to reserve and allocate hardware
> > irq
> > numbers, this patch implements an allocator for that.
>
> > Index: msi-new/arch/powerpc/sysdev/mpic_msi.c
> > ===================================================================
> > --- /dev/null
> > +++ msi-new/arch/powerpc/sysdev/mpic_msi.c
> ...
> > +irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num)
> > +{
> > + unsigned long flags;
> > + int offset, order = fls(num) - 1;
>
> get_count_order would be more clear. Also it has
> a correction factor. (Applies several places).
I was hoping someone would point out something better than fls, fixed.
> > +#ifdef CONFIG_MPIC_BROKEN_U3
> > +static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
> > +{
> > + irq_hw_number_t hwirq;
> > + struct irq_host_ops *ops = mpic->irqhost->ops;
> > + struct device_node *np;
> > + int flags, index, i;
> > + struct of_irq oirq;
> > +
> > + pr_debug("mpic: found U3, guessing msi allocator setup\n");
> > +
> > + /* Reserve source numbers we know are reserved in the HW */
> > + for (i = 0; i < 8; i++) __mpic_msi_reserve_hwirq(mpic, i);
> > + for (i = 42; i < 46; i++) __mpic_msi_reserve_hwirq(mpic, i);
> > + for (i = 100; i < 105; i++) __mpic_msi_reserve_hwirq(mpic, i);
>
> More lines please.
>
> > +#else
> > +static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) { return -1;
> > }
>
> and here.
Blank lines aren't free you know!
>
> > + if (len % 8 != 0) {
> > + printk(KERN_WARNING "mpic: Malformed msi-available-ranges "
> > + "property on %s\n", mpic->of_node->full_name);
> > + return -EINVAL;
> > + }
> > +
> > + bitmap_allocate_region(mpic->hwirq_bitmap, 0,
> > + fls(mpic->irq_count) - 1);
> > +
> > + /* Format is: (<u32 start> <u32 count>)+ */
> > + len /= sizeof(u32);
> > + for (i = 0; i < len / 2; i++, p += 2)
>
> how about just dividing by the calculated 8 above? or use
> count = len / 8.
I'm not sure I follow. If you can think of a clearer way I'm all ears,
or are you just trying to save a divide :)
>
> > + mpic_msi_free_hwirqs(mpic, *p, *(p + 1));
> > +
> > + return 0;
> > +}
> > +
> > +int mpic_msi_init_allocator(struct mpic *mpic)
> > +{
> > + int rc, size;
> > +
> > + BUG_ON(mpic->hwirq_bitmap);
> > + spin_lock_init(&mpic->bitmap_lock);
> > +
> > + size = mpic->irq_count / 8;
> > + pr_debug("mpic: allocator bitmap size is 0x%x bytes\n", size);
>
> BITS_TO_LONGS() * sizeof(long). We need to round up to longs to
> use bitmask_*, especially being a big endian architecture.
Eww, sorry that's horrible. Fixed.
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 [flat|nested] 34+ messages in thread* Re: [PATCH 6/7] MPIC MSI allocator
2007-04-23 4:04 ` Michael Ellerman
@ 2007-04-23 6:20 ` Milton Miller
0 siblings, 0 replies; 34+ messages in thread
From: Milton Miller @ 2007-04-23 6:20 UTC (permalink / raw)
To: michael; +Cc: linuxppc-dev, linux-pci
On Apr 22, 2007, at 11:04 PM, Michael Ellerman wrote:
> On Sat, 2007-04-21 at 18:17 -0500, Milton Miller wrote:
>> On Apr 19, 2007, Michael Ellerman wrote:
>>> To support MSI on MPIC we need a way to reserve and allocate hardware
>>> irq
>>> numbers, this patch implements an allocator for that.
>>> + /* Reserve source numbers we know are reserved in the HW */
>>> + for (i = 0; i < 8; i++) __mpic_msi_reserve_hwirq(mpic, i);
>>> + for (i = 42; i < 46; i++) __mpic_msi_reserve_hwirq(mpic, i);
>>> + for (i = 100; i < 105; i++) __mpic_msi_reserve_hwirq(mpic, i);
>>
>> More lines please.
>>
>>> +#else
>>> +static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) { return
>>> -1;
>>> }
>>
>> and here.
>
> Blank lines aren't free you know!
I didn't ask for any blank ones, so you can keep the bill. :-)
>>
>>> + if (len % 8 != 0) {
Here you use 8 as the size of the element to process.
>>> + printk(KERN_WARNING "mpic: Malformed msi-available-ranges "
>>> + "property on %s\n", mpic->of_node->full_name);
>>> + return -EINVAL;
>>> + }
>>> +
>>> + bitmap_allocate_region(mpic->hwirq_bitmap, 0,
>>> + fls(mpic->irq_count) - 1);
>>> +
>>> + /* Format is: (<u32 start> <u32 count>)+ */
>>> + len /= sizeof(u32);
Here you hide a divide by 4 and follow with divide by 2.
>>> + for (i = 0; i < len / 2; i++, p += 2)
>>
>> how about just dividing by the calculated 8 above? or use
>> count = len / 8.
>
> I'm not sure I follow. If you can think of a clearer way I'm all ears,
> or are you just trying to save a divide :)
I'm saying that it doesn't make sense to do both of the above.
I'd move the comment on being pairs of cells to before the
if () EINVAL then follow immediately with the divide. If you
think that hides length being adjusted then I was optionally
suggesting making a new variable count to use in the for loop.
Actually, since i isn't used in the loop you could just
increment i by 8 while < len, and save both divides.
milton
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 6/7] MPIC MSI allocator
2007-04-19 7:35 ` [PATCH 6/7] MPIC MSI allocator Michael Ellerman
2007-04-21 23:17 ` Milton Miller
@ 2007-04-23 3:50 ` Olof Johansson
2007-04-23 3:53 ` Michael Ellerman
2007-04-24 1:29 ` Benjamin Herrenschmidt
1 sibling, 2 replies; 34+ messages in thread
From: Olof Johansson @ 2007-04-23 3:50 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, linux-pci
On Thu, Apr 19, 2007 at 05:35:28PM +1000, Michael Ellerman wrote:
> To support MSI on MPIC we need a way to reserve and allocate hardware irq
> numbers, this patch implements an allocator for that.
>
> New firmware platforms must define a "msi-available-ranges" property on their
> MPIC node for MSI to work. For BROKEN_U3 we do a best-guess setup.
It's time to rename BROKEN_U3. It used to be the config option to enable
a few workarounds, but now it's used to select whenever there's a U3 in
the system. Care to do it in the scope of this patch set?
> Index: msi-new/include/asm-powerpc/mpic.h
> ===================================================================
> --- msi-new.orig/include/asm-powerpc/mpic.h
> +++ msi-new/include/asm-powerpc/mpic.h
> @@ -292,6 +292,11 @@ struct mpic
> u32 *hw_set;
> #endif
>
> +#ifdef CONFIG_PCI_MSI
> + spinlock_t bitmap_lock;
> + unsigned long *hwirq_bitmap;
> +#endif
Besides the #ifdef there's nothing in the name that indicates that it's
used for msi. Better names could be useful.
> @@ -440,5 +445,11 @@ void mpic_set_clk_ratio(struct mpic *mpi
> /* Enable/Disable EPIC serial interrupt mode */
> void mpic_set_serial_int(struct mpic *mpic, int enable);
>
> +#ifdef CONFIG_PCI_MSI
> +extern int mpic_msi_init_allocator(struct mpic *mpic);
> +extern irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num);
> +extern void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num);
> +#endif
These should go in mpic.h instead.
-Olof
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 6/7] MPIC MSI allocator
2007-04-23 3:50 ` Olof Johansson
@ 2007-04-23 3:53 ` Michael Ellerman
2007-04-24 1:29 ` Benjamin Herrenschmidt
1 sibling, 0 replies; 34+ messages in thread
From: Michael Ellerman @ 2007-04-23 3:53 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, linux-pci
[-- Attachment #1: Type: text/plain, Size: 2213 bytes --]
On Sun, 2007-04-22 at 22:50 -0500, Olof Johansson wrote:
> On Thu, Apr 19, 2007 at 05:35:28PM +1000, Michael Ellerman wrote:
> > To support MSI on MPIC we need a way to reserve and allocate hardware irq
> > numbers, this patch implements an allocator for that.
> >
> > New firmware platforms must define a "msi-available-ranges" property on their
> > MPIC node for MSI to work. For BROKEN_U3 we do a best-guess setup.
>
> It's time to rename BROKEN_U3. It used to be the config option to enable
> a few workarounds, but now it's used to select whenever there's a U3 in
> the system. Care to do it in the scope of this patch set?
Yeah it's pretty ugly. I guess I can do it. Got an idea for a better
name? MPIC_HT?
> > Index: msi-new/include/asm-powerpc/mpic.h
> > ===================================================================
> > --- msi-new.orig/include/asm-powerpc/mpic.h
> > +++ msi-new/include/asm-powerpc/mpic.h
> > @@ -292,6 +292,11 @@ struct mpic
> > u32 *hw_set;
> > #endif
> >
> > +#ifdef CONFIG_PCI_MSI
> > + spinlock_t bitmap_lock;
> > + unsigned long *hwirq_bitmap;
> > +#endif
>
> Besides the #ifdef there's nothing in the name that indicates that it's
> used for msi. Better names could be useful.
True. Although, it doesn't necessarily have anything to do with MSI,
it's just a bitmap of hwirqs that are used/free. As it happens we only
need it when we're doing MSI though.
>
> > @@ -440,5 +445,11 @@ void mpic_set_clk_ratio(struct mpic *mpi
> > /* Enable/Disable EPIC serial interrupt mode */
> > void mpic_set_serial_int(struct mpic *mpic, int enable);
> >
> > +#ifdef CONFIG_PCI_MSI
> > +extern int mpic_msi_init_allocator(struct mpic *mpic);
> > +extern irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num);
> > +extern void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num);
> > +#endif
>
> These should go in mpic.h instead.
Yep.
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 [flat|nested] 34+ messages in thread
* Re: [PATCH 6/7] MPIC MSI allocator
2007-04-23 3:50 ` Olof Johansson
2007-04-23 3:53 ` Michael Ellerman
@ 2007-04-24 1:29 ` Benjamin Herrenschmidt
2007-04-24 9:26 ` Segher Boessenkool
1 sibling, 1 reply; 34+ messages in thread
From: Benjamin Herrenschmidt @ 2007-04-24 1:29 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, linux-pci
> It's time to rename BROKEN_U3. It used to be the config option to enable
> a few workarounds, but now it's used to select whenever there's a U3 in
> the system. Care to do it in the scope of this patch set?
Not really.... first gen G5s don't use that :-) It's wether the MPIC is
part of U3/U4 -and- is used as a primary HT PIC.
Ben.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 6/7] MPIC MSI allocator
2007-04-24 1:29 ` Benjamin Herrenschmidt
@ 2007-04-24 9:26 ` Segher Boessenkool
2007-04-24 9:39 ` Benjamin Herrenschmidt
0 siblings, 1 reply; 34+ messages in thread
From: Segher Boessenkool @ 2007-04-24 9:26 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: Olof Johansson, linuxppc-dev, linux-pci
>> It's time to rename BROKEN_U3. It used to be the config option to
>> enable
>> a few workarounds, but now it's used to select whenever there's a U3
>> in
>> the system. Care to do it in the scope of this patch set?
>
> Not really.... first gen G5s don't use that :-) It's wether the MPIC is
> part of U3/U4 -and- is used as a primary HT PIC.
Not really... It is whether the HT-to-MPIC interface
on the U3/U4 has the "feature" that ack-required
interrupts coming in over HT need to be acked by hand.
First-gen G5's need that just as well, they just don't
have such interrupts on the default system configuration,
as far as I remember.
Segher
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 6/7] MPIC MSI allocator
2007-04-24 9:26 ` Segher Boessenkool
@ 2007-04-24 9:39 ` Benjamin Herrenschmidt
2007-04-24 9:44 ` Segher Boessenkool
0 siblings, 1 reply; 34+ messages in thread
From: Benjamin Herrenschmidt @ 2007-04-24 9:39 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: Olof Johansson, linuxppc-dev, linux-pci
On Tue, 2007-04-24 at 11:26 +0200, Segher Boessenkool wrote:
> >> It's time to rename BROKEN_U3. It used to be the config option to
> >> enable
> >> a few workarounds, but now it's used to select whenever there's a U3
> >> in
> >> the system. Care to do it in the scope of this patch set?
> >
> > Not really.... first gen G5s don't use that :-) It's wether the MPIC is
> > part of U3/U4 -and- is used as a primary HT PIC.
>
> Not really... It is whether the HT-to-MPIC interface
> on the U3/U4 has the "feature" that ack-required
> interrupts coming in over HT need to be acked by hand.
>
> First-gen G5's need that just as well, they just don't
> have such interrupts on the default system configuration,
> as far as I remember.
They didn't have an HT APIC or if they had one, they didn't enable it
(they probably did in the tunnel). They didn't use the U3 MPIC as an HT
IRQ master, thus it's irrelevant. Anyway, there is no point in this
discussion :-)
Ben.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 6/7] MPIC MSI allocator
2007-04-24 9:39 ` Benjamin Herrenschmidt
@ 2007-04-24 9:44 ` Segher Boessenkool
2007-04-24 9:51 ` Benjamin Herrenschmidt
0 siblings, 1 reply; 34+ messages in thread
From: Segher Boessenkool @ 2007-04-24 9:44 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: Olof Johansson, linuxppc-dev, linux-pci
>> First-gen G5's need that just as well, they just don't
>> have such interrupts on the default system configuration,
>> as far as I remember.
>
> They didn't have an HT APIC or if they had one, they didn't enable it
> (they probably did in the tunnel).
Yes, the two HT APICs on the tunnel were enabled.
> They didn't use the U3 MPIC as an HT
> IRQ master, thus it's irrelevant.
They did for the plugin PCI-X slots (well, it's chained
to another MPIC, but you still need the workaround).
> Anyway, there is no point in this
> discussion :-)
Yeah, the new name for CONFIG_BROKEN_U3 is fine
no matter what :-)
Segher
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 6/7] MPIC MSI allocator
2007-04-24 9:44 ` Segher Boessenkool
@ 2007-04-24 9:51 ` Benjamin Herrenschmidt
0 siblings, 0 replies; 34+ messages in thread
From: Benjamin Herrenschmidt @ 2007-04-24 9:51 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: Olof Johansson, linuxppc-dev, linux-pci
On Tue, 2007-04-24 at 11:44 +0200, Segher Boessenkool wrote:
> >> First-gen G5's need that just as well, they just don't
> >> have such interrupts on the default system configuration,
> >> as far as I remember.
> >
> > They didn't have an HT APIC or if they had one, they didn't enable it
> > (they probably did in the tunnel).
>
> Yes, the two HT APICs on the tunnel were enabled.
>
> > They didn't use the U3 MPIC as an HT
> > IRQ master, thus it's irrelevant.
>
> They did for the plugin PCI-X slots (well, it's chained
> to another MPIC, but you still need the workaround).
No you didn't. The slots IRQ lines were physically routed to GPIOs on
the southbridge MPIC. The -only- thing the northbridge MPIC was useful
for was the NB internal interrupts (like the i2c one).
> > Anyway, there is no point in this
> > discussion :-)
>
> Yeah, the new name for CONFIG_BROKEN_U3 is fine
> no matter what :-)
>
>
> Segher
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH 7/7] MPIC MSI backend
2007-04-19 7:35 [PATCH 1/7] Rip out the existing powerpc msi stubs Michael Ellerman
` (4 preceding siblings ...)
2007-04-19 7:35 ` [PATCH 6/7] MPIC MSI allocator Michael Ellerman
@ 2007-04-19 7:35 ` Michael Ellerman
2007-04-20 8:40 ` Segher Boessenkool
2007-04-21 23:17 ` Milton Miller
5 siblings, 2 replies; 34+ messages in thread
From: Michael Ellerman @ 2007-04-19 7:35 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-pci
MPIC MSI backend. Based on code from Segher, heavily hacked by me.
Renamed to mpic_htmsi, as it only deals with MSI over Hypertransport.
We need our own irq_chip so that we can do MSI masking/unmasking on
the device itself. We also need to mask explicitly on shutdown to make
sure we don't get bitten by lazy-disable semantics.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/sysdev/Makefile | 1
arch/powerpc/sysdev/mpic.c | 14 +-
arch/powerpc/sysdev/mpic.h | 9 +
arch/powerpc/sysdev/mpic_htmsi.c | 185 +++++++++++++++++++++++++++++++++++++++
4 files changed, 203 insertions(+), 6 deletions(-)
Index: msi-new/arch/powerpc/sysdev/Makefile
===================================================================
--- msi-new.orig/arch/powerpc/sysdev/Makefile
+++ msi-new/arch/powerpc/sysdev/Makefile
@@ -4,6 +4,7 @@ endif
mpic-obj-y := mpic.o
mpic-obj-$(CONFIG_PCI_MSI) += mpic_msi.o
+mpic-obj-$(CONFIG_PCI_MSI) += mpic_htmsi.o
obj-$(CONFIG_MPIC) += $(mpic-obj-y)
obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
Index: msi-new/arch/powerpc/sysdev/mpic.c
===================================================================
--- msi-new.orig/arch/powerpc/sysdev/mpic.c
+++ msi-new/arch/powerpc/sysdev/mpic.c
@@ -606,7 +606,7 @@ static irqreturn_t mpic_ipi_action(int i
*/
-static void mpic_unmask_irq(unsigned int irq)
+void mpic_unmask_irq(unsigned int irq)
{
unsigned int loops = 100000;
struct mpic *mpic = mpic_from_irq(irq);
@@ -626,7 +626,7 @@ static void mpic_unmask_irq(unsigned int
} while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK);
}
-static void mpic_mask_irq(unsigned int irq)
+void mpic_mask_irq(unsigned int irq)
{
unsigned int loops = 100000;
struct mpic *mpic = mpic_from_irq(irq);
@@ -647,7 +647,7 @@ static void mpic_mask_irq(unsigned int i
} while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK));
}
-static void mpic_end_irq(unsigned int irq)
+void mpic_end_irq(unsigned int irq)
{
struct mpic *mpic = mpic_from_irq(irq);
@@ -780,7 +780,7 @@ static unsigned int mpic_type_to_vecpri(
}
}
-static int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
+int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
{
struct mpic *mpic = mpic_from_irq(virq);
unsigned int src = mpic_irq_to_hw(virq);
@@ -1191,8 +1191,10 @@ void __init mpic_init(struct mpic *mpic)
/* Do the HT PIC fixups on U3 broken mpic */
DBG("MPIC flags: %x\n", mpic->flags);
- if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY))
- mpic_scan_ht_pics(mpic);
+ if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY)) {
+ mpic_scan_ht_pics(mpic);
+ mpic_htmsi_init(mpic);
+ }
for (i = 0; i < mpic->num_sources; i++) {
/* start with vector = source number, and masked */
Index: msi-new/arch/powerpc/sysdev/mpic.h
===================================================================
--- msi-new.orig/arch/powerpc/sysdev/mpic.h
+++ msi-new/arch/powerpc/sysdev/mpic.h
@@ -11,14 +11,23 @@
*
*/
+#include <linux/irq.h>
+
#ifdef CONFIG_PCI_MSI
extern void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq);
+extern int mpic_htmsi_init(struct mpic *mpic);
#else
static inline void mpic_msi_reserve_hwirq(struct mpic *mpic,
irq_hw_number_t hwirq)
{
return;
}
+static inline int mpic_htmsi_init(struct mpic *mpic) { return -1; }
#endif
+extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
+extern void mpic_end_irq(unsigned int irq);
+extern void mpic_mask_irq(unsigned int irq);
+extern void mpic_unmask_irq(unsigned int irq);
+
#endif /* _POWERPC_SYSDEV_MPIC_H */
Index: msi-new/arch/powerpc/sysdev/mpic_htmsi.c
===================================================================
--- /dev/null
+++ msi-new/arch/powerpc/sysdev/mpic_htmsi.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2006, Segher Boessenkool, IBM Corporation.
+ * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/bootmem.h>
+#include <linux/msi.h>
+#include <asm/mpic.h>
+#include <asm/prom.h>
+#include <asm/hw_irq.h>
+#include <asm/ppc-pci.h>
+
+#include "mpic.h"
+
+/* A bit ugly, can we get this from the pci_dev somehow? */
+static struct mpic *msi_mpic;
+
+static void mpic_htmsi_mask_irq(unsigned int irq)
+{
+ mask_msi_irq(irq);
+ mpic_mask_irq(irq);
+}
+
+static void mpic_htmsi_unmask_irq(unsigned int irq)
+{
+ mpic_unmask_irq(irq);
+ unmask_msi_irq(irq);
+}
+
+static struct irq_chip mpic_htmsi_chip = {
+ .shutdown = mpic_htmsi_mask_irq,
+ .mask = mpic_htmsi_mask_irq,
+ .unmask = mpic_htmsi_unmask_irq,
+ .eoi = mpic_end_irq,
+ .set_type = mpic_set_irq_type,
+ .typename = "MPIC-HTMSI",
+};
+
+static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos)
+{
+ u8 flags;
+ u32 tmp;
+ u64 addr;
+
+ pci_read_config_byte(pdev, pos + HT_MSI_FLAGS, &flags);
+
+ if (flags & HT_MSI_FLAGS_FIXED)
+ return HT_MSI_FIXED_ADDR;
+
+ pci_read_config_dword(pdev, pos + HT_MSI_ADDR_LO, &tmp);
+ addr = tmp & HT_MSI_ADDR_LO_MASK;
+ pci_read_config_dword(pdev, pos + HT_MSI_ADDR_HI, &tmp);
+ addr = addr | ((u64)tmp << 32);
+
+ return addr;
+}
+
+static u64 find_ht_magic_addr(struct pci_dev *pdev)
+{
+ struct pci_bus *bus;
+ unsigned int pos;
+
+ for (bus = pdev->bus; bus; bus = bus->parent) {
+ pos = pci_find_ht_capability(bus->self, HT_CAPTYPE_MSI_MAPPING);
+ if (pos)
+ return read_ht_magic_addr(bus->self, pos);
+ }
+
+ return 0;
+}
+
+static int htmsi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
+{
+ if (type == PCI_CAP_ID_MSIX)
+ pr_debug("htmsi: MSI-X untested, trying anyway.\n");
+
+ /* If we can't find a magic address then MSI ain't gonna work */
+ if (find_ht_magic_addr(pdev) == 0) {
+ pr_debug("htmsi: no magic address found for %s\n",
+ pci_name(pdev));
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static void htmsi_teardown_msi_irqs(struct pci_dev *pdev)
+{
+ struct msi_desc *entry;
+
+ list_for_each_entry(entry, &pdev->msi_list, list) {
+ if (entry->irq == NO_IRQ)
+ continue;
+
+ set_irq_msi(entry->irq, NULL);
+ mpic_msi_free_hwirqs(msi_mpic, virq_to_hw(entry->irq), 1);
+ irq_dispose_mapping(entry->irq);
+ }
+
+ return;
+}
+
+static void htmsi_compose_msi_msg(struct pci_dev *pdev, int virq,
+ struct msi_msg *msg)
+{
+ u64 addr;
+
+ addr = find_ht_magic_addr(pdev);
+ msg->address_lo = addr & 0xFFFFFFFF;
+ msg->address_hi = addr >> 32;
+ msg->data = virq_to_hw(virq);
+
+ pr_debug("htmsi: allocated virq 0x%x (hw 0x%lx) at address 0x%lx\n",
+ virq, virq_to_hw(virq), addr);
+}
+
+static int htmsi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+{
+ irq_hw_number_t hwirq;
+ int rc;
+ unsigned int virq;
+ struct msi_desc *entry;
+ struct msi_msg msg;
+
+ list_for_each_entry(entry, &pdev->msi_list, list) {
+ hwirq = mpic_msi_alloc_hwirqs(msi_mpic, 1);
+ if (hwirq < 0) {
+ rc = hwirq;
+ pr_debug("htmsi: failed allocating hwirq\n");
+ goto out_free;
+ }
+
+ virq = irq_create_mapping(msi_mpic->irqhost, hwirq);
+ if (virq == NO_IRQ) {
+ pr_debug("htmsi: failed mapping hwirq 0x%lx\n", hwirq);
+ mpic_msi_free_hwirqs(msi_mpic, hwirq, 1);
+ rc = -ENOSPC;
+ goto out_free;
+ }
+
+ set_irq_msi(virq, entry);
+ set_irq_chip(virq, &mpic_htmsi_chip);
+ set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
+
+ htmsi_compose_msi_msg(pdev, virq, &msg);
+ write_msi_msg(virq, &msg);
+
+ hwirq++;
+ }
+
+ return 0;
+
+ out_free:
+ htmsi_teardown_msi_irqs(pdev);
+ return rc;
+}
+
+int mpic_htmsi_init(struct mpic *mpic)
+{
+ int rc;
+
+ rc = mpic_msi_init_allocator(mpic);
+ if (rc) {
+ pr_debug("htmsi: Error allocating bitmap!\n");
+ return rc;
+ }
+
+ pr_debug("htmsi: Registering MPIC MSI callbacks.\n");
+
+ BUG_ON(msi_mpic);
+ msi_mpic = mpic;
+
+ ppc_md.setup_msi_irqs = htmsi_setup_msi_irqs;
+ ppc_md.teardown_msi_irqs = htmsi_teardown_msi_irqs;
+ ppc_md.msi_check_device = htmsi_msi_check_device;
+
+ return 0;
+}
^ permalink raw reply [flat|nested] 34+ messages in thread* Re: [PATCH 7/7] MPIC MSI backend
2007-04-19 7:35 ` [PATCH 7/7] MPIC MSI backend Michael Ellerman
@ 2007-04-20 8:40 ` Segher Boessenkool
2007-04-20 14:39 ` Michael Ellerman
2007-04-21 23:17 ` Milton Miller
1 sibling, 1 reply; 34+ messages in thread
From: Segher Boessenkool @ 2007-04-20 8:40 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, linux-pci
> MPIC MSI backend. Based on code from Segher, heavily hacked by me.
I guess I'll have to do
Signed-off-by: Segher Boessenkool <segher@kernel.crashing.org>
again, you keep losing it :-)
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Segher
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 7/7] MPIC MSI backend
2007-04-20 8:40 ` Segher Boessenkool
@ 2007-04-20 14:39 ` Michael Ellerman
0 siblings, 0 replies; 34+ messages in thread
From: Michael Ellerman @ 2007-04-20 14:39 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: linuxppc-dev, linux-pci
[-- Attachment #1: Type: text/plain, Size: 661 bytes --]
On Fri, 2007-04-20 at 10:40 +0200, Segher Boessenkool wrote:
> > MPIC MSI backend. Based on code from Segher, heavily hacked by me.
>
> I guess I'll have to do
>
> Signed-off-by: Segher Boessenkool <segher@kernel.crashing.org>
>
> again, you keep losing it :-)
Oh sorry, I do keep losing it. Actually looking at it closer there isn't
any of your code left, except in spirit I guess :)
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 [flat|nested] 34+ messages in thread
* Re: [PATCH 7/7] MPIC MSI backend
2007-04-19 7:35 ` [PATCH 7/7] MPIC MSI backend Michael Ellerman
2007-04-20 8:40 ` Segher Boessenkool
@ 2007-04-21 23:17 ` Milton Miller
2007-04-22 7:06 ` Segher Boessenkool
2007-04-23 3:45 ` Michael Ellerman
1 sibling, 2 replies; 34+ messages in thread
From: Milton Miller @ 2007-04-21 23:17 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, linux-pci
On Apr 19, 2007, Michael Ellerman wrote:
> MPIC MSI backend. Based on code from Segher, heavily hacked by me.
> Renamed to mpic_htmsi, as it only deals with MSI over Hypertransport.
...
> Index: msi-new/arch/powerpc/sysdev/Makefile
> ===================================================================
> --- msi-new.orig/arch/powerpc/sysdev/Makefile
> +++ msi-new/arch/powerpc/sysdev/Makefile
> @@ -4,6 +4,7 @@ endif
>
> mpic-obj-y := mpic.o
> mpic-obj-$(CONFIG_PCI_MSI) += mpic_msi.o
> +mpic-obj-$(CONFIG_PCI_MSI) += mpic_htmsi.o
> obj-$(CONFIG_MPIC) += $(mpic-obj-y)
This is overly complicated. You aren't going to be making this
a seperate link object anyways. It should end up somehting like
mpic-msi-$(CONFIG_PCI_MSI) := mpic_msi.o mpic_htmsi.o
obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-y)
> -static void mpic_unmask_irq(unsigned int irq)
> +void mpic_unmask_irq(unsigned int irq)
...
> -static void mpic_mask_irq(unsigned int irq)
> +void mpic_mask_irq(unsigned int irq)
...
Ok mpic.c is big enough already.
> Index: msi-new/arch/powerpc/sysdev/mpic.h
> ===================================================================
> --- msi-new.orig/arch/powerpc/sysdev/mpic.h
> +++ msi-new/arch/powerpc/sysdev/mpic.h
> @@ -11,14 +11,23 @@
> *
> */
>
> +#include <linux/irq.h>
> +
Why do you need this now? You already had uses of irq_ht_umber_t
and struct mpic. Unless this should be in the earlier patch?
> #ifdef CONFIG_PCI_MSI
> extern void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t
> hwirq);
> +extern int mpic_htmsi_init(struct mpic *mpic);
> #else
> static inline void mpic_msi_reserve_hwirq(struct mpic *mpic,
> irq_hw_number_t hwirq)
> {
> return;
> }
> +static inline int mpic_htmsi_init(struct mpic *mpic) { return -1; }
more lines please
> #endif
>
> +extern int mpic_set_irq_type(unsigned int virq, unsigned int
> flow_type);
> +extern void mpic_end_irq(unsigned int irq);
> +extern void mpic_mask_irq(unsigned int irq);
> +extern void mpic_unmask_irq(unsigned int irq);
> +
> #endif /* _POWERPC_SYSDEV_MPIC_H */
> Index: msi-new/arch/powerpc/sysdev/mpic_htmsi.c
I just stumbled across drivers/pci/htirq.c, is that of any use?
> +
> +int mpic_htmsi_init(struct mpic *mpic)
> +{
> + int rc;
> +
> + rc = mpic_msi_init_allocator(mpic);
> + if (rc) {
> + pr_debug("htmsi: Error allocating bitmap!\n");
> + return rc;
> + }
> +
> + pr_debug("htmsi: Registering MPIC MSI callbacks.\n");
> +
> + BUG_ON(msi_mpic);
> + msi_mpic = mpic;
> +
> + ppc_md.setup_msi_irqs = htmsi_setup_msi_irqs;
> + ppc_md.teardown_msi_irqs = htmsi_teardown_msi_irqs;
> + ppc_md.msi_check_device = htmsi_msi_check_device;
Unlike the rtas patch, this one didn't advertise it was
going to set the arch hooks unconditionally.
milton
^ permalink raw reply [flat|nested] 34+ messages in thread* Re: [PATCH 7/7] MPIC MSI backend
2007-04-21 23:17 ` Milton Miller
@ 2007-04-22 7:06 ` Segher Boessenkool
2007-04-22 19:30 ` Olof Johansson
2007-04-23 3:45 ` Michael Ellerman
1 sibling, 1 reply; 34+ messages in thread
From: Segher Boessenkool @ 2007-04-22 7:06 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, linux-pci
>> Index: msi-new/arch/powerpc/sysdev/mpic_htmsi.c
>
> I just stumbled across drivers/pci/htirq.c, is that of any use?
That file deals with setting up HT APICs. On all
current PowerPC systems with HT this is done (and
done correctly) by the firmware; there is no reason
to change any of it in the kernel.
mpic_htmsi deals with MSIs that come in over hypertransport
to the MPIC on CPC925/CPC945; this has nothing to
do with HT APICs.
Segher
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 7/7] MPIC MSI backend
2007-04-22 7:06 ` Segher Boessenkool
@ 2007-04-22 19:30 ` Olof Johansson
2007-04-23 4:24 ` Michael Ellerman
2007-04-23 8:24 ` Segher Boessenkool
0 siblings, 2 replies; 34+ messages in thread
From: Olof Johansson @ 2007-04-22 19:30 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: linuxppc-dev, linux-pci, Milton Miller
On Sun, Apr 22, 2007 at 09:06:15AM +0200, Segher Boessenkool wrote:
> mpic_htmsi deals with MSIs that come in over hypertransport
> to the MPIC on CPC925/CPC945; this has nothing to
> do with HT APICs.
Maybe it should be named mpic_cpc9x5msi instead?
-Olof
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 7/7] MPIC MSI backend
2007-04-22 19:30 ` Olof Johansson
@ 2007-04-23 4:24 ` Michael Ellerman
2007-04-23 8:24 ` Segher Boessenkool
1 sibling, 0 replies; 34+ messages in thread
From: Michael Ellerman @ 2007-04-23 4:24 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, linux-pci, Milton Miller
[-- Attachment #1: Type: text/plain, Size: 621 bytes --]
On Sun, 2007-04-22 at 14:30 -0500, Olof Johansson wrote:
> On Sun, Apr 22, 2007 at 09:06:15AM +0200, Segher Boessenkool wrote:
>
> > mpic_htmsi deals with MSIs that come in over hypertransport
> > to the MPIC on CPC925/CPC945; this has nothing to
> > do with HT APICs.
>
> Maybe it should be named mpic_cpc9x5msi instead?
Yeah, seems fair enough.
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 [flat|nested] 34+ messages in thread
* Re: [PATCH 7/7] MPIC MSI backend
2007-04-22 19:30 ` Olof Johansson
2007-04-23 4:24 ` Michael Ellerman
@ 2007-04-23 8:24 ` Segher Boessenkool
2007-04-23 8:31 ` Michael Ellerman
1 sibling, 1 reply; 34+ messages in thread
From: Segher Boessenkool @ 2007-04-23 8:24 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, linux-pci, Milton Miller
>> mpic_htmsi deals with MSIs that come in over hypertransport
>> to the MPIC on CPC925/CPC945; this has nothing to
>> do with HT APICs.
>
> Maybe it should be named mpic_cpc9x5msi instead?
Yeah probably, esp. since there are more MSI sources
on those chips, not just HT; and if support for those
sources gets added later, it should go to this file :-)
Segher
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 7/7] MPIC MSI backend
2007-04-23 8:24 ` Segher Boessenkool
@ 2007-04-23 8:31 ` Michael Ellerman
2007-04-23 17:33 ` Segher Boessenkool
0 siblings, 1 reply; 34+ messages in thread
From: Michael Ellerman @ 2007-04-23 8:31 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: Olof Johansson, linuxppc-dev, linux-pci, Milton Miller
[-- Attachment #1: Type: text/plain, Size: 889 bytes --]
On Mon, 2007-04-23 at 10:24 +0200, Segher Boessenkool wrote:
> >> mpic_htmsi deals with MSIs that come in over hypertransport
> >> to the MPIC on CPC925/CPC945; this has nothing to
> >> do with HT APICs.
> >
> > Maybe it should be named mpic_cpc9x5msi instead?
>
> Yeah probably, esp. since there are more MSI sources
> on those chips, not just HT; and if support for those
> sources gets added later, it should go to this file :-)
Actually I think I'll call it mpic_u3_msi.c, which although not quite as
accurate as cpc9x5, is more inline with the rest of the code that refers
to U3 - which really means U3/U4.
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 [flat|nested] 34+ messages in thread
* Re: [PATCH 7/7] MPIC MSI backend
2007-04-23 8:31 ` Michael Ellerman
@ 2007-04-23 17:33 ` Segher Boessenkool
0 siblings, 0 replies; 34+ messages in thread
From: Segher Boessenkool @ 2007-04-23 17:33 UTC (permalink / raw)
To: michael; +Cc: Olof Johansson, linuxppc-dev, linux-pci, Milton Miller
>>>> mpic_htmsi deals with MSIs that come in over hypertransport
>>>> to the MPIC on CPC925/CPC945; this has nothing to
>>>> do with HT APICs.
>>>
>>> Maybe it should be named mpic_cpc9x5msi instead?
>>
>> Yeah probably, esp. since there are more MSI sources
>> on those chips, not just HT; and if support for those
>> sources gets added later, it should go to this file :-)
>
> Actually I think I'll call it mpic_u3_msi.c, which although not quite
> as
> accurate as cpc9x5, is more inline with the rest of the code that
> refers
> to U3 - which really means U3/U4.
Yeah, good plan. It's a nicer name anyway :-)
Segher
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 7/7] MPIC MSI backend
2007-04-21 23:17 ` Milton Miller
2007-04-22 7:06 ` Segher Boessenkool
@ 2007-04-23 3:45 ` Michael Ellerman
1 sibling, 0 replies; 34+ messages in thread
From: Michael Ellerman @ 2007-04-23 3:45 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, linux-pci
[-- Attachment #1: Type: text/plain, Size: 3020 bytes --]
On Sat, 2007-04-21 at 18:17 -0500, Milton Miller wrote:
> On Apr 19, 2007, Michael Ellerman wrote:
> > MPIC MSI backend. Based on code from Segher, heavily hacked by me.
> > Renamed to mpic_htmsi, as it only deals with MSI over Hypertransport.
> ...
> > Index: msi-new/arch/powerpc/sysdev/Makefile
> > ===================================================================
> > --- msi-new.orig/arch/powerpc/sysdev/Makefile
> > +++ msi-new/arch/powerpc/sysdev/Makefile
> > @@ -4,6 +4,7 @@ endif
> >
> > mpic-obj-y := mpic.o
> > mpic-obj-$(CONFIG_PCI_MSI) += mpic_msi.o
> > +mpic-obj-$(CONFIG_PCI_MSI) += mpic_htmsi.o
> > obj-$(CONFIG_MPIC) += $(mpic-obj-y)
>
> This is overly complicated. You aren't going to be making this
> a seperate link object anyways. It should end up somehting like
>
> mpic-msi-$(CONFIG_PCI_MSI) := mpic_msi.o mpic_htmsi.o
> obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-y)
Fixed.
> > -static void mpic_unmask_irq(unsigned int irq)
> > +void mpic_unmask_irq(unsigned int irq)
> ...
> > -static void mpic_mask_irq(unsigned int irq)
> > +void mpic_mask_irq(unsigned int irq)
> ...
> Ok mpic.c is big enough already.
Yeah I tried it the other way, but it was messy.
> > Index: msi-new/arch/powerpc/sysdev/mpic.h
> > ===================================================================
> > --- msi-new.orig/arch/powerpc/sysdev/mpic.h
> > +++ msi-new/arch/powerpc/sysdev/mpic.h
> > @@ -11,14 +11,23 @@
> > *
> > */
> >
> > +#include <linux/irq.h>
> > +
>
> Why do you need this now? You already had uses of irq_ht_umber_t
> and struct mpic. Unless this should be in the earlier patch?
Cruft, removed.
> > #ifdef CONFIG_PCI_MSI
> > extern void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t
> > hwirq);
> > +extern int mpic_htmsi_init(struct mpic *mpic);
> > #else
> > static inline void mpic_msi_reserve_hwirq(struct mpic *mpic,
> > irq_hw_number_t hwirq)
> > {
> > return;
> > }
> > +static inline int mpic_htmsi_init(struct mpic *mpic) { return -1; }
>
> more lines please
OK.
> > +int mpic_htmsi_init(struct mpic *mpic)
> > +{
> > + int rc;
> > +
> > + rc = mpic_msi_init_allocator(mpic);
> > + if (rc) {
> > + pr_debug("htmsi: Error allocating bitmap!\n");
> > + return rc;
> > + }
> > +
> > + pr_debug("htmsi: Registering MPIC MSI callbacks.\n");
> > +
> > + BUG_ON(msi_mpic);
> > + msi_mpic = mpic;
> > +
> > + ppc_md.setup_msi_irqs = htmsi_setup_msi_irqs;
> > + ppc_md.teardown_msi_irqs = htmsi_teardown_msi_irqs;
> > + ppc_md.msi_check_device = htmsi_msi_check_device;
>
> Unlike the rtas patch, this one didn't advertise it was
> going to set the arch hooks unconditionally.
Yeah OK, fixed.
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 [flat|nested] 34+ messages in thread
* [PATCH 6/7] MPIC MSI allocator
2007-05-08 2:58 [PATCH 1/7] Rip out the existing powerpc msi stubs Michael Ellerman
@ 2007-05-08 2:58 ` Michael Ellerman
0 siblings, 0 replies; 34+ messages in thread
From: Michael Ellerman @ 2007-05-08 2:58 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
To support MSI on MPIC we need a way to reserve and allocate hardware irq
numbers, this patch implements an allocator for that purpose.
New firmware platforms must define a "msi-available-ranges" property on their
MPIC node for MSI to work. For U3/U4 we do a best-guess setup.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/sysdev/Makefile | 4
arch/powerpc/sysdev/mpic.c | 4
arch/powerpc/sysdev/mpic.h | 27 ++++++
arch/powerpc/sysdev/mpic_msi.c | 183 +++++++++++++++++++++++++++++++++++++++++
include/asm-powerpc/mpic.h | 5 +
5 files changed, 222 insertions(+), 1 deletion(-)
Index: msi-new/arch/powerpc/sysdev/Makefile
===================================================================
--- msi-new.orig/arch/powerpc/sysdev/Makefile
+++ msi-new/arch/powerpc/sysdev/Makefile
@@ -2,7 +2,9 @@ ifeq ($(CONFIG_PPC64),y)
EXTRA_CFLAGS += -mno-minimal-toc
endif
-obj-$(CONFIG_MPIC) += mpic.o
+mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o
+obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y)
+
obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
obj-$(CONFIG_PPC_MPC106) += grackle.o
obj-$(CONFIG_PPC_DCR) += dcr.o
Index: msi-new/arch/powerpc/sysdev/mpic.c
===================================================================
--- msi-new.orig/arch/powerpc/sysdev/mpic.c
+++ msi-new/arch/powerpc/sysdev/mpic.c
@@ -36,6 +36,8 @@
#include <asm/mpic.h>
#include <asm/smp.h>
+#include "mpic.h"
+
#ifdef DEBUG
#define DBG(fmt...) printk(fmt)
#else
@@ -879,6 +881,8 @@ static int mpic_host_map(struct irq_host
if (hw >= mpic->irq_count)
return -EINVAL;
+ mpic_msi_reserve_hwirq(mpic, hw);
+
/* Default chip */
chip = &mpic->hc_irq;
Index: msi-new/arch/powerpc/sysdev/mpic.h
===================================================================
--- /dev/null
+++ msi-new/arch/powerpc/sysdev/mpic.h
@@ -0,0 +1,27 @@
+#ifndef _POWERPC_SYSDEV_MPIC_H
+#define _POWERPC_SYSDEV_MPIC_H
+
+/*
+ * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#ifdef CONFIG_PCI_MSI
+extern void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq);
+extern int mpic_msi_init_allocator(struct mpic *mpic);
+extern irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num);
+extern void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num);
+#else
+static inline void mpic_msi_reserve_hwirq(struct mpic *mpic,
+ irq_hw_number_t hwirq)
+{
+ return;
+}
+#endif
+
+#endif /* _POWERPC_SYSDEV_MPIC_H */
Index: msi-new/arch/powerpc/sysdev/mpic_msi.c
===================================================================
--- /dev/null
+++ msi-new/arch/powerpc/sysdev/mpic_msi.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/bootmem.h>
+#include <linux/bitmap.h>
+#include <linux/msi.h>
+#include <asm/mpic.h>
+#include <asm/prom.h>
+#include <asm/hw_irq.h>
+#include <asm/ppc-pci.h>
+
+
+static void __mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
+{
+ pr_debug("mpic: reserving hwirq 0x%lx\n", hwirq);
+ bitmap_allocate_region(mpic->hwirq_bitmap, hwirq, 0);
+}
+
+void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
+{
+ unsigned long flags;
+
+ /* The mpic calls this even when there is no allocator setup */
+ if (!mpic->hwirq_bitmap)
+ return;
+
+ spin_lock_irqsave(&mpic->bitmap_lock, flags);
+ __mpic_msi_reserve_hwirq(mpic, hwirq);
+ spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
+}
+
+irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num)
+{
+ unsigned long flags;
+ int offset, order = get_count_order(num);
+
+ spin_lock_irqsave(&mpic->bitmap_lock, flags);
+ /*
+ * This is fast, but stricter than we need. We might want to add
+ * a fallback routine which does a linear search with no alignment.
+ */
+ offset = bitmap_find_free_region(mpic->hwirq_bitmap, mpic->irq_count,
+ order);
+ spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
+
+ pr_debug("mpic: allocated 0x%x (2^%d) at offset 0x%x\n",
+ num, order, offset);
+
+ return offset;
+}
+
+void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num)
+{
+ unsigned long flags;
+ int order = get_count_order(num);
+
+ pr_debug("mpic: freeing 0x%x (2^%d) at offset 0x%x\n",
+ num, order, offset);
+
+ spin_lock_irqsave(&mpic->bitmap_lock, flags);
+ bitmap_release_region(mpic->hwirq_bitmap, offset, order);
+ spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
+}
+
+#ifdef CONFIG_MPIC_U3_HT_IRQS
+static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
+{
+ irq_hw_number_t hwirq;
+ struct irq_host_ops *ops = mpic->irqhost->ops;
+ struct device_node *np;
+ int flags, index, i;
+ struct of_irq oirq;
+
+ pr_debug("mpic: found U3, guessing msi allocator setup\n");
+
+ /* Reserve source numbers we know are reserved in the HW */
+ for (i = 0; i < 8; i++)
+ __mpic_msi_reserve_hwirq(mpic, i);
+
+ for (i = 42; i < 46; i++)
+ __mpic_msi_reserve_hwirq(mpic, i);
+
+ for (i = 100; i < 105; i++)
+ __mpic_msi_reserve_hwirq(mpic, i);
+
+ np = NULL;
+ while ((np = of_find_all_nodes(np))) {
+ pr_debug("mpic: mapping hwirqs for %s\n", np->full_name);
+
+ index = 0;
+ while (of_irq_map_one(np, index++, &oirq) == 0) {
+ ops->xlate(mpic->irqhost, NULL, oirq.specifier,
+ oirq.size, &hwirq, &flags);
+ __mpic_msi_reserve_hwirq(mpic, hwirq);
+ }
+ }
+
+ return 0;
+}
+#else
+static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
+{
+ return -1;
+}
+#endif
+
+static int mpic_msi_reserve_dt_hwirqs(struct mpic *mpic)
+{
+ int i, len;
+ const u32 *p;
+
+ p = of_get_property(mpic->of_node, "msi-available-ranges", &len);
+ if (!p) {
+ pr_debug("mpic: no msi-available-ranges property found on %s\n",
+ mpic->of_node->full_name);
+ return -ENODEV;
+ }
+
+ if (len % 8 != 0) {
+ printk(KERN_WARNING "mpic: Malformed msi-available-ranges "
+ "property on %s\n", mpic->of_node->full_name);
+ return -EINVAL;
+ }
+
+ bitmap_allocate_region(mpic->hwirq_bitmap, 0,
+ get_count_order(mpic->irq_count));
+
+ /* Format is: (<u32 start> <u32 count>)+ */
+ len /= sizeof(u32);
+ for (i = 0; i < len / 2; i++, p += 2)
+ mpic_msi_free_hwirqs(mpic, *p, *(p + 1));
+
+ return 0;
+}
+
+int mpic_msi_init_allocator(struct mpic *mpic)
+{
+ int rc, size;
+
+ BUG_ON(mpic->hwirq_bitmap);
+ spin_lock_init(&mpic->bitmap_lock);
+
+ size = BITS_TO_LONGS(mpic->irq_count) * sizeof(long);
+ pr_debug("mpic: allocator bitmap size is 0x%x bytes\n", size);
+
+ if (mem_init_done)
+ mpic->hwirq_bitmap = kmalloc(size, GFP_KERNEL);
+ else
+ mpic->hwirq_bitmap = alloc_bootmem(size);
+
+ if (!mpic->hwirq_bitmap) {
+ pr_debug("mpic: ENOMEM allocating allocator bitmap!\n");
+ return -ENOMEM;
+ }
+
+ memset(mpic->hwirq_bitmap, 0, size);
+
+ rc = mpic_msi_reserve_dt_hwirqs(mpic);
+ if (rc) {
+ if (mpic->flags & MPIC_U3_HT_IRQS)
+ rc = mpic_msi_reserve_u3_hwirqs(mpic);
+
+ if (rc)
+ goto out_free;
+ }
+
+ return 0;
+
+ out_free:
+ if (mem_init_done)
+ kfree(mpic->hwirq_bitmap);
+
+ mpic->hwirq_bitmap = NULL;
+ return rc;
+}
Index: msi-new/include/asm-powerpc/mpic.h
===================================================================
--- msi-new.orig/include/asm-powerpc/mpic.h
+++ msi-new/include/asm-powerpc/mpic.h
@@ -292,6 +292,11 @@ struct mpic
u32 *hw_set;
#endif
+#ifdef CONFIG_PCI_MSI
+ spinlock_t bitmap_lock;
+ unsigned long *hwirq_bitmap;
+#endif
+
/* link */
struct mpic *next;
};
^ permalink raw reply [flat|nested] 34+ messages in thread