gpu: nvgpu: add priv lockdown release check for NVRISCV pmu

IRQ register access will cause priv errors if they
are accessed before priv lockdown is released.
This change adds a polling loop to check priv lockdown
before proceeding further while booting NVRISCV pmu.

Bug 200709761

Signed-off-by: Ramesh Mylavarapu <rmylavarapu@nvidia.com>
Change-Id: I44b8ce4c59b5a9f20901e5ce08610d17725da779
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2512351
Reviewed-by: Mahantesh Kumbar <mkumbar@nvidia.com>
Reviewed-by: Seema Khowala <seemaj@nvidia.com>
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com>
Reviewed-by: svc-mobile-misra <svc-mobile-misra@nvidia.com>
Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
This commit is contained in:
Ramesh Mylavarapu
2021-04-09 00:12:59 +05:30
committed by mobile promotions
parent 4d3a935b1a
commit a0b1b3f2be
2 changed files with 55 additions and 1 deletions

View File

@@ -21,6 +21,8 @@
*/
#include <nvgpu/gk20a.h>
#include <nvgpu/timers.h>
#include <nvgpu/io.h>
#include <nvgpu/dma.h>
#include <nvgpu/log.h>
#include <nvgpu/enabled.h>
@@ -52,6 +54,10 @@
#include <nvgpu/sec2/lsfm.h>
#endif
#if defined(CONFIG_NVGPU_NEXT)
#define PMU_PRIV_LOCKDOWN_RELEASE_POLLING_US (1U)
#endif
/* PMU locks used to sync with PMU-RTOS */
int nvgpu_pmu_lock_acquire(struct gk20a *g, struct nvgpu_pmu *pmu,
u32 id, u32 *token)
@@ -313,6 +319,35 @@ s32 nvgpu_pmu_next_core_rtos_args_allocate(struct gk20a *g,
exit:
return err;
}
static int nvgpu_pmu_wait_for_priv_lockdown_release(struct gk20a *g,
struct nvgpu_falcon *flcn, unsigned int timeout)
{
struct nvgpu_timeout to;
int status;
nvgpu_log_fn(g, " ");
status = nvgpu_timeout_init(g, &to, timeout, NVGPU_TIMER_CPU_TIMER);
if (status != 0) {
return status;
}
/* poll for priv lockdown release */
do {
if (!g->ops.falcon.is_priv_lockdown(flcn)) {
break;
}
nvgpu_udelay(PMU_PRIV_LOCKDOWN_RELEASE_POLLING_US);
} while (nvgpu_timeout_expired(&to) == 0);
if (nvgpu_timeout_peek_expired(&to)) {
status = -ETIMEDOUT;
}
return status;
}
#endif
int nvgpu_pmu_rtos_init(struct gk20a *g)
@@ -381,6 +416,12 @@ int nvgpu_pmu_rtos_init(struct gk20a *g)
#if defined(CONFIG_NVGPU_NEXT)
if (nvgpu_is_enabled(g, NVGPU_PMU_NEXT_CORE_ENABLED)) {
g->ops.falcon.bootstrap(g->pmu->flcn, 0U);
err = nvgpu_pmu_wait_for_priv_lockdown_release(g,
g->pmu->flcn, U32_MAX);
if(err != 0) {
nvgpu_err(g, "PRIV lockdown polling failed");
return err;
}
} else
#endif
{
@@ -395,6 +436,16 @@ int nvgpu_pmu_rtos_init(struct gk20a *g)
if (err != 0) {
goto exit;
}
#if defined(CONFIG_NVGPU_NEXT)
if (nvgpu_is_enabled(g, NVGPU_PMU_NEXT_CORE_ENABLED)) {
err = nvgpu_pmu_wait_for_priv_lockdown_release(g,
g->pmu->flcn, U32_MAX);
if(err != 0) {
nvgpu_err(g, "PRIV lockdown polling failed");
return err;
}
}
#endif
}
nvgpu_pmu_fw_state_change(g, g->pmu, PMU_FW_STATE_STARTING, false);