From efe0758081f25b39d5bb8b097fc0ae64d0e47c3f Mon Sep 17 00:00:00 2001 From: Mahantesh Kumbar Date: Mon, 14 Nov 2016 11:27:38 +0530 Subject: gpu: nvgpu: fix pmu->mscg_stat optimization issue - with help of WRITE_ONCE() & ACCESS_ONCE() make sure variable pmu->mscg_stat read/write goes through without optimization - Added WRITE_ONCE() define for kernel-3.18 version & below to support backward compatibility issue: inconsistencies on getting MSCG to trigger consistently in P5 due to a lack of memory barrier around and volatile accesses to the variable pmu->mscg_stat JIRA DNVGPU-71 Change-Id: I04d30493d42c52710304dbdfb9cb4a1e9a76f2c0 Signed-off-by: Mahantesh Kumbar Reviewed-on: http://git-master/r/1252524 (cherry picked from commit 8af7fc68e7ab06a856ba4ef4e44de7336682361b) Reviewed-on: http://git-master/r/1271614 Reviewed-by: svccoveritychecker GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/gk20a.h | 4 ++++ drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c | 12 +++++++++--- drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 8 +++++--- 3 files changed, 18 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/nvgpu/gk20a') diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 5e2344cf..692f054f 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -64,6 +64,10 @@ struct acr_desc; #endif #include "gm206/bios_gm206.h" +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) +#define WRITE_ONCE(x, val) \ + x = val +#endif /* PTIMER_REF_FREQ_HZ corresponds to a period of 32 nanoseconds. 32 ns is the resolution of ptimer. */ diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c index 9bf6acec..6611b120 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c @@ -511,15 +511,21 @@ static ssize_t mscg_enable_store(struct device *dev, g->mscg_enabled = true; if (g->ops.pmu.pmu_is_lpwr_feature_supported(g, PMU_PG_LPWR_FEATURE_MSCG)) { - if (!pmu->mscg_stat) - pmu->mscg_stat = PMU_MSCG_ENABLED; + if (!ACCESS_ONCE(pmu->mscg_stat)) { + WRITE_ONCE(pmu->mscg_stat, + PMU_MSCG_ENABLED); + /* make status visible */ + smp_mb(); + } } } else if (!val && g->mscg_enabled) { if (g->ops.pmu.pmu_is_lpwr_feature_supported(g, PMU_PG_LPWR_FEATURE_MSCG)) { gk20a_pmu_pg_global_enable(g, false); - pmu->mscg_stat = PMU_MSCG_DISABLED; + WRITE_ONCE(pmu->mscg_stat, PMU_MSCG_DISABLED); + /* make status visible */ + smp_mb(); g->mscg_enabled = false; if (g->elpg_enabled) gk20a_pmu_pg_global_enable(g, true); diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c index ef6a5943..11baa7af 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c @@ -3388,7 +3388,9 @@ static void pmu_handle_pg_elpg_msg(struct gk20a *g, struct pmu_msg *msg, PMU_PG_FEATURE_GR_POWER_GATING_ENABLED) { pmu->initialized = true; pmu->pmu_state = PMU_STATE_STARTED; - pmu->mscg_stat = PMU_MSCG_DISABLED; + WRITE_ONCE(pmu->mscg_stat, PMU_MSCG_DISABLED); + /* make status visible */ + smp_mb(); } else { pmu->pmu_state = PMU_STATE_ELPG_BOOTED; schedule_work(&pmu->pg_init); @@ -4849,7 +4851,7 @@ int gk20a_pmu_enable_elpg(struct gk20a *g) pg_engine_id++) { if (pg_engine_id == PMU_PG_ELPG_ENGINE_ID_MS && - pmu->mscg_stat == PMU_MSCG_DISABLED) + ACCESS_ONCE(pmu->mscg_stat) == PMU_MSCG_DISABLED) continue; if (BIT(pg_engine_id) & pg_engine_id_list) @@ -4925,7 +4927,7 @@ int gk20a_pmu_disable_elpg(struct gk20a *g) pg_engine_id++) { if (pg_engine_id == PMU_PG_ELPG_ENGINE_ID_MS && - pmu->mscg_stat == PMU_MSCG_DISABLED) + ACCESS_ONCE(pmu->mscg_stat) == PMU_MSCG_DISABLED) continue; if (BIT(pg_engine_id) & pg_engine_id_list) { -- cgit v1.2.2