summaryrefslogtreecommitdiff
path: root/arch/x86/hyperv/hv_apic.c
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2021-10-08 01:24:06 +0300
committerJakub Kicinski <kuba@kernel.org>2021-10-08 01:24:06 +0300
commit9fe1155233c8290ca6e206053e531ef87f9026ea (patch)
treeef0d45b2562e01beb8ce4cb4cd016155b4e32a65 /arch/x86/hyperv/hv_apic.c
parentc514fbb6231483b05c97eb22587188d4c453b28e (diff)
parent1da38549dd64c7f5dd22427f12dfa8db3d8a722b (diff)
downloadlinux-9fe1155233c8290ca6e206053e531ef87f9026ea.tar.xz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
No conflicts. Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'arch/x86/hyperv/hv_apic.c')
-rw-r--r--arch/x86/hyperv/hv_apic.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c
index 32a1ad356c18..db2d92fb44da 100644
--- a/arch/x86/hyperv/hv_apic.c
+++ b/arch/x86/hyperv/hv_apic.c
@@ -122,17 +122,27 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
ipi_arg->reserved = 0;
ipi_arg->vp_set.valid_bank_mask = 0;
- if (!cpumask_equal(mask, cpu_present_mask)) {
+ /*
+ * Use HV_GENERIC_SET_ALL and avoid converting cpumask to VP_SET
+ * when the IPI is sent to all currently present CPUs.
+ */
+ if (!cpumask_equal(mask, cpu_present_mask) || exclude_self) {
ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K;
if (exclude_self)
nr_bank = cpumask_to_vpset_noself(&(ipi_arg->vp_set), mask);
else
nr_bank = cpumask_to_vpset(&(ipi_arg->vp_set), mask);
- }
- if (nr_bank < 0)
- goto ipi_mask_ex_done;
- if (!nr_bank)
+
+ /*
+ * 'nr_bank <= 0' means some CPUs in cpumask can't be
+ * represented in VP_SET. Return an error and fall back to
+ * native (architectural) method of sending IPIs.
+ */
+ if (nr_bank <= 0)
+ goto ipi_mask_ex_done;
+ } else {
ipi_arg->vp_set.format = HV_GENERIC_SET_ALL;
+ }
status = hv_do_rep_hypercall(HVCALL_SEND_IPI_EX, 0, nr_bank,
ipi_arg, NULL);