diff options
author | Seshendra Gadagottu <sgadagottu@nvidia.com> | 2016-01-28 13:54:32 -0500 |
---|---|---|
committer | Terje Bergstrom <tbergstrom@nvidia.com> | 2016-01-29 15:58:22 -0500 |
commit | 9e02111a768ab631a6719c1eae8d7c03e6e89c23 (patch) | |
tree | 7cb3fb7cd59ca679579e4e7b920f2764a7cb7a81 | |
parent | 5cb995c7510e0290956a3aa221c6a77d4020b3ff (diff) |
gpu: nvgpu: fix race condition with poweroff
When gpu rail-gating is enabled, it is possible that
both rail gating code and system shudown can start
executing gk20a_pm_prepare_poweroff() in parallel.
To synchronize this execution, protect gk20a_pm_prepare_poweroff()
with a mutex lock.
Bug 200168805
Change-Id: I19536a43ed20c3e82b32c316922dc3e19e3f59bb
Signed-off-by: Seshendra Gadagottu <sgadagottu@nvidia.com>
Reviewed-on: http://git-master/r/999548
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 12 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 2 |
2 files changed, 11 insertions, 3 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index 0982ecdf..1000eba2 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -669,6 +669,7 @@ static int gk20a_init_support(struct platform_device *dev) | |||
669 | mutex_init(&g->dbg_sessions_lock); | 669 | mutex_init(&g->dbg_sessions_lock); |
670 | mutex_init(&g->client_lock); | 670 | mutex_init(&g->client_lock); |
671 | mutex_init(&g->ch_wdt_lock); | 671 | mutex_init(&g->ch_wdt_lock); |
672 | mutex_init(&g->poweroff_lock); | ||
672 | 673 | ||
673 | mutex_init(&g->interleave_lock); | 674 | mutex_init(&g->interleave_lock); |
674 | g->num_interleaved_channels = 0; | 675 | g->num_interleaved_channels = 0; |
@@ -689,17 +690,19 @@ static int gk20a_pm_prepare_poweroff(struct device *dev) | |||
689 | 690 | ||
690 | gk20a_dbg_fn(""); | 691 | gk20a_dbg_fn(""); |
691 | 692 | ||
692 | gk20a_scale_suspend(pdev); | 693 | mutex_lock(&g->poweroff_lock); |
693 | 694 | ||
694 | if (!g->power_on) | 695 | if (!g->power_on) |
695 | return 0; | 696 | goto done; |
697 | |||
698 | gk20a_scale_suspend(pdev); | ||
696 | 699 | ||
697 | /* cancel any pending cde work */ | 700 | /* cancel any pending cde work */ |
698 | gk20a_cde_suspend(g); | 701 | gk20a_cde_suspend(g); |
699 | 702 | ||
700 | ret = gk20a_channel_suspend(g); | 703 | ret = gk20a_channel_suspend(g); |
701 | if (ret) | 704 | if (ret) |
702 | return ret; | 705 | goto done; |
703 | 706 | ||
704 | /* disable elpg before gr or fifo suspend */ | 707 | /* disable elpg before gr or fifo suspend */ |
705 | ret |= gk20a_pmu_destroy(g); | 708 | ret |= gk20a_pmu_destroy(g); |
@@ -723,6 +726,9 @@ static int gk20a_pm_prepare_poweroff(struct device *dev) | |||
723 | /* Stop CPU from accessing the GPU registers. */ | 726 | /* Stop CPU from accessing the GPU registers. */ |
724 | gk20a_lockout_registers(g); | 727 | gk20a_lockout_registers(g); |
725 | 728 | ||
729 | done: | ||
730 | mutex_unlock(&g->poweroff_lock); | ||
731 | |||
726 | return ret; | 732 | return ret; |
727 | } | 733 | } |
728 | 734 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index b02d6111..0207588f 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -521,6 +521,8 @@ struct gk20a { | |||
521 | 521 | ||
522 | struct mutex ch_wdt_lock; | 522 | struct mutex ch_wdt_lock; |
523 | 523 | ||
524 | struct mutex poweroff_lock; | ||
525 | |||
524 | /* Channel priorities */ | 526 | /* Channel priorities */ |
525 | u32 timeslice_low_priority_us; | 527 | u32 timeslice_low_priority_us; |
526 | u32 timeslice_medium_priority_us; | 528 | u32 timeslice_medium_priority_us; |