diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index f393e7991..7ed4c7141 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h @@ -1747,6 +1747,7 @@ enum { #define GK20A_SIM_IORESOURCE_MEM 2 void gk20a_busy_noresume(struct gk20a *g); +int gk20a_busy_try_noresume(struct gk20a *g); void gk20a_idle_nosuspend(struct gk20a *g); int __must_check gk20a_busy(struct gk20a *g); 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 227a7d579..3ccc6b0ae 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( static int nvgpu_gpu_ioctl_l2_fb_ops(struct gk20a *g, struct nvgpu_gpu_l2_fb_args *args) { - int err = 0; + int ret = 0; if ((!args->l2_flush && !args->fb_flush) || (!args->l2_flush && args->l2_invalidate)) return -EINVAL; + ret = gk20a_busy_try_noresume(g); + + /* return if device is already powered off */ + if (ret == 0) + return 0; + if (args->l2_flush) g->ops.mm.l2_flush(g, args->l2_invalidate ? true : false); if (args->fb_flush) g->ops.mm.fb_flush(g); - return err; + if (ret > 0) + gk20a_idle_nosuspend(g); + + return 0; } 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 c453bcedb..964fc651e 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) pm_runtime_get_noresume(dev_from_gk20a(g)); } +int gk20a_busy_try_noresume(struct gk20a *g) +{ + return pm_runtime_get_if_in_use(dev_from_gk20a(g)); +} + /* * Check if the device can go busy. */