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);
|
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)
|
static int lapic_start_cpu(unsigned long apicid)
|
||||||
{
|
{
|
||||||
int timeout;
|
const int timeout_100ms = 100;
|
||||||
uint32_t send_status, accept_status;
|
uint32_t send_status, accept_status;
|
||||||
int j, maxlvt;
|
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);
|
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_INT_ASSERT | LAPIC_DM_INIT, apicid);
|
||||||
|
|
||||||
printk(BIOS_SPEW, "Waiting for send to finish...\n");
|
send_status = wait_for_ipi_completion(timeout_100ms);
|
||||||
timeout = 0;
|
if (send_status) {
|
||||||
do {
|
|
||||||
printk(BIOS_SPEW, "+");
|
|
||||||
udelay(100);
|
|
||||||
send_status = lapic_busy();
|
|
||||||
} while (send_status && (timeout++ < 1000));
|
|
||||||
if (timeout >= 1000) {
|
|
||||||
printk(BIOS_ERR, "CPU %ld: First APIC write timed out. "
|
printk(BIOS_ERR, "CPU %ld: First APIC write timed out. "
|
||||||
"Disabling\n", apicid);
|
"Disabling\n", apicid);
|
||||||
// too bad.
|
// too bad.
|
||||||
@ -131,14 +141,8 @@ static int lapic_start_cpu(unsigned long apicid)
|
|||||||
|
|
||||||
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_DM_INIT, apicid);
|
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_DM_INIT, apicid);
|
||||||
|
|
||||||
printk(BIOS_SPEW, "Waiting for send to finish...\n");
|
send_status = wait_for_ipi_completion(timeout_100ms);
|
||||||
timeout = 0;
|
if (send_status) {
|
||||||
do {
|
|
||||||
printk(BIOS_SPEW, "+");
|
|
||||||
udelay(100);
|
|
||||||
send_status = lapic_busy();
|
|
||||||
} while (send_status && (timeout++ < 1000));
|
|
||||||
if (timeout >= 1000) {
|
|
||||||
printk(BIOS_ERR, "CPU %ld: Second APIC write timed out. "
|
printk(BIOS_ERR, "CPU %ld: Second APIC write timed out. "
|
||||||
"Disabling\n", apicid);
|
"Disabling\n", apicid);
|
||||||
// too bad.
|
// too bad.
|
||||||
@ -172,13 +176,7 @@ static int lapic_start_cpu(unsigned long apicid)
|
|||||||
|
|
||||||
printk(BIOS_SPEW, "Startup point 1.\n");
|
printk(BIOS_SPEW, "Startup point 1.\n");
|
||||||
|
|
||||||
printk(BIOS_SPEW, "Waiting for send to finish...\n");
|
send_status = wait_for_ipi_completion(timeout_100ms);
|
||||||
timeout = 0;
|
|
||||||
do {
|
|
||||||
printk(BIOS_SPEW, "+");
|
|
||||||
udelay(100);
|
|
||||||
send_status = lapic_busy();
|
|
||||||
} while (send_status && (timeout++ < 1000));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Give the other CPU some time to accept the IPI.
|
* 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)
|
#define dprintk(LEVEL, args...) do { } while (0)
|
||||||
#endif
|
#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
|
* 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.
|
* 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)
|
void stop_this_cpu(void)
|
||||||
{
|
{
|
||||||
int timeout;
|
const int timeout_100ms = 100;
|
||||||
unsigned long send_status;
|
|
||||||
unsigned long id = lapicid();
|
unsigned long id = lapicid();
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "CPU %ld going down...\n", id);
|
printk(BIOS_DEBUG, "CPU %ld going down...\n", id);
|
||||||
|
|
||||||
/* send an LAPIC INIT to myself */
|
/* send an LAPIC INIT to myself */
|
||||||
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_INT_ASSERT | LAPIC_DM_INIT, id);
|
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_INT_ASSERT | LAPIC_DM_INIT, id);
|
||||||
|
wait_for_ipi_completion_without_printk(timeout_100ms);
|
||||||
/* 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");
|
|
||||||
|
|
||||||
mdelay(10);
|
mdelay(10);
|
||||||
|
|
||||||
@ -342,18 +344,7 @@ void stop_this_cpu(void)
|
|||||||
|
|
||||||
/* Deassert the LAPIC INIT */
|
/* Deassert the LAPIC INIT */
|
||||||
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_DM_INIT, id);
|
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_DM_INIT, id);
|
||||||
|
wait_for_ipi_completion_without_printk(timeout_100ms);
|
||||||
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");
|
|
||||||
|
|
||||||
halt();
|
halt();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user