summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/os/linux/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/os/linux/module.c')
-rw-r--r--drivers/gpu/nvgpu/os/linux/module.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/drivers/gpu/nvgpu/os/linux/module.c b/drivers/gpu/nvgpu/os/linux/module.c
index 1fd7f544..955481c8 100644
--- a/drivers/gpu/nvgpu/os/linux/module.c
+++ b/drivers/gpu/nvgpu/os/linux/module.c
@@ -24,6 +24,8 @@
24#include <linux/interrupt.h> 24#include <linux/interrupt.h>
25#include <linux/pm_runtime.h> 25#include <linux/pm_runtime.h>
26#include <linux/reset.h> 26#include <linux/reset.h>
27#include <linux/reboot.h>
28#include <linux/notifier.h>
27#include <linux/platform/tegra/common.h> 29#include <linux/platform/tegra/common.h>
28#include <linux/pci.h> 30#include <linux/pci.h>
29 31
@@ -76,6 +78,14 @@
76#define CREATE_TRACE_POINTS 78#define CREATE_TRACE_POINTS
77#include <trace/events/gk20a.h> 79#include <trace/events/gk20a.h>
78 80
81static int nvgpu_kernel_shutdown_notification(struct notifier_block *nb,
82 unsigned long event, void *unused)
83{
84 struct gk20a *g = container_of(nb, struct gk20a, nvgpu_reboot_nb);
85
86 __nvgpu_set_enabled(g, NVGPU_KERNEL_IS_DYING, true);
87 return NOTIFY_DONE;
88}
79 89
80struct device_node *nvgpu_get_node(struct gk20a *g) 90struct device_node *nvgpu_get_node(struct gk20a *g)
81{ 91{
@@ -98,6 +108,22 @@ void gk20a_busy_noresume(struct gk20a *g)
98 pm_runtime_get_noresume(dev_from_gk20a(g)); 108 pm_runtime_get_noresume(dev_from_gk20a(g));
99} 109}
100 110
111/*
112 * Check if the device can go busy.
113 */
114static int nvgpu_can_busy(struct gk20a *g)
115{
116 /* Can't do anything if the system is rebooting/shutting down. */
117 if (nvgpu_is_enabled(g, NVGPU_KERNEL_IS_DYING))
118 return 0;
119
120 /* Can't do anything if the driver is restarting. */
121 if (nvgpu_is_enabled(g, NVGPU_DRIVER_IS_DYING))
122 return 0;
123
124 return 1;
125}
126
101int gk20a_busy(struct gk20a *g) 127int gk20a_busy(struct gk20a *g)
102{ 128{
103 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); 129 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
@@ -111,7 +137,7 @@ int gk20a_busy(struct gk20a *g)
111 137
112 down_read(&l->busy_lock); 138 down_read(&l->busy_lock);
113 139
114 if (!gk20a_can_busy(g)) { 140 if (!nvgpu_can_busy(g)) {
115 ret = -ENODEV; 141 ret = -ENODEV;
116 atomic_dec(&g->usage_count.atomic_var); 142 atomic_dec(&g->usage_count.atomic_var);
117 goto fail; 143 goto fail;
@@ -158,7 +184,7 @@ void gk20a_idle(struct gk20a *g)
158 184
159 dev = dev_from_gk20a(g); 185 dev = dev_from_gk20a(g);
160 186
161 if (!(dev && gk20a_can_busy(g))) 187 if (!(dev && nvgpu_can_busy(g)))
162 return; 188 return;
163 189
164 if (pm_runtime_enabled(dev)) { 190 if (pm_runtime_enabled(dev)) {
@@ -1289,6 +1315,12 @@ static int gk20a_probe(struct platform_device *dev)
1289 goto return_err; 1315 goto return_err;
1290 } 1316 }
1291 1317
1318 gk20a->nvgpu_reboot_nb.notifier_call =
1319 nvgpu_kernel_shutdown_notification;
1320 err = register_reboot_notifier(&gk20a->nvgpu_reboot_nb);
1321 if (err)
1322 goto return_err;
1323
1292 return 0; 1324 return 0;
1293 1325
1294return_err: 1326return_err:
@@ -1368,6 +1400,8 @@ static int __exit gk20a_remove(struct platform_device *pdev)
1368 1400
1369 err = nvgpu_remove(dev, &nvgpu_class); 1401 err = nvgpu_remove(dev, &nvgpu_class);
1370 1402
1403 unregister_reboot_notifier(&g->nvgpu_reboot_nb);
1404
1371 set_gk20a(pdev, NULL); 1405 set_gk20a(pdev, NULL);
1372 1406
1373 gk20a_put(g); 1407 gk20a_put(g);