@@ -616,6 +616,121 @@ static int hv_msi_prepare(struct irq_domain *domain, struct device *dev,
616616{
617617 return pci_msi_prepare (domain , dev , nvec , info );
618618}
619+
620+ /**
621+ * hv_arch_irq_unmask() - "Unmask" the IRQ by setting its current
622+ * affinity.
623+ * @data: Describes the IRQ
624+ *
625+ * Build new a destination for the MSI and make a hypercall to
626+ * update the Interrupt Redirection Table. "Device Logical ID"
627+ * is built out of this PCI bus's instance GUID and the function
628+ * number of the device.
629+ */
630+ static void hv_arch_irq_unmask (struct irq_data * data )
631+ {
632+ struct msi_desc * msi_desc = irq_data_get_msi_desc (data );
633+ struct hv_retarget_device_interrupt * params ;
634+ struct hv_pcibus_device * hbus ;
635+ struct cpumask * dest ;
636+ cpumask_var_t tmp ;
637+ struct pci_bus * pbus ;
638+ struct pci_dev * pdev ;
639+ unsigned long flags ;
640+ u32 var_size = 0 ;
641+ int cpu , nr_bank ;
642+ u64 res ;
643+
644+ dest = irq_data_get_effective_affinity_mask (data );
645+ pdev = msi_desc_to_pci_dev (msi_desc );
646+ pbus = pdev -> bus ;
647+ hbus = container_of (pbus -> sysdata , struct hv_pcibus_device , sysdata );
648+
649+ spin_lock_irqsave (& hbus -> retarget_msi_interrupt_lock , flags );
650+
651+ params = & hbus -> retarget_msi_interrupt_params ;
652+ memset (params , 0 , sizeof (* params ));
653+ params -> partition_id = HV_PARTITION_ID_SELF ;
654+ params -> int_entry .source = HV_INTERRUPT_SOURCE_MSI ;
655+ hv_set_msi_entry_from_desc (& params -> int_entry .msi_entry , msi_desc );
656+ params -> device_id = (hbus -> hdev -> dev_instance .b [5 ] << 24 ) |
657+ (hbus -> hdev -> dev_instance .b [4 ] << 16 ) |
658+ (hbus -> hdev -> dev_instance .b [7 ] << 8 ) |
659+ (hbus -> hdev -> dev_instance .b [6 ] & 0xf8 ) |
660+ PCI_FUNC (pdev -> devfn );
661+ params -> int_target .vector = hv_msi_get_int_vector (data );
662+
663+ /*
664+ * Honoring apic->delivery_mode set to APIC_DELIVERY_MODE_FIXED by
665+ * setting the HV_DEVICE_INTERRUPT_TARGET_MULTICAST flag results in a
666+ * spurious interrupt storm. Not doing so does not seem to have a
667+ * negative effect (yet?).
668+ */
669+
670+ if (hbus -> protocol_version >= PCI_PROTOCOL_VERSION_1_2 ) {
671+ /*
672+ * PCI_PROTOCOL_VERSION_1_2 supports the VP_SET version of the
673+ * HVCALL_RETARGET_INTERRUPT hypercall, which also coincides
674+ * with >64 VP support.
675+ * ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED
676+ * is not sufficient for this hypercall.
677+ */
678+ params -> int_target .flags |=
679+ HV_DEVICE_INTERRUPT_TARGET_PROCESSOR_SET ;
680+
681+ if (!alloc_cpumask_var (& tmp , GFP_ATOMIC )) {
682+ res = 1 ;
683+ goto exit_unlock ;
684+ }
685+
686+ cpumask_and (tmp , dest , cpu_online_mask );
687+ nr_bank = cpumask_to_vpset (& params -> int_target .vp_set , tmp );
688+ free_cpumask_var (tmp );
689+
690+ if (nr_bank <= 0 ) {
691+ res = 1 ;
692+ goto exit_unlock ;
693+ }
694+
695+ /*
696+ * var-sized hypercall, var-size starts after vp_mask (thus
697+ * vp_set.format does not count, but vp_set.valid_bank_mask
698+ * does).
699+ */
700+ var_size = 1 + nr_bank ;
701+ } else {
702+ for_each_cpu_and (cpu , dest , cpu_online_mask ) {
703+ params -> int_target .vp_mask |=
704+ (1ULL << hv_cpu_number_to_vp_number (cpu ));
705+ }
706+ }
707+
708+ res = hv_do_hypercall (HVCALL_RETARGET_INTERRUPT | (var_size << 17 ),
709+ params , NULL );
710+
711+ exit_unlock :
712+ spin_unlock_irqrestore (& hbus -> retarget_msi_interrupt_lock , flags );
713+
714+ /*
715+ * During hibernation, when a CPU is offlined, the kernel tries
716+ * to move the interrupt to the remaining CPUs that haven't
717+ * been offlined yet. In this case, the below hv_do_hypercall()
718+ * always fails since the vmbus channel has been closed:
719+ * refer to cpu_disable_common() -> fixup_irqs() ->
720+ * irq_migrate_all_off_this_cpu() -> migrate_one_irq().
721+ *
722+ * Suppress the error message for hibernation because the failure
723+ * during hibernation does not matter (at this time all the devices
724+ * have been frozen). Note: the correct affinity info is still updated
725+ * into the irqdata data structure in migrate_one_irq() ->
726+ * irq_do_set_affinity() -> hv_set_affinity(), so later when the VM
727+ * resumes, hv_pci_restore_msi_state() is able to correctly restore
728+ * the interrupt with the correct affinity.
729+ */
730+ if (!hv_result_success (res ) && hbus -> state != hv_pcibus_removing )
731+ dev_err (& hbus -> hdev -> device ,
732+ "%s() failed: %#llx" , __func__ , res );
733+ }
619734#elif defined(CONFIG_ARM64 )
620735/*
621736 * SPI vectors to use for vPCI; arch SPIs range is [32, 1019], but leaving a bit
@@ -839,6 +954,12 @@ static struct irq_domain *hv_pci_get_root_domain(void)
839954{
840955 return hv_msi_gic_irq_domain ;
841956}
957+
958+ /*
959+ * SPIs are used for interrupts of PCI devices and SPIs is managed via GICD
960+ * registers which Hyper-V already supports, so no hypercall needed.
961+ */
962+ static void hv_arch_irq_unmask (struct irq_data * data ) { }
842963#endif /* CONFIG_ARM64 */
843964
844965/**
@@ -1456,119 +1577,9 @@ static void hv_irq_mask(struct irq_data *data)
14561577 irq_chip_mask_parent (data );
14571578}
14581579
1459- /**
1460- * hv_irq_unmask() - "Unmask" the IRQ by setting its current
1461- * affinity.
1462- * @data: Describes the IRQ
1463- *
1464- * Build new a destination for the MSI and make a hypercall to
1465- * update the Interrupt Redirection Table. "Device Logical ID"
1466- * is built out of this PCI bus's instance GUID and the function
1467- * number of the device.
1468- */
14691580static void hv_irq_unmask (struct irq_data * data )
14701581{
1471- struct msi_desc * msi_desc = irq_data_get_msi_desc (data );
1472- struct hv_retarget_device_interrupt * params ;
1473- struct hv_pcibus_device * hbus ;
1474- struct cpumask * dest ;
1475- cpumask_var_t tmp ;
1476- struct pci_bus * pbus ;
1477- struct pci_dev * pdev ;
1478- unsigned long flags ;
1479- u32 var_size = 0 ;
1480- int cpu , nr_bank ;
1481- u64 res ;
1482-
1483- dest = irq_data_get_effective_affinity_mask (data );
1484- pdev = msi_desc_to_pci_dev (msi_desc );
1485- pbus = pdev -> bus ;
1486- hbus = container_of (pbus -> sysdata , struct hv_pcibus_device , sysdata );
1487-
1488- spin_lock_irqsave (& hbus -> retarget_msi_interrupt_lock , flags );
1489-
1490- params = & hbus -> retarget_msi_interrupt_params ;
1491- memset (params , 0 , sizeof (* params ));
1492- params -> partition_id = HV_PARTITION_ID_SELF ;
1493- params -> int_entry .source = HV_INTERRUPT_SOURCE_MSI ;
1494- hv_set_msi_entry_from_desc (& params -> int_entry .msi_entry , msi_desc );
1495- params -> device_id = (hbus -> hdev -> dev_instance .b [5 ] << 24 ) |
1496- (hbus -> hdev -> dev_instance .b [4 ] << 16 ) |
1497- (hbus -> hdev -> dev_instance .b [7 ] << 8 ) |
1498- (hbus -> hdev -> dev_instance .b [6 ] & 0xf8 ) |
1499- PCI_FUNC (pdev -> devfn );
1500- params -> int_target .vector = hv_msi_get_int_vector (data );
1501-
1502- /*
1503- * Honoring apic->delivery_mode set to APIC_DELIVERY_MODE_FIXED by
1504- * setting the HV_DEVICE_INTERRUPT_TARGET_MULTICAST flag results in a
1505- * spurious interrupt storm. Not doing so does not seem to have a
1506- * negative effect (yet?).
1507- */
1508-
1509- if (hbus -> protocol_version >= PCI_PROTOCOL_VERSION_1_2 ) {
1510- /*
1511- * PCI_PROTOCOL_VERSION_1_2 supports the VP_SET version of the
1512- * HVCALL_RETARGET_INTERRUPT hypercall, which also coincides
1513- * with >64 VP support.
1514- * ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED
1515- * is not sufficient for this hypercall.
1516- */
1517- params -> int_target .flags |=
1518- HV_DEVICE_INTERRUPT_TARGET_PROCESSOR_SET ;
1519-
1520- if (!alloc_cpumask_var (& tmp , GFP_ATOMIC )) {
1521- res = 1 ;
1522- goto exit_unlock ;
1523- }
1524-
1525- cpumask_and (tmp , dest , cpu_online_mask );
1526- nr_bank = cpumask_to_vpset (& params -> int_target .vp_set , tmp );
1527- free_cpumask_var (tmp );
1528-
1529- if (nr_bank <= 0 ) {
1530- res = 1 ;
1531- goto exit_unlock ;
1532- }
1533-
1534- /*
1535- * var-sized hypercall, var-size starts after vp_mask (thus
1536- * vp_set.format does not count, but vp_set.valid_bank_mask
1537- * does).
1538- */
1539- var_size = 1 + nr_bank ;
1540- } else {
1541- for_each_cpu_and (cpu , dest , cpu_online_mask ) {
1542- params -> int_target .vp_mask |=
1543- (1ULL << hv_cpu_number_to_vp_number (cpu ));
1544- }
1545- }
1546-
1547- res = hv_do_hypercall (HVCALL_RETARGET_INTERRUPT | (var_size << 17 ),
1548- params , NULL );
1549-
1550- exit_unlock :
1551- spin_unlock_irqrestore (& hbus -> retarget_msi_interrupt_lock , flags );
1552-
1553- /*
1554- * During hibernation, when a CPU is offlined, the kernel tries
1555- * to move the interrupt to the remaining CPUs that haven't
1556- * been offlined yet. In this case, the below hv_do_hypercall()
1557- * always fails since the vmbus channel has been closed:
1558- * refer to cpu_disable_common() -> fixup_irqs() ->
1559- * irq_migrate_all_off_this_cpu() -> migrate_one_irq().
1560- *
1561- * Suppress the error message for hibernation because the failure
1562- * during hibernation does not matter (at this time all the devices
1563- * have been frozen). Note: the correct affinity info is still updated
1564- * into the irqdata data structure in migrate_one_irq() ->
1565- * irq_do_set_affinity() -> hv_set_affinity(), so later when the VM
1566- * resumes, hv_pci_restore_msi_state() is able to correctly restore
1567- * the interrupt with the correct affinity.
1568- */
1569- if (!hv_result_success (res ) && hbus -> state != hv_pcibus_removing )
1570- dev_err (& hbus -> hdev -> device ,
1571- "%s() failed: %#llx" , __func__ , res );
1582+ hv_arch_irq_unmask (data );
15721583
15731584 if (data -> parent_data -> chip -> irq_unmask )
15741585 irq_chip_unmask_parent (data );
0 commit comments