[PATCH v2 09/11] kernel:irq: Implement msi match function

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Jake Oshins <jakeo@xxxxxxxxxxxxx>

Previous patches in this series introduced the concept of ranked matches of
IRQ domains, where a default implementation ranks low and a specific
implementation might rank higher, overriding the default.

This patch supplies a match function for use by any IRQ domain derived from
the default MSI IRQ domain.  It returns a rank of '1' when the IRQ domain
does not ask for a match based on PCI domain and a rank of '2' if the IRQ
domain does set the flag indicating that it wants a more specific match.

At this point in the patch series, there is no implementation of an MSI IRQ
domain which asks for a more specific match.  That's found in the final patch,
introducing a new driver.

Signed-off-by: Jake Oshins <jakeo@xxxxxxxxxxxxx>
---
 include/linux/msi.h |  2 ++
 kernel/irq/msi.c    | 24 ++++++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/include/linux/msi.h b/include/linux/msi.h
index 7370225..a8ee7a1 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -259,6 +259,8 @@ enum {
 	MSI_FLAG_MULTI_PCI_MSI		= (1 << 3),
 	/* Support PCI MSIX interrupts */
 	MSI_FLAG_PCI_MSIX		= (1 << 4),
+	/* Require exact match for PCI domain */
+	MSI_FLAG_PCI_DOMAIN_MATCH	= (1 << 5),
 };
 
 int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 7e6512b..5fcd68c 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -141,11 +141,35 @@ static void msi_domain_free(struct irq_domain *domain, unsigned int virq,
 	irq_domain_free_irqs_top(domain, virq, nr_irqs);
 }
 
+/*
+ * Return a higher rank for exact matches against PCI domain (segment)
+ * so that generic MSI IRQ domains can be overridden by more specific
+ * implementations.
+ */
+static int msi_domain_match(struct irq_domain *d, struct device_node *node,
+			    enum irq_domain_bus_token bus_token,
+			    void *bus_data)
+{
+	struct msi_domain_info *info = d->host_data;
+
+	if (bus_token != d->bus_token)
+		return 0;
+
+	if (bus_token == DOMAIN_BUS_PCI_MSI) {
+		if (!(info->flags & MSI_FLAG_PCI_DOMAIN_MATCH))
+			return 1;
+		if (bus_data && (info->pci_domain == *(int *)bus_data))
+			return 2;
+	}
+	return 0;
+}
+
 static const struct irq_domain_ops msi_domain_ops = {
 	.alloc		= msi_domain_alloc,
 	.free		= msi_domain_free,
 	.activate	= msi_domain_activate,
 	.deactivate	= msi_domain_deactivate,
+	.match		= msi_domain_match,
 };
 
 #ifdef GENERIC_MSI_DOMAIN_OPS
-- 
1.9.1

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel



[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux