summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/gk20a.h1
-rw-r--r--drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c32
-rw-r--r--drivers/gpu/nvgpu/os/linux/module.c16
-rw-r--r--drivers/gpu/nvgpu/os/posix/nvgpu.c6
4 files changed, 49 insertions, 6 deletions
diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h
index 8b6de266..61fe4fb5 100644
--- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h
+++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h
@@ -1787,6 +1787,7 @@ int gk20a_wait_for_idle(struct gk20a *g);
1787 1787
1788int gk20a_init_gpu_characteristics(struct gk20a *g); 1788int gk20a_init_gpu_characteristics(struct gk20a *g);
1789 1789
1790bool gk20a_check_poweron(struct gk20a *g);
1790int gk20a_prepare_poweroff(struct gk20a *g); 1791int gk20a_prepare_poweroff(struct gk20a *g);
1791int gk20a_finalize_poweron(struct gk20a *g); 1792int gk20a_finalize_poweron(struct gk20a *g);
1792 1793
diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c
index 6fa15421..271c5d92 100644
--- a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c
+++ b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c
@@ -19,6 +19,7 @@
19#include <linux/file.h> 19#include <linux/file.h>
20#include <linux/anon_inodes.h> 20#include <linux/anon_inodes.h>
21#include <linux/fs.h> 21#include <linux/fs.h>
22#include <linux/pm_runtime.h>
22#include <uapi/linux/nvgpu.h> 23#include <uapi/linux/nvgpu.h>
23 24
24#include <nvgpu/bitops.h> 25#include <nvgpu/bitops.h>
@@ -596,19 +597,46 @@ static int gk20a_ctrl_get_fbp_l2_masks(
596static int nvgpu_gpu_ioctl_l2_fb_ops(struct gk20a *g, 597static int nvgpu_gpu_ioctl_l2_fb_ops(struct gk20a *g,
597 struct nvgpu_gpu_l2_fb_args *args) 598 struct nvgpu_gpu_l2_fb_args *args)
598{ 599{
599 int err = 0; 600 int ret;
601 bool always_poweron;
600 602
601 if ((!args->l2_flush && !args->fb_flush) || 603 if ((!args->l2_flush && !args->fb_flush) ||
602 (!args->l2_flush && args->l2_invalidate)) 604 (!args->l2_flush && args->l2_invalidate))
603 return -EINVAL; 605 return -EINVAL;
604 606
607 /* Handle this case for joint rails or DGPU */
608 always_poweron = (!nvgpu_is_enabled(g, NVGPU_CAN_RAILGATE) ||
609 !pm_runtime_enabled(dev_from_gk20a(g)));
610
611 /* In case of not always power_on, exit if g->power_on is false */
612 if (!always_poweron && !gk20a_check_poweron(g)) {
613 return 0;
614 }
615
616 /* There is a small window between a call to gk20a_idle() has occured
617 * and railgate being actually triggered(setting g->power_on = false),
618 * when l2_flush can race with railgate. Its better to take a busy_lock
619 * to prevent the gk20a_idle() from proceeding. There is a very small
620 * chance that gk20a_idle() might begin before gk20a_busy(). Having
621 * a locked access to g->power_on further reduces the probability of
622 * gk20a_idle() being triggered before gk20a_busy()
623 */
624 ret = gk20a_busy(g);
625
626 if (ret != 0) {
627 nvgpu_err(g, "failed to take power ref");
628 return ret;
629 }
630
605 if (args->l2_flush) 631 if (args->l2_flush)
606 g->ops.mm.l2_flush(g, args->l2_invalidate ? true : false); 632 g->ops.mm.l2_flush(g, args->l2_invalidate ? true : false);
607 633
608 if (args->fb_flush) 634 if (args->fb_flush)
609 g->ops.mm.fb_flush(g); 635 g->ops.mm.fb_flush(g);
610 636
611 return err; 637 gk20a_idle(g);
638
639 return 0;
612} 640}
613 641
614static int nvgpu_gpu_ioctl_set_mmu_debug_mode( 642static 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 18345ada..5627abfd 100644
--- a/drivers/gpu/nvgpu/os/linux/module.c
+++ b/drivers/gpu/nvgpu/os/linux/module.c
@@ -107,10 +107,7 @@ struct device_node *nvgpu_get_node(struct gk20a *g)
107 107
108void gk20a_busy_noresume(struct gk20a *g) 108void gk20a_busy_noresume(struct gk20a *g)
109{ 109{
110 int ret = pm_runtime_get_if_in_use(dev_from_gk20a(g)); 110 pm_runtime_get_noresume(dev_from_gk20a(g));
111
112 if (ret <= 0)
113 pm_runtime_get_noresume(dev_from_gk20a(g));
114} 111}
115 112
116/* 113/*
@@ -262,6 +259,17 @@ int nvgpu_finalize_poweron_linux(struct nvgpu_os_linux *l)
262 return 0; 259 return 0;
263} 260}
264 261
262bool gk20a_check_poweron(struct gk20a *g)
263{
264 bool ret;
265
266 nvgpu_mutex_acquire(&g->power_lock);
267 ret = g->power_on;
268 nvgpu_mutex_release(&g->power_lock);
269
270 return ret;
271}
272
265int gk20a_pm_finalize_poweron(struct device *dev) 273int gk20a_pm_finalize_poweron(struct device *dev)
266{ 274{
267 struct gk20a *g = get_gk20a(dev); 275 struct gk20a *g = get_gk20a(dev);
diff --git a/drivers/gpu/nvgpu/os/posix/nvgpu.c b/drivers/gpu/nvgpu/os/posix/nvgpu.c
index 2f84dc6e..e485ed73 100644
--- a/drivers/gpu/nvgpu/os/posix/nvgpu.c
+++ b/drivers/gpu/nvgpu/os/posix/nvgpu.c
@@ -24,6 +24,7 @@
24#include <stdlib.h> 24#include <stdlib.h>
25#include <pthread.h> 25#include <pthread.h>
26 26
27#include <nvgpu/gk20a.h>
27#include <nvgpu/bug.h> 28#include <nvgpu/bug.h>
28#include <nvgpu/types.h> 29#include <nvgpu/types.h>
29#include <nvgpu/atomic.h> 30#include <nvgpu/atomic.h>
@@ -92,6 +93,11 @@ void gk20a_idle_nosuspend(struct gk20a *g)
92{ 93{
93} 94}
94 95
96bool gk20a_check_poweron(struct gk20a *g)
97{
98 return false;
99}
100
95int gk20a_busy(struct gk20a *g) 101int gk20a_busy(struct gk20a *g)
96{ 102{
97 nvgpu_atomic_inc(&g->usage_count); 103 nvgpu_atomic_inc(&g->usage_count);