* requirement can be relaxed in the future. Right now, this is conservative
* and good.
*/
-#define SPINUNIT 100 /* 100 nsec */
+static atomic_t late_cpus_in, late_cpus_out;
-
-static atomic_t late_cpus_in;
-static atomic_t late_cpus_out;
-
-static int __wait_for_cpus(atomic_t *t, long long timeout)
+static bool wait_for_cpus(atomic_t *cnt)
{
- int all_cpus = num_online_cpus();
+ unsigned int timeout;
- atomic_inc(t);
+ WARN_ON_ONCE(atomic_dec_return(cnt) < 0);
- while (atomic_read(t) < all_cpus) {
- if (timeout < SPINUNIT) {
- pr_err("Timeout while waiting for CPUs rendezvous, remaining: %d\n",
- all_cpus - atomic_read(t));
- return 1;
- }
+ for (timeout = 0; timeout < USEC_PER_SEC; timeout++) {
+ if (!atomic_read(cnt))
+ return true;
- ndelay(SPINUNIT);
- timeout -= SPINUNIT;
+ udelay(1);
- touch_nmi_watchdog();
+ if (!(timeout % USEC_PER_MSEC))
+ touch_nmi_watchdog();
}
- return 0;
+ /* Prevent the late comers from making progress and let them time out */
+ atomic_inc(cnt);
+ return false;
}
/*
* Wait for all CPUs to arrive. A load will not be attempted unless all
* CPUs show up.
* */
- if (__wait_for_cpus(&late_cpus_in, NSEC_PER_SEC))
+ if (!wait_for_cpus(&late_cpus_in))
return -1;
/*
}
wait_for_siblings:
- if (__wait_for_cpus(&late_cpus_out, NSEC_PER_SEC))
+ if (!wait_for_cpus(&late_cpus_out))
panic("Timeout during microcode update!\n");
/*
pr_err("Attempting late microcode loading - it is dangerous and taints the kernel.\n");
pr_err("You should switch to early loading, if possible.\n");
- atomic_set(&late_cpus_in, 0);
- atomic_set(&late_cpus_out, 0);
+ atomic_set(&late_cpus_in, num_online_cpus());
+ atomic_set(&late_cpus_out, num_online_cpus());
/*
* Take a snapshot before the microcode update in order to compare and