diff options
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/debug.c | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/debug_allocator.c | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/debug_clk.c | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/debug_pmu.c | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/module.c | 55 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/module.h | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/pci.c | 13 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/thread.c | 6 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/pmu/pmu_fw.c | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/pramin.c | 9 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 37 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c | 33 |
12 files changed, 98 insertions, 65 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/debug.c b/drivers/gpu/nvgpu/common/linux/debug.c index 5750800f..08d0e679 100644 --- a/drivers/gpu/nvgpu/common/linux/debug.c +++ b/drivers/gpu/nvgpu/common/linux/debug.c | |||
@@ -409,5 +409,5 @@ void gk20a_debug_deinit(struct gk20a *g) | |||
409 | gk20a_fifo_debugfs_deinit(g); | 409 | gk20a_fifo_debugfs_deinit(g); |
410 | 410 | ||
411 | debugfs_remove_recursive(l->debugfs); | 411 | debugfs_remove_recursive(l->debugfs); |
412 | debugfs_remove_recursive(l->debugfs_alias); | 412 | debugfs_remove(l->debugfs_alias); |
413 | } | 413 | } |
diff --git a/drivers/gpu/nvgpu/common/linux/debug_allocator.c b/drivers/gpu/nvgpu/common/linux/debug_allocator.c index 91ae0512..d63a9030 100644 --- a/drivers/gpu/nvgpu/common/linux/debug_allocator.c +++ b/drivers/gpu/nvgpu/common/linux/debug_allocator.c | |||
@@ -55,8 +55,6 @@ void nvgpu_init_alloc_debug(struct gk20a *g, struct nvgpu_allocator *a) | |||
55 | 55 | ||
56 | void nvgpu_fini_alloc_debug(struct nvgpu_allocator *a) | 56 | void nvgpu_fini_alloc_debug(struct nvgpu_allocator *a) |
57 | { | 57 | { |
58 | if (!IS_ERR_OR_NULL(a->debugfs_entry)) | ||
59 | debugfs_remove(a->debugfs_entry); | ||
60 | } | 58 | } |
61 | 59 | ||
62 | void nvgpu_alloc_debugfs_init(struct gk20a *g) | 60 | void nvgpu_alloc_debugfs_init(struct gk20a *g) |
diff --git a/drivers/gpu/nvgpu/common/linux/debug_clk.c b/drivers/gpu/nvgpu/common/linux/debug_clk.c index b265ca69..81839de7 100644 --- a/drivers/gpu/nvgpu/common/linux/debug_clk.c +++ b/drivers/gpu/nvgpu/common/linux/debug_clk.c | |||
@@ -267,6 +267,5 @@ int gm20b_clk_init_debugfs(struct gk20a *g) | |||
267 | 267 | ||
268 | err_out: | 268 | err_out: |
269 | pr_err("%s: Failed to make debugfs node\n", __func__); | 269 | pr_err("%s: Failed to make debugfs node\n", __func__); |
270 | debugfs_remove_recursive(l->debugfs); | ||
271 | return -ENOMEM; | 270 | return -ENOMEM; |
272 | } | 271 | } |
diff --git a/drivers/gpu/nvgpu/common/linux/debug_pmu.c b/drivers/gpu/nvgpu/common/linux/debug_pmu.c index 191fcb0e..ec997e28 100644 --- a/drivers/gpu/nvgpu/common/linux/debug_pmu.c +++ b/drivers/gpu/nvgpu/common/linux/debug_pmu.c | |||
@@ -477,6 +477,5 @@ int gk20a_pmu_debugfs_init(struct gk20a *g) | |||
477 | return 0; | 477 | return 0; |
478 | err_out: | 478 | err_out: |
479 | pr_err("%s: Failed to make debugfs node\n", __func__); | 479 | pr_err("%s: Failed to make debugfs node\n", __func__); |
480 | debugfs_remove_recursive(l->debugfs); | ||
481 | return -ENOMEM; | 480 | return -ENOMEM; |
482 | } | 481 | } |
diff --git a/drivers/gpu/nvgpu/common/linux/module.c b/drivers/gpu/nvgpu/common/linux/module.c index 46b89ad0..c474f36a 100644 --- a/drivers/gpu/nvgpu/common/linux/module.c +++ b/drivers/gpu/nvgpu/common/linux/module.c | |||
@@ -226,9 +226,12 @@ static int gk20a_pm_prepare_poweroff(struct device *dev) | |||
226 | * After this point, gk20a interrupts should not get | 226 | * After this point, gk20a interrupts should not get |
227 | * serviced. | 227 | * serviced. |
228 | */ | 228 | */ |
229 | disable_irq(g->irq_stall); | 229 | if (g->irqs_enabled) { |
230 | if (g->irq_stall != g->irq_nonstall) | 230 | disable_irq(g->irq_stall); |
231 | disable_irq(g->irq_nonstall); | 231 | if (g->irq_stall != g->irq_nonstall) |
232 | disable_irq(g->irq_nonstall); | ||
233 | g->irqs_enabled = 0; | ||
234 | } | ||
232 | 235 | ||
233 | /* Decrement platform power refcount */ | 236 | /* Decrement platform power refcount */ |
234 | if (platform->idle) | 237 | if (platform->idle) |
@@ -641,6 +644,18 @@ static int gk20a_pm_unrailgate(struct device *dev) | |||
641 | } | 644 | } |
642 | 645 | ||
643 | /* | 646 | /* |
647 | * Remove association of the driver with OS interrupt handler | ||
648 | */ | ||
649 | void nvgpu_free_irq(struct gk20a *g) | ||
650 | { | ||
651 | struct device *dev = dev_from_gk20a(g); | ||
652 | |||
653 | devm_free_irq(dev, g->irq_stall, g); | ||
654 | if (g->irq_stall != g->irq_nonstall) | ||
655 | devm_free_irq(dev, g->irq_nonstall, g); | ||
656 | } | ||
657 | |||
658 | /* | ||
644 | * Idle the GPU in preparation of shutdown/remove. | 659 | * Idle the GPU in preparation of shutdown/remove. |
645 | * gk20a_driver_start_unload() does not idle the GPU, but instead changes the SW | 660 | * gk20a_driver_start_unload() does not idle the GPU, but instead changes the SW |
646 | * state to prevent further activity on the driver SW side. | 661 | * state to prevent further activity on the driver SW side. |
@@ -651,24 +666,27 @@ int nvgpu_quiesce(struct gk20a *g) | |||
651 | int err; | 666 | int err; |
652 | struct device *dev = dev_from_gk20a(g); | 667 | struct device *dev = dev_from_gk20a(g); |
653 | 668 | ||
654 | err = gk20a_wait_for_idle(g); | 669 | if (g->power_on) { |
655 | if (err) { | 670 | err = gk20a_wait_for_idle(g); |
656 | nvgpu_err(g, "failed to idle GPU, err=%d", err); | 671 | if (err) { |
657 | return err; | 672 | nvgpu_err(g, "failed to idle GPU, err=%d", err); |
658 | } | 673 | return err; |
674 | } | ||
659 | 675 | ||
660 | err = gk20a_fifo_disable_all_engine_activity(g, true); | 676 | err = gk20a_fifo_disable_all_engine_activity(g, true); |
661 | if (err) { | 677 | if (err) { |
662 | nvgpu_err(g, "failed to disable engine activity, err=%d", | 678 | nvgpu_err(g, |
663 | err); | 679 | "failed to disable engine activity, err=%d", |
680 | err); | ||
664 | return err; | 681 | return err; |
665 | } | 682 | } |
666 | 683 | ||
667 | err = gk20a_fifo_wait_engine_idle(g); | 684 | err = gk20a_fifo_wait_engine_idle(g); |
668 | if (err) { | 685 | if (err) { |
669 | nvgpu_err(g, "failed to idle engines, err=%d", | 686 | nvgpu_err(g, "failed to idle engines, err=%d", |
670 | err); | 687 | err); |
671 | return err; | 688 | return err; |
689 | } | ||
672 | } | 690 | } |
673 | 691 | ||
674 | if (gk20a_gpu_is_virtual(dev)) | 692 | if (gk20a_gpu_is_virtual(dev)) |
@@ -679,6 +697,7 @@ int nvgpu_quiesce(struct gk20a *g) | |||
679 | if (err) | 697 | if (err) |
680 | nvgpu_err(g, "failed to prepare for poweroff, err=%d", | 698 | nvgpu_err(g, "failed to prepare for poweroff, err=%d", |
681 | err); | 699 | err); |
700 | |||
682 | return err; | 701 | return err; |
683 | } | 702 | } |
684 | 703 | ||
diff --git a/drivers/gpu/nvgpu/common/linux/module.h b/drivers/gpu/nvgpu/common/linux/module.h index def98288..55a3b692 100644 --- a/drivers/gpu/nvgpu/common/linux/module.h +++ b/drivers/gpu/nvgpu/common/linux/module.h | |||
@@ -21,6 +21,7 @@ void gk20a_remove_support(struct gk20a *g); | |||
21 | void gk20a_driver_start_unload(struct gk20a *g); | 21 | void gk20a_driver_start_unload(struct gk20a *g); |
22 | int nvgpu_quiesce(struct gk20a *g); | 22 | int nvgpu_quiesce(struct gk20a *g); |
23 | int nvgpu_remove(struct device *dev, struct class *class); | 23 | int nvgpu_remove(struct device *dev, struct class *class); |
24 | void nvgpu_free_irq(struct gk20a *g); | ||
24 | 25 | ||
25 | extern struct class nvgpu_class; | 26 | extern struct class nvgpu_class; |
26 | 27 | ||
diff --git a/drivers/gpu/nvgpu/common/linux/pci.c b/drivers/gpu/nvgpu/common/linux/pci.c index f1d12367..1a7d1842 100644 --- a/drivers/gpu/nvgpu/common/linux/pci.c +++ b/drivers/gpu/nvgpu/common/linux/pci.c | |||
@@ -521,13 +521,12 @@ static void nvgpu_pci_remove(struct pci_dev *pdev) | |||
521 | if (gk20a_gpu_is_virtual(dev)) | 521 | if (gk20a_gpu_is_virtual(dev)) |
522 | return; | 522 | return; |
523 | 523 | ||
524 | /* only idle the GPU if the GPU is powered on */ | 524 | gk20a_driver_start_unload(g); |
525 | if (g->power_on) { | 525 | err = nvgpu_quiesce(g); |
526 | gk20a_driver_start_unload(g); | 526 | /* TODO: handle failure to idle */ |
527 | err = nvgpu_quiesce(g); | 527 | WARN(err, "gpu failed to idle during driver removal"); |
528 | /* TODO: handle failure to idle */ | 528 | |
529 | WARN(err, "gpu failed to idle during driver removal"); | 529 | nvgpu_free_irq(g); |
530 | } | ||
531 | 530 | ||
532 | nvgpu_remove(dev, &nvgpu_pci_class); | 531 | nvgpu_remove(dev, &nvgpu_pci_class); |
533 | 532 | ||
diff --git a/drivers/gpu/nvgpu/common/linux/thread.c b/drivers/gpu/nvgpu/common/linux/thread.c index fe3906eb..92c556f2 100644 --- a/drivers/gpu/nvgpu/common/linux/thread.c +++ b/drivers/gpu/nvgpu/common/linux/thread.c | |||
@@ -46,8 +46,10 @@ int nvgpu_thread_create(struct nvgpu_thread *thread, | |||
46 | 46 | ||
47 | void nvgpu_thread_stop(struct nvgpu_thread *thread) | 47 | void nvgpu_thread_stop(struct nvgpu_thread *thread) |
48 | { | 48 | { |
49 | kthread_stop(thread->task); | 49 | if (thread->task) { |
50 | thread->task = NULL; | 50 | kthread_stop(thread->task); |
51 | thread->task = NULL; | ||
52 | } | ||
51 | }; | 53 | }; |
52 | 54 | ||
53 | bool nvgpu_thread_should_stop(struct nvgpu_thread *thread) | 55 | bool nvgpu_thread_should_stop(struct nvgpu_thread *thread) |
diff --git a/drivers/gpu/nvgpu/common/pmu/pmu_fw.c b/drivers/gpu/nvgpu/common/pmu/pmu_fw.c index 077a1bf8..5fd8121d 100644 --- a/drivers/gpu/nvgpu/common/pmu/pmu_fw.c +++ b/drivers/gpu/nvgpu/common/pmu/pmu_fw.c | |||
@@ -2223,7 +2223,8 @@ static void nvgpu_remove_pmu_support(struct nvgpu_pmu *pmu) | |||
2223 | if (nvgpu_alloc_initialized(&pmu->dmem)) | 2223 | if (nvgpu_alloc_initialized(&pmu->dmem)) |
2224 | nvgpu_alloc_destroy(&pmu->dmem); | 2224 | nvgpu_alloc_destroy(&pmu->dmem); |
2225 | 2225 | ||
2226 | nvgpu_release_firmware(g, pmu->fw); | 2226 | if (pmu->fw) |
2227 | nvgpu_release_firmware(g, pmu->fw); | ||
2227 | 2228 | ||
2228 | nvgpu_mutex_destroy(&pmu->elpg_mutex); | 2229 | nvgpu_mutex_destroy(&pmu->elpg_mutex); |
2229 | nvgpu_mutex_destroy(&pmu->pg_mutex); | 2230 | nvgpu_mutex_destroy(&pmu->pg_mutex); |
diff --git a/drivers/gpu/nvgpu/common/pramin.c b/drivers/gpu/nvgpu/common/pramin.c index ae9c9b1f..7955e6c2 100644 --- a/drivers/gpu/nvgpu/common/pramin.c +++ b/drivers/gpu/nvgpu/common/pramin.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <nvgpu/pramin.h> | 17 | #include <nvgpu/pramin.h> |
18 | #include <nvgpu/page_allocator.h> | 18 | #include <nvgpu/page_allocator.h> |
19 | #include <nvgpu/enabled.h> | ||
19 | 20 | ||
20 | #include "gk20a/gk20a.h" | 21 | #include "gk20a/gk20a.h" |
21 | 22 | ||
@@ -88,6 +89,14 @@ void nvgpu_pramin_access_batched(struct gk20a *g, struct nvgpu_mem *mem, | |||
88 | void *sgl; | 89 | void *sgl; |
89 | u32 byteoff, start_reg, until_end, n; | 90 | u32 byteoff, start_reg, until_end, n; |
90 | 91 | ||
92 | /* | ||
93 | * TODO: Vidmem is not accesible through pramin on shutdown path. | ||
94 | * driver should be refactored to prevent this from happening, but for | ||
95 | * now it is ok just to ignore the writes | ||
96 | */ | ||
97 | if (!g->regs && nvgpu_is_enabled(g, NVGPU_DRIVER_IS_DYING)) | ||
98 | return; | ||
99 | |||
91 | alloc = get_vidmem_page_alloc(mem->priv.sgt->sgl); | 100 | alloc = get_vidmem_page_alloc(mem->priv.sgt->sgl); |
92 | sgt = &alloc->sgt; | 101 | sgt = &alloc->sgt; |
93 | for (sgl = sgt->sgl; sgl; sgl = nvgpu_sgt_get_next(sgt, sgl)) { | 102 | for (sgl = sgt->sgl; sgl; sgl = nvgpu_sgt_get_next(sgt, sgl)) { |
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 0b8422a6..ea69d7cb 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |||
@@ -465,21 +465,30 @@ static void gk20a_free_channel(struct channel_gk20a *ch, bool force) | |||
465 | 465 | ||
466 | trace_gk20a_free_channel(ch->chid); | 466 | trace_gk20a_free_channel(ch->chid); |
467 | 467 | ||
468 | /* abort channel and remove from runlist */ | 468 | /* |
469 | if (gk20a_is_channel_marked_as_tsg(ch)) { | 469 | * Disable channel/TSG and unbind here. This should not be executed if |
470 | err = g->ops.fifo.tsg_unbind_channel(ch); | 470 | * HW access is not available during shutdown/removal path as it will |
471 | if (err) | 471 | * trigger a timeout |
472 | nvgpu_err(g, "failed to unbind channel %d from TSG", ch->chid); | 472 | */ |
473 | /* | 473 | if (!nvgpu_is_enabled(g, NVGPU_DRIVER_IS_DYING)) { |
474 | * Channel is not a part of TSG this point onwards | 474 | /* abort channel and remove from runlist */ |
475 | * So stash its status and use it whenever necessary | 475 | if (gk20a_is_channel_marked_as_tsg(ch)) { |
476 | * e.g. while releasing gr_ctx in g->ops.gr.free_channel_ctx() | 476 | err = g->ops.fifo.tsg_unbind_channel(ch); |
477 | */ | 477 | if (err) |
478 | was_tsg = true; | 478 | nvgpu_err(g, |
479 | } else { | 479 | "failed to unbind channel %d from TSG", |
480 | gk20a_disable_channel(ch); | 480 | ch->chid); |
481 | /* | ||
482 | * Channel is not a part of TSG this point onwards | ||
483 | * So stash its status and use it whenever necessary | ||
484 | * e.g. while releasing gr_ctx in | ||
485 | * g->ops.gr.free_channel_ctx() | ||
486 | */ | ||
487 | was_tsg = true; | ||
488 | } else { | ||
489 | gk20a_disable_channel(ch); | ||
490 | } | ||
481 | } | 491 | } |
482 | |||
483 | /* wait until there's only our ref to the channel */ | 492 | /* wait until there's only our ref to the channel */ |
484 | if (!force) | 493 | if (!force) |
485 | gk20a_wait_until_counter_is_N( | 494 | gk20a_wait_until_counter_is_N( |
diff --git a/drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c b/drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c index fea3b0fa..71cba9ec 100644 --- a/drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c | |||
@@ -67,6 +67,7 @@ struct gk20a_fecs_trace { | |||
67 | struct nvgpu_mutex hash_lock; | 67 | struct nvgpu_mutex hash_lock; |
68 | struct nvgpu_mutex poll_lock; | 68 | struct nvgpu_mutex poll_lock; |
69 | struct nvgpu_thread poll_task; | 69 | struct nvgpu_thread poll_task; |
70 | bool init; | ||
70 | }; | 71 | }; |
71 | 72 | ||
72 | #ifdef CONFIG_GK20A_CTXSW_TRACE | 73 | #ifdef CONFIG_GK20A_CTXSW_TRACE |
@@ -547,23 +548,12 @@ static void gk20a_fecs_trace_debugfs_init(struct gk20a *g) | |||
547 | &gk20a_fecs_trace_debugfs_ring_fops); | 548 | &gk20a_fecs_trace_debugfs_ring_fops); |
548 | } | 549 | } |
549 | 550 | ||
550 | static void gk20a_fecs_trace_debugfs_cleanup(struct gk20a *g) | ||
551 | { | ||
552 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
553 | |||
554 | debugfs_remove_recursive(l->debugfs); | ||
555 | } | ||
556 | |||
557 | #else | 551 | #else |
558 | 552 | ||
559 | static void gk20a_fecs_trace_debugfs_init(struct gk20a *g) | 553 | static void gk20a_fecs_trace_debugfs_init(struct gk20a *g) |
560 | { | 554 | { |
561 | } | 555 | } |
562 | 556 | ||
563 | static inline void gk20a_fecs_trace_debugfs_cleanup(struct gk20a *g) | ||
564 | { | ||
565 | } | ||
566 | |||
567 | #endif /* CONFIG_DEBUG_FS */ | 557 | #endif /* CONFIG_DEBUG_FS */ |
568 | 558 | ||
569 | int gk20a_fecs_trace_init(struct gk20a *g) | 559 | int gk20a_fecs_trace_init(struct gk20a *g) |
@@ -598,6 +588,9 @@ int gk20a_fecs_trace_init(struct gk20a *g) | |||
598 | NVGPU_GPU_FLAGS_SUPPORT_FECS_CTXSW_TRACE; | 588 | NVGPU_GPU_FLAGS_SUPPORT_FECS_CTXSW_TRACE; |
599 | 589 | ||
600 | gk20a_fecs_trace_debugfs_init(g); | 590 | gk20a_fecs_trace_debugfs_init(g); |
591 | |||
592 | trace->init = true; | ||
593 | |||
601 | return 0; | 594 | return 0; |
602 | 595 | ||
603 | clean_hash_lock: | 596 | clean_hash_lock: |
@@ -682,15 +675,17 @@ int gk20a_fecs_trace_unbind_channel(struct gk20a *g, struct channel_gk20a *ch) | |||
682 | { | 675 | { |
683 | u32 context_ptr = gk20a_fecs_trace_fecs_context_ptr(g, ch); | 676 | u32 context_ptr = gk20a_fecs_trace_fecs_context_ptr(g, ch); |
684 | 677 | ||
685 | gk20a_dbg(gpu_dbg_fn|gpu_dbg_ctxsw, | 678 | if (g->fecs_trace) { |
679 | gk20a_dbg(gpu_dbg_fn|gpu_dbg_ctxsw, | ||
686 | "ch=%p context_ptr=%x", ch, context_ptr); | 680 | "ch=%p context_ptr=%x", ch, context_ptr); |
687 | 681 | ||
688 | if (g->ops.fecs_trace.is_enabled(g)) { | 682 | if (g->ops.fecs_trace.is_enabled(g)) { |
689 | if (g->ops.fecs_trace.flush) | 683 | if (g->ops.fecs_trace.flush) |
690 | g->ops.fecs_trace.flush(g); | 684 | g->ops.fecs_trace.flush(g); |
691 | gk20a_fecs_trace_poll(g); | 685 | gk20a_fecs_trace_poll(g); |
686 | } | ||
687 | gk20a_fecs_trace_hash_del(g, context_ptr); | ||
692 | } | 688 | } |
693 | gk20a_fecs_trace_hash_del(g, context_ptr); | ||
694 | return 0; | 689 | return 0; |
695 | } | 690 | } |
696 | 691 | ||
@@ -709,7 +704,9 @@ int gk20a_fecs_trace_deinit(struct gk20a *g) | |||
709 | { | 704 | { |
710 | struct gk20a_fecs_trace *trace = g->fecs_trace; | 705 | struct gk20a_fecs_trace *trace = g->fecs_trace; |
711 | 706 | ||
712 | gk20a_fecs_trace_debugfs_cleanup(g); | 707 | if (!trace->init) |
708 | return 0; | ||
709 | |||
713 | nvgpu_thread_stop(&trace->poll_task); | 710 | nvgpu_thread_stop(&trace->poll_task); |
714 | gk20a_fecs_trace_free_ring(g); | 711 | gk20a_fecs_trace_free_ring(g); |
715 | gk20a_fecs_trace_free_hash_table(g); | 712 | gk20a_fecs_trace_free_hash_table(g); |