amd-drm-next-5.14-2021-06-16: amdgpu: - Aldebaran fixes - Expose asic independent throttler status - BACO fixes for navi1x - Smartshift fixes - Misc code cleanups - RAS fixes for Sienna Cichlid - Gamma verificaton fixes - DC LTTPR fixes - DP AUX timeout handling fixes - GFX9, 10 powergating fixes amdkfd: - TLB flush fixes when using SDMA - Locking fixes - SVM fixes
Unified · Split
| @@ -47,12 +47,6 @@ static struct { · 46 unmodified lines | |||
| 47 | spinlock_t mem_limit_lock; | 47 | spinlock_t mem_limit_lock; |
| 48 | } kfd_mem_limit; | 48 | } kfd_mem_limit; |
| 49 | 49 | ||
| 50 | /* Struct used for amdgpu_amdkfd_bo_validate */ | ||
| 51 | struct amdgpu_vm_parser { | ||
| 52 | uint32_t domain; | ||
| 53 | bool wait; | ||
| 54 | }; | ||
| 55 | |||
| 56 | static const char * const domain_bit_to_string[] = { | 50 | static const char * const domain_bit_to_string[] = { |
| 57 | "CPU", | 51 | "CPU", |
| 58 | "GTT", | 52 | "GTT", |
| @@ -348,11 +342,9 @@ validate_fail: · 289 unmodified lines | |||
| 348 | return ret; | 342 | return ret; |
| 349 | } | 343 | } |
| 350 | 344 | ||
| 351 | static int amdgpu_amdkfd_validate(void *param, struct amdgpu_bo *bo) | 345 | static int amdgpu_amdkfd_validate_vm_bo(void *_unused, struct amdgpu_bo *bo) |
| 352 | { | 346 | { |
| 353 | struct amdgpu_vm_parser *p = param; | 347 | return amdgpu_amdkfd_bo_validate(bo, bo->allowed_domains, false); |
| 354 | |||
| 355 | return amdgpu_amdkfd_bo_validate(bo, p->domain, p->wait); | ||
| 356 | } | 348 | } |
| 357 | 349 | ||
| 358 | /* vm_validate_pt_pd_bos - Validate page table and directory BOs | 350 | /* vm_validate_pt_pd_bos - Validate page table and directory BOs |
| @@ -364,28 +356,23 @@ static int amdgpu_amdkfd_validate(void *param, struct amdgpu_bo *bo) · 5 unmodified lines | |||
| 364 | */ | 356 | */ |
| 365 | static int vm_validate_pt_pd_bos(struct amdgpu_vm *vm) | 357 | static int vm_validate_pt_pd_bos(struct amdgpu_vm *vm) |
| 366 | { | 358 | { |
| 367 | struct amdgpu_bo *pd = vm->root.base.bo; | 359 | struct amdgpu_bo *pd = vm->root.bo; |
| 368 | struct amdgpu_device *adev = amdgpu_ttm_adev(pd->tbo.bdev); | 360 | struct amdgpu_device *adev = amdgpu_ttm_adev(pd->tbo.bdev); |
| 369 | struct amdgpu_vm_parser param; | ||
| 370 | int ret; | 361 | int ret; |
| 371 | 362 | ||
| 372 | param.domain = AMDGPU_GEM_DOMAIN_VRAM; | 363 | ret = amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_amdkfd_validate_vm_bo, NULL); |
| 373 | param.wait = false; | ||
| 374 | |||
| 375 | ret = amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_amdkfd_validate, | ||
| 376 | ¶m); | ||
| 377 | if (ret) { | 364 | if (ret) { |
| 378 | pr_err("failed to validate PT BOs\n"); | 365 | pr_err("failed to validate PT BOs\n"); |
| 379 | return ret; | 366 | return ret; |
| 380 | } | 367 | } |
| 381 | 368 | ||
| 382 | ret = amdgpu_amdkfd_validate(¶m, pd); | 369 | ret = amdgpu_amdkfd_validate_vm_bo(NULL, pd); |
| 383 | if (ret) { | 370 | if (ret) { |
| 384 | pr_err("failed to validate PD\n"); | 371 | pr_err("failed to validate PD\n"); |
| 385 | return ret; | 372 | return ret; |
| 386 | } | 373 | } |
| 387 | 374 | ||
| 388 | vm->pd_phys_addr = amdgpu_gmc_pd_addr(vm->root.base.bo); | 375 | vm->pd_phys_addr = amdgpu_gmc_pd_addr(vm->root.bo); |
| 389 | 376 | ||
| 390 | if (vm->use_cpu_for_update) { | 377 | if (vm->use_cpu_for_update) { |
| 391 | ret = amdgpu_bo_kmap(pd, NULL); | 378 | ret = amdgpu_bo_kmap(pd, NULL); |
| @@ -400,7 +387,7 @@ static int vm_validate_pt_pd_bos(struct amdgpu_vm *vm) · 8 unmodified lines | |||
| 400 | 387 | ||
| 401 | static int vm_update_pds(struct amdgpu_vm *vm, struct amdgpu_sync *sync) | 388 | static int vm_update_pds(struct amdgpu_vm *vm, struct amdgpu_sync *sync) |
| 402 | { | 389 | { |
| 403 | struct amdgpu_bo *pd = vm->root.base.bo; | 390 | struct amdgpu_bo *pd = vm->root.bo; |
| 404 | struct amdgpu_device *adev = amdgpu_ttm_adev(pd->tbo.bdev); | 391 | struct amdgpu_device *adev = amdgpu_ttm_adev(pd->tbo.bdev); |
| 405 | int ret; | 392 | int ret; |
| 406 | 393 | ||
| @@ -652,7 +639,7 @@ kfd_mem_attach_dmabuf(struct amdgpu_device *adev, struct kgd_mem *mem, · 245 unmodified lines | |||
| 652 | } | 639 | } |
| 653 | } | 640 | } |
| 654 | 641 | ||
| 655 | gobj = amdgpu_gem_prime_import(&adev->ddev, mem->dmabuf); | 642 | gobj = amdgpu_gem_prime_import(adev_to_drm(adev), mem->dmabuf); |
| 656 | if (IS_ERR(gobj)) | 643 | if (IS_ERR(gobj)) |
| 657 | return PTR_ERR(gobj); | 644 | return PTR_ERR(gobj); |
| 658 | 645 | ||
| @@ -1166,7 +1153,7 @@ static int process_sync_pds_resv(struct amdkfd_process_info *process_info, · 507 unmodified lines | |||
| 1166 | 1153 | ||
| 1167 | list_for_each_entry(peer_vm, &process_info->vm_list_head, | 1154 | list_for_each_entry(peer_vm, &process_info->vm_list_head, |
| 1168 | vm_list_node) { | 1155 | vm_list_node) { |
| 1169 | struct amdgpu_bo *pd = peer_vm->root.base.bo; | 1156 | struct amdgpu_bo *pd = peer_vm->root.bo; |
| 1170 | 1157 | ||
| 1171 | ret = amdgpu_sync_resv(NULL, sync, pd->tbo.base.resv, | 1158 | ret = amdgpu_sync_resv(NULL, sync, pd->tbo.base.resv, |
| 1172 | AMDGPU_SYNC_NE_OWNER, | 1159 | AMDGPU_SYNC_NE_OWNER, |
| @@ -1233,7 +1220,7 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info, · 60 unmodified lines | |||
| 1233 | vm->process_info = *process_info; | 1220 | vm->process_info = *process_info; |
| 1234 | 1221 | ||
| 1235 | /* Validate page directory and attach eviction fence */ | 1222 | /* Validate page directory and attach eviction fence */ |
| 1236 | ret = amdgpu_bo_reserve(vm->root.base.bo, true); | 1223 | ret = amdgpu_bo_reserve(vm->root.bo, true); |
| 1237 | if (ret) | 1224 | if (ret) |
| 1238 | goto reserve_pd_fail; | 1225 | goto reserve_pd_fail; |
| 1239 | ret = vm_validate_pt_pd_bos(vm); | 1226 | ret = vm_validate_pt_pd_bos(vm); |
| @@ -1241,16 +1228,16 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info, · 1 unmodified line | |||
| 1241 | pr_err("validate_pt_pd_bos() failed\n"); | 1228 | pr_err("validate_pt_pd_bos() failed\n"); |
| 1242 | goto validate_pd_fail; | 1229 | goto validate_pd_fail; |
| 1243 | } | 1230 | } |
| 1244 | ret = amdgpu_bo_sync_wait(vm->root.base.bo, | 1231 | ret = amdgpu_bo_sync_wait(vm->root.bo, |
| 1245 | AMDGPU_FENCE_OWNER_KFD, false); | 1232 | AMDGPU_FENCE_OWNER_KFD, false); |
| 1246 | if (ret) | 1233 | if (ret) |
| 1247 | goto wait_pd_fail; | 1234 | goto wait_pd_fail; |
| 1248 | ret = dma_resv_reserve_shared(vm->root.base.bo->tbo.base.resv, 1); | 1235 | ret = dma_resv_reserve_shared(vm->root.bo->tbo.base.resv, 1); |
| 1249 | if (ret) | 1236 | if (ret) |
| 1250 | goto reserve_shared_fail; | 1237 | goto reserve_shared_fail; |
| 1251 | amdgpu_bo_fence(vm->root.base.bo, | 1238 | amdgpu_bo_fence(vm->root.bo, |
| 1252 | &vm->process_info->eviction_fence->base, true); | 1239 | &vm->process_info->eviction_fence->base, true); |
| 1253 | amdgpu_bo_unreserve(vm->root.base.bo); | 1240 | amdgpu_bo_unreserve(vm->root.bo); |
| 1254 | 1241 | ||
| 1255 | /* Update process info */ | 1242 | /* Update process info */ |
| 1256 | mutex_lock(&vm->process_info->lock); | 1243 | mutex_lock(&vm->process_info->lock); |
| @@ -1264,7 +1251,7 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info, · 7 unmodified lines | |||
| 1264 | reserve_shared_fail: | 1251 | reserve_shared_fail: |
| 1265 | wait_pd_fail: | 1252 | wait_pd_fail: |
| 1266 | validate_pd_fail: | 1253 | validate_pd_fail: |
| 1267 | amdgpu_bo_unreserve(vm->root.base.bo); | 1254 | amdgpu_bo_unreserve(vm->root.bo); |
| 1268 | reserve_pd_fail: | 1255 | reserve_pd_fail: |
| 1269 | vm->process_info = NULL; | 1256 | vm->process_info = NULL; |
| 1270 | if (info) { | 1257 | if (info) { |
| @@ -1319,7 +1306,7 @@ void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev, · 48 unmodified lines | |||
| 1319 | struct amdgpu_vm *vm) | 1306 | struct amdgpu_vm *vm) |
| 1320 | { | 1307 | { |
| 1321 | struct amdkfd_process_info *process_info = vm->process_info; | 1308 | struct amdkfd_process_info *process_info = vm->process_info; |
| 1322 | struct amdgpu_bo *pd = vm->root.base.bo; | 1309 | struct amdgpu_bo *pd = vm->root.bo; |
| 1323 | 1310 | ||
| 1324 | if (!process_info) | 1311 | if (!process_info) |
| 1325 | return; | 1312 | return; |
| @@ -1375,7 +1362,7 @@ void amdgpu_amdkfd_gpuvm_release_process_vm(struct kgd_dev *kgd, void *drm_priv) · 49 unmodified lines | |||
| 1375 | uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *drm_priv) | 1362 | uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *drm_priv) |
| 1376 | { | 1363 | { |
| 1377 | struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv); | 1364 | struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv); |
| 1378 | struct amdgpu_bo *pd = avm->root.base.bo; | 1365 | struct amdgpu_bo *pd = avm->root.bo; |
| 1379 | struct amdgpu_device *adev = amdgpu_ttm_adev(pd->tbo.bdev); | 1366 | struct amdgpu_device *adev = amdgpu_ttm_adev(pd->tbo.bdev); |
| 1380 | 1367 | ||
| 1381 | if (adev->asic_type < CHIP_VEGA10) | 1368 | if (adev->asic_type < CHIP_VEGA10) |
| @@ -2402,7 +2389,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef) · 1020 unmodified lines | |||
| 2402 | /* Attach eviction fence to PD / PT BOs */ | 2389 | /* Attach eviction fence to PD / PT BOs */ |
| 2403 | list_for_each_entry(peer_vm, &process_info->vm_list_head, | 2390 | list_for_each_entry(peer_vm, &process_info->vm_list_head, |
| 2404 | vm_list_node) { | 2391 | vm_list_node) { |
| 2405 | struct amdgpu_bo *bo = peer_vm->root.base.bo; | 2392 | struct amdgpu_bo *bo = peer_vm->root.bo; |
| 2406 | 2393 | ||
| 2407 | amdgpu_bo_fence(bo, &process_info->eviction_fence->base, true); | 2394 | amdgpu_bo_fence(bo, &process_info->eviction_fence->base, true); |
| 2408 | } | 2395 | } |
| @@ -832,7 +832,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) · 831 unmodified lines | |||
| 832 | if (r) | 832 | if (r) |
| 833 | return r; | 833 | return r; |
| 834 | 834 | ||
| 835 | p->job->vm_pd_addr = amdgpu_gmc_pd_addr(vm->root.base.bo); | 835 | p->job->vm_pd_addr = amdgpu_gmc_pd_addr(vm->root.bo); |
| 836 | 836 | ||
| 837 | if (amdgpu_vm_debug) { | 837 | if (amdgpu_vm_debug) { |
| 838 | /* Invalidate all BOs to test for userspace bugs */ | 838 | /* Invalidate all BOs to test for userspace bugs */ |
| @@ -1304,11 +1304,11 @@ static int amdgpu_debugfs_vm_info_show(struct seq_file *m, void *unused) · 1303 unmodified lines | |||
| 1304 | 1304 | ||
| 1305 | seq_printf(m, "pid:%d\tProcess:%s ----------\n", | 1305 | seq_printf(m, "pid:%d\tProcess:%s ----------\n", |
| 1306 | vm->task_info.pid, vm->task_info.process_name); | 1306 | vm->task_info.pid, vm->task_info.process_name); |
| 1307 | r = amdgpu_bo_reserve(vm->root.base.bo, true); | 1307 | r = amdgpu_bo_reserve(vm->root.bo, true); |
| 1308 | if (r) | 1308 | if (r) |
| 1309 | break; | 1309 | break; |
| 1310 | amdgpu_debugfs_vm_bo_info(vm, m); | 1310 | amdgpu_debugfs_vm_bo_info(vm, m); |
| 1311 | amdgpu_bo_unreserve(vm->root.base.bo); | 1311 | amdgpu_bo_unreserve(vm->root.bo); |
| 1312 | } | 1312 | } |
| 1313 | 1313 | ||
| 1314 | mutex_unlock(&dev->filelist_mutex); | 1314 | mutex_unlock(&dev->filelist_mutex); |
| @@ -4124,6 +4124,7 @@ static int amdgpu_device_recover_vram(struct amdgpu_device *adev) · 4123 unmodified lines | |||
| 4124 | { | 4124 | { |
| 4125 | struct dma_fence *fence = NULL, *next = NULL; | 4125 | struct dma_fence *fence = NULL, *next = NULL; |
| 4126 | struct amdgpu_bo *shadow; | 4126 | struct amdgpu_bo *shadow; |
| 4127 | struct amdgpu_bo_vm *vmbo; | ||
| 4127 | long r = 1, tmo; | 4128 | long r = 1, tmo; |
| 4128 | 4129 | ||
| 4129 | if (amdgpu_sriov_runtime(adev)) | 4130 | if (amdgpu_sriov_runtime(adev)) |
| @@ -4133,8 +4134,8 @@ static int amdgpu_device_recover_vram(struct amdgpu_device *adev) · 3 unmodified lines | |||
| 4133 | 4134 | ||
| 4134 | dev_info(adev->dev, "recover vram bo from shadow start\n"); | 4135 | dev_info(adev->dev, "recover vram bo from shadow start\n"); |
| 4135 | mutex_lock(&adev->shadow_list_lock); | 4136 | mutex_lock(&adev->shadow_list_lock); |
| 4136 | list_for_each_entry(shadow, &adev->shadow_list, shadow_list) { | 4137 | list_for_each_entry(vmbo, &adev->shadow_list, shadow_list) { |
| 4137 | 4138 | shadow = &vmbo->bo; | |
| 4138 | /* No need to recover an evicted BO */ | 4139 | /* No need to recover an evicted BO */ |
| 4139 | if (shadow->tbo.resource->mem_type != TTM_PL_TT || | 4140 | if (shadow->tbo.resource->mem_type != TTM_PL_TT || |
| 4140 | shadow->tbo.resource->start == AMDGPU_BO_INVALID_OFFSET || | 4141 | shadow->tbo.resource->start == AMDGPU_BO_INVALID_OFFSET || |
| @@ -325,7 +325,7 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev) · 324 unmodified lines | |||
| 325 | return 0; | 325 | return 0; |
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, | 328 | int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, int number_instance, |
| 329 | int *major, int *minor, int *revision) | 329 | int *major, int *minor, int *revision) |
| 330 | { | 330 | { |
| 331 | struct binary_header *bhdr; | 331 | struct binary_header *bhdr; |
| @@ -357,7 +357,7 @@ int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, · 25 unmodified lines | |||
| 357 | for (j = 0; j < num_ips; j++) { | 357 | for (j = 0; j < num_ips; j++) { |
| 358 | ip = (struct ip *)(adev->mman.discovery_bin + ip_offset); | 358 | ip = (struct ip *)(adev->mman.discovery_bin + ip_offset); |
| 359 | 359 | ||
| 360 | if (le16_to_cpu(ip->hw_id) == hw_id) { | 360 | if ((le16_to_cpu(ip->hw_id) == hw_id) && (ip->number_instance == number_instance)) { |
| 361 | if (major) | 361 | if (major) |
| 362 | *major = ip->major; | 362 | *major = ip->major; |
| 363 | if (minor) | 363 | if (minor) |
| @@ -30,7 +30,7 @@ · 29 unmodified lines | |||
| 30 | void amdgpu_discovery_fini(struct amdgpu_device *adev); | 30 | void amdgpu_discovery_fini(struct amdgpu_device *adev); |
| 31 | int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev); | 31 | int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev); |
| 32 | void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev); | 32 | void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev); |
| 33 | int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, | 33 | int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, int number_instance, |
| 34 | int *major, int *minor, int *revision); | 34 | int *major, int *minor, int *revision); |
| 35 | int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev); | 35 | int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev); |
| 36 | 36 | ||
| @@ -448,7 +448,7 @@ amdgpu_dma_buf_move_notify(struct dma_buf_attachment *attach) · 447 unmodified lines | |||
| 448 | 448 | ||
| 449 | for (bo_base = bo->vm_bo; bo_base; bo_base = bo_base->next) { | 449 | for (bo_base = bo->vm_bo; bo_base; bo_base = bo_base->next) { |
| 450 | struct amdgpu_vm *vm = bo_base->vm; | 450 | struct amdgpu_vm *vm = bo_base->vm; |
| 451 | struct dma_resv *resv = vm->root.base.bo->tbo.base.resv; | 451 | struct dma_resv *resv = vm->root.bo->tbo.base.resv; |
| 452 | 452 | ||
| 453 | if (ticket) { | 453 | if (ticket) { |
| 454 | /* When we get an error here it means that somebody | 454 | /* When we get an error here it means that somebody |
| @@ -69,13 +69,13 @@ void amdgpu_show_fdinfo(struct seq_file *m, struct file *f) · 68 unmodified lines | |||
| 69 | dev = PCI_SLOT(adev->pdev->devfn); | 69 | dev = PCI_SLOT(adev->pdev->devfn); |
| 70 | fn = PCI_FUNC(adev->pdev->devfn); | 70 | fn = PCI_FUNC(adev->pdev->devfn); |
| 71 | 71 | ||
| 72 | ret = amdgpu_bo_reserve(fpriv->vm.root.base.bo, false); | 72 | ret = amdgpu_bo_reserve(fpriv->vm.root.bo, false); |
| 73 | if (ret) { | 73 | if (ret) { |
| 74 | DRM_ERROR("Fail to reserve bo\n"); | 74 | DRM_ERROR("Fail to reserve bo\n"); |
| 75 | return; | 75 | return; |
| 76 | } | 76 | } |
| 77 | amdgpu_vm_get_memory(&fpriv->vm, &vram_mem, >t_mem, &cpu_mem); | 77 | amdgpu_vm_get_memory(&fpriv->vm, &vram_mem, >t_mem, &cpu_mem); |
| 78 | amdgpu_bo_unreserve(fpriv->vm.root.base.bo); | 78 | amdgpu_bo_unreserve(fpriv->vm.root.bo); |
| 79 | seq_printf(m, "pdev:\t%04x:%02x:%02x.%d\npasid:\t%u\n", domain, bus, | 79 | seq_printf(m, "pdev:\t%04x:%02x:%02x.%d\npasid:\t%u\n", domain, bus, |
| 80 | dev, fn, fpriv->vm.pasid); | 80 | dev, fn, fpriv->vm.pasid); |
| 81 | seq_printf(m, "vram mem:\t%llu kB\n", vram_mem/1024UL); | 81 | seq_printf(m, "vram mem:\t%llu kB\n", vram_mem/1024UL); |
| @@ -170,7 +170,7 @@ static int amdgpu_gem_object_open(struct drm_gem_object *obj, · 169 unmodified lines | |||
| 170 | return -EPERM; | 170 | return -EPERM; |
| 171 | 171 | ||
| 172 | if (abo->flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID && | 172 | if (abo->flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID && |
| 173 | abo->tbo.base.resv != vm->root.base.bo->tbo.base.resv) | 173 | abo->tbo.base.resv != vm->root.bo->tbo.base.resv) |
| 174 | return -EPERM; | 174 | return -EPERM; |
| 175 | 175 | ||
| 176 | r = amdgpu_bo_reserve(abo, false); | 176 | r = amdgpu_bo_reserve(abo, false); |
| @@ -320,11 +320,11 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data, · 143 unmodified lines | |||
| 320 | } | 320 | } |
| 321 | 321 | ||
| 322 | if (flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID) { | 322 | if (flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID) { |
| 323 | r = amdgpu_bo_reserve(vm->root.base.bo, false); | 323 | r = amdgpu_bo_reserve(vm->root.bo, false); |
| 324 | if (r) | 324 | if (r) |
| 325 | return r; | 325 | return r; |
| 326 | 326 | ||
| 327 | resv = vm->root.base.bo->tbo.base.resv; | 327 | resv = vm->root.bo->tbo.base.resv; |
| 328 | } | 328 | } |
| 329 | 329 | ||
| 330 | initial_domain = (u32)(0xffffffff & args->in.domains); | 330 | initial_domain = (u32)(0xffffffff & args->in.domains); |
| @@ -353,9 +353,9 @@ retry: · 22 unmodified lines | |||
| 353 | if (!r) { | 353 | if (!r) { |
| 354 | struct amdgpu_bo *abo = gem_to_amdgpu_bo(gobj); | 354 | struct amdgpu_bo *abo = gem_to_amdgpu_bo(gobj); |
| 355 | 355 | ||
| 356 | abo->parent = amdgpu_bo_ref(vm->root.base.bo); | 356 | abo->parent = amdgpu_bo_ref(vm->root.bo); |
| 357 | } | 357 | } |
| 358 | amdgpu_bo_unreserve(vm->root.base.bo); | 358 | amdgpu_bo_unreserve(vm->root.bo); |
| 359 | } | 359 | } |
| 360 | if (r) | 360 | if (r) |
| 361 | return r; | 361 | return r; |
| @@ -841,7 +841,7 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data, · 479 unmodified lines | |||
| 841 | } | 841 | } |
| 842 | for (base = robj->vm_bo; base; base = base->next) | 842 | for (base = robj->vm_bo; base; base = base->next) |
| 843 | if (amdgpu_xgmi_same_hive(amdgpu_ttm_adev(robj->tbo.bdev), | 843 | if (amdgpu_xgmi_same_hive(amdgpu_ttm_adev(robj->tbo.bdev), |
| 844 | amdgpu_ttm_adev(base->vm->root.base.bo->tbo.bdev))) { | 844 | amdgpu_ttm_adev(base->vm->root.bo->tbo.bdev))) { |
| 845 | r = -EINVAL; | 845 | r = -EINVAL; |
| 846 | amdgpu_bo_unreserve(robj); | 846 | amdgpu_bo_unreserve(robj); |
| 847 | goto out; | 847 | goto out; |
| @@ -124,6 +124,22 @@ void amdgpu_register_gpu_instance(struct amdgpu_device *adev) · 123 unmodified lines | |||
| 124 | mutex_unlock(&mgpu_info.mutex); | 124 | mutex_unlock(&mgpu_info.mutex); |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | static void amdgpu_get_audio_func(struct amdgpu_device *adev) | ||
| 128 | { | ||
| 129 | struct pci_dev *p = NULL; | ||
| 130 | |||
| 131 | p = pci_get_domain_bus_and_slot(pci_domain_nr(adev->pdev->bus), | ||
| 132 | adev->pdev->bus->number, 1); | ||
| 133 | if (p) { | ||
| 134 | pm_runtime_get_sync(&p->dev); | ||
| 135 | |||
| 136 | pm_runtime_mark_last_busy(&p->dev); | ||
| 137 | pm_runtime_put_autosuspend(&p->dev); | ||
| 138 | |||
| 139 | pci_dev_put(p); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 127 | /** | 143 | /** |
| 128 | * amdgpu_driver_load_kms - Main load function for KMS. | 144 | * amdgpu_driver_load_kms - Main load function for KMS. |
| 129 | * | 145 | * |
| @@ -213,9 +229,35 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags) · 83 unmodified lines | |||
| 213 | DPM_FLAG_MAY_SKIP_RESUME); | 229 | DPM_FLAG_MAY_SKIP_RESUME); |
| 214 | pm_runtime_use_autosuspend(dev->dev); | 230 | pm_runtime_use_autosuspend(dev->dev); |
| 215 | pm_runtime_set_autosuspend_delay(dev->dev, 5000); | 231 | pm_runtime_set_autosuspend_delay(dev->dev, 5000); |
| 232 | |||
| 216 | pm_runtime_allow(dev->dev); | 233 | pm_runtime_allow(dev->dev); |
| 234 | |||
| 217 | pm_runtime_mark_last_busy(dev->dev); | 235 | pm_runtime_mark_last_busy(dev->dev); |
| 218 | pm_runtime_put_autosuspend(dev->dev); | 236 | pm_runtime_put_autosuspend(dev->dev); |
| 237 | |||
| 238 | /* | ||
| 239 | * For runpm implemented via BACO, PMFW will handle the | ||
| 240 | * timing for BACO in and out: | ||
| 241 | * - put ASIC into BACO state only when both video and | ||
| 242 | * audio functions are in D3 state. | ||
| 243 | * - pull ASIC out of BACO state when either video or | ||
| 244 | * audio function is in D0 state. | ||
| 245 | * Also, at startup, PMFW assumes both functions are in | ||
| 246 | * D0 state. | ||
| 247 | * | ||
| 248 | * So if snd driver was loaded prior to amdgpu driver | ||
| 249 | * and audio function was put into D3 state, there will | ||
| 250 | * be no PMFW-aware D-state transition(D0->D3) on runpm | ||
| 251 | * suspend. Thus the BACO will be not correctly kicked in. | ||
| 252 | * | ||
| 253 | * Via amdgpu_get_audio_func(), the audio dev is put | ||
| 254 | * into D0 state. Then there will be a PMFW-aware D-state | ||
| 255 | * transition(D0->D3) on runpm suspend. | ||
| 256 | */ | ||
| 257 | if (amdgpu_device_supports_baco(dev) && | ||
| 258 | !(adev->flags & AMD_IS_APU) && | ||
| 259 | (adev->asic_type >= CHIP_NAVI10)) | ||
| 260 | amdgpu_get_audio_func(adev); | ||
| 219 | } | 261 | } |
| 220 | 262 | ||
| 221 | if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DRV_LOAD)) | 263 | if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DRV_LOAD)) |
| @@ -1220,7 +1262,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, · 998 unmodified lines | |||
| 1220 | } | 1262 | } |
| 1221 | 1263 | ||
| 1222 | pasid = fpriv->vm.pasid; | 1264 | pasid = fpriv->vm.pasid; |
| 1223 | pd = amdgpu_bo_ref(fpriv->vm.root.base.bo); | 1265 | pd = amdgpu_bo_ref(fpriv->vm.root.bo); |
| 1224 | 1266 | ||
| 1225 | amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr); | 1267 | amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr); |
| 1226 | amdgpu_vm_fini(adev, &fpriv->vm); | 1268 | amdgpu_vm_fini(adev, &fpriv->vm); |
| @@ -54,29 +54,42 @@ · 53 unmodified lines | |||
| 54 | 54 | ||
| 55 | static void amdgpu_bo_destroy(struct ttm_buffer_object *tbo) | 55 | static void amdgpu_bo_destroy(struct ttm_buffer_object *tbo) |
| 56 | { | 56 | { |
| 57 | struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev); | ||
| 58 | struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo); | 57 | struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo); |
| 59 | struct amdgpu_bo_user *ubo; | ||
| 60 | 58 | ||
| 61 | amdgpu_bo_kunmap(bo); | 59 | amdgpu_bo_kunmap(bo); |
| 62 | 60 | ||
| 63 | if (bo->tbo.base.import_attach) | 61 | if (bo->tbo.base.import_attach) |
| 64 | drm_prime_gem_destroy(&bo->tbo.base, bo->tbo.sg); | 62 | drm_prime_gem_destroy(&bo->tbo.base, bo->tbo.sg); |
| 65 | drm_gem_object_release(&bo->tbo.base); | 63 | drm_gem_object_release(&bo->tbo.base); |
| 64 | amdgpu_bo_unref(&bo->parent); | ||
| 65 | kvfree(bo); | ||
| 66 | } | ||
| 67 | |||
| 68 | static void amdgpu_bo_user_destroy(struct ttm_buffer_object *tbo) | ||
| 69 | { | ||
| 70 | struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo); | ||
| 71 | struct amdgpu_bo_user *ubo; | ||
| 72 | |||
| 73 | ubo = to_amdgpu_bo_user(bo); | ||
| 74 | kfree(ubo->metadata); | ||
| 75 | amdgpu_bo_destroy(tbo); | ||
| 76 | } | ||
| 77 | |||
| 78 | static void amdgpu_bo_vm_destroy(struct ttm_buffer_object *tbo) | ||
| 79 | { | ||
| 80 | struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev); | ||
| 81 | struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo); | ||
| 82 | struct amdgpu_bo_vm *vmbo; | ||
| 83 | |||
| 84 | vmbo = to_amdgpu_bo_vm(bo); | ||
| 66 | /* in case amdgpu_device_recover_vram got NULL of bo->parent */ | 85 | /* in case amdgpu_device_recover_vram got NULL of bo->parent */ |
| 67 | if (!list_empty(&bo->shadow_list)) { | 86 | if (!list_empty(&vmbo->shadow_list)) { |
| 68 | mutex_lock(&adev->shadow_list_lock); | 87 | mutex_lock(&adev->shadow_list_lock); |
| 69 | list_del_init(&bo->shadow_list); | 88 | list_del_init(&vmbo->shadow_list); |
| 70 | mutex_unlock(&adev->shadow_list_lock); | 89 | mutex_unlock(&adev->shadow_list_lock); |
| 71 | } | 90 | } |
| 72 | amdgpu_bo_unref(&bo->parent); | ||
| 73 | |||
| 74 | if (bo->tbo.type != ttm_bo_type_kernel) { | ||
| 75 | ubo = to_amdgpu_bo_user(bo); | ||
| 76 | kfree(ubo->metadata); | ||
| 77 | } | ||
| 78 | 91 | ||
| 79 | kvfree(bo); | 92 | amdgpu_bo_destroy(tbo); |
| 80 | } | 93 | } |
| 81 | 94 | ||
| 82 | /** | 95 | /** |
| @@ -91,8 +104,11 @@ static void amdgpu_bo_destroy(struct ttm_buffer_object *tbo) · 8 unmodified lines | |||
| 91 | */ | 104 | */ |
| 92 | bool amdgpu_bo_is_amdgpu_bo(struct ttm_buffer_object *bo) | 105 | bool amdgpu_bo_is_amdgpu_bo(struct ttm_buffer_object *bo) |
| 93 | { | 106 | { |
| 94 | if (bo->destroy == &amdgpu_bo_destroy) | 107 | if (bo->destroy == &amdgpu_bo_destroy || |
| 108 | bo->destroy == &amdgpu_bo_user_destroy || | ||
| 109 | bo->destroy == &amdgpu_bo_vm_destroy) | ||
| 95 | return true; | 110 | return true; |
| 111 | |||
| 96 | return false; | 112 | return false; |
| 97 | } | 113 | } |
| 98 | 114 | ||
| @@ -545,7 +561,6 @@ int amdgpu_bo_create(struct amdgpu_device *adev, · 446 unmodified lines | |||
| 545 | if (bo == NULL) | 561 | if (bo == NULL) |
| 546 | return -ENOMEM; | 562 | return -ENOMEM; |
| 547 | drm_gem_private_object_init(adev_to_drm(adev), &bo->tbo.base, size); | 563 | drm_gem_private_object_init(adev_to_drm(adev), &bo->tbo.base, size); |
| 548 | INIT_LIST_HEAD(&bo->shadow_list); | ||
| 549 | bo->vm_bo = NULL; | 564 | bo->vm_bo = NULL; |
| 550 | bo->preferred_domains = bp->preferred_domain ? bp->preferred_domain : | 565 | bo->preferred_domains = bp->preferred_domain ? bp->preferred_domain : |
| 551 | bp->domain; | 566 | bp->domain; |
| @@ -568,9 +583,12 @@ int amdgpu_bo_create(struct amdgpu_device *adev, · 16 unmodified lines | |||
| 568 | if (bp->type == ttm_bo_type_kernel) | 583 | if (bp->type == ttm_bo_type_kernel) |
| 569 | bo->tbo.priority = 1; | 584 | bo->tbo.priority = 1; |
| 570 | 585 | ||
| 586 | if (!bp->destroy) | ||
| 587 | bp->destroy = &amdgpu_bo_destroy; | ||
| 588 | |||
| 571 | r = ttm_bo_init_reserved(&adev->mman.bdev, &bo->tbo, size, bp->type, | 589 | r = ttm_bo_init_reserved(&adev->mman.bdev, &bo->tbo, size, bp->type, |
| 572 | &bo->placement, page_align, &ctx, NULL, | 590 | &bo->placement, page_align, &ctx, NULL, |
| 573 | bp->resv, &amdgpu_bo_destroy); | 591 | bp->resv, bp->destroy); |
| 574 | if (unlikely(r != 0)) | 592 | if (unlikely(r != 0)) |
| 575 | return r; | 593 | return r; |
| 576 | 594 | ||
| @@ -634,6 +652,7 @@ int amdgpu_bo_create_user(struct amdgpu_device *adev, · 57 unmodified lines | |||
| 634 | int r; | 652 | int r; |
| 635 | 653 | ||
| 636 | bp->bo_ptr_size = sizeof(struct amdgpu_bo_user); | 654 | bp->bo_ptr_size = sizeof(struct amdgpu_bo_user); |
| 655 | bp->destroy = &amdgpu_bo_user_destroy; | ||
| 637 | r = amdgpu_bo_create(adev, bp, &bo_ptr); | 656 | r = amdgpu_bo_create(adev, bp, &bo_ptr); |
| 638 | if (r) | 657 | if (r) |
| 639 | return r; | 658 | return r; |
| @@ -665,11 +684,13 @@ int amdgpu_bo_create_vm(struct amdgpu_device *adev, · 25 unmodified lines | |||
| 665 | * num of amdgpu_vm_pt entries. | 684 | * num of amdgpu_vm_pt entries. |
| 666 | */ | 685 | */ |
| 667 | BUG_ON(bp->bo_ptr_size < sizeof(struct amdgpu_bo_vm)); | 686 | BUG_ON(bp->bo_ptr_size < sizeof(struct amdgpu_bo_vm)); |
| 687 | bp->destroy = &amdgpu_bo_vm_destroy; | ||
| 668 | r = amdgpu_bo_create(adev, bp, &bo_ptr); | 688 | r = amdgpu_bo_create(adev, bp, &bo_ptr); |
| 669 | if (r) | 689 | if (r) |
| 670 | return r; | 690 | return r; |
| 671 | 691 | ||
| 672 | *vmbo_ptr = to_amdgpu_bo_vm(bo_ptr); | 692 | *vmbo_ptr = to_amdgpu_bo_vm(bo_ptr); |
| 693 | INIT_LIST_HEAD(&(*vmbo_ptr)->shadow_list); | ||
| 673 | return r; | 694 | return r; |
| 674 | } | 695 | } |
| 675 | 696 | ||
| @@ -714,12 +735,12 @@ retry: · 38 unmodified lines | |||
| 714 | * | 735 | * |
| 715 | * Insert a BO to the shadow list. | 736 | * Insert a BO to the shadow list. |
| 716 | */ | 737 | */ |
| 717 | void amdgpu_bo_add_to_shadow_list(struct amdgpu_bo *bo) | 738 | void amdgpu_bo_add_to_shadow_list(struct amdgpu_bo_vm *vmbo) |
| 718 | { | 739 | { |
| 719 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); | 740 | struct amdgpu_device *adev = amdgpu_ttm_adev(vmbo->bo.tbo.bdev); |
| 720 | 741 | ||
| 721 | mutex_lock(&adev->shadow_list_lock); | 742 | mutex_lock(&adev->shadow_list_lock); |
| 722 | list_add_tail(&bo->shadow_list, &adev->shadow_list); | 743 | list_add_tail(&vmbo->shadow_list, &adev->shadow_list); |
| 723 | mutex_unlock(&adev->shadow_list_lock); | 744 | mutex_unlock(&adev->shadow_list_lock); |
| 724 | } | 745 | } |
| 725 | 746 | ||
| @@ -55,7 +55,8 @@ struct amdgpu_bo_param { · 54 unmodified lines | |||
| 55 | u64 flags; | 55 | u64 flags; |
| 56 | enum ttm_bo_type type; | 56 | enum ttm_bo_type type; |
| 57 | bool no_wait_gpu; | 57 | bool no_wait_gpu; |
| 58 | struct dma_resv *resv; | 58 | struct dma_resv *resv; |
| 59 | void (*destroy)(struct ttm_buffer_object *bo); | ||
| 59 | }; | 60 | }; |
| 60 | 61 | ||
| 61 | /* bo virtual addresses in a vm */ | 62 | /* bo virtual addresses in a vm */ |
| @@ -108,9 +109,6 @@ struct amdgpu_bo { · 46 unmodified lines | |||
| 108 | #ifdef CONFIG_MMU_NOTIFIER | 109 | #ifdef CONFIG_MMU_NOTIFIER |
| 109 | struct mmu_interval_notifier notifier; | 110 | struct mmu_interval_notifier notifier; |
| 110 | #endif | 111 | #endif |
| 111 | |||
| 112 | struct list_head shadow_list; | ||
| 113 | |||
| 114 | struct kgd_mem *kfd_bo; | 112 | struct kgd_mem *kfd_bo; |
| 115 | }; | 113 | }; |
| 116 | 114 | ||
| @@ -126,7 +124,8 @@ struct amdgpu_bo_user { · 9 unmodified lines | |||
| 126 | struct amdgpu_bo_vm { | 124 | struct amdgpu_bo_vm { |
| 127 | struct amdgpu_bo bo; | 125 | struct amdgpu_bo bo; |
| 128 | struct amdgpu_bo *shadow; | 126 | struct amdgpu_bo *shadow; |
| 129 | struct amdgpu_vm_pt entries[]; | 127 | struct list_head shadow_list; |
| 128 | struct amdgpu_vm_bo_base entries[]; | ||
| 130 | }; | 129 | }; |
| 131 | 130 | ||
| 132 | static inline struct amdgpu_bo *ttm_to_amdgpu_bo(struct ttm_buffer_object *tbo) | 131 | static inline struct amdgpu_bo *ttm_to_amdgpu_bo(struct ttm_buffer_object *tbo) |
| @@ -332,7 +331,7 @@ u64 amdgpu_bo_gpu_offset_no_check(struct amdgpu_bo *bo); · 199 unmodified lines | |||
| 332 | int amdgpu_bo_validate(struct amdgpu_bo *bo); | 331 | int amdgpu_bo_validate(struct amdgpu_bo *bo); |
| 333 | void amdgpu_bo_get_memory(struct amdgpu_bo *bo, uint64_t *vram_mem, | 332 | void amdgpu_bo_get_memory(struct amdgpu_bo *bo, uint64_t *vram_mem, |
| 334 | uint64_t *gtt_mem, uint64_t *cpu_mem); | 333 | uint64_t *gtt_mem, uint64_t *cpu_mem); |
| 335 | void amdgpu_bo_add_to_shadow_list(struct amdgpu_bo *bo); | 334 | void amdgpu_bo_add_to_shadow_list(struct amdgpu_bo_vm *vmbo); |
| 336 | int amdgpu_bo_restore_shadow(struct amdgpu_bo *shadow, | 335 | int amdgpu_bo_restore_shadow(struct amdgpu_bo *shadow, |
| 337 | struct dma_fence **fence); | 336 | struct dma_fence **fence); |
| 338 | uint32_t amdgpu_bo_get_preferred_pin_domain(struct amdgpu_device *adev, | 337 | uint32_t amdgpu_bo_get_preferred_pin_domain(struct amdgpu_device *adev, |
| @@ -171,11 +171,81 @@ Err_out: · 170 unmodified lines | |||
| 171 | return ret; | 171 | return ret; |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | /* | ||
| 175 | * Helper funciton to query psp runtime database entry | ||
| 176 | * | ||
| 177 | * @adev: amdgpu_device pointer | ||
| 178 | * @entry_type: the type of psp runtime database entry | ||
| 179 | * @db_entry: runtime database entry pointer | ||
| 180 | * | ||
| 181 | * Return false if runtime database doesn't exit or entry is invalid | ||
| 182 | * or true if the specific database entry is found, and copy to @db_entry | ||
| 183 | */ | ||
| 184 | static bool psp_get_runtime_db_entry(struct amdgpu_device *adev, | ||
| 185 | enum psp_runtime_entry_type entry_type, | ||
| 186 | void *db_entry) | ||
| 187 | { | ||
| 188 | uint64_t db_header_pos, db_dir_pos; | ||
| 189 | struct psp_runtime_data_header db_header = {0}; | ||
| 190 | struct psp_runtime_data_directory db_dir = {0}; | ||
| 191 | bool ret = false; | ||
| 192 | int i; | ||
| 193 | |||
| 194 | db_header_pos = adev->gmc.mc_vram_size - PSP_RUNTIME_DB_OFFSET; | ||
| 195 | db_dir_pos = db_header_pos + sizeof(struct psp_runtime_data_header); | ||
| 196 | |||
| 197 | /* read runtime db header from vram */ | ||
| 198 | amdgpu_device_vram_access(adev, db_header_pos, (uint32_t *)&db_header, | ||
| 199 | sizeof(struct psp_runtime_data_header), false); | ||
| 200 | |||
| 201 | if (db_header.cookie != PSP_RUNTIME_DB_COOKIE_ID) { | ||
| 202 | /* runtime db doesn't exist, exit */ | ||
| 203 | dev_warn(adev->dev, "PSP runtime database doesn't exist\n"); | ||
| 204 | return false; | ||
| 205 | } | ||
| 206 | |||
| 207 | /* read runtime database entry from vram */ | ||
| 208 | amdgpu_device_vram_access(adev, db_dir_pos, (uint32_t *)&db_dir, | ||
| 209 | sizeof(struct psp_runtime_data_directory), false); | ||
| 210 | |||
| 211 | if (db_dir.entry_count >= PSP_RUNTIME_DB_DIAG_ENTRY_MAX_COUNT) { | ||
| 212 | /* invalid db entry count, exit */ | ||
| 213 | dev_warn(adev->dev, "Invalid PSP runtime database entry count\n"); | ||
| 214 | return false; | ||
| 215 | } | ||
| 216 | |||
| 217 | /* look up for requested entry type */ | ||
| 218 | for (i = 0; i < db_dir.entry_count && !ret; i++) { | ||
| 219 | if (db_dir.entry_list[i].entry_type == entry_type) { | ||
| 220 | switch (entry_type) { | ||
| 221 | case PSP_RUNTIME_ENTRY_TYPE_BOOT_CONFIG: | ||
| 222 | if (db_dir.entry_list[i].size < sizeof(struct psp_runtime_boot_cfg_entry)) { | ||
| 223 | /* invalid db entry size */ | ||
| 224 | dev_warn(adev->dev, "Invalid PSP runtime database entry size\n"); | ||
| 225 | return false; | ||
| 226 | } | ||
| 227 | /* read runtime database entry */ | ||
| 228 | amdgpu_device_vram_access(adev, db_header_pos + db_dir.entry_list[i].offset, | ||
| 229 | (uint32_t *)db_entry, sizeof(struct psp_runtime_boot_cfg_entry), false); | ||
| 230 | ret = true; | ||
| 231 | break; | ||
| 232 | default: | ||
| 233 | ret = false; | ||
| 234 | break; | ||
| 235 | } | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | return ret; | ||
| 240 | } | ||
| 241 | |||
| 174 | static int psp_sw_init(void *handle) | 242 | static int psp_sw_init(void *handle) |
| 175 | { | 243 | { |
| 176 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 244 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 177 | struct psp_context *psp = &adev->psp; | 245 | struct psp_context *psp = &adev->psp; |
| 178 | int ret; | 246 | int ret; |
| 247 | struct psp_runtime_boot_cfg_entry boot_cfg_entry; | ||
| 248 | struct psp_memory_training_context *mem_training_ctx = &psp->mem_train_ctx; | ||
| 179 | 249 | ||
| 180 | if (!amdgpu_sriov_vf(adev)) { | 250 | if (!amdgpu_sriov_vf(adev)) { |
| 181 | ret = psp_init_microcode(psp); | 251 | ret = psp_init_microcode(psp); |
| @@ -191,15 +261,39 @@ static int psp_sw_init(void *handle) · 9 unmodified lines | |||
| 191 | } | 261 | } |
| 192 | } | 262 | } |
| 193 | 263 | ||
| 194 | ret = psp_memory_training_init(psp); | 264 | memset(&boot_cfg_entry, 0, sizeof(boot_cfg_entry)); |
| 195 | if (ret) { | 265 | if (psp_get_runtime_db_entry(adev, |
| 196 | DRM_ERROR("Failed to initialize memory training!\n"); | 266 | PSP_RUNTIME_ENTRY_TYPE_BOOT_CONFIG, |
| 197 | return ret; | 267 | &boot_cfg_entry)) { |
| 268 | psp->boot_cfg_bitmask = boot_cfg_entry.boot_cfg_bitmask; | ||
| 269 | if ((psp->boot_cfg_bitmask) & | ||
| 270 | BOOT_CFG_FEATURE_TWO_STAGE_DRAM_TRAINING) { | ||
| 271 | /* If psp runtime database exists, then | ||
| 272 | * only enable two stage memory training | ||
| 273 | * when TWO_STAGE_DRAM_TRAINING bit is set | ||
| 274 | * in runtime database */ | ||
| 275 | mem_training_ctx->enable_mem_training = true; | ||
| 276 | } | ||
| 277 | |||
| 278 | } else { | ||
| 279 | /* If psp runtime database doesn't exist or | ||
| 280 | * is invalid, force enable two stage memory | ||
| 281 | * training */ | ||
| 282 | mem_training_ctx->enable_mem_training = true; | ||
| 198 | } | 283 | } |
| 199 | ret = psp_mem_training(psp, PSP_MEM_TRAIN_COLD_BOOT); | 284 | |
| 200 | if (ret) { | 285 | if (mem_training_ctx->enable_mem_training) { |
| 201 | DRM_ERROR("Failed to process memory training!\n"); | 286 | ret = psp_memory_training_init(psp); |
| 202 | return ret; | 287 | if (ret) { |
| 288 | DRM_ERROR("Failed to initialize memory training!\n"); | ||
| 289 | return ret; | ||
| 290 | } | ||
| 291 | |||
| 292 | ret = psp_mem_training(psp, PSP_MEM_TRAIN_COLD_BOOT); | ||
| 293 | if (ret) { | ||
| 294 | DRM_ERROR("Failed to process memory training!\n"); | ||
| 295 | return ret; | ||
| 296 | } | ||
| 203 | } | 297 | } |
| 204 | 298 | ||
| 205 | if (adev->asic_type == CHIP_NAVI10 || adev->asic_type == CHIP_SIENNA_CICHLID) { | 299 | if (adev->asic_type == CHIP_NAVI10 || adev->asic_type == CHIP_SIENNA_CICHLID) { |
| @@ -551,7 +645,30 @@ int psp_get_fw_attestation_records_addr(struct psp_context *psp, · 345 unmodified lines | |||
| 551 | return ret; | 645 | return ret; |
| 552 | } | 646 | } |
| 553 | 647 | ||
| 554 | static int psp_boot_config_set(struct amdgpu_device *adev) | 648 | static int psp_boot_config_get(struct amdgpu_device *adev, uint32_t *boot_cfg) |
| 649 | { | ||
| 650 | struct psp_context *psp = &adev->psp; | ||
| 651 | struct psp_gfx_cmd_resp *cmd = psp->cmd; | ||
| 652 | int ret; | ||
| 653 | |||
| 654 | if (amdgpu_sriov_vf(adev)) | ||
| 655 | return 0; | ||
| 656 | |||
| 657 | memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); | ||
| 658 | |||
| 659 | cmd->cmd_id = GFX_CMD_ID_BOOT_CFG; | ||
| 660 | cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_GET; | ||
| 661 | |||
| 662 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); | ||
| 663 | if (!ret) { | ||
| 664 | *boot_cfg = | ||
| 665 | (cmd->resp.uresp.boot_cfg.boot_cfg & BOOT_CONFIG_GECC) ? 1 : 0; | ||
| 666 | } | ||
| 667 | |||
| 668 | return ret; | ||
| 669 | } | ||
| 670 | |||
| 671 | static int psp_boot_config_set(struct amdgpu_device *adev, uint32_t boot_cfg) | ||
| 555 | { | 672 | { |
| 556 | struct psp_context *psp = &adev->psp; | 673 | struct psp_context *psp = &adev->psp; |
| 557 | struct psp_gfx_cmd_resp *cmd = psp->cmd; | 674 | struct psp_gfx_cmd_resp *cmd = psp->cmd; |
| @@ -563,8 +680,8 @@ static int psp_boot_config_set(struct amdgpu_device *adev) · 5 unmodified lines | |||
| 563 | 680 | ||
| 564 | cmd->cmd_id = GFX_CMD_ID_BOOT_CFG; | 681 | cmd->cmd_id = GFX_CMD_ID_BOOT_CFG; |
| 565 | cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_SET; | 682 | cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_SET; |
| 566 | cmd->cmd.boot_cfg.boot_config = BOOT_CONFIG_GECC; | 683 | cmd->cmd.boot_cfg.boot_config = boot_cfg; |
| 567 | cmd->cmd.boot_cfg.boot_config_valid = BOOT_CONFIG_GECC; | 684 | cmd->cmd.boot_cfg.boot_config_valid = boot_cfg; |
| 568 | 685 | ||
| 569 | return psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); | 686 | return psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); |
| 570 | } | 687 | } |
| @@ -1212,19 +1329,62 @@ static int psp_ras_terminate(struct psp_context *psp) · 641 unmodified lines | |||
| 1212 | static int psp_ras_initialize(struct psp_context *psp) | 1329 | static int psp_ras_initialize(struct psp_context *psp) |
| 1213 | { | 1330 | { |
| 1214 | int ret; | 1331 | int ret; |
| 1332 | uint32_t boot_cfg = 0xFF; | ||
| 1333 | struct amdgpu_device *adev = psp->adev; | ||
| 1215 | 1334 | ||
| 1216 | /* | 1335 | /* |
| 1217 | * TODO: bypass the initialize in sriov for now | 1336 | * TODO: bypass the initialize in sriov for now |
| 1218 | */ | 1337 | */ |
| 1219 | if (amdgpu_sriov_vf(psp->adev)) | 1338 | if (amdgpu_sriov_vf(adev)) |
| 1220 | return 0; | 1339 | return 0; |
| 1221 | 1340 | ||
| 1222 | if (!psp->adev->psp.ta_ras_ucode_size || | 1341 | if (!adev->psp.ta_ras_ucode_size || |
| 1223 | !psp->adev->psp.ta_ras_start_addr) { | 1342 | !adev->psp.ta_ras_start_addr) { |
| 1224 | dev_info(psp->adev->dev, "RAS: optional ras ta ucode is not available\n"); | 1343 | dev_info(adev->dev, "RAS: optional ras ta ucode is not available\n"); |
| 1225 | return 0; | 1344 | return 0; |
| 1226 | } | 1345 | } |
| 1227 | 1346 | ||
| 1347 | if (amdgpu_atomfirmware_dynamic_boot_config_supported(adev)) { | ||
| 1348 | /* query GECC enablement status from boot config | ||
| 1349 | * boot_cfg: 1: GECC is enabled or 0: GECC is disabled | ||
| 1350 | */ | ||
| 1351 | ret = psp_boot_config_get(adev, &boot_cfg); | ||
| 1352 | if (ret) | ||
| 1353 | dev_warn(adev->dev, "PSP get boot config failed\n"); | ||
| 1354 | |||
| 1355 | if (!amdgpu_ras_is_supported(psp->adev, AMDGPU_RAS_BLOCK__UMC)) { | ||
| 1356 | if (!boot_cfg) { | ||
| 1357 | dev_info(adev->dev, "GECC is disabled\n"); | ||
| 1358 | } else { | ||
| 1359 | /* disable GECC in next boot cycle if ras is | ||
| 1360 | * disabled by module parameter amdgpu_ras_enable | ||
| 1361 | * and/or amdgpu_ras_mask, or boot_config_get call | ||
| 1362 | * is failed | ||
| 1363 | */ | ||
| 1364 | ret = psp_boot_config_set(adev, 0); | ||
| 1365 | if (ret) | ||
| 1366 | dev_warn(adev->dev, "PSP set boot config failed\n"); | ||
| 1367 | else | ||
| 1368 | dev_warn(adev->dev, "GECC will be disabled in next boot cycle " | ||
| 1369 | "if set amdgpu_ras_enable and/or amdgpu_ras_mask to 0x0\n"); | ||
| 1370 | } | ||
| 1371 | } else { | ||
| 1372 | if (1 == boot_cfg) { | ||
| 1373 | dev_info(adev->dev, "GECC is enabled\n"); | ||
| 1374 | } else { | ||
| 1375 | /* enable GECC in next boot cycle if it is disabled | ||
| 1376 | * in boot config, or force enable GECC if failed to | ||
| 1377 | * get boot configuration | ||
| 1378 | */ | ||
| 1379 | ret = psp_boot_config_set(adev, BOOT_CONFIG_GECC); | ||
| 1380 | if (ret) | ||
| 1381 | dev_warn(adev->dev, "PSP set boot config failed\n"); | ||
| 1382 | else | ||
| 1383 | dev_warn(adev->dev, "GECC will be enabled in next boot cycle\n"); | ||
| 1384 | } | ||
| 1385 | } | ||
| 1386 | } | ||
| 1387 | |||
| 1228 | if (!psp->ras.ras_initialized) { | 1388 | if (!psp->ras.ras_initialized) { |
| 1229 | ret = psp_ras_init_shared_buf(psp); | 1389 | ret = psp_ras_init_shared_buf(psp); |
| 1230 | if (ret) | 1390 | if (ret) |
| @@ -1945,12 +2105,6 @@ static int psp_hw_start(struct psp_context *psp) · 714 unmodified lines | |||
| 1945 | return ret; | 2105 | return ret; |
| 1946 | } | 2106 | } |
| 1947 | 2107 | ||
| 1948 | if (amdgpu_atomfirmware_dynamic_boot_config_supported(adev)) { | ||
| 1949 | ret = psp_boot_config_set(adev); | ||
| 1950 | if (ret) | ||
| 1951 | dev_warn(adev->dev, "PSP set boot config failed\n"); | ||
| 1952 | } | ||
| 1953 | |||
| 1954 | ret = psp_tmr_init(psp); | 2108 | ret = psp_tmr_init(psp); |
| 1955 | if (ret) { | 2109 | if (ret) { |
| 1956 | DRM_ERROR("PSP tmr init failed!\n"); | 2110 | DRM_ERROR("PSP tmr init failed!\n"); |
| @@ -2188,10 +2342,7 @@ static int psp_load_smu_fw(struct psp_context *psp) · 231 unmodified lines | |||
| 2188 | if ((amdgpu_in_reset(adev) && | 2342 | if ((amdgpu_in_reset(adev) && |
| 2189 | ras && adev->ras_enabled && | 2343 | ras && adev->ras_enabled && |
| 2190 | (adev->asic_type == CHIP_ARCTURUS || | 2344 | (adev->asic_type == CHIP_ARCTURUS || |
| 2191 | adev->asic_type == CHIP_VEGA20)) || | 2345 | adev->asic_type == CHIP_VEGA20))) { |
| 2192 | (adev->in_runpm && | ||
| 2193 | adev->asic_type >= CHIP_NAVI10 && | ||
| 2194 | adev->asic_type <= CHIP_NAVI12)) { | ||
| 2195 | ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD); | 2346 | ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD); |
| 2196 | if (ret) { | 2347 | if (ret) { |
| 2197 | DRM_WARN("Failed to set MP1 state prepare for reload\n"); | 2348 | DRM_WARN("Failed to set MP1 state prepare for reload\n"); |
| @@ -2562,10 +2713,12 @@ static int psp_resume(void *handle) · 364 unmodified lines | |||
| 2562 | 2713 | ||
| 2563 | DRM_INFO("PSP is resuming...\n"); | 2714 | DRM_INFO("PSP is resuming...\n"); |
| 2564 | 2715 | ||
| 2565 | ret = psp_mem_training(psp, PSP_MEM_TRAIN_RESUME); | 2716 | if (psp->mem_train_ctx.enable_mem_training) { |
| 2566 | if (ret) { | 2717 | ret = psp_mem_training(psp, PSP_MEM_TRAIN_RESUME); |
| 2567 | DRM_ERROR("Failed to process memory training!\n"); | 2718 | if (ret) { |
| 2568 | return ret; | 2719 | DRM_ERROR("Failed to process memory training!\n"); |
| 2720 | return ret; | ||
| 2721 | } | ||
| 2569 | } | 2722 | } |
| 2570 | 2723 | ||
| 2571 | mutex_lock(&adev->firmware.mutex); | 2724 | mutex_lock(&adev->firmware.mutex); |
| @@ -2749,7 +2902,7 @@ int psp_init_asd_microcode(struct psp_context *psp, · 177 unmodified lines | |||
| 2749 | 2902 | ||
| 2750 | asd_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.asd_fw->data; | 2903 | asd_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.asd_fw->data; |
| 2751 | adev->psp.asd_fw_version = le32_to_cpu(asd_hdr->header.ucode_version); | 2904 | adev->psp.asd_fw_version = le32_to_cpu(asd_hdr->header.ucode_version); |
| 2752 | adev->psp.asd_feature_version = le32_to_cpu(asd_hdr->ucode_feature_version); | 2905 | adev->psp.asd_feature_version = le32_to_cpu(asd_hdr->sos.fw_version); |
| 2753 | adev->psp.asd_ucode_size = le32_to_cpu(asd_hdr->header.ucode_size_bytes); | 2906 | adev->psp.asd_ucode_size = le32_to_cpu(asd_hdr->header.ucode_size_bytes); |
| 2754 | adev->psp.asd_start_addr = (uint8_t *)asd_hdr + | 2907 | adev->psp.asd_start_addr = (uint8_t *)asd_hdr + |
| 2755 | le32_to_cpu(asd_hdr->header.ucode_array_offset_bytes); | 2908 | le32_to_cpu(asd_hdr->header.ucode_array_offset_bytes); |
| @@ -2785,7 +2938,7 @@ int psp_init_toc_microcode(struct psp_context *psp, · 29 unmodified lines | |||
| 2785 | 2938 | ||
| 2786 | toc_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.toc_fw->data; | 2939 | toc_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.toc_fw->data; |
| 2787 | adev->psp.toc_fw_version = le32_to_cpu(toc_hdr->header.ucode_version); | 2940 | adev->psp.toc_fw_version = le32_to_cpu(toc_hdr->header.ucode_version); |
| 2788 | adev->psp.toc_feature_version = le32_to_cpu(toc_hdr->ucode_feature_version); | 2941 | adev->psp.toc_feature_version = le32_to_cpu(toc_hdr->sos.fw_version); |
| 2789 | adev->psp.toc_bin_size = le32_to_cpu(toc_hdr->header.ucode_size_bytes); | 2942 | adev->psp.toc_bin_size = le32_to_cpu(toc_hdr->header.ucode_size_bytes); |
| 2790 | adev->psp.toc_start_addr = (uint8_t *)toc_hdr + | 2943 | adev->psp.toc_start_addr = (uint8_t *)toc_hdr + |
| 2791 | le32_to_cpu(toc_hdr->header.ucode_array_offset_bytes); | 2944 | le32_to_cpu(toc_hdr->header.ucode_array_offset_bytes); |
| @@ -2797,6 +2950,50 @@ out: · 5 unmodified lines | |||
| 2797 | return err; | 2950 | return err; |
| 2798 | } | 2951 | } |
| 2799 | 2952 | ||
| 2953 | static int psp_init_sos_base_fw(struct amdgpu_device *adev) | ||
| 2954 | { | ||
| 2955 | const struct psp_firmware_header_v1_0 *sos_hdr; | ||
| 2956 | const struct psp_firmware_header_v1_3 *sos_hdr_v1_3; | ||
| 2957 | uint8_t *ucode_array_start_addr; | ||
| 2958 | |||
| 2959 | sos_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.sos_fw->data; | ||
| 2960 | ucode_array_start_addr = (uint8_t *)sos_hdr + | ||
| 2961 | le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes); | ||
| 2962 | |||
| 2963 | if (adev->gmc.xgmi.connected_to_cpu || (adev->asic_type != CHIP_ALDEBARAN)) { | ||
| 2964 | adev->psp.sos_fw_version = le32_to_cpu(sos_hdr->header.ucode_version); | ||
| 2965 | adev->psp.sos_feature_version = le32_to_cpu(sos_hdr->sos.fw_version); | ||
| 2966 | |||
| 2967 | adev->psp.sys_bin_size = le32_to_cpu(sos_hdr->sos.offset_bytes); | ||
| 2968 | adev->psp.sys_start_addr = ucode_array_start_addr; | ||
| 2969 | |||
| 2970 | adev->psp.sos_bin_size = le32_to_cpu(sos_hdr->sos.size_bytes); | ||
| 2971 | adev->psp.sos_start_addr = ucode_array_start_addr + | ||
| 2972 | le32_to_cpu(sos_hdr->sos.offset_bytes); | ||
| 2973 | } else { | ||
| 2974 | /* Load alternate PSP SOS FW */ | ||
| 2975 | sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data; | ||
| 2976 | |||
| 2977 | adev->psp.sos_fw_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version); | ||
| 2978 | adev->psp.sos_feature_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version); | ||
| 2979 | |||
| 2980 | adev->psp.sys_bin_size = le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.size_bytes); | ||
| 2981 | adev->psp.sys_start_addr = ucode_array_start_addr + | ||
| 2982 | le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.offset_bytes); | ||
| 2983 | |||
| 2984 | adev->psp.sos_bin_size = le32_to_cpu(sos_hdr_v1_3->sos_aux.size_bytes); | ||
| 2985 | adev->psp.sos_start_addr = ucode_array_start_addr + | ||
| 2986 | le32_to_cpu(sos_hdr_v1_3->sos_aux.offset_bytes); | ||
| 2987 | } | ||
| 2988 | |||
| 2989 | if ((adev->psp.sys_bin_size == 0) || (adev->psp.sos_bin_size == 0)) { | ||
| 2990 | dev_warn(adev->dev, "PSP SOS FW not available"); | ||
| 2991 | return -EINVAL; | ||
| 2992 | } | ||
| 2993 | |||
| 2994 | return 0; | ||
| 2995 | } | ||
| 2996 | |||
| 2800 | int psp_init_sos_microcode(struct psp_context *psp, | 2997 | int psp_init_sos_microcode(struct psp_context *psp, |
| 2801 | const char *chip_name) | 2998 | const char *chip_name) |
| 2802 | { | 2999 | { |
| @@ -2807,6 +3004,7 @@ int psp_init_sos_microcode(struct psp_context *psp, · 4 unmodified lines | |||
| 2807 | const struct psp_firmware_header_v1_2 *sos_hdr_v1_2; | 3004 | const struct psp_firmware_header_v1_2 *sos_hdr_v1_2; |
| 2808 | const struct psp_firmware_header_v1_3 *sos_hdr_v1_3; | 3005 | const struct psp_firmware_header_v1_3 *sos_hdr_v1_3; |
| 2809 | int err = 0; | 3006 | int err = 0; |
| 3007 | uint8_t *ucode_array_start_addr; | ||
| 2810 | 3008 | ||
| 2811 | if (!chip_name) { | 3009 | if (!chip_name) { |
| 2812 | dev_err(adev->dev, "invalid chip name for sos microcode\n"); | 3010 | dev_err(adev->dev, "invalid chip name for sos microcode\n"); |
| @@ -2823,47 +3021,45 @@ int psp_init_sos_microcode(struct psp_context *psp, · 10 unmodified lines | |||
| 2823 | goto out; | 3021 | goto out; |
| 2824 | 3022 | ||
| 2825 | sos_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.sos_fw->data; | 3023 | sos_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.sos_fw->data; |
| 3024 | ucode_array_start_addr = (uint8_t *)sos_hdr + | ||
| 3025 | le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes); | ||
| 2826 | amdgpu_ucode_print_psp_hdr(&sos_hdr->header); | 3026 | amdgpu_ucode_print_psp_hdr(&sos_hdr->header); |
| 2827 | 3027 | ||
| 2828 | switch (sos_hdr->header.header_version_major) { | 3028 | switch (sos_hdr->header.header_version_major) { |
| 2829 | case 1: | 3029 | case 1: |
| 2830 | adev->psp.sos_fw_version = le32_to_cpu(sos_hdr->header.ucode_version); | 3030 | err = psp_init_sos_base_fw(adev); |
| 2831 | adev->psp.sos_feature_version = le32_to_cpu(sos_hdr->ucode_feature_version); | 3031 | if (err) |
| 2832 | adev->psp.sos_bin_size = le32_to_cpu(sos_hdr->sos_size_bytes); | 3032 | goto out; |
| 2833 | adev->psp.sys_bin_size = le32_to_cpu(sos_hdr->sos_offset_bytes); | 3033 | |
| 2834 | adev->psp.sys_start_addr = (uint8_t *)sos_hdr + | ||
| 2835 | le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes); | ||
| 2836 | adev->psp.sos_start_addr = (uint8_t *)adev->psp.sys_start_addr + | ||
| 2837 | le32_to_cpu(sos_hdr->sos_offset_bytes); | ||
| 2838 | if (sos_hdr->header.header_version_minor == 1) { | 3034 | if (sos_hdr->header.header_version_minor == 1) { |
| 2839 | sos_hdr_v1_1 = (const struct psp_firmware_header_v1_1 *)adev->psp.sos_fw->data; | 3035 | sos_hdr_v1_1 = (const struct psp_firmware_header_v1_1 *)adev->psp.sos_fw->data; |
| 2840 | adev->psp.toc_bin_size = le32_to_cpu(sos_hdr_v1_1->toc_size_bytes); | 3036 | adev->psp.toc_bin_size = le32_to_cpu(sos_hdr_v1_1->toc.size_bytes); |
| 2841 | adev->psp.toc_start_addr = (uint8_t *)adev->psp.sys_start_addr + | 3037 | adev->psp.toc_start_addr = (uint8_t *)adev->psp.sys_start_addr + |
| 2842 | le32_to_cpu(sos_hdr_v1_1->toc_offset_bytes); | 3038 | le32_to_cpu(sos_hdr_v1_1->toc.offset_bytes); |
| 2843 | adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_1->kdb_size_bytes); | 3039 | adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_1->kdb.size_bytes); |
| 2844 | adev->psp.kdb_start_addr = (uint8_t *)adev->psp.sys_start_addr + | 3040 | adev->psp.kdb_start_addr = (uint8_t *)adev->psp.sys_start_addr + |
| 2845 | le32_to_cpu(sos_hdr_v1_1->kdb_offset_bytes); | 3041 | le32_to_cpu(sos_hdr_v1_1->kdb.offset_bytes); |
| 2846 | } | 3042 | } |
| 2847 | if (sos_hdr->header.header_version_minor == 2) { | 3043 | if (sos_hdr->header.header_version_minor == 2) { |
| 2848 | sos_hdr_v1_2 = (const struct psp_firmware_header_v1_2 *)adev->psp.sos_fw->data; | 3044 | sos_hdr_v1_2 = (const struct psp_firmware_header_v1_2 *)adev->psp.sos_fw->data; |
| 2849 | adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_2->kdb_size_bytes); | 3045 | adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_2->kdb.size_bytes); |
| 2850 | adev->psp.kdb_start_addr = (uint8_t *)adev->psp.sys_start_addr + | 3046 | adev->psp.kdb_start_addr = (uint8_t *)adev->psp.sys_start_addr + |
| 2851 | le32_to_cpu(sos_hdr_v1_2->kdb_offset_bytes); | 3047 | le32_to_cpu(sos_hdr_v1_2->kdb.offset_bytes); |
| 2852 | } | 3048 | } |
| 2853 | if (sos_hdr->header.header_version_minor == 3) { | 3049 | if (sos_hdr->header.header_version_minor == 3) { |
| 2854 | sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data; | 3050 | sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data; |
| 2855 | adev->psp.toc_bin_size = le32_to_cpu(sos_hdr_v1_3->v1_1.toc_size_bytes); | 3051 | adev->psp.toc_bin_size = le32_to_cpu(sos_hdr_v1_3->v1_1.toc.size_bytes); |
| 2856 | adev->psp.toc_start_addr = (uint8_t *)adev->psp.sys_start_addr + | 3052 | adev->psp.toc_start_addr = ucode_array_start_addr + |
| 2857 | le32_to_cpu(sos_hdr_v1_3->v1_1.toc_offset_bytes); | 3053 | le32_to_cpu(sos_hdr_v1_3->v1_1.toc.offset_bytes); |
| 2858 | adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_3->v1_1.kdb_size_bytes); | 3054 | adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.size_bytes); |
| 2859 | adev->psp.kdb_start_addr = (uint8_t *)adev->psp.sys_start_addr + | 3055 | adev->psp.kdb_start_addr = ucode_array_start_addr + |
| 2860 | le32_to_cpu(sos_hdr_v1_3->v1_1.kdb_offset_bytes); | 3056 | le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.offset_bytes); |
| 2861 | adev->psp.spl_bin_size = le32_to_cpu(sos_hdr_v1_3->spl_size_bytes); | 3057 | adev->psp.spl_bin_size = le32_to_cpu(sos_hdr_v1_3->spl.size_bytes); |
| 2862 | adev->psp.spl_start_addr = (uint8_t *)adev->psp.sys_start_addr + | 3058 | adev->psp.spl_start_addr = ucode_array_start_addr + |
| 2863 | le32_to_cpu(sos_hdr_v1_3->spl_offset_bytes); | 3059 | le32_to_cpu(sos_hdr_v1_3->spl.offset_bytes); |
| 2864 | adev->psp.rl_bin_size = le32_to_cpu(sos_hdr_v1_3->rl_size_bytes); | 3060 | adev->psp.rl_bin_size = le32_to_cpu(sos_hdr_v1_3->rl.size_bytes); |
| 2865 | adev->psp.rl_start_addr = (uint8_t *)adev->psp.sys_start_addr + | 3061 | adev->psp.rl_start_addr = ucode_array_start_addr + |
| 2866 | le32_to_cpu(sos_hdr_v1_3->rl_offset_bytes); | 3062 | le32_to_cpu(sos_hdr_v1_3->rl.offset_bytes); |
| 2867 | } | 3063 | } |
| 2868 | break; | 3064 | break; |
| 2869 | default: | 3065 | default: |
| @@ -225,6 +225,61 @@ struct psp_memory_training_context { · 224 unmodified lines | |||
| 225 | 225 | ||
| 226 | enum psp_memory_training_init_flag init; | 226 | enum psp_memory_training_init_flag init; |
| 227 | u32 training_cnt; | 227 | u32 training_cnt; |
| 228 | bool enable_mem_training; | ||
| 229 | }; | ||
| 230 | |||
| 231 | /** PSP runtime DB **/ | ||
| 232 | #define PSP_RUNTIME_DB_SIZE_IN_BYTES 0x10000 | ||
| 233 | #define PSP_RUNTIME_DB_OFFSET 0x100000 | ||
| 234 | #define PSP_RUNTIME_DB_COOKIE_ID 0x0ed5 | ||
| 235 | #define PSP_RUNTIME_DB_VER_1 0x0100 | ||
| 236 | #define PSP_RUNTIME_DB_DIAG_ENTRY_MAX_COUNT 0x40 | ||
| 237 | |||
| 238 | enum psp_runtime_entry_type { | ||
| 239 | PSP_RUNTIME_ENTRY_TYPE_INVALID = 0x0, | ||
| 240 | PSP_RUNTIME_ENTRY_TYPE_TEST = 0x1, | ||
| 241 | PSP_RUNTIME_ENTRY_TYPE_MGPU_COMMON = 0x2, /* Common mGPU runtime data */ | ||
| 242 | PSP_RUNTIME_ENTRY_TYPE_MGPU_WAFL = 0x3, /* WAFL runtime data */ | ||
| 243 | PSP_RUNTIME_ENTRY_TYPE_MGPU_XGMI = 0x4, /* XGMI runtime data */ | ||
| 244 | PSP_RUNTIME_ENTRY_TYPE_BOOT_CONFIG = 0x5, /* Boot Config runtime data */ | ||
| 245 | }; | ||
| 246 | |||
| 247 | /* PSP runtime DB header */ | ||
| 248 | struct psp_runtime_data_header { | ||
| 249 | /* determine the existence of runtime db */ | ||
| 250 | uint16_t cookie; | ||
| 251 | /* version of runtime db */ | ||
| 252 | uint16_t version; | ||
| 253 | }; | ||
| 254 | |||
| 255 | /* PSP runtime DB entry */ | ||
| 256 | struct psp_runtime_entry { | ||
| 257 | /* type of runtime db entry */ | ||
| 258 | uint32_t entry_type; | ||
| 259 | /* offset of entry in bytes */ | ||
| 260 | uint16_t offset; | ||
| 261 | /* size of entry in bytes */ | ||
| 262 | uint16_t size; | ||
| 263 | }; | ||
| 264 | |||
| 265 | /* PSP runtime DB directory */ | ||
| 266 | struct psp_runtime_data_directory { | ||
| 267 | /* number of valid entries */ | ||
| 268 | uint16_t entry_count; | ||
| 269 | /* db entries*/ | ||
| 270 | struct psp_runtime_entry entry_list[PSP_RUNTIME_DB_DIAG_ENTRY_MAX_COUNT]; | ||
| 271 | }; | ||
| 272 | |||
| 273 | /* PSP runtime DB boot config feature bitmask */ | ||
| 274 | enum psp_runtime_boot_cfg_feature { | ||
| 275 | BOOT_CFG_FEATURE_GECC = 0x1, | ||
| 276 | BOOT_CFG_FEATURE_TWO_STAGE_DRAM_TRAINING = 0x2, | ||
| 277 | }; | ||
| 278 | |||
| 279 | /* PSP runtime DB boot config entry */ | ||
| 280 | struct psp_runtime_boot_cfg_entry { | ||
| 281 | uint32_t boot_cfg_bitmask; | ||
| 282 | uint32_t reserved; | ||
| 228 | }; | 283 | }; |
| 229 | 284 | ||
| 230 | struct psp_context | 285 | struct psp_context |
| @@ -325,6 +380,8 @@ struct psp_context · 94 unmodified lines | |||
| 325 | struct psp_securedisplay_context securedisplay_context; | 380 | struct psp_securedisplay_context securedisplay_context; |
| 326 | struct mutex mutex; | 381 | struct mutex mutex; |
| 327 | struct psp_memory_training_context mem_train_ctx; | 382 | struct psp_memory_training_context mem_train_ctx; |
| 383 | |||
| 384 | uint32_t boot_cfg_bitmask; | ||
| 328 | }; | 385 | }; |
| 329 | 386 | ||
| 330 | struct amdgpu_psp_funcs { | 387 | struct amdgpu_psp_funcs { |
| @@ -2122,7 +2122,7 @@ static void amdgpu_ras_counte_dw(struct work_struct *work) · 2121 unmodified lines | |||
| 2122 | struct amdgpu_ras *con = container_of(work, struct amdgpu_ras, | 2122 | struct amdgpu_ras *con = container_of(work, struct amdgpu_ras, |
| 2123 | ras_counte_delay_work.work); | 2123 | ras_counte_delay_work.work); |
| 2124 | struct amdgpu_device *adev = con->adev; | 2124 | struct amdgpu_device *adev = con->adev; |
| 2125 | struct drm_device *dev = &adev->ddev; | 2125 | struct drm_device *dev = adev_to_drm(adev); |
| 2126 | unsigned long ce_count, ue_count; | 2126 | unsigned long ce_count, ue_count; |
| 2127 | int res; | 2127 | int res; |
| 2128 | 2128 | ||
| @@ -257,36 +257,36 @@ void amdgpu_ucode_print_psp_hdr(const struct common_firmware_header *hdr) · 256 unmodified lines | |||
| 257 | container_of(hdr, struct psp_firmware_header_v1_0, header); | 257 | container_of(hdr, struct psp_firmware_header_v1_0, header); |
| 258 | 258 | ||
| 259 | DRM_DEBUG("ucode_feature_version: %u\n", | 259 | DRM_DEBUG("ucode_feature_version: %u\n", |
| 260 | le32_to_cpu(psp_hdr->ucode_feature_version)); | 260 | le32_to_cpu(psp_hdr->sos.fw_version)); |
| 261 | DRM_DEBUG("sos_offset_bytes: %u\n", | 261 | DRM_DEBUG("sos_offset_bytes: %u\n", |
| 262 | le32_to_cpu(psp_hdr->sos_offset_bytes)); | 262 | le32_to_cpu(psp_hdr->sos.offset_bytes)); |
| 263 | DRM_DEBUG("sos_size_bytes: %u\n", | 263 | DRM_DEBUG("sos_size_bytes: %u\n", |
| 264 | le32_to_cpu(psp_hdr->sos_size_bytes)); | 264 | le32_to_cpu(psp_hdr->sos.size_bytes)); |
| 265 | if (version_minor == 1) { | 265 | if (version_minor == 1) { |
| 266 | const struct psp_firmware_header_v1_1 *psp_hdr_v1_1 = | 266 | const struct psp_firmware_header_v1_1 *psp_hdr_v1_1 = |
| 267 | container_of(psp_hdr, struct psp_firmware_header_v1_1, v1_0); | 267 | container_of(psp_hdr, struct psp_firmware_header_v1_1, v1_0); |
| 268 | DRM_DEBUG("toc_header_version: %u\n", | 268 | DRM_DEBUG("toc_header_version: %u\n", |
| 269 | le32_to_cpu(psp_hdr_v1_1->toc_header_version)); | 269 | le32_to_cpu(psp_hdr_v1_1->toc.fw_version)); |
| 270 | DRM_DEBUG("toc_offset_bytes: %u\n", | 270 | DRM_DEBUG("toc_offset_bytes: %u\n", |
| 271 | le32_to_cpu(psp_hdr_v1_1->toc_offset_bytes)); | 271 | le32_to_cpu(psp_hdr_v1_1->toc.offset_bytes)); |
| 272 | DRM_DEBUG("toc_size_bytes: %u\n", | 272 | DRM_DEBUG("toc_size_bytes: %u\n", |
| 273 | le32_to_cpu(psp_hdr_v1_1->toc_size_bytes)); | 273 | le32_to_cpu(psp_hdr_v1_1->toc.size_bytes)); |
| 274 | DRM_DEBUG("kdb_header_version: %u\n", | 274 | DRM_DEBUG("kdb_header_version: %u\n", |
| 275 | le32_to_cpu(psp_hdr_v1_1->kdb_header_version)); | 275 | le32_to_cpu(psp_hdr_v1_1->kdb.fw_version)); |
| 276 | DRM_DEBUG("kdb_offset_bytes: %u\n", | 276 | DRM_DEBUG("kdb_offset_bytes: %u\n", |
| 277 | le32_to_cpu(psp_hdr_v1_1->kdb_offset_bytes)); | 277 | le32_to_cpu(psp_hdr_v1_1->kdb.offset_bytes)); |
| 278 | DRM_DEBUG("kdb_size_bytes: %u\n", | 278 | DRM_DEBUG("kdb_size_bytes: %u\n", |
| 279 | le32_to_cpu(psp_hdr_v1_1->kdb_size_bytes)); | 279 | le32_to_cpu(psp_hdr_v1_1->kdb.size_bytes)); |
| 280 | } | 280 | } |
| 281 | if (version_minor == 2) { | 281 | if (version_minor == 2) { |
| 282 | const struct psp_firmware_header_v1_2 *psp_hdr_v1_2 = | 282 | const struct psp_firmware_header_v1_2 *psp_hdr_v1_2 = |
| 283 | container_of(psp_hdr, struct psp_firmware_header_v1_2, v1_0); | 283 | container_of(psp_hdr, struct psp_firmware_header_v1_2, v1_0); |
| 284 | DRM_DEBUG("kdb_header_version: %u\n", | 284 | DRM_DEBUG("kdb_header_version: %u\n", |
| 285 | le32_to_cpu(psp_hdr_v1_2->kdb_header_version)); | 285 | le32_to_cpu(psp_hdr_v1_2->kdb.fw_version)); |
| 286 | DRM_DEBUG("kdb_offset_bytes: %u\n", | 286 | DRM_DEBUG("kdb_offset_bytes: %u\n", |
| 287 | le32_to_cpu(psp_hdr_v1_2->kdb_offset_bytes)); | 287 | le32_to_cpu(psp_hdr_v1_2->kdb.offset_bytes)); |
| 288 | DRM_DEBUG("kdb_size_bytes: %u\n", | 288 | DRM_DEBUG("kdb_size_bytes: %u\n", |
| 289 | le32_to_cpu(psp_hdr_v1_2->kdb_size_bytes)); | 289 | le32_to_cpu(psp_hdr_v1_2->kdb.size_bytes)); |
| 290 | } | 290 | } |
| 291 | if (version_minor == 3) { | 291 | if (version_minor == 3) { |
| 292 | const struct psp_firmware_header_v1_1 *psp_hdr_v1_1 = | 292 | const struct psp_firmware_header_v1_1 *psp_hdr_v1_1 = |
| @@ -294,23 +294,23 @@ void amdgpu_ucode_print_psp_hdr(const struct common_firmware_header *hdr) · 1 unmodified line | |||
| 294 | const struct psp_firmware_header_v1_3 *psp_hdr_v1_3 = | 294 | const struct psp_firmware_header_v1_3 *psp_hdr_v1_3 = |
| 295 | container_of(psp_hdr_v1_1, struct psp_firmware_header_v1_3, v1_1); | 295 | container_of(psp_hdr_v1_1, struct psp_firmware_header_v1_3, v1_1); |
| 296 | DRM_DEBUG("toc_header_version: %u\n", | 296 | DRM_DEBUG("toc_header_version: %u\n", |
| 297 | le32_to_cpu(psp_hdr_v1_3->v1_1.toc_header_version)); | 297 | le32_to_cpu(psp_hdr_v1_3->v1_1.toc.fw_version)); |
| 298 | DRM_DEBUG("toc_offset_bytes: %u\n", | 298 | DRM_DEBUG("toc_offset_bytes: %u\n", |
| 299 | le32_to_cpu(psp_hdr_v1_3->v1_1.toc_offset_bytes)); | 299 | le32_to_cpu(psp_hdr_v1_3->v1_1.toc.offset_bytes)); |
| 300 | DRM_DEBUG("toc_size_bytes: %u\n", | 300 | DRM_DEBUG("toc_size_bytes: %u\n", |
| 301 | le32_to_cpu(psp_hdr_v1_3->v1_1.toc_size_bytes)); | 301 | le32_to_cpu(psp_hdr_v1_3->v1_1.toc.size_bytes)); |
| 302 | DRM_DEBUG("kdb_header_version: %u\n", | 302 | DRM_DEBUG("kdb_header_version: %u\n", |
| 303 | le32_to_cpu(psp_hdr_v1_3->v1_1.kdb_header_version)); | 303 | le32_to_cpu(psp_hdr_v1_3->v1_1.kdb.fw_version)); |
| 304 | DRM_DEBUG("kdb_offset_bytes: %u\n", | 304 | DRM_DEBUG("kdb_offset_bytes: %u\n", |
| 305 | le32_to_cpu(psp_hdr_v1_3->v1_1.kdb_offset_bytes)); | 305 | le32_to_cpu(psp_hdr_v1_3->v1_1.kdb.offset_bytes)); |
| 306 | DRM_DEBUG("kdb_size_bytes: %u\n", | 306 | DRM_DEBUG("kdb_size_bytes: %u\n", |
| 307 | le32_to_cpu(psp_hdr_v1_3->v1_1.kdb_size_bytes)); | 307 | le32_to_cpu(psp_hdr_v1_3->v1_1.kdb.size_bytes)); |
| 308 | DRM_DEBUG("spl_header_version: %u\n", | 308 | DRM_DEBUG("spl_header_version: %u\n", |
| 309 | le32_to_cpu(psp_hdr_v1_3->spl_header_version)); | 309 | le32_to_cpu(psp_hdr_v1_3->spl.fw_version)); |
| 310 | DRM_DEBUG("spl_offset_bytes: %u\n", | 310 | DRM_DEBUG("spl_offset_bytes: %u\n", |
| 311 | le32_to_cpu(psp_hdr_v1_3->spl_offset_bytes)); | 311 | le32_to_cpu(psp_hdr_v1_3->spl.offset_bytes)); |
| 312 | DRM_DEBUG("spl_size_bytes: %u\n", | 312 | DRM_DEBUG("spl_size_bytes: %u\n", |
| 313 | le32_to_cpu(psp_hdr_v1_3->spl_size_bytes)); | 313 | le32_to_cpu(psp_hdr_v1_3->spl.size_bytes)); |
| 314 | } | 314 | } |
| 315 | } else { | 315 | } else { |
| 316 | DRM_ERROR("Unknown PSP ucode version: %u.%u\n", | 316 | DRM_ERROR("Unknown PSP ucode version: %u.%u\n", |
| @@ -71,43 +71,39 @@ struct smc_firmware_header_v2_1 { · 70 unmodified lines | |||
| 71 | uint32_t pptable_entry_offset; | 71 | uint32_t pptable_entry_offset; |
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| 74 | struct psp_fw_bin_desc { | ||
| 75 | uint32_t fw_version; | ||
| 76 | uint32_t offset_bytes; | ||
| 77 | uint32_t size_bytes; | ||
| 78 | }; | ||
| 79 | |||
| 74 | /* version_major=1, version_minor=0 */ | 80 | /* version_major=1, version_minor=0 */ |
| 75 | struct psp_firmware_header_v1_0 { | 81 | struct psp_firmware_header_v1_0 { |
| 76 | struct common_firmware_header header; | 82 | struct common_firmware_header header; |
| 77 | uint32_t ucode_feature_version; | 83 | struct psp_fw_bin_desc sos; |
| 78 | uint32_t sos_offset_bytes; | ||
| 79 | uint32_t sos_size_bytes; | ||
| 80 | }; | 84 | }; |
| 81 | 85 | ||
| 82 | /* version_major=1, version_minor=1 */ | 86 | /* version_major=1, version_minor=1 */ |
| 83 | struct psp_firmware_header_v1_1 { | 87 | struct psp_firmware_header_v1_1 { |
| 84 | struct psp_firmware_header_v1_0 v1_0; | 88 | struct psp_firmware_header_v1_0 v1_0; |
| 85 | uint32_t toc_header_version; | 89 | struct psp_fw_bin_desc toc; |
| 86 | uint32_t toc_offset_bytes; | 90 | struct psp_fw_bin_desc kdb; |
| 87 | uint32_t toc_size_bytes; | ||
| 88 | uint32_t kdb_header_version; | ||
| 89 | uint32_t kdb_offset_bytes; | ||
| 90 | uint32_t kdb_size_bytes; | ||
| 91 | }; | 91 | }; |
| 92 | 92 | ||
| 93 | /* version_major=1, version_minor=2 */ | 93 | /* version_major=1, version_minor=2 */ |
| 94 | struct psp_firmware_header_v1_2 { | 94 | struct psp_firmware_header_v1_2 { |
| 95 | struct psp_firmware_header_v1_0 v1_0; | 95 | struct psp_firmware_header_v1_0 v1_0; |
| 96 | uint32_t reserve[3]; | 96 | struct psp_fw_bin_desc res; |
| 97 | uint32_t kdb_header_version; | 97 | struct psp_fw_bin_desc kdb; |
| 98 | uint32_t kdb_offset_bytes; | ||
| 99 | uint32_t kdb_size_bytes; | ||
| 100 | }; | 98 | }; |
| 101 | 99 | ||
| 102 | /* version_major=1, version_minor=3 */ | 100 | /* version_major=1, version_minor=3 */ |
| 103 | struct psp_firmware_header_v1_3 { | 101 | struct psp_firmware_header_v1_3 { |
| 104 | struct psp_firmware_header_v1_1 v1_1; | 102 | struct psp_firmware_header_v1_1 v1_1; |
| 105 | uint32_t spl_header_version; | 103 | struct psp_fw_bin_desc spl; |
| 106 | uint32_t spl_offset_bytes; | 104 | struct psp_fw_bin_desc rl; |
| 107 | uint32_t spl_size_bytes; | 105 | struct psp_fw_bin_desc sys_drv_aux; |
| 108 | uint32_t rl_header_version; | 106 | struct psp_fw_bin_desc sos_aux; |
| 109 | uint32_t rl_offset_bytes; | ||
| 110 | uint32_t rl_size_bytes; | ||
| 111 | }; | 107 | }; |
| 112 | 108 | ||
| 113 | /* version_major=1, version_minor=0 */ | 109 | /* version_major=1, version_minor=0 */ |
| @@ -332,7 +332,7 @@ static void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base, · 331 unmodified lines | |||
| 332 | base->next = bo->vm_bo; | 332 | base->next = bo->vm_bo; |
| 333 | bo->vm_bo = base; | 333 | bo->vm_bo = base; |
| 334 | 334 | ||
| 335 | if (bo->tbo.base.resv != vm->root.base.bo->tbo.base.resv) | 335 | if (bo->tbo.base.resv != vm->root.bo->tbo.base.resv) |
| 336 | return; | 336 | return; |
| 337 | 337 | ||
| 338 | vm->bulk_moveable = false; | 338 | vm->bulk_moveable = false; |
| @@ -361,14 +361,14 @@ static void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base, · 22 unmodified lines | |||
| 361 | * Helper to get the parent entry for the child page table. NULL if we are at | 361 | * Helper to get the parent entry for the child page table. NULL if we are at |
| 362 | * the root page directory. | 362 | * the root page directory. |
| 363 | */ | 363 | */ |
| 364 | static struct amdgpu_vm_pt *amdgpu_vm_pt_parent(struct amdgpu_vm_pt *pt) | 364 | static struct amdgpu_vm_bo_base *amdgpu_vm_pt_parent(struct amdgpu_vm_bo_base *pt) |
| 365 | { | 365 | { |
| 366 | struct amdgpu_bo *parent = pt->base.bo->parent; | 366 | struct amdgpu_bo *parent = pt->bo->parent; |
| 367 | 367 | ||
| 368 | if (!parent) | 368 | if (!parent) |
| 369 | return NULL; | 369 | return NULL; |
| 370 | 370 | ||
| 371 | return container_of(parent->vm_bo, struct amdgpu_vm_pt, base); | 371 | return parent->vm_bo; |
| 372 | } | 372 | } |
| 373 | 373 | ||
| 374 | /* | 374 | /* |
| @@ -376,8 +376,8 @@ static struct amdgpu_vm_pt *amdgpu_vm_pt_parent(struct amdgpu_vm_pt *pt) · 1 unmodified line | |||
| 376 | */ | 376 | */ |
| 377 | struct amdgpu_vm_pt_cursor { | 377 | struct amdgpu_vm_pt_cursor { |
| 378 | uint64_t pfn; | 378 | uint64_t pfn; |
| 379 | struct amdgpu_vm_pt *parent; | 379 | struct amdgpu_vm_bo_base *parent; |
| 380 | struct amdgpu_vm_pt *entry; | 380 | struct amdgpu_vm_bo_base *entry; |
| 381 | unsigned level; | 381 | unsigned level; |
| 382 | }; | 382 | }; |
| 383 | 383 | ||
| @@ -416,17 +416,17 @@ static bool amdgpu_vm_pt_descendant(struct amdgpu_device *adev, · 32 unmodified lines | |||
| 416 | { | 416 | { |
| 417 | unsigned mask, shift, idx; | 417 | unsigned mask, shift, idx; |
| 418 | 418 | ||
| 419 | if (!cursor->entry->entries) | 419 | if ((cursor->level == AMDGPU_VM_PTB) || !cursor->entry || |
| 420 | !cursor->entry->bo) | ||
| 420 | return false; | 421 | return false; |
| 421 | 422 | ||
| 422 | BUG_ON(!cursor->entry->base.bo); | ||
| 423 | mask = amdgpu_vm_entries_mask(adev, cursor->level); | 423 | mask = amdgpu_vm_entries_mask(adev, cursor->level); |
| 424 | shift = amdgpu_vm_level_shift(adev, cursor->level); | 424 | shift = amdgpu_vm_level_shift(adev, cursor->level); |
| 425 | 425 | ||
| 426 | ++cursor->level; | 426 | ++cursor->level; |
| 427 | idx = (cursor->pfn >> shift) & mask; | 427 | idx = (cursor->pfn >> shift) & mask; |
| 428 | cursor->parent = cursor->entry; | 428 | cursor->parent = cursor->entry; |
| 429 | cursor->entry = &cursor->entry->entries[idx]; | 429 | cursor->entry = &to_amdgpu_bo_vm(cursor->entry->bo)->entries[idx]; |
| 430 | return true; | 430 | return true; |
| 431 | } | 431 | } |
| 432 | 432 | ||
| @@ -453,7 +453,7 @@ static bool amdgpu_vm_pt_sibling(struct amdgpu_device *adev, · 20 unmodified lines | |||
| 453 | shift = amdgpu_vm_level_shift(adev, cursor->level - 1); | 453 | shift = amdgpu_vm_level_shift(adev, cursor->level - 1); |
| 454 | num_entries = amdgpu_vm_num_entries(adev, cursor->level - 1); | 454 | num_entries = amdgpu_vm_num_entries(adev, cursor->level - 1); |
| 455 | 455 | ||
| 456 | if (cursor->entry == &cursor->parent->entries[num_entries - 1]) | 456 | if (cursor->entry == &to_amdgpu_bo_vm(cursor->parent->bo)->entries[num_entries - 1]) |
| 457 | return false; | 457 | return false; |
| 458 | 458 | ||
| 459 | cursor->pfn += 1ULL << shift; | 459 | cursor->pfn += 1ULL << shift; |
| @@ -539,7 +539,7 @@ static void amdgpu_vm_pt_first_dfs(struct amdgpu_device *adev, · 79 unmodified lines | |||
| 539 | * True when the search should continue, false otherwise. | 539 | * True when the search should continue, false otherwise. |
| 540 | */ | 540 | */ |
| 541 | static bool amdgpu_vm_pt_continue_dfs(struct amdgpu_vm_pt_cursor *start, | 541 | static bool amdgpu_vm_pt_continue_dfs(struct amdgpu_vm_pt_cursor *start, |
| 542 | struct amdgpu_vm_pt *entry) | 542 | struct amdgpu_vm_bo_base *entry) |
| 543 | { | 543 | { |
| 544 | return entry && (!start || entry != start->entry); | 544 | return entry && (!start || entry != start->entry); |
| 545 | } | 545 | } |
| @@ -590,7 +590,7 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, · 44 unmodified lines | |||
| 590 | struct amdgpu_bo_list_entry *entry) | 590 | struct amdgpu_bo_list_entry *entry) |
| 591 | { | 591 | { |
| 592 | entry->priority = 0; | 592 | entry->priority = 0; |
| 593 | entry->tv.bo = &vm->root.base.bo->tbo; | 593 | entry->tv.bo = &vm->root.bo->tbo; |
| 594 | /* Two for VM updates, one for TTM and one for the CS job */ | 594 | /* Two for VM updates, one for TTM and one for the CS job */ |
| 595 | entry->tv.num_shared = 4; | 595 | entry->tv.num_shared = 4; |
| 596 | entry->user_pages = NULL; | 596 | entry->user_pages = NULL; |
| @@ -622,7 +622,7 @@ void amdgpu_vm_del_from_lru_notify(struct ttm_buffer_object *bo) · 25 unmodified lines | |||
| 622 | for (bo_base = abo->vm_bo; bo_base; bo_base = bo_base->next) { | 622 | for (bo_base = abo->vm_bo; bo_base; bo_base = bo_base->next) { |
| 623 | struct amdgpu_vm *vm = bo_base->vm; | 623 | struct amdgpu_vm *vm = bo_base->vm; |
| 624 | 624 | ||
| 625 | if (abo->tbo.base.resv == vm->root.base.bo->tbo.base.resv) | 625 | if (abo->tbo.base.resv == vm->root.bo->tbo.base.resv) |
| 626 | vm->bulk_moveable = false; | 626 | vm->bulk_moveable = false; |
| 627 | } | 627 | } |
| 628 | 628 | ||
| @@ -781,11 +781,11 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev, · 152 unmodified lines | |||
| 781 | entries -= ats_entries; | 781 | entries -= ats_entries; |
| 782 | 782 | ||
| 783 | } else { | 783 | } else { |
| 784 | struct amdgpu_vm_pt *pt; | 784 | struct amdgpu_vm_bo_base *pt; |
| 785 | 785 | ||
| 786 | pt = container_of(ancestor->vm_bo, struct amdgpu_vm_pt, base); | 786 | pt = ancestor->vm_bo; |
| 787 | ats_entries = amdgpu_vm_num_ats_entries(adev); | 787 | ats_entries = amdgpu_vm_num_ats_entries(adev); |
| 788 | if ((pt - vm->root.entries) >= ats_entries) { | 788 | if ((pt - to_amdgpu_bo_vm(vm->root.bo)->entries) >= ats_entries) { |
| 789 | ats_entries = 0; | 789 | ats_entries = 0; |
| 790 | } else { | 790 | } else { |
| 791 | ats_entries = entries; | 791 | ats_entries = entries; |
| @@ -902,8 +902,8 @@ static int amdgpu_vm_pt_create(struct amdgpu_device *adev, · 110 unmodified lines | |||
| 902 | 902 | ||
| 903 | bp.type = ttm_bo_type_kernel; | 903 | bp.type = ttm_bo_type_kernel; |
| 904 | bp.no_wait_gpu = immediate; | 904 | bp.no_wait_gpu = immediate; |
| 905 | if (vm->root.base.bo) | 905 | if (vm->root.bo) |
| 906 | bp.resv = vm->root.base.bo->tbo.base.resv; | 906 | bp.resv = vm->root.bo->tbo.base.resv; |
| 907 | 907 | ||
| 908 | r = amdgpu_bo_create_vm(adev, &bp, vmbo); | 908 | r = amdgpu_bo_create_vm(adev, &bp, vmbo); |
| 909 | if (r) | 909 | if (r) |
| @@ -938,7 +938,7 @@ static int amdgpu_vm_pt_create(struct amdgpu_device *adev, · 28 unmodified lines | |||
| 938 | } | 938 | } |
| 939 | 939 | ||
| 940 | (*vmbo)->shadow->parent = amdgpu_bo_ref(bo); | 940 | (*vmbo)->shadow->parent = amdgpu_bo_ref(bo); |
| 941 | amdgpu_bo_add_to_shadow_list((*vmbo)->shadow); | 941 | amdgpu_bo_add_to_shadow_list(*vmbo); |
| 942 | 942 | ||
| 943 | return 0; | 943 | return 0; |
| 944 | } | 944 | } |
| @@ -962,19 +962,13 @@ static int amdgpu_vm_alloc_pts(struct amdgpu_device *adev, · 17 unmodified lines | |||
| 962 | struct amdgpu_vm_pt_cursor *cursor, | 962 | struct amdgpu_vm_pt_cursor *cursor, |
| 963 | bool immediate) | 963 | bool immediate) |
| 964 | { | 964 | { |
| 965 | struct amdgpu_vm_pt *entry = cursor->entry; | 965 | struct amdgpu_vm_bo_base *entry = cursor->entry; |
| 966 | struct amdgpu_bo *pt_bo; | 966 | struct amdgpu_bo *pt_bo; |
| 967 | struct amdgpu_bo_vm *pt; | 967 | struct amdgpu_bo_vm *pt; |
| 968 | int r; | 968 | int r; |
| 969 | 969 | ||
| 970 | if (entry->base.bo) { | 970 | if (entry->bo) |
| 971 | if (cursor->level < AMDGPU_VM_PTB) | ||
| 972 | entry->entries = | ||
| 973 | to_amdgpu_bo_vm(entry->base.bo)->entries; | ||
| 974 | else | ||
| 975 | entry->entries = NULL; | ||
| 976 | return 0; | 971 | return 0; |
| 977 | } | ||
| 978 | 972 | ||
| 979 | r = amdgpu_vm_pt_create(adev, vm, cursor->level, immediate, &pt); | 973 | r = amdgpu_vm_pt_create(adev, vm, cursor->level, immediate, &pt); |
| 980 | if (r) | 974 | if (r) |
| @@ -984,13 +978,8 @@ static int amdgpu_vm_alloc_pts(struct amdgpu_device *adev, · 3 unmodified lines | |||
| 984 | * freeing them up in the wrong order. | 978 | * freeing them up in the wrong order. |
| 985 | */ | 979 | */ |
| 986 | pt_bo = &pt->bo; | 980 | pt_bo = &pt->bo; |
| 987 | pt_bo->parent = amdgpu_bo_ref(cursor->parent->base.bo); | 981 | pt_bo->parent = amdgpu_bo_ref(cursor->parent->bo); |
| 988 | amdgpu_vm_bo_base_init(&entry->base, vm, pt_bo); | 982 | amdgpu_vm_bo_base_init(entry, vm, pt_bo); |
| 989 | if (cursor->level < AMDGPU_VM_PTB) | ||
| 990 | entry->entries = pt->entries; | ||
| 991 | else | ||
| 992 | entry->entries = NULL; | ||
| 993 | |||
| 994 | r = amdgpu_vm_clear_bo(adev, vm, pt, immediate); | 983 | r = amdgpu_vm_clear_bo(adev, vm, pt, immediate); |
| 995 | if (r) | 984 | if (r) |
| 996 | goto error_free_pt; | 985 | goto error_free_pt; |
| @@ -1008,18 +997,17 @@ error_free_pt: · 11 unmodified lines | |||
| 1008 | * | 997 | * |
| 1009 | * @entry: PDE to free | 998 | * @entry: PDE to free |
| 1010 | */ | 999 | */ |
| 1011 | static void amdgpu_vm_free_table(struct amdgpu_vm_pt *entry) | 1000 | static void amdgpu_vm_free_table(struct amdgpu_vm_bo_base *entry) |
| 1012 | { | 1001 | { |
| 1013 | struct amdgpu_bo *shadow; | 1002 | struct amdgpu_bo *shadow; |
| 1014 | 1003 | ||
| 1015 | if (entry->base.bo) { | 1004 | if (!entry->bo) |
| 1016 | shadow = amdgpu_bo_shadowed(entry->base.bo); | 1005 | return; |
| 1017 | entry->base.bo->vm_bo = NULL; | 1006 | shadow = amdgpu_bo_shadowed(entry->bo); |
| 1018 | list_del(&entry->base.vm_status); | 1007 | entry->bo->vm_bo = NULL; |
| 1019 | amdgpu_bo_unref(&shadow); | 1008 | list_del(&entry->vm_status); |
| 1020 | amdgpu_bo_unref(&entry->base.bo); | 1009 | amdgpu_bo_unref(&shadow); |
| 1021 | } | 1010 | amdgpu_bo_unref(&entry->bo); |
| 1022 | entry->entries = NULL; | ||
| 1023 | } | 1011 | } |
| 1024 | 1012 | ||
| 1025 | /** | 1013 | /** |
| @@ -1036,7 +1024,7 @@ static void amdgpu_vm_free_pts(struct amdgpu_device *adev, · 10 unmodified lines | |||
| 1036 | struct amdgpu_vm_pt_cursor *start) | 1024 | struct amdgpu_vm_pt_cursor *start) |
| 1037 | { | 1025 | { |
| 1038 | struct amdgpu_vm_pt_cursor cursor; | 1026 | struct amdgpu_vm_pt_cursor cursor; |
| 1039 | struct amdgpu_vm_pt *entry; | 1027 | struct amdgpu_vm_bo_base *entry; |
| 1040 | 1028 | ||
| 1041 | vm->bulk_moveable = false; | 1029 | vm->bulk_moveable = false; |
| 1042 | 1030 | ||
| @@ -1304,10 +1292,10 @@ uint64_t amdgpu_vm_map_gart(const dma_addr_t *pages_addr, uint64_t addr) · 261 unmodified lines | |||
| 1304 | */ | 1292 | */ |
| 1305 | static int amdgpu_vm_update_pde(struct amdgpu_vm_update_params *params, | 1293 | static int amdgpu_vm_update_pde(struct amdgpu_vm_update_params *params, |
| 1306 | struct amdgpu_vm *vm, | 1294 | struct amdgpu_vm *vm, |
| 1307 | struct amdgpu_vm_pt *entry) | 1295 | struct amdgpu_vm_bo_base *entry) |
| 1308 | { | 1296 | { |
| 1309 | struct amdgpu_vm_pt *parent = amdgpu_vm_pt_parent(entry); | 1297 | struct amdgpu_vm_bo_base *parent = amdgpu_vm_pt_parent(entry); |
| 1310 | struct amdgpu_bo *bo = parent->base.bo, *pbo; | 1298 | struct amdgpu_bo *bo = parent->bo, *pbo; |
| 1311 | uint64_t pde, pt, flags; | 1299 | uint64_t pde, pt, flags; |
| 1312 | unsigned level; | 1300 | unsigned level; |
| 1313 | 1301 | ||
| @@ -1315,8 +1303,8 @@ static int amdgpu_vm_update_pde(struct amdgpu_vm_update_params *params, · 1 unmodified line | |||
| 1315 | pbo = pbo->parent; | 1303 | pbo = pbo->parent; |
| 1316 | 1304 | ||
| 1317 | level += params->adev->vm_manager.root_level; | 1305 | level += params->adev->vm_manager.root_level; |
| 1318 | amdgpu_gmc_get_pde_for_bo(entry->base.bo, level, &pt, &flags); | 1306 | amdgpu_gmc_get_pde_for_bo(entry->bo, level, &pt, &flags); |
| 1319 | pde = (entry - parent->entries) * 8; | 1307 | pde = (entry - to_amdgpu_bo_vm(parent->bo)->entries) * 8; |
| 1320 | return vm->update_funcs->update(params, to_amdgpu_bo_vm(bo), pde, pt, | 1308 | return vm->update_funcs->update(params, to_amdgpu_bo_vm(bo), pde, pt, |
| 1321 | 1, 0, flags); | 1309 | 1, 0, flags); |
| 1322 | } | 1310 | } |
| @@ -1333,11 +1321,11 @@ static void amdgpu_vm_invalidate_pds(struct amdgpu_device *adev, · 10 unmodified lines | |||
| 1333 | struct amdgpu_vm *vm) | 1321 | struct amdgpu_vm *vm) |
| 1334 | { | 1322 | { |
| 1335 | struct amdgpu_vm_pt_cursor cursor; | 1323 | struct amdgpu_vm_pt_cursor cursor; |
| 1336 | struct amdgpu_vm_pt *entry; | 1324 | struct amdgpu_vm_bo_base *entry; |
| 1337 | 1325 | ||
| 1338 | for_each_amdgpu_vm_pt_dfs_safe(adev, vm, NULL, cursor, entry) | 1326 | for_each_amdgpu_vm_pt_dfs_safe(adev, vm, NULL, cursor, entry) |
| 1339 | if (entry->base.bo && !entry->base.moved) | 1327 | if (entry->bo && !entry->moved) |
| 1340 | amdgpu_vm_bo_relocated(&entry->base); | 1328 | amdgpu_vm_bo_relocated(entry); |
| 1341 | } | 1329 | } |
| 1342 | 1330 | ||
| 1343 | /** | 1331 | /** |
| @@ -1371,11 +1359,12 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev, · 27 unmodified lines | |||
| 1371 | return r; | 1359 | return r; |
| 1372 | 1360 | ||
| 1373 | while (!list_empty(&vm->relocated)) { | 1361 | while (!list_empty(&vm->relocated)) { |
| 1374 | struct amdgpu_vm_pt *entry; | 1362 | struct amdgpu_vm_bo_base *entry; |
| 1375 | 1363 | ||
| 1376 | entry = list_first_entry(&vm->relocated, struct amdgpu_vm_pt, | 1364 | entry = list_first_entry(&vm->relocated, |
| 1377 | base.vm_status); | 1365 | struct amdgpu_vm_bo_base, |
| 1378 | amdgpu_vm_bo_idle(&entry->base); | 1366 | vm_status); |
| 1367 | amdgpu_vm_bo_idle(entry); | ||
| 1379 | 1368 | ||
| 1380 | r = amdgpu_vm_update_pde(¶ms, vm, entry); | 1369 | r = amdgpu_vm_update_pde(¶ms, vm, entry); |
| 1381 | if (r) | 1370 | if (r) |
| @@ -1555,7 +1544,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_vm_update_params *params, · 173 unmodified lines | |||
| 1555 | continue; | 1544 | continue; |
| 1556 | } | 1545 | } |
| 1557 | 1546 | ||
| 1558 | pt = cursor.entry->base.bo; | 1547 | pt = cursor.entry->bo; |
| 1559 | if (!pt) { | 1548 | if (!pt) { |
| 1560 | /* We need all PDs and PTs for mapping something, */ | 1549 | /* We need all PDs and PTs for mapping something, */ |
| 1561 | if (flags & AMDGPU_PTE_VALID) | 1550 | if (flags & AMDGPU_PTE_VALID) |
| @@ -1567,7 +1556,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_vm_update_params *params, · 5 unmodified lines | |||
| 1567 | if (!amdgpu_vm_pt_ancestor(&cursor)) | 1556 | if (!amdgpu_vm_pt_ancestor(&cursor)) |
| 1568 | return -EINVAL; | 1557 | return -EINVAL; |
| 1569 | 1558 | ||
| 1570 | pt = cursor.entry->base.bo; | 1559 | pt = cursor.entry->bo; |
| 1571 | shift = parent_shift; | 1560 | shift = parent_shift; |
| 1572 | frag_end = max(frag_end, ALIGN(frag_start + 1, | 1561 | frag_end = max(frag_end, ALIGN(frag_start + 1, |
| 1573 | 1ULL << shift)); | 1562 | 1ULL << shift)); |
| @@ -1622,7 +1611,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_vm_update_params *params, · 48 unmodified lines | |||
| 1622 | */ | 1611 | */ |
| 1623 | while (cursor.pfn < frag_start) { | 1612 | while (cursor.pfn < frag_start) { |
| 1624 | /* Make sure previous mapping is freed */ | 1613 | /* Make sure previous mapping is freed */ |
| 1625 | if (cursor.entry->base.bo) { | 1614 | if (cursor.entry->bo) { |
| 1626 | params->table_freed = true; | 1615 | params->table_freed = true; |
| 1627 | amdgpu_vm_free_pts(adev, params->vm, &cursor); | 1616 | amdgpu_vm_free_pts(adev, params->vm, &cursor); |
| 1628 | } | 1617 | } |
| @@ -1704,7 +1693,7 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, · 75 unmodified lines | |||
| 1704 | if (!unlocked && !dma_fence_is_signaled(vm->last_unlocked)) { | 1693 | if (!unlocked && !dma_fence_is_signaled(vm->last_unlocked)) { |
| 1705 | struct dma_fence *tmp = dma_fence_get_stub(); | 1694 | struct dma_fence *tmp = dma_fence_get_stub(); |
| 1706 | 1695 | ||
| 1707 | amdgpu_bo_fence(vm->root.base.bo, vm->last_unlocked, true); | 1696 | amdgpu_bo_fence(vm->root.bo, vm->last_unlocked, true); |
| 1708 | swap(vm->last_unlocked, tmp); | 1697 | swap(vm->last_unlocked, tmp); |
| 1709 | dma_fence_put(tmp); | 1698 | dma_fence_put(tmp); |
| 1710 | } | 1699 | } |
| @@ -1850,7 +1839,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, · 139 unmodified lines | |||
| 1850 | 1839 | ||
| 1851 | if (clear || !bo) { | 1840 | if (clear || !bo) { |
| 1852 | mem = NULL; | 1841 | mem = NULL; |
| 1853 | resv = vm->root.base.bo->tbo.base.resv; | 1842 | resv = vm->root.bo->tbo.base.resv; |
| 1854 | } else { | 1843 | } else { |
| 1855 | struct drm_gem_object *obj = &bo->tbo.base; | 1844 | struct drm_gem_object *obj = &bo->tbo.base; |
| 1856 | 1845 | ||
| @@ -1881,7 +1870,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, · 24 unmodified lines | |||
| 1881 | } | 1870 | } |
| 1882 | 1871 | ||
| 1883 | if (clear || (bo && bo->tbo.base.resv == | 1872 | if (clear || (bo && bo->tbo.base.resv == |
| 1884 | vm->root.base.bo->tbo.base.resv)) | 1873 | vm->root.bo->tbo.base.resv)) |
| 1885 | last_update = &vm->last_update; | 1874 | last_update = &vm->last_update; |
| 1886 | else | 1875 | else |
| 1887 | last_update = &bo_va->last_pt_update; | 1876 | last_update = &bo_va->last_pt_update; |
| @@ -1923,7 +1912,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, · 35 unmodified lines | |||
| 1923 | * the evicted list so that it gets validated again on the | 1912 | * the evicted list so that it gets validated again on the |
| 1924 | * next command submission. | 1913 | * next command submission. |
| 1925 | */ | 1914 | */ |
| 1926 | if (bo && bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv) { | 1915 | if (bo && bo->tbo.base.resv == vm->root.bo->tbo.base.resv) { |
| 1927 | uint32_t mem_type = bo->tbo.resource->mem_type; | 1916 | uint32_t mem_type = bo->tbo.resource->mem_type; |
| 1928 | 1917 | ||
| 1929 | if (!(bo->preferred_domains & | 1918 | if (!(bo->preferred_domains & |
| @@ -2060,7 +2049,7 @@ static void amdgpu_vm_free_mapping(struct amdgpu_device *adev, · 130 unmodified lines | |||
| 2060 | */ | 2049 | */ |
| 2061 | static void amdgpu_vm_prt_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) | 2050 | static void amdgpu_vm_prt_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) |
| 2062 | { | 2051 | { |
| 2063 | struct dma_resv *resv = vm->root.base.bo->tbo.base.resv; | 2052 | struct dma_resv *resv = vm->root.bo->tbo.base.resv; |
| 2064 | struct dma_fence *excl, **shared; | 2053 | struct dma_fence *excl, **shared; |
| 2065 | unsigned i, shared_count; | 2054 | unsigned i, shared_count; |
| 2066 | int r; | 2055 | int r; |
| @@ -2106,7 +2095,7 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev, · 39 unmodified lines | |||
| 2106 | struct amdgpu_vm *vm, | 2095 | struct amdgpu_vm *vm, |
| 2107 | struct dma_fence **fence) | 2096 | struct dma_fence **fence) |
| 2108 | { | 2097 | { |
| 2109 | struct dma_resv *resv = vm->root.base.bo->tbo.base.resv; | 2098 | struct dma_resv *resv = vm->root.bo->tbo.base.resv; |
| 2110 | struct amdgpu_bo_va_mapping *mapping; | 2099 | struct amdgpu_bo_va_mapping *mapping; |
| 2111 | uint64_t init_pte_value = 0; | 2100 | uint64_t init_pte_value = 0; |
| 2112 | struct dma_fence *f = NULL; | 2101 | struct dma_fence *f = NULL; |
| @@ -2265,7 +2254,7 @@ static void amdgpu_vm_bo_insert_map(struct amdgpu_device *adev, · 152 unmodified lines | |||
| 2265 | if (mapping->flags & AMDGPU_PTE_PRT) | 2254 | if (mapping->flags & AMDGPU_PTE_PRT) |
| 2266 | amdgpu_vm_prt_get(adev); | 2255 | amdgpu_vm_prt_get(adev); |
| 2267 | 2256 | ||
| 2268 | if (bo && bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv && | 2257 | if (bo && bo->tbo.base.resv == vm->root.bo->tbo.base.resv && |
| 2269 | !bo_va->base.moved) { | 2258 | !bo_va->base.moved) { |
| 2270 | list_move(&bo_va->base.vm_status, &vm->moved); | 2259 | list_move(&bo_va->base.vm_status, &vm->moved); |
| 2271 | } | 2260 | } |
| @@ -2627,7 +2616,7 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, · 355 unmodified lines | |||
| 2627 | struct amdgpu_vm_bo_base **base; | 2616 | struct amdgpu_vm_bo_base **base; |
| 2628 | 2617 | ||
| 2629 | if (bo) { | 2618 | if (bo) { |
| 2630 | if (bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv) | 2619 | if (bo->tbo.base.resv == vm->root.bo->tbo.base.resv) |
| 2631 | vm->bulk_moveable = false; | 2620 | vm->bulk_moveable = false; |
| 2632 | 2621 | ||
| 2633 | for (base = &bo_va->base.bo->vm_bo; *base; | 2622 | for (base = &bo_va->base.bo->vm_bo; *base; |
| @@ -2721,7 +2710,7 @@ void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev, · 87 unmodified lines | |||
| 2721 | for (bo_base = bo->vm_bo; bo_base; bo_base = bo_base->next) { | 2710 | for (bo_base = bo->vm_bo; bo_base; bo_base = bo_base->next) { |
| 2722 | struct amdgpu_vm *vm = bo_base->vm; | 2711 | struct amdgpu_vm *vm = bo_base->vm; |
| 2723 | 2712 | ||
| 2724 | if (evicted && bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv) { | 2713 | if (evicted && bo->tbo.base.resv == vm->root.bo->tbo.base.resv) { |
| 2725 | amdgpu_vm_bo_evicted(bo_base); | 2714 | amdgpu_vm_bo_evicted(bo_base); |
| 2726 | continue; | 2715 | continue; |
| 2727 | } | 2716 | } |
| @@ -2732,7 +2721,7 @@ void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev, · 4 unmodified lines | |||
| 2732 | 2721 | ||
| 2733 | if (bo->tbo.type == ttm_bo_type_kernel) | 2722 | if (bo->tbo.type == ttm_bo_type_kernel) |
| 2734 | amdgpu_vm_bo_relocated(bo_base); | 2723 | amdgpu_vm_bo_relocated(bo_base); |
| 2735 | else if (bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv) | 2724 | else if (bo->tbo.base.resv == vm->root.bo->tbo.base.resv) |
| 2736 | amdgpu_vm_bo_moved(bo_base); | 2725 | amdgpu_vm_bo_moved(bo_base); |
| 2737 | else | 2726 | else |
| 2738 | amdgpu_vm_bo_invalidated(bo_base); | 2727 | amdgpu_vm_bo_invalidated(bo_base); |
| @@ -2862,7 +2851,7 @@ void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t min_vm_size, · 123 unmodified lines | |||
| 2862 | */ | 2851 | */ |
| 2863 | long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout) | 2852 | long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout) |
| 2864 | { | 2853 | { |
| 2865 | timeout = dma_resv_wait_timeout(vm->root.base.bo->tbo.base.resv, true, | 2854 | timeout = dma_resv_wait_timeout(vm->root.bo->tbo.base.resv, true, |
| 2866 | true, timeout); | 2855 | true, timeout); |
| 2867 | if (timeout <= 0) | 2856 | if (timeout <= 0) |
| 2868 | return timeout; | 2857 | return timeout; |
| @@ -2948,13 +2937,13 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid) · 79 unmodified lines | |||
| 2948 | if (r) | 2937 | if (r) |
| 2949 | goto error_unreserve; | 2938 | goto error_unreserve; |
| 2950 | 2939 | ||
| 2951 | amdgpu_vm_bo_base_init(&vm->root.base, vm, root_bo); | 2940 | amdgpu_vm_bo_base_init(&vm->root, vm, root_bo); |
| 2952 | 2941 | ||
| 2953 | r = amdgpu_vm_clear_bo(adev, vm, root, false); | 2942 | r = amdgpu_vm_clear_bo(adev, vm, root, false); |
| 2954 | if (r) | 2943 | if (r) |
| 2955 | goto error_unreserve; | 2944 | goto error_unreserve; |
| 2956 | 2945 | ||
| 2957 | amdgpu_bo_unreserve(vm->root.base.bo); | 2946 | amdgpu_bo_unreserve(vm->root.bo); |
| 2958 | 2947 | ||
| 2959 | if (pasid) { | 2948 | if (pasid) { |
| 2960 | unsigned long flags; | 2949 | unsigned long flags; |
| @@ -2974,12 +2963,12 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid) · 13 unmodified lines | |||
| 2974 | return 0; | 2963 | return 0; |
| 2975 | 2964 | ||
| 2976 | error_unreserve: | 2965 | error_unreserve: |
| 2977 | amdgpu_bo_unreserve(vm->root.base.bo); | 2966 | amdgpu_bo_unreserve(vm->root.bo); |
| 2978 | 2967 | ||
| 2979 | error_free_root: | 2968 | error_free_root: |
| 2980 | amdgpu_bo_unref(&root->shadow); | 2969 | amdgpu_bo_unref(&root->shadow); |
| 2981 | amdgpu_bo_unref(&root_bo); | 2970 | amdgpu_bo_unref(&root_bo); |
| 2982 | vm->root.base.bo = NULL; | 2971 | vm->root.bo = NULL; |
| 2983 | 2972 | ||
| 2984 | error_free_delayed: | 2973 | error_free_delayed: |
| 2985 | dma_fence_put(vm->last_unlocked); | 2974 | dma_fence_put(vm->last_unlocked); |
| @@ -3005,17 +2994,14 @@ error_free_immediate: · 19 unmodified lines | |||
| 3005 | * 0 if this VM is clean | 2994 | * 0 if this VM is clean |
| 3006 | */ | 2995 | */ |
| 3007 | static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev, | 2996 | static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev, |
| 3008 | struct amdgpu_vm *vm) | 2997 | struct amdgpu_vm *vm) |
| 3009 | { | 2998 | { |
| 3010 | enum amdgpu_vm_level root = adev->vm_manager.root_level; | 2999 | enum amdgpu_vm_level root = adev->vm_manager.root_level; |
| 3011 | unsigned int entries = amdgpu_vm_num_entries(adev, root); | 3000 | unsigned int entries = amdgpu_vm_num_entries(adev, root); |
| 3012 | unsigned int i = 0; | 3001 | unsigned int i = 0; |
| 3013 | 3002 | ||
| 3014 | if (!(vm->root.entries)) | ||
| 3015 | return 0; | ||
| 3016 | |||
| 3017 | for (i = 0; i < entries; i++) { | 3003 | for (i = 0; i < entries; i++) { |
| 3018 | if (vm->root.entries[i].base.bo) | 3004 | if (to_amdgpu_bo_vm(vm->root.bo)->entries[i].bo) |
| 3019 | return -EINVAL; | 3005 | return -EINVAL; |
| 3020 | } | 3006 | } |
| 3021 | 3007 | ||
| @@ -3049,7 +3035,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 27 unmodified lines | |||
| 3049 | bool pte_support_ats = (adev->asic_type == CHIP_RAVEN); | 3035 | bool pte_support_ats = (adev->asic_type == CHIP_RAVEN); |
| 3050 | int r; | 3036 | int r; |
| 3051 | 3037 | ||
| 3052 | r = amdgpu_bo_reserve(vm->root.base.bo, true); | 3038 | r = amdgpu_bo_reserve(vm->root.bo, true); |
| 3053 | if (r) | 3039 | if (r) |
| 3054 | return r; | 3040 | return r; |
| 3055 | 3041 | ||
| @@ -3077,7 +3063,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 21 unmodified lines | |||
| 3077 | if (pte_support_ats != vm->pte_support_ats) { | 3063 | if (pte_support_ats != vm->pte_support_ats) { |
| 3078 | vm->pte_support_ats = pte_support_ats; | 3064 | vm->pte_support_ats = pte_support_ats; |
| 3079 | r = amdgpu_vm_clear_bo(adev, vm, | 3065 | r = amdgpu_vm_clear_bo(adev, vm, |
| 3080 | to_amdgpu_bo_vm(vm->root.base.bo), | 3066 | to_amdgpu_bo_vm(vm->root.bo), |
| 3081 | false); | 3067 | false); |
| 3082 | if (r) | 3068 | if (r) |
| 3083 | goto free_idr; | 3069 | goto free_idr; |
| @@ -3094,7 +3080,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 10 unmodified lines | |||
| 3094 | 3080 | ||
| 3095 | if (vm->use_cpu_for_update) { | 3081 | if (vm->use_cpu_for_update) { |
| 3096 | /* Sync with last SDMA update/clear before switching to CPU */ | 3082 | /* Sync with last SDMA update/clear before switching to CPU */ |
| 3097 | r = amdgpu_bo_sync_wait(vm->root.base.bo, | 3083 | r = amdgpu_bo_sync_wait(vm->root.bo, |
| 3098 | AMDGPU_FENCE_OWNER_UNDEFINED, true); | 3084 | AMDGPU_FENCE_OWNER_UNDEFINED, true); |
| 3099 | if (r) | 3085 | if (r) |
| 3100 | goto free_idr; | 3086 | goto free_idr; |
| @@ -3122,7 +3108,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 21 unmodified lines | |||
| 3122 | } | 3108 | } |
| 3123 | 3109 | ||
| 3124 | /* Free the shadow bo for compute VM */ | 3110 | /* Free the shadow bo for compute VM */ |
| 3125 | amdgpu_bo_unref(&to_amdgpu_bo_vm(vm->root.base.bo)->shadow); | 3111 | amdgpu_bo_unref(&to_amdgpu_bo_vm(vm->root.bo)->shadow); |
| 3126 | 3112 | ||
| 3127 | if (pasid) | 3113 | if (pasid) |
| 3128 | vm->pasid = pasid; | 3114 | vm->pasid = pasid; |
| @@ -3138,7 +3124,7 @@ free_idr: · 9 unmodified lines | |||
| 3138 | spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); | 3124 | spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); |
| 3139 | } | 3125 | } |
| 3140 | unreserve_bo: | 3126 | unreserve_bo: |
| 3141 | amdgpu_bo_unreserve(vm->root.base.bo); | 3127 | amdgpu_bo_unreserve(vm->root.bo); |
| 3142 | return r; | 3128 | return r; |
| 3143 | } | 3129 | } |
| 3144 | 3130 | ||
| @@ -3181,7 +3167,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) · 36 unmodified lines | |||
| 3181 | 3167 | ||
| 3182 | amdgpu_amdkfd_gpuvm_destroy_cb(adev, vm); | 3168 | amdgpu_amdkfd_gpuvm_destroy_cb(adev, vm); |
| 3183 | 3169 | ||
| 3184 | root = amdgpu_bo_ref(vm->root.base.bo); | 3170 | root = amdgpu_bo_ref(vm->root.bo); |
| 3185 | amdgpu_bo_reserve(root, true); | 3171 | amdgpu_bo_reserve(root, true); |
| 3186 | if (vm->pasid) { | 3172 | if (vm->pasid) { |
| 3187 | unsigned long flags; | 3173 | unsigned long flags; |
| @@ -3208,7 +3194,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) · 20 unmodified lines | |||
| 3208 | amdgpu_vm_free_pts(adev, vm, NULL); | 3194 | amdgpu_vm_free_pts(adev, vm, NULL); |
| 3209 | amdgpu_bo_unreserve(root); | 3195 | amdgpu_bo_unreserve(root); |
| 3210 | amdgpu_bo_unref(&root); | 3196 | amdgpu_bo_unref(&root); |
| 3211 | WARN_ON(vm->root.base.bo); | 3197 | WARN_ON(vm->root.bo); |
| 3212 | 3198 | ||
| 3213 | drm_sched_entity_destroy(&vm->immediate); | 3199 | drm_sched_entity_destroy(&vm->immediate); |
| 3214 | drm_sched_entity_destroy(&vm->delayed); | 3200 | drm_sched_entity_destroy(&vm->delayed); |
| @@ -3325,7 +3311,7 @@ int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) · 110 unmodified lines | |||
| 3325 | /* Wait vm idle to make sure the vmid set in SPM_VMID is | 3311 | /* Wait vm idle to make sure the vmid set in SPM_VMID is |
| 3326 | * not referenced anymore. | 3312 | * not referenced anymore. |
| 3327 | */ | 3313 | */ |
| 3328 | r = amdgpu_bo_reserve(fpriv->vm.root.base.bo, true); | 3314 | r = amdgpu_bo_reserve(fpriv->vm.root.bo, true); |
| 3329 | if (r) | 3315 | if (r) |
| 3330 | return r; | 3316 | return r; |
| 3331 | 3317 | ||
| @@ -3333,7 +3319,7 @@ int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) · 1 unmodified line | |||
| 3333 | if (r < 0) | 3319 | if (r < 0) |
| 3334 | return r; | 3320 | return r; |
| 3335 | 3321 | ||
| 3336 | amdgpu_bo_unreserve(fpriv->vm.root.base.bo); | 3322 | amdgpu_bo_unreserve(fpriv->vm.root.bo); |
| 3337 | amdgpu_vmid_free_reserved(adev, &fpriv->vm, AMDGPU_GFXHUB_0); | 3323 | amdgpu_vmid_free_reserved(adev, &fpriv->vm, AMDGPU_GFXHUB_0); |
| 3338 | break; | 3324 | break; |
| 3339 | default: | 3325 | default: |
| @@ -3399,19 +3385,20 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, · 59 unmodified lines | |||
| 3399 | { | 3385 | { |
| 3400 | bool is_compute_context = false; | 3386 | bool is_compute_context = false; |
| 3401 | struct amdgpu_bo *root; | 3387 | struct amdgpu_bo *root; |
| 3388 | unsigned long irqflags; | ||
| 3402 | uint64_t value, flags; | 3389 | uint64_t value, flags; |
| 3403 | struct amdgpu_vm *vm; | 3390 | struct amdgpu_vm *vm; |
| 3404 | int r; | 3391 | int r; |
| 3405 | 3392 | ||
| 3406 | spin_lock(&adev->vm_manager.pasid_lock); | 3393 | spin_lock_irqsave(&adev->vm_manager.pasid_lock, irqflags); |
| 3407 | vm = idr_find(&adev->vm_manager.pasid_idr, pasid); | 3394 | vm = idr_find(&adev->vm_manager.pasid_idr, pasid); |
| 3408 | if (vm) { | 3395 | if (vm) { |
| 3409 | root = amdgpu_bo_ref(vm->root.base.bo); | 3396 | root = amdgpu_bo_ref(vm->root.bo); |
| 3410 | is_compute_context = vm->is_compute_context; | 3397 | is_compute_context = vm->is_compute_context; |
| 3411 | } else { | 3398 | } else { |
| 3412 | root = NULL; | 3399 | root = NULL; |
| 3413 | } | 3400 | } |
| 3414 | spin_unlock(&adev->vm_manager.pasid_lock); | 3401 | spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, irqflags); |
| 3415 | 3402 | ||
| 3416 | if (!root) | 3403 | if (!root) |
| 3417 | return false; | 3404 | return false; |
| @@ -3429,11 +3416,11 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, · 11 unmodified lines | |||
| 3429 | goto error_unref; | 3416 | goto error_unref; |
| 3430 | 3417 | ||
| 3431 | /* Double check that the VM still exists */ | 3418 | /* Double check that the VM still exists */ |
| 3432 | spin_lock(&adev->vm_manager.pasid_lock); | 3419 | spin_lock_irqsave(&adev->vm_manager.pasid_lock, irqflags); |
| 3433 | vm = idr_find(&adev->vm_manager.pasid_idr, pasid); | 3420 | vm = idr_find(&adev->vm_manager.pasid_idr, pasid); |
| 3434 | if (vm && vm->root.base.bo != root) | 3421 | if (vm && vm->root.bo != root) |
| 3435 | vm = NULL; | 3422 | vm = NULL; |
| 3436 | spin_unlock(&adev->vm_manager.pasid_lock); | 3423 | spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, irqflags); |
| 3437 | if (!vm) | 3424 | if (!vm) |
| 3438 | goto error_unlock; | 3425 | goto error_unlock; |
| 3439 | 3426 | ||
| @@ -152,13 +152,6 @@ struct amdgpu_vm_bo_base { · 151 unmodified lines | |||
| 152 | bool moved; | 152 | bool moved; |
| 153 | }; | 153 | }; |
| 154 | 154 | ||
| 155 | struct amdgpu_vm_pt { | ||
| 156 | struct amdgpu_vm_bo_base base; | ||
| 157 | |||
| 158 | /* array of page tables, one for each directory entry */ | ||
| 159 | struct amdgpu_vm_pt *entries; | ||
| 160 | }; | ||
| 161 | |||
| 162 | /* provided by hw blocks that can write ptes, e.g., sdma */ | 155 | /* provided by hw blocks that can write ptes, e.g., sdma */ |
| 163 | struct amdgpu_vm_pte_funcs { | 156 | struct amdgpu_vm_pte_funcs { |
| 164 | /* number of dw to reserve per operation */ | 157 | /* number of dw to reserve per operation */ |
| @@ -284,7 +277,7 @@ struct amdgpu_vm { · 119 unmodified lines | |||
| 284 | struct list_head done; | 277 | struct list_head done; |
| 285 | 278 | ||
| 286 | /* contains the page directory */ | 279 | /* contains the page directory */ |
| 287 | struct amdgpu_vm_pt root; | 280 | struct amdgpu_vm_bo_base root; |
| 288 | struct dma_fence *last_update; | 281 | struct dma_fence *last_update; |
| 289 | 282 | ||
| 290 | /* Scheduler entities for page table updates */ | 283 | /* Scheduler entities for page table updates */ |
| @@ -112,7 +112,7 @@ static int amdgpu_vm_sdma_commit(struct amdgpu_vm_update_params *p, · 111 unmodified lines | |||
| 112 | swap(p->vm->last_unlocked, f); | 112 | swap(p->vm->last_unlocked, f); |
| 113 | dma_fence_put(tmp); | 113 | dma_fence_put(tmp); |
| 114 | } else { | 114 | } else { |
| 115 | amdgpu_bo_fence(p->vm->root.base.bo, f, true); | 115 | amdgpu_bo_fence(p->vm->root.bo, f, true); |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | if (fence && !p->immediate) | 118 | if (fence && !p->immediate) |
| @@ -6970,8 +6970,12 @@ static int gfx_v10_0_kiq_init_register(struct amdgpu_ring *ring) · 6969 unmodified lines | |||
| 6970 | if (ring->use_doorbell) { | 6970 | if (ring->use_doorbell) { |
| 6971 | WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER, | 6971 | WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER, |
| 6972 | (adev->doorbell_index.kiq * 2) << 2); | 6972 | (adev->doorbell_index.kiq * 2) << 2); |
| 6973 | /* If GC has entered CGPG, ringing doorbell > first page doesn't | ||
| 6974 | * wakeup GC. Enlarge CP_MEC_DOORBELL_RANGE_UPPER to workaround | ||
| 6975 | * this issue. | ||
| 6976 | */ | ||
| 6973 | WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER, | 6977 | WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER, |
| 6974 | (adev->doorbell_index.userqueue_end * 2) << 2); | 6978 | (adev->doorbell.size - 4)); |
| 6975 | } | 6979 | } |
| 6976 | 6980 | ||
| 6977 | WREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL, | 6981 | WREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL, |
| @@ -3675,8 +3675,12 @@ static int gfx_v9_0_kiq_init_register(struct amdgpu_ring *ring) · 3674 unmodified lines | |||
| 3675 | if (ring->use_doorbell) { | 3675 | if (ring->use_doorbell) { |
| 3676 | WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER, | 3676 | WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER, |
| 3677 | (adev->doorbell_index.kiq * 2) << 2); | 3677 | (adev->doorbell_index.kiq * 2) << 2); |
| 3678 | /* If GC has entered CGPG, ringing doorbell > first page doesn't | ||
| 3679 | * wakeup GC. Enlarge CP_MEC_DOORBELL_RANGE_UPPER to workaround | ||
| 3680 | * this issue. | ||
| 3681 | */ | ||
| 3678 | WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER, | 3682 | WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER, |
| 3679 | (adev->doorbell_index.userqueue_end * 2) << 2); | 3683 | (adev->doorbell.size - 4)); |
| 3680 | } | 3684 | } |
| 3681 | 3685 | ||
| 3682 | WREG32_SOC15_RLC(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL, | 3686 | WREG32_SOC15_RLC(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL, |
| @@ -332,11 +332,16 @@ struct psp_gfx_uresp_fwar_db_info · 331 unmodified lines | |||
| 332 | uint32_t fwar_db_addr_hi; | 332 | uint32_t fwar_db_addr_hi; |
| 333 | }; | 333 | }; |
| 334 | 334 | ||
| 335 | /* Command-specific response for boot config. */ | ||
| 336 | struct psp_gfx_uresp_bootcfg { | ||
| 337 | uint32_t boot_cfg; /* boot config data */ | ||
| 338 | }; | ||
| 339 | |||
| 335 | /* Union of command-specific responses for GPCOM ring. */ | 340 | /* Union of command-specific responses for GPCOM ring. */ |
| 336 | union psp_gfx_uresp | 341 | union psp_gfx_uresp { |
| 337 | { | 342 | struct psp_gfx_uresp_reserved reserved; |
| 338 | struct psp_gfx_uresp_reserved reserved; | 343 | struct psp_gfx_uresp_bootcfg boot_cfg; |
| 339 | struct psp_gfx_uresp_fwar_db_info fwar_db_info; | 344 | struct psp_gfx_uresp_fwar_db_info fwar_db_info; |
| 340 | }; | 345 | }; |
| 341 | 346 | ||
| 342 | /* Structure of GFX Response buffer. | 347 | /* Structure of GFX Response buffer. |
| @@ -461,6 +461,7 @@ static int psp_v11_0_ring_create(struct psp_context *psp, · 460 unmodified lines | |||
| 461 | struct amdgpu_device *adev = psp->adev; | 461 | struct amdgpu_device *adev = psp->adev; |
| 462 | 462 | ||
| 463 | if (amdgpu_sriov_vf(adev)) { | 463 | if (amdgpu_sriov_vf(adev)) { |
| 464 | ring->ring_wptr = 0; | ||
| 464 | ret = psp_v11_0_ring_stop(psp, ring_type); | 465 | ret = psp_v11_0_ring_stop(psp, ring_type); |
| 465 | if (ret) { | 466 | if (ret) { |
| 466 | DRM_ERROR("psp_v11_0_ring_stop_sriov failed!\n"); | 467 | DRM_ERROR("psp_v11_0_ring_stop_sriov failed!\n"); |
| @@ -227,6 +227,7 @@ static int psp_v3_1_ring_create(struct psp_context *psp, · 226 unmodified lines | |||
| 227 | psp_v3_1_reroute_ih(psp); | 227 | psp_v3_1_reroute_ih(psp); |
| 228 | 228 | ||
| 229 | if (amdgpu_sriov_vf(adev)) { | 229 | if (amdgpu_sriov_vf(adev)) { |
| 230 | ring->ring_wptr = 0; | ||
| 230 | ret = psp_v3_1_ring_stop(psp, ring_type); | 231 | ret = psp_v3_1_ring_stop(psp, ring_type); |
| 231 | if (ret) { | 232 | if (ret) { |
| 232 | DRM_ERROR("psp_v3_1_ring_stop_sriov failed!\n"); | 233 | DRM_ERROR("psp_v3_1_ring_stop_sriov failed!\n"); |
| @@ -1566,13 +1566,29 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, · 1565 unmodified lines | |||
| 1566 | i, args->n_devices); | 1566 | i, args->n_devices); |
| 1567 | goto unmap_memory_from_gpu_failed; | 1567 | goto unmap_memory_from_gpu_failed; |
| 1568 | } | 1568 | } |
| 1569 | kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT); | ||
| 1570 | args->n_success = i+1; | 1569 | args->n_success = i+1; |
| 1571 | } | 1570 | } |
| 1572 | kfree(devices_arr); | ||
| 1573 | |||
| 1574 | mutex_unlock(&p->mutex); | 1571 | mutex_unlock(&p->mutex); |
| 1575 | 1572 | ||
| 1573 | err = amdgpu_amdkfd_gpuvm_sync_memory(dev->kgd, (struct kgd_mem *) mem, true); | ||
| 1574 | if (err) { | ||
| 1575 | pr_debug("Sync memory failed, wait interrupted by user signal\n"); | ||
| 1576 | goto sync_memory_failed; | ||
| 1577 | } | ||
| 1578 | |||
| 1579 | /* Flush TLBs after waiting for the page table updates to complete */ | ||
| 1580 | for (i = 0; i < args->n_devices; i++) { | ||
| 1581 | peer = kfd_device_by_id(devices_arr[i]); | ||
| 1582 | if (WARN_ON_ONCE(!peer)) | ||
| 1583 | continue; | ||
| 1584 | peer_pdd = kfd_get_process_device_data(peer, p); | ||
| 1585 | if (WARN_ON_ONCE(!peer_pdd)) | ||
| 1586 | continue; | ||
| 1587 | kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT); | ||
| 1588 | } | ||
| 1589 | |||
| 1590 | kfree(devices_arr); | ||
| 1591 | |||
| 1576 | return 0; | 1592 | return 0; |
| 1577 | 1593 | ||
| 1578 | bind_process_to_device_failed: | 1594 | bind_process_to_device_failed: |
| @@ -1580,6 +1596,7 @@ get_mem_obj_from_handle_failed: · 1 unmodified line | |||
| 1580 | unmap_memory_from_gpu_failed: | 1596 | unmap_memory_from_gpu_failed: |
| 1581 | mutex_unlock(&p->mutex); | 1597 | mutex_unlock(&p->mutex); |
| 1582 | copy_from_user_failed: | 1598 | copy_from_user_failed: |
| 1599 | sync_memory_failed: | ||
| 1583 | kfree(devices_arr); | 1600 | kfree(devices_arr); |
| 1584 | return err; | 1601 | return err; |
| 1585 | } | 1602 | } |
| @@ -1780,9 +1797,6 @@ static int kfd_ioctl_svm(struct file *filep, struct kfd_process *p, void *data) · 194 unmodified lines | |||
| 1780 | struct kfd_ioctl_svm_args *args = data; | 1797 | struct kfd_ioctl_svm_args *args = data; |
| 1781 | int r = 0; | 1798 | int r = 0; |
| 1782 | 1799 | ||
| 1783 | if (p->svm_disabled) | ||
| 1784 | return -EPERM; | ||
| 1785 | |||
| 1786 | pr_debug("start 0x%llx size 0x%llx op 0x%x nattr 0x%x\n", | 1800 | pr_debug("start 0x%llx size 0x%llx op 0x%x nattr 0x%x\n", |
| 1787 | args->start_addr, args->size, args->op, args->nattr); | 1801 | args->start_addr, args->size, args->op, args->nattr); |
| 1788 | 1802 | ||
| @@ -486,9 +486,6 @@ static int destroy_queue_nocpsch_locked(struct device_queue_manager *dqm, · 485 unmodified lines | |||
| 486 | if (retval == -ETIME) | 486 | if (retval == -ETIME) |
| 487 | qpd->reset_wavefronts = true; | 487 | qpd->reset_wavefronts = true; |
| 488 | 488 | ||
| 489 | |||
| 490 | mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); | ||
| 491 | |||
| 492 | list_del(&q->list); | 489 | list_del(&q->list); |
| 493 | if (list_empty(&qpd->queues_list)) { | 490 | if (list_empty(&qpd->queues_list)) { |
| 494 | if (qpd->reset_wavefronts) { | 491 | if (qpd->reset_wavefronts) { |
| @@ -523,6 +520,8 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm, · 28 unmodified lines | |||
| 523 | int retval; | 520 | int retval; |
| 524 | uint64_t sdma_val = 0; | 521 | uint64_t sdma_val = 0; |
| 525 | struct kfd_process_device *pdd = qpd_to_pdd(qpd); | 522 | struct kfd_process_device *pdd = qpd_to_pdd(qpd); |
| 523 | struct mqd_manager *mqd_mgr = | ||
| 524 | dqm->mqd_mgrs[get_mqd_type_from_queue_type(q->properties.type)]; | ||
| 526 | 525 | ||
| 527 | /* Get the SDMA queue stats */ | 526 | /* Get the SDMA queue stats */ |
| 528 | if ((q->properties.type == KFD_QUEUE_TYPE_SDMA) || | 527 | if ((q->properties.type == KFD_QUEUE_TYPE_SDMA) || |
| @@ -540,6 +539,8 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm, · 11 unmodified lines | |||
| 540 | pdd->sdma_past_activity_counter += sdma_val; | 539 | pdd->sdma_past_activity_counter += sdma_val; |
| 541 | dqm_unlock(dqm); | 540 | dqm_unlock(dqm); |
| 542 | 541 | ||
| 542 | mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); | ||
| 543 | |||
| 543 | return retval; | 544 | return retval; |
| 544 | } | 545 | } |
| 545 | 546 | ||
| @@ -1629,7 +1630,7 @@ out: · 1083 unmodified lines | |||
| 1629 | static int process_termination_nocpsch(struct device_queue_manager *dqm, | 1630 | static int process_termination_nocpsch(struct device_queue_manager *dqm, |
| 1630 | struct qcm_process_device *qpd) | 1631 | struct qcm_process_device *qpd) |
| 1631 | { | 1632 | { |
| 1632 | struct queue *q, *next; | 1633 | struct queue *q; |
| 1633 | struct device_process_node *cur, *next_dpn; | 1634 | struct device_process_node *cur, *next_dpn; |
| 1634 | int retval = 0; | 1635 | int retval = 0; |
| 1635 | bool found = false; | 1636 | bool found = false; |
| @@ -1637,12 +1638,19 @@ static int process_termination_nocpsch(struct device_queue_manager *dqm, · 1 unmodified line | |||
| 1637 | dqm_lock(dqm); | 1638 | dqm_lock(dqm); |
| 1638 | 1639 | ||
| 1639 | /* Clear all user mode queues */ | 1640 | /* Clear all user mode queues */ |
| 1640 | list_for_each_entry_safe(q, next, &qpd->queues_list, list) { | 1641 | while (!list_empty(&qpd->queues_list)) { |
| 1642 | struct mqd_manager *mqd_mgr; | ||
| 1641 | int ret; | 1643 | int ret; |
| 1642 | 1644 | ||
| 1645 | q = list_first_entry(&qpd->queues_list, struct queue, list); | ||
| 1646 | mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( | ||
| 1647 | q->properties.type)]; | ||
| 1643 | ret = destroy_queue_nocpsch_locked(dqm, qpd, q); | 1648 | ret = destroy_queue_nocpsch_locked(dqm, qpd, q); |
| 1644 | if (ret) | 1649 | if (ret) |
| 1645 | retval = ret; | 1650 | retval = ret; |
| 1651 | dqm_unlock(dqm); | ||
| 1652 | mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); | ||
| 1653 | dqm_lock(dqm); | ||
| 1646 | } | 1654 | } |
| 1647 | 1655 | ||
| 1648 | /* Unregister process */ | 1656 | /* Unregister process */ |
| @@ -1674,29 +1682,27 @@ static int get_wave_state(struct device_queue_manager *dqm, · 25 unmodified lines | |||
| 1674 | u32 *save_area_used_size) | 1682 | u32 *save_area_used_size) |
| 1675 | { | 1683 | { |
| 1676 | struct mqd_manager *mqd_mgr; | 1684 | struct mqd_manager *mqd_mgr; |
| 1677 | int r; | ||
| 1678 | 1685 | ||
| 1679 | dqm_lock(dqm); | 1686 | dqm_lock(dqm); |
| 1680 | 1687 | ||
| 1681 | if (q->properties.type != KFD_QUEUE_TYPE_COMPUTE || | ||
| 1682 | q->properties.is_active || !q->device->cwsr_enabled) { | ||
| 1683 | r = -EINVAL; | ||
| 1684 | goto dqm_unlock; | ||
| 1685 | } | ||
| 1686 | |||
| 1687 | mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_CP]; | 1688 | mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_CP]; |
| 1688 | 1689 | ||
| 1689 | if (!mqd_mgr->get_wave_state) { | 1690 | if (q->properties.type != KFD_QUEUE_TYPE_COMPUTE || |
| 1690 | r = -EINVAL; | 1691 | q->properties.is_active || !q->device->cwsr_enabled || |
| 1691 | goto dqm_unlock; | 1692 | !mqd_mgr->get_wave_state) { |
| 1693 | dqm_unlock(dqm); | ||
| 1694 | return -EINVAL; | ||
| 1692 | } | 1695 | } |
| 1693 | 1696 | ||
| 1694 | r = mqd_mgr->get_wave_state(mqd_mgr, q->mqd, ctl_stack, | ||
| 1695 | ctl_stack_used_size, save_area_used_size); | ||
| 1696 | |||
| 1697 | dqm_unlock: | ||
| 1698 | dqm_unlock(dqm); | 1697 | dqm_unlock(dqm); |
| 1699 | return r; | 1698 | |
| 1699 | /* | ||
| 1700 | * get_wave_state is outside the dqm lock to prevent circular locking | ||
| 1701 | * and the queue should be protected against destruction by the process | ||
| 1702 | * lock. | ||
| 1703 | */ | ||
| 1704 | return mqd_mgr->get_wave_state(mqd_mgr, q->mqd, ctl_stack, | ||
| 1705 | ctl_stack_used_size, save_area_used_size); | ||
| 1700 | } | 1706 | } |
| 1701 | 1707 | ||
| 1702 | static int process_termination_cpsch(struct device_queue_manager *dqm, | 1708 | static int process_termination_cpsch(struct device_queue_manager *dqm, |
| @@ -405,10 +405,6 @@ int kfd_init_apertures(struct kfd_process *process) · 404 unmodified lines | |||
| 405 | case CHIP_POLARIS12: | 405 | case CHIP_POLARIS12: |
| 406 | case CHIP_VEGAM: | 406 | case CHIP_VEGAM: |
| 407 | kfd_init_apertures_vi(pdd, id); | 407 | kfd_init_apertures_vi(pdd, id); |
| 408 | /* VI GPUs cannot support SVM with only | ||
| 409 | * 40 bits of virtual address space. | ||
| 410 | */ | ||
| 411 | process->svm_disabled = true; | ||
| 412 | break; | 408 | break; |
| 413 | case CHIP_VEGA10: | 409 | case CHIP_VEGA10: |
| 414 | case CHIP_VEGA12: | 410 | case CHIP_VEGA12: |
| @@ -743,6 +743,7 @@ struct svm_range_list { · 742 unmodified lines | |||
| 743 | spinlock_t deferred_list_lock; | 743 | spinlock_t deferred_list_lock; |
| 744 | atomic_t evicted_ranges; | 744 | atomic_t evicted_ranges; |
| 745 | struct delayed_work restore_work; | 745 | struct delayed_work restore_work; |
| 746 | DECLARE_BITMAP(bitmap_supported, MAX_GPU_INSTANCE); | ||
| 746 | }; | 747 | }; |
| 747 | 748 | ||
| 748 | /* Process data */ | 749 | /* Process data */ |
| @@ -826,7 +827,6 @@ struct kfd_process { · 77 unmodified lines | |||
| 826 | 827 | ||
| 827 | /* shared virtual memory registered by this process */ | 828 | /* shared virtual memory registered by this process */ |
| 828 | struct svm_range_list svms; | 829 | struct svm_range_list svms; |
| 829 | bool svm_disabled; | ||
| 830 | 830 | ||
| 831 | bool xnack_enabled; | 831 | bool xnack_enabled; |
| 832 | }; | 832 | }; |
| @@ -1260,7 +1260,6 @@ static struct kfd_process *create_process(const struct task_struct *thread) · 1259 unmodified lines | |||
| 1260 | process->mm = thread->mm; | 1260 | process->mm = thread->mm; |
| 1261 | process->lead_thread = thread->group_leader; | 1261 | process->lead_thread = thread->group_leader; |
| 1262 | process->n_pdds = 0; | 1262 | process->n_pdds = 0; |
| 1263 | process->svm_disabled = false; | ||
| 1264 | INIT_DELAYED_WORK(&process->eviction_work, evict_process_worker); | 1263 | INIT_DELAYED_WORK(&process->eviction_work, evict_process_worker); |
| 1265 | INIT_DELAYED_WORK(&process->restore_work, restore_process_worker); | 1264 | INIT_DELAYED_WORK(&process->restore_work, restore_process_worker); |
| 1266 | process->last_restore_timestamp = get_jiffies_64(); | 1265 | process->last_restore_timestamp = get_jiffies_64(); |
| @@ -281,7 +281,8 @@ svm_range *svm_range_new(struct svm_range_list *svms, uint64_t start, · 280 unmodified lines | |||
| 281 | 281 | ||
| 282 | p = container_of(svms, struct kfd_process, svms); | 282 | p = container_of(svms, struct kfd_process, svms); |
| 283 | if (p->xnack_enabled) | 283 | if (p->xnack_enabled) |
| 284 | bitmap_fill(prange->bitmap_access, MAX_GPU_INSTANCE); | 284 | bitmap_copy(prange->bitmap_access, svms->bitmap_supported, |
| 285 | MAX_GPU_INSTANCE); | ||
| 285 | 286 | ||
| 286 | svm_range_set_default_attributes(&prange->preferred_loc, | 287 | svm_range_set_default_attributes(&prange->preferred_loc, |
| 287 | &prange->prefetch_loc, | 288 | &prange->prefetch_loc, |
| @@ -577,36 +578,25 @@ svm_range_check_attr(struct kfd_process *p, · 289 unmodified lines | |||
| 577 | uint32_t nattr, struct kfd_ioctl_svm_attribute *attrs) | 578 | uint32_t nattr, struct kfd_ioctl_svm_attribute *attrs) |
| 578 | { | 579 | { |
| 579 | uint32_t i; | 580 | uint32_t i; |
| 580 | int gpuidx; | ||
| 581 | 581 | ||
| 582 | for (i = 0; i < nattr; i++) { | 582 | for (i = 0; i < nattr; i++) { |
| 583 | uint32_t val = attrs[i].value; | ||
| 584 | int gpuidx = MAX_GPU_INSTANCE; | ||
| 585 | |||
| 583 | switch (attrs[i].type) { | 586 | switch (attrs[i].type) { |
| 584 | case KFD_IOCTL_SVM_ATTR_PREFERRED_LOC: | 587 | case KFD_IOCTL_SVM_ATTR_PREFERRED_LOC: |
| 585 | if (attrs[i].value != KFD_IOCTL_SVM_LOCATION_SYSMEM && | 588 | if (val != KFD_IOCTL_SVM_LOCATION_SYSMEM && |
| 586 | attrs[i].value != KFD_IOCTL_SVM_LOCATION_UNDEFINED && | 589 | val != KFD_IOCTL_SVM_LOCATION_UNDEFINED) |
| 587 | kfd_process_gpuidx_from_gpuid(p, | 590 | gpuidx = kfd_process_gpuidx_from_gpuid(p, val); |
| 588 | attrs[i].value) < 0) { | ||
| 589 | pr_debug("no GPU 0x%x found\n", attrs[i].value); | ||
| 590 | return -EINVAL; | ||
| 591 | } | ||
| 592 | break; | 591 | break; |
| 593 | case KFD_IOCTL_SVM_ATTR_PREFETCH_LOC: | 592 | case KFD_IOCTL_SVM_ATTR_PREFETCH_LOC: |
| 594 | if (attrs[i].value != KFD_IOCTL_SVM_LOCATION_SYSMEM && | 593 | if (val != KFD_IOCTL_SVM_LOCATION_SYSMEM) |
| 595 | kfd_process_gpuidx_from_gpuid(p, | 594 | gpuidx = kfd_process_gpuidx_from_gpuid(p, val); |
| 596 | attrs[i].value) < 0) { | ||
| 597 | pr_debug("no GPU 0x%x found\n", attrs[i].value); | ||
| 598 | return -EINVAL; | ||
| 599 | } | ||
| 600 | break; | 595 | break; |
| 601 | case KFD_IOCTL_SVM_ATTR_ACCESS: | 596 | case KFD_IOCTL_SVM_ATTR_ACCESS: |
| 602 | case KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE: | 597 | case KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE: |
| 603 | case KFD_IOCTL_SVM_ATTR_NO_ACCESS: | 598 | case KFD_IOCTL_SVM_ATTR_NO_ACCESS: |
| 604 | gpuidx = kfd_process_gpuidx_from_gpuid(p, | 599 | gpuidx = kfd_process_gpuidx_from_gpuid(p, val); |
| 605 | attrs[i].value); | ||
| 606 | if (gpuidx < 0) { | ||
| 607 | pr_debug("no GPU 0x%x found\n", attrs[i].value); | ||
| 608 | return -EINVAL; | ||
| 609 | } | ||
| 610 | break; | 600 | break; |
| 611 | case KFD_IOCTL_SVM_ATTR_SET_FLAGS: | 601 | case KFD_IOCTL_SVM_ATTR_SET_FLAGS: |
| 612 | break; | 602 | break; |
| @@ -618,6 +608,15 @@ svm_range_check_attr(struct kfd_process *p, · 5 unmodified lines | |||
| 618 | pr_debug("unknown attr type 0x%x\n", attrs[i].type); | 608 | pr_debug("unknown attr type 0x%x\n", attrs[i].type); |
| 619 | return -EINVAL; | 609 | return -EINVAL; |
| 620 | } | 610 | } |
| 611 | |||
| 612 | if (gpuidx < 0) { | ||
| 613 | pr_debug("no GPU 0x%x found\n", val); | ||
| 614 | return -EINVAL; | ||
| 615 | } else if (gpuidx < MAX_GPU_INSTANCE && | ||
| 616 | !test_bit(gpuidx, p->svms.bitmap_supported)) { | ||
| 617 | pr_debug("GPU 0x%x not supported\n", val); | ||
| 618 | return -EINVAL; | ||
| 619 | } | ||
| 621 | } | 620 | } |
| 622 | 621 | ||
| 623 | return 0; | 622 | return 0; |
| @@ -1274,7 +1273,7 @@ static int svm_range_reserve_bos(struct svm_validate_context *ctx) · 650 unmodified lines | |||
| 1274 | adev = (struct amdgpu_device *)pdd->dev->kgd; | 1273 | adev = (struct amdgpu_device *)pdd->dev->kgd; |
| 1275 | vm = drm_priv_to_vm(pdd->drm_priv); | 1274 | vm = drm_priv_to_vm(pdd->drm_priv); |
| 1276 | 1275 | ||
| 1277 | ctx->tv[gpuidx].bo = &vm->root.base.bo->tbo; | 1276 | ctx->tv[gpuidx].bo = &vm->root.bo->tbo; |
| 1278 | ctx->tv[gpuidx].num_shared = 4; | 1277 | ctx->tv[gpuidx].num_shared = 4; |
| 1279 | list_add(&ctx->tv[gpuidx].head, &ctx->validate_list); | 1278 | list_add(&ctx->tv[gpuidx].head, &ctx->validate_list); |
| 1280 | } | 1279 | } |
| @@ -1855,7 +1854,7 @@ static void svm_range_drain_retry_fault(struct svm_range_list *svms) · 574 unmodified lines | |||
| 1855 | 1854 | ||
| 1856 | p = container_of(svms, struct kfd_process, svms); | 1855 | p = container_of(svms, struct kfd_process, svms); |
| 1857 | 1856 | ||
| 1858 | for (i = 0; i < p->n_pdds; i++) { | 1857 | for_each_set_bit(i, svms->bitmap_supported, p->n_pdds) { |
| 1859 | pdd = p->pdds[i]; | 1858 | pdd = p->pdds[i]; |
| 1860 | if (!pdd) | 1859 | if (!pdd) |
| 1861 | continue; | 1860 | continue; |
| @@ -2325,6 +2324,11 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, · 463 unmodified lines | |||
| 2325 | bool write_locked = false; | 2324 | bool write_locked = false; |
| 2326 | int r = 0; | 2325 | int r = 0; |
| 2327 | 2326 | ||
| 2327 | if (!KFD_IS_SVM_API_SUPPORTED(adev->kfd.dev)) { | ||
| 2328 | pr_debug("device does not support SVM\n"); | ||
| 2329 | return -EFAULT; | ||
| 2330 | } | ||
| 2331 | |||
| 2328 | p = kfd_lookup_process_by_pasid(pasid); | 2332 | p = kfd_lookup_process_by_pasid(pasid); |
| 2329 | if (!p) { | 2333 | if (!p) { |
| 2330 | pr_debug("kfd process not founded pasid 0x%x\n", pasid); | 2334 | pr_debug("kfd process not founded pasid 0x%x\n", pasid); |
| @@ -2472,6 +2476,7 @@ void svm_range_list_fini(struct kfd_process *p) · 141 unmodified lines | |||
| 2472 | int svm_range_list_init(struct kfd_process *p) | 2476 | int svm_range_list_init(struct kfd_process *p) |
| 2473 | { | 2477 | { |
| 2474 | struct svm_range_list *svms = &p->svms; | 2478 | struct svm_range_list *svms = &p->svms; |
| 2479 | int i; | ||
| 2475 | 2480 | ||
| 2476 | svms->objects = RB_ROOT_CACHED; | 2481 | svms->objects = RB_ROOT_CACHED; |
| 2477 | mutex_init(&svms->lock); | 2482 | mutex_init(&svms->lock); |
| @@ -2482,6 +2487,10 @@ int svm_range_list_init(struct kfd_process *p) · 4 unmodified lines | |||
| 2482 | INIT_LIST_HEAD(&svms->deferred_range_list); | 2487 | INIT_LIST_HEAD(&svms->deferred_range_list); |
| 2483 | spin_lock_init(&svms->deferred_list_lock); | 2488 | spin_lock_init(&svms->deferred_list_lock); |
| 2484 | 2489 | ||
| 2490 | for (i = 0; i < p->n_pdds; i++) | ||
| 2491 | if (KFD_IS_SVM_API_SUPPORTED(p->pdds[i]->dev)) | ||
| 2492 | bitmap_set(svms->bitmap_supported, i, 1); | ||
| 2493 | |||
| 2485 | return 0; | 2494 | return 0; |
| 2486 | } | 2495 | } |
| 2487 | 2496 | ||
| @@ -2978,14 +2987,15 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size, · 490 unmodified lines | |||
| 2978 | svm_range_set_default_attributes(&location, &prefetch_loc, | 2987 | svm_range_set_default_attributes(&location, &prefetch_loc, |
| 2979 | &granularity, &flags); | 2988 | &granularity, &flags); |
| 2980 | if (p->xnack_enabled) | 2989 | if (p->xnack_enabled) |
| 2981 | bitmap_fill(bitmap_access, MAX_GPU_INSTANCE); | 2990 | bitmap_copy(bitmap_access, svms->bitmap_supported, |
| 2991 | MAX_GPU_INSTANCE); | ||
| 2982 | else | 2992 | else |
| 2983 | bitmap_zero(bitmap_access, MAX_GPU_INSTANCE); | 2993 | bitmap_zero(bitmap_access, MAX_GPU_INSTANCE); |
| 2984 | bitmap_zero(bitmap_aip, MAX_GPU_INSTANCE); | 2994 | bitmap_zero(bitmap_aip, MAX_GPU_INSTANCE); |
| 2985 | goto fill_values; | 2995 | goto fill_values; |
| 2986 | } | 2996 | } |
| 2987 | bitmap_fill(bitmap_access, MAX_GPU_INSTANCE); | 2997 | bitmap_copy(bitmap_access, svms->bitmap_supported, MAX_GPU_INSTANCE); |
| 2988 | bitmap_fill(bitmap_aip, MAX_GPU_INSTANCE); | 2998 | bitmap_copy(bitmap_aip, svms->bitmap_supported, MAX_GPU_INSTANCE); |
| 2989 | 2999 | ||
| 2990 | while (node) { | 3000 | while (node) { |
| 2991 | struct interval_tree_node *next; | 3001 | struct interval_tree_node *next; |
| @@ -175,6 +175,11 @@ void svm_range_dma_unmap(struct device *dev, dma_addr_t *dma_addr, · 174 unmodified lines | |||
| 175 | void svm_range_free_dma_mappings(struct svm_range *prange); | 175 | void svm_range_free_dma_mappings(struct svm_range *prange); |
| 176 | void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm); | 176 | void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm); |
| 177 | 177 | ||
| 178 | /* SVM API and HMM page migration work together, device memory type | ||
| 179 | * is initialized to not 0 when page migration register device memory. | ||
| 180 | */ | ||
| 181 | #define KFD_IS_SVM_API_SUPPORTED(dev) ((dev)->pgmap.type != 0) | ||
| 182 | |||
| 178 | #else | 183 | #else |
| 179 | 184 | ||
| 180 | struct kfd_process; | 185 | struct kfd_process; |
| @@ -201,6 +206,8 @@ static inline int svm_range_schedule_evict_svm_bo( · 20 unmodified lines | |||
| 201 | return -EINVAL; | 206 | return -EINVAL; |
| 202 | } | 207 | } |
| 203 | 208 | ||
| 209 | #define KFD_IS_SVM_API_SUPPORTED(dev) false | ||
| 210 | |||
| 204 | #endif /* IS_ENABLED(CONFIG_HSA_AMD_SVM) */ | 211 | #endif /* IS_ENABLED(CONFIG_HSA_AMD_SVM) */ |
| 205 | 212 | ||
| 206 | #endif /* KFD_SVM_H_ */ | 213 | #endif /* KFD_SVM_H_ */ |
| @@ -36,6 +36,7 @@ · 35 unmodified lines | |||
| 36 | #include "kfd_topology.h" | 36 | #include "kfd_topology.h" |
| 37 | #include "kfd_device_queue_manager.h" | 37 | #include "kfd_device_queue_manager.h" |
| 38 | #include "kfd_iommu.h" | 38 | #include "kfd_iommu.h" |
| 39 | #include "kfd_svm.h" | ||
| 39 | #include "amdgpu_amdkfd.h" | 40 | #include "amdgpu_amdkfd.h" |
| 40 | #include "amdgpu_ras.h" | 41 | #include "amdgpu_ras.h" |
| 41 | 42 | ||
| @@ -1441,10 +1442,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu) · 1399 unmodified lines | |||
| 1441 | dev->node_props.capability |= (adev->ras_enabled != 0) ? | 1442 | dev->node_props.capability |= (adev->ras_enabled != 0) ? |
| 1442 | HSA_CAP_RASEVENTNOTIFY : 0; | 1443 | HSA_CAP_RASEVENTNOTIFY : 0; |
| 1443 | 1444 | ||
| 1444 | /* SVM API and HMM page migration work together, device memory type | 1445 | if (KFD_IS_SVM_API_SUPPORTED(adev->kfd.dev)) |
| 1445 | * is initialized to not 0 when page migration register device memory. | ||
| 1446 | */ | ||
| 1447 | if (adev->kfd.dev->pgmap.type != 0) | ||
| 1448 | dev->node_props.capability |= HSA_CAP_SVMAPI_SUPPORTED; | 1446 | dev->node_props.capability |= HSA_CAP_SVMAPI_SUPPORTED; |
| 1449 | 1447 | ||
| 1450 | kfd_debug_print_topology(); | 1448 | kfd_debug_print_topology(); |
| @@ -54,8 +54,8 @@ · 53 unmodified lines | |||
| 54 | #define HSA_CAP_ASIC_REVISION_SHIFT 22 | 54 | #define HSA_CAP_ASIC_REVISION_SHIFT 22 |
| 55 | #define HSA_CAP_SRAM_EDCSUPPORTED 0x04000000 | 55 | #define HSA_CAP_SRAM_EDCSUPPORTED 0x04000000 |
| 56 | #define HSA_CAP_SVMAPI_SUPPORTED 0x08000000 | 56 | #define HSA_CAP_SVMAPI_SUPPORTED 0x08000000 |
| 57 | 57 | #define HSA_CAP_FLAGS_COHERENTHOSTACCESS 0x10000000 | |
| 58 | #define HSA_CAP_RESERVED 0xf00f8000 | 58 | #define HSA_CAP_RESERVED 0xe00f8000 |
| 59 | 59 | ||
| 60 | struct kfd_node_properties { | 60 | struct kfd_node_properties { |
| 61 | uint64_t hive_id; | 61 | uint64_t hive_id; |
| @@ -101,8 +101,7 @@ struct kfd_node_properties { · 39 unmodified lines | |||
| 101 | 101 | ||
| 102 | #define HSA_MEM_FLAGS_HOT_PLUGGABLE 0x00000001 | 102 | #define HSA_MEM_FLAGS_HOT_PLUGGABLE 0x00000001 |
| 103 | #define HSA_MEM_FLAGS_NON_VOLATILE 0x00000002 | 103 | #define HSA_MEM_FLAGS_NON_VOLATILE 0x00000002 |
| 104 | #define HSA_MEM_FLAGS_COHERENTHOSTACCESS 0x00000004 | 104 | #define HSA_MEM_FLAGS_RESERVED 0xfffffffc |
| 105 | #define HSA_MEM_FLAGS_RESERVED 0xfffffff8 | ||
| 106 | 105 | ||
| 107 | struct kfd_mem_properties { | 106 | struct kfd_mem_properties { |
| 108 | struct list_head list; | 107 | struct list_head list; |
| @@ -28,7 +28,7 @@ · 27 unmodified lines | |||
| 28 | AMDGPUDM = amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o amdgpu_dm_color.o | 28 | AMDGPUDM = amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o amdgpu_dm_color.o |
| 29 | 29 | ||
| 30 | ifneq ($(CONFIG_DRM_AMD_DC),) | 30 | ifneq ($(CONFIG_DRM_AMD_DC),) |
| 31 | AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o amdgpu_dm_pp_smu.o | 31 | AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o amdgpu_dm_pp_smu.o amdgpu_dm_psr.o |
| 32 | endif | 32 | endif |
| 33 | 33 | ||
| 34 | ifdef CONFIG_DRM_AMD_DC_HDCP | 34 | ifdef CONFIG_DRM_AMD_DC_HDCP |
| @@ -58,6 +58,7 @@ · 57 unmodified lines | |||
| 58 | #if defined(CONFIG_DEBUG_FS) | 58 | #if defined(CONFIG_DEBUG_FS) |
| 59 | #include "amdgpu_dm_debugfs.h" | 59 | #include "amdgpu_dm_debugfs.h" |
| 60 | #endif | 60 | #endif |
| 61 | #include "amdgpu_dm_psr.h" | ||
| 61 | 62 | ||
| 62 | #include "ivsrcid/ivsrcid_vislands30.h" | 63 | #include "ivsrcid/ivsrcid_vislands30.h" |
| 63 | 64 | ||
| @@ -213,12 +214,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, · 149 unmodified lines | |||
| 213 | static void handle_cursor_update(struct drm_plane *plane, | 214 | static void handle_cursor_update(struct drm_plane *plane, |
| 214 | struct drm_plane_state *old_plane_state); | 215 | struct drm_plane_state *old_plane_state); |
| 215 | 216 | ||
| 216 | static void amdgpu_dm_set_psr_caps(struct dc_link *link); | ||
| 217 | static bool amdgpu_dm_psr_enable(struct dc_stream_state *stream); | ||
| 218 | static bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream); | ||
| 219 | static bool amdgpu_dm_psr_disable(struct dc_stream_state *stream); | ||
| 220 | static bool amdgpu_dm_psr_disable_all(struct amdgpu_display_manager *dm); | ||
| 221 | |||
| 222 | static const struct drm_format_info * | 217 | static const struct drm_format_info * |
| 223 | amd_get_format_info(const struct drm_mode_fb_cmd2 *cmd); | 218 | amd_get_format_info(const struct drm_mode_fb_cmd2 *cmd); |
| 224 | 219 | ||
| @@ -10245,6 +10240,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, · 10020 unmodified lines | |||
| 10245 | dm_old_crtc_state->dsc_force_changed == false) | 10240 | dm_old_crtc_state->dsc_force_changed == false) |
| 10246 | continue; | 10241 | continue; |
| 10247 | 10242 | ||
| 10243 | ret = amdgpu_dm_verify_lut_sizes(new_crtc_state); | ||
| 10244 | if (ret) | ||
| 10245 | goto fail; | ||
| 10246 | |||
| 10248 | if (!new_crtc_state->enable) | 10247 | if (!new_crtc_state->enable) |
| 10249 | continue; | 10248 | continue; |
| 10250 | 10249 | ||
| @@ -10725,136 +10724,6 @@ update: · 474 unmodified lines | |||
| 10725 | freesync_capable); | 10724 | freesync_capable); |
| 10726 | } | 10725 | } |
| 10727 | 10726 | ||
| 10728 | static void amdgpu_dm_set_psr_caps(struct dc_link *link) | ||
| 10729 | { | ||
| 10730 | uint8_t dpcd_data[EDP_PSR_RECEIVER_CAP_SIZE]; | ||
| 10731 | |||
| 10732 | if (!(link->connector_signal & SIGNAL_TYPE_EDP)) | ||
| 10733 | return; | ||
| 10734 | if (link->type == dc_connection_none) | ||
| 10735 | return; | ||
| 10736 | if (dm_helpers_dp_read_dpcd(NULL, link, DP_PSR_SUPPORT, | ||
| 10737 | dpcd_data, sizeof(dpcd_data))) { | ||
| 10738 | link->dpcd_caps.psr_caps.psr_version = dpcd_data[0]; | ||
| 10739 | |||
| 10740 | if (dpcd_data[0] == 0) { | ||
| 10741 | link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED; | ||
| 10742 | link->psr_settings.psr_feature_enabled = false; | ||
| 10743 | } else { | ||
| 10744 | link->psr_settings.psr_version = DC_PSR_VERSION_1; | ||
| 10745 | link->psr_settings.psr_feature_enabled = true; | ||
| 10746 | } | ||
| 10747 | |||
| 10748 | DRM_INFO("PSR support:%d\n", link->psr_settings.psr_feature_enabled); | ||
| 10749 | } | ||
| 10750 | } | ||
| 10751 | |||
| 10752 | /* | ||
| 10753 | * amdgpu_dm_link_setup_psr() - configure psr link | ||
| 10754 | * @stream: stream state | ||
| 10755 | * | ||
| 10756 | * Return: true if success | ||
| 10757 | */ | ||
| 10758 | static bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream) | ||
| 10759 | { | ||
| 10760 | struct dc_link *link = NULL; | ||
| 10761 | struct psr_config psr_config = {0}; | ||
| 10762 | struct psr_context psr_context = {0}; | ||
| 10763 | bool ret = false; | ||
| 10764 | |||
| 10765 | if (stream == NULL) | ||
| 10766 | return false; | ||
| 10767 | |||
| 10768 | link = stream->link; | ||
| 10769 | |||
| 10770 | psr_config.psr_version = link->dpcd_caps.psr_caps.psr_version; | ||
| 10771 | |||
| 10772 | if (psr_config.psr_version > 0) { | ||
| 10773 | psr_config.psr_exit_link_training_required = 0x1; | ||
| 10774 | psr_config.psr_frame_capture_indication_req = 0; | ||
| 10775 | psr_config.psr_rfb_setup_time = 0x37; | ||
| 10776 | psr_config.psr_sdp_transmit_line_num_deadline = 0x20; | ||
| 10777 | psr_config.allow_smu_optimizations = 0x0; | ||
| 10778 | |||
| 10779 | ret = dc_link_setup_psr(link, stream, &psr_config, &psr_context); | ||
| 10780 | |||
| 10781 | } | ||
| 10782 | DRM_DEBUG_DRIVER("PSR link: %d\n", link->psr_settings.psr_feature_enabled); | ||
| 10783 | |||
| 10784 | return ret; | ||
| 10785 | } | ||
| 10786 | |||
| 10787 | /* | ||
| 10788 | * amdgpu_dm_psr_enable() - enable psr f/w | ||
| 10789 | * @stream: stream state | ||
| 10790 | * | ||
| 10791 | * Return: true if success | ||
| 10792 | */ | ||
| 10793 | bool amdgpu_dm_psr_enable(struct dc_stream_state *stream) | ||
| 10794 | { | ||
| 10795 | struct dc_link *link = stream->link; | ||
| 10796 | unsigned int vsync_rate_hz = 0; | ||
| 10797 | struct dc_static_screen_params params = {0}; | ||
| 10798 | /* Calculate number of static frames before generating interrupt to | ||
| 10799 | * enter PSR. | ||
| 10800 | */ | ||
| 10801 | // Init fail safe of 2 frames static | ||
| 10802 | unsigned int num_frames_static = 2; | ||
| 10803 | |||
| 10804 | DRM_DEBUG_DRIVER("Enabling psr...\n"); | ||
| 10805 | |||
| 10806 | vsync_rate_hz = div64_u64(div64_u64(( | ||
| 10807 | stream->timing.pix_clk_100hz * 100), | ||
| 10808 | stream->timing.v_total), | ||
| 10809 | stream->timing.h_total); | ||
| 10810 | |||
| 10811 | /* Round up | ||
| 10812 | * Calculate number of frames such that at least 30 ms of time has | ||
| 10813 | * passed. | ||
| 10814 | */ | ||
| 10815 | if (vsync_rate_hz != 0) { | ||
| 10816 | unsigned int frame_time_microsec = 1000000 / vsync_rate_hz; | ||
| 10817 | num_frames_static = (30000 / frame_time_microsec) + 1; | ||
| 10818 | } | ||
| 10819 | |||
| 10820 | params.triggers.cursor_update = true; | ||
| 10821 | params.triggers.overlay_update = true; | ||
| 10822 | params.triggers.surface_update = true; | ||
| 10823 | params.num_frames = num_frames_static; | ||
| 10824 | |||
| 10825 | dc_stream_set_static_screen_params(link->ctx->dc, | ||
| 10826 | &stream, 1, | ||
| 10827 | ¶ms); | ||
| 10828 | |||
| 10829 | return dc_link_set_psr_allow_active(link, true, false, false); | ||
| 10830 | } | ||
| 10831 | |||
| 10832 | /* | ||
| 10833 | * amdgpu_dm_psr_disable() - disable psr f/w | ||
| 10834 | * @stream: stream state | ||
| 10835 | * | ||
| 10836 | * Return: true if success | ||
| 10837 | */ | ||
| 10838 | static bool amdgpu_dm_psr_disable(struct dc_stream_state *stream) | ||
| 10839 | { | ||
| 10840 | |||
| 10841 | DRM_DEBUG_DRIVER("Disabling psr...\n"); | ||
| 10842 | |||
| 10843 | return dc_link_set_psr_allow_active(stream->link, false, true, false); | ||
| 10844 | } | ||
| 10845 | |||
| 10846 | /* | ||
| 10847 | * amdgpu_dm_psr_disable() - disable psr f/w | ||
| 10848 | * if psr is enabled on any stream | ||
| 10849 | * | ||
| 10850 | * Return: true if success | ||
| 10851 | */ | ||
| 10852 | static bool amdgpu_dm_psr_disable_all(struct amdgpu_display_manager *dm) | ||
| 10853 | { | ||
| 10854 | DRM_DEBUG_DRIVER("Disabling psr if psr is enabled on any stream\n"); | ||
| 10855 | return dc_set_psr_allow_active(dm->dc, false); | ||
| 10856 | } | ||
| 10857 | |||
| 10858 | void amdgpu_dm_trigger_timing_sync(struct drm_device *dev) | 10727 | void amdgpu_dm_trigger_timing_sync(struct drm_device *dev) |
| 10859 | { | 10728 | { |
| 10860 | struct amdgpu_device *adev = drm_to_adev(dev); | 10729 | struct amdgpu_device *adev = drm_to_adev(dev); |
| @@ -617,6 +617,7 @@ void amdgpu_dm_trigger_timing_sync(struct drm_device *dev); · 616 unmodified lines | |||
| 617 | #define MAX_COLOR_LEGACY_LUT_ENTRIES 256 | 617 | #define MAX_COLOR_LEGACY_LUT_ENTRIES 256 |
| 618 | 618 | ||
| 619 | void amdgpu_dm_init_color_mod(void); | 619 | void amdgpu_dm_init_color_mod(void); |
| 620 | int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state); | ||
| 620 | int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc); | 621 | int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc); |
| 621 | int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, | 622 | int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, |
| 622 | struct dc_plane_state *dc_plane_state); | 623 | struct dc_plane_state *dc_plane_state); |
| @@ -284,6 +284,37 @@ static int __set_input_tf(struct dc_transfer_func *func, · 283 unmodified lines | |||
| 284 | return res ? 0 : -ENOMEM; | 284 | return res ? 0 : -ENOMEM; |
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | /** | ||
| 288 | * Verifies that the Degamma and Gamma LUTs attached to the |crtc_state| are of | ||
| 289 | * the expected size. | ||
| 290 | * Returns 0 on success. | ||
| 291 | */ | ||
| 292 | int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state) | ||
| 293 | { | ||
| 294 | const struct drm_color_lut *lut = NULL; | ||
| 295 | uint32_t size = 0; | ||
| 296 | |||
| 297 | lut = __extract_blob_lut(crtc_state->degamma_lut, &size); | ||
| 298 | if (lut && size != MAX_COLOR_LUT_ENTRIES) { | ||
| 299 | DRM_DEBUG_DRIVER( | ||
| 300 | "Invalid Degamma LUT size. Should be %u but got %u.\n", | ||
| 301 | MAX_COLOR_LUT_ENTRIES, size); | ||
| 302 | return -EINVAL; | ||
| 303 | } | ||
| 304 | |||
| 305 | lut = __extract_blob_lut(crtc_state->gamma_lut, &size); | ||
| 306 | if (lut && size != MAX_COLOR_LUT_ENTRIES && | ||
| 307 | size != MAX_COLOR_LEGACY_LUT_ENTRIES) { | ||
| 308 | DRM_DEBUG_DRIVER( | ||
| 309 | "Invalid Gamma LUT size. Should be %u (or %u for legacy) but got %u.\n", | ||
| 310 | MAX_COLOR_LUT_ENTRIES, MAX_COLOR_LEGACY_LUT_ENTRIES, | ||
| 311 | size); | ||
| 312 | return -EINVAL; | ||
| 313 | } | ||
| 314 | |||
| 315 | return 0; | ||
| 316 | } | ||
| 317 | |||
| 287 | /** | 318 | /** |
| 288 | * amdgpu_dm_update_crtc_color_mgmt: Maps DRM color management to DC stream. | 319 | * amdgpu_dm_update_crtc_color_mgmt: Maps DRM color management to DC stream. |
| 289 | * @crtc: amdgpu_dm crtc state | 320 | * @crtc: amdgpu_dm crtc state |
| @@ -317,14 +348,12 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc) · 27 unmodified lines | |||
| 317 | bool is_legacy; | 348 | bool is_legacy; |
| 318 | int r; | 349 | int r; |
| 319 | 350 | ||
| 320 | degamma_lut = __extract_blob_lut(crtc->base.degamma_lut, °amma_size); | 351 | r = amdgpu_dm_verify_lut_sizes(&crtc->base); |
| 321 | if (degamma_lut && degamma_size != MAX_COLOR_LUT_ENTRIES) | 352 | if (r) |
| 322 | return -EINVAL; | 353 | return r; |
| 323 | 354 | ||
| 355 | degamma_lut = __extract_blob_lut(crtc->base.degamma_lut, °amma_size); | ||
| 324 | regamma_lut = __extract_blob_lut(crtc->base.gamma_lut, ®amma_size); | 356 | regamma_lut = __extract_blob_lut(crtc->base.gamma_lut, ®amma_size); |
| 325 | if (regamma_lut && regamma_size != MAX_COLOR_LUT_ENTRIES && | ||
| 326 | regamma_size != MAX_COLOR_LEGACY_LUT_ENTRIES) | ||
| 327 | return -EINVAL; | ||
| 328 | 357 | ||
| 329 | has_degamma = | 358 | has_degamma = |
| 330 | degamma_lut && !__is_lut_linear(degamma_lut, degamma_size); | 359 | degamma_lut && !__is_lut_linear(degamma_lut, degamma_size); |
| @@ -0,0 +1,166 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2021 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 | #include "amdgpu_dm_psr.h" | ||
| 27 | #include "dc.h" | ||
| 28 | #include "dm_helpers.h" | ||
| 29 | |||
| 30 | /* | ||
| 31 | * amdgpu_dm_set_psr_caps() - set link psr capabilities | ||
| 32 | * @link: link | ||
| 33 | * | ||
| 34 | */ | ||
| 35 | void amdgpu_dm_set_psr_caps(struct dc_link *link) | ||
| 36 | { | ||
| 37 | uint8_t dpcd_data[EDP_PSR_RECEIVER_CAP_SIZE]; | ||
| 38 | |||
| 39 | if (!(link->connector_signal & SIGNAL_TYPE_EDP)) | ||
| 40 | return; | ||
| 41 | if (link->type == dc_connection_none) | ||
| 42 | return; | ||
| 43 | if (dm_helpers_dp_read_dpcd(NULL, link, DP_PSR_SUPPORT, | ||
| 44 | dpcd_data, sizeof(dpcd_data))) { | ||
| 45 | link->dpcd_caps.psr_caps.psr_version = dpcd_data[0]; | ||
| 46 | |||
| 47 | if (dpcd_data[0] == 0) { | ||
| 48 | link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED; | ||
| 49 | link->psr_settings.psr_feature_enabled = false; | ||
| 50 | } else { | ||
| 51 | link->psr_settings.psr_version = DC_PSR_VERSION_1; | ||
| 52 | link->psr_settings.psr_feature_enabled = true; | ||
| 53 | } | ||
| 54 | |||
| 55 | DRM_INFO("PSR support:%d\n", link->psr_settings.psr_feature_enabled); | ||
| 56 | } | ||
| 57 | } | ||
| 58 | |||
| 59 | /* | ||
| 60 | * amdgpu_dm_link_setup_psr() - configure psr link | ||
| 61 | * @stream: stream state | ||
| 62 | * | ||
| 63 | * Return: true if success | ||
| 64 | */ | ||
| 65 | bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream) | ||
| 66 | { | ||
| 67 | struct dc_link *link = NULL; | ||
| 68 | struct psr_config psr_config = {0}; | ||
| 69 | struct psr_context psr_context = {0}; | ||
| 70 | struct dc *dc = NULL; | ||
| 71 | bool ret = false; | ||
| 72 | |||
| 73 | if (stream == NULL) | ||
| 74 | return false; | ||
| 75 | |||
| 76 | link = stream->link; | ||
| 77 | dc = link->ctx->dc; | ||
| 78 | |||
| 79 | psr_config.psr_version = link->dpcd_caps.psr_caps.psr_version; | ||
| 80 | |||
| 81 | if (psr_config.psr_version > 0) { | ||
| 82 | psr_config.psr_exit_link_training_required = 0x1; | ||
| 83 | psr_config.psr_frame_capture_indication_req = 0; | ||
| 84 | psr_config.psr_rfb_setup_time = 0x37; | ||
| 85 | psr_config.psr_sdp_transmit_line_num_deadline = 0x20; | ||
| 86 | psr_config.allow_smu_optimizations = 0x0; | ||
| 87 | |||
| 88 | ret = dc_link_setup_psr(link, stream, &psr_config, &psr_context); | ||
| 89 | |||
| 90 | } | ||
| 91 | DRM_DEBUG_DRIVER("PSR link: %d\n", link->psr_settings.psr_feature_enabled); | ||
| 92 | |||
| 93 | return ret; | ||
| 94 | } | ||
| 95 | |||
| 96 | /* | ||
| 97 | * amdgpu_dm_psr_enable() - enable psr f/w | ||
| 98 | * @stream: stream state | ||
| 99 | * | ||
| 100 | * Return: true if success | ||
| 101 | */ | ||
| 102 | bool amdgpu_dm_psr_enable(struct dc_stream_state *stream) | ||
| 103 | { | ||
| 104 | struct dc_link *link = stream->link; | ||
| 105 | unsigned int vsync_rate_hz = 0; | ||
| 106 | struct dc_static_screen_params params = {0}; | ||
| 107 | /* Calculate number of static frames before generating interrupt to | ||
| 108 | * enter PSR. | ||
| 109 | */ | ||
| 110 | // Init fail safe of 2 frames static | ||
| 111 | unsigned int num_frames_static = 2; | ||
| 112 | |||
| 113 | DRM_DEBUG_DRIVER("Enabling psr...\n"); | ||
| 114 | |||
| 115 | vsync_rate_hz = div64_u64(div64_u64(( | ||
| 116 | stream->timing.pix_clk_100hz * 100), | ||
| 117 | stream->timing.v_total), | ||
| 118 | stream->timing.h_total); | ||
| 119 | |||
| 120 | /* Round up | ||
| 121 | * Calculate number of frames such that at least 30 ms of time has | ||
| 122 | * passed. | ||
| 123 | */ | ||
| 124 | if (vsync_rate_hz != 0) { | ||
| 125 | unsigned int frame_time_microsec = 1000000 / vsync_rate_hz; | ||
| 126 | num_frames_static = (30000 / frame_time_microsec) + 1; | ||
| 127 | } | ||
| 128 | |||
| 129 | params.triggers.cursor_update = true; | ||
| 130 | params.triggers.overlay_update = true; | ||
| 131 | params.triggers.surface_update = true; | ||
| 132 | params.num_frames = num_frames_static; | ||
| 133 | |||
| 134 | dc_stream_set_static_screen_params(link->ctx->dc, | ||
| 135 | &stream, 1, | ||
| 136 | ¶ms); | ||
| 137 | |||
| 138 | return dc_link_set_psr_allow_active(link, true, false, false); | ||
| 139 | } | ||
| 140 | |||
| 141 | /* | ||
| 142 | * amdgpu_dm_psr_disable() - disable psr f/w | ||
| 143 | * @stream: stream state | ||
| 144 | * | ||
| 145 | * Return: true if success | ||
| 146 | */ | ||
| 147 | bool amdgpu_dm_psr_disable(struct dc_stream_state *stream) | ||
| 148 | { | ||
| 149 | |||
| 150 | DRM_DEBUG_DRIVER("Disabling psr...\n"); | ||
| 151 | |||
| 152 | return dc_link_set_psr_allow_active(stream->link, false, true, false); | ||
| 153 | } | ||
| 154 | |||
| 155 | /* | ||
| 156 | * amdgpu_dm_psr_disable() - disable psr f/w | ||
| 157 | * if psr is enabled on any stream | ||
| 158 | * | ||
| 159 | * Return: true if success | ||
| 160 | */ | ||
| 161 | bool amdgpu_dm_psr_disable_all(struct amdgpu_display_manager *dm) | ||
| 162 | { | ||
| 163 | DRM_DEBUG_DRIVER("Disabling psr if psr is enabled on any stream\n"); | ||
| 164 | return dc_set_psr_allow_active(dm->dc, false); | ||
| 165 | } | ||
| 166 | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2021 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 | #ifndef AMDGPU_DM_AMDGPU_DM_PSR_H_ | ||
| 27 | #define AMDGPU_DM_AMDGPU_DM_PSR_H_ | ||
| 28 | |||
| 29 | #include "amdgpu.h" | ||
| 30 | |||
| 31 | void amdgpu_dm_set_psr_caps(struct dc_link *link); | ||
| 32 | bool amdgpu_dm_psr_enable(struct dc_stream_state *stream); | ||
| 33 | bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream); | ||
| 34 | bool amdgpu_dm_psr_disable(struct dc_stream_state *stream); | ||
| 35 | bool amdgpu_dm_psr_disable_all(struct amdgpu_display_manager *dm); | ||
| 36 | |||
| 37 | #endif /* AMDGPU_DM_AMDGPU_DM_PSR_H_ */ | ||
| @@ -60,7 +60,7 @@ include $(AMD_DC) · 59 unmodified lines | |||
| 60 | 60 | ||
| 61 | DISPLAY_CORE = dc.o dc_stat.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_sink.o \ | 61 | DISPLAY_CORE = dc.o dc_stat.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_sink.o \ |
| 62 | dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o \ | 62 | dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o \ |
| 63 | dc_link_enc_cfg.o | 63 | dc_link_enc_cfg.o dc_link_dpcd.o |
| 64 | 64 | ||
| 65 | ifdef CONFIG_DRM_AMD_DC_DCN | 65 | ifdef CONFIG_DRM_AMD_DC_DCN |
| 66 | DISPLAY_CORE += dc_vm_helper.o | 66 | DISPLAY_CORE += dc_vm_helper.o |
| @@ -123,7 +123,7 @@ void dcn20_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, · 122 unmodified lines | |||
| 123 | } | 123 | } |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr) | 126 | void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr, struct dc_state *context) |
| 127 | { | 127 | { |
| 128 | int dpp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR | 128 | int dpp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR |
| 129 | * clk_mgr->base.dentist_vco_freq_khz / clk_mgr->base.clks.dppclk_khz; | 129 | * clk_mgr->base.dentist_vco_freq_khz / clk_mgr->base.clks.dppclk_khz; |
| @@ -132,6 +132,68 @@ void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr) · 2 unmodified lines | |||
| 132 | 132 | ||
| 133 | uint32_t dppclk_wdivider = dentist_get_did_from_divider(dpp_divider); | 133 | uint32_t dppclk_wdivider = dentist_get_did_from_divider(dpp_divider); |
| 134 | uint32_t dispclk_wdivider = dentist_get_did_from_divider(disp_divider); | 134 | uint32_t dispclk_wdivider = dentist_get_did_from_divider(disp_divider); |
| 135 | uint32_t current_dispclk_wdivider; | ||
| 136 | uint32_t i; | ||
| 137 | |||
| 138 | REG_GET(DENTIST_DISPCLK_CNTL, | ||
| 139 | DENTIST_DISPCLK_WDIVIDER, ¤t_dispclk_wdivider); | ||
| 140 | |||
| 141 | /* When changing divider to or from 127, some extra programming is required to prevent corruption */ | ||
| 142 | if (current_dispclk_wdivider == 127 && dispclk_wdivider != 127) { | ||
| 143 | for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) { | ||
| 144 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; | ||
| 145 | uint32_t fifo_level; | ||
| 146 | struct dccg *dccg = clk_mgr->base.ctx->dc->res_pool->dccg; | ||
| 147 | struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; | ||
| 148 | int32_t N; | ||
| 149 | int32_t j; | ||
| 150 | |||
| 151 | if (!pipe_ctx->stream) | ||
| 152 | continue; | ||
| 153 | /* Virtual encoders don't have this function */ | ||
| 154 | if (!stream_enc->funcs->get_fifo_cal_average_level) | ||
| 155 | continue; | ||
| 156 | fifo_level = stream_enc->funcs->get_fifo_cal_average_level( | ||
| 157 | stream_enc); | ||
| 158 | N = fifo_level / 4; | ||
| 159 | dccg->funcs->set_fifo_errdet_ovr_en( | ||
| 160 | dccg, | ||
| 161 | true); | ||
| 162 | for (j = 0; j < N - 4; j++) | ||
| 163 | dccg->funcs->otg_drop_pixel( | ||
| 164 | dccg, | ||
| 165 | pipe_ctx->stream_res.tg->inst); | ||
| 166 | dccg->funcs->set_fifo_errdet_ovr_en( | ||
| 167 | dccg, | ||
| 168 | false); | ||
| 169 | } | ||
| 170 | } else if (dispclk_wdivider == 127 && current_dispclk_wdivider != 127) { | ||
| 171 | REG_UPDATE(DENTIST_DISPCLK_CNTL, | ||
| 172 | DENTIST_DISPCLK_WDIVIDER, 126); | ||
| 173 | REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 100); | ||
| 174 | for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) { | ||
| 175 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; | ||
| 176 | struct dccg *dccg = clk_mgr->base.ctx->dc->res_pool->dccg; | ||
| 177 | struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; | ||
| 178 | uint32_t fifo_level; | ||
| 179 | int32_t N; | ||
| 180 | int32_t j; | ||
| 181 | |||
| 182 | if (!pipe_ctx->stream) | ||
| 183 | continue; | ||
| 184 | /* Virtual encoders don't have this function */ | ||
| 185 | if (!stream_enc->funcs->get_fifo_cal_average_level) | ||
| 186 | continue; | ||
| 187 | fifo_level = stream_enc->funcs->get_fifo_cal_average_level( | ||
| 188 | stream_enc); | ||
| 189 | N = fifo_level / 4; | ||
| 190 | dccg->funcs->set_fifo_errdet_ovr_en(dccg, true); | ||
| 191 | for (j = 0; j < 12 - N; j++) | ||
| 192 | dccg->funcs->otg_add_pixel(dccg, | ||
| 193 | pipe_ctx->stream_res.tg->inst); | ||
| 194 | dccg->funcs->set_fifo_errdet_ovr_en(dccg, false); | ||
| 195 | } | ||
| 196 | } | ||
| 135 | 197 | ||
| 136 | REG_UPDATE(DENTIST_DISPCLK_CNTL, | 198 | REG_UPDATE(DENTIST_DISPCLK_CNTL, |
| 137 | DENTIST_DISPCLK_WDIVIDER, dispclk_wdivider); | 199 | DENTIST_DISPCLK_WDIVIDER, dispclk_wdivider); |
| @@ -251,11 +313,11 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base, · 113 unmodified lines | |||
| 251 | if (dpp_clock_lowered) { | 313 | if (dpp_clock_lowered) { |
| 252 | // if clock is being lowered, increase DTO before lowering refclk | 314 | // if clock is being lowered, increase DTO before lowering refclk |
| 253 | dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); | 315 | dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); |
| 254 | dcn20_update_clocks_update_dentist(clk_mgr); | 316 | dcn20_update_clocks_update_dentist(clk_mgr, context); |
| 255 | } else { | 317 | } else { |
| 256 | // if clock is being raised, increase refclk before lowering DTO | 318 | // if clock is being raised, increase refclk before lowering DTO |
| 257 | if (update_dppclk || update_dispclk) | 319 | if (update_dppclk || update_dispclk) |
| 258 | dcn20_update_clocks_update_dentist(clk_mgr); | 320 | dcn20_update_clocks_update_dentist(clk_mgr, context); |
| 259 | // always update dtos unless clock is lowered and not safe to lower | 321 | // always update dtos unless clock is lowered and not safe to lower |
| 260 | dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); | 322 | dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); |
| 261 | } | 323 | } |
| @@ -50,7 +50,8 @@ void dcn2_get_clock(struct clk_mgr *clk_mgr, · 49 unmodified lines | |||
| 50 | enum dc_clock_type clock_type, | 50 | enum dc_clock_type clock_type, |
| 51 | struct dc_clock_config *clock_cfg); | 51 | struct dc_clock_config *clock_cfg); |
| 52 | 52 | ||
| 53 | void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr); | 53 | void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr, |
| 54 | struct dc_state *context); | ||
| 54 | 55 | ||
| 55 | void dcn2_read_clocks_from_hw_dentist(struct clk_mgr *clk_mgr_base); | 56 | void dcn2_read_clocks_from_hw_dentist(struct clk_mgr *clk_mgr_base); |
| 56 | 57 | ||
| @@ -334,11 +334,11 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base, · 333 unmodified lines | |||
| 334 | if (dpp_clock_lowered) { | 334 | if (dpp_clock_lowered) { |
| 335 | /* if clock is being lowered, increase DTO before lowering refclk */ | 335 | /* if clock is being lowered, increase DTO before lowering refclk */ |
| 336 | dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); | 336 | dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); |
| 337 | dcn20_update_clocks_update_dentist(clk_mgr); | 337 | dcn20_update_clocks_update_dentist(clk_mgr, context); |
| 338 | } else { | 338 | } else { |
| 339 | /* if clock is being raised, increase refclk before lowering DTO */ | 339 | /* if clock is being raised, increase refclk before lowering DTO */ |
| 340 | if (update_dppclk || update_dispclk) | 340 | if (update_dppclk || update_dispclk) |
| 341 | dcn20_update_clocks_update_dentist(clk_mgr); | 341 | dcn20_update_clocks_update_dentist(clk_mgr, context); |
| 342 | /* There is a check inside dcn20_update_clocks_update_dpp_dto which ensures | 342 | /* There is a check inside dcn20_update_clocks_update_dpp_dto which ensures |
| 343 | * that we do not lower dto when it is not safe to lower. We do not need to | 343 | * that we do not lower dto when it is not safe to lower. We do not need to |
| 344 | * compare the current and new dppclk before calling this function.*/ | 344 | * compare the current and new dppclk before calling this function.*/ |
| @@ -409,13 +409,13 @@ void get_surface_tile_visual_confirm_color( · 408 unmodified lines | |||
| 409 | struct tg_color *color) | 409 | struct tg_color *color) |
| 410 | { | 410 | { |
| 411 | uint32_t color_value = MAX_TG_COLOR_VALUE; | 411 | uint32_t color_value = MAX_TG_COLOR_VALUE; |
| 412 | /* Determine the overscan color based on the top-most (desktop) plane's context */ | 412 | /* Determine the overscan color based on the bottom-most plane's context */ |
| 413 | struct pipe_ctx *top_pipe_ctx = pipe_ctx; | 413 | struct pipe_ctx *bottom_pipe_ctx = pipe_ctx; |
| 414 | 414 | ||
| 415 | while (top_pipe_ctx->top_pipe != NULL) | 415 | while (bottom_pipe_ctx->bottom_pipe != NULL) |
| 416 | top_pipe_ctx = top_pipe_ctx->top_pipe; | 416 | bottom_pipe_ctx = bottom_pipe_ctx->bottom_pipe; |
| 417 | 417 | ||
| 418 | switch (top_pipe_ctx->plane_state->tiling_info.gfx9.swizzle) { | 418 | switch (bottom_pipe_ctx->plane_state->tiling_info.gfx9.swizzle) { |
| 419 | case DC_SW_LINEAR: | 419 | case DC_SW_LINEAR: |
| 420 | /* LINEAR Surface - set border color to red */ | 420 | /* LINEAR Surface - set border color to red */ |
| 421 | color->color_r_cr = color_value; | 421 | color->color_r_cr = color_value; |
| @@ -49,6 +49,7 @@ · 48 unmodified lines | |||
| 49 | #include "dmub/dmub_srv.h" | 49 | #include "dmub/dmub_srv.h" |
| 50 | #include "inc/hw/panel_cntl.h" | 50 | #include "inc/hw/panel_cntl.h" |
| 51 | #include "inc/link_enc_cfg.h" | 51 | #include "inc/link_enc_cfg.h" |
| 52 | #include "inc/link_dpcd.h" | ||
| 52 | 53 | ||
| 53 | #define DC_LOGGER_INIT(logger) | 54 | #define DC_LOGGER_INIT(logger) |
| 54 | 55 | ||
| @@ -59,20 +60,6 @@ · 4 unmodified lines | |||
| 59 | #define RETIMER_REDRIVER_INFO(...) \ | 60 | #define RETIMER_REDRIVER_INFO(...) \ |
| 60 | DC_LOG_RETIMER_REDRIVER( \ | 61 | DC_LOG_RETIMER_REDRIVER( \ |
| 61 | __VA_ARGS__) | 62 | __VA_ARGS__) |
| 62 | /******************************************************************************* | ||
| 63 | * Private structures | ||
| 64 | ******************************************************************************/ | ||
| 65 | |||
| 66 | enum { | ||
| 67 | PEAK_FACTOR_X1000 = 1006, | ||
| 68 | /* | ||
| 69 | * Some receivers fail to train on first try and are good | ||
| 70 | * on subsequent tries. 2 retries should be plenty. If we | ||
| 71 | * don't have a successful training then we don't expect to | ||
| 72 | * ever get one. | ||
| 73 | */ | ||
| 74 | LINK_TRAINING_MAX_VERIFY_RETRY = 2 | ||
| 75 | }; | ||
| 76 | 63 | ||
| 77 | /******************************************************************************* | 64 | /******************************************************************************* |
| 78 | * Private functions | 65 | * Private functions |
| @@ -718,11 +705,9 @@ static void read_current_link_settings_on_detect(struct dc_link *link) · 639 unmodified lines | |||
| 718 | 705 | ||
| 719 | static bool detect_dp(struct dc_link *link, | 706 | static bool detect_dp(struct dc_link *link, |
| 720 | struct display_sink_capability *sink_caps, | 707 | struct display_sink_capability *sink_caps, |
| 721 | bool *converter_disable_audio, | ||
| 722 | struct audio_support *audio_support, | ||
| 723 | enum dc_detect_reason reason) | 708 | enum dc_detect_reason reason) |
| 724 | { | 709 | { |
| 725 | bool boot = false; | 710 | struct audio_support *audio_support = &link->dc->res_pool->audio_support; |
| 726 | 711 | ||
| 727 | sink_caps->signal = link_detect_sink(link, reason); | 712 | sink_caps->signal = link_detect_sink(link, reason); |
| 728 | sink_caps->transaction_type = | 713 | sink_caps->transaction_type = |
| @@ -745,60 +730,12 @@ static bool detect_dp(struct dc_link *link, · 16 unmodified lines | |||
| 745 | * of this function). */ | 730 | * of this function). */ |
| 746 | query_hdcp_capability(SIGNAL_TYPE_DISPLAY_PORT_MST, link); | 731 | query_hdcp_capability(SIGNAL_TYPE_DISPLAY_PORT_MST, link); |
| 747 | #endif | 732 | #endif |
| 748 | /* | ||
| 749 | * This call will initiate MST topology discovery. Which | ||
| 750 | * will detect MST ports and add new DRM connector DRM | ||
| 751 | * framework. Then read EDID via remote i2c over aux. In | ||
| 752 | * the end, will notify DRM detect result and save EDID | ||
| 753 | * into DRM framework. | ||
| 754 | * | ||
| 755 | * .detect is called by .fill_modes. | ||
| 756 | * .fill_modes is called by user mode ioctl | ||
| 757 | * DRM_IOCTL_MODE_GETCONNECTOR. | ||
| 758 | * | ||
| 759 | * .get_modes is called by .fill_modes. | ||
| 760 | * | ||
| 761 | * call .get_modes, AMDGPU DM implementation will create | ||
| 762 | * new dc_sink and add to dc_link. For long HPD plug | ||
| 763 | * in/out, MST has its own handle. | ||
| 764 | * | ||
| 765 | * Therefore, just after dc_create, link->sink is not | ||
| 766 | * created for MST until user mode app calls | ||
| 767 | * DRM_IOCTL_MODE_GETCONNECTOR. | ||
| 768 | * | ||
| 769 | * Need check ->sink usages in case ->sink = NULL | ||
| 770 | * TODO: s3 resume check | ||
| 771 | */ | ||
| 772 | if (reason == DETECT_REASON_BOOT) | ||
| 773 | boot = true; | ||
| 774 | |||
| 775 | dm_helpers_dp_update_branch_info(link->ctx, link); | ||
| 776 | |||
| 777 | if (!dm_helpers_dp_mst_start_top_mgr(link->ctx, | ||
| 778 | link, boot)) { | ||
| 779 | /* MST not supported */ | ||
| 780 | link->type = dc_connection_single; | ||
| 781 | sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT; | ||
| 782 | } | ||
| 783 | } | 733 | } |
| 784 | 734 | ||
| 785 | if (link->type != dc_connection_mst_branch && | 735 | if (link->type != dc_connection_mst_branch && |
| 786 | is_dp_branch_device(link)) { | 736 | is_dp_branch_device(link)) |
| 787 | /* DP SST branch */ | 737 | /* DP SST branch */ |
| 788 | link->type = dc_connection_sst_branch; | 738 | link->type = dc_connection_sst_branch; |
| 789 | if (!link->dpcd_caps.sink_count.bits.SINK_COUNT) { | ||
| 790 | /* | ||
| 791 | * SST branch unplug processing for short irq | ||
| 792 | */ | ||
| 793 | link_disconnect_sink(link); | ||
| 794 | return true; | ||
| 795 | } | ||
| 796 | |||
| 797 | if (is_dp_active_dongle(link) && | ||
| 798 | (link->dpcd_caps.dongle_type != | ||
| 799 | DISPLAY_DONGLE_DP_HDMI_CONVERTER)) | ||
| 800 | *converter_disable_audio = true; | ||
| 801 | } | ||
| 802 | } else { | 739 | } else { |
| 803 | /* DP passive dongles */ | 740 | /* DP passive dongles */ |
| 804 | sink_caps->signal = dp_passive_dongle_detection(link->ddc, | 741 | sink_caps->signal = dp_passive_dongle_detection(link->ddc, |
| @@ -893,7 +830,6 @@ static bool dc_link_detect_helper(struct dc_link *link, · 88 unmodified lines | |||
| 893 | struct dc_sink *sink = NULL; | 830 | struct dc_sink *sink = NULL; |
| 894 | struct dc_sink *prev_sink = NULL; | 831 | struct dc_sink *prev_sink = NULL; |
| 895 | struct dpcd_caps prev_dpcd_caps; | 832 | struct dpcd_caps prev_dpcd_caps; |
| 896 | bool same_dpcd = true; | ||
| 897 | enum dc_connection_type new_connection_type = dc_connection_none; | 833 | enum dc_connection_type new_connection_type = dc_connection_none; |
| 898 | enum dc_connection_type pre_connection_type = dc_connection_none; | 834 | enum dc_connection_type pre_connection_type = dc_connection_none; |
| 899 | bool perform_dp_seamless_boot = false; | 835 | bool perform_dp_seamless_boot = false; |
| @@ -904,9 +840,10 @@ static bool dc_link_detect_helper(struct dc_link *link, · 4 unmodified lines | |||
| 904 | if (dc_is_virtual_signal(link->connector_signal)) | 840 | if (dc_is_virtual_signal(link->connector_signal)) |
| 905 | return false; | 841 | return false; |
| 906 | 842 | ||
| 907 | if ((link->connector_signal == SIGNAL_TYPE_LVDS || | 843 | if (((link->connector_signal == SIGNAL_TYPE_LVDS || |
| 908 | link->connector_signal == SIGNAL_TYPE_EDP) && | 844 | link->connector_signal == SIGNAL_TYPE_EDP) && |
| 909 | link->local_sink) { | 845 | (!link->dc->config.allow_edp_hotplug_detection)) && |
| 846 | link->local_sink) { | ||
| 910 | // need to re-write OUI and brightness in resume case | 847 | // need to re-write OUI and brightness in resume case |
| 911 | if (link->connector_signal == SIGNAL_TYPE_EDP) { | 848 | if (link->connector_signal == SIGNAL_TYPE_EDP) { |
| 912 | dpcd_set_source_specific_data(link); | 849 | dpcd_set_source_specific_data(link); |
| @@ -983,20 +920,59 @@ static bool dc_link_detect_helper(struct dc_link *link, · 70 unmodified lines | |||
| 983 | return false; | 920 | return false; |
| 984 | } | 921 | } |
| 985 | 922 | ||
| 986 | if (!detect_dp(link, &sink_caps, | 923 | if (!detect_dp(link, &sink_caps, reason)) { |
| 987 | &converter_disable_audio, | ||
| 988 | aud_support, reason)) { | ||
| 989 | if (prev_sink) | 924 | if (prev_sink) |
| 990 | dc_sink_release(prev_sink); | 925 | dc_sink_release(prev_sink); |
| 991 | return false; | 926 | return false; |
| 992 | } | 927 | } |
| 993 | 928 | ||
| 994 | // Check if dpcp block is the same | 929 | if (link->type == dc_connection_mst_branch) { |
| 995 | if (prev_sink) { | 930 | LINK_INFO("link=%d, mst branch is now Connected\n", |
| 996 | if (memcmp(&link->dpcd_caps, &prev_dpcd_caps, | 931 | link->link_index); |
| 997 | sizeof(struct dpcd_caps))) | 932 | /* Need to setup mst link_cap struct here |
| 998 | same_dpcd = false; | 933 | * otherwise dc_link_detect() will leave mst link_cap |
| 934 | * empty which leads to allocate_mst_payload() has "0" | ||
| 935 | * pbn_per_slot value leading to exception on dc_fixpt_div() | ||
| 936 | */ | ||
| 937 | dp_verify_mst_link_cap(link); | ||
| 938 | |||
| 939 | /* | ||
| 940 | * This call will initiate MST topology discovery. Which | ||
| 941 | * will detect MST ports and add new DRM connector DRM | ||
| 942 | * framework. Then read EDID via remote i2c over aux. In | ||
| 943 | * the end, will notify DRM detect result and save EDID | ||
| 944 | * into DRM framework. | ||
| 945 | * | ||
| 946 | * .detect is called by .fill_modes. | ||
| 947 | * .fill_modes is called by user mode ioctl | ||
| 948 | * DRM_IOCTL_MODE_GETCONNECTOR. | ||
| 949 | * | ||
| 950 | * .get_modes is called by .fill_modes. | ||
| 951 | * | ||
| 952 | * call .get_modes, AMDGPU DM implementation will create | ||
| 953 | * new dc_sink and add to dc_link. For long HPD plug | ||
| 954 | * in/out, MST has its own handle. | ||
| 955 | * | ||
| 956 | * Therefore, just after dc_create, link->sink is not | ||
| 957 | * created for MST until user mode app calls | ||
| 958 | * DRM_IOCTL_MODE_GETCONNECTOR. | ||
| 959 | * | ||
| 960 | * Need check ->sink usages in case ->sink = NULL | ||
| 961 | * TODO: s3 resume check | ||
| 962 | */ | ||
| 963 | |||
| 964 | dm_helpers_dp_update_branch_info(link->ctx, link); | ||
| 965 | if (dm_helpers_dp_mst_start_top_mgr(link->ctx, | ||
| 966 | link, reason == DETECT_REASON_BOOT)) { | ||
| 967 | if (prev_sink) | ||
| 968 | dc_sink_release(prev_sink); | ||
| 969 | return false; | ||
| 970 | } else { | ||
| 971 | link->type = dc_connection_sst_branch; | ||
| 972 | sink_caps.signal = SIGNAL_TYPE_DISPLAY_PORT; | ||
| 973 | } | ||
| 999 | } | 974 | } |
| 975 | |||
| 1000 | /* Active SST downstream branch device unplug*/ | 976 | /* Active SST downstream branch device unplug*/ |
| 1001 | if (link->type == dc_connection_sst_branch && | 977 | if (link->type == dc_connection_sst_branch && |
| 1002 | link->dpcd_caps.sink_count.bits.SINK_COUNT == 0) { | 978 | link->dpcd_caps.sink_count.bits.SINK_COUNT == 0) { |
| @@ -1006,31 +982,23 @@ static bool dc_link_detect_helper(struct dc_link *link, · 3 unmodified lines | |||
| 1006 | return true; | 982 | return true; |
| 1007 | } | 983 | } |
| 1008 | 984 | ||
| 985 | /* disable audio for non DP to HDMI active sst converter */ | ||
| 986 | if (link->type == dc_connection_sst_branch && | ||
| 987 | is_dp_active_dongle(link) && | ||
| 988 | (link->dpcd_caps.dongle_type != | ||
| 989 | DISPLAY_DONGLE_DP_HDMI_CONVERTER)) | ||
| 990 | converter_disable_audio = true; | ||
| 991 | |||
| 1009 | // link switch from MST to non-MST stop topology manager | 992 | // link switch from MST to non-MST stop topology manager |
| 1010 | if (pre_connection_type == dc_connection_mst_branch && | 993 | if (pre_connection_type == dc_connection_mst_branch && |
| 1011 | link->type != dc_connection_mst_branch) { | 994 | link->type != dc_connection_mst_branch) |
| 1012 | dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); | 995 | dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); |
| 1013 | } | ||
| 1014 | 996 | ||
| 1015 | if (link->type == dc_connection_mst_branch) { | ||
| 1016 | LINK_INFO("link=%d, mst branch is now Connected\n", | ||
| 1017 | link->link_index); | ||
| 1018 | /* Need to setup mst link_cap struct here | ||
| 1019 | * otherwise dc_link_detect() will leave mst link_cap | ||
| 1020 | * empty which leads to allocate_mst_payload() has "0" | ||
| 1021 | * pbn_per_slot value leading to exception on dc_fixpt_div() | ||
| 1022 | */ | ||
| 1023 | dp_verify_mst_link_cap(link); | ||
| 1024 | |||
| 1025 | if (prev_sink) | ||
| 1026 | dc_sink_release(prev_sink); | ||
| 1027 | return false; | ||
| 1028 | } | ||
| 1029 | 997 | ||
| 1030 | // For seamless boot, to skip verify link cap, we read UEFI settings and set them as verified. | 998 | // For seamless boot, to skip verify link cap, we read UEFI settings and set them as verified. |
| 1031 | if (reason == DETECT_REASON_BOOT && | 999 | if (reason == DETECT_REASON_BOOT && |
| 1032 | !dc_ctx->dc->config.power_down_display_on_boot && | 1000 | !dc_ctx->dc->config.power_down_display_on_boot && |
| 1033 | link->link_status.link_active) | 1001 | link->link_status.link_active) |
| 1034 | perform_dp_seamless_boot = true; | 1002 | perform_dp_seamless_boot = true; |
| 1035 | 1003 | ||
| 1036 | if (perform_dp_seamless_boot) { | 1004 | if (perform_dp_seamless_boot) { |
| @@ -1213,11 +1181,11 @@ static bool dc_link_detect_helper(struct dc_link *link, · 176 unmodified lines | |||
| 1213 | link->dongle_max_pix_clk = 0; | 1181 | link->dongle_max_pix_clk = 0; |
| 1214 | } | 1182 | } |
| 1215 | 1183 | ||
| 1216 | LINK_INFO("link=%d, dc_sink_in=%p is now %s prev_sink=%p dpcd same=%d edid same=%d\n", | 1184 | LINK_INFO("link=%d, dc_sink_in=%p is now %s prev_sink=%p edid same=%d\n", |
| 1217 | link->link_index, sink, | 1185 | link->link_index, sink, |
| 1218 | (sink_caps.signal == | 1186 | (sink_caps.signal == |
| 1219 | SIGNAL_TYPE_NONE ? "Disconnected" : "Connected"), | 1187 | SIGNAL_TYPE_NONE ? "Disconnected" : "Connected"), |
| 1220 | prev_sink, same_dpcd, same_edid); | 1188 | prev_sink, same_edid); |
| 1221 | 1189 | ||
| 1222 | if (prev_sink) | 1190 | if (prev_sink) |
| 1223 | dc_sink_release(prev_sink); | 1191 | dc_sink_release(prev_sink); |
| @@ -1501,7 +1469,8 @@ static bool dc_link_construct(struct dc_link *link, · 277 unmodified lines | |||
| 1501 | link->connector_signal = SIGNAL_TYPE_EDP; | 1469 | link->connector_signal = SIGNAL_TYPE_EDP; |
| 1502 | 1470 | ||
| 1503 | if (link->hpd_gpio) { | 1471 | if (link->hpd_gpio) { |
| 1504 | link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; | 1472 | if (!link->dc->config.allow_edp_hotplug_detection) |
| 1473 | link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; | ||
| 1505 | link->irq_source_hpd_rx = | 1474 | link->irq_source_hpd_rx = |
| 1506 | dal_irq_get_rx_source(link->hpd_gpio); | 1475 | dal_irq_get_rx_source(link->hpd_gpio); |
| 1507 | } | 1476 | } |
| @@ -25,6 +25,8 @@ static const uint8_t DP_VGA_LVDS_CONVERTER_ID_3[] = "dnomlA"; · 24 unmodified lines | |||
| 25 | link->ctx->logger | 25 | link->ctx->logger |
| 26 | #define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */ | 26 | #define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */ |
| 27 | 27 | ||
| 28 | #include "link_dpcd.h" | ||
| 29 | |||
| 28 | /* maximum pre emphasis level allowed for each voltage swing level*/ | 30 | /* maximum pre emphasis level allowed for each voltage swing level*/ |
| 29 | static const enum dc_pre_emphasis | 31 | static const enum dc_pre_emphasis |
| 30 | voltage_swing_to_pre_emphasis[] = { PRE_EMPHASIS_LEVEL3, | 32 | voltage_swing_to_pre_emphasis[] = { PRE_EMPHASIS_LEVEL3, |
| @@ -1618,11 +1620,10 @@ enum dc_status dpcd_configure_lttpr_mode(struct dc_link *link, struct link_train · 1587 unmodified lines | |||
| 1618 | { | 1620 | { |
| 1619 | enum dc_status status = DC_OK; | 1621 | enum dc_status status = DC_OK; |
| 1620 | 1622 | ||
| 1621 | if (lt_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) | 1623 | if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) |
| 1622 | status = configure_lttpr_mode_transparent(link); | ||
| 1623 | |||
| 1624 | else if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) | ||
| 1625 | status = configure_lttpr_mode_non_transparent(link, lt_settings); | 1624 | status = configure_lttpr_mode_non_transparent(link, lt_settings); |
| 1625 | else | ||
| 1626 | status = configure_lttpr_mode_transparent(link); | ||
| 1626 | 1627 | ||
| 1627 | return status; | 1628 | return status; |
| 1628 | } | 1629 | } |
| @@ -1806,7 +1807,7 @@ bool perform_link_training_with_retries( · 177 unmodified lines | |||
| 1806 | enum dp_panel_mode panel_mode; | 1807 | enum dp_panel_mode panel_mode; |
| 1807 | struct link_encoder *link_enc; | 1808 | struct link_encoder *link_enc; |
| 1808 | enum link_training_result status = LINK_TRAINING_CR_FAIL_LANE0; | 1809 | enum link_training_result status = LINK_TRAINING_CR_FAIL_LANE0; |
| 1809 | struct dc_link_settings currnet_setting = *link_setting; | 1810 | struct dc_link_settings current_setting = *link_setting; |
| 1810 | 1811 | ||
| 1811 | /* Dynamically assigned link encoders associated with stream rather than | 1812 | /* Dynamically assigned link encoders associated with stream rather than |
| 1812 | * link. | 1813 | * link. |
| @@ -1832,7 +1833,7 @@ bool perform_link_training_with_retries( · 19 unmodified lines | |||
| 1832 | link, | 1833 | link, |
| 1833 | signal, | 1834 | signal, |
| 1834 | pipe_ctx->clock_source->id, | 1835 | pipe_ctx->clock_source->id, |
| 1835 | &currnet_setting); | 1836 | ¤t_setting); |
| 1836 | 1837 | ||
| 1837 | if (stream->sink_patches.dppowerup_delay > 0) { | 1838 | if (stream->sink_patches.dppowerup_delay > 0) { |
| 1838 | int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay; | 1839 | int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay; |
| @@ -1847,12 +1848,12 @@ bool perform_link_training_with_retries( · 8 unmodified lines | |||
| 1847 | panel_mode != DP_PANEL_MODE_DEFAULT); | 1848 | panel_mode != DP_PANEL_MODE_DEFAULT); |
| 1848 | 1849 | ||
| 1849 | if (link->aux_access_disabled) { | 1850 | if (link->aux_access_disabled) { |
| 1850 | dc_link_dp_perform_link_training_skip_aux(link, &currnet_setting); | 1851 | dc_link_dp_perform_link_training_skip_aux(link, ¤t_setting); |
| 1851 | return true; | 1852 | return true; |
| 1852 | } else { | 1853 | } else { |
| 1853 | status = dc_link_dp_perform_link_training( | 1854 | status = dc_link_dp_perform_link_training( |
| 1854 | link, | 1855 | link, |
| 1855 | &currnet_setting, | 1856 | ¤t_setting, |
| 1856 | skip_video_pattern); | 1857 | skip_video_pattern); |
| 1857 | if (status == LINK_TRAINING_SUCCESS) | 1858 | if (status == LINK_TRAINING_SUCCESS) |
| 1858 | return true; | 1859 | return true; |
| @@ -1872,12 +1873,12 @@ bool perform_link_training_with_retries( · 13 unmodified lines | |||
| 1872 | if (status == LINK_TRAINING_ABORT) | 1873 | if (status == LINK_TRAINING_ABORT) |
| 1873 | break; | 1874 | break; |
| 1874 | else if (do_fallback) { | 1875 | else if (do_fallback) { |
| 1875 | decide_fallback_link_setting(*link_setting, &currnet_setting, status); | 1876 | decide_fallback_link_setting(*link_setting, ¤t_setting, status); |
| 1876 | /* Fail link training if reduced link bandwidth no longer meets | 1877 | /* Fail link training if reduced link bandwidth no longer meets |
| 1877 | * stream requirements. | 1878 | * stream requirements. |
| 1878 | */ | 1879 | */ |
| 1879 | if (dc_bandwidth_in_kbps_from_timing(&stream->timing) < | 1880 | if (dc_bandwidth_in_kbps_from_timing(&stream->timing) < |
| 1880 | dc_link_bandwidth_kbps(link, &currnet_setting)) | 1881 | dc_link_bandwidth_kbps(link, ¤t_setting)) |
| 1881 | break; | 1882 | break; |
| 1882 | } | 1883 | } |
| 1883 | 1884 | ||
| @@ -3619,79 +3620,16 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link) · 1735 unmodified lines | |||
| 3619 | return true; | 3620 | return true; |
| 3620 | } | 3621 | } |
| 3621 | 3622 | ||
| 3622 | static bool retrieve_link_cap(struct dc_link *link) | 3623 | bool dp_retrieve_lttpr_cap(struct dc_link *link) |
| 3623 | { | 3624 | { |
| 3624 | /* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16, | ||
| 3625 | * which means size 16 will be good for both of those DPCD register block reads | ||
| 3626 | */ | ||
| 3627 | uint8_t dpcd_data[16]; | ||
| 3628 | uint8_t lttpr_dpcd_data[6]; | 3625 | uint8_t lttpr_dpcd_data[6]; |
| 3629 | |||
| 3630 | /*Only need to read 1 byte starting from DP_DPRX_FEATURE_ENUMERATION_LIST. | ||
| 3631 | */ | ||
| 3632 | uint8_t dpcd_dprx_data = '\0'; | ||
| 3633 | uint8_t dpcd_power_state = '\0'; | ||
| 3634 | |||
| 3635 | struct dp_device_vendor_id sink_id; | ||
| 3636 | union down_stream_port_count down_strm_port_count; | ||
| 3637 | union edp_configuration_cap edp_config_cap; | ||
| 3638 | union dp_downstream_port_present ds_port = { 0 }; | ||
| 3639 | enum dc_status status = DC_ERROR_UNEXPECTED; | ||
| 3640 | uint32_t read_dpcd_retry_cnt = 3; | ||
| 3641 | int i; | ||
| 3642 | struct dp_sink_hw_fw_revision dp_hw_fw_revision; | ||
| 3643 | bool is_lttpr_present = false; | ||
| 3644 | const uint32_t post_oui_delay = 30; // 30ms | ||
| 3645 | bool vbios_lttpr_enable = false; | 3626 | bool vbios_lttpr_enable = false; |
| 3646 | bool vbios_lttpr_interop = false; | 3627 | bool vbios_lttpr_interop = false; |
| 3647 | struct dc_bios *bios = link->dc->ctx->dc_bios; | 3628 | struct dc_bios *bios = link->dc->ctx->dc_bios; |
| 3629 | enum dc_status status = DC_ERROR_UNEXPECTED; | ||
| 3630 | bool is_lttpr_present = false; | ||
| 3648 | 3631 | ||
| 3649 | memset(dpcd_data, '\0', sizeof(dpcd_data)); | ||
| 3650 | memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data)); | 3632 | memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data)); |
| 3651 | memset(&down_strm_port_count, | ||
| 3652 | '\0', sizeof(union down_stream_port_count)); | ||
| 3653 | memset(&edp_config_cap, '\0', | ||
| 3654 | sizeof(union edp_configuration_cap)); | ||
| 3655 | |||
| 3656 | /* if extended timeout is supported in hardware, | ||
| 3657 | * default to LTTPR timeout (3.2ms) first as a W/A for DP link layer | ||
| 3658 | * CTS 4.2.1.1 regression introduced by CTS specs requirement update. | ||
| 3659 | */ | ||
| 3660 | dc_link_aux_try_to_configure_timeout(link->ddc, | ||
| 3661 | LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD); | ||
| 3662 | |||
| 3663 | status = core_link_read_dpcd(link, DP_SET_POWER, | ||
| 3664 | &dpcd_power_state, sizeof(dpcd_power_state)); | ||
| 3665 | |||
| 3666 | /* Delay 1 ms if AUX CH is in power down state. Based on spec | ||
| 3667 | * section 2.3.1.2, if AUX CH may be powered down due to | ||
| 3668 | * write to DPCD 600h = 2. Sink AUX CH is monitoring differential | ||
| 3669 | * signal and may need up to 1 ms before being able to reply. | ||
| 3670 | */ | ||
| 3671 | if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3) | ||
| 3672 | udelay(1000); | ||
| 3673 | |||
| 3674 | dpcd_set_source_specific_data(link); | ||
| 3675 | /* Sink may need to configure internals based on vendor, so allow some | ||
| 3676 | * time before proceeding with possibly vendor specific transactions | ||
| 3677 | */ | ||
| 3678 | msleep(post_oui_delay); | ||
| 3679 | |||
| 3680 | for (i = 0; i < read_dpcd_retry_cnt; i++) { | ||
| 3681 | status = core_link_read_dpcd( | ||
| 3682 | link, | ||
| 3683 | DP_DPCD_REV, | ||
| 3684 | dpcd_data, | ||
| 3685 | sizeof(dpcd_data)); | ||
| 3686 | if (status == DC_OK) | ||
| 3687 | break; | ||
| 3688 | } | ||
| 3689 | |||
| 3690 | if (status != DC_OK) { | ||
| 3691 | dm_error("%s: Read dpcd data failed.\n", __func__); | ||
| 3692 | return false; | ||
| 3693 | } | ||
| 3694 | |||
| 3695 | /* Query BIOS to determine if LTTPR functionality is forced on by system */ | 3633 | /* Query BIOS to determine if LTTPR functionality is forced on by system */ |
| 3696 | if (bios->funcs->get_lttpr_caps) { | 3634 | if (bios->funcs->get_lttpr_caps) { |
| 3697 | enum bp_result bp_query_result; | 3635 | enum bp_result bp_query_result; |
| @@ -3763,21 +3701,91 @@ static bool retrieve_link_cap(struct dc_link *link) · 65 unmodified lines | |||
| 3763 | DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; | 3701 | DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; |
| 3764 | 3702 | ||
| 3765 | /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */ | 3703 | /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */ |
| 3766 | is_lttpr_present = (link->dpcd_caps.lttpr_caps.phy_repeater_cnt > 0 && | 3704 | is_lttpr_present = (dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 && |
| 3767 | link->dpcd_caps.lttpr_caps.phy_repeater_cnt < 0xff && | ||
| 3768 | link->dpcd_caps.lttpr_caps.max_lane_count > 0 && | 3705 | link->dpcd_caps.lttpr_caps.max_lane_count > 0 && |
| 3769 | link->dpcd_caps.lttpr_caps.max_lane_count <= 4 && | 3706 | link->dpcd_caps.lttpr_caps.max_lane_count <= 4 && |
| 3770 | link->dpcd_caps.lttpr_caps.revision.raw >= 0x14); | 3707 | link->dpcd_caps.lttpr_caps.revision.raw >= 0x14); |
| 3771 | if (is_lttpr_present) | 3708 | if (is_lttpr_present) { |
| 3772 | CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: "); | 3709 | CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: "); |
| 3773 | else | 3710 | configure_lttpr_mode_transparent(link); |
| 3711 | } else | ||
| 3774 | link->lttpr_mode = LTTPR_MODE_NON_LTTPR; | 3712 | link->lttpr_mode = LTTPR_MODE_NON_LTTPR; |
| 3775 | } | 3713 | } |
| 3714 | return is_lttpr_present; | ||
| 3715 | } | ||
| 3716 | |||
| 3717 | static bool retrieve_link_cap(struct dc_link *link) | ||
| 3718 | { | ||
| 3719 | /* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16, | ||
| 3720 | * which means size 16 will be good for both of those DPCD register block reads | ||
| 3721 | */ | ||
| 3722 | uint8_t dpcd_data[16]; | ||
| 3723 | /*Only need to read 1 byte starting from DP_DPRX_FEATURE_ENUMERATION_LIST. | ||
| 3724 | */ | ||
| 3725 | uint8_t dpcd_dprx_data = '\0'; | ||
| 3726 | uint8_t dpcd_power_state = '\0'; | ||
| 3727 | |||
| 3728 | struct dp_device_vendor_id sink_id; | ||
| 3729 | union down_stream_port_count down_strm_port_count; | ||
| 3730 | union edp_configuration_cap edp_config_cap; | ||
| 3731 | union dp_downstream_port_present ds_port = { 0 }; | ||
| 3732 | enum dc_status status = DC_ERROR_UNEXPECTED; | ||
| 3733 | uint32_t read_dpcd_retry_cnt = 3; | ||
| 3734 | int i; | ||
| 3735 | struct dp_sink_hw_fw_revision dp_hw_fw_revision; | ||
| 3736 | const uint32_t post_oui_delay = 30; // 30ms | ||
| 3737 | bool is_lttpr_present = false; | ||
| 3738 | |||
| 3739 | memset(dpcd_data, '\0', sizeof(dpcd_data)); | ||
| 3740 | memset(&down_strm_port_count, | ||
| 3741 | '\0', sizeof(union down_stream_port_count)); | ||
| 3742 | memset(&edp_config_cap, '\0', | ||
| 3743 | sizeof(union edp_configuration_cap)); | ||
| 3744 | |||
| 3745 | /* if extended timeout is supported in hardware, | ||
| 3746 | * default to LTTPR timeout (3.2ms) first as a W/A for DP link layer | ||
| 3747 | * CTS 4.2.1.1 regression introduced by CTS specs requirement update. | ||
| 3748 | */ | ||
| 3749 | dc_link_aux_try_to_configure_timeout(link->ddc, | ||
| 3750 | LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD); | ||
| 3751 | |||
| 3752 | is_lttpr_present = dp_retrieve_lttpr_cap(link); | ||
| 3753 | |||
| 3754 | status = core_link_read_dpcd(link, DP_SET_POWER, | ||
| 3755 | &dpcd_power_state, sizeof(dpcd_power_state)); | ||
| 3756 | |||
| 3757 | /* Delay 1 ms if AUX CH is in power down state. Based on spec | ||
| 3758 | * section 2.3.1.2, if AUX CH may be powered down due to | ||
| 3759 | * write to DPCD 600h = 2. Sink AUX CH is monitoring differential | ||
| 3760 | * signal and may need up to 1 ms before being able to reply. | ||
| 3761 | */ | ||
| 3762 | if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3) | ||
| 3763 | udelay(1000); | ||
| 3764 | |||
| 3765 | dpcd_set_source_specific_data(link); | ||
| 3766 | /* Sink may need to configure internals based on vendor, so allow some | ||
| 3767 | * time before proceeding with possibly vendor specific transactions | ||
| 3768 | */ | ||
| 3769 | msleep(post_oui_delay); | ||
| 3770 | |||
| 3771 | for (i = 0; i < read_dpcd_retry_cnt; i++) { | ||
| 3772 | status = core_link_read_dpcd( | ||
| 3773 | link, | ||
| 3774 | DP_DPCD_REV, | ||
| 3775 | dpcd_data, | ||
| 3776 | sizeof(dpcd_data)); | ||
| 3777 | if (status == DC_OK) | ||
| 3778 | break; | ||
| 3779 | } | ||
| 3780 | |||
| 3781 | if (status != DC_OK) { | ||
| 3782 | dm_error("%s: Read receiver caps dpcd data failed.\n", __func__); | ||
| 3783 | return false; | ||
| 3784 | } | ||
| 3776 | 3785 | ||
| 3777 | if (!is_lttpr_present) | 3786 | if (!is_lttpr_present) |
| 3778 | dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD); | 3787 | dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD); |
| 3779 | 3788 | ||
| 3780 | |||
| 3781 | { | 3789 | { |
| 3782 | union training_aux_rd_interval aux_rd_interval; | 3790 | union training_aux_rd_interval aux_rd_interval; |
| 3783 | 3791 | ||
| @@ -0,0 +1,218 @@ | |||
| 1 | #include <inc/core_status.h> | ||
| 2 | #include <dc_link.h> | ||
| 3 | #include <inc/link_hwss.h> | ||
| 4 | #include <inc/link_dpcd.h> | ||
| 5 | #include "drm/drm_dp_helper.h" | ||
| 6 | #include <dc_dp_types.h> | ||
| 7 | #include "dm_helpers.h" | ||
| 8 | |||
| 9 | #define END_ADDRESS(start, size) (start + size - 1) | ||
| 10 | #define ADDRESS_RANGE_SIZE(start, end) (end - start + 1) | ||
| 11 | struct dpcd_address_range { | ||
| 12 | uint32_t start; | ||
| 13 | uint32_t end; | ||
| 14 | }; | ||
| 15 | |||
| 16 | static enum dc_status internal_link_read_dpcd( | ||
| 17 | struct dc_link *link, | ||
| 18 | uint32_t address, | ||
| 19 | uint8_t *data, | ||
| 20 | uint32_t size) | ||
| 21 | { | ||
| 22 | if (!link->aux_access_disabled && | ||
| 23 | !dm_helpers_dp_read_dpcd(link->ctx, | ||
| 24 | link, address, data, size)) { | ||
| 25 | return DC_ERROR_UNEXPECTED; | ||
| 26 | } | ||
| 27 | |||
| 28 | return DC_OK; | ||
| 29 | } | ||
| 30 | |||
| 31 | static enum dc_status internal_link_write_dpcd( | ||
| 32 | struct dc_link *link, | ||
| 33 | uint32_t address, | ||
| 34 | const uint8_t *data, | ||
| 35 | uint32_t size) | ||
| 36 | { | ||
| 37 | if (!link->aux_access_disabled && | ||
| 38 | !dm_helpers_dp_write_dpcd(link->ctx, | ||
| 39 | link, address, data, size)) { | ||
| 40 | return DC_ERROR_UNEXPECTED; | ||
| 41 | } | ||
| 42 | |||
| 43 | return DC_OK; | ||
| 44 | } | ||
| 45 | |||
| 46 | /* | ||
| 47 | * Partition the entire DPCD address space | ||
| 48 | * XXX: This partitioning must cover the entire DPCD address space, | ||
| 49 | * and must contain no gaps or overlapping address ranges. | ||
| 50 | */ | ||
| 51 | static const struct dpcd_address_range mandatory_dpcd_partitions[] = { | ||
| 52 | { 0, DP_TRAINING_PATTERN_SET_PHY_REPEATER(DP_PHY_LTTPR1) - 1}, | ||
| 53 | { DP_TRAINING_PATTERN_SET_PHY_REPEATER(DP_PHY_LTTPR1), DP_TRAINING_PATTERN_SET_PHY_REPEATER(DP_PHY_LTTPR2) - 1 }, | ||
| 54 | { DP_TRAINING_PATTERN_SET_PHY_REPEATER(DP_PHY_LTTPR2), DP_TRAINING_PATTERN_SET_PHY_REPEATER(DP_PHY_LTTPR3) - 1 }, | ||
| 55 | { DP_TRAINING_PATTERN_SET_PHY_REPEATER(DP_PHY_LTTPR3), DP_TRAINING_PATTERN_SET_PHY_REPEATER(DP_PHY_LTTPR4) - 1 }, | ||
| 56 | { DP_TRAINING_PATTERN_SET_PHY_REPEATER(DP_PHY_LTTPR4), DP_TRAINING_PATTERN_SET_PHY_REPEATER(DP_PHY_LTTPR5) - 1 }, | ||
| 57 | { DP_TRAINING_PATTERN_SET_PHY_REPEATER(DP_PHY_LTTPR5), DP_TRAINING_PATTERN_SET_PHY_REPEATER(DP_PHY_LTTPR6) - 1 }, | ||
| 58 | { DP_TRAINING_PATTERN_SET_PHY_REPEATER(DP_PHY_LTTPR6), DP_TRAINING_PATTERN_SET_PHY_REPEATER(DP_PHY_LTTPR7) - 1 }, | ||
| 59 | { DP_TRAINING_PATTERN_SET_PHY_REPEATER(DP_PHY_LTTPR7), DP_TRAINING_PATTERN_SET_PHY_REPEATER(DP_PHY_LTTPR8) - 1 }, | ||
| 60 | { DP_TRAINING_PATTERN_SET_PHY_REPEATER(DP_PHY_LTTPR8), DP_FEC_STATUS_PHY_REPEATER(DP_PHY_LTTPR1) - 1 }, | ||
| 61 | /* | ||
| 62 | * The FEC registers are contiguous | ||
| 63 | */ | ||
| 64 | { DP_FEC_STATUS_PHY_REPEATER(DP_PHY_LTTPR1), DP_FEC_STATUS_PHY_REPEATER(DP_PHY_LTTPR1) - 1 }, | ||
| 65 | { DP_FEC_STATUS_PHY_REPEATER(DP_PHY_LTTPR2), DP_FEC_STATUS_PHY_REPEATER(DP_PHY_LTTPR2) - 1 }, | ||
| 66 | { DP_FEC_STATUS_PHY_REPEATER(DP_PHY_LTTPR3), DP_FEC_STATUS_PHY_REPEATER(DP_PHY_LTTPR3) - 1 }, | ||
| 67 | { DP_FEC_STATUS_PHY_REPEATER(DP_PHY_LTTPR4), DP_FEC_STATUS_PHY_REPEATER(DP_PHY_LTTPR4) - 1 }, | ||
| 68 | { DP_FEC_STATUS_PHY_REPEATER(DP_PHY_LTTPR5), DP_FEC_STATUS_PHY_REPEATER(DP_PHY_LTTPR5) - 1 }, | ||
| 69 | { DP_FEC_STATUS_PHY_REPEATER(DP_PHY_LTTPR6), DP_FEC_STATUS_PHY_REPEATER(DP_PHY_LTTPR6) - 1 }, | ||
| 70 | { DP_FEC_STATUS_PHY_REPEATER(DP_PHY_LTTPR7), DP_FEC_STATUS_PHY_REPEATER(DP_PHY_LTTPR7) - 1 }, | ||
| 71 | { DP_FEC_STATUS_PHY_REPEATER(DP_PHY_LTTPR8), DP_LTTPR_MAX_ADD }, | ||
| 72 | /* all remaining DPCD addresses */ | ||
| 73 | { DP_LTTPR_MAX_ADD + 1, DP_DPCD_MAX_ADD } }; | ||
| 74 | |||
| 75 | static inline bool do_addresses_intersect_with_range( | ||
| 76 | const struct dpcd_address_range *range, | ||
| 77 | const uint32_t start_address, | ||
| 78 | const uint32_t end_address) | ||
| 79 | { | ||
| 80 | return start_address <= range->end && end_address >= range->start; | ||
| 81 | } | ||
| 82 | |||
| 83 | static uint32_t dpcd_get_next_partition_size(const uint32_t address, const uint32_t size) | ||
| 84 | { | ||
| 85 | const uint32_t end_address = END_ADDRESS(address, size); | ||
| 86 | uint32_t partition_iterator = 0; | ||
| 87 | |||
| 88 | /* | ||
| 89 | * find current partition | ||
| 90 | * this loop spins forever if partition map above is not surjective | ||
| 91 | */ | ||
| 92 | while (!do_addresses_intersect_with_range(&mandatory_dpcd_partitions[partition_iterator], | ||
| 93 | address, end_address)) | ||
| 94 | partition_iterator++; | ||
| 95 | if (end_address < mandatory_dpcd_partitions[partition_iterator].end) | ||
| 96 | return size; | ||
| 97 | return ADDRESS_RANGE_SIZE(address, mandatory_dpcd_partitions[partition_iterator].end); | ||
| 98 | } | ||
| 99 | |||
| 100 | /* | ||
| 101 | * Ranges of DPCD addresses that must be read in a single transaction | ||
| 102 | * XXX: Do not allow any two address ranges in this array to overlap | ||
| 103 | */ | ||
| 104 | static const struct dpcd_address_range mandatory_dpcd_blocks[] = { | ||
| 105 | { DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT }}; | ||
| 106 | |||
| 107 | /* | ||
| 108 | * extend addresses to read all mandatory blocks together | ||
| 109 | */ | ||
| 110 | static void dpcd_extend_address_range( | ||
| 111 | const uint32_t in_address, | ||
| 112 | uint8_t * const in_data, | ||
| 113 | const uint32_t in_size, | ||
| 114 | uint32_t *out_address, | ||
| 115 | uint8_t **out_data, | ||
| 116 | uint32_t *out_size) | ||
| 117 | { | ||
| 118 | const uint32_t end_address = END_ADDRESS(in_address, in_size); | ||
| 119 | const struct dpcd_address_range *addr_range; | ||
| 120 | struct dpcd_address_range new_addr_range; | ||
| 121 | uint32_t i; | ||
| 122 | |||
| 123 | new_addr_range.start = in_address; | ||
| 124 | new_addr_range.end = end_address; | ||
| 125 | for (i = 0; i < ARRAY_SIZE(mandatory_dpcd_blocks); i++) { | ||
| 126 | addr_range = &mandatory_dpcd_blocks[i]; | ||
| 127 | if (addr_range->start <= in_address && addr_range->end >= in_address) | ||
| 128 | new_addr_range.start = addr_range->start; | ||
| 129 | |||
| 130 | if (addr_range->start <= end_address && addr_range->end >= end_address) | ||
| 131 | new_addr_range.end = addr_range->end; | ||
| 132 | } | ||
| 133 | *out_address = in_address; | ||
| 134 | *out_size = in_size; | ||
| 135 | *out_data = in_data; | ||
| 136 | if (new_addr_range.start != in_address || new_addr_range.end != end_address) { | ||
| 137 | *out_address = new_addr_range.start; | ||
| 138 | *out_size = ADDRESS_RANGE_SIZE(new_addr_range.start, new_addr_range.end); | ||
| 139 | *out_data = kzalloc(*out_size * sizeof(**out_data), GFP_KERNEL); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | /* | ||
| 144 | * Reduce the AUX reply down to the values the caller requested | ||
| 145 | */ | ||
| 146 | static void dpcd_reduce_address_range( | ||
| 147 | const uint32_t extended_address, | ||
| 148 | uint8_t * const extended_data, | ||
| 149 | const uint32_t extended_size, | ||
| 150 | const uint32_t reduced_address, | ||
| 151 | uint8_t * const reduced_data, | ||
| 152 | const uint32_t reduced_size) | ||
| 153 | { | ||
| 154 | const uint32_t reduced_end_address = END_ADDRESS(reduced_address, reduced_size); | ||
| 155 | const uint32_t extended_end_address = END_ADDRESS(reduced_address, extended_size); | ||
| 156 | const uint32_t offset = reduced_address - extended_address; | ||
| 157 | |||
| 158 | if (extended_end_address == reduced_end_address && extended_address == reduced_address) | ||
| 159 | return; /* extended and reduced address ranges point to the same data */ | ||
| 160 | |||
| 161 | memcpy(&extended_data[offset], reduced_data, reduced_size); | ||
| 162 | kfree(extended_data); | ||
| 163 | } | ||
| 164 | |||
| 165 | enum dc_status core_link_read_dpcd( | ||
| 166 | struct dc_link *link, | ||
| 167 | uint32_t address, | ||
| 168 | uint8_t *data, | ||
| 169 | uint32_t size) | ||
| 170 | { | ||
| 171 | uint32_t extended_address; | ||
| 172 | uint32_t partitioned_address; | ||
| 173 | uint8_t *extended_data; | ||
| 174 | uint32_t extended_size; | ||
| 175 | /* size of the remaining partitioned address space */ | ||
| 176 | uint32_t size_left_to_read; | ||
| 177 | enum dc_status status; | ||
| 178 | /* size of the next partition to be read from */ | ||
| 179 | uint32_t partition_size; | ||
| 180 | uint32_t data_index = 0; | ||
| 181 | |||
| 182 | dpcd_extend_address_range(address, data, size, &extended_address, &extended_data, &extended_size); | ||
| 183 | partitioned_address = extended_address; | ||
| 184 | size_left_to_read = extended_size; | ||
| 185 | while (size_left_to_read) { | ||
| 186 | partition_size = dpcd_get_next_partition_size(partitioned_address, size_left_to_read); | ||
| 187 | status = internal_link_read_dpcd(link, partitioned_address, &extended_data[data_index], partition_size); | ||
| 188 | if (status != DC_OK) | ||
| 189 | break; | ||
| 190 | partitioned_address += partition_size; | ||
| 191 | data_index += partition_size; | ||
| 192 | size_left_to_read -= partition_size; | ||
| 193 | } | ||
| 194 | dpcd_reduce_address_range(extended_address, extended_data, extended_size, address, data, size); | ||
| 195 | return status; | ||
| 196 | } | ||
| 197 | |||
| 198 | enum dc_status core_link_write_dpcd( | ||
| 199 | struct dc_link *link, | ||
| 200 | uint32_t address, | ||
| 201 | const uint8_t *data, | ||
| 202 | uint32_t size) | ||
| 203 | { | ||
| 204 | uint32_t partition_size; | ||
| 205 | uint32_t data_index = 0; | ||
| 206 | enum dc_status status; | ||
| 207 | |||
| 208 | while (size) { | ||
| 209 | partition_size = dpcd_get_next_partition_size(address, size); | ||
| 210 | status = internal_link_write_dpcd(link, address, &data[data_index], partition_size); | ||
| 211 | if (status != DC_OK) | ||
| 212 | break; | ||
| 213 | address += partition_size; | ||
| 214 | data_index += partition_size; | ||
| 215 | size -= partition_size; | ||
| 216 | } | ||
| 217 | return status; | ||
| 218 | } | ||
| @@ -16,6 +16,7 @@ · 15 unmodified lines | |||
| 16 | #include "resource.h" | 16 | #include "resource.h" |
| 17 | #include "link_enc_cfg.h" | 17 | #include "link_enc_cfg.h" |
| 18 | #include "clk_mgr.h" | 18 | #include "clk_mgr.h" |
| 19 | #include "inc/link_dpcd.h" | ||
| 19 | 20 | ||
| 20 | static uint8_t convert_to_count(uint8_t lttpr_repeater_count) | 21 | static uint8_t convert_to_count(uint8_t lttpr_repeater_count) |
| 21 | { | 22 | { |
| @@ -47,36 +48,6 @@ static inline bool is_immediate_downstream(struct dc_link *link, uint32_t offset · 25 unmodified lines | |||
| 47 | return (convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == offset); | 48 | return (convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == offset); |
| 48 | } | 49 | } |
| 49 | 50 | ||
| 50 | enum dc_status core_link_read_dpcd( | ||
| 51 | struct dc_link *link, | ||
| 52 | uint32_t address, | ||
| 53 | uint8_t *data, | ||
| 54 | uint32_t size) | ||
| 55 | { | ||
| 56 | if (!link->aux_access_disabled && | ||
| 57 | !dm_helpers_dp_read_dpcd(link->ctx, | ||
| 58 | link, address, data, size)) { | ||
| 59 | return DC_ERROR_UNEXPECTED; | ||
| 60 | } | ||
| 61 | |||
| 62 | return DC_OK; | ||
| 63 | } | ||
| 64 | |||
| 65 | enum dc_status core_link_write_dpcd( | ||
| 66 | struct dc_link *link, | ||
| 67 | uint32_t address, | ||
| 68 | const uint8_t *data, | ||
| 69 | uint32_t size) | ||
| 70 | { | ||
| 71 | if (!link->aux_access_disabled && | ||
| 72 | !dm_helpers_dp_write_dpcd(link->ctx, | ||
| 73 | link, address, data, size)) { | ||
| 74 | return DC_ERROR_UNEXPECTED; | ||
| 75 | } | ||
| 76 | |||
| 77 | return DC_OK; | ||
| 78 | } | ||
| 79 | |||
| 80 | void dp_receiver_power_ctrl(struct dc_link *link, bool on) | 51 | void dp_receiver_power_ctrl(struct dc_link *link, bool on) |
| 81 | { | 52 | { |
| 82 | uint8_t state; | 53 | uint8_t state; |
| @@ -445,7 +445,7 @@ bool resource_are_vblanks_synchronizable( · 444 unmodified lines | |||
| 445 | { | 445 | { |
| 446 | uint32_t base60_refresh_rates[] = {10, 20, 5}; | 446 | uint32_t base60_refresh_rates[] = {10, 20, 5}; |
| 447 | uint8_t i; | 447 | uint8_t i; |
| 448 | uint8_t rr_count = sizeof(base60_refresh_rates)/sizeof(base60_refresh_rates[0]); | 448 | uint8_t rr_count = ARRAY_SIZE(base60_refresh_rates); |
| 449 | uint64_t frame_time_diff; | 449 | uint64_t frame_time_diff; |
| 450 | 450 | ||
| 451 | if (stream1->ctx->dc->config.vblank_alignment_dto_params && | 451 | if (stream1->ctx->dc->config.vblank_alignment_dto_params && |
| @@ -45,7 +45,7 @@ · 44 unmodified lines | |||
| 45 | /* forward declaration */ | 45 | /* forward declaration */ |
| 46 | struct aux_payload; | 46 | struct aux_payload; |
| 47 | 47 | ||
| 48 | #define DC_VER "3.2.139" | 48 | #define DC_VER "3.2.140" |
| 49 | 49 | ||
| 50 | #define MAX_SURFACES 3 | 50 | #define MAX_SURFACES 3 |
| 51 | #define MAX_PLANES 6 | 51 | #define MAX_PLANES 6 |
| @@ -303,6 +303,7 @@ struct dc_config { · 251 unmodified lines | |||
| 303 | bool multi_mon_pp_mclk_switch; | 303 | bool multi_mon_pp_mclk_switch; |
| 304 | bool disable_dmcu; | 304 | bool disable_dmcu; |
| 305 | bool enable_4to1MPC; | 305 | bool enable_4to1MPC; |
| 306 | bool allow_edp_hotplug_detection; | ||
| 306 | #if defined(CONFIG_DRM_AMD_DC_DCN) | 307 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 307 | bool clamp_min_dcfclk; | 308 | bool clamp_min_dcfclk; |
| 308 | #endif | 309 | #endif |
| @@ -86,6 +86,7 @@ void dc_dmub_srv_cmd_queue(struct dc_dmub_srv *dc_dmub_srv, · 85 unmodified lines | |||
| 86 | 86 | ||
| 87 | error: | 87 | error: |
| 88 | DC_ERROR("Error queuing DMUB command: status=%d\n", status); | 88 | DC_ERROR("Error queuing DMUB command: status=%d\n", status); |
| 89 | dc_dmub_srv_log_diagnostic_data(dc_dmub_srv); | ||
| 89 | } | 90 | } |
| 90 | 91 | ||
| 91 | void dc_dmub_srv_cmd_execute(struct dc_dmub_srv *dc_dmub_srv) | 92 | void dc_dmub_srv_cmd_execute(struct dc_dmub_srv *dc_dmub_srv) |
| @@ -95,8 +96,10 @@ void dc_dmub_srv_cmd_execute(struct dc_dmub_srv *dc_dmub_srv) · 3 unmodified lines | |||
| 95 | enum dmub_status status; | 96 | enum dmub_status status; |
| 96 | 97 | ||
| 97 | status = dmub_srv_cmd_execute(dmub); | 98 | status = dmub_srv_cmd_execute(dmub); |
| 98 | if (status != DMUB_STATUS_OK) | 99 | if (status != DMUB_STATUS_OK) { |
| 99 | DC_ERROR("Error starting DMUB execution: status=%d\n", status); | 100 | DC_ERROR("Error starting DMUB execution: status=%d\n", status); |
| 101 | dc_dmub_srv_log_diagnostic_data(dc_dmub_srv); | ||
| 102 | } | ||
| 100 | } | 103 | } |
| 101 | 104 | ||
| 102 | void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv) | 105 | void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv) |
| @@ -106,8 +109,10 @@ void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv) · 3 unmodified lines | |||
| 106 | enum dmub_status status; | 109 | enum dmub_status status; |
| 107 | 110 | ||
| 108 | status = dmub_srv_wait_for_idle(dmub, 100000); | 111 | status = dmub_srv_wait_for_idle(dmub, 100000); |
| 109 | if (status != DMUB_STATUS_OK) | 112 | if (status != DMUB_STATUS_OK) { |
| 110 | DC_ERROR("Error waiting for DMUB idle: status=%d\n", status); | 113 | DC_ERROR("Error waiting for DMUB idle: status=%d\n", status); |
| 114 | dc_dmub_srv_log_diagnostic_data(dc_dmub_srv); | ||
| 115 | } | ||
| 111 | } | 116 | } |
| 112 | 117 | ||
| 113 | void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dmub_srv, | 118 | void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dmub_srv, |
| @@ -214,3 +219,94 @@ void dc_dmub_trace_event_control(struct dc *dc, bool enable) · 100 unmodified lines | |||
| 214 | { | 219 | { |
| 215 | dm_helpers_dmub_outbox_interrupt_control(dc->ctx, enable); | 220 | dm_helpers_dmub_outbox_interrupt_control(dc->ctx, enable); |
| 216 | } | 221 | } |
| 222 | |||
| 223 | bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmub_diagnostic_data *diag_data) | ||
| 224 | { | ||
| 225 | if (!dc_dmub_srv || !dc_dmub_srv->dmub || !diag_data) | ||
| 226 | return false; | ||
| 227 | return dmub_srv_get_diagnostic_data(dc_dmub_srv->dmub, diag_data); | ||
| 228 | } | ||
| 229 | |||
| 230 | void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv) | ||
| 231 | { | ||
| 232 | struct dmub_diagnostic_data diag_data = {0}; | ||
| 233 | |||
| 234 | if (!dc_dmub_srv || !dc_dmub_srv->dmub) { | ||
| 235 | DC_LOG_ERROR("%s: invalid parameters.", __func__); | ||
| 236 | return; | ||
| 237 | } | ||
| 238 | |||
| 239 | if (!dc_dmub_srv_get_diagnostic_data(dc_dmub_srv, &diag_data)) { | ||
| 240 | DC_LOG_ERROR("%s: dc_dmub_srv_get_diagnostic_data failed.", __func__); | ||
| 241 | return; | ||
| 242 | } | ||
| 243 | |||
| 244 | DC_LOG_DEBUG( | ||
| 245 | "DMCUB STATE\n" | ||
| 246 | " dmcub_version : %08x\n" | ||
| 247 | " scratch [0] : %08x\n" | ||
| 248 | " scratch [1] : %08x\n" | ||
| 249 | " scratch [2] : %08x\n" | ||
| 250 | " scratch [3] : %08x\n" | ||
| 251 | " scratch [4] : %08x\n" | ||
| 252 | " scratch [5] : %08x\n" | ||
| 253 | " scratch [6] : %08x\n" | ||
| 254 | " scratch [7] : %08x\n" | ||
| 255 | " scratch [8] : %08x\n" | ||
| 256 | " scratch [9] : %08x\n" | ||
| 257 | " scratch [10] : %08x\n" | ||
| 258 | " scratch [11] : %08x\n" | ||
| 259 | " scratch [12] : %08x\n" | ||
| 260 | " scratch [13] : %08x\n" | ||
| 261 | " scratch [14] : %08x\n" | ||
| 262 | " scratch [15] : %08x\n" | ||
| 263 | " pc : %08x\n" | ||
| 264 | " unk_fault_addr : %08x\n" | ||
| 265 | " inst_fault_addr : %08x\n" | ||
| 266 | " data_fault_addr : %08x\n" | ||
| 267 | " inbox1_rptr : %08x\n" | ||
| 268 | " inbox1_wptr : %08x\n" | ||
| 269 | " inbox1_size : %08x\n" | ||
| 270 | " inbox0_rptr : %08x\n" | ||
| 271 | " inbox0_wptr : %08x\n" | ||
| 272 | " inbox0_size : %08x\n" | ||
| 273 | " is_enabled : %d\n" | ||
| 274 | " is_soft_reset : %d\n" | ||
| 275 | " is_secure_reset : %d\n" | ||
| 276 | " is_traceport_en : %d\n" | ||
| 277 | " is_cw0_en : %d\n" | ||
| 278 | " is_cw6_en : %d\n", | ||
| 279 | diag_data.dmcub_version, | ||
| 280 | diag_data.scratch[0], | ||
| 281 | diag_data.scratch[1], | ||
| 282 | diag_data.scratch[2], | ||
| 283 | diag_data.scratch[3], | ||
| 284 | diag_data.scratch[4], | ||
| 285 | diag_data.scratch[5], | ||
| 286 | diag_data.scratch[6], | ||
| 287 | diag_data.scratch[7], | ||
| 288 | diag_data.scratch[8], | ||
| 289 | diag_data.scratch[9], | ||
| 290 | diag_data.scratch[10], | ||
| 291 | diag_data.scratch[11], | ||
| 292 | diag_data.scratch[12], | ||
| 293 | diag_data.scratch[13], | ||
| 294 | diag_data.scratch[14], | ||
| 295 | diag_data.scratch[15], | ||
| 296 | diag_data.pc, | ||
| 297 | diag_data.undefined_address_fault_addr, | ||
| 298 | diag_data.inst_fetch_fault_addr, | ||
| 299 | diag_data.data_write_fault_addr, | ||
| 300 | diag_data.inbox1_rptr, | ||
| 301 | diag_data.inbox1_wptr, | ||
| 302 | diag_data.inbox1_size, | ||
| 303 | diag_data.inbox0_rptr, | ||
| 304 | diag_data.inbox0_wptr, | ||
| 305 | diag_data.inbox0_size, | ||
| 306 | diag_data.is_dmcub_enabled, | ||
| 307 | diag_data.is_dmcub_soft_reset, | ||
| 308 | diag_data.is_dmcub_secure_reset, | ||
| 309 | diag_data.is_traceport_en, | ||
| 310 | diag_data.is_cw0_enabled, | ||
| 311 | diag_data.is_cw6_enabled); | ||
| 312 | } | ||
| @@ -71,4 +71,8 @@ void dc_dmub_trace_event_control(struct dc *dc, bool enable); · 70 unmodified lines | |||
| 71 | 71 | ||
| 72 | void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dmub_srv, union dmub_inbox0_data_register data); | 72 | void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dmub_srv, union dmub_inbox0_data_register data); |
| 73 | 73 | ||
| 74 | bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmub_diagnostic_data *dmub_oca); | ||
| 75 | |||
| 76 | void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv); | ||
| 77 | |||
| 74 | #endif /* _DMUB_DC_SRV_H_ */ | 78 | #endif /* _DMUB_DC_SRV_H_ */ |
| @@ -615,7 +615,8 @@ int dce_aux_transfer_dmub_raw(struct ddc_service *ddc, · 614 unmodified lines | |||
| 615 | } | 615 | } |
| 616 | 616 | ||
| 617 | #define AUX_MAX_RETRIES 7 | 617 | #define AUX_MAX_RETRIES 7 |
| 618 | #define AUX_MAX_DEFER_RETRIES 7 | 618 | #define AUX_MIN_DEFER_RETRIES 7 |
| 619 | #define AUX_MAX_DEFER_TIMEOUT_MS 50 | ||
| 619 | #define AUX_MAX_I2C_DEFER_RETRIES 7 | 620 | #define AUX_MAX_I2C_DEFER_RETRIES 7 |
| 620 | #define AUX_MAX_INVALID_REPLY_RETRIES 2 | 621 | #define AUX_MAX_INVALID_REPLY_RETRIES 2 |
| 621 | #define AUX_MAX_TIMEOUT_RETRIES 3 | 622 | #define AUX_MAX_TIMEOUT_RETRIES 3 |
| @@ -628,6 +629,10 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc, · 6 unmodified lines | |||
| 628 | bool payload_reply = true; | 629 | bool payload_reply = true; |
| 629 | enum aux_return_code_type operation_result; | 630 | enum aux_return_code_type operation_result; |
| 630 | bool retry_on_defer = false; | 631 | bool retry_on_defer = false; |
| 632 | struct ddc *ddc_pin = ddc->ddc_pin; | ||
| 633 | struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; | ||
| 634 | struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(aux_engine); | ||
| 635 | uint32_t defer_time_in_ms = 0; | ||
| 631 | 636 | ||
| 632 | int aux_ack_retries = 0, | 637 | int aux_ack_retries = 0, |
| 633 | aux_defer_retries = 0, | 638 | aux_defer_retries = 0, |
| @@ -660,19 +665,27 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc, · 26 unmodified lines | |||
| 660 | break; | 665 | break; |
| 661 | 666 | ||
| 662 | case AUX_TRANSACTION_REPLY_AUX_DEFER: | 667 | case AUX_TRANSACTION_REPLY_AUX_DEFER: |
| 668 | /* polling_timeout_period is in us */ | ||
| 669 | defer_time_in_ms += aux110->polling_timeout_period / 1000; | ||
| 670 | ++aux_defer_retries; | ||
| 671 | /* fall through */ | ||
| 663 | case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER: | 672 | case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER: |
| 664 | retry_on_defer = true; | 673 | retry_on_defer = true; |
| 665 | fallthrough; | 674 | fallthrough; |
| 666 | case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK: | 675 | case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK: |
| 667 | if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES) { | 676 | if (aux_defer_retries >= AUX_MIN_DEFER_RETRIES |
| 677 | && defer_time_in_ms >= AUX_MAX_DEFER_TIMEOUT_MS) { | ||
| 668 | goto fail; | 678 | goto fail; |
| 669 | } else { | 679 | } else { |
| 670 | if ((*payload->reply == AUX_TRANSACTION_REPLY_AUX_DEFER) || | 680 | if ((*payload->reply == AUX_TRANSACTION_REPLY_AUX_DEFER) || |
| 671 | (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)) { | 681 | (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)) { |
| 672 | if (payload->defer_delay > 1) | 682 | if (payload->defer_delay > 1) { |
| 673 | msleep(payload->defer_delay); | 683 | msleep(payload->defer_delay); |
| 674 | else if (payload->defer_delay <= 1) | 684 | defer_time_in_ms += payload->defer_delay; |
| 685 | } else if (payload->defer_delay <= 1) { | ||
| 675 | udelay(payload->defer_delay * 1000); | 686 | udelay(payload->defer_delay * 1000); |
| 687 | defer_time_in_ms += payload->defer_delay; | ||
| 688 | } | ||
| 676 | } | 689 | } |
| 677 | } | 690 | } |
| 678 | break; | 691 | break; |
| @@ -701,7 +714,7 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc, · 22 unmodified lines | |||
| 701 | // Check whether a DEFER had occurred before the timeout. | 714 | // Check whether a DEFER had occurred before the timeout. |
| 702 | // If so, treat timeout as a DEFER. | 715 | // If so, treat timeout as a DEFER. |
| 703 | if (retry_on_defer) { | 716 | if (retry_on_defer) { |
| 704 | if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES) | 717 | if (++aux_defer_retries >= AUX_MIN_DEFER_RETRIES) |
| 705 | goto fail; | 718 | goto fail; |
| 706 | else if (payload->defer_delay > 0) | 719 | else if (payload->defer_delay > 0) |
| 707 | msleep(payload->defer_delay); | 720 | msleep(payload->defer_delay); |
| @@ -65,7 +65,6 @@ · 64 unmodified lines | |||
| 65 | 65 | ||
| 66 | #include "atomfirmware.h" | 66 | #include "atomfirmware.h" |
| 67 | 67 | ||
| 68 | #include "dce110_hw_sequencer.h" | ||
| 69 | #include "dcn10/dcn10_hw_sequencer.h" | 68 | #include "dcn10/dcn10_hw_sequencer.h" |
| 70 | 69 | ||
| 71 | #define GAMMA_HW_POINTS_NUM 256 | 70 | #define GAMMA_HW_POINTS_NUM 256 |
| @@ -54,6 +54,8 @@ · 53 unmodified lines | |||
| 54 | #include "dce/dmub_hw_lock_mgr.h" | 54 | #include "dce/dmub_hw_lock_mgr.h" |
| 55 | #include "dc_trace.h" | 55 | #include "dc_trace.h" |
| 56 | #include "dce/dmub_outbox.h" | 56 | #include "dce/dmub_outbox.h" |
| 57 | #include "inc/dc_link_dp.h" | ||
| 58 | #include "inc/link_dpcd.h" | ||
| 57 | 59 | ||
| 58 | #define DC_LOGGER_INIT(logger) | 60 | #define DC_LOGGER_INIT(logger) |
| 59 | 61 | ||
| @@ -1403,6 +1405,9 @@ void dcn10_init_hw(struct dc *dc) · 1343 unmodified lines | |||
| 1403 | if (dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) | 1405 | if (dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) |
| 1404 | continue; | 1406 | continue; |
| 1405 | 1407 | ||
| 1408 | /* DP 2.0 requires that LTTPR Caps be read first */ | ||
| 1409 | dp_retrieve_lttpr_cap(dc->links[i]); | ||
| 1410 | |||
| 1406 | /* | 1411 | /* |
| 1407 | * If any of the displays are lit up turn them off. | 1412 | * If any of the displays are lit up turn them off. |
| 1408 | * The reason is that some MST hubs cannot be turned off | 1413 | * The reason is that some MST hubs cannot be turned off |
| @@ -52,6 +52,7 @@ · 51 unmodified lines | |||
| 52 | SRI(AFMT_60958_1, DIG, id), \ | 52 | SRI(AFMT_60958_1, DIG, id), \ |
| 53 | SRI(AFMT_60958_2, DIG, id), \ | 53 | SRI(AFMT_60958_2, DIG, id), \ |
| 54 | SRI(DIG_FE_CNTL, DIG, id), \ | 54 | SRI(DIG_FE_CNTL, DIG, id), \ |
| 55 | SRI(DIG_FIFO_STATUS, DIG, id), \ | ||
| 55 | SRI(HDMI_CONTROL, DIG, id), \ | 56 | SRI(HDMI_CONTROL, DIG, id), \ |
| 56 | SRI(HDMI_DB_CONTROL, DIG, id), \ | 57 | SRI(HDMI_DB_CONTROL, DIG, id), \ |
| 57 | SRI(HDMI_GC, DIG, id), \ | 58 | SRI(HDMI_GC, DIG, id), \ |
| @@ -124,6 +125,7 @@ struct dcn10_stream_enc_registers { · 66 unmodified lines | |||
| 124 | uint32_t AFMT_60958_2; | 125 | uint32_t AFMT_60958_2; |
| 125 | uint32_t DIG_FE_CNTL; | 126 | uint32_t DIG_FE_CNTL; |
| 126 | uint32_t DIG_FE_CNTL2; | 127 | uint32_t DIG_FE_CNTL2; |
| 128 | uint32_t DIG_FIFO_STATUS; | ||
| 127 | uint32_t DP_MSE_RATE_CNTL; | 129 | uint32_t DP_MSE_RATE_CNTL; |
| 128 | uint32_t DP_MSE_RATE_UPDATE; | 130 | uint32_t DP_MSE_RATE_UPDATE; |
| 129 | uint32_t DP_PIXEL_FORMAT; | 131 | uint32_t DP_PIXEL_FORMAT; |
| @@ -266,6 +268,17 @@ struct dcn10_stream_enc_registers { · 136 unmodified lines | |||
| 266 | SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ | 268 | SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ |
| 267 | SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ | 269 | SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ |
| 268 | SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ | 270 | SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ |
| 271 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_LEVEL_ERROR, mask_sh),\ | ||
| 272 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_USE_OVERWRITE_LEVEL, mask_sh),\ | ||
| 273 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_OVERWRITE_LEVEL, mask_sh),\ | ||
| 274 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_ERROR_ACK, mask_sh),\ | ||
| 275 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CAL_AVERAGE_LEVEL, mask_sh),\ | ||
| 276 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MAXIMUM_LEVEL, mask_sh),\ | ||
| 277 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MINIMUM_LEVEL, mask_sh),\ | ||
| 278 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_READ_CLOCK_SRC, mask_sh),\ | ||
| 279 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CALIBRATED, mask_sh),\ | ||
| 280 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECAL_AVERAGE, mask_sh),\ | ||
| 281 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECOMP_MINMAX, mask_sh),\ | ||
| 269 | SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, mask_sh),\ | 282 | SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, mask_sh),\ |
| 270 | SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, mask_sh),\ | 283 | SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, mask_sh),\ |
| 271 | SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, mask_sh),\ | 284 | SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, mask_sh),\ |
| @@ -488,6 +501,17 @@ struct dcn10_stream_enc_registers { · 216 unmodified lines | |||
| 488 | type DP_VID_N_MUL;\ | 501 | type DP_VID_N_MUL;\ |
| 489 | type DP_VID_M_DOUBLE_VALUE_EN;\ | 502 | type DP_VID_M_DOUBLE_VALUE_EN;\ |
| 490 | type DIG_SOURCE_SELECT;\ | 503 | type DIG_SOURCE_SELECT;\ |
| 504 | type DIG_FIFO_LEVEL_ERROR;\ | ||
| 505 | type DIG_FIFO_USE_OVERWRITE_LEVEL;\ | ||
| 506 | type DIG_FIFO_OVERWRITE_LEVEL;\ | ||
| 507 | type DIG_FIFO_ERROR_ACK;\ | ||
| 508 | type DIG_FIFO_CAL_AVERAGE_LEVEL;\ | ||
| 509 | type DIG_FIFO_MAXIMUM_LEVEL;\ | ||
| 510 | type DIG_FIFO_MINIMUM_LEVEL;\ | ||
| 511 | type DIG_FIFO_READ_CLOCK_SRC;\ | ||
| 512 | type DIG_FIFO_CALIBRATED;\ | ||
| 513 | type DIG_FIFO_FORCE_RECAL_AVERAGE;\ | ||
| 514 | type DIG_FIFO_FORCE_RECOMP_MINMAX;\ | ||
| 491 | type DIG_CLOCK_PATTERN | 515 | type DIG_CLOCK_PATTERN |
| 492 | 516 | ||
| 493 | #define SE_REG_FIELD_LIST_DCN2_0(type) \ | 517 | #define SE_REG_FIELD_LIST_DCN2_0(type) \ |
| @@ -552,6 +552,17 @@ void enc2_stream_encoder_dp_set_stream_attribute( · 551 unmodified lines | |||
| 552 | DP_SST_SDP_SPLITTING, enable_sdp_splitting); | 552 | DP_SST_SDP_SPLITTING, enable_sdp_splitting); |
| 553 | } | 553 | } |
| 554 | 554 | ||
| 555 | uint32_t enc2_get_fifo_cal_average_level( | ||
| 556 | struct stream_encoder *enc) | ||
| 557 | { | ||
| 558 | struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); | ||
| 559 | uint32_t fifo_level; | ||
| 560 | |||
| 561 | REG_GET(DIG_FIFO_STATUS, | ||
| 562 | DIG_FIFO_CAL_AVERAGE_LEVEL, &fifo_level); | ||
| 563 | return fifo_level; | ||
| 564 | } | ||
| 565 | |||
| 555 | static const struct stream_encoder_funcs dcn20_str_enc_funcs = { | 566 | static const struct stream_encoder_funcs dcn20_str_enc_funcs = { |
| 556 | .dp_set_odm_combine = | 567 | .dp_set_odm_combine = |
| 557 | enc2_dp_set_odm_combine, | 568 | enc2_dp_set_odm_combine, |
| @@ -598,6 +609,7 @@ static const struct stream_encoder_funcs dcn20_str_enc_funcs = { · 40 unmodified lines | |||
| 598 | .dp_set_dsc_pps_info_packet = enc2_dp_set_dsc_pps_info_packet, | 609 | .dp_set_dsc_pps_info_packet = enc2_dp_set_dsc_pps_info_packet, |
| 599 | .set_dynamic_metadata = enc2_set_dynamic_metadata, | 610 | .set_dynamic_metadata = enc2_set_dynamic_metadata, |
| 600 | .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, | 611 | .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, |
| 612 | .get_fifo_cal_average_level = enc2_get_fifo_cal_average_level, | ||
| 601 | }; | 613 | }; |
| 602 | 614 | ||
| 603 | void dcn20_stream_encoder_construct( | 615 | void dcn20_stream_encoder_construct( |
| @@ -112,4 +112,7 @@ void enc2_set_dynamic_metadata(struct stream_encoder *enc, · 111 unmodified lines | |||
| 112 | uint32_t hubp_requestor_id, | 112 | uint32_t hubp_requestor_id, |
| 113 | enum dynamic_metadata_mode dmdata_mode); | 113 | enum dynamic_metadata_mode dmdata_mode); |
| 114 | 114 | ||
| 115 | uint32_t enc2_get_fifo_cal_average_level( | ||
| 116 | struct stream_encoder *enc); | ||
| 117 | |||
| 115 | #endif /* __DC_STREAM_ENCODER_DCN20_H__ */ | 118 | #endif /* __DC_STREAM_ENCODER_DCN20_H__ */ |
| @@ -823,6 +823,8 @@ static const struct stream_encoder_funcs dcn30_str_enc_funcs = { · 822 unmodified lines | |||
| 823 | .dp_set_dsc_pps_info_packet = enc3_dp_set_dsc_pps_info_packet, | 823 | .dp_set_dsc_pps_info_packet = enc3_dp_set_dsc_pps_info_packet, |
| 824 | .set_dynamic_metadata = enc2_set_dynamic_metadata, | 824 | .set_dynamic_metadata = enc2_set_dynamic_metadata, |
| 825 | .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, | 825 | .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, |
| 826 | |||
| 827 | .get_fifo_cal_average_level = enc2_get_fifo_cal_average_level, | ||
| 826 | }; | 828 | }; |
| 827 | 829 | ||
| 828 | void dcn30_dio_stream_encoder_construct( | 830 | void dcn30_dio_stream_encoder_construct( |
| @@ -106,6 +106,7 @@ · 105 unmodified lines | |||
| 106 | SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \ | 106 | SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \ |
| 107 | SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ | 107 | SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ |
| 108 | SRI(DIG_FE_CNTL, DIG, id), \ | 108 | SRI(DIG_FE_CNTL, DIG, id), \ |
| 109 | SRI(DIG_FIFO_STATUS, DIG, id), \ | ||
| 109 | SRI(DIG_CLOCK_PATTERN, DIG, id) | 110 | SRI(DIG_CLOCK_PATTERN, DIG, id) |
| 110 | 111 | ||
| 111 | 112 | ||
| @@ -167,6 +168,17 @@ · 55 unmodified lines | |||
| 167 | SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ | 168 | SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ |
| 168 | SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ | 169 | SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ |
| 169 | SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ | 170 | SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ |
| 171 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_LEVEL_ERROR, mask_sh),\ | ||
| 172 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_USE_OVERWRITE_LEVEL, mask_sh),\ | ||
| 173 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_OVERWRITE_LEVEL, mask_sh),\ | ||
| 174 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_ERROR_ACK, mask_sh),\ | ||
| 175 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CAL_AVERAGE_LEVEL, mask_sh),\ | ||
| 176 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MAXIMUM_LEVEL, mask_sh),\ | ||
| 177 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MINIMUM_LEVEL, mask_sh),\ | ||
| 178 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_READ_CLOCK_SRC, mask_sh),\ | ||
| 179 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CALIBRATED, mask_sh),\ | ||
| 180 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECAL_AVERAGE, mask_sh),\ | ||
| 181 | SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECOMP_MINMAX, mask_sh),\ | ||
| 170 | SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\ | 182 | SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\ |
| 171 | SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\ | 183 | SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\ |
| 172 | SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\ | 184 | SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\ |
| @@ -48,6 +48,8 @@ · 47 unmodified lines | |||
| 48 | #include "dc_dmub_srv.h" | 48 | #include "dc_dmub_srv.h" |
| 49 | #include "link_hwss.h" | 49 | #include "link_hwss.h" |
| 50 | #include "dpcd_defs.h" | 50 | #include "dpcd_defs.h" |
| 51 | #include "inc/dc_link_dp.h" | ||
| 52 | #include "inc/link_dpcd.h" | ||
| 51 | 53 | ||
| 52 | 54 | ||
| 53 | 55 | ||
| @@ -529,6 +531,8 @@ void dcn30_init_hw(struct dc *dc) · 475 unmodified lines | |||
| 529 | for (i = 0; i < dc->link_count; i++) { | 531 | for (i = 0; i < dc->link_count; i++) { |
| 530 | if (dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) | 532 | if (dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) |
| 531 | continue; | 533 | continue; |
| 534 | /* DP 2.0 states that LTTPR regs must be read first */ | ||
| 535 | dp_retrieve_lttpr_cap(dc->links[i]); | ||
| 532 | 536 | ||
| 533 | /* if any of the displays are lit up turn them off */ | 537 | /* if any of the displays are lit up turn them off */ |
| 534 | status = core_link_read_dpcd(dc->links[i], DP_SET_POWER, | 538 | status = core_link_read_dpcd(dc->links[i], DP_SET_POWER, |
| @@ -38,3 +38,8 @@ void dcn303_dsc_pg_control(struct dce_hwseq *hws, unsigned int dsc_inst, bool po · 37 unmodified lines | |||
| 38 | { | 38 | { |
| 39 | /*DCN303 removes PG registers*/ | 39 | /*DCN303 removes PG registers*/ |
| 40 | } | 40 | } |
| 41 | |||
| 42 | void dcn303_enable_power_gating_plane(struct dce_hwseq *hws, bool enable) | ||
| 43 | { | ||
| 44 | /*DCN303 removes PG registers*/ | ||
| 45 | } | ||
| @@ -13,5 +13,6 @@ · 12 unmodified lines | |||
| 13 | void dcn303_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on); | 13 | void dcn303_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on); |
| 14 | void dcn303_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on); | 14 | void dcn303_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on); |
| 15 | void dcn303_dsc_pg_control(struct dce_hwseq *hws, unsigned int dsc_inst, bool power_on); | 15 | void dcn303_dsc_pg_control(struct dce_hwseq *hws, unsigned int dsc_inst, bool power_on); |
| 16 | void dcn303_enable_power_gating_plane(struct dce_hwseq *hws, bool enable); | ||
| 16 | 17 | ||
| 17 | #endif /* __DC_HWSS_DCN303_H__ */ | 18 | #endif /* __DC_HWSS_DCN303_H__ */ |
| @@ -16,4 +16,5 @@ void dcn303_hw_sequencer_construct(struct dc *dc) · 15 unmodified lines | |||
| 16 | dc->hwseq->funcs.dpp_pg_control = dcn303_dpp_pg_control; | 16 | dc->hwseq->funcs.dpp_pg_control = dcn303_dpp_pg_control; |
| 17 | dc->hwseq->funcs.hubp_pg_control = dcn303_hubp_pg_control; | 17 | dc->hwseq->funcs.hubp_pg_control = dcn303_hubp_pg_control; |
| 18 | dc->hwseq->funcs.dsc_pg_control = dcn303_dsc_pg_control; | 18 | dc->hwseq->funcs.dsc_pg_control = dcn303_dsc_pg_control; |
| 19 | dc->hwseq->funcs.enable_power_gating_plane = dcn303_enable_power_gating_plane; | ||
| 19 | } | 20 | } |
| @@ -33,7 +33,6 @@ · 32 unmodified lines | |||
| 33 | #include "clk_mgr.h" | 33 | #include "clk_mgr.h" |
| 34 | #include "reg_helper.h" | 34 | #include "reg_helper.h" |
| 35 | #include "abm.h" | 35 | #include "abm.h" |
| 36 | #include "clk_mgr.h" | ||
| 37 | #include "hubp.h" | 36 | #include "hubp.h" |
| 38 | #include "dchubbub.h" | 37 | #include "dchubbub.h" |
| 39 | #include "timing_generator.h" | 38 | #include "timing_generator.h" |
| @@ -47,6 +46,7 @@ · 7 unmodified lines | |||
| 47 | #include "dpcd_defs.h" | 46 | #include "dpcd_defs.h" |
| 48 | #include "dce/dmub_outbox.h" | 47 | #include "dce/dmub_outbox.h" |
| 49 | #include "dc_link_dp.h" | 48 | #include "dc_link_dp.h" |
| 49 | #include "inc/link_dpcd.h" | ||
| 50 | 50 | ||
| 51 | #define DC_LOGGER_INIT(logger) | 51 | #define DC_LOGGER_INIT(logger) |
| 52 | 52 | ||
| @@ -934,7 +934,6 @@ static const struct dc_debug_options debug_defaults_drv = { · 933 unmodified lines | |||
| 934 | .dmub_command_table = true, | 934 | .dmub_command_table = true, |
| 935 | .pstate_enabled = true, | 935 | .pstate_enabled = true, |
| 936 | .use_max_lb = true, | 936 | .use_max_lb = true, |
| 937 | .pstate_enabled = true, | ||
| 938 | .enable_mem_low_power = { | 937 | .enable_mem_low_power = { |
| 939 | .bits = { | 938 | .bits = { |
| 940 | .vga = false, | 939 | .vga = false, |
| @@ -3536,7 +3536,7 @@ static bool CalculateBytePerPixelAnd256BBlockSizes( · 3535 unmodified lines | |||
| 3536 | *BytePerPixelDETC = 0; | 3536 | *BytePerPixelDETC = 0; |
| 3537 | *BytePerPixelY = 4; | 3537 | *BytePerPixelY = 4; |
| 3538 | *BytePerPixelC = 0; | 3538 | *BytePerPixelC = 0; |
| 3539 | } else if (SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_16) { | 3539 | } else if (SourcePixelFormat == dm_444_16) { |
| 3540 | *BytePerPixelDETY = 2; | 3540 | *BytePerPixelDETY = 2; |
| 3541 | *BytePerPixelDETC = 0; | 3541 | *BytePerPixelDETC = 0; |
| 3542 | *BytePerPixelY = 2; | 3542 | *BytePerPixelY = 2; |
| @@ -5674,7 +5674,7 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l · 2131 unmodified lines | |||
| 5674 | for (k = 0; k < v->NumberOfActivePlanes; k++) { | 5674 | for (k = 0; k < v->NumberOfActivePlanes; k++) { |
| 5675 | if (v->ViewportWidth[k] > v->SurfaceWidthY[k] || v->ViewportHeight[k] > v->SurfaceHeightY[k]) { | 5675 | if (v->ViewportWidth[k] > v->SurfaceWidthY[k] || v->ViewportHeight[k] > v->SurfaceHeightY[k]) { |
| 5676 | ViewportExceedsSurface = true; | 5676 | ViewportExceedsSurface = true; |
| 5677 | if (v->SourcePixelFormat[k] != dm_444_64 && v->SourcePixelFormat[k] != dm_444_32 && v->SourcePixelFormat[k] != dm_444_16 | 5677 | if (v->SourcePixelFormat[k] != dm_444_64 && v->SourcePixelFormat[k] != dm_444_32 |
| 5678 | && v->SourcePixelFormat[k] != dm_444_16 && v->SourcePixelFormat[k] != dm_444_8 | 5678 | && v->SourcePixelFormat[k] != dm_444_16 && v->SourcePixelFormat[k] != dm_444_8 |
| 5679 | && v->SourcePixelFormat[k] != dm_rgbe) { | 5679 | && v->SourcePixelFormat[k] != dm_rgbe) { |
| 5680 | if (v->ViewportWidthChroma[k] > v->SurfaceWidthC[k] | 5680 | if (v->ViewportWidthChroma[k] > v->SurfaceWidthC[k] |
| @@ -159,7 +159,6 @@ dml_get_pipe_attr_func(refcyc_per_meta_chunk_vblank_l_in_us, mode_lib->vba.TimeP · 158 unmodified lines | |||
| 159 | dml_get_pipe_attr_func(refcyc_per_meta_chunk_vblank_c_in_us, mode_lib->vba.TimePerChromaMetaChunkVBlank); | 159 | dml_get_pipe_attr_func(refcyc_per_meta_chunk_vblank_c_in_us, mode_lib->vba.TimePerChromaMetaChunkVBlank); |
| 160 | dml_get_pipe_attr_func(refcyc_per_meta_chunk_flip_l_in_us, mode_lib->vba.TimePerMetaChunkFlip); | 160 | dml_get_pipe_attr_func(refcyc_per_meta_chunk_flip_l_in_us, mode_lib->vba.TimePerMetaChunkFlip); |
| 161 | dml_get_pipe_attr_func(refcyc_per_meta_chunk_flip_c_in_us, mode_lib->vba.TimePerChromaMetaChunkFlip); | 161 | dml_get_pipe_attr_func(refcyc_per_meta_chunk_flip_c_in_us, mode_lib->vba.TimePerChromaMetaChunkFlip); |
| 162 | |||
| 163 | dml_get_pipe_attr_func(vstartup, mode_lib->vba.VStartup); | 162 | dml_get_pipe_attr_func(vstartup, mode_lib->vba.VStartup); |
| 164 | dml_get_pipe_attr_func(vupdate_offset, mode_lib->vba.VUpdateOffsetPix); | 163 | dml_get_pipe_attr_func(vupdate_offset, mode_lib->vba.VUpdateOffsetPix); |
| 165 | dml_get_pipe_attr_func(vupdate_width, mode_lib->vba.VUpdateWidthPix); | 164 | dml_get_pipe_attr_func(vupdate_width, mode_lib->vba.VUpdateWidthPix); |
| @@ -419,7 +418,6 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) · 253 unmodified lines | |||
| 419 | visited[j] = true; | 418 | visited[j] = true; |
| 420 | 419 | ||
| 421 | mode_lib->vba.pipe_plane[j] = mode_lib->vba.NumberOfActivePlanes; | 420 | mode_lib->vba.pipe_plane[j] = mode_lib->vba.NumberOfActivePlanes; |
| 422 | |||
| 423 | mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes] = 1; | 421 | mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes] = 1; |
| 424 | mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] = | 422 | mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] = |
| 425 | (enum scan_direction_class) (src->source_scan); | 423 | (enum scan_direction_class) (src->source_scan); |
| @@ -33,6 +33,7 @@ · 32 unmodified lines | |||
| 33 | #include "core_types.h" | 33 | #include "core_types.h" |
| 34 | #include "dc_link_ddc.h" | 34 | #include "dc_link_ddc.h" |
| 35 | #include "link_hwss.h" | 35 | #include "link_hwss.h" |
| 36 | #include "inc/link_dpcd.h" | ||
| 36 | 37 | ||
| 37 | #define DC_LOGGER \ | 38 | #define DC_LOGGER \ |
| 38 | link->ctx->logger | 39 | link->ctx->logger |
| @@ -42,7 +42,15 @@ enum { · 41 unmodified lines | |||
| 42 | /* to avoid infinite loop where-in the receiver | 42 | /* to avoid infinite loop where-in the receiver |
| 43 | * switches between different VS | 43 | * switches between different VS |
| 44 | */ | 44 | */ |
| 45 | LINK_TRAINING_MAX_CR_RETRY = 100 | 45 | LINK_TRAINING_MAX_CR_RETRY = 100, |
| 46 | /* | ||
| 47 | * Some receivers fail to train on first try and are good | ||
| 48 | * on subsequent tries. 2 retries should be plenty. If we | ||
| 49 | * don't have a successful training then we don't expect to | ||
| 50 | * ever get one. | ||
| 51 | */ | ||
| 52 | LINK_TRAINING_MAX_VERIFY_RETRY = 2, | ||
| 53 | PEAK_FACTOR_X1000 = 1006, | ||
| 46 | }; | 54 | }; |
| 47 | 55 | ||
| 48 | bool dp_verify_link_cap( | 56 | bool dp_verify_link_cap( |
| @@ -182,4 +190,5 @@ enum dc_status dpcd_configure_lttpr_mode( · 133 unmodified lines | |||
| 182 | struct link_training_settings *lt_settings); | 190 | struct link_training_settings *lt_settings); |
| 183 | 191 | ||
| 184 | enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings *link_settings); | 192 | enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings *link_settings); |
| 193 | bool dp_retrieve_lttpr_cap(struct dc_link *link); | ||
| 185 | #endif /* __DC_LINK_DP_H__ */ | 194 | #endif /* __DC_LINK_DP_H__ */ |
| @@ -237,6 +237,9 @@ struct stream_encoder_funcs { · 236 unmodified lines | |||
| 237 | void (*dp_set_odm_combine)( | 237 | void (*dp_set_odm_combine)( |
| 238 | struct stream_encoder *enc, | 238 | struct stream_encoder *enc, |
| 239 | bool odm_combine); | 239 | bool odm_combine); |
| 240 | |||
| 241 | uint32_t (*get_fifo_cal_average_level)( | ||
| 242 | struct stream_encoder *enc); | ||
| 240 | }; | 243 | }; |
| 241 | 244 | ||
| 242 | #endif /* STREAM_ENCODER_H_ */ | 245 | #endif /* STREAM_ENCODER_H_ */ |
| @@ -0,0 +1,18 @@ | |||
| 1 | #ifndef __LINK_DPCD_H__ | ||
| 2 | #define __LINK_DPCD_H__ | ||
| 3 | #include <inc/core_status.h> | ||
| 4 | #include <dc_link.h> | ||
| 5 | #include <inc/link_hwss.h> | ||
| 6 | |||
| 7 | enum dc_status core_link_read_dpcd( | ||
| 8 | struct dc_link *link, | ||
| 9 | uint32_t address, | ||
| 10 | uint8_t *data, | ||
| 11 | uint32_t size); | ||
| 12 | |||
| 13 | enum dc_status core_link_write_dpcd( | ||
| 14 | struct dc_link *link, | ||
| 15 | uint32_t address, | ||
| 16 | const uint8_t *data, | ||
| 17 | uint32_t size); | ||
| 18 | #endif | ||
| @@ -26,20 +26,6 @@ · 25 unmodified lines | |||
| 26 | #ifndef __DC_LINK_HWSS_H__ | 26 | #ifndef __DC_LINK_HWSS_H__ |
| 27 | #define __DC_LINK_HWSS_H__ | 27 | #define __DC_LINK_HWSS_H__ |
| 28 | 28 | ||
| 29 | #include "inc/core_status.h" | ||
| 30 | |||
| 31 | enum dc_status core_link_read_dpcd( | ||
| 32 | struct dc_link *link, | ||
| 33 | uint32_t address, | ||
| 34 | uint8_t *data, | ||
| 35 | uint32_t size); | ||
| 36 | |||
| 37 | enum dc_status core_link_write_dpcd( | ||
| 38 | struct dc_link *link, | ||
| 39 | uint32_t address, | ||
| 40 | const uint8_t *data, | ||
| 41 | uint32_t size); | ||
| 42 | |||
| 43 | struct gpio *get_hpd_gpio(struct dc_bios *dcb, | 29 | struct gpio *get_hpd_gpio(struct dc_bios *dcb, |
| 44 | struct graphics_object_id link_id, | 30 | struct graphics_object_id link_id, |
| 45 | struct gpio_service *gpio_service); | 31 | struct gpio_service *gpio_service); |
| @@ -243,6 +243,31 @@ struct dmub_srv_hw_params { · 242 unmodified lines | |||
| 243 | #endif | 243 | #endif |
| 244 | }; | 244 | }; |
| 245 | 245 | ||
| 246 | /** | ||
| 247 | * struct dmub_diagnostic_data - Diagnostic data retrieved from DMCUB for | ||
| 248 | * debugging purposes, including logging, crash analysis, etc. | ||
| 249 | */ | ||
| 250 | struct dmub_diagnostic_data { | ||
| 251 | uint32_t dmcub_version; | ||
| 252 | uint32_t scratch[16]; | ||
| 253 | uint32_t pc; | ||
| 254 | uint32_t undefined_address_fault_addr; | ||
| 255 | uint32_t inst_fetch_fault_addr; | ||
| 256 | uint32_t data_write_fault_addr; | ||
| 257 | uint32_t inbox1_rptr; | ||
| 258 | uint32_t inbox1_wptr; | ||
| 259 | uint32_t inbox1_size; | ||
| 260 | uint32_t inbox0_rptr; | ||
| 261 | uint32_t inbox0_wptr; | ||
| 262 | uint32_t inbox0_size; | ||
| 263 | uint8_t is_dmcub_enabled : 1; | ||
| 264 | uint8_t is_dmcub_soft_reset : 1; | ||
| 265 | uint8_t is_dmcub_secure_reset : 1; | ||
| 266 | uint8_t is_traceport_en : 1; | ||
| 267 | uint8_t is_cw0_enabled : 1; | ||
| 268 | uint8_t is_cw6_enabled : 1; | ||
| 269 | }; | ||
| 270 | |||
| 246 | /** | 271 | /** |
| 247 | * struct dmub_srv_base_funcs - Driver specific base callbacks | 272 | * struct dmub_srv_base_funcs - Driver specific base callbacks |
| 248 | */ | 273 | */ |
| @@ -335,6 +360,8 @@ struct dmub_srv_hw_funcs { · 86 unmodified lines | |||
| 335 | 360 | ||
| 336 | void (*send_inbox0_cmd)(struct dmub_srv *dmub, union dmub_inbox0_data_register data); | 361 | void (*send_inbox0_cmd)(struct dmub_srv *dmub, union dmub_inbox0_data_register data); |
| 337 | uint32_t (*get_current_time)(struct dmub_srv *dmub); | 362 | uint32_t (*get_current_time)(struct dmub_srv *dmub); |
| 363 | |||
| 364 | void (*get_diagnostic_data)(struct dmub_srv *dmub, struct dmub_diagnostic_data *dmub_oca); | ||
| 338 | }; | 365 | }; |
| 339 | 366 | ||
| 340 | /** | 367 | /** |
| @@ -685,6 +712,8 @@ enum dmub_status dmub_srv_cmd_with_reply_data(struct dmub_srv *dmub, · 344 unmodified lines | |||
| 685 | 712 | ||
| 686 | bool dmub_srv_get_outbox0_msg(struct dmub_srv *dmub, struct dmcub_trace_buf_entry *entry); | 713 | bool dmub_srv_get_outbox0_msg(struct dmub_srv *dmub, struct dmcub_trace_buf_entry *entry); |
| 687 | 714 | ||
| 715 | bool dmub_srv_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data); | ||
| 716 | |||
| 688 | #if defined(__cplusplus) | 717 | #if defined(__cplusplus) |
| 689 | } | 718 | } |
| 690 | #endif | 719 | #endif |
| @@ -47,10 +47,10 @@ · 46 unmodified lines | |||
| 47 | 47 | ||
| 48 | /* Firmware versioning. */ | 48 | /* Firmware versioning. */ |
| 49 | #ifdef DMUB_EXPOSE_VERSION | 49 | #ifdef DMUB_EXPOSE_VERSION |
| 50 | #define DMUB_FW_VERSION_GIT_HASH 0xefd666c1 | 50 | #define DMUB_FW_VERSION_GIT_HASH 0x5cac099d3 |
| 51 | #define DMUB_FW_VERSION_MAJOR 0 | 51 | #define DMUB_FW_VERSION_MAJOR 0 |
| 52 | #define DMUB_FW_VERSION_MINOR 0 | 52 | #define DMUB_FW_VERSION_MINOR 0 |
| 53 | #define DMUB_FW_VERSION_REVISION 69 | 53 | #define DMUB_FW_VERSION_REVISION 70 |
| 54 | #define DMUB_FW_VERSION_TEST 0 | 54 | #define DMUB_FW_VERSION_TEST 0 |
| 55 | #define DMUB_FW_VERSION_VBIOS 0 | 55 | #define DMUB_FW_VERSION_VBIOS 0 |
| 56 | #define DMUB_FW_VERSION_HOTFIX 0 | 56 | #define DMUB_FW_VERSION_HOTFIX 0 |
| @@ -40,7 +40,10 @@ · 39 unmodified lines | |||
| 40 | 40 | ||
| 41 | const struct dmub_srv_common_regs dmub_srv_dcn20_regs = { | 41 | const struct dmub_srv_common_regs dmub_srv_dcn20_regs = { |
| 42 | #define DMUB_SR(reg) REG_OFFSET(reg), | 42 | #define DMUB_SR(reg) REG_OFFSET(reg), |
| 43 | { DMUB_COMMON_REGS() }, | 43 | { |
| 44 | DMUB_COMMON_REGS() | ||
| 45 | DMCUB_INTERNAL_REGS() | ||
| 46 | }, | ||
| 44 | #undef DMUB_SR | 47 | #undef DMUB_SR |
| 45 | 48 | ||
| 46 | #define DMUB_SF(reg, field) FD_MASK(reg, field), | 49 | #define DMUB_SF(reg, field) FD_MASK(reg, field), |
| @@ -404,3 +407,63 @@ uint32_t dmub_dcn20_get_current_time(struct dmub_srv *dmub) · 357 unmodified lines | |||
| 404 | { | 407 | { |
| 405 | return REG_READ(DMCUB_TIMER_CURRENT); | 408 | return REG_READ(DMCUB_TIMER_CURRENT); |
| 406 | } | 409 | } |
| 410 | |||
| 411 | void dmub_dcn20_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data) | ||
| 412 | { | ||
| 413 | uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset; | ||
| 414 | uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled; | ||
| 415 | |||
| 416 | if (!dmub || !diag_data) | ||
| 417 | return; | ||
| 418 | |||
| 419 | memset(diag_data, 0, sizeof(*diag_data)); | ||
| 420 | |||
| 421 | diag_data->dmcub_version = dmub->fw_version; | ||
| 422 | |||
| 423 | diag_data->scratch[0] = REG_READ(DMCUB_SCRATCH0); | ||
| 424 | diag_data->scratch[1] = REG_READ(DMCUB_SCRATCH1); | ||
| 425 | diag_data->scratch[2] = REG_READ(DMCUB_SCRATCH2); | ||
| 426 | diag_data->scratch[3] = REG_READ(DMCUB_SCRATCH3); | ||
| 427 | diag_data->scratch[4] = REG_READ(DMCUB_SCRATCH4); | ||
| 428 | diag_data->scratch[5] = REG_READ(DMCUB_SCRATCH5); | ||
| 429 | diag_data->scratch[6] = REG_READ(DMCUB_SCRATCH6); | ||
| 430 | diag_data->scratch[7] = REG_READ(DMCUB_SCRATCH7); | ||
| 431 | diag_data->scratch[8] = REG_READ(DMCUB_SCRATCH8); | ||
| 432 | diag_data->scratch[9] = REG_READ(DMCUB_SCRATCH9); | ||
| 433 | diag_data->scratch[10] = REG_READ(DMCUB_SCRATCH10); | ||
| 434 | diag_data->scratch[11] = REG_READ(DMCUB_SCRATCH11); | ||
| 435 | diag_data->scratch[12] = REG_READ(DMCUB_SCRATCH12); | ||
| 436 | diag_data->scratch[13] = REG_READ(DMCUB_SCRATCH13); | ||
| 437 | diag_data->scratch[14] = REG_READ(DMCUB_SCRATCH14); | ||
| 438 | diag_data->scratch[15] = REG_READ(DMCUB_SCRATCH15); | ||
| 439 | |||
| 440 | diag_data->undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); | ||
| 441 | diag_data->inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); | ||
| 442 | diag_data->data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); | ||
| 443 | |||
| 444 | diag_data->inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); | ||
| 445 | diag_data->inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); | ||
| 446 | diag_data->inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); | ||
| 447 | |||
| 448 | diag_data->inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); | ||
| 449 | diag_data->inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); | ||
| 450 | diag_data->inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); | ||
| 451 | |||
| 452 | REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled); | ||
| 453 | diag_data->is_dmcub_enabled = is_dmub_enabled; | ||
| 454 | |||
| 455 | REG_GET(DMCUB_CNTL, DMCUB_SOFT_RESET, &is_soft_reset); | ||
| 456 | diag_data->is_dmcub_soft_reset = is_soft_reset; | ||
| 457 | |||
| 458 | REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset); | ||
| 459 | diag_data->is_dmcub_secure_reset = is_sec_reset; | ||
| 460 | |||
| 461 | REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled); | ||
| 462 | diag_data->is_traceport_en = is_traceport_enabled; | ||
| 463 | |||
| 464 | REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled); | ||
| 465 | diag_data->is_cw0_enabled = is_cw0_enabled; | ||
| 466 | |||
| 467 | REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); | ||
| 468 | diag_data->is_cw6_enabled = is_cw6_enabled; | ||
| 469 | } | ||
| @@ -36,6 +36,9 @@ struct dmub_srv; · 35 unmodified lines | |||
| 36 | DMUB_SR(DMCUB_CNTL) \ | 36 | DMUB_SR(DMCUB_CNTL) \ |
| 37 | DMUB_SR(DMCUB_MEM_CNTL) \ | 37 | DMUB_SR(DMCUB_MEM_CNTL) \ |
| 38 | DMUB_SR(DMCUB_SEC_CNTL) \ | 38 | DMUB_SR(DMCUB_SEC_CNTL) \ |
| 39 | DMUB_SR(DMCUB_INBOX0_SIZE) \ | ||
| 40 | DMUB_SR(DMCUB_INBOX0_RPTR) \ | ||
| 41 | DMUB_SR(DMCUB_INBOX0_WPTR) \ | ||
| 39 | DMUB_SR(DMCUB_INBOX1_BASE_ADDRESS) \ | 42 | DMUB_SR(DMCUB_INBOX1_BASE_ADDRESS) \ |
| 40 | DMUB_SR(DMCUB_INBOX1_SIZE) \ | 43 | DMUB_SR(DMCUB_INBOX1_SIZE) \ |
| 41 | DMUB_SR(DMCUB_INBOX1_RPTR) \ | 44 | DMUB_SR(DMCUB_INBOX1_RPTR) \ |
| @@ -108,7 +111,12 @@ struct dmub_srv; · 66 unmodified lines | |||
| 108 | DMUB_SR(DCN_VM_FB_LOCATION_BASE) \ | 111 | DMUB_SR(DCN_VM_FB_LOCATION_BASE) \ |
| 109 | DMUB_SR(DCN_VM_FB_OFFSET) \ | 112 | DMUB_SR(DCN_VM_FB_OFFSET) \ |
| 110 | DMUB_SR(DMCUB_INTERRUPT_ACK) \ | 113 | DMUB_SR(DMCUB_INTERRUPT_ACK) \ |
| 111 | DMUB_SR(DMCUB_TIMER_CURRENT) | 114 | DMUB_SR(DMCUB_TIMER_CURRENT) \ |
| 115 | DMUB_SR(DMCUB_INST_FETCH_FAULT_ADDR) \ | ||
| 116 | DMUB_SR(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR) \ | ||
| 117 | DMUB_SR(DMCUB_DATA_WRITE_FAULT_ADDR) | ||
| 118 | |||
| 119 | #define DMCUB_INTERNAL_REGS() | ||
| 112 | 120 | ||
| 113 | #define DMUB_COMMON_FIELDS() \ | 121 | #define DMUB_COMMON_FIELDS() \ |
| 114 | DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \ | 122 | DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \ |
| @@ -118,6 +126,7 @@ struct dmub_srv; · 3 unmodified lines | |||
| 118 | DMUB_SF(DMCUB_MEM_CNTL, DMCUB_MEM_WRITE_SPACE) \ | 126 | DMUB_SF(DMCUB_MEM_CNTL, DMCUB_MEM_WRITE_SPACE) \ |
| 119 | DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET) \ | 127 | DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET) \ |
| 120 | DMUB_SF(DMCUB_SEC_CNTL, DMCUB_MEM_UNIT_ID) \ | 128 | DMUB_SF(DMCUB_SEC_CNTL, DMCUB_MEM_UNIT_ID) \ |
| 129 | DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS) \ | ||
| 121 | DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_TOP_ADDRESS) \ | 130 | DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_TOP_ADDRESS) \ |
| 122 | DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE) \ | 131 | DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE) \ |
| 123 | DMUB_SF(DMCUB_REGION3_CW1_TOP_ADDRESS, DMCUB_REGION3_CW1_TOP_ADDRESS) \ | 132 | DMUB_SF(DMCUB_REGION3_CW1_TOP_ADDRESS, DMCUB_REGION3_CW1_TOP_ADDRESS) \ |
| @@ -147,6 +156,7 @@ struct dmub_srv; · 23 unmodified lines | |||
| 147 | struct dmub_srv_common_reg_offset { | 156 | struct dmub_srv_common_reg_offset { |
| 148 | #define DMUB_SR(reg) uint32_t reg; | 157 | #define DMUB_SR(reg) uint32_t reg; |
| 149 | DMUB_COMMON_REGS() | 158 | DMUB_COMMON_REGS() |
| 159 | DMCUB_INTERNAL_REGS() | ||
| 150 | #undef DMUB_SR | 160 | #undef DMUB_SR |
| 151 | }; | 161 | }; |
| 152 | 162 | ||
| @@ -234,4 +244,6 @@ bool dmub_dcn20_use_cached_trace_buffer(struct dmub_srv *dmub); · 81 unmodified lines | |||
| 234 | 244 | ||
| 235 | uint32_t dmub_dcn20_get_current_time(struct dmub_srv *dmub); | 245 | uint32_t dmub_dcn20_get_current_time(struct dmub_srv *dmub); |
| 236 | 246 | ||
| 247 | void dmub_dcn20_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *dmub_oca); | ||
| 248 | |||
| 237 | #endif /* _DMUB_DCN20_H_ */ | 249 | #endif /* _DMUB_DCN20_H_ */ |
| @@ -39,7 +39,10 @@ · 38 unmodified lines | |||
| 39 | 39 | ||
| 40 | const struct dmub_srv_common_regs dmub_srv_dcn21_regs = { | 40 | const struct dmub_srv_common_regs dmub_srv_dcn21_regs = { |
| 41 | #define DMUB_SR(reg) REG_OFFSET(reg), | 41 | #define DMUB_SR(reg) REG_OFFSET(reg), |
| 42 | { DMUB_COMMON_REGS() }, | 42 | { |
| 43 | DMUB_COMMON_REGS() | ||
| 44 | DMCUB_INTERNAL_REGS() | ||
| 45 | }, | ||
| 43 | #undef DMUB_SR | 46 | #undef DMUB_SR |
| 44 | 47 | ||
| 45 | #define DMUB_SF(reg, field) FD_MASK(reg, field), | 48 | #define DMUB_SF(reg, field) FD_MASK(reg, field), |
| @@ -40,7 +40,10 @@ · 39 unmodified lines | |||
| 40 | 40 | ||
| 41 | const struct dmub_srv_common_regs dmub_srv_dcn30_regs = { | 41 | const struct dmub_srv_common_regs dmub_srv_dcn30_regs = { |
| 42 | #define DMUB_SR(reg) REG_OFFSET(reg), | 42 | #define DMUB_SR(reg) REG_OFFSET(reg), |
| 43 | { DMUB_COMMON_REGS() }, | 43 | { |
| 44 | DMUB_COMMON_REGS() | ||
| 45 | DMCUB_INTERNAL_REGS() | ||
| 46 | }, | ||
| 44 | #undef DMUB_SR | 47 | #undef DMUB_SR |
| 45 | 48 | ||
| 46 | #define DMUB_SF(reg, field) FD_MASK(reg, field), | 49 | #define DMUB_SF(reg, field) FD_MASK(reg, field), |
| @@ -39,7 +39,10 @@ · 38 unmodified lines | |||
| 39 | 39 | ||
| 40 | const struct dmub_srv_common_regs dmub_srv_dcn301_regs = { | 40 | const struct dmub_srv_common_regs dmub_srv_dcn301_regs = { |
| 41 | #define DMUB_SR(reg) REG_OFFSET(reg), | 41 | #define DMUB_SR(reg) REG_OFFSET(reg), |
| 42 | { DMUB_COMMON_REGS() }, | 42 | { |
| 43 | DMUB_COMMON_REGS() | ||
| 44 | DMCUB_INTERNAL_REGS() | ||
| 45 | }, | ||
| 43 | #undef DMUB_SR | 46 | #undef DMUB_SR |
| 44 | 47 | ||
| 45 | #define DMUB_SF(reg, field) FD_MASK(reg, field), | 48 | #define DMUB_SF(reg, field) FD_MASK(reg, field), |
| @@ -39,7 +39,10 @@ · 38 unmodified lines | |||
| 39 | 39 | ||
| 40 | const struct dmub_srv_common_regs dmub_srv_dcn302_regs = { | 40 | const struct dmub_srv_common_regs dmub_srv_dcn302_regs = { |
| 41 | #define DMUB_SR(reg) REG_OFFSET(reg), | 41 | #define DMUB_SR(reg) REG_OFFSET(reg), |
| 42 | { DMUB_COMMON_REGS() }, | 42 | { |
| 43 | DMUB_COMMON_REGS() | ||
| 44 | DMCUB_INTERNAL_REGS() | ||
| 45 | }, | ||
| 43 | #undef DMUB_SR | 46 | #undef DMUB_SR |
| 44 | 47 | ||
| 45 | #define DMUB_SF(reg, field) FD_MASK(reg, field), | 48 | #define DMUB_SF(reg, field) FD_MASK(reg, field), |
| @@ -21,7 +21,10 @@ · 20 unmodified lines | |||
| 21 | 21 | ||
| 22 | const struct dmub_srv_common_regs dmub_srv_dcn303_regs = { | 22 | const struct dmub_srv_common_regs dmub_srv_dcn303_regs = { |
| 23 | #define DMUB_SR(reg) REG_OFFSET(reg), | 23 | #define DMUB_SR(reg) REG_OFFSET(reg), |
| 24 | { DMUB_COMMON_REGS() }, | 24 | { |
| 25 | DMUB_COMMON_REGS() | ||
| 26 | DMCUB_INTERNAL_REGS() | ||
| 27 | }, | ||
| 25 | #undef DMUB_SR | 28 | #undef DMUB_SR |
| 26 | 29 | ||
| 27 | #define DMUB_SF(reg, field) FD_MASK(reg, field), | 30 | #define DMUB_SF(reg, field) FD_MASK(reg, field), |
| @@ -176,6 +176,8 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) · 175 unmodified lines | |||
| 176 | funcs->get_outbox0_wptr = dmub_dcn20_get_outbox0_wptr; | 176 | funcs->get_outbox0_wptr = dmub_dcn20_get_outbox0_wptr; |
| 177 | funcs->set_outbox0_rptr = dmub_dcn20_set_outbox0_rptr; | 177 | funcs->set_outbox0_rptr = dmub_dcn20_set_outbox0_rptr; |
| 178 | 178 | ||
| 179 | funcs->get_diagnostic_data = dmub_dcn20_get_diagnostic_data; | ||
| 180 | |||
| 179 | if (asic == DMUB_ASIC_DCN21) { | 181 | if (asic == DMUB_ASIC_DCN21) { |
| 180 | dmub->regs = &dmub_srv_dcn21_regs; | 182 | dmub->regs = &dmub_srv_dcn21_regs; |
| 181 | 183 | ||
| @@ -794,3 +796,11 @@ bool dmub_srv_get_outbox0_msg(struct dmub_srv *dmub, struct dmcub_trace_buf_entr · 612 unmodified lines | |||
| 794 | 796 | ||
| 795 | return dmub_rb_out_trace_buffer_front(&dmub->outbox0_rb, (void *)entry); | 797 | return dmub_rb_out_trace_buffer_front(&dmub->outbox0_rb, (void *)entry); |
| 796 | } | 798 | } |
| 799 | |||
| 800 | bool dmub_srv_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data) | ||
| 801 | { | ||
| 802 | if (!dmub || !dmub->hw_funcs.get_diagnostic_data || !diag_data) | ||
| 803 | return false; | ||
| 804 | dmub->hw_funcs.get_diagnostic_data(dmub, diag_data); | ||
| 805 | return true; | ||
| 806 | } | ||
| @@ -87,19 +87,19 @@ struct abm_parameters { · 86 unmodified lines | |||
| 87 | }; | 87 | }; |
| 88 | 88 | ||
| 89 | static const struct abm_parameters abm_settings_config0[abm_defines_max_level] = { | 89 | static const struct abm_parameters abm_settings_config0[abm_defines_max_level] = { |
| 90 | // min_red max_red bright_pos dark_pos bright_gain contrast dev min_knee max_knee blStart blRed | 90 | // min_red max_red bright_pos dark_pos bright_gain contrast dev min_knee max_knee blRed blStart |
| 91 | {0xff, 0xbf, 0x20, 0x00, 0xff, 0x99, 0xb3, 0x40, 0xe0, 0xCCCC, 0xCCCC}, | 91 | {0xff, 0xbf, 0x20, 0x00, 0xff, 0x99, 0xb3, 0x40, 0xe0, 0xf777, 0xcccc}, |
| 92 | {0xde, 0x85, 0x20, 0x00, 0xff, 0x90, 0xa8, 0x40, 0xdf, 0xCCCC, 0xCCCC}, | 92 | {0xde, 0x85, 0x20, 0x00, 0xe0, 0x90, 0xa8, 0x40, 0xc8, 0xf777, 0xcccc}, |
| 93 | {0xb0, 0x50, 0x20, 0x00, 0xc0, 0x88, 0x78, 0x70, 0xa0, 0xCCCC, 0xCCCC}, | 93 | {0xb0, 0x50, 0x20, 0x00, 0xc0, 0x88, 0x78, 0x70, 0xa0, 0xeeee, 0x9999}, |
| 94 | {0x82, 0x40, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xCCCC, 0xCCCC}, | 94 | {0x82, 0x40, 0x20, 0x00, 0x00, 0xb8, 0xb3, 0x70, 0x70, 0xe333, 0xb333}, |
| 95 | }; | 95 | }; |
| 96 | 96 | ||
| 97 | static const struct abm_parameters abm_settings_config1[abm_defines_max_level] = { | 97 | static const struct abm_parameters abm_settings_config1[abm_defines_max_level] = { |
| 98 | // min_red max_red bright_pos dark_pos bright_gain contrast dev min_knee max_knee blStart blRed | 98 | // min_red max_red bright_pos dark_pos bright_gain contrast dev min_knee max_knee blRed blStart |
| 99 | {0xf0, 0xd9, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xCCCC, 0xCCCC}, | 99 | {0xf0, 0xd9, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xcccc, 0xcccc}, |
| 100 | {0xcd, 0xa5, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xCCCC, 0xCCCC}, | 100 | {0xcd, 0xa5, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xcccc, 0xcccc}, |
| 101 | {0x99, 0x65, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xCCCC, 0xCCCC}, | 101 | {0x99, 0x65, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xcccc, 0xcccc}, |
| 102 | {0x82, 0x4d, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xCCCC, 0xCCCC}, | 102 | {0x82, 0x4d, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xcccc, 0xcccc}, |
| 103 | }; | 103 | }; |
| 104 | 104 | ||
| 105 | static const struct abm_parameters * const abm_settings[] = { | 105 | static const struct abm_parameters * const abm_settings[] = { |
| @@ -29292,6 +29292,7 @@ · 29291 unmodified lines | |||
| 29292 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL_MASK 0x000000FCL | 29292 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL_MASK 0x000000FCL |
| 29293 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK_MASK 0x00000100L | 29293 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK_MASK 0x00000100L |
| 29294 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_CAL_AVERAGE_LEVEL_MASK 0x0000FC00L | 29294 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_CAL_AVERAGE_LEVEL_MASK 0x0000FC00L |
| 29295 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_MAXIMUM_LEVEL_MASK 0x001F0000L | ||
| 29295 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL_MASK 0x03C00000L | 29296 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL_MASK 0x03C00000L |
| 29296 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_READ_CLOCK_SRC_MASK 0x04000000L | 29297 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_READ_CLOCK_SRC_MASK 0x04000000L |
| 29297 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED_MASK 0x20000000L | 29298 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED_MASK 0x20000000L |
| @@ -34431,6 +34432,7 @@ · 5133 unmodified lines | |||
| 34431 | #define DIG3_DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL__SHIFT 0x2 | 34432 | #define DIG3_DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL__SHIFT 0x2 |
| 34432 | #define DIG3_DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK__SHIFT 0x8 | 34433 | #define DIG3_DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK__SHIFT 0x8 |
| 34433 | #define DIG3_DIG_FIFO_STATUS__DIG_FIFO_CAL_AVERAGE_LEVEL__SHIFT 0xa | 34434 | #define DIG3_DIG_FIFO_STATUS__DIG_FIFO_CAL_AVERAGE_LEVEL__SHIFT 0xa |
| 34435 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_MAXIMUM_LEVEL__SHIFT 0x10 | ||
| 34434 | #define DIG3_DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL__SHIFT 0x16 | 34436 | #define DIG3_DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL__SHIFT 0x16 |
| 34435 | #define DIG3_DIG_FIFO_STATUS__DIG_FIFO_READ_CLOCK_SRC__SHIFT 0x1a | 34437 | #define DIG3_DIG_FIFO_STATUS__DIG_FIFO_READ_CLOCK_SRC__SHIFT 0x1a |
| 34436 | #define DIG3_DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED__SHIFT 0x1d | 34438 | #define DIG3_DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED__SHIFT 0x1d |
| @@ -33869,6 +33869,7 @@ · 33868 unmodified lines | |||
| 33869 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL__SHIFT 0x2 | 33869 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL__SHIFT 0x2 |
| 33870 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK__SHIFT 0x8 | 33870 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK__SHIFT 0x8 |
| 33871 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_CAL_AVERAGE_LEVEL__SHIFT 0xa | 33871 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_CAL_AVERAGE_LEVEL__SHIFT 0xa |
| 33872 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_MAXIMUM_LEVEL__SHIFT 0x10 | ||
| 33872 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL__SHIFT 0x16 | 33873 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL__SHIFT 0x16 |
| 33873 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_READ_CLOCK_SRC__SHIFT 0x1a | 33874 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_READ_CLOCK_SRC__SHIFT 0x1a |
| 33874 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED__SHIFT 0x1d | 33875 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED__SHIFT 0x1d |
| @@ -33879,6 +33880,7 @@ · 4 unmodified lines | |||
| 33879 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL_MASK 0x000000FCL | 33880 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL_MASK 0x000000FCL |
| 33880 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK_MASK 0x00000100L | 33881 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK_MASK 0x00000100L |
| 33881 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_CAL_AVERAGE_LEVEL_MASK 0x0000FC00L | 33882 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_CAL_AVERAGE_LEVEL_MASK 0x0000FC00L |
| 33883 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_MAXIMUM_LEVEL_MASK 0x001F0000L | ||
| 33882 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL_MASK 0x03C00000L | 33884 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL_MASK 0x03C00000L |
| 33883 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_READ_CLOCK_SRC_MASK 0x04000000L | 33885 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_READ_CLOCK_SRC_MASK 0x04000000L |
| 33884 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED_MASK 0x20000000L | 33886 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED_MASK 0x20000000L |
| @@ -560,7 +560,7 @@ struct gpu_metrics_v1_2 { · 559 unmodified lines | |||
| 560 | uint16_t current_vclk1; | 560 | uint16_t current_vclk1; |
| 561 | uint16_t current_dclk1; | 561 | uint16_t current_dclk1; |
| 562 | 562 | ||
| 563 | /* Throttle status */ | 563 | /* Throttle status (ASIC dependent) */ |
| 564 | uint32_t throttle_status; | 564 | uint32_t throttle_status; |
| 565 | 565 | ||
| 566 | /* Fans */ | 566 | /* Fans */ |
| @@ -648,6 +648,9 @@ struct gpu_metrics_v1_3 { · 81 unmodified lines | |||
| 648 | uint16_t voltage_mem; | 648 | uint16_t voltage_mem; |
| 649 | 649 | ||
| 650 | uint16_t padding1; | 650 | uint16_t padding1; |
| 651 | |||
| 652 | /* Throttle status (ASIC independent) */ | ||
| 653 | uint64_t indep_throttle_status; | ||
| 651 | }; | 654 | }; |
| 652 | 655 | ||
| 653 | /* | 656 | /* |
| @@ -754,4 +757,57 @@ struct gpu_metrics_v2_1 { · 100 unmodified lines | |||
| 754 | uint16_t padding[3]; | 757 | uint16_t padding[3]; |
| 755 | }; | 758 | }; |
| 756 | 759 | ||
| 760 | struct gpu_metrics_v2_2 { | ||
| 761 | struct metrics_table_header common_header; | ||
| 762 | |||
| 763 | /* Temperature */ | ||
| 764 | uint16_t temperature_gfx; // gfx temperature on APUs | ||
| 765 | uint16_t temperature_soc; // soc temperature on APUs | ||
| 766 | uint16_t temperature_core[8]; // CPU core temperature on APUs | ||
| 767 | uint16_t temperature_l3[2]; | ||
| 768 | |||
| 769 | /* Utilization */ | ||
| 770 | uint16_t average_gfx_activity; | ||
| 771 | uint16_t average_mm_activity; // UVD or VCN | ||
| 772 | |||
| 773 | /* Driver attached timestamp (in ns) */ | ||
| 774 | uint64_t system_clock_counter; | ||
| 775 | |||
| 776 | /* Power/Energy */ | ||
| 777 | uint16_t average_socket_power; // dGPU + APU power on A + A platform | ||
| 778 | uint16_t average_cpu_power; | ||
| 779 | uint16_t average_soc_power; | ||
| 780 | uint16_t average_gfx_power; | ||
| 781 | uint16_t average_core_power[8]; // CPU core power on APUs | ||
| 782 | |||
| 783 | /* Average clocks */ | ||
| 784 | uint16_t average_gfxclk_frequency; | ||
| 785 | uint16_t average_socclk_frequency; | ||
| 786 | uint16_t average_uclk_frequency; | ||
| 787 | uint16_t average_fclk_frequency; | ||
| 788 | uint16_t average_vclk_frequency; | ||
| 789 | uint16_t average_dclk_frequency; | ||
| 790 | |||
| 791 | /* Current clocks */ | ||
| 792 | uint16_t current_gfxclk; | ||
| 793 | uint16_t current_socclk; | ||
| 794 | uint16_t current_uclk; | ||
| 795 | uint16_t current_fclk; | ||
| 796 | uint16_t current_vclk; | ||
| 797 | uint16_t current_dclk; | ||
| 798 | uint16_t current_coreclk[8]; // CPU core clocks | ||
| 799 | uint16_t current_l3clk[2]; | ||
| 800 | |||
| 801 | /* Throttle status (ASIC dependent) */ | ||
| 802 | uint32_t throttle_status; | ||
| 803 | |||
| 804 | /* Fans */ | ||
| 805 | uint16_t fan_pwm; | ||
| 806 | |||
| 807 | uint16_t padding[3]; | ||
| 808 | |||
| 809 | /* Throttle status (ASIC independent) */ | ||
| 810 | uint64_t indep_throttle_status; | ||
| 811 | }; | ||
| 812 | |||
| 757 | #endif | 813 | #endif |
| @@ -35,6 +35,48 @@ · 34 unmodified lines | |||
| 35 | 35 | ||
| 36 | #define SMU_DPM_USER_PROFILE_RESTORE (1 << 0) | 36 | #define SMU_DPM_USER_PROFILE_RESTORE (1 << 0) |
| 37 | 37 | ||
| 38 | // Power Throttlers | ||
| 39 | #define SMU_THROTTLER_PPT0_BIT 0 | ||
| 40 | #define SMU_THROTTLER_PPT1_BIT 1 | ||
| 41 | #define SMU_THROTTLER_PPT2_BIT 2 | ||
| 42 | #define SMU_THROTTLER_PPT3_BIT 3 | ||
| 43 | #define SMU_THROTTLER_SPL_BIT 4 | ||
| 44 | #define SMU_THROTTLER_FPPT_BIT 5 | ||
| 45 | #define SMU_THROTTLER_SPPT_BIT 6 | ||
| 46 | #define SMU_THROTTLER_SPPT_APU_BIT 7 | ||
| 47 | |||
| 48 | // Current Throttlers | ||
| 49 | #define SMU_THROTTLER_TDC_GFX_BIT 16 | ||
| 50 | #define SMU_THROTTLER_TDC_SOC_BIT 17 | ||
| 51 | #define SMU_THROTTLER_TDC_MEM_BIT 18 | ||
| 52 | #define SMU_THROTTLER_TDC_VDD_BIT 19 | ||
| 53 | #define SMU_THROTTLER_TDC_CVIP_BIT 20 | ||
| 54 | #define SMU_THROTTLER_EDC_CPU_BIT 21 | ||
| 55 | #define SMU_THROTTLER_EDC_GFX_BIT 22 | ||
| 56 | #define SMU_THROTTLER_APCC_BIT 23 | ||
| 57 | |||
| 58 | // Temperature | ||
| 59 | #define SMU_THROTTLER_TEMP_GPU_BIT 32 | ||
| 60 | #define SMU_THROTTLER_TEMP_CORE_BIT 33 | ||
| 61 | #define SMU_THROTTLER_TEMP_MEM_BIT 34 | ||
| 62 | #define SMU_THROTTLER_TEMP_EDGE_BIT 35 | ||
| 63 | #define SMU_THROTTLER_TEMP_HOTSPOT_BIT 36 | ||
| 64 | #define SMU_THROTTLER_TEMP_SOC_BIT 37 | ||
| 65 | #define SMU_THROTTLER_TEMP_VR_GFX_BIT 38 | ||
| 66 | #define SMU_THROTTLER_TEMP_VR_SOC_BIT 39 | ||
| 67 | #define SMU_THROTTLER_TEMP_VR_MEM0_BIT 40 | ||
| 68 | #define SMU_THROTTLER_TEMP_VR_MEM1_BIT 41 | ||
| 69 | #define SMU_THROTTLER_TEMP_LIQUID0_BIT 42 | ||
| 70 | #define SMU_THROTTLER_TEMP_LIQUID1_BIT 43 | ||
| 71 | #define SMU_THROTTLER_VRHOT0_BIT 44 | ||
| 72 | #define SMU_THROTTLER_VRHOT1_BIT 45 | ||
| 73 | #define SMU_THROTTLER_PROCHOT_CPU_BIT 46 | ||
| 74 | #define SMU_THROTTLER_PROCHOT_GFX_BIT 47 | ||
| 75 | |||
| 76 | // Other | ||
| 77 | #define SMU_THROTTLER_PPM_BIT 56 | ||
| 78 | #define SMU_THROTTLER_FIT_BIT 57 | ||
| 79 | |||
| 38 | struct smu_hw_power_state { | 80 | struct smu_hw_power_state { |
| 39 | unsigned int magic; | 81 | unsigned int magic; |
| 40 | }; | 82 | }; |
| @@ -723,7 +765,10 @@ struct pptable_funcs { · 682 unmodified lines | |||
| 723 | /** | 765 | /** |
| 724 | * @get_power_limit: Get the device's power limits. | 766 | * @get_power_limit: Get the device's power limits. |
| 725 | */ | 767 | */ |
| 726 | int (*get_power_limit)(struct smu_context *smu); | 768 | int (*get_power_limit)(struct smu_context *smu, |
| 769 | uint32_t *current_power_limit, | ||
| 770 | uint32_t *default_power_limit, | ||
| 771 | uint32_t *max_power_limit); | ||
| 727 | 772 | ||
| 728 | /** | 773 | /** |
| 729 | * @get_ppt_limit: Get the device's ppt limits. | 774 | * @get_ppt_limit: Get the device's ppt limits. |
| @@ -932,7 +977,9 @@ struct pptable_funcs { · 202 unmodified lines | |||
| 932 | * @disable_all_features_with_exception: Disable all features with | 977 | * @disable_all_features_with_exception: Disable all features with |
| 933 | * exception to those in &mask. | 978 | * exception to those in &mask. |
| 934 | */ | 979 | */ |
| 935 | int (*disable_all_features_with_exception)(struct smu_context *smu, enum smu_feature_mask mask); | 980 | int (*disable_all_features_with_exception)(struct smu_context *smu, |
| 981 | bool no_hw_disablement, | ||
| 982 | enum smu_feature_mask mask); | ||
| 936 | 983 | ||
| 937 | /** | 984 | /** |
| 938 | * @notify_display_change: Enable fast memory clock switching. | 985 | * @notify_display_change: Enable fast memory clock switching. |
| @@ -244,6 +244,9 @@ int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state) · 243 unmodified lines | |||
| 244 | int smu_v11_0_baco_enter(struct smu_context *smu); | 244 | int smu_v11_0_baco_enter(struct smu_context *smu); |
| 245 | int smu_v11_0_baco_exit(struct smu_context *smu); | 245 | int smu_v11_0_baco_exit(struct smu_context *smu); |
| 246 | 246 | ||
| 247 | int smu_v11_0_baco_set_armd3_sequence(struct smu_context *smu, | ||
| 248 | enum smu_v11_0_baco_seq baco_seq); | ||
| 249 | |||
| 247 | int smu_v11_0_mode1_reset(struct smu_context *smu); | 250 | int smu_v11_0_mode1_reset(struct smu_context *smu); |
| 248 | 251 | ||
| 249 | int smu_v11_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type clk_type, | 252 | int smu_v11_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type clk_type, |
| @@ -688,7 +688,10 @@ static int smu_late_init(void *handle) · 687 unmodified lines | |||
| 688 | return ret; | 688 | return ret; |
| 689 | } | 689 | } |
| 690 | 690 | ||
| 691 | ret = smu_get_asic_power_limits(smu); | 691 | ret = smu_get_asic_power_limits(smu, |
| 692 | &smu->current_power_limit, | ||
| 693 | &smu->default_power_limit, | ||
| 694 | &smu->max_power_limit); | ||
| 692 | if (ret) { | 695 | if (ret) { |
| 693 | dev_err(adev->dev, "Failed to get asic power limits!\n"); | 696 | dev_err(adev->dev, "Failed to get asic power limits!\n"); |
| 694 | return ret; | 697 | return ret; |
| @@ -1379,15 +1382,20 @@ static int smu_disable_dpms(struct smu_context *smu) · 684 unmodified lines | |||
| 1379 | if (smu->uploading_custom_pp_table && | 1382 | if (smu->uploading_custom_pp_table && |
| 1380 | (adev->asic_type >= CHIP_NAVI10) && | 1383 | (adev->asic_type >= CHIP_NAVI10) && |
| 1381 | (adev->asic_type <= CHIP_DIMGREY_CAVEFISH)) | 1384 | (adev->asic_type <= CHIP_DIMGREY_CAVEFISH)) |
| 1382 | return 0; | 1385 | return smu_disable_all_features_with_exception(smu, |
| 1386 | true, | ||
| 1387 | SMU_FEATURE_COUNT); | ||
| 1383 | 1388 | ||
| 1384 | /* | 1389 | /* |
| 1385 | * For Sienna_Cichlid, PMFW will handle the features disablement properly | 1390 | * For Sienna_Cichlid, PMFW will handle the features disablement properly |
| 1386 | * on BACO in. Driver involvement is unnecessary. | 1391 | * on BACO in. Driver involvement is unnecessary. |
| 1387 | */ | 1392 | */ |
| 1388 | if ((adev->asic_type == CHIP_SIENNA_CICHLID) && | 1393 | if (((adev->asic_type == CHIP_SIENNA_CICHLID) || |
| 1394 | ((adev->asic_type >= CHIP_NAVI10) && (adev->asic_type <= CHIP_NAVI12))) && | ||
| 1389 | use_baco) | 1395 | use_baco) |
| 1390 | return 0; | 1396 | return smu_disable_all_features_with_exception(smu, |
| 1397 | true, | ||
| 1398 | SMU_FEATURE_BACO_BIT); | ||
| 1391 | 1399 | ||
| 1392 | /* | 1400 | /* |
| 1393 | * For gpu reset, runpm and hibernation through BACO, | 1401 | * For gpu reset, runpm and hibernation through BACO, |
| @@ -1395,6 +1403,7 @@ static int smu_disable_dpms(struct smu_context *smu) · 1 unmodified line | |||
| 1395 | */ | 1403 | */ |
| 1396 | if (use_baco && smu_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT)) { | 1404 | if (use_baco && smu_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT)) { |
| 1397 | ret = smu_disable_all_features_with_exception(smu, | 1405 | ret = smu_disable_all_features_with_exception(smu, |
| 1406 | false, | ||
| 1398 | SMU_FEATURE_BACO_BIT); | 1407 | SMU_FEATURE_BACO_BIT); |
| 1399 | if (ret) | 1408 | if (ret) |
| 1400 | dev_err(adev->dev, "Failed to disable smu features except BACO.\n"); | 1409 | dev_err(adev->dev, "Failed to disable smu features except BACO.\n"); |
| @@ -2232,6 +2241,15 @@ int smu_get_power_limit(void *handle, · 831 unmodified lines | |||
| 2232 | } else { | 2241 | } else { |
| 2233 | switch (limit_level) { | 2242 | switch (limit_level) { |
| 2234 | case SMU_PPT_LIMIT_CURRENT: | 2243 | case SMU_PPT_LIMIT_CURRENT: |
| 2244 | if ((smu->adev->asic_type == CHIP_ALDEBARAN) || | ||
| 2245 | (smu->adev->asic_type == CHIP_SIENNA_CICHLID) || | ||
| 2246 | (smu->adev->asic_type == CHIP_NAVY_FLOUNDER) || | ||
| 2247 | (smu->adev->asic_type == CHIP_DIMGREY_CAVEFISH) || | ||
| 2248 | (smu->adev->asic_type == CHIP_BEIGE_GOBY)) | ||
| 2249 | ret = smu_get_asic_power_limits(smu, | ||
| 2250 | &smu->current_power_limit, | ||
| 2251 | NULL, | ||
| 2252 | NULL); | ||
| 2235 | *limit = smu->current_power_limit; | 2253 | *limit = smu->current_power_limit; |
| 2236 | break; | 2254 | break; |
| 2237 | case SMU_PPT_LIMIT_DEFAULT: | 2255 | case SMU_PPT_LIMIT_DEFAULT: |
| @@ -211,6 +211,26 @@ static const struct cmn2asic_mapping arcturus_workload_map[PP_SMC_POWER_PROFILE_ · 210 unmodified lines | |||
| 211 | WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), | 211 | WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), |
| 212 | }; | 212 | }; |
| 213 | 213 | ||
| 214 | static const uint8_t arcturus_throttler_map[] = { | ||
| 215 | [THROTTLER_TEMP_EDGE_BIT] = (SMU_THROTTLER_TEMP_EDGE_BIT), | ||
| 216 | [THROTTLER_TEMP_HOTSPOT_BIT] = (SMU_THROTTLER_TEMP_HOTSPOT_BIT), | ||
| 217 | [THROTTLER_TEMP_MEM_BIT] = (SMU_THROTTLER_TEMP_MEM_BIT), | ||
| 218 | [THROTTLER_TEMP_VR_GFX_BIT] = (SMU_THROTTLER_TEMP_VR_GFX_BIT), | ||
| 219 | [THROTTLER_TEMP_VR_MEM_BIT] = (SMU_THROTTLER_TEMP_VR_MEM0_BIT), | ||
| 220 | [THROTTLER_TEMP_VR_SOC_BIT] = (SMU_THROTTLER_TEMP_VR_SOC_BIT), | ||
| 221 | [THROTTLER_TDC_GFX_BIT] = (SMU_THROTTLER_TDC_GFX_BIT), | ||
| 222 | [THROTTLER_TDC_SOC_BIT] = (SMU_THROTTLER_TDC_SOC_BIT), | ||
| 223 | [THROTTLER_PPT0_BIT] = (SMU_THROTTLER_PPT0_BIT), | ||
| 224 | [THROTTLER_PPT1_BIT] = (SMU_THROTTLER_PPT1_BIT), | ||
| 225 | [THROTTLER_PPT2_BIT] = (SMU_THROTTLER_PPT2_BIT), | ||
| 226 | [THROTTLER_PPT3_BIT] = (SMU_THROTTLER_PPT3_BIT), | ||
| 227 | [THROTTLER_PPM_BIT] = (SMU_THROTTLER_PPM_BIT), | ||
| 228 | [THROTTLER_FIT_BIT] = (SMU_THROTTLER_FIT_BIT), | ||
| 229 | [THROTTLER_APCC_BIT] = (SMU_THROTTLER_APCC_BIT), | ||
| 230 | [THROTTLER_VRHOT0_BIT] = (SMU_THROTTLER_VRHOT0_BIT), | ||
| 231 | [THROTTLER_VRHOT1_BIT] = (SMU_THROTTLER_VRHOT1_BIT), | ||
| 232 | }; | ||
| 233 | |||
| 214 | static int arcturus_tables_init(struct smu_context *smu) | 234 | static int arcturus_tables_init(struct smu_context *smu) |
| 215 | { | 235 | { |
| 216 | struct smu_table_context *smu_table = &smu->smu_table; | 236 | struct smu_table_context *smu_table = &smu->smu_table; |
| @@ -237,7 +257,7 @@ static int arcturus_tables_init(struct smu_context *smu) · 20 unmodified lines | |||
| 237 | return -ENOMEM; | 257 | return -ENOMEM; |
| 238 | smu_table->metrics_time = 0; | 258 | smu_table->metrics_time = 0; |
| 239 | 259 | ||
| 240 | smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_1); | 260 | smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_3); |
| 241 | smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); | 261 | smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); |
| 242 | if (!smu_table->gpu_metrics_table) { | 262 | if (!smu_table->gpu_metrics_table) { |
| 243 | kfree(smu_table->metrics_table); | 263 | kfree(smu_table->metrics_table); |
| @@ -1174,7 +1194,10 @@ static int arcturus_get_fan_parameters(struct smu_context *smu) · 930 unmodified lines | |||
| 1174 | return 0; | 1194 | return 0; |
| 1175 | } | 1195 | } |
| 1176 | 1196 | ||
| 1177 | static int arcturus_get_power_limit(struct smu_context *smu) | 1197 | static int arcturus_get_power_limit(struct smu_context *smu, |
| 1198 | uint32_t *current_power_limit, | ||
| 1199 | uint32_t *default_power_limit, | ||
| 1200 | uint32_t *max_power_limit) | ||
| 1178 | { | 1201 | { |
| 1179 | struct smu_11_0_powerplay_table *powerplay_table = | 1202 | struct smu_11_0_powerplay_table *powerplay_table = |
| 1180 | (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table; | 1203 | (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table; |
| @@ -1190,17 +1213,24 @@ static int arcturus_get_power_limit(struct smu_context *smu) · 9 unmodified lines | |||
| 1190 | power_limit = | 1213 | power_limit = |
| 1191 | pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; | 1214 | pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; |
| 1192 | } | 1215 | } |
| 1193 | smu->current_power_limit = smu->default_power_limit = power_limit; | ||
| 1194 | 1216 | ||
| 1195 | if (smu->od_enabled) { | 1217 | if (current_power_limit) |
| 1196 | od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]); | 1218 | *current_power_limit = power_limit; |
| 1219 | if (default_power_limit) | ||
| 1220 | *default_power_limit = power_limit; | ||
| 1221 | |||
| 1222 | if (max_power_limit) { | ||
| 1223 | if (smu->od_enabled) { | ||
| 1224 | od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]); | ||
| 1197 | 1225 | ||
| 1198 | dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit); | 1226 | dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit); |
| 1227 | |||
| 1228 | power_limit *= (100 + od_percent); | ||
| 1229 | power_limit /= 100; | ||
| 1230 | } | ||
| 1199 | 1231 | ||
| 1200 | power_limit *= (100 + od_percent); | 1232 | *max_power_limit = power_limit; |
| 1201 | power_limit /= 100; | ||
| 1202 | } | 1233 | } |
| 1203 | smu->max_power_limit = power_limit; | ||
| 1204 | 1234 | ||
| 1205 | return 0; | 1235 | return 0; |
| 1206 | } | 1236 | } |
| @@ -2278,8 +2308,8 @@ static ssize_t arcturus_get_gpu_metrics(struct smu_context *smu, · 1071 unmodified lines | |||
| 2278 | void **table) | 2308 | void **table) |
| 2279 | { | 2309 | { |
| 2280 | struct smu_table_context *smu_table = &smu->smu_table; | 2310 | struct smu_table_context *smu_table = &smu->smu_table; |
| 2281 | struct gpu_metrics_v1_1 *gpu_metrics = | 2311 | struct gpu_metrics_v1_3 *gpu_metrics = |
| 2282 | (struct gpu_metrics_v1_1 *)smu_table->gpu_metrics_table; | 2312 | (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table; |
| 2283 | SmuMetrics_t metrics; | 2313 | SmuMetrics_t metrics; |
| 2284 | int ret = 0; | 2314 | int ret = 0; |
| 2285 | 2315 | ||
| @@ -2289,7 +2319,7 @@ static ssize_t arcturus_get_gpu_metrics(struct smu_context *smu, · 3 unmodified lines | |||
| 2289 | if (ret) | 2319 | if (ret) |
| 2290 | return ret; | 2320 | return ret; |
| 2291 | 2321 | ||
| 2292 | smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 1); | 2322 | smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3); |
| 2293 | 2323 | ||
| 2294 | gpu_metrics->temperature_edge = metrics.TemperatureEdge; | 2324 | gpu_metrics->temperature_edge = metrics.TemperatureEdge; |
| 2295 | gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; | 2325 | gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; |
| @@ -2318,6 +2348,9 @@ static ssize_t arcturus_get_gpu_metrics(struct smu_context *smu, · 22 unmodified lines | |||
| 2318 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; | 2348 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; |
| 2319 | 2349 | ||
| 2320 | gpu_metrics->throttle_status = metrics.ThrottlerStatus; | 2350 | gpu_metrics->throttle_status = metrics.ThrottlerStatus; |
| 2351 | gpu_metrics->indep_throttle_status = | ||
| 2352 | smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus, | ||
| 2353 | arcturus_throttler_map); | ||
| 2321 | 2354 | ||
| 2322 | gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; | 2355 | gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; |
| 2323 | 2356 | ||
| @@ -2330,7 +2363,7 @@ static ssize_t arcturus_get_gpu_metrics(struct smu_context *smu, · 6 unmodified lines | |||
| 2330 | 2363 | ||
| 2331 | *table = (void *)gpu_metrics; | 2364 | *table = (void *)gpu_metrics; |
| 2332 | 2365 | ||
| 2333 | return sizeof(struct gpu_metrics_v1_1); | 2366 | return sizeof(struct gpu_metrics_v1_3); |
| 2334 | } | 2367 | } |
| 2335 | 2368 | ||
| 2336 | static const struct pptable_funcs arcturus_ppt_funcs = { | 2369 | static const struct pptable_funcs arcturus_ppt_funcs = { |
| @@ -238,6 +238,28 @@ static struct cmn2asic_mapping navi10_workload_map[PP_SMC_POWER_PROFILE_COUNT] = · 237 unmodified lines | |||
| 238 | WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), | 238 | WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), |
| 239 | }; | 239 | }; |
| 240 | 240 | ||
| 241 | static const uint8_t navi1x_throttler_map[] = { | ||
| 242 | [THROTTLER_TEMP_EDGE_BIT] = (SMU_THROTTLER_TEMP_EDGE_BIT), | ||
| 243 | [THROTTLER_TEMP_HOTSPOT_BIT] = (SMU_THROTTLER_TEMP_HOTSPOT_BIT), | ||
| 244 | [THROTTLER_TEMP_MEM_BIT] = (SMU_THROTTLER_TEMP_MEM_BIT), | ||
| 245 | [THROTTLER_TEMP_VR_GFX_BIT] = (SMU_THROTTLER_TEMP_VR_GFX_BIT), | ||
| 246 | [THROTTLER_TEMP_VR_MEM0_BIT] = (SMU_THROTTLER_TEMP_VR_MEM0_BIT), | ||
| 247 | [THROTTLER_TEMP_VR_MEM1_BIT] = (SMU_THROTTLER_TEMP_VR_MEM1_BIT), | ||
| 248 | [THROTTLER_TEMP_VR_SOC_BIT] = (SMU_THROTTLER_TEMP_VR_SOC_BIT), | ||
| 249 | [THROTTLER_TEMP_LIQUID0_BIT] = (SMU_THROTTLER_TEMP_LIQUID0_BIT), | ||
| 250 | [THROTTLER_TEMP_LIQUID1_BIT] = (SMU_THROTTLER_TEMP_LIQUID1_BIT), | ||
| 251 | [THROTTLER_TDC_GFX_BIT] = (SMU_THROTTLER_TDC_GFX_BIT), | ||
| 252 | [THROTTLER_TDC_SOC_BIT] = (SMU_THROTTLER_TDC_SOC_BIT), | ||
| 253 | [THROTTLER_PPT0_BIT] = (SMU_THROTTLER_PPT0_BIT), | ||
| 254 | [THROTTLER_PPT1_BIT] = (SMU_THROTTLER_PPT1_BIT), | ||
| 255 | [THROTTLER_PPT2_BIT] = (SMU_THROTTLER_PPT2_BIT), | ||
| 256 | [THROTTLER_PPT3_BIT] = (SMU_THROTTLER_PPT3_BIT), | ||
| 257 | [THROTTLER_FIT_BIT] = (SMU_THROTTLER_FIT_BIT), | ||
| 258 | [THROTTLER_PPM_BIT] = (SMU_THROTTLER_PPM_BIT), | ||
| 259 | [THROTTLER_APCC_BIT] = (SMU_THROTTLER_APCC_BIT), | ||
| 260 | }; | ||
| 261 | |||
| 262 | |||
| 241 | static bool is_asic_secure(struct smu_context *smu) | 263 | static bool is_asic_secure(struct smu_context *smu) |
| 242 | { | 264 | { |
| 243 | struct amdgpu_device *adev = smu->adev; | 265 | struct amdgpu_device *adev = smu->adev; |
| @@ -446,30 +468,6 @@ static int navi10_store_powerplay_table(struct smu_context *smu) · 202 unmodified lines | |||
| 446 | return 0; | 468 | return 0; |
| 447 | } | 469 | } |
| 448 | 470 | ||
| 449 | static int navi10_set_mp1_state(struct smu_context *smu, | ||
| 450 | enum pp_mp1_state mp1_state) | ||
| 451 | { | ||
| 452 | struct amdgpu_device *adev = smu->adev; | ||
| 453 | uint32_t mp1_fw_flags; | ||
| 454 | int ret = 0; | ||
| 455 | |||
| 456 | ret = smu_cmn_set_mp1_state(smu, mp1_state); | ||
| 457 | if (ret) | ||
| 458 | return ret; | ||
| 459 | |||
| 460 | if (mp1_state == PP_MP1_STATE_UNLOAD) { | ||
| 461 | mp1_fw_flags = RREG32_PCIE(MP1_Public | | ||
| 462 | (smnMP1_FIRMWARE_FLAGS & 0xffffffff)); | ||
| 463 | |||
| 464 | mp1_fw_flags &= ~MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK; | ||
| 465 | |||
| 466 | WREG32_PCIE(MP1_Public | | ||
| 467 | (smnMP1_FIRMWARE_FLAGS & 0xffffffff), mp1_fw_flags); | ||
| 468 | } | ||
| 469 | |||
| 470 | return 0; | ||
| 471 | } | ||
| 472 | |||
| 473 | static int navi10_setup_pptable(struct smu_context *smu) | 471 | static int navi10_setup_pptable(struct smu_context *smu) |
| 474 | { | 472 | { |
| 475 | int ret = 0; | 473 | int ret = 0; |
| @@ -2138,7 +2136,10 @@ static int navi10_display_disable_memory_clock_switch(struct smu_context *smu, · 1662 unmodified lines | |||
| 2138 | return ret; | 2136 | return ret; |
| 2139 | } | 2137 | } |
| 2140 | 2138 | ||
| 2141 | static int navi10_get_power_limit(struct smu_context *smu) | 2139 | static int navi10_get_power_limit(struct smu_context *smu, |
| 2140 | uint32_t *current_power_limit, | ||
| 2141 | uint32_t *default_power_limit, | ||
| 2142 | uint32_t *max_power_limit) | ||
| 2142 | { | 2143 | { |
| 2143 | struct smu_11_0_powerplay_table *powerplay_table = | 2144 | struct smu_11_0_powerplay_table *powerplay_table = |
| 2144 | (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table; | 2145 | (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table; |
| @@ -2155,18 +2156,25 @@ static int navi10_get_power_limit(struct smu_context *smu) · 10 unmodified lines | |||
| 2155 | power_limit = | 2156 | power_limit = |
| 2156 | pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; | 2157 | pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; |
| 2157 | } | 2158 | } |
| 2158 | smu->current_power_limit = smu->default_power_limit = power_limit; | ||
| 2159 | 2159 | ||
| 2160 | if (smu->od_enabled && | 2160 | if (current_power_limit) |
| 2161 | navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) { | 2161 | *current_power_limit = power_limit; |
| 2162 | od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]); | 2162 | if (default_power_limit) |
| 2163 | *default_power_limit = power_limit; | ||
| 2163 | 2164 | ||
| 2164 | dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit); | 2165 | if (max_power_limit) { |
| 2166 | if (smu->od_enabled && | ||
| 2167 | navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) { | ||
| 2168 | od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]); | ||
| 2165 | 2169 | ||
| 2166 | power_limit *= (100 + od_percent); | 2170 | dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit); |
| 2167 | power_limit /= 100; | 2171 | |
| 2172 | power_limit *= (100 + od_percent); | ||
| 2173 | power_limit /= 100; | ||
| 2174 | } | ||
| 2175 | |||
| 2176 | *max_power_limit = power_limit; | ||
| 2168 | } | 2177 | } |
| 2169 | smu->max_power_limit = power_limit; | ||
| 2170 | 2178 | ||
| 2171 | return 0; | 2179 | return 0; |
| 2172 | } | 2180 | } |
| @@ -2257,6 +2265,29 @@ static int navi10_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu, · 84 unmodified lines | |||
| 2257 | return 0; | 2265 | return 0; |
| 2258 | } | 2266 | } |
| 2259 | 2267 | ||
| 2268 | static int navi10_baco_enter(struct smu_context *smu) | ||
| 2269 | { | ||
| 2270 | struct amdgpu_device *adev = smu->adev; | ||
| 2271 | |||
| 2272 | if (adev->in_runpm) | ||
| 2273 | return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_BACO); | ||
| 2274 | else | ||
| 2275 | return smu_v11_0_baco_enter(smu); | ||
| 2276 | } | ||
| 2277 | |||
| 2278 | static int navi10_baco_exit(struct smu_context *smu) | ||
| 2279 | { | ||
| 2280 | struct amdgpu_device *adev = smu->adev; | ||
| 2281 | |||
| 2282 | if (adev->in_runpm) { | ||
| 2283 | /* Wait for PMFW handling for the Dstate change */ | ||
| 2284 | msleep(10); | ||
| 2285 | return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS); | ||
| 2286 | } else { | ||
| 2287 | return smu_v11_0_baco_exit(smu); | ||
| 2288 | } | ||
| 2289 | } | ||
| 2290 | |||
| 2260 | static int navi10_set_default_od_settings(struct smu_context *smu) | 2291 | static int navi10_set_default_od_settings(struct smu_context *smu) |
| 2261 | { | 2292 | { |
| 2262 | OverDriveTable_t *od_table = | 2293 | OverDriveTable_t *od_table = |
| @@ -2676,6 +2707,9 @@ static ssize_t navi10_get_legacy_gpu_metrics(struct smu_context *smu, · 413 unmodified lines | |||
| 2676 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; | 2707 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; |
| 2677 | 2708 | ||
| 2678 | gpu_metrics->throttle_status = metrics.ThrottlerStatus; | 2709 | gpu_metrics->throttle_status = metrics.ThrottlerStatus; |
| 2710 | gpu_metrics->indep_throttle_status = | ||
| 2711 | smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus, | ||
| 2712 | navi1x_throttler_map); | ||
| 2679 | 2713 | ||
| 2680 | gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; | 2714 | gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; |
| 2681 | 2715 | ||
| @@ -2753,6 +2787,9 @@ static ssize_t navi10_get_gpu_metrics(struct smu_context *smu, · 71 unmodified lines | |||
| 2753 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; | 2787 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; |
| 2754 | 2788 | ||
| 2755 | gpu_metrics->throttle_status = metrics.ThrottlerStatus; | 2789 | gpu_metrics->throttle_status = metrics.ThrottlerStatus; |
| 2790 | gpu_metrics->indep_throttle_status = | ||
| 2791 | smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus, | ||
| 2792 | navi1x_throttler_map); | ||
| 2756 | 2793 | ||
| 2757 | gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; | 2794 | gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; |
| 2758 | 2795 | ||
| @@ -2829,6 +2866,9 @@ static ssize_t navi12_get_legacy_gpu_metrics(struct smu_context *smu, · 70 unmodified lines | |||
| 2829 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; | 2866 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; |
| 2830 | 2867 | ||
| 2831 | gpu_metrics->throttle_status = metrics.ThrottlerStatus; | 2868 | gpu_metrics->throttle_status = metrics.ThrottlerStatus; |
| 2869 | gpu_metrics->indep_throttle_status = | ||
| 2870 | smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus, | ||
| 2871 | navi1x_throttler_map); | ||
| 2832 | 2872 | ||
| 2833 | gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; | 2873 | gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; |
| 2834 | 2874 | ||
| @@ -2911,6 +2951,9 @@ static ssize_t navi12_get_gpu_metrics(struct smu_context *smu, · 76 unmodified lines | |||
| 2911 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; | 2951 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; |
| 2912 | 2952 | ||
| 2913 | gpu_metrics->throttle_status = metrics.ThrottlerStatus; | 2953 | gpu_metrics->throttle_status = metrics.ThrottlerStatus; |
| 2954 | gpu_metrics->indep_throttle_status = | ||
| 2955 | smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus, | ||
| 2956 | navi1x_throttler_map); | ||
| 2914 | 2957 | ||
| 2915 | gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; | 2958 | gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; |
| 2916 | 2959 | ||
| @@ -3095,8 +3138,8 @@ static const struct pptable_funcs navi10_ppt_funcs = { · 178 unmodified lines | |||
| 3095 | .baco_is_support = smu_v11_0_baco_is_support, | 3138 | .baco_is_support = smu_v11_0_baco_is_support, |
| 3096 | .baco_get_state = smu_v11_0_baco_get_state, | 3139 | .baco_get_state = smu_v11_0_baco_get_state, |
| 3097 | .baco_set_state = smu_v11_0_baco_set_state, | 3140 | .baco_set_state = smu_v11_0_baco_set_state, |
| 3098 | .baco_enter = smu_v11_0_baco_enter, | 3141 | .baco_enter = navi10_baco_enter, |
| 3099 | .baco_exit = smu_v11_0_baco_exit, | 3142 | .baco_exit = navi10_baco_exit, |
| 3100 | .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq, | 3143 | .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq, |
| 3101 | .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, | 3144 | .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, |
| 3102 | .set_default_od_settings = navi10_set_default_od_settings, | 3145 | .set_default_od_settings = navi10_set_default_od_settings, |
| @@ -3112,7 +3155,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { · 9 unmodified lines | |||
| 3112 | .get_fan_parameters = navi10_get_fan_parameters, | 3155 | .get_fan_parameters = navi10_get_fan_parameters, |
| 3113 | .post_init = navi10_post_smu_init, | 3156 | .post_init = navi10_post_smu_init, |
| 3114 | .interrupt_work = smu_v11_0_interrupt_work, | 3157 | .interrupt_work = smu_v11_0_interrupt_work, |
| 3115 | .set_mp1_state = navi10_set_mp1_state, | 3158 | .set_mp1_state = smu_cmn_set_mp1_state, |
| 3116 | }; | 3159 | }; |
| 3117 | 3160 | ||
| 3118 | void navi10_set_ppt_funcs(struct smu_context *smu) | 3161 | void navi10_set_ppt_funcs(struct smu_context *smu) |
| @@ -239,6 +239,27 @@ static struct cmn2asic_mapping sienna_cichlid_workload_map[PP_SMC_POWER_PROFILE_ · 238 unmodified lines | |||
| 239 | WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), | 239 | WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), |
| 240 | }; | 240 | }; |
| 241 | 241 | ||
| 242 | static const uint8_t sienna_cichlid_throttler_map[] = { | ||
| 243 | [THROTTLER_TEMP_EDGE_BIT] = (SMU_THROTTLER_TEMP_EDGE_BIT), | ||
| 244 | [THROTTLER_TEMP_HOTSPOT_BIT] = (SMU_THROTTLER_TEMP_HOTSPOT_BIT), | ||
| 245 | [THROTTLER_TEMP_MEM_BIT] = (SMU_THROTTLER_TEMP_MEM_BIT), | ||
| 246 | [THROTTLER_TEMP_VR_GFX_BIT] = (SMU_THROTTLER_TEMP_VR_GFX_BIT), | ||
| 247 | [THROTTLER_TEMP_VR_MEM0_BIT] = (SMU_THROTTLER_TEMP_VR_MEM0_BIT), | ||
| 248 | [THROTTLER_TEMP_VR_MEM1_BIT] = (SMU_THROTTLER_TEMP_VR_MEM1_BIT), | ||
| 249 | [THROTTLER_TEMP_VR_SOC_BIT] = (SMU_THROTTLER_TEMP_VR_SOC_BIT), | ||
| 250 | [THROTTLER_TEMP_LIQUID0_BIT] = (SMU_THROTTLER_TEMP_LIQUID0_BIT), | ||
| 251 | [THROTTLER_TEMP_LIQUID1_BIT] = (SMU_THROTTLER_TEMP_LIQUID1_BIT), | ||
| 252 | [THROTTLER_TDC_GFX_BIT] = (SMU_THROTTLER_TDC_GFX_BIT), | ||
| 253 | [THROTTLER_TDC_SOC_BIT] = (SMU_THROTTLER_TDC_SOC_BIT), | ||
| 254 | [THROTTLER_PPT0_BIT] = (SMU_THROTTLER_PPT0_BIT), | ||
| 255 | [THROTTLER_PPT1_BIT] = (SMU_THROTTLER_PPT1_BIT), | ||
| 256 | [THROTTLER_PPT2_BIT] = (SMU_THROTTLER_PPT2_BIT), | ||
| 257 | [THROTTLER_PPT3_BIT] = (SMU_THROTTLER_PPT3_BIT), | ||
| 258 | [THROTTLER_FIT_BIT] = (SMU_THROTTLER_FIT_BIT), | ||
| 259 | [THROTTLER_PPM_BIT] = (SMU_THROTTLER_PPM_BIT), | ||
| 260 | [THROTTLER_APCC_BIT] = (SMU_THROTTLER_APCC_BIT), | ||
| 261 | }; | ||
| 262 | |||
| 242 | static int | 263 | static int |
| 243 | sienna_cichlid_get_allowed_feature_mask(struct smu_context *smu, | 264 | sienna_cichlid_get_allowed_feature_mask(struct smu_context *smu, |
| 244 | uint32_t *feature_mask, uint32_t num) | 265 | uint32_t *feature_mask, uint32_t num) |
| @@ -449,7 +470,7 @@ static int sienna_cichlid_tables_init(struct smu_context *smu) · 204 unmodified lines | |||
| 449 | goto err0_out; | 470 | goto err0_out; |
| 450 | smu_table->metrics_time = 0; | 471 | smu_table->metrics_time = 0; |
| 451 | 472 | ||
| 452 | smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_1); | 473 | smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_3); |
| 453 | smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); | 474 | smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); |
| 454 | if (!smu_table->gpu_metrics_table) | 475 | if (!smu_table->gpu_metrics_table) |
| 455 | goto err1_out; | 476 | goto err1_out; |
| @@ -1770,7 +1791,10 @@ static int sienna_cichlid_display_disable_memory_clock_switch(struct smu_context · 1314 unmodified lines | |||
| 1770 | return ret; | 1791 | return ret; |
| 1771 | } | 1792 | } |
| 1772 | 1793 | ||
| 1773 | static int sienna_cichlid_get_power_limit(struct smu_context *smu) | 1794 | static int sienna_cichlid_get_power_limit(struct smu_context *smu, |
| 1795 | uint32_t *current_power_limit, | ||
| 1796 | uint32_t *default_power_limit, | ||
| 1797 | uint32_t *max_power_limit) | ||
| 1774 | { | 1798 | { |
| 1775 | struct smu_11_0_7_powerplay_table *powerplay_table = | 1799 | struct smu_11_0_7_powerplay_table *powerplay_table = |
| 1776 | (struct smu_11_0_7_powerplay_table *)smu->smu_table.power_play_table; | 1800 | (struct smu_11_0_7_powerplay_table *)smu->smu_table.power_play_table; |
| @@ -1783,17 +1807,23 @@ static int sienna_cichlid_get_power_limit(struct smu_context *smu) · 6 unmodified lines | |||
| 1783 | power_limit = | 1807 | power_limit = |
| 1784 | table_member[PPT_THROTTLER_PPT0]; | 1808 | table_member[PPT_THROTTLER_PPT0]; |
| 1785 | } | 1809 | } |
| 1786 | smu->current_power_limit = smu->default_power_limit = power_limit; | ||
| 1787 | 1810 | ||
| 1788 | if (smu->od_enabled) { | 1811 | if (current_power_limit) |
| 1789 | od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]); | 1812 | *current_power_limit = power_limit; |
| 1813 | if (default_power_limit) | ||
| 1814 | *default_power_limit = power_limit; | ||
| 1815 | |||
| 1816 | if (max_power_limit) { | ||
| 1817 | if (smu->od_enabled) { | ||
| 1818 | od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]); | ||
| 1790 | 1819 | ||
| 1791 | dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit); | 1820 | dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit); |
| 1792 | 1821 | ||
| 1793 | power_limit *= (100 + od_percent); | 1822 | power_limit *= (100 + od_percent); |
| 1794 | power_limit /= 100; | 1823 | power_limit /= 100; |
| 1824 | } | ||
| 1825 | *max_power_limit = power_limit; | ||
| 1795 | } | 1826 | } |
| 1796 | smu->max_power_limit = power_limit; | ||
| 1797 | 1827 | ||
| 1798 | return 0; | 1828 | return 0; |
| 1799 | } | 1829 | } |
| @@ -2100,6 +2130,29 @@ static int sienna_cichlid_run_btc(struct smu_context *smu) · 300 unmodified lines | |||
| 2100 | return smu_cmn_send_smc_msg(smu, SMU_MSG_RunDcBtc, NULL); | 2130 | return smu_cmn_send_smc_msg(smu, SMU_MSG_RunDcBtc, NULL); |
| 2101 | } | 2131 | } |
| 2102 | 2132 | ||
| 2133 | static int sienna_cichlid_baco_enter(struct smu_context *smu) | ||
| 2134 | { | ||
| 2135 | struct amdgpu_device *adev = smu->adev; | ||
| 2136 | |||
| 2137 | if (adev->in_runpm) | ||
| 2138 | return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_BACO); | ||
| 2139 | else | ||
| 2140 | return smu_v11_0_baco_enter(smu); | ||
| 2141 | } | ||
| 2142 | |||
| 2143 | static int sienna_cichlid_baco_exit(struct smu_context *smu) | ||
| 2144 | { | ||
| 2145 | struct amdgpu_device *adev = smu->adev; | ||
| 2146 | |||
| 2147 | if (adev->in_runpm) { | ||
| 2148 | /* Wait for PMFW handling for the Dstate change */ | ||
| 2149 | msleep(10); | ||
| 2150 | return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS); | ||
| 2151 | } else { | ||
| 2152 | return smu_v11_0_baco_exit(smu); | ||
| 2153 | } | ||
| 2154 | } | ||
| 2155 | |||
| 2103 | static bool sienna_cichlid_is_mode1_reset_supported(struct smu_context *smu) | 2156 | static bool sienna_cichlid_is_mode1_reset_supported(struct smu_context *smu) |
| 2104 | { | 2157 | { |
| 2105 | struct amdgpu_device *adev = smu->adev; | 2158 | struct amdgpu_device *adev = smu->adev; |
| @@ -3620,8 +3673,8 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, · 1514 unmodified lines | |||
| 3620 | void **table) | 3673 | void **table) |
| 3621 | { | 3674 | { |
| 3622 | struct smu_table_context *smu_table = &smu->smu_table; | 3675 | struct smu_table_context *smu_table = &smu->smu_table; |
| 3623 | struct gpu_metrics_v1_1 *gpu_metrics = | 3676 | struct gpu_metrics_v1_3 *gpu_metrics = |
| 3624 | (struct gpu_metrics_v1_1 *)smu_table->gpu_metrics_table; | 3677 | (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table; |
| 3625 | SmuMetricsExternal_t metrics_external; | 3678 | SmuMetricsExternal_t metrics_external; |
| 3626 | SmuMetrics_t *metrics = | 3679 | SmuMetrics_t *metrics = |
| 3627 | &(metrics_external.SmuMetrics); | 3680 | &(metrics_external.SmuMetrics); |
| @@ -3635,7 +3688,7 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, · 7 unmodified lines | |||
| 3635 | if (ret) | 3688 | if (ret) |
| 3636 | return ret; | 3689 | return ret; |
| 3637 | 3690 | ||
| 3638 | smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 1); | 3691 | smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3); |
| 3639 | 3692 | ||
| 3640 | gpu_metrics->temperature_edge = metrics->TemperatureEdge; | 3693 | gpu_metrics->temperature_edge = metrics->TemperatureEdge; |
| 3641 | gpu_metrics->temperature_hotspot = metrics->TemperatureHotspot; | 3694 | gpu_metrics->temperature_hotspot = metrics->TemperatureHotspot; |
| @@ -3670,6 +3723,9 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, · 28 unmodified lines | |||
| 3670 | gpu_metrics->current_dclk1 = metrics->CurrClock[PPCLK_DCLK_1]; | 3723 | gpu_metrics->current_dclk1 = metrics->CurrClock[PPCLK_DCLK_1]; |
| 3671 | 3724 | ||
| 3672 | gpu_metrics->throttle_status = metrics->ThrottlerStatus; | 3725 | gpu_metrics->throttle_status = metrics->ThrottlerStatus; |
| 3726 | gpu_metrics->indep_throttle_status = | ||
| 3727 | smu_cmn_get_indep_throttler_status(metrics->ThrottlerStatus, | ||
| 3728 | sienna_cichlid_throttler_map); | ||
| 3673 | 3729 | ||
| 3674 | gpu_metrics->current_fan_speed = metrics->CurrFanSpeed; | 3730 | gpu_metrics->current_fan_speed = metrics->CurrFanSpeed; |
| 3675 | 3731 | ||
| @@ -3692,7 +3748,7 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, · 16 unmodified lines | |||
| 3692 | 3748 | ||
| 3693 | *table = (void *)gpu_metrics; | 3749 | *table = (void *)gpu_metrics; |
| 3694 | 3750 | ||
| 3695 | return sizeof(struct gpu_metrics_v1_1); | 3751 | return sizeof(struct gpu_metrics_v1_3); |
| 3696 | } | 3752 | } |
| 3697 | 3753 | ||
| 3698 | static int sienna_cichlid_enable_mgpu_fan_boost(struct smu_context *smu) | 3754 | static int sienna_cichlid_enable_mgpu_fan_boost(struct smu_context *smu) |
| @@ -3875,8 +3931,8 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { · 176 unmodified lines | |||
| 3875 | .baco_is_support = smu_v11_0_baco_is_support, | 3931 | .baco_is_support = smu_v11_0_baco_is_support, |
| 3876 | .baco_get_state = smu_v11_0_baco_get_state, | 3932 | .baco_get_state = smu_v11_0_baco_get_state, |
| 3877 | .baco_set_state = smu_v11_0_baco_set_state, | 3933 | .baco_set_state = smu_v11_0_baco_set_state, |
| 3878 | .baco_enter = smu_v11_0_baco_enter, | 3934 | .baco_enter = sienna_cichlid_baco_enter, |
| 3879 | .baco_exit = smu_v11_0_baco_exit, | 3935 | .baco_exit = sienna_cichlid_baco_exit, |
| 3880 | .mode1_reset_is_support = sienna_cichlid_is_mode1_reset_supported, | 3936 | .mode1_reset_is_support = sienna_cichlid_is_mode1_reset_supported, |
| 3881 | .mode1_reset = smu_v11_0_mode1_reset, | 3937 | .mode1_reset = smu_v11_0_mode1_reset, |
| 3882 | .get_dpm_ultimate_freq = sienna_cichlid_get_dpm_ultimate_freq, | 3938 | .get_dpm_ultimate_freq = sienna_cichlid_get_dpm_ultimate_freq, |
| @@ -1474,7 +1474,8 @@ int smu_v11_0_set_azalia_d3_pme(struct smu_context *smu) · 1473 unmodified lines | |||
| 1474 | return smu_cmn_send_smc_msg(smu, SMU_MSG_BacoAudioD3PME, NULL); | 1474 | return smu_cmn_send_smc_msg(smu, SMU_MSG_BacoAudioD3PME, NULL); |
| 1475 | } | 1475 | } |
| 1476 | 1476 | ||
| 1477 | static int smu_v11_0_baco_set_armd3_sequence(struct smu_context *smu, enum smu_v11_0_baco_seq baco_seq) | 1477 | int smu_v11_0_baco_set_armd3_sequence(struct smu_context *smu, |
| 1478 | enum smu_v11_0_baco_seq baco_seq) | ||
| 1478 | { | 1479 | { |
| 1479 | return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ArmD3, baco_seq, NULL); | 1480 | return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ArmD3, baco_seq, NULL); |
| 1480 | } | 1481 | } |
| @@ -1578,16 +1579,8 @@ out: · 97 unmodified lines | |||
| 1578 | 1579 | ||
| 1579 | int smu_v11_0_baco_enter(struct smu_context *smu) | 1580 | int smu_v11_0_baco_enter(struct smu_context *smu) |
| 1580 | { | 1581 | { |
| 1581 | struct amdgpu_device *adev = smu->adev; | ||
| 1582 | int ret = 0; | 1582 | int ret = 0; |
| 1583 | 1583 | ||
| 1584 | /* Arcturus does not need this audio workaround */ | ||
| 1585 | if (adev->asic_type != CHIP_ARCTURUS) { | ||
| 1586 | ret = smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_BACO); | ||
| 1587 | if (ret) | ||
| 1588 | return ret; | ||
| 1589 | } | ||
| 1590 | |||
| 1591 | ret = smu_v11_0_baco_set_state(smu, SMU_BACO_STATE_ENTER); | 1584 | ret = smu_v11_0_baco_set_state(smu, SMU_BACO_STATE_ENTER); |
| 1592 | if (ret) | 1585 | if (ret) |
| 1593 | return ret; | 1586 | return ret; |
| @@ -190,6 +190,20 @@ static struct cmn2asic_mapping vangogh_workload_map[PP_SMC_POWER_PROFILE_COUNT] · 189 unmodified lines | |||
| 190 | WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), | 190 | WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), |
| 191 | }; | 191 | }; |
| 192 | 192 | ||
| 193 | static const uint8_t vangogh_throttler_map[] = { | ||
| 194 | [THROTTLER_STATUS_BIT_SPL] = (SMU_THROTTLER_SPL_BIT), | ||
| 195 | [THROTTLER_STATUS_BIT_FPPT] = (SMU_THROTTLER_FPPT_BIT), | ||
| 196 | [THROTTLER_STATUS_BIT_SPPT] = (SMU_THROTTLER_SPPT_BIT), | ||
| 197 | [THROTTLER_STATUS_BIT_SPPT_APU] = (SMU_THROTTLER_SPPT_APU_BIT), | ||
| 198 | [THROTTLER_STATUS_BIT_THM_CORE] = (SMU_THROTTLER_TEMP_CORE_BIT), | ||
| 199 | [THROTTLER_STATUS_BIT_THM_GFX] = (SMU_THROTTLER_TEMP_GPU_BIT), | ||
| 200 | [THROTTLER_STATUS_BIT_THM_SOC] = (SMU_THROTTLER_TEMP_SOC_BIT), | ||
| 201 | [THROTTLER_STATUS_BIT_TDC_VDD] = (SMU_THROTTLER_TDC_VDD_BIT), | ||
| 202 | [THROTTLER_STATUS_BIT_TDC_SOC] = (SMU_THROTTLER_TDC_SOC_BIT), | ||
| 203 | [THROTTLER_STATUS_BIT_TDC_GFX] = (SMU_THROTTLER_TDC_GFX_BIT), | ||
| 204 | [THROTTLER_STATUS_BIT_TDC_CVIP] = (SMU_THROTTLER_TDC_CVIP_BIT), | ||
| 205 | }; | ||
| 206 | |||
| 193 | static int vangogh_tables_init(struct smu_context *smu) | 207 | static int vangogh_tables_init(struct smu_context *smu) |
| 194 | { | 208 | { |
| 195 | struct smu_table_context *smu_table = &smu->smu_table; | 209 | struct smu_table_context *smu_table = &smu->smu_table; |
| @@ -226,7 +240,7 @@ static int vangogh_tables_init(struct smu_context *smu) · 30 unmodified lines | |||
| 226 | goto err0_out; | 240 | goto err0_out; |
| 227 | smu_table->metrics_time = 0; | 241 | smu_table->metrics_time = 0; |
| 228 | 242 | ||
| 229 | smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_1); | 243 | smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_2); |
| 230 | smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); | 244 | smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); |
| 231 | if (!smu_table->gpu_metrics_table) | 245 | if (!smu_table->gpu_metrics_table) |
| 232 | goto err1_out; | 246 | goto err1_out; |
| @@ -1632,8 +1646,8 @@ static ssize_t vangogh_get_legacy_gpu_metrics(struct smu_context *smu, · 1399 unmodified lines | |||
| 1632 | void **table) | 1646 | void **table) |
| 1633 | { | 1647 | { |
| 1634 | struct smu_table_context *smu_table = &smu->smu_table; | 1648 | struct smu_table_context *smu_table = &smu->smu_table; |
| 1635 | struct gpu_metrics_v2_1 *gpu_metrics = | 1649 | struct gpu_metrics_v2_2 *gpu_metrics = |
| 1636 | (struct gpu_metrics_v2_1 *)smu_table->gpu_metrics_table; | 1650 | (struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table; |
| 1637 | SmuMetrics_legacy_t metrics; | 1651 | SmuMetrics_legacy_t metrics; |
| 1638 | int ret = 0; | 1652 | int ret = 0; |
| 1639 | 1653 | ||
| @@ -1641,7 +1655,7 @@ static ssize_t vangogh_get_legacy_gpu_metrics(struct smu_context *smu, · 1 unmodified line | |||
| 1641 | if (ret) | 1655 | if (ret) |
| 1642 | return ret; | 1656 | return ret; |
| 1643 | 1657 | ||
| 1644 | smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 1); | 1658 | smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2); |
| 1645 | 1659 | ||
| 1646 | gpu_metrics->temperature_gfx = metrics.GfxTemperature; | 1660 | gpu_metrics->temperature_gfx = metrics.GfxTemperature; |
| 1647 | gpu_metrics->temperature_soc = metrics.SocTemperature; | 1661 | gpu_metrics->temperature_soc = metrics.SocTemperature; |
| @@ -1674,20 +1688,23 @@ static ssize_t vangogh_get_legacy_gpu_metrics(struct smu_context *smu, · 26 unmodified lines | |||
| 1674 | gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0]; | 1688 | gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0]; |
| 1675 | 1689 | ||
| 1676 | gpu_metrics->throttle_status = metrics.ThrottlerStatus; | 1690 | gpu_metrics->throttle_status = metrics.ThrottlerStatus; |
| 1691 | gpu_metrics->indep_throttle_status = | ||
| 1692 | smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus, | ||
| 1693 | vangogh_throttler_map); | ||
| 1677 | 1694 | ||
| 1678 | gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); | 1695 | gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); |
| 1679 | 1696 | ||
| 1680 | *table = (void *)gpu_metrics; | 1697 | *table = (void *)gpu_metrics; |
| 1681 | 1698 | ||
| 1682 | return sizeof(struct gpu_metrics_v2_1); | 1699 | return sizeof(struct gpu_metrics_v2_2); |
| 1683 | } | 1700 | } |
| 1684 | 1701 | ||
| 1685 | static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu, | 1702 | static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu, |
| 1686 | void **table) | 1703 | void **table) |
| 1687 | { | 1704 | { |
| 1688 | struct smu_table_context *smu_table = &smu->smu_table; | 1705 | struct smu_table_context *smu_table = &smu->smu_table; |
| 1689 | struct gpu_metrics_v2_1 *gpu_metrics = | 1706 | struct gpu_metrics_v2_2 *gpu_metrics = |
| 1690 | (struct gpu_metrics_v2_1 *)smu_table->gpu_metrics_table; | 1707 | (struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table; |
| 1691 | SmuMetrics_t metrics; | 1708 | SmuMetrics_t metrics; |
| 1692 | int ret = 0; | 1709 | int ret = 0; |
| 1693 | 1710 | ||
| @@ -1695,7 +1712,7 @@ static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu, · 1 unmodified line | |||
| 1695 | if (ret) | 1712 | if (ret) |
| 1696 | return ret; | 1713 | return ret; |
| 1697 | 1714 | ||
| 1698 | smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 1); | 1715 | smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2); |
| 1699 | 1716 | ||
| 1700 | gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature; | 1717 | gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature; |
| 1701 | gpu_metrics->temperature_soc = metrics.Current.SocTemperature; | 1718 | gpu_metrics->temperature_soc = metrics.Current.SocTemperature; |
| @@ -1735,12 +1752,15 @@ static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu, · 33 unmodified lines | |||
| 1735 | gpu_metrics->current_l3clk[0] = metrics.Current.L3Frequency[0]; | 1752 | gpu_metrics->current_l3clk[0] = metrics.Current.L3Frequency[0]; |
| 1736 | 1753 | ||
| 1737 | gpu_metrics->throttle_status = metrics.Current.ThrottlerStatus; | 1754 | gpu_metrics->throttle_status = metrics.Current.ThrottlerStatus; |
| 1755 | gpu_metrics->indep_throttle_status = | ||
| 1756 | smu_cmn_get_indep_throttler_status(metrics.Current.ThrottlerStatus, | ||
| 1757 | vangogh_throttler_map); | ||
| 1738 | 1758 | ||
| 1739 | gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); | 1759 | gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); |
| 1740 | 1760 | ||
| 1741 | *table = (void *)gpu_metrics; | 1761 | *table = (void *)gpu_metrics; |
| 1742 | 1762 | ||
| 1743 | return sizeof(struct gpu_metrics_v2_1); | 1763 | return sizeof(struct gpu_metrics_v2_2); |
| 1744 | } | 1764 | } |
| 1745 | 1765 | ||
| 1746 | static ssize_t vangogh_common_get_gpu_metrics(struct smu_context *smu, | 1766 | static ssize_t vangogh_common_get_gpu_metrics(struct smu_context *smu, |
| @@ -2051,7 +2071,10 @@ static int vangogh_mode2_reset(struct smu_context *smu) · 304 unmodified lines | |||
| 2051 | return vangogh_mode_reset(smu, SMU_RESET_MODE_2); | 2071 | return vangogh_mode_reset(smu, SMU_RESET_MODE_2); |
| 2052 | } | 2072 | } |
| 2053 | 2073 | ||
| 2054 | static int vangogh_get_power_limit(struct smu_context *smu) | 2074 | static int vangogh_get_power_limit(struct smu_context *smu, |
| 2075 | uint32_t *current_power_limit, | ||
| 2076 | uint32_t *default_power_limit, | ||
| 2077 | uint32_t *max_power_limit) | ||
| 2055 | { | 2078 | { |
| 2056 | struct smu_11_5_power_context *power_context = | 2079 | struct smu_11_5_power_context *power_context = |
| 2057 | smu->smu_power.power_context; | 2080 | smu->smu_power.power_context; |
| @@ -2067,8 +2090,12 @@ static int vangogh_get_power_limit(struct smu_context *smu) · 9 unmodified lines | |||
| 2067 | return ret; | 2090 | return ret; |
| 2068 | } | 2091 | } |
| 2069 | /* convert from milliwatt to watt */ | 2092 | /* convert from milliwatt to watt */ |
| 2070 | smu->current_power_limit = smu->default_power_limit = ppt_limit / 1000; | 2093 | if (current_power_limit) |
| 2071 | smu->max_power_limit = 29; | 2094 | *current_power_limit = ppt_limit / 1000; |
| 2095 | if (default_power_limit) | ||
| 2096 | *default_power_limit = ppt_limit / 1000; | ||
| 2097 | if (max_power_limit) | ||
| 2098 | *max_power_limit = 29; | ||
| 2072 | 2099 | ||
| 2073 | ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetFastPPTLimit, &ppt_limit); | 2100 | ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetFastPPTLimit, &ppt_limit); |
| 2074 | if (ret) { | 2101 | if (ret) { |
| @@ -128,6 +128,22 @@ static struct cmn2asic_mapping renoir_workload_map[PP_SMC_POWER_PROFILE_COUNT] = · 127 unmodified lines | |||
| 128 | WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), | 128 | WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), |
| 129 | }; | 129 | }; |
| 130 | 130 | ||
| 131 | static const uint8_t renoir_throttler_map[] = { | ||
| 132 | [THROTTLER_STATUS_BIT_SPL] = (SMU_THROTTLER_SPL_BIT), | ||
| 133 | [THROTTLER_STATUS_BIT_FPPT] = (SMU_THROTTLER_FPPT_BIT), | ||
| 134 | [THROTTLER_STATUS_BIT_SPPT] = (SMU_THROTTLER_SPPT_BIT), | ||
| 135 | [THROTTLER_STATUS_BIT_SPPT_APU] = (SMU_THROTTLER_SPPT_APU_BIT), | ||
| 136 | [THROTTLER_STATUS_BIT_THM_CORE] = (SMU_THROTTLER_TEMP_CORE_BIT), | ||
| 137 | [THROTTLER_STATUS_BIT_THM_GFX] = (SMU_THROTTLER_TEMP_GPU_BIT), | ||
| 138 | [THROTTLER_STATUS_BIT_THM_SOC] = (SMU_THROTTLER_TEMP_SOC_BIT), | ||
| 139 | [THROTTLER_STATUS_BIT_TDC_VDD] = (SMU_THROTTLER_TDC_VDD_BIT), | ||
| 140 | [THROTTLER_STATUS_BIT_TDC_SOC] = (SMU_THROTTLER_TDC_SOC_BIT), | ||
| 141 | [THROTTLER_STATUS_BIT_PROCHOT_CPU] = (SMU_THROTTLER_PROCHOT_CPU_BIT), | ||
| 142 | [THROTTLER_STATUS_BIT_PROCHOT_GFX] = (SMU_THROTTLER_PROCHOT_GFX_BIT), | ||
| 143 | [THROTTLER_STATUS_BIT_EDC_CPU] = (SMU_THROTTLER_EDC_CPU_BIT), | ||
| 144 | [THROTTLER_STATUS_BIT_EDC_GFX] = (SMU_THROTTLER_EDC_GFX_BIT), | ||
| 145 | }; | ||
| 146 | |||
| 131 | static int renoir_init_smc_tables(struct smu_context *smu) | 147 | static int renoir_init_smc_tables(struct smu_context *smu) |
| 132 | { | 148 | { |
| 133 | struct smu_table_context *smu_table = &smu->smu_table; | 149 | struct smu_table_context *smu_table = &smu->smu_table; |
| @@ -153,7 +169,7 @@ static int renoir_init_smc_tables(struct smu_context *smu) · 19 unmodified lines | |||
| 153 | if (!smu_table->watermarks_table) | 169 | if (!smu_table->watermarks_table) |
| 154 | goto err2_out; | 170 | goto err2_out; |
| 155 | 171 | ||
| 156 | smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_1); | 172 | smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_2); |
| 157 | smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); | 173 | smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); |
| 158 | if (!smu_table->gpu_metrics_table) | 174 | if (!smu_table->gpu_metrics_table) |
| 159 | goto err3_out; | 175 | goto err3_out; |
| @@ -1164,6 +1180,28 @@ static int renoir_get_smu_metrics_data(struct smu_context *smu, · 1004 unmodified lines | |||
| 1164 | case METRICS_VOLTAGE_VDDSOC: | 1180 | case METRICS_VOLTAGE_VDDSOC: |
| 1165 | *value = metrics->Voltage[1]; | 1181 | *value = metrics->Voltage[1]; |
| 1166 | break; | 1182 | break; |
| 1183 | case METRICS_SS_APU_SHARE: | ||
| 1184 | /* return the percentage of APU power with respect to APU's power limit. | ||
| 1185 | * percentage is reported, this isn't boost value. Smartshift power | ||
| 1186 | * boost/shift is only when the percentage is more than 100. | ||
| 1187 | */ | ||
| 1188 | if (metrics->StapmOriginalLimit > 0) | ||
| 1189 | *value = (metrics->ApuPower * 100) / metrics->StapmOriginalLimit; | ||
| 1190 | else | ||
| 1191 | *value = 0; | ||
| 1192 | break; | ||
| 1193 | case METRICS_SS_DGPU_SHARE: | ||
| 1194 | /* return the percentage of dGPU power with respect to dGPU's power limit. | ||
| 1195 | * percentage is reported, this isn't boost value. Smartshift power | ||
| 1196 | * boost/shift is only when the percentage is more than 100. | ||
| 1197 | */ | ||
| 1198 | if ((metrics->dGpuPower > 0) && | ||
| 1199 | (metrics->StapmCurrentLimit > metrics->StapmOriginalLimit)) | ||
| 1200 | *value = (metrics->dGpuPower * 100) / | ||
| 1201 | (metrics->StapmCurrentLimit - metrics->StapmOriginalLimit); | ||
| 1202 | else | ||
| 1203 | *value = 0; | ||
| 1204 | break; | ||
| 1167 | default: | 1205 | default: |
| 1168 | *value = UINT_MAX; | 1206 | *value = UINT_MAX; |
| 1169 | break; | 1207 | break; |
| @@ -1235,6 +1273,18 @@ static int renoir_read_sensor(struct smu_context *smu, · 65 unmodified lines | |||
| 1235 | (uint32_t *)data); | 1273 | (uint32_t *)data); |
| 1236 | *size = 4; | 1274 | *size = 4; |
| 1237 | break; | 1275 | break; |
| 1276 | case AMDGPU_PP_SENSOR_SS_APU_SHARE: | ||
| 1277 | ret = renoir_get_smu_metrics_data(smu, | ||
| 1278 | METRICS_SS_APU_SHARE, | ||
| 1279 | (uint32_t *)data); | ||
| 1280 | *size = 4; | ||
| 1281 | break; | ||
| 1282 | case AMDGPU_PP_SENSOR_SS_DGPU_SHARE: | ||
| 1283 | ret = renoir_get_smu_metrics_data(smu, | ||
| 1284 | METRICS_SS_DGPU_SHARE, | ||
| 1285 | (uint32_t *)data); | ||
| 1286 | *size = 4; | ||
| 1287 | break; | ||
| 1238 | default: | 1288 | default: |
| 1239 | ret = -EOPNOTSUPP; | 1289 | ret = -EOPNOTSUPP; |
| 1240 | break; | 1290 | break; |
| @@ -1264,8 +1314,8 @@ static ssize_t renoir_get_gpu_metrics(struct smu_context *smu, · 23 unmodified lines | |||
| 1264 | void **table) | 1314 | void **table) |
| 1265 | { | 1315 | { |
| 1266 | struct smu_table_context *smu_table = &smu->smu_table; | 1316 | struct smu_table_context *smu_table = &smu->smu_table; |
| 1267 | struct gpu_metrics_v2_1 *gpu_metrics = | 1317 | struct gpu_metrics_v2_2 *gpu_metrics = |
| 1268 | (struct gpu_metrics_v2_1 *)smu_table->gpu_metrics_table; | 1318 | (struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table; |
| 1269 | SmuMetrics_t metrics; | 1319 | SmuMetrics_t metrics; |
| 1270 | int ret = 0; | 1320 | int ret = 0; |
| 1271 | 1321 | ||
| @@ -1273,7 +1323,7 @@ static ssize_t renoir_get_gpu_metrics(struct smu_context *smu, · 1 unmodified line | |||
| 1273 | if (ret) | 1323 | if (ret) |
| 1274 | return ret; | 1324 | return ret; |
| 1275 | 1325 | ||
| 1276 | smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 1); | 1326 | smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2); |
| 1277 | 1327 | ||
| 1278 | gpu_metrics->temperature_gfx = metrics.GfxTemperature; | 1328 | gpu_metrics->temperature_gfx = metrics.GfxTemperature; |
| 1279 | gpu_metrics->temperature_soc = metrics.SocTemperature; | 1329 | gpu_metrics->temperature_soc = metrics.SocTemperature; |
| @@ -1311,6 +1361,9 @@ static ssize_t renoir_get_gpu_metrics(struct smu_context *smu, · 31 unmodified lines | |||
| 1311 | gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1]; | 1361 | gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1]; |
| 1312 | 1362 | ||
| 1313 | gpu_metrics->throttle_status = metrics.ThrottlerStatus; | 1363 | gpu_metrics->throttle_status = metrics.ThrottlerStatus; |
| 1364 | gpu_metrics->indep_throttle_status = | ||
| 1365 | smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus, | ||
| 1366 | renoir_throttler_map); | ||
| 1314 | 1367 | ||
| 1315 | gpu_metrics->fan_pwm = metrics.FanPwm; | 1368 | gpu_metrics->fan_pwm = metrics.FanPwm; |
| 1316 | 1369 | ||
| @@ -1318,7 +1371,7 @@ static ssize_t renoir_get_gpu_metrics(struct smu_context *smu, · 1 unmodified line | |||
| 1318 | 1371 | ||
| 1319 | *table = (void *)gpu_metrics; | 1372 | *table = (void *)gpu_metrics; |
| 1320 | 1373 | ||
| 1321 | return sizeof(struct gpu_metrics_v2_1); | 1374 | return sizeof(struct gpu_metrics_v2_2); |
| 1322 | } | 1375 | } |
| 1323 | 1376 | ||
| 1324 | static int renoir_gfx_state_change_set(struct smu_context *smu, uint32_t state) | 1377 | static int renoir_gfx_state_change_set(struct smu_context *smu, uint32_t state) |
| @@ -191,6 +191,20 @@ static const struct cmn2asic_mapping aldebaran_table_map[SMU_TABLE_COUNT] = { · 190 unmodified lines | |||
| 191 | TAB_MAP(I2C_COMMANDS), | 191 | TAB_MAP(I2C_COMMANDS), |
| 192 | }; | 192 | }; |
| 193 | 193 | ||
| 194 | static const uint8_t aldebaran_throttler_map[] = { | ||
| 195 | [THROTTLER_PPT0_BIT] = (SMU_THROTTLER_PPT0_BIT), | ||
| 196 | [THROTTLER_PPT1_BIT] = (SMU_THROTTLER_PPT1_BIT), | ||
| 197 | [THROTTLER_TDC_GFX_BIT] = (SMU_THROTTLER_TDC_GFX_BIT), | ||
| 198 | [THROTTLER_TDC_SOC_BIT] = (SMU_THROTTLER_TDC_SOC_BIT), | ||
| 199 | [THROTTLER_TDC_HBM_BIT] = (SMU_THROTTLER_TDC_MEM_BIT), | ||
| 200 | [THROTTLER_TEMP_GPU_BIT] = (SMU_THROTTLER_TEMP_GPU_BIT), | ||
| 201 | [THROTTLER_TEMP_MEM_BIT] = (SMU_THROTTLER_TEMP_MEM_BIT), | ||
| 202 | [THROTTLER_TEMP_VR_GFX_BIT] = (SMU_THROTTLER_TEMP_VR_GFX_BIT), | ||
| 203 | [THROTTLER_TEMP_VR_SOC_BIT] = (SMU_THROTTLER_TEMP_VR_SOC_BIT), | ||
| 204 | [THROTTLER_TEMP_VR_MEM_BIT] = (SMU_THROTTLER_TEMP_VR_MEM0_BIT), | ||
| 205 | [THROTTLER_APCC_BIT] = (SMU_THROTTLER_APCC_BIT), | ||
| 206 | }; | ||
| 207 | |||
| 194 | static int aldebaran_tables_init(struct smu_context *smu) | 208 | static int aldebaran_tables_init(struct smu_context *smu) |
| 195 | { | 209 | { |
| 196 | struct smu_table_context *smu_table = &smu->smu_table; | 210 | struct smu_table_context *smu_table = &smu->smu_table; |
| @@ -213,7 +227,7 @@ static int aldebaran_tables_init(struct smu_context *smu) · 16 unmodified lines | |||
| 213 | return -ENOMEM; | 227 | return -ENOMEM; |
| 214 | smu_table->metrics_time = 0; | 228 | smu_table->metrics_time = 0; |
| 215 | 229 | ||
| 216 | smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_2); | 230 | smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_3); |
| 217 | smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); | 231 | smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); |
| 218 | if (!smu_table->gpu_metrics_table) { | 232 | if (!smu_table->gpu_metrics_table) { |
| 219 | kfree(smu_table->metrics_table); | 233 | kfree(smu_table->metrics_table); |
| @@ -510,6 +524,16 @@ static int aldebaran_freqs_in_same_level(int32_t frequency1, · 290 unmodified lines | |||
| 510 | return (abs(frequency1 - frequency2) <= EPSILON); | 524 | return (abs(frequency1 - frequency2) <= EPSILON); |
| 511 | } | 525 | } |
| 512 | 526 | ||
| 527 | static bool aldebaran_is_primary(struct smu_context *smu) | ||
| 528 | { | ||
| 529 | struct amdgpu_device *adev = smu->adev; | ||
| 530 | |||
| 531 | if (adev->smuio.funcs && adev->smuio.funcs->get_die_id) | ||
| 532 | return adev->smuio.funcs->get_die_id(adev) == 0; | ||
| 533 | |||
| 534 | return true; | ||
| 535 | } | ||
| 536 | |||
| 513 | static int aldebaran_get_smu_metrics_data(struct smu_context *smu, | 537 | static int aldebaran_get_smu_metrics_data(struct smu_context *smu, |
| 514 | MetricsMember_t member, | 538 | MetricsMember_t member, |
| 515 | uint32_t *value) | 539 | uint32_t *value) |
| @@ -563,7 +587,10 @@ static int aldebaran_get_smu_metrics_data(struct smu_context *smu, · 47 unmodified lines | |||
| 563 | *value = metrics->AverageUclkActivity; | 587 | *value = metrics->AverageUclkActivity; |
| 564 | break; | 588 | break; |
| 565 | case METRICS_AVERAGE_SOCKETPOWER: | 589 | case METRICS_AVERAGE_SOCKETPOWER: |
| 566 | *value = metrics->AverageSocketPower << 8; | 590 | /* Valid power data is available only from primary die */ |
| 591 | *value = aldebaran_is_primary(smu) ? | ||
| 592 | metrics->AverageSocketPower << 8 : | ||
| 593 | 0; | ||
| 567 | break; | 594 | break; |
| 568 | case METRICS_TEMPERATURE_EDGE: | 595 | case METRICS_TEMPERATURE_EDGE: |
| 569 | *value = metrics->TemperatureEdge * | 596 | *value = metrics->TemperatureEdge * |
| @@ -1132,7 +1159,10 @@ static int aldebaran_read_sensor(struct smu_context *smu, · 562 unmodified lines | |||
| 1132 | return ret; | 1159 | return ret; |
| 1133 | } | 1160 | } |
| 1134 | 1161 | ||
| 1135 | static int aldebaran_get_power_limit(struct smu_context *smu) | 1162 | static int aldebaran_get_power_limit(struct smu_context *smu, |
| 1163 | uint32_t *current_power_limit, | ||
| 1164 | uint32_t *default_power_limit, | ||
| 1165 | uint32_t *max_power_limit) | ||
| 1136 | { | 1166 | { |
| 1137 | PPTable_t *pptable = smu->smu_table.driver_pptable; | 1167 | PPTable_t *pptable = smu->smu_table.driver_pptable; |
| 1138 | uint32_t power_limit = 0; | 1168 | uint32_t power_limit = 0; |
| @@ -1141,24 +1171,46 @@ static int aldebaran_get_power_limit(struct smu_context *smu) · 2 unmodified lines | |||
| 1141 | if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) | 1171 | if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) |
| 1142 | return -EINVAL; | 1172 | return -EINVAL; |
| 1143 | 1173 | ||
| 1144 | ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetPptLimit, &power_limit); | 1174 | /* Valid power data is available only from primary die. |
| 1175 | * For secondary die show the value as 0. | ||
| 1176 | */ | ||
| 1177 | if (aldebaran_is_primary(smu)) { | ||
| 1178 | ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetPptLimit, | ||
| 1179 | &power_limit); | ||
| 1145 | 1180 | ||
| 1146 | if (ret) { | 1181 | if (ret) { |
| 1147 | /* the last hope to figure out the ppt limit */ | 1182 | /* the last hope to figure out the ppt limit */ |
| 1148 | if (!pptable) { | 1183 | if (!pptable) { |
| 1149 | dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!"); | 1184 | dev_err(smu->adev->dev, |
| 1150 | return -EINVAL; | 1185 | "Cannot get PPT limit due to pptable missing!"); |
| 1186 | return -EINVAL; | ||
| 1187 | } | ||
| 1188 | power_limit = pptable->PptLimit; | ||
| 1151 | } | 1189 | } |
| 1152 | power_limit = pptable->PptLimit; | ||
| 1153 | } | 1190 | } |
| 1154 | 1191 | ||
| 1155 | smu->current_power_limit = smu->default_power_limit = power_limit; | 1192 | if (current_power_limit) |
| 1156 | if (pptable) | 1193 | *current_power_limit = power_limit; |
| 1157 | smu->max_power_limit = pptable->PptLimit; | 1194 | if (default_power_limit) |
| 1195 | *default_power_limit = power_limit; | ||
| 1196 | |||
| 1197 | if (max_power_limit) { | ||
| 1198 | if (pptable) | ||
| 1199 | *max_power_limit = pptable->PptLimit; | ||
| 1200 | } | ||
| 1158 | 1201 | ||
| 1159 | return 0; | 1202 | return 0; |
| 1160 | } | 1203 | } |
| 1161 | 1204 | ||
| 1205 | static int aldebaran_set_power_limit(struct smu_context *smu, uint32_t n) | ||
| 1206 | { | ||
| 1207 | /* Power limit can be set only through primary die */ | ||
| 1208 | if (aldebaran_is_primary(smu)) | ||
| 1209 | return smu_v13_0_set_power_limit(smu, n); | ||
| 1210 | |||
| 1211 | return -EINVAL; | ||
| 1212 | } | ||
| 1213 | |||
| 1162 | static int aldebaran_system_features_control(struct smu_context *smu, bool enable) | 1214 | static int aldebaran_system_features_control(struct smu_context *smu, bool enable) |
| 1163 | { | 1215 | { |
| 1164 | int ret; | 1216 | int ret; |
| @@ -1706,8 +1758,8 @@ static ssize_t aldebaran_get_gpu_metrics(struct smu_context *smu, · 541 unmodified lines | |||
| 1706 | void **table) | 1758 | void **table) |
| 1707 | { | 1759 | { |
| 1708 | struct smu_table_context *smu_table = &smu->smu_table; | 1760 | struct smu_table_context *smu_table = &smu->smu_table; |
| 1709 | struct gpu_metrics_v1_2 *gpu_metrics = | 1761 | struct gpu_metrics_v1_3 *gpu_metrics = |
| 1710 | (struct gpu_metrics_v1_2 *)smu_table->gpu_metrics_table; | 1762 | (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table; |
| 1711 | SmuMetrics_t metrics; | 1763 | SmuMetrics_t metrics; |
| 1712 | int i, ret = 0; | 1764 | int i, ret = 0; |
| 1713 | 1765 | ||
| @@ -1717,7 +1769,7 @@ static ssize_t aldebaran_get_gpu_metrics(struct smu_context *smu, · 3 unmodified lines | |||
| 1717 | if (ret) | 1769 | if (ret) |
| 1718 | return ret; | 1770 | return ret; |
| 1719 | 1771 | ||
| 1720 | smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 2); | 1772 | smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3); |
| 1721 | 1773 | ||
| 1722 | gpu_metrics->temperature_edge = metrics.TemperatureEdge; | 1774 | gpu_metrics->temperature_edge = metrics.TemperatureEdge; |
| 1723 | gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; | 1775 | gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; |
| @@ -1730,10 +1782,16 @@ static ssize_t aldebaran_get_gpu_metrics(struct smu_context *smu, · 6 unmodified lines | |||
| 1730 | gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; | 1782 | gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; |
| 1731 | gpu_metrics->average_mm_activity = 0; | 1783 | gpu_metrics->average_mm_activity = 0; |
| 1732 | 1784 | ||
| 1733 | gpu_metrics->average_socket_power = metrics.AverageSocketPower; | 1785 | /* Valid power data is available only from primary die */ |
| 1734 | gpu_metrics->energy_accumulator = | 1786 | if (aldebaran_is_primary(smu)) { |
| 1787 | gpu_metrics->average_socket_power = metrics.AverageSocketPower; | ||
| 1788 | gpu_metrics->energy_accumulator = | ||
| 1735 | (uint64_t)metrics.EnergyAcc64bitHigh << 32 | | 1789 | (uint64_t)metrics.EnergyAcc64bitHigh << 32 | |
| 1736 | metrics.EnergyAcc64bitLow; | 1790 | metrics.EnergyAcc64bitLow; |
| 1791 | } else { | ||
| 1792 | gpu_metrics->average_socket_power = 0; | ||
| 1793 | gpu_metrics->energy_accumulator = 0; | ||
| 1794 | } | ||
| 1737 | 1795 | ||
| 1738 | gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; | 1796 | gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; |
| 1739 | gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; | 1797 | gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; |
| @@ -1748,6 +1806,9 @@ static ssize_t aldebaran_get_gpu_metrics(struct smu_context *smu, · 8 unmodified lines | |||
| 1748 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; | 1806 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; |
| 1749 | 1807 | ||
| 1750 | gpu_metrics->throttle_status = metrics.ThrottlerStatus; | 1808 | gpu_metrics->throttle_status = metrics.ThrottlerStatus; |
| 1809 | gpu_metrics->indep_throttle_status = | ||
| 1810 | smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus, | ||
| 1811 | aldebaran_throttler_map); | ||
| 1751 | 1812 | ||
| 1752 | gpu_metrics->current_fan_speed = 0; | 1813 | gpu_metrics->current_fan_speed = 0; |
| 1753 | 1814 | ||
| @@ -1769,7 +1830,7 @@ static ssize_t aldebaran_get_gpu_metrics(struct smu_context *smu, · 15 unmodified lines | |||
| 1769 | 1830 | ||
| 1770 | *table = (void *)gpu_metrics; | 1831 | *table = (void *)gpu_metrics; |
| 1771 | 1832 | ||
| 1772 | return sizeof(struct gpu_metrics_v1_2); | 1833 | return sizeof(struct gpu_metrics_v1_3); |
| 1773 | } | 1834 | } |
| 1774 | 1835 | ||
| 1775 | static int aldebaran_mode2_reset(struct smu_context *smu) | 1836 | static int aldebaran_mode2_reset(struct smu_context *smu) |
| @@ -1898,7 +1959,7 @@ static const struct pptable_funcs aldebaran_ppt_funcs = { · 122 unmodified lines | |||
| 1898 | .get_enabled_mask = smu_cmn_get_enabled_mask, | 1959 | .get_enabled_mask = smu_cmn_get_enabled_mask, |
| 1899 | .feature_is_enabled = smu_cmn_feature_is_enabled, | 1960 | .feature_is_enabled = smu_cmn_feature_is_enabled, |
| 1900 | .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception, | 1961 | .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception, |
| 1901 | .set_power_limit = smu_v13_0_set_power_limit, | 1962 | .set_power_limit = aldebaran_set_power_limit, |
| 1902 | .init_max_sustainable_clocks = smu_v13_0_init_max_sustainable_clocks, | 1963 | .init_max_sustainable_clocks = smu_v13_0_init_max_sustainable_clocks, |
| 1903 | .enable_thermal_alert = smu_v13_0_enable_thermal_alert, | 1964 | .enable_thermal_alert = smu_v13_0_enable_thermal_alert, |
| 1904 | .disable_thermal_alert = smu_v13_0_disable_thermal_alert, | 1965 | .disable_thermal_alert = smu_v13_0_disable_thermal_alert, |
| @@ -356,6 +356,28 @@ static int yellow_carp_get_smu_metrics_data(struct smu_context *smu, · 355 unmodified lines | |||
| 356 | case METRICS_VOLTAGE_VDDSOC: | 356 | case METRICS_VOLTAGE_VDDSOC: |
| 357 | *value = metrics->Voltage[1]; | 357 | *value = metrics->Voltage[1]; |
| 358 | break; | 358 | break; |
| 359 | case METRICS_SS_APU_SHARE: | ||
| 360 | /* return the percentage of APU power with respect to APU's power limit. | ||
| 361 | * percentage is reported, this isn't boost value. Smartshift power | ||
| 362 | * boost/shift is only when the percentage is more than 100. | ||
| 363 | */ | ||
| 364 | if (metrics->StapmOpnLimit > 0) | ||
| 365 | *value = (metrics->ApuPower * 100) / metrics->StapmOpnLimit; | ||
| 366 | else | ||
| 367 | *value = 0; | ||
| 368 | break; | ||
| 369 | case METRICS_SS_DGPU_SHARE: | ||
| 370 | /* return the percentage of dGPU power with respect to dGPU's power limit. | ||
| 371 | * percentage is reported, this isn't boost value. Smartshift power | ||
| 372 | * boost/shift is only when the percentage is more than 100. | ||
| 373 | */ | ||
| 374 | if ((metrics->dGpuPower > 0) && | ||
| 375 | (metrics->StapmCurrentLimit > metrics->StapmOpnLimit)) | ||
| 376 | *value = (metrics->dGpuPower * 100) / | ||
| 377 | (metrics->StapmCurrentLimit - metrics->StapmOpnLimit); | ||
| 378 | else | ||
| 379 | *value = 0; | ||
| 380 | break; | ||
| 359 | default: | 381 | default: |
| 360 | *value = UINT_MAX; | 382 | *value = UINT_MAX; |
| 361 | break; | 383 | break; |
| @@ -427,6 +449,18 @@ static int yellow_carp_read_sensor(struct smu_context *smu, · 65 unmodified lines | |||
| 427 | (uint32_t *)data); | 449 | (uint32_t *)data); |
| 428 | *size = 4; | 450 | *size = 4; |
| 429 | break; | 451 | break; |
| 452 | case AMDGPU_PP_SENSOR_SS_APU_SHARE: | ||
| 453 | ret = yellow_carp_get_smu_metrics_data(smu, | ||
| 454 | METRICS_SS_APU_SHARE, | ||
| 455 | (uint32_t *)data); | ||
| 456 | *size = 4; | ||
| 457 | break; | ||
| 458 | case AMDGPU_PP_SENSOR_SS_DGPU_SHARE: | ||
| 459 | ret = yellow_carp_get_smu_metrics_data(smu, | ||
| 460 | METRICS_SS_DGPU_SHARE, | ||
| 461 | (uint32_t *)data); | ||
| 462 | *size = 4; | ||
| 463 | break; | ||
| 430 | default: | 464 | default: |
| 431 | ret = -EOPNOTSUPP; | 465 | ret = -EOPNOTSUPP; |
| 432 | break; | 466 | break; |
| @@ -398,6 +398,19 @@ int smu_cmn_get_enabled_32_bits_mask(struct smu_context *smu, · 397 unmodified lines | |||
| 398 | 398 | ||
| 399 | } | 399 | } |
| 400 | 400 | ||
| 401 | uint64_t smu_cmn_get_indep_throttler_status( | ||
| 402 | const unsigned long dep_status, | ||
| 403 | const uint8_t *throttler_map) | ||
| 404 | { | ||
| 405 | uint64_t indep_status = 0; | ||
| 406 | uint8_t dep_bit = 0; | ||
| 407 | |||
| 408 | for_each_set_bit(dep_bit, &dep_status, 32) | ||
| 409 | indep_status |= 1ULL << throttler_map[dep_bit]; | ||
| 410 | |||
| 411 | return indep_status; | ||
| 412 | } | ||
| 413 | |||
| 401 | int smu_cmn_feature_update_enable_state(struct smu_context *smu, | 414 | int smu_cmn_feature_update_enable_state(struct smu_context *smu, |
| 402 | uint64_t feature_mask, | 415 | uint64_t feature_mask, |
| 403 | bool enabled) | 416 | bool enabled) |
| @@ -575,23 +588,52 @@ int smu_cmn_set_pp_feature_mask(struct smu_context *smu, · 171 unmodified lines | |||
| 575 | return ret; | 588 | return ret; |
| 576 | } | 589 | } |
| 577 | 590 | ||
| 591 | /** | ||
| 592 | * smu_cmn_disable_all_features_with_exception - disable all dpm features | ||
| 593 | * except this specified by | ||
| 594 | * @mask | ||
| 595 | * | ||
| 596 | * @smu: smu_context pointer | ||
| 597 | * @no_hw_disablement: whether real dpm disablement should be performed | ||
| 598 | * true: update the cache(about dpm enablement state) only | ||
| 599 | * false: real dpm disablement plus cache update | ||
| 600 | * @mask: the dpm feature which should not be disabled | ||
| 601 | * SMU_FEATURE_COUNT: no exception, all dpm features | ||
| 602 | * to disable | ||
| 603 | * | ||
| 604 | * Returns: | ||
| 605 | * 0 on success or a negative error code on failure. | ||
| 606 | */ | ||
| 578 | int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, | 607 | int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, |
| 608 | bool no_hw_disablement, | ||
| 579 | enum smu_feature_mask mask) | 609 | enum smu_feature_mask mask) |
| 580 | { | 610 | { |
| 611 | struct smu_feature *feature = &smu->smu_feature; | ||
| 581 | uint64_t features_to_disable = U64_MAX; | 612 | uint64_t features_to_disable = U64_MAX; |
| 582 | int skipped_feature_id; | 613 | int skipped_feature_id; |
| 583 | 614 | ||
| 584 | skipped_feature_id = smu_cmn_to_asic_specific_index(smu, | 615 | if (mask != SMU_FEATURE_COUNT) { |
| 585 | CMN2ASIC_MAPPING_FEATURE, | 616 | skipped_feature_id = smu_cmn_to_asic_specific_index(smu, |
| 586 | mask); | 617 | CMN2ASIC_MAPPING_FEATURE, |
| 587 | if (skipped_feature_id < 0) | 618 | mask); |
| 588 | return -EINVAL; | 619 | if (skipped_feature_id < 0) |
| 620 | return -EINVAL; | ||
| 589 | 621 | ||
| 590 | features_to_disable &= ~(1ULL << skipped_feature_id); | 622 | features_to_disable &= ~(1ULL << skipped_feature_id); |
| 623 | } | ||
| 591 | 624 | ||
| 592 | return smu_cmn_feature_update_enable_state(smu, | 625 | if (no_hw_disablement) { |
| 593 | features_to_disable, | 626 | mutex_lock(&feature->mutex); |
| 594 | 0); | 627 | bitmap_andnot(feature->enabled, feature->enabled, |
| 628 | (unsigned long *)(&features_to_disable), SMU_FEATURE_MAX); | ||
| 629 | mutex_unlock(&feature->mutex); | ||
| 630 | |||
| 631 | return 0; | ||
| 632 | } else { | ||
| 633 | return smu_cmn_feature_update_enable_state(smu, | ||
| 634 | features_to_disable, | ||
| 635 | 0); | ||
| 636 | } | ||
| 595 | } | 637 | } |
| 596 | 638 | ||
| 597 | int smu_cmn_get_smc_version(struct smu_context *smu, | 639 | int smu_cmn_get_smc_version(struct smu_context *smu, |
| @@ -773,6 +815,9 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev) · 175 unmodified lines | |||
| 773 | case METRICS_VERSION(2, 1): | 815 | case METRICS_VERSION(2, 1): |
| 774 | structure_size = sizeof(struct gpu_metrics_v2_1); | 816 | structure_size = sizeof(struct gpu_metrics_v2_1); |
| 775 | break; | 817 | break; |
| 818 | case METRICS_VERSION(2, 2): | ||
| 819 | structure_size = sizeof(struct gpu_metrics_v2_2); | ||
| 820 | break; | ||
| 776 | default: | 821 | default: |
| 777 | return; | 822 | return; |
| 778 | } | 823 | } |
| @@ -60,6 +60,10 @@ int smu_cmn_get_enabled_32_bits_mask(struct smu_context *smu, · 59 unmodified lines | |||
| 60 | uint32_t *feature_mask, | 60 | uint32_t *feature_mask, |
| 61 | uint32_t num); | 61 | uint32_t num); |
| 62 | 62 | ||
| 63 | uint64_t smu_cmn_get_indep_throttler_status( | ||
| 64 | const unsigned long dep_status, | ||
| 65 | const uint8_t *throttler_map); | ||
| 66 | |||
| 63 | int smu_cmn_feature_update_enable_state(struct smu_context *smu, | 67 | int smu_cmn_feature_update_enable_state(struct smu_context *smu, |
| 64 | uint64_t feature_mask, | 68 | uint64_t feature_mask, |
| 65 | bool enabled); | 69 | bool enabled); |
| @@ -75,6 +79,7 @@ int smu_cmn_set_pp_feature_mask(struct smu_context *smu, · 9 unmodified lines | |||
| 75 | uint64_t new_mask); | 79 | uint64_t new_mask); |
| 76 | 80 | ||
| 77 | int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, | 81 | int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, |
| 82 | bool no_hw_disablement, | ||
| 78 | enum smu_feature_mask mask); | 83 | enum smu_feature_mask mask); |
| 79 | 84 | ||
| 80 | int smu_cmn_get_smc_version(struct smu_context *smu, | 85 | int smu_cmn_get_smc_version(struct smu_context *smu, |
| @@ -57,7 +57,7 @@ · 56 unmodified lines | |||
| 57 | #define smu_feature_set_allowed_mask(smu) smu_ppt_funcs(set_allowed_mask, 0, smu) | 57 | #define smu_feature_set_allowed_mask(smu) smu_ppt_funcs(set_allowed_mask, 0, smu) |
| 58 | #define smu_feature_get_enabled_mask(smu, mask, num) smu_ppt_funcs(get_enabled_mask, 0, smu, mask, num) | 58 | #define smu_feature_get_enabled_mask(smu, mask, num) smu_ppt_funcs(get_enabled_mask, 0, smu, mask, num) |
| 59 | #define smu_feature_is_enabled(smu, mask) smu_ppt_funcs(feature_is_enabled, 0, smu, mask) | 59 | #define smu_feature_is_enabled(smu, mask) smu_ppt_funcs(feature_is_enabled, 0, smu, mask) |
| 60 | #define smu_disable_all_features_with_exception(smu, mask) smu_ppt_funcs(disable_all_features_with_exception, 0, smu, mask) | 60 | #define smu_disable_all_features_with_exception(smu, no_hw_disablement, mask) smu_ppt_funcs(disable_all_features_with_exception, 0, smu, no_hw_disablement, mask) |
| 61 | #define smu_is_dpm_running(smu) smu_ppt_funcs(is_dpm_running, 0 , smu) | 61 | #define smu_is_dpm_running(smu) smu_ppt_funcs(is_dpm_running, 0 , smu) |
| 62 | #define smu_notify_display_change(smu) smu_ppt_funcs(notify_display_change, 0, smu) | 62 | #define smu_notify_display_change(smu) smu_ppt_funcs(notify_display_change, 0, smu) |
| 63 | #define smu_populate_umd_state_clk(smu) smu_ppt_funcs(populate_umd_state_clk, 0, smu) | 63 | #define smu_populate_umd_state_clk(smu) smu_ppt_funcs(populate_umd_state_clk, 0, smu) |
| @@ -82,7 +82,7 @@ · 18 unmodified lines | |||
| 82 | #define smu_i2c_fini(smu, control) smu_ppt_funcs(i2c_fini, 0, smu, control) | 82 | #define smu_i2c_fini(smu, control) smu_ppt_funcs(i2c_fini, 0, smu, control) |
| 83 | #define smu_get_unique_id(smu) smu_ppt_funcs(get_unique_id, 0, smu) | 83 | #define smu_get_unique_id(smu) smu_ppt_funcs(get_unique_id, 0, smu) |
| 84 | #define smu_log_thermal_throttling(smu) smu_ppt_funcs(log_thermal_throttling_event, 0, smu) | 84 | #define smu_log_thermal_throttling(smu) smu_ppt_funcs(log_thermal_throttling_event, 0, smu) |
| 85 | #define smu_get_asic_power_limits(smu) smu_ppt_funcs(get_power_limit, 0, smu) | 85 | #define smu_get_asic_power_limits(smu, current, default, max) smu_ppt_funcs(get_power_limit, 0, smu, current, default, max) |
| 86 | #define smu_get_pp_feature_mask(smu, buf) smu_ppt_funcs(get_pp_feature_mask, 0, smu, buf) | 86 | #define smu_get_pp_feature_mask(smu, buf) smu_ppt_funcs(get_pp_feature_mask, 0, smu, buf) |
| 87 | #define smu_set_pp_feature_mask(smu, new_mask) smu_ppt_funcs(set_pp_feature_mask, 0, smu, new_mask) | 87 | #define smu_set_pp_feature_mask(smu, new_mask) smu_ppt_funcs(set_pp_feature_mask, 0, smu, new_mask) |
| 88 | #define smu_gfx_ulv_control(smu, enablement) smu_ppt_funcs(gfx_ulv_control, 0, smu, enablement) | 88 | #define smu_gfx_ulv_control(smu, enablement) smu_ppt_funcs(gfx_ulv_control, 0, smu, enablement) |
| @@ -1377,10 +1377,27 @@ enum drm_dp_phy { · 1376 unmodified lines | |||
| 1377 | #define DP_SYMBOL_ERROR_COUNT_LANE1_PHY_REPEATER1 0xf0037 /* 1.3 */ | 1377 | #define DP_SYMBOL_ERROR_COUNT_LANE1_PHY_REPEATER1 0xf0037 /* 1.3 */ |
| 1378 | #define DP_SYMBOL_ERROR_COUNT_LANE2_PHY_REPEATER1 0xf0039 /* 1.3 */ | 1378 | #define DP_SYMBOL_ERROR_COUNT_LANE2_PHY_REPEATER1 0xf0039 /* 1.3 */ |
| 1379 | #define DP_SYMBOL_ERROR_COUNT_LANE3_PHY_REPEATER1 0xf003b /* 1.3 */ | 1379 | #define DP_SYMBOL_ERROR_COUNT_LANE3_PHY_REPEATER1 0xf003b /* 1.3 */ |
| 1380 | |||
| 1381 | #define __DP_FEC1_BASE 0xf0290 /* 1.4 */ | ||
| 1382 | #define __DP_FEC2_BASE 0xf0298 /* 1.4 */ | ||
| 1383 | #define DP_FEC_BASE(dp_phy) \ | ||
| 1384 | (__DP_FEC1_BASE + ((__DP_FEC2_BASE - __DP_FEC1_BASE) * \ | ||
| 1385 | ((dp_phy) - DP_PHY_LTTPR1))) | ||
| 1386 | |||
| 1387 | #define DP_FEC_REG(dp_phy, fec1_reg) \ | ||
| 1388 | (DP_FEC_BASE(dp_phy) - DP_FEC_BASE(DP_PHY_LTTPR1) + fec1_reg) | ||
| 1389 | |||
| 1380 | #define DP_FEC_STATUS_PHY_REPEATER1 0xf0290 /* 1.4 */ | 1390 | #define DP_FEC_STATUS_PHY_REPEATER1 0xf0290 /* 1.4 */ |
| 1391 | #define DP_FEC_STATUS_PHY_REPEATER(dp_phy) \ | ||
| 1392 | DP_FEC_REG(dp_phy, DP_FEC_STATUS_PHY_REPEATER1) | ||
| 1393 | |||
| 1381 | #define DP_FEC_ERROR_COUNT_PHY_REPEATER1 0xf0291 /* 1.4 */ | 1394 | #define DP_FEC_ERROR_COUNT_PHY_REPEATER1 0xf0291 /* 1.4 */ |
| 1382 | #define DP_FEC_CAPABILITY_PHY_REPEATER1 0xf0294 /* 1.4a */ | 1395 | #define DP_FEC_CAPABILITY_PHY_REPEATER1 0xf0294 /* 1.4a */ |
| 1383 | 1396 | ||
| 1397 | #define DP_LTTPR_MAX_ADD 0xf02ff /* 1.4 */ | ||
| 1398 | |||
| 1399 | #define DP_DPCD_MAX_ADD 0xfffff /* 1.4 */ | ||
| 1400 | |||
| 1384 | /* Repeater modes */ | 1401 | /* Repeater modes */ |
| 1385 | #define DP_PHY_REPEATER_MODE_TRANSPARENT 0x55 /* 1.3 */ | 1402 | #define DP_PHY_REPEATER_MODE_TRANSPARENT 0x55 /* 1.3 */ |
| 1386 | #define DP_PHY_REPEATER_MODE_NON_TRANSPARENT 0xaa /* 1.3 */ | 1403 | #define DP_PHY_REPEATER_MODE_NON_TRANSPARENT 0xaa /* 1.3 */ |