aboutsummaryrefslogtreecommitdiffstats
path: root/include/os/linux/ioctl_tsg.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_tsg.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_tsg.c')
-rw-r--r--include/os/linux/ioctl_tsg.c750
1 files changed, 750 insertions, 0 deletions
diff --git a/include/os/linux/ioctl_tsg.c b/include/os/linux/ioctl_tsg.c
new file mode 100644
index 0000000..2f8cb3a
--- /dev/null
+++ b/include/os/linux/ioctl_tsg.c
@@ -0,0 +1,750 @@
1/*
2 * Copyright (c) 2014-2020, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/fs.h>
18#include <linux/file.h>
19#include <linux/cdev.h>
20#include <linux/uaccess.h>
21#include <linux/poll.h>
22#include <uapi/linux/nvgpu.h>
23#include <linux/anon_inodes.h>
24
25#include <nvgpu/kmem.h>
26#include <nvgpu/log.h>
27#include <nvgpu/os_sched.h>
28#include <nvgpu/gk20a.h>
29#include <nvgpu/channel.h>
30#include <nvgpu/tsg.h>
31
32#include "gv11b/fifo_gv11b.h"
33#include "platform_gk20a.h"
34#include "ioctl_tsg.h"
35#include "ioctl_channel.h"
36#include "os_linux.h"
37
38struct tsg_private {
39 struct gk20a *g;
40 struct tsg_gk20a *tsg;
41};
42
43static int gk20a_tsg_bind_channel_fd(struct tsg_gk20a *tsg, int ch_fd)
44{
45 struct channel_gk20a *ch;
46 int err;
47
48 ch = gk20a_get_channel_from_file(ch_fd);
49 if (!ch)
50 return -EINVAL;
51
52 err = ch->g->ops.fifo.tsg_bind_channel(tsg, ch);
53
54 gk20a_channel_put(ch);
55 return err;
56}
57
58static int gk20a_tsg_ioctl_bind_channel_ex(struct gk20a *g,
59 struct tsg_gk20a *tsg, struct nvgpu_tsg_bind_channel_ex_args *arg)
60{
61 struct nvgpu_sched_ctrl *sched = &g->sched_ctrl;
62 struct channel_gk20a *ch;
63 struct gr_gk20a *gr = &g->gr;
64 int err = 0;
65
66 nvgpu_log(g, gpu_dbg_fn | gpu_dbg_sched, "tsgid=%u", tsg->tsgid);
67
68 nvgpu_mutex_acquire(&sched->control_lock);
69 if (sched->control_locked) {
70 err = -EPERM;
71 goto mutex_release;
72 }
73 err = gk20a_busy(g);
74 if (err) {
75 nvgpu_err(g, "failed to power on gpu");
76 goto mutex_release;
77 }
78
79 ch = gk20a_get_channel_from_file(arg->channel_fd);
80 if (!ch) {
81 err = -EINVAL;
82 goto idle;
83 }
84
85 if (arg->tpc_pg_enabled && (!tsg->tpc_num_initialized)) {
86 if ((arg->num_active_tpcs > gr->max_tpc_count) ||
87 !(arg->num_active_tpcs)) {
88 nvgpu_err(g, "Invalid num of active TPCs");
89 err = -EINVAL;
90 goto ch_put;
91 }
92 tsg->tpc_num_initialized = true;
93 tsg->num_active_tpcs = arg->num_active_tpcs;
94 tsg->tpc_pg_enabled = true;
95 } else {
96 tsg->tpc_pg_enabled = false; nvgpu_log(g, gpu_dbg_info, "dynamic TPC-PG not enabled");
97 }
98
99 if (arg->subcontext_id < g->fifo.max_subctx_count) {
100 ch->subctx_id = arg->subcontext_id;
101 } else {
102 err = -EINVAL;
103 goto ch_put;
104 }
105
106 nvgpu_log(g, gpu_dbg_info, "channel id : %d : subctx: %d",
107 ch->chid, ch->subctx_id);
108
109 /* Use runqueue selector 1 for all ASYNC ids */
110 if (ch->subctx_id > CHANNEL_INFO_VEID0)
111 ch->runqueue_sel = 1;
112
113 err = ch->g->ops.fifo.tsg_bind_channel(tsg, ch);
114ch_put:
115 gk20a_channel_put(ch);
116idle:
117 gk20a_idle(g);
118mutex_release:
119 nvgpu_mutex_release(&sched->control_lock);
120 return err;
121}
122
123static int gk20a_tsg_unbind_channel_fd(struct tsg_gk20a *tsg, int ch_fd)
124{
125 struct channel_gk20a *ch;
126 int err = 0;
127
128 ch = gk20a_get_channel_from_file(ch_fd);
129 if (!ch)
130 return -EINVAL;
131
132 if (ch->tsgid != tsg->tsgid) {
133 err = -EINVAL;
134 goto out;
135 }
136
137 err = gk20a_tsg_unbind_channel(ch);
138
139 /*
140 * Mark the channel timedout since channel unbound from TSG
141 * has no context of its own so it can't serve any job
142 */
143 gk20a_channel_set_timedout(ch);
144
145out:
146 gk20a_channel_put(ch);
147 return err;
148}
149
150static int gk20a_tsg_get_event_data_from_id(struct tsg_gk20a *tsg,
151 unsigned int event_id,
152 struct gk20a_event_id_data **event_id_data)
153{
154 struct gk20a_event_id_data *local_event_id_data;
155 bool event_found = false;
156
157 nvgpu_mutex_acquire(&tsg->event_id_list_lock);
158 nvgpu_list_for_each_entry(local_event_id_data, &tsg->event_id_list,
159 gk20a_event_id_data, event_id_node) {
160 if (local_event_id_data->event_id == event_id) {
161 event_found = true;
162 break;
163 }
164 }
165 nvgpu_mutex_release(&tsg->event_id_list_lock);
166
167 if (event_found) {
168 *event_id_data = local_event_id_data;
169 return 0;
170 } else {
171 return -1;
172 }
173}
174
175/*
176 * Convert common event_id of the form NVGPU_EVENT_ID_* to Linux specific
177 * event_id of the form NVGPU_IOCTL_CHANNEL_EVENT_ID_* which is used in IOCTLs
178 */
179static u32 nvgpu_event_id_to_ioctl_channel_event_id(u32 event_id)
180{
181 switch (event_id) {
182 case NVGPU_EVENT_ID_BPT_INT:
183 return NVGPU_IOCTL_CHANNEL_EVENT_ID_BPT_INT;
184 case NVGPU_EVENT_ID_BPT_PAUSE:
185 return NVGPU_IOCTL_CHANNEL_EVENT_ID_BPT_PAUSE;
186 case NVGPU_EVENT_ID_BLOCKING_SYNC:
187 return NVGPU_IOCTL_CHANNEL_EVENT_ID_BLOCKING_SYNC;
188 case NVGPU_EVENT_ID_CILP_PREEMPTION_STARTED:
189 return NVGPU_IOCTL_CHANNEL_EVENT_ID_CILP_PREEMPTION_STARTED;
190 case NVGPU_EVENT_ID_CILP_PREEMPTION_COMPLETE:
191 return NVGPU_IOCTL_CHANNEL_EVENT_ID_CILP_PREEMPTION_COMPLETE;
192 case NVGPU_EVENT_ID_GR_SEMAPHORE_WRITE_AWAKEN:
193 return NVGPU_IOCTL_CHANNEL_EVENT_ID_GR_SEMAPHORE_WRITE_AWAKEN;
194 }
195
196 return NVGPU_IOCTL_CHANNEL_EVENT_ID_MAX;
197}
198
199void gk20a_tsg_event_id_post_event(struct tsg_gk20a *tsg,
200 int __event_id)
201{
202 struct gk20a_event_id_data *event_id_data;
203 u32 event_id;
204 int err = 0;
205 struct gk20a *g = tsg->g;
206
207 event_id = nvgpu_event_id_to_ioctl_channel_event_id(__event_id);
208 if (event_id >= NVGPU_IOCTL_CHANNEL_EVENT_ID_MAX)
209 return;
210
211 err = gk20a_tsg_get_event_data_from_id(tsg, event_id,
212 &event_id_data);
213 if (err)
214 return;
215
216 nvgpu_mutex_acquire(&event_id_data->lock);