50
50
#include <linux/irqdomain.h>
51
51
#include <linux/acpi.h>
52
52
#include <linux/sizes.h>
53
+ #include <linux/of_irq.h>
53
54
#include <asm/mshyperv.h>
54
55
55
56
/*
@@ -817,9 +818,17 @@ static int hv_pci_vec_irq_gic_domain_alloc(struct irq_domain *domain,
817
818
int ret ;
818
819
819
820
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
+ }
823
832
824
833
ret = irq_domain_alloc_irqs_parent (domain , virq , 1 , & fwspec );
825
834
if (ret )
@@ -887,10 +896,44 @@ static const struct irq_domain_ops hv_pci_domain_ops = {
887
896
.activate = hv_pci_vec_irq_domain_activate ,
888
897
};
889
898
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
+
890
932
static int hv_pci_irqchip_init (void )
891
933
{
892
934
static struct hv_pci_chip_data * chip_data ;
893
935
struct fwnode_handle * fn = NULL ;
936
+ struct irq_domain * irq_domain_parent = NULL ;
894
937
int ret = - ENOMEM ;
895
938
896
939
chip_data = kzalloc (sizeof (* chip_data ), GFP_KERNEL );
@@ -907,9 +950,24 @@ static int hv_pci_irqchip_init(void)
907
950
* way to ensure that all the corresponding devices are also gone and
908
951
* no interrupts will be generated.
909
952
*/
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 );
913
971
914
972
if (!hv_msi_gic_irq_domain ) {
915
973
pr_err ("Failed to create Hyper-V arm64 vPCI MSI IRQ domain\n" );
0 commit comments