summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/x86/lapic/lapic_cpu_init.c93
1 files changed, 42 insertions, 51 deletions
diff --git a/src/cpu/x86/lapic/lapic_cpu_init.c b/src/cpu/x86/lapic/lapic_cpu_init.c
index e870921774..d01fb91a19 100644
--- a/src/cpu/x86/lapic/lapic_cpu_init.c
+++ b/src/cpu/x86/lapic/lapic_cpu_init.c
@@ -88,9 +88,25 @@ static void recover_lowest_1M(void)
memcpy(lowmem_backup_ptr, lowmem_backup, lowmem_backup_size);
}
+static uint32_t wait_for_ipi_completion(const int timeout_ms)
+{
+ int loops = timeout_ms * 10;
+ uint32_t send_status;
+
+ /* wait for the ipi send to finish */
+ printk(BIOS_SPEW, "Waiting for send to finish...\n");
+ do {
+ printk(BIOS_SPEW, "+");
+ udelay(100);
+ send_status = lapic_busy();
+ } while (send_status && (--loops > 0));
+
+ return send_status;
+}
+
static int lapic_start_cpu(unsigned long apicid)
{
- int timeout;
+ const int timeout_100ms = 100;
uint32_t send_status, accept_status;
int j, maxlvt;
@@ -105,14 +121,8 @@ static int lapic_start_cpu(unsigned long apicid)
*/
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_INT_ASSERT | LAPIC_DM_INIT, apicid);
- printk(BIOS_SPEW, "Waiting for send to finish...\n");
- timeout = 0;
- do {
- printk(BIOS_SPEW, "+");
- udelay(100);
- send_status = lapic_busy();
- } while (send_status && (timeout++ < 1000));
- if (timeout >= 1000) {
+ send_status = wait_for_ipi_completion(timeout_100ms);
+ if (send_status) {
printk(BIOS_ERR, "CPU %ld: First APIC write timed out. "
"Disabling\n", apicid);
// too bad.
@@ -131,14 +141,8 @@ static int lapic_start_cpu(unsigned long apicid)
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_DM_INIT, apicid);
- printk(BIOS_SPEW, "Waiting for send to finish...\n");
- timeout = 0;
- do {
- printk(BIOS_SPEW, "+");
- udelay(100);
- send_status = lapic_busy();
- } while (send_status && (timeout++ < 1000));
- if (timeout >= 1000) {
+ send_status = wait_for_ipi_completion(timeout_100ms);
+ if (send_status) {
printk(BIOS_ERR, "CPU %ld: Second APIC write timed out. "
"Disabling\n", apicid);
// too bad.
@@ -172,13 +176,7 @@ static int lapic_start_cpu(unsigned long apicid)
printk(BIOS_SPEW, "Startup point 1.\n");
- printk(BIOS_SPEW, "Waiting for send to finish...\n");
- timeout = 0;
- do {
- printk(BIOS_SPEW, "+");
- udelay(100);
- send_status = lapic_busy();
- } while (send_status && (timeout++ < 1000));
+ send_status = wait_for_ipi_completion(timeout_100ms);
/*
* Give the other CPU some time to accept the IPI.
@@ -306,6 +304,23 @@ static int start_cpu(struct device *cpu)
#define dprintk(LEVEL, args...) do { } while (0)
#endif
+static void wait_for_ipi_completion_without_printk(const int timeout_ms)
+{
+ int loops = timeout_ms * 10;
+ uint32_t send_status;
+
+ /* wait for the ipi send to finish */
+ dprintk(BIOS_SPEW, "Waiting for send to finish...\n");
+ do {
+ dprintk(BIOS_SPEW, "+");
+ udelay(100);
+ send_status = lapic_busy();
+ } while (send_status && (--loops > 0));
+
+ if (send_status)
+ dprintk(BIOS_ERR, "timed out\n");
+}
+
/**
* Normally this function is defined in lapic.h as an always inline function
* that just keeps the CPU in a hlt() loop. This does not work on all CPUs.
@@ -314,27 +329,14 @@ static int start_cpu(struct device *cpu)
*/
void stop_this_cpu(void)
{
- int timeout;
- unsigned long send_status;
+ const int timeout_100ms = 100;
unsigned long id = lapicid();
printk(BIOS_DEBUG, "CPU %ld going down...\n", id);
/* send an LAPIC INIT to myself */
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_INT_ASSERT | LAPIC_DM_INIT, id);
-
- /* wait for the ipi send to finish */
- dprintk(BIOS_SPEW, "Waiting for send to finish...\n");
-
- timeout = 0;
- do {
- dprintk(BIOS_SPEW, "+");
- udelay(100);
- send_status = lapic_busy();
- } while (send_status && (timeout++ < 1000));
-
- if (timeout >= 1000)
- dprintk(BIOS_ERR, "timed out\n");
+ wait_for_ipi_completion_without_printk(timeout_100ms);
mdelay(10);
@@ -342,18 +344,7 @@ void stop_this_cpu(void)
/* Deassert the LAPIC INIT */
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_DM_INIT, id);
-
- dprintk(BIOS_SPEW, "Waiting for send to finish...\n");
-
- timeout = 0;
- do {
- dprintk(BIOS_SPEW, "+");
- udelay(100);
- send_status = lapic_busy();
- } while (send_status && (timeout++ < 1000));
-
- if (timeout >= 1000)
- dprintk(BIOS_ERR, "timed out\n");
+ wait_for_ipi_completion_without_printk(timeout_100ms);
halt();
}