diff options
Diffstat (limited to 'include/os/linux/ioctl_tsg.c')
| -rw-r--r-- | include/os/linux/ioctl_tsg.c | 750 |
1 files changed, 0 insertions, 750 deletions
diff --git a/include/os/linux/ioctl_tsg.c b/include/os/linux/ioctl_tsg.c deleted file mode 100644 index 296b02b..0000000 --- a/include/os/linux/ioctl_tsg.c +++ /dev/null | |||
| @@ -1,750 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2014-2021, 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 | |||
| 38 | struct tsg_private { | ||
| 39 | struct gk20a *g; | ||
| 40 | struct tsg_gk20a *tsg; | ||
| 41 | }; | ||
| 42 | |||
| 43 | static 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 | |||
| 58 | static 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); | ||
| 114 | ch_put: | ||
| 115 | gk20a_channel_put(ch); | ||
| 116 | idle: | ||
| 117 | gk20a_idle(g); | ||
| 118 | mutex_release: | ||
| 119 | nvgpu_mutex_release(&sched->control_lock); | ||
| 120 | return err; | ||
| 121 | } | ||
| 122 | |||
| 123 | static 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, false); | ||
| 138 | if (err == -EAGAIN) { | ||
| 139 | goto out; | ||
| 140 | } | ||
| 141 | |||
| 142 | /* | ||
| 143 | * Mark the channel timedout since channel unbound from TSG | ||
| 144 | * has no context of its own so it can't serve any job | ||
| 145 | */ | ||
| 146 | gk20a_channel_set_timedout(ch); | ||
| 147 | |||
| 148 | out: | ||
| 149 | gk20a_channel_put(ch); | ||
| 150 | return err; | ||
| 151 | } | ||
| 152 | |||
| 153 | static int gk20a_tsg_get_event_data_from_id(struct tsg_gk20a *tsg, | ||
| 154 | unsigned int event_id, | ||
| 155 | struct gk20a_event_id_data **event_id_data) | ||
| 156 | { | ||
| 157 | struct gk20a_event_id_data *local_event_id_data; | ||
| 158 | bool event_found = false; | ||
| 159 | |||
| 160 | nvgpu_mutex_acquire(&tsg->event_id_list_lock); | ||
| 161 | nvgpu_list_for_each_entry(local_event_id_data, &tsg->event_id_list, | ||
| 162 | gk20a_event_id_data, event_id_node) { | ||
| 163 | if (local_event_id_data->event_id == event_id) { | ||
| 164 | event_found = true; | ||
| 165 | break; | ||
| 166 | } | ||
| 167 | } | ||
| 168 | nvgpu_mutex_release(&tsg->event_id_list_lock); | ||
| 169 | |||
| 170 | if (event_found) { | ||
| 171 | *event_id_data = local_event_id_data; | ||
| 172 | return 0; | ||
| 173 | } else { | ||
| 174 | return -1; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | /* | ||
| 179 | * Convert common event_id of the form NVGPU_EVENT_ID_* to Linux specific | ||
| 180 | * event_id of the form NVGPU_IOCTL_CHANNEL_EVENT_ID_* which is used in IOCTLs | ||
| 181 | */ | ||
| 182 | static u32 nvgpu_event_id_to_ioctl_channel_event_id(u32 event_id) | ||
| 183 | { | ||
| 184 | switch (event_id) { | ||
| 185 | case NVGPU_EVENT_ID_BPT_INT: | ||
| 186 | return NVGPU_IOCTL_CHANNEL_EVENT_ID_BPT_INT; | ||
| 187 | case NVGPU_EVENT_ID_BPT_PAUSE: | ||
| 188 | return NVGPU_IOCTL_CHANNEL_EVENT_ID_BPT_PAUSE; | ||
| 189 | case NVGPU_EVENT_ID_BLOCKING_SYNC: | ||
| 190 | return NVGPU_IOCTL_CHANNEL_EVENT_ID_BLOCKING_SYNC; | ||
| 191 | case NVGPU_EVENT_ID_CILP_PREEMPTION_STARTED: | ||
| 192 | return NVGPU_IOCTL_CHANNEL_EVENT_ID_CILP_PREEMPTION_STARTED; | ||
| 193 | case NVGPU_EVENT_ID_CILP_PREEMPTION_COMPLETE: | ||
| 194 | return NVGPU_IOCTL_CHANNEL_EVENT_ID_CILP_PREEMPTION_COMPLETE; | ||
| 195 | case NVGPU_EVENT_ID_GR_SEMAPHORE_WRITE_AWAKEN: | ||
| 196 | return NVGPU_IOCTL_CHANNEL_EVENT_ID_GR_SEMAPHORE_WRITE_AWAKEN; | ||
| 197 | } | ||
| 198 | |||
| 199 | return NVGPU_IOCTL_CHANNEL_EVENT_ID_MAX; | ||
| 200 | } | ||
| 201 | |||
| 202 | void gk20a_tsg_event_id_post_event(struct tsg_gk20a *tsg, | ||
| 203 | int __event_id) | ||
| 204 | { | ||
| 205 | struct gk20a_event_id_data *event_id_data; | ||
| 206 | u32 event_id; | ||
| 207 | int err = 0; | ||
| 208 | struct gk20a *g = tsg->g; | ||
| 209 | |||
| 210 | event_id = nvgpu_event_id_to_ioctl_channel_event_id(__event_id); | ||
| 211 | if (event_id >= NVGPU_IOCTL_CHANNEL_EVENT_ID_MAX) | ||
| 212 | return; | ||
| 213 | |||
| 214 | err = gk20a_tsg_get_event_data_from_id(tsg, event_id, | ||
| 215 | &event_id_data); | ||
| 216 | if (err) | ||
| 217 | return; | ||
| 218 | |||
| 219 | nvgpu_mutex_acquire(&event_id_data->lock); | ||
| 220 | |||
| 221 | nvgpu_log_info(g, | ||
| 222 | "posting event for event_id=%d on tsg=%d\n", | ||
| 223 | event_id, tsg->tsgid); | ||
