[airlied: make etnaviv build again] amdgpu: - DC trace support - More DC documentation - XGMI hive reset support - Rework IH interaction with KFD - Misc fixes and cleanups - Powerplay updates for newer polaris variants - Add cursor plane update fast path - Enable gpu reset by default on CI parts - Fix config with KFD/HSA not enabled amdkfd: - Limit vram overcommit - dmabuf support - Support for doorbell BOs ttm: - Support for simultaneous submissions to multiple engines scheduler: - Add helpers for hw with preemption support
Unified · Split
| @@ -82,6 +82,7 @@ · 81 unmodified lines | |||
| 82 | #include "amdgpu_bo_list.h" | 82 | #include "amdgpu_bo_list.h" |
| 83 | #include "amdgpu_gem.h" | 83 | #include "amdgpu_gem.h" |
| 84 | #include "amdgpu_doorbell.h" | 84 | #include "amdgpu_doorbell.h" |
| 85 | #include "amdgpu_amdkfd.h" | ||
| 85 | 86 | ||
| 86 | #define MAX_GPU_INSTANCE 16 | 87 | #define MAX_GPU_INSTANCE 16 |
| 87 | 88 | ||
| @@ -163,6 +164,7 @@ extern int amdgpu_si_support; · 75 unmodified lines | |||
| 163 | extern int amdgpu_cik_support; | 164 | extern int amdgpu_cik_support; |
| 164 | #endif | 165 | #endif |
| 165 | 166 | ||
| 167 | #define AMDGPU_VM_MAX_NUM_CTX 4096 | ||
| 166 | #define AMDGPU_SG_THRESHOLD (256*1024*1024) | 168 | #define AMDGPU_SG_THRESHOLD (256*1024*1024) |
| 167 | #define AMDGPU_DEFAULT_GTT_SIZE_MB 3072ULL /* 3GB by default */ | 169 | #define AMDGPU_DEFAULT_GTT_SIZE_MB 3072ULL /* 3GB by default */ |
| 168 | #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000 | 170 | #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000 |
| @@ -862,6 +864,9 @@ struct amdgpu_device { · 693 unmodified lines | |||
| 862 | /* GDS */ | 864 | /* GDS */ |
| 863 | struct amdgpu_gds gds; | 865 | struct amdgpu_gds gds; |
| 864 | 866 | ||
| 867 | /* KFD */ | ||
| 868 | struct amdgpu_kfd_dev kfd; | ||
| 869 | |||
| 865 | /* display related functionality */ | 870 | /* display related functionality */ |
| 866 | struct amdgpu_display_manager dm; | 871 | struct amdgpu_display_manager dm; |
| 867 | 872 | ||
| @@ -875,9 +880,6 @@ struct amdgpu_device { · 7 unmodified lines | |||
| 875 | atomic64_t visible_pin_size; | 880 | atomic64_t visible_pin_size; |
| 876 | atomic64_t gart_pin_size; | 881 | atomic64_t gart_pin_size; |
| 877 | 882 | ||
| 878 | /* amdkfd interface */ | ||
| 879 | struct kfd_dev *kfd; | ||
| 880 | |||
| 881 | /* soc15 register offset based on ip, instance and segment */ | 883 | /* soc15 register offset based on ip, instance and segment */ |
| 882 | uint32_t *reg_offset[MAX_HWIP][HWIP_MAX_INSTANCE]; | 884 | uint32_t *reg_offset[MAX_HWIP][HWIP_MAX_INSTANCE]; |
| 883 | 885 | ||
| @@ -910,7 +912,9 @@ struct amdgpu_device { · 26 unmodified lines | |||
| 910 | bool in_gpu_reset; | 912 | bool in_gpu_reset; |
| 911 | struct mutex lock_reset; | 913 | struct mutex lock_reset; |
| 912 | struct amdgpu_doorbell_index doorbell_index; | 914 | struct amdgpu_doorbell_index doorbell_index; |
| 915 | |||
| 913 | int asic_reset_res; | 916 | int asic_reset_res; |
| 917 | struct work_struct xgmi_reset_work; | ||
| 914 | }; | 918 | }; |
| 915 | 919 | ||
| 916 | static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev) | 920 | static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev) |
| @@ -886,6 +886,5 @@ void amdgpu_acpi_get_backlight_caps(struct amdgpu_device *adev, · 885 unmodified lines | |||
| 886 | void amdgpu_acpi_fini(struct amdgpu_device *adev) | 886 | void amdgpu_acpi_fini(struct amdgpu_device *adev) |
| 887 | { | 887 | { |
| 888 | unregister_acpi_notifier(&adev->acpi_nb); | 888 | unregister_acpi_notifier(&adev->acpi_nb); |
| 889 | if (adev->atif) | 889 | kfree(adev->atif); |
| 890 | kfree(adev->atif); | ||
| 891 | } | 890 | } |
| @@ -26,15 +26,26 @@ · 25 unmodified lines | |||
| 26 | #include "amdgpu.h" | 26 | #include "amdgpu.h" |
| 27 | #include "amdgpu_gfx.h" | 27 | #include "amdgpu_gfx.h" |
| 28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
| 29 | #include <linux/dma-buf.h> | ||
| 29 | 30 | ||
| 30 | const struct kgd2kfd_calls *kgd2kfd; | 31 | const struct kgd2kfd_calls *kgd2kfd; |
| 31 | 32 | ||
| 32 | static const unsigned int compute_vmid_bitmap = 0xFF00; | 33 | static const unsigned int compute_vmid_bitmap = 0xFF00; |
| 33 | 34 | ||
| 35 | /* Total memory size in system memory and all GPU VRAM. Used to | ||
| 36 | * estimate worst case amount of memory to reserve for page tables | ||
| 37 | */ | ||
| 38 | uint64_t amdgpu_amdkfd_total_mem_size; | ||
| 39 | |||
| 34 | int amdgpu_amdkfd_init(void) | 40 | int amdgpu_amdkfd_init(void) |
| 35 | { | 41 | { |
| 42 | struct sysinfo si; | ||
| 36 | int ret; | 43 | int ret; |
| 37 | 44 | ||
| 45 | si_meminfo(&si); | ||
| 46 | amdgpu_amdkfd_total_mem_size = si.totalram - si.totalhigh; | ||
| 47 | amdgpu_amdkfd_total_mem_size *= si.mem_unit; | ||
| 48 | |||
| 38 | #ifdef CONFIG_HSA_AMD | 49 | #ifdef CONFIG_HSA_AMD |
| 39 | ret = kgd2kfd_init(KFD_INTERFACE_VERSION, &kgd2kfd); | 50 | ret = kgd2kfd_init(KFD_INTERFACE_VERSION, &kgd2kfd); |
| 40 | if (ret) | 51 | if (ret) |
| @@ -87,8 +98,11 @@ void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev) · 46 unmodified lines | |||
| 87 | return; | 98 | return; |
| 88 | } | 99 | } |
| 89 | 100 | ||
| 90 | adev->kfd = kgd2kfd->probe((struct kgd_dev *)adev, | 101 | adev->kfd.dev = kgd2kfd->probe((struct kgd_dev *)adev, |
| 91 | adev->pdev, kfd2kgd); | 102 | adev->pdev, kfd2kgd); |
| 103 | |||
| 104 | if (adev->kfd.dev) | ||
| 105 | amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size; | ||
| 92 | } | 106 | } |
| 93 | 107 | ||
| 94 | /** | 108 | /** |
| @@ -128,7 +142,8 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev) · 33 unmodified lines | |||
| 128 | { | 142 | { |
| 129 | int i, n; | 143 | int i, n; |
| 130 | int last_valid_bit; | 144 | int last_valid_bit; |
| 131 | if (adev->kfd) { | 145 | |
| 146 | if (adev->kfd.dev) { | ||
| 132 | struct kgd2kfd_shared_resources gpu_resources = { | 147 | struct kgd2kfd_shared_resources gpu_resources = { |
| 133 | .compute_vmid_bitmap = compute_vmid_bitmap, | 148 | .compute_vmid_bitmap = compute_vmid_bitmap, |
| 134 | .num_pipe_per_mec = adev->gfx.mec.num_pipe_per_mec, | 149 | .num_pipe_per_mec = adev->gfx.mec.num_pipe_per_mec, |
| @@ -167,7 +182,7 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev) · 32 unmodified lines | |||
| 167 | &gpu_resources.doorbell_start_offset); | 182 | &gpu_resources.doorbell_start_offset); |
| 168 | 183 | ||
| 169 | if (adev->asic_type < CHIP_VEGA10) { | 184 | if (adev->asic_type < CHIP_VEGA10) { |
| 170 | kgd2kfd->device_init(adev->kfd, &gpu_resources); | 185 | kgd2kfd->device_init(adev->kfd.dev, &gpu_resources); |
| 171 | return; | 186 | return; |
| 172 | } | 187 | } |
| 173 | 188 | ||
| @@ -196,37 +211,37 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev) · 22 unmodified lines | |||
| 196 | gpu_resources.reserved_doorbell_mask = 0x1e0; | 211 | gpu_resources.reserved_doorbell_mask = 0x1e0; |
| 197 | gpu_resources.reserved_doorbell_val = 0x0e0; | 212 | gpu_resources.reserved_doorbell_val = 0x0e0; |
| 198 | 213 | ||
| 199 | kgd2kfd->device_init(adev->kfd, &gpu_resources); | 214 | kgd2kfd->device_init(adev->kfd.dev, &gpu_resources); |
| 200 | } | 215 | } |
| 201 | } | 216 | } |
| 202 | 217 | ||
| 203 | void amdgpu_amdkfd_device_fini(struct amdgpu_device *adev) | 218 | void amdgpu_amdkfd_device_fini(struct amdgpu_device *adev) |
| 204 | { | 219 | { |
| 205 | if (adev->kfd) { | 220 | if (adev->kfd.dev) { |
| 206 | kgd2kfd->device_exit(adev->kfd); | 221 | kgd2kfd->device_exit(adev->kfd.dev); |
| 207 | adev->kfd = NULL; | 222 | adev->kfd.dev = NULL; |
| 208 | } | 223 | } |
| 209 | } | 224 | } |
| 210 | 225 | ||
| 211 | void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev, | 226 | void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev, |
| 212 | const void *ih_ring_entry) | 227 | const void *ih_ring_entry) |
| 213 | { | 228 | { |
| 214 | if (adev->kfd) | 229 | if (adev->kfd.dev) |
| 215 | kgd2kfd->interrupt(adev->kfd, ih_ring_entry); | 230 | kgd2kfd->interrupt(adev->kfd.dev, ih_ring_entry); |
| 216 | } | 231 | } |
| 217 | 232 | ||
| 218 | void amdgpu_amdkfd_suspend(struct amdgpu_device *adev) | 233 | void amdgpu_amdkfd_suspend(struct amdgpu_device *adev) |
| 219 | { | 234 | { |
| 220 | if (adev->kfd) | 235 | if (adev->kfd.dev) |
| 221 | kgd2kfd->suspend(adev->kfd); | 236 | kgd2kfd->suspend(adev->kfd.dev); |
| 222 | } | 237 | } |
| 223 | 238 | ||
| 224 | int amdgpu_amdkfd_resume(struct amdgpu_device *adev) | 239 | int amdgpu_amdkfd_resume(struct amdgpu_device *adev) |
| 225 | { | 240 | { |
| 226 | int r = 0; | 241 | int r = 0; |
| 227 | 242 | ||
| 228 | if (adev->kfd) | 243 | if (adev->kfd.dev) |
| 229 | r = kgd2kfd->resume(adev->kfd); | 244 | r = kgd2kfd->resume(adev->kfd.dev); |
| 230 | 245 | ||
| 231 | return r; | 246 | return r; |
| 232 | } | 247 | } |
| @@ -235,8 +250,8 @@ int amdgpu_amdkfd_pre_reset(struct amdgpu_device *adev) · 2 unmodified lines | |||
| 235 | { | 250 | { |
| 236 | int r = 0; | 251 | int r = 0; |
| 237 | 252 | ||
| 238 | if (adev->kfd) | 253 | if (adev->kfd.dev) |
| 239 | r = kgd2kfd->pre_reset(adev->kfd); | 254 | r = kgd2kfd->pre_reset(adev->kfd.dev); |
| 240 | 255 | ||
| 241 | return r; | 256 | return r; |
| 242 | } | 257 | } |
| @@ -245,8 +260,8 @@ int amdgpu_amdkfd_post_reset(struct amdgpu_device *adev) · 2 unmodified lines | |||
| 245 | { | 260 | { |
| 246 | int r = 0; | 261 | int r = 0; |
| 247 | 262 | ||
| 248 | if (adev->kfd) | 263 | if (adev->kfd.dev) |
| 249 | r = kgd2kfd->post_reset(adev->kfd); | 264 | r = kgd2kfd->post_reset(adev->kfd.dev); |
| 250 | 265 | ||
| 251 | return r; | 266 | return r; |
| 252 | } | 267 | } |
| @@ -419,6 +434,62 @@ void amdgpu_amdkfd_get_cu_info(struct kgd_dev *kgd, struct kfd_cu_info *cu_info) · 166 unmodified lines | |||
| 419 | cu_info->lds_size = acu_info.lds_size; | 434 | cu_info->lds_size = acu_info.lds_size; |
| 420 | } | 435 | } |
| 421 | 436 | ||
| 437 | int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd, | ||
| 438 | struct kgd_dev **dma_buf_kgd, | ||
| 439 | uint64_t *bo_size, void *metadata_buffer, | ||
| 440 | size_t buffer_size, uint32_t *metadata_size, | ||
| 441 | uint32_t *flags) | ||
| 442 | { | ||
| 443 | struct amdgpu_device *adev = (struct amdgpu_device *)kgd; | ||
| 444 | struct dma_buf *dma_buf; | ||
| 445 | struct drm_gem_object *obj; | ||
| 446 | struct amdgpu_bo *bo; | ||
| 447 | uint64_t metadata_flags; | ||
| 448 | int r = -EINVAL; | ||
| 449 | |||
| 450 | dma_buf = dma_buf_get(dma_buf_fd); | ||
| 451 | if (IS_ERR(dma_buf)) | ||
| 452 | return PTR_ERR(dma_buf); | ||
| 453 | |||
| 454 | if (dma_buf->ops != &amdgpu_dmabuf_ops) | ||
| 455 | /* Can't handle non-graphics buffers */ | ||
| 456 | goto out_put; | ||
| 457 | |||
| 458 | obj = dma_buf->priv; | ||
| 459 | if (obj->dev->driver != adev->ddev->driver) | ||
| 460 | /* Can't handle buffers from different drivers */ | ||
| 461 | goto out_put; | ||
| 462 | |||
| 463 | adev = obj->dev->dev_private; | ||
| 464 | bo = gem_to_amdgpu_bo(obj); | ||
| 465 | if (!(bo->preferred_domains & (AMDGPU_GEM_DOMAIN_VRAM | | ||
| 466 | AMDGPU_GEM_DOMAIN_GTT))) | ||
| 467 | /* Only VRAM and GTT BOs are supported */ | ||
| 468 | goto out_put; | ||
| 469 | |||
| 470 | r = 0; | ||
| 471 | if (dma_buf_kgd) | ||
| 472 | *dma_buf_kgd = (struct kgd_dev *)adev; | ||
| 473 | if (bo_size) | ||
| 474 | *bo_size = amdgpu_bo_size(bo); | ||
| 475 | if (metadata_size) | ||
| 476 | *metadata_size = bo->metadata_size; | ||
| 477 | if (metadata_buffer) | ||
| 478 | r = amdgpu_bo_get_metadata(bo, metadata_buffer, buffer_size, | ||
| 479 | metadata_size, &metadata_flags); | ||
| 480 | if (flags) { | ||
| 481 | *flags = (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) ? | ||
| 482 | ALLOC_MEM_FLAGS_VRAM : ALLOC_MEM_FLAGS_GTT; | ||
| 483 | |||
| 484 | if (bo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) | ||
| 485 | *flags |= ALLOC_MEM_FLAGS_PUBLIC; | ||
| 486 | } | ||
| 487 | |||
| 488 | out_put: | ||
| 489 | dma_buf_put(dma_buf); | ||
| 490 | return r; | ||
| 491 | } | ||
| 492 | |||
| 422 | uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd) | 493 | uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd) |
| 423 | { | 494 | { |
| 424 | struct amdgpu_device *adev = (struct amdgpu_device *)kgd; | 495 | struct amdgpu_device *adev = (struct amdgpu_device *)kgd; |
| @@ -501,7 +572,7 @@ void amdgpu_amdkfd_set_compute_idle(struct kgd_dev *kgd, bool idle) · 76 unmodified lines | |||
| 501 | 572 | ||
| 502 | bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid) | 573 | bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid) |
| 503 | { | 574 | { |
| 504 | if (adev->kfd) { | 575 | if (adev->kfd.dev) { |
| 505 | if ((1 << vmid) & compute_vmid_bitmap) | 576 | if ((1 << vmid) & compute_vmid_bitmap) |
| 506 | return true; | 577 | return true; |
| 507 | } | 578 | } |
| @@ -515,7 +586,7 @@ bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm) · 7 unmodified lines | |||
| 515 | return false; | 586 | return false; |
| 516 | } | 587 | } |
| 517 | 588 | ||
| 518 | void amdgpu_amdkfd_unreserve_system_memory_limit(struct amdgpu_bo *bo) | 589 | void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo) |
| 519 | { | 590 | { |
| 520 | } | 591 | } |
| 521 | 592 | ||
| @@ -27,7 +27,6 @@ · 26 unmodified lines | |||
| 27 | 27 | ||
| 28 | #include <linux/types.h> | 28 | #include <linux/types.h> |
| 29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
| 30 | #include <linux/mmu_context.h> | ||
| 31 | #include <linux/workqueue.h> | 30 | #include <linux/workqueue.h> |
| 32 | #include <kgd_kfd_interface.h> | 31 | #include <kgd_kfd_interface.h> |
| 33 | #include <drm/ttm/ttm_execbuf_util.h> | 32 | #include <drm/ttm/ttm_execbuf_util.h> |
| @@ -35,6 +34,7 @@ · 1 unmodified line | |||
| 35 | #include "amdgpu_vm.h" | 34 | #include "amdgpu_vm.h" |
| 36 | 35 | ||
| 37 | extern const struct kgd2kfd_calls *kgd2kfd; | 36 | extern const struct kgd2kfd_calls *kgd2kfd; |
| 37 | extern uint64_t amdgpu_amdkfd_total_mem_size; | ||
| 38 | 38 | ||
| 39 | struct amdgpu_device; | 39 | struct amdgpu_device; |
| 40 | 40 | ||
| @@ -77,6 +77,11 @@ struct amdgpu_amdkfd_fence { · 36 unmodified lines | |||
| 77 | char timeline_name[TASK_COMM_LEN]; | 77 | char timeline_name[TASK_COMM_LEN]; |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
| 80 | struct amdgpu_kfd_dev { | ||
| 81 | struct kfd_dev *dev; | ||
| 82 | uint64_t vram_used; | ||
| 83 | }; | ||
| 84 | |||
| 80 | struct amdgpu_amdkfd_fence *amdgpu_amdkfd_fence_create(u64 context, | 85 | struct amdgpu_amdkfd_fence *amdgpu_amdkfd_fence_create(u64 context, |
| 81 | struct mm_struct *mm); | 86 | struct mm_struct *mm); |
| 82 | bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm); | 87 | bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm); |
| @@ -144,6 +149,11 @@ uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct kgd_dev *kgd); · 61 unmodified lines | |||
| 144 | 149 | ||
| 145 | uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct kgd_dev *kgd); | 150 | uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct kgd_dev *kgd); |
| 146 | void amdgpu_amdkfd_get_cu_info(struct kgd_dev *kgd, struct kfd_cu_info *cu_info); | 151 | void amdgpu_amdkfd_get_cu_info(struct kgd_dev *kgd, struct kfd_cu_info *cu_info); |
| 152 | int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd, | ||
| 153 | struct kgd_dev **dmabuf_kgd, | ||
| 154 | uint64_t *bo_size, void *metadata_buffer, | ||
| 155 | size_t buffer_size, uint32_t *metadata_size, | ||
| 156 | uint32_t *flags); | ||
| 147 | uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd); | 157 | uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd); |
| 148 | uint64_t amdgpu_amdkfd_get_hive_id(struct kgd_dev *kgd); | 158 | uint64_t amdgpu_amdkfd_get_hive_id(struct kgd_dev *kgd); |
| 149 | 159 | ||
| @@ -195,7 +205,13 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info, · 45 unmodified lines | |||
| 195 | int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd, | 205 | int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd, |
| 196 | struct kfd_vm_fault_info *info); | 206 | struct kfd_vm_fault_info *info); |
| 197 | 207 | ||
| 208 | int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd, | ||
| 209 | struct dma_buf *dmabuf, | ||
| 210 | uint64_t va, void *vm, | ||
| 211 | struct kgd_mem **mem, uint64_t *size, | ||
| 212 | uint64_t *mmap_offset); | ||
| 213 | |||
| 198 | void amdgpu_amdkfd_gpuvm_init_mem_limits(void); | 214 | void amdgpu_amdkfd_gpuvm_init_mem_limits(void); |
| 199 | void amdgpu_amdkfd_unreserve_system_memory_limit(struct amdgpu_bo *bo); | 215 | void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo); |
| 200 | 216 | ||
| 201 | #endif /* AMDGPU_AMDKFD_H_INCLUDED */ | 217 | #endif /* AMDGPU_AMDKFD_H_INCLUDED */ |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | |||
| 23 | #include <linux/fdtable.h> | 23 | #include <linux/fdtable.h> |
| 24 | #include <linux/uaccess.h> | 24 | #include <linux/uaccess.h> |
| 25 | #include <linux/firmware.h> | 25 | #include <linux/firmware.h> |
| 26 | #include <linux/mmu_context.h> | ||
| 26 | #include <drm/drmP.h> | 27 | #include <drm/drmP.h> |
| 27 | #include "amdgpu.h" | 28 | #include "amdgpu.h" |
| 28 | #include "amdgpu_amdkfd.h" | 29 | #include "amdgpu_amdkfd.h" |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | |||
| 24 | #include <linux/fdtable.h> | 24 | #include <linux/fdtable.h> |
| 25 | #include <linux/uaccess.h> | 25 | #include <linux/uaccess.h> |
| 26 | #include <linux/firmware.h> | 26 | #include <linux/firmware.h> |
| 27 | #include <linux/mmu_context.h> | ||
| 27 | #include <drm/drmP.h> | 28 | #include <drm/drmP.h> |
| 28 | #include "amdgpu.h" | 29 | #include "amdgpu.h" |
| 29 | #include "amdgpu_amdkfd.h" | 30 | #include "amdgpu_amdkfd.h" |
| @@ -26,6 +26,7 @@ · 25 unmodified lines | |||
| 26 | #include <linux/fdtable.h> | 26 | #include <linux/fdtable.h> |
| 27 | #include <linux/uaccess.h> | 27 | #include <linux/uaccess.h> |
| 28 | #include <linux/firmware.h> | 28 | #include <linux/firmware.h> |
| 29 | #include <linux/mmu_context.h> | ||
| 29 | #include <drm/drmP.h> | 30 | #include <drm/drmP.h> |
| 30 | #include "amdgpu.h" | 31 | #include "amdgpu.h" |
| 31 | #include "amdgpu_amdkfd.h" | 32 | #include "amdgpu_amdkfd.h" |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | |||
| 25 | #include <linux/list.h> | 25 | #include <linux/list.h> |
| 26 | #include <linux/pagemap.h> | 26 | #include <linux/pagemap.h> |
| 27 | #include <linux/sched/mm.h> | 27 | #include <linux/sched/mm.h> |
| 28 | #include <linux/dma-buf.h> | ||
| 28 | #include <drm/drmP.h> | 29 | #include <drm/drmP.h> |
| 29 | #include "amdgpu_object.h" | 30 | #include "amdgpu_object.h" |
| 30 | #include "amdgpu_vm.h" | 31 | #include "amdgpu_vm.h" |
| @@ -110,17 +111,17 @@ void amdgpu_amdkfd_gpuvm_init_mem_limits(void) · 79 unmodified lines | |||
| 110 | (kfd_mem_limit.max_ttm_mem_limit >> 20)); | 111 | (kfd_mem_limit.max_ttm_mem_limit >> 20)); |
| 111 | } | 112 | } |
| 112 | 113 | ||
| 113 | static int amdgpu_amdkfd_reserve_system_mem_limit(struct amdgpu_device *adev, | 114 | static int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev, |
| 114 | uint64_t size, u32 domain, bool sg) | 115 | uint64_t size, u32 domain, bool sg) |
| 115 | { | 116 | { |
| 116 | size_t acc_size, system_mem_needed, ttm_mem_needed; | 117 | size_t acc_size, system_mem_needed, ttm_mem_needed, vram_needed; |
| 118 | uint64_t reserved_for_pt = amdgpu_amdkfd_total_mem_size >> 9; | ||
| 117 | int ret = 0; | 119 | int ret = 0; |
| 118 | 120 | ||
| 119 | acc_size = ttm_bo_dma_acc_size(&adev->mman.bdev, size, | 121 | acc_size = ttm_bo_dma_acc_size(&adev->mman.bdev, size, |
| 120 | sizeof(struct amdgpu_bo)); | 122 | sizeof(struct amdgpu_bo)); |
| 121 | 123 | ||
| 122 | spin_lock(&kfd_mem_limit.mem_limit_lock); | 124 | vram_needed = 0; |
| 123 | |||
| 124 | if (domain == AMDGPU_GEM_DOMAIN_GTT) { | 125 | if (domain == AMDGPU_GEM_DOMAIN_GTT) { |
| 125 | /* TTM GTT memory */ | 126 | /* TTM GTT memory */ |
| 126 | system_mem_needed = acc_size + size; | 127 | system_mem_needed = acc_size + size; |
| @@ -133,23 +134,30 @@ static int amdgpu_amdkfd_reserve_system_mem_limit(struct amdgpu_device *adev, · 6 unmodified lines | |||
| 133 | /* VRAM and SG */ | 134 | /* VRAM and SG */ |
| 134 | system_mem_needed = acc_size; | 135 | system_mem_needed = acc_size; |
| 135 | ttm_mem_needed = acc_size; | 136 | ttm_mem_needed = acc_size; |
| 137 | if (domain == AMDGPU_GEM_DOMAIN_VRAM) | ||
| 138 | vram_needed = size; | ||
| 136 | } | 139 | } |
| 137 | 140 | ||
| 141 | spin_lock(&kfd_mem_limit.mem_limit_lock); | ||
| 142 | |||
| 138 | if ((kfd_mem_limit.system_mem_used + system_mem_needed > | 143 | if ((kfd_mem_limit.system_mem_used + system_mem_needed > |
| 139 | kfd_mem_limit.max_system_mem_limit) || | 144 | kfd_mem_limit.max_system_mem_limit) || |
| 140 | (kfd_mem_limit.ttm_mem_used + ttm_mem_needed > | 145 | (kfd_mem_limit.ttm_mem_used + ttm_mem_needed > |
| 141 | kfd_mem_limit.max_ttm_mem_limit)) | 146 | kfd_mem_limit.max_ttm_mem_limit) || |
| 147 | (adev->kfd.vram_used + vram_needed > | ||
| 148 | adev->gmc.real_vram_size - reserved_for_pt)) { | ||
| 142 | ret = -ENOMEM; | 149 | ret = -ENOMEM; |
| 143 | else { | 150 | } else { |
| 144 | kfd_mem_limit.system_mem_used += system_mem_needed; | 151 | kfd_mem_limit.system_mem_used += system_mem_needed; |
| 145 | kfd_mem_limit.ttm_mem_used += ttm_mem_needed; | 152 | kfd_mem_limit.ttm_mem_used += ttm_mem_needed; |
| 153 | adev->kfd.vram_used += vram_needed; | ||
| 146 | } | 154 | } |
| 147 | 155 | ||
| 148 | spin_unlock(&kfd_mem_limit.mem_limit_lock); | 156 | spin_unlock(&kfd_mem_limit.mem_limit_lock); |
| 149 | return ret; | 157 | return ret; |
| 150 | } | 158 | } |
| 151 | 159 | ||
| 152 | static void unreserve_system_mem_limit(struct amdgpu_device *adev, | 160 | static void unreserve_mem_limit(struct amdgpu_device *adev, |
| 153 | uint64_t size, u32 domain, bool sg) | 161 | uint64_t size, u32 domain, bool sg) |
| 154 | { | 162 | { |
| 155 | size_t acc_size; | 163 | size_t acc_size; |
| @@ -167,6 +175,11 @@ static void unreserve_system_mem_limit(struct amdgpu_device *adev, · 11 unmodified lines | |||
| 167 | } else { | 175 | } else { |
| 168 | kfd_mem_limit.system_mem_used -= acc_size; | 176 | kfd_mem_limit.system_mem_used -= acc_size; |
| 169 | kfd_mem_limit.ttm_mem_used -= acc_size; | 177 | kfd_mem_limit.ttm_mem_used -= acc_size; |
| 178 | if (domain == AMDGPU_GEM_DOMAIN_VRAM) { | ||
| 179 | adev->kfd.vram_used -= size; | ||
| 180 | WARN_ONCE(adev->kfd.vram_used < 0, | ||
| 181 | "kfd VRAM memory accounting unbalanced"); | ||
| 182 | } | ||
| 170 | } | 183 | } |
| 171 | WARN_ONCE(kfd_mem_limit.system_mem_used < 0, | 184 | WARN_ONCE(kfd_mem_limit.system_mem_used < 0, |
| 172 | "kfd system memory accounting unbalanced"); | 185 | "kfd system memory accounting unbalanced"); |
| @@ -176,29 +189,18 @@ static void unreserve_system_mem_limit(struct amdgpu_device *adev, · 3 unmodified lines | |||
| 176 | spin_unlock(&kfd_mem_limit.mem_limit_lock); | 189 | spin_unlock(&kfd_mem_limit.mem_limit_lock); |
| 177 | } | 190 | } |
| 178 | 191 | ||
| 179 | void amdgpu_amdkfd_unreserve_system_memory_limit(struct amdgpu_bo *bo) | 192 | void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo) |
| 180 | { | 193 | { |
| 181 | spin_lock(&kfd_mem_limit.mem_limit_lock); | 194 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); |
| 195 | u32 domain = bo->preferred_domains; | ||
| 196 | bool sg = (bo->preferred_domains == AMDGPU_GEM_DOMAIN_CPU); | ||
| 182 | 197 | ||
| 183 | if (bo->flags & AMDGPU_AMDKFD_USERPTR_BO) { | 198 | if (bo->flags & AMDGPU_AMDKFD_USERPTR_BO) { |
| 184 | kfd_mem_limit.system_mem_used -= | 199 | domain = AMDGPU_GEM_DOMAIN_CPU; |
| 185 | (bo->tbo.acc_size + amdgpu_bo_size(bo)); | 200 | sg = false; |
| 186 | kfd_mem_limit.ttm_mem_used -= bo->tbo.acc_size; | ||
| 187 | } else if (bo->preferred_domains == AMDGPU_GEM_DOMAIN_GTT) { | ||
| 188 | kfd_mem_limit.system_mem_used -= | ||
| 189 | (bo->tbo.acc_size + amdgpu_bo_size(bo)); | ||
| 190 | kfd_mem_limit.ttm_mem_used -= | ||
| 191 | (bo->tbo.acc_size + amdgpu_bo_size(bo)); | ||
| 192 | } else { | ||
| 193 | kfd_mem_limit.system_mem_used -= bo->tbo.acc_size; | ||
| 194 | kfd_mem_limit.ttm_mem_used -= bo->tbo.acc_size; | ||
| 195 | } | 201 | } |
| 196 | WARN_ONCE(kfd_mem_limit.system_mem_used < 0, | ||
| 197 | "kfd system memory accounting unbalanced"); | ||
| 198 | WARN_ONCE(kfd_mem_limit.ttm_mem_used < 0, | ||
| 199 | "kfd TTM memory accounting unbalanced"); | ||
| 200 | 202 | ||
| 201 | spin_unlock(&kfd_mem_limit.mem_limit_lock); | 203 | unreserve_mem_limit(adev, amdgpu_bo_size(bo), domain, sg); |
| 202 | } | 204 | } |
| 203 | 205 | ||
| 204 | 206 | ||
| @@ -535,7 +537,7 @@ static void add_kgd_mem_to_kfd_bo_list(struct kgd_mem *mem, · 330 unmodified lines | |||
| 535 | struct amdgpu_bo *bo = mem->bo; | 537 | struct amdgpu_bo *bo = mem->bo; |
| 536 | 538 | ||
| 537 | INIT_LIST_HEAD(&entry->head); | 539 | INIT_LIST_HEAD(&entry->head); |
| 538 | entry->shared = true; | 540 | entry->num_shared = 1; |
| 539 | entry->bo = &bo->tbo; | 541 | entry->bo = &bo->tbo; |
| 540 | mutex_lock(&process_info->lock); | 542 | mutex_lock(&process_info->lock); |
| 541 | if (userptr) | 543 | if (userptr) |
| @@ -676,7 +678,7 @@ static int reserve_bo_and_vm(struct kgd_mem *mem, · 134 unmodified lines | |||
| 676 | 678 | ||
| 677 | ctx->kfd_bo.priority = 0; | 679 | ctx->kfd_bo.priority = 0; |
| 678 | ctx->kfd_bo.tv.bo = &bo->tbo; | 680 | ctx->kfd_bo.tv.bo = &bo->tbo; |
| 679 | ctx->kfd_bo.tv.shared = true; | 681 | ctx->kfd_bo.tv.num_shared = 1; |
| 680 | ctx->kfd_bo.user_pages = NULL; | 682 | ctx->kfd_bo.user_pages = NULL; |
| 681 | list_add(&ctx->kfd_bo.tv.head, &ctx->list); | 683 | list_add(&ctx->kfd_bo.tv.head, &ctx->list); |
| 682 | 684 | ||
| @@ -740,7 +742,7 @@ static int reserve_bo_and_cond_vms(struct kgd_mem *mem, · 57 unmodified lines | |||
| 740 | 742 | ||
| 741 | ctx->kfd_bo.priority = 0; | 743 | ctx->kfd_bo.priority = 0; |
| 742 | ctx->kfd_bo.tv.bo = &bo->tbo; | 744 | ctx->kfd_bo.tv.bo = &bo->tbo; |
| 743 | ctx->kfd_bo.tv.shared = true; | 745 | ctx->kfd_bo.tv.num_shared = 1; |
| 744 | ctx->kfd_bo.user_pages = NULL; | 746 | ctx->kfd_bo.user_pages = NULL; |
| 745 | list_add(&ctx->kfd_bo.tv.head, &ctx->list); | 747 | list_add(&ctx->kfd_bo.tv.head, &ctx->list); |
| 746 | 748 | ||
| @@ -885,6 +887,24 @@ update_gpuvm_pte_failed: · 138 unmodified lines | |||
| 885 | return ret; | 887 | return ret; |
| 886 | } | 888 | } |
| 887 | 889 | ||
| 890 | static struct sg_table *create_doorbell_sg(uint64_t addr, uint32_t size) | ||
| 891 | { | ||
| 892 | struct sg_table *sg = kmalloc(sizeof(*sg), GFP_KERNEL); | ||
| 893 | |||
| 894 | if (!sg) | ||
| 895 | return NULL; | ||
| 896 | if (sg_alloc_table(sg, 1, GFP_KERNEL)) { | ||
| 897 | kfree(sg); | ||
| 898 | return NULL; | ||
| 899 | } | ||
| 900 | sg->sgl->dma_address = addr; | ||
| 901 | sg->sgl->length = size; | ||
| 902 | #ifdef CONFIG_NEED_SG_DMA_LENGTH | ||
| 903 | sg->sgl->dma_length = size; | ||
| 904 | #endif | ||
| 905 | return sg; | ||
| 906 | } | ||
| 907 | |||
| 888 | static int process_validate_vms(struct amdkfd_process_info *process_info) | 908 | static int process_validate_vms(struct amdkfd_process_info *process_info) |
| 889 | { | 909 | { |
| 890 | struct amdgpu_vm *peer_vm; | 910 | struct amdgpu_vm *peer_vm; |
| @@ -1168,6 +1188,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( · 277 unmodified lines | |||
| 1168 | { | 1188 | { |
| 1169 | struct amdgpu_device *adev = get_amdgpu_device(kgd); | 1189 | struct amdgpu_device *adev = get_amdgpu_device(kgd); |
| 1170 | struct amdgpu_vm *avm = (struct amdgpu_vm *)vm; | 1190 | struct amdgpu_vm *avm = (struct amdgpu_vm *)vm; |
| 1191 | enum ttm_bo_type bo_type = ttm_bo_type_device; | ||
| 1192 | struct sg_table *sg = NULL; | ||
| 1171 | uint64_t user_addr = 0; | 1193 | uint64_t user_addr = 0; |
| 1172 | struct amdgpu_bo *bo; | 1194 | struct amdgpu_bo *bo; |
| 1173 | struct amdgpu_bo_param bp; | 1195 | struct amdgpu_bo_param bp; |
| @@ -1196,13 +1218,25 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( · 22 unmodified lines | |||
| 1196 | if (!offset || !*offset) | 1218 | if (!offset || !*offset) |
| 1197 | return -EINVAL; | 1219 | return -EINVAL; |
| 1198 | user_addr = *offset; | 1220 | user_addr = *offset; |
| 1221 | } else if (flags & ALLOC_MEM_FLAGS_DOORBELL) { | ||
| 1222 | domain = AMDGPU_GEM_DOMAIN_GTT; | ||
| 1223 | alloc_domain = AMDGPU_GEM_DOMAIN_CPU; | ||
| 1224 | bo_type = ttm_bo_type_sg; | ||
| 1225 | alloc_flags = 0; | ||
| 1226 | if (size > UINT_MAX) | ||
| 1227 | return -EINVAL; | ||
| 1228 | sg = create_doorbell_sg(*offset, size); | ||
| 1229 | if (!sg) | ||
| 1230 | return -ENOMEM; | ||
| 1199 | } else { | 1231 | } else { |
| 1200 | return -EINVAL; | 1232 | return -EINVAL; |
| 1201 | } | 1233 | } |
| 1202 | 1234 | ||
| 1203 | *mem = kzalloc(sizeof(struct kgd_mem), GFP_KERNEL); | 1235 | *mem = kzalloc(sizeof(struct kgd_mem), GFP_KERNEL); |
| 1204 | if (!*mem) | 1236 | if (!*mem) { |
| 1205 | return -ENOMEM; | 1237 | ret = -ENOMEM; |
| 1238 | goto err; | ||
| 1239 | } | ||
| 1206 | INIT_LIST_HEAD(&(*mem)->bo_va_list); | 1240 | INIT_LIST_HEAD(&(*mem)->bo_va_list); |
| 1207 | mutex_init(&(*mem)->lock); | 1241 | mutex_init(&(*mem)->lock); |
| 1208 | (*mem)->aql_queue = !!(flags & ALLOC_MEM_FLAGS_AQL_QUEUE_MEM); | 1242 | (*mem)->aql_queue = !!(flags & ALLOC_MEM_FLAGS_AQL_QUEUE_MEM); |
| @@ -1235,8 +1269,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( · 26 unmodified lines | |||
| 1235 | 1269 | ||
| 1236 | amdgpu_sync_create(&(*mem)->sync); | 1270 | amdgpu_sync_create(&(*mem)->sync); |
| 1237 | 1271 | ||
| 1238 | ret = amdgpu_amdkfd_reserve_system_mem_limit(adev, size, | 1272 | ret = amdgpu_amdkfd_reserve_mem_limit(adev, size, alloc_domain, !!sg); |
| 1239 | alloc_domain, false); | ||
| 1240 | if (ret) { | 1273 | if (ret) { |
| 1241 | pr_debug("Insufficient system memory\n"); | 1274 | pr_debug("Insufficient system memory\n"); |
| 1242 | goto err_reserve_limit; | 1275 | goto err_reserve_limit; |
| @@ -1250,7 +1283,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( · 7 unmodified lines | |||
| 1250 | bp.byte_align = byte_align; | 1283 | bp.byte_align = byte_align; |
| 1251 | bp.domain = alloc_domain; | 1284 | bp.domain = alloc_domain; |
| 1252 | bp.flags = alloc_flags; | 1285 | bp.flags = alloc_flags; |
| 1253 | bp.type = ttm_bo_type_device; | 1286 | bp.type = bo_type; |
| 1254 | bp.resv = NULL; | 1287 | bp.resv = NULL; |
| 1255 | ret = amdgpu_bo_create(adev, &bp, &bo); | 1288 | ret = amdgpu_bo_create(adev, &bp, &bo); |
| 1256 | if (ret) { | 1289 | if (ret) { |
| @@ -1258,6 +1291,10 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( · 1 unmodified line | |||
| 1258 | domain_string(alloc_domain), ret); | 1291 | domain_string(alloc_domain), ret); |
| 1259 | goto err_bo_create; | 1292 | goto err_bo_create; |
| 1260 | } | 1293 | } |
| 1294 | if (bo_type == ttm_bo_type_sg) { | ||
| 1295 | bo->tbo.sg = sg; | ||
| 1296 | bo->tbo.ttm->sg = sg; | ||
| 1297 | } | ||
| 1261 | bo->kfd_bo = *mem; | 1298 | bo->kfd_bo = *mem; |
| 1262 | (*mem)->bo = bo; | 1299 | (*mem)->bo = bo; |
| 1263 | if (user_addr) | 1300 | if (user_addr) |
| @@ -1289,10 +1326,15 @@ allocate_init_user_pages_failed: · 25 unmodified lines | |||
| 1289 | /* Don't unreserve system mem limit twice */ | 1326 | /* Don't unreserve system mem limit twice */ |
| 1290 | goto err_reserve_limit; | 1327 | goto err_reserve_limit; |
| 1291 | err_bo_create: | 1328 | err_bo_create: |
| 1292 | unreserve_system_mem_limit(adev, size, alloc_domain, false); | 1329 | unreserve_mem_limit(adev, size, alloc_domain, !!sg); |
| 1293 | err_reserve_limit: | 1330 | err_reserve_limit: |
| 1294 | mutex_destroy(&(*mem)->lock); | 1331 | mutex_destroy(&(*mem)->lock); |
| 1295 | kfree(*mem); | 1332 | kfree(*mem); |
| 1333 | err: | ||
| 1334 | if (sg) { | ||
| 1335 | sg_free_table(sg); | ||
| 1336 | kfree(sg); | ||
| 1337 | } | ||
| 1296 | return ret; | 1338 | return ret; |
| 1297 | } | 1339 | } |
| 1298 | 1340 | ||
| @@ -1362,6 +1404,14 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu( · 63 unmodified lines | |||
| 1362 | /* Free the sync object */ | 1404 | /* Free the sync object */ |
| 1363 | amdgpu_sync_free(&mem->sync); | 1405 | amdgpu_sync_free(&mem->sync); |
| 1364 | 1406 | ||
| 1407 | /* If the SG is not NULL, it's one we created for a doorbell | ||
| 1408 | * BO. We need to free it. | ||
| 1409 | */ | ||
| 1410 | if (mem->bo->tbo.sg) { | ||
| 1411 | sg_free_table(mem->bo->tbo.sg); | ||
| 1412 | kfree(mem->bo->tbo.sg); | ||
| 1413 | } | ||
| 1414 | |||
| 1365 | /* Free the BO*/ | 1415 | /* Free the BO*/ |
| 1366 | amdgpu_bo_unref(&mem->bo); | 1416 | amdgpu_bo_unref(&mem->bo); |
| 1367 | mutex_destroy(&mem->lock); | 1417 | mutex_destroy(&mem->lock); |
| @@ -1664,6 +1714,60 @@ int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd, · 296 unmodified lines | |||
| 1664 | return 0; | 1714 | return 0; |
| 1665 | } | 1715 | } |
| 1666 | 1716 | ||
| 1717 | int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd, | ||
| 1718 | struct dma_buf *dma_buf, | ||
| 1719 | uint64_t va, void *vm, | ||
| 1720 | struct kgd_mem **mem, uint64_t *size, | ||
| 1721 | uint64_t *mmap_offset) | ||
| 1722 | { | ||
| 1723 | struct amdgpu_device *adev = (struct amdgpu_device *)kgd; | ||
| 1724 | struct drm_gem_object *obj; | ||
| 1725 | struct amdgpu_bo *bo; | ||
| 1726 | struct amdgpu_vm *avm = (struct amdgpu_vm *)vm; | ||
| 1727 | |||
| 1728 | if (dma_buf->ops != &amdgpu_dmabuf_ops) | ||
| 1729 | /* Can't handle non-graphics buffers */ | ||
| 1730 | return -EINVAL; | ||
| 1731 | |||
| 1732 | obj = dma_buf->priv; | ||
| 1733 | if (obj->dev->dev_private != adev) | ||
| 1734 | /* Can't handle buffers from other devices */ | ||
| 1735 | return -EINVAL; | ||
| 1736 | |||
| 1737 | bo = gem_to_amdgpu_bo(obj); | ||
| 1738 | if (!(bo->preferred_domains & (AMDGPU_GEM_DOMAIN_VRAM | | ||
| 1739 | AMDGPU_GEM_DOMAIN_GTT))) | ||
| 1740 | /* Only VRAM and GTT BOs are supported */ | ||
| 1741 | return -EINVAL; | ||
| 1742 | |||
| 1743 | *mem = kzalloc(sizeof(struct kgd_mem), GFP_KERNEL); | ||
| 1744 | if (!*mem) | ||
| 1745 | return -ENOMEM; | ||
| 1746 | |||
| 1747 | if (size) | ||
| 1748 | *size = amdgpu_bo_size(bo); | ||
| 1749 | |||
| 1750 | if (mmap_offset) | ||
| 1751 | *mmap_offset = amdgpu_bo_mmap_offset(bo); | ||
| 1752 | |||
| 1753 | INIT_LIST_HEAD(&(*mem)->bo_va_list); | ||
| 1754 | mutex_init(&(*mem)->lock); | ||
| 1755 | (*mem)->mapping_flags = | ||
| 1756 | AMDGPU_VM_PAGE_READABLE | AMDGPU_VM_PAGE_WRITEABLE | | ||
| 1757 | AMDGPU_VM_PAGE_EXECUTABLE | AMDGPU_VM_MTYPE_NC; | ||
| 1758 | |||
| 1759 | (*mem)->bo = amdgpu_bo_ref(bo); | ||
| 1760 | (*mem)->va = va; | ||
| 1761 | (*mem)->domain = (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) ? | ||
| 1762 | AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT; | ||
| 1763 | (*mem)->mapped_to_gpu_memory = 0; | ||
| 1764 | (*mem)->process_info = avm->process_info; | ||
| 1765 | add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info, false); | ||
| 1766 | amdgpu_sync_create(&(*mem)->sync); | ||
| 1767 | |||
| 1768 | return 0; | ||
| 1769 | } | ||
| 1770 | |||
| 1667 | /* Evict a userptr BO by stopping the queues if necessary | 1771 | /* Evict a userptr BO by stopping the queues if necessary |
| 1668 | * | 1772 | * |
| 1669 | * Runs in MMU notifier, may be in RECLAIM_FS context. This means it | 1773 | * Runs in MMU notifier, may be in RECLAIM_FS context. This means it |
| @@ -1830,7 +1934,7 @@ static int validate_invalid_user_pages(struct amdkfd_process_info *process_info) · 160 unmodified lines | |||
| 1830 | validate_list.head) { | 1934 | validate_list.head) { |
| 1831 | list_add_tail(&mem->resv_list.head, &resv_list); | 1935 | list_add_tail(&mem->resv_list.head, &resv_list); |
| 1832 | mem->resv_list.bo = mem->validate_list.bo; | 1936 | mem->resv_list.bo = mem->validate_list.bo; |
| 1833 | mem->resv_list.shared = mem->validate_list.shared; | 1937 | mem->resv_list.num_shared = mem->validate_list.num_shared; |
| 1834 | } | 1938 | } |
| 1835 | 1939 | ||
| 1836 | /* Reserve all BOs and page tables for validation */ | 1940 | /* Reserve all BOs and page tables for validation */ |
| @@ -2049,7 +2153,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef) · 212 unmodified lines | |||
| 2049 | 2153 | ||
| 2050 | list_add_tail(&mem->resv_list.head, &ctx.list); | 2154 | list_add_tail(&mem->resv_list.head, &ctx.list); |
| 2051 | mem->resv_list.bo = mem->validate_list.bo; | 2155 | mem->resv_list.bo = mem->validate_list.bo; |
| 2052 | mem->resv_list.shared = mem->validate_list.shared; | 2156 | mem->resv_list.num_shared = mem->validate_list.num_shared; |
| 2053 | } | 2157 | } |
| 2054 | 2158 | ||
| 2055 | ret = ttm_eu_reserve_buffers(&ctx.ticket, &ctx.list, | 2159 | ret = ttm_eu_reserve_buffers(&ctx.ticket, &ctx.list, |
| @@ -118,7 +118,6 @@ int amdgpu_bo_list_create(struct amdgpu_device *adev, struct drm_file *filp, · 117 unmodified lines | |||
| 118 | entry->priority = min(info[i].bo_priority, | 118 | entry->priority = min(info[i].bo_priority, |
| 119 | AMDGPU_BO_LIST_MAX_PRIORITY); | 119 | AMDGPU_BO_LIST_MAX_PRIORITY); |
| 120 | entry->tv.bo = &bo->tbo; | 120 | entry->tv.bo = &bo->tbo; |
| 121 | entry->tv.shared = !bo->prime_shared_count; | ||
| 122 | 121 | ||
| 123 | if (bo->preferred_domains == AMDGPU_GEM_DOMAIN_GDS) | 122 | if (bo->preferred_domains == AMDGPU_GEM_DOMAIN_GDS) |
| 124 | list->gds_obj = bo; | 123 | list->gds_obj = bo; |
| @@ -50,7 +50,8 @@ static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p, · 49 unmodified lines | |||
| 50 | bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj)); | 50 | bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj)); |
| 51 | p->uf_entry.priority = 0; | 51 | p->uf_entry.priority = 0; |
| 52 | p->uf_entry.tv.bo = &bo->tbo; | 52 | p->uf_entry.tv.bo = &bo->tbo; |
| 53 | p->uf_entry.tv.shared = true; | 53 | /* One for TTM and one for the CS job */ |
| 54 | p->uf_entry.tv.num_shared = 2; | ||
| 54 | p->uf_entry.user_pages = NULL; | 55 | p->uf_entry.user_pages = NULL; |
| 55 | 56 | ||
| 56 | drm_gem_object_put_unlocked(gobj); | 57 | drm_gem_object_put_unlocked(gobj); |
| @@ -598,6 +599,10 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, · 541 unmodified lines | |||
| 598 | return r; | 599 | return r; |
| 599 | } | 600 | } |
| 600 | 601 | ||
| 602 | /* One for TTM and one for the CS job */ | ||
| 603 | amdgpu_bo_list_for_each_entry(e, p->bo_list) | ||
| 604 | e->tv.num_shared = 2; | ||
| 605 | |||
| 601 | amdgpu_bo_list_get_list(p->bo_list, &p->validated); | 606 | amdgpu_bo_list_get_list(p->bo_list, &p->validated); |
| 602 | if (p->bo_list->first_userptr != p->bo_list->num_entries) | 607 | if (p->bo_list->first_userptr != p->bo_list->num_entries) |
| 603 | p->mn = amdgpu_mn_get(p->adev, AMDGPU_MN_TYPE_GFX); | 608 | p->mn = amdgpu_mn_get(p->adev, AMDGPU_MN_TYPE_GFX); |
| @@ -717,8 +722,14 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, · 113 unmodified lines | |||
| 717 | gws = p->bo_list->gws_obj; | 722 | gws = p->bo_list->gws_obj; |
| 718 | oa = p->bo_list->oa_obj; | 723 | oa = p->bo_list->oa_obj; |
| 719 | 724 | ||
| 720 | amdgpu_bo_list_for_each_entry(e, p->bo_list) | 725 | amdgpu_bo_list_for_each_entry(e, p->bo_list) { |
| 721 | e->bo_va = amdgpu_vm_bo_find(vm, ttm_to_amdgpu_bo(e->tv.bo)); | 726 | struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo); |
| 727 | |||
| 728 | /* Make sure we use the exclusive slot for shared BOs */ | ||
| 729 | if (bo->prime_shared_count) | ||
| 730 | e->tv.num_shared = 0; | ||
| 731 | e->bo_va = amdgpu_vm_bo_find(vm, bo); | ||
| 732 | } | ||
| 722 | 733 | ||
| 723 | if (gds) { | 734 | if (gds) { |
| 724 | p->job->gds_base = amdgpu_bo_gpu_offset(gds) >> PAGE_SHIFT; | 735 | p->job->gds_base = amdgpu_bo_gpu_offset(gds) >> PAGE_SHIFT; |
| @@ -955,10 +966,6 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) · 230 unmodified lines | |||
| 955 | if (r) | 966 | if (r) |
| 956 | return r; | 967 | return r; |
| 957 | 968 | ||
| 958 | r = reservation_object_reserve_shared(vm->root.base.bo->tbo.resv, 1); | ||
| 959 | if (r) | ||
| 960 | return r; | ||
| 961 | |||
| 962 | p->job->vm_pd_addr = amdgpu_gmc_pd_addr(vm->root.base.bo); | 969 | p->job->vm_pd_addr = amdgpu_gmc_pd_addr(vm->root.base.bo); |
| 963 | 970 | ||
| 964 | if (amdgpu_vm_debug) { | 971 | if (amdgpu_vm_debug) { |
| @@ -74,7 +74,7 @@ int amdgpu_map_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 73 unmodified lines | |||
| 74 | INIT_LIST_HEAD(&list); | 74 | INIT_LIST_HEAD(&list); |
| 75 | INIT_LIST_HEAD(&csa_tv.head); | 75 | INIT_LIST_HEAD(&csa_tv.head); |
| 76 | csa_tv.bo = &bo->tbo; | 76 | csa_tv.bo = &bo->tbo; |
| 77 | csa_tv.shared = true; | 77 | csa_tv.num_shared = 1; |
| 78 | 78 | ||
| 79 | list_add(&csa_tv.head, &list); | 79 | list_add(&csa_tv.head, &list); |
| 80 | amdgpu_vm_get_pd_bo(vm, &list, &pd); | 80 | amdgpu_vm_get_pd_bo(vm, &list, &pd); |
| @@ -248,7 +248,7 @@ static int amdgpu_ctx_alloc(struct amdgpu_device *adev, · 247 unmodified lines | |||
| 248 | return -ENOMEM; | 248 | return -ENOMEM; |
| 249 | 249 | ||
| 250 | mutex_lock(&mgr->lock); | 250 | mutex_lock(&mgr->lock); |
| 251 | r = idr_alloc(&mgr->ctx_handles, ctx, 1, 0, GFP_KERNEL); | 251 | r = idr_alloc(&mgr->ctx_handles, ctx, 1, AMDGPU_VM_MAX_NUM_CTX, GFP_KERNEL); |
| 252 | if (r < 0) { | 252 | if (r < 0) { |
| 253 | mutex_unlock(&mgr->lock); | 253 | mutex_unlock(&mgr->lock); |
| 254 | kfree(ctx); | 254 | kfree(ctx); |
| @@ -515,7 +515,6 @@ void amdgpu_device_pci_config_reset(struct amdgpu_device *adev) · 514 unmodified lines | |||
| 515 | */ | 515 | */ |
| 516 | static int amdgpu_device_doorbell_init(struct amdgpu_device *adev) | 516 | static int amdgpu_device_doorbell_init(struct amdgpu_device *adev) |
| 517 | { | 517 | { |
| 518 | amdgpu_asic_init_doorbell_index(adev); | ||
| 519 | 518 | ||
| 520 | /* No doorbell on SI hardware generation */ | 519 | /* No doorbell on SI hardware generation */ |
| 521 | if (adev->asic_type < CHIP_BONAIRE) { | 520 | if (adev->asic_type < CHIP_BONAIRE) { |
| @@ -529,6 +528,8 @@ static int amdgpu_device_doorbell_init(struct amdgpu_device *adev) · 7 unmodified lines | |||
| 529 | if (pci_resource_flags(adev->pdev, 2) & IORESOURCE_UNSET) | 528 | if (pci_resource_flags(adev->pdev, 2) & IORESOURCE_UNSET) |
| 530 | return -EINVAL; | 529 | return -EINVAL; |
| 531 | 530 | ||
| 531 | amdgpu_asic_init_doorbell_index(adev); | ||
| 532 | |||
| 532 | /* doorbell bar mapping */ | 533 | /* doorbell bar mapping */ |
| 533 | adev->doorbell.base = pci_resource_start(adev->pdev, 2); | 534 | adev->doorbell.base = pci_resource_start(adev->pdev, 2); |
| 534 | adev->doorbell.size = pci_resource_len(adev->pdev, 2); | 535 | adev->doorbell.size = pci_resource_len(adev->pdev, 2); |
| @@ -1864,6 +1865,9 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev) · 1329 unmodified lines | |||
| 1864 | { | 1865 | { |
| 1865 | int i, r; | 1866 | int i, r; |
| 1866 | 1867 | ||
| 1868 | if (adev->gmc.xgmi.num_physical_nodes > 1) | ||
| 1869 | amdgpu_xgmi_remove_device(adev); | ||
| 1870 | |||
| 1867 | amdgpu_amdkfd_device_fini(adev); | 1871 | amdgpu_amdkfd_device_fini(adev); |
| 1868 | 1872 | ||
| 1869 | amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE); | 1873 | amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE); |
| @@ -2353,6 +2357,19 @@ bool amdgpu_device_has_dc_support(struct amdgpu_device *adev) · 483 unmodified lines | |||
| 2353 | return amdgpu_device_asic_has_dc_support(adev->asic_type); | 2357 | return amdgpu_device_asic_has_dc_support(adev->asic_type); |
| 2354 | } | 2358 | } |
| 2355 | 2359 | ||
| 2360 | |||
| 2361 | static void amdgpu_device_xgmi_reset_func(struct work_struct *__work) | ||
| 2362 | { | ||
| 2363 | struct amdgpu_device *adev = | ||
| 2364 | container_of(__work, struct amdgpu_device, xgmi_reset_work); | ||
| 2365 | |||
| 2366 | adev->asic_reset_res = amdgpu_asic_reset(adev); | ||
| 2367 | if (adev->asic_reset_res) | ||
| 2368 | DRM_WARN("ASIC reset failed with err r, %d for drm dev, %s", | ||
| 2369 | adev->asic_reset_res, adev->ddev->unique); | ||
| 2370 | } | ||
| 2371 | |||
| 2372 | |||
| 2356 | /** | 2373 | /** |
| 2357 | * amdgpu_device_init - initialize the driver | 2374 | * amdgpu_device_init - initialize the driver |
| 2358 | * | 2375 | * |
| @@ -2451,6 +2468,8 @@ int amdgpu_device_init(struct amdgpu_device *adev, · 92 unmodified lines | |||
| 2451 | INIT_DELAYED_WORK(&adev->gfx.gfx_off_delay_work, | 2468 | INIT_DELAYED_WORK(&adev->gfx.gfx_off_delay_work, |
| 2452 | amdgpu_device_delay_enable_gfx_off); | 2469 | amdgpu_device_delay_enable_gfx_off); |
| 2453 | 2470 | ||
| 2471 | INIT_WORK(&adev->xgmi_reset_work, amdgpu_device_xgmi_reset_func); | ||
| 2472 | |||
| 2454 | adev->gfx.gfx_off_req_count = 1; | 2473 | adev->gfx.gfx_off_req_count = 1; |
| 2455 | adev->pm.ac_power = power_supply_is_system_supplied() > 0 ? true : false; | 2474 | adev->pm.ac_power = power_supply_is_system_supplied() > 0 ? true : false; |
| 2456 | 2475 | ||
| @@ -3239,6 +3258,8 @@ bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev) · 782 unmodified lines | |||
| 3239 | 3258 | ||
| 3240 | if (amdgpu_gpu_recovery == -1) { | 3259 | if (amdgpu_gpu_recovery == -1) { |
| 3241 | switch (adev->asic_type) { | 3260 | switch (adev->asic_type) { |
| 3261 | case CHIP_BONAIRE: | ||
| 3262 | case CHIP_HAWAII: | ||
| 3242 | case CHIP_TOPAZ: | 3263 | case CHIP_TOPAZ: |
| 3243 | case CHIP_TONGA: | 3264 | case CHIP_TONGA: |
| 3244 | case CHIP_FIJI: | 3265 | case CHIP_FIJI: |
| @@ -3328,10 +3349,31 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, · 83 unmodified lines | |||
| 3328 | */ | 3349 | */ |
| 3329 | if (need_full_reset) { | 3350 | if (need_full_reset) { |
| 3330 | list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { | 3351 | list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { |
| 3331 | r = amdgpu_asic_reset(tmp_adev); | 3352 | /* For XGMI run all resets in parallel to speed up the process */ |
| 3332 | if (r) | 3353 | if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) { |
| 3333 | DRM_WARN("ASIC reset failed with err r, %d for drm dev, %s", | 3354 | if (!queue_work(system_highpri_wq, &tmp_adev->xgmi_reset_work)) |
| 3355 | r = -EALREADY; | ||
| 3356 | } else | ||
| 3357 | r = amdgpu_asic_reset(tmp_adev); | ||
| 3358 | |||
| 3359 | if (r) { | ||
| 3360 | DRM_ERROR("ASIC reset failed with err r, %d for drm dev, %s", | ||
| 3334 | r, tmp_adev->ddev->unique); | 3361 | r, tmp_adev->ddev->unique); |
| 3362 | break; | ||
| 3363 | } | ||
| 3364 | } | ||
| 3365 | |||
| 3366 | /* For XGMI wait for all PSP resets to complete before proceed */ | ||
| 3367 | if (!r) { | ||
| 3368 | list_for_each_entry(tmp_adev, device_list_handle, | ||
| 3369 | gmc.xgmi.head) { | ||
| 3370 | if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) { | ||
| 3371 | flush_work(&tmp_adev->xgmi_reset_work); | ||
| 3372 | r = tmp_adev->asic_reset_res; | ||
| 3373 | if (r) | ||
| 3374 | break; | ||
| 3375 | } | ||
| 3376 | } | ||
| 3335 | } | 3377 | } |
| 3336 | } | 3378 | } |
| 3337 | 3379 | ||
| @@ -3518,8 +3560,6 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */ · 180 unmodified lines | |||
| 3518 | if (tmp_adev == adev) | 3560 | if (tmp_adev == adev) |
| 3519 | continue; | 3561 | continue; |
| 3520 | 3562 | ||
| 3521 | dev_info(tmp_adev->dev, "GPU reset begin for drm dev %s!\n", adev->ddev->unique); | ||
| 3522 | |||
| 3523 | amdgpu_device_lock_adev(tmp_adev); | 3563 | amdgpu_device_lock_adev(tmp_adev); |
| 3524 | r = amdgpu_device_pre_asic_reset(tmp_adev, | 3564 | r = amdgpu_device_pre_asic_reset(tmp_adev, |
| 3525 | NULL, | 3565 | NULL, |
| @@ -169,7 +169,7 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj, · 168 unmodified lines | |||
| 169 | INIT_LIST_HEAD(&duplicates); | 169 | INIT_LIST_HEAD(&duplicates); |
| 170 | 170 | ||
| 171 | tv.bo = &bo->tbo; | 171 | tv.bo = &bo->tbo; |
| 172 | tv.shared = true; | 172 | tv.num_shared = 1; |
| 173 | list_add(&tv.head, &list); | 173 | list_add(&tv.head, &list); |
| 174 | 174 | ||
| 175 | amdgpu_vm_get_pd_bo(vm, &list, &vm_pd); | 175 | amdgpu_vm_get_pd_bo(vm, &list, &vm_pd); |
| @@ -604,7 +604,10 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, · 428 unmodified lines | |||
| 604 | return -ENOENT; | 604 | return -ENOENT; |
| 605 | abo = gem_to_amdgpu_bo(gobj); | 605 | abo = gem_to_amdgpu_bo(gobj); |
| 606 | tv.bo = &abo->tbo; | 606 | tv.bo = &abo->tbo; |
| 607 | tv.shared = !!(abo->flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID); | 607 | if (abo->flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID) |
| 608 | tv.num_shared = 1; | ||
| 609 | else | ||
| 610 | tv.num_shared = 0; | ||
| 608 | list_add(&tv.head, &list); | 611 | list_add(&tv.head, &list); |
| 609 | } else { | 612 | } else { |
| 610 | gobj = NULL; | 613 | gobj = NULL; |
| @@ -54,6 +54,8 @@ void *amdgpu_gem_prime_vmap(struct drm_gem_object *obj); · 53 unmodified lines | |||
| 54 | void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); | 54 | void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); |
| 55 | int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); | 55 | int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); |
| 56 | 56 | ||
| 57 | extern const struct dma_buf_ops amdgpu_dmabuf_ops; | ||
| 58 | |||
| 57 | /* | 59 | /* |
| 58 | * GEM objects. | 60 | * GEM objects. |
| 59 | */ | 61 | */ |
| @@ -99,6 +99,7 @@ struct amdgpu_xgmi { · 98 unmodified lines | |||
| 99 | unsigned num_physical_nodes; | 99 | unsigned num_physical_nodes; |
| 100 | /* gpu list in the same hive */ | 100 | /* gpu list in the same hive */ |
| 101 | struct list_head head; | 101 | struct list_head head; |
| 102 | bool supported; | ||
| 102 | }; | 103 | }; |
| 103 | 104 | ||
| 104 | struct amdgpu_gmc { | 105 | struct amdgpu_gmc { |
| @@ -51,14 +51,12 @@ struct amdgpu_ih_ring { · 50 unmodified lines | |||
| 51 | struct amdgpu_ih_funcs { | 51 | struct amdgpu_ih_funcs { |
| 52 | /* ring read/write ptr handling, called from interrupt context */ | 52 | /* ring read/write ptr handling, called from interrupt context */ |
| 53 | u32 (*get_wptr)(struct amdgpu_device *adev); | 53 | u32 (*get_wptr)(struct amdgpu_device *adev); |
| 54 | bool (*prescreen_iv)(struct amdgpu_device *adev); | ||
| 55 | void (*decode_iv)(struct amdgpu_device *adev, | 54 | void (*decode_iv)(struct amdgpu_device *adev, |
| 56 | struct amdgpu_iv_entry *entry); | 55 | struct amdgpu_iv_entry *entry); |
| 57 | void (*set_rptr)(struct amdgpu_device *adev); | 56 | void (*set_rptr)(struct amdgpu_device *adev); |
| 58 | }; | 57 | }; |
| 59 | 58 | ||
| 60 | #define amdgpu_ih_get_wptr(adev) (adev)->irq.ih_funcs->get_wptr((adev)) | 59 | #define amdgpu_ih_get_wptr(adev) (adev)->irq.ih_funcs->get_wptr((adev)) |
| 61 | #define amdgpu_ih_prescreen_iv(adev) (adev)->irq.ih_funcs->prescreen_iv((adev)) | ||
| 62 | #define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv)) | 60 | #define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv)) |
| 63 | #define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev)) | 61 | #define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev)) |
| 64 | 62 | ||
| @@ -145,13 +145,6 @@ static void amdgpu_irq_callback(struct amdgpu_device *adev, · 144 unmodified lines | |||
| 145 | u32 ring_index = ih->rptr >> 2; | 145 | u32 ring_index = ih->rptr >> 2; |
| 146 | struct amdgpu_iv_entry entry; | 146 | struct amdgpu_iv_entry entry; |
| 147 | 147 | ||
| 148 | /* Prescreening of high-frequency interrupts */ | ||
| 149 | if (!amdgpu_ih_prescreen_iv(adev)) | ||
| 150 | return; | ||
| 151 | |||
| 152 | /* Before dispatching irq to IP blocks, send it to amdkfd */ | ||
| 153 | amdgpu_amdkfd_interrupt(adev, (const void *) &ih->ring[ring_index]); | ||
| 154 | |||
| 155 | entry.iv_entry = (const uint32_t *)&ih->ring[ring_index]; | 148 | entry.iv_entry = (const uint32_t *)&ih->ring[ring_index]; |
| 156 | amdgpu_ih_decode_iv(adev, &entry); | 149 | amdgpu_ih_decode_iv(adev, &entry); |
| 157 | 150 | ||
| @@ -371,39 +364,38 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev, · 213 unmodified lines | |||
| 371 | unsigned client_id = entry->client_id; | 364 | unsigned client_id = entry->client_id; |
| 372 | unsigned src_id = entry->src_id; | 365 | unsigned src_id = entry->src_id; |
| 373 | struct amdgpu_irq_src *src; | 366 | struct amdgpu_irq_src *src; |
| 367 | bool handled = false; | ||
| 374 | int r; | 368 | int r; |
| 375 | 369 | ||
| 376 | trace_amdgpu_iv(entry); | 370 | trace_amdgpu_iv(entry); |
| 377 | 371 | ||
| 378 | if (client_id >= AMDGPU_IRQ_CLIENTID_MAX) { | 372 | if (client_id >= AMDGPU_IRQ_CLIENTID_MAX) { |
| 379 | DRM_DEBUG("Invalid client_id in IV: %d\n", client_id); | 373 | DRM_DEBUG("Invalid client_id in IV: %d\n", client_id); |
| 380 | return; | ||
| 381 | } | ||
| 382 | 374 | ||
| 383 | if (src_id >= AMDGPU_MAX_IRQ_SRC_ID) { | 375 | } else if (src_id >= AMDGPU_MAX_IRQ_SRC_ID) { |
| 384 | DRM_DEBUG("Invalid src_id in IV: %d\n", src_id); | 376 | DRM_DEBUG("Invalid src_id in IV: %d\n", src_id); |
| 385 | return; | ||
| 386 | } | ||
| 387 | 377 | ||
| 388 | if (adev->irq.virq[src_id]) { | 378 | } else if (adev->irq.virq[src_id]) { |
| 389 | generic_handle_irq(irq_find_mapping(adev->irq.domain, src_id)); | 379 | generic_handle_irq(irq_find_mapping(adev->irq.domain, src_id)); |
| 390 | } else { | ||
| 391 | if (!adev->irq.client[client_id].sources) { | ||
| 392 | DRM_DEBUG("Unregistered interrupt client_id: %d src_id: %d\n", | ||
| 393 | client_id, src_id); | ||
| 394 | return; | ||
| 395 | } | ||
| 396 | 380 | ||
| 397 | src = adev->irq.client[client_id].sources[src_id]; | 381 | } else if (!adev->irq.client[client_id].sources) { |
| 398 | if (!src) { | 382 | DRM_DEBUG("Unregistered interrupt client_id: %d src_id: %d\n", |
| 399 | DRM_DEBUG("Unhandled interrupt src_id: %d\n", src_id); | 383 | client_id, src_id); |
| 400 | return; | ||
| 401 | } | ||
| 402 | 384 | ||
| 385 | } else if ((src = adev->irq.client[client_id].sources[src_id])) { | ||
| 403 | r = src->funcs->process(adev, src, entry); | 386 | r = src->funcs->process(adev, src, entry); |
| 404 | if (r) | 387 | if (r < 0) |
| 405 | DRM_ERROR("error processing interrupt (%d)\n", r); | 388 | DRM_ERROR("error processing interrupt (%d)\n", r); |
| 389 | else if (r) | ||
| 390 | handled = true; | ||
| 391 | |||
| 392 | } else { | ||
| 393 | DRM_DEBUG("Unhandled interrupt src_id: %d\n", src_id); | ||
| 406 | } | 394 | } |
| 395 | |||
| 396 | /* Send it to amdkfd as well if it isn't already handled */ | ||
| 397 | if (!handled) | ||
| 398 | amdgpu_amdkfd_interrupt(adev, entry->iv_entry); | ||
| 407 | } | 399 | } |
| 408 | 400 | ||
| 409 | /** | 401 | /** |
| @@ -81,7 +81,7 @@ static void amdgpu_bo_destroy(struct ttm_buffer_object *tbo) · 80 unmodified lines | |||
| 81 | amdgpu_bo_subtract_pin_size(bo); | 81 | amdgpu_bo_subtract_pin_size(bo); |
| 82 | 82 | ||
| 83 | if (bo->kfd_bo) | 83 | if (bo->kfd_bo) |
| 84 | amdgpu_amdkfd_unreserve_system_memory_limit(bo); | 84 | amdgpu_amdkfd_unreserve_memory_limit(bo); |
| 85 | 85 | ||
| 86 | amdgpu_bo_kunmap(bo); | 86 | amdgpu_bo_kunmap(bo); |
| 87 | 87 | ||
| @@ -607,53 +607,6 @@ int amdgpu_bo_create(struct amdgpu_device *adev, · 519 unmodified lines | |||
| 607 | return r; | 607 | return r; |
| 608 | } | 608 | } |
| 609 | 609 | ||
| 610 | /** | ||
| 611 | * amdgpu_bo_backup_to_shadow - Backs up an &amdgpu_bo buffer object | ||
| 612 | * @adev: amdgpu device object | ||
| 613 | * @ring: amdgpu_ring for the engine handling the buffer operations | ||
| 614 | * @bo: &amdgpu_bo buffer to be backed up | ||
| 615 | * @resv: reservation object with embedded fence | ||
| 616 | * @fence: dma_fence associated with the operation | ||
| 617 | * @direct: whether to submit the job directly | ||
| 618 | * | ||
| 619 | * Copies an &amdgpu_bo buffer object to its shadow object. | ||
| 620 | * Not used for now. | ||
| 621 | * | ||
| 622 | * Returns: | ||
| 623 | * 0 for success or a negative error code on failure. | ||
| 624 | */ | ||
| 625 | int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev, | ||
| 626 | struct amdgpu_ring *ring, | ||
| 627 | struct amdgpu_bo *bo, | ||
| 628 | struct reservation_object *resv, | ||
| 629 | struct dma_fence **fence, | ||
| 630 | bool direct) | ||
| 631 | |||
| 632 | { | ||
| 633 | struct amdgpu_bo *shadow = bo->shadow; | ||
| 634 | uint64_t bo_addr, shadow_addr; | ||
| 635 | int r; | ||
| 636 | |||
| 637 | if (!shadow) | ||
| 638 | return -EINVAL; | ||
| 639 | |||
| 640 | bo_addr = amdgpu_bo_gpu_offset(bo); | ||
| 641 | shadow_addr = amdgpu_bo_gpu_offset(bo->shadow); | ||
| 642 | |||
| 643 | r = reservation_object_reserve_shared(bo->tbo.resv, 1); | ||
| 644 | if (r) | ||
| 645 | goto err; | ||
| 646 | |||
| 647 | r = amdgpu_copy_buffer(ring, bo_addr, shadow_addr, | ||
| 648 | amdgpu_bo_size(bo), resv, fence, | ||
| 649 | direct, false); | ||
| 650 | if (!r) | ||
| 651 | amdgpu_bo_fence(bo, *fence, true); | ||
| 652 | |||
| 653 | err: | ||
| 654 | return r; | ||
| 655 | } | ||
| 656 | |||
| 657 | /** | 610 | /** |
| 658 | * amdgpu_bo_validate - validate an &amdgpu_bo buffer object | 611 | * amdgpu_bo_validate - validate an &amdgpu_bo buffer object |
| 659 | * @bo: pointer to the buffer object | 612 | * @bo: pointer to the buffer object |
| @@ -267,11 +267,6 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo); · 266 unmodified lines | |||
| 267 | void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence, | 267 | void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence, |
| 268 | bool shared); | 268 | bool shared); |
| 269 | u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo); | 269 | u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo); |
| 270 | int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev, | ||
| 271 | struct amdgpu_ring *ring, | ||
| 272 | struct amdgpu_bo *bo, | ||
| 273 | struct reservation_object *resv, | ||
| 274 | struct dma_fence **fence, bool direct); | ||
| 275 | int amdgpu_bo_validate(struct amdgpu_bo *bo); | 270 | int amdgpu_bo_validate(struct amdgpu_bo *bo); |
| 276 | int amdgpu_bo_restore_shadow(struct amdgpu_bo *shadow, | 271 | int amdgpu_bo_restore_shadow(struct amdgpu_bo *shadow, |
| 277 | struct dma_fence **fence); | 272 | struct dma_fence **fence); |
| @@ -39,8 +39,6 @@ · 38 unmodified lines | |||
| 39 | #include <drm/amdgpu_drm.h> | 39 | #include <drm/amdgpu_drm.h> |
| 40 | #include <linux/dma-buf.h> | 40 | #include <linux/dma-buf.h> |
| 41 | 41 | ||
| 42 | static const struct dma_buf_ops amdgpu_dmabuf_ops; | ||
| 43 | |||
| 44 | /** | 42 | /** |
| 45 | * amdgpu_gem_prime_get_sg_table - &drm_driver.gem_prime_get_sg_table | 43 | * amdgpu_gem_prime_get_sg_table - &drm_driver.gem_prime_get_sg_table |
| 46 | * implementation | 44 | * implementation |
| @@ -332,7 +330,7 @@ static int amdgpu_gem_begin_cpu_access(struct dma_buf *dma_buf, · 285 unmodified lines | |||
| 332 | return ret; | 330 | return ret; |
| 333 | } | 331 | } |
| 334 | 332 | ||
| 335 | static const struct dma_buf_ops amdgpu_dmabuf_ops = { | 333 | const struct dma_buf_ops amdgpu_dmabuf_ops = { |
| 336 | .attach = amdgpu_gem_map_attach, | 334 | .attach = amdgpu_gem_map_attach, |
| 337 | .detach = amdgpu_gem_map_detach, | 335 | .detach = amdgpu_gem_map_detach, |
| 338 | .map_dma_buf = drm_gem_map_dma_buf, | 336 | .map_dma_buf = drm_gem_map_dma_buf, |
| @@ -155,10 +155,22 @@ psp_cmd_submit_buf(struct psp_context *psp, · 154 unmodified lines | |||
| 155 | return ret; | 155 | return ret; |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | static void psp_prep_tmr_cmd_buf(struct psp_gfx_cmd_resp *cmd, | 158 | bool psp_support_vmr_ring(struct psp_context *psp) |
| 159 | { | ||
| 160 | if (amdgpu_sriov_vf(psp->adev) && psp->sos_fw_version > 0x80045) | ||
| 161 | return true; | ||
| 162 | else | ||
| 163 | return false; | ||
| 164 | } | ||
| 165 | |||
| 166 | static void psp_prep_tmr_cmd_buf(struct psp_context *psp, | ||
| 167 | struct psp_gfx_cmd_resp *cmd, | ||
| 159 | uint64_t tmr_mc, uint32_t size) | 168 | uint64_t tmr_mc, uint32_t size) |
| 160 | { | 169 | { |
| 161 | cmd->cmd_id = GFX_CMD_ID_SETUP_TMR; | 170 | if (psp_support_vmr_ring(psp)) |
| 171 | cmd->cmd_id = GFX_CMD_ID_SETUP_VMR; | ||
| 172 | else | ||
| 173 | cmd->cmd_id = GFX_CMD_ID_SETUP_TMR; | ||
| 162 | cmd->cmd.cmd_setup_tmr.buf_phy_addr_lo = lower_32_bits(tmr_mc); | 174 | cmd->cmd.cmd_setup_tmr.buf_phy_addr_lo = lower_32_bits(tmr_mc); |
| 163 | cmd->cmd.cmd_setup_tmr.buf_phy_addr_hi = upper_32_bits(tmr_mc); | 175 | cmd->cmd.cmd_setup_tmr.buf_phy_addr_hi = upper_32_bits(tmr_mc); |
| 164 | cmd->cmd.cmd_setup_tmr.buf_size = size; | 176 | cmd->cmd.cmd_setup_tmr.buf_size = size; |
| @@ -192,7 +204,7 @@ static int psp_tmr_load(struct psp_context *psp) · 27 unmodified lines | |||
| 192 | if (!cmd) | 204 | if (!cmd) |
| 193 | return -ENOMEM; | 205 | return -ENOMEM; |
| 194 | 206 | ||
| 195 | psp_prep_tmr_cmd_buf(cmd, psp->tmr_mc_addr, PSP_TMR_SIZE); | 207 | psp_prep_tmr_cmd_buf(psp, cmd, psp->tmr_mc_addr, PSP_TMR_SIZE); |
| 196 | DRM_INFO("reserve 0x%x from 0x%llx for PSP TMR SIZE\n", | 208 | DRM_INFO("reserve 0x%x from 0x%llx for PSP TMR SIZE\n", |
| 197 | PSP_TMR_SIZE, psp->tmr_mc_addr); | 209 | PSP_TMR_SIZE, psp->tmr_mc_addr); |
| 198 | 210 | ||
| @@ -536,8 +548,10 @@ static int psp_load_fw(struct amdgpu_device *adev) · 337 unmodified lines | |||
| 536 | int ret; | 548 | int ret; |
| 537 | struct psp_context *psp = &adev->psp; | 549 | struct psp_context *psp = &adev->psp; |
| 538 | 550 | ||
| 539 | if (amdgpu_sriov_vf(adev) && adev->in_gpu_reset != 0) | 551 | if (amdgpu_sriov_vf(adev) && adev->in_gpu_reset) { |
| 552 | psp_ring_destroy(psp, PSP_RING_TYPE__KM); | ||
| 540 | goto skip_memalloc; | 553 | goto skip_memalloc; |
| 554 | } | ||
| 541 | 555 | ||
| 542 | psp->cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | 556 | psp->cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); |
| 543 | if (!psp->cmd) | 557 | if (!psp->cmd) |
| @@ -217,6 +217,7 @@ extern const struct amdgpu_ip_block_version psp_v10_0_ip_block; · 216 unmodified lines | |||
| 217 | 217 | ||
| 218 | int psp_gpu_reset(struct amdgpu_device *adev); | 218 | int psp_gpu_reset(struct amdgpu_device *adev); |
| 219 | int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id); | 219 | int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id); |
| 220 | bool psp_support_vmr_ring(struct psp_context *psp); | ||
| 220 | 221 | ||
| 221 | extern const struct amdgpu_ip_block_version psp_v11_0_ip_block; | 222 | extern const struct amdgpu_ip_block_version psp_v11_0_ip_block; |
| 222 | 223 | ||
| @@ -397,7 +397,7 @@ bool amdgpu_ring_soft_recovery(struct amdgpu_ring *ring, unsigned int vmid, · 396 unmodified lines | |||
| 397 | { | 397 | { |
| 398 | ktime_t deadline = ktime_add_us(ktime_get(), 10000); | 398 | ktime_t deadline = ktime_add_us(ktime_get(), 10000); |
| 399 | 399 | ||
| 400 | if (!ring->funcs->soft_recovery) | 400 | if (!ring->funcs->soft_recovery || !fence) |
| 401 | return false; | 401 | return false; |
| 402 | 402 | ||
| 403 | atomic_inc(&ring->adev->gpu_reset_counter); | 403 | atomic_inc(&ring->adev->gpu_reset_counter); |
| @@ -617,7 +617,8 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, · 616 unmodified lines | |||
| 617 | { | 617 | { |
| 618 | entry->priority = 0; | 618 | entry->priority = 0; |
| 619 | entry->tv.bo = &vm->root.base.bo->tbo; | 619 | entry->tv.bo = &vm->root.base.bo->tbo; |
| 620 | entry->tv.shared = true; | 620 | /* One for the VM updates, one for TTM and one for the CS job */ |
| 621 | entry->tv.num_shared = 3; | ||
| 621 | entry->user_pages = NULL; | 622 | entry->user_pages = NULL; |
| 622 | list_add(&entry->tv.head, validated); | 623 | list_add(&entry->tv.head, validated); |
| 623 | } | 624 | } |
| @@ -773,10 +774,6 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev, · 149 unmodified lines | |||
| 773 | 774 | ||
| 774 | ring = container_of(vm->entity.rq->sched, struct amdgpu_ring, sched); | 775 | ring = container_of(vm->entity.rq->sched, struct amdgpu_ring, sched); |
| 775 | 776 | ||
| 776 | r = reservation_object_reserve_shared(bo->tbo.resv, 1); | ||
| 777 | if (r) | ||
| 778 | return r; | ||
| 779 | |||
| 780 | r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); | 777 | r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); |
| 781 | if (r) | 778 | if (r) |
| 782 | goto error; | 779 | goto error; |
| @@ -1842,10 +1839,6 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, · 1059 unmodified lines | |||
| 1842 | if (r) | 1839 | if (r) |
| 1843 | goto error_free; | 1840 | goto error_free; |
| 1844 | 1841 | ||
| 1845 | r = reservation_object_reserve_shared(vm->root.base.bo->tbo.resv, 1); | ||
| 1846 | if (r) | ||
| 1847 | goto error_free; | ||
| 1848 | |||
| 1849 | r = amdgpu_vm_update_ptes(¶ms, start, last + 1, addr, flags); | 1842 | r = amdgpu_vm_update_ptes(¶ms, start, last + 1, addr, flags); |
| 1850 | if (r) | 1843 | if (r) |
| 1851 | goto error_free; | 1844 | goto error_free; |
| @@ -3026,6 +3019,10 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 1174 unmodified lines | |||
| 3026 | if (r) | 3019 | if (r) |
| 3027 | goto error_free_root; | 3020 | goto error_free_root; |
| 3028 | 3021 | ||
| 3022 | r = reservation_object_reserve_shared(root->tbo.resv, 1); | ||
| 3023 | if (r) | ||
| 3024 | goto error_unreserve; | ||
| 3025 | |||
| 3029 | r = amdgpu_vm_clear_bo(adev, vm, root, | 3026 | r = amdgpu_vm_clear_bo(adev, vm, root, |
| 3030 | adev->vm_manager.root_level, | 3027 | adev->vm_manager.root_level, |
| 3031 | vm->pte_support_ats); | 3028 | vm->pte_support_ats); |
| @@ -3055,7 +3052,6 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 23 unmodified lines | |||
| 3055 | } | 3052 | } |
| 3056 | 3053 | ||
| 3057 | INIT_KFIFO(vm->faults); | 3054 | INIT_KFIFO(vm->faults); |
| 3058 | vm->fault_credit = 16; | ||
| 3059 | 3055 | ||
| 3060 | return 0; | 3056 | return 0; |
| 3061 | 3057 | ||
| @@ -3267,42 +3263,6 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) · 205 unmodified lines | |||
| 3267 | amdgpu_vmid_free_reserved(adev, vm, i); | 3263 | amdgpu_vmid_free_reserved(adev, vm, i); |
| 3268 | } | 3264 | } |
| 3269 | 3265 | ||
| 3270 | /** | ||
| 3271 | * amdgpu_vm_pasid_fault_credit - Check fault credit for given PASID | ||
| 3272 | * | ||
| 3273 | * @adev: amdgpu_device pointer | ||
| 3274 | * @pasid: PASID do identify the VM | ||
| 3275 | * | ||
| 3276 | * This function is expected to be called in interrupt context. | ||
| 3277 | * | ||
| 3278 | * Returns: | ||
| 3279 | * True if there was fault credit, false otherwise | ||
| 3280 | */ | ||
| 3281 | bool amdgpu_vm_pasid_fault_credit(struct amdgpu_device *adev, | ||
| 3282 | unsigned int pasid) | ||
| 3283 | { | ||
| 3284 | struct amdgpu_vm *vm; | ||
| 3285 | |||
| 3286 | spin_lock(&adev->vm_manager.pasid_lock); | ||
| 3287 | vm = idr_find(&adev->vm_manager.pasid_idr, pasid); | ||
| 3288 | if (!vm) { | ||
| 3289 | /* VM not found, can't track fault credit */ | ||
| 3290 | spin_unlock(&adev->vm_manager.pasid_lock); | ||
| 3291 | return true; | ||
| 3292 | } | ||
| 3293 | |||
| 3294 | /* No lock needed. only accessed by IRQ handler */ | ||
| 3295 | if (!vm->fault_credit) { | ||
| 3296 | /* Too many faults in this VM */ | ||
| 3297 | spin_unlock(&adev->vm_manager.pasid_lock); | ||
| 3298 | return false; | ||
| 3299 | } | ||
| 3300 | |||
| 3301 | vm->fault_credit--; | ||
| 3302 | spin_unlock(&adev->vm_manager.pasid_lock); | ||
| 3303 | return true; | ||
| 3304 | } | ||
| 3305 | |||
| 3306 | /** | 3266 | /** |
| 3307 | * amdgpu_vm_manager_init - init the VM manager | 3267 | * amdgpu_vm_manager_init - init the VM manager |
| 3308 | * | 3268 | * |
| @@ -229,9 +229,6 @@ struct amdgpu_vm { · 228 unmodified lines | |||
| 229 | /* Up to 128 pending retry page faults */ | 229 | /* Up to 128 pending retry page faults */ |
| 230 | DECLARE_KFIFO(faults, u64, 128); | 230 | DECLARE_KFIFO(faults, u64, 128); |
| 231 | 231 | ||
| 232 | /* Limit non-retry fault storms */ | ||
| 233 | unsigned int fault_credit; | ||
| 234 | |||
| 235 | /* Points to the KFD process VM info */ | 232 | /* Points to the KFD process VM info */ |
| 236 | struct amdkfd_process_info *process_info; | 233 | struct amdkfd_process_info *process_info; |
| 237 | 234 | ||
| @@ -299,8 +296,6 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 61 unmodified lines | |||
| 299 | int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, unsigned int pasid); | 296 | int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, unsigned int pasid); |
| 300 | void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm); | 297 | void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm); |
| 301 | void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); | 298 | void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); |
| 302 | bool amdgpu_vm_pasid_fault_credit(struct amdgpu_device *adev, | ||
| 303 | unsigned int pasid); | ||
| 304 | void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, | 299 | void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, |
| 305 | struct list_head *validated, | 300 | struct list_head *validated, |
| 306 | struct amdgpu_bo_list_entry *entry); | 301 | struct amdgpu_bo_list_entry *entry); |
| @@ -78,7 +78,7 @@ int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_dev · 77 unmodified lines | |||
| 78 | adev->gmc.xgmi.node_id, | 78 | adev->gmc.xgmi.node_id, |
| 79 | adev->gmc.xgmi.hive_id, ret); | 79 | adev->gmc.xgmi.hive_id, ret); |
| 80 | else | 80 | else |
| 81 | dev_info(adev->dev, "XGMI: Add node %d to hive 0x%llx.\n", | 81 | dev_info(adev->dev, "XGMI: Set topology for node %d, hive 0x%llx.\n", |
| 82 | adev->gmc.xgmi.physical_node_id, | 82 | adev->gmc.xgmi.physical_node_id, |
| 83 | adev->gmc.xgmi.hive_id); | 83 | adev->gmc.xgmi.hive_id); |
| 84 | 84 | ||
| @@ -94,9 +94,9 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) · 9 unmodified lines | |||
| 94 | 94 | ||
| 95 | int count = 0, ret = -EINVAL; | 95 | int count = 0, ret = -EINVAL; |
| 96 | 96 | ||
| 97 | if ((adev->asic_type < CHIP_VEGA20) || | 97 | if (!adev->gmc.xgmi.supported) |
| 98 | (adev->flags & AMD_IS_APU) ) | ||
| 99 | return 0; | 98 | return 0; |
| 99 | |||
| 100 | adev->gmc.xgmi.node_id = psp_xgmi_get_node_id(&adev->psp); | 100 | adev->gmc.xgmi.node_id = psp_xgmi_get_node_id(&adev->psp); |
| 101 | adev->gmc.xgmi.hive_id = psp_xgmi_get_hive_id(&adev->psp); | 101 | adev->gmc.xgmi.hive_id = psp_xgmi_get_hive_id(&adev->psp); |
| 102 | 102 | ||
| @@ -135,3 +135,23 @@ exit: · 32 unmodified lines | |||
| 135 | mutex_unlock(&xgmi_mutex); | 135 | mutex_unlock(&xgmi_mutex); |
| 136 | return ret; | 136 | return ret; |
| 137 | } | 137 | } |
| 138 | |||
| 139 | void amdgpu_xgmi_remove_device(struct amdgpu_device *adev) | ||
| 140 | { | ||
| 141 | struct amdgpu_hive_info *hive; | ||
| 142 | |||
| 143 | if (!adev->gmc.xgmi.supported) | ||
| 144 | return; | ||
| 145 | |||
| 146 | mutex_lock(&xgmi_mutex); | ||
| 147 | |||
| 148 | hive = amdgpu_get_xgmi_hive(adev); | ||
| 149 | if (!hive) | ||
| 150 | goto exit; | ||
| 151 | |||
| 152 | if (!(hive->number_devices--)) | ||
| 153 | mutex_destroy(&hive->hive_lock); | ||
| 154 | |||
| 155 | exit: | ||
| 156 | mutex_unlock(&xgmi_mutex); | ||
| 157 | } | ||
| @@ -35,5 +35,6 @@ struct amdgpu_hive_info { · 34 unmodified lines | |||
| 35 | struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev); | 35 | struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev); |
| 36 | int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_device *adev); | 36 | int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_device *adev); |
| 37 | int amdgpu_xgmi_add_device(struct amdgpu_device *adev); | 37 | int amdgpu_xgmi_add_device(struct amdgpu_device *adev); |
| 38 | void amdgpu_xgmi_remove_device(struct amdgpu_device *adev); | ||
| 38 | 39 | ||
| 39 | #endif | 40 | #endif |
| @@ -228,34 +228,6 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev) · 227 unmodified lines | |||
| 228 | * [127:96] - reserved | 228 | * [127:96] - reserved |
| 229 | */ | 229 | */ |
| 230 | 230 | ||
| 231 | /** | ||
| 232 | * cik_ih_prescreen_iv - prescreen an interrupt vector | ||
| 233 | * | ||
| 234 | * @adev: amdgpu_device pointer | ||
| 235 | * | ||
| 236 | * Returns true if the interrupt vector should be further processed. | ||
| 237 | */ | ||
| 238 | static bool cik_ih_prescreen_iv(struct amdgpu_device *adev) | ||
| 239 | { | ||
| 240 | u32 ring_index = adev->irq.ih.rptr >> 2; | ||
| 241 | u16 pasid; | ||
| 242 | |||
| 243 | switch (le32_to_cpu(adev->irq.ih.ring[ring_index]) & 0xff) { | ||
| 244 | case 146: | ||
| 245 | case 147: | ||
| 246 | pasid = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]) >> 16; | ||
| 247 | if (!pasid || amdgpu_vm_pasid_fault_credit(adev, pasid)) | ||
| 248 | return true; | ||
| 249 | break; | ||
| 250 | default: | ||
| 251 | /* Not a VM fault */ | ||
| 252 | return true; | ||
| 253 | } | ||
| 254 | |||
| 255 | adev->irq.ih.rptr += 16; | ||
| 256 | return false; | ||
| 257 | } | ||
| 258 | |||
| 259 | /** | 231 | /** |
| 260 | * cik_ih_decode_iv - decode an interrupt vector | 232 | * cik_ih_decode_iv - decode an interrupt vector |
| 261 | * | 233 | * |
| @@ -461,7 +433,6 @@ static const struct amd_ip_funcs cik_ih_ip_funcs = { · 199 unmodified lines | |||
| 461 | 433 | ||
| 462 | static const struct amdgpu_ih_funcs cik_ih_funcs = { | 434 | static const struct amdgpu_ih_funcs cik_ih_funcs = { |
| 463 | .get_wptr = cik_ih_get_wptr, | 435 | .get_wptr = cik_ih_get_wptr, |
| 464 | .prescreen_iv = cik_ih_prescreen_iv, | ||
| 465 | .decode_iv = cik_ih_decode_iv, | 436 | .decode_iv = cik_ih_decode_iv, |
| 466 | .set_rptr = cik_ih_set_rptr | 437 | .set_rptr = cik_ih_set_rptr |
| 467 | }; | 438 | }; |
| @@ -207,34 +207,6 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev) · 206 unmodified lines | |||
| 207 | return (wptr & adev->irq.ih.ptr_mask); | 207 | return (wptr & adev->irq.ih.ptr_mask); |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | /** | ||
| 211 | * cz_ih_prescreen_iv - prescreen an interrupt vector | ||
| 212 | * | ||
| 213 | * @adev: amdgpu_device pointer | ||
| 214 | * | ||
| 215 | * Returns true if the interrupt vector should be further processed. | ||
| 216 | */ | ||
| 217 | static bool cz_ih_prescreen_iv(struct amdgpu_device *adev) | ||
| 218 | { | ||
| 219 | u32 ring_index = adev->irq.ih.rptr >> 2; | ||
| 220 | u16 pasid; | ||
| 221 | |||
| 222 | switch (le32_to_cpu(adev->irq.ih.ring[ring_index]) & 0xff) { | ||
| 223 | case 146: | ||
| 224 | case 147: | ||
| 225 | pasid = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]) >> 16; | ||
| 226 | if (!pasid || amdgpu_vm_pasid_fault_credit(adev, pasid)) | ||
| 227 | return true; | ||
| 228 | break; | ||
| 229 | default: | ||
| 230 | /* Not a VM fault */ | ||
| 231 | return true; | ||
| 232 | } | ||
| 233 | |||
| 234 | adev->irq.ih.rptr += 16; | ||
| 235 | return false; | ||
| 236 | } | ||
| 237 | |||
| 238 | /** | 210 | /** |
| 239 | * cz_ih_decode_iv - decode an interrupt vector | 211 | * cz_ih_decode_iv - decode an interrupt vector |
| 240 | * | 212 | * |
| @@ -442,7 +414,6 @@ static const struct amd_ip_funcs cz_ih_ip_funcs = { · 201 unmodified lines | |||
| 442 | 414 | ||
| 443 | static const struct amdgpu_ih_funcs cz_ih_funcs = { | 415 | static const struct amdgpu_ih_funcs cz_ih_funcs = { |
| 444 | .get_wptr = cz_ih_get_wptr, | 416 | .get_wptr = cz_ih_get_wptr, |
| 445 | .prescreen_iv = cz_ih_prescreen_iv, | ||
| 446 | .decode_iv = cz_ih_decode_iv, | 417 | .decode_iv = cz_ih_decode_iv, |
| 447 | .set_rptr = cz_ih_set_rptr | 418 | .set_rptr = cz_ih_set_rptr |
| 448 | }; | 419 | }; |
| @@ -4068,6 +4068,11 @@ static void gfx_v8_0_rlc_start(struct amdgpu_device *adev) · 4067 unmodified lines | |||
| 4068 | 4068 | ||
| 4069 | static int gfx_v8_0_rlc_resume(struct amdgpu_device *adev) | 4069 | static int gfx_v8_0_rlc_resume(struct amdgpu_device *adev) |
| 4070 | { | 4070 | { |
| 4071 | if (amdgpu_sriov_vf(adev)) { | ||
| 4072 | gfx_v8_0_init_csb(adev); | ||
| 4073 | return 0; | ||
| 4074 | } | ||
| 4075 | |||
| 4071 | adev->gfx.rlc.funcs->stop(adev); | 4076 | adev->gfx.rlc.funcs->stop(adev); |
| 4072 | adev->gfx.rlc.funcs->reset(adev); | 4077 | adev->gfx.rlc.funcs->reset(adev); |
| 4073 | gfx_v8_0_init_pg(adev); | 4078 | gfx_v8_0_init_pg(adev); |
| @@ -4947,14 +4952,13 @@ static bool gfx_v8_0_check_soft_reset(void *handle) · 873 unmodified lines | |||
| 4947 | static int gfx_v8_0_pre_soft_reset(void *handle) | 4952 | static int gfx_v8_0_pre_soft_reset(void *handle) |
| 4948 | { | 4953 | { |
| 4949 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 4954 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 4950 | u32 grbm_soft_reset = 0, srbm_soft_reset = 0; | 4955 | u32 grbm_soft_reset = 0; |
| 4951 | 4956 | ||
| 4952 | if ((!adev->gfx.grbm_soft_reset) && | 4957 | if ((!adev->gfx.grbm_soft_reset) && |
| 4953 | (!adev->gfx.srbm_soft_reset)) | 4958 | (!adev->gfx.srbm_soft_reset)) |
| 4954 | return 0; | 4959 | return 0; |
| 4955 | 4960 | ||
| 4956 | grbm_soft_reset = adev->gfx.grbm_soft_reset; | 4961 | grbm_soft_reset = adev->gfx.grbm_soft_reset; |
| 4957 | srbm_soft_reset = adev->gfx.srbm_soft_reset; | ||
| 4958 | 4962 | ||
| 4959 | /* stop the rlc */ | 4963 | /* stop the rlc */ |
| 4960 | adev->gfx.rlc.funcs->stop(adev); | 4964 | adev->gfx.rlc.funcs->stop(adev); |
| @@ -5051,14 +5055,13 @@ static int gfx_v8_0_soft_reset(void *handle) · 90 unmodified lines | |||
| 5051 | static int gfx_v8_0_post_soft_reset(void *handle) | 5055 | static int gfx_v8_0_post_soft_reset(void *handle) |
| 5052 | { | 5056 | { |
| 5053 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 5057 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 5054 | u32 grbm_soft_reset = 0, srbm_soft_reset = 0; | 5058 | u32 grbm_soft_reset = 0; |
| 5055 | 5059 | ||
| 5056 | if ((!adev->gfx.grbm_soft_reset) && | 5060 | if ((!adev->gfx.grbm_soft_reset) && |
| 5057 | (!adev->gfx.srbm_soft_reset)) | 5061 | (!adev->gfx.srbm_soft_reset)) |
| 5058 | return 0; | 5062 | return 0; |
| 5059 | 5063 | ||
| 5060 | grbm_soft_reset = adev->gfx.grbm_soft_reset; | 5064 | grbm_soft_reset = adev->gfx.grbm_soft_reset; |
| 5061 | srbm_soft_reset = adev->gfx.srbm_soft_reset; | ||
| 5062 | 5065 | ||
| 5063 | if (REG_GET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_CP) || | 5066 | if (REG_GET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_CP) || |
| 5064 | REG_GET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_CPF) || | 5067 | REG_GET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_CPF) || |
| @@ -86,6 +86,7 @@ MODULE_FIRMWARE("amdgpu/picasso_me.bin"); · 85 unmodified lines | |||
| 86 | MODULE_FIRMWARE("amdgpu/picasso_mec.bin"); | 86 | MODULE_FIRMWARE("amdgpu/picasso_mec.bin"); |
| 87 | MODULE_FIRMWARE("amdgpu/picasso_mec2.bin"); | 87 | MODULE_FIRMWARE("amdgpu/picasso_mec2.bin"); |
| 88 | MODULE_FIRMWARE("amdgpu/picasso_rlc.bin"); | 88 | MODULE_FIRMWARE("amdgpu/picasso_rlc.bin"); |
| 89 | MODULE_FIRMWARE("amdgpu/picasso_rlc_am4.bin"); | ||
| 89 | 90 | ||
| 90 | MODULE_FIRMWARE("amdgpu/raven2_ce.bin"); | 91 | MODULE_FIRMWARE("amdgpu/raven2_ce.bin"); |
| 91 | MODULE_FIRMWARE("amdgpu/raven2_pfp.bin"); | 92 | MODULE_FIRMWARE("amdgpu/raven2_pfp.bin"); |
| @@ -645,7 +646,20 @@ static int gfx_v9_0_init_microcode(struct amdgpu_device *adev) · 553 unmodified lines | |||
| 645 | adev->gfx.ce_fw_version = le32_to_cpu(cp_hdr->header.ucode_version); | 646 | adev->gfx.ce_fw_version = le32_to_cpu(cp_hdr->header.ucode_version); |
| 646 | adev->gfx.ce_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version); | 647 | adev->gfx.ce_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version); |
| 647 | 648 | ||
| 648 | snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name); | 649 | /* |
| 650 | * For Picasso && AM4 SOCKET board, we use picasso_rlc_am4.bin | ||
| 651 | * instead of picasso_rlc.bin. | ||
| 652 | * Judgment method: | ||
| 653 | * PCO AM4: revision >= 0xC8 && revision <= 0xCF | ||
| 654 | * or revision >= 0xD8 && revision <= 0xDF | ||
| 655 | * otherwise is PCO FP5 | ||
| 656 | */ | ||
| 657 | if (!strcmp(chip_name, "picasso") && | ||
| 658 | (((adev->pdev->revision >= 0xC8) && (adev->pdev->revision <= 0xCF)) || | ||
| 659 | ((adev->pdev->revision >= 0xD8) && (adev->pdev->revision <= 0xDF)))) | ||
| 660 | snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc_am4.bin", chip_name); | ||
| 661 | else | ||
| 662 | snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name); | ||
| 649 | err = request_firmware(&adev->gfx.rlc_fw, fw_name, adev->dev); | 663 | err = request_firmware(&adev->gfx.rlc_fw, fw_name, adev->dev); |
| 650 | if (err) | 664 | if (err) |
| 651 | goto out; | 665 | goto out; |
| @@ -244,6 +244,62 @@ static int gmc_v9_0_vm_fault_interrupt_state(struct amdgpu_device *adev, · 243 unmodified lines | |||
| 244 | return 0; | 244 | return 0; |
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | /** | ||
| 248 | * vega10_ih_prescreen_iv - prescreen an interrupt vector | ||
| 249 | * | ||
| 250 | * @adev: amdgpu_device pointer | ||
| 251 | * | ||
| 252 | * Returns true if the interrupt vector should be further processed. | ||
| 253 | */ | ||
| 254 | static bool gmc_v9_0_prescreen_iv(struct amdgpu_device *adev, | ||
| 255 | struct amdgpu_iv_entry *entry, | ||
| 256 | uint64_t addr) | ||
| 257 | { | ||
| 258 | struct amdgpu_vm *vm; | ||
| 259 | u64 key; | ||
| 260 | int r; | ||
| 261 | |||
| 262 | /* No PASID, can't identify faulting process */ | ||
| 263 | if (!entry->pasid) | ||
| 264 | return true; | ||
| 265 | |||
| 266 | /* Not a retry fault */ | ||
| 267 | if (!(entry->src_data[1] & 0x80)) | ||
| 268 | return true; | ||
| 269 | |||
| 270 | /* Track retry faults in per-VM fault FIFO. */ | ||
| 271 | spin_lock(&adev->vm_manager.pasid_lock); | ||
| 272 | vm = idr_find(&adev->vm_manager.pasid_idr, entry->pasid); | ||
| 273 | if (!vm) { | ||
| 274 | /* VM not found, process it normally */ | ||
| 275 | spin_unlock(&adev->vm_manager.pasid_lock); | ||
| 276 | return true; | ||
| 277 | } | ||
| 278 | |||
| 279 | key = AMDGPU_VM_FAULT(entry->pasid, addr); | ||
| 280 | r = amdgpu_vm_add_fault(vm->fault_hash, key); | ||
| 281 | |||
| 282 | /* Hash table is full or the fault is already being processed, | ||
| 283 | * ignore further page faults | ||
| 284 | */ | ||
| 285 | if (r != 0) { | ||
| 286 | spin_unlock(&adev->vm_manager.pasid_lock); | ||
| 287 | return false; | ||
| 288 | } | ||
| 289 | /* No locking required with single writer and single reader */ | ||
| 290 | r = kfifo_put(&vm->faults, key); | ||
| 291 | if (!r) { | ||
| 292 | /* FIFO is full. Ignore it until there is space */ | ||
| 293 | amdgpu_vm_clear_fault(vm->fault_hash, key); | ||
| 294 | spin_unlock(&adev->vm_manager.pasid_lock); | ||
| 295 | return false; | ||
| 296 | } | ||
| 297 | |||
| 298 | spin_unlock(&adev->vm_manager.pasid_lock); | ||
| 299 | /* It's the first fault for this address, process it normally */ | ||
| 300 | return true; | ||
| 301 | } | ||
| 302 | |||
| 247 | static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, | 303 | static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, |
| 248 | struct amdgpu_irq_src *source, | 304 | struct amdgpu_irq_src *source, |
| 249 | struct amdgpu_iv_entry *entry) | 305 | struct amdgpu_iv_entry *entry) |
| @@ -255,6 +311,9 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, · 5 unmodified lines | |||
| 255 | addr = (u64)entry->src_data[0] << 12; | 311 | addr = (u64)entry->src_data[0] << 12; |
| 256 | addr |= ((u64)entry->src_data[1] & 0xf) << 44; | 312 | addr |= ((u64)entry->src_data[1] & 0xf) << 44; |
| 257 | 313 | ||
| 314 | if (!gmc_v9_0_prescreen_iv(adev, entry, addr)) | ||
| 315 | return 1; /* This also prevents sending it to KFD */ | ||
| 316 | |||
| 258 | if (!amdgpu_sriov_vf(adev)) { | 317 | if (!amdgpu_sriov_vf(adev)) { |
| 259 | status = RREG32(hub->vm_l2_pro_fault_status); | 318 | status = RREG32(hub->vm_l2_pro_fault_status); |
| 260 | WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1); | 319 | WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1); |
| @@ -902,6 +961,9 @@ static int gmc_v9_0_sw_init(void *handle) · 641 unmodified lines | |||
| 902 | /* This interrupt is VMC page fault.*/ | 961 | /* This interrupt is VMC page fault.*/ |
| 903 | r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VMC, VMC_1_0__SRCID__VM_FAULT, | 962 | r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VMC, VMC_1_0__SRCID__VM_FAULT, |
| 904 | &adev->gmc.vm_fault); | 963 | &adev->gmc.vm_fault); |
| 964 | if (r) | ||
| 965 | return r; | ||
| 966 | |||
| 905 | r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_UTCL2, UTCL2_1_0__SRCID__FAULT, | 967 | r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_UTCL2, UTCL2_1_0__SRCID__FAULT, |
| 906 | &adev->gmc.vm_fault); | 968 | &adev->gmc.vm_fault); |
| 907 | 969 | ||
| @@ -934,7 +996,7 @@ static int gmc_v9_0_sw_init(void *handle) · 26 unmodified lines | |||
| 934 | } | 996 | } |
| 935 | adev->need_swiotlb = drm_get_max_iomem() > ((u64)1 << dma_bits); | 997 | adev->need_swiotlb = drm_get_max_iomem() > ((u64)1 << dma_bits); |
| 936 | 998 | ||
| 937 | if (adev->asic_type == CHIP_VEGA20) { | 999 | if (adev->gmc.xgmi.supported) { |
| 938 | r = gfxhub_v1_1_get_xgmi_info(adev); | 1000 | r = gfxhub_v1_1_get_xgmi_info(adev); |
| 939 | if (r) | 1001 | if (r) |
| 940 | return r; | 1002 | return r; |
| @@ -207,34 +207,6 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev) · 206 unmodified lines | |||
| 207 | return (wptr & adev->irq.ih.ptr_mask); | 207 | return (wptr & adev->irq.ih.ptr_mask); |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | /** | ||
| 211 | * iceland_ih_prescreen_iv - prescreen an interrupt vector | ||
| 212 | * | ||
| 213 | * @adev: amdgpu_device pointer | ||
| 214 | * | ||
| 215 | * Returns true if the interrupt vector should be further processed. | ||
| 216 | */ | ||
| 217 | static bool iceland_ih_prescreen_iv(struct amdgpu_device *adev) | ||
| 218 | { | ||
| 219 | u32 ring_index = adev->irq.ih.rptr >> 2; | ||
| 220 | u16 pasid; | ||
| 221 | |||
| 222 | switch (le32_to_cpu(adev->irq.ih.ring[ring_index]) & 0xff) { | ||
| 223 | case 146: | ||
| 224 | case 147: | ||
| 225 | pasid = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]) >> 16; | ||
| 226 | if (!pasid || amdgpu_vm_pasid_fault_credit(adev, pasid)) | ||
| 227 | return true; | ||
| 228 | break; | ||
| 229 | default: | ||
| 230 | /* Not a VM fault */ | ||
| 231 | return true; | ||
| 232 | } | ||
| 233 | |||
| 234 | adev->irq.ih.rptr += 16; | ||
| 235 | return false; | ||
| 236 | } | ||
| 237 | |||
| 238 | /** | 210 | /** |
| 239 | * iceland_ih_decode_iv - decode an interrupt vector | 211 | * iceland_ih_decode_iv - decode an interrupt vector |
| 240 | * | 212 | * |
| @@ -440,7 +412,6 @@ static const struct amd_ip_funcs iceland_ih_ip_funcs = { · 199 unmodified lines | |||
| 440 | 412 | ||
| 441 | static const struct amdgpu_ih_funcs iceland_ih_funcs = { | 413 | static const struct amdgpu_ih_funcs iceland_ih_funcs = { |
| 442 | .get_wptr = iceland_ih_get_wptr, | 414 | .get_wptr = iceland_ih_get_wptr, |
| 443 | .prescreen_iv = iceland_ih_prescreen_iv, | ||
| 444 | .decode_iv = iceland_ih_decode_iv, | 415 | .decode_iv = iceland_ih_decode_iv, |
| 445 | .set_rptr = iceland_ih_set_rptr | 416 | .set_rptr = iceland_ih_set_rptr |
| 446 | }; | 417 | }; |
| @@ -43,6 +43,8 @@ enum psp_gfx_crtl_cmd_id · 42 unmodified lines | |||
| 43 | GFX_CTRL_CMD_ID_ENABLE_INT = 0x00050000, /* enable PSP-to-Gfx interrupt */ | 43 | GFX_CTRL_CMD_ID_ENABLE_INT = 0x00050000, /* enable PSP-to-Gfx interrupt */ |
| 44 | GFX_CTRL_CMD_ID_DISABLE_INT = 0x00060000, /* disable PSP-to-Gfx interrupt */ | 44 | GFX_CTRL_CMD_ID_DISABLE_INT = 0x00060000, /* disable PSP-to-Gfx interrupt */ |
| 45 | GFX_CTRL_CMD_ID_MODE1_RST = 0x00070000, /* trigger the Mode 1 reset */ | 45 | GFX_CTRL_CMD_ID_MODE1_RST = 0x00070000, /* trigger the Mode 1 reset */ |
| 46 | GFX_CTRL_CMD_ID_CONSUME_CMD = 0x000A0000, /* send interrupt to psp for updating write pointer of vf */ | ||
| 47 | GFX_CTRL_CMD_ID_DESTROY_GPCOM_RING = 0x000C0000, /* destroy GPCOM ring */ | ||
| 46 | 48 | ||
| 47 | GFX_CTRL_CMD_ID_MAX = 0x000F0000, /* max command ID */ | 49 | GFX_CTRL_CMD_ID_MAX = 0x000F0000, /* max command ID */ |
| 48 | }; | 50 | }; |
| @@ -89,7 +91,8 @@ enum psp_gfx_cmd_id · 40 unmodified lines | |||
| 89 | GFX_CMD_ID_LOAD_IP_FW = 0x00000006, /* load HW IP FW */ | 91 | GFX_CMD_ID_LOAD_IP_FW = 0x00000006, /* load HW IP FW */ |
| 90 | GFX_CMD_ID_DESTROY_TMR = 0x00000007, /* destroy TMR region */ | 92 | GFX_CMD_ID_DESTROY_TMR = 0x00000007, /* destroy TMR region */ |
| 91 | GFX_CMD_ID_SAVE_RESTORE = 0x00000008, /* save/restore HW IP FW */ | 93 | GFX_CMD_ID_SAVE_RESTORE = 0x00000008, /* save/restore HW IP FW */ |
| 92 | 94 | GFX_CMD_ID_SETUP_VMR = 0x00000009, /* setup VMR region */ | |
| 95 | GFX_CMD_ID_DESTROY_VMR = 0x0000000A, /* destroy VMR region */ | ||
| 93 | }; | 96 | }; |
| 94 | 97 | ||
| 95 | 98 | ||
| @@ -171,8 +171,11 @@ static int psp_v11_0_bootloader_load_sysdrv(struct psp_context *psp) · 170 unmodified lines | |||
| 171 | * are already been loaded. | 171 | * are already been loaded. |
| 172 | */ | 172 | */ |
| 173 | sol_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81); | 173 | sol_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81); |
| 174 | if (sol_reg) | 174 | if (sol_reg) { |
| 175 | psp->sos_fw_version = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_58); | ||
| 176 | printk("sos fw version = 0x%x.\n", psp->sos_fw_version); | ||
| 175 | return 0; | 177 | return 0; |
| 178 | } | ||
| 176 | 179 | ||
| 177 | /* Wait for bootloader to signify that is ready having bit 31 of C2PMSG_35 set to 1 */ | 180 | /* Wait for bootloader to signify that is ready having bit 31 of C2PMSG_35 set to 1 */ |
| 178 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), | 181 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), |
| @@ -296,26 +299,47 @@ static int psp_v11_0_ring_create(struct psp_context *psp, · 117 unmodified lines | |||
| 296 | struct psp_ring *ring = &psp->km_ring; | 299 | struct psp_ring *ring = &psp->km_ring; |
| 297 | struct amdgpu_device *adev = psp->adev; | 300 | struct amdgpu_device *adev = psp->adev; |
| 298 | 301 | ||
| 299 | /* Write low address of the ring to C2PMSG_69 */ | 302 | if (psp_support_vmr_ring(psp)) { |
| 300 | psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); | 303 | /* Write low address of the ring to C2PMSG_102 */ |
| 301 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_69, psp_ring_reg); | 304 | psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); |
| 302 | /* Write high address of the ring to C2PMSG_70 */ | 305 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, psp_ring_reg); |
| 303 | psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); | 306 | /* Write high address of the ring to C2PMSG_103 */ |
| 304 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_70, psp_ring_reg); | 307 | psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); |
| 305 | /* Write size of ring to C2PMSG_71 */ | 308 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_103, psp_ring_reg); |
| 306 | psp_ring_reg = ring->ring_size; | 309 | |
| 307 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_71, psp_ring_reg); | 310 | /* Write the ring initialization command to C2PMSG_101 */ |
| 308 | /* Write the ring initialization command to C2PMSG_64 */ | 311 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, |
| 309 | psp_ring_reg = ring_type; | 312 | GFX_CTRL_CMD_ID_INIT_GPCOM_RING); |
| 310 | psp_ring_reg = psp_ring_reg << 16; | 313 | |
| 311 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, psp_ring_reg); | 314 | /* there might be handshake issue with hardware which needs delay */ |
| 312 | 315 | mdelay(20); | |
| 313 | /* there might be handshake issue with hardware which needs delay */ | 316 | |
| 314 | mdelay(20); | 317 | /* Wait for response flag (bit 31) in C2PMSG_101 */ |
| 315 | 318 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101), | |
| 316 | /* Wait for response flag (bit 31) in C2PMSG_64 */ | 319 | 0x80000000, 0x8000FFFF, false); |
| 317 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), | 320 | |
| 318 | 0x80000000, 0x8000FFFF, false); | 321 | } else { |
| 322 | /* Write low address of the ring to C2PMSG_69 */ | ||
| 323 | psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); | ||
| 324 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_69, psp_ring_reg); | ||
| 325 | /* Write high address of the ring to C2PMSG_70 */ | ||
| 326 | psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); | ||
| 327 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_70, psp_ring_reg); | ||
| 328 | /* Write size of ring to C2PMSG_71 */ | ||
| 329 | psp_ring_reg = ring->ring_size; | ||
| 330 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_71, psp_ring_reg); | ||
| 331 | /* Write the ring initialization command to C2PMSG_64 */ | ||
| 332 | psp_ring_reg = ring_type; | ||
| 333 | psp_ring_reg = psp_ring_reg << 16; | ||
| 334 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, psp_ring_reg); | ||
| 335 | |||
| 336 | /* there might be handshake issue with hardware which needs delay */ | ||
| 337 | mdelay(20); | ||
| 338 | |||
| 339 | /* Wait for response flag (bit 31) in C2PMSG_64 */ | ||
| 340 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), | ||
| 341 | 0x80000000, 0x8000FFFF, false); | ||
| 342 | } | ||
| 319 | 343 | ||
| 320 | return ret; | 344 | return ret; |
| 321 | } | 345 | } |
| @@ -326,15 +350,24 @@ static int psp_v11_0_ring_stop(struct psp_context *psp, · 4 unmodified lines | |||
| 326 | int ret = 0; | 350 | int ret = 0; |
| 327 | struct amdgpu_device *adev = psp->adev; | 351 | struct amdgpu_device *adev = psp->adev; |
| 328 | 352 | ||
| 329 | /* Write the ring destroy command to C2PMSG_64 */ | 353 | /* Write the ring destroy command*/ |
| 330 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, GFX_CTRL_CMD_ID_DESTROY_RINGS); | 354 | if (psp_support_vmr_ring(psp)) |
| 355 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, | ||
| 356 | GFX_CTRL_CMD_ID_DESTROY_GPCOM_RING); | ||
| 357 | else | ||
| 358 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, | ||
| 359 | GFX_CTRL_CMD_ID_DESTROY_RINGS); | ||
| 331 | 360 | ||
| 332 | /* there might be handshake issue with hardware which needs delay */ | 361 | /* there might be handshake issue with hardware which needs delay */ |
| 333 | mdelay(20); | 362 | mdelay(20); |
| 334 | 363 | ||
| 335 | /* Wait for response flag (bit 31) in C2PMSG_64 */ | 364 | /* Wait for response flag (bit 31) */ |
| 336 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), | 365 | if (psp_support_vmr_ring(psp)) |
| 337 | 0x80000000, 0x80000000, false); | 366 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101), |
| 367 | 0x80000000, 0x80000000, false); | ||
| 368 | else | ||
| 369 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), | ||
| 370 | 0x80000000, 0x80000000, false); | ||
| 338 | 371 | ||
| 339 | return ret; | 372 | return ret; |
| 340 | } | 373 | } |
| @@ -373,7 +406,10 @@ static int psp_v11_0_cmd_submit(struct psp_context *psp, · 32 unmodified lines | |||
| 373 | uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4; | 406 | uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4; |
| 374 | 407 | ||
| 375 | /* KM (GPCOM) prepare write pointer */ | 408 | /* KM (GPCOM) prepare write pointer */ |
| 376 | psp_write_ptr_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67); | 409 | if (psp_support_vmr_ring(psp)) |
| 410 | psp_write_ptr_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102); | ||
| 411 | else | ||
| 412 | psp_write_ptr_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67); | ||
| 377 | 413 | ||
| 378 | /* Update KM RB frame pointer to new frame */ | 414 | /* Update KM RB frame pointer to new frame */ |
| 379 | /* write_frame ptr increments by size of rb_frame in bytes */ | 415 | /* write_frame ptr increments by size of rb_frame in bytes */ |
| @@ -402,7 +438,11 @@ static int psp_v11_0_cmd_submit(struct psp_context *psp, · 22 unmodified lines | |||
| 402 | 438 | ||
| 403 | /* Update the write Pointer in DWORDs */ | 439 | /* Update the write Pointer in DWORDs */ |
| 404 | psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw; | 440 | psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw; |
| 405 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, psp_write_ptr_reg); | 441 | if (psp_support_vmr_ring(psp)) { |
| 442 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, psp_write_ptr_reg); | ||
| 443 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, GFX_CTRL_CMD_ID_CONSUME_CMD); | ||
| 444 | } else | ||
| 445 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, psp_write_ptr_reg); | ||
| 406 | 446 | ||
| 407 | return 0; | 447 | return 0; |
| 408 | } | 448 | } |
| @@ -547,7 +587,7 @@ static int psp_v11_0_mode1_reset(struct psp_context *psp) · 138 unmodified lines | |||
| 547 | /*send the mode 1 reset command*/ | 587 | /*send the mode 1 reset command*/ |
| 548 | WREG32(offset, GFX_CTRL_CMD_ID_MODE1_RST); | 588 | WREG32(offset, GFX_CTRL_CMD_ID_MODE1_RST); |
| 549 | 589 | ||
| 550 | mdelay(1000); | 590 | msleep(500); |
| 551 | 591 | ||
| 552 | offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_33); | 592 | offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_33); |
| 553 | 593 | ||
| @@ -592,7 +592,7 @@ static int psp_v3_1_mode1_reset(struct psp_context *psp) · 591 unmodified lines | |||
| 592 | /*send the mode 1 reset command*/ | 592 | /*send the mode 1 reset command*/ |
| 593 | WREG32(offset, GFX_CTRL_CMD_ID_MODE1_RST); | 593 | WREG32(offset, GFX_CTRL_CMD_ID_MODE1_RST); |
| 594 | 594 | ||
| 595 | mdelay(1000); | 595 | msleep(500); |
| 596 | 596 | ||
| 597 | offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_33); | 597 | offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_33); |
| 598 | 598 | ||
| @@ -118,19 +118,6 @@ static u32 si_ih_get_wptr(struct amdgpu_device *adev) · 117 unmodified lines | |||
| 118 | return (wptr & adev->irq.ih.ptr_mask); | 118 | return (wptr & adev->irq.ih.ptr_mask); |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | /** | ||
| 122 | * si_ih_prescreen_iv - prescreen an interrupt vector | ||
| 123 | * | ||
| 124 | * @adev: amdgpu_device pointer | ||
| 125 | * | ||
| 126 | * Returns true if the interrupt vector should be further processed. | ||
| 127 | */ | ||
| 128 | static bool si_ih_prescreen_iv(struct amdgpu_device *adev) | ||
| 129 | { | ||
| 130 | /* Process all interrupts */ | ||
| 131 | return true; | ||
| 132 | } | ||
| 133 | |||
| 134 | static void si_ih_decode_iv(struct amdgpu_device *adev, | 121 | static void si_ih_decode_iv(struct amdgpu_device *adev, |
| 135 | struct amdgpu_iv_entry *entry) | 122 | struct amdgpu_iv_entry *entry) |
| 136 | { | 123 | { |
| @@ -301,7 +288,6 @@ static const struct amd_ip_funcs si_ih_ip_funcs = { · 164 unmodified lines | |||
| 301 | 288 | ||
| 302 | static const struct amdgpu_ih_funcs si_ih_funcs = { | 289 | static const struct amdgpu_ih_funcs si_ih_funcs = { |
| 303 | .get_wptr = si_ih_get_wptr, | 290 | .get_wptr = si_ih_get_wptr, |
| 304 | .prescreen_iv = si_ih_prescreen_iv, | ||
| 305 | .decode_iv = si_ih_decode_iv, | 291 | .decode_iv = si_ih_decode_iv, |
| 306 | .set_rptr = si_ih_set_rptr | 292 | .set_rptr = si_ih_set_rptr |
| 307 | }; | 293 | }; |
| @@ -507,6 +507,9 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev) · 506 unmodified lines | |||
| 507 | return -EINVAL; | 507 | return -EINVAL; |
| 508 | } | 508 | } |
| 509 | 509 | ||
| 510 | if (adev->asic_type == CHIP_VEGA20) | ||
| 511 | adev->gmc.xgmi.supported = true; | ||
| 512 | |||
| 510 | if (adev->flags & AMD_IS_APU) | 513 | if (adev->flags & AMD_IS_APU) |
| 511 | adev->nbio_funcs = &nbio_v7_0_funcs; | 514 | adev->nbio_funcs = &nbio_v7_0_funcs; |
| 512 | else if (adev->asic_type == CHIP_VEGA20) | 515 | else if (adev->asic_type == CHIP_VEGA20) |
| @@ -218,34 +218,6 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev) · 217 unmodified lines | |||
| 218 | return (wptr & adev->irq.ih.ptr_mask); | 218 | return (wptr & adev->irq.ih.ptr_mask); |
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | /** | ||
| 222 | * tonga_ih_prescreen_iv - prescreen an interrupt vector | ||
| 223 | * | ||
| 224 | * @adev: amdgpu_device pointer | ||
| 225 | * | ||
| 226 | * Returns true if the interrupt vector should be further processed. | ||
| 227 | */ | ||
| 228 | static bool tonga_ih_prescreen_iv(struct amdgpu_device *adev) | ||
| 229 | { | ||
| 230 | u32 ring_index = adev->irq.ih.rptr >> 2; | ||
| 231 | u16 pasid; | ||
| 232 | |||
| 233 | switch (le32_to_cpu(adev->irq.ih.ring[ring_index]) & 0xff) { | ||
| 234 | case 146: | ||
| 235 | case 147: | ||
| 236 | pasid = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]) >> 16; | ||
| 237 | if (!pasid || amdgpu_vm_pasid_fault_credit(adev, pasid)) | ||
| 238 | return true; | ||
| 239 | break; | ||
| 240 | default: | ||
| 241 | /* Not a VM fault */ | ||
| 242 | return true; | ||
| 243 | } | ||
| 244 | |||
| 245 | adev->irq.ih.rptr += 16; | ||
| 246 | return false; | ||
| 247 | } | ||
| 248 | |||
| 249 | /** | 221 | /** |
| 250 | * tonga_ih_decode_iv - decode an interrupt vector | 222 | * tonga_ih_decode_iv - decode an interrupt vector |
| 251 | * | 223 | * |
| @@ -506,7 +478,6 @@ static const struct amd_ip_funcs tonga_ih_ip_funcs = { · 254 unmodified lines | |||
| 506 | 478 | ||
| 507 | static const struct amdgpu_ih_funcs tonga_ih_funcs = { | 479 | static const struct amdgpu_ih_funcs tonga_ih_funcs = { |
| 508 | .get_wptr = tonga_ih_get_wptr, | 480 | .get_wptr = tonga_ih_get_wptr, |
| 509 | .prescreen_iv = tonga_ih_prescreen_iv, | ||
| 510 | .decode_iv = tonga_ih_decode_iv, | 481 | .decode_iv = tonga_ih_decode_iv, |
| 511 | .set_rptr = tonga_ih_set_rptr | 482 | .set_rptr = tonga_ih_set_rptr |
| 512 | }; | 483 | }; |
| @@ -219,90 +219,6 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev) · 218 unmodified lines | |||
| 219 | return (wptr & adev->irq.ih.ptr_mask); | 219 | return (wptr & adev->irq.ih.ptr_mask); |
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | /** | ||
| 223 | * vega10_ih_prescreen_iv - prescreen an interrupt vector | ||
| 224 | * | ||
| 225 | * @adev: amdgpu_device pointer | ||
| 226 | * | ||
| 227 | * Returns true if the interrupt vector should be further processed. | ||
| 228 | */ | ||
| 229 | static bool vega10_ih_prescreen_iv(struct amdgpu_device *adev) | ||
| 230 | { | ||
| 231 | u32 ring_index = adev->irq.ih.rptr >> 2; | ||
| 232 | u32 dw0, dw3, dw4, dw5; | ||
| 233 | u16 pasid; | ||
| 234 | u64 addr, key; | ||
| 235 | struct amdgpu_vm *vm; | ||
| 236 | int r; | ||
| 237 | |||
| 238 | dw0 = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]); | ||
| 239 | dw3 = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]); | ||
| 240 | dw4 = le32_to_cpu(adev->irq.ih.ring[ring_index + 4]); | ||
| 241 | dw5 = le32_to_cpu(adev->irq.ih.ring[ring_index + 5]); | ||
| 242 | |||
| 243 | /* Filter retry page faults, let only the first one pass. If | ||
| 244 | * there are too many outstanding faults, ignore them until | ||
| 245 | * some faults get cleared. | ||
| 246 | */ | ||
| 247 | switch (dw0 & 0xff) { | ||
| 248 | case SOC15_IH_CLIENTID_VMC: | ||
| 249 | case SOC15_IH_CLIENTID_UTCL2: | ||
| 250 | break; | ||
| 251 | default: | ||
| 252 | /* Not a VM fault */ | ||
| 253 | return true; | ||
| 254 | } | ||
| 255 | |||
| 256 | pasid = dw3 & 0xffff; | ||
| 257 | /* No PASID, can't identify faulting process */ | ||
| 258 | if (!pasid) | ||
| 259 | return true; | ||
| 260 | |||
| 261 | /* Not a retry fault, check fault credit */ | ||
| 262 | if (!(dw5 & 0x80)) { | ||
| 263 | if (!amdgpu_vm_pasid_fault_credit(adev, pasid)) | ||
| 264 | goto ignore_iv; | ||
| 265 | return true; | ||
| 266 | } | ||
| 267 | |||
| 268 | /* Track retry faults in per-VM fault FIFO. */ | ||
| 269 | spin_lock(&adev->vm_manager.pasid_lock); | ||
| 270 | vm = idr_find(&adev->vm_manager.pasid_idr, pasid); | ||
| 271 | addr = ((u64)(dw5 & 0xf) << 44) | ((u64)dw4 << 12); | ||
| 272 | key = AMDGPU_VM_FAULT(pasid, addr); | ||
| 273 | if (!vm) { | ||
| 274 | /* VM not found, process it normally */ | ||
| 275 | spin_unlock(&adev->vm_manager.pasid_lock); | ||
| 276 | return true; | ||
| 277 | } else { | ||
| 278 | r = amdgpu_vm_add_fault(vm->fault_hash, key); | ||
| 279 | |||
| 280 | /* Hash table is full or the fault is already being processed, | ||
| 281 | * ignore further page faults | ||
| 282 | */ | ||
| 283 | if (r != 0) { | ||
| 284 | spin_unlock(&adev->vm_manager.pasid_lock); | ||
| 285 | goto ignore_iv; | ||
| 286 | } | ||
| 287 | } | ||
| 288 | /* No locking required with single writer and single reader */ | ||
| 289 | r = kfifo_put(&vm->faults, key); | ||
| 290 | if (!r) { | ||
| 291 | /* FIFO is full. Ignore it until there is space */ | ||
| 292 | amdgpu_vm_clear_fault(vm->fault_hash, key); | ||
| 293 | spin_unlock(&adev->vm_manager.pasid_lock); | ||
| 294 | goto ignore_iv; | ||
| 295 | } | ||
| 296 | |||
| 297 | spin_unlock(&adev->vm_manager.pasid_lock); | ||
| 298 | /* It's the first fault for this address, process it normally */ | ||
| 299 | return true; | ||
| 300 | |||
| 301 | ignore_iv: | ||
| 302 | adev->irq.ih.rptr += 32; | ||
| 303 | return false; | ||
| 304 | } | ||
| 305 | |||
| 306 | /** | 222 | /** |
| 307 | * vega10_ih_decode_iv - decode an interrupt vector | 223 | * vega10_ih_decode_iv - decode an interrupt vector |
| 308 | * | 224 | * |
| @@ -487,7 +403,6 @@ const struct amd_ip_funcs vega10_ih_ip_funcs = { · 178 unmodified lines | |||
| 487 | 403 | ||
| 488 | static const struct amdgpu_ih_funcs vega10_ih_funcs = { | 404 | static const struct amdgpu_ih_funcs vega10_ih_funcs = { |
| 489 | .get_wptr = vega10_ih_get_wptr, | 405 | .get_wptr = vega10_ih_get_wptr, |
| 490 | .prescreen_iv = vega10_ih_prescreen_iv, | ||
| 491 | .decode_iv = vega10_ih_decode_iv, | 406 | .decode_iv = vega10_ih_decode_iv, |
| 492 | .set_rptr = vega10_ih_set_rptr | 407 | .set_rptr = vega10_ih_set_rptr |
| 493 | }; | 408 | }; |
| @@ -33,6 +33,7 @@ · 32 unmodified lines | |||
| 33 | #include <linux/time.h> | 33 | #include <linux/time.h> |
| 34 | #include <linux/mm.h> | 34 | #include <linux/mm.h> |
| 35 | #include <linux/mman.h> | 35 | #include <linux/mman.h> |
| 36 | #include <linux/dma-buf.h> | ||
| 36 | #include <asm/processor.h> | 37 | #include <asm/processor.h> |
| 37 | #include "kfd_priv.h" | 38 | #include "kfd_priv.h" |
| 38 | #include "kfd_device_queue_manager.h" | 39 | #include "kfd_device_queue_manager.h" |
| @@ -1273,6 +1274,12 @@ static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep, · 1234 unmodified lines | |||
| 1273 | return -EINVAL; | 1274 | return -EINVAL; |
| 1274 | } | 1275 | } |
| 1275 | 1276 | ||
| 1277 | if (flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) { | ||
| 1278 | if (args->size != kfd_doorbell_process_slice(dev)) | ||
| 1279 | return -EINVAL; | ||
| 1280 | offset = kfd_get_process_doorbells(dev, p); | ||
| 1281 | } | ||
| 1282 | |||
| 1276 | mutex_lock(&p->mutex); | 1283 | mutex_lock(&p->mutex); |
| 1277 | 1284 | ||
| 1278 | pdd = kfd_bind_process_to_device(dev, p); | 1285 | pdd = kfd_bind_process_to_device(dev, p); |
| @@ -1550,6 +1557,115 @@ copy_from_user_failed: · 271 unmodified lines | |||
| 1550 | return err; | 1557 | return err; |
| 1551 | } | 1558 | } |
| 1552 | 1559 | ||
| 1560 | static int kfd_ioctl_get_dmabuf_info(struct file *filep, | ||
| 1561 | struct kfd_process *p, void *data) | ||
| 1562 | { | ||
| 1563 | struct kfd_ioctl_get_dmabuf_info_args *args = data; | ||
| 1564 | struct kfd_dev *dev = NULL; | ||
| 1565 | struct kgd_dev *dma_buf_kgd; | ||
| 1566 | void *metadata_buffer = NULL; | ||
| 1567 | uint32_t flags; | ||
| 1568 | unsigned int i; | ||
| 1569 | int r; | ||
| 1570 | |||
| 1571 | /* Find a KFD GPU device that supports the get_dmabuf_info query */ | ||
| 1572 | for (i = 0; kfd_topology_enum_kfd_devices(i, &dev) == 0; i++) | ||
| 1573 | if (dev) | ||
| 1574 | break; | ||
| 1575 | if (!dev) | ||
| 1576 | return -EINVAL; | ||
| 1577 | |||
| 1578 | if (args->metadata_ptr) { | ||
| 1579 | metadata_buffer = kzalloc(args->metadata_size, GFP_KERNEL); | ||
| 1580 | if (!metadata_buffer) | ||
| 1581 | return -ENOMEM; | ||
| 1582 | } | ||
| 1583 | |||
| 1584 | /* Get dmabuf info from KGD */ | ||
| 1585 | r = amdgpu_amdkfd_get_dmabuf_info(dev->kgd, args->dmabuf_fd, | ||
| 1586 | &dma_buf_kgd, &args->size, | ||
| 1587 | metadata_buffer, args->metadata_size, | ||
| 1588 | &args->metadata_size, &flags); | ||
| 1589 | if (r) | ||
| 1590 | goto exit; | ||
| 1591 | |||
| 1592 | /* Reverse-lookup gpu_id from kgd pointer */ | ||
| 1593 | dev = kfd_device_by_kgd(dma_buf_kgd); | ||
| 1594 | if (!dev) { | ||
| 1595 | r = -EINVAL; | ||
| 1596 | goto exit; | ||
| 1597 | } | ||
| 1598 | args->gpu_id = dev->id; | ||
| 1599 | args->flags = flags; | ||
| 1600 | |||
| 1601 | /* Copy metadata buffer to user mode */ | ||
| 1602 | if (metadata_buffer) { | ||
| 1603 | r = copy_to_user((void __user *)args->metadata_ptr, | ||
| 1604 | metadata_buffer, args->metadata_size); | ||
| 1605 | if (r != 0) | ||
| 1606 | r = -EFAULT; | ||
| 1607 | } | ||
| 1608 | |||
| 1609 | exit: | ||
| 1610 | kfree(metadata_buffer); | ||
| 1611 | |||
| 1612 | return r; | ||
| 1613 | } | ||
| 1614 | |||
| 1615 | static int kfd_ioctl_import_dmabuf(struct file *filep, | ||
| 1616 | struct kfd_process *p, void *data) | ||
| 1617 | { | ||
| 1618 | struct kfd_ioctl_import_dmabuf_args *args = data; | ||
| 1619 | struct kfd_process_device *pdd; | ||
| 1620 | struct dma_buf *dmabuf; | ||
| 1621 | struct kfd_dev *dev; | ||
| 1622 | int idr_handle; | ||
| 1623 | uint64_t size; | ||
| 1624 | void *mem; | ||
| 1625 | int r; | ||
| 1626 | |||
| 1627 | dev = kfd_device_by_id(args->gpu_id); | ||
| 1628 | if (!dev) | ||
| 1629 | return -EINVAL; | ||
| 1630 | |||
| 1631 | dmabuf = dma_buf_get(args->dmabuf_fd); | ||
| 1632 | if (!dmabuf) | ||
| 1633 | return -EINVAL; | ||
| 1634 | |||
| 1635 | mutex_lock(&p->mutex); | ||
| 1636 | |||
| 1637 | pdd = kfd_bind_process_to_device(dev, p); | ||
| 1638 | if (IS_ERR(pdd)) { | ||
| 1639 | r = PTR_ERR(pdd); | ||
| 1640 | goto err_unlock; | ||
| 1641 | } | ||
| 1642 | |||
| 1643 | r = amdgpu_amdkfd_gpuvm_import_dmabuf(dev->kgd, dmabuf, | ||
| 1644 | args->va_addr, pdd->vm, | ||
| 1645 | (struct kgd_mem **)&mem, &size, | ||
| 1646 | NULL); | ||
| 1647 | if (r) | ||
| 1648 | goto err_unlock; | ||
| 1649 | |||
| 1650 | idr_handle = kfd_process_device_create_obj_handle(pdd, mem); | ||
| 1651 | if (idr_handle < 0) { | ||
| 1652 | r = -EFAULT; | ||
| 1653 | goto err_free; | ||
| 1654 | } | ||
| 1655 | |||
| 1656 | mutex_unlock(&p->mutex); | ||
| 1657 | |||
| 1658 | args->handle = MAKE_HANDLE(args->gpu_id, idr_handle); | ||
| 1659 | |||
| 1660 | return 0; | ||
| 1661 | |||
| 1662 | err_free: | ||
| 1663 | amdgpu_amdkfd_gpuvm_free_memory_of_gpu(dev->kgd, (struct kgd_mem *)mem); | ||
| 1664 | err_unlock: | ||
| 1665 | mutex_unlock(&p->mutex); | ||
| 1666 | return r; | ||
| 1667 | } | ||
| 1668 | |||
| 1553 | #define AMDKFD_IOCTL_DEF(ioctl, _func, _flags) \ | 1669 | #define AMDKFD_IOCTL_DEF(ioctl, _func, _flags) \ |
| 1554 | [_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, \ | 1670 | [_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, \ |
| 1555 | .cmd_drv = 0, .name = #ioctl} | 1671 | .cmd_drv = 0, .name = #ioctl} |
| @@ -1635,7 +1751,13 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = { · 79 unmodified lines | |||
| 1635 | kfd_ioctl_set_cu_mask, 0), | 1751 | kfd_ioctl_set_cu_mask, 0), |
| 1636 | 1752 | ||
| 1637 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_QUEUE_WAVE_STATE, | 1753 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_QUEUE_WAVE_STATE, |
| 1638 | kfd_ioctl_get_queue_wave_state, 0) | 1754 | kfd_ioctl_get_queue_wave_state, 0), |
| 1755 | |||
| 1756 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_DMABUF_INFO, | ||
| 1757 | kfd_ioctl_get_dmabuf_info, 0), | ||
| 1758 | |||
| 1759 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_IMPORT_DMABUF, | ||
| 1760 | kfd_ioctl_import_dmabuf, 0), | ||
| 1639 | 1761 | ||
| 1640 | }; | 1762 | }; |
| 1641 | 1763 | ||
| @@ -793,6 +793,7 @@ struct kfd_topology_device *kfd_topology_device_by_proximity_domain( · 792 unmodified lines | |||
| 793 | struct kfd_topology_device *kfd_topology_device_by_id(uint32_t gpu_id); | 793 | struct kfd_topology_device *kfd_topology_device_by_id(uint32_t gpu_id); |
| 794 | struct kfd_dev *kfd_device_by_id(uint32_t gpu_id); | 794 | struct kfd_dev *kfd_device_by_id(uint32_t gpu_id); |
| 795 | struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev); | 795 | struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev); |
| 796 | struct kfd_dev *kfd_device_by_kgd(const struct kgd_dev *kgd); | ||
| 796 | int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev); | 797 | int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev); |
| 797 | int kfd_numa_node_to_apic_id(int numa_node_id); | 798 | int kfd_numa_node_to_apic_id(int numa_node_id); |
| 798 | 799 | ||
| @@ -101,7 +101,25 @@ struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev) · 100 unmodified lines | |||
| 101 | down_read(&topology_lock); | 101 | down_read(&topology_lock); |
| 102 | 102 | ||
| 103 | list_for_each_entry(top_dev, &topology_device_list, list) | 103 | list_for_each_entry(top_dev, &topology_device_list, list) |
| 104 | if (top_dev->gpu->pdev == pdev) { | 104 | if (top_dev->gpu && top_dev->gpu->pdev == pdev) { |
| 105 | device = top_dev->gpu; | ||
| 106 | break; | ||
| 107 | } | ||
| 108 | |||
| 109 | up_read(&topology_lock); | ||
| 110 | |||
| 111 | return device; | ||
| 112 | } | ||
| 113 | |||
| 114 | struct kfd_dev *kfd_device_by_kgd(const struct kgd_dev *kgd) | ||
| 115 | { | ||
| 116 | struct kfd_topology_device *top_dev; | ||
| 117 | struct kfd_dev *device = NULL; | ||
| 118 | |||
| 119 | down_read(&topology_lock); | ||
| 120 | |||
| 121 | list_for_each_entry(top_dev, &topology_device_list, list) | ||
| 122 | if (top_dev->gpu && top_dev->gpu->kgd == kgd) { | ||
| 105 | device = top_dev->gpu; | 123 | device = top_dev->gpu; |
| 106 | break; | 124 | break; |
| 107 | } | 125 | } |
| @@ -23,6 +23,9 @@ · 22 unmodified lines | |||
| 23 | * | 23 | * |
| 24 | */ | 24 | */ |
| 25 | 25 | ||
| 26 | /* The caprices of the preprocessor require that this be declared right here */ | ||
| 27 | #define CREATE_TRACE_POINTS | ||
| 28 | |||
| 26 | #include "dm_services_types.h" | 29 | #include "dm_services_types.h" |
| 27 | #include "dc.h" | 30 | #include "dc.h" |
| 28 | #include "dc/inc/core_types.h" | 31 | #include "dc/inc/core_types.h" |
| @@ -54,6 +57,7 @@ · 25 unmodified lines | |||
| 54 | 57 | ||
| 55 | #include <drm/drmP.h> | 58 | #include <drm/drmP.h> |
| 56 | #include <drm/drm_atomic.h> | 59 | #include <drm/drm_atomic.h> |
| 60 | #include <drm/drm_atomic_uapi.h> | ||
| 57 | #include <drm/drm_atomic_helper.h> | 61 | #include <drm/drm_atomic_helper.h> |
| 58 | #include <drm/drm_dp_mst_helper.h> | 62 | #include <drm/drm_dp_mst_helper.h> |
| 59 | #include <drm/drm_fb_helper.h> | 63 | #include <drm/drm_fb_helper.h> |
| @@ -72,6 +76,7 @@ · 12 unmodified lines | |||
| 72 | 76 | ||
| 73 | #include "modules/inc/mod_freesync.h" | 77 | #include "modules/inc/mod_freesync.h" |
| 74 | #include "modules/power/power_helpers.h" | 78 | #include "modules/power/power_helpers.h" |
| 79 | #include "modules/inc/mod_info_packet.h" | ||
| 75 | 80 | ||
| 76 | #define FIRMWARE_RAVEN_DMCU "amdgpu/raven_dmcu.bin" | 81 | #define FIRMWARE_RAVEN_DMCU "amdgpu/raven_dmcu.bin" |
| 77 | MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU); | 82 | MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU); |
| @@ -129,6 +134,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state); · 51 unmodified lines | |||
| 129 | static int amdgpu_dm_atomic_check(struct drm_device *dev, | 134 | static int amdgpu_dm_atomic_check(struct drm_device *dev, |
| 130 | struct drm_atomic_state *state); | 135 | struct drm_atomic_state *state); |
| 131 | 136 | ||
| 137 | static void handle_cursor_update(struct drm_plane *plane, | ||
| 138 | struct drm_plane_state *old_plane_state); | ||
| 132 | 139 | ||
| 133 | 140 | ||
| 134 | 141 | ||
| @@ -398,6 +405,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) · 263 unmodified lines | |||
| 398 | /* Zero all the fields */ | 405 | /* Zero all the fields */ |
| 399 | memset(&init_data, 0, sizeof(init_data)); | 406 | memset(&init_data, 0, sizeof(init_data)); |
| 400 | 407 | ||
| 408 | mutex_init(&adev->dm.dc_lock); | ||
| 409 | |||
| 401 | if(amdgpu_dm_irq_init(adev)) { | 410 | if(amdgpu_dm_irq_init(adev)) { |
| 402 | DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n"); | 411 | DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n"); |
| 403 | goto error; | 412 | goto error; |
| @@ -512,6 +521,9 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) · 108 unmodified lines | |||
| 512 | /* DC Destroy TODO: Replace destroy DAL */ | 521 | /* DC Destroy TODO: Replace destroy DAL */ |
| 513 | if (adev->dm.dc) | 522 | if (adev->dm.dc) |
| 514 | dc_destroy(&adev->dm.dc); | 523 | dc_destroy(&adev->dm.dc); |
| 524 | |||
| 525 | mutex_destroy(&adev->dm.dc_lock); | ||
| 526 | |||
| 515 | return; | 527 | return; |
| 516 | } | 528 | } |
| 517 | 529 | ||
| @@ -2930,6 +2942,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, · 2412 unmodified lines | |||
| 2930 | 2942 | ||
| 2931 | if (dm_state && dm_state->freesync_capable) | 2943 | if (dm_state && dm_state->freesync_capable) |
| 2932 | stream->ignore_msa_timing_param = true; | 2944 | stream->ignore_msa_timing_param = true; |
| 2945 | |||
| 2933 | finish: | 2946 | finish: |
| 2934 | if (sink && sink->sink_signal == SIGNAL_TYPE_VIRTUAL && aconnector->base.force != DRM_FORCE_ON) | 2947 | if (sink && sink->sink_signal == SIGNAL_TYPE_VIRTUAL && aconnector->base.force != DRM_FORCE_ON) |
| 2935 | dc_sink_release(sink); | 2948 | dc_sink_release(sink); |
| @@ -3001,6 +3014,7 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc) · 65 unmodified lines | |||
| 3001 | state->abm_level = cur->abm_level; | 3014 | state->abm_level = cur->abm_level; |
| 3002 | state->vrr_supported = cur->vrr_supported; | 3015 | state->vrr_supported = cur->vrr_supported; |
| 3003 | state->freesync_config = cur->freesync_config; | 3016 | state->freesync_config = cur->freesync_config; |
| 3017 | state->crc_enabled = cur->crc_enabled; | ||
| 3004 | 3018 | ||
| 3005 | /* TODO Duplicate dc_stream after objects are stream object is flattened */ | 3019 | /* TODO Duplicate dc_stream after objects are stream object is flattened */ |
| 3006 | 3020 | ||
| @@ -3094,10 +3108,8 @@ int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector, · 87 unmodified lines | |||
| 3094 | rmx_type = RMX_FULL; | 3108 | rmx_type = RMX_FULL; |
| 3095 | break; | 3109 | break; |
| 3096 | case DRM_MODE_SCALE_NONE: | 3110 | case DRM_MODE_SCALE_NONE: |
| 3097 | rmx_type = RMX_OFF; | ||
| 3098 | break; | ||
| 3099 | default: | 3111 | default: |
| 3100 | rmx_type = RMX_ASPECT; | 3112 | rmx_type = RMX_OFF; |
| 3101 | break; | 3113 | break; |
| 3102 | } | 3114 | } |
| 3103 | 3115 | ||
| @@ -3210,10 +3222,11 @@ void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector) · 106 unmodified lines | |||
| 3210 | state = kzalloc(sizeof(*state), GFP_KERNEL); | 3222 | state = kzalloc(sizeof(*state), GFP_KERNEL); |
| 3211 | 3223 | ||
| 3212 | if (state) { | 3224 | if (state) { |
| 3213 | state->scaling = RMX_ASPECT; | 3225 | state->scaling = RMX_OFF; |
| 3214 | state->underscan_enable = false; | 3226 | state->underscan_enable = false; |
| 3215 | state->underscan_hborder = 0; | 3227 | state->underscan_hborder = 0; |
| 3216 | state->underscan_vborder = 0; | 3228 | state->underscan_vborder = 0; |
| 3229 | state->max_bpc = 8; | ||
| 3217 | 3230 | ||
| 3218 | __drm_atomic_helper_connector_reset(connector, &state->base); | 3231 | __drm_atomic_helper_connector_reset(connector, &state->base); |
| 3219 | } | 3232 | } |
| @@ -3235,6 +3248,11 @@ amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector) · 15 unmodified lines | |||
| 3235 | 3248 | ||
| 3236 | new_state->freesync_capable = state->freesync_capable; | 3249 | new_state->freesync_capable = state->freesync_capable; |
| 3237 | new_state->abm_level = state->abm_level; | 3250 | new_state->abm_level = state->abm_level; |
| 3251 | new_state->scaling = state->scaling; | ||
| 3252 | new_state->underscan_enable = state->underscan_enable; | ||
| 3253 | new_state->underscan_hborder = state->underscan_hborder; | ||
| 3254 | new_state->underscan_vborder = state->underscan_vborder; | ||
| 3255 | new_state->max_bpc = state->max_bpc; | ||
| 3238 | 3256 | ||
| 3239 | return &new_state->base; | 3257 | return &new_state->base; |
| 3240 | } | 3258 | } |
| @@ -3607,10 +3625,43 @@ static int dm_plane_atomic_check(struct drm_plane *plane, · 366 unmodified lines | |||
| 3607 | return -EINVAL; | 3625 | return -EINVAL; |
| 3608 | } | 3626 | } |
| 3609 | 3627 | ||
| 3628 | static int dm_plane_atomic_async_check(struct drm_plane *plane, | ||
| 3629 | struct drm_plane_state *new_plane_state) | ||
| 3630 | { | ||
| 3631 | /* Only support async updates on cursor planes. */ | ||
| 3632 | if (plane->type != DRM_PLANE_TYPE_CURSOR) | ||
| 3633 | return -EINVAL; | ||
| 3634 | |||
| 3635 | return 0; | ||
| 3636 | } | ||
| 3637 | |||
| 3638 | static void dm_plane_atomic_async_update(struct drm_plane *plane, | ||
| 3639 | struct drm_plane_state *new_state) | ||
| 3640 | { | ||
| 3641 | struct drm_plane_state *old_state = | ||
| 3642 | drm_atomic_get_old_plane_state(new_state->state, plane); | ||
| 3643 | |||
| 3644 | if (plane->state->fb != new_state->fb) | ||
| 3645 | drm_atomic_set_fb_for_plane(plane->state, new_state->fb); | ||
| 3646 | |||
| 3647 | plane->state->src_x = new_state->src_x; | ||
| 3648 | plane->state->src_y = new_state->src_y; | ||
| 3649 | plane->state->src_w = new_state->src_w; | ||
| 3650 | plane->state->src_h = new_state->src_h; | ||
| 3651 | plane->state->crtc_x = new_state->crtc_x; | ||
| 3652 | plane->state->crtc_y = new_state->crtc_y; | ||
| 3653 | plane->state->crtc_w = new_state->crtc_w; | ||
| 3654 | plane->state->crtc_h = new_state->crtc_h; | ||
| 3655 | |||
| 3656 | handle_cursor_update(plane, old_state); | ||
| 3657 | } | ||
| 3658 | |||
| 3610 | static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { | 3659 | static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { |
| 3611 | .prepare_fb = dm_plane_helper_prepare_fb, | 3660 | .prepare_fb = dm_plane_helper_prepare_fb, |
| 3612 | .cleanup_fb = dm_plane_helper_cleanup_fb, | 3661 | .cleanup_fb = dm_plane_helper_cleanup_fb, |
| 3613 | .atomic_check = dm_plane_atomic_check, | 3662 | .atomic_check = dm_plane_atomic_check, |
| 3663 | .atomic_async_check = dm_plane_atomic_async_check, | ||
| 3664 | .atomic_async_update = dm_plane_atomic_async_update | ||
| 3614 | }; | 3665 | }; |
| 3615 | 3666 | ||
| 3616 | /* | 3667 | /* |
| @@ -4299,6 +4350,7 @@ static int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc, · 682 unmodified lines | |||
| 4299 | static void handle_cursor_update(struct drm_plane *plane, | 4350 | static void handle_cursor_update(struct drm_plane *plane, |
| 4300 | struct drm_plane_state *old_plane_state) | 4351 | struct drm_plane_state *old_plane_state) |
| 4301 | { | 4352 | { |
| 4353 | struct amdgpu_device *adev = plane->dev->dev_private; | ||
| 4302 | struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb); | 4354 | struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb); |
| 4303 | struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc; | 4355 | struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc; |
| 4304 | struct dm_crtc_state *crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL; | 4356 | struct dm_crtc_state *crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL; |
| @@ -4323,9 +4375,12 @@ static void handle_cursor_update(struct drm_plane *plane, · 18 unmodified lines | |||
| 4323 | 4375 | ||
| 4324 | if (!position.enable) { | 4376 | if (!position.enable) { |
| 4325 | /* turn off cursor */ | 4377 | /* turn off cursor */ |
| 4326 | if (crtc_state && crtc_state->stream) | 4378 | if (crtc_state && crtc_state->stream) { |
| 4379 | mutex_lock(&adev->dm.dc_lock); | ||
| 4327 | dc_stream_set_cursor_position(crtc_state->stream, | 4380 | dc_stream_set_cursor_position(crtc_state->stream, |
| 4328 | &position); | 4381 | &position); |
| 4382 | mutex_unlock(&adev->dm.dc_lock); | ||
| 4383 | } | ||
| 4329 | return; | 4384 | return; |
| 4330 | } | 4385 | } |
| 4331 | 4386 | ||
| @@ -4343,6 +4398,7 @@ static void handle_cursor_update(struct drm_plane *plane, · 11 unmodified lines | |||
| 4343 | attributes.pitch = attributes.width; | 4398 | attributes.pitch = attributes.width; |
| 4344 | 4399 | ||
| 4345 | if (crtc_state->stream) { | 4400 | if (crtc_state->stream) { |
| 4401 | mutex_lock(&adev->dm.dc_lock); | ||
| 4346 | if (!dc_stream_set_cursor_attributes(crtc_state->stream, | 4402 | if (!dc_stream_set_cursor_attributes(crtc_state->stream, |
| 4347 | &attributes)) | 4403 | &attributes)) |
| 4348 | DRM_ERROR("DC failed to set cursor attributes\n"); | 4404 | DRM_ERROR("DC failed to set cursor attributes\n"); |
| @@ -4350,6 +4406,7 @@ static void handle_cursor_update(struct drm_plane *plane, · 1 unmodified line | |||
| 4350 | if (!dc_stream_set_cursor_position(crtc_state->stream, | 4406 | if (!dc_stream_set_cursor_position(crtc_state->stream, |
| 4351 | &position)) | 4407 | &position)) |
| 4352 | DRM_ERROR("DC failed to set cursor position\n"); | 4408 | DRM_ERROR("DC failed to set cursor position\n"); |
| 4409 | mutex_unlock(&adev->dm.dc_lock); | ||
| 4353 | } | 4410 | } |
| 4354 | } | 4411 | } |
| 4355 | 4412 | ||
| @@ -4423,8 +4480,8 @@ static void update_freesync_state_on_stream( · 67 unmodified lines | |||
| 4423 | dm->freesync_module, | 4480 | dm->freesync_module, |
| 4424 | new_stream, | 4481 | new_stream, |
| 4425 | &vrr, | 4482 | &vrr, |
| 4426 | packet_type_vrr, | 4483 | PACKET_TYPE_VRR, |
| 4427 | transfer_func_unknown, | 4484 | TRANSFER_FUNC_UNKNOWN, |
| 4428 | &vrr_infopacket); | 4485 | &vrr_infopacket); |
| 4429 | 4486 | ||
| 4430 | new_crtc_state->freesync_timing_changed = | 4487 | new_crtc_state->freesync_timing_changed = |
| @@ -4565,6 +4622,7 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, · 134 unmodified lines | |||
| 4565 | &acrtc_state->stream->vrr_infopacket; | 4622 | &acrtc_state->stream->vrr_infopacket; |
| 4566 | } | 4623 | } |
| 4567 | 4624 | ||
| 4625 | mutex_lock(&adev->dm.dc_lock); | ||
| 4568 | dc_commit_updates_for_stream(adev->dm.dc, | 4626 | dc_commit_updates_for_stream(adev->dm.dc, |
| 4569 | surface_updates, | 4627 | surface_updates, |
| 4570 | 1, | 4628 | 1, |
| @@ -4572,6 +4630,7 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, · 1 unmodified line | |||
| 4572 | &stream_update, | 4630 | &stream_update, |
| 4573 | &surface_updates->surface, | 4631 | &surface_updates->surface, |
| 4574 | state); | 4632 | state); |
| 4633 | mutex_unlock(&adev->dm.dc_lock); | ||
| 4575 | 4634 | ||
| 4576 | DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", | 4635 | DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", |
| 4577 | __func__, | 4636 | __func__, |
| @@ -4586,6 +4645,7 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, · 8 unmodified lines | |||
| 4586 | * with a dc_plane_state and follow the atomic model a bit more closely here. | 4645 | * with a dc_plane_state and follow the atomic model a bit more closely here. |
| 4587 | */ | 4646 | */ |
| 4588 | static bool commit_planes_to_stream( | 4647 | static bool commit_planes_to_stream( |
| 4648 | struct amdgpu_display_manager *dm, | ||
| 4589 | struct dc *dc, | 4649 | struct dc *dc, |
| 4590 | struct dc_plane_state **plane_states, | 4650 | struct dc_plane_state **plane_states, |
| 4591 | uint8_t new_plane_count, | 4651 | uint8_t new_plane_count, |
| @@ -4662,11 +4722,13 @@ static bool commit_planes_to_stream( · 70 unmodified lines | |||
| 4662 | updates[i].scaling_info = &scaling_info[i]; | 4722 | updates[i].scaling_info = &scaling_info[i]; |
| 4663 | } | 4723 | } |
| 4664 | 4724 | ||
| 4725 | mutex_lock(&dm->dc_lock); | ||
| 4665 | dc_commit_updates_for_stream( | 4726 | dc_commit_updates_for_stream( |
| 4666 | dc, | 4727 | dc, |
| 4667 | updates, | 4728 | updates, |
| 4668 | new_plane_count, | 4729 | new_plane_count, |
| 4669 | dc_stream, stream_update, plane_states, state); | 4730 | dc_stream, stream_update, plane_states, state); |
| 4731 | mutex_unlock(&dm->dc_lock); | ||
| 4670 | 4732 | ||
| 4671 | kfree(flip_addr); | 4733 | kfree(flip_addr); |
| 4672 | kfree(plane_info); | 4734 | kfree(plane_info); |
| @@ -4772,7 +4834,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, · 99 unmodified lines | |||
| 4772 | 4834 | ||
| 4773 | dc_stream_attach->abm_level = acrtc_state->abm_level; | 4835 | dc_stream_attach->abm_level = acrtc_state->abm_level; |
| 4774 | 4836 | ||
| 4775 | if (false == commit_planes_to_stream(dm->dc, | 4837 | if (false == commit_planes_to_stream(dm, |
| 4838 | dm->dc, | ||
| 4776 | plane_states_constructed, | 4839 | plane_states_constructed, |
| 4777 | planes_count, | 4840 | planes_count, |
| 4778 | acrtc_state, | 4841 | acrtc_state, |
| @@ -4942,7 +5005,9 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) · 163 unmodified lines | |||
| 4942 | 5005 | ||
| 4943 | if (dc_state) { | 5006 | if (dc_state) { |
| 4944 | dm_enable_per_frame_crtc_master_sync(dc_state); | 5007 | dm_enable_per_frame_crtc_master_sync(dc_state); |
| 5008 | mutex_lock(&dm->dc_lock); | ||
| 4945 | WARN_ON(!dc_commit_state(dm->dc, dc_state)); | 5009 | WARN_ON(!dc_commit_state(dm->dc, dc_state)); |
| 5010 | mutex_unlock(&dm->dc_lock); | ||
| 4946 | } | 5011 | } |
| 4947 | 5012 | ||
| 4948 | for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { | 5013 | for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { |
| @@ -5004,6 +5069,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) · 55 unmodified lines | |||
| 5004 | 5069 | ||
| 5005 | /*TODO How it works with MPO ?*/ | 5070 | /*TODO How it works with MPO ?*/ |
| 5006 | if (!commit_planes_to_stream( | 5071 | if (!commit_planes_to_stream( |
| 5072 | dm, | ||
| 5007 | dm->dc, | 5073 | dm->dc, |
| 5008 | status->plane_states, | 5074 | status->plane_states, |
| 5009 | status->plane_count, | 5075 | status->plane_count, |
| @@ -5896,6 +5962,13 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, · 886 unmodified lines | |||
| 5896 | ret = -EINVAL; | 5962 | ret = -EINVAL; |
| 5897 | goto fail; | 5963 | goto fail; |
| 5898 | } | 5964 | } |
| 5965 | } else if (state->legacy_cursor_update) { | ||
| 5966 | /* | ||
| 5967 | * This is a fast cursor update coming from the plane update | ||
| 5968 | * helper, check if it can be done asynchronously for better | ||
| 5969 | * performance. | ||
| 5970 | */ | ||
| 5971 | state->async_update = !drm_atomic_helper_async_check(dev, state); | ||
| 5899 | } | 5972 | } |
| 5900 | 5973 | ||
| 5901 | /* Must be success */ | 5974 | /* Must be success */ |
| @@ -134,6 +134,14 @@ struct amdgpu_display_manager { · 133 unmodified lines | |||
| 134 | 134 | ||
| 135 | struct drm_modeset_lock atomic_obj_lock; | 135 | struct drm_modeset_lock atomic_obj_lock; |
| 136 | 136 | ||
| 137 | /** | ||
| 138 | * @dc_lock: | ||
| 139 | * | ||
| 140 | * Guards access to DC functions that can issue register write | ||
| 141 | * sequences. | ||
| 142 | */ | ||
| 143 | struct mutex dc_lock; | ||
| 144 | |||
| 137 | /** | 145 | /** |
| 138 | * @irq_handler_list_low_tab: | 146 | * @irq_handler_list_low_tab: |
| 139 | * | 147 | * |
| @@ -0,0 +1,104 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2018 Advanced Micro Devices, Inc. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice shall be included in | ||
| 12 | * all copies or substantial portions of the Software. | ||
| 13 | * | ||
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 21 | * | ||
| 22 | * Authors: AMD | ||
| 23 | * | ||
| 24 | */ | ||
| 25 | |||
| 26 | #undef TRACE_SYSTEM | ||
| 27 | #define TRACE_SYSTEM amdgpu_dm | ||
| 28 | |||
| 29 | #if !defined(_AMDGPU_DM_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) | ||
| 30 | #define _AMDGPU_DM_TRACE_H_ | ||
| 31 | |||
| 32 | #include <linux/tracepoint.h> | ||
| 33 | |||
| 34 | TRACE_EVENT(amdgpu_dc_rreg, | ||
| 35 | TP_PROTO(unsigned long *read_count, uint32_t reg, uint32_t value), | ||
| 36 | TP_ARGS(read_count, reg, value), | ||
| 37 | TP_STRUCT__entry( | ||
| 38 | __field(uint32_t, reg) | ||
| 39 | __field(uint32_t, value) | ||
| 40 | ), | ||
| 41 | TP_fast_assign( | ||
| 42 | __entry->reg = reg; | ||
| 43 | __entry->value = value; | ||
| 44 | *read_count = *read_count + 1; | ||
| 45 | ), | ||
| 46 | TP_printk("reg=0x%08lx, value=0x%08lx", | ||
| 47 | (unsigned long)__entry->reg, | ||
| 48 | (unsigned long)__entry->value) | ||
| 49 | ); | ||
| 50 | |||
| 51 | TRACE_EVENT(amdgpu_dc_wreg, | ||
| 52 | TP_PROTO(unsigned long *write_count, uint32_t reg, uint32_t value), | ||
| 53 | TP_ARGS(write_count, reg, value), | ||
| 54 | TP_STRUCT__entry( | ||
| 55 | __field(uint32_t, reg) | ||
| 56 | __field(uint32_t, value) | ||
| 57 | ), | ||
| 58 | TP_fast_assign( | ||
| 59 | __entry->reg = reg; | ||
| 60 | __entry->value = value; | ||
| 61 | *write_count = *write_count + 1; | ||
| 62 | ), | ||
| 63 | TP_printk("reg=0x%08lx, value=0x%08lx", | ||
| 64 | (unsigned long)__entry->reg, | ||
| 65 | (unsigned long)__entry->value) | ||
| 66 | ); | ||
| 67 | |||
| 68 | |||
| 69 | TRACE_EVENT(amdgpu_dc_performance, | ||
| 70 | TP_PROTO(unsigned long read_count, unsigned long write_count, | ||
| 71 | unsigned long *last_read, unsigned long *last_write, | ||
| 72 | const char *func, unsigned int line), | ||
| 73 | TP_ARGS(read_count, write_count, last_read, last_write, func, line), | ||
| 74 | TP_STRUCT__entry( | ||
| 75 | __field(uint32_t, reads) | ||
| 76 | __field(uint32_t, writes) | ||
| 77 | __field(uint32_t, read_delta) | ||
| 78 | __field(uint32_t, write_delta) | ||
| 79 | __string(func, func) | ||
| 80 | __field(uint32_t, line) | ||
| 81 | ), | ||
| 82 | TP_fast_assign( | ||
| 83 | __entry->reads = read_count; | ||
| 84 | __entry->writes = write_count; | ||
| 85 | __entry->read_delta = read_count - *last_read; | ||
| 86 | __entry->write_delta = write_count - *last_write; | ||
| 87 | __assign_str(func, func); | ||
| 88 | __entry->line = line; | ||
| 89 | *last_read = read_count; | ||
| 90 | *last_write = write_count; | ||
| 91 | ), | ||
| 92 | TP_printk("%s:%d reads=%08ld (%08ld total), writes=%08ld (%08ld total)", | ||
| 93 | __get_str(func), __entry->line, | ||
| 94 | (unsigned long)__entry->read_delta, | ||
| 95 | (unsigned long)__entry->reads, | ||
| 96 | (unsigned long)__entry->write_delta, | ||
| 97 | (unsigned long)__entry->writes) | ||
| 98 | ); | ||
| 99 | #endif /* _AMDGPU_DM_TRACE_H_ */ | ||
| 100 | |||
| 101 | #undef TRACE_INCLUDE_PATH | ||
| 102 | #define TRACE_INCLUDE_PATH . | ||
| 103 | #define TRACE_INCLUDE_FILE amdgpu_dm_trace | ||
| 104 | #include <trace/define_trace.h> | ||
| @@ -62,6 +62,55 @@ · 61 unmodified lines | |||
| 62 | 62 | ||
| 63 | const static char DC_BUILD_ID[] = "production-build"; | 63 | const static char DC_BUILD_ID[] = "production-build"; |
| 64 | 64 | ||
| 65 | /** | ||
| 66 | * DOC: Overview | ||
| 67 | * | ||
| 68 | * DC is the OS-agnostic component of the amdgpu DC driver. | ||
| 69 | * | ||
| 70 | * DC maintains and validates a set of structs representing the state of the | ||
| 71 | * driver and writes that state to AMD hardware | ||
| 72 | * | ||
| 73 | * Main DC HW structs: | ||
| 74 | * | ||
| 75 | * struct dc - The central struct. One per driver. Created on driver load, | ||
| 76 | * destroyed on driver unload. | ||
| 77 | * | ||
| 78 | * struct dc_context - One per driver. | ||
| 79 | * Used as a backpointer by most other structs in dc. | ||
| 80 | * | ||
| 81 | * struct dc_link - One per connector (the physical DP, HDMI, miniDP, or eDP | ||
| 82 | * plugpoints). Created on driver load, destroyed on driver unload. | ||
| 83 | * | ||
| 84 | * struct dc_sink - One per display. Created on boot or hotplug. | ||
| 85 | * Destroyed on shutdown or hotunplug. A dc_link can have a local sink | ||
| 86 | * (the display directly attached). It may also have one or more remote | ||
| 87 | * sinks (in the Multi-Stream Transport case) | ||
| 88 | * | ||
| 89 | * struct resource_pool - One per driver. Represents the hw blocks not in the | ||
| 90 | * main pipeline. Not directly accessible by dm. | ||
| 91 | * | ||
| 92 | * Main dc state structs: | ||
| 93 | * | ||
| 94 | * These structs can be created and destroyed as needed. There is a full set of | ||
| 95 | * these structs in dc->current_state representing the currently programmed state. | ||
| 96 | * | ||
| 97 | * struct dc_state - The global DC state to track global state information, | ||
| 98 | * such as bandwidth values. | ||
| 99 | * | ||
| 100 | * struct dc_stream_state - Represents the hw configuration for the pipeline from | ||
| 101 | * a framebuffer to a display. Maps one-to-one with dc_sink. | ||
| 102 | * | ||
| 103 | * struct dc_plane_state - Represents a framebuffer. Each stream has at least one, | ||
| 104 | * and may have more in the Multi-Plane Overlay case. | ||
| 105 | * | ||
| 106 | * struct resource_context - Represents the programmable state of everything in | ||
| 107 | * the resource_pool. Not directly accessible by dm. | ||
| 108 | * | ||
| 109 | * struct pipe_ctx - A member of struct resource_context. Represents the | ||
| 110 | * internal hardware pipeline components. Each dc_plane_state has either | ||
| 111 | * one or two (in the pipe-split case). | ||
| 112 | */ | ||
| 113 | |||
| 65 | /******************************************************************************* | 114 | /******************************************************************************* |
| 66 | * Private functions | 115 | * Private functions |
| 67 | ******************************************************************************/ | 116 | ******************************************************************************/ |
| @@ -175,6 +224,17 @@ failed_alloc: · 107 unmodified lines | |||
| 175 | return false; | 224 | return false; |
| 176 | } | 225 | } |
| 177 | 226 | ||
| 227 | static struct dc_perf_trace *dc_perf_trace_create(void) | ||
| 228 | { | ||
| 229 | return kzalloc(sizeof(struct dc_perf_trace), GFP_KERNEL); | ||
| 230 | } | ||
| 231 | |||
| 232 | static void dc_perf_trace_destroy(struct dc_perf_trace **perf_trace) | ||
| 233 | { | ||
| 234 | kfree(*perf_trace); | ||
| 235 | *perf_trace = NULL; | ||
| 236 | } | ||
| 237 | |||
| 178 | /** | 238 | /** |
| 179 | ***************************************************************************** | 239 | ***************************************************************************** |
| 180 | * Function: dc_stream_adjust_vmin_vmax | 240 | * Function: dc_stream_adjust_vmin_vmax |
| @@ -240,7 +300,7 @@ bool dc_stream_get_crtc_position(struct dc *dc, · 59 unmodified lines | |||
| 240 | } | 300 | } |
| 241 | 301 | ||
| 242 | /** | 302 | /** |
| 243 | * dc_stream_configure_crc: Configure CRC capture for the given stream. | 303 | * dc_stream_configure_crc() - Configure CRC capture for the given stream. |
| 244 | * @dc: DC Object | 304 | * @dc: DC Object |
| 245 | * @stream: The stream to configure CRC on. | 305 | * @stream: The stream to configure CRC on. |
| 246 | * @enable: Enable CRC if true, disable otherwise. | 306 | * @enable: Enable CRC if true, disable otherwise. |
| @@ -292,7 +352,7 @@ bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream, · 45 unmodified lines | |||
| 292 | } | 352 | } |
| 293 | 353 | ||
| 294 | /** | 354 | /** |
| 295 | * dc_stream_get_crc: Get CRC values for the given stream. | 355 | * dc_stream_get_crc() - Get CRC values for the given stream. |
| 296 | * @dc: DC object | 356 | * @dc: DC object |
| 297 | * @stream: The DC stream state of the stream to get CRCs from. | 357 | * @stream: The DC stream state of the stream to get CRCs from. |
| 298 | * @r_cr, g_y, b_cb: CRC values for the three channels are stored here. | 358 | * @r_cr, g_y, b_cb: CRC values for the three channels are stored here. |
| @@ -536,6 +596,8 @@ static void destruct(struct dc *dc) · 237 unmodified lines | |||
| 536 | if (dc->ctx->created_bios) | 596 | if (dc->ctx->created_bios) |
| 537 | dal_bios_parser_destroy(&dc->ctx->dc_bios); | 597 | dal_bios_parser_destroy(&dc->ctx->dc_bios); |
| 538 | 598 | ||
| 599 | dc_perf_trace_destroy(&dc->ctx->perf_trace); | ||
| 600 | |||
| 539 | kfree(dc->ctx); | 601 | kfree(dc->ctx); |
| 540 | dc->ctx = NULL; | 602 | dc->ctx = NULL; |
| 541 | 603 | ||
| @@ -659,6 +721,12 @@ static bool construct(struct dc *dc, · 117 unmodified lines | |||
| 659 | goto fail; | 721 | goto fail; |
| 660 | } | 722 | } |
| 661 | 723 | ||
| 724 | dc_ctx->perf_trace = dc_perf_trace_create(); | ||
| 725 | if (!dc_ctx->perf_trace) { | ||
| 726 | ASSERT_CRITICAL(false); | ||
| 727 | goto fail; | ||
| 728 | } | ||
| 729 | |||
| 662 | /* Create GPIO service */ | 730 | /* Create GPIO service */ |
| 663 | dc_ctx->gpio_service = dal_gpio_service_create( | 731 | dc_ctx->gpio_service = dal_gpio_service_create( |
| 664 | dc_version, | 732 | dc_version, |
| @@ -1329,6 +1397,11 @@ static enum surface_update_type check_update_surfaces_for_stream( · 664 unmodified lines | |||
| 1329 | return overall_type; | 1397 | return overall_type; |
| 1330 | } | 1398 | } |
| 1331 | 1399 | ||
| 1400 | /** | ||
| 1401 | * dc_check_update_surfaces_for_stream() - Determine update type (fast, med, or full) | ||
| 1402 | * | ||
| 1403 | * See :c:type:`enum surface_update_type <surface_update_type>` for explanation of update types | ||
| 1404 | */ | ||
| 1332 | enum surface_update_type dc_check_update_surfaces_for_stream( | 1405 | enum surface_update_type dc_check_update_surfaces_for_stream( |
| 1333 | struct dc *dc, | 1406 | struct dc *dc, |
| 1334 | struct dc_surface_update *updates, | 1407 | struct dc_surface_update *updates, |
| @@ -1409,6 +1482,14 @@ static void commit_planes_do_stream_update(struct dc *dc, · 74 unmodified lines | |||
| 1409 | if (stream_update->output_csc_transform) | 1482 | if (stream_update->output_csc_transform) |
| 1410 | dc_stream_program_csc_matrix(dc, stream); | 1483 | dc_stream_program_csc_matrix(dc, stream); |
| 1411 | 1484 | ||
| 1485 | if (stream_update->dither_option) { | ||
| 1486 | resource_build_bit_depth_reduction_params(pipe_ctx->stream, | ||
| 1487 | &pipe_ctx->stream->bit_depth_params); | ||
| 1488 | pipe_ctx->stream_res.opp->funcs->opp_program_fmt(pipe_ctx->stream_res.opp, | ||
| 1489 | &stream->bit_depth_params, | ||
| 1490 | &stream->clamping); | ||
| 1491 | } | ||
| 1492 | |||
| 1412 | /* Full fe update*/ | 1493 | /* Full fe update*/ |
| 1413 | if (update_type == UPDATE_TYPE_FAST) | 1494 | if (update_type == UPDATE_TYPE_FAST) |
| 1414 | continue; | 1495 | continue; |
| @@ -1631,6 +1712,9 @@ enum dc_irq_source dc_interrupt_to_irq_source( · 216 unmodified lines | |||
| 1631 | return dal_irq_service_to_irq_source(dc->res_pool->irqs, src_id, ext_id); | 1712 | return dal_irq_service_to_irq_source(dc->res_pool->irqs, src_id, ext_id); |
| 1632 | } | 1713 | } |
| 1633 | 1714 | ||
| 1715 | /** | ||
| 1716 | * dc_interrupt_set() - Enable/disable an AMD hw interrupt source | ||
| 1717 | */ | ||
| 1634 | bool dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable) | 1718 | bool dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable) |
| 1635 | { | 1719 | { |
| 1636 | 1720 | ||
| @@ -1724,6 +1808,11 @@ static bool link_add_remote_sink_helper(struct dc_link *dc_link, struct dc_sink · 87 unmodified lines | |||
| 1724 | return true; | 1808 | return true; |
| 1725 | } | 1809 | } |
| 1726 | 1810 | ||
| 1811 | /** | ||
| 1812 | * dc_link_add_remote_sink() - Create a sink and attach it to an existing link | ||
| 1813 | * | ||
| 1814 | * EDID length is in bytes | ||
| 1815 | */ | ||
| 1727 | struct dc_sink *dc_link_add_remote_sink( | 1816 | struct dc_sink *dc_link_add_remote_sink( |
| 1728 | struct dc_link *link, | 1817 | struct dc_link *link, |
| 1729 | const uint8_t *edid, | 1818 | const uint8_t *edid, |
| @@ -1782,6 +1871,12 @@ fail_add_sink: · 52 unmodified lines | |||
| 1782 | return NULL; | 1871 | return NULL; |
| 1783 | } | 1872 | } |
| 1784 | 1873 | ||
| 1874 | /** | ||
| 1875 | * dc_link_remove_remote_sink() - Remove a remote sink from a dc_link | ||
| 1876 | * | ||
| 1877 | * Note that this just removes the struct dc_sink - it doesn't | ||
| 1878 | * program hardware or alter other members of dc_link | ||
| 1879 | */ | ||
| 1785 | void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) | 1880 | void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) |
| 1786 | { | 1881 | { |
| 1787 | int i; | 1882 | int i; |
| @@ -198,6 +198,13 @@ static bool program_hpd_filter( · 197 unmodified lines | |||
| 198 | return result; | 198 | return result; |
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | /** | ||
| 202 | * dc_link_detect_sink() - Determine if there is a sink connected | ||
| 203 | * | ||
| 204 | * @type: Returned connection type | ||
| 205 | * Does not detect downstream devices, such as MST sinks | ||
| 206 | * or display connected through active dongles | ||
| 207 | */ | ||
| 201 | bool dc_link_detect_sink(struct dc_link *link, enum dc_connection_type *type) | 208 | bool dc_link_detect_sink(struct dc_link *link, enum dc_connection_type *type) |
| 202 | { | 209 | { |
| 203 | uint32_t is_hpd_high = 0; | 210 | uint32_t is_hpd_high = 0; |
| @@ -324,9 +331,9 @@ static enum signal_type get_basic_signal_type( · 120 unmodified lines | |||
| 324 | return SIGNAL_TYPE_NONE; | 331 | return SIGNAL_TYPE_NONE; |
| 325 | } | 332 | } |
| 326 | 333 | ||
| 327 | /* | 334 | /** |
| 328 | * @brief | 335 | * dc_link_is_dp_sink_present() - Check if there is a native DP |
| 329 | * Check whether there is a dongle on DP connector | 336 | * or passive DP-HDMI dongle connected |
| 330 | */ | 337 | */ |
| 331 | bool dc_link_is_dp_sink_present(struct dc_link *link) | 338 | bool dc_link_is_dp_sink_present(struct dc_link *link) |
| 332 | { | 339 | { |
| @@ -593,6 +600,14 @@ static bool is_same_edid(struct dc_edid *old_edid, struct dc_edid *new_edid) · 260 unmodified lines | |||
| 593 | return (memcmp(old_edid->raw_edid, new_edid->raw_edid, new_edid->length) == 0); | 600 | return (memcmp(old_edid->raw_edid, new_edid->raw_edid, new_edid->length) == 0); |
| 594 | } | 601 | } |
| 595 | 602 | ||
| 603 | /** | ||
| 604 | * dc_link_detect() - Detect if a sink is attached to a given link | ||
| 605 | * | ||
| 606 | * link->local_sink is created or destroyed as needed. | ||
| 607 | * | ||
| 608 | * This does not create remote sinks but will trigger DM | ||
| 609 | * to start MST detection if a branch is detected. | ||
| 610 | */ | ||
| 596 | bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) | 611 | bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) |
| 597 | { | 612 | { |
| 598 | struct dc_sink_init_data sink_init_data = { 0 }; | 613 | struct dc_sink_init_data sink_init_data = { 0 }; |
| @@ -2196,7 +2196,7 @@ static void get_active_converter_info( · 2195 unmodified lines | |||
| 2196 | } | 2196 | } |
| 2197 | 2197 | ||
| 2198 | if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_11) { | 2198 | if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_11) { |
| 2199 | uint8_t det_caps[4]; | 2199 | uint8_t det_caps[16]; /* CTS 4.2.2.7 expects source to read Detailed Capabilities Info : 00080h-0008F.*/ |
| 2200 | union dwnstream_port_caps_byte0 *port_caps = | 2200 | union dwnstream_port_caps_byte0 *port_caps = |
| 2201 | (union dwnstream_port_caps_byte0 *)det_caps; | 2201 | (union dwnstream_port_caps_byte0 *)det_caps; |
| 2202 | core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_0, | 2202 | core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_0, |
| @@ -1447,6 +1447,14 @@ static bool are_stream_backends_same( · 1446 unmodified lines | |||
| 1447 | return true; | 1447 | return true; |
| 1448 | } | 1448 | } |
| 1449 | 1449 | ||
| 1450 | /** | ||
| 1451 | * dc_is_stream_unchanged() - Compare two stream states for equivalence. | ||
| 1452 | * | ||
| 1453 | * Checks if there a difference between the two states | ||
| 1454 | * that would require a mode change. | ||
| 1455 | * | ||
| 1456 | * Does not compare cursor position or attributes. | ||
| 1457 | */ | ||
| 1450 | bool dc_is_stream_unchanged( | 1458 | bool dc_is_stream_unchanged( |
| 1451 | struct dc_stream_state *old_stream, struct dc_stream_state *stream) | 1459 | struct dc_stream_state *old_stream, struct dc_stream_state *stream) |
| 1452 | { | 1460 | { |
| @@ -1457,6 +1465,9 @@ bool dc_is_stream_unchanged( · 4 unmodified lines | |||
| 1457 | return true; | 1465 | return true; |
| 1458 | } | 1466 | } |
| 1459 | 1467 | ||
| 1468 | /** | ||
| 1469 | * dc_is_stream_scaling_unchanged() - Compare scaling rectangles of two streams. | ||
| 1470 | */ | ||
| 1460 | bool dc_is_stream_scaling_unchanged( | 1471 | bool dc_is_stream_scaling_unchanged( |
| 1461 | struct dc_stream_state *old_stream, struct dc_stream_state *stream) | 1472 | struct dc_stream_state *old_stream, struct dc_stream_state *stream) |
| 1462 | { | 1473 | { |
| @@ -1616,6 +1627,9 @@ bool resource_is_stream_unchanged( · 153 unmodified lines | |||
| 1616 | return false; | 1627 | return false; |
| 1617 | } | 1628 | } |
| 1618 | 1629 | ||
| 1630 | /** | ||
| 1631 | * dc_add_stream_to_ctx() - Add a new dc_stream_state to a dc_state. | ||
| 1632 | */ | ||
| 1619 | enum dc_status dc_add_stream_to_ctx( | 1633 | enum dc_status dc_add_stream_to_ctx( |
| 1620 | struct dc *dc, | 1634 | struct dc *dc, |
| 1621 | struct dc_state *new_ctx, | 1635 | struct dc_state *new_ctx, |
| @@ -1640,6 +1654,9 @@ enum dc_status dc_add_stream_to_ctx( · 18 unmodified lines | |||
| 1640 | return res; | 1654 | return res; |
| 1641 | } | 1655 | } |
| 1642 | 1656 | ||
| 1657 | /** | ||
| 1658 | * dc_remove_stream_from_ctx() - Remove a stream from a dc_state. | ||
| 1659 | */ | ||
| 1643 | enum dc_status dc_remove_stream_from_ctx( | 1660 | enum dc_status dc_remove_stream_from_ctx( |
| 1644 | struct dc *dc, | 1661 | struct dc *dc, |
| 1645 | struct dc_state *new_ctx, | 1662 | struct dc_state *new_ctx, |
| @@ -1860,6 +1877,12 @@ enum dc_status resource_map_pool_resources( · 214 unmodified lines | |||
| 1860 | return DC_ERROR_UNEXPECTED; | 1877 | return DC_ERROR_UNEXPECTED; |
| 1861 | } | 1878 | } |
| 1862 | 1879 | ||
| 1880 | /** | ||
| 1881 | * dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state | ||
| 1882 | * Is a shallow copy. Increments refcounts on existing streams and planes. | ||
| 1883 | * @dc: copy out of dc->current_state | ||
| 1884 | * @dst_ctx: copy into this | ||
| 1885 | */ | ||
| 1863 | void dc_resource_state_copy_construct_current( | 1886 | void dc_resource_state_copy_construct_current( |
| 1864 | const struct dc *dc, | 1887 | const struct dc *dc, |
| 1865 | struct dc_state *dst_ctx) | 1888 | struct dc_state *dst_ctx) |
| @@ -1875,6 +1898,14 @@ void dc_resource_state_construct( · 9 unmodified lines | |||
| 1875 | dst_ctx->dccg = dc->res_pool->clk_mgr; | 1898 | dst_ctx->dccg = dc->res_pool->clk_mgr; |
| 1876 | } | 1899 | } |
| 1877 | 1900 | ||
| 1901 | /** | ||
| 1902 | * dc_validate_global_state() - Determine if HW can support a given state | ||
| 1903 | * Checks HW resource availability and bandwidth requirement. | ||
| 1904 | * @dc: dc struct for this driver | ||
| 1905 | * @new_ctx: state to be validated | ||
| 1906 | * | ||
| 1907 | * Return: DC_OK if the result can be programmed. Otherwise, an error code. | ||
| 1908 | */ | ||
| 1878 | enum dc_status dc_validate_global_state( | 1909 | enum dc_status dc_validate_global_state( |
| 1879 | struct dc *dc, | 1910 | struct dc *dc, |
| 1880 | struct dc_state *new_ctx) | 1911 | struct dc_state *new_ctx) |
| @@ -2202,113 +2233,15 @@ static void set_vendor_info_packet( · 321 unmodified lines | |||
| 2202 | struct dc_info_packet *info_packet, | 2233 | struct dc_info_packet *info_packet, |
| 2203 | struct dc_stream_state *stream) | 2234 | struct dc_stream_state *stream) |
| 2204 | { | 2235 | { |
| 2205 | uint32_t length = 0; | 2236 | /* SPD info packet for FreeSync */ |
| 2206 | bool hdmi_vic_mode = false; | ||
| 2207 | uint8_t checksum = 0; | ||
| 2208 | uint32_t i = 0; | ||
| 2209 | enum dc_timing_3d_format format; | ||
| 2210 | // Can be different depending on packet content /*todo*/ | ||
| 2211 | // unsigned int length = pPathMode->dolbyVision ? 24 : 5; | ||
| 2212 | |||
| 2213 | info_packet->valid = false; | ||
| 2214 | |||
| 2215 | format = stream->timing.timing_3d_format; | ||
| 2216 | if (stream->view_format == VIEW_3D_FORMAT_NONE) | ||
| 2217 | format = TIMING_3D_FORMAT_NONE; | ||
| 2218 | |||
| 2219 | /* Can be different depending on packet content */ | ||
| 2220 | length = 5; | ||
| 2221 | |||
| 2222 | if (stream->timing.hdmi_vic != 0 | ||
| 2223 | && stream->timing.h_total >= 3840 | ||
| 2224 | && stream->timing.v_total >= 2160) | ||
| 2225 | hdmi_vic_mode = true; | ||
| 2226 | |||
| 2227 | /* According to HDMI 1.4a CTS, VSIF should be sent | ||
| 2228 | * for both 3D stereo and HDMI VIC modes. | ||
| 2229 | * For all other modes, there is no VSIF sent. */ | ||
| 2230 | 2237 | ||
| 2231 | if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode) | 2238 | /* Check if Freesync is supported. Return if false. If true, |
| 2239 | * set the corresponding bit in the info packet | ||
| 2240 | */ | ||
| 2241 | if (!stream->vsp_infopacket.valid) | ||
| 2232 | return; | 2242 | return; |
| 2233 | 2243 | ||
| 2234 | /* 24bit IEEE Registration identifier (0x000c03). LSB first. */ | 2244 | *info_packet = stream->vsp_infopacket; |
| 2235 | info_packet->sb[1] = 0x03; | ||
| 2236 | info_packet->sb[2] = 0x0C; | ||
| 2237 | info_packet->sb[3] = 0x00; | ||
| 2238 | |||
| 2239 | /*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format. | ||
| 2240 | * The value for HDMI_Video_Format are: | ||
| 2241 | * 0x0 (0b000) - No additional HDMI video format is presented in this | ||
| 2242 | * packet | ||
| 2243 | * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC | ||
| 2244 | * parameter follows | ||
| 2245 | * 0x2 (0b010) - 3D format indication present. 3D_Structure and | ||
| 2246 | * potentially 3D_Ext_Data follows | ||
| 2247 | * 0x3..0x7 (0b011..0b111) - reserved for future use */ | ||
| 2248 | if (format != TIMING_3D_FORMAT_NONE) | ||
| 2249 | info_packet->sb[4] = (2 << 5); | ||
| 2250 | else if (hdmi_vic_mode) | ||
| 2251 | info_packet->sb[4] = (1 << 5); | ||
| 2252 | |||
| 2253 | /* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2): | ||
| 2254 | * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure. | ||
| 2255 | * The value for 3D_Structure are: | ||
| 2256 | * 0x0 - Frame Packing | ||
| 2257 | * 0x1 - Field Alternative | ||
| 2258 | * 0x2 - Line Alternative | ||
| 2259 | * 0x3 - Side-by-Side (full) | ||
| 2260 | * 0x4 - L + depth | ||
| 2261 | * 0x5 - L + depth + graphics + graphics-depth | ||
| 2262 | * 0x6 - Top-and-Bottom | ||
| 2263 | * 0x7 - Reserved for future use | ||
| 2264 | * 0x8 - Side-by-Side (Half) | ||
| 2265 | * 0x9..0xE - Reserved for future use | ||
| 2266 | * 0xF - Not used */ | ||
| 2267 | switch (format) { | ||
| 2268 | case TIMING_3D_FORMAT_HW_FRAME_PACKING: | ||
| 2269 | case TIMING_3D_FORMAT_SW_FRAME_PACKING: | ||
| 2270 | info_packet->sb[5] = (0x0 << 4); | ||
| 2271 | break; | ||
| 2272 | |||
| 2273 | case TIMING_3D_FORMAT_SIDE_BY_SIDE: | ||
| 2274 | case TIMING_3D_FORMAT_SBS_SW_PACKED: | ||
| 2275 | info_packet->sb[5] = (0x8 << 4); | ||
| 2276 | length = 6; | ||
| 2277 | break; | ||
| 2278 | |||
| 2279 | case TIMING_3D_FORMAT_TOP_AND_BOTTOM: | ||
| 2280 | case TIMING_3D_FORMAT_TB_SW_PACKED: | ||
| 2281 | info_packet->sb[5] = (0x6 << 4); | ||
| 2282 | break; | ||
| 2283 | |||
| 2284 | default: | ||
| 2285 | break; | ||
| 2286 | } | ||
| 2287 | |||
| 2288 | /*PB5: If PB4 is set to 0x1 (extended resolution format) | ||
| 2289 | * fill PB5 with the correct HDMI VIC code */ | ||
| 2290 | if (hdmi_vic_mode) | ||
| 2291 | info_packet->sb[5] = stream->timing.hdmi_vic; | ||
| 2292 | |||
| 2293 | /* Header */ | ||
| 2294 | info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; /* VSIF packet type. */ | ||
| 2295 | info_packet->hb1 = 0x01; /* Version */ | ||
| 2296 | |||
| 2297 | /* 4 lower bits = Length, 4 higher bits = 0 (reserved) */ | ||
| 2298 | info_packet->hb2 = (uint8_t) (length); | ||
| 2299 | |||
| 2300 | /* Calculate checksum */ | ||
| 2301 | checksum = 0; | ||
| 2302 | checksum += info_packet->hb0; | ||
| 2303 | checksum += info_packet->hb1; | ||
| 2304 | checksum += info_packet->hb2; | ||
| 2305 | |||
| 2306 | for (i = 1; i <= length; i++) | ||
| 2307 | checksum += info_packet->sb[i]; | ||
| 2308 | |||
| 2309 | info_packet->sb[0] = (uint8_t) (0x100 - checksum); | ||
| 2310 | |||
| 2311 | info_packet->valid = true; | ||
| 2312 | } | 2245 | } |
| 2313 | 2246 | ||
| 2314 | static void set_spd_info_packet( | 2247 | static void set_spd_info_packet( |
| @@ -2364,10 +2297,6 @@ void dc_resource_state_destruct(struct dc_state *context) · 49 unmodified lines | |||
| 2364 | } | 2297 | } |
| 2365 | } | 2298 | } |
| 2366 | 2299 | ||
| 2367 | /* | ||
| 2368 | * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced | ||
| 2369 | * by the src_ctx | ||
| 2370 | */ | ||
| 2371 | void dc_resource_state_copy_construct( | 2300 | void dc_resource_state_copy_construct( |
| 2372 | const struct dc_state *src_ctx, | 2301 | const struct dc_state *src_ctx, |
| 2373 | struct dc_state *dst_ctx) | 2302 | struct dc_state *dst_ctx) |
| @@ -170,7 +170,7 @@ struct dc_stream_status *dc_stream_get_status( · 169 unmodified lines | |||
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | /** | 172 | /** |
| 173 | * Update the cursor attributes and set cursor surface address | 173 | * dc_stream_set_cursor_attributes() - Update cursor attributes and set cursor surface address |
| 174 | */ | 174 | */ |
| 175 | bool dc_stream_set_cursor_attributes( | 175 | bool dc_stream_set_cursor_attributes( |
| 176 | struct dc_stream_state *stream, | 176 | struct dc_stream_state *stream, |
| @@ -39,7 +39,7 @@ · 38 unmodified lines | |||
| 39 | #include "inc/hw/dmcu.h" | 39 | #include "inc/hw/dmcu.h" |
| 40 | #include "dml/display_mode_lib.h" | 40 | #include "dml/display_mode_lib.h" |
| 41 | 41 | ||
| 42 | #define DC_VER "3.2.06" | 42 | #define DC_VER "3.2.08" |
| 43 | 43 | ||
| 44 | #define MAX_SURFACES 3 | 44 | #define MAX_SURFACES 3 |
| 45 | #define MAX_STREAMS 6 | 45 | #define MAX_STREAMS 6 |
| @@ -358,15 +358,16 @@ union dc_tiling_info { · 357 unmodified lines | |||
| 358 | } gfx8; | 358 | } gfx8; |
| 359 | 359 | ||
| 360 | struct { | 360 | struct { |
| 361 | enum swizzle_mode_values swizzle; | ||
| 361 | unsigned int num_pipes; | 362 | unsigned int num_pipes; |
| 362 | unsigned int num_banks; | 363 | unsigned int max_compressed_frags; |
| 363 | unsigned int pipe_interleave; | 364 | unsigned int pipe_interleave; |
| 365 | |||
| 366 | unsigned int num_banks; | ||
| 364 | unsigned int num_shader_engines; | 367 | unsigned int num_shader_engines; |
| 365 | unsigned int num_rb_per_se; | 368 | unsigned int num_rb_per_se; |
| 366 | unsigned int max_compressed_frags; | ||
| 367 | bool shaderEnable; | 369 | bool shaderEnable; |
| 368 | 370 | ||
| 369 | enum swizzle_mode_values swizzle; | ||
| 370 | bool meta_linear; | 371 | bool meta_linear; |
| 371 | bool rb_aligned; | 372 | bool rb_aligned; |
| 372 | bool pipe_aligned; | 373 | bool pipe_aligned; |
| @@ -128,8 +128,10 @@ struct dc_link { · 127 unmodified lines | |||
| 128 | 128 | ||
| 129 | const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); | 129 | const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); |
| 130 | 130 | ||
| 131 | /* | 131 | /** |
| 132 | * Return an enumerated dc_link. dc_link order is constant and determined at | 132 | * dc_get_link_at_index() - Return an enumerated dc_link. |
| 133 | * | ||
| 134 | * dc_link order is constant and determined at | ||
| 133 | * boot time. They cannot be created or destroyed. | 135 | * boot time. They cannot be created or destroyed. |
| 134 | * Use dc_get_caps() to get number of links. | 136 | * Use dc_get_caps() to get number of links. |
| 135 | */ | 137 | */ |
| @@ -56,6 +56,7 @@ struct dc_stream_state { · 55 unmodified lines | |||
| 56 | struct dc_crtc_timing_adjust adjust; | 56 | struct dc_crtc_timing_adjust adjust; |
| 57 | struct dc_info_packet vrr_infopacket; | 57 | struct dc_info_packet vrr_infopacket; |
| 58 | struct dc_info_packet vsc_infopacket; | 58 | struct dc_info_packet vsc_infopacket; |
| 59 | struct dc_info_packet vsp_infopacket; | ||
| 59 | 60 | ||
| 60 | struct rect src; /* composition area */ | 61 | struct rect src; /* composition area */ |
| 61 | struct rect dst; /* stream addressable area */ | 62 | struct rect dst; /* stream addressable area */ |
| @@ -129,11 +130,13 @@ struct dc_stream_update { · 67 unmodified lines | |||
| 129 | struct dc_crtc_timing_adjust *adjust; | 130 | struct dc_crtc_timing_adjust *adjust; |
| 130 | struct dc_info_packet *vrr_infopacket; | 131 | struct dc_info_packet *vrr_infopacket; |
| 131 | struct dc_info_packet *vsc_infopacket; | 132 | struct dc_info_packet *vsc_infopacket; |
| 133 | struct dc_info_packet *vsp_infopacket; | ||
| 132 | 134 | ||
| 133 | bool *dpms_off; | 135 | bool *dpms_off; |
| 134 | 136 | ||
| 135 | struct colorspace_transform *gamut_remap; | 137 | struct colorspace_transform *gamut_remap; |
| 136 | enum dc_color_space *output_color_space; | 138 | enum dc_color_space *output_color_space; |
| 139 | enum dc_dither_option *dither_option; | ||
| 137 | 140 | ||
| 138 | struct dc_csc_transform *output_csc_transform; | 141 | struct dc_csc_transform *output_csc_transform; |
| 139 | 142 | ||
| @@ -73,10 +73,18 @@ struct hw_asic_id { · 72 unmodified lines | |||
| 73 | void *atombios_base_address; | 73 | void *atombios_base_address; |
| 74 | }; | 74 | }; |
| 75 | 75 | ||
| 76 | struct dc_perf_trace { | ||
| 77 | unsigned long read_count; | ||
| 78 | unsigned long write_count; | ||
| 79 | unsigned long last_entry_read; | ||
| 80 | unsigned long last_entry_write; | ||
| 81 | }; | ||
| 82 | |||
| 76 | struct dc_context { | 83 | struct dc_context { |
| 77 | struct dc *dc; | 84 | struct dc *dc; |
| 78 | 85 | ||
| 79 | void *driver_context; /* e.g. amdgpu_device */ | 86 | void *driver_context; /* e.g. amdgpu_device */ |
| 87 | struct dc_perf_trace *perf_trace; | ||
| 80 | void *cgs_device; | 88 | void *cgs_device; |
| 81 | 89 | ||
| 82 | enum dce_environment dce_environment; | 90 | enum dce_environment dce_environment; |
| @@ -191,7 +199,6 @@ union display_content_support { · 108 unmodified lines | |||
| 191 | }; | 199 | }; |
| 192 | 200 | ||
| 193 | struct dc_panel_patch { | 201 | struct dc_panel_patch { |
| 194 | unsigned int disconnect_delay; | ||
| 195 | unsigned int dppowerup_delay; | 202 | unsigned int dppowerup_delay; |
| 196 | unsigned int extra_t12_ms; | 203 | unsigned int extra_t12_ms; |
| 197 | }; | 204 | }; |
| @@ -117,6 +117,18 @@ void dce100_prepare_bandwidth( · 116 unmodified lines | |||
| 117 | false); | 117 | false); |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | void dce100_optimize_bandwidth( | ||
| 121 | struct dc *dc, | ||
| 122 | struct dc_state *context) | ||
| 123 | { | ||
| 124 | dce110_set_safe_displaymarks(&context->res_ctx, dc->res_pool); | ||
| 125 | |||
| 126 | dc->res_pool->clk_mgr->funcs->update_clocks( | ||
| 127 | dc->res_pool->clk_mgr, | ||
| 128 | context, | ||
| 129 | true); | ||
| 130 | } | ||
| 131 | |||
| 120 | /**************************************************************************/ | 132 | /**************************************************************************/ |
| 121 | 133 | ||
| 122 | void dce100_hw_sequencer_construct(struct dc *dc) | 134 | void dce100_hw_sequencer_construct(struct dc *dc) |
| @@ -125,6 +137,6 @@ void dce100_hw_sequencer_construct(struct dc *dc) · 2 unmodified lines | |||
| 125 | 137 | ||
| 126 | dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating; | 138 | dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating; |
| 127 | dc->hwss.prepare_bandwidth = dce100_prepare_bandwidth; | 139 | dc->hwss.prepare_bandwidth = dce100_prepare_bandwidth; |
| 128 | dc->hwss.optimize_bandwidth = dce100_prepare_bandwidth; | 140 | dc->hwss.optimize_bandwidth = dce100_optimize_bandwidth; |
| 129 | } | 141 | } |
| 130 | 142 | ||
| @@ -64,65 +64,37 @@ static const struct dce110_compressor_reg_offsets reg_offsets[] = { · 63 unmodified lines | |||
| 64 | 64 | ||
| 65 | static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600; | 65 | static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600; |
| 66 | 66 | ||
| 67 | enum fbc_idle_force { | ||
| 68 | /* Bit 0 - Display registers updated */ | ||
| 69 | FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE = 0x00000001, | ||
| 70 | |||
| 71 | /* Bit 2 - FBC_GRPH_COMP_EN register updated */ | ||
| 72 | FBC_IDLE_FORCE_GRPH_COMP_EN = 0x00000002, | ||
| 73 | /* Bit 3 - FBC_SRC_SEL register updated */ | ||
| 74 | FBC_IDLE_FORCE_SRC_SEL_CHANGE = 0x00000004, | ||
| 75 | /* Bit 4 - FBC_MIN_COMPRESSION register updated */ | ||
| 76 | FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE = 0x00000008, | ||
| 77 | /* Bit 5 - FBC_ALPHA_COMP_EN register updated */ | ||
| 78 | FBC_IDLE_FORCE_ALPHA_COMP_EN = 0x00000010, | ||
| 79 | /* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */ | ||
| 80 | FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN = 0x00000020, | ||
| 81 | /* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */ | ||
| 82 | FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF = 0x00000040, | ||
| 83 | |||
| 84 | /* Bit 24 - Memory write to region 0 defined by MC registers. */ | ||
| 85 | FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0 = 0x01000000, | ||
| 86 | /* Bit 25 - Memory write to region 1 defined by MC registers */ | ||
| 87 | FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1 = 0x02000000, | ||
| 88 | /* Bit 26 - Memory write to region 2 defined by MC registers */ | ||
| 89 | FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2 = 0x04000000, | ||
| 90 | /* Bit 27 - Memory write to region 3 defined by MC registers. */ | ||
| 91 | FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3 = 0x08000000, | ||
| 92 | |||
| 93 | /* Bit 28 - Memory write from any client other than MCIF */ | ||
| 94 | FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF = 0x10000000, | ||
| 95 | /* Bit 29 - CG statics screen signal is inactive */ | ||
| 96 | FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000, | ||
| 97 | }; | ||
| 98 | |||
| 99 | |||
| 100 | static uint32_t align_to_chunks_number_per_line(uint32_t pixels) | 67 | static uint32_t align_to_chunks_number_per_line(uint32_t pixels) |
| 101 | { | 68 | { |
| 102 | return 256 * ((pixels + 255) / 256); | 69 | return 256 * ((pixels + 255) / 256); |
| 103 | } | 70 | } |
| 104 | 71 | ||
| 105 | static void reset_lb_on_vblank(struct dc_context *ctx) | 72 | static void reset_lb_on_vblank(struct compressor *compressor, uint32_t crtc_inst) |
| 106 | { | 73 | { |
| 107 | uint32_t value, frame_count; | 74 | uint32_t value; |
| 75 | uint32_t frame_count; | ||
| 76 | uint32_t status_pos; | ||
| 108 | uint32_t retry = 0; | 77 | uint32_t retry = 0; |
| 109 | uint32_t status_pos = | 78 | struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); |
| 110 | dm_read_reg(ctx, mmCRTC_STATUS_POSITION); | 79 | |
| 80 | cp110->offsets = reg_offsets[crtc_inst]; | ||
| 81 | |||
| 82 | status_pos = dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_POSITION)); | ||
| 111 | 83 | ||
| 112 | 84 | ||
| 113 | /* Only if CRTC is enabled and counter is moving we wait for one frame. */ | 85 | /* Only if CRTC is enabled and counter is moving we wait for one frame. */ |
| 114 | if (status_pos != dm_read_reg(ctx, mmCRTC_STATUS_POSITION)) { | 86 | if (status_pos != dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_POSITION))) { |
| 115 | /* Resetting LB on VBlank */ | 87 | /* Resetting LB on VBlank */ |
| 116 | value = dm_read_reg(ctx, mmLB_SYNC_RESET_SEL); | 88 | value = dm_read_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL)); |
| 117 | set_reg_field_value(value, 3, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL); | 89 | set_reg_field_value(value, 3, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL); |
| 118 | set_reg_field_value(value, 1, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL2); | 90 | set_reg_field_value(value, 1, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL2); |
| 119 | dm_write_reg(ctx, mmLB_SYNC_RESET_SEL, value); | 91 | dm_write_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL), value); |
| 120 | 92 | ||
| 121 | frame_count = dm_read_reg(ctx, mmCRTC_STATUS_FRAME_COUNT); | 93 | frame_count = dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_FRAME_COUNT)); |
| 122 | 94 | ||
| 123 | 95 | ||
| 124 | for (retry = 10000; retry > 0; retry--) { | 96 | for (retry = 10000; retry > 0; retry--) { |
| 125 | if (frame_count != dm_read_reg(ctx, mmCRTC_STATUS_FRAME_COUNT)) | 97 | if (frame_count != dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_FRAME_COUNT))) |
| 126 | break; | 98 | break; |
| 127 | udelay(10); | 99 | udelay(10); |
| 128 | } | 100 | } |
| @@ -130,13 +102,11 @@ static void reset_lb_on_vblank(struct dc_context *ctx) · 1 unmodified line | |||
| 130 | dm_error("Frame count did not increase for 100ms.\n"); | 102 | dm_error("Frame count did not increase for 100ms.\n"); |
| 131 | 103 | ||
| 132 | /* Resetting LB on VBlank */ | 104 | /* Resetting LB on VBlank */ |
| 133 | value = dm_read_reg(ctx, mmLB_SYNC_RESET_SEL); | 105 | value = dm_read_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL)); |
| 134 | set_reg_field_value(value, 2, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL); | 106 | set_reg_field_value(value, 2, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL); |
| 135 | set_reg_field_value(value, 0, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL2); | 107 | set_reg_field_value(value, 0, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL2); |
| 136 | dm_write_reg(ctx, mmLB_SYNC_RESET_SEL, value); | 108 | dm_write_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL), value); |
| 137 | |||
| 138 | } | 109 | } |
| 139 | |||
| 140 | } | 110 | } |
| 141 | 111 | ||
| 142 | static void wait_for_fbc_state_changed( | 112 | static void wait_for_fbc_state_changed( |
| @@ -226,10 +196,10 @@ void dce110_compressor_enable_fbc( · 83 unmodified lines | |||
| 226 | uint32_t addr; | 196 | uint32_t addr; |
| 227 | uint32_t value, misc_value; | 197 | uint32_t value, misc_value; |
| 228 | 198 | ||
| 229 | |||
| 230 | addr = mmFBC_CNTL; | 199 | addr = mmFBC_CNTL; |
| 231 | value = dm_read_reg(compressor->ctx, addr); | 200 | value = dm_read_reg(compressor->ctx, addr); |
| 232 | set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); | 201 | set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); |
| 202 | /* params->inst is valid HW CRTC instance start from 0 */ | ||
| 233 | set_reg_field_value( | 203 | set_reg_field_value( |
| 234 | value, | 204 | value, |
| 235 | params->inst, | 205 | params->inst, |
| @@ -238,8 +208,10 @@ void dce110_compressor_enable_fbc( · 2 unmodified lines | |||
| 238 | 208 | ||
| 239 | /* Keep track of enum controller_id FBC is attached to */ | 209 | /* Keep track of enum controller_id FBC is attached to */ |
| 240 | compressor->is_enabled = true; | 210 | compressor->is_enabled = true; |
| 241 | compressor->attached_inst = params->inst; | 211 | /* attached_inst is SW CRTC instance start from 1 |
| 242 | cp110->offsets = reg_offsets[params->inst]; | 212 | * 0 = CONTROLLER_ID_UNDEFINED means not attached crtc |
| 213 | */ | ||
| 214 | compressor->attached_inst = params->inst + CONTROLLER_ID_D0; | ||
| 243 | 215 | ||
| 244 | /* Toggle it as there is bug in HW */ | 216 | /* Toggle it as there is bug in HW */ |
| 245 | set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); | 217 | set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); |
| @@ -268,9 +240,10 @@ void dce110_compressor_enable_fbc( · 22 unmodified lines | |||
| 268 | void dce110_compressor_disable_fbc(struct compressor *compressor) | 240 | void dce110_compressor_disable_fbc(struct compressor *compressor) |
| 269 | { | 241 | { |
| 270 | struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); | 242 | struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); |
| 243 | uint32_t crtc_inst = 0; | ||
| 271 | 244 | ||
| 272 | if (compressor->options.bits.FBC_SUPPORT) { | 245 | if (compressor->options.bits.FBC_SUPPORT) { |
| 273 | if (dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) { | 246 | if (dce110_compressor_is_fbc_enabled_in_hw(compressor, &crtc_inst)) { |
| 274 | uint32_t reg_data; | 247 | uint32_t reg_data; |
| 275 | /* Turn off compression */ | 248 | /* Turn off compression */ |
| 276 | reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL); | 249 | reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL); |
| @@ -284,8 +257,10 @@ void dce110_compressor_disable_fbc(struct compressor *compressor) · 7 unmodified lines | |||
| 284 | wait_for_fbc_state_changed(cp110, false); | 257 | wait_for_fbc_state_changed(cp110, false); |
| 285 | } | 258 | } |
| 286 | 259 | ||
| 287 | /* Sync line buffer - dce100/110 only*/ | 260 | /* Sync line buffer which fbc was attached to dce100/110 only */ |
| 288 | reset_lb_on_vblank(compressor->ctx); | 261 | if (crtc_inst > CONTROLLER_ID_UNDEFINED && crtc_inst < CONTROLLER_ID_D3) |
| 262 | reset_lb_on_vblank(compressor, | ||
| 263 | crtc_inst - CONTROLLER_ID_D0); | ||
| 289 | } | 264 | } |
| 290 | } | 265 | } |
| 291 | 266 | ||
| @@ -328,6 +303,8 @@ void dce110_compressor_program_compressed_surface_address_and_pitch( · 36 unmodified lines | |||
| 328 | uint32_t compressed_surf_address_low_part = | 303 | uint32_t compressed_surf_address_low_part = |
| 329 | compressor->compr_surface_address.addr.low_part; | 304 | compressor->compr_surface_address.addr.low_part; |
| 330 | 305 | ||
| 306 | cp110->offsets = reg_offsets[params->inst]; | ||
| 307 | |||
| 331 | /* Clear content first. */ | 308 | /* Clear content first. */ |
| 332 | dm_write_reg( | 309 | dm_write_reg( |
| 333 | compressor->ctx, | 310 | compressor->ctx, |
| @@ -410,13 +387,7 @@ void dce110_compressor_set_fbc_invalidation_triggers( · 76 unmodified lines | |||
| 410 | value = dm_read_reg(compressor->ctx, addr); | 387 | value = dm_read_reg(compressor->ctx, addr); |
| 411 | set_reg_field_value( | 388 | set_reg_field_value( |
| 412 | value, | 389 | value, |
| 413 | fbc_trigger | | 390 | fbc_trigger, |
| 414 | FBC_IDLE_FORCE_GRPH_COMP_EN | | ||
| 415 | FBC_IDLE_FORCE_SRC_SEL_CHANGE | | ||
| 416 | FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE | | ||
| 417 | FBC_IDLE_FORCE_ALPHA_COMP_EN | | ||
| 418 | FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN | | ||
| 419 | FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF, | ||
| 420 | FBC_IDLE_FORCE_CLEAR_MASK, | 391 | FBC_IDLE_FORCE_CLEAR_MASK, |
| 421 | FBC_IDLE_FORCE_CLEAR_MASK); | 392 | FBC_IDLE_FORCE_CLEAR_MASK); |
| 422 | dm_write_reg(compressor->ctx, addr, value); | 393 | dm_write_reg(compressor->ctx, addr, value); |
| @@ -549,7 +520,7 @@ void dce110_compressor_construct(struct dce110_compressor *compressor, · 126 unmodified lines | |||
| 549 | compressor->base.channel_interleave_size = 0; | 520 | compressor->base.channel_interleave_size = 0; |
| 550 | compressor->base.dram_channels_num = 0; | 521 | compressor->base.dram_channels_num = 0; |
| 551 | compressor->base.lpt_channels_num = 0; | 522 | compressor->base.lpt_channels_num = 0; |
| 552 | compressor->base.attached_inst = 0; | 523 | compressor->base.attached_inst = CONTROLLER_ID_UNDEFINED; |
| 553 | compressor->base.is_enabled = false; | 524 | compressor->base.is_enabled = false; |
| 554 | compressor->base.funcs = &dce110_compressor_funcs; | 525 | compressor->base.funcs = &dce110_compressor_funcs; |
| 555 | 526 | ||
| @@ -1766,12 +1766,13 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, · 1765 unmodified lines | |||
| 1766 | * Check if FBC can be enabled | 1766 | * Check if FBC can be enabled |
| 1767 | */ | 1767 | */ |
| 1768 | static bool should_enable_fbc(struct dc *dc, | 1768 | static bool should_enable_fbc(struct dc *dc, |
| 1769 | struct dc_state *context, | 1769 | struct dc_state *context, |
| 1770 | uint32_t *pipe_idx) | 1770 | uint32_t *pipe_idx) |
| 1771 | { | 1771 | { |
| 1772 | uint32_t i; | 1772 | uint32_t i; |
| 1773 | struct pipe_ctx *pipe_ctx = NULL; | 1773 | struct pipe_ctx *pipe_ctx = NULL; |
| 1774 | struct resource_context *res_ctx = &context->res_ctx; | 1774 | struct resource_context *res_ctx = &context->res_ctx; |
| 1775 | unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; | ||
| 1775 | 1776 | ||
| 1776 | 1777 | ||
| 1777 | ASSERT(dc->fbc_compressor); | 1778 | ASSERT(dc->fbc_compressor); |
| @@ -1786,14 +1787,28 @@ static bool should_enable_fbc(struct dc *dc, · 8 unmodified lines | |||
| 1786 | 1787 | ||
| 1787 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | 1788 | for (i = 0; i < dc->res_pool->pipe_count; i++) { |
| 1788 | if (res_ctx->pipe_ctx[i].stream) { | 1789 | if (res_ctx->pipe_ctx[i].stream) { |
| 1790 | |||
| 1789 | pipe_ctx = &res_ctx->pipe_ctx[i]; | 1791 | pipe_ctx = &res_ctx->pipe_ctx[i]; |
| 1790 | *pipe_idx = i; | 1792 | |
| 1791 | break; | 1793 | if (!pipe_ctx) |
| 1794 | continue; | ||
| 1795 | |||
| 1796 | /* fbc not applicable on underlay pipe */ | ||
| 1797 | if (pipe_ctx->pipe_idx != underlay_idx) { | ||
| 1798 | *pipe_idx = i; | ||
| 1799 | break; | ||
| 1800 | } | ||
| 1792 | } | 1801 | } |
| 1793 | } | 1802 | } |
| 1794 | 1803 | ||
| 1795 | /* Pipe context should be found */ | 1804 | if (i == dc->res_pool->pipe_count) |
| 1796 | ASSERT(pipe_ctx); | 1805 | return false; |
| 1806 | |||
| 1807 | if (!pipe_ctx->stream->sink) | ||
| 1808 | return false; | ||
| 1809 | |||
| 1810 | if (!pipe_ctx->stream->sink->link) | ||
| 1811 | return false; | ||
| 1797 | 1812 | ||
| 1798 | /* Only supports eDP */ | 1813 | /* Only supports eDP */ |
| 1799 | if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP) | 1814 | if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP) |
| @@ -1817,8 +1832,9 @@ static bool should_enable_fbc(struct dc *dc, · 17 unmodified lines | |||
| 1817 | /* | 1832 | /* |
| 1818 | * Enable FBC | 1833 | * Enable FBC |
| 1819 | */ | 1834 | */ |
| 1820 | static void enable_fbc(struct dc *dc, | 1835 | static void enable_fbc( |
| 1821 | struct dc_state *context) | 1836 | struct dc *dc, |
| 1837 | struct dc_state *context) | ||
| 1822 | { | 1838 | { |
| 1823 | uint32_t pipe_idx = 0; | 1839 | uint32_t pipe_idx = 0; |
| 1824 | 1840 | ||
| @@ -1828,10 +1844,9 @@ static void enable_fbc(struct dc *dc, · 3 unmodified lines | |||
| 1828 | struct compressor *compr = dc->fbc_compressor; | 1844 | struct compressor *compr = dc->fbc_compressor; |
| 1829 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; | 1845 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; |
| 1830 | 1846 | ||
| 1831 | |||
| 1832 | params.source_view_width = pipe_ctx->stream->timing.h_addressable; | 1847 | params.source_view_width = pipe_ctx->stream->timing.h_addressable; |
| 1833 | params.source_view_height = pipe_ctx->stream->timing.v_addressable; | 1848 | params.source_view_height = pipe_ctx->stream->timing.v_addressable; |
| 1834 | 1849 | params.inst = pipe_ctx->stream_res.tg->inst; | |
| 1835 | compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr; | 1850 | compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr; |
| 1836 | 1851 | ||
| 1837 | compr->funcs->surface_address_and_pitch(compr, ¶ms); | 1852 | compr->funcs->surface_address_and_pitch(compr, ¶ms); |
| @@ -2046,10 +2061,10 @@ enum dc_status dce110_apply_ctx_to_hw( · 208 unmodified lines | |||
| 2046 | return status; | 2061 | return status; |
| 2047 | } | 2062 | } |
| 2048 | 2063 | ||
| 2049 | dcb->funcs->set_scratch_critical_state(dcb, false); | ||
| 2050 | |||
| 2051 | if (dc->fbc_compressor) | 2064 | if (dc->fbc_compressor) |
| 2052 | enable_fbc(dc, context); | 2065 | enable_fbc(dc, dc->current_state); |
| 2066 | |||
| 2067 | dcb->funcs->set_scratch_critical_state(dcb, false); | ||
| 2053 | 2068 | ||
| 2054 | return DC_OK; | 2069 | return DC_OK; |
| 2055 | } | 2070 | } |
| @@ -2408,7 +2423,6 @@ static void dce110_program_front_end_for_pipe( · 352 unmodified lines | |||
| 2408 | struct dc_plane_state *plane_state = pipe_ctx->plane_state; | 2423 | struct dc_plane_state *plane_state = pipe_ctx->plane_state; |
| 2409 | struct xfm_grph_csc_adjustment adjust; | 2424 | struct xfm_grph_csc_adjustment adjust; |
| 2410 | struct out_csc_color_matrix tbl_entry; | 2425 | struct out_csc_color_matrix tbl_entry; |
| 2411 | unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; | ||
| 2412 | unsigned int i; | 2426 | unsigned int i; |
| 2413 | DC_LOGGER_INIT(); | 2427 | DC_LOGGER_INIT(); |
| 2414 | memset(&tbl_entry, 0, sizeof(tbl_entry)); | 2428 | memset(&tbl_entry, 0, sizeof(tbl_entry)); |
| @@ -2449,15 +2463,6 @@ static void dce110_program_front_end_for_pipe( · 34 unmodified lines | |||
| 2449 | 2463 | ||
| 2450 | program_scaler(dc, pipe_ctx); | 2464 | program_scaler(dc, pipe_ctx); |
| 2451 | 2465 | ||
| 2452 | /* fbc not applicable on Underlay pipe */ | ||
| 2453 | if (dc->fbc_compressor && old_pipe->stream && | ||
| 2454 | pipe_ctx->pipe_idx != underlay_idx) { | ||
| 2455 | if (plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) | ||
| 2456 | dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); | ||
| 2457 | else | ||
| 2458 | enable_fbc(dc, dc->current_state); | ||
| 2459 | } | ||
| 2460 | |||
| 2461 | mi->funcs->mem_input_program_surface_config( | 2466 | mi->funcs->mem_input_program_surface_config( |
| 2462 | mi, | 2467 | mi, |
| 2463 | plane_state->format, | 2468 | plane_state->format, |
| @@ -2534,6 +2539,9 @@ static void dce110_apply_ctx_for_surface( · 70 unmodified lines | |||
| 2534 | if (num_planes == 0) | 2539 | if (num_planes == 0) |
| 2535 | return; | 2540 | return; |
| 2536 | 2541 | ||
| 2542 | if (dc->fbc_compressor) | ||
| 2543 | dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); | ||
| 2544 | |||
| 2537 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | 2545 | for (i = 0; i < dc->res_pool->pipe_count; i++) { |
| 2538 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; | 2546 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; |
| 2539 | struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; | 2547 | struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; |
| @@ -2576,6 +2584,9 @@ static void dce110_apply_ctx_for_surface( · 36 unmodified lines | |||
| 2576 | (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) | 2584 | (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) |
| 2577 | dc->hwss.pipe_control_lock(dc, pipe_ctx, false); | 2585 | dc->hwss.pipe_control_lock(dc, pipe_ctx, false); |
| 2578 | } | 2586 | } |
| 2587 | |||
| 2588 | if (dc->fbc_compressor) | ||
| 2589 | enable_fbc(dc, dc->current_state); | ||
| 2579 | } | 2590 | } |
| 2580 | 2591 | ||
| 2581 | static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) | 2592 | static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) |
| @@ -328,12 +328,10 @@ static void dcn1_update_clocks(struct clk_mgr *clk_mgr, · 327 unmodified lines | |||
| 328 | 328 | ||
| 329 | *smu_req_cur = smu_req; | 329 | *smu_req_cur = smu_req; |
| 330 | } | 330 | } |
| 331 | |||
| 332 | static const struct clk_mgr_funcs dcn1_funcs = { | 331 | static const struct clk_mgr_funcs dcn1_funcs = { |
| 333 | .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, | 332 | .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, |
| 334 | .update_clocks = dcn1_update_clocks | 333 | .update_clocks = dcn1_update_clocks |
| 335 | }; | 334 | }; |
| 336 | |||
| 337 | struct clk_mgr *dcn1_clk_mgr_create(struct dc_context *ctx) | 335 | struct clk_mgr *dcn1_clk_mgr_create(struct dc_context *ctx) |
| 338 | { | 336 | { |
| 339 | struct dc_debug_options *debug = &ctx->dc->debug; | 337 | struct dc_debug_options *debug = &ctx->dc->debug; |
| @@ -373,3 +371,5 @@ struct clk_mgr *dcn1_clk_mgr_create(struct dc_context *ctx) · 33 unmodified lines | |||
| 373 | 371 | ||
| 374 | return &clk_mgr_dce->base; | 372 | return &clk_mgr_dce->base; |
| 375 | } | 373 | } |
| 374 | |||
| 375 | |||
| @@ -28,6 +28,12 @@ · 27 unmodified lines | |||
| 28 | 28 | ||
| 29 | #include "../dce/dce_clk_mgr.h" | 29 | #include "../dce/dce_clk_mgr.h" |
| 30 | 30 | ||
| 31 | struct clk_bypass { | ||
| 32 | uint32_t dcfclk_bypass; | ||
| 33 | uint32_t dispclk_pypass; | ||
| 34 | uint32_t dprefclk_bypass; | ||
| 35 | }; | ||
| 36 | |||
| 31 | void dcn1_pplib_apply_display_requirements( | 37 | void dcn1_pplib_apply_display_requirements( |
| 32 | struct dc *dc, | 38 | struct dc *dc, |
| 33 | struct dc_state *context); | 39 | struct dc_state *context); |
| @@ -324,7 +324,7 @@ bool cm_helper_translate_curve_to_hw_format( · 323 unmodified lines | |||
| 324 | if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS) | 324 | if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS) |
| 325 | return false; | 325 | return false; |
| 326 | 326 | ||
| 327 | PERF_TRACE(); | 327 | PERF_TRACE_CTX(output_tf->ctx); |
| 328 | 328 | ||
| 329 | corner_points = lut_params->corner_points; | 329 | corner_points = lut_params->corner_points; |
| 330 | rgb_resulted = lut_params->rgb_resulted; | 330 | rgb_resulted = lut_params->rgb_resulted; |
| @@ -513,7 +513,7 @@ bool cm_helper_translate_curve_to_degamma_hw_format( · 182 unmodified lines | |||
| 513 | if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS) | 513 | if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS) |
| 514 | return false; | 514 | return false; |
| 515 | 515 | ||
| 516 | PERF_TRACE(); | 516 | PERF_TRACE_CTX(output_tf->ctx); |
| 517 | 517 | ||
| 518 | corner_points = lut_params->corner_points; | 518 | corner_points = lut_params->corner_points; |
| 519 | rgb_resulted = lut_params->rgb_resulted; | 519 | rgb_resulted = lut_params->rgb_resulted; |
| @@ -44,6 +44,7 @@ · 43 unmodified lines | |||
| 44 | #include "dcn10_hubp.h" | 44 | #include "dcn10_hubp.h" |
| 45 | #include "dcn10_hubbub.h" | 45 | #include "dcn10_hubbub.h" |
| 46 | #include "dcn10_cm_common.h" | 46 | #include "dcn10_cm_common.h" |
| 47 | #include "dcn10_clk_mgr.h" | ||
| 47 | 48 | ||
| 48 | static unsigned int snprintf_count(char *pBuf, unsigned int bufSize, char *fmt, ...) | 49 | static unsigned int snprintf_count(char *pBuf, unsigned int bufSize, char *fmt, ...) |
| 49 | { | 50 | { |
| @@ -463,19 +464,22 @@ static unsigned int dcn10_get_otg_states(struct dc *dc, char *pBuf, unsigned int · 413 unmodified lines | |||
| 463 | static unsigned int dcn10_get_clock_states(struct dc *dc, char *pBuf, unsigned int bufSize) | 464 | static unsigned int dcn10_get_clock_states(struct dc *dc, char *pBuf, unsigned int bufSize) |
| 464 | { | 465 | { |
| 465 | unsigned int chars_printed = 0; | 466 | unsigned int chars_printed = 0; |
| 467 | unsigned int remaining_buffer = bufSize; | ||
| 466 | 468 | ||
| 467 | chars_printed = snprintf_count(pBuf, bufSize, "dcfclk_khz,dcfclk_deep_sleep_khz,dispclk_khz," | 469 | chars_printed = snprintf_count(pBuf, bufSize, "dcfclk,dcfclk_deep_sleep,dispclk," |
| 468 | "dppclk_khz,max_supported_dppclk_khz,fclk_khz,socclk_khz\n" | 470 | "dppclk,fclk,socclk\n" |
| 469 | "%d,%d,%d,%d,%d,%d,%d\n", | 471 | "%d,%d,%d,%d,%d,%d\n", |
| 470 | dc->current_state->bw.dcn.clk.dcfclk_khz, | 472 | dc->current_state->bw.dcn.clk.dcfclk_khz, |
| 471 | dc->current_state->bw.dcn.clk.dcfclk_deep_sleep_khz, | 473 | dc->current_state->bw.dcn.clk.dcfclk_deep_sleep_khz, |
| 472 | dc->current_state->bw.dcn.clk.dispclk_khz, | 474 | dc->current_state->bw.dcn.clk.dispclk_khz, |
| 473 | dc->current_state->bw.dcn.clk.dppclk_khz, | 475 | dc->current_state->bw.dcn.clk.dppclk_khz, |
| 474 | dc->current_state->bw.dcn.clk.max_supported_dppclk_khz, | ||
| 475 | dc->current_state->bw.dcn.clk.fclk_khz, | 476 | dc->current_state->bw.dcn.clk.fclk_khz, |
| 476 | dc->current_state->bw.dcn.clk.socclk_khz); | 477 | dc->current_state->bw.dcn.clk.socclk_khz); |
| 477 | 478 | ||
| 478 | return chars_printed; | 479 | remaining_buffer -= chars_printed; |
| 480 | pBuf += chars_printed; | ||
| 481 | |||
| 482 | return bufSize - remaining_buffer; | ||
| 479 | } | 483 | } |
| 480 | 484 | ||
| 481 | static void dcn10_clear_otpc_underflow(struct dc *dc) | 485 | static void dcn10_clear_otpc_underflow(struct dc *dc) |
| @@ -538,16 +542,16 @@ void dcn10_get_hw_state(struct dc *dc, char *pBuf, unsigned int bufSize, unsigne · 56 unmodified lines | |||
| 538 | * Bit 0 - 15: Hardware block mask | 542 | * Bit 0 - 15: Hardware block mask |
| 539 | * Bit 15: 1 = Invariant Only, 0 = All | 543 | * Bit 15: 1 = Invariant Only, 0 = All |
| 540 | */ | 544 | */ |
| 541 | const unsigned int DC_HW_STATE_MASK_HUBBUB = 0x1; | 545 | const unsigned int DC_HW_STATE_MASK_HUBBUB = 0x1; |
| 542 | const unsigned int DC_HW_STATE_MASK_HUBP = 0x2; | 546 | const unsigned int DC_HW_STATE_MASK_HUBP = 0x2; |
| 543 | const unsigned int DC_HW_STATE_MASK_RQ = 0x4; | 547 | const unsigned int DC_HW_STATE_MASK_RQ = 0x4; |
| 544 | const unsigned int DC_HW_STATE_MASK_DLG = 0x8; | 548 | const unsigned int DC_HW_STATE_MASK_DLG = 0x8; |
| 545 | const unsigned int DC_HW_STATE_MASK_TTU = 0x10; | 549 | const unsigned int DC_HW_STATE_MASK_TTU = 0x10; |
| 546 | const unsigned int DC_HW_STATE_MASK_CM = 0x20; | 550 | const unsigned int DC_HW_STATE_MASK_CM = 0x20; |
| 547 | const unsigned int DC_HW_STATE_MASK_MPCC = 0x40; | 551 | const unsigned int DC_HW_STATE_MASK_MPCC = 0x40; |
| 548 | const unsigned int DC_HW_STATE_MASK_OTG = 0x80; | 552 | const unsigned int DC_HW_STATE_MASK_OTG = 0x80; |
| 549 | const unsigned int DC_HW_STATE_MASK_CLOCKS = 0x100; | 553 | const unsigned int DC_HW_STATE_MASK_CLOCKS = 0x100; |
| 550 | const unsigned int DC_HW_STATE_INVAR_ONLY = 0x8000; | 554 | const unsigned int DC_HW_STATE_INVAR_ONLY = 0x8000; |
| 551 | 555 | ||
| 552 | unsigned int chars_printed = 0; | 556 | unsigned int chars_printed = 0; |
| 553 | unsigned int remaining_buf_size = bufSize; | 557 | unsigned int remaining_buf_size = bufSize; |
| @@ -603,6 +607,9 @@ void dcn10_get_hw_state(struct dc *dc, char *pBuf, unsigned int bufSize, unsigne · 49 unmodified lines | |||
| 603 | remaining_buf_size -= chars_printed; | 607 | remaining_buf_size -= chars_printed; |
| 604 | } | 608 | } |
| 605 | 609 | ||
| 606 | if ((mask & DC_HW_STATE_MASK_CLOCKS) && remaining_buf_size > 0) | 610 | if ((mask & DC_HW_STATE_MASK_CLOCKS) && remaining_buf_size > 0) { |
| 607 | chars_printed = dcn10_get_clock_states(dc, pBuf, remaining_buf_size); | 611 | chars_printed = dcn10_get_clock_states(dc, pBuf, remaining_buf_size); |
| 612 | pBuf += chars_printed; | ||
| 613 | remaining_buf_size -= chars_printed; | ||
| 614 | } | ||
| 608 | } | 615 | } |
| @@ -202,7 +202,6 @@ enum dcn10_clk_src_array_id { · 201 unmodified lines | |||
| 202 | #define MMHUB_SR(reg_name)\ | 202 | #define MMHUB_SR(reg_name)\ |
| 203 | .reg_name = MMHUB_BASE(mm ## reg_name ## _BASE_IDX) + \ | 203 | .reg_name = MMHUB_BASE(mm ## reg_name ## _BASE_IDX) + \ |
| 204 | mm ## reg_name | 204 | mm ## reg_name |
| 205 | |||
| 206 | /* macros to expend register list macro defined in HW object header file | 205 | /* macros to expend register list macro defined in HW object header file |
| 207 | * end *********************/ | 206 | * end *********************/ |
| 208 | 207 | ||
| @@ -436,7 +435,6 @@ static const struct dcn_optc_mask tg_mask = { · 227 unmodified lines | |||
| 436 | TG_COMMON_MASK_SH_LIST_DCN1_0(_MASK) | 435 | TG_COMMON_MASK_SH_LIST_DCN1_0(_MASK) |
| 437 | }; | 436 | }; |
| 438 | 437 | ||
| 439 | |||
| 440 | static const struct bios_registers bios_regs = { | 438 | static const struct bios_registers bios_regs = { |
| 441 | NBIO_SR(BIOS_SCRATCH_0), | 439 | NBIO_SR(BIOS_SCRATCH_0), |
| 442 | NBIO_SR(BIOS_SCRATCH_3), | 440 | NBIO_SR(BIOS_SCRATCH_3), |
| @@ -497,7 +495,6 @@ static const struct dce110_clk_src_mask cs_mask = { · 54 unmodified lines | |||
| 497 | CS_COMMON_MASK_SH_LIST_DCN1_0(_MASK) | 495 | CS_COMMON_MASK_SH_LIST_DCN1_0(_MASK) |
| 498 | }; | 496 | }; |
| 499 | 497 | ||
| 500 | |||
| 501 | static const struct resource_caps res_cap = { | 498 | static const struct resource_caps res_cap = { |
| 502 | .num_timing_generator = 4, | 499 | .num_timing_generator = 4, |
| 503 | .num_opp = 4, | 500 | .num_opp = 4, |
| @@ -1277,7 +1274,6 @@ static bool construct( · 773 unmodified lines | |||
| 1277 | goto fail; | 1274 | goto fail; |
| 1278 | } | 1275 | } |
| 1279 | } | 1276 | } |
| 1280 | |||
| 1281 | pool->base.clk_mgr = dcn1_clk_mgr_create(ctx); | 1277 | pool->base.clk_mgr = dcn1_clk_mgr_create(ctx); |
| 1282 | if (pool->base.clk_mgr == NULL) { | 1278 | if (pool->base.clk_mgr == NULL) { |
| 1283 | dm_error("DC: failed to create display clock!\n"); | 1279 | dm_error("DC: failed to create display clock!\n"); |
| @@ -33,6 +33,7 @@ · 32 unmodified lines | |||
| 33 | 33 | ||
| 34 | #define EVENT_LOG_AUX_REQ(ddc, type, action, address, len, data) | 34 | #define EVENT_LOG_AUX_REQ(ddc, type, action, address, len, data) |
| 35 | #define EVENT_LOG_AUX_REP(ddc, type, replyStatus, len, data) | 35 | #define EVENT_LOG_AUX_REP(ddc, type, replyStatus, len, data) |
| 36 | #define EVENT_LOG_CUST_MSG(tag, a, ...) | ||
| 36 | 37 | ||
| 37 | #endif | 38 | #endif |
| 38 | 39 | ||
| @@ -102,7 +102,7 @@ struct pp_smu_funcs_rv { · 101 unmodified lines | |||
| 102 | */ | 102 | */ |
| 103 | void (*set_display_count)(struct pp_smu *pp, int count); | 103 | void (*set_display_count)(struct pp_smu *pp, int count); |
| 104 | 104 | ||
| 105 | /* which SMU message? are reader and writer WM separate SMU msg? */ | 105 | /* reader and writer WM's are sent together as part of one table*/ |
| 106 | /* | 106 | /* |
| 107 | * PPSMC_MSG_SetDriverDramAddrHigh | 107 | * PPSMC_MSG_SetDriverDramAddrHigh |
| 108 | * PPSMC_MSG_SetDriverDramAddrLow | 108 | * PPSMC_MSG_SetDriverDramAddrLow |
| @@ -31,6 +31,8 @@ · 30 unmodified lines | |||
| 31 | 31 | ||
| 32 | #define __DM_SERVICES_H__ | 32 | #define __DM_SERVICES_H__ |
| 33 | 33 | ||
| 34 | #include "amdgpu_dm_trace.h" | ||
| 35 | |||
| 34 | /* TODO: remove when DC is complete. */ | 36 | /* TODO: remove when DC is complete. */ |
| 35 | #include "dm_services_types.h" | 37 | #include "dm_services_types.h" |
| 36 | #include "logger_interface.h" | 38 | #include "logger_interface.h" |
| @@ -70,6 +72,7 @@ static inline uint32_t dm_read_reg_func( · 33 unmodified lines | |||
| 70 | } | 72 | } |
| 71 | #endif | 73 | #endif |
| 72 | value = cgs_read_register(ctx->cgs_device, address); | 74 | value = cgs_read_register(ctx->cgs_device, address); |
| 75 | trace_amdgpu_dc_rreg(&ctx->perf_trace->read_count, address, value); | ||
| 73 | 76 | ||
| 74 | return value; | 77 | return value; |
| 75 | } | 78 | } |
| @@ -90,6 +93,7 @@ static inline void dm_write_reg_func( · 14 unmodified lines | |||
| 90 | } | 93 | } |
| 91 | #endif | 94 | #endif |
| 92 | cgs_write_register(ctx->cgs_device, address, value); | 95 | cgs_write_register(ctx->cgs_device, address, value); |
| 96 | trace_amdgpu_dc_wreg(&ctx->perf_trace->write_count, address, value); | ||
| 93 | } | 97 | } |
| 94 | 98 | ||
| 95 | static inline uint32_t dm_read_index_reg( | 99 | static inline uint32_t dm_read_index_reg( |
| @@ -351,8 +355,12 @@ unsigned long long dm_get_elapse_time_in_ns(struct dc_context *ctx, · 255 unmodified lines | |||
| 351 | /* | 355 | /* |
| 352 | * performance tracing | 356 | * performance tracing |
| 353 | */ | 357 | */ |
| 354 | void dm_perf_trace_timestamp(const char *func_name, unsigned int line); | 358 | #define PERF_TRACE() trace_amdgpu_dc_performance(CTX->perf_trace->read_count,\ |
| 355 | #define PERF_TRACE() dm_perf_trace_timestamp(__func__, __LINE__) | 359 | CTX->perf_trace->write_count, &CTX->perf_trace->last_entry_read,\ |
| 360 | &CTX->perf_trace->last_entry_write, __func__, __LINE__) | ||
| 361 | #define PERF_TRACE_CTX(__CTX) trace_amdgpu_dc_performance(__CTX->perf_trace->read_count,\ | ||
| 362 | __CTX->perf_trace->write_count, &__CTX->perf_trace->last_entry_read,\ | ||
| 363 | &__CTX->perf_trace->last_entry_write, __func__, __LINE__) | ||
| 356 | 364 | ||
| 357 | 365 | ||
| 358 | /* | 366 | /* |
| @@ -56,7 +56,6 @@ struct gpio_service *dal_gpio_service_create( · 55 unmodified lines | |||
| 56 | struct dc_context *ctx) | 56 | struct dc_context *ctx) |
| 57 | { | 57 | { |
| 58 | struct gpio_service *service; | 58 | struct gpio_service *service; |
| 59 | |||
| 60 | uint32_t index_of_id; | 59 | uint32_t index_of_id; |
| 61 | 60 | ||
| 62 | service = kzalloc(sizeof(struct gpio_service), GFP_KERNEL); | 61 | service = kzalloc(sizeof(struct gpio_service), GFP_KERNEL); |
| @@ -78,44 +77,33 @@ struct gpio_service *dal_gpio_service_create( · 15 unmodified lines | |||
| 78 | goto failure_1; | 77 | goto failure_1; |
| 79 | } | 78 | } |
| 80 | 79 | ||
| 81 | /* allocate and initialize business storage */ | 80 | /* allocate and initialize busyness storage */ |
| 82 | { | 81 | { |
| 83 | const uint32_t bits_per_uint = sizeof(uint32_t) << 3; | ||
| 84 | |||
| 85 | index_of_id = 0; | 82 | index_of_id = 0; |
| 86 | service->ctx = ctx; | 83 | service->ctx = ctx; |
| 87 | 84 | ||
| 88 | do { | 85 | do { |
| 89 | uint32_t number_of_bits = | 86 | uint32_t number_of_bits = |
| 90 | service->factory.number_of_pins[index_of_id]; | 87 | service->factory.number_of_pins[index_of_id]; |
| 88 | uint32_t i = 0; | ||
| 91 | 89 | ||
| 92 | uint32_t number_of_uints = | 90 | if (number_of_bits) { |
| 93 | (number_of_bits + bits_per_uint - 1) / | 91 | service->busyness[index_of_id] = |
| 94 | bits_per_uint; | 92 | kcalloc(number_of_bits, sizeof(char), |
| 95 | 93 | GFP_KERNEL); | |
| 96 | uint32_t *slot; | ||
| 97 | |||
| 98 | if (number_of_bits) { | ||
| 99 | uint32_t index_of_uint = 0; | ||
| 100 | 94 | ||
| 101 | slot = kcalloc(number_of_uints, | 95 | if (!service->busyness[index_of_id]) { |
| 102 | sizeof(uint32_t), | ||
| 103 | GFP_KERNEL); | ||
| 104 | |||
| 105 | if (!slot) { | ||
| 106 | BREAK_TO_DEBUGGER(); | 96 | BREAK_TO_DEBUGGER(); |
| 107 | goto failure_2; | 97 | goto failure_2; |
| 108 | } | 98 | } |
| 109 | 99 | ||
| 110 | do { | 100 | do { |
| 111 | slot[index_of_uint] = 0; | 101 | service->busyness[index_of_id][i] = 0; |
| 112 | 102 | ++i; | |
| 113 | ++index_of_uint; | 103 | } while (i < number_of_bits); |
| 114 | } while (index_of_uint < number_of_uints); | 104 | } else { |
| 115 | } else | 105 | service->busyness[index_of_id] = NULL; |
| 116 | slot = NULL; | 106 | } |
| 117 | |||
| 118 | service->busyness[index_of_id] = slot; | ||
| 119 | 107 | ||
| 120 | ++index_of_id; | 108 | ++index_of_id; |
| 121 | } while (index_of_id < GPIO_ID_COUNT); | 109 | } while (index_of_id < GPIO_ID_COUNT); |
| @@ -125,13 +113,8 @@ struct gpio_service *dal_gpio_service_create( · 3 unmodified lines | |||
| 125 | 113 | ||
| 126 | failure_2: | 114 | failure_2: |
| 127 | while (index_of_id) { | 115 | while (index_of_id) { |
| 128 | uint32_t *slot; | ||
| 129 | |||
| 130 | --index_of_id; | 116 | --index_of_id; |
| 131 | 117 | kfree(service->busyness[index_of_id]); | |
| 132 | slot = service->busyness[index_of_id]; | ||
| 133 | |||
| 134 | kfree(slot); | ||
| 135 | } | 118 | } |
| 136 | 119 | ||
| 137 | failure_1: | 120 | failure_1: |
| @@ -169,9 +152,7 @@ void dal_gpio_service_destroy( · 31 unmodified lines | |||
| 169 | uint32_t index_of_id = 0; | 152 | uint32_t index_of_id = 0; |
| 170 | 153 | ||
| 171 | do { | 154 | do { |
| 172 | uint32_t *slot = (*ptr)->busyness[index_of_id]; | 155 | kfree((*ptr)->busyness[index_of_id]); |
| 173 | |||
| 174 | kfree(slot); | ||
| 175 | 156 | ||
| 176 | ++index_of_id; | 157 | ++index_of_id; |
| 177 | } while (index_of_id < GPIO_ID_COUNT); | 158 | } while (index_of_id < GPIO_ID_COUNT); |
| @@ -192,11 +173,7 @@ static bool is_pin_busy( · 14 unmodified lines | |||
| 192 | enum gpio_id id, | 173 | enum gpio_id id, |
| 193 | uint32_t en) | 174 | uint32_t en) |
| 194 | { | 175 | { |
| 195 | const uint32_t bits_per_uint = sizeof(uint32_t) << 3; | 176 | return service->busyness[id][en]; |
| 196 | |||
| 197 | const uint32_t *slot = service->busyness[id] + (en / bits_per_uint); | ||
| 198 | |||
| 199 | return 0 != (*slot & (1 << (en % bits_per_uint))); | ||
| 200 | } | 177 | } |
| 201 | 178 | ||
| 202 | static void set_pin_busy( | 179 | static void set_pin_busy( |
| @@ -204,10 +181,7 @@ static void set_pin_busy( · 1 unmodified line | |||
| 204 | enum gpio_id id, | 181 | enum gpio_id id, |
| 205 | uint32_t en) | 182 | uint32_t en) |
| 206 | { | 183 | { |
| 207 | const uint32_t bits_per_uint = sizeof(uint32_t) << 3; | 184 | service->busyness[id][en] = true; |
| 208 | |||
| 209 | service->busyness[id][en / bits_per_uint] |= | ||
| 210 | (1 << (en % bits_per_uint)); | ||
| 211 | } | 185 | } |
| 212 | 186 | ||
| 213 | static void set_pin_free( | 187 | static void set_pin_free( |
| @@ -215,10 +189,7 @@ static void set_pin_free( · 1 unmodified line | |||
| 215 | enum gpio_id id, | 189 | enum gpio_id id, |
| 216 | uint32_t en) | 190 | uint32_t en) |
| 217 | { | 191 | { |
| 218 | const uint32_t bits_per_uint = sizeof(uint32_t) << 3; | 192 | service->busyness[id][en] = false; |
| 219 | |||
| 220 | service->busyness[id][en / bits_per_uint] &= | ||
| 221 | ~(1 << (en % bits_per_uint)); | ||
| 222 | } | 193 | } |
| 223 | 194 | ||
| 224 | enum gpio_result dal_gpio_service_open( | 195 | enum gpio_result dal_gpio_service_open( |
| @@ -36,10 +36,9 @@ struct gpio_service { · 35 unmodified lines | |||
| 36 | /* | 36 | /* |
| 37 | * @brief | 37 | * @brief |
| 38 | * Business storage. | 38 | * Business storage. |
| 39 | * For each member of 'enum gpio_id', | 39 | * one byte For each member of 'enum gpio_id' |
| 40 | * store array of bits (packed into uint32_t slots), | 40 | */ |
| 41 | * index individual bit by 'en' value */ | 41 | char *busyness[GPIO_ID_COUNT]; |
| 42 | uint32_t *busyness[GPIO_ID_COUNT]; | ||
| 43 | }; | 42 | }; |
| 44 | 43 | ||
| 45 | enum gpio_result dal_gpio_service_open( | 44 | enum gpio_result dal_gpio_service_open( |
| @@ -77,6 +77,7 @@ struct compressor_funcs { · 76 unmodified lines | |||
| 77 | }; | 77 | }; |
| 78 | struct compressor { | 78 | struct compressor { |
| 79 | struct dc_context *ctx; | 79 | struct dc_context *ctx; |
| 80 | /* CONTROLLER_ID_D0 + instance, CONTROLLER_ID_UNDEFINED = 0 */ | ||
| 80 | uint32_t attached_inst; | 81 | uint32_t attached_inst; |
| 81 | bool is_enabled; | 82 | bool is_enabled; |
| 82 | const struct compressor_funcs *funcs; | 83 | const struct compressor_funcs *funcs; |
| @@ -272,6 +272,17 @@ union bw_context { · 271 unmodified lines | |||
| 272 | struct dce_bw_output dce; | 272 | struct dce_bw_output dce; |
| 273 | }; | 273 | }; |
| 274 | 274 | ||
| 275 | /** | ||
| 276 | * struct dc_state - The full description of a state requested by a user | ||
| 277 | * | ||
| 278 | * @streams: Stream properties | ||
| 279 | * @stream_status: The planes on a given stream | ||
| 280 | * @res_ctx: Persistent state of resources | ||
| 281 | * @bw: The output from bandwidth and watermark calculations | ||
| 282 | * @pp_display_cfg: PowerPlay clocks and settings | ||
| 283 | * @dcn_bw_vars: non-stack memory to support bandwidth calculations | ||
| 284 | * | ||
| 285 | */ | ||
| 275 | struct dc_state { | 286 | struct dc_state { |
| 276 | struct dc_stream_state *streams[MAX_PIPES]; | 287 | struct dc_stream_state *streams[MAX_PIPES]; |
| 277 | struct dc_stream_status stream_status[MAX_PIPES]; | 288 | struct dc_stream_status stream_status[MAX_PIPES]; |
| @@ -279,7 +290,6 @@ struct dc_state { · 1 unmodified line | |||
| 279 | 290 | ||
| 280 | struct resource_context res_ctx; | 291 | struct resource_context res_ctx; |
| 281 | 292 | ||
| 282 | /* The output from BW and WM calculations. */ | ||
| 283 | union bw_context bw; | 293 | union bw_context bw; |
| 284 | 294 | ||
| 285 | /* Note: these are big structures, do *not* put on stack! */ | 295 | /* Note: these are big structures, do *not* put on stack! */ |
| @@ -1761,7 +1761,7 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf, · 1760 unmodified lines | |||
| 1761 | 1761 | ||
| 1762 | struct pwl_float_data *rgb_user = NULL; | 1762 | struct pwl_float_data *rgb_user = NULL; |
| 1763 | struct pwl_float_data_ex *curve = NULL; | 1763 | struct pwl_float_data_ex *curve = NULL; |
| 1764 | struct gamma_pixel *axix_x = NULL; | 1764 | struct gamma_pixel *axis_x = NULL; |
| 1765 | struct pixel_gamma_point *coeff = NULL; | 1765 | struct pixel_gamma_point *coeff = NULL; |
| 1766 | enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB; | 1766 | enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB; |
| 1767 | bool ret = false; | 1767 | bool ret = false; |
| @@ -1787,10 +1787,10 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf, · 19 unmodified lines | |||
| 1787 | GFP_KERNEL); | 1787 | GFP_KERNEL); |
| 1788 | if (!curve) | 1788 | if (!curve) |
| 1789 | goto curve_alloc_fail; | 1789 | goto curve_alloc_fail; |
| 1790 | axix_x = kvcalloc(ramp->num_entries + _EXTRA_POINTS, sizeof(*axix_x), | 1790 | axis_x = kvcalloc(ramp->num_entries + _EXTRA_POINTS, sizeof(*axis_x), |
| 1791 | GFP_KERNEL); | 1791 | GFP_KERNEL); |
| 1792 | if (!axix_x) | 1792 | if (!axis_x) |
| 1793 | goto axix_x_alloc_fail; | 1793 | goto axis_x_alloc_fail; |
| 1794 | coeff = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS, sizeof(*coeff), | 1794 | coeff = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS, sizeof(*coeff), |
| 1795 | GFP_KERNEL); | 1795 | GFP_KERNEL); |
| 1796 | if (!coeff) | 1796 | if (!coeff) |
| @@ -1803,7 +1803,7 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf, · 6 unmodified lines | |||
| 1803 | tf = input_tf->tf; | 1803 | tf = input_tf->tf; |
| 1804 | 1804 | ||
| 1805 | build_evenly_distributed_points( | 1805 | build_evenly_distributed_points( |
| 1806 | axix_x, | 1806 | axis_x, |
| 1807 | ramp->num_entries, | 1807 | ramp->num_entries, |
| 1808 | dividers); | 1808 | dividers); |
| 1809 | 1809 | ||
| @@ -1828,7 +1828,7 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf, · 18 unmodified lines | |||
| 1828 | tf_pts->x_point_at_y1_blue = 1; | 1828 | tf_pts->x_point_at_y1_blue = 1; |
| 1829 | 1829 | ||
| 1830 | map_regamma_hw_to_x_user(ramp, coeff, rgb_user, | 1830 | map_regamma_hw_to_x_user(ramp, coeff, rgb_user, |
| 1831 | coordinates_x, axix_x, curve, | 1831 | coordinates_x, axis_x, curve, |
| 1832 | MAX_HW_POINTS, tf_pts, | 1832 | MAX_HW_POINTS, tf_pts, |
| 1833 | mapUserRamp && ramp->type != GAMMA_CUSTOM); | 1833 | mapUserRamp && ramp->type != GAMMA_CUSTOM); |
| 1834 | if (ramp->type == GAMMA_CUSTOM) | 1834 | if (ramp->type == GAMMA_CUSTOM) |
| @@ -1838,8 +1838,8 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf, · 3 unmodified lines | |||
| 1838 | 1838 | ||
| 1839 | kvfree(coeff); | 1839 | kvfree(coeff); |
| 1840 | coeff_alloc_fail: | 1840 | coeff_alloc_fail: |
| 1841 | kvfree(axix_x); | 1841 | kvfree(axis_x); |
| 1842 | axix_x_alloc_fail: | 1842 | axis_x_alloc_fail: |
| 1843 | kvfree(curve); | 1843 | kvfree(curve); |
| 1844 | curve_alloc_fail: | 1844 | curve_alloc_fail: |
| 1845 | kvfree(rgb_user); | 1845 | kvfree(rgb_user); |
| @@ -608,12 +608,12 @@ static void build_vrr_infopacket_data(const struct mod_vrr_params *vrr, · 607 unmodified lines | |||
| 608 | static void build_vrr_infopacket_fs2_data(enum color_transfer_func app_tf, | 608 | static void build_vrr_infopacket_fs2_data(enum color_transfer_func app_tf, |
| 609 | struct dc_info_packet *infopacket) | 609 | struct dc_info_packet *infopacket) |
| 610 | { | 610 | { |
| 611 | if (app_tf != transfer_func_unknown) { | 611 | if (app_tf != TRANSFER_FUNC_UNKNOWN) { |
| 612 | infopacket->valid = true; | 612 | infopacket->valid = true; |
| 613 | 613 | ||
| 614 | infopacket->sb[6] |= 0x08; // PB6 = [Bit 3 = Native Color Active] | 614 | infopacket->sb[6] |= 0x08; // PB6 = [Bit 3 = Native Color Active] |
| 615 | 615 | ||
| 616 | if (app_tf == transfer_func_gamma_22) { | 616 | if (app_tf == TRANSFER_FUNC_GAMMA_22) { |
| 617 | infopacket->sb[9] |= 0x04; // PB6 = [Bit 2 = Gamma 2.2 EOTF Active] | 617 | infopacket->sb[9] |= 0x04; // PB6 = [Bit 2 = Gamma 2.2 EOTF Active] |
| 618 | } | 618 | } |
| 619 | } | 619 | } |
| @@ -688,11 +688,11 @@ void mod_freesync_build_vrr_infopacket(struct mod_freesync *mod_freesync, · 68 unmodified lines | |||
| 688 | return; | 688 | return; |
| 689 | 689 | ||
| 690 | switch (packet_type) { | 690 | switch (packet_type) { |
| 691 | case packet_type_fs2: | 691 | case PACKET_TYPE_FS2: |
| 692 | build_vrr_infopacket_v2(stream->signal, vrr, app_tf, infopacket); | 692 | build_vrr_infopacket_v2(stream->signal, vrr, app_tf, infopacket); |
| 693 | break; | 693 | break; |
| 694 | case packet_type_vrr: | 694 | case PACKET_TYPE_VRR: |
| 695 | case packet_type_fs1: | 695 | case PACKET_TYPE_FS1: |
| 696 | default: | 696 | default: |
| 697 | build_vrr_infopacket_v1(stream->signal, vrr, infopacket); | 697 | build_vrr_infopacket_v1(stream->signal, vrr, infopacket); |
| 698 | } | 698 | } |
| @@ -26,15 +26,13 @@ · 25 unmodified lines | |||
| 26 | #ifndef MOD_INFO_PACKET_H_ | 26 | #ifndef MOD_INFO_PACKET_H_ |
| 27 | #define MOD_INFO_PACKET_H_ | 27 | #define MOD_INFO_PACKET_H_ |
| 28 | 28 | ||
| 29 | struct info_packet_inputs { | 29 | #include "mod_shared.h" |
| 30 | const struct dc_stream_state *pStream; | ||
| 31 | }; | ||
| 32 | 30 | ||
| 33 | struct info_packets { | 31 | //Forward Declarations |
| 34 | struct dc_info_packet *pVscInfoPacket; | 32 | struct dc_stream_state; |
| 35 | }; | 33 | struct dc_info_packet; |
| 36 | 34 | ||
| 37 | void mod_build_infopackets(struct info_packet_inputs *inputs, | 35 | void mod_build_vsc_infopacket(const struct dc_stream_state *stream, |
| 38 | struct info_packets *info_packets); | 36 | struct dc_info_packet *info_packet); |
| 39 | 37 | ||
| 40 | #endif | 38 | #endif |
| @@ -23,27 +23,26 @@ · 22 unmodified lines | |||
| 23 | * | 23 | * |
| 24 | */ | 24 | */ |
| 25 | 25 | ||
| 26 | |||
| 27 | #ifndef MOD_SHARED_H_ | 26 | #ifndef MOD_SHARED_H_ |
| 28 | #define MOD_SHARED_H_ | 27 | #define MOD_SHARED_H_ |
| 29 | 28 | ||
| 30 | enum color_transfer_func { | 29 | enum color_transfer_func { |
| 31 | transfer_func_unknown, | 30 | TRANSFER_FUNC_UNKNOWN, |
| 32 | transfer_func_srgb, | 31 | TRANSFER_FUNC_SRGB, |
| 33 | transfer_func_bt709, | 32 | TRANSFER_FUNC_BT709, |
| 34 | transfer_func_pq2084, | 33 | TRANSFER_FUNC_PQ2084, |
| 35 | transfer_func_pq2084_interim, | 34 | TRANSFER_FUNC_PQ2084_INTERIM, |
| 36 | transfer_func_linear_0_1, | 35 | TRANSFER_FUNC_LINEAR_0_1, |
| 37 | transfer_func_linear_0_125, | 36 | TRANSFER_FUNC_LINEAR_0_125, |
| 38 | transfer_func_dolbyvision, | 37 | TRANSFER_FUNC_GAMMA_22, |
| 39 | transfer_func_gamma_22, | 38 | TRANSFER_FUNC_GAMMA_26 |
| 40 | transfer_func_gamma_26 | ||
| 41 | }; | 39 | }; |
| 42 | 40 | ||
| 43 | enum vrr_packet_type { | 41 | enum vrr_packet_type { |
| 44 | packet_type_vrr, | 42 | PACKET_TYPE_VRR, |
| 45 | packet_type_fs1, | 43 | PACKET_TYPE_FS1, |
| 46 | packet_type_fs2 | 44 | PACKET_TYPE_FS2 |
| 47 | }; | 45 | }; |
| 48 | 46 | ||
| 47 | |||
| 49 | #endif /* MOD_SHARED_H_ */ | 48 | #endif /* MOD_SHARED_H_ */ |
| @@ -25,6 +25,10 @@ · 24 unmodified lines | |||
| 25 | 25 | ||
| 26 | #include "mod_info_packet.h" | 26 | #include "mod_info_packet.h" |
| 27 | #include "core_types.h" | 27 | #include "core_types.h" |
| 28 | #include "dc_types.h" | ||
| 29 | #include "mod_shared.h" | ||
| 30 | |||
| 31 | #define HDMI_INFOFRAME_TYPE_VENDOR 0x81 | ||
| 28 | 32 | ||
| 29 | enum ColorimetryRGBDP { | 33 | enum ColorimetryRGBDP { |
| 30 | ColorimetryRGB_DP_sRGB = 0, | 34 | ColorimetryRGB_DP_sRGB = 0, |
| @@ -41,7 +45,7 @@ enum ColorimetryYCCDP { · 10 unmodified lines | |||
| 41 | ColorimetryYCC_DP_ITU2020YCbCr = 7, | 45 | ColorimetryYCC_DP_ITU2020YCbCr = 7, |
| 42 | }; | 46 | }; |
| 43 | 47 | ||
| 44 | static void mod_build_vsc_infopacket(const struct dc_stream_state *stream, | 48 | void mod_build_vsc_infopacket(const struct dc_stream_state *stream, |
| 45 | struct dc_info_packet *info_packet) | 49 | struct dc_info_packet *info_packet) |
| 46 | { | 50 | { |
| 47 | unsigned int vscPacketRevision = 0; | 51 | unsigned int vscPacketRevision = 0; |
| @@ -159,7 +163,7 @@ static void mod_build_vsc_infopacket(const struct dc_stream_state *stream, · 111 unmodified lines | |||
| 159 | * DPCD register is exposed in the new Extended Receiver Capability field for DPCD Rev. 1.4 | 163 | * DPCD register is exposed in the new Extended Receiver Capability field for DPCD Rev. 1.4 |
| 160 | * (and higher). When MISC1. bit 6. is Set to 1, a Source device uses a VSC SDP to indicate | 164 | * (and higher). When MISC1. bit 6. is Set to 1, a Source device uses a VSC SDP to indicate |
| 161 | * the Pixel Encoding/Colorimetry Format and that a Sink device must ignore MISC1, bit 7, and | 165 | * the Pixel Encoding/Colorimetry Format and that a Sink device must ignore MISC1, bit 7, and |
| 162 | * MISC0, bits 7:1 (MISC1, bit 7. and MISC0, bits 7:1 become “don’t care”).) | 166 | * MISC0, bits 7:1 (MISC1, bit 7. and MISC0, bits 7:1 become "don't care").) |
| 163 | */ | 167 | */ |
| 164 | if (vscPacketRevision == 0x5) { | 168 | if (vscPacketRevision == 0x5) { |
| 165 | /* Secondary-data Packet ID = 0 */ | 169 | /* Secondary-data Packet ID = 0 */ |
| @@ -320,10 +324,3 @@ static void mod_build_vsc_infopacket(const struct dc_stream_state *stream, · 154 unmodified lines | |||
| 320 | 324 | ||
| 321 | } | 325 | } |
| 322 | 326 | ||
| 323 | void mod_build_infopackets(struct info_packet_inputs *inputs, | ||
| 324 | struct info_packets *info_packets) | ||
| 325 | { | ||
| 326 | if (info_packets->pVscInfoPacket != NULL) | ||
| 327 | mod_build_vsc_infopacket(inputs->pStream, info_packets->pVscInfoPacket); | ||
| 328 | } | ||
| 329 | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2018 Advanced Micro Devices, Inc. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice shall be included | ||
| 12 | * in all copies or substantial portions of the Software. | ||
| 13 | * | ||
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
| 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 17 | * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | ||
| 18 | * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 19 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 20 | */ | ||
| 21 | #ifndef _mmhub_9_4_0_OFFSET_HEADER | ||
| 22 | #define _mmhub_9_4_0_OFFSET_HEADER | ||
| 23 | |||
| 24 | |||
| 25 | // addressBlock: mmhub_utcl2_vmsharedpfdec | ||
| 26 | // base address: 0x6a040 | ||
| 27 | #define mmMC_VM_XGMI_LFB_CNTL 0x0823 | ||
| 28 | #define mmMC_VM_XGMI_LFB_CNTL_BASE_IDX 0 | ||
| 29 | #define mmMC_VM_XGMI_LFB_SIZE 0x0824 | ||
| 30 | #define mmMC_VM_XGMI_LFB_SIZE_BASE_IDX 0 | ||
| 31 | |||
| 32 | #endif | ||
| @@ -0,0 +1,35 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2018 Advanced Micro Devices, Inc. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice shall be included | ||
| 12 | * in all copies or substantial portions of the Software. | ||
| 13 | * | ||
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
| 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 17 | * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | ||
| 18 | * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 19 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 20 | */ | ||
| 21 | #ifndef _mmhub_9_4_0_SH_MASK_HEADER | ||
| 22 | #define _mmhub_9_4_0_SH_MASK_HEADER | ||
| 23 | |||
| 24 | |||
| 25 | // addressBlock: mmhub_utcl2_vmsharedpfdec | ||
| 26 | //MC_VM_XGMI_LFB_CNTL | ||
| 27 | #define MC_VM_XGMI_LFB_CNTL__PF_LFB_REGION__SHIFT 0x0 | ||
| 28 | #define MC_VM_XGMI_LFB_CNTL__PF_MAX_REGION__SHIFT 0x4 | ||
| 29 | #define MC_VM_XGMI_LFB_CNTL__PF_LFB_REGION_MASK 0x00000007L | ||
| 30 | #define MC_VM_XGMI_LFB_CNTL__PF_MAX_REGION_MASK 0x00000070L | ||
| 31 | //MC_VM_XGMI_LFB_SIZE | ||
| 32 | #define MC_VM_XGMI_LFB_SIZE__PF_LFB_SIZE__SHIFT 0x0 | ||
| 33 | #define MC_VM_XGMI_LFB_SIZE__PF_LFB_SIZE_MASK 0x0000FFFFL | ||
| 34 | |||
| 35 | #endif | ||
| @@ -188,8 +188,8 @@ struct tile_config { · 187 unmodified lines | |||
| 188 | */ | 188 | */ |
| 189 | #define ALLOC_MEM_FLAGS_VRAM (1 << 0) | 189 | #define ALLOC_MEM_FLAGS_VRAM (1 << 0) |
| 190 | #define ALLOC_MEM_FLAGS_GTT (1 << 1) | 190 | #define ALLOC_MEM_FLAGS_GTT (1 << 1) |
| 191 | #define ALLOC_MEM_FLAGS_USERPTR (1 << 2) /* TODO */ | 191 | #define ALLOC_MEM_FLAGS_USERPTR (1 << 2) |
| 192 | #define ALLOC_MEM_FLAGS_DOORBELL (1 << 3) /* TODO */ | 192 | #define ALLOC_MEM_FLAGS_DOORBELL (1 << 3) |
| 193 | 193 | ||
| 194 | /* | 194 | /* |
| 195 | * Allocation flags attributes/access options. | 195 | * Allocation flags attributes/access options. |
| @@ -276,6 +276,10 @@ struct amd_pm_funcs { · 275 unmodified lines | |||
| 276 | struct amd_pp_simple_clock_info *clocks); | 276 | struct amd_pp_simple_clock_info *clocks); |
| 277 | int (*notify_smu_enable_pwe)(void *handle); | 277 | int (*notify_smu_enable_pwe)(void *handle); |
| 278 | int (*enable_mgpu_fan_boost)(void *handle); | 278 | int (*enable_mgpu_fan_boost)(void *handle); |
| 279 | int (*set_active_display_count)(void *handle, uint32_t count); | ||
| 280 | int (*set_hard_min_dcefclk_by_freq)(void *handle, uint32_t clock); | ||
| 281 | int (*set_hard_min_fclk_by_freq)(void *handle, uint32_t clock); | ||
| 282 | int (*set_min_deep_sleep_dcefclk)(void *handle, uint32_t clock); | ||
| 279 | }; | 283 | }; |
| 280 | 284 | ||
| 281 | #endif | 285 | #endif |
| @@ -725,7 +725,7 @@ static int pp_dpm_force_clock_level(void *handle, · 724 unmodified lines | |||
| 725 | } | 725 | } |
| 726 | 726 | ||
| 727 | if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { | 727 | if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { |
| 728 | pr_info("force clock level is for dpm manual mode only.\n"); | 728 | pr_debug("force clock level is for dpm manual mode only.\n"); |
| 729 | return -EINVAL; | 729 | return -EINVAL; |
| 730 | } | 730 | } |
| 731 | 731 | ||
| @@ -899,7 +899,7 @@ static int pp_set_power_profile_mode(void *handle, long *input, uint32_t size) · 167 unmodified lines | |||
| 899 | } | 899 | } |
| 900 | 900 | ||
| 901 | if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { | 901 | if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { |
| 902 | pr_info("power profile setting is for manual dpm mode only.\n"); | 902 | pr_debug("power profile setting is for manual dpm mode only.\n"); |
| 903 | return ret; | 903 | return ret; |
| 904 | } | 904 | } |
| 905 | 905 | ||
| @@ -1072,7 +1072,7 @@ static int pp_get_current_clocks(void *handle, · 166 unmodified lines | |||
| 1072 | &hw_clocks, PHM_PerformanceLevelDesignation_Activity); | 1072 | &hw_clocks, PHM_PerformanceLevelDesignation_Activity); |
| 1073 | 1073 | ||
| 1074 | if (ret) { | 1074 | if (ret) { |
| 1075 | pr_info("Error in phm_get_clock_info \n"); | 1075 | pr_debug("Error in phm_get_clock_info \n"); |
| 1076 | mutex_unlock(&hwmgr->smu_lock); | 1076 | mutex_unlock(&hwmgr->smu_lock); |
| 1077 | return -EINVAL; | 1077 | return -EINVAL; |
| 1078 | } | 1078 | } |
| @@ -1332,6 +1332,78 @@ static int pp_enable_mgpu_fan_boost(void *handle) · 253 unmodified lines | |||
| 1332 | return 0; | 1332 | return 0; |
| 1333 | } | 1333 | } |
| 1334 | 1334 | ||
| 1335 | static int pp_set_min_deep_sleep_dcefclk(void *handle, uint32_t clock) | ||
| 1336 | { | ||
| 1337 | struct pp_hwmgr *hwmgr = handle; | ||
| 1338 | |||
| 1339 | if (!hwmgr || !hwmgr->pm_en) | ||
| 1340 | return -EINVAL; | ||
| 1341 | |||
| 1342 | if (hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk == NULL) { | ||
| 1343 | pr_debug("%s was not implemented.\n", __func__); | ||
| 1344 | return -EINVAL;; | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | mutex_lock(&hwmgr->smu_lock); | ||
| 1348 | hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, clock); | ||
| 1349 | mutex_unlock(&hwmgr->smu_lock); | ||
| 1350 | |||
| 1351 | return 0; | ||
| 1352 | } | ||
| 1353 | |||
| 1354 | static int pp_set_hard_min_dcefclk_by_freq(void *handle, uint32_t clock) | ||
| 1355 | { | ||
| 1356 | struct pp_hwmgr *hwmgr = handle; | ||
| 1357 | |||
| 1358 | if (!hwmgr || !hwmgr->pm_en) | ||
| 1359 | return -EINVAL; | ||
| 1360 | |||
| 1361 | if (hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq == NULL) { | ||
| 1362 | pr_debug("%s was not implemented.\n", __func__); | ||
| 1363 | return -EINVAL;; | ||
| 1364 | } | ||
| 1365 | |||
| 1366 | mutex_lock(&hwmgr->smu_lock); | ||
| 1367 | hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq(hwmgr, clock); | ||
| 1368 | mutex_unlock(&hwmgr->smu_lock); | ||
| 1369 | |||
| 1370 | return 0; | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | static int pp_set_hard_min_fclk_by_freq(void *handle, uint32_t clock) | ||
| 1374 | { | ||
| 1375 | struct pp_hwmgr *hwmgr = handle; | ||
| 1376 | |||
| 1377 | if (!hwmgr || !hwmgr->pm_en) | ||
| 1378 | return -EINVAL; | ||
| 1379 | |||
| 1380 | if (hwmgr->hwmgr_func->set_hard_min_fclk_by_freq == NULL) { | ||
| 1381 | pr_debug("%s was not implemented.\n", __func__); | ||
| 1382 | return -EINVAL;; | ||
| 1383 | } | ||
| 1384 | |||
| 1385 | mutex_lock(&hwmgr->smu_lock); | ||
| 1386 | hwmgr->hwmgr_func->set_hard_min_fclk_by_freq(hwmgr, clock); | ||
| 1387 | mutex_unlock(&hwmgr->smu_lock); | ||
| 1388 | |||
| 1389 | return 0; | ||
| 1390 | } | ||
| 1391 | |||
| 1392 | static int pp_set_active_display_count(void *handle, uint32_t count) | ||
| 1393 | { | ||
| 1394 | struct pp_hwmgr *hwmgr = handle; | ||
| 1395 | int ret = 0; | ||
| 1396 | |||
| 1397 | if (!hwmgr || !hwmgr->pm_en) | ||
| 1398 | return -EINVAL; | ||
| 1399 | |||
| 1400 | mutex_lock(&hwmgr->smu_lock); | ||
| 1401 | ret = phm_set_active_display_count(hwmgr, count); | ||
| 1402 | mutex_unlock(&hwmgr->smu_lock); | ||
| 1403 | |||
| 1404 | return ret; | ||
| 1405 | } | ||
| 1406 | |||
| 1335 | static const struct amd_pm_funcs pp_dpm_funcs = { | 1407 | static const struct amd_pm_funcs pp_dpm_funcs = { |
| 1336 | .load_firmware = pp_dpm_load_fw, | 1408 | .load_firmware = pp_dpm_load_fw, |
| 1337 | .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete, | 1409 | .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete, |
| @@ -1378,4 +1450,8 @@ static const struct amd_pm_funcs pp_dpm_funcs = { · 40 unmodified lines | |||
| 1378 | .get_display_mode_validation_clocks = pp_get_display_mode_validation_clocks, | 1450 | .get_display_mode_validation_clocks = pp_get_display_mode_validation_clocks, |
| 1379 | .notify_smu_enable_pwe = pp_notify_smu_enable_pwe, | 1451 | .notify_smu_enable_pwe = pp_notify_smu_enable_pwe, |
| 1380 | .enable_mgpu_fan_boost = pp_enable_mgpu_fan_boost, | 1452 | .enable_mgpu_fan_boost = pp_enable_mgpu_fan_boost, |
| 1453 | .set_active_display_count = pp_set_active_display_count, | ||
| 1454 | .set_min_deep_sleep_dcefclk = pp_set_min_deep_sleep_dcefclk, | ||
| 1455 | .set_hard_min_dcefclk_by_freq = pp_set_hard_min_dcefclk_by_freq, | ||
| 1456 | .set_hard_min_fclk_by_freq = pp_set_hard_min_fclk_by_freq, | ||
| 1381 | }; | 1457 | }; |
| @@ -286,8 +286,8 @@ int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr, · 285 unmodified lines | |||
| 286 | if (display_config == NULL) | 286 | if (display_config == NULL) |
| 287 | return -EINVAL; | 287 | return -EINVAL; |
| 288 | 288 | ||
| 289 | if (NULL != hwmgr->hwmgr_func->set_deep_sleep_dcefclk) | 289 | if (NULL != hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk) |
| 290 | hwmgr->hwmgr_func->set_deep_sleep_dcefclk(hwmgr, display_config->min_dcef_deep_sleep_set_clk); | 290 | hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, display_config->min_dcef_deep_sleep_set_clk); |
| 291 | 291 | ||
| 292 | for (index = 0; index < display_config->num_path_including_non_display; index++) { | 292 | for (index = 0; index < display_config->num_path_including_non_display; index++) { |
| 293 | if (display_config->displays[index].controller_id != 0) | 293 | if (display_config->displays[index].controller_id != 0) |
| @@ -478,3 +478,44 @@ int phm_disable_smc_firmware_ctf(struct pp_hwmgr *hwmgr) · 184 unmodified lines | |||
| 478 | 478 | ||
| 479 | return hwmgr->hwmgr_func->disable_smc_firmware_ctf(hwmgr); | 479 | return hwmgr->hwmgr_func->disable_smc_firmware_ctf(hwmgr); |
| 480 | } | 480 | } |
| 481 | |||
| 482 | int phm_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count) | ||
| 483 | { | ||
| 484 | PHM_FUNC_CHECK(hwmgr); | ||
| 485 | |||
| 486 | if (!hwmgr->hwmgr_func->set_active_display_count) | ||
| 487 | return -EINVAL; | ||
| 488 | |||
| 489 | return hwmgr->hwmgr_func->set_active_display_count(hwmgr, count); | ||
| 490 | } | ||
| 491 | |||
| 492 | int phm_set_min_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clock) | ||
| 493 | { | ||
| 494 | PHM_FUNC_CHECK(hwmgr); | ||
| 495 | |||
| 496 | if (!hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk) | ||
| 497 | return -EINVAL; | ||
| 498 | |||
| 499 | return hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, clock); | ||
| 500 | } | ||
| 501 | |||
| 502 | int phm_set_hard_min_dcefclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) | ||
| 503 | { | ||
| 504 | PHM_FUNC_CHECK(hwmgr); | ||
| 505 | |||
| 506 | if (!hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq) | ||
| 507 | return -EINVAL; | ||
| 508 | |||
| 509 | return hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq(hwmgr, clock); | ||
| 510 | } | ||
| 511 | |||
| 512 | int phm_set_hard_min_fclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) | ||
| 513 | { | ||
| 514 | PHM_FUNC_CHECK(hwmgr); | ||
| 515 | |||
| 516 | if (!hwmgr->hwmgr_func->set_hard_min_fclk_by_freq) | ||
| 517 | return -EINVAL; | ||
| 518 | |||
| 519 | return hwmgr->hwmgr_func->set_hard_min_fclk_by_freq(hwmgr, clock); | ||
| 520 | } | ||
| 521 | |||
| @@ -216,12 +216,12 @@ static inline uint32_t convert_10k_to_mhz(uint32_t clock) · 215 unmodified lines | |||
| 216 | return (clock + 99) / 100; | 216 | return (clock + 99) / 100; |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | static int smu10_set_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clock) | 219 | static int smu10_set_min_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clock) |
| 220 | { | 220 | { |
| 221 | struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); | 221 | struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); |
| 222 | 222 | ||
| 223 | if (smu10_data->need_min_deep_sleep_dcefclk && | 223 | if (smu10_data->need_min_deep_sleep_dcefclk && |
| 224 | smu10_data->deep_sleep_dcefclk != convert_10k_to_mhz(clock)) { | 224 | smu10_data->deep_sleep_dcefclk != convert_10k_to_mhz(clock)) { |
| 225 | smu10_data->deep_sleep_dcefclk = convert_10k_to_mhz(clock); | 225 | smu10_data->deep_sleep_dcefclk = convert_10k_to_mhz(clock); |
| 226 | smum_send_msg_to_smc_with_parameter(hwmgr, | 226 | smum_send_msg_to_smc_with_parameter(hwmgr, |
| 227 | PPSMC_MSG_SetMinDeepSleepDcefclk, | 227 | PPSMC_MSG_SetMinDeepSleepDcefclk, |
| @@ -230,6 +230,34 @@ static int smu10_set_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clock) · 2 unmodified lines | |||
| 230 | return 0; | 230 | return 0; |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | static int smu10_set_hard_min_dcefclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) | ||
| 234 | { | ||
| 235 | struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); | ||
| 236 | |||
| 237 | if (smu10_data->dcf_actual_hard_min_freq && | ||
| 238 | smu10_data->dcf_actual_hard_min_freq != convert_10k_to_mhz(clock)) { | ||
| 239 | smu10_data->dcf_actual_hard_min_freq = convert_10k_to_mhz(clock); | ||
| 240 | smum_send_msg_to_smc_with_parameter(hwmgr, | ||
| 241 | PPSMC_MSG_SetHardMinDcefclkByFreq, | ||
| 242 | smu10_data->dcf_actual_hard_min_freq); | ||
| 243 | } | ||
| 244 | return 0; | ||
| 245 | } | ||
| 246 | |||
| 247 | static int smu10_set_hard_min_fclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) | ||
| 248 | { | ||
| 249 | struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); | ||
| 250 | |||
| 251 | if (smu10_data->f_actual_hard_min_freq && | ||
| 252 | smu10_data->f_actual_hard_min_freq != convert_10k_to_mhz(clock)) { | ||
| 253 | smu10_data->f_actual_hard_min_freq = convert_10k_to_mhz(clock); | ||
| 254 | smum_send_msg_to_smc_with_parameter(hwmgr, | ||
| 255 | PPSMC_MSG_SetHardMinFclkByFreq, | ||
| 256 | smu10_data->f_actual_hard_min_freq); | ||
| 257 | } | ||
| 258 | return 0; | ||
| 259 | } | ||
| 260 | |||
| 233 | static int smu10_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count) | 261 | static int smu10_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count) |
| 234 | { | 262 | { |
| 235 | struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); | 263 | struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); |
| @@ -1206,7 +1234,7 @@ static const struct pp_hwmgr_func smu10_hwmgr_funcs = { · 970 unmodified lines | |||
| 1206 | .get_max_high_clocks = smu10_get_max_high_clocks, | 1234 | .get_max_high_clocks = smu10_get_max_high_clocks, |
| 1207 | .read_sensor = smu10_read_sensor, | 1235 | .read_sensor = smu10_read_sensor, |
| 1208 | .set_active_display_count = smu10_set_active_display_count, | 1236 | .set_active_display_count = smu10_set_active_display_count, |
| 1209 | .set_deep_sleep_dcefclk = smu10_set_deep_sleep_dcefclk, | 1237 | .set_min_deep_sleep_dcefclk = smu10_set_min_deep_sleep_dcefclk, |
| 1210 | .dynamic_state_management_enable = smu10_enable_dpm_tasks, | 1238 | .dynamic_state_management_enable = smu10_enable_dpm_tasks, |
| 1211 | .power_off_asic = smu10_power_off_asic, | 1239 | .power_off_asic = smu10_power_off_asic, |
| 1212 | .asic_setup = smu10_setup_asic_task, | 1240 | .asic_setup = smu10_setup_asic_task, |
| @@ -1217,6 +1245,8 @@ static const struct pp_hwmgr_func smu10_hwmgr_funcs = { · 4 unmodified lines | |||
| 1217 | .display_clock_voltage_request = smu10_display_clock_voltage_request, | 1245 | .display_clock_voltage_request = smu10_display_clock_voltage_request, |
| 1218 | .powergate_gfx = smu10_gfx_off_control, | 1246 | .powergate_gfx = smu10_gfx_off_control, |
| 1219 | .powergate_sdma = smu10_powergate_sdma, | 1247 | .powergate_sdma = smu10_powergate_sdma, |
| 1248 | .set_hard_min_dcefclk_by_freq = smu10_set_hard_min_dcefclk_by_freq, | ||
| 1249 | .set_hard_min_fclk_by_freq = smu10_set_hard_min_fclk_by_freq, | ||
| 1220 | }; | 1250 | }; |
| 1221 | 1251 | ||
| 1222 | int smu10_init_function_pointers(struct pp_hwmgr *hwmgr) | 1252 | int smu10_init_function_pointers(struct pp_hwmgr *hwmgr) |
| @@ -2859,7 +2859,10 @@ static int smu7_vblank_too_short(struct pp_hwmgr *hwmgr, · 2858 unmodified lines | |||
| 2859 | case CHIP_POLARIS10: | 2859 | case CHIP_POLARIS10: |
| 2860 | case CHIP_POLARIS11: | 2860 | case CHIP_POLARIS11: |
| 2861 | case CHIP_POLARIS12: | 2861 | case CHIP_POLARIS12: |
| 2862 | switch_limit_us = data->is_memory_gddr5 ? 190 : 150; | 2862 | if (hwmgr->is_kicker) |
| 2863 | switch_limit_us = data->is_memory_gddr5 ? 450 : 150; | ||
| 2864 | else | ||
| 2865 | switch_limit_us = data->is_memory_gddr5 ? 190 : 150; | ||
| 2863 | break; | 2866 | break; |
| 2864 | case CHIP_VEGAM: | 2867 | case CHIP_VEGAM: |
| 2865 | switch_limit_us = 30; | 2868 | switch_limit_us = 30; |
| @@ -4219,9 +4222,17 @@ static int smu7_check_mc_firmware(struct pp_hwmgr *hwmgr) · 1353 unmodified lines | |||
| 4219 | if (tmp & (1 << 23)) { | 4222 | if (tmp & (1 << 23)) { |
| 4220 | data->mem_latency_high = MEM_LATENCY_HIGH; | 4223 | data->mem_latency_high = MEM_LATENCY_HIGH; |
| 4221 | data->mem_latency_low = MEM_LATENCY_LOW; | 4224 | data->mem_latency_low = MEM_LATENCY_LOW; |
| 4225 | if ((hwmgr->chip_id == CHIP_POLARIS10) || | ||
| 4226 | (hwmgr->chip_id == CHIP_POLARIS11) || | ||
| 4227 | (hwmgr->chip_id == CHIP_POLARIS12)) | ||
| 4228 | smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableFFC); | ||
| 4222 | } else { | 4229 | } else { |
| 4223 | data->mem_latency_high = 330; | 4230 | data->mem_latency_high = 330; |
| 4224 | data->mem_latency_low = 330; | 4231 | data->mem_latency_low = 330; |
| 4232 | if ((hwmgr->chip_id == CHIP_POLARIS10) || | ||
| 4233 | (hwmgr->chip_id == CHIP_POLARIS11) || | ||
| 4234 | (hwmgr->chip_id == CHIP_POLARIS12)) | ||
| 4235 | smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableFFC); | ||
| 4225 | } | 4236 | } |
| 4226 | 4237 | ||
| 4227 | return 0; | 4238 | return 0; |
| @@ -463,5 +463,8 @@ extern int phm_display_clock_voltage_request(struct pp_hwmgr *hwmgr, · 462 unmodified lines | |||
| 463 | 463 | ||
| 464 | extern int phm_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks); | 464 | extern int phm_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks); |
| 465 | extern int phm_disable_smc_firmware_ctf(struct pp_hwmgr *hwmgr); | 465 | extern int phm_disable_smc_firmware_ctf(struct pp_hwmgr *hwmgr); |
| 466 | |||
| 467 | extern int phm_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count); | ||
| 468 | |||
| 466 | #endif /* _HARDWARE_MANAGER_H_ */ | 469 | #endif /* _HARDWARE_MANAGER_H_ */ |
| 467 | 470 | ||
| @@ -309,7 +309,7 @@ struct pp_hwmgr_func { · 308 unmodified lines | |||
| 309 | int (*avfs_control)(struct pp_hwmgr *hwmgr, bool enable); | 309 | int (*avfs_control)(struct pp_hwmgr *hwmgr, bool enable); |
| 310 | int (*disable_smc_firmware_ctf)(struct pp_hwmgr *hwmgr); | 310 | int (*disable_smc_firmware_ctf)(struct pp_hwmgr *hwmgr); |
| 311 | int (*set_active_display_count)(struct pp_hwmgr *hwmgr, uint32_t count); | 311 | int (*set_active_display_count)(struct pp_hwmgr *hwmgr, uint32_t count); |
| 312 | int (*set_deep_sleep_dcefclk)(struct pp_hwmgr *hwmgr, uint32_t clock); | 312 | int (*set_min_deep_sleep_dcefclk)(struct pp_hwmgr *hwmgr, uint32_t clock); |
| 313 | int (*start_thermal_controller)(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range); | 313 | int (*start_thermal_controller)(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range); |
| 314 | int (*notify_cac_buffer_info)(struct pp_hwmgr *hwmgr, | 314 | int (*notify_cac_buffer_info)(struct pp_hwmgr *hwmgr, |
| 315 | uint32_t virtual_addr_low, | 315 | uint32_t virtual_addr_low, |
| @@ -332,6 +332,8 @@ struct pp_hwmgr_func { · 16 unmodified lines | |||
| 332 | int (*smus_notify_pwe)(struct pp_hwmgr *hwmgr); | 332 | int (*smus_notify_pwe)(struct pp_hwmgr *hwmgr); |
| 333 | int (*powergate_sdma)(struct pp_hwmgr *hwmgr, bool bgate); | 333 | int (*powergate_sdma)(struct pp_hwmgr *hwmgr, bool bgate); |
| 334 | int (*enable_mgpu_fan_boost)(struct pp_hwmgr *hwmgr); | 334 | int (*enable_mgpu_fan_boost)(struct pp_hwmgr *hwmgr); |
| 335 | int (*set_hard_min_dcefclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); | ||
| 336 | int (*set_hard_min_fclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); | ||
| 335 | }; | 337 | }; |
| 336 | 338 | ||
| 337 | struct pp_table_func { | 339 | struct pp_table_func { |
| @@ -395,6 +395,9 @@ typedef uint16_t PPSMC_Result; · 394 unmodified lines | |||
| 395 | 395 | ||
| 396 | #define PPSMC_MSG_SetVBITimeout ((uint16_t) 0x306) | 396 | #define PPSMC_MSG_SetVBITimeout ((uint16_t) 0x306) |
| 397 | 397 | ||
| 398 | #define PPSMC_MSG_EnableFFC ((uint16_t) 0x307) | ||
| 399 | #define PPSMC_MSG_DisableFFC ((uint16_t) 0x308) | ||
| 400 | |||
| 398 | #define PPSMC_MSG_EnableDpmDidt ((uint16_t) 0x309) | 401 | #define PPSMC_MSG_EnableDpmDidt ((uint16_t) 0x309) |
| 399 | #define PPSMC_MSG_DisableDpmDidt ((uint16_t) 0x30A) | 402 | #define PPSMC_MSG_DisableDpmDidt ((uint16_t) 0x30A) |
| 400 | 403 | ||
| @@ -1528,8 +1528,21 @@ static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) · 1527 unmodified lines | |||
| 1528 | efuse = efuse >> 24; | 1528 | efuse = efuse >> 24; |
| 1529 | 1529 | ||
| 1530 | if (hwmgr->chip_id == CHIP_POLARIS10) { | 1530 | if (hwmgr->chip_id == CHIP_POLARIS10) { |
| 1531 | min = 1000; | 1531 | if (hwmgr->is_kicker) { |
| 1532 | max = 2300; | 1532 | min = 1200; |
| 1533 | max = 2500; | ||
| 1534 | } else { | ||
| 1535 | min = 1000; | ||
| 1536 | max = 2300; | ||
| 1537 | } | ||
| 1538 | } else if (hwmgr->chip_id == CHIP_POLARIS11) { | ||
| 1539 | if (hwmgr->is_kicker) { | ||
| 1540 | min = 900; | ||
| 1541 | max = 2100; | ||
| 1542 | } else { | ||
| 1543 | min = 1100; | ||
| 1544 | max = 2100; | ||
| 1545 | } | ||
| 1533 | } else { | 1546 | } else { |
| 1534 | min = 1100; | 1547 | min = 1100; |
| 1535 | max = 2100; | 1548 | max = 2100; |
| @@ -1626,6 +1639,7 @@ static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) · 90 unmodified lines | |||
| 1626 | { | 1639 | { |
| 1627 | struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); | 1640 | struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); |
| 1628 | struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); | 1641 | struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); |
| 1642 | struct amdgpu_device *adev = hwmgr->adev; | ||
| 1629 | 1643 | ||
| 1630 | SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); | 1644 | SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); |
| 1631 | int result = 0; | 1645 | int result = 0; |
| @@ -1645,6 +1659,59 @@ static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) · 13 unmodified lines | |||
| 1645 | 1659 | ||
| 1646 | result = atomctrl_get_avfs_information(hwmgr, &avfs_params); | 1660 | result = atomctrl_get_avfs_information(hwmgr, &avfs_params); |
| 1647 | 1661 | ||
| 1662 | if (0 == result) { | ||
| 1663 | if (((adev->pdev->device == 0x67ef) && | ||
| 1664 | ((adev->pdev->revision == 0xe0) || | ||
| 1665 | (adev->pdev->revision == 0xe5))) || | ||
| 1666 | ((adev->pdev->device == 0x67ff) && | ||
| 1667 | ((adev->pdev->revision == 0xcf) || | ||
| 1668 | (adev->pdev->revision == 0xef) || | ||
| 1669 | (adev->pdev->revision == 0xff)))) { | ||
| 1670 | avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage = 1; | ||
| 1671 | if ((adev->pdev->device == 0x67ef && adev->pdev->revision == 0xe5) || | ||
| 1672 | (adev->pdev->device == 0x67ff && adev->pdev->revision == 0xef)) { | ||
| 1673 | if ((avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0 == 0xEA522DD3) && | ||
| 1674 | (avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1 == 0x5645A) && | ||
| 1675 | (avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2 == 0x33F9E) && | ||
| 1676 | (avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1 == 0xFFFFC5CC) && | ||
| 1677 | (avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2 == 0x1B1A) && | ||
| 1678 | (avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b == 0xFFFFFCED)) { | ||
| 1679 | avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0 = 0xF718F1D4; | ||
| 1680 | avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1 = 0x323FD; | ||
| 1681 | avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2 = 0x1E455; | ||
| 1682 | avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = 0; | ||
| 1683 | avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2 = 0; | ||
| 1684 | avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b = 0x23; | ||
| 1685 | } | ||
| 1686 | } | ||
| 1687 | } else if (hwmgr->chip_id == CHIP_POLARIS12 && !hwmgr->is_kicker) { | ||
| 1688 | avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage = 1; | ||
| 1689 | avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0 = 0xF6B024DD; | ||
| 1690 | avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1 = 0x3005E; | ||
| 1691 | avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2 = 0x18A5F; | ||
| 1692 | avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = 0x315; | ||
| 1693 | avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2 = 0xFED1; | ||
| 1694 | avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b = 0x3B; | ||
| 1695 | } else if (((adev->pdev->device == 0x67df) && | ||
| 1696 | ((adev->pdev->revision == 0xe0) || | ||
| 1697 | (adev->pdev->revision == 0xe3) || | ||
| 1698 | (adev->pdev->revision == 0xe4) || | ||
| 1699 | (adev->pdev->revision == 0xe5) || | ||
| 1700 | (adev->pdev->revision == 0xe7) || | ||
| 1701 | (adev->pdev->revision == 0xef))) || | ||
| 1702 | ((adev->pdev->device == 0x6fdf) && | ||
| 1703 | ((adev->pdev->revision == 0xef) || | ||
| 1704 | (adev->pdev->revision == 0xff)))) { | ||
| 1705 | avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage = 1; | ||
| 1706 | avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0 = 0xF843B66B; | ||
| 1707 | avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1 = 0x59CB5; | ||
| 1708 | avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2 = 0xFFFF287F; | ||
| 1709 | avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = 0; | ||
| 1710 | avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2 = 0xFF23; | ||
| 1711 | avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b = 0x58; | ||
| 1712 | } | ||
| 1713 | } | ||
| 1714 | |||
| 1648 | if (0 == result) { | 1715 | if (0 == result) { |
| 1649 | table->BTCGB_VDROOP_TABLE[0].a0 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a0); | 1716 | table->BTCGB_VDROOP_TABLE[0].a0 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a0); |
| 1650 | table->BTCGB_VDROOP_TABLE[0].a1 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a1); | 1717 | table->BTCGB_VDROOP_TABLE[0].a1 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a1); |
| @@ -118,6 +118,7 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu) · 117 unmodified lines | |||
| 118 | unsigned int n_obj, n_bomap_pages; | 118 | unsigned int n_obj, n_bomap_pages; |
| 119 | size_t file_size, mmu_size; | 119 | size_t file_size, mmu_size; |
| 120 | __le64 *bomap, *bomap_start; | 120 | __le64 *bomap, *bomap_start; |
| 121 | unsigned long flags; | ||
| 121 | 122 | ||
| 122 | /* Only catch the first event, or when manually re-armed */ | 123 | /* Only catch the first event, or when manually re-armed */ |
| 123 | if (!etnaviv_dump_core) | 124 | if (!etnaviv_dump_core) |
| @@ -134,13 +135,13 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu) · 10 unmodified lines | |||
| 134 | mmu_size + gpu->buffer.size; | 135 | mmu_size + gpu->buffer.size; |
| 135 | 136 | ||
| 136 | /* Add in the active command buffers */ | 137 | /* Add in the active command buffers */ |
| 137 | spin_lock(&gpu->sched.job_list_lock); | 138 | spin_lock_irqsave(&gpu->sched.job_list_lock, flags); |
| 138 | list_for_each_entry(s_job, &gpu->sched.ring_mirror_list, node) { | 139 | list_for_each_entry(s_job, &gpu->sched.ring_mirror_list, node) { |
| 139 | submit = to_etnaviv_submit(s_job); | 140 | submit = to_etnaviv_submit(s_job); |
| 140 | file_size += submit->cmdbuf.size; | 141 | file_size += submit->cmdbuf.size; |
| 141 | n_obj++; | 142 | n_obj++; |
| 142 | } | 143 | } |
| 143 | spin_unlock(&gpu->sched.job_list_lock); | 144 | spin_unlock_irqrestore(&gpu->sched.job_list_lock, flags); |
| 144 | 145 | ||
| 145 | /* Add in the active buffer objects */ | 146 | /* Add in the active buffer objects */ |
| 146 | list_for_each_entry(vram, &gpu->mmu->mappings, mmu_node) { | 147 | list_for_each_entry(vram, &gpu->mmu->mappings, mmu_node) { |
| @@ -182,14 +183,14 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu) · 35 unmodified lines | |||
| 182 | gpu->buffer.size, | 183 | gpu->buffer.size, |
| 183 | etnaviv_cmdbuf_get_va(&gpu->buffer)); | 184 | etnaviv_cmdbuf_get_va(&gpu->buffer)); |
| 184 | 185 | ||
| 185 | spin_lock(&gpu->sched.job_list_lock); | 186 | spin_lock_irqsave(&gpu->sched.job_list_lock, flags); |
| 186 | list_for_each_entry(s_job, &gpu->sched.ring_mirror_list, node) { | 187 | list_for_each_entry(s_job, &gpu->sched.ring_mirror_list, node) { |
| 187 | submit = to_etnaviv_submit(s_job); | 188 | submit = to_etnaviv_submit(s_job); |
| 188 | etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD, | 189 | etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD, |
| 189 | submit->cmdbuf.vaddr, submit->cmdbuf.size, | 190 | submit->cmdbuf.vaddr, submit->cmdbuf.size, |
| 190 | etnaviv_cmdbuf_get_va(&submit->cmdbuf)); | 191 | etnaviv_cmdbuf_get_va(&submit->cmdbuf)); |
| 191 | } | 192 | } |
| 192 | spin_unlock(&gpu->sched.job_list_lock); | 193 | spin_unlock_irqrestore(&gpu->sched.job_list_lock, flags); |
| 193 | 194 | ||
| 194 | /* Reserve space for the bomap */ | 195 | /* Reserve space for the bomap */ |
| 195 | if (n_bomap_pages) { | 196 | if (n_bomap_pages) { |
| @@ -217,7 +217,7 @@ int qxl_release_list_add(struct qxl_release *release, struct qxl_bo *bo) · 216 unmodified lines | |||
| 217 | 217 | ||
| 218 | qxl_bo_ref(bo); | 218 | qxl_bo_ref(bo); |
| 219 | entry->tv.bo = &bo->tbo; | 219 | entry->tv.bo = &bo->tbo; |
| 220 | entry->tv.shared = false; | 220 | entry->tv.num_shared = 0; |
| 221 | list_add_tail(&entry->tv.head, &release->bos); | 221 | list_add_tail(&entry->tv.head, &release->bos); |
| 222 | return 0; | 222 | return 0; |
| 223 | } | 223 | } |
| @@ -178,7 +178,7 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) · 177 unmodified lines | |||
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | p->relocs[i].tv.bo = &p->relocs[i].robj->tbo; | 180 | p->relocs[i].tv.bo = &p->relocs[i].robj->tbo; |
| 181 | p->relocs[i].tv.shared = !r->write_domain; | 181 | p->relocs[i].tv.num_shared = !r->write_domain; |
| 182 | 182 | ||
| 183 | radeon_cs_buckets_add(&buckets, &p->relocs[i].tv.head, | 183 | radeon_cs_buckets_add(&buckets, &p->relocs[i].tv.head, |
| 184 | priority); | 184 | priority); |
| @@ -253,7 +253,7 @@ static int radeon_cs_sync_rings(struct radeon_cs_parser *p) · 68 unmodified lines | |||
| 253 | 253 | ||
| 254 | resv = reloc->robj->tbo.resv; | 254 | resv = reloc->robj->tbo.resv; |
| 255 | r = radeon_sync_resv(p->rdev, &p->ib.sync, resv, | 255 | r = radeon_sync_resv(p->rdev, &p->ib.sync, resv, |
| 256 | reloc->tv.shared); | 256 | reloc->tv.num_shared); |
| 257 | if (r) | 257 | if (r) |
| 258 | return r; | 258 | return r; |
| 259 | } | 259 | } |
| @@ -552,7 +552,7 @@ static void radeon_gem_va_update_vm(struct radeon_device *rdev, · 551 unmodified lines | |||
| 552 | INIT_LIST_HEAD(&list); | 552 | INIT_LIST_HEAD(&list); |
| 553 | 553 | ||
| 554 | tv.bo = &bo_va->bo->tbo; | 554 | tv.bo = &bo_va->bo->tbo; |
| 555 | tv.shared = true; | 555 | tv.num_shared = 1; |
| 556 | list_add(&tv.head, &list); | 556 | list_add(&tv.head, &list); |
| 557 | 557 | ||
| 558 | vm_bos = radeon_vm_get_bos(rdev, bo_va->vm, &list); | 558 | vm_bos = radeon_vm_get_bos(rdev, bo_va->vm, &list); |
| @@ -142,7 +142,7 @@ struct radeon_bo_list *radeon_vm_get_bos(struct radeon_device *rdev, · 141 unmodified lines | |||
| 142 | list[0].preferred_domains = RADEON_GEM_DOMAIN_VRAM; | 142 | list[0].preferred_domains = RADEON_GEM_DOMAIN_VRAM; |
| 143 | list[0].allowed_domains = RADEON_GEM_DOMAIN_VRAM; | 143 | list[0].allowed_domains = RADEON_GEM_DOMAIN_VRAM; |
| 144 | list[0].tv.bo = &vm->page_directory->tbo; | 144 | list[0].tv.bo = &vm->page_directory->tbo; |
| 145 | list[0].tv.shared = true; | 145 | list[0].tv.num_shared = 1; |
| 146 | list[0].tiling_flags = 0; | 146 | list[0].tiling_flags = 0; |
| 147 | list_add(&list[0].tv.head, head); | 147 | list_add(&list[0].tv.head, head); |
| 148 | 148 | ||
| @@ -154,7 +154,7 @@ struct radeon_bo_list *radeon_vm_get_bos(struct radeon_device *rdev, · 5 unmodified lines | |||
| 154 | list[idx].preferred_domains = RADEON_GEM_DOMAIN_VRAM; | 154 | list[idx].preferred_domains = RADEON_GEM_DOMAIN_VRAM; |
| 155 | list[idx].allowed_domains = RADEON_GEM_DOMAIN_VRAM; | 155 | list[idx].allowed_domains = RADEON_GEM_DOMAIN_VRAM; |
| 156 | list[idx].tv.bo = &list[idx].robj->tbo; | 156 | list[idx].tv.bo = &list[idx].robj->tbo; |
| 157 | list[idx].tv.shared = true; | 157 | list[idx].tv.num_shared = 1; |
| 158 | list[idx].tiling_flags = 0; | 158 | list[idx].tiling_flags = 0; |
| 159 | list_add(&list[idx++].tv.head, head); | 159 | list_add(&list[idx++].tv.head, head); |
| 160 | } | 160 | } |
| @@ -211,6 +211,62 @@ void drm_sched_fault(struct drm_gpu_scheduler *sched) · 210 unmodified lines | |||
| 211 | } | 211 | } |
| 212 | EXPORT_SYMBOL(drm_sched_fault); | 212 | EXPORT_SYMBOL(drm_sched_fault); |
| 213 | 213 | ||
| 214 | /** | ||
| 215 | * drm_sched_suspend_timeout - Suspend scheduler job timeout | ||
| 216 | * | ||
| 217 | * @sched: scheduler instance for which to suspend the timeout | ||
| 218 | * | ||
| 219 | * Suspend the delayed work timeout for the scheduler. This is done by | ||
| 220 | * modifying the delayed work timeout to an arbitrary large value, | ||
| 221 | * MAX_SCHEDULE_TIMEOUT in this case. Note that this function can be | ||
| 222 | * called from an IRQ context. | ||
| 223 | * | ||
| 224 | * Returns the timeout remaining | ||
| 225 | * | ||
| 226 | */ | ||
| 227 | unsigned long drm_sched_suspend_timeout(struct drm_gpu_scheduler *sched) | ||
| 228 | { | ||
| 229 | unsigned long sched_timeout, now = jiffies; | ||
| 230 | |||
| 231 | sched_timeout = sched->work_tdr.timer.expires; | ||
| 232 | |||
| 233 | /* | ||
| 234 | * Modify the timeout to an arbitrarily large value. This also prevents | ||
| 235 | * the timeout to be restarted when new submissions arrive | ||
| 236 | */ | ||
| 237 | if (mod_delayed_work(system_wq, &sched->work_tdr, MAX_SCHEDULE_TIMEOUT) | ||
| 238 | && time_after(sched_timeout, now)) | ||
| 239 | return sched_timeout - now; | ||
| 240 | else | ||
| 241 | return sched->timeout; | ||
| 242 | } | ||
| 243 | EXPORT_SYMBOL(drm_sched_suspend_timeout); | ||
| 244 | |||
| 245 | /** | ||
| 246 | * drm_sched_resume_timeout - Resume scheduler job timeout | ||
| 247 | * | ||
| 248 | * @sched: scheduler instance for which to resume the timeout | ||
| 249 | * @remaining: remaining timeout | ||
| 250 | * | ||
| 251 | * Resume the delayed work timeout for the scheduler. Note that | ||
| 252 | * this function can be called from an IRQ context. | ||
| 253 | */ | ||
| 254 | void drm_sched_resume_timeout(struct drm_gpu_scheduler *sched, | ||
| 255 | unsigned long remaining) | ||
| 256 | { | ||
| 257 | unsigned long flags; | ||
| 258 | |||
| 259 | spin_lock_irqsave(&sched->job_list_lock, flags); | ||
| 260 | |||
| 261 | if (list_empty(&sched->ring_mirror_list)) | ||
| 262 | cancel_delayed_work(&sched->work_tdr); | ||
| 263 | else | ||
| 264 | mod_delayed_work(system_wq, &sched->work_tdr, remaining); | ||
| 265 | |||
| 266 | spin_unlock_irqrestore(&sched->job_list_lock, flags); | ||
| 267 | } | ||
| 268 | EXPORT_SYMBOL(drm_sched_resume_timeout); | ||
| 269 | |||
| 214 | /* job_finish is called after hw fence signaled | 270 | /* job_finish is called after hw fence signaled |
| 215 | */ | 271 | */ |
| 216 | static void drm_sched_job_finish(struct work_struct *work) | 272 | static void drm_sched_job_finish(struct work_struct *work) |
| @@ -218,6 +274,7 @@ static void drm_sched_job_finish(struct work_struct *work) · 1 unmodified line | |||
| 218 | struct drm_sched_job *s_job = container_of(work, struct drm_sched_job, | 274 | struct drm_sched_job *s_job = container_of(work, struct drm_sched_job, |
| 219 | finish_work); | 275 | finish_work); |
| 220 | struct drm_gpu_scheduler *sched = s_job->sched; | 276 | struct drm_gpu_scheduler *sched = s_job->sched; |
| 277 | unsigned long flags; | ||
| 221 | 278 | ||
| 222 | /* | 279 | /* |
| 223 | * Canceling the timeout without removing our job from the ring mirror | 280 | * Canceling the timeout without removing our job from the ring mirror |
| @@ -228,12 +285,12 @@ static void drm_sched_job_finish(struct work_struct *work) · 4 unmodified lines | |||
| 228 | */ | 285 | */ |
| 229 | cancel_delayed_work_sync(&sched->work_tdr); | 286 | cancel_delayed_work_sync(&sched->work_tdr); |
| 230 | 287 | ||
| 231 | spin_lock(&sched->job_list_lock); | 288 | spin_lock_irqsave(&sched->job_list_lock, flags); |
| 232 | /* remove job from ring_mirror_list */ | 289 | /* remove job from ring_mirror_list */ |
| 233 | list_del_init(&s_job->node); | 290 | list_del_init(&s_job->node); |
| 234 | /* queue TDR for next job */ | 291 | /* queue TDR for next job */ |
| 235 | drm_sched_start_timeout(sched); | 292 | drm_sched_start_timeout(sched); |
| 236 | spin_unlock(&sched->job_list_lock); | 293 | spin_unlock_irqrestore(&sched->job_list_lock, flags); |
| 237 | 294 | ||
| 238 | sched->ops->free_job(s_job); | 295 | sched->ops->free_job(s_job); |
| 239 | } | 296 | } |
| @@ -249,20 +306,22 @@ static void drm_sched_job_finish_cb(struct dma_fence *f, · 9 unmodified lines | |||
| 249 | static void drm_sched_job_begin(struct drm_sched_job *s_job) | 306 | static void drm_sched_job_begin(struct drm_sched_job *s_job) |
| 250 | { | 307 | { |
| 251 | struct drm_gpu_scheduler *sched = s_job->sched; | 308 | struct drm_gpu_scheduler *sched = s_job->sched; |
| 309 | unsigned long flags; | ||
| 252 | 310 | ||
| 253 | dma_fence_add_callback(&s_job->s_fence->finished, &s_job->finish_cb, | 311 | dma_fence_add_callback(&s_job->s_fence->finished, &s_job->finish_cb, |
| 254 | drm_sched_job_finish_cb); | 312 | drm_sched_job_finish_cb); |
| 255 | 313 | ||
| 256 | spin_lock(&sched->job_list_lock); | 314 | spin_lock_irqsave(&sched->job_list_lock, flags); |
| 257 | list_add_tail(&s_job->node, &sched->ring_mirror_list); | 315 | list_add_tail(&s_job->node, &sched->ring_mirror_list); |
| 258 | drm_sched_start_timeout(sched); | 316 | drm_sched_start_timeout(sched); |
| 259 | spin_unlock(&sched->job_list_lock); | 317 | spin_unlock_irqrestore(&sched->job_list_lock, flags); |
| 260 | } | 318 | } |
| 261 | 319 | ||
| 262 | static void drm_sched_job_timedout(struct work_struct *work) | 320 | static void drm_sched_job_timedout(struct work_struct *work) |
| 263 | { | 321 | { |
| 264 | struct drm_gpu_scheduler *sched; | 322 | struct drm_gpu_scheduler *sched; |
| 265 | struct drm_sched_job *job; | 323 | struct drm_sched_job *job; |
| 324 | unsigned long flags; | ||
| 266 | 325 | ||
| 267 | sched = container_of(work, struct drm_gpu_scheduler, work_tdr.work); | 326 | sched = container_of(work, struct drm_gpu_scheduler, work_tdr.work); |
| 268 | job = list_first_entry_or_null(&sched->ring_mirror_list, | 327 | job = list_first_entry_or_null(&sched->ring_mirror_list, |
| @@ -271,9 +330,9 @@ static void drm_sched_job_timedout(struct work_struct *work) · 2 unmodified lines | |||
| 271 | if (job) | 330 | if (job) |
| 272 | job->sched->ops->timedout_job(job); | 331 | job->sched->ops->timedout_job(job); |
| 273 | 332 | ||
| 274 | spin_lock(&sched->job_list_lock); | 333 | spin_lock_irqsave(&sched->job_list_lock, flags); |
| 275 | drm_sched_start_timeout(sched); | 334 | drm_sched_start_timeout(sched); |
| 276 | spin_unlock(&sched->job_list_lock); | 335 | spin_unlock_irqrestore(&sched->job_list_lock, flags); |
| 277 | } | 336 | } |
| 278 | 337 | ||
| 279 | /** | 338 | /** |
| @@ -287,9 +346,10 @@ void drm_sched_hw_job_reset(struct drm_gpu_scheduler *sched, struct drm_sched_jo · 7 unmodified lines | |||
| 287 | { | 346 | { |
| 288 | struct drm_sched_job *s_job; | 347 | struct drm_sched_job *s_job; |
| 289 | struct drm_sched_entity *entity, *tmp; | 348 | struct drm_sched_entity *entity, *tmp; |
| 349 | unsigned long flags; | ||
| 290 | int i; | 350 | int i; |
| 291 | 351 | ||
| 292 | spin_lock(&sched->job_list_lock); | 352 | spin_lock_irqsave(&sched->job_list_lock, flags); |
| 293 | list_for_each_entry_reverse(s_job, &sched->ring_mirror_list, node) { | 353 | list_for_each_entry_reverse(s_job, &sched->ring_mirror_list, node) { |
| 294 | if (s_job->s_fence->parent && | 354 | if (s_job->s_fence->parent && |
| 295 | dma_fence_remove_callback(s_job->s_fence->parent, | 355 | dma_fence_remove_callback(s_job->s_fence->parent, |
| @@ -299,7 +359,7 @@ void drm_sched_hw_job_reset(struct drm_gpu_scheduler *sched, struct drm_sched_jo · 3 unmodified lines | |||
| 299 | atomic_dec(&sched->hw_rq_count); | 359 | atomic_dec(&sched->hw_rq_count); |
| 300 | } | 360 | } |
| 301 | } | 361 | } |
| 302 | spin_unlock(&sched->job_list_lock); | 362 | spin_unlock_irqrestore(&sched->job_list_lock, flags); |
| 303 | 363 | ||
| 304 | if (bad && bad->s_priority != DRM_SCHED_PRIORITY_KERNEL) { | 364 | if (bad && bad->s_priority != DRM_SCHED_PRIORITY_KERNEL) { |
| 305 | atomic_inc(&bad->karma); | 365 | atomic_inc(&bad->karma); |
| @@ -337,9 +397,10 @@ void drm_sched_job_recovery(struct drm_gpu_scheduler *sched) · 31 unmodified lines | |||
| 337 | { | 397 | { |
| 338 | struct drm_sched_job *s_job, *tmp; | 398 | struct drm_sched_job *s_job, *tmp; |
| 339 | bool found_guilty = false; | 399 | bool found_guilty = false; |
| 400 | unsigned long flags; | ||
| 340 | int r; | 401 | int r; |
| 341 | 402 | ||
| 342 | spin_lock(&sched->job_list_lock); | 403 | spin_lock_irqsave(&sched->job_list_lock, flags); |
| 343 | list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) { | 404 | list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) { |
| 344 | struct drm_sched_fence *s_fence = s_job->s_fence; | 405 | struct drm_sched_fence *s_fence = s_job->s_fence; |
| 345 | struct dma_fence *fence; | 406 | struct dma_fence *fence; |
| @@ -353,7 +414,7 @@ void drm_sched_job_recovery(struct drm_gpu_scheduler *sched) · 7 unmodified lines | |||
| 353 | if (found_guilty && s_job->s_fence->scheduled.context == guilty_context) | 414 | if (found_guilty && s_job->s_fence->scheduled.context == guilty_context) |
| 354 | dma_fence_set_error(&s_fence->finished, -ECANCELED); | 415 | dma_fence_set_error(&s_fence->finished, -ECANCELED); |
| 355 | 416 | ||
| 356 | spin_unlock(&sched->job_list_lock); | 417 | spin_unlock_irqrestore(&sched->job_list_lock, flags); |
| 357 | fence = sched->ops->run_job(s_job); | 418 | fence = sched->ops->run_job(s_job); |
| 358 | atomic_inc(&sched->hw_rq_count); | 419 | atomic_inc(&sched->hw_rq_count); |
| 359 | 420 | ||
| @@ -372,10 +433,10 @@ void drm_sched_job_recovery(struct drm_gpu_scheduler *sched) · 12 unmodified lines | |||
| 372 | drm_sched_expel_job_unlocked(s_job); | 433 | drm_sched_expel_job_unlocked(s_job); |
| 373 | drm_sched_process_job(NULL, &s_fence->cb); | 434 | drm_sched_process_job(NULL, &s_fence->cb); |
| 374 | } | 435 | } |
| 375 | spin_lock(&sched->job_list_lock); | 436 | spin_lock_irqsave(&sched->job_list_lock, flags); |
| 376 | } | 437 | } |
| 377 | drm_sched_start_timeout(sched); | 438 | drm_sched_start_timeout(sched); |
| 378 | spin_unlock(&sched->job_list_lock); | 439 | spin_unlock_irqrestore(&sched->job_list_lock, flags); |
| 379 | } | 440 | } |
| 380 | EXPORT_SYMBOL(drm_sched_job_recovery); | 441 | EXPORT_SYMBOL(drm_sched_job_recovery); |
| 381 | 442 | ||
| @@ -612,7 +673,7 @@ int drm_sched_init(struct drm_gpu_scheduler *sched, · 230 unmodified lines | |||
| 612 | long timeout, | 673 | long timeout, |
| 613 | const char *name) | 674 | const char *name) |
| 614 | { | 675 | { |
| 615 | int i; | 676 | int i, ret; |
| 616 | sched->ops = ops; | 677 | sched->ops = ops; |
| 617 | sched->hw_submission_limit = hw_submission; | 678 | sched->hw_submission_limit = hw_submission; |
| 618 | sched->name = name; | 679 | sched->name = name; |
| @@ -633,8 +694,10 @@ int drm_sched_init(struct drm_gpu_scheduler *sched, · 14 unmodified lines | |||
| 633 | /* Each scheduler will run on a seperate kernel thread */ | 694 | /* Each scheduler will run on a seperate kernel thread */ |
| 634 | sched->thread = kthread_run(drm_sched_main, sched, sched->name); | 695 | sched->thread = kthread_run(drm_sched_main, sched, sched->name); |
| 635 | if (IS_ERR(sched->thread)) { | 696 | if (IS_ERR(sched->thread)) { |
| 697 | ret = PTR_ERR(sched->thread); | ||
| 698 | sched->thread = NULL; | ||
| 636 | DRM_ERROR("Failed to create scheduler for %s.\n", name); | 699 | DRM_ERROR("Failed to create scheduler for %s.\n", name); |
| 637 | return PTR_ERR(sched->thread); | 700 | return ret; |
| 638 | } | 701 | } |
| 639 | 702 | ||
| 640 | sched->ready = true; | 703 | sched->ready = true; |
| @@ -126,10 +126,11 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, · 125 unmodified lines | |||
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | if (!ret) { | 128 | if (!ret) { |
| 129 | if (!entry->shared) | 129 | if (!entry->num_shared) |
| 130 | continue; | 130 | continue; |
| 131 | 131 | ||
| 132 | ret = reservation_object_reserve_shared(bo->resv, 1); | 132 | ret = reservation_object_reserve_shared(bo->resv, |
| 133 | entry->num_shared); | ||
| 133 | if (!ret) | 134 | if (!ret) |
| 134 | continue; | 135 | continue; |
| 135 | } | 136 | } |
| @@ -150,8 +151,9 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, · 14 unmodified lines | |||
| 150 | } | 151 | } |
| 151 | } | 152 | } |
| 152 | 153 | ||
| 153 | if (!ret && entry->shared) | 154 | if (!ret && entry->num_shared) |
| 154 | ret = reservation_object_reserve_shared(bo->resv, 1); | 155 | ret = reservation_object_reserve_shared(bo->resv, |
| 156 | entry->num_shared); | ||
| 155 | 157 | ||
| 156 | if (unlikely(ret != 0)) { | 158 | if (unlikely(ret != 0)) { |
| 157 | if (ret == -EINTR) | 159 | if (ret == -EINTR) |
| @@ -199,7 +201,7 @@ void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket, · 41 unmodified lines | |||
| 199 | 201 | ||
| 200 | list_for_each_entry(entry, list, head) { | 202 | list_for_each_entry(entry, list, head) { |
| 201 | bo = entry->bo; | 203 | bo = entry->bo; |
| 202 | if (entry->shared) | 204 | if (entry->num_shared) |
| 203 | reservation_object_add_shared_fence(bo->resv, fence); | 205 | reservation_object_add_shared_fence(bo->resv, fence); |
| 204 | else | 206 | else |
| 205 | reservation_object_add_excl_fence(bo->resv, fence); | 207 | reservation_object_add_excl_fence(bo->resv, fence); |
| @@ -85,7 +85,7 @@ static void vmw_resource_release(struct kref *kref) · 84 unmodified lines | |||
| 85 | struct ttm_validate_buffer val_buf; | 85 | struct ttm_validate_buffer val_buf; |
| 86 | 86 | ||
| 87 | val_buf.bo = bo; | 87 | val_buf.bo = bo; |
| 88 | val_buf.shared = false; | 88 | val_buf.num_shared = 0; |
| 89 | res->func->unbind(res, false, &val_buf); | 89 | res->func->unbind(res, false, &val_buf); |
| 90 | } | 90 | } |
| 91 | res->backup_dirty = false; | 91 | res->backup_dirty = false; |
| @@ -462,7 +462,7 @@ vmw_resource_check_buffer(struct ww_acquire_ctx *ticket, · 370 unmodified lines | |||
| 462 | 462 | ||
| 463 | INIT_LIST_HEAD(&val_list); | 463 | INIT_LIST_HEAD(&val_list); |
| 464 | val_buf->bo = ttm_bo_reference(&res->backup->base); | 464 | val_buf->bo = ttm_bo_reference(&res->backup->base); |
| 465 | val_buf->shared = false; | 465 | val_buf->num_shared = 0; |
| 466 | list_add_tail(&val_buf->head, &val_list); | 466 | list_add_tail(&val_buf->head, &val_list); |
| 467 | ret = ttm_eu_reserve_buffers(ticket, &val_list, interruptible, NULL); | 467 | ret = ttm_eu_reserve_buffers(ticket, &val_list, interruptible, NULL); |
| 468 | if (unlikely(ret != 0)) | 468 | if (unlikely(ret != 0)) |
| @@ -565,7 +565,7 @@ static int vmw_resource_do_evict(struct ww_acquire_ctx *ticket, · 96 unmodified lines | |||
| 565 | BUG_ON(!func->may_evict); | 565 | BUG_ON(!func->may_evict); |
| 566 | 566 | ||
| 567 | val_buf.bo = NULL; | 567 | val_buf.bo = NULL; |
| 568 | val_buf.shared = false; | 568 | val_buf.num_shared = 0; |
| 569 | ret = vmw_resource_check_buffer(ticket, res, interruptible, &val_buf); | 569 | ret = vmw_resource_check_buffer(ticket, res, interruptible, &val_buf); |
| 570 | if (unlikely(ret != 0)) | 570 | if (unlikely(ret != 0)) |
| 571 | return ret; | 571 | return ret; |
| @@ -614,7 +614,7 @@ int vmw_resource_validate(struct vmw_resource *res, bool intr) · 42 unmodified lines | |||
| 614 | return 0; | 614 | return 0; |
| 615 | 615 | ||
| 616 | val_buf.bo = NULL; | 616 | val_buf.bo = NULL; |
| 617 | val_buf.shared = false; | 617 | val_buf.num_shared = 0; |
| 618 | if (res->backup) | 618 | if (res->backup) |
| 619 | val_buf.bo = &res->backup->base; | 619 | val_buf.bo = &res->backup->base; |
| 620 | do { | 620 | do { |
| @@ -685,7 +685,7 @@ void vmw_resource_unbind_list(struct vmw_buffer_object *vbo) · 64 unmodified lines | |||
| 685 | struct vmw_resource *res, *next; | 685 | struct vmw_resource *res, *next; |
| 686 | struct ttm_validate_buffer val_buf = { | 686 | struct ttm_validate_buffer val_buf = { |
| 687 | .bo = &vbo->base, | 687 | .bo = &vbo->base, |
| 688 | .shared = false | 688 | .num_shared = 0 |
| 689 | }; | 689 | }; |
| 690 | 690 | ||
| 691 | lockdep_assert_held(&vbo->base.resv->lock.base); | 691 | lockdep_assert_held(&vbo->base.resv->lock.base); |
| @@ -266,7 +266,7 @@ int vmw_validation_add_bo(struct vmw_validation_context *ctx, · 265 unmodified lines | |||
| 266 | val_buf->bo = ttm_bo_get_unless_zero(&vbo->base); | 266 | val_buf->bo = ttm_bo_get_unless_zero(&vbo->base); |
| 267 | if (!val_buf->bo) | 267 | if (!val_buf->bo) |
| 268 | return -ESRCH; | 268 | return -ESRCH; |
| 269 | val_buf->shared = false; | 269 | val_buf->num_shared = 0; |
| 270 | list_add_tail(&val_buf->head, &ctx->bo_list); | 270 | list_add_tail(&val_buf->head, &ctx->bo_list); |
| 271 | bo_node->as_mob = as_mob; | 271 | bo_node->as_mob = as_mob; |
| 272 | bo_node->cpu_blit = cpu_blit; | 272 | bo_node->cpu_blit = cpu_blit; |
| @@ -331,4 +331,8 @@ struct drm_sched_fence *drm_sched_fence_create( · 330 unmodified lines | |||
| 331 | void drm_sched_fence_scheduled(struct drm_sched_fence *fence); | 331 | void drm_sched_fence_scheduled(struct drm_sched_fence *fence); |
| 332 | void drm_sched_fence_finished(struct drm_sched_fence *fence); | 332 | void drm_sched_fence_finished(struct drm_sched_fence *fence); |
| 333 | 333 | ||
| 334 | unsigned long drm_sched_suspend_timeout(struct drm_gpu_scheduler *sched); | ||
| 335 | void drm_sched_resume_timeout(struct drm_gpu_scheduler *sched, | ||
| 336 | unsigned long remaining); | ||
| 337 | |||
| 334 | #endif | 338 | #endif |
| @@ -40,13 +40,13 @@ · 39 unmodified lines | |||
| 40 | * | 40 | * |
| 41 | * @head: list head for thread-private list. | 41 | * @head: list head for thread-private list. |
| 42 | * @bo: refcounted buffer object pointer. | 42 | * @bo: refcounted buffer object pointer. |
| 43 | * @shared: should the fence be added shared? | 43 | * @num_shared: How many shared fences we want to add. |
| 44 | */ | 44 | */ |
| 45 | 45 | ||
| 46 | struct ttm_validate_buffer { | 46 | struct ttm_validate_buffer { |
| 47 | struct list_head head; | 47 | struct list_head head; |
| 48 | struct ttm_buffer_object *bo; | 48 | struct ttm_buffer_object *bo; |
| 49 | bool shared; | 49 | unsigned int num_shared; |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | /** | 52 | /** |
| @@ -398,6 +398,24 @@ struct kfd_ioctl_unmap_memory_from_gpu_args { · 397 unmodified lines | |||
| 398 | __u32 n_success; /* to/from KFD */ | 398 | __u32 n_success; /* to/from KFD */ |
| 399 | }; | 399 | }; |
| 400 | 400 | ||
| 401 | struct kfd_ioctl_get_dmabuf_info_args { | ||
| 402 | __u64 size; /* from KFD */ | ||
| 403 | __u64 metadata_ptr; /* to KFD */ | ||
| 404 | __u32 metadata_size; /* to KFD (space allocated by user) | ||
| 405 | * from KFD (actual metadata size) | ||
| 406 | */ | ||
| 407 | __u32 gpu_id; /* from KFD */ | ||
| 408 | __u32 flags; /* from KFD (KFD_IOC_ALLOC_MEM_FLAGS) */ | ||
| 409 | __u32 dmabuf_fd; /* to KFD */ | ||
| 410 | }; | ||
| 411 | |||
| 412 | struct kfd_ioctl_import_dmabuf_args { | ||
| 413 | __u64 va_addr; /* to KFD */ | ||
| 414 | __u64 handle; /* from KFD */ | ||
| 415 | __u32 gpu_id; /* to KFD */ | ||
| 416 | __u32 dmabuf_fd; /* to KFD */ | ||
| 417 | }; | ||
| 418 | |||
| 401 | #define AMDKFD_IOCTL_BASE 'K' | 419 | #define AMDKFD_IOCTL_BASE 'K' |
| 402 | #define AMDKFD_IO(nr) _IO(AMDKFD_IOCTL_BASE, nr) | 420 | #define AMDKFD_IO(nr) _IO(AMDKFD_IOCTL_BASE, nr) |
| 403 | #define AMDKFD_IOR(nr, type) _IOR(AMDKFD_IOCTL_BASE, nr, type) | 421 | #define AMDKFD_IOR(nr, type) _IOR(AMDKFD_IOCTL_BASE, nr, type) |
| @@ -486,7 +504,13 @@ struct kfd_ioctl_unmap_memory_from_gpu_args { · 82 unmodified lines | |||
| 486 | #define AMDKFD_IOC_GET_QUEUE_WAVE_STATE \ | 504 | #define AMDKFD_IOC_GET_QUEUE_WAVE_STATE \ |
| 487 | AMDKFD_IOWR(0x1B, struct kfd_ioctl_get_queue_wave_state_args) | 505 | AMDKFD_IOWR(0x1B, struct kfd_ioctl_get_queue_wave_state_args) |
| 488 | 506 | ||
| 507 | #define AMDKFD_IOC_GET_DMABUF_INFO \ | ||
| 508 | AMDKFD_IOWR(0x1C, struct kfd_ioctl_get_dmabuf_info_args) | ||
| 509 | |||
| 510 | #define AMDKFD_IOC_IMPORT_DMABUF \ | ||
| 511 | AMDKFD_IOWR(0x1D, struct kfd_ioctl_import_dmabuf_args) | ||
| 512 | |||
| 489 | #define AMDKFD_COMMAND_START 0x01 | 513 | #define AMDKFD_COMMAND_START 0x01 |
| 490 | #define AMDKFD_COMMAND_END 0x1C | 514 | #define AMDKFD_COMMAND_END 0x1E |
| 491 | 515 | ||
| 492 | #endif | 516 | #endif |