.. | .. |
---|
3 | 3 | * Copyright (C) 2015-2018 Etnaviv Project |
---|
4 | 4 | */ |
---|
5 | 5 | |
---|
| 6 | +#include <linux/clk.h> |
---|
6 | 7 | #include <linux/component.h> |
---|
| 8 | +#include <linux/delay.h> |
---|
7 | 9 | #include <linux/dma-fence.h> |
---|
8 | | -#include <linux/moduleparam.h> |
---|
| 10 | +#include <linux/dma-mapping.h> |
---|
| 11 | +#include <linux/module.h> |
---|
9 | 12 | #include <linux/of_device.h> |
---|
| 13 | +#include <linux/platform_device.h> |
---|
| 14 | +#include <linux/pm_runtime.h> |
---|
| 15 | +#include <linux/regulator/consumer.h> |
---|
10 | 16 | #include <linux/thermal.h> |
---|
11 | 17 | |
---|
12 | 18 | #include "etnaviv_cmdbuf.h" |
---|
.. | .. |
---|
36 | 42 | |
---|
37 | 43 | int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value) |
---|
38 | 44 | { |
---|
| 45 | + struct etnaviv_drm_private *priv = gpu->drm->dev_private; |
---|
| 46 | + |
---|
39 | 47 | switch (param) { |
---|
40 | 48 | case ETNAVIV_PARAM_GPU_MODEL: |
---|
41 | 49 | *value = gpu->identity.model; |
---|
.. | .. |
---|
139 | 147 | |
---|
140 | 148 | case ETNAVIV_PARAM_GPU_NUM_VARYINGS: |
---|
141 | 149 | *value = gpu->identity.varyings_count; |
---|
| 150 | + break; |
---|
| 151 | + |
---|
| 152 | + case ETNAVIV_PARAM_SOFTPIN_START_ADDR: |
---|
| 153 | + if (priv->mmu_global->version == ETNAVIV_IOMMU_V2) |
---|
| 154 | + *value = ETNAVIV_SOFTPIN_START_ADDRESS; |
---|
| 155 | + else |
---|
| 156 | + *value = ~0ULL; |
---|
142 | 157 | break; |
---|
143 | 158 | |
---|
144 | 159 | default: |
---|
.. | .. |
---|
318 | 333 | gpu->identity.revision = etnaviv_field(chipIdentity, |
---|
319 | 334 | VIVS_HI_CHIP_IDENTITY_REVISION); |
---|
320 | 335 | } else { |
---|
| 336 | + u32 chipDate = gpu_read(gpu, VIVS_HI_CHIP_DATE); |
---|
321 | 337 | |
---|
322 | 338 | gpu->identity.model = gpu_read(gpu, VIVS_HI_CHIP_MODEL); |
---|
323 | 339 | gpu->identity.revision = gpu_read(gpu, VIVS_HI_CHIP_REV); |
---|
| 340 | + gpu->identity.customer_id = gpu_read(gpu, VIVS_HI_CHIP_CUSTOMER_ID); |
---|
| 341 | + |
---|
| 342 | + /* |
---|
| 343 | + * Reading these two registers on GC600 rev 0x19 result in a |
---|
| 344 | + * unhandled fault: external abort on non-linefetch |
---|
| 345 | + */ |
---|
| 346 | + if (!etnaviv_is_model_rev(gpu, GC600, 0x19)) { |
---|
| 347 | + gpu->identity.product_id = gpu_read(gpu, VIVS_HI_CHIP_PRODUCT_ID); |
---|
| 348 | + gpu->identity.eco_id = gpu_read(gpu, VIVS_HI_CHIP_ECO_ID); |
---|
| 349 | + } |
---|
324 | 350 | |
---|
325 | 351 | /* |
---|
326 | 352 | * !!!! HACK ALERT !!!! |
---|
.. | .. |
---|
335 | 361 | |
---|
336 | 362 | /* Another special case */ |
---|
337 | 363 | if (etnaviv_is_model_rev(gpu, GC300, 0x2201)) { |
---|
338 | | - u32 chipDate = gpu_read(gpu, VIVS_HI_CHIP_DATE); |
---|
339 | 364 | u32 chipTime = gpu_read(gpu, VIVS_HI_CHIP_TIME); |
---|
340 | 365 | |
---|
341 | 366 | if (chipDate == 0x20080814 && chipTime == 0x12051100) { |
---|
.. | .. |
---|
358 | 383 | gpu->identity.model = chipModel_GC3000; |
---|
359 | 384 | gpu->identity.revision &= 0xffff; |
---|
360 | 385 | } |
---|
| 386 | + |
---|
| 387 | + if (etnaviv_is_model_rev(gpu, GC1000, 0x5037) && (chipDate == 0x20120617)) |
---|
| 388 | + gpu->identity.eco_id = 1; |
---|
| 389 | + |
---|
| 390 | + if (etnaviv_is_model_rev(gpu, GC320, 0x5303) && (chipDate == 0x20140511)) |
---|
| 391 | + gpu->identity.eco_id = 1; |
---|
361 | 392 | } |
---|
362 | 393 | |
---|
363 | 394 | dev_info(gpu->dev, "model: GC%x, revision: %x\n", |
---|
364 | 395 | gpu->identity.model, gpu->identity.revision); |
---|
365 | 396 | |
---|
| 397 | + gpu->idle_mask = ~VIVS_HI_IDLE_STATE_AXI_LP; |
---|
366 | 398 | /* |
---|
367 | 399 | * If there is a match in the HWDB, we aren't interested in the |
---|
368 | 400 | * remaining register values, as they might be wrong. |
---|
.. | .. |
---|
375 | 407 | /* Disable fast clear on GC700. */ |
---|
376 | 408 | if (gpu->identity.model == chipModel_GC700) |
---|
377 | 409 | gpu->identity.features &= ~chipFeatures_FAST_CLEAR; |
---|
| 410 | + |
---|
| 411 | + /* These models/revisions don't have the 2D pipe bit */ |
---|
| 412 | + if ((gpu->identity.model == chipModel_GC500 && |
---|
| 413 | + gpu->identity.revision <= 2) || |
---|
| 414 | + gpu->identity.model == chipModel_GC300) |
---|
| 415 | + gpu->identity.features |= chipFeatures_PIPE_2D; |
---|
378 | 416 | |
---|
379 | 417 | if ((gpu->identity.model == chipModel_GC500 && |
---|
380 | 418 | gpu->identity.revision < 2) || |
---|
.. | .. |
---|
409 | 447 | gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_5); |
---|
410 | 448 | } |
---|
411 | 449 | |
---|
412 | | - /* GC600 idle register reports zero bits where modules aren't present */ |
---|
413 | | - if (gpu->identity.model == chipModel_GC600) { |
---|
| 450 | + /* GC600/300 idle register reports zero bits where modules aren't present */ |
---|
| 451 | + if (gpu->identity.model == chipModel_GC600 || |
---|
| 452 | + gpu->identity.model == chipModel_GC300) |
---|
414 | 453 | gpu->idle_mask = VIVS_HI_IDLE_STATE_TX | |
---|
415 | 454 | VIVS_HI_IDLE_STATE_RA | |
---|
416 | 455 | VIVS_HI_IDLE_STATE_SE | |
---|
.. | .. |
---|
419 | 458 | VIVS_HI_IDLE_STATE_PE | |
---|
420 | 459 | VIVS_HI_IDLE_STATE_DE | |
---|
421 | 460 | VIVS_HI_IDLE_STATE_FE; |
---|
422 | | - } else { |
---|
423 | | - gpu->idle_mask = ~VIVS_HI_IDLE_STATE_AXI_LP; |
---|
424 | | - } |
---|
425 | 461 | |
---|
426 | 462 | etnaviv_hw_specs(gpu); |
---|
427 | 463 | } |
---|
.. | .. |
---|
493 | 529 | /* read idle register. */ |
---|
494 | 530 | idle = gpu_read(gpu, VIVS_HI_IDLE_STATE); |
---|
495 | 531 | |
---|
496 | | - /* try reseting again if FE it not idle */ |
---|
| 532 | + /* try resetting again if FE is not idle */ |
---|
497 | 533 | if ((idle & VIVS_HI_IDLE_STATE_FE) == 0) { |
---|
498 | 534 | dev_dbg(gpu->dev, "FE is not idle\n"); |
---|
499 | 535 | continue; |
---|
.. | .. |
---|
531 | 567 | |
---|
532 | 568 | /* We rely on the GPU running, so program the clock */ |
---|
533 | 569 | etnaviv_gpu_update_clock(gpu); |
---|
| 570 | + |
---|
| 571 | + gpu->fe_running = false; |
---|
| 572 | + gpu->exec_state = -1; |
---|
| 573 | + if (gpu->mmu_context) |
---|
| 574 | + etnaviv_iommu_context_put(gpu->mmu_context); |
---|
| 575 | + gpu->mmu_context = NULL; |
---|
534 | 576 | |
---|
535 | 577 | return 0; |
---|
536 | 578 | } |
---|
.. | .. |
---|
594 | 636 | VIVS_MMUv2_SEC_COMMAND_CONTROL_ENABLE | |
---|
595 | 637 | VIVS_MMUv2_SEC_COMMAND_CONTROL_PREFETCH(prefetch)); |
---|
596 | 638 | } |
---|
| 639 | + |
---|
| 640 | + gpu->fe_running = true; |
---|
| 641 | +} |
---|
| 642 | + |
---|
| 643 | +static void etnaviv_gpu_start_fe_idleloop(struct etnaviv_gpu *gpu, |
---|
| 644 | + struct etnaviv_iommu_context *context) |
---|
| 645 | +{ |
---|
| 646 | + u16 prefetch; |
---|
| 647 | + u32 address; |
---|
| 648 | + |
---|
| 649 | + /* setup the MMU */ |
---|
| 650 | + etnaviv_iommu_restore(gpu, context); |
---|
| 651 | + |
---|
| 652 | + /* Start command processor */ |
---|
| 653 | + prefetch = etnaviv_buffer_init(gpu); |
---|
| 654 | + address = etnaviv_cmdbuf_get_va(&gpu->buffer, |
---|
| 655 | + &gpu->mmu_context->cmdbuf_mapping); |
---|
| 656 | + |
---|
| 657 | + etnaviv_gpu_start_fe(gpu, address, prefetch); |
---|
597 | 658 | } |
---|
598 | 659 | |
---|
599 | 660 | static void etnaviv_gpu_setup_pulse_eater(struct etnaviv_gpu *gpu) |
---|
.. | .. |
---|
629 | 690 | |
---|
630 | 691 | static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu) |
---|
631 | 692 | { |
---|
632 | | - u16 prefetch; |
---|
633 | | - |
---|
634 | 693 | if ((etnaviv_is_model_rev(gpu, GC320, 0x5007) || |
---|
635 | 694 | etnaviv_is_model_rev(gpu, GC320, 0x5220)) && |
---|
636 | 695 | gpu_read(gpu, VIVS_HI_CHIP_TIME) != 0x2062400) { |
---|
.. | .. |
---|
676 | 735 | /* setup the pulse eater */ |
---|
677 | 736 | etnaviv_gpu_setup_pulse_eater(gpu); |
---|
678 | 737 | |
---|
679 | | - /* setup the MMU */ |
---|
680 | | - etnaviv_iommu_restore(gpu); |
---|
681 | | - |
---|
682 | | - /* Start command processor */ |
---|
683 | | - prefetch = etnaviv_buffer_init(gpu); |
---|
684 | | - |
---|
685 | 738 | gpu_write(gpu, VIVS_HI_INTR_ENBL, ~0U); |
---|
686 | | - etnaviv_gpu_start_fe(gpu, etnaviv_cmdbuf_get_va(&gpu->buffer), |
---|
687 | | - prefetch); |
---|
688 | 739 | } |
---|
689 | 740 | |
---|
690 | 741 | int etnaviv_gpu_init(struct etnaviv_gpu *gpu) |
---|
691 | 742 | { |
---|
| 743 | + struct etnaviv_drm_private *priv = gpu->drm->dev_private; |
---|
692 | 744 | int ret, i; |
---|
693 | 745 | |
---|
694 | 746 | ret = pm_runtime_get_sync(gpu->dev); |
---|
.. | .. |
---|
714 | 766 | } |
---|
715 | 767 | |
---|
716 | 768 | /* |
---|
717 | | - * Set the GPU linear window to be at the end of the DMA window, where |
---|
718 | | - * the CMA area is likely to reside. This ensures that we are able to |
---|
719 | | - * map the command buffers while having the linear window overlap as |
---|
720 | | - * much RAM as possible, so we can optimize mappings for other buffers. |
---|
721 | | - * |
---|
722 | | - * For 3D cores only do this if MC2.0 is present, as with MC1.0 it leads |
---|
723 | | - * to different views of the memory on the individual engines. |
---|
724 | | - */ |
---|
725 | | - if (!(gpu->identity.features & chipFeatures_PIPE_3D) || |
---|
726 | | - (gpu->identity.minor_features0 & chipMinorFeatures0_MC20)) { |
---|
727 | | - u32 dma_mask = (u32)dma_get_required_mask(gpu->dev); |
---|
728 | | - if (dma_mask < PHYS_OFFSET + SZ_2G) |
---|
729 | | - gpu->memory_base = PHYS_OFFSET; |
---|
730 | | - else |
---|
731 | | - gpu->memory_base = dma_mask - SZ_2G + 1; |
---|
732 | | - } else if (PHYS_OFFSET >= SZ_2G) { |
---|
733 | | - dev_info(gpu->dev, "Need to move linear window on MC1.0, disabling TS\n"); |
---|
734 | | - gpu->memory_base = PHYS_OFFSET; |
---|
735 | | - gpu->identity.features &= ~chipFeatures_FAST_CLEAR; |
---|
736 | | - } |
---|
737 | | - |
---|
738 | | - /* |
---|
739 | 769 | * On cores with security features supported, we claim control over the |
---|
740 | 770 | * security states. |
---|
741 | 771 | */ |
---|
.. | .. |
---|
749 | 779 | goto fail; |
---|
750 | 780 | } |
---|
751 | 781 | |
---|
752 | | - gpu->mmu = etnaviv_iommu_new(gpu); |
---|
753 | | - if (IS_ERR(gpu->mmu)) { |
---|
754 | | - dev_err(gpu->dev, "Failed to instantiate GPU IOMMU\n"); |
---|
755 | | - ret = PTR_ERR(gpu->mmu); |
---|
| 782 | + ret = etnaviv_iommu_global_init(gpu); |
---|
| 783 | + if (ret) |
---|
756 | 784 | goto fail; |
---|
| 785 | + |
---|
| 786 | + /* |
---|
| 787 | + * Set the GPU linear window to be at the end of the DMA window, where |
---|
| 788 | + * the CMA area is likely to reside. This ensures that we are able to |
---|
| 789 | + * map the command buffers while having the linear window overlap as |
---|
| 790 | + * much RAM as possible, so we can optimize mappings for other buffers. |
---|
| 791 | + * |
---|
| 792 | + * For 3D cores only do this if MC2.0 is present, as with MC1.0 it leads |
---|
| 793 | + * to different views of the memory on the individual engines. |
---|
| 794 | + */ |
---|
| 795 | + if (!(gpu->identity.features & chipFeatures_PIPE_3D) || |
---|
| 796 | + (gpu->identity.minor_features0 & chipMinorFeatures0_MC20)) { |
---|
| 797 | + u32 dma_mask = (u32)dma_get_required_mask(gpu->dev); |
---|
| 798 | + if (dma_mask < PHYS_OFFSET + SZ_2G) |
---|
| 799 | + priv->mmu_global->memory_base = PHYS_OFFSET; |
---|
| 800 | + else |
---|
| 801 | + priv->mmu_global->memory_base = dma_mask - SZ_2G + 1; |
---|
| 802 | + } else if (PHYS_OFFSET >= SZ_2G) { |
---|
| 803 | + dev_info(gpu->dev, "Need to move linear window on MC1.0, disabling TS\n"); |
---|
| 804 | + priv->mmu_global->memory_base = PHYS_OFFSET; |
---|
| 805 | + gpu->identity.features &= ~chipFeatures_FAST_CLEAR; |
---|
757 | 806 | } |
---|
758 | 807 | |
---|
759 | | - gpu->cmdbuf_suballoc = etnaviv_cmdbuf_suballoc_new(gpu); |
---|
760 | | - if (IS_ERR(gpu->cmdbuf_suballoc)) { |
---|
761 | | - dev_err(gpu->dev, "Failed to create cmdbuf suballocator\n"); |
---|
762 | | - ret = PTR_ERR(gpu->cmdbuf_suballoc); |
---|
763 | | - goto destroy_iommu; |
---|
764 | | - } |
---|
| 808 | + /* |
---|
| 809 | + * If the GPU is part of a system with DMA addressing limitations, |
---|
| 810 | + * request pages for our SHM backend buffers from the DMA32 zone to |
---|
| 811 | + * hopefully avoid performance killing SWIOTLB bounce buffering. |
---|
| 812 | + */ |
---|
| 813 | + if (dma_addressing_limited(gpu->dev)) |
---|
| 814 | + priv->shm_gfp_mask |= GFP_DMA32; |
---|
765 | 815 | |
---|
766 | 816 | /* Create buffer: */ |
---|
767 | | - ret = etnaviv_cmdbuf_init(gpu->cmdbuf_suballoc, &gpu->buffer, |
---|
| 817 | + ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &gpu->buffer, |
---|
768 | 818 | PAGE_SIZE); |
---|
769 | 819 | if (ret) { |
---|
770 | 820 | dev_err(gpu->dev, "could not create command buffer\n"); |
---|
771 | | - goto destroy_suballoc; |
---|
772 | | - } |
---|
773 | | - |
---|
774 | | - if (gpu->mmu->version == ETNAVIV_IOMMU_V1 && |
---|
775 | | - etnaviv_cmdbuf_get_va(&gpu->buffer) > 0x80000000) { |
---|
776 | | - ret = -EINVAL; |
---|
777 | | - dev_err(gpu->dev, |
---|
778 | | - "command buffer outside valid memory window\n"); |
---|
779 | | - goto free_buffer; |
---|
| 821 | + goto fail; |
---|
780 | 822 | } |
---|
781 | 823 | |
---|
782 | 824 | /* Setup event management */ |
---|
.. | .. |
---|
789 | 831 | /* Now program the hardware */ |
---|
790 | 832 | mutex_lock(&gpu->lock); |
---|
791 | 833 | etnaviv_gpu_hw_init(gpu); |
---|
792 | | - gpu->exec_state = -1; |
---|
793 | 834 | mutex_unlock(&gpu->lock); |
---|
794 | 835 | |
---|
795 | 836 | pm_runtime_mark_last_busy(gpu->dev); |
---|
796 | 837 | pm_runtime_put_autosuspend(gpu->dev); |
---|
797 | 838 | |
---|
| 839 | + gpu->initialized = true; |
---|
| 840 | + |
---|
798 | 841 | return 0; |
---|
799 | 842 | |
---|
800 | | -free_buffer: |
---|
801 | | - etnaviv_cmdbuf_free(&gpu->buffer); |
---|
802 | | - gpu->buffer.suballoc = NULL; |
---|
803 | | -destroy_suballoc: |
---|
804 | | - etnaviv_cmdbuf_suballoc_destroy(gpu->cmdbuf_suballoc); |
---|
805 | | - gpu->cmdbuf_suballoc = NULL; |
---|
806 | | -destroy_iommu: |
---|
807 | | - etnaviv_iommu_destroy(gpu->mmu); |
---|
808 | | - gpu->mmu = NULL; |
---|
809 | 843 | fail: |
---|
810 | 844 | pm_runtime_mark_last_busy(gpu->dev); |
---|
811 | 845 | pm_put: |
---|
.. | .. |
---|
857 | 891 | idle = gpu_read(gpu, VIVS_HI_IDLE_STATE); |
---|
858 | 892 | |
---|
859 | 893 | verify_dma(gpu, &debug); |
---|
| 894 | + |
---|
| 895 | + seq_puts(m, "\tidentity\n"); |
---|
| 896 | + seq_printf(m, "\t model: 0x%x\n", gpu->identity.model); |
---|
| 897 | + seq_printf(m, "\t revision: 0x%x\n", gpu->identity.revision); |
---|
| 898 | + seq_printf(m, "\t product_id: 0x%x\n", gpu->identity.product_id); |
---|
| 899 | + seq_printf(m, "\t customer_id: 0x%x\n", gpu->identity.customer_id); |
---|
| 900 | + seq_printf(m, "\t eco_id: 0x%x\n", gpu->identity.eco_id); |
---|
860 | 901 | |
---|
861 | 902 | seq_puts(m, "\tfeatures\n"); |
---|
862 | 903 | seq_printf(m, "\t major_features: 0x%08x\n", |
---|
.. | .. |
---|
937 | 978 | seq_puts(m, "\t FP is not idle\n"); |
---|
938 | 979 | if ((idle & VIVS_HI_IDLE_STATE_TS) == 0) |
---|
939 | 980 | seq_puts(m, "\t TS is not idle\n"); |
---|
| 981 | + if ((idle & VIVS_HI_IDLE_STATE_BL) == 0) |
---|
| 982 | + seq_puts(m, "\t BL is not idle\n"); |
---|
| 983 | + if ((idle & VIVS_HI_IDLE_STATE_ASYNCFE) == 0) |
---|
| 984 | + seq_puts(m, "\t ASYNCFE is not idle\n"); |
---|
| 985 | + if ((idle & VIVS_HI_IDLE_STATE_MC) == 0) |
---|
| 986 | + seq_puts(m, "\t MC is not idle\n"); |
---|
| 987 | + if ((idle & VIVS_HI_IDLE_STATE_PPA) == 0) |
---|
| 988 | + seq_puts(m, "\t PPA is not idle\n"); |
---|
| 989 | + if ((idle & VIVS_HI_IDLE_STATE_WD) == 0) |
---|
| 990 | + seq_puts(m, "\t WD is not idle\n"); |
---|
| 991 | + if ((idle & VIVS_HI_IDLE_STATE_NN) == 0) |
---|
| 992 | + seq_puts(m, "\t NN is not idle\n"); |
---|
| 993 | + if ((idle & VIVS_HI_IDLE_STATE_TP) == 0) |
---|
| 994 | + seq_puts(m, "\t TP is not idle\n"); |
---|
940 | 995 | if (idle & VIVS_HI_IDLE_STATE_AXI_LP) |
---|
941 | 996 | seq_puts(m, "\t AXI low power mode\n"); |
---|
942 | 997 | |
---|
.. | .. |
---|
981 | 1036 | |
---|
982 | 1037 | void etnaviv_gpu_recover_hang(struct etnaviv_gpu *gpu) |
---|
983 | 1038 | { |
---|
984 | | - unsigned long flags; |
---|
985 | 1039 | unsigned int i = 0; |
---|
986 | 1040 | |
---|
987 | 1041 | dev_err(gpu->dev, "recover hung GPU!\n"); |
---|
.. | .. |
---|
994 | 1048 | etnaviv_hw_reset(gpu); |
---|
995 | 1049 | |
---|
996 | 1050 | /* complete all events, the GPU won't do it after the reset */ |
---|
997 | | - spin_lock_irqsave(&gpu->event_spinlock, flags); |
---|
| 1051 | + spin_lock(&gpu->event_spinlock); |
---|
998 | 1052 | for_each_set_bit_from(i, gpu->event_bitmap, ETNA_NR_EVENTS) |
---|
999 | 1053 | complete(&gpu->event_free); |
---|
1000 | 1054 | bitmap_zero(gpu->event_bitmap, ETNA_NR_EVENTS); |
---|
1001 | | - spin_unlock_irqrestore(&gpu->event_spinlock, flags); |
---|
1002 | | - gpu->completed_fence = gpu->active_fence; |
---|
| 1055 | + spin_unlock(&gpu->event_spinlock); |
---|
1003 | 1056 | |
---|
1004 | 1057 | etnaviv_gpu_hw_init(gpu); |
---|
1005 | | - gpu->lastctx = NULL; |
---|
1006 | | - gpu->exec_state = -1; |
---|
1007 | 1058 | |
---|
1008 | 1059 | mutex_unlock(&gpu->lock); |
---|
1009 | 1060 | pm_runtime_mark_last_busy(gpu->dev); |
---|
.. | .. |
---|
1038 | 1089 | { |
---|
1039 | 1090 | struct etnaviv_fence *f = to_etnaviv_fence(fence); |
---|
1040 | 1091 | |
---|
1041 | | - return fence_completed(f->gpu, f->base.seqno); |
---|
| 1092 | + return (s32)(f->gpu->completed_fence - f->base.seqno) >= 0; |
---|
1042 | 1093 | } |
---|
1043 | 1094 | |
---|
1044 | 1095 | static void etnaviv_fence_release(struct dma_fence *fence) |
---|
.. | .. |
---|
1077 | 1128 | return &f->base; |
---|
1078 | 1129 | } |
---|
1079 | 1130 | |
---|
| 1131 | +/* returns true if fence a comes after fence b */ |
---|
| 1132 | +static inline bool fence_after(u32 a, u32 b) |
---|
| 1133 | +{ |
---|
| 1134 | + return (s32)(a - b) > 0; |
---|
| 1135 | +} |
---|
| 1136 | + |
---|
1080 | 1137 | /* |
---|
1081 | 1138 | * event management: |
---|
1082 | 1139 | */ |
---|
.. | .. |
---|
1084 | 1141 | static int event_alloc(struct etnaviv_gpu *gpu, unsigned nr_events, |
---|
1085 | 1142 | unsigned int *events) |
---|
1086 | 1143 | { |
---|
1087 | | - unsigned long flags, timeout = msecs_to_jiffies(10 * 10000); |
---|
| 1144 | + unsigned long timeout = msecs_to_jiffies(10 * 10000); |
---|
1088 | 1145 | unsigned i, acquired = 0; |
---|
1089 | 1146 | |
---|
1090 | 1147 | for (i = 0; i < nr_events; i++) { |
---|
.. | .. |
---|
1101 | 1158 | timeout = ret; |
---|
1102 | 1159 | } |
---|
1103 | 1160 | |
---|
1104 | | - spin_lock_irqsave(&gpu->event_spinlock, flags); |
---|
| 1161 | + spin_lock(&gpu->event_spinlock); |
---|
1105 | 1162 | |
---|
1106 | 1163 | for (i = 0; i < nr_events; i++) { |
---|
1107 | 1164 | int event = find_first_zero_bit(gpu->event_bitmap, ETNA_NR_EVENTS); |
---|
.. | .. |
---|
1111 | 1168 | set_bit(event, gpu->event_bitmap); |
---|
1112 | 1169 | } |
---|
1113 | 1170 | |
---|
1114 | | - spin_unlock_irqrestore(&gpu->event_spinlock, flags); |
---|
| 1171 | + spin_unlock(&gpu->event_spinlock); |
---|
1115 | 1172 | |
---|
1116 | 1173 | return 0; |
---|
1117 | 1174 | |
---|
.. | .. |
---|
1124 | 1181 | |
---|
1125 | 1182 | static void event_free(struct etnaviv_gpu *gpu, unsigned int event) |
---|
1126 | 1183 | { |
---|
1127 | | - unsigned long flags; |
---|
1128 | | - |
---|
1129 | | - spin_lock_irqsave(&gpu->event_spinlock, flags); |
---|
1130 | | - |
---|
1131 | 1184 | if (!test_bit(event, gpu->event_bitmap)) { |
---|
1132 | 1185 | dev_warn(gpu->dev, "event %u is already marked as free", |
---|
1133 | 1186 | event); |
---|
1134 | | - spin_unlock_irqrestore(&gpu->event_spinlock, flags); |
---|
1135 | 1187 | } else { |
---|
1136 | 1188 | clear_bit(event, gpu->event_bitmap); |
---|
1137 | | - spin_unlock_irqrestore(&gpu->event_spinlock, flags); |
---|
1138 | | - |
---|
1139 | 1189 | complete(&gpu->event_free); |
---|
1140 | 1190 | } |
---|
1141 | 1191 | } |
---|
.. | .. |
---|
1144 | 1194 | * Cmdstream submission/retirement: |
---|
1145 | 1195 | */ |
---|
1146 | 1196 | int etnaviv_gpu_wait_fence_interruptible(struct etnaviv_gpu *gpu, |
---|
1147 | | - u32 id, struct timespec *timeout) |
---|
| 1197 | + u32 id, struct drm_etnaviv_timespec *timeout) |
---|
1148 | 1198 | { |
---|
1149 | 1199 | struct dma_fence *fence; |
---|
1150 | 1200 | int ret; |
---|
.. | .. |
---|
1191 | 1241 | * that lock in this function while waiting. |
---|
1192 | 1242 | */ |
---|
1193 | 1243 | int etnaviv_gpu_wait_obj_inactive(struct etnaviv_gpu *gpu, |
---|
1194 | | - struct etnaviv_gem_object *etnaviv_obj, struct timespec *timeout) |
---|
| 1244 | + struct etnaviv_gem_object *etnaviv_obj, |
---|
| 1245 | + struct drm_etnaviv_timespec *timeout) |
---|
1195 | 1246 | { |
---|
1196 | 1247 | unsigned long remaining; |
---|
1197 | 1248 | long ret; |
---|
.. | .. |
---|
1315 | 1366 | goto out_unlock; |
---|
1316 | 1367 | } |
---|
1317 | 1368 | |
---|
1318 | | - gpu->active_fence = gpu_fence->seqno; |
---|
| 1369 | + if (!gpu->fe_running) |
---|
| 1370 | + etnaviv_gpu_start_fe_idleloop(gpu, submit->mmu_context); |
---|
| 1371 | + |
---|
| 1372 | + if (submit->prev_mmu_context) |
---|
| 1373 | + etnaviv_iommu_context_put(submit->prev_mmu_context); |
---|
| 1374 | + submit->prev_mmu_context = etnaviv_iommu_context_get(gpu->mmu_context); |
---|
1319 | 1375 | |
---|
1320 | 1376 | if (submit->nr_pmrs) { |
---|
1321 | 1377 | gpu->event[event[1]].sync_point = &sync_point_perfmon_sample_pre; |
---|
.. | .. |
---|
1326 | 1382 | |
---|
1327 | 1383 | gpu->event[event[0]].fence = gpu_fence; |
---|
1328 | 1384 | submit->cmdbuf.user_size = submit->cmdbuf.size - 8; |
---|
1329 | | - etnaviv_buffer_queue(gpu, submit->exec_state, event[0], |
---|
1330 | | - &submit->cmdbuf); |
---|
| 1385 | + etnaviv_buffer_queue(gpu, submit->exec_state, submit->mmu_context, |
---|
| 1386 | + event[0], &submit->cmdbuf); |
---|
1331 | 1387 | |
---|
1332 | 1388 | if (submit->nr_pmrs) { |
---|
1333 | 1389 | gpu->event[event[2]].sync_point = &sync_point_perfmon_sample_post; |
---|
.. | .. |
---|
1456 | 1512 | { |
---|
1457 | 1513 | int ret; |
---|
1458 | 1514 | |
---|
1459 | | - if (gpu->clk_reg) { |
---|
1460 | | - ret = clk_prepare_enable(gpu->clk_reg); |
---|
1461 | | - if (ret) |
---|
1462 | | - return ret; |
---|
1463 | | - } |
---|
| 1515 | + ret = clk_prepare_enable(gpu->clk_reg); |
---|
| 1516 | + if (ret) |
---|
| 1517 | + return ret; |
---|
1464 | 1518 | |
---|
1465 | | - if (gpu->clk_bus) { |
---|
1466 | | - ret = clk_prepare_enable(gpu->clk_bus); |
---|
1467 | | - if (ret) |
---|
1468 | | - goto disable_clk_reg; |
---|
1469 | | - } |
---|
| 1519 | + ret = clk_prepare_enable(gpu->clk_bus); |
---|
| 1520 | + if (ret) |
---|
| 1521 | + goto disable_clk_reg; |
---|
1470 | 1522 | |
---|
1471 | | - if (gpu->clk_core) { |
---|
1472 | | - ret = clk_prepare_enable(gpu->clk_core); |
---|
1473 | | - if (ret) |
---|
1474 | | - goto disable_clk_bus; |
---|
1475 | | - } |
---|
| 1523 | + ret = clk_prepare_enable(gpu->clk_core); |
---|
| 1524 | + if (ret) |
---|
| 1525 | + goto disable_clk_bus; |
---|
1476 | 1526 | |
---|
1477 | | - if (gpu->clk_shader) { |
---|
1478 | | - ret = clk_prepare_enable(gpu->clk_shader); |
---|
1479 | | - if (ret) |
---|
1480 | | - goto disable_clk_core; |
---|
1481 | | - } |
---|
| 1527 | + ret = clk_prepare_enable(gpu->clk_shader); |
---|
| 1528 | + if (ret) |
---|
| 1529 | + goto disable_clk_core; |
---|
1482 | 1530 | |
---|
1483 | 1531 | return 0; |
---|
1484 | 1532 | |
---|
1485 | 1533 | disable_clk_core: |
---|
1486 | | - if (gpu->clk_core) |
---|
1487 | | - clk_disable_unprepare(gpu->clk_core); |
---|
| 1534 | + clk_disable_unprepare(gpu->clk_core); |
---|
1488 | 1535 | disable_clk_bus: |
---|
1489 | | - if (gpu->clk_bus) |
---|
1490 | | - clk_disable_unprepare(gpu->clk_bus); |
---|
| 1536 | + clk_disable_unprepare(gpu->clk_bus); |
---|
1491 | 1537 | disable_clk_reg: |
---|
1492 | | - if (gpu->clk_reg) |
---|
1493 | | - clk_disable_unprepare(gpu->clk_reg); |
---|
| 1538 | + clk_disable_unprepare(gpu->clk_reg); |
---|
1494 | 1539 | |
---|
1495 | 1540 | return ret; |
---|
1496 | 1541 | } |
---|
1497 | 1542 | |
---|
1498 | 1543 | static int etnaviv_gpu_clk_disable(struct etnaviv_gpu *gpu) |
---|
1499 | 1544 | { |
---|
1500 | | - if (gpu->clk_shader) |
---|
1501 | | - clk_disable_unprepare(gpu->clk_shader); |
---|
1502 | | - if (gpu->clk_core) |
---|
1503 | | - clk_disable_unprepare(gpu->clk_core); |
---|
1504 | | - if (gpu->clk_bus) |
---|
1505 | | - clk_disable_unprepare(gpu->clk_bus); |
---|
1506 | | - if (gpu->clk_reg) |
---|
1507 | | - clk_disable_unprepare(gpu->clk_reg); |
---|
| 1545 | + clk_disable_unprepare(gpu->clk_shader); |
---|
| 1546 | + clk_disable_unprepare(gpu->clk_core); |
---|
| 1547 | + clk_disable_unprepare(gpu->clk_bus); |
---|
| 1548 | + clk_disable_unprepare(gpu->clk_reg); |
---|
1508 | 1549 | |
---|
1509 | 1550 | return 0; |
---|
1510 | 1551 | } |
---|
.. | .. |
---|
1532 | 1573 | |
---|
1533 | 1574 | static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu) |
---|
1534 | 1575 | { |
---|
1535 | | - if (gpu->buffer.suballoc) { |
---|
| 1576 | + if (gpu->initialized && gpu->fe_running) { |
---|
1536 | 1577 | /* Replace the last WAIT with END */ |
---|
1537 | 1578 | mutex_lock(&gpu->lock); |
---|
1538 | 1579 | etnaviv_buffer_end(gpu); |
---|
.. | .. |
---|
1544 | 1585 | * we fail, just warn and continue. |
---|
1545 | 1586 | */ |
---|
1546 | 1587 | etnaviv_gpu_wait_idle(gpu, 100); |
---|
| 1588 | + |
---|
| 1589 | + gpu->fe_running = false; |
---|
1547 | 1590 | } |
---|
| 1591 | + |
---|
| 1592 | + gpu->exec_state = -1; |
---|
1548 | 1593 | |
---|
1549 | 1594 | return etnaviv_gpu_clk_disable(gpu); |
---|
1550 | 1595 | } |
---|
.. | .. |
---|
1560 | 1605 | |
---|
1561 | 1606 | etnaviv_gpu_update_clock(gpu); |
---|
1562 | 1607 | etnaviv_gpu_hw_init(gpu); |
---|
1563 | | - |
---|
1564 | | - gpu->lastctx = NULL; |
---|
1565 | | - gpu->exec_state = -1; |
---|
1566 | 1608 | |
---|
1567 | 1609 | mutex_unlock(&gpu->lock); |
---|
1568 | 1610 | |
---|
.. | .. |
---|
1692 | 1734 | etnaviv_gpu_hw_suspend(gpu); |
---|
1693 | 1735 | #endif |
---|
1694 | 1736 | |
---|
1695 | | - if (gpu->buffer.suballoc) |
---|
| 1737 | + if (gpu->mmu_context) |
---|
| 1738 | + etnaviv_iommu_context_put(gpu->mmu_context); |
---|
| 1739 | + |
---|
| 1740 | + if (gpu->initialized) { |
---|
1696 | 1741 | etnaviv_cmdbuf_free(&gpu->buffer); |
---|
1697 | | - |
---|
1698 | | - if (gpu->cmdbuf_suballoc) { |
---|
1699 | | - etnaviv_cmdbuf_suballoc_destroy(gpu->cmdbuf_suballoc); |
---|
1700 | | - gpu->cmdbuf_suballoc = NULL; |
---|
1701 | | - } |
---|
1702 | | - |
---|
1703 | | - if (gpu->mmu) { |
---|
1704 | | - etnaviv_iommu_destroy(gpu->mmu); |
---|
1705 | | - gpu->mmu = NULL; |
---|
| 1742 | + etnaviv_iommu_global_fini(gpu); |
---|
| 1743 | + gpu->initialized = false; |
---|
1706 | 1744 | } |
---|
1707 | 1745 | |
---|
1708 | 1746 | gpu->drm = NULL; |
---|
.. | .. |
---|
1730 | 1768 | { |
---|
1731 | 1769 | struct device *dev = &pdev->dev; |
---|
1732 | 1770 | struct etnaviv_gpu *gpu; |
---|
1733 | | - struct resource *res; |
---|
1734 | 1771 | int err; |
---|
1735 | 1772 | |
---|
1736 | 1773 | gpu = devm_kzalloc(dev, sizeof(*gpu), GFP_KERNEL); |
---|
.. | .. |
---|
1742 | 1779 | mutex_init(&gpu->fence_lock); |
---|
1743 | 1780 | |
---|
1744 | 1781 | /* Map registers: */ |
---|
1745 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
1746 | | - gpu->mmio = devm_ioremap_resource(&pdev->dev, res); |
---|
| 1782 | + gpu->mmio = devm_platform_ioremap_resource(pdev, 0); |
---|
1747 | 1783 | if (IS_ERR(gpu->mmio)) |
---|
1748 | 1784 | return PTR_ERR(gpu->mmio); |
---|
1749 | 1785 | |
---|
.. | .. |
---|
1762 | 1798 | } |
---|
1763 | 1799 | |
---|
1764 | 1800 | /* Get Clocks: */ |
---|
1765 | | - gpu->clk_reg = devm_clk_get(&pdev->dev, "reg"); |
---|
| 1801 | + gpu->clk_reg = devm_clk_get_optional(&pdev->dev, "reg"); |
---|
1766 | 1802 | DBG("clk_reg: %p", gpu->clk_reg); |
---|
1767 | 1803 | if (IS_ERR(gpu->clk_reg)) |
---|
1768 | | - gpu->clk_reg = NULL; |
---|
| 1804 | + return PTR_ERR(gpu->clk_reg); |
---|
1769 | 1805 | |
---|
1770 | | - gpu->clk_bus = devm_clk_get(&pdev->dev, "bus"); |
---|
| 1806 | + gpu->clk_bus = devm_clk_get_optional(&pdev->dev, "bus"); |
---|
1771 | 1807 | DBG("clk_bus: %p", gpu->clk_bus); |
---|
1772 | 1808 | if (IS_ERR(gpu->clk_bus)) |
---|
1773 | | - gpu->clk_bus = NULL; |
---|
| 1809 | + return PTR_ERR(gpu->clk_bus); |
---|
1774 | 1810 | |
---|
1775 | 1811 | gpu->clk_core = devm_clk_get(&pdev->dev, "core"); |
---|
1776 | 1812 | DBG("clk_core: %p", gpu->clk_core); |
---|
1777 | 1813 | if (IS_ERR(gpu->clk_core)) |
---|
1778 | | - gpu->clk_core = NULL; |
---|
| 1814 | + return PTR_ERR(gpu->clk_core); |
---|
1779 | 1815 | gpu->base_rate_core = clk_get_rate(gpu->clk_core); |
---|
1780 | 1816 | |
---|
1781 | | - gpu->clk_shader = devm_clk_get(&pdev->dev, "shader"); |
---|
| 1817 | + gpu->clk_shader = devm_clk_get_optional(&pdev->dev, "shader"); |
---|
1782 | 1818 | DBG("clk_shader: %p", gpu->clk_shader); |
---|
1783 | 1819 | if (IS_ERR(gpu->clk_shader)) |
---|
1784 | | - gpu->clk_shader = NULL; |
---|
| 1820 | + return PTR_ERR(gpu->clk_shader); |
---|
1785 | 1821 | gpu->base_rate_shader = clk_get_rate(gpu->clk_shader); |
---|
1786 | 1822 | |
---|
1787 | 1823 | /* TODO: figure out max mapped size */ |
---|
.. | .. |
---|
1818 | 1854 | struct etnaviv_gpu *gpu = dev_get_drvdata(dev); |
---|
1819 | 1855 | u32 idle, mask; |
---|
1820 | 1856 | |
---|
1821 | | - /* If we have outstanding fences, we're not idle */ |
---|
1822 | | - if (gpu->completed_fence != gpu->active_fence) |
---|
| 1857 | + /* If there are any jobs in the HW queue, we're not idle */ |
---|
| 1858 | + if (atomic_read(&gpu->sched.hw_rq_count)) |
---|
1823 | 1859 | return -EBUSY; |
---|
1824 | 1860 | |
---|
1825 | | - /* Check whether the hardware (except FE) is idle */ |
---|
1826 | | - mask = gpu->idle_mask & ~VIVS_HI_IDLE_STATE_FE; |
---|
| 1861 | + /* Check whether the hardware (except FE and MC) is idle */ |
---|
| 1862 | + mask = gpu->idle_mask & ~(VIVS_HI_IDLE_STATE_FE | |
---|
| 1863 | + VIVS_HI_IDLE_STATE_MC); |
---|
1827 | 1864 | idle = gpu_read(gpu, VIVS_HI_IDLE_STATE) & mask; |
---|
1828 | | - if (idle != mask) |
---|
| 1865 | + if (idle != mask) { |
---|
| 1866 | + dev_warn_ratelimited(dev, "GPU not yet idle, mask: 0x%08x\n", |
---|
| 1867 | + idle); |
---|
1829 | 1868 | return -EBUSY; |
---|
| 1869 | + } |
---|
1830 | 1870 | |
---|
1831 | 1871 | return etnaviv_gpu_hw_suspend(gpu); |
---|
1832 | 1872 | } |
---|
.. | .. |
---|
1841 | 1881 | return ret; |
---|
1842 | 1882 | |
---|
1843 | 1883 | /* Re-initialise the basic hardware state */ |
---|
1844 | | - if (gpu->drm && gpu->buffer.suballoc) { |
---|
| 1884 | + if (gpu->drm && gpu->initialized) { |
---|
1845 | 1885 | ret = etnaviv_gpu_hw_resume(gpu); |
---|
1846 | 1886 | if (ret) { |
---|
1847 | 1887 | etnaviv_gpu_clk_disable(gpu); |
---|