aboutsummaryrefslogtreecommitdiffstats
path: root/include/os/linux/ioctl_channel.c
diff options
context:
space:
mode:
authorJoshua Bakita <bakitajoshua@gmail.com>2023-06-28 18:24:25 -0400
committerJoshua Bakita <bakitajoshua@gmail.com>2023-06-28 18:24:25 -0400
commit01e6fac4d61fdd7fff5433942ec93fc2ea1e4df1 (patch)
tree4ef34501728a087be24f4ba0af90f91486bf780b /include/os/linux/ioctl_channel.c
parent306a03d18b305e4e573be3b2931978fa10679eb9 (diff)
Include nvgpu headers
These are needed to build on NVIDIA's Jetson boards for the time being. Only a couple structs are required, so it should be fairly easy to remove this dependency at some point in the future.
Diffstat (limited to 'include/os/linux/ioctl_channel.c')
-rw-r--r--include/os/linux/ioctl_channel.c1388
1 files changed, 1388 insertions, 0 deletions
diff --git a/include/os/linux/ioctl_channel.c b/include/os/linux/ioctl_channel.c
new file mode 100644
index 0000000..0f39cc7
--- /dev/null
+++ b/include/os/linux/ioctl_channel.c
@@ -0,0 +1,1388 @@
1/*
2 * GK20A Graphics channel
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 <trace/events/gk20a.h>
20#include <linux/file.h>
21#include <linux/anon_inodes.h>
22#include <linux/dma-buf.h>
23#include <linux/poll.h>
24#include <uapi/linux/nvgpu.h>
25
26#include <nvgpu/semaphore.h>
27#include <nvgpu/timers.h>
28#include <nvgpu/kmem.h>
29#include <nvgpu/log.h>
30#include <nvgpu/list.h>
31#include <nvgpu/debug.h>
32#include <nvgpu/enabled.h>
33#include <nvgpu/error_notifier.h>
34#include <nvgpu/barrier.h>
35#include <nvgpu/nvhost.h>
36#include <nvgpu/os_sched.h>
37#include <nvgpu/gk20a.h>
38#include <nvgpu/channel.h>
39#include <nvgpu/channel_sync.h>
40
41#include "gk20a/dbg_gpu_gk20a.h"
42#include "gk20a/fence_gk20a.h"
43
44#include "platform_gk20a.h"
45#include "ioctl_channel.h"
46#include "channel.h"
47#include "os_linux.h"
48#include "ctxsw_trace.h"
49
50/* the minimal size of client buffer */
51#define CSS_MIN_CLIENT_SNAPSHOT_SIZE \
52 (sizeof(struct gk20a_cs_snapshot_fifo) + \
53 sizeof(struct gk20a_cs_snapshot_fifo_entry) * 256)
54
55static const char *gr_gk20a_graphics_preempt_mode_name(u32 graphics_preempt_mode)
56{
57 switch (graphics_preempt_mode) {
58 case NVGPU_PREEMPTION_MODE_GRAPHICS_WFI:
59 return "WFI";
60 default:
61 return "?";
62 }
63}
64
65static const char *gr_gk20a_compute_preempt_mode_name(u32 compute_preempt_mode)
66{
67 switch (compute_preempt_mode) {
68 case NVGPU_PREEMPTION_MODE_COMPUTE_WFI:
69 return "WFI";
70 case NVGPU_PREEMPTION_MODE_COMPUTE_CTA:
71 return "CTA";
72 default:
73 return "?";
74 }
75}
76
77static void gk20a_channel_trace_sched_param(
78 void (*trace)(int chid, int tsgid, pid_t pid, u32 timeslice,
79 u32 timeout, const char *interleave,
80 const char *graphics_preempt_mode,
81 const char *compute_preempt_mode),
82 struct channel_gk20a *ch)
83{
84 struct tsg_gk20a *tsg = tsg_gk20a_from_ch(ch);
85
86 if (!tsg)
87 return;
88
89 (trace)(ch->chid, ch->tsgid, ch->pid,
90 tsg_gk20a_from_ch(ch)->timeslice_us,
91 ch->timeout_ms_max,
92 gk20a_fifo_interleave_level_name(tsg->interleave_level),
93 gr_gk20a_graphics_preempt_mode_name(
94 tsg->gr_ctx.graphics_preempt_mode),
95 gr_gk20a_compute_preempt_mode_name(
96 tsg->gr_ctx.compute_preempt_mode));
97}
98
99/*
100 * Although channels do have pointers back to the gk20a struct that they were
101 * created under in cases where the driver is killed that pointer can be bad.
102 * The channel memory can be freed before the release() function for a given
103 * channel is called. This happens when the driver dies and userspace doesn't
104 * get a chance to call release() until after the entire gk20a driver data is
105 * unloaded and freed.
106 */
107struct channel_priv {
108 struct gk20a *g;
109 struct channel_gk20a *c;
110};
111
112#if defined(CONFIG_GK20A_CYCLE_STATS)
113
114void gk20a_channel_free_cycle_stats_buffer(struct channel_gk20a *ch)
115{
116 struct nvgpu_channel_linux *priv = ch->os_priv;
117
118 /* disable existing cyclestats buffer */
119 nvgpu_mutex_acquire(&ch->cyclestate.cyclestate_buffer_mutex);
120 if (priv->cyclestate_buffer_handler) {
121 dma_buf_vunmap(priv->cyclestate_buffer_handler,
122 ch->cyclestate.cyclestate_buffer);
123 dma_buf_put(priv->cyclestate_buffer_handler);
124 priv->cyclestate_buffer_handler = NULL;
125 ch->cyclestate.cyclestate_buffer = NULL;
126 ch->cyclestate.cyclestate_buffer_size = 0;
127 }
128 nvgpu_mutex_release(&ch->cyclestate.cyclestate_buffer_mutex);
129}
130
131int gk20a_channel_cycle_stats(struct channel_gk20a *ch, int dmabuf_fd)
132{
133 struct dma_buf *dmabuf;
134 void *virtual_address;
135 struct nvgpu_channel_linux *priv = ch->os_priv;
136
137 /* is it allowed to handle calls for current GPU? */
138 if (!nvgpu_is_enabled(ch->g, NVGPU_SUPPORT_CYCLE_STATS))
139 return -ENOSYS;
140
141 if (dmabuf_fd && !priv->cyclestate_buffer_handler) {
142
143 /* set up new cyclestats buffer */
144 dmabuf = dma_buf_get(dmabuf_fd);
145 if (IS_ERR(dmabuf))
146 return PTR_ERR(dmabuf);
147 virtual_address = dma_buf_vmap(dmabuf);
148 if (!virtual_address)
149 return -ENOMEM;
150
151 priv->cyclestate_buffer_handler = dmabuf;
152 ch->cyclestate.cyclestate_buffer = virtual_address;
153 ch->cyclestate.cyclestate_buffer_size = dmabuf->size;
154 return 0;
155
156 } else if (!dmabuf_fd && priv->cyclestate_buffer_handler) {
157 gk20a_channel_free_cycle_stats_buffer(ch);
158 return 0;
159
160 } else if (!dmabuf_fd && !priv->cyclestate_buffer_handler) {
161 /* no request from GL */
162 return 0;
163
164 } else {
165 pr_err("channel already has cyclestats buffer\n");
166 return -EINVAL;
167 }
168}
169
170int gk20a_flush_cycle_stats_snapshot(struct channel_gk20a *ch)
171{
172 int ret;
173
174 nvgpu_mutex_acquire(&ch->cs_client_mutex);
175 if (ch->cs_client)
176 ret = gr_gk20a_css_flush(ch, ch->cs_client);
177 else
178 ret = -EBADF;
179 nvgpu_mutex_release(&ch->cs_client_mutex);
180
181 return ret;
182}
183
184int gk20a_attach_cycle_stats_snapshot(struct channel_gk20a *ch,
185 u32 dmabuf_fd,
186 u32 perfmon_id_count,
187 u32 *perfmon_id_start)
188{
189 int ret = 0;
190 struct gk20a *g = ch->g;
191 struct gk20a_cs_snapshot_client_linux *client_linux;
192 struct gk20a_cs_snapshot_client *client;
193
194 nvgpu_mutex_acquire(&ch->cs_client_mutex);
195 if (ch->cs_client) {
196 nvgpu_mutex_release(&ch->cs_client_mutex);
197 return -EEXIST;
198 }
199
200 client_linux = nvgpu_kzalloc(g, sizeof(*client_linux));
201 if (!client_linux) {
202 ret = -ENOMEM;
203 goto err;
204 }
205
206 client_linux->dmabuf_fd = dmabuf_fd;
207 client_linux->dma_handler = dma_buf_get(client_linux->dmabuf_fd);
208 if (IS_ERR(client_linux->dma_handler)) {
209 ret = PTR_ERR(client_linux->dma_handler);
210 client_linux->dma_handler = NULL;