diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 223 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 21 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gr_gk20a.c | 2 |
4 files changed, 150 insertions, 97 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 20976992..be9c7cd4 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |||
@@ -1167,10 +1167,6 @@ struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g) | |||
1167 | init_waitqueue_head(&ch->semaphore_wq); | 1167 | init_waitqueue_head(&ch->semaphore_wq); |
1168 | init_waitqueue_head(&ch->submit_wq); | 1168 | init_waitqueue_head(&ch->submit_wq); |
1169 | 1169 | ||
1170 | mutex_init(&ch->poll_events.lock); | ||
1171 | ch->poll_events.events_enabled = false; | ||
1172 | ch->poll_events.num_pending_events = 0; | ||
1173 | |||
1174 | ch->update_fn = NULL; | 1170 | ch->update_fn = NULL; |
1175 | ch->update_fn_data = NULL; | 1171 | ch->update_fn_data = NULL; |
1176 | spin_lock_init(&ch->update_fn_lock); | 1172 | spin_lock_init(&ch->update_fn_lock); |
@@ -2322,6 +2318,8 @@ int gk20a_init_channel_support(struct gk20a *g, u32 chid) | |||
2322 | mutex_init(&c->cs_client_mutex); | 2318 | mutex_init(&c->cs_client_mutex); |
2323 | #endif | 2319 | #endif |
2324 | INIT_LIST_HEAD(&c->dbg_s_list); | 2320 | INIT_LIST_HEAD(&c->dbg_s_list); |
2321 | INIT_LIST_HEAD(&c->event_id_list); | ||
2322 | mutex_init(&c->event_id_list_lock); | ||
2325 | mutex_init(&c->dbg_s_lock); | 2323 | mutex_init(&c->dbg_s_lock); |
2326 | list_add(&c->free_chs, &g->fifo.free_chs); | 2324 | list_add(&c->free_chs, &g->fifo.free_chs); |
2327 | 2325 | ||
@@ -2495,123 +2493,176 @@ notif_clean_up: | |||
2495 | return ret; | 2493 | return ret; |
2496 | } | 2494 | } |
2497 | 2495 | ||
2498 | /* poll events for semaphores */ | 2496 | unsigned int gk20a_event_id_poll(struct file *filep, poll_table *wait) |
2499 | |||
2500 | static void gk20a_channel_events_enable(struct channel_gk20a_poll_events *ev) | ||
2501 | { | 2497 | { |
2502 | gk20a_dbg_fn(""); | 2498 | unsigned int mask = 0; |
2499 | struct gk20a_event_id_data *event_id_data = filep->private_data; | ||
2500 | struct gk20a *g = event_id_data->g; | ||
2501 | u32 event_id = event_id_data->event_id; | ||
2502 | |||
2503 | gk20a_dbg(gpu_dbg_fn | gpu_dbg_info, ""); | ||
2504 | |||
2505 | poll_wait(filep, &event_id_data->event_id_wq, wait); | ||
2506 | |||
2507 | mutex_lock(&event_id_data->lock); | ||
2503 | 2508 | ||
2504 | mutex_lock(&ev->lock); | 2509 | if (!event_id_data->is_tsg) { |
2510 | struct channel_gk20a *ch = g->fifo.channel | ||
2511 | + event_id_data->id; | ||
2512 | |||
2513 | gk20a_dbg_info( | ||
2514 | "found pending event_id=%d on chid=%d\n", | ||
2515 | event_id, ch->hw_chid); | ||
2516 | } | ||
2517 | mask = (POLLPRI | POLLIN); | ||
2505 | 2518 | ||
2506 | ev->events_enabled = true; | 2519 | mutex_unlock(&event_id_data->lock); |
2507 | ev->num_pending_events = 0; | ||
2508 | 2520 | ||
2509 | mutex_unlock(&ev->lock); | 2521 | return mask; |
2510 | } | 2522 | } |
2511 | 2523 | ||
2512 | static void gk20a_channel_events_disable(struct channel_gk20a_poll_events *ev) | 2524 | int gk20a_event_id_release(struct inode *inode, struct file *filp) |
2513 | { | 2525 | { |
2514 | gk20a_dbg_fn(""); | 2526 | struct gk20a_event_id_data *event_id_data = filp->private_data; |
2527 | struct gk20a *g = event_id_data->g; | ||
2515 | 2528 | ||
2516 | mutex_lock(&ev->lock); | 2529 | if (!event_id_data->is_tsg) { |
2530 | struct channel_gk20a *ch = g->fifo.channel + event_id_data->id; | ||
2517 | 2531 | ||
2518 | ev->events_enabled = false; | 2532 | mutex_lock(&ch->event_id_list_lock); |
2519 | ev->num_pending_events = 0; | 2533 | list_del_init(&event_id_data->event_id_node); |
2534 | mutex_unlock(&ch->event_id_list_lock); | ||
2535 | } | ||
2536 | |||
2537 | kfree(event_id_data); | ||
2538 | filp->private_data = NULL; | ||
2520 | 2539 | ||
2521 | mutex_unlock(&ev->lock); | 2540 | return 0; |
2522 | } | 2541 | } |
2523 | 2542 | ||
2524 | static void gk20a_channel_events_clear(struct channel_gk20a_poll_events *ev) | 2543 | static const struct file_operations gk20a_event_id_ops = { |
2525 | { | 2544 | .owner = THIS_MODULE, |
2526 | gk20a_dbg_fn(""); | 2545 | .poll = gk20a_event_id_poll, |
2546 | .release = gk20a_event_id_release, | ||
2547 | }; | ||
2527 | 2548 | ||
2528 | mutex_lock(&ev->lock); | 2549 | static int gk20a_channel_get_event_data_from_id(struct channel_gk20a *ch, |
2550 | int event_id, | ||
2551 | struct gk20a_event_id_data **event_id_data) | ||
2552 | { | ||
2553 | struct gk20a_event_id_data *local_event_id_data; | ||
2554 | bool event_found = false; | ||
2529 | 2555 | ||
2530 | if (ev->events_enabled && | 2556 | mutex_lock(&ch->event_id_list_lock); |
2531 | ev->num_pending_events > 0) | 2557 | list_for_each_entry(local_event_id_data, &ch->event_id_list, |
2532 | ev->num_pending_events--; | 2558 | event_id_node) { |
2559 | if (local_event_id_data->event_id == event_id) { | ||
2560 | event_found = true; | ||
2561 | break; | ||
2562 | } | ||
2563 | } | ||
2564 | mutex_unlock(&ch->event_id_list_lock); | ||
2533 | 2565 | ||
2534 | mutex_unlock(&ev->lock); | 2566 | if (event_found) { |
2567 | *event_id_data = local_event_id_data; | ||
2568 | return 0; | ||
2569 | } else { | ||
2570 | return -1; | ||
2571 | } | ||
2535 | } | 2572 | } |
2536 | 2573 | ||
2537 | static int gk20a_channel_events_ctrl(struct channel_gk20a *ch, | 2574 | static int gk20a_channel_event_id_enable(struct channel_gk20a *ch, |
2538 | struct nvgpu_channel_events_ctrl_args *args) | 2575 | int event_id, |
2576 | int *fd) | ||
2539 | { | 2577 | { |
2540 | int ret = 0; | 2578 | int err = 0; |
2579 | int local_fd; | ||
2580 | struct file *file; | ||
2581 | char *name; | ||
2582 | struct gk20a_event_id_data *event_id_data; | ||
2541 | 2583 | ||
2542 | gk20a_dbg(gpu_dbg_fn | gpu_dbg_info, | 2584 | err = gk20a_channel_get_event_data_from_id(ch, |
2543 | "channel events ctrl cmd %d", args->cmd); | 2585 | event_id, &event_id_data); |
2586 | if (err == 0) /* We already have event enabled */ | ||
2587 | return -EINVAL; | ||
2544 | 2588 | ||
2545 | switch (args->cmd) { | 2589 | err = get_unused_fd_flags(O_RDWR); |
2546 | case NVGPU_IOCTL_CHANNEL_EVENTS_CTRL_CMD_ENABLE: | 2590 | if (err < 0) |
2547 | gk20a_channel_events_enable(&ch->poll_events); | 2591 | return err; |
2548 | break; | 2592 | local_fd = err; |
2549 | 2593 | ||
2550 | case NVGPU_IOCTL_CHANNEL_EVENTS_CTRL_CMD_DISABLE: | 2594 | name = kasprintf(GFP_KERNEL, "nvgpu-event%d-fd%d", |
2551 | gk20a_channel_events_disable(&ch->poll_events); | 2595 | event_id, local_fd); |
2552 | break; | ||
2553 | 2596 | ||
2554 | case NVGPU_IOCTL_CHANNEL_EVENTS_CTRL_CMD_CLEAR: | 2597 | file = anon_inode_getfile(name, &gk20a_event_id_ops, |
2555 | gk20a_channel_events_clear(&ch->poll_events); | 2598 | NULL, O_RDWR); |
2556 | break; | 2599 | kfree(name); |
2600 | if (IS_ERR(file)) { | ||
2601 | err = PTR_ERR(file); | ||
2602 | goto clean_up; | ||
2603 | } | ||
2557 | 2604 | ||
2558 | default: | 2605 | event_id_data = kzalloc(sizeof(*event_id_data), GFP_KERNEL); |
2559 | gk20a_err(dev_from_gk20a(ch->g), | 2606 | if (!event_id_data) { |
2560 | "unrecognized channel events ctrl cmd: 0x%x", | 2607 | err = -ENOMEM; |
2561 | args->cmd); | 2608 | goto clean_up_file; |
2562 | ret = -EINVAL; | ||
2563 | break; | ||
2564 | } | 2609 | } |
2610 | event_id_data->g = ch->g; | ||
2611 | event_id_data->id = ch->hw_chid; | ||
2612 | event_id_data->is_tsg = false; | ||
2613 | event_id_data->event_id = event_id; | ||
2565 | 2614 | ||
2566 | return ret; | 2615 | init_waitqueue_head(&event_id_data->event_id_wq); |
2567 | } | 2616 | mutex_init(&event_id_data->lock); |
2617 | INIT_LIST_HEAD(&event_id_data->event_id_node); | ||
2568 | 2618 | ||
2569 | void gk20a_channel_event(struct channel_gk20a *ch) | 2619 | mutex_lock(&ch->event_id_list_lock); |
2570 | { | 2620 | list_add_tail(&event_id_data->event_id_node, &ch->event_id_list); |
2571 | mutex_lock(&ch->poll_events.lock); | 2621 | mutex_unlock(&ch->event_id_list_lock); |
2572 | 2622 | ||
2573 | if (ch->poll_events.events_enabled) { | 2623 | fd_install(local_fd, file); |
2574 | gk20a_dbg_info("posting event on channel id %d", | 2624 | file->private_data = event_id_data; |
2575 | ch->hw_chid); | ||
2576 | gk20a_dbg_info("%d channel events pending", | ||
2577 | ch->poll_events.num_pending_events); | ||
2578 | 2625 | ||
2579 | ch->poll_events.num_pending_events++; | 2626 | *fd = local_fd; |
2580 | /* not waking up here, caller does that */ | ||
2581 | } | ||
2582 | 2627 | ||
2583 | mutex_unlock(&ch->poll_events.lock); | 2628 | return 0; |
2584 | } | ||
2585 | 2629 | ||
2586 | void gk20a_channel_post_event(struct channel_gk20a *ch) | 2630 | clean_up_file: |
2587 | { | 2631 | fput(file); |
2588 | gk20a_channel_event(ch); | 2632 | clean_up: |
2589 | wake_up_interruptible_all(&ch->semaphore_wq); | 2633 | put_unused_fd(local_fd); |
2634 | return err; | ||
2590 | } | 2635 | } |
2591 | 2636 | ||
2592 | unsigned int gk20a_channel_poll(struct file *filep, poll_table *wait) | 2637 | static int gk20a_channel_event_id_ctrl(struct channel_gk20a *ch, |
2638 | struct nvgpu_event_id_ctrl_args *args) | ||
2593 | { | 2639 | { |
2594 | unsigned int mask = 0; | 2640 | int err = 0; |
2595 | struct channel_gk20a *ch = filep->private_data; | 2641 | int fd = -1; |
2596 | 2642 | ||
2597 | gk20a_dbg(gpu_dbg_fn | gpu_dbg_info, ""); | 2643 | if (args->event_id < 0 || |
2644 | args->event_id >= NVGPU_IOCTL_CHANNEL_EVENT_ID_MAX) | ||
2645 | return -EINVAL; | ||
2598 | 2646 | ||
2599 | poll_wait(filep, &ch->semaphore_wq, wait); | 2647 | if (gk20a_is_channel_marked_as_tsg(ch)) |
2648 | return -EINVAL; | ||
2600 | 2649 | ||
2601 | mutex_lock(&ch->poll_events.lock); | 2650 | switch (args->cmd) { |
2651 | case NVGPU_IOCTL_CHANNEL_EVENT_ID_CMD_ENABLE: | ||
2652 | err = gk20a_channel_event_id_enable(ch, args->event_id, &fd); | ||
2653 | if (!err) | ||
2654 | args->event_fd = fd; | ||
2655 | break; | ||
2602 | 2656 | ||
2603 | if (ch->poll_events.events_enabled && | 2657 | default: |
2604 | ch->poll_events.num_pending_events > 0) { | 2658 | gk20a_err(dev_from_gk20a(ch->g), |
2605 | gk20a_dbg_info("found pending event on channel id %d", | 2659 | "unrecognized channel event id cmd: 0x%x", |
2606 | ch->hw_chid); | 2660 | args->cmd); |
2607 | gk20a_dbg_info("%d channel events pending", | 2661 | err = -EINVAL; |
2608 | ch->poll_events.num_pending_events); | 2662 | break; |
2609 | mask = (POLLPRI | POLLIN); | ||
2610 | } | 2663 | } |
2611 | 2664 | ||
2612 | mutex_unlock(&ch->poll_events.lock); | 2665 | return err; |
2613 | |||
2614 | return mask; | ||
2615 | } | 2666 | } |
2616 | 2667 | ||
2617 | int gk20a_channel_set_priority(struct channel_gk20a *ch, u32 priority) | 2668 | int gk20a_channel_set_priority(struct channel_gk20a *ch, u32 priority) |
@@ -2756,7 +2807,7 @@ void gk20a_channel_semaphore_wakeup(struct gk20a *g) | |||
2756 | for (chid = 0; chid < f->num_channels; chid++) { | 2807 | for (chid = 0; chid < f->num_channels; chid++) { |
2757 | struct channel_gk20a *c = g->fifo.channel+chid; | 2808 | struct channel_gk20a *c = g->fifo.channel+chid; |
2758 | if (gk20a_channel_get(c)) { | 2809 | if (gk20a_channel_get(c)) { |
2759 | gk20a_channel_post_event(c); | 2810 | wake_up_interruptible_all(&c->semaphore_wq); |
2760 | gk20a_channel_update(c, 0); | 2811 | gk20a_channel_update(c, 0); |
2761 | gk20a_channel_put(c); | 2812 | gk20a_channel_put(c); |
2762 | } | 2813 | } |
@@ -3040,9 +3091,9 @@ long gk20a_channel_ioctl(struct file *filp, | |||
3040 | err = gk20a_fifo_force_reset_ch(ch, true); | 3091 | err = gk20a_fifo_force_reset_ch(ch, true); |
3041 | gk20a_idle(dev); | 3092 | gk20a_idle(dev); |
3042 | break; | 3093 | break; |
3043 | case NVGPU_IOCTL_CHANNEL_EVENTS_CTRL: | 3094 | case NVGPU_IOCTL_CHANNEL_EVENT_ID_CTRL: |
3044 | err = gk20a_channel_events_ctrl(ch, | 3095 | err = gk20a_channel_event_id_ctrl(ch, |
3045 | (struct nvgpu_channel_events_ctrl_args *)buf); | 3096 | (struct nvgpu_event_id_ctrl_args *)buf); |
3046 | break; | 3097 | break; |
3047 | #ifdef CONFIG_GK20A_CYCLE_STATS | 3098 | #ifdef CONFIG_GK20A_CYCLE_STATS |
3048 | case NVGPU_IOCTL_CHANNEL_CYCLE_STATS_SNAPSHOT: | 3099 | case NVGPU_IOCTL_CHANNEL_CYCLE_STATS_SNAPSHOT: |
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h index e3fbba3e..cbe0fd59 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h | |||
@@ -74,10 +74,16 @@ struct channel_gk20a_timeout { | |||
74 | struct channel_gk20a_job *job; | 74 | struct channel_gk20a_job *job; |
75 | }; | 75 | }; |
76 | 76 | ||
77 | struct channel_gk20a_poll_events { | 77 | struct gk20a_event_id_data { |
78 | struct gk20a *g; | ||
79 | |||
80 | int id; /* ch or tsg */ | ||
81 | bool is_tsg; | ||
82 | u32 event_id; | ||
83 | |||
84 | wait_queue_head_t event_id_wq; | ||
78 | struct mutex lock; | 85 | struct mutex lock; |
79 | bool events_enabled; | 86 | struct list_head event_id_node; |
80 | int num_pending_events; | ||
81 | }; | 87 | }; |
82 | 88 | ||
83 | struct channel_gk20a_clean_up { | 89 | struct channel_gk20a_clean_up { |
@@ -163,6 +169,9 @@ struct channel_gk20a { | |||
163 | struct mutex dbg_s_lock; | 169 | struct mutex dbg_s_lock; |
164 | struct list_head dbg_s_list; | 170 | struct list_head dbg_s_list; |
165 | 171 | ||
172 | struct list_head event_id_list; | ||
173 | struct mutex event_id_list_lock; | ||
174 | |||
166 | bool has_timedout; | 175 | bool has_timedout; |
167 | u32 timeout_ms_max; | 176 | u32 timeout_ms_max; |
168 | bool timeout_debug_dump; | 177 | bool timeout_debug_dump; |
@@ -178,9 +187,6 @@ struct channel_gk20a { | |||
178 | u64 virt_ctx; | 187 | u64 virt_ctx; |
179 | #endif | 188 | #endif |
180 | 189 | ||
181 | /* event support */ | ||
182 | struct channel_gk20a_poll_events poll_events; | ||
183 | |||
184 | /* signal channel owner via a callback, if set, in gk20a_channel_update | 190 | /* signal channel owner via a callback, if set, in gk20a_channel_update |
185 | * via schedule_work */ | 191 | * via schedule_work */ |
186 | void (*update_fn)(struct channel_gk20a *, void *); | 192 | void (*update_fn)(struct channel_gk20a *, void *); |
@@ -227,9 +233,6 @@ long gk20a_channel_ioctl(struct file *filp, | |||
227 | int gk20a_channel_release(struct inode *inode, struct file *filp); | 233 | int gk20a_channel_release(struct inode *inode, struct file *filp); |
228 | struct channel_gk20a *gk20a_get_channel_from_file(int fd); | 234 | struct channel_gk20a *gk20a_get_channel_from_file(int fd); |
229 | void gk20a_channel_update(struct channel_gk20a *c, int nr_completed); | 235 | void gk20a_channel_update(struct channel_gk20a *c, int nr_completed); |
230 | unsigned int gk20a_channel_poll(struct file *filep, poll_table *wait); | ||
231 | void gk20a_channel_event(struct channel_gk20a *ch); | ||
232 | void gk20a_channel_post_event(struct channel_gk20a *ch); | ||
233 | 236 | ||
234 | void gk20a_init_channel(struct gpu_ops *gops); | 237 | void gk20a_init_channel(struct gpu_ops *gops); |
235 | 238 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index fb0a6aa3..2aad3365 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -108,7 +108,6 @@ static const struct file_operations gk20a_channel_ops = { | |||
108 | .compat_ioctl = gk20a_channel_ioctl, | 108 | .compat_ioctl = gk20a_channel_ioctl, |
109 | #endif | 109 | #endif |
110 | .unlocked_ioctl = gk20a_channel_ioctl, | 110 | .unlocked_ioctl = gk20a_channel_ioctl, |
111 | .poll = gk20a_channel_poll, | ||
112 | }; | 111 | }; |
113 | 112 | ||
114 | static const struct file_operations gk20a_ctrl_ops = { | 113 | static const struct file_operations gk20a_ctrl_ops = { |
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c index a10650be..56d1d505 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c | |||
@@ -4983,7 +4983,7 @@ static int gk20a_gr_handle_semaphore_pending(struct gk20a *g, | |||
4983 | struct fifo_gk20a *f = &g->fifo; | 4983 | struct fifo_gk20a *f = &g->fifo; |
4984 | struct channel_gk20a *ch = &f->channel[isr_data->chid]; | 4984 | struct channel_gk20a *ch = &f->channel[isr_data->chid]; |
4985 | 4985 | ||
4986 | gk20a_channel_post_event(ch); | 4986 | wake_up_interruptible_all(&ch->semaphore_wq); |
4987 | 4987 | ||
4988 | return 0; | 4988 | return 0; |
4989 | } | 4989 | } |