|
@@ -33,6 +33,7 @@ struct call_function_data {
|
|
|
struct call_single_data csd;
|
|
|
atomic_t refs;
|
|
|
cpumask_var_t cpumask;
|
|
|
+ cpumask_var_t cpumask_ipi;
|
|
|
};
|
|
|
|
|
|
static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_function_data, cfd_data);
|
|
@@ -56,6 +57,9 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu)
|
|
|
if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL,
|
|
|
cpu_to_node(cpu)))
|
|
|
return notifier_from_errno(-ENOMEM);
|
|
|
+ if (!zalloc_cpumask_var_node(&cfd->cpumask_ipi, GFP_KERNEL,
|
|
|
+ cpu_to_node(cpu)))
|
|
|
+ return notifier_from_errno(-ENOMEM);
|
|
|
break;
|
|
|
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
@@ -65,6 +69,7 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu)
|
|
|
case CPU_DEAD:
|
|
|
case CPU_DEAD_FROZEN:
|
|
|
free_cpumask_var(cfd->cpumask);
|
|
|
+ free_cpumask_var(cfd->cpumask_ipi);
|
|
|
break;
|
|
|
#endif
|
|
|
};
|
|
@@ -526,6 +531,12 @@ void smp_call_function_many(const struct cpumask *mask,
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * After we put an entry into the list, data->cpumask
|
|
|
+ * may be cleared again when another CPU sends another IPI for
|
|
|
+ * a SMP function call, so data->cpumask will be zero.
|
|
|
+ */
|
|
|
+ cpumask_copy(data->cpumask_ipi, data->cpumask);
|
|
|
raw_spin_lock_irqsave(&call_function.lock, flags);
|
|
|
/*
|
|
|
* Place entry at the _HEAD_ of the list, so that any cpu still
|
|
@@ -549,7 +560,7 @@ void smp_call_function_many(const struct cpumask *mask,
|
|
|
smp_mb();
|
|
|
|
|
|
/* Send a message to all CPUs in the map */
|
|
|
- arch_send_call_function_ipi_mask(data->cpumask);
|
|
|
+ arch_send_call_function_ipi_mask(data->cpumask_ipi);
|
|
|
|
|
|
/* Optionally wait for the CPUs to complete */
|
|
|
if (wait)
|