|
Olaf Hering |
e9d267 |
From: Sunil Muthuswamy <sunilmut@microsoft.com>
|
|
Olaf Hering |
e9d267 |
Date: Wed, 5 Jan 2022 11:32:36 -0800
|
|
Takashi Iwai |
12240b |
Patch-mainline: v5.17-rc1
|
|
Takashi Iwai |
12240b |
Git-commit: d9932b46915664c88709d59927fa67e797adec56
|
|
Olaf Hering |
e9d267 |
Subject: PCI: hv: Add arm64 Hyper-V vPCI support
|
|
Olaf Hering |
e9d267 |
References: jsc#SLE-17855,bsc#1186071
|
|
Olaf Hering |
e9d267 |
|
|
Olaf Hering |
e9d267 |
Add arm64 Hyper-V vPCI support by implementing the arch specific
|
|
Olaf Hering |
e9d267 |
interfaces. Introduce an IRQ domain and chip specific to Hyper-v vPCI that
|
|
Olaf Hering |
e9d267 |
is based on SPIs. The IRQ domain parents itself to the arch GIC IRQ domain
|
|
Olaf Hering |
e9d267 |
for basic vector management.
|
|
Olaf Hering |
e9d267 |
|
|
Olaf Hering |
e9d267 |
Signed-off-by: Sunil Muthuswamy <sunilmut@microsoft.com>
|
|
Olaf Hering |
e9d267 |
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
|
|
Olaf Hering |
e9d267 |
Reviewed-by: Marc Zyngier <maz@kernel.org>
|
|
Olaf Hering |
e9d267 |
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
|
|
Olaf Hering |
e9d267 |
Acked-by: Olaf Hering <ohering@suse.de>
|
|
Olaf Hering |
e9d267 |
---
|
|
Olaf Hering |
e9d267 |
arch/arm64/include/asm/hyperv-tlfs.h | 9 +
|
|
Olaf Hering |
e9d267 |
drivers/pci/Kconfig | 2 +-
|
|
Olaf Hering |
e9d267 |
drivers/pci/controller/Kconfig | 2 +-
|
|
Olaf Hering |
e9d267 |
drivers/pci/controller/pci-hyperv.c | 235 +++++++++++++++++++++-
|
|
Olaf Hering |
e9d267 |
4 files changed, 245 insertions(+), 3 deletions(-)
|
|
Olaf Hering |
e9d267 |
|
|
Olaf Hering |
e9d267 |
diff --git a/arch/arm64/include/asm/hyperv-tlfs.h b/arch/arm64/include/asm/hyperv-tlfs.h
|
|
Olaf Hering |
e9d267 |
--- a/arch/arm64/include/asm/hyperv-tlfs.h
|
|
Olaf Hering |
e9d267 |
+++ b/arch/arm64/include/asm/hyperv-tlfs.h
|
|
Olaf Hering |
e9d267 |
@@ -64,6 +64,15 @@
|
|
Olaf Hering |
e9d267 |
#define HV_REGISTER_STIMER0_CONFIG 0x000B0000
|
|
Olaf Hering |
e9d267 |
#define HV_REGISTER_STIMER0_COUNT 0x000B0001
|
|
Olaf Hering |
e9d267 |
|
|
Olaf Hering |
e9d267 |
+union hv_msi_entry {
|
|
Olaf Hering |
e9d267 |
+ u64 as_uint64[2];
|
|
Olaf Hering |
e9d267 |
+ struct {
|
|
Olaf Hering |
e9d267 |
+ u64 address;
|
|
Olaf Hering |
e9d267 |
+ u32 data;
|
|
Olaf Hering |
e9d267 |
+ u32 reserved;
|
|
Olaf Hering |
e9d267 |
+ } __packed;
|
|
Olaf Hering |
e9d267 |
+};
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
#include <asm-generic/hyperv-tlfs.h>
|
|
Olaf Hering |
e9d267 |
|
|
Olaf Hering |
e9d267 |
#endif
|
|
Olaf Hering |
e9d267 |
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
|
|
Olaf Hering |
e9d267 |
--- a/drivers/pci/Kconfig
|
|
Olaf Hering |
e9d267 |
+++ b/drivers/pci/Kconfig
|
|
Olaf Hering |
e9d267 |
@@ -184,7 +184,7 @@ config PCI_LABEL
|
|
Olaf Hering |
e9d267 |
|
|
Olaf Hering |
e9d267 |
config PCI_HYPERV
|
|
Olaf Hering |
e9d267 |
tristate "Hyper-V PCI Frontend"
|
|
Olaf Hering |
e9d267 |
- depends on X86_64 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && SYSFS
|
|
Olaf Hering |
e9d267 |
+ depends on ((X86 && X86_64) || ARM64) && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && SYSFS
|
|
Olaf Hering |
e9d267 |
select PCI_HYPERV_INTERFACE
|
|
Olaf Hering |
e9d267 |
help
|
|
Olaf Hering |
e9d267 |
The PCI device frontend driver allows the kernel to import arbitrary
|
|
Olaf Hering |
e9d267 |
diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
|
|
Olaf Hering |
e9d267 |
--- a/drivers/pci/controller/Kconfig
|
|
Olaf Hering |
e9d267 |
+++ b/drivers/pci/controller/Kconfig
|
|
Olaf Hering |
e9d267 |
@@ -281,7 +281,7 @@ config PCIE_BRCMSTB
|
|
Olaf Hering |
e9d267 |
|
|
Olaf Hering |
e9d267 |
config PCI_HYPERV_INTERFACE
|
|
Olaf Hering |
e9d267 |
tristate "Hyper-V PCI Interface"
|
|
Olaf Hering |
e9d267 |
- depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64
|
|
Olaf Hering |
e9d267 |
+ depends on ((X86 && X86_64) || ARM64) && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN
|
|
Olaf Hering |
e9d267 |
help
|
|
Olaf Hering |
e9d267 |
The Hyper-V PCI Interface is a helper driver allows other drivers to
|
|
Olaf Hering |
e9d267 |
have a common interface with the Hyper-V PCI frontend driver.
|
|
Olaf Hering |
e9d267 |
diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
|
|
Olaf Hering |
e9d267 |
--- a/drivers/pci/controller/pci-hyperv.c
|
|
Olaf Hering |
e9d267 |
+++ b/drivers/pci/controller/pci-hyperv.c
|
|
Olaf Hering |
e9d267 |
@@ -47,6 +47,8 @@
|
|
Olaf Hering |
e9d267 |
#include <linux/msi.h>
|
|
Olaf Hering |
e9d267 |
#include <linux/hyperv.h>
|
|
Olaf Hering |
e9d267 |
#include <linux/refcount.h>
|
|
Olaf Hering |
e9d267 |
+#include <linux/irqdomain.h>
|
|
Olaf Hering |
e9d267 |
+#include <linux/acpi.h>
|
|
Olaf Hering |
e9d267 |
#include <asm/mshyperv.h>
|
|
Olaf Hering |
e9d267 |
|
|
Olaf Hering |
e9d267 |
/*
|
|
Olaf Hering |
e9d267 |
@@ -614,7 +616,230 @@ static int hv_msi_prepare(struct irq_domain *domain, struct device *dev,
|
|
Olaf Hering |
e9d267 |
{
|
|
Olaf Hering |
e9d267 |
return pci_msi_prepare(domain, dev, nvec, info);
|
|
Olaf Hering |
e9d267 |
}
|
|
Olaf Hering |
e9d267 |
-#endif /* CONFIG_X86 */
|
|
Olaf Hering |
e9d267 |
+#elif defined(CONFIG_ARM64)
|
|
Olaf Hering |
e9d267 |
+/*
|
|
Olaf Hering |
e9d267 |
+ * SPI vectors to use for vPCI; arch SPIs range is [32, 1019], but leaving a bit
|
|
Olaf Hering |
e9d267 |
+ * of room at the start to allow for SPIs to be specified through ACPI and
|
|
Olaf Hering |
e9d267 |
+ * starting with a power of two to satisfy power of 2 multi-MSI requirement.
|
|
Olaf Hering |
e9d267 |
+ */
|
|
Olaf Hering |
e9d267 |
+#define HV_PCI_MSI_SPI_START 64
|
|
Olaf Hering |
e9d267 |
+#define HV_PCI_MSI_SPI_NR (1020 - HV_PCI_MSI_SPI_START)
|
|
Olaf Hering |
e9d267 |
+#define DELIVERY_MODE 0
|
|
Olaf Hering |
e9d267 |
+#define FLOW_HANDLER NULL
|
|
Olaf Hering |
e9d267 |
+#define FLOW_NAME NULL
|
|
Olaf Hering |
e9d267 |
+#define hv_msi_prepare NULL
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+struct hv_pci_chip_data {
|
|
Olaf Hering |
e9d267 |
+ DECLARE_BITMAP(spi_map, HV_PCI_MSI_SPI_NR);
|
|
Olaf Hering |
e9d267 |
+ struct mutex map_lock;
|
|
Olaf Hering |
e9d267 |
+};
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+/* Hyper-V vPCI MSI GIC IRQ domain */
|
|
Olaf Hering |
e9d267 |
+static struct irq_domain *hv_msi_gic_irq_domain;
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+/* Hyper-V PCI MSI IRQ chip */
|
|
Olaf Hering |
e9d267 |
+static struct irq_chip hv_arm64_msi_irq_chip = {
|
|
Olaf Hering |
e9d267 |
+ .name = "MSI",
|
|
Olaf Hering |
e9d267 |
+ .irq_set_affinity = irq_chip_set_affinity_parent,
|
|
Olaf Hering |
e9d267 |
+ .irq_eoi = irq_chip_eoi_parent,
|
|
Olaf Hering |
e9d267 |
+ .irq_mask = irq_chip_mask_parent,
|
|
Olaf Hering |
e9d267 |
+ .irq_unmask = irq_chip_unmask_parent
|
|
Olaf Hering |
e9d267 |
+};
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+static unsigned int hv_msi_get_int_vector(struct irq_data *irqd)
|
|
Olaf Hering |
e9d267 |
+{
|
|
Olaf Hering |
e9d267 |
+ return irqd->parent_data->hwirq;
|
|
Olaf Hering |
e9d267 |
+}
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+static void hv_set_msi_entry_from_desc(union hv_msi_entry *msi_entry,
|
|
Olaf Hering |
e9d267 |
+ struct msi_desc *msi_desc)
|
|
Olaf Hering |
e9d267 |
+{
|
|
Olaf Hering |
e9d267 |
+ msi_entry->address = ((u64)msi_desc->msg.address_hi << 32) |
|
|
Olaf Hering |
e9d267 |
+ msi_desc->msg.address_lo;
|
|
Olaf Hering |
e9d267 |
+ msi_entry->data = msi_desc->msg.data;
|
|
Olaf Hering |
e9d267 |
+}
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+/*
|
|
Olaf Hering |
e9d267 |
+ * @nr_bm_irqs: Indicates the number of IRQs that were allocated from
|
|
Olaf Hering |
e9d267 |
+ * the bitmap.
|
|
Olaf Hering |
e9d267 |
+ * @nr_dom_irqs: Indicates the number of IRQs that were allocated from
|
|
Olaf Hering |
e9d267 |
+ * the parent domain.
|
|
Olaf Hering |
e9d267 |
+ */
|
|
Olaf Hering |
e9d267 |
+static void hv_pci_vec_irq_free(struct irq_domain *domain,
|
|
Olaf Hering |
e9d267 |
+ unsigned int virq,
|
|
Olaf Hering |
e9d267 |
+ unsigned int nr_bm_irqs,
|
|
Olaf Hering |
e9d267 |
+ unsigned int nr_dom_irqs)
|
|
Olaf Hering |
e9d267 |
+{
|
|
Olaf Hering |
e9d267 |
+ struct hv_pci_chip_data *chip_data = domain->host_data;
|
|
Olaf Hering |
e9d267 |
+ struct irq_data *d = irq_domain_get_irq_data(domain, virq);
|
|
Olaf Hering |
e9d267 |
+ int first = d->hwirq - HV_PCI_MSI_SPI_START;
|
|
Olaf Hering |
e9d267 |
+ int i;
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ mutex_lock(&chip_data->map_lock);
|
|
Olaf Hering |
e9d267 |
+ bitmap_release_region(chip_data->spi_map,
|
|
Olaf Hering |
e9d267 |
+ first,
|
|
Olaf Hering |
e9d267 |
+ get_count_order(nr_bm_irqs));
|
|
Olaf Hering |
e9d267 |
+ mutex_unlock(&chip_data->map_lock);
|
|
Olaf Hering |
e9d267 |
+ for (i = 0; i < nr_dom_irqs; i++) {
|
|
Olaf Hering |
e9d267 |
+ if (i)
|
|
Olaf Hering |
e9d267 |
+ d = irq_domain_get_irq_data(domain, virq + i);
|
|
Olaf Hering |
e9d267 |
+ irq_domain_reset_irq_data(d);
|
|
Olaf Hering |
e9d267 |
+ }
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ irq_domain_free_irqs_parent(domain, virq, nr_dom_irqs);
|
|
Olaf Hering |
e9d267 |
+}
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+static void hv_pci_vec_irq_domain_free(struct irq_domain *domain,
|
|
Olaf Hering |
e9d267 |
+ unsigned int virq,
|
|
Olaf Hering |
e9d267 |
+ unsigned int nr_irqs)
|
|
Olaf Hering |
e9d267 |
+{
|
|
Olaf Hering |
e9d267 |
+ hv_pci_vec_irq_free(domain, virq, nr_irqs, nr_irqs);
|
|
Olaf Hering |
e9d267 |
+}
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+static int hv_pci_vec_alloc_device_irq(struct irq_domain *domain,
|
|
Olaf Hering |
e9d267 |
+ unsigned int nr_irqs,
|
|
Olaf Hering |
e9d267 |
+ irq_hw_number_t *hwirq)
|
|
Olaf Hering |
e9d267 |
+{
|
|
Olaf Hering |
e9d267 |
+ struct hv_pci_chip_data *chip_data = domain->host_data;
|
|
Olaf Hering |
e9d267 |
+ unsigned int index;
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ /* Find and allocate region from the SPI bitmap */
|
|
Olaf Hering |
e9d267 |
+ mutex_lock(&chip_data->map_lock);
|
|
Olaf Hering |
e9d267 |
+ index = bitmap_find_free_region(chip_data->spi_map,
|
|
Olaf Hering |
e9d267 |
+ HV_PCI_MSI_SPI_NR,
|
|
Olaf Hering |
e9d267 |
+ get_count_order(nr_irqs));
|
|
Olaf Hering |
e9d267 |
+ mutex_unlock(&chip_data->map_lock);
|
|
Olaf Hering |
e9d267 |
+ if (index < 0)
|
|
Olaf Hering |
e9d267 |
+ return -ENOSPC;
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ *hwirq = index + HV_PCI_MSI_SPI_START;
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ return 0;
|
|
Olaf Hering |
e9d267 |
+}
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+static int hv_pci_vec_irq_gic_domain_alloc(struct irq_domain *domain,
|
|
Olaf Hering |
e9d267 |
+ unsigned int virq,
|
|
Olaf Hering |
e9d267 |
+ irq_hw_number_t hwirq)
|
|
Olaf Hering |
e9d267 |
+{
|
|
Olaf Hering |
e9d267 |
+ struct irq_fwspec fwspec;
|
|
Olaf Hering |
e9d267 |
+ struct irq_data *d;
|
|
Olaf Hering |
e9d267 |
+ int ret;
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ fwspec.fwnode = domain->parent->fwnode;
|
|
Olaf Hering |
e9d267 |
+ fwspec.param_count = 2;
|
|
Olaf Hering |
e9d267 |
+ fwspec.param[0] = hwirq;
|
|
Olaf Hering |
e9d267 |
+ fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ ret = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
|
|
Olaf Hering |
e9d267 |
+ if (ret)
|
|
Olaf Hering |
e9d267 |
+ return ret;
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ /*
|
|
Olaf Hering |
e9d267 |
+ * Since the interrupt specifier is not coming from ACPI or DT, the
|
|
Olaf Hering |
e9d267 |
+ * trigger type will need to be set explicitly. Otherwise, it will be
|
|
Olaf Hering |
e9d267 |
+ * set to whatever is in the GIC configuration.
|
|
Olaf Hering |
e9d267 |
+ */
|
|
Olaf Hering |
e9d267 |
+ d = irq_domain_get_irq_data(domain->parent, virq);
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ return d->chip->irq_set_type(d, IRQ_TYPE_EDGE_RISING);
|
|
Olaf Hering |
e9d267 |
+}
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+static int hv_pci_vec_irq_domain_alloc(struct irq_domain *domain,
|
|
Olaf Hering |
e9d267 |
+ unsigned int virq, unsigned int nr_irqs,
|
|
Olaf Hering |
e9d267 |
+ void *args)
|
|
Olaf Hering |
e9d267 |
+{
|
|
Olaf Hering |
e9d267 |
+ irq_hw_number_t hwirq;
|
|
Olaf Hering |
e9d267 |
+ unsigned int i;
|
|
Olaf Hering |
e9d267 |
+ int ret;
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ ret = hv_pci_vec_alloc_device_irq(domain, nr_irqs, &hwirq);
|
|
Olaf Hering |
e9d267 |
+ if (ret)
|
|
Olaf Hering |
e9d267 |
+ return ret;
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ for (i = 0; i < nr_irqs; i++) {
|
|
Olaf Hering |
e9d267 |
+ ret = hv_pci_vec_irq_gic_domain_alloc(domain, virq + i,
|
|
Olaf Hering |
e9d267 |
+ hwirq + i);
|
|
Olaf Hering |
e9d267 |
+ if (ret) {
|
|
Olaf Hering |
e9d267 |
+ hv_pci_vec_irq_free(domain, virq, nr_irqs, i);
|
|
Olaf Hering |
e9d267 |
+ return ret;
|
|
Olaf Hering |
e9d267 |
+ }
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ irq_domain_set_hwirq_and_chip(domain, virq + i,
|
|
Olaf Hering |
e9d267 |
+ hwirq + i,
|
|
Olaf Hering |
e9d267 |
+ &hv_arm64_msi_irq_chip,
|
|
Olaf Hering |
e9d267 |
+ domain->host_data);
|
|
Olaf Hering |
e9d267 |
+ pr_debug("pID:%d vID:%u\n", (int)(hwirq + i), virq + i);
|
|
Olaf Hering |
e9d267 |
+ }
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ return 0;
|
|
Olaf Hering |
e9d267 |
+}
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+/*
|
|
Olaf Hering |
e9d267 |
+ * Pick the first cpu as the irq affinity that can be temporarily used for
|
|
Olaf Hering |
e9d267 |
+ * composing MSI from the hypervisor. GIC will eventually set the right
|
|
Olaf Hering |
e9d267 |
+ * affinity for the irq and the 'unmask' will retarget the interrupt to that
|
|
Olaf Hering |
e9d267 |
+ * cpu.
|
|
Olaf Hering |
e9d267 |
+ */
|
|
Olaf Hering |
e9d267 |
+static int hv_pci_vec_irq_domain_activate(struct irq_domain *domain,
|
|
Olaf Hering |
e9d267 |
+ struct irq_data *irqd, bool reserve)
|
|
Olaf Hering |
e9d267 |
+{
|
|
Olaf Hering |
e9d267 |
+ int cpu = cpumask_first(cpu_present_mask);
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ irq_data_update_effective_affinity(irqd, cpumask_of(cpu));
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ return 0;
|
|
Olaf Hering |
e9d267 |
+}
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+static const struct irq_domain_ops hv_pci_domain_ops = {
|
|
Olaf Hering |
e9d267 |
+ .alloc = hv_pci_vec_irq_domain_alloc,
|
|
Olaf Hering |
e9d267 |
+ .free = hv_pci_vec_irq_domain_free,
|
|
Olaf Hering |
e9d267 |
+ .activate = hv_pci_vec_irq_domain_activate,
|
|
Olaf Hering |
e9d267 |
+};
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+static int hv_pci_irqchip_init(void)
|
|
Olaf Hering |
e9d267 |
+{
|
|
Olaf Hering |
e9d267 |
+ static struct hv_pci_chip_data *chip_data;
|
|
Olaf Hering |
e9d267 |
+ struct fwnode_handle *fn = NULL;
|
|
Olaf Hering |
e9d267 |
+ int ret = -ENOMEM;
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ chip_data = kzalloc(sizeof(*chip_data), GFP_KERNEL);
|
|
Olaf Hering |
e9d267 |
+ if (!chip_data)
|
|
Olaf Hering |
e9d267 |
+ return ret;
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ mutex_init(&chip_data->map_lock);
|
|
Olaf Hering |
e9d267 |
+ fn = irq_domain_alloc_named_fwnode("hv_vpci_arm64");
|
|
Olaf Hering |
e9d267 |
+ if (!fn)
|
|
Olaf Hering |
e9d267 |
+ goto free_chip;
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ /*
|
|
Olaf Hering |
e9d267 |
+ * IRQ domain once enabled, should not be removed since there is no
|
|
Olaf Hering |
e9d267 |
+ * way to ensure that all the corresponding devices are also gone and
|
|
Olaf Hering |
e9d267 |
+ * no interrupts will be generated.
|
|
Olaf Hering |
e9d267 |
+ */
|
|
Olaf Hering |
e9d267 |
+ hv_msi_gic_irq_domain = acpi_irq_create_hierarchy(0, HV_PCI_MSI_SPI_NR,
|
|
Olaf Hering |
e9d267 |
+ fn, &hv_pci_domain_ops,
|
|
Olaf Hering |
e9d267 |
+ chip_data);
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ if (!hv_msi_gic_irq_domain) {
|
|
Olaf Hering |
e9d267 |
+ pr_err("Failed to create Hyper-V arm64 vPCI MSI IRQ domain\n");
|
|
Olaf Hering |
e9d267 |
+ goto free_chip;
|
|
Olaf Hering |
e9d267 |
+ }
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ return 0;
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+free_chip:
|
|
Olaf Hering |
e9d267 |
+ kfree(chip_data);
|
|
Olaf Hering |
e9d267 |
+ if (fn)
|
|
Olaf Hering |
e9d267 |
+ irq_domain_free_fwnode(fn);
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+ return ret;
|
|
Olaf Hering |
e9d267 |
+}
|
|
Olaf Hering |
e9d267 |
+
|
|
Olaf Hering |
e9d267 |
+static struct irq_domain *hv_pci_get_root_domain(void)
|
|
Olaf Hering |
e9d267 |
+{
|
|
Olaf Hering |
e9d267 |
+ return hv_msi_gic_irq_domain;
|
|
Olaf Hering |
e9d267 |
+}
|
|
Olaf Hering |
e9d267 |
+#endif /* CONFIG_ARM64 */
|
|
Olaf Hering |
e9d267 |
|
|
Olaf Hering |
e9d267 |
/**
|
|
Olaf Hering |
e9d267 |
* hv_pci_generic_compl() - Invoked for a completion packet
|
|
Olaf Hering |
e9d267 |
@@ -1227,6 +1452,8 @@ static void hv_msi_free(struct irq_domain *domain, struct msi_domain_info *info,
|
|
Olaf Hering |
e9d267 |
static void hv_irq_mask(struct irq_data *data)
|
|
Olaf Hering |
e9d267 |
{
|
|
Olaf Hering |
e9d267 |
pci_msi_mask_irq(data);
|
|
Olaf Hering |
e9d267 |
+ if (data->parent_data->chip->irq_mask)
|
|
Olaf Hering |
e9d267 |
+ irq_chip_mask_parent(data);
|
|
Olaf Hering |
e9d267 |
}
|
|
Olaf Hering |
e9d267 |
|
|
Olaf Hering |
e9d267 |
/**
|
|
Olaf Hering |
e9d267 |
@@ -1343,6 +1570,8 @@ exit_unlock:
|
|
Olaf Hering |
e9d267 |
dev_err(&hbus->hdev->device,
|
|
Olaf Hering |
e9d267 |
"%s() failed: %#llx", __func__, res);
|
|
Olaf Hering |
e9d267 |
|
|
Olaf Hering |
e9d267 |
+ if (data->parent_data->chip->irq_unmask)
|
|
Olaf Hering |
e9d267 |
+ irq_chip_unmask_parent(data);
|
|
Olaf Hering |
e9d267 |
pci_msi_unmask_irq(data);
|
|
Olaf Hering |
e9d267 |
}
|
|
Olaf Hering |
e9d267 |
|
|
Olaf Hering |
e9d267 |
@@ -1618,7 +1847,11 @@ static struct irq_chip hv_msi_irq_chip = {
|
|
Olaf Hering |
e9d267 |
.name = "Hyper-V PCIe MSI",
|
|
Olaf Hering |
e9d267 |
.irq_compose_msi_msg = hv_compose_msi_msg,
|
|
Olaf Hering |
e9d267 |
.irq_set_affinity = irq_chip_set_affinity_parent,
|
|
Olaf Hering |
e9d267 |
+#ifdef CONFIG_X86
|
|
Olaf Hering |
e9d267 |
.irq_ack = irq_chip_ack_parent,
|
|
Olaf Hering |
e9d267 |
+#elif defined(CONFIG_ARM64)
|
|
Olaf Hering |
e9d267 |
+ .irq_eoi = irq_chip_eoi_parent,
|
|
Olaf Hering |
e9d267 |
+#endif
|
|
Olaf Hering |
e9d267 |
.irq_mask = hv_irq_mask,
|
|
Olaf Hering |
e9d267 |
.irq_unmask = hv_irq_unmask,
|
|
Olaf Hering |
e9d267 |
};
|