diff options
author | Suresh Warrier <warrier@linux.vnet.ibm.com> | 2016-08-19 01:35:49 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@ozlabs.org> | 2016-09-09 02:17:59 -0400 |
commit | 4ee11c1a9f7cc20026bb66ac624533310a605312 (patch) | |
tree | a93e00dd3a4598ca60daff910a03079f188b92a4 | |
parent | 07b1fdf5bd135d94eff2b3a6849b90c358963066 (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.h | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/pci-ioda.c | 24 |
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); | |||
33 | void pnv_cxl_release_hwirqs(struct pci_dev *dev, int hwirq, int num); | 34 | void pnv_cxl_release_hwirqs(struct pci_dev *dev, int hwirq, int num); |
34 | int pnv_cxl_get_irq_count(struct pci_dev *dev); | 35 | int pnv_cxl_get_irq_count(struct pci_dev *dev); |
35 | struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev); | 36 | struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev); |
37 | int64_t pnv_opal_pci_msi_eoi(struct irq_chip *chip, unsigned int hw_irq); | ||
38 | bool is_pnv_opal_msi(struct irq_chip *chip); | ||
36 | 39 | ||
37 | #ifdef CONFIG_CXL_BASE | 40 | #ifdef CONFIG_CXL_BASE |
38 | int pnv_cxl_alloc_hwirq_ranges(struct cxl_irq_ranges *irqs, | 41 | int 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 |
2713 | static void pnv_ioda2_msi_eoi(struct irq_data *d) | 2713 | int64_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 | |||
2721 | static 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 | */ | ||
2761 | bool is_pnv_opal_msi(struct irq_chip *chip) | ||
2762 | { | ||
2763 | return chip->irq_eoi == pnv_ioda2_msi_eoi; | ||
2764 | } | ||
2765 | EXPORT_SYMBOL_GPL(is_pnv_opal_msi); | ||
2766 | |||
2751 | static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, | 2767 | static 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) |