summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu
diff options
context:
space:
mode:
authorJeremy Ho <jeremyh@nvidia.com>2019-07-02 04:43:17 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2019-07-16 09:12:03 -0400
commit42c2bdfb9f1afed4b22f74cb635db52d5f3e7cd0 (patch)
tree72ee74708ebc835bca06aa1a38d023d8f060f098 /drivers/gpu/nvgpu
parent00b41b85389fe08be780d0e6134e9e891ea65399 (diff)
gpu: nvgpu: remove reversed ordering for deadlock
In some cases, we would get deadlock issue due to there are two locks acquisition on common clk driver's lock and nvgpu driver's locks. At the bug, inconsistent lock ordering problem will come with one thread gets "nvgpu lock -> clk lock" and the other thread gets "clk lock -> nvgpu lock". Slove the latter path with one-time initializing clk_parent entry and use cached data afterward. Bug 2555115 Change-Id: I31c5c2728f406307e7cfd4e555f4db0c163234d8 Signed-off-by: Jeremy Ho <jeremyh@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/2146727 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Aleksandr Frid <afrid@nvidia.com> Reviewed-by: Bibek Basu <bbasu@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r--drivers/gpu/nvgpu/gk20a/clk_gk20a.h1
-rw-r--r--drivers/gpu/nvgpu/os/linux/clk.c6
-rw-r--r--drivers/gpu/nvgpu/os/linux/platform_gk20a_tegra.c11
3 files changed, 14 insertions, 4 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/clk_gk20a.h b/drivers/gpu/nvgpu/gk20a/clk_gk20a.h
index 03aa6ab7..b8ec9420 100644
--- a/drivers/gpu/nvgpu/gk20a/clk_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/clk_gk20a.h
@@ -95,6 +95,7 @@ struct clk_gk20a {
95 struct gk20a *g; 95 struct gk20a *g;
96#if defined(CONFIG_COMMON_CLK) 96#if defined(CONFIG_COMMON_CLK)
97 struct clk *tegra_clk; 97 struct clk *tegra_clk;
98 struct clk *tegra_clk_parent;
98 struct clk_hw hw; 99 struct clk_hw hw;
99#endif 100#endif
100 struct pll gpc_pll; 101 struct pll gpc_pll;
diff --git a/drivers/gpu/nvgpu/os/linux/clk.c b/drivers/gpu/nvgpu/os/linux/clk.c
index 6575a037..471f2aef 100644
--- a/drivers/gpu/nvgpu/os/linux/clk.c
+++ b/drivers/gpu/nvgpu/os/linux/clk.c
@@ -90,7 +90,7 @@ static unsigned long nvgpu_linux_get_fmax_at_vmin_safe(struct gk20a *g)
90 */ 90 */
91 if (g->clk.tegra_clk) 91 if (g->clk.tegra_clk)
92 return tegra_dvfs_get_fmax_at_vmin_safe_t( 92 return tegra_dvfs_get_fmax_at_vmin_safe_t(
93 clk_get_parent(g->clk.tegra_clk)); 93 g->clk.tegra_clk_parent);
94 94
95 if (platform->maxmin_clk_id) 95 if (platform->maxmin_clk_id)
96 return tegra_bpmp_dvfs_get_fmax_at_vmin( 96 return tegra_bpmp_dvfs_get_fmax_at_vmin(
@@ -116,7 +116,7 @@ static int nvgpu_linux_predict_mv_at_hz_cur_tfloor(struct clk_gk20a *clk,
116 unsigned long rate) 116 unsigned long rate)
117{ 117{
118 return tegra_dvfs_predict_mv_at_hz_cur_tfloor( 118 return tegra_dvfs_predict_mv_at_hz_cur_tfloor(
119 clk_get_parent(clk->tegra_clk), rate); 119 clk->tegra_clk_parent, rate);
120} 120}
121 121
122static unsigned long nvgpu_linux_get_maxrate(struct gk20a *g, u32 api_domain) 122static unsigned long nvgpu_linux_get_maxrate(struct gk20a *g, u32 api_domain)
@@ -125,7 +125,7 @@ static unsigned long nvgpu_linux_get_maxrate(struct gk20a *g, u32 api_domain)
125 125
126 switch (api_domain) { 126 switch (api_domain) {
127 case CTRL_CLK_DOMAIN_GPCCLK: 127 case CTRL_CLK_DOMAIN_GPCCLK:
128 ret = tegra_dvfs_get_maxrate(clk_get_parent(g->clk.tegra_clk)); 128 ret = tegra_dvfs_get_maxrate(g->clk.tegra_clk_parent);
129 break; 129 break;
130 default: 130 default:
131 nvgpu_err(g, "unknown clock: %u", api_domain); 131 nvgpu_err(g, "unknown clock: %u", api_domain);
diff --git a/drivers/gpu/nvgpu/os/linux/platform_gk20a_tegra.c b/drivers/gpu/nvgpu/os/linux/platform_gk20a_tegra.c
index 6a453096..0977e63a 100644
--- a/drivers/gpu/nvgpu/os/linux/platform_gk20a_tegra.c
+++ b/drivers/gpu/nvgpu/os/linux/platform_gk20a_tegra.c
@@ -649,7 +649,7 @@ int gk20a_tegra_init_secure_alloc(struct gk20a_platform *platform)
649static struct clk *gk20a_clk_get(struct gk20a *g) 649static struct clk *gk20a_clk_get(struct gk20a *g)
650{ 650{
651 if (!g->clk.tegra_clk) { 651 if (!g->clk.tegra_clk) {
652 struct clk *clk; 652 struct clk *clk, *clk_parent;
653 char clk_dev_id[32]; 653 char clk_dev_id[32];
654 struct device *dev = dev_from_gk20a(g); 654 struct device *dev = dev_from_gk20a(g);
655 655
@@ -661,7 +661,16 @@ static struct clk *gk20a_clk_get(struct gk20a *g)
661 clk_dev_id); 661 clk_dev_id);
662 return NULL; 662 return NULL;
663 } 663 }
664
665 clk_parent = clk_get_parent(clk);
666 if (IS_ERR_OR_NULL(clk_parent)) {
667 nvgpu_err(g, "fail to get tegra gpu clk parent%s/gpu\n",
668 clk_dev_id);
669 return NULL;
670 }
671
664 g->clk.tegra_clk = clk; 672 g->clk.tegra_clk = clk;
673 g->clk.tegra_clk_parent = clk_parent;
665 } 674 }
666 675
667 return g->clk.tegra_clk; 676 return g->clk.tegra_clk;