diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index c83da8b4..643adca5 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |||
@@ -486,6 +486,95 @@ static int gk20a_channel_cycle_stats(struct channel_gk20a *ch, | |||
486 | return -EINVAL; | 486 | return -EINVAL; |
487 | } | 487 | } |
488 | } | 488 | } |
489 | |||
490 | |||
491 | static int gk20a_flush_cycle_stats_snapshot(struct channel_gk20a *ch) | ||
492 | { | ||
493 | int ret; | ||
494 | |||
495 | mutex_lock(&ch->cs_client_mutex); | ||
496 | if (ch->cs_client) | ||
497 | ret = gr_gk20a_css_flush(ch->g, ch->cs_client); | ||
498 | else | ||
499 | ret = -EBADF; | ||
500 | mutex_unlock(&ch->cs_client_mutex); | ||
501 | |||
502 | return ret; | ||
503 | } | ||
504 | |||
505 | static int gk20a_attach_cycle_stats_snapshot(struct channel_gk20a *ch, | ||
506 | u32 dmabuf_fd, | ||
507 | u32 perfmon_id_count, | ||
508 | u32 *perfmon_id_start) | ||
509 | { | ||
510 | int ret; | ||
511 | |||
512 | mutex_lock(&ch->cs_client_mutex); | ||
513 | if (ch->cs_client) { | ||
514 | ret = -EEXIST; | ||
515 | } else { | ||
516 | ret = gr_gk20a_css_attach(ch->g, | ||
517 | dmabuf_fd, | ||
518 | perfmon_id_count, | ||
519 | perfmon_id_start, | ||
520 | &ch->cs_client); | ||
521 | } | ||
522 | mutex_unlock(&ch->cs_client_mutex); | ||
523 | |||
524 | return ret; | ||
525 | } | ||
526 | |||
527 | static int gk20a_free_cycle_stats_snapshot(struct channel_gk20a *ch) | ||
528 | { | ||
529 | int ret; | ||
530 | |||
531 | mutex_lock(&ch->cs_client_mutex); | ||
532 | if (ch->cs_client) { | ||
533 | ret = gr_gk20a_css_detach(ch->g, ch->cs_client); | ||
534 | ch->cs_client = NULL; | ||
535 | } else { | ||
536 | ret = 0; | ||
537 | } | ||
538 | mutex_unlock(&ch->cs_client_mutex); | ||
539 | |||
540 | return ret; | ||
541 | } | ||
542 | |||
543 | static int gk20a_channel_cycle_stats_snapshot(struct channel_gk20a *ch, | ||
544 | struct nvgpu_cycle_stats_snapshot_args *args) | ||
545 | { | ||
546 | int ret; | ||
547 | |||
548 | if (!args->dmabuf_fd) | ||
549 | return -EINVAL; | ||
550 | |||
551 | /* handle the command (most frequent cases first) */ | ||
552 | switch (args->cmd) { | ||
553 | case NVGPU_IOCTL_CHANNEL_CYCLE_STATS_SNAPSHOT_CMD_FLUSH: | ||
554 | ret = gk20a_flush_cycle_stats_snapshot(ch); | ||
555 | args->extra = 0; | ||
556 | break; | ||
557 | |||
558 | case NVGPU_IOCTL_CHANNEL_CYCLE_STATS_SNAPSHOT_CMD_ATTACH: | ||
559 | ret = gk20a_attach_cycle_stats_snapshot(ch, | ||
560 | args->dmabuf_fd, | ||
561 | args->extra, | ||
562 | &args->extra); | ||
563 | break; | ||
564 | |||
565 | case NVGPU_IOCTL_CHANNEL_CYCLE_STATS_SNAPSHOT_CMD_DETACH: | ||
566 | ret = gk20a_free_cycle_stats_snapshot(ch); | ||
567 | args->extra = 0; | ||
568 | break; | ||
569 | |||
570 | default: | ||
571 | pr_err("cyclestats: unknown command %u\n", args->cmd); | ||
572 | ret = -EINVAL; | ||
573 | break; | ||
574 | } | ||
575 | |||
576 | return ret; | ||
577 | } | ||
489 | #endif | 578 | #endif |
490 | 579 | ||
491 | static int gk20a_init_error_notifier(struct channel_gk20a *ch, | 580 | static int gk20a_init_error_notifier(struct channel_gk20a *ch, |
@@ -602,6 +691,7 @@ void gk20a_free_channel(struct channel_gk20a *ch, bool finish) | |||
602 | 691 | ||
603 | #if defined(CONFIG_GK20A_CYCLE_STATS) | 692 | #if defined(CONFIG_GK20A_CYCLE_STATS) |
604 | gk20a_free_cycle_stats_buffer(ch); | 693 | gk20a_free_cycle_stats_buffer(ch); |
694 | gk20a_free_cycle_stats_snapshot(ch); | ||
605 | #endif | 695 | #endif |
606 | 696 | ||
607 | channel_gk20a_free_priv_cmdbuf(ch); | 697 | channel_gk20a_free_priv_cmdbuf(ch); |
@@ -1639,6 +1729,7 @@ int gk20a_init_channel_support(struct gk20a *g, u32 chid) | |||
1639 | INIT_LIST_HEAD(&c->jobs); | 1729 | INIT_LIST_HEAD(&c->jobs); |
1640 | #if defined(CONFIG_GK20A_CYCLE_STATS) | 1730 | #if defined(CONFIG_GK20A_CYCLE_STATS) |
1641 | mutex_init(&c->cyclestate.cyclestate_buffer_mutex); | 1731 | mutex_init(&c->cyclestate.cyclestate_buffer_mutex); |
1732 | mutex_init(&c->cs_client_mutex); | ||
1642 | #endif | 1733 | #endif |
1643 | INIT_LIST_HEAD(&c->dbg_s_list); | 1734 | INIT_LIST_HEAD(&c->dbg_s_list); |
1644 | mutex_init(&c->dbg_s_lock); | 1735 | mutex_init(&c->dbg_s_lock); |
@@ -2335,6 +2426,20 @@ long gk20a_channel_ioctl(struct file *filp, | |||
2335 | err = gk20a_channel_events_ctrl(ch, | 2426 | err = gk20a_channel_events_ctrl(ch, |
2336 | (struct nvgpu_channel_events_ctrl_args *)buf); | 2427 | (struct nvgpu_channel_events_ctrl_args *)buf); |
2337 | break; | 2428 | break; |
2429 | #ifdef CONFIG_GK20A_CYCLE_STATS | ||
2430 | case NVGPU_IOCTL_CHANNEL_CYCLE_STATS_SNAPSHOT: | ||
2431 | err = gk20a_busy(dev); | ||
2432 | if (err) { | ||
2433 | dev_err(&dev->dev, | ||
2434 | "%s: failed to host gk20a for ioctl cmd: 0x%x", | ||
2435 | __func__, cmd); | ||
2436 | break; | ||
2437 | } | ||
2438 | err = gk20a_channel_cycle_stats_snapshot(ch, | ||
2439 | (struct nvgpu_cycle_stats_snapshot_args *)buf); | ||
2440 | gk20a_idle(dev); | ||
2441 | break; | ||
2442 | #endif | ||
2338 | default: | 2443 | default: |
2339 | dev_dbg(&dev->dev, "unrecognized ioctl cmd: 0x%x", cmd); | 2444 | dev_dbg(&dev->dev, "unrecognized ioctl cmd: 0x%x", cmd); |
2340 | err = -ENOTTY; | 2445 | err = -ENOTTY; |