Skip to content

Commit

Permalink
dts: spl_wakeup: Remove all workarounds in the spl wakeup logic
Browse files Browse the repository at this point in the history
We coded few workarounds in special wakeup logic to handle the
buggy firmware. Now that is fixed remove them as they break the
special wakeup protocol. As per the spec we should not de-assert
beofre assert is complete. So follow this protocol.

Signed-off-by: Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com>
Reviewed-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
Tested-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
  • Loading branch information
shilpasri authored and stewartsmith committed Mar 14, 2018
1 parent 773836f commit b5c9d09
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 59 deletions.
59 changes: 29 additions & 30 deletions core/direct-controls.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ static int p9_core_set_special_wakeup(struct cpu_thread *cpu)
prlog(PR_ERR, "Could not set special wakeup on %u:%u:"
" Unable to write PPM_SPECIAL_WKUP_HYP.\n",
chip_id, core_id);
return OPAL_HARDWARE;
goto out_fail;
}

for (i = 0; i < P9_SPWKUP_TIMEOUT / P9_SPWKUP_POLL_INTERVAL; i++) {
Expand All @@ -321,9 +321,22 @@ static int p9_core_set_special_wakeup(struct cpu_thread *cpu)
chip_id, core_id);
goto out_fail;
}
if (val & P9_SPECIAL_WKUP_DONE)
return 0;

if (val & P9_SPECIAL_WKUP_DONE) {
/*
* CORE_GATED will be unset on a successful special
* wakeup of the core which indicates that the core is
* out of stop state. If CORE_GATED is still set then
* raise error.
*/
if (dctl_core_is_gated(cpu)) {
prlog(PR_ERR, "Failed special wakeup on %u:%u"
" as CORE_GATED is set\n",
chip_id, core_id);
goto out_fail;
} else {
return 0;
}
}
time_wait_us(P9_SPWKUP_POLL_INTERVAL);
}

Expand All @@ -332,10 +345,11 @@ static int p9_core_set_special_wakeup(struct cpu_thread *cpu)
chip_id, core_id);

out_fail:
/* De-assert special wakeup after a small delay. */
time_wait_us(1);
xscom_write(chip_id, swake_addr, 0);

/*
* As per the special wakeup protocol we should not de-assert
* the special wakeup on the core until WAKEUP_DONE is set.
* So even on error do not de-assert.
*/
return OPAL_HARDWARE;
}

Expand All @@ -344,12 +358,8 @@ 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.
Expand All @@ -363,25 +373,14 @@ static int p9_core_clear_special_wakeup(struct cpu_thread *cpu)
chip_id, core_id);
return OPAL_HARDWARE;
}
time_wait_us(1);

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;
/*
* Don't wait for de-assert to complete as other components
* could have requested for special wkeup. Wait for 10ms to
* avoid back-to-back asserts
*/
time_wait_us(10000);
return 0;
}

static int p9_thread_quiesced(struct cpu_thread *cpu)
Expand Down
30 changes: 1 addition & 29 deletions hw/dts.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,42 +236,14 @@ static int dts_read_core_temp_p9(uint32_t pir, struct dts *dts)
return 0;
}

static int dts_wakeup_core(struct cpu_thread *cpu)
{
int retries = 10;
int rc;

while (retries-- > 0) {
rc = dctl_set_special_wakeup(cpu);
if (rc) {
prerror("Failed to set special wakeup on %d (%d)\n",
cpu->pir, rc);
return rc;
}

if (!dctl_core_is_gated(cpu))
break;

prlog(PR_NOTICE, "Retrying special wakeup on %d\n", cpu->pir);
rc = dctl_clear_special_wakeup(cpu);
if (rc) {
prerror("Failed to clear special wakeup on %d (%d)\n",
cpu->pir, rc);
return rc;
}
}

return rc;
}

static void dts_async_read_temp(struct timer *t __unused, void *data,
u64 now __unused)
{
struct dts dts;
int rc, swkup_rc;
struct cpu_thread *cpu = data;

swkup_rc = dts_wakeup_core(cpu);
swkup_rc = dctl_set_special_wakeup(cpu);

rc = dts_read_core_temp_p9(cpu->pir, &dts);
if (!rc) {
Expand Down

0 comments on commit b5c9d09

Please sign in to comment.