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 | 47 | spinlock_t mem_limit_lock; |
| 48 | 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 | 50 | static const char * const domain_bit_to_string[] = { |
| 57 | 51 | "CPU", |
| 58 | 52 | "GTT", |
| @@ -348,11 +342,9 @@ validate_fail: · 289 unmodified lines | ||
| 348 | 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; | |
| 354 | − | |
| 355 | − return amdgpu_amdkfd_bo_validate(bo, p->domain, p->wait); | |
| 347 | + return amdgpu_amdkfd_bo_validate(bo, bo->allowed_domains, false); | |
| 356 | 348 | } |
| 357 | 349 | |
| 358 | 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 | 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 | 360 | struct amdgpu_device *adev = amdgpu_ttm_adev(pd->tbo.bdev); |
| 369 | − struct amdgpu_vm_parser param; | |
| 370 | 361 | int ret; |
| 371 | 362 | |
| 372 | − param.domain = AMDGPU_GEM_DOMAIN_VRAM; | |
| 373 | − param.wait = false; | |
| 374 | − | |
| 375 | − ret = amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_amdkfd_validate, | |
| 376 | − ¶m); | |
| 363 | + ret = amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_amdkfd_validate_vm_bo, NULL); | |
| 377 | 364 | if (ret) { |
| 378 | 365 | pr_err("failed to validate PT BOs\n"); |
| 379 | 366 | return ret; |
| 380 | 367 | } |
| 381 | 368 | |
| 382 | − ret = amdgpu_amdkfd_validate(¶m, pd); | |
| 369 | + ret = amdgpu_amdkfd_validate_vm_bo(NULL, pd); | |
| 383 | 370 | if (ret) { |
| 384 | 371 | pr_err("failed to validate PD\n"); |
| 385 | 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 | 377 | if (vm->use_cpu_for_update) { |
| 391 | 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 | 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 | 391 | struct amdgpu_device *adev = amdgpu_ttm_adev(pd->tbo.bdev); |
| 405 | 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 | 643 | if (IS_ERR(gobj)) |
| 657 | 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 | 1154 | list_for_each_entry(peer_vm, &process_info->vm_list_head, |
| 1168 | 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 | 1158 | ret = amdgpu_sync_resv(NULL, sync, pd->tbo.base.resv, |
| 1172 | 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 | 1220 | vm->process_info = *process_info; |
| 1234 | 1221 | |
| 1235 | 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 | 1224 | if (ret) |
| 1238 | 1225 | goto reserve_pd_fail; |
| 1239 | 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 | 1228 | pr_err("validate_pt_pd_bos() failed\n"); |
| 1242 | 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 | 1232 | AMDGPU_FENCE_OWNER_KFD, false); |
| 1246 | 1233 | if (ret) |
| 1247 | 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 | 1236 | if (ret) |
| 1250 | 1237 | goto reserve_shared_fail; |
| 1251 | − amdgpu_bo_fence(vm->root.base.bo, | |
| 1238 | + amdgpu_bo_fence(vm->root.bo, | |
| 1252 | 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 | 1242 | /* Update process info */ |
| 1256 | 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 | 1251 | reserve_shared_fail: |
| 1265 | 1252 | wait_pd_fail: |
| 1266 | 1253 | validate_pd_fail: |
| 1267 | − amdgpu_bo_unreserve(vm->root.base.bo); | |
| 1254 | + amdgpu_bo_unreserve(vm->root.bo); | |
| 1268 | 1255 | reserve_pd_fail: |
| 1269 | 1256 | vm->process_info = NULL; |
| 1270 | 1257 | if (info) { |
| @@ -1319,7 +1306,7 @@ void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev, · 48 unmodified lines | ||
| 1319 | 1306 | struct amdgpu_vm *vm) |
| 1320 | 1307 | { |
| 1321 | 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 | 1311 | if (!process_info) |
| 1325 | 1312 | return; |
| @@ -1375,7 +1362,7 @@ void amdgpu_amdkfd_gpuvm_release_process_vm(struct kgd_dev *kgd, void *drm_priv) · 49 unmodified lines | ||
| 1375 | 1362 | uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *drm_priv) |
| 1376 | 1363 | { |
| 1377 | 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 | 1366 | struct amdgpu_device *adev = amdgpu_ttm_adev(pd->tbo.bdev); |
| 1380 | 1367 | |
| 1381 | 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 | 2389 | /* Attach eviction fence to PD / PT BOs */ |
| 2403 | 2390 | list_for_each_entry(peer_vm, &process_info->vm_list_head, |
| 2404 | 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 | 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 | 832 | if (r) |
| 833 | 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 | 837 | if (amdgpu_vm_debug) { |
| 838 | 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 | 1305 | seq_printf(m, "pid:%d\tProcess:%s ----------\n", |
| 1306 | 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 | 1308 | if (r) |
| 1309 | 1309 | break; |
| 1310 | 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 | 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 | 4125 | struct dma_fence *fence = NULL, *next = NULL; |
| 4126 | 4126 | struct amdgpu_bo *shadow; |
| 4127 | + struct amdgpu_bo_vm *vmbo; | |
| 4127 | 4128 | long r = 1, tmo; |
| 4128 | 4129 | |
| 4129 | 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 | 4135 | dev_info(adev->dev, "recover vram bo from shadow start\n"); |
| 4135 | 4136 | mutex_lock(&adev->shadow_list_lock); |
| 4136 | − list_for_each_entry(shadow, &adev->shadow_list, shadow_list) { | |
| 4137 | − | |
| 4137 | + list_for_each_entry(vmbo, &adev->shadow_list, shadow_list) { | |
| 4138 | + shadow = &vmbo->bo; | |
| 4138 | 4139 | /* No need to recover an evicted BO */ |
| 4139 | 4140 | if (shadow->tbo.resource->mem_type != TTM_PL_TT || |
| 4140 | 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 | 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 | 329 | int *major, int *minor, int *revision) |
| 330 | 330 | { |
| 331 | 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 | 357 | for (j = 0; j < num_ips; j++) { |
| 358 | 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 | 361 | if (major) |
| 362 | 362 | *major = ip->major; |
| 363 | 363 | if (minor) |
| @@ -30,7 +30,7 @@ · 29 unmodified lines | ||
| 30 | 30 | void amdgpu_discovery_fini(struct amdgpu_device *adev); |
| 31 | 31 | int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev); |
| 32 | 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 | 34 | int *major, int *minor, int *revision); |
| 35 | 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 | 449 | for (bo_base = bo->vm_bo; bo_base; bo_base = bo_base->next) { |
| 450 | 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 | 453 | if (ticket) { |
| 454 | 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 | 69 | dev = PCI_SLOT(adev->pdev->devfn); |
| 70 | 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 | 73 | if (ret) { |
| 74 | 74 | DRM_ERROR("Fail to reserve bo\n"); |
| 75 | 75 | return; |
| 76 | 76 | } |
| 77 | 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 | 79 | seq_printf(m, "pdev:\t%04x:%02x:%02x.%d\npasid:\t%u\n", domain, bus, |
| 80 | 80 | dev, fn, fpriv->vm.pasid); |
| 81 | 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 | 170 | return -EPERM; |
| 171 | 171 | |
| 172 | 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 | 174 | return -EPERM; |
| 175 | 175 | |
| 176 | 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 | 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 | 324 | if (r) |
| 325 | 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 | 330 | initial_domain = (u32)(0xffffffff & args->in.domains); |
| @@ -353,9 +353,9 @@ retry: · 22 unmodified lines | ||
| 353 | 353 | if (!r) { |
| 354 | 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 | 360 | if (r) |
| 361 | 361 | return r; |
| @@ -841,7 +841,7 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data, · 479 unmodified lines | ||
| 841 | 841 | } |
| 842 | 842 | for (base = robj->vm_bo; base; base = base->next) |
| 843 | 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 | 845 | r = -EINVAL; |
| 846 | 846 | amdgpu_bo_unreserve(robj); |
| 847 | 847 | goto out; |
| @@ -124,6 +124,22 @@ void amdgpu_register_gpu_instance(struct amdgpu_device *adev) · 123 unmodified lines | ||
| 124 | 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 | 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 | 229 | DPM_FLAG_MAY_SKIP_RESUME); |
| 214 | 230 | pm_runtime_use_autosuspend(dev->dev); |
| 215 | 231 | pm_runtime_set_autosuspend_delay(dev->dev, 5000); |
| 232 | + | |
| 216 | 233 | pm_runtime_allow(dev->dev); |
| 234 | + | |
| 217 | 235 | pm_runtime_mark_last_busy(dev->dev); |
| 218 | 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 | 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 | 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 | 1267 | amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr); |
| 1226 | 1268 | amdgpu_vm_fini(adev, &fpriv->vm); |
| @@ -54,29 +54,42 @@ · 53 unmodified lines | ||
| 54 | 54 | |
| 55 | 55 | static void amdgpu_bo_destroy(struct ttm_buffer_object *tbo) |
| 56 | 56 | { |
| 57 | − struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev); | |
| 58 | 57 | struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo); |
| 59 | − struct amdgpu_bo_user *ubo; | |
| 60 | 58 | |
| 61 | 59 | amdgpu_bo_kunmap(bo); |
| 62 | 60 | |
| 63 | 61 | if (bo->tbo.base.import_attach) |
| 64 | 62 | drm_prime_gem_destroy(&bo->tbo.base, bo->tbo.sg); |
| 65 | 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 | 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 | 87 | mutex_lock(&adev->shadow_list_lock); |
| 69 | − list_del_init(&bo->shadow_list); | |
| 88 | + list_del_init(&vmbo->shadow_list); | |
| 70 | 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 | 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 | 110 | return true; |
| 111 | + | |
| 96 | 112 | return false; |
| 97 | 113 | } |
| 98 | 114 | |
| @@ -545,7 +561,6 @@ int amdgpu_bo_create(struct amdgpu_device *adev, · 446 unmodified lines | ||
| 545 | 561 | if (bo == NULL) |
| 546 | 562 | return -ENOMEM; |
| 547 | 563 | drm_gem_private_object_init(adev_to_drm(adev), &bo->tbo.base, size); |
| 548 | − INIT_LIST_HEAD(&bo->shadow_list); | |
| 549 | 564 | bo->vm_bo = NULL; |
| 550 | 565 | bo->preferred_domains = bp->preferred_domain ? bp->preferred_domain : |
| 551 | 566 | bp->domain; |
| @@ -568,9 +583,12 @@ int amdgpu_bo_create(struct amdgpu_device *adev, · 16 unmodified lines | ||
| 568 | 583 | if (bp->type == ttm_bo_type_kernel) |
| 569 | 584 | bo->tbo.priority = 1; |
| 570 | 585 | |
| 586 | + if (!bp->destroy) | |
| 587 | + bp->destroy = &amdgpu_bo_destroy; | |
| 588 | + | |
| 571 | 589 | r = ttm_bo_init_reserved(&adev->mman.bdev, &bo->tbo, size, bp->type, |
| 572 | 590 | &bo->placement, page_align, &ctx, NULL, |
| 573 | − bp->resv, &amdgpu_bo_destroy); | |
| 591 | + bp->resv, bp->destroy); | |
| 574 | 592 | if (unlikely(r != 0)) |
| 575 | 593 | return r; |
| 576 | 594 | |
| @@ -634,6 +652,7 @@ int amdgpu_bo_create_user(struct amdgpu_device *adev, · 57 unmodified lines | ||
| 634 | 652 | int r; |
| 635 | 653 | |
| 636 | 654 | bp->bo_ptr_size = sizeof(struct amdgpu_bo_user); |
| 655 | + bp->destroy = &amdgpu_bo_user_destroy; | |
| 637 | 656 | r = amdgpu_bo_create(adev, bp, &bo_ptr); |
| 638 | 657 | if (r) |
| 639 | 658 | return r; |
| @@ -665,11 +684,13 @@ int amdgpu_bo_create_vm(struct amdgpu_device *adev, · 25 unmodified lines | ||
| 665 | 684 | * num of amdgpu_vm_pt entries. |
| 666 | 685 | */ |
| 667 | 686 | BUG_ON(bp->bo_ptr_size < sizeof(struct amdgpu_bo_vm)); |
| 687 | + bp->destroy = &amdgpu_bo_vm_destroy; | |
| 668 | 688 | r = amdgpu_bo_create(adev, bp, &bo_ptr); |
| 669 | 689 | if (r) |
| 670 | 690 | return r; |
| 671 | 691 | |
| 672 | 692 | *vmbo_ptr = to_amdgpu_bo_vm(bo_ptr); |
| 693 | + INIT_LIST_HEAD(&(*vmbo_ptr)->shadow_list); | |
| 673 | 694 | return r; |
| 674 | 695 | } |
| 675 | 696 | |
| @@ -714,12 +735,12 @@ retry: · 38 unmodified lines | ||
| 714 | 735 | * |
| 715 | 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 | 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 | 744 | mutex_unlock(&adev->shadow_list_lock); |
| 724 | 745 | } |
| 725 | 746 | |
| @@ -55,7 +55,8 @@ struct amdgpu_bo_param { · 54 unmodified lines | ||
| 55 | 55 | u64 flags; |
| 56 | 56 | enum ttm_bo_type type; |
| 57 | 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 | 62 | /* bo virtual addresses in a vm */ |
| @@ -108,9 +109,6 @@ struct amdgpu_bo { · 46 unmodified lines | ||
| 108 | 109 | #ifdef CONFIG_MMU_NOTIFIER |
| 109 | 110 | struct mmu_interval_notifier notifier; |
| 110 | 111 | #endif |
| 111 | − | |
| 112 | − struct list_head shadow_list; | |
| 113 | − | |
| 114 | 112 | struct kgd_mem *kfd_bo; |
| 115 | 113 | }; |
| 116 | 114 | |
| @@ -126,7 +124,8 @@ struct amdgpu_bo_user { · 9 unmodified lines | ||
| 126 | 124 | struct amdgpu_bo_vm { |
| 127 | 125 | struct amdgpu_bo bo; |
| 128 | 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 | 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 | 331 | int amdgpu_bo_validate(struct amdgpu_bo *bo); |
| 333 | 332 | void amdgpu_bo_get_memory(struct amdgpu_bo *bo, uint64_t *vram_mem, |
| 334 | 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 | 335 | int amdgpu_bo_restore_shadow(struct amdgpu_bo *shadow, |
| 337 | 336 | struct dma_fence **fence); |
| 338 | 337 | uint32_t amdgpu_bo_get_preferred_pin_domain(struct amdgpu_device *adev, |
| @@ -171,11 +171,81 @@ Err_out: · 170 unmodified lines | ||
| 171 | 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 | 242 | static int psp_sw_init(void *handle) |
| 175 | 243 | { |
| 176 | 244 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 177 | 245 | struct psp_context *psp = &adev->psp; |
| 178 | 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 | 250 | if (!amdgpu_sriov_vf(adev)) { |
| 181 | 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); | |
| 195 | − if (ret) { | |
| 196 | − DRM_ERROR("Failed to initialize memory training!\n"); | |
| 197 | − return ret; | |
| 264 | + memset(&boot_cfg_entry, 0, sizeof(boot_cfg_entry)); | |
| 265 | + if (psp_get_runtime_db_entry(adev, | |
| 266 | + PSP_RUNTIME_ENTRY_TYPE_BOOT_CONFIG, | |
| 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); | |
| 200 | − if (ret) { | |
| 201 | − DRM_ERROR("Failed to process memory training!\n"); | |
| 202 | − return ret; | |
| 284 | + | |
| 285 | + if (mem_training_ctx->enable_mem_training) { | |
| 286 | + ret = psp_memory_training_init(psp); | |
| 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 | 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 | 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 | 673 | struct psp_context *psp = &adev->psp; |
| 557 | 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 | 681 | cmd->cmd_id = GFX_CMD_ID_BOOT_CFG; |
| 565 | 682 | cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_SET; |
| 566 | − cmd->cmd.boot_cfg.boot_config = BOOT_CONFIG_GECC; | |
| 567 | − cmd->cmd.boot_cfg.boot_config_valid = BOOT_CONFIG_GECC; | |
| 683 | + cmd->cmd.boot_cfg.boot_config = boot_cfg; | |
| 684 | + cmd->cmd.boot_cfg.boot_config_valid = boot_cfg; | |
| 568 | 685 | |
| 569 | 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 | 1329 | static int psp_ras_initialize(struct psp_context *psp) |
| 1213 | 1330 | { |
| 1214 | 1331 | int ret; |
| 1332 | + uint32_t boot_cfg = 0xFF; | |
| 1333 | + struct amdgpu_device *adev = psp->adev; | |
| 1215 | 1334 | |
| 1216 | 1335 | /* |
| 1217 | 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 | 1339 | return 0; |
| 1221 | 1340 | |
| 1222 | − if (!psp->adev->psp.ta_ras_ucode_size || | |
| 1223 | − !psp->adev->psp.ta_ras_start_addr) { | |
| 1224 | − dev_info(psp->adev->dev, "RAS: optional ras ta ucode is not available\n"); | |
| 1341 | + if (!adev->psp.ta_ras_ucode_size || | |
| 1342 | + !adev->psp.ta_ras_start_addr) { | |
| 1343 | + dev_info(adev->dev, "RAS: optional ras ta ucode is not available\n"); | |
| 1225 | 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 | 1388 | if (!psp->ras.ras_initialized) { |
| 1229 | 1389 | ret = psp_ras_init_shared_buf(psp); |
| 1230 | 1390 | if (ret) |
| @@ -1945,12 +2105,6 @@ static int psp_hw_start(struct psp_context *psp) · 714 unmodified lines | ||
| 1945 | 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 | 2108 | ret = psp_tmr_init(psp); |
| 1955 | 2109 | if (ret) { |
| 1956 | 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 | 2342 | if ((amdgpu_in_reset(adev) && |
| 2189 | 2343 | ras && adev->ras_enabled && |
| 2190 | 2344 | (adev->asic_type == CHIP_ARCTURUS || |
| 2191 | − adev->asic_type == CHIP_VEGA20)) || | |
| 2192 | − (adev->in_runpm && | |
| 2193 | − adev->asic_type >= CHIP_NAVI10 && | |
| 2194 | − adev->asic_type <= CHIP_NAVI12)) { | |
| 2345 | + adev->asic_type == CHIP_VEGA20))) { | |
| 2195 | 2346 | ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD); |
| 2196 | 2347 | if (ret) { |
| 2197 | 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 | 2714 | DRM_INFO("PSP is resuming...\n"); |
| 2564 | 2715 | |
| 2565 | − ret = psp_mem_training(psp, PSP_MEM_TRAIN_RESUME); | |
| 2566 | − if (ret) { | |
| 2567 | − DRM_ERROR("Failed to process memory training!\n"); | |
| 2568 | − return ret; | |
| 2716 | + if (psp->mem_train_ctx.enable_mem_training) { | |
| 2717 | + ret = psp_mem_training(psp, PSP_MEM_TRAIN_RESUME); | |
| 2718 | + if (ret) { | |
| 2719 | + DRM_ERROR("Failed to process memory training!\n"); | |
| 2720 | + return ret; | |
| 2721 | + } | |
| 2569 | 2722 | } |
| 2570 | 2723 | |
| 2571 | 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 | 2903 | asd_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.asd_fw->data; |
| 2751 | 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 | 2906 | adev->psp.asd_ucode_size = le32_to_cpu(asd_hdr->header.ucode_size_bytes); |
| 2754 | 2907 | adev->psp.asd_start_addr = (uint8_t *)asd_hdr + |
| 2755 | 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 | 2939 | toc_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.toc_fw->data; |
| 2787 | 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 | 2942 | adev->psp.toc_bin_size = le32_to_cpu(toc_hdr->header.ucode_size_bytes); |
| 2790 | 2943 | adev->psp.toc_start_addr = (uint8_t *)toc_hdr + |
| 2791 | 2944 | le32_to_cpu(toc_hdr->header.ucode_array_offset_bytes); |
| @@ -2797,6 +2950,50 @@ out: · 5 unmodified lines | ||
| 2797 | 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 | 2997 | int psp_init_sos_microcode(struct psp_context *psp, |
| 2801 | 2998 | const char *chip_name) |
| 2802 | 2999 | { |
| @@ -2807,6 +3004,7 @@ int psp_init_sos_microcode(struct psp_context *psp, · 4 unmodified lines | ||
| 2807 | 3004 | const struct psp_firmware_header_v1_2 *sos_hdr_v1_2; |
| 2808 | 3005 | const struct psp_firmware_header_v1_3 *sos_hdr_v1_3; |
| 2809 | 3006 | int err = 0; |
| 3007 | + uint8_t *ucode_array_start_addr; | |
| 2810 | 3008 | |
| 2811 | 3009 | if (!chip_name) { |
| 2812 | 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 | 3021 | goto out; |
| 2824 | 3022 | |
| 2825 | 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 | 3026 | amdgpu_ucode_print_psp_hdr(&sos_hdr->header); |
| 2827 | 3027 | |
| 2828 | 3028 | switch (sos_hdr->header.header_version_major) { |
| 2829 | 3029 | case 1: |
| 2830 | − adev->psp.sos_fw_version = le32_to_cpu(sos_hdr->header.ucode_version); | |
| 2831 | − adev->psp.sos_feature_version = le32_to_cpu(sos_hdr->ucode_feature_version); | |
| 2832 | − adev->psp.sos_bin_size = le32_to_cpu(sos_hdr->sos_size_bytes); | |
| 2833 | − adev->psp.sys_bin_size = le32_to_cpu(sos_hdr->sos_offset_bytes); | |
| 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); | |
| 3030 | + err = psp_init_sos_base_fw(adev); | |
| 3031 | + if (err) | |
| 3032 | + goto out; | |
| 3033 | + | |
| 2838 | 3034 | if (sos_hdr->header.header_version_minor == 1) { |
| 2839 | 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 | 3037 | adev->psp.toc_start_addr = (uint8_t *)adev->psp.sys_start_addr + |
| 2842 | − 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); | |
| 3038 | + le32_to_cpu(sos_hdr_v1_1->toc.offset_bytes); | |
| 3039 | + adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_1->kdb.size_bytes); | |
| 2844 | 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 | 3043 | if (sos_hdr->header.header_version_minor == 2) { |
| 2848 | 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 | 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 | 3049 | if (sos_hdr->header.header_version_minor == 3) { |
| 2854 | 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); | |
| 2856 | − adev->psp.toc_start_addr = (uint8_t *)adev->psp.sys_start_addr + | |
| 2857 | − 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); | |
| 2859 | − adev->psp.kdb_start_addr = (uint8_t *)adev->psp.sys_start_addr + | |
| 2860 | − 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); | |
| 2862 | − adev->psp.spl_start_addr = (uint8_t *)adev->psp.sys_start_addr + | |
| 2863 | − 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); | |
| 2865 | − adev->psp.rl_start_addr = (uint8_t *)adev->psp.sys_start_addr + | |
| 2866 | − le32_to_cpu(sos_hdr_v1_3->rl_offset_bytes); | |
| 3051 | + adev->psp.toc_bin_size = le32_to_cpu(sos_hdr_v1_3->v1_1.toc.size_bytes); | |
| 3052 | + adev->psp.toc_start_addr = ucode_array_start_addr + | |
| 3053 | + le32_to_cpu(sos_hdr_v1_3->v1_1.toc.offset_bytes); | |
| 3054 | + adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.size_bytes); | |
| 3055 | + adev->psp.kdb_start_addr = ucode_array_start_addr + | |
| 3056 | + le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.offset_bytes); | |
| 3057 | + adev->psp.spl_bin_size = le32_to_cpu(sos_hdr_v1_3->spl.size_bytes); | |
| 3058 | + adev->psp.spl_start_addr = ucode_array_start_addr + | |
| 3059 | + le32_to_cpu(sos_hdr_v1_3->spl.offset_bytes); | |
| 3060 | + adev->psp.rl_bin_size = le32_to_cpu(sos_hdr_v1_3->rl.size_bytes); | |
| 3061 | + adev->psp.rl_start_addr = ucode_array_start_addr + | |
| 3062 | + le32_to_cpu(sos_hdr_v1_3->rl.offset_bytes); | |
| 2867 | 3063 | } |
| 2868 | 3064 | break; |
| 2869 | 3065 | default: |
| @@ -225,6 +225,61 @@ struct psp_memory_training_context { · 224 unmodified lines | ||
| 225 | 225 | |
| 226 | 226 | enum psp_memory_training_init_flag init; |
| 227 | 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 | 285 | struct psp_context |
| @@ -325,6 +380,8 @@ struct psp_context · 94 unmodified lines | ||
| 325 | 380 | struct psp_securedisplay_context securedisplay_context; |
| 326 | 381 | struct mutex mutex; |
| 327 | 382 | struct psp_memory_training_context mem_train_ctx; |
| 383 | + | |
| 384 | + uint32_t boot_cfg_bitmask; | |
| 328 | 385 | }; |
| 329 | 386 | |
| 330 | 387 | struct amdgpu_psp_funcs { |
| @@ -2122,7 +2122,7 @@ static void amdgpu_ras_counte_dw(struct work_struct *work) · 2121 unmodified lines | ||
| 2122 | 2122 | struct amdgpu_ras *con = container_of(work, struct amdgpu_ras, |
| 2123 | 2123 | ras_counte_delay_work.work); |
| 2124 | 2124 | struct amdgpu_device *adev = con->adev; |
| 2125 | − struct drm_device *dev = &adev->ddev; | |
| 2125 | + struct drm_device *dev = adev_to_drm(adev); | |
| 2126 | 2126 | unsigned long ce_count, ue_count; |
| 2127 | 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 | 257 | container_of(hdr, struct psp_firmware_header_v1_0, header); |
| 258 | 258 | |
| 259 | 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 | 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 | 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 | 265 | if (version_minor == 1) { |
| 266 | 266 | const struct psp_firmware_header_v1_1 *psp_hdr_v1_1 = |
| 267 | 267 | container_of(psp_hdr, struct psp_firmware_header_v1_1, v1_0); |
| 268 | 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 | 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 | 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 | 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 | 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 | 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 | 281 | if (version_minor == 2) { |
| 282 | 282 | const struct psp_firmware_header_v1_2 *psp_hdr_v1_2 = |
| 283 | 283 | container_of(psp_hdr, struct psp_firmware_header_v1_2, v1_0); |
| 284 | 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 | 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 | 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 | 291 | if (version_minor == 3) { |
| 292 | 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 | 294 | const struct psp_firmware_header_v1_3 *psp_hdr_v1_3 = |
| 295 | 295 | container_of(psp_hdr_v1_1, struct psp_firmware_header_v1_3, v1_1); |
| 296 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 315 | } else { |
| 316 | 316 | DRM_ERROR("Unknown PSP ucode version: %u.%u\n", |
| @@ -71,43 +71,39 @@ struct smc_firmware_header_v2_1 { · 70 unmodified lines | ||
| 71 | 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 | 80 | /* version_major=1, version_minor=0 */ |
| 75 | 81 | struct psp_firmware_header_v1_0 { |
| 76 | 82 | struct common_firmware_header header; |
| 77 | − uint32_t ucode_feature_version; | |
| 78 | − uint32_t sos_offset_bytes; | |
| 79 | − uint32_t sos_size_bytes; | |
| 83 | + struct psp_fw_bin_desc sos; | |
| 80 | 84 | }; |
| 81 | 85 | |
| 82 | 86 | /* version_major=1, version_minor=1 */ |
| 83 | 87 | struct psp_firmware_header_v1_1 { |
| 84 | 88 | struct psp_firmware_header_v1_0 v1_0; |
| 85 | − uint32_t toc_header_version; | |
| 86 | − uint32_t toc_offset_bytes; | |
| 87 | − uint32_t toc_size_bytes; | |
| 88 | − uint32_t kdb_header_version; | |
| 89 | − uint32_t kdb_offset_bytes; | |
| 90 | − uint32_t kdb_size_bytes; | |
| 89 | + struct psp_fw_bin_desc toc; | |
| 90 | + struct psp_fw_bin_desc kdb; | |
| 91 | 91 | }; |
| 92 | 92 | |
| 93 | 93 | /* version_major=1, version_minor=2 */ |
| 94 | 94 | struct psp_firmware_header_v1_2 { |
| 95 | 95 | struct psp_firmware_header_v1_0 v1_0; |
| 96 | − uint32_t reserve[3]; | |
| 97 | − uint32_t kdb_header_version; | |
| 98 | − uint32_t kdb_offset_bytes; | |
| 99 | − uint32_t kdb_size_bytes; | |
| 96 | + struct psp_fw_bin_desc res; | |
| 97 | + struct psp_fw_bin_desc kdb; | |
| 100 | 98 | }; |
| 101 | 99 | |
| 102 | 100 | /* version_major=1, version_minor=3 */ |
| 103 | 101 | struct psp_firmware_header_v1_3 { |
| 104 | 102 | struct psp_firmware_header_v1_1 v1_1; |
| 105 | − uint32_t spl_header_version; | |
| 106 | − uint32_t spl_offset_bytes; | |
| 107 | − uint32_t spl_size_bytes; | |
| 108 | − uint32_t rl_header_version; | |
| 109 | − uint32_t rl_offset_bytes; | |
| 110 | − uint32_t rl_size_bytes; | |
| 103 | + struct psp_fw_bin_desc spl; | |
| 104 | + struct psp_fw_bin_desc rl; | |
| 105 | + struct psp_fw_bin_desc sys_drv_aux; | |
| 106 | + struct psp_fw_bin_desc sos_aux; | |
| 111 | 107 | }; |
| 112 | 108 | |
| 113 | 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 | 332 | base->next = bo->vm_bo; |
| 333 | 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 | 336 | return; |
| 337 | 337 | |
| 338 | 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 | 361 | * Helper to get the parent entry for the child page table. NULL if we are at |
| 362 | 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 | 368 | if (!parent) |
| 369 | 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 | 377 | struct amdgpu_vm_pt_cursor { |
| 378 | 378 | uint64_t pfn; |
| 379 | − struct amdgpu_vm_pt *parent; | |
| 380 | − struct amdgpu_vm_pt *entry; | |
| 379 | + struct amdgpu_vm_bo_base *parent; | |
| 380 | + struct amdgpu_vm_bo_base *entry; | |
| 381 | 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 | 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 | 421 | return false; |
| 421 | 422 | |
| 422 | − BUG_ON(!cursor->entry->base.bo); | |
| 423 | 423 | mask = amdgpu_vm_entries_mask(adev, cursor->level); |
| 424 | 424 | shift = amdgpu_vm_level_shift(adev, cursor->level); |
| 425 | 425 | |
| 426 | 426 | ++cursor->level; |
| 427 | 427 | idx = (cursor->pfn >> shift) & mask; |
| 428 | 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 | 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 | 453 | shift = amdgpu_vm_level_shift(adev, cursor->level - 1); |
| 454 | 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 | 457 | return false; |
| 458 | 458 | |
| 459 | 459 | cursor->pfn += 1ULL << shift; |
| @@ -539,7 +539,7 @@ static void amdgpu_vm_pt_first_dfs(struct amdgpu_device *adev, · 79 unmodified lines | ||
| 539 | 539 | * True when the search should continue, false otherwise. |
| 540 | 540 | */ |
| 541 | 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 | 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 | 590 | struct amdgpu_bo_list_entry *entry) |
| 591 | 591 | { |
| 592 | 592 | entry->priority = 0; |
| 593 | − entry->tv.bo = &vm->root.base.bo->tbo; | |
| 593 | + entry->tv.bo = &vm->root.bo->tbo; | |
| 594 | 594 | /* Two for VM updates, one for TTM and one for the CS job */ |
| 595 | 595 | entry->tv.num_shared = 4; |
| 596 | 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 | 622 | for (bo_base = abo->vm_bo; bo_base; bo_base = bo_base->next) { |
| 623 | 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 | 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 | 781 | entries -= ats_entries; |
| 782 | 782 | |
| 783 | 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 | 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 | 789 | ats_entries = 0; |
| 790 | 790 | } else { |
| 791 | 791 | ats_entries = entries; |
| @@ -902,8 +902,8 @@ static int amdgpu_vm_pt_create(struct amdgpu_device *adev, · 110 unmodified lines | ||
| 902 | 902 | |
| 903 | 903 | bp.type = ttm_bo_type_kernel; |
| 904 | 904 | bp.no_wait_gpu = immediate; |
| 905 | − if (vm->root.base.bo) | |
| 906 | − bp.resv = vm->root.base.bo->tbo.base.resv; | |
| 905 | + if (vm->root.bo) | |
| 906 | + bp.resv = vm->root.bo->tbo.base.resv; | |
| 907 | 907 | |
| 908 | 908 | r = amdgpu_bo_create_vm(adev, &bp, vmbo); |
| 909 | 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 | 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 | 943 | return 0; |
| 944 | 944 | } |
| @@ -962,19 +962,13 @@ static int amdgpu_vm_alloc_pts(struct amdgpu_device *adev, · 17 unmodified lines | ||
| 962 | 962 | struct amdgpu_vm_pt_cursor *cursor, |
| 963 | 963 | bool immediate) |
| 964 | 964 | { |
| 965 | − struct amdgpu_vm_pt *entry = cursor->entry; | |
| 965 | + struct amdgpu_vm_bo_base *entry = cursor->entry; | |
| 966 | 966 | struct amdgpu_bo *pt_bo; |
| 967 | 967 | struct amdgpu_bo_vm *pt; |
| 968 | 968 | int r; |
| 969 | 969 | |
| 970 | − if (entry->base.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; | |
| 970 | + if (entry->bo) | |
| 976 | 971 | return 0; |
| 977 | − } | |
| 978 | 972 | |
| 979 | 973 | r = amdgpu_vm_pt_create(adev, vm, cursor->level, immediate, &pt); |
| 980 | 974 | if (r) |
| @@ -984,13 +978,8 @@ static int amdgpu_vm_alloc_pts(struct amdgpu_device *adev, · 3 unmodified lines | ||
| 984 | 978 | * freeing them up in the wrong order. |
| 985 | 979 | */ |
| 986 | 980 | pt_bo = &pt->bo; |
| 987 | − pt_bo->parent = amdgpu_bo_ref(cursor->parent->base.bo); | |
| 988 | − amdgpu_vm_bo_base_init(&entry->base, vm, pt_bo); | |
| 989 | − if (cursor->level < AMDGPU_VM_PTB) | |
| 990 | − entry->entries = pt->entries; | |
| 991 | − else | |
| 992 | − entry->entries = NULL; | |
| 993 | − | |
| 981 | + pt_bo->parent = amdgpu_bo_ref(cursor->parent->bo); | |
| 982 | + amdgpu_vm_bo_base_init(entry, vm, pt_bo); | |
| 994 | 983 | r = amdgpu_vm_clear_bo(adev, vm, pt, immediate); |
| 995 | 984 | if (r) |
| 996 | 985 | goto error_free_pt; |
| @@ -1008,18 +997,17 @@ error_free_pt: · 11 unmodified lines | ||
| 1008 | 997 | * |
| 1009 | 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 | 1002 | struct amdgpu_bo *shadow; |
| 1014 | 1003 | |
| 1015 | − if (entry->base.bo) { | |
| 1016 | − shadow = amdgpu_bo_shadowed(entry->base.bo); | |
| 1017 | − entry->base.bo->vm_bo = NULL; | |
| 1018 | − list_del(&entry->base.vm_status); | |
| 1019 | − amdgpu_bo_unref(&shadow); | |
| 1020 | − amdgpu_bo_unref(&entry->base.bo); | |
| 1021 | − } | |
| 1022 | − entry->entries = NULL; | |
| 1004 | + if (!entry->bo) | |
| 1005 | + return; | |
| 1006 | + shadow = amdgpu_bo_shadowed(entry->bo); | |
| 1007 | + entry->bo->vm_bo = NULL; | |
| 1008 | + list_del(&entry->vm_status); | |
| 1009 | + amdgpu_bo_unref(&shadow); | |
| 1010 | + amdgpu_bo_unref(&entry->bo); | |
| 1023 | 1011 | } |
| 1024 | 1012 | |
| 1025 | 1013 | /** |
| @@ -1036,7 +1024,7 @@ static void amdgpu_vm_free_pts(struct amdgpu_device *adev, · 10 unmodified lines | ||
| 1036 | 1024 | struct amdgpu_vm_pt_cursor *start) |
| 1037 | 1025 | { |
| 1038 | 1026 | struct amdgpu_vm_pt_cursor cursor; |
| 1039 | − struct amdgpu_vm_pt *entry; | |
| 1027 | + struct amdgpu_vm_bo_base *entry; | |
| 1040 | 1028 | |
| 1041 | 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 | 1293 | static int amdgpu_vm_update_pde(struct amdgpu_vm_update_params *params, |
| 1306 | 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); | |
| 1310 | − struct amdgpu_bo *bo = parent->base.bo, *pbo; | |
| 1297 | + struct amdgpu_vm_bo_base *parent = amdgpu_vm_pt_parent(entry); | |
| 1298 | + struct amdgpu_bo *bo = parent->bo, *pbo; | |
| 1311 | 1299 | uint64_t pde, pt, flags; |
| 1312 | 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 | 1303 | pbo = pbo->parent; |
| 1316 | 1304 | |
| 1317 | 1305 | level += params->adev->vm_manager.root_level; |
| 1318 | − amdgpu_gmc_get_pde_for_bo(entry->base.bo, level, &pt, &flags); | |
| 1319 | − pde = (entry - parent->entries) * 8; | |
| 1306 | + amdgpu_gmc_get_pde_for_bo(entry->bo, level, &pt, &flags); | |
| 1307 | + pde = (entry - to_amdgpu_bo_vm(parent->bo)->entries) * 8; | |
| 1320 | 1308 | return vm->update_funcs->update(params, to_amdgpu_bo_vm(bo), pde, pt, |
| 1321 | 1309 | 1, 0, flags); |
| 1322 | 1310 | } |
| @@ -1333,11 +1321,11 @@ static void amdgpu_vm_invalidate_pds(struct amdgpu_device *adev, · 10 unmodified lines | ||
| 1333 | 1321 | struct amdgpu_vm *vm) |
| 1334 | 1322 | { |
| 1335 | 1323 | struct amdgpu_vm_pt_cursor cursor; |
| 1336 | − struct amdgpu_vm_pt *entry; | |
| 1324 | + struct amdgpu_vm_bo_base *entry; | |
| 1337 | 1325 | |
| 1338 | 1326 | for_each_amdgpu_vm_pt_dfs_safe(adev, vm, NULL, cursor, entry) |
| 1339 | − if (entry->base.bo && !entry->base.moved) | |
| 1340 | − amdgpu_vm_bo_relocated(&entry->base); | |
| 1327 | + if (entry->bo && !entry->moved) | |
| 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 | 1359 | return r; |
| 1372 | 1360 | |
| 1373 | 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, | |
| 1377 | − base.vm_status); | |
| 1378 | − amdgpu_vm_bo_idle(&entry->base); | |
| 1364 | + entry = list_first_entry(&vm->relocated, | |
| 1365 | + struct amdgpu_vm_bo_base, | |
| 1366 | + vm_status); | |
| 1367 | + amdgpu_vm_bo_idle(entry); | |
| 1379 | 1368 | |
| 1380 | 1369 | r = amdgpu_vm_update_pde(¶ms, vm, entry); |
| 1381 | 1370 | if (r) |
| @@ -1555,7 +1544,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_vm_update_params *params, · 173 unmodified lines | ||
| 1555 | 1544 | continue; |
| 1556 | 1545 | } |
| 1557 | 1546 | |
| 1558 | − pt = cursor.entry->base.bo; | |
| 1547 | + pt = cursor.entry->bo; | |
| 1559 | 1548 | if (!pt) { |
| 1560 | 1549 | /* We need all PDs and PTs for mapping something, */ |
| 1561 | 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 | 1556 | if (!amdgpu_vm_pt_ancestor(&cursor)) |
| 1568 | 1557 | return -EINVAL; |
| 1569 | 1558 | |
| 1570 | − pt = cursor.entry->base.bo; | |
| 1559 | + pt = cursor.entry->bo; | |
| 1571 | 1560 | shift = parent_shift; |
| 1572 | 1561 | frag_end = max(frag_end, ALIGN(frag_start + 1, |
| 1573 | 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 | 1612 | while (cursor.pfn < frag_start) { |
| 1624 | 1613 | /* Make sure previous mapping is freed */ |
| 1625 | − if (cursor.entry->base.bo) { | |
| 1614 | + if (cursor.entry->bo) { | |
| 1626 | 1615 | params->table_freed = true; |
| 1627 | 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 | 1693 | if (!unlocked && !dma_fence_is_signaled(vm->last_unlocked)) { |
| 1705 | 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 | 1697 | swap(vm->last_unlocked, tmp); |
| 1709 | 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 | 1840 | if (clear || !bo) { |
| 1852 | 1841 | mem = NULL; |
| 1853 | − resv = vm->root.base.bo->tbo.base.resv; | |
| 1842 | + resv = vm->root.bo->tbo.base.resv; | |
| 1854 | 1843 | } else { |
| 1855 | 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 | 1872 | if (clear || (bo && bo->tbo.base.resv == |
| 1884 | − vm->root.base.bo->tbo.base.resv)) | |
| 1873 | + vm->root.bo->tbo.base.resv)) | |
| 1885 | 1874 | last_update = &vm->last_update; |
| 1886 | 1875 | else |
| 1887 | 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 | 1912 | * the evicted list so that it gets validated again on the |
| 1924 | 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 | 1916 | uint32_t mem_type = bo->tbo.resource->mem_type; |
| 1928 | 1917 | |
| 1929 | 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 | 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 | 2053 | struct dma_fence *excl, **shared; |
| 2065 | 2054 | unsigned i, shared_count; |
| 2066 | 2055 | int r; |
| @@ -2106,7 +2095,7 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev, · 39 unmodified lines | ||
| 2106 | 2095 | struct amdgpu_vm *vm, |
| 2107 | 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 | 2099 | struct amdgpu_bo_va_mapping *mapping; |
| 2111 | 2100 | uint64_t init_pte_value = 0; |
| 2112 | 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 | 2254 | if (mapping->flags & AMDGPU_PTE_PRT) |
| 2266 | 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 | 2258 | !bo_va->base.moved) { |
| 2270 | 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 | 2616 | struct amdgpu_vm_bo_base **base; |
| 2628 | 2617 | |
| 2629 | 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 | 2620 | vm->bulk_moveable = false; |
| 2632 | 2621 | |
| 2633 | 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 | 2710 | for (bo_base = bo->vm_bo; bo_base; bo_base = bo_base->next) { |
| 2722 | 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 | 2714 | amdgpu_vm_bo_evicted(bo_base); |
| 2726 | 2715 | continue; |
| 2727 | 2716 | } |
| @@ -2732,7 +2721,7 @@ void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev, · 4 unmodified lines | ||
| 2732 | 2721 | |
| 2733 | 2722 | if (bo->tbo.type == ttm_bo_type_kernel) |
| 2734 | 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 | 2725 | amdgpu_vm_bo_moved(bo_base); |
| 2737 | 2726 | else |
| 2738 | 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 | 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 | 2855 | true, timeout); |
| 2867 | 2856 | if (timeout <= 0) |
| 2868 | 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 | 2937 | if (r) |
| 2949 | 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 | 2942 | r = amdgpu_vm_clear_bo(adev, vm, root, false); |
| 2954 | 2943 | if (r) |
| 2955 | 2944 | goto error_unreserve; |
| 2956 | 2945 | |
| 2957 | − amdgpu_bo_unreserve(vm->root.base.bo); | |
| 2946 | + amdgpu_bo_unreserve(vm->root.bo); | |
| 2958 | 2947 | |
| 2959 | 2948 | if (pasid) { |
| 2960 | 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 | 2963 | return 0; |
| 2975 | 2964 | |
| 2976 | 2965 | error_unreserve: |
| 2977 | − amdgpu_bo_unreserve(vm->root.base.bo); | |
| 2966 | + amdgpu_bo_unreserve(vm->root.bo); | |
| 2978 | 2967 | |
| 2979 | 2968 | error_free_root: |
| 2980 | 2969 | amdgpu_bo_unref(&root->shadow); |
| 2981 | 2970 | amdgpu_bo_unref(&root_bo); |
| 2982 | − vm->root.base.bo = NULL; | |
| 2971 | + vm->root.bo = NULL; | |
| 2983 | 2972 | |
| 2984 | 2973 | error_free_delayed: |
| 2985 | 2974 | dma_fence_put(vm->last_unlocked); |
| @@ -3005,17 +2994,14 @@ error_free_immediate: · 19 unmodified lines | ||
| 3005 | 2994 | * 0 if this VM is clean |
| 3006 | 2995 | */ |
| 3007 | 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 | 2999 | enum amdgpu_vm_level root = adev->vm_manager.root_level; |
| 3011 | 3000 | unsigned int entries = amdgpu_vm_num_entries(adev, root); |
| 3012 | 3001 | unsigned int i = 0; |
| 3013 | 3002 | |
| 3014 | − if (!(vm->root.entries)) | |
| 3015 | − return 0; | |
| 3016 | − | |
| 3017 | 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 | 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 | 3035 | bool pte_support_ats = (adev->asic_type == CHIP_RAVEN); |
| 3050 | 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 | 3039 | if (r) |
| 3054 | 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 | 3063 | if (pte_support_ats != vm->pte_support_ats) { |
| 3078 | 3064 | vm->pte_support_ats = pte_support_ats; |
| 3079 | 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 | 3067 | false); |
| 3082 | 3068 | if (r) |
| 3083 | 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 | 3081 | if (vm->use_cpu_for_update) { |
| 3096 | 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 | 3084 | AMDGPU_FENCE_OWNER_UNDEFINED, true); |
| 3099 | 3085 | if (r) |
| 3100 | 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 | 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 | 3113 | if (pasid) |
| 3128 | 3114 | vm->pasid = pasid; |
| @@ -3138,7 +3124,7 @@ free_idr: · 9 unmodified lines | ||
| 3138 | 3124 | spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); |
| 3139 | 3125 | } |
| 3140 | 3126 | unreserve_bo: |
| 3141 | − amdgpu_bo_unreserve(vm->root.base.bo); | |
| 3127 | + amdgpu_bo_unreserve(vm->root.bo); | |
| 3142 | 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 | 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 | 3171 | amdgpu_bo_reserve(root, true); |
| 3186 | 3172 | if (vm->pasid) { |
| 3187 | 3173 | unsigned long flags; |
| @@ -3208,7 +3194,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) · 20 unmodified lines | ||
| 3208 | 3194 | amdgpu_vm_free_pts(adev, vm, NULL); |
| 3209 | 3195 | amdgpu_bo_unreserve(root); |
| 3210 | 3196 | amdgpu_bo_unref(&root); |
| 3211 | − WARN_ON(vm->root.base.bo); | |
| 3197 | + WARN_ON(vm->root.bo); | |
| 3212 | 3198 | |
| 3213 | 3199 | drm_sched_entity_destroy(&vm->immediate); |
| 3214 | 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 | 3311 | /* Wait vm idle to make sure the vmid set in SPM_VMID is |
| 3326 | 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 | 3315 | if (r) |
| 3330 | 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 | 3319 | if (r < 0) |
| 3334 | 3320 | return r; |
| 3335 | 3321 | |
| 3336 | − amdgpu_bo_unreserve(fpriv->vm.root.base.bo); | |
| 3322 | + amdgpu_bo_unreserve(fpriv->vm.root.bo); | |
| 3337 | 3323 | amdgpu_vmid_free_reserved(adev, &fpriv->vm, AMDGPU_GFXHUB_0); |
| 3338 | 3324 | break; |
| 3339 | 3325 | default: |
| @@ -3399,19 +3385,20 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, · 59 unmodified lines | ||
| 3399 | 3385 | { |
| 3400 | 3386 | bool is_compute_context = false; |
| 3401 | 3387 | struct amdgpu_bo *root; |
| 3388 | + unsigned long irqflags; | |
| 3402 | 3389 | uint64_t value, flags; |
| 3403 | 3390 | struct amdgpu_vm *vm; |
| 3404 | 3391 | int r; |
| 3405 | 3392 | |
| 3406 | − spin_lock(&adev->vm_manager.pasid_lock); | |
| 3393 | + spin_lock_irqsave(&adev->vm_manager.pasid_lock, irqflags); | |
| 3407 | 3394 | vm = idr_find(&adev->vm_manager.pasid_idr, pasid); |
| 3408 | 3395 | if (vm) { |
| 3409 | − root = amdgpu_bo_ref(vm->root.base.bo); | |
| 3396 | + root = amdgpu_bo_ref(vm->root.bo); | |
| 3410 | 3397 | is_compute_context = vm->is_compute_context; |
| 3411 | 3398 | } else { |
| 3412 | 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 | 3403 | if (!root) |
| 3417 | 3404 | return false; |
| @@ -3429,11 +3416,11 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, · 11 unmodified lines | ||
| 3429 | 3416 | goto error_unref; |
| 3430 | 3417 | |
| 3431 | 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 | 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 | 3422 | vm = NULL; |
| 3436 | − spin_unlock(&adev->vm_manager.pasid_lock); | |
| 3423 | + spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, irqflags); | |
| 3437 | 3424 | if (!vm) |
| 3438 | 3425 | goto error_unlock; |
| 3439 | 3426 | |
| @@ -152,13 +152,6 @@ struct amdgpu_vm_bo_base { · 151 unmodified lines | ||
| 152 | 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 | 155 | /* provided by hw blocks that can write ptes, e.g., sdma */ |
| 163 | 156 | struct amdgpu_vm_pte_funcs { |
| 164 | 157 | /* number of dw to reserve per operation */ |
| @@ -284,7 +277,7 @@ struct amdgpu_vm { · 119 unmodified lines | ||
| 284 | 277 | struct list_head done; |
| 285 | 278 | |
| 286 | 279 | /* contains the page directory */ |
| 287 | − struct amdgpu_vm_pt root; | |
| 280 | + struct amdgpu_vm_bo_base root; | |
| 288 | 281 | struct dma_fence *last_update; |
| 289 | 282 | |
| 290 | 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 | 112 | swap(p->vm->last_unlocked, f); |
| 113 | 113 | dma_fence_put(tmp); |
| 114 | 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 | 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 | 6970 | if (ring->use_doorbell) { |
| 6971 | 6971 | WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER, |
| 6972 | 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 | 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 | 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 | 3675 | if (ring->use_doorbell) { |
| 3676 | 3676 | WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER, |
| 3677 | 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 | 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 | 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 | 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 | 340 | /* Union of command-specific responses for GPCOM ring. */ |
| 336 | −union psp_gfx_uresp | |
| 337 | −{ | |
| 338 | − struct psp_gfx_uresp_reserved reserved; | |
| 339 | − struct psp_gfx_uresp_fwar_db_info fwar_db_info; | |
| 341 | +union psp_gfx_uresp { | |
| 342 | + struct psp_gfx_uresp_reserved reserved; | |
| 343 | + struct psp_gfx_uresp_bootcfg boot_cfg; | |
| 344 | + struct psp_gfx_uresp_fwar_db_info fwar_db_info; | |
| 340 | 345 | }; |
| 341 | 346 | |
| 342 | 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 | 461 | struct amdgpu_device *adev = psp->adev; |
| 462 | 462 | |
| 463 | 463 | if (amdgpu_sriov_vf(adev)) { |
| 464 | + ring->ring_wptr = 0; | |
| 464 | 465 | ret = psp_v11_0_ring_stop(psp, ring_type); |
| 465 | 466 | if (ret) { |
| 466 | 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 | 227 | psp_v3_1_reroute_ih(psp); |
| 228 | 228 | |
| 229 | 229 | if (amdgpu_sriov_vf(adev)) { |
| 230 | + ring->ring_wptr = 0; | |
| 230 | 231 | ret = psp_v3_1_ring_stop(psp, ring_type); |
| 231 | 232 | if (ret) { |
| 232 | 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 | 1566 | i, args->n_devices); |
| 1567 | 1567 | goto unmap_memory_from_gpu_failed; |
| 1568 | 1568 | } |
| 1569 | − kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT); | |
| 1570 | 1569 | args->n_success = i+1; |
| 1571 | 1570 | } |
| 1572 | − kfree(devices_arr); | |
| 1573 | − | |
| 1574 | 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 | 1592 | return 0; |
| 1577 | 1593 | |
| 1578 | 1594 | bind_process_to_device_failed: |
| @@ -1580,6 +1596,7 @@ get_mem_obj_from_handle_failed: · 1 unmodified line | ||
| 1580 | 1596 | unmap_memory_from_gpu_failed: |
| 1581 | 1597 | mutex_unlock(&p->mutex); |
| 1582 | 1598 | copy_from_user_failed: |
| 1599 | +sync_memory_failed: | |
| 1583 | 1600 | kfree(devices_arr); |
| 1584 | 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 | 1797 | struct kfd_ioctl_svm_args *args = data; |
| 1781 | 1798 | int r = 0; |
| 1782 | 1799 | |
| 1783 | − if (p->svm_disabled) | |
| 1784 | − return -EPERM; | |
| 1785 | − | |
| 1786 | 1800 | pr_debug("start 0x%llx size 0x%llx op 0x%x nattr 0x%x\n", |
| 1787 | 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 | 486 | if (retval == -ETIME) |
| 487 | 487 | qpd->reset_wavefronts = true; |
| 488 | 488 | |
| 489 | − | |
| 490 | − mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); | |
| 491 | − | |
| 492 | 489 | list_del(&q->list); |
| 493 | 490 | if (list_empty(&qpd->queues_list)) { |
| 494 | 491 | if (qpd->reset_wavefronts) { |
| @@ -523,6 +520,8 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm, · 28 unmodified lines | ||
| 523 | 520 | int retval; |
| 524 | 521 | uint64_t sdma_val = 0; |
| 525 | 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 | 526 | /* Get the SDMA queue stats */ |
| 528 | 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 | 539 | pdd->sdma_past_activity_counter += sdma_val; |
| 541 | 540 | dqm_unlock(dqm); |
| 542 | 541 | |
| 542 | + mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); | |
| 543 | + | |
| 543 | 544 | return retval; |
| 544 | 545 | } |
| 545 | 546 | |
| @@ -1629,7 +1630,7 @@ out: · 1083 unmodified lines | ||
| 1629 | 1630 | static int process_termination_nocpsch(struct device_queue_manager *dqm, |
| 1630 | 1631 | struct qcm_process_device *qpd) |
| 1631 | 1632 | { |
| 1632 | − struct queue *q, *next; | |
| 1633 | + struct queue *q; | |
| 1633 | 1634 | struct device_process_node *cur, *next_dpn; |
| 1634 | 1635 | int retval = 0; |
| 1635 | 1636 | bool found = false; |
| @@ -1637,12 +1638,19 @@ static int process_termination_nocpsch(struct device_queue_manager *dqm, · 1 unmodified line | ||
| 1637 | 1638 | dqm_lock(dqm); |
| 1638 | 1639 | |
| 1639 | 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 | 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 | 1648 | ret = destroy_queue_nocpsch_locked(dqm, qpd, q); |
| 1644 | 1649 | if (ret) |
| 1645 | 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 | 1656 | /* Unregister process */ |
| @@ -1674,29 +1682,27 @@ static int get_wave_state(struct device_queue_manager *dqm, · 25 unmodified lines | ||
| 1674 | 1682 | u32 *save_area_used_size) |
| 1675 | 1683 | { |
| 1676 | 1684 | struct mqd_manager *mqd_mgr; |
| 1677 | − int r; | |
| 1678 | 1685 | |
| 1679 | 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 | 1688 | mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_CP]; |
| 1688 | 1689 | |
| 1689 | − if (!mqd_mgr->get_wave_state) { | |
| 1690 | − r = -EINVAL; | |
| 1691 | − goto dqm_unlock; | |
| 1690 | + if (q->properties.type != KFD_QUEUE_TYPE_COMPUTE || | |
| 1691 | + q->properties.is_active || !q->device->cwsr_enabled || | |
| 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 | 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 | 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 | 405 | case CHIP_POLARIS12: |
| 406 | 406 | case CHIP_VEGAM: |
| 407 | 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 | 408 | break; |
| 413 | 409 | case CHIP_VEGA10: |
| 414 | 410 | case CHIP_VEGA12: |
| @@ -743,6 +743,7 @@ struct svm_range_list { · 742 unmodified lines | ||
| 743 | 743 | spinlock_t deferred_list_lock; |
| 744 | 744 | atomic_t evicted_ranges; |
| 745 | 745 | struct delayed_work restore_work; |
| 746 | + DECLARE_BITMAP(bitmap_supported, MAX_GPU_INSTANCE); | |
| 746 | 747 | }; |
| 747 | 748 | |
| 748 | 749 | /* Process data */ |
| @@ -826,7 +827,6 @@ struct kfd_process { · 77 unmodified lines | ||
| 826 | 827 | |
| 827 | 828 | /* shared virtual memory registered by this process */ |
| 828 | 829 | struct svm_range_list svms; |
| 829 | − bool svm_disabled; | |
| 830 | 830 | |
| 831 | 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 | 1260 | process->mm = thread->mm; |
| 1261 | 1261 | process->lead_thread = thread->group_leader; |
| 1262 | 1262 | process->n_pdds = 0; |
| 1263 | − process->svm_disabled = false; | |
| 1264 | 1263 | INIT_DELAYED_WORK(&process->eviction_work, evict_process_worker); |
| 1265 | 1264 | INIT_DELAYED_WORK(&process->restore_work, restore_process_worker); |
| 1266 | 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 | 282 | p = container_of(svms, struct kfd_process, svms); |
| 283 | 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 | 287 | svm_range_set_default_attributes(&prange->preferred_loc, |
| 287 | 288 | &prange->prefetch_loc, |
| @@ -577,36 +578,25 @@ svm_range_check_attr(struct kfd_process *p, · 289 unmodified lines | ||
| 577 | 578 | uint32_t nattr, struct kfd_ioctl_svm_attribute *attrs) |
| 578 | 579 | { |
| 579 | 580 | uint32_t i; |
| 580 | − int gpuidx; | |
| 581 | 581 | |
| 582 | 582 | for (i = 0; i < nattr; i++) { |
| 583 | + uint32_t val = attrs[i].value; | |
| 584 | + int gpuidx = MAX_GPU_INSTANCE; | |
| 585 | + | |
| 583 | 586 | switch (attrs[i].type) { |
| 584 | 587 | case KFD_IOCTL_SVM_ATTR_PREFERRED_LOC: |
| 585 | − if (attrs[i].value != KFD_IOCTL_SVM_LOCATION_SYSMEM && | |
| 586 | − attrs[i].value != KFD_IOCTL_SVM_LOCATION_UNDEFINED && | |
| 587 | − kfd_process_gpuidx_from_gpuid(p, | |
| 588 | − attrs[i].value) < 0) { | |
| 589 | − pr_debug("no GPU 0x%x found\n", attrs[i].value); | |
| 590 | − return -EINVAL; | |
| 591 | − } | |
| 588 | + if (val != KFD_IOCTL_SVM_LOCATION_SYSMEM && | |
| 589 | + val != KFD_IOCTL_SVM_LOCATION_UNDEFINED) | |
| 590 | + gpuidx = kfd_process_gpuidx_from_gpuid(p, val); | |
| 592 | 591 | break; |
| 593 | 592 | case KFD_IOCTL_SVM_ATTR_PREFETCH_LOC: |
| 594 | − if (attrs[i].value != KFD_IOCTL_SVM_LOCATION_SYSMEM && | |
| 595 | − kfd_process_gpuidx_from_gpuid(p, | |
| 596 | − attrs[i].value) < 0) { | |
| 597 | − pr_debug("no GPU 0x%x found\n", attrs[i].value); | |
| 598 | − return -EINVAL; | |
| 599 | − } | |
| 593 | + if (val != KFD_IOCTL_SVM_LOCATION_SYSMEM) | |
| 594 | + gpuidx = kfd_process_gpuidx_from_gpuid(p, val); | |
| 600 | 595 | break; |
| 601 | 596 | case KFD_IOCTL_SVM_ATTR_ACCESS: |
| 602 | 597 | case KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE: |
| 603 | 598 | case KFD_IOCTL_SVM_ATTR_NO_ACCESS: |
| 604 | − gpuidx = kfd_process_gpuidx_from_gpuid(p, | |
| 605 | − attrs[i].value); | |
| 606 | − if (gpuidx < 0) { | |
| 607 | − pr_debug("no GPU 0x%x found\n", attrs[i].value); | |
| 608 | − return -EINVAL; | |
| 609 | − } | |
| 599 | + gpuidx = kfd_process_gpuidx_from_gpuid(p, val); | |
| 610 | 600 | break; |
| 611 | 601 | case KFD_IOCTL_SVM_ATTR_SET_FLAGS: |
| 612 | 602 | break; |
| @@ -618,6 +608,15 @@ svm_range_check_attr(struct kfd_process *p, · 5 unmodified lines | ||
| 618 | 608 | pr_debug("unknown attr type 0x%x\n", attrs[i].type); |
| 619 | 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 | 622 | return 0; |
| @@ -1274,7 +1273,7 @@ static int svm_range_reserve_bos(struct svm_validate_context *ctx) · 650 unmodified lines | ||
| 1274 | 1273 | adev = (struct amdgpu_device *)pdd->dev->kgd; |
| 1275 | 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 | 1277 | ctx->tv[gpuidx].num_shared = 4; |
| 1279 | 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 | 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 | 1858 | pdd = p->pdds[i]; |
| 1860 | 1859 | if (!pdd) |
| 1861 | 1860 | continue; |
| @@ -2325,6 +2324,11 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, · 463 unmodified lines | ||
| 2325 | 2324 | bool write_locked = false; |
| 2326 | 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 | 2332 | p = kfd_lookup_process_by_pasid(pasid); |
| 2329 | 2333 | if (!p) { |
| 2330 | 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 | 2476 | int svm_range_list_init(struct kfd_process *p) |
| 2473 | 2477 | { |
| 2474 | 2478 | struct svm_range_list *svms = &p->svms; |
| 2479 | + int i; | |
| 2475 | 2480 | |
| 2476 | 2481 | svms->objects = RB_ROOT_CACHED; |
| 2477 | 2482 | mutex_init(&svms->lock); |
| @@ -2482,6 +2487,10 @@ int svm_range_list_init(struct kfd_process *p) · 4 unmodified lines | ||
| 2482 | 2487 | INIT_LIST_HEAD(&svms->deferred_range_list); |
| 2483 | 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 | 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 | 2987 | svm_range_set_default_attributes(&location, &prefetch_loc, |
| 2979 | 2988 | &granularity, &flags); |
| 2980 | 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 | 2992 | else |
| 2983 | 2993 | bitmap_zero(bitmap_access, MAX_GPU_INSTANCE); |
| 2984 | 2994 | bitmap_zero(bitmap_aip, MAX_GPU_INSTANCE); |
| 2985 | 2995 | goto fill_values; |
| 2986 | 2996 | } |
| 2987 | − bitmap_fill(bitmap_access, MAX_GPU_INSTANCE); | |
| 2988 | − bitmap_fill(bitmap_aip, MAX_GPU_INSTANCE); | |
| 2997 | + bitmap_copy(bitmap_access, svms->bitmap_supported, MAX_GPU_INSTANCE); | |
| 2998 | + bitmap_copy(bitmap_aip, svms->bitmap_supported, MAX_GPU_INSTANCE); | |
| 2989 | 2999 | |
| 2990 | 3000 | while (node) { |
| 2991 | 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 | 175 | void svm_range_free_dma_mappings(struct svm_range *prange); |
| 176 | 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 | 183 | #else |
| 179 | 184 | |
| 180 | 185 | struct kfd_process; |
| @@ -201,6 +206,8 @@ static inline int svm_range_schedule_evict_svm_bo( · 20 unmodified lines | ||
| 201 | 206 | return -EINVAL; |
| 202 | 207 | } |
| 203 | 208 | |
| 209 | +#define KFD_IS_SVM_API_SUPPORTED(dev) false | |
| 210 | + | |
| 204 | 211 | #endif /* IS_ENABLED(CONFIG_HSA_AMD_SVM) */ |
| 205 | 212 | |
| 206 | 213 | #endif /* KFD_SVM_H_ */ |
| @@ -36,6 +36,7 @@ · 35 unmodified lines | ||
| 36 | 36 | #include "kfd_topology.h" |
| 37 | 37 | #include "kfd_device_queue_manager.h" |
| 38 | 38 | #include "kfd_iommu.h" |
| 39 | +#include "kfd_svm.h" | |
| 39 | 40 | #include "amdgpu_amdkfd.h" |
| 40 | 41 | #include "amdgpu_ras.h" |
| 41 | 42 | |
| @@ -1441,10 +1442,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu) · 1399 unmodified lines | ||
| 1441 | 1442 | dev->node_props.capability |= (adev->ras_enabled != 0) ? |
| 1442 | 1443 | HSA_CAP_RASEVENTNOTIFY : 0; |
| 1443 | 1444 | |
| 1444 | − /* SVM API and HMM page migration work together, device memory type | |
| 1445 | − * is initialized to not 0 when page migration register device memory. | |
| 1446 | − */ | |
| 1447 | − if (adev->kfd.dev->pgmap.type != 0) | |
| 1445 | + if (KFD_IS_SVM_API_SUPPORTED(adev->kfd.dev)) | |
| 1448 | 1446 | dev->node_props.capability |= HSA_CAP_SVMAPI_SUPPORTED; |
| 1449 | 1447 | |
| 1450 | 1448 | kfd_debug_print_topology(); |
| @@ -54,8 +54,8 @@ · 53 unmodified lines | ||
| 54 | 54 | #define HSA_CAP_ASIC_REVISION_SHIFT 22 |
| 55 | 55 | #define HSA_CAP_SRAM_EDCSUPPORTED 0x04000000 |
| 56 | 56 | #define HSA_CAP_SVMAPI_SUPPORTED 0x08000000 |
| 57 | − | |
| 58 | −#define HSA_CAP_RESERVED 0xf00f8000 | |
| 57 | +#define HSA_CAP_FLAGS_COHERENTHOSTACCESS 0x10000000 | |
| 58 | +#define HSA_CAP_RESERVED 0xe00f8000 | |
| 59 | 59 | |
| 60 | 60 | struct kfd_node_properties { |
| 61 | 61 | uint64_t hive_id; |
| @@ -101,8 +101,7 @@ struct kfd_node_properties { · 39 unmodified lines | ||
| 101 | 101 | |
| 102 | 102 | #define HSA_MEM_FLAGS_HOT_PLUGGABLE 0x00000001 |
| 103 | 103 | #define HSA_MEM_FLAGS_NON_VOLATILE 0x00000002 |
| 104 | −#define HSA_MEM_FLAGS_COHERENTHOSTACCESS 0x00000004 | |
| 105 | −#define HSA_MEM_FLAGS_RESERVED 0xfffffff8 | |
| 104 | +#define HSA_MEM_FLAGS_RESERVED 0xfffffffc | |
| 106 | 105 | |
| 107 | 106 | struct kfd_mem_properties { |
| 108 | 107 | struct list_head list; |
| @@ -28,7 +28,7 @@ · 27 unmodified lines | ||
| 28 | 28 | AMDGPUDM = amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o amdgpu_dm_color.o |
| 29 | 29 | |
| 30 | 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 | 32 | endif |
| 33 | 33 | |
| 34 | 34 | ifdef CONFIG_DRM_AMD_DC_HDCP |
| @@ -58,6 +58,7 @@ · 57 unmodified lines | ||
| 58 | 58 | #if defined(CONFIG_DEBUG_FS) |
| 59 | 59 | #include "amdgpu_dm_debugfs.h" |
| 60 | 60 | #endif |
| 61 | +#include "amdgpu_dm_psr.h" | |
| 61 | 62 | |
| 62 | 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 | 214 | static void handle_cursor_update(struct drm_plane *plane, |
| 214 | 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 | 217 | static const struct drm_format_info * |
| 223 | 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 | 10240 | dm_old_crtc_state->dsc_force_changed == false) |
| 10246 | 10241 | continue; |
| 10247 | 10242 | |
| 10243 | + ret = amdgpu_dm_verify_lut_sizes(new_crtc_state); | |
| 10244 | + if (ret) | |
| 10245 | + goto fail; | |
| 10246 | + | |
| 10248 | 10247 | if (!new_crtc_state->enable) |
| 10249 | 10248 | continue; |
| 10250 | 10249 | |
| @@ -10725,136 +10724,6 @@ update: · 474 unmodified lines | ||
| 10725 | 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 | 10727 | void amdgpu_dm_trigger_timing_sync(struct drm_device *dev) |
| 10859 | 10728 | { |
| 10860 | 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 | 617 | #define MAX_COLOR_LEGACY_LUT_ENTRIES 256 |
| 618 | 618 | |
| 619 | 619 | void amdgpu_dm_init_color_mod(void); |
| 620 | +int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state); | |
| 620 | 621 | int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc); |
| 621 | 622 | int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, |
| 622 | 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 | 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 | 319 | * amdgpu_dm_update_crtc_color_mgmt: Maps DRM color management to DC stream. |
| 289 | 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 | 348 | bool is_legacy; |
| 318 | 349 | int r; |
| 319 | 350 | |
| 320 | − degamma_lut = __extract_blob_lut(crtc->base.degamma_lut, °amma_size); | |
| 321 | − if (degamma_lut && degamma_size != MAX_COLOR_LUT_ENTRIES) | |
| 322 | − return -EINVAL; | |
| 351 | + r = amdgpu_dm_verify_lut_sizes(&crtc->base); | |
| 352 | + if (r) | |
| 353 | + return r; | |
| 323 | 354 | |
| 355 | + degamma_lut = __extract_blob_lut(crtc->base.degamma_lut, °amma_size); | |
| 324 | 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 | 358 | has_degamma = |
| 330 | 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 | 61 | DISPLAY_CORE = dc.o dc_stat.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_sink.o \ |
| 62 | 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 | 65 | ifdef CONFIG_DRM_AMD_DC_DCN |
| 66 | 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 | 128 | int dpp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR |
| 129 | 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 | 133 | uint32_t dppclk_wdivider = dentist_get_did_from_divider(dpp_divider); |
| 134 | 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 | 198 | REG_UPDATE(DENTIST_DISPCLK_CNTL, |
| 137 | 199 | DENTIST_DISPCLK_WDIVIDER, dispclk_wdivider); |
| @@ -251,11 +313,11 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base, · 113 unmodified lines | ||
| 251 | 313 | if (dpp_clock_lowered) { |
| 252 | 314 | // if clock is being lowered, increase DTO before lowering refclk |
| 253 | 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 | 317 | } else { |
| 256 | 318 | // if clock is being raised, increase refclk before lowering DTO |
| 257 | 319 | if (update_dppclk || update_dispclk) |
| 258 | − dcn20_update_clocks_update_dentist(clk_mgr); | |
| 320 | + dcn20_update_clocks_update_dentist(clk_mgr, context); | |
| 259 | 321 | // always update dtos unless clock is lowered and not safe to lower |
| 260 | 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 | 50 | enum dc_clock_type clock_type, |
| 51 | 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 | 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 | 334 | if (dpp_clock_lowered) { |
| 335 | 335 | /* if clock is being lowered, increase DTO before lowering refclk */ |
| 336 | 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 | 338 | } else { |
| 339 | 339 | /* if clock is being raised, increase refclk before lowering DTO */ |
| 340 | 340 | if (update_dppclk || update_dispclk) |
| 341 | − dcn20_update_clocks_update_dentist(clk_mgr); | |
| 341 | + dcn20_update_clocks_update_dentist(clk_mgr, context); | |
| 342 | 342 | /* There is a check inside dcn20_update_clocks_update_dpp_dto which ensures |
| 343 | 343 | * that we do not lower dto when it is not safe to lower. We do not need to |
| 344 | 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 | 409 | struct tg_color *color) |
| 410 | 410 | { |
| 411 | 411 | uint32_t color_value = MAX_TG_COLOR_VALUE; |
| 412 | − /* Determine the overscan color based on the top-most (desktop) plane's context */ | |
| 413 | − struct pipe_ctx *top_pipe_ctx = pipe_ctx; | |
| 412 | + /* Determine the overscan color based on the bottom-most plane's context */ | |
| 413 | + struct pipe_ctx *bottom_pipe_ctx = pipe_ctx; | |
| 414 | 414 | |
| 415 | − while (top_pipe_ctx->top_pipe != NULL) | |
| 416 | − top_pipe_ctx = top_pipe_ctx->top_pipe; | |
| 415 | + while (bottom_pipe_ctx->bottom_pipe != NULL) | |
| 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 | 419 | case DC_SW_LINEAR: |
| 420 | 420 | /* LINEAR Surface - set border color to red */ |
| 421 | 421 | color->color_r_cr = color_value; |
| @@ -49,6 +49,7 @@ · 48 unmodified lines | ||
| 49 | 49 | #include "dmub/dmub_srv.h" |
| 50 | 50 | #include "inc/hw/panel_cntl.h" |
| 51 | 51 | #include "inc/link_enc_cfg.h" |
| 52 | +#include "inc/link_dpcd.h" | |
| 52 | 53 | |
| 53 | 54 | #define DC_LOGGER_INIT(logger) |
| 54 | 55 | |
| @@ -59,20 +60,6 @@ · 4 unmodified lines | ||
| 59 | 60 | #define RETIMER_REDRIVER_INFO(...) \ |
| 60 | 61 | DC_LOG_RETIMER_REDRIVER( \ |
| 61 | 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 | 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 | 706 | static bool detect_dp(struct dc_link *link, |
| 720 | 707 | struct display_sink_capability *sink_caps, |
| 721 | − bool *converter_disable_audio, | |
| 722 | − struct audio_support *audio_support, | |
| 723 | 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 | 712 | sink_caps->signal = link_detect_sink(link, reason); |
| 728 | 713 | sink_caps->transaction_type = |
| @@ -745,60 +730,12 @@ static bool detect_dp(struct dc_link *link, · 16 unmodified lines | ||
| 745 | 730 | * of this function). */ |
| 746 | 731 | query_hdcp_capability(SIGNAL_TYPE_DISPLAY_PORT_MST, link); |
| 747 | 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 | 735 | if (link->type != dc_connection_mst_branch && |
| 786 | − is_dp_branch_device(link)) { | |
| 736 | + is_dp_branch_device(link)) | |
| 787 | 737 | /* DP SST branch */ |
| 788 | 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 | 739 | } else { |
| 803 | 740 | /* DP passive dongles */ |
| 804 | 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 | 830 | struct dc_sink *sink = NULL; |
| 894 | 831 | struct dc_sink *prev_sink = NULL; |
| 895 | 832 | struct dpcd_caps prev_dpcd_caps; |
| 896 | − bool same_dpcd = true; | |
| 897 | 833 | enum dc_connection_type new_connection_type = dc_connection_none; |
| 898 | 834 | enum dc_connection_type pre_connection_type = dc_connection_none; |
| 899 | 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 | 840 | if (dc_is_virtual_signal(link->connector_signal)) |
| 905 | 841 | return false; |
| 906 | 842 | |
| 907 | − if ((link->connector_signal == SIGNAL_TYPE_LVDS || | |
| 908 | − link->connector_signal == SIGNAL_TYPE_EDP) && | |
| 909 | − link->local_sink) { | |
| 843 | + if (((link->connector_signal == SIGNAL_TYPE_LVDS || | |
| 844 | + link->connector_signal == SIGNAL_TYPE_EDP) && | |
| 845 | + (!link->dc->config.allow_edp_hotplug_detection)) && | |
| 846 | + link->local_sink) { | |
| 910 | 847 | // need to re-write OUI and brightness in resume case |
| 911 | 848 | if (link->connector_signal == SIGNAL_TYPE_EDP) { |
| 912 | 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 | 920 | return false; |
| 984 | 921 | } |
| 985 | 922 | |
| 986 | − if (!detect_dp(link, &sink_caps, | |
| 987 | − &converter_disable_audio, | |
| 988 | − aud_support, reason)) { | |
| 923 | + if (!detect_dp(link, &sink_caps, reason)) { | |
| 989 | 924 | if (prev_sink) |
| 990 | 925 | dc_sink_release(prev_sink); |
| 991 | 926 | return false; |
| 992 | 927 | } |
| 993 | 928 | |
| 994 | − // Check if dpcp block is the same | |
| 995 | − if (prev_sink) { | |
| 996 | − if (memcmp(&link->dpcd_caps, &prev_dpcd_caps, | |
| 997 | − sizeof(struct dpcd_caps))) | |
| 998 | − same_dpcd = false; | |
| 929 | + if (link->type == dc_connection_mst_branch) { | |
| 930 | + LINK_INFO("link=%d, mst branch is now Connected\n", | |
| 931 | + link->link_index); | |
| 932 | + /* Need to setup mst link_cap struct here | |
| 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 | 976 | /* Active SST downstream branch device unplug*/ |
| 1001 | 977 | if (link->type == dc_connection_sst_branch && |
| 1002 | 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 | 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 | 992 | // link switch from MST to non-MST stop topology manager |
| 1010 | 993 | if (pre_connection_type == dc_connection_mst_branch && |
| 1011 | − link->type != dc_connection_mst_branch) { | |
| 994 | + link->type != dc_connection_mst_branch) | |
| 1012 | 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 | 998 | // For seamless boot, to skip verify link cap, we read UEFI settings and set them as verified. |
| 1031 | 999 | if (reason == DETECT_REASON_BOOT && |
| 1032 | − !dc_ctx->dc->config.power_down_display_on_boot && | |
| 1033 | − link->link_status.link_active) | |
| 1000 | + !dc_ctx->dc->config.power_down_display_on_boot && | |
| 1001 | + link->link_status.link_active) | |
| 1034 | 1002 | perform_dp_seamless_boot = true; |
| 1035 | 1003 | |
| 1036 | 1004 | if (perform_dp_seamless_boot) { |
| @@ -1213,11 +1181,11 @@ static bool dc_link_detect_helper(struct dc_link *link, · 176 unmodified lines | ||
| 1213 | 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 | 1185 | link->link_index, sink, |
| 1218 | 1186 | (sink_caps.signal == |
| 1219 | 1187 | SIGNAL_TYPE_NONE ? "Disconnected" : "Connected"), |
| 1220 | − prev_sink, same_dpcd, same_edid); | |
| 1188 | + prev_sink, same_edid); | |
| 1221 | 1189 | |
| 1222 | 1190 | if (prev_sink) |
| 1223 | 1191 | dc_sink_release(prev_sink); |
| @@ -1501,7 +1469,8 @@ static bool dc_link_construct(struct dc_link *link, · 277 unmodified lines | ||
| 1501 | 1469 | link->connector_signal = SIGNAL_TYPE_EDP; |
| 1502 | 1470 | |
| 1503 | 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 | 1474 | link->irq_source_hpd_rx = |
| 1506 | 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 | 25 | link->ctx->logger |
| 26 | 26 | #define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */ |
| 27 | 27 | |
| 28 | +#include "link_dpcd.h" | |
| 29 | + | |
| 28 | 30 | /* maximum pre emphasis level allowed for each voltage swing level*/ |
| 29 | 31 | static const enum dc_pre_emphasis |
| 30 | 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 | 1621 | enum dc_status status = DC_OK; |
| 1620 | 1622 | |
| 1621 | − if (lt_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) | |
| 1622 | − status = configure_lttpr_mode_transparent(link); | |
| 1623 | − | |
| 1624 | − else if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) | |
| 1623 | + if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) | |
| 1625 | 1624 | status = configure_lttpr_mode_non_transparent(link, lt_settings); |
| 1625 | + else | |
| 1626 | + status = configure_lttpr_mode_transparent(link); | |
| 1626 | 1627 | |
| 1627 | 1628 | return status; |
| 1628 | 1629 | } |
| @@ -1806,7 +1807,7 @@ bool perform_link_training_with_retries( · 177 unmodified lines | ||
| 1806 | 1807 | enum dp_panel_mode panel_mode; |
| 1807 | 1808 | struct link_encoder *link_enc; |
| 1808 | 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 | 1812 | /* Dynamically assigned link encoders associated with stream rather than |
| 1812 | 1813 | * link. |
| @@ -1832,7 +1833,7 @@ bool perform_link_training_with_retries( · 19 unmodified lines | ||
| 1832 | 1833 | link, |
| 1833 | 1834 | signal, |
| 1834 | 1835 | pipe_ctx->clock_source->id, |
| 1835 | − &currnet_setting); | |
| 1836 | + ¤t_setting); | |
| 1836 | 1837 | |
| 1837 | 1838 | if (stream->sink_patches.dppowerup_delay > 0) { |
| 1838 | 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 | 1848 | panel_mode != DP_PANEL_MODE_DEFAULT); |
| 1848 | 1849 | |
| 1849 | 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 | 1852 | return true; |
| 1852 | 1853 | } else { |
| 1853 | 1854 | status = dc_link_dp_perform_link_training( |
| 1854 | 1855 | link, |
| 1855 | − &currnet_setting, | |
| 1856 | + ¤t_setting, | |
| 1856 | 1857 | skip_video_pattern); |
| 1857 | 1858 | if (status == LINK_TRAINING_SUCCESS) |
| 1858 | 1859 | return true; |
| @@ -1872,12 +1873,12 @@ bool perform_link_training_with_retries( · 13 unmodified lines | ||
| 1872 | 1873 | if (status == LINK_TRAINING_ABORT) |
| 1873 | 1874 | break; |
| 1874 | 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 | 1877 | /* Fail link training if reduced link bandwidth no longer meets |
| 1877 | 1878 | * stream requirements. |
| 1878 | 1879 | */ |
| 1879 | 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 | 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 | 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 | 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 | 3626 | bool vbios_lttpr_enable = false; |
| 3646 | 3627 | bool vbios_lttpr_interop = false; |
| 3647 | 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 | 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 | 3633 | /* Query BIOS to determine if LTTPR functionality is forced on by system */ |
| 3696 | 3634 | if (bios->funcs->get_lttpr_caps) { |
| 3697 | 3635 | enum bp_result bp_query_result; |
| @@ -3763,21 +3701,91 @@ static bool retrieve_link_cap(struct dc_link *link) · 65 unmodified lines | ||
| 3763 | 3701 | DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; |
| 3764 | 3702 | |
| 3765 | 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 && | |
| 3767 | − link->dpcd_caps.lttpr_caps.phy_repeater_cnt < 0xff && | |
| 3704 | + is_lttpr_present = (dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 && | |
| 3768 | 3705 | link->dpcd_caps.lttpr_caps.max_lane_count > 0 && |
| 3769 | 3706 | link->dpcd_caps.lttpr_caps.max_lane_count <= 4 && |
| 3770 | 3707 | link->dpcd_caps.lttpr_caps.revision.raw >= 0x14); |
| 3771 | − if (is_lttpr_present) | |
| 3708 | + if (is_lttpr_present) { | |
| 3772 | 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 | 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 | 3786 | if (!is_lttpr_present) |
| 3778 | 3787 | dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD); |
| 3779 | 3788 | |
| 3780 | − | |
| 3781 | 3789 | { |
| 3782 | 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 | 16 | #include "resource.h" |
| 17 | 17 | #include "link_enc_cfg.h" |
| 18 | 18 | #include "clk_mgr.h" |
| 19 | +#include "inc/link_dpcd.h" | |
| 19 | 20 | |
| 20 | 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 | 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 | 51 | void dp_receiver_power_ctrl(struct dc_link *link, bool on) |
| 81 | 52 | { |
| 82 | 53 | uint8_t state; |
| @@ -445,7 +445,7 @@ bool resource_are_vblanks_synchronizable( · 444 unmodified lines | ||
| 445 | 445 | { |
| 446 | 446 | uint32_t base60_refresh_rates[] = {10, 20, 5}; |
| 447 | 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 | 449 | uint64_t frame_time_diff; |
| 450 | 450 | |
| 451 | 451 | if (stream1->ctx->dc->config.vblank_alignment_dto_params && |
| @@ -45,7 +45,7 @@ · 44 unmodified lines | ||
| 45 | 45 | /* forward declaration */ |
| 46 | 46 | struct aux_payload; |
| 47 | 47 | |
| 48 | −#define DC_VER "3.2.139" | |
| 48 | +#define DC_VER "3.2.140" | |
| 49 | 49 | |
| 50 | 50 | #define MAX_SURFACES 3 |
| 51 | 51 | #define MAX_PLANES 6 |
| @@ -303,6 +303,7 @@ struct dc_config { · 251 unmodified lines | ||
| 303 | 303 | bool multi_mon_pp_mclk_switch; |
| 304 | 304 | bool disable_dmcu; |
| 305 | 305 | bool enable_4to1MPC; |
| 306 | + bool allow_edp_hotplug_detection; | |
| 306 | 307 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 307 | 308 | bool clamp_min_dcfclk; |
| 308 | 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 | 87 | error: |
| 88 | 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 | 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 | 96 | enum dmub_status status; |
| 96 | 97 | |
| 97 | 98 | status = dmub_srv_cmd_execute(dmub); |
| 98 | − if (status != DMUB_STATUS_OK) | |
| 99 | + if (status != DMUB_STATUS_OK) { | |
| 99 | 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 | 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 | 109 | enum dmub_status status; |
| 107 | 110 | |
| 108 | 111 | status = dmub_srv_wait_for_idle(dmub, 100000); |
| 109 | − if (status != DMUB_STATUS_OK) | |
| 112 | + if (status != DMUB_STATUS_OK) { | |
| 110 | 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 | 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 | 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 | 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 | 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 | 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 | 620 | #define AUX_MAX_I2C_DEFER_RETRIES 7 |
| 620 | 621 | #define AUX_MAX_INVALID_REPLY_RETRIES 2 |
| 621 | 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 | 629 | bool payload_reply = true; |
| 629 | 630 | enum aux_return_code_type operation_result; |
| 630 | 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 | 637 | int aux_ack_retries = 0, |
| 633 | 638 | aux_defer_retries = 0, |
| @@ -660,19 +665,27 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc, · 26 unmodified lines | ||
| 660 | 665 | break; |
| 661 | 666 | |
| 662 | 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 | 672 | case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER: |
| 664 | 673 | retry_on_defer = true; |
| 665 | 674 | fallthrough; |
| 666 | 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 | 678 | goto fail; |
| 669 | 679 | } else { |
| 670 | 680 | if ((*payload->reply == AUX_TRANSACTION_REPLY_AUX_DEFER) || |
| 671 | 681 | (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)) { |
| 672 | − if (payload->defer_delay > 1) | |
| 682 | + if (payload->defer_delay > 1) { | |
| 673 | 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 | 686 | udelay(payload->defer_delay * 1000); |
| 687 | + defer_time_in_ms += payload->defer_delay; | |
| 688 | + } | |
| 676 | 689 | } |
| 677 | 690 | } |
| 678 | 691 | break; |
| @@ -701,7 +714,7 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc, · 22 unmodified lines | ||
| 701 | 714 | // Check whether a DEFER had occurred before the timeout. |
| 702 | 715 | // If so, treat timeout as a DEFER. |
| 703 | 716 | if (retry_on_defer) { |
| 704 | − if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES) | |
| 717 | + if (++aux_defer_retries >= AUX_MIN_DEFER_RETRIES) | |
| 705 | 718 | goto fail; |
| 706 | 719 | else if (payload->defer_delay > 0) |
| 707 | 720 | msleep(payload->defer_delay); |
| @@ -65,7 +65,6 @@ · 64 unmodified lines | ||
| 65 | 65 | |
| 66 | 66 | #include "atomfirmware.h" |
| 67 | 67 | |
| 68 | −#include "dce110_hw_sequencer.h" | |
| 69 | 68 | #include "dcn10/dcn10_hw_sequencer.h" |
| 70 | 69 | |
| 71 | 70 | #define GAMMA_HW_POINTS_NUM 256 |
| @@ -54,6 +54,8 @@ · 53 unmodified lines | ||
| 54 | 54 | #include "dce/dmub_hw_lock_mgr.h" |
| 55 | 55 | #include "dc_trace.h" |
| 56 | 56 | #include "dce/dmub_outbox.h" |
| 57 | +#include "inc/dc_link_dp.h" | |
| 58 | +#include "inc/link_dpcd.h" | |
| 57 | 59 | |
| 58 | 60 | #define DC_LOGGER_INIT(logger) |
| 59 | 61 | |
| @@ -1403,6 +1405,9 @@ void dcn10_init_hw(struct dc *dc) · 1343 unmodified lines | ||
| 1403 | 1405 | if (dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) |
| 1404 | 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 | 1412 | * If any of the displays are lit up turn them off. |
| 1408 | 1413 | * The reason is that some MST hubs cannot be turned off |
| @@ -52,6 +52,7 @@ · 51 unmodified lines | ||
| 52 | 52 | SRI(AFMT_60958_1, DIG, id), \ |
| 53 | 53 | SRI(AFMT_60958_2, DIG, id), \ |
| 54 | 54 | SRI(DIG_FE_CNTL, DIG, id), \ |
| 55 | + SRI(DIG_FIFO_STATUS, DIG, id), \ | |
| 55 | 56 | SRI(HDMI_CONTROL, DIG, id), \ |
| 56 | 57 | SRI(HDMI_DB_CONTROL, DIG, id), \ |
| 57 | 58 | SRI(HDMI_GC, DIG, id), \ |
| @@ -124,6 +125,7 @@ struct dcn10_stream_enc_registers { · 66 unmodified lines | ||
| 124 | 125 | uint32_t AFMT_60958_2; |
| 125 | 126 | uint32_t DIG_FE_CNTL; |
| 126 | 127 | uint32_t DIG_FE_CNTL2; |
| 128 | + uint32_t DIG_FIFO_STATUS; | |
| 127 | 129 | uint32_t DP_MSE_RATE_CNTL; |
| 128 | 130 | uint32_t DP_MSE_RATE_UPDATE; |
| 129 | 131 | uint32_t DP_PIXEL_FORMAT; |
| @@ -266,6 +268,17 @@ struct dcn10_stream_enc_registers { · 136 unmodified lines | ||
| 266 | 268 | SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ |
| 267 | 269 | SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ |
| 268 | 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 | 282 | SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, mask_sh),\ |
| 270 | 283 | SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, mask_sh),\ |
| 271 | 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 | 501 | type DP_VID_N_MUL;\ |
| 489 | 502 | type DP_VID_M_DOUBLE_VALUE_EN;\ |
| 490 | 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 | 515 | type DIG_CLOCK_PATTERN |
| 492 | 516 | |
| 493 | 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 | 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 | 566 | static const struct stream_encoder_funcs dcn20_str_enc_funcs = { |
| 556 | 567 | .dp_set_odm_combine = |
| 557 | 568 | enc2_dp_set_odm_combine, |
| @@ -598,6 +609,7 @@ static const struct stream_encoder_funcs dcn20_str_enc_funcs = { · 40 unmodified lines | ||
| 598 | 609 | .dp_set_dsc_pps_info_packet = enc2_dp_set_dsc_pps_info_packet, |
| 599 | 610 | .set_dynamic_metadata = enc2_set_dynamic_metadata, |
| 600 | 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 | 615 | void dcn20_stream_encoder_construct( |
| @@ -112,4 +112,7 @@ void enc2_set_dynamic_metadata(struct stream_encoder *enc, · 111 unmodified lines | ||
| 112 | 112 | uint32_t hubp_requestor_id, |
| 113 | 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 | 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 | 823 | .dp_set_dsc_pps_info_packet = enc3_dp_set_dsc_pps_info_packet, |
| 824 | 824 | .set_dynamic_metadata = enc2_set_dynamic_metadata, |
| 825 | 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 | 830 | void dcn30_dio_stream_encoder_construct( |
| @@ -106,6 +106,7 @@ · 105 unmodified lines | ||
| 106 | 106 | SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \ |
| 107 | 107 | SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ |
| 108 | 108 | SRI(DIG_FE_CNTL, DIG, id), \ |
| 109 | + SRI(DIG_FIFO_STATUS, DIG, id), \ | |
| 109 | 110 | SRI(DIG_CLOCK_PATTERN, DIG, id) |
| 110 | 111 | |
| 111 | 112 | |
| @@ -167,6 +168,17 @@ · 55 unmodified lines | ||
| 167 | 168 | SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ |
| 168 | 169 | SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ |
| 169 | 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 | 182 | SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\ |
| 171 | 183 | SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\ |
| 172 | 184 | SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\ |
| @@ -48,6 +48,8 @@ · 47 unmodified lines | ||
| 48 | 48 | #include "dc_dmub_srv.h" |
| 49 | 49 | #include "link_hwss.h" |
| 50 | 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 | 531 | for (i = 0; i < dc->link_count; i++) { |
| 530 | 532 | if (dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) |
| 531 | 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 | 537 | /* if any of the displays are lit up turn them off */ |
| 534 | 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 | 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 | 13 | void dcn303_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on); |
| 14 | 14 | void dcn303_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on); |
| 15 | 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 | 18 | #endif /* __DC_HWSS_DCN303_H__ */ |
| @@ -16,4 +16,5 @@ void dcn303_hw_sequencer_construct(struct dc *dc) · 15 unmodified lines | ||
| 16 | 16 | dc->hwseq->funcs.dpp_pg_control = dcn303_dpp_pg_control; |
| 17 | 17 | dc->hwseq->funcs.hubp_pg_control = dcn303_hubp_pg_control; |
| 18 | 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 | 33 | #include "clk_mgr.h" |
| 34 | 34 | #include "reg_helper.h" |
| 35 | 35 | #include "abm.h" |
| 36 | −#include "clk_mgr.h" | |
| 37 | 36 | #include "hubp.h" |
| 38 | 37 | #include "dchubbub.h" |
| 39 | 38 | #include "timing_generator.h" |
| @@ -47,6 +46,7 @@ · 7 unmodified lines | ||
| 47 | 46 | #include "dpcd_defs.h" |
| 48 | 47 | #include "dce/dmub_outbox.h" |
| 49 | 48 | #include "dc_link_dp.h" |
| 49 | +#include "inc/link_dpcd.h" | |
| 50 | 50 | |
| 51 | 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 | 934 | .dmub_command_table = true, |
| 935 | 935 | .pstate_enabled = true, |
| 936 | 936 | .use_max_lb = true, |
| 937 | − .pstate_enabled = true, | |
| 938 | 937 | .enable_mem_low_power = { |
| 939 | 938 | .bits = { |
| 940 | 939 | .vga = false, |
| @@ -3536,7 +3536,7 @@ static bool CalculateBytePerPixelAnd256BBlockSizes( · 3535 unmodified lines | ||
| 3536 | 3536 | *BytePerPixelDETC = 0; |
| 3537 | 3537 | *BytePerPixelY = 4; |
| 3538 | 3538 | *BytePerPixelC = 0; |
| 3539 | − } else if (SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_16) { | |
| 3539 | + } else if (SourcePixelFormat == dm_444_16) { | |
| 3540 | 3540 | *BytePerPixelDETY = 2; |
| 3541 | 3541 | *BytePerPixelDETC = 0; |
| 3542 | 3542 | *BytePerPixelY = 2; |
| @@ -5674,7 +5674,7 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l · 2131 unmodified lines | ||
| 5674 | 5674 | for (k = 0; k < v->NumberOfActivePlanes; k++) { |
| 5675 | 5675 | if (v->ViewportWidth[k] > v->SurfaceWidthY[k] || v->ViewportHeight[k] > v->SurfaceHeightY[k]) { |
| 5676 | 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 | 5678 | && v->SourcePixelFormat[k] != dm_444_16 && v->SourcePixelFormat[k] != dm_444_8 |
| 5679 | 5679 | && v->SourcePixelFormat[k] != dm_rgbe) { |
| 5680 | 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 | 159 | dml_get_pipe_attr_func(refcyc_per_meta_chunk_vblank_c_in_us, mode_lib->vba.TimePerChromaMetaChunkVBlank); |
| 160 | 160 | dml_get_pipe_attr_func(refcyc_per_meta_chunk_flip_l_in_us, mode_lib->vba.TimePerMetaChunkFlip); |
| 161 | 161 | dml_get_pipe_attr_func(refcyc_per_meta_chunk_flip_c_in_us, mode_lib->vba.TimePerChromaMetaChunkFlip); |
| 162 | − | |
| 163 | 162 | dml_get_pipe_attr_func(vstartup, mode_lib->vba.VStartup); |
| 164 | 163 | dml_get_pipe_attr_func(vupdate_offset, mode_lib->vba.VUpdateOffsetPix); |
| 165 | 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 | 418 | visited[j] = true; |
| 420 | 419 | |
| 421 | 420 | mode_lib->vba.pipe_plane[j] = mode_lib->vba.NumberOfActivePlanes; |
| 422 | − | |
| 423 | 421 | mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes] = 1; |
| 424 | 422 | mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] = |
| 425 | 423 | (enum scan_direction_class) (src->source_scan); |
| @@ -33,6 +33,7 @@ · 32 unmodified lines | ||
| 33 | 33 | #include "core_types.h" |
| 34 | 34 | #include "dc_link_ddc.h" |
| 35 | 35 | #include "link_hwss.h" |
| 36 | +#include "inc/link_dpcd.h" | |
| 36 | 37 | |
| 37 | 38 | #define DC_LOGGER \ |
| 38 | 39 | link->ctx->logger |
| @@ -42,7 +42,15 @@ enum { · 41 unmodified lines | ||
| 42 | 42 | /* to avoid infinite loop where-in the receiver |
| 43 | 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 | 56 | bool dp_verify_link_cap( |
| @@ -182,4 +190,5 @@ enum dc_status dpcd_configure_lttpr_mode( · 133 unmodified lines | ||
| 182 | 190 | struct link_training_settings *lt_settings); |
| 183 | 191 | |
| 184 | 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 | 194 | #endif /* __DC_LINK_DP_H__ */ |
| @@ -237,6 +237,9 @@ struct stream_encoder_funcs { · 236 unmodified lines | ||
| 237 | 237 | void (*dp_set_odm_combine)( |
| 238 | 238 | struct stream_encoder *enc, |
| 239 | 239 | bool odm_combine); |
| 240 | + | |
| 241 | + uint32_t (*get_fifo_cal_average_level)( | |
| 242 | + struct stream_encoder *enc); | |
| 240 | 243 | }; |
| 241 | 244 | |
| 242 | 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 | 26 | #ifndef __DC_LINK_HWSS_H__ |
| 27 | 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 | 29 | struct gpio *get_hpd_gpio(struct dc_bios *dcb, |
| 44 | 30 | struct graphics_object_id link_id, |
| 45 | 31 | struct gpio_service *gpio_service); |
| @@ -243,6 +243,31 @@ struct dmub_srv_hw_params { · 242 unmodified lines | ||
| 243 | 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 | 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 | 361 | void (*send_inbox0_cmd)(struct dmub_srv *dmub, union dmub_inbox0_data_register data); |
| 337 | 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 | 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 | 717 | #if defined(__cplusplus) |
| 689 | 718 | } |
| 690 | 719 | #endif |
| @@ -47,10 +47,10 @@ · 46 unmodified lines | ||
| 47 | 47 | |
| 48 | 48 | /* Firmware versioning. */ |
| 49 | 49 | #ifdef DMUB_EXPOSE_VERSION |
| 50 | −#define DMUB_FW_VERSION_GIT_HASH 0xefd666c1 | |
| 50 | +#define DMUB_FW_VERSION_GIT_HASH 0x5cac099d3 | |
| 51 | 51 | #define DMUB_FW_VERSION_MAJOR 0 |
| 52 | 52 | #define DMUB_FW_VERSION_MINOR 0 |
| 53 | −#define DMUB_FW_VERSION_REVISION 69 | |
| 53 | +#define DMUB_FW_VERSION_REVISION 70 | |
| 54 | 54 | #define DMUB_FW_VERSION_TEST 0 |
| 55 | 55 | #define DMUB_FW_VERSION_VBIOS 0 |
| 56 | 56 | #define DMUB_FW_VERSION_HOTFIX 0 |
| @@ -40,7 +40,10 @@ · 39 unmodified lines | ||
| 40 | 40 | |
| 41 | 41 | const struct dmub_srv_common_regs dmub_srv_dcn20_regs = { |
| 42 | 42 | #define DMUB_SR(reg) REG_OFFSET(reg), |
| 43 | − { DMUB_COMMON_REGS() }, | |
| 43 | + { | |
| 44 | + DMUB_COMMON_REGS() | |
| 45 | + DMCUB_INTERNAL_REGS() | |
| 46 | + }, | |
| 44 | 47 | #undef DMUB_SR |
| 45 | 48 | |
| 46 | 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 | 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 | 36 | DMUB_SR(DMCUB_CNTL) \ |
| 37 | 37 | DMUB_SR(DMCUB_MEM_CNTL) \ |
| 38 | 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 | 42 | DMUB_SR(DMCUB_INBOX1_BASE_ADDRESS) \ |
| 40 | 43 | DMUB_SR(DMCUB_INBOX1_SIZE) \ |
| 41 | 44 | DMUB_SR(DMCUB_INBOX1_RPTR) \ |
| @@ -108,7 +111,12 @@ struct dmub_srv; · 66 unmodified lines | ||
| 108 | 111 | DMUB_SR(DCN_VM_FB_LOCATION_BASE) \ |
| 109 | 112 | DMUB_SR(DCN_VM_FB_OFFSET) \ |
| 110 | 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 | 121 | #define DMUB_COMMON_FIELDS() \ |
| 114 | 122 | DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \ |
| @@ -118,6 +126,7 @@ struct dmub_srv; · 3 unmodified lines | ||
| 118 | 126 | DMUB_SF(DMCUB_MEM_CNTL, DMCUB_MEM_WRITE_SPACE) \ |
| 119 | 127 | DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET) \ |
| 120 | 128 | DMUB_SF(DMCUB_SEC_CNTL, DMCUB_MEM_UNIT_ID) \ |
| 129 | + DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS) \ | |
| 121 | 130 | DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_TOP_ADDRESS) \ |
| 122 | 131 | DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE) \ |
| 123 | 132 | DMUB_SF(DMCUB_REGION3_CW1_TOP_ADDRESS, DMCUB_REGION3_CW1_TOP_ADDRESS) \ |
| @@ -147,6 +156,7 @@ struct dmub_srv; · 23 unmodified lines | ||
| 147 | 156 | struct dmub_srv_common_reg_offset { |
| 148 | 157 | #define DMUB_SR(reg) uint32_t reg; |
| 149 | 158 | DMUB_COMMON_REGS() |
| 159 | + DMCUB_INTERNAL_REGS() | |
| 150 | 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 | 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 | 249 | #endif /* _DMUB_DCN20_H_ */ |
| @@ -39,7 +39,10 @@ · 38 unmodified lines | ||
| 39 | 39 | |
| 40 | 40 | const struct dmub_srv_common_regs dmub_srv_dcn21_regs = { |
| 41 | 41 | #define DMUB_SR(reg) REG_OFFSET(reg), |
| 42 | − { DMUB_COMMON_REGS() }, | |
| 42 | + { | |
| 43 | + DMUB_COMMON_REGS() | |
| 44 | + DMCUB_INTERNAL_REGS() | |
| 45 | + }, | |
| 43 | 46 | #undef DMUB_SR |
| 44 | 47 | |
| 45 | 48 | #define DMUB_SF(reg, field) FD_MASK(reg, field), |
| @@ -40,7 +40,10 @@ · 39 unmodified lines | ||
| 40 | 40 | |
| 41 | 41 | const struct dmub_srv_common_regs dmub_srv_dcn30_regs = { |
| 42 | 42 | #define DMUB_SR(reg) REG_OFFSET(reg), |
| 43 | − { DMUB_COMMON_REGS() }, | |
| 43 | + { | |
| 44 | + DMUB_COMMON_REGS() | |
| 45 | + DMCUB_INTERNAL_REGS() | |
| 46 | + }, | |
| 44 | 47 | #undef DMUB_SR |
| 45 | 48 | |
| 46 | 49 | #define DMUB_SF(reg, field) FD_MASK(reg, field), |
| @@ -39,7 +39,10 @@ · 38 unmodified lines | ||
| 39 | 39 | |
| 40 | 40 | const struct dmub_srv_common_regs dmub_srv_dcn301_regs = { |
| 41 | 41 | #define DMUB_SR(reg) REG_OFFSET(reg), |
| 42 | − { DMUB_COMMON_REGS() }, | |
| 42 | + { | |
| 43 | + DMUB_COMMON_REGS() | |
| 44 | + DMCUB_INTERNAL_REGS() | |
| 45 | + }, | |
| 43 | 46 | #undef DMUB_SR |
| 44 | 47 | |
| 45 | 48 | #define DMUB_SF(reg, field) FD_MASK(reg, field), |
| @@ -39,7 +39,10 @@ · 38 unmodified lines | ||
| 39 | 39 | |
| 40 | 40 | const struct dmub_srv_common_regs dmub_srv_dcn302_regs = { |
| 41 | 41 | #define DMUB_SR(reg) REG_OFFSET(reg), |
| 42 | − { DMUB_COMMON_REGS() }, | |
| 42 | + { | |
| 43 | + DMUB_COMMON_REGS() | |
| 44 | + DMCUB_INTERNAL_REGS() | |
| 45 | + }, | |
| 43 | 46 | #undef DMUB_SR |
| 44 | 47 | |
| 45 | 48 | #define DMUB_SF(reg, field) FD_MASK(reg, field), |
| @@ -21,7 +21,10 @@ · 20 unmodified lines | ||
| 21 | 21 | |
| 22 | 22 | const struct dmub_srv_common_regs dmub_srv_dcn303_regs = { |
| 23 | 23 | #define DMUB_SR(reg) REG_OFFSET(reg), |
| 24 | − { DMUB_COMMON_REGS() }, | |
| 24 | + { | |
| 25 | + DMUB_COMMON_REGS() | |
| 26 | + DMCUB_INTERNAL_REGS() | |
| 27 | + }, | |
| 25 | 28 | #undef DMUB_SR |
| 26 | 29 | |
| 27 | 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 | 176 | funcs->get_outbox0_wptr = dmub_dcn20_get_outbox0_wptr; |
| 177 | 177 | funcs->set_outbox0_rptr = dmub_dcn20_set_outbox0_rptr; |
| 178 | 178 | |
| 179 | + funcs->get_diagnostic_data = dmub_dcn20_get_diagnostic_data; | |
| 180 | + | |
| 179 | 181 | if (asic == DMUB_ASIC_DCN21) { |
| 180 | 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 | 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 | 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 | |
| 91 | − {0xff, 0xbf, 0x20, 0x00, 0xff, 0x99, 0xb3, 0x40, 0xe0, 0xCCCC, 0xCCCC}, | |
| 92 | − {0xde, 0x85, 0x20, 0x00, 0xff, 0x90, 0xa8, 0x40, 0xdf, 0xCCCC, 0xCCCC}, | |
| 93 | − {0xb0, 0x50, 0x20, 0x00, 0xc0, 0x88, 0x78, 0x70, 0xa0, 0xCCCC, 0xCCCC}, | |
| 94 | − {0x82, 0x40, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xCCCC, 0xCCCC}, | |
| 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, 0xf777, 0xcccc}, | |
| 92 | + {0xde, 0x85, 0x20, 0x00, 0xe0, 0x90, 0xa8, 0x40, 0xc8, 0xf777, 0xcccc}, | |
| 93 | + {0xb0, 0x50, 0x20, 0x00, 0xc0, 0x88, 0x78, 0x70, 0xa0, 0xeeee, 0x9999}, | |
| 94 | + {0x82, 0x40, 0x20, 0x00, 0x00, 0xb8, 0xb3, 0x70, 0x70, 0xe333, 0xb333}, | |
| 95 | 95 | }; |
| 96 | 96 | |
| 97 | 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 | |
| 99 | − {0xf0, 0xd9, 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}, | |
| 102 | − {0x82, 0x4d, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xCCCC, 0xCCCC}, | |
| 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}, | |
| 100 | + {0xcd, 0xa5, 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}, | |
| 103 | 103 | }; |
| 104 | 104 | |
| 105 | 105 | static const struct abm_parameters * const abm_settings[] = { |
| @@ -29292,6 +29292,7 @@ · 29291 unmodified lines | ||
| 29292 | 29292 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL_MASK 0x000000FCL |
| 29293 | 29293 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK_MASK 0x00000100L |
| 29294 | 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 | 29296 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL_MASK 0x03C00000L |
| 29296 | 29297 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_READ_CLOCK_SRC_MASK 0x04000000L |
| 29297 | 29298 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED_MASK 0x20000000L |
| @@ -34431,6 +34432,7 @@ · 5133 unmodified lines | ||
| 34431 | 34432 | #define DIG3_DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL__SHIFT 0x2 |
| 34432 | 34433 | #define DIG3_DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK__SHIFT 0x8 |
| 34433 | 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 | 34436 | #define DIG3_DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL__SHIFT 0x16 |
| 34435 | 34437 | #define DIG3_DIG_FIFO_STATUS__DIG_FIFO_READ_CLOCK_SRC__SHIFT 0x1a |
| 34436 | 34438 | #define DIG3_DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED__SHIFT 0x1d |
| @@ -33869,6 +33869,7 @@ · 33868 unmodified lines | ||
| 33869 | 33869 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL__SHIFT 0x2 |
| 33870 | 33870 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK__SHIFT 0x8 |
| 33871 | 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 | 33873 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL__SHIFT 0x16 |
| 33873 | 33874 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_READ_CLOCK_SRC__SHIFT 0x1a |
| 33874 | 33875 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED__SHIFT 0x1d |
| @@ -33879,6 +33880,7 @@ · 4 unmodified lines | ||
| 33879 | 33880 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL_MASK 0x000000FCL |
| 33880 | 33881 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK_MASK 0x00000100L |
| 33881 | 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 | 33884 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL_MASK 0x03C00000L |
| 33883 | 33885 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_READ_CLOCK_SRC_MASK 0x04000000L |
| 33884 | 33886 | #define DIG0_DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED_MASK 0x20000000L |
| @@ -560,7 +560,7 @@ struct gpu_metrics_v1_2 { · 559 unmodified lines | ||
| 560 | 560 | uint16_t current_vclk1; |
| 561 | 561 | uint16_t current_dclk1; |
| 562 | 562 | |
| 563 | − /* Throttle status */ | |
| 563 | + /* Throttle status (ASIC dependent) */ | |
| 564 | 564 | uint32_t throttle_status; |
| 565 | 565 | |
| 566 | 566 | /* Fans */ |
| @@ -648,6 +648,9 @@ struct gpu_metrics_v1_3 { · 81 unmodified lines | ||
| 648 | 648 | uint16_t voltage_mem; |
| 649 | 649 | |
| 650 | 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 | 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 | 813 | #endif |
| @@ -35,6 +35,48 @@ · 34 unmodified lines | ||
| 35 | 35 | |
| 36 | 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 | 80 | struct smu_hw_power_state { |
| 39 | 81 | unsigned int magic; |
| 40 | 82 | }; |
| @@ -723,7 +765,10 @@ struct pptable_funcs { · 682 unmodified lines | ||
| 723 | 765 | /** |
| 724 | 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 | 774 | * @get_ppt_limit: Get the device's ppt limits. |
| @@ -932,7 +977,9 @@ struct pptable_funcs { · 202 unmodified lines | ||
| 932 | 977 | * @disable_all_features_with_exception: Disable all features with |
| 933 | 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 | 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 | 244 | int smu_v11_0_baco_enter(struct smu_context *smu); |
| 245 | 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 | 250 | int smu_v11_0_mode1_reset(struct smu_context *smu); |
| 248 | 251 | |
| 249 | 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 | 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 | 695 | if (ret) { |
| 693 | 696 | dev_err(adev->dev, "Failed to get asic power limits!\n"); |
| 694 | 697 | return ret; |
| @@ -1379,15 +1382,20 @@ static int smu_disable_dpms(struct smu_context *smu) · 684 unmodified lines | ||
| 1379 | 1382 | if (smu->uploading_custom_pp_table && |
| 1380 | 1383 | (adev->asic_type >= CHIP_NAVI10) && |
| 1381 | 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 | 1390 | * For Sienna_Cichlid, PMFW will handle the features disablement properly |
| 1386 | 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 | 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 | 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 | 1404 | if (use_baco && smu_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT)) { |
| 1397 | 1405 | ret = smu_disable_all_features_with_exception(smu, |
| 1406 | + false, | |
| 1398 | 1407 | SMU_FEATURE_BACO_BIT); |
| 1399 | 1408 | if (ret) |
| 1400 | 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 | 2241 | } else { |
| 2233 | 2242 | switch (limit_level) { |
| 2234 | 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 | 2253 | *limit = smu->current_power_limit; |
| 2236 | 2254 | break; |
| 2237 | 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 | 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 | 234 | static int arcturus_tables_init(struct smu_context *smu) |
| 215 | 235 | { |
| 216 | 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 | 257 | return -ENOMEM; |
| 238 | 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 | 261 | smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); |
| 242 | 262 | if (!smu_table->gpu_metrics_table) { |
| 243 | 263 | kfree(smu_table->metrics_table); |
| @@ -1174,7 +1194,10 @@ static int arcturus_get_fan_parameters(struct smu_context *smu) · 930 unmodified lines | ||
| 1174 | 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 | 1202 | struct smu_11_0_powerplay_table *powerplay_table = |
| 1180 | 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 | 1213 | power_limit = |
| 1191 | 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) { | |
| 1196 | − od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]); | |
| 1217 | + if (current_power_limit) | |
| 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); | |
| 1201 | − power_limit /= 100; | |
| 1232 | + *max_power_limit = power_limit; | |
| 1202 | 1233 | } |
| 1203 | − smu->max_power_limit = power_limit; | |
| 1204 | 1234 | |
| 1205 | 1235 | return 0; |
| 1206 | 1236 | } |
| @@ -2278,8 +2308,8 @@ static ssize_t arcturus_get_gpu_metrics(struct smu_context *smu, · 1071 unmodified lines | ||
| 2278 | 2308 | void **table) |
| 2279 | 2309 | { |
| 2280 | 2310 | struct smu_table_context *smu_table = &smu->smu_table; |
| 2281 | − struct gpu_metrics_v1_1 *gpu_metrics = | |
| 2282 | − (struct gpu_metrics_v1_1 *)smu_table->gpu_metrics_table; | |
| 2311 | + struct gpu_metrics_v1_3 *gpu_metrics = | |
| 2312 | + (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table; | |
| 2283 | 2313 | SmuMetrics_t metrics; |
| 2284 | 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 | 2319 | if (ret) |
| 2290 | 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 | 2324 | gpu_metrics->temperature_edge = metrics.TemperatureEdge; |
| 2295 | 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 | 2348 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; |
| 2319 | 2349 | |
| 2320 | 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 | 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 | 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 | 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 | 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 | 263 | static bool is_asic_secure(struct smu_context *smu) |
| 242 | 264 | { |
| 243 | 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 | 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 | 471 | static int navi10_setup_pptable(struct smu_context *smu) |
| 474 | 472 | { |
| 475 | 473 | int ret = 0; |
| @@ -2138,7 +2136,10 @@ static int navi10_display_disable_memory_clock_switch(struct smu_context *smu, · 1662 unmodified lines | ||
| 2138 | 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 | 2144 | struct smu_11_0_powerplay_table *powerplay_table = |
| 2144 | 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 | 2156 | power_limit = |
| 2156 | 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 && | |
| 2161 | − navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) { | |
| 2162 | − od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]); | |
| 2160 | + if (current_power_limit) | |
| 2161 | + *current_power_limit = power_limit; | |
| 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); | |
| 2167 | − power_limit /= 100; | |
| 2170 | + dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit); | |
| 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 | 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 | 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 | 2291 | static int navi10_set_default_od_settings(struct smu_context *smu) |
| 2261 | 2292 | { |
| 2262 | 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 | 2707 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; |
| 2677 | 2708 | |
| 2678 | 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 | 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 | 2787 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; |
| 2754 | 2788 | |
| 2755 | 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 | 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 | 2866 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; |
| 2830 | 2867 | |
| 2831 | 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 | 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 | 2951 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; |
| 2912 | 2952 | |
| 2913 | 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 | 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 | 3138 | .baco_is_support = smu_v11_0_baco_is_support, |
| 3096 | 3139 | .baco_get_state = smu_v11_0_baco_get_state, |
| 3097 | 3140 | .baco_set_state = smu_v11_0_baco_set_state, |
| 3098 | − .baco_enter = smu_v11_0_baco_enter, | |
| 3099 | − .baco_exit = smu_v11_0_baco_exit, | |
| 3141 | + .baco_enter = navi10_baco_enter, | |
| 3142 | + .baco_exit = navi10_baco_exit, | |
| 3100 | 3143 | .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq, |
| 3101 | 3144 | .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, |
| 3102 | 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 | 3155 | .get_fan_parameters = navi10_get_fan_parameters, |
| 3113 | 3156 | .post_init = navi10_post_smu_init, |
| 3114 | 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 | 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 | 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 | 263 | static int |
| 243 | 264 | sienna_cichlid_get_allowed_feature_mask(struct smu_context *smu, |
| 244 | 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 | 470 | goto err0_out; |
| 450 | 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 | 474 | smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); |
| 454 | 475 | if (!smu_table->gpu_metrics_table) |
| 455 | 476 | goto err1_out; |
| @@ -1770,7 +1791,10 @@ static int sienna_cichlid_display_disable_memory_clock_switch(struct smu_context · 1314 unmodified lines | ||
| 1770 | 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 | 1799 | struct smu_11_0_7_powerplay_table *powerplay_table = |
| 1776 | 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 | 1807 | power_limit = |
| 1784 | 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) { | |
| 1789 | − od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]); | |
| 1811 | + if (current_power_limit) | |
| 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); | |
| 1794 | − power_limit /= 100; | |
| 1822 | + power_limit *= (100 + od_percent); | |
| 1823 | + power_limit /= 100; | |
| 1824 | + } | |
| 1825 | + *max_power_limit = power_limit; | |
| 1795 | 1826 | } |
| 1796 | − smu->max_power_limit = power_limit; | |
| 1797 | 1827 | |
| 1798 | 1828 | return 0; |
| 1799 | 1829 | } |
| @@ -2100,6 +2130,29 @@ static int sienna_cichlid_run_btc(struct smu_context *smu) · 300 unmodified lines | ||
| 2100 | 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 | 2156 | static bool sienna_cichlid_is_mode1_reset_supported(struct smu_context *smu) |
| 2104 | 2157 | { |
| 2105 | 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 | 3673 | void **table) |
| 3621 | 3674 | { |
| 3622 | 3675 | struct smu_table_context *smu_table = &smu->smu_table; |
| 3623 | − struct gpu_metrics_v1_1 *gpu_metrics = | |
| 3624 | − (struct gpu_metrics_v1_1 *)smu_table->gpu_metrics_table; | |
| 3676 | + struct gpu_metrics_v1_3 *gpu_metrics = | |
| 3677 | + (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table; | |
| 3625 | 3678 | SmuMetricsExternal_t metrics_external; |
| 3626 | 3679 | SmuMetrics_t *metrics = |
| 3627 | 3680 | &(metrics_external.SmuMetrics); |
| @@ -3635,7 +3688,7 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, · 7 unmodified lines | ||
| 3635 | 3688 | if (ret) |
| 3636 | 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 | 3693 | gpu_metrics->temperature_edge = metrics->TemperatureEdge; |
| 3641 | 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 | 3723 | gpu_metrics->current_dclk1 = metrics->CurrClock[PPCLK_DCLK_1]; |
| 3671 | 3724 | |
| 3672 | 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 | 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 | 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 | 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 | 3931 | .baco_is_support = smu_v11_0_baco_is_support, |
| 3876 | 3932 | .baco_get_state = smu_v11_0_baco_get_state, |
| 3877 | 3933 | .baco_set_state = smu_v11_0_baco_set_state, |
| 3878 | − .baco_enter = smu_v11_0_baco_enter, | |
| 3879 | − .baco_exit = smu_v11_0_baco_exit, | |
| 3934 | + .baco_enter = sienna_cichlid_baco_enter, | |
| 3935 | + .baco_exit = sienna_cichlid_baco_exit, | |
| 3880 | 3936 | .mode1_reset_is_support = sienna_cichlid_is_mode1_reset_supported, |
| 3881 | 3937 | .mode1_reset = smu_v11_0_mode1_reset, |
| 3882 | 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 | 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 | 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 | 1580 | int smu_v11_0_baco_enter(struct smu_context *smu) |
| 1580 | 1581 | { |
| 1581 | − struct amdgpu_device *adev = smu->adev; | |
| 1582 | 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 | 1584 | ret = smu_v11_0_baco_set_state(smu, SMU_BACO_STATE_ENTER); |
| 1592 | 1585 | if (ret) |
| 1593 | 1586 | return ret; |
| @@ -190,6 +190,20 @@ static struct cmn2asic_mapping vangogh_workload_map[PP_SMC_POWER_PROFILE_COUNT] · 189 unmodified lines | ||
| 190 | 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 | 207 | static int vangogh_tables_init(struct smu_context *smu) |
| 194 | 208 | { |
| 195 | 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 | 240 | goto err0_out; |
| 227 | 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 | 244 | smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); |
| 231 | 245 | if (!smu_table->gpu_metrics_table) |
| 232 | 246 | goto err1_out; |
| @@ -1632,8 +1646,8 @@ static ssize_t vangogh_get_legacy_gpu_metrics(struct smu_context *smu, · 1399 unmodified lines | ||
| 1632 | 1646 | void **table) |
| 1633 | 1647 | { |
| 1634 | 1648 | struct smu_table_context *smu_table = &smu->smu_table; |
| 1635 | − struct gpu_metrics_v2_1 *gpu_metrics = | |
| 1636 | − (struct gpu_metrics_v2_1 *)smu_table->gpu_metrics_table; | |
| 1649 | + struct gpu_metrics_v2_2 *gpu_metrics = | |
| 1650 | + (struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table; | |
| 1637 | 1651 | SmuMetrics_legacy_t metrics; |
| 1638 | 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 | 1655 | if (ret) |
| 1642 | 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 | 1660 | gpu_metrics->temperature_gfx = metrics.GfxTemperature; |
| 1647 | 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 | 1688 | gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0]; |
| 1675 | 1689 | |
| 1676 | 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 | 1695 | gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); |
| 1679 | 1696 | |
| 1680 | 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 | 1702 | static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu, |
| 1686 | 1703 | void **table) |
| 1687 | 1704 | { |
| 1688 | 1705 | struct smu_table_context *smu_table = &smu->smu_table; |
| 1689 | − struct gpu_metrics_v2_1 *gpu_metrics = | |
| 1690 | − (struct gpu_metrics_v2_1 *)smu_table->gpu_metrics_table; | |
| 1706 | + struct gpu_metrics_v2_2 *gpu_metrics = | |
| 1707 | + (struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table; | |
| 1691 | 1708 | SmuMetrics_t metrics; |
| 1692 | 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 | 1712 | if (ret) |
| 1696 | 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 | 1717 | gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature; |
| 1701 | 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 | 1752 | gpu_metrics->current_l3clk[0] = metrics.Current.L3Frequency[0]; |
| 1736 | 1753 | |
| 1737 | 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 | 1759 | gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); |
| 1740 | 1760 | |
| 1741 | 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 | 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 | 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 | 2079 | struct smu_11_5_power_context *power_context = |
| 2057 | 2080 | smu->smu_power.power_context; |
| @@ -2067,8 +2090,12 @@ static int vangogh_get_power_limit(struct smu_context *smu) · 9 unmodified lines | ||
| 2067 | 2090 | return ret; |
| 2068 | 2091 | } |
| 2069 | 2092 | /* convert from milliwatt to watt */ |
| 2070 | − smu->current_power_limit = smu->default_power_limit = ppt_limit / 1000; | |
| 2071 | − smu->max_power_limit = 29; | |
| 2093 | + if (current_power_limit) | |
| 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 | 2100 | ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetFastPPTLimit, &ppt_limit); |
| 2074 | 2101 | if (ret) { |
| @@ -128,6 +128,22 @@ static struct cmn2asic_mapping renoir_workload_map[PP_SMC_POWER_PROFILE_COUNT] = · 127 unmodified lines | ||
| 128 | 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 | 147 | static int renoir_init_smc_tables(struct smu_context *smu) |
| 132 | 148 | { |
| 133 | 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 | 169 | if (!smu_table->watermarks_table) |
| 154 | 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 | 173 | smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); |
| 158 | 174 | if (!smu_table->gpu_metrics_table) |
| 159 | 175 | goto err3_out; |
| @@ -1164,6 +1180,28 @@ static int renoir_get_smu_metrics_data(struct smu_context *smu, · 1004 unmodified lines | ||
| 1164 | 1180 | case METRICS_VOLTAGE_VDDSOC: |
| 1165 | 1181 | *value = metrics->Voltage[1]; |
| 1166 | 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 | 1205 | default: |
| 1168 | 1206 | *value = UINT_MAX; |
| 1169 | 1207 | break; |
| @@ -1235,6 +1273,18 @@ static int renoir_read_sensor(struct smu_context *smu, · 65 unmodified lines | ||
| 1235 | 1273 | (uint32_t *)data); |
| 1236 | 1274 | *size = 4; |
| 1237 | 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 | 1288 | default: |
| 1239 | 1289 | ret = -EOPNOTSUPP; |
| 1240 | 1290 | break; |
| @@ -1264,8 +1314,8 @@ static ssize_t renoir_get_gpu_metrics(struct smu_context *smu, · 23 unmodified lines | ||
| 1264 | 1314 | void **table) |
| 1265 | 1315 | { |
| 1266 | 1316 | struct smu_table_context *smu_table = &smu->smu_table; |
| 1267 | − struct gpu_metrics_v2_1 *gpu_metrics = | |
| 1268 | − (struct gpu_metrics_v2_1 *)smu_table->gpu_metrics_table; | |
| 1317 | + struct gpu_metrics_v2_2 *gpu_metrics = | |
| 1318 | + (struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table; | |
| 1269 | 1319 | SmuMetrics_t metrics; |
| 1270 | 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 | 1323 | if (ret) |
| 1274 | 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 | 1328 | gpu_metrics->temperature_gfx = metrics.GfxTemperature; |
| 1279 | 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 | 1361 | gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1]; |
| 1312 | 1362 | |
| 1313 | 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 | 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 | 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 | 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 | 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 | 208 | static int aldebaran_tables_init(struct smu_context *smu) |
| 195 | 209 | { |
| 196 | 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 | 227 | return -ENOMEM; |
| 214 | 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 | 231 | smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); |
| 218 | 232 | if (!smu_table->gpu_metrics_table) { |
| 219 | 233 | kfree(smu_table->metrics_table); |
| @@ -510,6 +524,16 @@ static int aldebaran_freqs_in_same_level(int32_t frequency1, · 290 unmodified lines | ||
| 510 | 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 | 537 | static int aldebaran_get_smu_metrics_data(struct smu_context *smu, |
| 514 | 538 | MetricsMember_t member, |
| 515 | 539 | uint32_t *value) |
| @@ -563,7 +587,10 @@ static int aldebaran_get_smu_metrics_data(struct smu_context *smu, · 47 unmodified lines | ||
| 563 | 587 | *value = metrics->AverageUclkActivity; |
| 564 | 588 | break; |
| 565 | 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 | 594 | break; |
| 568 | 595 | case METRICS_TEMPERATURE_EDGE: |
| 569 | 596 | *value = metrics->TemperatureEdge * |
| @@ -1132,7 +1159,10 @@ static int aldebaran_read_sensor(struct smu_context *smu, · 562 unmodified lines | ||
| 1132 | 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 | 1167 | PPTable_t *pptable = smu->smu_table.driver_pptable; |
| 1138 | 1168 | uint32_t power_limit = 0; |
| @@ -1141,24 +1171,46 @@ static int aldebaran_get_power_limit(struct smu_context *smu) · 2 unmodified lines | ||
| 1141 | 1171 | if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) |
| 1142 | 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) { | |
| 1147 | − /* the last hope to figure out the ppt limit */ | |
| 1148 | − if (!pptable) { | |
| 1149 | − dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!"); | |
| 1150 | − return -EINVAL; | |
| 1181 | + if (ret) { | |
| 1182 | + /* the last hope to figure out the ppt limit */ | |
| 1183 | + if (!pptable) { | |
| 1184 | + dev_err(smu->adev->dev, | |
| 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; | |
| 1156 | − if (pptable) | |
| 1157 | − smu->max_power_limit = pptable->PptLimit; | |
| 1192 | + if (current_power_limit) | |
| 1193 | + *current_power_limit = power_limit; | |
| 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 | 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 | 1214 | static int aldebaran_system_features_control(struct smu_context *smu, bool enable) |
| 1163 | 1215 | { |
| 1164 | 1216 | int ret; |
| @@ -1706,8 +1758,8 @@ static ssize_t aldebaran_get_gpu_metrics(struct smu_context *smu, · 541 unmodified lines | ||
| 1706 | 1758 | void **table) |
| 1707 | 1759 | { |
| 1708 | 1760 | struct smu_table_context *smu_table = &smu->smu_table; |
| 1709 | − struct gpu_metrics_v1_2 *gpu_metrics = | |
| 1710 | − (struct gpu_metrics_v1_2 *)smu_table->gpu_metrics_table; | |
| 1761 | + struct gpu_metrics_v1_3 *gpu_metrics = | |
| 1762 | + (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table; | |
| 1711 | 1763 | SmuMetrics_t metrics; |
| 1712 | 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 | 1769 | if (ret) |
| 1718 | 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 | 1774 | gpu_metrics->temperature_edge = metrics.TemperatureEdge; |
| 1723 | 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 | 1782 | gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; |
| 1731 | 1783 | gpu_metrics->average_mm_activity = 0; |
| 1732 | 1784 | |
| 1733 | − gpu_metrics->average_socket_power = metrics.AverageSocketPower; | |
| 1734 | − gpu_metrics->energy_accumulator = | |
| 1785 | + /* Valid power data is available only from primary die */ | |
| 1786 | + if (aldebaran_is_primary(smu)) { | |
| 1787 | + gpu_metrics->average_socket_power = metrics.AverageSocketPower; | |
| 1788 | + gpu_metrics->energy_accumulator = | |
| 1735 | 1789 | (uint64_t)metrics.EnergyAcc64bitHigh << 32 | |
| 1736 | 1790 | metrics.EnergyAcc64bitLow; |
| 1791 | + } else { | |
| 1792 | + gpu_metrics->average_socket_power = 0; | |
| 1793 | + gpu_metrics->energy_accumulator = 0; | |
| 1794 | + } | |
| 1737 | 1795 | |
| 1738 | 1796 | gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; |
| 1739 | 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 | 1806 | gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; |
| 1749 | 1807 | |
| 1750 | 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 | 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 | 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 | 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 | 1959 | .get_enabled_mask = smu_cmn_get_enabled_mask, |
| 1899 | 1960 | .feature_is_enabled = smu_cmn_feature_is_enabled, |
| 1900 | 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 | 1963 | .init_max_sustainable_clocks = smu_v13_0_init_max_sustainable_clocks, |
| 1903 | 1964 | .enable_thermal_alert = smu_v13_0_enable_thermal_alert, |
| 1904 | 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 | 356 | case METRICS_VOLTAGE_VDDSOC: |
| 357 | 357 | *value = metrics->Voltage[1]; |
| 358 | 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 | 381 | default: |
| 360 | 382 | *value = UINT_MAX; |
| 361 | 383 | break; |
| @@ -427,6 +449,18 @@ static int yellow_carp_read_sensor(struct smu_context *smu, · 65 unmodified lines | ||
| 427 | 449 | (uint32_t *)data); |
| 428 | 450 | *size = 4; |
| 429 | 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 | 464 | default: |
| 431 | 465 | ret = -EOPNOTSUPP; |
| 432 | 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 | 414 | int smu_cmn_feature_update_enable_state(struct smu_context *smu, |
| 402 | 415 | uint64_t feature_mask, |
| 403 | 416 | bool enabled) |
| @@ -575,23 +588,52 @@ int smu_cmn_set_pp_feature_mask(struct smu_context *smu, · 171 unmodified lines | ||
| 575 | 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 | 607 | int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, |
| 608 | + bool no_hw_disablement, | |
| 579 | 609 | enum smu_feature_mask mask) |
| 580 | 610 | { |
| 611 | + struct smu_feature *feature = &smu->smu_feature; | |
| 581 | 612 | uint64_t features_to_disable = U64_MAX; |
| 582 | 613 | int skipped_feature_id; |
| 583 | 614 | |
| 584 | − skipped_feature_id = smu_cmn_to_asic_specific_index(smu, | |
| 585 | − CMN2ASIC_MAPPING_FEATURE, | |
| 586 | − mask); | |
| 587 | − if (skipped_feature_id < 0) | |
| 588 | − return -EINVAL; | |
| 615 | + if (mask != SMU_FEATURE_COUNT) { | |
| 616 | + skipped_feature_id = smu_cmn_to_asic_specific_index(smu, | |
| 617 | + CMN2ASIC_MAPPING_FEATURE, | |
| 618 | + mask); | |
| 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, | |
| 593 | − features_to_disable, | |
| 594 | − 0); | |
| 625 | + if (no_hw_disablement) { | |
| 626 | + mutex_lock(&feature->mutex); | |
| 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 | 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 | 815 | case METRICS_VERSION(2, 1): |
| 774 | 816 | structure_size = sizeof(struct gpu_metrics_v2_1); |
| 775 | 817 | break; |
| 818 | + case METRICS_VERSION(2, 2): | |
| 819 | + structure_size = sizeof(struct gpu_metrics_v2_2); | |
| 820 | + break; | |
| 776 | 821 | default: |
| 777 | 822 | return; |
| 778 | 823 | } |
| @@ -60,6 +60,10 @@ int smu_cmn_get_enabled_32_bits_mask(struct smu_context *smu, · 59 unmodified lines | ||
| 60 | 60 | uint32_t *feature_mask, |
| 61 | 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 | 67 | int smu_cmn_feature_update_enable_state(struct smu_context *smu, |
| 64 | 68 | uint64_t feature_mask, |
| 65 | 69 | bool enabled); |
| @@ -75,6 +79,7 @@ int smu_cmn_set_pp_feature_mask(struct smu_context *smu, · 9 unmodified lines | ||
| 75 | 79 | uint64_t new_mask); |
| 76 | 80 | |
| 77 | 81 | int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, |
| 82 | + bool no_hw_disablement, | |
| 78 | 83 | enum smu_feature_mask mask); |
| 79 | 84 | |
| 80 | 85 | int smu_cmn_get_smc_version(struct smu_context *smu, |
| @@ -57,7 +57,7 @@ · 56 unmodified lines | ||
| 57 | 57 | #define smu_feature_set_allowed_mask(smu) smu_ppt_funcs(set_allowed_mask, 0, smu) |
| 58 | 58 | #define smu_feature_get_enabled_mask(smu, mask, num) smu_ppt_funcs(get_enabled_mask, 0, smu, mask, num) |
| 59 | 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 | 61 | #define smu_is_dpm_running(smu) smu_ppt_funcs(is_dpm_running, 0 , smu) |
| 62 | 62 | #define smu_notify_display_change(smu) smu_ppt_funcs(notify_display_change, 0, smu) |
| 63 | 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 | 82 | #define smu_i2c_fini(smu, control) smu_ppt_funcs(i2c_fini, 0, smu, control) |
| 83 | 83 | #define smu_get_unique_id(smu) smu_ppt_funcs(get_unique_id, 0, smu) |
| 84 | 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 | 86 | #define smu_get_pp_feature_mask(smu, buf) smu_ppt_funcs(get_pp_feature_mask, 0, smu, buf) |
| 87 | 87 | #define smu_set_pp_feature_mask(smu, new_mask) smu_ppt_funcs(set_pp_feature_mask, 0, smu, new_mask) |
| 88 | 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 | 1377 | #define DP_SYMBOL_ERROR_COUNT_LANE1_PHY_REPEATER1 0xf0037 /* 1.3 */ |
| 1378 | 1378 | #define DP_SYMBOL_ERROR_COUNT_LANE2_PHY_REPEATER1 0xf0039 /* 1.3 */ |
| 1379 | 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 | 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 | 1394 | #define DP_FEC_ERROR_COUNT_PHY_REPEATER1 0xf0291 /* 1.4 */ |
| 1382 | 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 | 1401 | /* Repeater modes */ |
| 1385 | 1402 | #define DP_PHY_REPEATER_MODE_TRANSPARENT 0x55 /* 1.3 */ |
| 1386 | 1403 | #define DP_PHY_REPEATER_MODE_NON_TRANSPARENT 0xaa /* 1.3 */ |