* [PATCH 0/9] Powerpc MSI Implementation (.. again)
@ 2006-12-13 10:39 Michael Ellerman
2006-12-13 10:39 ` [PATCH 1/9] Add #defines for Hypertransport MSI fields Michael Ellerman
` (8 more replies)
0 siblings, 9 replies; 26+ messages in thread
From: Michael Ellerman @ 2006-12-13 10:39 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linux-pci, linuxppc-dev
MSI again, one (?) more time.
Not much left todo:
* Needs a good read to check everything makes sense
* We might want to save the irq type in the mpic ht backend
* RTAS code needs to be tested
cheers
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 1/9] Add #defines for Hypertransport MSI fields
2006-12-13 10:39 [PATCH 0/9] Powerpc MSI Implementation (.. again) Michael Ellerman
@ 2006-12-13 10:39 ` Michael Ellerman
2006-12-13 10:39 ` [PATCH 2/9] Rip out the existing powerpc msi stubs Michael Ellerman
` (7 subsequent siblings)
8 siblings, 0 replies; 26+ messages in thread
From: Michael Ellerman @ 2006-12-13 10:39 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linux-pci, linuxppc-dev
Add a few #defines for grabbing and working with the address fields
in a HT_CAPTYPE_MSI_MAPPING capability. All from the HT spec v3.00.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
include/linux/pci_regs.h | 7 +++++++
1 file changed, 7 insertions(+)
Index: msi/include/linux/pci_regs.h
===================================================================
--- msi.orig/include/linux/pci_regs.h
+++ msi/include/linux/pci_regs.h
@@ -487,6 +487,13 @@
#define HT_CAPTYPE_UNITID_CLUMP 0x90 /* Unit ID clumping */
#define HT_CAPTYPE_EXTCONF 0x98 /* Extended Configuration Space Access */
#define HT_CAPTYPE_MSI_MAPPING 0xA8 /* MSI Mapping Capability */
+#define HT_MSI_FLAGS 0x02 /* Offset to flags */
+#define HT_MSI_FLAGS_ENABLE 0x1 /* Mapping enable */
+#define HT_MSI_FLAGS_FIXED 0x2 /* Fixed mapping only */
+#define HT_MSI_FIXED_ADDR 0x00000000FEE00000ULL /* Fixed addr */
+#define HT_MSI_ADDR_LO 0x04 /* Offset to low addr bits */
+#define HT_MSI_ADDR_LO_MASK 0xFFF00000 /* Low address bit mask */
+#define HT_MSI_ADDR_HI 0x08 /* Offset to high addr bits */
#define HT_CAPTYPE_DIRECT_ROUTE 0xB0 /* Direct routing configuration */
#define HT_CAPTYPE_VCSET 0xB8 /* Virtual Channel configuration */
#define HT_CAPTYPE_ERROR_RETRY 0xC0 /* Retry on error configuration */
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 2/9] Rip out the existing powerpc msi stubs
2006-12-13 10:39 [PATCH 0/9] Powerpc MSI Implementation (.. again) Michael Ellerman
2006-12-13 10:39 ` [PATCH 1/9] Add #defines for Hypertransport MSI fields Michael Ellerman
@ 2006-12-13 10:39 ` Michael Ellerman
2006-12-13 10:39 ` [PATCH 3/9] Powerpc MSI implementation Michael Ellerman
` (6 subsequent siblings)
8 siblings, 0 replies; 26+ messages in thread
From: Michael Ellerman @ 2006-12-13 10:39 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linux-pci, linuxppc-dev
Rip out the existing powerpc msi stubs. These were the start of an
implementation based on ppc_md calls, but were never used.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/kernel/irq.c | 28 ----------------------------
include/asm-powerpc/machdep.h | 5 -----
2 files changed, 33 deletions(-)
Index: msi/arch/powerpc/kernel/irq.c
===================================================================
--- msi.orig/arch/powerpc/kernel/irq.c
+++ msi/arch/powerpc/kernel/irq.c
@@ -945,34 +945,6 @@ arch_initcall(irq_late_init);
#endif /* CONFIG_PPC_MERGE */
-#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;
-}
-EXPORT_SYMBOL(pci_enable_msi);
-
-void pci_disable_msi(struct pci_dev * pdev)
-{
- if (ppc_md.disable_msi)
- ppc_md.disable_msi(pdev);
-}
-EXPORT_SYMBOL(pci_disable_msi);
-
-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) {}
-EXPORT_SYMBOL(pci_enable_msix);
-EXPORT_SYMBOL(pci_disable_msix);
-
-#endif
-
#ifdef CONFIG_PPC64
static int __init setup_noirqdistrib(char *str)
{
Index: msi/include/asm-powerpc/machdep.h
===================================================================
--- msi.orig/include/asm-powerpc/machdep.h
+++ msi/include/asm-powerpc/machdep.h
@@ -243,11 +243,6 @@ struct machdep_calls {
*/
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] 26+ messages in thread
* [PATCH 3/9] Powerpc MSI implementation
2006-12-13 10:39 [PATCH 0/9] Powerpc MSI Implementation (.. again) Michael Ellerman
2006-12-13 10:39 ` [PATCH 1/9] Add #defines for Hypertransport MSI fields Michael Ellerman
2006-12-13 10:39 ` [PATCH 2/9] Rip out the existing powerpc msi stubs Michael Ellerman
@ 2006-12-13 10:39 ` Michael Ellerman
2006-12-13 10:39 ` [PATCH 4/9] Enable MSI on Powerpc Michael Ellerman
` (5 subsequent siblings)
8 siblings, 0 replies; 26+ messages in thread
From: Michael Ellerman @ 2006-12-13 10:39 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linux-pci, linuxppc-dev
Powerpc MSI implementation, based on a collection of "ops" callbacks.
We have to take the ops approach to accomodate RTAS, where firmware
handles almost all details of MSI setup/teardown. Bare-metal MSI
can be accomodated also.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/kernel/msi.c | 322 ++++++++++++++++++++++++++++++++++++++++++
include/asm-powerpc/machdep.h | 6
include/asm-powerpc/msi.h | 173 ++++++++++++++++++++++
include/linux/pci.h | 7
4 files changed, 508 insertions(+)
Index: msi/arch/powerpc/kernel/msi.c
===================================================================
--- /dev/null
+++ msi/arch/powerpc/kernel/msi.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2006 (C), 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.
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <asm/msi.h>
+#include <asm/machdep.h>
+
+static struct ppc_msi_ops *get_msi_ops(struct pci_dev *pdev)
+{
+ if (ppc_md.get_msi_ops)
+ return ppc_md.get_msi_ops(pdev);
+
+ return NULL;
+}
+
+/* Activated by pci=nomsi on the command line. */
+static int no_msi;
+
+void pci_no_msi(void)
+{
+ msi_debug("MSI disabled by user\n");
+ no_msi = 1;
+}
+
+
+/* msi_info helpers */
+
+static int alloc_msi_info(struct pci_dev *pdev, int num,
+ struct msix_entry *entries, int type)
+{
+ struct msi_info *info;
+ unsigned int entries_size;
+
+ entries_size = sizeof(struct msix_entry) * num;
+
+ info = kzalloc(sizeof(struct msi_info) + entries_size, GFP_KERNEL);
+ if (!info) {
+ msi_debug("kzalloc failed for %s\n", pci_name(pdev));
+ return -ENOMEM;
+ }
+
+ info->type = type;
+ info->num = num;
+ info->entries = (struct msix_entry *)(info + 1);
+ memcpy(info->entries, entries, entries_size);
+
+ BUG_ON(pdev->msi_info); /* don't leak info structs */
+ pdev->msi_info = info;
+
+ return 0;
+}
+
+static struct msi_info *get_msi_info(struct pci_dev *pdev)
+{
+ return pdev->msi_info;
+}
+
+static void free_msi_info(struct pci_dev *pdev)
+{
+ kfree(pdev->msi_info);
+ pdev->msi_info = NULL;
+}
+
+
+/* Generic helpers */
+
+static int generic_msi_enable(struct pci_dev *pdev, int nvec,
+ struct msix_entry *entries, int type)
+{
+ struct ppc_msi_ops *ops;
+ int i, rc;
+
+ if (no_msi || !pdev || !entries || !nvec || get_msi_info(pdev)) {
+ msi_debug("precondition failed for %p\n", pdev);
+ return -EINVAL;
+ }
+
+ ops = get_msi_ops(pdev);
+ if (!ops) {
+ msi_debug("no ops for %s\n", pci_name(pdev));
+ return -EINVAL;
+ }
+
+ for (i = 0; i < nvec; i++)
+ entries[i].vector = NO_IRQ;
+
+ rc = ops->check(pdev, nvec, entries, type);
+ if (rc) {
+ msi_debug("check failed (%d) for %s\n", rc, pci_name(pdev));
+ return rc;
+ }
+
+ rc = alloc_msi_info(pdev, nvec, entries, type);
+ if (rc)
+ return rc;
+
+ rc = ops->alloc(pdev, nvec, entries, type);
+ if (rc) {
+ msi_debug("alloc failed (%d) for %s\n", rc, pci_name(pdev));
+ goto out_free_info;
+ }
+
+ if (ops->enable) {
+ rc = ops->enable(pdev, nvec, entries, type);
+ if (rc) {
+ msi_debug("enable failed (%d) for %s\n", rc,
+ pci_name(pdev));
+ goto out_ops_free;
+ }
+ }
+
+ pci_intx(pdev, 0);
+
+ return 0;
+
+ out_ops_free:
+ ops->free(pdev, nvec, entries, type);
+ out_free_info:
+ free_msi_info(pdev);
+
+ return rc;
+}
+
+static int generic_msi_disable(struct pci_dev *pdev, int type)
+{
+ struct ppc_msi_ops *ops;
+ struct msi_info *info;
+
+ if (no_msi || !pdev) {
+ msi_debug("precondition failed for %p\n", pdev);
+ return -1;
+ }
+
+ info = get_msi_info(pdev);
+ if (!info) {
+ msi_debug("No info for %s\n", pci_name(pdev));
+ return -1;
+ }
+
+ ops = get_msi_ops(pdev);
+ if (!ops) {
+ msi_debug("no ops for %s\n", pci_name(pdev));
+ return -1;
+ }
+
+ if (ops->disable)
+ ops->disable(pdev, info->num, info->entries, type);
+
+ ops->free(pdev, info->num, info->entries, type);
+
+ pci_intx(pdev, 1);
+
+ return 0;
+}
+
+
+/* MSI */
+
+int pci_enable_msi(struct pci_dev *pdev)
+{
+ struct msix_entry entry;
+ int rc;
+
+ entry.entry = 0;
+
+ rc = generic_msi_enable(pdev, 1, &entry, PCI_CAP_ID_MSI);
+ if (rc)
+ return rc;
+
+ get_msi_info(pdev)->saved_irq = pdev->irq;
+ pdev->irq = entry.vector;
+ pdev->msi_enabled = 1;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pci_enable_msi);
+
+void pci_disable_msi(struct pci_dev *pdev)
+{
+ if (generic_msi_disable(pdev, PCI_CAP_ID_MSI) != 0)
+ return;
+
+ pdev->irq = get_msi_info(pdev)->saved_irq;
+ free_msi_info(pdev);
+ pdev->msi_enabled = 0;
+}
+EXPORT_SYMBOL_GPL(pci_disable_msi);
+
+
+/* MSI-X */
+
+int pci_enable_msix(struct pci_dev *pdev, struct msix_entry *entries, int nvec)
+{
+ int rc;
+
+ rc = generic_msi_enable(pdev, nvec, entries, PCI_CAP_ID_MSIX);
+ if (rc)
+ return rc;
+
+ pdev->msix_enabled = 1;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pci_enable_msix);
+
+void pci_disable_msix(struct pci_dev *pdev)
+{
+ if (generic_msi_disable(pdev, PCI_CAP_ID_MSIX) != 0)
+ return;
+
+ free_msi_info(pdev);
+ pdev->msix_enabled = 0;
+}
+EXPORT_SYMBOL_GPL(pci_disable_msix);
+
+
+/* Stubs for now */
+
+void disable_msi_mode(struct pci_dev *dev, int pos, int type)
+{
+ return;
+}
+
+void pci_scan_msi_device(struct pci_dev *dev)
+{
+ return;
+}
+
+void msi_remove_pci_irq_vectors(struct pci_dev* dev)
+{
+ return;
+}
+
+
+/* Bare metal enable/disable */
+
+int msi_raw_enable(struct pci_dev *pdev, int num,
+ struct msix_entry *entries, int type)
+{
+ struct ppc_msi_ops *ops;
+ struct msi_msg msg;
+ int pos;
+ u16 control;
+
+ pos = pci_find_capability(pdev, type);
+ if (!pos) {
+ msi_debug("cap (%d) not found for %s\n", type, pci_name(pdev));
+ return -1;
+ }
+
+ ops = get_msi_ops(pdev);
+ BUG_ON(!ops);
+
+ pci_read_config_word(pdev, pos + PCI_MSI_FLAGS, &control);
+
+ switch (type) {
+ case PCI_CAP_ID_MSI:
+ BUG_ON(!ops->setup_msi_msg);
+
+ ops->setup_msi_msg(pdev, &entries[0], &msg, type);
+
+ pci_write_config_dword(pdev, pos + PCI_MSI_ADDRESS_LO,
+ msg.address_lo);
+
+ if (control & PCI_MSI_FLAGS_64BIT) {
+ pci_write_config_dword(pdev, pos + PCI_MSI_ADDRESS_HI,
+ msg.address_hi);
+ pci_write_config_dword(pdev, pos + PCI_MSI_DATA_64,
+ msg.data);
+ } else {
+ pci_write_config_dword(pdev, pos + PCI_MSI_DATA_32,
+ msg.data);
+ }
+
+ control |= PCI_MSI_FLAGS_ENABLE;
+ break;
+ case PCI_CAP_ID_MSIX:
+ WARN_ON(1); /* XXX implement me */
+ return -1;
+ default:
+ BUG();
+ }
+
+ pci_write_config_word(pdev, pos + PCI_MSI_FLAGS, control);
+
+ return 0;
+}
+
+void msi_raw_disable(struct pci_dev *pdev, int num,
+ struct msix_entry *entries, int type)
+{
+ int pos;
+ u16 control;
+
+ pos = pci_find_capability(pdev, type);
+ BUG_ON(!pos);
+
+ pci_read_config_word(pdev, pos + PCI_MSI_FLAGS, &control);
+
+ switch (type) {
+ case PCI_CAP_ID_MSI:
+ control &= ~PCI_MSI_FLAGS_ENABLE;
+ break;
+ case PCI_CAP_ID_MSIX:
+ control &= ~PCI_MSIX_FLAGS_ENABLE;
+ break;
+ default:
+ BUG();
+ }
+
+ pci_write_config_word(pdev, pos + PCI_MSI_FLAGS, control);
+
+ return;
+}
Index: msi/include/asm-powerpc/machdep.h
===================================================================
--- msi.orig/include/asm-powerpc/machdep.h
+++ msi/include/asm-powerpc/machdep.h
@@ -30,6 +30,9 @@ struct pci_controller;
#ifdef CONFIG_KEXEC
struct kimage;
#endif
+#ifdef CONFIG_PCI_MSI
+struct ppc_msi_ops;
+#endif
#ifdef CONFIG_SMP
struct smp_ops_t {
@@ -111,6 +114,9 @@ struct machdep_calls {
void (*pcibios_fixup)(void);
int (*pci_probe_mode)(struct pci_bus *);
void (*pci_irq_fixup)(struct pci_dev *dev);
+#ifdef CONFIG_PCI_MSI
+ struct ppc_msi_ops* (*get_msi_ops)(struct pci_dev *pdev);
+#endif
/* To setup PHBs when using automatic OF platform driver for PCI */
int (*pci_setup_phb)(struct pci_controller *host);
Index: msi/include/asm-powerpc/msi.h
===================================================================
--- /dev/null
+++ msi/include/asm-powerpc/msi.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+#ifndef _ASM_POWERPC_MSI_H
+#define _ASM_POWERPC_MSI_H
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#include <linux/pci.h>
+#include <linux/msi.h>
+
+/*
+ * MSI and MSI-X although different in some details, are also similar in
+ * many respects, and ultimately achieve the same end. Given that, this code
+ * tries as far as possible to implement both MSI and MSI-X with a minimum
+ * of code duplication. We will use "MSI" to refer to both MSI and MSI-X,
+ * except where it is important to differentiate between the two.
+ *
+ * Enabling MSI for a device can be broken down into:
+ * 1) Checking the device can support the type/number of MSIs requested.
+ * 2) Allocating irqs for the MSIs and setting up the irq_descs.
+ * 3) Writing the appropriate configuration to the device and enabling MSIs.
+ *
+ * To implement that we have the following callbacks:
+ * 1) check(pdev, num, msix_entries, type)
+ * 2) alloc(pdev, num, msix_entries, type)
+ * 3) enable(pdev, num, msix_entries, type)
+ * a) setup_msi_msg(pdev, msix_entry, msi_msg, type)
+ *
+ * We give platforms full control over the enable step. However many
+ * platforms will simply want to program the device using standard PCI
+ * accessors. These platforms can use a generic enable callback and define
+ * a setup_msi_msg() callback which simply fills in the "magic" address and
+ * data values. Other platforms may leave setup_msi_msg() empty.
+ *
+ * Disabling MSI requires:
+ * 1) Disabling MSI on the device.
+ * 2) Freeing the irqs and any associated accounting information.
+ *
+ * Which maps directly to the two callbacks:
+ * 1) disable(pdev, num, msix_entries, type)
+ * 2) free(pdev, num, msix_entries, type)
+ */
+
+struct ppc_msi_ops
+{
+ /* check - Check that the requested MSI allocation is OK.
+ *
+ * @pdev: PCI device structure.
+ * @num: The number of MSIs being requested.
+ * @entries: An array of @num msix_entry structures.
+ * @type: The type, MSI or MSI-X.
+ *
+ * This routine is responsible for checking that the given PCI device
+ * can be allocated the requested type and number of MSIs.
+ *
+ * It is up to this routine to determine if the requested number of
+ * MSIs is valid for the device in question. If the number of MSIs,
+ * or the particular MSI entries, can not be supported for any
+ * reason this routine must return non-zero.
+ *
+ * If the check is succesful this routine must return 0.
+ */
+ int (*check) (struct pci_dev *pdev, int num,
+ struct msix_entry *entries, int type);
+
+ /* alloc - Allocate MSIs for the given device.
+ *
+ * @pdev: PCI device structure.
+ * @num: The number of MSIs being requested.
+ * @entries: An array of @num msix_entry structures.
+ * @type: The type, MSI or MSI-X.
+ *
+ * This routine is responsible for allocating the number of
+ * MSIs to the given PCI device.
+ *
+ * Upon completion there must be @num MSIs assigned to this device,
+ * the "vector" member of each struct msix_entry must be filled in
+ * with the Linux irq number allocated to it. The corresponding
+ * irq_descs must also be setup with an appropriate handler if
+ * required.
+ *
+ * If the allocation completes succesfully this routine must return 0.
+ */
+ int (*alloc) (struct pci_dev *pdev, int num,
+ struct msix_entry *entries, int type);
+
+ /* enable - Enable the MSIs on the given device.
+ *
+ * @pdev: PCI device structure.
+ * @num: The number of MSIs being requested.
+ * @entries: An array of @num msix_entry structures.
+ * @type: The type, MSI or MSI-X.
+ *
+ * This routine enables the MSIs on the given PCI device.
+ *
+ * If the enable completes succesfully this routine must return 0.
+ *
+ * This callback is optional.
+ */
+ int (*enable) (struct pci_dev *pdev, int num,
+ struct msix_entry *entries, int type);
+
+ /* setup_msi_msg - Setup an MSI message for the given device.
+ *
+ * @pdev: PCI device structure.
+ * @entry: The MSI entry to create a msi_msg for.
+ * @msg: Written with the magic address and data.
+ * @type: The type, MSI or MSI-X.
+ *
+ * Returns the "magic address and data" used to trigger the msi.
+ * If the setup is succesful this routine must return 0.
+ *
+ * This callback is optional.
+ */
+ int (*setup_msi_msg) (struct pci_dev *pdev, struct msix_entry *entry,
+ struct msi_msg *msg, int type);
+
+ /* disable - disable the MSI for the given device.
+ *
+ * @pdev: PCI device structure.
+ * @num: The number of MSIs to disable.
+ * @entries: An array of @num msix_entry structures.
+ * @type: The type, MSI or MSI-X.
+ *
+ * This routine should perform the inverse of enable.
+ */
+ void (*disable) (struct pci_dev *pdev, int num,
+ struct msix_entry *entries, int type);
+
+ /* free - free the MSIs assigned to the device.
+ *
+ * @pdev: PCI device structure.
+ * @num: The number of MSIs.
+ * @entries: An array of @num msix_entry structures.
+ * @type: The type, MSI or MSI-X.
+ *
+ * Free all MSIs and associated resources for the device. If any
+ * MSIs have been enabled they will have been disabled already by
+ * the generic code.
+ */
+ void (*free) (struct pci_dev *pdev, int num,
+ struct msix_entry *entries, int type);
+};
+
+
+/* Used by the MSI code to track MSI info for a pci_dev */
+struct msi_info {
+ int type;
+ unsigned int saved_irq;
+ unsigned int num;
+ struct msix_entry *entries;
+ void __iomem *msix_base;
+};
+
+extern int msi_raw_enable(struct pci_dev *pdev, int num,
+ struct msix_entry *entries, int type);
+extern void msi_raw_disable(struct pci_dev *pdev, int num,
+ struct msix_entry *entries, int type);
+
+#define msi_debug(fmt, args...) \
+ pr_debug("MSI:%s:%d: " fmt, __FUNCTION__, __LINE__, ## args)
+
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_MSI_H */
Index: msi/include/linux/pci.h
===================================================================
--- msi.orig/include/linux/pci.h
+++ msi/include/linux/pci.h
@@ -107,6 +107,10 @@ struct pci_cap_saved_state {
u32 data[0];
};
+#if defined(CONFIG_PCI_MSI) && defined(CONFIG_PPC_MERGE)
+struct msi_info;
+#endif
+
/*
* The pci_dev structure is used to describe PCI devices.
*/
@@ -174,6 +178,9 @@ struct pci_dev {
struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */
int rom_attr_enabled; /* has display of the rom attribute been enabled? */
struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */
+#if defined(CONFIG_PCI_MSI) && defined(CONFIG_PPC_MERGE)
+ struct msi_info *msi_info;
+#endif
};
#define pci_dev_g(n) list_entry(n, struct pci_dev, global_list)
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 4/9] Enable MSI on Powerpc
2006-12-13 10:39 [PATCH 0/9] Powerpc MSI Implementation (.. again) Michael Ellerman
` (2 preceding siblings ...)
2006-12-13 10:39 ` [PATCH 3/9] Powerpc MSI implementation Michael Ellerman
@ 2006-12-13 10:39 ` Michael Ellerman
2006-12-13 10:39 ` [PATCH 5/9] RTAS MSI implementation Michael Ellerman
` (4 subsequent siblings)
8 siblings, 0 replies; 26+ messages in thread
From: Michael Ellerman @ 2006-12-13 10:39 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linux-pci, linuxppc-dev
Allow PCI_MSI to build on Powerpc.
We still need CONFIG_POWERPC.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/kernel/Makefile | 5 +++++
drivers/pci/Kconfig | 2 +-
drivers/pci/Makefile | 4 +++-
3 files changed, 9 insertions(+), 2 deletions(-)
Index: msi/arch/powerpc/kernel/Makefile
===================================================================
--- msi.orig/arch/powerpc/kernel/Makefile
+++ msi/arch/powerpc/kernel/Makefile
@@ -65,6 +65,11 @@ 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)
+
+msiobj-y := msi.o
+msiobj-$(CONFIG_PPC_RTAS) += msi-rtas.o
+obj-$(CONFIG_PCI_MSI) += $(msiobj-y)
+
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/drivers/pci/Kconfig
===================================================================
--- msi.orig/drivers/pci/Kconfig
+++ msi/drivers/pci/Kconfig
@@ -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_MERGE
help
This allows device drivers to enable MSI (Message Signaled
Interrupts). Message Signaled Interrupts enable a device to
Index: msi/drivers/pci/Makefile
===================================================================
--- msi.orig/drivers/pci/Makefile
+++ msi/drivers/pci/Makefile
@@ -14,8 +14,10 @@ obj-$(CONFIG_HOTPLUG) += hotplug.o
# Build the PCI Hotplug drivers if we were asked to
obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
-# Build the PCI MSI interrupt support
+# Build the PCI MSI interrupt support, but not for arch/powerpc
+ifndef CONFIG_PPC_MERGE
obj-$(CONFIG_PCI_MSI) += msi.o
+endif
# Build the Hypertransport interrupt support
obj-$(CONFIG_HT_IRQ) += htirq.o
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 5/9] RTAS MSI implementation
2006-12-13 10:39 [PATCH 0/9] Powerpc MSI Implementation (.. again) Michael Ellerman
` (3 preceding siblings ...)
2006-12-13 10:39 ` [PATCH 4/9] Enable MSI on Powerpc Michael Ellerman
@ 2006-12-13 10:39 ` Michael Ellerman
2006-12-13 10:40 ` [PATCH 6/9] MPIC MSI allocator Michael Ellerman
` (3 subsequent siblings)
8 siblings, 0 replies; 26+ messages in thread
From: Michael Ellerman @ 2006-12-13 10:39 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linux-pci, linuxppc-dev
Powerpc MSI support via RTAS. Based on Jake's code.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/kernel/msi-rtas.c | 265 +++++++++++++++++++++++++++++++++++++++++
include/asm-powerpc/msi.h | 6
2 files changed, 271 insertions(+)
Index: msi/arch/powerpc/kernel/msi-rtas.c
===================================================================
--- /dev/null
+++ msi/arch/powerpc/kernel/msi-rtas.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2006 Jake Moilanen <moilanen@austin.ibm.com>, IBM Corp.
+ * Copyright (C) 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.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/irq.h>
+#include <asm/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_MSI_FN 0
+#define RTAS_CHANGE_MSI_FN 1
+#define RTAS_RESET_MSI_FN 2
+
+
+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) {
+ msi_debug("No OF device node for %s\n", pci_name(pdev));
+ return NULL;
+ }
+
+ pdn = PCI_DN(dn);
+ if (!pdn) {
+ msi_debug("No PCI DN for %s\n", pci_name(pdev));
+ return NULL;
+ }
+
+ return pdn;
+}
+
+/* RTAS Helpers */
+
+static int rtas_change_msi(struct pci_dn *pdn, u32 function, u32 num_irqs)
+{
+ u32 addr, seq_num, rtas_ret[2];
+ unsigned long buid;
+ int rc;
+
+ addr = rtas_config_addr(pdn->busno, pdn->devfn, 0);
+ buid = pdn->phb->buid;
+
+ seq_num = 1;
+ do {
+ rc = rtas_call(change_token, 6, 3, rtas_ret, addr,
+ BUID_HI(buid), BUID_LO(buid),
+ function, num_irqs, seq_num);
+
+ seq_num = rtas_ret[1];
+ } while (rtas_busy_delay(rc));
+
+ if (rc) {
+ msi_debug("error (%d) for %s\n", rc, pci_name(pdn->pcidev));
+ return rc;
+ }
+
+ return rtas_ret[0];
+}
+
+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) {
+ msi_debug("error (%d) querying source number for %s\n",
+ rc, pci_name(pdn->pcidev));
+ return rc;
+ }
+
+ return rtas_ret[0];
+}
+
+/*
+ * The spec gives firmware the option to enable either MSI or MSI-X,
+ * this doesn't wash with the Linux API. For the time beinging, we
+ * kludge around that by checking ourselves the right type is enabled.
+ */
+static int check_msi_type(struct pci_dev *pdev, int type)
+{
+ int pos, msi_enabled, msix_enabled;
+ u16 reg;
+
+ pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
+ if (!pos) {
+ msi_debug("cap (%d) not found for %s\n", type, pci_name(pdev));
+ return -1;
+ }
+
+ pci_read_config_word(pdev, pos + PCI_MSI_FLAGS, ®);
+
+ msi_enabled = msix_enabled = 0;
+
+ if (reg & PCI_MSI_FLAGS_ENABLE)
+ msi_enabled = 1;
+
+ if (reg & PCI_MSIX_FLAGS_ENABLE)
+ msix_enabled = 1;
+
+ if (type == PCI_CAP_ID_MSI && (msix_enabled || !msi_enabled)) {
+ msi_debug("Expected MSI but got %s.\n",
+ msix_enabled ? "MSI-X" : "none");
+ return -1;
+ }
+
+ if (type == PCI_CAP_ID_MSIX && (msi_enabled || !msix_enabled)) {
+ msi_debug("Expected MSI-X but got %s.\n",
+ msi_enabled ? "MSI" : "none");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void msi_rtas_free(struct pci_dev *pdev, int num,
+ struct msix_entry *entries, int type)
+{
+ struct pci_dn *pdn;
+ int i;
+
+ pdn = get_pdn(pdev);
+ if (!pdn)
+ return;
+
+ for (i = 0; i < num; i++) {
+ irq_dispose_mapping(entries[i].vector);
+ }
+
+ if (rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, 0) != 0) {
+ msi_debug("Setting MSIs to 0 failed!\n");
+ BUG();
+ }
+}
+
+static int msi_rtas_check(struct pci_dev *pdev, int num,
+ struct msix_entry *entries, int type)
+{
+ struct device_node *dn;
+ int i;
+
+ /* We must have a pci_dn for the RTAS code. */
+ if (!get_pdn(pdev))
+ return -1;
+
+ dn = pci_device_to_OF_node(pdev);
+ if (!of_find_property(dn, "ibm,req#msi", NULL)) {
+ msi_debug("No ibm,req#msi for %s\n", pci_name(pdev));
+ return -1;
+ }
+
+ /*
+ * Firmware gives us no control over which entries are allocated
+ * for MSI-X, it seems to assume we want 0 - n. For now just insist
+ * that the entries array entry members are 0 - n.
+ */
+ for (i = 0; i < num; i++) {
+ if (entries[i].entry != i) {
+ msi_debug("entries[%d].entry (%d) != %d\n", i,
+ entries[i].entry, i);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int msi_rtas_alloc(struct pci_dev *pdev, int num,
+ struct msix_entry *entries, int type)
+{
+ struct pci_dn *pdn;
+ int hwirq, virq, i;
+
+ pdn = get_pdn(pdev);
+ if (!pdn)
+ return -1;
+
+ /*
+ * In the case of an error it's not clear whether the device is left
+ * with MSI enabled or not, I think we should explicitly disable.
+ */
+ if (rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, num) != num) {
+ msi_debug("rtas_change_msi() failed for %s\n", pci_name(pdev));
+ goto out_free;
+ }
+
+ if (check_msi_type(pdev, type))
+ goto out_free;
+
+ for (i = 0; i < num; i++) {
+ hwirq = rtas_query_irq_number(pdn, i);
+ if (hwirq < 0) {
+ msi_debug("error (%d) getting hwirq for %s\n",
+ hwirq, pci_name(pdev));
+ goto out_free;
+ }
+
+ virq = irq_create_mapping(NULL, hwirq);
+
+ if (virq == NO_IRQ) {
+ msi_debug("Failed mapping hwirq %d\n", hwirq);
+ goto out_free;
+ }
+
+ entries[i].vector = virq;
+ }
+
+ return 0;
+
+ out_free:
+ msi_rtas_free(pdev, num, entries, type);
+ return -1;
+}
+
+static struct ppc_msi_ops rtas_msi_ops = {
+ .check = msi_rtas_check,
+ .alloc = msi_rtas_alloc,
+ .free = msi_rtas_free
+};
+
+static struct ppc_msi_ops *rtas_get_msi_ops(struct pci_dev *pdev)
+{
+ return &rtas_msi_ops;
+}
+
+int msi_rtas_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)) {
+ msi_debug("Couldn't find RTAS tokens, no MSI support.\n");
+ return -1;
+ }
+
+ msi_debug("Registering RTAS MSI ops.\n");
+
+ ppc_md.get_msi_ops = rtas_get_msi_ops;
+
+ return 0;
+}
Index: msi/include/asm-powerpc/msi.h
===================================================================
--- msi.orig/include/asm-powerpc/msi.h
+++ msi/include/asm-powerpc/msi.h
@@ -168,6 +168,12 @@ extern void msi_raw_disable(struct pci_d
#define msi_debug(fmt, args...) \
pr_debug("MSI:%s:%d: " fmt, __FUNCTION__, __LINE__, ## args)
+#ifdef CONFIG_PCI_MSI
+extern int msi_rtas_init(void);
+#else
+static inline int msi_rtas_init(void) { return -1; };
+#endif
+
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_MSI_H */
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 6/9] MPIC MSI allocator
2006-12-13 10:39 [PATCH 0/9] Powerpc MSI Implementation (.. again) Michael Ellerman
` (4 preceding siblings ...)
2006-12-13 10:39 ` [PATCH 5/9] RTAS MSI implementation Michael Ellerman
@ 2006-12-13 10:40 ` Michael Ellerman
2006-12-13 18:23 ` Olof Johansson
2006-12-13 10:40 ` [PATCH 7/9] MPIC MSI backend Michael Ellerman
` (2 subsequent siblings)
8 siblings, 1 reply; 26+ messages in thread
From: Michael Ellerman @ 2006-12-13 10:40 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linux-pci, 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. It looks like we'll
end up with several backends based on the MPIC, so the allocator is attached
to the struct mpic, not the msi backend.
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 | 30 +++++++
arch/powerpc/sysdev/mpic_msi.c | 160 +++++++++++++++++++++++++++++++++++++++++
include/asm-powerpc/mpic.h | 5 +
5 files changed, 203 insertions(+), 1 deletion(-)
Index: msi/arch/powerpc/sysdev/Makefile
===================================================================
--- msi.orig/arch/powerpc/sysdev/Makefile
+++ msi/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 dcr-low.o
Index: msi/arch/powerpc/sysdev/mpic.c
===================================================================
--- msi.orig/arch/powerpc/sysdev/mpic.c
+++ msi/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
@@ -825,6 +827,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/arch/powerpc/sysdev/mpic.h
===================================================================
--- /dev/null
+++ msi/arch/powerpc/sysdev/mpic.h
@@ -0,0 +1,30 @@
+#ifndef _POWERPC_SYSDEV_MPIC_H
+#define _POWERPC_SYSDEV_MPIC_H
+
+/*
+ * Copyright (C) 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/bitmap.h>
+#include <asm/msi.h>
+
+#ifdef CONFIG_PCI_MSI
+extern int mpic_msi_init_allocator(struct mpic *mpic);
+extern void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq);
+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/arch/powerpc/sysdev/mpic_msi.c
===================================================================
--- /dev/null
+++ msi/arch/powerpc/sysdev/mpic_msi.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 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/irq.h>
+#include <linux/bootmem.h>
+#include <linux/bitops.h>
+#include <asm/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)
+{
+ msi_debug("reserving hwirq 0x%lx\n", hwirq);
+
+ if (hwirq > mpic->irq_count) {
+ WARN_ON(1);
+ return;
+ }
+
+ 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);
+
+ msi_debug("allocated %d (2^%d) at offset %d\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);
+
+ msi_debug("freeing %d (2^%d) at offset %d\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);
+}
+
+static void mpic_msi_auto_reserve_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;
+
+ /* 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 < 26; 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))) {
+ msi_debug("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);
+ }
+ }
+}
+
+static int mpic_msi_reserve_dt_hwirqs(struct mpic *mpic)
+{
+ int i, len;
+ const u32 *p;
+
+ p = get_property(mpic->of_node, "msi-available", &len);
+ if (!p) {
+ msi_debug("no msi-available property found on %s\n",
+ mpic->of_node->full_name);
+ return -ENODEV;
+ }
+
+ if (len % 8 != 0) {
+ printk(KERN_WARNING "Malformed msi-available property on %s\n",
+ mpic->of_node->full_name);
+ return -EINVAL;
+ }
+
+ /* By default everything is reserved */
+ 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 size = mpic->irq_count / 8;
+
+ BUG_ON(mpic->hwirq_bitmap);
+
+ msi_debug("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) {
+ msi_debug("no mem allocating allocator bitmap!\n");
+ return -ENOMEM;
+ }
+
+ memset(mpic->hwirq_bitmap, 0, size);
+
+ if (mpic_msi_reserve_dt_hwirqs(mpic))
+ mpic_msi_auto_reserve_hwirqs(mpic);
+
+ return 0;
+}
Index: msi/include/asm-powerpc/mpic.h
===================================================================
--- msi.orig/include/asm-powerpc/mpic.h
+++ msi/include/asm-powerpc/mpic.h
@@ -300,6 +300,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] 26+ messages in thread
* [PATCH 7/9] MPIC MSI backend
2006-12-13 10:39 [PATCH 0/9] Powerpc MSI Implementation (.. again) Michael Ellerman
` (5 preceding siblings ...)
2006-12-13 10:40 ` [PATCH 6/9] MPIC MSI allocator Michael Ellerman
@ 2006-12-13 10:40 ` Michael Ellerman
2006-12-13 10:40 ` [PATCH 8/9] Activate MSI on Powerpc Michael Ellerman
2006-12-13 10:40 ` [PATCH 9/9] Enable MSI mappings for MPIC Michael Ellerman
8 siblings, 0 replies; 26+ messages in thread
From: Michael Ellerman @ 2006-12-13 10:40 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linux-pci, linuxppc-dev
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 properly discover the HT magic address by reading the config space.
Now have an irq allocator we can support > 1 MSI, and we don't reuse
the LSI.
Tested, succesfully getting MSIs from the tg3 via HT/PCI-X on a JS21
running SLOF. Successive insmod/rmmods working too.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/sysdev/Makefile | 2
arch/powerpc/sysdev/mpic.h | 7 +
arch/powerpc/sysdev/mpic_htmsi.c | 193 +++++++++++++++++++++++++++++++++++++++
3 files changed, 201 insertions(+), 1 deletion(-)
Index: msi/arch/powerpc/sysdev/Makefile
===================================================================
--- msi.orig/arch/powerpc/sysdev/Makefile
+++ msi/arch/powerpc/sysdev/Makefile
@@ -3,7 +3,7 @@ EXTRA_CFLAGS += -mno-minimal-toc
endif
mpic-obj-y := mpic.o
-mpic-obj-$(CONFIG_PCI_MSI) += mpic_msi.o
+mpic-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_htmsi.o
obj-$(CONFIG_MPIC) += $(mpic-obj-y)
obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
Index: msi/arch/powerpc/sysdev/mpic.h
===================================================================
--- msi.orig/arch/powerpc/sysdev/mpic.h
+++ msi/arch/powerpc/sysdev/mpic.h
@@ -15,11 +15,18 @@
#include <asm/msi.h>
#ifdef CONFIG_PCI_MSI
+extern int mpic_htmsi_init(struct mpic *mpic);
+
extern int mpic_msi_init_allocator(struct mpic *mpic);
extern void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq);
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 int mpic_htmsi_init(struct mpic *mpic)
+{
+ return -1;
+}
+
static inline void mpic_msi_reserve_hwirq(struct mpic *mpic,
irq_hw_number_t hwirq)
{
Index: msi/arch/powerpc/sysdev/mpic_htmsi.c
===================================================================
--- /dev/null
+++ msi/arch/powerpc/sysdev/mpic_htmsi.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2006 Segher Boessenkool, IBM Corp.
+ * Copyright (C) 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.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/irq.h>
+#include <linux/bootmem.h>
+#include <asm/msi.h>
+#include <asm/mpic.h>
+#include <asm/prom.h>
+#include <asm/hw_irq.h>
+#include <asm/ppc-pci.h>
+
+#include "mpic.h"
+
+/* XXX Do we ever need > 1 of these? void * msi_ops.data perhaps ? */
+static struct mpic *msi_mpic;
+
+static unsigned int find_ht_msi_capability(struct pci_dev *pdev)
+{
+ unsigned int pos = pci_find_capability(pdev, PCI_CAP_ID_HT);
+ u8 subcap, ttl = 48;
+
+ while (pos && ttl--) {
+ pci_read_config_byte(pdev, pos + 3, &subcap);
+ if ((subcap & 0xF8) == HT_CAPTYPE_MSI_MAPPING)
+ return pos;
+ pos = pci_find_next_capability(pdev, pos, PCI_CAP_ID_HT);
+ }
+
+ return 0;
+}
+
+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 = find_ht_msi_capability(bus->self);
+ if (pos)
+ return read_ht_magic_addr(bus->self, pos);
+ }
+
+ return 0;
+}
+
+static int htmsi_check(struct pci_dev *pdev, int num,
+ struct msix_entry *entries, int type)
+{
+ if (type == PCI_CAP_ID_MSIX) {
+ msi_debug("MSI-X unsupported for %s\n", pci_name(pdev));
+ return 1;
+ }
+
+ /* If we can't find a magic address then MSI ain't gonna work */
+ if (find_ht_magic_addr(pdev) == 0) {
+ msi_debug("no magic address found for %s\n", pci_name(pdev));
+ return 1;
+ }
+
+ return 0;
+}
+
+static void htmsi_free(struct pci_dev *pdev, int num,
+ struct msix_entry *entries, int type)
+{
+ irq_hw_number_t hwirq;
+ int i;
+
+ hwirq = irq_map[entries[0].vector].hwirq;
+
+ for (i = 0; i < num; i++) {
+ irq_dispose_mapping(entries[i].vector);
+ entries[i].vector = NO_IRQ;
+ }
+
+ msi_debug("freeing %d hwirqs for msi at offset 0x%lx\n", num, hwirq);
+ mpic_msi_free_hwirqs(msi_mpic, hwirq, num);
+
+ return;
+}
+
+static int htmsi_alloc(struct pci_dev *pdev, int num,
+ struct msix_entry *entries, int type)
+{
+ int i;
+ irq_hw_number_t hwirq;
+ unsigned int virq;
+
+ hwirq = mpic_msi_alloc_hwirqs(msi_mpic, num);
+ if (hwirq < 0) {
+ msi_debug("failed allocating %d hwirqs for %s\n", num,
+ pci_name(pdev));
+ return -1;
+ }
+
+ for (i = 0; i < num; i++) {
+ /* FIXME should we save the existing type */
+ set_irq_type(hwirq, IRQ_TYPE_EDGE_RISING);
+
+ virq = irq_create_mapping(msi_mpic->irqhost, hwirq);
+ if (virq == NO_IRQ) {
+ msi_debug("failed mapping hwirq 0x%lx for %s\n", hwirq,
+ pci_name(pdev));
+ goto out_free;
+ }
+
+ entries[i].vector = virq;
+ hwirq++;
+ }
+
+ return 0;
+
+ out_free:
+ htmsi_free(pdev, num, entries, type);
+ return -1;
+}
+
+static int htmsi_setup_msi_msg(struct pci_dev *pdev,
+ struct msix_entry *entry, struct msi_msg *msg, int type)
+{
+ u64 addr;
+
+ addr = find_ht_magic_addr(pdev);
+ msg->address_lo = addr & 0xFFFFFFFF;
+ msg->address_hi = addr >> 32;
+ msg->data = irq_map[entry->vector].hwirq;
+
+ msi_debug("allocated irq %d at 0x%lx for %s\n", entry->vector,
+ addr, pci_name(pdev));
+
+ return 0;
+}
+
+static struct ppc_msi_ops mpic_htmsi_ops = {
+ .check = htmsi_check,
+ .alloc = htmsi_alloc,
+ .free = htmsi_free,
+ .enable = msi_raw_enable,
+ .disable = msi_raw_disable,
+ .setup_msi_msg = htmsi_setup_msi_msg,
+};
+
+static struct ppc_msi_ops *htmsi_get_msi_ops(struct pci_dev *pdev)
+{
+ return &mpic_htmsi_ops;
+}
+
+int mpic_htmsi_init(struct mpic *mpic)
+{
+ int rc;
+
+ rc = mpic_msi_init_allocator(mpic);
+ if (rc) {
+ pr_debug("mpic_htmsi_init: Error allocating bitmap!\n");
+ return rc;
+ }
+
+ msi_mpic = mpic;
+
+ pr_debug("mpic_htmsi_init: Registering MPIC MSI ops.\n");
+ ppc_md.get_msi_ops = htmsi_get_msi_ops;
+
+ return 0;
+}
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 8/9] Activate MSI on Powerpc
2006-12-13 10:39 [PATCH 0/9] Powerpc MSI Implementation (.. again) Michael Ellerman
` (6 preceding siblings ...)
2006-12-13 10:40 ` [PATCH 7/9] MPIC MSI backend Michael Ellerman
@ 2006-12-13 10:40 ` Michael Ellerman
2006-12-13 10:40 ` [PATCH 9/9] Enable MSI mappings for MPIC Michael Ellerman
8 siblings, 0 replies; 26+ messages in thread
From: Michael Ellerman @ 2006-12-13 10:40 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linux-pci, linuxppc-dev
Hook up a few platforms to use the appropriate MSI backend.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/pseries/setup.c | 2 ++
arch/powerpc/sysdev/mpic.c | 6 ++++--
2 files changed, 6 insertions(+), 2 deletions(-)
Index: msi/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- msi.orig/arch/powerpc/platforms/pseries/setup.c
+++ msi/arch/powerpc/platforms/pseries/setup.c
@@ -65,6 +65,7 @@
#include <asm/i8259.h>
#include <asm/udbg.h>
#include <asm/smp.h>
+#include <asm/msi.h>
#include "plpar_wrappers.h"
#include "ras.h"
@@ -284,6 +285,7 @@ static void __init pseries_discover_pic(
#ifdef CONFIG_SMP
smp_init_pseries_xics();
#endif
+ msi_rtas_init();
return;
}
}
Index: msi/arch/powerpc/sysdev/mpic.c
===================================================================
--- msi.orig/arch/powerpc/sysdev/mpic.c
+++ msi/arch/powerpc/sysdev/mpic.c
@@ -1126,8 +1126,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 */
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 9/9] Enable MSI mappings for MPIC
2006-12-13 10:39 [PATCH 0/9] Powerpc MSI Implementation (.. again) Michael Ellerman
` (7 preceding siblings ...)
2006-12-13 10:40 ` [PATCH 8/9] Activate MSI on Powerpc Michael Ellerman
@ 2006-12-13 10:40 ` Michael Ellerman
8 siblings, 0 replies; 26+ messages in thread
From: Michael Ellerman @ 2006-12-13 10:40 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linux-pci, linuxppc-dev
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 | 49 +++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 47 insertions(+), 2 deletions(-)
Index: msi/arch/powerpc/sysdev/mpic.c
===================================================================
--- msi.orig/arch/powerpc/sysdev/mpic.c
+++ msi/arch/powerpc/sysdev/mpic.c
@@ -377,7 +377,51 @@ static void mpic_shutdown_ht_interrupt(s
spin_unlock_irqrestore(&mpic->fixup_lock, flags);
}
-static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
+#ifdef CONFIG_PCI_MSI
+static void __init mpic_setup_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 & 0xF8) == 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_INFO "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_setup_ht_msi(struct mpic *mpic, u8 __iomem *devbase,
+ unsigned int devfn)
+{
+ return;
+}
+#endif
+
+static void __init mpic_setup_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
unsigned int devfn, u32 vdid)
{
int i, irq, n;
@@ -467,7 +511,8 @@ static void __init mpic_scan_ht_pics(str
if (!(s & PCI_STATUS_CAP_LIST))
goto next;
- mpic_scan_ht_pic(mpic, devbase, devfn, l);
+ mpic_setup_ht_pic(mpic, devbase, devfn, l);
+ mpic_setup_ht_msi(mpic, devbase, devfn);
next:
/* next device, if function 0 */
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 6/9] MPIC MSI allocator
2006-12-13 10:40 ` [PATCH 6/9] MPIC MSI allocator Michael Ellerman
@ 2006-12-13 18:23 ` Olof Johansson
2006-12-13 23:25 ` Benjamin Herrenschmidt
2006-12-14 0:34 ` Michael Ellerman
0 siblings, 2 replies; 26+ messages in thread
From: Olof Johansson @ 2006-12-13 18:23 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, linux-pci, Paul Mackerras
On Wed, 13 Dec 2006 21:40:03 +1100 Michael Ellerman <michael@ellerman.id.au> wrote:
> To support MSI on MPIC we need a way to reserve and allocate hardware irq
> numbers, this patch implements an allocator for that. It looks like we'll
> end up with several backends based on the MPIC, so the allocator is attached
> to the struct mpic, not the msi backend.
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
> +static void mpic_msi_auto_reserve_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;
> +
> + /* Reserve source numbers we know are reserved in the HW */
How do we know? Reserved on what HW? Sure looks system/platform
dependent to me.
> + for (i = 0; i < 8; i++)
> + __mpic_msi_reserve_hwirq(mpic, i);
> + for (i = 42; i < 26; i++)
^^^^^^^^^^^^^^^
Is this some sort of check to see if we're awake? :)
> + __mpic_msi_reserve_hwirq(mpic, i);
> + for (i = 100; i < 105; i++)
> + __mpic_msi_reserve_hwirq(mpic, i);
-Olof
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 6/9] MPIC MSI allocator
2006-12-13 18:23 ` Olof Johansson
@ 2006-12-13 23:25 ` Benjamin Herrenschmidt
2006-12-14 0:09 ` Olof Johansson
2006-12-14 0:34 ` Michael Ellerman
1 sibling, 1 reply; 26+ messages in thread
From: Benjamin Herrenschmidt @ 2006-12-13 23:25 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, linux-pci, Paul Mackerras
On Wed, 2006-12-13 at 12:23 -0600, Olof Johansson wrote:
> On Wed, 13 Dec 2006 21:40:03 +1100 Michael Ellerman <michael@ellerman.id.au> wrote:
>
> > To support MSI on MPIC we need a way to reserve and allocate hardware irq
> > numbers, this patch implements an allocator for that. It looks like we'll
> > end up with several backends based on the MPIC, so the allocator is attached
> > to the struct mpic, not the msi backend.
> >
> > Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
>
> > +static void mpic_msi_auto_reserve_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;
> > +
> > + /* Reserve source numbers we know are reserved in the HW */
>
> How do we know? Reserved on what HW? Sure looks system/platform
> dependent to me.
>
> > + for (i = 0; i < 8; i++)
> > + __mpic_msi_reserve_hwirq(mpic, i);
> > + for (i = 42; i < 26; i++)
> ^^^^^^^^^^^^^^^
>
> Is this some sort of check to see if we're awake? :)
This code in MPIC currently is only ever used on U3/U4 and so that code
reserves IRQs we know are used for U3/U4 internal IRQs and not available
for HT interrupts (or MSIs). The code, then, does a second pass also
exclusing all IRQs for all devices in the device-tree.
This is a "hack" that works until device-trees provide the right
property we have defined for mpic to indicate what range of irqs is to
be used for MSIs.
Ben.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 6/9] MPIC MSI allocator
2006-12-13 23:25 ` Benjamin Herrenschmidt
@ 2006-12-14 0:09 ` Olof Johansson
2006-12-14 0:32 ` Benjamin Herrenschmidt
0 siblings, 1 reply; 26+ messages in thread
From: Olof Johansson @ 2006-12-14 0:09 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linux-pci, Mackerras, Paul
On Thu, 14 Dec 2006 10:25:44 +1100 Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> This code in MPIC currently is only ever used on U3/U4 and so that code
> reserves IRQs we know are used for U3/U4 internal IRQs and not available
> for HT interrupts (or MSIs). The code, then, does a second pass also
> exclusing all IRQs for all devices in the device-tree.
>
> This is a "hack" that works until device-trees provide the right
> property we have defined for mpic to indicate what range of irqs is to
> be used for MSIs.
So make the platform register the range of (possibly) usable MSI
addresses instead of adding a nasty hack like that to the mpic driver.
Adding numeric constants like that (completely without comments as to
where they came from) in a function called
mpic_msi_auto_reserve_hwirqs() is just too ugly.
-Olof
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 6/9] MPIC MSI allocator
2006-12-14 0:09 ` Olof Johansson
@ 2006-12-14 0:32 ` Benjamin Herrenschmidt
2006-12-14 0:59 ` Michael Ellerman
0 siblings, 1 reply; 26+ messages in thread
From: Benjamin Herrenschmidt @ 2006-12-14 0:32 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, linux-pci, Paul Mackerras
> So make the platform register the range of (possibly) usable MSI
> addresses instead of adding a nasty hack like that to the mpic driver.
The hack is not that nasty... it's only ever run on U3/U4 on which it's
actually correct, at least if Michael did what I told him to do which is
to test the MPIC_BROKEN_U3 bit :-)
> Adding numeric constants like that (completely without comments as to
> where they came from) in a function called
> mpic_msi_auto_reserve_hwirqs() is just too ugly.
Yes, it should be mpic_msi_reserve_u3u4_irqs() or something like that.
Ben.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 6/9] MPIC MSI allocator
2006-12-13 18:23 ` Olof Johansson
2006-12-13 23:25 ` Benjamin Herrenschmidt
@ 2006-12-14 0:34 ` Michael Ellerman
1 sibling, 0 replies; 26+ messages in thread
From: Michael Ellerman @ 2006-12-14 0:34 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, linux-pci, Paul Mackerras
[-- Attachment #1: Type: text/plain, Size: 2027 bytes --]
On Wed, 2006-12-13 at 12:23 -0600, Olof Johansson wrote:
> On Wed, 13 Dec 2006 21:40:03 +1100 Michael Ellerman <michael@ellerman.id.au> wrote:
>
> > To support MSI on MPIC we need a way to reserve and allocate hardware irq
> > numbers, this patch implements an allocator for that. It looks like we'll
> > end up with several backends based on the MPIC, so the allocator is attached
> > to the struct mpic, not the msi backend.
> >
> > Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
>
> > +static void mpic_msi_auto_reserve_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;
> > +
> > + /* Reserve source numbers we know are reserved in the HW */
>
> How do we know? Reserved on what HW? Sure looks system/platform
> dependent to me.
I agree. It's a fall-back position, we first check for the
"msi-available" property, and if that's not there we try to guess. New
firmwares should define "msi-available", but we don't want to wait for
that to happen, if it really bothers you we could have a
CONFIG_MPIC_MSI_DODGY_ALLOCATOR_GUESSING_ENABLE :)
So 0-7, 42-45 and 100-104 are known to be reserved on various revisions
of MPIC (and if there's more we can add them), and then we go through
the whole device tree and reserve anything that's already got an irq
mapped.
>
> > + for (i = 0; i < 8; i++)
> > + __mpic_msi_reserve_hwirq(mpic, i);
> > + for (i = 42; i < 26; i++)
> ^^^^^^^^^^^^^^^
>
> Is this some sort of check to see if we're awake? :)
Hehe. No it's proof that I wasn't awake when I wrote it, that's late
night hacking for you :)
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] 26+ messages in thread
* Re: [PATCH 6/9] MPIC MSI allocator
2006-12-14 0:32 ` Benjamin Herrenschmidt
@ 2006-12-14 0:59 ` Michael Ellerman
2006-12-14 1:02 ` Benjamin Herrenschmidt
2006-12-14 1:06 ` Olof Johansson
0 siblings, 2 replies; 26+ messages in thread
From: Michael Ellerman @ 2006-12-14 0:59 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Olof Johansson, linuxppc-dev, linux-pci, Paul Mackerras
[-- Attachment #1: Type: text/plain, Size: 1304 bytes --]
On Thu, 2006-12-14 at 11:32 +1100, Benjamin Herrenschmidt wrote:
> > So make the platform register the range of (possibly) usable MSI
> > addresses instead of adding a nasty hack like that to the mpic driver.
>
> The hack is not that nasty... it's only ever run on U3/U4 on which it's
> actually correct, at least if Michael did what I told him to do which is
> to test the MPIC_BROKEN_U3 bit :-)
Nah I didn't make it U3/U4 specific, although I could. If we do that,
then I think the logic needs to be:
if get_property("msi_available")
mpic_msi_reserve_dt_irqs()
elif is_u3_or_u4()
mpic_msi_reserve_u3u4_irqs()
else
return error
Because if we don't have a firmware property, and we don't make an
educated guess at what's reserved, then there's a very good chance our
first MSI will get hwirq 0 and that it won't work.
As far as putting hacks in the MPIC driver .. have you read it
lately? ;) But seriously, I think if there's anyway these magic numbers
should be, it is in this code, not the platform code.
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] 26+ messages in thread
* Re: [PATCH 6/9] MPIC MSI allocator
2006-12-14 0:59 ` Michael Ellerman
@ 2006-12-14 1:02 ` Benjamin Herrenschmidt
2006-12-14 1:06 ` Michael Ellerman
2006-12-14 1:06 ` Olof Johansson
1 sibling, 1 reply; 26+ messages in thread
From: Benjamin Herrenschmidt @ 2006-12-14 1:02 UTC (permalink / raw)
To: michael; +Cc: Olof Johansson, linuxppc-dev, linux-pci, Paul Mackerras
> if get_property("msi_available")
> mpic_msi_reserve_dt_irqs()
available-msi is a better name now that I think of it, or better even:
"msi-ranges"
> elif is_u3_or_u4()
> mpic_msi_reserve_u3u4_irqs()
> else
> return error
>
> Because if we don't have a firmware property, and we don't make an
> educated guess at what's reserved, then there's a very good chance our
> first MSI will get hwirq 0 and that it won't work.
>
> As far as putting hacks in the MPIC driver .. have you read it
> lately? ;) But seriously, I think if there's anyway these magic numbers
> should be, it is in this code, not the platform code.
Ben.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 6/9] MPIC MSI allocator
2006-12-14 1:02 ` Benjamin Herrenschmidt
@ 2006-12-14 1:06 ` Michael Ellerman
2006-12-14 14:46 ` Segher Boessenkool
0 siblings, 1 reply; 26+ messages in thread
From: Michael Ellerman @ 2006-12-14 1:06 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Olof Johansson, linuxppc-dev, linux-pci, Paul Mackerras
[-- Attachment #1: Type: text/plain, Size: 599 bytes --]
On Thu, 2006-12-14 at 12:02 +1100, Benjamin Herrenschmidt wrote:
> > if get_property("msi_available")
> > mpic_msi_reserve_dt_irqs()
>
> available-msi is a better name now that I think of it, or better even:
> "msi-ranges"
"msi-ranges" is ambiguous, are the ranges available or reserved?
How about "msi-available-ranges" :D
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] 26+ messages in thread
* Re: [PATCH 6/9] MPIC MSI allocator
2006-12-14 0:59 ` Michael Ellerman
2006-12-14 1:02 ` Benjamin Herrenschmidt
@ 2006-12-14 1:06 ` Olof Johansson
1 sibling, 0 replies; 26+ messages in thread
From: Olof Johansson @ 2006-12-14 1:06 UTC (permalink / raw)
To: michael; +Cc: linux-pci, Paul Mackerras, linuxppc-dev
On Thu, 14 Dec 2006 11:59:00 +1100 Michael Ellerman <michael@ellerman.id.au> wrote:
> Nah I didn't make it U3/U4 specific, although I could. If we do that,
> then I think the logic needs to be:
>
> if get_property("msi_available")
> mpic_msi_reserve_dt_irqs()
> elif is_u3_or_u4()
> mpic_msi_reserve_u3u4_irqs()
> else
> return error
>
> Because if we don't have a firmware property, and we don't make an
> educated guess at what's reserved, then there's a very good chance our
> first MSI will get hwirq 0 and that it won't work.
Looks like a good solution to me.
> As far as putting hacks in the MPIC driver .. have you read it
> lately? ;) But seriously, I think if there's anyway these magic numbers
> should be, it is in this code, not the platform code.
It used to be fairly OK, but the TSI merge really pushed it over the
edge, obfuscation-wise. :(
But that's no excuse to make it worse than it has to be.
-Olof
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 6/9] MPIC MSI allocator
2006-12-14 1:06 ` Michael Ellerman
@ 2006-12-14 14:46 ` Segher Boessenkool
2006-12-14 19:44 ` Benjamin Herrenschmidt
0 siblings, 1 reply; 26+ messages in thread
From: Segher Boessenkool @ 2006-12-14 14:46 UTC (permalink / raw)
To: michael; +Cc: Olof Johansson, linux-pci, Paul Mackerras, linuxppc-dev
>>> if get_property("msi_available")
>>> mpic_msi_reserve_dt_irqs()
>>
>> available-msi is a better name now that I think of it, or better
>> even:
>> "msi-ranges"
>
> "msi-ranges" is ambiguous, are the ranges available or reserved?
>
> How about "msi-available-ranges" :D
The property describes vectors that are not (yet) in use by
the hardware; so let's do "available-vectors"?
Segher
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 6/9] MPIC MSI allocator
2006-12-14 14:46 ` Segher Boessenkool
@ 2006-12-14 19:44 ` Benjamin Herrenschmidt
2006-12-15 1:47 ` Segher Boessenkool
0 siblings, 1 reply; 26+ messages in thread
From: Benjamin Herrenschmidt @ 2006-12-14 19:44 UTC (permalink / raw)
To: Segher Boessenkool
Cc: Olof Johansson, linux-pci, Paul Mackerras, linuxppc-dev
On Thu, 2006-12-14 at 15:46 +0100, Segher Boessenkool wrote:
> >>> if get_property("msi_available")
> >>> mpic_msi_reserve_dt_irqs()
> >>
> >> available-msi is a better name now that I think of it, or better
> >> even:
> >> "msi-ranges"
> >
> > "msi-ranges" is ambiguous, are the ranges available or reserved?
> >
> > How about "msi-available-ranges" :D
>
> The property describes vectors that are not (yet) in use by
> the hardware; so let's do "available-vectors"?
If we are going to be pedantic, it should be msi-available-sources :-)
Ben.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 6/9] MPIC MSI allocator
2006-12-14 19:44 ` Benjamin Herrenschmidt
@ 2006-12-15 1:47 ` Segher Boessenkool
2006-12-15 1:51 ` Michael Ellerman
2006-12-15 2:28 ` Benjamin Herrenschmidt
0 siblings, 2 replies; 26+ messages in thread
From: Segher Boessenkool @ 2006-12-15 1:47 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Olof Johansson, linux-pci, Paul Mackerras, linuxppc-dev
>>> "msi-ranges" is ambiguous, are the ranges available or reserved?
>>>
>>> How about "msi-available-ranges" :D
>>
>> The property describes vectors that are not (yet) in use by
>> the hardware; so let's do "available-vectors"?
>
> If we are going to be pedantic, it should be msi-available-sources :-)
But a) it's not really MSI-only, and b) they're not source
numbers, but delivery vector numbers (yeah, those are almost
the same on U3/U4, but hey).
Segher
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 6/9] MPIC MSI allocator
2006-12-15 1:47 ` Segher Boessenkool
@ 2006-12-15 1:51 ` Michael Ellerman
2006-12-15 2:28 ` Benjamin Herrenschmidt
1 sibling, 0 replies; 26+ messages in thread
From: Michael Ellerman @ 2006-12-15 1:51 UTC (permalink / raw)
To: Segher Boessenkool
Cc: Olof Johansson, linux-pci, Paul Mackerras, linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 989 bytes --]
On Fri, 2006-12-15 at 02:47 +0100, Segher Boessenkool wrote:
> >>> "msi-ranges" is ambiguous, are the ranges available or reserved?
> >>>
> >>> How about "msi-available-ranges" :D
> >>
> >> The property describes vectors that are not (yet) in use by
> >> the hardware; so let's do "available-vectors"?
> >
> > If we are going to be pedantic, it should be msi-available-sources :-)
>
> But a) it's not really MSI-only, and b) they're not source
> numbers, but delivery vector numbers (yeah, those are almost
> the same on U3/U4, but hey).
OK I'm gonna lock you two in a padded room, and whoever comes out alive
gets to name the property, OK? Then let me know what it is and I'll
update the freakin code!
:D
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] 26+ messages in thread
* Re: [PATCH 6/9] MPIC MSI allocator
2006-12-15 1:47 ` Segher Boessenkool
2006-12-15 1:51 ` Michael Ellerman
@ 2006-12-15 2:28 ` Benjamin Herrenschmidt
2006-12-15 2:58 ` Segher Boessenkool
1 sibling, 1 reply; 26+ messages in thread
From: Benjamin Herrenschmidt @ 2006-12-15 2:28 UTC (permalink / raw)
To: Segher Boessenkool
Cc: Olof Johansson, linux-pci, Paul Mackerras, linuxppc-dev
On Fri, 2006-12-15 at 02:47 +0100, Segher Boessenkool wrote:
> >>> "msi-ranges" is ambiguous, are the ranges available or reserved?
> >>>
> >>> How about "msi-available-ranges" :D
> >>
> >> The property describes vectors that are not (yet) in use by
> >> the hardware; so let's do "available-vectors"?
> >
> > If we are going to be pedantic, it should be msi-available-sources :-)
>
> But a) it's not really MSI-only, and b) they're not source
> numbers, but delivery vector numbers (yeah, those are almost
> the same on U3/U4, but hey).
Actually, they aren't vector numbers, those are what you program in the
MPIC itself to be emited. Thus they are source numbers according to the
last time I read the docs :-) Not that it matters anyway :-)
Ben.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 6/9] MPIC MSI allocator
2006-12-15 2:28 ` Benjamin Herrenschmidt
@ 2006-12-15 2:58 ` Segher Boessenkool
2006-12-15 6:42 ` Olof Johansson
0 siblings, 1 reply; 26+ messages in thread
From: Segher Boessenkool @ 2006-12-15 2:58 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Olof Johansson, linux-pci, Paul Mackerras, linuxppc-dev
>>> If we are going to be pedantic, it should be msi-available-
>>> sources :-)
>>
>> But a) it's not really MSI-only, and b) they're not source
>> numbers, but delivery vector numbers (yeah, those are almost
>> the same on U3/U4, but hey).
>
> Actually, they aren't vector numbers, those are what you program in
> the
> MPIC itself to be emited. Thus they are source numbers according to
> the
> last time I read the docs :-) Not that it matters anyway :-)
Yeah, my bad.
So how about:
"available-interrupts" denotes the input numbers to an
interrupt controller that the OS can freely assign. This
naming fits in well with the other interrupt property names,
and the semantics are nicely generic.
"msi-ranges", if present, denotes the ranges of input
interrupt numbers that can be used for MSIs (does this
fit what you need well, Olof?)
Segher
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 6/9] MPIC MSI allocator
2006-12-15 2:58 ` Segher Boessenkool
@ 2006-12-15 6:42 ` Olof Johansson
0 siblings, 0 replies; 26+ messages in thread
From: Olof Johansson @ 2006-12-15 6:42 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: linux-pci, Paul Mackerras, linuxppc-dev
On Fri, 15 Dec 2006 03:58:57 +0100 Segher Boessenkool <segher@kernel.crashing.org> wrote:
> "msi-ranges", if present, denotes the ranges of input
> interrupt numbers that can be used for MSIs (does this
> fit what you need well, Olof?)
Yep, sounds good to me!
-Olof
^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2006-12-15 6:43 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-12-13 10:39 [PATCH 0/9] Powerpc MSI Implementation (.. again) Michael Ellerman
2006-12-13 10:39 ` [PATCH 1/9] Add #defines for Hypertransport MSI fields Michael Ellerman
2006-12-13 10:39 ` [PATCH 2/9] Rip out the existing powerpc msi stubs Michael Ellerman
2006-12-13 10:39 ` [PATCH 3/9] Powerpc MSI implementation Michael Ellerman
2006-12-13 10:39 ` [PATCH 4/9] Enable MSI on Powerpc Michael Ellerman
2006-12-13 10:39 ` [PATCH 5/9] RTAS MSI implementation Michael Ellerman
2006-12-13 10:40 ` [PATCH 6/9] MPIC MSI allocator Michael Ellerman
2006-12-13 18:23 ` Olof Johansson
2006-12-13 23:25 ` Benjamin Herrenschmidt
2006-12-14 0:09 ` Olof Johansson
2006-12-14 0:32 ` Benjamin Herrenschmidt
2006-12-14 0:59 ` Michael Ellerman
2006-12-14 1:02 ` Benjamin Herrenschmidt
2006-12-14 1:06 ` Michael Ellerman
2006-12-14 14:46 ` Segher Boessenkool
2006-12-14 19:44 ` Benjamin Herrenschmidt
2006-12-15 1:47 ` Segher Boessenkool
2006-12-15 1:51 ` Michael Ellerman
2006-12-15 2:28 ` Benjamin Herrenschmidt
2006-12-15 2:58 ` Segher Boessenkool
2006-12-15 6:42 ` Olof Johansson
2006-12-14 1:06 ` Olof Johansson
2006-12-14 0:34 ` Michael Ellerman
2006-12-13 10:40 ` [PATCH 7/9] MPIC MSI backend Michael Ellerman
2006-12-13 10:40 ` [PATCH 8/9] Activate MSI on Powerpc Michael Ellerman
2006-12-13 10:40 ` [PATCH 9/9] Enable MSI mappings for MPIC Michael Ellerman
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).