diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_device.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 240 |
1 files changed, 206 insertions, 34 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 6068d8207d10..51bfc114584e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -38,6 +38,7 @@ #include "amdgpu_i2c.h" #include "atom.h" #include "amdgpu_atombios.h" +#include "amd_pcie.h" #ifdef CONFIG_DRM_AMDGPU_CIK #include "cik.h" #endif @@ -57,6 +58,7 @@ static const char *amdgpu_asic_name[] = { "TONGA", "FIJI", "CARRIZO", + "STONEY", "LAST", }; @@ -948,6 +950,15 @@ static bool amdgpu_check_pot_argument(int arg) */ static void amdgpu_check_arguments(struct amdgpu_device *adev) { + if (amdgpu_sched_jobs < 4) { + dev_warn(adev->dev, "sched jobs (%d) must be at least 4\n", + amdgpu_sched_jobs); + amdgpu_sched_jobs = 4; + } else if (!amdgpu_check_pot_argument(amdgpu_sched_jobs)){ + dev_warn(adev->dev, "sched jobs (%d) must be a power of 2\n", + amdgpu_sched_jobs); + amdgpu_sched_jobs = roundup_pow_of_two(amdgpu_sched_jobs); + } /* vramlimit must be a power of two */ if (!amdgpu_check_pot_argument(amdgpu_vram_limit)) { dev_warn(adev->dev, "vram limit (%d) must be a power of 2\n", @@ -1022,7 +1033,7 @@ static void amdgpu_check_arguments(struct amdgpu_device *adev) * amdgpu_switcheroo_set_state - set switcheroo state * * @pdev: pci dev pointer - * @state: vga switcheroo state + * @state: vga_switcheroo state * * Callback for the switcheroo driver. Suspends or resumes the * the asics before or after it is powered up using ACPI methods. @@ -1165,7 +1176,8 @@ static int amdgpu_early_init(struct amdgpu_device *adev) case CHIP_TONGA: case CHIP_FIJI: case CHIP_CARRIZO: - if (adev->asic_type == CHIP_CARRIZO) + case CHIP_STONEY: + if (adev->asic_type == CHIP_CARRIZO || adev->asic_type == CHIP_STONEY) adev->family = AMDGPU_FAMILY_CZ; else adev->family = AMDGPU_FAMILY_VI; @@ -1212,12 +1224,14 @@ static int amdgpu_early_init(struct amdgpu_device *adev) } else { if (adev->ip_blocks[i].funcs->early_init) { r = adev->ip_blocks[i].funcs->early_init((void *)adev); - if (r == -ENOENT) + if (r == -ENOENT) { adev->ip_block_status[i].valid = false; - else if (r) + } else if (r) { + DRM_ERROR("early_init %d failed %d\n", i, r); return r; - else + } else { adev->ip_block_status[i].valid = true; + } } else { adev->ip_block_status[i].valid = true; } @@ -1235,20 +1249,28 @@ static int amdgpu_init(struct amdgpu_device *adev) if (!adev->ip_block_status[i].valid) continue; r = adev->ip_blocks[i].funcs->sw_init((void *)adev); - if (r) + if (r) { + DRM_ERROR("sw_init %d failed %d\n", i, r); return r; + } adev->ip_block_status[i].sw = true; /* need to do gmc hw init early so we can allocate gpu mem */ if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) { r = amdgpu_vram_scratch_init(adev); - if (r) + if (r) { + DRM_ERROR("amdgpu_vram_scratch_init failed %d\n", r); return r; + } r = adev->ip_blocks[i].funcs->hw_init((void *)adev); - if (r) + if (r) { + DRM_ERROR("hw_init %d failed %d\n", i, r); return r; + } r = amdgpu_wb_init(adev); - if (r) + if (r) { + DRM_ERROR("amdgpu_wb_init failed %d\n", r); return r; + } adev->ip_block_status[i].hw = true; } } @@ -1260,8 +1282,10 @@ static int amdgpu_init(struct amdgpu_device *adev) if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) continue; r = adev->ip_blocks[i].funcs->hw_init((void *)adev); - if (r) + if (r) { + DRM_ERROR("hw_init %d failed %d\n", i, r); return r; + } adev->ip_block_status[i].hw = true; } @@ -1278,12 +1302,16 @@ static int amdgpu_late_init(struct amdgpu_device *adev) /* enable clockgating to save power */ r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, AMD_CG_STATE_GATE); - if (r) + if (r) { + DRM_ERROR("set_clockgating_state(gate) %d failed %d\n", i, r); return r; + } if (adev->ip_blocks[i].funcs->late_init) { r = adev->ip_blocks[i].funcs->late_init((void *)adev); - if (r) + if (r) { + DRM_ERROR("late_init %d failed %d\n", i, r); return r; + } } } @@ -1304,10 +1332,15 @@ static int amdgpu_fini(struct amdgpu_device *adev) /* ungate blocks before hw fini so that we can shutdown the blocks safely */ r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, AMD_CG_STATE_UNGATE); - if (r) + if (r) { + DRM_ERROR("set_clockgating_state(ungate) %d failed %d\n", i, r); return r; + } r = adev->ip_blocks[i].funcs->hw_fini((void *)adev); /* XXX handle errors */ + if (r) { + DRM_DEBUG("hw_fini %d failed %d\n", i, r); + } adev->ip_block_status[i].hw = false; } @@ -1316,6 +1349,9 @@ static int amdgpu_fini(struct amdgpu_device *adev) continue; r = adev->ip_blocks[i].funcs->sw_fini((void *)adev); /* XXX handle errors */ + if (r) { + DRM_DEBUG("sw_fini %d failed %d\n", i, r); + } adev->ip_block_status[i].sw = false; adev->ip_block_status[i].valid = false; } @@ -1333,9 +1369,15 @@ static int amdgpu_suspend(struct amdgpu_device *adev) /* ungate blocks so that suspend can properly shut them down */ r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, AMD_CG_STATE_UNGATE); + if (r) { + DRM_ERROR("set_clockgating_state(ungate) %d failed %d\n", i, r); + } /* XXX handle errors */ r = adev->ip_blocks[i].funcs->suspend(adev); /* XXX handle errors */ + if (r) { + DRM_ERROR("suspend %d failed %d\n", i, r); + } } return 0; @@ -1349,8 +1391,10 @@ static int amdgpu_resume(struct amdgpu_device *adev) if (!adev->ip_block_status[i].valid) continue; r = adev->ip_blocks[i].funcs->resume(adev); - if (r) + if (r) { + DRM_ERROR("resume %d failed %d\n", i, r); return r; + } } return 0; @@ -1418,7 +1462,6 @@ int amdgpu_device_init(struct amdgpu_device *adev, mutex_init(&adev->gfx.gpu_clock_mutex); mutex_init(&adev->srbm_mutex); mutex_init(&adev->grbm_idx_mutex); - init_rwsem(&adev->exclusive_lock); mutex_init(&adev->mn_lock); hash_init(adev->mn_hash); @@ -1483,8 +1526,10 @@ int amdgpu_device_init(struct amdgpu_device *adev, return -EINVAL; } r = amdgpu_atombios_init(adev); - if (r) + if (r) { + dev_err(adev->dev, "amdgpu_atombios_init failed\n"); return r; + } /* Post card if necessary */ if (!amdgpu_card_posted(adev)) { @@ -1498,21 +1543,26 @@ int amdgpu_device_init(struct amdgpu_device *adev, /* Initialize clocks */ r = amdgpu_atombios_get_clock_info(adev); - if (r) + if (r) { + dev_err(adev->dev, "amdgpu_atombios_get_clock_info failed\n"); return r; + } /* init i2c buses */ amdgpu_atombios_i2c_init(adev); /* Fence driver */ r = amdgpu_fence_driver_init(adev); - if (r) + if (r) { + dev_err(adev->dev, "amdgpu_fence_driver_init failed\n"); return r; + } /* init the mode config */ drm_mode_config_init(adev->ddev); r = amdgpu_init(adev); if (r) { + dev_err(adev->dev, "amdgpu_init failed\n"); amdgpu_fini(adev); return r; } @@ -1527,7 +1577,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, return r; } - r = amdgpu_ctx_init(adev, true, &adev->kernel_ctx); + r = amdgpu_ctx_init(adev, AMD_SCHED_PRIORITY_KERNEL, &adev->kernel_ctx); if (r) { dev_err(adev->dev, "failed to create kernel context (%d).\n", r); return r; @@ -1569,8 +1619,10 @@ int amdgpu_device_init(struct amdgpu_device *adev, * explicit gating rather than handling it automatically. */ r = amdgpu_late_init(adev); - if (r) + if (r) { + dev_err(adev->dev, "amdgpu_late_init failed\n"); return r; + } return 0; } @@ -1657,11 +1709,21 @@ int amdgpu_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon) } drm_modeset_unlock_all(dev); - /* unpin the front buffers */ + /* unpin the front buffers and cursors */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct amdgpu_framebuffer *rfb = to_amdgpu_framebuffer(crtc->primary->fb); struct amdgpu_bo *robj; + if (amdgpu_crtc->cursor_bo) { + struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); + r = amdgpu_bo_reserve(aobj, false); + if (r == 0) { + amdgpu_bo_unpin(aobj); + amdgpu_bo_unreserve(aobj); + } + } + if (rfb == NULL || rfb->obj == NULL) { continue; } @@ -1713,6 +1775,7 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon) { struct drm_connector *connector; struct amdgpu_device *adev = dev->dev_private; + struct drm_crtc *crtc; int r; if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) @@ -1732,20 +1795,43 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon) } /* post card */ - amdgpu_atom_asic_init(adev->mode_info.atom_context); + if (!amdgpu_card_posted(adev)) + amdgpu_atom_asic_init(adev->mode_info.atom_context); r = amdgpu_resume(adev); + if (r) + DRM_ERROR("amdgpu_resume failed (%d).\n", r); amdgpu_fence_driver_resume(adev); - r = amdgpu_ib_ring_tests(adev); - if (r) - DRM_ERROR("ib ring test failed (%d).\n", r); + if (resume) { + r = amdgpu_ib_ring_tests(adev); + if (r) + DRM_ERROR("ib ring test failed (%d).\n", r); + } r = amdgpu_late_init(adev); if (r) return r; + /* pin cursors */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + + if (amdgpu_crtc->cursor_bo) { + struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); + r = amdgpu_bo_reserve(aobj, false); + if (r == 0) { + r = amdgpu_bo_pin(aobj, + AMDGPU_GEM_DOMAIN_VRAM, + &amdgpu_crtc->cursor_addr); + if (r != 0) + DRM_ERROR("Failed to pin cursor BO (%d)\n", r); + amdgpu_bo_unreserve(aobj); + } + } + } + /* blat the mode back in */ if (fbcon) { drm_helper_resume_force_mode(dev); @@ -1758,6 +1844,7 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon) } drm_kms_helper_poll_enable(dev); + drm_helper_hpd_irq_event(dev); if (fbcon) { amdgpu_fbdev_set_suspend(adev, 0); @@ -1785,14 +1872,6 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev) int i, r; int resched; - down_write(&adev->exclusive_lock); - - if (!adev->needs_reset) { - up_write(&adev->exclusive_lock); - return 0; - } - - adev->needs_reset = false; atomic_inc(&adev->gpu_reset_counter); /* block TTM */ @@ -1856,10 +1935,103 @@ retry: dev_info(adev->dev, "GPU reset failed\n"); } - up_write(&adev->exclusive_lock); return r; } +#define AMDGPU_DEFAULT_PCIE_GEN_MASK 0x30007 /* gen: chipset 1/2, asic 1/2/3 */ +#define AMDGPU_DEFAULT_PCIE_MLW_MASK 0x2f0000 /* 1/2/4/8/16 lanes */ + +void amdgpu_get_pcie_info(struct amdgpu_device *adev) +{ + u32 mask; + int ret; + + if (amdgpu_pcie_gen_cap) + adev->pm.pcie_gen_mask = amdgpu_pcie_gen_cap; + + if (amdgpu_pcie_lane_cap) + adev->pm.pcie_mlw_mask = amdgpu_pcie_lane_cap; + + /* covers APUs as well */ + if (pci_is_root_bus(adev->pdev->bus)) { + if (adev->pm.pcie_gen_mask == 0) + adev->pm.pcie_gen_mask = AMDGPU_DEFAULT_PCIE_GEN_MASK; + if (adev->pm.pcie_mlw_mask == 0) + adev->pm.pcie_mlw_mask = AMDGPU_DEFAULT_PCIE_MLW_MASK; + return; + } + + if (adev->pm.pcie_gen_mask == 0) { + ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask); + if (!ret) { + adev->pm.pcie_gen_mask = (CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 | + CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 | + CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3); + + if (mask & DRM_PCIE_SPEED_25) + adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1; + if (mask & DRM_PCIE_SPEED_50) + adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2; + if (mask & DRM_PCIE_SPEED_80) + adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3; + } else { + adev->pm.pcie_gen_mask = AMDGPU_DEFAULT_PCIE_GEN_MASK; + } + } + if (adev->pm.pcie_mlw_mask == 0) { + ret = drm_pcie_get_max_link_width(adev->ddev, &mask); + if (!ret) { + switch (mask) { + case 32: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X32 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 16: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 12: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 8: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 4: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 2: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 1: + adev->pm.pcie_mlw_mask = CAIL_PCIE_LINK_WIDTH_SUPPORT_X1; + break; + default: + break; + } + } else { + adev->pm.pcie_mlw_mask = AMDGPU_DEFAULT_PCIE_MLW_MASK; + } + } +} /* * Debugfs |