summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorVijayakumar <vsubbu@nvidia.com>2014-09-26 10:54:09 +0530
committerMatthew Pedro <mapedro@nvidia.com>2015-02-17 10:31:02 -0800
commit0a44699a4ea5e6df4ddcd323a62cb2aae87d40f7 (patch)
tree924c5953baf44ed8eff1221b7e01bc91b05997e1 /drivers/gpu
parente29ad67434ceab33a35812f10ce10fdfa63a5c56 (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.c65
-rw-r--r--drivers/gpu/nvgpu/gk20a/pmu_gk20a.h11
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 {