diff options
author | Vijayakumar <vsubbu@nvidia.com> | 2014-09-26 10:54:09 +0530 |
---|---|---|
committer | Matthew Pedro <mapedro@nvidia.com> | 2015-02-17 10:31:02 -0800 |
commit | 0a44699a4ea5e6df4ddcd323a62cb2aae87d40f7 (patch) | |
tree | 924c5953baf44ed8eff1221b7e01bc91b05997e1 /drivers/gpu | |
parent | e29ad67434ceab33a35812f10ce10fdfa63a5c56 (diff) |
gpu: nvgpu: send ELPG init cmd after GR is ready
bug 200040021
bug 200032923
bug 1570774
Change-Id: Ic162902bd2f05abab9ebd37392ed56dc4c164ba8
Reviewed-on: http://git-master/r/539995
Signed-off-by: Naveen Kumar S <nkumars@nvidia.com>
(cherry picked from commit 62e9ba6c8fbabcb77e0ec6267463f51ae319a0b3)
Reviewed-on: http://git-master/r/666721
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Matthew Pedro <mapedro@nvidia.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 65 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | 11 |
2 files changed, 56 insertions, 20 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c index 7b960b8adab0..0e5d80af7f07 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c @@ -47,6 +47,8 @@ static void ap_callback_init_and_enable_ctrl( static int gk20a_pmu_ap_send_command(struct gk20a *g, union pmu_ap_cmd *p_ap_cmd, bool b_block); +static int pmu_init_powergating(struct gk20a *g); + static u32 pmu_cmdline_size_v0(struct pmu_gk20a *pmu) { return sizeof(struct pmu_cmdline_args_v0); @@ -1735,12 +1737,13 @@ static void pmu_handle_pg_buf_config_msg(struct gk20a *g, struct pmu_msg *msg, return; } - if (eng_buf_stat->status == PMU_PG_MSG_ENG_BUF_FAILED) { - gk20a_err(dev_from_gk20a(g), "failed to load PGENG buffer"); - } - pmu->buf_loaded = (eng_buf_stat->status == PMU_PG_MSG_ENG_BUF_LOADED); - schedule_work(&pmu->pg_init); + if ((!pmu->buf_loaded) && + (pmu->pmu_state == PMU_STATE_LOADING_PG_BUF)) + gk20a_err(dev_from_gk20a(g), "failed to load PGENG buffer"); + else { + schedule_work(&pmu->pg_init); + } } int gk20a_init_pmu_setup_hw1(struct gk20a *g) @@ -1792,6 +1795,10 @@ static void pmu_setup_hw(struct work_struct *work) struct gk20a *g = pmu->g; switch (pmu->pmu_state) { + case PMU_STATE_INIT_RECEIVED: + gk20a_dbg_pmu("pmu starting"); + pmu_init_powergating(g); + break; case PMU_STATE_ELPG_BOOTED: gk20a_dbg_pmu("elpg booted"); gk20a_init_pmu_bind_fecs(g); @@ -1829,14 +1836,19 @@ int gk20a_init_pmu_bind_fecs(struct gk20a *g) gk20a_dbg_fn(""); size = 0; - gk20a_gr_wait_initialized(g); err = gr_gk20a_fecs_get_reglist_img_size(g, &size); - if (err) { + if (err && (pmu->pmu_state == PMU_STATE_ELPG_BOOTED)) { gk20a_err(dev_from_gk20a(g), "fail to query fecs pg buffer size"); return err; } + if (err) { + gk20a_err(dev_from_gk20a(g), + "fail to query fecs pg buffer size invalid boot state"); + return err; + } + if (!pmu->pg_buf.cpuva) { pmu->pg_buf.cpuva = dma_alloc_coherent(d, size, &iova, @@ -1873,19 +1885,31 @@ int gk20a_init_pmu_bind_fecs(struct gk20a *g) } err = gr_gk20a_fecs_set_reglist_bind_inst(g, mm->pmu.inst_block.cpu_pa); - if (err) { + if (err && (pmu->pmu_state == PMU_STATE_ELPG_BOOTED)) { gk20a_err(dev_from_gk20a(g), "fail to bind pmu inst to gr"); return err; } - err = gr_gk20a_fecs_set_reglist_virtual_addr(g, pmu->pg_buf.pmu_va); if (err) { gk20a_err(dev_from_gk20a(g), + "fail to bind pmu inst to gr invalid boot state"); + return err; + } + + err = gr_gk20a_fecs_set_reglist_virtual_addr(g, pmu->pg_buf.pmu_va); + if (err && (pmu->pmu_state == PMU_STATE_ELPG_BOOTED)) { + gk20a_err(dev_from_gk20a(g), "fail to set pg buffer pmu va"); return err; } + if (err) { + gk20a_err(dev_from_gk20a(g), + "fail to set pg buffer pmu va invalid boot state"); + return err; + } + memset(&cmd, 0, sizeof(struct pmu_cmd)); cmd.hdr.unit_id = PMU_UNIT_PG; cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_eng_buf_load); @@ -2027,9 +2051,10 @@ static void pmu_handle_pg_elpg_msg(struct gk20a *g, struct pmu_msg *msg, case PMU_PG_ELPG_MSG_DISALLOW_ACK: gk20a_dbg_pmu("DISALLOW is acknowledged from PMU"); pmu->elpg_stat = PMU_ELPG_STAT_OFF; - if (pmu->pmu_state == PMU_STATE_ELPG_BOOTING) + if (pmu->pmu_state == PMU_STATE_ELPG_BOOTING) { pmu->pmu_state = PMU_STATE_ELPG_BOOTED; - schedule_work(&pmu->pg_init); + schedule_work(&pmu->pg_init); + } break; default: gk20a_err(dev_from_gk20a(g), @@ -2062,14 +2087,16 @@ static void pmu_handle_pg_stat_msg(struct gk20a *g, struct pmu_msg *msg, } } -static int pmu_init_powergating(struct pmu_gk20a *pmu) +static int pmu_init_powergating(struct gk20a *g) { - struct gk20a *g = pmu->g; + struct pmu_gk20a *pmu = &g->pmu; struct pmu_cmd cmd; u32 seq; gk20a_dbg_fn(""); + mutex_lock(&pmu->isr_mutex); + if (tegra_cpu_is_asim()) { /* TBD: calculate threshold for silicon */ gk20a_writel(g, pwr_pmu_pg_idlefilth_r(ENGINE_GR_GK20A), @@ -2084,6 +2111,8 @@ static int pmu_init_powergating(struct pmu_gk20a *pmu) PMU_PG_POST_POWERUP_IDLE_THRESHOLD); } + gk20a_gr_wait_initialized(g); + /* init ELPG */ memset(&cmd, 0, sizeof(struct pmu_cmd)); cmd.hdr.unit_id = PMU_UNIT_PG; @@ -2127,7 +2156,10 @@ static int pmu_init_powergating(struct pmu_gk20a *pmu) /* start with elpg disabled until first enable call */ pmu->elpg_refcnt = 0; - pmu->pmu_state = PMU_STATE_ELPG_BOOTING; + if (pmu->pmu_state == PMU_STATE_INIT_RECEIVED) + pmu->pmu_state = PMU_STATE_ELPG_BOOTING; + + mutex_unlock(&pmu->isr_mutex); return 0; } @@ -2242,6 +2274,7 @@ static int pmu_process_init_msg(struct pmu_gk20a *pmu, union pmu_init_msg_pmu *init; struct pmu_sha1_gid_data gid_data; u32 i, tail = 0; + gk20a_dbg_pmu("init received\n"); tail = pwr_pmu_msgq_tail_val_v( gk20a_readl(g, pwr_pmu_msgq_tail_r())); @@ -2299,6 +2332,9 @@ static int pmu_process_init_msg(struct pmu_gk20a *pmu, PMU_DMEM_ALLOC_ALIGNMENT); pmu->pmu_ready = true; + pmu->pmu_state = PMU_STATE_INIT_RECEIVED; + schedule_work(&pmu->pg_init); + gk20a_dbg_pmu("init received end\n"); return 0; } @@ -2629,7 +2665,6 @@ static int pmu_process_message(struct pmu_gk20a *pmu) if (unlikely(!pmu->pmu_ready)) { pmu_process_init_msg(pmu, &msg); - pmu_init_powergating(pmu); pmu_init_perfmon(pmu); return 0; } diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h index 07903fcfac73..153baf3f1894 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h @@ -989,11 +989,12 @@ struct pmu_pg_stats { /* Choices for pmu_state */ #define PMU_STATE_OFF 0 /* PMU is off */ #define PMU_STATE_STARTING 1 /* PMU is on, but not booted */ -#define PMU_STATE_ELPG_BOOTING 2 /* PMU is booting */ -#define PMU_STATE_ELPG_BOOTED 3 /* ELPG is initialized */ -#define PMU_STATE_LOADING_PG_BUF 4 /* Loading PG buf */ -#define PMU_STATE_LOADING_ZBC 5 /* Loading ZBC buf */ -#define PMU_STATE_STARTED 6 /* Fully unitialized */ +#define PMU_STATE_INIT_RECEIVED 2 /* PMU init message received */ +#define PMU_STATE_ELPG_BOOTING 3 /* PMU is booting */ +#define PMU_STATE_ELPG_BOOTED 4 /* ELPG is initialized */ +#define PMU_STATE_LOADING_PG_BUF 5 /* Loading PG buf */ +#define PMU_STATE_LOADING_ZBC 6 /* Loading ZBC buf */ +#define PMU_STATE_STARTED 7 /* Fully unitialized */ struct pmu_gk20a { |