107 lines
3.2 KiB
Diff
107 lines
3.2 KiB
Diff
|
From a05852e828063b6731fcac543b87367c137c16f8 Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||
|
Date: Thu, 6 Jun 2013 18:21:18 +0200
|
||
|
Subject: [PATCH 073/203] of: pci: add registry of MSI chips
|
||
|
|
||
|
This commit adds a very basic registry of msi_chip structures, so that
|
||
|
an IRQ controller driver can register an msi_chip, and a PCIe host
|
||
|
controller can find it, based on a 'struct device_node'.
|
||
|
|
||
|
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||
|
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
|
||
|
Acked-by: Rob Herring <rob.herring@calxeda.com>
|
||
|
---
|
||
|
drivers/of/of_pci.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
|
||
|
include/linux/msi.h | 2 ++
|
||
|
include/linux/of_pci.h | 12 ++++++++++++
|
||
|
3 files changed, 59 insertions(+)
|
||
|
|
||
|
--- a/drivers/of/of_pci.c
|
||
|
+++ b/drivers/of/of_pci.c
|
||
|
@@ -89,3 +89,48 @@ int of_pci_parse_bus_range(struct device
|
||
|
return 0;
|
||
|
}
|
||
|
EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
|
||
|
+
|
||
|
+#ifdef CONFIG_PCI_MSI
|
||
|
+
|
||
|
+static LIST_HEAD(of_pci_msi_chip_list);
|
||
|
+static DEFINE_MUTEX(of_pci_msi_chip_mutex);
|
||
|
+
|
||
|
+int of_pci_msi_chip_add(struct msi_chip *chip)
|
||
|
+{
|
||
|
+ if (!of_property_read_bool(chip->of_node, "msi-controller"))
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ mutex_lock(&of_pci_msi_chip_mutex);
|
||
|
+ list_add(&chip->list, &of_pci_msi_chip_list);
|
||
|
+ mutex_unlock(&of_pci_msi_chip_mutex);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+EXPORT_SYMBOL_GPL(of_pci_msi_chip_add);
|
||
|
+
|
||
|
+void of_pci_msi_chip_remove(struct msi_chip *chip)
|
||
|
+{
|
||
|
+ mutex_lock(&of_pci_msi_chip_mutex);
|
||
|
+ list_del(&chip->list);
|
||
|
+ mutex_unlock(&of_pci_msi_chip_mutex);
|
||
|
+}
|
||
|
+EXPORT_SYMBOL_GPL(of_pci_msi_chip_remove);
|
||
|
+
|
||
|
+struct msi_chip *of_pci_find_msi_chip_by_node(struct device_node *of_node)
|
||
|
+{
|
||
|
+ struct msi_chip *c;
|
||
|
+
|
||
|
+ mutex_lock(&of_pci_msi_chip_mutex);
|
||
|
+ list_for_each_entry(c, &of_pci_msi_chip_list, list) {
|
||
|
+ if (c->of_node == of_node) {
|
||
|
+ mutex_unlock(&of_pci_msi_chip_mutex);
|
||
|
+ return c;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ mutex_unlock(&of_pci_msi_chip_mutex);
|
||
|
+
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+EXPORT_SYMBOL_GPL(of_pci_find_msi_chip_by_node);
|
||
|
+
|
||
|
+#endif /* CONFIG_PCI_MSI */
|
||
|
--- a/include/linux/msi.h
|
||
|
+++ b/include/linux/msi.h
|
||
|
@@ -67,6 +67,8 @@ void default_restore_msi_irqs(struct pci
|
||
|
struct msi_chip {
|
||
|
struct module *owner;
|
||
|
struct device *dev;
|
||
|
+ struct device_node *of_node;
|
||
|
+ struct list_head list;
|
||
|
|
||
|
int (*setup_irq)(struct msi_chip *chip, struct pci_dev *dev,
|
||
|
struct msi_desc *desc);
|
||
|
--- a/include/linux/of_pci.h
|
||
|
+++ b/include/linux/of_pci.h
|
||
|
@@ -2,6 +2,7 @@
|
||
|
#define __OF_PCI_H
|
||
|
|
||
|
#include <linux/pci.h>
|
||
|
+#include <linux/msi.h>
|
||
|
|
||
|
struct pci_dev;
|
||
|
struct of_irq;
|
||
|
@@ -13,4 +14,15 @@ struct device_node *of_pci_find_child_de
|
||
|
int of_pci_get_devfn(struct device_node *np);
|
||
|
int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
|
||
|
|
||
|
+#if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
|
||
|
+int of_pci_msi_chip_add(struct msi_chip *chip);
|
||
|
+void of_pci_msi_chip_remove(struct msi_chip *chip);
|
||
|
+struct msi_chip *of_pci_find_msi_chip_by_node(struct device_node *of_node);
|
||
|
+#else
|
||
|
+static inline int of_pci_msi_chip_add(struct msi_chip *chip) { return -EINVAL; }
|
||
|
+static inline void of_pci_msi_chip_remove(struct msi_chip *chip) { }
|
||
|
+static inline struct msi_chip *
|
||
|
+of_pci_find_msi_chip_by_node(struct device_node *of_node) { return NULL; }
|
||
|
+#endif
|
||
|
+
|
||
|
#endif
|