[patch 16/16] PCI/MSI: Enhance core to support hierarchy irqdomain

From: Thomas Gleixner
Date: Wed Nov 12 2014 - 08:43:26 EST


From: Jiang Liu <jiang.liu@xxxxxxxxxxxxxxx>

Enhance PCI MSI core to support hierarchy irqdomain, so the common
code can be shared across architectures.

[ tglx: Extracted and combined from several patches ]

Signed-off-by: Jiang Liu <jiang.liu@xxxxxxxxxxxxxxx>
Cc: Bjorn Helgaas <bhelgaas@xxxxxxxxxx>
Cc: Grant Likely <grant.likely@xxxxxxxxxx>
Cc: Marc Zyngier <marc.zyngier@xxxxxxx>
Cc: Yingjoe Chen <yingjoe.chen@xxxxxxxxxxxx>
Cc: Yijing Wang <wangyijing@xxxxxxxxxx>
Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
---
drivers/pci/Kconfig | 5 ++++
drivers/pci/msi.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/msi.h | 8 ++++++
3 files changed, 75 insertions(+)

Index: tip/drivers/pci/Kconfig
===================================================================
--- tip.orig/drivers/pci/Kconfig
+++ tip/drivers/pci/Kconfig
@@ -17,6 +17,11 @@ config PCI_MSI

If you don't know what to do here, say Y.

+config PCI_MSI_IRQ_DOMAIN
+ bool
+ depends on PCI_MSI
+ select GENERIC_MSI_IRQ_DOMAIN
+
config PCI_DEBUG
bool "PCI Debugging"
depends on PCI && DEBUG_KERNEL
Index: tip/drivers/pci/msi.c
===================================================================
--- tip.orig/drivers/pci/msi.c
+++ tip/drivers/pci/msi.c
@@ -19,6 +19,7 @@
#include <linux/errno.h>
#include <linux/io.h>
#include <linux/slab.h>
+#include <linux/irqdomain.h>

#include "pci.h"

@@ -1072,3 +1073,64 @@ int pci_enable_msix_range(struct pci_dev
return nvec;
}
EXPORT_SYMBOL(pci_enable_msix_range);
+
+#ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
+void pci_msi_domain_write_msg(struct irq_data *irq_data, struct msi_msg *msg)
+{
+ struct msi_desc *desc = irq_data->msi_desc;
+
+ /*
+ * MSI-X message is written per-IRQ.
+ * MSI message denotes a contiguous group of IRQs, written for 0th IRQ.
+ */
+ if (desc->irq == irq_data->irq)
+ pci_write_msi_msg(desc, msg);
+}
+
+/*
+ * Generate a unique ID number for each possible MSI source, the ID number
+ * is only used within the irqdomain.
+ */
+irq_hw_number_t pci_msi_domain_calc_hwirq(struct pci_dev *dev,
+ struct msi_desc *desc)
+{
+ return (irq_hw_number_t)desc->msi_attrib.entry_nr |
+ PCI_DEVID(dev->bus->number, dev->devfn) << 11 |
+ (pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 27;
+}
+
+int pci_msi_domain_alloc_irqs(struct irq_domain *domain, int type,
+ struct pci_dev *dev, void *arg)
+{
+ struct msi_domain_info *info = domain->host_data;
+ int node = dev_to_node(&dev->dev);
+ struct msi_desc *desc;
+ int i, virq;
+
+ list_for_each_entry(desc, &dev->msi_list, list) {
+ if (info->ops->calc_hwirq)
+ info->ops->calc_hwirq(info, arg, desc);
+
+ virq = irq_domain_alloc_irqs(domain, desc->nvec_used,
+ node, arg);
+ if (virq < 0) {
+ /* Special handling for pci_enable_msi_range(). */
+ if (type == PCI_CAP_ID_MSI && desc->nvec_used > 1)
+ return 1;
+ else
+ return -ENOSPC;
+ }
+ for (i = 0; i < desc->nvec_used; i++)
+ irq_set_msi_desc_off(virq, i, desc);
+ }
+
+ list_for_each_entry(desc, &dev->msi_list, list)
+ if (desc->nvec_used == 1)
+ dev_dbg(&dev->dev, "irq %d for MSI/MSI-X\n", virq);
+ else
+ dev_dbg(&dev->dev, "irq [%d-%d] for MSI/MSI-X\n",
+ virq, virq + desc->nvec_used - 1);
+
+ return 0;
+}
+#endif /* CONFIG_PCI_MSI_IRQ_DOMAIN */
Index: tip/include/linux/msi.h
===================================================================
--- tip.orig/include/linux/msi.h
+++ tip/include/linux/msi.h
@@ -112,4 +112,12 @@ struct msi_domain_info *msi_get_domain_i

#endif /* CONFIG_GENERIC_MSI_IRQ_DOMAIN */

+#ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
+void pci_msi_domain_write_msg(struct irq_data *irq_data, struct msi_msg *msg);
+int pci_msi_domain_alloc_irqs(struct irq_domain *domain, int type,
+ struct pci_dev *dev, void *arg);
+irq_hw_number_t pci_msi_domain_calc_hwirq(struct pci_dev *dev,
+ struct msi_desc *desc);
+#endif /* CONFIG_PCI_MSI_IRQ_DOMAIN */
+
#endif /* LINUX_MSI_H */


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/