mvebu: backport mainline patches from kernel 3.12
[openwrt.git] / target / linux / mvebu / patches-3.10 / 0072-PCI-Introduce-new-MSI-chip-infrastructure.patch
diff --git a/target/linux/mvebu/patches-3.10/0072-PCI-Introduce-new-MSI-chip-infrastructure.patch b/target/linux/mvebu/patches-3.10/0072-PCI-Introduce-new-MSI-chip-infrastructure.patch
new file mode 100644 (file)
index 0000000..291a3b3
--- /dev/null
@@ -0,0 +1,108 @@
+From 9c6ddccbbfaf789beccc6a1d87abe9bc60dc570f Mon Sep 17 00:00:00 2001
+From: Thierry Reding <thierry.reding@avionic-design.de>
+Date: Thu, 6 Jun 2013 18:20:29 +0200
+Subject: [PATCH 072/203] PCI: Introduce new MSI chip infrastructure
+
+The new struct msi_chip is used to associated an MSI controller with a
+PCI bus. It is automatically handed down from the root to its children
+during bus enumeration.
+
+This patch provides default (weak) implementations for the architecture-
+specific MSI functions (arch_setup_msi_irq(), arch_teardown_msi_irq()
+and arch_msi_check_device()) which check if a PCI device's bus has an
+attached MSI chip and forward the call appropriately.
+
+Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Acked-by: Bjorn Helgaas <bhelgaas@google.com>
+Tested-by: Daniel Price <daniel.price@gmail.com>
+Tested-by: Thierry Reding <thierry.reding@gmail.com>
+---
+ drivers/pci/msi.c   | 27 +++++++++++++++++++++++++--
+ drivers/pci/probe.c |  1 +
+ include/linux/msi.h | 11 +++++++++++
+ include/linux/pci.h |  1 +
+ 4 files changed, 38 insertions(+), 2 deletions(-)
+
+--- a/drivers/pci/msi.c
++++ b/drivers/pci/msi.c
+@@ -32,16 +32,39 @@ static int pci_msi_enable = 1;
+ int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+ {
+-      return -EINVAL;
++      struct msi_chip *chip = dev->bus->msi;
++      int err;
++
++      if (!chip || !chip->setup_irq)
++              return -EINVAL;
++
++      err = chip->setup_irq(chip, dev, desc);
++      if (err < 0)
++              return err;
++
++      irq_set_chip_data(desc->irq, chip);
++
++      return 0;
+ }
+ void __weak arch_teardown_msi_irq(unsigned int irq)
+ {
++      struct msi_chip *chip = irq_get_chip_data(irq);
++
++      if (!chip || !chip->teardown_irq)
++              return;
++
++      chip->teardown_irq(chip, irq);
+ }
+ int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
+ {
+-      return 0;
++      struct msi_chip *chip = dev->bus->msi;
++
++      if (!chip || !chip->check_device)
++              return 0;
++
++      return chip->check_device(chip, dev, nvec, type);
+ }
+ int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -634,6 +634,7 @@ static struct pci_bus *pci_alloc_child_b
+       child->parent = parent;
+       child->ops = parent->ops;
++      child->msi = parent->msi;
+       child->sysdata = parent->sysdata;
+       child->bus_flags = parent->bus_flags;
+--- a/include/linux/msi.h
++++ b/include/linux/msi.h
+@@ -64,4 +64,15 @@ void arch_restore_msi_irqs(struct pci_de
+ void default_teardown_msi_irqs(struct pci_dev *dev);
+ void default_restore_msi_irqs(struct pci_dev *dev, int irq);
++struct msi_chip {
++      struct module *owner;
++      struct device *dev;
++
++      int (*setup_irq)(struct msi_chip *chip, struct pci_dev *dev,
++                       struct msi_desc *desc);
++      void (*teardown_irq)(struct msi_chip *chip, unsigned int irq);
++      int (*check_device)(struct msi_chip *chip, struct pci_dev *dev,
++                          int nvec, int type);
++};
++
+ #endif /* LINUX_MSI_H */
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -432,6 +432,7 @@ struct pci_bus {
+       struct resource busn_res;       /* bus numbers routed to this bus */
+       struct pci_ops  *ops;           /* configuration access functions */
++      struct msi_chip *msi;           /* MSI controller */
+       void            *sysdata;       /* hook for sys-specific extension */
+       struct proc_dir_entry *procdir; /* directory entry in /proc/bus/pci */