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