diff options
author | Debarshi Dutta <ddutta@nvidia.com> | 2019-07-17 07:53:42 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2019-08-02 10:12:00 -0400 |
commit | 47f6bc0c2e85d0a8ff943b88c81108ca1bfc588e (patch) | |
tree | 8cafdce8c9eeb4d7d3b8127d69a0763f3a968e70 /drivers | |
parent | 9fdb446b472c7a299b10365ddc91fc86a8e6788f (diff) |
gpu: nvgpu: Fix the race between runtime PM and L2 flush
gk20a_mm_l2_flush flushes the L2 cache when "struct gk20a->power_on"
is true. But it doesn't acquire power lock when doing that, which
creates a race that runtime PM might suspend the GPU in the middle
of L2 flush. The FB flush looks having the same issue with L2 flushing.
This patch fixes that by calling pm_runtime_get_if_in_use at the
beginning of the ioctl. This API from PM does a compare and add to
the usage count. If the device was not in use, it simply returns
without incrementing the usage count as its unnecessary to wake up
the GPU(using e.g. a call to gk20a_busy()) as the caches are
flushed when the device would be resumed anyways.
Bug 2643951
Change-Id: I2417f7ca3223c722dcb4d9057d32a7e065b9e574
Signed-off-by: Debarshi Dutta <ddutta@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2151532
GVS: Gerrit_Virtual_Submit
Reviewed-by: Mark Zhang <markz@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/gk20a.h | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c | 13 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/module.c | 5 |
3 files changed, 17 insertions, 2 deletions
diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index f393e799..7ed4c714 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h | |||
@@ -1747,6 +1747,7 @@ enum { | |||
1747 | #define GK20A_SIM_IORESOURCE_MEM 2 | 1747 | #define GK20A_SIM_IORESOURCE_MEM 2 |
1748 | 1748 | ||
1749 | void gk20a_busy_noresume(struct gk20a *g); | 1749 | void gk20a_busy_noresume(struct gk20a *g); |
1750 | int gk20a_busy_try_noresume(struct gk20a *g); | ||
1750 | void gk20a_idle_nosuspend(struct gk20a *g); | 1751 | void gk20a_idle_nosuspend(struct gk20a *g); |
1751 | int __must_check gk20a_busy(struct gk20a *g); | 1752 | int __must_check gk20a_busy(struct gk20a *g); |
1752 | void gk20a_idle(struct gk20a *g); | 1753 | void gk20a_idle(struct gk20a *g); |
diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c index 227a7d57..3ccc6b0a 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c | |||
@@ -568,19 +568,28 @@ static int gk20a_ctrl_get_fbp_l2_masks( | |||
568 | static int nvgpu_gpu_ioctl_l2_fb_ops(struct gk20a *g, | 568 | static int nvgpu_gpu_ioctl_l2_fb_ops(struct gk20a *g, |
569 | struct nvgpu_gpu_l2_fb_args *args) | 569 | struct nvgpu_gpu_l2_fb_args *args) |
570 | { | 570 | { |
571 | int err = 0; | 571 | int ret = 0; |
572 | 572 | ||
573 | if ((!args->l2_flush && !args->fb_flush) || | 573 | if ((!args->l2_flush && !args->fb_flush) || |
574 | (!args->l2_flush && args->l2_invalidate)) | 574 | (!args->l2_flush && args->l2_invalidate)) |
575 | return -EINVAL; | 575 | return -EINVAL; |
576 | 576 | ||
577 | ret = gk20a_busy_try_noresume(g); | ||
578 | |||
579 | /* return if device is already powered off */ | ||
580 | if (ret == 0) | ||
581 | return 0; | ||
582 | |||
577 | if (args->l2_flush) | 583 | if (args->l2_flush) |
578 | g->ops.mm.l2_flush(g, args->l2_invalidate ? true : false); | 584 | g->ops.mm.l2_flush(g, args->l2_invalidate ? true : false); |
579 | 585 | ||
580 | if (args->fb_flush) | 586 | if (args->fb_flush) |
581 | g->ops.mm.fb_flush(g); | 587 | g->ops.mm.fb_flush(g); |
582 | 588 | ||
583 | return err; | 589 | if (ret > 0) |
590 | gk20a_idle_nosuspend(g); | ||
591 | |||
592 | return 0; | ||
584 | } | 593 | } |
585 | 594 | ||
586 | static int nvgpu_gpu_ioctl_set_mmu_debug_mode( | 595 | static int nvgpu_gpu_ioctl_set_mmu_debug_mode( |
diff --git a/drivers/gpu/nvgpu/os/linux/module.c b/drivers/gpu/nvgpu/os/linux/module.c index c453bced..964fc651 100644 --- a/drivers/gpu/nvgpu/os/linux/module.c +++ b/drivers/gpu/nvgpu/os/linux/module.c | |||
@@ -109,6 +109,11 @@ void gk20a_busy_noresume(struct gk20a *g) | |||
109 | pm_runtime_get_noresume(dev_from_gk20a(g)); | 109 | pm_runtime_get_noresume(dev_from_gk20a(g)); |
110 | } | 110 | } |
111 | 111 | ||
112 | int gk20a_busy_try_noresume(struct gk20a *g) | ||
113 | { | ||
114 | return pm_runtime_get_if_in_use(dev_from_gk20a(g)); | ||
115 | } | ||
116 | |||
112 | /* | 117 | /* |
113 | * Check if the device can go busy. | 118 | * Check if the device can go busy. |
114 | */ | 119 | */ |