aboutsummaryrefslogtreecommitdiffstats
path: root/include/os/linux/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'include/os/linux/module.c')
-rw-r--r--include/os/linux/module.c1529
1 files changed, 1529 insertions, 0 deletions
diff --git a/include/os/linux/module.c b/include/os/linux/module.c
new file mode 100644
index 0000000..807df2c
--- /dev/null
+++ b/include/os/linux/module.c
@@ -0,0 +1,1529 @@
1/*
2 * GK20A Graphics
3 *
4 * Copyright (c) 2011-2020, NVIDIA CORPORATION. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/module.h>
20#include <linux/of.h>
21#include <linux/of_device.h>
22#include <linux/of_platform.h>
23#include <linux/of_address.h>
24#include <linux/interrupt.h>
25#include <linux/pm_runtime.h>
26#include <linux/reset.h>
27#include <linux/reboot.h>
28#include <linux/notifier.h>
29#include <linux/platform/tegra/common.h>
30#include <linux/pci.h>
31
32#include <uapi/linux/nvgpu.h>
33#include <dt-bindings/soc/gm20b-fuse.h>
34#include <dt-bindings/soc/gp10b-fuse.h>
35#include <dt-bindings/soc/gv11b-fuse.h>
36
37#include <soc/tegra/fuse.h>
38
39#include <nvgpu/hal_init.h>
40#include <nvgpu/dma.h>
41#include <nvgpu/kmem.h>
42#include <nvgpu/nvgpu_common.h>
43#include <nvgpu/soc.h>
44#include <nvgpu/enabled.h>
45#include <nvgpu/debug.h>
46#include <nvgpu/ctxsw_trace.h>
47#include <nvgpu/vidmem.h>
48#include <nvgpu/sim.h>
49#include <nvgpu/clk_arb.h>
50#include <nvgpu/timers.h>
51#include <nvgpu/channel.h>
52
53#include "platform_gk20a.h"
54#include "sysfs.h"
55#include "vgpu/vgpu_linux.h"
56#include "scale.h"
57#include "pci.h"
58#include "module.h"
59#include "module_usermode.h"
60#include "intr.h"
61#include "ioctl.h"
62#include "ioctl_ctrl.h"
63
64#include "os_linux.h"
65#include "os_ops.h"
66#include "ctxsw_trace.h"
67#include "driver_common.h"
68#include "channel.h"
69#include "debug_pmgr.h"
70
71#ifdef CONFIG_NVGPU_SUPPORT_CDE
72#include "cde.h"
73#endif
74
75#define CLASS_NAME "nvidia-gpu"
76/* TODO: Change to e.g. "nvidia-gpu%s" once we have symlinks in place. */
77
78#define GK20A_WAIT_FOR_IDLE_MS 2000
79
80#define CREATE_TRACE_POINTS
81#include <trace/events/gk20a.h>
82
83static int nvgpu_kernel_shutdown_notification(struct notifier_block *nb,
84 unsigned long event, void *unused)
85{
86 struct gk20a *g = container_of(nb, struct gk20a, nvgpu_reboot_nb);
87
88 __nvgpu_set_enabled(g, NVGPU_KERNEL_IS_DYING, true);
89 return NOTIFY_DONE;
90}
91
92struct device_node *nvgpu_get_node(struct gk20a *g)
93{
94 struct device *dev = dev_from_gk20a(g);
95
96 if (dev_is_pci(dev)) {
97 struct pci_bus *bus = to_pci_dev(dev)->bus;
98
99 while (!pci_is_root_bus(bus))
100 bus = bus->parent;
101
102 return bus->bridge->parent->of_node;
103 }
104
105 return dev->of_node;
106}
107
108void gk20a_busy_noresume(struct gk20a *g)
109{
110 pm_runtime_get_noresume(dev_from_gk20a(g));
111}
112
113/*
114 * Check if the device can go busy.
115 */
116static int nvgpu_can_busy(struct gk20a *g)
117{
118 /* Can't do anything if the system is rebooting/shutting down. */
119 if (nvgpu_is_enabled(g, NVGPU_KERNEL_IS_DYING))
120 return 0;
121
122 /* Can't do anything if the driver is restarting. */
123 if (nvgpu_is_enabled(g, NVGPU_DRIVER_IS_DYING))
124 return 0;
125
126 return 1;
127}
128
129int gk20a_busy(struct gk20a *g)
130{
131 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
132 int ret = 0;
133 struct device *dev;
134
135 if (!g)
136 return -ENODEV;
137
138 atomic_inc(&g->usage_count.atomic_var);
139
140 down_read(&l->busy_lock);
141
142 if (!nvgpu_can_busy(g)) {
143 ret = -ENODEV;
144 atomic_dec(&g->usage_count.atomic_var);
145 goto fail;
146 }
147
148 dev = dev_from_gk20a(g);
149
150 if (pm_runtime_enabled(dev)) {
151 /* Increment usage count and attempt to resume device */
152 ret = pm_runtime_get_sync(dev);
153 if (ret < 0) {
154 /* Mark suspended so runtime pm will retry later */
155 pm_runtime_set_suspended(dev);
156 pm_runtime_put_noidle(dev);
157 atomic_dec(&g->usage_count.atomic_var);
158 goto fail;
159 }
160 } else {
161 ret = gk20a_gpu_is_virtual(dev) ?
162 vgpu_pm_finalize_poweron(dev) :
163 gk20a_pm_finalize_poweron(dev);
164 if (ret) {
165 atomic_dec(&g->usage_count.atomic_var);
166 goto fail;
167 }
168 }
169
170fail:
171 up_read(&l->busy_lock);
172
173 return ret < 0 ? ret : 0;
174}
175
176void gk20a_idle_nosuspend(struct gk20a *g)
177{
178 pm_runtime_put_noidle(dev_from_gk20a(g));
179}
180
181void gk20a_idle(struct gk20a *g)
182{
183 struct device *dev;
184
185 atomic_dec(&g->usage_count.atomic_var);
186
187 dev = dev_from_gk20a(g);
188
189 if (!(dev && nvgpu_can_busy(g)))
190 return;
191
192 if (pm_runtime_enabled(dev)) {
193 pm_runtime_mark_last_busy(dev);
194 pm_runtime_put_sync_autosuspend(dev);
195 }
196}
197
198/*
199 * Undoes gk20a_lockout_registers().
200 */
201static int gk20a_restore_registers(struct gk20a *g)
202{
203 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
204
205 l->regs = l->regs_saved;
206 l->bar1 = l->bar1_saved;
207
208 nvgpu_restore_usermode_registers(g);
209
210 return 0;
211}
212
213int nvgpu_finalize_poweron_linux(struct nvgpu_os_linux *l)
214{
215 struct gk20a *g = &l->g;
216 int err;
217
218 if (l->init_done)
219 return 0;
220
221 err = nvgpu_init_channel_support_linux(l);
222 if (err) {
223 nvgpu_err(g, "failed to init linux channel support");
224 return err;
225 }
226
227 if (l->ops.clk.init_debugfs) {
228 err = l->ops.clk.init_debugfs(g);
229 if (err) {
230 nvgpu_err(g, "failed to init linux clk debugfs");