tpm_tis: fix potential buffer overruns caused by bit glitches on the bus
[pandora-kernel.git] / kernel / smp.c
index db197d6..9e800b2 100644 (file)
@@ -31,6 +31,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);
@@ -54,6 +55,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
@@ -63,6 +67,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
        };
@@ -524,6 +529,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
@@ -547,7 +558,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)