From 5f10073540acba056ccf905010dd400d8f32ca31 Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Mon, 21 Mar 2016 19:58:28 +0530 Subject: 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 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 --- drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 18 ++++- drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 2 + drivers/gpu/nvgpu/gk20a/tsg_gk20a.c | 126 ++++++++++++++++++++++++++++++++ drivers/gpu/nvgpu/gk20a/tsg_gk20a.h | 3 + include/uapi/linux/nvgpu.h | 8 +- 5 files changed, 152 insertions(+), 5 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) mutex_lock(&event_id_data->lock); - if (!event_id_data->is_tsg) { + if (event_id_data->is_tsg) { + struct tsg_gk20a *tsg = g->fifo.tsg + event_id_data->id; + + gk20a_dbg_info( + "found pending event_id=%d on TSG=%d\n", + event_id, tsg->tsgid); + } else { struct channel_gk20a *ch = g->fifo.channel + event_id_data->id; @@ -2526,7 +2532,13 @@ int gk20a_event_id_release(struct inode *inode, struct file *filp) struct gk20a_event_id_data *event_id_data = filp->private_data; struct gk20a *g = event_id_data->g; - if (!event_id_data->is_tsg) { + if (event_id_data->is_tsg) { + struct tsg_gk20a *tsg = g->fifo.tsg + event_id_data->id; + + mutex_lock(&tsg->event_id_list_lock); + list_del_init(&event_id_data->event_id_node); + mutex_unlock(&tsg->event_id_list_lock); + } else { struct channel_gk20a *ch = g->fifo.channel + event_id_data->id; mutex_lock(&ch->event_id_list_lock); @@ -2540,7 +2552,7 @@ int gk20a_event_id_release(struct inode *inode, struct file *filp) return 0; } -static const struct file_operations gk20a_event_id_ops = { +const struct file_operations gk20a_event_id_ops = { .owner = THIS_MODULE, .poll = gk20a_event_id_poll, .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; #include "gr_gk20a.h" #include "fence_gk20a.h" +extern const struct file_operations gk20a_event_id_ops; + struct notification { struct { 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) INIT_LIST_HEAD(&tsg->ch_list); mutex_init(&tsg->ch_list_lock); + INIT_LIST_HEAD(&tsg->event_id_list); + mutex_init(&tsg->event_id_list_lock); + return 0; } @@ -184,6 +187,122 @@ static int gk20a_tsg_set_priority(struct gk20a *g, struct tsg_gk20a *tsg, return 0; } +static int gk20a_tsg_get_event_data_from_id(struct tsg_gk20a *tsg, + int event_id, + struct gk20a_event_id_data **event_id_data) +{ + struct gk20a_event_id_data *local_event_id_data; + bool event_found = false; + + mutex_lock(&tsg->event_id_list_lock); + list_for_each_entry(local_event_id_data, &tsg->event_id_list, + event_id_node) { + if (local_event_id_data->event_id == event_id) { + event_found = true; + break; + } + } + mutex_unlock(&tsg->event_id_list_lock); + + if (event_found) { + *event_id_data = local_event_id_data; + return 0; + } else { + return -1; + } +} + +static int gk20a_tsg_event_id_enable(struct tsg_gk20a *tsg, + int event_id, + int *fd) +{ + int err = 0; + int local_fd; + struct file *file; + char *name; + struct gk20a_event_id_data *event_id_data; + + err = gk20a_tsg_get_event_data_from_id(tsg, + event_id, &event_id_data); + if (err == 0) /* We already have event enabled */ + return -EINVAL; + + err = get_unused_fd_flags(O_RDWR); + if (err < 0) + return err; + local_fd = err; + + name = kasprintf(GFP_KERNEL, "nvgpu-event%d-fd%d", + event_id, local_fd); + + file = anon_inode_getfile(name, &gk20a_event_id_ops, + NULL, O_RDWR); + kfree(name); + if (IS_ERR(file)) { + err = PTR_ERR(file); + goto clean_up; + } + + event_id_data = kzalloc(sizeof(*event_id_data), GFP_KERNEL); + if (!event_id_data) { + err = -ENOMEM; + goto clean_up_file; + } + event_id_data->g = tsg->g; + event_id_data->id = tsg->tsgid; + event_id_data->is_tsg = true; + event_id_data->event_id = event_id; + + init_waitqueue_head(&event_id_data->event_id_wq); + mutex_init(&event_id_data->lock); + INIT_LIST_HEAD(&event_id_data->event_id_node); + + mutex_lock(&tsg->event_id_list_lock); + list_add_tail(&event_id_data->event_id_node, &tsg->event_id_list); + mutex_unlock(&tsg->event_id_list_lock); + + fd_install(local_fd, file); + file->private_data = event_id_data; + + *fd = local_fd; + + return 0; + +clean_up_file: + fput(file); +clean_up: + put_unused_fd(local_fd); + return err; +} + +static int gk20a_tsg_event_id_ctrl(struct gk20a *g, struct tsg_gk20a *tsg, + struct nvgpu_event_id_ctrl_args *args) +{ + int err = 0; + int fd = -1; + + if (args->event_id < 0 || + args->event_id >= NVGPU_IOCTL_CHANNEL_EVENT_ID_MAX) + return -EINVAL; + + switch (args->cmd) { + case NVGPU_IOCTL_CHANNEL_EVENT_ID_CMD_ENABLE: + err = gk20a_tsg_event_id_enable(tsg, args->event_id, &fd); + if (!err) + args->event_fd = fd; + break; + + default: + gk20a_err(dev_from_gk20a(tsg->g), + "unrecognized tsg event id cmd: 0x%x", + args->cmd); + err = -EINVAL; + break; + } + + return err; +} + static void release_used_tsg(struct fifo_gk20a *f, struct tsg_gk20a *tsg) { mutex_lock(&f->tsg_inuse_mutex); @@ -372,6 +491,13 @@ long gk20a_tsg_dev_ioctl(struct file *filp, unsigned int cmd, break; } + case NVGPU_IOCTL_TSG_EVENT_ID_CTRL: + { + err = gk20a_tsg_event_id_ctrl(g, tsg, + (struct nvgpu_event_id_ctrl_args *)buf); + break; + } + default: gk20a_err(dev_from_gk20a(g), "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 { struct vm_gk20a *vm; u32 interleave_level; + + struct list_head event_id_list; + struct mutex event_id_list_lock; }; int gk20a_enable_tsg(struct tsg_gk20a *tsg); diff --git a/include/uapi/linux/nvgpu.h b/include/uapi/linux/nvgpu.h index 6fed9e9f..45d1c217 100644 --- a/include/uapi/linux/nvgpu.h +++ b/include/uapi/linux/nvgpu.h @@ -448,11 +448,15 @@ struct nvgpu_gpu_get_cpu_time_correlation_info_args { _IO(NVGPU_TSG_IOCTL_MAGIC, 5) #define NVGPU_IOCTL_TSG_SET_PRIORITY \ _IOW(NVGPU_TSG_IOCTL_MAGIC, 6, struct nvgpu_set_priority_args) +#define NVGPU_IOCTL_TSG_EVENT_ID_CTRL \ + _IOWR(NVGPU_TSG_IOCTL_MAGIC, 7, struct nvgpu_event_id_ctrl_args) #define NVGPU_TSG_IOCTL_MAX_ARG_SIZE \ - sizeof(struct nvgpu_set_priority_args) + sizeof(struct nvgpu_event_id_ctrl_args) #define NVGPU_TSG_IOCTL_LAST \ - _IOC_NR(NVGPU_IOCTL_TSG_SET_PRIORITY) + _IOC_NR(NVGPU_IOCTL_TSG_EVENT_ID_CTRL) + + /* * /dev/nvhost-dbg-gpu device * -- cgit v1.2.2