diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c | 141 |
1 files changed, 88 insertions, 53 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c b/drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c index 11f1169b..ba85e3a3 100644 --- a/drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c | |||
@@ -59,6 +59,8 @@ struct gk20a_fecs_trace { | |||
59 | struct nvgpu_mutex poll_lock; | 59 | struct nvgpu_mutex poll_lock; |
60 | struct nvgpu_thread poll_task; | 60 | struct nvgpu_thread poll_task; |
61 | bool init; | 61 | bool init; |
62 | struct nvgpu_mutex enable_lock; | ||
63 | u32 enable_count; | ||
62 | }; | 64 | }; |
63 | 65 | ||
64 | #ifdef CONFIG_GK20A_CTXSW_TRACE | 66 | #ifdef CONFIG_GK20A_CTXSW_TRACE |
@@ -438,15 +440,23 @@ int gk20a_fecs_trace_init(struct gk20a *g) | |||
438 | if (err) | 440 | if (err) |
439 | goto clean_poll_lock; | 441 | goto clean_poll_lock; |
440 | 442 | ||
443 | err = nvgpu_mutex_init(&trace->enable_lock); | ||
444 | if (err) | ||
445 | goto clean_hash_lock; | ||
446 | |||
441 | BUG_ON(!is_power_of_2(GK20A_FECS_TRACE_NUM_RECORDS)); | 447 | BUG_ON(!is_power_of_2(GK20A_FECS_TRACE_NUM_RECORDS)); |
442 | hash_init(trace->pid_hash_table); | 448 | hash_init(trace->pid_hash_table); |
443 | 449 | ||
444 | __nvgpu_set_enabled(g, NVGPU_SUPPORT_FECS_CTXSW_TRACE, true); | 450 | __nvgpu_set_enabled(g, NVGPU_SUPPORT_FECS_CTXSW_TRACE, true); |
445 | 451 | ||
452 | trace->enable_count = 0; | ||
446 | trace->init = true; | 453 | trace->init = true; |
447 | 454 | ||
448 | return 0; | 455 | return 0; |
449 | 456 | ||
457 | clean_hash_lock: | ||
458 | nvgpu_mutex_destroy(&trace->hash_lock); | ||
459 | |||
450 | clean_poll_lock: | 460 | clean_poll_lock: |
451 | nvgpu_mutex_destroy(&trace->poll_lock); | 461 | nvgpu_mutex_destroy(&trace->poll_lock); |
452 | clean: | 462 | clean: |
@@ -579,11 +589,18 @@ int gk20a_fecs_trace_deinit(struct gk20a *g) | |||
579 | if (!trace->init) | 589 | if (!trace->init) |
580 | return 0; | 590 | return 0; |
581 | 591 | ||
582 | nvgpu_thread_stop(&trace->poll_task); | 592 | /* |
593 | * Check if tracer was enabled before attempting to stop the | ||
594 | * tracer thread. | ||
595 | */ | ||
596 | if (trace->enable_count > 0) { | ||
597 | nvgpu_thread_stop(&trace->poll_task); | ||
598 | } | ||
583 | gk20a_fecs_trace_free_hash_table(g); | 599 | gk20a_fecs_trace_free_hash_table(g); |
584 | 600 | ||
585 | nvgpu_mutex_destroy(&g->fecs_trace->hash_lock); | 601 | nvgpu_mutex_destroy(&g->fecs_trace->hash_lock); |
586 | nvgpu_mutex_destroy(&g->fecs_trace->poll_lock); | 602 | nvgpu_mutex_destroy(&g->fecs_trace->poll_lock); |
603 | nvgpu_mutex_destroy(&g->fecs_trace->enable_lock); | ||
587 | 604 | ||
588 | nvgpu_kfree(g, g->fecs_trace); | 605 | nvgpu_kfree(g, g->fecs_trace); |
589 | g->fecs_trace = NULL; | 606 | g->fecs_trace = NULL; |
@@ -613,46 +630,51 @@ int gk20a_fecs_trace_enable(struct gk20a *g) | |||
613 | if (!trace) | 630 | if (!trace) |
614 | return -EINVAL; | 631 | return -EINVAL; |
615 | 632 | ||
616 | if (nvgpu_thread_is_running(&trace->poll_task)) | 633 | nvgpu_mutex_acquire(&trace->enable_lock); |
617 | return 0; | 634 | trace->enable_count++; |
618 | 635 | ||
619 | /* drop data in hw buffer */ | 636 | if (trace->enable_count == 1U) { |
620 | if (g->ops.fecs_trace.flush) | 637 | /* drop data in hw buffer */ |
621 | g->ops.fecs_trace.flush(g); | 638 | if (g->ops.fecs_trace.flush) |
622 | write = gk20a_fecs_trace_get_write_index(g); | 639 | g->ops.fecs_trace.flush(g); |
623 | 640 | ||
624 | if (nvgpu_is_enabled(g, NVGPU_FECS_TRACE_FEATURE_CONTROL)) { | 641 | write = gk20a_fecs_trace_get_write_index(g); |
625 | /* | ||
626 | * For enabling FECS trace support, MAILBOX1's MSB | ||
627 | * (Bit 31:31) should be set to 1. Bits 30:0 represents | ||
628 | * actual pointer value. | ||
629 | */ | ||
630 | write = write | | ||
631 | (BIT32(NVGPU_FECS_TRACE_FEATURE_CONTROL_BIT)); | ||
632 | } | ||
633 | gk20a_fecs_trace_set_read_index(g, write); | ||
634 | 642 | ||
635 | /* | 643 | if (nvgpu_is_enabled(g, NVGPU_FECS_TRACE_FEATURE_CONTROL)) { |
636 | * FECS ucode does a priv holdoff around the assertion of | 644 | /* |
637 | * context reset. So, pri transactions (e.g. mailbox1 register | 645 | * For enabling FECS trace support, MAILBOX1's MSB |
638 | * write) might fail due to this. Hence, do write with ack | 646 | * (Bit 31:31) should be set to 1. Bits 30:0 represents |
639 | * i.e. write and read it back to make sure write happened for | 647 | * actual pointer value. |
640 | * mailbox1. | 648 | */ |
641 | */ | 649 | write = write | |
642 | while (gk20a_fecs_trace_get_read_index(g) != write) { | 650 | (BIT32(NVGPU_FECS_TRACE_FEATURE_CONTROL_BIT)); |
643 | nvgpu_log(g, gpu_dbg_ctxsw, "mailbox1 update failed"); | 651 | } |
644 | gk20a_fecs_trace_set_read_index(g, write); | 652 | gk20a_fecs_trace_set_read_index(g, write); |
645 | } | ||
646 | 653 | ||
647 | err = nvgpu_thread_create(&trace->poll_task, g, | 654 | /* |
648 | gk20a_fecs_trace_periodic_polling, __func__); | 655 | * FECS ucode does a priv holdoff around the assertion of |
649 | if (err) { | 656 | * context reset. So, pri transactions (e.g. mailbox1 register |
650 | nvgpu_warn(g, | 657 | * write) might fail due to this. Hence, do write with ack |
658 | * i.e. write and read it back to make sure write happened for | ||
659 | * mailbox1. | ||
660 | */ | ||
661 | while (gk20a_fecs_trace_get_read_index(g) != write) { | ||
662 | nvgpu_log(g, gpu_dbg_ctxsw, "mailbox1 update failed"); | ||
663 | gk20a_fecs_trace_set_read_index(g, write); | ||
664 | } | ||
665 | |||
666 | err = nvgpu_thread_create(&trace->poll_task, g, | ||
667 | gk20a_fecs_trace_periodic_polling, __func__); | ||
668 | if (err) { | ||
669 | nvgpu_warn(g, | ||
651 | "failed to create FECS polling task"); | 670 | "failed to create FECS polling task"); |
652 | return err; | 671 | goto done; |
672 | } | ||
653 | } | 673 | } |
654 | 674 | ||
655 | return 0; | 675 | done: |
676 | nvgpu_mutex_release(&trace->enable_lock); | ||
677 | return err; | ||
656 | } | 678 | } |
657 | 679 | ||
658 | int gk20a_fecs_trace_disable(struct gk20a *g) | 680 | int gk20a_fecs_trace_disable(struct gk20a *g) |
@@ -660,32 +682,45 @@ int gk20a_fecs_trace_disable(struct gk20a *g) | |||
660 | struct gk20a_fecs_trace *trace = g->fecs_trace; | 682 | struct gk20a_fecs_trace *trace = g->fecs_trace; |
661 | int read = 0; | 683 | int read = 0; |
662 | 684 | ||
663 | if (nvgpu_thread_is_running(&trace->poll_task)) | 685 | if (trace == NULL) { |
664 | nvgpu_thread_stop(&trace->poll_task); | 686 | return -EINVAL; |
687 | } | ||
665 | 688 | ||
666 | if (nvgpu_is_enabled(g, NVGPU_FECS_TRACE_FEATURE_CONTROL)) { | 689 | nvgpu_mutex_acquire(&trace->enable_lock); |
667 | /* | 690 | if (trace->enable_count <= 0U) { |
668 | * For disabling FECS trace support, MAILBOX1's MSB | 691 | nvgpu_mutex_release(&trace->enable_lock); |
669 | * (Bit 31:31) should be set to 0. | 692 | return 0; |
670 | */ | 693 | } |
671 | read = gk20a_fecs_trace_get_read_index(g) & | 694 | trace->enable_count--; |
672 | (~(BIT32(NVGPU_FECS_TRACE_FEATURE_CONTROL_BIT))); | 695 | if (trace->enable_count == 0U) { |
696 | if (nvgpu_is_enabled(g, NVGPU_FECS_TRACE_FEATURE_CONTROL)) { | ||
697 | /* | ||
698 | * For disabling FECS trace support, MAILBOX1's MSB | ||
699 | * (Bit 31:31) should be set to 0. | ||
700 | */ | ||
701 | read = gk20a_fecs_trace_get_read_index(g) & | ||
702 | (~(BIT32(NVGPU_FECS_TRACE_FEATURE_CONTROL_BIT))); | ||
673 | 703 | ||
674 | gk20a_fecs_trace_set_read_index(g, read); | 704 | gk20a_fecs_trace_set_read_index(g, read); |
675 | 705 | ||
676 | /* | 706 | /* |
677 | * FECS ucode does a priv holdoff around the assertion | 707 | * FECS ucode does a priv holdoff around the assertion |
678 | * of context reset. So, pri transactions (e.g. | 708 | * of context reset. So, pri transactions (e.g. |
679 | * mailbox1 register write) might fail due to this. | 709 | * mailbox1 register write) might fail due to this. |
680 | * Hence, do write with ack i.e. write and read it back | 710 | * Hence, do write with ack i.e. write and read it back |
681 | * to make sure write happened for mailbox1. | 711 | * to make sure write happened for mailbox1. |
682 | */ | 712 | */ |
683 | while (gk20a_fecs_trace_get_read_index(g) != read) { | 713 | while (gk20a_fecs_trace_get_read_index(g) != read) { |
684 | nvgpu_log(g, gpu_dbg_ctxsw, | 714 | nvgpu_log(g, gpu_dbg_ctxsw, |
685 | "mailbox1 update failed"); | 715 | "mailbox1 update failed"); |
686 | gk20a_fecs_trace_set_read_index(g, read); | 716 | gk20a_fecs_trace_set_read_index(g, read); |
717 | } | ||
687 | } | 718 | } |
719 | |||
720 | nvgpu_thread_stop(&trace->poll_task); | ||
721 | |||
688 | } | 722 | } |
723 | nvgpu_mutex_release(&trace->enable_lock); | ||
689 | 724 | ||
690 | return -EPERM; | 725 | return -EPERM; |
691 | } | 726 | } |