aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuresh Warrier <warrier@linux.vnet.ibm.com>2016-08-19 01:35:49 -0400
committerPaul Mackerras <paulus@ozlabs.org>2016-09-09 02:17:59 -0400
commit4ee11c1a9f7cc20026bb66ac624533310a605312 (patch)
treea93e00dd3a4598ca60daff910a03079f188b92a4
parent07b1fdf5bd135d94eff2b3a6849b90c358963066 (diff)
powerpc/powernv: Provide facilities for EOI, usable from real mode
This adds a new function pnv_opal_pci_msi_eoi() which does the part of end-of-interrupt (EOI) handling of an MSI which involves doing an OPAL call. This function can be called in real mode. This doesn't just export pnv_ioda2_msi_eoi() because that does a call to icp_native_eoi(), which does not work in real mode. This also adds a function, is_pnv_opal_msi(), which KVM can call to check whether an interrupt is one for which we should be calling pnv_opal_pci_msi_eoi() when we need to do an EOI. [paulus@ozlabs.org - split out the addition of pnv_opal_pci_msi_eoi() from Suresh's patch "KVM: PPC: Book3S HV: Handle passthrough interrupts in guest"; added is_pnv_opal_msi(); wrote description.] Signed-off-by: Suresh Warrier <warrier@linux.vnet.ibm.com> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
-rw-r--r--arch/powerpc/include/asm/pnv-pci.h3
-rw-r--r--arch/powerpc/platforms/powernv/pci-ioda.c24
2 files changed, 23 insertions, 4 deletions
diff --git a/arch/powerpc/include/asm/pnv-pci.h b/arch/powerpc/include/asm/pnv-pci.h
index 0cbd8134ce81..1b46b52d3212 100644
--- a/arch/powerpc/include/asm/pnv-pci.h
+++ b/arch/powerpc/include/asm/pnv-pci.h
@@ -12,6 +12,7 @@
12 12
13#include <linux/pci.h> 13#include <linux/pci.h>
14#include <linux/pci_hotplug.h> 14#include <linux/pci_hotplug.h>
15#include <linux/irq.h>
15#include <misc/cxl-base.h> 16#include <misc/cxl-base.h>
16#include <asm/opal-api.h> 17#include <asm/opal-api.h>
17 18
@@ -33,6 +34,8 @@ int pnv_cxl_alloc_hwirqs(struct pci_dev *dev, int num);
33void pnv_cxl_release_hwirqs(struct pci_dev *dev, int hwirq, int num); 34void pnv_cxl_release_hwirqs(struct pci_dev *dev, int hwirq, int num);
34int pnv_cxl_get_irq_count(struct pci_dev *dev); 35int pnv_cxl_get_irq_count(struct pci_dev *dev);
35struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev); 36struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev);
37int64_t pnv_opal_pci_msi_eoi(struct irq_chip *chip, unsigned int hw_irq);
38bool is_pnv_opal_msi(struct irq_chip *chip);
36 39
37#ifdef CONFIG_CXL_BASE 40#ifdef CONFIG_CXL_BASE
38int pnv_cxl_alloc_hwirq_ranges(struct cxl_irq_ranges *irqs, 41int pnv_cxl_alloc_hwirq_ranges(struct cxl_irq_ranges *irqs,
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index fd9444f9fb0c..9ce48ae55062 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -2710,15 +2710,21 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,
2710} 2710}
2711 2711
2712#ifdef CONFIG_PCI_MSI 2712#ifdef CONFIG_PCI_MSI
2713static void pnv_ioda2_msi_eoi(struct irq_data *d) 2713int64_t pnv_opal_pci_msi_eoi(struct irq_chip *chip, unsigned int hw_irq)
2714{ 2714{
2715 unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
2716 struct irq_chip *chip = irq_data_get_irq_chip(d);
2717 struct pnv_phb *phb = container_of(chip, struct pnv_phb, 2715 struct pnv_phb *phb = container_of(chip, struct pnv_phb,
2718 ioda.irq_chip); 2716 ioda.irq_chip);
2717
2718 return opal_pci_msi_eoi(phb->opal_id, hw_irq);
2719}
2720
2721static void pnv_ioda2_msi_eoi(struct irq_data *d)
2722{
2719 int64_t rc; 2723 int64_t rc;
2724 unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
2725 struct irq_chip *chip = irq_data_get_irq_chip(d);
2720 2726
2721 rc = opal_pci_msi_eoi(phb->opal_id, hw_irq); 2727 rc = pnv_opal_pci_msi_eoi(chip, hw_irq);
2722 WARN_ON_ONCE(rc); 2728 WARN_ON_ONCE(rc);
2723 2729
2724 icp_native_eoi(d); 2730 icp_native_eoi(d);
@@ -2748,6 +2754,16 @@ void pnv_set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq)
2748 irq_set_chip(virq, &phb->ioda.irq_chip); 2754 irq_set_chip(virq, &phb->ioda.irq_chip);
2749} 2755}
2750 2756
2757/*
2758 * Returns true iff chip is something that we could call
2759 * pnv_opal_pci_msi_eoi for.
2760 */
2761bool is_pnv_opal_msi(struct irq_chip *chip)
2762{
2763 return chip->irq_eoi == pnv_ioda2_msi_eoi;
2764}
2765EXPORT_SYMBOL_GPL(is_pnv_opal_msi);
2766
2751static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, 2767static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
2752 unsigned int hwirq, unsigned int virq, 2768 unsigned int hwirq, unsigned int virq,
2753 unsigned int is_64, struct msi_msg *msg) 2769 unsigned int is_64, struct msi_msg *msg)