summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c223
1 files changed, 137 insertions, 86 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 */ 2496unsigned int gk20a_event_id_poll(struct file *filep, poll_table *wait)
2499
2500static 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
2512static void gk20a_channel_events_disable(struct channel_gk20a_poll_events *ev) 2524int 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
2524static void gk20a_channel_events_clear(struct channel_gk20a_poll_events *ev) 2543static 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); 2549static 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
2537static int gk20a_channel_events_ctrl(struct channel_gk20a *ch, 2574static 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
2569void 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
2586void gk20a_channel_post_event(struct channel_gk20a *ch) 2630clean_up_file:
2587{ 2631 fput(file);
2588 gk20a_channel_event(ch); 2632clean_up:
2589 wake_up_interruptible_all(&ch->semaphore_wq); 2633 put_unused_fd(local_fd);
2634 return err;
2590} 2635}
2591 2636
2592unsigned int gk20a_channel_poll(struct file *filep, poll_table *wait) 2637static 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
2617int gk20a_channel_set_priority(struct channel_gk20a *ch, u32 priority) 2668int 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: