Skip to content

Commit d684f9b

Browse files
romank-msftliuw
authored andcommitted
PCI: hv: Get vPCI MSI IRQ domain from DeviceTree
The hyperv-pci driver uses ACPI for MSI IRQ domain configuration on arm64. It won't be able to do that in the VTL mode where only DeviceTree can be used. Update the hyperv-pci driver to get vPCI MSI IRQ domain in the DeviceTree case, too. Signed-off-by: Roman Kisel <romank@linux.microsoft.com> Acked-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Michael Kelley <mhklinux@outlook.com> Link: https://lore.kernel.org/r/20250428210742.435282-12-romank@linux.microsoft.com Signed-off-by: Wei Liu <wei.liu@kernel.org> Message-ID: <20250428210742.435282-12-romank@linux.microsoft.com>
1 parent ab7e531 commit d684f9b

File tree

1 file changed

+64
-6
lines changed

1 file changed

+64
-6
lines changed

drivers/pci/controller/pci-hyperv.c

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include <linux/irqdomain.h>
5151
#include <linux/acpi.h>
5252
#include <linux/sizes.h>
53+
#include <linux/of_irq.h>
5354
#include <asm/mshyperv.h>
5455

5556
/*
@@ -817,9 +818,17 @@ static int hv_pci_vec_irq_gic_domain_alloc(struct irq_domain *domain,
817818
int ret;
818819

819820
fwspec.fwnode = domain->parent->fwnode;
820-
fwspec.param_count = 2;
821-
fwspec.param[0] = hwirq;
822-
fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
821+
if (is_of_node(fwspec.fwnode)) {
822+
/* SPI lines for OF translations start at offset 32 */
823+
fwspec.param_count = 3;
824+
fwspec.param[0] = 0;
825+
fwspec.param[1] = hwirq - 32;
826+
fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
827+
} else {
828+
fwspec.param_count = 2;
829+
fwspec.param[0] = hwirq;
830+
fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
831+
}
823832

824833
ret = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
825834
if (ret)
@@ -887,10 +896,44 @@ static const struct irq_domain_ops hv_pci_domain_ops = {
887896
.activate = hv_pci_vec_irq_domain_activate,
888897
};
889898

899+
#ifdef CONFIG_OF
900+
901+
static struct irq_domain *hv_pci_of_irq_domain_parent(void)
902+
{
903+
struct device_node *parent;
904+
struct irq_domain *domain;
905+
906+
parent = of_irq_find_parent(hv_get_vmbus_root_device()->of_node);
907+
if (!parent)
908+
return NULL;
909+
domain = irq_find_host(parent);
910+
of_node_put(parent);
911+
912+
return domain;
913+
}
914+
915+
#endif
916+
917+
#ifdef CONFIG_ACPI
918+
919+
static struct irq_domain *hv_pci_acpi_irq_domain_parent(void)
920+
{
921+
acpi_gsi_domain_disp_fn gsi_domain_disp_fn;
922+
923+
gsi_domain_disp_fn = acpi_get_gsi_dispatcher();
924+
if (!gsi_domain_disp_fn)
925+
return NULL;
926+
return irq_find_matching_fwnode(gsi_domain_disp_fn(0),
927+
DOMAIN_BUS_ANY);
928+
}
929+
930+
#endif
931+
890932
static int hv_pci_irqchip_init(void)
891933
{
892934
static struct hv_pci_chip_data *chip_data;
893935
struct fwnode_handle *fn = NULL;
936+
struct irq_domain *irq_domain_parent = NULL;
894937
int ret = -ENOMEM;
895938

896939
chip_data = kzalloc(sizeof(*chip_data), GFP_KERNEL);
@@ -907,9 +950,24 @@ static int hv_pci_irqchip_init(void)
907950
* way to ensure that all the corresponding devices are also gone and
908951
* no interrupts will be generated.
909952
*/
910-
hv_msi_gic_irq_domain = acpi_irq_create_hierarchy(0, HV_PCI_MSI_SPI_NR,
911-
fn, &hv_pci_domain_ops,
912-
chip_data);
953+
#ifdef CONFIG_ACPI
954+
if (!acpi_disabled)
955+
irq_domain_parent = hv_pci_acpi_irq_domain_parent();
956+
#endif
957+
#ifdef CONFIG_OF
958+
if (!irq_domain_parent)
959+
irq_domain_parent = hv_pci_of_irq_domain_parent();
960+
#endif
961+
if (!irq_domain_parent) {
962+
WARN_ONCE(1, "Invalid firmware configuration for VMBus interrupts\n");
963+
ret = -EINVAL;
964+
goto free_chip;
965+
}
966+
967+
hv_msi_gic_irq_domain = irq_domain_create_hierarchy(irq_domain_parent, 0,
968+
HV_PCI_MSI_SPI_NR,
969+
fn, &hv_pci_domain_ops,
970+
chip_data);
913971

914972
if (!hv_msi_gic_irq_domain) {
915973
pr_err("Failed to create Hyper-V arm64 vPCI MSI IRQ domain\n");

0 commit comments

Comments
 (0)