[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 | 82 | #include "amdgpu_bo_list.h" |
| 83 | 83 | #include "amdgpu_gem.h" |
| 84 | 84 | #include "amdgpu_doorbell.h" |
| 85 | +#include "amdgpu_amdkfd.h" | |
| 85 | 86 | |
| 86 | 87 | #define MAX_GPU_INSTANCE 16 |
| 87 | 88 | |
| @@ -163,6 +164,7 @@ extern int amdgpu_si_support; · 75 unmodified lines | ||
| 163 | 164 | extern int amdgpu_cik_support; |
| 164 | 165 | #endif |
| 165 | 166 | |
| 167 | +#define AMDGPU_VM_MAX_NUM_CTX 4096 | |
| 166 | 168 | #define AMDGPU_SG_THRESHOLD (256*1024*1024) |
| 167 | 169 | #define AMDGPU_DEFAULT_GTT_SIZE_MB 3072ULL /* 3GB by default */ |
| 168 | 170 | #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000 |
| @@ -862,6 +864,9 @@ struct amdgpu_device { · 693 unmodified lines | ||
| 862 | 864 | /* GDS */ |
| 863 | 865 | struct amdgpu_gds gds; |
| 864 | 866 | |
| 867 | + /* KFD */ | |
| 868 | + struct amdgpu_kfd_dev kfd; | |
| 869 | + | |
| 865 | 870 | /* display related functionality */ |
| 866 | 871 | struct amdgpu_display_manager dm; |
| 867 | 872 | |
| @@ -875,9 +880,6 @@ struct amdgpu_device { · 7 unmodified lines | ||
| 875 | 880 | atomic64_t visible_pin_size; |
| 876 | 881 | atomic64_t gart_pin_size; |
| 877 | 882 | |
| 878 | − /* amdkfd interface */ | |
| 879 | − struct kfd_dev *kfd; | |
| 880 | − | |
| 881 | 883 | /* soc15 register offset based on ip, instance and segment */ |
| 882 | 884 | uint32_t *reg_offset[MAX_HWIP][HWIP_MAX_INSTANCE]; |
| 883 | 885 | |
| @@ -910,7 +912,9 @@ struct amdgpu_device { · 26 unmodified lines | ||
| 910 | 912 | bool in_gpu_reset; |
| 911 | 913 | struct mutex lock_reset; |
| 912 | 914 | struct amdgpu_doorbell_index doorbell_index; |
| 915 | + | |
| 913 | 916 | int asic_reset_res; |
| 917 | + struct work_struct xgmi_reset_work; | |
| 914 | 918 | }; |
| 915 | 919 | |
| 916 | 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 | 886 | void amdgpu_acpi_fini(struct amdgpu_device *adev) |
| 887 | 887 | { |
| 888 | 888 | unregister_acpi_notifier(&adev->acpi_nb); |
| 889 | − if (adev->atif) | |
| 890 | − kfree(adev->atif); | |
| 889 | + kfree(adev->atif); | |
| 891 | 890 | } |
| @@ -26,15 +26,26 @@ · 25 unmodified lines | ||
| 26 | 26 | #include "amdgpu.h" |
| 27 | 27 | #include "amdgpu_gfx.h" |
| 28 | 28 | #include <linux/module.h> |
| 29 | +#include <linux/dma-buf.h> | |
| 29 | 30 | |
| 30 | 31 | const struct kgd2kfd_calls *kgd2kfd; |
| 31 | 32 | |
| 32 | 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 | 40 | int amdgpu_amdkfd_init(void) |
| 35 | 41 | { |
| 42 | + struct sysinfo si; | |
| 36 | 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 | 49 | #ifdef CONFIG_HSA_AMD |
| 39 | 50 | ret = kgd2kfd_init(KFD_INTERFACE_VERSION, &kgd2kfd); |
| 40 | 51 | if (ret) |
| @@ -87,8 +98,11 @@ void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev) · 46 unmodified lines | ||
| 87 | 98 | return; |
| 88 | 99 | } |
| 89 | 100 | |
| 90 | − adev->kfd = kgd2kfd->probe((struct kgd_dev *)adev, | |
| 91 | − adev->pdev, kfd2kgd); | |
| 101 | + adev->kfd.dev = kgd2kfd->probe((struct kgd_dev *)adev, | |
| 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 | 143 | int i, n; |
| 130 | 144 | int last_valid_bit; |
| 131 | − if (adev->kfd) { | |
| 145 | + | |
| 146 | + if (adev->kfd.dev) { | |
| 132 | 147 | struct kgd2kfd_shared_resources gpu_resources = { |
| 133 | 148 | .compute_vmid_bitmap = compute_vmid_bitmap, |
| 134 | 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 | 182 | &gpu_resources.doorbell_start_offset); |
| 168 | 183 | |
| 169 | 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 | 186 | return; |
| 172 | 187 | } |
| 173 | 188 | |
| @@ -196,37 +211,37 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev) · 22 unmodified lines | ||
| 196 | 211 | gpu_resources.reserved_doorbell_mask = 0x1e0; |
| 197 | 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 | 218 | void amdgpu_amdkfd_device_fini(struct amdgpu_device *adev) |
| 204 | 219 | { |
| 205 | − if (adev->kfd) { | |
| 206 | − kgd2kfd->device_exit(adev->kfd); | |
| 207 | − adev->kfd = NULL; | |
| 220 | + if (adev->kfd.dev) { | |
| 221 | + kgd2kfd->device_exit(adev->kfd.dev); | |
| 222 | + adev->kfd.dev = NULL; | |
| 208 | 223 | } |
| 209 | 224 | } |
| 210 | 225 | |
| 211 | 226 | void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev, |
| 212 | 227 | const void *ih_ring_entry) |
| 213 | 228 | { |
| 214 | − if (adev->kfd) | |
| 215 | − kgd2kfd->interrupt(adev->kfd, ih_ring_entry); | |
| 229 | + if (adev->kfd.dev) | |
| 230 | + kgd2kfd->interrupt(adev->kfd.dev, ih_ring_entry); | |
| 216 | 231 | } |
| 217 | 232 | |
| 218 | 233 | void amdgpu_amdkfd_suspend(struct amdgpu_device *adev) |
| 219 | 234 | { |
| 220 | − if (adev->kfd) | |
| 221 | − kgd2kfd->suspend(adev->kfd); | |
| 235 | + if (adev->kfd.dev) | |
| 236 | + kgd2kfd->suspend(adev->kfd.dev); | |
| 222 | 237 | } |
| 223 | 238 | |
| 224 | 239 | int amdgpu_amdkfd_resume(struct amdgpu_device *adev) |
| 225 | 240 | { |
| 226 | 241 | int r = 0; |
| 227 | 242 | |
| 228 | − if (adev->kfd) | |
| 229 | − r = kgd2kfd->resume(adev->kfd); | |
| 243 | + if (adev->kfd.dev) | |
| 244 | + r = kgd2kfd->resume(adev->kfd.dev); | |
| 230 | 245 | |
| 231 | 246 | return r; |
| 232 | 247 | } |
| @@ -235,8 +250,8 @@ int amdgpu_amdkfd_pre_reset(struct amdgpu_device *adev) · 2 unmodified lines | ||
| 235 | 250 | { |
| 236 | 251 | int r = 0; |
| 237 | 252 | |
| 238 | − if (adev->kfd) | |
| 239 | − r = kgd2kfd->pre_reset(adev->kfd); | |
| 253 | + if (adev->kfd.dev) | |
| 254 | + r = kgd2kfd->pre_reset(adev->kfd.dev); | |
| 240 | 255 | |
| 241 | 256 | return r; |
| 242 | 257 | } |
| @@ -245,8 +260,8 @@ int amdgpu_amdkfd_post_reset(struct amdgpu_device *adev) · 2 unmodified lines | ||
| 245 | 260 | { |
| 246 | 261 | int r = 0; |
| 247 | 262 | |
| 248 | − if (adev->kfd) | |
| 249 | − r = kgd2kfd->post_reset(adev->kfd); | |
| 263 | + if (adev->kfd.dev) | |
| 264 | + r = kgd2kfd->post_reset(adev->kfd.dev); | |
| 250 | 265 | |
| 251 | 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 | 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 | 493 | uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd) |
| 423 | 494 | { |
| 424 | 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 | 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 | 576 | if ((1 << vmid) & compute_vmid_bitmap) |
| 506 | 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 | 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 | 28 | #include <linux/types.h> |
| 29 | 29 | #include <linux/mm.h> |
| 30 | −#include <linux/mmu_context.h> | |
| 31 | 30 | #include <linux/workqueue.h> |
| 32 | 31 | #include <kgd_kfd_interface.h> |
| 33 | 32 | #include <drm/ttm/ttm_execbuf_util.h> |
| @@ -35,6 +34,7 @@ · 1 unmodified line | ||
| 35 | 34 | #include "amdgpu_vm.h" |
| 36 | 35 | |
| 37 | 36 | extern const struct kgd2kfd_calls *kgd2kfd; |
| 37 | +extern uint64_t amdgpu_amdkfd_total_mem_size; | |
| 38 | 38 | |
| 39 | 39 | struct amdgpu_device; |
| 40 | 40 | |
| @@ -77,6 +77,11 @@ struct amdgpu_amdkfd_fence { · 36 unmodified lines | ||
| 77 | 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 | 85 | struct amdgpu_amdkfd_fence *amdgpu_amdkfd_fence_create(u64 context, |
| 81 | 86 | struct mm_struct *mm); |
| 82 | 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 | 150 | uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct kgd_dev *kgd); |
| 146 | 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 | 157 | uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd); |
| 148 | 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 | 205 | int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd, |
| 196 | 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 | 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 | 217 | #endif /* AMDGPU_AMDKFD_H_INCLUDED */ |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | #include <linux/fdtable.h> |
| 24 | 24 | #include <linux/uaccess.h> |
| 25 | 25 | #include <linux/firmware.h> |
| 26 | +#include <linux/mmu_context.h> | |
| 26 | 27 | #include <drm/drmP.h> |
| 27 | 28 | #include "amdgpu.h" |
| 28 | 29 | #include "amdgpu_amdkfd.h" |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | #include <linux/fdtable.h> |
| 25 | 25 | #include <linux/uaccess.h> |
| 26 | 26 | #include <linux/firmware.h> |
| 27 | +#include <linux/mmu_context.h> | |
| 27 | 28 | #include <drm/drmP.h> |
| 28 | 29 | #include "amdgpu.h" |
| 29 | 30 | #include "amdgpu_amdkfd.h" |
| @@ -26,6 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <linux/fdtable.h> |
| 27 | 27 | #include <linux/uaccess.h> |
| 28 | 28 | #include <linux/firmware.h> |
| 29 | +#include <linux/mmu_context.h> | |
| 29 | 30 | #include <drm/drmP.h> |
| 30 | 31 | #include "amdgpu.h" |
| 31 | 32 | #include "amdgpu_amdkfd.h" |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <linux/list.h> |
| 26 | 26 | #include <linux/pagemap.h> |
| 27 | 27 | #include <linux/sched/mm.h> |
| 28 | +#include <linux/dma-buf.h> | |
| 28 | 29 | #include <drm/drmP.h> |
| 29 | 30 | #include "amdgpu_object.h" |
| 30 | 31 | #include "amdgpu_vm.h" |
| @@ -110,17 +111,17 @@ void amdgpu_amdkfd_gpuvm_init_mem_limits(void) · 79 unmodified lines | ||
| 110 | 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 | 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 | 119 | int ret = 0; |
| 118 | 120 | |
| 119 | 121 | acc_size = ttm_bo_dma_acc_size(&adev->mman.bdev, size, |
| 120 | 122 | sizeof(struct amdgpu_bo)); |
| 121 | 123 | |
| 122 | − spin_lock(&kfd_mem_limit.mem_limit_lock); | |
| 123 | − | |
| 124 | + vram_needed = 0; | |
| 124 | 125 | if (domain == AMDGPU_GEM_DOMAIN_GTT) { |
| 125 | 126 | /* TTM GTT memory */ |
| 126 | 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 | 134 | /* VRAM and SG */ |
| 134 | 135 | system_mem_needed = acc_size; |
| 135 | 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 | 143 | if ((kfd_mem_limit.system_mem_used + system_mem_needed > |
| 139 | − kfd_mem_limit.max_system_mem_limit) || | |
| 140 | − (kfd_mem_limit.ttm_mem_used + ttm_mem_needed > | |
| 141 | − kfd_mem_limit.max_ttm_mem_limit)) | |
| 144 | + kfd_mem_limit.max_system_mem_limit) || | |
| 145 | + (kfd_mem_limit.ttm_mem_used + ttm_mem_needed > | |
| 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 | 149 | ret = -ENOMEM; |
| 143 | − else { | |
| 150 | + } else { | |
| 144 | 151 | kfd_mem_limit.system_mem_used += system_mem_needed; |
| 145 | 152 | kfd_mem_limit.ttm_mem_used += ttm_mem_needed; |
| 153 | + adev->kfd.vram_used += vram_needed; | |
| 146 | 154 | } |
| 147 | 155 | |
| 148 | 156 | spin_unlock(&kfd_mem_limit.mem_limit_lock); |
| 149 | 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 | 161 | uint64_t size, u32 domain, bool sg) |
| 154 | 162 | { |
| 155 | 163 | size_t acc_size; |
| @@ -167,6 +175,11 @@ static void unreserve_system_mem_limit(struct amdgpu_device *adev, · 11 unmodified lines | ||
| 167 | 175 | } else { |
| 168 | 176 | kfd_mem_limit.system_mem_used -= acc_size; |
| 169 | 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 | 184 | WARN_ONCE(kfd_mem_limit.system_mem_used < 0, |
| 172 | 185 | "kfd system memory accounting unbalanced"); |
| @@ -176,29 +189,18 @@ static void unreserve_system_mem_limit(struct amdgpu_device *adev, · 3 unmodified lines | ||
| 176 | 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 | 198 | if (bo->flags & AMDGPU_AMDKFD_USERPTR_BO) { |
| 184 | − kfd_mem_limit.system_mem_used -= | |
| 185 | − (bo->tbo.acc_size + amdgpu_bo_size(bo)); | |
| 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; | |
| 199 | + domain = AMDGPU_GEM_DOMAIN_CPU; | |
| 200 | + sg = false; | |
| 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 | 537 | struct amdgpu_bo *bo = mem->bo; |
| 536 | 538 | |
| 537 | 539 | INIT_LIST_HEAD(&entry->head); |
| 538 | − entry->shared = true; | |
| 540 | + entry->num_shared = 1; | |
| 539 | 541 | entry->bo = &bo->tbo; |
| 540 | 542 | mutex_lock(&process_info->lock); |
| 541 | 543 | if (userptr) |
| @@ -676,7 +678,7 @@ static int reserve_bo_and_vm(struct kgd_mem *mem, · 134 unmodified lines | ||
| 676 | 678 | |
| 677 | 679 | ctx->kfd_bo.priority = 0; |
| 678 | 680 | ctx->kfd_bo.tv.bo = &bo->tbo; |
| 679 | − ctx->kfd_bo.tv.shared = true; | |
| 681 | + ctx->kfd_bo.tv.num_shared = 1; | |
| 680 | 682 | ctx->kfd_bo.user_pages = NULL; |
| 681 | 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 | 743 | ctx->kfd_bo.priority = 0; |
| 742 | 744 | ctx->kfd_bo.tv.bo = &bo->tbo; |
| 743 | − ctx->kfd_bo.tv.shared = true; | |
| 745 | + ctx->kfd_bo.tv.num_shared = 1; | |
| 744 | 746 | ctx->kfd_bo.user_pages = NULL; |
| 745 | 747 | list_add(&ctx->kfd_bo.tv.head, &ctx->list); |
| 746 | 748 | |
| @@ -885,6 +887,24 @@ update_gpuvm_pte_failed: · 138 unmodified lines | ||
| 885 | 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 | 908 | static int process_validate_vms(struct amdkfd_process_info *process_info) |
| 889 | 909 | { |
| 890 | 910 | struct amdgpu_vm *peer_vm; |
| @@ -1168,6 +1188,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( · 277 unmodified lines | ||
| 1168 | 1188 | { |
| 1169 | 1189 | struct amdgpu_device *adev = get_amdgpu_device(kgd); |
| 1170 | 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 | 1193 | uint64_t user_addr = 0; |
| 1172 | 1194 | struct amdgpu_bo *bo; |
| 1173 | 1195 | struct amdgpu_bo_param bp; |
| @@ -1196,13 +1218,25 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( · 22 unmodified lines | ||
| 1196 | 1218 | if (!offset || !*offset) |
| 1197 | 1219 | return -EINVAL; |
| 1198 | 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 | 1231 | } else { |
| 1200 | 1232 | return -EINVAL; |
| 1201 | 1233 | } |
| 1202 | 1234 | |
| 1203 | 1235 | *mem = kzalloc(sizeof(struct kgd_mem), GFP_KERNEL); |
| 1204 | − if (!*mem) | |
| 1205 | − return -ENOMEM; | |
| 1236 | + if (!*mem) { | |
| 1237 | + ret = -ENOMEM; | |
| 1238 | + goto err; | |
| 1239 | + } | |
| 1206 | 1240 | INIT_LIST_HEAD(&(*mem)->bo_va_list); |
| 1207 | 1241 | mutex_init(&(*mem)->lock); |
| 1208 | 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 | 1270 | amdgpu_sync_create(&(*mem)->sync); |
| 1237 | 1271 | |
| 1238 | − ret = amdgpu_amdkfd_reserve_system_mem_limit(adev, size, | |
| 1239 | − alloc_domain, false); | |
| 1272 | + ret = amdgpu_amdkfd_reserve_mem_limit(adev, size, alloc_domain, !!sg); | |
| 1240 | 1273 | if (ret) { |
| 1241 | 1274 | pr_debug("Insufficient system memory\n"); |
| 1242 | 1275 | goto err_reserve_limit; |
| @@ -1250,7 +1283,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( · 7 unmodified lines | ||
| 1250 | 1283 | bp.byte_align = byte_align; |
| 1251 | 1284 | bp.domain = alloc_domain; |
| 1252 | 1285 | bp.flags = alloc_flags; |
| 1253 | − bp.type = ttm_bo_type_device; | |
| 1286 | + bp.type = bo_type; | |
| 1254 | 1287 | bp.resv = NULL; |
| 1255 | 1288 | ret = amdgpu_bo_create(adev, &bp, &bo); |
| 1256 | 1289 | if (ret) { |
| @@ -1258,6 +1291,10 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( · 1 unmodified line | ||
| 1258 | 1291 | domain_string(alloc_domain), ret); |
| 1259 | 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 | 1298 | bo->kfd_bo = *mem; |
| 1262 | 1299 | (*mem)->bo = bo; |
| 1263 | 1300 | if (user_addr) |
| @@ -1289,10 +1326,15 @@ allocate_init_user_pages_failed: · 25 unmodified lines | ||
| 1289 | 1326 | /* Don't unreserve system mem limit twice */ |
| 1290 | 1327 | goto err_reserve_limit; |
| 1291 | 1328 | err_bo_create: |
| 1292 | − unreserve_system_mem_limit(adev, size, alloc_domain, false); | |
| 1329 | + unreserve_mem_limit(adev, size, alloc_domain, !!sg); | |
| 1293 | 1330 | err_reserve_limit: |
| 1294 | 1331 | mutex_destroy(&(*mem)->lock); |
| 1295 | 1332 | kfree(*mem); |
| 1333 | +err: | |
| 1334 | + if (sg) { | |
| 1335 | + sg_free_table(sg); | |
| 1336 | + kfree(sg); | |
| 1337 | + } | |
| 1296 | 1338 | return ret; |
| 1297 | 1339 | } |
| 1298 | 1340 | |
| @@ -1362,6 +1404,14 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu( · 63 unmodified lines | ||
| 1362 | 1404 | /* Free the sync object */ |
| 1363 | 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 | 1415 | /* Free the BO*/ |
| 1366 | 1416 | amdgpu_bo_unref(&mem->bo); |
| 1367 | 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 | 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 | 1771 | /* Evict a userptr BO by stopping the queues if necessary |
| 1668 | 1772 | * |
| 1669 | 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 | 1934 | validate_list.head) { |
| 1831 | 1935 | list_add_tail(&mem->resv_list.head, &resv_list); |
| 1832 | 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 | 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 | 2154 | list_add_tail(&mem->resv_list.head, &ctx.list); |
| 2051 | 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 | 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 | 118 | entry->priority = min(info[i].bo_priority, |
| 119 | 119 | AMDGPU_BO_LIST_MAX_PRIORITY); |
| 120 | 120 | entry->tv.bo = &bo->tbo; |
| 121 | − entry->tv.shared = !bo->prime_shared_count; | |
| 122 | 121 | |
| 123 | 122 | if (bo->preferred_domains == AMDGPU_GEM_DOMAIN_GDS) |
| 124 | 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 | 50 | bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj)); |
| 51 | 51 | p->uf_entry.priority = 0; |
| 52 | 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 | 55 | p->uf_entry.user_pages = NULL; |
| 55 | 56 | |
| 56 | 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 | 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 | 606 | amdgpu_bo_list_get_list(p->bo_list, &p->validated); |
| 602 | 607 | if (p->bo_list->first_userptr != p->bo_list->num_entries) |
| 603 | 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 | 722 | gws = p->bo_list->gws_obj; |
| 718 | 723 | oa = p->bo_list->oa_obj; |
| 719 | 724 | |
| 720 | − 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)); | |
| 725 | + amdgpu_bo_list_for_each_entry(e, p->bo_list) { | |
| 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 | 734 | if (gds) { |
| 724 | 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 | 966 | if (r) |
| 956 | 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 | 969 | p->job->vm_pd_addr = amdgpu_gmc_pd_addr(vm->root.base.bo); |
| 963 | 970 | |
| 964 | 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 | 74 | INIT_LIST_HEAD(&list); |
| 75 | 75 | INIT_LIST_HEAD(&csa_tv.head); |
| 76 | 76 | csa_tv.bo = &bo->tbo; |
| 77 | − csa_tv.shared = true; | |
| 77 | + csa_tv.num_shared = 1; | |
| 78 | 78 | |
| 79 | 79 | list_add(&csa_tv.head, &list); |
| 80 | 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 | 248 | return -ENOMEM; |
| 249 | 249 | |
| 250 | 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 | 252 | if (r < 0) { |
| 253 | 253 | mutex_unlock(&mgr->lock); |
| 254 | 254 | kfree(ctx); |
| @@ -515,7 +515,6 @@ void amdgpu_device_pci_config_reset(struct amdgpu_device *adev) · 514 unmodified lines | ||
| 515 | 515 | */ |
| 516 | 516 | static int amdgpu_device_doorbell_init(struct amdgpu_device *adev) |
| 517 | 517 | { |
| 518 | − amdgpu_asic_init_doorbell_index(adev); | |
| 519 | 518 | |
| 520 | 519 | /* No doorbell on SI hardware generation */ |
| 521 | 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 | 528 | if (pci_resource_flags(adev->pdev, 2) & IORESOURCE_UNSET) |
| 530 | 529 | return -EINVAL; |
| 531 | 530 | |
| 531 | + amdgpu_asic_init_doorbell_index(adev); | |
| 532 | + | |
| 532 | 533 | /* doorbell bar mapping */ |
| 533 | 534 | adev->doorbell.base = pci_resource_start(adev->pdev, 2); |
| 534 | 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 | 1866 | int i, r; |
| 1866 | 1867 | |
| 1868 | + if (adev->gmc.xgmi.num_physical_nodes > 1) | |
| 1869 | + amdgpu_xgmi_remove_device(adev); | |
| 1870 | + | |
| 1867 | 1871 | amdgpu_amdkfd_device_fini(adev); |
| 1868 | 1872 | |
| 1869 | 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 | 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 | 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 | 2468 | INIT_DELAYED_WORK(&adev->gfx.gfx_off_delay_work, |
| 2452 | 2469 | amdgpu_device_delay_enable_gfx_off); |
| 2453 | 2470 | |
| 2471 | + INIT_WORK(&adev->xgmi_reset_work, amdgpu_device_xgmi_reset_func); | |
| 2472 | + | |
| 2454 | 2473 | adev->gfx.gfx_off_req_count = 1; |
| 2455 | 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 | 3259 | if (amdgpu_gpu_recovery == -1) { |
| 3241 | 3260 | switch (adev->asic_type) { |
| 3261 | + case CHIP_BONAIRE: | |
| 3262 | + case CHIP_HAWAII: | |
| 3242 | 3263 | case CHIP_TOPAZ: |
| 3243 | 3264 | case CHIP_TONGA: |
| 3244 | 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 | 3350 | if (need_full_reset) { |
| 3330 | 3351 | list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { |
| 3331 | − r = amdgpu_asic_reset(tmp_adev); | |
| 3332 | − if (r) | |
| 3333 | − DRM_WARN("ASIC reset failed with err r, %d for drm dev, %s", | |
| 3352 | + /* For XGMI run all resets in parallel to speed up the process */ | |
| 3353 | + if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) { | |
| 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 | 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 | 3560 | if (tmp_adev == adev) |
| 3519 | 3561 | continue; |
| 3520 | 3562 | |
| 3521 | − dev_info(tmp_adev->dev, "GPU reset begin for drm dev %s!\n", adev->ddev->unique); | |
| 3522 | − | |
| 3523 | 3563 | amdgpu_device_lock_adev(tmp_adev); |
| 3524 | 3564 | r = amdgpu_device_pre_asic_reset(tmp_adev, |
| 3525 | 3565 | NULL, |
| @@ -169,7 +169,7 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj, · 168 unmodified lines | ||
| 169 | 169 | INIT_LIST_HEAD(&duplicates); |
| 170 | 170 | |
| 171 | 171 | tv.bo = &bo->tbo; |
| 172 | − tv.shared = true; | |
| 172 | + tv.num_shared = 1; | |
| 173 | 173 | list_add(&tv.head, &list); |
| 174 | 174 | |
| 175 | 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 | 604 | return -ENOENT; |
| 605 | 605 | abo = gem_to_amdgpu_bo(gobj); |
| 606 | 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 | 611 | list_add(&tv.head, &list); |
| 609 | 612 | } else { |
| 610 | 613 | gobj = NULL; |
| @@ -54,6 +54,8 @@ void *amdgpu_gem_prime_vmap(struct drm_gem_object *obj); · 53 unmodified lines | ||
| 54 | 54 | void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); |
| 55 | 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 | 60 | * GEM objects. |
| 59 | 61 | */ |
| @@ -99,6 +99,7 @@ struct amdgpu_xgmi { · 98 unmodified lines | ||
| 99 | 99 | unsigned num_physical_nodes; |
| 100 | 100 | /* gpu list in the same hive */ |
| 101 | 101 | struct list_head head; |
| 102 | + bool supported; | |
| 102 | 103 | }; |
| 103 | 104 | |
| 104 | 105 | struct amdgpu_gmc { |
| @@ -51,14 +51,12 @@ struct amdgpu_ih_ring { · 50 unmodified lines | ||
| 51 | 51 | struct amdgpu_ih_funcs { |
| 52 | 52 | /* ring read/write ptr handling, called from interrupt context */ |
| 53 | 53 | u32 (*get_wptr)(struct amdgpu_device *adev); |
| 54 | − bool (*prescreen_iv)(struct amdgpu_device *adev); | |
| 55 | 54 | void (*decode_iv)(struct amdgpu_device *adev, |
| 56 | 55 | struct amdgpu_iv_entry *entry); |
| 57 | 56 | void (*set_rptr)(struct amdgpu_device *adev); |
| 58 | 57 | }; |
| 59 | 58 | |
| 60 | 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 | 60 | #define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv)) |
| 63 | 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 | 145 | u32 ring_index = ih->rptr >> 2; |
| 146 | 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 | 148 | entry.iv_entry = (const uint32_t *)&ih->ring[ring_index]; |
| 156 | 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 | 364 | unsigned client_id = entry->client_id; |
| 372 | 365 | unsigned src_id = entry->src_id; |
| 373 | 366 | struct amdgpu_irq_src *src; |
| 367 | + bool handled = false; | |
| 374 | 368 | int r; |
| 375 | 369 | |
| 376 | 370 | trace_amdgpu_iv(entry); |
| 377 | 371 | |
| 378 | 372 | if (client_id >= AMDGPU_IRQ_CLIENTID_MAX) { |
| 379 | 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 | 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 | 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]; | |
| 398 | − if (!src) { | |
| 399 | − DRM_DEBUG("Unhandled interrupt src_id: %d\n", src_id); | |
| 400 | − return; | |
| 401 | − } | |
| 381 | + } else if (!adev->irq.client[client_id].sources) { | |
| 382 | + DRM_DEBUG("Unregistered interrupt client_id: %d src_id: %d\n", | |
| 383 | + client_id, src_id); | |
| 402 | 384 | |
| 385 | + } else if ((src = adev->irq.client[client_id].sources[src_id])) { | |
| 403 | 386 | r = src->funcs->process(adev, src, entry); |
| 404 | − if (r) | |
| 387 | + if (r < 0) | |
| 405 | 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 | 81 | amdgpu_bo_subtract_pin_size(bo); |
| 82 | 82 | |
| 83 | 83 | if (bo->kfd_bo) |
| 84 | − amdgpu_amdkfd_unreserve_system_memory_limit(bo); | |
| 84 | + amdgpu_amdkfd_unreserve_memory_limit(bo); | |
| 85 | 85 | |
| 86 | 86 | amdgpu_bo_kunmap(bo); |
| 87 | 87 | |
| @@ -607,53 +607,6 @@ int amdgpu_bo_create(struct amdgpu_device *adev, · 519 unmodified lines | ||
| 607 | 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 | 611 | * amdgpu_bo_validate - validate an &amdgpu_bo buffer object |
| 659 | 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 | 267 | void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence, |
| 268 | 268 | bool shared); |
| 269 | 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 | 270 | int amdgpu_bo_validate(struct amdgpu_bo *bo); |
| 276 | 271 | int amdgpu_bo_restore_shadow(struct amdgpu_bo *shadow, |
| 277 | 272 | struct dma_fence **fence); |
| @@ -39,8 +39,6 @@ · 38 unmodified lines | ||
| 39 | 39 | #include <drm/amdgpu_drm.h> |
| 40 | 40 | #include <linux/dma-buf.h> |
| 41 | 41 | |
| 42 | −static const struct dma_buf_ops amdgpu_dmabuf_ops; | |
| 43 | − | |
| 44 | 42 | /** |
| 45 | 43 | * amdgpu_gem_prime_get_sg_table - &drm_driver.gem_prime_get_sg_table |
| 46 | 44 | * implementation |
| @@ -332,7 +330,7 @@ static int amdgpu_gem_begin_cpu_access(struct dma_buf *dma_buf, · 285 unmodified lines | ||
| 332 | 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 | 334 | .attach = amdgpu_gem_map_attach, |
| 337 | 335 | .detach = amdgpu_gem_map_detach, |
| 338 | 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 | 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 | 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 | 174 | cmd->cmd.cmd_setup_tmr.buf_phy_addr_lo = lower_32_bits(tmr_mc); |
| 163 | 175 | cmd->cmd.cmd_setup_tmr.buf_phy_addr_hi = upper_32_bits(tmr_mc); |
| 164 | 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 | 204 | if (!cmd) |
| 193 | 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 | 208 | DRM_INFO("reserve 0x%x from 0x%llx for PSP TMR SIZE\n", |
| 197 | 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 | 548 | int ret; |
| 537 | 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 | 553 | goto skip_memalloc; |
| 554 | + } | |
| 541 | 555 | |
| 542 | 556 | psp->cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); |
| 543 | 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 | 218 | int psp_gpu_reset(struct amdgpu_device *adev); |
| 219 | 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 | 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 | 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 | 401 | return false; |
| 402 | 402 | |
| 403 | 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 | 618 | entry->priority = 0; |
| 619 | 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 | 622 | entry->user_pages = NULL; |
| 622 | 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 | 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 | 777 | r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); |
| 781 | 778 | if (r) |
| 782 | 779 | goto error; |
| @@ -1842,10 +1839,6 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, · 1059 unmodified lines | ||
| 1842 | 1839 | if (r) |
| 1843 | 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 | 1842 | r = amdgpu_vm_update_ptes(¶ms, start, last + 1, addr, flags); |
| 1850 | 1843 | if (r) |
| 1851 | 1844 | goto error_free; |
| @@ -3026,6 +3019,10 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 1174 unmodified lines | ||
| 3026 | 3019 | if (r) |
| 3027 | 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 | 3026 | r = amdgpu_vm_clear_bo(adev, vm, root, |
| 3030 | 3027 | adev->vm_manager.root_level, |
| 3031 | 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 | 3054 | INIT_KFIFO(vm->faults); |
| 3058 | − vm->fault_credit = 16; | |
| 3059 | 3055 | |
| 3060 | 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 | 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 | 3267 | * amdgpu_vm_manager_init - init the VM manager |
| 3308 | 3268 | * |
| @@ -229,9 +229,6 @@ struct amdgpu_vm { · 228 unmodified lines | ||
| 229 | 229 | /* Up to 128 pending retry page faults */ |
| 230 | 230 | DECLARE_KFIFO(faults, u64, 128); |
| 231 | 231 | |
| 232 | − /* Limit non-retry fault storms */ | |
| 233 | − unsigned int fault_credit; | |
| 234 | − | |
| 235 | 232 | /* Points to the KFD process VM info */ |
| 236 | 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 | 296 | int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, unsigned int pasid); |
| 300 | 297 | void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm); |
| 301 | 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 | 299 | void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, |
| 305 | 300 | struct list_head *validated, |
| 306 | 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 | 78 | adev->gmc.xgmi.node_id, |
| 79 | 79 | adev->gmc.xgmi.hive_id, ret); |
| 80 | 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 | 82 | adev->gmc.xgmi.physical_node_id, |
| 83 | 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 | 95 | int count = 0, ret = -EINVAL; |
| 96 | 96 | |
| 97 | − if ((adev->asic_type < CHIP_VEGA20) || | |
| 98 | − (adev->flags & AMD_IS_APU) ) | |
| 97 | + if (!adev->gmc.xgmi.supported) | |
| 99 | 98 | return 0; |
| 99 | + | |
| 100 | 100 | adev->gmc.xgmi.node_id = psp_xgmi_get_node_id(&adev->psp); |
| 101 | 101 | adev->gmc.xgmi.hive_id = psp_xgmi_get_hive_id(&adev->psp); |
| 102 | 102 | |
| @@ -135,3 +135,23 @@ exit: · 32 unmodified lines | ||
| 135 | 135 | mutex_unlock(&xgmi_mutex); |
| 136 | 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 | 35 | struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev); |
| 36 | 36 | int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_device *adev); |
| 37 | 37 | int amdgpu_xgmi_add_device(struct amdgpu_device *adev); |
| 38 | +void amdgpu_xgmi_remove_device(struct amdgpu_device *adev); | |
| 38 | 39 | |
| 39 | 40 | #endif |
| @@ -228,34 +228,6 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev) · 227 unmodified lines | ||
| 228 | 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 | 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 | 434 | static const struct amdgpu_ih_funcs cik_ih_funcs = { |
| 463 | 435 | .get_wptr = cik_ih_get_wptr, |
| 464 | − .prescreen_iv = cik_ih_prescreen_iv, | |
| 465 | 436 | .decode_iv = cik_ih_decode_iv, |
| 466 | 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 | 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 | 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 | 415 | static const struct amdgpu_ih_funcs cz_ih_funcs = { |
| 444 | 416 | .get_wptr = cz_ih_get_wptr, |
| 445 | − .prescreen_iv = cz_ih_prescreen_iv, | |
| 446 | 417 | .decode_iv = cz_ih_decode_iv, |
| 447 | 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 | 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 | 4076 | adev->gfx.rlc.funcs->stop(adev); |
| 4072 | 4077 | adev->gfx.rlc.funcs->reset(adev); |
| 4073 | 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 | 4952 | static int gfx_v8_0_pre_soft_reset(void *handle) |
| 4948 | 4953 | { |
| 4949 | 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 | 4957 | if ((!adev->gfx.grbm_soft_reset) && |
| 4953 | 4958 | (!adev->gfx.srbm_soft_reset)) |
| 4954 | 4959 | return 0; |
| 4955 | 4960 | |
| 4956 | 4961 | grbm_soft_reset = adev->gfx.grbm_soft_reset; |
| 4957 | − srbm_soft_reset = adev->gfx.srbm_soft_reset; | |
| 4958 | 4962 | |
| 4959 | 4963 | /* stop the rlc */ |
| 4960 | 4964 | adev->gfx.rlc.funcs->stop(adev); |
| @@ -5051,14 +5055,13 @@ static int gfx_v8_0_soft_reset(void *handle) · 90 unmodified lines | ||
| 5051 | 5055 | static int gfx_v8_0_post_soft_reset(void *handle) |
| 5052 | 5056 | { |
| 5053 | 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 | 5060 | if ((!adev->gfx.grbm_soft_reset) && |
| 5057 | 5061 | (!adev->gfx.srbm_soft_reset)) |
| 5058 | 5062 | return 0; |
| 5059 | 5063 | |
| 5060 | 5064 | grbm_soft_reset = adev->gfx.grbm_soft_reset; |
| 5061 | − srbm_soft_reset = adev->gfx.srbm_soft_reset; | |
| 5062 | 5065 | |
| 5063 | 5066 | if (REG_GET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_CP) || |
| 5064 | 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 | 86 | MODULE_FIRMWARE("amdgpu/picasso_mec.bin"); |
| 87 | 87 | MODULE_FIRMWARE("amdgpu/picasso_mec2.bin"); |
| 88 | 88 | MODULE_FIRMWARE("amdgpu/picasso_rlc.bin"); |
| 89 | +MODULE_FIRMWARE("amdgpu/picasso_rlc_am4.bin"); | |
| 89 | 90 | |
| 90 | 91 | MODULE_FIRMWARE("amdgpu/raven2_ce.bin"); |
| 91 | 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 | 646 | adev->gfx.ce_fw_version = le32_to_cpu(cp_hdr->header.ucode_version); |
| 646 | 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 | 663 | err = request_firmware(&adev->gfx.rlc_fw, fw_name, adev->dev); |
| 650 | 664 | if (err) |
| 651 | 665 | goto out; |
| @@ -244,6 +244,62 @@ static int gmc_v9_0_vm_fault_interrupt_state(struct amdgpu_device *adev, · 243 unmodified lines | ||
| 244 | 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 | 303 | static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, |
| 248 | 304 | struct amdgpu_irq_src *source, |
| 249 | 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 | 311 | addr = (u64)entry->src_data[0] << 12; |
| 256 | 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 | 317 | if (!amdgpu_sriov_vf(adev)) { |
| 259 | 318 | status = RREG32(hub->vm_l2_pro_fault_status); |
| 260 | 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 | 961 | /* This interrupt is VMC page fault.*/ |
| 903 | 962 | r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VMC, VMC_1_0__SRCID__VM_FAULT, |
| 904 | 963 | &adev->gmc.vm_fault); |
| 964 | + if (r) | |
| 965 | + return r; | |
| 966 | + | |
| 905 | 967 | r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_UTCL2, UTCL2_1_0__SRCID__FAULT, |
| 906 | 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 | 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 | 1000 | r = gfxhub_v1_1_get_xgmi_info(adev); |
| 939 | 1001 | if (r) |
| 940 | 1002 | return r; |
| @@ -207,34 +207,6 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev) · 206 unmodified lines | ||
| 207 | 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 | 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 | 413 | static const struct amdgpu_ih_funcs iceland_ih_funcs = { |
| 442 | 414 | .get_wptr = iceland_ih_get_wptr, |
| 443 | − .prescreen_iv = iceland_ih_prescreen_iv, | |
| 444 | 415 | .decode_iv = iceland_ih_decode_iv, |
| 445 | 416 | .set_rptr = iceland_ih_set_rptr |
| 446 | 417 | }; |
| @@ -43,6 +43,8 @@ enum psp_gfx_crtl_cmd_id · 42 unmodified lines | ||
| 43 | 43 | GFX_CTRL_CMD_ID_ENABLE_INT = 0x00050000, /* enable PSP-to-Gfx interrupt */ |
| 44 | 44 | GFX_CTRL_CMD_ID_DISABLE_INT = 0x00060000, /* disable PSP-to-Gfx interrupt */ |
| 45 | 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 | 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 | 91 | GFX_CMD_ID_LOAD_IP_FW = 0x00000006, /* load HW IP FW */ |
| 90 | 92 | GFX_CMD_ID_DESTROY_TMR = 0x00000007, /* destroy TMR region */ |
| 91 | 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 | 171 | * are already been loaded. |
| 172 | 172 | */ |
| 173 | 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 | 177 | return 0; |
| 178 | + } | |
| 176 | 179 | |
| 177 | 180 | /* Wait for bootloader to signify that is ready having bit 31 of C2PMSG_35 set to 1 */ |
| 178 | 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 | 299 | struct psp_ring *ring = &psp->km_ring; |
| 297 | 300 | struct amdgpu_device *adev = psp->adev; |
| 298 | 301 | |
| 299 | − /* Write low address of the ring to C2PMSG_69 */ | |
| 300 | − psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); | |
| 301 | − WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_69, psp_ring_reg); | |
| 302 | − /* Write high address of the ring to C2PMSG_70 */ | |
| 303 | − psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); | |
| 304 | − WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_70, psp_ring_reg); | |
| 305 | − /* Write size of ring to C2PMSG_71 */ | |
| 306 | − psp_ring_reg = ring->ring_size; | |
| 307 | − WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_71, psp_ring_reg); | |
| 308 | − /* Write the ring initialization command to C2PMSG_64 */ | |
| 309 | − psp_ring_reg = ring_type; | |
| 310 | − psp_ring_reg = psp_ring_reg << 16; | |
| 311 | − WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, psp_ring_reg); | |
| 312 | − | |
| 313 | − /* there might be handshake issue with hardware which needs delay */ | |
| 314 | − mdelay(20); | |
| 315 | − | |
| 316 | − /* Wait for response flag (bit 31) in C2PMSG_64 */ | |
| 317 | − ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), | |
| 318 | − 0x80000000, 0x8000FFFF, false); | |
| 302 | + if (psp_support_vmr_ring(psp)) { | |
| 303 | + /* Write low address of the ring to C2PMSG_102 */ | |
| 304 | + psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); | |
| 305 | + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, psp_ring_reg); | |
| 306 | + /* Write high address of the ring to C2PMSG_103 */ | |
| 307 | + psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); | |
| 308 | + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_103, psp_ring_reg); | |
| 309 | + | |
| 310 | + /* Write the ring initialization command to C2PMSG_101 */ | |
| 311 | + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, | |
| 312 | + GFX_CTRL_CMD_ID_INIT_GPCOM_RING); | |
| 313 | + | |
| 314 | + /* there might be handshake issue with hardware which needs delay */ | |
| 315 | + mdelay(20); | |
| 316 | + | |
| 317 | + /* Wait for response flag (bit 31) in C2PMSG_101 */ | |
| 318 | + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101), | |
| 319 | + 0x80000000, 0x8000FFFF, false); | |
| 320 | + | |
| 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 | 344 | return ret; |
| 321 | 345 | } |
| @@ -326,15 +350,24 @@ static int psp_v11_0_ring_stop(struct psp_context *psp, · 4 unmodified lines | ||
| 326 | 350 | int ret = 0; |
| 327 | 351 | struct amdgpu_device *adev = psp->adev; |
| 328 | 352 | |
| 329 | − /* Write the ring destroy command to C2PMSG_64 */ | |
| 330 | − WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, GFX_CTRL_CMD_ID_DESTROY_RINGS); | |
| 353 | + /* Write the ring destroy command*/ | |
| 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 | 361 | /* there might be handshake issue with hardware which needs delay */ |
| 333 | 362 | mdelay(20); |
| 334 | 363 | |
| 335 | − /* Wait for response flag (bit 31) in C2PMSG_64 */ | |
| 336 | − ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), | |
| 337 | − 0x80000000, 0x80000000, false); | |
| 364 | + /* Wait for response flag (bit 31) */ | |
| 365 | + if (psp_support_vmr_ring(psp)) | |
| 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 | 372 | return ret; |
| 340 | 373 | } |
| @@ -373,7 +406,10 @@ static int psp_v11_0_cmd_submit(struct psp_context *psp, · 32 unmodified lines | ||
| 373 | 406 | uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4; |
| 374 | 407 | |
| 375 | 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 | 414 | /* Update KM RB frame pointer to new frame */ |
| 379 | 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 | 439 | /* Update the write Pointer in DWORDs */ |
| 404 | 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 | 447 | return 0; |
| 408 | 448 | } |
| @@ -547,7 +587,7 @@ static int psp_v11_0_mode1_reset(struct psp_context *psp) · 138 unmodified lines | ||
| 547 | 587 | /*send the mode 1 reset command*/ |
| 548 | 588 | WREG32(offset, GFX_CTRL_CMD_ID_MODE1_RST); |
| 549 | 589 | |
| 550 | − mdelay(1000); | |
| 590 | + msleep(500); | |
| 551 | 591 | |
| 552 | 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 | 592 | /*send the mode 1 reset command*/ |
| 593 | 593 | WREG32(offset, GFX_CTRL_CMD_ID_MODE1_RST); |
| 594 | 594 | |
| 595 | − mdelay(1000); | |
| 595 | + msleep(500); | |
| 596 | 596 | |
| 597 | 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 | 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 | 121 | static void si_ih_decode_iv(struct amdgpu_device *adev, |
| 135 | 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 | 289 | static const struct amdgpu_ih_funcs si_ih_funcs = { |
| 303 | 290 | .get_wptr = si_ih_get_wptr, |
| 304 | − .prescreen_iv = si_ih_prescreen_iv, | |
| 305 | 291 | .decode_iv = si_ih_decode_iv, |
| 306 | 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 | 507 | return -EINVAL; |
| 508 | 508 | } |
| 509 | 509 | |
| 510 | + if (adev->asic_type == CHIP_VEGA20) | |
| 511 | + adev->gmc.xgmi.supported = true; | |
| 512 | + | |
| 510 | 513 | if (adev->flags & AMD_IS_APU) |
| 511 | 514 | adev->nbio_funcs = &nbio_v7_0_funcs; |
| 512 | 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 | 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 | 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 | 479 | static const struct amdgpu_ih_funcs tonga_ih_funcs = { |
| 508 | 480 | .get_wptr = tonga_ih_get_wptr, |
| 509 | − .prescreen_iv = tonga_ih_prescreen_iv, | |
| 510 | 481 | .decode_iv = tonga_ih_decode_iv, |
| 511 | 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 | 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 | 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 | 404 | static const struct amdgpu_ih_funcs vega10_ih_funcs = { |
| 489 | 405 | .get_wptr = vega10_ih_get_wptr, |
| 490 | − .prescreen_iv = vega10_ih_prescreen_iv, | |
| 491 | 406 | .decode_iv = vega10_ih_decode_iv, |
| 492 | 407 | .set_rptr = vega10_ih_set_rptr |
| 493 | 408 | }; |
| @@ -33,6 +33,7 @@ · 32 unmodified lines | ||
| 33 | 33 | #include <linux/time.h> |
| 34 | 34 | #include <linux/mm.h> |
| 35 | 35 | #include <linux/mman.h> |
| 36 | +#include <linux/dma-buf.h> | |
| 36 | 37 | #include <asm/processor.h> |
| 37 | 38 | #include "kfd_priv.h" |
| 38 | 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 | 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 | 1283 | mutex_lock(&p->mutex); |
| 1277 | 1284 | |
| 1278 | 1285 | pdd = kfd_bind_process_to_device(dev, p); |
| @@ -1550,6 +1557,115 @@ copy_from_user_failed: · 271 unmodified lines | ||
| 1550 | 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 | 1669 | #define AMDKFD_IOCTL_DEF(ioctl, _func, _flags) \ |
| 1554 | 1670 | [_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, \ |
| 1555 | 1671 | .cmd_drv = 0, .name = #ioctl} |
| @@ -1635,7 +1751,13 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = { · 79 unmodified lines | ||
| 1635 | 1751 | kfd_ioctl_set_cu_mask, 0), |
| 1636 | 1752 | |
| 1637 | 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 | 793 | struct kfd_topology_device *kfd_topology_device_by_id(uint32_t gpu_id); |
| 794 | 794 | struct kfd_dev *kfd_device_by_id(uint32_t gpu_id); |
| 795 | 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 | 797 | int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev); |
| 797 | 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 | 101 | down_read(&topology_lock); |
| 102 | 102 | |
| 103 | 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 | 123 | device = top_dev->gpu; |
| 106 | 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 | 29 | #include "dm_services_types.h" |
| 27 | 30 | #include "dc.h" |
| 28 | 31 | #include "dc/inc/core_types.h" |
| @@ -54,6 +57,7 @@ · 25 unmodified lines | ||
| 54 | 57 | |
| 55 | 58 | #include <drm/drmP.h> |
| 56 | 59 | #include <drm/drm_atomic.h> |
| 60 | +#include <drm/drm_atomic_uapi.h> | |
| 57 | 61 | #include <drm/drm_atomic_helper.h> |
| 58 | 62 | #include <drm/drm_dp_mst_helper.h> |
| 59 | 63 | #include <drm/drm_fb_helper.h> |
| @@ -72,6 +76,7 @@ · 12 unmodified lines | ||
| 72 | 76 | |
| 73 | 77 | #include "modules/inc/mod_freesync.h" |
| 74 | 78 | #include "modules/power/power_helpers.h" |
| 79 | +#include "modules/inc/mod_info_packet.h" | |
| 75 | 80 | |
| 76 | 81 | #define FIRMWARE_RAVEN_DMCU "amdgpu/raven_dmcu.bin" |
| 77 | 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 | 134 | static int amdgpu_dm_atomic_check(struct drm_device *dev, |
| 130 | 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 | 405 | /* Zero all the fields */ |
| 399 | 406 | memset(&init_data, 0, sizeof(init_data)); |
| 400 | 407 | |
| 408 | + mutex_init(&adev->dm.dc_lock); | |
| 409 | + | |
| 401 | 410 | if(amdgpu_dm_irq_init(adev)) { |
| 402 | 411 | DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n"); |
| 403 | 412 | goto error; |
| @@ -512,6 +521,9 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) · 108 unmodified lines | ||
| 512 | 521 | /* DC Destroy TODO: Replace destroy DAL */ |
| 513 | 522 | if (adev->dm.dc) |
| 514 | 523 | dc_destroy(&adev->dm.dc); |
| 524 | + | |
| 525 | + mutex_destroy(&adev->dm.dc_lock); | |
| 526 | + | |
| 515 | 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 | 2943 | if (dm_state && dm_state->freesync_capable) |
| 2932 | 2944 | stream->ignore_msa_timing_param = true; |
| 2945 | + | |
| 2933 | 2946 | finish: |
| 2934 | 2947 | if (sink && sink->sink_signal == SIGNAL_TYPE_VIRTUAL && aconnector->base.force != DRM_FORCE_ON) |
| 2935 | 2948 | dc_sink_release(sink); |
| @@ -3001,6 +3014,7 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc) · 65 unmodified lines | ||
| 3001 | 3014 | state->abm_level = cur->abm_level; |
| 3002 | 3015 | state->vrr_supported = cur->vrr_supported; |
| 3003 | 3016 | state->freesync_config = cur->freesync_config; |
| 3017 | + state->crc_enabled = cur->crc_enabled; | |
| 3004 | 3018 | |
| 3005 | 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 | 3108 | rmx_type = RMX_FULL; |
| 3095 | 3109 | break; |
| 3096 | 3110 | case DRM_MODE_SCALE_NONE: |
| 3097 | − rmx_type = RMX_OFF; | |
| 3098 | − break; | |
| 3099 | 3111 | default: |
| 3100 | − rmx_type = RMX_ASPECT; | |
| 3112 | + rmx_type = RMX_OFF; | |
| 3101 | 3113 | break; |
| 3102 | 3114 | } |
| 3103 | 3115 | |
| @@ -3210,10 +3222,11 @@ void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector) · 106 unmodified lines | ||
| 3210 | 3222 | state = kzalloc(sizeof(*state), GFP_KERNEL); |
| 3211 | 3223 | |
| 3212 | 3224 | if (state) { |
| 3213 | − state->scaling = RMX_ASPECT; | |
| 3225 | + state->scaling = RMX_OFF; | |
| 3214 | 3226 | state->underscan_enable = false; |
| 3215 | 3227 | state->underscan_hborder = 0; |
| 3216 | 3228 | state->underscan_vborder = 0; |
| 3229 | + state->max_bpc = 8; | |
| 3217 | 3230 | |
| 3218 | 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 | 3249 | new_state->freesync_capable = state->freesync_capable; |
| 3237 | 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 | 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 | 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 | 3659 | static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { |
| 3611 | 3660 | .prepare_fb = dm_plane_helper_prepare_fb, |
| 3612 | 3661 | .cleanup_fb = dm_plane_helper_cleanup_fb, |
| 3613 | 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 | 4350 | static void handle_cursor_update(struct drm_plane *plane, |
| 4300 | 4351 | struct drm_plane_state *old_plane_state) |
| 4301 | 4352 | { |
| 4353 | + struct amdgpu_device *adev = plane->dev->dev_private; | |
| 4302 | 4354 | struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb); |
| 4303 | 4355 | struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc; |
| 4304 | 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 | 4376 | if (!position.enable) { |
| 4325 | 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 | 4380 | dc_stream_set_cursor_position(crtc_state->stream, |
| 4328 | 4381 | &position); |
| 4382 | + mutex_unlock(&adev->dm.dc_lock); | |
| 4383 | + } | |
| 4329 | 4384 | return; |
| 4330 | 4385 | } |
| 4331 | 4386 | |
| @@ -4343,6 +4398,7 @@ static void handle_cursor_update(struct drm_plane *plane, · 11 unmodified lines | ||
| 4343 | 4398 | attributes.pitch = attributes.width; |
| 4344 | 4399 | |
| 4345 | 4400 | if (crtc_state->stream) { |
| 4401 | + mutex_lock(&adev->dm.dc_lock); | |
| 4346 | 4402 | if (!dc_stream_set_cursor_attributes(crtc_state->stream, |
| 4347 | 4403 | &attributes)) |
| 4348 | 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 | 4406 | if (!dc_stream_set_cursor_position(crtc_state->stream, |
| 4351 | 4407 | &position)) |
| 4352 | 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 | 4480 | dm->freesync_module, |
| 4424 | 4481 | new_stream, |
| 4425 | 4482 | &vrr, |
| 4426 | − packet_type_vrr, | |
| 4427 | − transfer_func_unknown, | |
| 4483 | + PACKET_TYPE_VRR, | |
| 4484 | + TRANSFER_FUNC_UNKNOWN, | |
| 4428 | 4485 | &vrr_infopacket); |
| 4429 | 4486 | |
| 4430 | 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 | 4622 | &acrtc_state->stream->vrr_infopacket; |
| 4566 | 4623 | } |
| 4567 | 4624 | |
| 4625 | + mutex_lock(&adev->dm.dc_lock); | |
| 4568 | 4626 | dc_commit_updates_for_stream(adev->dm.dc, |
| 4569 | 4627 | surface_updates, |
| 4570 | 4628 | 1, |
| @@ -4572,6 +4630,7 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, · 1 unmodified line | ||
| 4572 | 4630 | &stream_update, |
| 4573 | 4631 | &surface_updates->surface, |
| 4574 | 4632 | state); |
| 4633 | + mutex_unlock(&adev->dm.dc_lock); | |
| 4575 | 4634 | |
| 4576 | 4635 | DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", |
| 4577 | 4636 | __func__, |
| @@ -4586,6 +4645,7 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, · 8 unmodified lines | ||
| 4586 | 4645 | * with a dc_plane_state and follow the atomic model a bit more closely here. |
| 4587 | 4646 | */ |
| 4588 | 4647 | static bool commit_planes_to_stream( |
| 4648 | + struct amdgpu_display_manager *dm, | |
| 4589 | 4649 | struct dc *dc, |
| 4590 | 4650 | struct dc_plane_state **plane_states, |
| 4591 | 4651 | uint8_t new_plane_count, |
| @@ -4662,11 +4722,13 @@ static bool commit_planes_to_stream( · 70 unmodified lines | ||
| 4662 | 4722 | updates[i].scaling_info = &scaling_info[i]; |
| 4663 | 4723 | } |
| 4664 | 4724 | |
| 4725 | + mutex_lock(&dm->dc_lock); | |
| 4665 | 4726 | dc_commit_updates_for_stream( |
| 4666 | 4727 | dc, |
| 4667 | 4728 | updates, |
| 4668 | 4729 | new_plane_count, |
| 4669 | 4730 | dc_stream, stream_update, plane_states, state); |
| 4731 | + mutex_unlock(&dm->dc_lock); | |
| 4670 | 4732 | |
| 4671 | 4733 | kfree(flip_addr); |
| 4672 | 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 | 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 | 4839 | plane_states_constructed, |
| 4777 | 4840 | planes_count, |
| 4778 | 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 | 5006 | if (dc_state) { |
| 4944 | 5007 | dm_enable_per_frame_crtc_master_sync(dc_state); |
| 5008 | + mutex_lock(&dm->dc_lock); | |
| 4945 | 5009 | WARN_ON(!dc_commit_state(dm->dc, dc_state)); |
| 5010 | + mutex_unlock(&dm->dc_lock); | |
| 4946 | 5011 | } |
| 4947 | 5012 | |
| 4948 | 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 | 5070 | /*TODO How it works with MPO ?*/ |
| 5006 | 5071 | if (!commit_planes_to_stream( |
| 5072 | + dm, | |
| 5007 | 5073 | dm->dc, |
| 5008 | 5074 | status->plane_states, |
| 5009 | 5075 | status->plane_count, |
| @@ -5896,6 +5962,13 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, · 886 unmodified lines | ||
| 5896 | 5962 | ret = -EINVAL; |
| 5897 | 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 | 5974 | /* Must be success */ |
| @@ -134,6 +134,14 @@ struct amdgpu_display_manager { · 133 unmodified lines | ||
| 134 | 134 | |
| 135 | 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 | 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 | 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 | 115 | * Private functions |
| 67 | 116 | ******************************************************************************/ |
| @@ -175,6 +224,17 @@ failed_alloc: · 107 unmodified lines | ||
| 175 | 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 | 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 | 304 | * @dc: DC Object |
| 245 | 305 | * @stream: The stream to configure CRC on. |
| 246 | 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 | 356 | * @dc: DC object |
| 297 | 357 | * @stream: The DC stream state of the stream to get CRCs from. |
| 298 | 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 | 596 | if (dc->ctx->created_bios) |
| 537 | 597 | dal_bios_parser_destroy(&dc->ctx->dc_bios); |
| 538 | 598 | |
| 599 | + dc_perf_trace_destroy(&dc->ctx->perf_trace); | |
| 600 | + | |
| 539 | 601 | kfree(dc->ctx); |
| 540 | 602 | dc->ctx = NULL; |
| 541 | 603 | |
| @@ -659,6 +721,12 @@ static bool construct(struct dc *dc, · 117 unmodified lines | ||
| 659 | 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 | 730 | /* Create GPIO service */ |
| 663 | 731 | dc_ctx->gpio_service = dal_gpio_service_create( |
| 664 | 732 | dc_version, |
| @@ -1329,6 +1397,11 @@ static enum surface_update_type check_update_surfaces_for_stream( · 664 unmodified lines | ||
| 1329 | 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 | 1405 | enum surface_update_type dc_check_update_surfaces_for_stream( |
| 1333 | 1406 | struct dc *dc, |
| 1334 | 1407 | struct dc_surface_update *updates, |
| @@ -1409,6 +1482,14 @@ static void commit_planes_do_stream_update(struct dc *dc, · 74 unmodified lines | ||
| 1409 | 1482 | if (stream_update->output_csc_transform) |
| 1410 | 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 | 1493 | /* Full fe update*/ |
| 1413 | 1494 | if (update_type == UPDATE_TYPE_FAST) |
| 1414 | 1495 | continue; |
| @@ -1631,6 +1712,9 @@ enum dc_irq_source dc_interrupt_to_irq_source( · 216 unmodified lines | ||
| 1631 | 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 | 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 | 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 | 1816 | struct dc_sink *dc_link_add_remote_sink( |
| 1728 | 1817 | struct dc_link *link, |
| 1729 | 1818 | const uint8_t *edid, |
| @@ -1782,6 +1871,12 @@ fail_add_sink: · 52 unmodified lines | ||
| 1782 | 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 | 1880 | void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) |
| 1786 | 1881 | { |
| 1787 | 1882 | int i; |
| @@ -198,6 +198,13 @@ static bool program_hpd_filter( · 197 unmodified lines | ||
| 198 | 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 | 208 | bool dc_link_detect_sink(struct dc_link *link, enum dc_connection_type *type) |
| 202 | 209 | { |
| 203 | 210 | uint32_t is_hpd_high = 0; |
| @@ -324,9 +331,9 @@ static enum signal_type get_basic_signal_type( · 120 unmodified lines | ||
| 324 | 331 | return SIGNAL_TYPE_NONE; |
| 325 | 332 | } |
| 326 | 333 | |
| 327 | −/* | |
| 328 | − * @brief | |
| 329 | − * Check whether there is a dongle on DP connector | |
| 334 | +/** | |
| 335 | + * dc_link_is_dp_sink_present() - Check if there is a native DP | |
| 336 | + * or passive DP-HDMI dongle connected | |
| 330 | 337 | */ |
| 331 | 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 | 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 | 611 | bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) |
| 597 | 612 | { |
| 598 | 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 | 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 | 2200 | union dwnstream_port_caps_byte0 *port_caps = |
| 2201 | 2201 | (union dwnstream_port_caps_byte0 *)det_caps; |
| 2202 | 2202 | core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_0, |
| @@ -1447,6 +1447,14 @@ static bool are_stream_backends_same( · 1446 unmodified lines | ||
| 1447 | 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 | 1458 | bool dc_is_stream_unchanged( |
| 1451 | 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 | 1465 | return true; |
| 1458 | 1466 | } |
| 1459 | 1467 | |
| 1468 | +/** | |
| 1469 | + * dc_is_stream_scaling_unchanged() - Compare scaling rectangles of two streams. | |
| 1470 | + */ | |
| 1460 | 1471 | bool dc_is_stream_scaling_unchanged( |
| 1461 | 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 | 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 | 1633 | enum dc_status dc_add_stream_to_ctx( |
| 1620 | 1634 | struct dc *dc, |
| 1621 | 1635 | struct dc_state *new_ctx, |
| @@ -1640,6 +1654,9 @@ enum dc_status dc_add_stream_to_ctx( · 18 unmodified lines | ||
| 1640 | 1654 | return res; |
| 1641 | 1655 | } |
| 1642 | 1656 | |
| 1657 | +/** | |
| 1658 | + * dc_remove_stream_from_ctx() - Remove a stream from a dc_state. | |
| 1659 | + */ | |
| 1643 | 1660 | enum dc_status dc_remove_stream_from_ctx( |
| 1644 | 1661 | struct dc *dc, |
| 1645 | 1662 | struct dc_state *new_ctx, |
| @@ -1860,6 +1877,12 @@ enum dc_status resource_map_pool_resources( · 214 unmodified lines | ||
| 1860 | 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 | 1886 | void dc_resource_state_copy_construct_current( |
| 1864 | 1887 | const struct dc *dc, |
| 1865 | 1888 | struct dc_state *dst_ctx) |
| @@ -1875,6 +1898,14 @@ void dc_resource_state_construct( · 9 unmodified lines | ||
| 1875 | 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 | 1909 | enum dc_status dc_validate_global_state( |
| 1879 | 1910 | struct dc *dc, |
| 1880 | 1911 | struct dc_state *new_ctx) |
| @@ -2202,113 +2233,15 @@ static void set_vendor_info_packet( · 321 unmodified lines | ||
| 2202 | 2233 | struct dc_info_packet *info_packet, |
| 2203 | 2234 | struct dc_stream_state *stream) |
| 2204 | 2235 | { |
| 2205 | − uint32_t length = 0; | |
| 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. */ | |
| 2236 | + /* SPD info packet for FreeSync */ | |
| 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 | 2242 | return; |
| 2233 | 2243 | |
| 2234 | − /* 24bit IEEE Registration identifier (0x000c03). LSB first. */ | |
| 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; | |
| 2244 | + *info_packet = stream->vsp_infopacket; | |
| 2312 | 2245 | } |
| 2313 | 2246 | |
| 2314 | 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 | 2300 | void dc_resource_state_copy_construct( |
| 2372 | 2301 | const struct dc_state *src_ctx, |
| 2373 | 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 | 175 | bool dc_stream_set_cursor_attributes( |
| 176 | 176 | struct dc_stream_state *stream, |
| @@ -39,7 +39,7 @@ · 38 unmodified lines | ||
| 39 | 39 | #include "inc/hw/dmcu.h" |
| 40 | 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 | 44 | #define MAX_SURFACES 3 |
| 45 | 45 | #define MAX_STREAMS 6 |
| @@ -358,15 +358,16 @@ union dc_tiling_info { · 357 unmodified lines | ||
| 358 | 358 | } gfx8; |
| 359 | 359 | |
| 360 | 360 | struct { |
| 361 | + enum swizzle_mode_values swizzle; | |
| 361 | 362 | unsigned int num_pipes; |
| 362 | − unsigned int num_banks; | |
| 363 | + unsigned int max_compressed_frags; | |
| 363 | 364 | unsigned int pipe_interleave; |
| 365 | + | |
| 366 | + unsigned int num_banks; | |
| 364 | 367 | unsigned int num_shader_engines; |
| 365 | 368 | unsigned int num_rb_per_se; |
| 366 | − unsigned int max_compressed_frags; | |
| 367 | 369 | bool shaderEnable; |
| 368 | 370 | |
| 369 | − enum swizzle_mode_values swizzle; | |
| 370 | 371 | bool meta_linear; |
| 371 | 372 | bool rb_aligned; |
| 372 | 373 | bool pipe_aligned; |
| @@ -128,8 +128,10 @@ struct dc_link { · 127 unmodified lines | ||
| 128 | 128 | |
| 129 | 129 | const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); |
| 130 | 130 | |
| 131 | −/* | |
| 132 | − * Return an enumerated dc_link. dc_link order is constant and determined at | |
| 131 | +/** | |
| 132 | + * dc_get_link_at_index() - Return an enumerated dc_link. | |
| 133 | + * | |
| 134 | + * dc_link order is constant and determined at | |
| 133 | 135 | * boot time. They cannot be created or destroyed. |
| 134 | 136 | * Use dc_get_caps() to get number of links. |
| 135 | 137 | */ |
| @@ -56,6 +56,7 @@ struct dc_stream_state { · 55 unmodified lines | ||
| 56 | 56 | struct dc_crtc_timing_adjust adjust; |
| 57 | 57 | struct dc_info_packet vrr_infopacket; |
| 58 | 58 | struct dc_info_packet vsc_infopacket; |
| 59 | + struct dc_info_packet vsp_infopacket; | |
| 59 | 60 | |
| 60 | 61 | struct rect src; /* composition area */ |
| 61 | 62 | struct rect dst; /* stream addressable area */ |
| @@ -129,11 +130,13 @@ struct dc_stream_update { · 67 unmodified lines | ||
| 129 | 130 | struct dc_crtc_timing_adjust *adjust; |
| 130 | 131 | struct dc_info_packet *vrr_infopacket; |
| 131 | 132 | struct dc_info_packet *vsc_infopacket; |
| 133 | + struct dc_info_packet *vsp_infopacket; | |
| 132 | 134 | |
| 133 | 135 | bool *dpms_off; |
| 134 | 136 | |
| 135 | 137 | struct colorspace_transform *gamut_remap; |
| 136 | 138 | enum dc_color_space *output_color_space; |
| 139 | + enum dc_dither_option *dither_option; | |
| 137 | 140 | |
| 138 | 141 | struct dc_csc_transform *output_csc_transform; |
| 139 | 142 | |
| @@ -73,10 +73,18 @@ struct hw_asic_id { · 72 unmodified lines | ||
| 73 | 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 | 83 | struct dc_context { |
| 77 | 84 | struct dc *dc; |
| 78 | 85 | |
| 79 | 86 | void *driver_context; /* e.g. amdgpu_device */ |
| 87 | + struct dc_perf_trace *perf_trace; | |
| 80 | 88 | void *cgs_device; |
| 81 | 89 | |
| 82 | 90 | enum dce_environment dce_environment; |
| @@ -191,7 +199,6 @@ union display_content_support { · 108 unmodified lines | ||
| 191 | 199 | }; |
| 192 | 200 | |
| 193 | 201 | struct dc_panel_patch { |
| 194 | − unsigned int disconnect_delay; | |
| 195 | 202 | unsigned int dppowerup_delay; |
| 196 | 203 | unsigned int extra_t12_ms; |
| 197 | 204 | }; |
| @@ -117,6 +117,18 @@ void dce100_prepare_bandwidth( · 116 unmodified lines | ||
| 117 | 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 | 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 | 138 | dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating; |
| 127 | 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 | 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 | 67 | static uint32_t align_to_chunks_number_per_line(uint32_t pixels) |
| 101 | 68 | { |
| 102 | 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 | 77 | uint32_t retry = 0; |
| 109 | − uint32_t status_pos = | |
| 110 | − dm_read_reg(ctx, mmCRTC_STATUS_POSITION); | |
| 78 | + struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); | |
| 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 | 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 | 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 | 89 | set_reg_field_value(value, 3, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL); |
| 118 | 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 | 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 | 98 | break; |
| 127 | 99 | udelay(10); |
| 128 | 100 | } |
| @@ -130,13 +102,11 @@ static void reset_lb_on_vblank(struct dc_context *ctx) · 1 unmodified line | ||
| 130 | 102 | dm_error("Frame count did not increase for 100ms.\n"); |
| 131 | 103 | |
| 132 | 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 | 106 | set_reg_field_value(value, 2, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL); |
| 135 | 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); | |
| 137 | − | |
| 108 | + dm_write_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL), value); | |
| 138 | 109 | } |
| 139 | − | |
| 140 | 110 | } |
| 141 | 111 | |
| 142 | 112 | static void wait_for_fbc_state_changed( |
| @@ -226,10 +196,10 @@ void dce110_compressor_enable_fbc( · 83 unmodified lines | ||
| 226 | 196 | uint32_t addr; |
| 227 | 197 | uint32_t value, misc_value; |
| 228 | 198 | |
| 229 | − | |
| 230 | 199 | addr = mmFBC_CNTL; |
| 231 | 200 | value = dm_read_reg(compressor->ctx, addr); |
| 232 | 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 | 203 | set_reg_field_value( |
| 234 | 204 | value, |
| 235 | 205 | params->inst, |
| @@ -238,8 +208,10 @@ void dce110_compressor_enable_fbc( · 2 unmodified lines | ||
| 238 | 208 | |
| 239 | 209 | /* Keep track of enum controller_id FBC is attached to */ |
| 240 | 210 | compressor->is_enabled = true; |
| 241 | − compressor->attached_inst = params->inst; | |
| 242 | − cp110->offsets = reg_offsets[params->inst]; | |
| 211 | + /* attached_inst is SW CRTC instance start from 1 | |
| 212 | + * 0 = CONTROLLER_ID_UNDEFINED means not attached crtc | |
| 213 | + */ | |
| 214 | + compressor->attached_inst = params->inst + CONTROLLER_ID_D0; | |
| 243 | 215 | |
| 244 | 216 | /* Toggle it as there is bug in HW */ |
| 245 | 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 | 240 | void dce110_compressor_disable_fbc(struct compressor *compressor) |
| 269 | 241 | { |
| 270 | 242 | struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); |
| 243 | + uint32_t crtc_inst = 0; | |
| 271 | 244 | |
| 272 | 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 | 247 | uint32_t reg_data; |
| 275 | 248 | /* Turn off compression */ |
| 276 | 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 | 257 | wait_for_fbc_state_changed(cp110, false); |
| 285 | 258 | } |
| 286 | 259 | |
| 287 | − /* Sync line buffer - dce100/110 only*/ | |
| 288 | − reset_lb_on_vblank(compressor->ctx); | |
| 260 | + /* Sync line buffer which fbc was attached to dce100/110 only */ | |
| 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 | 303 | uint32_t compressed_surf_address_low_part = |
| 329 | 304 | compressor->compr_surface_address.addr.low_part; |
| 330 | 305 | |
| 306 | + cp110->offsets = reg_offsets[params->inst]; | |
| 307 | + | |
| 331 | 308 | /* Clear content first. */ |
| 332 | 309 | dm_write_reg( |
| 333 | 310 | compressor->ctx, |
| @@ -410,13 +387,7 @@ void dce110_compressor_set_fbc_invalidation_triggers( · 76 unmodified lines | ||
| 410 | 387 | value = dm_read_reg(compressor->ctx, addr); |
| 411 | 388 | set_reg_field_value( |
| 412 | 389 | value, |
| 413 | − 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, | |
| 390 | + fbc_trigger, | |
| 420 | 391 | FBC_IDLE_FORCE_CLEAR_MASK, |
| 421 | 392 | FBC_IDLE_FORCE_CLEAR_MASK); |
| 422 | 393 | dm_write_reg(compressor->ctx, addr, value); |
| @@ -549,7 +520,7 @@ void dce110_compressor_construct(struct dce110_compressor *compressor, · 126 unmodified lines | ||
| 549 | 520 | compressor->base.channel_interleave_size = 0; |
| 550 | 521 | compressor->base.dram_channels_num = 0; |
| 551 | 522 | compressor->base.lpt_channels_num = 0; |
| 552 | − compressor->base.attached_inst = 0; | |
| 523 | + compressor->base.attached_inst = CONTROLLER_ID_UNDEFINED; | |
| 553 | 524 | compressor->base.is_enabled = false; |
| 554 | 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 | 1766 | * Check if FBC can be enabled |
| 1767 | 1767 | */ |
| 1768 | 1768 | static bool should_enable_fbc(struct dc *dc, |
| 1769 | − struct dc_state *context, | |
| 1770 | − uint32_t *pipe_idx) | |
| 1769 | + struct dc_state *context, | |
| 1770 | + uint32_t *pipe_idx) | |
| 1771 | 1771 | { |
| 1772 | 1772 | uint32_t i; |
| 1773 | 1773 | struct pipe_ctx *pipe_ctx = NULL; |
| 1774 | 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 | 1778 | ASSERT(dc->fbc_compressor); |
| @@ -1786,14 +1787,28 @@ static bool should_enable_fbc(struct dc *dc, · 8 unmodified lines | ||
| 1786 | 1787 | |
| 1787 | 1788 | for (i = 0; i < dc->res_pool->pipe_count; i++) { |
| 1788 | 1789 | if (res_ctx->pipe_ctx[i].stream) { |
| 1790 | + | |
| 1789 | 1791 | pipe_ctx = &res_ctx->pipe_ctx[i]; |
| 1790 | − *pipe_idx = i; | |
| 1791 | − break; | |
| 1792 | + | |
| 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 */ | |
| 1796 | − ASSERT(pipe_ctx); | |
| 1804 | + if (i == dc->res_pool->pipe_count) | |
| 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 | 1813 | /* Only supports eDP */ |
| 1799 | 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 | 1833 | * Enable FBC |
| 1819 | 1834 | */ |
| 1820 | −static void enable_fbc(struct dc *dc, | |
| 1821 | − struct dc_state *context) | |
| 1835 | +static void enable_fbc( | |
| 1836 | + struct dc *dc, | |
| 1837 | + struct dc_state *context) | |
| 1822 | 1838 | { |
| 1823 | 1839 | uint32_t pipe_idx = 0; |
| 1824 | 1840 | |
| @@ -1828,10 +1844,9 @@ static void enable_fbc(struct dc *dc, · 3 unmodified lines | ||
| 1828 | 1844 | struct compressor *compr = dc->fbc_compressor; |
| 1829 | 1845 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; |
| 1830 | 1846 | |
| 1831 | − | |
| 1832 | 1847 | params.source_view_width = pipe_ctx->stream->timing.h_addressable; |
| 1833 | 1848 | params.source_view_height = pipe_ctx->stream->timing.v_addressable; |
| 1834 | − | |
| 1849 | + params.inst = pipe_ctx->stream_res.tg->inst; | |
| 1835 | 1850 | compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr; |
| 1836 | 1851 | |
| 1837 | 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 | 2061 | return status; |
| 2047 | 2062 | } |
| 2048 | 2063 | |
| 2049 | − dcb->funcs->set_scratch_critical_state(dcb, false); | |
| 2050 | − | |
| 2051 | 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 | 2069 | return DC_OK; |
| 2055 | 2070 | } |
| @@ -2408,7 +2423,6 @@ static void dce110_program_front_end_for_pipe( · 352 unmodified lines | ||
| 2408 | 2423 | struct dc_plane_state *plane_state = pipe_ctx->plane_state; |
| 2409 | 2424 | struct xfm_grph_csc_adjustment adjust; |
| 2410 | 2425 | struct out_csc_color_matrix tbl_entry; |
| 2411 | − unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; | |
| 2412 | 2426 | unsigned int i; |
| 2413 | 2427 | DC_LOGGER_INIT(); |
| 2414 | 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 | 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 | 2466 | mi->funcs->mem_input_program_surface_config( |
| 2462 | 2467 | mi, |
| 2463 | 2468 | plane_state->format, |
| @@ -2534,6 +2539,9 @@ static void dce110_apply_ctx_for_surface( · 70 unmodified lines | ||
| 2534 | 2539 | if (num_planes == 0) |
| 2535 | 2540 | return; |
| 2536 | 2541 | |
| 2542 | + if (dc->fbc_compressor) | |
| 2543 | + dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); | |
| 2544 | + | |
| 2537 | 2545 | for (i = 0; i < dc->res_pool->pipe_count; i++) { |
| 2538 | 2546 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; |
| 2539 | 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 | 2584 | (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) |
| 2577 | 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 | 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 | 329 | *smu_req_cur = smu_req; |
| 330 | 330 | } |
| 331 | − | |
| 332 | 331 | static const struct clk_mgr_funcs dcn1_funcs = { |
| 333 | 332 | .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, |
| 334 | 333 | .update_clocks = dcn1_update_clocks |
| 335 | 334 | }; |
| 336 | − | |
| 337 | 335 | struct clk_mgr *dcn1_clk_mgr_create(struct dc_context *ctx) |
| 338 | 336 | { |
| 339 | 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 | 372 | return &clk_mgr_dce->base; |
| 375 | 373 | } |
| 374 | + | |
| 375 | + | |
| @@ -28,6 +28,12 @@ · 27 unmodified lines | ||
| 28 | 28 | |
| 29 | 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 | 37 | void dcn1_pplib_apply_display_requirements( |
| 32 | 38 | struct dc *dc, |
| 33 | 39 | struct dc_state *context); |
| @@ -324,7 +324,7 @@ bool cm_helper_translate_curve_to_hw_format( · 323 unmodified lines | ||
| 324 | 324 | if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS) |
| 325 | 325 | return false; |
| 326 | 326 | |
| 327 | − PERF_TRACE(); | |
| 327 | + PERF_TRACE_CTX(output_tf->ctx); | |
| 328 | 328 | |
| 329 | 329 | corner_points = lut_params->corner_points; |
| 330 | 330 | rgb_resulted = lut_params->rgb_resulted; |
| @@ -513,7 +513,7 @@ bool cm_helper_translate_curve_to_degamma_hw_format( · 182 unmodified lines | ||
| 513 | 513 | if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS) |
| 514 | 514 | return false; |
| 515 | 515 | |
| 516 | − PERF_TRACE(); | |
| 516 | + PERF_TRACE_CTX(output_tf->ctx); | |
| 517 | 517 | |
| 518 | 518 | corner_points = lut_params->corner_points; |
| 519 | 519 | rgb_resulted = lut_params->rgb_resulted; |
| @@ -44,6 +44,7 @@ · 43 unmodified lines | ||
| 44 | 44 | #include "dcn10_hubp.h" |
| 45 | 45 | #include "dcn10_hubbub.h" |
| 46 | 46 | #include "dcn10_cm_common.h" |
| 47 | +#include "dcn10_clk_mgr.h" | |
| 47 | 48 | |
| 48 | 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 | 464 | static unsigned int dcn10_get_clock_states(struct dc *dc, char *pBuf, unsigned int bufSize) |
| 464 | 465 | { |
| 465 | 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," | |
| 468 | − "dppclk_khz,max_supported_dppclk_khz,fclk_khz,socclk_khz\n" | |
| 469 | − "%d,%d,%d,%d,%d,%d,%d\n", | |
| 469 | + chars_printed = snprintf_count(pBuf, bufSize, "dcfclk,dcfclk_deep_sleep,dispclk," | |
| 470 | + "dppclk,fclk,socclk\n" | |
| 471 | + "%d,%d,%d,%d,%d,%d\n", | |
| 470 | 472 | dc->current_state->bw.dcn.clk.dcfclk_khz, |
| 471 | 473 | dc->current_state->bw.dcn.clk.dcfclk_deep_sleep_khz, |
| 472 | 474 | dc->current_state->bw.dcn.clk.dispclk_khz, |
| 473 | 475 | dc->current_state->bw.dcn.clk.dppclk_khz, |
| 474 | − dc->current_state->bw.dcn.clk.max_supported_dppclk_khz, | |
| 475 | 476 | dc->current_state->bw.dcn.clk.fclk_khz, |
| 476 | 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 | 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 | 542 | * Bit 0 - 15: Hardware block mask |
| 539 | 543 | * Bit 15: 1 = Invariant Only, 0 = All |
| 540 | 544 | */ |
| 541 | − const unsigned int DC_HW_STATE_MASK_HUBBUB = 0x1; | |
| 542 | − const unsigned int DC_HW_STATE_MASK_HUBP = 0x2; | |
| 543 | − const unsigned int DC_HW_STATE_MASK_RQ = 0x4; | |
| 544 | − const unsigned int DC_HW_STATE_MASK_DLG = 0x8; | |
| 545 | − const unsigned int DC_HW_STATE_MASK_TTU = 0x10; | |
| 546 | − const unsigned int DC_HW_STATE_MASK_CM = 0x20; | |
| 547 | − const unsigned int DC_HW_STATE_MASK_MPCC = 0x40; | |
| 548 | − const unsigned int DC_HW_STATE_MASK_OTG = 0x80; | |
| 549 | − const unsigned int DC_HW_STATE_MASK_CLOCKS = 0x100; | |
| 550 | − const unsigned int DC_HW_STATE_INVAR_ONLY = 0x8000; | |
| 545 | + const unsigned int DC_HW_STATE_MASK_HUBBUB = 0x1; | |
| 546 | + const unsigned int DC_HW_STATE_MASK_HUBP = 0x2; | |
| 547 | + const unsigned int DC_HW_STATE_MASK_RQ = 0x4; | |
| 548 | + const unsigned int DC_HW_STATE_MASK_DLG = 0x8; | |
| 549 | + const unsigned int DC_HW_STATE_MASK_TTU = 0x10; | |
| 550 | + const unsigned int DC_HW_STATE_MASK_CM = 0x20; | |
| 551 | + const unsigned int DC_HW_STATE_MASK_MPCC = 0x40; | |
| 552 | + const unsigned int DC_HW_STATE_MASK_OTG = 0x80; | |
| 553 | + const unsigned int DC_HW_STATE_MASK_CLOCKS = 0x100; | |
| 554 | + const unsigned int DC_HW_STATE_INVAR_ONLY = 0x8000; | |
| 551 | 555 | |
| 552 | 556 | unsigned int chars_printed = 0; |
| 553 | 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 | 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 | 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 | 202 | #define MMHUB_SR(reg_name)\ |
| 203 | 203 | .reg_name = MMHUB_BASE(mm ## reg_name ## _BASE_IDX) + \ |
| 204 | 204 | mm ## reg_name |
| 205 | − | |
| 206 | 205 | /* macros to expend register list macro defined in HW object header file |
| 207 | 206 | * end *********************/ |
| 208 | 207 | |
| @@ -436,7 +435,6 @@ static const struct dcn_optc_mask tg_mask = { · 227 unmodified lines | ||
| 436 | 435 | TG_COMMON_MASK_SH_LIST_DCN1_0(_MASK) |
| 437 | 436 | }; |
| 438 | 437 | |
| 439 | − | |
| 440 | 438 | static const struct bios_registers bios_regs = { |
| 441 | 439 | NBIO_SR(BIOS_SCRATCH_0), |
| 442 | 440 | NBIO_SR(BIOS_SCRATCH_3), |
| @@ -497,7 +495,6 @@ static const struct dce110_clk_src_mask cs_mask = { · 54 unmodified lines | ||
| 497 | 495 | CS_COMMON_MASK_SH_LIST_DCN1_0(_MASK) |
| 498 | 496 | }; |
| 499 | 497 | |
| 500 | − | |
| 501 | 498 | static const struct resource_caps res_cap = { |
| 502 | 499 | .num_timing_generator = 4, |
| 503 | 500 | .num_opp = 4, |
| @@ -1277,7 +1274,6 @@ static bool construct( · 773 unmodified lines | ||
| 1277 | 1274 | goto fail; |
| 1278 | 1275 | } |
| 1279 | 1276 | } |
| 1280 | − | |
| 1281 | 1277 | pool->base.clk_mgr = dcn1_clk_mgr_create(ctx); |
| 1282 | 1278 | if (pool->base.clk_mgr == NULL) { |
| 1283 | 1279 | dm_error("DC: failed to create display clock!\n"); |
| @@ -33,6 +33,7 @@ · 32 unmodified lines | ||
| 33 | 33 | |
| 34 | 34 | #define EVENT_LOG_AUX_REQ(ddc, type, action, address, len, data) |
| 35 | 35 | #define EVENT_LOG_AUX_REP(ddc, type, replyStatus, len, data) |
| 36 | +#define EVENT_LOG_CUST_MSG(tag, a, ...) | |
| 36 | 37 | |
| 37 | 38 | #endif |
| 38 | 39 | |
| @@ -102,7 +102,7 @@ struct pp_smu_funcs_rv { · 101 unmodified lines | ||
| 102 | 102 | */ |
| 103 | 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 | 107 | * PPSMC_MSG_SetDriverDramAddrHigh |
| 108 | 108 | * PPSMC_MSG_SetDriverDramAddrLow |
| @@ -31,6 +31,8 @@ · 30 unmodified lines | ||
| 31 | 31 | |
| 32 | 32 | #define __DM_SERVICES_H__ |
| 33 | 33 | |
| 34 | +#include "amdgpu_dm_trace.h" | |
| 35 | + | |
| 34 | 36 | /* TODO: remove when DC is complete. */ |
| 35 | 37 | #include "dm_services_types.h" |
| 36 | 38 | #include "logger_interface.h" |
| @@ -70,6 +72,7 @@ static inline uint32_t dm_read_reg_func( · 33 unmodified lines | ||
| 70 | 72 | } |
| 71 | 73 | #endif |
| 72 | 74 | value = cgs_read_register(ctx->cgs_device, address); |
| 75 | + trace_amdgpu_dc_rreg(&ctx->perf_trace->read_count, address, value); | |
| 73 | 76 | |
| 74 | 77 | return value; |
| 75 | 78 | } |
| @@ -90,6 +93,7 @@ static inline void dm_write_reg_func( · 14 unmodified lines | ||
| 90 | 93 | } |
| 91 | 94 | #endif |
| 92 | 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 | 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 | 356 | * performance tracing |
| 353 | 357 | */ |
| 354 | −void dm_perf_trace_timestamp(const char *func_name, unsigned int line); | |
| 355 | −#define PERF_TRACE() dm_perf_trace_timestamp(__func__, __LINE__) | |
| 358 | +#define PERF_TRACE() trace_amdgpu_dc_performance(CTX->perf_trace->read_count,\ | |
| 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 | 56 | struct dc_context *ctx) |
| 57 | 57 | { |
| 58 | 58 | struct gpio_service *service; |
| 59 | − | |
| 60 | 59 | uint32_t index_of_id; |
| 61 | 60 | |
| 62 | 61 | service = kzalloc(sizeof(struct gpio_service), GFP_KERNEL); |
| @@ -78,44 +77,33 @@ struct gpio_service *dal_gpio_service_create( · 15 unmodified lines | ||
| 78 | 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 | 82 | index_of_id = 0; |
| 86 | 83 | service->ctx = ctx; |
| 87 | 84 | |
| 88 | 85 | do { |
| 89 | 86 | uint32_t number_of_bits = |
| 90 | 87 | service->factory.number_of_pins[index_of_id]; |
| 88 | + uint32_t i = 0; | |
| 91 | 89 | |
| 92 | − uint32_t number_of_uints = | |
| 93 | − (number_of_bits + bits_per_uint - 1) / | |
| 94 | − bits_per_uint; | |
| 95 | − | |
| 96 | − uint32_t *slot; | |
| 97 | − | |
| 98 | − if (number_of_bits) { | |
| 99 | − uint32_t index_of_uint = 0; | |
| 90 | + if (number_of_bits) { | |
| 91 | + service->busyness[index_of_id] = | |
| 92 | + kcalloc(number_of_bits, sizeof(char), | |
| 93 | + GFP_KERNEL); | |
| 100 | 94 | |
| 101 | − slot = kcalloc(number_of_uints, | |
| 102 | − sizeof(uint32_t), | |
| 103 | − GFP_KERNEL); | |
| 104 | − | |
| 105 | − if (!slot) { | |
| 95 | + if (!service->busyness[index_of_id]) { | |
| 106 | 96 | BREAK_TO_DEBUGGER(); |
| 107 | 97 | goto failure_2; |
| 108 | 98 | } |
| 109 | 99 | |
| 110 | 100 | do { |
| 111 | − slot[index_of_uint] = 0; | |
| 112 | − | |
| 113 | − ++index_of_uint; | |
| 114 | − } while (index_of_uint < number_of_uints); | |
| 115 | − } else | |
| 116 | − slot = NULL; | |
| 117 | − | |
| 118 | − service->busyness[index_of_id] = slot; | |
| 101 | + service->busyness[index_of_id][i] = 0; | |
| 102 | + ++i; | |
| 103 | + } while (i < number_of_bits); | |
| 104 | + } else { | |
| 105 | + service->busyness[index_of_id] = NULL; | |
| 106 | + } | |
| 119 | 107 | |
| 120 | 108 | ++index_of_id; |
| 121 | 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 | 114 | failure_2: |
| 127 | 115 | while (index_of_id) { |
| 128 | − uint32_t *slot; | |
| 129 | − | |
| 130 | 116 | --index_of_id; |
| 131 | − | |
| 132 | − slot = service->busyness[index_of_id]; | |
| 133 | − | |
| 134 | − kfree(slot); | |
| 117 | + kfree(service->busyness[index_of_id]); | |
| 135 | 118 | } |
| 136 | 119 | |
| 137 | 120 | failure_1: |
| @@ -169,9 +152,7 @@ void dal_gpio_service_destroy( · 31 unmodified lines | ||
| 169 | 152 | uint32_t index_of_id = 0; |
| 170 | 153 | |
| 171 | 154 | do { |
| 172 | − uint32_t *slot = (*ptr)->busyness[index_of_id]; | |
| 173 | − | |
| 174 | − kfree(slot); | |
| 155 | + kfree((*ptr)->busyness[index_of_id]); | |
| 175 | 156 | |
| 176 | 157 | ++index_of_id; |
| 177 | 158 | } while (index_of_id < GPIO_ID_COUNT); |
| @@ -192,11 +173,7 @@ static bool is_pin_busy( · 14 unmodified lines | ||
| 192 | 173 | enum gpio_id id, |
| 193 | 174 | uint32_t en) |
| 194 | 175 | { |
| 195 | − const uint32_t bits_per_uint = sizeof(uint32_t) << 3; | |
| 196 | − | |
| 197 | − const uint32_t *slot = service->busyness[id] + (en / bits_per_uint); | |
| 198 | − | |
| 199 | − return 0 != (*slot & (1 << (en % bits_per_uint))); | |
| 176 | + return service->busyness[id][en]; | |
| 200 | 177 | } |
| 201 | 178 | |
| 202 | 179 | static void set_pin_busy( |
| @@ -204,10 +181,7 @@ static void set_pin_busy( · 1 unmodified line | ||
| 204 | 181 | enum gpio_id id, |
| 205 | 182 | uint32_t en) |
| 206 | 183 | { |
| 207 | − const uint32_t bits_per_uint = sizeof(uint32_t) << 3; | |
| 208 | − | |
| 209 | − service->busyness[id][en / bits_per_uint] |= | |
| 210 | − (1 << (en % bits_per_uint)); | |
| 184 | + service->busyness[id][en] = true; | |
| 211 | 185 | } |
| 212 | 186 | |
| 213 | 187 | static void set_pin_free( |
| @@ -215,10 +189,7 @@ static void set_pin_free( · 1 unmodified line | ||
| 215 | 189 | enum gpio_id id, |
| 216 | 190 | uint32_t en) |
| 217 | 191 | { |
| 218 | − const uint32_t bits_per_uint = sizeof(uint32_t) << 3; | |
| 219 | − | |
| 220 | − service->busyness[id][en / bits_per_uint] &= | |
| 221 | − ~(1 << (en % bits_per_uint)); | |
| 192 | + service->busyness[id][en] = false; | |
| 222 | 193 | } |
| 223 | 194 | |
| 224 | 195 | enum gpio_result dal_gpio_service_open( |
| @@ -36,10 +36,9 @@ struct gpio_service { · 35 unmodified lines | ||
| 36 | 36 | /* |
| 37 | 37 | * @brief |
| 38 | 38 | * Business storage. |
| 39 | − * For each member of 'enum gpio_id', | |
| 40 | − * store array of bits (packed into uint32_t slots), | |
| 41 | − * index individual bit by 'en' value */ | |
| 42 | − uint32_t *busyness[GPIO_ID_COUNT]; | |
| 39 | + * one byte For each member of 'enum gpio_id' | |
| 40 | + */ | |
| 41 | + char *busyness[GPIO_ID_COUNT]; | |
| 43 | 42 | }; |
| 44 | 43 | |
| 45 | 44 | enum gpio_result dal_gpio_service_open( |
| @@ -77,6 +77,7 @@ struct compressor_funcs { · 76 unmodified lines | ||
| 77 | 77 | }; |
| 78 | 78 | struct compressor { |
| 79 | 79 | struct dc_context *ctx; |
| 80 | + /* CONTROLLER_ID_D0 + instance, CONTROLLER_ID_UNDEFINED = 0 */ | |
| 80 | 81 | uint32_t attached_inst; |
| 81 | 82 | bool is_enabled; |
| 82 | 83 | const struct compressor_funcs *funcs; |
| @@ -272,6 +272,17 @@ union bw_context { · 271 unmodified lines | ||
| 272 | 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 | 286 | struct dc_state { |
| 276 | 287 | struct dc_stream_state *streams[MAX_PIPES]; |
| 277 | 288 | struct dc_stream_status stream_status[MAX_PIPES]; |
| @@ -279,7 +290,6 @@ struct dc_state { · 1 unmodified line | ||
| 279 | 290 | |
| 280 | 291 | struct resource_context res_ctx; |
| 281 | 292 | |
| 282 | − /* The output from BW and WM calculations. */ | |
| 283 | 293 | union bw_context bw; |
| 284 | 294 | |
| 285 | 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 | 1762 | struct pwl_float_data *rgb_user = NULL; |
| 1763 | 1763 | struct pwl_float_data_ex *curve = NULL; |
| 1764 | − struct gamma_pixel *axix_x = NULL; | |
| 1764 | + struct gamma_pixel *axis_x = NULL; | |
| 1765 | 1765 | struct pixel_gamma_point *coeff = NULL; |
| 1766 | 1766 | enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB; |
| 1767 | 1767 | bool ret = false; |
| @@ -1787,10 +1787,10 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf, · 19 unmodified lines | ||
| 1787 | 1787 | GFP_KERNEL); |
| 1788 | 1788 | if (!curve) |
| 1789 | 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 | 1791 | GFP_KERNEL); |
| 1792 | − if (!axix_x) | |
| 1793 | − goto axix_x_alloc_fail; | |
| 1792 | + if (!axis_x) | |
| 1793 | + goto axis_x_alloc_fail; | |
| 1794 | 1794 | coeff = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS, sizeof(*coeff), |
| 1795 | 1795 | GFP_KERNEL); |
| 1796 | 1796 | if (!coeff) |
| @@ -1803,7 +1803,7 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf, · 6 unmodified lines | ||
| 1803 | 1803 | tf = input_tf->tf; |
| 1804 | 1804 | |
| 1805 | 1805 | build_evenly_distributed_points( |
| 1806 | − axix_x, | |
| 1806 | + axis_x, | |
| 1807 | 1807 | ramp->num_entries, |
| 1808 | 1808 | dividers); |
| 1809 | 1809 | |
| @@ -1828,7 +1828,7 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf, · 18 unmodified lines | ||
| 1828 | 1828 | tf_pts->x_point_at_y1_blue = 1; |
| 1829 | 1829 | |
| 1830 | 1830 | map_regamma_hw_to_x_user(ramp, coeff, rgb_user, |
| 1831 | − coordinates_x, axix_x, curve, | |
| 1831 | + coordinates_x, axis_x, curve, | |
| 1832 | 1832 | MAX_HW_POINTS, tf_pts, |
| 1833 | 1833 | mapUserRamp && ramp->type != GAMMA_CUSTOM); |
| 1834 | 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 | 1839 | kvfree(coeff); |
| 1840 | 1840 | coeff_alloc_fail: |
| 1841 | − kvfree(axix_x); | |
| 1842 | −axix_x_alloc_fail: | |
| 1841 | + kvfree(axis_x); | |
| 1842 | +axis_x_alloc_fail: | |
| 1843 | 1843 | kvfree(curve); |
| 1844 | 1844 | curve_alloc_fail: |
| 1845 | 1845 | kvfree(rgb_user); |
| @@ -608,12 +608,12 @@ static void build_vrr_infopacket_data(const struct mod_vrr_params *vrr, · 607 unmodified lines | ||
| 608 | 608 | static void build_vrr_infopacket_fs2_data(enum color_transfer_func app_tf, |
| 609 | 609 | struct dc_info_packet *infopacket) |
| 610 | 610 | { |
| 611 | − if (app_tf != transfer_func_unknown) { | |
| 611 | + if (app_tf != TRANSFER_FUNC_UNKNOWN) { | |
| 612 | 612 | infopacket->valid = true; |
| 613 | 613 | |
| 614 | 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 | 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 | 688 | return; |
| 689 | 689 | |
| 690 | 690 | switch (packet_type) { |
| 691 | − case packet_type_fs2: | |
| 691 | + case PACKET_TYPE_FS2: | |
| 692 | 692 | build_vrr_infopacket_v2(stream->signal, vrr, app_tf, infopacket); |
| 693 | 693 | break; |
| 694 | − case packet_type_vrr: | |
| 695 | − case packet_type_fs1: | |
| 694 | + case PACKET_TYPE_VRR: | |
| 695 | + case PACKET_TYPE_FS1: | |
| 696 | 696 | default: |
| 697 | 697 | build_vrr_infopacket_v1(stream->signal, vrr, infopacket); |
| 698 | 698 | } |
| @@ -26,15 +26,13 @@ · 25 unmodified lines | ||
| 26 | 26 | #ifndef MOD_INFO_PACKET_H_ |
| 27 | 27 | #define MOD_INFO_PACKET_H_ |
| 28 | 28 | |
| 29 | −struct info_packet_inputs { | |
| 30 | − const struct dc_stream_state *pStream; | |
| 31 | −}; | |
| 29 | +#include "mod_shared.h" | |
| 32 | 30 | |
| 33 | −struct info_packets { | |
| 34 | − struct dc_info_packet *pVscInfoPacket; | |
| 35 | −}; | |
| 31 | +//Forward Declarations | |
| 32 | +struct dc_stream_state; | |
| 33 | +struct dc_info_packet; | |
| 36 | 34 | |
| 37 | −void mod_build_infopackets(struct info_packet_inputs *inputs, | |
| 38 | − struct info_packets *info_packets); | |
| 35 | +void mod_build_vsc_infopacket(const struct dc_stream_state *stream, | |
| 36 | + struct dc_info_packet *info_packet); | |
| 39 | 37 | |
| 40 | 38 | #endif |
| @@ -23,27 +23,26 @@ · 22 unmodified lines | ||
| 23 | 23 | * |
| 24 | 24 | */ |
| 25 | 25 | |
| 26 | − | |
| 27 | 26 | #ifndef MOD_SHARED_H_ |
| 28 | 27 | #define MOD_SHARED_H_ |
| 29 | 28 | |
| 30 | 29 | enum color_transfer_func { |
| 31 | − transfer_func_unknown, | |
| 32 | − transfer_func_srgb, | |
| 33 | − transfer_func_bt709, | |
| 34 | − transfer_func_pq2084, | |
| 35 | − transfer_func_pq2084_interim, | |
| 36 | − transfer_func_linear_0_1, | |
| 37 | − transfer_func_linear_0_125, | |
| 38 | − transfer_func_dolbyvision, | |
| 39 | − transfer_func_gamma_22, | |
| 40 | − transfer_func_gamma_26 | |
| 30 | + TRANSFER_FUNC_UNKNOWN, | |
| 31 | + TRANSFER_FUNC_SRGB, | |
| 32 | + TRANSFER_FUNC_BT709, | |
| 33 | + TRANSFER_FUNC_PQ2084, | |
| 34 | + TRANSFER_FUNC_PQ2084_INTERIM, | |
| 35 | + TRANSFER_FUNC_LINEAR_0_1, | |
| 36 | + TRANSFER_FUNC_LINEAR_0_125, | |
| 37 | + TRANSFER_FUNC_GAMMA_22, | |
| 38 | + TRANSFER_FUNC_GAMMA_26 | |
| 41 | 39 | }; |
| 42 | 40 | |
| 43 | 41 | enum vrr_packet_type { |
| 44 | − packet_type_vrr, | |
| 45 | − packet_type_fs1, | |
| 46 | − packet_type_fs2 | |
| 42 | + PACKET_TYPE_VRR, | |
| 43 | + PACKET_TYPE_FS1, | |
| 44 | + PACKET_TYPE_FS2 | |
| 47 | 45 | }; |
| 48 | 46 | |
| 47 | + | |
| 49 | 48 | #endif /* MOD_SHARED_H_ */ |
| @@ -25,6 +25,10 @@ · 24 unmodified lines | ||
| 25 | 25 | |
| 26 | 26 | #include "mod_info_packet.h" |
| 27 | 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 | 33 | enum ColorimetryRGBDP { |
| 30 | 34 | ColorimetryRGB_DP_sRGB = 0, |
| @@ -41,7 +45,7 @@ enum ColorimetryYCCDP { · 10 unmodified lines | ||
| 41 | 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 | 49 | struct dc_info_packet *info_packet) |
| 46 | 50 | { |
| 47 | 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 | 163 | * DPCD register is exposed in the new Extended Receiver Capability field for DPCD Rev. 1.4 |
| 160 | 164 | * (and higher). When MISC1. bit 6. is Set to 1, a Source device uses a VSC SDP to indicate |
| 161 | 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 | 168 | if (vscPacketRevision == 0x5) { |
| 165 | 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 | 189 | #define ALLOC_MEM_FLAGS_VRAM (1 << 0) |
| 190 | 190 | #define ALLOC_MEM_FLAGS_GTT (1 << 1) |
| 191 | −#define ALLOC_MEM_FLAGS_USERPTR (1 << 2) /* TODO */ | |
| 192 | −#define ALLOC_MEM_FLAGS_DOORBELL (1 << 3) /* TODO */ | |
| 191 | +#define ALLOC_MEM_FLAGS_USERPTR (1 << 2) | |
| 192 | +#define ALLOC_MEM_FLAGS_DOORBELL (1 << 3) | |
| 193 | 193 | |
| 194 | 194 | /* |
| 195 | 195 | * Allocation flags attributes/access options. |
| @@ -276,6 +276,10 @@ struct amd_pm_funcs { · 275 unmodified lines | ||
| 276 | 276 | struct amd_pp_simple_clock_info *clocks); |
| 277 | 277 | int (*notify_smu_enable_pwe)(void *handle); |
| 278 | 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 | 285 | #endif |
| @@ -725,7 +725,7 @@ static int pp_dpm_force_clock_level(void *handle, · 724 unmodified lines | ||
| 725 | 725 | } |
| 726 | 726 | |
| 727 | 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 | 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 | 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 | 903 | return ret; |
| 904 | 904 | } |
| 905 | 905 | |
| @@ -1072,7 +1072,7 @@ static int pp_get_current_clocks(void *handle, · 166 unmodified lines | ||
| 1072 | 1072 | &hw_clocks, PHM_PerformanceLevelDesignation_Activity); |
| 1073 | 1073 | |
| 1074 | 1074 | if (ret) { |
| 1075 | − pr_info("Error in phm_get_clock_info \n"); | |
| 1075 | + pr_debug("Error in phm_get_clock_info \n"); | |
| 1076 | 1076 | mutex_unlock(&hwmgr->smu_lock); |
| 1077 | 1077 | return -EINVAL; |
| 1078 | 1078 | } |
| @@ -1332,6 +1332,78 @@ static int pp_enable_mgpu_fan_boost(void *handle) · 253 unmodified lines | ||
| 1332 | 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 | 1407 | static const struct amd_pm_funcs pp_dpm_funcs = { |
| 1336 | 1408 | .load_firmware = pp_dpm_load_fw, |
| 1337 | 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 | 1450 | .get_display_mode_validation_clocks = pp_get_display_mode_validation_clocks, |
| 1379 | 1451 | .notify_smu_enable_pwe = pp_notify_smu_enable_pwe, |
| 1380 | 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 | 286 | if (display_config == NULL) |
| 287 | 287 | return -EINVAL; |
| 288 | 288 | |
| 289 | − if (NULL != hwmgr->hwmgr_func->set_deep_sleep_dcefclk) | |
| 290 | − hwmgr->hwmgr_func->set_deep_sleep_dcefclk(hwmgr, display_config->min_dcef_deep_sleep_set_clk); | |
| 289 | + if (NULL != hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk) | |
| 290 | + hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, display_config->min_dcef_deep_sleep_set_clk); | |
| 291 | 291 | |
| 292 | 292 | for (index = 0; index < display_config->num_path_including_non_display; index++) { |
| 293 | 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 | 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 | 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 | 221 | struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); |
| 222 | 222 | |
| 223 | 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 | 225 | smu10_data->deep_sleep_dcefclk = convert_10k_to_mhz(clock); |
| 226 | 226 | smum_send_msg_to_smc_with_parameter(hwmgr, |
| 227 | 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 | 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 | 261 | static int smu10_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count) |
| 234 | 262 | { |
| 235 | 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 | 1234 | .get_max_high_clocks = smu10_get_max_high_clocks, |
| 1207 | 1235 | .read_sensor = smu10_read_sensor, |
| 1208 | 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 | 1238 | .dynamic_state_management_enable = smu10_enable_dpm_tasks, |
| 1211 | 1239 | .power_off_asic = smu10_power_off_asic, |
| 1212 | 1240 | .asic_setup = smu10_setup_asic_task, |
| @@ -1217,6 +1245,8 @@ static const struct pp_hwmgr_func smu10_hwmgr_funcs = { · 4 unmodified lines | ||
| 1217 | 1245 | .display_clock_voltage_request = smu10_display_clock_voltage_request, |
| 1218 | 1246 | .powergate_gfx = smu10_gfx_off_control, |
| 1219 | 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 | 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 | 2859 | case CHIP_POLARIS10: |
| 2860 | 2860 | case CHIP_POLARIS11: |
| 2861 | 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 | 2866 | break; |
| 2864 | 2867 | case CHIP_VEGAM: |
| 2865 | 2868 | switch_limit_us = 30; |
| @@ -4219,9 +4222,17 @@ static int smu7_check_mc_firmware(struct pp_hwmgr *hwmgr) · 1353 unmodified lines | ||
| 4219 | 4222 | if (tmp & (1 << 23)) { |
| 4220 | 4223 | data->mem_latency_high = MEM_LATENCY_HIGH; |
| 4221 | 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 | 4229 | } else { |
| 4223 | 4230 | data->mem_latency_high = 330; |
| 4224 | 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 | 4238 | return 0; |
| @@ -463,5 +463,8 @@ extern int phm_display_clock_voltage_request(struct pp_hwmgr *hwmgr, · 462 unmodified lines | ||
| 463 | 463 | |
| 464 | 464 | extern int phm_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks); |
| 465 | 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 | 469 | #endif /* _HARDWARE_MANAGER_H_ */ |
| 467 | 470 | |
| @@ -309,7 +309,7 @@ struct pp_hwmgr_func { · 308 unmodified lines | ||
| 309 | 309 | int (*avfs_control)(struct pp_hwmgr *hwmgr, bool enable); |
| 310 | 310 | int (*disable_smc_firmware_ctf)(struct pp_hwmgr *hwmgr); |
| 311 | 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 | 313 | int (*start_thermal_controller)(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range); |
| 314 | 314 | int (*notify_cac_buffer_info)(struct pp_hwmgr *hwmgr, |
| 315 | 315 | uint32_t virtual_addr_low, |
| @@ -332,6 +332,8 @@ struct pp_hwmgr_func { · 16 unmodified lines | ||
| 332 | 332 | int (*smus_notify_pwe)(struct pp_hwmgr *hwmgr); |
| 333 | 333 | int (*powergate_sdma)(struct pp_hwmgr *hwmgr, bool bgate); |
| 334 | 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 | 339 | struct pp_table_func { |
| @@ -395,6 +395,9 @@ typedef uint16_t PPSMC_Result; · 394 unmodified lines | ||
| 395 | 395 | |
| 396 | 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 | 401 | #define PPSMC_MSG_EnableDpmDidt ((uint16_t) 0x309) |
| 399 | 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 | 1528 | efuse = efuse >> 24; |
| 1529 | 1529 | |
| 1530 | 1530 | if (hwmgr->chip_id == CHIP_POLARIS10) { |
| 1531 | − min = 1000; | |
| 1532 | − max = 2300; | |
| 1531 | + if (hwmgr->is_kicker) { | |
| 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 | 1546 | } else { |
| 1534 | 1547 | min = 1100; |
| 1535 | 1548 | max = 2100; |
| @@ -1626,6 +1639,7 @@ static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) · 90 unmodified lines | ||
| 1626 | 1639 | { |
| 1627 | 1640 | struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); |
| 1628 | 1641 | struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); |
| 1642 | + struct amdgpu_device *adev = hwmgr->adev; | |
| 1629 | 1643 | |
| 1630 | 1644 | SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); |
| 1631 | 1645 | int result = 0; |
| @@ -1645,6 +1659,59 @@ static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) · 13 unmodified lines | ||
| 1645 | 1659 | |
| 1646 | 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 | 1715 | if (0 == result) { |
| 1649 | 1716 | table->BTCGB_VDROOP_TABLE[0].a0 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a0); |
| 1650 | 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 | 118 | unsigned int n_obj, n_bomap_pages; |
| 119 | 119 | size_t file_size, mmu_size; |
| 120 | 120 | __le64 *bomap, *bomap_start; |
| 121 | + unsigned long flags; | |
| 121 | 122 | |
| 122 | 123 | /* Only catch the first event, or when manually re-armed */ |
| 123 | 124 | if (!etnaviv_dump_core) |
| @@ -134,13 +135,13 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu) · 10 unmodified lines | ||
| 134 | 135 | mmu_size + gpu->buffer.size; |
| 135 | 136 | |
| 136 | 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 | 139 | list_for_each_entry(s_job, &gpu->sched.ring_mirror_list, node) { |
| 139 | 140 | submit = to_etnaviv_submit(s_job); |
| 140 | 141 | file_size += submit->cmdbuf.size; |
| 141 | 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 | 146 | /* Add in the active buffer objects */ |
| 146 | 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 | 183 | gpu->buffer.size, |
| 183 | 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 | 187 | list_for_each_entry(s_job, &gpu->sched.ring_mirror_list, node) { |
| 187 | 188 | submit = to_etnaviv_submit(s_job); |
| 188 | 189 | etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD, |
| 189 | 190 | submit->cmdbuf.vaddr, submit->cmdbuf.size, |
| 190 | 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 | 195 | /* Reserve space for the bomap */ |
| 195 | 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 | 218 | qxl_bo_ref(bo); |
| 219 | 219 | entry->tv.bo = &bo->tbo; |
| 220 | − entry->tv.shared = false; | |
| 220 | + entry->tv.num_shared = 0; | |
| 221 | 221 | list_add_tail(&entry->tv.head, &release->bos); |
| 222 | 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 | 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 | 183 | radeon_cs_buckets_add(&buckets, &p->relocs[i].tv.head, |
| 184 | 184 | priority); |
| @@ -253,7 +253,7 @@ static int radeon_cs_sync_rings(struct radeon_cs_parser *p) · 68 unmodified lines | ||
| 253 | 253 | |
| 254 | 254 | resv = reloc->robj->tbo.resv; |
| 255 | 255 | r = radeon_sync_resv(p->rdev, &p->ib.sync, resv, |
| 256 | − reloc->tv.shared); | |
| 256 | + reloc->tv.num_shared); | |
| 257 | 257 | if (r) |
| 258 | 258 | return r; |
| 259 | 259 | } |
| @@ -552,7 +552,7 @@ static void radeon_gem_va_update_vm(struct radeon_device *rdev, · 551 unmodified lines | ||
| 552 | 552 | INIT_LIST_HEAD(&list); |
| 553 | 553 | |
| 554 | 554 | tv.bo = &bo_va->bo->tbo; |
| 555 | − tv.shared = true; | |
| 555 | + tv.num_shared = 1; | |
| 556 | 556 | list_add(&tv.head, &list); |
| 557 | 557 | |
| 558 | 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 | 142 | list[0].preferred_domains = RADEON_GEM_DOMAIN_VRAM; |
| 143 | 143 | list[0].allowed_domains = RADEON_GEM_DOMAIN_VRAM; |
| 144 | 144 | list[0].tv.bo = &vm->page_directory->tbo; |
| 145 | − list[0].tv.shared = true; | |
| 145 | + list[0].tv.num_shared = 1; | |
| 146 | 146 | list[0].tiling_flags = 0; |
| 147 | 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 | 154 | list[idx].preferred_domains = RADEON_GEM_DOMAIN_VRAM; |
| 155 | 155 | list[idx].allowed_domains = RADEON_GEM_DOMAIN_VRAM; |
| 156 | 156 | list[idx].tv.bo = &list[idx].robj->tbo; |
| 157 | − list[idx].tv.shared = true; | |
| 157 | + list[idx].tv.num_shared = 1; | |
| 158 | 158 | list[idx].tiling_flags = 0; |
| 159 | 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 | 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 | 270 | /* job_finish is called after hw fence signaled |
| 215 | 271 | */ |
| 216 | 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 | 274 | struct drm_sched_job *s_job = container_of(work, struct drm_sched_job, |
| 219 | 275 | finish_work); |
| 220 | 276 | struct drm_gpu_scheduler *sched = s_job->sched; |
| 277 | + unsigned long flags; | |
| 221 | 278 | |
| 222 | 279 | /* |
| 223 | 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 | 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 | 289 | /* remove job from ring_mirror_list */ |
| 233 | 290 | list_del_init(&s_job->node); |
| 234 | 291 | /* queue TDR for next job */ |
| 235 | 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 | 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 | 306 | static void drm_sched_job_begin(struct drm_sched_job *s_job) |
| 250 | 307 | { |
| 251 | 308 | struct drm_gpu_scheduler *sched = s_job->sched; |
| 309 | + unsigned long flags; | |
| 252 | 310 | |
| 253 | 311 | dma_fence_add_callback(&s_job->s_fence->finished, &s_job->finish_cb, |
| 254 | 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 | 315 | list_add_tail(&s_job->node, &sched->ring_mirror_list); |
| 258 | 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 | 320 | static void drm_sched_job_timedout(struct work_struct *work) |
| 263 | 321 | { |
| 264 | 322 | struct drm_gpu_scheduler *sched; |
| 265 | 323 | struct drm_sched_job *job; |
| 324 | + unsigned long flags; | |
| 266 | 325 | |
| 267 | 326 | sched = container_of(work, struct drm_gpu_scheduler, work_tdr.work); |
| 268 | 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 | 330 | if (job) |
| 272 | 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 | 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 | 347 | struct drm_sched_job *s_job; |
| 289 | 348 | struct drm_sched_entity *entity, *tmp; |
| 349 | + unsigned long flags; | |
| 290 | 350 | int i; |
| 291 | 351 | |
| 292 | − spin_lock(&sched->job_list_lock); | |
| 352 | + spin_lock_irqsave(&sched->job_list_lock, flags); | |
| 293 | 353 | list_for_each_entry_reverse(s_job, &sched->ring_mirror_list, node) { |
| 294 | 354 | if (s_job->s_fence->parent && |
| 295 | 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 | 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 | 364 | if (bad && bad->s_priority != DRM_SCHED_PRIORITY_KERNEL) { |
| 305 | 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 | 398 | struct drm_sched_job *s_job, *tmp; |
| 339 | 399 | bool found_guilty = false; |
| 400 | + unsigned long flags; | |
| 340 | 401 | int r; |
| 341 | 402 | |
| 342 | − spin_lock(&sched->job_list_lock); | |
| 403 | + spin_lock_irqsave(&sched->job_list_lock, flags); | |
| 343 | 404 | list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) { |
| 344 | 405 | struct drm_sched_fence *s_fence = s_job->s_fence; |
| 345 | 406 | struct dma_fence *fence; |
| @@ -353,7 +414,7 @@ void drm_sched_job_recovery(struct drm_gpu_scheduler *sched) · 7 unmodified lines | ||
| 353 | 414 | if (found_guilty && s_job->s_fence->scheduled.context == guilty_context) |
| 354 | 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 | 418 | fence = sched->ops->run_job(s_job); |
| 358 | 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 | 433 | drm_sched_expel_job_unlocked(s_job); |
| 373 | 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 | 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 | 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 | 673 | long timeout, |
| 613 | 674 | const char *name) |
| 614 | 675 | { |
| 615 | − int i; | |
| 676 | + int i, ret; | |
| 616 | 677 | sched->ops = ops; |
| 617 | 678 | sched->hw_submission_limit = hw_submission; |
| 618 | 679 | sched->name = name; |
| @@ -633,8 +694,10 @@ int drm_sched_init(struct drm_gpu_scheduler *sched, · 14 unmodified lines | ||
| 633 | 694 | /* Each scheduler will run on a seperate kernel thread */ |
| 634 | 695 | sched->thread = kthread_run(drm_sched_main, sched, sched->name); |
| 635 | 696 | if (IS_ERR(sched->thread)) { |
| 697 | + ret = PTR_ERR(sched->thread); | |
| 698 | + sched->thread = NULL; | |
| 636 | 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 | 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 | 128 | if (!ret) { |
| 129 | − if (!entry->shared) | |
| 129 | + if (!entry->num_shared) | |
| 130 | 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 | 134 | if (!ret) |
| 134 | 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 | − ret = reservation_object_reserve_shared(bo->resv, 1); | |
| 154 | + if (!ret && entry->num_shared) | |
| 155 | + ret = reservation_object_reserve_shared(bo->resv, | |
| 156 | + entry->num_shared); | |
| 155 | 157 | |
| 156 | 158 | if (unlikely(ret != 0)) { |
| 157 | 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 | 202 | list_for_each_entry(entry, list, head) { |
| 201 | 203 | bo = entry->bo; |
| 202 | − if (entry->shared) | |
| 204 | + if (entry->num_shared) | |
| 203 | 205 | reservation_object_add_shared_fence(bo->resv, fence); |
| 204 | 206 | else |
| 205 | 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 | 85 | struct ttm_validate_buffer val_buf; |
| 86 | 86 | |
| 87 | 87 | val_buf.bo = bo; |
| 88 | − val_buf.shared = false; | |
| 88 | + val_buf.num_shared = 0; | |
| 89 | 89 | res->func->unbind(res, false, &val_buf); |
| 90 | 90 | } |
| 91 | 91 | res->backup_dirty = false; |
| @@ -462,7 +462,7 @@ vmw_resource_check_buffer(struct ww_acquire_ctx *ticket, · 370 unmodified lines | ||
| 462 | 462 | |
| 463 | 463 | INIT_LIST_HEAD(&val_list); |
| 464 | 464 | val_buf->bo = ttm_bo_reference(&res->backup->base); |
| 465 | − val_buf->shared = false; | |
| 465 | + val_buf->num_shared = 0; | |
| 466 | 466 | list_add_tail(&val_buf->head, &val_list); |
| 467 | 467 | ret = ttm_eu_reserve_buffers(ticket, &val_list, interruptible, NULL); |
| 468 | 468 | if (unlikely(ret != 0)) |
| @@ -565,7 +565,7 @@ static int vmw_resource_do_evict(struct ww_acquire_ctx *ticket, · 96 unmodified lines | ||
| 565 | 565 | BUG_ON(!func->may_evict); |
| 566 | 566 | |
| 567 | 567 | val_buf.bo = NULL; |
| 568 | − val_buf.shared = false; | |
| 568 | + val_buf.num_shared = 0; | |
| 569 | 569 | ret = vmw_resource_check_buffer(ticket, res, interruptible, &val_buf); |
| 570 | 570 | if (unlikely(ret != 0)) |
| 571 | 571 | return ret; |
| @@ -614,7 +614,7 @@ int vmw_resource_validate(struct vmw_resource *res, bool intr) · 42 unmodified lines | ||
| 614 | 614 | return 0; |
| 615 | 615 | |
| 616 | 616 | val_buf.bo = NULL; |
| 617 | − val_buf.shared = false; | |
| 617 | + val_buf.num_shared = 0; | |
| 618 | 618 | if (res->backup) |
| 619 | 619 | val_buf.bo = &res->backup->base; |
| 620 | 620 | do { |
| @@ -685,7 +685,7 @@ void vmw_resource_unbind_list(struct vmw_buffer_object *vbo) · 64 unmodified lines | ||
| 685 | 685 | struct vmw_resource *res, *next; |
| 686 | 686 | struct ttm_validate_buffer val_buf = { |
| 687 | 687 | .bo = &vbo->base, |
| 688 | − .shared = false | |
| 688 | + .num_shared = 0 | |
| 689 | 689 | }; |
| 690 | 690 | |
| 691 | 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 | 266 | val_buf->bo = ttm_bo_get_unless_zero(&vbo->base); |
| 267 | 267 | if (!val_buf->bo) |
| 268 | 268 | return -ESRCH; |
| 269 | − val_buf->shared = false; | |
| 269 | + val_buf->num_shared = 0; | |
| 270 | 270 | list_add_tail(&val_buf->head, &ctx->bo_list); |
| 271 | 271 | bo_node->as_mob = as_mob; |
| 272 | 272 | bo_node->cpu_blit = cpu_blit; |
| @@ -331,4 +331,8 @@ struct drm_sched_fence *drm_sched_fence_create( · 330 unmodified lines | ||
| 331 | 331 | void drm_sched_fence_scheduled(struct drm_sched_fence *fence); |
| 332 | 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 | 338 | #endif |
| @@ -40,13 +40,13 @@ · 39 unmodified lines | ||
| 40 | 40 | * |
| 41 | 41 | * @head: list head for thread-private list. |
| 42 | 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 | 46 | struct ttm_validate_buffer { |
| 47 | 47 | struct list_head head; |
| 48 | 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 | 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 | 419 | #define AMDKFD_IOCTL_BASE 'K' |
| 402 | 420 | #define AMDKFD_IO(nr) _IO(AMDKFD_IOCTL_BASE, nr) |
| 403 | 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 | 504 | #define AMDKFD_IOC_GET_QUEUE_WAVE_STATE \ |
| 487 | 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 | 513 | #define AMDKFD_COMMAND_START 0x01 |
| 490 | −#define AMDKFD_COMMAND_END 0x1C | |
| 514 | +#define AMDKFD_COMMAND_END 0x1E | |
| 491 | 515 | |
| 492 | 516 | #endif |