From 27c35b967a84788a45260579802b8ffa66ed05e8 Mon Sep 17 00:00:00 2001 From: Robert Lippert Date: Mon, 20 Nov 2017 11:40:36 +0530 Subject: core/direct-controls: wait for core special wkup bit cleared When clearing special wakeup bit on a core, wait until the bit is actually cleared by the hardware in the status register until returning success. This may help avoid issues with back-to-back reads where the special wakeup request is cleared but the firmware is still processing the request and the next attempt to set the bit reads an immediate success from the previous operation. Change-Id: I86ec8cbbbddd1a5724f451244907693bc09e01ea Signed-off-by: Robert Lippert Signed-off-by: Stewart Smith --- core/direct-controls.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/core/direct-controls.c b/core/direct-controls.c index fcb9350a..0ed00c18 100644 --- a/core/direct-controls.c +++ b/core/direct-controls.c @@ -95,8 +95,12 @@ static int p9_core_clear_special_wakeup(struct cpu_thread *cpu) uint32_t chip_id = pir_to_chip_id(cpu->pir); uint32_t core_id = pir_to_core_id(cpu->pir); uint32_t swake_addr; + uint32_t sshhyp_addr; + uint64_t val; + int i; swake_addr = XSCOM_ADDR_P9_EC_SLAVE(core_id, EC_PPM_SPECIAL_WKUP_HYP); + sshhyp_addr = XSCOM_ADDR_P9_EC_SLAVE(core_id, P9_EC_PPM_SSHHYP); /* * De-assert special wakeup after a small delay. @@ -110,8 +114,25 @@ static int p9_core_clear_special_wakeup(struct cpu_thread *cpu) chip_id, core_id); return OPAL_HARDWARE; } + time_wait_us(1); - return OPAL_SUCCESS; + for (i = 0; i < P9_SPWKUP_TIMEOUT/P9_SPWKUP_POLL_INTERVAL; i++) { + if (xscom_read(chip_id, sshhyp_addr, &val)) { + prlog(PR_ERR, "Could not clear special wakeup on %u:%u:" + " Unable to read PPM_SSHHYP.\n", + chip_id, core_id); + return OPAL_HARDWARE; + } + if (!(val & P9_SPECIAL_WKUP_DONE)) + return 0; + + time_wait_us(P9_SPWKUP_POLL_INTERVAL); + } + + prlog(PR_ERR, "Could not clear special wakeup on %u:%u:" + " timeout waiting for clear of SPECIAL_WKUP_DONE.\n", + chip_id, core_id); + return OPAL_HARDWARE; } static int p9_thread_quiesced(struct cpu_thread *cpu) -- cgit v1.2.1