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:
		| @@ -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(); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user