diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2016-03-21 10:28:28 -0400 |
---|---|---|
committer | Terje Bergstrom <tbergstrom@nvidia.com> | 2016-04-07 11:44:38 -0400 |
commit | 5f10073540acba056ccf905010dd400d8f32ca31 (patch) | |
tree | 4365f3e416dad7d9dae1801040b5274ae96bca44 /drivers | |
parent | e87ba53235151cccee181489ceb5e35b131e7d2d (diff) |
gpu: nvgpu: add TSG support to channel event id
Add NVGPU_IOCTL_TSG_EVENT_ID_CTRL API for channel
event id support to TSGs
This API will accept an event_id (like BPT.INT or
BPT.PAUSE), a command to enable
the event, and return a file descriptor on which
we can raise the event (if cmd=enable)
Events generated for TSGs will reuse file
operations "gk20a_event_id_ops"
Bug 200089620
Change-Id: I2f563c6d3a0988eb670caac2d3c7c6795724792c
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/1030776
(cherry picked from commit 72b61fa266279038f013e582be80c21808e1038d)
Reviewed-on: http://git-master/r/1120319
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 18 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/tsg_gk20a.c | 126 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/tsg_gk20a.h | 3 |
4 files changed, 146 insertions, 3 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index be9c7cd4..4ad9d85b 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |||
@@ -2506,7 +2506,13 @@ unsigned int gk20a_event_id_poll(struct file *filep, poll_table *wait) | |||
2506 | 2506 | ||
2507 | mutex_lock(&event_id_data->lock); | 2507 | mutex_lock(&event_id_data->lock); |
2508 | 2508 | ||
2509 | if (!event_id_data->is_tsg) { | 2509 | if (event_id_data->is_tsg) { |
2510 | struct tsg_gk20a *tsg = g->fifo.tsg + event_id_data->id; | ||
2511 | |||
2512 | gk20a_dbg_info( | ||
2513 | "found pending event_id=%d on TSG=%d\n", | ||
2514 | event_id, tsg->tsgid); | ||
2515 | } else { | ||
2510 | struct channel_gk20a *ch = g->fifo.channel | 2516 | struct channel_gk20a *ch = g->fifo.channel |
2511 | + event_id_data->id; | 2517 | + event_id_data->id; |
2512 | 2518 | ||
@@ -2526,7 +2532,13 @@ int gk20a_event_id_release(struct inode *inode, struct file *filp) | |||
2526 | struct gk20a_event_id_data *event_id_data = filp->private_data; | 2532 | struct gk20a_event_id_data *event_id_data = filp->private_data; |
2527 | struct gk20a *g = event_id_data->g; | 2533 | struct gk20a *g = event_id_data->g; |
2528 | 2534 | ||
2529 | if (!event_id_data->is_tsg) { | 2535 | if (event_id_data->is_tsg) { |
2536 | struct tsg_gk20a *tsg = g->fifo.tsg + event_id_data->id; | ||
2537 | |||
2538 | mutex_lock(&tsg->event_id_list_lock); | ||
2539 | list_del_init(&event_id_data->event_id_node); | ||
2540 | mutex_unlock(&tsg->event_id_list_lock); | ||
2541 | } else { | ||
2530 | struct channel_gk20a *ch = g->fifo.channel + event_id_data->id; | 2542 | struct channel_gk20a *ch = g->fifo.channel + event_id_data->id; |
2531 | 2543 | ||
2532 | mutex_lock(&ch->event_id_list_lock); | 2544 | mutex_lock(&ch->event_id_list_lock); |
@@ -2540,7 +2552,7 @@ int gk20a_event_id_release(struct inode *inode, struct file *filp) | |||
2540 | return 0; | 2552 | return 0; |
2541 | } | 2553 | } |
2542 | 2554 | ||
2543 | static const struct file_operations gk20a_event_id_ops = { | 2555 | const struct file_operations gk20a_event_id_ops = { |
2544 | .owner = THIS_MODULE, | 2556 | .owner = THIS_MODULE, |
2545 | .poll = gk20a_event_id_poll, | 2557 | .poll = gk20a_event_id_poll, |
2546 | .release = gk20a_event_id_release, | 2558 | .release = gk20a_event_id_release, |
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h index cbe0fd59..577e3861 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h | |||
@@ -38,6 +38,8 @@ struct gk20a_fence; | |||
38 | #include "gr_gk20a.h" | 38 | #include "gr_gk20a.h" |
39 | #include "fence_gk20a.h" | 39 | #include "fence_gk20a.h" |
40 | 40 | ||
41 | extern const struct file_operations gk20a_event_id_ops; | ||
42 | |||
41 | struct notification { | 43 | struct notification { |
42 | struct { | 44 | struct { |
43 | u32 nanoseconds[2]; | 45 | u32 nanoseconds[2]; |
diff --git a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c index b41cca08..a0232a69 100644 --- a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c | |||
@@ -153,6 +153,9 @@ int gk20a_init_tsg_support(struct gk20a *g, u32 tsgid) | |||
153 | INIT_LIST_HEAD(&tsg->ch_list); | 153 | INIT_LIST_HEAD(&tsg->ch_list); |
154 | mutex_init(&tsg->ch_list_lock); | 154 | mutex_init(&tsg->ch_list_lock); |
155 | 155 | ||
156 | INIT_LIST_HEAD(&tsg->event_id_list); | ||
157 | mutex_init(&tsg->event_id_list_lock); | ||
158 | |||
156 | return 0; | 159 | return 0; |
157 | } | 160 | } |
158 | 161 | ||
@@ -184,6 +187,122 @@ static int gk20a_tsg_set_priority(struct gk20a *g, struct tsg_gk20a *tsg, | |||
184 | return 0; | 187 | return 0; |
185 | } | 188 | } |
186 | 189 | ||
190 | static int gk20a_tsg_get_event_data_from_id(struct tsg_gk20a *tsg, | ||
191 | int event_id, | ||
192 | struct gk20a_event_id_data **event_id_data) | ||
193 | { | ||
194 | struct gk20a_event_id_data *local_event_id_data; | ||
195 | bool event_found = false; | ||
196 | |||
197 | mutex_lock(&tsg->event_id_list_lock); | ||
198 | list_for_each_entry(local_event_id_data, &tsg->event_id_list, | ||
199 | event_id_node) { | ||
200 | if (local_event_id_data->event_id == event_id) { | ||
201 | event_found = true; | ||
202 | break; | ||
203 | } | ||
204 | } | ||
205 | mutex_unlock(&tsg->event_id_list_lock); | ||
206 | |||
207 | if (event_found) { | ||
208 | *event_id_data = local_event_id_data; | ||
209 | return 0; | ||
210 | } else { | ||
211 | return -1; | ||
212 | } | ||
213 | } | ||
214 | |||
215 | static int gk20a_tsg_event_id_enable(struct tsg_gk20a *tsg, | ||
216 | int event_id, | ||
217 | int *fd) | ||
218 | { | ||
219 | int err = 0; | ||
220 | int local_fd; | ||
221 | struct file *file; | ||
222 | char *name; | ||
223 | struct gk20a_event_id_data *event_id_data; | ||
224 | |||
225 | err = gk20a_tsg_get_event_data_from_id(tsg, | ||
226 | event_id, &event_id_data); | ||
227 | if (err == 0) /* We already have event enabled */ | ||
228 | return -EINVAL; | ||
229 | |||
230 | err = get_unused_fd_flags(O_RDWR); | ||
231 | if (err < 0) | ||
232 | return err; | ||
233 | local_fd = err; | ||
234 | |||
235 | name = kasprintf(GFP_KERNEL, "nvgpu-event%d-fd%d", | ||
236 | event_id, local_fd); | ||
237 | |||
238 | file = anon_inode_getfile(name, &gk20a_event_id_ops, | ||
239 | NULL, O_RDWR); | ||
240 | kfree(name); | ||
241 | if (IS_ERR(file)) { | ||
242 | err = PTR_ERR(file); | ||
243 | goto clean_up; | ||
244 | } | ||
245 | |||
246 | event_id_data = kzalloc(sizeof(*event_id_data), GFP_KERNEL); | ||
247 | if (!event_id_data) { | ||
248 | err = -ENOMEM; | ||
249 | goto clean_up_file; | ||
250 | } | ||
251 | event_id_data->g = tsg->g; | ||
252 | event_id_data->id = tsg->tsgid; | ||
253 | event_id_data->is_tsg = true; | ||
254 | event_id_data->event_id = event_id; | ||
255 | |||
256 | init_waitqueue_head(&event_id_data->event_id_wq); | ||
257 | mutex_init(&event_id_data->lock); | ||
258 | INIT_LIST_HEAD(&event_id_data->event_id_node); | ||
259 | |||
260 | mutex_lock(&tsg->event_id_list_lock); | ||
261 | list_add_tail(&event_id_data->event_id_node, &tsg->event_id_list); | ||
262 | mutex_unlock(&tsg->event_id_list_lock); | ||
263 | |||
264 | fd_install(local_fd, file); | ||
265 | file->private_data = event_id_data; | ||
266 | |||
267 | *fd = local_fd; | ||
268 | |||
269 | return 0; | ||
270 | |||
271 | clean_up_file: | ||
272 | fput(file); | ||
273 | clean_up: | ||
274 | put_unused_fd(local_fd); | ||
275 | return err; | ||
276 | } | ||
277 | |||
278 | static int gk20a_tsg_event_id_ctrl(struct gk20a *g, struct tsg_gk20a *tsg, | ||
279 | struct nvgpu_event_id_ctrl_args *args) | ||
280 | { | ||
281 | int err = 0; | ||
282 | int fd = -1; | ||
283 | |||
284 | if (args->event_id < 0 || | ||
285 | args->event_id >= NVGPU_IOCTL_CHANNEL_EVENT_ID_MAX) | ||
286 | return -EINVAL; | ||
287 | |||
288 | switch (args->cmd) { | ||
289 | case NVGPU_IOCTL_CHANNEL_EVENT_ID_CMD_ENABLE: | ||
290 | err = gk20a_tsg_event_id_enable(tsg, args->event_id, &fd); | ||
291 | if (!err) | ||
292 | args->event_fd = fd; | ||
293 | break; | ||
294 | |||
295 | default: | ||
296 | gk20a_err(dev_from_gk20a(tsg->g), | ||
297 | "unrecognized tsg event id cmd: 0x%x", | ||
298 | args->cmd); | ||
299 | err = -EINVAL; | ||
300 | break; | ||
301 | } | ||
302 | |||
303 | return err; | ||
304 | } | ||
305 | |||
187 | static void release_used_tsg(struct fifo_gk20a *f, struct tsg_gk20a *tsg) | 306 | static void release_used_tsg(struct fifo_gk20a *f, struct tsg_gk20a *tsg) |
188 | { | 307 | { |
189 | mutex_lock(&f->tsg_inuse_mutex); | 308 | mutex_lock(&f->tsg_inuse_mutex); |
@@ -372,6 +491,13 @@ long gk20a_tsg_dev_ioctl(struct file *filp, unsigned int cmd, | |||
372 | break; | 491 | break; |
373 | } | 492 | } |
374 | 493 | ||
494 | case NVGPU_IOCTL_TSG_EVENT_ID_CTRL: | ||
495 | { | ||
496 | err = gk20a_tsg_event_id_ctrl(g, tsg, | ||
497 | (struct nvgpu_event_id_ctrl_args *)buf); | ||
498 | break; | ||
499 | } | ||
500 | |||
375 | default: | 501 | default: |
376 | gk20a_err(dev_from_gk20a(g), | 502 | gk20a_err(dev_from_gk20a(g), |
377 | "unrecognized tsg gpu ioctl cmd: 0x%x", | 503 | "unrecognized tsg gpu ioctl cmd: 0x%x", |
diff --git a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.h b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.h index 7e0a75d1..ac872e30 100644 --- a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.h | |||
@@ -51,6 +51,9 @@ struct tsg_gk20a { | |||
51 | struct vm_gk20a *vm; | 51 | struct vm_gk20a *vm; |
52 | 52 | ||
53 | u32 interleave_level; | 53 | u32 interleave_level; |
54 | |||
55 | struct list_head event_id_list; | ||
56 | struct mutex event_id_list_lock; | ||
54 | }; | 57 | }; |
55 | 58 | ||
56 | int gk20a_enable_tsg(struct tsg_gk20a *tsg); | 59 | int gk20a_enable_tsg(struct tsg_gk20a *tsg); |