cpu/x86/lapic: Add wait_ipi_completion() helpers
Change-Id: Ib9c404cb55b96dcc5639287c214c5c8f468c0529 Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/55192 Reviewed-by: Angel Pons <th3fanbus@gmail.com> Reviewed-by: Arthur Heymans <arthur@aheymans.xyz> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
a4ceba4ae5
commit
68fe11beb0
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue